// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/webui/options/core_options_handler.h"

#include <stddef.h>

#include <memory>
#include <utility>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/json/json_reader.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/user_metrics.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/chromium_strings.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/grit/locale_settings.h"
#include "components/proxy_config/proxy_config_pref_names.h"
#include "components/strings/grit/components_strings.h"
#include "components/url_formatter/url_fixer.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/web_ui.h"
#include "extensions/browser/extension_pref_value_map.h"
#include "extensions/browser/extension_pref_value_map_factory.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/extension.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"

using base::UserMetricsAction;

namespace options {

namespace {

// Whether "controlledBy" property of pref value sent to options web UI needs to
// be set to "extension" when the preference is controlled by an extension.
bool CanSetExtensionControlledPrefValue(
    const PrefService::Preference* preference) {
#if defined(OS_WIN)
  // These have more obvious UI than the standard one for extension controlled
  // values (an extension puzzle piece) on the settings page. To avoiding
  // showing the extension puzzle piece for these settings, their "controlledBy"
  // value should never be set to "extension".
  return preference->name() != prefs::kURLsToRestoreOnStartup &&
         preference->name() != prefs::kRestoreOnStartup &&
         preference->name() != prefs::kHomePage &&
         preference->name() != prefs::kHomePageIsNewTabPage;
#else
  return true;
#endif
}

}  // namespace

CoreOptionsHandler::CoreOptionsHandler()
    : handlers_host_(NULL) {
}

CoreOptionsHandler::~CoreOptionsHandler() {}

void CoreOptionsHandler::InitializeHandler() {
  Profile* profile = Profile::FromWebUI(web_ui());

  plugin_status_pref_setter_.Init(
      profile,
      base::Bind(&CoreOptionsHandler::OnPreferenceChanged,
                 base::Unretained(this),
                 profile->GetPrefs()));

  pref_change_filters_[prefs::kBrowserGuestModeEnabled] =
      base::Bind(&CoreOptionsHandler::IsUserUnsupervised,
                 base::Unretained(this));
  pref_change_filters_[prefs::kBrowserAddPersonEnabled] =
      base::Bind(&CoreOptionsHandler::IsUserUnsupervised,
                 base::Unretained(this));
}

void CoreOptionsHandler::InitializePage() {
  UpdateClearPluginLSOData();
  UpdatePepperFlashSettingsEnabled();
}

void CoreOptionsHandler::GetLocalizedValues(
    base::DictionaryValue* localized_strings) {
  GetStaticLocalizedValues(localized_strings);
}

void CoreOptionsHandler::GetStaticLocalizedValues(
    base::DictionaryValue* localized_strings) {
  DCHECK(localized_strings);
  // Main
  localized_strings->SetString("optionsPageTitle",
      l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE));

  // Controlled settings bubble.
  localized_strings->SetString("controlledSettingPolicy",
      l10n_util::GetStringUTF16(IDS_OPTIONS_CONTROLLED_SETTING_POLICY));
  localized_strings->SetString("controlledSettingExtension",
      l10n_util::GetStringUTF16(IDS_OPTIONS_CONTROLLED_SETTING_EXTENSION));
  localized_strings->SetString("controlledSettingExtensionWithName",
      l10n_util::GetStringUTF16(
          IDS_OPTIONS_CONTROLLED_SETTING_EXTENSION_WITH_NAME));
  localized_strings->SetString("controlledSettingManageExtension",
      l10n_util::GetStringUTF16(
          IDS_OPTIONS_CONTROLLED_SETTING_MANAGE_EXTENSION));
  localized_strings->SetString("controlledSettingDisableExtension",
      l10n_util::GetStringUTF16(IDS_EXTENSIONS_DISABLE));
  localized_strings->SetString("controlledSettingRecommended",
      l10n_util::GetStringUTF16(IDS_OPTIONS_CONTROLLED_SETTING_RECOMMENDED));
  localized_strings->SetString("controlledSettingHasRecommendation",
      l10n_util::GetStringUTF16(
          IDS_OPTIONS_CONTROLLED_SETTING_HAS_RECOMMENDATION));
  localized_strings->SetString("controlledSettingFollowRecommendation",
      l10n_util::GetStringUTF16(
          IDS_OPTIONS_CONTROLLED_SETTING_FOLLOW_RECOMMENDATION));
  localized_strings->SetString("controlledSettingsPolicy",
      l10n_util::GetStringUTF16(IDS_OPTIONS_CONTROLLED_SETTINGS_POLICY));
  localized_strings->SetString("controlledSettingsExtension",
      l10n_util::GetStringUTF16(IDS_OPTIONS_CONTROLLED_SETTINGS_EXTENSION));
  localized_strings->SetString("controlledSettingsExtensionWithName",
      l10n_util::GetStringUTF16(
          IDS_OPTIONS_CONTROLLED_SETTINGS_EXTENSION_WITH_NAME));

