blob: 6b622baeaacb1ae0cf363cb8584b7018fdeb0cba [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/webui/chromeos/salsa_ui.h"
#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
#include "base/prefs/pref_service.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "grit/browser_resources.h"
// Whitelist of which preferences are possible targets for Salsa treatments.
// If new preferences are added and they are to be used in an experiment, then
// they must be added to this list as well to keep chrome://salsa from
// changing arbitrary values.
namespace {
const char* kWhitelist[] = {
prefs::kFlingMaxCancelToDownTimeInMs,
prefs::kFlingMaxTapGapTimeInMs,
prefs::kLongPressTimeInSeconds,
prefs::kLongPressTimeInSeconds,
prefs::kMaxSecondsBetweenDoubleClick,
prefs::kMaxSeparationForGestureTouchesInPixels,
prefs::kMaxSwipeDeviationRatio,
prefs::kMaxTouchDownDurationInSecondsForClick,
prefs::kMaxTouchMoveInPixelsForClick,
prefs::kMaxDistanceBetweenTapsForDoubleTap,
prefs::kMaxDistanceForTwoFingerTapInPixels,
prefs::kMinDistanceForPinchScrollInPixels,
prefs::kMinFlickSpeedSquared,
prefs::kMinPinchUpdateDistanceInPixels,
prefs::kMinRailBreakVelocity,
prefs::kMinScrollDeltaSquared,
prefs::kMinSwipeSpeed,
prefs::kMinTouchDownDurationInSecondsForClick,
prefs::kPointsBufferedForVelocity,
prefs::kRailBreakProportion,
prefs::kRailStartProportion,
prefs::kFlingAccelerationCurveCoefficient0,
prefs::kFlingAccelerationCurveCoefficient1,
prefs::kFlingAccelerationCurveCoefficient2,
prefs::kFlingAccelerationCurveCoefficient3,
prefs::kFlingVelocityCap,
prefs::kTabScrubActivationDelayInMS,
prefs::kOverscrollHorizontalThresholdComplete,
prefs::kOverscrollVerticalThresholdComplete,
prefs::kOverscrollMinimumThresholdStart,
prefs::kOverscrollVerticalThresholdStart,
prefs::kOverscrollHorizontalResistThreshold,
prefs::kOverscrollVerticalResistThreshold,
prefs::kFlingCurveTouchscreenAlpha,
prefs::kFlingCurveTouchscreenBeta,
prefs::kFlingCurveTouchscreenGamma,
prefs::kFlingCurveTouchpadAlpha,
prefs::kFlingCurveTouchpadBeta,
prefs::kFlingCurveTouchpadGamma,
};
void RevertPreferences(PrefService* prefs,
std::map<int, const base::Value*>* vals) {
std::map<int, const base::Value*>::const_iterator it;
for (it = vals->begin(); it != vals->end(); ++it) {
if (!prefs->FindPreference(kWhitelist[it->first]))
continue;
if (!it->second) {
prefs->ClearPref(kWhitelist[it->first]);
} else {
prefs->Set(kWhitelist[it->first], *it->second);
delete it->second;
}
}
}
} // namespace
SalsaUI::SalsaUI(content::WebUI* web_ui)
: content::WebUIController(web_ui) {
// Set up the chrome://salsa source.
content::WebUIDataSource* html_source =
content::WebUIDataSource::Create(chrome::kChromeUISalsaHost);
// Register callback handlers.
web_ui->RegisterMessageCallback(
"salsaSetPreferenceValue",
base::Bind(&SalsaUI::SetPreferenceValue,
base::Unretained(this)));
web_ui->RegisterMessageCallback(
"salsaBackupPreferenceValue",
base::Bind(&SalsaUI::BackupPreferenceValue,
base::Unretained(this)));
// Add required resources.
html_source->AddResourcePath("salsa.css", IDR_SALSA_CSS);
html_source->AddResourcePath("salsa.js", IDR_SALSA_JS);
html_source->SetDefaultResource(IDR_SALSA_HTML);
Profile* profile = Profile::FromWebUI(web_ui);
content::WebUIDataSource::Add(profile, html_source);
}
SalsaUI::~SalsaUI() {
std::map<int, const base::Value*>* values_to_revert =
new std::map<int, const base::Value*>;
values_to_revert->swap(orig_values_);
Profile* profile = Profile::FromWebUI(web_ui());
PrefService* prefs = profile->GetPrefs();
content::BrowserThread::PostTask(
content::BrowserThread::UI,
FROM_HERE,
base::Bind(&RevertPreferences, prefs, base::Owned(values_to_revert))
);
}
int SalsaUI::WhitelistIndex(const char* key) const {
if (!key)
return -1;
int len = arraysize(kWhitelist);
for (int i = 0; i < len; ++i) {
if (!strcmp(key, kWhitelist[i]))
return i;
}
return -1;
}
void SalsaUI::SetPreferenceValue(const base::ListValue* args) {
std::string pref_name;
const base::Value* value;
if (!args->GetString(0, &pref_name) || !args->Get(1, &value))
return;
int index = WhitelistIndex(pref_name.c_str());
if (index < 0)
return;
Profile* profile = Profile::FromWebUI(web_ui());
PrefService* prefs = profile->GetPrefs();
const PrefService::Preference* pref =
prefs->FindPreference(kWhitelist[index]);
if (pref->GetType() == value->GetType()) {
prefs->Set(kWhitelist[index], *value);
} else if (pref->GetType() == base::Value::TYPE_DOUBLE &&
value->GetType() == base::Value::TYPE_INTEGER) {
int int_val;
if (!value->GetAsInteger(&int_val))
return;
base::FundamentalValue double_val(static_cast<double>(int_val));
prefs->Set(kWhitelist[index], double_val);
}
}
void SalsaUI::BackupPreferenceValue(const base::ListValue* args) {
std::string pref_name;
if (!args->GetString(0, &pref_name))
return;
int index = WhitelistIndex(pref_name.c_str());
if (index < 0)
return;
Profile* profile = Profile::FromWebUI(web_ui());
PrefService* prefs = profile->GetPrefs();
const PrefService::Preference* pref =
prefs->FindPreference(kWhitelist[index]);
if (!pref)
return;
// Get our own copy of the user defined value or NULL if they are using the
// default. You have to make a copy since they'll be used in the destructor
// to restore the values and we need to make sure they're still around.
orig_values_[index] =
pref->IsDefaultValue() ? NULL : pref->GetValue()->DeepCopy();
}