From e69809345864fcbc48fd47bfdd6f25baa3c5e1eb Mon Sep 17 00:00:00 2001 From: Julian Descottes Date: Wed, 14 Jun 2017 17:52:50 +0200 Subject: [PATCH] Bug 1372520 - use DevToolsShim to inspectNode in nContextMenu;r=bgrins,mixedpuppy As devtools become optional, nsContextMenu needs to check if devtools are installed before displaying the devtools-related menu entries. Rather than loading devtools classing and calling APIs, use APIs provided by the DevToolsShim, that will stay in mozilla-central. MozReview-Commit-ID: CxqabTjhckC --HG-- extra : rebase_source : 1781edcf11316eab7e95cbab834d1bc3230c44d7 --- browser/base/content/nsContextMenu.js | 13 +++-- devtools/client/framework/devtools-browser.js | 35 -------------- devtools/client/framework/devtools.js | 47 +++++++++++++++++++ devtools/shim/DevToolsShim.jsm | 20 ++++++++ 4 files changed, 75 insertions(+), 40 deletions(-) diff --git a/browser/base/content/nsContextMenu.js b/browser/base/content/nsContextMenu.js index 0d19aa419d9b..db98d8a16a02 100644 --- a/browser/base/content/nsContextMenu.js +++ b/browser/base/content/nsContextMenu.js @@ -20,6 +20,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "WebNavigationFrames", "resource://gre/modules/WebNavigationFrames.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "ContextualIdentityService", "resource://gre/modules/ContextualIdentityService.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "DevToolsShim", + "chrome://devtools-shim/content/DevToolsShim.jsm"); var gContextMenuContentData = null; @@ -304,7 +306,11 @@ nsContextMenu.prototype = { this.onImage || this.onCanvas || this.onVideo || this.onAudio || this.onLink || this.onTextInput); - var showInspect = this.inTabBrowser && gPrefService.getBoolPref("devtools.inspector.enabled"); + + var showInspect = DevToolsShim.isInstalled() && + this.inTabBrowser && + gPrefService.getBoolPref("devtools.inspector.enabled", false); + this.showItem("context-viewsource", shouldShow); this.showItem("context-viewinfo", shouldShow); // The page info is broken for WebExtension popups, as the browser is @@ -631,10 +637,7 @@ nsContextMenu.prototype = { }, inspectNode() { - let gBrowser = this.browser.ownerGlobal.gBrowser; - let { require } = Cu.import("resource://devtools/shared/Loader.jsm", {}); - let { gDevToolsBrowser } = require("devtools/client/framework/devtools-browser"); - return gDevToolsBrowser.inspectNode(gBrowser.selectedTab, this.targetSelectors); + return DevToolsShim.inspectNode(gBrowser.selectedTab, this.targetSelectors); }, /** diff --git a/devtools/client/framework/devtools-browser.js b/devtools/client/framework/devtools-browser.js index 86ea144cbf39..3b2b2baae315 100644 --- a/devtools/client/framework/devtools-browser.js +++ b/devtools/client/framework/devtools-browser.js @@ -307,41 +307,6 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = { } }, - async inspectNode(tab, nodeSelectors) { - let target = TargetFactory.forTab(tab); - - let toolbox = await gDevTools.showToolbox(target, "inspector"); - let inspector = toolbox.getCurrentPanel(); - - // new-node-front tells us when the node has been selected, whether the - // browser is remote or not. - let onNewNode = inspector.selection.once("new-node-front"); - - // Evaluate the cross iframes query selectors - async function querySelectors(nodeFront) { - let selector = nodeSelectors.pop(); - if (!selector) { - return nodeFront; - } - nodeFront = await inspector.walker.querySelector(nodeFront, selector); - if (nodeSelectors.length > 0) { - let { nodes } = await inspector.walker.children(nodeFront); - // This is the NodeFront for the document node inside the iframe - nodeFront = nodes[0]; - } - return querySelectors(nodeFront); - } - let nodeFront = await inspector.walker.getRootNode(); - nodeFront = await querySelectors(nodeFront); - // Select the final node - inspector.selection.setNodeFront(nodeFront, "browser-context-menu"); - - await onNewNode; - // Now that the node has been selected, wait until the inspector is - // fully updated. - await inspector.once("inspector-updated"); - }, - _getContentProcessTarget(processId) { // Create a DebuggerServer in order to connect locally to it if (!DebuggerServer.initialized) { diff --git a/devtools/client/framework/devtools.js b/devtools/client/framework/devtools.js index e468d60e26e9..0e08256e81e1 100644 --- a/devtools/client/framework/devtools.js +++ b/devtools/client/framework/devtools.js @@ -574,6 +574,53 @@ DevTools.prototype = { BrowserToolboxProcess.init({ addonID }); }, + /** + * Called from the DevToolsShim, used by nsContextMenu.js. + * + * @param {XULTab} tab + * The browser tab on which inspect node was used. + * @param {Array} selectors + * An array of CSS selectors to find the target node. Several selectors can be + * needed if the element is nested in frames and not directly in the root + * document. + * @return {Promise} a promise that resolves when the node is selected in the inspector + * markup view. + */ + async inspectNode(tab, nodeSelectors) { + let target = TargetFactory.forTab(tab); + + let toolbox = await gDevTools.showToolbox(target, "inspector"); + let inspector = toolbox.getCurrentPanel(); + + // new-node-front tells us when the node has been selected, whether the + // browser is remote or not. + let onNewNode = inspector.selection.once("new-node-front"); + + // Evaluate the cross iframes query selectors + async function querySelectors(nodeFront) { + let selector = nodeSelectors.pop(); + if (!selector) { + return nodeFront; + } + nodeFront = await inspector.walker.querySelector(nodeFront, selector); + if (nodeSelectors.length > 0) { + let { nodes } = await inspector.walker.children(nodeFront); + // This is the NodeFront for the document node inside the iframe + nodeFront = nodes[0]; + } + return querySelectors(nodeFront); + } + let nodeFront = await inspector.walker.getRootNode(); + nodeFront = await querySelectors(nodeFront); + // Select the final node + inspector.selection.setNodeFront(nodeFront, "browser-context-menu"); + + await onNewNode; + // Now that the node has been selected, wait until the inspector is + // fully updated. + await inspector.once("inspector-updated"); + }, + /** * Either the SDK Loader has been destroyed by the add-on contribution * workflow, or firefox is shutting down. diff --git a/devtools/shim/DevToolsShim.jsm b/devtools/shim/DevToolsShim.jsm index 04ec75160dd0..9d07b117cb9d 100644 --- a/devtools/shim/DevToolsShim.jsm +++ b/devtools/shim/DevToolsShim.jsm @@ -177,6 +177,26 @@ this.DevToolsShim = { 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. + * @param {Array} selectors + * An array of CSS selectors to find the target node. Several selectors can be + * needed if the element is nested in frames and not directly in the root + * document. + * @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(); + } + return this.gDevTools.inspectNode(tab, selectors); + }, + _onDevToolsRegistered: function () { // Register all pending event listeners on the real gDevTools object. for (let [event, listener] of this.listeners) {