| 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..fd2ddd84f14d8361fecf4916d685e5287e9373be 100644
|
| --- a/chrome/renderer/resources/extensions/automation/automation_node.js
|
| +++ b/chrome/renderer/resources/extensions/automation/automation_node.js
|
| @@ -14,6 +14,12 @@ var schema = requireNative('automationInternal').GetSchemaAdditions();
|
| var utils = require('utils');
|
|
|
| /**
|
| + * Maps an accessibility tree id to an AutomationNode with role type webView.
|
| + * @type {!Object.<string, string>}
|
| + */
|
| +var idToWebView_ = {};
|
| +
|
| +/**
|
| * A single node in the Automation tree.
|
| * @param {AutomationRootNodeImpl} root The root of the tree.
|
| * @constructor
|
| @@ -40,18 +46,21 @@ AutomationNodeImpl.prototype = {
|
| },
|
|
|
| parent: function() {
|
| + if (this.role == schema.RoleType.rootWebArea) {
|
| + if (idToWebView_[this.treeID])
|
| + return idToWebView_[this.treeID];
|
| + }
|
| return this.rootImpl.get(this.parentID);
|
| },
|
|
|
| firstChild: function() {
|
| - var node = this.rootImpl.get(this.childIds[0]);
|
| - return node;
|
| + return this.lookupWebViewChild_() || 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.lookupWebViewChild_() ||
|
| + this.rootImpl.get(childIds[childIds.length - 1]);
|
| },
|
|
|
| children: function() {
|
| @@ -118,7 +127,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 +152,13 @@ AutomationNodeImpl.prototype = {
|
| ' attributes=' + $JSON.stringify(this.attributes);
|
| },
|
|
|
| + lookupWebViewChild_: function() {
|
| + if (this.role != schema.RoleType.webView)
|
| + return null;
|
| +
|
| + return automationUtil.idToAutomationRootNode[this.childTreeID];
|
| + },
|
| +
|
| dispatchEventAtCapturing_: function(event, path) {
|
| privates(event).impl.eventPhase = Event.CAPTURING_PHASE;
|
| for (var i = path.length - 1; i >= 0; i--) {
|
| @@ -194,8 +209,7 @@ AutomationNodeImpl.prototype = {
|
|
|
| performAction_: function(actionType, opt_args) {
|
| // Not yet initialized.
|
| - if (this.rootImpl.processID === undefined ||
|
| - this.rootImpl.routingID === undefined ||
|
| + if (this.rootImpl.treeID === undefined ||
|
| this.id === undefined) {
|
| return;
|
| }
|
| @@ -206,8 +220,7 @@ AutomationNodeImpl.prototype = {
|
| ' {"interact": true} in the "automation" manifest key.');
|
| }
|
|
|
| - automationInternal.performAction({ processID: this.rootImpl.processID,
|
| - routingID: this.rootImpl.routingID,
|
| + automationInternal.performAction({ treeID: this.rootImpl.treeID,
|
| automationNodeID: this.id,
|
| actionType: actionType },
|
| opt_args || {});
|
| @@ -255,6 +268,7 @@ var ATTRIBUTE_NAME_TO_ATTRIBUTE_ID = {
|
| * @const
|
| */
|
| var ATTRIBUTE_BLACKLIST = {'activedescendantId': true,
|
| + 'childTreeId': true,
|
| 'controlsIds': true,
|
| 'describedbyIds': true,
|
| 'flowtoIds': true,
|
| @@ -276,14 +290,13 @@ var ATTRIBUTE_BLACKLIST = {'activedescendantId': true,
|
| * AutomationNode object.
|
| * Thus, tree traversals amount to a lookup in our hash.
|
| *
|
| - * The tree itself is identified by the process id and routing id of the
|
| + * The tree itself is identified by the accessibility tree id of the
|
| * renderer widget host.
|
| * @constructor
|
| */
|
| -function AutomationRootNodeImpl(processID, routingID) {
|
| +function AutomationRootNodeImpl(treeID) {
|
| AutomationNodeImpl.call(this, this);
|
| - this.processID = processID;
|
| - this.routingID = routingID;
|
| + this.treeID = treeID;
|
| this.axNodeDataCache_ = {};
|
| }
|
|
|
| @@ -292,6 +305,8 @@ AutomationRootNodeImpl.prototype = {
|
|
|
| isRootNode: true,
|
|
|
| + role: 'rootWebArea',
|
| +
|
| get: function(id) {
|
| if (id == undefined)
|
| return undefined;
|
| @@ -353,6 +368,7 @@ AutomationRootNodeImpl.prototype = {
|
| destroy: function() {
|
| this.dispatchEvent(schema.EventType.destroyed);
|
| this.invalidate_(this.wrapper);
|
| + idToWebView_[this.treeID] = undefined;
|
| },
|
|
|
| onAccessibilityEvent: function(eventParams) {
|
| @@ -406,19 +422,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 +464,7 @@ AutomationRootNodeImpl.prototype = {
|
| createNewChildren_: function(node, newChildIds, updateState) {
|
| logging.CHECK(node);
|
| var success = true;
|
| +
|
| for (var i = 0; i < newChildIds.length; i++) {
|
| var childId = newChildIds[i];
|
| var childNode = this.axNodeDataCache_[childId];
|
| @@ -495,6 +503,21 @@ AutomationRootNodeImpl.prototype = {
|
|
|
| setData_: function(node, nodeData) {
|
| var nodeImpl = privates(node).impl;
|
| +
|
| + if (nodeData.role == schema.RoleType.webView) {
|
| + if (nodeImpl.pendingChildFrame === undefined)
|
| + nodeImpl.pendingChildFrame = true;
|
| +
|
| + if (nodeImpl.pendingChildFrame) {
|
| + nodeImpl.childTreeID = nodeData.intAttributes.childTreeId;
|
| + idToWebView_[nodeImpl.childTreeID] = node;
|
| + automationInternal.enableFrame(nodeImpl.childTreeID);
|
| + automationUtil.storeTreeCallback(nodeImpl.childTreeID, function(root) {
|
| + nodeImpl.pendingChildFrame = false;
|
| + nodeImpl.dispatchEvent(schema.EventType.childrenChanged);
|
| + });
|
| + }
|
| + }
|
| for (var key in AutomationAttributeDefaults) {
|
| if (key in nodeData)
|
| nodeImpl[key] = nodeData[key];
|
| @@ -609,9 +632,7 @@ var AutomationNode = utils.expose('AutomationNode',
|
|
|
| var AutomationRootNode = utils.expose('AutomationRootNode',
|
| AutomationRootNodeImpl,
|
| - { superclass: AutomationNode,
|
| - functions: ['load'],
|
| - readonly: ['loaded'] });
|
| + { superclass: AutomationNode });
|
|
|
| exports.AutomationNode = AutomationNode;
|
| exports.AutomationRootNode = AutomationRootNode;
|
|
|