// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. cr.define('options', function() { ///////////////////////////////////////////////////////////////////////////// // Preferences class: /** * Preferences class manages access to Chrome profile preferences. * @constructor */ function Preferences() { // Map of registered preferences. this.registeredPreferences_ = {}; } cr.addSingletonGetter(Preferences); /** * Sets a Boolean preference and signals its new value. * @param {string} name Preference name. * @param {boolean} value New preference value. * @param {boolean} commit Whether to commit the change to Chrome. * @param {string} metric User metrics identifier. */ Preferences.setBooleanPref = function(name, value, commit, metric) { if (!commit) { Preferences.getInstance().setPrefNoCommit_(name, 'bool', Boolean(value)); return; } var argumentList = [name, Boolean(value)]; if (metric != undefined) argumentList.push(metric); chrome.send('setBooleanPref', argumentList); }; /** * Sets an integer preference and signals its new value. * @param {string} name Preference name. * @param {number} value New preference value. * @param {boolean} commit Whether to commit the change to Chrome. * @param {string} metric User metrics identifier. */ Preferences.setIntegerPref = function(name, value, commit, metric) { if (!commit) { Preferences.getInstance().setPrefNoCommit_(name, 'int', Number(value)); return; } var argumentList = [name, Number(value)]; if (metric != undefined) argumentList.push(metric); chrome.send('setIntegerPref', argumentList); }; /** * Sets a double-valued preference and signals its new value. * @param {string} name Preference name. * @param {number} value New preference value. * @param {boolean} commit Whether to commit the change to Chrome. * @param {string} metric User metrics identifier. */ Preferences.setDoublePref = function(name, value, commit, metric) { if (!commit) { Preferences.getInstance().setPrefNoCommit_(name, 'double', Number(value)); return; } var argumentList = [name, Number(value)]; if (metric != undefined) argumentList.push(metric); chrome.send('setDoublePref', argumentList); }; /** * Sets a string preference and signals its new value. * @param {string} name Preference name. * @param {string} value New preference value. * @param {boolean} commit Whether to commit the change to Chrome. * @param {string} metric User metrics identifier. */ Preferences.setStringPref = function(name, value, commit, metric) { if (!commit) { Preferences.getInstance().setPrefNoCommit_(name, 'string', String(value)); return; } var argumentList = [name, String(value)]; if (metric != undefined) argumentList.push(metric); chrome.send('setStringPref', argumentList); }; /** * Sets a string preference that represents a URL and signals its new value. * The value will be fixed to be a valid URL when it gets committed to Chrome. * @param {string} name Preference name. * @param {string} value New preference value. * @param {boolean} commit Whether to commit the change to Chrome. * @param {string} metric User metrics identifier. */ Preferences.setURLPref = function(name, value, commit, metric) { if (!commit) { Preferences.getInstance().setPrefNoCommit_(name, 'url', String(value)); return; } var argumentList = [name, String(value)]; if (metric != undefined) argumentList.push(metric); chrome.send('setURLPref', argumentList); }; /** * Sets a JSON list preference and signals its new value. * @param {string} name Preference name. * @param {Array} value New preference value. * @param {boolean} commit Whether to commit the change to Chrome. * @param {string} metric User metrics identifier. */ Preferences.setListPref = function(name, value, commit, metric) { if (!commit) { Preferences.getInstance().setPrefNoCommit_(name, 'list', value); return; } var argumentList = [name, JSON.stringify(value)]; if (metric != undefined) argumentList.push(metric); chrome.send('setListPref', argumentList); }; /** * Clears the user setting for a preference and signals its new effective * value. * @param {string} name Preference name. * @param {boolean} commit Whether to commit the change to Chrome. * @param {string} metric User metrics identifier. */ Preferences.clearPref = function(name, commit, metric) { if (!commit) { Preferences.getInstance().clearPrefNoCommit_(name); return; } var argumentList = [name]; if (metric != undefined) argumentList.push(metric); chrome.send('clearPref', argumentList); }; Preferences.prototype = { __proto__: cr.EventTarget.prototype, /** * Adds an event listener to the target. * @param {string} type The name of the event. * @param {!Function|{handleEvent:Function}} handler The handler for the * event. This is called when the event is dispatched. */ addEventListener: function(type, handler) { cr.EventTarget.prototype.addEventListener.call(this, type, handler); if (!(type in this.registeredPreferences_)) this.registeredPreferences_[type] = {}; }, /** * Initializes preference reading and change notifications. */ initialize: function() { var params1 = ['Preferences.prefsFetchedCallback']; var params2 = ['Preferences.prefsChangedCallback']; for (var prefName in this.registeredPreferences_) { params1.push(prefName); params2.push(prefName); } chrome.send('fetchPrefs', params1); chrome.send('observePrefs', params2); }, /** * Helper function for flattening of dictionary passed via fetchPrefs * callback. * @param {string} prefix Preference name prefix. * @param {object} dict Map with preference values. * @private */ flattenMapAndDispatchEvent_: function(prefix, dict) { for (var prefName in dict) { if (typeof dict[prefName] == 'object' && !this.registeredPreferences_[prefix + prefName]) { this.flattenMapAndDispatchEvent_(prefix + prefName + '.', dict[prefName]); } else { var event = new Event(prefix + prefName); this.registeredPreferences_[prefix + prefName].orig = dict[prefName]; event.value = dict[prefName]; this.dispatchEvent(event); } } }, /** * Sets a preference and signals its new value. The change is propagated * throughout the UI code but is not committed to Chrome yet. The new value * and its data type are stored so that commitPref() can later be used to * invoke the appropriate set*Pref() method and actually commit the change. * @param {string} name Preference name. * @param {string} type Preference data type. * @param {*} value New preference value. * @private */ setPrefNoCommit_: function(name, type, value) { var pref = this.registeredPreferences_[name]; pref.action = 'set'; pref.type = type; pref.value = value; var event = new Event(name); // Decorate pref value as CoreOptionsHandler::CreateValueForPref() does. event.value = { value: value, recommendedValue: pref.orig.recommendedValue, disabled: pref.orig.disabled, uncommitted: true, }; this.dispatchEvent(event); }, /** * Clears a preference and signals its new value. The change is propagated * throughout the UI code but is not committed to Chrome yet. * @param {string} name Preference name. * @private */ clearPrefNoCommit_: function(name) { var pref = this.registeredPreferences_[name]; pref.action = 'clear'; delete pref.type; delete pref.value; var event = new Event(name); // Decorate pref value as CoreOptionsHandler::CreateValueForPref() does. event.value = { value: pref.orig.recommendedValue, controlledBy: 'recommended', recommendedValue: pref.orig.recommendedValue, disabled: pref.orig.disabled, uncommitted: true, }; this.dispatchEvent(event); }, /** * Commits a preference change to Chrome and signals the new preference * value. Does nothing if there is no uncommitted change. * @param {string} name Preference name. * @param {string} metric User metrics identifier. */ commitPref: function(name, metric) { var pref = this.registeredPreferences_[name]; switch (pref.action) { case 'set': switch (pref.type) { case 'bool': Preferences.setBooleanPref(name, pref.value, true, metric); break; case 'int': Preferences.setIntegerPref(name, pref.value, true, metric); break; case 'double': Preferences.setDoublePref(name, pref.value, true, metric); break; case 'string': Preferences.setStringPref(name, pref.value, true, metric); break; case 'url': Preferences.setURLPref(name, pref.value, true, metric); break; case 'list': Preferences.setListPref(name, pref.value, true, metric); break; } break; case 'clear': Preferences.clearPref(name, true, metric); break; } delete pref.action; delete pref.type; delete pref.value; }, /** * Rolls back a preference change and signals the original preference value. * Does nothing if there is no uncommitted change. * @param {string} name Preference name. */ rollbackPref: function(name) { var pref = this.registeredPreferences_[name]; if (!pref.action) return; delete pref.action; delete pref.type; delete pref.value; var event = new Event(name); event.value = pref.orig; event.value.uncommitted = true; this.dispatchEvent(event); } }; /** * Callback for fetchPrefs method. * @param {object} dict Map of fetched property values. */ Preferences.prefsFetchedCallback = function(dict) { Preferences.getInstance().flattenMapAndDispatchEvent_('', dict); }; /** * Callback for observePrefs method. * @param {array} notification An array defining changed preference values. * notification[0] contains name of the change preference while its new value * is stored in notification[1]. */ Preferences.prefsChangedCallback = function(notification) { var event = new Event(notification[0]); event.value = notification[1]; prefs = Preferences.getInstance(); prefs.registeredPreferences_[notification[0]] = {orig: notification[1]}; prefs.dispatchEvent(event); }; // Export return { Preferences: Preferences }; });