Bug 1361080 - Add "Enable DevTools..." menu item if devtools.enabled is false;r=ochameau draft
authorJulian Descottes <jdescottes@mozilla.com>
Tue, 29 Aug 2017 23:09:21 +0200
changeset 678539 b1dd8e4163fb6cbec236f8a1e3b64ab65b15577c
parent 678538 29b9149cecfc6c1087bce42b3afdd6b88c82e62e
child 678540 9166f477e2d38351e836aa14c53a420bd9cbddf7
push id83952
push userjdescottes@mozilla.com
push dateWed, 11 Oct 2017 14:45:10 +0000
reviewersochameau
bugs1361080
milestone58.0a1
Bug 1361080 - Add "Enable DevTools..." menu item if devtools.enabled is false;r=ochameau MozReview-Commit-ID: IL09o4xve64
devtools/shim/devtools-startup.js
devtools/shim/locales/en-US/startup.properties
--- a/devtools/shim/devtools-startup.js
+++ b/devtools/shim/devtools-startup.js
@@ -38,19 +38,24 @@ XPCOMUtils.defineLazyModuleGetter(this, 
                                   "resource://gre/modules/Services.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
                                   "resource://gre/modules/AppConstants.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
                                   "resource:///modules/CustomizableUI.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "CustomizableWidgets",
                                   "resource:///modules/CustomizableWidgets.jsm");
 
