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 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 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(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 content::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 } 738