Bug 1398734 - Implement devtools inspector extension page sidebar container component.
MozReview-Commit-ID: HbHoV32Xk3s
--- a/devtools/client/inspector/extensions/actions/index.js
+++ b/devtools/client/inspector/extensions/actions/index.js
@@ -6,12 +6,15 @@
const { createEnum } = require("devtools/client/shared/enum");
createEnum([
// Update the extension sidebar with an object TreeView.
"EXTENSION_SIDEBAR_OBJECT_TREEVIEW_UPDATE",
+ // Switch the extension sidebar into an extension page container.
+ "EXTENSION_SIDEBAR_PAGE_UPDATE",
+
// Remove an extension sidebar from the inspector store.
"EXTENSION_SIDEBAR_REMOVE"
], module.exports);
--- a/devtools/client/inspector/extensions/actions/sidebar.js
+++ b/devtools/client/inspector/extensions/actions/sidebar.js
@@ -1,16 +1,17 @@
/* 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 {
EXTENSION_SIDEBAR_OBJECT_TREEVIEW_UPDATE,
+ EXTENSION_SIDEBAR_PAGE_UPDATE,
EXTENSION_SIDEBAR_REMOVE,
} = require("./index");
module.exports = {
/**
* Update the sidebar with an object treeview.
*/
@@ -18,16 +19,26 @@ module.exports = {
return {
type: EXTENSION_SIDEBAR_OBJECT_TREEVIEW_UPDATE,
sidebarId,
object,
};
},
/**
+ * Switch the sidebar into the extension page mode.
+ */
+ updateExtensionPage(sidebarId) {
+ return {
+ type: EXTENSION_SIDEBAR_PAGE_UPDATE,
+ sidebarId,
+ };
+ },
+
+ /**
* Remove the extension sidebar from the inspector store.
*/
removeExtensionSidebar(sidebarId) {
return {
type: EXTENSION_SIDEBAR_REMOVE,
sidebarId,
};
}
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/extensions/components/ExtensionPage.js
@@ -0,0 +1,49 @@
+/* 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 {
+ createClass,
+ DOM: dom,
+ PropTypes,
+} = require("devtools/client/shared/vendor/react");
+
+/**
+ * The ExtensionPage React Component is used in the ExtensionSidebar component to provide
+ * a UI viewMode which shows an extension page rendered inside the sidebar panel.
+ */
+const ExtensionPage = createClass({
+ displayName: "ExtensionPage",
+
+ propTypes: {
+ onExtensionPageMount: PropTypes.func.isRequired,
+ onExtensionPageUnmount: PropTypes.func.isRequired,
+ },
+
+ componentDidMount() {
+ this.props.onExtensionPageMount(this.containerEl);
+ },
+
+ componentWillUnmount() {
+ this.props.onExtensionPageUnmount(this.containerEl);
+ },
+
+ render() {
+ return dom.div({
+ className: "inspector-extension-sidebar-page",
+ style: {
+ flex: "auto",
+ height: "100%",
+ margin: 0,
+ padding: 0,
+ },
+ ref: (divEl) => {
+ this.containerEl = divEl;
+ },
+ });
+ },
+});
+
+module.exports = ExtensionPage;
--- a/devtools/client/inspector/extensions/components/ExtensionSidebar.js
+++ b/devtools/client/inspector/extensions/components/ExtensionSidebar.js
@@ -9,55 +9,76 @@ const {
createClass, createFactory,
DOM: dom,
PropTypes,
} = require("devtools/client/shared/vendor/react");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const ObjectTreeView = createFactory(require("./ObjectTreeView"));
+const ExtensionPage = createFactory(require("./ExtensionPage"));
/**
* The ExtensionSidebar is a React component with 2 supported viewMode:
* - an ObjectTreeView UI, used to show the JS objects (used by the sidebar.setObject
* and sidebar.setExpression WebExtensions APIs)
* - an ExtensionPage UI used to show an extension page (used by the sidebar.setPage
* WebExtensions APIs).
*
* TODO: implement the ExtensionPage viewMode.
*/
const ExtensionSidebar = createClass({
displayName: "ExtensionSidebar",
propTypes: {
id: PropTypes.string.isRequired,
extensionsSidebar: PropTypes.object.isRequired,
+ onExtensionPageMount: PropTypes.func.isRequired,
+ onExtensionPageUnmount: PropTypes.func.isRequired,
},
mixins: [ addons.PureRenderMixin ],
render() {
- const { id, extensionsSidebar } = this.props;
+ const {
+ id,
+ extensionsSidebar,
+ onExtensionPageMount,
+ onExtensionPageUnmount,
+ } = this.props;
let {
viewMode = "empty-sidebar",
- object
+ object,
} = extensionsSidebar[id] || {};
let sidebarContentEl;
switch (viewMode) {
case "object-treeview":
sidebarContentEl = ObjectTreeView({ object });
break;
+ case "extension-page":
+ sidebarContentEl = ExtensionPage({
+ onExtensionPageMount,
+ onExtensionPageUnmount,
+ });
+ break;
case "empty-sidebar":
break;
default:
throw new Error(`Unknown ExtensionSidebar viewMode: "${viewMode}"`);
}
const className = "devtools-monospace extension-sidebar inspector-tabpanel";
- return dom.div({ id, className }, sidebarContentEl);
+ return dom.div({
+ id,
+ className,
+ style: {
+ flex: "auto",
+ height: "100%",
+ },
+ }, sidebarContentEl);
}
});
module.exports = connect(state => state)(ExtensionSidebar);
--- a/devtools/client/inspector/extensions/components/moz.build
+++ b/devtools/client/inspector/extensions/components/moz.build
@@ -1,10 +1,11 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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(
+ 'ExtensionPage.js',
'ExtensionSidebar.js',
'ObjectTreeView.js',
)
--- a/devtools/client/inspector/extensions/extension-sidebar.js
+++ b/devtools/client/inspector/extensions/extension-sidebar.js
@@ -2,23 +2,25 @@
* 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 {
createElement, createFactory,
} = require("devtools/client/shared/vendor/react");
+const EventEmitter = require("devtools/shared/old-event-emitter");
const { Provider } = require("devtools/client/shared/vendor/react-redux");
const ExtensionSidebarComponent = createFactory(require("./components/ExtensionSidebar"));
const {
updateObjectTreeView,
+ updateExtensionPage,
removeExtensionSidebar,
} = require("./actions/sidebar");
/**
* ExtensionSidebar instances represents Inspector sidebars installed by add-ons
* using the devtools.panels.elements.createSidebarPane WebExtensions API.
*
* The WebExtensions API registers the extensions' sidebars on the toolbox instance
@@ -31,16 +33,17 @@ const {
* @param {Object} options
* @param {String} options.id
* The unique id of the sidebar.
* @param {String} options.title
* The title of the sidebar.
*/
class ExtensionSidebar {
constructor(inspector, {id, title}) {
+ EventEmitter.decorate(this);
this.inspector = inspector;
this.store = inspector.store;
this.id = id;
this.title = title;
this.destroyed = false;
}
@@ -50,16 +53,22 @@ class ExtensionSidebar {
get provider() {
if (!this._provider) {
this._provider = createElement(Provider, {
store: this.store,
key: this.id,
title: this.title,
}, ExtensionSidebarComponent({
id: this.id,
+ onExtensionPageMount: (containerEl) => {
+ this.emit("extension-page-mount", containerEl);
+ },
+ onExtensionPageUnmount: (containerEl) => {
+ this.emit("extension-page-unmount", containerEl);
+ },
}));
}
return this._provider;
}
/**
* Destroy the ExtensionSidebar instance, dispatch a removeExtensionSidebar Redux action
@@ -91,11 +100,19 @@ class ExtensionSidebar {
*/
setObject(object) {
if (this.removed) {
throw new Error("Unable to set an object preview on a removed ExtensionSidebar");
}
this.store.dispatch(updateObjectTreeView(this.id, object));
}
+
+ setExtensionPage() {
+ if (this.removed) {
+ throw new Error("Unable to set an object preview on a removed ExtensionSidebar");
+ }
+
+ this.store.dispatch(updateExtensionPage(this.id));
+ }
}
module.exports = ExtensionSidebar;
--- a/devtools/client/inspector/extensions/reducers/sidebar.js
+++ b/devtools/client/inspector/extensions/reducers/sidebar.js
@@ -1,16 +1,17 @@
/* 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 {
EXTENSION_SIDEBAR_OBJECT_TREEVIEW_UPDATE,
+ EXTENSION_SIDEBAR_PAGE_UPDATE,
EXTENSION_SIDEBAR_REMOVE,
} = require("../actions/index");
const INITIAL_SIDEBAR = {};
let reducers = {
[EXTENSION_SIDEBAR_OBJECT_TREEVIEW_UPDATE](sidebar, {sidebarId, object}) {
@@ -19,16 +20,26 @@ let reducers = {
return Object.assign({}, sidebar, {
[sidebarId]: {
viewMode: "object-treeview",
object,
}
});
},
+ [EXTENSION_SIDEBAR_PAGE_UPDATE](sidebar, {sidebarId}) {
+ // Update the sidebar to a "object-treeview" which shows
+ // the passed object.
+ return Object.assign({}, sidebar, {
+ [sidebarId]: {
+ viewMode: "extension-page",
+ }
+ });
+ },
+
[EXTENSION_SIDEBAR_REMOVE](sidebar, {sidebarId}) {
// Remove the sidebar from the Redux store.
delete sidebar[sidebarId];
return Object.assign({}, sidebar);
},
};