diff options
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/FrameTreeElement.js')
-rw-r--r-- | Source/WebInspectorUI/UserInterface/FrameTreeElement.js | 631 |
1 files changed, 0 insertions, 631 deletions
diff --git a/Source/WebInspectorUI/UserInterface/FrameTreeElement.js b/Source/WebInspectorUI/UserInterface/FrameTreeElement.js deleted file mode 100644 index 24d69f088..000000000 --- a/Source/WebInspectorUI/UserInterface/FrameTreeElement.js +++ /dev/null @@ -1,631 +0,0 @@ -/* - * 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.FrameTreeElement = function(frame, representedObject) -{ - console.assert(frame instanceof WebInspector.Frame); - - WebInspector.ResourceTreeElement.call(this, frame.mainResource, representedObject || frame); - - this._frame = frame; - this._newChildQueue = []; - - this._updateExpandedSetting(); - - frame.addEventListener(WebInspector.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this); - frame.addEventListener(WebInspector.Frame.Event.ResourceWasAdded, this._resourceWasAdded, this); - frame.addEventListener(WebInspector.Frame.Event.ResourceWasRemoved, this._resourceWasRemoved, this); - frame.addEventListener(WebInspector.Frame.Event.ChildFrameWasAdded, this._childFrameWasAdded, this); - frame.addEventListener(WebInspector.Frame.Event.ChildFrameWasRemoved, this._childFrameWasRemoved, this); - - frame.domTree.addEventListener(WebInspector.DOMTree.Event.ContentFlowWasAdded, this._childContentFlowWasAdded, this); - frame.domTree.addEventListener(WebInspector.DOMTree.Event.ContentFlowWasRemoved, this._childContentFlowWasRemoved, this); - frame.domTree.addEventListener(WebInspector.DOMTree.Event.RootDOMNodeInvalidated, this._rootDOMNodeInvalidated, this); - - if (this._frame.isMainFrame()) { - this._downloadingPage = false; - WebInspector.notifications.addEventListener(WebInspector.Notification.PageArchiveStarted, this._pageArchiveStarted, this); - WebInspector.notifications.addEventListener(WebInspector.Notification.PageArchiveEnded, this._pageArchiveEnded, this); - } - - this._updateParentStatus(); - this.shouldRefreshChildren = true; -}; - -WebInspector.FrameTreeElement.MediumChildCountThreshold = 5; -WebInspector.FrameTreeElement.LargeChildCountThreshold = 15; -WebInspector.FrameTreeElement.NumberOfMediumCategoriesThreshold = 2; -WebInspector.FrameTreeElement.NewChildQueueUpdateInterval = 500; - -WebInspector.FrameTreeElement.prototype = { - constructor: WebInspector.FrameTreeElement, - - // Public - - get frame() - { - return this._frame; - }, - - descendantResourceTreeElementTypeDidChange: function(resourceTreeElement, oldType) - { - // Called by descendant ResourceTreeElements. - - // Add the tree element again, which will move it to the new location - // based on sorting and possible folder changes. - this._addTreeElement(resourceTreeElement); - }, - - descendantResourceTreeElementMainTitleDidChange: function(resourceTreeElement, oldMainTitle) - { - // Called by descendant ResourceTreeElements. - - // Add the tree element again, which will move it to the new location - // based on sorting and possible folder changes. - this._addTreeElement(resourceTreeElement); - }, - - // Overrides from SourceCodeTreeElement. - - updateSourceMapResources: function() - { - // Frames handle their own SourceMapResources. - - if (!this.treeOutline || !this.treeOutline.includeSourceMapResourceChildren) - return; - - if (!this._frame) - return; - - this._updateParentStatus(); - - if (this.resource && this.resource.sourceMaps.length) - this.shouldRefreshChildren = true; - }, - - onattach: function() - { - // Frames handle their own SourceMapResources. - - WebInspector.GeneralTreeElement.prototype.onattach.call(this); - }, - - // Called from ResourceTreeElement. - - updateStatusForMainFrame: function() - { - function loadedImages() - { - if (!this._reloadButton || !this._downloadButton) - return; - - var fragment = document.createDocumentFragment("div"); - fragment.appendChild(this._downloadButton.element); - fragment.appendChild(this._reloadButton.element); - this.status = fragment; - - delete this._loadingMainFrameButtons; - } - - if (this._reloadButton && this._downloadButton) { - loadedImages.call(this); - return; - } - - if (!this._loadingMainFrameButtons) { - this._loadingMainFrameButtons = true; - - var tooltip = WebInspector.UIString("Reload page (%s)\nReload ignoring cache (%s)").format(WebInspector._reloadPageKeyboardShortcut.displayName, WebInspector._reloadPageIgnoringCacheKeyboardShortcut.displayName); - wrappedSVGDocument("Images/Reload.svg", null, tooltip, function(element) { - this._reloadButton = new WebInspector.TreeElementStatusButton(element); - this._reloadButton.addEventListener(WebInspector.TreeElementStatusButton.Event.Clicked, this._reloadPageClicked, this); - loadedImages.call(this); - }.bind(this)); - - wrappedSVGDocument("Images/DownloadArrow.svg", null, WebInspector.UIString("Download Web Archive"), function(element) { - this._downloadButton = new WebInspector.TreeElementStatusButton(element); - this._downloadButton.addEventListener(WebInspector.TreeElementStatusButton.Event.Clicked, this._downloadButtonClicked, this); - this._updateDownloadButton(); - loadedImages.call(this); - }.bind(this)); - } - }, - - // Overrides from TreeElement (Private). - - onpopulate: function() - { - if (this.children.length && !this.shouldRefreshChildren) - return; - - this.shouldRefreshChildren = false; - - this.removeChildren(); - this._clearNewChildQueue(); - - if (this._shouldGroupIntoFolders() && !this._groupedIntoFolders) - this._groupedIntoFolders = true; - - for (var i = 0; i < this._frame.childFrames.length; ++i) - this._addTreeElementForRepresentedObject(this._frame.childFrames[i]); - - for (var i = 0; i < this._frame.resources.length; ++i) - this._addTreeElementForRepresentedObject(this._frame.resources[i]); - - var sourceMaps = this.resource && this.resource.sourceMaps; - for (var i = 0; i < sourceMaps.length; ++i) { - var sourceMap = sourceMaps[i]; - for (var j = 0; j < sourceMap.resources.length; ++j) - this._addTreeElementForRepresentedObject(sourceMap.resources[j]); - } - - var flowMap = this._frame.domTree.flowMap; - for (var flowKey in flowMap) - this._addTreeElementForRepresentedObject(flowMap[flowKey]); - }, - - onexpand: function() - { - this._expandedSetting.value = true; - this._frame.domTree.requestContentFlowList(); - }, - - oncollapse: function() - { - // Only store the setting if we have children, since setting hasChildren to false will cause a collapse, - // and we only care about user triggered collapses. - if (this.hasChildren) - this._expandedSetting.value = false; - }, - - removeChildren: function() - { - TreeElement.prototype.removeChildren.call(this); - - if (this._framesFolderTreeElement) - this._framesFolderTreeElement.removeChildren(); - - for (var type in this._resourceFoldersTypeMap) - this._resourceFoldersTypeMap[type].removeChildren(); - - delete this._resourceFoldersTypeMap; - delete this._framesFolderTreeElement; - }, - - // Private - - _updateExpandedSetting: function() - { - this._expandedSetting = new WebInspector.Setting("frame-expanded-" + this._frame.url.hash, this._frame.isMainFrame() ? true : false); - if (this._expandedSetting.value) - this.expand(); - else - this.collapse(); - }, - - _updateParentStatus: function() - { - this.hasChildren = (this._frame.resources.length || this._frame.childFrames.length || (this.resource && this.resource.sourceMaps.length)); - if (!this.hasChildren) - this.removeChildren(); - }, - - _mainResourceDidChange: function(event) - { - this._updateResource(this._frame.mainResource); - this._updateParentStatus(); - - this._groupedIntoFolders = false; - - this._clearNewChildQueue(); - - this.removeChildren(); - - // Change the expanded setting since the frame URL has changed. Do this before setting shouldRefreshChildren, since - // shouldRefreshChildren will call onpopulate if expanded is true. - this._updateExpandedSetting(); - - if (this._frame.isMainFrame()) - this._updateDownloadButton(); - - this.shouldRefreshChildren = true; - }, - - _resourceWasAdded: function(event) - { - this._addRepresentedObjectToNewChildQueue(event.data.resource); - }, - - _resourceWasRemoved: function(event) - { - this._removeChildForRepresentedObject(event.data.resource); - }, - - _childFrameWasAdded: function(event) - { - this._addRepresentedObjectToNewChildQueue(event.data.childFrame); - }, - - _childFrameWasRemoved: function(event) - { - this._removeChildForRepresentedObject(event.data.childFrame); - }, - - _childContentFlowWasAdded: function(event) - { - this._addRepresentedObjectToNewChildQueue(event.data.flow); - }, - - _childContentFlowWasRemoved: function(event) - { - this._removeChildForRepresentedObject(event.data.flow); - }, - - _rootDOMNodeInvalidated: function() { - if (this.expanded) - this._frame.domTree.requestContentFlowList(); - }, - - _addRepresentedObjectToNewChildQueue: function(representedObject) - { - // This queue reduces flashing as resources load and change folders when their type becomes known. - - this._newChildQueue.push(representedObject); - if (!this._newChildQueueTimeoutIdentifier) - this._newChildQueueTimeoutIdentifier = setTimeout(this._populateFromNewChildQueue.bind(this), WebInspector.FrameTreeElement.NewChildQueueUpdateInterval); - }, - - _removeRepresentedObjectFromNewChildQueue: function(representedObject) - { - this._newChildQueue.remove(representedObject); - }, - - _populateFromNewChildQueue: function() - { - for (var i = 0; i < this._newChildQueue.length; ++i) - this._addChildForRepresentedObject(this._newChildQueue[i]); - - this._newChildQueue = []; - this._newChildQueueTimeoutIdentifier = null; - }, - - _clearNewChildQueue: function() - { - this._newChildQueue = []; - if (this._newChildQueueTimeoutIdentifier) { - clearTimeout(this._newChildQueueTimeoutIdentifier); - this._newChildQueueTimeoutIdentifier = null; - } - }, - - _addChildForRepresentedObject: function(representedObject) - { - console.assert(representedObject instanceof WebInspector.Resource || representedObject instanceof WebInspector.Frame || representedObject instanceof WebInspector.ContentFlow); - if (!(representedObject instanceof WebInspector.Resource || representedObject instanceof WebInspector.Frame || representedObject instanceof WebInspector.ContentFlow)) - return; - - this._updateParentStatus(); - - if (!this.treeOutline) { - // Just mark as needing to update to avoid doing work that might not be needed. - this.shouldRefreshChildren = true; - return; - } - - if (this._shouldGroupIntoFolders() && !this._groupedIntoFolders) { - // Mark as needing a refresh to rebuild the tree into folders. - this._groupedIntoFolders = true; - this.shouldRefreshChildren = true; - return; - } - - this._addTreeElementForRepresentedObject(representedObject); - }, - - _removeChildForRepresentedObject: function(representedObject) - { - console.assert(representedObject instanceof WebInspector.Resource || representedObject instanceof WebInspector.Frame || representedObject instanceof WebInspector.ContentFlow); - if (!(representedObject instanceof WebInspector.Resource || representedObject instanceof WebInspector.Frame || representedObject instanceof WebInspector.ContentFlow)) - return; - - this._removeRepresentedObjectFromNewChildQueue(representedObject); - - this._updateParentStatus(); - - if (!this.treeOutline) { - // Just mark as needing to update to avoid doing work that might not be needed. - this.shouldRefreshChildren = true; - return; - } - - // Find the tree element for the frame by using getCachedTreeElement - // to only get the item if it has been created already. - var childTreeElement = this.treeOutline.getCachedTreeElement(representedObject); - if (!childTreeElement || !childTreeElement.parent) - return; - - this._removeTreeElement(childTreeElement); - }, - - _addTreeElementForRepresentedObject: function(representedObject) - { - var childTreeElement = this.treeOutline.getCachedTreeElement(representedObject); - if (!childTreeElement) { - if (representedObject instanceof WebInspector.SourceMapResource) - childTreeElement = new WebInspector.SourceMapResourceTreeElement(representedObject); - else if (representedObject instanceof WebInspector.Resource) - childTreeElement = new WebInspector.ResourceTreeElement(representedObject); - else if (representedObject instanceof WebInspector.Frame) - childTreeElement = new WebInspector.FrameTreeElement(representedObject); - else if (representedObject instanceof WebInspector.ContentFlow) - childTreeElement = new WebInspector.ContentFlowTreeElement(representedObject); - } - - this._addTreeElement(childTreeElement); - }, - - _addTreeElement: function(childTreeElement) - { - console.assert(childTreeElement); - if (!childTreeElement) - return; - - var wasSelected = childTreeElement.selected; - - this._removeTreeElement(childTreeElement, true, true); - - var parentTreeElement = this._parentTreeElementForRepresentedObject(childTreeElement.representedObject); - if (parentTreeElement !== this && !parentTreeElement.parent) - this._insertFolderTreeElement(parentTreeElement); - - this._insertResourceTreeElement(parentTreeElement, childTreeElement); - - if (wasSelected) - childTreeElement.revealAndSelect(true, false, true, true); - }, - - _compareTreeElementsByMainTitle: function(a, b) - { - return a.mainTitle.localeCompare(b.mainTitle); - }, - - _insertFolderTreeElement: function(folderTreeElement) - { - console.assert(this._groupedIntoFolders); - console.assert(!folderTreeElement.parent); - this.insertChild(folderTreeElement, insertionIndexForObjectInListSortedByFunction(folderTreeElement, this.children, this._compareTreeElementsByMainTitle)); - }, - - _compareResourceTreeElements: function(a, b) - { - if (a === b) - return 0; - - var aIsResource = a instanceof WebInspector.ResourceTreeElement; - var bIsResource = b instanceof WebInspector.ResourceTreeElement; - - if (aIsResource && bIsResource) - return WebInspector.ResourceTreeElement.compareResourceTreeElements(a, b); - - if (!aIsResource && !bIsResource) { - // When both components are not resources then just compare the titles. - return a.mainTitle.localeCompare(b.mainTitle); - } - - // Non-resources should appear before the resources. - // FIXME: There should be a better way to group the elements by their type. - return aIsResource ? 1 : -1; - }, - - _insertResourceTreeElement: function(parentTreeElement, childTreeElement) - { - console.assert(!childTreeElement.parent); - parentTreeElement.insertChild(childTreeElement, insertionIndexForObjectInListSortedByFunction(childTreeElement, parentTreeElement.children, this._compareResourceTreeElements)); - }, - - _removeTreeElement: function(childTreeElement, suppressOnDeselect, suppressSelectSibling) - { - var oldParent = childTreeElement.parent; - if (!oldParent) - return; - - oldParent.removeChild(childTreeElement, suppressOnDeselect, suppressSelectSibling); - - if (oldParent === this) - return; - - console.assert(oldParent instanceof WebInspector.FolderTreeElement); - if (!(oldParent instanceof WebInspector.FolderTreeElement)) - return; - - // Remove the old parent folder if it is now empty. - if (!oldParent.children.length) - oldParent.parent.removeChild(oldParent); - }, - - _folderNameForResourceType: function(type) - { - return WebInspector.Resource.Type.displayName(type, true); - }, - - _parentTreeElementForRepresentedObject: function(representedObject) - { - if (!this._groupedIntoFolders) - return this; - - function createFolderTreeElement(type, displayName) - { - var folderTreeElement = new WebInspector.FolderTreeElement(displayName); - folderTreeElement._expandedSetting = new WebInspector.Setting(type + "-folder-expanded-" + this._frame.url.hash, false); - if (folderTreeElement._expandedSetting.value) - folderTreeElement.expand(); - folderTreeElement.onexpand = this._folderTreeElementExpandedStateChange.bind(this); - folderTreeElement.oncollapse = this._folderTreeElementExpandedStateChange.bind(this); - return folderTreeElement; - } - - if (representedObject instanceof WebInspector.Frame) { - if (!this._framesFolderTreeElement) - this._framesFolderTreeElement = createFolderTreeElement.call(this, "frames", WebInspector.UIString("Frames")); - return this._framesFolderTreeElement; - } - - if (representedObject instanceof WebInspector.ContentFlow) { - if (!this._flowsFolderTreeElement) - this._flowsFolderTreeElement = createFolderTreeElement.call(this, "flows", WebInspector.UIString("Flows")); - return this._flowsFolderTreeElement; - } - - if (representedObject instanceof WebInspector.Resource) { - var folderName = this._folderNameForResourceType(representedObject.type); - if (!folderName) - return this; - - if (!this._resourceFoldersTypeMap) - this._resourceFoldersTypeMap = {}; - if (!this._resourceFoldersTypeMap[representedObject.type]) - this._resourceFoldersTypeMap[representedObject.type] = createFolderTreeElement.call(this, representedObject.type, folderName); - return this._resourceFoldersTypeMap[representedObject.type]; - } - - console.error("Unknown representedObject: ", representedObject); - return this; - }, - - _folderTreeElementExpandedStateChange: function(folderTreeElement) - { - console.assert(folderTreeElement._expandedSetting); - folderTreeElement._expandedSetting.value = folderTreeElement.expanded; - }, - - _shouldGroupIntoFolders: function() - { - // Already grouped into folders, keep it that way. - if (this._groupedIntoFolders) - return true; - - // Resources and Frames are grouped into folders if one of two thresholds are met: - // 1) Once the number of medium categories passes NumberOfMediumCategoriesThreshold. - // 2) When there is a category that passes LargeChildCountThreshold and there are - // any resources in another category. - - // Folders are avoided when there is only one category or most categories are small. - - var numberOfSmallCategories = 0; - var numberOfMediumCategories = 0; - var foundLargeCategory = false; - var frame = this._frame; - - function pushResourceType(type) { - // There are some other properties on WebInspector.Resource.Type that we need to skip, like private data and functions - if (type.charAt(0) === "_") - return false; - - // Only care about the values that are strings, not functions, etc. - var typeValue = WebInspector.Resource.Type[type]; - if (typeof typeValue !== "string") - return false; - - return pushCategory(frame.resourcesWithType(typeValue).length); - } - - function pushCategory(resourceCount) - { - if (!resourceCount) - return false; - - // If this type has any resources and there is a known large category, make folders. - if (foundLargeCategory) - return true; - - // If there are lots of this resource type, then count it as a large category. - if (resourceCount >= WebInspector.FrameTreeElement.LargeChildCountThreshold) { - // If we already have other resources in other small or medium categories, make folders. - if (numberOfSmallCategories || numberOfMediumCategories) - return true; - - foundLargeCategory = true; - return false; - } - - // Check if this is a medium category. - if (resourceCount >= WebInspector.FrameTreeElement.MediumChildCountThreshold) { - // If this is the medium category that puts us over the maximum allowed, make folders. - return ++numberOfMediumCategories >= WebInspector.FrameTreeElement.NumberOfMediumCategoriesThreshold; - } - - // This is a small category. - ++numberOfSmallCategories; - return false; - } - - // Iterate over all the available resource types. - return pushCategory(frame.childFrames.length) || pushCategory(frame.domTree.flowsCount) || Object.keys(WebInspector.Resource.Type).some(pushResourceType); - }, - - _reloadPageClicked: function(event) - { - // Ignore cache when the shift key is pressed. - PageAgent.reload(event.data.shiftKey); - }, - - _downloadButtonClicked: function(event) - { - WebInspector.archiveMainFrame(); - }, - - _updateDownloadButton: function() - { - console.assert(this._frame.isMainFrame()); - if (!this._downloadButton) - return; - - if (!PageAgent.archive) { - this._downloadButton.hidden = true; - return; - } - - if (this._downloadingPage) { - this._downloadButton.enabled = false; - return; - } - - this._downloadButton.enabled = WebInspector.canArchiveMainFrame(); - }, - - _pageArchiveStarted: function(event) - { - this._downloadingPage = true; - this._updateDownloadButton(); - }, - - _pageArchiveEnded: function(event) - { - this._downloadingPage = false; - this._updateDownloadButton(); - } -}; - -WebInspector.FrameTreeElement.prototype.__proto__ = WebInspector.ResourceTreeElement.prototype; |