Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(311)

Side by Side Diff: chrome/browser/resources/chromeos/switch_access/automation_manager.js

Issue 2863613003: Implemented scanning by group (Closed)
Patch Set: Responded to comments Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * Class to manage interactions with the accessibility tree, including moving 6 * Class to manage interactions with the accessibility tree, including moving
7 * to and selecting nodes. 7 * to and selecting nodes.
8 * 8 *
9 * @constructor 9 * @constructor
10 */ 10 */
11 function AutomationManager() { 11 function AutomationManager() {
12 /** 12 /**
13 * Currently selected node. 13 * Currently highlighted node.
14 * 14 *
15 * @private {chrome.automation.AutomationNode} 15 * @private {chrome.automation.AutomationNode}
16 */ 16 */
17 this.node_ = null; 17 this.node_ = null;
18 18
19 /** 19 /**
20 * Root node (i.e., the desktop). 20 * The root of the subtree that the user is navigating through.
21 * 21 *
22 * @private {chrome.automation.AutomationNode} 22 * @private {chrome.automation.AutomationNode}
23 */ 23 */
24 this.root_ = null; 24 this.scope_ = null;
25
26 /**
27 * The desktop node.
28 *
29 * @private {chrome.automation.AutomationNode}
30 */
31 this.desktop_ = null;
32
33 /**
34 * A stack of past scopes. Allows user to traverse back to previous groups
35 * after selecting one or more groups. The most recent group is at the end
36 * of the array.
37 *
38 * @private {Array<chrome.automation.AutomationNode>}
39 */
40 this.scopeStack_ = [];
25 41
26 /** 42 /**
27 * Moves to the appropriate node in the accessibility tree. 43 * Moves to the appropriate node in the accessibility tree.
28 * 44 *
29 * @private {AutomationTreeWalker} 45 * @private {AutomationTreeWalker}
30 */ 46 */
31 this.treeWalker_ = null; 47 this.treeWalker_ = null;
32 48
33 this.init_(); 49 this.init_();
34 }; 50 };
35 51
36 AutomationManager.prototype = { 52 AutomationManager.prototype = {
37 /** 53 /**
38 * Set this.node_ and this.root_ to the desktop node, and initialize the 54 * Set this.node_, this.root_, and this.desktop_ to the desktop node, and
39 * tree walker. 55 * creates an initial tree walker.
40 * 56 *
41 * @private 57 * @private
42 */ 58 */
43 init_: function() { 59 init_: function() {
44 this.treeWalker_ = new AutomationTreeWalker();
45
46 chrome.automation.getDesktop(function(desktop) { 60 chrome.automation.getDesktop(function(desktop) {
47 this.node_ = desktop; 61 this.node_ = desktop;
48 this.root_ = desktop; 62 this.scope_ = desktop;
63 this.desktop_ = desktop;
64 this.treeWalker_ = this.createTreeWalker_(desktop);
49 console.log('AutomationNode for desktop is loaded'); 65 console.log('AutomationNode for desktop is loaded');
50 this.printNode_(this.node_); 66 this.printNode_(this.node_);
51 }.bind(this)); 67 }.bind(this));
52 }, 68 },
53 69
54 /** 70 /**
55 * Set this.node_ to the next/previous interesting node, and then highlight 71 * Set this.node_ to the next/previous interesting node, and then highlight
56 * it on the screen. If no interesting node is found, set this.node_ to the 72 * it on the screen. If no interesting node is found, set this.node_ to the
57 * first/last interesting node. If |doNext| is true, will search for next 73 * first/last interesting node. If |doNext| is true, will search for next
58 * node. Otherwise, will search for previous node. 74 * node. Otherwise, will search for previous node.
59 * 75 *
60 * @param {boolean} doNext 76 * @param {boolean} doNext
61 */ 77 */
62 moveToNode: function(doNext) { 78 moveToNode: function(doNext) {
63 let node = this.treeWalker_.moveToNode(this.node_, this.root_, doNext); 79 if (!this.treeWalker_)
80 return;
81
82 let node = this.treeWalker_.moveToNode(doNext);
64 if (node) { 83 if (node) {
65 this.node_ = node; 84 this.node_ = node;
66 this.printNode_(this.node_); 85 this.printNode_(this.node_);
67 chrome.accessibilityPrivate.setFocusRing([this.node_.location]); 86 chrome.accessibilityPrivate.setFocusRing([this.node_.location]);
68 } 87 }
69 }, 88 },
70 89
71 /** 90 /**
72 * Perform the default action on the currently selected node. 91 * Select the currently highlighted node. If the node is the current scope,
92 * go back to the previous scope (i.e., create a new tree walker rooted at
93 * the previous scope). If the node is a group other than the current scope,
94 * create a new tree walker for the new subtree the user is scanning through.
95 * Otherwise, meaning the node is interesting, perform the default action on
96 * it.
73 */ 97 */
74 doDefault: function() { 98 selectCurrentNode: function() {
75 if (!this.node_) 99 if (!this.node_ || !this.scope_ || !this.treeWalker_)
76 return; 100 return;
77 101
102 if (this.node_ === this.scope_) {
103 // Don't let user select the top-level root node (i.e., the desktop node).
104 if (this.scopeStack_.length === 0)
105 return;
106
107 // Find a previous scope that is still valid.
108 let oldScope;
109 do {
110 oldScope = this.scopeStack_.pop();
111 } while (oldScope && !oldScope.role);
112
113 // oldScope will always be valid here, so this will always be true.
114 if (oldScope) {
115 this.scope_ = oldScope;
116 this.treeWalker_ = this.createTreeWalker_(this.scope_, this.node_);
117 }
118 return;
119 }
120
121 if (AutomationPredicate.isGroup(this.node_, this.scope_)) {
122 this.scopeStack_.push(this.scope_);
123 this.scope_ = this.node_;
124 this.treeWalker_ = this.createTreeWalker_(this.scope_);
125 this.moveToNode(true);
126 return;
127 }
128
78 this.node_.doDefault(); 129 this.node_.doDefault();
79 }, 130 },
80 131
132 /**
133 * Create an AutomationTreeWalker for the subtree with |scope| as its root.
134 * If |opt_start| is defined, the tree walker will start walking the tree
135 * from |opt_start|; otherwise, it will start from |scope|.
136 *
137 * @param {!chrome.automation.AutomationNode} scope
138 * @param {!chrome.automation.AutomationNode=} opt_start
139 * @return {!AutomationTreeWalker}
140 */
141 createTreeWalker_: function(scope, opt_start) {
142 // If no explicit start node, start walking the tree from |scope|.
143 let start = opt_start || scope;
144
145 let leafPred = function(node) {
146 return (node !== scope && AutomationPredicate.isSubtreeLeaf(node, scope))
147 || !AutomationPredicate.isInterestingSubtree(node);
148 };
149 let visitPred = function(node) {
150 // Avoid visiting the top-level root node (i.e., the desktop node).
151 return node !== this.desktop_
152 && AutomationPredicate.isSubtreeLeaf(node, scope);
153 }.bind(this);
154
155 let restrictions = {
156 leaf: leafPred,
157 visit: visitPred
158 };
159 return new AutomationTreeWalker(start, scope, restrictions);
160 },
161
81 // TODO(elichtenberg): Move print functions to a custom logger class. Only 162 // TODO(elichtenberg): Move print functions to a custom logger class. Only
82 // log when debuggingEnabled is true. 163 // log when debuggingEnabled is true.
83 /** 164 /**
84 * Print out details about a node. 165 * Print out details about a node.
85 * 166 *
86 * @param {chrome.automation.AutomationNode} node 167 * @param {chrome.automation.AutomationNode} node
87 * @private 168 * @private
88 */ 169 */
89 printNode_: function(node) { 170 printNode_: function(node) {
90 if (node) { 171 if (node) {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 */ 229 */
149 debugMoveToParent: function() { 230 debugMoveToParent: function() {
150 let parent = this.treeWalker_.debugMoveToParent(this.node_); 231 let parent = this.treeWalker_.debugMoveToParent(this.node_);
151 if (parent) { 232 if (parent) {
152 this.node_ = parent; 233 this.node_ = parent;
153 this.printNode_(this.node_); 234 this.printNode_(this.node_);
154 chrome.accessibilityPrivate.setFocusRing([this.node_.location]); 235 chrome.accessibilityPrivate.setFocusRing([this.node_.location]);
155 } 236 }
156 } 237 }
157 }; 238 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698