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.
<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
</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.">
{COUNT, plural,
=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 {
public:
enum class Status {
kUninitialized,
// Cookie blocking is enabled.
kEnabled,
// Cookie blocking is disabled.
kDisabled,
// Cookie blocking is enabled in general but was disabled for this site.
kDisabledForSite,
};
......
......@@ -6,7 +6,8 @@
#include <memory>
#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/grit/generated_resources.h"
#include "chrome/grit/theme_resources.h"
......@@ -14,16 +15,19 @@
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_types.h"
#include "ui/gfx/text_utils.h"
#include "ui/gfx/vector_icon_types.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/md_text_button.h"
#include "ui/views/bubble/bubble_frame_view.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/style/typography.h"
#include "ui/views/controls/link.h"
#include "ui/views/layout/fill_layout.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
void CookieControlsBubbleView::ShowBubble(
......@@ -33,30 +37,31 @@ void CookieControlsBubbleView::ShowBubble(
CookieControlsController* controller,
CookieControlsController::Status status) {
DCHECK(web_contents);
if (cookie_bubble_)
if (g_instance)
return;
cookie_bubble_ =
g_instance =
new CookieControlsBubbleView(anchor_view, web_contents, controller);
cookie_bubble_->SetHighlightedButton(highlighted_button);
g_instance->SetHighlightedButton(highlighted_button);
views::Widget* bubble_widget =
views::BubbleDialogDelegateView::CreateBubble(cookie_bubble_);
views::BubbleDialogDelegateView::CreateBubble(g_instance);
controller->Update(web_contents);
bubble_widget->Show();
}
// static
CookieControlsBubbleView* CookieControlsBubbleView::GetCookieBubble() {
return cookie_bubble_;
return g_instance;
}
void CookieControlsBubbleView::OnStatusChanged(
CookieControlsController::Status status) {
if (status_ == status)
CookieControlsController::Status new_status) {
if (status_ == new_status)
return;
status_ = status;
UpdateUi(status, blocked_cookies_ > 0);
show_disable_cookie_blocking_ui_ = false;
status_ = new_status;
UpdateUi();
}
void CookieControlsBubbleView::OnBlockedCookiesCountChanged(
......@@ -67,17 +72,17 @@ void CookieControlsBubbleView::OnBlockedCookiesCountChanged(
return;
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;
sub_title_->SetText(
text_->SetText(
l10n_util::GetPluralStringFUTF16(IDS_COOKIE_CONTROLS_BLOCKED_MESSAGE,
controller_->GetBlockedDomainCount()));
// 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)
UpdateUi(status_, blocked_cookies_ > 0);
UpdateUi();
}
CookieControlsBubbleView::CookieControlsBubbleView(
......@@ -91,94 +96,123 @@ CookieControlsBubbleView::CookieControlsBubbleView(
CookieControlsBubbleView::~CookieControlsBubbleView() = default;
void CookieControlsBubbleView::UpdateUi(CookieControlsController::Status status,
bool has_blocked_cookies) {
if (status == CookieControlsController::Status::kDisabled) {
void CookieControlsBubbleView::UpdateUi() {
if (status_ == CookieControlsController::Status::kDisabled) {
CloseBubble();
return;
}
if (status == CookieControlsController::Status::kEnabled) {
header_image_->SetImage(
DialogModelChanged();
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(
has_blocked_cookies ? IDR_COOKIE_BLOCKING_ON_HEADER
: IDR_COOKIE_BLOCKING_INACTIVE_HEADER));
title_->SetText(
l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_DIALOG_TITLE));
sub_title_->SetVisible(true);
spacer_->SetVisible(has_blocked_cookies);
turn_off_button_->SetVisible(has_blocked_cookies);
turn_on_button_->SetVisible(false);
text_->SetVisible(true);
not_working_link_->SetVisible(has_blocked_cookies);
blocked_cookies_.reset();
} else {
DCHECK_EQ(status, CookieControlsController::Status::kDisabledForSite);
header_image_->SetImage(
DCHECK_EQ(status_, CookieControlsController::Status::kDisabledForSite);
header_view_->SetVisible(true);
header_view_->SetImage(
ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
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();
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() {
// Widget's Close() is async, but we don't want to use cookie_bubble_ after
// this. Additionally web_contents() may have been destroyed.
cookie_bubble_ = nullptr;
g_instance = nullptr;
LocationBarBubbleDelegateView::CloseBubble();
}
int CookieControlsBubbleView::GetDialogButtons() const {
if (show_disable_cookie_blocking_ui_ ||
status_ == CookieControlsController::Status::kDisabledForSite) {
return ui::DIALOG_BUTTON_OK;
}
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() {
SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical));
header_image_ = new views::ImageView();
AddChildView(header_image_);
title_ =
new views::Label(base::string16(), views::style::CONTEXT_DIALOG_TITLE);
title_->SetBorder(views::CreateEmptyBorder(8, 0, 0, 0));
title_->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
title_->SetMultiLine(true);
AddChildView(title_);
sub_title_ = new views::Label(base::string16(), views::style::CONTEXT_LABEL);
sub_title_->SetBorder(views::CreateEmptyBorder(8, 0, 0, 0));
sub_title_->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
sub_title_->SetMultiLine(true);
AddChildView(sub_title_);
spacer_ = new views::View();
spacer_->SetPreferredSize(gfx::Size(0, 16));
AddChildView(spacer_);
auto* button_container = new views::View();
button_container->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal));
turn_on_button_ =
views::MdTextButton::CreateSecondaryUiButton(
this, l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_TURN_ON_BUTTON))
.release();
button_container->AddChildView(turn_on_button_);
turn_off_button_ =
views::MdTextButton::CreateSecondaryUiButton(
this, l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_TURN_OFF_BUTTON))
.release();
button_container->AddChildView(turn_off_button_);
AddChildView(button_container);
SetLayoutManager(std::make_unique<views::FillLayout>());
auto text = std::make_unique<views::Label>(base::string16(),
views::style::CONTEXT_LABEL);
text->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
text->SetMultiLine(true);
text_ = AddChildView(std::move(text));
}
std::unique_ptr<views::View> CookieControlsBubbleView::CreateExtraView() {
auto view = std::make_unique<views::Link>(
l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_NOT_WORKING_TITLE));
not_working_link_ = view.get();
not_working_link_->set_listener(this);
return std::move(view);
}
void CookieControlsBubbleView::AddedToWidget() {
auto header_view = std::make_unique<NonAccessibleImageView>();
header_view_ = header_view.get();
GetBubbleFrameView()->SetHeaderView(std::move(header_view));
}
gfx::Size CookieControlsBubbleView::CalculatePreferredSize() const {
// The total width of this view should always be identical to the width
// of the header images.
int width = ui::ResourceBundle::GetSharedInstance()
.GetImageSkiaNamed(IDR_COOKIE_BLOCKING_ON_HEADER)
->width();
return gfx::Size{width, GetHeightForWidth(width)};
}
base::string16 CookieControlsBubbleView::GetWindowTitle() const {
if (show_disable_cookie_blocking_ui_)
return l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_NOT_WORKING_TITLE);
switch (status_) {
case CookieControlsController::Status::kEnabled:
return l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_DIALOG_TITLE);
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 {
return false;
return true;
}
bool CookieControlsBubbleView::ShouldShowCloseButton() const {
......@@ -188,19 +222,33 @@ bool CookieControlsBubbleView::ShouldShowCloseButton() const {
void CookieControlsBubbleView::WindowClosing() {
// |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.
bool this_bubble = cookie_bubble_ == this;
bool this_bubble = g_instance == this;
if (this_bubble)
cookie_bubble_ = nullptr;
g_instance = nullptr;
controller_->OnBubbleUiClosing(web_contents());
}
void CookieControlsBubbleView::ButtonPressed(views::Button* sender,
const ui::Event& event) {
if (sender == turn_off_button_) {
bool CookieControlsBubbleView::Accept() {
if (show_disable_cookie_blocking_ui_) {
controller_->OnCookieBlockingEnabledForSite(false);
} else {
DCHECK_EQ(sender, turn_on_button_);
DCHECK_EQ(status_, CookieControlsController::Status::kDisabledForSite);
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 @@
#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_COOKIE_CONTROLS_BUBBLE_VIEW_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_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 "ui/views/controls/button/button.h"
#include "ui/views/controls/link_listener.h"
namespace content {
class WebContents;
......@@ -19,11 +21,12 @@ class WebContents;
namespace views {
class ImageView;
class Label;
class Link;
} // namespace views
// View used to display the cookie controls ui.
class CookieControlsBubbleView : public LocationBarBubbleDelegateView,
public views::ButtonListener,
public views::LinkListener,
public CookieControlsView {
public:
static void ShowBubble(views::View* anchor_view,
......@@ -44,38 +47,40 @@ class CookieControlsBubbleView : public LocationBarBubbleDelegateView,
CookieControlsController* cookie_contols);
~CookieControlsBubbleView() override;
void UpdateUi(CookieControlsController::Status status,
bool has_blocked_cookies);
void UpdateUi();
// LocationBarBubbleDelegateView:
void CloseBubble() override;
int GetDialogButtons() const override;
base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
void Init() override;
base::string16 GetWindowTitle() const override;
std::unique_ptr<views::View> CreateExtraView() override;
bool ShouldShowWindowTitle() const override;
bool ShouldShowCloseButton() const override;
void WindowClosing() override;
bool Accept() override;
bool Close() override;
gfx::Size CalculatePreferredSize() const override;
void AddedToWidget() override;
// views::ButtonListener:
void ButtonPressed(views::Button* sender, const ui::Event& event) 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_;
// views::LinkListener:
void LinkClicked(views::Link* source, int event_flags) override;
CookieControlsController* controller_ = nullptr;
CookieControlsController::Status status_ =
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::Button* turn_on_button_ = nullptr;
views::Button* turn_off_button_ = nullptr;
views::Label* title_ = nullptr;
views::Label* sub_title_ = nullptr;
views::View* spacer_ = nullptr;
views::ImageView* header_view_ = nullptr;
views::Label* text_ = nullptr;
views::Link* not_working_link_ = nullptr;
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