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

#include "base/command_line.h"
#include "base/prefs/pref_service.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/content_settings/content_settings_utils.h"
#include "chrome/browser/content_settings/cookie_settings.h"
#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
#include "chrome/browser/favicon/favicon_tab_helper.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/media/media_capture_devices_dispatcher.h"
#include "chrome/browser/plugins/chrome_plugin_service_filter.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/collected_cookies_infobar_delegate.h"
#include "chrome/browser/ui/content_settings/content_setting_bubble_model_delegate.h"
#include "chrome/browser/ui/content_settings/media_setting_changed_infobar_delegate.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/content_settings.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/render_messages.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "grit/ui_resources.h"
#include "net/base/net_util.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"

using content::UserMetricsAction;
using content::WebContents;
using content_settings::SettingInfo;
using content_settings::SettingSource;
using content_settings::SETTING_SOURCE_USER;
using content_settings::SETTING_SOURCE_NONE;

namespace {
struct ContentSettingsTypeIdEntry {
  ContentSettingsType type;
  int id;
};

int GetIdForContentType(const ContentSettingsTypeIdEntry* entries,
                        size_t num_entries,
                        ContentSettingsType type) {
  for (size_t i = 0; i < num_entries; ++i) {
    if (entries[i].type == type)
      return entries[i].id;
  }
  return 0;
}

const content::MediaStreamDevice& GetMediaDeviceById(
    const std::string& device_id,
    const content::MediaStreamDevices& devices) {
  DCHECK(!devices.empty());
  for (content::MediaStreamDevices::const_iterator it = devices.begin();
       it != devices.end(); ++it) {
    if (it->id == device_id)
      return *(it);
  }

  // A device with the |device_id| was not found. It is likely that the device
  // has been unplugged from the OS. Return the first device as the default
  // device.
  return *devices.begin();
}

}  // namespace

