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