1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/views/website_settings/website_settings_popup_view.h"
9 #include "base/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"
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
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;
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
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 kPermissionsSectionPaddingTop
= 16;
103 // Space between the headline and the content of a section on the permissions
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;
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
{
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
128 void SetIdentityStatus(const base::string16
& status_text
, SkColor text_color
);
131 // The label that displays the name of the site's identity.
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
142 class InternalPageInfoPopupView
: public views::BubbleDelegateView
{
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
;
154 friend class WebsiteSettingsPopupView
;
156 DISALLOW_COPY_AND_ASSIGN(InternalPageInfoPopupView
);
159 ////////////////////////////////////////////////////////////////////////////////
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
);
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() {
280 void WebsiteSettingsPopupView::ShowPopup(
281 views::View
* anchor_view
,
282 const gfx::Rect
& anchor_rect
,
284 content::WebContents
* web_contents
,
286 const SecurityStateModel::SecurityInfo
& security_info
) {
287 is_popup_showing
= true;
288 gfx::NativeView parent_window
=
289 anchor_view
? nullptr : web_contents
->GetNativeView();
290 if (InternalChromePage(url
)) {
291 // Use the concrete type so that |SetAnchorRect| can be called as a friend.
292 InternalPageInfoPopupView
* popup
=
293 new InternalPageInfoPopupView(anchor_view
, parent_window
);
295 popup
->SetAnchorRect(anchor_rect
);
296 popup
->GetWidget()->Show();
298 WebsiteSettingsPopupView
* popup
= new WebsiteSettingsPopupView(
299 anchor_view
, parent_window
, profile
, web_contents
, url
, security_info
);
301 popup
->SetAnchorRect(anchor_rect
);
302 popup
->GetWidget()->Show();
307 bool WebsiteSettingsPopupView::IsPopupShowing() {
308 return is_popup_showing
;
311 WebsiteSettingsPopupView::WebsiteSettingsPopupView(
312 views::View
* anchor_view
,
313 gfx::NativeView parent_window
,
315 content::WebContents
* web_contents
,
317 const SecurityStateModel::SecurityInfo
& security_info
)
318 : content::WebContentsObserver(web_contents
),
319 BubbleDelegateView(anchor_view
, views::BubbleBorder::TOP_LEFT
),
320 web_contents_(web_contents
),
322 tabbed_pane_(nullptr),
323 permissions_tab_(nullptr),
324 site_data_content_(nullptr),
325 cookie_dialog_link_(nullptr),
326 permissions_content_(nullptr),
327 connection_tab_(nullptr),
328 identity_info_content_(nullptr),
329 certificate_dialog_link_(nullptr),
330 reset_decisions_button_(nullptr),
331 help_center_content_(nullptr),
333 help_center_link_(nullptr),
334 connection_info_content_(nullptr),
335 weak_factory_(this) {
336 set_parent_window(parent_window
);
338 // Compensate for built-in vertical padding in the anchor view's image.
339 set_anchor_view_insets(gfx::Insets(kLocationIconVerticalMargin
, 0,
340 kLocationIconVerticalMargin
, 0));
342 views::GridLayout
* layout
= new views::GridLayout(this);
343 SetLayoutManager(layout
);
344 const int content_column
= 0;
345 views::ColumnSet
* column_set
= layout
->AddColumnSet(content_column
);
346 column_set
->AddColumn(views::GridLayout::FILL
,
347 views::GridLayout::FILL
,
349 views::GridLayout::USE_PREF
,
353 header_
= new PopupHeaderView(this);
354 layout
->StartRow(1, content_column
);
355 layout
->AddView(header_
);
357 layout
->AddPaddingRow(1, kHeaderMarginBottom
);
358 tabbed_pane_
= new views::TabbedPane();
359 layout
->StartRow(1, content_column
);
360 layout
->AddView(tabbed_pane_
);
362 // Tabs must be added after the |tabbed_pane_| was added to the views
363 // hierarchy. Adding the |tabbed_pane_| to the views hierarchy triggers the
364 // initialization of the native tab UI element. If the native tab UI element
365 // is not initialized, adding a tab will result in a NULL pointer exception.
366 permissions_tab_
= CreatePermissionsTab();
367 tabbed_pane_
->AddTabAtIndex(
369 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TAB_LABEL_PERMISSIONS
),
371 connection_tab_
= CreateConnectionTab();
372 tabbed_pane_
->AddTabAtIndex(
374 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TAB_LABEL_CONNECTION
),
376 DCHECK_EQ(tabbed_pane_
->GetTabCount(), NUM_TAB_IDS
);
377 tabbed_pane_
->set_listener(this);
379 set_margins(gfx::Insets(kPopupMarginTop
, kPopupMarginLeft
,
380 kPopupMarginBottom
, kPopupMarginRight
));
382 views::BubbleDelegateView::CreateBubble(this);
384 presenter_
.reset(new WebsiteSettings(
385 this, profile
, TabSpecificContentSettings::FromWebContents(web_contents
),
386 web_contents
, url
, security_info
, content::CertStore::GetInstance()));
389 void WebsiteSettingsPopupView::RenderFrameDeleted(
390 content::RenderFrameHost
* render_frame_host
) {
391 if (render_frame_host
== web_contents_
->GetMainFrame()) {
392 GetWidget()->Close();
396 void WebsiteSettingsPopupView::OnPermissionChanged(
397 const WebsiteSettingsUI::PermissionInfo
& permission
) {
398 presenter_
->OnSitePermissionChanged(permission
.type
, permission
.setting
);
401 void WebsiteSettingsPopupView::OnWidgetDestroying(views::Widget
* widget
) {
402 is_popup_showing
= false;
403 presenter_
->OnUIClosing();
406 void WebsiteSettingsPopupView::ButtonPressed(views::Button
* button
,
407 const ui::Event
& event
) {
408 if (button
== reset_decisions_button_
)
409 presenter_
->OnRevokeSSLErrorBypassButtonPressed();
410 GetWidget()->Close();
413 void WebsiteSettingsPopupView::LinkClicked(views::Link
* source
,
415 // The popup closes automatically when the collected cookies dialog or the
416 // certificate viewer opens. So delay handling of the link clicked to avoid
417 // a crash in the base class which needs to complete the mouse event handling.
418 content::BrowserThread::PostTask(
419 content::BrowserThread::UI
, FROM_HERE
,
420 base::Bind(&WebsiteSettingsPopupView::HandleLinkClickedAsync
,
421 weak_factory_
.GetWeakPtr(), source
));
424 void WebsiteSettingsPopupView::TabSelectedAt(int index
) {
426 case TAB_ID_PERMISSIONS
:
427 presenter_
->RecordWebsiteSettingsAction(
428 WebsiteSettings::WEBSITE_SETTINGS_PERMISSIONS_TAB_SELECTED
);
430 case TAB_ID_CONNECTION
:
431 // If the Connection tab is selected first, we're still inside the
432 // construction of presenter_. In that case, the action is already logged
433 // by WEBSITE_SETTINGS_CONNECTION_TAB_SHOWN_IMMEDIATELY.
435 presenter_
->RecordWebsiteSettingsAction(
436 WebsiteSettings::WEBSITE_SETTINGS_CONNECTION_TAB_SELECTED
);
442 tabbed_pane_
->GetSelectedTab()->Layout();
446 gfx::Size
WebsiteSettingsPopupView::GetPreferredSize() const {
447 if (header_
== nullptr && tabbed_pane_
== nullptr)
448 return views::View::GetPreferredSize();
452 height
+= header_
->GetPreferredSize().height() + kHeaderMarginBottom
;
454 height
+= tabbed_pane_
->GetPreferredSize().height();
456 int width
= kPermissionsSectionContentMinWidth
;
457 if (site_data_content_
)
458 width
= std::max(width
, site_data_content_
->GetPreferredSize().width());
459 if (permissions_content_
)
460 width
= std::max(width
, permissions_content_
->GetPreferredSize().width());
462 width
= std::max(width
, header_
->GetPreferredSize().width());
463 width
+= kPermissionsSectionPaddingLeft
;
464 width
= std::min(width
, kMaxPopupWidth
);
465 return gfx::Size(width
, height
);
468 void WebsiteSettingsPopupView::SetCookieInfo(
469 const CookieInfoList
& cookie_info_list
) {
470 site_data_content_
->RemoveAllChildViews(true);
472 views::GridLayout
* layout
= new views::GridLayout(site_data_content_
);
473 site_data_content_
->SetLayoutManager(layout
);
475 const int site_data_content_column
= 0;
476 views::ColumnSet
* column_set
=
477 layout
->AddColumnSet(site_data_content_column
);
478 column_set
->AddColumn(views::GridLayout::FILL
,
479 views::GridLayout::FILL
,
481 views::GridLayout::FIXED
,
482 kSiteDataIconColumnWidth
,
484 column_set
->AddPaddingColumn(0, kIconMarginLeft
);
485 column_set
->AddColumn(views::GridLayout::FILL
,
486 views::GridLayout::FILL
,
488 views::GridLayout::USE_PREF
,
491 // No padding. This third column is for |third_party_label_text| (see below),
492 // and the text needs to flow naturally from the |first_party_label_text|
494 column_set
->AddColumn(views::GridLayout::FILL
, views::GridLayout::FILL
, 1,
495 views::GridLayout::USE_PREF
, 0, 0);
497 layout
->AddPaddingRow(1, 5);
499 // |cookie_info_list| should only ever have 2 items: first- and third-party
501 DCHECK_EQ(cookie_info_list
.size(), 2u);
502 base::string16 first_party_label_text
;
503 base::string16 third_party_label_text
;
504 for (const auto& i
: cookie_info_list
) {
505 if (i
.is_first_party
) {
506 first_party_label_text
=
507 l10n_util::GetStringFUTF16(IDS_WEBSITE_SETTINGS_FIRST_PARTY_SITE_DATA
,
508 base::IntToString16(i
.allowed
));
510 third_party_label_text
=
511 l10n_util::GetStringFUTF16(IDS_WEBSITE_SETTINGS_THIRD_PARTY_SITE_DATA
,
512 base::IntToString16(i
.allowed
));
516 cookie_dialog_link_
= new views::Link(first_party_label_text
);
517 cookie_dialog_link_
->set_listener(this);
519 layout
->StartRow(1, site_data_content_column
);
520 WebsiteSettingsUI::PermissionInfo info
;
521 info
.type
= CONTENT_SETTINGS_TYPE_COOKIES
;
522 info
.setting
= CONTENT_SETTING_ALLOW
;
523 views::ImageView
* icon
= new views::ImageView();
524 const gfx::Image
& image
= WebsiteSettingsUI::GetPermissionIcon(info
);
525 icon
->SetImage(image
.ToImageSkia());
526 layout
->AddView(icon
, 1, 1, views::GridLayout::CENTER
,
527 views::GridLayout::CENTER
);
528 layout
->AddView(cookie_dialog_link_
, 1, 1, views::GridLayout::CENTER
,
529 views::GridLayout::CENTER
);
530 base::string16 comma
= base::ASCIIToUTF16(", ");
532 layout
->AddView(new views::Label(comma
+ third_party_label_text
), 1, 1,
533 views::GridLayout::LEADING
, views::GridLayout::CENTER
);
535 layout
->AddPaddingRow(1, 6);
537 layout
->Layout(site_data_content_
);
541 void WebsiteSettingsPopupView::SetPermissionInfo(
542 const PermissionInfoList
& permission_info_list
) {
543 // When a permission is changed, WebsiteSettings::OnSitePermissionChanged()
544 // calls this method with updated permissions. However, PermissionSelectorView
545 // will have already updated its state, so it's already reflected in the UI.
546 // In addition, if a permission is set to the default setting, WebsiteSettings
547 // removes it from |permission_info_list|, but the button should remain.
548 if (permissions_content_
)
551 permissions_content_
= new views::View();
552 views::GridLayout
* layout
= new views::GridLayout(permissions_content_
);
553 permissions_content_
->SetLayoutManager(layout
);
555 base::string16 headline
=
556 permission_info_list
.empty()
558 : l10n_util::GetStringUTF16(
559 IDS_WEBSITE_SETTINGS_TITLE_SITE_PERMISSIONS
);
560 views::View
* permissions_section
=
561 CreateSection(headline
, permissions_content_
, nullptr);
562 permissions_tab_
->AddChildView(permissions_section
);
564 const int content_column
= 0;
565 views::ColumnSet
* column_set
= layout
->AddColumnSet(content_column
);
566 column_set
->AddColumn(views::GridLayout::FILL
,
567 views::GridLayout::FILL
,
569 views::GridLayout::USE_PREF
,
572 for (PermissionInfoList::const_iterator permission
=
573 permission_info_list
.begin();
574 permission
!= permission_info_list
.end();
576 layout
->StartRow(1, content_column
);
577 PermissionSelectorView
* selector
= new PermissionSelectorView(
578 web_contents_
? web_contents_
->GetURL() : GURL::EmptyGURL(),
580 selector
->AddObserver(this);
581 layout
->AddView(selector
,
584 views::GridLayout::LEADING
,
585 views::GridLayout::CENTER
);
586 layout
->AddPaddingRow(1, kPermissionsSectionRowSpacing
);
589 layout
->Layout(permissions_content_
);
591 // Add site settings link.
592 site_settings_link_
= new views::Link(
593 l10n_util::GetStringUTF16(IDS_PAGE_INFO_SITE_SETTINGS_LINK
));
594 site_settings_link_
->set_listener(this);
595 views::View
* link_section
= new views::View();
596 const int kLinkMarginTop
= 4;
597 link_section
->SetLayoutManager(
598 new views::BoxLayout(views::BoxLayout::kHorizontal
,
599 kConnectionSectionPaddingLeft
, kLinkMarginTop
, 0));
600 link_section
->AddChildView(site_settings_link_
);
601 permissions_tab_
->AddChildView(link_section
);
606 void WebsiteSettingsPopupView::SetIdentityInfo(
607 const IdentityInfo
& identity_info
) {
608 base::string16 identity_status_text
= identity_info
.GetSecuritySummary();
609 header_
->SetIdentityName(base::UTF8ToUTF16(identity_info
.site_identity
));
610 header_
->SetIdentityStatus(identity_status_text
, SK_ColorBLACK
);
612 // The headline and the certificate dialog link of the site's identity
613 // section is only displayed if the site's identity was verified. If the
614 // site's identity was verified, then the headline contains the organization
615 // name from the provided certificate. If the organization name is not
616 // available than the hostname of the site is used instead.
617 base::string16 headline
;
618 if (identity_info
.cert_id
) {
619 cert_id_
= identity_info
.cert_id
;
621 certificate_dialog_link_
= new views::Link(
622 l10n_util::GetStringUTF16(IDS_PAGEINFO_CERT_INFO_BUTTON
));
623 certificate_dialog_link_
->set_listener(this);
625 if (identity_info
.show_ssl_decision_revoke_button
) {
626 reset_decisions_button_
= new views::LabelButton(
628 l10n_util::GetStringUTF16(
629 IDS_PAGEINFO_RESET_INVALID_CERTIFICATE_DECISIONS_BUTTON
));
630 reset_decisions_button_
->SetStyle(views::Button::STYLE_BUTTON
);
633 headline
= base::UTF8ToUTF16(identity_info
.site_identity
);
635 ResetConnectionSection(
636 identity_info_content_
,
637 WebsiteSettingsUI::GetIdentityIcon(identity_info
.identity_status
),
638 base::string16(), // The identity section has no headline.
639 base::UTF8ToUTF16(identity_info
.identity_status_description
),
640 certificate_dialog_link_
,
641 reset_decisions_button_
);
643 ResetConnectionSection(
644 connection_info_content_
,
645 WebsiteSettingsUI::GetConnectionIcon(identity_info
.connection_status
),
646 base::string16(), // The connection section has no headline.
647 base::UTF8ToUTF16(identity_info
.connection_status_description
),
651 connection_tab_
->InvalidateLayout();
656 void WebsiteSettingsPopupView::SetSelectedTab(TabId tab_id
) {
657 tabbed_pane_
->SelectTabAt(tab_id
);
660 views::View
* WebsiteSettingsPopupView::CreatePermissionsTab() {
661 views::View
* pane
= new views::View();
662 pane
->SetLayoutManager(
663 new views::BoxLayout(views::BoxLayout::kVertical
, 0, 0, 1));
665 // Add cookies and site data section.
666 site_data_content_
= new views::View();
667 views::View
* site_data_section
= CreateSection(
668 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TITLE_SITE_DATA
),
669 site_data_content_
, NULL
);
670 pane
->AddChildView(site_data_section
);
675 views::View
* WebsiteSettingsPopupView::CreateConnectionTab() {
676 views::View
* pane
= new views::View();
677 pane
->SetLayoutManager(
678 new views::BoxLayout(views::BoxLayout::kVertical
, 0, 0, 1));
680 // Add site identity section.
681 identity_info_content_
= new views::View();
682 pane
->AddChildView(identity_info_content_
);
684 // Add connection section.
685 pane
->AddChildView(new views::Separator(views::Separator::HORIZONTAL
));
686 connection_info_content_
= new views::View();
687 pane
->AddChildView(connection_info_content_
);
689 // Add help center link.
690 pane
->AddChildView(new views::Separator(views::Separator::HORIZONTAL
));
691 help_center_link_
= new views::Link(
692 l10n_util::GetStringUTF16(IDS_PAGE_INFO_HELP_CENTER_LINK
));
693 help_center_link_
->set_listener(this);
694 help_center_content_
= new views::View();
695 views::View
* link_section
=
696 CreateSection(base::string16(),
697 help_center_content_
,
699 link_section
->AddChildView(help_center_link_
);
700 pane
->AddChildView(link_section
);
704 views::View
* WebsiteSettingsPopupView::CreateSection(
705 const base::string16
& headline_text
,
706 views::View
* content
,
708 views::View
* container
= new views::View();
709 views::GridLayout
* layout
= new views::GridLayout(container
);
710 container
->SetLayoutManager(layout
);
711 const int content_column
= 0;
712 views::ColumnSet
* column_set
= layout
->AddColumnSet(content_column
);
713 column_set
->AddPaddingColumn(0, kPermissionsSectionPaddingLeft
);
714 column_set
->AddColumn(views::GridLayout::FILL
,
715 views::GridLayout::FILL
,
717 views::GridLayout::USE_PREF
,
721 if (headline_text
.length() > 0) {
722 layout
->AddPaddingRow(1, kPermissionsSectionPaddingTop
);
723 layout
->StartRow(1, content_column
);
724 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
725 views::Label
* headline
= new views::Label(
726 headline_text
, rb
.GetFontList(ui::ResourceBundle::BoldFont
));
727 layout
->AddView(headline
, 1, 1, views::GridLayout::LEADING
,
728 views::GridLayout::CENTER
);
731 layout
->AddPaddingRow(1, kPermissionsSectionHeadlineMarginBottom
);
732 layout
->StartRow(1, content_column
);
733 layout
->AddView(content
, 1, 1, views::GridLayout::LEADING
,
734 views::GridLayout::CENTER
);
737 layout
->AddPaddingRow(1, 4);
738 layout
->StartRow(1, content_column
);
739 layout
->AddView(link
, 1, 1, views::GridLayout::LEADING
,
740 views::GridLayout::CENTER
);
743 layout
->AddPaddingRow(1, kPermissionsSectionPaddingBottom
);
747 void WebsiteSettingsPopupView::ResetConnectionSection(
748 views::View
* section_container
,
749 const gfx::Image
& icon
,
750 const base::string16
& headline
,
751 const base::string16
& text
,
753 views::LabelButton
* reset_decisions_button
) {
754 section_container
->RemoveAllChildViews(true);
756 views::GridLayout
* layout
= new views::GridLayout(section_container
);
757 section_container
->SetLayoutManager(layout
);
758 views::ColumnSet
* column_set
= layout
->AddColumnSet(0);
759 column_set
->AddPaddingColumn(0, kConnectionSectionPaddingLeft
);
760 column_set
->AddColumn(views::GridLayout::LEADING
,
761 views::GridLayout::LEADING
,
763 views::GridLayout::USE_PREF
,
766 column_set
->AddPaddingColumn(0, kIconMarginLeft
);
767 column_set
->AddColumn(views::GridLayout::FILL
,
768 views::GridLayout::FILL
,
770 views::GridLayout::USE_PREF
,
773 column_set
->AddPaddingColumn(0, kConnectionSectionPaddingRight
);
776 layout
->AddPaddingRow(0, kConnectionSectionPaddingTop
);
777 layout
->StartRow(1, 0);
780 views::ImageView
* icon_view
= new views::ImageView();
781 icon_view
->SetImage(*icon
.ToImageSkia());
782 layout
->AddView(icon_view
, 1, 1, views::GridLayout::LEADING
,
783 views::GridLayout::LEADING
);
785 // Add section content.
786 views::View
* content_pane
= new views::View();
787 views::GridLayout
* content_layout
= new views::GridLayout(content_pane
);
788 content_pane
->SetLayoutManager(content_layout
);
789 views::ColumnSet
* content_column_set
= content_layout
->AddColumnSet(0);
790 content_column_set
->AddColumn(views::GridLayout::LEADING
,
791 views::GridLayout::LEADING
,
793 views::GridLayout::USE_PREF
,
796 if (!headline
.empty()) {
797 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
798 views::Label
* headline_label
= new views::Label(
799 headline
, rb
.GetFontList(ui::ResourceBundle::BoldFont
));
800 headline_label
->SetMultiLine(true);
801 headline_label
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
802 // Allow linebreaking in the middle of words if necessary, so that extremely
803 // long hostnames (longer than one line) will still be completely shown.
804 headline_label
->SetAllowCharacterBreak(true);
805 content_layout
->StartRow(1, 0);
806 content_layout
->AddView(headline_label
);
809 views::Label
* description_label
= new views::Label(text
);
810 description_label
->SetMultiLine(true);
811 description_label
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
812 description_label
->SetAllowCharacterBreak(true);
813 content_layout
->StartRow(1, 0);
814 content_layout
->AddView(description_label
);
817 content_layout
->StartRow(1, 0);
818 content_layout
->AddView(link
);
821 if (reset_decisions_button
) {
822 content_layout
->StartRow(1, 0);
823 content_layout
->AddView(reset_decisions_button
);
826 layout
->AddView(content_pane
, 1, 1, views::GridLayout::LEADING
,
827 views::GridLayout::LEADING
);
828 layout
->AddPaddingRow(0, kConnectionSectionPaddingBottom
);
831 void WebsiteSettingsPopupView::HandleLinkClickedAsync(views::Link
* source
) {
832 if (source
== cookie_dialog_link_
) {
833 // Count how often the Collected Cookies dialog is opened.
834 presenter_
->RecordWebsiteSettingsAction(
835 WebsiteSettings::WEBSITE_SETTINGS_COOKIES_DIALOG_OPENED
);
837 if (web_contents_
!= NULL
)
838 new CollectedCookiesViews(web_contents_
);
839 } else if (source
== certificate_dialog_link_
) {
840 gfx::NativeWindow parent
= GetAnchorView() ?
841 GetAnchorView()->GetWidget()->GetNativeWindow() : nullptr;
842 presenter_
->RecordWebsiteSettingsAction(
843 WebsiteSettings::WEBSITE_SETTINGS_CERTIFICATE_DIALOG_OPENED
);
844 ShowCertificateViewerByID(web_contents_
, parent
, cert_id_
);
845 } else if (source
== help_center_link_
) {
846 web_contents_
->OpenURL(content::OpenURLParams(
847 GURL(chrome::kPageInfoHelpCenterURL
), content::Referrer(),
848 NEW_FOREGROUND_TAB
, ui::PAGE_TRANSITION_LINK
, false));
849 presenter_
->RecordWebsiteSettingsAction(
850 WebsiteSettings::WEBSITE_SETTINGS_CONNECTION_HELP_OPENED
);
851 } else if (source
== site_settings_link_
) {
852 // TODO(palmer): This opens the general Content Settings pane, which is OK
853 // for now. But on Android, it opens a page specific to a given origin that
854 // shows all of the settings for that origin. If/when that's available on
855 // desktop we should link to that here, too.
856 web_contents_
->OpenURL(content::OpenURLParams(
857 GURL(chrome::kChromeUIContentSettingsURL
), content::Referrer(),
858 NEW_FOREGROUND_TAB
, ui::PAGE_TRANSITION_LINK
, false));
859 presenter_
->RecordWebsiteSettingsAction(
860 WebsiteSettings::WEBSITE_SETTINGS_SITE_SETTINGS_OPENED
);