• 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   */
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