ContentSettingTitleAndLinkModel::ContentSettingTitleAndLinkModel(
    Delegate* delegate,
    WebContents* web_contents,
    Profile* profile,
    ContentSettingsType content_type)
    : ContentSettingBubbleModel(web_contents, profile, content_type),
        delegate_(delegate) {
  // Notifications do not have a bubble.
  DCHECK_NE(content_type, CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
  SetBlockedResources();
  SetTitle();
  SetManageLink();
}

void ContentSettingTitleAndLinkModel::SetBlockedResources() {
  TabSpecificContentSettings* settings =
      TabSpecificContentSettings::FromWebContents(web_contents());
  const std::set<std::string>& resources = settings->BlockedResourcesForType(
      content_type());
  for (std::set<std::string>::const_iterator it = resources.begin();
       it != resources.end(); ++it) {
    AddBlockedResource(*it);
  }
}

void ContentSettingTitleAndLinkModel::SetTitle() {
  static const ContentSettingsTypeIdEntry kBlockedTitleIDs[] = {
    {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_TITLE},
    {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_TITLE},
    {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_TITLE},
    {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_MESSAGE},
    {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_TITLE},
    {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT,
        IDS_BLOCKED_DISPLAYING_INSECURE_CONTENT},
    {CONTENT_SETTINGS_TYPE_PPAPI_BROKER,
        IDS_BLOCKED_PPAPI_BROKER_TITLE},
    {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_TITLE},
  };
  // Fields as for kBlockedTitleIDs, above.
  static const ContentSettingsTypeIdEntry
      kResourceSpecificBlockedTitleIDs[] = {
        {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_TITLE},
      };
  static const ContentSettingsTypeIdEntry kAccessedTitleIDs[] = {
    {CONTENT_SETTINGS_TYPE_COOKIES, IDS_ACCESSED_COOKIES_TITLE},
    {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_TITLE},
    {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_TITLE},
  };
  const ContentSettingsTypeIdEntry *title_ids = kBlockedTitleIDs;
  size_t num_title_ids = arraysize(kBlockedTitleIDs);
  if (web_contents() &&
      TabSpecificContentSettings::FromWebContents(
          web_contents())->IsContentAllowed(content_type()) &&
      !TabSpecificContentSettings::FromWebContents(
          web_contents())->IsContentBlocked(content_type())) {
    title_ids = kAccessedTitleIDs;
    num_title_ids = arraysize(kAccessedTitleIDs);
  } else if (!bubble_content().resource_identifiers.empty()) {
    title_ids = kResourceSpecificBlockedTitleIDs;
    num_title_ids = arraysize(kResourceSpecificBlockedTitleIDs);
  }
  int title_id =
      GetIdForContentType(title_ids, num_title_ids, content_type());
  if (title_id)
    set_title(l10n_util::GetStringUTF8(title_id));
}

void ContentSettingTitleAndLinkModel::SetManageLink() {
  static const ContentSettingsTypeIdEntry kLinkIDs[] = {
    {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_LINK},
    {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_LINK},
    {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_LINK},
    {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_LINK},
    {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_LINK},
    {CONTENT_SETTINGS_TYPE_GEOLOCATION, IDS_GEOLOCATION_BUBBLE_MANAGE_LINK},
    {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, IDS_LEARN_MORE},
    {CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS, IDS_HANDLERS_BUBBLE_MANAGE_LINK},
    {CONTENT_SETTINGS_TYPE_MEDIASTREAM, IDS_MEDIASTREAM_BUBBLE_MANAGE_LINK},
    {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_PPAPI_BROKER_BUBBLE_MANAGE_LINK},
    {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOADS_LINK},
    {CONTENT_SETTINGS_TYPE_MIDI_SYSEX, IDS_MIDI_SYSEX_BUBBLE_MANAGE_LINK},
    {CONTENT_SETTINGS_TYPE_SAVE_PASSWORD,
     IDS_OPTIONS_PASSWORDS_MANAGE_PASSWORDS},
  };
  set_manage_link(l10n_util::GetStringUTF8(
      GetIdForContentType(kLinkIDs, arraysize(kLinkIDs), content_type())));
}

void ContentSettingTitleAndLinkModel::OnManageLinkClicked() {
  if (delegate_)
    delegate_->ShowContentSettingsPage(content_type());
}

class ContentSettingTitleLinkAndCustomModel
    : public ContentSettingTitleAndLinkModel {
 public:
  ContentSettingTitleLinkAndCustomModel(Delegate* delegate,
                                        WebContents* web_contents,
                                        Profile* profile,
                                        ContentSettingsType content_type);
  virtual ~ContentSettingTitleLinkAndCustomModel() {}

 private:
  void SetCustomLink();
  virtual void OnCustomLinkClicked() OVERRIDE {}
};

ContentSettingTitleLinkAndCustomModel::ContentSettingTitleLinkAndCustomModel(
    Delegate* delegate,
    WebContents* web_contents,
    Profile* profile,
    ContentSettingsType content_type)
    : ContentSettingTitleAndLinkModel(
          delegate, web_contents, profile, content_type) {
  SetCustomLink();
}

void ContentSettingTitleLinkAndCustomModel::SetCustomLink() {
  static const ContentSettingsTypeIdEntry kCustomIDs[] = {
    {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_INFO},
    {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_LOAD_ALL},
    {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, IDS_ALLOW_INSECURE_CONTENT_BUTTON},
  };
  int custom_link_id =
      GetIdForContentType(kCustomIDs, arraysize(kCustomIDs), content_type());
  if (custom_link_id)
    set_custom_link(l10n_util::GetStringUTF8(custom_link_id));
}

class ContentSettingSingleRadioGroup
    : public ContentSettingTitleLinkAndCustomModel {
 public:
  ContentSettingSingleRadioGroup(Delegate* delegate,
                                 WebContents* web_contents,
                                 Profile* profile,
                                 ContentSettingsType content_type);
  virtual ~ContentSettingSingleRadioGroup();

 protected:
  bool settings_changed() const;

 private:
  void SetRadioGroup();
  void AddException(ContentSetting setting,
                    const std::string& resource_identifier);
  virtual void OnRadioClicked(int radio_index) OVERRIDE;

  ContentSetting block_setting_;
  int selected_item_;
};

ContentSettingSingleRadioGroup::ContentSettingSingleRadioGroup(
    Delegate* delegate,
    WebContents* web_contents,
    Profile* profile,
    ContentSettingsType content_type)
    : ContentSettingTitleLinkAndCustomModel(delegate, web_contents, profile,
                                            content_type),
      block_setting_(CONTENT_SETTING_BLOCK),
      selected_item_(0) {
  SetRadioGroup();
}

ContentSettingSingleRadioGroup::~ContentSettingSingleRadioGroup() {
  if (settings_changed()) {
    ContentSetting setting =
        selected_item_ == 0 ? CONTENT_SETTING_ALLOW : block_setting_;
    const std::set<std::string>& resources =
        bubble_content().resource_identifiers;
    if (resources.empty()) {
      AddException(setting, std::string());
    } else {
      for (std::set<std::string>::const_iterator it = resources.begin();
           it != resources.end(); ++it) {
        AddException(setting, *it);
      }
    }
  }
}

bool ContentSettingSingleRadioGroup::settings_changed() const {
  return selected_item_ != bubble_content().radio_group.default_item;
}

// Initialize the radio group by setting the appropriate labels for the
// content type and setting the default value based on the content setting.
void ContentSettingSingleRadioGroup::SetRadioGroup() {
  GURL url = web_contents()->GetURL();
  string16 display_host;
  net::AppendFormattedHost(
      url,
      profile()->GetPrefs()->GetString(prefs::kAcceptLanguages),
      &display_host);

  if (display_host.empty())
    display_host = ASCIIToUTF16(url.spec());

  const std::set<std::string>& resources =
      bubble_content().resource_identifiers;

  TabSpecificContentSettings* content_settings =
      TabSpecificContentSettings::FromWebContents(web_contents());
  bool allowed =
      !content_settings->IsContentBlocked(content_type());
  DCHECK(!allowed ||
         content_settings->IsContentAllowed(content_type()));

  RadioGroup radio_group;
  radio_group.url = url;

  static const ContentSettingsTypeIdEntry kBlockedAllowIDs[] = {
    {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_UNBLOCK},
    {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_UNBLOCK},
    {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_UNBLOCK},
    {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_UNBLOCK_ALL},
    {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_UNBLOCK},
    {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_UNBLOCK},
    {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_UNBLOCK},
  };
  // Fields as for kBlockedAllowIDs, above.
  static const ContentSettingsTypeIdEntry kResourceSpecificBlockedAllowIDs[] = {
    {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_UNBLOCK},
  };
  static const ContentSettingsTypeIdEntry kAllowedAllowIDs[] = {
    // TODO(bauerb): The string shouldn't be "unblock" (they weren't blocked).
    {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_UNBLOCK},
    {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_NO_ACTION},
    {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_NO_ACTION},
  };

  std::string radio_allow_label;
  if (allowed) {
    int resource_id = GetIdForContentType(kAllowedAllowIDs,
                                          arraysize(kAllowedAllowIDs),
                                          content_type());
    radio_allow_label = (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) ?
        l10n_util::GetStringFUTF8(resource_id, display_host) :
        l10n_util::GetStringUTF8(resource_id);
  } else if (resources.empty()) {
    radio_allow_label = l10n_util::GetStringFUTF8(
        GetIdForContentType(kBlockedAllowIDs, arraysize(kBlockedAllowIDs),
                            content_type()),
        display_host);
  } else {
    radio_allow_label = l10n_util::GetStringFUTF8(
        GetIdForContentType(kResourceSpecificBlockedAllowIDs,
                            arraysize(kResourceSpecificBlockedAllowIDs),
                            content_type()),
        display_host);
  }

  static const ContentSettingsTypeIdEntry kBlockedBlockIDs[] = {
    {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_NO_ACTION},
    {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_NO_ACTION},
    {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_NO_ACTION},
    {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_NO_ACTION},
    {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_NO_ACTION},
    {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_NO_ACTION},
    {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_NO_ACTION},
  };
  static const ContentSettingsTypeIdEntry kAllowedBlockIDs[] = {
    // TODO(bauerb): The string should say "block".
    {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_NO_ACTION},
    {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_BLOCK},
    {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_BLOCK},
  };

  std::string radio_block_label;
  if (allowed) {
    int resource_id = GetIdForContentType(kAllowedBlockIDs,
                                          arraysize(kAllowedBlockIDs),
                                          content_type());
    radio_block_label = (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) ?
        l10n_util::GetStringUTF8(resource_id) :
        l10n_util::GetStringFUTF8(resource_id, display_host);
  } else {
    radio_block_label = l10n_util::GetStringUTF8(
        GetIdForContentType(kBlockedBlockIDs, arraysize(kBlockedBlockIDs),
                            content_type()));
  }

  radio_group.radio_items.push_back(radio_allow_label);
  radio_group.radio_items.push_back(radio_block_label);
  HostContentSettingsMap* map = profile()->GetHostContentSettingsMap();
  CookieSettings* cookie_settings =
      CookieSettings::Factory::GetForProfile(profile()).get();
  ContentSetting most_restrictive_setting;
  SettingSource most_restrictive_setting_source = SETTING_SOURCE_NONE;
  bool most_restrictive_setting_is_wildcard = false;

  if (resources.empty()) {
    if (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) {
      most_restrictive_setting = cookie_settings->GetCookieSetting(
          url, url, true, &most_restrictive_setting_source);
    } else {
      SettingInfo info;
      scoped_ptr<Value> value(map->GetWebsiteSetting(
          url, url, content_type(), std::string(), &info));
      most_restrictive_setting =
          content_settings::ValueToContentSetting(value.get());
      most_restrictive_setting_source = info.source;
      most_restrictive_setting_is_wildcard =
          info.primary_pattern == ContentSettingsPattern::Wildcard() &&
          info.secondary_pattern == ContentSettingsPattern::Wildcard();
    }
  } else {
    most_restrictive_setting = CONTENT_SETTING_ALLOW;
    for (std::set<std::string>::const_iterator it = resources.begin();
         it != resources.end(); ++it) {
      SettingInfo info;
      scoped_ptr<Value> val(map->GetWebsiteSetting(
          url, url, content_type(), *it, &info));
      ContentSetting setting =
          content_settings::ValueToContentSetting(val.get());
      if (setting == CONTENT_SETTING_BLOCK) {
        most_restrictive_setting = CONTENT_SETTING_BLOCK;
        most_restrictive_setting_source = info.source;
        most_restrictive_setting_is_wildcard =
            info.primary_pattern == ContentSettingsPattern::Wildcard() &&
            info.secondary_pattern == ContentSettingsPattern::Wildcard();
        break;
      }
      if (setting == CONTENT_SETTING_ASK) {
        most_restrictive_setting = CONTENT_SETTING_ASK;
        most_restrictive_setting_source = info.source;
        most_restrictive_setting_is_wildcard =
            info.primary_pattern == ContentSettingsPattern::Wildcard() &&
            info.secondary_pattern == ContentSettingsPattern::Wildcard();
      }
    }
  }

  if (content_type() == CONTENT_SETTINGS_TYPE_PLUGINS &&
      most_restrictive_setting == CONTENT_SETTING_ALLOW &&
      most_restrictive_setting_is_wildcard) {
    // In the corner case of unrecognized plugins (which are now blocked by
    // default) we indicate the blocked state in the UI and allow the user to
    // whitelist.
    radio_group.default_item = 1;
  } else if (most_restrictive_setting == CONTENT_SETTING_ALLOW) {
    radio_group.default_item = 0;
    // |block_setting_| is already set to |CONTENT_SETTING_BLOCK|.
  } else {
    radio_group.default_item = 1;
    block_setting_ = most_restrictive_setting;
  }
  if (most_restrictive_setting_source != SETTING_SOURCE_USER) {
    set_radio_group_enabled(false);
  } else {
    set_radio_group_enabled(true);
  }
  selected_item_ = radio_group.default_item;
  set_radio_group(radio_group);
}

void ContentSettingSingleRadioGroup::AddException(
    ContentSetting setting,
    const std::string& resource_identifier) {
  if (profile()) {
    profile()->GetHostContentSettingsMap()->AddExceptionForURL(
        bubble_content().radio_group.url,
        bubble_content().radio_group.url,
        content_type(),
        resource_identifier,
        setting);
  }
}

void ContentSettingSingleRadioGroup::OnRadioClicked(int radio_index) {
  selected_item_ = radio_index;
}

class ContentSettingCookiesBubbleModel : public ContentSettingSingleRadioGroup {
 public:
  ContentSettingCookiesBubbleModel(Delegate* delegate,
                                   WebContents* web_contents,
                                   Profile* profile,
                                   ContentSettingsType content_type);

  virtual ~ContentSettingCookiesBubbleModel();

 private:
  virtual void OnCustomLinkClicked() OVERRIDE;
};

ContentSettingCookiesBubbleModel::ContentSettingCookiesBubbleModel(
    Delegate* delegate,
    WebContents* web_contents,
    Profile* profile,
    ContentSettingsType content_type)
    : ContentSettingSingleRadioGroup(
          delegate, web_contents, profile, content_type) {
  DCHECK_EQ(CONTENT_SETTINGS_TYPE_COOKIES, content_type);
  set_custom_link_enabled(true);
}

ContentSettingCookiesBubbleModel::~ContentSettingCookiesBubbleModel() {
  // On some plattforms e.g. MacOS X it is possible to close a tab while the
  // cookies settings bubble is open. This resets the web contents to NULL.
  if (settings_changed() && web_contents()) {
    CollectedCookiesInfoBarDelegate::Create(
        InfoBarService::FromWebContents(web_contents()));
  }
}

void ContentSettingCookiesBubbleModel::OnCustomLinkClicked() {
  if (!web_contents())
    return;
  content::NotificationService::current()->Notify(
      chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN,
      content::Source<TabSpecificContentSettings>(
          TabSpecificContentSettings::FromWebContents(web_contents())),
      content::NotificationService::NoDetails());
  delegate()->ShowCollectedCookiesDialog(web_contents());
}

class ContentSettingPluginBubbleModel : public ContentSettingSingleRadioGroup {
 public:
  ContentSettingPluginBubbleModel(Delegate* delegate,
                                  WebContents* web_contents,
                                  Profile* profile,
                                  ContentSettingsType content_type);

  virtual ~ContentSettingPluginBubbleModel() {}

 private:
  virtual void OnCustomLinkClicked() OVERRIDE;
};

ContentSettingPluginBubbleModel::ContentSettingPluginBubbleModel(
    Delegate* delegate,
    WebContents* web_contents,
    Profile* profile,
    ContentSettingsType content_type)
    : ContentSettingSingleRadioGroup(
          delegate, web_contents, profile, content_type) {
  DCHECK_EQ(content_type, CONTENT_SETTINGS_TYPE_PLUGINS);
  set_custom_link_enabled(web_contents &&
                          TabSpecificContentSettings::FromWebContents(
                              web_contents)->load_plugins_link_enabled());
}

void ContentSettingPluginBubbleModel::OnCustomLinkClicked() {
  content::RecordAction(UserMetricsAction("ClickToPlay_LoadAll_Bubble"));
  DCHECK(web_contents());
  content::RenderViewHost* host = web_contents()->GetRenderViewHost();
#if defined(ENABLE_PLUGINS)
  ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
      host->GetProcess()->GetID());
#endif
  // TODO(bauerb): We should send the identifiers of blocked plug-ins here.
  host->Send(new ChromeViewMsg_LoadBlockedPlugins(host->GetRoutingID(),
                                                  std::string()));
  set_custom_link_enabled(false);
  TabSpecificContentSettings::FromWebContents(web_contents())->
      set_load_plugins_link_enabled(false);
}

