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