Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bubble for enabling cookie consent blocking #14148

Merged
merged 1 commit into from
Aug 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions browser/about_flags.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
using brave_shields::features::kBraveAdblockCnameUncloaking;
using brave_shields::features::kBraveAdblockCollapseBlockedElements;
using brave_shields::features::kBraveAdblockCookieListDefault;
using brave_shields::features::kBraveAdblockCookieListOptIn;
using brave_shields::features::kBraveAdblockCosmeticFiltering;
using brave_shields::features::kBraveAdblockCosmeticFilteringChildFrames;
using brave_shields::features::kBraveAdblockCspRules;
Expand Down Expand Up @@ -90,6 +91,12 @@ constexpr char kBraveAdblockCookieListDefaultDescription[] =
"Enables the 'Easylist-Cookie List' regional list regardless of its "
"toggle setting in brave://adblock";

constexpr char kBraveAdblockCookieListOptInName[] =
"Show an opt-in bubble for the 'Easylist-Cookie List' filter";
constexpr char kBraveAdblockCookieListOptInDescription[] =
"When enabled, a bubble will be displayed inviting the user to enable the "
"'Easylist-Cookie List' filter for blocking cookie consent dialogs";

constexpr char kBraveAdblockCosmeticFilteringName[] =
"Enable cosmetic filtering";
constexpr char kBraveAdblockCosmeticFilteringDescription[] =
Expand Down Expand Up @@ -500,6 +507,10 @@ constexpr char kPlaylistDescription[] = "Enables Playlist";
flag_descriptions::kBraveAdblockCookieListDefaultName, \
flag_descriptions::kBraveAdblockCookieListDefaultDescription, \
kOsAll, FEATURE_VALUE_TYPE(kBraveAdblockCookieListDefault)}, \
{"brave-adblock-cookie-list-opt-in", \
flag_descriptions::kBraveAdblockCookieListOptInName, \
flag_descriptions::kBraveAdblockCookieListOptInDescription, \
kOsDesktop, FEATURE_VALUE_TYPE(kBraveAdblockCookieListOptIn)}, \
{"brave-adblock-cosmetic-filtering", \
flag_descriptions::kBraveAdblockCosmeticFilteringName, \
flag_descriptions::kBraveAdblockCosmeticFilteringDescription, kOsAll, \
Expand Down
8 changes: 8 additions & 0 deletions browser/brave_content_browser_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ using extensions::ChromeContentBrowserClientExtensionsPart;
#include "brave/browser/ui/webui/brave_federated/federated_internals.mojom.h"
#include "brave/browser/ui/webui/brave_federated/federated_internals_ui.h"
#include "brave/browser/ui/webui/brave_rewards/rewards_panel_ui.h"
#include "brave/browser/ui/webui/brave_shields/cookie_list_opt_in_ui.h"
#include "brave/browser/ui/webui/brave_shields/shields_panel_ui.h"
#include "brave/browser/ui/webui/brave_wallet/wallet_page_ui.h"
#include "brave/browser/ui/webui/brave_wallet/wallet_panel_ui.h"
Expand All @@ -207,6 +208,7 @@ using extensions::ChromeContentBrowserClientExtensionsPart;
#include "brave/components/brave_rewards/common/brave_rewards_panel.mojom.h"
#include "brave/components/brave_rewards/common/features.h"
#include "brave/components/brave_shields/common/brave_shields_panel.mojom.h"
#include "brave/components/brave_shields/common/cookie_list_opt_in.mojom.h"
#include "brave/components/brave_today/common/brave_news.mojom.h"
#include "brave/components/brave_today/common/features.h"
#endif
Expand Down Expand Up @@ -574,6 +576,12 @@ void BraveContentBrowserClient::RegisterBrowserInterfaceBindersForFrame(
brave_private_new_tab::mojom::PageHandler, BravePrivateNewTabUI>(map);
chrome::internal::RegisterWebUIControllerInterfaceBinder<
brave_shields::mojom::PanelHandlerFactory, ShieldsPanelUI>(map);
if (base::FeatureList::IsEnabled(
brave_shields::features::kBraveAdblockCookieListOptIn)) {
chrome::internal::RegisterWebUIControllerInterfaceBinder<
brave_shields::mojom::CookieListOptInPageHandlerFactory,
CookieListOptInUI>(map);
}
if (base::FeatureList::IsEnabled(
brave_rewards::features::kWebUIPanelFeature)) {
chrome::internal::RegisterWebUIControllerInterfaceBinder<
Expand Down
8 changes: 8 additions & 0 deletions browser/ui/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ source_set("ui") {
"webui/brave_rewards/rewards_panel_ui.h",
"webui/brave_settings_ui.cc",
"webui/brave_settings_ui.h",
"webui/brave_shields/cookie_list_opt_in_page_handler.cc",
"webui/brave_shields/cookie_list_opt_in_page_handler.h",
"webui/brave_shields/cookie_list_opt_in_ui.cc",
"webui/brave_shields/cookie_list_opt_in_ui.h",
"webui/brave_shields/shields_panel_data_handler.cc",
"webui/brave_shields/shields_panel_data_handler.h",
"webui/brave_shields/shields_panel_handler.cc",
Expand Down Expand Up @@ -184,6 +188,8 @@ source_set("ui") {
"views/brave_first_run_dialog.h",
"views/brave_layout_provider.cc",
"views/brave_layout_provider.h",
"views/brave_shields/cookie_list_opt_in_bubble_host.cc",
"views/brave_shields/cookie_list_opt_in_bubble_host.h",
"views/crash_report_permission_ask_dialog_view.cc",
"views/crash_report_permission_ask_dialog_view.h",
"views/download/brave_download_item_view.cc",
Expand Down Expand Up @@ -360,6 +366,7 @@ source_set("ui") {
deps += [
"//brave/browser/ui/views/brave_ads",
"//brave/browser/ui/views/brave_tooltips",
"//brave/components/brave_shields/common:common",
]
}

Expand Down Expand Up @@ -472,6 +479,7 @@ source_set("ui") {
"//brave/components/brave_rewards/resources:tip_generated_resources",
"//brave/components/brave_rewards/resources/rewards_panel:brave_rewards_panel_generated",
"//brave/components/brave_shields/common:mojom",
"//brave/components/brave_shields/resources/cookie_list_opt_in:cookie_list_opt_in_generated",
"//brave/components/brave_shields/resources/panel:brave_shields_panel_generated",
"//brave/components/brave_sync",
"//brave/components/brave_sync:sync_service_impl_helper",
Expand Down
236 changes: 236 additions & 0 deletions browser/ui/views/brave_shields/cookie_list_opt_in_browsertest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <algorithm>
#include <vector>

#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "brave/browser/brave_browser_process.h"
#include "brave/browser/ui/views/brave_shields/cookie_list_opt_in_bubble_host.h"
#include "brave/components/adblock_rust_ffi/src/wrapper.h"
#include "brave/components/brave_shields/browser/ad_block_regional_service_manager.h"
#include "brave/components/brave_shields/browser/ad_block_service.h"
#include "brave/components/brave_shields/common/brave_shield_constants.h"
#include "brave/components/brave_shields/common/features.h"
#include "brave/components/brave_shields/common/pref_names.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/sessions/session_restore.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_service.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "url/url_constants.h"

namespace brave_shields {

class CookieListOptInBrowserTest : public InProcessBrowserTest {
public:
static inline constexpr char kRegionalAdBlockComponentTestId[] =
"lfgnenkkneohplacnfabidofpgcdpofm";

static inline constexpr char kRegionalAdBlockComponentTest64PublicKey[] =
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqNcRp37CBZCXe1vbmXyobycPxHyE"
"KNIgNl6p0XBBxtcZcQOijpY70GjCRzgCL7m1+FBo4MR3FXLiF2aPn/"
"QsUR8t7+zfw3XzBVos4Ssexkqpd4/"
"4ciASwTXpbuyFOq4Z5dcgJ1afeT9Zj5bmh4ekLpgJ1NzVwCMhEKk6cmSKIaGVo5EEydtlor2"
"nkUJrSFuZA6tYZ++"
"4BOfhhCtzrvXTZjg7mTlB6ca21NL4oLwtqvJMtF8ddoumh619BB5wOqxLzntC/"
"oWyOxf00V5HDC7e/"
"DRj9J8jLRFLd4EQUO4Mk+kG3MNy0ph9cqdw6zFR7a2H3LGkl4ejsifM1mUDuJL0cwIDAQAB";

CookieListOptInBrowserTest() : CookieListOptInBrowserTest(true) {}
~CookieListOptInBrowserTest() override = default;

protected:
explicit CookieListOptInBrowserTest(bool enable_feature) {
if (enable_feature) {
scoped_feature_list_.InitWithFeatures(
{features::kBraveAdblockCookieListOptIn}, {});
} else {
scoped_feature_list_.InitWithFeatures(
{}, {features::kBraveAdblockCookieListOptIn});
}
}

virtual void SetUpLocalState() { InitializeFilterLists(); }

void PreRunTestOnMainThread() override {
CookieListOptInBubbleHost::AllowBubbleInBackgroundForTesting();
SetUpLocalState();
InProcessBrowserTest::PreRunTestOnMainThread();
}

auto* regional_service_manager() {
return g_brave_browser_process->ad_block_service()
->regional_service_manager();
}

content::WebContents* GetBubbleWebContents() {
auto* host = CookieListOptInBubbleHost::FromBrowser(browser());
return host ? host->GetBubbleWebContentsForTesting() : nullptr;
}

void WaitForSessionRestore() {
if (SessionRestore::IsRestoring(browser()->profile())) {
base::RunLoop run_loop;
auto subscription = SessionRestore::RegisterOnSessionRestoredCallback(
base::BindLambdaForTesting(
[&run_loop](Profile*, int) { run_loop.Quit(); }));
run_loop.Run();
}
}

bool IsCookieListFilterEnabled() {
return regional_service_manager()->IsFilterListEnabled(kCookieListUuid);
}

private:
void InitializeFilterLists() {
std::vector regional_catalog = {adblock::FilterList(
kCookieListUuid,
"https://secure.fanboy.co.nz/fanboy-cookiemonster_ubo.txt",
"Easylist-Cookie List - Filter Obtrusive Cookie Notices", {},
"https://forums.lanik.us/", kRegionalAdBlockComponentTestId,
kRegionalAdBlockComponentTest64PublicKey,
"Removes obtrusive cookie law notices")};
regional_service_manager()->SetRegionalCatalog(regional_catalog);
}

base::test::ScopedFeatureList scoped_feature_list_;
};

IN_PROC_BROWSER_TEST_F(CookieListOptInBrowserTest, EnableFromBubble) {
zenparsing marked this conversation as resolved.
Show resolved Hide resolved
auto* web_contents = GetBubbleWebContents();
ASSERT_TRUE(web_contents);

base::RunLoop run_loop;
PrefChangeRegistrar pref_observer;
pref_observer.Init(g_browser_process->local_state());
pref_observer.Add(prefs::kAdBlockRegionalFilters,
base::BindLambdaForTesting([this, &run_loop]() {
if (IsCookieListFilterEnabled()) {
run_loop.Quit();
}
}));

ASSERT_EQ(true, content::EvalJs(web_contents, R"js(
new Promise((resolve) => {
setInterval(() => {
const elem = document.querySelector('.opt-in-action button')
if (elem) {
resolve(elem)
}
}, 30)
}).then((elem) => {
elem.click()
return true
})
)js"));

run_loop.Run();

EXPECT_TRUE(IsCookieListFilterEnabled());

ASSERT_TRUE(
AddTabAtIndex(1, GURL(url::kAboutBlankURL), ui::PAGE_TRANSITION_TYPED));

WaitForLoadStop(browser()->tab_strip_model()->GetActiveWebContents());
EXPECT_FALSE(GetBubbleWebContents());
zenparsing marked this conversation as resolved.
Show resolved Hide resolved
}

IN_PROC_BROWSER_TEST_F(CookieListOptInBrowserTest, PRE_MultipleWindowRestore) {
zenparsing marked this conversation as resolved.
Show resolved Hide resolved
EXPECT_TRUE(GetBubbleWebContents());

// Create another browser window.
CreateBrowser(browser()->profile());

// Before closing, reset the "show" pref so that the opt-in will be displayed
zenparsing marked this conversation as resolved.
Show resolved Hide resolved
// again.
g_browser_process->local_state()->SetBoolean(
prefs::kAdBlockCookieListOptInShown, false);
}

IN_PROC_BROWSER_TEST_F(CookieListOptInBrowserTest, MultipleWindowRestore) {
WaitForSessionRestore();

auto* browser_list = BrowserList::GetInstance();
EXPECT_EQ(browser_list->size(), 2ul);

// Count the number of windows that are showing the bubble.
auto bubble_count = std::count_if(
browser_list->begin(), browser_list->end(), [](Browser* browser) {
if (auto* host = CookieListOptInBubbleHost::FromBrowser(browser)) {
if (host->GetBubbleWebContentsForTesting()) {
return true;
}
}
return false;
});

// Only one browser window should be showing the bubble on restore. Note that
// all browser windows will be inactive in tests. Outside of tests, the bubble
// will only be displayed on active browsers windows.
EXPECT_EQ(bubble_count, 1);
}

class CookieListOptInPreEnabledBrowserTest : public CookieListOptInBrowserTest {
public:
~CookieListOptInPreEnabledBrowserTest() override = default;

protected:
void SetUpLocalState() override {
CookieListOptInBrowserTest::SetUpLocalState();
regional_service_manager()->EnableFilterList(kCookieListUuid, true);
}
};

IN_PROC_BROWSER_TEST_F(CookieListOptInPreEnabledBrowserTest, AlreadyEnabled) {
WaitForSessionRestore();
EXPECT_FALSE(GetBubbleWebContents());
EXPECT_FALSE(g_browser_process->local_state()->GetBoolean(
prefs::kAdBlockCookieListOptInShown));
}

class CookieListOptInFirstRunBrowserTest : public CookieListOptInBrowserTest {
public:
~CookieListOptInFirstRunBrowserTest() override = default;

protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
// In browser tests, `chrome::IsChromeFirstRun()` will return `false`. Force
// first-run behavior for this test by using a command line flag.
command_line->AppendSwitch(switches::kForceFirstRun);
}
};

IN_PROC_BROWSER_TEST_F(CookieListOptInFirstRunBrowserTest, FirstRun) {
WaitForSessionRestore();
EXPECT_FALSE(GetBubbleWebContents());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we also wait for session restore, ensure the active tab has finished loading and kAdBlockCookieListOptInShown is false?

Copy link
Collaborator Author

@zenparsing zenparsing Aug 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to wait for restore and added check for kAdBlockCookieListOptInShown. Browser tests automatically wait for the first tab to finish loading (see here).

EXPECT_FALSE(IsCookieListFilterEnabled());
EXPECT_FALSE(g_browser_process->local_state()->GetBoolean(
prefs::kAdBlockCookieListOptInShown));
}

class CookieListOptInFeatureOffBrowserTest : public CookieListOptInBrowserTest {
public:
CookieListOptInFeatureOffBrowserTest() : CookieListOptInBrowserTest(false) {}
~CookieListOptInFeatureOffBrowserTest() override = default;
};

IN_PROC_BROWSER_TEST_F(CookieListOptInFeatureOffBrowserTest, FeatureOff) {
WaitForSessionRestore();
EXPECT_FALSE(GetBubbleWebContents());
EXPECT_FALSE(IsCookieListFilterEnabled());
EXPECT_FALSE(g_browser_process->local_state()->GetBoolean(
prefs::kAdBlockCookieListOptInShown));
}

} // namespace brave_shields
Loading