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

Side by Side Diff: chrome/renderer/resources/extensions/automation_custom_bindings.js

Issue 1705853002: NOT FOR REVIEW. ax tree focus with debugging (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed crash Created 4 years, 10 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 // Custom bindings for the automation API. 5 // Custom bindings for the automation API.
6 var AutomationNode = require('automationNode').AutomationNode; 6 var AutomationNode = require('automationNode').AutomationNode;
7 var AutomationRootNode = require('automationNode').AutomationRootNode; 7 var AutomationRootNode = require('automationNode').AutomationRootNode;
8 var automation = require('binding').Binding.create('automation'); 8 var automation = require('binding').Binding.create('automation');
9 var automationInternal = 9 var automationInternal =
10 require('binding').Binding.create('automationInternal').generate(); 10 require('binding').Binding.create('automationInternal').generate();
11 var eventBindings = require('event_bindings'); 11 var eventBindings = require('event_bindings');
12 var Event = eventBindings.Event; 12 var Event = eventBindings.Event;
13 var exceptionHandler = require('uncaught_exception_handler'); 13 var exceptionHandler = require('uncaught_exception_handler');
14 var forEach = require('utils').forEach; 14 var forEach = require('utils').forEach;
15 var lastError = require('lastError'); 15 var lastError = require('lastError');
16 var logging = requireNative('logging'); 16 var logging = requireNative('logging');
17 var nativeAutomationInternal = requireNative('automationInternal'); 17 var nativeAutomationInternal = requireNative('automationInternal');
18 var GetRoutingID = nativeAutomationInternal.GetRoutingID; 18 var GetRoutingID = nativeAutomationInternal.GetRoutingID;
19 var GetSchemaAdditions = nativeAutomationInternal.GetSchemaAdditions; 19 var GetSchemaAdditions = nativeAutomationInternal.GetSchemaAdditions;
20 var DestroyAccessibilityTree = 20 var DestroyAccessibilityTree =
21 nativeAutomationInternal.DestroyAccessibilityTree; 21 nativeAutomationInternal.DestroyAccessibilityTree;
22 var GetIntAttribute = nativeAutomationInternal.GetIntAttribute; 22 var GetIntAttribute = nativeAutomationInternal.GetIntAttribute;
23 var StartCachingAccessibilityTrees = 23 var StartCachingAccessibilityTrees =
24 nativeAutomationInternal.StartCachingAccessibilityTrees; 24 nativeAutomationInternal.StartCachingAccessibilityTrees;
25 var AddTreeChangeObserver = nativeAutomationInternal.AddTreeChangeObserver; 25 var AddTreeChangeObserver = nativeAutomationInternal.AddTreeChangeObserver;
26 var RemoveTreeChangeObserver = 26 var RemoveTreeChangeObserver =
27 nativeAutomationInternal.RemoveTreeChangeObserver; 27 nativeAutomationInternal.RemoveTreeChangeObserver;
28 var GetFocus = nativeAutomationInternal.GetFocus;
28 var schema = GetSchemaAdditions(); 29 var schema = GetSchemaAdditions();
29 30
30 /** 31 /**
31 * A namespace to export utility functions to other files in automation. 32 * A namespace to export utility functions to other files in automation.
32 */ 33 */
33 window.automationUtil = function() {}; 34 window.automationUtil = function() {};
34 35
35 // TODO(aboxhall): Look into using WeakMap 36 // TODO(aboxhall): Look into using WeakMap
36 var idToCallback = {}; 37 var idToCallback = {};
37 38
(...skipping 21 matching lines...) Expand all
59 * @type {Object<number, TreeChangeObserver>} 60 * @type {Object<number, TreeChangeObserver>}
60 */ 61 */
61 automationUtil.treeChangeObserverMap = {}; 62 automationUtil.treeChangeObserverMap = {};
62 63
63 /** 64 /**
64 * The id of the next tree change observer. 65 * The id of the next tree change observer.
65 * @type {number} 66 * @type {number}
66 */ 67 */
67 automationUtil.nextTreeChangeObserverId = 1; 68 automationUtil.nextTreeChangeObserverId = 1;
68 69
70 /**
71 * @type {AutomationNode} The current focused node. This is only updated
72 * when calling automationUtil.updateFocusedNode.
73 */
74 automationUtil.focusedNode = null;
75
76 /**
77 * Update automationUtil.focusedNode to be the node that currently has focus.
78 */
79 automationUtil.updateFocusedNode = function() {
80 automationUtil.focusedNode = null;
81 console.log('updateFocusedNode calling GetFocus');
82 var focusedNodeInfo = GetFocus(DESKTOP_TREE_ID);
83 console.log('updateFocusedNode calling GetFocus done:');
84 console.log(focusedNodeInfo);
85 console.log(JSON.stringify(focusedNodeInfo));
86 if (!focusedNodeInfo) {
87 console.log('updateFocusedNode return 1');
88 return;
89 }
90 var tree = AutomationRootNode.getOrCreate(focusedNodeInfo.treeId);
91 if (tree) {
92 console.log('updateFocusedNode return 2');
93 automationUtil.focusedNode =
94 privates(tree).impl.get(focusedNodeInfo.nodeId);
95 } else {
96 console.log('updateFocusedNode return 3');
97 }
98
99 console.log('updateFocusedNode returning: ' + automationUtil.focusedNode);
100 };
101
69 automation.registerCustomHook(function(bindingsAPI) { 102 automation.registerCustomHook(function(bindingsAPI) {
70 var apiFunctions = bindingsAPI.apiFunctions; 103 var apiFunctions = bindingsAPI.apiFunctions;
71 104
72 // TODO(aboxhall, dtseng): Make this return the speced AutomationRootNode obj. 105 // TODO(aboxhall, dtseng): Make this return the speced AutomationRootNode obj.
73 apiFunctions.setHandleRequest('getTree', function getTree(tabID, callback) { 106 apiFunctions.setHandleRequest('getTree', function getTree(tabID, callback) {
74 var routingID = GetRoutingID(); 107 var routingID = GetRoutingID();
75 StartCachingAccessibilityTrees(); 108 StartCachingAccessibilityTrees();
76 109
77 // enableTab() ensures the renderer for the active or specified tab has 110 // enableTab() ensures the renderer for the active or specified tab has
78 // accessibility enabled, and fetches its ax tree id to use as 111 // accessibility enabled, and fetches its ax tree id to use as
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 AutomationRootNode.destroy(DESKTOP_TREE_ID); 144 AutomationRootNode.destroy(DESKTOP_TREE_ID);
112 callback(); 145 callback();
113 return; 146 return;
114 } 147 }
115 }); 148 });
116 } else { 149 } else {
117 callback(desktopTree); 150 callback(desktopTree);
118 } 151 }
119 }); 152 });
120 153
154 apiFunctions.setHandleRequest('getFocus', function() {
155 console.log('automation_custom_bindings getFocus');
156 automationUtil.updateFocusedNode();
157 console.log('automation_custom_bindings getFocus 2');
158 console.log('automation_custom_bindings getFocus 2 returning: ' +
159 automationUtil.focusedNode);
160 return automationUtil.focusedNode;
161 });
162
121 function removeTreeChangeObserver(observer) { 163 function removeTreeChangeObserver(observer) {
122 for (var id in automationUtil.treeChangeObserverMap) { 164 for (var id in automationUtil.treeChangeObserverMap) {
123 if (automationUtil.treeChangeObserverMap[id] == observer) { 165 if (automationUtil.treeChangeObserverMap[id] == observer) {
124 RemoveTreeChangeObserver(id); 166 RemoveTreeChangeObserver(id);
125 delete automationUtil.treeChangeObserverMap[id]; 167 delete automationUtil.treeChangeObserverMap[id];
126 return; 168 return;
127 } 169 }
128 } 170 }
129 } 171 }
130 apiFunctions.setHandleRequest('removeTreeChangeObserver', function(observer) { 172 apiFunctions.setHandleRequest('removeTreeChangeObserver', function(observer) {
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 automationInternal.onNodesRemoved.addListener(function(treeID, nodeIDs) { 266 automationInternal.onNodesRemoved.addListener(function(treeID, nodeIDs) {
225 var tree = AutomationRootNode.getOrCreate(treeID); 267 var tree = AutomationRootNode.getOrCreate(treeID);
226 if (!tree) 268 if (!tree)
227 return; 269 return;
228 270
229 for (var i = 0; i < nodeIDs.length; i++) { 271 for (var i = 0; i < nodeIDs.length; i++) {
230 privates(tree).impl.remove(nodeIDs[i]); 272 privates(tree).impl.remove(nodeIDs[i]);
231 } 273 }
232 }); 274 });
233 275
234 // Listen to the automationInternal.onAccessibilityEvent event, which is 276 /**
235 // essentially a proxy for the AccessibilityHostMsg_Events IPC from the 277 * Dispatch accessibility events fired on individual nodes to its
236 // renderer. 278 * corresponding AutomationNode. Handle focus events specially
237 automationInternal.onAccessibilityEvent.addListener(function(data) { 279 * (see below).
238 var id = data.treeID; 280 */
281 automationInternal.onAccessibilityEvent.addListener(function(eventParams) {
282 var id = eventParams.treeID;
239 var targetTree = AutomationRootNode.getOrCreate(id); 283 var targetTree = AutomationRootNode.getOrCreate(id);
240 284
241 if (!privates(targetTree).impl.onAccessibilityEvent(data)) 285 // When we get a focus event, ignore the actual event target, and instead
286 // check what node has focus globally. If that represents a focus change,
287 // fire a focus event on the correct target.
288 if (eventParams.eventType == schema.EventType.focus) {
289 var previousFocusedNode = automationUtil.focusedNode;
290 automationUtil.updateFocusedNode();
291 if (automationUtil.focusedNode &&
292 automationUtil.focusedNode == previousFocusedNode) {
293 return;
294 }
295
296 if (automationUtil.focusedNode) {
297 targetTree = automationUtil.focusedNode.root;
298 eventParams.treeID = privates(targetTree).impl.treeID;
299 eventParams.targetID = privates(automationUtil.focusedNode).impl.id;
300 }
301 }
302
303 if (!privates(targetTree).impl.onAccessibilityEvent(eventParams))
242 return; 304 return;
243 305
244 // If we're not waiting on a callback to getTree(), we can early out here. 306 // If we're not waiting on a callback to getTree(), we can early out here.
245 if (!(id in idToCallback)) 307 if (!(id in idToCallback))
246 return; 308 return;
247 309
248 // We usually get a 'placeholder' tree first, which doesn't have any url 310 // We usually get a 'placeholder' tree first, which doesn't have any url
249 // attribute or child nodes. If we've got that, wait for the full tree before 311 // attribute or child nodes. If we've got that, wait for the full tree before
250 // calling the callback. 312 // calling the callback.
251 // TODO(dmazzoni): Don't send down placeholder (crbug.com/397553) 313 // TODO(dmazzoni): Don't send down placeholder (crbug.com/397553)
(...skipping 26 matching lines...) Expand all
278 }); 340 });
279 341
280 exports.binding = automation.generate(); 342 exports.binding = automation.generate();
281 343
282 // Add additional accessibility bindings not specified in the automation IDL. 344 // Add additional accessibility bindings not specified in the automation IDL.
283 // Accessibility and automation share some APIs (see 345 // Accessibility and automation share some APIs (see
284 // ui/accessibility/ax_enums.idl). 346 // ui/accessibility/ax_enums.idl).
285 forEach(schema, function(k, v) { 347 forEach(schema, function(k, v) {
286 exports.binding[k] = v; 348 exports.binding[k] = v;
287 }); 349 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698