| Index: chrome/renderer/resources/extensions/automation/automation_node.js
|
| diff --git a/chrome/renderer/resources/extensions/automation/automation_node.js b/chrome/renderer/resources/extensions/automation/automation_node.js
|
| index fb851690585913880b3ba70de3c1a2f1ea4dbd09..bab41bdef70b189cd772b26ef482ca20ac944efd 100644
|
| --- a/chrome/renderer/resources/extensions/automation/automation_node.js
|
| +++ b/chrome/renderer/resources/extensions/automation/automation_node.js
|
| @@ -14,6 +14,14 @@ var schema = requireNative('automationInternal').GetSchemaAdditions();
|
| var utils = require('utils');
|
|
|
| /**
|
| + * Maps an id in the form:
|
| + * <process_id>_<routing_id>
|
| + * to an AutomationNode with role type webArea.
|
| + * @type {!Object.<string, string>}
|
| + */
|
| +var idToWebArea_ = {};
|
| +
|
| +/**
|
| * A single node in the Automation tree.
|
| * @param {AutomationRootNodeImpl} root The root of the tree.
|
| * @constructor
|
| @@ -40,18 +48,22 @@ AutomationNodeImpl.prototype = {
|
| },
|
|
|
| parent: function() {
|
| + if (this.role == schema.RoleType.rootWebArea) {
|
| + var parentId = this.processID + '_' + this.routingID;
|
| + if (idToWebArea_[parentId])
|
| + return idToWebArea_[parentId];
|
| + }
|
| return this.rootImpl.get(this.parentID);
|
| },
|
|
|
| firstChild: function() {
|
| - var node = this.rootImpl.get(this.childIds[0]);
|
| - return node;
|
| + return this.lookupWebAreaChild_() || this.rootImpl.get(this.childIds[0]);
|
| },
|
|
|
| lastChild: function() {
|
| var childIds = this.childIds;
|
| - var node = this.rootImpl.get(childIds[childIds.length - 1]);
|
| - return node;
|
| + return this.lookupWebAreaChild_() ||
|
| + this.rootImpl.get(childIds[childIds.length - 1]);
|
| },
|
|
|
| children: function() {
|
| @@ -118,7 +130,6 @@ AutomationNodeImpl.prototype = {
|
| var parent = this.parent();
|
| while (parent) {
|
| path.push(parent);
|
| - // TODO(aboxhall/dtseng): handle unloaded parent node
|
| parent = parent.parent();
|
| }
|
| var event = new AutomationEvent(eventType, this.wrapper);
|
| @@ -144,6 +155,15 @@ AutomationNodeImpl.prototype = {
|
| ' attributes=' + $JSON.stringify(this.attributes);
|
| },
|
|
|
| + lookupWebAreaChild_: function() {
|
| + if (this.role != schema.RoleType.webArea)
|
| + return null;
|
| +
|
| + return automationUtil.idToAutomationRootNode[
|
| + automationUtil.createAutomationRootNodeID(
|
| + this.processID, this.routingID)];
|
| + },
|
| +
|
| dispatchEventAtCapturing_: function(event, path) {
|
| privates(event).impl.eventPhase = Event.CAPTURING_PHASE;
|
| for (var i = path.length - 1; i >= 0; i--) {
|
| @@ -292,6 +312,8 @@ AutomationRootNodeImpl.prototype = {
|
|
|
| isRootNode: true,
|
|
|
| + loaded: false,
|
| +
|
| get: function(id) {
|
| if (id == undefined)
|
| return undefined;
|
| @@ -353,6 +375,8 @@ AutomationRootNodeImpl.prototype = {
|
| destroy: function() {
|
| this.dispatchEvent(schema.EventType.destroyed);
|
| this.invalidate_(this.wrapper);
|
| + idToWebArea_[automationUtil.createAutomationRootNodeID(this.processID,
|
| + this.routingID)] = undefined;
|
| },
|
|
|
| onAccessibilityEvent: function(eventParams) {
|
| @@ -406,19 +430,10 @@ AutomationRootNodeImpl.prototype = {
|
| nodeImpl[key] = AutomationAttributeDefaults[key];
|
| }
|
| nodeImpl.childIds = [];
|
| - nodeImpl.loaded = false;
|
| nodeImpl.id = id;
|
| delete this.axNodeDataCache_[id];
|
| },
|
|
|
| - load: function(callback) {
|
| - // TODO(dtseng/aboxhall): Implement.
|
| - if (!this.loaded)
|
| - throw 'Unsupported state: root node is not loaded.';
|
| -
|
| - setTimeout(callback, 0);
|
| - },
|
| -
|
| deleteOldChildren_: function(node, newChildIds) {
|
| // Create a set of child ids in |src| for fast lookup, and return false
|
| // if a duplicate is found;
|
| @@ -490,11 +505,31 @@ AutomationRootNodeImpl.prototype = {
|
| privates(childNode).impl.parentID = privates(node).impl.id;
|
| }
|
|
|
| + if (node.role == schema.RoleType.webArea && node.children().length == 0) {
|
| + var pid = node.processID;
|
| + var rid = node.attributes.routingID;
|
| + var id = automationUtil.createAutomationRootNodeID(pid, rid);
|
| + var targetTree = automationUtil.idToAutomationRootNode[id];
|
| + if (!targetTree)
|
| + targetTree = new AutomationRootNode(pid, rid);
|
| + automationUtil.idToAutomationRootNode[id] = targetTree;
|
| + }
|
| +
|
| return success;
|
| },
|
|
|
| setData_: function(node, nodeData) {
|
| var nodeImpl = privates(node).impl;
|
| +
|
| + if (nodeData.role == schema.RoleType.webArea) {
|
| + nodeImpl.processID = nodeData.intAttributes.frameId;
|
| + nodeImpl.routingID = nodeData.intAttributes.childFrameId;
|
| + idToWebArea_[nodeImpl.processID +
|
| + '_' +
|
| + nodeImpl.routingID] = node;
|
| + delete nodeData.intAttributes['processId'];
|
| + delete nodeData.intAttributes['routingId'];
|
| + }
|
| for (var key in AutomationAttributeDefaults) {
|
| if (key in nodeData)
|
| nodeImpl[key] = nodeData[key];
|
| @@ -541,6 +576,18 @@ AutomationRootNodeImpl.prototype = {
|
| });
|
| },
|
|
|
| + load: function(callback) {
|
| + if (!this.loaded)
|
| + automationInternal.enableFrame(this.processID, this.routingID);
|
| +
|
| + automationUtil.storeTreeCallback(this.processID, this.routingID,
|
| + function(root) {
|
| + privates(root).impl.loaded = true;
|
| + if (callback)
|
| + callback(root);
|
| + });
|
| + },
|
| +
|
| updateNode_: function(nodeData, updateState) {
|
| var node = this.axNodeDataCache_[nodeData.id];
|
| var didUpdateRoot = false;
|
| @@ -599,7 +646,8 @@ var AutomationNode = utils.expose('AutomationNode',
|
| 'makeVisible',
|
| 'setSelection',
|
| 'addEventListener',
|
| - 'removeEventListener'],
|
| + 'removeEventListener',
|
| + 'load'],
|
| readonly: ['isRootNode',
|
| 'role',
|
| 'state',
|
|
|