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 Common page for reading and writing preferences from 7 * the background context (background page or options page). 8 * 9 */ 10 11 goog.provide('cvox.ChromeVoxPrefs'); 12 13 goog.require('cvox.ChromeVox'); 14 goog.require('cvox.ExtensionBridge'); 15 goog.require('cvox.KeyMap'); 16 17 18 /** 19 * This object has default values of preferences and contains the common 20 * code for working with preferences shared by the Options and Background 21 * pages. 22 * @constructor 23 */ 24 cvox.ChromeVoxPrefs = function() { 25 var lastRunVersion = localStorage['lastRunVersion']; 26 if (!lastRunVersion) { 27 lastRunVersion = '1.16.0'; 28 } 29 var loadExistingSettings = true; 30 // TODO(dtseng): Logic below needs clarification. Perhaps needs a 31 // 'lastIncompatibleVersion' member. 32 if (lastRunVersion == '1.16.0') { 33 loadExistingSettings = false; 34 } 35 localStorage['lastRunVersion'] = chrome.app.getDetails().version; 36 37 /** 38 * The current mapping from keys to command. 39 * @type {!cvox.KeyMap} 40 * @private 41 */ 42 this.keyMap_ = cvox.KeyMap.fromLocalStorage() || cvox.KeyMap.fromDefaults(); 43 this.keyMap_.merge(cvox.KeyMap.fromDefaults()); 44 45 // Clear per session preferences. 46 // This is to keep the position dictionary from growing excessively large. 47 localStorage['position'] = '{}'; 48 49 // Default per session sticky to off. 50 localStorage['sticky'] = false; 51 52 this.init(loadExistingSettings); 53 }; 54 55 56 /** 57 * The default value of all preferences except the key map. 58 * @const 59 * @type {Object.<string, Object>} 60 */ 61 cvox.ChromeVoxPrefs.DEFAULT_PREFS = { 62 'active': true, 63 'brailleCaptions': false, 64 // TODO(dtseng): Leaking state about multiple key maps here until we have a 65 // class to manage multiple key maps. Also, this doesn't belong as a pref; 66 // should just store in local storage. 67 'currentKeyMap' : cvox.KeyMap.DEFAULT_KEYMAP, 68 'cvoxKey': '', 69 'earcons': true, 70 'focusFollowsMouse': false, 71 'granularity': undefined, 72 'position': '{}', 73 'siteSpecificScriptBase': 74 'https://ssl.gstatic.com/accessibility/javascript/ext/', 75 'siteSpecificScriptLoader': 76 'https://ssl.gstatic.com/accessibility/javascript/ext/loader.js', 77 'sticky': false, 78 'typingEcho': 0, 79 'useIBeamCursor': cvox.ChromeVox.isMac, 80 'useVerboseMode': true, 81 'siteSpecificEnhancements': true 82 }; 83 84 85 /** 86 * Merge the default values of all known prefs with what's found in 87 * localStorage. 88 * @param {boolean} pullFromLocalStorage or not to pull prefs from local 89 * storage. True if we want to respect changes the user has already made 90 * to prefs, false if we want to overwrite them. Set false if we've made 91 * changes to keyboard shortcuts and need to make sure they aren't 92 * overridden by the old keymap in local storage. 93 */ 94 cvox.ChromeVoxPrefs.prototype.init = function(pullFromLocalStorage) { 95 // Set the default value of any pref that isn't already in localStorage. 96 for (var pref in cvox.ChromeVoxPrefs.DEFAULT_PREFS) { 97 if (localStorage[pref] === undefined) { 98 localStorage[pref] = cvox.ChromeVoxPrefs.DEFAULT_PREFS[pref]; 99 } 100 } 101 }; 102 103 /** 104 * Switches to another key map. 105 * @param {string} selectedKeyMap The id of the keymap in 106 * cvox.KeyMap.AVAIABLE_KEYMAP_INFO. 107 */ 108 cvox.ChromeVoxPrefs.prototype.switchToKeyMap = function(selectedKeyMap) { 109 // TODO(dtseng): Leaking state about multiple key maps here until we have a 110 // class to manage multiple key maps. 111 localStorage['currentKeyMap'] = selectedKeyMap; 112 this.keyMap_ = cvox.KeyMap.fromCurrentKeyMap(); 113 this.keyMap_.toLocalStorage(); 114 this.keyMap_.resetModifier(); 115 this.sendPrefsToAllTabs(false, true); 116 }; 117 118 119 /** 120 * Get the prefs (not including keys). 121 * @return {Object} A map of all prefs except the key map from localStorage. 122 */ 123 cvox.ChromeVoxPrefs.prototype.getPrefs = function() { 124 var prefs = {}; 125 for (var pref in cvox.ChromeVoxPrefs.DEFAULT_PREFS) { 126 prefs[pref] = localStorage[pref]; 127 } 128 prefs['version'] = chrome.app.getDetails().version; 129 return prefs; 130 }; 131 132 133 /** 134 * Reloads the key map from local storage. 135 */ 136 cvox.ChromeVoxPrefs.prototype.reloadKeyMap = function() { 137 // Get the current key map from localStorage. 138 // TODO(dtseng): We currently don't support merges since we write the entire 139 // map back to local storage. 140 var currentKeyMap = cvox.KeyMap.fromLocalStorage(); 141 if (!currentKeyMap) { 142 currentKeyMap = cvox.KeyMap.fromCurrentKeyMap(); 143 currentKeyMap.toLocalStorage(); 144 } 145 this.keyMap_ = currentKeyMap; 146 }; 147 148 149 /** 150 * Get the key map, from key binding to an array of [command, description]. 151 * @return {cvox.KeyMap} The key map. 152 */ 153 cvox.ChromeVoxPrefs.prototype.getKeyMap = function() { 154 return this.keyMap_; 155 }; 156 157 158 /** 159 * Reset to the default key bindings. 160 */ 161 cvox.ChromeVoxPrefs.prototype.resetKeys = function() { 162 this.keyMap_ = cvox.KeyMap.fromDefaults(); 163 this.keyMap_.toLocalStorage(); 164 this.sendPrefsToAllTabs(false, true); 165 }; 166 167 168 /** 169 * Send all of the settings to all tabs. 170 * @param {boolean} sendPrefs Whether to send the prefs. 171 * @param {boolean} sendKeyBindings Whether to send the key bindings. 172 */ 173 cvox.ChromeVoxPrefs.prototype.sendPrefsToAllTabs = 174 function(sendPrefs, sendKeyBindings) { 175 var context = this; 176 var message = {}; 177 if (sendPrefs) { 178 message['prefs'] = context.getPrefs(); 179 } 180 if (sendKeyBindings) { 181 // Note that cvox.KeyMap stringifies to a minimal object when message gets 182 // passed to the content script. 183 message['keyBindings'] = this.keyMap_.toJSON(); 184 } 185 chrome.windows.getAll({populate: true}, function(windows) { 186 for (var i = 0; i < windows.length; i++) { 187 var tabs = windows[i].tabs; 188 for (var j = 0; j < tabs.length; j++) { 189 chrome.tabs.sendMessage(tabs[j].id, message); 190 } 191 } 192 }); 193 }; 194 195 /** 196 * Send all of the settings over the specified port. 197 * @param {Port} port The port representing the connection to a content script. 198 */ 199 cvox.ChromeVoxPrefs.prototype.sendPrefsToPort = function(port) { 200 port.postMessage({ 201 'keyBindings': this.keyMap_.toJSON(), 202 'prefs': this.getPrefs()}); 203 }; 204 205 206 /** 207 * Set the value of a pref and update all active tabs if it's changed. 208 * @param {string} key The pref key. 209 * @param {Object|string} value The new value of the pref. 210 */ 211 cvox.ChromeVoxPrefs.prototype.setPref = function(key, value) { 212 if (localStorage[key] != value) { 213 localStorage[key] = value; 214 this.sendPrefsToAllTabs(true, false); 215 } 216 }; 217 218 /** 219 * Delegates to cvox.KeyMap. 220 * @param {string} command The command to set. 221 * @param {cvox.KeySequence} newKey The new key to assign it to. 222 * @return {boolean} True if the key was bound to the command. 223 */ 224 cvox.ChromeVoxPrefs.prototype.setKey = function(command, newKey) { 225 if (this.keyMap_.rebind(command, newKey)) { 226 this.keyMap_.toLocalStorage(); 227 this.sendPrefsToAllTabs(false, true); 228 return true; 229 } 230 return false; 231 }; 232