tor-browser

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

client-wrapper.js (6262B)


      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  checkVersionCompatibility,
      9 } = require("resource://devtools/client/shared/remote-debugging/version-checker.js");
     10 
     11 const {
     12  RUNTIME_PREFERENCE,
     13 } = require("resource://devtools/client/aboutdebugging/src/constants.js");
     14 const {
     15  WorkersListener,
     16 } = require("resource://devtools/client/shared/workers-listener.js");
     17 const RootResourceCommand = require("resource://devtools/shared/commands/root-resource/root-resource-command.js");
     18 
     19 const PREF_TYPES = {
     20  BOOL: "BOOL",
     21 };
     22 
     23 // Map of preference to preference type.
     24 const PREF_TO_TYPE = {
     25  [RUNTIME_PREFERENCE.CHROME_DEBUG_ENABLED]: PREF_TYPES.BOOL,
     26  [RUNTIME_PREFERENCE.CONNECTION_PROMPT]: PREF_TYPES.BOOL,
     27  [RUNTIME_PREFERENCE.PERMANENT_PRIVATE_BROWSING]: PREF_TYPES.BOOL,
     28  [RUNTIME_PREFERENCE.REMOTE_DEBUG_ENABLED]: PREF_TYPES.BOOL,
     29  [RUNTIME_PREFERENCE.SERVICE_WORKERS_ENABLED]: PREF_TYPES.BOOL,
     30 };
     31 
     32 // Some events are fired by mainRoot rather than client.
     33 const MAIN_ROOT_EVENTS = ["addonListChanged", "tabListChanged"];
     34 
     35 /**
     36 * The ClientWrapper class is used to isolate aboutdebugging from the DevTools client API
     37 * The modules of about:debugging should never call DevTools client APIs directly.
     38 */
     39 class ClientWrapper {
     40  constructor(client) {
     41    this.client = client;
     42    this.workersListener = new WorkersListener(client.mainRoot);
     43  }
     44 
     45  once(evt, listener) {
     46    if (MAIN_ROOT_EVENTS.includes(evt)) {
     47      this.client.mainRoot.once(evt, listener);
     48    } else {
     49      this.client.once(evt, listener);
     50    }
     51  }
     52 
     53  on(evt, listener) {
     54    if (evt === "workersUpdated") {
     55      this.workersListener.addListener(listener);
     56    } else if (MAIN_ROOT_EVENTS.includes(evt)) {
     57      this.client.mainRoot.on(evt, listener);
     58    } else {
     59      this.client.on(evt, listener);
     60    }
     61  }
     62 
     63  off(evt, listener) {
     64    if (evt === "workersUpdated") {
     65      this.workersListener.removeListener(listener);
     66    } else if (MAIN_ROOT_EVENTS.includes(evt)) {
     67      this.client.mainRoot.off(evt, listener);
     68    } else {
     69      this.client.off(evt, listener);
     70    }
     71  }
     72 
     73  async getFront(typeName) {
     74    return this.client.mainRoot.getFront(typeName);
     75  }
     76 
     77  async getDeviceDescription() {
     78    const deviceFront = await this.getFront("device");
     79    const description = await deviceFront.getDescription();
     80 
     81    // Only expose a specific set of properties.
     82    return {
     83      canDebugServiceWorkers: description.canDebugServiceWorkers,
     84      channel: description.channel,
     85      deviceName: description.deviceName,
     86      name: description.brandName,
     87      os: description.os,
     88      version: description.version,
     89    };
     90  }
     91 
     92  createRootResourceCommand() {
     93    return new RootResourceCommand({ rootFront: this.client.mainRoot });
     94  }
     95 
     96  async checkVersionCompatibility() {
     97    return checkVersionCompatibility(this.client);
     98  }
     99 
    100  async setPreference(prefName, value) {
    101    const prefType = PREF_TO_TYPE[prefName];
    102    const preferenceFront = await this.client.mainRoot.getFront("preference");
    103    switch (prefType) {
    104      case PREF_TYPES.BOOL:
    105        return preferenceFront.setBoolPref(prefName, value);
    106      default:
    107        throw new Error("Unsupported preference" + prefName);
    108    }
    109  }
    110 
    111  async getPreference(prefName, defaultValue) {
    112    if (typeof defaultValue === "undefined") {
    113      throw new Error(
    114        "Default value is mandatory for getPreference, the actor will " +
    115          "throw if the preference is not set on the target runtime"
    116      );
    117    }
    118 
    119    const prefType = PREF_TO_TYPE[prefName];
    120    const preferenceFront = await this.client.mainRoot.getFront("preference");
    121    switch (prefType) {
    122      case PREF_TYPES.BOOL: {
    123        // TODO: Add server-side trait and methods to pass a default value to getBoolPref.
    124        // See Bug 1522588.
    125        let prefValue;
    126        try {
    127          prefValue = await preferenceFront.getBoolPref(prefName);
    128        } catch (e) {
    129          prefValue = defaultValue;
    130        }
    131        return prefValue;
    132      }
    133      default:
    134        throw new Error("Unsupported preference:" + prefName);
    135    }
    136  }
    137 
    138  async listTabs() {
    139    return this.client.mainRoot.listTabs();
    140  }
    141 
    142  async listAddons(options) {
    143    return this.client.mainRoot.listAddons(options);
    144  }
    145 
    146  async getAddon({ id }) {
    147    return this.client.mainRoot.getAddon({ id });
    148  }
    149 
    150  async uninstallAddon({ id }) {
    151    const addonsFront = await this.getFront("addons");
    152    return addonsFront.uninstallAddon(id);
    153  }
    154 
    155  async getMainProcess() {
    156    return this.client.mainRoot.getMainProcess();
    157  }
    158 
    159  async getServiceWorkerFront({ id }) {
    160    return this.client.mainRoot.getWorker(id);
    161  }
    162 
    163  async listWorkers() {
    164    const { other, service, shared } =
    165      await this.client.mainRoot.listAllWorkers();
    166 
    167    return {
    168      otherWorkers: other,
    169      serviceWorkers: service,
    170      sharedWorkers: shared,
    171    };
    172  }
    173 
    174  async close() {
    175    return this.client.close();
    176  }
    177 
    178  isClosed() {
    179    return this.client._transportClosed;
    180  }
    181 
    182  // This method will be mocked to return a dummy URL during mochitests
    183  getPerformancePanelUrl() {
    184    return "chrome://devtools/content/performance-new/panel/index.xhtml";
    185  }
    186 
    187  /**
    188   * @param {Window} win - The window of the dialog window.
    189   * @param {Function} openAboutProfiling
    190   */
    191  async loadPerformanceProfiler(win, openAboutProfiling) {
    192    const perfFront = await this.getFront("perf");
    193    const { traits } = this.client;
    194    await win.gInit(perfFront, traits, "devtools-remote", openAboutProfiling);
    195  }
    196 
    197  /**
    198   * @param {Window} win - The window of the dialog window.
    199   * @param {Function} openRemoteDevTools
    200   */
    201  async loadAboutProfiling(win, openRemoteDevTools) {
    202    const perfFront = await this.getFront("perf");
    203    const isSupportedPlatform = await perfFront.isSupportedPlatform();
    204    const supportedFeatures = await perfFront.getSupportedFeatures();
    205    await win.gInit(
    206      "aboutprofiling-remote",
    207      isSupportedPlatform,
    208      supportedFeatures,
    209      openRemoteDevTools
    210    );
    211  }
    212 
    213  get traits() {
    214    return { ...this.client.mainRoot.traits };
    215  }
    216 }
    217 
    218 exports.ClientWrapper = ClientWrapper;