tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

child-transport.js (3782B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 const flags = require("resource://devtools/shared/flags.js");
      8 
      9 /**
     10 * A transport for the debugging protocol that uses nsIMessageManagers to
     11 * exchange packets with servers running in child processes.
     12 *
     13 * In the parent process, |mm| should be the nsIMessageSender for the
     14 * child process. In a child process, |mm| should be the child process
     15 * message manager, which sends packets to the parent.
     16 *
     17 * |prefix| is a string included in the message names, to distinguish
     18 * multiple servers running in the same child process.
     19 *
     20 * This transport exchanges messages named 'debug:<prefix>:packet', where
     21 * <prefix> is |prefix|, whose data is the protocol packet.
     22 *
     23 * To avoid confusion, we use 'message' to mean something that
     24 * nsIMessageSender conveys, and 'packet' to mean a remote debugging
     25 * protocol packet.
     26 */
     27 class ChildDebuggerTransport {
     28  constructor(mm, prefix) {
     29    this._mm = mm;
     30    this._messageName = "debug:" + prefix + ":packet";
     31  }
     32 
     33  hooks = null;
     34 
     35  _addListener() {
     36    this._mm.addMessageListener(this._messageName, this);
     37  }
     38 
     39  _removeListener() {
     40    try {
     41      this._mm.removeMessageListener(this._messageName, this);
     42    } catch (e) {
     43      if (e.result != Cr.NS_ERROR_NULL_POINTER) {
     44        throw e;
     45      }
     46      // In some cases, especially when using messageManagers in non-e10s mode, we reach
     47      // this point with a dead messageManager which only throws errors but does not
     48      // seem to indicate in any other way that it is dead.
     49    }
     50  }
     51 
     52  ready() {
     53    this._addListener();
     54  }
     55 
     56  close(options) {
     57    this._removeListener();
     58    if (this.hooks.onTransportClosed) {
     59      this.hooks.onTransportClosed(null, options);
     60    }
     61  }
     62 
     63  receiveMessage({ data }) {
     64    this.hooks.onPacket(data);
     65  }
     66 
     67  /**
     68   * Helper method to ensure a given `object` can be sent across message manager
     69   * without being serialized to JSON.
     70   * See https://searchfox.org/mozilla-central/rev/6bfadf95b4a6aaa8bb3b2a166d6c3545983e179a/dom/base/nsFrameMessageManager.cpp#458-469
     71   */
     72  _canBeSerialized(object) {
     73    try {
     74      const holder = new StructuredCloneHolder(
     75        "ChildDebuggerTransport._canBeSerialized",
     76        null,
     77        object
     78      );
     79      holder.deserialize(this);
     80    } catch (e) {
     81      return false;
     82    }
     83    return true;
     84  }
     85 
     86  pathToUnserializable(object) {
     87    for (const key in object) {
     88      const value = object[key];
     89      if (!this._canBeSerialized(value)) {
     90        if (typeof value == "object") {
     91          return [key].concat(this.pathToUnserializable(value));
     92        }
     93        return [key];
     94      }
     95    }
     96    return [];
     97  }
     98 
     99  send(packet) {
    100    if (flags.testing && !this._canBeSerialized(packet)) {
    101      const attributes = this.pathToUnserializable(packet);
    102      let msg =
    103        "Following packet can't be serialized: " + JSON.stringify(packet);
    104      msg += "\nBecause of attributes: " + attributes.join(", ") + "\n";
    105      msg += "Did you pass a function or an XPCOM object in it?";
    106      throw new Error(msg);
    107    }
    108    try {
    109      this._mm.sendAsyncMessage(this._messageName, packet);
    110    } catch (e) {
    111      if (e.result != Cr.NS_ERROR_NULL_POINTER) {
    112        throw e;
    113      }
    114      // In some cases, especially when using messageManagers in non-e10s mode, we reach
    115      // this point with a dead messageManager which only throws errors but does not
    116      // seem to indicate in any other way that it is dead.
    117    }
    118  }
    119 
    120  startBulkSend() {
    121    throw new Error("Can't send bulk data to child processes.");
    122  }
    123 }
    124 
    125 exports.ChildDebuggerTransport = ChildDebuggerTransport;