172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/content_setting_bubble_gtk.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <set>
821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <string>
921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <vector>
1021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/i18n/rtl.h"
123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
13731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/blocked_content_container.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/content_setting_bubble_model.h"
15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/content_settings/host_content_settings_map.h"
1621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/gtk/gtk_theme_service.h"
1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_util.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/content_settings.h"
21dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h"
22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/common/notification_source.h"
23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/common/notification_type.h"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/app_resources.h"
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/text/text_elider.h"
2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/gtk_util.h"
2921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "webkit/plugins/npapi/plugin_list.h"
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
31513209b27ff55e2841eac0e4120199c23acce758Ben Murdochnamespace {
32513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Padding between content and edge of info bubble.
34513209b27ff55e2841eac0e4120199c23acce758Ben Murdochconst int kContentBorder = 7;
35513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
36513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// The maximum width of a title entry in the content box. We elide anything
37513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// longer than this.
38513209b27ff55e2841eac0e4120199c23acce758Ben Murdochconst int kMaxLinkPixelSize = 500;
39513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
40513209b27ff55e2841eac0e4120199c23acce758Ben Murdochstd::string BuildElidedText(const std::string& input) {
4172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return UTF16ToUTF8(ui::ElideText(
42513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      UTF8ToUTF16(input),
43513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      gfx::Font(),
44513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      kMaxLinkPixelSize,
45513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      false));
46513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
47513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
48513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}  // namespace
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochContentSettingBubbleGtk::ContentSettingBubbleGtk(
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkWidget* anchor,
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    InfoBubbleGtkDelegate* delegate,
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ContentSettingBubbleModel* content_setting_bubble_model,
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Profile* profile,
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TabContents* tab_contents)
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : anchor_(anchor),
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      profile_(profile),
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      tab_contents_(tab_contents),
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      delegate_(delegate),
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      content_setting_bubble_model_(content_setting_bubble_model),
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      info_bubble_(NULL) {
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 Source<TabContents>(tab_contents));
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BuildBubble();
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochContentSettingBubbleGtk::~ContentSettingBubbleGtk() {
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ContentSettingBubbleGtk::Close() {
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (info_bubble_)
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info_bubble_->Close();
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ContentSettingBubbleGtk::InfoBubbleClosing(InfoBubbleGtk* info_bubble,
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                bool closed_by_escape) {
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delegate_->InfoBubbleClosing(info_bubble, closed_by_escape);
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delete this;
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ContentSettingBubbleGtk::Observe(NotificationType type,
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      const NotificationSource& source,
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      const NotificationDetails& details) {
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(type == NotificationType::TAB_CONTENTS_DESTROYED);
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(source == Source<TabContents>(tab_contents_));
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  tab_contents_ = NULL;
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ContentSettingBubbleGtk::BuildBubble() {
90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GtkThemeService* theme_provider = GtkThemeService::GetFrom(profile_);
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* bubble_content = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_set_border_width(GTK_CONTAINER(bubble_content), kContentBorder);
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const ContentSettingBubbleModel::BubbleContent& content =
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      content_setting_bubble_model_->bubble_content();
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!content.title.empty()) {
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Add the content label.
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkWidget* label = gtk_label_new(content.title.c_str());
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_box_pack_start(GTK_BOX(bubble_content), label, FALSE, FALSE, 0);
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const std::set<std::string>& plugins = content.resource_identifiers;
1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!plugins.empty()) {
1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    GtkWidget* list_content = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    for (std::set<std::string>::const_iterator it = plugins.begin();
1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        it != plugins.end(); ++it) {
11021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      std::string name = UTF16ToUTF8(
11121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          webkit::npapi::PluginList::Singleton()->GetPluginGroupName(*it));
11221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      if (name.empty())
1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        name = *it;
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
115513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      GtkWidget* label = gtk_label_new(BuildElidedText(name).c_str());
1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      GtkWidget* label_box = gtk_hbox_new(FALSE, 0);
1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      gtk_box_pack_start(GTK_BOX(label_box), label, FALSE, FALSE, 0);
1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      gtk_box_pack_start(GTK_BOX(list_content),
1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                         label_box,
1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                         FALSE, FALSE, 0);
1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    gtk_box_pack_start(GTK_BOX(bubble_content), list_content, FALSE, FALSE,
1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                       gtk_util::kControlSpacing);
1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (content_setting_bubble_model_->content_type() ==
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CONTENT_SETTINGS_TYPE_POPUPS) {
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::vector<ContentSettingBubbleModel::PopupItem>& popup_items =
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        content.popup_items;
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkWidget* table = gtk_table_new(popup_items.size(), 2, FALSE);
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int row = 0;
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (std::vector<ContentSettingBubbleModel::PopupItem>::const_iterator
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         i(popup_items.begin()); i != popup_items.end(); ++i, ++row) {
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GtkWidget* image = gtk_image_new();
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (!i->bitmap.empty()) {
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        GdkPixbuf* icon_pixbuf = gfx::GdkPixbufFromSkBitmap(&i->bitmap);
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gtk_image_set_from_pixbuf(GTK_IMAGE(image), icon_pixbuf);
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        g_object_unref(icon_pixbuf);
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // We stuff the image in an event box so we can trap mouse clicks on the
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // image (and launch the popup).
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        GtkWidget* event_box = gtk_event_box_new();
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gtk_container_add(GTK_CONTAINER(event_box), image);
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        popup_icons_[event_box] = i -popup_items.begin();
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        g_signal_connect(event_box, "button_press_event",
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         G_CALLBACK(OnPopupIconButtonPressThunk), this);
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gtk_table_attach(GTK_TABLE(table), event_box, 0, 1, row, row + 1,
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         GTK_FILL, GTK_FILL, gtk_util::kControlSpacing / 2,
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         gtk_util::kControlSpacing / 2);
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
154513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      GtkWidget* button = gtk_chrome_link_button_new(
155513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          BuildElidedText(i->title).c_str());
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      popup_links_[button] = i -popup_items.begin();
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      g_signal_connect(button, "clicked", G_CALLBACK(OnPopupLinkClickedThunk),
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       this);
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_table_attach(GTK_TABLE(table), button, 1, 2, row, row + 1,
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       GTK_FILL, GTK_FILL, gtk_util::kControlSpacing / 2,
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       gtk_util::kControlSpacing / 2);
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_box_pack_start(GTK_BOX(bubble_content), table, FALSE, FALSE, 0);
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (content_setting_bubble_model_->content_type() !=
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CONTENT_SETTINGS_TYPE_COOKIES) {
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const ContentSettingBubbleModel::RadioGroup& radio_group =
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        content.radio_group;
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (ContentSettingBubbleModel::RadioItems::const_iterator i =
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         radio_group.radio_items.begin();
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         i != radio_group.radio_items.end(); ++i) {
174513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      std::string elided = BuildElidedText(*i);
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GtkWidget* radio =
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          radio_group_gtk_.empty() ?
177513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch              gtk_radio_button_new_with_label(NULL, elided.c_str()) :
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              gtk_radio_button_new_with_label_from_widget(
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  GTK_RADIO_BUTTON(radio_group_gtk_[0]),
180513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                  elided.c_str());
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_box_pack_start(GTK_BOX(bubble_content), radio, FALSE, FALSE, 0);
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (i - radio_group.radio_items.begin() == radio_group.default_item) {
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // We must set the default value before we attach the signal handlers
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // or pain occurs.
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE);
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      radio_group_gtk_.push_back(radio);
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (std::vector<GtkWidget*>::const_iterator i = radio_group_gtk_.begin();
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         i != radio_group_gtk_.end(); ++i) {
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // We can attach signal handlers now that all defaults are set.
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      g_signal_connect(*i, "toggled", G_CALLBACK(OnRadioToggledThunk), this);
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (std::vector<ContentSettingBubbleModel::DomainList>::const_iterator i =
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       content.domain_lists.begin();
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       i != content.domain_lists.end(); ++i) {
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Put each list into its own vbox to allow spacing between lists.
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkWidget* list_content = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
202513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    GtkWidget* label = gtk_label_new(BuildElidedText(i->title).c_str());
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkWidget* label_box = gtk_hbox_new(FALSE, 0);
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_box_pack_start(GTK_BOX(label_box), label, FALSE, FALSE, 0);
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_box_pack_start(GTK_BOX(list_content), label_box, FALSE, FALSE, 0);
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (std::set<std::string>::const_iterator j = i->hosts.begin();
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         j != i->hosts.end(); ++j) {
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_box_pack_start(GTK_BOX(list_content),
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         gtk_util::IndentWidget(gtk_util::CreateBoldLabel(*j)),
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         FALSE, FALSE, 0);
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_box_pack_start(GTK_BOX(bubble_content), list_content, FALSE, FALSE,
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       gtk_util::kControlSpacing);
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
21721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (!content.custom_link.empty()) {
21821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    GtkWidget* custom_link_box = gtk_hbox_new(FALSE, 0);
21921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    GtkWidget* custom_link = NULL;
22021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (content.custom_link_enabled) {
22121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      custom_link = gtk_chrome_link_button_new(content.custom_link.c_str());
22221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      g_signal_connect(custom_link, "clicked",
22321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                       G_CALLBACK(OnCustomLinkClickedThunk), this);
22421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    } else {
22521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      custom_link = gtk_label_new(content.custom_link.c_str());
22621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      gtk_misc_set_alignment(GTK_MISC(custom_link), 0, 0.5);
22721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
22821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    DCHECK(custom_link);
22921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    gtk_box_pack_start(GTK_BOX(custom_link_box), custom_link, FALSE, FALSE, 0);
23021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    gtk_box_pack_start(GTK_BOX(bubble_content), custom_link_box,
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       FALSE, FALSE, 0);
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
23421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  gtk_box_pack_start(GTK_BOX(bubble_content), gtk_hseparator_new(),
23521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                     FALSE, FALSE, 0);
2363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* bottom_box = gtk_hbox_new(FALSE, 0);
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* manage_link =
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_chrome_link_button_new(content.manage_link.c_str());
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(manage_link, "clicked", G_CALLBACK(OnManageLinkClickedThunk),
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   this);
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_start(GTK_BOX(bottom_box), manage_link, FALSE, FALSE, 0);
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* button = gtk_button_new_with_label(
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      l10n_util::GetStringUTF8(IDS_DONE).c_str());
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(button, "clicked", G_CALLBACK(OnCloseButtonClickedThunk),
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   this);
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_end(GTK_BOX(bottom_box), button, FALSE, FALSE, 0);
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_start(GTK_BOX(bubble_content), bottom_box, FALSE, FALSE, 0);
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_grab_focus(bottom_box);
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_grab_focus(button);
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InfoBubbleGtk::ArrowLocationGtk arrow_location =
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !base::i18n::IsRTL() ?
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT :
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT;
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  info_bubble_ = InfoBubbleGtk::Show(
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      anchor_,
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NULL,
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bubble_content,
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      arrow_location,
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      true,  // match_system_theme
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      true,  // grab_input
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      theme_provider,
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      this);
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ContentSettingBubbleGtk::OnPopupIconButtonPress(
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkWidget* icon_event_box,
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GdkEventButton* event) {
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PopupMap::iterator i(popup_icons_.find(icon_event_box));
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(i != popup_icons_.end());
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  content_setting_bubble_model_->OnPopupClicked(i->second);
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The views interface implicitly closes because of the launching of a new
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // window; we need to do that explicitly.
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Close();
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ContentSettingBubbleGtk::OnPopupLinkClicked(GtkWidget* button) {
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PopupMap::iterator i(popup_links_.find(button));
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(i != popup_links_.end());
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  content_setting_bubble_model_->OnPopupClicked(i->second);
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The views interface implicitly closes because of the launching of a new
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // window; we need to do that explicitly.
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Close();
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ContentSettingBubbleGtk::OnRadioToggled(GtkWidget* widget) {
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (ContentSettingBubbleGtk::RadioGroupGtk::const_iterator i =
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       radio_group_gtk_.begin();
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       i != radio_group_gtk_.end(); ++i) {
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (widget == *i) {
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      content_setting_bubble_model_->OnRadioClicked(
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          i - radio_group_gtk_.begin());
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NOTREACHED() << "unknown radio toggled";
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ContentSettingBubbleGtk::OnCloseButtonClicked(GtkWidget *button) {
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Close();
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
30721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ContentSettingBubbleGtk::OnCustomLinkClicked(GtkWidget* button) {
30821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  content_setting_bubble_model_->OnCustomLinkClicked();
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Close();
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
31221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ContentSettingBubbleGtk::OnManageLinkClicked(GtkWidget* button) {
31321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  content_setting_bubble_model_->OnManageLinkClicked();
3143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Close();
3153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
316