// 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/content_settings_handler.h"

#include <map>
#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/prefs/pref_service.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/content_settings/content_settings_details.h"
#include "chrome/browser/content_settings/content_settings_utils.h"
#include "chrome/browser/content_settings/host_content_settings_map.h"
#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_special_storage_policy.h"
#include "chrome/browser/google/google_util.h"
#include "chrome/browser/notifications/desktop_notification_service.h"
#include "chrome/browser/notifications/desktop_notification_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/content_settings.h"
#include "chrome/common/content_settings_pattern.h"
#include "chrome/common/extensions/extension_set.h"
#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_ui.h"
#include "content/public/common/content_switches.h"
#include "extensions/common/permissions/api_permission.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "ui/base/l10n/l10n_util.h"

#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/login/user_manager.h"
#endif

using content::UserMetricsAction;
using extensions::APIPermission;

namespace {

struct ContentSettingsTypeNameEntry {
  ContentSettingsType type;
  const char* name;
};

// Maps from a secondary pattern to a setting.
typedef std::map<ContentSettingsPattern, ContentSetting>
    OnePatternSettings;
// Maps from a primary pattern/source pair to a OnePatternSettings. All the
// mappings in OnePatternSettings share the given primary pattern and source.
typedef std::map<std::pair<ContentSettingsPattern, std::string>,
                 OnePatternSettings>
    AllPatternsSettings;

// The AppFilter is used in AddExceptionsGrantedByHostedApps() to choose
// extensions which should have their extent displayed.
typedef bool (*AppFilter)(const extensions::Extension& app, Profile* profile);

const char kExceptionsLearnMoreUrl[] =
    "https://support.google.com/chrome/?p=settings_manage_exceptions";

const char* kSetting = "setting";
const char* kOrigin = "origin";
const char* kSource = "source";
const char* kAppName = "appName";
const char* kAppId = "appId";
const char* kEmbeddingOrigin = "embeddingOrigin";
const char* kPreferencesSource = "preference";
const char* kVideoSetting = "video";

const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames[] = {
  {CONTENT_SETTINGS_TYPE_COOKIES, "cookies"},
  {CONTENT_SETTINGS_TYPE_IMAGES, "images"},
  {CONTENT_SETTINGS_TYPE_JAVASCRIPT, "javascript"},
  {CONTENT_SETTINGS_TYPE_PLUGINS, "plugins"},
  {CONTENT_SETTINGS_TYPE_POPUPS, "popups"},
  {CONTENT_SETTINGS_TYPE_GEOLOCATION, "location"},
  {CONTENT_SETTINGS_TYPE_NOTIFICATIONS, "notifications"},
  {CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE, "auto-select-certificate"},
  {CONTENT_SETTINGS_TYPE_FULLSCREEN, "fullscreen"},
  {CONTENT_SETTINGS_TYPE_MOUSELOCK, "mouselock"},
  {CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS, "register-protocol-handler"},
  {CONTENT_SETTINGS_TYPE_MEDIASTREAM, "media-stream"},
  {CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, "media-stream-mic"},
  {CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, "media-stream-camera"},
  {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, "ppapi-broker"},
  {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, "multiple-automatic-downloads"},
  {CONTENT_SETTINGS_TYPE_MIDI_SYSEX, "midi-sysex"},
  {CONTENT_SETTINGS_TYPE_SAVE_PASSWORD, "save-password"},
};

ContentSettingsType ContentSettingsTypeFromGroupName(const std::string& name) {
  for (size_t i = 0; i < arraysize(kContentSettingsTypeGroupNames); ++i) {
    if (name == kContentSettingsTypeGroupNames[i].name)
      return kContentSettingsTypeGroupNames[i].type;
  }

  NOTREACHED() << name << " is not a recognized content settings type.";
  return CONTENT_SETTINGS_TYPE_DEFAULT;
}

std::string ContentSettingToString(ContentSetting setting) {
  switch (setting) {
    case CONTENT_SETTING_ALLOW:
      return "allow";
    case CONTENT_SETTING_ASK:
      return "ask";
    case CONTENT_SETTING_BLOCK:
      return "block";
    case CONTENT_SETTING_SESSION_ONLY:
      return "session";
    case CONTENT_SETTING_DEFAULT:
      return "default";
    case CONTENT_SETTING_NUM_SETTINGS:
      NOTREACHED();
  }

  return std::string();
}

ContentSetting ContentSettingFromString(const std::string& name) {
  if (name == "allow")
    return CONTENT_SETTING_ALLOW;
  if (name == "ask")
    return CONTENT_SETTING_ASK;
  if (name == "block")
    return CONTENT_SETTING_BLOCK;
  if (name == "session")
    return CONTENT_SETTING_SESSION_ONLY;

  NOTREACHED() << name << " is not a recognized content setting.";
  return CONTENT_SETTING_DEFAULT;
}

// Create a DictionaryValue* that will act as a data source for a single row
// in a HostContentSettingsMap-controlled exceptions table (e.g., cookies).
// Ownership of the pointer is passed to the caller.
DictionaryValue* GetExceptionForPage(
    const ContentSettingsPattern& pattern,
    const ContentSettingsPattern& secondary_pattern,
    const ContentSetting& setting,
    const std::string& provider_name) {
  DictionaryValue* exception = new DictionaryValue();
  exception->SetString(kOrigin, pattern.ToString());
  exception->SetString(kEmbeddingOrigin,
                       secondary_pattern == ContentSettingsPattern::Wildcard()
                           ? std::string()
                           : secondary_pattern.ToString());
  exception->SetString(kSetting, ContentSettingToString(setting));
  exception->SetString(kSource, provider_name);
  return exception;
}

// Create a DictionaryValue* that will act as a data source for a single row
// in the Geolocation exceptions table. Ownership of the pointer is passed to
// the caller.
DictionaryValue* GetGeolocationExceptionForPage(
    const ContentSettingsPattern& origin,
    const ContentSettingsPattern& embedding_origin,
    ContentSetting setting) {
  DictionaryValue* exception = new DictionaryValue();
  exception->SetString(kSetting, ContentSettingToString(setting));
  exception->SetString(kOrigin, origin.ToString());
  exception->SetString(kEmbeddingOrigin, embedding_origin.ToString());
  return exception;
}

// Create a DictionaryValue* that will act as a data source for a single row
// in the desktop notifications exceptions table. Ownership of the pointer is
// passed to the caller.
DictionaryValue* GetNotificationExceptionForPage(
    const ContentSettingsPattern& pattern,
    ContentSetting setting,
    const std::string& provider_name) {
  DictionaryValue* exception = new DictionaryValue();
  exception->SetString(kSetting, ContentSettingToString(setting));
  exception->SetString(kOrigin, pattern.ToString());
  exception->SetString(kSource, provider_name);
  return exception;
}

// Returns true whenever the |extension| is hosted and has |permission|.
// Must have the AppFilter signature.
template <APIPermission::ID permission>
bool HostedAppHasPermission(
    const extensions::Extension& extension, Profile* /*profile*/) {
    return extension.is_hosted_app() && extension.HasAPIPermission(permission);
}

// Add an "Allow"-entry to the list of |exceptions| for a |url_pattern| from
// the web extent of a hosted |app|.
void AddExceptionForHostedApp(const std::string& url_pattern,
    const extensions::Extension& app, ListValue* exceptions) {
  DictionaryValue* exception = new DictionaryValue();
  exception->SetString(kSetting, ContentSettingToString(CONTENT_SETTING_ALLOW));
  exception->SetString(kOrigin, url_pattern);
  exception->SetString(kEmbeddingOrigin, url_pattern);
  exception->SetString(kSource, "HostedApp");
  exception->SetString(kAppName, app.name());
  exception->SetString(kAppId, app.id());
  exceptions->Append(exception);
}

// Asks the |profile| for hosted apps which have the |permission| set, and
// adds their web extent and launch URL to the |exceptions| list.
void AddExceptionsGrantedByHostedApps(
    Profile* profile, AppFilter app_filter, ListValue* exceptions) {
  const ExtensionService* extension_service = profile->GetExtensionService();
  // After ExtensionSystem::Init has been called at the browser's start,
  // GetExtensionService() should not return NULL, so this is safe:
  const ExtensionSet* extensions = extension_service->extensions();

  for (ExtensionSet::const_iterator extension = extensions->begin();
       extension != extensions->end(); ++extension) {
    if (!app_filter(*extension->get(), profile))
      continue;

    extensions::URLPatternSet web_extent = (*extension)->web_extent();
    // Add patterns from web extent.
    for (extensions::URLPatternSet::const_iterator pattern = web_extent.begin();
         pattern != web_extent.end(); ++pattern) {
      std::string url_pattern = pattern->GetAsString();
      AddExceptionForHostedApp(url_pattern, *extension->get(), exceptions);
    }
    // Retrieve the launch URL.
    GURL launch_url =
        extensions::AppLaunchInfo::GetLaunchWebURL(extension->get());
    // Skip adding the launch URL if it is part of the web extent.
    if (web_extent.MatchesURL(launch_url))
      continue;
    AddExceptionForHostedApp(launch_url.spec(), *extension->get(), exceptions);
  }
}

}  // namespace

