Bug 1471795 - Part 13: Add installing form for temporary extension. r?jdescottes, r?ladybenko
MozReview-Commit-ID: G3EhOLzO7dn
--- a/devtools/client/aboutdebugging-new/aboutdebugging.css
+++ b/devtools/client/aboutdebugging-new/aboutdebugging.css
@@ -6,14 +6,15 @@
@import "resource://devtools/client/themes/variables.css";
@import "resource://devtools/client/aboutdebugging-new/src/components/App.css";
@import "resource://devtools/client/aboutdebugging-new/src/components/DebugTargetsPane.css";
@import "resource://devtools/client/aboutdebugging-new/src/components/RuntimeInfo.css";
@import "resource://devtools/client/aboutdebugging-new/src/components/RuntimesPane.css";
@import "resource://devtools/client/aboutdebugging-new/src/components/debugtarget/DebugTargetItem.css";
@import "resource://devtools/client/aboutdebugging-new/src/components/debugtarget/DebugTargetList.css";
@import "resource://devtools/client/aboutdebugging-new/src/components/debugtarget/ExtensionItem.css";
+@import "resource://devtools/client/aboutdebugging-new/src/components/debugtarget/TemporaryExtensionInstaller.css";
@import "resource://devtools/client/aboutdebugging-new/src/components/runtime/ThisFirefoxItem.css";
#mount {
height: 100%;
width: 100%;
}
--- a/devtools/client/aboutdebugging-new/src/components/DebugTargetsPane.js
+++ b/devtools/client/aboutdebugging-new/src/components/DebugTargetsPane.js
@@ -9,16 +9,18 @@ const dom = require("devtools/client/sha
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const Runtime = require("../runtimes/runtime");
const DebugTargetList = createFactory(require("./debugtarget/DebugTargetList"));
const ExtensionItem = createFactory(require("./debugtarget/ExtensionItem"));
const RuntimeInfo = createFactory(require("./RuntimeInfo"));
const TabItem = createFactory(require("./debugtarget/TabItem"));
+const TemporaryExtensionInstaller =
+ createFactory(require("./debugtarget/TemporaryExtensionInstaller"));
class DebugTargetsPane extends PureComponent {
static get propTypes() {
return {
runtime: PropTypes.instanceOf(Runtime).isRequired,
};
}
@@ -100,16 +102,17 @@ class DebugTargetsPane extends PureCompo
{
className: "debug-targets-pane",
},
RuntimeInfo({ info }),
DebugTargetList({
className: "debug-target-list--temporary-extensions",
debugTargetItemComponent: ExtensionItem,
debugTargets: temporaryExtensions,
+ headerComponent: TemporaryExtensionInstaller,
runtime,
title: "Temporary Extensions",
}),
DebugTargetList({
className: "debug-target-list--installed-extensions",
debugTargetItemComponent: ExtensionItem,
debugTargets: installedExtensions,
runtime,
--- a/devtools/client/aboutdebugging-new/src/components/debugtarget/DebugTargetList.js
+++ b/devtools/client/aboutdebugging-new/src/components/debugtarget/DebugTargetList.js
@@ -11,40 +11,43 @@ const PropTypes = require("devtools/clie
const Runtime = require("../../runtimes/runtime");
class DebugTargetList extends PureComponent {
static get propTypes() {
return {
className: PropTypes.string.isRequired,
debugTargetItemComponent: PropTypes.any.isRequired,
debugTargets: PropTypes.arrayOf(PropTypes.object).isRequired,
+ headerComponent: PropTypes.any,
runtime: PropTypes.instanceOf(Runtime).isRequired,
title: PropTypes.string.isRequired,
};
}
render() {
const {
className,
debugTargetItemComponent,
debugTargets,
+ headerComponent,
runtime,
title,
} = this.props;
return dom.div(
{
className: `debug-target-list ${ className }`,
},
dom.h2(
{
className: `debug-target-list__title ${ className }__title`,
},
title
),
+ headerComponent ? headerComponent({ runtime }) : null,
dom.ul(
{
className: `debug-target-list__ul ${ className }__ul`,
},
debugTargets.map(
debugTarget => debugTargetItemComponent({ debugTarget, runtime }))
)
);
new file mode 100644
--- /dev/null
+++ b/devtools/client/aboutdebugging-new/src/components/debugtarget/TemporaryExtensionInstaller.css
@@ -0,0 +1,7 @@
+/* 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/. */
+
+.temporary-extension-installer {
+ margin-block-end: 10px;
+}
new file mode 100644
--- /dev/null
+++ b/devtools/client/aboutdebugging-new/src/components/debugtarget/TemporaryExtensionInstaller.js
@@ -0,0 +1,46 @@
+/* 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 { 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 Runtime = require("../../runtimes/runtime");
+
+class TemporaryExtensionInstaller extends PureComponent {
+ static get propTypes() {
+ return {
+ runtime: PropTypes.instanceOf(Runtime).isRequired,
+ };
+ }
+
+ async install() {
+ const { runtime } = this.props;
+
+ try {
+ await runtime.installTemporaryExtension();
+ } catch (e) {
+ console.error(e);
+ }
+ }
+
+ render() {
+ return dom.div(
+ {
+ className: "temporary-extension-installer",
+ },
+ dom.button(
+ {
+ className: "temporary-extension-installer__install-button",
+ onClick: e => this.install()
+ },
+ "Load Temporary Add-on…"
+ )
+ );
+ }
+}
+
+module.exports = TemporaryExtensionInstaller;
--- a/devtools/client/aboutdebugging-new/src/components/debugtarget/moz.build
+++ b/devtools/client/aboutdebugging-new/src/components/debugtarget/moz.build
@@ -4,10 +4,12 @@
DevToolsModules(
'DebugTargetItem.css',
'DebugTargetItem.js',
'DebugTargetList.css',
'DebugTargetList.js',
'ExtensionItem.css',
'ExtensionItem.js',
- 'TabItem.js'
+ 'TabItem.js',
+ 'TemporaryExtensionInstaller.css',
+ 'TemporaryExtensionInstaller.js'
)
--- a/devtools/client/aboutdebugging-new/src/runtimes/runtime.js
+++ b/devtools/client/aboutdebugging-new/src/runtimes/runtime.js
@@ -99,16 +99,24 @@ class Runtime {
* Subclass should override this method.
* @param {Object} - debug target
*/
async inspectTab(_) {
throw new Error("Subclass of Runtime should override inspectTab()");
}
/**
+ * Install temporary extension.
+ * Subclass should override this method.
+ */
+ async installTemporaryExtension() {
+ throw new Error("Subclass of Runtime should override installTemporaryExtension()");
+ }
+
+ /**
* Remove a tab update listener.
* Subclass should override this method.
* @param {function}
*/
removeExtensionsUpdateListener(listener) {
throw new Error("Subclass of Runtime should override " +
"removeExtensionsUpdateListener()");
}
--- a/devtools/client/aboutdebugging-new/src/runtimes/this-firefox.js
+++ b/devtools/client/aboutdebugging-new/src/runtimes/this-firefox.js
@@ -1,14 +1,15 @@
/* 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 { Cc, Ci } = require("chrome");
const { AddonManager } = require("resource://gre/modules/AddonManager.jsm");
const { BrowserToolboxProcess } =
require("resource://devtools/client/framework/ToolboxProcess.jsm");
const { DebuggerClient } = require("devtools/shared/client/debugger-client");
const { DebuggerServer } = require("devtools/server/main");
const Services = require("Services");
const Runtime = require("./runtime");
@@ -84,16 +85,46 @@ class ThisFirefox extends Runtime {
}
});
}
async inspectTab(debugTarget) {
window.open(`about:devtools-toolbox?type=tab&id=${ debugTarget.outerWindowID }`);
}
+ async installTemporaryExtension() {
+ return new Promise((resolve, reject) => {
+ const fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+ fp.init(window,
+ "Select Manifest File or Package (.xpi)",
+ Ci.nsIFilePicker.modeOpen);
+ fp.open(async res => {
+ 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.leafName.endsWith(".zip")) {
+ file = file.parent;
+ }
+
+ try {
+ await AddonManager.installTemporaryAddon(file);
+ resolve();
+ } catch (e) {
+ reject(e);
+ }
+ });
+ });
+ }
+
removeExtensionsUpdateListener(listener) {
const index = this.extensionsListeners.indexOf(listener);
if (index > -1) {
this.extensionsListeners.splice(index, 1);
}
}