Bug 1429185 - Disable all devtools entry points with devtools.policy.disabled;r=ochameau draft
authorJulian Descottes <jdescottes@mozilla.com>
Thu, 22 Feb 2018 17:44:03 +0100
changeset 759847 0b4564987831d28f68308927ca60a9cff0818d4a
parent 758396 ea3da643422c58d65335f1778dd6c89c09911585
child 759848 1ceab46ff89f0330aa4a492b6b064501d74da180
push id100488
push userjdescottes@mozilla.com
push dateMon, 26 Feb 2018 18:18:07 +0000
reviewersochameau
bugs1429185
milestone60.0a1
Bug 1429185 - Disable all devtools entry points with devtools.policy.disabled;r=ochameau MozReview-Commit-ID: 9ObZc8my1mE
browser/base/content/nsContextMenu.js
devtools/shim/devtools-startup-prefs.js
devtools/shim/devtools-startup.js
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -430,17 +430,18 @@ nsContextMenu.prototype = {
                   this.onMathML && !this.isContentSelected);
 
     var shouldShow = !(this.isContentSelected ||
                        this.onImage || this.onCanvas ||
                        this.onVideo || this.onAudio ||
                        this.onLink || this.onTextInput);
 
     var showInspect = this.inTabBrowser &&
-                      Services.prefs.getBoolPref("devtools.inspector.enabled", true);
+                      Services.prefs.getBoolPref("devtools.inspector.enabled", true) &&
+                      !Services.prefs.getBoolPref("devtools.policy.disabled", false);
 
     this.showItem("context-viewsource", shouldShow);
     this.showItem("context-viewinfo", shouldShow);
     // The page info is broken for WebExtension popups, as the browser is
     // destroyed when the popup is closed.
     this.setItemAttr("context-viewinfo", "disabled", this.webExtBrowserType === "popup");
     this.showItem("inspect-separator", showInspect);
     this.showItem("context-inspect", showInspect);