namespace options {

ContentSettingsHandler::MediaSettingsInfo::MediaSettingsInfo()
    : flash_default_setting(CONTENT_SETTING_DEFAULT),
      flash_settings_initialized(false),
      last_flash_refresh_request_id(0),
      show_flash_default_link(false),
      show_flash_exceptions_link(false),
      default_setting(CONTENT_SETTING_DEFAULT),
      policy_disable_audio(false),
      policy_disable_video(false),
      default_setting_initialized(false),
      exceptions_initialized(false) {
}

ContentSettingsHandler::MediaSettingsInfo::~MediaSettingsInfo() {
}

ContentSettingsHandler::ContentSettingsHandler() {
}

ContentSettingsHandler::~ContentSettingsHandler() {
}

void ContentSettingsHandler::GetLocalizedValues(
    DictionaryValue* localized_strings) {
  DCHECK(localized_strings);

  static OptionsStringResource resources[] = {
    { "allowException", IDS_EXCEPTIONS_ALLOW_BUTTON },
    { "blockException", IDS_EXCEPTIONS_BLOCK_BUTTON },
    { "sessionException", IDS_EXCEPTIONS_SESSION_ONLY_BUTTON },
    { "askException", IDS_EXCEPTIONS_ASK_BUTTON },
    { "otr_exceptions_explanation", IDS_EXCEPTIONS_OTR_LABEL },
    { "addNewExceptionInstructions", IDS_EXCEPTIONS_ADD_NEW_INSTRUCTIONS },
    { "manageExceptions", IDS_EXCEPTIONS_MANAGE },
    { "manage_handlers", IDS_HANDLERS_MANAGE },
    { "exceptionPatternHeader", IDS_EXCEPTIONS_PATTERN_HEADER },
    { "exceptionBehaviorHeader", IDS_EXCEPTIONS_ACTION_HEADER },
    { "embeddedOnHost", IDS_EXCEPTIONS_GEOLOCATION_EMBEDDED_ON_HOST },
    // Cookies filter.
    { "cookies_tab_label", IDS_COOKIES_TAB_LABEL },
    { "cookies_header", IDS_COOKIES_HEADER },
    { "cookies_allow", IDS_COOKIES_ALLOW_RADIO },
    { "cookies_block", IDS_COOKIES_BLOCK_RADIO },
    { "cookies_session_only", IDS_COOKIES_SESSION_ONLY_RADIO },
    { "cookies_block_3rd_party", IDS_COOKIES_BLOCK_3RDPARTY_CHKBOX },
    { "cookies_clear_when_close", IDS_COOKIES_CLEAR_WHEN_CLOSE_CHKBOX },
    { "cookies_lso_clear_when_close", IDS_COOKIES_LSO_CLEAR_WHEN_CLOSE_CHKBOX },
    { "cookies_show_cookies", IDS_COOKIES_SHOW_COOKIES_BUTTON },
    { "flash_storage_settings", IDS_FLASH_STORAGE_SETTINGS },
    { "flash_storage_url", IDS_FLASH_STORAGE_URL },
#if defined(ENABLE_GOOGLE_NOW)
    { "googleGeolocationAccessEnable",
       IDS_GEOLOCATION_GOOGLE_ACCESS_ENABLE_CHKBOX },
#endif
    // Image filter.
    { "images_tab_label", IDS_IMAGES_TAB_LABEL },
    { "images_header", IDS_IMAGES_HEADER },
    { "images_allow", IDS_IMAGES_LOAD_RADIO },
    { "images_block", IDS_IMAGES_NOLOAD_RADIO },
    // JavaScript filter.
    { "javascript_tab_label", IDS_JAVASCRIPT_TAB_LABEL },
    { "javascript_header", IDS_JAVASCRIPT_HEADER },
    { "javascript_allow", IDS_JS_ALLOW_RADIO },
    { "javascript_block", IDS_JS_DONOTALLOW_RADIO },
    // Plug-ins filter.
    { "plugins_tab_label", IDS_PLUGIN_TAB_LABEL },
    { "plugins_header", IDS_PLUGIN_HEADER },
    { "plugins_ask", IDS_PLUGIN_ASK_RADIO },
    { "plugins_allow", IDS_PLUGIN_LOAD_RADIO },
    { "plugins_block", IDS_PLUGIN_NOLOAD_RADIO },
    { "disableIndividualPlugins", IDS_PLUGIN_SELECTIVE_DISABLE },
    // Pop-ups filter.
    { "popups_tab_label", IDS_POPUP_TAB_LABEL },
    { "popups_header", IDS_POPUP_HEADER },
    { "popups_allow", IDS_POPUP_ALLOW_RADIO },
    { "popups_block", IDS_POPUP_BLOCK_RADIO },
    // Location filter.
    { "location_tab_label", IDS_GEOLOCATION_TAB_LABEL },
    { "location_header", IDS_GEOLOCATION_HEADER },
    { "location_allow", IDS_GEOLOCATION_ALLOW_RADIO },
    { "location_ask", IDS_GEOLOCATION_ASK_RADIO },
    { "location_block", IDS_GEOLOCATION_BLOCK_RADIO },
    { "set_by", IDS_GEOLOCATION_SET_BY_HOVER },
    // Notifications filter.
    { "notifications_tab_label", IDS_NOTIFICATIONS_TAB_LABEL },
    { "notifications_header", IDS_NOTIFICATIONS_HEADER },
    { "notifications_allow", IDS_NOTIFICATIONS_ALLOW_RADIO },
    { "notifications_ask", IDS_NOTIFICATIONS_ASK_RADIO },
    { "notifications_block", IDS_NOTIFICATIONS_BLOCK_RADIO },
    // Fullscreen filter.
    { "fullscreen_tab_label", IDS_FULLSCREEN_TAB_LABEL },
    { "fullscreen_header", IDS_FULLSCREEN_HEADER },
    // Mouse Lock filter.
    { "mouselock_tab_label", IDS_MOUSE_LOCK_TAB_LABEL },
    { "mouselock_header", IDS_MOUSE_LOCK_HEADER },
    { "mouselock_allow", IDS_MOUSE_LOCK_ALLOW_RADIO },
    { "mouselock_ask", IDS_MOUSE_LOCK_ASK_RADIO },
    { "mouselock_block", IDS_MOUSE_LOCK_BLOCK_RADIO },
#if defined(OS_CHROMEOS) || defined(OS_WIN)
    // Protected Content filter
    { "protectedContentTabLabel", IDS_PROTECTED_CONTENT_TAB_LABEL },
    { "protectedContentInfo", IDS_PROTECTED_CONTENT_INFO },
    { "protectedContentEnable", IDS_PROTECTED_CONTENT_ENABLE},
#endif  // defined(OS_CHROMEOS) || defined(OS_WIN)
    // Media stream capture device filter.
    { "mediaStreamTabLabel", IDS_MEDIA_STREAM_TAB_LABEL },
    { "media-stream_header", IDS_MEDIA_STREAM_HEADER },
    { "mediaStreamAsk", IDS_MEDIA_STREAM_ASK_RADIO },
    { "mediaStreamBlock", IDS_MEDIA_STREAM_BLOCK_RADIO },
    { "mediaStreamAudioAsk", IDS_MEDIA_STREAM_ASK_AUDIO_ONLY_RADIO },
    { "mediaStreamAudioBlock", IDS_MEDIA_STREAM_BLOCK_AUDIO_ONLY_RADIO },
    { "mediaStreamVideoAsk", IDS_MEDIA_STREAM_ASK_VIDEO_ONLY_RADIO },
    { "mediaStreamVideoBlock", IDS_MEDIA_STREAM_BLOCK_VIDEO_ONLY_RADIO },
    { "mediaStreamBubbleAudio", IDS_MEDIA_STREAM_AUDIO_MANAGED },
    { "mediaStreamBubbleVideo", IDS_MEDIA_STREAM_VIDEO_MANAGED },
    { "mediaAudioExceptionHeader", IDS_MEDIA_AUDIO_EXCEPTION_HEADER },
    { "mediaVideoExceptionHeader", IDS_MEDIA_VIDEO_EXCEPTION_HEADER },
    { "mediaPepperFlashDefaultDivergedLabel",
      IDS_MEDIA_PEPPER_FLASH_DEFAULT_DIVERGED_LABEL },
    { "mediaPepperFlashExceptionsDivergedLabel",
      IDS_MEDIA_PEPPER_FLASH_EXCEPTIONS_DIVERGED_LABEL },
    { "mediaPepperFlashChangeLink", IDS_MEDIA_PEPPER_FLASH_CHANGE_LINK },
    { "mediaPepperFlashGlobalPrivacyURL", IDS_FLASH_GLOBAL_PRIVACY_URL },
    { "mediaPepperFlashWebsitePrivacyURL", IDS_FLASH_WEBSITE_PRIVACY_URL },
    // PPAPI broker filter.
    // TODO(bauerb): Use IDS_PPAPI_BROKER_HEADER.
    { "ppapi-broker_header", IDS_PPAPI_BROKER_TAB_LABEL },
    { "ppapiBrokerTabLabel", IDS_PPAPI_BROKER_TAB_LABEL },
    { "ppapi_broker_allow", IDS_PPAPI_BROKER_ALLOW_RADIO },
    { "ppapi_broker_ask", IDS_PPAPI_BROKER_ASK_RADIO },
    { "ppapi_broker_block", IDS_PPAPI_BROKER_BLOCK_RADIO },
    // Multiple automatic downloads
    { "multiple-automatic-downloads_header",
      IDS_AUTOMATIC_DOWNLOADS_TAB_LABEL },
    { "multiple-automatic-downloads_allow",
      IDS_AUTOMATIC_DOWNLOADS_ALLOW_RADIO },
    { "multiple-automatic-downloads_ask",
      IDS_AUTOMATIC_DOWNLOADS_ASK_RADIO },
    { "multiple-automatic-downloads_block",
      IDS_AUTOMATIC_DOWNLOADS_BLOCK_RADIO },
    // MIDI system exclusive messages
    { "midi-sysex_header", IDS_MIDI_SYSEX_TAB_LABEL },
    { "midiSysExAllow", IDS_MIDI_SYSEX_ALLOW_RADIO },
    { "midiSysExAsk", IDS_MIDI_SYSEX_ASK_RADIO },
    { "midiSysExBlock", IDS_MIDI_SYSEX_BLOCK_RADIO },
  };

  RegisterStrings(localized_strings, resources, arraysize(resources));
  RegisterTitle(localized_strings, "contentSettingsPage",
                IDS_CONTENT_SETTINGS_TITLE);

  // Register titles for each of the individual settings whose exception
  // dialogs will be processed by |ContentSettingsHandler|.
  RegisterTitle(localized_strings, "cookies",
                IDS_COOKIES_TAB_LABEL);
  RegisterTitle(localized_strings, "images",
                IDS_IMAGES_TAB_LABEL);
  RegisterTitle(localized_strings, "javascript",
                IDS_JAVASCRIPT_TAB_LABEL);
  RegisterTitle(localized_strings, "plugins",
                IDS_PLUGIN_TAB_LABEL);
  RegisterTitle(localized_strings, "popups",
                IDS_POPUP_TAB_LABEL);
  RegisterTitle(localized_strings, "location",
                IDS_GEOLOCATION_TAB_LABEL);
  RegisterTitle(localized_strings, "notifications",
                IDS_NOTIFICATIONS_TAB_LABEL);
  RegisterTitle(localized_strings, "fullscreen",
                IDS_FULLSCREEN_TAB_LABEL);
  RegisterTitle(localized_strings, "mouselock",
                IDS_MOUSE_LOCK_TAB_LABEL);
  RegisterTitle(localized_strings, "media-stream",
                IDS_MEDIA_STREAM_TAB_LABEL);
  RegisterTitle(localized_strings, "ppapi-broker",
                IDS_PPAPI_BROKER_TAB_LABEL);
  RegisterTitle(localized_strings, "multiple-automatic-downloads",
                IDS_AUTOMATIC_DOWNLOADS_TAB_LABEL);
  RegisterTitle(localized_strings, "midi-sysex",
                IDS_MIDI_SYSEX_TAB_LABEL);

  localized_strings->SetBoolean("newContentSettings",
      CommandLine::ForCurrentProcess()->HasSwitch(switches::kContentSettings2));
  localized_strings->SetString(
      "exceptionsLearnMoreUrl",
      google_util::StringAppendGoogleLocaleParam(
          kExceptionsLearnMoreUrl));
}

void ContentSettingsHandler::InitializeHandler() {
  notification_registrar_.Add(
      this, chrome::NOTIFICATION_PROFILE_CREATED,
      content::NotificationService::AllSources());
  notification_registrar_.Add(
      this, chrome::NOTIFICATION_PROFILE_DESTROYED,
      content::NotificationService::AllSources());

  notification_registrar_.Add(
      this, chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED,
      content::NotificationService::AllSources());
  notification_registrar_.Add(
      this, chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED,
      content::NotificationService::AllSources());
  Profile* profile = Profile::FromWebUI(web_ui());
  notification_registrar_.Add(
      this, chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED,
      content::Source<Profile>(profile));

  PrefService* prefs = profile->GetPrefs();
  pref_change_registrar_.Init(prefs);
  pref_change_registrar_.Add(
      prefs::kPepperFlashSettingsEnabled,
      base::Bind(&ContentSettingsHandler::OnPepperFlashPrefChanged,
                 base::Unretained(this)));
  pref_change_registrar_.Add(
      prefs::kAudioCaptureAllowed,
      base::Bind(&ContentSettingsHandler::UpdateMediaSettingsView,
                 base::Unretained(this)));
  pref_change_registrar_.Add(
      prefs::kVideoCaptureAllowed,
      base::Bind(&ContentSettingsHandler::UpdateMediaSettingsView,
                 base::Unretained(this)));

  flash_settings_manager_.reset(new PepperFlashSettingsManager(this, profile));
}

void ContentSettingsHandler::InitializePage() {
  media_settings_ = MediaSettingsInfo();
  RefreshFlashMediaSettings();

  UpdateHandlersEnabledRadios();
  UpdateAllExceptionsViewsFromModel();
}

void ContentSettingsHandler::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  switch (type) {
    case chrome::NOTIFICATION_PROFILE_DESTROYED: {
      if (content::Source<Profile>(source).ptr()->IsOffTheRecord()) {
        web_ui()->CallJavascriptFunction(
            "ContentSettingsExceptionsArea.OTRProfileDestroyed");
      }
      break;
    }

    case chrome::NOTIFICATION_PROFILE_CREATED: {
      if (content::Source<Profile>(source).ptr()->IsOffTheRecord())
        UpdateAllOTRExceptionsViewsFromModel();
      break;
    }

    case chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED: {
      // Filter out notifications from other profiles.
      HostContentSettingsMap* map =
          content::Source<HostContentSettingsMap>(source).ptr();
      if (map != GetContentSettingsMap() &&
          map != GetOTRContentSettingsMap())
        break;

      const ContentSettingsDetails* settings_details =
          content::Details<const ContentSettingsDetails>(details).ptr();

      // TODO(estade): we pretend update_all() is always true.
      if (settings_details->update_all_types())
        UpdateAllExceptionsViewsFromModel();
      else
        UpdateExceptionsViewFromModel(settings_details->type());
      break;
    }

    case chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED: {
      UpdateNotificationExceptionsView();
      break;
    }

    case chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED: {
      UpdateHandlersEnabledRadios();
      break;
    }

    default:
      OptionsPageUIHandler::Observe(type, source, details);
  }
}

