Bug 1000814 - Move ChildDebuggerTransport to its own module. r=jryans draft
authorAlexandre Poirot <poirot.alex@gmail.com>
Wed, 11 Jul 2018 08:38:53 -0700
changeset 817215 f39cf0c5198341ba0aaf68004c1a1470706a6132
parent 817214 eb0803140ac65afee9a4cd3ae5323f7e80662a7d
child 817216 0a540c2a59ed486320544a81f890742756631f8f
push id115987
push userbmo:poirot.alex@gmail.com
push dateThu, 12 Jul 2018 07:12:00 +0000
reviewersjryans
bugs1000814
milestone63.0a1
Bug 1000814 - Move ChildDebuggerTransport to its own module. r=jryans MozReview-Commit-ID: FgTVee7NLyC
devtools/server/main.js
devtools/shared/transport/child-transport.js
devtools/shared/transport/moz.build
devtools/shared/transport/transport.js
--- a/devtools/server/main.js
+++ b/devtools/server/main.js
@@ -7,24 +7,25 @@
 /**
  * Toolkit glue for the remote debugging protocol, loaded into the
  * debugging global.
  */
 var { Ci, Cc } = require("chrome");
 var Services = require("Services");
 var { ActorPool, OriginalLocation, RegisteredActorFactory,
       ObservedActorFactory } = require("devtools/server/actors/common");
-var { ChildDebuggerTransport, WorkerDebuggerTransport } =
+var { WorkerDebuggerTransport } =
   require("devtools/shared/transport/transport");
 var DevToolsUtils = require("devtools/shared/DevToolsUtils");
 var { dumpn } = DevToolsUtils;
 
 loader.lazyRequireGetter(this, "DebuggerSocket", "devtools/shared/security/socket", true);
 loader.lazyRequireGetter(this, "Authentication", "devtools/shared/security/auth");
 loader.lazyRequireGetter(this, "LocalDebuggerTransport", "devtools/shared/transport/local-transport", true);
+loader.lazyRequireGetter(this, "ChildDebuggerTransport", "devtools/shared/transport/child-transport", true);
 
 loader.lazyGetter(this, "generateUUID", () => {
   // eslint-disable-next-line no-shadow
   const { generateUUID } = Cc["@mozilla.org/uuid-generator;1"]
                            .getService(Ci.nsIUUIDGenerator);
   return generateUUID;
 });
 
copy from devtools/shared/transport/transport.js
copy to devtools/shared/transport/child-transport.js
--- a/devtools/shared/transport/transport.js
+++ b/devtools/shared/transport/child-transport.js
@@ -1,493 +1,16 @@
 /* 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";
 
-/* global uneval */
-
-const { Cc, Cr, CC } = require("chrome");
-const DevToolsUtils = require("devtools/shared/DevToolsUtils");
-const { dumpn, dumpv } = DevToolsUtils;
+const { Cr } = require("chrome");
 const flags = require("devtools/shared/flags");
