1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 * Module that listens for requests to start a `DevToolsServer` for an entire content
7 * process. Loaded into content processes by the main process during
8 * content-process-connector.js' `connectToContentProcess` via the process
9 * script `content-process.js`.
11 * The actual server startup itself is in this JSM so that code can be cached.
14 export function initContentProcessTarget(msg) {
15 const mm = msg.target;
16 const prefix = msg.data.prefix;
17 const watcherActorID = msg.data.watcherActorID;
19 // Lazy load Loader.sys.mjs to prevent loading any devtools dependency too early.
21 useDistinctSystemPrincipalLoader,
22 releaseDistinctSystemPrincipalLoader,
23 } = ChromeUtils.importESModule(
24 "resource://devtools/shared/loader/DistinctSystemPrincipalLoader.sys.mjs",
28 // Use a unique object to identify this one usage of the loader
29 const loaderRequester = {};
31 // Init a custom, invisible DevToolsServer, in order to not pollute the
32 // debugger with all devtools modules, nor break the debugger itself with
33 // using it in the same process.
34 const loader = useDistinctSystemPrincipalLoader(loaderRequester);
36 const { DevToolsServer } = loader.require(
37 "resource://devtools/server/devtools-server.js"
40 DevToolsServer.init();
41 // For browser content toolbox, we do need a regular root actor and all tab
42 // actors, but don't need all the "browser actors" that are only useful when
43 // debugging the parent process via the browser toolbox.
44 DevToolsServer.registerActors({ root: true, target: true });
46 // Connect both parent/child processes devtools servers RDP via message
48 const conn = DevToolsServer.connectToParent(prefix, mm);
50 const { ContentProcessTargetActor } = loader.require(
51 "resource://devtools/server/actors/targets/content-process.js"
54 const actor = new ContentProcessTargetActor(conn, {
55 sessionContext: msg.data.sessionContext,
59 const response = { watcherActorID, prefix, actor: actor.form() };
60 mm.sendAsyncMessage("debug:content-process-actor", response);
62 function onDestroy(options) {
63 mm.removeMessageListener(
64 "debug:content-process-disconnect",
65 onContentProcessDisconnect
67 actor.off("destroyed", onDestroy);
69 // Notify the parent process that the actor is being destroyed
70 mm.sendAsyncMessage("debug:content-process-actor-destroyed", {
74 // Call DevToolsServerConnection.close to destroy all child actors. It should end up
75 // calling DevToolsServerConnection.onTransportClosed that would actually cleanup all actor
79 // Destroy the related loader when the target is destroyed
80 // and we were the last user of the special loader
81 releaseDistinctSystemPrincipalLoader(loaderRequester);
83 function onContentProcessDisconnect(message) {
84 if (message.data.prefix != prefix) {
85 // Several copies of this process script can be running for a single process if
86 // we are debugging the same process from multiple clients.
87 // If this disconnect request doesn't match a connection known here, ignore it.
93 // Clean up things when the client disconnects
94 mm.addMessageListener(
95 "debug:content-process-disconnect",
96 onContentProcessDisconnect
98 // And also when the target actor is destroyed
99 actor.on("destroyed", onDestroy);