diff options
author | bulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-09 11:34:51 +0000 |
---|---|---|
committer | bulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-09 11:34:51 +0000 |
commit | 5ec40cfbe054961db55591c94e46979c4c4d53d7 (patch) | |
tree | 9412e0b34a4da5569e5d2c5d06edb4885f9a9d3d /chrome | |
parent | d6d0cf6a3dea6ec00a70781cca4902e133090647 (diff) | |
download | chromium_src-5ec40cfbe054961db55591c94e46979c4c4d53d7.zip chromium_src-5ec40cfbe054961db55591c94e46979c4c4d53d7.tar.gz chromium_src-5ec40cfbe054961db55591c94e46979c4c4d53d7.tar.bz2 |
Adds ContentSettingBubbleModel.
Review URL: http://codereview.chromium.org/668075
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41021 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/content_setting_bubble_model.cc | 188 | ||||
-rw-r--r-- | chrome/browser/content_setting_bubble_model.h | 94 | ||||
-rw-r--r-- | chrome/browser/content_setting_bubble_model_unittest.cc | 45 | ||||
-rw-r--r-- | chrome/browser/gtk/content_blocked_bubble_gtk.cc | 234 | ||||
-rw-r--r-- | chrome/browser/gtk/content_blocked_bubble_gtk.h | 55 | ||||
-rw-r--r-- | chrome/browser/gtk/location_bar_view_gtk.cc | 9 | ||||
-rw-r--r-- | chrome/browser/gtk/location_bar_view_gtk.h | 4 | ||||
-rw-r--r-- | chrome/browser/views/content_blocked_bubble_contents.cc | 183 | ||||
-rw-r--r-- | chrome/browser/views/content_blocked_bubble_contents.h | 32 | ||||
-rw-r--r-- | chrome/browser/views/location_bar_view.cc | 16 | ||||
-rwxr-xr-x | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 3 |
12 files changed, 543 insertions, 322 deletions
diff --git a/chrome/browser/content_setting_bubble_model.cc b/chrome/browser/content_setting_bubble_model.cc new file mode 100644 index 0000000..e361b12 --- /dev/null +++ b/chrome/browser/content_setting_bubble_model.cc @@ -0,0 +1,188 @@ +// Copyright (c) 2010 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/content_setting_bubble_model.h" + +#include "app/l10n_util.h" +#include "chrome/browser/blocked_popup_container.h" +#include "chrome/browser/host_content_settings_map.h" +#include "chrome/browser/pref_service.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents_delegate.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/pref_names.h" +#include "grit/generated_resources.h" +#include "net/base/net_util.h" + +class ContentSettingTitleAndLinkModel : public ContentSettingBubbleModel { + public: + ContentSettingTitleAndLinkModel(TabContents* tab_contents, Profile* profile, + ContentSettingsType content_type) + : ContentSettingBubbleModel(tab_contents, profile, content_type) { + SetTitle(); + SetManageLink(); + } + + private: + void SetTitle() { + static const int kTitleIDs[CONTENT_SETTINGS_NUM_TYPES] = { + IDS_BLOCKED_COOKIES_TITLE, + IDS_BLOCKED_IMAGES_TITLE, + IDS_BLOCKED_JAVASCRIPT_TITLE, + IDS_BLOCKED_PLUGINS_TITLE, + IDS_BLOCKED_POPUPS_TITLE, + }; + set_title(l10n_util::GetStringUTF8(kTitleIDs[content_type()])); + } + + void SetManageLink() { + static const int kLinkIDs[CONTENT_SETTINGS_NUM_TYPES] = { + IDS_BLOCKED_COOKIES_LINK, + IDS_BLOCKED_IMAGES_LINK, + IDS_BLOCKED_JAVASCRIPT_LINK, + IDS_BLOCKED_PLUGINS_LINK, + IDS_BLOCKED_POPUPS_LINK, + }; + set_manage_link(l10n_util::GetStringUTF8(kLinkIDs[content_type()])); + } + + virtual void OnManageLinkClicked() { + if (tab_contents()) + tab_contents()->delegate()->ShowContentSettingsWindow(content_type()); + } +}; + +class ContentSettingSingleRadioGroup : public ContentSettingTitleAndLinkModel { + public: + ContentSettingSingleRadioGroup(TabContents* tab_contents, Profile* profile, + ContentSettingsType content_type) + : ContentSettingTitleAndLinkModel(tab_contents, profile, content_type) { + SetRadioGroups(); + } + + private: + void SetRadioGroups() { + GURL url = tab_contents()->GetURL(); + std::wstring display_host_wide; + net::AppendFormattedHost(url, + profile()->GetPrefs()->GetString(prefs::kAcceptLanguages), + &display_host_wide, NULL, NULL); + std::string display_host(WideToUTF8(display_host_wide)); + + RadioGroup radio_group; + radio_group.host = url.host(); + + static const int kAllowIDs[CONTENT_SETTINGS_NUM_TYPES] = { + 0, // We don't manage cookies here. + IDS_BLOCKED_IMAGES_UNBLOCK, + IDS_BLOCKED_JAVASCRIPT_UNBLOCK, + IDS_BLOCKED_PLUGINS_UNBLOCK, + IDS_BLOCKED_POPUPS_UNBLOCK, + }; + std::string radio_allow_label; + radio_allow_label = l10n_util::GetStringFUTF8( + kAllowIDs[content_type()], UTF8ToUTF16(display_host)); + + static const int kBlockIDs[CONTENT_SETTINGS_NUM_TYPES] = { + 0, // We don't manage cookies here. + IDS_BLOCKED_IMAGES_NO_ACTION, + IDS_BLOCKED_JAVASCRIPT_NO_ACTION, + IDS_BLOCKED_PLUGINS_NO_ACTION, + IDS_BLOCKED_POPUPS_NO_ACTION, + }; + std::string radio_block_label; + radio_block_label = l10n_util::GetStringFUTF8( + kBlockIDs[content_type()], UTF8ToUTF16(display_host)); + + radio_group.radio_items.push_back(radio_allow_label); + radio_group.radio_items.push_back(radio_block_label); + radio_group.default_item = + profile()->GetHostContentSettingsMap()->GetContentSetting(url, + content_type()) == CONTENT_SETTING_ALLOW ? 0 : 1; + add_radio_group(radio_group); + } + + virtual void OnRadioClicked(int radio_group, int radio_index) { + profile()->GetHostContentSettingsMap()->SetContentSetting( + bubble_content().radio_groups[radio_group].host, + content_type(), + radio_index == 0 ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK); + } +}; + +class ContentSettingPopupBubbleModel : public ContentSettingSingleRadioGroup { + public: + ContentSettingPopupBubbleModel(TabContents* tab_contents, Profile* profile, + ContentSettingsType content_type) + : ContentSettingSingleRadioGroup(tab_contents, profile, content_type) { + SetPopups(); + } + + private: + void SetPopups() { + BlockedPopupContainer::BlockedContents blocked_contents; + DCHECK(tab_contents()->blocked_popup_container()); + tab_contents()->blocked_popup_container()->GetBlockedContents( + &blocked_contents); + for (BlockedPopupContainer::BlockedContents::const_iterator + i(blocked_contents.begin()); i != blocked_contents.end(); ++i) { + std::string title(UTF16ToUTF8((*i)->GetTitle())); + // The popup may not have committed a load yet, in which case it won't + // have a URL or title. + if (title.empty()) + title = l10n_util::GetStringUTF8(IDS_TAB_LOADING_TITLE); + PopupItem popup_item; + popup_item.title = title; + popup_item.bitmap = (*i)->GetFavIcon(); + popup_item.tab_contents = (*i); + add_popup(popup_item); + } + } + + virtual void OnPopupClicked(int index) { + if (tab_contents() && tab_contents()->blocked_popup_container()) { + tab_contents()->blocked_popup_container()->LaunchPopupForContents( + bubble_content().popup_items[index].tab_contents); + } + } +}; + +// static +ContentSettingBubbleModel* + ContentSettingBubbleModel::CreateContentSettingBubbleModel( + TabContents* tab_contents, + Profile* profile, + ContentSettingsType content_type) { + if (content_type == CONTENT_SETTINGS_TYPE_COOKIES) { + return new ContentSettingTitleAndLinkModel(tab_contents, profile, + content_type); + } + if (content_type == CONTENT_SETTINGS_TYPE_POPUPS) { + return new ContentSettingPopupBubbleModel(tab_contents, profile, + content_type); + } + return new ContentSettingSingleRadioGroup(tab_contents, profile, + content_type); +} + +ContentSettingBubbleModel::ContentSettingBubbleModel( + TabContents* tab_contents, Profile* profile, + ContentSettingsType content_type) + : tab_contents_(tab_contents), profile_(profile), + content_type_(content_type) { + registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED, + Source<TabContents>(tab_contents)); +} + +ContentSettingBubbleModel::~ContentSettingBubbleModel() { +} + +void ContentSettingBubbleModel::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + DCHECK(type == NotificationType::TAB_CONTENTS_DESTROYED); + DCHECK(source == Source<TabContents>(tab_contents_)); + tab_contents_ = NULL; +} diff --git a/chrome/browser/content_setting_bubble_model.h b/chrome/browser/content_setting_bubble_model.h new file mode 100644 index 0000000..dcbafb7 --- /dev/null +++ b/chrome/browser/content_setting_bubble_model.h @@ -0,0 +1,94 @@ +// Copyright (c) 2010 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. + +#ifndef CHROME_BROWSER_CONTENT_SETTING_BUBBLE_MODEL_H_ +#define CHROME_BROWSER_CONTENT_SETTING_BUBBLE_MODEL_H_ + +#include <string> +#include <vector> + +#include "chrome/common/content_settings.h" +#include "chrome/common/notification_observer.h" +#include "chrome/common/notification_registrar.h" +#include "third_party/skia/include/core/SkBitmap.h" + +class Profile; +class SkBitmap; +class TabContents; + +// This model provides data for ContentSettingBubble, and also controls +// the action triggered when the allow / block radio buttons are triggered. +class ContentSettingBubbleModel : public NotificationObserver { + public: + virtual ~ContentSettingBubbleModel(); + + static ContentSettingBubbleModel* CreateContentSettingBubbleModel( + TabContents* tab_contents, + Profile* profile, + ContentSettingsType content_type); + + ContentSettingsType content_type() const { return content_type_; } + + struct PopupItem { + SkBitmap bitmap; + std::string title; + TabContents* tab_contents; + }; + typedef std::vector<PopupItem> PopupItems; + + typedef std::vector<std::string> RadioItems; + struct RadioGroup { + std::string host; + std::string title; + RadioItems radio_items; + int default_item; + }; + typedef std::vector<RadioGroup> RadioGroups; + + struct BubbleContent { + std::string title; + PopupItems popup_items; + RadioGroups radio_groups; + std::string manage_link; + }; + + const BubbleContent& bubble_content() const { return bubble_content_; } + + // NotificationObserver: + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + virtual void OnRadioClicked(int radio_group, int radio_index) {} + virtual void OnPopupClicked(int index) {} + virtual void OnManageLinkClicked() {} + + protected: + ContentSettingBubbleModel(TabContents* tab_contents, Profile* profile, + ContentSettingsType content_type); + + TabContents* tab_contents() const { return tab_contents_; } + Profile* profile() const { return profile_; } + + void set_title(const std::string& title) { bubble_content_.title = title; } + void add_popup(const PopupItem& popup) { + bubble_content_.popup_items.push_back(popup); + } + void add_radio_group(const RadioGroup& radio_group) { + bubble_content_.radio_groups.push_back(radio_group); + } + void set_manage_link(const std::string& link) { + bubble_content_.manage_link = link; + } + + private: + TabContents* tab_contents_; + Profile* profile_; + ContentSettingsType content_type_; + BubbleContent bubble_content_; + // A registrar for listening for TAB_CONTENTS_DESTROYED notifications. + NotificationRegistrar registrar_; +}; + +#endif // CHROME_BROWSER_CONTENT_SETTING_BUBBLE_MODEL_H_ diff --git a/chrome/browser/content_setting_bubble_model_unittest.cc b/chrome/browser/content_setting_bubble_model_unittest.cc new file mode 100644 index 0000000..d75ceff --- /dev/null +++ b/chrome/browser/content_setting_bubble_model_unittest.cc @@ -0,0 +1,45 @@ +// Copyright (c) 2010 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/content_setting_bubble_model.h" + +#include "chrome/browser/profile.h" +#include "chrome/browser/renderer_host/test/test_render_view_host.h" +#include "chrome/browser/tab_contents/test_tab_contents.h" +#include "chrome/test/testing_profile.h" +#include "testing/gtest/include/gtest/gtest.h" + +typedef RenderViewHostTestHarness ContentSettingBubbleModelTest; + +TEST_F(ContentSettingBubbleModelTest, ImageRadios) { + TestTabContents tab_contents(profile_.get(), NULL); + RenderViewHostDelegate::Resource* render_view_host_delegate = &tab_contents; + render_view_host_delegate->OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES); + + scoped_ptr<ContentSettingBubbleModel> content_setting_bubble_model( + ContentSettingBubbleModel::CreateContentSettingBubbleModel( + &tab_contents, profile_.get(), CONTENT_SETTINGS_TYPE_IMAGES)); + const ContentSettingBubbleModel::BubbleContent& bubble_content = + content_setting_bubble_model->bubble_content(); + EXPECT_EQ(1U, bubble_content.radio_groups.size()); + EXPECT_EQ(2U, bubble_content.radio_groups[0].radio_items.size()); + EXPECT_EQ(0, bubble_content.radio_groups[0].default_item); + EXPECT_NE(std::string(), bubble_content.manage_link); + EXPECT_NE(std::string(), bubble_content.title); +} + +TEST_F(ContentSettingBubbleModelTest, Cookies) { + TestTabContents tab_contents(profile_.get(), NULL); + RenderViewHostDelegate::Resource* render_view_host_delegate = &tab_contents; + render_view_host_delegate->OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES); + + scoped_ptr<ContentSettingBubbleModel> content_setting_bubble_model( + ContentSettingBubbleModel::CreateContentSettingBubbleModel( + &tab_contents, profile_.get(), CONTENT_SETTINGS_TYPE_COOKIES)); + const ContentSettingBubbleModel::BubbleContent& bubble_content = + content_setting_bubble_model->bubble_content(); + EXPECT_EQ(0U, bubble_content.radio_groups.size()); + EXPECT_NE(std::string(), bubble_content.manage_link); + EXPECT_NE(std::string(), bubble_content.title); +} diff --git a/chrome/browser/gtk/content_blocked_bubble_gtk.cc b/chrome/browser/gtk/content_blocked_bubble_gtk.cc index 3bc1873..11bc921 100644 --- a/chrome/browser/gtk/content_blocked_bubble_gtk.cc +++ b/chrome/browser/gtk/content_blocked_bubble_gtk.cc @@ -7,6 +7,7 @@ #include "app/gfx/gtk_util.h" #include "app/l10n_util.h" #include "chrome/browser/blocked_popup_container.h" +#include "chrome/browser/content_setting_bubble_model.h" #include "chrome/browser/gtk/gtk_chrome_link_button.h" #include "chrome/browser/gtk/gtk_theme_provider.h" #include "chrome/browser/gtk/gtk_util.h" @@ -23,46 +24,40 @@ // Padding between content and edge of info bubble. static const int kContentBorder = 7; -ContentBlockedBubbleGtk::ContentBlockedBubbleGtk( +ContentSettingBubbleGtk::ContentSettingBubbleGtk( GtkWindow* toplevel_window, const gfx::Rect& bounds, InfoBubbleGtkDelegate* delegate, - ContentSettingsType content_type, - const std::string& host, - const std::wstring& display_host, + ContentSettingBubbleModel* content_setting_bubble_model, Profile* profile, TabContents* tab_contents) : toplevel_window_(toplevel_window), bounds_(bounds), - content_type_(content_type), - host_(host), - display_host_(display_host), profile_(profile), tab_contents_(tab_contents), delegate_(delegate), - info_bubble_(NULL), - allow_radio_(NULL), - block_radio_(NULL) { + content_setting_bubble_model_(content_setting_bubble_model), + info_bubble_(NULL) { registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED, Source<TabContents>(tab_contents)); BuildBubble(); } -ContentBlockedBubbleGtk::~ContentBlockedBubbleGtk() { +ContentSettingBubbleGtk::~ContentSettingBubbleGtk() { } -void ContentBlockedBubbleGtk::Close() { +void ContentSettingBubbleGtk::Close() { if (info_bubble_) info_bubble_->Close(); } -void ContentBlockedBubbleGtk::InfoBubbleClosing(InfoBubbleGtk* info_bubble, +void ContentSettingBubbleGtk::InfoBubbleClosing(InfoBubbleGtk* info_bubble, bool closed_by_escape) { delegate_->InfoBubbleClosing(info_bubble, closed_by_escape); delete this; } -void ContentBlockedBubbleGtk::Observe(NotificationType type, +void ContentSettingBubbleGtk::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { DCHECK(type == NotificationType::TAB_CONTENTS_DESTROYED); @@ -70,42 +65,28 @@ void ContentBlockedBubbleGtk::Observe(NotificationType type, tab_contents_ = NULL; } -void ContentBlockedBubbleGtk::BuildBubble() { +void ContentSettingBubbleGtk::BuildBubble() { GtkThemeProvider* theme_provider = GtkThemeProvider::GetFrom(profile_); GtkWidget* bubble_content = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); gtk_container_set_border_width(GTK_CONTAINER(bubble_content), kContentBorder); // Add the content label. - static const int kTitleIDs[CONTENT_SETTINGS_NUM_TYPES] = { - IDS_BLOCKED_COOKIES_TITLE, - IDS_BLOCKED_IMAGES_TITLE, - IDS_BLOCKED_JAVASCRIPT_TITLE, - IDS_BLOCKED_PLUGINS_TITLE, - IDS_BLOCKED_POPUPS_TITLE, - }; - DCHECK_EQ(arraysize(kTitleIDs), - static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES)); - GtkWidget* label = gtk_label_new(l10n_util::GetStringUTF8( - kTitleIDs[content_type_]).c_str()); + GtkWidget* label = gtk_label_new( + content_setting_bubble_model_->bubble_content().title.c_str()); gtk_box_pack_start(GTK_BOX(bubble_content), label, FALSE, FALSE, 0); - if (content_type_ == CONTENT_SETTINGS_TYPE_POPUPS) { - BlockedPopupContainer::BlockedContents blocked_contents; - DCHECK(tab_contents_); - DCHECK(tab_contents_->blocked_popup_container()); - tab_contents_->blocked_popup_container()->GetBlockedContents( - &blocked_contents); - - GtkWidget* table = gtk_table_new(blocked_contents.size(), 2, FALSE); + if (content_setting_bubble_model_->content_type() == + CONTENT_SETTINGS_TYPE_POPUPS) { + const std::vector<ContentSettingBubbleModel::PopupItem>& popup_items = + content_setting_bubble_model_->bubble_content().popup_items; + GtkWidget* table = gtk_table_new(popup_items.size(), 2, FALSE); int row = 0; - for (BlockedPopupContainer::BlockedContents::const_iterator - i(blocked_contents.begin()); i != blocked_contents.end(); - ++i, ++row) { - SkBitmap icon = (*i)->GetFavIcon(); + for (std::vector<ContentSettingBubbleModel::PopupItem>::const_iterator + i(popup_items.begin()); i != popup_items.end(); ++i, ++row) { GtkWidget* image = gtk_image_new(); - if (!icon.empty()) { - GdkPixbuf* icon_pixbuf = gfx::GdkPixbufFromSkBitmap(&icon); + if (!i->bitmap.empty()) { + GdkPixbuf* icon_pixbuf = gfx::GdkPixbufFromSkBitmap(&i->bitmap); gtk_image_set_from_pixbuf(GTK_IMAGE(image), icon_pixbuf); g_object_unref(icon_pixbuf); @@ -114,7 +95,7 @@ void ContentBlockedBubbleGtk::BuildBubble() { GtkWidget* event_box = gtk_event_box_new(); gtk_container_add(GTK_CONTAINER(event_box), image); - popup_icons_[event_box] = *i; + popup_icons_[event_box] = i -popup_items.begin(); g_signal_connect(event_box, "button_press_event", G_CALLBACK(OnPopupIconButtonPress), this); gtk_table_attach(GTK_TABLE(table), event_box, 0, 1, row, row + 1, @@ -122,15 +103,8 @@ void ContentBlockedBubbleGtk::BuildBubble() { gtk_util::kControlSpacing / 2); } - string16 title((*i)->GetTitle()); - // The popup may not have committed a load yet, in which case it won't - // have a URL or title. - if (title.empty()) - title = l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE); - - GtkWidget* button = - gtk_chrome_link_button_new(UTF16ToUTF8(title).c_str()); - popup_links_[button] = *i; + GtkWidget* button = gtk_chrome_link_button_new(i->title.c_str()); + popup_links_[button] = i -popup_items.begin(); g_signal_connect(button, "clicked", G_CALLBACK(OnPopupLinkClicked), this); gtk_table_attach(GTK_TABLE(table), button, 1, 2, row, row + 1, @@ -141,67 +115,44 @@ void ContentBlockedBubbleGtk::BuildBubble() { gtk_box_pack_start(GTK_BOX(bubble_content), table, FALSE, FALSE, 0); } - if (content_type_ != CONTENT_SETTINGS_TYPE_COOKIES) { - static const int kAllowIDs[CONTENT_SETTINGS_NUM_TYPES] = { - 0, // Not displayed for cookies - IDS_BLOCKED_IMAGES_UNBLOCK, - IDS_BLOCKED_JAVASCRIPT_UNBLOCK, - IDS_BLOCKED_PLUGINS_UNBLOCK, - IDS_BLOCKED_POPUPS_UNBLOCK, - }; - DCHECK_EQ(arraysize(kAllowIDs), - static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES)); - allow_radio_ = gtk_radio_button_new_with_label( - NULL, - l10n_util::GetStringFUTF8(kAllowIDs[content_type_], - WideToUTF16Hack(display_host_)).c_str()); - gtk_box_pack_start(GTK_BOX(bubble_content), allow_radio_, FALSE, - FALSE, 0); - - static const int kBlockIDs[CONTENT_SETTINGS_NUM_TYPES] = { - 0, // Not displayed for cookies - IDS_BLOCKED_IMAGES_NO_ACTION, - IDS_BLOCKED_JAVASCRIPT_NO_ACTION, - IDS_BLOCKED_PLUGINS_NO_ACTION, - IDS_BLOCKED_POPUPS_NO_ACTION, - }; - DCHECK_EQ(arraysize(kBlockIDs), - static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES)); - block_radio_ = gtk_radio_button_new_with_label_from_widget( - GTK_RADIO_BUTTON(allow_radio_), - l10n_util::GetStringUTF8(kBlockIDs[content_type_]).c_str()); - gtk_box_pack_start(GTK_BOX(bubble_content), block_radio_, FALSE, - FALSE, 0); - - // We must set the default value before we attach the signal handlers or - // pain occurs. - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON( - (profile_->GetHostContentSettingsMap()->GetContentSetting(host_, - content_type_) == CONTENT_SETTING_ALLOW) ? - allow_radio_ : block_radio_), TRUE); - - g_signal_connect(allow_radio_, "toggled", - G_CALLBACK(OnAllowBlockToggled), this); - g_signal_connect(block_radio_, "toggled", - G_CALLBACK(OnAllowBlockToggled), this); + if (content_setting_bubble_model_->content_type() != + CONTENT_SETTINGS_TYPE_COOKIES) { + const ContentSettingBubbleModel::RadioGroups& radio_groups = + content_setting_bubble_model_->bubble_content().radio_groups; + for (ContentSettingBubbleModel::RadioGroups::const_iterator i = + radio_groups.begin(); i != radio_groups.end(); ++i) { + const ContentSettingBubbleModel::RadioItems& radio_items = i->radio_items; + RadioGroupGtk radio_group_gtk; + for (ContentSettingBubbleModel::RadioItems::const_iterator j = + radio_items.begin(); j != radio_items.end(); ++j) { + GtkWidget* radio = + radio_group_gtk.empty() ? + gtk_radio_button_new_with_label(NULL, j->c_str()) : + gtk_radio_button_new_with_label_from_widget( + GTK_RADIO_BUTTON(radio_group_gtk[0]), + j->c_str()); + gtk_box_pack_start(GTK_BOX(bubble_content), radio, FALSE, FALSE, 0); + if (j - radio_items.begin() == i->default_item) { + // We must set the default value before we attach the signal handlers + // or pain occurs. + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); + } + radio_group_gtk.push_back(radio); + } + for (std::vector<GtkWidget*>::const_iterator j = radio_group_gtk.begin(); + j != radio_group_gtk.end(); ++j) { + g_signal_connect(*j, "toggled", G_CALLBACK(OnRadioToggled), this); + } + radio_groups_gtk_.push_back(radio_group_gtk); + gtk_box_pack_start(GTK_BOX(bubble_content), gtk_hseparator_new(), FALSE, + FALSE, 0); + } } - gtk_box_pack_start(GTK_BOX(bubble_content), gtk_hseparator_new(), FALSE, - FALSE, 0); - GtkWidget* bottom_box = gtk_hbox_new(FALSE, 0); - static const int kLinkIDs[CONTENT_SETTINGS_NUM_TYPES] = { - IDS_BLOCKED_COOKIES_LINK, - IDS_BLOCKED_IMAGES_LINK, - IDS_BLOCKED_JAVASCRIPT_LINK, - IDS_BLOCKED_PLUGINS_LINK, - IDS_BLOCKED_POPUPS_LINK, - }; - DCHECK_EQ(arraysize(kLinkIDs), - static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES)); - GtkWidget* manage_link = gtk_chrome_link_button_new(l10n_util::GetStringUTF8( - kLinkIDs[content_type_]).c_str()); + GtkWidget* manage_link = gtk_chrome_link_button_new( + content_setting_bubble_model_->bubble_content().manage_link.c_str()); g_signal_connect(manage_link, "clicked", G_CALLBACK(OnManageLinkClicked), this); gtk_box_pack_start(GTK_BOX(bottom_box), manage_link, FALSE, FALSE, 0); @@ -227,65 +178,62 @@ void ContentBlockedBubbleGtk::BuildBubble() { this); } -void ContentBlockedBubbleGtk::LaunchPopup(TabContents* popup) { - if (tab_contents_ && tab_contents_->blocked_popup_container()) { - tab_contents_->blocked_popup_container()->LaunchPopupForContents(popup); - - // The views interface implicitly closes because of the launching of a new - // window; we need to do that explicitly. - Close(); - } -} - // static -void ContentBlockedBubbleGtk::OnPopupIconButtonPress( +void ContentSettingBubbleGtk::OnPopupIconButtonPress( GtkWidget* icon_event_box, GdkEventButton* event, - ContentBlockedBubbleGtk* bubble) { + ContentSettingBubbleGtk* bubble) { PopupMap::iterator i(bubble->popup_icons_.find(icon_event_box)); DCHECK(i != bubble->popup_icons_.end()); - bubble->LaunchPopup(i->second); + bubble->content_setting_bubble_model_->OnPopupClicked(i->second); + // The views interface implicitly closes because of the launching of a new + // window; we need to do that explicitly. + bubble->Close(); + } // static -void ContentBlockedBubbleGtk::OnPopupLinkClicked( +void ContentSettingBubbleGtk::OnPopupLinkClicked( GtkWidget* button, - ContentBlockedBubbleGtk* bubble) { + ContentSettingBubbleGtk* bubble) { PopupMap::iterator i(bubble->popup_links_.find(button)); DCHECK(i != bubble->popup_links_.end()); - bubble->LaunchPopup(i->second); + bubble->content_setting_bubble_model_->OnPopupClicked(i->second); + // The views interface implicitly closes because of the launching of a new + // window; we need to do that explicitly. + bubble->Close(); } // static -void ContentBlockedBubbleGtk::OnAllowBlockToggled( +void ContentSettingBubbleGtk::OnRadioToggled( GtkWidget* widget, - ContentBlockedBubbleGtk* bubble) { - DCHECK((widget == bubble->allow_radio_) || (widget == bubble->block_radio_)); - bubble->profile_->GetHostContentSettingsMap()->SetContentSetting( - bubble->host_, - bubble->content_type_, - gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(bubble->allow_radio_)) ? - CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK); + ContentSettingBubbleGtk* bubble) { + for (std::vector<RadioGroupGtk>::const_iterator i = + bubble->radio_groups_gtk_.begin(); + i != bubble->radio_groups_gtk_.end(); ++i) { + for (RadioGroupGtk::const_iterator j = i->begin(); j != i->end(); j++) { + if (widget == *j) { + bubble->content_setting_bubble_model_->OnRadioClicked( + i - bubble->radio_groups_gtk_.begin(), + j - i->begin()); + return; + } + } + } + NOTREACHED() << "unknown radio toggled"; } // static -void ContentBlockedBubbleGtk::OnCloseButtonClicked( +void ContentSettingBubbleGtk::OnCloseButtonClicked( GtkButton *button, - ContentBlockedBubbleGtk* bubble) { + ContentSettingBubbleGtk* bubble) { bubble->Close(); } // static -void ContentBlockedBubbleGtk::OnManageLinkClicked( +void ContentSettingBubbleGtk::OnManageLinkClicked( GtkButton* button, - ContentBlockedBubbleGtk* bubble) { - if (bubble->tab_contents_) { - bubble->tab_contents_->delegate()->ShowContentSettingsWindow( - bubble->content_type_); - } else { - ContentSettingsWindowGtk::Show(NULL, bubble->content_type_, - bubble->profile_); - } - + ContentSettingBubbleGtk* bubble) { + bubble->content_setting_bubble_model_->OnManageLinkClicked(); bubble->Close(); } diff --git a/chrome/browser/gtk/content_blocked_bubble_gtk.h b/chrome/browser/gtk/content_blocked_bubble_gtk.h index d201574..7939e8a 100644 --- a/chrome/browser/gtk/content_blocked_bubble_gtk.h +++ b/chrome/browser/gtk/content_blocked_bubble_gtk.h @@ -8,35 +8,36 @@ #include <map> #include <string> +#include "base/scoped_ptr.h" #include "chrome/browser/gtk/info_bubble_gtk.h" #include "chrome/common/content_settings_types.h" #include "chrome/common/notification_registrar.h" +class ContentSettingBubbleModel; class Profile; class TabContents; -// ContentBlockedBubbleGtk is used when the user turns on different kinds of +// ContentSettingBubbleGtk is used when the user turns on different kinds of // content blocking (e.g. "block images"). An icon appears in the location bar, // and when clicked, an instance of this class is created specialized for the // type of content being blocked. -class ContentBlockedBubbleGtk : public InfoBubbleGtkDelegate, +// TODO(bulach): rename this file. +class ContentSettingBubbleGtk : public InfoBubbleGtkDelegate, public NotificationObserver { public: - ContentBlockedBubbleGtk(GtkWindow* toplevel_window, - const gfx::Rect& bounds, - InfoBubbleGtkDelegate* delegate, - ContentSettingsType content_type, - const std::string& host, - const std::wstring& display_host, - Profile* profile, - TabContents* tab_contents); - virtual ~ContentBlockedBubbleGtk(); + ContentSettingBubbleGtk( + GtkWindow* toplevel_window, + const gfx::Rect& bounds, + InfoBubbleGtkDelegate* delegate, + ContentSettingBubbleModel* content_setting_bubble_model, + Profile* profile, TabContents* tab_contents); + virtual ~ContentSettingBubbleGtk(); // Dismisses the infobubble. void Close(); private: - typedef std::map<GtkWidget*, TabContents*> PopupMap; + typedef std::map<GtkWidget*, int> PopupMap; // InfoBubbleGtkDelegate: virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble, @@ -50,21 +51,18 @@ class ContentBlockedBubbleGtk : public InfoBubbleGtkDelegate, // Builds the info bubble and all the widgets that it displays. void BuildBubble(); - // Launches a popup from a click on a widget. - void LaunchPopup(TabContents* popup); - // Widget callback methods. static void OnPopupIconButtonPress(GtkWidget* icon, GdkEventButton* event, - ContentBlockedBubbleGtk* bubble); + ContentSettingBubbleGtk* bubble); static void OnPopupLinkClicked(GtkWidget* button, - ContentBlockedBubbleGtk* bubble); - static void OnAllowBlockToggled(GtkWidget* widget, - ContentBlockedBubbleGtk* bubble); + ContentSettingBubbleGtk* bubble); + static void OnRadioToggled(GtkWidget* widget, + ContentSettingBubbleGtk* bubble); static void OnCloseButtonClicked(GtkButton *button, - ContentBlockedBubbleGtk* bubble); + ContentSettingBubbleGtk* bubble); static void OnManageLinkClicked(GtkButton* button, - ContentBlockedBubbleGtk* bubble); + ContentSettingBubbleGtk* bubble); // A reference to the toplevel browser window, which we pass to the // InfoBubbleGtk implementation so it can tell the WM that it's a subwindow. @@ -73,13 +71,6 @@ class ContentBlockedBubbleGtk : public InfoBubbleGtkDelegate, // Positioning information for the info bubble. gfx::Rect bounds_; - // The type of content handled by this view. - ContentSettingsType content_type_; - - // The hostname affected. - std::string host_; - std::wstring display_host_; - // The active profile. Profile* profile_; @@ -92,14 +83,18 @@ class ContentBlockedBubbleGtk : public InfoBubbleGtkDelegate, // Pass on delegate messages to this. InfoBubbleGtkDelegate* delegate_; + // Provides data for this bubble. + scoped_ptr<ContentSettingBubbleModel> content_setting_bubble_model_; + // The info bubble. InfoBubbleGtk* info_bubble_; // Stored controls so we can figure out what was clicked. PopupMap popup_links_; PopupMap popup_icons_; - GtkWidget* allow_radio_; - GtkWidget* block_radio_; + + typedef std::vector<GtkWidget*> RadioGroupGtk; + std::vector<RadioGroupGtk> radio_groups_gtk_; }; #endif // CHROME_BROWSER_GTK_CONTENT_BLOCKED_BUBBLE_GTK_H_ diff --git a/chrome/browser/gtk/location_bar_view_gtk.cc b/chrome/browser/gtk/location_bar_view_gtk.cc index ed0cda4..9e2cb0a 100644 --- a/chrome/browser/gtk/location_bar_view_gtk.cc +++ b/chrome/browser/gtk/location_bar_view_gtk.cc @@ -20,6 +20,7 @@ #include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/command_updater.h" +#include "chrome/browser/content_setting_bubble_model.h" #include "chrome/browser/content_setting_image_model.h" #include "chrome/browser/extensions/extension_accessibility_api_constants.h" #include "chrome/browser/extensions/extension_action_context_menu_model.h" @@ -1016,10 +1017,12 @@ gboolean LocationBarViewGtk::ContentSettingImageViewGtk::OnButtonPressed( GtkWindow* toplevel = GTK_WINDOW(gtk_widget_get_toplevel(sender)); - info_bubble_ = new ContentBlockedBubbleGtk( + info_bubble_ = new ContentSettingBubbleGtk( toplevel, bounds, this, - content_setting_image_model_->get_content_settings_type(), url.host(), - display_host, profile_, tab_contents); + ContentSettingBubbleModel::CreateContentSettingBubbleModel( + tab_contents, profile_, + content_setting_image_model_->get_content_settings_type()), + profile_, tab_contents); return TRUE; } diff --git a/chrome/browser/gtk/location_bar_view_gtk.h b/chrome/browser/gtk/location_bar_view_gtk.h index c0da0c7..1da0e7a 100644 --- a/chrome/browser/gtk/location_bar_view_gtk.h +++ b/chrome/browser/gtk/location_bar_view_gtk.h @@ -31,8 +31,8 @@ class AutocompleteEditViewGtk; class BubblePositioner; class Browser; class CommandUpdater; -class ContentBlockedBubbleGtk; class ContentSettingImageModel; +class ContentSettingBubbleGtk; class ExtensionAction; class ExtensionActionContextMenuModel; class GtkThemeProvider; @@ -166,7 +166,7 @@ class LocationBarViewGtk : public AutocompleteEditController, Profile* profile_; // The currently shown info bubble if any. - ContentBlockedBubbleGtk* info_bubble_; + ContentSettingBubbleGtk* info_bubble_; DISALLOW_COPY_AND_ASSIGN(ContentSettingImageViewGtk); }; diff --git a/chrome/browser/views/content_blocked_bubble_contents.cc b/chrome/browser/views/content_blocked_bubble_contents.cc index a44311c..e9be34f 100644 --- a/chrome/browser/views/content_blocked_bubble_contents.cc +++ b/chrome/browser/views/content_blocked_bubble_contents.cc @@ -10,6 +10,7 @@ #include "app/l10n_util.h" #include "chrome/browser/blocked_popup_container.h" +#include "chrome/browser/content_setting_bubble_model.h" #include "chrome/browser/host_content_settings_map.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" @@ -26,10 +27,10 @@ #include "views/grid_layout.h" #include "views/standard_layout.h" -class ContentBlockedBubbleContents::Favicon : public views::ImageView { +class ContentSettingBubbleContents::Favicon : public views::ImageView { public: Favicon(const SkBitmap& image, - ContentBlockedBubbleContents* parent, + ContentSettingBubbleContents* parent, views::Link* link); virtual ~Favicon(); @@ -45,32 +46,32 @@ class ContentBlockedBubbleContents::Favicon : public views::ImageView { views::Event::EventType event_type, const gfx::Point& p); - ContentBlockedBubbleContents* parent_; + ContentSettingBubbleContents* parent_; views::Link* link_; }; #if defined(OS_WIN) -HCURSOR ContentBlockedBubbleContents::Favicon::g_hand_cursor = NULL; +HCURSOR ContentSettingBubbleContents::Favicon::g_hand_cursor = NULL; #endif -ContentBlockedBubbleContents::Favicon::Favicon( +ContentSettingBubbleContents::Favicon::Favicon( const SkBitmap& image, - ContentBlockedBubbleContents* parent, + ContentSettingBubbleContents* parent, views::Link* link) : parent_(parent), link_(link) { SetImage(image); } -ContentBlockedBubbleContents::Favicon::~Favicon() { +ContentSettingBubbleContents::Favicon::~Favicon() { } -bool ContentBlockedBubbleContents::Favicon::OnMousePressed( +bool ContentSettingBubbleContents::Favicon::OnMousePressed( const views::MouseEvent& event) { return event.IsLeftMouseButton() || event.IsMiddleMouseButton(); } -void ContentBlockedBubbleContents::Favicon::OnMouseReleased( +void ContentSettingBubbleContents::Favicon::OnMouseReleased( const views::MouseEvent& event, bool canceled) { if (!canceled && @@ -79,7 +80,7 @@ void ContentBlockedBubbleContents::Favicon::OnMouseReleased( parent_->LinkActivated(link_, event.GetFlags()); } -gfx::NativeCursor ContentBlockedBubbleContents::Favicon::GetCursorForPoint( +gfx::NativeCursor ContentSettingBubbleContents::Favicon::GetCursorForPoint( views::Event::EventType event_type, const gfx::Point& p) { #if defined(OS_WIN) @@ -91,55 +92,54 @@ gfx::NativeCursor ContentBlockedBubbleContents::Favicon::GetCursorForPoint( #endif } -ContentBlockedBubbleContents::ContentBlockedBubbleContents( - ContentSettingsType content_type, - const std::string& host, - const std::wstring& display_host, +ContentSettingBubbleContents::ContentSettingBubbleContents( + ContentSettingBubbleModel* content_setting_bubble_model, Profile* profile, TabContents* tab_contents) - : content_type_(content_type), - host_(host), - display_host_(display_host), + : content_setting_bubble_model_(content_setting_bubble_model), profile_(profile), tab_contents_(tab_contents), info_bubble_(NULL), - allow_radio_(NULL), - block_radio_(NULL), close_button_(NULL), manage_link_(NULL) { registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED, Source<TabContents>(tab_contents)); } -ContentBlockedBubbleContents::~ContentBlockedBubbleContents() { +ContentSettingBubbleContents::~ContentSettingBubbleContents() { } -void ContentBlockedBubbleContents::ViewHierarchyChanged(bool is_add, +void ContentSettingBubbleContents::ViewHierarchyChanged(bool is_add, View* parent, View* child) { if (is_add && (child == this)) InitControlLayout(); } -void ContentBlockedBubbleContents::ButtonPressed(views::Button* sender, +void ContentSettingBubbleContents::ButtonPressed(views::Button* sender, const views::Event& event) { if (sender == close_button_) { info_bubble_->Close(); // CAREFUL: This deletes us. return; } - DCHECK((sender == allow_radio_) || (sender == block_radio_)); - profile_->GetHostContentSettingsMap()->SetContentSetting(host_, content_type_, - allow_radio_->checked() ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK); + for (std::vector<RadioGroup>::const_iterator i = radio_groups_.begin(); + i != radio_groups_.end(); ++i) { + for (RadioGroup::const_iterator j = i->begin(); j != i->end(); ++j) { + if (sender == *j) { + content_setting_bubble_model_->OnRadioClicked( + i - radio_groups_.begin(), j - i->begin()); + return; + } + } + } + NOTREACHED() << "unknown radio"; } -void ContentBlockedBubbleContents::LinkActivated(views::Link* source, +void ContentSettingBubbleContents::LinkActivated(views::Link* source, int event_flags) { if (source == manage_link_) { - if (tab_contents_) - tab_contents_->delegate()->ShowContentSettingsWindow(content_type_); - else - browser::ShowContentSettingsWindow(NULL, content_type_, profile_); + content_setting_bubble_model_->OnManageLinkClicked(); // CAREFUL: Showing the settings window activates it, which deactivates the // info bubble, which causes it to close, which deletes us. return; @@ -147,11 +147,10 @@ void ContentBlockedBubbleContents::LinkActivated(views::Link* source, PopupLinks::const_iterator i(popup_links_.find(source)); DCHECK(i != popup_links_.end()); - if (tab_contents_ && tab_contents_->blocked_popup_container()) - tab_contents_->blocked_popup_container()->LaunchPopupForContents(i->second); + content_setting_bubble_model_->OnPopupClicked(i->second); } -void ContentBlockedBubbleContents::Observe(NotificationType type, +void ContentSettingBubbleContents::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { DCHECK(type == NotificationType::TAB_CONTENTS_DESTROYED); @@ -159,7 +158,7 @@ void ContentBlockedBubbleContents::Observe(NotificationType type, tab_contents_ = NULL; } -void ContentBlockedBubbleContents::InitControlLayout() { +void ContentSettingBubbleContents::InitControlLayout() { using views::GridLayout; GridLayout* layout = new views::GridLayout(this); @@ -170,23 +169,17 @@ void ContentBlockedBubbleContents::InitControlLayout() { column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1, GridLayout::USE_PREF, 0, 0); - static const int kTitleIDs[CONTENT_SETTINGS_NUM_TYPES] = { - IDS_BLOCKED_COOKIES_TITLE, - IDS_BLOCKED_IMAGES_TITLE, - IDS_BLOCKED_JAVASCRIPT_TITLE, - IDS_BLOCKED_PLUGINS_TITLE, - IDS_BLOCKED_POPUPS_TITLE, - }; - DCHECK_EQ(arraysize(kTitleIDs), - static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES)); - views::Label* title_label = - new views::Label(l10n_util::GetString(kTitleIDs[content_type_])); + const ContentSettingBubbleModel::BubbleContent& bubble_content = + content_setting_bubble_model_->bubble_content(); + views::Label* title_label = new views::Label(UTF8ToWide( + bubble_content.title)); layout->StartRow(0, single_column_set_id); layout->AddView(title_label); layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); - if (content_type_ == CONTENT_SETTINGS_TYPE_POPUPS) { + if (content_setting_bubble_model_->content_type() == + CONTENT_SETTINGS_TYPE_POPUPS) { const int popup_column_set_id = 2; views::ColumnSet* popup_column_set = layout->AddColumnSet(popup_column_set_id); @@ -196,26 +189,17 @@ void ContentBlockedBubbleContents::InitControlLayout() { popup_column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1, GridLayout::USE_PREF, 0, 0); - BlockedPopupContainer::BlockedContents blocked_contents; - DCHECK(tab_contents_->blocked_popup_container()); - tab_contents_->blocked_popup_container()->GetBlockedContents( - &blocked_contents); - for (BlockedPopupContainer::BlockedContents::const_iterator - i(blocked_contents.begin()); i != blocked_contents.end(); ++i) { - string16 title((*i)->GetTitle()); - // The popup may not have committed a load yet, in which case it won't - // have a URL or title. - if (title.empty()) - title = l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE); - - if (i != blocked_contents.begin()) + for (std::vector<ContentSettingBubbleModel::PopupItem>::const_iterator + i(bubble_content.popup_items.begin()); + i != bubble_content.popup_items.end(); ++i) { + if (i != bubble_content.popup_items.begin()) layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); layout->StartRow(0, popup_column_set_id); - views::Link* link = new views::Link(UTF16ToWideHack(title)); + views::Link* link = new views::Link(UTF8ToWide(i->title)); link->SetController(this); - popup_links_[link] = *i; - layout->AddView(new Favicon((*i)->GetFavIcon(), this, link)); + popup_links_[link] = i - bubble_content.popup_items.begin(); + layout->AddView(new Favicon((*i).bitmap, this, link)); layout->AddView(link); } layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); @@ -226,54 +210,30 @@ void ContentBlockedBubbleContents::InitControlLayout() { layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); } - if (content_type_ != CONTENT_SETTINGS_TYPE_COOKIES) { - static const int kAllowIDs[CONTENT_SETTINGS_NUM_TYPES] = { - 0, // Not displayed for cookies - IDS_BLOCKED_IMAGES_UNBLOCK, - IDS_BLOCKED_JAVASCRIPT_UNBLOCK, - IDS_BLOCKED_PLUGINS_UNBLOCK, - IDS_BLOCKED_POPUPS_UNBLOCK, - }; - DCHECK_EQ(arraysize(kAllowIDs), - static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES)); - const int radio_button_group = 0; - allow_radio_ = new views::RadioButton( - l10n_util::GetStringF(kAllowIDs[content_type_], display_host_), - radio_button_group); - allow_radio_->set_listener(this); - - static const int kBlockIDs[CONTENT_SETTINGS_NUM_TYPES] = { - 0, // Not displayed for cookies - IDS_BLOCKED_IMAGES_NO_ACTION, - IDS_BLOCKED_JAVASCRIPT_NO_ACTION, - IDS_BLOCKED_PLUGINS_NO_ACTION, - IDS_BLOCKED_POPUPS_NO_ACTION, - }; - DCHECK_EQ(arraysize(kBlockIDs), - static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES)); - block_radio_ = new views::RadioButton( - l10n_util::GetString(kBlockIDs[content_type_]), radio_button_group); - block_radio_->set_listener(this); - - layout->StartRow(0, single_column_set_id); - layout->AddView(allow_radio_); - layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); - layout->StartRow(0, single_column_set_id); - layout->AddView(block_radio_); - layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); - - // Now that the buttons have been added to the view hierarchy, it's safe to - // call SetChecked() on them. - if (profile_->GetHostContentSettingsMap()->GetContentSetting(host_, - content_type_) == CONTENT_SETTING_ALLOW) - allow_radio_->SetChecked(true); - else - block_radio_->SetChecked(true); - + const ContentSettingBubbleModel::RadioGroups& radio_groups =
+ content_setting_bubble_model_->bubble_content().radio_groups;
+ for (ContentSettingBubbleModel::RadioGroups::const_iterator i = + radio_groups.begin(); i != radio_groups.end(); ++i) {
+ const ContentSettingBubbleModel::RadioItems& radio_items = i->radio_items;
+ RadioGroup radio_group;
+ for (ContentSettingBubbleModel::RadioItems::const_iterator j = + radio_items.begin(); j != radio_items.end(); ++j) { + views::RadioButton* radio = new views::RadioButton( + UTF8ToWide(*j), i - radio_groups.begin()); + radio->set_listener(this); + radio_group.push_back(radio); + layout->StartRow(0, single_column_set_id); + layout->AddView(radio); + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); + } + radio_groups_.push_back(radio_group); views::Separator* separator = new views::Separator; layout->StartRow(0, single_column_set_id); layout->AddView(separator, 1, 1, GridLayout::FILL, GridLayout::FILL); layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); + // Now that the buttons have been added to the view hierarchy, it's safe + // to call SetChecked() on them. + radio_group[i->default_item]->SetChecked(true); } const int double_column_set_id = 1; @@ -285,16 +245,7 @@ void ContentBlockedBubbleContents::InitControlLayout() { double_column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0, GridLayout::USE_PREF, 0, 0); - static const int kLinkIDs[CONTENT_SETTINGS_NUM_TYPES] = { - IDS_BLOCKED_COOKIES_LINK, - IDS_BLOCKED_IMAGES_LINK, - IDS_BLOCKED_JAVASCRIPT_LINK, - IDS_BLOCKED_PLUGINS_LINK, - IDS_BLOCKED_POPUPS_LINK, - }; - DCHECK_EQ(arraysize(kLinkIDs), - static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES)); - manage_link_ = new views::Link(l10n_util::GetString(kLinkIDs[content_type_])); + manage_link_ = new views::Link(UTF8ToWide(bubble_content.manage_link)); manage_link_->SetController(this); layout->StartRow(0, double_column_set_id); diff --git a/chrome/browser/views/content_blocked_bubble_contents.h b/chrome/browser/views/content_blocked_bubble_contents.h index d4781c4..b27516f 100644 --- a/chrome/browser/views/content_blocked_bubble_contents.h +++ b/chrome/browser/views/content_blocked_bubble_contents.h @@ -13,7 +13,7 @@ #include "views/controls/button/button.h" #include "views/controls/link.h" -// ContentBlockedBubbleContents is used when the user turns on different kinds +// ContentSettingBubbleContents is used when the user turns on different kinds // of content blocking (e.g. "block images"). When viewing a page with blocked // content, icons appear in the omnibox corresponding to the content types that // were blocked, and the user can click one to get a bubble hosting a few @@ -23,6 +23,7 @@ // get to a more comprehensive settings management dialog. A few types have // more or fewer controls than this. +class ContentSettingBubbleModel; class InfoBubble; class Profile; class TabContents; @@ -32,17 +33,16 @@ class NativeButton; class RadioButton; } -class ContentBlockedBubbleContents : public views::View, +// TODO(bulach): rename this file. +class ContentSettingBubbleContents : public views::View, public views::ButtonListener, public views::LinkController, public NotificationObserver { public: - ContentBlockedBubbleContents(ContentSettingsType content_type, - const std::string& host, - const std::wstring& display_host, - Profile* profile, - TabContents* tab_contents); - virtual ~ContentBlockedBubbleContents(); + ContentSettingBubbleContents( + ContentSettingBubbleModel* content_setting_bubble_model, + Profile* profile, TabContents* tab_contents); + virtual ~ContentSettingBubbleContents(); // Sets |info_bubble_|, so we can close the bubble if needed. The caller owns // the bubble and must keep it alive. @@ -51,7 +51,7 @@ class ContentBlockedBubbleContents : public views::View, private: class Favicon; - typedef std::map<views::Link*, TabContents*> PopupLinks; + typedef std::map<views::Link*, int> PopupLinks; // Overridden from views::View: virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child); @@ -70,12 +70,8 @@ class ContentBlockedBubbleContents : public views::View, // Creates the child views. void InitControlLayout(); - // The type of content handled by this view. - ContentSettingsType content_type_; - - // The hostname affected. - std::string host_; - std::wstring display_host_; + // Provides data for this bubble. + scoped_ptr<ContentSettingBubbleModel> content_setting_bubble_model_; // The active profile. Profile* profile_; @@ -92,12 +88,12 @@ class ContentBlockedBubbleContents : public views::View, // Some of our controls, so we can tell what's been clicked when we get a // message. PopupLinks popup_links_; - views::RadioButton* allow_radio_; - views::RadioButton* block_radio_; + typedef std::vector<views::RadioButton*> RadioGroup; + std::vector<RadioGroup> radio_groups_; views::NativeButton* close_button_; views::Link* manage_link_; - DISALLOW_IMPLICIT_CONSTRUCTORS(ContentBlockedBubbleContents); + DISALLOW_IMPLICIT_CONSTRUCTORS(ContentSettingBubbleContents); }; #endif // CHROME_BROWSER_VIEWS_CONTENT_BLOCKED_BUBBLE_CONTENTS_H_ diff --git a/chrome/browser/views/location_bar_view.cc b/chrome/browser/views/location_bar_view.cc index 23c439b..b1c8d5b 100644 --- a/chrome/browser/views/location_bar_view.cc +++ b/chrome/browser/views/location_bar_view.cc @@ -20,6 +20,7 @@ #include "chrome/browser/browser_window.h" #include "chrome/browser/bubble_positioner.h" #include "chrome/browser/command_updater.h" +#include "chrome/browser/content_setting_bubble_model.h" #include "chrome/browser/content_setting_image_model.h" #include "chrome/browser/extensions/extension_browser_event_router.h" #include "chrome/browser/extensions/extensions_service.h" @@ -1383,15 +1384,12 @@ bool LocationBarView::ContentSettingImageView::OnMousePressed( TabContents* tab_contents = parent_->GetTabContents(); if (!tab_contents) return true; - GURL url = tab_contents->GetURL(); - std::wstring display_host; - net::AppendFormattedHost(url, - profile_->GetPrefs()->GetString(prefs::kAcceptLanguages), &display_host, - NULL, NULL); - ContentBlockedBubbleContents* bubble_contents = - new ContentBlockedBubbleContents( - content_setting_image_model_->get_content_settings_type(), url.host(), - display_host, profile_, tab_contents); + ContentSettingBubbleContents* bubble_contents = + new ContentSettingBubbleContents( + ContentSettingBubbleModel::CreateContentSettingBubbleModel( + tab_contents, profile_, + content_setting_image_model_->get_content_settings_type()), + profile_, tab_contents); DCHECK(!info_bubble_); info_bubble_ = InfoBubble::Show(GetWindow(), bounds, bubble_contents, this); bubble_contents->set_info_bubble(info_bubble_); diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index e3832f0..dceec65 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -751,6 +751,8 @@ 'browser/command_updater.h', 'browser/content_exceptions_table_model.cc', 'browser/content_exceptions_table_model.h', + 'browser/content_setting_bubble_model.cc', + 'browser/content_setting_bubble_model.h', 'browser/content_setting_combo_model.cc', 'browser/content_setting_combo_model.h', 'browser/content_setting_image_model.cc', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index fae75d3..cec0b93 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -567,7 +567,8 @@ 'browser/browser_theme_pack_unittest.cc', 'browser/browser_theme_provider_unittest.cc', 'browser/browser_unittest.cc', - 'browser/content_setting_image_model_unittest.cc', + 'browser/content_setting_bubble_model_unittest.cc', + 'browser/content_setting_image_model_unittest.cc', 'browser/chrome_browser_application_mac_unittest.mm', 'browser/debugger/devtools_remote_message_unittest.cc', 'browser/debugger/devtools_remote_listen_socket_unittest.cc', |