-const StreamUtils = require("devtools/shared/transport/stream-utils");
-const { Packet, JSONPacket, BulkPacket } =
-  require("devtools/shared/transport/packets");
-
-loader.lazyGetter(this, "ScriptableInputStream", () => {
-  return CC("@mozilla.org/scriptableinputstream;1",
-          "nsIScriptableInputStream", "init");
-});
-
-const PACKET_HEADER_MAX = 200;
-
-/**
- * An adapter that handles data transfers between the debugger client and
- * server. It can work with both nsIPipe and nsIServerSocket transports so
- * long as the properly created input and output streams are specified.
- * (However, for intra-process connections, LocalDebuggerTransport, below,
- * is more efficient than using an nsIPipe pair with DebuggerTransport.)
- *
- * @param input nsIAsyncInputStream
- *        The input stream.
- * @param output nsIAsyncOutputStream
- *        The output stream.
- *
- * Given a DebuggerTransport instance dt:
- * 1) Set dt.hooks to a packet handler object (described below).
- * 2) Call dt.ready() to begin watching for input packets.
- * 3) Call dt.send() / dt.startBulkSend() to send packets.
- * 4) Call dt.close() to close the connection, and disengage from the event
- *    loop.
- *
- * A packet handler is an object with the following methods:
- *
- * - onPacket(packet) - called when we have received a complete packet.
- *   |packet| is the parsed form of the packet --- a JavaScript value, not
- *   a JSON-syntax string.
- *
- * - onBulkPacket(packet) - called when we have switched to bulk packet
- *   receiving mode. |packet| is an object containing:
- *   * actor:  Name of actor that will receive the packet
- *   * type:   Name of actor's method that should be called on receipt
- *   * length: Size of the data to be read
- *   * stream: This input stream should only be used directly if you can ensure
- *             that you will read exactly |length| bytes and will not close the
- *             stream when reading is complete
- *   * done:   If you use the stream directly (instead of |copyTo| below), you
- *             must signal completion by resolving / rejecting this deferred.
- *             If it's rejected, the transport will be closed.  If an Error is
- *             supplied as a rejection value, it will be logged via |dumpn|.
- *             If you do use |copyTo|, resolving is taken care of for you when
- *             copying completes.
- *   * copyTo: A helper function for getting your data out of the stream that
- *             meets the stream handling requirements above, and has the
- *             following signature:
- *     @param  output nsIAsyncOutputStream
- *             The stream to copy to.
- *     @return Promise
- *             The promise is resolved when copying completes or rejected if any
- *             (unexpected) errors occur.
- *             This object also emits "progress" events for each chunk that is
- *             copied.  See stream-utils.js.
- *
- * - onClosed(reason) - called when the connection is closed. |reason| is
- *   an optional nsresult or object, typically passed when the transport is
- *   closed due to some error in a underlying stream.
- *
- * See ./packets.js and the Remote Debugging Protocol specification for more
- * details on the format of these packets.
- */
-function DebuggerTransport(input, output) {
-  this._input = input;
-  this._scriptableInput = new ScriptableInputStream(input);
-  this._output = output;
-
-  // The current incoming (possibly partial) header, which will determine which
-  // type of Packet |_incoming| below will become.
-  this._incomingHeader = "";
-  // The current incoming Packet object
-  this._incoming = null;
-  // A queue of outgoing Packet objects
-  this._outgoing = [];
-
-  this.hooks = null;
-  this.active = false;
-
-  this._incomingEnabled = true;
-  this._outgoingEnabled = true;
-
-  this.close = this.close.bind(this);
-}
-
-DebuggerTransport.prototype = {
-  /**
-   * Transmit an object as a JSON packet.
-   *
-   * This method returns immediately, without waiting for the entire
-   * packet to be transmitted, registering event handlers as needed to
-   * transmit the entire packet. Packets are transmitted in the order
-   * they are passed to this method.
-   */
-  send: function(object) {
-    const packet = new JSONPacket(this);
-    packet.object = object;
-    this._outgoing.push(packet);
-    this._flushOutgoing();
-  },
-
-  /**
-   * Transmit streaming data via a bulk packet.
-   *
-   * This method initiates the bulk send process by queuing up the header data.
-   * The caller receives eventual access to a stream for writing.
-   *
-   * N.B.: Do *not* attempt to close the stream handed to you, as it will
-   * continue to be used by this transport afterwards.  Most users should
-   * instead use the provided |copyFrom| function instead.
-   *
-   * @param header Object
-   *        This is modeled after the format of JSON packets above, but does not
-   *        actually contain the data, but is instead just a routing header:
-   *          * actor:  Name of actor that will receive the packet
-   *          * type:   Name of actor's method that should be called on receipt
-   *          * length: Size of the data to be sent
-   * @return Promise
-   *         The promise will be resolved when you are allowed to write to the
-   *         stream with an object containing:
-   *           * stream:   This output stream should only be used directly if
-   *                       you can ensure that you will write exactly |length|
-   *                       bytes and will not close the stream when writing is
-   *                       complete
-   *           * done:     If you use the stream directly (instead of |copyFrom|
-   *                       below), you must signal completion by resolving /
-   *                       rejecting this deferred.  If it's rejected, the
-   *                       transport will be closed.  If an Error is supplied as
-   *                       a rejection value, it will be logged via |dumpn|.  If
-   *                       you do use |copyFrom|, resolving is taken care of for
-   *                       you when copying completes.
-   *           * copyFrom: A helper function for getting your data onto the
-   *                       stream that meets the stream handling requirements
-   *                       above, and has the following signature:
-   *             @param  input nsIAsyncInputStream
-   *                     The stream to copy from.
-   *             @return Promise
-   *                     The promise is resolved when copying completes or
-   *                     rejected if any (unexpected) errors occur.
-   *                     This object also emits "progress" events for each chunk
-   *                     that is copied.  See stream-utils.js.
-   */
-  startBulkSend: function(header) {
-    const packet = new BulkPacket(this);
-    packet.header = header;
-    this._outgoing.push(packet);
-    this._flushOutgoing();
-    return packet.streamReadyForWriting;
-  },
-
-  /**
-   * Close the transport.
-   * @param reason nsresult / object (optional)
-   *        The status code or error message that corresponds to the reason for
-   *        closing the transport (likely because a stream closed or failed).
-   */
-  close: function(reason) {
-    this.active = false;
-    this._input.close();
-    this._scriptableInput.close();
-    this._output.close();
-    this._destroyIncoming();
-    this._destroyAllOutgoing();
-    if (this.hooks) {
-      this.hooks.onClosed(reason);
-      this.hooks = null;
-    }
-    if (reason) {
-      dumpn("Transport closed: " + DevToolsUtils.safeErrorString(reason));
-    } else {
-      dumpn("Transport closed.");
-    }
-  },
-
-  /**
-   * The currently outgoing packet (at the top of the queue).
-   */
-  get _currentOutgoing() {
-    return this._outgoing[0];
-  },
-
-  /**
-   * Flush data to the outgoing stream.  Waits until the output stream notifies
-   * us that it is ready to be written to (via onOutputStreamReady).
-   */
-  _flushOutgoing: function() {
-    if (!this._outgoingEnabled || this._outgoing.length === 0) {
-      return;
-    }
-
-    // If the top of the packet queue has nothing more to send, remove it.
-    if (this._currentOutgoing.done) {
-      this._finishCurrentOutgoing();
-    }
-
-    if (this._outgoing.length > 0) {
-      const threadManager = Cc["@mozilla.org/thread-manager;1"].getService();
-      this._output.asyncWait(this, 0, 0, threadManager.currentThread);
-    }
-  },
-
-  /**
-   * Pause this transport's attempts to write to the output stream.  This is
-   * used when we've temporarily handed off our output stream for writing bulk
-   * data.
-   */
-  pauseOutgoing: function() {
-    this._outgoingEnabled = false;
-  },
-
-  /**
-   * Resume this transport's attempts to write to the output stream.
-   */
-  resumeOutgoing: function() {
-    this._outgoingEnabled = true;
-    this._flushOutgoing();
-  },
-
-  // nsIOutputStreamCallback
-  /**
-   * This is called when the output stream is ready for more data to be written.
-   * The current outgoing packet will attempt to write some amount of data, but
-   * may not complete.
-   */
-  onOutputStreamReady: DevToolsUtils.makeInfallible(function(stream) {
-    if (!this._outgoingEnabled || this._outgoing.length === 0) {
-      return;
-    }
-
-    try {
-      this._currentOutgoing.write(stream);
-    } catch (e) {
-      if (e.result != Cr.NS_BASE_STREAM_WOULD_BLOCK) {
-        this.close(e.result);
-        return;
-      }
-      throw e;
-    }
-
-    this._flushOutgoing();
-  }, "DebuggerTransport.prototype.onOutputStreamReady"),
-
-  /**
-   * Remove the current outgoing packet from the queue upon completion.
-   */
-  _finishCurrentOutgoing: function() {
-    if (this._currentOutgoing) {
-      this._currentOutgoing.destroy();
-      this._outgoing.shift();
-    }
-  },
-
-  /**
-   * Clear the entire outgoing queue.
-   */
-  _destroyAllOutgoing: function() {
-    for (const packet of this._outgoing) {
-      packet.destroy();
-    }
-    this._outgoing = [];
-  },
-
-  /**
-   * Initialize the input stream for reading. Once this method has been called,
-   * we watch for packets on the input stream, and pass them to the appropriate
-   * handlers via this.hooks.
-   */
-  ready: function() {
-    this.active = true;
-    this._waitForIncoming();
-  },
-
-  /**
-   * Asks the input stream to notify us (via onInputStreamReady) when it is
-   * ready for reading.
-   */
-  _waitForIncoming: function() {
-    if (this._incomingEnabled) {
-      const threadManager = Cc["@mozilla.org/thread-manager;1"].getService();
-      this._input.asyncWait(this, 0, 0, threadManager.currentThread);
-    }
-  },
-
-  /**
-   * Pause this transport's attempts to read from the input stream.  This is
-   * used when we've temporarily handed off our input stream for reading bulk
-   * data.
-   */
-  pauseIncoming: function() {
-    this._incomingEnabled = false;
-  },
-
-  /**
-   * Resume this transport's attempts to read from the input stream.
-   */
-  resumeIncoming: function() {
-    this._incomingEnabled = true;
-    this._flushIncoming();
-    this._waitForIncoming();
-  },
-
-  // nsIInputStreamCallback
-  /**
-   * Called when the stream is either readable or closed.
-   */
-  onInputStreamReady: DevToolsUtils.makeInfallible(function(stream) {
-    try {
-      while (stream.available() && this._incomingEnabled &&
-             this._processIncoming(stream, stream.available())) {
-         // Loop until there is nothing more to process
-      }
-      this._waitForIncoming();
-    } catch (e) {
-      if (e.result != Cr.NS_BASE_STREAM_WOULD_BLOCK) {
-        this.close(e.result);
-      } else {
-        throw e;
-      }
-    }
-  }, "DebuggerTransport.prototype.onInputStreamReady"),
-
-  /**
-   * Process the incoming data.  Will create a new currently incoming Packet if
-   * needed.  Tells the incoming Packet to read as much data as it can, but
-   * reading may not complete.  The Packet signals that its data is ready for
-   * delivery by calling one of this transport's _on*Ready methods (see
-   * ./packets.js and the _on*Ready methods below).
-   * @return boolean
-   *         Whether incoming stream processing should continue for any
-   *         remaining data.
-   */
-  _processIncoming: function(stream, count) {
-    dumpv("Data available: " + count);
-
-    if (!count) {
-      dumpv("Nothing to read, skipping");
-      return false;
-    }
-
-    try {
-      if (!this._incoming) {
-        dumpv("Creating a new packet from incoming");
-
-        if (!this._readHeader(stream)) {
-          // Not enough data to read packet type
-          return false;
-        }
-
-        // Attempt to create a new Packet by trying to parse each possible
-        // header pattern.
-        this._incoming = Packet.fromHeader(this._incomingHeader, this);
-        if (!this._incoming) {
-          throw new Error("No packet types for header: " +
-                        this._incomingHeader);
-        }
-      }
-
-      if (!this._incoming.done) {
-        // We have an incomplete packet, keep reading it.
-        dumpv("Existing packet incomplete, keep reading");
-        this._incoming.read(stream, this._scriptableInput);
-      }
-    } catch (e) {
-      const msg = "Error reading incoming packet: (" + e + " - " + e.stack + ")";
-      dumpn(msg);
-
-      // Now in an invalid state, shut down the transport.
-      this.close();
-      return false;
-    }
-
-    if (!this._incoming.done) {
-      // Still not complete, we'll wait for more data.
-      dumpv("Packet not done, wait for more");
-      return true;
-    }
-
-    // Ready for next packet
-    this._flushIncoming();
-    return true;
-  },
-
-  /**
-   * Read as far as we can into the incoming data, attempting to build up a
-   * complete packet header (which terminates with ":").  We'll only read up to
-   * PACKET_HEADER_MAX characters.
-   * @return boolean
-   *         True if we now have a complete header.
-   */
-  _readHeader: function() {
-    const amountToRead = PACKET_HEADER_MAX - this._incomingHeader.length;
-    this._incomingHeader +=
-    StreamUtils.delimitedRead(this._scriptableInput, ":", amountToRead);
-    if (flags.wantVerbose) {
-      dumpv("Header read: " + this._incomingHeader);
-    }
-
-    if (this._incomingHeader.endsWith(":")) {
-      if (flags.wantVerbose) {
-        dumpv("Found packet header successfully: " + this._incomingHeader);
-      }
-      return true;
-    }
-
-    if (this._incomingHeader.length >= PACKET_HEADER_MAX) {
-      throw new Error("Failed to parse packet header!");
-    }
-
-    // Not enough data yet.
-    return false;
-  },
-
-  /**
-   * If the incoming packet is done, log it as needed and clear the buffer.
-   */
-  _flushIncoming: function() {
-    if (!this._incoming.done) {
-      return;
-    }
-    if (flags.wantLogging) {
-      dumpn("Got: " + this._incoming);
-    }
-    this._destroyIncoming();
-  },
-
-  /**
-   * Handler triggered by an incoming JSONPacket completing it's |read| method.
-   * Delivers the packet to this.hooks.onPacket.
-   */
-  _onJSONObjectReady: function(object) {
-    DevToolsUtils.executeSoon(DevToolsUtils.makeInfallible(() => {
-    // Ensure the transport is still alive by the time this runs.
-      if (this.active) {
-        this.hooks.onPacket(object);
-      }
-    }, "DebuggerTransport instance's this.hooks.onPacket"));
-  },
-
-  /**
-   * Handler triggered by an incoming BulkPacket entering the |read| phase for
-   * the stream portion of the packet.  Delivers info about the incoming
-   * streaming data to this.hooks.onBulkPacket.  See the main comment on the
-   * transport at the top of this file for more details.
-   */
-  _onBulkReadReady: function(...args) {
-    DevToolsUtils.executeSoon(DevToolsUtils.makeInfallible(() => {
-    // Ensure the transport is still alive by the time this runs.
-      if (this.active) {
-        this.hooks.onBulkPacket(...args);
-      }
-    }, "DebuggerTransport instance's this.hooks.onBulkPacket"));
-  },
-
-  /**
-   * Remove all handlers and references related to the current incoming packet,
-   * either because it is now complete or because the transport is closing.
-   */
-  _destroyIncoming: function() {
-    if (this._incoming) {
-      this._incoming.destroy();
-    }
-    this._incomingHeader = "";
-    this._incoming = null;
-  }
-
-};
-
-exports.DebuggerTransport = DebuggerTransport;
 
 /**
  * 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.
@@ -598,126 +121,8 @@ ChildDebuggerTransport.prototype = {
   swapBrowser(mm) {
     this._removeListener();
     this._mm = mm;
     this._addListener();
   },
 };
 
 exports.ChildDebuggerTransport = ChildDebuggerTransport;
-
-// WorkerDebuggerTransport is defined differently depending on whether we are
-// on the main thread or a worker thread. In the former case, we are required
-// by the devtools loader, and isWorker will be false. Otherwise, we are
-// required by the worker loader, and isWorker will be true.
-//
-// Each worker debugger supports only a single connection to the main thread.
-// However, its theoretically possible for multiple servers to connect to the
-// same worker. Consequently, each transport has a connection id, to allow
-// messages from multiple connections to be multiplexed on a single channel.
-
-if (!this.isWorker) {
-  // Main thread
-  (function() {
-    /**
-     * A transport that uses a WorkerDebugger to send packets from the main
-     * thread to a worker thread.
-     */
-    function WorkerDebuggerTransport(dbg, id) {
-      this._dbg = dbg;
-      this._id = id;
-      this.onMessage = this._onMessage.bind(this);
-    }
-
-    WorkerDebuggerTransport.prototype = {
-      constructor: WorkerDebuggerTransport,
-
-      ready: function() {
-        this._dbg.addListener(this);
-      },
-
-      close: function() {
-        this._dbg.removeListener(this);
-        if (this.hooks) {
-          this.hooks.onClosed();
-        }
-      },
-
-      send: function(packet) {
-        this._dbg.postMessage(JSON.stringify({
-          type: "message",
-          id: this._id,
-          message: packet
-        }));
-      },
-
-      startBulkSend: function() {
-        throw new Error("Can't send bulk data from worker threads!");
-      },
-
-      _onMessage: function(message) {
-        const packet = JSON.parse(message);
-        if (packet.type !== "message" || packet.id !== this._id) {
-          return;
-        }
-
-        if (this.hooks) {
-          this.hooks.onPacket(packet.message);
-        }
-      }
-    };
-
-    exports.WorkerDebuggerTransport = WorkerDebuggerTransport;
-  }).call(this);
-} else {
-  // Worker thread
-  (function() {
-    /**
-     * A transport that uses a WorkerDebuggerGlobalScope to send packets from a
-     * worker thread to the main thread.
-     */
-    function WorkerDebuggerTransport(scope, id) {
-      this._scope = scope;
-      this._id = id;
-      this._onMessage = this._onMessage.bind(this);
-    }
-
-    WorkerDebuggerTransport.prototype = {
-      constructor: WorkerDebuggerTransport,
-
-      ready: function() {
-        this._scope.addEventListener("message", this._onMessage);
-      },
-
-      close: function() {
-        this._scope.removeEventListener("message", this._onMessage);
-        if (this.hooks) {
-          this.hooks.onClosed();
-        }
-      },
-
-      send: function(packet) {
-        this._scope.postMessage(JSON.stringify({
-          type: "message",
-          id: this._id,
-          message: packet
-        }));
-      },
-
-      startBulkSend: function() {
-        throw new Error("Can't send bulk data from worker threads!");
-      },
-
-      _onMessage: function(event) {
-        const packet = JSON.parse(event.data);
-        if (packet.type !== "message" || packet.id !== this._id) {
-          return;
-        }
-
-        if (this.hooks) {
-          this.hooks.onPacket(packet.message);
-        }
-      }
-    };
-
-    exports.WorkerDebuggerTransport = WorkerDebuggerTransport;
-  }).call(this);
-}
--- a/devtools/shared/transport/moz.build
+++ b/devtools/shared/transport/moz.build
@@ -2,14 +2,15 @@
 # vim: set filetype=python:
 # 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/.
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
 
 DevToolsModules(
+    'child-transport.js',
     'local-transport.js',
     'packets.js',
     'stream-utils.js',
     'transport.js',
     'websocket-transport.js',
 )