void ContentSettingsHandler::OnGetPermissionSettingsCompleted(
    uint32 request_id,
    bool success,
    PP_Flash_BrowserOperations_Permission default_permission,
    const ppapi::FlashSiteSettings& sites) {
  if (success && request_id == media_settings_.last_flash_refresh_request_id) {
    media_settings_.flash_settings_initialized = true;
    media_settings_.flash_default_setting =
        PepperFlashContentSettingsUtils::FlashPermissionToContentSetting(
            default_permission);
    PepperFlashContentSettingsUtils::FlashSiteSettingsToMediaExceptions(
        sites, &media_settings_.flash_exceptions);
    PepperFlashContentSettingsUtils::SortMediaExceptions(
        &media_settings_.flash_exceptions);

    UpdateFlashMediaLinksVisibility();
  }
}

void ContentSettingsHandler::UpdateSettingDefaultFromModel(
    ContentSettingsType type) {
  DictionaryValue filter_settings;
  std::string provider_id;
  filter_settings.SetString(ContentSettingsTypeToGroupName(type) + ".value",
                            GetSettingDefaultFromModel(type, &provider_id));
  filter_settings.SetString(
      ContentSettingsTypeToGroupName(type) + ".managedBy", provider_id);

  web_ui()->CallJavascriptFunction(
      "ContentSettings.setContentFilterSettingsValue", filter_settings);
}

