Title: [193432] trunk/Source/WebInspectorUI
Revision
193432
Author
bb...@apple.com
Date
2015-12-04 11:53:05 -0800 (Fri, 04 Dec 2015)

Log Message

Web Inspector: support runtime registration of tab type associations
https://bugs.webkit.org/show_bug.cgi?id=151594

Reviewed by Joseph Pecoraro.

We want to add special tabs that only exist in engineering builds
for debugging purposes. Though the relevant models and views can be
put in the Debug/ directory to exclude them from production builds,
there's no way to register tabs conditionally at runtime; tabs are
hardcoded.

This patch makes it possible to register new tab types at runtime.
First, WebInspector keeps a map of known, registered tab classes.
Details that were hardcoded before---whether to show in New Tab,
whether a tab can be instantiated given the active domains, UI text,
etc.---are now static methods on the base TabContentView or overidden
in its subclasses. Lastly, a public method allows code in Bootstrap.js
to register tabs at runtime. Doing so sends a notification so the
NewTabContentView can show the newly available tab item.

* UserInterface/Base/Main.js:
(WebInspector.contentLoaded):
(WebInspector.isTabTypeAllowed):
(WebInspector.knownTabClasses): Added, used by NewTabContentView.
(WebInspector._createTabContentViewForType): Renamed from _tabContentViewForType.
(WebInspector._rememberOpenTabs):
(WebInspector._updateNewTabButtonState):
(WebInspector._tryToRestorePendingTabs): Added.

Whenever a new tab is registered, try to restore pending tabs, since
an extra tab won't be added initially when production tabs are added.
But, it could have been saved in the Setting for opened tabs.

(WebInspector.showNewTabTab):
(WebInspector.isNewTabWithTypeAllowed):
(WebInspector.createNewTabWithType):
(WebInspector._tabContentViewForType): Deleted.
* UserInterface/Base/Object.js:
* UserInterface/Views/ConsoleTabContentView.js:
(WebInspector.ConsoleTabContentView):
(WebInspector.ConsoleTabContentView.tabInfo): Added.
* UserInterface/Views/DebuggerTabContentView.js:
(WebInspector.DebuggerTabContentView):
(WebInspector.DebuggerTabContentView.tabInfo): Added.
* UserInterface/Views/ElementsTabContentView.js:
(WebInspector.ElementsTabContentView):
(WebInspector.ElementsTabContentView.tabInfo): Added.
(WebInspector.ElementsTabContentView.isTabAllowed): Added.
* UserInterface/Views/NetworkTabContentView.js:
(WebInspector.NetworkTabContentView):
(WebInspector.NetworkTabContentView.tabInfo): Added.
(WebInspector.NetworkTabContentView.isTabAllowed): Added.
* UserInterface/Views/NewTabContentView.js:

Keep a list of shown tab items, so we don't have to query the DOM
to update enabled/disabled state. Put tree construction inside a
layout() override and dirty the view whenever known tab types change.

(WebInspector.NewTabContentView):
(WebInspector.NewTabContentView.tabInfo): Added.
(WebInspector.NewTabContentView.isEphemeral): Added.
(WebInspector.NewTabContentView.shouldSaveTab): Added.
(WebInspector.NewTabContentView.prototype.layout): Added.
(WebInspector.NewTabContentView.prototype._updateShownTabs): Added.
(WebInspector.NewTabContentView.prototype._allowableTabTypes):
(WebInspector.NewTabContentView.prototype._updateTabItems):
(WebInspector.NewTabContentView.prototype.get tabItemElements): Deleted.
* UserInterface/Views/ResourcesTabContentView.js:
(WebInspector.ResourcesTabContentView):
(WebInspector.ResourcesTabContentView.tabInfo): Added.
* UserInterface/Views/SearchTabContentView.js:
(WebInspector.SearchTabContentView):
(WebInspector.SearchTabContentView.tabInfo): Added.
(WebInspector.SearchTabContentView.isEphemeral): Added.
* UserInterface/Views/SettingsTabContentView.js:
(WebInspector.SettingsTabContentView.isTabAllowed): Added.
(WebInspector.SettingsTabContentView.shouldSaveTab): Added.
* UserInterface/Views/StorageTabContentView.js:
(WebInspector.StorageTabContentView):
(WebInspector.StorageTabContentView.tabInfo): Added.
(WebInspector.StorageTabContentView.isTabAllowed): Added.
* UserInterface/Views/TabBrowser.js:
(WebInspector.TabBrowser.showTabForContentView):

Add a workaround for <https://webkit.org/b/151876>. This bug is
revealed by the changes to NewTabContentView in this patch.

* UserInterface/Views/TabContentView.js:
(WebInspector.TabContentView.isTabAllowed): Added.
(WebInspector.TabContentView.isEphemeral): Added.
(WebInspector.TabContentView.shouldSaveTab): Added.
* UserInterface/Views/TimelineTabContentView.js:
(WebInspector.TimelineTabContentView):
(WebInspector.TimelineTabContentView.tabInfo): Added.
(WebInspector.TimelineTabContentView.isTabAllowed): Added.

Modified Paths

Diff

Modified: trunk/Source/WebInspectorUI/ChangeLog (193431 => 193432)


