Bug 1735825 - [devtools] Pass watcher context down to TargetActorRegistry. r=jdescottes,rpl

Differential Revision: https://phabricator.services.mozilla.com/D128897
This commit is contained in:
Alexandre Poirot 2021-11-02 10:57:24 +00:00
Родитель 4465bb9663
Коммит 3f2c1a3ad6
6 изменённых файлов: 75 добавлений и 43 удалений

Просмотреть файл

@ -36,10 +36,9 @@ function getTargetActorsCount(tab) {
);
// Retrieve the target actor instances
const targets = TargetActorRegistry.getTargetActors(
return TargetActorRegistry.getTargetActorsCountForBrowserElement(
content.browsingContext.browserId
);
return targets.length;
});
}

Просмотреть файл

@ -4,6 +4,8 @@
"use strict";
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
var EXPORTED_SYMBOLS = ["TargetActorRegistry"];
// Keep track of all WindowGlobal target actors.
@ -33,17 +35,39 @@ var TargetActorRegistry = {
},
/**
* Return the first target actor matching the passed browser element id. Returns null if
* Return the first target actor matching the passed watcher's context. Returns null if
* no matching target actors could be found.
*
* @param {Integer} browserId: The browserId to retrieve targets for. Pass null to
* retrieve the parent process targets.
* @param {String} connectionPrefix: Optional prefix, in order to select only actor
* @param {Object} context: WatcherActor's context. To only retrieve targets related
* to the scope of this watcher actor.
* See watcher actor constructor for more info.
* @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}
*/
getTargetActor(browserId, connectionPrefix) {
return this.getTargetActors(browserId, connectionPrefix)[0] || null;
getTopLevelTargetActorForContext(context, connectionPrefix) {
if (context.type == "all") {
if (
Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_DEFAULT
) {
// The xpcshell target actor also lives in the "parent process", even if it
// is an instance of ContentProcessTargetActor.
if (xpcShellTargetActor) {
return xpcShellTargetActor;
}
const actors = this.getTargetActors(context, connectionPrefix);
// In theory, there should be only one actor here.
return actors[0];
}
return null;
} else if (context.type == "browser-element") {
const actors = this.getTargetActors(context, connectionPrefix);
return actors.find(actor => {
return actor.isTopLevelTarget;
});
}
throw new Error("Unsupported context type: " + context.type);
},
/**
@ -51,20 +75,22 @@ 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 {Integer} browserId: The browserId to retrieve targets for. Pass null to
* retrieve the parent process targets.
* @param {String} connectionPrefix: Optional prefix, in order to select only actor
* @param {Object} context: WatcherActor's context. To only retrieve targets related
* to the scope of this watcher actor.
* See watcher actor constructor for more info.
* @param {String} connectionPrefix: DevToolsServerConnection's prefix, in order to select only actor
* related to the same connection. i.e. the same client.
* @returns {Array<TargetActor>}
*/
getTargetActors(browserId, connectionPrefix) {
getTargetActors(context, connectionPrefix) {
const actors = [];
for (const actor of windowGlobalTargetActors) {
if (
((!connectionPrefix || actor.actorID.startsWith(connectionPrefix)) &&
actor.browserId == browserId) ||
(browserId === null && actor.typeName === "parentProcessTarget")
) {
const isMatchingPrefix = actor.actorID.startsWith(connectionPrefix);
const isMatchingContext =
(context.type == "all" && actor.typeName === "parentProcessTarget") ||
(context.type == "browser-element" &&
actor.browserId == context.browserId);
if (isMatchingPrefix && isMatchingContext) {
actors.push(actor);
}
}
@ -72,23 +98,21 @@ var TargetActorRegistry = {
},
/**
* Return the parent process target actor. Returns null if it couldn't be found.
* Helper for tests to help track the number of targets created for a given tab.
* (Used by browser_ext_devtools_inspectedWindow.js)
*
* @returns {TargetActor|null}
* @param {Number} browserId: ID for the tab
*
* @returns {Number} Number of targets for this tab.
*/
getParentProcessTargetActor() {
getTargetActorsCountForBrowserElement(browserId) {
let count = 0;
for (const actor of windowGlobalTargetActors) {
if (actor.typeName === "parentProcessTarget") {
return actor;
if (actor.browserId == browserId) {
count++;
}
}
// The xpcshell target actor also lives in the "parent process", even if it
// is an instance of ContentProcessTargetActor.
if (xpcShellTargetActor) {
return xpcShellTargetActor;
}
return null;
return count;
},
};

Просмотреть файл

@ -897,7 +897,7 @@ function hasStyleSheetWatcherSupportForTarget(targetActor) {
sessionDataByWatcherActor.values()
).find(sessionData => {
const actors = TargetActorRegistry.getTargetActors(
targetActor.browserId,
sessionData.context,
sessionData.connectionPrefix
);
return actors.includes(targetActor);

Просмотреть файл

@ -448,14 +448,12 @@ exports.WatcherActor = protocol.ActorClassWithSpec(watcherSpec, {
* target helpers. (and only those which are ignored)
*/
_getTargetActorInParentProcess() {
if (this.context.type == "all") {
return TargetActorRegistry.getParentProcessTargetActor();
} else if (this.context.type == "browser-element") {
// Note: if any, the WindowGlobalTargetActor returned here is created for a parent process
// page and lives in the parent process.
return TargetActorRegistry.getTargetActor(this.context.browserId);
}
throw new Error("Unsupported context type: " + this.context.type);
// Note: For browser-element debugging, the WindowGlobalTargetActor returned here is created
// for a parent process page and lives in the parent process.
return TargetActorRegistry.getTopLevelTargetActorForContext(
this.context,
this.conn.prefix
);
},
/**

Просмотреть файл

@ -559,7 +559,7 @@ class DevToolsFrameChild extends JSWindowActorChild {
// For ex, regular toolbox versus browser console versus browser toolbox
const connectionPrefix = watcherActorID.replace(/watcher\d+$/, "");
const targetActors = TargetActorRegistry.getTargetActors(
context.browserId,
context,
connectionPrefix
);

Просмотреть файл

@ -24,7 +24,13 @@ add_task(async function() {
info(
"Spawn a content task in order to be able to manipulate actors and resource watchers directly"
);
await ContentTask.spawn(tab.linkedBrowser, [], function() {
const connectionPrefix = targetCommand.watcherFront.actorID.replace(
/watcher\d+$/,
""
);
await ContentTask.spawn(tab.linkedBrowser, [connectionPrefix], function(
_connectionPrefix
) {
const { require } = ChromeUtils.import(
"resource://devtools/shared/Loader.jsm"
);
@ -37,9 +43,14 @@ add_task(async function() {
} = require("devtools/server/actors/resources/index");
// Retrieve the target actor instance and its watcher for console messages
const targetActor = TargetActorRegistry.getTargetActor(
content.browsingContext.browserId
const targetActor = TargetActorRegistry.getTopLevelTargetActorForContext(
{
type: "browser-element",
browserId: content.browsingContext.browserId,
},
_connectionPrefix
);
ok(targetActor, "Got the top level target actor from the content process");
const watcher = getResourceWatcher(targetActor, TYPES.CONSOLE_MESSAGE);
// Storing the target actor in the global so we can retrieve it later, even if it