void ContentSettingsHandler::UpdateMediaSettingsView() {
  PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
  bool audio_disabled = !prefs->GetBoolean(prefs::kAudioCaptureAllowed) &&
      prefs->IsManagedPreference(prefs::kAudioCaptureAllowed);
  bool video_disabled = !prefs->GetBoolean(prefs::kVideoCaptureAllowed) &&
      prefs->IsManagedPreference(prefs::kVideoCaptureAllowed);

  media_settings_.policy_disable_audio = audio_disabled;
  media_settings_.policy_disable_video = video_disabled;
  media_settings_.default_setting =
      GetContentSettingsMap()->GetDefaultContentSetting(
          CONTENT_SETTINGS_TYPE_MEDIASTREAM, NULL);
  media_settings_.default_setting_initialized = true;
  UpdateFlashMediaLinksVisibility();

  DictionaryValue media_ui_settings;
  media_ui_settings.SetBoolean("cameraDisabled", video_disabled);
  media_ui_settings.SetBoolean("micDisabled", audio_disabled);

  // In case only video is enabled change the text appropriately.
  if (audio_disabled && !video_disabled) {
    media_ui_settings.SetString("askText", "mediaStreamVideoAsk");
    media_ui_settings.SetString("blockText", "mediaStreamVideoBlock");
    media_ui_settings.SetBoolean("showBubble", true);
    media_ui_settings.SetString("bubbleText", "mediaStreamBubbleAudio");

    web_ui()->CallJavascriptFunction("ContentSettings.updateMediaUI",
                                     media_ui_settings);
    return;
  }

  // In case only audio is enabled change the text appropriately.
  if (video_disabled && !audio_disabled) {
    DictionaryValue media_ui_settings;
    media_ui_settings.SetString("askText", "mediaStreamAudioAsk");
    media_ui_settings.SetString("blockText", "mediaStreamAudioBlock");
    media_ui_settings.SetBoolean("showBubble", true);
    media_ui_settings.SetString("bubbleText", "mediaStreamBubbleVideo");

    web_ui()->CallJavascriptFunction("ContentSettings.updateMediaUI",
                                     media_ui_settings);
    return;
  }

  if (audio_disabled && video_disabled) {
    // Fake policy controlled default because the user can not change anything
    // until both audio and video are blocked.
    DictionaryValue filter_settings;
    std::string group_name =
        ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_MEDIASTREAM);
    filter_settings.SetString(group_name + ".value",
                              ContentSettingToString(CONTENT_SETTING_BLOCK));
    filter_settings.SetString(group_name + ".managedBy", "policy");
    web_ui()->CallJavascriptFunction(
        "ContentSettings.setContentFilterSettingsValue", filter_settings);
  }

  media_ui_settings.SetString("askText", "mediaStreamAsk");
  media_ui_settings.SetString("blockText", "mediaStreamBlock");
  media_ui_settings.SetBoolean("showBubble", false);
  media_ui_settings.SetString("bubbleText", std::string());

  web_ui()->CallJavascriptFunction("ContentSettings.updateMediaUI",
                                   media_ui_settings);
}

