blob: 75ff34a7cc3cb7407febd10d7d2c2f30b7f2d63e [file] [log] [blame]
// Copyright 2019 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.
/**
* Class to handle interactions with the Switch Access back button.
*/
class BackButtonManager {
/**
* @param {!NavigationManager} navigationManager
*/
constructor(navigationManager) {
/**
* Keeps track of when the back button is open and appears alone
* (rather than as part of the menu).
* @private {boolean}
*/
this.backButtonOpen_ = false;
/** @private {!NavigationManager} */
this.navigationManager_ = navigationManager;
/** @private {PanelInterface} */
this.menuPanel_;
/** @private {chrome.automation.AutomationNode} */
this.backButtonNode_;
}
/**
* Shows the menu as just a back button in the upper right corner of the
* node.
* @param {chrome.accessibilityPrivate.ScreenRect=} nodeLocation
*/
show(nodeLocation) {
if (!nodeLocation)
return;
this.backButtonOpen_ = true;
chrome.accessibilityPrivate.setSwitchAccessMenuState(
true, nodeLocation, 0 /* num_actions */);
this.menuPanel_.setFocusRing(SAConstants.BACK_ID, true);
}
/**
* Resets the effects of show().
*/
hide() {
this.backButtonOpen_ = false;
chrome.accessibilityPrivate.setSwitchAccessMenuState(
false, RectHelper.ZERO_RECT, 0);
this.menuPanel_.setFocusRing(SAConstants.BACK_ID, false);
}
/**
* Selects the back button, hiding the button and exiting the current scope.
* @return {boolean} Whether or not the back button was successfully selected.
*/
select() {
if (this.navigationManager_.selectBackButtonInMenu()) {
return true;
}
if (!this.backButtonOpen_) {
return false;
}
if (this.navigationManager_.leaveKeyboardIfNeeded()) {
return true;
}
this.navigationManager_.exitCurrentScope();
return true;
}
/**
* Returns the back button node, if we have found it.
* @return {chrome.automation.AutomationNode}
*/
backButtonNode() {
return this.backButtonNode_;
}
/**
* Finds the back button node.
* @param {!chrome.automation.AutomationNode} desktop
* @private
*/
findBackButtonNode_(desktop) {
this.backButtonNode_ =
new AutomationTreeWalker(
desktop, constants.Dir.FORWARD,
{visit: (node) => node.htmlAttributes.id === SAConstants.BACK_ID})
.next()
.node;
// TODO(anastasi): Determine appropriate event and listen for it, rather
// than setting a timeout.
if (!this.backButtonNode_) {
setTimeout(this.findBackButtonNode_.bind(this, desktop), 500);
}
}
/**
* Sets the reference to the menu panel, sets up a click handler for the
* back button, and finds the back button node.
* @param {!PanelInterface} menuPanel
* @param {!chrome.automation.AutomationNode} desktop
*/
init(menuPanel, desktop) {
this.menuPanel_ = menuPanel;
// Ensures that the back button behaves the same way when clicked
// as when selected.
const backButtonElement = this.menuPanel_.backButtonElement();
backButtonElement.addEventListener('click', this.select.bind(this));
this.findBackButtonNode_(desktop);
}
}