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