diff options
Diffstat (limited to 'devtools/server/connectors/content-process-connector.js')
-rw-r--r-- | devtools/server/connectors/content-process-connector.js | 125 |
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; |