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 kPermissionsSectionPaddingRight
= 18;
102 const int kPermissionsSectionPaddingTop
= 16;
104 // Space between the headline and the content of a section on the permissions
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;
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
{
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
129 void SetIdentityStatus(const base::string16
& status_text
, SkColor text_color
);
131 int GetPreferredNameWidth() const;
134 // The label that displays the name of the site's identity.
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
145 class InternalPageInfoPopupView
: public views::BubbleDelegateView
{
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
;
157 friend class WebsiteSettingsPopupView
;
159 DISALLOW_COPY_AND_ASSIGN(InternalPageInfoPopupView
);
162 ////////////////////////////////////////////////////////////////////////////////
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
);
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() {
287 void WebsiteSettingsPopupView::ShowPopup(
288 views::View
* anchor_view
,
289 const gfx::Rect
& anchor_rect
,
291 content::WebContents
* web_contents
,
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
);
302 popup
->SetAnchorRect(anchor_rect
);
303 popup
->GetWidget()->Show();
305 WebsiteSettingsPopupView
* popup
= new WebsiteSettingsPopupView(
306 anchor_view
, parent_window
, profile
, web_contents
, url
, security_info
);
308 popup
->SetAnchorRect(anchor_rect
);
309 popup
->GetWidget()->Show();
314 bool WebsiteSettingsPopupView::IsPopupShowing() {
315 return is_popup_showing
;
318 WebsiteSettingsPopupView::WebsiteSettingsPopupView(
319 views::View
* anchor_view
,
320 gfx::NativeView parent_window
,
322 content::WebContents
* web_contents
,
324 const SecurityStateModel::SecurityInfo
& security_info
)
325 : content::WebContentsObserver(web_contents
),
326 BubbleDelegateView(anchor_view
, views::BubbleBorder::TOP_LEFT
),
327 web_contents_(web_contents
),
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),
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(
376 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TAB_LABEL_PERMISSIONS
),
378 connection_tab_
= CreateConnectionTab();
379 tabbed_pane_
->AddTabAtIndex(
381 l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TAB_LABEL_CONNECTION
),
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
,
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
) {
433 case TAB_ID_PERMISSIONS
:
434 presenter_
->RecordWebsiteSettingsAction(
435 WebsiteSettings::WEBSITE_SETTINGS_PERMISSIONS_TAB_SELECTED
);
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.
442 presenter_
->RecordWebsiteSettingsAction(
443 WebsiteSettings::WEBSITE_SETTINGS_CONNECTION_TAB_SELECTED
);
449 tabbed_pane_
->GetSelectedTab()->Layout();
453 gfx::Size
WebsiteSettingsPopupView::GetPreferredSize() const {
454 if (header_
== nullptr && tabbed_pane_
== nullptr)
455 return views::View::GetPreferredSize();
459 height
+= header_
->GetPreferredSize().height() + kHeaderMarginBottom
;
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());
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|
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
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
));
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_
);
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_
)
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()
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();
583 layout
->StartRow(1, content_column
);
584 PermissionSelectorView
* selector
= new PermissionSelectorView(
585 web_contents_
? web_contents_
->GetURL() : GURL::EmptyGURL(),
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
);
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(
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
),
658 connection_tab_
->InvalidateLayout();
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
);
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_
,
706 link_section
->AddChildView(help_center_link_
);
707 pane
->AddChildView(link_section
);
711 views::View
* WebsiteSettingsPopupView::CreateSection(
712 const base::string16
& headline_text
,
713 views::View
* content
,
715 views::View
* container
= new views::View();
716 views::GridLayout
* layout
= new views::GridLayout(container
);
717 container
->SetLayoutManager(layout
);
718 const int content_column
= 0;
719 views::ColumnSet
* column_set
= layout
->AddColumnSet(content_column
);
720 column_set
->AddPaddingColumn(0, kPermissionsSectionPaddingLeft
);
721 column_set
->AddColumn(views::GridLayout::FILL
,
722 views::GridLayout::FILL
,
724 views::GridLayout::USE_PREF
,
728 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
);
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
);
754 void WebsiteSettingsPopupView::ResetConnectionSection(
755 views::View
* section_container
,
756 const gfx::Image
& icon
,
757 const base::string16
& headline
,
758 const base::string16
& text
,
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);
786 views::ImageView
* icon_view
= new views::ImageView();
787 icon_view
->SetImage(*icon
.ToImageSkia());
788 layout
->AddView(icon_view
, 1, 1, views::GridLayout::LEADING
,
789 views::GridLayout::LEADING
);
791 // Add section content.
792 views::View
* content_pane
= new views::View();
793 views::GridLayout
* content_layout
= new views::GridLayout(content_pane
);
794 content_pane
->SetLayoutManager(content_layout
);
795 views::ColumnSet
* content_column_set
= content_layout
->AddColumnSet(0);
796 content_column_set
->AddColumn(views::GridLayout::LEADING
,
797 views::GridLayout::LEADING
,
799 views::GridLayout::USE_PREF
,
802 if (!headline
.empty()) {
803 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
804 views::Label
* headline_label
= new views::Label(
805 headline
, rb
.GetFontList(ui::ResourceBundle::BoldFont
));
806 headline_label
->SetMultiLine(true);
807 headline_label
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
808 // Allow linebreaking in the middle of words if necessary, so that extremely
809 // long hostnames (longer than one line) will still be completely shown.
810 headline_label
->SetAllowCharacterBreak(true);
811 content_layout
->StartRow(1, 0);
812 content_layout
->AddView(headline_label
);
815 views::Label
* description_label
= new views::Label(text
);
816 description_label
->SetMultiLine(true);
817 description_label
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
818 description_label
->SetAllowCharacterBreak(true);
819 content_layout
->StartRow(1, 0);
820 content_layout
->AddView(description_label
);
823 content_layout
->StartRow(1, 0);
824 content_layout
->AddView(link
);
827 if (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
);