blob: dac5a5c6d9347f1dc21a2b33c591f687dba8f48b [file] [log] [blame]
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
WebInspector.ResourceSidebarPanel = function() {
WebInspector.NavigationSidebarPanel.call(this, "resource", WebInspector.UIString("Resources"), "Images/NavigationItemStorage.svg", "1", true, false, true);
var searchElement = document.createElement("div");
searchElement.classList.add("search-bar");
this.element.appendChild(searchElement);
this._inputElement = document.createElement("input");
this._inputElement.type = "search";
this._inputElement.spellcheck = false;
this._inputElement.addEventListener("search", this._searchFieldChanged.bind(this));
this._inputElement.addEventListener("input", this._searchFieldInput.bind(this));
this._inputElement.setAttribute("results", 5);
this._inputElement.setAttribute("autosave", "inspector-search");
this._inputElement.setAttribute("placeholder", WebInspector.UIString("Search Resource Content"));
searchElement.appendChild(this._inputElement);
this.filterBar.placeholder = WebInspector.UIString("Filter Resource List");
this._waitingForInitialMainFrame = true;
this._lastSearchedPageSetting = new WebInspector.Setting("last-searched-page", null);
this._searchQuerySetting = new WebInspector.Setting("search-sidebar-query", "");
this._inputElement.value = this._searchQuerySetting.value;
this._searchKeyboardShortcut = new WebInspector.KeyboardShortcut(WebInspector.KeyboardShortcut.Modifier.CommandOrControl | WebInspector.KeyboardShortcut.Modifier.Shift, "F", this._focusSearchField.bind(this));
this._localStorageRootTreeElement = null;
this._sessionStorageRootTreeElement = null;
this._databaseRootTreeElement = null;
this._databaseHostTreeElementMap = {};
this._cookieStorageRootTreeElement = null;
this._applicationCacheRootTreeElement = null;
this._applicationCacheURLTreeElementMap = {};
WebInspector.storageManager.addEventListener(WebInspector.StorageManager.Event.CookieStorageObjectWasAdded, this._cookieStorageObjectWasAdded, this);
WebInspector.storageManager.addEventListener(WebInspector.StorageManager.Event.DOMStorageObjectWasAdded, this._domStorageObjectWasAdded, this);
WebInspector.storageManager.addEventListener(WebInspector.StorageManager.Event.DOMStorageObjectWasInspected, this._domStorageObjectWasInspected, this);
WebInspector.storageManager.addEventListener(WebInspector.StorageManager.Event.DatabaseWasAdded, this._databaseWasAdded, this);
WebInspector.storageManager.addEventListener(WebInspector.StorageManager.Event.DatabaseWasInspected, this._databaseWasInspected, this);
WebInspector.storageManager.addEventListener(WebInspector.StorageManager.Event.Cleared, this._storageCleared, this);
WebInspector.applicationCacheManager.addEventListener(WebInspector.ApplicationCacheManager.Event.FrameManifestAdded, this._frameManifestAdded, this);
WebInspector.applicationCacheManager.addEventListener(WebInspector.ApplicationCacheManager.Event.FrameManifestRemoved, this._frameManifestRemoved, this);
WebInspector.frameResourceManager.addEventListener(WebInspector.FrameResourceManager.Event.MainFrameDidChange, this._mainFrameDidChange, this);
WebInspector.frameResourceManager.addEventListener(WebInspector.FrameResourceManager.Event.FrameWasAdded, this._frameWasAdded, this);
WebInspector.domTreeManager.addEventListener(WebInspector.DOMTreeManager.Event.DOMNodeWasInspected, this._domNodeWasInspected, this);
WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.ScriptAdded, this._scriptWasAdded, this);
WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.ScriptsCleared, this._scriptsCleared, this);
this._resourcesContentTreeOutline = this.contentTreeOutline;
this._searchContentTreeOutline = this.createContentTreeOutline();
this._resourcesContentTreeOutline.onselect = this._treeElementSelected.bind(this);
this._searchContentTreeOutline.onselect = this._treeElementSelected.bind(this);
this._resourcesContentTreeOutline.includeSourceMapResourceChildren = true;
if (WebInspector.debuggableType === WebInspector.DebuggableType.JavaScript)
this._resourcesContentTreeOutline.element.classList.add(WebInspector.NavigationSidebarPanel.HideDisclosureButtonsStyleClassName);
};
WebInspector.ResourceSidebarPanel.prototype = {
constructor: WebInspector.ResourceSidebarPanel,
// Public
get contentTreeOutlineToAutoPrune()
{
return this._searchContentTreeOutline;
},
showMainFrameDOMTree: function(nodeToSelect, preventFocusChange)
{
var contentView = WebInspector.contentBrowser.contentViewForRepresentedObject(WebInspector.frameResourceManager.mainFrame);
contentView.showDOMTree(nodeToSelect, preventFocusChange);
WebInspector.contentBrowser.showContentView(contentView);
},
showMainFrameSourceCode: function()
{
var contentView = WebInspector.contentBrowser.contentViewForRepresentedObject(WebInspector.frameResourceManager.mainFrame);
contentView.showSourceCode();
WebInspector.contentBrowser.showContentView(contentView);
},
showContentFlowDOMTree: function(contentFlow, nodeToSelect, preventFocusChange)
{
var contentView = WebInspector.contentBrowser.contentViewForRepresentedObject(contentFlow);
if (nodeToSelect)
contentView.selectAndRevealDOMNode(nodeToSelect, preventFocusChange);
WebInspector.contentBrowser.showContentView(contentView);
},
showSourceCodeForFrame: function(frameIdentifier, revealAndSelectTreeElement)
{
delete this._frameIdentifierToShowSourceCodeWhenAvailable;
// We can't show anything until we have the main frame in the sidebar.
// Otherwise the path components in the navigation bar would be missing.
var frame = WebInspector.frameResourceManager.frameForIdentifier(frameIdentifier);
if (!frame || !this._mainFrameTreeElement) {
this._frameIdentifierToShowSourceCodeWhenAvailable = frameIdentifier;
return;
}
var contentView = WebInspector.contentBrowser.contentViewForRepresentedObject(frame);
console.assert(contentView);
if (!contentView)
return;
contentView.showSourceCode();
WebInspector.contentBrowser.showContentView(contentView);
if (revealAndSelectTreeElement)
this.treeElementForRepresentedObject(frame).revealAndSelect(true, true, true, true);
},
showSourceCode: function(sourceCode, positionToReveal, textRangeToSelect, forceUnformatted)
{
console.assert(!positionToReveal || positionToReveal instanceof WebInspector.SourceCodePosition, positionToReveal);
var representedObject = sourceCode;
if (representedObject instanceof WebInspector.Script) {
// A script represented by a resource should always show the resource.
representedObject = representedObject.resource || representedObject;
}
// A main resource is always represented by its parent frame.
if (representedObject instanceof WebInspector.Resource && representedObject.isMainResource())
representedObject = representedObject.parentFrame;
var cookie = positionToReveal ? {lineNumber: positionToReveal.lineNumber, columnNumber: positionToReveal.columnNumber} : {};
WebInspector.contentBrowser.showContentViewForRepresentedObject(representedObject, cookie);
},
showSourceCodeLocation: function(sourceCodeLocation)
{
this.showSourceCode(sourceCodeLocation.displaySourceCode, sourceCodeLocation.displayPosition());
},
showOriginalUnformattedSourceCodeLocation: function(sourceCodeLocation)
{
this.showSourceCode(sourceCodeLocation.sourceCode, sourceCodeLocation.position(), undefined, true);
},
showOriginalOrFormattedSourceCodeLocation: function(sourceCodeLocation)
{
this.showSourceCode(sourceCodeLocation.sourceCode, sourceCodeLocation.formattedPosition());
},
showSourceCodeTextRange: function(sourceCodeTextRange)
{
var textRangeToSelect = sourceCodeTextRange.displayTextRange;
this.showSourceCode(sourceCodeTextRange.displaySourceCode, textRangeToSelect.startPosition(), textRangeToSelect);
},
showOriginalOrFormattedSourceCodeTextRange: function(sourceCodeTextRange)
{
var textRangeToSelect = sourceCodeTextRange.formattedTextRange;
this.showSourceCode(sourceCodeTextRange.sourceCode, textRangeToSelect.startPosition(), textRangeToSelect);
},
showResource: function(resource)
{
WebInspector.contentBrowser.showContentViewForRepresentedObject(resource.isMainResource() ? resource.parentFrame : resource);
},
showResourceRequest: function(resource)
{
var contentView = WebInspector.contentBrowser.contentViewForRepresentedObject(resource.isMainResource() ? resource.parentFrame : resource);
if (contentView instanceof WebInspector.FrameContentView)
var resourceContentView = contentView.showResource();
else if (contentView instanceof WebInspector.ResourceClusterContentView)
var resourceContentView = contentView;
console.assert(resourceContentView instanceof WebInspector.ResourceClusterContentView);
if (!(resourceContentView instanceof WebInspector.ResourceClusterContentView))
return;
resourceContentView.showRequest();
WebInspector.contentBrowser.showContentView(contentView);
},
treeElementForRepresentedObject: function(representedObject)
{
// A custom implementation is needed for this since the frames are populated lazily.
// The Frame is used as the representedObject instead of the main resource in our tree.
if (representedObject instanceof WebInspector.Resource && representedObject.parentFrame && representedObject.parentFrame.mainResource === representedObject)
representedObject = representedObject.parentFrame;
function isAncestor(ancestor, resourceOrFrame)
{
// SourceMapResources are descendants of another SourceCode object.
if (resourceOrFrame instanceof WebInspector.SourceMapResource) {
if (resourceOrFrame.sourceMap.originalSourceCode === ancestor)
return true;
// Not a direct ancestor, so check the ancestors of the parent SourceCode object.
resourceOrFrame = resourceOrFrame.sourceMap.originalSourceCode;
}
var currentFrame = resourceOrFrame.parentFrame;
while (currentFrame) {
if (currentFrame === ancestor)
return true;
currentFrame = currentFrame.parentFrame;
}
return false;
}
function getParent(resourceOrFrame)
{
// SourceMapResources are descendants of another SourceCode object.
if (resourceOrFrame instanceof WebInspector.SourceMapResource)
return resourceOrFrame.sourceMap.originalSourceCode;
return resourceOrFrame.parentFrame;
}
var treeElement = this._resourcesContentTreeOutline.findTreeElement(representedObject, isAncestor, getParent);
if (treeElement)
return treeElement;
// Only special case Script objects.
if (!(representedObject instanceof WebInspector.Script)) {
console.error("Didn't find a TreeElement for a representedObject associated with the ResourceSidebarPanel.");
return null;
}
// If the Script has a URL we should have found it earlier.
if (representedObject.url) {
console.error("Didn't find a ScriptTreeElement for a Script with a URL.");
return null;
}
// Since the Script does not have a URL we consider it an 'anonymous' script. These scripts happen from calls to
// window.eval() or browser features like Auto Fill and Reader. They are not normally added to the sidebar, but since
// we have a ScriptContentView asking for the tree element we will make a ScriptTreeElement on demand and add it.
if (!this._anonymousScriptsFolderTreeElement)
this._anonymousScriptsFolderTreeElement = new WebInspector.FolderTreeElement(WebInspector.UIString("Anonymous Scripts"));
if (!this._anonymousScriptsFolderTreeElement.parent) {
var index = insertionIndexForObjectInListSortedByFunction(this._anonymousScriptsFolderTreeElement, this._resourcesContentTreeOutline.children, this._compareTreeElements);
this._resourcesContentTreeOutline.insertChild(this._anonymousScriptsFolderTreeElement, index);
}
var scriptTreeElement = new WebInspector.ScriptTreeElement(representedObject);
this._anonymousScriptsFolderTreeElement.appendChild(scriptTreeElement);
return scriptTreeElement;
},
performSearch: function(searchTerm)
{
// Before performing a new search, clear the old search.
this._searchContentTreeOutline.removeChildren();
this._inputElement.value = searchTerm;
this._searchQuerySetting.value = searchTerm;
this._lastSearchedPageSetting.value = searchTerm && WebInspector.frameResourceManager.mainFrame ? WebInspector.frameResourceManager.mainFrame.url.hash : null;
this.hideEmptyContentPlaceholder();
searchTerm = searchTerm.trim();
if (!searchTerm.length) {
this.filterBar.placeholder = WebInspector.UIString("Filter Resource List");
this.contentTreeOutline = this._resourcesContentTreeOutline;
return;
}
this.filterBar.placeholder = WebInspector.UIString("Filter Search Results");
this.contentTreeOutline = this._searchContentTreeOutline;
var updateEmptyContentPlaceholderTimeout = null;
function updateEmptyContentPlaceholderSoon()
{
if (updateEmptyContentPlaceholderTimeout)
return;
updateEmptyContentPlaceholderTimeout = setTimeout(updateEmptyContentPlaceholder.bind(this), 100);
}
function updateEmptyContentPlaceholder()
{
if (updateEmptyContentPlaceholderTimeout) {
clearTimeout(updateEmptyContentPlaceholderTimeout);
updateEmptyContentPlaceholderTimeout = null;
}
this.updateEmptyContentPlaceholder(WebInspector.UIString("No Search Results"));
}
function resourcesCallback(error, result)
{
updateEmptyContentPlaceholderSoon.call(this);
if (error)
return;
for (var i = 0; i < result.length; ++i) {
var searchResult = result[i];
if (!searchResult.url || !searchResult.frameId)
continue;
function resourceCallback(url, error, resourceMatches)
{
updateEmptyContentPlaceholderSoon.call(this);
if (error || !resourceMatches || !resourceMatches.length)
return;
var frame = WebInspector.frameResourceManager.frameForIdentifier(searchResult.frameId);
if (!frame)
return;
var resource = frame.url === url ? frame.mainResource : frame.resourceForURL(url);
if (!resource)
return;
var resourceTreeElement = this._searchTreeElementForResource(resource);
for (var i = 0; i < resourceMatches.length; ++i) {
var match = resourceMatches[i];
var lineMatch;
var searchRegex = new RegExp(searchTerm.escapeForRegExp(), "gi");
while ((searchRegex.lastIndex < match.lineContent.length) && (lineMatch = searchRegex.exec(match.lineContent))) {
var matchObject = new WebInspector.ResourceSearchMatchObject(resource, match.lineContent, searchTerm, new WebInspector.TextRange(match.lineNumber, lineMatch.index, match.lineNumber, searchRegex.lastIndex));
var matchTreeElement = new WebInspector.SearchResultTreeElement(matchObject);
resourceTreeElement.appendChild(matchTreeElement);
}
}
updateEmptyContentPlaceholder.call(this);
}
PageAgent.searchInResource(searchResult.frameId, searchResult.url, searchTerm, false, false, resourceCallback.bind(this, searchResult.url));
}
}
function domCallback(error, searchId, resultsCount)
{
updateEmptyContentPlaceholderSoon.call(this);
if (error || !resultsCount)
return;
this._domSearchIdentifier = searchId;
function domSearchResults(error, nodeIds)
{
updateEmptyContentPlaceholderSoon.call(this);
if (error)
return;
for (var i = 0; i < nodeIds.length; ++i) {
// If someone started a new search, then return early and stop showing seach results from the old query.
if (this._domSearchIdentifier !== searchId)
return;
var domNode = WebInspector.domTreeManager.nodeForId(nodeIds[i]);
if (!domNode || !domNode.ownerDocument)
continue;
// We do not display the document node when the search query is "/". We don't have anything to display in the content view for it.
if (domNode.nodeType() === Node.DOCUMENT_NODE)
continue;
// FIXME: Use this should use a frame to do resourceForURL, but DOMAgent does not provide a frameId.
var resource = WebInspector.frameResourceManager.resourceForURL(domNode.ownerDocument.documentURL);
if (!resource)
continue;
var resourceTreeElement = this._searchTreeElementForResource(resource);
var domNodeTitle = WebInspector.DOMSearchMatchObject.titleForDOMNode(domNode);
var searchRegex = new RegExp(searchTerm.escapeForRegExp(), "gi");
// Textual matches.
var lineMatch;
var didFindTextualMatch = false;
while ((searchRegex.lastIndex < domNodeTitle.length) && (lineMatch = searchRegex.exec(domNodeTitle))) {
var matchObject = new WebInspector.DOMSearchMatchObject(resource, domNode, domNodeTitle, searchTerm, new WebInspector.TextRange(0, lineMatch.index, 0, searchRegex.lastIndex));
var matchTreeElement = new WebInspector.SearchResultTreeElement(matchObject);
resourceTreeElement.appendChild(matchTreeElement);
didFindTextualMatch = true;
}
// Non-textual matches are CSS Selector or XPath matches. In such cases, display the node entirely highlighted.
if (!didFindTextualMatch) {
var matchObject = new WebInspector.DOMSearchMatchObject(resource, domNode, domNodeTitle, domNodeTitle, new WebInspector.TextRange(0, 0, 0, domNodeTitle.length));
var matchTreeElement = new WebInspector.SearchResultTreeElement(matchObject);
resourceTreeElement.appendChild(matchTreeElement);
}
updateEmptyContentPlaceholder.call(this);
}
}
DOMAgent.getSearchResults(searchId, 0, resultsCount, domSearchResults.bind(this));
}
WebInspector.domTreeManager.requestDocument();
// FIXME: Should we be searching for regexes or just plain text?
PageAgent.searchInResources(searchTerm, false, false, resourcesCallback.bind(this));
if ("_domSearchIdentifier" in this) {
DOMAgent.discardSearchResults(this._domSearchIdentifier);
delete this._domSearchIdentifier;
}
DOMAgent.performSearch(searchTerm, domCallback.bind(this));
},
// Private
_searchFieldChanged: function(event)
{
this.performSearch(event.target.value);
},
_searchFieldInput: function(event)
{
// If the search field is cleared, immediately clear the search results tree outline.
if (!event.target.value.length && this.contentTreeOutline === this._searchContentTreeOutline)
this.performSearch("");
},
_searchTreeElementForResource: function(resource)
{
// FIXME: This should take a frame ID (if one is available) - so we can differentiate between multiple resources
// with the same URL.
var resourceTreeElement = this._searchContentTreeOutline.getCachedTreeElement(resource);
if (!resourceTreeElement) {
resourceTreeElement = new WebInspector.ResourceTreeElement(resource);
resourceTreeElement.hasChildren = true;
resourceTreeElement.expand();
this._searchContentTreeOutline.appendChild(resourceTreeElement);
}
return resourceTreeElement;
},
_focusSearchField: function(keyboardShortcut, event)
{
this.show();
this._inputElement.select();
},
_mainFrameDidChange: function(event)
{
if (this._mainFrameTreeElement) {
this._mainFrameTreeElement.frame.removeEventListener(WebInspector.Frame.Event.MainResourceDidChange, this._mainFrameMainResourceDidChange, this);
this._resourcesContentTreeOutline.removeChild(this._mainFrameTreeElement);
this._mainFrameTreeElement = null;
}
var newFrame = WebInspector.frameResourceManager.mainFrame;
if (newFrame) {
newFrame.addEventListener(WebInspector.Frame.Event.MainResourceDidChange, this._mainFrameMainResourceDidChange, this);
this._mainFrameTreeElement = new WebInspector.FrameTreeElement(newFrame);
this._resourcesContentTreeOutline.insertChild(this._mainFrameTreeElement, 0);
// Select by default. Allow onselect if we aren't showing a content view.
if (!this._resourcesContentTreeOutline.selectedTreeElement)
this._mainFrameTreeElement.revealAndSelect(true, false, !!WebInspector.contentBrowser.currentContentView);
if (this._frameIdentifierToShowSourceCodeWhenAvailable)
this.showSourceCodeForFrame(this._frameIdentifierToShowSourceCodeWhenAvailable, true);
}
// We only care about the first time the main frame changes.
if (!this._waitingForInitialMainFrame)
return;
// Only if there is a main frame.
if (!newFrame)
return;
delete this._waitingForInitialMainFrame;
// Only if the last page searched is the same as the current page.
if (this._lastSearchedPageSetting.value !== newFrame.url.hash)
return;
// Search for whatever is in the input field. This was populated with the last used search term.
this.performSearch(this._inputElement.value);
},
_mainFrameMainResourceDidChange: function(event)
{
var currentContentView = WebInspector.contentBrowser.currentContentView;
var wasShowingResourceContentView = currentContentView instanceof WebInspector.ResourceContentView
|| currentContentView instanceof WebInspector.FrameContentView || currentContentView instanceof WebInspector.ScriptContentView;
// Close all resource and frame content views since the main frame has navigated and all resources are cleared.
WebInspector.contentBrowser.contentViewContainer.closeAllContentViewsOfPrototype(WebInspector.ResourceClusterContentView);
WebInspector.contentBrowser.contentViewContainer.closeAllContentViewsOfPrototype(WebInspector.FrameContentView);
WebInspector.contentBrowser.contentViewContainer.closeAllContentViewsOfPrototype(WebInspector.ScriptContentView);
function delayedWork()
{
// Show the main frame since there is no content view showing or we were showing a resource before.
// FIXME: We could try to select the same resource that was selected before in the case of a reload.
if (!WebInspector.contentBrowser.currentContentView || wasShowingResourceContentView)
this._mainFrameTreeElement.revealAndSelect(true, false);
}
// Delay this work because other listeners of this event might not have fired yet. So selecting the main frame
// before those listeners do their work might cause the content of the old page to show instead of the new page.
setTimeout(delayedWork.bind(this), 0);
},
_frameWasAdded: function(event)
{
if (!this._frameIdentifierToShowSourceCodeWhenAvailable)
return;
var frame = event.data.frame;
if (frame.id !== this._frameIdentifierToShowSourceCodeWhenAvailable)
return;
this.showSourceCodeForFrame(frame.id, true);
},
_scriptWasAdded: function(event)
{
var script = event.data.script;
// We don't add scripts without URLs here. Those scripts can quickly clutter the interface and
// are usually more transient. They will get added if/when they need to be shown in a content view.
if (!script.url)
return;
// Exclude inspector scripts.
if (script.url.indexOf("__WebInspector") === 0)
return;
// If the script URL matches a resource we can assume it is part of that resource and does not need added.
if (script.resource)
return;
var insertIntoTopLevel = false;
if (script.injected) {
if (!this._extensionScriptsFolderTreeElement)
this._extensionScriptsFolderTreeElement = new WebInspector.FolderTreeElement(WebInspector.UIString("Extension Scripts"));
var parentFolderTreeElement = this._extensionScriptsFolderTreeElement;
} else {
if (WebInspector.debuggableType === WebInspector.DebuggableType.JavaScript)
insertIntoTopLevel = true;
else {
if (!this._extraScriptsFolderTreeElement)
this._extraScriptsFolderTreeElement = new WebInspector.FolderTreeElement(WebInspector.UIString("Extra Scripts"));
var parentFolderTreeElement = this._extraScriptsFolderTreeElement;
}
}
var scriptTreeElement = new WebInspector.ScriptTreeElement(script);
if (insertIntoTopLevel) {
var index = insertionIndexForObjectInListSortedByFunction(scriptTreeElement, this._resourcesContentTreeOutline.children, this._compareTreeElements);
this._resourcesContentTreeOutline.insertChild(scriptTreeElement, index);
} else {
if (!parentFolderTreeElement.parent) {
var index = insertionIndexForObjectInListSortedByFunction(parentFolderTreeElement, this._resourcesContentTreeOutline.children, this._compareTreeElements);
this._resourcesContentTreeOutline.insertChild(parentFolderTreeElement, index);
}
parentFolderTreeElement.appendChild(scriptTreeElement);
}
},
_scriptsCleared: function(event)
{
if (this._extensionScriptsFolderTreeElement) {
if (this._extensionScriptsFolderTreeElement.parent)
this._extensionScriptsFolderTreeElement.parent.removeChild(this._extensionScriptsFolderTreeElement);
this._extensionScriptsFolderTreeElement = null;
}
if (this._extraScriptsFolderTreeElement) {
if (this._extraScriptsFolderTreeElement.parent)
this._extraScriptsFolderTreeElement.parent.removeChild(this._extraScriptsFolderTreeElement);
this._extraScriptsFolderTreeElement = null;
}
if (this._anonymousScriptsFolderTreeElement) {
if (this._anonymousScriptsFolderTreeElement.parent)
this._anonymousScriptsFolderTreeElement.parent.removeChild(this._anonymousScriptsFolderTreeElement);
this._anonymousScriptsFolderTreeElement = null;
}
},
_treeElementSelected: function(treeElement, selectedByUser)
{
if (treeElement instanceof WebInspector.FolderTreeElement || treeElement instanceof WebInspector.DatabaseHostTreeElement)
return;
if (treeElement instanceof WebInspector.ResourceTreeElement || treeElement instanceof WebInspector.ScriptTreeElement ||
treeElement instanceof WebInspector.StorageTreeElement || treeElement instanceof WebInspector.DatabaseTableTreeElement ||
treeElement instanceof WebInspector.DatabaseTreeElement || treeElement instanceof WebInspector.ApplicationCacheFrameTreeElement ||
treeElement instanceof WebInspector.ContentFlowTreeElement) {
WebInspector.contentBrowser.showContentViewForRepresentedObject(treeElement.representedObject);
return;
}
console.assert(treeElement instanceof WebInspector.SearchResultTreeElement);
if (!(treeElement instanceof WebInspector.SearchResultTreeElement))
return;
if (treeElement.representedObject instanceof WebInspector.DOMSearchMatchObject)
this.showMainFrameDOMTree(treeElement.representedObject.domNode, true);
else if (treeElement.representedObject instanceof WebInspector.ResourceSearchMatchObject)
this.showOriginalOrFormattedSourceCodeTextRange(treeElement.representedObject.sourceCodeTextRange);
},
_domNodeWasInspected: function(event)
{
this.showMainFrameDOMTree(event.data.node);
},
_domStorageObjectWasAdded: function(event)
{
var domStorage = event.data.domStorage;
var storageElement = new WebInspector.DOMStorageTreeElement(domStorage);
if (domStorage.isLocalStorage())
this._localStorageRootTreeElement = this._addStorageChild(storageElement, this._localStorageRootTreeElement, WebInspector.UIString("Local Storage"));
else
this._sessionStorageRootTreeElement = this._addStorageChild(storageElement, this._sessionStorageRootTreeElement, WebInspector.UIString("Session Storage"));
},
_domStorageObjectWasInspected: function(event)
{
var domStorage = event.data.domStorage;
var treeElement = this.treeElementForRepresentedObject(domStorage);
treeElement.revealAndSelect(true);
},
_databaseWasAdded: function(event)
{
var database = event.data.database;
console.assert(database instanceof WebInspector.DatabaseObject);
if (!this._databaseHostTreeElementMap[database.host]) {
this._databaseHostTreeElementMap[database.host] = new WebInspector.DatabaseHostTreeElement(database.host);
this._databaseRootTreeElement = this._addStorageChild(this._databaseHostTreeElementMap[database.host], this._databaseRootTreeElement, WebInspector.UIString("Databases"));
}
var databaseElement = new WebInspector.DatabaseTreeElement(database);
this._databaseHostTreeElementMap[database.host].appendChild(databaseElement);
},
_databaseWasInspected: function(event)
{
var database = event.data.database;
var treeElement = this.treeElementForRepresentedObject(database);
treeElement.revealAndSelect(true);
},
_cookieStorageObjectWasAdded: function(event)
{
console.assert(event.data.cookieStorage instanceof WebInspector.CookieStorageObject);
var cookieElement = new WebInspector.CookieStorageTreeElement(event.data.cookieStorage);
this._cookieStorageRootTreeElement = this._addStorageChild(cookieElement, this._cookieStorageRootTreeElement, WebInspector.UIString("Cookies"));
},
_frameManifestAdded: function(event)
{
var frameManifest = event.data.frameManifest;
console.assert(frameManifest instanceof WebInspector.ApplicationCacheFrame);
var manifest = frameManifest.manifest;
var manifestURL = manifest.manifestURL;
if (!this._applicationCacheURLTreeElementMap[manifestURL]) {
this._applicationCacheURLTreeElementMap[manifestURL] = new WebInspector.ApplicationCacheManifestTreeElement(manifest);
this._applicationCacheRootTreeElement = this._addStorageChild(this._applicationCacheURLTreeElementMap[manifestURL], this._applicationCacheRootTreeElement, WebInspector.UIString("Application Cache"));
}
var frameCacheElement = new WebInspector.ApplicationCacheFrameTreeElement(frameManifest);
this._applicationCacheURLTreeElementMap[manifestURL].appendChild(frameCacheElement);
},
_frameManifestRemoved: function(event)
{
// FIXME: Implement this.
},
_compareTreeElements: function(a, b)
{
// Always sort the main frame element first.
if (a instanceof WebInspector.FrameTreeElement)
return -1;
if (b instanceof WebInspector.FrameTreeElement)
return 1;
console.assert(a.mainTitle);
console.assert(b.mainTitle);
return (a.mainTitle || "").localeCompare(b.mainTitle || "");
},
_addStorageChild: function(childElement, parentElement, folderName)
{
if (!parentElement) {
childElement.flattened = true;
this._resourcesContentTreeOutline.insertChild(childElement, insertionIndexForObjectInListSortedByFunction(childElement, this._resourcesContentTreeOutline.children, this._compareTreeElements));
return childElement;
}
if (parentElement instanceof WebInspector.StorageTreeElement) {
console.assert(parentElement.flattened);
var previousOnlyChild = parentElement;
previousOnlyChild.flattened = false;
this._resourcesContentTreeOutline.removeChild(previousOnlyChild);
var folderElement = new WebInspector.FolderTreeElement(folderName, null, null);
this._resourcesContentTreeOutline.insertChild(folderElement, insertionIndexForObjectInListSortedByFunction(folderElement, this._resourcesContentTreeOutline.children, this._compareTreeElements));
folderElement.appendChild(previousOnlyChild);
folderElement.insertChild(childElement, insertionIndexForObjectInListSortedByFunction(childElement, folderElement.children, this._compareTreeElements));
return folderElement;
}
console.assert(parentElement instanceof WebInspector.FolderTreeElement);
parentElement.insertChild(childElement, insertionIndexForObjectInListSortedByFunction(childElement, parentElement.children, this._compareTreeElements));
return parentElement;
},
_storageCleared: function(event)
{
// Close all DOM and cookie storage content views since the main frame has navigated and all storages are cleared.
WebInspector.contentBrowser.contentViewContainer.closeAllContentViewsOfPrototype(WebInspector.CookieStorageContentView);
WebInspector.contentBrowser.contentViewContainer.closeAllContentViewsOfPrototype(WebInspector.DOMStorageContentView);
WebInspector.contentBrowser.contentViewContainer.closeAllContentViewsOfPrototype(WebInspector.DatabaseTableContentView);
WebInspector.contentBrowser.contentViewContainer.closeAllContentViewsOfPrototype(WebInspector.DatabaseContentView);
WebInspector.contentBrowser.contentViewContainer.closeAllContentViewsOfPrototype(WebInspector.ApplicationCacheFrameContentView);
if (this._localStorageRootTreeElement && this._localStorageRootTreeElement.parent)
this._localStorageRootTreeElement.parent.removeChild(this._localStorageRootTreeElement);
if (this._sessionStorageRootTreeElement && this._sessionStorageRootTreeElement.parent)
this._sessionStorageRootTreeElement.parent.removeChild(this._sessionStorageRootTreeElement);
if (this._databaseRootTreeElement && this._databaseRootTreeElement.parent)
this._databaseRootTreeElement.parent.removeChild(this._databaseRootTreeElement);
if (this._cookieStorageRootTreeElement && this._cookieStorageRootTreeElement.parent)
this._cookieStorageRootTreeElement.parent.removeChild(this._cookieStorageRootTreeElement);
if (this._applicationCacheRootTreeElement && this._applicationCacheRootTreeElement.parent)
this._applicationCacheRootTreeElement.parent.removeChild(this._applicationCacheRootTreeElement);
this._localStorageRootTreeElement = null;
this._sessionStorageRootTreeElement = null;
this._databaseRootTreeElement = null;
this._databaseHostTreeElementMap = {};
this._cookieStorageRootTreeElement = null;
this._applicationCacheRootTreeElement = null;
this._applicationCacheURLTreeElementMap = {};
}
};
WebInspector.ResourceSidebarPanel.prototype.__proto__ = WebInspector.NavigationSidebarPanel.prototype;