summaryrefslogtreecommitdiffstats
path: root/devtools/shared/transport/child-transport.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/shared/transport/child-transport.js')
-rw-r--r--devtools/shared/transport/child-transport.js128
1 files changed, 128 insertions, 0 deletions
diff --git a/devtools/shared/transport/child-transport.js b/devtools/shared/transport/child-transport.js
new file mode 100644
index 0000000000..52511432e5
--- /dev/null
+++ b/devtools/shared/transport/child-transport.js
@@ -0,0 +1,128 @@
+/* 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";
+
+const flags = require("resource://devtools/shared/flags.js");
+
+/**
+ * A transport for the debugging protocol that uses nsIMessageManagers to
+ * exchange packets with servers running in child processes.
+ *
+ * In the parent process, |mm| should be the nsIMessageSender for the
+ * child process. In a child process, |mm| should be the child process
+ * message manager, which sends packets to the parent.
+ *
+ * |prefix| is a string included in the message names, to distinguish
+ * multiple servers running in the same child process.
+ *
+ * This transport exchanges messages named 'debug:<prefix>:packet', where
+ * <prefix> is |prefix|, whose data is the protocol packet.
+ */
+function ChildDebuggerTransport(mm, prefix) {
+ this._mm = mm;
+ this._messageName = "debug:" + prefix + ":packet";
+}
+
+/*
+ * To avoid confusion, we use 'message' to mean something that
+ * nsIMessageSender conveys, and 'packet' to mean a remote debugging
+ * protocol packet.
+ */
+ChildDebuggerTransport.prototype = {
+ constructor: ChildDebuggerTransport,
+
+ hooks: null,
+
+ _addListener() {
+ this._mm.addMessageListener(this._messageName, this);
+ },
+
+ _removeListener() {
+ try {
+ this._mm.removeMessageListener(this._messageName, this);
+ } catch (e) {
+ if (e.result != Cr.NS_ERROR_NULL_POINTER) {
+ throw e;
+ }
+ // In some cases, especially when using messageManagers in non-e10s mode, we reach
+ // this point with a dead messageManager which only throws errors but does not
+ // seem to indicate in any other way that it is dead.
+ }
+ },
+
+ ready() {
+ this._addListener();
+ },
+
+ close(options) {
+ this._removeListener();
+ if (this.hooks.onTransportClosed) {
+ this.hooks.onTransportClosed(null, options);
+ }
+ },
+
+ receiveMessage({ data }) {
+ this.hooks.onPacket(data);
+ },
+
+ /**
+ * Helper method to ensure a given `object` can be sent across message manager
+ * without being serialized to JSON.
+ * See https://searchfox.org/mozilla-central/rev/6bfadf95b4a6aaa8bb3b2a166d6c3545983e179a/dom/base/nsFrameMessageManager.cpp#458-469
+ */
+ _canBeSerialized(object) {
+ try {
+ const holder = new StructuredCloneHolder(
+ "ChildDebuggerTransport._canBeSerialized",
+ null,
+ object
+ );
+ holder.deserialize(this);
+ } catch (e) {
+ return false;
+ }
+ return true;
+ },
+
+ pathToUnserializable(object) {
+ for (const key in object) {
+ const value = object[key];
+ if (!this._canBeSerialized(value)) {
+ if (typeof value == "object") {
+ return [key].concat(this.pathToUnserializable(value));
+ }
+ return [key];
+ }
+ }
+ return [];
+ },
+
+ send(packet) {
+ if (flags.testing && !this._canBeSerialized(packet)) {
+ const attributes = this.pathToUnserializable(packet);
+ let msg =
+ "Following packet can't be serialized: " + JSON.stringify(packet);
+ msg += "\nBecause of attributes: " + attributes.join(", ") + "\n";
+ msg += "Did you pass a function or an XPCOM object in it?";
+ throw new Error(msg);
+ }
+ try {
+ this._mm.sendAsyncMessage(this._messageName, packet);
+ } catch (e) {
+ if (e.result != Cr.NS_ERROR_NULL_POINTER) {
+ throw e;
+ }
+ // In some cases, especially when using messageManagers in non-e10s mode, we reach
+ // this point with a dead messageManager which only throws errors but does not
+ // seem to indicate in any other way that it is dead.
+ }
+ },
+
+ startBulkSend() {
+ throw new Error("Can't send bulk data to child processes.");
+ },
+};
+
+exports.ChildDebuggerTransport = ChildDebuggerTransport;