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 = {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