tor-browser

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

prefs.sys.mjs (5120B)


      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 file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 const { PREF_BOOL, PREF_INT, PREF_INVALID, PREF_STRING } = Ci.nsIPrefBranch;
      6 
      7 export class Branch {
      8  /**
      9   * @param {string=} branch
     10   *     Preference subtree.  Uses root tree given `null`.
     11   */
     12  constructor(branch) {
     13    this._branch = Services.prefs.getBranch(branch);
     14  }
     15 
     16  /**
     17   * Gets value of `pref` in its known type.
     18   *
     19   * @param {string} pref
     20   *     Preference name.
     21   * @param {*=} fallback
     22   *     Fallback value to return if `pref` does not exist.
     23   *
     24   * @returns {(string|boolean|number)}
     25   *     Value of `pref`, or the `fallback` value if `pref` does
     26   *     not exist.
     27   *
     28   * @throws {TypeError}
     29   *     If `pref` is not a recognised preference and no `fallback`
     30   *     value has been provided.
     31   */
     32  get(pref, fallback = null) {
     33    switch (this._branch.getPrefType(pref)) {
     34      case PREF_STRING:
     35        return this._branch.getStringPref(pref);
     36 
     37      case PREF_BOOL:
     38        return this._branch.getBoolPref(pref);
     39 
     40      case PREF_INT:
     41        return this._branch.getIntPref(pref);
     42 
     43      case PREF_INVALID:
     44      default:
     45        if (fallback != null) {
     46          return fallback;
     47        }
     48        throw new TypeError(`Unrecognised preference: ${pref}`);
     49    }
     50  }
     51 
     52  /**
     53   * Sets the value of `pref`.
     54   *
     55   * @param {string} pref
     56   *     Preference name.
     57   * @param {(string|boolean|number)} value
     58   *     `pref`'s new value.
     59   *
     60   * @throws {TypeError}
     61   *     If `value` is not the correct type for `pref`.
     62   */
     63  set(pref, value) {
     64    let typ;
     65    if (typeof value != "undefined" && value != null) {
     66      typ = value.constructor.name;
     67    }
     68 
     69    switch (typ) {
     70      case "String":
     71        // Unicode compliant
     72        return this._branch.setStringPref(pref, value);
     73 
     74      case "Boolean":
     75        return this._branch.setBoolPref(pref, value);
     76 
     77      case "Number":
     78        return this._branch.setIntPref(pref, value);
     79 
     80      default:
     81        throw new TypeError(`Illegal preference type value: ${typ}`);
     82    }
     83  }
     84 }
     85 
     86 /**
     87 * Provides shortcuts for lazily getting and setting typed Marionette
     88 * preferences.
     89 *
     90 * Some of Marionette's preferences are stored using primitive values
     91 * that internally are represented by complex types.
     92 *
     93 * Because we cannot trust the input of many of these preferences,
     94 * this class provides abstraction that lets us safely deal with
     95 * potentially malformed input.
     96 *
     97 * A further complication is that we cannot rely on `Preferences.sys.mjs`
     98 * in Marionette.  See https://bugzilla.mozilla.org/show_bug.cgi?id=1357517
     99 * for further details.
    100 */
    101 class MarionetteBranch extends Branch {
    102  constructor(branch = "marionette.") {
    103    super(branch);
    104  }
    105 
    106  /**
    107   * The `marionette.debugging.clicktostart` preference delays
    108   * server startup until a modal dialogue has been clicked to allow
    109   * time for user to set breakpoints in the Browser Toolbox.
    110   *
    111   * @returns {boolean}
    112   */
    113  get clickToStart() {
    114    return this.get("debugging.clicktostart", false);
    115  }
    116 
    117  /**
    118   * The `marionette.navigate-after-click.enabled` preference enables the
    119   * fallback logic for Selenium clients to wait for a potential navigation
    120   * after clicking an element via "WebDriver:ElementClick".
    121   *
    122   * @returns {boolean}
    123   */
    124  get navigateAfterClickEnabled() {
    125    return this.get("marionette.navigate-after-click.enabled", true);
    126  }
    127 
    128  /**
    129   * The `marionette.navigate-after-click.timeout` preference defines the
    130   * amount of milliseconds to wait for a potential navigation after a click
    131   * event was dispatches via "WebDriver:ElementClick".
    132   *
    133   * @returns {number}
    134   */
    135  get navigateAfterClickTimeout() {
    136    return this.get("marionette.navigate-after-click.timeout", 50);
    137  }
    138 
    139  /**
    140   * The `marionette.port` preference, detailing which port
    141   * the TCP server should listen on.
    142   *
    143   * @returns {number}
    144   */
    145  get port() {
    146    return this.get("port", 2828);
    147  }
    148 
    149  set port(newPort) {
    150    this.set("port", newPort);
    151  }
    152 }
    153 
    154 /** Reads a JSON serialised blob stored in the environment. */
    155 export class EnvironmentPrefs {
    156  /**
    157   * Reads the environment variable `key` and tries to parse it as
    158   * JSON Object, then provides an iterator over its keys and values.
    159   *
    160   * If the environment variable is not set, this function returns empty.
    161   *
    162   * @param {string} key
    163   *     Environment variable.
    164   *
    165   * @returns {Iterable.<string, (string|boolean|number)>}
    166   */
    167  static *from(key) {
    168    if (!Services.env.exists(key)) {
    169      return;
    170    }
    171 
    172    let prefs;
    173    try {
    174      prefs = JSON.parse(Services.env.get(key));
    175    } catch (e) {
    176      throw new TypeError(`Unable to parse prefs from ${key}`, e);
    177    }
    178 
    179    for (let prefName of Object.keys(prefs)) {
    180      yield [prefName, prefs[prefName]];
    181    }
    182  }
    183 }
    184 
    185 // There is a future potential of exposing this as Marionette.prefs.port
    186 // if we introduce a Marionette.sys.mjs module.
    187 export const MarionettePrefs = new MarionetteBranch();