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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 var AutomationEvent = require('automationEvent').AutomationEvent; 5 var AutomationEvent = require('automationEvent').AutomationEvent;
6 var automationInternal = 6 var automationInternal =
7 require('binding').Binding.create('automationInternal').generate(); 7 require('binding').Binding.create('automationInternal').generate();
8 var IsInteractPermitted = 8 var IsInteractPermitted =
9 requireNative('automationInternal').IsInteractPermitted; 9 requireNative('automationInternal').IsInteractPermitted;
10 10
11 var lastError = require('lastError'); 11 var lastError = require('lastError');
12 var logging = requireNative('logging'); 12 var logging = requireNative('logging');
13 var schema = requireNative('automationInternal').GetSchemaAdditions(); 13 var schema = requireNative('automationInternal').GetSchemaAdditions();
14 var utils = require('utils'); 14 var utils = require('utils');
15 15
16 /** 16 /**
17 * Maps an id in the form:
18 * <process_id>_<routing_id>
19 * to an AutomationNode with role type webArea.
20 * @type {!Object.<string, string>}
21 */
22 var idToWebArea_ = {};
23
24 /**
17 * A single node in the Automation tree. 25 * A single node in the Automation tree.
18 * @param {AutomationRootNodeImpl} root The root of the tree. 26 * @param {AutomationRootNodeImpl} root The root of the tree.
19 * @constructor 27 * @constructor
20 */ 28 */
21 function AutomationNodeImpl(root) { 29 function AutomationNodeImpl(root) {
22 this.rootImpl = root; 30 this.rootImpl = root;
23 this.childIds = []; 31 this.childIds = [];
24 // Public attributes. No actual data gets set on this object. 32 // Public attributes. No actual data gets set on this object.
25 this.attributes = {}; 33 this.attributes = {};
26 // Internal object holding all attributes. 34 // Internal object holding all attributes.
27 this.attributesInternal = {}; 35 this.attributesInternal = {};
28 this.listeners = {}; 36 this.listeners = {};
29 this.location = { left: 0, top: 0, width: 0, height: 0 }; 37 this.location = { left: 0, top: 0, width: 0, height: 0 };
30 } 38 }
31 39
32 AutomationNodeImpl.prototype = { 40 AutomationNodeImpl.prototype = {
33 id: -1, 41 id: -1,
34 role: '', 42 role: '',
35 state: { busy: true }, 43 state: { busy: true },
36 isRootNode: false, 44 isRootNode: false,
45 loaded: false,
37 46
38 get root() { 47 get root() {
39 return this.rootImpl.wrapper; 48 return this.rootImpl.wrapper;
40 }, 49 },
41 50
42 parent: function() { 51 parent: function() {
52 if (this.role == schema.RoleType.rootWebArea) {
53 var parentId = this.processID + '_' + this.routingID;
54 if (idToWebArea_[parentId])
55 return idToWebArea_[parentId];
56 }
43 return this.rootImpl.get(this.parentID); 57 return this.rootImpl.get(this.parentID);
44 }, 58 },
45 59
46 firstChild: function() { 60 firstChild: function() {
47 var node = this.rootImpl.get(this.childIds[0]); 61 return this.lookupWebAreaChild_() || this.rootImpl.get(this.childIds[0]);
48 return node;
49 }, 62 },
50 63
51 lastChild: function() { 64 lastChild: function() {
52 var childIds = this.childIds; 65 var childIds = this.childIds;
53 var node = this.rootImpl.get(childIds[childIds.length - 1]); 66 return this.lookupWebAreaChild_() ||
54 return node; 67 this.rootImpl.get(childIds[childIds.length - 1]);
55 }, 68 },
56 69
57 children: function() { 70 children: function() {
58 var children = []; 71 var children = [];
59 for (var i = 0, childID; childID = this.childIds[i]; i++) { 72 for (var i = 0, childID; childID = this.childIds[i]; i++) {
60 logging.CHECK(this.rootImpl.get(childID)); 73 logging.CHECK(this.rootImpl.get(childID));
61 children.push(this.rootImpl.get(childID)); 74 children.push(this.rootImpl.get(childID));
62 } 75 }
63 return children; 76 return children;
64 }, 77 },
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 removeEventListener: function(eventType, callback) { 119 removeEventListener: function(eventType, callback) {
107 if (this.listeners[eventType]) { 120 if (this.listeners[eventType]) {
108 var listeners = this.listeners[eventType]; 121 var listeners = this.listeners[eventType];
109 for (var i = 0; i < listeners.length; i++) { 122 for (var i = 0; i < listeners.length; i++) {
110 if (callback === listeners[i].callback) 123 if (callback === listeners[i].callback)
111 listeners.splice(i, 1); 124 listeners.splice(i, 1);
112 } 125 }
113 } 126 }
114 }, 127 },
115 128
129 load: function(callback) {
130 if (this.role != schema.RoleType.webArea)
131 throw 'Unsupported state: can only load webArea nodes.';
132
133 if (!this.loaded)
134 automationInternal.enableRenderer(this.processID, this.routingID);
135
136 automationUtil.onTreeLoaded(this.processID, this.routingID, function(root) {
137 if (callback)
138 callback(root);
139 }.bind(this));
140 },
141
116 dispatchEvent: function(eventType) { 142 dispatchEvent: function(eventType) {
117 var path = []; 143 var path = [];
118 var parent = this.parent(); 144 var parent = this.parent();
119 while (parent) { 145 while (parent) {
120 path.push(parent); 146 path.push(parent);
121 // TODO(aboxhall/dtseng): handle unloaded parent node 147 // TODO(aboxhall/dtseng): handle unloaded parent node
122 parent = parent.parent(); 148 parent = parent.parent();
123 } 149 }
124 var event = new AutomationEvent(eventType, this.wrapper); 150 var event = new AutomationEvent(eventType, this.wrapper);
125 151
(...skipping 11 matching lines...) Expand all
137 163
138 toString: function() { 164 toString: function() {
139 return 'node id=' + this.id + 165 return 'node id=' + this.id +
140 ' role=' + this.role + 166 ' role=' + this.role +
141 ' state=' + $JSON.stringify(this.state) + 167 ' state=' + $JSON.stringify(this.state) +
142 ' parentID=' + this.parentID + 168 ' parentID=' + this.parentID +
143 ' childIds=' + $JSON.stringify(this.childIds) + 169 ' childIds=' + $JSON.stringify(this.childIds) +
144 ' attributes=' + $JSON.stringify(this.attributes); 170 ' attributes=' + $JSON.stringify(this.attributes);
145 }, 171 },
146 172
173 lookupWebAreaChild_: function() {
174 if (this.role != schema.RoleType.webArea)
175 return null;
176
177 return automationUtil.idToAutomationRootNode[
178 automationUtil.createAutomationRootNodeID(this.processID, this.routingID)] ;
179 },
180
147 dispatchEventAtCapturing_: function(event, path) { 181 dispatchEventAtCapturing_: function(event, path) {
148 privates(event).impl.eventPhase = Event.CAPTURING_PHASE; 182 privates(event).impl.eventPhase = Event.CAPTURING_PHASE;
149 for (var i = path.length - 1; i >= 0; i--) { 183 for (var i = path.length - 1; i >= 0; i--) {
150 this.fireEventListeners_(path[i], event); 184 this.fireEventListeners_(path[i], event);
151 if (privates(event).impl.propagationStopped) 185 if (privates(event).impl.propagationStopped)
152 return false; 186 return false;
153 } 187 }
154 return true; 188 return true;
155 }, 189 },
156 190
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 null, 380 null,
347 chrome); 381 chrome);
348 return false; 382 return false;
349 } 383 }
350 return true; 384 return true;
351 }, 385 },
352 386
353 destroy: function() { 387 destroy: function() {
354 this.dispatchEvent(schema.EventType.destroyed); 388 this.dispatchEvent(schema.EventType.destroyed);
355 this.invalidate_(this.wrapper); 389 this.invalidate_(this.wrapper);
390 idToWebArea_[this.processID +
391 '_' +
392 this.routingID] = undefined;
356 }, 393 },
357 394
358 onAccessibilityEvent: function(eventParams) { 395 onAccessibilityEvent: function(eventParams) {
359 if (!this.unserialize(eventParams.update)) { 396 if (!this.unserialize(eventParams.update)) {
360 logging.WARNING('unserialization failed'); 397 logging.WARNING('unserialization failed');
361 return false; 398 return false;
362 } 399 }
363 400
364 var targetNode = this.get(eventParams.targetID); 401 var targetNode = this.get(eventParams.targetID);
365 if (targetNode) { 402 if (targetNode) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 436
400 // Retrieve the internal AutomationNodeImpl instance for this node. 437 // Retrieve the internal AutomationNodeImpl instance for this node.
401 // This object is not accessible outside of bindings code, but we can access 438 // This object is not accessible outside of bindings code, but we can access
402 // it here. 439 // it here.
403 var nodeImpl = privates(node).impl; 440 var nodeImpl = privates(node).impl;
404 var id = nodeImpl.id; 441 var id = nodeImpl.id;
405 for (var key in AutomationAttributeDefaults) { 442 for (var key in AutomationAttributeDefaults) {
406 nodeImpl[key] = AutomationAttributeDefaults[key]; 443 nodeImpl[key] = AutomationAttributeDefaults[key];
407 } 444 }
408 nodeImpl.childIds = []; 445 nodeImpl.childIds = [];
409 nodeImpl.loaded = false;
410 nodeImpl.id = id; 446 nodeImpl.id = id;
411 delete this.axNodeDataCache_[id]; 447 delete this.axNodeDataCache_[id];
412 }, 448 },
413 449
414 load: function(callback) {
415 // TODO(dtseng/aboxhall): Implement.
416 if (!this.loaded)
417 throw 'Unsupported state: root node is not loaded.';
418
419 setTimeout(callback, 0);
420 },
421
422 deleteOldChildren_: function(node, newChildIds) { 450 deleteOldChildren_: function(node, newChildIds) {
423 // Create a set of child ids in |src| for fast lookup, and return false 451 // Create a set of child ids in |src| for fast lookup, and return false
424 // if a duplicate is found; 452 // if a duplicate is found;
425 var newChildIdSet = {}; 453 var newChildIdSet = {};
426 for (var i = 0; i < newChildIds.length; i++) { 454 for (var i = 0; i < newChildIds.length; i++) {
427 var childId = newChildIds[i]; 455 var childId = newChildIds[i];
428 if (newChildIdSet[childId]) { 456 if (newChildIdSet[childId]) {
429 logging.WARNING('Node ' + privates(node).impl.id + 457 logging.WARNING('Node ' + privates(node).impl.id +
430 ' has duplicate child id ' + childId); 458 ' has duplicate child id ' + childId);
431 lastError.set('automation', 459 lastError.set('automation',
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 } 516 }
489 privates(childNode).impl.indexInParent = i; 517 privates(childNode).impl.indexInParent = i;
490 privates(childNode).impl.parentID = privates(node).impl.id; 518 privates(childNode).impl.parentID = privates(node).impl.id;
491 } 519 }
492 520
493 return success; 521 return success;
494 }, 522 },
495 523
496 setData_: function(node, nodeData) { 524 setData_: function(node, nodeData) {
497 var nodeImpl = privates(node).impl; 525 var nodeImpl = privates(node).impl;
526
527 if (nodeData.role == schema.RoleType.webArea) {
528 nodeImpl.processID = nodeData.intAttributes.processId;
529 nodeImpl.routingID = nodeData.intAttributes.routingId;
530 idToWebArea_[nodeImpl.processID +
531 '_' +
532 nodeImpl.routingID] = node;
533 delete nodeData.intAttributes['processId'];
534 delete nodeData.intAttributes['routingId'];
535 }
498 for (var key in AutomationAttributeDefaults) { 536 for (var key in AutomationAttributeDefaults) {
499 if (key in nodeData) 537 if (key in nodeData)
500 nodeImpl[key] = nodeData[key]; 538 nodeImpl[key] = nodeData[key];
501 else 539 else
502 nodeImpl[key] = AutomationAttributeDefaults[key]; 540 nodeImpl[key] = AutomationAttributeDefaults[key];
503 } 541 }
504 for (var i = 0; i < AutomationAttributeTypes.length; i++) { 542 for (var i = 0; i < AutomationAttributeTypes.length; i++) {
505 var attributeType = AutomationAttributeTypes[i]; 543 var attributeType = AutomationAttributeTypes[i];
506 for (var attributeName in nodeData[attributeType]) { 544 for (var attributeName in nodeData[attributeType]) {
507 nodeImpl.attributesInternal[attributeName] = 545 nodeImpl.attributesInternal[attributeName] =
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 'firstChild', 630 'firstChild',
593 'lastChild', 631 'lastChild',
594 'children', 632 'children',
595 'previousSibling', 633 'previousSibling',
596 'nextSibling', 634 'nextSibling',
597 'doDefault', 635 'doDefault',
598 'focus', 636 'focus',
599 'makeVisible', 637 'makeVisible',
600 'setSelection', 638 'setSelection',
601 'addEventListener', 639 'addEventListener',
602 'removeEventListener'], 640 'removeEventListener',
641 'load'],
603 readonly: ['isRootNode', 642 readonly: ['isRootNode',
604 'role', 643 'role',
605 'state', 644 'state',
606 'location', 645 'location',
607 'attributes', 646 'attributes',
647 'loaded',
608 'root'] }); 648 'root'] });
609 649
610 var AutomationRootNode = utils.expose('AutomationRootNode', 650 var AutomationRootNode = utils.expose('AutomationRootNode',
611 AutomationRootNodeImpl, 651 AutomationRootNodeImpl,
612 { superclass: AutomationNode, 652 { superclass: AutomationNode,
613 functions: ['load'], 653 functions: ['load'] });
614 readonly: ['loaded'] });
615 654
616 exports.AutomationNode = AutomationNode; 655 exports.AutomationNode = AutomationNode;
617 exports.AutomationRootNode = AutomationRootNode; 656 exports.AutomationRootNode = AutomationRootNode;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698