Bug 1392352 - Part 2.1 - To fold: use JS tabbrowser implementation;r=mconley,r=dao draft
authorBrian Grinstead <bgrinstead@mozilla.com>
Thu, 05 Oct 2017 15:58:46 -0700
changeset 760460 3c7adddf2d137919508c6ee64eec40a9ce62f3ed
parent 760459 26976f26c88be8ce255b862a862208eb6a5f2db4
child 760461 bfe1433b7ccb93db1fda0e59ae23bc41aeecfdaf
push id100651
push userbgrinstead@mozilla.com
push dateTue, 27 Feb 2018 17:19:18 +0000
reviewersmconley, dao
bugs1392352
milestone60.0a1
Bug 1392352 - Part 2.1 - To fold: use JS tabbrowser implementation;r=mconley,r=dao MozReview-Commit-ID: LhmY9ZfS0rh
browser/base/content/browser-fullScreenAndPointerLock.js
browser/base/content/browser.js
browser/base/content/browser.xul
browser/base/content/global-scripts.inc
browser/base/content/tabbrowser.xml
browser/base/content/test/performance/browser_tabopen_squeeze_reflows.js
browser/base/content/test/performance/browser_tabstrip_overflow_underflow_reflows.js
browser/base/jar.mn
devtools/client/scratchpad/test/browser_scratchpad_contexts.js
testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
toolkit/components/addoncompat/RemoteAddonsParent.jsm
toolkit/components/addoncompat/multiprocessShims.js
toolkit/modules/PopupNotifications.jsm
--- a/browser/base/content/browser-fullScreenAndPointerLock.js
+++ b/browser/base/content/browser-fullScreenAndPointerLock.js
@@ -371,17 +371,17 @@ var FullScreen = {
         // The event target is the element which requested the DOM
         // fullscreen. If we were entering DOM fullscreen for a remote
         // browser, the target would be `gBrowser` and the original
         // target would be the browser which was the parameter of
         // `remoteFrameFullscreenChanged` call. If the fullscreen
         // request was initiated from an in-process browser, we need
         // to get its corresponding browser here.
         let browser;
-        if (event.target == gBrowser) {
+        if (event.target == gBrowser.container) {
           browser = event.originalTarget;
         } else {
           let topWin = event.target.ownerGlobal.top;
           browser = gBrowser.getBrowserForContentWindow(topWin);
         }
         TelemetryStopwatch.start("FULLSCREEN_CHANGE_MS");
         this.enterDomFullscreen(browser);
         break;
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -216,32 +216,32 @@ XPCOMUtils.defineLazyGetter(this, "Win7F
       }
     };
   }
   return null;
 });
 
 const nsIWebNavigation = Ci.nsIWebNavigation;
 
+var gBrowser = null; // Will be instantiated by the <tabbbrowser> constructor.
 var gLastValidURLStr = "";
 var gInPrintPreviewMode = false;
 var gContextMenu = null; // nsContextMenu instance
 var gMultiProcessBrowser =
   window.QueryInterface(Ci.nsIInterfaceRequestor)
         .getInterface(Ci.nsIWebNavigation)
         .QueryInterface(Ci.nsILoadContext)
         .useRemoteTabs;
 
 if (AppConstants.platform != "macosx") {
   var gEditUIVisible = true;
 }
 
