Chromium Code Reviews| Index: chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js |
| diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js |
| index f26ecc76ceac3bdcc491a4a46ab5b00a90bf64f3..e8b1e591ce0dc1282251872d6d453949cab6faf1 100644 |
| --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js |
| +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js |
| @@ -11,6 +11,8 @@ goog.provide('cvox2.Background'); |
| goog.provide('cvox2.global'); |
| goog.require('cvox.TabsApiHandler'); |
| +goog.require('cvox2.AutomationPredicates'); |
| +goog.require('cvox2.AutomationUtil'); |
| /** Classic Chrome accessibility API. */ |
| cvox2.global.accessibility = |
| @@ -32,6 +34,14 @@ cvox2.Background = function() { |
| cvox.ChromeVox.braille, |
| cvox.ChromeVox.earcons); |
| + /** @type {AutomationNode} @private */ |
| + this.currentNode_ = null; |
| + |
| + /** @type {cvox.TabsApiHandler} @private */ |
| + this.tabsHandler_ = new cvox.TabsApiHandler(cvox.ChromeVox.tts, |
| + cvox.ChromeVox.braille, |
| + cvox.ChromeVox.earcons); |
| + |
| // Only needed with unmerged ChromeVox classic loaded before. |
| cvox2.global.accessibility.setAccessibilityEnabled(false); |
| @@ -66,9 +76,8 @@ cvox2.Background.prototype = { |
| return; |
| } |
| - if (!chrome.commands.onCommand.hasListeners()) { |
| + if (!chrome.commands.onCommand.hasListeners()) |
| chrome.commands.onCommand.addListener(this.onGotCommand); |
| - } |
| this.disableClassicChromeVox_(tab.id); |
| @@ -83,25 +92,113 @@ cvox2.Background.prototype = { |
| onGotTree: function(root) { |
| // Register all automation event listeners. |
| root.addEventListener(chrome.automation.EventType.focus, |
| - this.onAutomationEvent.bind(this), |
| + this.onFocus, |
| + true); |
| + root.addEventListener(chrome.automation.EventType.loadComplete, |
| + this.onLoadComplete, |
| true); |
| + |
| + if (root.attributes.docLoaded) |
| + this.onLoadComplete({target: root}); |
| }, |
| /** |
| - * A generic handler for all desktop automation events. |
| - * @param {AutomationEvent} evt The event. |
| + * Handles chrome.commands.onCommand. |
| + * @param {string} command |
| */ |
| - onAutomationEvent: function(evt) { |
| - var output = evt.target.attributes.name + ' ' + evt.target.role; |
| + onGotCommand: function(command) { |
| + if (!this.current_) |
| + return; |
| + |
| + var previous = this.current_; |
| + var current = this.current_; |
| + |
| + // Reverse? |
| + var r = false; |
| + var pred = null; |
| + switch (command) { |
| + case 'nextHeading': |
| + r = false; |
| + pred = cvox2.AutomationPredicates.heading; |
| + break; |
| + case 'previousHeading': |
| + r = true; |
| + pred = cvox2.AutomationPredicates.heading; |
| + break; |
| + case 'nextLine': |
| + r = false; |
| + pred = cvox2.AutomationPredicates.inlineTextBox; |
| + break; |
| + case 'previousLine': |
| + r = true; |
| + pred = cvox2.AutomationPredicates.inlineTextBox; |
| + break; |
| + case 'nextLink': |
| + r = false; |
| + pred = cvox2.AutomationPredicates.link; |
| + break; |
| + case 'previousLink': |
| + r = true; |
| + pred = cvox2.AutomationPredicates.link; |
| + break; |
| + case 'nextElement': |
| + current = current.role == chrome.automation.RoleType.inlineTextBox ? |
| + current.parent() : current; |
| + current = cvox2.AutomationUtil.findNextNode(current, |
| + false, |
| + cvox2.AutomationPredicates.inlineTextBox); |
| + current = current ? current.parent() : current; |
| + break; |
| + case 'previousElement': |
| + current = current.role == chrome.automation.RoleType.inlineTextBox ? |
| + current.parent() : current; |
| + current = cvox2.AutomationUtil.findNextNode(current, |
| + true, |
| + cvox2.AutomationPredicates.inlineTextBox); |
| + current = current ? current.parent() : current; |
| + break; |
| + } |
| + |
| + if (pred) |
| + current = cvox2.AutomationUtil.findNextNode(current, r, pred); |
| + |
| + if (current) |
| + current.focus(); |
| + |
| + this.onFocus({target: current || previous}); |
| + }, |
| + |
| + /** |
| + * Provides all feedback once ChromeVox's focus changes. |
| + * @param {Object} evt |
|
dmazzoni
2014/09/29 06:06:18
Is there a specific automation api type rather tha
David Tseng
2014/09/29 17:05:23
See below.
|
| + */ |
| + onFocus: function(evt) { |
| + var node = evt.target; |
| + if (!node) |
| + return; |
| + var container = node; |
| + while (container && (container.role == 'inlineTextBox' || |
| + container.role == 'staticText')) |
| + container = container.parent(); |
| + |
| + var role = container ? container.role : node.role; |
| + |
| + var output = |
| + [node.attributes.name, node.attributes.value, role].join(', '); |
| cvox.ChromeVox.tts.speak(output, cvox.AbstractTts.QUEUE_MODE_FLUSH); |
| cvox.ChromeVox.braille.write(cvox.NavBraille.fromText(output)); |
| + this.current_ = node; |
| }, |
| /** |
| - * Handles chrome.commands.onCommand. |
| - * @param {string} command |
| + * Provides all feedback once a load complete event fires. |
| + * @param {Object} evt |
|
dmazzoni
2014/09/29 06:06:18
Is there a specific automation api type rather tha
David Tseng
2014/09/29 17:05:23
No; nothing defined on chrome.automation at least.
|
| */ |
| - onGotCommand: function(command) { |
| + onLoadComplete: function(evt) { |
| + this.current_ = cvox2.AutomationUtil.findNodePost(evt.target, |
| + false, |
| + cvox2.AutomationPredicates.inlineTextBox); |
| + this.onFocus({target: this.current_}); |
| }, |
| /** |
| @@ -117,7 +214,7 @@ cvox2.Background.prototype = { |
| /** |
| * Disables classic ChromeVox. |
| - * @param {number} tabId The tab where ChromeVox classic is running. |
| + * @param {number} tabId The tab where ChromeVox classic is running in. |
| */ |
| disableClassicChromeVox_: function(tabId) { |
| chrome.tabs.executeScript( |