Bug 1425347 - Hide system add-ons by default in about:debugging r?jdescottes
MozReview-Commit-ID: 4bhF6Zxsn6w
--- a/devtools/client/aboutdebugging/components/addons/Panel.js
+++ b/devtools/client/aboutdebugging/components/addons/Panel.js
@@ -20,16 +20,17 @@ loader.lazyRequireGetter(this, "Debugger
"devtools/shared/client/debugger-client", true);
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/aboutdebugging.properties");
const ExtensionIcon = "chrome://mozapps/skin/extensions/extensionGeneric.svg";
const CHROME_ENABLED_PREF = "devtools.chrome.enabled";
const REMOTE_ENABLED_PREF = "devtools.debugger.remote-enabled";
+const SYSTEM_ENABLED_PREF = "devtools.aboutdebugging.showSystemAddons";
const WEB_EXT_URL = "https://developer.mozilla.org/Add-ons" +
"/WebExtensions/Getting_started_with_web-ext";
class AddonsPanel extends Component {
static get propTypes() {
return {
client: PropTypes.instanceOf(DebuggerClient).isRequired,
connect: PropTypes.object,
@@ -38,19 +39,21 @@ class AddonsPanel extends Component {
}
constructor(props) {
super(props);
this.state = {
extensions: [],
debugDisabled: false,
+ showSystemAddons: false,
};
this.updateDebugStatus = this.updateDebugStatus.bind(this);
+ this.updateShowSystemStatus = this.updateShowSystemStatus.bind(this);
this.updateAddonsList = this.updateAddonsList.bind(this);
this.onInstalled = this.onInstalled.bind(this);
this.onUninstalled = this.onUninstalled.bind(this);
this.onEnabled = this.onEnabled.bind(this);
this.onDisabled = this.onDisabled.bind(this);
}
componentDidMount() {
@@ -58,49 +61,60 @@ class AddonsPanel extends Component {
// Listen to startup since that's when errors and warnings
// get populated on the extension.
Management.on("startup", this.updateAddonsList);
Services.prefs.addObserver(CHROME_ENABLED_PREF,
this.updateDebugStatus);
Services.prefs.addObserver(REMOTE_ENABLED_PREF,
this.updateDebugStatus);
+ Services.prefs.addObserver(SYSTEM_ENABLED_PREF,
+ this.updateShowSystemStatus);
this.updateDebugStatus();
+ this.updateShowSystemStatus();
this.updateAddonsList();
}
componentWillUnmount() {
AddonManager.removeAddonListener(this);
Management.off("startup", this.updateAddonsList);
Services.prefs.removeObserver(CHROME_ENABLED_PREF,
this.updateDebugStatus);
Services.prefs.removeObserver(REMOTE_ENABLED_PREF,
this.updateDebugStatus);
+ Services.prefs.removeObserver(SYSTEM_ENABLED_PREF,
+ this.updateShowSystemStatus);
}
updateDebugStatus() {
const debugDisabled =
!Services.prefs.getBoolPref(CHROME_ENABLED_PREF) ||
!Services.prefs.getBoolPref(REMOTE_ENABLED_PREF);
this.setState({ debugDisabled });
}
+ updateShowSystemStatus() {
+ const showSystemAddons = Services.prefs.getBoolPref(SYSTEM_ENABLED_PREF, false);
+ this.setState({ showSystemAddons });
+ }
+
updateAddonsList() {
this.props.client.listAddons()
.then(({addons}) => {
const extensions = addons.filter(addon => addon.debuggable).map(addon => {
return {
addonTargetActor: addon.actor,
addonID: addon.id,
// Forward the whole addon actor form for potential remote debugging.
form: addon,
icon: addon.iconURL || ExtensionIcon,
+ isSystem: addon.isSystem,
manifestURL: addon.manifestURL,
name: addon.name,
temporarilyInstalled: addon.temporarilyInstalled,
url: addon.url,
warnings: addon.warnings,
};
});
@@ -135,23 +149,26 @@ class AddonsPanel extends Component {
* Mandatory callback as AddonManager listener.
*/
onDisabled() {
this.updateAddonsList();
}
render() {
const { client, connect, id } = this.props;
- const { debugDisabled, extensions: targets } = this.state;
+ const { debugDisabled, extensions: targets, showSystemAddons } = this.state;
const installedName = Strings.GetStringFromName("extensions");
const temporaryName = Strings.GetStringFromName("temporaryExtensions");
+ const systemName = Strings.GetStringFromName("systemExtensions");
const targetClass = AddonTarget;
- const installedTargets = targets.filter((target) => !target.temporarilyInstalled);
+ const installedTargets = targets.filter(
+ (target) => !target.isSystem && !target.temporarilyInstalled);
const temporaryTargets = targets.filter((target) => target.temporarilyInstalled);
+ const systemTargets = showSystemAddons && targets.filter((target) => target.isSystem);
return dom.div({
id: id + "-panel",
className: "panel",
role: "tabpanel",
"aria-labelledby": id + "-header"
},
PanelHeader({
@@ -186,13 +203,27 @@ class AddonsPanel extends Component {
name: installedName,
targets: installedTargets,
client,
connect,
debugDisabled,
targetClass,
sort: true
})
- ));
+ ),
+ showSystemAddons ?
+ dom.div({ id: "system-addons" },
+ TargetList({
+ id: "system-extensions",
+ name: systemName,
+ targets: systemTargets,
+ client,
+ connect,
+ debugDisabled,
+ targetClass,
+ sort: true
+ })
+ ) : null,
+ );
}
}
module.exports = AddonsPanel;
--- a/devtools/client/aboutdebugging/test/browser_addons_debug_info.js
+++ b/devtools/client/aboutdebugging/test/browser_addons_debug_info.js
@@ -1,11 +1,14 @@
"use strict";
+const { Preferences } = ChromeUtils.import("resource://gre/modules/Preferences.jsm", {});
+
const UUID_REGEX = /^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/;
+const SHOW_SYSTEM_ADDONS_PREF = "devtools.aboutdebugging.showSystemAddons";
function testFilePath(container, expectedFilePath) {
// Verify that the path to the install location is shown next to its label.
const filePath = container.querySelector(".file-path");
ok(filePath, "file path is in DOM");
ok(filePath.textContent.endsWith(expectedFilePath), "file path is set correctly");
is(filePath.previousElementSibling.textContent, "Location", "file path has label");
}
@@ -114,8 +117,31 @@ add_task(async function testUnknownManif
"the message is helpful");
ok(messages[0].classList.contains("addon-target-warning-message"),
"the message is a warning");
await uninstallAddon({document, id: addonId, name: addonName});
await closeAboutDebugging(tab);
});
+
+add_task(async function testSystemAddonsHidden() {
+ await pushPref(SHOW_SYSTEM_ADDONS_PREF, false);
+
+ const { document } = await openAboutDebugging("addons");
+ const systemAddonsShown = () => !!document.getElementById("system-extensions");
+
+ await waitForInitialAddonList(document);
+
+ ok(!systemAddonsShown(), "System extensions are hidden");
+
+ Preferences.set(SHOW_SYSTEM_ADDONS_PREF, true);
+
+ await waitUntil(systemAddonsShown);
+
+ ok(systemAddonsShown(), "System extensions are now shown");
+
+ Preferences.set(SHOW_SYSTEM_ADDONS_PREF, false);
+
+ await waitUntil(() => !systemAddonsShown());
+
+ ok(!systemAddonsShown(), "System extensions are hidden again");
+});
--- a/devtools/client/locales/en-US/aboutdebugging.properties
+++ b/devtools/client/locales/en-US/aboutdebugging.properties
@@ -71,16 +71,20 @@ retryTemporaryInstall = Retry
# LOCALIZATION NOTE (extensions):
# This string is displayed as a header above the list of loaded add-ons.
extensions = Extensions
# LOCALIZATION NOTE (temporaryExtensions):
# This string is displayed as a header above the list of temporarily loaded add-ons.
temporaryExtensions = Temporary Extensions
+# LOCALIZATION NOTE (systemExtensions):
+# This string is displayed as a header above the list of system add-ons.
+systemExtensions = System Extensions
+
# LOCALIZATION NOTE (internalUUID):
# This string is displayed as a label for the internal UUID of an extension.
# The UUID is generated for this profile on install.
internalUUID = Internal UUID
# LOCALIZATION NOTE (extensionID):
# This string is displayed as a label for the ID of an extension. This is not the same as the internal UUID.
extensionID = Extension ID
--- a/devtools/client/preferences/devtools-client.js
+++ b/devtools/client/preferences/devtools-client.js
@@ -310,8 +310,15 @@ pref("devtools.editor.enableCodeFolding"
pref("devtools.editor.autocomplete", true);
// Whether to reload when touch simulation is toggled
pref("devtools.responsive.reloadConditions.touchSimulation", false);
// Whether to reload when user agent is changed
pref("devtools.responsive.reloadConditions.userAgent", false);
// Whether to show the notification about reloading to apply emulation
pref("devtools.responsive.reloadNotification.enabled", true);
+
+// about:debugging: only show system add-ons in local builds by default.
+#ifdef MOZILLA_OFFICIAL
+ pref("devtools.aboutdebugging.showSystemAddons", false);
+#else
+ pref("devtools.aboutdebugging.showSystemAddons", true);
+#endif
--- a/devtools/server/actors/addon/webextension.js
+++ b/devtools/server/actors/addon/webextension.js
@@ -74,16 +74,17 @@ const WebExtensionActor = protocol.Actor
form() {
const policy = ExtensionParent.WebExtensionPolicy.getByID(this.id);
return {
actor: this.actorID,
id: this.id,
name: this.addon.name,
url: this.addon.sourceURI ? this.addon.sourceURI.spec : undefined,
iconURL: this.addon.iconURL,
+ isSystem: this.addon.isSystem,
debuggable: this.addon.isDebuggable,
temporarilyInstalled: this.addon.temporarilyInstalled,
type: this.addon.type,
isWebExtension: this.addon.isWebExtension,
isAPIExtension: this.addon.isAPIExtension,
manifestURL: policy && policy.getURL("manifest.json"),
warnings: ExtensionParent.DebugUtils.getExtensionManifestWarnings(this.id),
};
--- a/devtools/server/actors/targets/addon.js
+++ b/devtools/server/actors/targets/addon.js
@@ -82,16 +82,17 @@ AddonTargetActor.prototype = {
}
return {
actor: this.actorID,
id: this.id,
name: this._addon.name,
url: this.url,
iconURL: this._addon.iconURL,
+ isSystem: this._addon.isSystem,
debuggable: this._addon.isDebuggable,
temporarilyInstalled: this._addon.temporarilyInstalled,
type: this._addon.type,
isWebExtension: this._addon.isWebExtension,
isAPIExtension: this._addon.isAPIExtension,
consoleActor: this._consoleActor.actorID,
traits: {