diff --git a/devtools/server/actors/watcher/target-helpers/frame-helper.js b/devtools/server/actors/watcher/target-helpers/frame-helper.js index c90c571fa9bd..64474f8a92c4 100644 --- a/devtools/server/actors/watcher/target-helpers/frame-helper.js +++ b/devtools/server/actors/watcher/target-helpers/frame-helper.js @@ -4,7 +4,6 @@ "use strict"; -const Services = require("Services"); const { WatcherRegistry, } = require("devtools/server/actors/watcher/WatcherRegistry.jsm"); @@ -12,6 +11,10 @@ const { WindowGlobalLogger, } = require("devtools/server/connectors/js-window-actor/WindowGlobalLogger.jsm"); const Targets = require("devtools/server/actors/targets/index"); +const { + getAllRemoteBrowsingContexts, + shouldNotifyWindowGlobal, +} = require("devtools/server/actors/watcher/target-helpers/utils.js"); /** * Force creating targets for all existing BrowsingContext, that, for a given Watcher Actor. @@ -189,107 +192,6 @@ function getFilteredRemoteBrowsingContext(browserElement) { ); } -/** - * Get all the BrowsingContexts. - * - * Really all of them: - * - For all the privileged windows (browser.xhtml, browser console, ...) - * - For all chrome *and* content contexts (privileged windows, as well as elements and their inner content documents) - * - For all nested browsing context. We fetch the contexts recursively. - * - * @param BrowsingContext topBrowsingContext (optional) - * If defined, this will restrict to this Browsing Context only - * and any of its (nested) children. - */ -function getAllRemoteBrowsingContexts(topBrowsingContext) { - const browsingContexts = []; - - // For a given BrowsingContext, add the `browsingContext` - // all of its children, that, recursively. - function walk(browsingContext) { - if (browsingContexts.includes(browsingContext)) { - return; - } - browsingContexts.push(browsingContext); - - for (const child of browsingContext.children) { - walk(child); - } - - if (browsingContext.window) { - // If the document is in the parent process, also iterate over each 's browsing context. - // BrowsingContext.children doesn't cross chrome to content boundaries, - // so we have to cross these boundaries by ourself. - for (const browser of browsingContext.window.document.querySelectorAll( - `browser[remote="true"]` - )) { - walk(browser.browsingContext); - } - } - } - - // If a Browsing Context is passed, only walk through the given BrowsingContext - if (topBrowsingContext) { - walk(topBrowsingContext); - // Remove the top level browsing context we just added by calling walk. - browsingContexts.shift(); - } else { - // Fetch all top level window's browsing contexts - // Note that getWindowEnumerator works from all processes, including the content process. - for (const window of Services.ww.getWindowEnumerator()) { - if (window.docShell.browsingContext) { - walk(window.docShell.browsingContext); - } - } - } - - return browsingContexts; -} - -/** - * Helper function to know if a given WindowGlobal should be exposed via watchTargets("frame") API - * XXX: We probably want to share this function with DevToolsFrameChild, - * but may be not, it looks like the checks are really differents because WindowGlobalParent and WindowGlobalChild - * expose very different attributes. (WindowGlobalChild exposes much less!) - */ -function shouldNotifyWindowGlobal(browsingContext, watchedBrowserId) { - const windowGlobal = browsingContext.currentWindowGlobal; - // Loading or destroying BrowsingContext won't have any associated WindowGlobal. - // Ignore them. They should be either handled via DOMWindowCreated event or JSWindowActor destroy - if (!windowGlobal) { - return false; - } - // Ignore extension for now as attaching to them is special. - if (browsingContext.currentRemoteType == "extension") { - return false; - } - // Ignore globals running in the parent process for now as they won't be in a distinct process anyway. - // And JSWindowActor will most likely only be created if we toggle includeChrome - // on the JSWindowActor registration. - if (windowGlobal.osPid == -1 && windowGlobal.isInProcess) { - return false; - } - // Ignore about:blank which are quickly replaced and destroyed by the final URI - // bug 1625026 aims at removing this workaround and allow debugging any about:blank load - if ( - windowGlobal.documentURI && - windowGlobal.documentURI.spec == "about:blank" - ) { - return false; - } - - if (watchedBrowserId && browsingContext.browserId != watchedBrowserId) { - return false; - } - - // For now, we only mention the "remote frames". - // i.e. the frames which are in a distinct process compared to their parent document - return ( - !browsingContext.parent || - windowGlobal.osPid != browsingContext.parent.currentWindowGlobal.osPid - ); -} - // Set to true to log info about about WindowGlobal's being watched. const DEBUG = false; diff --git a/devtools/server/actors/watcher/target-helpers/moz.build b/devtools/server/actors/watcher/target-helpers/moz.build index f413ba732352..b1a35d89983d 100644 --- a/devtools/server/actors/watcher/target-helpers/moz.build +++ b/devtools/server/actors/watcher/target-helpers/moz.build @@ -7,5 +7,6 @@ DevToolsModules( 'frame-helper.js', 'process-helper.js', + 'utils.js', ) diff --git a/devtools/server/actors/watcher/target-helpers/utils.js b/devtools/server/actors/watcher/target-helpers/utils.js new file mode 100644 index 000000000000..5bc521bfadb2 --- /dev/null +++ b/devtools/server/actors/watcher/target-helpers/utils.js @@ -0,0 +1,113 @@ +/* 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 Services = require("Services"); + +/** + * Helper function to know if a given WindowGlobal should be exposed via watchTargets("frame") API + * XXX: We probably want to share this function with DevToolsFrameChild, + * but may be not, it looks like the checks are really differents because WindowGlobalParent and WindowGlobalChild + * expose very different attributes. (WindowGlobalChild exposes much less!) + */ +function shouldNotifyWindowGlobal(browsingContext, watchedBrowserId) { + const windowGlobal = browsingContext.currentWindowGlobal; + // Loading or destroying BrowsingContext won't have any associated WindowGlobal. + // Ignore them. They should be either handled via DOMWindowCreated event or JSWindowActor destroy + if (!windowGlobal) { + return false; + } + // Ignore extension for now as attaching to them is special. + if (browsingContext.currentRemoteType == "extension") { + return false; + } + // Ignore globals running in the parent process for now as they won't be in a distinct process anyway. + // And JSWindowActor will most likely only be created if we toggle includeChrome + // on the JSWindowActor registration. + if (windowGlobal.osPid == -1 && windowGlobal.isInProcess) { + return false; + } + // Ignore about:blank which are quickly replaced and destroyed by the final URI + // bug 1625026 aims at removing this workaround and allow debugging any about:blank load + if ( + windowGlobal.documentURI && + windowGlobal.documentURI.spec == "about:blank" + ) { + return false; + } + + if (watchedBrowserId && browsingContext.browserId != watchedBrowserId) { + return false; + } + + // For now, we only mention the "remote frames". + // i.e. the frames which are in a distinct process compared to their parent document + return ( + !browsingContext.parent || + windowGlobal.osPid != browsingContext.parent.currentWindowGlobal.osPid + ); +} + +/** + * Get all the BrowsingContexts. + * + * Really all of them: + * - For all the privileged windows (browser.xhtml, browser console, ...) + * - For all chrome *and* content contexts (privileged windows, as well as elements and their inner content documents) + * - For all nested browsing context. We fetch the contexts recursively. + * + * @param BrowsingContext topBrowsingContext (optional) + * If defined, this will restrict to this Browsing Context only + * and any of its (nested) children. + */ +function getAllRemoteBrowsingContexts(topBrowsingContext) { + const browsingContexts = []; + + // For a given BrowsingContext, add the `browsingContext` + // all of its children, that, recursively. + function walk(browsingContext) { + if (browsingContexts.includes(browsingContext)) { + return; + } + browsingContexts.push(browsingContext); + + for (const child of browsingContext.children) { + walk(child); + } + + if (browsingContext.window) { + // If the document is in the parent process, also iterate over each 's browsing context. + // BrowsingContext.children doesn't cross chrome to content boundaries, + // so we have to cross these boundaries by ourself. + for (const browser of browsingContext.window.document.querySelectorAll( + `browser[remote="true"]` + )) { + walk(browser.browsingContext); + } + } + } + + // If a Browsing Context is passed, only walk through the given BrowsingContext + if (topBrowsingContext) { + walk(topBrowsingContext); + // Remove the top level browsing context we just added by calling walk. + browsingContexts.shift(); + } else { + // Fetch all top level window's browsing contexts + // Note that getWindowEnumerator works from all processes, including the content process. + for (const window of Services.ww.getWindowEnumerator()) { + if (window.docShell.browsingContext) { + walk(window.docShell.browsingContext); + } + } + } + + return browsingContexts; +} + +module.exports = { + getAllRemoteBrowsingContexts, + shouldNotifyWindowGlobal, +};