Infobar material design refresh: layout
[chromium-blink-merge.git] / chrome / browser / ui / views / website_settings / website_settings_popup_view.cc
blob5239ff87aaefa187be322c69a1e271b34aa9c93a
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/i18n/rtl.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/certificate_viewer.h"
13 #include "chrome/browser/infobars/infobar_service.h"
14 #include "chrome/browser/profiles/profile.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 "chrome/grit/chromium_strings.h"
23 #include "chrome/grit/generated_resources.h"
24 #include "components/content_settings/core/common/content_settings_types.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "content/public/browser/cert_store.h"
27 #include "content/public/browser/user_metrics.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/geometry/insets.h"
35 #include "ui/gfx/image/image.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"
54 namespace {
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.
62 bool is_popup_showing = false;
64 // Padding values for sections on the connection tab.
65 const int kConnectionSectionPaddingBottom = 16;
66 const int kConnectionSectionPaddingLeft = 18;
67 const int kConnectionSectionPaddingTop = 16;
68 const int kConnectionSectionPaddingRight = 18;
70 // Left icon margin.
71 const int kIconMarginLeft = 6;
73 // Margin and padding values for the |PopupHeaderView|.
74 const int kHeaderMarginBottom = 10;
75 const int kHeaderPaddingBottom = 12;
76 const int kHeaderPaddingLeft = 18;
77 const int kHeaderPaddingRight = 8;
78 const int kHeaderPaddingTop = 12;
80 // Spacing between the site identity label and the site identity status text in
81 // the popup header.
82 const int kHeaderRowSpacing = 4;
84 // To make the bubble's arrow point directly at the location icon rather than at
85 // the Omnibox's edge, inset the bubble's anchor rect by this amount of pixels.
86 const int kLocationIconVerticalMargin = 5;
88 // The max possible width of the popup.
89 const int kMaxPopupWidth = 500;
91 // The margins between the popup border and the popup content.
92 const int kPopupMarginTop = 4;
93 const int kPopupMarginLeft = 0;
94 const int kPopupMarginBottom = 10;
95 const int kPopupMarginRight = 0;
97 // Padding values for sections on the permissions tab.
98 const int kPermissionsSectionContentMinWidth = 300;
99 const int kPermissionsSectionPaddingBottom = 6;
100 const int kPermissionsSectionPaddingLeft = 18;
101 const int kPermissionsSectionPaddingTop = 16;
103 // Space between the headline and the content of a section on the permissions
104 // tab.
105 const int kPermissionsSectionHeadlineMarginBottom = 10;
106 // The content of the "Permissions" section and the "Cookies and Site Data"
107 // section is structured in individual rows. |kPermissionsSectionRowSpacing|
108 // is the space between these rows.
109 const int kPermissionsSectionRowSpacing = 2;
111 const int kSiteDataIconColumnWidth = 20;
113 } // namespace
115 // |PopupHeaderView| is the UI element (view) that represents the header of the
116 // |WebsiteSettingsPopupView|. The header shows the status of the site's
117 // identity check and the name of the site's identity.
118 class PopupHeaderView : public views::View {
119 public:
120 explicit PopupHeaderView(views::ButtonListener* close_button_listener);
121 ~PopupHeaderView() override;
123 // Sets the name of the site's identity.
124 void SetIdentityName(const base::string16& name);
126 // Sets the |status_text| for the identity check of this site and the
127 // |text_color|.
128 void SetIdentityStatus(const base::string16& status_text, SkColor text_color);
130 private:
131 // The label that displays the name of the site's identity.
132 views::Label* name_;
133 // The label that displays the status of the identity check for this site.
134 views::Label* status_;
136 DISALLOW_COPY_AND_ASSIGN(PopupHeaderView);
139 // Website Settings are not supported for internal Chrome pages. Instead of the
140 // |WebsiteSettingsPopupView|, the |InternalPageInfoPopupView| is
141 // displayed.
142 class InternalPageInfoPopupView : public views::BubbleDelegateView {
143 public:
144 // If |anchor_view| is nullptr, or has no Widget, |parent_window| may be
145 // provided to ensure this bubble is closed when the parent closes.
146 InternalPageInfoPopupView(views::View* anchor_view,
147 gfx::NativeView parent_window);
148 ~InternalPageInfoPopupView() override;
150 // views::BubbleDelegateView:
151 void OnWidgetDestroying(views::Widget* widget) override;
153 private:
154 friend class WebsiteSettingsPopupView;
156 DISALLOW_COPY_AND_ASSIGN(InternalPageInfoPopupView);
159 ////////////////////////////////////////////////////////////////////////////////
160 // Popup Header
161 ////////////////////////////////////////////////////////////////////////////////
163 PopupHeaderView::PopupHeaderView(views::ButtonListener* close_button_listener)
164 : name_(nullptr), status_(nullptr) {
165 views::GridLayout* layout = new views::GridLayout(this);
166 SetLayoutManager(layout);
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,
174 views::GridLayout::USE_PREF,
177 column_set->AddPaddingColumn(1, 0);
178 column_set->AddColumn(views::GridLayout::FILL,
179 views::GridLayout::FILL,
181 views::GridLayout::USE_PREF,
184 column_set->AddPaddingColumn(0, kHeaderPaddingRight);
186 layout->AddPaddingRow(0, kHeaderPaddingTop);
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);
205 layout->AddPaddingRow(0, kHeaderRowSpacing);
207 layout->StartRow(1, label_column);
208 status_ = new views::Label(base::string16());
209 status_->SetMultiLine(true);
210 status_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
211 layout->AddView(status_,
214 views::GridLayout::LEADING,
215 views::GridLayout::LEADING);
217 layout->AddPaddingRow(1, kHeaderPaddingBottom);
220 PopupHeaderView::~PopupHeaderView() {
223 void PopupHeaderView::SetIdentityName(const base::string16& name) {
224 name_->SetText(name);
227 void PopupHeaderView::SetIdentityStatus(const base::string16& status,
228 SkColor text_color) {
229 status_->SetText(status);
230 status_->SetEnabledColor(text_color);
233 ////////////////////////////////////////////////////////////////////////////////
234 // InternalPageInfoPopupView
235 ////////////////////////////////////////////////////////////////////////////////
237 InternalPageInfoPopupView::InternalPageInfoPopupView(
238 views::View* anchor_view,
239 gfx::NativeView parent_window)
240 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT) {
241 set_parent_window(parent_window);
243 // Compensate for built-in vertical padding in the anchor view's image.
244 set_anchor_view_insets(gfx::Insets(kLocationIconVerticalMargin, 0,
245 kLocationIconVerticalMargin, 0));
247 const int kSpacing = 4;
248 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, kSpacing,
249 kSpacing, kSpacing));
250 views::ImageView* icon_view = new views::ImageView();
251 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
252 icon_view->SetImage(rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_26));
253 AddChildView(icon_view);
255 views::Label* label =
256 new views::Label(l10n_util::GetStringUTF16(IDS_PAGE_INFO_INTERNAL_PAGE));
257 label->SetMultiLine(true);
258 label->SetAllowCharacterBreak(true);
259 label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
260 AddChildView(label);
262 views::BubbleDelegateView::CreateBubble(this);
265 InternalPageInfoPopupView::~InternalPageInfoPopupView() {
268 void InternalPageInfoPopupView::OnWidgetDestroying(views::Widget* widget) {
269 is_popup_showing = false;
272 ////////////////////////////////////////////////////////////////////////////////
273 // WebsiteSettingsPopupView
274 ////////////////////////////////////////////////////////////////////////////////
276 WebsiteSettingsPopupView::~WebsiteSettingsPopupView() {
279 // static
280 void WebsiteSettingsPopupView::ShowPopup(views::View* anchor_view,
281 const gfx::Rect& anchor_rect,
282 Profile* profile,
283 content::WebContents* web_contents,
284 const GURL& url,
285 const content::SSLStatus& ssl) {
286 is_popup_showing = true;
287 gfx::NativeView parent_window =
288 anchor_view ? nullptr : web_contents->GetNativeView();
289 if (InternalChromePage(url)) {
290 // Use the concrete type so that SetAnchorRect() can be called as a friend.
291 InternalPageInfoPopupView* popup =
292 new InternalPageInfoPopupView(anchor_view, parent_window);
293 if (!anchor_view)
294 popup->SetAnchorRect(anchor_rect);
295 popup->GetWidget()->Show();
296 } else {
297 WebsiteSettingsPopupView* popup = new WebsiteSettingsPopupView(
298 anchor_view, parent_window, profile, web_contents, url, ssl);
299 if (!anchor_view)
300 popup->SetAnchorRect(anchor_rect);
301 popup->GetWidget()->Show();
305 // static
306 bool WebsiteSettingsPopupView::IsPopupShowing() {
307 return is_popup_showing;
310 WebsiteSettingsPopupView::WebsiteSettingsPopupView(
311 views::View* anchor_view,
312 gfx::NativeView parent_window,
313 Profile* profile,
314 content::WebContents* web_contents,
315 const GURL& url,
316 const content::SSLStatus& ssl)
317 : content::WebContentsObserver(web_contents),
318 BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT),
319 web_contents_(web_contents),
320 header_(nullptr),
321 tabbed_pane_(nullptr),
322 permissions_tab_(nullptr),
323 site_data_content_(nullptr),
324 cookie_dialog_link_(nullptr),
325 permissions_content_(nullptr),
326 connection_tab_(nullptr),
327 identity_info_content_(nullptr),
328 certificate_dialog_link_(nullptr),
329 reset_decisions_button_(nullptr),
330 help_center_content_(nullptr),
331 cert_id_(0),
332 help_center_link_(nullptr),
333 connection_info_content_(nullptr),
334 weak_factory_(this) {
335 set_parent_window(parent_window);
337 // Compensate for built-in vertical padding in the anchor view's image.
338 set_anchor_view_insets(gfx::Insets(kLocationIconVerticalMargin, 0,
339 kLocationIconVerticalMargin, 0));
341 views::GridLayout* layout = new views::GridLayout(this);
342 SetLayoutManager(layout);
343 const int content_column = 0;
344 views::ColumnSet* column_set = layout->AddColumnSet(content_column);
345 column_set->AddColumn(views::GridLayout::FILL,
346 views::GridLayout::FILL,
348 views::GridLayout::USE_PREF,
352 header_ = new PopupHeaderView(this);
353 layout->StartRow(1, content_column);
354 layout->AddView(header_);
356 layout->AddPaddingRow(1, kHeaderMarginBottom);
357 tabbed_pane_ = new views::TabbedPane();
358 layout->StartRow(1, content_column);
359 layout->AddView(tabbed_pane_);
361 // Tabs must be added after the tabbed_pane_ was added to the views hierarchy.
362 // Adding the |tabbed_pane_| to the views hierarchy triggers the
363 // initialization of the native tab UI element. If the native tab UI element
364 // is not initalized, adding a tab will result in a NULL pointer exception.
365 permissions_tab_ = CreatePermissionsTab();
366 tabbed_pane_->AddTabAtIndex(
367 TAB_ID_PERMISSIONS,
368 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TAB_LABEL_PERMISSIONS),
369 permissions_tab_);
370 connection_tab_ = CreateConnectionTab();
371 tabbed_pane_->AddTabAtIndex(
372 TAB_ID_CONNECTION,
373 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TAB_LABEL_CONNECTION),
374 connection_tab_);
375 DCHECK_EQ(tabbed_pane_->GetTabCount(), NUM_TAB_IDS);
376 tabbed_pane_->set_listener(this);
378 set_margins(gfx::Insets(kPopupMarginTop, kPopupMarginLeft,
379 kPopupMarginBottom, kPopupMarginRight));
381 views::BubbleDelegateView::CreateBubble(this);
383 presenter_.reset(new WebsiteSettings(
384 this, profile, TabSpecificContentSettings::FromWebContents(web_contents),
385 web_contents, url, ssl, content::CertStore::GetInstance()));
388 void WebsiteSettingsPopupView::RenderFrameDeleted(
389 content::RenderFrameHost* render_frame_host) {
390 if (render_frame_host == web_contents_->GetMainFrame()) {
391 GetWidget()->Close();
395 void WebsiteSettingsPopupView::OnPermissionChanged(
396 const WebsiteSettingsUI::PermissionInfo& permission) {
397 presenter_->OnSitePermissionChanged(permission.type, permission.setting);
400 void WebsiteSettingsPopupView::OnWidgetDestroying(views::Widget* widget) {
401 is_popup_showing = false;
402 presenter_->OnUIClosing();
405 void WebsiteSettingsPopupView::ButtonPressed(views::Button* button,
406 const ui::Event& event) {
407 if (button == reset_decisions_button_)
408 presenter_->OnRevokeSSLErrorBypassButtonPressed();
409 GetWidget()->Close();
412 void WebsiteSettingsPopupView::LinkClicked(views::Link* source,
413 int event_flags) {
414 // The popup closes automatically when the collected cookies dialog or the
415 // certificate viewer opens. So delay handling of the link clicked to avoid
416 // a crash in the base class which needs to complete the mouse event handling.
417 content::BrowserThread::PostTask(
418 content::BrowserThread::UI, FROM_HERE,
419 base::Bind(&WebsiteSettingsPopupView::HandleLinkClickedAsync,
420 weak_factory_.GetWeakPtr(), source));
423 void WebsiteSettingsPopupView::TabSelectedAt(int index) {
424 switch (index) {
425 case TAB_ID_PERMISSIONS:
426 presenter_->RecordWebsiteSettingsAction(
427 WebsiteSettings::WEBSITE_SETTINGS_PERMISSIONS_TAB_SELECTED);
428 break;
429 case TAB_ID_CONNECTION:
430 // If the Connection tab is selected first, we're still inside the
431 // construction of presenter_. In that case, the action is already logged
432 // by WEBSITE_SETTINGS_CONNECTION_TAB_SHOWN_IMMEDIATELY.
433 if (presenter_) {
434 presenter_->RecordWebsiteSettingsAction(
435 WebsiteSettings::WEBSITE_SETTINGS_CONNECTION_TAB_SELECTED);
437 break;
438 default:
439 NOTREACHED();
441 tabbed_pane_->GetSelectedTab()->Layout();
442 SizeToContents();
445 gfx::Size WebsiteSettingsPopupView::GetPreferredSize() const {
446 if (header_ == nullptr && tabbed_pane_ == nullptr)
447 return views::View::GetPreferredSize();
449 int height = 0;
450 if (header_)
451 height += header_->GetPreferredSize().height();
452 if (tabbed_pane_)
453 height += tabbed_pane_->GetPreferredSize().height();
455 int width = kPermissionsSectionContentMinWidth;
456 if (site_data_content_)
457 width = std::max(width, site_data_content_->GetPreferredSize().width());
458 if (permissions_content_)
459 width = std::max(width, permissions_content_->GetPreferredSize().width());
460 width += kPermissionsSectionPaddingLeft;
461 width = std::min(width, kMaxPopupWidth);
463 return gfx::Size(width, height);
466 void WebsiteSettingsPopupView::SetCookieInfo(
467 const CookieInfoList& cookie_info_list) {
468 site_data_content_->RemoveAllChildViews(true);
470 views::GridLayout* layout = new views::GridLayout(site_data_content_);
471 site_data_content_->SetLayoutManager(layout);
473 const int site_data_content_column = 0;
474 views::ColumnSet* column_set =
475 layout->AddColumnSet(site_data_content_column);
476 column_set->AddColumn(views::GridLayout::FILL,
477 views::GridLayout::FILL,
479 views::GridLayout::FIXED,
480 kSiteDataIconColumnWidth,
482 column_set->AddPaddingColumn(0, kIconMarginLeft);
483 column_set->AddColumn(views::GridLayout::FILL,
484 views::GridLayout::FILL,
486 views::GridLayout::USE_PREF,
489 // No padding. This third column is for |third_party_label_text| (see below),
490 // and the text needs to flow naturally from the |first_party_label_text|
491 // link.
492 column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
493 views::GridLayout::USE_PREF, 0, 0);
495 layout->AddPaddingRow(1, 5);
497 // |cookie_info_list| should only ever have 2 items: first- and third-party
498 // cookies.
499 DCHECK_EQ(cookie_info_list.size(), 2u);
500 base::string16 first_party_label_text;
501 base::string16 third_party_label_text;
502 for (const auto& i : cookie_info_list) {
503 if (i.is_first_party) {
504 first_party_label_text =
505 l10n_util::GetStringFUTF16(IDS_WEBSITE_SETTINGS_FIRST_PARTY_SITE_DATA,
506 base::IntToString16(i.allowed));
507 } else {
508 third_party_label_text =
509 l10n_util::GetStringFUTF16(IDS_WEBSITE_SETTINGS_THIRD_PARTY_SITE_DATA,
510 base::IntToString16(i.allowed));
514 cookie_dialog_link_ = new views::Link(first_party_label_text);
515 cookie_dialog_link_->set_listener(this);
517 layout->StartRow(1, site_data_content_column);
518 WebsiteSettingsUI::PermissionInfo info;
519 info.type = CONTENT_SETTINGS_TYPE_COOKIES;
520 info.setting = CONTENT_SETTING_ALLOW;
521 views::ImageView* icon = new views::ImageView();
522 const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon(info);
523 icon->SetImage(image.ToImageSkia());
524 layout->AddView(icon, 1, 1, views::GridLayout::CENTER,
525 views::GridLayout::CENTER);
526 layout->AddView(cookie_dialog_link_, 1, 1, views::GridLayout::CENTER,
527 views::GridLayout::CENTER);
528 base::string16 comma = base::ASCIIToUTF16(", ");
530 layout->AddView(new views::Label(comma + third_party_label_text), 1, 1,
531 views::GridLayout::LEADING, views::GridLayout::CENTER);
533 layout->AddPaddingRow(1, 6);
535 layout->Layout(site_data_content_);
536 SizeToContents();
539 void WebsiteSettingsPopupView::SetPermissionInfo(
540 const PermissionInfoList& permission_info_list) {
541 permissions_content_ = new views::View();
542 views::GridLayout* layout = new views::GridLayout(permissions_content_);
543 permissions_content_->SetLayoutManager(layout);
545 base::string16 headline =
546 permission_info_list.empty()
547 ? base::string16()
548 : l10n_util::GetStringUTF16(
549 IDS_WEBSITE_SETTINGS_TITLE_SITE_PERMISSIONS);
550 views::View* permissions_section =
551 CreateSection(headline, permissions_content_, nullptr);
552 permissions_tab_->AddChildView(permissions_section);
554 const int content_column = 0;
555 views::ColumnSet* column_set = layout->AddColumnSet(content_column);
556 column_set->AddColumn(views::GridLayout::FILL,
557 views::GridLayout::FILL,
559 views::GridLayout::USE_PREF,
562 for (PermissionInfoList::const_iterator permission =
563 permission_info_list.begin();
564 permission != permission_info_list.end();
565 ++permission) {
566 layout->StartRow(1, content_column);
567 PermissionSelectorView* selector = new PermissionSelectorView(
568 web_contents_ ? web_contents_->GetURL() : GURL::EmptyGURL(),
569 *permission);
570 selector->AddObserver(this);
571 layout->AddView(selector,
574 views::GridLayout::LEADING,
575 views::GridLayout::CENTER);
576 layout->AddPaddingRow(1, kPermissionsSectionRowSpacing);
579 layout->Layout(permissions_content_);
581 // Add site settings link.
582 site_settings_link_ = new views::Link(
583 l10n_util::GetStringUTF16(IDS_PAGE_INFO_SITE_SETTINGS_LINK));
584 site_settings_link_->set_listener(this);
585 views::View* link_section = new views::View();
586 const int kLinkMarginTop = 4;
587 link_section->SetLayoutManager(
588 new views::BoxLayout(views::BoxLayout::kHorizontal,
589 kConnectionSectionPaddingLeft, kLinkMarginTop, 0));
590 link_section->AddChildView(site_settings_link_);
591 permissions_tab_->AddChildView(link_section);
593 SizeToContents();
596 void WebsiteSettingsPopupView::SetIdentityInfo(
597 const IdentityInfo& identity_info) {
598 base::string16 identity_status_text = identity_info.GetSecuritySummary();
599 header_->SetIdentityName(base::UTF8ToUTF16(identity_info.site_identity));
600 header_->SetIdentityStatus(identity_status_text, SK_ColorBLACK);
602 // The headline and the certificate dialog link of the site's identity
603 // section is only displayed if the site's identity was verified. If the
604 // site's identity was verified, then the headline contains the organization
605 // name from the provided certificate. If the organization name is not
606 // available than the hostname of the site is used instead.
607 base::string16 headline;
608 if (identity_info.cert_id) {
609 cert_id_ = identity_info.cert_id;
611 certificate_dialog_link_ = new views::Link(
612 l10n_util::GetStringUTF16(IDS_PAGEINFO_CERT_INFO_BUTTON));
613 certificate_dialog_link_->set_listener(this);
615 if (identity_info.show_ssl_decision_revoke_button) {
616 reset_decisions_button_ = new views::LabelButton(
617 this,
618 l10n_util::GetStringUTF16(
619 IDS_PAGEINFO_RESET_INVALID_CERTIFICATE_DECISIONS_BUTTON));
620 reset_decisions_button_->SetStyle(views::Button::STYLE_BUTTON);
623 headline = base::UTF8ToUTF16(identity_info.site_identity);
625 ResetConnectionSection(
626 identity_info_content_,
627 WebsiteSettingsUI::GetIdentityIcon(identity_info.identity_status),
628 base::string16(), // The identity section has no headline.
629 base::UTF8ToUTF16(identity_info.identity_status_description),
630 certificate_dialog_link_,
631 reset_decisions_button_);
633 ResetConnectionSection(
634 connection_info_content_,
635 WebsiteSettingsUI::GetConnectionIcon(identity_info.connection_status),
636 base::string16(), // The connection section has no headline.
637 base::UTF8ToUTF16(identity_info.connection_status_description),
638 nullptr,
639 nullptr);
641 connection_tab_->InvalidateLayout();
642 Layout();
643 SizeToContents();
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));
655 // Add cookies and site data section.
656 site_data_content_ = new views::View();
657 views::View* site_data_section = CreateSection(
658 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TITLE_SITE_DATA),
659 site_data_content_, NULL);
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));
670 // Add site identity section.
671 identity_info_content_ = new views::View();
672 pane->AddChildView(identity_info_content_);
674 // Add connection section.
675 pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL));
676 connection_info_content_ = new views::View();
677 pane->AddChildView(connection_info_content_);
679 // Add help center link.
680 pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL));
681 help_center_link_ = new views::Link(
682 l10n_util::GetStringUTF16(IDS_PAGE_INFO_HELP_CENTER_LINK));
683 help_center_link_->set_listener(this);
684 help_center_content_ = new views::View();
685 views::View* link_section =
686 CreateSection(base::string16(),
687 help_center_content_,
688 help_center_link_);
689 link_section->AddChildView(help_center_link_);
690 pane->AddChildView(link_section);
691 return pane;
694 views::View* WebsiteSettingsPopupView::CreateSection(
695 const base::string16& headline_text,
696 views::View* content,
697 views::Link* link) {
698 views::View* container = new views::View();
699 views::GridLayout* layout = new views::GridLayout(container);
700 container->SetLayoutManager(layout);
701 const int content_column = 0;
702 views::ColumnSet* column_set = layout->AddColumnSet(content_column);
703 column_set->AddPaddingColumn(0, kPermissionsSectionPaddingLeft);
704 column_set->AddColumn(views::GridLayout::FILL,
705 views::GridLayout::FILL,
707 views::GridLayout::USE_PREF,
711 if (headline_text.length() > 0) {
712 layout->AddPaddingRow(1, kPermissionsSectionPaddingTop);
713 layout->StartRow(1, content_column);
714 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
715 views::Label* headline = new views::Label(
716 headline_text, rb.GetFontList(ui::ResourceBundle::BoldFont));
717 layout->AddView(headline, 1, 1, views::GridLayout::LEADING,
718 views::GridLayout::CENTER);
721 layout->AddPaddingRow(1, kPermissionsSectionHeadlineMarginBottom);
722 layout->StartRow(1, content_column);
723 layout->AddView(content, 1, 1, views::GridLayout::LEADING,
724 views::GridLayout::CENTER);
726 if (link) {
727 layout->AddPaddingRow(1, 4);
728 layout->StartRow(1, content_column);
729 layout->AddView(link, 1, 1, views::GridLayout::LEADING,
730 views::GridLayout::CENTER);
733 layout->AddPaddingRow(1, kPermissionsSectionPaddingBottom);
734 return container;
737 void WebsiteSettingsPopupView::ResetConnectionSection(
738 views::View* section_container,
739 const gfx::Image& icon,
740 const base::string16& headline,
741 const base::string16& text,
742 views::Link* link,
743 views::LabelButton* reset_decisions_button) {
744 section_container->RemoveAllChildViews(true);
746 views::GridLayout* layout = new views::GridLayout(section_container);
747 section_container->SetLayoutManager(layout);
748 views::ColumnSet* column_set = layout->AddColumnSet(0);
749 column_set->AddPaddingColumn(0, kConnectionSectionPaddingLeft);
750 column_set->AddColumn(views::GridLayout::LEADING,
751 views::GridLayout::LEADING,
753 views::GridLayout::USE_PREF,
756 column_set->AddPaddingColumn(0, kIconMarginLeft);
757 column_set->AddColumn(views::GridLayout::FILL,
758 views::GridLayout::FILL,
760 views::GridLayout::USE_PREF,
763 column_set->AddPaddingColumn(0, kConnectionSectionPaddingRight);
766 layout->AddPaddingRow(0, kConnectionSectionPaddingTop);
767 layout->StartRow(1, 0);
769 // Add status icon.
770 views::ImageView* icon_view = new views::ImageView();
771 icon_view->SetImage(*icon.ToImageSkia());
772 layout->AddView(icon_view, 1, 1, views::GridLayout::LEADING,
773 views::GridLayout::LEADING);
775 // Add section content.
776 views::View* content_pane = new views::View();
777 views::GridLayout* content_layout = new views::GridLayout(content_pane);
778 content_pane->SetLayoutManager(content_layout);
779 views::ColumnSet* content_column_set = content_layout->AddColumnSet(0);
780 content_column_set->AddColumn(views::GridLayout::LEADING,
781 views::GridLayout::LEADING,
783 views::GridLayout::USE_PREF,
786 if (!headline.empty()) {
787 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
788 views::Label* headline_label = new views::Label(
789 headline, rb.GetFontList(ui::ResourceBundle::BoldFont));
790 headline_label->SetMultiLine(true);
791 headline_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
792 // Allow linebreaking in the middle of words if necessary, so that extremely
793 // long hostnames (longer than one line) will still be completely shown.
794 headline_label->SetAllowCharacterBreak(true);
795 content_layout->StartRow(1, 0);
796 content_layout->AddView(headline_label);
799 views::Label* description_label = new views::Label(text);
800 description_label->SetMultiLine(true);
801 description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
802 description_label->SetAllowCharacterBreak(true);
803 content_layout->StartRow(1, 0);
804 content_layout->AddView(description_label);
806 if (link) {
807 content_layout->StartRow(1, 0);
808 content_layout->AddView(link);
811 if (reset_decisions_button) {
812 content_layout->StartRow(1, 0);
813 content_layout->AddView(reset_decisions_button);
816 layout->AddView(content_pane, 1, 1, views::GridLayout::LEADING,
817 views::GridLayout::LEADING);
818 layout->AddPaddingRow(0, kConnectionSectionPaddingBottom);
821 void WebsiteSettingsPopupView::HandleLinkClickedAsync(views::Link* source) {
822 if (source == cookie_dialog_link_) {
823 // Count how often the Collected Cookies dialog is opened.
824 presenter_->RecordWebsiteSettingsAction(
825 WebsiteSettings::WEBSITE_SETTINGS_COOKIES_DIALOG_OPENED);
827 if (web_contents_ != NULL)
828 new CollectedCookiesViews(web_contents_);
829 } else if (source == certificate_dialog_link_) {
830 gfx::NativeWindow parent = GetAnchorView() ?
831 GetAnchorView()->GetWidget()->GetNativeWindow() : nullptr;
832 presenter_->RecordWebsiteSettingsAction(
833 WebsiteSettings::WEBSITE_SETTINGS_CERTIFICATE_DIALOG_OPENED);
834 ShowCertificateViewerByID(web_contents_, parent, cert_id_);
835 } else if (source == help_center_link_) {
836 web_contents_->OpenURL(content::OpenURLParams(
837 GURL(chrome::kPageInfoHelpCenterURL), content::Referrer(),
838 NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_LINK, false));
839 presenter_->RecordWebsiteSettingsAction(
840 WebsiteSettings::WEBSITE_SETTINGS_CONNECTION_HELP_OPENED);
841 } else if (source == site_settings_link_) {
842 // TODO(palmer): This opens the general Content Settings pane, which is OK
843 // for now. But on Android, it opens a page specific to a given origin that
844 // shows all of the settings for that origin. If/when that's available on
845 // desktop we should link to that here, too.
846 web_contents_->OpenURL(content::OpenURLParams(
847 GURL(chrome::kChromeUIContentSettingsURL), content::Referrer(),
848 NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_LINK, false));
849 presenter_->RecordWebsiteSettingsAction(
850 WebsiteSettings::WEBSITE_SETTINGS_SITE_SETTINGS_OPENED);
851 } else {
852 NOTREACHED();