tor-browser

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

adb-addon.js (5112B)


      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 { AddonManager } = ChromeUtils.importESModule(
      8  "resource://gre/modules/AddonManager.sys.mjs",
      9  // AddonManager is a singleton, never create two instances of it.
     10  { global: "shared" }
     11 );
     12 const { AppConstants } = ChromeUtils.importESModule(
     13  "resource://gre/modules/AppConstants.sys.mjs"
     14 );
     15 const EventEmitter = require("resource://devtools/shared/event-emitter.js");
     16 
     17 const PREF_ADB_EXTENSION_URL = "devtools.remote.adb.extensionURL";
     18 const PREF_ADB_EXTENSION_ID = "devtools.remote.adb.extensionID";
     19 
     20 const ADB_ADDON_STATES = {
     21  DOWNLOADING: "downloading",
     22  INSTALLED: "installed",
     23  INSTALLING: "installing",
     24  PREPARING: "preparing",
     25  UNINSTALLED: "uninstalled",
     26  UNKNOWN: "unknown",
     27 };
     28 exports.ADB_ADDON_STATES = ADB_ADDON_STATES;
     29 
     30 /**
     31 * Wrapper around the ADB Extension providing ADB binaries for devtools remote debugging.
     32 * Fires the following events:
     33 * - "update": the status of the addon was updated
     34 * - "failure": addon installation failed
     35 * - "progress": addon download in progress
     36 *
     37 * AdbAddon::state can take any of the values from ADB_ADDON_STATES.
     38 */
     39 class ADBAddon extends EventEmitter {
     40  constructor() {
     41    super();
     42 
     43    this._status = ADB_ADDON_STATES.UNKNOWN;
     44 
     45    const addonsListener = {};
     46    addonsListener.onEnabled =
     47      addonsListener.onDisabled =
     48      addonsListener.onInstalled =
     49      addonsListener.onUninstalled =
     50        () => this.updateInstallStatus();
     51    AddonManager.addAddonListener(addonsListener);
     52 
     53    this.updateInstallStatus();
     54  }
     55 
     56  set status(value) {
     57    if (this._status != value) {
     58      this._status = value;
     59      this.emit("update");
     60    }
     61  }
     62 
     63  get status() {
     64    return this._status;
     65  }
     66 
     67  async _getAddon() {
     68    const addonId = Services.prefs.getCharPref(PREF_ADB_EXTENSION_ID);
     69    return AddonManager.getAddonByID(addonId);
     70  }
     71 
     72  async updateInstallStatus() {
     73    const addon = await this._getAddon();
     74    if (addon && !addon.userDisabled) {
     75      this.status = ADB_ADDON_STATES.INSTALLED;
     76    } else {
     77      this.status = ADB_ADDON_STATES.UNINSTALLED;
     78    }
     79  }
     80 
     81  /**
     82   * Returns the platform specific download link for the ADB extension.
     83   */
     84  _getXpiLink() {
     85    let OS = "";
     86 
     87    switch (AppConstants.platform) {
     88      case "linux": {
     89        const cpuArch = Services.sysinfo.get("arch");
     90        if (cpuArch === "x86-64") {
     91          OS = "linux64";
     92        } else {
     93          OS = "linux";
     94        }
     95        break;
     96      }
     97      case "macosx":
     98        OS = "mac64";
     99        break;
    100      case "win":
    101        OS = "win32";
    102        break;
    103    }
    104 
    105    const xpiLink = Services.prefs.getCharPref(PREF_ADB_EXTENSION_URL);
    106    return xpiLink.replace(/#OS#/g, OS);
    107  }
    108 
    109  /**
    110   * Install and enable the adb extension. Returns a promise that resolves when ADB is
    111   * enabled.
    112   *
    113   * @param {string} source
    114   *        String passed to the AddonManager for telemetry.
    115   */
    116  async install(source) {
    117    if (!source) {
    118      throw new Error(
    119        "Missing mandatory `source` parameter for adb-addon.install"
    120      );
    121    }
    122 
    123    const addon = await this._getAddon();
    124    if (addon && !addon.userDisabled) {
    125      this.status = ADB_ADDON_STATES.INSTALLED;
    126      return;
    127    }
    128    this.status = ADB_ADDON_STATES.PREPARING;
    129    if (addon?.userDisabled) {
    130      await addon.enable();
    131    } else {
    132      const install = await AddonManager.getInstallForURL(this._getXpiLink(), {
    133        telemetryInfo: { source },
    134      });
    135      install.addListener(this);
    136      install.install();
    137    }
    138  }
    139 
    140  async uninstall() {
    141    const addon = await this._getAddon();
    142    addon.uninstall();
    143  }
    144 
    145  installFailureHandler(install, message) {
    146    this.status = ADB_ADDON_STATES.UNINSTALLED;
    147    this.emit("failure", message);
    148  }
    149 
    150  // Expected AddonManager install listener.
    151  onDownloadStarted() {
    152    this.status = ADB_ADDON_STATES.DOWNLOADING;
    153  }
    154 
    155  // Expected AddonManager install listener.
    156  onDownloadProgress(install) {
    157    if (install.maxProgress == -1) {
    158      this.emit("progress", -1);
    159    } else {
    160      this.emit("progress", install.progress / install.maxProgress);
    161    }
    162  }
    163 
    164  // Expected AddonManager install listener.
    165  onDownloadCancelled(install) {
    166    this.installFailureHandler(install, "Download cancelled");
    167  }
    168 
    169  // Expected AddonManager install listener.
    170  onDownloadFailed(install) {
    171    this.installFailureHandler(install, "Download failed");
    172  }
    173 
    174  // Expected AddonManager install listener.
    175  onInstallStarted() {
    176    this.status = ADB_ADDON_STATES.INSTALLING;
    177  }
    178 
    179  // Expected AddonManager install listener.
    180  onInstallCancelled(install) {
    181    this.installFailureHandler(install, "Install cancelled");
    182  }
    183 
    184  // Expected AddonManager install listener.
    185  onInstallFailed(install) {
    186    this.installFailureHandler(install, "Install failed");
    187  }
    188 
    189  // Expected AddonManager install listener.
    190  onInstallEnded({ addon }) {
    191    addon.enable();
    192  }
    193 }
    194 
    195 exports.adbAddon = new ADBAddon();