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.
5 #include "chrome/browser/ui/views/website_settings/website_settings_popup_view.h"
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/url_constants.h"
21 #include "chrome/grit/chromium_strings.h"
22 #include "chrome/grit/generated_resources.h"
23 #include "components/content_settings/core/common/content_settings_types.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/theme_resources.h"
28 #include "ui/base/l10n/l10n_util.h"
29 #include "ui/base/models/simple_menu_model.h"
30 #include "ui/base/resource/resource_bundle.h"
31 #include "ui/gfx/canvas.h"
32 #include "ui/gfx/font_list.h"
33 #include "ui/gfx/image/image.h"
34 #include "ui/gfx/insets.h"
35 #include "ui/resources/grit/ui_resources.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"
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
61 bool is_popup_showing = false;
63 // Padding values for sections on the connection tab.
64 const int kConnectionSectionPaddingBottom = 16;
65 const int kConnectionSectionPaddingLeft = 18;
66 const int kConnectionSectionPaddingTop = 16;
67 const int kConnectionSectionPaddingRight = 18;
69 // The text color that is used for the site identity status text, if the site's
70 // identity was sucessfully verified.
71 const SkColor kIdentityVerifiedTextColor = 0xFF298a27;
74 const int kIconMarginLeft = 6;
76 // Margin and padding values for the |PopupHeaderView|.
77 const int kHeaderMarginBottom = 10;
78 const int kHeaderPaddingBottom = 12;
79 const int kHeaderPaddingLeft = 18;
80 const int kHeaderPaddingRight = 8;
81 const int kHeaderPaddingTop = 12;
83 // Spacing between the site identity label and the site identity status text in
85 const int kHeaderRowSpacing = 4;
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.
89 const int kLocationIconVerticalMargin = 5;
91 // The max possible width of the popup.
92 const int kMaxPopupWidth = 500;
94 // The margins between the popup border and the popup content.
95 const int kPopupMarginTop = 4;
96 const int kPopupMarginLeft = 0;
97 const int kPopupMarginBottom = 10;
98 const int kPopupMarginRight = 0;
100 // Padding values for sections on the permissions tab.
101 const int kPermissionsSectionContentMinWidth = 300;
102 const int kPermissionsSectionPaddingBottom = 6;
103 const int kPermissionsSectionPaddingLeft = 18;
104 const int kPermissionsSectionPaddingTop = 16;
106 // Space between the headline and the content of a section on the permissions
108 const 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.
112 const int kPermissionsSectionRowSpacing = 2;
114 const int kSiteDataIconColumnWidth = 20;
115 const int kSiteDataSectionRowSpacing = 11;
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.
122 class PopupHeaderView : public views::View {
124 explicit PopupHeaderView(views::ButtonListener* close_button_listener);
125 ~PopupHeaderView() override;
127 // Sets the name of the site's identity.
128 void SetIdentityName(const base::string16& name);
130 // Sets the |status_text| for the identity check of this site and the
132 void SetIdentityStatus(const base::string16& status_text, SkColor text_color);
135 // The label that displays the name of the site's identity.
137 // The label that displays the status of the identity check for this site.
138 views::Label* status_;
140 DISALLOW_COPY_AND_ASSIGN(PopupHeaderView);
143 // Website Settings are not supported for internal Chrome pages. Instead of the
144 // |WebsiteSettingsPopupView|, the |InternalPageInfoPopupView| is
146 class InternalPageInfoPopupView : public views::BubbleDelegateView {
148 explicit InternalPageInfoPopupView(views::View* anchor_view);
149 ~InternalPageInfoPopupView() override;
151 // views::BubbleDelegateView:
152 void OnWidgetDestroying(views::Widget* widget) override;
155 DISALLOW_COPY_AND_ASSIGN(InternalPageInfoPopupView);
158 ////////////////////////////////////////////////////////////////////////////////
160 ////////////////////////////////////////////////////////////////////////////////
162 PopupHeaderView::PopupHeaderView(views::ButtonListener* close_button_listener)
163 : name_(NULL), status_(NULL) {
164 views::GridLayout* layout = new views::GridLayout(this);
165 SetLayoutManager(layout);
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,
173 views::GridLayout::USE_PREF,
176 column_set->AddPaddingColumn(1, 0);
177 column_set->AddColumn(views::GridLayout::FILL,
178 views::GridLayout::FILL,
180 views::GridLayout::USE_PREF,
183 column_set->AddPaddingColumn(0, kHeaderPaddingRight);
185 layout->AddPaddingRow(0, kHeaderPaddingTop);
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);
204 layout->AddPaddingRow(0, kHeaderRowSpacing);
206 layout->StartRow(0, label_column);
207 status_ = new views::Label(base::string16());
208 layout->AddView(status_,
211 views::GridLayout::LEADING,
212 views::GridLayout::CENTER);
214 layout->AddPaddingRow(0, kHeaderPaddingBottom);
217 PopupHeaderView::~PopupHeaderView() {
220 void PopupHeaderView::SetIdentityName(const base::string16& name) {
221 name_->SetText(name);
224 void PopupHeaderView::SetIdentityStatus(const base::string16& status,
225 SkColor text_color) {
226 status_->SetText(status);
227 status_->SetEnabledColor(text_color);
230 ////////////////////////////////////////////////////////////////////////////////
231 // InternalPageInfoPopupView
232 ////////////////////////////////////////////////////////////////////////////////
234 InternalPageInfoPopupView::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));
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);
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);
255 views::BubbleDelegateView::CreateBubble(this)->Show();
259 InternalPageInfoPopupView::~InternalPageInfoPopupView() {
262 void InternalPageInfoPopupView::OnWidgetDestroying(views::Widget* widget) {
263 is_popup_showing = false;
266 ////////////////////////////////////////////////////////////////////////////////
267 // WebsiteSettingsPopupView
268 ////////////////////////////////////////////////////////////////////////////////
270 WebsiteSettingsPopupView::~WebsiteSettingsPopupView() {
274 void WebsiteSettingsPopupView::ShowPopup(views::View* anchor_view,
276 content::WebContents* web_contents,
278 const content::SSLStatus& ssl,
280 is_popup_showing = true;
281 if (InternalChromePage(url)) {
282 new InternalPageInfoPopupView(anchor_view);
284 new WebsiteSettingsPopupView(anchor_view, profile, web_contents, url, ssl,
290 bool WebsiteSettingsPopupView::IsPopupShowing() {
291 return is_popup_showing;
294 WebsiteSettingsPopupView::WebsiteSettingsPopupView(
295 views::View* anchor_view,
297 content::WebContents* web_contents,
299 const content::SSLStatus& ssl,
301 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT),
302 web_contents_(web_contents),
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 reset_decisions_button_(NULL),
315 help_center_link_(NULL),
316 connection_info_content_(NULL),
317 page_info_content_(NULL),
318 weak_factory_(this) {
319 // Compensate for built-in vertical padding in the anchor view's image.
320 set_anchor_view_insets(gfx::Insets(kLocationIconVerticalMargin, 0,
321 kLocationIconVerticalMargin, 0));
323 views::GridLayout* layout = new views::GridLayout(this);
324 SetLayoutManager(layout);
325 const int content_column = 0;
326 views::ColumnSet* column_set = layout->AddColumnSet(content_column);
327 column_set->AddColumn(views::GridLayout::FILL,
328 views::GridLayout::FILL,
330 views::GridLayout::USE_PREF,
334 header_ = new PopupHeaderView(this);
335 layout->StartRow(1, content_column);
336 layout->AddView(header_);
338 layout->AddPaddingRow(1, kHeaderMarginBottom);
339 tabbed_pane_ = new views::TabbedPane();
340 layout->StartRow(1, content_column);
341 layout->AddView(tabbed_pane_);
342 // Tabs must be added after the tabbed_pane_ was added to the views
343 // hierachy. Adding the |tabbed_pane_| to the views hierachy triggers the
344 // initialization of the native tab UI element. If the native tab UI
345 // element is not initalized adding a tab will result in a NULL pointer
347 tabbed_pane_->AddTabAtIndex(
349 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TAB_LABEL_PERMISSIONS),
350 CreatePermissionsTab());
351 connection_tab_ = CreateConnectionTab();
352 tabbed_pane_->AddTabAtIndex(
354 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TAB_LABEL_CONNECTION),
356 DCHECK_EQ(tabbed_pane_->GetTabCount(), NUM_TAB_IDS);
357 tabbed_pane_->set_listener(this);
359 set_margins(gfx::Insets(kPopupMarginTop, kPopupMarginLeft,
360 kPopupMarginBottom, kPopupMarginRight));
362 views::BubbleDelegateView::CreateBubble(this)->Show();
365 presenter_.reset(new WebsiteSettings(
367 TabSpecificContentSettings::FromWebContents(web_contents),
368 InfoBarService::FromWebContents(web_contents), url, ssl,
369 content::CertStore::GetInstance()));
372 void WebsiteSettingsPopupView::OnPermissionChanged(
373 const WebsiteSettingsUI::PermissionInfo& permission) {
374 presenter_->OnSitePermissionChanged(permission.type, permission.setting);
377 void WebsiteSettingsPopupView::OnWidgetDestroying(views::Widget* widget) {
378 is_popup_showing = false;
379 presenter_->OnUIClosing();
382 void WebsiteSettingsPopupView::ButtonPressed(views::Button* button,
383 const ui::Event& event) {
384 if (button == reset_decisions_button_)
385 presenter_->OnRevokeSSLErrorBypassButtonPressed();
386 GetWidget()->Close();
389 void WebsiteSettingsPopupView::LinkClicked(views::Link* source,
391 if (source == cookie_dialog_link_) {
392 // Count how often the Collected Cookies dialog is opened.
393 presenter_->RecordWebsiteSettingsAction(
394 WebsiteSettings::WEBSITE_SETTINGS_COOKIES_DIALOG_OPENED);
396 new CollectedCookiesViews(web_contents_);
397 } else if (source == certificate_dialog_link_) {
398 gfx::NativeWindow parent = GetAnchorView() ?
399 GetAnchorView()->GetWidget()->GetNativeWindow() : NULL;
400 presenter_->RecordWebsiteSettingsAction(
401 WebsiteSettings::WEBSITE_SETTINGS_CERTIFICATE_DIALOG_OPENED);
402 ShowCertificateViewerByID(web_contents_, parent, cert_id_);
403 } else if (source == signed_certificate_timestamps_link_) {
404 chrome::ShowSignedCertificateTimestampsViewer(
405 web_contents_, signed_certificate_timestamp_ids_);
406 presenter_->RecordWebsiteSettingsAction(
407 WebsiteSettings::WEBSITE_SETTINGS_TRANSPARENCY_VIEWER_OPENED);
408 } else if (source == help_center_link_) {
410 content::OpenURLParams(GURL(chrome::kPageInfoHelpCenterURL),
413 ui::PAGE_TRANSITION_LINK,
415 presenter_->RecordWebsiteSettingsAction(
416 WebsiteSettings::WEBSITE_SETTINGS_CONNECTION_HELP_OPENED);
420 void WebsiteSettingsPopupView::TabSelectedAt(int index) {
422 case TAB_ID_PERMISSIONS:
423 presenter_->RecordWebsiteSettingsAction(
424 WebsiteSettings::WEBSITE_SETTINGS_PERMISSIONS_TAB_SELECTED);
426 case TAB_ID_CONNECTION:
427 // If the Connection tab is selected first, we're still inside the
428 // construction of presenter_. In that case, the action is already logged
429 // by WEBSITE_SETTINGS_CONNECTION_TAB_SHOWN_IMMEDIATELY.
431 presenter_->RecordWebsiteSettingsAction(
432 WebsiteSettings::WEBSITE_SETTINGS_CONNECTION_TAB_SELECTED);
438 tabbed_pane_->GetSelectedTab()->Layout();
442 gfx::Size WebsiteSettingsPopupView::GetPreferredSize() const {
443 if (header_ == NULL && tabbed_pane_ == NULL)
444 return views::View::GetPreferredSize();
448 height += header_->GetPreferredSize().height();
450 height += tabbed_pane_->GetPreferredSize().height();
452 int width = kPermissionsSectionContentMinWidth;
453 if (site_data_content_)
454 width = std::max(width, site_data_content_->GetPreferredSize().width());
455 if (permissions_content_)
456 width = std::max(width, permissions_content_->GetPreferredSize().width());
457 width += kPermissionsSectionPaddingLeft;
458 width = std::min(width, kMaxPopupWidth);
460 return gfx::Size(width, height);
463 void WebsiteSettingsPopupView::SetCookieInfo(
464 const CookieInfoList& cookie_info_list) {
465 site_data_content_->RemoveAllChildViews(true);
467 views::GridLayout* layout = new views::GridLayout(site_data_content_);
468 site_data_content_->SetLayoutManager(layout);
470 const int site_data_content_column = 0;
471 views::ColumnSet* column_set =
472 layout->AddColumnSet(site_data_content_column);
473 column_set->AddColumn(views::GridLayout::FILL,
474 views::GridLayout::FILL,
476 views::GridLayout::FIXED,
477 kSiteDataIconColumnWidth,
479 column_set->AddPaddingColumn(0, kIconMarginLeft);
480 column_set->AddColumn(views::GridLayout::FILL,
481 views::GridLayout::FILL,
483 views::GridLayout::USE_PREF,
487 layout->AddPaddingRow(1, 5);
488 for (CookieInfoList::const_iterator i(cookie_info_list.begin());
489 i != cookie_info_list.end();
491 base::string16 label_text = l10n_util::GetStringFUTF16(
492 IDS_WEBSITE_SETTINGS_SITE_DATA_STATS_LINE,
493 base::UTF8ToUTF16(i->cookie_source),
494 base::IntToString16(i->allowed),
495 base::IntToString16(i->blocked));
496 if (i != cookie_info_list.begin())
497 layout->AddPaddingRow(1, kSiteDataSectionRowSpacing);
498 layout->StartRow(1, site_data_content_column);
499 WebsiteSettingsUI::PermissionInfo info;
500 info.type = CONTENT_SETTINGS_TYPE_COOKIES;
501 info.setting = CONTENT_SETTING_ALLOW;
502 views::ImageView* icon = new views::ImageView();
503 const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon(info);
504 icon->SetImage(image.ToImageSkia());
505 layout->AddView(icon, 1, 1, views::GridLayout::CENTER,
506 views::GridLayout::CENTER);
507 layout->AddView(new views::Label(label_text), 1, 1,
508 views::GridLayout::LEADING, views::GridLayout::CENTER);
510 layout->AddPaddingRow(1, 6);
512 layout->Layout(site_data_content_);
516 void WebsiteSettingsPopupView::SetPermissionInfo(
517 const PermissionInfoList& permission_info_list) {
518 permissions_content_->RemoveAllChildViews(true);
520 views::GridLayout* layout =
521 new views::GridLayout(permissions_content_);
522 permissions_content_->SetLayoutManager(layout);
523 const int content_column = 0;
524 views::ColumnSet* column_set =
525 layout->AddColumnSet(content_column);
526 column_set->AddColumn(views::GridLayout::FILL,
527 views::GridLayout::FILL,
529 views::GridLayout::USE_PREF,
532 for (PermissionInfoList::const_iterator permission =
533 permission_info_list.begin();
534 permission != permission_info_list.end();
536 layout->StartRow(1, content_column);
537 PermissionSelectorView* selector = new PermissionSelectorView(
538 web_contents_ ? web_contents_->GetURL() : GURL::EmptyGURL(),
540 selector->AddObserver(this);
541 layout->AddView(selector,
544 views::GridLayout::LEADING,
545 views::GridLayout::CENTER);
546 layout->AddPaddingRow(1, kPermissionsSectionRowSpacing);
552 void WebsiteSettingsPopupView::SetIdentityInfo(
553 const IdentityInfo& identity_info) {
554 base::string16 identity_status_text;
555 SkColor text_color = SK_ColorBLACK;
556 switch (identity_info.identity_status) {
557 case WebsiteSettings::SITE_IDENTITY_STATUS_CERT:
558 case WebsiteSettings::SITE_IDENTITY_STATUS_EV_CERT:
559 identity_status_text =
560 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_IDENTITY_VERIFIED);
561 text_color = kIdentityVerifiedTextColor;
563 case WebsiteSettings::SITE_IDENTITY_STATUS_ADMIN_PROVIDED_CERT:
564 identity_status_text =
565 l10n_util::GetStringUTF16(IDS_CERT_POLICY_PROVIDED_CERT_HEADER);
568 identity_status_text =
569 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_IDENTITY_NOT_VERIFIED);
572 header_->SetIdentityName(base::UTF8ToUTF16(identity_info.site_identity));
573 header_->SetIdentityStatus(identity_status_text, text_color);
575 // The headline and the certificate dialog link of the site's identity
576 // section is only displayed if the site's identity was verified. If the
577 // site's identity was verified, then the headline contains the organization
578 // name from the provided certificate. If the organization name is not
579 // available than the hostname of the site is used instead.
580 base::string16 headline;
581 if (identity_info.cert_id) {
582 cert_id_ = identity_info.cert_id;
583 signed_certificate_timestamp_ids_.assign(
584 identity_info.signed_certificate_timestamp_ids.begin(),
585 identity_info.signed_certificate_timestamp_ids.end());
587 certificate_dialog_link_ = new views::Link(
588 l10n_util::GetStringUTF16(IDS_PAGEINFO_CERT_INFO_BUTTON));
589 certificate_dialog_link_->set_listener(this);
591 if (!signed_certificate_timestamp_ids_.empty()) {
592 signed_certificate_timestamps_link_ =
593 new views::Link(l10n_util::GetStringUTF16(
594 IDS_PAGEINFO_CERT_TRANSPARENCY_INFO_BUTTON));
595 signed_certificate_timestamps_link_->set_listener(this);
598 if (identity_info.show_ssl_decision_revoke_button) {
599 reset_decisions_button_ = new views::LabelButton(
601 l10n_util::GetStringUTF16(
602 IDS_PAGEINFO_RESET_INVALID_CERTIFICATE_DECISIONS_BUTTON));
603 reset_decisions_button_->SetStyle(views::Button::STYLE_BUTTON);
606 headline = base::UTF8ToUTF16(identity_info.site_identity);
608 ResetConnectionSection(
609 identity_info_content_,
610 WebsiteSettingsUI::GetIdentityIcon(identity_info.identity_status),
611 base::string16(), // The identity section has no headline.
612 base::UTF8ToUTF16(identity_info.identity_status_description),
613 certificate_dialog_link_,
614 signed_certificate_timestamps_link_,
615 reset_decisions_button_);
617 ResetConnectionSection(
618 connection_info_content_,
619 WebsiteSettingsUI::GetConnectionIcon(identity_info.connection_status),
620 base::string16(), // The connection section has no headline.
621 base::UTF8ToUTF16(identity_info.connection_status_description),
626 connection_tab_->InvalidateLayout();
631 void WebsiteSettingsPopupView::SetFirstVisit(
632 const base::string16& first_visit) {
633 ResetConnectionSection(
635 WebsiteSettingsUI::GetFirstVisitIcon(first_visit),
636 l10n_util::GetStringUTF16(IDS_PAGE_INFO_SITE_INFO_TITLE),
641 connection_tab_->InvalidateLayout();
646 void WebsiteSettingsPopupView::SetSelectedTab(TabId tab_id) {
647 tabbed_pane_->SelectTabAt(tab_id);
650 views::View* WebsiteSettingsPopupView::CreatePermissionsTab() {
651 views::View* pane = new views::View();
652 pane->SetLayoutManager(
653 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
654 // Add cookies and site data section.
655 cookie_dialog_link_ = new views::Link(
656 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_SHOW_SITE_DATA));
657 cookie_dialog_link_->set_listener(this);
658 site_data_content_ = new views::View();
659 views::View* site_data_section =
660 CreateSection(l10n_util::GetStringUTF16(
661 IDS_WEBSITE_SETTINGS_TITLE_SITE_DATA),
663 cookie_dialog_link_);
664 pane->AddChildView(site_data_section);
665 // Add permissions section.
666 permissions_content_ = new views::View();
667 views::View* permissions_section =
668 CreateSection(l10n_util::GetStringUTF16(
669 IDS_WEBSITE_SETTINGS_TITLE_SITE_PERMISSIONS),
670 permissions_content_,
672 pane->AddChildView(permissions_section);
676 views::View* WebsiteSettingsPopupView::CreateConnectionTab() {
677 views::View* pane = new views::View();
678 pane->SetLayoutManager(
679 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
680 // Add site identity section.
681 identity_info_content_ = new views::View();
682 pane->AddChildView(identity_info_content_);
684 // Add connection section.
685 pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL));
686 connection_info_content_ = new views::View();
687 pane->AddChildView(connection_info_content_);
689 // Add page info section.
690 pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL));
691 page_info_content_ = new views::View();
692 pane->AddChildView(page_info_content_);
694 // Add help center link.
695 pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL));
696 help_center_link_ = new views::Link(
697 l10n_util::GetStringUTF16(IDS_PAGE_INFO_HELP_CENTER_LINK));
698 help_center_link_->set_listener(this);
699 views::View* link_section = new views::View();
700 const int kLinkMarginTop = 4;
701 link_section->SetLayoutManager(
702 new views::BoxLayout(views::BoxLayout::kHorizontal,
703 kConnectionSectionPaddingLeft,
706 link_section->AddChildView(help_center_link_);
707 pane->AddChildView(link_section);
711 views::View* WebsiteSettingsPopupView::CreateSection(
712 const base::string16& headline_text,
713 views::View* content,
715 views::View* container = new views::View();
716 views::GridLayout* layout = new views::GridLayout(container);
717 container->SetLayoutManager(layout);
718 const int content_column = 0;
719 views::ColumnSet* column_set = layout->AddColumnSet(content_column);
720 column_set->AddPaddingColumn(0, kPermissionsSectionPaddingLeft);
721 column_set->AddColumn(views::GridLayout::FILL,
722 views::GridLayout::FILL,
724 views::GridLayout::USE_PREF,
728 layout->AddPaddingRow(1, kPermissionsSectionPaddingTop);
729 layout->StartRow(1, content_column);
730 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
731 views::Label* headline = new views::Label(
732 headline_text, rb.GetFontList(ui::ResourceBundle::BoldFont));
733 layout->AddView(headline, 1, 1, views::GridLayout::LEADING,
734 views::GridLayout::CENTER);
736 layout->AddPaddingRow(1, kPermissionsSectionHeadlineMarginBottom);
737 layout->StartRow(1, content_column);
738 layout->AddView(content, 1, 1, views::GridLayout::LEADING,
739 views::GridLayout::CENTER);
742 layout->AddPaddingRow(1, 4);
743 layout->StartRow(1, content_column);
744 layout->AddView(link, 1, 1, views::GridLayout::LEADING,
745 views::GridLayout::CENTER);
748 layout->AddPaddingRow(1, kPermissionsSectionPaddingBottom);
752 void WebsiteSettingsPopupView::ResetConnectionSection(
753 views::View* section_container,
754 const gfx::Image& icon,
755 const base::string16& headline,
756 const base::string16& text,
758 views::Link* secondary_link,
759 views::LabelButton* reset_decisions_button) {
760 section_container->RemoveAllChildViews(true);
762 views::GridLayout* layout = new views::GridLayout(section_container);
763 section_container->SetLayoutManager(layout);
764 views::ColumnSet* column_set = layout->AddColumnSet(0);
765 column_set->AddPaddingColumn(0, kConnectionSectionPaddingLeft);
766 column_set->AddColumn(views::GridLayout::LEADING,
767 views::GridLayout::LEADING,
769 views::GridLayout::USE_PREF,
772 column_set->AddPaddingColumn(0, kIconMarginLeft);
773 column_set->AddColumn(views::GridLayout::FILL,
774 views::GridLayout::FILL,
776 views::GridLayout::USE_PREF,
779 column_set->AddPaddingColumn(0, kConnectionSectionPaddingRight);
782 layout->AddPaddingRow(0, kConnectionSectionPaddingTop);
783 layout->StartRow(1, 0);
786 views::ImageView* icon_view = new views::ImageView();
787 icon_view->SetImage(*icon.ToImageSkia());
788 layout->AddView(icon_view, 1, 1, views::GridLayout::LEADING,
789 views::GridLayout::LEADING);
791 // Add section content.
792 views::View* content_pane = new views::View();
793 views::GridLayout* content_layout = new views::GridLayout(content_pane);
794 content_pane->SetLayoutManager(content_layout);
795 views::ColumnSet* content_column_set = content_layout->AddColumnSet(0);
796 content_column_set->AddColumn(views::GridLayout::LEADING,
797 views::GridLayout::LEADING,
799 views::GridLayout::USE_PREF,
802 if (!headline.empty()) {
803 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
804 views::Label* headline_label = new views::Label(
805 headline, rb.GetFontList(ui::ResourceBundle::BoldFont));
806 headline_label->SetMultiLine(true);
807 headline_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
808 // Allow linebreaking in the middle of words if necessary, so that extremely
809 // long hostnames (longer than one line) will still be completely shown.
810 headline_label->SetAllowCharacterBreak(true);
811 content_layout->StartRow(1, 0);
812 content_layout->AddView(headline_label);
815 views::Label* description_label = new views::Label(text);
816 description_label->SetMultiLine(true);
817 description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
818 description_label->SetAllowCharacterBreak(true);
819 content_layout->StartRow(1, 0);
820 content_layout->AddView(description_label);
823 content_layout->StartRow(1, 0);
824 content_layout->AddView(link);
827 if (secondary_link) {
828 content_layout->StartRow(1, 0);
829 content_layout->AddView(secondary_link);
832 if (reset_decisions_button) {
833 content_layout->StartRow(1, 0);
834 content_layout->AddView(reset_decisions_button);
837 layout->AddView(content_pane, 1, 1, views::GridLayout::LEADING,
838 views::GridLayout::LEADING);
839 layout->AddPaddingRow(0, kConnectionSectionPaddingBottom);