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
3 // found in the LICENSE file.
5 // Custom bindings for the automation API.
6 var automation = require('binding').Binding.create('automation');
7 var automationInternal =
8 require('binding').Binding.create('automationInternal').generate();
9 var eventBindings = require('event_bindings');
10 var Event = eventBindings.Event;
11 var AutomationNode = require('automationNode').AutomationNode;
12 var AutomationTree = require('automationTree').AutomationTree;
14 // TODO(aboxhall): Look into using WeakMap
15 var idToAutomationTree = {};
16 var idToCallback = {};
18 // TODO(dtseng): Move out to automation/automation_util.js or as a static member
19 // of AutomationTree to keep this file clean.
21 * Creates an id associated with a particular AutomationTree based upon a
22 * renderer/renderer host pair's process and routing id.
24 var createAutomationTreeID = function(pid, rid) {
25 return pid + '_' + rid;
28 automation.registerCustomHook(function(bindingsAPI) {
29 var apiFunctions = bindingsAPI.apiFunctions;
31 // TODO(aboxhall, dtseng): Make this return the speced AutomationRootNode obj.
32 apiFunctions.setHandleRequest('getTree', function(callback) {
33 // enableCurrentTab() ensures the renderer for the current tab has
34 // accessibility enabled, and fetches its process and routing ids to use as
35 // a key in the idToAutomationTree map. The callback to enableCurrentTab is
36 // bound to the callback passed in to getTree(), so that once the tree is
37 // available (either due to having been cached earlier, or after an
38 // accessibility event occurs which causes the tree to be populated), the
39 // callback can be called.
40 automationInternal.enableCurrentTab(function(pid, rid) {
41 var id = createAutomationTreeID(pid, rid);
42 var targetTree = idToAutomationTree[id];
44 // If we haven't cached the tree, hold the callback until the tree is
45 // populated by the initial onAccessibilityEvent call.
46 if (id in idToCallback)
47 idToCallback[id].push(callback);
49 idToCallback[id] = [callback];
57 // Listen to the automationInternal.onaccessibilityEvent event, which is
58 // essentially a proxy for the AccessibilityHostMsg_Events IPC from the
60 automationInternal.onAccessibilityEvent.addListener(function(data) {
61 var pid = data.processID;
62 var rid = data.routingID;
63 var id = createAutomationTreeID(pid, rid);
64 var targetTree = idToAutomationTree[id];
66 // If this is the first time we've gotten data for this tree, it will
67 // contain all of the tree's data, so create a new tree which will be
68 // bootstrapped from |data|.
69 targetTree = new AutomationTree(pid, rid);
70 idToAutomationTree[id] = targetTree;
72 privates(targetTree).impl.update(data);
74 var eventType = data.eventType;
75 if (eventType == 'load_complete' || eventType == 'layout_complete') {
76 // If the tree wasn't available when getTree() was called, the callback will
77 // have been cached in idToCallback, so call and delete it now that we
78 // have the complete tree.
79 if (id in idToCallback) {
80 for (var i = 0; i < idToCallback[id].length; i++) {
81 var callback = idToCallback[id][i];
84 delete idToCallback[id];
89 exports.binding = automation.generate();