Bug 1732120 - [devtools] Remove FrameTargetActor in favor of WindowGlobalTargetActor. r=nchevobbe,devtools-backward-compat-reviewers

This intermediate actor is no longer useful for a while.
(Since we dropped the LocalTabProxy. I think since we introduced the TabDescriptor?)

I updated actor-hierarchy.md significantly as it was quite outdated!
We would probably benefit having a section dedicated to the WatcherActor.

Differential Revision: https://phabricator.services.mozilla.com/D126373
This commit is contained in:
Alexandre Poirot 2021-09-27 12:16:12 +00:00
parent 97cd4b0fcd
commit fafbaf95cb
14 changed files with 64 additions and 136 deletions

View File

@ -34,7 +34,7 @@ exports.TabDescriptorFactory = {
* - spawn a DevToolsServer in the parent process,
* - create a DevToolsClient
* - connect the DevToolsClient to the DevToolsServer
* - call RootActor's `getTab` request to retrieve the FrameTargetActor's form
* - call RootActor's `getTab` request to retrieve the WindowGlobalTargetActor's form
*
* @param {XULTab} tab
* The tab to use in creating a new descriptor.

View File

@ -15,30 +15,33 @@ RootActor: First one, automatically instantiated when we start connecting.
| Actors exposing features related to the main process, that are not
| specific to any particular target (document, tab, add-on, or worker).
| These actors are registered with `global: true` in
| devtools/server/main.js.
| devtools/server/actors/utils/actor-registry.js
| Examples include:
| PreferenceActor (for Firefox prefs)
|
\-- Target actors:
Actors that represent the main "thing" being targeted by a given toolbox,
such as a tab, frame, worker, add-on, etc. and track its lifetime.
Generally, there is a target actor for each thing you can point a
toolbox at.
Examples include:
FrameTargetActor (for a frame, such as a tab)
WorkerTargetActor (for various kind of workers)
|
\-- Target-scoped actors:
Actors exposing one particular feature set. They are children of a
given target actor and the data they return is filtered to reflect
the target.
These actors are registered with `target: true` in
devtools/server/main.js.
Examples include:
WebConsoleActor
InspectorActor
These actors may extend this hierarchy by having their own children,
like LongStringActor, WalkerActor, etc.
\-- Descriptor Actor's -or- Watcher Actor
|
\ -- Target actors:
Actors that represent the main "thing" being targeted by a given toolbox,
such as a tab, frame, worker, add-on, etc. and track its lifetime.
Generally, there is a target actor for each thing you can point a
toolbox at.
Examples include:
WindowGlobalTargetActor (for a WindowGlobal, such as a tab or a remote iframe)
ProcessTargetActor
WorkerTargetActor (for various kind of workers)
|
\-- Target-scoped actors:
Actors exposing one particular feature set. They are children of a
given target actor and the data they return is filtered to reflect
the target.
These actors are registered with `target: true` in
devtools/server/actors/utils/actor-registry.js
Examples include:
WebConsoleActor
InspectorActor
These actors may extend this hierarchy by having their own children,
like LongStringActor, WalkerActor, etc.
```
## RootActor
@ -54,25 +57,14 @@ RootActor (root.js)
|
|-- TabDescriptorActor (descriptors/tab.js)
| Targets frames (such as a tab) living in the parent or child process.
| Note that this is just a proxy for FrameTargetActor, which is loaded via
| the frame's message manager as a frame script in the process containing
| the frame content. This proxy via message manager is always used, even
| when the content happens to be in the same process.
| Returned by "listTabs" or "getTab" requests.
| |
| \-- FrameTargetActor (frame.js)
| The "real" target actor for a frame (such as a tab) which runs in
| whichever process holds the content. FrameTargetActorProxy
| communicates with this via the frame's message manager.
| Extends the abstract class WindowGlobalTargetActor.
| Returned by "connect" server method on FrameTargetActorProxy.
|
|-- WorkerTargetActor (worker.js)
| Targets a worker (applies to various kinds like web worker, service
| worker, etc.).
| Returned by "listWorkers" request to the root actor to get all workers.
| Returned by "listWorkers" request to a FrameTargetActorProxy to get
| workers for a specific frame.
| Returned by "listWorkers" request to a WindowGlobalTargetActor to get
| workers for a specific document/WindowGlobal.
| Returned by "listWorkers" request to a ContentProcessTargetActor to get
| workers for the chrome of the child process.
|
@ -104,18 +96,26 @@ RootActor (root.js)
Extends ParentProcessTargetActor.
Returned by "connect" request to WebExtensionActor.
```
All these descriptor actors expose a `getTarget()` method which
returns the target actor for the descriptor's debuggable context
(tab, worker, process or add-on).
But note that this is now considered as a deprecated codepath.
Ideally, all targets should be retrieved via the new WatcherActor.
For now, the WatcherActor only support tabs and entire browser debugging.
Workers and add-ons still have to go through descriptor's getTarget.
## Target Actors
Those are the actors exposed by the root actors which are meant to track the
lifetime of a given target: tab, process, add-on, or worker. It also allows to
fetch the target-scoped actors connected to this target, which are actors like
console, inspector, thread (for debugger), style inspector, etc.
Those are the actors exposed by the watcher actor, or, via descriptor's getTarget methods.
They are meant to track the lifetime of a given target: document, process, add-on, or worker.
It also allows to fetch the target-scoped actors connected to this target,
which are actors like console, inspector, thread (for debugger), style inspector, etc.
Some target actors inherit from WindowGlobalTargetActor (defined in
browsing-context.js) which is meant for "browsing contexts" which present
window-global.js) which is meant for "window globals" which present
documents to the user. It automatically tracks the lifetime of the targeted
browsing context, but it also tracks its iframes and allows switching the
window global, but it also tracks its iframes and allows switching the
target to one of its iframes.
For historical reasons, target actors also handle creating the ThreadActor, used
@ -164,7 +164,7 @@ Each of these actors focuses on providing one particular feature set. They are
children of a given target actor.
The data they return is filtered to reflect the target. For example, the
InspectorActor that you fetch from a FrameTargetActor gives you information
InspectorActor that you fetch from a WindowGlobalTargetActor gives you information
about the markup and styles for only that frame.
These actors may extend this hierarchy by having their own children, like

