Bug 1172897 - Rename TabActor to BrowsingContextTargetActor. r=ochameau

MozReview-Commit-ID: LPTEx2h4F1o

--HG--
rename : devtools/server/actors/tab.js => devtools/server/actors/targets/browsing-context.js
rename : devtools/shared/specs/tab.js => devtools/shared/specs/targets/browsing-context.js
extra : rebase_source : e62720693ad492cdfb68ab21af1f54d78e85123a
This commit is contained in:
J. Ryan Stinnett 2018-05-25 18:20:28 -05:00
parent 37ba0f60c9
commit eaa4969e77
97 changed files with 869 additions and 801 deletions

View File

@ -60,7 +60,7 @@ exports.debugRemoteAddon = async function(addonForm, client) {
form: addonForm,
chrome: true,
client,
isTabActor: addonForm.isWebExtension
isBrowsingContext: addonForm.isWebExtension
};
const target = await TargetFactory.forRemoteTab(options);

View File

@ -252,7 +252,7 @@ var DebuggerController = {
DebuggerView.destroy();
this.StackFrames.disconnect();
this.ThreadState.disconnect();
if (this._target.isTabActor) {
if (this._target.isBrowsingContext) {
this.Workers.disconnect();
}
@ -309,7 +309,7 @@ var DebuggerController = {
}
});
if (this._target.isTabActor) {
if (this._target.isBrowsingContext) {
this.Workers.connect();
}
this.ThreadState.connect();

View File

@ -651,7 +651,7 @@ AddonDebugger.prototype = {
form: addonActor,
client: this.client,
chrome: true,
isTabActor: false
isBrowsingContext: false
};
let toolboxOptions = {

View File

@ -158,7 +158,7 @@ BrowserToolboxProcess.prototype = {
this.debuggerServer.on("connectionchange", this._onConnectionChange);
this.debuggerServer.init();
// We mainly need a root actor and tab actors for opening a toolbox, even
// We mainly need a root actor and target actors for opening a toolbox, even
// against chrome/content/addon. But the "no auto hide" button uses the
// preference actor, so also register the browser actors.
this.debuggerServer.registerAllActors();

View File

@ -96,7 +96,7 @@ function attachThread(toolbox) {
});
};
if (target.isTabActor) {
if (target.isBrowsingContext) {
// Attaching a tab, a browser process, or a WebExtensions add-on.
target.activeTab.attachThread(threadOptions, handleResponse);
} else if (target.isAddon) {

View File

@ -122,7 +122,7 @@ var onConnectionReady = async function([aType, aTraits]) {
const gParent = document.getElementById("globalActors");
// Build the Remote Process button
// If Fx<39, tab actors were used to be exposed on RootActor
// If Fx<39, chrome target actors were used to be exposed on RootActor
// but in Fx>=39, chrome is debuggable via getProcess() and ChromeActor
if (globals.consoleActor || gClient.mainRoot.traits.allowChromeProcess) {
const a = document.createElement("a");
@ -163,8 +163,8 @@ var onConnectionReady = async function([aType, aTraits]) {
function buildAddonLink(addon, parent) {
const a = document.createElement("a");
a.onclick = async function() {
const isTabActor = addon.isWebExtension;
openToolbox(addon, true, "webconsole", isTabActor);
const isBrowsingContext = addon.isWebExtension;
openToolbox(addon, true, "webconsole", isBrowsingContext);
};
a.textContent = addon.name;
@ -223,12 +223,12 @@ function handleConnectionTimeout() {
* The user clicked on one of the buttons.
* Opens the toolbox.
*/
function openToolbox(form, chrome = false, tool = "webconsole", isTabActor) {
function openToolbox(form, chrome = false, tool = "webconsole", isBrowsingContext) {
const options = {
form: form,
client: gClient,
chrome: chrome,
isTabActor: isTabActor
isBrowsingContext: isBrowsingContext
};
TargetFactory.forRemoteTab(options).then((target) => {
const hostType = Toolbox.HostType.WINDOW;

View File

@ -317,7 +317,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
form: response.form,
client: client,
chrome: true,
isTabActor: false
isBrowsingContext: false
};
return TargetFactory.forRemoteTab(options);
})

View File

@ -21,7 +21,7 @@ const { DebuggerClient } = require("devtools/shared/client/debugger-client");
* {Number} the tab outerWindowID
* - chrome: Optional
* {Boolean} Force the creation of a chrome target. Gives more privileges to
* the tab actor. Allows chrome execution in the webconsole and see chrome
* the target actor. Allows chrome execution in the webconsole and see chrome
* files in the debugger. (handy when contributing to firefox)
*
* If type == "process":
@ -51,7 +51,7 @@ exports.targetFromURL = async function targetFromURL(url) {
// (handy to debug chrome stuff in a child process)
let chrome = params.has("chrome");
let form, isTabActor;
let form, isBrowsingContext;
if (type === "tab") {
// Fetch target for a remote tab
id = parseInt(id, 10);
@ -79,8 +79,10 @@ exports.targetFromURL = async function targetFromURL(url) {
form = response.form;
chrome = true;
if (id != 0) {
// Child process are not exposing tab actors and only support debugger+console
isTabActor = false;
// Child processes are not exposing browsing context target actors with the full
// set of tab-scoped actors we would get from a browser tab. Instead, they only
// support debugger and console.
isBrowsingContext = false;
}
} catch (ex) {
if (ex.error == "noProcess") {
@ -111,7 +113,7 @@ exports.targetFromURL = async function targetFromURL(url) {
throw new Error(`targetFromURL, unsupported type '${type}' parameter`);
}
return TargetFactory.forRemoteTab({ client, form, chrome, isTabActor });
return TargetFactory.forRemoteTab({ client, form, chrome, isBrowsingContext });
};
/**

View File

@ -133,11 +133,11 @@ function TabTarget(tab) {
this._client = tab.client;
this._chrome = tab.chrome;
}
// Default isTabActor to true if not explicitly specified
if (typeof tab.isTabActor == "boolean") {
this._isTabActor = tab.isTabActor;
// Default isBrowsingContext to true if not explicitly specified
if (typeof tab.isBrowsingContext == "boolean") {
this._isBrowsingContext = tab.isBrowsingContext;
} else {
this._isTabActor = true;
this._isBrowsingContext = true;
}
}
@ -308,11 +308,13 @@ TabTarget.prototype = {
return this._chrome;
},
// Tells us if the related actor implements TabActor interface
// and requires to call `attach` request before being used
// and `detach` during cleanup
get isTabActor() {
return this._isTabActor;
// Tells us if the related actor implements BrowsingContextTargetActor
// interface and requires to call `attach` request before being used and
// `detach` during cleanup.
// TODO: This flag is quite confusing, try to find a better way.
// Bug 1465635 hopes to blow up these classes entirely.
get isBrowsingContext() {
return this._isBrowsingContext;
},
get window() {
@ -419,12 +421,12 @@ TabTarget.prototype = {
} else if (this._form.isWebExtension &&
this.client.mainRoot.traits.webExtensionAddonConnect) {
// The addonActor form is related to a WebExtensionParentActor instance,
// which isn't a tab actor on its own, it is an actor living in the parent process
// with access to the addon metadata, it can control the addon (e.g. reloading it)
// and listen to the AddonManager events related to the lifecycle of the addon
// (e.g. when the addon is disabled or uninstalled ).
// To retrieve the TabActor instance, we call its "connect" method,
// (which fetches the TabActor form from a WebExtensionChildActor instance).
// which isn't a target actor on its own, it is an actor living in the parent
// process with access to the addon metadata, it can control the addon (e.g.
// reloading it) and listen to the AddonManager events related to the lifecycle of
// the addon (e.g. when the addon is disabled or uninstalled).
// To retrieve the target actor instance, we call its "connect" method, (which
// fetches the target actor form from a WebExtensionChildActor instance).
const {form} = await this._client.request({
to: this._form.actor, type: "connect",
});
@ -476,13 +478,13 @@ TabTarget.prototype = {
attachTab();
}, e => this._remote.reject(e));
} else if (this.isTabActor) {
} else if (this.isBrowsingContext) {
// In the remote debugging case, the protocol connection will have been
// already initialized in the connection screen code.
attachTab();
} else {
// AddonActor and chrome debugging on RootActor doesn't inherits from
// TabActor and doesn't need to be attached.
// AddonActor and chrome debugging on RootActor doesn't inherit from
// BrowsingContextTargetActor and doesn't need to be attached.
attachConsole();
}
@ -772,7 +774,7 @@ WorkerTarget.prototype = {
return true;
},
get isTabActor() {
get isBrowsingContext() {
return true;
},

View File

@ -19,7 +19,7 @@ function assertIsTabTarget(target, url, chrome = false) {
is(target.url, url);
is(target.isLocalTab, false);
is(target.chrome, chrome);
is(target.isTabActor, true);
is(target.isBrowsingContext, true);
is(target.isRemote, true);
}
@ -44,7 +44,7 @@ add_task(async function() {
is(target.url, window.location.href);
is(target.isLocalTab, false);
is(target.chrome, true);
is(target.isTabActor, true);
is(target.isBrowsingContext, true);
is(target.isRemote, true);
info("Test tab");

View File

@ -49,11 +49,11 @@ add_task(async function() {
info("Toolbox destroyed");
// Also wait for tabDetached. Toolbox destroys the Target which calls
// TabActor.detach(). But Target doesn't wait for detach's end to resolve.
// Whereas it is quite important as it is a significant part of toolbox
// cleanup. If we do not wait for it and starts removing debugged document,
// the actor is still considered as being attached and continues processing
// events.
// BrowsingContextTargetActor.detach(). But Target doesn't wait for detach's
// end to resolve. Whereas it is quite important as it is a significant part
// of toolbox cleanup. If we do not wait for it and starts removing debugged
// document, the actor is still considered as being attached and continues
// processing events.
await onTabActorDetached;
iframe.remove();

View File

@ -83,8 +83,8 @@ var connect = async function() {
if (addonID) {
const { addons } = await gClient.listAddons();
const addonActor = addons.filter(addon => addon.id === addonID).pop();
const isTabActor = addonActor.isWebExtension;
await openToolbox({form: addonActor, chrome: true, isTabActor});
const isBrowsingContext = addonActor.isWebExtension;
await openToolbox({form: addonActor, chrome: true, isBrowsingContext});
} else {
const response = await gClient.getProcess();
await openToolbox({form: response.form, chrome: true});
@ -130,12 +130,12 @@ function onCloseCommand(event) {
window.close();
}
async function openToolbox({ form, chrome, isTabActor }) {
async function openToolbox({ form, chrome, isBrowsingContext }) {
let options = {
form: form,
client: gClient,
chrome: chrome,
isTabActor: isTabActor
isBrowsingContext: isBrowsingContext
};
appendStatusMessage(`Create toolbox target: ${JSON.stringify(arguments, null, 2)}`);
const target = await TargetFactory.forRemoteTab(options);

View File

@ -2203,7 +2203,7 @@ Toolbox.prototype = {
_listFrames: function(event) {
if (!this._target.activeTab || !this._target.activeTab.traits.frames) {
// We are not targetting a regular TabActor
// We are not targetting a regular BrowsingContextTargetActor
// it can be either an addon or browser toolbox actor
return promise.resolve();
}

View File

@ -84,7 +84,7 @@ TooltipsOverlay.prototype = {
this._isStarted = true;
// For now, preview tooltip has to be instanciated on startup in order to
// For now, preview tooltip has to be instantiated on startup in order to
// call tooltip.startTogglingOnHover. Ideally startTogglingOnHover wouldn't be part
// of HTMLTooltip and offer a way to lazy load this tooltip.
this.getTooltip("previewTooltip");

View File

@ -40,7 +40,7 @@
return sandbox.exports;
};
// Ensure fetching a live TabActor form for the targeted app
// Ensure fetching a live target actor form
// (helps fetching the test actor registered dynamically)
const getUpdatedForm = function(client, tab) {
return client.getTab({tab: tab})

View File

@ -293,13 +293,13 @@ var testSpec = protocol.generateActorSpec({
});
var TestActor = exports.TestActor = protocol.ActorClassWithSpec(testSpec, {
initialize: function(conn, tabActor, options) {
initialize: function(conn, targetActor, options) {
this.conn = conn;
this.tabActor = tabActor;
this.targetActor = targetActor;
},
get content() {
return this.tabActor.window;
return this.targetActor.window;
},
/**
@ -532,7 +532,7 @@ var TestActor = exports.TestActor = protocol.ActorClassWithSpec(testSpec, {
return new Promise(resolve => {
// Wait for DOMWindowCreated first, as listening on the current outerwindow
// doesn't allow receiving test-page-processing-done.
this.tabActor.chromeEventHandler.addEventListener("DOMWindowCreated", () => {
this.targetActor.chromeEventHandler.addEventListener("DOMWindowCreated", () => {
this.content.addEventListener(
"test-page-processing-done", resolve, { once: true }
);

View File

@ -177,7 +177,7 @@ HUD_SERVICE.prototype =
const client = new DebuggerClient(DebuggerServer.connectPipe());
await client.connect();
const response = await client.getProcess();
return { form: response.form, client, chrome: true, isTabActor: true };
return { form: response.form, client, chrome: true, isBrowsingContext: true };
}
async function openWindow(t) {

View File

@ -145,7 +145,7 @@ WebConsoleConnectionProxy.prototype = {
this.target.on("navigate", this._onTabNavigated);
this._consoleActor = this.target.form.consoleActor;
if (this.target.isTabActor) {
if (this.target.isBrowsingContext) {
const tab = this.target.form;
this.webConsoleFrame.onLocationChange(tab.url, tab.title);
}

View File

@ -252,12 +252,12 @@ var AppManager = exports.AppManager = {
});
});
}
// Fx <39 exposes tab actors on the root actor
// Fx <39 exposes chrome target actors on the root actor
return TargetFactory.forRemoteTab({
form: this._listTabsResponse,
client: this.connection.client,
chrome: true,
isTabActor: false
isBrowsingContext: false
});
}
@ -273,7 +273,7 @@ var AppManager = exports.AppManager = {
return (async function() {
// Once we asked the app to launch, the app isn't necessary completely loaded.
// launch request only ask the app to launch and immediatly returns.
// We have to keep trying to get app tab actors required to create its target.
// We have to keep trying to get app target actors required to create its target.
for (let i = 0; i < 10; i++) {
try {
@ -495,7 +495,7 @@ var AppManager = exports.AppManager = {
},
isMainProcessDebuggable: function() {
// Fx <39 exposes chrome tab actors on RootActor
// Fx <39 exposes chrome target actors on RootActor
// Fx >=39 exposes a dedicated actor via getProcess request
return this.connection.client &&
this.connection.client.mainRoot &&

View File

@ -19,11 +19,11 @@ Ensure that the actor's destroy is really destroying everything that it should.
```js
destroy: function() {
Actor.prototype.destroy.call(this);
this.tabActor.off("will-navigate", this.onWillNavigate);
this.tabActor.off("navigate", this.onNavigate);
this.targetActor.off("will-navigate", this.onWillNavigate);
this.targetActor.off("navigate", this.onNavigate);
this.stopAnimationPlayerUpdates();
this.tabActor = this.observer = this.actors = null;
this.targetActor = this.observer = this.actors = null;
},
```

View File

@ -1,7 +1,7 @@
# How actors are organized
To start with, actors are living within /devtools/server/actors/ folder.
They are organized in a hierarchy for easier lifecycle/memory management:
To start with, actors are living within devtools/server/actors folder.
They are organized in a hierarchy for easier lifecycle and memory management:
once a parent is removed from the pool, its children are removed as well.
(See actor-registration.md for more information about how to implement one)
@ -9,25 +9,36 @@ The overall hierarchy of actors looks like this:
```
RootActor: First one, automatically instantiated when we start connecting.
| Mostly meant to instantiate new actors.
| Mostly meant to instantiate new actors.
|
|--> Global-scoped actors:
| Actors exposing features related to the main process,
| that are not specific to any particular context (document, tab, app,
| add-on, or worker).
| A good example is the preference actor.
|-- Global-scoped actors:
| 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.
| Examples include:
| PreferenceActor (for Firefox prefs)
|
\--> "TabActor" (or alike):
| Actors meant to designate one context (document, tab, app,
| add-on, or worker) and track its lifetime. Generally, there is
| one of these for each thing you can point a toolbox at.
|
\--> Tab-scoped actors:
Actors exposing one particular feature set, this time,
specific to a given context (document, tab, app, add-on, or
worker). Examples include the console and inspector actors.
These actors may extend this hierarchy by having their
own children, like LongStringActor, WalkerActor, etc.
\-- 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:
ContentActor (for a frame, such as a tab)
WorkerActor (for various kind of workers)
|
\-- Tab-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 `tab: 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.
```
## RootActor
@ -48,10 +59,11 @@ RootActor (root.js)
| via message manager is always used, even when e10s is disabled.
| Returned by "listTabs" or "getTab" requests.
| |
| \-> ContentActor (content.js)
| \-- ContentActor (content.js)
| The "real" actor for a tab, which runs in whichever process holds the
| content. BrowserTabActor communicates with this via the tab's
| message manager.
| Extends the abstract class BrowsingContextTargetActor.
| Returned by "connect" on BrowserTabActor.
|
|-- WorkerActor (worker.js)
@ -66,11 +78,13 @@ RootActor (root.js)
|-- WindowActor (window.js)
| Targets a single window, such as a browser window in Firefox, but it can
| be used to reach any window in the parent process.
| Extends the abstract class BrowsingContextTargetActor.
| Returned by "getWindow" request to the root actor.
|
|-- ChromeActor (chrome.js)
| Targets all resources in the parent process of firefox
| (chrome documents, JSM, JS XPCOM, etc.).
| Extends the abstract class BrowsingContextTargetActor.
| Returned by "getProcess" request without any argument.
|
|-- ChildProcessActor (child-process.js)
@ -83,53 +97,73 @@ RootActor (root.js)
Returned by "listAddons" request.
```
## "TabActor"
## Target Actors
Those are the actors exposed by the root actors which are meant to track the
lifetime of a given context: tab, app, process, add-on, or worker. It also
allows to fetch the tab-scoped actors connected to this context. Actors like
console, inspector, thread (for debugger), styleinspector, etc. Most of them
inherit from TabActor (defined in tab.js) which is document centric. It
automatically tracks the lifetime of the targeted document, but it also tracks
its iframes and allows switching the context to one of its iframes. For
historical reasons, these actors also handle creating the ThreadActor, used to
manage breakpoints in the debugger. All the other tab-scoped actors are created
when we access the TabActor's grip. We return the tab-scoped actors `actorID` in
it. Actors inheriting from TabActor expose `attach`/`detach` requests, that
allows to start/stop the ThreadActor.
lifetime of a given target: tab, process, add-on, or worker. It also allows to
fetch the tab-scoped actors connected to this target, which are actors like
console, inspector, thread (for debugger), style inspector, etc.
The tab-scoped actors expect to find the following properties on the "TabActor":
Some target actors inherit from BrowsingContextTargetActor (defined in
browsing-context.js) which is meant for "browsing contexts" 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
target to one of its iframes.
For historical reasons, target actors also handle creating the ThreadActor, used
to manage breakpoints in the debugger. Actors inheriting from
BrowsingContextTargetActor expose `attach`/`detach` requests, that allows to
start/stop the ThreadActor.
Tab-scoped actors are accessed via the target actor's RDP form which contains
the `actorID` for each tab-scoped actor.
The tab-scoped actors expect to find the following properties on the target
actor:
- threadActor:
ThreadActor instance for the given context,
ThreadActor instance for the given target,
only defined once `attach` request is called, or on construction.
- isRootActor: (historical name)
Always false, except on ChromeActor.
Despite the attribute name, it is being used to accept all resources
(like chrome one) instead of limiting only to content resources.
- makeDebugger:
Helper function used to create Debugger object for the targeted context.
Helper function used to create Debugger object for the target.
(See actors/utils/make-debugger.js for more info)
In addition to this, the actors inheriting from TabActor, expose many other
attributes and events:
In addition to this, the actors inheriting from BrowsingContextTargetActor,
expose many other attributes and events:
- window:
Reference to the window global object currently targeted.
It can change over time if we switch context to an iframe, so it
It can change over time if we switch target to an iframe, so it
shouldn't be stored in a variable, but always retrieved from the actor.
- windows:
List of all document globals including the main window object and all iframes.
List of all document globals including the main window object and all
iframes.
- docShell:
DocShell reference for the targeted context.
Primary docShell reference for the targeted document.
- docShells:
List of all docshells for the targeted document and all its iframes.
List of all docShells for the targeted document and all its iframes.
- chromeEventHandler:
The chrome event handler for the current context. Allows to listen to events
The chrome event handler for the current target. Allows to listen to events
that can be missing/cancelled on this document itself.
See TabActor documentation for events definition.
See BrowsingContextTargetActor documentation for more details.
## Tab-scoped actors
Each of these actors focuses on providing one particular feature set, specific
to one context, that can be a web page, an app, a top level firefox window, a
process, an add-on, or a worker.
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 ContentActor gives you information about
the markup and styles for only that frame.
These actors may extend this hierarchy by having their own children, like
LongStringActor, WalkerActor, etc.
To improve performance, tab-scoped actors are created lazily. The target actor
lists the actor ID for each one, but the actor modules aren't actually loaded
and instantiated at that point. Once the first request for a given tab-scoped
actor is received by the server, that specific actor is instantiated just in
time to service the request.

View File

@ -6,7 +6,7 @@ Tab actors are the most common types of actors. That's the type of actors you wi
Tab actors target a document, this could be a tab in Firefox or a remote document in Firefox for Android.
Global actors however are for the rest, for things not related to any particular document but instead for things global to the whole Firefox/Chrome/Safari intance the toolbox is connected to (e.g. the preference actor).
Global actors however are for the rest, for things not related to any particular document but instead for things global to the whole Firefox/Chrome/Safari instance the toolbox is connected to (e.g. the preference actor).
## The DebuggerServer.registerModule function

View File

@ -658,69 +658,69 @@ where each *tab* describes a single open tab, and *selected* is the index in the
Each *tab* has the form:
```
{ "actor":<tabActor>, "title":<title>, "url":<URL> }
{ "actor":<targetActor>, "title":<title>, "url":<URL> }
```
where *tabActor* is the name of an actor representing the tab, and *title* and *URL* are the title and URL of the web page currently visible in that tab. This form may have other properties describing other tab-specific actors.
where *targetActor* is the name of an actor representing the tab, and *title* and *URL* are the title and URL of the web page currently visible in that tab. This form may have other properties describing other tab-specific actors.
To attach to a *tabActor*, a client sends a message of the form:
To attach to a *targetActor*, a client sends a message of the form:
```
{ "to":<tabActor>, "type":"attach" }
{ "to":<targetActor>, "type":"attach" }
```
The tab actor replies:
The target actor replies:
```
{ "from":<tabActor>, "type":"tabAttached", "threadActor":<tabThreadActor> }
{ "from":<targetActor>, "type":"tabAttached", "threadActor":<tabThreadActor> }
```
where *tabThreadActor* is the name of a thread-like actor representing the tab's current content. If the user navigates the tab, *tabThreadActor* switches to the new content; we do not create a separate thread-like actor each page the tab visits.
If the user closes the tab before the client attaches to it, *tabActor* replies:
If the user closes the tab before the client attaches to it, *targetActor* replies:
```
{ "from":<tabActor>, "type":"exited" }
{ "from":<targetActor>, "type":"exited" }
```
When the client is no longer interested in interacting with the tab, the client can request:
```
{ "to":<tabActor>, "type":"detach" }
{ "to":<targetActor>, "type":"detach" }
```
The *tabActor* replies:
The *targetActor* replies:
```
{ "from":<tabActor>, "type":"detached" }
{ "from":<targetActor>, "type":"detached" }
```
If the client was not already attached to *tabActor*, *tabActor* sends an error reply of the form:
If the client was not already attached to *targetActor*, *targetActor* sends an error reply of the form:
```
{ "from":<tabActor>, "error":"wrongState" }
{ "from":<targetActor>, "error":"wrongState" }
```
While the client is attached, *tabActor* sends notifications to the client whenever the user navigates the tab to a new page. When navigation begins, *tabActor* sends a packet of the form:
While the client is attached, *targetActor* sends notifications to the client whenever the user navigates the tab to a new page. When navigation begins, *targetActor* sends a packet of the form:
```
{ "from":<tabActor>, "type":"tabNavigated", "state":"start",
{ "from":<targetActor>, "type":"tabNavigated", "state":"start",
"url":<newURL> }
```
This indicates that the tab has begun navigating to *newURL*; JavaScript execution in the tab's prior page is suspended. When navigation is complete, *tabActor* sends a packet of the form:
This indicates that the tab has begun navigating to *newURL*; JavaScript execution in the tab's prior page is suspended. When navigation is complete, *targetActor* sends a packet of the form:
```
{ "from":<tabActor>, "type":"tabNavigated", "state":"stop",
{ "from":<targetActor>, "type":"tabNavigated", "state":"stop",
"url":<newURL>, "title":<newTitle> }
```
where *newURL* and *newTitle* are the URL and title of the page the tab is now showing. The *tabThreadActor* given in the response to the original `"attach"` packet is now debugging the new page's code.
If the user closes a tab to which the client is attached, its *tabActor* sends a notification packet of the form:
If the user closes a tab to which the client is attached, its *targetActor* sends a notification packet of the form:
```
{ "from":<tabActor>, "type":"tabDetached" }
{ "from":<targetActor>, "type":"tabDetached" }
```
The client is now detached from the tab.

View File

@ -123,10 +123,10 @@ Its goal is to provide a simple way for highlighters to insert their content int
Using this helper is quite simple:
```js
let helper = new CanvasFrameAnonymousContentHelper(tabActor, this.buildMarkup.bind(this));
let helper = new CanvasFrameAnonymousContentHelper(targetActor, this.buildMarkup.bind(this));
```
It only requires a `tabActor`, which highlighters get when they are instantiated, and a callback function that will be used to create and insert the content the first time the highlighter is shown, and every time there's a page navigation.
It only requires a `targetActor`, which highlighters get when they are instantiated, and a callback function that will be used to create and insert the content the first time the highlighter is shown, and every time there's a page navigation.
The returned object provides the following API:
@ -147,9 +147,9 @@ A good way to get started is by taking a look at [existing highlighters here](ht
Here is some boilerplate code for a new highlighter class:
```js
function MyNewHighlighter(tabActor) {
this.doc = tabActor.window.document;
this.markup = new CanvasFrameAnonymousContentHelper(tabActor, this._buildMarkup.bind(this));
function MyNewHighlighter(targetActor) {
this.doc = targetActor.window.document;
this.markup = new CanvasFrameAnonymousContentHelper(targetActor, this._buildMarkup.bind(this));
}
MyNewHighlighter.prototype = {

View File

@ -382,9 +382,9 @@ const AccessibleActor = ActorClassWithSpec(accessibleSpec, {
* service.
*/
const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
initialize(conn, tabActor) {
initialize(conn, targetActor) {
Actor.prototype.initialize.call(this, conn);
this.tabActor = tabActor;
this.targetActor = targetActor;
this.refMap = new Map();
this.setA11yServiceGetter();
this.onPick = this.onPick.bind(this);
@ -404,11 +404,11 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
},
get rootWin() {
return this.tabActor && this.tabActor.window;
return this.targetActor && this.targetActor.window;
},
get rootDoc() {
return this.tabActor && this.tabActor.window.document;
return this.targetActor && this.targetActor.window.document;
},
reset() {
@ -447,7 +447,7 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
this.highlighter.destroy();
this.highlighter = null;
this.tabActor = null;
this.targetActor = null;
this.refMap = null;
},
@ -918,7 +918,7 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
* Start picker content listeners.
*/
_startPickerListeners: function() {
const target = this.tabActor.chromeEventHandler;
const target = this.targetActor.chromeEventHandler;
target.addEventListener("mousemove", this.onHovered, true);
target.addEventListener("click", this.onPick, true);
target.addEventListener("mousedown", this._preventContentEvent, true);
@ -932,7 +932,7 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
* If content is still alive, stop picker content listeners.
*/
_stopPickerListeners: function() {
const target = this.tabActor.chromeEventHandler;
const target = this.targetActor.chromeEventHandler;
if (!target) {
return;
@ -967,7 +967,7 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
* tools UI.
*/
const AccessibilityActor = ActorClassWithSpec(accessibilitySpec, {
initialize(conn, tabActor) {
initialize(conn, targetActor) {
Actor.prototype.initialize.call(this, conn);
this.initializedDeferred = defer();
@ -989,7 +989,7 @@ const AccessibilityActor = ActorClassWithSpec(accessibilitySpec, {
}
Services.obs.addObserver(this, "a11y-init-or-shutdown");
this.tabActor = tabActor;
this.targetActor = targetActor;
},
bootstrap() {
@ -1181,7 +1181,7 @@ const AccessibilityActor = ActorClassWithSpec(accessibilitySpec, {
*/
getWalker() {
if (!this.walker) {
this.walker = new AccessibleWalkerActor(this.conn, this.tabActor);
this.walker = new AccessibleWalkerActor(this.conn, this.targetActor);
}
return this.walker;
},
@ -1216,7 +1216,7 @@ const AccessibilityActor = ActorClassWithSpec(accessibilitySpec, {
Actor.prototype.destroy.call(this);
this.walker = null;
this.tabActor = null;
this.targetActor = null;
resolver();
}
});

View File

@ -16,8 +16,8 @@ const { webconsoleSpec } = require("devtools/shared/specs/webconsole");
/**
* 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 TabActor.prototype
* */
* maintain the properties of BrowsingContextTargetActor.prototype
*/
const addonConsolePrototype = extend({}, WebConsoleActor.prototype);
/**

View File

@ -135,7 +135,7 @@ BrowserAddonActor.prototype = {
if (this.attached) {
this.onDetach();
// The BrowserAddonActor is not a TabActor and it has to send
// The BrowserAddonActor is not a BrowsingContextTargetActor and it has to send
// "tabDetached" directly to close the devtools toolbox window.
this.conn.send({ from: this.actorID, type: "tabDetached" });
}

View File

@ -605,28 +605,28 @@ exports.AnimationPlayerActor = AnimationPlayerActor;
* The Animations actor lists animation players for a given node.
*/
exports.AnimationsActor = protocol.ActorClassWithSpec(animationsSpec, {
initialize: function(conn, tabActor) {
initialize: function(conn, targetActor) {
Actor.prototype.initialize.call(this, conn);
this.tabActor = tabActor;
this.targetActor = targetActor;
this.onWillNavigate = this.onWillNavigate.bind(this);
this.onNavigate = this.onNavigate.bind(this);
this.onAnimationMutation = this.onAnimationMutation.bind(this);
this.allAnimationsPaused = false;
this.tabActor.on("will-navigate", this.onWillNavigate);
this.tabActor.on("navigate", this.onNavigate);
this.targetActor.on("will-navigate", this.onWillNavigate);
this.targetActor.on("navigate", this.onNavigate);
this.animationCreatedTimeMap = new Map();
},
destroy: function() {
Actor.prototype.destroy.call(this);
this.tabActor.off("will-navigate", this.onWillNavigate);
this.tabActor.off("navigate", this.onNavigate);
this.targetActor.off("will-navigate", this.onWillNavigate);
this.targetActor.off("navigate", this.onNavigate);
this.stopAnimationPlayerUpdates();
this.tabActor = this.observer = this.actors = this.walker = null;
this.targetActor = this.observer = this.actors = this.walker = null;
this.animationCreatedTimeMap.clear();
this.animationCreatedTimeMap = null;
@ -792,7 +792,7 @@ exports.AnimationsActor = protocol.ActorClassWithSpec(animationsSpec, {
}
let animations = [];
for (const {document} of this.tabActor.windows) {
for (const {document} of this.targetActor.windows) {
animations = [...animations, ...document.getAnimations({subtree: true})];
}
return animations;
@ -811,27 +811,27 @@ exports.AnimationsActor = protocol.ActorClassWithSpec(animationsSpec, {
},
/**
* Pause all animations in the current tabActor's frames.
* Pause all animations in the current targetActor's frames.
*/
pauseAll: function() {
// Until the WebAnimations API provides a way to play/pause via the document
// timeline, we have to iterate through the whole DOM to find all players.
for (const player of
this.getAllAnimations(this.tabActor.window.document, true)) {
this.getAllAnimations(this.targetActor.window.document, true)) {
this.pauseSync(player);
}
this.allAnimationsPaused = true;
},
/**
* Play all animations in the current tabActor's frames.
* Play all animations in the current targetActor's frames.
* This method only returns when animations have left their pending states.
*/
playAll: function() {
// Until the WebAnimations API provides a way to play/pause via the document
// timeline, we have to iterate through the whole DOM to find all players.
for (const player of
this.getAllAnimations(this.tabActor.window.document, true)) {
this.getAllAnimations(this.targetActor.window.document, true)) {
this.playSync(player);
}
this.allAnimationsPaused = false;
@ -966,7 +966,7 @@ exports.AnimationsActor = protocol.ActorClassWithSpec(animationsSpec, {
* Update all animation created time map.
*/
updateAllAnimationsCreatedTime() {
const currentAnimations = this.getAllAnimations(this.tabActor.window.document);
const currentAnimations = this.getAllAnimations(this.targetActor.window.document);
// Remove invalid animations.
for (const previousAnimation of this.animationCreatedTimeMap.keys()) {

View File

@ -231,19 +231,19 @@ var FunctionCallActor = protocol.ActorClassWithSpec(functionCallSpec, {
* This actor observes function calls on certain objects or globals.
*/
exports.CallWatcherActor = protocol.ActorClassWithSpec(callWatcherSpec, {
initialize: function(conn, tabActor) {
initialize: function(conn, targetActor) {
protocol.Actor.prototype.initialize.call(this, conn);
this.tabActor = tabActor;
this.targetActor = targetActor;
this._onGlobalCreated = this._onGlobalCreated.bind(this);
this._onGlobalDestroyed = this._onGlobalDestroyed.bind(this);
this._onContentFunctionCall = this._onContentFunctionCall.bind(this);
this.tabActor.on("window-ready", this._onGlobalCreated);
this.tabActor.on("window-destroyed", this._onGlobalDestroyed);
this.targetActor.on("window-ready", this._onGlobalCreated);
this.targetActor.on("window-destroyed", this._onGlobalDestroyed);
},
destroy: function(conn) {
protocol.Actor.prototype.destroy.call(this, conn);
this.tabActor.off("window-ready", this._onGlobalCreated);
this.tabActor.off("window-destroyed", this._onGlobalDestroyed);
this.targetActor.off("window-ready", this._onGlobalCreated);
this.targetActor.off("window-destroyed", this._onGlobalDestroyed);
this.finalize();
},
@ -255,7 +255,7 @@ exports.CallWatcherActor = protocol.ActorClassWithSpec(callWatcherSpec, {
onCall: null,
/**
* Starts waiting for the current tab actor's document global to be
* Starts waiting for the current target actor's document global to be
* created, in order to instrument the specified objects and become
* aware of everything the content does with them.
*/
@ -278,7 +278,7 @@ exports.CallWatcherActor = protocol.ActorClassWithSpec(callWatcherSpec, {
this.resumeRecording();
}
if (performReload) {
this.tabActor.window.location.reload();
this.targetActor.window.location.reload();
}
},
@ -309,7 +309,7 @@ exports.CallWatcherActor = protocol.ActorClassWithSpec(callWatcherSpec, {
* Initialize the timestamp epoch used to offset function call timestamps.
*/
initTimestampEpoch: function() {
this._timestampEpoch = this.tabActor.window.performance.now();
this._timestampEpoch = this.targetActor.window.performance.now();
},
/**
@ -336,7 +336,7 @@ exports.CallWatcherActor = protocol.ActorClassWithSpec(callWatcherSpec, {
},
/**
* Invoked whenever the current tab actor's document global is created.
* Invoked whenever the current target actor's document global is created.
*/
_onGlobalCreated: function({window, id, isTopLevel}) {
if (!this._initialized) {
@ -399,7 +399,8 @@ exports.CallWatcherActor = protocol.ActorClassWithSpec(callWatcherSpec, {
if (self._recording) {
const type = CallWatcherFront.METHOD_FUNCTION;
const stack = getStack(name);
const timestamp = self.tabActor.window.performance.now() - self._timestampEpoch;
const now = self.targetActor.window.performance.now();
const timestamp = now - self._timestampEpoch;
subcallback(unwrappedWindow, global, this, type, name, stack, timestamp,
args, result);
}
@ -432,8 +433,8 @@ exports.CallWatcherActor = protocol.ActorClassWithSpec(callWatcherSpec, {
if (self._recording) {
const type = CallWatcherFront.GETTER_FUNCTION;
const stack = getStack(name);
const timestamp =
self.tabActor.window.performance.now() - self._timestampEpoch;
const now = self.targetActor.window.performance.now();
const timestamp = now - self._timestampEpoch;
subcallback(unwrappedWindow, global, this, type, name, stack, timestamp,
args, result);
}
@ -448,8 +449,8 @@ exports.CallWatcherActor = protocol.ActorClassWithSpec(callWatcherSpec, {
if (self._recording) {
const type = CallWatcherFront.SETTER_FUNCTION;
const stack = getStack(name);
const timestamp =
self.tabActor.window.performance.now() - self._timestampEpoch;
const now = self.targetActor.window.performance.now();
const timestamp = now - self._timestampEpoch;
subcallback(unwrappedWindow, global, this, type, name, stack, timestamp,
args, undefined);
}
@ -516,7 +517,7 @@ exports.CallWatcherActor = protocol.ActorClassWithSpec(callWatcherSpec, {
},
/**
* Invoked whenever the current tab actor's inner window is destroyed.
* Invoked whenever the current target actor's inner window is destroyed.
*/
_onGlobalDestroyed: function({window, id, isTopLevel}) {
if (this._tracedWindowId == id) {

View File

@ -124,10 +124,10 @@ exports.CanvasActor = protocol.ActorClassWithSpec(canvasSpec, {
// any draw calls were called for a recording.
_animationContainsDrawCall: false,
initialize: function(conn, tabActor) {
initialize: function(conn, targetActor) {
protocol.Actor.prototype.initialize.call(this, conn);
this.tabActor = tabActor;
this._webGLPrimitiveCounter = new WebGLPrimitiveCounter(tabActor);
this.targetActor = targetActor;
this._webGLPrimitiveCounter = new WebGLPrimitiveCounter(targetActor);
this._onContentFunctionCall = this._onContentFunctionCall.bind(this);
},
destroy: function(conn) {
@ -142,13 +142,13 @@ exports.CanvasActor = protocol.ActorClassWithSpec(canvasSpec, {
setup: function({ reload }) {
if (this._initialized) {
if (reload) {
this.tabActor.window.location.reload();
this.targetActor.window.location.reload();
}
return;
}
this._initialized = true;
this._callWatcher = new CallWatcherActor(this.conn, this.tabActor);
this._callWatcher = new CallWatcherActor(this.conn, this.targetActor);
this._callWatcher.onCall = this._onContentFunctionCall;
this._callWatcher.setup({
tracedGlobals: CANVAS_CONTEXTS,

View File

@ -14,15 +14,15 @@ const WebGLPrimitivesType = {
};
/**
* A utility for monitoring WebGL primitive draws. Takes a `tabActor`
* A utility for monitoring WebGL primitive draws. Takes a `targetActor`
* and monitors primitive draws over time.
*/
const WebGLDrawArrays = "drawArrays";
const WebGLDrawElements = "drawElements";
exports.WebGLPrimitiveCounter = class WebGLPrimitiveCounter {
constructor(tabActor) {
this.tabActor = tabActor;
constructor(targetActor) {
this.targetActor = targetActor;
}
destroy() {}
@ -35,7 +35,7 @@ exports.WebGLPrimitiveCounter = class WebGLPrimitiveCounter {
this._vertices = 0;
this._points = 0;
this._lines = 0;
this._startTime = this.tabActor.docShell.now();
this._startTime = this.targetActor.docShell.now();
}
/**

View File

@ -7,29 +7,32 @@
const { Ci } = require("chrome");
const Services = require("Services");
const { DebuggerServer } = require("../main");
const { getChildDocShells, TabActor, tabPrototype } = require("./tab");
const {
getChildDocShells,
BrowsingContextTargetActor,
browsingContextTargetPrototype
} = require("devtools/server/actors/targets/browsing-context");
const makeDebugger = require("./utils/make-debugger");
const { extend } = require("devtools/shared/extend");
const { ActorClassWithSpec } = require("devtools/shared/protocol");
const { tabSpec } = require("devtools/shared/specs/tab");
const { browsingContextTargetSpec } = require("devtools/shared/specs/targets/browsing-context");
/**
* Creates a TabActor for debugging all the chrome content in the
* current process. Most of the implementation is inherited from TabActor.
* ChromeActor is a child of RootActor, it can be instanciated via
* RootActor.getProcess request.
* ChromeActor exposes all tab actors via its form() request, like TabActor.
* Creates a target actor for debugging all the chrome content in the current process.
* Most of the implementation is inherited from BrowsingContextTargetActor. ChromeActor is
* a child of RootActor, it can be instantiated via RootActor.getProcess request.
* ChromeActor exposes all tab actors via its form() request, like
* BrowsingContextTargetActor.
*
* History lecture:
* All tab actors used to also be registered as global actors,
* so that the root actor was also exposing tab actors for the main process.
* Tab actors ended up having RootActor as parent actor,
* but more and more features of the tab actors were relying on TabActor.
* So we are now exposing a process actor that offers the same API as TabActor
* by inheriting its functionality.
* Global actors are now only the actors that are meant to be global,
* and are no longer related to any specific scope/document.
* All tab actors used to also be registered as global actors, so that the root actor was
* also exposing tab actors for the main process. Tab actors ended up having RootActor as
* parent actor, but more and more features of the tab actors were relying on
* BrowsingContextTargetActor. So we are now exposing a process actor that offers the same
* API as BrowsingContextTargetActor by inheriting its functionality. Global actors are
* now only the actors that are meant to be global, and are no longer related to any
* specific scope/document.
*
* @param connection DebuggerServerConnection
* The connection to the client.
@ -38,13 +41,14 @@ const { tabSpec } = require("devtools/shared/specs/tab");
/**
* 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 TabActor.prototype
* maintain the properties of BrowsingContextTargetActor.prototype
* */
const chromePrototype = extend({}, tabPrototype);
const chromePrototype = extend({}, browsingContextTargetPrototype);
chromePrototype.initialize = function(connection) {
TabActor.prototype.initialize.call(this, connection);
BrowsingContextTargetActor.prototype.initialize.call(this, connection);
// This creates a Debugger instance for chrome debugging all globals.
this.makeDebugger = makeDebugger.bind(null, {
findDebuggees: dbg => dbg.findAllGlobals(),
@ -54,7 +58,7 @@ chromePrototype.initialize = function(connection) {
// Ensure catching the creation of any new content docshell
this.listenForNewDocShells = true;
// Defines the default docshell selected for the tab actor
// Defines the default docshell selected for the target actor
let window = Services.wm.getMostRecentWindow(DebuggerServer.chromeWindowType);
// Default to any available top level window if there is no expected window
@ -86,7 +90,7 @@ chromePrototype.initialize = function(connection) {
chromePrototype.isRootActor = true;
/**
* Getter for the list of all docshells in this tabActor
* Getter for the list of all docshells in this targetActor
* @return {Array}
*/
Object.defineProperty(chromePrototype, "docShells", {
@ -107,7 +111,7 @@ Object.defineProperty(chromePrototype, "docShells", {
});
chromePrototype.observe = function(subject, topic, data) {
TabActor.prototype.observe.call(this, subject, topic, data);
BrowsingContextTargetActor.prototype.observe.call(this, subject, topic, data);
if (!this.attached) {
return;
}
@ -126,7 +130,7 @@ chromePrototype._attach = function() {
return false;
}
TabActor.prototype._attach.call(this);
BrowsingContextTargetActor.prototype._attach.call(this);
// Listen for any new/destroyed chrome docshell
Services.obs.addObserver(this, "chrome-webnavigation-create");
@ -168,7 +172,7 @@ chromePrototype._detach = function() {
this._progressListener.unwatch(docShell);
}
TabActor.prototype._detach.call(this);
BrowsingContextTargetActor.prototype._detach.call(this);
return undefined;
};
@ -206,4 +210,4 @@ chromePrototype.postNest = function(nestData) {
chromePrototype.typeName = "Chrome";
exports.chromePrototype = chromePrototype;
exports.ChromeActor = ActorClassWithSpec(tabSpec, chromePrototype);
exports.ChromeActor = ActorClassWithSpec(browsingContextTargetSpec, chromePrototype);

View File

@ -133,13 +133,13 @@ exports.ObservedActorFactory = ObservedActorFactory;
* actors are already there. Add all actors in the final extra actors table to
* |pool|.
*
* The root actor and the tab actor use this to instantiate actors that other
* The root actor and the target actor use this to instantiate actors that other
* parts of the browser have specified with DebuggerServer.addTabActor and
* DebuggerServer.addGlobalActor.
*
* @param factories
* An object whose own property names are the names of properties to add to
* some reply packet (say, a tab actor grip or the "listTabs" response
* some reply packet (say, a target actor grip or the "listTabs" response
* form), and whose own property values are actor constructor functions, as
* documented for addTabActor and addGlobalActor.
*

View File

@ -5,20 +5,23 @@
"use strict";
var { Cr } = require("chrome");
var { TabActor, tabPrototype } = require("devtools/server/actors/tab");
var {
BrowsingContextTargetActor,
browsingContextTargetPrototype
} = require("devtools/server/actors/targets/browsing-context");
const { extend } = require("devtools/shared/extend");
const { ActorClassWithSpec } = require("devtools/shared/protocol");
const { tabSpec } = require("devtools/shared/specs/tab");
const { browsingContextTargetSpec } = require("devtools/shared/specs/targets/browsing-context");
/**
* Tab actor for documents living in a child process.
* Target actor for documents living in a child process.
*
* Depends on TabActor, defined in tab.js.
* Depends on BrowsingContextTargetActor, defined in browsing-context.js.
*/
/**
* Creates a tab actor for handling requests to the single tab, like
* Creates a target actor for handling requests to the single tab, like
* attaching and detaching. ContentActor respects the actor factories
* registered with DebuggerServer.addTabActor.
*
@ -28,20 +31,20 @@ const { tabSpec } = require("devtools/shared/specs/tab");
* The content script global holding |content| and |docShell| properties for a tab.
* @param prefix
* the prefix used in protocol to create IDs for each actor.
* Used as ID identifying this particular TabActor from the parent process.
* Used as ID identifying this particular target actor from the parent process.
*/
/**
* 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 TabActor.prototype
* */
* maintain the properties of BrowsingContextTargetActor.prototype
*/
const contentPrototype = extend({}, tabPrototype);
const contentPrototype = extend({}, browsingContextTargetPrototype);
contentPrototype.initialize = function(connection, chromeGlobal) {
this._chromeGlobal = chromeGlobal;
TabActor.prototype.initialize.call(this, connection, chromeGlobal);
BrowsingContextTargetActor.prototype.initialize.call(this, connection, chromeGlobal);
this.traits.reconfigure = false;
this._sendForm = this._sendForm.bind(this);
this._chromeGlobal.addMessageListener("debug:form", this._sendForm);
@ -75,7 +78,7 @@ contentPrototype.exit = function() {
this._sendForm = null;
}
TabActor.prototype.exit.call(this);
BrowsingContextTargetActor.prototype.exit.call(this);
this._chromeGlobal = null;
};
@ -88,4 +91,4 @@ contentPrototype._sendForm = function() {
this._chromeGlobal.sendAsyncMessage("debug:form", this.form());
};
exports.ContentActor = ActorClassWithSpec(tabSpec, contentPrototype);
exports.ContentActor = ActorClassWithSpec(browsingContextTargetSpec, contentPrototype);

View File

@ -62,10 +62,10 @@ const l10n = exports.l10n = {
* });
*/
var CSSUsageActor = protocol.ActorClassWithSpec(cssUsageSpec, {
initialize: function(conn, tabActor) {
initialize: function(conn, targetActor) {
protocol.Actor.prototype.initialize.call(this, conn);
this._tabActor = tabActor;
this._targetActor = targetActor;
this._running = false;
this._onTabLoad = this._onTabLoad.bind(this);
@ -75,7 +75,7 @@ var CSSUsageActor = protocol.ActorClassWithSpec(cssUsageSpec, {
},
destroy: function() {
this._tabActor = undefined;
this._targetActor = undefined;
delete this._onTabLoad;
delete this._onChange;
@ -117,16 +117,16 @@ var CSSUsageActor = protocol.ActorClassWithSpec(cssUsageSpec, {
destroy: () => {}
};
this._progress = this._tabActor.docShell.QueryInterface(Ci.nsIInterfaceRequestor)
this._progress = this._targetActor.docShell.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebProgress);
this._progress.addProgressListener(this._progressListener, this._notifyOn);
if (noreload) {
// If we're not starting by reloading the page, then pretend that onload
// has just happened.
this._onTabLoad(this._tabActor.window.document);
this._onTabLoad(this._targetActor.window.document);
} else {
this._tabActor.window.location.reload();
this._targetActor.window.location.reload();
}
this.emit("state-change", { isRunning: true });
@ -167,8 +167,8 @@ var CSSUsageActor = protocol.ActorClassWithSpec(cssUsageSpec, {
this._visitedPages = new Set();
this._knownRules = new Map();
this._populateKnownRules(this._tabActor.window.document);
this._updateUsage(this._tabActor.window.document, false);
this._populateKnownRules(this._targetActor.window.document);
this._updateUsage(this._targetActor.window.document, false);
},
/**

View File

@ -24,11 +24,11 @@ const { TouchSimulator } = require("devtools/server/actors/emulation/touch-simul
*/
const EmulationActor = protocol.ActorClassWithSpec(emulationSpec, {
initialize(conn, tabActor) {
initialize(conn, targetActor) {
protocol.Actor.prototype.initialize.call(this, conn);
this.tabActor = tabActor;
this.docShell = tabActor.docShell;
this.touchSimulator = new TouchSimulator(tabActor.chromeEventHandler);
this.targetActor = targetActor;
this.docShell = targetActor.docShell;
this.touchSimulator = new TouchSimulator(targetActor.chromeEventHandler);
},
destroy() {
@ -36,7 +36,7 @@ const EmulationActor = protocol.ActorClassWithSpec(emulationSpec, {
this.clearNetworkThrottling();
this.clearTouchEventsOverride();
this.clearUserAgentOverride();
this.tabActor = null;
this.targetActor = null;
this.docShell = null;
this.touchSimulator = null;
protocol.Actor.prototype.destroy.call(this);
@ -48,10 +48,10 @@ const EmulationActor = protocol.ActorClassWithSpec(emulationSpec, {
* monitor, which for historical reasons is part of the console actor.
*/
get _consoleActor() {
if (this.tabActor.exited) {
if (this.targetActor.exited) {
return null;
}
const form = this.tabActor.form();
const form = this.targetActor.form();
return this.conn._getOrCreateActor(form.consoleActor);
},

View File

@ -15,9 +15,9 @@ const { framerateSpec } = require("devtools/shared/specs/framerate");
* @see devtools/server/performance/framerate.js for documentation.
*/
exports.FramerateActor = ActorClassWithSpec(framerateSpec, {
initialize: function(conn, tabActor) {
initialize: function(conn, targetActor) {
Actor.prototype.initialize.call(this, conn);
this.bridge = new Framerate(tabActor);
this.bridge = new Framerate(targetActor);
},
destroy: function(conn) {
Actor.prototype.destroy.call(this, conn);

View File

@ -12,12 +12,12 @@ const { createSystem } = require("gcli/system");
* Manage remote connections that want to talk to GCLI
*/
const GcliActor = ActorClassWithSpec(gcliSpec, {
initialize: function(conn, tabActor) {
initialize: function(conn, targetActor) {
Actor.prototype.initialize.call(this, conn);
this._commandsChanged = this._commandsChanged.bind(this);
this._tabActor = tabActor;
this._targetActor = targetActor;
// see _getRequisition()
this._requisitionPromise = undefined;
},
@ -28,7 +28,7 @@ const GcliActor = ActorClassWithSpec(gcliSpec, {
// If _getRequisition has not been called, just bail quickly
if (this._requisitionPromise == null) {
this._commandsChanged = undefined;
this._tabActor = undefined;
this._targetActor = undefined;
return Promise.resolve();
}
@ -40,7 +40,7 @@ const GcliActor = ActorClassWithSpec(gcliSpec, {
this._system = undefined;
this._requisitionPromise = undefined;
this._tabActor = undefined;
this._targetActor = undefined;
this._commandsChanged = undefined;
});
@ -170,7 +170,7 @@ const GcliActor = ActorClassWithSpec(gcliSpec, {
* Lazy init for a Requisition
*/
_getRequisition: function() {
if (this._tabActor == null) {
if (this._targetActor == null) {
throw new Error("GcliActor used post-destroy");
}
@ -179,7 +179,7 @@ const GcliActor = ActorClassWithSpec(gcliSpec, {
}
const Requisition = require("gcli/cli").Requisition;
const tabActor = this._tabActor;
const targetActor = this._targetActor;
this._system = createSystem({ location: "server" });
this._system.commands.onCommandsChange.add(this._commandsChanged);
@ -203,11 +203,11 @@ const GcliActor = ActorClassWithSpec(gcliSpec, {
},
get window() {
return tabActor.window;
return targetActor.window;
},
get document() {
return tabActor.window && tabActor.window.document;
return targetActor.window && targetActor.window.document;
}
};

View File

@ -86,15 +86,15 @@ exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
this._autohide = autohide;
this._inspector = inspector;
this._walker = this._inspector.walker;
this._tabActor = this._inspector.tabActor;
this._targetActor = this._inspector.targetActor;
this._highlighterEnv = new HighlighterEnvironment();
this._highlighterEnv.initFromTabActor(this._tabActor);
this._highlighterEnv.initFromTargetActor(this._targetActor);
this._highlighterReady = this._highlighterReady.bind(this);
this._highlighterHidden = this._highlighterHidden.bind(this);
this._onNavigate = this._onNavigate.bind(this);
const doc = this._tabActor.window.document;
const doc = this._targetActor.window.document;
// Only try to create the highlighter when the document is loaded,
// otherwise, wait for the navigate event to fire.
if (doc.documentElement && doc.readyState != "uninitialized") {
@ -103,7 +103,7 @@ exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
// Listen to navigation events to switch from the BoxModelHighlighter to the
// SimpleOutlineHighlighter, and back, if the top level window changes.
this._tabActor.on("navigate", this._onNavigate);
this._targetActor.on("navigate", this._onNavigate);
},
get conn() {
@ -120,7 +120,7 @@ exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
},
_createHighlighter: function() {
this._isPreviousWindowXUL = isXUL(this._tabActor.window);
this._isPreviousWindowXUL = isXUL(this._targetActor.window);
if (!this._isPreviousWindowXUL) {
this._highlighter = new BoxModelHighlighter(this._highlighterEnv,
@ -146,12 +146,12 @@ exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
_onNavigate: function({isTopLevel}) {
// Skip navigation events for non top-level windows, or if the document
// doesn't exist anymore.
if (!isTopLevel || !this._tabActor.window.document.documentElement) {
if (!isTopLevel || !this._targetActor.window.document.documentElement) {
return;
}
// Only rebuild the highlighter if the window type changed.
if (isXUL(this._tabActor.window) !== this._isPreviousWindowXUL) {
if (isXUL(this._targetActor.window) !== this._isPreviousWindowXUL) {
this._destroyHighlighter();
this._createHighlighter();
}
@ -162,7 +162,7 @@ exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
this.hideBoxModel();
this._destroyHighlighter();
this._tabActor.off("navigate", this._onNavigate);
this._targetActor.off("navigate", this._onNavigate);
this._highlighterEnv.destroy();
this._highlighterEnv = null;
@ -170,7 +170,7 @@ exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
this._autohide = null;
this._inspector = null;
this._walker = null;
this._tabActor = null;
this._targetActor = null;
},
/**
@ -260,7 +260,7 @@ exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
this._stopPickerListeners();
this._isPicking = false;
if (this._autohide) {
this._tabActor.window.setTimeout(() => {
this._targetActor.window.setTimeout(() => {
this._highlighter.hide();
}, HIGHLIGHTER_PICKED_TIMER);
}
@ -436,7 +436,7 @@ exports.CustomHighlighterActor = protocol.ActorClassWithSpec(customHighlighterSp
/**
* Create a highlighter instance given its typename
* The typename must be one of HIGHLIGHTER_CLASSES and the class must
* implement constructor(tabActor), show(node), hide(), destroy()
* implement constructor(targetActor), show(node), hide(), destroy()
*/
initialize: function(parent, typeName) {
protocol.Actor.prototype.initialize.call(this, null);
@ -455,9 +455,9 @@ exports.CustomHighlighterActor = protocol.ActorClassWithSpec(customHighlighterSp
// container to append their elements and thus a non-XUL window or they have
// to define a static XULSupported flag that indicates that the highlighter
// supports XUL windows. Otherwise, bail out.
if (!isXUL(this._parent.tabActor.window) || constructor.XULSupported) {
if (!isXUL(this._parent.targetActor.window) || constructor.XULSupported) {
this._highlighterEnv = new HighlighterEnvironment();
this._highlighterEnv.initFromTabActor(parent.tabActor);
this._highlighterEnv.initFromTargetActor(parent.targetActor);
this._highlighter = new constructor(this._highlighterEnv);
if (this._highlighter.on) {
this._highlighter.on("highlighter-event", this._onHighlighterEvent.bind(this));
@ -545,19 +545,19 @@ exports.CustomHighlighterActor = protocol.ActorClassWithSpec(customHighlighterSp
* The HighlighterEnvironment is an object that holds all the required data for
* highlighters to work: the window, docShell, event listener target, ...
* It also emits "will-navigate", "navigate" and "window-ready" events,
* similarly to the TabActor.
* similarly to the BrowsingContextTargetActor.
*
* It can be initialized either from a TabActor (which is the most frequent way
* of using it, since highlighters are usually initialized by the
* HighlighterActor or CustomHighlighterActor, which have a tabActor reference).
* It can also be initialized just with a window object (which is useful for
* when a highlighter is used outside of the debugger server context, for
* instance from a gcli command).
* It can be initialized either from a BrowsingContextTargetActor (which is the
* most frequent way of using it, since highlighters are usually initialized by
* the HighlighterActor or CustomHighlighterActor, which have a targetActor
* reference). It can also be initialized just with a window object (which is
* useful for when a highlighter is used outside of the debugger server context,
* for instance from a gcli command).
*/
function HighlighterEnvironment() {
this.relayTabActorWindowReady = this.relayTabActorWindowReady.bind(this);
this.relayTabActorNavigate = this.relayTabActorNavigate.bind(this);
this.relayTabActorWillNavigate = this.relayTabActorWillNavigate.bind(this);
this.relayTargetActorWindowReady = this.relayTargetActorWindowReady.bind(this);
this.relayTargetActorNavigate = this.relayTargetActorNavigate.bind(this);
this.relayTargetActorWillNavigate = this.relayTargetActorWillNavigate.bind(this);
EventEmitter.decorate(this);
}
@ -565,11 +565,11 @@ function HighlighterEnvironment() {
exports.HighlighterEnvironment = HighlighterEnvironment;
HighlighterEnvironment.prototype = {
initFromTabActor: function(tabActor) {
this._tabActor = tabActor;
this._tabActor.on("window-ready", this.relayTabActorWindowReady);
this._tabActor.on("navigate", this.relayTabActorNavigate);
this._tabActor.on("will-navigate", this.relayTabActorWillNavigate);
initFromTargetActor: function(targetActor) {
this._targetActor = targetActor;
this._targetActor.on("window-ready", this.relayTargetActorWindowReady);
this._targetActor.on("navigate", this.relayTargetActorNavigate);
this._targetActor.on("will-navigate", this.relayTargetActorWillNavigate);
},
initFromWindow: function(win) {
@ -617,7 +617,7 @@ HighlighterEnvironment.prototype = {
},
get isInitialized() {
return this._win || this._tabActor;
return this._win || this._targetActor;
},
get isXUL() {
@ -626,10 +626,10 @@ HighlighterEnvironment.prototype = {
get window() {
if (!this.isInitialized) {
throw new Error("Initialize HighlighterEnvironment with a tabActor " +
throw new Error("Initialize HighlighterEnvironment with a targetActor " +
"or window first");
}
const win = this._tabActor ? this._tabActor.window : this._win;
const win = this._targetActor ? this._targetActor.window : this._win;
return Cu.isDeadWrapper(win) ? null : win;
},
@ -653,41 +653,40 @@ HighlighterEnvironment.prototype = {
/**
* Get the right target for listening to events on the page.
* - If the environment was initialized from a TabActor *and* if we're in the
* Browser Toolbox (to inspect firefox desktop): the tabActor is the
* RootActor, in which case, the window property can be used to listen to
* events.
* - With firefox desktop, that tabActor is a BrowserTabActor, and with B2G,
* a ContentActor (which overrides BrowserTabActor). In both cases we use
* the chromeEventHandler which gives us a target we can use to listen to
* - If the environment was initialized from a BrowsingContextTargetActor
* *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 ContentActor, 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
* chromeEventHandler.
*/
get pageListenerTarget() {
if (this._tabActor && this._tabActor.isRootActor) {
if (this._targetActor && this._targetActor.isRootActor) {
return this.window;
}
return this.docShell && this.docShell.chromeEventHandler;
},
relayTabActorWindowReady: function(data) {
relayTargetActorWindowReady: function(data) {
this.emit("window-ready", data);
},
relayTabActorNavigate: function(data) {
relayTargetActorNavigate: function(data) {
this.emit("navigate", data);
},
relayTabActorWillNavigate: function(data) {
relayTargetActorWillNavigate: function(data) {
this.emit("will-navigate", data);
},
destroy: function() {
if (this._tabActor) {
this._tabActor.off("window-ready", this.relayTabActorWindowReady);
this._tabActor.off("navigate", this.relayTabActorNavigate);
this._tabActor.off("will-navigate", this.relayTabActorWillNavigate);
if (this._targetActor) {
this._targetActor.off("window-ready", this.relayTargetActorWindowReady);
this._targetActor.off("navigate", this.relayTargetActorNavigate);
this._targetActor.off("will-navigate", this.relayTargetActorWillNavigate);
}
// In case the environment was initialized from a window, we need to remove
@ -700,7 +699,7 @@ HighlighterEnvironment.prototype = {
}
}
this._tabActor = null;
this._targetActor = null;
this._win = null;
}
};

View File

@ -74,9 +74,9 @@ const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
* inspector-related actors, including the walker.
*/
exports.InspectorActor = protocol.ActorClassWithSpec(inspectorSpec, {
initialize: function(conn, tabActor) {
initialize: function(conn, targetActor) {
protocol.Actor.prototype.initialize.call(this, conn);
this.tabActor = tabActor;
this.targetActor = targetActor;
this._onColorPicked = this._onColorPicked.bind(this);
this._onColorPickCanceled = this._onColorPickCanceled.bind(this);
@ -92,11 +92,11 @@ exports.InspectorActor = protocol.ActorClassWithSpec(inspectorSpec, {
this._pageStylePromise = null;
this._walkerPromise = null;
this.walker = null;
this.tabActor = null;
this.targetActor = null;
},
get window() {
return this.tabActor.window;
return this.targetActor.window;
},
getWalker: function(options = {}) {
@ -109,9 +109,9 @@ exports.InspectorActor = protocol.ActorClassWithSpec(inspectorSpec, {
const window = this.window;
const domReady = () => {
const tabActor = this.tabActor;
const targetActor = this.targetActor;
window.removeEventListener("DOMContentLoaded", domReady, true);
this.walker = WalkerActor(this.conn, tabActor, options);
this.walker = WalkerActor(this.conn, targetActor, options);
this.manage(this.walker);
this.walker.once("destroyed", () => {
this._walkerPromise = null;
@ -238,7 +238,7 @@ exports.InspectorActor = protocol.ActorClassWithSpec(inspectorSpec, {
createEyeDropper: function() {
this.destroyEyeDropper();
this._highlighterEnv = new HighlighterEnvironment();
this._highlighterEnv.initFromTabActor(this.tabActor);
this._highlighterEnv.initFromTargetActor(this.targetActor);
this._eyeDropper = new EyeDropper(this._highlighterEnv);
},
@ -266,7 +266,7 @@ exports.InspectorActor = protocol.ActorClassWithSpec(inspectorSpec, {
this._eyeDropper.show(this.window.document.documentElement, options);
this._eyeDropper.once("selected", this._onColorPicked);
this._eyeDropper.once("canceled", this._onColorPickCanceled);
this.tabActor.once("will-navigate", this.destroyEyeDropper);
this.targetActor.once("will-navigate", this.destroyEyeDropper);
},
/**
@ -279,7 +279,7 @@ exports.InspectorActor = protocol.ActorClassWithSpec(inspectorSpec, {
this._eyeDropper.hide();
this._eyeDropper.off("selected", this._onColorPicked);
this._eyeDropper.off("canceled", this._onColorPickCanceled);
this.tabActor.off("will-navigate", this.destroyEyeDropper);
this.targetActor.off("will-navigate", this.destroyEyeDropper);
}
},
@ -290,7 +290,7 @@ exports.InspectorActor = protocol.ActorClassWithSpec(inspectorSpec, {
* don't render the canvasFrame without throwing any error.
*/
supportsHighlighters: function() {
const doc = this.tabActor.window.document;
const doc = this.targetActor.window.document;
const ns = doc.documentElement.namespaceURI;
// XUL documents do not support insertAnonymousContent().

View File

@ -337,7 +337,7 @@ const NodeActor = protocol.ActorClassWithSpec(nodeSpec, {
*/
getEventListeners: function(node) {
const parsers = this._eventParsers;
const dbg = this.parent().tabActor.makeDebugger();
const dbg = this.parent().targetActor.makeDebugger();
const listenerArray = [];
for (const [, {getListeners, normalizeListener}] of parsers) {

View File

@ -113,10 +113,10 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
* @param DebuggerServerConnection conn
* The server connection.
*/
initialize: function(conn, tabActor, options) {
initialize: function(conn, targetActor, options) {
protocol.Actor.prototype.initialize.call(this, conn);
this.tabActor = tabActor;
this.rootWin = tabActor.window;
this.targetActor = targetActor;
this.rootWin = targetActor.window;
this.rootDoc = this.rootWin.document;
this._refMap = new Map();
this._pendingMutations = [];
@ -142,14 +142,14 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
this._throttledEmitNewMutations = throttle(this._emitNewMutations.bind(this),
MUTATIONS_THROTTLING_DELAY);
tabActor.on("will-navigate", this.onFrameUnload);
tabActor.on("window-ready", this.onFrameLoad);
targetActor.on("will-navigate", this.onFrameUnload);
targetActor.on("window-ready", this.onFrameLoad);
// Ensure that the root document node actor is ready and
// managed.
this.rootNode = this.document();
this.layoutChangeObserver = getLayoutChangesObserver(this.tabActor);
this.layoutChangeObserver = getLayoutChangesObserver(this.targetActor);
this._onReflows = this._onReflows.bind(this);
this.layoutChangeObserver.on("reflows", this._onReflows);
this._onResize = this._onResize.bind(this);
@ -231,8 +231,8 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
this._retainedOrphans = null;
this._refMap = null;
this.tabActor.off("will-navigate", this.onFrameUnload);
this.tabActor.off("window-ready", this.onFrameLoad);
this.targetActor.off("will-navigate", this.onFrameUnload);
this.targetActor.off("window-ready", this.onFrameLoad);
this.onFrameLoad = null;
this.onFrameUnload = null;
@ -242,7 +242,7 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
this.layoutChangeObserver.off("reflows", this._onReflows);
this.layoutChangeObserver.off("resize", this._onResize);
this.layoutChangeObserver = null;
releaseLayoutChangesObserver(this.tabActor);
releaseLayoutChangesObserver(this.targetActor);
eventListenerService.removeListenerChangeListener(
this._onEventListenerChange);
@ -250,7 +250,7 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
this.onMutations = null;
this.layoutActor = null;
this.tabActor = null;
this.targetActor = null;
this.emit("destroyed");
} catch (e) {
@ -853,7 +853,7 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
_multiFrameQuerySelectorAll: function(selector) {
let nodes = [];
for (const {document} of this.tabActor.windows) {
for (const {document} of this.targetActor.windows) {
try {
nodes = [...nodes, ...document.querySelectorAll(selector)];
} catch (e) {
@ -1989,7 +1989,7 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
*/
getLayoutInspector: function() {
if (!this.layoutActor) {
this.layoutActor = new LayoutActor(this.conn, this.tabActor, this);
this.layoutActor = new LayoutActor(this.conn, this.targetActor, this);
}
return this.layoutActor;

View File

@ -127,17 +127,17 @@ const GridActor = ActorClassWithSpec(gridSpec, {
* The CSS layout actor provides layout information for the given document.
*/
const LayoutActor = ActorClassWithSpec(layoutSpec, {
initialize(conn, tabActor, walker) {
initialize(conn, targetActor, walker) {
Actor.prototype.initialize.call(this, conn);
this.tabActor = tabActor;
this.targetActor = targetActor;
this.walker = walker;
},
destroy() {
Actor.prototype.destroy.call(this);
this.tabActor = null;
this.targetActor = null;
this.walker = null;
},

View File

@ -10,6 +10,7 @@ DIRS += [
'highlighters',
'inspector',
'object',
'targets',
'utils',
'webconsole',
'worker',
@ -63,7 +64,6 @@ DevToolsModules(
'string.js',
'styles.js',
'stylesheets.js',
'tab.js',
'thread.js',
'timeline.js',
'webaudio.js',

View File

@ -41,7 +41,7 @@ var PerformanceActor = ActorClassWithSpec(performanceSpec, {
},
},
initialize: function(conn, tabActor) {
initialize: function(conn, targetActor) {
Actor.prototype.initialize.call(this, conn);
this._onRecordingStarted = this._onRecordingStarted.bind(this);
@ -51,7 +51,7 @@ var PerformanceActor = ActorClassWithSpec(performanceSpec, {
this._onTimelineData = this._onTimelineData.bind(this);
this._onConsoleProfileStart = this._onConsoleProfileStart.bind(this);
this.bridge = new PerformanceRecorder(conn, tabActor);
this.bridge = new PerformanceRecorder(conn, targetActor);
this.bridge.on("recording-started", this._onRecordingStarted);
this.bridge.on("recording-stopping", this._onRecordingStopping);

View File

@ -19,7 +19,7 @@ const EventEmitter = require("devtools/shared/event-emitter");
var PromisesActor = protocol.ActorClassWithSpec(promisesSpec, {
/**
* @param conn DebuggerServerConnection.
* @param parentActor TabActor|RootActor
* @param parentActor BrowsingContextTargetActor|RootActor
*/
initialize: function(conn, parentActor) {
protocol.Actor.prototype.initialize.call(this, conn);

View File

@ -17,7 +17,7 @@
* by any other actor that needs it.
*
* - Observable: A utility parent class, meant at being extended by classes that
* need a to observe something on the tabActor's windows.
* need a to observe something on the targetActor's windows.
*
* - Dedicated observers: There's only one of them for now: ReflowObserver which
* listens to reflow events via the docshell,
@ -34,20 +34,20 @@ const {reflowSpec} = require("devtools/shared/specs/reflow");
* The reflow actor tracks reflows and emits events about them.
*/
exports.ReflowActor = protocol.ActorClassWithSpec(reflowSpec, {
initialize: function(conn, tabActor) {
initialize: function(conn, targetActor) {
protocol.Actor.prototype.initialize.call(this, conn);
this.tabActor = tabActor;
this.targetActor = targetActor;
this._onReflow = this._onReflow.bind(this);
this.observer = getLayoutChangesObserver(tabActor);
this.observer = getLayoutChangesObserver(targetActor);
this._isStarted = false;
},
destroy: function() {
this.stop();
releaseLayoutChangesObserver(this.tabActor);
releaseLayoutChangesObserver(this.targetActor);
this.observer = null;
this.tabActor = null;
this.targetActor = null;
protocol.Actor.prototype.destroy.call(this);
},
@ -85,19 +85,19 @@ exports.ReflowActor = protocol.ActorClassWithSpec(reflowSpec, {
/**
* Base class for all sorts of observers that need to listen to events on the
* tabActor's windows.
* @param {TabActor} tabActor
* targetActor's windows.
* @param {BrowsingContextTargetActor} targetActor
* @param {Function} callback Executed everytime the observer observes something
*/
function Observable(tabActor, callback) {
this.tabActor = tabActor;
function Observable(targetActor, callback) {
this.targetActor = targetActor;
this.callback = callback;
this._onWindowReady = this._onWindowReady.bind(this);
this._onWindowDestroyed = this._onWindowDestroyed.bind(this);
this.tabActor.on("window-ready", this._onWindowReady);
this.tabActor.on("window-destroyed", this._onWindowDestroyed);
this.targetActor.on("window-ready", this._onWindowReady);
this.targetActor.on("window-destroyed", this._onWindowDestroyed);
}
Observable.prototype = {
@ -117,11 +117,11 @@ Observable.prototype = {
this.stop();
this.tabActor.off("window-ready", this._onWindowReady);
this.tabActor.off("window-destroyed", this._onWindowDestroyed);
this.targetActor.off("window-ready", this._onWindowReady);
this.targetActor.off("window-destroyed", this._onWindowDestroyed);
this.callback = null;
this.tabActor = null;
this.targetActor = null;
},
/**
@ -133,7 +133,7 @@ Observable.prototype = {
}
this.isObserving = true;
this._startListeners(this.tabActor.windows);
this._startListeners(this.targetActor.windows);
},
/**
@ -145,9 +145,9 @@ Observable.prototype = {
}
this.isObserving = false;
if (this.tabActor.attached && this.tabActor.docShell) {
// It's only worth stopping if the tabActor is still attached
this._stopListeners(this.tabActor.windows);
if (this.targetActor.attached && this.targetActor.docShell) {
// It's only worth stopping if the targetActor is still attached
this._stopListeners(this.targetActor.windows);
}
},
@ -208,8 +208,8 @@ exports.setIgnoreLayoutChanges = function(ignore, syncReflowNode) {
*
* This class isn't exported on the module because it shouldn't be instantiated
* to avoid creating several instances per tabs.
* Use `getLayoutChangesObserver(tabActor)`
* and `releaseLayoutChangesObserver(tabActor)`
* Use `getLayoutChangesObserver(targetActor)`
* and `releaseLayoutChangesObserver(targetActor)`
* which are exported to get and release instances.
*
* The observer loops every EVENT_BATCHING_DELAY ms and checks if layout changes
@ -219,10 +219,10 @@ exports.setIgnoreLayoutChanges = function(ignore, syncReflowNode) {
* - "reflows", with an array of all the reflows that occured,
* - "resizes", with an array of all the resizes that occured,
*
* @param {TabActor} tabActor
* @param {BrowsingContextTargetActor} targetActor
*/
function LayoutChangesObserver(tabActor) {
this.tabActor = tabActor;
function LayoutChangesObserver(targetActor) {
this.targetActor = targetActor;
this._startEventLoop = this._startEventLoop.bind(this);
this._onReflow = this._onReflow.bind(this);
@ -231,8 +231,8 @@ function LayoutChangesObserver(tabActor) {
// Creating the various observers we're going to need
// For now, just the reflow observer, but later we can add markupMutation,
// styleSheetChanges and styleRuleChanges
this.reflowObserver = new ReflowObserver(this.tabActor, this._onReflow);
this.resizeObserver = new WindowResizeObserver(this.tabActor, this._onResize);
this.reflowObserver = new ReflowObserver(this.targetActor, this._onReflow);
this.resizeObserver = new WindowResizeObserver(this.targetActor, this._onResize);
EventEmitter.decorate(this);
}
@ -262,7 +262,7 @@ LayoutChangesObserver.prototype = {
this.resizeObserver.destroy();
this.hasResized = false;
this.tabActor = null;
this.targetActor = null;
},
start: function() {
@ -301,9 +301,9 @@ LayoutChangesObserver.prototype = {
* Calls itself in a loop.
*/
_startEventLoop: function() {
// Avoid emitting events if the tabActor has been detached (may happen
// Avoid emitting events if the targetActor has been detached (may happen
// during shutdown)
if (!this.tabActor || !this.tabActor.attached) {
if (!this.targetActor || !this.targetActor.attached) {
return;
}
@ -374,21 +374,21 @@ LayoutChangesObserver.prototype = {
/**
* Get a LayoutChangesObserver instance for a given window. This function makes
* sure there is only one instance per window.
* @param {TabActor} tabActor
* @param {BrowsingContextTargetActor} targetActor
* @return {LayoutChangesObserver}
*/
var observedWindows = new Map();
function getLayoutChangesObserver(tabActor) {
const observerData = observedWindows.get(tabActor);
function getLayoutChangesObserver(targetActor) {
const observerData = observedWindows.get(targetActor);
if (observerData) {
observerData.refCounting++;
return observerData.observer;
}
const obs = new LayoutChangesObserver(tabActor);
observedWindows.set(tabActor, {
const obs = new LayoutChangesObserver(targetActor);
observedWindows.set(targetActor, {
observer: obs,
// counting references allows to stop the observer when no tabActor owns an
// counting references allows to stop the observer when no targetActor owns an
// instance.
refCounting: 1
});
@ -399,12 +399,12 @@ exports.getLayoutChangesObserver = getLayoutChangesObserver;
/**
* Release a LayoutChangesObserver instance that was retrieved by
* getLayoutChangesObserver. This is required to ensure the tabActor reference
* getLayoutChangesObserver. This is required to ensure the targetActor reference
* is removed and the observer is eventually stopped and destroyed.
* @param {TabActor} tabActor
* @param {BrowsingContextTargetActor} targetActor
*/
function releaseLayoutChangesObserver(tabActor) {
const observerData = observedWindows.get(tabActor);
function releaseLayoutChangesObserver(targetActor) {
const observerData = observedWindows.get(targetActor);
if (!observerData) {
return;
}
@ -412,20 +412,20 @@ function releaseLayoutChangesObserver(tabActor) {
observerData.refCounting--;
if (!observerData.refCounting) {
observerData.observer.destroy();
observedWindows.delete(tabActor);
observedWindows.delete(targetActor);
}
}
exports.releaseLayoutChangesObserver = releaseLayoutChangesObserver;
/**
* Reports any reflow that occurs in the tabActor's docshells.
* Reports any reflow that occurs in the targetActor's docshells.
* @extends Observable
* @param {TabActor} tabActor
* @param {BrowsingContextTargetActor} targetActor
* @param {Function} callback Executed everytime a reflow occurs
*/
class ReflowObserver extends Observable {
constructor(tabActor, callback) {
super(tabActor, callback);
constructor(targetActor, callback) {
super(targetActor, callback);
}
_startListeners(windows) {
@ -464,14 +464,14 @@ ReflowObserver.prototype.QueryInterface = ChromeUtils
.generateQI([Ci.nsIReflowObserver, Ci.nsISupportsWeakReference]);
/**
* Reports window resize events on the tabActor's windows.
* Reports window resize events on the targetActor's windows.
* @extends Observable
* @param {TabActor} tabActor
* @param {BrowsingContextTargetActor} targetActor
* @param {Function} callback Executed everytime a resize occurs
*/
class WindowResizeObserver extends Observable {
constructor(tabActor, callback) {
super(tabActor, callback);
constructor(targetActor, callback) {
super(targetActor, callback);
this.onResize = this.onResize.bind(this);
}
@ -489,14 +489,11 @@ class WindowResizeObserver extends Observable {
get listenerTarget() {
// For the rootActor, return its window.
if (this.tabActor.isRootActor) {
return this.tabActor.window;
if (this.targetActor.isRootActor) {
return this.targetActor.window;
}
// Otherwise, get the tabActor's chromeEventHandler.
return this.tabActor.window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell)
.chromeEventHandler;
// Otherwise, get the targetActor's chromeEventHandler.
return this.targetActor.chromeEventHandler;
}
}

View File

@ -147,14 +147,14 @@ RootActor.prototype = {
// Added in Firefox 40. Indicates that the backend supports registering custom
// commands through the WebConsoleCommands API.
webConsoleCommands: true,
// Whether root actor exposes tab actors and access to any window.
// Whether root actor exposes chrome target actors and access to any window.
// If allowChromeProcess is true, you can:
// * get a ChromeActor instance to debug chrome and any non-content
// resource via getProcess requests
// * get a WindowActor instance to debug windows which could be chrome,
// like browser windows via getWindow requests
// If allowChromeProcess is defined, but not true, it means that root actor
// no longer expose tab actors, but also that the above requests are
// no longer expose chrome target actors, but also that the above requests are
// forbidden for security reasons.
get allowChromeProcess() {
return DebuggerServer.allowChromeProcess;
@ -169,7 +169,7 @@ RootActor.prototype = {
// markers, currently in use by the network monitor. Fx45+
documentLoadingMarkers: true,
// Whether or not the webextension addon actor have to be connected
// to retrieve the extension child process tab actors.
// to retrieve the extension child process target actors.
webExtensionAddonConnect: true,
},
@ -573,7 +573,7 @@ RootActor.prototype = {
this._globalActorPool.removeActor(actor);
}
if (this._tabActorPool) {
// Iterate over TabActor instances to also remove tab actors
// Iterate over BrowsingContextTargetActor instances to also remove tab actors
// created during listTabs for each document.
this._tabActorPool.forEach(tab => {
tab.removeActorByName(name);

View File

@ -2596,10 +2596,10 @@ const StorageActor = protocol.ActorClassWithSpec(specs.storageSpec, {
return this.childWindowPool;
},
initialize(conn, tabActor) {
initialize(conn, targetActor) {
protocol.Actor.prototype.initialize.call(this, conn);
this.parentActor = tabActor;
this.parentActor = targetActor;
this.childActorPool = new Map();
this.childWindowPool = new Set();
@ -2618,7 +2618,7 @@ const StorageActor = protocol.ActorClassWithSpec(specs.storageSpec, {
Services.obs.addObserver(this, "inner-window-destroyed");
this.onPageChange = this.onPageChange.bind(this);
const handler = tabActor.chromeEventHandler;
const handler = targetActor.chromeEventHandler;
handler.addEventListener("pageshow", this.onPageChange, true);
handler.addEventListener("pagehide", this.onPageChange, true);

View File

@ -74,8 +74,8 @@ var PageStyleActor = protocol.ActorClassWithSpec(pageStyleSpec, {
this.onFrameUnload = this.onFrameUnload.bind(this);
this.onStyleSheetAdded = this.onStyleSheetAdded.bind(this);
this.inspector.tabActor.on("will-navigate", this.onFrameUnload);
this.inspector.tabActor.on("stylesheet-added", this.onStyleSheetAdded);
this.inspector.targetActor.on("will-navigate", this.onFrameUnload);
this.inspector.targetActor.on("stylesheet-added", this.onStyleSheetAdded);
this._styleApplied = this._styleApplied.bind(this);
this._watchedSheets = new Set();
@ -86,8 +86,8 @@ var PageStyleActor = protocol.ActorClassWithSpec(pageStyleSpec, {
return;
}
protocol.Actor.prototype.destroy.call(this);
this.inspector.tabActor.off("will-navigate", this.onFrameUnload);
this.inspector.tabActor.off("stylesheet-added", this.onStyleSheetAdded);
this.inspector.targetActor.off("will-navigate", this.onFrameUnload);
this.inspector.targetActor.off("stylesheet-added", this.onStyleSheetAdded);
this.inspector = null;
this.walker = null;
this.refMap = null;
@ -111,7 +111,7 @@ var PageStyleActor = protocol.ActorClassWithSpec(pageStyleSpec, {
// We need to use CSS from the inspected window in order to use CSS.supports() and
// detect the right platform features from there.
const CSS = this.inspector.tabActor.window.CSS;
const CSS = this.inspector.targetActor.window.CSS;
return {
actor: this.actorID,
@ -190,8 +190,8 @@ var PageStyleActor = protocol.ActorClassWithSpec(pageStyleSpec, {
* The actor for this style sheet
*/
_sheetRef: function(sheet) {
const tabActor = this.inspector.tabActor;
const actor = tabActor.createStyleSheetActor(sheet);
const targetActor = this.inspector.targetActor;
const actor = targetActor.createStyleSheetActor(sheet);
return actor;
},
@ -263,7 +263,7 @@ var PageStyleActor = protocol.ActorClassWithSpec(pageStyleSpec, {
* object with 'fontFaces', a list of fonts that apply to this node.
*/
getAllUsedFontFaces: function(options) {
const windows = this.inspector.tabActor.windows;
const windows = this.inspector.targetActor.windows;
let fontsList = [];
for (const win of windows) {
fontsList = [...fontsList,
@ -1141,7 +1141,7 @@ var StyleRuleActor = protocol.ActorClassWithSpec(styleRuleSpec, {
// We need to grab CSS from the window, since calling supports() on the
// one from the current global will fail due to not being an HTML global.
const CSS = this.pageStyle.inspector.tabActor.window.CSS;
const CSS = this.pageStyle.inspector.targetActor.window.CSS;
form.declarations = declarations.map(decl => {
// Use the 1-arg CSS.supports() call so that we also accept !important
// in the value.

View File

@ -357,7 +357,7 @@ var StyleSheetActor = protocol.ActorClassWithSpec(styleSheetSpec, {
parentStyleSheet = parentStyleSheet.parentStyleSheet;
}
// When the style is injected via nsIDOMWindowUtils.loadSheet, even
// the parent style sheet has no owner, so default back to tab actor
// the parent style sheet has no owner, so default back to target actor
// document
if (parentStyleSheet.ownerNode) {
this.ownerDocument = parentStyleSheet.ownerNode.ownerDocument;
@ -513,7 +513,7 @@ var StyleSheetActor = protocol.ActorClassWithSpec(styleSheetSpec, {
/**
* Try to locate the console actor if it exists via our parent actor (the tab).
*
* Keep this in sync with the TabActor version.
* Keep this in sync with the BrowsingContextTargetActor version.
*/
get _consoleActor() {
if (this.parentActor.exited) {
@ -642,10 +642,10 @@ var StyleSheetsActor = protocol.ActorClassWithSpec(styleSheetsSpec, {
return { actor: this.actorID };
},
initialize: function(conn, tabActor) {
initialize: function(conn, targetActor) {
protocol.Actor.prototype.initialize.call(this, null);
this.parentActor = tabActor;
this.parentActor = targetActor;
this._onNewStyleSheetActor = this._onNewStyleSheetActor.bind(this);
this._onSheetAdded = this._onSheetAdded.bind(this);
@ -686,7 +686,7 @@ var StyleSheetsActor = protocol.ActorClassWithSpec(styleSheetsSpec, {
},
/**
* Event handler that is called when a the tab actor emits window-ready.
* Event handler that is called when a the target actor emits window-ready.
*
* @param {Event} evt
* The triggering event.
@ -696,7 +696,7 @@ var StyleSheetsActor = protocol.ActorClassWithSpec(styleSheetsSpec, {
},
/**
* Event handler that is called when a the tab actor emits stylesheet-added.
* Event handler that is called when a the target actor emits stylesheet-added.
*
* @param {StyleSheetActor} actor
* The new style sheet actor.

View File

@ -1,5 +1,3 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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/. */
@ -8,9 +6,18 @@
/* global XPCNativeWrapper */
// For performance matters, this file should only be loaded in the targeted
// document process. For example, it shouldn't be evaluated in the parent
// process until we try to debug a document living in the parent process.
/*
* BrowsingContextTargetActor is an abstract class used by target actors that hold
* documents, such as frames, chrome windows, etc.
*
* This class is extended by ContentActor, ChromeActor, and WindowActor.
*
* See devtools/docs/backend/actor-hierarchy.md for more details.
*
* For performance matters, this file should only be loaded in the targeted context's
* process. For example, it shouldn't be evaluated in the parent process until we try to
* debug a document living in the parent process.
*/
var { Ci, Cu, Cr, Cc } = require("chrome");
var Services = require("Services");
@ -21,14 +28,14 @@ var {
var { DebuggerServer } = require("devtools/server/main");
var DevToolsUtils = require("devtools/shared/DevToolsUtils");
var { assert } = DevToolsUtils;
var { TabSources } = require("./utils/TabSources");
var makeDebugger = require("./utils/make-debugger");
var { TabSources } = require("devtools/server/actors/utils/TabSources");
var makeDebugger = require("devtools/server/actors/utils/make-debugger");
const InspectorUtils = require("InspectorUtils");
const EXTENSION_CONTENT_JSM = "resource://gre/modules/ExtensionContent.jsm";
const { ActorClassWithSpec, Actor } = require("devtools/shared/protocol");
const { tabSpec } = require("devtools/shared/specs/tab");
const { browsingContextTargetSpec } = require("devtools/shared/specs/targets/browsing-context");
loader.lazyRequireGetter(this, "ThreadActor", "devtools/server/actors/thread", true);
loader.lazyRequireGetter(this, "unwrapDebuggerObjectGlobal", "devtools/server/actors/thread", true);
@ -86,12 +93,19 @@ function getInnerId(window) {
.getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
}
const tabPrototype = {
const browsingContextTargetPrototype = {
/**
* Creates a TabActor whose main goal is to manage lifetime and
* expose the tab actors being registered via DebuggerServer.registerModule.
* But also track the lifetime of the document being tracked.
* BrowsingContextTargetActor is an abstract class used by target actors that
* hold documents, such as frames, chrome windows, etc. The term "browsing
* context" is defined in the HTML spec as "an environment in which `Document`
* objects are presented to the user". In Gecko, this means a browsing context
* is a `docShell`.
*
* TODO: Bug 1465637: Rename "tab" actors to something else.
* The main goal of this class is to expose the tab actors being registered via
* `DebuggerServer.registerModule` and manage their lifetimes. In addition,
* this class also tracks the lifetime of the targeted browsing context.
*
* ### Main requests:
*
@ -103,36 +117,37 @@ const tabPrototype = {
* Instantiates a ThreadActor that can be later attached to in order to
* debug JS sources in the document.
* `switchToFrame`:
* Change the targeted document of the whole TabActor, and its child tab actors
* Change the targeted document of the whole actor, and its child tab actors
* to an iframe or back to its original document.
*
* Most of the TabActor properties (like `chromeEventHandler` or `docShells`)
* are meant to be used by the various child tab actors.
* Most properties (like `chromeEventHandler` or `docShells`) are meant to be
* used by the various child target actors.
*
* ### RDP events:
*
* - `tabNavigated`:
* Sent when the tab is about to navigate or has just navigated to
* a different document.
* Sent when the browsing context is about to navigate or has just navigated
* to a different document.
* This event contains the following attributes:
* * url (string) The new URI being loaded.
* * nativeConsoleAPI (boolean) `false` if the console API of the page has
* been overridden (e.g. by Firebug),
* `true` if the Gecko implementation is used.
* * state (string) `start` if we just start requesting the new URL,
* `stop` if the new URL is done loading.
* * isFrameSwitching (boolean) Indicates the event is dispatched when
* switching the TabActor context to
* a different frame. When we switch to
* an iframe, there is no document load.
* The targeted document is most likely
* going to be already done loading.
* * title (string) The document title being loaded.
* (sent only on state=stop)
* * url (string)
* The new URI being loaded.
* * nativeConsoleAPI (boolean)
* `false` if the console API of the page has been overridden (e.g. by Firebug)
* `true` if the Gecko implementation is used
* * state (string)
* `start` if we just start requesting the new URL
* `stop` if the new URL is done loading
* * isFrameSwitching (boolean)
* Indicates the event is dispatched when switching the actor context to a
* different frame. When we switch to an iframe, there is no document
* load. The targeted document is most likely going to be already done
* loading.
* * title (string)
* The document title being loaded. (sent only on state=stop)
*
* - `frameUpdate`:
* Sent when there was a change in the child frames contained in the document
* or when the tab's context was switched to another frame.
* or when the actor's context was switched to another frame.
* This event can have four different forms depending on the type of change:
* * One or many frames are updated:
* { frames: [{ id, url, title, parentID }, ...] }
@ -140,18 +155,17 @@ const tabPrototype = {
* { frames: [{ id, destroy: true }]}
* * All frames got destroyed:
* { destroyAll: true }
* * We switched the context of the TabActor to a specific frame:
* * We switched the context of the actor to a specific frame:
* { selected: #id }
*
* ### Internal, non-rdp events:
* Various events are also dispatched on the TabActor itself that are not
* related to RDP, so, not sent to the client. They all relate to the documents
* tracked by the TabActor (its main targeted document, but also any of its
* iframes).
*
* Various events are also dispatched on the actor itself without being sent to
* the client. They all relate to the documents tracked by this target actor
* (its main targeted document, but also any of its iframes):
* - will-navigate
* This event fires once navigation starts.
* All pending user prompts are dealt with,
* but it is fired before the first request starts.
* This event fires once navigation starts. All pending user prompts are
* dealt with, but it is fired before the first request starts.
* - navigate
* This event is fired once the document's readyState is "complete".
* - window-ready
@ -164,27 +178,27 @@ const tabPrototype = {
* this page, so it's now live again and we should resume handling it.
* * For each existing document, when an `attach` request is received.
* At this point scripts in the page will be already loaded.
* * When `swapFrameLoaders` is used, such as with moving tabs between
* windows or toggling Responsive Design Mode.
* * When `swapFrameLoaders` is used, such as with moving browsing contexts
* between windows or toggling Responsive Design Mode.
* - window-destroyed
* This event is fired in two cases:
* * When the window object is destroyed, i.e. when the related document
* is garbage collected. This can happen when the tab is closed or the
* iframe is removed from the DOM.
* is garbage collected. This can happen when the browsing context is
* closed or the iframe is removed from the DOM.
* It is equivalent of `inner-window-destroyed` event.
* * When the page goes into the bfcache and gets frozen.
* The equivalent of `pagehide`.
* - changed-toplevel-document
* This event fires when we switch the TabActor targeted document
* This event fires when we switch the actor's targeted document
* to one of its iframes, or back to its original top document.
* It is dispatched between window-destroyed and window-ready.
* - stylesheet-added
* This event is fired when a StyleSheetActor is created.
* It contains the following attribute :
* It contains the following attribute:
* * actor (StyleSheetActor) The created actor.
*
* Note that *all* these events are dispatched in the following order
* when we switch the context of the TabActor to a given iframe:
* when we switch the context of the actor to a given iframe:
* - will-navigate
* - window-destroyed
* - changed-toplevel-document
@ -229,7 +243,7 @@ const tabPrototype = {
// as well as frame switching via `switchToFrame` request
frames: true,
// Do not require to send reconfigure request to reset the document state
// to what it was before using the TabActor
// to what it was before using the actor
noTabReconfigureOnClose: true,
// Supports the logInPage request.
logInPage: true,
@ -281,8 +295,10 @@ const tabPrototype = {
return this._contextPool;
},
// A constant prefix that will be used to form the actor ID by the server.
actorPrefix: "tab",
/**
* A constant prefix that will be used to form the actor ID by the server.
*/
typeName: "browsingContextTarget",
/**
* An object on which listen for DOMWindowCreated and pageshow events.
@ -292,7 +308,7 @@ const tabPrototype = {
},
/**
* Getter for the nsIMessageManager associated to the tab.
* Getter for the nsIMessageManager associated to the browsing context.
*/
get messageManager() {
try {
@ -305,15 +321,15 @@ const tabPrototype = {
},
/**
* Getter for the tab's doc shell.
* Getter for the browsing context's `docShell`.
*/
get docShell() {
throw new Error(
"The docShell getter should be implemented by a subclass of TabActor");
throw new Error("`docShell` getter should be overridden by a subclass of " +
"`BrowsingContextTargetActor`");
},
/**
* Getter for the list of all docshell in this tabActor
* Getter for the list of all `docShell`s in the browsing context.
* @return {Array}
*/
get docShells() {
@ -321,7 +337,7 @@ const tabPrototype = {
},
/**
* Getter for the tab content's DOM window.
* Getter for the browsing context's current DOM window.
*/
get window() {
// On xpcshell, there is no document
@ -344,10 +360,10 @@ const tabPrototype = {
/**
* Getter for the WebExtensions ContentScript globals related to the
* current tab content's DOM window.
* browsing context's current DOM window.
*/
get webextensionsContentScriptGlobals() {
// Ignore xpcshell runtime which spawn TabActors without a window
// Ignore xpcshell runtime which spawns target actors without a window
// and only retrieve the content scripts globals if the ExtensionContent JSM module
// has been already loaded (which is true if the WebExtensions internals have already
// been loaded in the same content process).
@ -359,7 +375,7 @@ const tabPrototype = {
},
/**
* Getter for the list of all content DOM windows in this tabActor
* Getter for the list of all content DOM windows in the browsing context.
* @return {Array}
*/
get windows() {
@ -370,7 +386,7 @@ const tabPrototype = {
},
/**
* Getter for the original docShell the tabActor got attached to in the first
* Getter for the original docShell this actor got attached to in the first
* place.
* Note that your actor should normally *not* rely on this top level docShell
* if you want it to show information relative to the iframe that's currently
@ -387,7 +403,7 @@ const tabPrototype = {
},
/**
* Getter for the original window the tabActor got attached to in the first
* Getter for the original window this actor got attached to in the first
* place.
* Note that your actor should normally *not* rely on this top level window if
* you want it to show information relative to the iframe that's currently
@ -407,7 +423,7 @@ const tabPrototype = {
},
/**
* Getter for the nsIWebNavigation for the tab.
* Getter for the nsIWebNavigation for the target.
*/
get webNavigation() {
return this.docShell
@ -416,25 +432,21 @@ const tabPrototype = {
},
/**
* Getter for the tab's document.
* Getter for the browsing context's document.
*/
get contentDocument() {
return this.webNavigation.document;
},
/**
* Getter for the tab title.
* @return string
* Tab title.
* Getter for the browsing context's title.
*/
get title() {
return this.contentDocument.contentTitle;
},
/**
* Getter for the tab URL.
* @return string
* Tab URL.
* Getter for the browsing context's URL.
*/
get url() {
if (this.webNavigation.currentURI) {
@ -456,14 +468,14 @@ const tabPrototype = {
assert(!this.exited,
"form() shouldn't be called on exited browser actor.");
assert(this.actorID,
"tab should have an actorID.");
"Actor should have an actorID.");
const response = {
actor: this.actorID
};
// We may try to access window while the document is closing, then
// accessing window throws. Also on xpcshell we are using tabactor even if
// accessing window throws. Also on xpcshell we are using this actor even if
// there is no valid document.
if (this.docShell && !this.docShell.isBeingDestroyed()) {
response.title = this.title;
@ -497,17 +509,18 @@ const tabPrototype = {
},
/**
* Called by the root actor when the underlying tab is closed.
* Called by the root actor when the underlying browsing context is closed.
*/
exit() {
if (this.exited) {
return;
}
// Tell the thread actor that the tab is closed, so that it may terminate
// Tell the thread actor that the browsing context is closed, so that it may terminate
// instead of resuming the debuggee script.
if (this._attached) {
this.threadActor._tabClosed = true;
// TODO: Bug 997119: Remove this coupling with thread actor
this.threadActor._parentClosed = true;
}
this._detach();
@ -523,8 +536,8 @@ const tabPrototype = {
},
/**
* Return true if the given global is associated with this tab and should be
* added as a debuggee, false otherwise.
* Return true if the given global is associated with this browsing context and should
* be added as a debuggee, false otherwise.
*/
_shouldAddNewGlobalAsDebuggee(wrappedGlobal) {
if (wrappedGlobal.hostAnnotations &&
@ -562,7 +575,7 @@ const tabPrototype = {
_appendExtraActors: appendExtraActors,
/**
* Does the actual work of attaching to a tab.
* Does the actual work of attaching to a browsing context.
*/
_attach() {
if (this._attached) {
@ -686,8 +699,8 @@ const tabPrototype = {
},
observe(subject, topic, data) {
// Ignore any event that comes before/after the tab actor is attached
// That typically happens during firefox shutdown.
// Ignore any event that comes before/after the actor is attached.
// That typically happens during Firefox shutdown.
if (!this.attached) {
return;
}
@ -750,16 +763,15 @@ const tabPrototype = {
} else {
// If for some reason (typically during Firefox shutdown), the original
// document is destroyed, and there is no other top level docshell,
// we detach the tab actor to unregister all listeners and prevent any
// exception
// we detach the actor to unregister all listeners and prevent any
// exception.
this.exit();
}
return;
}
// If the currently targeted context is destroyed,
// and we aren't on the top-level document,
// we have to switch to the top-level one.
// If the currently targeted browsing context is destroyed, and we aren't on
// the top-level document, we have to switch to the top-level one.
if (webProgress.DOMWindow == this.window &&
this.window != this._originalWindow) {
this._changeTopLevelDocument(this._originalWindow);
@ -881,17 +893,17 @@ const tabPrototype = {
},
/**
* Does the actual work of detaching from a tab.
* Does the actual work of detaching from a browsing context.
*
* @returns false if the tab wasn't attached or true of detaching succeeds.
* @returns false if the actor wasn't attached or true of detaching succeeds.
*/
_detach() {
if (!this.attached) {
return false;
}
// Check for docShell availability, as it can be already gone
// during Firefox shutdown.
// Check for `docShell` availability, as it can be already gone during
// Firefox shutdown.
if (this.docShell) {
this._unwatchDocShell(this.docShell);
this._restoreDocumentSettings();
@ -968,7 +980,7 @@ const tabPrototype = {
},
/**
* Bring the tab's window to front.
* Bring the browsing context's window to front.
*/
focus() {
if (this.window) {
@ -978,7 +990,7 @@ const tabPrototype = {
},
/**
* Reload the page in this tab.
* Reload the page in this browsing context.
*/
reload(request) {
const force = request && request.options && request.options.force;
@ -993,19 +1005,19 @@ const tabPrototype = {
this.webNavigation.reload(force ?
Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE :
Ci.nsIWebNavigation.LOAD_FLAGS_NONE);
}, "TabActor.prototype.reload's delayed body"));
}, "BrowsingContextTargetActor.prototype.reload's delayed body"));
return {};
},
/**
* Navigate this tab to a new location
* Navigate this browsing context to a new location
*/
navigateTo(request) {
// Wait a tick so that the response packet can be dispatched before the
// subsequent navigation event packet.
Services.tm.dispatchToMainThread(DevToolsUtils.makeInfallible(() => {
this.window.location = request.url;
}, "TabActor.prototype.navigateTo's delayed body"));
}, "BrowsingContextTargetActor.prototype.navigateTo's delayed body"));
return {};
},
@ -1016,7 +1028,7 @@ const tabPrototype = {
const options = request.options || {};
if (!this.docShell) {
// The tab is already closed.
// The browsing context is already closed.
return {};
}
this._toggleDevToolsSettings(options);
@ -1133,7 +1145,7 @@ const tabPrototype = {
*/
_getJavascriptEnabled() {
if (!this.docShell) {
// The tab is already closed.
// The browsing context is already closed.
return null;
}
@ -1154,7 +1166,7 @@ const tabPrototype = {
*/
_getCacheDisabled() {
if (!this.docShell) {
// The tab is already closed.
// The browsing context is already closed.
return null;
}
@ -1168,7 +1180,7 @@ const tabPrototype = {
*/
_getServiceWorkersTestingEnabled() {
if (!this.docShell) {
// The tab is already closed.
// The browsing context is already closed.
return null;
}
@ -1182,7 +1194,7 @@ const tabPrototype = {
*/
preNest() {
if (!this.window) {
// The tab is already closed.
// The browsing context is already closed.
return;
}
const windowUtils = this.window
@ -1197,7 +1209,7 @@ const tabPrototype = {
*/
postNest(nestData) {
if (!this.window) {
// The tab is already closed.
// The browsing context is already closed.
return;
}
const windowUtils = this.window
@ -1237,9 +1249,9 @@ const tabPrototype = {
const docShell = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
// Here is the very important call where we switch the currently
// targeted context (it will indirectly update this.window and
// many other attributes defined from docShell).
// Here is the very important call where we switch the currently targeted
// browsing context (it will indirectly update this.window and many other
// attributes defined from docShell).
Object.defineProperty(this, "docShell", {
value: docShell,
enumerable: true,
@ -1303,8 +1315,8 @@ const tabPrototype = {
},
/**
* Start notifying server and client about a new document
* being loaded in the currently targeted context.
* Start notifying server and client about a new document being loaded in the
* currently targeted browsing context.
*/
_willNavigate(window, newURI, request, isFrameSwitching = false) {
let isTopLevel = window == this.window;
@ -1314,11 +1326,11 @@ const tabPrototype = {
// Clear the iframe list if the original top-level document changes.
this._notifyDocShellDestroyAll();
// If the top level document changes and we are targeting
// an iframe, we need to reset to the upcoming new top level document.
// But for this will-navigate event, we will dispatch on the old window.
// (The inspector codebase expect to receive will-navigate for the
// currently displayed document in order to cleanup the markup view)
// If the top level document changes and we are targeting an iframe, we
// need to reset to the upcoming new top level document. But for this
// will-navigate event, we will dispatch on the old window. (The inspector
// codebase expect to receive will-navigate for the currently displayed
// document in order to cleanup the markup view)
if (this.window != this._originalWindow) {
reset = true;
window = this.window;
@ -1326,11 +1338,10 @@ const tabPrototype = {
}
}
// will-navigate event needs to be dispatched synchronously,
// by calling the listeners in the order or registration.
// This event fires once navigation starts,
// (all pending user prompts are dealt with),
// but before the first request starts.
// will-navigate event needs to be dispatched synchronously, by calling the
// listeners in the order or registration. This event fires once navigation
// starts, (all pending user prompts are dealt with), but before the first
// request starts.
this.emit("will-navigate", {
window: window,
isTopLevel: isTopLevel,
@ -1338,7 +1349,7 @@ const tabPrototype = {
request: request
});
// We don't do anything for inner frames in TabActor.
// We don't do anything for inner frames here.
// (we will only update thread actor on window-ready)
if (!isTopLevel) {
return;
@ -1371,7 +1382,7 @@ const tabPrototype = {
/**
* Notify server and client about a new document done loading in the current
* targeted context.
* targeted browsing context.
*/
_navigate(window, isFrameSwitching = false) {
const isTopLevel = window == this.window;
@ -1385,7 +1396,7 @@ const tabPrototype = {
isTopLevel: isTopLevel
});
// We don't do anything for inner frames in TabActor.
// We don't do anything for inner frames here.
// (we will only update thread actor on window-ready)
if (!isTopLevel) {
return;
@ -1464,20 +1475,21 @@ const tabPrototype = {
},
};
exports.tabPrototype = tabPrototype;
exports.TabActor = ActorClassWithSpec(tabSpec, tabPrototype);
exports.browsingContextTargetPrototype = browsingContextTargetPrototype;
exports.BrowsingContextTargetActor =
ActorClassWithSpec(browsingContextTargetSpec, browsingContextTargetPrototype);
/**
* The DebuggerProgressListener object is an nsIWebProgressListener which
* handles onStateChange events for the inspected browser. If the user tries to
* navigate away from a paused page, the listener makes sure that the debuggee
* is resumed before the navigation begins.
* handles onStateChange events for the targeted browsing context. If the user
* tries to navigate away from a paused page, the listener makes sure that the
* debuggee is resumed before the navigation begins.
*
* @param TabActor aTabActor
* The tab actor associated with this listener.
* @param BrowsingContextTargetActor targetActor
* The browsing context target actor associated with this listener.
*/
function DebuggerProgressListener(tabActor) {
this._tabActor = tabActor;
function DebuggerProgressListener(targetActor) {
this._targetActor = targetActor;
this._onWindowCreated = this.onWindowCreated.bind(this);
this._onWindowHidden = this.onWindowHidden.bind(this);
@ -1523,9 +1535,9 @@ DebuggerProgressListener.prototype = {
handler.addEventListener("pageshow", this._onWindowCreated, true);
handler.addEventListener("pagehide", this._onWindowHidden, true);
// Dispatch the _windowReady event on the tabActor for pre-existing windows
// Dispatch the _windowReady event on the targetActor for pre-existing windows
for (const win of this._getWindowsInDocShell(docShell)) {
this._tabActor._windowReady(win);
this._targetActor._windowReady(win);
this._knownWindowIDs.set(getWindowID(win), win);
}
},
@ -1565,7 +1577,7 @@ DebuggerProgressListener.prototype = {
},
onWindowCreated: DevToolsUtils.makeInfallible(function(evt) {
if (!this._tabActor.attached) {
if (!this._targetActor.attached) {
return;
}
@ -1589,13 +1601,13 @@ DebuggerProgressListener.prototype = {
return;
}
this._tabActor._windowReady(window);
this._targetActor._windowReady(window);
this._knownWindowIDs.set(innerID, window);
}, "DebuggerProgressListener.prototype.onWindowCreated"),
onWindowHidden: DevToolsUtils.makeInfallible(function(evt) {
if (!this._tabActor.attached) {
if (!this._targetActor.attached) {
return;
}
@ -1614,12 +1626,12 @@ DebuggerProgressListener.prototype = {
}
const window = evt.target.defaultView;
this._tabActor._windowDestroyed(window, null, true);
this._targetActor._windowDestroyed(window, null, true);
this._knownWindowIDs.delete(getWindowID(window));
}, "DebuggerProgressListener.prototype.onWindowHidden"),
observe: DevToolsUtils.makeInfallible(function(subject, topic) {
if (!this._tabActor.attached) {
if (!this._targetActor.attached) {
return;
}
@ -1630,13 +1642,13 @@ DebuggerProgressListener.prototype = {
const window = this._knownWindowIDs.get(innerID);
if (window) {
this._knownWindowIDs.delete(innerID);
this._tabActor._windowDestroyed(window, innerID);
this._targetActor._windowDestroyed(window, innerID);
}
}, "DebuggerProgressListener.prototype.observe"),
onStateChange:
DevToolsUtils.makeInfallible(function(progress, request, flag, status) {
if (!this._tabActor.attached) {
if (!this._targetActor.attached) {
return;
}
@ -1649,7 +1661,7 @@ DebuggerProgressListener.prototype = {
if (isDocument && isStop) {
// Watch document stop to ensure having the new iframe url.
progress.QueryInterface(Ci.nsIDocShell);
this._tabActor._notifyDocShellsUpdate([progress]);
this._targetActor._notifyDocShellsUpdate([progress]);
}
const window = progress.DOMWindow;
@ -1657,7 +1669,7 @@ DebuggerProgressListener.prototype = {
// One of the earliest events that tells us a new URI
// is being loaded in this window.
const newURI = request instanceof Ci.nsIChannel ? request.URI.spec : null;
this._tabActor._willNavigate(window, newURI, request);
this._targetActor._willNavigate(window, newURI, request);
}
if (isWindow && isStop) {
// Don't dispatch "navigate" event just yet when there is a redirect to
@ -1676,14 +1688,14 @@ DebuggerProgressListener.prototype = {
// Ignore events from iframes
if (evt.target === window.document) {
handler.removeEventListener("DOMContentLoaded", onLoad, true);
this._tabActor._navigate(window);
this._targetActor._navigate(window);
}
};
handler.addEventListener("DOMContentLoaded", onLoad, true);
} else {
// Somewhat equivalent of load event.
// (window.document.readyState == complete)
this._tabActor._navigate(window);
this._targetActor._navigate(window);
}
}
}, "DebuggerProgressListener.prototype.onStateChange")

View File

@ -0,0 +1,9 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
DevToolsModules(
'browsing-context.js',
)

View File

@ -60,7 +60,7 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
this._dbg = null;
this._gripDepth = 0;
this._threadLifetimePool = null;
this._tabClosed = false;
this._parentClosed = false;
this._scripts = null;
this._pauseOnDOMEvents = null;
@ -392,10 +392,10 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
reportError(e, "Got an exception during TA__pauseAndRespond: ");
}
// If the browser tab has been closed, terminate the debuggee script
// If the parent actor has been closed, terminate the debuggee script
// instead of continuing. Executing JS after the content window is gone is
// a bad idea.
return this._tabClosed ? null : undefined;
return this._parentClosed ? null : undefined;
},
_makeOnEnterFrame: function({ pauseAndRespond }) {
@ -1598,7 +1598,7 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
/**
* A function called when there's a new source from a thread actor's sources.
* Emits `newSource` on the tab actor.
* Emits `newSource` on the target actor.
*
* @param {SourceActor} source
*/
@ -1621,7 +1621,7 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
/**
* A function called when there's an updated source from a thread actor' sources.
* Emits `updatedSource` on the tab actor.
* Emits `updatedSource` on the target actor.
*
* @param {SourceActor} source
*/

View File

@ -27,12 +27,12 @@ const { timelineSpec } = require("devtools/shared/specs/timeline");
*/
exports.TimelineActor = protocol.ActorClassWithSpec(timelineSpec, {
/**
* Initializes this actor with the provided connection and tab actor.
* Initializes this actor with the provided connection and target actor.
*/
initialize: function(conn, tabActor) {
initialize: function(conn, targetActor) {
protocol.Actor.prototype.initialize.call(this, conn);
this.tabActor = tabActor;
this.bridge = new Timeline(tabActor);
this.targetActor = targetActor;
this.bridge = new Timeline(targetActor);
this._onTimelineDocLoading = this._onTimelineDocLoading.bind(this);
this._onTimelineMarkers = this._onTimelineMarkers.bind(this);
@ -58,7 +58,7 @@ exports.TimelineActor = protocol.ActorClassWithSpec(timelineSpec, {
this.bridge.off("frames", this._onTimelineFrames);
this.bridge.destroy();
this.bridge = null;
this.tabActor = null;
this.targetActor = null;
protocol.Actor.prototype.destroy.call(this);
},

View File

@ -246,7 +246,7 @@ WalkerSearch.prototype = {
}
}
const documents = this.walker.tabActor.windows.map(win=>win.document);
const documents = this.walker.targetActor.windows.map(win=>win.document);
// Sort the resulting nodes by order of appearance in the DOM
resultList.sort((a, b) => {

View File

@ -402,9 +402,9 @@ var AudioNodeActor = exports.AudioNodeActor = protocol.ActorClassWithSpec(audion
* up by calling setup().
*/
exports.WebAudioActor = protocol.ActorClassWithSpec(webAudioSpec, {
initialize: function(conn, tabActor) {
initialize: function(conn, targetActor) {
protocol.Actor.prototype.initialize.call(this, conn);
this.tabActor = tabActor;
this.targetActor = targetActor;
this._onContentFunctionCall = this._onContentFunctionCall.bind(this);
@ -431,7 +431,7 @@ exports.WebAudioActor = protocol.ActorClassWithSpec(webAudioSpec, {
},
/**
* Starts waiting for the current tab actor's document global to be
* Starts waiting for the current target actor's document global to be
* created, in order to instrument the Canvas context and become
* aware of everything the content does with Web Audio.
*
@ -448,14 +448,14 @@ exports.WebAudioActor = protocol.ActorClassWithSpec(webAudioSpec, {
if (this._initialized) {
if (reload) {
this.tabActor.window.location.reload();
this.targetActor.window.location.reload();
}
return;
}
this._initialized = true;
this._callWatcher = new CallWatcherActor(this.conn, this.tabActor);
this._callWatcher = new CallWatcherActor(this.conn, this.targetActor);
this._callWatcher.onCall = this._onContentFunctionCall;
this._callWatcher.setup({
tracedGlobals: AUDIO_GLOBALS,
@ -466,10 +466,10 @@ exports.WebAudioActor = protocol.ActorClassWithSpec(webAudioSpec, {
});
// Bind to `window-ready` so we can reenable recording on the
// call watcher
this.tabActor.on("window-ready", this._onGlobalCreated);
this.targetActor.on("window-ready", this._onGlobalCreated);
// Bind to the `window-destroyed` event so we can unbind events between
// the global destruction and the `finalize` cleanup method on the actor.
this.tabActor.on("window-destroyed", this._onGlobalDestroyed);
this.targetActor.on("window-destroyed", this._onGlobalDestroyed);
},
/**
@ -562,9 +562,9 @@ exports.WebAudioActor = protocol.ActorClassWithSpec(webAudioSpec, {
// NS_ERROR_FAILURE errors with this silent try/catch.
}
this.tabActor.off("window-destroyed", this._onGlobalDestroyed);
this.tabActor.off("window-ready", this._onGlobalCreated);
this.tabActor = null;
this.targetActor.off("window-destroyed", this._onGlobalDestroyed);
this.targetActor.off("window-ready", this._onGlobalCreated);
this.targetActor = null;
this._nativeToActorID = null;
this._callWatcher.eraseRecording();
this._callWatcher.finalize();

View File

@ -264,7 +264,7 @@ WebConsoleActor.prototype =
/**
* Flag used to track if we are listening for events from the progress
* listener of the tab actor. We use the progress listener to clear
* listener of the target actor. We use the progress listener to clear
* this.evalWindow on page navigation.
*
* @private

View File

@ -93,7 +93,7 @@ function logAccessDeniedWarning(window, callerInfo, extensionPolicy) {
}
function CustomizedReload(params) {
this.docShell = params.tabActor.window
this.docShell = params.targetActor.window
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell);
this.docShell.QueryInterface(Ci.nsIWebProgress);
@ -263,9 +263,9 @@ var WebExtensionInspectedWindowActor = protocol.ActorClassWithSpec(
/**
* Created the WebExtension InspectedWindow actor
*/
initialize(conn, tabActor) {
initialize(conn, targetActor) {
protocol.Actor.prototype.initialize.call(this, conn);
this.tabActor = tabActor;
this.targetActor = targetActor;
},
destroy(conn) {
@ -289,16 +289,16 @@ var WebExtensionInspectedWindowActor = protocol.ActorClassWithSpec(
return this._dbg;
}
this._dbg = this.tabActor.makeDebugger();
this._dbg = this.targetActor.makeDebugger();
return this._dbg;
},
get window() {
return this.tabActor.window;
return this.targetActor.window;
},
get webNavigation() {
return this.tabActor.webNavigation;
return this.targetActor.webNavigation;
},
createEvalBindings(dbgWindow, options) {
@ -400,7 +400,7 @@ var WebExtensionInspectedWindowActor = protocol.ActorClassWithSpec(
try {
this.customizedReload = new CustomizedReload({
tabActor: this.tabActor,
targetActor: this.targetActor,
inspectedWindowEval: this.eval.bind(this),
callerInfo, injectedScript, userAgent, ignoreCache,
});
@ -443,8 +443,8 @@ var WebExtensionInspectedWindowActor = protocol.ActorClassWithSpec(
/**
* Evaluate the provided javascript code in a target window (that is always the
* tabActor window when called through RDP protocol, or the passed customTargetWindow
* when called directly from the CustomizedReload instances).
* targetActor window when called through RDP protocol, or the passed
* customTargetWindow when called directly from the CustomizedReload instances).
*
* @param {webExtensionCallerInfo} callerInfo
* the addonId and the url (the addon base url or the url of the actual caller
@ -468,7 +468,7 @@ var WebExtensionInspectedWindowActor = protocol.ActorClassWithSpec(
* javascript code in every sub-frame of the target window during the tab reload.
* NOTE: this parameter is not part of the RDP protocol exposed by this actor, when
* it is called over the remote debugging protocol the target window is always
* `tabActor.window`.
* `targetActor.window`.
*/
eval(callerInfo, expression, options, customTargetWindow) {
const window = customTargetWindow || this.window;

View File

@ -11,17 +11,18 @@ const Services = require("Services");
const { ChromeActor, chromePrototype } = require("./chrome");
const makeDebugger = require("./utils/make-debugger");
const { ActorClassWithSpec } = require("devtools/shared/protocol");
const { tabSpec } = require("devtools/shared/specs/tab");
const { browsingContextTargetSpec } = require("devtools/shared/specs/targets/browsing-context");
loader.lazyRequireGetter(this, "unwrapDebuggerObjectGlobal", "devtools/server/actors/thread", true);
loader.lazyRequireGetter(this, "ChromeUtils");
const FALLBACK_DOC_MESSAGE = "Your addon does not have any document opened yet.";
/**
* Creates a TabActor for debugging all the contexts associated to a target WebExtensions
* add-on running in a child extension process.
* Most of the implementation is inherited from ChromeActor (which inherits most of its
* implementation from TabActor).
* Creates a target actor for debugging all the contexts associated to a target
* WebExtensions add-on running in a child extension process. Most of the implementation
* is inherited from ChromeActor (which inherits most of its implementation from
* BrowsingContextTargetActor).
*
* WebExtensionChildActor is created by a WebExtensionParentActor counterpart, when its
* parent actor's `connect` method has been called (on the listAddons RDP package),
* it runs in the same process that the extension is running into (which can be the main
@ -29,20 +30,21 @@ const FALLBACK_DOC_MESSAGE = "Your addon does not have any document opened yet."
* if the extension is running in oop-mode).
*
* A WebExtensionChildActor contains all tab actors, like a regular ChromeActor
* or TabActor.
* or BrowsingContextTargetActor.
*
* History lecture:
* - The add-on actors used to not inherit TabActor because of the different way the
* add-on APIs where exposed to the add-on itself, and for this reason the Addon Debugger
* has only a sub-set of the feature available in the Tab or in the Browser Toolbox.
* - The add-on actors used to not inherit BrowsingContextTargetActor because of the
* different way the add-on APIs where exposed to the add-on itself, and for this reason
* the Addon Debugger has only a sub-set of the feature available in the Tab or in the
* Browser Toolbox.
* - In a WebExtensions add-on all the provided contexts (background, popups etc.),
* besides the Content Scripts which run in the content process, hooked to an existent
* tab, by creating a new WebExtensionActor which inherits from ChromeActor, we can
* provide a full features Addon Toolbox (which is basically like a BrowserToolbox which
* filters the visible sources and frames to the one that are related to the target
* add-on).
* besides the Content Scripts which run in the content process, hooked to an existent
* tab, by creating a new WebExtensionActor which inherits from ChromeActor, we can
* provide a full features Addon Toolbox (which is basically like a BrowserToolbox which
* filters the visible sources and frames to the one that are related to the target
* add-on).
* - When the WebExtensions OOP mode has been introduced, this actor has been refactored
* and moved from the main process to the new child extension process.
* and moved from the main process to the new child extension process.
*
* @param {DebuggerServerConnection} conn
* The connection to the client.
@ -76,7 +78,7 @@ webExtensionChildPrototype.initialize = function(conn, chromeGlobal, prefix, add
});
// Bind the _allowSource helper to this, it is used in the
// TabActor to lazily create the TabSources instance.
// BrowsingContextTargetActor to lazily create the TabSources instance.
this._allowSource = this._allowSource.bind(this);
this._onParentExit = this._onParentExit.bind(this);
@ -186,7 +188,7 @@ webExtensionChildPrototype._searchForExtensionWindow = function() {
return undefined;
};
// Customized ChromeActor/TabActor hooks.
// Customized ChromeActor/BrowsingContextTargetActor hooks.
webExtensionChildPrototype._onDocShellDestroy = function(docShell) {
// Stop watching this docshell (the unwatch() method will check if we
@ -215,7 +217,7 @@ webExtensionChildPrototype._onNewExtensionWindow = function(window) {
webExtensionChildPrototype._attach = function() {
// NOTE: we need to be sure that `this.window` can return a
// window before calling the ChromeActor.onAttach, or the TabActor
// window before calling the ChromeActor.onAttach, or the BrowsingContextTargetActor
// will not be subscribed to the child doc shell updates.
if (!this.window || this.window.document.nodePrincipal.addonId !== this.id) {
@ -395,4 +397,5 @@ webExtensionChildPrototype._onParentExit = function(msg) {
this.exit();
};
exports.WebExtensionChildActor = ActorClassWithSpec(tabSpec, webExtensionChildPrototype);
exports.WebExtensionChildActor =
ActorClassWithSpec(browsingContextTargetSpec, webExtensionChildPrototype);

View File

@ -186,9 +186,9 @@ var ProgramActor = protocol.ActorClassWithSpec(programSpec, {
* up by calling setup().
*/
exports.WebGLActor = protocol.ActorClassWithSpec(webGLSpec, {
initialize: function(conn, tabActor) {
initialize: function(conn, targetActor) {
protocol.Actor.prototype.initialize.call(this, conn);
this.tabActor = tabActor;
this.targetActor = targetActor;
this._onGlobalCreated = this._onGlobalCreated.bind(this);
this._onGlobalDestroyed = this._onGlobalDestroyed.bind(this);
this._onProgramLinked = this._onProgramLinked.bind(this);
@ -199,7 +199,7 @@ exports.WebGLActor = protocol.ActorClassWithSpec(webGLSpec, {
},
/**
* Starts waiting for the current tab actor's document global to be
* Starts waiting for the current target actor's document global to be
* created, in order to instrument the Canvas context and become
* aware of everything the content does WebGL-wise.
*
@ -214,12 +214,12 @@ exports.WebGLActor = protocol.ActorClassWithSpec(webGLSpec, {
this._programActorsCache = [];
this._webglObserver = new WebGLObserver();
this.tabActor.on("window-ready", this._onGlobalCreated);
this.tabActor.on("window-destroyed", this._onGlobalDestroyed);
this.targetActor.on("window-ready", this._onGlobalCreated);
this.targetActor.on("window-destroyed", this._onGlobalDestroyed);
EventEmitter.on(this._webglObserver, "program-linked", this._onProgramLinked);
if (reload) {
this.tabActor.window.location.reload();
this.targetActor.window.location.reload();
}
},
@ -234,8 +234,8 @@ exports.WebGLActor = protocol.ActorClassWithSpec(webGLSpec, {
}
this._initialized = false;
this.tabActor.off("window-ready", this._onGlobalCreated);
this.tabActor.off("window-destroyed", this._onGlobalDestroyed);
this.targetActor.off("window-ready", this._onGlobalCreated);
this.targetActor.off("window-destroyed", this._onGlobalDestroyed);
EventEmitter.off(this._webglObserver, "program-linked", this._onProgramLinked);
this._programActorsCache = null;
@ -244,21 +244,21 @@ exports.WebGLActor = protocol.ActorClassWithSpec(webGLSpec, {
},
/**
* Gets an array of cached program actors for the current tab actor's window.
* Gets an array of cached program actors for the current target actor's window.
* This is useful for dealing with bfcache, when no new programs are linked.
*/
getPrograms: function() {
const id = ContentObserver.GetInnerWindowID(this.tabActor.window);
const id = ContentObserver.GetInnerWindowID(this.targetActor.window);
return this._programActorsCache.filter(e => e.ownerWindow == id);
},
/**
* Waits for one frame via `requestAnimationFrame` on the tab actor's window.
* Waits for one frame via `requestAnimationFrame` on the target actor's window.
* Used in tests.
*/
waitForFrame: function() {
const deferred = defer();
this.tabActor.window.requestAnimationFrame(deferred.resolve);
this.targetActor.window.requestAnimationFrame(deferred.resolve);
return deferred.promise;
},
@ -277,12 +277,12 @@ exports.WebGLActor = protocol.ActorClassWithSpec(webGLSpec, {
*/
getPixel: function({ selector, position }) {
const { x, y } = position;
const canvas = this.tabActor.window.document.querySelector(selector);
const canvas = this.targetActor.window.document.querySelector(selector);
const context = XPCNativeWrapper.unwrap(canvas.getContext("webgl"));
const { proxy } = this._webglObserver.for(context);
const height = canvas.height;
let buffer = new this.tabActor.window.Uint8Array(4);
let buffer = new this.targetActor.window.Uint8Array(4);
buffer = XPCNativeWrapper.unwrap(buffer);
proxy.readPixels(
@ -301,7 +301,7 @@ exports.WebGLActor = protocol.ActorClassWithSpec(webGLSpec, {
},
/**
* Invoked whenever the current tab actor's document global is created.
* Invoked whenever the current target actor's document global is created.
*/
_onGlobalCreated: function({id, window, isTopLevel}) {
if (isTopLevel) {
@ -311,7 +311,7 @@ exports.WebGLActor = protocol.ActorClassWithSpec(webGLSpec, {
},
/**
* Invoked whenever the current tab actor's inner window is destroyed.
* Invoked whenever the current target actor's inner window is destroyed.
*/
_onGlobalDestroyed: function({id, isTopLevel, isFrozen}) {
if (isTopLevel && !isFrozen) {

View File

@ -6,11 +6,14 @@
const { Ci } = require("chrome");
const Services = require("Services");
const { TabActor, tabPrototype } = require("./tab");
const {
BrowsingContextTargetActor,
browsingContextTargetPrototype
} = require("devtools/server/actors/targets/browsing-context");
const { extend } = require("devtools/shared/extend");
const { ActorClassWithSpec } = require("devtools/shared/protocol");
const { tabSpec } = require("devtools/shared/specs/tab");
const { browsingContextTargetSpec } = require("devtools/shared/specs/targets/browsing-context");
/**
* Creates a WindowActor for debugging a single window, like a browser window in Firefox,
@ -18,15 +21,14 @@ const { tabSpec } = require("devtools/shared/specs/tab");
* process only because the root actor's `onGetWindow` doesn't try to cross process
* boundaries.) Both chrome and content windows are supported.
*
* Most of the implementation is inherited from TabActor. WindowActor exposes all tab
* actors via its form() request, like TabActor.
* Most of the implementation is inherited from BrowsingContextTargetActor. WindowActor
* exposes all tab actors via its form() request, like BrowsingContextTargetActor.
*
* You can request a specific window's actor via RootActor.getWindow().
*
* Caveat: 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 TabActor.prototype
* Caveat: 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 BrowsingContextTargetActor.prototype
*
* @param connection DebuggerServerConnection
* The connection to the client.
@ -34,10 +36,10 @@ const { tabSpec } = require("devtools/shared/specs/tab");
* The window.
*/
const windowPrototype = extend({}, tabPrototype);
const windowPrototype = extend({}, browsingContextTargetPrototype);
windowPrototype.initialize = function(connection, window) {
TabActor.prototype.initialize.call(this, connection);
BrowsingContextTargetActor.prototype.initialize.call(this, connection);
const docShell = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell);
@ -52,7 +54,7 @@ windowPrototype.initialize = function(connection, window) {
windowPrototype.isRootActor = true;
windowPrototype.observe = function(subject, topic, data) {
TabActor.prototype.observe.call(this, subject, topic, data);
BrowsingContextTargetActor.prototype.observe.call(this, subject, topic, data);
if (!this.attached) {
return;
}
@ -66,7 +68,7 @@ windowPrototype._attach = function() {
return false;
}
TabActor.prototype._attach.call(this);
BrowsingContextTargetActor.prototype._attach.call(this);
// Listen for chrome docshells in addition to content docshells
if (this.docShell.itemType == Ci.nsIDocShellTreeItem.typeChrome) {
@ -85,9 +87,9 @@ windowPrototype._detach = function() {
Services.obs.removeObserver(this, "chrome-webnavigation-destroy");
}
TabActor.prototype._detach.call(this);
BrowsingContextTargetActor.prototype._detach.call(this);
return true;
};
exports.WindowActor = ActorClassWithSpec(tabSpec, windowPrototype);
exports.WindowActor = ActorClassWithSpec(browsingContextTargetSpec, windowPrototype);

View File

@ -974,12 +974,10 @@ var DebuggerServer = {
* @param Element frame
* The frame element with remote content to connect to.
* @param function [onDestroy]
* Optional function to invoke when the child process closes
* or the connection shuts down. (Need to forget about the
* related TabActor)
* Optional function to invoke when the child process closes or the connection
* shuts down. (Need to forget about the related target actor.)
* @return object
* A promise object that is resolved once the connection is
* established.
* A promise object that is resolved once the connection is established.
*/
connectToFrame(connection, frame, onDestroy, {addonId} = {}) {
return new Promise(resolve => {

View File

@ -4,21 +4,21 @@
"use strict";
/**
* A very simple utility for monitoring framerate. Takes a `tabActor`
* A very simple utility for monitoring framerate. Takes a `targetActor`
* and monitors framerate over time. The actor wrapper around this
* can be found at devtools/server/actors/framerate.js
*/
class Framerate {
constructor(tabActor) {
this.tabActor = tabActor;
this._contentWin = tabActor.window;
constructor(targetActor) {
this.targetActor = targetActor;
this._contentWin = targetActor.window;
this._onRefreshDriverTick = this._onRefreshDriverTick.bind(this);
this._onGlobalCreated = this._onGlobalCreated.bind(this);
this.tabActor.on("window-ready", this._onGlobalCreated);
this.targetActor.on("window-ready", this._onGlobalCreated);
}
destroy(conn) {
this.tabActor.off("window-ready", this._onGlobalCreated);
this.targetActor.off("window-ready", this._onGlobalCreated);
this.stopRecording();
}
@ -31,7 +31,7 @@ class Framerate {
}
this._recording = true;
this._ticks = [];
this._startTime = this.tabActor.docShell.now();
this._startTime = this.targetActor.docShell.now();
this._rafID = this._contentWin.requestAnimationFrame(this._onRefreshDriverTick);
}
@ -82,11 +82,11 @@ class Framerate {
return;
}
this._rafID = this._contentWin.requestAnimationFrame(this._onRefreshDriverTick);
this._ticks.push(this.tabActor.docShell.now() - this._startTime);
this._ticks.push(this.targetActor.docShell.now() - this._startTime);
}
/**
* When the content window for the tab actor is created.
* When the content window for the target actor is created.
*/
_onGlobalCreated(win) {
if (this._recording) {

View File

@ -39,11 +39,11 @@ const DRAIN_ALLOCATIONS_TIMEOUT = 2000;
* @param Target target
* The target owning this connection.
*/
function PerformanceRecorder(conn, tabActor) {
function PerformanceRecorder(conn, targetActor) {
EventEmitter.decorate(this);
this.conn = conn;
this.tabActor = tabActor;
this.targetActor = targetActor;
this._pendingConsoleRecordings = [];
this._recordings = [];
@ -100,9 +100,9 @@ PerformanceRecorder.prototype = {
* found in ./actors.js.
*/
_connectComponents: function() {
this._profiler = new Profiler(this.tabActor);
this._memory = new Memory(this.tabActor);
this._timeline = new Timeline(this.tabActor);
this._profiler = new Profiler(this.targetActor);
this._memory = new Memory(this.targetActor);
this._timeline = new Timeline(this.targetActor);
this._profiler.registerEventNotifications({ events: PROFILER_EVENTS });
},

View File

@ -37,10 +37,10 @@ const DEFAULT_TIMELINE_DATA_PULL_TIMEOUT = 200;
/**
* The timeline actor pops and forwards timeline markers registered in docshells.
*/
function Timeline(tabActor) {
function Timeline(targetActor) {
EventEmitter.decorate(this);
this.tabActor = tabActor;
this.targetActor = targetActor;
this._isRecording = false;
this._stackFrames = null;
@ -50,7 +50,7 @@ function Timeline(tabActor) {
// Make sure to get markers from new windows as they become available
this._onWindowReady = this._onWindowReady.bind(this);
this._onGarbageCollection = this._onGarbageCollection.bind(this);
this.tabActor.on("window-ready", this._onWindowReady);
this.targetActor.on("window-ready", this._onWindowReady);
}
Timeline.prototype = {
@ -60,16 +60,16 @@ Timeline.prototype = {
destroy: function() {
this.stop();
this.tabActor.off("window-ready", this._onWindowReady);
this.tabActor = null;
this.targetActor.off("window-ready", this._onWindowReady);
this.targetActor = null;
},
/**
* Get the list of docShells in the currently attached tabActor. Note that we
* always list the docShells included in the real root docShell, even if the
* tabActor was switched to a child frame. This is because for now, paint
* markers are only recorded at parent frame level so switching the timeline
* to a child frame would hide all paint markers.
* Get the list of docShells in the currently attached targetActor. Note that
* we always list the docShells included in the real root docShell, even if
* the targetActor was switched to a child frame. This is because for now,
* paint markers are only recorded at parent frame level so switching the
* timeline to a child frame would hide all paint markers.
* See https://bugzilla.mozilla.org/show_bug.cgi?id=1050773#c14
* @return {Array}
*/
@ -77,10 +77,10 @@ Timeline.prototype = {
let originalDocShell;
const docShells = [];
if (this.tabActor.isRootActor) {
originalDocShell = this.tabActor.docShell;
if (this.targetActor.isRootActor) {
originalDocShell = this.targetActor.docShell;
} else {
originalDocShell = this.tabActor.originalDocShell;
originalDocShell = this.targetActor.originalDocShell;
}
if (!originalDocShell) {
@ -236,12 +236,12 @@ Timeline.prototype = {
}
if (this._withTicks) {
this._framerate = new Framerate(this.tabActor);
this._framerate = new Framerate(this.targetActor);
this._framerate.startRecording();
}
if (this._withMemory || this._withGCEvents) {
this._memory = new Memory(this.tabActor, this._stackFrames);
this._memory = new Memory(this.targetActor, this._stackFrames);
this._memory.attach();
}
@ -310,7 +310,7 @@ Timeline.prototype = {
},
/**
* When a new window becomes available in the tabActor, start recording its
* When a new window becomes available in the targetActor, start recording its
* markers if we were recording.
*/
_onWindowReady: function({ window }) {

View File

@ -132,15 +132,15 @@ add_task(async function() {
const EventEmitter = require("devtools/shared/event-emitter");
// !Hack! Retrieve a server side object, the BrowserTabActor instance
const tabActor = DebuggerServer.searchAllConnectionsForActor(actorId);
const targetActor = DebuggerServer.searchAllConnectionsForActor(actorId);
// In order to listen to internal will-navigate/navigate events
EventEmitter.on(tabActor, "will-navigate", function(data) {
EventEmitter.on(targetActor, "will-navigate", function(data) {
sendSyncMessage("devtools-test:event", {
event: "will-navigate",
data: { newURI: data.newURI }
});
});
EventEmitter.on(tabActor, "navigate", function(data) {
EventEmitter.on(targetActor, "navigate", function(data) {
sendSyncMessage("devtools-test:event", {
event: "navigate",
data: { readyState: content.document.readyState }

View File

@ -139,9 +139,10 @@ function waitUntilClientConnected(client) {
/**
* Connect a debugger client.
*
* @param {DebuggerClient}
* @return {Promise} Resolves to the selected tabActor form when the client is
* connected.
* @return {Promise} Resolves to the targetActor form for the selected tab when the client
* is connected.
*/
function connectDebuggerClient(client) {
return client.connect()
@ -190,20 +191,6 @@ function forceCollections() {
Cu.forceShrinkingGC();
}
/**
* Get a mock tabActor from a given window.
* This is sometimes useful to test actors or classes that use the tabActor in
* isolation.
* @param {DOMWindow} win
* @return {Object}
*/
function getMockTabActor(win) {
return {
window: win,
isRootActor: true
};
}
registerCleanupFunction(function tearDown() {
Services.cookies.removeAll();

View File

@ -106,6 +106,6 @@ support-files =
[test_unsafeDereference.html]
[test_webconsole-node-grip.html]
[test_webextension-addon-debugging-connect.html]
skip-if = !e10s # test is designed to work on e10s only
disabled = true # Bug 1467313: broken, needs repair or removal
[test_webextension-addon-debugging-reload.html]
skip-if = !e10s # test is designed to work on e10s only
disabled = true # Bug 1467313: broken, needs repair or removal

View File

@ -82,7 +82,7 @@ function runTests() {
ok(actor.testActor, "Got the test actor");
// Ensure sending at least one request to our actor,
// otherwise it won't be instanciated, nor be destroyed...
// otherwise it won't be instantiated, nor be destroyed...
client.request({
to: actor.testActor,
type: "hello",

View File

@ -60,7 +60,7 @@ addTest(function() {
addTest(function() {
info("Try to get a NodeFront from a valid actorID and valid complex path");
gWalker.getNodeFromActor(gWalker.actorID,
["tabActor", "window", "document", "body"]).then(bodyNode => {
["targetActor", "window", "document", "body"]).then(bodyNode => {
ok(bodyNode, "A node was returned");
gWalker.querySelector(gWalker.rootNode, "body").then(node => {
is(bodyNode, node, "The body node was returned");

View File

@ -45,7 +45,7 @@ async function test_connect_addon(oopMode) {
form: addonActor,
client,
chrome: true,
isTabActor: true,
isBrowsingContext: true,
});
is(addonTarget.form.isOOP, oopMode,
"Got the expected oop mode in the webextension actor form");

View File

@ -110,7 +110,7 @@ async function attachAddon(addonId) {
form: addonActor,
client,
chrome: true,
isTabActor: true,
isBrowsingContext: true,
});
return addonTarget;

View File

@ -424,8 +424,8 @@ function finishClient(client) {
});
}
// Create a server, connect to it and fetch tab actors for the parent process;
// pass |callback| the debugger client and tab actor form with all actor IDs.
// Create a server, connect to it and fetch target actors for the parent process;
// pass |callback| the debugger client and target actor form with all actor IDs.
function get_chrome_actors(callback) {
DebuggerServer.init();
DebuggerServer.registerAllActors();

View File

@ -35,11 +35,11 @@ function run_test() {
do_test_pending();
}
// Attach to |tabActor|, and check the response.
function test_attach_tab(tabActor) {
gClient.request({ to: tabActor, type: "attach" }, function(response) {
// Attach to |targetActor|, and check the response.
function test_attach_tab(targetActor) {
gClient.request({ to: targetActor, type: "attach" }, function(response) {
Assert.equal(false, "error" in response);
Assert.equal(response.from, tabActor);
Assert.equal(response.from, targetActor);
Assert.equal(response.type, "tabAttached");
Assert.ok(typeof response.threadActor === "string");

View File

@ -21,18 +21,25 @@ const EventEmitter = require("devtools/shared/event-emitter");
LayoutChangesObserver.prototype._setTimeout = cb => cb;
LayoutChangesObserver.prototype._clearTimeout = function() {};
// Mock the tabActor since we only really want to test the LayoutChangesObserver
// Mock the targetActor since we only really want to test the LayoutChangesObserver
// and don't want to depend on a window object, nor want to test protocol.js
class MockTabActor extends EventEmitter {
class MockTargetActor extends EventEmitter {
constructor() {
super();
this.window = new MockWindow();
this.docShell = new MockDocShell();
this.window = new MockWindow(this.docShell);
this.windows = [this.window];
this.attached = true;
}
get chromeEventHandler() {
return this.docShell.chromeEventHandler;
}
}
function MockWindow() {}
function MockWindow(docShell) {
this.docShell = docShell;
}
MockWindow.prototype = {
QueryInterface: function() {
const self = this;
@ -40,9 +47,6 @@ MockWindow.prototype = {
getInterface: function() {
return {
QueryInterface: function() {
if (!self.docShell) {
self.docShell = new MockDocShell();
}
return self.docShell;
}
};
@ -99,39 +103,38 @@ function run_test() {
function instancesOfObserversAreSharedBetweenWindows() {
info("Checking that when requesting twice an instances of the observer " +
"for the same TabActor, the instance is shared");
"for the same BrowsingContextTargetActor, the instance is shared");
info("Checking 2 instances of the observer for the tabActor 1");
const tabActor1 = new MockTabActor();
const obs11 = getLayoutChangesObserver(tabActor1);
const obs12 = getLayoutChangesObserver(tabActor1);
info("Checking 2 instances of the observer for the targetActor 1");
const targetActor1 = new MockTargetActor();
const obs11 = getLayoutChangesObserver(targetActor1);
const obs12 = getLayoutChangesObserver(targetActor1);
Assert.equal(obs11, obs12);
info("Checking 2 instances of the observer for the tabActor 2");
const tabActor2 = new MockTabActor();
const obs21 = getLayoutChangesObserver(tabActor2);
const obs22 = getLayoutChangesObserver(tabActor2);
info("Checking 2 instances of the observer for the targetActor 2");
const targetActor2 = new MockTargetActor();
const obs21 = getLayoutChangesObserver(targetActor2);
const obs22 = getLayoutChangesObserver(targetActor2);
Assert.equal(obs21, obs22);
info("Checking that observers instances for 2 different tabActors are " +
info("Checking that observers instances for 2 different targetActors are " +
"different");
Assert.notEqual(obs11, obs21);
releaseLayoutChangesObserver(tabActor1);
releaseLayoutChangesObserver(tabActor1);
releaseLayoutChangesObserver(tabActor2);
releaseLayoutChangesObserver(tabActor2);
releaseLayoutChangesObserver(targetActor1);
releaseLayoutChangesObserver(targetActor1);
releaseLayoutChangesObserver(targetActor2);
releaseLayoutChangesObserver(targetActor2);
}
function eventsAreBatched() {
info("Checking that reflow events are batched and only sent when the " +
"timeout expires");
// Note that in this test, we mock the TabActor and its window property, so we
// also mock the setTimeout/clearTimeout mechanism and just call the callback
// manually
const tabActor = new MockTabActor();
const observer = getLayoutChangesObserver(tabActor);
// Note that in this test, we mock the target actor and its window property, so we also
// mock the setTimeout/clearTimeout mechanism and just call the callback manually
const targetActor = new MockTargetActor();
const observer = getLayoutChangesObserver(targetActor);
const reflowsEvents = [];
const onReflows = reflows => reflowsEvents.push(reflows);
@ -142,19 +145,19 @@ function eventsAreBatched() {
observer.on("resize", onResize);
info("Fake one reflow event");
tabActor.window.docShell.observer.reflow();
targetActor.window.docShell.observer.reflow();
info("Checking that no batched reflow event has been emitted");
Assert.equal(reflowsEvents.length, 0);
info("Fake another reflow event");
tabActor.window.docShell.observer.reflow();
targetActor.window.docShell.observer.reflow();
info("Checking that still no batched reflow event has been emitted");
Assert.equal(reflowsEvents.length, 0);
info("Fake a few of resize events too");
tabActor.window.docShell.mockResize();
tabActor.window.docShell.mockResize();
tabActor.window.docShell.mockResize();
targetActor.window.docShell.mockResize();
targetActor.window.docShell.mockResize();
targetActor.window.docShell.mockResize();
info("Checking that still no batched resize event has been emitted");
Assert.equal(resizeEvents.length, 0);
@ -166,15 +169,15 @@ function eventsAreBatched() {
observer.off("reflows", onReflows);
observer.off("resize", onResize);
releaseLayoutChangesObserver(tabActor);
releaseLayoutChangesObserver(targetActor);
}
function noEventsAreSentWhenThereAreNoReflowsAndLoopTimeouts() {
info("Checking that if no reflows were detected and the event batching " +
"loop expires, then no reflows event is sent");
const tabActor = new MockTabActor();
const observer = getLayoutChangesObserver(tabActor);
const targetActor = new MockTargetActor();
const observer = getLayoutChangesObserver(targetActor);
const reflowsEvents = [];
const onReflows = (reflows) => reflowsEvents.push(reflows);
@ -185,14 +188,14 @@ function noEventsAreSentWhenThereAreNoReflowsAndLoopTimeouts() {
Assert.equal(reflowsEvents.length, 0);
observer.off("reflows", onReflows);
releaseLayoutChangesObserver(tabActor);
releaseLayoutChangesObserver(targetActor);
}
function observerIsAlreadyStarted() {
info("Checking that the observer is already started when getting it");
const tabActor = new MockTabActor();
const observer = getLayoutChangesObserver(tabActor);
const targetActor = new MockTargetActor();
const observer = getLayoutChangesObserver(targetActor);
Assert.ok(observer.isObserving);
observer.stop();
@ -201,28 +204,28 @@ function observerIsAlreadyStarted() {
observer.start();
Assert.ok(observer.isObserving);
releaseLayoutChangesObserver(tabActor);
releaseLayoutChangesObserver(targetActor);
}
function destroyStopsObserving() {
info("Checking that the destroying the observer stops it");
const tabActor = new MockTabActor();
const observer = getLayoutChangesObserver(tabActor);
const targetActor = new MockTargetActor();
const observer = getLayoutChangesObserver(targetActor);
Assert.ok(observer.isObserving);
observer.destroy();
Assert.ok(!observer.isObserving);
releaseLayoutChangesObserver(tabActor);
releaseLayoutChangesObserver(targetActor);
}
function stoppingAndStartingSeveralTimesWorksCorrectly() {
info("Checking that the stopping and starting several times the observer" +
" works correctly");
const tabActor = new MockTabActor();
const observer = getLayoutChangesObserver(tabActor);
const targetActor = new MockTargetActor();
const observer = getLayoutChangesObserver(targetActor);
Assert.ok(observer.isObserving);
observer.start();
@ -237,58 +240,58 @@ function stoppingAndStartingSeveralTimesWorksCorrectly() {
observer.stop();
Assert.ok(!observer.isObserving);
releaseLayoutChangesObserver(tabActor);
releaseLayoutChangesObserver(targetActor);
}
function reflowsArentStackedWhenStopped() {
info("Checking that when stopped, reflows aren't stacked in the observer");
const tabActor = new MockTabActor();
const observer = getLayoutChangesObserver(tabActor);
const targetActor = new MockTargetActor();
const observer = getLayoutChangesObserver(targetActor);
info("Stoping the observer");
observer.stop();
info("Faking reflows");
tabActor.window.docShell.observer.reflow();
tabActor.window.docShell.observer.reflow();
tabActor.window.docShell.observer.reflow();
targetActor.window.docShell.observer.reflow();
targetActor.window.docShell.observer.reflow();
targetActor.window.docShell.observer.reflow();
info("Checking that reflows aren't recorded");
Assert.equal(observer.reflows.length, 0);
info("Starting the observer and faking more reflows");
observer.start();
tabActor.window.docShell.observer.reflow();
tabActor.window.docShell.observer.reflow();
tabActor.window.docShell.observer.reflow();
targetActor.window.docShell.observer.reflow();
targetActor.window.docShell.observer.reflow();
targetActor.window.docShell.observer.reflow();
info("Checking that reflows are recorded");
Assert.equal(observer.reflows.length, 3);
releaseLayoutChangesObserver(tabActor);
releaseLayoutChangesObserver(targetActor);
}
function stackedReflowsAreResetOnStop() {
info("Checking that stacked reflows are reset on stop");
const tabActor = new MockTabActor();
const observer = getLayoutChangesObserver(tabActor);
const targetActor = new MockTargetActor();
const observer = getLayoutChangesObserver(targetActor);
tabActor.window.docShell.observer.reflow();
targetActor.window.docShell.observer.reflow();
Assert.equal(observer.reflows.length, 1);
observer.stop();
Assert.equal(observer.reflows.length, 0);
tabActor.window.docShell.observer.reflow();
targetActor.window.docShell.observer.reflow();
Assert.equal(observer.reflows.length, 0);
observer.start();
Assert.equal(observer.reflows.length, 0);
tabActor.window.docShell.observer.reflow();
targetActor.window.docShell.observer.reflow();
Assert.equal(observer.reflows.length, 1);
releaseLayoutChangesObserver(tabActor);
releaseLayoutChangesObserver(targetActor);
}

View File

@ -14,7 +14,7 @@ add_task(async function() {
const client = await startTestDebuggerServer("promises-actor-test");
const chromeActors = await getChromeActors(client);
// We have to attach the chrome TabActor before playing with the PromiseActor
// We have to attach the chrome target actor before playing with the PromiseActor
await attachTab(client, chromeActors);
await testAttach(client, chromeActors);

View File

@ -15,12 +15,12 @@ add_task(async function() {
const targetTab = findTab(response.tabs, "promises-actor-test");
Assert.ok(targetTab, "Found our target tab.");
// Attach to the TabActor and check the response
// Attach to the BrowsingContextTargetActor and check the response
await new Promise(resolve => {
client.request({ to: targetTab.actor, type: "attach" }, response => {
Assert.ok(!("error" in response), "Expect no error in response.");
Assert.equal(response.from, targetTab.actor,
"Expect the target TabActor in response form field.");
"Expect the target BrowsingContextTargetActor in response form field.");
Assert.equal(response.type, "tabAttached",
"Expect tabAttached in the response type.");
Assert.ok(typeof response.promisesActor === "string",

View File

@ -15,7 +15,7 @@ add_task(async function() {
const client = await startTestDebuggerServer("promises-actor-test");
const chromeActors = await getChromeActors(client);
// We have to attach the chrome TabActor before playing with the PromiseActor
// We have to attach the chrome target actor before playing with the PromiseActor
await attachTab(client, chromeActors);
await testListPromises(client, chromeActors, v =>
new Promise(resolve => resolve(v)));

View File

@ -18,7 +18,7 @@ add_task(async function() {
ok(Promise.toString().includes("native code"), "Expect native DOM Promise");
// We have to attach the chrome TabActor before playing with the PromiseActor
// We have to attach the chrome target actor before playing with the PromiseActor
await attachTab(client, chromeActors);
await testNewPromisesEvent(client, chromeActors,
v => new Promise(resolve => resolve(v)));

View File

@ -20,7 +20,7 @@ add_task(async function() {
ok(Promise.toString().includes("native code"), "Expect native DOM Promise");
// We have to attach the chrome TabActor before playing with the PromiseActor
// We have to attach the chrome target actor before playing with the PromiseActor
await attachTab(client, chromeActors);
await testPromisesSettled(client, chromeActors,
v => new Promise(resolve => resolve(v)),

View File

@ -27,7 +27,7 @@ add_task(async function() {
ok(Promise.toString().includes("native code"), "Expect native DOM Promise.");
// We have to attach the chrome TabActor before playing with the PromiseActor
// We have to attach the chrome target actor before playing with the PromiseActor
await attachTab(client, chromeActors);
await testPromiseCreationTimestamp(client, chromeActors, v => {
return new Promise(resolve => resolve(v));

View File

@ -18,7 +18,7 @@ add_task(async function() {
ok(Promise.toString().includes("native code"), "Expect native DOM Promise.");
// We have to attach the chrome TabActor before playing with the PromiseActor
// We have to attach the chrome target actor before playing with the PromiseActor
await attachTab(client, chromeActors);
await testGetTimeToSettle(client, chromeActors, () => {
const p = new Promise(() => {});

View File

@ -20,7 +20,7 @@ add_task(async function() {
ok(Promise.toString().includes("native code"), "Expect native DOM Promise.");
// We have to attach the chrome TabActor before playing with the PromiseActor
// We have to attach the chrome target actor before playing with the PromiseActor
await attachTab(client, chromeActors);
await testGetTimeToSettle(client, chromeActors,
v => new Promise(resolve => setTimeout(() => resolve(v), 100)));

View File

@ -51,12 +51,12 @@ function test_deprecated_api() {
// Bug 988237: Test the new lazy actor loading
function test_lazy_api() {
let isActorLoaded = false;
let isActorInstanciated = false;
let isActorInstantiated = false;
function onActorEvent(subject, topic, data) {
if (data == "loaded") {
isActorLoaded = true;
} else if (data == "instantiated") {
isActorInstanciated = true;
isActorInstantiated = true;
}
}
Services.obs.addObserver(onActorEvent, "actor");
@ -69,7 +69,7 @@ function test_lazy_api() {
Assert.ok(DebuggerServer.tabActorFactories.hasOwnProperty("lazyActor"));
Assert.ok(DebuggerServer.globalActorFactories.hasOwnProperty("lazyActor"));
Assert.ok(!isActorLoaded);
Assert.ok(!isActorInstanciated);
Assert.ok(!isActorInstantiated);
const client = new DebuggerClient(DebuggerServer.connectPipe());
client.connect().then(function onConnect() {
@ -79,7 +79,7 @@ function test_lazy_api() {
// On listTabs, the actor is still not loaded,
// but we can see its name in the list of available actors
Assert.ok(!isActorLoaded);
Assert.ok(!isActorInstanciated);
Assert.ok(!isActorInstantiated);
Assert.ok("lazyActor" in response);
const {LazyFront} = require("xpcshell-test/registertestactors-03");
@ -91,7 +91,7 @@ function test_lazy_api() {
// Finally, the actor is loaded on the first request being made to it
Assert.ok(isActorLoaded);
Assert.ok(isActorInstanciated);
Assert.ok(isActorInstantiated);
Services.obs.removeObserver(onActorEvent, "actor");
client.close().then(() => run_next_test());

View File

@ -327,17 +327,17 @@ DebuggerClient.prototype = {
},
/**
* Attach to a tab actor.
* Attach to a tab's target actor.
*
* @param string tabActor
* The actor ID for the tab to attach.
* @param string targetActor
* The target actor ID for the tab to attach.
* @param function onResponse
* Called with the response packet and a TabClient
* (which will be undefined on error).
*/
attachTab: function(tabActor, onResponse = noop) {
if (this._clients.has(tabActor)) {
const cachedTab = this._clients.get(tabActor);
attachTab: function(targetActor, onResponse = noop) {
if (this._clients.has(targetActor)) {
const cachedTab = this._clients.get(targetActor);
const cachedResponse = {
cacheDisabled: cachedTab.cacheDisabled,
javascriptEnabled: cachedTab.javascriptEnabled,
@ -348,7 +348,7 @@ DebuggerClient.prototype = {
}
const packet = {
to: tabActor,
to: targetActor,
type: "attach"
};
return this.request(packet).then(response => {

View File

@ -17,7 +17,7 @@ const {arg, DebuggerClient} = require("devtools/shared/client/debugger-client");
* The debugger client parent.
* @param grip Object
* A PropertyIteratorActor grip returned by the protocol via
* TabActor.enumProperties request.
* BrowsingContextTargetActor.enumProperties request.
*/
function PropertyIteratorClient(client, grip) {
this._grip = grip;

View File

@ -193,7 +193,7 @@ RootClient.prototype = {
},
/**
* Fetch the TabActor for the currently selected tab, or for a specific
* Fetch the target actor for the currently selected tab, or for a specific
* tab given as first parameter.
*
* @param [optional] object filter

View File

@ -14,7 +14,7 @@ const {arg, DebuggerClient} = require("devtools/shared/client/debugger-client");
* The debugger client parent.
* @param grip Object
* A SymbolIteratorActor grip returned by the protocol via
* TabActor.enumSymbols request.
* BrowsingContextTargetActor.enumSymbols request.
*/
function SymbolIteratorClient(client, grip) {
this._grip = grip;

View File

@ -13,8 +13,8 @@ const EventEmitter = require("devtools/shared/event-emitter");
* event sent immediately after a web content document window has been set up,
* but before any script code has been executed.
*/
function ContentObserver(tabActor) {
this._contentWindow = tabActor.window;
function ContentObserver(targetActor) {
this._contentWindow = targetActor.window;
this._onContentGlobalCreated = this._onContentGlobalCreated.bind(this);
this._onInnerWindowDestroyed = this._onInnerWindowDestroyed.bind(this);
this.startListening();

View File

@ -324,7 +324,7 @@ types.addActorType = function(name) {
const actorID = typeof (v) === "string" ? v : v.actor;
let front = ctx.conn.getActor(actorID);
if (!front) {
// If front isn't instanciated yet, create one.
// If front isn't instantiated yet, create one.
// Try lazy loading front if not already loaded.
// The front module will synchronously call `FrontClassWithSpec` and
@ -1249,7 +1249,7 @@ var Front = function(conn = null, form = null, detail = null, context = null) {
// protocol.js no longer uses this data in the constructor, only external
// uses do. External usage of manually-constructed fronts will be
// drastically reduced if we convert the root and tab actors to
// drastically reduced if we convert the root and target actors to
// protocol.js, in which case this can probably go away.
if (form) {
this.actorID = form.actor;

View File

@ -215,8 +215,8 @@ const Types = exports.__TypesForTests = [
front: null,
},
{
types: ["tab"],
spec: "devtools/shared/specs/tab",
types: ["browsingContextTarget"],
spec: "devtools/shared/specs/targets/browsing-context",
front: null,
},
{

View File

@ -4,6 +4,10 @@
# 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/.
DIRS += [
'targets',
]
DevToolsModules(
'accessibility.js',
'actor-registry.js',
@ -43,7 +47,6 @@ DevToolsModules(
'stylesheets.js',
'symbol-iterator.js',
'symbol.js',
'tab.js',
'timeline.js',
'webaudio.js',
'webconsole.js',

View File

@ -5,7 +5,7 @@
const {types, generateActorSpec, RetVal, Option} = require("devtools/shared/protocol");
types.addDictType("tab.attach", {
types.addDictType("browsingContextTarget.attach", {
type: "string",
threadActor: "number",
cacheDisabled: "boolean",
@ -13,53 +13,53 @@ types.addDictType("tab.attach", {
traits: "json"
});
types.addDictType("tab.detach", {
types.addDictType("browsingContextTarget.detach", {
error: "nullable:string",
type: "nullable:string"
});
types.addDictType("tab.switchtoframe", {
types.addDictType("browsingContextTarget.switchtoframe", {
error: "nullable:string",
message: "nullable:string"
});
types.addDictType("tab.listframes", {
frames: "array:tab.window"
types.addDictType("browsingContextTarget.listframes", {
frames: "array:browsingContextTarget.window"
});
types.addDictType("tab.window", {
types.addDictType("browsingContextTarget.window", {
id: "string",
parentID: "nullable:string",
url: "string",
title: "string"
});
types.addDictType("tab.workers", {
types.addDictType("browsingContextTarget.workers", {
error: "nullable:string"
});
types.addDictType("tab.reload", {
types.addDictType("browsingContextTarget.reload", {
force: "boolean"
});
types.addDictType("tab.reconfigure", {
types.addDictType("browsingContextTarget.reconfigure", {
javascriptEnabled: "nullable:boolean",
cacheDisabled: "nullable:boolean",
serviceWorkersTestingEnabled: "nullable:boolean",
performReload: "nullable:boolean"
});
const tabSpec = generateActorSpec({
typeName: "tab",
const browsingContextTargetSpec = generateActorSpec({
typeName: "browsingContextTarget",
methods: {
attach: {
request: {},
response: RetVal("tab.attach")
response: RetVal("browsingContextTarget.attach")
},
detach: {
request: {},
response: RetVal("tab.detach")
response: RetVal("browsingContextTarget.detach")
},
ensureCSSErrorReportingEnabled: {
request: {},
@ -71,7 +71,7 @@ const tabSpec = generateActorSpec({
},
reload: {
request: {
options: Option(0, "tab.reload"),
options: Option(0, "browsingContextTarget.reload"),
},
response: {}
},
@ -83,7 +83,7 @@ const tabSpec = generateActorSpec({
},
reconfigure: {
request: {
options: Option(0, "tab.reconfigure")
options: Option(0, "browsingContextTarget.reconfigure")
},
response: {}
},
@ -91,15 +91,15 @@ const tabSpec = generateActorSpec({
request: {
windowId: Option(0, "string")
},
response: RetVal("tab.switchtoframe")
response: RetVal("browsingContextTarget.switchtoframe")
},
listFrames: {
request: {},
response: RetVal("tab.listframes")
response: RetVal("browsingContextTarget.listframes")
},
listWorkers: {
request: {},
response: RetVal("tab.workers")
response: RetVal("browsingContextTarget.workers")
},
logInPage: {
request: {
@ -112,4 +112,4 @@ const tabSpec = generateActorSpec({
}
});
exports.tabSpec = tabSpec;
exports.browsingContextTargetSpec = browsingContextTargetSpec;

View File

@ -0,0 +1,9 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
DevToolsModules(
'browsing-context.js',
)

View File

@ -29,7 +29,7 @@ function test_index_is_alphabetically_sorted() {
function test_specs() {
for (const type of Types) {
for (const typeName of type.types) {
ok(getType(typeName), `${typeName} spec is defined`);
ok(!!getType(typeName), `${typeName} spec is defined`);
}
}
ok(true, "Specs are all accessible");
@ -43,7 +43,7 @@ function test_fronts() {
for (const typeName of item.types) {
lazyLoadFront(typeName);
const type = getType(typeName);
ok(type, `Front for ${typeName} has a spec`);
ok(!!type, `Front for ${typeName} has a spec`);
ok(type.frontClass, `${typeName} has a front correctly defined`);
}
}

View File

@ -1737,7 +1737,7 @@ NetworkMonitor.prototype = {
*
* @constructor
* @param number outerWindowID
* The outerWindowID of the TabActor's main window.
* The outerWindowID of the target actor's main window.
* @param nsIMessageManager messageManager
* The nsIMessageManager to use to communicate with the parent process.
* @param object DebuggerServerConnection