--- a/devtools/shim/devtools-startup-prefs.js
+++ b/devtools/shim/devtools-startup-prefs.js
@@ -30,8 +30,12 @@ pref("devtools.onboarding.experiment", "
 
 // If devtools.onboarding.experiment is set to "on" or "force", we will flip the
 // devtools.enabled preference to false once. The flag is used to make sure it is only
 // flipped once.
 pref("devtools.onboarding.experiment.flipped", false);
 
 // Flag to check if we already logged the devtools onboarding related probe.
 pref("devtools.onboarding.telemetry.logged", false);
+
+// Completely disable DevTools entry points, as well as all DevTools command line
+// arguments This should be merged with devtools.enabled, see Bug 1440675.
+pref("devtools.policy.disabled", false);
\ No newline at end of file
--- a/devtools/shim/devtools-startup.js
+++ b/devtools/shim/devtools-startup.js
@@ -27,16 +27,18 @@ const kDebuggerPrefs = [
 ];
 
 // If devtools.toolbar.visible is set to true, the developer toolbar should appear on
 // startup.
 const TOOLBAR_VISIBLE_PREF = "devtools.toolbar.visible";
 
 const DEVTOOLS_ENABLED_PREF = "devtools.enabled";
 
+const DEVTOOLS_POLICY_DISABLED_PREF = "devtools.policy.disabled";
+
 const { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm", {});
 ChromeUtils.defineModuleGetter(this, "Services",
                                "resource://gre/modules/Services.jsm");
 ChromeUtils.defineModuleGetter(this, "AppConstants",
                                "resource://gre/modules/AppConstants.jsm");
 ChromeUtils.defineModuleGetter(this, "CustomizableUI",
                                "resource:///modules/CustomizableUI.jsm");
 ChromeUtils.defineModuleGetter(this, "CustomizableWidgets",
@@ -187,69 +189,90 @@ DevToolsStartup.prototype = {
    */
   recorded: false,
 
   /**
    * Flag that indicates if the developer toggle was already added to customizableUI.
    */
   developerToggleCreated: false,
 
+  isDisabledByPolicy: function () {
+    return Services.prefs.getBoolPref(DEVTOOLS_POLICY_DISABLED_PREF, false);
+  },
+
   handle: function (cmdLine) {
-    let consoleFlag = cmdLine.handleFlag("jsconsole", false);
-    let debuggerFlag = cmdLine.handleFlag("jsdebugger", false);
-    let devtoolsFlag = cmdLine.handleFlag("devtools", false);
+    let flags = this.readCommandLineFlags(cmdLine);
 
     // handle() can be called after browser startup (e.g. opening links from other apps).
     let isInitialLaunch = cmdLine.state == Ci.nsICommandLine.STATE_INITIAL_LAUNCH;
     if (isInitialLaunch) {
       // Execute only on first launch of this browser instance.
-      let hasDevToolsFlag = consoleFlag || devtoolsFlag || debuggerFlag;
+      let hasDevToolsFlag = flags.console || flags.devtools || flags.debugger;
       this.setupEnabledPref(hasDevToolsFlag);
 
       // Store devtoolsFlag to check it later in onWindowReady.
-      this.devtoolsFlag = devtoolsFlag;
+      this.devtoolsFlag = flags.devtools;
       // Only top level Firefox Windows fire a browser-delayed-startup-finished event
       Services.obs.addObserver(this.onWindowReady, "browser-delayed-startup-finished");
 
-      if (AppConstants.MOZ_DEV_EDITION) {
+      if (AppConstants.MOZ_DEV_EDITION && !this.isDisabledByPolicy()) {
         // On DevEdition, the developer toggle is displayed by default in the navbar area
         // and should be created before the first paint.
         this.hookDeveloperToggle();
       }
 
       // Update menu items when devtools.enabled changes.
       Services.prefs.addObserver(DEVTOOLS_ENABLED_PREF, this.onEnabledPrefChanged);
     }
 
-    if (consoleFlag) {
+    if (flags.console) {
       this.handleConsoleFlag(cmdLine);
     }
-    if (debuggerFlag) {
+    if (flags.debugger) {
       this.handleDebuggerFlag(cmdLine);
     }
 
-    let debuggerServerFlag;
+    if (flags.debuggerServer) {
+      this.handleDebuggerServerFlag(cmdLine, flags.debuggerServer);
+    }
+  },
+
+  readCommandLineFlags(cmdLine) {
+    // All command line flags are disabled if DevTools are disabled by policy.
+    if (this.isDisabledByPolicy()) {
+      return { console: false, debugger: false, devtools: false, debuggerServer: false };
+    }
+
+    let console = cmdLine.handleFlag("jsconsole", false);
+    let debuggerFlag = cmdLine.handleFlag("jsdebugger", false);
+    let devtools = cmdLine.handleFlag("devtools", false);
+
+    let debuggerServer;
     try {
-      debuggerServerFlag =
+      debuggerServer =
         cmdLine.handleFlagWithParam("start-debugger-server", false);
     } catch (e) {
       // We get an error if the option is given but not followed by a value.
       // By catching and trying again, the value is effectively optional.
-      debuggerServerFlag = cmdLine.handleFlag("start-debugger-server", false);
+      debuggerServer = cmdLine.handleFlag("start-debugger-server", false);
     }
-    if (debuggerServerFlag) {
-      this.handleDebuggerServerFlag(cmdLine, debuggerServerFlag);
-    }
+
+    return { console, debugger: debuggerFlag, devtools, debuggerServer };
   },
 
   /**
    * Called when receiving the "browser-delayed-startup-finished" event for a new
    * top-level window.
    */
   onWindowReady(window) {
+    if (this.isDisabledByPolicy()) {
+      this.removeDevToolsMenus(window);
+      return;
+    }
+
     this.hookWindow(window);
 
     if (Services.prefs.getBoolPref(TOOLBAR_VISIBLE_PREF, false)) {
       // Loading devtools-browser will open the developer toolbar by also checking this
       // pref.
       this.initDevTools();
     }
 
@@ -258,16 +281,24 @@ DevToolsStartup.prototype = {
     if (!this._firstWindowReadyReceived) {
       this.onFirstWindowReady(window);
       this._firstWindowReadyReceived = true;
     }
 
     JsonView.initialize();
   },
 
+  removeDevToolsMenus(window) {
+    // This will hide the "Tools > Web Developer" menu.
+    window.document.getElementById("webDeveloperMenu").setAttribute("hidden", "true");
+    // This will hide the "Web Developer" item in the hamburger menu.
+    window.document.getElementById("appMenu-developer-button").setAttribute("hidden",
+      "true");
+  },
+
   onFirstWindowReady(window) {
     if (this.devtoolsFlag) {
       this.handleDevToolsFlag(window);
     }
 
     // Wait until we get a window before sending a ping to telemetry to avoid slowing down
     // the startup phase.
     this.pingOnboardingTelemetry();
@@ -611,16 +642,22 @@ DevToolsStartup.prototype = {
    * @param {String} reason
    *        One of "KeyShortcut", "SystemMenu", "HamburgerMenu", "ContextMenu",
    *        "CommandLine".
    * @param {String} keyId
    *        Optional. If the onboarding flow was triggered by a keyboard shortcut, pass
    *        the shortcut key id (or toolId) to about:devtools.
    */
   openInstallPage: function (reason, keyId) {
+    // If DevTools are completely disabled, bail out here as this might be called directly
+    // from other files.
+    if (this.isDisabledByPolicy()) {
+      return;
+    }
+
     let { gBrowser } = Services.wm.getMostRecentWindow("navigator:browser");
 
     // Focus about:devtools tab if there is already one opened in the current window.
     for (let tab of gBrowser.tabs) {
       let browser = tab.linkedBrowser;
       // browser.documentURI might be undefined if the browser tab is still loading.
       let location = browser.documentURI ? browser.documentURI.spec : "";
       if (location.startsWith("about:devtools") &&