Bug 1473513 - Backed out changeset d72f6ff37ca6 for failures on mobile/android/tests/browser/chrome/test_debugger_server.html CLOSED TREE

Summary:
MozReview-Commit-ID: LKPmFrhaQ5q

Depends on D6807

Bug #: 1473513

Differential Revision: https://phabricator.services.mozilla.com/D6808
This commit is contained in:
Alexandre Poirot 2018-09-25 19:34:26 +03:00
parent 40272ff560
commit 1255c658b2
31 changed files with 463 additions and 493 deletions

View File

@ -13,7 +13,7 @@ add_task(async function() {
DebuggerServer.init();
DebuggerServer.registerAllActors();
ActorRegistry.registerModule(ACTORS_URL, {
DebuggerServer.registerModule(ACTORS_URL, {
prefix: "testOne",
constructor: "TestActor1",
type: { global: true },

View File

@ -16,7 +16,6 @@ Services.prefs.setBoolPref("devtools.debugger.log", false);
var { BrowserToolboxProcess } = ChromeUtils.import("resource://devtools/client/framework/ToolboxProcess.jsm", {});
var { DebuggerServer } = require("devtools/server/main");
var { ActorRegistry } = require("devtools/server/actor-registry");
var { DebuggerClient } = require("devtools/shared/client/debugger-client");
var ObjectClient = require("devtools/shared/client/object-client");
var { AddonManager } = ChromeUtils.import("resource://gre/modules/AddonManager.jsm", {});

View File

@ -734,7 +734,7 @@ async function enableWebComponents() {
/*
* Register an actor in the content process of the current tab.
*
* Calling ActorRegistry.registerModule only registers the actor in the current process.
* Calling DebuggerServer.registerModule only registers the actor in the current process.
* As all test scripts are ran in the parent process, it is only registered here.
* This function helps register them in the content process used for the current tab.
*
@ -755,7 +755,7 @@ async function registerActorInContentProcess(url, options) {
return ContentTask.spawn(gBrowser.selectedBrowser, { url, options }, args => {
// eslint-disable-next-line no-shadow
const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
const { ActorRegistry } = require("devtools/server/actor-registry");
ActorRegistry.registerModule(args.url, args.options);
const { DebuggerServer } = require("devtools/server/main");
DebuggerServer.registerModule(args.url, args.options);
});
}

View File

@ -8,12 +8,12 @@ Target-scoped actors target a document, this could be a tab in Firefox or a remo
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 ActorRegistry.registerModule function
## The DebuggerServer.registerModule function
To register a target-scoped actor:
```
ActorRegistry.registerModule("devtools/server/actors/webconsole", {
DebuggerServer.registerModule("devtools/server/actors/webconsole", {
prefix: "console",
constructor: "WebConsoleActor",
type: { target: true }
@ -23,17 +23,17 @@ ActorRegistry.registerModule("devtools/server/actors/webconsole", {
To register a global actor:
```
ActorRegistry.registerModule("devtools/server/actors/addon/addons", {
DebuggerServer.registerModule("devtools/server/actors/addon/addons", {
prefix: "addons",
constructor: "AddonsActor",
type: { global: true }
});
```
If you are adding a new built-in actor, you should be registering it using `ActorRegistry.registerModule` in `addBrowserActors` or `addTargetScopedActors` in `/devtools/server/actor-registry.js`.
If you are adding a new built-in actor, you should be registering it using `DebuggerServer.registerModule` in `_addBrowserActors` or `_addTargetScopedActors` in `/devtools/server/main.js`.
## A note about lazy registration
The `ActorRegistry` loads and creates all of the actors lazily to keep the initial memory usage down (which is extremely important on lower end devices).
The `DebuggerServer` loads and creates all of the actors lazily to keep the initial memory usage down (which is extremely important on lower end devices).
It becomes especially important when debugging pages with e10s when there are more than one process, because that's when we need to spawn a `DebuggerServer` per process (it may not be immediately obvious that the server in the main process is mostly only here for piping messages to the actors in the child process).

View File

@ -51,7 +51,7 @@ The actor implementation would go somewhere like
// You also need to export the actor class in your module for discovery.
exports.HelloActor = HelloActor;
To activate your actor, register it in the `addBrowserActors` method in `server/actor-registry.js`.
To activate your actor, register it in the `_addBrowserActors` method in `server/main.js`.
The registration code would look something like this:
this.registerModule("devtools/server/actors/hello-world", {

View File

@ -1,412 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var Services = require("Services");
var { Ci } = require("chrome");
var gRegisteredModules = Object.create(null);
const ActorRegistry = {
// Map of global actor names to actor constructors.
globalActorFactories: {},
// Map of target-scoped actor names to actor constructors.
targetScopedActorFactories: {},
init(connections) {
this._connections = connections;
},
/**
* Register a CommonJS module with the debugger server.
* @param id string
* The ID of a CommonJS module.
* The actor is going to be registered immediately, but loaded only
* when a client starts sending packets to an actor with the same id.
*
* @param options object
* An object with 3 mandatory attributes:
* - prefix (string):
* The prefix of an actor is used to compute:
* - the `actorID` of each new actor instance (ex: prefix1).
* (See ActorPool.addActor)
* - the actor name in the listTabs request. Sending a listTabs
* request to the root actor returns actor IDs. IDs are in
* dictionaries, with actor names as keys and actor IDs as values.
* The actor name is the prefix to which the "Actor" string is
* appended. So for an actor with the `console` prefix, the actor
* name will be `consoleActor`.
* - constructor (string):
* the name of the exported symbol to be used as the actor
* constructor.
* - type (a dictionary of booleans with following attribute names):
* - "global"
* registers a global actor instance, if true.
* A global actor has the root actor as its parent.
* - "target"
* registers a target-scoped actor instance, if true.
* A new actor will be created for each target, such as a tab.
*/
registerModule(id, options) {
if (id in gRegisteredModules) {
return;
}
if (!options) {
throw new Error("ActorRegistry.registerModule requires an options argument");
}
const {prefix, constructor, type} = options;
if (typeof (prefix) !== "string") {
throw new Error(`Lazy actor definition for '${id}' requires a string ` +
`'prefix' option.`);
}
if (typeof (constructor) !== "string") {
throw new Error(`Lazy actor definition for '${id}' requires a string ` +
`'constructor' option.`);
}
if (!("global" in type) && !("target" in type)) {
throw new Error(`Lazy actor definition for '${id}' requires a dictionary ` +
`'type' option whose attributes can be 'global' or 'target'.`);
}
const name = prefix + "Actor";
const mod = {
id,
prefix,
constructorName: constructor,
type,
globalActor: type.global,
targetScopedActor: type.target
};
gRegisteredModules[id] = mod;
if (mod.targetScopedActor) {
this.addTargetScopedActor(mod, name);
}
if (mod.globalActor) {
this.addGlobalActor(mod, name);
}
},
/**
* Unregister a previously-loaded CommonJS module from the debugger server.
*/
unregisterModule(id) {
const mod = gRegisteredModules[id];
if (!mod) {
throw new Error("Tried to unregister a module that was not previously registered.");
}
// Lazy actors
if (mod.targetScopedActor) {
this.removeTargetScopedActor(mod);
}
if (mod.globalActor) {
this.removeGlobalActor(mod);
}
delete gRegisteredModules[id];
},
/**
* Install Firefox-specific actors.
*
* /!\ Be careful when adding a new actor, especially global actors.
* Any new global actor will be exposed and returned by the root actor.
*/
addBrowserActors() {
this.registerModule("devtools/server/actors/preference", {
prefix: "preference",
constructor: "PreferenceActor",
type: { global: true }
});
this.registerModule("devtools/server/actors/actor-registry", {
prefix: "actorRegistry",
constructor: "ActorRegistryActor",
type: { global: true }
});
this.registerModule("devtools/server/actors/addon/addons", {
prefix: "addons",
constructor: "AddonsActor",
type: { global: true }
});
this.registerModule("devtools/server/actors/device", {
prefix: "device",
constructor: "DeviceActor",
type: { global: true }
});
this.registerModule("devtools/server/actors/heap-snapshot-file", {
prefix: "heapSnapshotFile",
constructor: "HeapSnapshotFileActor",
type: { global: true }
});
// Always register this as a global module, even while there is a pref turning
// on and off the other performance actor. This actor shouldn't conflict with
// the other one. These are also lazily loaded so there shouldn't be a performance
// impact.
this.registerModule("devtools/server/actors/perf", {
prefix: "perf",
constructor: "PerfActor",
type: { global: true }
});
},
/**
* Install target-scoped actors.
*/
addTargetScopedActors() {
this.registerModule("devtools/server/actors/webconsole", {
prefix: "console",
constructor: "WebConsoleActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/inspector/inspector", {
prefix: "inspector",
constructor: "InspectorActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/canvas", {
prefix: "canvas",
constructor: "CanvasActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/webgl", {
prefix: "webgl",
constructor: "WebGLActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/webaudio", {
prefix: "webaudio",
constructor: "WebAudioActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/stylesheets", {
prefix: "styleSheets",
constructor: "StyleSheetsActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/storage", {
prefix: "storage",
constructor: "StorageActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/memory", {
prefix: "memory",
constructor: "MemoryActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/framerate", {
prefix: "framerate",
constructor: "FramerateActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/reflow", {
prefix: "reflow",
constructor: "ReflowActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/css-properties", {
prefix: "cssProperties",
constructor: "CssPropertiesActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/csscoverage", {
prefix: "cssUsage",
constructor: "CSSUsageActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/timeline", {
prefix: "timeline",
constructor: "TimelineActor",
type: { target: true }
});
if ("nsIProfiler" in Ci &&
!Services.prefs.getBoolPref("devtools.performance.new-panel-enabled", false)) {
this.registerModule("devtools/server/actors/performance", {
prefix: "performance",
constructor: "PerformanceActor",
type: { target: true }
});
}
this.registerModule("devtools/server/actors/animation", {
prefix: "animations",
constructor: "AnimationsActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/promises", {
prefix: "promises",
constructor: "PromisesActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/emulation", {
prefix: "emulation",
constructor: "EmulationActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/addon/webextension-inspected-window", {
prefix: "webExtensionInspectedWindow",
constructor: "WebExtensionInspectedWindowActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/accessibility", {
prefix: "accessibility",
constructor: "AccessibilityActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/screenshot", {
prefix: "screenshot",
constructor: "ScreenshotActor",
type: { target: true }
});
},
/**
* Registers handlers for new target-scoped request types defined dynamically.
*
* Note that the name or actorPrefix of the request type is not allowed to clash with
* existing protocol packet properties, like 'title', 'url' or 'actor', since that would
* break the protocol.
*
* @param options object
* - constructorName: (required)
* name of actor constructor, which is also used when removing the actor.
* One of the following:
* - id:
* module ID that contains the actor
* - constructorFun:
* a function to construct the actor
* @param name string
* The name of the new request type.
*/
addTargetScopedActor(options, name) {
if (!name) {
throw Error("addTargetScopedActor requires the `name` argument");
}
if (["title", "url", "actor"].includes(name)) {
throw Error(name + " is not allowed");
}
if (this.targetScopedActorFactories.hasOwnProperty(name)) {
throw Error(name + " already exists");
}
this.targetScopedActorFactories[name] = { options, name };
},
/**
* Unregisters the handler for the specified target-scoped request type.
*
* When unregistering an existing target-scoped actor, we remove the actor factory as
* well as all existing instances of the actor.
*
* @param actor object, string
* In case of object:
* The `actor` object being given to related addTargetScopedActor call.
* In case of string:
* The `name` string being given to related addTargetScopedActor call.
*/
removeTargetScopedActor(actorOrName) {
let name;
if (typeof actorOrName == "string") {
name = actorOrName;
} else {
const actor = actorOrName;
for (const factoryName in this.targetScopedActorFactories) {
const handler = this.targetScopedActorFactories[factoryName];
if ((handler.options.constructorName == actor.name) ||
(handler.options.id == actor.id)) {
name = factoryName;
break;
}
}
}
if (!name) {
return;
}
delete this.targetScopedActorFactories[name];
for (const connID of Object.getOwnPropertyNames(this._connections)) {
// DebuggerServerConnection in child process don't have rootActor
if (this._connections[connID].rootActor) {
this._connections[connID].rootActor.removeActorByName(name);
}
}
},
/**
* Registers handlers for new browser-scoped request types defined dynamically.
*
* Note that the name or actorPrefix of the request type is not allowed to clash with
* existing protocol packet properties, like 'from', 'tabs' or 'selected', since that
* would break the protocol.
*
* @param options object
* - constructorName: (required)
* name of actor constructor, which is also used when removing the actor.
* One of the following:
* - id:
* module ID that contains the actor
* - constructorFun:
* a function to construct the actor
* @param name string
* The name of the new request type.
*/
addGlobalActor(options, name) {
if (!name) {
throw Error("addGlobalActor requires the `name` argument");
}
if (["from", "tabs", "selected"].includes(name)) {
throw Error(name + " is not allowed");
}
if (this.globalActorFactories.hasOwnProperty(name)) {
throw Error(name + " already exists");
}
this.globalActorFactories[name] = { options, name };
},
/**
* Unregisters the handler for the specified browser-scoped request type.
*
* When unregistering an existing global actor, we remove the actor factory as well as
* all existing instances of the actor.
*
* @param actor object, string
* In case of object:
* The `actor` object being given to related addGlobalActor call.
* In case of string:
* The `name` string being given to related addGlobalActor call.
*/
removeGlobalActor(actorOrName) {
let name;
if (typeof actorOrName == "string") {
name = actorOrName;
} else {
const actor = actorOrName;
for (const factoryName in this.globalActorFactories) {
const handler = this.globalActorFactories[factoryName];
if ((handler.options.constructorName == actor.name) ||
(handler.options.id == actor.id)) {
name = factoryName;
break;
}
}
}
if (!name) {
return;
}
delete this.globalActorFactories[name];
for (const connID of Object.getOwnPropertyNames(this._connections)) {
// DebuggerServerConnection in child process don't have rootActor
if (this._connections[connID].rootActor) {
this._connections[connID].rootActor.removeActorByName(name);
}
}
},
destroy() {
for (const id of Object.getOwnPropertyNames(gRegisteredModules)) {
this.unregisterModule(id);
}
gRegisteredModules = Object.create(null);
this.globalActorFactories = {};
this.targetScopedActorFactories = {};
},
};
exports.ActorRegistry = ActorRegistry;

View File

@ -42,7 +42,7 @@ loader.lazyRequireGetter(this, "ChromeWindowTargetActor",
*
* - globalActorFactories: an object |A| describing further actors to
* attach to the 'listTabs' reply. This is the type accumulated by
* ActorRegistry.addGlobalActor. For each own property |P| of |A|,
* DebuggerServer.addGlobalActor. For each own property |P| of |A|,
* the root actor adds a property named |P| to the 'listTabs'
* reply whose value is the name of an actor constructed by
* |A[P]|.
@ -576,8 +576,8 @@ RootActor.prototype = {
},
/**
* Remove the extra actor (added by ActorRegistry.addGlobalActor or
* ActorRegistry.addTargetScopedActor) name |name|.
* Remove the extra actor (added by DebuggerServer.addGlobalActor or
* DebuggerServer.addTargetScopedActor) name |name|.
*/
removeActorByName: function(name) {
if (name in this._extraActors) {

View File

@ -23,7 +23,7 @@
var { Ci, Cu, Cr, Cc } = require("chrome");
var Services = require("Services");
const ChromeUtils = require("ChromeUtils");
var { ActorRegistry } = require("devtools/server/actor-registry");
var { DebuggerServer } = require("devtools/server/main");
var DevToolsUtils = require("devtools/shared/DevToolsUtils");
var { assert } = DevToolsUtils;
var { TabSources } = require("devtools/server/actors/utils/TabSources");
@ -103,7 +103,7 @@ const browsingContextTargetPrototype = {
* is a `docShell`.
*
* The main goal of this class is to expose the target-scoped actors being registered
* via `ActorRegistry.registerModule` and manage their lifetimes. In addition, this
* via `DebuggerServer.registerModule` and manage their lifetimes. In addition, this
* class also tracks the lifetime of the targeted browsing context.
*
* ### Main requests:
@ -481,13 +481,13 @@ const browsingContextTargetPrototype = {
// Walk over target-scoped actor factories and make sure they are all
// instantiated and added into the ActorPool.
const actors = createExtraActors(
ActorRegistry.targetScopedActorFactories,
const addedActors = createExtraActors(
DebuggerServer.targetScopedActorFactories,
this._targetScopedActorPool,
this
);
Object.assign(response, actors);
Object.assign(response, addedActors);
return response;
},

View File

@ -7,7 +7,6 @@
const { Cu, CC } = require("chrome");
const { DebuggerServer } = require("devtools/server/main");
const { ActorRegistry } = require("devtools/server/actor-registry");
/**
* Support for actor registration. Main used by ActorRegistryActor
@ -39,15 +38,15 @@ exports.registerActorInCurrentProcess = function(sourceText, fileName, options)
const { prefix, constructor, type } = options;
if (type.global && !ActorRegistry.globalActorFactories.hasOwnProperty(prefix)) {
ActorRegistry.addGlobalActor({
if (type.global && !DebuggerServer.globalActorFactories.hasOwnProperty(prefix)) {
DebuggerServer.addGlobalActor({
constructorName: constructor,
constructorFun: sandbox[constructor]
}, prefix);
}
if (type.target && !ActorRegistry.targetScopedActorFactories.hasOwnProperty(prefix)) {
ActorRegistry.addTargetScopedActor({
if (type.target && !DebuggerServer.targetScopedActorFactories.hasOwnProperty(prefix)) {
DebuggerServer.addTargetScopedActor({
constructorName: constructor,
constructorFun: sandbox[constructor]
}, prefix);
@ -67,10 +66,10 @@ exports.unregisterActor = function(options) {
exports.unregisterActorInCurrentProcess = function(options) {
if (options.target) {
ActorRegistry.removeTargetScopedActor(options);
DebuggerServer.removeTargetScopedActor(options);
}
if (options.global) {
ActorRegistry.removeGlobalActor(options);
DebuggerServer.removeGlobalActor(options);
}
};

View File

@ -9,7 +9,6 @@
var { Ci } = require("chrome");
var Services = require("Services");
var { DebuggerServer } = require("devtools/server/main");
var { ActorRegistry } = require("devtools/server/actor-registry");
var DevToolsUtils = require("devtools/shared/DevToolsUtils");
loader.lazyRequireGetter(this, "RootActor", "devtools/server/actors/root", true);
@ -49,7 +48,7 @@ exports.sendShutdownEvent = sendShutdownEvent;
/**
* Construct a root actor appropriate for use in a server running in a
* browser. The returned root actor:
* - respects the factories registered with ActorRegistry.addGlobalActor,
* - respects the factories registered with DebuggerServer.addGlobalActor,
* - uses a BrowserTabList to supply target actors for tabs,
* - sends all navigator:browser window documents a Debugger:Shutdown event
* when it exits.
@ -65,7 +64,7 @@ exports.createRootActor = function createRootActor(connection) {
serviceWorkerRegistrationList:
new ServiceWorkerRegistrationActorList(connection),
processList: new ProcessActorList(),
globalActorFactories: ActorRegistry.globalActorFactories,
globalActorFactories: DebuggerServer.globalActorFactories,
onShutdown: sendShutdownEvent
});
};

View File

@ -11,7 +11,6 @@
var { Ci, Cc } = require("chrome");
var Services = require("Services");
var { ActorPool } = require("devtools/server/actors/common");
var { ActorRegistry } = require("devtools/server/actor-registry");
var DevToolsUtils = require("devtools/shared/DevToolsUtils");
var { dumpn } = DevToolsUtils;
@ -34,6 +33,8 @@ const CONTENT_PROCESS_SERVER_STARTUP_SCRIPT =
loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
var gRegisteredModules = Object.create(null);
/**
* Public API
*/
@ -81,7 +82,6 @@ var DebuggerServer = {
}
this._connections = {};
ActorRegistry.init(this._connections);
this._nextConnID = 0;
this._initialized = true;
@ -111,9 +111,14 @@ var DebuggerServer = {
this._connections[connID].close();
}
ActorRegistry.destroy();
for (const id of Object.getOwnPropertyNames(gRegisteredModules)) {
this.unregisterModule(id);
}
gRegisteredModules = Object.create(null);
this.closeAllListeners();
this.globalActorFactories = {};
this.targetScopedActorFactories = {};
this._initialized = false;
dumpn("Debugger server is shut down.");
@ -149,7 +154,7 @@ var DebuggerServer = {
*/
registerActors({ root, browser, target }) {
if (browser) {
ActorRegistry.addBrowserActors();
this._addBrowserActors();
}
if (root) {
@ -158,7 +163,7 @@ var DebuggerServer = {
}
if (target) {
ActorRegistry.addTargetScopedActors();
this._addTargetScopedActors();
}
},
@ -169,6 +174,254 @@ var DebuggerServer = {
this.registerActors({ root: true, browser: true, target: true });
},
/**
* Register a CommonJS module with the debugger server.
* @param id string
* The ID of a CommonJS module.
* The actor is going to be registered immediately, but loaded only
* when a client starts sending packets to an actor with the same id.
*
* @param options object
* An object with 3 mandatory attributes:
* - prefix (string):
* The prefix of an actor is used to compute:
* - the `actorID` of each new actor instance (ex: prefix1).
* (See ActorPool.addActor)
* - the actor name in the listTabs request. Sending a listTabs
* request to the root actor returns actor IDs. IDs are in
* dictionaries, with actor names as keys and actor IDs as values.
* The actor name is the prefix to which the "Actor" string is
* appended. So for an actor with the `console` prefix, the actor
* name will be `consoleActor`.
* - constructor (string):
* the name of the exported symbol to be used as the actor
* constructor.
* - type (a dictionary of booleans with following attribute names):
* - "global"
* registers a global actor instance, if true.
* A global actor has the root actor as its parent.
* - "target"
* registers a target-scoped actor instance, if true.
* A new actor will be created for each target, such as a tab.
*/
registerModule(id, options) {
if (id in gRegisteredModules) {
return;
}
if (!options) {
throw new Error("DebuggerServer.registerModule requires an options argument");
}
const {prefix, constructor, type} = options;
if (typeof (prefix) !== "string") {
throw new Error(`Lazy actor definition for '${id}' requires a string ` +
`'prefix' option.`);
}
if (typeof (constructor) !== "string") {
throw new Error(`Lazy actor definition for '${id}' requires a string ` +
`'constructor' option.`);
}
if (!("global" in type) && !("target" in type)) {
throw new Error(`Lazy actor definition for '${id}' requires a dictionary ` +
`'type' option whose attributes can be 'global' or 'target'.`);
}
const name = prefix + "Actor";
const mod = {
id,
prefix,
constructorName: constructor,
type,
globalActor: type.global,
targetScopedActor: type.target
};
gRegisteredModules[id] = mod;
if (mod.targetScopedActor) {
this.addTargetScopedActor(mod, name);
}
if (mod.globalActor) {
this.addGlobalActor(mod, name);
}
},
/**
* Returns true if a module id has been registered.
*/
isModuleRegistered(id) {
return (id in gRegisteredModules);
},
/**
* Unregister a previously-loaded CommonJS module from the debugger server.
*/
unregisterModule(id) {
const mod = gRegisteredModules[id];
if (!mod) {
throw new Error("Tried to unregister a module that was not previously registered.");
}
// Lazy actors
if (mod.targetScopedActor) {
this.removeTargetScopedActor(mod);
}
if (mod.globalActor) {
this.removeGlobalActor(mod);
}
delete gRegisteredModules[id];
},
/**
* Install Firefox-specific actors.
*
* /!\ Be careful when adding a new actor, especially global actors.
* Any new global actor will be exposed and returned by the root actor.
*/
_addBrowserActors() {
this.registerModule("devtools/server/actors/preference", {
prefix: "preference",
constructor: "PreferenceActor",
type: { global: true }
});
this.registerModule("devtools/server/actors/actor-registry", {
prefix: "actorRegistry",
constructor: "ActorRegistryActor",
type: { global: true }
});
this.registerModule("devtools/server/actors/addon/addons", {
prefix: "addons",
constructor: "AddonsActor",
type: { global: true }
});
this.registerModule("devtools/server/actors/device", {
prefix: "device",
constructor: "DeviceActor",
type: { global: true }
});
this.registerModule("devtools/server/actors/heap-snapshot-file", {
prefix: "heapSnapshotFile",
constructor: "HeapSnapshotFileActor",
type: { global: true }
});
// Always register this as a global module, even while there is a pref turning
// on and off the other performance actor. This actor shouldn't conflict with
// the other one. These are also lazily loaded so there shouldn't be a performance
// impact.
this.registerModule("devtools/server/actors/perf", {
prefix: "perf",
constructor: "PerfActor",
type: { global: true }
});
},
/**
* Install target-scoped actors.
*/
_addTargetScopedActors() {
this.registerModule("devtools/server/actors/webconsole", {
prefix: "console",
constructor: "WebConsoleActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/inspector/inspector", {
prefix: "inspector",
constructor: "InspectorActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/canvas", {
prefix: "canvas",
constructor: "CanvasActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/webgl", {
prefix: "webgl",
constructor: "WebGLActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/webaudio", {
prefix: "webaudio",
constructor: "WebAudioActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/stylesheets", {
prefix: "styleSheets",
constructor: "StyleSheetsActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/storage", {
prefix: "storage",
constructor: "StorageActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/memory", {
prefix: "memory",
constructor: "MemoryActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/framerate", {
prefix: "framerate",
constructor: "FramerateActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/reflow", {
prefix: "reflow",
constructor: "ReflowActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/css-properties", {
prefix: "cssProperties",
constructor: "CssPropertiesActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/csscoverage", {
prefix: "cssUsage",
constructor: "CSSUsageActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/timeline", {
prefix: "timeline",
constructor: "TimelineActor",
type: { target: true }
});
if ("nsIProfiler" in Ci &&
!Services.prefs.getBoolPref("devtools.performance.new-panel-enabled", false)) {
this.registerModule("devtools/server/actors/performance", {
prefix: "performance",
constructor: "PerformanceActor",
type: { target: true }
});
}
this.registerModule("devtools/server/actors/animation", {
prefix: "animations",
constructor: "AnimationsActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/promises", {
prefix: "promises",
constructor: "PromisesActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/emulation", {
prefix: "emulation",
constructor: "EmulationActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/addon/webextension-inspected-window", {
prefix: "webExtensionInspectedWindow",
constructor: "WebExtensionInspectedWindowActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/accessibility", {
prefix: "accessibility",
constructor: "AccessibilityActor",
type: { target: true }
});
this.registerModule("devtools/server/actors/screenshot", {
prefix: "screenshot",
constructor: "ScreenshotActor",
type: { target: true }
});
},
/**
* Passes a set of options to the AddonTargetActors for the given ID.
*
@ -909,6 +1162,146 @@ var DebuggerServer = {
this.createRootActor = actorFactory;
},
/**
* Registers handlers for new target-scoped request types defined dynamically.
*
* Note that the name or actorPrefix of the request type is not allowed to clash with
* existing protocol packet properties, like 'title', 'url' or 'actor', since that would
* break the protocol.
*
* @param options object
* - constructorName: (required)
* name of actor constructor, which is also used when removing the actor.
* One of the following:
* - id:
* module ID that contains the actor
* - constructorFun:
* a function to construct the actor
* @param name string
* The name of the new request type.
*/
addTargetScopedActor(options, name) {
if (!name) {
throw Error("addTargetScopedActor requires the `name` argument");
}
if (["title", "url", "actor"].includes(name)) {
throw Error(name + " is not allowed");
}
if (DebuggerServer.targetScopedActorFactories.hasOwnProperty(name)) {
throw Error(name + " already exists");
}
DebuggerServer.targetScopedActorFactories[name] = { options, name };
},
/**
* Unregisters the handler for the specified target-scoped request type.
*
* When unregistering an existing target-scoped actor, we remove the actor factory as
* well as all existing instances of the actor.
*
* @param actor object, string
* In case of object:
* The `actor` object being given to related addTargetScopedActor call.
* In case of string:
* The `name` string being given to related addTargetScopedActor call.
*/
removeTargetScopedActor(actorOrName) {
let name;
if (typeof actorOrName == "string") {
name = actorOrName;
} else {
const actor = actorOrName;
for (const factoryName in DebuggerServer.targetScopedActorFactories) {
const handler = DebuggerServer.targetScopedActorFactories[factoryName];
if ((handler.options.constructorName == actor.name) ||
(handler.options.id == actor.id)) {
name = factoryName;
break;
}
}
}
if (!name) {
return;
}
delete DebuggerServer.targetScopedActorFactories[name];
for (const connID of Object.getOwnPropertyNames(this._connections)) {
// DebuggerServerConnection in child process don't have rootActor
if (this._connections[connID].rootActor) {
this._connections[connID].rootActor.removeActorByName(name);
}
}
},
/**
* Registers handlers for new browser-scoped request types defined dynamically.
*
* Note that the name or actorPrefix of the request type is not allowed to clash with
* existing protocol packet properties, like 'from', 'tabs' or 'selected', since that
* would break the protocol.
*
* @param options object
* - constructorName: (required)
* name of actor constructor, which is also used when removing the actor.
* One of the following:
* - id:
* module ID that contains the actor
* - constructorFun:
* a function to construct the actor
* @param name string
* The name of the new request type.
*/
addGlobalActor(options, name) {
if (!name) {
throw Error("addGlobalActor requires the `name` argument");
}
if (["from", "tabs", "selected"].includes(name)) {
throw Error(name + " is not allowed");
}
if (DebuggerServer.globalActorFactories.hasOwnProperty(name)) {
throw Error(name + " already exists");
}
DebuggerServer.globalActorFactories[name] = { options, name };
},
/**
* Unregisters the handler for the specified browser-scoped request type.
*
* When unregistering an existing global actor, we remove the actor factory as well as
* all existing instances of the actor.
*
* @param actor object, string
* In case of object:
* The `actor` object being given to related addGlobalActor call.
* In case of string:
* The `name` string being given to related addGlobalActor call.
*/
removeGlobalActor(actorOrName) {
let name;
if (typeof actorOrName == "string") {
name = actorOrName;
} else {
const actor = actorOrName;
for (const factoryName in DebuggerServer.globalActorFactories) {
const handler = DebuggerServer.globalActorFactories[factoryName];
if ((handler.options.constructorName == actor.name) ||
(handler.options.id == actor.id)) {
name = factoryName;
break;
}
}
}
if (!name) {
return;
}
delete DebuggerServer.globalActorFactories[name];
for (const connID of Object.getOwnPropertyNames(this._connections)) {
// DebuggerServerConnection in child process don't have rootActor
if (this._connections[connID].rootActor) {
this._connections[connID].rootActor.removeActorByName(name);
}
}
},
/**
* Called when DevTools are unloaded to remove the contend process server startup script
* for the list of scripts loaded for each new content process. Will also remove message

View File

@ -20,7 +20,6 @@ MOCHITEST_CHROME_MANIFESTS += ['tests/mochitest/chrome.ini']
XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
DevToolsModules(
'actor-registry.js',
'main.js',
)

View File

@ -16,7 +16,7 @@ async function test() {
DebuggerServer.init();
DebuggerServer.registerAllActors();
ActorRegistry.registerModule(ACTORS_URL, {
DebuggerServer.registerModule(ACTORS_URL, {
prefix: "error",
constructor: "ErrorActor",
type: { global: true },

View File

@ -12,7 +12,6 @@ Services.scriptloader.loadSubScript(
this);
const {DebuggerClient} = require("devtools/shared/client/debugger-client");
const { ActorRegistry } = require("devtools/server/actor-registry");
const {DebuggerServer} = require("devtools/server/main");
const PATH = "browser/devtools/server/tests/browser/";

View File

@ -47,7 +47,6 @@ function runTests() {
/* eslint-disable no-shadow */
const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
const { DebuggerServer } = require("devtools/server/main");
const { ActorRegistry } = require("devtools/server/actor-registry");
/* eslint-enable no-shadow */
DebuggerServer.init();
@ -68,7 +67,7 @@ function runTests() {
TestActor.prototype.requestTypes = {
"hello": TestActor.prototype.hello
};
ActorRegistry.addTargetScopedActor({
DebuggerServer.addTargetScopedActor({
constructorName: "TestActor",
constructorFun: TestActor,
}, "testActor");

View File

@ -31,7 +31,6 @@ Services.prefs.setBoolPref("devtools.debugger.log", true);
Services.prefs.setBoolPref("devtools.debugger.remote-enabled", true);
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
const { ActorRegistry } = require("devtools/server/actor-registry");
const { DebuggerServer } = require("devtools/server/main");
const { DebuggerServer: WorkerDebuggerServer } = worker.require("devtools/server/main");
const { DebuggerClient } = require("devtools/shared/client/debugger-client");
@ -77,7 +76,7 @@ function makeMemoryActorTest(testGeneratorFunction) {
return function run_test() {
do_test_pending();
startTestDebuggerServer(TEST_GLOBAL_NAME).then(client => {
ActorRegistry.registerModule("devtools/server/actors/heap-snapshot-file", {
DebuggerServer.registerModule("devtools/server/actors/heap-snapshot-file", {
prefix: "heapSnapshotFile",
constructor: "HeapSnapshotFileActor",
type: { global: true }
@ -115,7 +114,7 @@ function makeFullRuntimeMemoryActorTest(testGeneratorFunction) {
return function run_test() {
do_test_pending();
startTestDebuggerServer("test_MemoryActor").then(client => {
ActorRegistry.registerModule("devtools/server/actors/heap-snapshot-file", {
DebuggerServer.registerModule("devtools/server/actors/heap-snapshot-file", {
prefix: "heapSnapshotFile",
constructor: "HeapSnapshotFileActor",
type: { global: true }

View File

@ -16,12 +16,12 @@ function getActorInstance(connID, actorID) {
* regardless of the object's state.
*/
add_task(async function() {
ActorRegistry.registerModule("resource://test/pre_init_global_actors.js", {
DebuggerServer.registerModule("resource://test/pre_init_global_actors.js", {
prefix: "preInitGlobal",
constructor: "PreInitGlobalActor",
type: { global: true },
});
ActorRegistry.registerModule("resource://test/pre_init_target_scoped_actors.js", {
DebuggerServer.registerModule("resource://test/pre_init_target_scoped_actors.js", {
prefix: "preInitTargetScoped",
constructor: "PreInitTargetScopedActor",
type: { target: true },
@ -29,12 +29,12 @@ add_task(async function() {
const client = await startTestDebuggerServer("example tab");
ActorRegistry.registerModule("resource://test/post_init_global_actors.js", {
DebuggerServer.registerModule("resource://test/post_init_global_actors.js", {
prefix: "postInitGlobal",
constructor: "PostInitGlobalActor",
type: { global: true },
});
ActorRegistry.registerModule("resource://test/post_init_target_scoped_actors.js", {
DebuggerServer.registerModule("resource://test/post_init_target_scoped_actors.js", {
prefix: "postInitTargetScoped",
constructor: "PostInitTargetScopedActor",
type: { target: true },

View File

@ -27,7 +27,7 @@ TestActor.prototype.requestTypes = {
};
function run_test() {
ActorRegistry.addGlobalActor({
DebuggerServer.addGlobalActor({
constructorName: "TestActor",
constructorFun: TestActor,
}, "test");

View File

@ -51,7 +51,7 @@ TestClient.prototype = {
};
function run_test() {
ActorRegistry.addGlobalActor({
DebuggerServer.addGlobalActor({
constructorName: "TestActor",
constructorFun: TestActor,
}, "test");

View File

@ -14,7 +14,7 @@ function run_test() {
run_next_test();
}
// Bug 988237: Test the new lazy actor actor-register
// Bug 988237: Test the new lazy actor loading
function test_lazy_api() {
let isActorLoaded = false;
let isActorInstantiated = false;
@ -26,14 +26,14 @@ function test_lazy_api() {
}
}
Services.obs.addObserver(onActorEvent, "actor");
ActorRegistry.registerModule("xpcshell-test/registertestactors-lazy", {
DebuggerServer.registerModule("xpcshell-test/registertestactors-lazy", {
prefix: "lazy",
constructor: "LazyActor",
type: { global: true, target: true }
});
// The actor is immediatly registered, but not loaded
Assert.ok(ActorRegistry.targetScopedActorFactories.hasOwnProperty("lazyActor"));
Assert.ok(ActorRegistry.globalActorFactories.hasOwnProperty("lazyActor"));
Assert.ok(DebuggerServer.targetScopedActorFactories.hasOwnProperty("lazyActor"));
Assert.ok(DebuggerServer.globalActorFactories.hasOwnProperty("lazyActor"));
Assert.ok(!isActorLoaded);
Assert.ok(!isActorInstantiated);
@ -65,9 +65,9 @@ function test_lazy_api() {
}
function manual_remove() {
Assert.ok(ActorRegistry.globalActorFactories.hasOwnProperty("lazyActor"));
ActorRegistry.removeGlobalActor("lazyActor");
Assert.ok(!ActorRegistry.globalActorFactories.hasOwnProperty("lazyActor"));
Assert.ok(DebuggerServer.globalActorFactories.hasOwnProperty("lazyActor"));
DebuggerServer.removeGlobalActor("lazyActor");
Assert.ok(!DebuggerServer.globalActorFactories.hasOwnProperty("lazyActor"));
run_next_test();
}
@ -76,8 +76,8 @@ function cleanup() {
DebuggerServer.destroy();
// Check that all actors are unregistered on server destruction
Assert.ok(!ActorRegistry.targetScopedActorFactories.hasOwnProperty("lazyActor"));
Assert.ok(!ActorRegistry.globalActorFactories.hasOwnProperty("lazyActor"));
Assert.ok(!DebuggerServer.targetScopedActorFactories.hasOwnProperty("lazyActor"));
Assert.ok(!DebuggerServer.globalActorFactories.hasOwnProperty("lazyActor"));
run_next_test();
}

View File

@ -7,7 +7,6 @@ const { LazyPool, createExtraActors } = require("devtools/shared/protocol/lazy-p
const { RootActor } = require("devtools/server/actors/root");
const { ThreadActor } = require("devtools/server/actors/thread");
const { DebuggerServer } = require("devtools/server/main");
const { ActorRegistry } = require("devtools/server/actor-registry");
const { TabSources } = require("devtools/server/actors/utils/TabSources");
const makeDebugger = require("devtools/server/actors/utils/make-debugger");
@ -64,7 +63,7 @@ TestTabList.prototype = {
exports.createRootActor = function createRootActor(connection) {
const root = new RootActor(connection, {
tabList: new TestTabList(connection),
globalActorFactories: ActorRegistry.globalActorFactories,
globalActorFactories: DebuggerServer.globalActorFactories,
});
root.applicationType = "xpcshell-tests";
@ -113,7 +112,7 @@ TestTargetActor.prototype = {
// Walk over target-scoped actors and add them to a new LazyPool.
const actorPool = new LazyPool(this.conn);
const actors = createExtraActors(
ActorRegistry.targetScopedActorFactories,
DebuggerServer.targetScopedActorFactories,
actorPool,
this
);

View File

@ -51,7 +51,7 @@ exports.LazyPool = LazyPool;
* |pool|. _extraActors is treated as a cache for lazy actors
*
* The target actor uses this to instantiate actors that other
* parts of the browser have specified with ActorRegistry.addTargetScopedActor
* parts of the browser have specified with DebuggerServer.addTargetScopedActor
*
* @param factories
* An object whose own property names are the names of properties to add to

View File

@ -1,12 +1,12 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { LazyPool, createExtraActors } = require("devtools/shared/protocol/lazy-pool");
const { RootActor } = require("devtools/server/actors/root");
const { ThreadActor } = require("devtools/server/actors/thread");
const { DebuggerServer } = require("devtools/server/main");
const { ActorRegistry } = require("devtools/server/actor-registry");
const promise = require("promise");
var gTestGlobals = [];
@ -52,7 +52,7 @@ TestTabList.prototype = {
exports.createRootActor = function createRootActor(connection) {
const root = new RootActor(connection, {
tabList: new TestTabList(connection),
globalActorFactories: ActorRegistry.globalActorFactories
globalActorFactories: DebuggerServer.globalActorFactories
});
root.applicationType = "xpcshell-tests";
return root;
@ -85,7 +85,7 @@ TestTargetActor.prototype = {
// Walk over target-scoped actors and add them to a new LazyPool.
const actorPool = new LazyPool(this.conn);
const actors = createExtraActors(
ActorRegistry.targetScopedActorFactories,
DebuggerServer.targetScopedActorFactories,
actorPool,
this
);

View File

@ -25,7 +25,6 @@ const Services = require("Services");
// Enable remote debugging for the relevant tests.
Services.prefs.setBoolPref("devtools.debugger.remote-enabled", true);
const { ActorRegistry } = require("devtools/server/actor-registry");
const { DebuggerServer } = require("devtools/server/main");
const { DebuggerClient } = require("devtools/shared/client/debugger-client");
@ -91,7 +90,7 @@ Services.console.registerListener(listener);
* Initialize the testing debugger server.
*/
function initTestDebuggerServer() {
ActorRegistry.registerModule("devtools/server/actors/thread", {
DebuggerServer.registerModule("devtools/server/actors/thread", {
prefix: "script",
constructor: "ScriptActor",
type: { global: true, target: true }

View File

@ -39,7 +39,7 @@ TestBulkActor.prototype.requestTypes = {
};
function add_test_bulk_actor() {
ActorRegistry.addGlobalActor({
DebuggerServer.addGlobalActor({
constructorName: "TestBulkActor",
constructorFun: TestBulkActor,
}, "testBulk");

View File

@ -93,7 +93,7 @@ TestBulkActor.prototype.requestTypes = {
};
function add_test_bulk_actor() {
ActorRegistry.addGlobalActor({
DebuggerServer.addGlobalActor({
constructorName: "TestBulkActor",
constructorFun: TestBulkActor,
}, "testBulk");

View File

@ -3,14 +3,14 @@
"use strict";
const { RootActor } = require("devtools/server/actors/root");
const { ActorRegistry } = require("devtools/server/actor-registry");
const { DebuggerServer } = require("devtools/server/main");
/**
* Root actor that doesn't have the bulk trait.
*/
exports.createRootActor = function createRootActor(connection) {
const root = new RootActor(connection, {
globalActorFactories: ActorRegistry.globalActorFactories
globalActorFactories: DebuggerServer.globalActorFactories
});
root.applicationType = "xpcshell-tests";
root.traits = {

View File

@ -6,8 +6,6 @@ const { LazyPool, createExtraActors } = require("devtools/shared/protocol/lazy-p
const { RootActor } = require("devtools/server/actors/root");
const { ThreadActor } = require("devtools/server/actors/thread");
const { DebuggerServer } = require("devtools/server/main");
const { ActorRegistry } = require("devtools/server/actor-registry");
const promise = require("promise");
var gTestGlobals = [];
DebuggerServer.addTestGlobal = function(global) {
@ -52,7 +50,7 @@ TestTabList.prototype = {
exports.createRootActor = function createRootActor(connection) {
const root = new RootActor(connection, {
tabList: new TestTabList(connection),
globalActorFactories: ActorRegistry.globalActorFactories
globalActorFactories: DebuggerServer.globalActorFactories
});
root.applicationType = "xpcshell-tests";
return root;
@ -85,12 +83,13 @@ TestTargetActor.prototype = {
// Walk over target-scoped actors and add them to a new LazyPool.
const actorPool = new LazyPool(this.conn);
const actors = createExtraActors(
ActorRegistry.targetScopedActorFactories,
DebuggerServer.targetScopedActorFactories,
actorPool,
this
);
if (!actorPool.isEmpty()) {
this._targetActorPool = actorPool;
this.conn.addActorPool(this._targetActorPool);
}
return { ...response, ...actors };

View File

@ -11,14 +11,14 @@
*/
const { RootActor } = require("devtools/server/actors/root");
const { ActorRegistry } = require("devtools/server/actor-registry");
const { DebuggerServer } = require("devtools/server/main");
const { BrowserTabList, BrowserAddonList, sendShutdownEvent } =
require("devtools/server/actors/webbrowser");
/**
* Construct a root actor appropriate for use in a server running in a
* browser on Android. The returned root actor:
* - respects the factories registered with ActorRegistry.addGlobalActor,
* - respects the factories registered with DebuggerServer.addGlobalActor,
* - uses a MobileTabList to supply tab actors,
* - sends all navigator:browser window documents a Debugger:Shutdown event
* when it exits.
@ -30,7 +30,7 @@ exports.createRootActor = function createRootActor(aConnection) {
let parameters = {
tabList: new MobileTabList(aConnection),
addonList: new BrowserAddonList(aConnection),
globalActorFactories: ActorRegistry.globalActorFactories,
globalActorFactories: DebuggerServer.globalActorFactories,
onShutdown: sendShutdownEvent
};
return new RootActor(aConnection, parameters);

View File

@ -34,8 +34,8 @@ module.exports = async function() {
`function () {
const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
const { ActorRegistry } = require("devtools/server/actor-registry");
ActorRegistry.registerModule("chrome://damp/content/tests/server/actor.js", {
const { DebuggerServer } = require("devtools/server/main");
DebuggerServer.registerModule("chrome://damp/content/tests/server/actor.js", {
prefix: "dampTest",
constructor: "DampTestActor",
type: { target: true }

View File

@ -10,7 +10,6 @@ const { DebuggerServer } = require("devtools/server/main");
const { RootActor } = require("devtools/server/actors/root");
const { BrowserTabList } = require("devtools/server/actors/webbrowser");
const Services = require("Services");
const { ActorRegistry } = require("devtools/server/actors/utils/actor-registry");
/**
* xpcshell-test (XPCST) specific actors.
@ -24,7 +23,7 @@ const { ActorRegistry } = require("devtools/server/actors/utils/actor-registry")
function createRootActor(connection) {
let parameters = {
tabList: new XPCSTTabList(connection),
globalActorFactories: ActorRegistry.globalActorFactories,
globalActorFactories: DebuggerServer.globalActorFactories,
onShutdown() {
// If the user never switches to the "debugger" tab we might get a
// shutdown before we've attached.