| 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 523e200d0959ad5b670da9a1f74dd328354a809d..b7ba66a5df10207d47e76a7f239185fc0b7726aa 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,115 @@ Background = function() {
|
| // Classic keymap.
|
| cvox.ChromeVoxKbHandler.handlerKeyMap = cvox.KeyMap.fromDefaults();
|
|
|
| - chrome.automation.addTreeChangeObserver(this.onTreeChange);
|
| + // Live region handler.
|
| + this.liveRegions_ = new LiveRegions(this);
|
| };
|
|
|
| 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));
|
| +
|
| + // If switching out of a ChromeVox Next mode, make sure we cancel
|
| + // the progress loading sound just in case.
|
| + if ((this.mode_ === ChromeVoxMode.NEXT ||
|
| + this.mode_ === ChromeVoxMode.FORCE_NEXT) &&
|
| + this.mode_ != mode) {
|
| + cvox.ChromeVox.earcons.cancelEarcon(cvox.Earcon.PAGE_START_LOADING);
|
| + }
|
| +
|
| + this.mode_ = mode;
|
| + },
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + refreshMode: function(url) {
|
| + var mode = this.mode_;
|
| + if (mode != ChromeVoxMode.FORCE_NEXT) {
|
| + if (this.isWhitelistedForNext_(url))
|
| + mode = ChromeVoxMode.NEXT;
|
| + else if (this.isBlacklistedForClassic_(url))
|
| + mode = ChromeVoxMode.COMPAT;
|
| + else
|
| + mode = ChromeVoxMode.CLASSIC;
|
| + }
|
| +
|
| + this.setMode(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 +404,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 +445,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 +481,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 +502,8 @@ Background.prototype = {
|
| evt.preventDefault();
|
| evt.stopPropagation();
|
| }
|
| +
|
| + Output.flushNextSpeechUtterance();
|
| },
|
|
|
| /**
|
| @@ -481,67 +556,6 @@ Background.prototype = {
|
| },
|
|
|
| /**
|
| - * Refreshes the current mode based on a url.
|
| - * @param {string} url
|
| - */
|
| - refreshMode: function(url) {
|
| - var mode = this.mode_;
|
| - if (mode != ChromeVoxMode.FORCE_NEXT) {
|
| - if (this.isWhitelistedForNext_(url))
|
| - mode = ChromeVoxMode.NEXT;
|
| - else if (this.isBlacklistedForClassic_(url))
|
| - mode = ChromeVoxMode.COMPAT;
|
| - else
|
| - 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();
|
| - },
|
| -
|
| - /**
|
| * Returns true if the url should have Classic running.
|
| * @return {boolean}
|
| * @private
|
| @@ -583,62 +597,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));
|
| -
|
| - // If switching out of a ChromeVox Next mode, make sure we cancel
|
| - // the progress loading sound just in case.
|
| - if ((this.mode_ === ChromeVoxMode.NEXT ||
|
| - this.mode_ === ChromeVoxMode.FORCE_NEXT) &&
|
| - this.mode_ != mode) {
|
| - cvox.ChromeVox.earcons.cancelEarcon(cvox.Earcon.PAGE_START_LOADING);
|
| - }
|
| -
|
| - this.mode_ = mode;
|
| - },
|
| -
|
| - /**
|
| * @param {!Spannable} text
|
| * @param {number} position
|
| * @private
|
|
|