diff --git a/devtools/server/actors/descriptors/process.js b/devtools/server/actors/descriptors/process.js index b60524afc921..dd8ec654c6ba 100644 --- a/devtools/server/actors/descriptors/process.js +++ b/devtools/server/actors/descriptors/process.js @@ -8,6 +8,9 @@ const Services = require("Services"); const { DevToolsServer } = require("devtools/server/devtools-server"); const { Cc, Ci } = require("chrome"); +const { + createBrowserSessionContext, +} = require("devtools/server/actors/watcher/session-context"); const { ActorClassWithSpec, Actor } = require("devtools/shared/protocol"); const { processDescriptorSpec, @@ -157,12 +160,7 @@ const ProcessDescriptorActor = ActorClassWithSpec(processDescriptorSpec, { */ getWatcher() { if (!this.watcher) { - this.watcher = new WatcherActor(this.conn, { - type: "all", - // For now, the top level target (ParentProcessTargetActor) is created via ProcessDescriptor.getTarget - // and is never replaced by any other, nor is it created by the WatcherActor. - isServerTargetSwitchingEnabled: false, - }); + this.watcher = new WatcherActor(this.conn, createBrowserSessionContext()); this.manage(this.watcher); } return this.watcher; diff --git a/devtools/server/actors/descriptors/tab.js b/devtools/server/actors/descriptors/tab.js index 3e3d3bc1d2e5..309006c92995 100644 --- a/devtools/server/actors/descriptors/tab.js +++ b/devtools/server/actors/descriptors/tab.js @@ -25,6 +25,9 @@ loader.lazyImporter( const { ActorClassWithSpec, Actor } = require("devtools/shared/protocol"); const { tabDescriptorSpec } = require("devtools/shared/specs/descriptors/tab"); const { AppConstants } = require("resource://gre/modules/AppConstants.jsm"); +const { + createBrowserElementSessionContext, +} = require("devtools/server/actors/watcher/session-context"); loader.lazyRequireGetter( this, @@ -181,13 +184,12 @@ const TabDescriptorActor = ActorClassWithSpec(tabDescriptorSpec, { */ getWatcher(config) { if (!this.watcher) { - this.watcher = new WatcherActor(this.conn, { - type: "browser-element", - browserId: this._browser.browserId, - // Nowaday, it should always be enabled except for WebExtension special - // codepath and some tests. - isServerTargetSwitchingEnabled: config.isServerTargetSwitchingEnabled, - }); + this.watcher = new WatcherActor( + this.conn, + createBrowserElementSessionContext(this._browser, { + isServerTargetSwitchingEnabled: config.isServerTargetSwitchingEnabled, + }) + ); this.manage(this.watcher); } return this.watcher; diff --git a/devtools/server/actors/descriptors/webextension.js b/devtools/server/actors/descriptors/webextension.js index 4c2f0de9e077..fbb76040cfc5 100644 --- a/devtools/server/actors/descriptors/webextension.js +++ b/devtools/server/actors/descriptors/webextension.js @@ -19,6 +19,9 @@ const { const { connectToFrame, } = require("devtools/server/connectors/frame-connector"); +const { + createWebExtensionSessionContext, +} = require("devtools/server/actors/watcher/session-context"); loader.lazyImporter( this, @@ -109,15 +112,17 @@ const WebExtensionDescriptorActor = protocol.ActorClassWithSpec( if (!this.watcher) { // Ensure connecting to the webextension frame in order to populate this._form await this._extensionFrameConnect(); - this.watcher = new WatcherActor(this.conn, { - type: "webextension", - addonId: this.addonId, - addonBrowsingContextID: this._form.browsingContextID, - addonInnerWindowId: this._form.innerWindowId, - // For now, there is only one target (WebExtensionTargetActor), it is never replaced, - // and is only created via WebExtensionDescriptor.getTarget (and never by the watcher actor). - isServerTargetSwitchingEnabled: config.isServerTargetSwitchingEnabled, - }); + this.watcher = new WatcherActor( + this.conn, + createWebExtensionSessionContext( + { + addonId: this.addonId, + browsingContextID: this._form.browsingContextID, + innerWindowId: this._form.innerWindowId, + }, + config + ) + ); this.manage(this.watcher); } return this.watcher; diff --git a/devtools/server/actors/network-monitor/network-event-actor.js b/devtools/server/actors/network-monitor/network-event-actor.js index 091398704f20..9374c19c3868 100644 --- a/devtools/server/actors/network-monitor/network-event-actor.js +++ b/devtools/server/actors/network-monitor/network-event-actor.js @@ -19,8 +19,8 @@ const { LongStringActor } = require("devtools/server/actors/string"); * @param DevToolsServerConnection conn * The connection into which this Actor will be added. * @param object sessionContext - * WatcherActor's session context. This helps know what is the overall debugged scope. - * See watcher actor constructor for more info. + * The Session Context to help know what is debugged. + * See devtools/server/actors/watcher/session-context.js * @param object options * Dictionary object with the following attributes: * - onNetworkEventUpdate: optional function diff --git a/devtools/server/actors/targets/target-actor-registry.jsm b/devtools/server/actors/targets/target-actor-registry.jsm index 664e28088d05..abdf26704c52 100644 --- a/devtools/server/actors/targets/target-actor-registry.jsm +++ b/devtools/server/actors/targets/target-actor-registry.jsm @@ -38,9 +38,8 @@ var TargetActorRegistry = { * Return the first target actor matching the passed watcher's session context. Returns null if * no matching target actors could be found. * - * @param {Object} sessionContext: WatcherActor's session context. To only retrieve targets related - * to the scope of this watcher actor. - * See watcher actor constructor for more info. + * @param {Object} sessionContext: The Session Context to help know what is debugged. + * See devtools/server/actors/watcher/session-context.js * @param {String} connectionPrefix: DevToolsServerConnection's prefix, in order to select only actor * related to the same connection. i.e. the same client. * @returns {TargetActor|null} @@ -78,9 +77,8 @@ var TargetActorRegistry = { * In some scenarios, the registry can have multiple target actors for a given * browserId (e.g. the regular DevTools content toolbox + DevTools WebExtensions targets). * - * @param {Object} sessionContext: WatcherActor's session context. To only retrieve targets related - * to the scope of this watcher actor. - * See watcher actor constructor for more info. + * @param {Object} sessionContext: The Session Context to help know what is debugged. + * See devtools/server/actors/watcher/session-context.js * @param {String} connectionPrefix: DevToolsServerConnection's prefix, in order to select only actor * related to the same connection. i.e. the same client. * @returns {Array} diff --git a/devtools/server/actors/targets/window-global.js b/devtools/server/actors/targets/window-global.js index 4e9e628cb301..eeeb9c61e10b 100644 --- a/devtools/server/actors/targets/window-global.js +++ b/devtools/server/actors/targets/window-global.js @@ -256,8 +256,8 @@ const windowGlobalTargetPrototype = { * If true, the actor will only focus on the passed docShell and not on the whole * docShell tree. This should be enabled when we have targets for all documents. * - sessionContext Object - * WatcherActor's session context. This helps know what is the overall debugged scope. - * See watcher actor constructor for more info. + * The Session Context to help know what is debugged. + * See devtools/server/actors/watcher/session-context.js */ initialize: function( connection, diff --git a/devtools/server/actors/watcher.js b/devtools/server/actors/watcher.js index 67fa40b8cffe..361941071893 100644 --- a/devtools/server/actors/watcher.js +++ b/devtools/server/actors/watcher.js @@ -76,15 +76,9 @@ exports.WatcherActor = protocol.ActorClassWithSpec(watcherSpec, { * * @param {DevToolsServerConnection} conn * The connection to use in order to communicate back to the client. - * @param {Object} sessionContext - * Mandatory argument to define the debugged context of this actor. - * Note that as this object is passed to other processes and thread, - * this should be a serializable object. - * @param {String} sessionContext.type: The type of debugged context. - * Can be: - * - "all", to debug everything in the browser. - * - "browser-element", to focus on one given element - * and all its children resources (workers, iframes,...) + * @param {object} sessionContext + * The Session Context to help know what is debugged. + * See devtools/server/actors/watcher/session-context.js * @param {Number} sessionContext.browserId: If this is a "browser-element" context type, * the "browserId" of the element we would like to debug. * @param {Boolean} sessionContext.isServerTargetSwitchingEnabled: Flag to to know if we should diff --git a/devtools/server/actors/watcher/WatcherRegistry.jsm b/devtools/server/actors/watcher/WatcherRegistry.jsm index 165405eebfb6..bca2a5948f5f 100644 --- a/devtools/server/actors/watcher/WatcherRegistry.jsm +++ b/devtools/server/actors/watcher/WatcherRegistry.jsm @@ -41,8 +41,8 @@ const { SUPPORTED_DATA } = SessionDataHelpers; // It is keyed by WatcherActor ID and values contains following attributes: // - targets: Set of strings, refering to target types to be listened to // - resources: Set of strings, refering to resource types to be observed -// - sessionContext: WatcherActor's session context. Describe what the watcher should be debugging. -// See watcher actor constructor for more info. +// - sessionContext Object, The Session Context to help know what is debugged. +// See devtools/server/actors/watcher/session-context.js // - connectionPrefix: The DevToolsConnection prefix of the watcher actor. Used to compute new actor ID in the content processes. // // Unfortunately, `sharedData` is subject to race condition and may have side effect diff --git a/devtools/server/actors/watcher/browsing-context-helpers.jsm b/devtools/server/actors/watcher/browsing-context-helpers.jsm index 75e37b8a90d1..dab432e79e26 100644 --- a/devtools/server/actors/watcher/browsing-context-helpers.jsm +++ b/devtools/server/actors/watcher/browsing-context-helpers.jsm @@ -30,8 +30,8 @@ const isEveryFrameTargetEnabled = Services.prefs.getBoolPref( * @param {BrowsingContext} browsingContext * The browsing context we want to check if it is part of debugged context * @param {Object} sessionContext - * WatcherActor's session context. This helps know what is the overall debugged scope. - * See watcher actor constructor for more info. + * The Session Context to help know what is debugged. + * See devtools/server/actors/watcher/session-context.js * @param {Object} options * Optional arguments passed via a dictionary. * @param {Boolean} options.forceAcceptTopLevelTarget @@ -169,8 +169,8 @@ function isBrowsingContextPartOfContext( * @param {WindowGlobalParent|WindowGlobalChild} windowGlobal * The WindowGlobal we want to check if it is part of debugged context * @param {Object} sessionContext - * WatcherActor's session context. This helps know what is the overall debugged scope. - * See watcher actor constructor for more info. + * The Session Context to help know what is debugged. + * See devtools/server/actors/watcher/session-context.js * @param {Object} options * Optional arguments passed via a dictionary. * See `isBrowsingContextPartOfContext` jsdoc. @@ -232,8 +232,8 @@ function _validateWindowGlobal( * @param {WindowGlobalParent|WindowGlobalChild} windowGlobal * The WindowGlobal we want to check if it is part of debugged context * @param {Object} sessionContext - * WatcherActor's session context. This helps know what is the overall debugged scope. - * See watcher actor constructor for more info. + * The Session Context to help know what is debugged. + * See devtools/server/actors/watcher/session-context.js * @param {Object} options * Optional arguments passed via a dictionary. * See `isBrowsingContextPartOfContext` jsdoc. @@ -258,8 +258,8 @@ function isWindowGlobalPartOfContext(windowGlobal, sessionContext, options) { * - For all nested browsing context. We fetch the contexts recursively. * * @param {Object} sessionContext - * WatcherActor's session context. This helps know what is the overall debugged scope. - * See watcher actor constructor for more info. + * The Session Context to help know what is debugged. + * See devtools/server/actors/watcher/session-context.js * @param {Object} options * Optional arguments passed via a dictionary. * @param {Boolean} options.acceptSameProcessIframes diff --git a/devtools/server/actors/watcher/moz.build b/devtools/server/actors/watcher/moz.build index cc1a26b5a734..7bfc50f39dcc 100644 --- a/devtools/server/actors/watcher/moz.build +++ b/devtools/server/actors/watcher/moz.build @@ -10,6 +10,7 @@ DIRS += [ DevToolsModules( "browsing-context-helpers.jsm", + "session-context.js", "SessionDataHelpers.jsm", "WatcherRegistry.jsm", ) diff --git a/devtools/server/actors/watcher/session-context.js b/devtools/server/actors/watcher/session-context.js new file mode 100644 index 000000000000..030f215afb5b --- /dev/null +++ b/devtools/server/actors/watcher/session-context.js @@ -0,0 +1,100 @@ +/* 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"; + +// Module to create all the Session Context objects. +// +// These are static JSON serializable object that help describe +// the debugged context. It is passed around to most of the server codebase +// in order to know which object to consider inspecting and communicating back to the client. +// +// These objects are all instantiated by the Descriptor actors +// and passed as a constructor argument to the Watcher actor. +// +// These objects have only two attributes used by all the Session contexts: +// - type: String +// Describes which type of context we are debugging. +// Can be "all", "browser-element" or "webextension". +// See each create* method for more info about each type and their specific attributes. +// - isServerTargetSwitchingEnabled: Boolean +// If true, targets should all be spawned by the server codebase. +// Especially the first, top level target. + +/** + * Create the SessionContext used by the Browser Toolbox and Browser Console. + * + * This context means debugging everything. + * The whole browser: + * - all processes: parent and content, + * - all privileges: privileged/chrome and content/web, + * - all components/targets: HTML documents, processes, workers, add-ons,... + */ +function createBrowserSessionContext() { + return { + type: "all", + // For now, the top level target (ParentProcessTargetActor) is created via ProcessDescriptor.getTarget + // and is never replaced by any other, nor is it created by the WatcherActor. + isServerTargetSwitchingEnabled: false, + }; +} + +/** + * Create the SessionContext used by the regular web page toolboxes as well as remote debugging android device tabs. + * + * @param {BrowserElement} browserElement + * The tab to debug. It should be a reference to a element. + * @param {Object} config + * An object with optional configuration. Only supports "isServerTargetSwitchingEnabled" attribute. + * See jsdoc in this file header for more info. + */ +function createBrowserElementSessionContext(browserElement, config) { + return { + type: "browser-element", + browserId: browserElement.browserId, + // Nowaday, it should always be enabled except for WebExtension special + // codepath and some tests. + isServerTargetSwitchingEnabled: config.isServerTargetSwitchingEnabled, + }; +} + +/** + * Create the SessionContext used by the web extension toolboxes. + * + * @param {Object} addon + * First object argument to describe the add-on. + * @param {String} addon.addonId + * The web extension ID, to uniquely identify the debugged add-on. + * @param {String} addon.browsingContextID + * The ID of the BrowsingContext into which this add-on is loaded. + * For now the top level target is associated with this one precise BrowsingContext. + * Knowing about it later helps associate resources to the same BrowsingContext ID and so the same target. + * @param {String} addon.innerWindowId + * The ID of the WindowGlobal into which this add-on is loaded. + * This is used for the same reason as browsingContextID. It helps match the resource with the right target. + * We now also use the WindowGlobal ID/innerWindowId to identify the targets. + * @param {Object} config + * An object with optional configuration. Only supports "isServerTargetSwitchingEnabled" attribute. + * See jsdoc in this file header for more info. + */ +function createWebExtensionSessionContext( + { addonId, browsingContextID, innerWindowId }, + config +) { + return { + type: "webextension", + addonId: addonId, + addonBrowsingContextID: browsingContextID, + addonInnerWindowId: innerWindowId, + // For now, there is only one target (WebExtensionTargetActor), it is never replaced, + // and is only created via WebExtensionDescriptor.getTarget (and never by the watcher actor). + isServerTargetSwitchingEnabled: config.isServerTargetSwitchingEnabled, + }; +} + +module.exports = { + createBrowserSessionContext, + createBrowserElementSessionContext, + createWebExtensionSessionContext, +};