  // Search
  RegisterTitle(localized_strings, "searchPage", IDS_OPTIONS_SEARCH_PAGE_TITLE);
  localized_strings->SetString("searchPlaceholder",
      l10n_util::GetStringUTF16(IDS_OPTIONS_SEARCH_PLACEHOLDER));
  localized_strings->SetString("searchPageNoMatches",
      l10n_util::GetStringUTF16(IDS_OPTIONS_SEARCH_PAGE_NO_MATCHES));
  localized_strings->SetString("searchPageHelpLabel",
      l10n_util::GetStringUTF16(IDS_OPTIONS_SEARCH_PAGE_HELP_LABEL));
  localized_strings->SetString("searchPageHelpTitle",
      l10n_util::GetStringFUTF16(IDS_OPTIONS_SEARCH_PAGE_HELP_TITLE,
          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
  localized_strings->SetString("searchPageHelpURL",
                               chrome::kSettingsSearchHelpURL);

  // About
  localized_strings->SetString("aboutButton",
                               l10n_util::GetStringUTF16(IDS_ABOUT_BUTTON));

  // Common
  localized_strings->SetString("ok",
      l10n_util::GetStringUTF16(IDS_OK));
  localized_strings->SetString("cancel",
      l10n_util::GetStringUTF16(IDS_CANCEL));
  localized_strings->SetString("learnMore",
      l10n_util::GetStringUTF16(IDS_LEARN_MORE));
  localized_strings->SetString("close",
      l10n_util::GetStringUTF16(IDS_CLOSE));
  localized_strings->SetString("done",
      l10n_util::GetStringUTF16(IDS_DONE));
  localized_strings->SetString("deletableItemDeleteButtonTitle",
      l10n_util::GetStringUTF16(IDS_OPTIONS_DELETABLE_ITEM_DELETE_BUTTON));
}

void CoreOptionsHandler::Uninitialize() {
  std::string last_pref;
  for (PreferenceCallbackMap::const_iterator iter = pref_callback_map_.begin();
       iter != pref_callback_map_.end();
       ++iter) {
    if (last_pref != iter->first) {
      StopObservingPref(iter->first);
      last_pref = iter->first;
    }
  }
}

void CoreOptionsHandler::OnPreferenceChanged(PrefService* service,
                                             const std::string& pref_name) {
  if (pref_name == prefs::kClearPluginLSODataEnabled) {
    // This preference is stored in Local State, not in the user preferences.
    UpdateClearPluginLSOData();
    return;
  }
  if (pref_name == prefs::kPepperFlashSettingsEnabled) {
    UpdatePepperFlashSettingsEnabled();
    return;
  }
  NotifyPrefChanged(pref_name, std::string());
}

void CoreOptionsHandler::RegisterMessages() {
  registrar_.Init(Profile::FromWebUI(web_ui())->GetPrefs());
  local_state_registrar_.Init(g_browser_process->local_state());

  web_ui()->RegisterMessageCallback("coreOptionsInitialize",
      base::Bind(&CoreOptionsHandler::HandleInitialize,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("onFinishedLoadingOptions",
      base::Bind(&CoreOptionsHandler::OnFinishedLoading,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("fetchPrefs",
      base::Bind(&CoreOptionsHandler::HandleFetchPrefs,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("observePrefs",
      base::Bind(&CoreOptionsHandler::HandleObservePrefs,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("setBooleanPref",
      base::Bind(&CoreOptionsHandler::HandleSetBooleanPref,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("setIntegerPref",
      base::Bind(&CoreOptionsHandler::HandleSetIntegerPref,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("setDoublePref",
      base::Bind(&CoreOptionsHandler::HandleSetDoublePref,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("setStringPref",
      base::Bind(&CoreOptionsHandler::HandleSetStringPref,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("setURLPref",
      base::Bind(&CoreOptionsHandler::HandleSetURLPref,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("setListPref",
      base::Bind(&CoreOptionsHandler::HandleSetListPref,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("clearPref",
      base::Bind(&CoreOptionsHandler::HandleClearPref,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("coreOptionsUserMetricsAction",
      base::Bind(&CoreOptionsHandler::HandleUserMetricsAction,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("disableExtension",
      base::Bind(&CoreOptionsHandler::HandleDisableExtension,
                 base::Unretained(this)));
}

void CoreOptionsHandler::HandleInitialize(const base::ListValue* args) {
  DCHECK(handlers_host_);
  handlers_host_->InitializeHandlers();
}

void CoreOptionsHandler::OnFinishedLoading(const base::ListValue* args) {
  DCHECK(handlers_host_);
  handlers_host_->OnFinishedLoading();
}

std::unique_ptr<base::Value> CoreOptionsHandler::FetchPref(
    const std::string& pref_name) {
  return CreateValueForPref(pref_name, std::string());
}

void CoreOptionsHandler::ObservePref(const std::string& pref_name) {
  if (g_browser_process->local_state()->FindPreference(pref_name)) {
    local_state_registrar_.Add(
        pref_name,
        base::Bind(&CoreOptionsHandler::OnPreferenceChanged,
                   base::Unretained(this),
                   local_state_registrar_.prefs()));
  }
  // TODO(pneubeck): change this to if/else once kProxy is only used as a user
  // pref. Currently, it is both a user and a local state pref.
  if (Profile::FromWebUI(web_ui())->GetPrefs()->FindPreference(pref_name)) {
    registrar_.Add(
        pref_name,
        base::Bind(&CoreOptionsHandler::OnPreferenceChanged,
                   base::Unretained(this),
                   registrar_.prefs()));
  }
}

void CoreOptionsHandler::StopObservingPref(const std::string& pref_name) {
  if (g_browser_process->local_state()->FindPreference(pref_name))
    local_state_registrar_.Remove(pref_name);
  else
    registrar_.Remove(pref_name);
}

void CoreOptionsHandler::SetPref(const std::string& pref_name,
                                 const base::Value* value,
                                 const std::string& metric) {
  PrefService* pref_service = FindServiceForPref(pref_name);
  PrefChangeFilterMap::iterator iter = pref_change_filters_.find(pref_name);
  if (iter != pref_change_filters_.end()) {
    // Also check if the pref is user modifiable (don't even try to run the
    // filter function if the user is not allowed to change the pref).
    const PrefService::Preference* pref =
        pref_service->FindPreference(pref_name);
    if ((pref && !pref->IsUserModifiable()) || !iter->second.Run(value)) {
      // Reject the change; remind the page of the true value.
      NotifyPrefChanged(pref_name, std::string());
      return;
    }
  }

  switch (value->GetType()) {
    case base::Value::Type::BOOLEAN:
    case base::Value::Type::INTEGER:
    case base::Value::Type::DOUBLE:
    case base::Value::Type::STRING:
    case base::Value::Type::LIST:
      pref_service->Set(pref_name, *value);
      break;

    default:
      NOTREACHED();
      return;
  }

  ProcessUserMetric(value, metric);
}

void CoreOptionsHandler::ClearPref(const std::string& pref_name,
                                   const std::string& metric) {
  PrefService* pref_service = FindServiceForPref(pref_name);
  pref_service->ClearPref(pref_name);

  if (!metric.empty())
    base::RecordComputedAction(metric);
}

void CoreOptionsHandler::ProcessUserMetric(const base::Value* value,
                                           const std::string& metric) {
  if (metric.empty())
    return;

  std::string metric_string = metric;
  if (value->IsType(base::Value::Type::BOOLEAN)) {
    bool bool_value;
    CHECK(value->GetAsBoolean(&bool_value));
    metric_string += bool_value ? "_Enable" : "_Disable";
  }

  base::RecordComputedAction(metric_string);
}

void CoreOptionsHandler::NotifyPrefChanged(
    const std::string& pref_name,
    const std::string& controlling_pref_name) {
  std::unique_ptr<base::Value> value(
      CreateValueForPref(pref_name, controlling_pref_name));
  DispatchPrefChangeNotification(pref_name, std::move(value));
}

void CoreOptionsHandler::DispatchPrefChangeNotification(
    const std::string& name,
    std::unique_ptr<base::Value> value) {
  std::pair<PreferenceCallbackMap::const_iterator,
            PreferenceCallbackMap::const_iterator> range =
      pref_callback_map_.equal_range(name);
  base::ListValue result_value;
  result_value.AppendString(name);
  result_value.Append(std::move(value));
  for (PreferenceCallbackMap::const_iterator iter = range.first;
       iter != range.second; ++iter) {
    const std::string& callback_function = iter->second;
    web_ui()->CallJavascriptFunctionUnsafe(callback_function, result_value);
  }
}

std::unique_ptr<base::Value> CoreOptionsHandler::CreateValueForPref(
    const std::string& pref_name,
    const std::string& controlling_pref_name) {
  const PrefService* pref_service = FindServiceForPref(pref_name);
  const PrefService::Preference* pref =
      pref_service->FindPreference(pref_name);
  if (!pref) {
    NOTREACHED();
    return base::MakeUnique<base::Value>();
  }
  const PrefService::Preference* controlling_pref =
      pref_service->FindPreference(controlling_pref_name);
  if (!controlling_pref)
    controlling_pref = pref;

  auto dict = base::MakeUnique<base::DictionaryValue>();
  dict->Set("value", base::MakeUnique<base::Value>(*pref->GetValue()));
  if (controlling_pref->IsManaged()) {
    dict->SetString("controlledBy", "policy");
  } else if (controlling_pref->IsExtensionControlled() &&
             CanSetExtensionControlledPrefValue(controlling_pref)) {
    Profile* profile = Profile::FromWebUI(web_ui());
    ExtensionPrefValueMap* extension_pref_value_map =
        ExtensionPrefValueMapFactory::GetForBrowserContext(profile);
    std::string extension_id =
        extension_pref_value_map->GetExtensionControllingPref(
            controlling_pref->name());

    const extensions::Extension* extension =
        extensions::ExtensionRegistry::Get(profile)->GetExtensionById(
            extension_id, extensions::ExtensionRegistry::EVERYTHING);
    if (extension) {
      dict->SetString("controlledBy", "extension");
      dict->Set("extension", extensions::util::GetExtensionInfo(extension));
    }
  } else if (controlling_pref->IsRecommended()) {
    dict->SetString("controlledBy", "recommended");
  }

  const base::Value* recommended_value =
      controlling_pref->GetRecommendedValue();
  if (recommended_value)
    dict->Set("recommendedValue",
              base::MakeUnique<base::Value>(*recommended_value));
  dict->SetBoolean("disabled", !controlling_pref->IsUserModifiable());
  return std::move(dict);
}

PrefService* CoreOptionsHandler::FindServiceForPref(
    const std::string& pref_name) {
  // Proxy is a peculiar case: on ChromeOS, settings exist in both user
  // prefs and local state, but chrome://settings should affect only user prefs.
  // Elsewhere the proxy settings are stored in local state.
  // See http://crbug.com/157147
  PrefService* user_prefs = Profile::FromWebUI(web_ui())->GetPrefs();
  if (pref_name == proxy_config::prefs::kProxy)
#if defined(OS_CHROMEOS)
    return user_prefs;
#else
    return g_browser_process->local_state();
#endif

  // Find which PrefService contains the given pref. Pref names should not
  // be duplicated across services, however if they are, prefer the user's
  // prefs.
  if (user_prefs->FindPreference(pref_name))
    return user_prefs;

  if (g_browser_process->local_state()->FindPreference(pref_name))
    return g_browser_process->local_state();

  return user_prefs;
}

void CoreOptionsHandler::HandleFetchPrefs(const base::ListValue* args) {
  // First param is name of callback function, so, there needs to be at least
  // one more element for the actual preference identifier.
  DCHECK_GE(static_cast<int>(args->GetSize()), 2);

  // Get callback JS function name.
  const base::Value* callback;
  if (!args->Get(0, &callback) || !callback->IsType(base::Value::Type::STRING))
    return;

  base::string16 callback_function;
  if (!callback->GetAsString(&callback_function))
    return;

  // Get the list of name for prefs to build the response dictionary.
  base::DictionaryValue result_value;
  const base::Value* list_member;

  for (size_t i = 1; i < args->GetSize(); i++) {
    if (!args->Get(i, &list_member))
      break;

    if (!list_member->IsType(base::Value::Type::STRING))
      continue;

    std::string pref_name;
    if (!list_member->GetAsString(&pref_name))
      continue;

    result_value.Set(pref_name, FetchPref(pref_name));
  }
  web_ui()->CallJavascriptFunctionUnsafe(base::UTF16ToASCII(callback_function),
                                         result_value);
}

void CoreOptionsHandler::HandleObservePrefs(const base::ListValue* args) {
  // First param is name is JS callback function name, the rest are pref
  // identifiers that we are observing.
  DCHECK_GE(static_cast<int>(args->GetSize()), 2);

  // Get preference change callback function name.
  std::string callback_func_name;
  if (!args->GetString(0, &callback_func_name))
    return;

  // Get all other parameters - pref identifiers.
  for (size_t i = 1; i < args->GetSize(); i++) {
    const base::Value* list_member;
    if (!args->Get(i, &list_member))
      break;

    // Just ignore bad pref identifiers for now.
    std::string pref_name;
    if (!list_member->IsType(base::Value::Type::STRING) ||
        !list_member->GetAsString(&pref_name))
      continue;

    if (pref_callback_map_.find(pref_name) == pref_callback_map_.end())
      ObservePref(pref_name);

    pref_callback_map_.insert(
        PreferenceCallbackMap::value_type(pref_name, callback_func_name));
  }
}

void CoreOptionsHandler::HandleSetBooleanPref(const base::ListValue* args) {
  HandleSetPref(args, TYPE_BOOLEAN);
}

void CoreOptionsHandler::HandleSetIntegerPref(const base::ListValue* args) {
  HandleSetPref(args, TYPE_INTEGER);
}

void CoreOptionsHandler::HandleSetDoublePref(const base::ListValue* args) {
  HandleSetPref(args, TYPE_DOUBLE);
}

void CoreOptionsHandler::HandleSetStringPref(const base::ListValue* args) {
  HandleSetPref(args, TYPE_STRING);
}

void CoreOptionsHandler::HandleSetURLPref(const base::ListValue* args) {
  HandleSetPref(args, TYPE_URL);
}

void CoreOptionsHandler::HandleSetListPref(const base::ListValue* args) {
  HandleSetPref(args, TYPE_LIST);
}

void CoreOptionsHandler::HandleSetPref(const base::ListValue* args,
                                       PrefType type) {
  DCHECK_GT(static_cast<int>(args->GetSize()), 1);

  std::string pref_name;
  if (!args->GetString(0, &pref_name))
    return;

  const base::Value* value;
  if (!args->Get(1, &value))
    return;

  std::unique_ptr<base::Value> temp_value;

  switch (type) {
    case TYPE_BOOLEAN:
      if (!value->IsType(base::Value::Type::BOOLEAN)) {
        NOTREACHED();
        return;
      }
      break;
    case TYPE_INTEGER: {
      // In JS all numbers are doubles.
      double double_value;
      if (!value->GetAsDouble(&double_value)) {
        NOTREACHED();
        return;
      }
      int int_value = static_cast<int>(double_value);
      temp_value.reset(new base::Value(int_value));
      value = temp_value.get();
      break;
    }
    case TYPE_DOUBLE:
      if (!value->IsType(base::Value::Type::DOUBLE)) {
        NOTREACHED();
        return;
      }
      break;
    case TYPE_STRING:
      if (!value->IsType(base::Value::Type::STRING)) {
        NOTREACHED();
        return;
      }
      break;
    case TYPE_URL: {
      std::string original;
      if (!value->GetAsString(&original)) {
        NOTREACHED();
        return;
      }
      GURL fixed = url_formatter::FixupURL(original, std::string());
      temp_value.reset(new base::Value(fixed.spec()));
      value = temp_value.get();
      break;
    }
    case TYPE_LIST: {
      // In case we have a List pref we got a JSON string.
      std::string json_string;
      if (!value->GetAsString(&json_string)) {
        NOTREACHED();
        return;
      }
      temp_value = base::JSONReader::Read(json_string);
      value = temp_value.get();
      if (!value || !value->IsType(base::Value::Type::LIST)) {
        NOTREACHED();
        return;
      }
      break;
    }
    default:
      NOTREACHED();
  }

  std::string metric;
  if (args->GetSize() > 2 && !args->GetString(2, &metric))
    LOG(WARNING) << "Invalid metric parameter: " << pref_name;
  SetPref(pref_name, value, metric);
}

void CoreOptionsHandler::HandleClearPref(const base::ListValue* args) {
  DCHECK_GT(static_cast<int>(args->GetSize()), 0);

  std::string pref_name;
  if (!args->GetString(0, &pref_name))
    return;

  std::string metric;
  if (args->GetSize() > 1) {
    if (!args->GetString(1, &metric))
      NOTREACHED();
  }

  ClearPref(pref_name, metric);
}

void CoreOptionsHandler::HandleUserMetricsAction(const base::ListValue* args) {
  std::string metric = base::UTF16ToUTF8(ExtractStringValue(args));
  if (!metric.empty())
    base::RecordComputedAction(metric);
}

void CoreOptionsHandler::HandleDisableExtension(const base::ListValue* args) {
  std::string extension_id;
  if (args->GetString(0, &extension_id)) {
    ExtensionService* extension_service = extensions::ExtensionSystem::Get(
        Profile::FromWebUI(web_ui()))->extension_service();
    DCHECK(extension_service);
    extension_service->DisableExtension(
        extension_id, extensions::Extension::DISABLE_USER_ACTION);
  } else {
    NOTREACHED();
  }
}

void CoreOptionsHandler::UpdateClearPluginLSOData() {
  base::Value enabled(plugin_status_pref_setter_.IsClearPluginLSODataEnabled());
  web_ui()->CallJavascriptFunctionUnsafe(
      "options.OptionsPage.setClearPluginLSODataEnabled", enabled);
}

void CoreOptionsHandler::UpdatePepperFlashSettingsEnabled() {
  base::Value enabled(
      plugin_status_pref_setter_.IsPepperFlashSettingsEnabled());
  web_ui()->CallJavascriptFunctionUnsafe(
      "options.OptionsPage.setPepperFlashSettingsEnabled", enabled);
}

bool CoreOptionsHandler::IsUserUnsupervised(const base::Value* to_value) {
  return !Profile::FromWebUI(web_ui())->IsSupervised();
}

}  // namespace options