class ContentSettingPopupBubbleModel : public ContentSettingSingleRadioGroup {
 public:
  ContentSettingPopupBubbleModel(Delegate* delegate,
                                 WebContents* web_contents,
                                 Profile* profile,
                                 ContentSettingsType content_type);
  virtual ~ContentSettingPopupBubbleModel() {}

 private:
  void SetPopups();
  virtual void OnPopupClicked(int index) OVERRIDE;
};

ContentSettingPopupBubbleModel::ContentSettingPopupBubbleModel(
    Delegate* delegate,
    WebContents* web_contents,
    Profile* profile,
    ContentSettingsType content_type)
    : ContentSettingSingleRadioGroup(
        delegate, web_contents, profile, content_type) {
  SetPopups();
}


void ContentSettingPopupBubbleModel::SetPopups() {
  std::map<int32, GURL> blocked_popups =
      PopupBlockerTabHelper::FromWebContents(web_contents())
          ->GetBlockedPopupRequests();
  for (std::map<int32, GURL>::const_iterator iter = blocked_popups.begin();
       iter != blocked_popups.end();
       ++iter) {
    std::string title(iter->second.spec());
    // The popup may not have a valid URL.
    if (title.empty())
      title = l10n_util::GetStringUTF8(IDS_TAB_LOADING_TITLE);
    PopupItem popup_item(
        ui::ResourceBundle::GetSharedInstance().GetImageNamed(
            IDR_DEFAULT_FAVICON),
        title,
        iter->first);
    add_popup(popup_item);
  }
}