--- a/devtools/shared/transport/transport.js
+++ b/devtools/shared/transport/transport.js
@@ -479,136 +479,16 @@ DebuggerTransport.prototype = {
     this._incomingHeader = "";
     this._incoming = null;
   }
 
 };
 
 exports.DebuggerTransport = DebuggerTransport;
 
-/**
- * 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: function() {
-    this._addListener();
-  },
-
-  close: function() {
-    this._removeListener();
-    this.hooks.onClosed();
-  },
-
-  receiveMessage: function({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: function(object) {
-    try {
-      const holder = new StructuredCloneHolder(object);
-      holder.deserialize(this);
-    } catch (e) {
-      return false;
-    }
-    return true;
-  },
-
-  pathToUnserializable: function(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: function(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: function() {
-    throw new Error("Can't send bulk data to child processes.");
-  },
-
-  swapBrowser(mm) {
-    this._removeListener();
-    this._mm = mm;
-    this._addListener();
-  },
-};
-
-exports.ChildDebuggerTransport = ChildDebuggerTransport;
-
 // WorkerDebuggerTransport is defined differently depending on whether we are
 // on the main thread or a worker thread. In the former case, we are required
 // by the devtools loader, and isWorker will be false. Otherwise, we are
 // required by the worker loader, and isWorker will be true.
 //
 // Each worker debugger supports only a single connection to the main thread.
 // However, its theoretically possible for multiple servers to connect to the
 // same worker. Consequently, each transport has a connection id, to allow