• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   * @extends {cr.EventTarget}
14   */
15  function Preferences() {
16    // Map of registered preferences.
17    this.registeredPreferences_ = {};
18  }
19
20  cr.addSingletonGetter(Preferences);
21
22  /**
23   * Sets a Boolean preference and signals its new value.
24   * @param {string} name Preference name.
25   * @param {boolean} value New preference value.
26   * @param {boolean} commit Whether to commit the change to Chrome.
27   * @param {string=} opt_metric User metrics identifier.
28   */
29  Preferences.setBooleanPref = function(name, value, commit, opt_metric) {
30    if (!commit) {
31      Preferences.getInstance().setPrefNoCommit_(name, 'bool', Boolean(value));
32      return;
33    }
34
35    var argumentList = [name, Boolean(value)];
36    if (opt_metric != undefined) argumentList.push(opt_metric);
37    chrome.send('setBooleanPref', argumentList);
38  };
39
40  /**
41   * Sets an integer preference and signals its new value.
42   * @param {string} name Preference name.
43   * @param {number} value New preference value.
44   * @param {boolean} commit Whether to commit the change to Chrome.
45   * @param {string} metric User metrics identifier.
46   */
47  Preferences.setIntegerPref = function(name, value, commit, metric) {
48    if (!commit) {
49      Preferences.getInstance().setPrefNoCommit_(name, 'int', Number(value));
50      return;
51    }
52
53    var argumentList = [name, Number(value)];
54    if (metric != undefined) argumentList.push(metric);
55    chrome.send('setIntegerPref', argumentList);
56  };
57
58  /**
59   * Sets a double-valued preference and signals its new value.
60   * @param {string} name Preference name.
61   * @param {number} value New preference value.
62   * @param {boolean} commit Whether to commit the change to Chrome.
63   * @param {string} metric User metrics identifier.
64   */
65  Preferences.setDoublePref = function(name, value, commit, metric) {
66    if (!commit) {
67      Preferences.getInstance().setPrefNoCommit_(name, 'double', Number(value));
68      return;
69    }
70
71    var argumentList = [name, Number(value)];
72    if (metric != undefined) argumentList.push(metric);
73    chrome.send('setDoublePref', argumentList);
74  };
75
76  /**
77   * Sets a string preference and signals its new value.
78   * @param {string} name Preference name.
79   * @param {string} value New preference value.
80   * @param {boolean} commit Whether to commit the change to Chrome.
81   * @param {string} metric User metrics identifier.
82   */
83  Preferences.setStringPref = function(name, value, commit, metric) {
84    if (!commit) {
85      Preferences.getInstance().setPrefNoCommit_(name, 'string', String(value));
86      return;
87    }
88
89    var argumentList = [name, String(value)];
90    if (metric != undefined) argumentList.push(metric);
91    chrome.send('setStringPref', argumentList);
92  };
93
94  /**
95   * Sets a string preference that represents a URL and signals its new value.
96   * The value will be fixed to be a valid URL when it gets committed to Chrome.
97   * @param {string} name Preference name.
98   * @param {string} value New preference value.
99   * @param {boolean} commit Whether to commit the change to Chrome.
100   * @param {string} metric User metrics identifier.
101   */
102  Preferences.setURLPref = function(name, value, commit, metric) {
103    if (!commit) {
104      Preferences.getInstance().setPrefNoCommit_(name, 'url', String(value));
105      return;
106    }
107
108    var argumentList = [name, String(value)];
109    if (metric != undefined) argumentList.push(metric);
110    chrome.send('setURLPref', argumentList);
111  };
112
113  /**
114   * Sets a JSON list preference and signals its new value.
115   * @param {string} name Preference name.
116   * @param {Array} value New preference value.
117   * @param {boolean} commit Whether to commit the change to Chrome.
118   * @param {string} metric User metrics identifier.
119   */
120  Preferences.setListPref = function(name, value, commit, metric) {
121    if (!commit) {
122      Preferences.getInstance().setPrefNoCommit_(name, 'list', value);
123      return;
124    }
125
126    var argumentList = [name, JSON.stringify(value)];
127    if (metric != undefined) argumentList.push(metric);
128    chrome.send('setListPref', argumentList);
129  };
130
131  /**
132   * Clears the user setting for a preference and signals its new effective
133   * value.
134   * @param {string} name Preference name.
135   * @param {boolean} commit Whether to commit the change to Chrome.
136   * @param {string=} opt_metric User metrics identifier.
137   */
138  Preferences.clearPref = function(name, commit, opt_metric) {
139    if (!commit) {
140      Preferences.getInstance().clearPrefNoCommit_(name);
141      return;
142    }
143
144    var argumentList = [name];
145    if (opt_metric != undefined) argumentList.push(opt_metric);
146    chrome.send('clearPref', argumentList);
147  };
148
149  Preferences.prototype = {
150    __proto__: cr.EventTarget.prototype,
151
152    /**
153     * Adds an event listener to the target.
154     * @param {string} type The name of the event.
155     * @param {!Function|{handleEvent:Function}} handler The handler for the
156     *     event. This is called when the event is dispatched.
157     */
158    addEventListener: function(type, handler) {
159      cr.EventTarget.prototype.addEventListener.call(this, type, handler);
160      if (!(type in this.registeredPreferences_))
161        this.registeredPreferences_[type] = {};
162    },
163
164    /**
165     * Initializes preference reading and change notifications.
166     */
167    initialize: function() {
168      var params1 = ['Preferences.prefsFetchedCallback'];
169      var params2 = ['Preferences.prefsChangedCallback'];
170      for (var prefName in this.registeredPreferences_) {
171        params1.push(prefName);
172        params2.push(prefName);
173      }
174      chrome.send('fetchPrefs', params1);
175      chrome.send('observePrefs', params2);
176    },
177
178    /**
179     * Helper function for flattening of dictionary passed via fetchPrefs
180     * callback.
181     * @param {string} prefix Preference name prefix.
182     * @param {Object} dict Map with preference values.
183     * @private
184     */
185    flattenMapAndDispatchEvent_: function(prefix, dict) {
186      for (var prefName in dict) {
187        var value = dict[prefName];
188        if (typeof value == 'object' &&
189            !this.registeredPreferences_[prefix + prefName]) {
190          this.flattenMapAndDispatchEvent_(prefix + prefName + '.', value);
191        } else if (value) {
192          var event = new Event(prefix + prefName);
193          this.registeredPreferences_[prefix + prefName].orig = value;
194          event.value = value;
195          this.dispatchEvent(event);
196        }
197      }
198    },
199
200    /**
201     * Sets a preference and signals its new value. The change is propagated
202     * throughout the UI code but is not committed to Chrome yet. The new value
203     * and its data type are stored so that commitPref() can later be used to
204     * invoke the appropriate set*Pref() method and actually commit the change.
205     * @param {string} name Preference name.
206     * @param {string} type Preference data type.
207     * @param {*} value New preference value.
208     * @private
209     */
210    setPrefNoCommit_: function(name, type, value) {
211      var pref = this.registeredPreferences_[name];
212      pref.action = 'set';
213      pref.type = type;
214      pref.value = value;
215
216      var event = new Event(name);
217      // Decorate pref value as CoreOptionsHandler::CreateValueForPref() does.
218      event.value = {value: value, uncommitted: true};
219      if (pref.orig) {
220        event.value.recommendedValue = pref.orig.recommendedValue;
221        event.value.disabled = pref.orig.disabled;
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 = {controlledBy: 'recommended', uncommitted: true};
241      if (pref.orig) {
242        event.value.value = pref.orig.recommendedValue;
243        event.value.recommendedValue = pref.orig.recommendedValue;
244        event.value.disabled = pref.orig.disabled;
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
322   *     value is stored in notification[1].
323   */
324  Preferences.prefsChangedCallback = function(notification) {
325    var event = new Event(notification[0]);
326    event.value = notification[1];
327    var prefs = Preferences.getInstance();
328    prefs.registeredPreferences_[notification[0]] = {orig: notification[1]};
329    if (event.value)
330      prefs.dispatchEvent(event);
331  };
332
333  // Export
334  return {
335    Preferences: Preferences
336  };
337
338});
339