--- a/devtools/shim/DevToolsShim.jsm
+++ b/devtools/shim/DevToolsShim.jsm
@@ -30,60 +30,78 @@ function removeItem(array, callback) {
* listening to events, register tools, themes. As soon as a DevTools addon is installed
* the DevToolsShim will forward all the requests received until then to the real DevTools
* instance.
*
* DevToolsShim.isInstalled() can also be used to know if DevTools are currently
* installed.
*/
this.DevToolsShim = {
- gDevTools: null,
+ _gDevTools: null,
listeners: [],
tools: [],
themes: [],
/**
+ * Lazy getter for the `gDevTools` instance. Should only be called when users interacts
+ * with DevTools as it will force loading them.
+ *
+ * @return {DevTools} a devtools instance (from client/framework/devtools)
+ */
+ get gDevTools() {
+ if (!this.isInstalled()) {
+ throw new Error(`Trying to interact with DevTools, but they are not installed`);
+ }
+
+ if (!this.isInitialized()) {
+ this._initDevTools();
+ }
+
+ return this._gDevTools;
+ },
+
+ /**
* Check if DevTools are currently installed (but not necessarily initialized).
*
* @return {Boolean} true if DevTools are installed.
*/
isInstalled: function () {
return Services.io.getProtocolHandler("resource")
.QueryInterface(Ci.nsIResProtocolHandler)
.hasSubstitution("devtools");
},
/**
* Check if DevTools have already been initialized.
*
* @return {Boolean} true if DevTools are initialized.
*/
isInitialized: function () {
- return !!this.gDevTools;
+ return !!this._gDevTools;
},
/**
* Register an instance of gDevTools. Should be called by DevTools during startup.
*
* @param {DevTools} a devtools instance (from client/framework/devtools)
*/
register: function (gDevTools) {
- this.gDevTools = gDevTools;
+ this._gDevTools = gDevTools;
this._onDevToolsRegistered();
- this.gDevTools.emit("devtools-registered");
+ this._gDevTools.emit("devtools-registered");
},
/**
* Unregister the current instance of gDevTools. Should be called by DevTools during
* shutdown.
*/
unregister: function () {
if (this.isInitialized()) {
- this.gDevTools.emit("devtools-unregistered");
- this.gDevTools = null;
+ this._gDevTools.emit("devtools-unregistered");
+ this._gDevTools = null;
}
},
/**
* The following methods can be called before DevTools are initialized:
* - on
* - off
* - registerTool
@@ -97,110 +115,110 @@ this.DevToolsShim = {
/**
* This method is used by browser/components/extensions/ext-devtools.js for the events:
* - toolbox-created
* - toolbox-destroyed
*/
on: function (event, listener) {
if (this.isInitialized()) {
- this.gDevTools.on(event, listener);
+ this._gDevTools.on(event, listener);
} else {
this.listeners.push([event, listener]);
}
},
/**
* This method is currently only used by devtools code, but is kept here for consistency
* with on().
*/
off: function (event, listener) {
if (this.isInitialized()) {
- this.gDevTools.off(event, listener);
+ this._gDevTools.off(event, listener);
} else {
removeItem(this.listeners, ([e, l]) => e === event && l === listener);
}
},
/**
* This method is only used by the addon-sdk and should be removed when Firefox 56 is
* no longer supported.
*/
registerTool: function (tool) {
if (this.isInitialized()) {
- this.gDevTools.registerTool(tool);
+ this._gDevTools.registerTool(tool);
} else {
this.tools.push(tool);
}
},
/**
* This method is only used by the addon-sdk and should be removed when Firefox 56 is
* no longer supported.
*/
unregisterTool: function (tool) {
if (this.isInitialized()) {
- this.gDevTools.unregisterTool(tool);
+ this._gDevTools.unregisterTool(tool);
} else {
removeItem(this.tools, t => t === tool);
}
},
/**
* This method is only used by the addon-sdk and should be removed when Firefox 56 is
* no longer supported.
*/
registerTheme: function (theme) {
if (this.isInitialized()) {
- this.gDevTools.registerTheme(theme);
+ this._gDevTools.registerTheme(theme);
} else {
this.themes.push(theme);
}
},
/**
* This method is only used by the addon-sdk and should be removed when Firefox 56 is
* no longer supported.
*/
unregisterTheme: function (theme) {
if (this.isInitialized()) {
- this.gDevTools.unregisterTheme(theme);
+ this._gDevTools.unregisterTheme(theme);
} else {
removeItem(this.themes, t => t === theme);
}
},
/**
* Called from SessionStore.jsm in mozilla-central when saving the current state.
*
* @return {Array} array of currently opened scratchpad windows. Empty array if devtools
* are not installed
*/
getOpenedScratchpads: function () {
if (!this.isInitialized()) {
return [];
}
- return this.gDevTools.getOpenedScratchpads();
+ return this._gDevTools.getOpenedScratchpads();
},
/**
* Called from SessionStore.jsm in mozilla-central when restoring a state that contained
* opened scratchpad windows.
*/
restoreScratchpadSession: function (scratchpads) {
if (!this.isInstalled()) {
return;
}
if (!this.isInitialized()) {
this._initDevTools();
}
- this.gDevTools.restoreScratchpadSession(scratchpads);
+ this._gDevTools.restoreScratchpadSession(scratchpads);
},
/**
* Called from nsContextMenu.js in mozilla-central when using the Inspect Element
* context menu item.
*
* @param {XULTab} tab
* The browser tab on which inspect node was used.
@@ -211,40 +229,36 @@ this.DevToolsShim = {
* @return {Promise} a promise that resolves when the node is selected in the inspector
* markup view or that resolves immediately if DevTools are not installed.
*/
inspectNode: function (tab, selectors) {
if (!this.isInstalled()) {
return Promise.resolve();
}
- if (!this.isInitialized()) {
- this._initDevTools();
- }
-
return this.gDevTools.inspectNode(tab, selectors);
},
_initDevTools: function () {
let { loader } = Cu.import("resource://devtools/shared/Loader.jsm", {});
loader.require("devtools/client/framework/devtools-browser");
},
_onDevToolsRegistered: function () {
// Register all pending event listeners on the real gDevTools object.
for (let [event, listener] of this.listeners) {
- this.gDevTools.on(event, listener);
+ this._gDevTools.on(event, listener);
}
for (let tool of this.tools) {
- this.gDevTools.registerTool(tool);
+ this._gDevTools.registerTool(tool);
}
for (let theme of this.themes) {
- this.gDevTools.registerTheme(theme);
+ this._gDevTools.registerTheme(theme);
}
this.listeners = [];
this.tools = [];
this.themes = [];
},
};
@@ -272,19 +286,11 @@ let addonSdkMethods = [
* therefore DevTools should always be available when they are called.
*/
let webExtensionsMethods = [
"getTheme",
];
for (let method of [...addonSdkMethods, ...webExtensionsMethods]) {
this.DevToolsShim[method] = function () {
- if (!this.isInstalled()) {
- throw new Error(`Method ${method} unavailable if DevTools are not installed`);
- }
-
- if (!this.isInitialized()) {
- this._initDevTools();
- }
-
return this.gDevTools[method].apply(this.gDevTools, arguments);
};
}