std::string ContentSettingsHandler::GetSettingDefaultFromModel(
    ContentSettingsType type, std::string* provider_id) {
  Profile* profile = Profile::FromWebUI(web_ui());
  ContentSetting default_setting;
  if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
    default_setting =
        DesktopNotificationServiceFactory::GetForProfile(profile)->
            GetDefaultContentSetting(provider_id);
  } else {
    default_setting =
        profile->GetHostContentSettingsMap()->
            GetDefaultContentSetting(type, provider_id);
  }

  return ContentSettingToString(default_setting);
}

void ContentSettingsHandler::UpdateHandlersEnabledRadios() {
  base::FundamentalValue handlers_enabled(
      GetProtocolHandlerRegistry()->enabled());

  web_ui()->CallJavascriptFunction(
      "ContentSettings.updateHandlersEnabledRadios",
      handlers_enabled);
}

void ContentSettingsHandler::UpdateAllExceptionsViewsFromModel() {
  for (int type = CONTENT_SETTINGS_TYPE_DEFAULT + 1;
       type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
    UpdateExceptionsViewFromModel(static_cast<ContentSettingsType>(type));
  }
}

void ContentSettingsHandler::UpdateAllOTRExceptionsViewsFromModel() {
  for (int type = CONTENT_SETTINGS_TYPE_DEFAULT + 1;
       type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
    UpdateOTRExceptionsViewFromModel(static_cast<ContentSettingsType>(type));
  }
}

void ContentSettingsHandler::UpdateExceptionsViewFromModel(
    ContentSettingsType type) {
  switch (type) {
    case CONTENT_SETTINGS_TYPE_GEOLOCATION:
      UpdateGeolocationExceptionsView();
      break;
    case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
      UpdateNotificationExceptionsView();
      break;
    case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
      UpdateMediaSettingsView();
      break;
    case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
    case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
      UpdateMediaExceptionsView();
      break;
    case CONTENT_SETTINGS_TYPE_MIXEDSCRIPT:
      // We don't yet support exceptions for mixed scripting.
      break;
    case CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE:
      // The content settings type CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
      // is supposed to be set by policy only. Hence there is no user facing UI
      // for this content type and we skip it here.
      break;
    case CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS:
      // The RPH settings are retrieved separately.
      break;
    case CONTENT_SETTINGS_TYPE_SAVE_PASSWORD:
      // There is no user facing UI for this content type and we skip it here.
      break;
    case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
      UpdateMIDISysExExceptionsView();
      break;
#if defined(OS_WIN)
    case CONTENT_SETTINGS_TYPE_METRO_SWITCH_TO_DESKTOP:
      break;
#endif
    default:
      UpdateExceptionsViewFromHostContentSettingsMap(type);
      break;
  }
}

void ContentSettingsHandler::UpdateOTRExceptionsViewFromModel(
    ContentSettingsType type) {
  switch (type) {
    case CONTENT_SETTINGS_TYPE_GEOLOCATION:
    case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
    case CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE:
    case CONTENT_SETTINGS_TYPE_MIXEDSCRIPT:
#if defined(OS_WIN)
    case CONTENT_SETTINGS_TYPE_METRO_SWITCH_TO_DESKTOP:
#endif
    case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
    case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
    case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
    case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS:
    case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
      break;
    default:
      UpdateExceptionsViewFromOTRHostContentSettingsMap(type);
      break;
  }
}

// TODO(estade): merge with GetExceptionsFromHostContentSettingsMap.
void ContentSettingsHandler::UpdateGeolocationExceptionsView() {
  Profile* profile = Profile::FromWebUI(web_ui());
  HostContentSettingsMap* map = profile->GetHostContentSettingsMap();

  ContentSettingsForOneType all_settings;
  map->GetSettingsForOneType(
      CONTENT_SETTINGS_TYPE_GEOLOCATION,
      std::string(),
      &all_settings);

  // Group geolocation settings by primary_pattern.
  AllPatternsSettings all_patterns_settings;
  for (ContentSettingsForOneType::iterator i = all_settings.begin();
       i != all_settings.end(); ++i) {
    // Don't add default settings.
    if (i->primary_pattern == ContentSettingsPattern::Wildcard() &&
        i->secondary_pattern == ContentSettingsPattern::Wildcard() &&
        i->source != kPreferencesSource) {
      continue;
    }
    all_patterns_settings[std::make_pair(i->primary_pattern, i->source)]
        [i->secondary_pattern] = i->setting;
  }

  ListValue exceptions;
  AddExceptionsGrantedByHostedApps(
      profile,
      HostedAppHasPermission<APIPermission::kGeolocation>,
      &exceptions);

  for (AllPatternsSettings::iterator i = all_patterns_settings.begin();
       i != all_patterns_settings.end(); ++i) {
    const ContentSettingsPattern& primary_pattern = i->first.first;
    const OnePatternSettings& one_settings = i->second;

    OnePatternSettings::const_iterator parent =
        one_settings.find(primary_pattern);

    // Add the "parent" entry for the non-embedded setting.
    ContentSetting parent_setting =
        parent == one_settings.end() ? CONTENT_SETTING_DEFAULT : parent->second;
    exceptions.Append(GetGeolocationExceptionForPage(primary_pattern,
                                                     primary_pattern,
                                                     parent_setting));

    // Add the "children" for any embedded settings.
    for (OnePatternSettings::const_iterator j = one_settings.begin();
         j != one_settings.end();
         ++j) {
      // Skip the non-embedded setting which we already added above.
      if (j == parent)
        continue;

      exceptions.Append(GetGeolocationExceptionForPage(
          primary_pattern, j->first, j->second));
    }
  }

  StringValue type_string(
      ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_GEOLOCATION));
  web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
                                   type_string, exceptions);

  // This is mainly here to keep this function ideologically parallel to
  // UpdateExceptionsViewFromHostContentSettingsMap().
  UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_GEOLOCATION);
}

void ContentSettingsHandler::UpdateNotificationExceptionsView() {
  Profile* profile = Profile::FromWebUI(web_ui());
  DesktopNotificationService* service =
      DesktopNotificationServiceFactory::GetForProfile(profile);

  ContentSettingsForOneType settings;
  service->GetNotificationsSettings(&settings);

  ListValue exceptions;
  AddExceptionsGrantedByHostedApps(profile,
      HostedAppHasPermission<APIPermission::kNotification>,
      &exceptions);

  for (ContentSettingsForOneType::const_iterator i =
           settings.begin();
       i != settings.end();
       ++i) {
    // Don't add default settings.
    if (i->primary_pattern == ContentSettingsPattern::Wildcard() &&
        i->secondary_pattern == ContentSettingsPattern::Wildcard() &&
        i->source != kPreferencesSource) {
      continue;
    }

    exceptions.Append(
        GetNotificationExceptionForPage(i->primary_pattern, i->setting,
                                        i->source));
  }

  StringValue type_string(
      ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_NOTIFICATIONS));
  web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
                                   type_string, exceptions);

  // This is mainly here to keep this function ideologically parallel to
  // UpdateExceptionsViewFromHostContentSettingsMap().
  UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
}

