Commit 3c058026 authored by Christian Dullweber's avatar Christian Dullweber Committed by Commit Bot

Add intermediary step for cookie controls UI

Show a page explaining the effect of third-party cookie blocking.

https://screenshot.googleplex.com/pWGgd3OzxK8.png

Bug: 967668
Change-Id: I3f2167c455ac4ef3a4600f0d4483783bae95a763
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1835365
Commit-Queue: Christian Dullweber <dullweber@chromium.org>
Reviewed-by: default avatarAllen Bauer <kylixrd@chromium.org>
Reviewed-by: default avatarElly Fong-Jones <ellyjones@chromium.org>
Reviewed-by: default avatarBret Sepulveda <bsep@chromium.org>
Reviewed-by: default avatarEvan Stade <estade@chromium.org>
Cr-Commit-Position: refs/heads/master@{#704116}
parent 741bbcc2
...@@ -2509,6 +2509,12 @@ are declared in tools/grit/grit_rule.gni. ...@@ -2509,6 +2509,12 @@ are declared in tools/grit/grit_rule.gni.
<message name="IDS_COOKIE_CONTROLS_TURN_OFF_BUTTON" desc="Label shown on a button that turns off cookie blocking for a specific site."> <message name="IDS_COOKIE_CONTROLS_TURN_OFF_BUTTON" desc="Label shown on a button that turns off cookie blocking for a specific site.">
Turn off for this site Turn off for this site
</message> </message>
<message name="IDS_COOKIE_CONTROLS_NOT_WORKING_TITLE" desc="Label shown on a dialog that allows users to turn off third-party cookie blocking for a specific site.">
Site not working?
</message>
<message name="IDS_COOKIE_CONTROLS_NOT_WORKING_DESCRIPTION" desc="Label shown on a dialog that allows users to turn off third-party cookie blocking for a specific site.">
Some sites use third-party cookies to load their pages. If a site isn't working, you can try turning off cookie blocking.
</message>
<message name="IDS_COOKIE_CONTROLS_BLOCKED_MESSAGE" desc="Text shown in the dialog that allows users to control cookie blocking. Shows the number of sites for which cookies have been blocked."> <message name="IDS_COOKIE_CONTROLS_BLOCKED_MESSAGE" desc="Text shown in the dialog that allows users to control cookie blocking. Shows the number of sites for which cookies have been blocked.">
{COUNT, plural, {COUNT, plural,
=0 {This site doesn't use cookies for cross-site tracking} =0 {This site doesn't use cookies for cross-site tracking}
......
55ec4ca6ba6aab18bf86f0b48b708e781a507e28
\ No newline at end of file
55ec4ca6ba6aab18bf86f0b48b708e781a507e28
\ No newline at end of file
...@@ -26,8 +26,11 @@ class CookieControlsController { ...@@ -26,8 +26,11 @@ class CookieControlsController {
public: public:
enum class Status { enum class Status {
kUninitialized, kUninitialized,
// Cookie blocking is enabled.
kEnabled, kEnabled,
// Cookie blocking is disabled.
kDisabled, kDisabled,
// Cookie blocking is enabled in general but was disabled for this site.
kDisabledForSite, kDisabledForSite,
}; };
......
...@@ -6,7 +6,8 @@ ...@@ -6,7 +6,8 @@
#include <memory> #include <memory>
#include "base/logging.h" #include "base/logging.h"
#include "chrome/app/vector_icons/vector_icons.h" #include "base/strings/string16.h"
#include "chrome/browser/ui/views/accessibility/non_accessible_image_view.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h" #include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/grit/generated_resources.h" #include "chrome/grit/generated_resources.h"
#include "chrome/grit/theme_resources.h" #include "chrome/grit/theme_resources.h"
...@@ -14,16 +15,19 @@ ...@@ -14,16 +15,19 @@
#include "ui/base/resource/resource_bundle.h" #include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_types.h" #include "ui/base/ui_base_types.h"
#include "ui/gfx/text_utils.h" #include "ui/gfx/text_utils.h"
#include "ui/gfx/vector_icon_types.h" #include "ui/views/bubble/bubble_frame_view.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/md_text_button.h"
#include "ui/views/controls/image_view.h" #include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h" #include "ui/views/controls/link.h"
#include "ui/views/layout/box_layout.h" #include "ui/views/layout/fill_layout.h"
#include "ui/views/style/typography.h"
#include "ui/views/widget/widget.h" #include "ui/views/widget/widget.h"
#include "ui/views/window/dialog_client_view.h"
CookieControlsBubbleView* CookieControlsBubbleView::cookie_bubble_ = nullptr; namespace {
// Singleton instance of the cookie bubble. The cookie bubble can only be
// shown on the active browser window, so there is no case in which it will be
// shown twice at the same time.
static CookieControlsBubbleView* g_instance;
} // namespace
// static // static
void CookieControlsBubbleView::ShowBubble( void CookieControlsBubbleView::ShowBubble(
...@@ -33,30 +37,31 @@ void CookieControlsBubbleView::ShowBubble( ...@@ -33,30 +37,31 @@ void CookieControlsBubbleView::ShowBubble(
CookieControlsController* controller, CookieControlsController* controller,
CookieControlsController::Status status) { CookieControlsController::Status status) {
DCHECK(web_contents); DCHECK(web_contents);
if (cookie_bubble_) if (g_instance)
return; return;
cookie_bubble_ = g_instance =
new CookieControlsBubbleView(anchor_view, web_contents, controller); new CookieControlsBubbleView(anchor_view, web_contents, controller);
cookie_bubble_->SetHighlightedButton(highlighted_button); g_instance->SetHighlightedButton(highlighted_button);
views::Widget* bubble_widget = views::Widget* bubble_widget =
views::BubbleDialogDelegateView::CreateBubble(cookie_bubble_); views::BubbleDialogDelegateView::CreateBubble(g_instance);
controller->Update(web_contents); controller->Update(web_contents);
bubble_widget->Show(); bubble_widget->Show();
} }
// static // static
CookieControlsBubbleView* CookieControlsBubbleView::GetCookieBubble() { CookieControlsBubbleView* CookieControlsBubbleView::GetCookieBubble() {
return cookie_bubble_; return g_instance;
} }
void CookieControlsBubbleView::OnStatusChanged( void CookieControlsBubbleView::OnStatusChanged(
CookieControlsController::Status status) { CookieControlsController::Status new_status) {
if (status_ == status) if (status_ == new_status)
return; return;
status_ = status;
UpdateUi(status, blocked_cookies_ > 0); show_disable_cookie_blocking_ui_ = false;
status_ = new_status;
UpdateUi();
} }
void CookieControlsBubbleView::OnBlockedCookiesCountChanged( void CookieControlsBubbleView::OnBlockedCookiesCountChanged(
...@@ -67,17 +72,17 @@ void CookieControlsBubbleView::OnBlockedCookiesCountChanged( ...@@ -67,17 +72,17 @@ void CookieControlsBubbleView::OnBlockedCookiesCountChanged(
return; return;
bool has_blocked_changed = bool has_blocked_changed =
blocked_cookies_ == -1 || (blocked_cookies_ > 0) != (blocked_cookies > 0); !blocked_cookies_ || (*blocked_cookies_ > 0) != (blocked_cookies > 0);
blocked_cookies_ = blocked_cookies; blocked_cookies_ = blocked_cookies;
sub_title_->SetText( text_->SetText(
l10n_util::GetPluralStringFUTF16(IDS_COOKIE_CONTROLS_BLOCKED_MESSAGE, l10n_util::GetPluralStringFUTF16(IDS_COOKIE_CONTROLS_BLOCKED_MESSAGE,
controller_->GetBlockedDomainCount())); controller_->GetBlockedDomainCount()));
// If this only incremented the number of blocked sites, no UI update is // If this only incremented the number of blocked sites, no UI update is
// necessary besides the |sub_title_| text. // necessary besides the |text_| text.
if (has_blocked_changed) if (has_blocked_changed)
UpdateUi(status_, blocked_cookies_ > 0); UpdateUi();
} }
CookieControlsBubbleView::CookieControlsBubbleView( CookieControlsBubbleView::CookieControlsBubbleView(
...@@ -91,94 +96,123 @@ CookieControlsBubbleView::CookieControlsBubbleView( ...@@ -91,94 +96,123 @@ CookieControlsBubbleView::CookieControlsBubbleView(
CookieControlsBubbleView::~CookieControlsBubbleView() = default; CookieControlsBubbleView::~CookieControlsBubbleView() = default;
void CookieControlsBubbleView::UpdateUi(CookieControlsController::Status status, void CookieControlsBubbleView::UpdateUi() {
bool has_blocked_cookies) { if (status_ == CookieControlsController::Status::kDisabled) {
if (status == CookieControlsController::Status::kDisabled) {
CloseBubble(); CloseBubble();
return; return;
} }
if (status == CookieControlsController::Status::kEnabled) { DialogModelChanged();
header_image_->SetImage( GetBubbleFrameView()->UpdateWindowTitle();
bool has_blocked_cookies = blocked_cookies_ > 0;
not_working_link_->SetVisible(false);
text_->SetVisible(false);
header_view_->SetVisible(false);
if (show_disable_cookie_blocking_ui_) {
text_->SetVisible(true);
text_->SetText(
l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_NOT_WORKING_DESCRIPTION));
} else if (status_ == CookieControlsController::Status::kEnabled) {
header_view_->SetVisible(true);
header_view_->SetImage(
ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
has_blocked_cookies ? IDR_COOKIE_BLOCKING_ON_HEADER has_blocked_cookies ? IDR_COOKIE_BLOCKING_ON_HEADER
: IDR_COOKIE_BLOCKING_INACTIVE_HEADER)); : IDR_COOKIE_BLOCKING_INACTIVE_HEADER));
title_->SetText( text_->SetVisible(true);
l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_DIALOG_TITLE)); not_working_link_->SetVisible(has_blocked_cookies);
sub_title_->SetVisible(true); blocked_cookies_.reset();
spacer_->SetVisible(has_blocked_cookies);
turn_off_button_->SetVisible(has_blocked_cookies);
turn_on_button_->SetVisible(false);
} else { } else {
DCHECK_EQ(status, CookieControlsController::Status::kDisabledForSite); DCHECK_EQ(status_, CookieControlsController::Status::kDisabledForSite);
header_image_->SetImage( header_view_->SetVisible(true);
header_view_->SetImage(
ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
IDR_COOKIE_BLOCKING_OFF_HEADER)); IDR_COOKIE_BLOCKING_OFF_HEADER));
title_->SetText(
l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_DIALOG_TITLE_OFF));
sub_title_->SetVisible(false);
spacer_->SetVisible(true);
turn_off_button_->SetVisible(false);
turn_on_button_->SetVisible(true);
} }
Layout(); Layout();
SizeToContents();
// The show_disable_cookie_blocking_ui_ state has a different title
// configuration. To avoid jumping UI, don't resize the bubble. This should be
// safe as the bubble in this state has less content than in Enabled state.
if (!show_disable_cookie_blocking_ui_)
SizeToContents();
} }
void CookieControlsBubbleView::CloseBubble() { void CookieControlsBubbleView::CloseBubble() {
// Widget's Close() is async, but we don't want to use cookie_bubble_ after // Widget's Close() is async, but we don't want to use cookie_bubble_ after
// this. Additionally web_contents() may have been destroyed. // this. Additionally web_contents() may have been destroyed.
cookie_bubble_ = nullptr; g_instance = nullptr;
LocationBarBubbleDelegateView::CloseBubble(); LocationBarBubbleDelegateView::CloseBubble();
} }
int CookieControlsBubbleView::GetDialogButtons() const { int CookieControlsBubbleView::GetDialogButtons() const {
if (show_disable_cookie_blocking_ui_ ||
status_ == CookieControlsController::Status::kDisabledForSite) {
return ui::DIALOG_BUTTON_OK;
}
return ui::DIALOG_BUTTON_NONE; return ui::DIALOG_BUTTON_NONE;
} }
base::string16 CookieControlsBubbleView::GetDialogButtonLabel(
ui::DialogButton button) const {
if (show_disable_cookie_blocking_ui_)
return l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_TURN_OFF_BUTTON);
DCHECK_EQ(status_, CookieControlsController::Status::kDisabledForSite);
return l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_TURN_ON_BUTTON);
}
void CookieControlsBubbleView::Init() { void CookieControlsBubbleView::Init() {
SetLayoutManager(std::make_unique<views::BoxLayout>( SetLayoutManager(std::make_unique<views::FillLayout>());
views::BoxLayout::Orientation::kVertical)); auto text = std::make_unique<views::Label>(base::string16(),
header_image_ = new views::ImageView(); views::style::CONTEXT_LABEL);
AddChildView(header_image_); text->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
text->SetMultiLine(true);
title_ = text_ = AddChildView(std::move(text));
new views::Label(base::string16(), views::style::CONTEXT_DIALOG_TITLE); }
title_->SetBorder(views::CreateEmptyBorder(8, 0, 0, 0));
title_->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT); std::unique_ptr<views::View> CookieControlsBubbleView::CreateExtraView() {
title_->SetMultiLine(true); auto view = std::make_unique<views::Link>(
AddChildView(title_); l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_NOT_WORKING_TITLE));
not_working_link_ = view.get();
sub_title_ = new views::Label(base::string16(), views::style::CONTEXT_LABEL); not_working_link_->set_listener(this);
sub_title_->SetBorder(views::CreateEmptyBorder(8, 0, 0, 0)); return std::move(view);
sub_title_->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT); }
sub_title_->SetMultiLine(true);
AddChildView(sub_title_); void CookieControlsBubbleView::AddedToWidget() {
auto header_view = std::make_unique<NonAccessibleImageView>();
spacer_ = new views::View(); header_view_ = header_view.get();
spacer_->SetPreferredSize(gfx::Size(0, 16)); GetBubbleFrameView()->SetHeaderView(std::move(header_view));
AddChildView(spacer_); }
auto* button_container = new views::View(); gfx::Size CookieControlsBubbleView::CalculatePreferredSize() const {
button_container->SetLayoutManager(std::make_unique<views::BoxLayout>( // The total width of this view should always be identical to the width
views::BoxLayout::Orientation::kHorizontal)); // of the header images.
turn_on_button_ = int width = ui::ResourceBundle::GetSharedInstance()
views::MdTextButton::CreateSecondaryUiButton( .GetImageSkiaNamed(IDR_COOKIE_BLOCKING_ON_HEADER)
this, l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_TURN_ON_BUTTON)) ->width();
.release(); return gfx::Size{width, GetHeightForWidth(width)};
button_container->AddChildView(turn_on_button_); }
turn_off_button_ = base::string16 CookieControlsBubbleView::GetWindowTitle() const {
views::MdTextButton::CreateSecondaryUiButton( if (show_disable_cookie_blocking_ui_)
this, l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_TURN_OFF_BUTTON)) return l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_NOT_WORKING_TITLE);
.release(); switch (status_) {
button_container->AddChildView(turn_off_button_); case CookieControlsController::Status::kEnabled:
return l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_DIALOG_TITLE);
AddChildView(button_container); case CookieControlsController::Status::kDisabledForSite:
return l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_DIALOG_TITLE_OFF);
case CookieControlsController::Status::kUninitialized:
return base::string16();
case CookieControlsController::Status::kDisabled:
NOTREACHED();
return base::string16();
}
} }
bool CookieControlsBubbleView::ShouldShowWindowTitle() const { bool CookieControlsBubbleView::ShouldShowWindowTitle() const {
return false; return true;
} }
bool CookieControlsBubbleView::ShouldShowCloseButton() const { bool CookieControlsBubbleView::ShouldShowCloseButton() const {
...@@ -188,19 +222,33 @@ bool CookieControlsBubbleView::ShouldShowCloseButton() const { ...@@ -188,19 +222,33 @@ bool CookieControlsBubbleView::ShouldShowCloseButton() const {
void CookieControlsBubbleView::WindowClosing() { void CookieControlsBubbleView::WindowClosing() {
// |cookie_bubble_| can be a new bubble by this point (as Close(); doesn't // |cookie_bubble_| can be a new bubble by this point (as Close(); doesn't
// call this right away). Only set to nullptr when it's this bubble. // call this right away). Only set to nullptr when it's this bubble.
bool this_bubble = cookie_bubble_ == this; bool this_bubble = g_instance == this;
if (this_bubble) if (this_bubble)
cookie_bubble_ = nullptr; g_instance = nullptr;
controller_->OnBubbleUiClosing(web_contents()); controller_->OnBubbleUiClosing(web_contents());
} }
void CookieControlsBubbleView::ButtonPressed(views::Button* sender, bool CookieControlsBubbleView::Accept() {
const ui::Event& event) { if (show_disable_cookie_blocking_ui_) {
if (sender == turn_off_button_) {
controller_->OnCookieBlockingEnabledForSite(false); controller_->OnCookieBlockingEnabledForSite(false);
} else { } else {
DCHECK_EQ(sender, turn_on_button_); DCHECK_EQ(status_, CookieControlsController::Status::kDisabledForSite);
controller_->OnCookieBlockingEnabledForSite(true); controller_->OnCookieBlockingEnabledForSite(true);
} }
return false;
}
bool CookieControlsBubbleView::Close() {
return Cancel();
}
void CookieControlsBubbleView::LinkClicked(views::Link* source,
int event_flags) {
DCHECK_EQ(source, not_working_link_);
DCHECK_EQ(status_, CookieControlsController::Status::kEnabled);
// Don't go through the controller as this is an intermediary state that
// is only relevant for the bubble UI.
show_disable_cookie_blocking_ui_ = true;
UpdateUi();
} }
...@@ -6,11 +6,13 @@ ...@@ -6,11 +6,13 @@
#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_COOKIE_CONTROLS_BUBBLE_VIEW_H_ #define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_COOKIE_CONTROLS_BUBBLE_VIEW_H_
#include "base/macros.h" #include "base/macros.h"
#include "base/optional.h"
#include "chrome/browser/ui/cookie_controls/cookie_controls_controller.h" #include "chrome/browser/ui/cookie_controls/cookie_controls_controller.h"
#include "chrome/browser/ui/cookie_controls/cookie_controls_view.h" #include "chrome/browser/ui/cookie_controls/cookie_controls_view.h"
#include "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h" #include "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h"
#include "components/content_settings/core/browser/cookie_settings.h" #include "components/content_settings/core/browser/cookie_settings.h"
#include "ui/views/controls/button/button.h" #include "ui/views/controls/button/button.h"
#include "ui/views/controls/link_listener.h"
namespace content { namespace content {
class WebContents; class WebContents;
...@@ -19,11 +21,12 @@ class WebContents; ...@@ -19,11 +21,12 @@ class WebContents;
namespace views { namespace views {
class ImageView; class ImageView;
class Label; class Label;
class Link;
} // namespace views } // namespace views
// View used to display the cookie controls ui. // View used to display the cookie controls ui.
class CookieControlsBubbleView : public LocationBarBubbleDelegateView, class CookieControlsBubbleView : public LocationBarBubbleDelegateView,
public views::ButtonListener, public views::LinkListener,
public CookieControlsView { public CookieControlsView {
public: public:
static void ShowBubble(views::View* anchor_view, static void ShowBubble(views::View* anchor_view,
...@@ -44,38 +47,40 @@ class CookieControlsBubbleView : public LocationBarBubbleDelegateView, ...@@ -44,38 +47,40 @@ class CookieControlsBubbleView : public LocationBarBubbleDelegateView,
CookieControlsController* cookie_contols); CookieControlsController* cookie_contols);
~CookieControlsBubbleView() override; ~CookieControlsBubbleView() override;
void UpdateUi(CookieControlsController::Status status, void UpdateUi();
bool has_blocked_cookies);
// LocationBarBubbleDelegateView: // LocationBarBubbleDelegateView:
void CloseBubble() override; void CloseBubble() override;
int GetDialogButtons() const override; int GetDialogButtons() const override;
base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
void Init() override; void Init() override;
base::string16 GetWindowTitle() const override;
std::unique_ptr<views::View> CreateExtraView() override;
bool ShouldShowWindowTitle() const override; bool ShouldShowWindowTitle() const override;
bool ShouldShowCloseButton() const override; bool ShouldShowCloseButton() const override;
void WindowClosing() override; void WindowClosing() override;
bool Accept() override;
bool Close() override;
gfx::Size CalculatePreferredSize() const override;
void AddedToWidget() override;
// views::ButtonListener: // views::LinkListener:
void ButtonPressed(views::Button* sender, const ui::Event& event) override; void LinkClicked(views::Link* source, int event_flags) override;
// Singleton instance of the cookie bubble. The cookie bubble can only be
// shown on the active browser window, so there is no case in which it will be
// shown twice at the same time.
static CookieControlsBubbleView* cookie_bubble_;
CookieControlsController* controller_ = nullptr; CookieControlsController* controller_ = nullptr;
CookieControlsController::Status status_ = CookieControlsController::Status status_ =
CookieControlsController::Status::kUninitialized; CookieControlsController::Status::kUninitialized;
int blocked_cookies_ = -1; // If true, display an intermediate step with a button to disable cookie
// blocking on the current site.
bool show_disable_cookie_blocking_ui_ = false;
base::Optional<int> blocked_cookies_;
views::ImageView* header_image_ = nullptr; views::ImageView* header_view_ = nullptr;
views::Button* turn_on_button_ = nullptr; views::Label* text_ = nullptr;
views::Button* turn_off_button_ = nullptr; views::Link* not_working_link_ = nullptr;
views::Label* title_ = nullptr;
views::Label* sub_title_ = nullptr;
views::View* spacer_ = nullptr;
ScopedObserver<CookieControlsController, CookieControlsView> observer_{this}; ScopedObserver<CookieControlsController, CookieControlsView> observer_{this};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment