// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/ui/views/website_settings/website_settings_popup_view.h" #include <stddef.h> #include <algorithm> #include <vector> #include "base/i18n/rtl.h" #include "base/macros.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/certificate_viewer.h" #include "chrome/browser/devtools/devtools_toggle_action.h" #include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_dialogs.h" #include "chrome/browser/ui/views/collected_cookies_views.h" #include "chrome/browser/ui/views/website_settings/chosen_object_view.h" #include "chrome/browser/ui/views/website_settings/permission_selector_view.h" #include "chrome/browser/ui/website_settings/website_settings.h" #include "chrome/browser/ui/website_settings/website_settings_utils.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/prefs/pref_service.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/cert_store.h" #include "content/public/browser/user_metrics.h" #include "grit/components_chromium_strings.h" #include "grit/components_google_chrome_strings.h" #include "grit/components_strings.h" #include "grit/theme_resources.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/models/simple_menu_model.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/canvas.h" #include "ui/gfx/font_list.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/image/image.h" #include "ui/resources/grit/ui_resources.h" #include "ui/views/bubble/bubble_frame_view.h" #include "ui/views/controls/button/image_button.h" #include "ui/views/controls/button/label_button.h" #include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" #include "ui/views/controls/link.h" #include "ui/views/controls/styled_label.h" #include "ui/views/layout/box_layout.h" #include "ui/views/layout/grid_layout.h" #include "ui/views/layout/layout_manager.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h" #include "url/gurl.h" namespace { // NOTE(jdonnelly): This use of this process-wide variable assumes that there's // never more than one website settings popup shown and that it's associated // with the current window. If this assumption fails in the future, we'll need // to return a weak pointer from ShowPopup so callers can associate it with the // current window (or other context) and check if the popup they care about is // showing. bool is_popup_showing = false; // Left icon margin. const int kIconMarginLeft = 6; // Margin and padding values for the |PopupHeaderView|. const int kHeaderMarginBottom = 10; const int kHeaderPaddingBottom = 16; const int kHeaderPaddingLeft = 18; const int kHeaderPaddingRightForCloseButton = 8; const int kHeaderPaddingRightForText = kHeaderPaddingLeft; const int kHeaderPaddingTop = 12; // Spacing between the site identity label and the site identity status text in // the popup header. const int kHeaderRowSpacing = 4; // To make the bubble's arrow point directly at the location icon rather than at // the Omnibox's edge, inset the bubble's anchor rect by this amount of pixels. const int kLocationIconVerticalMargin = 5; // The max possible width of the popup. const int kMaxPopupWidth = 1000; // The margins between the popup border and the popup content. const int kPopupMarginTop = 4; const int kPopupMarginLeft = 0; const int kPopupMarginBottom = 14; const int kPopupMarginRight = 0; // Padding values for sections on the site settings view. const int kSiteSettingsViewContentMinWidth = 300; const int kSiteSettingsViewPaddingBottom = 6; const int kSiteSettingsViewPaddingLeft = 18; const int kSiteSettingsViewPaddingRight = 18; const int kSiteSettingsViewPaddingTop = 4; // Space between the headline and the content of a section. const int kSiteSettingsViewHeadlineMarginBottom = 10; // Spacing between rows in the "Permissions" and "Cookies and Site Data" // sections. const int kContentRowSpacing = 2; const int kSiteDataIconColumnWidth = 20; const int BUTTON_RESET_CERTIFICATE_DECISIONS = 1337; } // namespace // |PopupHeaderView| is the UI element (view) that represents the header of the // |WebsiteSettingsPopupView|. The header shows the status of the site's // identity check and the name of the site's identity. class PopupHeaderView : public views::View { public: explicit PopupHeaderView(views::ButtonListener* button_listener, views::StyledLabelListener* styled_label_listener); ~PopupHeaderView() override; // Sets the name of the site's identity. void SetIdentityName(const base::string16& name); // Sets the security summary text for the current page. void SetSecuritySummary(const base::string16& security_summary_text, bool include_details_link); int GetPreferredNameWidth() const; void AddResetDecisionsButton(); private: // The label that displays the name of the site's identity. views::Label* name_; // The label that displays the status of the identity check for this site. // Includes a link to open the DevTools Security panel. views::StyledLabel* status_; // The button listener attached to the buttons in this view. views::ButtonListener* button_listener_; // A container for the button for resetting cert decisions. The button is only // shown sometimes, so we use a container to keep track of where to place it // (if needed). views::View* reset_decisions_button_container_; DISALLOW_COPY_AND_ASSIGN(PopupHeaderView); }; // Website Settings are not supported for internal Chrome pages. Instead of the // |WebsiteSettingsPopupView|, the |InternalPageInfoPopupView| is // displayed. class InternalPageInfoPopupView : public views::BubbleDelegateView { public: // If |anchor_view| is nullptr, or has no Widget, |parent_window| may be // provided to ensure this bubble is closed when the parent closes. InternalPageInfoPopupView(views::View* anchor_view, gfx::NativeView parent_window); ~InternalPageInfoPopupView() override; // views::BubbleDelegateView: views::NonClientFrameView* CreateNonClientFrameView( views::Widget* widget) override; void OnWidgetDestroying(views::Widget* widget) override; private: friend class WebsiteSettingsPopupView; DISALLOW_COPY_AND_ASSIGN(InternalPageInfoPopupView); }; //////////////////////////////////////////////////////////////////////////////// // Popup Header //////////////////////////////////////////////////////////////////////////////// PopupHeaderView::PopupHeaderView( views::ButtonListener* button_listener, views::StyledLabelListener* styled_label_listener) : name_(nullptr), status_(nullptr), button_listener_(button_listener), reset_decisions_button_container_(nullptr) { views::GridLayout* layout = new views::GridLayout(this); SetLayoutManager(layout); const int label_column = 0; views::ColumnSet* column_set = layout->AddColumnSet(label_column); column_set->AddPaddingColumn(0, kHeaderPaddingLeft); column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, views::GridLayout::USE_PREF, 0, 0); column_set->AddPaddingColumn(1, 0); column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, views::GridLayout::USE_PREF, 0, 0); column_set->AddPaddingColumn(0, kHeaderPaddingRightForCloseButton); layout->AddPaddingRow(0, kHeaderPaddingTop); layout->StartRow(0, label_column); ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); name_ = new views::Label( base::string16(), rb.GetFontList(ui::ResourceBundle::BoldFont)); layout->AddView(name_, 1, 1, views::GridLayout::LEADING, views::GridLayout::TRAILING); views::ImageButton* close_button = new views::ImageButton(button_listener); close_button->SetImage(views::CustomButton::STATE_NORMAL, rb.GetImageNamed(IDR_CLOSE_2).ToImageSkia()); close_button->SetImage(views::CustomButton::STATE_HOVERED, rb.GetImageNamed(IDR_CLOSE_2_H).ToImageSkia()); close_button->SetImage(views::CustomButton::STATE_PRESSED, rb.GetImageNamed(IDR_CLOSE_2_P).ToImageSkia()); layout->AddView(close_button, 1, 1, views::GridLayout::TRAILING, views::GridLayout::LEADING); layout->AddPaddingRow(0, kHeaderRowSpacing); const int label_column_status = 1; views::ColumnSet* column_set_status = layout->AddColumnSet(label_column_status); column_set_status->AddPaddingColumn(0, kHeaderPaddingLeft); column_set_status->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, views::GridLayout::USE_PREF, 0, 0); column_set_status->AddPaddingColumn(0, kHeaderPaddingRightForText); layout->StartRow(0, label_column_status); status_ = new views::StyledLabel(base::string16(), styled_label_listener); layout->AddView(status_, 1, 1, views::GridLayout::LEADING, views::GridLayout::LEADING); layout->StartRow(0, label_column_status); reset_decisions_button_container_ = new views::View(); reset_decisions_button_container_->SetLayoutManager( new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0)); layout->AddView(reset_decisions_button_container_, 1, 1, views::GridLayout::LEADING, views::GridLayout::LEADING); layout->AddPaddingRow(1, kHeaderPaddingBottom); } PopupHeaderView::~PopupHeaderView() {} int PopupHeaderView::GetPreferredNameWidth() const { return name_->GetPreferredSize().width(); } void PopupHeaderView::SetIdentityName(const base::string16& name) { name_->SetText(name); } void PopupHeaderView::SetSecuritySummary( const base::string16& security_summary_text, bool include_details_link) { if (include_details_link) { base::string16 details_string = l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_DETAILS_LINK); std::vector<base::string16> subst; subst.push_back(security_summary_text); subst.push_back(details_string); std::vector<size_t> offsets; base::string16 text = base::ReplaceStringPlaceholders( base::ASCIIToUTF16("$1 $2"), subst, &offsets); status_->SetText(text); gfx::Range details_range(offsets[1], text.length()); views::StyledLabel::RangeStyleInfo link_style = views::StyledLabel::RangeStyleInfo::CreateForLink(); link_style.font_style |= gfx::Font::FontStyle::UNDERLINE; link_style.disable_line_wrapping = false; status_->AddStyleRange(details_range, link_style); } else { status_->SetText(security_summary_text); } // Fit the styled label to occupy available width. status_->SizeToFit(0); } void PopupHeaderView::AddResetDecisionsButton() { views::LabelButton* reset_decisions_button = new views::LabelButton( button_listener_, l10n_util::GetStringUTF16( IDS_PAGEINFO_RESET_INVALID_CERTIFICATE_DECISIONS_BUTTON)); reset_decisions_button->set_id(BUTTON_RESET_CERTIFICATE_DECISIONS); reset_decisions_button->SetStyle(views::Button::STYLE_BUTTON); reset_decisions_button_container_->AddChildView(reset_decisions_button); // Now that it contains a button, the container needs padding at the top. reset_decisions_button_container_->SetBorder( views::Border::CreateEmptyBorder(8, 0, 0, 0)); InvalidateLayout(); } //////////////////////////////////////////////////////////////////////////////// // InternalPageInfoPopupView //////////////////////////////////////////////////////////////////////////////// InternalPageInfoPopupView::InternalPageInfoPopupView( views::View* anchor_view, gfx::NativeView parent_window) : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT) { set_parent_window(parent_window); // Compensate for built-in vertical padding in the anchor view's image. set_anchor_view_insets(gfx::Insets(kLocationIconVerticalMargin, 0, kLocationIconVerticalMargin, 0)); const int kSpacing = 16; SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, kSpacing, kSpacing, kSpacing)); set_margins(gfx::Insets()); views::ImageView* icon_view = new views::ImageView(); ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); icon_view->SetImage(rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_16)); AddChildView(icon_view); views::Label* label = new views::Label(l10n_util::GetStringUTF16(IDS_PAGE_INFO_INTERNAL_PAGE)); label->SetMultiLine(true); label->SetAllowCharacterBreak(true); label->SetHorizontalAlignment(gfx::ALIGN_LEFT); AddChildView(label); views::BubbleDelegateView::CreateBubble(this); } InternalPageInfoPopupView::~InternalPageInfoPopupView() { } views::NonClientFrameView* InternalPageInfoPopupView::CreateNonClientFrameView( views::Widget* widget) { views::BubbleFrameView* frame = static_cast<views::BubbleFrameView*>( BubbleDelegateView::CreateNonClientFrameView(widget)); // 16px padding + half of icon width comes out to 24px. frame->bubble_border()->set_arrow_offset( 24 + frame->bubble_border()->GetBorderThickness()); return frame; } void InternalPageInfoPopupView::OnWidgetDestroying(views::Widget* widget) { is_popup_showing = false; } //////////////////////////////////////////////////////////////////////////////// // WebsiteSettingsPopupView //////////////////////////////////////////////////////////////////////////////// WebsiteSettingsPopupView::~WebsiteSettingsPopupView() { } // static void WebsiteSettingsPopupView::ShowPopup( views::View* anchor_view, const gfx::Rect& anchor_rect, Profile* profile, content::WebContents* web_contents, const GURL& url, const security_state::SecurityStateModel::SecurityInfo& security_info) { is_popup_showing = true; gfx::NativeView parent_window = anchor_view ? nullptr : web_contents->GetNativeView(); if (InternalChromePage(url)) { // Use the concrete type so that |SetAnchorRect| can be called as a friend. InternalPageInfoPopupView* popup = new InternalPageInfoPopupView(anchor_view, parent_window); if (!anchor_view) popup->SetAnchorRect(anchor_rect); popup->GetWidget()->Show(); } else { WebsiteSettingsPopupView* popup = new WebsiteSettingsPopupView( anchor_view, parent_window, profile, web_contents, url, security_info); if (!anchor_view) popup->SetAnchorRect(anchor_rect); popup->GetWidget()->Show(); } } // static bool WebsiteSettingsPopupView::IsPopupShowing() { return is_popup_showing; } WebsiteSettingsPopupView::WebsiteSettingsPopupView( views::View* anchor_view, gfx::NativeView parent_window, Profile* profile, content::WebContents* web_contents, const GURL& url, const security_state::SecurityStateModel::SecurityInfo& security_info) : content::WebContentsObserver(web_contents), BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT), web_contents_(web_contents), header_(nullptr), separator_(nullptr), site_settings_view_(nullptr), site_data_content_(nullptr), cookie_dialog_link_(nullptr), permissions_content_(nullptr), cert_id_(0), site_settings_link_(nullptr), weak_factory_(this) { set_parent_window(parent_window); is_devtools_disabled_ = profile->GetPrefs()->GetBoolean(prefs::kDevToolsDisabled); // Compensate for built-in vertical padding in the anchor view's image. set_anchor_view_insets(gfx::Insets(kLocationIconVerticalMargin, 0, kLocationIconVerticalMargin, 0)); views::GridLayout* layout = new views::GridLayout(this); SetLayoutManager(layout); const int content_column = 0; views::ColumnSet* column_set = layout->AddColumnSet(content_column); column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, views::GridLayout::USE_PREF, 0, 0); header_ = new PopupHeaderView(this, this); layout->StartRow(1, content_column); layout->AddView(header_); layout->StartRow(0, content_column); separator_ = new views::Separator(views::Separator::HORIZONTAL); layout->AddView(separator_); layout->AddPaddingRow(1, kHeaderMarginBottom); layout->StartRow(1, content_column); site_settings_view_ = CreateSiteSettingsView(); layout->AddView(site_settings_view_); set_margins(gfx::Insets(kPopupMarginTop, kPopupMarginLeft, kPopupMarginBottom, kPopupMarginRight)); views::BubbleDelegateView::CreateBubble(this); presenter_.reset(new WebsiteSettings( this, profile, TabSpecificContentSettings::FromWebContents(web_contents), web_contents, url, security_info, content::CertStore::GetInstance())); } void WebsiteSettingsPopupView::RenderFrameDeleted( content::RenderFrameHost* render_frame_host) { if (render_frame_host == web_contents_->GetMainFrame()) { GetWidget()->Close(); } } void WebsiteSettingsPopupView::OnPermissionChanged( const WebsiteSettingsUI::PermissionInfo& permission) { presenter_->OnSitePermissionChanged(permission.type, permission.setting); } void WebsiteSettingsPopupView::OnChosenObjectDeleted( const WebsiteSettingsUI::ChosenObjectInfo& info) { presenter_->OnSiteChosenObjectDeleted(info.ui_info, *info.object); } void WebsiteSettingsPopupView::OnWidgetDestroying(views::Widget* widget) { is_popup_showing = false; presenter_->OnUIClosing(); } void WebsiteSettingsPopupView::ButtonPressed(views::Button* button, const ui::Event& event) { if (button->id() == BUTTON_RESET_CERTIFICATE_DECISIONS) presenter_->OnRevokeSSLErrorBypassButtonPressed(); GetWidget()->Close(); } void WebsiteSettingsPopupView::LinkClicked(views::Link* source, int event_flags) { // The popup closes automatically when the collected cookies dialog or the // certificate viewer opens. So delay handling of the link clicked to avoid // a crash in the base class which needs to complete the mouse event handling. content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, base::Bind(&WebsiteSettingsPopupView::HandleLinkClickedAsync, weak_factory_.GetWeakPtr(), source)); } gfx::Size WebsiteSettingsPopupView::GetPreferredSize() const { if (header_ == nullptr && site_settings_view_ == nullptr) return views::View::GetPreferredSize(); int height = 0; if (header_) height += header_->GetPreferredSize().height() + kHeaderMarginBottom; if (separator_) height += separator_->GetPreferredSize().height(); if (site_settings_view_) height += site_settings_view_->GetPreferredSize().height(); int width = kSiteSettingsViewContentMinWidth; if (site_data_content_) width = std::max(width, site_data_content_->GetPreferredSize().width()); if (permissions_content_) width = std::max(width, permissions_content_->GetPreferredSize().width()); if (header_) width = std::max(width, header_->GetPreferredNameWidth()); width += kSiteSettingsViewPaddingLeft + kSiteSettingsViewPaddingRight; width = std::min(width, kMaxPopupWidth); return gfx::Size(width, height); } void WebsiteSettingsPopupView::SetCookieInfo( const CookieInfoList& cookie_info_list) { // |cookie_info_list| should only ever have 2 items: first- and third-party // cookies. DCHECK_EQ(cookie_info_list.size(), 2u); base::string16 first_party_label_text; base::string16 third_party_label_text; for (const auto& i : cookie_info_list) { if (i.is_first_party) { first_party_label_text = l10n_util::GetStringFUTF16(IDS_WEBSITE_SETTINGS_FIRST_PARTY_SITE_DATA, base::IntToString16(i.allowed)); } else { third_party_label_text = l10n_util::GetStringFUTF16(IDS_WEBSITE_SETTINGS_THIRD_PARTY_SITE_DATA, base::IntToString16(i.allowed)); } } if (!cookie_dialog_link_) { cookie_dialog_link_ = new views::Link(first_party_label_text); cookie_dialog_link_->set_listener(this); } else { cookie_dialog_link_->SetText(first_party_label_text); } views::GridLayout* layout = static_cast<views::GridLayout*>(site_data_content_->GetLayoutManager()); if (!layout) { layout = new views::GridLayout(site_data_content_); site_data_content_->SetLayoutManager(layout); const int site_data_content_column = 0; views::ColumnSet* column_set = layout->AddColumnSet(site_data_content_column); column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, views::GridLayout::FIXED, kSiteDataIconColumnWidth, 0); column_set->AddPaddingColumn(0, kIconMarginLeft); column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, views::GridLayout::USE_PREF, 0, 0); // No padding. This third column is for |third_party_label_text| (see // below), // and the text needs to flow naturally from the |first_party_label_text| // link. column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, views::GridLayout::USE_PREF, 0, 0); layout->AddPaddingRow(1, 5); layout->StartRow(1, site_data_content_column); WebsiteSettingsUI::PermissionInfo info; info.type = CONTENT_SETTINGS_TYPE_COOKIES; info.setting = CONTENT_SETTING_ALLOW; info.is_incognito = Profile::FromBrowserContext(web_contents_->GetBrowserContext()) ->IsOffTheRecord(); views::ImageView* icon = new views::ImageView(); const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon(info); icon->SetImage(image.ToImageSkia()); layout->AddView(icon, 1, 1, views::GridLayout::CENTER, views::GridLayout::CENTER); layout->AddView(cookie_dialog_link_, 1, 1, views::GridLayout::CENTER, views::GridLayout::CENTER); base::string16 comma = base::ASCIIToUTF16(", "); layout->AddView(new views::Label(comma + third_party_label_text), 1, 1, views::GridLayout::LEADING, views::GridLayout::CENTER); layout->AddPaddingRow(1, 6); } layout->Layout(site_data_content_); SizeToContents(); } void WebsiteSettingsPopupView::SetPermissionInfo( const PermissionInfoList& permission_info_list, const ChosenObjectInfoList& chosen_object_info_list) { // When a permission is changed, WebsiteSettings::OnSitePermissionChanged() // calls this method with updated permissions. However, PermissionSelectorView // will have already updated its state, so it's already reflected in the UI. // In addition, if a permission is set to the default setting, WebsiteSettings // removes it from |permission_info_list|, but the button should remain. if (permissions_content_) { STLDeleteContainerPointers(chosen_object_info_list.begin(), chosen_object_info_list.end()); return; } permissions_content_ = new views::View(); views::GridLayout* layout = new views::GridLayout(permissions_content_); permissions_content_->SetLayoutManager(layout); base::string16 headline = permission_info_list.empty() ? base::string16() : l10n_util::GetStringUTF16( IDS_WEBSITE_SETTINGS_TITLE_SITE_PERMISSIONS); views::View* permissions_section = CreateSection(headline, permissions_content_, nullptr); site_settings_view_->AddChildView(permissions_section); const int content_column = 0; views::ColumnSet* column_set = layout->AddColumnSet(content_column); column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, views::GridLayout::USE_PREF, 0, 0); for (const auto& permission : permission_info_list) { layout->StartRow(1, content_column); PermissionSelectorView* selector = new PermissionSelectorView( web_contents_ ? web_contents_->GetURL() : GURL::EmptyGURL(), permission); selector->AddObserver(this); layout->AddView(selector, 1, 1, views::GridLayout::LEADING, views::GridLayout::CENTER); layout->AddPaddingRow(1, kContentRowSpacing); } for (auto object : chosen_object_info_list) { layout->StartRow(1, content_column); // The view takes ownership of the object info. auto object_view = new ChosenObjectView(make_scoped_ptr(object)); object_view->AddObserver(this); layout->AddView(object_view, 1, 1, views::GridLayout::LEADING, views::GridLayout::CENTER); layout->AddPaddingRow(1, kContentRowSpacing); } layout->Layout(permissions_content_); // Add site settings link. site_settings_link_ = new views::Link( l10n_util::GetStringUTF16(IDS_PAGE_INFO_SITE_SETTINGS_LINK)); site_settings_link_->set_listener(this); views::View* link_section = new views::View(); const int kLinkMarginTop = 4; link_section->SetLayoutManager( new views::BoxLayout(views::BoxLayout::kHorizontal, kSiteSettingsViewPaddingLeft, kLinkMarginTop, 0)); link_section->AddChildView(site_settings_link_); site_settings_view_->AddChildView(link_section); SizeToContents(); } void WebsiteSettingsPopupView::SetIdentityInfo( const IdentityInfo& identity_info) { base::string16 security_summary_text = identity_info.GetSecuritySummary(); header_->SetIdentityName(base::UTF8ToUTF16(identity_info.site_identity)); if (identity_info.cert_id) { cert_id_ = identity_info.cert_id; if (identity_info.show_ssl_decision_revoke_button) header_->AddResetDecisionsButton(); } bool include_details_link = !is_devtools_disabled_ || identity_info.cert_id != 0; header_->SetSecuritySummary(security_summary_text, include_details_link); Layout(); SizeToContents(); } void WebsiteSettingsPopupView::SetSelectedTab(TabId tab_id) { // TODO(lgarron): Remove this method. (https://crbug.com/571533) } views::View* WebsiteSettingsPopupView::CreateSiteSettingsView() { views::View* pane = new views::View(); pane->SetLayoutManager( new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1)); // Add cookies and site data section. site_data_content_ = new views::View(); views::View* site_data_section = CreateSection( l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TITLE_SITE_DATA), site_data_content_, NULL); pane->AddChildView(site_data_section); return pane; } views::View* WebsiteSettingsPopupView::CreateSection( const base::string16& headline_text, views::View* content, views::Link* link) { views::View* container = new views::View(); views::GridLayout* layout = new views::GridLayout(container); container->SetLayoutManager(layout); const int content_column = 0; views::ColumnSet* column_set = layout->AddColumnSet(content_column); column_set->AddPaddingColumn(0, kSiteSettingsViewPaddingLeft); column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, views::GridLayout::USE_PREF, 0, 0); if (headline_text.length() > 0) { layout->AddPaddingRow(1, kSiteSettingsViewPaddingTop); layout->StartRow(1, content_column); ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); views::Label* headline = new views::Label( headline_text, rb.GetFontList(ui::ResourceBundle::BoldFont)); layout->AddView(headline, 1, 1, views::GridLayout::LEADING, views::GridLayout::CENTER); } layout->AddPaddingRow(1, kSiteSettingsViewHeadlineMarginBottom); layout->StartRow(1, content_column); layout->AddView(content, 1, 1, views::GridLayout::LEADING, views::GridLayout::CENTER); if (link) { layout->AddPaddingRow(1, 4); layout->StartRow(1, content_column); layout->AddView(link, 1, 1, views::GridLayout::LEADING, views::GridLayout::CENTER); } layout->AddPaddingRow(1, kSiteSettingsViewPaddingBottom); return container; } void WebsiteSettingsPopupView::HandleLinkClickedAsync(views::Link* source) { if (source == cookie_dialog_link_) { // Count how often the Collected Cookies dialog is opened. presenter_->RecordWebsiteSettingsAction( WebsiteSettings::WEBSITE_SETTINGS_COOKIES_DIALOG_OPENED); if (web_contents_ != NULL) new CollectedCookiesViews(web_contents_); } else if (source == site_settings_link_) { // TODO(palmer): This opens the general Content Settings pane, which is OK // for now. But on Android, it opens a page specific to a given origin that // shows all of the settings for that origin. If/when that's available on // desktop we should link to that here, too. web_contents_->OpenURL(content::OpenURLParams( GURL(chrome::kChromeUIContentSettingsURL), content::Referrer(), NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_LINK, false)); presenter_->RecordWebsiteSettingsAction( WebsiteSettings::WEBSITE_SETTINGS_SITE_SETTINGS_OPENED); } else { NOTREACHED(); } } void WebsiteSettingsPopupView::StyledLabelLinkClicked(views::StyledLabel* label, const gfx::Range& range, int event_flags) { presenter_->RecordWebsiteSettingsAction( WebsiteSettings::WEBSITE_SETTINGS_SECURITY_DETAILS_OPENED); if (is_devtools_disabled_) { DCHECK_NE(cert_id_, 0); gfx::NativeWindow parent = anchor_widget() ? anchor_widget()->GetNativeWindow() : nullptr; presenter_->RecordWebsiteSettingsAction( WebsiteSettings::WEBSITE_SETTINGS_CERTIFICATE_DIALOG_OPENED); ShowCertificateViewerByID(web_contents_, parent, cert_id_); } else { DevToolsWindow::OpenDevToolsWindow( web_contents_, DevToolsToggleAction::ShowSecurityPanel()); } }