Bug 1500350: Add a checkbox to enable addon debugging on this-firefox. r=jdescottes,ladybenko
authorDaisuke Akatsuka <dakatsuka@mozilla.com>
Tue, 19 Feb 2019 01:10:54 +0000
changeset 459835 9a1f91d90de19afda7fb9ecd573074451fb7f153
parent 459834 e433748cd2a1eff590ec57977aa2c6800a3c72b2
child 459836 b10932876150bc73be47f0b332028d3b8bcaa6f3
push id35576
push userbtara@mozilla.com
push dateTue, 19 Feb 2019 09:46:27 +0000
treeherdermozilla-central@dd4aa59c6a12 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdescottes, ladybenko
bugs1500350
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1500350: Add a checkbox to enable addon debugging on this-firefox. r=jdescottes,ladybenko Differential Revision: https://phabricator.services.mozilla.com/D18196
devtools/client/aboutdebugging-new/src/actions/runtimes.js
devtools/client/aboutdebugging-new/src/base.css
devtools/client/aboutdebugging-new/src/components/ExtensionDebugSetting.js
devtools/client/aboutdebugging-new/src/components/RuntimePage.js
devtools/client/aboutdebugging-new/src/components/moz.build
devtools/client/aboutdebugging-new/src/constants.js
devtools/client/aboutdebugging-new/src/modules/client-wrapper.js
devtools/client/aboutdebugging-new/src/modules/debug-target-support.js
devtools/client/aboutdebugging-new/src/reducers/runtimes-state.js
devtools/client/aboutdebugging-new/src/types/runtime.js
devtools/client/aboutdebugging-new/tmp-locale/en-US/aboutdebugging.notftl
--- a/devtools/client/aboutdebugging-new/src/actions/runtimes.js
+++ b/devtools/client/aboutdebugging-new/src/actions/runtimes.js
@@ -9,16 +9,17 @@ const Actions = require("./index");
 const {
   getAllRuntimes,
   getCurrentRuntime,
   findRuntimeById,
 } = require("../modules/runtimes-state-helper");
 
 const { l10n } = require("../modules/l10n");
 const { createClientForRuntime } = require("../modules/runtime-client-factory");
