tor-browser

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

remote-client-manager.js (4101B)


      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 {
      8  CONNECTION_TYPES,
      9 } = require("resource://devtools/client/shared/remote-debugging/constants.js");
     10 
     11 /**
     12 * This class is designed to be a singleton shared by all DevTools to get access to
     13 * existing clients created for remote debugging.
     14 */
     15 class RemoteClientManager {
     16  constructor() {
     17    this._clients = new Map();
     18    this._runtimeInfoMap = new Map();
     19    this._onClientClosed = this._onClientClosed.bind(this);
     20  }
     21 
     22  /**
     23   * Store a remote client that is already connected.
     24   *
     25   * @param {string} id
     26   *        Remote runtime id (see devtools/client/aboutdebugging/src/types).
     27   * @param {string} type
     28   *        Remote runtime type (see devtools/client/aboutdebugging/src/types).
     29   * @param {DevToolsClient} client
     30   * @param {object} runtimeInfo
     31   *        See runtimeInfo type from client/aboutdebugging/src/types/runtime.js
     32   */
     33  setClient(id, type, client, runtimeInfo) {
     34    const key = this._getKey(id, type);
     35    this._clients.set(key, client);
     36    if (runtimeInfo) {
     37      this._runtimeInfoMap.set(key, runtimeInfo);
     38    }
     39    client.once("closed", this._onClientClosed);
     40  }
     41 
     42  // See JSDoc for id, type from setClient.
     43  hasClient(id, type) {
     44    return this._clients.has(this._getKey(id, type));
     45  }
     46 
     47  // See JSDoc for id, type from setClient.
     48  getClient(id, type) {
     49    return this._clients.get(this._getKey(id, type));
     50  }
     51 
     52  // See JSDoc for id, type from setClient.
     53  removeClient(id, type) {
     54    const key = this._getKey(id, type);
     55    this._removeClientByKey(key);
     56  }
     57 
     58  removeAllClients() {
     59    const keys = [...this._clients.keys()];
     60    for (const key of keys) {
     61      this._removeClientByKey(key);
     62    }
     63  }
     64 
     65  /**
     66   * Retrieve a unique, url-safe key based on a runtime id and type.
     67   */
     68  getRemoteId(id, type) {
     69    return encodeURIComponent(this._getKey(id, type));
     70  }
     71 
     72  /**
     73   * Retrieve a managed client for a remote id. The remote id should have been generated
     74   * using getRemoteId.
     75   */
     76  getClientByRemoteId(remoteId) {
     77    const key = this._getKeyByRemoteId(remoteId);
     78    return this._clients.get(key);
     79  }
     80 
     81  /**
     82   * Retrieve the runtime info for a remote id. To display metadata about a runtime, such
     83   * as name, device name, version... this runtimeInfo should be used rather than calling
     84   * APIs on the client.
     85   */
     86  getRuntimeInfoByRemoteId(remoteId) {
     87    const key = this._getKeyByRemoteId(remoteId);
     88    return this._runtimeInfoMap.get(key);
     89  }
     90 
     91  /**
     92   * Retrieve a managed client for a remote id. The remote id should have been generated
     93   * using getRemoteId.
     94   */
     95  getConnectionTypeByRemoteId(remoteId) {
     96    const key = this._getKeyByRemoteId(remoteId);
     97    for (const type of Object.values(CONNECTION_TYPES)) {
     98      if (key.endsWith(type)) {
     99        return type;
    100      }
    101    }
    102    return CONNECTION_TYPES.UNKNOWN;
    103  }
    104 
    105  _getKey(id, type) {
    106    return id + "-" + type;
    107  }
    108 
    109  _getKeyByRemoteId(remoteId) {
    110    if (!remoteId) {
    111      // If no remote id was provided, return the key corresponding to the local
    112      // this-firefox runtime.
    113      const { THIS_FIREFOX } = CONNECTION_TYPES;
    114      return this._getKey(THIS_FIREFOX, THIS_FIREFOX);
    115    }
    116 
    117    return decodeURIComponent(remoteId);
    118  }
    119 
    120  _removeClientByKey(key) {
    121    const client = this._clients.get(key);
    122    if (client) {
    123      client.off("closed", this._onClientClosed);
    124      this._clients.delete(key);
    125      this._runtimeInfoMap.delete(key);
    126    }
    127  }
    128 
    129  /**
    130   * Cleanup all closed clients when a "closed" notification is received from a client.
    131   */
    132  _onClientClosed() {
    133    const closedClientKeys = [...this._clients.keys()].filter(key => {
    134      return this._clients.get(key)._transportClosed;
    135    });
    136 
    137    for (const key of closedClientKeys) {
    138      this._removeClientByKey(key);
    139    }
    140  }
    141 }
    142 
    143 // Expose a singleton of RemoteClientManager.
    144 module.exports = {
    145  remoteClientManager: new RemoteClientManager(),
    146 };