void ContentSettingsHandler::UpdateMediaExceptionsView() {
  ListValue media_exceptions;
  GetExceptionsFromHostContentSettingsMap(
      GetContentSettingsMap(),
      CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
      &media_exceptions);

  ListValue video_exceptions;
  GetExceptionsFromHostContentSettingsMap(
      GetContentSettingsMap(),
      CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
      &video_exceptions);

  // Merge the |video_exceptions| list to |media_exceptions| list.
  std::map<std::string, base::DictionaryValue*> entries_map;
  for (ListValue::const_iterator media_entry(media_exceptions.begin());
       media_entry != media_exceptions.end(); ++media_entry) {
    DictionaryValue* media_dict = NULL;
    if (!(*media_entry)->GetAsDictionary(&media_dict))
      NOTREACHED();

    media_dict->SetString(kVideoSetting,
                          ContentSettingToString(CONTENT_SETTING_ASK));

    std::string media_origin;
    media_dict->GetString(kOrigin, &media_origin);
    entries_map[media_origin] = media_dict;
  }

  for (ListValue::iterator video_entry = video_exceptions.begin();
       video_entry != video_exceptions.end(); ++video_entry) {
    DictionaryValue* video_dict = NULL;
    if (!(*video_entry)->GetAsDictionary(&video_dict))
      NOTREACHED();

    std::string video_origin;
    std::string video_setting;
    video_dict->GetString(kOrigin, &video_origin);
    video_dict->GetString(kSetting, &video_setting);

    std::map<std::string, base::DictionaryValue*>::iterator iter =
        entries_map.find(video_origin);
    if (iter == entries_map.end()) {
      DictionaryValue* exception = new DictionaryValue();
      exception->SetString(kOrigin, video_origin);
      exception->SetString(kSetting,
                           ContentSettingToString(CONTENT_SETTING_ASK));
      exception->SetString(kVideoSetting, video_setting);
      exception->SetString(kSource, kPreferencesSource);

      // Append the new entry to the list and map.
      media_exceptions.Append(exception);
      entries_map[video_origin] = exception;
    } else {
      // Modify the existing entry.
      iter->second->SetString(kVideoSetting, video_setting);
    }
  }

  media_settings_.exceptions.clear();
  for (ListValue::const_iterator media_entry = media_exceptions.begin();
       media_entry != media_exceptions.end(); ++media_entry) {
    DictionaryValue* media_dict = NULL;
    bool result = (*media_entry)->GetAsDictionary(&media_dict);
    DCHECK(result);

    std::string origin;
    std::string audio_setting;
    std::string video_setting;
    media_dict->GetString(kOrigin, &origin);
    media_dict->GetString(kSetting, &audio_setting);
    media_dict->GetString(kVideoSetting, &video_setting);
    media_settings_.exceptions.push_back(MediaException(
        ContentSettingsPattern::FromString(origin),
        ContentSettingFromString(audio_setting),
        ContentSettingFromString(video_setting)));
  }
  PepperFlashContentSettingsUtils::SortMediaExceptions(
      &media_settings_.exceptions);
  media_settings_.exceptions_initialized = true;
  UpdateFlashMediaLinksVisibility();

  StringValue type_string(
       ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_MEDIASTREAM));
  web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
                                   type_string, media_exceptions);

  UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_MEDIASTREAM);
}

void ContentSettingsHandler::UpdateMIDISysExExceptionsView() {
  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableWebMIDI)) {
    web_ui()->CallJavascriptFunction(
        "ContentSettings.showExperimentalWebMIDISettings",
        base::FundamentalValue(true));
  }

  UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_MIDI_SYSEX);
  UpdateExceptionsViewFromHostContentSettingsMap(
      CONTENT_SETTINGS_TYPE_MIDI_SYSEX);
}

void ContentSettingsHandler::UpdateExceptionsViewFromHostContentSettingsMap(
    ContentSettingsType type) {
  ListValue exceptions;
  GetExceptionsFromHostContentSettingsMap(
      GetContentSettingsMap(), type, &exceptions);
  StringValue type_string(ContentSettingsTypeToGroupName(type));
  web_ui()->CallJavascriptFunction("ContentSettings.setExceptions", type_string,
                                   exceptions);

  UpdateExceptionsViewFromOTRHostContentSettingsMap(type);

  // TODO(koz): The default for fullscreen is always 'ask'.
  // http://crbug.com/104683
  if (type == CONTENT_SETTINGS_TYPE_FULLSCREEN)
    return;

  // The default may also have changed (we won't get a separate notification).
  // If it hasn't changed, this call will be harmless.
  UpdateSettingDefaultFromModel(type);
}

void ContentSettingsHandler::UpdateExceptionsViewFromOTRHostContentSettingsMap(
    ContentSettingsType type) {
  const HostContentSettingsMap* otr_settings_map = GetOTRContentSettingsMap();
  if (!otr_settings_map)
    return;
  ListValue exceptions;
  GetExceptionsFromHostContentSettingsMap(otr_settings_map, type, &exceptions);
  StringValue type_string(ContentSettingsTypeToGroupName(type));
  web_ui()->CallJavascriptFunction("ContentSettings.setOTRExceptions",
                                   type_string, exceptions);
}

void ContentSettingsHandler::GetExceptionsFromHostContentSettingsMap(
    const HostContentSettingsMap* map,
    ContentSettingsType type,
    ListValue* exceptions) {
  ContentSettingsForOneType entries;
  map->GetSettingsForOneType(type, std::string(), &entries);
  // Group settings by primary_pattern.
  AllPatternsSettings all_patterns_settings;
  for (ContentSettingsForOneType::iterator i = entries.begin();
       i != entries.end(); ++i) {
    // Don't add default settings.
    if (i->primary_pattern == ContentSettingsPattern::Wildcard() &&
        i->secondary_pattern == ContentSettingsPattern::Wildcard() &&
        i->source != kPreferencesSource) {
      continue;
    }

    // Off-the-record HostContentSettingsMap contains incognito content settings
    // as well as normal content settings. Here, we use the incongnito settings
    // only.
    if (map->is_off_the_record() && !i->incognito)
      continue;

    all_patterns_settings[std::make_pair(i->primary_pattern, i->source)]
        [i->secondary_pattern] = i->setting;
  }

  // Keep the exceptions sorted by provider so they will be displayed in
  // precedence order.
  std::vector<std::vector<Value*> > all_provider_exceptions;
  all_provider_exceptions.resize(HostContentSettingsMap::NUM_PROVIDER_TYPES);

  for (AllPatternsSettings::iterator i = all_patterns_settings.begin();
       i != all_patterns_settings.end();
       ++i) {
    const ContentSettingsPattern& primary_pattern = i->first.first;
    const OnePatternSettings& one_settings = i->second;

    // The "parent" entry either has an identical primary and secondary pattern,
    // or has a wildcard secondary. The two cases are indistinguishable in the
    // UI.
    OnePatternSettings::const_iterator parent =
        one_settings.find(primary_pattern);
    if (parent == one_settings.end())
      parent = one_settings.find(ContentSettingsPattern::Wildcard());

    const std::string& source = i->first.second;
    std::vector<Value*>* this_provider_exceptions = &all_provider_exceptions.at(
        HostContentSettingsMap::GetProviderTypeFromSource(source));

    // Add the "parent" entry for the non-embedded setting.
    ContentSetting parent_setting =
        parent == one_settings.end() ? CONTENT_SETTING_DEFAULT : parent->second;
    const ContentSettingsPattern& secondary_pattern =
        parent == one_settings.end() ? primary_pattern : parent->first;
    this_provider_exceptions->push_back(GetExceptionForPage(primary_pattern,
                                                            secondary_pattern,
                                                            parent_setting,
                                                            source));

    // Add the "children" for any embedded settings.
    for (OnePatternSettings::const_iterator j = one_settings.begin();
         j != one_settings.end(); ++j) {
      // Skip the non-embedded setting which we already added above.
      if (j == parent)
        continue;

      ContentSetting content_setting = j->second;
      this_provider_exceptions->push_back(GetExceptionForPage(
          primary_pattern,
          j->first,
          content_setting,
          source));
    }
  }

  for (size_t i = 0; i < all_provider_exceptions.size(); ++i) {
    for (size_t j = 0; j < all_provider_exceptions[i].size(); ++j) {
      exceptions->Append(all_provider_exceptions[i][j]);
    }
  }
}

