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

Unified Diff: chrome/renderer/resources/extensions/automation/automation_node.js

Issue 667713006: Implement automatic load of composed/embedded automation trees (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@lkcr
Patch Set: Created 6 years, 1 month 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 side-by-side diff with in-line comments
Download patch
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',
aboxhall 2014/11/03 17:15:49 Why is this necessary? Won't this come down in the
David Tseng 2014/11/03 19:31:53 It was (if we give callers the placeholder node) w
+
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;
aboxhall 2014/11/03 17:15:49 delete idToWebView_[this.treeID] does the same thi
David Tseng 2014/11/03 19:31:52 Obsolete.
},
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) {
aboxhall 2014/11/03 17:15:49 I think we should have a set of roles which can be
David Tseng 2014/11/03 19:31:53 Added TODO since that seems a bit early at this po
+ if (nodeImpl.pendingChildFrame === undefined)
+ nodeImpl.pendingChildFrame = true;
aboxhall 2014/11/03 17:15:49 Do we want to expose the pendingChildFrame propert
David Tseng 2014/11/03 19:31:52 I'd prefer for the caller to check if there are ch
+
+ if (nodeImpl.pendingChildFrame) {
+ nodeImpl.childTreeID = nodeData.intAttributes.childTreeId;
+ idToWebView_[nodeImpl.childTreeID] = node;
aboxhall 2014/11/03 17:15:49 So the id in idToWebView is the ID of the frame it
David Tseng 2014/11/03 19:31:52 Obsolete with other change.
+ automationInternal.enableFrame(nodeImpl.childTreeID);
+ automationUtil.storeTreeCallback(nodeImpl.childTreeID, function(root) {
aboxhall 2014/11/03 17:15:49 What's preventing us from setting root.id as the s
David Tseng 2014/11/03 19:31:52 I'm pretty sure node ids are not globally unique a
aboxhall 2014/11/03 19:40:18 Ah of course, they won't be unique if they're in d
+ 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',
aboxhall 2014/11/03 17:15:49 Do we still need to expose this type at all?
David Tseng 2014/11/03 19:31:52 Still seems useful at least for testing.
AutomationRootNodeImpl,
- { superclass: AutomationNode,
- functions: ['load'],
- readonly: ['loaded'] });
+ { superclass: AutomationNode });
exports.AutomationNode = AutomationNode;
exports.AutomationRootNode = AutomationRootNode;

Powered by Google App Engine
This is Rietveld 408576698