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