void ContentSettingPopupBubbleModel::OnPopupClicked(int index) {
  if (web_contents()) {
    PopupBlockerTabHelper::FromWebContents(web_contents())->
        ShowBlockedPopup(bubble_content().popup_items[index].popup_id);
  }
}

// The model for the save password bubble.
SavePasswordBubbleModel::SavePasswordBubbleModel(Delegate* delegate,
                                                 WebContents* web_contents,
                                                 Profile* profile)
    : ContentSettingTitleAndLinkModel(delegate, web_contents, profile,
                                      CONTENT_SETTINGS_TYPE_SAVE_PASSWORD),
      state_(TabSpecificContentSettings::NO_PASSWORD_TO_BE_SAVED) {
  DCHECK(profile);
  TabSpecificContentSettings* content_settings =
      TabSpecificContentSettings::FromWebContents(web_contents);
  state_ = content_settings->GetPasswordSavingState();

  SetTitle();
}

SavePasswordBubbleModel::~SavePasswordBubbleModel() {}

void SavePasswordBubbleModel::SetTitle() {
  int title_id = 0;
  // If the save password icon was accessed, the icon is displayed and the
  // bubble is instantiated
  if (state_ == TabSpecificContentSettings::PASSWORD_TO_BE_SAVED)
    title_id = IDS_SAVE_PASSWORD;

  set_title(l10n_util::GetStringUTF8(title_id));
}

void SavePasswordBubbleModel::OnCancelClicked() {
  TabSpecificContentSettings* content_settings =
      TabSpecificContentSettings::FromWebContents(web_contents());
  content_settings->set_password_action(PasswordFormManager::BLACKLIST);
}

void SavePasswordBubbleModel::OnDoneClicked() {
  TabSpecificContentSettings* content_settings =
      TabSpecificContentSettings::FromWebContents(web_contents());
  content_settings->set_password_action(PasswordFormManager::DO_NOTHING);
}

void SavePasswordBubbleModel::OnSaveClicked() {
  TabSpecificContentSettings* content_settings =
      TabSpecificContentSettings::FromWebContents(web_contents());
  content_settings->set_password_action(PasswordFormManager::SAVE);
}

// The model of the content settings bubble for media settings.
class ContentSettingMediaStreamBubbleModel
    : public ContentSettingTitleAndLinkModel {
 public:
  ContentSettingMediaStreamBubbleModel(Delegate* delegate,
                                       WebContents* web_contents,
                                       Profile* profile);

  virtual ~ContentSettingMediaStreamBubbleModel();

 private:
  void SetTitle();
  // Sets the data for the radio buttons of the bubble.
  void SetRadioGroup();
  // Sets the data for the media menus of the bubble.
  void SetMediaMenus();
  // Updates the camera and microphone setting with the passed |setting|.
  void UpdateSettings(ContentSetting setting);
  // Updates the camera and microphone default device with the passed |type|
  // and device.
  void UpdateDefaultDeviceForType(content::MediaStreamType type,
                                  const std::string& device);

  // ContentSettingBubbleModel implementation.
  virtual void OnRadioClicked(int radio_index) OVERRIDE;
  virtual void OnMediaMenuClicked(content::MediaStreamType type,
                                  const std::string& selected_device) OVERRIDE;

  // The index of the selected radio item.
  int selected_item_;
  // The content settings that are associated with the individual radio
  // buttons.
  ContentSetting radio_item_setting_[2];
  // The state of the microphone and camera access.
  TabSpecificContentSettings::MicrophoneCameraState state_;
};

ContentSettingMediaStreamBubbleModel::ContentSettingMediaStreamBubbleModel(
    Delegate* delegate,
    WebContents* web_contents,
    Profile* profile)
    : ContentSettingTitleAndLinkModel(
          delegate, web_contents, profile, CONTENT_SETTINGS_TYPE_MEDIASTREAM),
      selected_item_(0),
      state_(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED) {
  DCHECK(profile);
  // Initialize the content settings associated with the individual radio
  // buttons.
  radio_item_setting_[0] = CONTENT_SETTING_ASK;
  radio_item_setting_[1] = CONTENT_SETTING_BLOCK;

  TabSpecificContentSettings* content_settings =
      TabSpecificContentSettings::FromWebContents(web_contents);
  state_ = content_settings->GetMicrophoneCameraState();

  SetTitle();
  SetRadioGroup();
  SetMediaMenus();
}

ContentSettingMediaStreamBubbleModel::~ContentSettingMediaStreamBubbleModel() {
  // On some platforms (e.g. MacOS X) it is possible to close a tab while the
  // media stream bubble is open. This resets the web contents to NULL.
  if (!web_contents())
    return;

  bool media_setting_changed = false;
  for (MediaMenuMap::const_iterator it = bubble_content().media_menus.begin();
      it != bubble_content().media_menus.end(); ++it) {
    if (it->second.selected_device.id != it->second.default_device.id) {
      UpdateDefaultDeviceForType(it->first, it->second.selected_device.id);
      media_setting_changed = true;
    }
  }

  // Update the media settings if the radio button selection was changed.
  if (selected_item_ != bubble_content().radio_group.default_item) {
    UpdateSettings(radio_item_setting_[selected_item_]);
    media_setting_changed = true;
  }

  // Trigger the reload infobar if the media setting has been changed.
  if (media_setting_changed) {
    MediaSettingChangedInfoBarDelegate::Create(
        InfoBarService::FromWebContents(web_contents()));
  }
}

