tor-browser

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

WebSocketTransport.sys.mjs (2936B)


      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 // This is an XPCOM service-ified copy of ../devtools/shared/transport/websocket-transport.js.
      6 
      7 const lazy = {};
      8 
      9 ChromeUtils.defineESModuleGetters(lazy, {
     10  EventEmitter: "resource://gre/modules/EventEmitter.sys.mjs",
     11 });
     12 
     13 export function WebSocketTransport(socket) {
     14  lazy.EventEmitter.decorate(this);
     15 
     16  this.active = false;
     17  this.hooks = null;
     18  this.socket = socket;
     19 }
     20 
     21 WebSocketTransport.prototype = {
     22  ready() {
     23    if (this.active) {
     24      return;
     25    }
     26 
     27    this.socket.addEventListener("message", this);
     28    this.socket.addEventListener("close", this);
     29 
     30    this.active = true;
     31  },
     32 
     33  send(object) {
     34    this.emit("send", object);
     35    if (this.socket) {
     36      this.socket.send(JSON.stringify(object));
     37    }
     38  },
     39 
     40  startBulkSend() {
     41    throw new Error("Bulk send is not supported by WebSocket transport");
     42  },
     43 
     44  /**
     45   * Force closing the active connection and WebSocket.
     46   */
     47  close() {
     48    if (!this.socket) {
     49      return;
     50    }
     51    this.emit("close");
     52 
     53    if (this.hooks) {
     54      this.hooks.onConnectionClose();
     55    }
     56 
     57    this.active = false;
     58 
     59    this.socket.removeEventListener("message", this);
     60 
     61    // Remove the listener that is used when the connection
     62    // is closed because we already emitted the 'close' event.
     63    // Instead listen for the closing of the WebSocket.
     64    this.socket.removeEventListener("close", this);
     65    this.socket.addEventListener("close", this.onSocketClose.bind(this));
     66 
     67    // Close socket with code `1000` for a normal closure.
     68    this.socket.close(1000);
     69  },
     70 
     71  /**
     72   * Callback for socket on close event,
     73   * it is used in case websocket was closed by the client.
     74   */
     75  onClose() {
     76    if (!this.socket) {
     77      return;
     78    }
     79    this.emit("close");
     80 
     81    if (this.hooks) {
     82      this.hooks.onConnectionClose();
     83      this.hooks.onSocketClose();
     84      this.hooks = null;
     85    }
     86 
     87    this.active = false;
     88 
     89    this.socket.removeEventListener("message", this);
     90    this.socket.removeEventListener("close", this);
     91    this.socket = null;
     92  },
     93 
     94  /**
     95   * Callback which is called when we can be sure that websocket is closed.
     96   */
     97  onSocketClose() {
     98    this.socket = null;
     99 
    100    if (this.hooks) {
    101      this.hooks.onSocketClose();
    102      this.hooks = null;
    103    }
    104  },
    105 
    106  handleEvent(event) {
    107    switch (event.type) {
    108      case "message":
    109        this.onMessage(event);
    110        break;
    111      case "close":
    112        this.onClose();
    113        break;
    114    }
    115  },
    116 
    117  onMessage({ data }) {
    118    if (typeof data !== "string") {
    119      throw new Error(
    120        "Binary messages are not supported by WebSocket transport"
    121      );
    122    }
    123 
    124    const object = JSON.parse(data);
    125    this.emit("packet", object);
    126    if (this.hooks) {
    127      this.hooks.onPacket(object);
    128    }
    129  },
    130 };