Elim cr-checkbox
[chromium-blink-merge.git] / chrome / browser / ui / views / website_settings / website_settings_popup_view.cc
blobf5d7232f4827c8ec4fb22a083c491189fb46eb11
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 = 1000;
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 kPermissionsSectionPaddingRight = 18;
102 const int kPermissionsSectionPaddingTop = 16;
104 // Space between the headline and the content of a section on the permissions
105 // tab.
106 const int kPermissionsSectionHeadlineMarginBottom = 10;
107 // The content of the "Permissions" section and the "Cookies and Site Data"
108 // section is structured in individual rows. |kPermissionsSectionRowSpacing|
109 // is the space between these rows.
110 const int kPermissionsSectionRowSpacing = 2;
112 const int kSiteDataIconColumnWidth = 20;
114 } // namespace
116 // |PopupHeaderView| is the UI element (view) that represents the header of the
117 // |WebsiteSettingsPopupView|. The header shows the status of the site's
118 // identity check and the name of the site's identity.
119 class PopupHeaderView : public views::View {
120 public:
121 explicit PopupHeaderView(views::ButtonListener* close_button_listener);
122 ~PopupHeaderView() override;
124 // Sets the name of the site's identity.
125 void SetIdentityName(const base::string16& name);
127 // Sets the |status_text| for the identity check of this site and the
128 // |text_color|.
129 void SetIdentityStatus(const base::string16& status_text, SkColor text_color);
131 int GetPreferredNameWidth() const;
133 private:
134 // The label that displays the name of the site's identity.
135 views::Label* name_;
136 // The label that displays the status of the identity check for this site.
137 views::Label* status_;
139 DISALLOW_COPY_AND_ASSIGN(PopupHeaderView);
142 // Website Settings are not supported for internal Chrome pages. Instead of the
143 // |WebsiteSettingsPopupView|, the |InternalPageInfoPopupView| is
144 // displayed.
145 class InternalPageInfoPopupView : public views::BubbleDelegateView {
146 public:
147 // If |anchor_view| is nullptr, or has no Widget, |parent_window| may be
148 // provided to ensure this bubble is closed when the parent closes.
149 InternalPageInfoPopupView(views::View* anchor_view,
150 gfx::NativeView parent_window);
151 ~InternalPageInfoPopupView() override;
153 // views::BubbleDelegateView:
154 void OnWidgetDestroying(views::Widget* widget) override;
156 private:
157 friend class WebsiteSettingsPopupView;
159 DISALLOW_COPY_AND_ASSIGN(InternalPageInfoPopupView);
162 ////////////////////////////////////////////////////////////////////////////////
163 // Popup Header
164 ////////////////////////////////////////////////////////////////////////////////
166 PopupHeaderView::PopupHeaderView(views::ButtonListener* close_button_listener)
167 : name_(nullptr), status_(nullptr) {
168 views::GridLayout* layout = new views::GridLayout(this);
169 SetLayoutManager(layout);
171 const int label_column = 0;
172 views::ColumnSet* column_set = layout->AddColumnSet(label_column);
173 column_set->AddPaddingColumn(0, kHeaderPaddingLeft);
174 column_set->AddColumn(views::GridLayout::FILL,
175 views::GridLayout::FILL,
177 views::GridLayout::USE_PREF,
180 column_set->AddPaddingColumn(1, 0);
181 column_set->AddColumn(views::GridLayout::FILL,
182 views::GridLayout::FILL,
184 views::GridLayout::USE_PREF,
187 column_set->AddPaddingColumn(0, kHeaderPaddingRight);
189 layout->AddPaddingRow(0, kHeaderPaddingTop);
191 layout->StartRow(0, label_column);
192 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
193 name_ = new views::Label(
194 base::string16(), rb.GetFontList(ui::ResourceBundle::BoldFont));
195 layout->AddView(name_, 1, 1, views::GridLayout::LEADING,
196 views::GridLayout::TRAILING);
197 views::ImageButton* close_button =
198 new views::ImageButton(close_button_listener);
199 close_button->SetImage(views::CustomButton::STATE_NORMAL,
200 rb.GetImageNamed(IDR_CLOSE_2).ToImageSkia());
201 close_button->SetImage(views::CustomButton::STATE_HOVERED,
202 rb.GetImageNamed(IDR_CLOSE_2_H).ToImageSkia());
203 close_button->SetImage(views::CustomButton::STATE_PRESSED,
204 rb.GetImageNamed(IDR_CLOSE_2_P).ToImageSkia());
205 layout->AddView(close_button, 1, 1, views::GridLayout::TRAILING,
206 views::GridLayout::LEADING);
208 layout->AddPaddingRow(0, kHeaderRowSpacing);
210 layout->StartRow(1, label_column);
211 status_ = new views::Label(base::string16());
212 status_->SetMultiLine(true);
213 status_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
214 layout->AddView(status_,
217 views::GridLayout::LEADING,
218 views::GridLayout::LEADING);
220 layout->AddPaddingRow(1, kHeaderPaddingBottom);
223 PopupHeaderView::~PopupHeaderView() {
226 int PopupHeaderView::GetPreferredNameWidth() const {
227 return name_->GetPreferredSize().width();
230 void PopupHeaderView::SetIdentityName(const base::string16& name) {
231 name_->SetText(name);
234 void PopupHeaderView::SetIdentityStatus(const base::string16& status,
235 SkColor text_color) {
236 status_->SetText(status);
237 status_->SetEnabledColor(text_color);
240 ////////////////////////////////////////////////////////////////////////////////
241 // InternalPageInfoPopupView
242 ////////////////////////////////////////////////////////////////////////////////
244 InternalPageInfoPopupView::InternalPageInfoPopupView(
245 views::View* anchor_view,
246 gfx::NativeView parent_window)
247 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT) {
248 set_parent_window(parent_window);
250 // Compensate for built-in vertical padding in the anchor view's image.
251 set_anchor_view_insets(gfx::Insets(kLocationIconVerticalMargin, 0,
252 kLocationIconVerticalMargin, 0));
254 const int kSpacing = 4;
255 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, kSpacing,
256 kSpacing, kSpacing));
257 views::ImageView* icon_view = new views::ImageView();
258 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
259 icon_view->SetImage(rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_26));
260 AddChildView(icon_view);
262 views::Label* label =
263 new views::Label(l10n_util::GetStringUTF16(IDS_PAGE_INFO_INTERNAL_PAGE));
264 label->SetMultiLine(true);
265 label->SetAllowCharacterBreak(true);
266 label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
267 AddChildView(label);
269 views::BubbleDelegateView::CreateBubble(this);
272 InternalPageInfoPopupView::~InternalPageInfoPopupView() {
275 void InternalPageInfoPopupView::OnWidgetDestroying(views::Widget* widget) {
276 is_popup_showing = false;
279 ////////////////////////////////////////////////////////////////////////////////
280 // WebsiteSettingsPopupView
281 ////////////////////////////////////////////////////////////////////////////////
283 WebsiteSettingsPopupView::~WebsiteSettingsPopupView() {
286 // static
287 void WebsiteSettingsPopupView::ShowPopup(
288 views::View* anchor_view,
289 const gfx::Rect& anchor_rect,
290 Profile* profile,
291 content::WebContents* web_contents,
292 const GURL& url,
293 const SecurityStateModel::SecurityInfo& security_info) {
294 is_popup_showing = true;
295 gfx::NativeView parent_window =
296 anchor_view ? nullptr : web_contents->GetNativeView();
297 if (InternalChromePage(url)) {
298 // Use the concrete type so that |SetAnchorRect| can be called as a friend.
299 InternalPageInfoPopupView* popup =
300 new InternalPageInfoPopupView(anchor_view, parent_window);
301 if (!anchor_view)
302 popup->SetAnchorRect(anchor_rect);
303 popup->GetWidget()->Show();
304 } else {
305 WebsiteSettingsPopupView* popup = new WebsiteSettingsPopupView(
306 anchor_view, parent_window, profile, web_contents, url, security_info);
307 if (!anchor_view)
308 popup->SetAnchorRect(anchor_rect);
309 popup->GetWidget()->Show();
313 // static
314 bool WebsiteSettingsPopupView::IsPopupShowing() {
315 return is_popup_showing;
318 WebsiteSettingsPopupView::WebsiteSettingsPopupView(
319 views::View* anchor_view,
320 gfx::NativeView parent_window,
321 Profile* profile,
322 content::WebContents* web_contents,
323 const GURL& url,
324 const SecurityStateModel::SecurityInfo& security_info)
325 : content::WebContentsObserver(web_contents),
326 BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT),
327 web_contents_(web_contents),
328 header_(nullptr),
329 tabbed_pane_(nullptr),
330 permissions_tab_(nullptr),
331 site_data_content_(nullptr),
332 cookie_dialog_link_(nullptr),
333 permissions_content_(nullptr),
334 connection_tab_(nullptr),
335 identity_info_content_(nullptr),
336 certificate_dialog_link_(nullptr),
337 reset_decisions_button_(nullptr),
338 help_center_content_(nullptr),
339 cert_id_(0),
340 help_center_link_(nullptr),
341 connection_info_content_(nullptr),
342 weak_factory_(this) {
343 set_parent_window(parent_window);
345 // Compensate for built-in vertical padding in the anchor view's image.
346 set_anchor_view_insets(gfx::Insets(kLocationIconVerticalMargin, 0,
347 kLocationIconVerticalMargin, 0));
349 views::GridLayout* layout = new views::GridLayout(this);
350 SetLayoutManager(layout);
351 const int content_column = 0;
352 views::ColumnSet* column_set = layout->AddColumnSet(content_column);
353 column_set->AddColumn(views::GridLayout::FILL,
354 views::GridLayout::FILL,
356 views::GridLayout::USE_PREF,
360 header_ = new PopupHeaderView(this);
361 layout->StartRow(1, content_column);
362 layout->AddView(header_);
364 layout->AddPaddingRow(1, kHeaderMarginBottom);
365 tabbed_pane_ = new views::TabbedPane();
366 layout->StartRow(1, content_column);
367 layout->AddView(tabbed_pane_);
369 // Tabs must be added after the |tabbed_pane_| was added to the views
370 // hierarchy. Adding the |tabbed_pane_| to the views hierarchy triggers the
371 // initialization of the native tab UI element. If the native tab UI element
372 // is not initialized, adding a tab will result in a NULL pointer exception.
373 permissions_tab_ = CreatePermissionsTab();
374 tabbed_pane_->AddTabAtIndex(
375 TAB_ID_PERMISSIONS,
376 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TAB_LABEL_PERMISSIONS),
377 permissions_tab_);
378 connection_tab_ = CreateConnectionTab();
379 tabbed_pane_->AddTabAtIndex(
380 TAB_ID_CONNECTION,
381 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TAB_LABEL_CONNECTION),
382 connection_tab_);
383 DCHECK_EQ(tabbed_pane_->GetTabCount(), NUM_TAB_IDS);
384 tabbed_pane_->set_listener(this);
386 set_margins(gfx::Insets(kPopupMarginTop, kPopupMarginLeft,
387 kPopupMarginBottom, kPopupMarginRight));
389 views::BubbleDelegateView::CreateBubble(this);
391 presenter_.reset(new WebsiteSettings(
392 this, profile, TabSpecificContentSettings::FromWebContents(web_contents),
393 web_contents, url, security_info, content::CertStore::GetInstance()));
396 void WebsiteSettingsPopupView::RenderFrameDeleted(
397 content::RenderFrameHost* render_frame_host) {
398 if (render_frame_host == web_contents_->GetMainFrame()) {
399 GetWidget()->Close();
403 void WebsiteSettingsPopupView::OnPermissionChanged(
404 const WebsiteSettingsUI::PermissionInfo& permission) {
405 presenter_->OnSitePermissionChanged(permission.type, permission.setting);
408 void WebsiteSettingsPopupView::OnWidgetDestroying(views::Widget* widget) {
409 is_popup_showing = false;
410 presenter_->OnUIClosing();
413 void WebsiteSettingsPopupView::ButtonPressed(views::Button* button,
414 const ui::Event& event) {
415 if (button == reset_decisions_button_)
416 presenter_->OnRevokeSSLErrorBypassButtonPressed();
417 GetWidget()->Close();
420 void WebsiteSettingsPopupView::LinkClicked(views::Link* source,
421 int event_flags) {
422 // The popup closes automatically when the collected cookies dialog or the
423 // certificate viewer opens. So delay handling of the link clicked to avoid
424 // a crash in the base class which needs to complete the mouse event handling.
425 content::BrowserThread::PostTask(
426 content::BrowserThread::UI, FROM_HERE,
427 base::Bind(&WebsiteSettingsPopupView::HandleLinkClickedAsync,
428 weak_factory_.GetWeakPtr(), source));
431 void WebsiteSettingsPopupView::TabSelectedAt(int index) {
432 switch (index) {
433 case TAB_ID_PERMISSIONS:
434 presenter_->RecordWebsiteSettingsAction(
435 WebsiteSettings::WEBSITE_SETTINGS_PERMISSIONS_TAB_SELECTED);
436 break;
437 case TAB_ID_CONNECTION:
438 // If the Connection tab is selected first, we're still inside the
439 // construction of presenter_. In that case, the action is already logged
440 // by WEBSITE_SETTINGS_CONNECTION_TAB_SHOWN_IMMEDIATELY.
441 if (presenter_) {
442 presenter_->RecordWebsiteSettingsAction(
443 WebsiteSettings::WEBSITE_SETTINGS_CONNECTION_TAB_SELECTED);
445 break;
446 default:
447 NOTREACHED();
449 tabbed_pane_->GetSelectedTab()->Layout();
450 SizeToContents();
453 gfx::Size WebsiteSettingsPopupView::GetPreferredSize() const {
454 if (header_ == nullptr && tabbed_pane_ == nullptr)
455 return views::View::GetPreferredSize();
457 int height = 0;
458 if (header_)
459 height += header_->GetPreferredSize().height() + kHeaderMarginBottom;
460 if (tabbed_pane_)
461 height += tabbed_pane_->GetPreferredSize().height();
463 int width = kPermissionsSectionContentMinWidth;
464 if (site_data_content_)
465 width = std::max(width, site_data_content_->GetPreferredSize().width());
466 if (permissions_content_)
467 width = std::max(width, permissions_content_->GetPreferredSize().width());
468 if (header_)
469 width = std::max(width, header_->GetPreferredNameWidth());
470 width += kPermissionsSectionPaddingLeft + kPermissionsSectionPaddingRight;
471 width = std::min(width, kMaxPopupWidth);
472 return gfx::Size(width, height);
475 void WebsiteSettingsPopupView::SetCookieInfo(
476 const CookieInfoList& cookie_info_list) {
477 site_data_content_->RemoveAllChildViews(true);
479 views::GridLayout* layout = new views::GridLayout(site_data_content_);
480 site_data_content_->SetLayoutManager(layout);
482 const int site_data_content_column = 0;
483 views::ColumnSet* column_set =
484 layout->AddColumnSet(site_data_content_column);
485 column_set->AddColumn(views::GridLayout::FILL,
486 views::GridLayout::FILL,
488 views::GridLayout::FIXED,
489 kSiteDataIconColumnWidth,
491 column_set->AddPaddingColumn(0, kIconMarginLeft);
492 column_set->AddColumn(views::GridLayout::FILL,
493 views::GridLayout::FILL,
495 views::GridLayout::USE_PREF,
498 // No padding. This third column is for |third_party_label_text| (see below),
499 // and the text needs to flow naturally from the |first_party_label_text|
500 // link.
501 column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
502 views::GridLayout::USE_PREF, 0, 0);
504 layout->AddPaddingRow(1, 5);
506 // |cookie_info_list| should only ever have 2 items: first- and third-party
507 // cookies.
508 DCHECK_EQ(cookie_info_list.size(), 2u);
509 base::string16 first_party_label_text;
510 base::string16 third_party_label_text;
511 for (const auto& i : cookie_info_list) {
512 if (i.is_first_party) {
513 first_party_label_text =
514 l10n_util::GetStringFUTF16(IDS_WEBSITE_SETTINGS_FIRST_PARTY_SITE_DATA,
515 base::IntToString16(i.allowed));
516 } else {
517 third_party_label_text =
518 l10n_util::GetStringFUTF16(IDS_WEBSITE_SETTINGS_THIRD_PARTY_SITE_DATA,
519 base::IntToString16(i.allowed));
523 cookie_dialog_link_ = new views::Link(first_party_label_text);
524 cookie_dialog_link_->set_listener(this);
526 layout->StartRow(1, site_data_content_column);
527 WebsiteSettingsUI::PermissionInfo info;
528 info.type = CONTENT_SETTINGS_TYPE_COOKIES;
529 info.setting = CONTENT_SETTING_ALLOW;
530 views::ImageView* icon = new views::ImageView();
531 const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon(info);
532 icon->SetImage(image.ToImageSkia());
533 layout->AddView(icon, 1, 1, views::GridLayout::CENTER,
534 views::GridLayout::CENTER);
535 layout->AddView(cookie_dialog_link_, 1, 1, views::GridLayout::CENTER,
536 views::GridLayout::CENTER);
537 base::string16 comma = base::ASCIIToUTF16(", ");
539 layout->AddView(new views::Label(comma + third_party_label_text), 1, 1,
540 views::GridLayout::LEADING, views::GridLayout::CENTER);
542 layout->AddPaddingRow(1, 6);
544 layout->Layout(site_data_content_);
545 SizeToContents();
548 void WebsiteSettingsPopupView::SetPermissionInfo(
549 const PermissionInfoList& permission_info_list) {
550 // When a permission is changed, WebsiteSettings::OnSitePermissionChanged()
551 // calls this method with updated permissions. However, PermissionSelectorView
552 // will have already updated its state, so it's already reflected in the UI.
553 // In addition, if a permission is set to the default setting, WebsiteSettings
554 // removes it from |permission_info_list|, but the button should remain.
555 if (permissions_content_)
556 return;
558 permissions_content_ = new views::View();
559 views::GridLayout* layout = new views::GridLayout(permissions_content_);
560 permissions_content_->SetLayoutManager(layout);
562 base::string16 headline =
563 permission_info_list.empty()
564 ? base::string16()
565 : l10n_util::GetStringUTF16(
566 IDS_WEBSITE_SETTINGS_TITLE_SITE_PERMISSIONS);
567 views::View* permissions_section =
568 CreateSection(headline, permissions_content_, nullptr);
569 permissions_tab_->AddChildView(permissions_section);
571 const int content_column = 0;
572 views::ColumnSet* column_set = layout->AddColumnSet(content_column);
573 column_set->AddColumn(views::GridLayout::FILL,
574 views::GridLayout::FILL,
576 views::GridLayout::USE_PREF,
579 for (PermissionInfoList::const_iterator permission =
580 permission_info_list.begin();
581 permission != permission_info_list.end();
582 ++permission) {
583 layout->StartRow(1, content_column);
584 PermissionSelectorView* selector = new PermissionSelectorView(
585 web_contents_ ? web_contents_->GetURL() : GURL::EmptyGURL(),
586 *permission);
587 selector->AddObserver(this);
588 layout->AddView(selector,
591 views::GridLayout::LEADING,
592 views::GridLayout::CENTER);
593 layout->AddPaddingRow(1, kPermissionsSectionRowSpacing);
596 layout->Layout(permissions_content_);
598 // Add site settings link.
599 site_settings_link_ = new views::Link(
600 l10n_util::GetStringUTF16(IDS_PAGE_INFO_SITE_SETTINGS_LINK));
601 site_settings_link_->set_listener(this);
602 views::View* link_section = new views::View();
603 const int kLinkMarginTop = 4;
604 link_section->SetLayoutManager(
605 new views::BoxLayout(views::BoxLayout::kHorizontal,
606 kConnectionSectionPaddingLeft, kLinkMarginTop, 0));
607 link_section->AddChildView(site_settings_link_);
608 permissions_tab_->AddChildView(link_section);
610 SizeToContents();
613 void WebsiteSettingsPopupView::SetIdentityInfo(
614 const IdentityInfo& identity_info) {
615 base::string16 identity_status_text = identity_info.GetSecuritySummary();
616 header_->SetIdentityName(base::UTF8ToUTF16(identity_info.site_identity));
617 header_->SetIdentityStatus(identity_status_text, SK_ColorBLACK);
619 // The headline and the certificate dialog link of the site's identity
620 // section is only displayed if the site's identity was verified. If the
621 // site's identity was verified, then the headline contains the organization
622 // name from the provided certificate. If the organization name is not
623 // available than the hostname of the site is used instead.
624 base::string16 headline;
625 if (identity_info.cert_id) {
626 cert_id_ = identity_info.cert_id;
628 certificate_dialog_link_ = new views::Link(
629 l10n_util::GetStringUTF16(IDS_PAGEINFO_CERT_INFO_BUTTON));
630 certificate_dialog_link_->set_listener(this);
632 if (identity_info.show_ssl_decision_revoke_button) {
633 reset_decisions_button_ = new views::LabelButton(
634 this,
635 l10n_util::GetStringUTF16(
636 IDS_PAGEINFO_RESET_INVALID_CERTIFICATE_DECISIONS_BUTTON));
637 reset_decisions_button_->SetStyle(views::Button::STYLE_BUTTON);
640 headline = base::UTF8ToUTF16(identity_info.site_identity);
642 ResetConnectionSection(
643 identity_info_content_,
644 WebsiteSettingsUI::GetIdentityIcon(identity_info.identity_status),
645 base::string16(), // The identity section has no headline.
646 base::UTF8ToUTF16(identity_info.identity_status_description),
647 certificate_dialog_link_,
648 reset_decisions_button_);
650 ResetConnectionSection(
651 connection_info_content_,
652 WebsiteSettingsUI::GetConnectionIcon(identity_info.connection_status),
653 base::string16(), // The connection section has no headline.
654 base::UTF8ToUTF16(identity_info.connection_status_description),
655 nullptr,
656 nullptr);
658 connection_tab_->InvalidateLayout();
659 Layout();
660 SizeToContents();
663 void WebsiteSettingsPopupView::SetSelectedTab(TabId tab_id) {
664 tabbed_pane_->SelectTabAt(tab_id);
667 views::View* WebsiteSettingsPopupView::CreatePermissionsTab() {
668 views::View* pane = new views::View();
669 pane->SetLayoutManager(
670 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
672 // Add cookies and site data section.
673 site_data_content_ = new views::View();
674 views::View* site_data_section = CreateSection(
675 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TITLE_SITE_DATA),
676 site_data_content_, NULL);
677 pane->AddChildView(site_data_section);
679 return pane;
682 views::View* WebsiteSettingsPopupView::CreateConnectionTab() {
683 views::View* pane = new views::View();
684 pane->SetLayoutManager(
685 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
687 // Add site identity section.
688 identity_info_content_ = new views::View();
689 pane->AddChildView(identity_info_content_);
691 // Add connection section.
692 pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL));
693 connection_info_content_ = new views::View();
694 pane->AddChildView(connection_info_content_);
696 // Add help center link.
697 pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL));
698 help_center_link_ = new views::Link(
699 l10n_util::GetStringUTF16(IDS_PAGE_INFO_HELP_CENTER_LINK));
700 help_center_link_->set_listener(this);
701 help_center_content_ = new views::View();
702 views::View* link_section =
703 CreateSection(base::string16(),
704 help_center_content_,
705 help_center_link_);
706 link_section->AddChildView(help_center_link_);
707 pane->AddChildView(link_section);
708 return pane;
711 views::View* WebsiteSettingsPopupView::CreateSection(
712 const base::string16& headline_text,
713 views::View* content,
714 views::Link* link) {
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 if (headline_text.length() > 0) {
729 layout->AddPaddingRow(1, kPermissionsSectionPaddingTop);
730 layout->StartRow(1, content_column);
731 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
732 views::Label* headline = new views::Label(
733 headline_text, rb.GetFontList(ui::ResourceBundle::BoldFont));
734 layout->AddView(headline, 1, 1, views::GridLayout::LEADING,
735 views::GridLayout::CENTER);
738 layout->AddPaddingRow(1, kPermissionsSectionHeadlineMarginBottom);
739 layout->StartRow(1, content_column);
740 layout->AddView(content, 1, 1, views::GridLayout::LEADING,
741 views::GridLayout::CENTER);
743 if (link) {
744 layout->AddPaddingRow(1, 4);
745 layout->StartRow(1, content_column);
746 layout->AddView(link, 1, 1, views::GridLayout::LEADING,
747 views::GridLayout::CENTER);
750 layout->AddPaddingRow(1, kPermissionsSectionPaddingBottom);
751 return container;
754 void WebsiteSettingsPopupView::ResetConnectionSection(
755 views::View* section_container,
756 const gfx::Image& icon,
757 const base::string16& headline,
758 const base::string16& text,
759 views::Link* link,
760 views::LabelButton* reset_decisions_button) {
761 section_container->RemoveAllChildViews(true);
763 views::GridLayout* layout = new views::GridLayout(section_container);
764 section_container->SetLayoutManager(layout);
765 views::ColumnSet* column_set = layout->AddColumnSet(0);
766 column_set->AddPaddingColumn(0, kConnectionSectionPaddingLeft);
767 column_set->AddColumn(views::GridLayout::LEADING,
768 views::GridLayout::LEADING,
770 views::GridLayout::USE_PREF,
773 column_set->AddPaddingColumn(0, kIconMarginLeft);
774 column_set->AddColumn(views::GridLayout::FILL,
775 views::GridLayout::FILL,
777 views::GridLayout::USE_PREF,
780 column_set->AddPaddingColumn(0, kConnectionSectionPaddingRight);
782 layout->AddPaddingRow(0, kConnectionSectionPaddingTop);
783 layout->StartRow(1, 0);
785 // Add status icon.
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);
822 if (link) {
823 content_layout->StartRow(1, 0);
824 content_layout->AddView(link);
827 if (reset_decisions_button) {
828 content_layout->StartRow(1, 0);
829 content_layout->AddView(reset_decisions_button);
832 layout->AddView(content_pane, 1, 1, views::GridLayout::LEADING,
833 views::GridLayout::LEADING);
834 layout->AddPaddingRow(0, kConnectionSectionPaddingBottom);
837 void WebsiteSettingsPopupView::HandleLinkClickedAsync(views::Link* source) {
838 if (source == cookie_dialog_link_) {
839 // Count how often the Collected Cookies dialog is opened.
840 presenter_->RecordWebsiteSettingsAction(
841 WebsiteSettings::WEBSITE_SETTINGS_COOKIES_DIALOG_OPENED);
843 if (web_contents_ != NULL)
844 new CollectedCookiesViews(web_contents_);
845 } else if (source == certificate_dialog_link_) {
846 gfx::NativeWindow parent = GetAnchorView() ?
847 GetAnchorView()->GetWidget()->GetNativeWindow() : nullptr;
848 presenter_->RecordWebsiteSettingsAction(
849 WebsiteSettings::WEBSITE_SETTINGS_CERTIFICATE_DIALOG_OPENED);
850 ShowCertificateViewerByID(web_contents_, parent, cert_id_);
851 } else if (source == help_center_link_) {
852 web_contents_->OpenURL(content::OpenURLParams(
853 GURL(chrome::kPageInfoHelpCenterURL), content::Referrer(),
854 NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_LINK, false));
855 presenter_->RecordWebsiteSettingsAction(
856 WebsiteSettings::WEBSITE_SETTINGS_CONNECTION_HELP_OPENED);
857 } else if (source == site_settings_link_) {
858 // TODO(palmer): This opens the general Content Settings pane, which is OK
859 // for now. But on Android, it opens a page specific to a given origin that
860 // shows all of the settings for that origin. If/when that's available on
861 // desktop we should link to that here, too.
862 web_contents_->OpenURL(content::OpenURLParams(
863 GURL(chrome::kChromeUIContentSettingsURL), content::Referrer(),
864 NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_LINK, false));
865 presenter_->RecordWebsiteSettingsAction(
866 WebsiteSettings::WEBSITE_SETTINGS_SITE_SETTINGS_OPENED);
867 } else {
868 NOTREACHED();