root/chrome/browser/ui/webui/chromeos/salsa_ui.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. RevertPreferences
  2. WhitelistIndex
  3. SetPreferenceValue
  4. BackupPreferenceValue

// 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();
}

/* [<][>][^][v][top][bottom][index][help] */