Home | History | Annotate | Download | only in chromeos
      1 // Copyright 2013 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 #include "chrome/browser/ui/webui/chromeos/salsa_ui.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/prefs/pref_service.h"
     10 #include "base/values.h"
     11 #include "chrome/browser/browser_process.h"
     12 #include "chrome/browser/profiles/profile.h"
     13 #include "chrome/common/pref_names.h"
     14 #include "chrome/common/url_constants.h"
     15 #include "content/public/browser/browser_thread.h"
     16 #include "content/public/browser/web_ui.h"
     17 #include "content/public/browser/web_ui_data_source.h"
     18 #include "grit/browser_resources.h"
     19 
     20 // Whitelist of which preferences are possible targets for Salsa treatments.
     21 // If new preferences are added and they are to be used in an experiment, then
     22 // they must be added to this list as well to keep chrome://salsa from
     23 // changing arbitrary values.
     24 
     25 namespace {
     26 
     27 const char* kWhitelist[] = {
     28   prefs::kMaxSeparationForGestureTouchesInPixels,
     29   prefs::kTabScrubActivationDelayInMS,
     30   prefs::kOverscrollHorizontalThresholdComplete,
     31   prefs::kOverscrollVerticalThresholdComplete,
     32   prefs::kOverscrollMinimumThresholdStart,
     33   prefs::kOverscrollVerticalThresholdStart,
     34   prefs::kOverscrollHorizontalResistThreshold,
     35   prefs::kOverscrollVerticalResistThreshold,
     36 };
     37 
     38 void RevertPreferences(PrefService* prefs,
     39                        std::map<int, const base::Value*>* vals) {
     40   std::map<int, const base::Value*>::const_iterator it;
     41   for (it = vals->begin(); it != vals->end(); ++it) {
     42     if (!prefs->FindPreference(kWhitelist[it->first]))
     43       continue;
     44 
     45     if (!it->second) {
     46       prefs->ClearPref(kWhitelist[it->first]);
     47     } else {
     48       prefs->Set(kWhitelist[it->first], *it->second);
     49       delete it->second;
     50     }
     51   }
     52 }
     53 
     54 } // namespace
     55 
     56 SalsaUI::SalsaUI(content::WebUI* web_ui)
     57     : content::WebUIController(web_ui) {
     58   // Set up the chrome://salsa source.
     59   content::WebUIDataSource* html_source =
     60       content::WebUIDataSource::Create(chrome::kChromeUISalsaHost);
     61 
     62   // Register callback handlers.
     63   web_ui->RegisterMessageCallback(
     64       "salsaSetPreferenceValue",
     65       base::Bind(&SalsaUI::SetPreferenceValue,
     66                  base::Unretained(this)));
     67   web_ui->RegisterMessageCallback(
     68       "salsaBackupPreferenceValue",
     69       base::Bind(&SalsaUI::BackupPreferenceValue,
     70                  base::Unretained(this)));
     71 
     72   // Add required resources.
     73   html_source->AddResourcePath("salsa.css", IDR_SALSA_CSS);
     74   html_source->AddResourcePath("salsa.js", IDR_SALSA_JS);
     75   html_source->SetDefaultResource(IDR_SALSA_HTML);
     76 
     77   Profile* profile = Profile::FromWebUI(web_ui);
     78   content::WebUIDataSource::Add(profile, html_source);
     79 }
     80 
     81 SalsaUI::~SalsaUI() {
     82   std::map<int, const base::Value*>* values_to_revert =
     83       new std::map<int, const base::Value*>;
     84   values_to_revert->swap(orig_values_);
     85 
     86   Profile* profile = Profile::FromWebUI(web_ui());
     87   PrefService* prefs = profile->GetPrefs();
     88 
     89   content::BrowserThread::PostTask(
     90       content::BrowserThread::UI,
     91       FROM_HERE,
     92       base::Bind(&RevertPreferences, prefs, base::Owned(values_to_revert))
     93     );
     94 }
     95 
     96 int SalsaUI::WhitelistIndex(const char* key) const {
     97   if (!key)
     98     return -1;
     99 
    100   int len = arraysize(kWhitelist);
    101   for (int i = 0; i < len; ++i) {
    102     if (!strcmp(key, kWhitelist[i]))
    103       return i;
    104   }
    105   return -1;
    106 }
    107 
    108 void SalsaUI::SetPreferenceValue(const base::ListValue* args) {
    109   std::string pref_name;
    110   const base::Value* value;
    111   if (!args->GetString(0, &pref_name) || !args->Get(1, &value))
    112     return;
    113 
    114   int index = WhitelistIndex(pref_name.c_str());
    115   if (index < 0)
    116     return;
    117 
    118   Profile* profile = Profile::FromWebUI(web_ui());
    119   PrefService* prefs = profile->GetPrefs();
    120   const PrefService::Preference* pref =
    121       prefs->FindPreference(kWhitelist[index]);
    122 
    123   if (pref->GetType() == value->GetType()) {
    124     prefs->Set(kWhitelist[index], *value);
    125   } else if (pref->GetType() == base::Value::TYPE_DOUBLE &&
    126              value->GetType() == base::Value::TYPE_INTEGER) {
    127     int int_val;
    128     if (!value->GetAsInteger(&int_val))
    129       return;
    130     base::FundamentalValue double_val(static_cast<double>(int_val));
    131     prefs->Set(kWhitelist[index], double_val);
    132   }
    133 }
    134 
    135 void SalsaUI::BackupPreferenceValue(const base::ListValue* args) {
    136   std::string pref_name;
    137   if (!args->GetString(0, &pref_name))
    138     return;
    139 
    140   int index = WhitelistIndex(pref_name.c_str());
    141   if (index < 0)
    142     return;
    143 
    144   Profile* profile = Profile::FromWebUI(web_ui());
    145   PrefService* prefs = profile->GetPrefs();
    146   const PrefService::Preference* pref =
    147       prefs->FindPreference(kWhitelist[index]);
    148 
    149   if (!pref)
    150     return;
    151 
    152   // Get our own copy of the user defined value or NULL if they are using the
    153   // default. You have to make a copy since they'll be used in the destructor
    154   // to restore the values and we need to make sure they're still around.
    155   orig_values_[index] =
    156       pref->IsDefaultValue() ? NULL : pref->GetValue()->DeepCopy();
    157 }
    158