1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file. 4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/** 6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @fileoverview Script that runs on the background page. 7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.provide('cvox.ChromeVoxBackground'); 11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.AbstractEarcons'); 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.AccessibilityApiHandler'); 14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.BrailleBackground'); 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.BrailleCaptionsBackground'); 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.ChromeVox'); 17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.ChromeVoxEditableTextBase'); 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.ChromeVoxPrefs'); 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.CompositeTts'); 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.ConsoleTts'); 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.EarconsBackground'); 22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.ExtensionBridge'); 23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.HostFactory'); 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.InjectedScriptLoader'); 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccigoog.require('cvox.Msgs'); 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.NavBraille'); 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// TODO(dtseng): This is required to prevent Closure from stripping our export 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// prefs on window. 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.OptionsPage'); 30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.PlatformFilter'); 31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.PlatformUtil'); 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccigoog.require('cvox.TabsApiHandler'); 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.TtsBackground'); 34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/** 37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * This object manages the global and persistent state for ChromeVox. 38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * It listens for messages from the content scripts on pages and 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * interprets them. 40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @constructor 41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground = function() { 43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/** 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Initialize the background page: set up TTS and bridge listeners. 48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground.prototype.init = function() { 50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // In the case of ChromeOS, only continue initialization if this instance of 51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // ChromeVox is as we expect. This prevents ChromeVox from the webstore from 52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // running. 53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (cvox.ChromeVox.isChromeOS && 54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chrome.i18n.getMessage('@@extension_id') != 55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 'mndnfokpggljbaajbnioimlmbfngpief') { 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cvox.ChromeVox.msgs = new cvox.Msgs(); 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.prefs = new cvox.ChromeVoxPrefs(); 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.readPrefs(); 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var consoleTts = cvox.ConsoleTts.getInstance(); 64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) consoleTts.setEnabled(true); 65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) /** 67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Chrome's actual TTS which knows and cares about pitch, volume, etc. 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @type {cvox.TtsBackground} 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @private 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.backgroundTts_ = new cvox.TtsBackground(); 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) /** 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @type {cvox.TtsInterface} 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.tts = new cvox.CompositeTts() 77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .add(this.backgroundTts_) 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) .add(consoleTts); 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.earcons = new cvox.EarconsBackground(); 81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.addBridgeListener(); 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) /** 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * The actual Braille service. 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @type {cvox.BrailleBackground} 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @private 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.backgroundBraille_ = new cvox.BrailleBackground(); 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.accessibilityApiHandler_ = new cvox.AccessibilityApiHandler( 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.tts, this.backgroundBraille_, this.earcons); 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.tabsApiHandler_ = new cvox.TabsApiHandler( 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.tts, this.backgroundBraille_, this.earcons); 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Export globals on cvox.ChromeVox. 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cvox.ChromeVox.tts = this.tts; 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cvox.ChromeVox.braille = this.backgroundBraille_; 98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cvox.ChromeVox.earcons = this.earcons; 99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(dtseng): Remove the second check on or after m33. 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (cvox.ChromeVox.isChromeOS && 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chrome.accessibilityPrivate.onChromeVoxLoadStateChanged) { 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chrome.accessibilityPrivate.onChromeVoxLoadStateChanged.addListener( 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.onLoadStateChanged); 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.checkVersionNumber(); 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Set up a message passing system for goog.provide() calls from 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // within the content scripts. 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chrome.extension.onMessage.addListener( 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) function(request, sender, callback) { 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (request['srcFile']) { 114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var srcFile = request['srcFile']; 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cvox.InjectedScriptLoader.fetchCode( 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) [srcFile], 117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) function(code) { 118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) callback({'code': code[srcFile]}); 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }); 120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return true; 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }); 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var self = this; 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (chrome.commandLinePrivate) { 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci chrome.commandLinePrivate.hasSwitch('enable-chromevox-next', 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci goog.bind(function(result) { 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (result) { 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Inject the content script into all running tabs. 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci chrome.windows.getAll({'populate': true}, function(windows) { 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (var i = 0; i < windows.length; i++) { 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var tabs = windows[i].tabs; 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.injectChromeVoxIntoTabs(tabs); 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci }); 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci }, this)); 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (localStorage['active'] == 'false') { 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Warn the user when the browser first starts if ChromeVox is inactive. 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.tts.speak(cvox.ChromeVox.msgs.getMsg('chromevox_inactive'), 1); 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (cvox.PlatformUtil.matchesPlatform(cvox.PlatformFilter.WML)) { 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Introductory message. 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.tts.speak(cvox.ChromeVox.msgs.getMsg('chromevox_intro'), 1); 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cvox.ChromeVox.braille.write(cvox.NavBraille.fromText( 148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cvox.ChromeVox.msgs.getMsg('intro_brl'))); 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/** 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Inject ChromeVox into a tab. 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {Array.<Tab>} tabs The tab where ChromeVox scripts should be injected. 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {boolean=} opt_forceCompiled forces compiled ChromeVox to be injected; 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * defaults to Closure's compiled flag. 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccicvox.ChromeVoxBackground.prototype.injectChromeVoxIntoTabs = 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci function(tabs, opt_forceCompiled) { 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var listOfFiles; 162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // These lists of files must match the content_scripts section in 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the manifest files. 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (COMPILED || opt_forceCompiled) { 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci listOfFiles = ['chromeVoxChromePageScript.js']; 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci listOfFiles = [ 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'closure/closure_preinit.js', 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'closure/base.js', 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'deps.js', 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'chromevox/injected/loader.js']; 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var stageTwo = function(code) { 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (var i = 0, tab; tab = tabs[i]; i++) { 1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci window.console.log('Injecting into ' + tab.id, tab); 1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var sawError = false; 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci /** 1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * A helper function which executes code. 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {string} code The code to execute. 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var executeScript = goog.bind(function(code) { 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci chrome.tabs.executeScript( 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci tab.id, 1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci {'code': code, 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'allFrames': true}, 1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci goog.bind(function() { 1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!chrome.extension.lastError) { 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (sawError) { 1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci sawError = true; 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci console.error('Could not inject into tab', tab); 1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.tts.speak('Error starting ChromeVox for ' + 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci tab.title + ', ' + tab.url, 1); 2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci }, this)); 2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci }, this); 2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // There is a scenario where two copies of the content script can get 2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // loaded into the same tab on browser startup - one automatically and one 2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // because the background page injects the content script into every tab 2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // on startup. To work around potential bugs resulting from this, 2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // ChromeVox exports a global function called disableChromeVox() that can 2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // be used here to disable any existing running instance before we inject 2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // a new instance of the content script into this tab. 2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // 2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // It's harmless if there wasn't a copy of ChromeVox already running. 2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // 2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Also, set some variables so that Closure deps work correctly and so 2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // that ChromeVox knows not to announce feedback as if a page just loaded. 2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci executeScript('try { window.disableChromeVox(); } catch(e) { }\n' + 2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'window.INJECTED_AFTER_LOAD = true;\n' + 2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'window.CLOSURE_NO_DEPS = true\n'); 2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Now inject the ChromeVox content script code into the tab. 2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci listOfFiles.forEach(function(file) { executeScript(code[file]); }); 2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci }; 2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // We use fetchCode instead of chrome.extensions.executeFile because 2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // executeFile doesn't propagate the file name to the content script 2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // which means that script is not visible in Dev Tools. 2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cvox.InjectedScriptLoader.fetchCode(listOfFiles, stageTwo); 228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/** 232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Called when a TTS message is received from a page content script. 233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object} msg The TTS message. 234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground.prototype.onTtsMessage = function(msg) { 236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (msg['action'] == 'speak') { 237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Tell the handler for native UI (chrome of chrome) events that 238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // the last speech came from web, and not from native UI. 239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.accessibilityApiHandler_.setWebContext(); 240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.tts.speak(msg['text'], msg['queueMode'], msg['properties']); 241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (msg['action'] == 'stop') { 242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.tts.stop(); 243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (msg['action'] == 'increaseOrDecrease') { 244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.tts.increaseOrDecreaseProperty(msg['property'], msg['increase']); 245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var property = msg['property']; 246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var engine = this.backgroundTts_; 247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var valueAsPercent = Math.round( 248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.backgroundTts_.propertyToPercentage(property) * 100); 249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var announcement; 250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) switch (msg['property']) { 251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case cvox.AbstractTts.RATE: 252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) announcement = cvox.ChromeVox.msgs.getMsg('announce_rate', 253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) [valueAsPercent]); 254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case cvox.AbstractTts.PITCH: 256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) announcement = cvox.ChromeVox.msgs.getMsg('announce_pitch', 257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) [valueAsPercent]); 258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case cvox.AbstractTts.VOLUME: 260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) announcement = cvox.ChromeVox.msgs.getMsg('announce_volume', 261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) [valueAsPercent]); 262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (announcement) { 265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.tts.speak(announcement, 266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cvox.AbstractTts.QUEUE_MODE_FLUSH, 267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cvox.AbstractTts.PERSONALITY_ANNOTATION); 268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (msg['action'] == 'cyclePunctuationEcho') { 270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.tts.speak(cvox.ChromeVox.msgs.getMsg( 271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.backgroundTts_.cyclePunctuationEcho()), 272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cvox.AbstractTts.QUEUE_MODE_FLUSH); 273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/** 278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Called when an earcon message is received from a page content script. 279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object} msg The earcon message. 280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground.prototype.onEarconMessage = function(msg) { 282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (msg.action == 'play') { 283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.earcons.playEarcon(msg.earcon); 284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/** 289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Listen for connections from our content script bridges, and dispatch the 290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * messages to the proper destination. 291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground.prototype.addBridgeListener = function() { 293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cvox.ExtensionBridge.addMessageListener(goog.bind(function(msg, port) { 294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var target = msg['target']; 295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var action = msg['action']; 296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) switch (target) { 298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 'OpenTab': 299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var destination = new Object(); 300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) destination.url = msg['url']; 301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chrome.tabs.create(destination); 302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 'KbExplorer': 304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var explorerPage = new Object(); 305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) explorerPage.url = 'chromevox/background/kbexplorer.html'; 306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chrome.tabs.create(explorerPage); 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 'HelpDocs': 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var helpPage = new Object(); 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) helpPage.url = 'http://chromevox.com/tutorial/index.html'; 311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chrome.tabs.create(helpPage); 312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 'Options': 314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (action == 'open') { 315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var optionsPage = new Object(); 316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) optionsPage.url = 'chromevox/background/options.html'; 317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chrome.tabs.create(optionsPage); 318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 'Data': 321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (action == 'getHistory') { 322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var results = {}; 323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chrome.history.search({text: '', maxResults: 25}, function(items) { 324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) items.forEach(function(item) { 325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (item.url) { 326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) results[item.url] = true; 327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }); 329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) port.postMessage({ 330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 'history': results 331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }); 332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }); 333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 'Prefs': 336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (action == 'getPrefs') { 337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.prefs.sendPrefsToPort(port); 338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (action == 'setPref') { 339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (msg['pref'] == 'active' && 340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) msg['value'] != cvox.ChromeVox.isActive) { 341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (cvox.ChromeVox.isActive) { 342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.tts.speak(cvox.ChromeVox.msgs.getMsg('chromevox_inactive')); 343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chrome.accessibilityPrivate.setNativeAccessibilityEnabled( 344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) true); 345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chrome.accessibilityPrivate.setNativeAccessibilityEnabled( 347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) false); 348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (msg['pref'] == 'earcons') { 350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.earcons.enabled = msg['value']; 351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (msg['pref'] == 'sticky' && msg['announce']) { 352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (msg['value']) { 353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.tts.speak(cvox.ChromeVox.msgs.getMsg('sticky_mode_enabled')); 354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.tts.speak( 356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cvox.ChromeVox.msgs.getMsg('sticky_mode_disabled')); 357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (msg['pref'] == 'typingEcho' && msg['announce']) { 359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var announce = ''; 360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) switch (msg['value']) { 361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case cvox.TypingEcho.CHARACTER: 362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) announce = cvox.ChromeVox.msgs.getMsg('character_echo'); 363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case cvox.TypingEcho.WORD: 365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) announce = cvox.ChromeVox.msgs.getMsg('word_echo'); 366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case cvox.TypingEcho.CHARACTER_AND_WORD: 368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) announce = cvox.ChromeVox.msgs.getMsg('character_and_word_echo'); 369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case cvox.TypingEcho.NONE: 371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) announce = cvox.ChromeVox.msgs.getMsg('none_echo'); 372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) default: 374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (announce) { 377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.tts.speak(announce); 378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 379cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (msg['pref'] == 'brailleCaptions') { 380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cvox.BrailleCaptionsBackground.setActive(msg['value']); 381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.prefs.setPref(msg['pref'], msg['value']); 383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.readPrefs(); 384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 'Math': 387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO (sorge): Put the change of styles etc. here! 388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (msg['action'] == 'getDomains') { 389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) port.postMessage({'message': 'DOMAINS_STYLES', 390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 'domains': this.backgroundTts_.mathmap.allDomains, 391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 'styles': this.backgroundTts_.mathmap.allStyles}); 392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 'TTS': 395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (msg['startCallbackId'] != undefined) { 396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) msg['properties']['startCallback'] = function() { 397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) port.postMessage({'message': 'TTS_CALLBACK', 398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 'id': msg['startCallbackId']}); 399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }; 400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (msg['endCallbackId'] != undefined) { 402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) msg['properties']['endCallback'] = function() { 403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) port.postMessage({'message': 'TTS_CALLBACK', 404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 'id': msg['endCallbackId']}); 405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }; 406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) try { 408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.onTtsMessage(msg); 409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } catch (err) { 410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) console.log(err); 411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 'EARCON': 414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.onEarconMessage(msg); 415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 'BRAILLE': 417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) try { 418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.backgroundBraille_.onBrailleMessage(msg); 419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } catch (err) { 420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) console.log(err); 421cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 422cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 423cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 424cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }, this)); 425cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 426cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 427cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 428cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/** 429cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Checks the version number. If it has changed, display release notes 430cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * to the user. 431cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 432cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground.prototype.checkVersionNumber = function() { 433cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Don't update version or show release notes if the current tab is within an 434cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // incognito window (which may occur on ChromeOS immediately after OOBE). 435cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (this.isIncognito_()) { 436cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 437cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 438cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.localStorageVersion = localStorage['versionString']; 439cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.showNotesIfNewVersion(); 440cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 441cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 443cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/** 444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Display release notes to the user. 445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 446cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground.prototype.displayReleaseNotes = function() { 447cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chrome.tabs.create( 448cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) {'url': 'http://chromevox.com/release_notes.html'}); 449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 450cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 451cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 452cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/** 453cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Gets the current version number from the extension manifest. 454cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 455cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground.prototype.showNotesIfNewVersion = function() { 456cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Check version number in manifest. 457cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var url = chrome.extension.getURL('manifest.json'); 458cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var xhr = new XMLHttpRequest(); 459cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var context = this; 460cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) xhr.onreadystatechange = function() { 461cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (xhr.readyState == 4) { 462cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var manifest = JSON.parse(xhr.responseText); 463cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) console.log('Version: ' + manifest.version); 464cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 465cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var shouldShowReleaseNotes = 466cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) (context.localStorageVersion != manifest.version); 467cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 468cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // On Chrome OS, don't show the release notes the first time, only 469cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // after a version upgrade. 470cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (navigator.userAgent.indexOf('CrOS') != -1 && 471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) context.localStorageVersion == undefined) { 472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) shouldShowReleaseNotes = false; 473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (shouldShowReleaseNotes) { 476cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) context.displayReleaseNotes(); 477cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 478cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 479cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Update version number in local storage 480cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) localStorage['versionString'] = manifest.version; 481cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.localStorageVersion = manifest.version; 482cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 483cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }; 484cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) xhr.open('GET', url); 485cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) xhr.send(); 486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 487cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 488cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 489cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/** 490cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Read and apply preferences that affect the background context. 491cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 492cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground.prototype.readPrefs = function() { 493cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var prefs = this.prefs.getPrefs(); 494cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cvox.ChromeVoxEditableTextBase.useIBeamCursor = 495cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) (prefs['useIBeamCursor'] == 'true'); 496cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cvox.ChromeVox.isActive = 497cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) (prefs['active'] == 'true' || cvox.ChromeVox.isChromeOS); 49846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) cvox.ChromeVox.isStickyPrefOn = (prefs['sticky'] == 'true'); 499cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 500cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 501cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/** 502cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Checks if we are currently in an incognito window. 503cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {boolean} True if incognito or not within a tab context, false 504cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * otherwise. 505cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @private 506cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 507cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground.prototype.isIncognito_ = function() { 508cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var incognito = false; 509cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chrome.tabs.getCurrent(function(tab) { 510cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Tab is null if not called from a tab context. In that case, also consider 511cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // it incognito. 512cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) incognito = tab ? tab.incognito : true; 513cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }); 514cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return incognito; 515cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 516cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 517cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 518cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// TODO(dtseng): The loading param is no longer used. Remove it once the 519cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// upstream Chrome API changes. 520cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/** 521cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Handles the onChromeVoxLoadStateChanged event. 522cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {boolean} loading True if ChromeVox is loading; false if it is 523cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * unloading. 524cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {boolean} makeAnnouncements True if announcements should be made. 525cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 526cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground.prototype.onLoadStateChanged = function( 527cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) loading, makeAnnouncements) { 528cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (loading) { 529cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (makeAnnouncements) { 530cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cvox.ChromeVox.tts.speak(cvox.ChromeVox.msgs.getMsg('chromevox_intro'), 531cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1, 532cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) {doNotInterrupt: true}); 533cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cvox.ChromeVox.braille.write(cvox.NavBraille.fromText( 534cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cvox.ChromeVox.msgs.getMsg('intro_brl'))); 535cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 536cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 537cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) }; 538cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 539cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 540cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Create the background page object and export a function window['speak'] 541cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// so that other background pages can access it. Also export the prefs object 542cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// for access by the options page. 543cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)(function() { 544cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var background = new cvox.ChromeVoxBackground(); 545cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) background.init(); 546cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) window['speak'] = goog.bind(background.tts.speak, background.tts); 547cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 548cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Export the prefs object for access by the options page. 549cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) window['prefs'] = background.prefs; 550cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 551cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Export the braille object for access by the options page. 552cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) window['braille'] = cvox.ChromeVox.braille; 5531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Export this background page for ChromeVox Next to access. 5551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cvox.ChromeVox.background = background; 556cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)})(); 557