void ContentSettingMediaStreamBubbleModel::SetTitle() {
  int title_id = 0;
  switch (state_) {
    case TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED:
      // If neither microphone nor camera stream was accessed, then there is no
      // icon didplayed in the omnibox and no settings bubble availbale. Hence
      // there is no title.
      NOTREACHED();
      return;
    case TabSpecificContentSettings::MICROPHONE_ACCESSED:
      title_id = IDS_MICROPHONE_ACCESSED;
      break;
    case TabSpecificContentSettings::CAMERA_ACCESSED:
      title_id = IDS_CAMERA_ACCESSED;
      break;
    case TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED:
      title_id = IDS_MICROPHONE_CAMERA_ALLOWED;
      break;
    case TabSpecificContentSettings::MICROPHONE_BLOCKED:
      title_id = IDS_MICROPHONE_BLOCKED;
      break;
    case TabSpecificContentSettings::CAMERA_BLOCKED:
      title_id = IDS_CAMERA_BLOCKED;
      break;
    case TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED:
      title_id = IDS_MICROPHONE_CAMERA_BLOCKED;
      break;
  }
  set_title(l10n_util::GetStringUTF8(title_id));
}

void ContentSettingMediaStreamBubbleModel::SetRadioGroup() {
  TabSpecificContentSettings* content_settings =
      TabSpecificContentSettings::FromWebContents(web_contents());
  GURL url = content_settings->media_stream_access_origin();
  RadioGroup radio_group;
  radio_group.url = url;

  string16 display_host_utf16;
  net::AppendFormattedHost(
      url,
      profile()->GetPrefs()->GetString(prefs::kAcceptLanguages),
      &display_host_utf16);
  std::string display_host(UTF16ToUTF8(display_host_utf16));
  if (display_host.empty())
    display_host = url.spec();

  int radio_allow_label_id = 0;
  int radio_block_label_id = 0;
  switch (state_) {
    case TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED:
      NOTREACHED();
      return;
    case TabSpecificContentSettings::MICROPHONE_ACCESSED:
      radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_NO_ACTION;
      radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_BLOCK;
      selected_item_ = 0;
      break;
    case TabSpecificContentSettings::CAMERA_ACCESSED:
      radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_CAMERA_NO_ACTION;
      radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_CAMERA_BLOCK;
      selected_item_ = 0;
      break;
    case TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED:
      radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION;
      radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_BLOCK;
      selected_item_ = 0;
      break;
    case TabSpecificContentSettings::MICROPHONE_BLOCKED:
      if (url.SchemeIsSecure()) {
        radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_ALLOW;
        radio_item_setting_[0] = CONTENT_SETTING_ALLOW;
      } else {
        radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_ASK;
      }

      radio_block_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_NO_ACTION;
      selected_item_ = 1;
      break;
    case TabSpecificContentSettings::CAMERA_BLOCKED:
      if (url.SchemeIsSecure()) {
        radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_ALLOW;
        radio_item_setting_[0] = CONTENT_SETTING_ALLOW;
      } else {
        radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_ASK;
      }

      radio_block_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_NO_ACTION;
      selected_item_ = 1;
      break;
    case TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED:
      if (url.SchemeIsSecure()) {
        radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ALLOW;
        radio_item_setting_[0] = CONTENT_SETTING_ALLOW;
      } else {
        radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ASK;
      }

      radio_block_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION;
      selected_item_ = 1;
      break;
  }

  std::string radio_allow_label = l10n_util::GetStringFUTF8(
      radio_allow_label_id, UTF8ToUTF16(display_host));
  std::string radio_block_label =
      l10n_util::GetStringUTF8(radio_block_label_id);

  radio_group.default_item = selected_item_;
  radio_group.radio_items.push_back(radio_allow_label);
  radio_group.radio_items.push_back(radio_block_label);

  set_radio_group(radio_group);
  set_radio_group_enabled(true);
}

void ContentSettingMediaStreamBubbleModel::UpdateSettings(
    ContentSetting setting) {
  if (profile()) {
    HostContentSettingsMap* content_settings =
        profile()->GetHostContentSettingsMap();
    TabSpecificContentSettings* tab_content_settings =
        TabSpecificContentSettings::FromWebContents(web_contents());
    // The same patterns must be used as in other places (e.g. the infobar) in
    // order to override the existing rule. Otherwise a new rule is created.
    // TODO(markusheintz): Extract to a helper so that there is only a single
    // place to touch.
    ContentSettingsPattern primary_pattern =
        ContentSettingsPattern::FromURLNoWildcard(
            tab_content_settings->media_stream_access_origin());
    ContentSettingsPattern secondary_pattern =
        ContentSettingsPattern::Wildcard();
    if (state_ == TabSpecificContentSettings::MICROPHONE_ACCESSED ||
        state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED ||
        state_ == TabSpecificContentSettings::MICROPHONE_BLOCKED ||
        state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED) {
      content_settings->SetContentSetting(
          primary_pattern, secondary_pattern,
          CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, std::string(), setting);
    }
    if (state_ == TabSpecificContentSettings::CAMERA_ACCESSED ||
        state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED ||
        state_ == TabSpecificContentSettings::CAMERA_BLOCKED ||
        state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED) {
      content_settings->SetContentSetting(
          primary_pattern, secondary_pattern,
          CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, std::string(), setting);
    }
  }
}

void ContentSettingMediaStreamBubbleModel::UpdateDefaultDeviceForType(
    content::MediaStreamType type,
    const std::string& device) {
  PrefService* prefs = profile()->GetPrefs();
  if (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
    prefs->SetString(prefs::kDefaultAudioCaptureDevice, device);
  } else {
    DCHECK_EQ(content::MEDIA_DEVICE_VIDEO_CAPTURE, type);
    prefs->SetString(prefs::kDefaultVideoCaptureDevice, device);
  }
}

