<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[193432] trunk/Source/WebInspectorUI</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/193432">193432</a></dd>
<dt>Author</dt> <dd>bburg@apple.com</dd>
<dt>Date</dt> <dd>2015-12-04 11:53:05 -0800 (Fri, 04 Dec 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>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 &lt;https://webkit.org/b/151876&gt;. 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.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceBaseMainjs">trunk/Source/WebInspectorUI/UserInterface/Base/Main.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceBaseObjectjs">trunk/Source/WebInspectorUI/UserInterface/Base/Object.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsConsoleTabContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleTabContentView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsDebuggerTabContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerTabContentView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsElementsTabContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/ElementsTabContentView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsNetworkTabContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTabContentView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsNewTabContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/NewTabContentView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsResourcesTabContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/ResourcesTabContentView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsSearchTabContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/SearchTabContentView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsSettingsTabContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsStorageTabContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/StorageTabContentView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsTabBrowserjs">trunk/Source/WebInspectorUI/UserInterface/Views/TabBrowser.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsTabContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/TabContentView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsTimelineTabContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (193431 => 193432)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,3 +1,101 @@
</span><ins>+2015-12-04  Brian Burg  &lt;bburg@apple.com&gt;
+
+        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 &lt;https://webkit.org/b/151876&gt;. 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.
+
</ins><span class="cx"> 2015-12-04  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Remove untested and unused Worker inspection
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceBaseMainjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Main.js (193431 => 193432)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -365,6 +365,26 @@
</span><span class="cx">     this._updateToolbarHeight();
</span><span class="cx">     this._setupViewHierarchy();
</span><span class="cx"> 
</span><ins>+    // 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);
+
</ins><span class="cx">     this._pendingOpenTabs = [];
</span><span class="cx"> 
</span><span class="cx">     let openTabTypes = this._openTabsSetting.value;
</span><span class="lines">@@ -376,7 +396,7 @@
</span><span class="cx">             continue;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        let tabContentView = this._tabContentViewForType(tabType);
</del><ins>+        let tabContentView = this._createTabContentViewForType(tabType);
</ins><span class="cx">         if (!tabContentView)
</span><span class="cx">             continue;
</span><span class="cx">         this.tabBrowser.addTabForContentView(tabContentView, true);
</span><span class="lines">@@ -417,57 +437,39 @@
</span><span class="cx"> 
</span><span class="cx"> WebInspector.isTabTypeAllowed = function(tabType)
</span><span class="cx"> {
</span><del>-    switch (tabType) {
-    case WebInspector.ElementsTabContentView.Type:
-        return !!window.DOMAgent;
-    case WebInspector.NetworkTabContentView.Type:
-        return !!window.NetworkAgent &amp;&amp; !!window.PageAgent;
-    case WebInspector.StorageTabContentView.Type:
-        return !!window.DOMStorageAgent || !!window.DatabaseAgent || !!window.IndexedDBAgent;
-    case WebInspector.TimelineTabContentView.Type:
-        return !!window.TimelineAgent;
-    }
</del><ins>+    let tabClass = this._knownTabClassesByType.get(tabType);
+    if (!tabClass)
+        return false;
</ins><span class="cx"> 
</span><del>-    return true;
</del><ins>+    return tabClass.isTabAllowed();
</ins><span class="cx"> };
</span><span class="cx"> 
</span><del>-WebInspector._tabContentViewForType = function(tabType)
</del><ins>+WebInspector.knownTabClasses = function()
</ins><span class="cx"> {
</span><del>-    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:
</del><ins>+    return new Set(this._knownTabClassesByType.values());
+}
+
+WebInspector._createTabContentViewForType = function(tabType)
+{
+    let tabClass = this._knownTabClassesByType.get(tabType);
+    if (!tabClass) {
</ins><span class="cx">         console.error(&quot;Unknown tab type&quot;, tabType);
</span><ins>+        return null;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    return null;
</del><ins>+    console.assert(WebInspector.TabContentView.isPrototypeOf(tabClass));
+    return new tabClass;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> WebInspector._rememberOpenTabs = function()
</span><span class="cx"> {
</span><del>-    var openTabs = [];
</del><ins>+    let openTabs = [];
</ins><span class="cx"> 
</span><del>-    for (var tabBarItem of this.tabBar.tabBarItems) {
-        var tabContentView = tabBarItem.representedObject;
</del><ins>+    for (let tabBarItem of this.tabBar.tabBarItems) {
+        let tabContentView = tabBarItem.representedObject;
</ins><span class="cx">         if (!(tabContentView instanceof WebInspector.TabContentView))
</span><span class="cx">             continue;
</span><del>-        if (tabContentView instanceof WebInspector.SettingsTabContentView || tabContentView instanceof WebInspector.NewTabContentView)
</del><ins>+        if (!tabContentView.constructor.shouldSaveTab())
</ins><span class="cx">             continue;
</span><span class="cx">         console.assert(tabContentView.type, &quot;Tab type can't be null, undefined, or empty string&quot;, tabContentView.type, tabContentView);
</span><span class="cx">         openTabs.push(tabContentView.type);
</span><span class="lines">@@ -482,11 +484,10 @@
</span><span class="cx"> 
</span><span class="cx"> WebInspector._updateNewTabButtonState = function(event)
</span><span class="cx"> {
</span><del>-    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;
</del><ins>+    let allTabs = [...this._knownTabClassesByType.values()];
+    let addableTabs = allTabs.filter((tabClass) =&gt; !tabClass.isEphemeral());
+    let canMakeNewTab = addableTabs.some((tabClass) =&gt; this.isNewTabWithTypeAllowed(tabClass.Type));
+    this.tabBar.newTabItem.disabled = !canMakeNewTab;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> WebInspector._newTabItemClicked = function(event)
</span><span class="lines">@@ -500,9 +501,32 @@
</span><span class="cx">     this.showNewTabTab();
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+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();
+}
+
</ins><span class="cx"> WebInspector.showNewTabTab = function(shouldAnimate)
</span><span class="cx"> {
</span><del>-    var tabContentView = this.tabBrowser.bestTabContentViewForClass(WebInspector.NewTabContentView);
</del><ins>+    let tabContentView = this.tabBrowser.bestTabContentViewForClass(WebInspector.NewTabContentView);
</ins><span class="cx">     if (!tabContentView)
</span><span class="cx">         tabContentView = new WebInspector.NewTabContentView;
</span><span class="cx">     this.tabBrowser.showTabForContentView(tabContentView, !shouldAnimate);
</span><span class="lines">@@ -510,15 +534,16 @@
</span><span class="cx"> 
</span><span class="cx"> WebInspector.isNewTabWithTypeAllowed = function(tabType)
</span><span class="cx"> {
</span><del>-    if (!this.isTabTypeAllowed(tabType))
</del><ins>+    let tabClass = this._knownTabClassesByType.get(tabType);
+    if (!tabClass || !tabClass.isTabAllowed())
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="cx">     // Only allow one tab per class for now.
</span><del>-    for (var tabBarItem of this.tabBar.tabBarItems) {
-        var tabContentView = tabBarItem.representedObject;
</del><ins>+    for (let tabBarItem of this.tabBar.tabBarItems) {
+        let tabContentView = tabBarItem.representedObject;
</ins><span class="cx">         if (!(tabContentView instanceof WebInspector.TabContentView))
</span><span class="cx">             continue;
</span><del>-        if (tabContentView.type === tabType)
</del><ins>+        if (tabContentView.constructor === tabClass)
</ins><span class="cx">             return false;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -533,7 +558,7 @@
</span><span class="cx">     console.assert(!referencedView || referencedView instanceof WebInspector.TabContentView, referencedView);
</span><span class="cx">     console.assert(!shouldReplaceTab || referencedView, &quot;Must provide a reference view to replace a tab.&quot;);
</span><span class="cx"> 
</span><del>-    let tabContentView = this._tabContentViewForType(tabType);
</del><ins>+    let tabContentView = this._createTabContentViewForType(tabType);
</ins><span class="cx">     const suppressAnimations = true;
</span><span class="cx">     let insertionIndex = referencedView ? this.tabBar.tabBarItems.indexOf(referencedView.tabBarItem) : undefined;
</span><span class="cx">     this.tabBrowser.addTabForContentView(tabContentView, suppressAnimations, insertionIndex);
</span><span class="lines">@@ -545,6 +570,21 @@
</span><span class="cx">         this.tabBrowser.showTabForContentView(tabContentView);
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+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);
+}
+
</ins><span class="cx"> WebInspector.activateExtraDomains = function(domains)
</span><span class="cx"> {
</span><span class="cx">     this.hasExtraDomains = true;
</span><span class="lines">@@ -561,26 +601,7 @@
</span><span class="cx"> 
</span><span class="cx">     this._updateReloadToolbarButton();
</span><span class="cx">     this._updateDownloadToolbarButton();
</span><del>-
-    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();
</del><ins>+    this._tryToRestorePendingTabs();
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> WebInspector.contentBrowserTreeElementForRepresentedObject = function(contentBrowser, representedObject)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceBaseObjectjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Object.js (193431 => 193432)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -208,4 +208,5 @@
</span><span class="cx">     PageArchiveStarted: &quot;page-archive-started&quot;,
</span><span class="cx">     PageArchiveEnded: &quot;page-archive-ended&quot;,
</span><span class="cx">     ExtraDomainsActivated: &quot;extra-domains-activated&quot;,
</span><ins>+    TabTypesChanged: &quot;tab-types-changed&quot;,
</ins><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsConsoleTabContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleTabContentView.js (193431 => 193432)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -27,11 +27,20 @@
</span><span class="cx"> {
</span><span class="cx">     constructor(identifier)
</span><span class="cx">     {
</span><del>-        var tabBarItem = new WebInspector.TabBarItem(&quot;Images/Console.svg&quot;, WebInspector.UIString(&quot;Console&quot;));
</del><ins>+        let {image, title} = WebInspector.ConsoleTabContentView.tabInfo();
+        let tabBarItem = new WebInspector.TabBarItem(image, title);
</ins><span class="cx"> 
</span><span class="cx">         super(identifier || &quot;console&quot;, &quot;console&quot;, tabBarItem, null, null, true);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static tabInfo()
+    {
+        return {
+            image: &quot;Images/Console.svg&quot;,
+            title: WebInspector.UIString(&quot;Console&quot;),
+        };
+    }
+
</ins><span class="cx">     // Public
</span><span class="cx"> 
</span><span class="cx">     get type()
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsDebuggerTabContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerTabContentView.js (193431 => 193432)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -27,12 +27,21 @@
</span><span class="cx"> {
</span><span class="cx">     constructor(identifier)
</span><span class="cx">     {
</span><del>-        var tabBarItem = new WebInspector.TabBarItem(&quot;Images/Debugger.svg&quot;, WebInspector.UIString(&quot;Debugger&quot;));
-        var detailsSidebarPanels = [WebInspector.resourceDetailsSidebarPanel, WebInspector.scopeChainDetailsSidebarPanel, WebInspector.probeDetailsSidebarPanel];
</del><ins>+        let {image, title} = WebInspector.DebuggerTabContentView.tabInfo();
+        let tabBarItem = new WebInspector.TabBarItem(image, title);
+        let detailsSidebarPanels = [WebInspector.resourceDetailsSidebarPanel, WebInspector.scopeChainDetailsSidebarPanel, WebInspector.probeDetailsSidebarPanel];
</ins><span class="cx"> 
</span><span class="cx">         super(identifier || &quot;debugger&quot;, &quot;debugger&quot;, tabBarItem, WebInspector.DebuggerSidebarPanel, detailsSidebarPanels);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static tabInfo()
+    {
+        return {
+            image: &quot;Images/Debugger.svg&quot;,
+            title: WebInspector.UIString(&quot;Debugger&quot;),
+        };
+    }
+
</ins><span class="cx">     // Public
</span><span class="cx"> 
</span><span class="cx">     get type()
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsElementsTabContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ElementsTabContentView.js (193431 => 193432)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -27,8 +27,9 @@
</span><span class="cx"> {
</span><span class="cx">     constructor(identifier)
</span><span class="cx">     {
</span><del>-        var tabBarItem = new WebInspector.TabBarItem(&quot;Images/Elements.svg&quot;, WebInspector.UIString(&quot;Elements&quot;));
-        var detailsSidebarPanels = [WebInspector.domNodeDetailsSidebarPanel, WebInspector.cssStyleDetailsSidebarPanel];
</del><ins>+        let {image, title} = WebInspector.ElementsTabContentView.tabInfo();
+        let tabBarItem = new WebInspector.TabBarItem(image, title);
+        let detailsSidebarPanels = [WebInspector.domNodeDetailsSidebarPanel, WebInspector.cssStyleDetailsSidebarPanel];
</ins><span class="cx"> 
</span><span class="cx">         if (WebInspector.layerTreeDetailsSidebarPanel)
</span><span class="cx">             detailsSidebarPanels.push(WebInspector.layerTreeDetailsSidebarPanel);
</span><span class="lines">@@ -41,6 +42,19 @@
</span><span class="cx">         this._showDOMTreeContentView();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static tabInfo()
+    {
+        return {
+            image: &quot;Images/Elements.svg&quot;,
+            title: WebInspector.UIString(&quot;Elements&quot;),
+        };
+    }
+
+    static isTabAllowed()
+    {
+        return !!window.DOMAgent;
+    }
+
</ins><span class="cx">     // Public
</span><span class="cx"> 
</span><span class="cx">     get type()
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsNetworkTabContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTabContentView.js (193431 => 193432)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -27,12 +27,26 @@
</span><span class="cx"> {
</span><span class="cx">     constructor(identifier)
</span><span class="cx">     {
</span><del>-        var tabBarItem = new WebInspector.TabBarItem(&quot;Images/Network.svg&quot;, WebInspector.UIString(&quot;Network&quot;));
-        var detailsSidebarPanels = [WebInspector.resourceDetailsSidebarPanel, WebInspector.probeDetailsSidebarPanel];
</del><ins>+        let {image, title} = WebInspector.NetworkTabContentView.tabInfo();
+        let tabBarItem = new WebInspector.TabBarItem(image, title);
+        let detailsSidebarPanels = [WebInspector.resourceDetailsSidebarPanel, WebInspector.probeDetailsSidebarPanel];
</ins><span class="cx"> 
</span><span class="cx">         super(identifier || &quot;network&quot;, &quot;network&quot;, tabBarItem, WebInspector.NetworkSidebarPanel, detailsSidebarPanels);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static tabInfo()
+    {
+        return {
+            image: &quot;Images/Network.svg&quot;,
+            title: WebInspector.UIString(&quot;Network&quot;),
+        };
+    }
+
+    static isTabAllowed()
+    {
+        return !!window.NetworkAgent &amp;&amp; !!window.PageAgent;
+    }
+
</ins><span class="cx">     // Public
</span><span class="cx"> 
</span><span class="cx">     get type()
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsNewTabContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NewTabContentView.js (193431 => 193432)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -27,43 +27,34 @@
</span><span class="cx"> {
</span><span class="cx">     constructor(identifier)
</span><span class="cx">     {
</span><del>-        var tabBarItem = new WebInspector.TabBarItem(&quot;Images/NewTab.svg&quot;, WebInspector.UIString(&quot;New Tab&quot;));
</del><ins>+        let {image, title} = WebInspector.NewTabContentView.tabInfo();
+        let tabBarItem = new WebInspector.TabBarItem(image, title);
</ins><span class="cx">         tabBarItem.isDefaultTab = true;
</span><span class="cx"> 
</span><span class="cx">         super(identifier || &quot;new-tab&quot;, &quot;new-tab&quot;, tabBarItem);
</span><span class="cx"> 
</span><del>-        var allowedNewTabs = [
-            {image: &quot;Images/Console.svg&quot;, title: WebInspector.UIString(&quot;Console&quot;), type: WebInspector.ConsoleTabContentView.Type},
-            {image: &quot;Images/Debugger.svg&quot;, title: WebInspector.UIString(&quot;Debugger&quot;), type: WebInspector.DebuggerTabContentView.Type},
-            {image: &quot;Images/Elements.svg&quot;, title: WebInspector.UIString(&quot;Elements&quot;), type: WebInspector.ElementsTabContentView.Type},
-            {image: &quot;Images/Network.svg&quot;, title: WebInspector.UIString(&quot;Network&quot;), type: WebInspector.NetworkTabContentView.Type},
-            {image: &quot;Images/Resources.svg&quot;, title: WebInspector.UIString(&quot;Resources&quot;), type: WebInspector.ResourcesTabContentView.Type},
-            {image: &quot;Images/Storage.svg&quot;, title: WebInspector.UIString(&quot;Storage&quot;), type: WebInspector.StorageTabContentView.Type},
-            {image: &quot;Images/Timeline.svg&quot;, title: WebInspector.UIString(&quot;Timelines&quot;), type: WebInspector.TimelineTabContentView.Type}
-        ];
</del><ins>+        WebInspector.notifications.addEventListener(WebInspector.Notification.TabTypesChanged, this._updateShownTabs.bind(this));
</ins><span class="cx"> 
</span><del>-        allowedNewTabs.sort(function(a, b) { return a.title.localeCompare(b.title); });
</del><ins>+        this._tabElementsByTabClass = new Map;
+        this._updateShownTabs();
+    }
</ins><span class="cx"> 
</span><del>-        for (var info of allowedNewTabs) {
-            if (!WebInspector.isTabTypeAllowed(info.type))
-                continue;
</del><ins>+    static tabInfo()
+    {
+        return {
+            image: &quot;Images/NewTab.svg&quot;,
+            title: WebInspector.UIString(&quot;New Tab&quot;),
+        };
+    }
</ins><span class="cx"> 
</span><del>-            var tabItemElement = document.createElement(&quot;div&quot;);
-            tabItemElement.classList.add(WebInspector.NewTabContentView.TabItemStyleClassName);
-            tabItemElement.addEventListener(&quot;click&quot;, this._createNewTabWithType.bind(this, info.type));
-            tabItemElement[WebInspector.NewTabContentView.TypeSymbol] = info.type;
</del><ins>+    static isEphemeral()
+    {
+        return true;
+    }
</ins><span class="cx"> 
</span><del>-            var boxElement = tabItemElement.appendChild(document.createElement(&quot;div&quot;));
-            boxElement.classList.add(&quot;box&quot;);
-
-            var imageElement = boxElement.appendChild(document.createElement(&quot;img&quot;));
-            imageElement.src = info.image;
-
-            var labelElement = tabItemElement.appendChild(document.createElement(&quot;label&quot;));
-            labelElement.textContent = info.title;
-
-            this.element.appendChild(tabItemElement);
-        }
</del><ins>+    static shouldSaveTab()
+    {
+        return false;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Public
</span><span class="lines">@@ -93,9 +84,32 @@
</span><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    get tabItemElements()
</del><ins>+    layout()
</ins><span class="cx">     {
</span><del>-        return Array.from(this.element.querySelectorAll(&quot;.&quot; + WebInspector.NewTabContentView.TabItemStyleClassName));
</del><ins>+        this._tabElementsByTabClass.clear();
+        this.element.removeChildren();
+
+        for (let tabClass of this._shownTabClasses) {
+            let tabItemElement = document.createElement(&quot;div&quot;);
+            tabItemElement.classList.add(&quot;tab-item&quot;);
+            tabItemElement.addEventListener(&quot;click&quot;, this._createNewTabWithType.bind(this, tabClass.Type));
+            tabItemElement[WebInspector.NewTabContentView.TypeSymbol] = tabClass.Type;
+
+            let boxElement = tabItemElement.appendChild(document.createElement(&quot;div&quot;));
+            boxElement.classList.add(&quot;box&quot;);
+
+            let info = tabClass.tabInfo();
+            let imageElement = boxElement.appendChild(document.createElement(&quot;img&quot;));
+            imageElement.src = info.image;
+
+            let labelElement = tabItemElement.appendChild(document.createElement(&quot;label&quot;));
+            labelElement.textContent = info.title;
+
+            this.element.appendChild(tabItemElement);
+            this._tabElementsByTabClass.set(tabClass, tabItemElement);
+        }
+
+        this._updateTabItems();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Private
</span><span class="lines">@@ -114,19 +128,29 @@
</span><span class="cx">         WebInspector.createNewTabWithType(tabType, options);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    _updateShownTabs()
+    {
+        let allTabClasses = [...WebInspector.knownTabClasses()];
+        let allowedTabClasses = allTabClasses.filter((tabClass) =&gt; tabClass.isTabAllowed() &amp;&amp; !tabClass.isEphemeral());
+        allowedTabClasses.sort((a, b) =&gt; a.tabInfo().title.localeCompare(b.tabInfo().title));
+
+        if (Object.shallowEqual(this._shownTabClasses, allowedTabClasses))
+            return;
+
+        this._shownTabClasses = allowedTabClasses;
+        this.needsLayout();
+    }
+
</ins><span class="cx">     _allowableTabTypes()
</span><span class="cx">     {
</span><del>-        let tabItemElements = this.tabItemElements;
-        let tabTypes = tabItemElements.map((tabItemElement) =&gt; tabItemElement[WebInspector.NewTabContentView.TypeSymbol]);
</del><ins>+        let tabTypes = this._shownTabClasses.map((tabClass) =&gt; tabClass.Type);
</ins><span class="cx">         return tabTypes.filter((type) =&gt; WebInspector.isNewTabWithTypeAllowed(type));
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     _updateTabItems()
</span><span class="cx">     {
</span><del>-        let tabItemElements = this.tabItemElements;
-        for (let tabItemElement of tabItemElements) {
-            let type = tabItemElement[WebInspector.NewTabContentView.TypeSymbol];
-            let allowed = WebInspector.isNewTabWithTypeAllowed(type);
</del><ins>+        for (let [tabClass, tabItemElement] of this._tabElementsByTabClass.entries()) {
+            let allowed = WebInspector.isNewTabWithTypeAllowed(tabClass.Type);
</ins><span class="cx">             tabItemElement.classList.toggle(WebInspector.NewTabContentView.DisabledStyleClassName, !allowed);
</span><span class="cx">         }
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsResourcesTabContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ResourcesTabContentView.js (193431 => 193432)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -27,8 +27,9 @@
</span><span class="cx"> {
</span><span class="cx">     constructor(identifier)
</span><span class="cx">     {
</span><del>-        var tabBarItem = new WebInspector.TabBarItem(&quot;Images/Resources.svg&quot;, WebInspector.UIString(&quot;Resources&quot;));
-        var detailsSidebarPanels = [WebInspector.resourceDetailsSidebarPanel, WebInspector.probeDetailsSidebarPanel];
</del><ins>+        let {image, title} = WebInspector.ResourcesTabContentView.tabInfo();
+        let tabBarItem = new WebInspector.TabBarItem(image, title);
+        let detailsSidebarPanels = [WebInspector.resourceDetailsSidebarPanel, WebInspector.probeDetailsSidebarPanel];
</ins><span class="cx"> 
</span><span class="cx">         // FIXME: Until ContentFlows are moved to the Elements tab, these details sidebar panels need to be included.
</span><span class="cx">         detailsSidebarPanels = detailsSidebarPanels.concat([WebInspector.domNodeDetailsSidebarPanel, WebInspector.cssStyleDetailsSidebarPanel]);
</span><span class="lines">@@ -38,6 +39,14 @@
</span><span class="cx">         super(identifier || &quot;resources&quot;, &quot;resources&quot;, tabBarItem, WebInspector.ResourceSidebarPanel, detailsSidebarPanels);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static tabInfo()
+    {
+        return {
+            image: &quot;Images/Resources.svg&quot;,
+            title: WebInspector.UIString(&quot;Resources&quot;),
+        };
+    }
+
</ins><span class="cx">     // Public
</span><span class="cx"> 
</span><span class="cx">     get type()
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsSearchTabContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SearchTabContentView.js (193431 => 193432)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -27,8 +27,9 @@
</span><span class="cx"> {
</span><span class="cx">     constructor(identifier)
</span><span class="cx">     {
</span><del>-        var tabBarItem = new WebInspector.TabBarItem(&quot;Images/SearchResults.svg&quot;, WebInspector.UIString(&quot;Search&quot;));
-        var detailsSidebarPanels = [WebInspector.resourceDetailsSidebarPanel, WebInspector.probeDetailsSidebarPanel,
</del><ins>+        let {image, title} = WebInspector.SearchTabContentView.tabInfo();
+        let tabBarItem = new WebInspector.TabBarItem(image, title);
+        let detailsSidebarPanels = [WebInspector.resourceDetailsSidebarPanel, WebInspector.probeDetailsSidebarPanel,
</ins><span class="cx">             WebInspector.domNodeDetailsSidebarPanel, WebInspector.cssStyleDetailsSidebarPanel];
</span><span class="cx"> 
</span><span class="cx">         if (WebInspector.layerTreeDetailsSidebarPanel)
</span><span class="lines">@@ -37,6 +38,19 @@
</span><span class="cx">         super(identifier || &quot;search&quot;, &quot;search&quot;, tabBarItem, WebInspector.SearchSidebarPanel, detailsSidebarPanels);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static tabInfo()
+    {
+        return {
+            image: &quot;Images/SearchResults.svg&quot;,
+            title: WebInspector.UIString(&quot;Search&quot;),
+        };
+    }
+
+    static isEphemeral()
+    {
+        return true;
+    }
+
</ins><span class="cx">     // Public
</span><span class="cx"> 
</span><span class="cx">     get type()
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsSettingsTabContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.js (193431 => 193432)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -32,6 +32,17 @@
</span><span class="cx">         super(identifier || &quot;settings&quot;, &quot;settings&quot;, tabBarItem);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static isTabAllowed()
+    {
+        // FIXME (149284): This tab isn't ready to be shown yet.
+        return false;
+    }
+
+    static shouldSaveTab()
+    {
+        return false;
+    }
+
</ins><span class="cx">     // Public
</span><span class="cx"> 
</span><span class="cx">     get type()
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsStorageTabContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/StorageTabContentView.js (193431 => 193432)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -27,12 +27,26 @@
</span><span class="cx"> {
</span><span class="cx">     constructor(identifier)
</span><span class="cx">     {
</span><del>-        var tabBarItem = new WebInspector.TabBarItem(&quot;Images/Storage.svg&quot;, WebInspector.UIString(&quot;Storage&quot;));
-        var detailsSidebarPanels = [WebInspector.applicationCacheDetailsSidebarPanel];
</del><ins>+        let {image, title} = WebInspector.StorageTabContentView.tabInfo();
+        let tabBarItem = new WebInspector.TabBarItem(image, title);
+        let detailsSidebarPanels = [WebInspector.applicationCacheDetailsSidebarPanel];
</ins><span class="cx"> 
</span><span class="cx">         super(identifier || &quot;storage&quot;, &quot;storage&quot;, tabBarItem, WebInspector.StorageSidebarPanel, detailsSidebarPanels);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static tabInfo()
+    {
+        return {
+            image: &quot;Images/Storage.svg&quot;,
+            title: WebInspector.UIString(&quot;Storage&quot;),
+        };
+    }
+
+    static isTabAllowed()
+    {
+        return !!window.DOMStorageAgent || !!window.DatabaseAgent || !!window.IndexedDBAgent;
+    }
+
</ins><span class="cx">     // Public
</span><span class="cx"> 
</span><span class="cx">     get type()
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsTabBrowserjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TabBrowser.js (193431 => 193432)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -160,6 +160,13 @@
</span><span class="cx"> 
</span><span class="cx">         this._tabBar.selectedTabBarItem = tabContentView.tabBarItem;
</span><span class="cx"> 
</span><ins>+        // FIXME: this is a workaround for &lt;https://webkit.org/b/151876&gt;.
+        // 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();
</ins><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsTabContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TabContentView.js (193431 => 193432)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -55,6 +55,24 @@
</span><span class="cx">         this._cookieSetting = new WebInspector.Setting(identifier + &quot;-tab-cookie&quot;, {});
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    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;
+    }
+
</ins><span class="cx">     // Public
</span><span class="cx"> 
</span><span class="cx">     get type()
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsTimelineTabContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.js (193431 => 193432)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -27,12 +27,26 @@
</span><span class="cx"> {
</span><span class="cx">     constructor(identifier)
</span><span class="cx">     {
</span><del>-        var tabBarItem = new WebInspector.TabBarItem(&quot;Images/Timeline.svg&quot;, WebInspector.UIString(&quot;Timelines&quot;));
-        var detailsSidebarPanels = [WebInspector.resourceDetailsSidebarPanel, WebInspector.probeDetailsSidebarPanel];
</del><ins>+        let {image, title} = WebInspector.TimelineTabContentView.tabInfo();
+        let tabBarItem = new WebInspector.TabBarItem(image, title);
+        let detailsSidebarPanels = [WebInspector.resourceDetailsSidebarPanel, WebInspector.probeDetailsSidebarPanel];
</ins><span class="cx"> 
</span><span class="cx">         super(identifier || &quot;timeline&quot;, &quot;timeline&quot;, tabBarItem, WebInspector.TimelineSidebarPanel, detailsSidebarPanels);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static tabInfo()
+    {
+        return {
+            image: &quot;Images/Timeline.svg&quot;,
+            title: WebInspector.UIString(&quot;Timelines&quot;),
+        };
+    }
+
+    static isTabAllowed()
+    {
+        return !!window.TimelineAgent;
+    }
+
</ins><span class="cx">     // Public
</span><span class="cx"> 
</span><span class="cx">     get type()
</span></span></pre>
</div>
</div>

</body>
</html>