tor-browser

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

parent-accessibility.js (5165B)


      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 { Actor } = require("resource://devtools/shared/protocol.js");
      8 const {
      9  parentAccessibilitySpec,
     10 } = require("resource://devtools/shared/specs/accessibility.js");
     11 
     12 const PREF_ACCESSIBILITY_FORCE_DISABLED = "accessibility.force_disabled";
     13 
     14 class ParentAccessibilityActor extends Actor {
     15  constructor(conn) {
     16    super(conn, parentAccessibilitySpec);
     17 
     18    this.userPref = Services.prefs.getIntPref(
     19      PREF_ACCESSIBILITY_FORCE_DISABLED
     20    );
     21 
     22    if (this.enabled && !this.accService) {
     23      // Set a local reference to an accessibility service if accessibility was
     24      // started elsewhere to ensure that parent process a11y service does not
     25      // get GC'ed away.
     26      this.accService = Cc["@mozilla.org/accessibilityService;1"].getService(
     27        Ci.nsIAccessibilityService
     28      );
     29    }
     30 
     31    Services.obs.addObserver(this, "a11y-consumers-changed");
     32    Services.prefs.addObserver(PREF_ACCESSIBILITY_FORCE_DISABLED, this);
     33  }
     34 
     35  bootstrap() {
     36    return {
     37      canBeDisabled: this.canBeDisabled,
     38      canBeEnabled: this.canBeEnabled,
     39    };
     40  }
     41 
     42  observe(subject, topic, data) {
     43    if (topic === "a11y-consumers-changed") {
     44      // This event is fired when accessibility service consumers change. Since
     45      // this observer lives in parent process there are 2 possible consumers of
     46      // a11y service: XPCOM and PlatformAPI (e.g. screen readers). We only care
     47      // about PlatformAPI consumer changes because when set, we can no longer
     48      // disable accessibility service.
     49      const { PlatformAPI } = JSON.parse(data);
     50      this.emit("can-be-disabled-change", !PlatformAPI);
     51    } else if (
     52      !this.disabling &&
     53      topic === "nsPref:changed" &&
     54      data === PREF_ACCESSIBILITY_FORCE_DISABLED
     55    ) {
     56      // PREF_ACCESSIBILITY_FORCE_DISABLED preference change event. When set to
     57      // >=1, it means that the user wants to disable accessibility service and
     58      // prevent it from starting in the future. Note: we also check
     59      // this.disabling state when handling this pref change because this is how
     60      // we disable the accessibility inspector itself.
     61      this.emit("can-be-enabled-change", this.canBeEnabled);
     62    }
     63  }
     64 
     65  /**
     66   * A getter that indicates if accessibility service is enabled.
     67   *
     68   * @return {boolean}
     69   *         True if accessibility service is on.
     70   */
     71  get enabled() {
     72    return Services.appinfo.accessibilityEnabled;
     73  }
     74 
     75  /**
     76   * A getter that indicates if the accessibility service can be disabled.
     77   *
     78   * @return {boolean}
     79   *         True if accessibility service can be disabled.
     80   */
     81  get canBeDisabled() {
     82    if (this.enabled) {
     83      const a11yService = Cc["@mozilla.org/accessibilityService;1"].getService(
     84        Ci.nsIAccessibilityService
     85      );
     86      const { PlatformAPI } = JSON.parse(a11yService.getConsumers());
     87      return !PlatformAPI;
     88    }
     89 
     90    return true;
     91  }
     92 
     93  /**
     94   * A getter that indicates if the accessibility service can be enabled.
     95   *
     96   * @return {boolean}
     97   *         True if accessibility service can be enabled.
     98   */
     99  get canBeEnabled() {
    100    return Services.prefs.getIntPref(PREF_ACCESSIBILITY_FORCE_DISABLED) < 1;
    101  }
    102 
    103  /**
    104   * Enable accessibility service (via XPCOM service).
    105   */
    106  enable() {
    107    if (this.enabled || !this.canBeEnabled) {
    108      return;
    109    }
    110 
    111    this.accService = Cc["@mozilla.org/accessibilityService;1"].getService(
    112      Ci.nsIAccessibilityService
    113    );
    114  }
    115 
    116  /**
    117   * Force disable accessibility service. This method removes the reference to
    118   * the XPCOM a11y service object and flips the
    119   * PREF_ACCESSIBILITY_FORCE_DISABLED preference on and off to shutdown a11y
    120   * service.
    121   */
    122  disable() {
    123    if (!this.enabled || !this.canBeDisabled) {
    124      return;
    125    }
    126 
    127    this.disabling = true;
    128    this.accService = null;
    129    // Set PREF_ACCESSIBILITY_FORCE_DISABLED to 1 to force disable
    130    // accessibility service. This is the only way to guarantee an immediate
    131    // accessibility service shutdown in all processes. This also prevents
    132    // accessibility service from starting up in the future.
    133    Services.prefs.setIntPref(PREF_ACCESSIBILITY_FORCE_DISABLED, 1);
    134    // Set PREF_ACCESSIBILITY_FORCE_DISABLED back to previous default or user
    135    // set value. This will not start accessibility service until the user
    136    // activates it again. It simply ensures that accessibility service can
    137    // start again (when value is below 1).
    138    Services.prefs.setIntPref(PREF_ACCESSIBILITY_FORCE_DISABLED, this.userPref);
    139    delete this.disabling;
    140  }
    141 
    142  /**
    143   * Destroy the helper class, remove all listeners and if possible disable
    144   * accessibility service in the parent process.
    145   */
    146  destroy() {
    147    this.disable();
    148    super.destroy();
    149    Services.obs.removeObserver(this, "a11y-consumers-changed");
    150    Services.prefs.removeObserver(PREF_ACCESSIBILITY_FORCE_DISABLED, this);
    151  }
    152 }
    153 
    154 exports.ParentAccessibilityActor = ParentAccessibilityActor;