void ContentSettingMediaStreamBubbleModel::SetMediaMenus() {
  TabSpecificContentSettings* content_settings =
      TabSpecificContentSettings::FromWebContents(web_contents());
  const std::string& requested_microphone =
       content_settings->media_stream_requested_audio_device();
   const std::string& requested_camera =
       content_settings->media_stream_requested_video_device();

  // Add microphone menu.
  PrefService* prefs = profile()->GetPrefs();
  MediaCaptureDevicesDispatcher* dispatcher =
      MediaCaptureDevicesDispatcher::GetInstance();
  const content::MediaStreamDevices& microphones =
      dispatcher->GetAudioCaptureDevices();

  bool show_mic_menu =
      (state_ == TabSpecificContentSettings::MICROPHONE_ACCESSED ||
       state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED ||
       state_ == TabSpecificContentSettings::MICROPHONE_BLOCKED ||
       state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED);
  bool show_camera_menu =
      (state_ == TabSpecificContentSettings::CAMERA_ACCESSED ||
       state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED ||
       state_ == TabSpecificContentSettings::CAMERA_BLOCKED ||
       state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED);
  DCHECK(show_mic_menu || show_camera_menu);

  if (show_mic_menu) {
    MediaMenu mic_menu;
    mic_menu.label = l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_MIC_LABEL);
    if (!microphones.empty()) {
      std::string preferred_mic;
      if (requested_microphone.empty()) {
        preferred_mic = prefs->GetString(prefs::kDefaultAudioCaptureDevice);
        mic_menu.disabled = false;
      } else {
        // Set the |disabled| to true in order to disable the device selection
        // menu on the media settings bubble. This must be done if the website
        // manages the microphone devices itself.
        preferred_mic = requested_microphone;
        mic_menu.disabled = true;
      }

      mic_menu.default_device = GetMediaDeviceById(preferred_mic, microphones);
      mic_menu.selected_device = mic_menu.default_device;
    }
    add_media_menu(content::MEDIA_DEVICE_AUDIO_CAPTURE, mic_menu);
  }

  if (show_camera_menu) {
    const content::MediaStreamDevices& cameras =
        dispatcher->GetVideoCaptureDevices();
    MediaMenu camera_menu;
    camera_menu.label =
        l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_CAMERA_LABEL);
    if (!cameras.empty()) {
      std::string preferred_camera;
      if (requested_camera.empty()) {
        preferred_camera = prefs->GetString(prefs::kDefaultVideoCaptureDevice);
        camera_menu.disabled = false;
      } else {
        // Disable the menu since the website is managing the camera devices
        // itself.
        preferred_camera = requested_camera;
        camera_menu.disabled = true;
      }

      camera_menu.default_device =
          GetMediaDeviceById(preferred_camera, cameras);
      camera_menu.selected_device = camera_menu.default_device;
    }
    add_media_menu(content::MEDIA_DEVICE_VIDEO_CAPTURE, camera_menu);
  }
}

void ContentSettingMediaStreamBubbleModel::OnRadioClicked(int radio_index) {
  selected_item_ = radio_index;
}

void ContentSettingMediaStreamBubbleModel::OnMediaMenuClicked(
    content::MediaStreamType type,
    const std::string& selected_device_id) {
  DCHECK(type == content::MEDIA_DEVICE_AUDIO_CAPTURE ||
         type == content::MEDIA_DEVICE_VIDEO_CAPTURE);
  DCHECK_EQ(1U, bubble_content().media_menus.count(type));
  MediaCaptureDevicesDispatcher* dispatcher =
      MediaCaptureDevicesDispatcher::GetInstance();
  const content::MediaStreamDevices& devices =
      (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) ?
          dispatcher->GetAudioCaptureDevices() :
          dispatcher->GetVideoCaptureDevices();
  set_selected_device(GetMediaDeviceById(selected_device_id, devices));
}

class ContentSettingDomainListBubbleModel
    : public ContentSettingTitleAndLinkModel {
 public:
  ContentSettingDomainListBubbleModel(Delegate* delegate,
                                      WebContents* web_contents,
                                      Profile* profile,
                                      ContentSettingsType content_type);
  virtual ~ContentSettingDomainListBubbleModel() {}

 private:
  void MaybeAddDomainList(const std::set<std::string>& hosts, int title_id);
  void SetDomainsAndCustomLink();
  virtual void OnCustomLinkClicked() OVERRIDE;
};

ContentSettingDomainListBubbleModel::ContentSettingDomainListBubbleModel(
    Delegate* delegate,
    WebContents* web_contents,
    Profile* profile,
    ContentSettingsType content_type)
    : ContentSettingTitleAndLinkModel(
        delegate, web_contents, profile, content_type) {
  DCHECK_EQ(CONTENT_SETTINGS_TYPE_GEOLOCATION, content_type) <<
      "SetDomains currently only supports geolocation content type";
  SetDomainsAndCustomLink();
}

void ContentSettingDomainListBubbleModel::MaybeAddDomainList(
    const std::set<std::string>& hosts, int title_id) {
  if (!hosts.empty()) {
    DomainList domain_list;
    domain_list.title = l10n_util::GetStringUTF8(title_id);
    domain_list.hosts = hosts;
    add_domain_list(domain_list);
  }
}

void ContentSettingDomainListBubbleModel::SetDomainsAndCustomLink() {
  TabSpecificContentSettings* content_settings =
      TabSpecificContentSettings::FromWebContents(web_contents());
  const ContentSettingsUsagesState& usages =
      content_settings->geolocation_usages_state();
  ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state;
  unsigned int tab_state_flags = 0;
  usages.GetDetailedInfo(&formatted_hosts_per_state, &tab_state_flags);
  // Divide the tab's current geolocation users into sets according to their
  // permission state.
  MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_ALLOW],
                     IDS_GEOLOCATION_BUBBLE_SECTION_ALLOWED);

  MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_BLOCK],
                     IDS_GEOLOCATION_BUBBLE_SECTION_DENIED);

  if (tab_state_flags & ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION) {
    set_custom_link(l10n_util::GetStringUTF8(
        IDS_GEOLOCATION_BUBBLE_CLEAR_LINK));
    set_custom_link_enabled(true);
  } else if (tab_state_flags &
             ContentSettingsUsagesState::TABSTATE_HAS_CHANGED) {
    set_custom_link(l10n_util::GetStringUTF8(
        IDS_GEOLOCATION_BUBBLE_REQUIRE_RELOAD_TO_CLEAR));
  }
}

void ContentSettingDomainListBubbleModel::OnCustomLinkClicked() {
  if (!web_contents())
    return;
  // Reset this embedder's entry to default for each of the requesting
  // origins currently on the page.
  const GURL& embedder_url = web_contents()->GetURL();
  TabSpecificContentSettings* content_settings =
      TabSpecificContentSettings::FromWebContents(web_contents());
  const ContentSettingsUsagesState::StateMap& state_map =
      content_settings->geolocation_usages_state().state_map();
  HostContentSettingsMap* settings_map =
      profile()->GetHostContentSettingsMap();

  for (ContentSettingsUsagesState::StateMap::const_iterator it =
       state_map.begin(); it != state_map.end(); ++it) {
    settings_map->SetContentSetting(
        ContentSettingsPattern::FromURLNoWildcard(it->first),
        ContentSettingsPattern::FromURLNoWildcard(embedder_url),
        CONTENT_SETTINGS_TYPE_GEOLOCATION,
        std::string(),
        CONTENT_SETTING_DEFAULT);
  }
}

class ContentSettingMixedScriptBubbleModel
    : public ContentSettingTitleLinkAndCustomModel {
 public:
  ContentSettingMixedScriptBubbleModel(Delegate* delegate,
                                       WebContents* web_contents,
                                       Profile* profile,
                                       ContentSettingsType content_type);

  virtual ~ContentSettingMixedScriptBubbleModel() {}

 private:
  virtual void OnCustomLinkClicked() OVERRIDE;
};