+const { isExtensionDebugSettingNeeded } = require("../modules/debug-target-support");
 
 const { remoteClientManager } =
   require("devtools/client/shared/remote-debugging/remote-client-manager");
 
 const {
   CONNECT_RUNTIME_FAILURE,
   CONNECT_RUNTIME_START,
   CONNECT_RUNTIME_SUCCESS,
@@ -31,16 +32,19 @@ const {
   RUNTIMES,
   THIS_FIREFOX_RUNTIME_CREATED,
   UNWATCH_RUNTIME_FAILURE,
   UNWATCH_RUNTIME_START,
   UNWATCH_RUNTIME_SUCCESS,
   UPDATE_CONNECTION_PROMPT_SETTING_FAILURE,
   UPDATE_CONNECTION_PROMPT_SETTING_START,
   UPDATE_CONNECTION_PROMPT_SETTING_SUCCESS,
+  UPDATE_EXTENSION_DEBUG_SETTING_FAILURE,
+  UPDATE_EXTENSION_DEBUG_SETTING_START,
+  UPDATE_EXTENSION_DEBUG_SETTING_SUCCESS,
   UPDATE_RUNTIME_MULTIE10S_FAILURE,
   UPDATE_RUNTIME_MULTIE10S_START,
   UPDATE_RUNTIME_MULTIE10S_SUCCESS,
   WATCH_RUNTIME_FAILURE,
   WATCH_RUNTIME_START,
   WATCH_RUNTIME_SUCCESS,
 } = require("../constants");
 
@@ -66,32 +70,40 @@ function connectRuntime(id) {
       const runtime = findRuntimeById(id, getState().runtimes);
       const clientWrapper = await createClientForRuntime(runtime);
 
       const deviceDescription = await clientWrapper.getDeviceDescription();
       const compatibilityReport = await clientWrapper.checkVersionCompatibility();
       const icon = await getRuntimeIcon(deviceDescription.channel);
 
       const {
+        CHROME_DEBUG_ENABLED,
         CONNECTION_PROMPT,
         PERMANENT_PRIVATE_BROWSING,
+        REMOTE_DEBUG_ENABLED,
         SERVICE_WORKERS_ENABLED,
       } = RUNTIME_PREFERENCE;
       const connectionPromptEnabled =
         await clientWrapper.getPreference(CONNECTION_PROMPT, false);
+      const extensionDebugEnabled =
+        isExtensionDebugSettingNeeded(runtime.type)
+          ? await clientWrapper.getPreference(CHROME_DEBUG_ENABLED, true) &&
+            await clientWrapper.getPreference(REMOTE_DEBUG_ENABLED, true)
+          : true;
       const privateBrowsing =
         await clientWrapper.getPreference(PERMANENT_PRIVATE_BROWSING, false);
       const serviceWorkersEnabled =
         await clientWrapper.getPreference(SERVICE_WORKERS_ENABLED, true);
       const serviceWorkersAvailable = serviceWorkersEnabled && !privateBrowsing;
 
       const runtimeDetails = {
         clientWrapper,
         compatibilityReport,
         connectionPromptEnabled,
+        extensionDebugEnabled,
         info: {
           deviceName: deviceDescription.deviceName,
           icon,
           name: deviceDescription.name,
           type: runtime.type,
           version: deviceDescription.version,
         },
         isMultiE10s: deviceDescription.isMultiE10s,
@@ -181,16 +193,42 @@ function updateConnectionPromptSetting(c
       dispatch({ type: UPDATE_CONNECTION_PROMPT_SETTING_SUCCESS,
                  runtime, connectionPromptEnabled });
     } catch (e) {
       dispatch({ type: UPDATE_CONNECTION_PROMPT_SETTING_FAILURE, error: e });
     }
   };
 }
 
+function updateExtensionDebugSetting(extensionDebugEnabled) {
+  return async (dispatch, getState) => {
+    dispatch({ type: UPDATE_EXTENSION_DEBUG_SETTING_START });
+    try {
+      const runtime = getCurrentRuntime(getState().runtimes);
+      const { clientWrapper } = runtime.runtimeDetails;
+
+      const { CHROME_DEBUG_ENABLED, REMOTE_DEBUG_ENABLED } = RUNTIME_PREFERENCE;
+      await clientWrapper.setPreference(CHROME_DEBUG_ENABLED, extensionDebugEnabled);
+      await clientWrapper.setPreference(REMOTE_DEBUG_ENABLED, extensionDebugEnabled);
+
+      // Re-get actual value from the runtime.
+      const isChromeDebugEnabled =
+        await clientWrapper.getPreference(CHROME_DEBUG_ENABLED, extensionDebugEnabled);
+      const isRemoveDebugEnabled =
+        await clientWrapper.getPreference(REMOTE_DEBUG_ENABLED, extensionDebugEnabled);
+      extensionDebugEnabled = isChromeDebugEnabled && isRemoveDebugEnabled;
+
+      dispatch({ type: UPDATE_EXTENSION_DEBUG_SETTING_SUCCESS,
+                 runtime, extensionDebugEnabled });
+    } catch (e) {
+      dispatch({ type: UPDATE_EXTENSION_DEBUG_SETTING_FAILURE, error: e });
+    }
+  };
+}
+
 function updateMultiE10s() {
   return async (dispatch, getState) => {
     dispatch({ type: UPDATE_RUNTIME_MULTIE10S_START });
     try {
       const runtime = getCurrentRuntime(getState().runtimes);
       const { clientWrapper } = runtime.runtimeDetails;
       // Re-get actual value from the runtime.
       const { isMultiE10s } = await clientWrapper.getDeviceDescription();
@@ -370,12 +408,13 @@ function removeRuntimeListeners() {
 
 module.exports = {
   connectRuntime,
   createThisFirefoxRuntime,
   disconnectRuntime,
   removeRuntimeListeners,
   unwatchRuntime,
   updateConnectionPromptSetting,
+  updateExtensionDebugSetting,
   updateNetworkRuntimes,
   updateUSBRuntimes,
   watchRuntime,
 };
--- a/devtools/client/aboutdebugging-new/src/base.css
+++ b/devtools/client/aboutdebugging-new/src/base.css
@@ -118,16 +118,21 @@ p {
   white-space: nowrap;
 }
 
 /* Technical text that should use a monospace font, such as code, error messages. */
 .technical-text {
   font-family: var(--monospace-font-family);
 }
 
+/* Text that is not selectable */
+.unselectable-text {
+  -moz-user-select: none;
+}
+
 /*
 * Typography
 */
 
 /* Main style for heading (i.e. h1) */
 /* +--------+-------------+
 *  | [Icon] | Lorem ipsum |
 *  +--------+-------------+
@@ -294,16 +299,23 @@ Form controls
   height: 100%;
 
   border: 1px solid var(--box-border-color);
   border-radius: 2px;
   color: var(--text-color);
   background-color: var(--box-background);
 }
 
+.default-checkbox {
+  /* Note: this styles are from Photon, not common.css */
+  height: calc(var(--base-unit) * 4);
+  margin-inline-end: var(--base-unit);
+  width: calc(var(--base-unit) * 4);
+}
+
 /*
 * Other UI components
 */
 
 /*
 * A small, colored badge.
 * NOTE: styles borrowed from Photon's micro buttons (there aren't badges)
 */
new file mode 100644
--- /dev/null
+++ b/devtools/client/aboutdebugging-new/src/components/ExtensionDebugSetting.js
@@ -0,0 +1,74 @@
+/* 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/. */
+
+"use strict";
+
+const { createFactory, PureComponent } = require("devtools/client/shared/vendor/react");
+const dom = require("devtools/client/shared/vendor/react-dom-factories");
+const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
+
+const FluentReact = require("devtools/client/shared/vendor/fluent-react");
+const Localized = createFactory(FluentReact.Localized);
+
+const Actions = require("../actions/index");
+
+const DOC_URL =
+  "https://developer.mozilla.org/docs/Tools/about:debugging#Enabling_add-on_debugging";
+
+class ExtensionDebugSetting extends PureComponent {
+  static get propTypes() {
+    return {
+      dispatch: PropTypes.func.isRequired,
+      extensionDebugEnabled: PropTypes.bool.isRequired,
+    };
+  }
+
+  onToggle() {
+    const { extensionDebugEnabled, dispatch } = this.props;
+    dispatch(Actions.updateExtensionDebugSetting(!extensionDebugEnabled));
+  }
+
+  renderCheckbox() {
+    const { extensionDebugEnabled } = this.props;
+
+    return dom.input(
+      {
+        type: "checkbox",
+        id: "extension-debug-setting-input",
+        className: "default-checkbox",
+        checked: extensionDebugEnabled,
+        onChange: () => this.onToggle(),
+      }
+    );
+  }
+
+  renderLabel() {
+    return Localized(
+      {
+        id: "about-debugging-extension-debug-setting-label",
+        a: dom.a({
+          href: DOC_URL,
+          target: "_blank",
+        }),
+      },
+      dom.label(
+        {
+          className: "unselectable-text",
+          htmlFor: "extension-debug-setting-input",
+        },
+        "Enable extension debugging [Learn more]"
+      )
+    );
+  }
+
+  render() {
+    return dom.aside(
+      {},
+      this.renderCheckbox(),
+      this.renderLabel(),
+    );
+  }
+}
+
+module.exports = ExtensionDebugSetting;
--- a/devtools/client/aboutdebugging-new/src/components/RuntimePage.js
+++ b/devtools/client/aboutdebugging-new/src/components/RuntimePage.js
@@ -10,16 +10,17 @@ const dom = require("devtools/client/sha
 const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
 
 const FluentReact = require("devtools/client/shared/vendor/fluent-react");
 const Localized = createFactory(FluentReact.Localized);
 
 const CompatibilityWarning = createFactory(require("./CompatibilityWarning"));
 const ConnectionPromptSetting = createFactory(require("./ConnectionPromptSetting"));
 const DebugTargetPane = createFactory(require("./debugtarget/DebugTargetPane"));
+const ExtensionDebugSetting = createFactory(require("./ExtensionDebugSetting"));
 const ExtensionDetail = createFactory(require("./debugtarget/ExtensionDetail"));
 const InspectAction = createFactory(require("./debugtarget/InspectAction"));
 const ProfilerDialog = createFactory(require("./ProfilerDialog"));
 const RuntimeInfo = createFactory(require("./RuntimeInfo"));
 const ServiceWorkerAction = createFactory(require("./debugtarget/ServiceWorkerAction"));
 const ServiceWorkersWarning = createFactory(require("./ServiceWorkersWarning"));
 const TabDetail = createFactory(require("./debugtarget/TabDetail"));
 const TemporaryExtensionAction = createFactory(require("./debugtarget/TemporaryExtensionAction"));
@@ -28,17 +29,20 @@ const TemporaryExtensionInstaller =
   createFactory(require("./debugtarget/TemporaryExtensionInstaller"));
 const WorkerDetail = createFactory(require("./debugtarget/WorkerDetail"));
 
 const Actions = require("../actions/index");
 const { DEBUG_TARGET_PANE, PAGE_TYPES, RUNTIMES } = require("../constants");
 const Types = require("../types/index");
 
 const { getCurrentRuntimeDetails } = require("../modules/runtimes-state-helper");
-const { isSupportedDebugTargetPane } = require("../modules/debug-target-support");
+const {
+  isExtensionDebugSettingNeeded,
+  isSupportedDebugTargetPane,
+} = require("../modules/debug-target-support");
 
 class RuntimePage extends PureComponent {
   static get propTypes() {
     return {
       collapsibilities: Types.collapsibilities.isRequired,
       dispatch: PropTypes.func.isRequired,
       installedExtensions: PropTypes.arrayOf(PropTypes.object).isRequired,
       otherWorkers: PropTypes.arrayOf(PropTypes.object).isRequired,
@@ -120,16 +124,22 @@ class RuntimePage extends PureComponent 
         dispatch,
         isCollapsed: collapsibilities.get(paneKey),
         name,
         targets,
       })
     );
   }
 
+  renderExtensionDebugSetting() {
+    const { runtimeDetails, dispatch } = this.props;
+    const { extensionDebugEnabled } = runtimeDetails;
+    return ExtensionDebugSetting({ extensionDebugEnabled, dispatch });
+  }
+
   render() {
     const {
       dispatch,
       installedExtensions,
       otherWorkers,
       runtimeDetails,
       serviceWorkers,
       sharedWorkers,
@@ -150,16 +160,20 @@ class RuntimePage extends PureComponent 
     return dom.article(
       {
         className: "page js-runtime-page",
       },
       RuntimeInfo(runtimeDetails.info),
       this.renderRemoteRuntimeActions(),
       runtimeDetails.serviceWorkersAvailable ? null : ServiceWorkersWarning(),
       CompatibilityWarning({ compatibilityReport }),
+      // show component to enable/disable extension debugging.
+      isExtensionDebugSettingNeeded(type)
+        ? this.renderExtensionDebugSetting()
+        : null,
       isSupportedDebugTargetPane(type, DEBUG_TARGET_PANE.TEMPORARY_EXTENSION)
         ? TemporaryExtensionInstaller({
             dispatch,
             temporaryInstallError,
         }) : null,
       this.renderDebugTargetPane("Temporary Extensions",
                                  temporaryExtensions,
                                  TemporaryExtensionAction,
--- a/devtools/client/aboutdebugging-new/src/components/moz.build
+++ b/devtools/client/aboutdebugging-new/src/components/moz.build
@@ -9,15 +9,16 @@ DIRS += [
     'sidebar',
 ]
 
 DevToolsModules(
     'App.css',
     'App.js',
     'CompatibilityWarning.js',
     'ConnectionPromptSetting.js',
+    'ExtensionDebugSetting.js',
     'ProfilerDialog.css',
     'ProfilerDialog.js',
     'RuntimeInfo.js',
     'RuntimePage.css',
     'RuntimePage.js',
     'ServiceWorkersWarning.js',
 )
--- a/devtools/client/aboutdebugging-new/src/constants.js
+++ b/devtools/client/aboutdebugging-new/src/constants.js
@@ -45,16 +45,19 @@ const actionTypes = {
   TEMPORARY_EXTENSION_INSTALL_SUCCESS: "TEMPORARY_EXTENSION_INSTALL_SUCCESS",
   THIS_FIREFOX_RUNTIME_CREATED: "THIS_FIREFOX_RUNTIME_CREATED",
   UNWATCH_RUNTIME_FAILURE: "UNWATCH_RUNTIME_FAILURE",
   UNWATCH_RUNTIME_START: "UNWATCH_RUNTIME_START",
   UNWATCH_RUNTIME_SUCCESS: "UNWATCH_RUNTIME_SUCCESS",
   UPDATE_CONNECTION_PROMPT_SETTING_FAILURE: "UPDATE_CONNECTION_PROMPT_SETTING_FAILURE",
   UPDATE_CONNECTION_PROMPT_SETTING_START: "UPDATE_CONNECTION_PROMPT_SETTING_START",
   UPDATE_CONNECTION_PROMPT_SETTING_SUCCESS: "UPDATE_CONNECTION_PROMPT_SETTING_SUCCESS",
+  UPDATE_EXTENSION_DEBUG_SETTING_FAILURE: "UPDATE_EXTENSION_DEBUG_SETTING_FAILURE",
+  UPDATE_EXTENSION_DEBUG_SETTING_START: "UPDATE_EXTENSION_DEBUG_SETTING_START",
+  UPDATE_EXTENSION_DEBUG_SETTING_SUCCESS: "UPDATE_EXTENSION_DEBUG_SETTING_SUCCESS",
   UPDATE_RUNTIME_MULTIE10S_FAILURE: "UPDATE_RUNTIME_MULTIE10S_FAILURE",
   UPDATE_RUNTIME_MULTIE10S_START: "UPDATE_RUNTIME_MULTIE10S_START",
   UPDATE_RUNTIME_MULTIE10S_SUCCESS: "UPDATE_RUNTIME_MULTIE10S_SUCCESS",
   USB_RUNTIMES_SCAN_START: "USB_RUNTIMES_SCAN_START",
   USB_RUNTIMES_SCAN_SUCCESS: "USB_RUNTIMES_SCAN_SUCCESS",
   WATCH_RUNTIME_FAILURE: "WATCH_RUNTIME_FAILURE",
   WATCH_RUNTIME_START: "WATCH_RUNTIME_START",
   WATCH_RUNTIME_SUCCESS: "WATCH_RUNTIME_SUCCESS",
@@ -90,18 +93,20 @@ const PREFERENCES = {
   NETWORK_ENABLED: "devtools.aboutdebugging.network",
   // Preference that drives the display of system addons in about:debugging.
   SHOW_SYSTEM_ADDONS: "devtools.aboutdebugging.showSystemAddons",
   // Temporary preference without any default value until wifi is enabled.
   WIFI_ENABLED: "devtools.aboutdebugging.wifi",
 };
 
 const RUNTIME_PREFERENCE = {
+  CHROME_DEBUG_ENABLED: "devtools.chrome.enabled",
   CONNECTION_PROMPT: "devtools.debugger.prompt-connection",
   PERMANENT_PRIVATE_BROWSING: "browser.privatebrowsing.autostart",
+  REMOTE_DEBUG_ENABLED: "devtools.debugger.remote-enabled",
   SERVICE_WORKERS_ENABLED: "dom.serviceWorkers.enabled",
 };
 
 const RUNTIMES = {
   NETWORK: CONNECTION_TYPES.NETWORK,
   THIS_FIREFOX: CONNECTION_TYPES.THIS_FIREFOX,
   USB: CONNECTION_TYPES.USB,
 };
--- a/devtools/client/aboutdebugging-new/src/modules/client-wrapper.js
+++ b/devtools/client/aboutdebugging-new/src/modules/client-wrapper.js
@@ -11,18 +11,20 @@ const { RUNTIME_PREFERENCE } = require("
 const { WorkersListener } = require("./workers-listener");
 
 const PREF_TYPES = {
   BOOL: "BOOL",
 };
 
 // Map of preference to preference type.
 const PREF_TO_TYPE = {
+  [RUNTIME_PREFERENCE.CHROME_DEBUG_ENABLED]: PREF_TYPES.BOOL,
   [RUNTIME_PREFERENCE.CONNECTION_PROMPT]: PREF_TYPES.BOOL,
   [RUNTIME_PREFERENCE.PERMANENT_PRIVATE_BROWSING]: PREF_TYPES.BOOL,
+  [RUNTIME_PREFERENCE.REMOTE_DEBUG_ENABLED]: PREF_TYPES.BOOL,
   [RUNTIME_PREFERENCE.SERVICE_WORKERS_ENABLED]: PREF_TYPES.BOOL,
 };
 
 // Some events are fired by mainRoot rather than client.
 const MAIN_ROOT_EVENTS = [
   "addonListChanged",
   "tabListChanged",
 ];
--- a/devtools/client/aboutdebugging-new/src/modules/debug-target-support.js
+++ b/devtools/client/aboutdebugging-new/src/modules/debug-target-support.js
@@ -21,15 +21,28 @@ const REMOTE_DEBUG_TARGET_PANES = ALL_DE
 
 const SUPPORTED_TARGET_PANE_BY_RUNTIME = {
   [RUNTIMES.THIS_FIREFOX]: ALL_DEBUG_TARGET_PANES,
   [RUNTIMES.USB]: REMOTE_DEBUG_TARGET_PANES,
   [RUNTIMES.NETWORK]: REMOTE_DEBUG_TARGET_PANES,
 };
 
 /**
+ * If extension debug setting is needed for given runtime type, return true.
+ *
+ * @param {String} runtimeType
+ * @return {bool} true: needed
+ */
+function isExtensionDebugSettingNeeded(runtimeType) {
+  // Debugging local addons for This Firefox reuses the Browser Toolbox, which requires
+  // some preferences to be enabled.
+  return runtimeType === RUNTIMES.THIS_FIREFOX;
+}
+exports.isExtensionDebugSettingNeeded = isExtensionDebugSettingNeeded;
+
+/**
  * A debug target pane is more specialized than a debug target. For instance EXTENSION is
  * a DEBUG_TARGET but INSTALLED_EXTENSION and TEMPORARY_EXTENSION are DEBUG_TARGET_PANES.
  */
 function isSupportedDebugTargetPane(runtimeType, debugTargetPaneKey) {
   return SUPPORTED_TARGET_PANE_BY_RUNTIME[runtimeType].includes(debugTargetPaneKey);
 }
 exports.isSupportedDebugTargetPane = isSupportedDebugTargetPane;
--- a/devtools/client/aboutdebugging-new/src/reducers/runtimes-state.js
+++ b/devtools/client/aboutdebugging-new/src/reducers/runtimes-state.js
@@ -4,16 +4,17 @@
 
 "use strict";
 
 const {
   CONNECT_RUNTIME_SUCCESS,
   DISCONNECT_RUNTIME_SUCCESS,
   RUNTIMES,
   UPDATE_CONNECTION_PROMPT_SETTING_SUCCESS,
+  UPDATE_EXTENSION_DEBUG_SETTING_SUCCESS,
   UPDATE_RUNTIME_MULTIE10S_SUCCESS,
   REMOTE_RUNTIMES_UPDATED,
   SELECTED_RUNTIME_ID_UPDATED,
   THIS_FIREFOX_RUNTIME_CREATED,
 } = require("../constants");
 
 const {
   findRuntimeById,
@@ -92,16 +93,25 @@ function runtimesReducer(state = Runtime
       const { connectionPromptEnabled } = action;
       const { id: runtimeId } = action.runtime;
       const runtime = findRuntimeById(runtimeId, state);
       const runtimeDetails =
         Object.assign({}, runtime.runtimeDetails, { connectionPromptEnabled });
       return _updateRuntimeById(runtimeId, { runtimeDetails }, state);
     }
 
+    case UPDATE_EXTENSION_DEBUG_SETTING_SUCCESS: {
+      const { extensionDebugEnabled } = action;
+      const { id: runtimeId } = action.runtime;
+      const runtime = findRuntimeById(runtimeId, state);
+      const runtimeDetails =
+        Object.assign({}, runtime.runtimeDetails, { extensionDebugEnabled });
+      return _updateRuntimeById(runtimeId, { runtimeDetails }, state);
+    }
+
     case UPDATE_RUNTIME_MULTIE10S_SUCCESS: {
       const { isMultiE10s } = action;
       const { id: runtimeId } = action.runtime;
       const runtime = findRuntimeById(runtimeId, state);
       const runtimeDetails =
         Object.assign({}, runtime.runtimeDetails, { isMultiE10s });
       return _updateRuntimeById(runtimeId, { runtimeDetails }, state);
     }
--- a/devtools/client/aboutdebugging-new/src/types/runtime.js
+++ b/devtools/client/aboutdebugging-new/src/types/runtime.js
@@ -50,16 +50,20 @@ const runtimeDetails = {
 
   // compatibility report to check if the target runtime is in range of the backward
   // compatibility policy for DevTools remote debugging.
   compatibilityReport: PropTypes.shape(compatibilityReport).isRequired,
 
   // reflect devtools.debugger.prompt-connection preference of this runtime
   connectionPromptEnabled: PropTypes.bool.isRequired,
 
+  // In case that runtime is this-firefox, reflects devtools.chrome.enabled and
+  // devtools.debugger.remote-enabled preference. Otherwise, this sould be true.
+  extensionDebugEnabled: PropTypes.bool.isRequired,
+
   // runtime information
   info: PropTypes.shape(runtimeInfo).isRequired,
 
   // True if this runtime supports multiple content processes
   // This might be undefined when connecting to runtimes older than Fx 66
   isMultiE10s: PropTypes.bool,
 
   // True if service workers should be available in the target runtime. Service workers
--- a/devtools/client/aboutdebugging-new/tmp-locale/en-US/aboutdebugging.notftl
+++ b/devtools/client/aboutdebugging-new/tmp-locale/en-US/aboutdebugging.notftl
@@ -295,8 +295,14 @@ about-debugging-page-title-selected-page
 # { $selectedRuntimeId } is the id of the current runtime, such as "this-firefox", "localhost:6080", ...
 about-debugging-page-title-with-runtime = { -application-title } - { about-debugging-page-title-selected-page } / { $selectedRuntimeId }
 
 # Page title without the runtime displayed in the tab
 about-debugging-page-title = { -application-title } - { about-debugging-page-title-selected-page }
 
 # Title of a modal dialog displayed on remote runtime pages after clicking on the Profile Runtime button.
 about-debugging-profiler-dialog-title = Performance Profiler
+
+# Label of a checkbox displayed in the runtime page for "This Firefox".
+# This checkbox will toggle preferences that enable local addon debugging.
+# The "Learn more" link points to MDN.
+# https://developer.mozilla.org/docs/Tools/about:debugging#Enabling_add-on_debugging
+about-debugging-extension-debug-setting-label = Enable extension debugging <a>Learn more</a>