background.js revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
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.ChromeMsgs');
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.ChromeVox');
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.ChromeVoxEditableTextBase');
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.ChromeVoxPrefs');
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.CompositeTts');
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.ConsoleTts');
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.EarconsBackground');
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.ExtensionBridge');
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.HostFactory');
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.InjectedScriptLoader');
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');
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.TtsBackground');
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * This object manages the global and persistent state for ChromeVox.
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * It listens for messages from the content scripts on pages and
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * interprets them.
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @constructor
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground = function() {
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Initialize the background page: set up TTS and bridge listeners.
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground.prototype.init = function() {
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // In the case of ChromeOS, only continue initialization if this instance of
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // ChromeVox is as we expect. This prevents ChromeVox from the webstore from
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // running.
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (cvox.ChromeVox.isChromeOS &&
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      chrome.i18n.getMessage('@@extension_id') !=
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          'mndnfokpggljbaajbnioimlmbfngpief') {
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cvox.ChromeVox.msgs = cvox.HostFactory.getMsgs();
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.prefs = new cvox.ChromeVoxPrefs();
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.readPrefs();
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var consoleTts = cvox.ConsoleTts.getInstance();
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  consoleTts.setEnabled(true);
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  /**
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * Chrome's actual TTS which knows and cares about pitch, volume, etc.
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * @type {cvox.TtsBackground}
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * @private
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   */
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.backgroundTts_ = new cvox.TtsBackground();
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  /**
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * @type {cvox.TtsInterface}
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   */
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.tts = new cvox.CompositeTts()
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      .add(this.backgroundTts_)
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      .add(consoleTts);
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.earcons = new cvox.EarconsBackground();
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.addBridgeListener();
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  /**
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * The actual Braille service.
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * @type {cvox.BrailleBackground}
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * @private
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   */
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.backgroundBraille_ = new cvox.BrailleBackground();
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.accessibilityApiHandler_ = new cvox.AccessibilityApiHandler(
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      this.tts, this.backgroundBraille_, this.earcons);
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Export globals on cvox.ChromeVox.
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cvox.ChromeVox.tts = this.tts;
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cvox.ChromeVox.braille = this.backgroundBraille_;
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cvox.ChromeVox.earcons = this.earcons;
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(dtseng): Remove the second check on or after m33.
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (cvox.ChromeVox.isChromeOS &&
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      chrome.accessibilityPrivate.onChromeVoxLoadStateChanged) {
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    chrome.accessibilityPrivate.onChromeVoxLoadStateChanged.addListener(
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        this.onLoadStateChanged);
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var listOfFiles;
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // These lists of files must match the content_scripts section in
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // the manifest files.
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (COMPILED) {
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    listOfFiles = ['chromeVoxChromePageScript.js'];
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    listOfFiles = [
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        'closure/closure_preinit.js',
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        'closure/base.js',
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        'deps.js',
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        'chromevox/injected/loader.js'];
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var self = this;
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var stageTwo = function(code) {
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Inject the content script into all running tabs.
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    chrome.windows.getAll({'populate': true}, function(windows) {
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      for (var i = 0; i < windows.length; i++) {
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        var tabs = windows[i].tabs;
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        for (var j = 0; j < tabs.length; j++) {
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          var tab = tabs[j];
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          self.injectChromeVoxIntoTab(tab, listOfFiles, code);
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    });
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  };
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.checkVersionNumber();
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Set up a message passing system for goog.provide() calls from
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // within the content scripts.
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  chrome.extension.onMessage.addListener(
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      function(request, sender, callback) {
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (request['srcFile']) {
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          var srcFile = request['srcFile'];
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          cvox.InjectedScriptLoader.fetchCode(
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              [srcFile],
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              function(code) {
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                callback({'code': code[srcFile]});
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              });
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        return true;
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      });
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // We use fetchCode instead of chrome.extensions.executeFile because
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // executeFile doesn't propagate the file name to the content script
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // which means that script is not visible in Dev Tools.
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cvox.InjectedScriptLoader.fetchCode(listOfFiles, stageTwo);
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (localStorage['active'] == 'false') {
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Warn the user when the browser first starts if ChromeVox is inactive.
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    this.tts.speak(cvox.ChromeVox.msgs.getMsg('chromevox_inactive'), 1);
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else if (cvox.PlatformUtil.matchesPlatform(cvox.PlatformFilter.WML)) {
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Introductory message.
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    this.tts.speak(cvox.ChromeVox.msgs.getMsg('chromevox_intro'), 1);
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    cvox.ChromeVox.braille.write(cvox.NavBraille.fromText(
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        cvox.ChromeVox.msgs.getMsg('intro_brl')));
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Inject ChromeVox into a tab.
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Tab} tab The tab where ChromeVox scripts should be injected.
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Array.<string>} files The files to load.
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object.<string, string>} code The contents of the files.
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground.prototype.injectChromeVoxIntoTab =
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    function(tab, files, code) {
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  window.console.log('Injecting into ' + tab.id, tab);
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var sawError = false;
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  /**
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * A helper function which executes code.
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * @param {string} code The code to execute.
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   */
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var executeScript = goog.bind(function(code) {
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    chrome.tabs.executeScript(
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        tab.id,
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        {'code': code,
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         'allFrames': true},
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        goog.bind(function() {
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          if (!chrome.extension.lastError) {
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            return;
189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          }
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          if (sawError) {
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            return;
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          }
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          sawError = true;
194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          console.error('Could not inject into tab', tab);
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          this.tts.speak('Error starting ChromeVox for ' +
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              tab.title + ', ' + tab.url, 1);
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }, this));
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }, this);
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // There is a scenario where two copies of the content script can get
201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // loaded into the same tab on browser startup - one automatically
202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // and one because the background page injects the content script into
203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // every tab on startup. To work around potential bugs resulting from this,
204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // ChromeVox exports a global function called disableChromeVox() that can
205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // be used here to disable any existing running instance before we inject
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // a new instance of the content script into this tab.
207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  //
208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // It's harmless if there wasn't a copy of ChromeVox already running.
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  //
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Also, set some variables so that Closure deps work correctly and so
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // that ChromeVox knows not to announce feedback as if a page just loaded.
212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  executeScript('try { window.disableChromeVox(); } catch(e) { }\n' +
213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                'window.INJECTED_AFTER_LOAD = true;\n' +
214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                'window.CLOSURE_NO_DEPS = true\n');
215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Now inject the ChromeVox content script code into the tab.
217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  files.forEach(function(file) { executeScript(code[file]); });
218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Called when a TTS message is received from a page content script.
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object} msg The TTS message.
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground.prototype.onTtsMessage = function(msg) {
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (msg['action'] == 'speak') {
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Tell the handler for native UI (chrome of chrome) events that
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // the last speech came from web, and not from native UI.
229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    this.accessibilityApiHandler_.setWebContext();
230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    this.tts.speak(msg['text'], msg['queueMode'], msg['properties']);
231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else if (msg['action'] == 'stop') {
232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    this.tts.stop();
233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else if (msg['action'] == 'increaseOrDecrease') {
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    this.tts.increaseOrDecreaseProperty(msg['property'], msg['increase']);
235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    var property = msg['property'];
236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    var engine = this.backgroundTts_;
237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    var valueAsPercent = Math.round(
238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        this.backgroundTts_.propertyToPercentage(property) * 100);
239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    var announcement;
240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    switch (msg['property']) {
241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case cvox.AbstractTts.RATE:
242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      announcement = cvox.ChromeVox.msgs.getMsg('announce_rate',
243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                [valueAsPercent]);
244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case cvox.AbstractTts.PITCH:
246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      announcement = cvox.ChromeVox.msgs.getMsg('announce_pitch',
247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                [valueAsPercent]);
248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case cvox.AbstractTts.VOLUME:
250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      announcement = cvox.ChromeVox.msgs.getMsg('announce_volume',
251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                [valueAsPercent]);
252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (announcement) {
255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      this.tts.speak(announcement,
256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     cvox.AbstractTts.QUEUE_MODE_FLUSH,
257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     cvox.AbstractTts.PERSONALITY_ANNOTATION);
258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else if (msg['action'] == 'cyclePunctuationEcho') {
260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    this.tts.speak(cvox.ChromeVox.msgs.getMsg(
261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            this.backgroundTts_.cyclePunctuationEcho()),
262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   cvox.AbstractTts.QUEUE_MODE_FLUSH);
263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Called when an earcon message is received from a page content script.
269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object} msg The earcon message.
270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground.prototype.onEarconMessage = function(msg) {
272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (msg.action == 'play') {
273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    this.earcons.playEarcon(msg.earcon);
274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Listen for connections from our content script bridges, and dispatch the
280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * messages to the proper destination.
281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground.prototype.addBridgeListener = function() {
283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cvox.ExtensionBridge.addMessageListener(goog.bind(function(msg, port) {
284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    var target = msg['target'];
285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    var action = msg['action'];
286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    switch (target) {
288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case 'OpenTab':
289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      var destination = new Object();
290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      destination.url = msg['url'];
291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      chrome.tabs.create(destination);
292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case 'KbExplorer':
294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      var explorerPage = new Object();
295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      explorerPage.url = 'chromevox/background/kbexplorer.html';
296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      chrome.tabs.create(explorerPage);
297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case 'HelpDocs':
299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      var helpPage = new Object();
300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      helpPage.url = 'http://chromevox.com/tutorial/index.html';
301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      chrome.tabs.create(helpPage);
302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case 'Options':
304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (action == 'open') {
305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        var optionsPage = new Object();
306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        optionsPage.url = 'chromevox/background/options.html';
307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        chrome.tabs.create(optionsPage);
308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case 'Data':
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (action == 'getHistory') {
312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        var results = {};
313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        chrome.history.search({text: '', maxResults: 25}, function(items) {
314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          items.forEach(function(item) {
315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            if (item.url) {
316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              results[item.url] = true;
317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            }
318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          });
319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          port.postMessage({
320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            'history': results
321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          });
322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        });
323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case 'Prefs':
326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (action == 'getPrefs') {
327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        this.prefs.sendPrefsToPort(port);
328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      } else if (action == 'setPref') {
329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (msg['pref'] == 'active' &&
330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            msg['value'] != cvox.ChromeVox.isActive) {
331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          if (cvox.ChromeVox.isActive) {
332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            this.tts.speak(cvox.ChromeVox.msgs.getMsg('chromevox_inactive'));
333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            chrome.accessibilityPrivate.setNativeAccessibilityEnabled(
334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                true);
335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          } else {
336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            chrome.accessibilityPrivate.setNativeAccessibilityEnabled(
337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                false);
338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          }
339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        } else if (msg['pref'] == 'earcons') {
340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          this.earcons.enabled = msg['value'];
341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        } else if (msg['pref'] == 'sticky' && msg['announce']) {
342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          if (msg['value']) {
343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            this.tts.speak(cvox.ChromeVox.msgs.getMsg('sticky_mode_enabled'));
344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          } else {
345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            this.tts.speak(
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                cvox.ChromeVox.msgs.getMsg('sticky_mode_disabled'));
347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          }
348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        } else if (msg['pref'] == 'typingEcho' && msg['announce']) {
349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          var announce = '';
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          switch (msg['value']) {
351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            case cvox.TypingEcho.CHARACTER:
352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              announce = cvox.ChromeVox.msgs.getMsg('character_echo');
353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              break;
354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            case cvox.TypingEcho.WORD:
355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              announce = cvox.ChromeVox.msgs.getMsg('word_echo');
356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              break;
357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            case cvox.TypingEcho.CHARACTER_AND_WORD:
358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              announce = cvox.ChromeVox.msgs.getMsg('character_and_word_echo');
359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              break;
360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            case cvox.TypingEcho.NONE:
361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              announce = cvox.ChromeVox.msgs.getMsg('none_echo');
362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              break;
363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            default:
364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              break;
365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          }
366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          if (announce) {
367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            this.tts.speak(announce);
368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          }
369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        } else if (msg['pref'] == 'brailleCaptions') {
370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          cvox.BrailleCaptionsBackground.setActive(msg['value']);
371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        this.prefs.setPref(msg['pref'], msg['value']);
373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        this.readPrefs();
374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case 'Math':
377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // TODO (sorge): Put the change of styles etc. here!
378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (msg['action'] == 'getDomains') {
379cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        port.postMessage({'message': 'DOMAINS_STYLES',
380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          'domains': this.backgroundTts_.mathmap.allDomains,
381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          'styles': this.backgroundTts_.mathmap.allStyles});
382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case 'TTS':
385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (msg['startCallbackId'] != undefined) {
386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        msg['properties']['startCallback'] = function() {
387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          port.postMessage({'message': 'TTS_CALLBACK',
388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                            'id': msg['startCallbackId']});
389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        };
390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (msg['endCallbackId'] != undefined) {
392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        msg['properties']['endCallback'] = function() {
393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          port.postMessage({'message': 'TTS_CALLBACK',
394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                            'id': msg['endCallbackId']});
395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        };
396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      try {
398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        this.onTtsMessage(msg);
399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      } catch (err) {
400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        console.log(err);
401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case 'EARCON':
404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      this.onEarconMessage(msg);
405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case 'BRAILLE':
407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      try {
408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        this.backgroundBraille_.onBrailleMessage(msg);
409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      } catch (err) {
410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        console.log(err);
411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }, this));
415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Checks the version number. If it has changed, display release notes
420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * to the user.
421cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
422cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground.prototype.checkVersionNumber = function() {
423cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Don't update version or show release notes if the current tab is within an
424cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // incognito window (which may occur on ChromeOS immediately after OOBE).
425cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (this.isIncognito_()) {
426cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
427cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
428cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.localStorageVersion = localStorage['versionString'];
429cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.showNotesIfNewVersion();
430cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
431cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
432cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
433cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
434cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Display release notes to the user.
435cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
436cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground.prototype.displayReleaseNotes = function() {
437cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  chrome.tabs.create(
438cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      {'url': 'http://chromevox.com/release_notes.html'});
439cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
440cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
441cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
443cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Gets the current version number from the extension manifest.
444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground.prototype.showNotesIfNewVersion = function() {
446cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Check version number in manifest.
447cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var url = chrome.extension.getURL('manifest.json');
448cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var xhr = new XMLHttpRequest();
449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var context = this;
450cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  xhr.onreadystatechange = function() {
451cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (xhr.readyState == 4) {
452cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      var manifest = JSON.parse(xhr.responseText);
453cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      console.log('Version: ' + manifest.version);
454cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
455cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      var shouldShowReleaseNotes =
456cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          (context.localStorageVersion != manifest.version);
457cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
458cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // On Chrome OS, don't show the release notes the first time, only
459cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // after a version upgrade.
460cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (navigator.userAgent.indexOf('CrOS') != -1 &&
461cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          context.localStorageVersion == undefined) {
462cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        shouldShowReleaseNotes = false;
463cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
464cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
465cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (shouldShowReleaseNotes) {
466cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        context.displayReleaseNotes();
467cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
468cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
469cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Update version number in local storage
470cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      localStorage['versionString'] = manifest.version;
471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      this.localStorageVersion = manifest.version;
472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  };
474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  xhr.open('GET', url);
475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  xhr.send();
476cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
477cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
478cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
479cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
480cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Read and apply preferences that affect the background context.
481cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
482cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground.prototype.readPrefs = function() {
483cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var prefs = this.prefs.getPrefs();
484cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cvox.ChromeVoxEditableTextBase.useIBeamCursor =
485cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      (prefs['useIBeamCursor'] == 'true');
486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cvox.ChromeVox.isActive =
487cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      (prefs['active'] == 'true' || cvox.ChromeVox.isChromeOS);
48846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  cvox.ChromeVox.isStickyPrefOn = (prefs['sticky'] == 'true');
489cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
490cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
491cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
492cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Checks if we are currently in an incognito window.
493cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {boolean} True if incognito or not within a tab context, false
494cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * otherwise.
495cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @private
496cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
497cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground.prototype.isIncognito_ = function() {
498cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var incognito = false;
499cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  chrome.tabs.getCurrent(function(tab) {
500cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Tab is null if not called from a tab context. In that case, also consider
501cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // it incognito.
502cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    incognito = tab ? tab.incognito : true;
503cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  });
504cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return incognito;
505cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
506cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
507cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
508cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// TODO(dtseng): The loading param is no longer used. Remove it once the
509cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// upstream Chrome API changes.
510cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
511cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Handles the onChromeVoxLoadStateChanged event.
512cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {boolean} loading True if ChromeVox is loading; false if it is
513cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * unloading.
514cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {boolean} makeAnnouncements True if announcements should be made.
515cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
516cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ChromeVoxBackground.prototype.onLoadStateChanged = function(
517cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    loading, makeAnnouncements) {
518cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (loading) {
519cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (makeAnnouncements) {
520cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        cvox.ChromeVox.tts.speak(cvox.ChromeVox.msgs.getMsg('chromevox_intro'),
521cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 1,
522cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 {doNotInterrupt: true});
523cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        cvox.ChromeVox.braille.write(cvox.NavBraille.fromText(
524cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            cvox.ChromeVox.msgs.getMsg('intro_brl')));
525cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
526cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
527cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  };
528cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
529cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
530cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Create the background page object and export a function window['speak']
531cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// so that other background pages can access it. Also export the prefs object
532cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// for access by the options page.
533cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)(function() {
534cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var background = new cvox.ChromeVoxBackground();
535cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  background.init();
536cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  window['speak'] = goog.bind(background.tts.speak, background.tts);
537cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
538cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Export the prefs object for access by the options page.
539cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  window['prefs'] = background.prefs;
540cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
541cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Export the braille object for access by the options page.
542cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  window['braille'] = cvox.ChromeVox.braille;
543cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)})();
544