ContentSettingMixedScriptBubbleModel::ContentSettingMixedScriptBubbleModel(
    Delegate* delegate,
    WebContents* web_contents,
    Profile* profile,
    ContentSettingsType content_type)
    : ContentSettingTitleLinkAndCustomModel(
        delegate, web_contents, profile, content_type) {
  DCHECK_EQ(content_type, CONTENT_SETTINGS_TYPE_MIXEDSCRIPT);
  set_custom_link_enabled(true);
}

void ContentSettingMixedScriptBubbleModel::OnCustomLinkClicked() {
  content::RecordAction(UserMetricsAction("MixedScript_LoadAnyway_Bubble"));
  DCHECK(web_contents());
  content::RenderViewHost* host = web_contents()->GetRenderViewHost();
  host->Send(new ChromeViewMsg_SetAllowRunningInsecureContent(
      host->GetRoutingID(), true));
}

ContentSettingRPHBubbleModel::ContentSettingRPHBubbleModel(
    Delegate* delegate,
    WebContents* web_contents,
    Profile* profile,
    ProtocolHandlerRegistry* registry,
    ContentSettingsType content_type)
    : ContentSettingTitleAndLinkModel(
          delegate, web_contents, profile, content_type),
      selected_item_(0),
      registry_(registry),
      pending_handler_(ProtocolHandler::EmptyProtocolHandler()),
      previous_handler_(ProtocolHandler::EmptyProtocolHandler()) {

  DCHECK_EQ(CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS, content_type);

  TabSpecificContentSettings* content_settings =
      TabSpecificContentSettings::FromWebContents(web_contents);
  pending_handler_ = content_settings->pending_protocol_handler();
  previous_handler_ = content_settings->previous_protocol_handler();

  string16 protocol;
  if (pending_handler_.protocol() == "mailto") {
    protocol = l10n_util::GetStringUTF16(
        IDS_REGISTER_PROTOCOL_HANDLER_MAILTO_NAME);
  } else if (pending_handler_.protocol() == "webcal") {
    protocol = l10n_util::GetStringUTF16(
        IDS_REGISTER_PROTOCOL_HANDLER_WEBCAL_NAME);
  } else {
    protocol = UTF8ToUTF16(pending_handler_.protocol());
  }

  if (previous_handler_.IsEmpty()) {
    set_title(l10n_util::GetStringFUTF8(
        IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM,
        pending_handler_.title(), UTF8ToUTF16(pending_handler_.url().host()),
        protocol));
  } else {
    set_title(l10n_util::GetStringFUTF8(
        IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM_REPLACE,
        pending_handler_.title(), UTF8ToUTF16(pending_handler_.url().host()),
        protocol, previous_handler_.title()));
  }

  std::string radio_allow_label =
      l10n_util::GetStringFUTF8(IDS_REGISTER_PROTOCOL_HANDLER_ACCEPT,
                                pending_handler_.title());
  std::string radio_deny_label =
      l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_DENY);
  std::string radio_ignore_label =
      l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_IGNORE);

  GURL url = web_contents->GetURL();
  RadioGroup radio_group;
  radio_group.url = url;

  radio_group.radio_items.push_back(radio_allow_label);
  radio_group.radio_items.push_back(radio_deny_label);
  radio_group.radio_items.push_back(radio_ignore_label);
  ContentSetting setting =
      content_settings->pending_protocol_handler_setting();
  if (setting == CONTENT_SETTING_ALLOW)
    radio_group.default_item = RPH_ALLOW;
  else if (setting == CONTENT_SETTING_BLOCK)
    radio_group.default_item = RPH_BLOCK;
  else
    radio_group.default_item = RPH_IGNORE;

  selected_item_ = radio_group.default_item;
  set_radio_group_enabled(true);
  set_radio_group(radio_group);
}

void ContentSettingRPHBubbleModel::OnRadioClicked(int radio_index) {
  if (selected_item_ == radio_index)
    return;

  selected_item_ = radio_index;

  if (radio_index == RPH_ALLOW)
    RegisterProtocolHandler();
  else if (radio_index == RPH_BLOCK)
    UnregisterProtocolHandler();
  else if (radio_index == RPH_IGNORE)
    IgnoreProtocolHandler();
  else
    NOTREACHED();
}

void ContentSettingRPHBubbleModel::OnDoneClicked() {
  // The user has one chance to deal with the RPH content setting UI,
  // then we remove it.
  TabSpecificContentSettings::FromWebContents(web_contents())->
      ClearPendingProtocolHandler();
  content::NotificationService::current()->Notify(
      chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
      content::Source<WebContents>(web_contents()),
      content::NotificationService::NoDetails());
}

void ContentSettingRPHBubbleModel::RegisterProtocolHandler() {
  // A no-op if the handler hasn't been ignored, but needed in case the user
  // selects sequences like register/ignore/register.
  registry_->RemoveIgnoredHandler(pending_handler_);

  registry_->OnAcceptRegisterProtocolHandler(pending_handler_);
  TabSpecificContentSettings::FromWebContents(web_contents())->
      set_pending_protocol_handler_setting(CONTENT_SETTING_ALLOW);
}

void ContentSettingRPHBubbleModel::UnregisterProtocolHandler() {
  registry_->OnDenyRegisterProtocolHandler(pending_handler_);
  TabSpecificContentSettings::FromWebContents(web_contents())->
      set_pending_protocol_handler_setting(CONTENT_SETTING_BLOCK);
  ClearOrSetPreviousHandler();
}

void ContentSettingRPHBubbleModel::IgnoreProtocolHandler() {
  registry_->OnIgnoreRegisterProtocolHandler(pending_handler_);
  TabSpecificContentSettings::FromWebContents(web_contents())->
      set_pending_protocol_handler_setting(CONTENT_SETTING_DEFAULT);
  ClearOrSetPreviousHandler();
}

void ContentSettingRPHBubbleModel::ClearOrSetPreviousHandler() {
  if (previous_handler_.IsEmpty()) {
    registry_->ClearDefault(pending_handler_.protocol());
  } else {
    registry_->OnAcceptRegisterProtocolHandler(previous_handler_);
  }
}

// TODO(toyoshim): Should share as many code with geolocation as possible.
class ContentSettingMIDISysExBubbleModel
    : public ContentSettingTitleAndLinkModel {
 public:
  ContentSettingMIDISysExBubbleModel(Delegate* delegate,
                                     WebContents* web_contents,
                                     Profile* profile,
                                     ContentSettingsType content_type);
  virtual ~ContentSettingMIDISysExBubbleModel() {}

 private:
  void MaybeAddDomainList(const std::set<std::string>& hosts, int title_id);
  void SetDomainsAndCustomLink();
  virtual void OnCustomLinkClicked() OVERRIDE;
};

