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