diff options
Diffstat (limited to 'remote/marionette/prefs.sys.mjs')
-rw-r--r-- | remote/marionette/prefs.sys.mjs | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/remote/marionette/prefs.sys.mjs b/remote/marionette/prefs.sys.mjs new file mode 100644 index 0000000000..17df13d0fd --- /dev/null +++ b/remote/marionette/prefs.sys.mjs @@ -0,0 +1,175 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const { PREF_BOOL, PREF_INT, PREF_INVALID, PREF_STRING } = Ci.nsIPrefBranch; + +export class Branch { + /** + * @param {string=} branch + * Preference subtree. Uses root tree given `null`. + */ + constructor(branch) { + this._branch = Services.prefs.getBranch(branch); + } + + /** + * Gets value of `pref` in its known type. + * + * @param {string} pref + * Preference name. + * @param {*=} fallback + * Fallback value to return if `pref` does not exist. + * + * @returns {(string|boolean|number)} + * Value of `pref`, or the `fallback` value if `pref` does + * not exist. + * + * @throws {TypeError} + * If `pref` is not a recognised preference and no `fallback` + * value has been provided. + */ + get(pref, fallback = null) { + switch (this._branch.getPrefType(pref)) { + case PREF_STRING: + return this._branch.getStringPref(pref); + + case PREF_BOOL: + return this._branch.getBoolPref(pref); + + case PREF_INT: + return this._branch.getIntPref(pref); + + case PREF_INVALID: + default: + if (fallback != null) { + return fallback; + } + throw new TypeError(`Unrecognised preference: ${pref}`); + } + } + + /** + * Sets the value of `pref`. + * + * @param {string} pref + * Preference name. + * @param {(string|boolean|number)} value + * `pref`'s new value. + * + * @throws {TypeError} + * If `value` is not the correct type for `pref`. + */ + set(pref, value) { + let typ; + if (typeof value != "undefined" && value != null) { + typ = value.constructor.name; + } + + switch (typ) { + case "String": + // Unicode compliant + return this._branch.setStringPref(pref, value); + + case "Boolean": + return this._branch.setBoolPref(pref, value); + + case "Number": + return this._branch.setIntPref(pref, value); + + default: + throw new TypeError(`Illegal preference type value: ${typ}`); + } + } +} + +/** + * Provides shortcuts for lazily getting and setting typed Marionette + * preferences. + * + * Some of Marionette's preferences are stored using primitive values + * that internally are represented by complex types. + * + * Because we cannot trust the input of many of these preferences, + * this class provides abstraction that lets us safely deal with + * potentially malformed input. + * + * A further complication is that we cannot rely on `Preferences.sys.mjs` + * in Marionette. See https://bugzilla.mozilla.org/show_bug.cgi?id=1357517 + * for further details. + */ +class MarionetteBranch extends Branch { + constructor(branch = "marionette.") { + super(branch); + } + + /** + * The `marionette.debugging.clicktostart` preference delays + * server startup until a modal dialogue has been clicked to allow + * time for user to set breakpoints in the Browser Toolbox. + * + * @returns {boolean} + */ + get clickToStart() { + return this.get("debugging.clicktostart", false); + } + + /** + * The `marionette.port` preference, detailing which port + * the TCP server should listen on. + * + * @returns {number} + */ + get port() { + return this.get("port", 2828); + } + + set port(newPort) { + this.set("port", newPort); + } + + /** + * Gets the `marionette.setpermission.enabled` preference, should + * only be used for testdriver's set_permission API. + * + * @returns {boolean} + */ + get setPermissionEnabled() { + return this.get("setpermission.enabled", false); + } +} + +/** Reads a JSON serialised blob stored in the environment. */ +export class EnvironmentPrefs { + /** + * Reads the environment variable `key` and tries to parse it as + * JSON Object, then provides an iterator over its keys and values. + * + * If the environment variable is not set, this function returns empty. + * + * @param {string} key + * Environment variable. + * + * @returns {Iterable.<string, (string|boolean|number)>} + */ + static *from(key) { + if (!Services.env.exists(key)) { + return; + } + + let prefs; + try { + prefs = JSON.parse(Services.env.get(key)); + } catch (e) { + throw new TypeError(`Unable to parse prefs from ${key}`, e); + } + + for (let prefName of Object.keys(prefs)) { + yield [prefName, prefs[prefName]]; + } + } +} + +// There is a future potential of exposing this as Marionette.prefs.port +// if we introduce a Marionette.jsm module. +export const MarionettePrefs = new MarionetteBranch(); |