void ContentSettingsHandler::RemoveNotificationException(
    const ListValue* args, size_t arg_index) {
  Profile* profile = Profile::FromWebUI(web_ui());
  std::string origin;
  std::string setting;
  bool rv = args->GetString(arg_index++, &origin);
  DCHECK(rv);
  rv = args->GetString(arg_index++, &setting);
  DCHECK(rv);
  ContentSetting content_setting = ContentSettingFromString(setting);

  DCHECK(content_setting == CONTENT_SETTING_ALLOW ||
         content_setting == CONTENT_SETTING_BLOCK);
  DesktopNotificationServiceFactory::GetForProfile(profile)->
      ClearSetting(ContentSettingsPattern::FromString(origin));
}

void ContentSettingsHandler::RemoveMediaException(
    const ListValue* args, size_t arg_index) {
  std::string mode;
  bool rv = args->GetString(arg_index++, &mode);
  DCHECK(rv);

  std::string pattern;
  rv = args->GetString(arg_index++, &pattern);
  DCHECK(rv);

  HostContentSettingsMap* settings_map =
      mode == "normal" ? GetContentSettingsMap() :
                         GetOTRContentSettingsMap();
  if (settings_map) {
    settings_map->SetWebsiteSetting(ContentSettingsPattern::FromString(pattern),
                                    ContentSettingsPattern::Wildcard(),
                                    CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
                                    std::string(),
                                    NULL);
    settings_map->SetWebsiteSetting(ContentSettingsPattern::FromString(pattern),
                                    ContentSettingsPattern::Wildcard(),
                                    CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
                                    std::string(),
                                    NULL);
  }
}

void ContentSettingsHandler::RemoveExceptionFromHostContentSettingsMap(
    const ListValue* args, size_t arg_index,
    ContentSettingsType type) {
  std::string mode;
  bool rv = args->GetString(arg_index++, &mode);
  DCHECK(rv);

  std::string pattern;
  rv = args->GetString(arg_index++, &pattern);
  DCHECK(rv);

  std::string secondary_pattern;
  rv = args->GetString(arg_index++, &secondary_pattern);
  DCHECK(rv);

  HostContentSettingsMap* settings_map =
      mode == "normal" ? GetContentSettingsMap() :
                         GetOTRContentSettingsMap();
  if (settings_map) {
    settings_map->SetWebsiteSetting(
        ContentSettingsPattern::FromString(pattern),
        secondary_pattern.empty()
            ? ContentSettingsPattern::Wildcard()
            : ContentSettingsPattern::FromString(secondary_pattern),
        type,
        std::string(),
        NULL);
  }
}

