Bug 1599806 - remove setupInParent from accessibility actor and split up child/parent functionality into two separate actors. r=ochameau

Differential Revision: https://phabricator.services.mozilla.com/D58807

--HG--
rename : devtools/server/actors/accessibility/accessibility-parent.js => devtools/server/actors/accessibility/parent-accessibility.js
extra : moz-landing-system : lando
This commit is contained in:
Yura Zenevich 2020-03-06 17:18:58 +00:00
Родитель aabab512b9
Коммит cbbc2cdd24
10 изменённых файлов: 227 добавлений и 356 удалений

Просмотреть файл

@ -9,6 +9,11 @@ const {
} = require("devtools/shared/constants");
const { FILTERS } = require("devtools/client/accessibility/constants");
const PARENT_ACCESSIBILITY_EVENTS = [
"can-be-disabled-change",
"can-be-enabled-change",
];
/**
* Component responsible for tracking all Accessibility fronts in parent and
* content processes.
@ -100,12 +105,34 @@ class AccessibilityProxy {
this.accessibleWalkerFront.off("picker-accessible-canceled", onCanceled);
}
disableAccessibility() {
return this.accessibilityFront.disable();
async disableAccessibility() {
// Accessibility service is shut down using the parent accessibility front.
// That, in turn, shuts down accessibility service in all content processes.
// We need to wait until that happens to be sure platform accessibility is
// fully disabled.
// TODO: Remove this after Firefox 75 and use parentAccessibilityFront.
if (this.parentAccessibilityFront) {
const disabled = this.accessibilityFront.once("shutdown");
await this.parentAccessibilityFront.disable();
await disabled;
} else {
await this.accessibilityFront.disable();
}
}
enableAccessibility() {
return this.accessibilityFront.enable();
async enableAccessibility() {
// Accessibility service is initialized using the parent accessibility
// front. That, in turn, initializes accessibility service in all content
// processes. We need to wait until that happens to be sure platform
// accessibility is fully enabled.
// TODO: Remove this after Firefox 75 and use parentAccessibilityFront.
if (this.parentAccessibilityFront) {
const enabled = this.accessibilityFront.once("init");
await this.parentAccessibilityFront.enable();
await enabled;
} else {
await this.accessibilityFront.enable();
}
}
/**
@ -133,7 +160,9 @@ class AccessibilityProxy {
}
async resetAccessiblity() {
const { enabled, canBeDisabled, canBeEnabled } = this.accessibilityFront;
const { enabled } = this.accessibilityFront;
const { canBeEnabled, canBeDisabled } =
this.parentAccessibilityFront || this.accessibilityFront;
return { enabled, canBeDisabled, canBeEnabled };
}
@ -152,8 +181,14 @@ class AccessibilityProxy {
startListeningForLifecycleEvents(eventMap) {
for (let [type, listeners] of Object.entries(eventMap)) {
listeners = Array.isArray(listeners) ? listeners : [listeners];
const accessibilityFront =
// TODO: Remove parentAccessibilityFront check after Firefox 75.
this.parentAccessibilityFront &&
PARENT_ACCESSIBILITY_EVENTS.includes(type)
? this.parentAccessibilityFront
: this.accessibilityFront;
for (const listener of listeners) {
this.accessibilityFront.on(type, listener);
accessibilityFront.on(type, listener);
}
}
}
@ -161,24 +196,39 @@ class AccessibilityProxy {
stopListeningForLifecycleEvents(eventMap) {
for (let [type, listeners] of Object.entries(eventMap)) {
listeners = Array.isArray(listeners) ? listeners : [listeners];
// TODO: Remove parentAccessibilityFront check after Firefox 75.
const accessibilityFront =
this.parentAccessibilityFront &&
PARENT_ACCESSIBILITY_EVENTS.includes(type)
? this.parentAccessibilityFront
: this.accessibilityFront;
for (const listener of listeners) {
this.accessibilityFront.off(type, listener);
accessibilityFront.off(type, listener);
}
}
}
async ensureReady() {
const { mainRoot } = this.target.client;
if (await mainRoot.hasActor("parentAccessibility")) {
this.parentAccessibilityFront = await mainRoot.getFront(
"parentaccessibility"
);
}
this.accessibleWalkerFront = this.accessibilityFront.accessibleWalkerFront;
this.simulatorFront = this.accessibilityFront.simulatorFront;
if (this.simulatorFront) {
this.simulate = types => this.simulatorFront.simulate({ types });
}
}
async initialize() {
try {
this.accessibilityFront = await this.target.getFront("accessibility");
// Finalize accessibility front initialization. See accessibility front
// bootstrap method description.
await this.accessibilityFront.bootstrap();
this.accessibleWalkerFront = this.accessibilityFront.accessibleWalkerFront;
this.simulatorFront = this.accessibilityFront.simulatorFront;
if (this.simulatorFront) {
this.simulate = types => this.simulatorFront.simulate({ types });
}
this.supports = {};
// To add a check for backward compatibility add something similar to the
// example below:
@ -196,6 +246,7 @@ class AccessibilityProxy {
destroy() {
this.accessibilityFront = null;
this.parentAccessibilityFront = null;
this.accessibleWalkerFront = null;
this.simulatorFront = null;
this.simulate = null;

Просмотреть файл

@ -90,6 +90,7 @@ AccessibilityPanel.prototype = {
this.shouldRefresh = true;
await this.startup.initAccessibility();
await this.accessibilityProxy.ensureReady();
this.picker = new Picker(this);
this.fluentBundles = await this.createFluentBundles();

Просмотреть файл

@ -4,10 +4,8 @@
"use strict";
const { DevToolsServer } = require("devtools/server/devtools-server");
const Services = require("Services");
const { Actor, ActorClassWithSpec } = require("devtools/shared/protocol");
const defer = require("devtools/shared/defer");
const { accessibilitySpec } = require("devtools/shared/specs/accessibility");
loader.lazyRequireGetter(
@ -22,7 +20,6 @@ loader.lazyRequireGetter(
"devtools/server/actors/accessibility/simulator",
true
);
loader.lazyRequireGetter(this, "events", "devtools/shared/event-emitter");
loader.lazyRequireGetter(
this,
"isWebRenderEnabled",
@ -30,189 +27,35 @@ loader.lazyRequireGetter(
true
);
const PREF_ACCESSIBILITY_FORCE_DISABLED = "accessibility.force_disabled";
/**
* The AccessibilityActor is a top level container actor that initializes
* accessible walker and is the top-most point of interaction for accessibility
* tools UI.
* tools UI for a top level content process.
*/
const AccessibilityActor = ActorClassWithSpec(accessibilitySpec, {
initialize(conn, targetActor) {
Actor.prototype.initialize.call(this, conn);
this.initializedDeferred = defer();
if (DevToolsServer.isInChildProcess) {
this._msgName = `debug:${this.conn.prefix}accessibility`;
// eslint-disable-next-line no-restricted-properties
this.conn.setupInParent({
module: "devtools/server/actors/accessibility/accessibility-parent",
setupParent: "setupParentProcess",
});
this.onMessage = this.onMessage.bind(this);
this.messageManager.addMessageListener(
`${this._msgName}:event`,
this.onMessage
);
} else {
this.userPref = Services.prefs.getIntPref(
PREF_ACCESSIBILITY_FORCE_DISABLED
);
Services.obs.addObserver(this, "a11y-consumers-changed");
Services.prefs.addObserver(PREF_ACCESSIBILITY_FORCE_DISABLED, this);
this.initializedDeferred.resolve();
}
// This event is fired when accessibility service is initialized or shut
// down. "init" and "shutdown" events are only relayed when the enabled
// state matches the event (e.g. the event came from the same process as
// the actor).
Services.obs.addObserver(this, "a11y-init-or-shutdown");
this.targetActor = targetActor;
},
bootstrap() {
return this.initializedDeferred.promise.then(() => ({
return {
enabled: this.enabled,
canBeEnabled: this.canBeEnabled,
canBeDisabled: this.canBeDisabled,
}));
};
},
get enabled() {
return Services.appinfo.accessibilityEnabled;
},
get canBeEnabled() {
if (DevToolsServer.isInChildProcess) {
return this._canBeEnabled;
}
return Services.prefs.getIntPref(PREF_ACCESSIBILITY_FORCE_DISABLED) < 1;
},
get canBeDisabled() {
if (DevToolsServer.isInChildProcess) {
return this._canBeDisabled;
} else if (!this.enabled) {
return true;
}
const { PlatformAPI } = JSON.parse(this.walker.a11yService.getConsumers());
return !PlatformAPI;
},
/**
* Getter for a message manager that corresponds to a current tab. It is onyl
* used if the AccessibilityActor runs in the child process.
*
* @return {Object}
* Message manager that corresponds to the current content tab.
*/
get messageManager() {
if (!DevToolsServer.isInChildProcess) {
throw new Error(
"Message manager should only be used when actor is in child process."
);
}
return this.conn.parentMessageManager;
},
onMessage(msg) {
const { topic, data } = msg.data;
switch (topic) {
case "initialized":
this._canBeEnabled = data.canBeEnabled;
this._canBeDisabled = data.canBeDisabled;
// Sometimes when the tool is reopened content process accessibility service is
// not shut down yet because GC did not run in that process (though it did in
// parent process and the service was shut down there). We need to sync the two
// services if possible.
if (!data.enabled && this.enabled && data.canBeEnabled) {
this.messageManager.sendAsyncMessage(this._msgName, {
action: "enable",
});
}
this.initializedDeferred.resolve();
break;
case "can-be-disabled-change":
this._canBeDisabled = data;
events.emit(this, "can-be-disabled-change", this.canBeDisabled);
break;
case "can-be-enabled-change":
this._canBeEnabled = data;
events.emit(this, "can-be-enabled-change", this.canBeEnabled);
break;
default:
break;
}
},
/**
* Enable acessibility service in the given process.
*/
async enable() {
if (this.enabled || !this.canBeEnabled) {
return;
}
const initPromise = this.once("init");
if (DevToolsServer.isInChildProcess) {
this.messageManager.sendAsyncMessage(this._msgName, { action: "enable" });
} else {
// This executes accessibility service lazy getter and adds accessible
// events observer.
this.walker.a11yService;
}
await initPromise;
},
/**
* Disable acessibility service in the given process.
*/
async disable() {
if (!this.enabled || !this.canBeDisabled) {
return;
}
this.disabling = true;
const shutdownPromise = this.once("shutdown");
if (DevToolsServer.isInChildProcess) {
this.messageManager.sendAsyncMessage(this._msgName, {
action: "disable",
});
} else {
// 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.
//
// TODO: Introduce a shutdown method that is exposed via XPCOM on
// accessibility service.
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
);
}
await shutdownPromise;
delete this.disabling;
},
/**
* Observe Accessibility service init and shutdown events. It relays these
* events to AccessibilityFront iff the event is fired for the a11y service
* events to AccessibilityFront if the event is fired for the a11y service
* that lives in the same process.
*
* @param {null} subject
@ -223,41 +66,15 @@ const AccessibilityActor = ActorClassWithSpec(accessibilitySpec, {
* "0" corresponds to shutdown and "1" to init.
*/
observe(subject, topic, data) {
if (topic === "a11y-init-or-shutdown") {
// This event is fired when accessibility service is initialized or shut
// down. "init" and "shutdown" events are only relayed when the enabled
// state matches the event (e.g. the event came from the same process as
// the actor).
const enabled = data === "1";
if (enabled && this.enabled) {
events.emit(this, "init");
this.emit("init");
} else if (!enabled && !this.enabled) {
if (this.walker) {
this.walker.reset();
}
events.emit(this, "shutdown");
}
} else if (topic === "a11y-consumers-changed") {
// This event is fired when accessibility service consumers change. There
// are 3 possible consumers of a11y service: XPCOM, PlatformAPI (e.g.
// screen readers) and MainProcess. PlatformAPI consumer can only be set
// in parent process, and MainProcess consumer can only be set in child
// process. We only care about PlatformAPI consumer changes because when
// set, we can no longer disable accessibility service.
const { PlatformAPI } = JSON.parse(data);
events.emit(this, "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.
events.emit(this, "can-be-enabled-change", this.canBeEnabled);
this.emit("shutdown");
}
},
@ -277,9 +94,10 @@ const AccessibilityActor = ActorClassWithSpec(accessibilitySpec, {
/**
* Get or create Simulator actor, managed by AccessibilityActor,
* only if webrender is enabled. Simulator applies color filters on an entire viewport.
* This needs to be done using webrender and not an SVG <feColorMatrix> since it is
* accelerated and scrolling with filter applied needs to be smooth (Bug1431466).
* only if webrender is enabled. Simulator applies color filters on an entire
* viewport. This needs to be done using webrender and not an SVG
* <feColorMatrix> since it is accelerated and scrolling with filter applied
* needs to be smooth (Bug1431466).
*
* @return {Object|null}
* SimulatorActor for the current tab.
@ -299,35 +117,14 @@ const AccessibilityActor = ActorClassWithSpec(accessibilitySpec, {
},
/**
* Destroy accessibility service actor. This method also shutsdown
* accessibility service if possible.
* Destroy accessibility actor. This method also shutsdown accessibility
* service if possible.
*/
async destroy() {
if (this.destroyed) {
await this.destroyed;
return;
}
let resolver;
this.destroyed = new Promise(resolve => {
resolver = resolve;
});
Services.obs.removeObserver(this, "a11y-init-or-shutdown");
if (DevToolsServer.isInChildProcess) {
this.messageManager.removeMessageListener(
`${this._msgName}:event`,
this.onMessage
);
} else {
Services.obs.removeObserver(this, "a11y-consumers-changed");
Services.prefs.removeObserver(PREF_ACCESSIBILITY_FORCE_DISABLED, this);
}
Actor.prototype.destroy.call(this);
Services.obs.removeObserver(this, "a11y-init-or-shutdown");
this.walker = null;
this.targetActor = null;
resolver();
},
});

Просмотреть файл

@ -7,10 +7,10 @@ DIRS += [
]
DevToolsModules(
'accessibility-parent.js',
'accessibility.js',
'accessible.js',
'constants.js',
'parent-accessibility.js',
'simulator.js',
'walker.js',
'worker.js',

Просмотреть файл

@ -6,26 +6,20 @@
const { Cc, Ci } = require("chrome");
const Services = require("Services");
const { Actor, ActorClassWithSpec } = require("devtools/shared/protocol");
const {
parentAccessibilitySpec,
} = require("devtools/shared/specs/accessibility");
const PREF_ACCESSIBILITY_FORCE_DISABLED = "accessibility.force_disabled";
/**
* A helper class that does all the work related to accessibility service
* lifecycle (initialization, shutdown, consumer changes, etc) in parent
* parent process. It is not guaranteed that the AccessibilityActor starts in
* parent process and thus triggering these lifecycle functions directly is
* extremely unreliable.
*/
class AccessibilityParent {
constructor(mm, prefix) {
this._msgName = `debug:${prefix}accessibility`;
this.onAccessibilityMessage = this.onAccessibilityMessage.bind(this);
this.setMessageManager(mm);
const ParentAccessibilityActor = ActorClassWithSpec(parentAccessibilitySpec, {
initialize(conn) {
Actor.prototype.initialize.call(this, conn);
this.userPref = Services.prefs.getIntPref(
PREF_ACCESSIBILITY_FORCE_DISABLED
);
Services.obs.addObserver(this, "a11y-consumers-changed");
Services.prefs.addObserver(PREF_ACCESSIBILITY_FORCE_DISABLED, this);
if (this.enabled && !this.accService) {
// Set a local reference to an accessibility service if accessibility was
@ -36,65 +30,16 @@ class AccessibilityParent {
);
}
this.messageManager.sendAsyncMessage(`${this._msgName}:event`, {
topic: "initialized",
data: {
enabled: this.enabled,
Services.obs.addObserver(this, "a11y-consumers-changed");
Services.prefs.addObserver(PREF_ACCESSIBILITY_FORCE_DISABLED, this);
},
bootstrap() {
return {
canBeDisabled: this.canBeDisabled,
canBeEnabled: this.canBeEnabled,
};
},
});
}
/**
* Set up message manager listener to listen for messages coming from the
* AccessibilityActor when it is instantiated in the child process.
*
* @param {Object} mm
* Message manager that corresponds to the current content tab.
*/
setMessageManager(mm) {
if (this.messageManager === mm) {
return;
}
if (this.messageManager) {
// If the browser was swapped we need to reset the message manager.
const oldMM = this.messageManager;
oldMM.removeMessageListener(this._msgName, this.onAccessibilityMessage);
}
this.messageManager = mm;
if (mm) {
mm.addMessageListener(this._msgName, this.onAccessibilityMessage);
}
}
/**
* Content AccessibilityActor message listener.
*
* @param {String} msg
* Name of the action to perform.
*/
onAccessibilityMessage(msg) {
const { action } = msg.json;
switch (action) {
case "enable":
this.enable();
break;
case "disable":
this.disable();
break;
case "disconnect":
this.destroy();
break;
default:
break;
}
}
observe(subject, topic, data) {
if (topic === "a11y-consumers-changed") {
@ -104,10 +49,7 @@ class AccessibilityParent {
// about PlatformAPI consumer changes because when set, we can no longer
// disable accessibility service.
const { PlatformAPI } = JSON.parse(data);
this.messageManager.sendAsyncMessage(`${this._msgName}:event`, {
topic: "can-be-disabled-change",
data: !PlatformAPI,
});
this.emit("can-be-disabled-change", !PlatformAPI);
} else if (
!this.disabling &&
topic === "nsPref:changed" &&
@ -118,12 +60,9 @@ class AccessibilityParent {
// 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.messageManager.sendAsyncMessage(`${this._msgName}:event`, {
topic: "can-be-enabled-change",
data: Services.prefs.getIntPref(PREF_ACCESSIBILITY_FORCE_DISABLED) < 1,
});
}
this.emit("can-be-enabled-change", this.canBeEnabled);
}
},
/**
* A getter that indicates if accessibility service is enabled.
@ -133,7 +72,7 @@ class AccessibilityParent {
*/
get enabled() {
return Services.appinfo.accessibilityEnabled;
}
},
/**
* A getter that indicates if the accessibility service can be disabled.
@ -151,7 +90,7 @@ class AccessibilityParent {
}
return true;
}
},
/**
* A getter that indicates if the accessibility service can be enabled.
@ -161,7 +100,7 @@ class AccessibilityParent {
*/
get canBeEnabled() {
return Services.prefs.getIntPref(PREF_ACCESSIBILITY_FORCE_DISABLED) < 1;
}
},
/**
* Enable accessibility service (via XPCOM service).
@ -174,7 +113,7 @@ class AccessibilityParent {
this.accService = Cc["@mozilla.org/accessibilityService;1"].getService(
Ci.nsIAccessibilityService
);
}
},
/**
* Force disable accessibility service. This method removes the reference to
@ -200,42 +139,18 @@ class AccessibilityParent {
// start again (when value is below 1).
Services.prefs.setIntPref(PREF_ACCESSIBILITY_FORCE_DISABLED, this.userPref);
delete this.disabling;
}
},
/**
* Destroy thie helper class, remove all listeners and if possible disable
* accessibility service in the parent process.
*/
destroy() {
Actor.prototype.destroy.call(this);
Services.obs.removeObserver(this, "a11y-consumers-changed");
Services.prefs.removeObserver(PREF_ACCESSIBILITY_FORCE_DISABLED, this);
this.setMessageManager(null);
this.accService = null;
}
}
/**
* Setup function that runs in parent process and setups AccessibleActor bits
* that must always run in parent process.
*
* @param {Object} options.mm
* Message manager that corresponds to the current content tab.
* @param {String} options.prefix
* Unique prefix for message manager messages.
* @return {Object}
* Defines event listeners for when client disconnects or browser gets
* swapped.
*/
function setupParentProcess({ mm, prefix }) {
let accessibility = new AccessibilityParent(mm, prefix);
return {
onBrowserSwap: newMM => accessibility.setMessageManager(newMM),
onDisconnected: () => {
accessibility.destroy();
accessibility = null;
},
};
}
});
exports.setupParentProcess = setupParentProcess;
exports.ParentAccessibilityActor = ParentAccessibilityActor;

Просмотреть файл

@ -156,6 +156,19 @@ const ActorRegistry = {
constructor: "PerfActor",
type: { global: true },
});
/**
* Always register parent accessibility actor as a global module. This
* actor is responsible for all top level accessibility actor functionality
* that relies on the parent process.
*/
this.registerModule(
"devtools/server/actors/accessibility/parent-accessibility",
{
prefix: "parentAccessibility",
constructor: "ParentAccessibilityActor",
type: { global: true },
}
);
},
/**

Просмотреть файл

@ -12,6 +12,7 @@ const {
accessibleSpec,
accessibleWalkerSpec,
accessibilitySpec,
parentAccessibilitySpec,
simulatorSpec,
} = require("devtools/shared/specs/accessibility");
const events = require("devtools/shared/event-emitter");
@ -180,10 +181,14 @@ class AccessibilityFront extends FrontClassWithSpec(accessibilitySpec) {
this.before("init", this.init.bind(this));
this.before("shutdown", this.shutdown.bind(this));
// TODO: Deprecated. Remove after Fx75.
this.before("can-be-enabled-change", this.canBeEnabled.bind(this));
// TODO: Deprecated. Remove after Fx75.
this.before("can-be-disabled-change", this.canBeDisabled.bind(this));
// Attribute name from which to retrieve the actorID out of the target actor's form
// Attribute name from which to retrieve the actorID out of the target
// actor's form
this.formAttributeName = "accessibilityActor";
}
@ -200,6 +205,7 @@ class AccessibilityFront extends FrontClassWithSpec(accessibilitySpec) {
async bootstrap() {
this.accessibleWalkerFront = await super.getWalker();
this.simulatorFront = await super.getSimulator();
// TODO: Deprecated. Remove canBeEnabled and canBeDisabled after Fx75.
({
enabled: this.enabled,
canBeEnabled: this.canBeEnabled,
@ -215,6 +221,37 @@ class AccessibilityFront extends FrontClassWithSpec(accessibilitySpec) {
this.enabled = false;
}
// TODO: Deprecated. Remove after Fx75.
canBeEnabled(canBeEnabled) {
this.canBeEnabled = canBeEnabled;
}
// TODO: Deprecated. Remove after Fx75.
canBeDisabled(canBeDisabled) {
this.canBeDisabled = canBeDisabled;
}
}
class ParentAccessibilityFront extends FrontClassWithSpec(
parentAccessibilitySpec
) {
constructor(client, targetFront, parentFront) {
super(client, targetFront, parentFront);
this.before("can-be-enabled-change", this.canBeEnabled.bind(this));
this.before("can-be-disabled-change", this.canBeDisabled.bind(this));
// Attribute name from which to retrieve the actorID out of the target
// actor's form
this.formAttributeName = "parentAccessibilityActor";
}
async initialize() {
({
canBeEnabled: this.canBeEnabled,
canBeDisabled: this.canBeDisabled,
} = await super.bootstrap());
}
canBeEnabled(canBeEnabled) {
this.canBeEnabled = canBeEnabled;
}
@ -232,5 +269,7 @@ exports.AccessibleWalkerFront = AccessibleWalkerFront;
registerFront(AccessibleWalkerFront);
exports.AccessibilityFront = AccessibilityFront;
registerFront(AccessibilityFront);
exports.ParentAccessibilityFront = ParentAccessibilityFront;
registerFront(ParentAccessibilityFront);
exports.SimulatorFront = SimulatorFront;
registerFront(SimulatorFront);

Просмотреть файл

@ -414,6 +414,19 @@ class RootFront extends FrontClassWithSpec(rootSpec) {
this.fronts.set(typeName, front);
return front;
}
/*
* This function returns true if the root actor has a registered global actor
* with a given name.
* @param {String} actorName
* The name of a global actor.
*
* @return {Boolean}
*/
async hasActor(actorName) {
const rootForm = await this.rootForm;
return !!rootForm[actorName + "Actor"];
}
}
exports.RootFront = RootFront;
registerFront(RootFront);

