Added: trunk/Source/WebInspectorUI/UserInterface/Views/SourcesSidebarPanel.css (0 => 229443)
--- trunk/Source/WebInspectorUI/UserInterface/Views/SourcesSidebarPanel.css (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SourcesSidebarPanel.css 2018-03-09 01:32:51 UTC (rev 229443)
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+.sidebar > .panel.navigation.sources > .content {
+ top: var(--navigation-bar-height);
+}
+
+.sidebar > .panel.navigation.sources > .navigation-bar {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+}
Added: trunk/Source/WebInspectorUI/UserInterface/Views/SourcesSidebarPanel.js (0 => 229443)
--- trunk/Source/WebInspectorUI/UserInterface/Views/SourcesSidebarPanel.js (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SourcesSidebarPanel.js 2018-03-09 01:32:51 UTC (rev 229443)
@@ -0,0 +1,504 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+WI.SourcesSidebarPanel = class SourcesSidebarPanel extends WI.NavigationSidebarPanel
+{
+ constructor()
+ {
+ super("sources", WI.UIString("Sources"), true);
+
+ this._navigationBar = new WI.NavigationBar;
+ this.addSubview(this._navigationBar);
+
+ this._targetTreeElementMap = new Map;
+
+ let scopeItemPrefix = "sources-sidebar-";
+ let scopeBarItems = [];
+
+ scopeBarItems.push(new WI.ScopeBarItem(scopeItemPrefix + "type-all", WI.UIString("All Resources"), true));
+
+ for (let key in WI.Resource.Type) {
+ let value = WI.Resource.Type[key];
+ let scopeBarItem = new WI.ScopeBarItem(scopeItemPrefix + value, WI.Resource.displayNameForType(value, true));
+ scopeBarItem[WI.SourcesSidebarPanel.ResourceTypeSymbol] = value;
+ scopeBarItems.push(scopeBarItem);
+ }
+
+ this._scopeBar = new WI.ScopeBar("sources-sidebar-scope-bar", scopeBarItems, scopeBarItems[0], true);
+ this._scopeBar.addEventListener(WI.ScopeBar.Event.SelectionChanged, this._scopeBarSelectionDidChange, this);
+
+ this._navigationBar.addNavigationItem(this._scopeBar);
+
+ WI.Frame.addEventListener(WI.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this);
+
+ WI.frameResourceManager.addEventListener(WI.FrameResourceManager.Event.MainFrameDidChange, this._mainFrameDidChange, this);
+
+ WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ScriptAdded, this._scriptWasAdded, this);
+ WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ScriptRemoved, this._scriptWasRemoved, this);
+ WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ScriptsCleared, this._scriptsCleared, this);
+
+ WI.cssStyleManager.addEventListener(WI.CSSStyleManager.Event.StyleSheetAdded, this._styleSheetAdded, this);
+
+ WI.targetManager.addEventListener(WI.TargetManager.Event.TargetRemoved, this._targetRemoved, this);
+
+ WI.notifications.addEventListener(WI.Notification.ExtraDomainsActivated, this._extraDomainsActivated, this);
+
+ this.contentTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._treeSelectionDidChange, this);
+ this.contentTreeOutline.includeSourceMapResourceChildren = true;
+
+ if (SourcesSidebarPanel.shouldPlaceResourcesAtTopLevel()) {
+ this.contentTreeOutline.disclosureButtons = false;
+ WI.SourceCode.addEventListener(WI.SourceCode.Event.SourceMapAdded, () => { this.contentTreeOutline.disclosureButtons = true; }, this);
+ }
+ }
+
+ // Static
+
+ static shouldPlaceResourcesAtTopLevel()
+ {
+ return (WI.sharedApp.debuggableType === WI.DebuggableType._javascript_ && !WI.sharedApp.hasExtraDomains)
+ || WI.sharedApp.debuggableType === WI.DebuggableType.ServiceWorker;
+ }
+
+ // Public
+
+ get minimumWidth()
+ {
+ return this._navigationBar.minimumWidth;
+ }
+
+ closed()
+ {
+ super.closed();
+
+ WI.Frame.removeEventListener(null, null, this);
+ WI.frameResourceManager.removeEventListener(null, null, this);
+ WI.debuggerManager.removeEventListener(null, null, this);
+ WI.notifications.removeEventListener(null, null, this);
+ }
+
+ showDefaultContentView()
+ {
+ if (WI.frameResourceManager.mainFrame) {
+ this.contentBrowser.showContentViewForRepresentedObject(WI.frameResourceManager.mainFrame);
+ return;
+ }
+
+ let firstTreeElement = this.contentTreeOutline.children[0];
+ if (firstTreeElement)
+ this.showDefaultContentViewForTreeElement(firstTreeElement);
+ }
+
+ treeElementForRepresentedObject(representedObject)
+ {
+ // A custom implementation is needed for this since the frames are populated lazily.
+
+ if (!this._mainFrameTreeElement && (representedObject instanceof WI.Resource || representedObject instanceof WI.Frame || representedObject instanceof WI.Collection)) {
+ // All resources are under the main frame, so we need to return early if we don't have the main frame yet.
+ return null;
+ }
+
+ // The Frame is used as the representedObject instead of the main resource in our tree.
+ if (representedObject instanceof WI.Resource && representedObject.parentFrame && representedObject.parentFrame.mainResource === representedObject)
+ representedObject = representedObject.parentFrame;
+
+ function isAncestor(ancestor, resourceOrFrame)
+ {
+ // SourceMapResources are descendants of another SourceCode object.
+ if (resourceOrFrame instanceof WI.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;
+ }
+
+ let 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 WI.SourceMapResource)
+ return resourceOrFrame.sourceMap.originalSourceCode;
+ return resourceOrFrame.parentFrame;
+ }
+
+ let treeElement = this.contentTreeOutline.findTreeElement(representedObject, isAncestor, getParent);
+ if (treeElement)
+ return treeElement;
+
+ // Only special case Script objects.
+ if (!(representedObject instanceof WI.Script)) {
+ console.error("Didn't find a TreeElement for representedObject", representedObject);
+ 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) {
+ let collection = new WI.ScriptCollection;
+ this._anonymousScriptsFolderTreeElement = new WI.FolderTreeElement(WI.UIString("Anonymous Scripts"), collection);
+ }
+
+ if (!this._anonymousScriptsFolderTreeElement.parent) {
+ let index = insertionIndexForObjectInListSortedByFunction(this._anonymousScriptsFolderTreeElement, this.contentTreeOutline.children, this._compareTreeElements);
+ this.contentTreeOutline.insertChild(this._anonymousScriptsFolderTreeElement, index);
+ }
+
+ this._anonymousScriptsFolderTreeElement.representedObject.add(representedObject);
+
+ let scriptTreeElement = new WI.ScriptTreeElement(representedObject);
+ this._anonymousScriptsFolderTreeElement.appendChild(scriptTreeElement);
+
+ return scriptTreeElement;
+ }
+
+ // Protected
+
+ initialLayout()
+ {
+ super.initialLayout();
+
+ if (WI.frameResourceManager.mainFrame)
+ this._mainFrameMainResourceDidChange(WI.frameResourceManager.mainFrame);
+
+ for (let script of WI.debuggerManager.knownNonResourceScripts) {
+ this._addScript(script);
+
+ if (script.sourceMaps.length && SourcesSidebarPanel.shouldPlaceResourcesAtTopLevel())
+ this.contentTreeOutline.disclosureButtons = true;
+ }
+ }
+
+ hasCustomFilters()
+ {
+ console.assert(this._scopeBar.selectedItems.length === 1);
+ let selectedScopeBarItem = this._scopeBar.selectedItems[0];
+ return selectedScopeBarItem && !selectedScopeBarItem.exclusive;
+ }
+
+ matchTreeElementAgainstCustomFilters(treeElement, flags)
+ {
+ console.assert(this._scopeBar.selectedItems.length === 1);
+ let selectedScopeBarItem = this._scopeBar.selectedItems[0];
+
+ // Show everything if there is no selection or "All Resources" is selected (the exclusive item).
+ if (!selectedScopeBarItem || selectedScopeBarItem.exclusive)
+ return true;
+
+ // Folders are hidden on the first pass, but visible childen under the folder will force the folder visible again.
+ if (treeElement instanceof WI.FolderTreeElement)
+ return false;
+
+ function match()
+ {
+ if (treeElement instanceof WI.FrameTreeElement)
+ return selectedScopeBarItem[WI.SourcesSidebarPanel.ResourceTypeSymbol] === WI.Resource.Type.Document;
+
+ if (treeElement instanceof WI.ScriptTreeElement)
+ return selectedScopeBarItem[WI.SourcesSidebarPanel.ResourceTypeSymbol] === WI.Resource.Type.Script;
+
+ if (treeElement instanceof WI.CSSStyleSheetTreeElement)
+ return selectedScopeBarItem[WI.SourcesSidebarPanel.ResourceTypeSymbol] === WI.Resource.Type.Stylesheet;
+
+ console.assert(treeElement instanceof WI.ResourceTreeElement, "Unknown treeElement", treeElement);
+ if (!(treeElement instanceof WI.ResourceTreeElement))
+ return false;
+
+ return treeElement.resource.type === selectedScopeBarItem[WI.SourcesSidebarPanel.ResourceTypeSymbol];
+ }
+
+ let matched = match();
+ if (matched)
+ flags.expandTreeElement = true;
+ return matched;
+ }
+
+ // Private
+
+ _mainResourceDidChange(event)
+ {
+ if (!event.target.isMainFrame())
+ return;
+
+ this._mainFrameMainResourceDidChange(event.target);
+ }
+
+ _mainFrameDidChange(event)
+ {
+ this._mainFrameMainResourceDidChange(WI.frameResourceManager.mainFrame);
+ }
+
+ _mainFrameMainResourceDidChange(mainFrame)
+ {
+ this.contentBrowser.contentViewContainer.closeAllContentViews();
+
+ if (this._mainFrameTreeElement) {
+ this.contentTreeOutline.removeChild(this._mainFrameTreeElement);
+ this._mainFrameTreeElement = null;
+ }
+
+ if (!mainFrame)
+ return;
+
+ this._mainFrameTreeElement = new WI.FrameTreeElement(mainFrame);
+ this.contentTreeOutline.insertChild(this._mainFrameTreeElement, 0);
+
+ function delayedWork()
+ {
+ if (!this.contentTreeOutline.selectedTreeElement) {
+ let currentContentView = this.contentBrowser.currentContentView;
+ let treeElement = currentContentView ? this.treeElementForRepresentedObject(currentContentView.representedObject) : null;
+ if (!treeElement)
+ treeElement = this._mainFrameTreeElement;
+ this.showDefaultContentViewForTreeElement(treeElement);
+ }
+ }
+
+ // Cookie restoration will attempt to re-select the resource we were showing.
+ // Give it time to do that before selecting the main frame resource.
+ setTimeout(delayedWork.bind(this));
+ }
+
+ _scriptWasAdded(event)
+ {
+ this._addScript(event.data.script);
+ }
+
+ _addScript(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 && !script.sourceURL)
+ return;
+
+ // Target main resource.
+ if (script.target !== WI.pageTarget) {
+ if (script.isMainResource())
+ this._addTargetWithMainResource(script.target);
+ this.contentTreeOutline.disclosureButtons = true;
+ 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 || script.dynamicallyAddedScriptElement)
+ return;
+
+ let insertIntoTopLevel = false;
+ let parentFolderTreeElement = null;
+
+ if (script.injected) {
+ if (!this._extensionScriptsFolderTreeElement) {
+ let collection = new WI.ScriptCollection;
+ this._extensionScriptsFolderTreeElement = new WI.FolderTreeElement(WI.UIString("Extension Scripts"), collection);
+ }
+
+ parentFolderTreeElement = this._extensionScriptsFolderTreeElement;
+ } else {
+ if (SourcesSidebarPanel.shouldPlaceResourcesAtTopLevel())
+ insertIntoTopLevel = true;
+ else {
+ if (!this._extraScriptsFolderTreeElement) {
+ let collection = new WI.ScriptCollection;
+ this._extraScriptsFolderTreeElement = new WI.FolderTreeElement(WI.UIString("Extra Scripts"), collection);
+ }
+
+ parentFolderTreeElement = this._extraScriptsFolderTreeElement;
+ }
+ }
+
+ if (parentFolderTreeElement)
+ parentFolderTreeElement.representedObject.add(script);
+
+ let scriptTreeElement = new WI.ScriptTreeElement(script);
+
+ if (insertIntoTopLevel) {
+ let index = insertionIndexForObjectInListSortedByFunction(scriptTreeElement, this.contentTreeOutline.children, this._compareTreeElements);
+ this.contentTreeOutline.insertChild(scriptTreeElement, index);
+ } else {
+ if (!parentFolderTreeElement.parent) {
+ let index = insertionIndexForObjectInListSortedByFunction(parentFolderTreeElement, this.contentTreeOutline.children, this._compareTreeElements);
+ this.contentTreeOutline.insertChild(parentFolderTreeElement, index);
+ }
+
+ parentFolderTreeElement.appendChild(scriptTreeElement);
+ }
+ }
+
+ _scriptWasRemoved(event)
+ {
+ let script = event.data.script;
+ let scriptTreeElement = this.contentTreeOutline.getCachedTreeElement(script);
+ if (!scriptTreeElement)
+ return;
+
+ let parentTreeElement = scriptTreeElement.parent;
+ parentTreeElement.removeChild(scriptTreeElement);
+
+ if (parentTreeElement instanceof WI.FolderTreeElement) {
+ parentTreeElement.representedObject.remove(script);
+
+ if (!parentTreeElement.children.length)
+ parentTreeElement.parent.removeChild(parentTreeElement);
+ }
+ }
+
+ _scriptsCleared(event)
+ {
+ const suppressOnDeselect = true;
+ const suppressSelectSibling = true;
+
+ if (this._extensionScriptsFolderTreeElement) {
+ if (this._extensionScriptsFolderTreeElement.parent)
+ this._extensionScriptsFolderTreeElement.parent.removeChild(this._extensionScriptsFolderTreeElement, suppressOnDeselect, suppressSelectSibling);
+
+ this._extensionScriptsFolderTreeElement.representedObject.clear();
+ this._extensionScriptsFolderTreeElement = null;
+ }
+
+ if (this._extraScriptsFolderTreeElement) {
+ if (this._extraScriptsFolderTreeElement.parent)
+ this._extraScriptsFolderTreeElement.parent.removeChild(this._extraScriptsFolderTreeElement, suppressOnDeselect, suppressSelectSibling);
+
+ this._extraScriptsFolderTreeElement.representedObject.clear();
+ this._extraScriptsFolderTreeElement = null;
+ }
+
+ if (this._anonymousScriptsFolderTreeElement) {
+ if (this._anonymousScriptsFolderTreeElement.parent)
+ this._anonymousScriptsFolderTreeElement.parent.removeChild(this._anonymousScriptsFolderTreeElement, suppressOnDeselect, suppressSelectSibling);
+
+ this._anonymousScriptsFolderTreeElement.representedObject.clear();
+ this._anonymousScriptsFolderTreeElement = null;
+ }
+
+ if (this._targetTreeElementMap.size) {
+ for (let treeElement of this._targetTreeElementMap)
+ treeElement.parent.removeChild(treeElement, suppressOnDeselect, suppressSelectSibling);
+ this._targetTreeElementMap.clear();
+ }
+ }
+
+ _styleSheetAdded(event)
+ {
+ let styleSheet = event.data.styleSheet;
+ if (!styleSheet.isInspectorStyleSheet())
+ return;
+
+ let frameTreeElement = this.treeElementForRepresentedObject(styleSheet.parentFrame);
+ if (!frameTreeElement)
+ return;
+
+ frameTreeElement.addRepresentedObjectToNewChildQueue(styleSheet);
+ }
+
+ _addTargetWithMainResource(target)
+ {
+ console.assert(target.type === WI.Target.Type.Worker || target.type === WI.Target.Type.ServiceWorker);
+
+ let targetTreeElement = new WI.WorkerTreeElement(target);
+ this._targetTreeElementMap.set(target, targetTreeElement);
+
+ let index = insertionIndexForObjectInListSortedByFunction(targetTreeElement, this.contentTreeOutline.children, this._compareTreeElements);
+ this.contentTreeOutline.insertChild(targetTreeElement, index);
+ }
+
+ _targetRemoved(event)
+ {
+ let removedTarget = event.data.target;
+
+ let targetTreeElement = this._targetTreeElementMap.take(removedTarget);
+ if (targetTreeElement)
+ targetTreeElement.parent.removeChild(targetTreeElement);
+ }
+
+ _treeSelectionDidChange(event)
+ {
+ if (!this.visible)
+ return;
+
+ let treeElement = event.data.selectedElement;
+ if (!treeElement)
+ return;
+
+ if (treeElement instanceof WI.FolderTreeElement
+ || treeElement instanceof WI.ResourceTreeElement
+ || treeElement instanceof WI.ScriptTreeElement
+ || treeElement instanceof WI.CSSStyleSheetTreeElement) {
+ const cookie = null;
+ const options = {
+ ignoreNetworkTab: true,
+ ignoreSearchTab: true,
+ };
+ WI.showRepresentedObject(treeElement.representedObject, cookie, options);
+ return;
+ }
+
+ console.error("Unknown tree element", treeElement);
+ }
+
+ _compareTreeElements(a, b)
+ {
+ // Always sort the main frame element first.
+ if (a instanceof WI.FrameTreeElement)
+ return -1;
+ if (b instanceof WI.FrameTreeElement)
+ return 1;
+
+ console.assert(a.mainTitle);
+ console.assert(b.mainTitle);
+
+ return (a.mainTitle || "").extendedLocaleCompare(b.mainTitle || "");
+ }
+
+ _extraDomainsActivated()
+ {
+ if (SourcesSidebarPanel.shouldPlaceResourcesAtTopLevel())
+ this.contentTreeOutline.disclosureButtons = true;
+ }
+
+ _scopeBarSelectionDidChange(event)
+ {
+ this.updateFilter();
+ }
+};
+
+WI.SourcesSidebarPanel.ResourceTypeSymbol = Symbol("resource-type");
Added: trunk/Source/WebInspectorUI/UserInterface/Views/SourcesTabContentView.js (0 => 229443)
--- trunk/Source/WebInspectorUI/UserInterface/Views/SourcesTabContentView.js (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SourcesTabContentView.js 2018-03-09 01:32:51 UTC (rev 229443)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+WI.SourcesTabContentView = class SourcesTabContentView extends WI.ContentBrowserTabContentView
+{
+ constructor(identifier)
+ {
+ let tabBarItem = WI.GeneralTabBarItem.fromTabInfo(WI.SourcesTabContentView.tabInfo());
+ const detailsSidebarPanelConstructors = [WI.ResourceDetailsSidebarPanel, WI.ProbeDetailsSidebarPanel];
+ super(identifier || "sources", "sources", tabBarItem, WI.SourcesSidebarPanel, detailsSidebarPanelConstructors);
+ }
+
+ static tabInfo()
+ {
+ return {
+ image: "Images/Resources.svg",
+ title: WI.UIString("Sources"),
+ };
+ }
+
+ static isTabAllowed()
+ {
+ return WI.settings.experimentalEnableSourcesTab.value;
+ }
+
+ // Public
+
+ get type()
+ {
+ return WI.SourcesTabContentView.Type;
+ }
+
+ get supportsSplitContentBrowser()
+ {
+ return true;
+ }
+
+ canShowRepresentedObject(representedObject)
+ {
+ return representedObject instanceof WI.Frame
+ || representedObject instanceof WI.Resource
+ || representedObject instanceof WI.Script
+ || representedObject instanceof WI.CSSStyleSheet
+ || (representedObject instanceof WI.Collection && !(representedObject instanceof WI.CanvasCollection));
+ }
+};
+
+WI.SourcesTabContentView.Type = "sources";