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