// Copyright 2015 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/extensions/api/settings_private/prefs_util.h"

#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/proxy_config/proxy_config_pref_names.h"
#include "components/url_formatter/url_fixer.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/common/extension.h"

#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h"
#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chromeos/settings/cros_settings_names.h"
#endif

namespace {

#if defined(OS_CHROMEOS)
bool IsPrivilegedCrosSetting(const std::string& pref_name) {
  if (!chromeos::CrosSettings::IsCrosSettings(pref_name))
    return false;
  // kSystemTimezone should be changeable by all users.
  if (pref_name == chromeos::kSystemTimezone)
    return false;
  // All other Cros settings are considered privileged and are either policy
  // controlled or owner controlled.
  return true;
}
#endif

}  // namespace

namespace extensions {

namespace settings_private = api::settings_private;

PrefsUtil::PrefsUtil(Profile* profile) : profile_(profile) {}

PrefsUtil::~PrefsUtil() {}

#if defined(OS_CHROMEOS)
using CrosSettings = chromeos::CrosSettings;
#endif

const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
  static PrefsUtil::TypedPrefMap* s_whitelist = nullptr;
  if (s_whitelist)
    return *s_whitelist;
  // TODO(dbeam): why aren't we using kPrefName from pref_names.h?
  s_whitelist = new PrefsUtil::TypedPrefMap();
  (*s_whitelist)["alternate_error_pages.enabled"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["autofill.enabled"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["bookmark_bar.show_on_all_tabs"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["browser.show_home_button"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;

  // Downloads settings.
  (*s_whitelist)["download.default_directory"] =
      settings_private::PrefType::PREF_TYPE_STRING;
  (*s_whitelist)["download.prompt_for_download"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["gdata.disabled"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;

  (*s_whitelist)["enable_do_not_track"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["homepage"] = settings_private::PrefType::PREF_TYPE_URL;
  (*s_whitelist)["homepage_is_newtabpage"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["intl.app_locale"] =
      settings_private::PrefType::PREF_TYPE_STRING;
  (*s_whitelist)["net.network_prediction_options"] =
      settings_private::PrefType::PREF_TYPE_NUMBER;
  (*s_whitelist)["profile.password_manager_allow_show_passwords"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["profile.password_manager_enabled"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["safebrowsing.enabled"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["safebrowsing.extended_reporting_enabled"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["search.suggest_enabled"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["session.restore_on_startup"] =
      settings_private::PrefType::PREF_TYPE_NUMBER;
  (*s_whitelist)["session.startup_urls"] =
      settings_private::PrefType::PREF_TYPE_LIST;
  (*s_whitelist)["spellcheck.dictionaries"] =
      settings_private::PrefType::PREF_TYPE_LIST;
  (*s_whitelist)["spellcheck.use_spelling_service"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["translate.enabled"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["translate_blocked_languages"] =
      settings_private::PrefType::PREF_TYPE_LIST;

  // Clear browsing data settings.
  (*s_whitelist)["browser.clear_data.browsing_history"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["browser.clear_data.download_history"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["browser.clear_data.cache"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["browser.clear_data.cookies"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["browser.clear_data.passwords"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["browser.clear_data.form_data"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["browser.clear_data.hosted_apps_data"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["browser.clear_data.content_licenses"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["browser.clear_data.time_period"] =
      settings_private::PrefType::PREF_TYPE_NUMBER;
  (*s_whitelist)["profile.default_content_setting_values.cookies"] =
      settings_private::PrefType::PREF_TYPE_NUMBER;
  (*s_whitelist)["profile.default_content_setting_values.fullscreen"] =
      settings_private::PrefType::PREF_TYPE_NUMBER;
  (*s_whitelist)["profile.default_content_setting_values.geolocation"] =
      settings_private::PrefType::PREF_TYPE_NUMBER;
  (*s_whitelist)["profile.default_content_setting_values.images"] =
      settings_private::PrefType::PREF_TYPE_NUMBER;
  (*s_whitelist)["profile.default_content_setting_values.javascript"] =
      settings_private::PrefType::PREF_TYPE_NUMBER;
  (*s_whitelist)["profile.default_content_setting_values.media_stream_camera"] =
      settings_private::PrefType::PREF_TYPE_NUMBER;
  (*s_whitelist)["profile.default_content_setting_values.media_stream_mic"] =
      settings_private::PrefType::PREF_TYPE_NUMBER;
  (*s_whitelist)["profile.default_content_setting_values.notifications"] =
      settings_private::PrefType::PREF_TYPE_NUMBER;
  (*s_whitelist)["profile.default_content_setting_values.popups"] =
      settings_private::PrefType::PREF_TYPE_NUMBER;
  (*s_whitelist)["profile.content_settings.exceptions.cookies"] =
      settings_private::PrefType::PREF_TYPE_DICTIONARY;
  (*s_whitelist)["profile.content_settings.exceptions.fullscreen"] =
      settings_private::PrefType::PREF_TYPE_DICTIONARY;
  (*s_whitelist)["profile.content_settings.exceptions.geolocation"] =
      settings_private::PrefType::PREF_TYPE_DICTIONARY;
  (*s_whitelist)["profile.content_settings.exceptions.images"] =
      settings_private::PrefType::PREF_TYPE_DICTIONARY;
  (*s_whitelist)["profile.content_settings.exceptions.javascript"] =
      settings_private::PrefType::PREF_TYPE_DICTIONARY;
  (*s_whitelist)["profile.content_settings.exceptions.media_stream_camera"] =
      settings_private::PrefType::PREF_TYPE_DICTIONARY;
  (*s_whitelist)["profile.content_settings.exceptions.media_stream_mic"] =
      settings_private::PrefType::PREF_TYPE_DICTIONARY;
  (*s_whitelist)["profile.content_settings.exceptions.notifications"] =
      settings_private::PrefType::PREF_TYPE_DICTIONARY;
  (*s_whitelist)["profile.content_settings.exceptions.popups"] =
      settings_private::PrefType::PREF_TYPE_DICTIONARY;

  // Web content settings.
  (*s_whitelist)["webkit.webprefs.default_font_size"] =
      settings_private::PrefType::PREF_TYPE_NUMBER;
  (*s_whitelist)["webkit.webprefs.minimum_font_size"] =
      settings_private::PrefType::PREF_TYPE_NUMBER;
  (*s_whitelist)["webkit.webprefs.fonts.fixed.Zyyy"] =
      settings_private::PrefType::PREF_TYPE_STRING;
  (*s_whitelist)["webkit.webprefs.fonts.sansserif.Zyyy"] =
      settings_private::PrefType::PREF_TYPE_STRING;
  (*s_whitelist)["webkit.webprefs.fonts.serif.Zyyy"] =
      settings_private::PrefType::PREF_TYPE_STRING;
  (*s_whitelist)["webkit.webprefs.fonts.standard.Zyyy"] =
      settings_private::PrefType::PREF_TYPE_STRING;
  (*s_whitelist)["intl.charset_default"] =
      settings_private::PrefType::PREF_TYPE_STRING;

#if defined(OS_CHROMEOS)
  (*s_whitelist)["cros.accounts.allowBWSI"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["cros.accounts.supervisedUsersEnabled"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["cros.accounts.showUserNamesOnSignIn"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["cros.accounts.allowGuest"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["cros.accounts.users"] =
      settings_private::PrefType::PREF_TYPE_LIST;
  (*s_whitelist)["settings.accessibility"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["settings.a11y.autoclick"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["settings.a11y.autoclick_delay_ms"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["settings.a11y.caret_highlight"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["settings.a11y.cursor_highlight"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["settings.a11y.enable_menu"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["settings.a11y.focus_highlight"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["settings.a11y.high_contrast_enabled"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["settings.a11y.large_cursor_enabled"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["settings.a11y.screen_magnifier"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["settings.a11y.select_to_speak"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["settings.a11y.sticky_keys_enabled"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["settings.a11y.switch_access"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["settings.a11y.virtual_keyboard"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["settings.clock.use_24hour_clock"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["settings.language.preferred_languages"] =
      settings_private::PrefType::PREF_TYPE_STRING;
  (*s_whitelist)["settings.touchpad.enable_tap_dragging"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["cros.metrics.reportingEnabled"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["cros.device.attestation_for_content_protection_enabled"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["settings.internet.wake_on_wifi_darkconnect"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["settings.enable_screen_lock"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;

  // Input settings.
  (*s_whitelist)["settings.touchpad.enable_tap_to_click"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["settings.touchpad.natural_scroll"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["settings.language.xkb_remap_search_key_to"] =
      settings_private::PrefType::PREF_TYPE_NUMBER;
  (*s_whitelist)["settings.language.xkb_remap_control_key_to"] =
      settings_private::PrefType::PREF_TYPE_NUMBER;
  (*s_whitelist)["settings.language.xkb_remap_alt_key_to"] =
      settings_private::PrefType::PREF_TYPE_NUMBER;
  (*s_whitelist)["settings.language.remap_caps_lock_key_to"] =
      settings_private::PrefType::PREF_TYPE_NUMBER;
  (*s_whitelist)["settings.language.remap_diamond_key_to"] =
      settings_private::PrefType::PREF_TYPE_NUMBER;
  (*s_whitelist)["settings.language.send_function_keys"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
#else
  (*s_whitelist)["intl.accept_languages"] =
      settings_private::PrefType::PREF_TYPE_STRING;

  // System settings.
  (*s_whitelist)["background_mode.enabled"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
  (*s_whitelist)["hardware_acceleration_mode.enabled"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
#endif

#if defined(GOOGLE_CHROME_BUILD)
  (*s_whitelist)["media_router.cloudservices.enabled"] =
      settings_private::PrefType::PREF_TYPE_BOOLEAN;
#endif  // defined(GOOGLE_CHROME_BUILD)

  return *s_whitelist;
}

settings_private::PrefType PrefsUtil::GetType(const std::string& name,
                                              base::Value::Type type) {
  switch (type) {
    case base::Value::Type::TYPE_BOOLEAN:
      return settings_private::PrefType::PREF_TYPE_BOOLEAN;
    case base::Value::Type::TYPE_INTEGER:
    case base::Value::Type::TYPE_DOUBLE:
      return settings_private::PrefType::PREF_TYPE_NUMBER;
    case base::Value::Type::TYPE_STRING:
      return IsPrefTypeURL(name) ? settings_private::PrefType::PREF_TYPE_URL
                                 : settings_private::PrefType::PREF_TYPE_STRING;
    case base::Value::Type::TYPE_LIST:
      return settings_private::PrefType::PREF_TYPE_LIST;
    case base::Value::Type::TYPE_DICTIONARY:
      return settings_private::PrefType::PREF_TYPE_DICTIONARY;
    default:
      return settings_private::PrefType::PREF_TYPE_NONE;
  }
}

scoped_ptr<settings_private::PrefObject> PrefsUtil::GetCrosSettingsPref(
    const std::string& name) {
  scoped_ptr<settings_private::PrefObject> pref_object(
      new settings_private::PrefObject());

#if defined(OS_CHROMEOS)
  const base::Value* value = CrosSettings::Get()->GetPref(name);
  DCHECK(value);
  pref_object->key = name;
  pref_object->type = GetType(name, value->GetType());
  pref_object->value.reset(value->DeepCopy());
#endif

  return pref_object;
}

scoped_ptr<settings_private::PrefObject> PrefsUtil::GetPref(
    const std::string& name) {
  const PrefService::Preference* pref = nullptr;
  scoped_ptr<settings_private::PrefObject> pref_object;
  if (IsCrosSetting(name)) {
    pref_object = GetCrosSettingsPref(name);
  } else {
    PrefService* pref_service = FindServiceForPref(name);
    pref = pref_service->FindPreference(name);
    if (!pref)
      return nullptr;
    pref_object.reset(new settings_private::PrefObject());
    pref_object->key = pref->name();
    pref_object->type = GetType(name, pref->GetType());
    pref_object->value.reset(pref->GetValue()->DeepCopy());
  }

#if defined(OS_CHROMEOS)
  if (IsPrefPrimaryUserControlled(name)) {
    pref_object->policy_source =
        settings_private::PolicySource::POLICY_SOURCE_PRIMARY_USER;
    pref_object->policy_enforcement =
        settings_private::PolicyEnforcement::POLICY_ENFORCEMENT_ENFORCED;
    pref_object->policy_source_name.reset(new std::string(
        user_manager::UserManager::Get()->GetPrimaryUser()->email()));
    return pref_object;
  }
  if (IsPrefEnterpriseManaged(name)) {
    // Enterprise managed prefs are treated the same as device policy restricted
    // prefs in the UI.
    pref_object->policy_source =
        settings_private::PolicySource::POLICY_SOURCE_DEVICE_POLICY;
    pref_object->policy_enforcement =
        settings_private::PolicyEnforcement::POLICY_ENFORCEMENT_ENFORCED;
    return pref_object;
  }
#endif

  if (pref && pref->IsManaged()) {
    pref_object->policy_source =
        settings_private::PolicySource::POLICY_SOURCE_USER_POLICY;
    pref_object->policy_enforcement =
        settings_private::PolicyEnforcement::POLICY_ENFORCEMENT_ENFORCED;
    return pref_object;
  }
  if (pref && pref->IsRecommended()) {
    pref_object->policy_source =
        settings_private::PolicySource::POLICY_SOURCE_USER_POLICY;
    pref_object->policy_enforcement =
        settings_private::PolicyEnforcement::POLICY_ENFORCEMENT_RECOMMENDED;
    pref_object->recommended_value.reset(
        pref->GetRecommendedValue()->DeepCopy());
    return pref_object;
  }

#if defined(OS_CHROMEOS)
  if (IsPrefOwnerControlled(name)) {
    // Check for owner controlled after managed checks because if there is a
    // device policy there is no "owner". (In the unlikely case that both
    // situations apply, either badge is potentially relevant, so the order
    // is somewhat arbitrary).
    pref_object->policy_source =
        settings_private::PolicySource::POLICY_SOURCE_OWNER;
    pref_object->policy_enforcement =
        settings_private::PolicyEnforcement::POLICY_ENFORCEMENT_ENFORCED;
    pref_object->policy_source_name.reset(new std::string(
        user_manager::UserManager::Get()->GetOwnerAccountId().GetUserEmail()));
    return pref_object;
  }
#endif

  if (pref && pref->IsExtensionControlled()) {
    std::string extension_id =
        ExtensionPrefValueMapFactory::GetForBrowserContext(profile_)
            ->GetExtensionControllingPref(pref->name());
    const Extension* extension = ExtensionRegistry::Get(profile_)->
        GetExtensionById(extension_id, ExtensionRegistry::ENABLED);
    if (extension) {
      pref_object->policy_source =
          settings_private::PolicySource::POLICY_SOURCE_EXTENSION;
      pref_object->policy_enforcement =
          settings_private::PolicyEnforcement::POLICY_ENFORCEMENT_ENFORCED;
      pref_object->extension_id.reset(new std::string(extension_id));
      pref_object->policy_source_name.reset(new std::string(extension->name()));
      return pref_object;
    }
  }
  if (pref && (!pref->IsUserModifiable() || IsPrefSupervisorControlled(name))) {
    // TODO(stevenjb): Investigate whether either of these should be badged.
    pref_object->read_only.reset(new bool(true));
    return pref_object;
  }

  return pref_object;
}

PrefsUtil::SetPrefResult PrefsUtil::SetPref(const std::string& pref_name,
                                            const base::Value* value) {
  if (IsCrosSetting(pref_name))
    return SetCrosSettingsPref(pref_name, value);

  PrefService* pref_service = FindServiceForPref(pref_name);

  if (!IsPrefUserModifiable(pref_name))
    return PREF_NOT_MODIFIABLE;

  const PrefService::Preference* pref = pref_service->FindPreference(pref_name);
  if (!pref)
    return PREF_NOT_FOUND;

  DCHECK_EQ(pref->GetType(), value->GetType());

  switch (pref->GetType()) {
    case base::Value::TYPE_BOOLEAN:
    case base::Value::TYPE_DOUBLE:
    case base::Value::TYPE_LIST:
    case base::Value::TYPE_DICTIONARY:
      pref_service->Set(pref_name, *value);
      break;
    case base::Value::TYPE_INTEGER: {
      // In JS all numbers are doubles.
      double double_value;
      if (!value->GetAsDouble(&double_value))
        return PREF_TYPE_MISMATCH;

      pref_service->SetInteger(pref_name, static_cast<int>(double_value));
      break;
    }
    case base::Value::TYPE_STRING: {
      std::string string_value;
      if (!value->GetAsString(&string_value))
        return PREF_TYPE_MISMATCH;

      if (IsPrefTypeURL(pref_name)) {
        GURL fixed = url_formatter::FixupURL(string_value, std::string());
        if (fixed.is_valid())
          string_value = fixed.spec();
        else
          string_value = std::string();
      }

      pref_service->SetString(pref_name, string_value);
      break;
    }
    default:
      return PREF_TYPE_UNSUPPORTED;
  }

  // TODO(orenb): Process setting metrics here and in the CrOS setting method
  // too (like "ProcessUserMetric" in CoreOptionsHandler).
  return SUCCESS;
}

PrefsUtil::SetPrefResult PrefsUtil::SetCrosSettingsPref(
    const std::string& pref_name, const base::Value* value) {
#if defined(OS_CHROMEOS)
  chromeos::OwnerSettingsServiceChromeOS* service =
      chromeos::OwnerSettingsServiceChromeOSFactory::GetForBrowserContext(
          profile_);

  // Check if setting requires owner.
  if (service && service->HandlesSetting(pref_name)) {
    if (service->Set(pref_name, *value))
      return SUCCESS;
    return PREF_NOT_MODIFIABLE;
  }

  CrosSettings::Get()->Set(pref_name, *value);
  return SUCCESS;
#else
  return PREF_NOT_FOUND;
#endif
}

bool PrefsUtil::AppendToListCrosSetting(const std::string& pref_name,
                                        const base::Value& value) {
#if defined(OS_CHROMEOS)
  chromeos::OwnerSettingsServiceChromeOS* service =
      chromeos::OwnerSettingsServiceChromeOSFactory::GetForBrowserContext(
          profile_);

  // Returns false if not the owner, for settings requiring owner.
  if (service && service->HandlesSetting(pref_name)) {
    return service->AppendToList(pref_name, value);
  }

  CrosSettings::Get()->AppendToList(pref_name, &value);
  return true;
#else
  return false;
#endif
}

bool PrefsUtil::RemoveFromListCrosSetting(const std::string& pref_name,
                                          const base::Value& value) {
#if defined(OS_CHROMEOS)
  chromeos::OwnerSettingsServiceChromeOS* service =
      chromeos::OwnerSettingsServiceChromeOSFactory::GetForBrowserContext(
          profile_);

  // Returns false if not the owner, for settings requiring owner.
  if (service && service->HandlesSetting(pref_name)) {
    return service->RemoveFromList(pref_name, value);
  }

  CrosSettings::Get()->RemoveFromList(pref_name, &value);
  return true;
#else
  return false;
#endif
}

bool PrefsUtil::IsPrefTypeURL(const std::string& pref_name) {
  settings_private::PrefType pref_type =
      settings_private::PrefType::PREF_TYPE_NONE;

  const TypedPrefMap keys = GetWhitelistedKeys();
  const auto& iter = keys.find(pref_name);
  if (iter != keys.end())
    pref_type = iter->second;

  return pref_type == settings_private::PrefType::PREF_TYPE_URL;
}

#if defined(OS_CHROMEOS)
bool PrefsUtil::IsPrefEnterpriseManaged(const std::string& pref_name) {
  if (IsPrivilegedCrosSetting(pref_name)) {
    policy::BrowserPolicyConnectorChromeOS* connector =
        g_browser_process->platform_part()->browser_policy_connector_chromeos();
    if (connector->IsEnterpriseManaged())
      return true;
  }
  return false;
}

bool PrefsUtil::IsPrefOwnerControlled(const std::string& pref_name) {
  if (IsPrivilegedCrosSetting(pref_name)) {
    if (!chromeos::ProfileHelper::IsOwnerProfile(profile_))
      return true;
  }
  return false;
}

bool PrefsUtil::IsPrefPrimaryUserControlled(const std::string& pref_name) {
  if (pref_name == prefs::kWakeOnWifiDarkConnect) {
    user_manager::UserManager* user_manager = user_manager::UserManager::Get();
    const user_manager::User* user =
        chromeos::ProfileHelper::Get()->GetUserByProfile(profile_);
    if (user && user->email() != user_manager->GetPrimaryUser()->email())
      return true;
  }
  return false;
}
#endif

bool PrefsUtil::IsPrefSupervisorControlled(const std::string& pref_name) {
  if (pref_name != prefs::kBrowserGuestModeEnabled &&
      pref_name != prefs::kBrowserAddPersonEnabled) {
    return false;
  }
  return profile_->IsSupervised();
}

bool PrefsUtil::IsPrefUserModifiable(const std::string& pref_name) {
  const PrefService::Preference* profile_pref =
      profile_->GetPrefs()->FindPreference(pref_name);
  if (profile_pref)
    return profile_pref->IsUserModifiable();

  const PrefService::Preference* local_state_pref =
      g_browser_process->local_state()->FindPreference(pref_name);
  if (local_state_pref)
    return local_state_pref->IsUserModifiable();

  return false;
}

PrefService* PrefsUtil::FindServiceForPref(const std::string& pref_name) {
  PrefService* user_prefs = profile_->GetPrefs();

  // 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

  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;
}

bool PrefsUtil::IsCrosSetting(const std::string& pref_name) {
#if defined(OS_CHROMEOS)
  return CrosSettings::Get()->IsCrosSettings(pref_name);
#else
  return false;
#endif
}

}  // namespace extensions