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.
5 #include "chrome/browser/ui/gtk/website_settings/website_settings_popup_gtk.h"
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"
42 using content::OpenURLParams
;
46 // The width of the popup.
47 const int kPopupWidth
= 400;
49 // Spacing between consecutive tabs in the tabstrip.
50 const int kInterTabSpacing
= 2;
52 // Spacing between start of tab and tab text.
53 const int kTabTextHorizontalMargin
= 12;
55 // The vertical lift of the tab's text off the bottom of the tab.
56 const int kTabTextBaseline
= 4;
58 // The max width of the text labels on the connection tab.
59 const int kConnectionTabTextWidth
= 300;
61 // The text color of the site identity status label for websites with a
63 const GdkColor kGdkGreen
= GDK_COLOR_RGB(0x29, 0x8a, 0x27);
65 GtkWidget
* CreateTextLabel(const std::string
& text
,
67 GtkThemeService
* theme_service
,
68 const GdkColor
& color
) {
69 GtkWidget
* label
= theme_service
->BuildLabel(text
, color
);
71 gtk_util::SetLabelWidth(label
, width
);
72 gtk_label_set_line_wrap_mode(GTK_LABEL(label
), PANGO_WRAP_WORD_CHAR
);
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
));
84 void SetConnectionSection(GtkWidget
* section_box
,
85 const gfx::Image
& icon
,
86 GtkWidget
* content_box
) {
88 ClearContainer(section_box
);
89 gtk_container_set_border_width(GTK_CONTAINER(section_box
),
90 ui::kContentAreaBorder
);
92 GtkWidget
* hbox
= gtk_hbox_new(FALSE
, ui::kControlSpacing
);
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);
99 gtk_box_pack_start(GTK_BOX(hbox
), content_box
, TRUE
, TRUE
, 0);
101 gtk_box_pack_start(GTK_BOX(section_box
), hbox
, TRUE
, TRUE
, 0);
102 gtk_widget_show_all(section_box
);
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
);
111 GtkWidget
* title_hbox
= gtk_hbox_new(FALSE
, ui::kControlSpacing
);
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);
121 gtk_box_pack_start(GTK_BOX(title_hbox
), label
, FALSE
, FALSE
, 0);
123 // Add section content
124 gtk_box_pack_start(GTK_BOX(section_box
), section_content
, FALSE
, FALSE
, 0);
128 // A popup that is shown for internal pages (like chrome://).
129 class InternalPageInfoPopupGtk
: public BubbleDelegateGtk
{
131 explicit InternalPageInfoPopupGtk(gfx::NativeWindow parent
,
133 virtual ~InternalPageInfoPopupGtk();
136 // BubbleDelegateGtk implementation.
137 virtual void BubbleClosing(BubbleGtk
* bubble
, bool closed_by_escape
) OVERRIDE
;
139 // The popup bubble container.
142 DISALLOW_COPY_AND_ASSIGN(InternalPageInfoPopupGtk
);
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);
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);
163 gtk_widget_show_all(contents
);
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
,
173 BubbleGtk::ANCHOR_TOP_LEFT
,
174 BubbleGtk::MATCH_SYSTEM_THEME
|
175 BubbleGtk::POPUP_WINDOW
|
176 BubbleGtk::GRAB_INPUT
,
182 InternalPageInfoPopupGtk::~InternalPageInfoPopupGtk() {
185 void InternalPageInfoPopupGtk::BubbleClosing(BubbleGtk
* bubble
,
186 bool closed_by_escape
) {
193 void WebsiteSettingsPopupGtk::Show(gfx::NativeWindow parent
,
195 content::WebContents
* web_contents
,
197 const content::SSLStatus
& ssl
) {
198 if (InternalChromePage(url
))
199 new InternalPageInfoPopupGtk(parent
, profile
);
201 new WebsiteSettingsPopupGtk(parent
, profile
, web_contents
, url
, ssl
);
204 WebsiteSettingsPopupGtk::WebsiteSettingsPopupGtk(
205 gfx::NativeWindow parent
,
207 content::WebContents
* web_contents
,
209 const content::SSLStatus
& ssl
)
212 theme_service_(GtkThemeService::GetFrom(profile
)),
214 web_contents_(web_contents
),
218 cookies_section_contents_(NULL
),
219 permissions_section_contents_(NULL
),
220 identity_contents_(NULL
),
221 connection_contents_(NULL
),
222 first_visit_contents_(NULL
),
224 BrowserWindowGtk
* browser_window
=
225 BrowserWindowGtk::GetBrowserWindowForNativeWindow(parent
);
226 browser_
= browser_window
->browser();
227 anchor_
= browser_window
->
228 GetToolbar()->GetLocationBarView()->location_icon_widget();
230 registrar_
.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED
,
231 content::Source
<ThemeService
>(theme_service_
));
235 bubble_
= BubbleGtk::Show(anchor_
,
238 BubbleGtk::ANCHOR_TOP_LEFT
,
239 BubbleGtk::MATCH_SYSTEM_THEME
|
240 BubbleGtk::POPUP_WINDOW
|
241 BubbleGtk::GRAB_INPUT
,
249 presenter_
.reset(new WebsiteSettings(
250 this, profile
, TabSpecificContentSettings::FromWebContents(web_contents
),
251 InfoBarService::FromWebContents(web_contents
), url
, ssl
,
252 content::CertStore::GetInstance()));
255 WebsiteSettingsPopupGtk::~WebsiteSettingsPopupGtk() {
258 void WebsiteSettingsPopupGtk::BubbleClosing(BubbleGtk
* bubble
,
259 bool closed_by_escape
) {
260 if (presenter_
.get()) {
261 presenter_
->OnUIClosing();
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);
270 void WebsiteSettingsPopupGtk::InitContents() {
272 contents_
= gtk_vbox_new(FALSE
, 0);
274 gtk_util::RemoveAllChildren(contents_
);
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
);
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_
,
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_
,
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
,
308 gtk_box_pack_start(GTK_BOX(connection_tab
), gtk_hseparator_new(), FALSE
,
310 connection_contents_
= gtk_vbox_new(FALSE
, 0);
311 gtk_box_pack_start(GTK_BOX(connection_tab
), connection_contents_
, FALSE
,
313 gtk_box_pack_start(GTK_BOX(connection_tab
), gtk_hseparator_new(), FALSE
,
315 first_visit_contents_
= gtk_vbox_new(FALSE
, 0);
316 gtk_box_pack_start(GTK_BOX(connection_tab
), first_visit_contents_
, FALSE
,
318 gtk_box_pack_start(GTK_BOX(connection_tab
), gtk_hseparator_new(), FALSE
,
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);
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);
344 gtk_box_pack_start(GTK_BOX(tabstrip
),
345 BuildTab(IDS_WEBSITE_SETTINGS_TAB_LABEL_PERMISSIONS
),
347 gtk_box_pack_start(GTK_BOX(tabstrip
),
348 BuildTab(IDS_WEBSITE_SETTINGS_TAB_LABEL_CONNECTION
),
351 // Create tab container and add all tabs.
352 notebook_
= gtk_notebook_new();
353 gtk_notebook_set_tab_hborder(GTK_NOTEBOOK(notebook_
), 0);
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
);
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
,
367 DCHECK_EQ(gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_
)), NUM_TAB_IDS
);
369 gtk_box_pack_start(GTK_BOX(contents_
), notebook_
, FALSE
, FALSE
, 0);
371 theme_service_
->InitThemesFor(this);
372 gtk_widget_show_all(contents_
);
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);
391 void WebsiteSettingsPopupGtk::Observe(
393 const content::NotificationSource
& source
,
394 const content::NotificationDetails
& details
) {
395 DCHECK_EQ(chrome::NOTIFICATION_BROWSER_THEME_CHANGED
, type
);
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
);
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_
);
409 void WebsiteSettingsPopupGtk::OnPermissionChanged(
410 PermissionSelector
* selector
) {
411 presenter_
->OnSitePermissionChanged(selector
->GetType(),
412 selector
->GetSetting());
415 void WebsiteSettingsPopupGtk::SetCookieInfo(
416 const CookieInfoList
& cookie_info_list
) {
417 DCHECK(cookies_section_contents_
);
418 ClearContainer(cookies_section_contents_
);
420 // Create cookies info rows.
421 for (CookieInfoList::const_iterator it
= cookie_info_list
.begin();
422 it
!= cookie_info_list
.end();
424 // Create the cookies info box.
425 GtkWidget
* cookies_info
= gtk_hbox_new(FALSE
, 0);
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);
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
));
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
);
445 // Add the cookies info box to the section box.
446 gtk_box_pack_start(GTK_BOX(cookies_section_contents_
),
451 // Create row with links for cookie settings and for the cookies dialog.
452 GtkWidget
* link_hbox
= gtk_hbox_new(FALSE
, 0);
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
,
461 gtk_box_pack_start(GTK_BOX(cookies_section_contents_
), link_hbox
,
464 gtk_widget_show_all(cookies_section_contents_
);
467 void WebsiteSettingsPopupGtk::SetIdentityInfo(
468 const IdentityInfo
& identity_info
) {
469 // Create popup header.
471 ClearContainer(header_box_
);
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);
491 std::string identity_status_text
;
492 const GdkColor
* color
= &ui::kGdkBlack
;
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
);
501 case WebsiteSettings::SITE_IDENTITY_STATUS_ADMIN_PROVIDED_CERT
:
502 identity_status_text
=
503 l10n_util::GetStringUTF8(IDS_CERT_POLICY_PROVIDED_CERT_HEADER
);
506 identity_status_text
=
507 l10n_util::GetStringUTF8(IDS_WEBSITE_SETTINGS_IDENTITY_NOT_VERIFIED
);
510 GtkWidget
* status_label
= CreateTextLabel(
511 identity_status_text
, kPopupWidth
, theme_service_
, *color
);
513 GTK_BOX(header_box_
), status_label
, FALSE
, FALSE
, 0);
514 gtk_widget_show_all(header_box_
);
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
,
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
,
532 gtk_box_pack_start(GTK_BOX(section_content
), link_hbox
, FALSE
, FALSE
, 0);
534 SetConnectionSection(
536 WebsiteSettingsUI::GetIdentityIcon(identity_info
.identity_status
),
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
,
546 SetConnectionSection(
547 connection_contents_
,
548 WebsiteSettingsUI::GetConnectionIcon(identity_info
.connection_status
),
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
),
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);
563 GtkWidget
* first_visit_label
= CreateTextLabel(base::UTF16ToUTF8(first_visit
),
564 kConnectionTabTextWidth
,
567 GtkWidget
* section_contents
= gtk_vbox_new(FALSE
, ui::kControlSpacing
);
568 gtk_box_pack_start(GTK_BOX(section_contents
), title
, FALSE
, FALSE
, 0);
570 GTK_BOX(section_contents
), first_visit_label
, FALSE
, FALSE
, 0);
572 SetConnectionSection(
573 first_visit_contents_
,
574 WebsiteSettingsUI::GetFirstVisitIcon(first_visit
),
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.
585 for (PermissionInfoList::const_iterator permission
=
586 permission_info_list
.begin();
587 permission
!= permission_info_list
.end();
589 PermissionSelector
* selector
=
590 new PermissionSelector(
592 web_contents_
? web_contents_
->GetURL() : GURL::EmptyGURL(),
595 permission
->default_setting
,
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
,
604 gtk_widget_show_all(permissions_section_contents_
);
607 void WebsiteSettingsPopupGtk::SetSelectedTab(TabId tab_id
) {
609 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook_
),
610 static_cast<gint
>(tab_id
));
613 int WebsiteSettingsPopupGtk::TabstripButtonToTabIndex(GtkWidget
* button
) {
614 GList
* tabs
= gtk_container_get_children(GTK_CONTAINER(button
->parent
));
616 for (GList
* it
= tabs
; it
; it
= g_list_next(it
), ++i
) {
617 if (it
->data
== button
)
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_
);
633 gboolean
WebsiteSettingsPopupGtk::OnTabExpose(
634 GtkWidget
* widget
, GdkEventExpose
* event
) {
635 if (gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_
)) !=
636 TabstripButtonToTabIndex(widget
)) {
640 NineBox
nine(IDR_WEBSITE_SETTINGS_TAB_LEFT2
,
641 IDR_WEBSITE_SETTINGS_TAB_CENTER2
,
642 IDR_WEBSITE_SETTINGS_TAB_RIGHT2
,
644 nine
.RenderToWidget(widget
);
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
));
656 GtkAllocation tab_bounds
;
657 gtk_widget_get_allocation(selected_tab
, &tab_bounds
);
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();
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
);
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
);
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();
682 tiling_shadow
->SetSource(cr
, widget
, allocation
.x
, allocation
.y
);
683 cairo_pattern_set_extend(cairo_get_source(cr
), CAIRO_EXTEND_REPEAT
);
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
);
695 GdkRectangle right_tiling_area
=
696 { tab_bounds
.x
+ tab_bounds
.width
+ tab_shadow_width
,
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
);
711 void WebsiteSettingsPopupGtk::OnCookiesLinkClicked(GtkWidget
* widget
) {
712 // Count how often the Collected Cookies dialog is opened.
713 content::RecordAction(
714 base::UserMetricsAction("WebsiteSettings_CookiesDialogOpened"));
716 new CollectedCookiesGtk(GTK_WINDOW(parent_
), web_contents_
);
720 void WebsiteSettingsPopupGtk::OnViewCertLinkClicked(GtkWidget
* widget
) {
721 DCHECK_NE(cert_id_
, 0);
722 ShowCertificateViewerByID(web_contents_
, GTK_WINDOW(parent_
), cert_id_
);
726 void WebsiteSettingsPopupGtk::OnCloseButtonClicked(GtkWidget
* widget
) {
730 void WebsiteSettingsPopupGtk::OnHelpLinkClicked(GtkWidget
* widget
) {
731 browser_
->OpenURL(OpenURLParams(GURL(chrome::kPageInfoHelpCenterURL
),
734 content::PAGE_TRANSITION_LINK
,