View File

@ -6,7 +6,7 @@
/*
* Descriptor Actor that represents a Tab in the parent process. It
* launches a FrameTargetActor in the content process to do the real work and tunnels the
* launches a WindowGlobalTargetActor in the content process to do the real work and tunnels the
* data.
*
* See devtools/docs/backend/actor-hierarchy.md for more details.
@ -36,7 +36,7 @@ loader.lazyRequireGetter(
/**
* Creates a target actor proxy for handling requests to a single browser frame.
* Both <xul:browser> and <iframe mozbrowser> are supported.
* This actor is a shim that connects to a FrameTargetActor in a remote browser process.
* This actor is a shim that connects to a WindowGlobalTargetActor in a remote browser process.
* All RDP packets get forwarded using the message manager.
*
* @param connection The main RDP connection.

View File

@ -302,7 +302,7 @@ HighlighterEnvironment.prototype = {
* *and* if we're in the Browser Toolbox (to inspect Firefox Desktop): the
* targetActor is the RootActor, in which case, the window property can be
* used to listen to events.
* - With Firefox Desktop, the targetActor is a FrameTargetActor, and we use
* - With Firefox Desktop, the targetActor is a WindowGlobalTargetActor, and we use
* the chromeEventHandler which gives us a target we can use to listen to
* events, even from nested iframes.
* - If the environment was initialized from a window, we also use the

View File

@ -452,11 +452,11 @@ const NodeActor = protocol.ActorClassWithSpec(nodeSpec, {
// this throws as the debugger can _not_ be in the same compartment as the debugger.
// This happens when we toggle fission for content toolbox because we try to reparent
// the Walker of the tab. This happens because we do not detect in Walker.reparentRemoteFrame
// that the target of the tab is the top level. That's because the target is a FrameTargetActor
// that the target of the tab is the top level. That's because the target is a WindowGlobalTargetActor
// which is retrieved via Node.getEmbedderElement and doesn't return the LocalTabTargetActor.
// We should probably work on TabDescriptor so that the LocalTabTargetActor has a descriptor,
// and see if we can possibly move the local tab specific out of the TargetActor and have
// the TabDescriptor expose a pure FrameTargetActor?? (See bug 1579042)
// the TabDescriptor expose a pure WindowGlobalTargetActor?? (See bug 1579042)
if (Cu.getObjectPrincipal(global) == Cu.getObjectPrincipal(dbg)) {
return undefined;
}

View File

@ -1,46 +0,0 @@
/* 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";
/*
* Target actor for a frame / docShell in the content process (where the actual
* content lives).
*
* This actor extends WindowGlobalTargetActor.
*
* See devtools/docs/backend/actor-hierarchy.md for more details.
*/
const {
windowGlobalTargetPrototype,
} = require("devtools/server/actors/targets/window-global");
const { extend } = require("devtools/shared/extend");
const { frameTargetSpec } = require("devtools/shared/specs/targets/frame");
const Targets = require("devtools/server/actors/targets/index");
const TargetActorMixin = require("devtools/server/actors/targets/target-actor-mixin");
/**
* Protocol.js expects only the prototype object, and does not maintain the prototype
* chain when it constructs the ActorClass. For this reason we are using `extend` to
* maintain the properties of WindowGlobalTargetActor.prototype
*
* Target actor for a frame / docShell in the content process.
*/
const frameTargetPrototype = extend({}, windowGlobalTargetPrototype);
Object.defineProperty(frameTargetPrototype, "title", {
get: function() {
return this.window.document.title;
},
enumerable: true,
configurable: true,
});
exports.FrameTargetActor = TargetActorMixin(
Targets.TYPES.FRAME,
frameTargetSpec,
frameTargetPrototype
);

