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