summaryrefslogtreecommitdiffstats
path: root/devtools/server/startup/content-process.jsm
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--devtools/server/startup/content-process.jsm110
1 files changed, 110 insertions, 0 deletions
diff --git a/devtools/server/startup/content-process.jsm b/devtools/server/startup/content-process.jsm
new file mode 100644
index 0000000000..c54e8d2048
--- /dev/null
+++ b/devtools/server/startup/content-process.jsm
@@ -0,0 +1,110 @@
+/* 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";
+
+/*
+ * 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.
+ */
+
+/* exported initContentProcessTarget */
+const EXPORTED_SYMBOLS = ["initContentProcessTarget"];
+
+let gLoader;
+
+function setupServer(mm) {
+ // Prevent spawning multiple server per process, even if the caller call us
+ // multiple times
+ if (gLoader) {
+ return gLoader;
+ }
+
+ // Lazy load Loader.jsm to prevent loading any devtools dependency too early.
+ const { DevToolsLoader } = ChromeUtils.import(
+ "resource://devtools/shared/Loader.jsm"
+ );
+
+ // 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.
+ gLoader = new DevToolsLoader({
+ invisibleToDebugger: true,
+ });
+ const { DevToolsServer } = gLoader.require("devtools/server/devtools-server");
+
+ 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 });
+
+ // Destroy the server once its last connection closes. Note that multiple frame
+ // scripts may be running in parallel and reuse the same server.
+ function destroyServer() {
+ // Only destroy the server if there is no more connections to it. It may be used
+ // to debug the same process from another client.
+ if (DevToolsServer.hasConnection()) {
+ return;
+ }
+ DevToolsServer.off("connectionchange", destroyServer);
+
+ DevToolsServer.destroy();
+ gLoader.destroy();
+ gLoader = null;
+ }
+ DevToolsServer.on("connectionchange", destroyServer);
+
+ return gLoader;
+}
+
+function initContentProcessTarget(msg) {
+ const mm = msg.target;
+ const prefix = msg.data.prefix;
+ const watcherActorID = msg.data.watcherActorID;
+
+ // Setup a server if none started yet
+ const loader = setupServer(mm);
+
+ // Connect both parent/child processes devtools servers RDP via message
+ // managers
+ const { DevToolsServer } = loader.require("devtools/server/devtools-server");
+ const conn = DevToolsServer.connectToParent(prefix, mm);
+ conn.parentMessageManager = mm;
+
+ const { ContentProcessTargetActor } = loader.require(
+ "devtools/server/actors/targets/content-process"
+ );
+ const actor = new ContentProcessTargetActor(conn);
+ actor.manage(actor);
+
+ const response = { watcherActorID, prefix, actor: actor.form() };
+ mm.sendAsyncMessage("debug:content-process-actor", response);
+
+ // Clean up things when the client disconnects
+ mm.addMessageListener("debug:content-process-disconnect", function onDestroy(
+ 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;
+ }
+ mm.removeMessageListener("debug:content-process-disconnect", onDestroy);
+
+ // Call DevToolsServerConnection.close to destroy all child actors. It should end up
+ // calling DevToolsServerConnection.onClosed that would actually cleanup all actor
+ // pools.
+ conn.close();
+ });
+ return {
+ actor,
+ connection: conn,
+ };
+}