[Extensions] Make extension message bubble factory platform-abstract
[chromium-blink-merge.git] / chrome / browser / ui / views / website_settings / website_settings_popup_view.cc
blob9ae1a94efd03445ba24d5be8900c551172b034e9
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"
7 #include <algorithm>
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/geometry/insets.h"
34 #include "ui/gfx/image/image.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"
51 #include "url/gurl.h"
53 namespace {
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.
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;
73 // Left icon margin.
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
84 // the popup header.
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
107 // tab.
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;
117 } // namespace
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 {
123 public:
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
131 // |text_color|.
132 void SetIdentityStatus(const base::string16& status_text, SkColor text_color);
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_;
140 DISALLOW_COPY_AND_ASSIGN(PopupHeaderView);
143 // Website Settings are not supported for internal Chrome pages. Instead of the
144 // |WebsiteSettingsPopupView|, the |InternalPageInfoPopupView| is
145 // displayed.
146 class InternalPageInfoPopupView : public views::BubbleDelegateView {
147 public:
148 explicit InternalPageInfoPopupView(views::View* anchor_view);
149 ~InternalPageInfoPopupView() override;
151 // views::BubbleDelegateView:
152 void OnWidgetDestroying(views::Widget* widget) override;
154 private:
155 DISALLOW_COPY_AND_ASSIGN(InternalPageInfoPopupView);
158 ////////////////////////////////////////////////////////////////////////////////
159 // Popup Header
160 ////////////////////////////////////////////////////////////////////////////////
162 PopupHeaderView::PopupHeaderView(views::ButtonListener* close_button_listener)
163 : name_(nullptr), status_(nullptr) {
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(1, label_column);
207 status_ = new views::Label(base::string16());
208 status_->SetMultiLine(true);
209 status_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
210 layout->AddView(status_,
213 views::GridLayout::LEADING,
214 views::GridLayout::LEADING);
216 layout->AddPaddingRow(1, kHeaderPaddingBottom);
219 PopupHeaderView::~PopupHeaderView() {
222 void PopupHeaderView::SetIdentityName(const base::string16& name) {
223 name_->SetText(name);
226 void PopupHeaderView::SetIdentityStatus(const base::string16& status,
227 SkColor text_color) {
228 status_->SetText(status);
229 status_->SetEnabledColor(text_color);
232 ////////////////////////////////////////////////////////////////////////////////
233 // InternalPageInfoPopupView
234 ////////////////////////////////////////////////////////////////////////////////
236 InternalPageInfoPopupView::InternalPageInfoPopupView(views::View* anchor_view)
237 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT) {
238 // Compensate for built-in vertical padding in the anchor view's image.
239 set_anchor_view_insets(gfx::Insets(kLocationIconVerticalMargin, 0,
240 kLocationIconVerticalMargin, 0));
242 const int kSpacing = 4;
243 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, kSpacing,
244 kSpacing, kSpacing));
245 views::ImageView* icon_view = new views::ImageView();
246 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
247 icon_view->SetImage(rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_26));
248 AddChildView(icon_view);
250 views::Label* label =
251 new views::Label(l10n_util::GetStringUTF16(IDS_PAGE_INFO_INTERNAL_PAGE));
252 label->SetMultiLine(true);
253 label->SetAllowCharacterBreak(true);
254 label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
255 AddChildView(label);
257 views::BubbleDelegateView::CreateBubble(this)->Show();
258 SizeToContents();
261 InternalPageInfoPopupView::~InternalPageInfoPopupView() {
264 void InternalPageInfoPopupView::OnWidgetDestroying(views::Widget* widget) {
265 is_popup_showing = false;
268 ////////////////////////////////////////////////////////////////////////////////
269 // WebsiteSettingsPopupView
270 ////////////////////////////////////////////////////////////////////////////////
272 WebsiteSettingsPopupView::~WebsiteSettingsPopupView() {
275 // static
276 void WebsiteSettingsPopupView::ShowPopup(views::View* anchor_view,
277 Profile* profile,
278 content::WebContents* web_contents,
279 const GURL& url,
280 const content::SSLStatus& ssl,
281 Browser* browser) {
282 is_popup_showing = true;
283 if (InternalChromePage(url)) {
284 new InternalPageInfoPopupView(anchor_view);
285 } else {
286 new WebsiteSettingsPopupView(anchor_view, profile, web_contents, url, ssl,
287 browser);
291 // static
292 bool WebsiteSettingsPopupView::IsPopupShowing() {
293 return is_popup_showing;
296 WebsiteSettingsPopupView::WebsiteSettingsPopupView(
297 views::View* anchor_view,
298 Profile* profile,
299 content::WebContents* web_contents,
300 const GURL& url,
301 const content::SSLStatus& ssl,
302 Browser* browser)
303 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT),
304 web_contents_(web_contents),
305 browser_(browser),
306 header_(nullptr),
307 tabbed_pane_(nullptr),
308 permissions_tab_(nullptr),
309 site_data_content_(nullptr),
310 cookie_dialog_link_(nullptr),
311 permissions_content_(nullptr),
312 connection_tab_(nullptr),
313 identity_info_content_(nullptr),
314 certificate_dialog_link_(nullptr),
315 signed_certificate_timestamps_link_(nullptr),
316 reset_decisions_button_(nullptr),
317 cert_id_(0),
318 help_center_link_(nullptr),
319 connection_info_content_(nullptr),
320 page_info_content_(nullptr),
321 weak_factory_(this) {
322 // Compensate for built-in vertical padding in the anchor view's image.
323 set_anchor_view_insets(gfx::Insets(kLocationIconVerticalMargin, 0,
324 kLocationIconVerticalMargin, 0));
326 views::GridLayout* layout = new views::GridLayout(this);
327 SetLayoutManager(layout);
328 const int content_column = 0;
329 views::ColumnSet* column_set = layout->AddColumnSet(content_column);
330 column_set->AddColumn(views::GridLayout::FILL,
331 views::GridLayout::FILL,
333 views::GridLayout::USE_PREF,
337 header_ = new PopupHeaderView(this);
338 layout->StartRow(1, content_column);
339 layout->AddView(header_);
341 layout->AddPaddingRow(1, kHeaderMarginBottom);
342 tabbed_pane_ = new views::TabbedPane();
343 layout->StartRow(1, content_column);
344 layout->AddView(tabbed_pane_);
346 // Tabs must be added after the tabbed_pane_ was added to the views hierarchy.
347 // Adding the |tabbed_pane_| to the views hierarchy triggers the
348 // initialization of the native tab UI element. If the native tab UI element
349 // is not initalized, adding a tab will result in a NULL pointer exception.
350 permissions_tab_ = CreatePermissionsTab();
351 tabbed_pane_->AddTabAtIndex(
352 TAB_ID_PERMISSIONS,
353 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TAB_LABEL_PERMISSIONS),
354 permissions_tab_);
355 connection_tab_ = CreateConnectionTab();
356 tabbed_pane_->AddTabAtIndex(
357 TAB_ID_CONNECTION,
358 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TAB_LABEL_CONNECTION),
359 connection_tab_);
360 DCHECK_EQ(tabbed_pane_->GetTabCount(), NUM_TAB_IDS);
361 tabbed_pane_->set_listener(this);
363 set_margins(gfx::Insets(kPopupMarginTop, kPopupMarginLeft,
364 kPopupMarginBottom, kPopupMarginRight));
366 views::BubbleDelegateView::CreateBubble(this)->Show();
367 SizeToContents();
369 presenter_.reset(new WebsiteSettings(
370 this, profile,
371 TabSpecificContentSettings::FromWebContents(web_contents),
372 InfoBarService::FromWebContents(web_contents), url, ssl,
373 content::CertStore::GetInstance()));
376 void WebsiteSettingsPopupView::OnPermissionChanged(
377 const WebsiteSettingsUI::PermissionInfo& permission) {
378 presenter_->OnSitePermissionChanged(permission.type, permission.setting);
381 void WebsiteSettingsPopupView::OnWidgetDestroying(views::Widget* widget) {
382 is_popup_showing = false;
383 presenter_->OnUIClosing();
386 void WebsiteSettingsPopupView::ButtonPressed(views::Button* button,
387 const ui::Event& event) {
388 if (button == reset_decisions_button_)
389 presenter_->OnRevokeSSLErrorBypassButtonPressed();
390 GetWidget()->Close();
393 void WebsiteSettingsPopupView::LinkClicked(views::Link* source,
394 int event_flags) {
395 // The popup closes automatically when the collected cookies dialog or the
396 // certificate viewer opens. So delay handling of the link clicked to avoid
397 // a crash in the base class which needs to complete the mouse event handling.
398 content::BrowserThread::PostTask(
399 content::BrowserThread::UI, FROM_HERE,
400 base::Bind(&WebsiteSettingsPopupView::HandleLinkClickedAsync,
401 weak_factory_.GetWeakPtr(), source));
404 void WebsiteSettingsPopupView::TabSelectedAt(int index) {
405 switch (index) {
406 case TAB_ID_PERMISSIONS:
407 presenter_->RecordWebsiteSettingsAction(
408 WebsiteSettings::WEBSITE_SETTINGS_PERMISSIONS_TAB_SELECTED);
409 break;
410 case TAB_ID_CONNECTION:
411 // If the Connection tab is selected first, we're still inside the
412 // construction of presenter_. In that case, the action is already logged
413 // by WEBSITE_SETTINGS_CONNECTION_TAB_SHOWN_IMMEDIATELY.
414 if (presenter_) {
415 presenter_->RecordWebsiteSettingsAction(
416 WebsiteSettings::WEBSITE_SETTINGS_CONNECTION_TAB_SELECTED);
418 break;
419 default:
420 NOTREACHED();
422 tabbed_pane_->GetSelectedTab()->Layout();
423 SizeToContents();
426 gfx::Size WebsiteSettingsPopupView::GetPreferredSize() const {
427 if (header_ == nullptr && tabbed_pane_ == nullptr)
428 return views::View::GetPreferredSize();
430 int height = 0;
431 if (header_)
432 height += header_->GetPreferredSize().height();
433 if (tabbed_pane_)
434 height += tabbed_pane_->GetPreferredSize().height();
436 int width = kPermissionsSectionContentMinWidth;
437 if (site_data_content_)
438 width = std::max(width, site_data_content_->GetPreferredSize().width());
439 if (permissions_content_)
440 width = std::max(width, permissions_content_->GetPreferredSize().width());
441 width += kPermissionsSectionPaddingLeft;
442 width = std::min(width, kMaxPopupWidth);
444 return gfx::Size(width, height);
447 void WebsiteSettingsPopupView::SetCookieInfo(
448 const CookieInfoList& cookie_info_list) {
449 site_data_content_->RemoveAllChildViews(true);
451 views::GridLayout* layout = new views::GridLayout(site_data_content_);
452 site_data_content_->SetLayoutManager(layout);
454 const int site_data_content_column = 0;
455 views::ColumnSet* column_set =
456 layout->AddColumnSet(site_data_content_column);
457 column_set->AddColumn(views::GridLayout::FILL,
458 views::GridLayout::FILL,
460 views::GridLayout::FIXED,
461 kSiteDataIconColumnWidth,
463 column_set->AddPaddingColumn(0, kIconMarginLeft);
464 column_set->AddColumn(views::GridLayout::FILL,
465 views::GridLayout::FILL,
467 views::GridLayout::USE_PREF,
471 layout->AddPaddingRow(1, 5);
472 for (CookieInfoList::const_iterator i(cookie_info_list.begin());
473 i != cookie_info_list.end();
474 ++i) {
475 base::string16 label_text = l10n_util::GetStringFUTF16(
476 IDS_WEBSITE_SETTINGS_SITE_DATA_STATS_LINE,
477 base::UTF8ToUTF16(i->cookie_source),
478 base::IntToString16(i->allowed),
479 base::IntToString16(i->blocked));
480 if (i != cookie_info_list.begin())
481 layout->AddPaddingRow(1, kSiteDataSectionRowSpacing);
482 layout->StartRow(1, site_data_content_column);
483 WebsiteSettingsUI::PermissionInfo info;
484 info.type = CONTENT_SETTINGS_TYPE_COOKIES;
485 info.setting = CONTENT_SETTING_ALLOW;
486 views::ImageView* icon = new views::ImageView();
487 const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon(info);
488 icon->SetImage(image.ToImageSkia());
489 layout->AddView(icon, 1, 1, views::GridLayout::CENTER,
490 views::GridLayout::CENTER);
491 layout->AddView(new views::Label(label_text), 1, 1,
492 views::GridLayout::LEADING, views::GridLayout::CENTER);
494 layout->AddPaddingRow(1, 6);
496 layout->Layout(site_data_content_);
497 SizeToContents();
500 void WebsiteSettingsPopupView::SetPermissionInfo(
501 const PermissionInfoList& permission_info_list) {
502 permissions_content_ = new views::View();
503 views::GridLayout* layout = new views::GridLayout(permissions_content_);
504 permissions_content_->SetLayoutManager(layout);
506 base::string16 headline =
507 permission_info_list.empty()
508 ? base::string16()
509 : l10n_util::GetStringUTF16(
510 IDS_WEBSITE_SETTINGS_TITLE_SITE_PERMISSIONS);
511 views::View* permissions_section =
512 CreateSection(headline, permissions_content_, nullptr);
513 permissions_tab_->AddChildView(permissions_section);
515 const int content_column = 0;
516 views::ColumnSet* column_set = layout->AddColumnSet(content_column);
517 column_set->AddColumn(views::GridLayout::FILL,
518 views::GridLayout::FILL,
520 views::GridLayout::USE_PREF,
523 for (PermissionInfoList::const_iterator permission =
524 permission_info_list.begin();
525 permission != permission_info_list.end();
526 ++permission) {
527 layout->StartRow(1, content_column);
528 PermissionSelectorView* selector = new PermissionSelectorView(
529 web_contents_ ? web_contents_->GetURL() : GURL::EmptyGURL(),
530 *permission);
531 selector->AddObserver(this);
532 layout->AddView(selector,
535 views::GridLayout::LEADING,
536 views::GridLayout::CENTER);
537 layout->AddPaddingRow(1, kPermissionsSectionRowSpacing);
540 layout->Layout(permissions_content_);
542 // Add site settings link.
543 site_settings_link_ = new views::Link(
544 l10n_util::GetStringUTF16(IDS_PAGE_INFO_SITE_SETTINGS_LINK));
545 site_settings_link_->set_listener(this);
546 views::View* link_section = new views::View();
547 const int kLinkMarginTop = 4;
548 link_section->SetLayoutManager(
549 new views::BoxLayout(views::BoxLayout::kHorizontal,
550 kConnectionSectionPaddingLeft, kLinkMarginTop, 0));
551 link_section->AddChildView(site_settings_link_);
552 permissions_tab_->AddChildView(link_section);
554 SizeToContents();
557 void WebsiteSettingsPopupView::SetIdentityInfo(
558 const IdentityInfo& identity_info) {
559 base::string16 identity_status_text = identity_info.GetIdentityStatusText();
560 SkColor text_color = SK_ColorBLACK;
561 if (identity_info.identity_status ==
562 WebsiteSettings::SITE_IDENTITY_STATUS_CERT ||
563 identity_info.identity_status ==
564 WebsiteSettings::SITE_IDENTITY_STATUS_EV_CERT) {
565 text_color = kIdentityVerifiedTextColor;
567 header_->SetIdentityName(base::UTF8ToUTF16(identity_info.site_identity));
568 header_->SetIdentityStatus(identity_status_text, text_color);
570 // The headline and the certificate dialog link of the site's identity
571 // section is only displayed if the site's identity was verified. If the
572 // site's identity was verified, then the headline contains the organization
573 // name from the provided certificate. If the organization name is not
574 // available than the hostname of the site is used instead.
575 base::string16 headline;
576 if (identity_info.cert_id) {
577 cert_id_ = identity_info.cert_id;
578 signed_certificate_timestamp_ids_.assign(
579 identity_info.signed_certificate_timestamp_ids.begin(),
580 identity_info.signed_certificate_timestamp_ids.end());
582 certificate_dialog_link_ = new views::Link(
583 l10n_util::GetStringUTF16(IDS_PAGEINFO_CERT_INFO_BUTTON));
584 certificate_dialog_link_->set_listener(this);
586 if (!signed_certificate_timestamp_ids_.empty()) {
587 signed_certificate_timestamps_link_ =
588 new views::Link(l10n_util::GetStringUTF16(
589 IDS_PAGEINFO_CERT_TRANSPARENCY_INFO_BUTTON));
590 signed_certificate_timestamps_link_->set_listener(this);
593 if (identity_info.show_ssl_decision_revoke_button) {
594 reset_decisions_button_ = new views::LabelButton(
595 this,
596 l10n_util::GetStringUTF16(
597 IDS_PAGEINFO_RESET_INVALID_CERTIFICATE_DECISIONS_BUTTON));
598 reset_decisions_button_->SetStyle(views::Button::STYLE_BUTTON);
601 headline = base::UTF8ToUTF16(identity_info.site_identity);
603 ResetConnectionSection(
604 identity_info_content_,
605 WebsiteSettingsUI::GetIdentityIcon(identity_info.identity_status),
606 base::string16(), // The identity section has no headline.
607 base::UTF8ToUTF16(identity_info.identity_status_description),
608 certificate_dialog_link_,
609 signed_certificate_timestamps_link_,
610 reset_decisions_button_);
612 ResetConnectionSection(
613 connection_info_content_,
614 WebsiteSettingsUI::GetConnectionIcon(identity_info.connection_status),
615 base::string16(), // The connection section has no headline.
616 base::UTF8ToUTF16(identity_info.connection_status_description),
617 nullptr,
618 nullptr,
619 nullptr);
621 connection_tab_->InvalidateLayout();
622 Layout();
623 SizeToContents();
626 void WebsiteSettingsPopupView::SetFirstVisit(
627 const base::string16& first_visit) {
628 ResetConnectionSection(
629 page_info_content_,
630 WebsiteSettingsUI::GetFirstVisitIcon(first_visit),
631 l10n_util::GetStringUTF16(IDS_PAGE_INFO_SITE_INFO_TITLE),
632 first_visit,
633 nullptr,
634 nullptr,
635 nullptr);
636 connection_tab_->InvalidateLayout();
637 Layout();
638 SizeToContents();
641 void WebsiteSettingsPopupView::SetSelectedTab(TabId tab_id) {
642 tabbed_pane_->SelectTabAt(tab_id);
645 views::View* WebsiteSettingsPopupView::CreatePermissionsTab() {
646 views::View* pane = new views::View();
647 pane->SetLayoutManager(
648 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
650 // Add cookies and site data section.
651 cookie_dialog_link_ = new views::Link(
652 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_SHOW_SITE_DATA));
653 cookie_dialog_link_->set_listener(this);
654 site_data_content_ = new views::View();
655 views::View* site_data_section =
656 CreateSection(l10n_util::GetStringUTF16(
657 IDS_WEBSITE_SETTINGS_TITLE_SITE_DATA),
658 site_data_content_,
659 cookie_dialog_link_);
660 pane->AddChildView(site_data_section);
662 return pane;
665 views::View* WebsiteSettingsPopupView::CreateConnectionTab() {
666 views::View* pane = new views::View();
667 pane->SetLayoutManager(
668 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
669 // Add site identity section.
670 identity_info_content_ = new views::View();
671 pane->AddChildView(identity_info_content_);
673 // Add connection section.
674 pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL));
675 connection_info_content_ = new views::View();
676 pane->AddChildView(connection_info_content_);
678 // Add page info section.
679 pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL));
680 page_info_content_ = new views::View();
681 pane->AddChildView(page_info_content_);
683 // Add help center link.
684 pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL));
685 help_center_link_ = new views::Link(
686 l10n_util::GetStringUTF16(IDS_PAGE_INFO_HELP_CENTER_LINK));
687 help_center_link_->set_listener(this);
688 views::View* link_section = new views::View();
689 const int kLinkMarginTop = 4;
690 link_section->SetLayoutManager(
691 new views::BoxLayout(views::BoxLayout::kHorizontal,
692 kConnectionSectionPaddingLeft,
693 kLinkMarginTop,
694 0));
695 link_section->AddChildView(help_center_link_);
696 pane->AddChildView(link_section);
697 return pane;
700 views::View* WebsiteSettingsPopupView::CreateSection(
701 const base::string16& headline_text,
702 views::View* content,
703 views::Link* link) {
704 views::View* container = new views::View();
705 views::GridLayout* layout = new views::GridLayout(container);
706 container->SetLayoutManager(layout);
707 const int content_column = 0;
708 views::ColumnSet* column_set = layout->AddColumnSet(content_column);
709 column_set->AddPaddingColumn(0, kPermissionsSectionPaddingLeft);
710 column_set->AddColumn(views::GridLayout::FILL,
711 views::GridLayout::FILL,
713 views::GridLayout::USE_PREF,
717 if (headline_text.length() > 0) {
718 layout->AddPaddingRow(1, kPermissionsSectionPaddingTop);
719 layout->StartRow(1, content_column);
720 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
721 views::Label* headline = new views::Label(
722 headline_text, rb.GetFontList(ui::ResourceBundle::BoldFont));
723 layout->AddView(headline, 1, 1, views::GridLayout::LEADING,
724 views::GridLayout::CENTER);
727 layout->AddPaddingRow(1, kPermissionsSectionHeadlineMarginBottom);
728 layout->StartRow(1, content_column);
729 layout->AddView(content, 1, 1, views::GridLayout::LEADING,
730 views::GridLayout::CENTER);
732 if (link) {
733 layout->AddPaddingRow(1, 4);
734 layout->StartRow(1, content_column);
735 layout->AddView(link, 1, 1, views::GridLayout::LEADING,
736 views::GridLayout::CENTER);
739 layout->AddPaddingRow(1, kPermissionsSectionPaddingBottom);
740 return container;
743 void WebsiteSettingsPopupView::ResetConnectionSection(
744 views::View* section_container,
745 const gfx::Image& icon,
746 const base::string16& headline,
747 const base::string16& text,
748 views::Link* link,
749 views::Link* secondary_link,
750 views::LabelButton* reset_decisions_button) {
751 section_container->RemoveAllChildViews(true);
753 views::GridLayout* layout = new views::GridLayout(section_container);
754 section_container->SetLayoutManager(layout);
755 views::ColumnSet* column_set = layout->AddColumnSet(0);
756 column_set->AddPaddingColumn(0, kConnectionSectionPaddingLeft);
757 column_set->AddColumn(views::GridLayout::LEADING,
758 views::GridLayout::LEADING,
760 views::GridLayout::USE_PREF,
763 column_set->AddPaddingColumn(0, kIconMarginLeft);
764 column_set->AddColumn(views::GridLayout::FILL,
765 views::GridLayout::FILL,
767 views::GridLayout::USE_PREF,
770 column_set->AddPaddingColumn(0, kConnectionSectionPaddingRight);
773 layout->AddPaddingRow(0, kConnectionSectionPaddingTop);
774 layout->StartRow(1, 0);
776 // Add status icon.
777 views::ImageView* icon_view = new views::ImageView();
778 icon_view->SetImage(*icon.ToImageSkia());
779 layout->AddView(icon_view, 1, 1, views::GridLayout::LEADING,
780 views::GridLayout::LEADING);
782 // Add section content.
783 views::View* content_pane = new views::View();
784 views::GridLayout* content_layout = new views::GridLayout(content_pane);
785 content_pane->SetLayoutManager(content_layout);
786 views::ColumnSet* content_column_set = content_layout->AddColumnSet(0);
787 content_column_set->AddColumn(views::GridLayout::LEADING,
788 views::GridLayout::LEADING,
790 views::GridLayout::USE_PREF,
793 if (!headline.empty()) {
794 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
795 views::Label* headline_label = new views::Label(
796 headline, rb.GetFontList(ui::ResourceBundle::BoldFont));
797 headline_label->SetMultiLine(true);
798 headline_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
799 // Allow linebreaking in the middle of words if necessary, so that extremely
800 // long hostnames (longer than one line) will still be completely shown.
801 headline_label->SetAllowCharacterBreak(true);
802 content_layout->StartRow(1, 0);
803 content_layout->AddView(headline_label);
806 views::Label* description_label = new views::Label(text);
807 description_label->SetMultiLine(true);
808 description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
809 description_label->SetAllowCharacterBreak(true);
810 content_layout->StartRow(1, 0);
811 content_layout->AddView(description_label);
813 if (link) {
814 content_layout->StartRow(1, 0);
815 content_layout->AddView(link);
818 if (secondary_link) {
819 content_layout->StartRow(1, 0);
820 content_layout->AddView(secondary_link);
823 if (reset_decisions_button) {
824 content_layout->StartRow(1, 0);
825 content_layout->AddView(reset_decisions_button);
828 layout->AddView(content_pane, 1, 1, views::GridLayout::LEADING,
829 views::GridLayout::LEADING);
830 layout->AddPaddingRow(0, kConnectionSectionPaddingBottom);
833 void WebsiteSettingsPopupView::HandleLinkClickedAsync(views::Link* source) {
834 if (source == cookie_dialog_link_) {
835 // Count how often the Collected Cookies dialog is opened.
836 presenter_->RecordWebsiteSettingsAction(
837 WebsiteSettings::WEBSITE_SETTINGS_COOKIES_DIALOG_OPENED);
839 new CollectedCookiesViews(web_contents_);
840 } else if (source == certificate_dialog_link_) {
841 gfx::NativeWindow parent = GetAnchorView() ?
842 GetAnchorView()->GetWidget()->GetNativeWindow() : nullptr;
843 presenter_->RecordWebsiteSettingsAction(
844 WebsiteSettings::WEBSITE_SETTINGS_CERTIFICATE_DIALOG_OPENED);
845 ShowCertificateViewerByID(web_contents_, parent, cert_id_);
846 } else if (source == signed_certificate_timestamps_link_) {
847 chrome::ShowSignedCertificateTimestampsViewer(
848 web_contents_, signed_certificate_timestamp_ids_);
849 presenter_->RecordWebsiteSettingsAction(
850 WebsiteSettings::WEBSITE_SETTINGS_TRANSPARENCY_VIEWER_OPENED);
851 } else if (source == help_center_link_) {
852 browser_->OpenURL(
853 content::OpenURLParams(GURL(chrome::kPageInfoHelpCenterURL),
854 content::Referrer(),
855 NEW_FOREGROUND_TAB,
856 ui::PAGE_TRANSITION_LINK,
857 false));
858 presenter_->RecordWebsiteSettingsAction(
859 WebsiteSettings::WEBSITE_SETTINGS_CONNECTION_HELP_OPENED);
860 } else if (source == site_settings_link_) {
861 // TODO(palmer): This opens the general Content Settings pane, which is OK
862 // for now. But on Android, it opens a page specific to a given origin that
863 // shows all of the settings for that origin. If/when that's available on
864 // desktop we should link to that here, too.
865 browser_->OpenURL(content::OpenURLParams(
866 GURL(chrome::kChromeUIContentSettingsURL), content::Referrer(),
867 NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_LINK, false));
868 presenter_->RecordWebsiteSettingsAction(
869 WebsiteSettings::WEBSITE_SETTINGS_SITE_SETTINGS_OPENED);
870 } else {
871 NOTREACHED();