blob: 740e0a27faab131ec60e2400675b200aea06c744 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* The top-level class for the Switch Access accessibility feature. Handles
* initialization and small matters that don't fit anywhere else in the
* codebase.
*/
class SwitchAccess {
static initialize() {
SwitchAccess.instance = new SwitchAccess();
chrome.automation.getDesktop((desktop) => {
// NavigationManager must be initialized first.
NavigationManager.initialize(desktop);
Commands.initialize();
KeyboardRootNode.startWatchingVisibility();
PreferenceManager.initialize();
});
}
/** @private */
constructor() {
/**
* Feature flag controlling improvement of text input capabilities.
* @private {boolean}
*/
this.enableImprovedTextInput_ = false;
chrome.commandLinePrivate.hasSwitch(
'enable-experimental-accessibility-switch-access-text', (result) => {
this.enableImprovedTextInput_ = result;
});
}
/**
* Returns whether or not the feature flag
* for improved text input is enabled.
* @return {boolean}
*/
improvedTextInputEnabled() {
return this.enableImprovedTextInput_;
}
/**
* Helper function to robustly find a node fitting a given FindParams, even if
* that node has not yet been created.
* Used to find the menu and back button.
* @param {!chrome.automation.FindParams} findParams
* @param {!function(!AutomationNode): void} foundCallback
*/
static findNodeMatching(findParams, foundCallback) {
const desktop = NavigationManager.desktopNode;
// First, check if the node is currently in the tree.
let node = desktop.find(findParams);
if (node) {
foundCallback(node);
return;
}
// If it's not currently in the tree, listen for changes to the desktop
// tree.
const eventHandler = new EventHandler(
desktop, chrome.automation.EventType.CHILDREN_CHANGED,
null /** callback */);
const onEvent = (event) => {
if (event.target.matches(findParams)) {
// If the event target is the node we're looking for, we've found it.
eventHandler.stop();
foundCallback(event.target);
} else if (event.target.children.length > 0) {
// Otherwise, see if one of its children is the node we're looking for.
node = event.target.find(findParams);
if (node) {
eventHandler.stop();
foundCallback(node);
}
}
};
eventHandler.setCallback(onEvent);
eventHandler.start();
}
/*
* Creates and records the specified error.
* @param {SAConstants.ErrorType} errorType
* @param {string} errorString
* @param {boolean} shouldRecover
* @return {!Error}
*/
static error(errorType, errorString, shouldRecover = false) {
if (shouldRecover) {
setTimeout(NavigationManager.moveToValidNode, 0);
}
const errorTypeCountForUMA = Object.keys(SAConstants.ErrorType).length;
chrome.metricsPrivate.recordEnumerationValue(
'Accessibility.CrosSwitchAccess.Error', errorType,
errorTypeCountForUMA);
return new Error(errorString);
}
}