/* * 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;