summaryrefslogtreecommitdiffstats
path: root/devtools/server/startup/content-process.sys.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/server/startup/content-process.sys.mjs')
-rw-r--r--devtools/server/startup/content-process.sys.mjs104
1 files changed, 104 insertions, 0 deletions
diff --git a/devtools/server/startup/content-process.sys.mjs b/devtools/server/startup/content-process.sys.mjs
new file mode 100644
index 0000000000..fd974e8c4a
--- /dev/null
+++ b/devtools/server/startup/content-process.sys.mjs
@@ -0,0 +1,104 @@
+/* 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/. */
+
+/*
+ * Module that listens for requests to start a `DevToolsServer` for an entire content
+ * process. Loaded into content processes by the main process during
+ * content-process-connector.js' `connectToContentProcess` via the process
+ * script `content-process.js`.
+ *
+ * The actual server startup itself is in this JSM so that code can be cached.
+ */
+
+export function initContentProcessTarget(msg) {
+ const mm = msg.target;
+ const prefix = msg.data.prefix;
+ const watcherActorID = msg.data.watcherActorID;
+
+ // Lazy load Loader.sys.mjs to prevent loading any devtools dependency too early.
+ const {
+ useDistinctSystemPrincipalLoader,
+ releaseDistinctSystemPrincipalLoader,
+ } = ChromeUtils.importESModule(
+ "resource://devtools/shared/loader/DistinctSystemPrincipalLoader.sys.mjs"
+ );
+
+ // Use a unique object to identify this one usage of the loader
+ const loaderRequester = {};
+
+ // Init a custom, invisible DevToolsServer, in order to not pollute the
+ // debugger with all devtools modules, nor break the debugger itself with
+ // using it in the same process.
+ const loader = useDistinctSystemPrincipalLoader(loaderRequester);
+
+ const { DevToolsServer } = loader.require(
+ "resource://devtools/server/devtools-server.js"
+ );
+
+ DevToolsServer.init();
+ // For browser content toolbox, we do need a regular root actor and all tab
+ // actors, but don't need all the "browser actors" that are only useful when
+ // debugging the parent process via the browser toolbox.
+ DevToolsServer.registerActors({ root: true, target: true });
+
+ // Connect both parent/child processes devtools servers RDP via message
+ // managers
+ const conn = DevToolsServer.connectToParent(prefix, mm);
+
+ const { ContentProcessTargetActor } = loader.require(
+ "resource://devtools/server/actors/targets/content-process.js"
+ );
+
+ const actor = new ContentProcessTargetActor(conn, {
+ sessionContext: msg.data.sessionContext,
+ });
+ actor.manage(actor);
+
+ const response = { watcherActorID, prefix, actor: actor.form() };
+ mm.sendAsyncMessage("debug:content-process-actor", response);
+
+ function onDestroy(options) {
+ mm.removeMessageListener(
+ "debug:content-process-disconnect",
+ onContentProcessDisconnect
+ );
+ actor.off("destroyed", onDestroy);
+
+ // Notify the parent process that the actor is being destroyed
+ mm.sendAsyncMessage("debug:content-process-actor-destroyed", {
+ watcherActorID,
+ });
+
+ // Call DevToolsServerConnection.close to destroy all child actors. It should end up
+ // calling DevToolsServerConnection.onTransportClosed that would actually cleanup all actor
+ // pools.
+ conn.close(options);
+
+ // Destroy the related loader when the target is destroyed
+ // and we were the last user of the special loader
+ releaseDistinctSystemPrincipalLoader(loaderRequester);
+ }
+ function onContentProcessDisconnect(message) {
+ if (message.data.prefix != prefix) {
+ // Several copies of this process script can be running for a single process if
+ // we are debugging the same process from multiple clients.
+ // If this disconnect request doesn't match a connection known here, ignore it.
+ return;
+ }
+ onDestroy();
+ }
+
+ // Clean up things when the client disconnects
+ mm.addMessageListener(
+ "debug:content-process-disconnect",
+ onContentProcessDisconnect
+ );
+ // And also when the target actor is destroyed
+ actor.on("destroyed", onDestroy);
+
+ return {
+ actor,
+ connection: conn,
+ };
+}