// 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
};
});