void ContentSettingsHandler::RegisterMessages() {
  web_ui()->RegisterMessageCallback("setContentFilter",
      base::Bind(&ContentSettingsHandler::SetContentFilter,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("removeException",
      base::Bind(&ContentSettingsHandler::RemoveException,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("setException",
      base::Bind(&ContentSettingsHandler::SetException,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("checkExceptionPatternValidity",
      base::Bind(&ContentSettingsHandler::CheckExceptionPatternValidity,
                 base::Unretained(this)));
}

void ContentSettingsHandler::ApplyWhitelist(ContentSettingsType content_type,
                                            ContentSetting default_setting) {
  Profile* profile = Profile::FromWebUI(web_ui());
  HostContentSettingsMap* map = GetContentSettingsMap();
  if (content_type != CONTENT_SETTINGS_TYPE_PLUGINS)
    return;
  const int kDefaultWhitelistVersion = 1;
  PrefService* prefs = profile->GetPrefs();
  int version = prefs->GetInteger(
      prefs::kContentSettingsDefaultWhitelistVersion);
  if (version >= kDefaultWhitelistVersion)
    return;
  ContentSetting old_setting =
      map->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS, NULL);
  // TODO(bauerb): Remove this once the Google Talk plug-in works nicely with
  // click-to-play (b/6090625).
  if (old_setting == CONTENT_SETTING_ALLOW &&
      default_setting == CONTENT_SETTING_ASK) {
    map->SetWebsiteSetting(
        ContentSettingsPattern::Wildcard(),
        ContentSettingsPattern::Wildcard(),
        CONTENT_SETTINGS_TYPE_PLUGINS,
        "google-talk",
        new base::FundamentalValue(CONTENT_SETTING_ALLOW));
  }
  prefs->SetInteger(prefs::kContentSettingsDefaultWhitelistVersion,
                    kDefaultWhitelistVersion);
}

void ContentSettingsHandler::SetContentFilter(const ListValue* args) {
  DCHECK_EQ(2U, args->GetSize());
  std::string group, setting;
  if (!(args->GetString(0, &group) &&
        args->GetString(1, &setting))) {
    NOTREACHED();
    return;
  }

  ContentSetting default_setting = ContentSettingFromString(setting);
  ContentSettingsType content_type = ContentSettingsTypeFromGroupName(group);
  Profile* profile = Profile::FromWebUI(web_ui());

#if defined(OS_CHROMEOS)
  // ChromeOS special case : in Guest mode settings are opened in Incognito
  // mode, so we need original profile to actually modify settings.
  if (chromeos::UserManager::Get()->IsLoggedInAsGuest())
    profile = profile->GetOriginalProfile();
#endif

  if (content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
    DesktopNotificationServiceFactory::GetForProfile(profile)->
        SetDefaultContentSetting(default_setting);
  } else {
    HostContentSettingsMap* map = profile->GetHostContentSettingsMap();
    ApplyWhitelist(content_type, default_setting);
    map->SetDefaultContentSetting(content_type, default_setting);
  }
  switch (content_type) {
    case CONTENT_SETTINGS_TYPE_COOKIES:
      content::RecordAction(
          UserMetricsAction("Options_DefaultCookieSettingChanged"));
      break;
    case CONTENT_SETTINGS_TYPE_IMAGES:
      content::RecordAction(
          UserMetricsAction("Options_DefaultImagesSettingChanged"));
      break;
    case CONTENT_SETTINGS_TYPE_JAVASCRIPT:
      content::RecordAction(
          UserMetricsAction("Options_DefaultJavaScriptSettingChanged"));
      break;
    case CONTENT_SETTINGS_TYPE_PLUGINS:
      content::RecordAction(
          UserMetricsAction("Options_DefaultPluginsSettingChanged"));
      break;
    case CONTENT_SETTINGS_TYPE_POPUPS:
      content::RecordAction(
          UserMetricsAction("Options_DefaultPopupsSettingChanged"));
      break;
    case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
      content::RecordAction(
          UserMetricsAction("Options_DefaultNotificationsSettingChanged"));
      break;
    case CONTENT_SETTINGS_TYPE_GEOLOCATION:
      content::RecordAction(
          UserMetricsAction("Options_DefaultGeolocationSettingChanged"));
      break;
    case CONTENT_SETTINGS_TYPE_MOUSELOCK:
      content::RecordAction(
          UserMetricsAction("Options_DefaultMouseLockSettingChanged"));
      break;
    case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
      content::RecordAction(
          UserMetricsAction("Options_DefaultMediaStreamMicSettingChanged"));
      break;
    case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS:
      content::RecordAction(UserMetricsAction(
          "Options_DefaultMultipleAutomaticDownloadsSettingChanged"));
      break;
    case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
      content::RecordAction(
          UserMetricsAction("Options_DefaultMIDISysExSettingChanged"));
      break;
    default:
      break;
  }
}

void ContentSettingsHandler::RemoveException(const ListValue* args) {
  size_t arg_i = 0;
  std::string type_string;
  CHECK(args->GetString(arg_i++, &type_string));

  ContentSettingsType type = ContentSettingsTypeFromGroupName(type_string);
  switch (type) {
    case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
      RemoveNotificationException(args, arg_i);
      break;
    case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
      RemoveMediaException(args, arg_i);
      break;
    default:
      RemoveExceptionFromHostContentSettingsMap(args, arg_i, type);
      break;
  }
}

void ContentSettingsHandler::SetException(const ListValue* args) {
  size_t arg_i = 0;
  std::string type_string;
  CHECK(args->GetString(arg_i++, &type_string));
  std::string mode;
  CHECK(args->GetString(arg_i++, &mode));
  std::string pattern;
  CHECK(args->GetString(arg_i++, &pattern));
  std::string setting;
  CHECK(args->GetString(arg_i++, &setting));

  ContentSettingsType type = ContentSettingsTypeFromGroupName(type_string);
  if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION ||
      type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS ||
      type == CONTENT_SETTINGS_TYPE_MEDIASTREAM ||
      type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC ||
      type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA) {
    NOTREACHED();
  } else {
    HostContentSettingsMap* settings_map =
        mode == "normal" ? GetContentSettingsMap() :
                           GetOTRContentSettingsMap();

    // The settings map could be null if the mode was OTR but the OTR profile
    // got destroyed before we received this message.
    if (!settings_map)
      return;
    settings_map->SetContentSetting(ContentSettingsPattern::FromString(pattern),
                                    ContentSettingsPattern::Wildcard(),
                                    type,
                                    std::string(),
                                    ContentSettingFromString(setting));
  }
}

void ContentSettingsHandler::CheckExceptionPatternValidity(
    const ListValue* args) {
  size_t arg_i = 0;
  std::string type_string;
  CHECK(args->GetString(arg_i++, &type_string));
  std::string mode_string;
  CHECK(args->GetString(arg_i++, &mode_string));
  std::string pattern_string;
  CHECK(args->GetString(arg_i++, &pattern_string));

  ContentSettingsPattern pattern =
      ContentSettingsPattern::FromString(pattern_string);

  web_ui()->CallJavascriptFunction(
      "ContentSettings.patternValidityCheckComplete",
      base::StringValue(type_string),
      base::StringValue(mode_string),
      base::StringValue(pattern_string),
      base::FundamentalValue(pattern.IsValid()));
}

// static
std::string ContentSettingsHandler::ContentSettingsTypeToGroupName(
    ContentSettingsType type) {
  for (size_t i = 0; i < arraysize(kContentSettingsTypeGroupNames); ++i) {
    if (type == kContentSettingsTypeGroupNames[i].type)
      return kContentSettingsTypeGroupNames[i].name;
  }

  NOTREACHED();
  return std::string();
}

HostContentSettingsMap* ContentSettingsHandler::GetContentSettingsMap() {
  return Profile::FromWebUI(web_ui())->GetHostContentSettingsMap();
}

ProtocolHandlerRegistry* ContentSettingsHandler::GetProtocolHandlerRegistry() {
  return ProtocolHandlerRegistryFactory::GetForProfile(
      Profile::FromWebUI(web_ui()));
}

HostContentSettingsMap*
    ContentSettingsHandler::GetOTRContentSettingsMap() {
  Profile* profile = Profile::FromWebUI(web_ui());
  if (profile->HasOffTheRecordProfile())
    return profile->GetOffTheRecordProfile()->GetHostContentSettingsMap();
  return NULL;
}

void ContentSettingsHandler::RefreshFlashMediaSettings() {
  media_settings_.flash_settings_initialized = false;

  media_settings_.last_flash_refresh_request_id =
      flash_settings_manager_->GetPermissionSettings(
          PP_FLASH_BROWSEROPERATIONS_SETTINGTYPE_CAMERAMIC);
}

void ContentSettingsHandler::OnPepperFlashPrefChanged() {
  ShowFlashMediaLink(DEFAULT_SETTING, false);
  ShowFlashMediaLink(EXCEPTIONS, false);

  PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
  if (prefs->GetBoolean(prefs::kPepperFlashSettingsEnabled))
    RefreshFlashMediaSettings();
  else
    media_settings_.flash_settings_initialized = false;
}

void ContentSettingsHandler::ShowFlashMediaLink(LinkType link_type, bool show) {
  bool& show_link = link_type == DEFAULT_SETTING ?
      media_settings_.show_flash_default_link :
      media_settings_.show_flash_exceptions_link;
  if (show_link != show) {
    web_ui()->CallJavascriptFunction(
        link_type == DEFAULT_SETTING ?
            "ContentSettings.showMediaPepperFlashDefaultLink" :
            "ContentSettings.showMediaPepperFlashExceptionsLink",
        base::FundamentalValue(show));
    show_link = show;
  }
}

void ContentSettingsHandler::UpdateFlashMediaLinksVisibility() {
  if (!media_settings_.flash_settings_initialized ||
      !media_settings_.default_setting_initialized ||
      !media_settings_.exceptions_initialized) {
    return;
  }

  // Flash won't send us notifications when its settings get changed, which
  // means the Flash settings in |media_settings_| may be out-dated, especially
  // after we show links to change Flash settings.
  // In order to avoid confusion, we won't hide the links once they are showed.
  // One exception is that we will hide them when Pepper Flash is disabled
  // (handled in OnPepperFlashPrefChanged()).
  if (media_settings_.show_flash_default_link &&
      media_settings_.show_flash_exceptions_link) {
    return;
  }

  if (!media_settings_.show_flash_default_link) {
    // If both audio and video capture are disabled by policy, the link
    // shouldn't be showed. Flash conforms to the policy in this case because
    // it cannot open those devices. We don't have to look at the Flash
    // settings.
    if (!(media_settings_.policy_disable_audio &&
          media_settings_.policy_disable_video) &&
        media_settings_.flash_default_setting !=
            media_settings_.default_setting) {
      ShowFlashMediaLink(DEFAULT_SETTING, true);
    }
  }
  if (!media_settings_.show_flash_exceptions_link) {
    // If audio or video capture is disabled by policy, we skip comparison of
    // exceptions for audio or video capture, respectively.
    if (!PepperFlashContentSettingsUtils::AreMediaExceptionsEqual(
            media_settings_.default_setting,
            media_settings_.exceptions,
            media_settings_.flash_default_setting,
            media_settings_.flash_exceptions,
            media_settings_.policy_disable_audio,
            media_settings_.policy_disable_video)) {
      ShowFlashMediaLink(EXCEPTIONS, true);
    }
  }
}

}  // namespace options
