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 007b5bd686485f5c944391b33ada6b6fbf68d6b1..f373ebd1d5782f543e3584f5abf4fdf3412d6dd4 100644 |
| --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js |
| +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js |
| @@ -8,11 +8,12 @@ |
| */ |
| goog.provide('Background'); |
| -goog.provide('ChromeVoxMode'); |
| goog.provide('global'); |
| goog.require('AutomationPredicate'); |
| goog.require('AutomationUtil'); |
| +goog.require('ChromeVoxState'); |
| +goog.require('LiveRegions'); |
| goog.require('NextEarcons'); |
| goog.require('Output'); |
| goog.require('Output.EventType'); |
| @@ -31,21 +32,13 @@ var EventType = chrome.automation.EventType; |
| var RoleType = chrome.automation.RoleType; |
| /** |
| - * All possible modes ChromeVox can run. |
| - * @enum {string} |
| - */ |
| -ChromeVoxMode = { |
| - CLASSIC: 'classic', |
| - COMPAT: 'compat', |
| - NEXT: 'next', |
| - FORCE_NEXT: 'force_next' |
| -}; |
| - |
| -/** |
| * ChromeVox2 background page. |
| * @constructor |
| + * @extends {ChromeVoxState} |
| */ |
| Background = function() { |
| + ChromeVoxState.call(this); |
| + |
| /** |
| * A list of site substring patterns to use with ChromeVox next. Keep these |
| * strings relatively specific. |
| @@ -127,35 +120,98 @@ Background = function() { |
| // Classic keymap. |
| cvox.ChromeVoxKbHandler.handlerKeyMap = cvox.KeyMap.fromDefaults(); |
| - chrome.automation.addTreeChangeObserver(this.onTreeChange); |
| + // Live region handler. |
| + this.liveRegions_ = new LiveRegions(this); |
| }; |
| +/** |
| + * Live region events received in fewer than this many milliseconds will |
| + * queue, otherwise they'll be output with a category flush. |
| + * @type {number} |
| + * @const |
| + */ |
|
David Tseng
2015/11/23 23:23:57
Move this as well?
dmazzoni
2015/11/30 22:00:47
Done.
|
| +Background.LIVE_REGION_QUEUE_TIME_MS = 500; |
|
Peter Lundblad
2015/11/24 11:04:30
Move to LiveRegionHandler?
dmazzoni
2015/11/30 22:00:46
Done.
|
| + |
| Background.prototype = { |
| - /** Forces ChromeVox Next to be active for all tabs. */ |
| - forceChromeVoxNextActive: function() { |
| - this.setChromeVoxMode(ChromeVoxMode.FORCE_NEXT); |
| - }, |
| + __proto__: ChromeVoxState.prototype, |
| - /** @type {ChromeVoxMode} */ |
| - get mode() { |
| + /** |
| + * @override |
| + */ |
| + getMode: function() { |
| return this.mode_; |
| }, |
| - /** @type {cursors.Range} */ |
| - get currentRange() { |
| + /** |
| + * @override |
| + */ |
| + setMode: function(mode, opt_injectClassic) { |
| + // Switching key maps potentially affects the key codes that involve |
| + // sequencing. Without resetting this list, potentially stale key codes |
| + // remain. The key codes themselves get pushed in |
| + // cvox.KeySequence.deserialize which gets called by cvox.KeyMap. |
| + cvox.ChromeVox.sequenceSwitchKeyCodes = []; |
| + if (mode === ChromeVoxMode.CLASSIC || mode === ChromeVoxMode.COMPAT) |
| + cvox.ChromeVoxKbHandler.handlerKeyMap = cvox.KeyMap.fromDefaults(); |
| + else |
| + cvox.ChromeVoxKbHandler.handlerKeyMap = cvox.KeyMap.fromNext(); |
| + |
| + if (mode == ChromeVoxMode.CLASSIC) { |
| + if (chrome.commands && |
| + chrome.commands.onCommand.hasListener(this.onGotCommand)) |
| + chrome.commands.onCommand.removeListener(this.onGotCommand); |
| + } else { |
| + if (chrome.commands && |
| + !chrome.commands.onCommand.hasListener(this.onGotCommand)) |
| + chrome.commands.onCommand.addListener(this.onGotCommand); |
| + } |
| + |
| + chrome.tabs.query({active: true}, function(tabs) { |
| + if (mode === ChromeVoxMode.CLASSIC) { |
| + // Generally, we don't want to inject classic content scripts as it is |
| + // done by the extension system at document load. The exception is when |
| + // we toggle classic on manually as part of a user command. |
| + if (opt_injectClassic) |
| + cvox.ChromeVox.injectChromeVoxIntoTabs(tabs); |
| + } else { |
| + // When in compat mode, if the focus is within the desktop tree proper, |
| + // then do not disable content scripts. |
| + if (this.currentRange_ && |
| + this.currentRange_.start.node.root.role == RoleType.desktop) |
| + return; |
| + |
| + this.disableClassicChromeVox_(); |
| + } |
| + }.bind(this)); |
| + |
| + this.mode_ = mode; |
| + }, |
| + |
| + /** |
| + * @override |
| + */ |
| + getCurrentRange: function() { |
| return this.currentRange_; |
| }, |
| - set currentRange(value) { |
| - if (!value) |
| + /** |
| + * @override |
| + */ |
| + setCurrentRange: function(newRange) { |
| + if (!newRange) |
| return; |
| - this.currentRange_ = value; |
| + this.currentRange_ = newRange; |
| if (this.currentRange_) |
| this.currentRange_.start.node.makeVisible(); |
| }, |
| + /** Forces ChromeVox Next to be active for all tabs. */ |
| + forceChromeVoxNextActive: function() { |
| + this.setMode(ChromeVoxMode.FORCE_NEXT); |
| + }, |
| + |
| /** |
| * Handles ChromeVox Next commands. |
| * @param {string} command |
| @@ -331,8 +387,8 @@ Background.prototype = { |
| .onSpeechEnd(function() { continueReading(prevRange); }) |
| .go(); |
| prevRange = this.currentRange_; |
| - this.currentRange = |
| - this.currentRange.move(cursors.Unit.NODE, Dir.FORWARD); |
| + this.setCurrentRange( |
| + this.currentRange_.move(cursors.Unit.NODE, Dir.FORWARD)); |
| if (!this.currentRange_ || this.currentRange_.equals(prevRange)) |
| global.isReadingContinuously = false; |
| @@ -372,7 +428,7 @@ Background.prototype = { |
| } else { |
| newMode = ChromeVoxMode.FORCE_NEXT; |
| } |
| - this.setChromeVoxMode(newMode, true); |
| + this.setMode(newMode, true); |
| var isClassic = |
| newMode == ChromeVoxMode.CLASSIC || newMode == ChromeVoxMode.COMPAT; |
| @@ -408,7 +464,7 @@ Background.prototype = { |
| actionNode.focus(); |
| var prevRange = this.currentRange_; |
| - this.currentRange = current; |
| + this.setCurrentRange(current); |
| new Output().withSpeechAndBraille( |
| this.currentRange_, prevRange, Output.EventType.NAVIGATE) |
| @@ -429,6 +485,8 @@ Background.prototype = { |
| evt.preventDefault(); |
| evt.stopPropagation(); |
| } |
| + |
| + Output.flushNextSpeechUtterance(); |
| }, |
| /** |
| @@ -495,50 +553,7 @@ Background.prototype = { |
| mode = ChromeVoxMode.CLASSIC; |
| } |
| - this.setChromeVoxMode(mode); |
| - }, |
| - |
| - /** |
| - * Called when the automation tree is changed. |
| - * @param {chrome.automation.TreeChange} treeChange |
| - */ |
| - onTreeChange: function(treeChange) { |
| - if (this.mode_ === ChromeVoxMode.CLASSIC || !cvox.ChromeVox.isActive) |
| - return; |
| - |
| - var node = treeChange.target; |
| - if (!node.containerLiveStatus) |
| - return; |
| - |
| - if (node.containerLiveRelevant.indexOf('additions') >= 0 && |
| - treeChange.type == 'nodeCreated') |
| - this.outputLiveRegionChange_(node, null); |
| - if (node.containerLiveRelevant.indexOf('text') >= 0 && |
| - treeChange.type == 'nodeChanged') |
| - this.outputLiveRegionChange_(node, null); |
| - if (node.containerLiveRelevant.indexOf('removals') >= 0 && |
| - treeChange.type == 'nodeRemoved') |
| - this.outputLiveRegionChange_(node, '@live_regions_removed'); |
| - }, |
| - |
| - /** |
| - * Given a node that needs to be spoken as part of a live region |
| - * change and an additional optional format string, output the |
| - * live region description. |
| - * @param {!chrome.automation.AutomationNode} node The changed node. |
| - * @param {?string} opt_prependFormatStr If set, a format string for |
| - * cvox2.Output to prepend to the output. |
| - * @private |
| - */ |
| - outputLiveRegionChange_: function(node, opt_prependFormatStr) { |
| - var range = cursors.Range.fromNode(node); |
| - var output = new Output(); |
| - if (opt_prependFormatStr) { |
| - output.format(opt_prependFormatStr); |
| - } |
| - output.withSpeech(range, null, Output.EventType.NAVIGATE); |
| - output.withSpeechCategory(cvox.TtsCategory.LIVE); |
| - output.go(); |
| + this.setMode(mode); |
| }, |
| /** |
| @@ -583,54 +598,6 @@ Background.prototype = { |
| }, |
| /** |
| - * Sets the current ChromeVox mode. |
| - * @param {ChromeVoxMode} mode |
| - * @param {boolean=} opt_injectClassic Injects ChromeVox classic into tabs; |
| - * defaults to false. |
| - */ |
| - setChromeVoxMode: function(mode, opt_injectClassic) { |
| - // Switching key maps potentially affects the key codes that involve |
| - // sequencing. Without resetting this list, potentially stale key codes |
| - // remain. The key codes themselves get pushed in |
| - // cvox.KeySequence.deserialize which gets called by cvox.KeyMap. |
| - cvox.ChromeVox.sequenceSwitchKeyCodes = []; |
| - if (mode === ChromeVoxMode.CLASSIC || mode === ChromeVoxMode.COMPAT) |
| - cvox.ChromeVoxKbHandler.handlerKeyMap = cvox.KeyMap.fromDefaults(); |
| - else |
| - cvox.ChromeVoxKbHandler.handlerKeyMap = cvox.KeyMap.fromNext(); |
| - |
| - if (mode == ChromeVoxMode.CLASSIC) { |
| - if (chrome.commands && |
| - chrome.commands.onCommand.hasListener(this.onGotCommand)) |
| - chrome.commands.onCommand.removeListener(this.onGotCommand); |
| - } else { |
| - if (chrome.commands && |
| - !chrome.commands.onCommand.hasListener(this.onGotCommand)) |
| - chrome.commands.onCommand.addListener(this.onGotCommand); |
| - } |
| - |
| - chrome.tabs.query({active: true}, function(tabs) { |
| - if (mode === ChromeVoxMode.CLASSIC) { |
| - // Generally, we don't want to inject classic content scripts as it is |
| - // done by the extension system at document load. The exception is when |
| - // we toggle classic on manually as part of a user command. |
| - if (opt_injectClassic) |
| - cvox.ChromeVox.injectChromeVoxIntoTabs(tabs); |
| - } else { |
| - // When in compat mode, if the focus is within the desktop tree proper, |
| - // then do not disable content scripts. |
| - if (this.currentRange_ && |
| - this.currentRange_.start.node.root.role == RoleType.desktop) |
| - return; |
| - |
| - this.disableClassicChromeVox_(); |
| - } |
| - }.bind(this)); |
| - |
| - this.mode_ = mode; |
| - }, |
| - |
| - /** |
| * @param {!Spannable} text |
| * @param {number} position |
| * @private |