Bug 1297535 - Register devtools menu and keys on DOMContentLoaded to happen before CustomizableUI. r=bgrins draft
authorAlexandre Poirot <poirot.alex@gmail.com>
Wed, 24 Aug 2016 07:26:32 -0700
changeset 417583 e7bcdce8a595fb2e78a584d80433ac6d0c63f317
parent 417383 29beaebdfaccbdaeb4c1ee5a43a9795ab015ef49
child 417584 e237d78245f0be3658cc7ac885d5b4bfea5ac604
push id30437
push userbmo:poirot.alex@gmail.com
push dateMon, 26 Sep 2016 13:15:03 +0000
reviewersbgrins
bugs1297535
milestone52.0a1
Bug 1297535 - Register devtools menu and keys on DOMContentLoaded to happen before CustomizableUI. r=bgrins MozReview-Commit-ID: ACy3yJTgzyA
devtools/client/framework/devtools-browser.js
--- a/devtools/client/framework/devtools-browser.js
+++ b/devtools/client/framework/devtools-browser.js
@@ -136,16 +136,20 @@ var gDevToolsBrowser = exports.gDevTools
         break;
       case "nsPref:changed":
         if (prefName.endsWith("enabled")) {
           for (let win of this._trackedBrowserWindows) {
             this.updateCommandAvailability(win);
           }
         }
         break;
+      case "domwindowopened":
+        let win = subject.QueryInterface(Ci.nsIDOMEventTarget);
+        win.addEventListener("DOMContentLoaded", this, { once: true });
+        break;
     }
   },
 
   _prefObserverRegistered: false,
 
   ensurePrefObserver: function () {
     if (!this._prefObserverRegistered) {
       this._prefObserverRegistered = true;
@@ -397,29 +401,44 @@ var gDevToolsBrowser = exports.gDevTools
    * Move WebIDE widget to the navbar
    */
    // Used by webide.js
   moveWebIDEWidgetInNavbar: function () {
     CustomizableUI.addWidgetToArea("webide-button", CustomizableUI.AREA_NAVBAR);
   },
 
   /**
+   * Starts setting up devtools on a given browser window. This method is
+   * called on DOMContentLoaded, so earlier than registerBrowserWindow which
+   * is called after delayed-startup notification. This method should only do
+   * what has to be done early. Otherwise devtools should be initialized lazily
+   * to prevent overloading Firefox startup.
+   *
+   * @param {ChromeWindow} window
+   *        The window to which devtools should be hooked to.
+   */
+  _onBrowserWindowLoaded: function (win) {
+    if (!win.gBrowser) {
+      return;
+    }
+    BrowserMenus.addMenus(win.document);
+  },
+
+  /**
    * Add this DevTools's presence to a browser window's document
    *
-   * @param {XULDocument} doc
-   *        The document to which devtools should be hooked to.
+   * @param {ChromeWindow} win
+   *        The window to which devtools should be hooked to.
    */
   _registerBrowserWindow: function (win) {
     if (gDevToolsBrowser._trackedBrowserWindows.has(win)) {
       return;
     }
     gDevToolsBrowser._trackedBrowserWindows.add(win);
 
-    BrowserMenus.addMenus(win.document);
-
     // Register the Developer widget in the Hamburger menu or navbar
     // only once menus are registered as it depends on it.
     gDevToolsBrowser.installDeveloperWidget();
 
     // Inject lazily DeveloperToolbar on the chrome window
     loader.lazyGetter(win, "DeveloperToolbar", function () {
       let { DeveloperToolbar } = require("devtools/client/shared/developer-toolbar");
       return new DeveloperToolbar(win);
@@ -674,16 +693,19 @@ var gDevToolsBrowser = exports.gDevTools
         this._tabStats.histOpen.push(open);
         this._tabStats.histPinned.push(pinned);
         this._tabStats.peakOpen = Math.max(open, this._tabStats.peakOpen);
         this._tabStats.peakPinned = Math.max(pinned, this._tabStats.peakPinned);
         break;
       case "TabSelect":
         gDevToolsBrowser._updateMenuCheckbox();
         break;
+      case "DOMContentLoaded":
+        gDevToolsBrowser._onBrowserWindowLoaded(event.target.defaultView);
+        break;
       case "unload":
         // top-level browser window unload
         gDevToolsBrowser._forgetBrowserWindow(event.target.defaultView);
         break;
     }
   },
 
   _pingTelemetry: function () {
@@ -703,16 +725,17 @@ var gDevToolsBrowser = exports.gDevTools
     this._telemetry.log(TABS_PINNED_AVG_HISTOGRAM, mean(tabStats.histPinned));
   },
 
   /**
    * All browser windows have been closed, tidy up remaining objects.
    */
   destroy: function () {
     Services.prefs.removeObserver("devtools.", gDevToolsBrowser);
+    Services.ww.unregisterNotification(gDevToolsBrowser);
     Services.obs.removeObserver(gDevToolsBrowser, "browser-delayed-startup-finished");
     Services.obs.removeObserver(gDevToolsBrowser.destroy, "quit-application");
 
     gDevToolsBrowser._pingTelemetry();
     gDevToolsBrowser._telemetry = null;
 
     for (let win of gDevToolsBrowser._trackedBrowserWindows) {
       gDevToolsBrowser._forgetBrowserWindow(win);
@@ -735,24 +758,26 @@ gDevTools.on("tool-unregistered", functi
   }
   gDevToolsBrowser._removeToolFromWindows(toolId);
 });
 
 gDevTools.on("toolbox-ready", gDevToolsBrowser._updateMenuCheckbox);
 gDevTools.on("toolbox-destroyed", gDevToolsBrowser._updateMenuCheckbox);
 
 Services.obs.addObserver(gDevToolsBrowser.destroy, "quit-application", false);
+Services.ww.registerNotification(gDevToolsBrowser);
 Services.obs.addObserver(gDevToolsBrowser, "browser-delayed-startup-finished", false);
 
 // Fake end of browser window load event for all already opened windows
 // that is already fully loaded.
 let enumerator = Services.wm.getEnumerator(gDevTools.chromeWindowType);
 while (enumerator.hasMoreElements()) {
   let win = enumerator.getNext();
   if (win.gBrowserInit && win.gBrowserInit.delayedStartupFinished) {
+    gDevToolsBrowser._onBrowserWindowLoaded(win);
     gDevToolsBrowser._registerBrowserWindow(win);
   }
 }
 
 // Watch for module loader unload. Fires when the tools are reloaded.
 unload(function () {
   gDevToolsBrowser.destroy();
 });