OLD | NEW |
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 |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 'during phase ' + eventPhase + ': ' + | 190 'during phase ' + eventPhase + ': ' + |
191 e.message + '\nStack trace: ' + e.stack); | 191 e.message + '\nStack trace: ' + e.stack); |
192 } | 192 } |
193 } | 193 } |
194 }, | 194 }, |
195 | 195 |
196 performAction_: function(actionType, opt_args) { | 196 performAction_: function(actionType, opt_args) { |
197 // Not yet initialized. | 197 // Not yet initialized. |
198 if (this.rootImpl.processID === undefined || | 198 if (this.rootImpl.processID === undefined || |
199 this.rootImpl.routingID === undefined || | 199 this.rootImpl.routingID === undefined || |
200 this.wrapper.id === undefined) { | 200 this.id === undefined) { |
201 return; | 201 return; |
202 } | 202 } |
203 | 203 |
204 // Check permissions. | 204 // Check permissions. |
205 if (!IsInteractPermitted()) { | 205 if (!IsInteractPermitted()) { |
206 throw new Error(actionType + ' requires {"desktop": true} or' + | 206 throw new Error(actionType + ' requires {"desktop": true} or' + |
207 ' {"interact": true} in the "automation" manifest key.'); | 207 ' {"interact": true} in the "automation" manifest key.'); |
208 } | 208 } |
209 | 209 |
210 automationInternal.performAction({ processID: this.rootImpl.processID, | 210 automationInternal.performAction({ processID: this.rootImpl.processID, |
211 routingID: this.rootImpl.routingID, | 211 routingID: this.rootImpl.routingID, |
212 automationNodeID: this.wrapper.id, | 212 automationNodeID: this.id, |
213 actionType: actionType }, | 213 actionType: actionType }, |
214 opt_args || {}); | 214 opt_args || {}); |
215 } | 215 } |
216 }; | 216 }; |
217 | 217 |
218 // Maps an attribute to its default value in an invalidated node. | 218 // Maps an attribute to its default value in an invalidated node. |
219 // These attributes are taken directly from the Automation idl. | 219 // These attributes are taken directly from the Automation idl. |
220 var AutomationAttributeDefaults = { | 220 var AutomationAttributeDefaults = { |
221 'id': -1, | 221 'id': -1, |
222 'role': '', | 222 'role': '', |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
322 null, | 322 null, |
323 chrome); | 323 chrome); |
324 return false; | 324 return false; |
325 } | 325 } |
326 if (nodeToClear === this.wrapper) { | 326 if (nodeToClear === this.wrapper) { |
327 this.invalidate_(nodeToClear); | 327 this.invalidate_(nodeToClear); |
328 } else { | 328 } else { |
329 var children = nodeToClear.children(); | 329 var children = nodeToClear.children(); |
330 for (var i = 0; i < children.length; i++) | 330 for (var i = 0; i < children.length; i++) |
331 this.invalidate_(children[i]); | 331 this.invalidate_(children[i]); |
332 privates(nodeToClear).impl.childIds = [] | 332 var nodeToClearImpl = privates(nodeToClear).impl; |
333 updateState.pendingNodes[nodeToClear.id] = nodeToClear; | 333 nodeToClearImpl.childIds = [] |
| 334 updateState.pendingNodes[nodeToClearImpl.id] = nodeToClear; |
334 } | 335 } |
335 } | 336 } |
336 | 337 |
337 for (var i = 0; i < update.nodes.length; i++) { | 338 for (var i = 0; i < update.nodes.length; i++) { |
338 if (!this.updateNode_(update.nodes[i], updateState)) | 339 if (!this.updateNode_(update.nodes[i], updateState)) |
339 return false; | 340 return false; |
340 } | 341 } |
341 | 342 |
342 if (Object.keys(updateState.pendingNodes).length > 0) { | 343 if (Object.keys(updateState.pendingNodes).length > 0) { |
343 logging.WARNING('Nodes left pending by the update: ' + | 344 logging.WARNING('Nodes left pending by the update: ' + |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 return; | 396 return; |
396 var children = node.children(); | 397 var children = node.children(); |
397 | 398 |
398 for (var i = 0, child; child = children[i]; i++) | 399 for (var i = 0, child; child = children[i]; i++) |
399 this.invalidate_(child); | 400 this.invalidate_(child); |
400 | 401 |
401 // Retrieve the internal AutomationNodeImpl instance for this node. | 402 // Retrieve the internal AutomationNodeImpl instance for this node. |
402 // This object is not accessible outside of bindings code, but we can access | 403 // This object is not accessible outside of bindings code, but we can access |
403 // it here. | 404 // it here. |
404 var nodeImpl = privates(node).impl; | 405 var nodeImpl = privates(node).impl; |
405 var id = node.id; | 406 var id = nodeImpl.id; |
406 for (var key in AutomationAttributeDefaults) { | 407 for (var key in AutomationAttributeDefaults) { |
407 nodeImpl[key] = AutomationAttributeDefaults[key]; | 408 nodeImpl[key] = AutomationAttributeDefaults[key]; |
408 } | 409 } |
409 nodeImpl.childIds = []; | 410 nodeImpl.childIds = []; |
410 nodeImpl.loaded = false; | 411 nodeImpl.loaded = false; |
411 nodeImpl.id = id; | 412 nodeImpl.id = id; |
412 delete this.axNodeDataCache_[id]; | 413 delete this.axNodeDataCache_[id]; |
413 }, | 414 }, |
414 | 415 |
415 load: function(callback) { | 416 load: function(callback) { |
416 // TODO(dtseng/aboxhall): Implement. | 417 // TODO(dtseng/aboxhall): Implement. |
417 if (!this.loaded) | 418 if (!this.loaded) |
418 throw 'Unsupported state: root node is not loaded.'; | 419 throw 'Unsupported state: root node is not loaded.'; |
419 | 420 |
420 setTimeout(callback, 0); | 421 setTimeout(callback, 0); |
421 }, | 422 }, |
422 | 423 |
423 deleteOldChildren_: function(node, newChildIds) { | 424 deleteOldChildren_: function(node, newChildIds) { |
424 // Create a set of child ids in |src| for fast lookup, and return false | 425 // Create a set of child ids in |src| for fast lookup, and return false |
425 // if a duplicate is found; | 426 // if a duplicate is found; |
426 var newChildIdSet = {}; | 427 var newChildIdSet = {}; |
427 for (var i = 0; i < newChildIds.length; i++) { | 428 for (var i = 0; i < newChildIds.length; i++) { |
428 var childId = newChildIds[i]; | 429 var childId = newChildIds[i]; |
429 if (newChildIdSet[childId]) { | 430 if (newChildIdSet[childId]) { |
430 logging.WARNING('Node ' + node.id + ' has duplicate child id ' + | 431 logging.WARNING('Node ' + privates(node).impl.id + |
431 childId); | 432 ' has duplicate child id ' + childId); |
432 lastError.set('automation', | 433 lastError.set('automation', |
433 'Bad update received on automation tree', | 434 'Bad update received on automation tree', |
434 null, | 435 null, |
435 chrome); | 436 chrome); |
436 return false; | 437 return false; |
437 } | 438 } |
438 newChildIdSet[newChildIds[i]] = true; | 439 newChildIdSet[newChildIds[i]] = true; |
439 } | 440 } |
440 | 441 |
441 // Delete the old children. | 442 // Delete the old children. |
(...skipping 14 matching lines...) Expand all Loading... |
456 }, | 457 }, |
457 | 458 |
458 createNewChildren_: function(node, newChildIds, updateState) { | 459 createNewChildren_: function(node, newChildIds, updateState) { |
459 logging.CHECK(node); | 460 logging.CHECK(node); |
460 var success = true; | 461 var success = true; |
461 for (var i = 0; i < newChildIds.length; i++) { | 462 for (var i = 0; i < newChildIds.length; i++) { |
462 var childId = newChildIds[i]; | 463 var childId = newChildIds[i]; |
463 var childNode = this.axNodeDataCache_[childId]; | 464 var childNode = this.axNodeDataCache_[childId]; |
464 if (childNode) { | 465 if (childNode) { |
465 if (childNode.parent() != node) { | 466 if (childNode.parent() != node) { |
466 var parentId = 0; | 467 var parentId = -1; |
467 if (childNode.parent()) parentId = childNode.parent().id; | 468 if (childNode.parent()) { |
| 469 var parentImpl = privates(childNode.parent()).impl; |
| 470 parentId = parentImpl.id; |
| 471 } |
468 // This is a serious error - nodes should never be reparented. | 472 // This is a serious error - nodes should never be reparented. |
469 // If this case occurs, continue so this node isn't left in an | 473 // If this case occurs, continue so this node isn't left in an |
470 // inconsistent state, but return failure at the end. | 474 // inconsistent state, but return failure at the end. |
471 logging.WARNING('Node ' + childId + ' reparented from ' + | 475 logging.WARNING('Node ' + childId + ' reparented from ' + |
472 parentId + ' to ' + node.id); | 476 parentId + ' to ' + privates(node).impl.id); |
473 lastError.set('automation', | 477 lastError.set('automation', |
474 'Bad update received on automation tree', | 478 'Bad update received on automation tree', |
475 null, | 479 null, |
476 chrome); | 480 chrome); |
477 success = false; | 481 success = false; |
478 continue; | 482 continue; |
479 } | 483 } |
480 } else { | 484 } else { |
481 childNode = new AutomationNode(this); | 485 childNode = new AutomationNode(this); |
482 this.axNodeDataCache_[childId] = childNode; | 486 this.axNodeDataCache_[childId] = childNode; |
483 privates(childNode).impl.id = childId; | 487 privates(childNode).impl.id = childId; |
484 updateState.pendingNodes[childNode.id] = childNode; | 488 updateState.pendingNodes[childId] = childNode; |
485 updateState.newNodes[childNode.id] = childNode; | 489 updateState.newNodes[childId] = childNode; |
486 } | 490 } |
487 privates(childNode).impl.indexInParent = i; | 491 privates(childNode).impl.indexInParent = i; |
488 privates(childNode).impl.parentID = node.id; | 492 privates(childNode).impl.parentID = privates(node).impl.id; |
489 } | 493 } |
490 | 494 |
491 return success; | 495 return success; |
492 }, | 496 }, |
493 | 497 |
494 setData_: function(node, nodeData) { | 498 setData_: function(node, nodeData) { |
495 var nodeImpl = privates(node).impl; | 499 var nodeImpl = privates(node).impl; |
496 for (var key in AutomationAttributeDefaults) { | 500 for (var key in AutomationAttributeDefaults) { |
497 if (key in nodeData) { | 501 if (key in nodeData) { |
498 if (key == 'id' && nodeImpl[key] != nodeData[key]) { | 502 if (key == 'id' && nodeImpl[key] != nodeData[key]) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
541 } | 545 } |
542 return node.attributesInternal[attributeName]; | 546 return node.attributesInternal[attributeName]; |
543 }.bind(this), | 547 }.bind(this), |
544 }); | 548 }); |
545 }, | 549 }, |
546 | 550 |
547 updateNode_: function(nodeData, updateState) { | 551 updateNode_: function(nodeData, updateState) { |
548 var node = this.axNodeDataCache_[nodeData.id]; | 552 var node = this.axNodeDataCache_[nodeData.id]; |
549 var didUpdateRoot = false; | 553 var didUpdateRoot = false; |
550 if (node) { | 554 if (node) { |
551 delete updateState.pendingNodes[node.id]; | 555 delete updateState.pendingNodes[privates(node).impl.id]; |
552 } else { | 556 } else { |
553 if (nodeData.role != schema.RoleType.rootWebArea && | 557 if (nodeData.role != schema.RoleType.rootWebArea && |
554 nodeData.role != schema.RoleType.desktop) { | 558 nodeData.role != schema.RoleType.desktop) { |
555 logging.WARNING(String(nodeData.id) + | 559 logging.WARNING(String(nodeData.id) + |
556 ' is not in the cache and not the new root.'); | 560 ' is not in the cache and not the new root.'); |
557 lastError.set('automation', | 561 lastError.set('automation', |
558 'Bad update received on automation tree', | 562 'Bad update received on automation tree', |
559 null, | 563 null, |
560 chrome); | 564 chrome); |
561 return false; | 565 return false; |
(...skipping 13 matching lines...) Expand all Loading... |
575 this.invalidate_(this.wrapper); | 579 this.invalidate_(this.wrapper); |
576 } | 580 } |
577 return false; | 581 return false; |
578 } | 582 } |
579 var nodeImpl = privates(node).impl; | 583 var nodeImpl = privates(node).impl; |
580 | 584 |
581 var success = this.createNewChildren_(node, | 585 var success = this.createNewChildren_(node, |
582 nodeData.childIds, | 586 nodeData.childIds, |
583 updateState); | 587 updateState); |
584 nodeImpl.childIds = nodeData.childIds; | 588 nodeImpl.childIds = nodeData.childIds; |
585 this.axNodeDataCache_[node.id] = node; | 589 this.axNodeDataCache_[nodeImpl.id] = node; |
586 | 590 |
587 return success; | 591 return success; |
588 } | 592 } |
589 }; | 593 }; |
590 | 594 |
591 | 595 |
592 var AutomationNode = utils.expose('AutomationNode', | 596 var AutomationNode = utils.expose('AutomationNode', |
593 AutomationNodeImpl, | 597 AutomationNodeImpl, |
594 { functions: ['parent', | 598 { functions: ['parent', |
595 'firstChild', | 599 'firstChild', |
596 'lastChild', | 600 'lastChild', |
597 'children', | 601 'children', |
598 'previousSibling', | 602 'previousSibling', |
599 'nextSibling', | 603 'nextSibling', |
600 'doDefault', | 604 'doDefault', |
601 'focus', | 605 'focus', |
602 'makeVisible', | 606 'makeVisible', |
603 'setSelection', | 607 'setSelection', |
604 'addEventListener', | 608 'addEventListener', |
605 'removeEventListener', | 609 'removeEventListener'], |
606 'toString'], | |
607 readonly: ['isRootNode', | 610 readonly: ['isRootNode', |
608 'id', | |
609 'role', | 611 'role', |
610 'state', | 612 'state', |
611 'location', | 613 'location', |
612 'attributes', | 614 'attributes', |
613 'root', | 615 'root'] }); |
614 'toString'] }); | |
615 | 616 |
616 var AutomationRootNode = utils.expose('AutomationRootNode', | 617 var AutomationRootNode = utils.expose('AutomationRootNode', |
617 AutomationRootNodeImpl, | 618 AutomationRootNodeImpl, |
618 { superclass: AutomationNode, | 619 { superclass: AutomationNode, |
619 functions: ['load'], | 620 functions: ['load'], |
620 readonly: ['loaded'] }); | 621 readonly: ['loaded'] }); |
621 | 622 |
622 exports.AutomationNode = AutomationNode; | 623 exports.AutomationNode = AutomationNode; |
623 exports.AutomationRootNode = AutomationRootNode; | 624 exports.AutomationRootNode = AutomationRootNode; |
OLD | NEW |