View File

@ -6,7 +6,6 @@
DevToolsModules(
"content-process.js",
"frame.js",
"index.js",
"parent-process.js",
"target-actor-mixin.js",

View File

@ -14,7 +14,7 @@
* WindowGlobalTargetActor is an abstract class used by target actors that hold
* documents, such as frames, chrome windows, etc.
*
* This class is extended by FrameTargetActor, ParentProcessTargetActor.
* This class is extended by ParentProcessTargetActor, itself being extented by WebExtensionTargetActor.
*
* See devtools/docs/backend/actor-hierarchy.md for more details.
*
@ -237,7 +237,7 @@ const windowGlobalTargetPrototype = {
* - window-ready
* - navigate
*
* This class is subclassed by FrameTargetActor and others.
* This class is subclassed by ParentProcessTargetActor and others.
* Subclasses are expected to implement a getter for the docShell property.
*
* @param connection DevToolsServerConnection
@ -254,7 +254,7 @@ const windowGlobalTargetPrototype = {
* - isTopLevelTarget Boolean
* Should be set to true for all top-level targets. A top level target
* is the topmost target of a DevTools "session". For instance for a local
* tab toolbox, the FrameTargetActor for the content page is the top level target.
* tab toolbox, the WindowGlobalTargetActor for the content page is the top level target.
* For the Multiprocess Browser Toolbox, the parent process target is the top level
* target.
* At the moment this only impacts the WindowGlobalTarget `reconfigure`
@ -505,7 +505,7 @@ const windowGlobalTargetPrototype = {
* Getter for the window global's title.
*/
get title() {
return this.contentDocument.contentTitle;
return this.contentDocument.title;
},
/**

View File

@ -115,7 +115,7 @@ class DevToolsFrameChild extends JSWindowActorChild {
// The map is indexed by the Watcher Actor ID.
// The values are objects containing the following properties:
// - connection: the DevToolsServerConnection itself
// - actor: the FrameTargetActor instance
// - actor: the WindowGlobalTargetActor instance
this._connections = new Map();
this._onConnectionChange = this._onConnectionChange.bind(this);
@ -318,7 +318,7 @@ class DevToolsFrameChild extends JSWindowActorChild {
// before any packet is sent from the content process.
// As the order of messages is guaranteed to be delivered in the order they
// were queued, we don't have to wait for anything around this sendAsyncMessage call.
// In theory, the FrameTargetActor may emit events in its constructor.
// In theory, the WindowGlobalTargetActor may emit events in its constructor.
// If it does, such RDP packets may be lost.
// The important point here is to send this message before processing the watchedData,
// which will start the Watcher and start emitting resources on the target actor.
@ -370,14 +370,14 @@ class DevToolsFrameChild extends JSWindowActorChild {
"devtools/server/devtools-server"
);
const { FrameTargetActor } = this.loader.require(
"devtools/server/actors/targets/frame"
const { WindowGlobalTargetActor } = this.loader.require(
"devtools/server/actors/targets/window-global"
);
DevToolsServer.init();
// We want a special server without any root actor and only target-scoped actors.
// We are going to spawn a FrameTargetActor instance in the next few lines,
// We are going to spawn a WindowGlobalTargetActor instance in the next few lines,
// it is going to act like a root actor without being one.
DevToolsServer.registerActors({ target: true });
DevToolsServer.on("connectionchange", this._onConnectionChange);
@ -388,7 +388,7 @@ class DevToolsFrameChild extends JSWindowActorChild {
);
// Create the actual target actor.
const targetActor = new FrameTargetActor(connection, {
const targetActor = new WindowGlobalTargetActor(connection, {
docShell: this.docShell,
// Targets created from the server side, via Watcher actor and DevToolsFrame JSWindow
// actor pair are following WindowGlobal lifecycle. i.e. will be destroyed on any

View File

@ -102,7 +102,7 @@ var DevToolsServer = {
/**
* We run a special server in child process whose main actor is an instance
* of FrameTargetActor, but that isn't a root actor. Instead there is no root
* of WindowGlobalTargetActor, but that isn't a root actor. Instead there is no root
* actor registered on DevToolsServer.
*/
get rootlessServer() {

View File

@ -44,7 +44,7 @@ try {
DevToolsServer.init();
// We want a special server without any root actor and only target-scoped actors.
// We are going to spawn a FrameTargetActor instance in the next few lines,
// We are going to spawn a WindowGlobalTargetActor instance in the next few lines,
// it is going to act like a root actor without being one.
DevToolsServer.registerActors({ target: true });
@ -84,15 +84,15 @@ try {
});
} else {
const {
FrameTargetActor,
} = require("devtools/server/actors/targets/frame");
WindowGlobalTargetActor,
} = require("devtools/server/actors/targets/window-global");
const { docShell } = chromeGlobal;
// For a script loaded via loadFrameScript, the global is the content
// message manager.
// All FrameTarget actors created via the framescript are top-level
// targets. Non top-level FrameTarget actors are all created by the
// All WindowGlobalTarget actors created via the framescript are top-level
// targets. Non top-level WindowGlobalTarget actors are all created by the
// DevToolsFrameChild actor.
actor = new FrameTargetActor(conn, {
actor = new WindowGlobalTargetActor(conn, {
docShell,
isTopLevelTarget: true,
});

View File

@ -298,11 +298,6 @@ const Types = (exports.__TypesForTests = [
spec: "devtools/shared/specs/targets/content-process",
front: null,
},
{
types: ["frameTarget"],
spec: "devtools/shared/specs/targets/frame",
front: null,
},
{
types: ["parentProcessTarget"],
spec: "devtools/shared/specs/targets/parent-process",

View File

@ -1,19 +0,0 @@
/* 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 { generateActorSpec } = require("devtools/shared/protocol");
const { extend } = require("devtools/shared/extend");
const {
windowGlobalTargetSpecPrototype,
} = require("devtools/shared/specs/targets/window-global");
// Bug 1467560: Update `generateActorSpec` support extension more naturally
const frameTargetSpec = generateActorSpec(
extend(windowGlobalTargetSpecPrototype, {
typeName: "frameTarget",
})
);
exports.frameTargetSpec = frameTargetSpec;

View File

@ -6,7 +6,6 @@
DevToolsModules(
"content-process.js",
"frame.js",
"parent-process.js",
"webextension.js",
"window-global.js",