1 // Copyright (c) 2012 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 cr.define('options', function() { 6 7 ///////////////////////////////////////////////////////////////////////////// 8 // Preferences class: 9 10 /** 11 * Preferences class manages access to Chrome profile preferences. 12 * @constructor 13 */ 14 function Preferences() { 15 // Map of registered preferences. 16 this.registeredPreferences_ = {}; 17 } 18 19 cr.addSingletonGetter(Preferences); 20 21 /** 22 * Sets a Boolean preference and signals its new value. 23 * @param {string} name Preference name. 24 * @param {boolean} value New preference value. 25 * @param {boolean} commit Whether to commit the change to Chrome. 26 * @param {string} metric User metrics identifier. 27 */ 28 Preferences.setBooleanPref = function(name, value, commit, metric) { 29 if (!commit) { 30 Preferences.getInstance().setPrefNoCommit_(name, 'bool', Boolean(value)); 31 return; 32 } 33 34 var argumentList = [name, Boolean(value)]; 35 if (metric != undefined) argumentList.push(metric); 36 chrome.send('setBooleanPref', argumentList); 37 }; 38 39 /** 40 * Sets an integer preference and signals its new value. 41 * @param {string} name Preference name. 42 * @param {number} value New preference value. 43 * @param {boolean} commit Whether to commit the change to Chrome. 44 * @param {string} metric User metrics identifier. 45 */ 46 Preferences.setIntegerPref = function(name, value, commit, metric) { 47 if (!commit) { 48 Preferences.getInstance().setPrefNoCommit_(name, 'int', Number(value)); 49 return; 50 } 51 52 var argumentList = [name, Number(value)]; 53 if (metric != undefined) argumentList.push(metric); 54 chrome.send('setIntegerPref', argumentList); 55 }; 56 57 /** 58 * Sets a double-valued preference and signals its new value. 59 * @param {string} name Preference name. 60 * @param {number} value New preference value. 61 * @param {boolean} commit Whether to commit the change to Chrome. 62 * @param {string} metric User metrics identifier. 63 */ 64 Preferences.setDoublePref = function(name, value, commit, metric) { 65 if (!commit) { 66 Preferences.getInstance().setPrefNoCommit_(name, 'double', Number(value)); 67 return; 68 } 69 70 var argumentList = [name, Number(value)]; 71 if (metric != undefined) argumentList.push(metric); 72 chrome.send('setDoublePref', argumentList); 73 }; 74 75 /** 76 * Sets a string preference and signals its new value. 77 * @param {string} name Preference name. 78 * @param {string} value New preference value. 79 * @param {boolean} commit Whether to commit the change to Chrome. 80 * @param {string} metric User metrics identifier. 81 */ 82 Preferences.setStringPref = function(name, value, commit, metric) { 83 if (!commit) { 84 Preferences.getInstance().setPrefNoCommit_(name, 'string', String(value)); 85 return; 86 } 87 88 var argumentList = [name, String(value)]; 89 if (metric != undefined) argumentList.push(metric); 90 chrome.send('setStringPref', argumentList); 91 }; 92 93 /** 94 * Sets a string preference that represents a URL and signals its new value. 95 * The value will be fixed to be a valid URL when it gets committed to Chrome. 96 * @param {string} name Preference name. 97 * @param {string} value New preference value. 98 * @param {boolean} commit Whether to commit the change to Chrome. 99 * @param {string} metric User metrics identifier. 100 */ 101 Preferences.setURLPref = function(name, value, commit, metric) { 102 if (!commit) { 103 Preferences.getInstance().setPrefNoCommit_(name, 'url', String(value)); 104 return; 105 } 106 107 var argumentList = [name, String(value)]; 108 if (metric != undefined) argumentList.push(metric); 109 chrome.send('setURLPref', argumentList); 110 }; 111 112 /** 113 * Sets a JSON list preference and signals its new value. 114 * @param {string} name Preference name. 115 * @param {Array} value New preference value. 116 * @param {boolean} commit Whether to commit the change to Chrome. 117 * @param {string} metric User metrics identifier. 118 */ 119 Preferences.setListPref = function(name, value, commit, metric) { 120 if (!commit) { 121 Preferences.getInstance().setPrefNoCommit_(name, 'list', value); 122 return; 123 } 124 125 var argumentList = [name, JSON.stringify(value)]; 126 if (metric != undefined) argumentList.push(metric); 127 chrome.send('setListPref', argumentList); 128 }; 129 130 /** 131 * Clears the user setting for a preference and signals its new effective 132 * value. 133 * @param {string} name Preference name. 134 * @param {boolean} commit Whether to commit the change to Chrome. 135 * @param {string} metric User metrics identifier. 136 */ 137 Preferences.clearPref = function(name, commit, metric) { 138 if (!commit) { 139 Preferences.getInstance().clearPrefNoCommit_(name); 140 return; 141 } 142 143 var argumentList = [name]; 144 if (metric != undefined) argumentList.push(metric); 145 chrome.send('clearPref', argumentList); 146 }; 147 148 Preferences.prototype = { 149 __proto__: cr.EventTarget.prototype, 150 151 /** 152 * Adds an event listener to the target. 153 * @param {string} type The name of the event. 154 * @param {!Function|{handleEvent:Function}} handler The handler for the 155 * event. This is called when the event is dispatched. 156 */ 157 addEventListener: function(type, handler) { 158 cr.EventTarget.prototype.addEventListener.call(this, type, handler); 159 if (!(type in this.registeredPreferences_)) 160 this.registeredPreferences_[type] = {}; 161 }, 162 163 /** 164 * Initializes preference reading and change notifications. 165 */ 166 initialize: function() { 167 var params1 = ['Preferences.prefsFetchedCallback']; 168 var params2 = ['Preferences.prefsChangedCallback']; 169 for (var prefName in this.registeredPreferences_) { 170 params1.push(prefName); 171 params2.push(prefName); 172 } 173 chrome.send('fetchPrefs', params1); 174 chrome.send('observePrefs', params2); 175 }, 176 177 /** 178 * Helper function for flattening of dictionary passed via fetchPrefs 179 * callback. 180 * @param {string} prefix Preference name prefix. 181 * @param {object} dict Map with preference values. 182 * @private 183 */ 184 flattenMapAndDispatchEvent_: function(prefix, dict) { 185 for (var prefName in dict) { 186 if (typeof dict[prefName] == 'object' && 187 !this.registeredPreferences_[prefix + prefName]) { 188 this.flattenMapAndDispatchEvent_(prefix + prefName + '.', 189 dict[prefName]); 190 } else { 191 var event = new Event(prefix + prefName); 192 this.registeredPreferences_[prefix + prefName].orig = dict[prefName]; 193 event.value = dict[prefName]; 194 this.dispatchEvent(event); 195 } 196 } 197 }, 198 199 /** 200 * Sets a preference and signals its new value. The change is propagated 201 * throughout the UI code but is not committed to Chrome yet. The new value 202 * and its data type are stored so that commitPref() can later be used to 203 * invoke the appropriate set*Pref() method and actually commit the change. 204 * @param {string} name Preference name. 205 * @param {string} type Preference data type. 206 * @param {*} value New preference value. 207 * @private 208 */ 209 setPrefNoCommit_: function(name, type, value) { 210 var pref = this.registeredPreferences_[name]; 211 pref.action = 'set'; 212 pref.type = type; 213 pref.value = value; 214 215 var event = new Event(name); 216 // Decorate pref value as CoreOptionsHandler::CreateValueForPref() does. 217 event.value = { 218 value: value, 219 recommendedValue: pref.orig.recommendedValue, 220 disabled: pref.orig.disabled, 221 uncommitted: true, 222 }; 223 this.dispatchEvent(event); 224 }, 225 226 /** 227 * Clears a preference and signals its new value. The change is propagated 228 * throughout the UI code but is not committed to Chrome yet. 229 * @param {string} name Preference name. 230 * @private 231 */ 232 clearPrefNoCommit_: function(name) { 233 var pref = this.registeredPreferences_[name]; 234 pref.action = 'clear'; 235 delete pref.type; 236 delete pref.value; 237 238 var event = new Event(name); 239 // Decorate pref value as CoreOptionsHandler::CreateValueForPref() does. 240 event.value = { 241 value: pref.orig.recommendedValue, 242 controlledBy: 'recommended', 243 recommendedValue: pref.orig.recommendedValue, 244 disabled: pref.orig.disabled, 245 uncommitted: true, 246 }; 247 this.dispatchEvent(event); 248 }, 249 250 /** 251 * Commits a preference change to Chrome and signals the new preference 252 * value. Does nothing if there is no uncommitted change. 253 * @param {string} name Preference name. 254 * @param {string} metric User metrics identifier. 255 */ 256 commitPref: function(name, metric) { 257 var pref = this.registeredPreferences_[name]; 258 switch (pref.action) { 259 case 'set': 260 switch (pref.type) { 261 case 'bool': 262 Preferences.setBooleanPref(name, pref.value, true, metric); 263 break; 264 case 'int': 265 Preferences.setIntegerPref(name, pref.value, true, metric); 266 break; 267 case 'double': 268 Preferences.setDoublePref(name, pref.value, true, metric); 269 break; 270 case 'string': 271 Preferences.setStringPref(name, pref.value, true, metric); 272 break; 273 case 'url': 274 Preferences.setURLPref(name, pref.value, true, metric); 275 break; 276 case 'list': 277 Preferences.setListPref(name, pref.value, true, metric); 278 break; 279 } 280 break; 281 case 'clear': 282 Preferences.clearPref(name, true, metric); 283 break; 284 } 285 delete pref.action; 286 delete pref.type; 287 delete pref.value; 288 }, 289 290 /** 291 * Rolls back a preference change and signals the original preference value. 292 * Does nothing if there is no uncommitted change. 293 * @param {string} name Preference name. 294 */ 295 rollbackPref: function(name) { 296 var pref = this.registeredPreferences_[name]; 297 if (!pref.action) 298 return; 299 300 delete pref.action; 301 delete pref.type; 302 delete pref.value; 303 304 var event = new Event(name); 305 event.value = pref.orig; 306 event.value.uncommitted = true; 307 this.dispatchEvent(event); 308 } 309 }; 310 311 /** 312 * Callback for fetchPrefs method. 313 * @param {object} dict Map of fetched property values. 314 */ 315 Preferences.prefsFetchedCallback = function(dict) { 316 Preferences.getInstance().flattenMapAndDispatchEvent_('', dict); 317 }; 318 319 /** 320 * Callback for observePrefs method. 321 * @param {array} notification An array defining changed preference values. 322 * notification[0] contains name of the change preference while its new value 323 * is stored in notification[1]. 324 */ 325 Preferences.prefsChangedCallback = function(notification) { 326 var event = new Event(notification[0]); 327 event.value = notification[1]; 328 prefs = Preferences.getInstance(); 329 prefs.registeredPreferences_[notification[0]] = {orig: notification[1]}; 330 prefs.dispatchEvent(event); 331 }; 332 333 // Export 334 return { 335 Preferences: Preferences 336 }; 337 338 }); 339