-XPCOMUtils.defineLazyGetter(this, "Bundle", function () {
-  const kUrl = "chrome://devtools-shim/locale/key-shortcuts.properties";
-  return Services.strings.createBundle(kUrl);
+XPCOMUtils.defineLazyGetter(this, "StartupBundle", function () {
+  const url = "chrome://devtools-shim/locale/startup.properties";
+  return Services.strings.createBundle(url);
+});
+
+XPCOMUtils.defineLazyGetter(this, "KeyShortcutsBundle", function () {
+  const url = "chrome://devtools-shim/locale/key-shortcuts.properties";
+  return Services.strings.createBundle(url);
 });
 
 XPCOMUtils.defineLazyGetter(this, "KeyShortcuts", function () {
   const isMac = AppConstants.platform == "macosx";
 
   // Common modifier shared by most key shortcuts
   const modifiers = isMac ? "accel,alt" : "accel,shift";
 
@@ -59,117 +64,119 @@ XPCOMUtils.defineLazyGetter(this, "KeySh
   return [
     // The following keys are also registered in /client/menus.js
     // And should be synced.
 
     // Both are toggling the toolbox on the last selected panel
     // or the default one.
     {
       id: "toggleToolbox",
-      shortcut: Bundle.GetStringFromName("toggleToolbox.commandkey"),
+      shortcut: KeyShortcutsBundle.GetStringFromName("toggleToolbox.commandkey"),
       modifiers
     },
     // All locales are using F12
     {
       id: "toggleToolboxF12",
-      shortcut: Bundle.GetStringFromName("toggleToolboxF12.commandkey"),
+      shortcut: KeyShortcutsBundle.GetStringFromName("toggleToolboxF12.commandkey"),
       modifiers: "" // F12 is the only one without modifiers
     },
     // Toggle the visibility of the Developer Toolbar (=gcli)
     {
       id: "toggleToolbar",
-      shortcut: Bundle.GetStringFromName("toggleToolbar.commandkey"),
+      shortcut: KeyShortcutsBundle.GetStringFromName("toggleToolbar.commandkey"),
       modifiers: "shift"
     },
     // Open WebIDE window
     {
       id: "webide",
-      shortcut: Bundle.GetStringFromName("webide.commandkey"),
+      shortcut: KeyShortcutsBundle.GetStringFromName("webide.commandkey"),
       modifiers: "shift"
     },
     // Open the Browser Toolbox
     {
       id: "browserToolbox",
-      shortcut: Bundle.GetStringFromName("browserToolbox.commandkey"),
+      shortcut: KeyShortcutsBundle.GetStringFromName("browserToolbox.commandkey"),
       modifiers: "accel,alt,shift"
     },
     // Open the Browser Console
     {
       id: "browserConsole",
-      shortcut: Bundle.GetStringFromName("browserConsole.commandkey"),
+      shortcut: KeyShortcutsBundle.GetStringFromName("browserConsole.commandkey"),
       modifiers: "accel,shift"
     },
     // Toggle the Responsive Design Mode
     {
       id: "responsiveDesignMode",
-      shortcut: Bundle.GetStringFromName("responsiveDesignMode.commandkey"),
+      shortcut: KeyShortcutsBundle.GetStringFromName("responsiveDesignMode.commandkey"),
       modifiers
     },
     // Open ScratchPad window
     {
       id: "scratchpad",
-      shortcut: Bundle.GetStringFromName("scratchpad.commandkey"),
+      shortcut: KeyShortcutsBundle.GetStringFromName("scratchpad.commandkey"),
       modifiers: "shift"
     },
 
     // The following keys are also registered in /client/definitions.js
     // and should be synced.
 
     // Key for opening the Inspector
     {
       toolId: "inspector",
-      shortcut: Bundle.GetStringFromName("inspector.commandkey"),
+      shortcut: KeyShortcutsBundle.GetStringFromName("inspector.commandkey"),
       modifiers
     },
     // Key for opening the Web Console
     {
       toolId: "webconsole",
-      shortcut: Bundle.GetStringFromName("webconsole.commandkey"),
+      shortcut: KeyShortcutsBundle.GetStringFromName("webconsole.commandkey"),
       modifiers
     },
     // Key for opening the Debugger
     {
       toolId: "jsdebugger",
-      shortcut: Bundle.GetStringFromName("debugger.commandkey"),
+      shortcut: KeyShortcutsBundle.GetStringFromName("debugger.commandkey"),
       modifiers
     },
     // Key for opening the Network Monitor
     {
       toolId: "netmonitor",
-      shortcut: Bundle.GetStringFromName("netmonitor.commandkey"),
+      shortcut: KeyShortcutsBundle.GetStringFromName("netmonitor.commandkey"),
       modifiers
     },
     // Key for opening the Style Editor
     {
       toolId: "styleeditor",
-      shortcut: Bundle.GetStringFromName("styleeditor.commandkey"),
+      shortcut: KeyShortcutsBundle.GetStringFromName("styleeditor.commandkey"),
       modifiers: "shift"
     },
     // Key for opening the Performance Panel
     {
       toolId: "performance",
-      shortcut: Bundle.GetStringFromName("performance.commandkey"),
+      shortcut: KeyShortcutsBundle.GetStringFromName("performance.commandkey"),
       modifiers: "shift"
     },
     // Key for opening the Storage Panel
     {
       toolId: "storage",
-      shortcut: Bundle.GetStringFromName("storage.commandkey"),
+      shortcut: KeyShortcutsBundle.GetStringFromName("storage.commandkey"),
       modifiers: "shift"
     },
     // Key for opening the DOM Panel
     {
       toolId: "dom",
-      shortcut: Bundle.GetStringFromName("dom.commandkey"),
+      shortcut: KeyShortcutsBundle.GetStringFromName("dom.commandkey"),
       modifiers
     },
   ];
 });
 
-function DevToolsStartup() {}
+function DevToolsStartup() {
+  this.onEnabledPrefChanged = this.onEnabledPrefChanged.bind(this);
+}
 
 DevToolsStartup.prototype = {
   /**
    * Boolean flag to check if DevTools have been already initialized or not.
    * By initialized, we mean that its main modules are loaded.
    */
   initialized: false,
 
@@ -226,16 +233,18 @@ DevToolsStartup.prototype = {
         this.handleDevToolsFlag(window);
         // This listener is called for all Firefox windows, but we want to execute
         // that command only once
         devtoolsFlag = false;
       }
       JsonView.initialize();
     };
     Services.obs.addObserver(onWindowReady, "browser-delayed-startup-finished");
+
+    Services.prefs.addObserver(DEVTOOLS_ENABLED_PREF, this.onEnabledPrefChanged);
   },
 
   /**
    * Register listeners to all possible entry points for Developer Tools.
    * But instead of implementing the actual actions, defer to DevTools codebase.
    * In most cases, it only needs to call this.initDevTools which handles the rest.
    * We do that to prevent loading any DevTools module until the user intent to use them.
    */
@@ -251,16 +260,19 @@ DevToolsStartup.prototype = {
       this.developerToggleCreated = true;
     }
 
     // The developer menu hook only needs to be added if devtools have not been
     // initialized yet.
     if (!this.initialized) {
       this.hookWebDeveloperMenu(window);
     }
+
+    this.createDevToolsEnableMenuItem(window);
+    this.updateDevToolsMenuItems(window);
   },
 
   /**
    * Dynamically register a wrench icon in the customization menu.
    * You can use this button by right clicking on Firefox toolbar
    * and dragging it from the customization panel to the toolbar.
    * (i.e. this isn't displayed by default to users!)
    *
@@ -285,18 +297,21 @@ DevToolsStartup.prototype = {
       type: "view",
       viewId: "PanelUI-developer",
       shortcutId: "key_toggleToolbox",
       tooltiptext: "developer-button.tooltiptext2",
       defaultArea: AppConstants.MOZ_DEV_EDITION ?
                      CustomizableUI.AREA_NAVBAR :
                      CustomizableUI.AREA_PANEL,
       onViewShowing: (event) => {
-        // Ensure creating the menuitems in the system menu before trying to copy them.
-        this.initDevTools("HamburgerMenu");
+        if (Services.prefs.getBoolPref(DEVTOOLS_ENABLED_PREF)) {
+          // If DevTools are enabled, initialize DevTools to create all menuitems in the
+          // system menu before trying to copy them.
+          this.initDevTools("HamburgerMenu");
+        }
 
         // Populate the subview with whatever menuitems are in the developer
         // menu. We skip menu elements, because the menu panel has no way
         // of dealing with those right now.
         let doc = event.target.ownerDocument;
 
         let menu = doc.getElementById("menuWebDeveloperPopup");
 
@@ -336,19 +351,70 @@ DevToolsStartup.prototype = {
 
   /*
    * We listen to the "Web Developer" system menu, which is under "Tools" main item.
    * This menu item is hardcoded empty in Firefox UI. We listen for its opening to
    * populate it lazily. Loading main DevTools module is going to populate it.
    */
   hookWebDeveloperMenu(window) {
     let menu = window.document.getElementById("webDeveloperMenu");
-    menu.addEventListener("popupshowing", () => {
+    let onPopupShowing = () => {
+      if (!Services.prefs.getBoolPref(DEVTOOLS_ENABLED_PREF)) {
+        return;
+      }
+      menu.removeEventListener("popupshowing", onPopupShowing);
       this.initDevTools("SystemMenu");
-    }, { once: true });
+    };
+    menu.addEventListener("popupshowing", onPopupShowing);
+  },
+
+  /**
+   * Create a new menu item to enable DevTools and insert it DevTools's submenu in the
+   * System Menu.
+   */
+  createDevToolsEnableMenuItem(window) {
+    let {document} = window;
+
+    // Create the menu item.
+    let item = document.createElement("menuitem");
+    item.id = "enableDeveloperTools";
+    item.setAttribute("label", StartupBundle.GetStringFromName("enableDevTools.label"));
+    item.setAttribute("accesskey",
+      StartupBundle.GetStringFromName("enableDevTools.accesskey"));
+
+    // The menu item should open the install page for DevTools.
+    item.addEventListener("command", () => {
+      this.openInstallPage("SystemMenu");
+    });
+
+    // Insert the menu item in the DevTools submenu.
+    let systemMenuItem = document.getElementById("menuWebDeveloperPopup");
+    systemMenuItem.appendChild(item);
+  },
+
+  /**
+   * Update the visibility the menu item to enable DevTools.
+   */
+  updateDevToolsMenuItems(window) {
+    let item = window.document.getElementById("enableDeveloperTools");
+    item.hidden = Services.prefs.getBoolPref(DEVTOOLS_ENABLED_PREF);
+  },
+
+  /**
+   * Loop on all windows and update the hidden attribute of the "enable DevTools" menu
+   * item.
+   */
+  onEnabledPrefChanged() {
+    let enumerator = Services.wm.getEnumerator("navigator:browser");
+    while (enumerator.hasMoreElements()) {
+      let window = enumerator.getNext();
+      if (window.gBrowserInit && window.gBrowserInit.delayedStartupFinished) {
+        this.updateDevToolsMenuItems(window);
+      }
+    }
   },
 
   /**
    * Depending on some runtime parameters (command line arguments as well as existing
    * preferences), the DEVTOOLS_ENABLED_PREF might be forced to true.
    *
    * @param {Boolean} hasDevToolsFlag
    *        true if any DevTools command line argument was passed when starting Firefox.
new file mode 100644
--- /dev/null
+++ b/devtools/shim/locales/en-US/startup.properties
@@ -0,0 +1,8 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# LOCALIZATION NOTE (enableDevTools.label):
+# Label for the menu item displayed in Tools > Developer Tools when DevTools are disabled.
+enableDevTools.label=Enable Developer Tools…
+enableDevTools.accesskey=E