Commit 75493b12 authored by Katie D's avatar Katie D Committed by Commit Bot

[Switch Access] Recalculate current group when nodes are removed.

When a node in the current group is removed we should check that
the current group is valid, and re-calculate its children.

This change also has some other bugfixes to improve stability
around edgecases.

AX-Relnotes: N/A
Bug: 1105196, 1106575
Change-Id: I0461150aadc42d5bd01099d96bf69d8d1f71119a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2303056Reviewed-by: default avatarAnastasia Helfinstein <anastasi@google.com>
Commit-Queue: Katie Dektar <katie@chromium.org>
Cr-Commit-Position: refs/heads/master@{#789643}
parent 98842155
...@@ -10,9 +10,9 @@ class RepeatedTreeChangeHandler { ...@@ -10,9 +10,9 @@ class RepeatedTreeChangeHandler {
/** /**
* @param {!chrome.automation.TreeChangeObserverFilter} filter * @param {!chrome.automation.TreeChangeObserverFilter} filter
* @param {!function(!chrome.automation.TreeChange)} callback * @param {!function(!chrome.automation.TreeChange)} callback
* @param {{predicate: (function(!chrome.automation.TreeChange): boolean)}} * @param {{predicate: ((function(!chrome.automation.TreeChange): boolean) |
* options * undefined)}} options predicate A generic predicate that filters for
* predicate A generic predicate that filters for changes of interest. * changes of interest.
*/ */
constructor(filter, callback, options = {}) { constructor(filter, callback, options = {}) {
/** @private {!Array<!chrome.automation.TreeChange>} */ /** @private {!Array<!chrome.automation.TreeChange>} */
......
...@@ -161,6 +161,7 @@ js_type_check("closure_compile") { ...@@ -161,6 +161,7 @@ js_type_check("closure_compile") {
"../common:closure_shim", "../common:closure_shim",
"../common:constants", "../common:constants",
"../common:repeated_event_handler", "../common:repeated_event_handler",
"../common:repeated_tree_change_handler",
"../common:tree_walker", "../common:tree_walker",
] ]
} }
......
...@@ -17,6 +17,11 @@ class FocusData { ...@@ -17,6 +17,11 @@ class FocusData {
/** @return {boolean} */ /** @return {boolean} */
isValid() { isValid() {
if (this.group.isValidGroup()) {
// Ensure it is still valid. Some nodes may have been added
// or removed since this was last used.
this.group.refreshChildren();
}
return this.group.isValidGroup(); return this.group.isValidGroup();
} }
} }
......
...@@ -143,7 +143,11 @@ class NavigationManager { ...@@ -143,7 +143,11 @@ class NavigationManager {
*/ */
static moveBackward() { static moveBackward() {
const navigator = NavigationManager.instance; const navigator = NavigationManager.instance;
if (navigator.node_.isValidAndVisible()) {
navigator.setNode_(navigator.node_.previous); navigator.setNode_(navigator.node_.previous);
} else {
NavigationManager.moveToValidNode();
}
} }
/** /**
...@@ -151,7 +155,11 @@ class NavigationManager { ...@@ -151,7 +155,11 @@ class NavigationManager {
*/ */
static moveForward() { static moveForward() {
const navigator = NavigationManager.instance; const navigator = NavigationManager.instance;
if (navigator.node_.isValidAndVisible()) {
navigator.setNode_(navigator.node_.next); navigator.setNode_(navigator.node_.next);
} else {
NavigationManager.moveToValidNode();
}
} }
/** /**
...@@ -251,14 +259,20 @@ class NavigationManager { ...@@ -251,14 +259,20 @@ class NavigationManager {
} }
/** /**
* When the automation tree changes, check if it affects any nodes we are * When the automation tree changes, ensure the group and node we are
* currently listening to. * currently listening to are fresh. This is only called when the tree change
* occurred on the node or group which are currently active.
* @param {!chrome.automation.TreeChange} treeChange * @param {!chrome.automation.TreeChange} treeChange
* @private * @private
*/ */
onTreeChange_(treeChange) { onTreeChange_(treeChange) {
if (treeChange.type === chrome.automation.TreeChangeType.NODE_REMOVED) { if (treeChange.type === chrome.automation.TreeChangeType.NODE_REMOVED) {
this.group_.refresh();
NavigationManager.moveToValidNode(); NavigationManager.moveToValidNode();
} else if (
treeChange.type ===
chrome.automation.TreeChangeType.SUBTREE_UPDATE_END) {
this.group_.refresh();
} }
} }
...@@ -283,6 +297,14 @@ class NavigationManager { ...@@ -283,6 +297,14 @@ class NavigationManager {
this.desktop_, chrome.automation.EventType.SCROLL_POSITION_CHANGED, this.desktop_, chrome.automation.EventType.SCROLL_POSITION_CHANGED,
this.onScrollChange_.bind(this)); this.onScrollChange_.bind(this));
new RepeatedTreeChangeHandler(
chrome.automation.TreeChangeObserverFilter.ALL_TREE_CHANGES,
this.onTreeChange_.bind(this), {
predicate: (treeChange) =>
this.group_.findChild(treeChange.target) != null ||
this.group_.isEquivalentTo(treeChange.target)
});
// The status tray fires a SHOW event when it opens. // The status tray fires a SHOW event when it opens.
this.desktop_.addEventListener( this.desktop_.addEventListener(
chrome.automation.EventType.SHOW, this.onModalDialog_.bind(this), chrome.automation.EventType.SHOW, this.onModalDialog_.bind(this),
...@@ -290,9 +312,6 @@ class NavigationManager { ...@@ -290,9 +312,6 @@ class NavigationManager {
this.desktop_.addEventListener( this.desktop_.addEventListener(
chrome.automation.EventType.MENU_START, this.onModalDialog_.bind(this), chrome.automation.EventType.MENU_START, this.onModalDialog_.bind(this),
false); false);
chrome.automation.addTreeChangeObserver(
chrome.automation.TreeChangeObserverFilter.ALL_TREE_CHANGES,
this.onTreeChange_.bind(this));
} }
/** /**
......
...@@ -77,7 +77,7 @@ class BackButtonNode extends SAChildNode { ...@@ -77,7 +77,7 @@ class BackButtonNode extends SAChildNode {
/** @override */ /** @override */
isValidAndVisible() { isValidAndVisible() {
return true; return this.group_.isValidGroup();
} }
/** @override */ /** @override */
......
...@@ -304,6 +304,16 @@ class RootNodeWrapper extends SARootNode { ...@@ -304,6 +304,16 @@ class RootNodeWrapper extends SARootNode {
} }
} }
/** @override */
refreshChildren() {
const childConstructor = (node) => NodeWrapper.create(node, this);
try {
RootNodeWrapper.findAndSetChildren(this, childConstructor);
} catch (e) {
this.invalidated_ = true;
}
}
/** @override */ /** @override */
refresh() { refresh() {
// Find the currently focused child. // Find the currently focused child.
...@@ -316,12 +326,9 @@ class RootNodeWrapper extends SARootNode { ...@@ -316,12 +326,9 @@ class RootNodeWrapper extends SARootNode {
} }
// Update this RootNodeWrapper's children. // Update this RootNodeWrapper's children.
const childConstructor = (node) => NodeWrapper.create(node, this); this.refreshChildren();
try { if (this.invalidated_) {
RootNodeWrapper.findAndSetChildren(this, childConstructor);
} catch (e) {
this.onUnfocus(); this.onUnfocus();
this.invalidated_ = true;
NavigationManager.moveToValidNode(); NavigationManager.moveToValidNode();
return; return;
} }
......
...@@ -363,8 +363,8 @@ class SARootNode { ...@@ -363,8 +363,8 @@ class SARootNode {
// Must have one interesting child that is not the back button. // Must have one interesting child that is not the back button.
return this.children_ return this.children_
.filter( .filter(
(child) => child.isValidAndVisible() && (child) => !(child instanceof BackButtonNode) &&
!(child instanceof BackButtonNode)) child.isValidAndVisible())
.length >= 1; .length >= 1;
} }
...@@ -384,6 +384,11 @@ class SARootNode { ...@@ -384,6 +384,11 @@ class SARootNode {
/** Called when a group is explicitly exited. */ /** Called when a group is explicitly exited. */
onExit() {} onExit() {}
/** Called when a group should recalculate its children. */
refreshChildren() {
this.children = this.children.filter((child) => child.isValidAndVisible());
}
/** Called when the group's children may have changed. */ /** Called when the group's children may have changed. */
refresh() {} refresh() {}
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
"common/array_util.js", "common/array_util.js",
"common/automation_predicate.js", "common/automation_predicate.js",
"common/repeated_event_handler.js", "common/repeated_event_handler.js",
"common/repeated_tree_change_handler.js",
"common/tree_walker.js", "common/tree_walker.js",
"switch_access/auto_scan_manager.js", "switch_access/auto_scan_manager.js",
"switch_access/commands.js", "switch_access/commands.js",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment