Bug 1353548 - Create devtools menu entries on menu showing. r=jryans draft
authorAlexandre Poirot <poirot.alex@gmail.com>
Wed, 05 Apr 2017 18:17:37 +0200
changeset 556657 9a503e7793fca6b3b05afd5ee83f98211868a6b3
parent 555511 891981e67948aaebf7a63bba5181ef0a538ce163
child 622953 555ebd7cee482cee31faced2b175835a78aba9b3
push id52616
push userbmo:poirot.alex@gmail.com
push dateThu, 06 Apr 2017 08:35:53 +0000
reviewersjryans
bugs1353548
milestone55.0a1
Bug 1353548 - Create devtools menu entries on menu showing. r=jryans MozReview-Commit-ID: JGhAtxyXBOg
devtools/client/framework/browser-menus.js
devtools/client/framework/devtools-browser.js
--- a/devtools/client/framework/browser-menus.js
+++ b/devtools/client/framework/browser-menus.js
@@ -367,18 +367,22 @@ function removeTopLevelItems(doc) {
 
 /**
  * Add menus and shortcuts to a browser document
  *
  * @param {XULDocument} doc
  *        The document to which keys and menus are to be added.
  */
 exports.addMenus = function (doc) {
+  // Prevent trying to add the entries more than once
+  let endSeparator = doc.getElementById("devToolsEndSeparator");
+  if (endSeparator) {
+    return;
+  }
   addTopLevelItems(doc);
-
   addAllToolsToMenu(doc);
 };
 
 /**
  * Remove menus and shortcuts from a browser document
  *
  * @param {XULDocument} doc
  *        The document to which keys and menus are to be removed.
--- a/devtools/client/framework/devtools-browser.js
+++ b/devtools/client/framework/devtools-browser.js
@@ -84,33 +84,38 @@ var gDevToolsBrowser = exports.gDevTools
    * depending on their relevant prefs. It gets run when a window is registered,
    * or when any of the devtools prefs change.
    */
   updateCommandAvailability: function (win) {
     let doc = win.document;
 
     function toggleMenuItem(id, isEnabled) {
       let cmd = doc.getElementById(id);
+      if (!cmd) {
+        return;
+      }
       if (isEnabled) {
         cmd.removeAttribute("disabled");
         cmd.removeAttribute("hidden");
       } else {
         cmd.setAttribute("disabled", "true");
         cmd.setAttribute("hidden", "true");
       }
     }
 
     // Enable developer toolbar?
     let devToolbarEnabled = Services.prefs.getBoolPref("devtools.toolbar.enabled");
     toggleMenuItem("menu_devToolbar", devToolbarEnabled);
     let focusEl = doc.getElementById("menu_devToolbar");
-    if (devToolbarEnabled) {
-      focusEl.removeAttribute("disabled");
-    } else {
-      focusEl.setAttribute("disabled", "true");
+    if (focusEl) {
+      if (devToolbarEnabled) {
+        focusEl.removeAttribute("disabled");
+      } else {
+        focusEl.setAttribute("disabled", "true");
+      }
     }
     if (devToolbarEnabled && Services.prefs.getBoolPref("devtools.toolbar.visible")) {
       win.DeveloperToolbar.show(false).catch(console.error);
     }
 
     // Enable WebIDE?
     let webIDEEnabled = Services.prefs.getBoolPref("devtools.webide.enabled");
     toggleMenuItem("menu_webide", webIDEEnabled);
@@ -442,20 +447,26 @@ var gDevToolsBrowser = exports.gDevTools
         let developerItems = doc.getElementById("PanelUI-developerItems");
         // Import private helpers from CustomizableWidgets
         let { clearSubview, fillSubviewFromMenuItems } =
           Cu.import("resource:///modules/CustomizableWidgets.jsm", {});
         clearSubview(developerItems);
         fillSubviewFromMenuItems(itemsToDisplay, developerItems);
       },
       onBeforeCreated: function (doc) {
+        // As the menu items are lazy loaded, ensure creating them first.
+        // Don't do it in onViewShowing as a <key> element is being used
+        // to print the shortcut on the Developer button.
+        BrowserMenus.addMenus(doc);
+
         // Bug 1223127, CUI should make this easier to do.
         if (doc.getElementById("PanelUI-developerItems")) {
           return;
         }
+
         let view = doc.createElement("panelview");
         view.id = "PanelUI-developerItems";
         let panel = doc.createElement("vbox");
         panel.setAttribute("class", "panel-subview-body");
         view.appendChild(panel);
         doc.getElementById("PanelUI-multiView").appendChild(view);
       }
     });
@@ -513,28 +524,42 @@ var gDevToolsBrowser = exports.gDevTools
    * Move WebIDE widget to the navbar
    */
    // Used by webide.js
   moveWebIDEWidgetInNavbar: function () {
     CustomizableUI.addWidgetToArea("webide-button", CustomizableUI.AREA_NAVBAR);
   },
 
   /**
+   * Called just before the tools menu is opened, in order to lazily create
+   * DevTools menu entries.
+   *
+   * @param {DOMEvent} event
+   *        popupshowing event object
+   */
+  _onToolsMenuShowing: function (event) {
+    let doc = event.target.ownerDocument;
+    BrowserMenus.addMenus(doc);
+  },
+
+  /**
    * Add this DevTools's presence to a browser window's document
    *
    * @param {XULDocument} doc
    *        The document to which devtools should be hooked to.
    */
   _registerBrowserWindow: function (win) {
     if (gDevToolsBrowser._trackedBrowserWindows.has(win)) {
       return;
     }
     gDevToolsBrowser._trackedBrowserWindows.add(win);
 
-    BrowserMenus.addMenus(win.document);
+    let menu = win.document.getElementById("webDeveloperMenu");
+    menu.addEventListener("popupshowing", this._onToolsMenuShowing);
+
 
     // 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");
@@ -743,16 +768,18 @@ var gDevToolsBrowser = exports.gDevTools
   _forgetBrowserWindow: function (win) {
     if (!gDevToolsBrowser._trackedBrowserWindows.has(win)) {
       return;
     }
     gDevToolsBrowser._trackedBrowserWindows.delete(win);
     win.removeEventListener("unload", this);
 
     BrowserMenus.removeMenus(win.document);
+    let menu = win.document.getElementById("webDeveloperMenu");
+    menu.removeEventListener("popupshowing", this._onToolsMenuShowing);
 
     // Destroy toolboxes for closed window
     for (let [target, toolbox] of gDevTools._toolboxes) {
       if (target.tab && target.tab.ownerDocument.defaultView == win) {
         toolbox.destroy();
       }
     }