summaryrefslogtreecommitdiffstats
path: root/devtools/server/connectors/content-process-connector.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/server/connectors/content-process-connector.js')
-rw-r--r--devtools/server/connectors/content-process-connector.js125
1 files changed, 125 insertions, 0 deletions
diff --git a/devtools/server/connectors/content-process-connector.js b/devtools/server/connectors/content-process-connector.js
new file mode 100644
index 0000000000..ea95a5d6ab
--- /dev/null
+++ b/devtools/server/connectors/content-process-connector.js
@@ -0,0 +1,125 @@
+/* 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 DevToolsUtils = require("resource://devtools/shared/DevToolsUtils.js");
+var { dumpn } = DevToolsUtils;
+var {
+ createContentProcessSessionContext,
+} = require("resource://devtools/server/actors/watcher/session-context.js");
+
+loader.lazyRequireGetter(
+ this,
+ "ChildDebuggerTransport",
+ "resource://devtools/shared/transport/child-transport.js",
+ true
+);
+
+const CONTENT_PROCESS_SERVER_STARTUP_SCRIPT =
+ "resource://devtools/server/startup/content-process.js";
+
+loader.lazyRequireGetter(
+ this,
+ "EventEmitter",
+ "resource://devtools/shared/event-emitter.js"
+);
+
+/**
+ * Start a DevTools server in a content process (representing the entire process, not
+ * just a single frame) and add it as a child server for an active connection.
+ */
+function connectToContentProcess(connection, mm, onDestroy) {
+ return new Promise(resolve => {
+ const prefix = connection.allocID("content-process");
+ let actor, childTransport;
+
+ mm.addMessageListener(
+ "debug:content-process-actor",
+ function listener(msg) {
+ // Ignore actors being created by a Watcher actor,
+ // they will be handled by devtools/server/watcher/target-helpers/process.js
+ if (msg.watcherActorID) {
+ return;
+ }
+ mm.removeMessageListener("debug:content-process-actor", listener);
+
+ // Pipe Debugger message from/to parent/child via the message manager
+ childTransport = new ChildDebuggerTransport(mm, prefix);
+ childTransport.hooks = {
+ onPacket: connection.send.bind(connection),
+ };
+ childTransport.ready();
+
+ connection.setForwarding(prefix, childTransport);
+
+ dumpn(`Start forwarding for process with prefix ${prefix}`);
+
+ actor = msg.json.actor;
+
+ resolve(actor);
+ }
+ );
+
+ // Load the content process server startup script only once.
+ const isContentProcessServerStartupScripLoaded = Services.ppmm
+ .getDelayedProcessScripts()
+ .some(([uri]) => uri === CONTENT_PROCESS_SERVER_STARTUP_SCRIPT);
+ if (!isContentProcessServerStartupScripLoaded) {
+ // Load the process script that will receive the debug:init-content-server message
+ Services.ppmm.loadProcessScript(
+ CONTENT_PROCESS_SERVER_STARTUP_SCRIPT,
+ true
+ );
+ }
+
+ // Send a message to the content process server startup script to forward it the
+ // prefix.
+ mm.sendAsyncMessage("debug:init-content-server", {
+ prefix,
+ // This connector is only used for the Browser Content Toolbox,
+ // when creating the content process target from the Process Descriptor.
+ sessionContext: createContentProcessSessionContext(),
+ });
+
+ function onClose() {
+ Services.obs.removeObserver(
+ onMessageManagerClose,
+ "message-manager-close"
+ );
+ EventEmitter.off(connection, "closed", onClose);
+ if (childTransport) {
+ // If we have a child transport, the actor has already
+ // been created. We need to stop using this message manager.
+ childTransport.close();
+ childTransport = null;
+ connection.cancelForwarding(prefix);
+
+ // ... and notify the child process to clean the target-scoped actors.
+ try {
+ mm.sendAsyncMessage("debug:content-process-disconnect", { prefix });
+ } catch (e) {
+ // Nothing to do
+ }
+ }
+
+ if (onDestroy) {
+ onDestroy(mm);
+ }
+ }
+
+ const onMessageManagerClose = DevToolsUtils.makeInfallible(
+ (subject, topic, data) => {
+ if (subject == mm) {
+ onClose();
+ }
+ }
+ );
+ Services.obs.addObserver(onMessageManagerClose, "message-manager-close");
+
+ EventEmitter.on(connection, "closed", onClose);
+ });
+}
+
+exports.connectToContentProcess = connectToContentProcess;