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 5cr.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 = {value: value, uncommitted: true}; 218 if (pref.orig) { 219 event.value.recommendedValue = pref.orig.recommendedValue; 220 event.value.disabled = pref.orig.disabled; 221 } 222 this.dispatchEvent(event); 223 }, 224 225 /** 226 * Clears a preference and signals its new value. The change is propagated 227 * throughout the UI code but is not committed to Chrome yet. 228 * @param {string} name Preference name. 229 * @private 230 */ 231 clearPrefNoCommit_: function(name) { 232 var pref = this.registeredPreferences_[name]; 233 pref.action = 'clear'; 234 delete pref.type; 235 delete pref.value; 236 237 var event = new Event(name); 238 // Decorate pref value as CoreOptionsHandler::CreateValueForPref() does. 239 event.value = { 240 value: pref.orig.recommendedValue, 241 controlledBy: 'recommended', 242 recommendedValue: pref.orig.recommendedValue, 243 disabled: pref.orig.disabled, 244 uncommitted: true, 245 }; 246 this.dispatchEvent(event); 247 }, 248 249 /** 250 * Commits a preference change to Chrome and signals the new preference 251 * value. Does nothing if there is no uncommitted change. 252 * @param {string} name Preference name. 253 * @param {string} metric User metrics identifier. 254 */ 255 commitPref: function(name, metric) { 256 var pref = this.registeredPreferences_[name]; 257 switch (pref.action) { 258 case 'set': 259 switch (pref.type) { 260 case 'bool': 261 Preferences.setBooleanPref(name, pref.value, true, metric); 262 break; 263 case 'int': 264 Preferences.setIntegerPref(name, pref.value, true, metric); 265 break; 266 case 'double': 267 Preferences.setDoublePref(name, pref.value, true, metric); 268 break; 269 case 'string': 270 Preferences.setStringPref(name, pref.value, true, metric); 271 break; 272 case 'url': 273 Preferences.setURLPref(name, pref.value, true, metric); 274 break; 275 case 'list': 276 Preferences.setListPref(name, pref.value, true, metric); 277 break; 278 } 279 break; 280 case 'clear': 281 Preferences.clearPref(name, true, metric); 282 break; 283 } 284 delete pref.action; 285 delete pref.type; 286 delete pref.value; 287 }, 288 289 /** 290 * Rolls back a preference change and signals the original preference value. 291 * Does nothing if there is no uncommitted change. 292 * @param {string} name Preference name. 293 */ 294 rollbackPref: function(name) { 295 var pref = this.registeredPreferences_[name]; 296 if (!pref.action) 297 return; 298 299 delete pref.action; 300 delete pref.type; 301 delete pref.value; 302 303 var event = new Event(name); 304 event.value = pref.orig; 305 event.value.uncommitted = true; 306 this.dispatchEvent(event); 307 } 308 }; 309 310 /** 311 * Callback for fetchPrefs method. 312 * @param {object} dict Map of fetched property values. 313 */ 314 Preferences.prefsFetchedCallback = function(dict) { 315 Preferences.getInstance().flattenMapAndDispatchEvent_('', dict); 316 }; 317 318 /** 319 * Callback for observePrefs method. 320 * @param {array} notification An array defining changed preference values. 321 * notification[0] contains name of the change preference while its new value 322 * is stored in notification[1]. 323 */ 324 Preferences.prefsChangedCallback = function(notification) { 325 var event = new Event(notification[0]); 326 event.value = notification[1]; 327 prefs = Preferences.getInstance(); 328 prefs.registeredPreferences_[notification[0]] = {orig: notification[1]}; 329 prefs.dispatchEvent(event); 330 }; 331 332 // Export 333 return { 334 Preferences: Preferences 335 }; 336 337}); 338