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::kFlingMaxCancelToDownTimeInMs, 29 prefs::kFlingMaxTapGapTimeInMs, 30 prefs::kLongPressTimeInSeconds, 31 prefs::kLongPressTimeInSeconds, 32 prefs::kMaxSecondsBetweenDoubleClick, 33 prefs::kMaxSeparationForGestureTouchesInPixels, 34 prefs::kMaxSwipeDeviationRatio, 35 prefs::kMaxTouchDownDurationInSecondsForClick, 36 prefs::kMaxTouchMoveInPixelsForClick, 37 prefs::kMaxDistanceBetweenTapsForDoubleTap, 38 prefs::kMaxDistanceForTwoFingerTapInPixels, 39 prefs::kMinDistanceForPinchScrollInPixels, 40 prefs::kMinFlickSpeedSquared, 41 prefs::kMinPinchUpdateDistanceInPixels, 42 prefs::kMinRailBreakVelocity, 43 prefs::kMinScrollDeltaSquared, 44 prefs::kMinSwipeSpeed, 45 prefs::kMinTouchDownDurationInSecondsForClick, 46 prefs::kPointsBufferedForVelocity, 47 prefs::kRailBreakProportion, 48 prefs::kRailStartProportion, 49 prefs::kFlingAccelerationCurveCoefficient0, 50 prefs::kFlingAccelerationCurveCoefficient1, 51 prefs::kFlingAccelerationCurveCoefficient2, 52 prefs::kFlingAccelerationCurveCoefficient3, 53 prefs::kFlingVelocityCap, 54 prefs::kTabScrubActivationDelayInMS, 55 prefs::kOverscrollHorizontalThresholdComplete, 56 prefs::kOverscrollVerticalThresholdComplete, 57 prefs::kOverscrollMinimumThresholdStart, 58 prefs::kOverscrollVerticalThresholdStart, 59 prefs::kOverscrollHorizontalResistThreshold, 60 prefs::kOverscrollVerticalResistThreshold, 61 prefs::kImmersiveModeRevealDelayMs, 62 prefs::kImmersiveModeRevealXThresholdPixels, 63 prefs::kFlingCurveTouchscreenAlpha, 64 prefs::kFlingCurveTouchscreenBeta, 65 prefs::kFlingCurveTouchscreenGamma, 66 prefs::kFlingCurveTouchpadAlpha, 67 prefs::kFlingCurveTouchpadBeta, 68 prefs::kFlingCurveTouchpadGamma, 69 }; 70 71 void RevertPreferences(PrefService* prefs, 72 std::map<int, const base::Value*>* vals) { 73 std::map<int, const base::Value*>::const_iterator it; 74 for (it = vals->begin(); it != vals->end(); ++it) { 75 if (!prefs->FindPreference(kWhitelist[it->first])) 76 continue; 77 78 if (!it->second) { 79 prefs->ClearPref(kWhitelist[it->first]); 80 } else { 81 prefs->Set(kWhitelist[it->first], *it->second); 82 delete it->second; 83 } 84 } 85 } 86 87 } // namespace 88 89 SalsaUI::SalsaUI(content::WebUI* web_ui) 90 : content::WebUIController(web_ui) { 91 // Set up the chrome://salsa source. 92 content::WebUIDataSource* html_source = 93 content::WebUIDataSource::Create(chrome::kChromeUISalsaHost); 94 95 // Register callback handlers. 96 web_ui->RegisterMessageCallback( 97 "salsaSetPreferenceValue", 98 base::Bind(&SalsaUI::SetPreferenceValue, 99 base::Unretained(this))); 100 web_ui->RegisterMessageCallback( 101 "salsaBackupPreferenceValue", 102 base::Bind(&SalsaUI::BackupPreferenceValue, 103 base::Unretained(this))); 104 105 // Add required resources. 106 html_source->AddResourcePath("salsa.css", IDR_SALSA_CSS); 107 html_source->AddResourcePath("salsa.js", IDR_SALSA_JS); 108 html_source->SetDefaultResource(IDR_SALSA_HTML); 109 110 Profile* profile = Profile::FromWebUI(web_ui); 111 content::WebUIDataSource::Add(profile, html_source); 112 } 113 114 SalsaUI::~SalsaUI() { 115 std::map<int, const base::Value*>* values_to_revert = 116 new std::map<int, const base::Value*>; 117 values_to_revert->swap(orig_values_); 118 119 Profile* profile = Profile::FromWebUI(web_ui()); 120 PrefService* prefs = profile->GetPrefs(); 121 122 content::BrowserThread::PostTask( 123 content::BrowserThread::UI, 124 FROM_HERE, 125 base::Bind(&RevertPreferences, prefs, base::Owned(values_to_revert)) 126 ); 127 } 128 129 int SalsaUI::WhitelistIndex(const char* key) const { 130 if (!key) 131 return -1; 132 133 int len = arraysize(kWhitelist); 134 for (int i = 0; i < len; ++i) { 135 if (!strcmp(key, kWhitelist[i])) 136 return i; 137 } 138 return -1; 139 } 140 141 void SalsaUI::SetPreferenceValue(const base::ListValue* args) { 142 std::string pref_name; 143 const base::Value* value; 144 if (!args->GetString(0, &pref_name) || !args->Get(1, &value)) 145 return; 146 147 int index = WhitelistIndex(pref_name.c_str()); 148 if (index < 0) 149 return; 150 151 Profile* profile = Profile::FromWebUI(web_ui()); 152 PrefService* prefs = profile->GetPrefs(); 153 const PrefService::Preference* pref = 154 prefs->FindPreference(kWhitelist[index]); 155 156 if (pref->GetType() == value->GetType()) { 157 prefs->Set(kWhitelist[index], *value); 158 } else if (pref->GetType() == base::Value::TYPE_DOUBLE && 159 value->GetType() == base::Value::TYPE_INTEGER) { 160 int int_val; 161 if (!value->GetAsInteger(&int_val)) 162 return; 163 base::FundamentalValue double_val(static_cast<double>(int_val)); 164 prefs->Set(kWhitelist[index], double_val); 165 } 166 } 167 168 void SalsaUI::BackupPreferenceValue(const base::ListValue* args) { 169 std::string pref_name; 170 if (!args->GetString(0, &pref_name)) 171 return; 172 173 int index = WhitelistIndex(pref_name.c_str()); 174 if (index < 0) 175 return; 176 177 Profile* profile = Profile::FromWebUI(web_ui()); 178 PrefService* prefs = profile->GetPrefs(); 179 const PrefService::Preference* pref = 180 prefs->FindPreference(kWhitelist[index]); 181 182 if (!pref) 183 return; 184 185 // Get our own copy of the user defined value or NULL if they are using the 186 // default. You have to make a copy since they'll be used in the destructor 187 // to restore the values and we need to make sure they're still around. 188 orig_values_[index] = 189 pref->IsDefaultValue() ? NULL : pref->GetValue()->DeepCopy(); 190 } 191