Home | History | Annotate | Download | only in options
      1 // Copyright (c) 2012 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/options/core_options_handler.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/json/json_reader.h"
     10 #include "base/memory/scoped_ptr.h"
     11 #include "base/strings/string16.h"
     12 #include "base/strings/string_number_conversions.h"
     13 #include "base/strings/utf_string_conversions.h"
     14 #include "base/values.h"
     15 #include "chrome/browser/browser_process.h"
     16 #include "chrome/browser/chrome_notification_types.h"
     17 #include "chrome/browser/extensions/extension_service.h"
     18 #include "chrome/browser/extensions/extension_util.h"
     19 #include "chrome/browser/profiles/profile.h"
     20 #include "chrome/common/chrome_switches.h"
     21 #include "chrome/common/pref_names.h"
     22 #include "chrome/common/url_constants.h"
     23 #include "chrome/grit/chromium_strings.h"
     24 #include "chrome/grit/generated_resources.h"
     25 #include "chrome/grit/locale_settings.h"
     26 #include "components/url_fixer/url_fixer.h"
     27 #include "content/public/browser/notification_details.h"
     28 #include "content/public/browser/notification_types.h"
     29 #include "content/public/browser/user_metrics.h"
     30 #include "content/public/browser/web_ui.h"
     31 #include "extensions/browser/extension_pref_value_map.h"
     32 #include "extensions/browser/extension_pref_value_map_factory.h"
     33 #include "extensions/browser/extension_registry.h"
     34 #include "extensions/browser/extension_system.h"
     35 #include "extensions/common/extension.h"
     36 #include "grit/components_strings.h"
     37 #include "ui/base/l10n/l10n_util.h"
     38 #include "url/gurl.h"
     39 
     40 using base::UserMetricsAction;
     41 
     42 namespace options {
     43 
     44 namespace {
     45 
     46 // Whether "controlledBy" property of pref value sent to options web UI needs to
     47 // be set to "extension" when the preference is controlled by an extension.
     48 bool CanSetExtensionControlledPrefValue(
     49     const PrefService::Preference* preference) {
     50 #if defined(OS_WIN)
     51   // These have more obvious UI than the standard one for extension controlled
     52   // values (an extension puzzle piece) on the settings page. To avoiding
     53   // showing the extension puzzle piece for these settings, their "controlledBy"
     54   // value should never be set to "extension".
     55   return preference->name() != prefs::kURLsToRestoreOnStartup &&
     56          preference->name() != prefs::kRestoreOnStartup &&
     57          preference->name() != prefs::kHomePage &&
     58          preference->name() != prefs::kHomePageIsNewTabPage;
     59 #else
     60   return true;
     61 #endif
     62 }
     63 
     64 // Hack to re-use IDS_ABOUT, which is a menu item for the About page.
     65 // Since it's a menu item, it may include a "&" to indicate a hotkey.
     66 base::string16 GetAboutString() {
     67   if (!switches::AboutInSettingsEnabled())
     68     return base::string16();
     69 
     70   base::string16 str = l10n_util::GetStringUTF16(IDS_ABOUT);
     71   size_t start_pos = str.find(base::ASCIIToUTF16("&"));
     72   if (start_pos != base::string16::npos)
     73     str.erase(start_pos, 1);
     74   return str;
     75 }
     76 
     77 }  // namespace
     78 
     79 CoreOptionsHandler::CoreOptionsHandler()
     80     : handlers_host_(NULL) {
     81 }
     82 
     83 CoreOptionsHandler::~CoreOptionsHandler() {}
     84 
     85 void CoreOptionsHandler::InitializeHandler() {
     86   Profile* profile = Profile::FromWebUI(web_ui());
     87 
     88   plugin_status_pref_setter_.Init(
     89       profile,
     90       base::Bind(&CoreOptionsHandler::OnPreferenceChanged,
     91                  base::Unretained(this),
     92                  profile->GetPrefs()));
     93 
     94   pref_change_filters_[prefs::kBrowserGuestModeEnabled] =
     95       base::Bind(&CoreOptionsHandler::IsUserUnsupervised,
     96                  base::Unretained(this));
     97   pref_change_filters_[prefs::kBrowserAddPersonEnabled] =
     98       base::Bind(&CoreOptionsHandler::IsUserUnsupervised,
     99                  base::Unretained(this));
    100 }
    101 
    102 void CoreOptionsHandler::InitializePage() {
    103   UpdateClearPluginLSOData();
    104   UpdatePepperFlashSettingsEnabled();
    105 }
    106 
    107 void CoreOptionsHandler::GetLocalizedValues(
    108     base::DictionaryValue* localized_strings) {
    109   GetStaticLocalizedValues(localized_strings);
    110 }
    111 
    112 void CoreOptionsHandler::GetStaticLocalizedValues(
    113     base::DictionaryValue* localized_strings) {
    114   DCHECK(localized_strings);
    115   // Main
    116   localized_strings->SetString("optionsPageTitle",
    117       l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE));
    118 
    119   // Controlled settings bubble.
    120   localized_strings->SetString("controlledSettingPolicy",
    121       l10n_util::GetStringUTF16(IDS_OPTIONS_CONTROLLED_SETTING_POLICY));
    122   localized_strings->SetString("controlledSettingExtension",
    123       l10n_util::GetStringUTF16(IDS_OPTIONS_CONTROLLED_SETTING_EXTENSION));
    124   localized_strings->SetString("controlledSettingExtensionWithName",
    125       l10n_util::GetStringUTF16(
    126           IDS_OPTIONS_CONTROLLED_SETTING_EXTENSION_WITH_NAME));
    127   localized_strings->SetString("controlledSettingManageExtension",
    128       l10n_util::GetStringUTF16(
    129           IDS_OPTIONS_CONTROLLED_SETTING_MANAGE_EXTENSION));
    130   localized_strings->SetString("controlledSettingDisableExtension",
    131       l10n_util::GetStringUTF16(IDS_EXTENSIONS_DISABLE));
    132   localized_strings->SetString("controlledSettingRecommended",
    133       l10n_util::GetStringUTF16(IDS_OPTIONS_CONTROLLED_SETTING_RECOMMENDED));
    134   localized_strings->SetString("controlledSettingHasRecommendation",
    135       l10n_util::GetStringUTF16(
    136           IDS_OPTIONS_CONTROLLED_SETTING_HAS_RECOMMENDATION));
    137   localized_strings->SetString("controlledSettingFollowRecommendation",
    138       l10n_util::GetStringUTF16(
    139           IDS_OPTIONS_CONTROLLED_SETTING_FOLLOW_RECOMMENDATION));
    140   localized_strings->SetString("controlledSettingsPolicy",
    141       l10n_util::GetStringUTF16(IDS_OPTIONS_CONTROLLED_SETTINGS_POLICY));
    142   localized_strings->SetString("controlledSettingsExtension",
    143       l10n_util::GetStringUTF16(IDS_OPTIONS_CONTROLLED_SETTINGS_EXTENSION));
    144   localized_strings->SetString("controlledSettingsExtensionWithName",
    145       l10n_util::GetStringUTF16(
    146           IDS_OPTIONS_CONTROLLED_SETTINGS_EXTENSION_WITH_NAME));
    147 
    148   // Search
    149   RegisterTitle(localized_strings, "searchPage", IDS_OPTIONS_SEARCH_PAGE_TITLE);
    150   localized_strings->SetString("searchPlaceholder",
    151       l10n_util::GetStringUTF16(IDS_OPTIONS_SEARCH_PLACEHOLDER));
    152   localized_strings->SetString("searchPageNoMatches",
    153       l10n_util::GetStringUTF16(IDS_OPTIONS_SEARCH_PAGE_NO_MATCHES));
    154   localized_strings->SetString("searchPageHelpLabel",
    155       l10n_util::GetStringUTF16(IDS_OPTIONS_SEARCH_PAGE_HELP_LABEL));
    156   localized_strings->SetString("searchPageHelpTitle",
    157       l10n_util::GetStringFUTF16(IDS_OPTIONS_SEARCH_PAGE_HELP_TITLE,
    158           l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
    159   localized_strings->SetString("searchPageHelpURL",
    160                                chrome::kSettingsSearchHelpURL);
    161 
    162   // About
    163   localized_strings->SetBoolean("showAbout",
    164                                 switches::AboutInSettingsEnabled());
    165   localized_strings->SetString("aboutButton", GetAboutString());
    166 
    167   // Common
    168   localized_strings->SetString("ok",
    169       l10n_util::GetStringUTF16(IDS_OK));
    170   localized_strings->SetString("cancel",
    171       l10n_util::GetStringUTF16(IDS_CANCEL));
    172   localized_strings->SetString("learnMore",
    173       l10n_util::GetStringUTF16(IDS_LEARN_MORE));
    174   localized_strings->SetString("close",
    175       l10n_util::GetStringUTF16(IDS_CLOSE));
    176   localized_strings->SetString("done",
    177       l10n_util::GetStringUTF16(IDS_DONE));
    178   localized_strings->SetString("deletableItemDeleteButtonTitle",
    179       l10n_util::GetStringUTF16(IDS_OPTIONS_DELETABLE_ITEM_DELETE_BUTTON));
    180 }
    181 
    182 void CoreOptionsHandler::Uninitialize() {
    183   std::string last_pref;
    184   for (PreferenceCallbackMap::const_iterator iter = pref_callback_map_.begin();
    185        iter != pref_callback_map_.end();
    186        ++iter) {
    187     if (last_pref != iter->first) {
    188       StopObservingPref(iter->first);
    189       last_pref = iter->first;
    190     }
    191   }
    192 }
    193 
    194 void CoreOptionsHandler::OnPreferenceChanged(PrefService* service,
    195                                              const std::string& pref_name) {
    196   if (pref_name == prefs::kClearPluginLSODataEnabled) {
    197     // This preference is stored in Local State, not in the user preferences.
    198     UpdateClearPluginLSOData();
    199     return;
    200   }
    201   if (pref_name == prefs::kPepperFlashSettingsEnabled) {
    202     UpdatePepperFlashSettingsEnabled();
    203     return;
    204   }
    205   NotifyPrefChanged(pref_name, std::string());
    206 }
    207 
    208 void CoreOptionsHandler::RegisterMessages() {
    209   registrar_.Init(Profile::FromWebUI(web_ui())->GetPrefs());
    210   local_state_registrar_.Init(g_browser_process->local_state());
    211 
    212   web_ui()->RegisterMessageCallback("coreOptionsInitialize",
    213       base::Bind(&CoreOptionsHandler::HandleInitialize,
    214                  base::Unretained(this)));
    215   web_ui()->RegisterMessageCallback("onFinishedLoadingOptions",
    216       base::Bind(&CoreOptionsHandler::OnFinishedLoading,
    217                  base::Unretained(this)));
    218   web_ui()->RegisterMessageCallback("fetchPrefs",
    219       base::Bind(&CoreOptionsHandler::HandleFetchPrefs,
    220                  base::Unretained(this)));
    221   web_ui()->RegisterMessageCallback("observePrefs",
    222       base::Bind(&CoreOptionsHandler::HandleObservePrefs,
    223                  base::Unretained(this)));
    224   web_ui()->RegisterMessageCallback("setBooleanPref",
    225       base::Bind(&CoreOptionsHandler::HandleSetBooleanPref,
    226                  base::Unretained(this)));
    227   web_ui()->RegisterMessageCallback("setIntegerPref",
    228       base::Bind(&CoreOptionsHandler::HandleSetIntegerPref,
    229                  base::Unretained(this)));
    230   web_ui()->RegisterMessageCallback("setDoublePref",
    231       base::Bind(&CoreOptionsHandler::HandleSetDoublePref,
    232                  base::Unretained(this)));
    233   web_ui()->RegisterMessageCallback("setStringPref",
    234       base::Bind(&CoreOptionsHandler::HandleSetStringPref,
    235                  base::Unretained(this)));
    236   web_ui()->RegisterMessageCallback("setURLPref",
    237       base::Bind(&CoreOptionsHandler::HandleSetURLPref,
    238                  base::Unretained(this)));
    239   web_ui()->RegisterMessageCallback("setListPref",
    240       base::Bind(&CoreOptionsHandler::HandleSetListPref,
    241                  base::Unretained(this)));
    242   web_ui()->RegisterMessageCallback("clearPref",
    243       base::Bind(&CoreOptionsHandler::HandleClearPref,
    244                  base::Unretained(this)));
    245   web_ui()->RegisterMessageCallback("coreOptionsUserMetricsAction",
    246       base::Bind(&CoreOptionsHandler::HandleUserMetricsAction,
    247                  base::Unretained(this)));
    248   web_ui()->RegisterMessageCallback("disableExtension",
    249       base::Bind(&CoreOptionsHandler::HandleDisableExtension,
    250                  base::Unretained(this)));
    251 }
    252 
    253 void CoreOptionsHandler::HandleInitialize(const base::ListValue* args) {
    254   DCHECK(handlers_host_);
    255   handlers_host_->InitializeHandlers();
    256 }
    257 
    258 void CoreOptionsHandler::OnFinishedLoading(const base::ListValue* args) {
    259   DCHECK(handlers_host_);
    260   handlers_host_->OnFinishedLoading();
    261 }
    262 
    263 base::Value* CoreOptionsHandler::FetchPref(const std::string& pref_name) {
    264   return CreateValueForPref(pref_name, std::string());
    265 }
    266 
    267 void CoreOptionsHandler::ObservePref(const std::string& pref_name) {
    268   if (g_browser_process->local_state()->FindPreference(pref_name.c_str())) {
    269     local_state_registrar_.Add(
    270         pref_name.c_str(),
    271         base::Bind(&CoreOptionsHandler::OnPreferenceChanged,
    272                    base::Unretained(this),
    273                    local_state_registrar_.prefs()));
    274   }
    275   // TODO(pneubeck): change this to if/else once kProxy is only used as a user
    276   // pref. Currently, it is both a user and a local state pref.
    277   if (Profile::FromWebUI(web_ui())->GetPrefs()->FindPreference(
    278           pref_name.c_str())) {
    279     registrar_.Add(
    280         pref_name.c_str(),
    281         base::Bind(&CoreOptionsHandler::OnPreferenceChanged,
    282                    base::Unretained(this),
    283                    registrar_.prefs()));
    284   }
    285 }
    286 
    287 void CoreOptionsHandler::StopObservingPref(const std::string& pref_name) {
    288   if (g_browser_process->local_state()->FindPreference(pref_name.c_str()))
    289     local_state_registrar_.Remove(pref_name.c_str());
    290   else
    291     registrar_.Remove(pref_name.c_str());
    292 }
    293 
    294 void CoreOptionsHandler::SetPref(const std::string& pref_name,
    295                                  const base::Value* value,
    296                                  const std::string& metric) {
    297   PrefService* pref_service = FindServiceForPref(pref_name);
    298   PrefChangeFilterMap::iterator iter = pref_change_filters_.find(pref_name);
    299   if (iter != pref_change_filters_.end()) {
    300     // Also check if the pref is user modifiable (don't even try to run the
    301     // filter function if the user is not allowed to change the pref).
    302     const PrefService::Preference* pref =
    303         pref_service->FindPreference(pref_name.c_str());
    304     if ((pref && !pref->IsUserModifiable()) || !iter->second.Run(value)) {
    305       // Reject the change; remind the page of the true value.
    306       NotifyPrefChanged(pref_name, std::string());
    307       return;
    308     }
    309   }
    310 
    311   switch (value->GetType()) {
    312     case base::Value::TYPE_BOOLEAN:
    313     case base::Value::TYPE_INTEGER:
    314     case base::Value::TYPE_DOUBLE:
    315     case base::Value::TYPE_STRING:
    316     case base::Value::TYPE_LIST:
    317       pref_service->Set(pref_name.c_str(), *value);
    318       break;
    319 
    320     default:
    321       NOTREACHED();
    322       return;
    323   }
    324 
    325   ProcessUserMetric(value, metric);
    326 }
    327 
    328 void CoreOptionsHandler::ClearPref(const std::string& pref_name,
    329                                    const std::string& metric) {
    330   PrefService* pref_service = FindServiceForPref(pref_name);
    331   pref_service->ClearPref(pref_name.c_str());
    332 
    333   if (!metric.empty())
    334     content::RecordComputedAction(metric);
    335 }
    336 
    337 void CoreOptionsHandler::ProcessUserMetric(const base::Value* value,
    338                                            const std::string& metric) {
    339   if (metric.empty())
    340     return;
    341 
    342   std::string metric_string = metric;
    343   if (value->IsType(base::Value::TYPE_BOOLEAN)) {
    344     bool bool_value;
    345     CHECK(value->GetAsBoolean(&bool_value));
    346     metric_string += bool_value ? "_Enable" : "_Disable";
    347   }
    348 
    349   content::RecordComputedAction(metric_string);
    350 }
    351 
    352 void CoreOptionsHandler::NotifyPrefChanged(
    353     const std::string& pref_name,
    354     const std::string& controlling_pref_name) {
    355   scoped_ptr<base::Value> value(
    356       CreateValueForPref(pref_name, controlling_pref_name));
    357   DispatchPrefChangeNotification(pref_name, value.Pass());
    358 }
    359 
    360 void CoreOptionsHandler::DispatchPrefChangeNotification(
    361     const std::string& name,
    362     scoped_ptr<base::Value> value) {
    363   std::pair<PreferenceCallbackMap::const_iterator,
    364             PreferenceCallbackMap::const_iterator> range =
    365       pref_callback_map_.equal_range(name);
    366   base::ListValue result_value;
    367   result_value.Append(new base::StringValue(name.c_str()));
    368   result_value.Append(value.release());
    369   for (PreferenceCallbackMap::const_iterator iter = range.first;
    370        iter != range.second; ++iter) {
    371     const std::string& callback_function = iter->second;
    372     web_ui()->CallJavascriptFunction(callback_function, result_value);
    373   }
    374 }
    375 
    376 base::Value* CoreOptionsHandler::CreateValueForPref(
    377     const std::string& pref_name,
    378     const std::string& controlling_pref_name) {
    379   const PrefService* pref_service = FindServiceForPref(pref_name.c_str());
    380   const PrefService::Preference* pref =
    381       pref_service->FindPreference(pref_name.c_str());
    382   if (!pref) {
    383     NOTREACHED();
    384     return base::Value::CreateNullValue();
    385   }
    386   const PrefService::Preference* controlling_pref =
    387       pref_service->FindPreference(controlling_pref_name.c_str());
    388   if (!controlling_pref)
    389     controlling_pref = pref;
    390 
    391   base::DictionaryValue* dict = new base::DictionaryValue;
    392   dict->Set("value", pref->GetValue()->DeepCopy());
    393   if (controlling_pref->IsManaged()) {
    394     dict->SetString("controlledBy", "policy");
    395   } else if (controlling_pref->IsExtensionControlled() &&
    396              CanSetExtensionControlledPrefValue(controlling_pref)) {
    397     Profile* profile = Profile::FromWebUI(web_ui());
    398     ExtensionPrefValueMap* extension_pref_value_map =
    399         ExtensionPrefValueMapFactory::GetForBrowserContext(profile);
    400     std::string extension_id =
    401         extension_pref_value_map->GetExtensionControllingPref(
    402             controlling_pref->name());
    403 
    404     const extensions::Extension* extension =
    405         extensions::ExtensionRegistry::Get(profile)->GetExtensionById(
    406             extension_id, extensions::ExtensionRegistry::EVERYTHING);
    407     if (extension) {
    408       dict->SetString("controlledBy", "extension");
    409       dict->Set("extension",
    410                 extensions::util::GetExtensionInfo(extension).release());
    411     }
    412   } else if (controlling_pref->IsRecommended()) {
    413     dict->SetString("controlledBy", "recommended");
    414   }
    415 
    416   const base::Value* recommended_value =
    417       controlling_pref->GetRecommendedValue();
    418   if (recommended_value)
    419     dict->Set("recommendedValue", recommended_value->DeepCopy());
    420   dict->SetBoolean("disabled", !controlling_pref->IsUserModifiable());
    421   return dict;
    422 }
    423 
    424 PrefService* CoreOptionsHandler::FindServiceForPref(
    425     const std::string& pref_name) {
    426   // Proxy is a peculiar case: on ChromeOS, settings exist in both user
    427   // prefs and local state, but chrome://settings should affect only user prefs.
    428   // Elsewhere the proxy settings are stored in local state.
    429   // See http://crbug.com/157147
    430   PrefService* user_prefs = Profile::FromWebUI(web_ui())->GetPrefs();
    431   if (pref_name == prefs::kProxy)
    432 #if defined(OS_CHROMEOS)
    433     return user_prefs;
    434 #else
    435     return g_browser_process->local_state();
    436 #endif
    437 
    438   // Find which PrefService contains the given pref. Pref names should not
    439   // be duplicated across services, however if they are, prefer the user's
    440   // prefs.
    441   if (user_prefs->FindPreference(pref_name.c_str()))
    442     return user_prefs;
    443 
    444   if (g_browser_process->local_state()->FindPreference(pref_name.c_str()))
    445     return g_browser_process->local_state();
    446 
    447   return user_prefs;
    448 }
    449 
    450 void CoreOptionsHandler::HandleFetchPrefs(const base::ListValue* args) {
    451   // First param is name of callback function, so, there needs to be at least
    452   // one more element for the actual preference identifier.
    453   DCHECK_GE(static_cast<int>(args->GetSize()), 2);
    454 
    455   // Get callback JS function name.
    456   const base::Value* callback;
    457   if (!args->Get(0, &callback) || !callback->IsType(base::Value::TYPE_STRING))
    458     return;
    459 
    460   base::string16 callback_function;
    461   if (!callback->GetAsString(&callback_function))
    462     return;
    463 
    464   // Get the list of name for prefs to build the response dictionary.
    465   base::DictionaryValue result_value;
    466   const base::Value* list_member;
    467 
    468   for (size_t i = 1; i < args->GetSize(); i++) {
    469     if (!args->Get(i, &list_member))
    470       break;
    471 
    472     if (!list_member->IsType(base::Value::TYPE_STRING))
    473       continue;
    474 
    475     std::string pref_name;
    476     if (!list_member->GetAsString(&pref_name))
    477       continue;
    478 
    479     result_value.Set(pref_name.c_str(), FetchPref(pref_name));
    480   }
    481   web_ui()->CallJavascriptFunction(base::UTF16ToASCII(callback_function),
    482                                    result_value);
    483 }
    484 
    485 void CoreOptionsHandler::HandleObservePrefs(const base::ListValue* args) {
    486   // First param is name is JS callback function name, the rest are pref
    487   // identifiers that we are observing.
    488   DCHECK_GE(static_cast<int>(args->GetSize()), 2);
    489 
    490   // Get preference change callback function name.
    491   std::string callback_func_name;
    492   if (!args->GetString(0, &callback_func_name))
    493     return;
    494 
    495   // Get all other parameters - pref identifiers.
    496   for (size_t i = 1; i < args->GetSize(); i++) {
    497     const base::Value* list_member;
    498     if (!args->Get(i, &list_member))
    499       break;
    500 
    501     // Just ignore bad pref identifiers for now.
    502     std::string pref_name;
    503     if (!list_member->IsType(base::Value::TYPE_STRING) ||
    504         !list_member->GetAsString(&pref_name))
    505       continue;
    506 
    507     if (pref_callback_map_.find(pref_name) == pref_callback_map_.end())
    508       ObservePref(pref_name);
    509 
    510     pref_callback_map_.insert(
    511         PreferenceCallbackMap::value_type(pref_name, callback_func_name));
    512   }
    513 }
    514 
    515 void CoreOptionsHandler::HandleSetBooleanPref(const base::ListValue* args) {
    516   HandleSetPref(args, TYPE_BOOLEAN);
    517 }
    518 
    519 void CoreOptionsHandler::HandleSetIntegerPref(const base::ListValue* args) {
    520   HandleSetPref(args, TYPE_INTEGER);
    521 }
    522 
    523 void CoreOptionsHandler::HandleSetDoublePref(const base::ListValue* args) {
    524   HandleSetPref(args, TYPE_DOUBLE);
    525 }
    526 
    527 void CoreOptionsHandler::HandleSetStringPref(const base::ListValue* args) {
    528   HandleSetPref(args, TYPE_STRING);
    529 }
    530 
    531 void CoreOptionsHandler::HandleSetURLPref(const base::ListValue* args) {
    532   HandleSetPref(args, TYPE_URL);
    533 }
    534 
    535 void CoreOptionsHandler::HandleSetListPref(const base::ListValue* args) {
    536   HandleSetPref(args, TYPE_LIST);
    537 }
    538 
    539 void CoreOptionsHandler::HandleSetPref(const base::ListValue* args,
    540                                        PrefType type) {
    541   DCHECK_GT(static_cast<int>(args->GetSize()), 1);
    542 
    543   std::string pref_name;
    544   if (!args->GetString(0, &pref_name))
    545     return;
    546 
    547   const base::Value* value;
    548   if (!args->Get(1, &value))
    549     return;
    550 
    551   scoped_ptr<base::Value> temp_value;
    552 
    553   switch (type) {
    554     case TYPE_BOOLEAN:
    555       if (!value->IsType(base::Value::TYPE_BOOLEAN)) {
    556         NOTREACHED();
    557         return;
    558       }
    559       break;
    560     case TYPE_INTEGER: {
    561       // In JS all numbers are doubles.
    562       double double_value;
    563       if (!value->GetAsDouble(&double_value)) {
    564         NOTREACHED();
    565         return;
    566       }
    567       int int_value = static_cast<int>(double_value);
    568       temp_value.reset(new base::FundamentalValue(int_value));
    569       value = temp_value.get();
    570       break;
    571     }
    572     case TYPE_DOUBLE:
    573       if (!value->IsType(base::Value::TYPE_DOUBLE)) {
    574         NOTREACHED();
    575         return;
    576       }
    577       break;
    578     case TYPE_STRING:
    579       if (!value->IsType(base::Value::TYPE_STRING)) {
    580         NOTREACHED();
    581         return;
    582       }
    583       break;
    584     case TYPE_URL: {
    585       std::string original;
    586       if (!value->GetAsString(&original)) {
    587         NOTREACHED();
    588         return;
    589       }
    590       GURL fixed = url_fixer::FixupURL(original, std::string());
    591       temp_value.reset(new base::StringValue(fixed.spec()));
    592       value = temp_value.get();
    593       break;
    594     }
    595     case TYPE_LIST: {
    596       // In case we have a List pref we got a JSON string.
    597       std::string json_string;
    598       if (!value->GetAsString(&json_string)) {
    599         NOTREACHED();
    600         return;
    601       }
    602       temp_value.reset(
    603           base::JSONReader::Read(json_string));
    604       value = temp_value.get();
    605       if (!value->IsType(base::Value::TYPE_LIST)) {
    606         NOTREACHED();
    607         return;
    608       }
    609       break;
    610     }
    611     default:
    612       NOTREACHED();
    613   }
    614 
    615   std::string metric;
    616   if (args->GetSize() > 2 && !args->GetString(2, &metric))
    617     LOG(WARNING) << "Invalid metric parameter: " << pref_name;
    618   SetPref(pref_name, value, metric);
    619 }
    620 
    621 void CoreOptionsHandler::HandleClearPref(const base::ListValue* args) {
    622   DCHECK_GT(static_cast<int>(args->GetSize()), 0);
    623 
    624   std::string pref_name;
    625   if (!args->GetString(0, &pref_name))
    626     return;
    627 
    628   std::string metric;
    629   if (args->GetSize() > 1) {
    630     if (!args->GetString(1, &metric))
    631       NOTREACHED();
    632   }
    633 
    634   ClearPref(pref_name, metric);
    635 }
    636 
    637 void CoreOptionsHandler::HandleUserMetricsAction(const base::ListValue* args) {
    638   std::string metric = base::UTF16ToUTF8(ExtractStringValue(args));
    639   if (!metric.empty())
    640     content::RecordComputedAction(metric);
    641 }
    642 
    643 void CoreOptionsHandler::HandleDisableExtension(const base::ListValue* args) {
    644   std::string extension_id;
    645   if (args->GetString(0, &extension_id)) {
    646     ExtensionService* extension_service = extensions::ExtensionSystem::Get(
    647         Profile::FromWebUI(web_ui()))->extension_service();
    648     DCHECK(extension_service);
    649     extension_service->DisableExtension(
    650         extension_id, extensions::Extension::DISABLE_USER_ACTION);
    651   } else {
    652     NOTREACHED();
    653   }
    654 }
    655 
    656 void CoreOptionsHandler::UpdateClearPluginLSOData() {
    657   base::FundamentalValue enabled(
    658           plugin_status_pref_setter_.IsClearPluginLSODataEnabled());
    659   web_ui()->CallJavascriptFunction(
    660       "OptionsPage.setClearPluginLSODataEnabled", enabled);
    661 }
    662 
    663 void CoreOptionsHandler::UpdatePepperFlashSettingsEnabled() {
    664   base::FundamentalValue enabled(
    665           plugin_status_pref_setter_.IsPepperFlashSettingsEnabled());
    666   web_ui()->CallJavascriptFunction(
    667       "OptionsPage.setPepperFlashSettingsEnabled", enabled);
    668 }
    669 
    670 bool CoreOptionsHandler::IsUserUnsupervised(const base::Value* to_value) {
    671   return !Profile::FromWebUI(web_ui())->IsSupervised();
    672 }
    673 
    674 }  // namespace options
    675