ContentSettingMIDISysExBubbleModel::ContentSettingMIDISysExBubbleModel(
    Delegate* delegate,
    WebContents* web_contents,
    Profile* profile,
    ContentSettingsType content_type)
    : ContentSettingTitleAndLinkModel(
        delegate, web_contents, profile, content_type) {
  DCHECK_EQ(CONTENT_SETTINGS_TYPE_MIDI_SYSEX, content_type);
  SetDomainsAndCustomLink();
}

void ContentSettingMIDISysExBubbleModel::MaybeAddDomainList(
    const std::set<std::string>& hosts, int title_id) {
  if (!hosts.empty()) {
    DomainList domain_list;
    domain_list.title = l10n_util::GetStringUTF8(title_id);
    domain_list.hosts = hosts;
    add_domain_list(domain_list);
  }
}

void ContentSettingMIDISysExBubbleModel::SetDomainsAndCustomLink() {
  TabSpecificContentSettings* content_settings =
      TabSpecificContentSettings::FromWebContents(web_contents());
  const ContentSettingsUsagesState& usages_state =
      content_settings->midi_usages_state();
  ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state;
  unsigned int tab_state_flags = 0;
  usages_state.GetDetailedInfo(&formatted_hosts_per_state, &tab_state_flags);
  // Divide the tab's current MIDI sysex users into sets according to their
  // permission state.
  MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_ALLOW],
                     IDS_MIDI_SYSEX_BUBBLE_ALLOWED);

  MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_BLOCK],
                     IDS_MIDI_SYSEX_BUBBLE_DENIED);

  if (tab_state_flags & ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION) {
    set_custom_link(l10n_util::GetStringUTF8(
        IDS_MIDI_SYSEX_BUBBLE_CLEAR_LINK));
    set_custom_link_enabled(true);
  } else if (tab_state_flags &
             ContentSettingsUsagesState::TABSTATE_HAS_CHANGED) {
    set_custom_link(l10n_util::GetStringUTF8(
        IDS_MIDI_SYSEX_BUBBLE_REQUIRE_RELOAD_TO_CLEAR));
  }
}

void ContentSettingMIDISysExBubbleModel::OnCustomLinkClicked() {
  if (!web_contents())
    return;
  // Reset this embedder's entry to default for each of the requesting
  // origins currently on the page.
  TabSpecificContentSettings* content_settings =
      TabSpecificContentSettings::FromWebContents(web_contents());
  const ContentSettingsUsagesState::StateMap& state_map =
      content_settings->midi_usages_state().state_map();
  HostContentSettingsMap* settings_map =
      profile()->GetHostContentSettingsMap();

  for (ContentSettingsUsagesState::StateMap::const_iterator it =
       state_map.begin(); it != state_map.end(); ++it) {
    settings_map->SetContentSetting(
        ContentSettingsPattern::FromURLNoWildcard(it->first),
        ContentSettingsPattern::Wildcard(),
        CONTENT_SETTINGS_TYPE_MIDI_SYSEX,
        std::string(),
        CONTENT_SETTING_DEFAULT);
  }
}

// static
ContentSettingBubbleModel*
    ContentSettingBubbleModel::CreateContentSettingBubbleModel(
        Delegate* delegate,
        WebContents* web_contents,
        Profile* profile,
        ContentSettingsType content_type) {
  if (content_type == CONTENT_SETTINGS_TYPE_SAVE_PASSWORD) {
    return new SavePasswordBubbleModel(delegate, web_contents, profile);
  }
  if (content_type == CONTENT_SETTINGS_TYPE_COOKIES) {
    return new ContentSettingCookiesBubbleModel(delegate, web_contents, profile,
                                                content_type);
  }
  if (content_type == CONTENT_SETTINGS_TYPE_POPUPS) {
    return new ContentSettingPopupBubbleModel(delegate, web_contents, profile,
                                              content_type);
  }
  if (content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
    return new ContentSettingDomainListBubbleModel(delegate, web_contents,
                                                   profile, content_type);
  }
  if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM) {
    return new ContentSettingMediaStreamBubbleModel(delegate, web_contents,
                                                    profile);
  }
  if (content_type == CONTENT_SETTINGS_TYPE_PLUGINS) {
    return new ContentSettingPluginBubbleModel(delegate, web_contents, profile,
                                               content_type);
  }
  if (content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT) {
    return new ContentSettingMixedScriptBubbleModel(delegate, web_contents,
                                                    profile, content_type);
  }
  if (content_type == CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS) {
    ProtocolHandlerRegistry* registry =
        ProtocolHandlerRegistryFactory::GetForProfile(profile);
    return new ContentSettingRPHBubbleModel(delegate, web_contents, profile,
                                            registry, content_type);
  }
  if (content_type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX) {
    return new ContentSettingMIDISysExBubbleModel(delegate, web_contents,
                                                  profile, content_type);
  }
  return new ContentSettingSingleRadioGroup(delegate, web_contents, profile,
                                            content_type);
}

ContentSettingBubbleModel::ContentSettingBubbleModel(
    WebContents* web_contents,
    Profile* profile,
    ContentSettingsType content_type)
    : web_contents_(web_contents),
      profile_(profile),
      content_type_(content_type) {
  registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
                 content::Source<WebContents>(web_contents));
  registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
                 content::Source<Profile>(profile_));
}

ContentSettingBubbleModel::~ContentSettingBubbleModel() {
}

ContentSettingBubbleModel::RadioGroup::RadioGroup() : default_item(0) {}

ContentSettingBubbleModel::RadioGroup::~RadioGroup() {}

ContentSettingBubbleModel::DomainList::DomainList() {}

ContentSettingBubbleModel::DomainList::~DomainList() {}

ContentSettingBubbleModel::MediaMenu::MediaMenu() : disabled(false) {}

ContentSettingBubbleModel::MediaMenu::~MediaMenu() {}

ContentSettingBubbleModel::BubbleContent::BubbleContent()
    : radio_group_enabled(false),
      custom_link_enabled(false) {
}

ContentSettingBubbleModel::BubbleContent::~BubbleContent() {}


void ContentSettingBubbleModel::AddBlockedResource(
    const std::string& resource_identifier) {
  bubble_content_.resource_identifiers.insert(resource_identifier);
}

void ContentSettingBubbleModel::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) {
    DCHECK_EQ(web_contents_,
              content::Source<WebContents>(source).ptr());
    web_contents_ = NULL;
  } else {
    DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type);
    DCHECK_EQ(profile_, content::Source<Profile>(source).ptr());
    profile_ = NULL;
  }
}
