mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-12 04:45:45 +00:00
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:
parent
37ba0f60c9
commit
eaa4969e77
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -651,7 +651,7 @@ AddonDebugger.prototype = {
|
||||
form: addonActor,
|
||||
client: this.client,
|
||||
chrome: true,
|
||||
isTabActor: false
|
||||
isBrowsingContext: false
|
||||
};
|
||||
|
||||
let toolboxOptions = {
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -317,7 +317,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
|
||||
form: response.form,
|
||||
client: client,
|
||||
chrome: true,
|
||||
isTabActor: false
|
||||
isBrowsingContext: false
|
||||
};
|
||||
return TargetFactory.forRemoteTab(options);
|
||||
})
|
||||
|
@ -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 });
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
},
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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})
|
||||
|
@ -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 }
|
||||
);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 &&
|
||||
|
@ -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;
|
||||
},
|
||||
```
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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 = {
|
||||
|
@ -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();
|
||||
}
|
||||
});
|
||||
|
@ -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);
|
||||
|
||||
/**
|
||||
|
@ -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" });
|
||||
}
|
||||
|
@ -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()) {
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
},
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
@ -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().
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
},
|
||||
|
||||
|
@ -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',
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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")
|
9
devtools/server/actors/targets/moz.build
Normal file
9
devtools/server/actors/targets/moz.build
Normal 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',
|
||||
)
|
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
},
|
||||
|
||||
|
@ -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) => {
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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 => {
|
||||
|
@ -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) {
|
||||
|
@ -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 });
|
||||
},
|
||||
|
||||
|
@ -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 }) {
|
||||
|
@ -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 }
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -110,7 +110,7 @@ async function attachAddon(addonId) {
|
||||
form: addonActor,
|
||||
client,
|
||||
chrome: true,
|
||||
isTabActor: true,
|
||||
isBrowsingContext: true,
|
||||
});
|
||||
|
||||
return addonTarget;
|
||||
|
@ -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();
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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)));
|
||||
|
@ -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)));
|
||||
|
@ -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)),
|
||||
|
@ -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));
|
||||
|
@ -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(() => {});
|
||||
|
@ -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)));
|
||||
|
@ -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());
|
||||
|
@ -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 => {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
},
|
||||
{
|
||||
|
@ -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',
|
||||
|
@ -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;
|
9
devtools/shared/specs/targets/moz.build
Normal file
9
devtools/shared/specs/targets/moz.build
Normal 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',
|
||||
)
|
@ -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`);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user