blob: 6647e02bba3910e394584ee3bc5de8a61e55225f [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.
* @private {boolean}
*/
this.backButtonOpen_ = false;
/** @private {!NavigationManager} */
this.navigationManager_ = navigationManager;
/** @private {PanelInterface} */
this.menuPanel_;
/** @private {chrome.automation.AutomationNode} */
this.buttonNode_;
}
/**
* 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, SAConstants.EMPTY_LOCATION, 0);
this.menuPanel_.setFocusRing(SAConstants.BACK_ID, false);
}
/**
* Selects the back button, hiding the button and exiting the current scope.
*/
select() {
if (!this.backButtonOpen_)
return false;
if (this.navigationManager_.leaveKeyboardIfNeeded())
return true;
this.navigationManager_.exitCurrentScope();
return true;
}
/**
* Returns the button node, if we have found it.
* @return {chrome.automation.AutomationNode}
*/
buttonNode() {
return this.buttonNode_;
}
/**
* Sets the reference to the menu panel and finds the back button node.
* @param {!PanelInterface} menuPanel
*/
init(menuPanel, desktop) {
this.menuPanel_ = menuPanel;
this.buttonNode_ =
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.buttonNode_)
setTimeout(this.init.bind(this, menuPanel, desktop), 500);
}
}