/* 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 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 devtools 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 Pool.manage) * - 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) { thrownew Error( "ActorRegistry.registerModule requires an options argument"
);
} const { prefix, constructor, type } = options; if (typeof prefix !== "string") { thrownew Error(
`Lazy actor definition for'${id}' requires a string ` +
`'prefix' option.`
);
} if (typeof constructor !== "string") { thrownew Error(
`Lazy actor definition for'${id}' requires a string ` +
`'constructor' option.`
);
} if (!("global" in type) && !("target" in type)) { thrownew 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 devtools server.
*/
unregisterModule(id) { const mod = gRegisteredModules[id]; if (!mod) { thrownew 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/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 },
}); /** * Always register parent accessibility actor as a global module. This * actor is responsible for all top level accessibility actor functionality * that relies on the parent process.
*/ this.registerModule( "devtools/server/actors/accessibility/parent-accessibility",
{
prefix: "parentAccessibility",
constructor: "ParentAccessibilityActor",
type: { global: true },
}
);
/** * Registers handlers for new target-scoped request types defined dynamically. * * Note that the name 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;
} deletethis.targetScopedActorFactories[name]; for (const connID of Object.getOwnPropertyNames(this._connections)) { // DevToolsServerConnection 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 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;
} deletethis.globalActorFactories[name]; for (const connID of Object.getOwnPropertyNames(this._connections)) {
// DevToolsServerConnection 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);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.