| Index: chrome/browser/resources/chromeos/chromevox/cvox2/background/recovery_strategy.js
|
| diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/recovery_strategy.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/recovery_strategy.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f3409ba0898f1b7b6ba63d92034782c81cdf7ea3
|
| --- /dev/null
|
| +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/recovery_strategy.js
|
| @@ -0,0 +1,133 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +/**
|
| + * @fileoverview Defines various strategies for recovering automation nodes.
|
| + */
|
| +
|
| +goog.provide('AncestryRecoveryStrategy');
|
| +goog.provide('RecoveryStrategy');
|
| +goog.provide('TreePathRecoveryStrategy');
|
| +
|
| +goog.scope(function() {
|
| +var AutomationNode = chrome.automation.AutomationNode;
|
| +var RoleType = chrome.automation.RoleType;
|
| +
|
| +/**
|
| + * @param {!AutomationNode} node
|
| + * @constructor
|
| + */
|
| +RecoveryStrategy = function(node) {
|
| + /** @private {!AutomationNode} */
|
| + this.node_ = node;
|
| +};
|
| +
|
| +RecoveryStrategy.prototype = {
|
| + /** @return {!AutomationNode} */
|
| + get node() {
|
| + if (this.requiresRecovery())
|
| + this.node_ = this.recover() || this.node_;
|
| +
|
| + return this.node_;
|
| + },
|
| +
|
| + /** @return {boolean} */
|
| + requiresRecovery: function() {
|
| + return !this.node_ || !this.node_.role;
|
| + },
|
| +
|
| + /**
|
| + * @return {AutomationNode}
|
| + * @protected
|
| + */
|
| + recover: function() {
|
| + return null;
|
| + }
|
| +};
|
| +
|
| +/**
|
| + * A recovery strategy that uses the node's ancestors.
|
| + * @constructor
|
| + * @extends {RecoveryStrategy}
|
| + */
|
| +AncestryRecoveryStrategy = function(node) {
|
| + RecoveryStrategy.call(this, node);
|
| +
|
| + /** @type {!Array<AutomationNode>} @private */
|
| + this.ancestry_ = [];
|
| + var nodeWalker = node;
|
| + while (nodeWalker) {
|
| + this.ancestry_.push(nodeWalker);
|
| + nodeWalker = nodeWalker.parent;
|
| + if (nodeWalker && nodeWalker.role == RoleType.WINDOW)
|
| + break;
|
| + }
|
| +};
|
| +
|
| +AncestryRecoveryStrategy.prototype = {
|
| + __proto__: RecoveryStrategy.prototype,
|
| +
|
| + /** @override */
|
| + recover: function() {
|
| + return this.ancestry_[this.getFirstValidNodeIndex_()];
|
| + },
|
| +
|
| + /**
|
| + * @return {number}
|
| + * @protected
|
| + */
|
| + getFirstValidNodeIndex_: function() {
|
| + for (var i = 0; i < this.ancestry_.length; i++) {
|
| + var firstValidNode = this.ancestry_[i];
|
| + if (firstValidNode != null && firstValidNode.role !== undefined &&
|
| + firstValidNode.root != undefined) {
|
| + return i;
|
| + }
|
| + }
|
| + return 0;
|
| + }
|
| +};
|
| +
|
| +/**
|
| + * A recovery strategy that uses the node's tree path.
|
| + * @constructor
|
| + * @extends {AncestryRecoveryStrategy}
|
| + */
|
| +TreePathRecoveryStrategy = function(node) {
|
| + AncestryRecoveryStrategy.call(this, node);
|
| +
|
| + /** @type {!Array<number>} @private */
|
| + this.recoveryChildIndex_ = [];
|
| + var nodeWalker = node;
|
| + while (nodeWalker) {
|
| + this.recoveryChildIndex_.push(nodeWalker.indexInParent);
|
| + nodeWalker = nodeWalker.parent;
|
| + if (nodeWalker && nodeWalker.role == RoleType.WINDOW)
|
| + break;
|
| + }
|
| +};
|
| +
|
| +TreePathRecoveryStrategy.prototype = {
|
| + __proto__: AncestryRecoveryStrategy.prototype,
|
| +
|
| + /** @override */
|
| + recover: function() {
|
| + var index = this.getFirstValidNodeIndex_();
|
| + if (index == 0)
|
| + return this.ancestry_[index];
|
| +
|
| + // Otherwise, attempt to recover.
|
| + var node = this.ancestry_[index];
|
| + for (var j = index - 1; j >= 0; j--) {
|
| + var childIndex = this.recoveryChildIndex_[j];
|
| + var children = node.children;
|
| + if (!children[childIndex])
|
| + return node;
|
| + node = children[childIndex];
|
| + }
|
| + return node;
|
| + }
|
| +};
|
| +
|
| +}); // goog.scope
|
|
|