Chromium Code Reviews| 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..f2600add1c21b5c98808429ea77cc7adefad34eb 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,24 @@ AutomationNodeImpl.prototype = { |
| }, |
| parent: function() { |
| + if (this.role == schema.RoleType.rootWebArea) { |
| + var parentId = automationUtil.createAutomationRootNodeID(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 +132,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 +157,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 +314,10 @@ AutomationRootNodeImpl.prototype = { |
| isRootNode: true, |
| + loaded: false, |
| + |
| + role: 'rootWebArea', |
| + |
| get: function(id) { |
| if (id == undefined) |
| return undefined; |
| @@ -353,6 +379,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 +434,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; |
| @@ -457,6 +476,16 @@ AutomationRootNodeImpl.prototype = { |
| createNewChildren_: function(node, newChildIds, updateState) { |
| logging.CHECK(node); |
| var success = true; |
| + |
| + if (node.role == schema.RoleType.webArea && node.children().length == 0) { |
| + var pid = privates(node).impl.processID; |
|
dmazzoni
2014/10/31 18:28:35
I think it'd be more clear if this was childProces
|
| + var rid = privates(node).impl.routingID; |
| + var id = automationUtil.createAutomationRootNodeID(pid, rid); |
| + var targetTree = automationUtil.idToAutomationRootNode[id]; |
|
dmazzoni
2014/10/31 18:28:35
targetTree -> childTree
|
| + if (!targetTree) |
| + targetTree = new AutomationRootNode(pid, rid); |
| + automationUtil.idToAutomationRootNode[id] = targetTree; |
| + } |
| for (var i = 0; i < newChildIds.length; i++) { |
| var childId = newChildIds[i]; |
| var childNode = this.axNodeDataCache_[childId]; |
| @@ -495,6 +524,15 @@ AutomationRootNodeImpl.prototype = { |
| 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_[automationUtil.createAutomationRootNodeID(nodeImpl.processID, |
| + nodeImpl.routingID)] = node; |
| + delete nodeData.intAttributes['processId']; |
|
dmazzoni
2014/10/31 18:28:35
this doesn't match, should be nodeData.intAttribut
|
| + delete nodeData.intAttributes['routingId']; |
| + } |
| for (var key in AutomationAttributeDefaults) { |
| if (key in nodeData) |
| nodeImpl[key] = nodeData[key]; |
| @@ -541,6 +579,19 @@ 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 +650,8 @@ var AutomationNode = utils.expose('AutomationNode', |
| 'makeVisible', |
| 'setSelection', |
| 'addEventListener', |
| - 'removeEventListener'], |
| + 'removeEventListener', |
| + 'load'], |
| readonly: ['isRootNode', |
| 'role', |
| 'state', |