summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorerg@chromium.org <erg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-05 21:10:38 +0000
committererg@chromium.org <erg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-05 21:10:38 +0000
commitd7313ce9aecaed59829e57bf12521eaf135e5f74 (patch)
treeec6762fad10912ab698397856f67d37709c97ff2 /chrome
parentbe82dced35dab699b978c6b9f256f78b3ee99900 (diff)
downloadchromium_src-d7313ce9aecaed59829e57bf12521eaf135e5f74.zip
chromium_src-d7313ce9aecaed59829e57bf12521eaf135e5f74.tar.gz
chromium_src-d7313ce9aecaed59829e57bf12521eaf135e5f74.tar.bz2
GTK: Implement the new content blocking address bar bubbles on Linux.
BUG=33314 TEST=none Review URL: http://codereview.chromium.org/573023 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@38246 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/gtk/browser_toolbar_gtk.cc6
-rw-r--r--chrome/browser/gtk/content_blocked_bubble_gtk.cc226
-rw-r--r--chrome/browser/gtk/content_blocked_bubble_gtk.h95
-rw-r--r--chrome/browser/gtk/location_bar_view_gtk.cc119
-rw-r--r--chrome/browser/gtk/location_bar_view_gtk.h53
-rw-r--r--chrome/browser/views/content_blocked_bubble_contents.cc2
-rwxr-xr-xchrome/chrome_browser.gypi2
7 files changed, 500 insertions, 3 deletions
diff --git a/chrome/browser/gtk/browser_toolbar_gtk.cc b/chrome/browser/gtk/browser_toolbar_gtk.cc
index 4652097..8976e52 100644
--- a/chrome/browser/gtk/browser_toolbar_gtk.cc
+++ b/chrome/browser/gtk/browser_toolbar_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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.
@@ -246,6 +246,10 @@ void BrowserToolbarGtk::Init(Profile* profile,
gtk_widget_hide(actions_toolbar_->widget());
}
+ // Because the above does a recursive show all on all widgets we need to
+ // update the icon visibility to hide them.
+ location_bar_->UpdateContentBlockedIcons();
+
SetViewIDs();
}
diff --git a/chrome/browser/gtk/content_blocked_bubble_gtk.cc b/chrome/browser/gtk/content_blocked_bubble_gtk.cc
new file mode 100644
index 0000000..4f87c5a
--- /dev/null
+++ b/chrome/browser/gtk/content_blocked_bubble_gtk.cc
@@ -0,0 +1,226 @@
+// 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/gtk/content_blocked_bubble_gtk.h"
+
+#include "app/l10n_util.h"
+#include "chrome/browser/blocked_popup_container.h"
+#include "chrome/browser/gtk/gtk_chrome_link_button.h"
+#include "chrome/browser/host_content_settings_map.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/content_settings.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/browser/gtk/gtk_theme_provider.h"
+#include "grit/generated_resources.h"
+
+ContentBlockedBubbleGtk::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)
+ : 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) {
+ registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
+ Source<TabContents>(tab_contents));
+ BuildBubble();
+}
+
+ContentBlockedBubbleGtk::~ContentBlockedBubbleGtk() {
+}
+
+void ContentBlockedBubbleGtk::Close() {
+ if (info_bubble_)
+ info_bubble_->Close();
+}
+
+void ContentBlockedBubbleGtk::InfoBubbleClosing(InfoBubbleGtk* info_bubble,
+ bool closed_by_escape) {
+ delegate_->InfoBubbleClosing(info_bubble, closed_by_escape);
+ delete this;
+}
+
+void ContentBlockedBubbleGtk::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(type == NotificationType::TAB_CONTENTS_DESTROYED);
+ DCHECK(source == Source<TabContents>(tab_contents_));
+ tab_contents_ = NULL;
+}
+
+void ContentBlockedBubbleGtk::BuildBubble() {
+ GtkThemeProvider* theme_provider = GtkThemeProvider::GetFrom(profile_);
+
+ GtkWidget* bubble_content = gtk_vbox_new(FALSE, 5);
+
+ // 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());
+ 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_->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) {
+ GtkWidget* button =
+ gtk_chrome_link_button_new(UTF16ToUTF8((*i)->GetTitle()).c_str());
+ popup_links_[button] = *i;
+ g_signal_connect(button, "clicked", G_CALLBACK(OnPopupLinkClicked),
+ this);
+ gtk_box_pack_start(GTK_BOX(bubble_content), button, 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(block_radio_), TRUE);
+
+ g_signal_connect(G_OBJECT(allow_radio_), "toggled",
+ G_CALLBACK(OnAllowBlockToggled), this);
+ g_signal_connect(G_OBJECT(block_radio_), "toggled",
+ G_CALLBACK(OnAllowBlockToggled), this);
+ }
+
+ 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());
+ g_signal_connect(manage_link, "clicked", G_CALLBACK(OnManageLinkClicked),
+ this);
+ gtk_box_pack_start(GTK_BOX(bottom_box), manage_link, FALSE, FALSE, 0);
+
+ GtkWidget* button = gtk_button_new_with_label(
+ l10n_util::GetStringUTF8(IDS_CLOSE).c_str());
+ g_signal_connect(button, "clicked", G_CALLBACK(OnCloseButtonClicked), this);
+ gtk_box_pack_end(GTK_BOX(bottom_box), button, FALSE, FALSE, 0);
+
+ gtk_box_pack_start(GTK_BOX(bubble_content), bottom_box, FALSE, FALSE, 0);
+
+ InfoBubbleGtk::ArrowLocationGtk arrow_location =
+ (l10n_util::GetTextDirection() == l10n_util::LEFT_TO_RIGHT) ?
+ InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT :
+ InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT;
+ info_bubble_ = InfoBubbleGtk::Show(
+ toplevel_window_,
+ bounds_,
+ bubble_content,
+ arrow_location,
+ true,
+ theme_provider,
+ this);
+}
+
+// static
+void ContentBlockedBubbleGtk::OnPopupLinkClicked(
+ GtkWidget* button,
+ ContentBlockedBubbleGtk* bubble) {
+ PopupLinks::iterator i(bubble->popup_links_.find(button));
+ DCHECK(i != bubble->popup_links_.end());
+ if (bubble->tab_contents_ &&
+ bubble->tab_contents_->blocked_popup_container()) {
+ bubble->tab_contents_->blocked_popup_container()->
+ LaunchPopupForContents(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(
+ 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);
+}
+
+// static
+void ContentBlockedBubbleGtk::OnCloseButtonClicked(
+ GtkButton *button,
+ ContentBlockedBubbleGtk* bubble) {
+ bubble->Close();
+}
+
+// static
+void ContentBlockedBubbleGtk::OnManageLinkClicked(
+ GtkButton* button,
+ ContentBlockedBubbleGtk* bubble) {
+ // TODO(erg): Attach this to the options page once that's been written.
+ NOTIMPLEMENTED();
+}
diff --git a/chrome/browser/gtk/content_blocked_bubble_gtk.h b/chrome/browser/gtk/content_blocked_bubble_gtk.h
new file mode 100644
index 0000000..3679a38
--- /dev/null
+++ b/chrome/browser/gtk/content_blocked_bubble_gtk.h
@@ -0,0 +1,95 @@
+// 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_GTK_CONTENT_BLOCKED_BUBBLE_GTK_H_
+#define CHROME_BROWSER_GTK_CONTENT_BLOCKED_BUBBLE_GTK_H_
+
+#include "chrome/browser/gtk/info_bubble_gtk.h"
+#include "chrome/common/content_settings_types.h"
+#include "chrome/common/notification_registrar.h"
+
+class Profile;
+class TabContents;
+
+// ContentBlockedBubbleGtk 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,
+ 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();
+
+ // Dismisses the infobubble.
+ void Close();
+
+ private:
+ typedef std::map<GtkWidget*, TabContents*> PopupLinks;
+
+ // InfoBubbleGtkDelegate:
+ virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble,
+ bool closed_by_escape);
+
+ // NotificationObserver:
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ // Builds the info bubble and all the widgets that it displays.
+ void BuildBubble();
+
+ // Widget callback methods.
+ static void OnPopupLinkClicked(GtkWidget* button,
+ ContentBlockedBubbleGtk* bubble);
+ static void OnAllowBlockToggled(GtkWidget* widget,
+ ContentBlockedBubbleGtk* bubble);
+ static void OnCloseButtonClicked(GtkButton *button,
+ ContentBlockedBubbleGtk* bubble);
+ static void OnManageLinkClicked(GtkButton* button,
+ ContentBlockedBubbleGtk* 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.
+ GtkWindow* toplevel_window_;
+
+ // 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_;
+
+ // The active tab contents.
+ TabContents* tab_contents_;
+
+ // A registrar for listening for TAB_CONTENTS_DESTROYED notifications.
+ NotificationRegistrar registrar_;
+
+ // Pass on delegate messages to this.
+ InfoBubbleGtkDelegate* delegate_;
+
+ // The info bubble.
+ InfoBubbleGtk* info_bubble_;
+
+ // Stored controls so we can figure out what was clicked.
+ PopupLinks popup_links_;
+ GtkWidget* allow_radio_;
+ GtkWidget* block_radio_;
+};
+
+#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 3a9462ca..270e63b 100644
--- a/chrome/browser/gtk/location_bar_view_gtk.cc
+++ b/chrome/browser/gtk/location_bar_view_gtk.cc
@@ -25,6 +25,7 @@
#include "chrome/browser/extensions/extension_tabs_module.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/gtk/cairo_cached_surface.h"
+#include "chrome/browser/gtk/content_blocked_bubble_gtk.h"
#include "chrome/browser/gtk/extension_popup_gtk.h"
#include "chrome/browser/gtk/first_run_bubble.h"
#include "chrome/browser/gtk/gtk_theme_provider.h"
@@ -39,8 +40,10 @@
#include "chrome/common/gtk_util.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/page_transition_types.h"
+#include "chrome/common/pref_names.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
+#include "net/base/net_util.h"
#include "webkit/glue/window_open_disposition.h"
namespace {
@@ -167,6 +170,7 @@ LocationBarViewGtk::LocationBarViewGtk(
LocationBarViewGtk::~LocationBarViewGtk() {
// All of our widgets should have be children of / owned by the alignment.
hbox_.Destroy();
+ content_blocking_hbox_.Destroy();
page_action_hbox_.Destroy();
}
@@ -323,6 +327,22 @@ void LocationBarViewGtk::Init(bool popup_window_mode) {
gtk_box_pack_end(GTK_BOX(hbox_.get()), security_icon_event_box_,
FALSE, FALSE, 0);
+ content_blocking_hbox_.Own(gtk_hbox_new(FALSE, kInnerPadding));
+ gtk_widget_set_name(content_blocking_hbox_.get(),
+ "chrome-content-blocking-hbox");
+ gtk_box_pack_end(GTK_BOX(hbox_.get()), content_blocking_hbox_.get(),
+ FALSE, FALSE, 0);
+
+ for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
+ ContentBlockedViewGtk* content_blocked_view =
+ new ContentBlockedViewGtk(static_cast<ContentSettingsType>(i), this,
+ profile_);
+ content_blocked_views_.push_back(content_blocked_view);
+ gtk_box_pack_end(GTK_BOX(content_blocking_hbox_.get()),
+ content_blocked_view->widget(), FALSE, FALSE, 0);
+ content_blocked_view->SetVisible(false);
+ }
+
page_action_hbox_.Own(gtk_hbox_new(FALSE, kInnerPadding));
gtk_widget_set_name(page_action_hbox_.get(),
"chrome-page-action-hbox");
@@ -511,7 +531,13 @@ void LocationBarViewGtk::FocusSearch() {
}
void LocationBarViewGtk::UpdateContentBlockedIcons() {
- // TODO(pkasting): Implement.
+ const TabContents* tab_contents = browser_->GetSelectedTabContents();
+ for (ScopedVector<ContentBlockedViewGtk>::iterator i(
+ content_blocked_views_.begin());
+ i != content_blocked_views_.end(); ++i) {
+ (*i)->SetVisible((!toolbar_model_->input_in_progress() && tab_contents) ?
+ tab_contents->IsContentBlocked((*i)->content_type()) : false);
+ }
}
void LocationBarViewGtk::UpdatePageActions() {
@@ -898,6 +924,97 @@ void LocationBarViewGtk::AdjustChildrenVisibility() {
}
////////////////////////////////////////////////////////////////////////////////
+// LocationBarViewGtk::ContentBlockedViewGtk
+LocationBarViewGtk::ContentBlockedViewGtk::ContentBlockedViewGtk(
+ ContentSettingsType content_type,
+ const LocationBarViewGtk* parent,
+ Profile* profile)
+ : content_type_(content_type),
+ parent_(parent),
+ profile_(profile),
+ info_bubble_(NULL) {
+ event_box_.Own(gtk_event_box_new());
+
+ // Make the event box not visible so it does not paint a background.
+ gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_.get()), FALSE);
+ g_signal_connect(event_box_.get(), "button-press-event",
+ G_CALLBACK(&OnButtonPressedThunk), this);
+
+ image_.Own(gtk_image_new());
+ gtk_container_add(GTK_CONTAINER(event_box_.get()), image_.get());
+
+ static const int kIconIDs[CONTENT_SETTINGS_NUM_TYPES] = {
+ IDR_BLOCKED_COOKIES,
+ IDR_BLOCKED_IMAGES,
+ IDR_BLOCKED_JAVASCRIPT,
+ IDR_BLOCKED_PLUGINS,
+ IDR_BLOCKED_POPUPS,
+ };
+ DCHECK_EQ(arraysize(kIconIDs),
+ static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES));
+ gtk_image_set_from_pixbuf(GTK_IMAGE(image_.get()),
+ ResourceBundle::GetSharedInstance().GetPixbufNamed(
+ kIconIDs[content_type]));
+
+ static const int kTooltipIDs[CONTENT_SETTINGS_NUM_TYPES] = {
+ IDS_BLOCKED_COOKIES_TITLE,
+ IDS_BLOCKED_IMAGES_TITLE,
+ IDS_BLOCKED_JAVASCRIPT_TITLE,
+ IDS_BLOCKED_PLUGINS_TITLE,
+ IDS_BLOCKED_POPUPS_TOOLTIP,
+ };
+ DCHECK_EQ(arraysize(kTooltipIDs),
+ static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES));
+ gtk_widget_set_tooltip_text(
+ widget(),
+ l10n_util::GetStringUTF8(kTooltipIDs[content_type_]).c_str());
+}
+
+LocationBarViewGtk::ContentBlockedViewGtk::~ContentBlockedViewGtk() {
+ image_.Destroy();
+ event_box_.Destroy();
+
+ if (info_bubble_)
+ info_bubble_->Close();
+}
+
+void LocationBarViewGtk::ContentBlockedViewGtk::SetVisible(bool visible) {
+ if (visible)
+ gtk_widget_show(widget());
+ else
+ gtk_widget_hide(widget());
+}
+
+gboolean LocationBarViewGtk::ContentBlockedViewGtk::OnButtonPressed(
+ GtkWidget* sender, GdkEvent* event) {
+ gfx::Rect bounds =
+ gtk_util::GetWidgetRectRelativeToToplevel(sender);
+
+ TabContents* tab_contents =
+ BrowserList::GetLastActive()->GetSelectedTabContents();
+ 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);
+
+ GtkWindow* toplevel = GTK_WINDOW(gtk_widget_get_toplevel(sender));
+
+ info_bubble_ = new ContentBlockedBubbleGtk(
+ toplevel, bounds, this, content_type_, url.host(), display_host, profile_,
+ tab_contents);
+ return TRUE;
+}
+
+void LocationBarViewGtk::ContentBlockedViewGtk::InfoBubbleClosing(
+ InfoBubbleGtk* info_bubble,
+ bool closed_by_escape) {
+ info_bubble_ = NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
// LocationBarViewGtk::PageActionViewGtk
LocationBarViewGtk::PageActionViewGtk::PageActionViewGtk(
diff --git a/chrome/browser/gtk/location_bar_view_gtk.h b/chrome/browser/gtk/location_bar_view_gtk.h
index 112aeba..6e6cfb5 100644
--- a/chrome/browser/gtk/location_bar_view_gtk.h
+++ b/chrome/browser/gtk/location_bar_view_gtk.h
@@ -16,8 +16,10 @@
#include "chrome/browser/autocomplete/autocomplete_edit.h"
#include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h"
#include "chrome/browser/extensions/image_loading_tracker.h"
+#include "chrome/browser/gtk/info_bubble_gtk.h"
#include "chrome/browser/gtk/menu_gtk.h"
#include "chrome/browser/location_bar.h"
+#include "chrome/common/content_settings_types.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/owned_widget_gtk.h"
@@ -29,6 +31,7 @@ class AutocompleteEditViewGtk;
class BubblePositioner;
class Browser;
class CommandUpdater;
+class ContentBlockedBubbleGtk;
class ExtensionAction;
class ExtensionActionContextMenuModel;
class GtkThemeProvider;
@@ -120,6 +123,52 @@ class LocationBarViewGtk : public AutocompleteEditController,
static const GdkColor kBackgroundColorByLevel[3];
private:
+ class ContentBlockedViewGtk : public InfoBubbleGtkDelegate {
+ public:
+ ContentBlockedViewGtk(ContentSettingsType content_type,
+ const LocationBarViewGtk* parent,
+ Profile* profile);
+ virtual ~ContentBlockedViewGtk();
+
+ GtkWidget* widget() { return event_box_.get(); }
+
+ ContentSettingsType content_type() const { return content_type_; }
+ void set_profile(Profile* profile) { profile_ = profile; }
+
+ bool IsVisible() { return GTK_WIDGET_VISIBLE(widget()); }
+ void SetVisible(bool visible);
+
+ private:
+ static gboolean OnButtonPressedThunk(GtkWidget* sender,
+ GdkEvent* event,
+ ContentBlockedViewGtk* view) {
+ return view->OnButtonPressed(sender, event);
+ }
+ gboolean OnButtonPressed(GtkWidget* sender, GdkEvent* event);
+
+ // InfoBubbleDelegate overrides:
+ virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble,
+ bool closed_by_escape);
+
+ // The widgets for this content blocked view.
+ OwnedWidgetGtk event_box_;
+ OwnedWidgetGtk image_;
+
+ // The type of content handled by this view.
+ ContentSettingsType content_type_;
+
+ // The owning LocationBarViewGtk.
+ const LocationBarViewGtk* parent_;
+
+ // The currently active profile.
+ Profile* profile_;
+
+ // The currently shown info bubble if any.
+ ContentBlockedBubbleGtk* info_bubble_;
+
+ DISALLOW_COPY_AND_ASSIGN(ContentBlockedViewGtk);
+ };
+
class PageActionViewGtk : public ImageLoadingTracker::Observer {
public:
PageActionViewGtk(
@@ -261,6 +310,10 @@ class LocationBarViewGtk : public AutocompleteEditController,
// Toolbar info text (EV cert info).
GtkWidget* info_label_;
+ // Content blocking icons.
+ OwnedWidgetGtk content_blocking_hbox_;
+ ScopedVector<ContentBlockedViewGtk> content_blocked_views_;
+
// Extension page action icons.
OwnedWidgetGtk page_action_hbox_;
ScopedVector<PageActionViewGtk> page_action_views_;
diff --git a/chrome/browser/views/content_blocked_bubble_contents.cc b/chrome/browser/views/content_blocked_bubble_contents.cc
index 35eb5b4..601562f 100644
--- a/chrome/browser/views/content_blocked_bubble_contents.cc
+++ b/chrome/browser/views/content_blocked_bubble_contents.cc
@@ -166,7 +166,7 @@ void ContentBlockedBubbleContents::InitControlLayout() {
IDS_BLOCKED_PLUGINS_NO_ACTION,
IDS_BLOCKED_POPUPS_NO_ACTION,
};
- DCHECK_EQ(arraysize(kAllowIDs),
+ 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);
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 2a524b2..6b6ddbd 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -938,6 +938,8 @@
'browser/gtk/clear_browsing_data_dialog_gtk.h',
'browser/gtk/constrained_window_gtk.cc',
'browser/gtk/constrained_window_gtk.h',
+ 'browser/gtk/content_blocked_bubble_gtk.cc',
+ 'browser/gtk/content_blocked_bubble_gtk.h',
'browser/gtk/create_application_shortcuts_dialog_gtk.cc',
'browser/gtk/create_application_shortcuts_dialog_gtk.h',
'browser/gtk/custom_button.cc',