This source file includes following definitions.
- AllowMetricsReportingChange
- InitializeHandler
- InitializePage
- GetLocalizedValues
- GetStaticLocalizedValues
- Uninitialize
- OnPreferenceChanged
- RegisterMessages
- HandleInitialize
- OnFinishedLoading
- FetchPref
- ObservePref
- StopObservingPref
- SetPref
- ClearPref
- ProcessUserMetric
- NotifyPrefChanged
- DispatchPrefChangeNotification
- CreateValueForPref
- FindServiceForPref
- HandleFetchPrefs
- HandleObservePrefs
- HandleSetBooleanPref
- HandleSetIntegerPref
- HandleSetDoublePref
- HandleSetStringPref
- HandleSetURLPref
- HandleSetListPref
- HandleSetPref
- HandleClearPref
- HandleUserMetricsAction
- HandleDisableExtension
- UpdateClearPluginLSOData
- UpdatePepperFlashSettingsEnabled
#include "chrome/browser/ui/webui/options/core_options_handler.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/json/json_reader.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/options/options_util.h"
#include "chrome/common/net/url_fixer_upper.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_ui.h"
#include "extensions/browser/extension_pref_value_map.h"
#include "extensions/browser/extension_pref_value_map_factory.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/extension.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"
using base::UserMetricsAction;
namespace options {
namespace {
bool AllowMetricsReportingChange(const base::Value* to_value) {
bool enable;
if (!to_value->GetAsBoolean(&enable)) {
NOTREACHED();
return false;
}
return enable == OptionsUtil::ResolveMetricsReportingEnabled(enable);
}
}
CoreOptionsHandler::CoreOptionsHandler()
: handlers_host_(NULL) {
}
CoreOptionsHandler::~CoreOptionsHandler() {}
void CoreOptionsHandler::InitializeHandler() {
Profile* profile = Profile::FromWebUI(web_ui());
plugin_status_pref_setter_.Init(
profile,
base::Bind(&CoreOptionsHandler::OnPreferenceChanged,
base::Unretained(this),
profile->GetPrefs()));
pref_change_filters_[prefs::kMetricsReportingEnabled] =
base::Bind(&AllowMetricsReportingChange);
}
void CoreOptionsHandler::InitializePage() {
UpdateClearPluginLSOData();
UpdatePepperFlashSettingsEnabled();
}
void CoreOptionsHandler::GetLocalizedValues(
base::DictionaryValue* localized_strings) {
GetStaticLocalizedValues(localized_strings);
}
void CoreOptionsHandler::GetStaticLocalizedValues(
base::DictionaryValue* localized_strings) {
DCHECK(localized_strings);
localized_strings->SetString("optionsPageTitle",
l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE));
localized_strings->SetString("controlledSettingPolicy",
l10n_util::GetStringUTF16(IDS_OPTIONS_CONTROLLED_SETTING_POLICY));
localized_strings->SetString("controlledSettingExtension",
l10n_util::GetStringUTF16(IDS_OPTIONS_CONTROLLED_SETTING_EXTENSION));
localized_strings->SetString("controlledSettingExtensionWithName",
l10n_util::GetStringUTF16(
IDS_OPTIONS_CONTROLLED_SETTING_EXTENSION_WITH_NAME));
localized_strings->SetString("controlledSettingManageExtension",
l10n_util::GetStringUTF16(
IDS_OPTIONS_CONTROLLED_SETTING_MANAGE_EXTENSION));
localized_strings->SetString("controlledSettingDisableExtension",
l10n_util::GetStringUTF16(IDS_EXTENSIONS_DISABLE));
localized_strings->SetString("controlledSettingRecommended",
l10n_util::GetStringUTF16(IDS_OPTIONS_CONTROLLED_SETTING_RECOMMENDED));
localized_strings->SetString("controlledSettingHasRecommendation",
l10n_util::GetStringUTF16(
IDS_OPTIONS_CONTROLLED_SETTING_HAS_RECOMMENDATION));
localized_strings->SetString("controlledSettingFollowRecommendation",
l10n_util::GetStringUTF16(
IDS_OPTIONS_CONTROLLED_SETTING_FOLLOW_RECOMMENDATION));
localized_strings->SetString("controlledSettingsPolicy",
l10n_util::GetStringUTF16(IDS_OPTIONS_CONTROLLED_SETTINGS_POLICY));
localized_strings->SetString("controlledSettingsExtension",
l10n_util::GetStringUTF16(IDS_OPTIONS_CONTROLLED_SETTINGS_EXTENSION));
localized_strings->SetString("controlledSettingsExtensionWithName",
l10n_util::GetStringUTF16(
IDS_OPTIONS_CONTROLLED_SETTINGS_EXTENSION_WITH_NAME));
RegisterTitle(localized_strings, "searchPage", IDS_OPTIONS_SEARCH_PAGE_TITLE);
localized_strings->SetString("searchPlaceholder",
l10n_util::GetStringUTF16(IDS_OPTIONS_SEARCH_PLACEHOLDER));
localized_strings->SetString("searchPageNoMatches",
l10n_util::GetStringUTF16(IDS_OPTIONS_SEARCH_PAGE_NO_MATCHES));
localized_strings->SetString("searchPageHelpLabel",
l10n_util::GetStringUTF16(IDS_OPTIONS_SEARCH_PAGE_HELP_LABEL));
localized_strings->SetString("searchPageHelpTitle",
l10n_util::GetStringFUTF16(IDS_OPTIONS_SEARCH_PAGE_HELP_TITLE,
l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
localized_strings->SetString("searchPageHelpURL",
chrome::kSettingsSearchHelpURL);
localized_strings->SetString("ok",
l10n_util::GetStringUTF16(IDS_OK));
localized_strings->SetString("cancel",
l10n_util::GetStringUTF16(IDS_CANCEL));
localized_strings->SetString("learnMore",
l10n_util::GetStringUTF16(IDS_LEARN_MORE));
localized_strings->SetString("close",
l10n_util::GetStringUTF16(IDS_CLOSE));
localized_strings->SetString("done",
l10n_util::GetStringUTF16(IDS_DONE));
}
void CoreOptionsHandler::Uninitialize() {
std::string last_pref;
for (PreferenceCallbackMap::const_iterator iter = pref_callback_map_.begin();
iter != pref_callback_map_.end();
++iter) {
if (last_pref != iter->first) {
StopObservingPref(iter->first);
last_pref = iter->first;
}
}
}
void CoreOptionsHandler::OnPreferenceChanged(PrefService* service,
const std::string& pref_name) {
if (pref_name == prefs::kClearPluginLSODataEnabled) {
UpdateClearPluginLSOData();
return;
}
if (pref_name == prefs::kPepperFlashSettingsEnabled) {
UpdatePepperFlashSettingsEnabled();
return;
}
NotifyPrefChanged(pref_name, std::string());
}
void CoreOptionsHandler::RegisterMessages() {
registrar_.Init(Profile::FromWebUI(web_ui())->GetPrefs());
local_state_registrar_.Init(g_browser_process->local_state());
web_ui()->RegisterMessageCallback("coreOptionsInitialize",
base::Bind(&CoreOptionsHandler::HandleInitialize,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("onFinishedLoadingOptions",
base::Bind(&CoreOptionsHandler::OnFinishedLoading,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("fetchPrefs",
base::Bind(&CoreOptionsHandler::HandleFetchPrefs,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("observePrefs",
base::Bind(&CoreOptionsHandler::HandleObservePrefs,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("setBooleanPref",
base::Bind(&CoreOptionsHandler::HandleSetBooleanPref,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("setIntegerPref",
base::Bind(&CoreOptionsHandler::HandleSetIntegerPref,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("setDoublePref",
base::Bind(&CoreOptionsHandler::HandleSetDoublePref,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("setStringPref",
base::Bind(&CoreOptionsHandler::HandleSetStringPref,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("setURLPref",
base::Bind(&CoreOptionsHandler::HandleSetURLPref,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("setListPref",
base::Bind(&CoreOptionsHandler::HandleSetListPref,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("clearPref",
base::Bind(&CoreOptionsHandler::HandleClearPref,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("coreOptionsUserMetricsAction",
base::Bind(&CoreOptionsHandler::HandleUserMetricsAction,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("disableExtension",
base::Bind(&CoreOptionsHandler::HandleDisableExtension,
base::Unretained(this)));
}
void CoreOptionsHandler::HandleInitialize(const base::ListValue* args) {
DCHECK(handlers_host_);
handlers_host_->InitializeHandlers();
}
void CoreOptionsHandler::OnFinishedLoading(const base::ListValue* args) {
DCHECK(handlers_host_);
handlers_host_->OnFinishedLoading();
}
base::Value* CoreOptionsHandler::FetchPref(const std::string& pref_name) {
return CreateValueForPref(pref_name, std::string());
}
void CoreOptionsHandler::ObservePref(const std::string& pref_name) {
if (g_browser_process->local_state()->FindPreference(pref_name.c_str())) {
local_state_registrar_.Add(
pref_name.c_str(),
base::Bind(&CoreOptionsHandler::OnPreferenceChanged,
base::Unretained(this),
local_state_registrar_.prefs()));
}
if (Profile::FromWebUI(web_ui())->GetPrefs()->FindPreference(
pref_name.c_str())) {
registrar_.Add(
pref_name.c_str(),
base::Bind(&CoreOptionsHandler::OnPreferenceChanged,
base::Unretained(this),
registrar_.prefs()));
}
}
void CoreOptionsHandler::StopObservingPref(const std::string& pref_name) {
if (g_browser_process->local_state()->FindPreference(pref_name.c_str()))
local_state_registrar_.Remove(pref_name.c_str());
else
registrar_.Remove(pref_name.c_str());
}
void CoreOptionsHandler::SetPref(const std::string& pref_name,
const base::Value* value,
const std::string& metric) {
PrefService* pref_service = FindServiceForPref(pref_name);
PrefChangeFilterMap::iterator iter = pref_change_filters_.find(pref_name);
if (iter != pref_change_filters_.end()) {
const PrefService::Preference* pref =
pref_service->FindPreference(pref_name.c_str());
if ((pref && !pref->IsUserModifiable()) || !iter->second.Run(value)) {
NotifyPrefChanged(pref_name, std::string());
return;
}
}
switch (value->GetType()) {
case base::Value::TYPE_BOOLEAN:
case base::Value::TYPE_INTEGER:
case base::Value::TYPE_DOUBLE:
case base::Value::TYPE_STRING:
case base::Value::TYPE_LIST:
pref_service->Set(pref_name.c_str(), *value);
break;
default:
NOTREACHED();
return;
}
ProcessUserMetric(value, metric);
}
void CoreOptionsHandler::ClearPref(const std::string& pref_name,
const std::string& metric) {
PrefService* pref_service = FindServiceForPref(pref_name);
pref_service->ClearPref(pref_name.c_str());
if (!metric.empty())
content::RecordComputedAction(metric);
}
void CoreOptionsHandler::ProcessUserMetric(const base::Value* value,
const std::string& metric) {
if (metric.empty())
return;
std::string metric_string = metric;
if (value->IsType(base::Value::TYPE_BOOLEAN)) {
bool bool_value;
CHECK(value->GetAsBoolean(&bool_value));
metric_string += bool_value ? "_Enable" : "_Disable";
}
content::RecordComputedAction(metric_string);
}
void CoreOptionsHandler::NotifyPrefChanged(
const std::string& pref_name,
const std::string& controlling_pref_name) {
scoped_ptr<base::Value> value(
CreateValueForPref(pref_name, controlling_pref_name));
DispatchPrefChangeNotification(pref_name, value.Pass());
}
void CoreOptionsHandler::DispatchPrefChangeNotification(
const std::string& name,
scoped_ptr<base::Value> value) {
std::pair<PreferenceCallbackMap::const_iterator,
PreferenceCallbackMap::const_iterator> range =
pref_callback_map_.equal_range(name);
base::ListValue result_value;
result_value.Append(new base::StringValue(name.c_str()));
result_value.Append(value.release());
for (PreferenceCallbackMap::const_iterator iter = range.first;
iter != range.second; ++iter) {
const std::string& callback_function = iter->second;
web_ui()->CallJavascriptFunction(callback_function, result_value);
}
}
base::Value* CoreOptionsHandler::CreateValueForPref(
const std::string& pref_name,
const std::string& controlling_pref_name) {
const PrefService* pref_service = FindServiceForPref(pref_name.c_str());
const PrefService::Preference* pref =
pref_service->FindPreference(pref_name.c_str());
if (!pref) {
NOTREACHED();
return base::Value::CreateNullValue();
}
const PrefService::Preference* controlling_pref =
pref_service->FindPreference(controlling_pref_name.c_str());
if (!controlling_pref)
controlling_pref = pref;
base::DictionaryValue* dict = new base::DictionaryValue;
dict->Set("value", pref->GetValue()->DeepCopy());
if (controlling_pref->IsManaged()) {
dict->SetString("controlledBy", "policy");
} else if (controlling_pref->IsExtensionControlled()) {
dict->SetString("controlledBy", "extension");
Profile* profile = Profile::FromWebUI(web_ui());
ExtensionPrefValueMap* extension_pref_value_map =
ExtensionPrefValueMapFactory::GetForBrowserContext(profile);
std::string extension_id =
extension_pref_value_map->GetExtensionControllingPref(
controlling_pref->name());
const extensions::Extension* extension =
extensions::ExtensionRegistry::Get(profile)->GetExtensionById(
extension_id, extensions::ExtensionRegistry::EVERYTHING);
if (extension) {
dict->Set("extension",
extensions::util::GetExtensionInfo(extension).release());
}
} else if (controlling_pref->IsRecommended()) {
dict->SetString("controlledBy", "recommended");
}
const base::Value* recommended_value =
controlling_pref->GetRecommendedValue();
if (recommended_value)
dict->Set("recommendedValue", recommended_value->DeepCopy());
dict->SetBoolean("disabled", !controlling_pref->IsUserModifiable());
return dict;
}
PrefService* CoreOptionsHandler::FindServiceForPref(
const std::string& pref_name) {
PrefService* user_prefs = Profile::FromWebUI(web_ui())->GetPrefs();
if (pref_name == prefs::kProxy)
#if defined(OS_CHROMEOS)
return user_prefs;
#else
return g_browser_process->local_state();
#endif
if (user_prefs->FindPreference(pref_name.c_str()))
return user_prefs;
if (g_browser_process->local_state()->FindPreference(pref_name.c_str()))
return g_browser_process->local_state();
return user_prefs;
}
void CoreOptionsHandler::HandleFetchPrefs(const base::ListValue* args) {
DCHECK_GE(static_cast<int>(args->GetSize()), 2);
const base::Value* callback;
if (!args->Get(0, &callback) || !callback->IsType(base::Value::TYPE_STRING))
return;
base::string16 callback_function;
if (!callback->GetAsString(&callback_function))
return;
base::DictionaryValue result_value;
const base::Value* list_member;
for (size_t i = 1; i < args->GetSize(); i++) {
if (!args->Get(i, &list_member))
break;
if (!list_member->IsType(base::Value::TYPE_STRING))
continue;
std::string pref_name;
if (!list_member->GetAsString(&pref_name))
continue;
result_value.Set(pref_name.c_str(), FetchPref(pref_name));
}
web_ui()->CallJavascriptFunction(base::UTF16ToASCII(callback_function),
result_value);
}
void CoreOptionsHandler::HandleObservePrefs(const base::ListValue* args) {
DCHECK_GE(static_cast<int>(args->GetSize()), 2);
std::string callback_func_name;
if (!args->GetString(0, &callback_func_name))
return;
for (size_t i = 1; i < args->GetSize(); i++) {
const base::Value* list_member;
if (!args->Get(i, &list_member))
break;
std::string pref_name;
if (!list_member->IsType(base::Value::TYPE_STRING) ||
!list_member->GetAsString(&pref_name))
continue;
if (pref_callback_map_.find(pref_name) == pref_callback_map_.end())
ObservePref(pref_name);
pref_callback_map_.insert(
PreferenceCallbackMap::value_type(pref_name, callback_func_name));
}
}
void CoreOptionsHandler::HandleSetBooleanPref(const base::ListValue* args) {
HandleSetPref(args, TYPE_BOOLEAN);
}
void CoreOptionsHandler::HandleSetIntegerPref(const base::ListValue* args) {
HandleSetPref(args, TYPE_INTEGER);
}
void CoreOptionsHandler::HandleSetDoublePref(const base::ListValue* args) {
HandleSetPref(args, TYPE_DOUBLE);
}
void CoreOptionsHandler::HandleSetStringPref(const base::ListValue* args) {
HandleSetPref(args, TYPE_STRING);
}
void CoreOptionsHandler::HandleSetURLPref(const base::ListValue* args) {
HandleSetPref(args, TYPE_URL);
}
void CoreOptionsHandler::HandleSetListPref(const base::ListValue* args) {
HandleSetPref(args, TYPE_LIST);
}
void CoreOptionsHandler::HandleSetPref(const base::ListValue* args,
PrefType type) {
DCHECK_GT(static_cast<int>(args->GetSize()), 1);
std::string pref_name;
if (!args->GetString(0, &pref_name))
return;
const base::Value* value;
if (!args->Get(1, &value))
return;
scoped_ptr<base::Value> temp_value;
switch (type) {
case TYPE_BOOLEAN:
if (!value->IsType(base::Value::TYPE_BOOLEAN)) {
NOTREACHED();
return;
}
break;
case TYPE_INTEGER: {
double double_value;
if (!value->GetAsDouble(&double_value)) {
NOTREACHED();
return;
}
int int_value = static_cast<int>(double_value);
temp_value.reset(new base::FundamentalValue(int_value));
value = temp_value.get();
break;
}
case TYPE_DOUBLE:
if (!value->IsType(base::Value::TYPE_DOUBLE)) {
NOTREACHED();
return;
}
break;
case TYPE_STRING:
if (!value->IsType(base::Value::TYPE_STRING)) {
NOTREACHED();
return;
}
break;
case TYPE_URL: {
std::string original;
if (!value->GetAsString(&original)) {
NOTREACHED();
return;
}
GURL fixed = URLFixerUpper::FixupURL(original, std::string());
temp_value.reset(new base::StringValue(fixed.spec()));
value = temp_value.get();
break;
}
case TYPE_LIST: {
std::string json_string;
if (!value->GetAsString(&json_string)) {
NOTREACHED();
return;
}
temp_value.reset(
base::JSONReader::Read(json_string));
value = temp_value.get();
if (!value->IsType(base::Value::TYPE_LIST)) {
NOTREACHED();
return;
}
break;
}
default:
NOTREACHED();
}
std::string metric;
if (args->GetSize() > 2 && !args->GetString(2, &metric))
LOG(WARNING) << "Invalid metric parameter: " << pref_name;
SetPref(pref_name, value, metric);
}
void CoreOptionsHandler::HandleClearPref(const base::ListValue* args) {
DCHECK_GT(static_cast<int>(args->GetSize()), 0);
std::string pref_name;
if (!args->GetString(0, &pref_name))
return;
std::string metric;
if (args->GetSize() > 1) {
if (!args->GetString(1, &metric))
NOTREACHED();
}
ClearPref(pref_name, metric);
}
void CoreOptionsHandler::HandleUserMetricsAction(const base::ListValue* args) {
std::string metric = base::UTF16ToUTF8(ExtractStringValue(args));
if (!metric.empty())
content::RecordComputedAction(metric);
}
void CoreOptionsHandler::HandleDisableExtension(const base::ListValue* args) {
std::string extension_id;
if (args->GetString(0, &extension_id)) {
ExtensionService* extension_service = extensions::ExtensionSystem::Get(
Profile::FromWebUI(web_ui()))->extension_service();
DCHECK(extension_service);
extension_service->DisableExtension(
extension_id, extensions::Extension::DISABLE_USER_ACTION);
} else {
NOTREACHED();
}
}
void CoreOptionsHandler::UpdateClearPluginLSOData() {
base::FundamentalValue enabled(
plugin_status_pref_setter_.IsClearPluginLSODataEnabled());
web_ui()->CallJavascriptFunction(
"OptionsPage.setClearPluginLSODataEnabled", enabled);
}
void CoreOptionsHandler::UpdatePepperFlashSettingsEnabled() {
base::FundamentalValue enabled(
plugin_status_pref_setter_.IsPepperFlashSettingsEnabled());
web_ui()->CallJavascriptFunction(
"OptionsPage.setPepperFlashSettingsEnabled", enabled);
}
}