--- trunk/Source/WebInspectorUI/ChangeLog	2015-12-04 19:41:52 UTC (rev 193431)
+++ trunk/Source/WebInspectorUI/ChangeLog	2015-12-04 19:53:05 UTC (rev 193432)
@@ -1,3 +1,101 @@
+2015-12-04  Brian Burg  <bb...@apple.com>
+
+        Web Inspector: support runtime registration of tab type associations
+        https://bugs.webkit.org/show_bug.cgi?id=151594
+
+        Reviewed by Joseph Pecoraro.
+
+        We want to add special tabs that only exist in engineering builds
+        for debugging purposes. Though the relevant models and views can be
+        put in the Debug/ directory to exclude them from production builds,
+        there's no way to register tabs conditionally at runtime; tabs are
+        hardcoded.
+
+        This patch makes it possible to register new tab types at runtime.
+        First, WebInspector keeps a map of known, registered tab classes.
+        Details that were hardcoded before---whether to show in New Tab,
+        whether a tab can be instantiated given the active domains, UI text,
+        etc.---are now static methods on the base TabContentView or overidden
+        in its subclasses. Lastly, a public method allows code in Bootstrap.js
+        to register tabs at runtime. Doing so sends a notification so the
+        NewTabContentView can show the newly available tab item.
+
+        * UserInterface/Base/Main.js:
+        (WebInspector.contentLoaded):
+        (WebInspector.isTabTypeAllowed):
+        (WebInspector.knownTabClasses): Added, used by NewTabContentView.
+        (WebInspector._createTabContentViewForType): Renamed from _tabContentViewForType.
+        (WebInspector._rememberOpenTabs):
+        (WebInspector._updateNewTabButtonState):
+        (WebInspector._tryToRestorePendingTabs): Added.
+
+        Whenever a new tab is registered, try to restore pending tabs, since
+        an extra tab won't be added initially when production tabs are added.
+        But, it could have been saved in the Setting for opened tabs.
+
+        (WebInspector.showNewTabTab):
+        (WebInspector.isNewTabWithTypeAllowed):
+        (WebInspector.createNewTabWithType):
+        (WebInspector._tabContentViewForType): Deleted.
+        * UserInterface/Base/Object.js:
+        * UserInterface/Views/ConsoleTabContentView.js:
+        (WebInspector.ConsoleTabContentView):
+        (WebInspector.ConsoleTabContentView.tabInfo): Added.
+        * UserInterface/Views/DebuggerTabContentView.js:
+        (WebInspector.DebuggerTabContentView):
+        (WebInspector.DebuggerTabContentView.tabInfo): Added.
+        * UserInterface/Views/ElementsTabContentView.js:
+        (WebInspector.ElementsTabContentView):
+        (WebInspector.ElementsTabContentView.tabInfo): Added.
+        (WebInspector.ElementsTabContentView.isTabAllowed): Added.
+        * UserInterface/Views/NetworkTabContentView.js:
+        (WebInspector.NetworkTabContentView):
+        (WebInspector.NetworkTabContentView.tabInfo): Added.
+        (WebInspector.NetworkTabContentView.isTabAllowed): Added.
+        * UserInterface/Views/NewTabContentView.js:
+
+        Keep a list of shown tab items, so we don't have to query the DOM
+        to update enabled/disabled state. Put tree construction inside a
+        layout() override and dirty the view whenever known tab types change.
+
+        (WebInspector.NewTabContentView):
+        (WebInspector.NewTabContentView.tabInfo): Added.
+        (WebInspector.NewTabContentView.isEphemeral): Added.
+        (WebInspector.NewTabContentView.shouldSaveTab): Added.
+        (WebInspector.NewTabContentView.prototype.layout): Added.
+        (WebInspector.NewTabContentView.prototype._updateShownTabs): Added.
+        (WebInspector.NewTabContentView.prototype._allowableTabTypes):
+        (WebInspector.NewTabContentView.prototype._updateTabItems):
+        (WebInspector.NewTabContentView.prototype.get tabItemElements): Deleted.
+        * UserInterface/Views/ResourcesTabContentView.js:
+        (WebInspector.ResourcesTabContentView):
+        (WebInspector.ResourcesTabContentView.tabInfo): Added.
+        * UserInterface/Views/SearchTabContentView.js:
+        (WebInspector.SearchTabContentView):
+        (WebInspector.SearchTabContentView.tabInfo): Added.
+        (WebInspector.SearchTabContentView.isEphemeral): Added.
+        * UserInterface/Views/SettingsTabContentView.js:
+        (WebInspector.SettingsTabContentView.isTabAllowed): Added.
+        (WebInspector.SettingsTabContentView.shouldSaveTab): Added.
+        * UserInterface/Views/StorageTabContentView.js:
+        (WebInspector.StorageTabContentView):
+        (WebInspector.StorageTabContentView.tabInfo): Added.
+        (WebInspector.StorageTabContentView.isTabAllowed): Added.
+        * UserInterface/Views/TabBrowser.js:
+        (WebInspector.TabBrowser.showTabForContentView):
+
+        Add a workaround for <https://webkit.org/b/151876>. This bug is
+        revealed by the changes to NewTabContentView in this patch.
+
+        * UserInterface/Views/TabContentView.js:
+        (WebInspector.TabContentView.isTabAllowed): Added.
+        (WebInspector.TabContentView.isEphemeral): Added.
+        (WebInspector.TabContentView.shouldSaveTab): Added.
+        * UserInterface/Views/TimelineTabContentView.js:
+        (WebInspector.TimelineTabContentView):
+        (WebInspector.TimelineTabContentView.tabInfo): Added.
+        (WebInspector.TimelineTabContentView.isTabAllowed): Added.
+
 2015-12-04  Joseph Pecoraro  <pecor...@apple.com>
 
         Web Inspector: Remove untested and unused Worker inspection

Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Main.js (193431 => 193432)


