| OLD | NEW |
| 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 * @param {!chrome.automation.AutomationNode} desktop | 10 * @param {!chrome.automation.AutomationNode} desktop |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 this.init_(); | 50 this.init_(); |
| 51 } | 51 } |
| 52 | 52 |
| 53 /** | 53 /** |
| 54 * Highlight colors for the focus ring to distinguish between different types | 54 * Highlight colors for the focus ring to distinguish between different types |
| 55 * of nodes. | 55 * of nodes. |
| 56 * | 56 * |
| 57 * @const | 57 * @const |
| 58 */ | 58 */ |
| 59 AutomationManager.Color = { | 59 AutomationManager.Color = { |
| 60 SCOPE: '#de742f', // dark orange | 60 SCOPE: '#de742f', // dark orange |
| 61 GROUP: '#ffbb33', // light orange | 61 GROUP: '#ffbb33', // light orange |
| 62 LEAF: '#78e428' //light green | 62 LEAF: '#78e428' // light green |
| 63 }; | 63 }; |
| 64 | 64 |
| 65 AutomationManager.prototype = { | 65 AutomationManager.prototype = { |
| 66 /** | 66 /** |
| 67 * Set this.node_, this.root_, and this.desktop_ to the desktop node, and | 67 * Set this.node_, this.root_, and this.desktop_ to the desktop node, and |
| 68 * creates an initial tree walker. | 68 * creates an initial tree walker. |
| 69 * | 69 * |
| 70 * @private | 70 * @private |
| 71 */ | 71 */ |
| 72 init_: function() { | 72 init_: function() { |
| 73 console.log('AutomationNode for desktop is loaded'); | 73 console.log('AutomationNode for desktop is loaded'); |
| 74 this.printNode_(this.node_); | 74 this.printNode_(this.node_); |
| 75 | 75 |
| 76 this.desktop_.addEventListener( | 76 this.desktop_.addEventListener( |
| 77 chrome.automation.EventType.FOCUS, | 77 chrome.automation.EventType.FOCUS, this.handleFocusChange_.bind(this), |
| 78 this.handleFocusChange_.bind(this), | |
| 79 false); | 78 false); |
| 80 | 79 |
| 81 // TODO(elichtenberg): Eventually use a more specific filter than | 80 // TODO(elichtenberg): Eventually use a more specific filter than |
| 82 // ALL_TREE_CHANGES. | 81 // ALL_TREE_CHANGES. |
| 83 chrome.automation.addTreeChangeObserver( | 82 chrome.automation.addTreeChangeObserver( |
| 84 chrome.automation.TreeChangeObserverFilter.ALL_TREE_CHANGES, | 83 chrome.automation.TreeChangeObserverFilter.ALL_TREE_CHANGES, |
| 85 this.handleNodeRemoved_.bind(this)); | 84 this.handleNodeRemoved_.bind(this)); |
| 86 }, | 85 }, |
| 87 | 86 |
| 88 /** | 87 /** |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 handleNodeRemoved_: function(treeChange) { | 151 handleNodeRemoved_: function(treeChange) { |
| 153 // TODO(elichtenberg): Only listen to NODE_REMOVED callbacks. Don't need | 152 // TODO(elichtenberg): Only listen to NODE_REMOVED callbacks. Don't need |
| 154 // any others. | 153 // any others. |
| 155 if (treeChange.type !== chrome.automation.TreeChangeType.NODE_REMOVED) | 154 if (treeChange.type !== chrome.automation.TreeChangeType.NODE_REMOVED) |
| 156 return; | 155 return; |
| 157 | 156 |
| 158 // TODO(elichtenberg): Currently not getting NODE_REMOVED event when whole | 157 // TODO(elichtenberg): Currently not getting NODE_REMOVED event when whole |
| 159 // tree is deleted. Once fixed, can delete this. Should only need to check | 158 // tree is deleted. Once fixed, can delete this. Should only need to check |
| 160 // if target is current node. | 159 // if target is current node. |
| 161 let removedByRWA = | 160 let removedByRWA = |
| 162 treeChange.target.role === chrome.automation.RoleType.ROOT_WEB_AREA | 161 treeChange.target.role === chrome.automation.RoleType.ROOT_WEB_AREA && |
| 163 && !this.node_.role; | 162 !this.node_.role; |
| 164 | 163 |
| 165 if (!removedByRWA && treeChange.target !== this.node_) | 164 if (!removedByRWA && treeChange.target !== this.node_) |
| 166 return; | 165 return; |
| 167 | 166 |
| 168 console.log('Node removed'); | 167 console.log('Node removed'); |
| 169 chrome.accessibilityPrivate.setFocusRing([]); | 168 chrome.accessibilityPrivate.setFocusRing([]); |
| 170 | 169 |
| 171 // Current node not invalid until after treeChange callback, so move to | 170 // Current node not invalid until after treeChange callback, so move to |
| 172 // valid node after callback. Delay added to prevent moving to another | 171 // valid node after callback. Delay added to prevent moving to another |
| 173 // node about to be made invalid. If already at a valid node (e.g., user | 172 // node about to be made invalid. If already at a valid node (e.g., user |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 * @param {!chrome.automation.AutomationNode} scope | 292 * @param {!chrome.automation.AutomationNode} scope |
| 294 * @param {!chrome.automation.AutomationNode=} opt_start | 293 * @param {!chrome.automation.AutomationNode=} opt_start |
| 295 * @private | 294 * @private |
| 296 * @return {!AutomationTreeWalker} | 295 * @return {!AutomationTreeWalker} |
| 297 */ | 296 */ |
| 298 createTreeWalker_: function(scope, opt_start) { | 297 createTreeWalker_: function(scope, opt_start) { |
| 299 // If no explicit start node, start walking the tree from |scope|. | 298 // If no explicit start node, start walking the tree from |scope|. |
| 300 let start = opt_start || scope; | 299 let start = opt_start || scope; |
| 301 | 300 |
| 302 let leafPred = function(node) { | 301 let leafPred = function(node) { |
| 303 return (node !== scope && AutomationPredicate.isSubtreeLeaf(node, scope)) | 302 return (node !== scope && |
| 304 || !AutomationPredicate.isInterestingSubtree(node); | 303 AutomationPredicate.isSubtreeLeaf(node, scope)) || |
| 304 !AutomationPredicate.isInterestingSubtree(node); |
| 305 }; | 305 }; |
| 306 let visitPred = function(node) { | 306 let visitPred = function(node) { |
| 307 // Avoid visiting the top-level root node (i.e., the desktop node). | 307 // Avoid visiting the top-level root node (i.e., the desktop node). |
| 308 return node !== this.desktop_ | 308 return node !== this.desktop_ && |
| 309 && AutomationPredicate.isSubtreeLeaf(node, scope); | 309 AutomationPredicate.isSubtreeLeaf(node, scope); |
| 310 }.bind(this); | 310 }.bind(this); |
| 311 | 311 |
| 312 let restrictions = { | 312 let restrictions = {leaf: leafPred, visit: visitPred}; |
| 313 leaf: leafPred, | |
| 314 visit: visitPred | |
| 315 }; | |
| 316 return new AutomationTreeWalker(start, scope, restrictions); | 313 return new AutomationTreeWalker(start, scope, restrictions); |
| 317 }, | 314 }, |
| 318 | 315 |
| 319 // TODO(elichtenberg): Move print functions to a custom logger class. Only | 316 // TODO(elichtenberg): Move print functions to a custom logger class. Only |
| 320 // log when debuggingEnabled is true. | 317 // log when debuggingEnabled is true. |
| 321 /** | 318 /** |
| 322 * Print out details about a node. | 319 * Print out details about a node. |
| 323 * | 320 * |
| 324 * @param {chrome.automation.AutomationNode} node | 321 * @param {chrome.automation.AutomationNode} node |
| 325 * @private | 322 * @private |
| 326 */ | 323 */ |
| 327 printNode_: function(node) { | 324 printNode_: function(node) { |
| 328 if (node) { | 325 if (node) { |
| 329 console.log('Name = ' + node.name); | 326 console.log('Name = ' + node.name); |
| 330 console.log('Role = ' + node.role); | 327 console.log('Role = ' + node.role); |
| 331 console.log('Root role = ' + node.root.role); | 328 console.log('Root role = ' + node.root.role); |
| 332 if (!node.parent) | 329 if (!node.parent) |
| 333 console.log('At index ' + node.indexInParent + ', has no parent'); | 330 console.log('At index ' + node.indexInParent + ', has no parent'); |
| 334 else { | 331 else { |
| 335 let numSiblings = node.parent.children.length; | 332 let numSiblings = node.parent.children.length; |
| 336 console.log( | 333 console.log( |
| 337 'At index ' + node.indexInParent + ', there are ' | 334 'At index ' + node.indexInParent + ', there are ' + numSiblings + |
| 338 + numSiblings + ' siblings'); | 335 ' siblings'); |
| 339 } | 336 } |
| 340 console.log('Has ' + node.children.length + ' children'); | 337 console.log('Has ' + node.children.length + ' children'); |
| 341 } else { | 338 } else { |
| 342 console.log('Node is null'); | 339 console.log('Node is null'); |
| 343 } | 340 } |
| 344 console.log(node); | 341 console.log(node); |
| 345 console.log('\n'); | 342 console.log('\n'); |
| 346 }, | 343 }, |
| 347 | 344 |
| 348 /** | 345 /** |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 386 */ | 383 */ |
| 387 debugMoveToParent: function() { | 384 debugMoveToParent: function() { |
| 388 let parent = this.treeWalker_.debugMoveToParent(this.node_); | 385 let parent = this.treeWalker_.debugMoveToParent(this.node_); |
| 389 if (parent) { | 386 if (parent) { |
| 390 this.node_ = parent; | 387 this.node_ = parent; |
| 391 this.printNode_(this.node_); | 388 this.printNode_(this.node_); |
| 392 chrome.accessibilityPrivate.setFocusRing([this.node_.location]); | 389 chrome.accessibilityPrivate.setFocusRing([this.node_.location]); |
| 393 } | 390 } |
| 394 } | 391 } |
| 395 }; | 392 }; |
| OLD | NEW |