braille_background.js revision cedac228d2dd51db4b79ea1e72c7f249408ee061
1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/**
6 * @fileoverview Sends Braille commands to the Braille API.
7 */
8
9goog.provide('cvox.BrailleBackground');
10
11goog.require('cvox.AbstractBraille');
12goog.require('cvox.BrailleDisplayManager');
13goog.require('cvox.BrailleTable');
14goog.require('cvox.ChromeVox');
15goog.require('cvox.LibLouis');
16
17
18/**
19 * @constructor
20 * @param {cvox.BrailleDisplayManager=} opt_displayManagerForTest
21 *        display manager (for mocking in tests)
22 * @extends {cvox.AbstractBraille}
23 */
24cvox.BrailleBackground = function(opt_displayManagerForTest) {
25  goog.base(this);
26  /**
27   * @type {cvox.BrailleDisplayManager}
28   * @private
29   */
30  this.displayManager_ = opt_displayManagerForTest ||
31      new cvox.BrailleDisplayManager();
32  cvox.BrailleTable.getAll(goog.bind(function(tables) {
33    /**
34     * @type {!Array.<cvox.BrailleTable.Table>}
35     * @private
36     */
37    this.tables_ = tables;
38    this.initialize_(0);
39  }, this));
40  this.displayManager_.setCommandListener(goog.bind(this.sendCommand_, this));
41  /**
42   * @type {cvox.NavBraille}
43   * @private
44   */
45  this.lastContent_ = null;
46  /**
47   * @type {?string}
48   * @private
49   */
50  this.lastContentId_ = null;
51};
52goog.inherits(cvox.BrailleBackground, cvox.AbstractBraille);
53
54
55/** @override */
56cvox.BrailleBackground.prototype.write = function(params) {
57  this.lastContentId_ = null;
58  this.lastContent_ = null;
59  this.displayManager_.setContent(params);
60};
61
62
63/** @override */
64cvox.BrailleBackground.prototype.setCommandListener = function(func) {
65  // TODO(plundblad): Implement when the background page handles commands
66  // as well.
67};
68
69
70/**
71 * Refreshes the braille translator used for output.  This should be
72 * called when something changed (such as a preference) to make sure that
73 * the correct translator is used.
74 */
75cvox.BrailleBackground.prototype.refreshTranslator = function() {
76  if (!this.liblouis_) {
77    return;
78  }
79  // First, see if we have a braille table set previously.
80  var tables = this.tables_;
81  var table = cvox.BrailleTable.forId(tables, localStorage['brailleTable']);
82  if (!table) {
83    // Match table against current locale.
84    var currentLocale = chrome.i18n.getMessage('@@ui_locale').split(/[_-]/);
85    var major = currentLocale[0];
86    var minor = currentLocale[1];
87    var firstPass = tables.filter(function(table) {
88      return table.locale.split(/[_-]/)[0] == major;
89    });
90    if (firstPass.length > 0) {
91      table = firstPass[0];
92      if (minor) {
93        var secondPass = firstPass.filter(function(table) {
94          return table.locale.split(/[_-]/)[1] == minor;
95        });
96        if (secondPass.length > 0) {
97          table = secondPass[0];
98        }
99      }
100    }
101  }
102  if (!table) {
103    table = cvox.BrailleTable.forId(tables, 'en-US-comp8');
104  }
105  // TODO(plundblad): ONly update when user explicitly chooses a table
106  // so that switching locales changes table by default.
107  localStorage['brailleTable'] = table.id;
108  if (table.dots == '6') {
109    localStorage['brailleTableType'] = 'brailleTable6';
110    localStorage['brailleTable6'] = table.id;
111  } else {
112    localStorage['brailleTableType'] = 'brailleTable8';
113    localStorage['brailleTable8'] = table.id;
114  }
115
116  // Initialize all other defaults.
117  // TODO(plundblad): Stop doing this here.
118  if (!localStorage['brailleTable6']) {
119    localStorage['brailleTable6'] = 'en-US-g1';
120  }
121  if (!localStorage['brailleTable8']) {
122    localStorage['brailleTable8'] = 'en-US-comp8';
123  }
124
125  // If the user explicitly set an 8 dot table, use that when looking
126  // for an uncontracted table.  Otherwise, use the current table and let
127  // getUncontracted find an appropriate corresponding table.
128  var table8Dot = cvox.BrailleTable.forId(tables,
129                                          localStorage['brailleTable8']);
130  var uncontractedTable = cvox.BrailleTable.getUncontracted(
131      tables,
132      table8Dot ? table8Dot : table);
133  this.liblouis_.getTranslator(table.fileName, goog.bind(
134      function(translator) {
135        if (uncontractedTable.id === table.id) {
136          this.displayManager_.setTranslator(translator);
137        } else {
138          this.liblouis_.getTranslator(uncontractedTable.fileName, goog.bind(
139              function(uncontractedTranslator) {
140                this.displayManager_.setTranslator(
141                    translator, uncontractedTranslator);
142              }, this));
143        }
144      }, this));
145};
146
147
148/**
149 * Called when a Braille message is received from a page content script.
150 * @param {Object} msg The Braille message.
151 */
152cvox.BrailleBackground.prototype.onBrailleMessage = function(msg) {
153  if (msg['action'] == 'write') {
154    this.lastContentId_ = msg['contentId'];
155    this.lastContent_ = cvox.NavBraille.fromJson(msg['params']);
156    this.displayManager_.setContent(this.lastContent_);
157  }
158};
159
160
161/**
162 * Initialization to be done after part of the background page's DOM has been
163 * constructed. Currently only used on ChromeOS.
164 * @param {number} retries Number of retries.
165 * @private
166 */
167cvox.BrailleBackground.prototype.initialize_ = function(retries) {
168  if (retries > 5) {
169    console.error(
170        'Timeout waiting for document.body; not initializing braille.');
171    return;
172  }
173  if (!document.body) {
174    window.setTimeout(goog.bind(this.initialize_, this, ++retries), 500);
175  } else {
176    /**
177     * @type {cvox.LibLouis}
178     * @private
179     */
180    this.liblouis_ = new cvox.LibLouis(
181        chrome.extension.getURL(
182            'chromevox/background/braille/liblouis_nacl.nmf'),
183        chrome.extension.getURL(
184            'chromevox/background/braille/tables'));
185    this.liblouis_.attachToElement(document.body);
186    this.refreshTranslator();
187  }
188};
189
190
191/**
192 * Dispatches braille input commands to the content script.
193 * @param {!cvox.BrailleKeyEvent} brailleEvt The event.
194 * @param {cvox.NavBraille} content content of display when event fired.
195 * @private
196 */
197cvox.BrailleBackground.prototype.sendCommand_ =
198    function(brailleEvt, content) {
199  var msg = {
200    'message': 'BRAILLE',
201    'args': brailleEvt
202  };
203  if (content === this.lastContent_) {
204    msg.contentId = this.lastContentId_;
205  }
206  cvox.ExtensionBridge.send(msg);
207};
208