Просмотреть файл

@ -222,10 +222,12 @@ const accessibilitySpec = generateActorSpec({
shutdown: {
type: "shutdown",
},
// TODO: Deprecated. Remove after Fx75.
"can-be-disabled-change": {
type: "canBeDisabledChange",
canBeDisabled: Arg(0, "boolean"),
},
// TODO: Deprecated. Remove after Fx75.
"can-be-enabled-change": {
type: "canBeEnabledChange",
canBeEnabled: Arg(0, "boolean"),
@ -251,6 +253,40 @@ const accessibilitySpec = generateActorSpec({
simulator: RetVal("nullable:simulator"),
},
},
// TODO: Deprecated. Remove after Fx75.
enable: {
request: {},
response: {},
},
// TODO: Deprecated. Remove after Fx75.
disable: {
request: {},
response: {},
},
},
});
const parentAccessibilitySpec = generateActorSpec({
typeName: "parentaccessibility",
events: {
"can-be-disabled-change": {
type: "canBeDisabledChange",
canBeDisabled: Arg(0, "boolean"),
},
"can-be-enabled-change": {
type: "canBeEnabledChange",
canBeEnabled: Arg(0, "boolean"),
},
},
methods: {
bootstrap: {
request: {},
response: {
state: RetVal("json"),
},
},
enable: {
request: {},
response: {},
@ -265,4 +301,5 @@ const accessibilitySpec = generateActorSpec({
exports.accessibleSpec = accessibleSpec;
exports.accessibleWalkerSpec = accessibleWalkerSpec;
exports.accessibilitySpec = accessibilitySpec;
exports.parentAccessibilitySpec = parentAccessibilitySpec;
exports.simulatorSpec = simulatorSpec;

Просмотреть файл

@ -13,7 +13,12 @@
// This array should be sorted by `spec` attribute.
const Types = (exports.__TypesForTests = [
{
types: ["accessible", "accessiblewalker", "accessibility"],
types: [
"accessible",
"accessiblewalker",
"accessibility",
"parentaccessibility",
],
spec: "devtools/shared/specs/accessibility",
front: "devtools/shared/fronts/accessibility",
},