-/* globals gBrowser, gNavToolbox, gURLBar:true */
+/* globals gNavToolbox, gURLBar:true */
 [
-  ["gBrowser",            "content"],
   ["gNavToolbox",         "navigator-toolbox"],
   ["gURLBar",             "urlbar"],
 ].forEach(function(elementGlobal) {
   var [name, id] = elementGlobal;
   Object.defineProperty(window, name, {
     configurable: true,
     enumerable: true,
     get() {
@@ -1191,18 +1191,17 @@ var gBrowserInit = {
           .getInterface(nsIWebNavigation)
           .QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
           .QueryInterface(Ci.nsIInterfaceRequestor)
           .getInterface(Ci.nsIXULWindow)
           .XULBrowserWindow = window.XULBrowserWindow;
     window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow =
       new nsBrowserAccess();
 
-    let initBrowser =
-      document.getAnonymousElementByAttribute(gBrowser, "anonid", "initialBrowser");
+    let initBrowser = gBrowser.initialBrowser;
 
     // remoteType and sameProcessAsFrameLoader are passed through to
     // updateBrowserRemoteness as part of an options object, which itself defaults
     // to an empty object. So defaulting them to undefined here will cause the
     // default behavior in updateBrowserRemoteness if they don't get set.
     let isRemote = gMultiProcessBrowser;
     let remoteType;
     let sameProcessAsFrameLoader;
@@ -1296,17 +1295,17 @@ var gBrowserInit = {
     mm.loadFrameScript("chrome://browser/content/content-UITour.js", true);
     mm.loadFrameScript("chrome://global/content/content-HybridContentTelemetry.js", true);
     mm.loadFrameScript("chrome://global/content/manifestMessages.js", true);
 
     window.messageManager.addMessageListener("Browser:LoadURI", RedirectLoad);
 
     if (!gMultiProcessBrowser) {
       // There is a Content:Click message manually sent from content.
-      Services.els.addSystemEventListener(gBrowser, "click", contentAreaClick, true);
+      Services.els.addSystemEventListener(gBrowser.container, "click", contentAreaClick, true);
     }
 
     // hook up UI through progress listener
     gBrowser.addProgressListener(window.XULBrowserWindow);
     gBrowser.addTabsProgressListener(window.TabsProgressListener);
 
     SidebarUI.init();
 
@@ -4337,25 +4336,21 @@ var XULBrowserWindow = {
     return this.canViewSource = document.getElementById("canViewSource");
   },
 
   setJSStatus() {
     // unsupported
   },
 
   forceInitialBrowserRemote(aRemoteType) {
-    let initBrowser =
-      document.getAnonymousElementByAttribute(gBrowser, "anonid", "initialBrowser");
-    gBrowser.updateBrowserRemoteness(initBrowser, true, { remoteType: aRemoteType });
+    gBrowser.updateBrowserRemoteness(gBrowser.initialBrowser, true, { remoteType: aRemoteType });
   },
 
   forceInitialBrowserNonRemote(aOpener) {
-    let initBrowser =
-      document.getAnonymousElementByAttribute(gBrowser, "anonid", "initialBrowser");
-    gBrowser.updateBrowserRemoteness(initBrowser, false, { opener: aOpener });
+    gBrowser.updateBrowserRemoteness(gBrowser.initialBrowser, false, { opener: aOpener });
   },
 
   setDefaultStatus(status) {
     this.defaultStatus = status;
     this.updateStatusField();
   },
 
   setOverLink(url, anchorElt) {
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -9,16 +9,17 @@
 <?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/content/downloads/downloads.css"?>
 <?xml-stylesheet href="chrome://browser/content/places/places.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/content/usercontext/usercontext.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/skin/controlcenter/panel.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/skin/customizableui/panelUI.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/skin/downloads/downloads.css"?>
 <?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/content/tabbrowser.css" type="text/css"?>
 
 <?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
 <?xul-overlay href="chrome://browser/content/baseMenuOverlay.xul"?>
 <?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
 
 # All DTD information is stored in a separate file so that it can be shared by
 # hiddenWindow.xul.
 #include browser-doctype.inc
@@ -1204,18 +1205,17 @@
         </sidebarheader>
         <browser id="sidebar" flex="1" autoscroll="false" disablehistory="true" disablefullscreen="true"
                   style="min-width: 14em; width: 18em; max-width: 36em;" tooltip="aHTMLTooltip"/>
       </vbox>
 
       <splitter id="sidebar-splitter" class="chromeclass-extrachrome sidebar-splitter" hidden="true"/>
       <vbox id="appcontent" flex="1">
         <notificationbox id="high-priority-global-notificationbox" notificationside="top"/>
-        <tabbrowser id="content"
-                    flex="1" contenttooltip="aHTMLTooltip"
+        <tabbrowser flex="1" contenttooltip="aHTMLTooltip"
                     tabcontainer="tabbrowser-tabs"
                     contentcontextmenu="contentAreaContextMenu"
                     autocompletepopup="PopupAutoComplete"
                     selectmenulist="ContentSelectDropdown"
                     datetimepicker="DateTimePickerPanel"/>
       </vbox>
       <vbox id="browser-border-end" hidden="true" layer="true"/>
     </hbox>
old mode 100755
new mode 100644
--- a/browser/base/content/global-scripts.inc
+++ b/browser/base/content/global-scripts.inc
@@ -6,16 +6,17 @@
 # If you update this list, you may need to add a mapping within the following
 # file so that ESLint works correctly:
 # tools/lint/eslint/eslint-plugin-mozilla/lib/environments/browser-window.js
 
 <script type="application/javascript">
 Components.utils.import("resource://gre/modules/Services.jsm");
 
 for (let script of [
+  "chrome://browser/content/tabbrowser.js",
   "chrome://browser/content/browser.js",
 
   "chrome://browser/content/browser-captivePortal.js",
   "chrome://browser/content/browser-compacttheme.js",
   "chrome://browser/content/browser-feeds.js",
   "chrome://browser/content/browser-media.js",
   "chrome://browser/content/browser-pageActions.js",
   "chrome://browser/content/browser-places.js",
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -19,16 +19,52 @@
   <binding id="tabbrowser">
     <resources>
       <stylesheet src="chrome://browser/content/tabbrowser.css"/>
     </resources>
 
     <content>
       <xul:tabbox anonid="tabbox" class="tabbrowser-tabbox"
                   flex="1" eventnode="document" xbl:inherits="tabcontainer"
+                  onselect="if (event.target.localName == 'tabpanels') gBrowser.updateCurrentBrowser();">
+        <xul:tabpanels flex="1" class="plain" selectedIndex="0" anonid="panelcontainer">
+          <xul:notificationbox flex="1" notificationside="top">
+            <xul:hbox flex="1" class="browserSidebarContainer">
+              <xul:vbox flex="1" class="browserContainer">
+                <xul:stack flex="1" class="browserStack" anonid="browserStack">
+                  <xul:browser anonid="initialBrowser" type="content" message="true" messagemanagergroup="browsers"
+                               primary="true"
+                               xbl:inherits="tooltip=contenttooltip,contextmenu=contentcontextmenu,autocompletepopup,selectmenulist,datetimepicker"/>
+                </xul:stack>
+              </xul:vbox>
+            </xul:hbox>
+          </xul:notificationbox>
+        </xul:tabpanels>
+      </xul:tabbox>
+      <children/>
+    </content>
+    <implementation>
+      <constructor>
+        gBrowser = new TabBrowser(this);
+      </constructor>
+      <destructor>
+        gBrowser.disconnectedCallback();
+      </destructor>
+    </implementation>
+  </binding>
+
+  <binding id="tabbrowser-TO-DELETE">
+    <resources>
+      <stylesheet src="chrome://browser/content/tabbrowser.css"/>
+    </resources>
+
+    <content>
+      <xul:stringbundle anonid="tbstringbundle" src="chrome://browser/locale/tabbrowser.properties"/>
+      <xul:tabbox anonid="tabbox" class="tabbrowser-tabbox"
+                  flex="1" eventnode="document" xbl:inherits="handleCtrlPageUpDown,tabcontainer"
                   onselect="if (event.target.localName == 'tabpanels') this.parentNode.updateCurrentBrowser();">
         <xul:tabpanels flex="1" class="plain" selectedIndex="0" anonid="panelcontainer">
           <xul:notificationbox flex="1" notificationside="top">
             <xul:hbox flex="1" class="browserSidebarContainer">
               <xul:vbox flex="1" class="browserContainer">
                 <xul:stack flex="1" class="browserStack" anonid="browserStack">
                   <xul:browser anonid="initialBrowser" type="content" message="true" messagemanagergroup="browsers"
                                primary="true" blank="true"
@@ -6459,20 +6495,16 @@
       </constructor>
 
       <destructor>
         <![CDATA[
           Services.prefs.removeObserver("privacy.userContext", this);
         ]]>
       </destructor>
 
-      <field name="tabbrowser" readonly="true">
-        gBrowser;
-      </field>
-
       <field name="tabbox" readonly="true">
         this.tabbrowser.tabbox;
       </field>
 
       <field name="contextMenu" readonly="true">
         document.getElementById("tabContextMenu");
       </field>
 
@@ -6489,16 +6521,22 @@
       <field name="restoreTabsButton">
         document.getAnonymousElementByAttribute(this, "anonid", "restore-tabs-button");
       </field>
       <field name="_restoreTabsButtonWrapperWidth">0</field>
       <field name="windowUtils">
         window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
       </field>
 
+      <property name="tabbrowser" readonly="true">
+        <getter>
+          return window.gBrowser;
+        </getter>
+      </property>
+
       <property name="restoreTabsButtonWrapperWidth" readonly="true">
         <getter>
           if (!this._restoreTabsButtonWrapperWidth) {
             this._restoreTabsButtonWrapperWidth = this.windowUtils
               .getBoundsWithoutFlushing(this.restoreTabsButton.parentNode)
               .width;
           }
           return this._restoreTabsButtonWrapperWidth;
--- a/browser/base/content/test/performance/browser_tabopen_squeeze_reflows.js
+++ b/browser/base/content/test/performance/browser_tabopen_squeeze_reflows.js
@@ -9,17 +9,17 @@
  * See https://developer.mozilla.org/en-US/Firefox/Performance_best_practices_for_Firefox_fe_engineers
  * for tips on how to do that.
  */
 const EXPECTED_REFLOWS = [
   {
     stack: [
       "select@chrome://global/content/bindings/textbox.xml",
       "focusAndSelectUrlBar@chrome://browser/content/browser.js",
-      "_adjustFocusAfterTabSwitch@chrome://browser/content/tabbrowser.xml",
+      "_adjustFocusAfterTabSwitch@chrome://browser/content/tabbrowser.js",
     ],
   }
 ];
 
 /*
  * This test ensures that there are no unexpected
  * uninterruptible reflows when opening a new tab that will
  * cause the existing tabs to squeeze smaller.
--- a/browser/base/content/test/performance/browser_tabstrip_overflow_underflow_reflows.js
+++ b/browser/base/content/test/performance/browser_tabstrip_overflow_underflow_reflows.js
@@ -9,17 +9,17 @@
  * See https://developer.mozilla.org/en-US/Firefox/Performance_best_practices_for_Firefox_fe_engineers
  * for tips on how to do that.
  */
 const EXPECTED_OVERFLOW_REFLOWS = [
   {
     stack: [
       "select@chrome://global/content/bindings/textbox.xml",
       "focusAndSelectUrlBar@chrome://browser/content/browser.js",
-      "_adjustFocusAfterTabSwitch@chrome://browser/content/tabbrowser.xml",
+      "_adjustFocusAfterTabSwitch@chrome://browser/content/tabbrowser.js",
     ]
   },
 ];
 
 const EXPECTED_UNDERFLOW_REFLOWS = [
   /**
    * Nothing here! Please don't add anything new!
    */
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -112,16 +112,17 @@ browser.jar:
         content/browser/safeMode.js                   (content/safeMode.js)
         content/browser/safeMode.xul                  (content/safeMode.xul)
         content/browser/sanitize.xul                  (content/sanitize.xul)
         content/browser/sanitizeDialog.js             (content/sanitizeDialog.js)
         content/browser/sanitizeDialog.css            (content/sanitizeDialog.css)
         content/browser/contentSearchUI.js            (content/contentSearchUI.js)
         content/browser/contentSearchUI.css           (content/contentSearchUI.css)
         content/browser/tabbrowser.css                (content/tabbrowser.css)
+        content/browser/tabbrowser.js                 (content/tabbrowser.js)
         content/browser/tabbrowser.xml                (content/tabbrowser.xml)
 *       content/browser/urlbarBindings.xml            (content/urlbarBindings.xml)
         content/browser/utilityOverlay.js             (content/utilityOverlay.js)
         content/browser/web-panels.js                 (content/web-panels.js)
 *       content/browser/web-panels.xul                (content/web-panels.xul)
         content/browser/webext-panels.js              (content/webext-panels.js)
 *       content/browser/webext-panels.xul             (content/webext-panels.xul)
 *       content/browser/baseMenuOverlay.xul           (content/baseMenuOverlay.xul)
--- a/devtools/client/scratchpad/test/browser_scratchpad_contexts.js
+++ b/devtools/client/scratchpad/test/browser_scratchpad_contexts.js
@@ -86,17 +86,17 @@ function runTests() {
     method: "run",
     prepare: function* () {
       sp.editor.replaceText("gBrowser", sp.editor.getPosition(7));
 
       is(sp.getText(), "window.gBrowser",
          "setText() worked with no end for the replace range");
     },
     then: function* ([, , result]) {
-      is(result.class, "XULElement",
+      is(result.class, "Object",
          "chrome context has access to chrome objects");
     }
   }, {
     method: "run",
     prepare: function* () {
       // Check that the sandbox is cached.
       sp.editor.setText("typeof foobarBug636725cache;");
     },
--- a/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
+++ b/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
@@ -139,17 +139,17 @@ var BrowserTestUtils = {
    *        false.
    *
    * @return {Promise}
    *         Resolves when the tab is ready and loaded as necessary.
    * @resolves The new tab.
    */
   openNewForegroundTab(tabbrowser, ...args) {
     let options;
-    if (tabbrowser instanceof Ci.nsIDOMXULElement) {
+    if (tabbrowser.ownerGlobal && tabbrowser === tabbrowser.ownerGlobal.gBrowser) {
       // tabbrowser is a tabbrowser, read the rest of the arguments from args.
       let [
         opening = "about:blank",
         waitForLoad = true,
         waitForStateStop = false,
         forceNewProcess = false,
       ] = args;
 
--- a/toolkit/components/addoncompat/RemoteAddonsParent.jsm
+++ b/toolkit/components/addoncompat/RemoteAddonsParent.jsm
@@ -434,23 +434,27 @@ var EventTargetParent = {
       }
 
       // Check if |target| is somewhere on the path from the
       // <tabbrowser> up to the root element.
       let window = target.ownerGlobal;
 
       // Some non-browser windows define gBrowser globals which are not elements
       // and can't be passed to target.contains().
-      if (window &&
-          window.gBrowser instanceof Ci.nsIDOMXULElement &&
-          target.contains(window.gBrowser)) {
+      if (window && window.gBrowser &&
+          window.gBrowser.container instanceof Ci.nsIDOMXULElement &&
+          target.contains(window.gBrowser.container)) {
         return window;
       }
     }
 
+    if (target.ownerGlobal && target === target.ownerGlobal.gBrowser) {
+      return target.ownerGlobal;
+    }
+
     return null;
   },
 
   // When a given event fires in the child, we fire it on the
   // <browser> element and the window since those are the two possible
   // results of redirectEventTarget.
   getTargets(browser) {
     let window = browser.ownerGlobal;
--- a/toolkit/components/addoncompat/multiprocessShims.js
+++ b/toolkit/components/addoncompat/multiprocessShims.js
@@ -108,20 +108,20 @@ AddonInterpositionService.prototype = {
     if (Cu.isCrossProcessWrapper(target)) {
       return Cu.getCrossProcessWrapperTag(target);
     }
 
     if (target instanceof Ci.nsIDOMXULElement) {
       if (target.localName == "browser" && target.isRemoteBrowser) {
         return "RemoteBrowserElement";
       }
+    }
 
-      if (target.localName == "tabbrowser") {
-        return "TabBrowserElement";
-      }
+    if (target.ownerGlobal && target === target.ownerGlobal.gBrowser) {
+      return "TabBrowserElement";
     }
 
     if (target instanceof Ci.nsIDOMChromeWindow && target.gMultiProcessBrowser) {
       return "ChromeWindow";
     }
 
     if (target instanceof Ci.nsIDOMEventTarget) {
       return "EventTarget";
--- a/toolkit/modules/PopupNotifications.jsm
+++ b/toolkit/modules/PopupNotifications.jsm
@@ -183,17 +183,17 @@ Notification.prototype = {
     }
   },
 };
 
 /**
  * The PopupNotifications object manages popup notifications for a given browser
  * window.
  * @param tabbrowser
- *        window's <xul:tabbrowser/>. Used to observe tab switching events and
+ *        window's TabBrowser. Used to observe tab switching events and
  *        for determining the active browser element.
  * @param panel
  *        The <xul:panel/> element to use for notifications. The panel is
  *        populated with <popupnotification> children and displayed it as
  *        needed.
  * @param iconBox
  *        Reference to a container element that should be hidden or
  *        unhidden when notifications are hidden or shown. It should be the
@@ -206,17 +206,17 @@ Notification.prototype = {
  *          shouldSuppress:
  *            If this function returns true, then all notifications are
  *            suppressed for this window. This state is checked on construction
  *            and when the "anchorVisibilityChange" method is called.
  *        }
  */
 function PopupNotifications(tabbrowser, panel,
                                                       iconBox, options = {}) {
-  if (!(tabbrowser instanceof Ci.nsIDOMXULElement))
+  if (!tabbrowser)
     throw "Invalid tabbrowser";
   if (iconBox && !(iconBox instanceof Ci.nsIDOMXULElement))
     throw "Invalid iconBox";
   if (!(panel instanceof Ci.nsIDOMXULElement))
     throw "Invalid panel";
 
   this._shouldSuppress = options.shouldSuppress || (() => false);
   this._suppress = this._shouldSuppress();