--- trunk/Source/WebInspectorUI/UserInterface/Base/Main.js	2015-12-04 19:41:52 UTC (rev 193431)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Main.js	2015-12-04 19:53:05 UTC (rev 193432)
@@ -365,6 +365,26 @@
     this._updateToolbarHeight();
     this._setupViewHierarchy();
 
+    // These tabs are always available for selecting, modulo isTabAllowed().
+    // Other tabs may be engineering-only or toggled at runtime if incomplete.
+    let productionTabClasses = [
+        WebInspector.ConsoleTabContentView,
+        WebInspector.DebuggerTabContentView,
+        WebInspector.ElementsTabContentView,
+        WebInspector.NetworkTabContentView,
+        WebInspector.NewTabContentView,
+        WebInspector.ResourcesTabContentView,
+        WebInspector.SearchTabContentView,
+        WebInspector.StorageTabContentView,
+        WebInspector.TimelineTabContentView,
+    ];
+
+    this._knownTabClassesByType = new Map;
+    // Set tab classes directly. The public API triggers other updates and
+    // notifications that won't work or have no listeners at this point.
+    for (let tabClass of productionTabClasses)
+        this._knownTabClassesByType.set(tabClass.Type, tabClass);
+
     this._pendingOpenTabs = [];
 
     let openTabTypes = this._openTabsSetting.value;
@@ -376,7 +396,7 @@
             continue;
         }
 
-        let tabContentView = this._tabContentViewForType(tabType);
+        let tabContentView = this._createTabContentViewForType(tabType);
         if (!tabContentView)
             continue;
         this.tabBrowser.addTabForContentView(tabContentView, true);
@@ -417,57 +437,39 @@
 
 WebInspector.isTabTypeAllowed = function(tabType)
 {
-    switch (tabType) {
-    case WebInspector.ElementsTabContentView.Type:
-        return !!window.DOMAgent;
-    case WebInspector.NetworkTabContentView.Type:
-        return !!window.NetworkAgent && !!window.PageAgent;
-    case WebInspector.StorageTabContentView.Type:
-        return !!window.DOMStorageAgent || !!window.DatabaseAgent || !!window.IndexedDBAgent;
-    case WebInspector.TimelineTabContentView.Type:
-        return !!window.TimelineAgent;
-    }
+    let tabClass = this._knownTabClassesByType.get(tabType);
+    if (!tabClass)
+        return false;
 
-    return true;
+    return tabClass.isTabAllowed();
 };
 
