From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../actors/accessibility/parent-accessibility.js | 154 +++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 devtools/server/actors/accessibility/parent-accessibility.js (limited to 'devtools/server/actors/accessibility/parent-accessibility.js') diff --git a/devtools/server/actors/accessibility/parent-accessibility.js b/devtools/server/actors/accessibility/parent-accessibility.js new file mode 100644 index 0000000000..fd2c945ea7 --- /dev/null +++ b/devtools/server/actors/accessibility/parent-accessibility.js @@ -0,0 +1,154 @@ +/* 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/. */ + +"use strict"; + +const { Actor } = require("resource://devtools/shared/protocol.js"); +const { + parentAccessibilitySpec, +} = require("resource://devtools/shared/specs/accessibility.js"); + +const PREF_ACCESSIBILITY_FORCE_DISABLED = "accessibility.force_disabled"; + +class ParentAccessibilityActor extends Actor { + constructor(conn) { + super(conn, parentAccessibilitySpec); + + this.userPref = Services.prefs.getIntPref( + PREF_ACCESSIBILITY_FORCE_DISABLED + ); + + if (this.enabled && !this.accService) { + // Set a local reference to an accessibility service if accessibility was + // started elsewhere to ensure that parent process a11y service does not + // get GC'ed away. + this.accService = Cc["@mozilla.org/accessibilityService;1"].getService( + Ci.nsIAccessibilityService + ); + } + + Services.obs.addObserver(this, "a11y-consumers-changed"); + Services.prefs.addObserver(PREF_ACCESSIBILITY_FORCE_DISABLED, this); + } + + bootstrap() { + return { + canBeDisabled: this.canBeDisabled, + canBeEnabled: this.canBeEnabled, + }; + } + + observe(subject, topic, data) { + if (topic === "a11y-consumers-changed") { + // This event is fired when accessibility service consumers change. Since + // this observer lives in parent process there are 2 possible consumers of + // a11y service: XPCOM and PlatformAPI (e.g. screen readers). We only care + // about PlatformAPI consumer changes because when set, we can no longer + // disable accessibility service. + const { PlatformAPI } = JSON.parse(data); + this.emit("can-be-disabled-change", !PlatformAPI); + } else if ( + !this.disabling && + topic === "nsPref:changed" && + data === PREF_ACCESSIBILITY_FORCE_DISABLED + ) { + // PREF_ACCESSIBILITY_FORCE_DISABLED preference change event. When set to + // >=1, it means that the user wants to disable accessibility service and + // prevent it from starting in the future. Note: we also check + // this.disabling state when handling this pref change because this is how + // we disable the accessibility inspector itself. + this.emit("can-be-enabled-change", this.canBeEnabled); + } + } + + /** + * A getter that indicates if accessibility service is enabled. + * + * @return {Boolean} + * True if accessibility service is on. + */ + get enabled() { + return Services.appinfo.accessibilityEnabled; + } + + /** + * A getter that indicates if the accessibility service can be disabled. + * + * @return {Boolean} + * True if accessibility service can be disabled. + */ + get canBeDisabled() { + if (this.enabled) { + const a11yService = Cc["@mozilla.org/accessibilityService;1"].getService( + Ci.nsIAccessibilityService + ); + const { PlatformAPI } = JSON.parse(a11yService.getConsumers()); + return !PlatformAPI; + } + + return true; + } + + /** + * A getter that indicates if the accessibility service can be enabled. + * + * @return {Boolean} + * True if accessibility service can be enabled. + */ + get canBeEnabled() { + return Services.prefs.getIntPref(PREF_ACCESSIBILITY_FORCE_DISABLED) < 1; + } + + /** + * Enable accessibility service (via XPCOM service). + */ + enable() { + if (this.enabled || !this.canBeEnabled) { + return; + } + + this.accService = Cc["@mozilla.org/accessibilityService;1"].getService( + Ci.nsIAccessibilityService + ); + } + + /** + * Force disable accessibility service. This method removes the reference to + * the XPCOM a11y service object and flips the + * PREF_ACCESSIBILITY_FORCE_DISABLED preference on and off to shutdown a11y + * service. + */ + disable() { + if (!this.enabled || !this.canBeDisabled) { + return; + } + + this.disabling = true; + this.accService = null; + // Set PREF_ACCESSIBILITY_FORCE_DISABLED to 1 to force disable + // accessibility service. This is the only way to guarantee an immediate + // accessibility service shutdown in all processes. This also prevents + // accessibility service from starting up in the future. + Services.prefs.setIntPref(PREF_ACCESSIBILITY_FORCE_DISABLED, 1); + // Set PREF_ACCESSIBILITY_FORCE_DISABLED back to previous default or user + // set value. This will not start accessibility service until the user + // activates it again. It simply ensures that accessibility service can + // start again (when value is below 1). + Services.prefs.setIntPref(PREF_ACCESSIBILITY_FORCE_DISABLED, this.userPref); + delete this.disabling; + } + + /** + * Destroy the helper class, remove all listeners and if possible disable + * accessibility service in the parent process. + */ + destroy() { + this.disable(); + super.destroy(); + Services.obs.removeObserver(this, "a11y-consumers-changed"); + Services.prefs.removeObserver(PREF_ACCESSIBILITY_FORCE_DISABLED, this); + } +} + +exports.ParentAccessibilityActor = ParentAccessibilityActor; -- cgit v1.2.3