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