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