-WebInspector._tabContentViewForType = function(tabType)
+WebInspector.knownTabClasses = function()
 {
-    switch (tabType) {
-    case WebInspector.ConsoleTabContentView.Type:
-        return new WebInspector.ConsoleTabContentView;
-    case WebInspector.DebuggerTabContentView.Type:
-        return new WebInspector.DebuggerTabContentView;
-    case WebInspector.ElementsTabContentView.Type:
-        return new WebInspector.ElementsTabContentView;
-    case WebInspector.NetworkTabContentView.Type:
-        return new WebInspector.NetworkTabContentView;
-    case WebInspector.NewTabContentView.Type:
-        return new WebInspector.NewTabContentView;
-    case WebInspector.ResourcesTabContentView.Type:
-        return new WebInspector.ResourcesTabContentView;
-    case WebInspector.SearchTabContentView.Type:
-        return new WebInspector.SearchTabContentView;
-    case WebInspector.StorageTabContentView.Type:
-        return new WebInspector.StorageTabContentView;
-    case WebInspector.TimelineTabContentView.Type:
-        return new WebInspector.TimelineTabContentView;
-    default:
+    return new Set(this._knownTabClassesByType.values());
+}
+
+WebInspector._createTabContentViewForType = function(tabType)
+{
+    let tabClass = this._knownTabClassesByType.get(tabType);
+    if (!tabClass) {
         console.error("Unknown tab type", tabType);
+        return null;
     }
 
-    return null;
+    console.assert(WebInspector.TabContentView.isPrototypeOf(tabClass));
+    return new tabClass;
 };
 
 WebInspector._rememberOpenTabs = function()
 {
-    var openTabs = [];
+    let openTabs = [];
 
-    for (var tabBarItem of this.tabBar.tabBarItems) {
-        var tabContentView = tabBarItem.representedObject;
+    for (let tabBarItem of this.tabBar.tabBarItems) {
+        let tabContentView = tabBarItem.representedObject;
         if (!(tabContentView instanceof WebInspector.TabContentView))
             continue;
-        if (tabContentView instanceof WebInspector.SettingsTabContentView || tabContentView instanceof WebInspector.NewTabContentView)
+        if (!tabContentView.constructor.shouldSaveTab())
             continue;
         console.assert(tabContentView.type, "Tab type can't be null, undefined, or empty string", tabContentView.type, tabContentView);
         openTabs.push(tabContentView.type);
@@ -482,11 +484,10 @@
 
 WebInspector._updateNewTabButtonState = function(event)
 {
-    var newTabAllowed = this.isNewTabWithTypeAllowed(WebInspector.ConsoleTabContentView.Type) || this.isNewTabWithTypeAllowed(WebInspector.ElementsTabContentView.Type)
-        || this.isNewTabWithTypeAllowed(WebInspector.ResourcesTabContentView.Type) || this.isNewTabWithTypeAllowed(WebInspector.StorageTabContentView.Type)
-        || this.isNewTabWithTypeAllowed(WebInspector.TimelineTabContentView.Type) || this.isNewTabWithTypeAllowed(WebInspector.DebuggerTabContentView.Type)
-        || this.isNewTabWithTypeAllowed(WebInspector.NetworkTabContentView.Type);
-    this.tabBar.newTabItem.disabled = !newTabAllowed;
+    let allTabs = [...this._knownTabClassesByType.values()];
+    let addableTabs = allTabs.filter((tabClass) => !tabClass.isEphemeral());
+    let canMakeNewTab = addableTabs.some((tabClass) => this.isNewTabWithTypeAllowed(tabClass.Type));
+    this.tabBar.newTabItem.disabled = !canMakeNewTab;
 };
 
 WebInspector._newTabItemClicked = function(event)
@@ -500,9 +501,32 @@
     this.showNewTabTab();
 };
 
+WebInspector._tryToRestorePendingTabs = function()
+{
+    let stillPendingOpenTabs = [];
+    for (let {tabType, index} of this._pendingOpenTabs) {
+        if (!this.isTabTypeAllowed(tabType)) {
+            stillPendingOpenTabs.push({tabType, index});
+            continue;
+        }
+
+        let tabContentView = this._createTabContentViewForType(tabType);
+        if (!tabContentView)
+            continue;
+
+        this.tabBrowser.addTabForContentView(tabContentView, true, index);
+
+        tabContentView.restoreStateFromCookie(WebInspector.StateRestorationType.Load);
+    }
+
+    this._pendingOpenTabs = stillPendingOpenTabs;
+
+    this._updateNewTabButtonState();
+}
+
 WebInspector.showNewTabTab = function(shouldAnimate)
 {
-    var tabContentView = this.tabBrowser.bestTabContentViewForClass(WebInspector.NewTabContentView);
+    let tabContentView = this.tabBrowser.bestTabContentViewForClass(WebInspector.NewTabContentView);
     if (!tabContentView)
         tabContentView = new WebInspector.NewTabContentView;
     this.tabBrowser.showTabForContentView(tabContentView, !shouldAnimate);
@@ -510,15 +534,16 @@
 
 WebInspector.isNewTabWithTypeAllowed = function(tabType)
 {
-    if (!this.isTabTypeAllowed(tabType))
+    let tabClass = this._knownTabClassesByType.get(tabType);
+    if (!tabClass || !tabClass.isTabAllowed())
         return false;
 
     // Only allow one tab per class for now.
-    for (var tabBarItem of this.tabBar.tabBarItems) {
-        var tabContentView = tabBarItem.representedObject;
+    for (let tabBarItem of this.tabBar.tabBarItems) {
+        let tabContentView = tabBarItem.representedObject;
         if (!(tabContentView instanceof WebInspector.TabContentView))
             continue;
-        if (tabContentView.type === tabType)
+        if (tabContentView.constructor === tabClass)
             return false;
     }
 
@@ -533,7 +558,7 @@
     console.assert(!referencedView || referencedView instanceof WebInspector.TabContentView, referencedView);
     console.assert(!shouldReplaceTab || referencedView, "Must provide a reference view to replace a tab.");
 
-    let tabContentView = this._tabContentViewForType(tabType);
+    let tabContentView = this._createTabContentViewForType(tabType);
     const suppressAnimations = true;
     let insertionIndex = referencedView ? this.tabBar.tabBarItems.indexOf(referencedView.tabBarItem) : undefined;
     this.tabBrowser.addTabForContentView(tabContentView, suppressAnimations, insertionIndex);
@@ -545,6 +570,21 @@
         this.tabBrowser.showTabForContentView(tabContentView);
 };
 
+WebInspector.registerTabClass = function(tabClass)
+{
+    console.assert(WebInspector.TabContentView.isPrototypeOf(tabClass));
+    if (!WebInspector.TabContentView.isPrototypeOf(tabClass))
+        return;
+
+    if (this._knownTabClassesByType.has(tabClass.Type))
+        return;
+
+    this._knownTabClassesByType.set(tabClass.Type, tabClass);
+
+    this._tryToRestorePendingTabs();
+    this.notifications.dispatchEventToListeners(WebInspector.Notification.TabTypesChanged);
+}
+
 WebInspector.activateExtraDomains = function(domains)
 {
     this.hasExtraDomains = true;
@@ -561,26 +601,7 @@
 
     this._updateReloadToolbarButton();
     this._updateDownloadToolbarButton();
-
-    let stillPendingOpenTabs = [];
-    for (let {tabType, index} of this._pendingOpenTabs) {
-        if (!this.isTabTypeAllowed(tabType)) {
-            stillPendingOpenTabs.push({tabType, index});
-            continue;
-        }
-
-        let tabContentView = this._tabContentViewForType(tabType);
-        if (!tabContentView)
-            continue;
-
-        this.tabBrowser.addTabForContentView(tabContentView, true, index);
-
-        tabContentView.restoreStateFromCookie(WebInspector.StateRestorationType.Load);
-    }
-
-    this._pendingOpenTabs = stillPendingOpenTabs;
-
-    this._updateNewTabButtonState();
+    this._tryToRestorePendingTabs();
 };
 
 WebInspector.contentBrowserTreeElementForRepresentedObject = function(contentBrowser, representedObject)

Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Object.js (193431 => 193432)


--- trunk/Source/WebInspectorUI/UserInterface/Base/Object.js	2015-12-04 19:41:52 UTC (rev 193431)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Object.js	2015-12-04 19:53:05 UTC (rev 193432)
@@ -208,4 +208,5 @@
     PageArchiveStarted: "page-archive-started",
     PageArchiveEnded: "page-archive-ended",
     ExtraDomainsActivated: "extra-domains-activated",
+    TabTypesChanged: "tab-types-changed",
 };

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleTabContentView.js (193431 => 193432)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleTabContentView.js	2015-12-04 19:41:52 UTC (rev 193431)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleTabContentView.js	2015-12-04 19:53:05 UTC (rev 193432)
@@ -27,11 +27,20 @@
 {
     constructor(identifier)
     {
-        var tabBarItem = new WebInspector.TabBarItem("Images/Console.svg", WebInspector.UIString("Console"));
+        let {image, title} = WebInspector.ConsoleTabContentView.tabInfo();
+        let tabBarItem = new WebInspector.TabBarItem(image, title);
 
         super(identifier || "console", "console", tabBarItem, null, null, true);
     }
 
+    static tabInfo()
+    {
+        return {
+            image: "Images/Console.svg",
+            title: WebInspector.UIString("Console"),
+        };
+    }
+
     // Public
 
     get type()

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerTabContentView.js (193431 => 193432)


--- trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerTabContentView.js	2015-12-04 19:41:52 UTC (rev 193431)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerTabContentView.js	2015-12-04 19:53:05 UTC (rev 193432)
@@ -27,12 +27,21 @@
 {
     constructor(identifier)
     {
-        var tabBarItem = new WebInspector.TabBarItem("Images/Debugger.svg", WebInspector.UIString("Debugger"));
-        var detailsSidebarPanels = [WebInspector.resourceDetailsSidebarPanel, WebInspector.scopeChainDetailsSidebarPanel, WebInspector.probeDetailsSidebarPanel];
+        let {image, title} = WebInspector.DebuggerTabContentView.tabInfo();
+        let tabBarItem = new WebInspector.TabBarItem(image, title);
+        let detailsSidebarPanels = [WebInspector.resourceDetailsSidebarPanel, WebInspector.scopeChainDetailsSidebarPanel, WebInspector.probeDetailsSidebarPanel];
 
         super(identifier || "debugger", "debugger", tabBarItem, WebInspector.DebuggerSidebarPanel, detailsSidebarPanels);
     }
 
+    static tabInfo()
+    {
+        return {
+            image: "Images/Debugger.svg",
+            title: WebInspector.UIString("Debugger"),
+        };
+    }
+
     // Public
 
     get type()

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ElementsTabContentView.js (193431 => 193432)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ElementsTabContentView.js	2015-12-04 19:41:52 UTC (rev 193431)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ElementsTabContentView.js	2015-12-04 19:53:05 UTC (rev 193432)
@@ -27,8 +27,9 @@
 {
     constructor(identifier)
     {
-        var tabBarItem = new WebInspector.TabBarItem("Images/Elements.svg", WebInspector.UIString("Elements"));
-        var detailsSidebarPanels = [WebInspector.domNodeDetailsSidebarPanel, WebInspector.cssStyleDetailsSidebarPanel];
+        let {image, title} = WebInspector.ElementsTabContentView.tabInfo();
+        let tabBarItem = new WebInspector.TabBarItem(image, title);
+        let detailsSidebarPanels = [WebInspector.domNodeDetailsSidebarPanel, WebInspector.cssStyleDetailsSidebarPanel];
 
         if (WebInspector.layerTreeDetailsSidebarPanel)
             detailsSidebarPanels.push(WebInspector.layerTreeDetailsSidebarPanel);
@@ -41,6 +42,19 @@
         this._showDOMTreeContentView();
     }
 
+    static tabInfo()
+    {
+        return {
+            image: "Images/Elements.svg",
+            title: WebInspector.UIString("Elements"),
+        };
+    }
+
+    static isTabAllowed()
+    {
+        return !!window.DOMAgent;
+    }
+
     // Public
 
     get type()

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTabContentView.js (193431 => 193432)


--- trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTabContentView.js	2015-12-04 19:41:52 UTC (rev 193431)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTabContentView.js	2015-12-04 19:53:05 UTC (rev 193432)
@@ -27,12 +27,26 @@
 {
     constructor(identifier)
     {
-        var tabBarItem = new WebInspector.TabBarItem("Images/Network.svg", WebInspector.UIString("Network"));
-        var detailsSidebarPanels = [WebInspector.resourceDetailsSidebarPanel, WebInspector.probeDetailsSidebarPanel];
+        let {image, title} = WebInspector.NetworkTabContentView.tabInfo();
+        let tabBarItem = new WebInspector.TabBarItem(image, title);
+        let detailsSidebarPanels = [WebInspector.resourceDetailsSidebarPanel, WebInspector.probeDetailsSidebarPanel];
 
         super(identifier || "network", "network", tabBarItem, WebInspector.NetworkSidebarPanel, detailsSidebarPanels);
     }
 
+    static tabInfo()
+    {
+        return {
+            image: "Images/Network.svg",
+            title: WebInspector.UIString("Network"),
+        };
+    }
+
+    static isTabAllowed()
+    {
+        return !!window.NetworkAgent && !!window.PageAgent;
+    }
+
     // Public
 
     get type()

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NewTabContentView.js (193431 => 193432)


--- trunk/Source/WebInspectorUI/UserInterface/Views/NewTabContentView.js	2015-12-04 19:41:52 UTC (rev 193431)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NewTabContentView.js	2015-12-04 19:53:05 UTC (rev 193432)
@@ -27,43 +27,34 @@
 {
     constructor(identifier)
     {
-        var tabBarItem = new WebInspector.TabBarItem("Images/NewTab.svg", WebInspector.UIString("New Tab"));
+        let {image, title} = WebInspector.NewTabContentView.tabInfo();
+        let tabBarItem = new WebInspector.TabBarItem(image, title);
         tabBarItem.isDefaultTab = true;
 
         super(identifier || "new-tab", "new-tab", tabBarItem);
 
-        var allowedNewTabs = [
-            {image: "Images/Console.svg", title: WebInspector.UIString("Console"), type: WebInspector.ConsoleTabContentView.Type},
-            {image: "Images/Debugger.svg", title: WebInspector.UIString("Debugger"), type: WebInspector.DebuggerTabContentView.Type},
-            {image: "Images/Elements.svg", title: WebInspector.UIString("Elements"), type: WebInspector.ElementsTabContentView.Type},
-            {image: "Images/Network.svg", title: WebInspector.UIString("Network"), type: WebInspector.NetworkTabContentView.Type},
-            {image: "Images/Resources.svg", title: WebInspector.UIString("Resources"), type: WebInspector.ResourcesTabContentView.Type},
-            {image: "Images/Storage.svg", title: WebInspector.UIString("Storage"), type: WebInspector.StorageTabContentView.Type},
-            {image: "Images/Timeline.svg", title: WebInspector.UIString("Timelines"), type: WebInspector.TimelineTabContentView.Type}
-        ];
+        WebInspector.notifications.addEventListener(WebInspector.Notification.TabTypesChanged, this._updateShownTabs.bind(this));
 
-        allowedNewTabs.sort(function(a, b) { return a.title.localeCompare(b.title); });
+        this._tabElementsByTabClass = new Map;
+        this._updateShownTabs();
+    }
 
-        for (var info of allowedNewTabs) {
-            if (!WebInspector.isTabTypeAllowed(info.type))
-                continue;
+    static tabInfo()
+    {
+        return {
+            image: "Images/NewTab.svg",
+            title: WebInspector.UIString("New Tab"),
+        };
+    }
 
-            var tabItemElement = document.createElement("div");
-            tabItemElement.classList.add(WebInspector.NewTabContentView.TabItemStyleClassName);
-            tabItemElement.addEventListener("click", this._createNewTabWithType.bind(this, info.type));
-            tabItemElement[WebInspector.NewTabContentView.TypeSymbol] = info.type;
+    static isEphemeral()
+    {
+        return true;
+    }
 
-            var boxElement = tabItemElement.appendChild(document.createElement("div"));
-            boxElement.classList.add("box");
-
-            var imageElement = boxElement.appendChild(document.createElement("img"));
-            imageElement.src = ""
-
-            var labelElement = tabItemElement.appendChild(document.createElement("label"));
-            labelElement.textContent = info.title;
-
-            this.element.appendChild(tabItemElement);
-        }
+    static shouldSaveTab()
+    {
+        return false;
     }
 
     // Public
@@ -93,9 +84,32 @@
         return false;
     }
 
-    get tabItemElements()
+    layout()
     {
-        return Array.from(this.element.querySelectorAll("." + WebInspector.NewTabContentView.TabItemStyleClassName));
+        this._tabElementsByTabClass.clear();
+        this.element.removeChildren();
+
+        for (let tabClass of this._shownTabClasses) {
+            let tabItemElement = document.createElement("div");
+            tabItemElement.classList.add("tab-item");
+            tabItemElement.addEventListener("click", this._createNewTabWithType.bind(this, tabClass.Type));
+            tabItemElement[WebInspector.NewTabContentView.TypeSymbol] = tabClass.Type;
+
+            let boxElement = tabItemElement.appendChild(document.createElement("div"));
+            boxElement.classList.add("box");
+
+            let info = tabClass.tabInfo();
+            let imageElement = boxElement.appendChild(document.createElement("img"));
+            imageElement.src = ""
+
+            let labelElement = tabItemElement.appendChild(document.createElement("label"));
+            labelElement.textContent = info.title;
+
+            this.element.appendChild(tabItemElement);
+            this._tabElementsByTabClass.set(tabClass, tabItemElement);
+        }
+
+        this._updateTabItems();
     }
 
     // Private
@@ -114,19 +128,29 @@
         WebInspector.createNewTabWithType(tabType, options);
     }
 
+    _updateShownTabs()
+    {
+        let allTabClasses = [...WebInspector.knownTabClasses()];
+        let allowedTabClasses = allTabClasses.filter((tabClass) => tabClass.isTabAllowed() && !tabClass.isEphemeral());
+        allowedTabClasses.sort((a, b) => a.tabInfo().title.localeCompare(b.tabInfo().title));
+
+        if (Object.shallowEqual(this._shownTabClasses, allowedTabClasses))
+            return;
+
+        this._shownTabClasses = allowedTabClasses;
+        this.needsLayout();
+    }
+
     _allowableTabTypes()
     {
-        let tabItemElements = this.tabItemElements;
-        let tabTypes = tabItemElements.map((tabItemElement) => tabItemElement[WebInspector.NewTabContentView.TypeSymbol]);
+        let tabTypes = this._shownTabClasses.map((tabClass) => tabClass.Type);
         return tabTypes.filter((type) => WebInspector.isNewTabWithTypeAllowed(type));
     }
 
     _updateTabItems()
     {
-        let tabItemElements = this.tabItemElements;
-        for (let tabItemElement of tabItemElements) {
-            let type = tabItemElement[WebInspector.NewTabContentView.TypeSymbol];
-            let allowed = WebInspector.isNewTabWithTypeAllowed(type);
+        for (let [tabClass, tabItemElement] of this._tabElementsByTabClass.entries()) {
+            let allowed = WebInspector.isNewTabWithTypeAllowed(tabClass.Type);
             tabItemElement.classList.toggle(WebInspector.NewTabContentView.DisabledStyleClassName, !allowed);
         }
     }

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ResourcesTabContentView.js (193431 => 193432)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ResourcesTabContentView.js	2015-12-04 19:41:52 UTC (rev 193431)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ResourcesTabContentView.js	2015-12-04 19:53:05 UTC (rev 193432)
@@ -27,8 +27,9 @@
 {
     constructor(identifier)
     {
-        var tabBarItem = new WebInspector.TabBarItem("Images/Resources.svg", WebInspector.UIString("Resources"));
-        var detailsSidebarPanels = [WebInspector.resourceDetailsSidebarPanel, WebInspector.probeDetailsSidebarPanel];
+        let {image, title} = WebInspector.ResourcesTabContentView.tabInfo();
+        let tabBarItem = new WebInspector.TabBarItem(image, title);
+        let detailsSidebarPanels = [WebInspector.resourceDetailsSidebarPanel, WebInspector.probeDetailsSidebarPanel];
 
         // FIXME: Until ContentFlows are moved to the Elements tab, these details sidebar panels need to be included.
         detailsSidebarPanels = detailsSidebarPanels.concat([WebInspector.domNodeDetailsSidebarPanel, WebInspector.cssStyleDetailsSidebarPanel]);
@@ -38,6 +39,14 @@
         super(identifier || "resources", "resources", tabBarItem, WebInspector.ResourceSidebarPanel, detailsSidebarPanels);
     }
 
+    static tabInfo()
+    {
+        return {
+            image: "Images/Resources.svg",
+            title: WebInspector.UIString("Resources"),
+        };
+    }
+
     // Public
 
     get type()

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SearchTabContentView.js (193431 => 193432)


--- trunk/Source/WebInspectorUI/UserInterface/Views/SearchTabContentView.js	2015-12-04 19:41:52 UTC (rev 193431)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SearchTabContentView.js	2015-12-04 19:53:05 UTC (rev 193432)
@@ -27,8 +27,9 @@
 {
     constructor(identifier)
     {
-        var tabBarItem = new WebInspector.TabBarItem("Images/SearchResults.svg", WebInspector.UIString("Search"));
-        var detailsSidebarPanels = [WebInspector.resourceDetailsSidebarPanel, WebInspector.probeDetailsSidebarPanel,
+        let {image, title} = WebInspector.SearchTabContentView.tabInfo();
+        let tabBarItem = new WebInspector.TabBarItem(image, title);
+        let detailsSidebarPanels = [WebInspector.resourceDetailsSidebarPanel, WebInspector.probeDetailsSidebarPanel,
             WebInspector.domNodeDetailsSidebarPanel, WebInspector.cssStyleDetailsSidebarPanel];
 
         if (WebInspector.layerTreeDetailsSidebarPanel)
@@ -37,6 +38,19 @@
         super(identifier || "search", "search", tabBarItem, WebInspector.SearchSidebarPanel, detailsSidebarPanels);
     }
 
+    static tabInfo()
+    {
+        return {
+            image: "Images/SearchResults.svg",
+            title: WebInspector.UIString("Search"),
+        };
+    }
+
+    static isEphemeral()
+    {
+        return true;
+    }
+
     // Public
 
     get type()

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.js (193431 => 193432)


--- trunk/Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.js	2015-12-04 19:41:52 UTC (rev 193431)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.js	2015-12-04 19:53:05 UTC (rev 193432)
@@ -32,6 +32,17 @@
         super(identifier || "settings", "settings", tabBarItem);
     }
 
+    static isTabAllowed()
+    {
+        // FIXME (149284): This tab isn't ready to be shown yet.
+        return false;
+    }
+
+    static shouldSaveTab()
+    {
+        return false;
+    }
+
     // Public
 
     get type()

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/StorageTabContentView.js (193431 => 193432)


--- trunk/Source/WebInspectorUI/UserInterface/Views/StorageTabContentView.js	2015-12-04 19:41:52 UTC (rev 193431)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/StorageTabContentView.js	2015-12-04 19:53:05 UTC (rev 193432)
@@ -27,12 +27,26 @@
 {
     constructor(identifier)
     {
-        var tabBarItem = new WebInspector.TabBarItem("Images/Storage.svg", WebInspector.UIString("Storage"));
-        var detailsSidebarPanels = [WebInspector.applicationCacheDetailsSidebarPanel];
+        let {image, title} = WebInspector.StorageTabContentView.tabInfo();
+        let tabBarItem = new WebInspector.TabBarItem(image, title);
+        let detailsSidebarPanels = [WebInspector.applicationCacheDetailsSidebarPanel];
 
         super(identifier || "storage", "storage", tabBarItem, WebInspector.StorageSidebarPanel, detailsSidebarPanels);
     }
 
+    static tabInfo()
+    {
+        return {
+            image: "Images/Storage.svg",
+            title: WebInspector.UIString("Storage"),
+        };
+    }
+
+    static isTabAllowed()
+    {
+        return !!window.DOMStorageAgent || !!window.DatabaseAgent || !!window.IndexedDBAgent;
+    }
+
     // Public
 
     get type()

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TabBrowser.js (193431 => 193432)


--- trunk/Source/WebInspectorUI/UserInterface/Views/TabBrowser.js	2015-12-04 19:41:52 UTC (rev 193431)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TabBrowser.js	2015-12-04 19:53:05 UTC (rev 193432)
@@ -160,6 +160,13 @@
 
         this._tabBar.selectedTabBarItem = tabContentView.tabBarItem;
 
+        // FIXME: this is a workaround for <https://webkit.org/b/151876>.
+        // Without this extra call, we might never lay out the child tab
+        // if it has already marked itself as dirty in the same run loop
+        // as it is attached. It will schedule a layout, but when the rAF
+        // fires the parent will abort the layout because the counter is
+        // out of sync.
+        this.needsLayout();
         return true;
     }
 

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TabContentView.js (193431 => 193432)


--- trunk/Source/WebInspectorUI/UserInterface/Views/TabContentView.js	2015-12-04 19:41:52 UTC (rev 193431)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TabContentView.js	2015-12-04 19:53:05 UTC (rev 193432)
@@ -55,6 +55,24 @@
         this._cookieSetting = new WebInspector.Setting(identifier + "-tab-cookie", {});
     }
 
+    static isTabAllowed()
+    {
+        // Returns false if a necessary domain or other features are unavailable.
+        return true;
+    }
+
+    static isEphemeral()
+    {
+        // Returns true if the tab should not be shown in the new tab content view.
+        return false;
+    }
+
+    static shouldSaveTab()
+    {
+        // Returns false if the tab should not be restored when re-opening the Inspector.
+        return true;
+    }
+
     // Public
 
     get type()

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.js (193431 => 193432)


--- trunk/Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.js	2015-12-04 19:41:52 UTC (rev 193431)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.js	2015-12-04 19:53:05 UTC (rev 193432)
@@ -27,12 +27,26 @@
 {
     constructor(identifier)
     {
-        var tabBarItem = new WebInspector.TabBarItem("Images/Timeline.svg", WebInspector.UIString("Timelines"));
-        var detailsSidebarPanels = [WebInspector.resourceDetailsSidebarPanel, WebInspector.probeDetailsSidebarPanel];
+        let {image, title} = WebInspector.TimelineTabContentView.tabInfo();
+        let tabBarItem = new WebInspector.TabBarItem(image, title);
+        let detailsSidebarPanels = [WebInspector.resourceDetailsSidebarPanel, WebInspector.probeDetailsSidebarPanel];
 
         super(identifier || "timeline", "timeline", tabBarItem, WebInspector.TimelineSidebarPanel, detailsSidebarPanels);
     }
 
+    static tabInfo()
+    {
+        return {
+            image: "Images/Timeline.svg",
+            title: WebInspector.UIString("Timelines"),
+        };
+    }
+
+    static isTabAllowed()
+    {
+        return !!window.TimelineAgent;
+    }
+
     // Public
 
     get type()
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to