summaryrefslogtreecommitdiffstats
path: root/devtools/client/aboutdebugging/components/addons
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/aboutdebugging/components/addons')
-rw-r--r--devtools/client/aboutdebugging/components/addons/controls.js97
-rw-r--r--devtools/client/aboutdebugging/components/addons/install-error.js26
-rw-r--r--devtools/client/aboutdebugging/components/addons/moz.build10
-rw-r--r--devtools/client/aboutdebugging/components/addons/panel.js146
-rw-r--r--devtools/client/aboutdebugging/components/addons/target.js84
5 files changed, 363 insertions, 0 deletions
diff --git a/devtools/client/aboutdebugging/components/addons/controls.js b/devtools/client/aboutdebugging/components/addons/controls.js
new file mode 100644
index 000000000..7f985528c
--- /dev/null
+++ b/devtools/client/aboutdebugging/components/addons/controls.js
@@ -0,0 +1,97 @@
+/* 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/. */
+
+/* eslint-env browser */
+/* globals AddonManager */
+
+"use strict";
+
+loader.lazyImporter(this, "AddonManager",
+ "resource://gre/modules/AddonManager.jsm");
+
+const { Cc, Ci } = require("chrome");
+const { createFactory, createClass, DOM: dom, PropTypes } =
+ require("devtools/client/shared/vendor/react");
+const Services = require("Services");
+const AddonsInstallError = createFactory(require("./install-error"));
+
+const Strings = Services.strings.createBundle(
+ "chrome://devtools/locale/aboutdebugging.properties");
+
+const MORE_INFO_URL = "https://developer.mozilla.org/docs/Tools" +
+ "/about:debugging#Enabling_add-on_debugging";
+
+module.exports = createClass({
+ displayName: "AddonsControls",
+
+ propTypes: {
+ debugDisabled: PropTypes.bool
+ },
+
+ getInitialState() {
+ return {
+ installError: null,
+ };
+ },
+
+ onEnableAddonDebuggingChange(event) {
+ let enabled = event.target.checked;
+ Services.prefs.setBoolPref("devtools.chrome.enabled", enabled);
+ Services.prefs.setBoolPref("devtools.debugger.remote-enabled", enabled);
+ },
+
+ loadAddonFromFile() {
+ this.setState({ installError: null });
+ let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+ fp.init(window,
+ Strings.GetStringFromName("selectAddonFromFile2"),
+ Ci.nsIFilePicker.modeOpen);
+ let res = fp.show();
+ if (res == Ci.nsIFilePicker.returnCancel || !fp.file) {
+ return;
+ }
+ let file = fp.file;
+ // AddonManager.installTemporaryAddon accepts either
+ // addon directory or final xpi file.
+ if (!file.isDirectory() && !file.leafName.endsWith(".xpi")) {
+ file = file.parent;
+ }
+
+ AddonManager.installTemporaryAddon(file)
+ .catch(e => {
+ console.error(e);
+ this.setState({ installError: e.message });
+ });
+ },
+
+ render() {
+ let { debugDisabled } = this.props;
+
+ return dom.div({ className: "addons-top" },
+ dom.div({ className: "addons-controls" },
+ dom.div({ className: "addons-options toggle-container-with-text" },
+ dom.input({
+ id: "enable-addon-debugging",
+ type: "checkbox",
+ checked: !debugDisabled,
+ onChange: this.onEnableAddonDebuggingChange,
+ }),
+ dom.label({
+ className: "addons-debugging-label",
+ htmlFor: "enable-addon-debugging",
+ title: Strings.GetStringFromName("addonDebugging.tooltip")
+ }, Strings.GetStringFromName("addonDebugging.label")),
+ "(",
+ dom.a({ href: MORE_INFO_URL, target: "_blank" },
+ Strings.GetStringFromName("moreInfo")),
+ ")"
+ ),
+ dom.button({
+ id: "load-addon-from-file",
+ onClick: this.loadAddonFromFile,
+ }, Strings.GetStringFromName("loadTemporaryAddon"))
+ ),
+ AddonsInstallError({ error: this.state.installError }));
+ }
+});
diff --git a/devtools/client/aboutdebugging/components/addons/install-error.js b/devtools/client/aboutdebugging/components/addons/install-error.js
new file mode 100644
index 000000000..aea1c4f09
--- /dev/null
+++ b/devtools/client/aboutdebugging/components/addons/install-error.js
@@ -0,0 +1,26 @@
+/* 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/. */
+
+/* eslint-env browser */
+"use strict";
+
+const { createClass, DOM: dom, PropTypes } = require("devtools/client/shared/vendor/react");
+
+module.exports = createClass({
+ displayName: "AddonsInstallError",
+
+ propTypes: {
+ error: PropTypes.string
+ },
+
+ render() {
+ if (!this.props.error) {
+ return null;
+ }
+ let text = `There was an error during installation: ${this.props.error}`;
+ return dom.div({ className: "addons-install-error" },
+ dom.div({ className: "warning" }),
+ dom.span({}, text));
+ }
+});
diff --git a/devtools/client/aboutdebugging/components/addons/moz.build b/devtools/client/aboutdebugging/components/addons/moz.build
new file mode 100644
index 000000000..378554f78
--- /dev/null
+++ b/devtools/client/aboutdebugging/components/addons/moz.build
@@ -0,0 +1,10 @@
+# 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/.
+
+DevToolsModules(
+ 'controls.js',
+ 'install-error.js',
+ 'panel.js',
+ 'target.js',
+)
diff --git a/devtools/client/aboutdebugging/components/addons/panel.js b/devtools/client/aboutdebugging/components/addons/panel.js
new file mode 100644
index 000000000..425a10a8d
--- /dev/null
+++ b/devtools/client/aboutdebugging/components/addons/panel.js
@@ -0,0 +1,146 @@
+/* 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 { AddonManager } = require("resource://gre/modules/AddonManager.jsm");
+const { createFactory, createClass, DOM: dom, PropTypes } =
+ require("devtools/client/shared/vendor/react");
+const Services = require("Services");
+
+const AddonsControls = createFactory(require("./controls"));
+const AddonTarget = createFactory(require("./target"));
+const PanelHeader = createFactory(require("../panel-header"));
+const TargetList = createFactory(require("../target-list"));
+
+loader.lazyRequireGetter(this, "DebuggerClient",
+ "devtools/shared/client/main", 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";
+
+module.exports = createClass({
+ displayName: "AddonsPanel",
+
+ propTypes: {
+ client: PropTypes.instanceOf(DebuggerClient).isRequired,
+ id: PropTypes.string.isRequired
+ },
+
+ getInitialState() {
+ return {
+ extensions: [],
+ debugDisabled: false,
+ };
+ },
+
+ componentDidMount() {
+ AddonManager.addAddonListener(this);
+
+ Services.prefs.addObserver(CHROME_ENABLED_PREF,
+ this.updateDebugStatus, false);
+ Services.prefs.addObserver(REMOTE_ENABLED_PREF,
+ this.updateDebugStatus, false);
+
+ this.updateDebugStatus();
+ this.updateAddonsList();
+ },
+
+ componentWillUnmount() {
+ AddonManager.removeAddonListener(this);
+ Services.prefs.removeObserver(CHROME_ENABLED_PREF,
+ this.updateDebugStatus);
+ Services.prefs.removeObserver(REMOTE_ENABLED_PREF,
+ this.updateDebugStatus);
+ },
+
+ updateDebugStatus() {
+ let debugDisabled =
+ !Services.prefs.getBoolPref(CHROME_ENABLED_PREF) ||
+ !Services.prefs.getBoolPref(REMOTE_ENABLED_PREF);
+
+ this.setState({ debugDisabled });
+ },
+
+ updateAddonsList() {
+ this.props.client.listAddons()
+ .then(({addons}) => {
+ let extensions = addons.filter(addon => addon.debuggable).map(addon => {
+ return {
+ name: addon.name,
+ icon: addon.iconURL || ExtensionIcon,
+ addonID: addon.id,
+ addonActor: addon.actor,
+ temporarilyInstalled: addon.temporarilyInstalled
+ };
+ });
+
+ this.setState({ extensions });
+ }, error => {
+ throw new Error("Client error while listing addons: " + error);
+ });
+ },
+
+ /**
+ * Mandatory callback as AddonManager listener.
+ */
+ onInstalled() {
+ this.updateAddonsList();
+ },
+
+ /**
+ * Mandatory callback as AddonManager listener.
+ */
+ onUninstalled() {
+ this.updateAddonsList();
+ },
+
+ /**
+ * Mandatory callback as AddonManager listener.
+ */
+ onEnabled() {
+ this.updateAddonsList();
+ },
+
+ /**
+ * Mandatory callback as AddonManager listener.
+ */
+ onDisabled() {
+ this.updateAddonsList();
+ },
+
+ render() {
+ let { client, id } = this.props;
+ let { debugDisabled, extensions: targets } = this.state;
+ let name = Strings.GetStringFromName("extensions");
+ let targetClass = AddonTarget;
+
+ return dom.div({
+ id: id + "-panel",
+ className: "panel",
+ role: "tabpanel",
+ "aria-labelledby": id + "-header"
+ },
+ PanelHeader({
+ id: id + "-header",
+ name: Strings.GetStringFromName("addons")
+ }),
+ AddonsControls({ debugDisabled }),
+ dom.div({ id: "addons" },
+ TargetList({
+ id: "extensions",
+ name,
+ targets,
+ client,
+ debugDisabled,
+ targetClass,
+ sort: true
+ })
+ ));
+ }
+});
diff --git a/devtools/client/aboutdebugging/components/addons/target.js b/devtools/client/aboutdebugging/components/addons/target.js
new file mode 100644
index 000000000..c21499650
--- /dev/null
+++ b/devtools/client/aboutdebugging/components/addons/target.js
@@ -0,0 +1,84 @@
+/* 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/. */
+
+/* eslint-env browser */
+
+"use strict";
+
+const { createClass, DOM: dom, PropTypes } =
+ require("devtools/client/shared/vendor/react");
+const { debugAddon } = require("../../modules/addon");
+const Services = require("Services");
+
+loader.lazyImporter(this, "BrowserToolboxProcess",
+ "resource://devtools/client/framework/ToolboxProcess.jsm");
+
+loader.lazyRequireGetter(this, "DebuggerClient",
+ "devtools/shared/client/main", true);
+
+const Strings = Services.strings.createBundle(
+ "chrome://devtools/locale/aboutdebugging.properties");
+
+module.exports = createClass({
+ displayName: "AddonTarget",
+
+ propTypes: {
+ client: PropTypes.instanceOf(DebuggerClient).isRequired,
+ debugDisabled: PropTypes.bool,
+ target: PropTypes.shape({
+ addonActor: PropTypes.string.isRequired,
+ addonID: PropTypes.string.isRequired,
+ icon: PropTypes.string,
+ name: PropTypes.string.isRequired,
+ temporarilyInstalled: PropTypes.bool
+ }).isRequired
+ },
+
+ debug() {
+ let { target } = this.props;
+ debugAddon(target.addonID);
+ },
+
+ reload() {
+ let { client, target } = this.props;
+ // This function sometimes returns a partial promise that only
+ // implements then().
+ client.request({
+ to: target.addonActor,
+ type: "reload"
+ }).then(() => {}, error => {
+ throw new Error(
+ "Error reloading addon " + target.addonID + ": " + error);
+ });
+ },
+
+ render() {
+ let { target, debugDisabled } = this.props;
+ // Only temporarily installed add-ons can be reloaded.
+ const canBeReloaded = target.temporarilyInstalled;
+
+ return dom.li({ className: "target-container" },
+ dom.img({
+ className: "target-icon",
+ role: "presentation",
+ src: target.icon
+ }),
+ dom.div({ className: "target" },
+ dom.div({ className: "target-name", title: target.name }, target.name)
+ ),
+ dom.button({
+ className: "debug-button",
+ onClick: this.debug,
+ disabled: debugDisabled,
+ }, Strings.GetStringFromName("debug")),
+ dom.button({
+ className: "reload-button",
+ onClick: this.reload,
+ disabled: !canBeReloaded,
+ title: !canBeReloaded ?
+ Strings.GetStringFromName("reloadDisabledTooltip") : ""
+ }, Strings.GetStringFromName("reload"))
+ );
+ }
+});