website_settings_popup_view.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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/views/website_settings/website_settings_popup_view.h" 6 7#include <algorithm> 8 9#include "base/command_line.h" 10#include "base/strings/string_number_conversions.h" 11#include "base/strings/utf_string_conversions.h" 12#include "chrome/browser/certificate_viewer.h" 13#include "chrome/browser/infobars/infobar_service.h" 14#include "chrome/browser/profiles/profile.h" 15#include "chrome/browser/ui/browser.h" 16#include "chrome/browser/ui/browser_dialogs.h" 17#include "chrome/browser/ui/views/collected_cookies_views.h" 18#include "chrome/browser/ui/views/website_settings/permission_selector_view.h" 19#include "chrome/browser/ui/website_settings/website_settings.h" 20#include "chrome/browser/ui/website_settings/website_settings_utils.h" 21#include "chrome/common/chrome_switches.h" 22#include "chrome/common/content_settings_types.h" 23#include "chrome/common/url_constants.h" 24#include "content/public/browser/browser_thread.h" 25#include "content/public/browser/cert_store.h" 26#include "content/public/browser/user_metrics.h" 27#include "grit/chromium_strings.h" 28#include "grit/generated_resources.h" 29#include "grit/theme_resources.h" 30#include "grit/ui_resources.h" 31#include "ui/base/l10n/l10n_util.h" 32#include "ui/base/models/simple_menu_model.h" 33#include "ui/base/resource/resource_bundle.h" 34#include "ui/gfx/canvas.h" 35#include "ui/gfx/font_list.h" 36#include "ui/gfx/image/image.h" 37#include "ui/gfx/insets.h" 38#include "ui/views/controls/button/image_button.h" 39#include "ui/views/controls/button/menu_button.h" 40#include "ui/views/controls/button/menu_button_listener.h" 41#include "ui/views/controls/image_view.h" 42#include "ui/views/controls/label.h" 43#include "ui/views/controls/link.h" 44#include "ui/views/controls/menu/menu_model_adapter.h" 45#include "ui/views/controls/menu/menu_runner.h" 46#include "ui/views/controls/separator.h" 47#include "ui/views/controls/tabbed_pane/tabbed_pane.h" 48#include "ui/views/layout/box_layout.h" 49#include "ui/views/layout/grid_layout.h" 50#include "ui/views/layout/layout_manager.h" 51#include "ui/views/view.h" 52#include "ui/views/widget/widget.h" 53#include "url/gurl.h" 54 55namespace { 56 57// Padding values for sections on the connection tab. 58const int kConnectionSectionPaddingBottom = 16; 59const int kConnectionSectionPaddingLeft = 18; 60const int kConnectionSectionPaddingTop = 16; 61const int kConnectionSectionPaddingRight = 18; 62 63// The text color that is used for the site identity status text, if the site's 64// identity was sucessfully verified. 65const int kIdentityVerifiedTextColor = 0xFF298a27; 66 67// Left icon margin. 68const int kIconMarginLeft = 6; 69 70// Margin and padding values for the |PopupHeaderView|. 71const int kHeaderMarginBottom = 10; 72const int kHeaderPaddingBottom = 12; 73const int kHeaderPaddingLeft = 18; 74const int kHeaderPaddingRight = 8; 75const int kHeaderPaddingTop = 12; 76 77// Spacing between the site identity label and the site identity status text in 78// the popup header. 79const int kHeaderRowSpacing = 4; 80 81// To make the bubble's arrow point directly at the location icon rather than at 82// the Omnibox's edge, inset the bubble's anchor rect by this amount of pixels. 83const int kLocationIconVerticalMargin = 5; 84 85// The max possible width of the popup. 86const int kMaxPopupWidth = 500; 87 88// The margins between the popup border and the popup content. 89const int kPopupMarginTop = 4; 90const int kPopupMarginLeft = 0; 91const int kPopupMarginBottom = 10; 92const int kPopupMarginRight = 0; 93 94// Padding values for sections on the permissions tab. 95const int kPermissionsSectionContentMinWidth = 300; 96const int kPermissionsSectionPaddingBottom = 6; 97const int kPermissionsSectionPaddingLeft = 18; 98const int kPermissionsSectionPaddingTop = 16; 99 100// Space between the headline and the content of a section on the permissions 101// tab. 102const int kPermissionsSectionHeadlineMarginBottom = 10; 103// The content of the "Permissions" section and the "Cookies and Site Data" 104// section is structured in individual rows. |kPermissionsSectionRowSpacing| 105// is the space between these rows. 106const int kPermissionsSectionRowSpacing = 2; 107 108const int kSiteDataIconColumnWidth = 20; 109const int kSiteDataSectionRowSpacing = 11; 110 111} // namespace 112 113// |PopupHeaderView| is the UI element (view) that represents the header of the 114// |WebsiteSettingsPopupView|. The header shows the status of the site's 115// identity check and the name of the site's identity. 116class PopupHeaderView : public views::View { 117 public: 118 explicit PopupHeaderView(views::ButtonListener* close_button_listener); 119 virtual ~PopupHeaderView(); 120 121 // Sets the name of the site's identity. 122 void SetIdentityName(const base::string16& name); 123 124 // Sets the |status_text| for the identity check of this site and the 125 // |text_color|. 126 void SetIdentityStatus(const base::string16& status_text, SkColor text_color); 127 128 private: 129 // The label that displays the name of the site's identity. 130 views::Label* name_; 131 // The label that displays the status of the identity check for this site. 132 views::Label* status_; 133 134 DISALLOW_COPY_AND_ASSIGN(PopupHeaderView); 135}; 136 137// Website Settings are not supported for internal Chrome pages. Instead of the 138// |WebsiteSettingsPopupView|, the |InternalPageInfoPopupView| is 139// displayed. 140class InternalPageInfoPopupView : public views::BubbleDelegateView { 141 public: 142 explicit InternalPageInfoPopupView(views::View* anchor_view); 143 virtual ~InternalPageInfoPopupView(); 144 145 private: 146 DISALLOW_COPY_AND_ASSIGN(InternalPageInfoPopupView); 147}; 148 149//////////////////////////////////////////////////////////////////////////////// 150// Popup Header 151//////////////////////////////////////////////////////////////////////////////// 152 153PopupHeaderView::PopupHeaderView(views::ButtonListener* close_button_listener) 154 : name_(NULL), status_(NULL) { 155 views::GridLayout* layout = new views::GridLayout(this); 156 SetLayoutManager(layout); 157 158 const int label_column = 0; 159 views::ColumnSet* column_set = layout->AddColumnSet(label_column); 160 column_set->AddPaddingColumn(0, kHeaderPaddingLeft); 161 column_set->AddColumn(views::GridLayout::FILL, 162 views::GridLayout::FILL, 163 1, 164 views::GridLayout::USE_PREF, 165 0, 166 0); 167 column_set->AddPaddingColumn(1, 0); 168 column_set->AddColumn(views::GridLayout::FILL, 169 views::GridLayout::FILL, 170 1, 171 views::GridLayout::USE_PREF, 172 0, 173 0); 174 column_set->AddPaddingColumn(0, kHeaderPaddingRight); 175 176 layout->AddPaddingRow(0, kHeaderPaddingTop); 177 178 layout->StartRow(0, label_column); 179 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 180 name_ = new views::Label( 181 base::string16(), rb.GetFontList(ui::ResourceBundle::BoldFont)); 182 layout->AddView(name_, 1, 1, views::GridLayout::LEADING, 183 views::GridLayout::TRAILING); 184 views::ImageButton* close_button = 185 new views::ImageButton(close_button_listener); 186 close_button->SetImage(views::CustomButton::STATE_NORMAL, 187 rb.GetImageNamed(IDR_CLOSE_2).ToImageSkia()); 188 close_button->SetImage(views::CustomButton::STATE_HOVERED, 189 rb.GetImageNamed(IDR_CLOSE_2_H).ToImageSkia()); 190 close_button->SetImage(views::CustomButton::STATE_PRESSED, 191 rb.GetImageNamed(IDR_CLOSE_2_P).ToImageSkia()); 192 layout->AddView(close_button, 1, 1, views::GridLayout::TRAILING, 193 views::GridLayout::LEADING); 194 195 layout->AddPaddingRow(0, kHeaderRowSpacing); 196 197 layout->StartRow(0, label_column); 198 status_ = new views::Label(base::string16()); 199 layout->AddView(status_, 200 1, 201 1, 202 views::GridLayout::LEADING, 203 views::GridLayout::CENTER); 204 205 layout->AddPaddingRow(0, kHeaderPaddingBottom); 206} 207 208PopupHeaderView::~PopupHeaderView() { 209} 210 211void PopupHeaderView::SetIdentityName(const base::string16& name) { 212 name_->SetText(name); 213} 214 215void PopupHeaderView::SetIdentityStatus(const base::string16& status, 216 SkColor text_color) { 217 status_->SetText(status); 218 status_->SetEnabledColor(text_color); 219} 220 221//////////////////////////////////////////////////////////////////////////////// 222// InternalPageInfoPopupView 223//////////////////////////////////////////////////////////////////////////////// 224 225InternalPageInfoPopupView::InternalPageInfoPopupView(views::View* anchor_view) 226 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT) { 227 // Compensate for built-in vertical padding in the anchor view's image. 228 set_anchor_view_insets(gfx::Insets(kLocationIconVerticalMargin, 0, 229 kLocationIconVerticalMargin, 0)); 230 231 const int kSpacing = 4; 232 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, kSpacing, 233 kSpacing, kSpacing)); 234 views::ImageView* icon_view = new views::ImageView(); 235 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 236 icon_view->SetImage(rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_26)); 237 AddChildView(icon_view); 238 239 views::Label* label = 240 new views::Label(l10n_util::GetStringUTF16(IDS_PAGE_INFO_INTERNAL_PAGE)); 241 label->SetMultiLine(true); 242 label->SetAllowCharacterBreak(true); 243 label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 244 AddChildView(label); 245 246 views::BubbleDelegateView::CreateBubble(this)->Show(); 247 SizeToContents(); 248} 249 250InternalPageInfoPopupView::~InternalPageInfoPopupView() { 251} 252 253//////////////////////////////////////////////////////////////////////////////// 254// WebsiteSettingsPopupView 255//////////////////////////////////////////////////////////////////////////////// 256 257WebsiteSettingsPopupView::~WebsiteSettingsPopupView() { 258} 259 260// static 261void WebsiteSettingsPopupView::ShowPopup(views::View* anchor_view, 262 Profile* profile, 263 content::WebContents* web_contents, 264 const GURL& url, 265 const content::SSLStatus& ssl, 266 Browser* browser) { 267 if (InternalChromePage(url)) { 268 new InternalPageInfoPopupView(anchor_view); 269 } else { 270 new WebsiteSettingsPopupView(anchor_view, profile, web_contents, url, ssl, 271 browser); 272 } 273} 274 275WebsiteSettingsPopupView::WebsiteSettingsPopupView( 276 views::View* anchor_view, 277 Profile* profile, 278 content::WebContents* web_contents, 279 const GURL& url, 280 const content::SSLStatus& ssl, 281 Browser* browser) 282 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT), 283 web_contents_(web_contents), 284 browser_(browser), 285 header_(NULL), 286 tabbed_pane_(NULL), 287 site_data_content_(NULL), 288 cookie_dialog_link_(NULL), 289 permissions_content_(NULL), 290 connection_tab_(NULL), 291 identity_info_content_(NULL), 292 certificate_dialog_link_(NULL), 293 signed_certificate_timestamps_link_(NULL), 294 cert_id_(0), 295 help_center_link_(NULL), 296 connection_info_content_(NULL), 297 page_info_content_(NULL), 298 weak_factory_(this) { 299 // Compensate for built-in vertical padding in the anchor view's image. 300 set_anchor_view_insets(gfx::Insets(kLocationIconVerticalMargin, 0, 301 kLocationIconVerticalMargin, 0)); 302 303 views::GridLayout* layout = new views::GridLayout(this); 304 SetLayoutManager(layout); 305 const int content_column = 0; 306 views::ColumnSet* column_set = layout->AddColumnSet(content_column); 307 column_set->AddColumn(views::GridLayout::FILL, 308 views::GridLayout::FILL, 309 1, 310 views::GridLayout::USE_PREF, 311 0, 312 0); 313 314 header_ = new PopupHeaderView(this); 315 layout->StartRow(1, content_column); 316 layout->AddView(header_); 317 318 layout->AddPaddingRow(1, kHeaderMarginBottom); 319 tabbed_pane_ = new views::TabbedPane(); 320 layout->StartRow(1, content_column); 321 layout->AddView(tabbed_pane_); 322 // Tabs must be added after the tabbed_pane_ was added to the views 323 // hierachy. Adding the |tabbed_pane_| to the views hierachy triggers the 324 // initialization of the native tab UI element. If the native tab UI 325 // element is not initalized adding a tab will result in a NULL pointer 326 // exception. 327 tabbed_pane_->AddTabAtIndex( 328 TAB_ID_PERMISSIONS, 329 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TAB_LABEL_PERMISSIONS), 330 CreatePermissionsTab()); 331 connection_tab_ = CreateConnectionTab(); 332 tabbed_pane_->AddTabAtIndex( 333 TAB_ID_CONNECTION, 334 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TAB_LABEL_CONNECTION), 335 connection_tab_); 336 DCHECK_EQ(tabbed_pane_->GetTabCount(), NUM_TAB_IDS); 337 tabbed_pane_->set_listener(this); 338 339 set_margins(gfx::Insets(kPopupMarginTop, kPopupMarginLeft, 340 kPopupMarginBottom, kPopupMarginRight)); 341 342 views::BubbleDelegateView::CreateBubble(this)->Show(); 343 SizeToContents(); 344 345 presenter_.reset(new WebsiteSettings( 346 this, profile, 347 TabSpecificContentSettings::FromWebContents(web_contents), 348 InfoBarService::FromWebContents(web_contents), url, ssl, 349 content::CertStore::GetInstance())); 350} 351 352void WebsiteSettingsPopupView::OnPermissionChanged( 353 PermissionSelectorView* permission_selector) { 354 DCHECK(permission_selector); 355 presenter_->OnSitePermissionChanged(permission_selector->type(), 356 permission_selector->current_setting()); 357} 358 359void WebsiteSettingsPopupView::OnWidgetDestroying(views::Widget* widget) { 360 presenter_->OnUIClosing(); 361} 362 363void WebsiteSettingsPopupView::ButtonPressed( 364 views::Button* button, 365 const ui::Event& event) { 366 GetWidget()->Close(); 367} 368 369void WebsiteSettingsPopupView::LinkClicked(views::Link* source, 370 int event_flags) { 371 // The popup closes automatically when the collected cookies dialog or the 372 // certificate viewer opens. So delay handling of the link clicked to avoid 373 // a crash in the base class which needs to complete the mouse event handling. 374 content::BrowserThread::PostTask( 375 content::BrowserThread::UI, FROM_HERE, 376 base::Bind(&WebsiteSettingsPopupView::HandleLinkClickedAsync, 377 weak_factory_.GetWeakPtr(), source)); 378} 379 380void WebsiteSettingsPopupView::TabSelectedAt(int index) { 381 tabbed_pane_->GetSelectedTab()->Layout(); 382 SizeToContents(); 383} 384 385gfx::Size WebsiteSettingsPopupView::GetPreferredSize() { 386 if (header_ == NULL && tabbed_pane_ == NULL) 387 return views::View::GetPreferredSize(); 388 389 int height = 0; 390 if (header_) 391 height += header_->GetPreferredSize().height(); 392 if (tabbed_pane_) 393 height += tabbed_pane_->GetPreferredSize().height(); 394 395 int width = kPermissionsSectionContentMinWidth; 396 if (site_data_content_) 397 width = std::max(width, site_data_content_->GetPreferredSize().width()); 398 if (permissions_content_) 399 width = std::max(width, permissions_content_->GetPreferredSize().width()); 400 width += kPermissionsSectionPaddingLeft; 401 width = std::min(width, kMaxPopupWidth); 402 403 return gfx::Size(width, height); 404} 405 406void WebsiteSettingsPopupView::SetCookieInfo( 407 const CookieInfoList& cookie_info_list) { 408 site_data_content_->RemoveAllChildViews(true); 409 410 views::GridLayout* layout = new views::GridLayout(site_data_content_); 411 site_data_content_->SetLayoutManager(layout); 412 413 const int site_data_content_column = 0; 414 views::ColumnSet* column_set = 415 layout->AddColumnSet(site_data_content_column); 416 column_set->AddColumn(views::GridLayout::FILL, 417 views::GridLayout::FILL, 418 1, 419 views::GridLayout::FIXED, 420 kSiteDataIconColumnWidth, 421 0); 422 column_set->AddPaddingColumn(0, kIconMarginLeft); 423 column_set->AddColumn(views::GridLayout::FILL, 424 views::GridLayout::FILL, 425 1, 426 views::GridLayout::USE_PREF, 427 0, 428 0); 429 430 layout->AddPaddingRow(1, 5); 431 for (CookieInfoList::const_iterator i(cookie_info_list.begin()); 432 i != cookie_info_list.end(); 433 ++i) { 434 base::string16 label_text = l10n_util::GetStringFUTF16( 435 IDS_WEBSITE_SETTINGS_SITE_DATA_STATS_LINE, 436 base::UTF8ToUTF16(i->cookie_source), 437 base::IntToString16(i->allowed), 438 base::IntToString16(i->blocked)); 439 if (i != cookie_info_list.begin()) 440 layout->AddPaddingRow(1, kSiteDataSectionRowSpacing); 441 layout->StartRow(1, site_data_content_column); 442 views::ImageView* icon = new views::ImageView(); 443 const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon( 444 CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_ALLOW); 445 icon->SetImage(image.ToImageSkia()); 446 layout->AddView(icon, 1, 1, views::GridLayout::CENTER, 447 views::GridLayout::CENTER); 448 layout->AddView(new views::Label(label_text), 1, 1, 449 views::GridLayout::LEADING, views::GridLayout::CENTER); 450 } 451 layout->AddPaddingRow(1, 6); 452 453 layout->Layout(site_data_content_); 454 SizeToContents(); 455} 456 457void WebsiteSettingsPopupView::SetPermissionInfo( 458 const PermissionInfoList& permission_info_list) { 459 permissions_content_->RemoveAllChildViews(true); 460 461 views::GridLayout* layout = 462 new views::GridLayout(permissions_content_); 463 permissions_content_->SetLayoutManager(layout); 464 const int content_column = 0; 465 views::ColumnSet* column_set = 466 layout->AddColumnSet(content_column); 467 column_set->AddColumn(views::GridLayout::FILL, 468 views::GridLayout::FILL, 469 1, 470 views::GridLayout::USE_PREF, 471 0, 472 0); 473 for (PermissionInfoList::const_iterator permission = 474 permission_info_list.begin(); 475 permission != permission_info_list.end(); 476 ++permission) { 477 layout->StartRow(1, content_column); 478 PermissionSelectorView* selector = new PermissionSelectorView( 479 web_contents_ ? web_contents_->GetURL() : GURL::EmptyGURL(), 480 permission->type, 481 permission->default_setting, 482 permission->setting, 483 permission->source); 484 selector->AddObserver(this); 485 layout->AddView(selector, 486 1, 487 1, 488 views::GridLayout::LEADING, 489 views::GridLayout::CENTER); 490 layout->AddPaddingRow(1, kPermissionsSectionRowSpacing); 491 } 492 493 SizeToContents(); 494} 495 496void WebsiteSettingsPopupView::SetIdentityInfo( 497 const IdentityInfo& identity_info) { 498 base::string16 identity_status_text; 499 SkColor text_color = SK_ColorBLACK; 500 switch (identity_info.identity_status) { 501 case WebsiteSettings::SITE_IDENTITY_STATUS_CERT: 502 case WebsiteSettings::SITE_IDENTITY_STATUS_EV_CERT: 503 identity_status_text = 504 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_IDENTITY_VERIFIED); 505 text_color = kIdentityVerifiedTextColor; 506 break; 507 case WebsiteSettings::SITE_IDENTITY_STATUS_ADMIN_PROVIDED_CERT: 508 identity_status_text = 509 l10n_util::GetStringUTF16(IDS_CERT_POLICY_PROVIDED_CERT_HEADER); 510 break; 511 default: 512 identity_status_text = 513 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_IDENTITY_NOT_VERIFIED); 514 break; 515 } 516 header_->SetIdentityName(base::UTF8ToUTF16(identity_info.site_identity)); 517 header_->SetIdentityStatus(identity_status_text, text_color); 518 519 // The headline and the certificate dialog link of the site's identity 520 // section is only displayed if the site's identity was verified. If the 521 // site's identity was verified, then the headline contains the organization 522 // name from the provided certificate. If the organization name is not 523 // available than the hostname of the site is used instead. 524 base::string16 headline; 525 if (identity_info.cert_id) { 526 cert_id_ = identity_info.cert_id; 527 signed_certificate_timestamp_ids_.assign( 528 identity_info.signed_certificate_timestamp_ids.begin(), 529 identity_info.signed_certificate_timestamp_ids.end()); 530 531 certificate_dialog_link_ = new views::Link( 532 l10n_util::GetStringUTF16(IDS_PAGEINFO_CERT_INFO_BUTTON)); 533 certificate_dialog_link_->set_listener(this); 534 535 if (!signed_certificate_timestamp_ids_.empty() && 536 CommandLine::ForCurrentProcess()->HasSwitch( 537 switches::kEnableSignedCertificateTimestampsViewer)) { 538 signed_certificate_timestamps_link_ = 539 new views::Link(l10n_util::GetStringUTF16( 540 IDS_PAGEINFO_CERT_TRANSPARENCY_INFO_BUTTON)); 541 signed_certificate_timestamps_link_->set_listener(this); 542 } 543 544 headline = base::UTF8ToUTF16(identity_info.site_identity); 545 } 546 ResetConnectionSection( 547 identity_info_content_, 548 WebsiteSettingsUI::GetIdentityIcon(identity_info.identity_status), 549 base::string16(), // The identity section has no headline. 550 base::UTF8ToUTF16(identity_info.identity_status_description), 551 certificate_dialog_link_, 552 signed_certificate_timestamps_link_); 553 554 ResetConnectionSection( 555 connection_info_content_, 556 WebsiteSettingsUI::GetConnectionIcon(identity_info.connection_status), 557 base::string16(), // The connection section has no headline. 558 base::UTF8ToUTF16(identity_info.connection_status_description), 559 NULL, 560 NULL); 561 562 connection_tab_->InvalidateLayout(); 563 Layout(); 564 SizeToContents(); 565} 566 567void WebsiteSettingsPopupView::SetFirstVisit( 568 const base::string16& first_visit) { 569 ResetConnectionSection( 570 page_info_content_, 571 WebsiteSettingsUI::GetFirstVisitIcon(first_visit), 572 l10n_util::GetStringUTF16(IDS_PAGE_INFO_SITE_INFO_TITLE), 573 first_visit, 574 NULL, 575 NULL); 576 connection_tab_->InvalidateLayout(); 577 Layout(); 578 SizeToContents(); 579} 580 581void WebsiteSettingsPopupView::SetSelectedTab(TabId tab_id) { 582 tabbed_pane_->SelectTabAt(tab_id); 583} 584 585views::View* WebsiteSettingsPopupView::CreatePermissionsTab() { 586 views::View* pane = new views::View(); 587 pane->SetLayoutManager( 588 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1)); 589 // Add cookies and site data section. 590 cookie_dialog_link_ = new views::Link( 591 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_SHOW_SITE_DATA)); 592 cookie_dialog_link_->set_listener(this); 593 site_data_content_ = new views::View(); 594 views::View* site_data_section = 595 CreateSection(l10n_util::GetStringUTF16( 596 IDS_WEBSITE_SETTINGS_TITLE_SITE_DATA), 597 site_data_content_, 598 cookie_dialog_link_); 599 pane->AddChildView(site_data_section); 600 // Add permissions section. 601 permissions_content_ = new views::View(); 602 views::View* permissions_section = 603 CreateSection(l10n_util::GetStringUTF16( 604 IDS_WEBSITE_SETTINGS_TITLE_SITE_PERMISSIONS), 605 permissions_content_, 606 NULL); 607 pane->AddChildView(permissions_section); 608 return pane; 609} 610 611views::View* WebsiteSettingsPopupView::CreateConnectionTab() { 612 views::View* pane = new views::View(); 613 pane->SetLayoutManager( 614 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1)); 615 // Add site identity section. 616 identity_info_content_ = new views::View(); 617 pane->AddChildView(identity_info_content_); 618 619 // Add connection section. 620 pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL)); 621 connection_info_content_ = new views::View(); 622 pane->AddChildView(connection_info_content_); 623 624 // Add page info section. 625 pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL)); 626 page_info_content_ = new views::View(); 627 pane->AddChildView(page_info_content_); 628 629 // Add help center link. 630 pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL)); 631 help_center_link_ = new views::Link( 632 l10n_util::GetStringUTF16(IDS_PAGE_INFO_HELP_CENTER_LINK)); 633 help_center_link_->set_listener(this); 634 views::View* link_section = new views::View(); 635 const int kLinkMarginTop = 4; 636 link_section->SetLayoutManager( 637 new views::BoxLayout(views::BoxLayout::kHorizontal, 638 kConnectionSectionPaddingLeft, 639 kLinkMarginTop, 640 0)); 641 link_section->AddChildView(help_center_link_); 642 pane->AddChildView(link_section); 643 return pane; 644} 645 646views::View* WebsiteSettingsPopupView::CreateSection( 647 const base::string16& headline_text, 648 views::View* content, 649 views::Link* link) { 650 views::View* container = new views::View(); 651 views::GridLayout* layout = new views::GridLayout(container); 652 container->SetLayoutManager(layout); 653 const int content_column = 0; 654 views::ColumnSet* column_set = layout->AddColumnSet(content_column); 655 column_set->AddPaddingColumn(0, kPermissionsSectionPaddingLeft); 656 column_set->AddColumn(views::GridLayout::FILL, 657 views::GridLayout::FILL, 658 1, 659 views::GridLayout::USE_PREF, 660 0, 661 0); 662 663 layout->AddPaddingRow(1, kPermissionsSectionPaddingTop); 664 layout->StartRow(1, content_column); 665 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 666 views::Label* headline = new views::Label( 667 headline_text, rb.GetFontList(ui::ResourceBundle::BoldFont)); 668 layout->AddView(headline, 1, 1, views::GridLayout::LEADING, 669 views::GridLayout::CENTER); 670 671 layout->AddPaddingRow(1, kPermissionsSectionHeadlineMarginBottom); 672 layout->StartRow(1, content_column); 673 layout->AddView(content, 1, 1, views::GridLayout::LEADING, 674 views::GridLayout::CENTER); 675 676 if (link) { 677 layout->AddPaddingRow(1, 4); 678 layout->StartRow(1, content_column); 679 layout->AddView(link, 1, 1, views::GridLayout::LEADING, 680 views::GridLayout::CENTER); 681 } 682 683 layout->AddPaddingRow(1, kPermissionsSectionPaddingBottom); 684 return container; 685} 686 687void WebsiteSettingsPopupView::ResetConnectionSection( 688 views::View* section_container, 689 const gfx::Image& icon, 690 const base::string16& headline, 691 const base::string16& text, 692 views::Link* link, 693 views::Link* secondary_link) { 694 section_container->RemoveAllChildViews(true); 695 696 views::GridLayout* layout = new views::GridLayout(section_container); 697 section_container->SetLayoutManager(layout); 698 views::ColumnSet* column_set = layout->AddColumnSet(0); 699 column_set->AddPaddingColumn(0, kConnectionSectionPaddingLeft); 700 column_set->AddColumn(views::GridLayout::LEADING, 701 views::GridLayout::LEADING, 702 0, 703 views::GridLayout::USE_PREF, 704 0, 705 0); 706 column_set->AddPaddingColumn(0, kIconMarginLeft); 707 column_set->AddColumn(views::GridLayout::FILL, 708 views::GridLayout::FILL, 709 1, 710 views::GridLayout::USE_PREF, 711 0, 712 0); 713 column_set->AddPaddingColumn(0, kConnectionSectionPaddingRight); 714 715 716 layout->AddPaddingRow(0, kConnectionSectionPaddingTop); 717 layout->StartRow(1, 0); 718 719 // Add status icon. 720 views::ImageView* icon_view = new views::ImageView(); 721 icon_view->SetImage(*icon.ToImageSkia()); 722 layout->AddView(icon_view, 1, 1, views::GridLayout::LEADING, 723 views::GridLayout::LEADING); 724 725 // Add section content. 726 views::View* content_pane = new views::View(); 727 views::GridLayout* content_layout = new views::GridLayout(content_pane); 728 content_pane->SetLayoutManager(content_layout); 729 views::ColumnSet* content_column_set = content_layout->AddColumnSet(0); 730 content_column_set->AddColumn(views::GridLayout::LEADING, 731 views::GridLayout::LEADING, 732 1, 733 views::GridLayout::USE_PREF, 734 0, 735 0); 736 if (!headline.empty()) { 737 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 738 views::Label* headline_label = new views::Label( 739 headline, rb.GetFontList(ui::ResourceBundle::BoldFont)); 740 headline_label->SetMultiLine(true); 741 headline_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 742 // Allow linebreaking in the middle of words if necessary, so that extremely 743 // long hostnames (longer than one line) will still be completely shown. 744 headline_label->SetAllowCharacterBreak(true); 745 content_layout->StartRow(1, 0); 746 content_layout->AddView(headline_label); 747 } 748 749 views::Label* description_label = new views::Label(text); 750 description_label->SetMultiLine(true); 751 description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 752 description_label->SetAllowCharacterBreak(true); 753 content_layout->StartRow(1, 0); 754 content_layout->AddView(description_label); 755 756 if (link) { 757 content_layout->StartRow(1, 0); 758 content_layout->AddView(link); 759 } 760 761 if (secondary_link) { 762 content_layout->StartRow(1, 0); 763 content_layout->AddView(secondary_link); 764 } 765 766 layout->AddView(content_pane, 1, 1, views::GridLayout::LEADING, 767 views::GridLayout::LEADING); 768 layout->AddPaddingRow(0, kConnectionSectionPaddingBottom); 769} 770 771// Used to asynchronously handle clicks since these calls may cause the 772// destruction of the settings view and the base class window still 773// needs to be alive to finish handling the mouse click. 774void WebsiteSettingsPopupView::HandleLinkClickedAsync(views::Link* source) { 775 if (source == cookie_dialog_link_) { 776 // Count how often the Collected Cookies dialog is opened. 777 content::RecordAction( 778 base::UserMetricsAction("WebsiteSettings_CookiesDialogOpened")); 779 new CollectedCookiesViews(web_contents_); 780 } else if (source == certificate_dialog_link_) { 781 gfx::NativeWindow parent = 782 GetAnchorView() ? GetAnchorView()->GetWidget()->GetNativeWindow() : 783 NULL; 784 ShowCertificateViewerByID(web_contents_, parent, cert_id_); 785 } else if (source == signed_certificate_timestamps_link_) { 786 chrome::ShowSignedCertificateTimestampsViewer( 787 web_contents_, signed_certificate_timestamp_ids_); 788 } else if (source == help_center_link_) { 789 browser_->OpenURL(content::OpenURLParams( 790 GURL(chrome::kPageInfoHelpCenterURL), 791 content::Referrer(), 792 NEW_FOREGROUND_TAB, 793 content::PAGE_TRANSITION_LINK, 794 false)); 795 } 796} 797