Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / gtk / website_settings / website_settings_popup_gtk.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/gtk/website_settings/website_settings_popup_gtk.h"
6
7 #include "base/i18n/rtl.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/certificate_viewer.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/infobars/infobar_service.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/browser_list.h"
15 #include "chrome/browser/ui/gtk/browser_toolbar_gtk.h"
16 #include "chrome/browser/ui/gtk/browser_window_gtk.h"
17 #include "chrome/browser/ui/gtk/collected_cookies_gtk.h"
18 #include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
19 #include "chrome/browser/ui/gtk/gtk_theme_service.h"
20 #include "chrome/browser/ui/gtk/gtk_util.h"
21 #include "chrome/browser/ui/gtk/location_bar_view_gtk.h"
22 #include "chrome/browser/ui/gtk/nine_box.h"
23 #include "chrome/browser/ui/gtk/website_settings/permission_selector.h"
24 #include "chrome/browser/ui/website_settings/website_settings.h"
25 #include "chrome/browser/ui/website_settings/website_settings_utils.h"
26 #include "chrome/common/url_constants.h"
27 #include "content/public/browser/cert_store.h"
28 #include "content/public/browser/notification_service.h"
29 #include "content/public/browser/user_metrics.h"
30 #include "grit/chromium_strings.h"
31 #include "grit/generated_resources.h"
32 #include "grit/locale_settings.h"
33 #include "grit/theme_resources.h"
34 #include "grit/ui_resources.h"
35 #include "ui/base/gtk/gtk_hig_constants.h"
36 #include "ui/base/l10n/l10n_util.h"
37 #include "ui/base/resource/resource_bundle.h"
38 #include "ui/gfx/image/cairo_cached_surface.h"
39 #include "ui/gfx/image/image.h"
40 #include "url/gurl.h"
41
42 using content::OpenURLParams;
43
44 namespace {
45
46 // The width of the popup.
47 const int kPopupWidth = 400;
48
49 // Spacing between consecutive tabs in the tabstrip.
50 const int kInterTabSpacing = 2;
51
52 // Spacing between start of tab and tab text.
53 const int kTabTextHorizontalMargin = 12;
54
55 // The vertical lift of the tab's text off the bottom of the tab.
56 const int kTabTextBaseline = 4;
57
58 // The max width of the text labels on the connection tab.
59 const int kConnectionTabTextWidth = 300;
60
61 // The text color of the site identity status label for websites with a
62 // verified identity.
63 const GdkColor kGdkGreen = GDK_COLOR_RGB(0x29, 0x8a, 0x27);
64
65 GtkWidget* CreateTextLabel(const std::string& text,
66                            int width,
67                            GtkThemeService* theme_service,
68                            const GdkColor& color) {
69   GtkWidget* label = theme_service->BuildLabel(text, color);
70   if (width > 0)
71     gtk_util::SetLabelWidth(label, width);
72   gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD_CHAR);
73   return label;
74 }
75
76 void ClearContainer(GtkWidget* container) {
77   GList* child = gtk_container_get_children(GTK_CONTAINER(container));
78   for (GList* item = child; item; item = g_list_next(item))
79     gtk_container_remove(GTK_CONTAINER(container), GTK_WIDGET(item->data));
80
81   g_list_free(child);
82 }
83
84 void SetConnectionSection(GtkWidget* section_box,
85                           const gfx::Image& icon,
86                           GtkWidget* content_box) {
87   DCHECK(section_box);
88   ClearContainer(section_box);
89   gtk_container_set_border_width(GTK_CONTAINER(section_box),
90                                  ui::kContentAreaBorder);
91
92   GtkWidget* hbox = gtk_hbox_new(FALSE, ui::kControlSpacing);
93
94   GdkPixbuf* pixbuf = icon.ToGdkPixbuf();
95   GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf);
96   gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
97   gtk_misc_set_alignment(GTK_MISC(image), 0, 0);
98
99   gtk_box_pack_start(GTK_BOX(hbox), content_box, TRUE, TRUE, 0);
100
101   gtk_box_pack_start(GTK_BOX(section_box), hbox, TRUE, TRUE, 0);
102   gtk_widget_show_all(section_box);
103 }
104
105 GtkWidget* CreatePermissionTabSection(std::string section_title,
106                                       GtkWidget* section_content,
107                                       GtkThemeService* theme_service) {
108   GtkWidget* section_box = gtk_vbox_new(FALSE, ui::kControlSpacing);
109
110   // Add Section title
111   GtkWidget* title_hbox = gtk_hbox_new(FALSE, ui::kControlSpacing);
112
113   GtkWidget* label = theme_service->BuildLabel(section_title, ui::kGdkBlack);
114   PangoAttrList* attributes = pango_attr_list_new();
115   pango_attr_list_insert(attributes,
116                          pango_attr_weight_new(PANGO_WEIGHT_BOLD));
117   gtk_label_set_attributes(GTK_LABEL(label), attributes);
118   pango_attr_list_unref(attributes);
119   gtk_box_pack_start(GTK_BOX(section_box), title_hbox, FALSE, FALSE, 0);
120
121   gtk_box_pack_start(GTK_BOX(title_hbox), label, FALSE, FALSE, 0);
122
123   // Add section content
124   gtk_box_pack_start(GTK_BOX(section_box), section_content, FALSE, FALSE, 0);
125   return section_box;
126 }
127
128 // A popup that is shown for internal pages (like chrome://).
129 class InternalPageInfoPopupGtk : public BubbleDelegateGtk {
130  public:
131   explicit InternalPageInfoPopupGtk(gfx::NativeWindow parent,
132                                           Profile* profile);
133   virtual ~InternalPageInfoPopupGtk();
134
135  private:
136   // BubbleDelegateGtk implementation.
137   virtual void BubbleClosing(BubbleGtk* bubble, bool closed_by_escape) OVERRIDE;
138
139   // The popup bubble container.
140   BubbleGtk* bubble_;
141
142   DISALLOW_COPY_AND_ASSIGN(InternalPageInfoPopupGtk);
143 };
144
145 InternalPageInfoPopupGtk::InternalPageInfoPopupGtk(
146     gfx::NativeWindow parent, Profile* profile) {
147   GtkWidget* contents = gtk_hbox_new(FALSE, ui::kLabelSpacing);
148   gtk_container_set_border_width(GTK_CONTAINER(contents),
149                                  ui::kContentAreaBorder);
150   // Add the popup icon.
151   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
152   GdkPixbuf* pixbuf = rb.GetNativeImageNamed(IDR_PRODUCT_LOGO_26).ToGdkPixbuf();
153   GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf);
154   gtk_box_pack_start(GTK_BOX(contents), image, FALSE, FALSE, 0);
155   gtk_misc_set_alignment(GTK_MISC(image), 0, 0);
156
157   // Add the popup text.
158   GtkThemeService* theme_service = GtkThemeService::GetFrom(profile);
159   GtkWidget* label = theme_service->BuildLabel(
160       l10n_util::GetStringUTF8(IDS_PAGE_INFO_INTERNAL_PAGE), ui::kGdkBlack);
161   gtk_box_pack_start(GTK_BOX(contents), label, FALSE, FALSE, 0);
162
163   gtk_widget_show_all(contents);
164
165   // Create the bubble.
166   BrowserWindowGtk* browser_window =
167       BrowserWindowGtk::GetBrowserWindowForNativeWindow(parent);
168   GtkWidget* anchor = browser_window->
169       GetToolbar()->GetLocationBarView()->location_icon_widget();
170   bubble_ = BubbleGtk::Show(anchor,
171                             NULL,  // |rect|
172                             contents,
173                             BubbleGtk::ANCHOR_TOP_LEFT,
174                             BubbleGtk::MATCH_SYSTEM_THEME |
175                                 BubbleGtk::POPUP_WINDOW |
176                                 BubbleGtk::GRAB_INPUT,
177                             theme_service,
178                             this);  // |delegate|
179   DCHECK(bubble_);
180 }
181
182 InternalPageInfoPopupGtk::~InternalPageInfoPopupGtk() {
183 }
184
185 void InternalPageInfoPopupGtk::BubbleClosing(BubbleGtk* bubble,
186                                              bool closed_by_escape) {
187   delete this;
188 }
189
190 }  // namespace
191
192 // static
193 void WebsiteSettingsPopupGtk::Show(gfx::NativeWindow parent,
194                                    Profile* profile,
195                                    content::WebContents* web_contents,
196                                    const GURL& url,
197                                    const content::SSLStatus& ssl) {
198   if (InternalChromePage(url))
199     new InternalPageInfoPopupGtk(parent, profile);
200   else
201     new WebsiteSettingsPopupGtk(parent, profile, web_contents, url, ssl);
202 }
203
204 WebsiteSettingsPopupGtk::WebsiteSettingsPopupGtk(
205     gfx::NativeWindow parent,
206     Profile* profile,
207     content::WebContents* web_contents,
208     const GURL& url,
209     const content::SSLStatus& ssl)
210     : parent_(parent),
211       contents_(NULL),
212       theme_service_(GtkThemeService::GetFrom(profile)),
213       profile_(profile),
214       web_contents_(web_contents),
215       browser_(NULL),
216       cert_id_(0),
217       header_box_(NULL),
218       cookies_section_contents_(NULL),
219       permissions_section_contents_(NULL),
220       identity_contents_(NULL),
221       connection_contents_(NULL),
222       first_visit_contents_(NULL),
223       notebook_(NULL) {
224   BrowserWindowGtk* browser_window =
225       BrowserWindowGtk::GetBrowserWindowForNativeWindow(parent);
226   browser_ = browser_window->browser();
227   anchor_ = browser_window->
228       GetToolbar()->GetLocationBarView()->location_icon_widget();
229
230   registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
231                  content::Source<ThemeService>(theme_service_));
232
233   InitContents();
234
235   bubble_ = BubbleGtk::Show(anchor_,
236                             NULL,  // |rect|
237                             contents_,
238                             BubbleGtk::ANCHOR_TOP_LEFT,
239                             BubbleGtk::MATCH_SYSTEM_THEME |
240                                 BubbleGtk::POPUP_WINDOW |
241                                 BubbleGtk::GRAB_INPUT,
242                             theme_service_,
243                             this);  // |delegate|
244   if (!bubble_) {
245     NOTREACHED();
246     return;
247   }
248
249   presenter_.reset(new WebsiteSettings(
250       this, profile, TabSpecificContentSettings::FromWebContents(web_contents),
251       InfoBarService::FromWebContents(web_contents), url, ssl,
252       content::CertStore::GetInstance()));
253 }
254
255 WebsiteSettingsPopupGtk::~WebsiteSettingsPopupGtk() {
256 }
257
258 void WebsiteSettingsPopupGtk::BubbleClosing(BubbleGtk* bubble,
259                                             bool closed_by_escape) {
260   if (presenter_.get()) {
261     presenter_->OnUIClosing();
262     presenter_.reset();
263   }
264
265   // Slightly delay destruction to allow the event stack to unwind and release
266   // references to owned widgets.
267   base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
268 }
269
270 void WebsiteSettingsPopupGtk::InitContents() {
271   if (!contents_)
272     contents_ = gtk_vbox_new(FALSE, 0);
273   else
274     gtk_util::RemoveAllChildren(contents_);
275
276   // Create popup header.
277   header_box_ = gtk_vbox_new(FALSE, ui::kControlSpacing);
278   gtk_box_pack_start(GTK_BOX(contents_), header_box_, FALSE, FALSE, 0);
279   gtk_container_set_border_width(GTK_CONTAINER(header_box_),
280                                  ui::kContentAreaBorder);
281
282   // Create the container for the contents of the permissions tab.
283   GtkWidget* permission_tab_contents =
284       gtk_vbox_new(FALSE, ui::kContentAreaSpacing);
285   gtk_container_set_border_width(GTK_CONTAINER(permission_tab_contents),
286                                  ui::kContentAreaBorder);
287   cookies_section_contents_ = gtk_vbox_new(FALSE, ui::kControlSpacing);
288   std::string title = l10n_util::GetStringUTF8(
289       IDS_WEBSITE_SETTINGS_TITLE_SITE_DATA);
290   gtk_box_pack_start(GTK_BOX(permission_tab_contents),
291                      CreatePermissionTabSection(title,
292                                                 cookies_section_contents_,
293                                                 theme_service_),
294                      FALSE, FALSE, 0);
295   permissions_section_contents_ = gtk_vbox_new(FALSE, ui::kControlSpacing);
296   title = l10n_util::GetStringUTF8(IDS_WEBSITE_SETTINGS_TITLE_SITE_PERMISSIONS);
297   gtk_box_pack_start(GTK_BOX(permission_tab_contents),
298                      CreatePermissionTabSection(title,
299                                                 permissions_section_contents_,
300                                                 theme_service_),
301                      FALSE, FALSE, 0);
302
303   // Create the container for the contents of the connection tab.
304   GtkWidget* connection_tab = gtk_vbox_new(FALSE, 0);
305   identity_contents_ = gtk_vbox_new(FALSE, 0);
306   gtk_box_pack_start(GTK_BOX(connection_tab), identity_contents_, FALSE, FALSE,
307                      0);
308   gtk_box_pack_start(GTK_BOX(connection_tab), gtk_hseparator_new(), FALSE,
309                      FALSE, 0);
310   connection_contents_ = gtk_vbox_new(FALSE, 0);
311   gtk_box_pack_start(GTK_BOX(connection_tab), connection_contents_, FALSE,
312                      FALSE, 0);
313   gtk_box_pack_start(GTK_BOX(connection_tab), gtk_hseparator_new(), FALSE,
314                      FALSE, 0);
315   first_visit_contents_ = gtk_vbox_new(FALSE, 0);
316   gtk_box_pack_start(GTK_BOX(connection_tab), first_visit_contents_, FALSE,
317                      FALSE, 0);
318   gtk_box_pack_start(GTK_BOX(connection_tab), gtk_hseparator_new(), FALSE,
319                      FALSE, 0);
320
321   GtkWidget* help_link = theme_service_->BuildChromeLinkButton(
322       l10n_util::GetStringUTF8(IDS_PAGE_INFO_HELP_CENTER_LINK));
323   GtkWidget* help_link_hbox = gtk_hbox_new(FALSE, 0);
324   gtk_container_set_border_width(GTK_CONTAINER(help_link_hbox),
325                                  ui::kContentAreaBorder);
326   gtk_box_pack_start(GTK_BOX(help_link_hbox), help_link, FALSE, FALSE, 0);
327   gtk_box_pack_start(GTK_BOX(connection_tab), help_link_hbox, FALSE, FALSE, 0);
328   g_signal_connect(help_link, "clicked",
329                    G_CALLBACK(OnHelpLinkClickedThunk), this);
330
331   // Create tabstrip (used only for Chrome-theme mode).
332   GtkWidget* tabstrip = gtk_hbox_new(FALSE, kInterTabSpacing);
333   tabstrip_alignment_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
334   gtk_alignment_set_padding(GTK_ALIGNMENT(tabstrip_alignment_), 0, 0,
335                             ui::kContentAreaBorder, ui::kContentAreaBorder);
336   int tab_height = ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(
337       IDR_WEBSITE_SETTINGS_TAB_LEFT2).ToImageSkia()->height();
338   gtk_widget_set_size_request(tabstrip_alignment_, -1, tab_height);
339   g_signal_connect(tabstrip_alignment_, "expose-event",
340                    G_CALLBACK(&OnTabstripExposeThunk), this);
341   gtk_container_add(GTK_CONTAINER(tabstrip_alignment_), tabstrip);
342   gtk_box_pack_start(GTK_BOX(contents_), tabstrip_alignment_, FALSE, FALSE, 0);
343
344   gtk_box_pack_start(GTK_BOX(tabstrip),
345       BuildTab(IDS_WEBSITE_SETTINGS_TAB_LABEL_PERMISSIONS),
346       FALSE, FALSE, 0);
347   gtk_box_pack_start(GTK_BOX(tabstrip),
348       BuildTab(IDS_WEBSITE_SETTINGS_TAB_LABEL_CONNECTION),
349       FALSE, FALSE, 0);
350
351   // Create tab container and add all tabs.
352   notebook_ = gtk_notebook_new();
353   gtk_notebook_set_tab_hborder(GTK_NOTEBOOK(notebook_), 0);
354
355   GtkWidget* label = gtk_label_new(l10n_util::GetStringUTF8(
356       IDS_WEBSITE_SETTINGS_TAB_LABEL_PERMISSIONS).c_str());
357   gtk_misc_set_padding(GTK_MISC(label), kTabTextHorizontalMargin, 0);
358   gtk_notebook_insert_page(GTK_NOTEBOOK(notebook_), permission_tab_contents,
359                            label, TAB_ID_PERMISSIONS);
360
361   label = gtk_label_new(l10n_util::GetStringUTF8(
362       IDS_WEBSITE_SETTINGS_TAB_LABEL_CONNECTION).c_str());
363   gtk_misc_set_padding(GTK_MISC(label), kTabTextHorizontalMargin, 0);
364   gtk_notebook_insert_page(GTK_NOTEBOOK(notebook_), connection_tab, label,
365                            TAB_ID_CONNECTION);
366
367   DCHECK_EQ(gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_)), NUM_TAB_IDS);
368
369   gtk_box_pack_start(GTK_BOX(contents_), notebook_, FALSE, FALSE, 0);
370
371   theme_service_->InitThemesFor(this);
372   gtk_widget_show_all(contents_);
373 }
374
375 GtkWidget* WebsiteSettingsPopupGtk::BuildTab(int ids) {
376   GtkWidget* tab = gtk_event_box_new();
377   gtk_event_box_set_visible_window(GTK_EVENT_BOX(tab), FALSE);
378   GtkWidget* label = gtk_label_new(l10n_util::GetStringUTF8(ids).c_str());
379   gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &ui::kGdkBlack);
380   gtk_misc_set_padding(GTK_MISC(label),
381                        kTabTextHorizontalMargin, kTabTextBaseline);
382   gtk_misc_set_alignment(GTK_MISC(label), 0.5, 1.0);
383   gtk_container_add(GTK_CONTAINER(tab), label);
384   g_signal_connect(tab, "button-press-event",
385                    G_CALLBACK(&OnTabButtonPressThunk), this);
386   g_signal_connect(tab, "expose-event",
387                    G_CALLBACK(&OnTabExposeThunk), this);
388   return tab;
389 }
390
391 void WebsiteSettingsPopupGtk::Observe(
392     int type,
393     const content::NotificationSource& source,
394     const content::NotificationDetails& details) {
395   DCHECK_EQ(chrome::NOTIFICATION_BROWSER_THEME_CHANGED, type);
396
397   if (theme_service_->UsingNativeTheme()) {
398     gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook_), TRUE);
399     gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook_), TRUE);
400     gtk_widget_set_no_show_all(tabstrip_alignment_, TRUE);
401   } else {
402     gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook_), FALSE);
403     gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook_), FALSE);
404     gtk_widget_set_no_show_all(tabstrip_alignment_, FALSE);
405     gtk_widget_show_all(tabstrip_alignment_);
406   }
407 }
408
409 void WebsiteSettingsPopupGtk::OnPermissionChanged(
410     PermissionSelector* selector) {
411   presenter_->OnSitePermissionChanged(selector->GetType(),
412                                       selector->GetSetting());
413 }
414
415 void WebsiteSettingsPopupGtk::SetCookieInfo(
416     const CookieInfoList& cookie_info_list) {
417   DCHECK(cookies_section_contents_);
418   ClearContainer(cookies_section_contents_);
419
420   // Create cookies info rows.
421   for (CookieInfoList::const_iterator it = cookie_info_list.begin();
422        it != cookie_info_list.end();
423        ++it) {
424     // Create the cookies info box.
425     GtkWidget* cookies_info = gtk_hbox_new(FALSE, 0);
426
427     // Add the icon to the cookies info box
428     GdkPixbuf* pixbuf = WebsiteSettingsUI::GetPermissionIcon(
429         CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_ALLOW).ToGdkPixbuf();
430     GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf);
431     gtk_misc_set_alignment(GTK_MISC(image), 0, 0);
432     gtk_box_pack_start(GTK_BOX(cookies_info), image, FALSE, FALSE, 0);
433
434     // Add the allowed and blocked cookies counts to the cookies info box.
435     std::string info_str = l10n_util::GetStringFUTF8(
436         IDS_WEBSITE_SETTINGS_SITE_DATA_STATS_LINE,
437         base::UTF8ToUTF16(it->cookie_source),
438         base::IntToString16(it->allowed),
439         base::IntToString16(it->blocked));
440
441     GtkWidget* info = theme_service_->BuildLabel(info_str, ui::kGdkBlack);
442     const int kPadding = 4;
443     gtk_box_pack_start(GTK_BOX(cookies_info), info, FALSE, FALSE, kPadding);
444
445     // Add the cookies info box to the section box.
446     gtk_box_pack_start(GTK_BOX(cookies_section_contents_),
447                        cookies_info,
448                        FALSE, FALSE, 0);
449   }
450
451   // Create row with links for cookie settings and for the cookies dialog.
452   GtkWidget* link_hbox = gtk_hbox_new(FALSE, 0);
453
454   GtkWidget* view_cookies_link = theme_service_->BuildChromeLinkButton(
455       l10n_util::GetStringUTF8(IDS_WEBSITE_SETTINGS_SHOW_SITE_DATA));
456   g_signal_connect(view_cookies_link, "clicked",
457                    G_CALLBACK(OnCookiesLinkClickedThunk), this);
458   gtk_box_pack_start(GTK_BOX(link_hbox), view_cookies_link,
459                      FALSE, FALSE, 0);
460
461   gtk_box_pack_start(GTK_BOX(cookies_section_contents_), link_hbox,
462                      TRUE, FALSE, 0);
463
464   gtk_widget_show_all(cookies_section_contents_);
465 }
466
467 void WebsiteSettingsPopupGtk::SetIdentityInfo(
468     const IdentityInfo& identity_info) {
469   // Create popup header.
470   DCHECK(header_box_);
471   ClearContainer(header_box_);
472
473   GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
474   GtkWidget* identity_label = theme_service_->BuildLabel(
475       identity_info.site_identity, ui::kGdkBlack);
476   gtk_label_set_selectable(GTK_LABEL(identity_label), TRUE);
477   PangoAttrList* attributes = pango_attr_list_new();
478   pango_attr_list_insert(attributes,
479                          pango_attr_weight_new(PANGO_WEIGHT_BOLD));
480   gtk_label_set_attributes(GTK_LABEL(identity_label), attributes);
481   pango_attr_list_unref(attributes);
482   gtk_box_pack_start(GTK_BOX(hbox), identity_label, FALSE, FALSE, 0);
483   close_button_.reset(CustomDrawButton::CloseButtonBubble(theme_service_));
484   g_signal_connect(close_button_->widget(), "clicked",
485                    G_CALLBACK(OnCloseButtonClickedThunk), this);
486   gtk_box_pack_start(GTK_BOX(hbox), close_button_->widget(), FALSE, FALSE, 0);
487   int label_width = kPopupWidth - close_button_->SurfaceWidth();
488   gtk_util::SetLabelWidth(identity_label, label_width);
489   gtk_box_pack_start(GTK_BOX(header_box_), hbox, FALSE, FALSE, 0);
490
491   std::string identity_status_text;
492   const GdkColor* color = &ui::kGdkBlack;
493
494   switch (identity_info.identity_status) {
495     case WebsiteSettings::SITE_IDENTITY_STATUS_CERT:
496     case WebsiteSettings::SITE_IDENTITY_STATUS_EV_CERT:
497       identity_status_text =
498           l10n_util::GetStringUTF8(IDS_WEBSITE_SETTINGS_IDENTITY_VERIFIED);
499       color = &kGdkGreen;
500       break;
501     case WebsiteSettings::SITE_IDENTITY_STATUS_ADMIN_PROVIDED_CERT:
502       identity_status_text =
503           l10n_util::GetStringUTF8(IDS_CERT_POLICY_PROVIDED_CERT_HEADER);
504       break;
505     default:
506       identity_status_text =
507           l10n_util::GetStringUTF8(IDS_WEBSITE_SETTINGS_IDENTITY_NOT_VERIFIED);
508       break;
509   }
510   GtkWidget* status_label = CreateTextLabel(
511       identity_status_text, kPopupWidth, theme_service_, *color);
512   gtk_box_pack_start(
513       GTK_BOX(header_box_), status_label, FALSE, FALSE, 0);
514   gtk_widget_show_all(header_box_);
515
516   // Create identity section.
517   GtkWidget* section_content = gtk_vbox_new(FALSE, ui::kControlSpacing);
518   GtkWidget* identity_description =
519       CreateTextLabel(identity_info.identity_status_description,
520                       kConnectionTabTextWidth, theme_service_, ui::kGdkBlack);
521   gtk_box_pack_start(GTK_BOX(section_content), identity_description, FALSE,
522                      FALSE, 0);
523   if (identity_info.cert_id) {
524     cert_id_ = identity_info.cert_id;
525     GtkWidget* view_cert_link = theme_service_->BuildChromeLinkButton(
526         l10n_util::GetStringUTF8(IDS_PAGEINFO_CERT_INFO_BUTTON));
527     g_signal_connect(view_cert_link, "clicked",
528                      G_CALLBACK(OnViewCertLinkClickedThunk), this);
529     GtkWidget* link_hbox = gtk_hbox_new(FALSE, 0);
530     gtk_box_pack_start(GTK_BOX(link_hbox), view_cert_link,
531                        FALSE, FALSE, 0);
532     gtk_box_pack_start(GTK_BOX(section_content), link_hbox, FALSE, FALSE, 0);
533   }
534   SetConnectionSection(
535       identity_contents_,
536       WebsiteSettingsUI::GetIdentityIcon(identity_info.identity_status),
537       section_content);
538
539   // Create connection section.
540   GtkWidget* connection_description =
541       CreateTextLabel(identity_info.connection_status_description,
542                       kConnectionTabTextWidth, theme_service_, ui::kGdkBlack);
543   section_content = gtk_vbox_new(FALSE, ui::kControlSpacing);
544   gtk_box_pack_start(GTK_BOX(section_content), connection_description, FALSE,
545                      FALSE, 0);
546   SetConnectionSection(
547       connection_contents_,
548       WebsiteSettingsUI::GetConnectionIcon(identity_info.connection_status),
549       section_content);
550 }
551
552 void WebsiteSettingsPopupGtk::SetFirstVisit(const base::string16& first_visit) {
553   GtkWidget* title = theme_service_->BuildLabel(
554       l10n_util::GetStringUTF8(IDS_PAGE_INFO_SITE_INFO_TITLE),
555       ui::kGdkBlack);
556   PangoAttrList* attributes = pango_attr_list_new();
557   pango_attr_list_insert(attributes,
558                          pango_attr_weight_new(PANGO_WEIGHT_BOLD));
559   gtk_label_set_attributes(GTK_LABEL(title), attributes);
560   pango_attr_list_unref(attributes);
561   gtk_misc_set_alignment(GTK_MISC(title), 0, 0);
562
563   GtkWidget* first_visit_label = CreateTextLabel(base::UTF16ToUTF8(first_visit),
564                                                  kConnectionTabTextWidth,
565                                                  theme_service_,
566                                                  ui::kGdkBlack);
567   GtkWidget* section_contents = gtk_vbox_new(FALSE, ui::kControlSpacing);
568   gtk_box_pack_start(GTK_BOX(section_contents), title, FALSE, FALSE, 0);
569   gtk_box_pack_start(
570       GTK_BOX(section_contents), first_visit_label, FALSE, FALSE, 0);
571
572   SetConnectionSection(
573       first_visit_contents_,
574       WebsiteSettingsUI::GetFirstVisitIcon(first_visit),
575       section_contents);
576 }
577
578 void WebsiteSettingsPopupGtk::SetPermissionInfo(
579       const PermissionInfoList& permission_info_list) {
580   DCHECK(permissions_section_contents_);
581   ClearContainer(permissions_section_contents_);
582   // Clear the map since the UI is reconstructed.
583   selectors_.clear();
584
585   for (PermissionInfoList::const_iterator permission =
586            permission_info_list.begin();
587        permission != permission_info_list.end();
588        ++permission) {
589     PermissionSelector* selector =
590         new PermissionSelector(
591            theme_service_,
592            web_contents_ ? web_contents_->GetURL() : GURL::EmptyGURL(),
593            permission->type,
594            permission->setting,
595            permission->default_setting,
596            permission->source);
597     selector->AddObserver(this);
598     GtkWidget* hbox = selector->widget();
599     selectors_.push_back(selector);
600     gtk_box_pack_start(GTK_BOX(permissions_section_contents_), hbox, FALSE,
601                        FALSE, 0);
602   }
603
604   gtk_widget_show_all(permissions_section_contents_);
605 }
606
607 void WebsiteSettingsPopupGtk::SetSelectedTab(TabId tab_id) {
608   DCHECK(notebook_);
609   gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook_),
610                                 static_cast<gint>(tab_id));
611 }
612
613 int WebsiteSettingsPopupGtk::TabstripButtonToTabIndex(GtkWidget* button) {
614   GList* tabs = gtk_container_get_children(GTK_CONTAINER(button->parent));
615   int i = 0;
616   for (GList* it = tabs; it; it = g_list_next(it), ++i) {
617     if (it->data == button)
618       break;
619   }
620   g_list_free(tabs);
621
622   return i;
623 }
624
625 gboolean WebsiteSettingsPopupGtk::OnTabButtonPress(
626     GtkWidget* widget, GdkEvent* event) {
627   gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook_),
628                                 TabstripButtonToTabIndex(widget));
629   gtk_widget_queue_draw(tabstrip_alignment_);
630   return FALSE;
631 }
632
633 gboolean WebsiteSettingsPopupGtk::OnTabExpose(
634     GtkWidget* widget, GdkEventExpose* event) {
635   if (gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_)) !=
636       TabstripButtonToTabIndex(widget)) {
637     return FALSE;
638   }
639
640   NineBox nine(IDR_WEBSITE_SETTINGS_TAB_LEFT2,
641                IDR_WEBSITE_SETTINGS_TAB_CENTER2,
642                IDR_WEBSITE_SETTINGS_TAB_RIGHT2,
643                0, 0, 0, 0, 0, 0);
644   nine.RenderToWidget(widget);
645
646   return FALSE;
647 }
648
649 gboolean WebsiteSettingsPopupGtk::OnTabstripExpose(
650     GtkWidget* widget, GdkEventExpose* event) {
651   int tab_idx = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_));
652   GtkWidget* tabstrip = gtk_bin_get_child(GTK_BIN(tabstrip_alignment_));
653   GList* tabs = gtk_container_get_children(GTK_CONTAINER(tabstrip));
654   GtkWidget* selected_tab = GTK_WIDGET(g_list_nth_data(tabs, tab_idx));
655   g_list_free(tabs);
656   GtkAllocation tab_bounds;
657   gtk_widget_get_allocation(selected_tab, &tab_bounds);
658
659   cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(gtk_widget_get_window(widget)));
660   GtkAllocation allocation;
661   gtk_widget_get_allocation(widget, &allocation);
662   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
663
664   // Draw the shadows that abut the selected tab.
665   gfx::CairoCachedSurface* left_tab_shadow =
666       rb.GetNativeImageNamed(IDR_WEBSITE_SETTINGS_TABSTRIP_LEFT).ToCairo();
667   int tab_shadow_width = left_tab_shadow->Width();
668   left_tab_shadow->SetSource(cr, widget,
669       tab_bounds.x - tab_shadow_width, allocation.y);
670   cairo_paint(cr);
671
672   gfx::CairoCachedSurface* right_tab_shadow =
673       rb.GetNativeImageNamed(IDR_WEBSITE_SETTINGS_TABSTRIP_RIGHT).ToCairo();
674   right_tab_shadow->SetSource(cr, widget,
675       tab_bounds.x + tab_bounds.width, allocation.y);
676   cairo_paint(cr);
677
678   // Draw the shadow for the inactive part of the tabstrip.
679   gfx::CairoCachedSurface* tiling_shadow =
680       rb.GetNativeImageNamed(IDR_WEBSITE_SETTINGS_TABSTRIP_CENTER).ToCairo();
681
682   tiling_shadow->SetSource(cr, widget, allocation.x, allocation.y);
683   cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
684
685   GdkRectangle left_tiling_area =
686       { allocation.x, allocation.y,
687         tab_bounds.x - tab_shadow_width, allocation.height };
688   GdkRectangle invalid_left_tiling_area;
689   if (gdk_rectangle_intersect(&left_tiling_area, &event->area,
690                               &invalid_left_tiling_area)) {
691     gdk_cairo_rectangle(cr, &invalid_left_tiling_area);
692     cairo_fill(cr);
693   }
694
695   GdkRectangle right_tiling_area =
696       { tab_bounds.x + tab_bounds.width + tab_shadow_width,
697         allocation.y,
698         allocation.width,
699         allocation.height };
700   GdkRectangle invalid_right_tiling_area;
701   if (gdk_rectangle_intersect(&right_tiling_area, &event->area,
702                               &invalid_right_tiling_area)) {
703     gdk_cairo_rectangle(cr, &invalid_right_tiling_area);
704     cairo_fill(cr);
705   }
706
707   cairo_destroy(cr);
708   return FALSE;
709 }
710
711 void WebsiteSettingsPopupGtk::OnCookiesLinkClicked(GtkWidget* widget) {
712   // Count how often the Collected Cookies dialog is opened.
713   content::RecordAction(
714       base::UserMetricsAction("WebsiteSettings_CookiesDialogOpened"));
715
716   new CollectedCookiesGtk(GTK_WINDOW(parent_), web_contents_);
717   bubble_->Close();
718 }
719
720 void WebsiteSettingsPopupGtk::OnViewCertLinkClicked(GtkWidget* widget) {
721   DCHECK_NE(cert_id_, 0);
722   ShowCertificateViewerByID(web_contents_, GTK_WINDOW(parent_), cert_id_);
723   bubble_->Close();
724 }
725
726 void WebsiteSettingsPopupGtk::OnCloseButtonClicked(GtkWidget* widget) {
727   bubble_->Close();
728 }
729
730 void WebsiteSettingsPopupGtk::OnHelpLinkClicked(GtkWidget* widget) {
731   browser_->OpenURL(OpenURLParams(GURL(chrome::kPageInfoHelpCenterURL),
732                     content::Referrer(),
733                     NEW_FOREGROUND_TAB,
734                     content::PAGE_TRANSITION_LINK,
735                      false));
736   bubble_->Close();
737 }