blob: ee9531308cdfc5732fe2724e82374f315ed92209 [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/browsing_data/browsing_data_remover_impl.h"
#include <stddef.h>
#include <stdint.h>
#include <list>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/run_loop.h"
#include "base/scoped_observation.h"
#include "base/strings/strcat.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/cancelable_task_tracker.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/bind.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_future.h"
#include "base/threading/sequence_bound.h"
#include "base/time/time.h"
#include "components/fingerprinting_protection_filter/interventions/common/interventions_features.h"
#include "content/browser/btm/btm_service_impl.h"
#include "content/browser/btm/btm_storage.h"
#include "content/browser/btm/btm_test_utils.h"
#include "content/browser/btm/btm_utils.h"
#include "content/browser/fingerprinting_protection/canvas_noise_token_data.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/browsing_data_filter_builder.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/browsing_data_remover_delegate.h"
#include "content/public/browser/cookie_store_factory.h"
#include "content/public/browser/dom_storage_context.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/storage_partition_config.h"
#include "content/public/browser/storage_usage_info.h"
#include "content/public/common/content_client.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/browsing_data_remover_test_util.h"
#include "content/public/test/mock_download_manager.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_storage_partition.h"
#include "content/public/test/test_utils.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_access_params.h"
#include "net/cookies/cookie_deletion_info.h"
#include "net/cookies/cookie_store.h"
#include "net/http/http_network_session.h"
#include "net/http/http_transaction_factory.h"
#include "services/network/cookie_manager.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/test/test_network_context.h"
#include "storage/browser/test/mock_special_storage_policy.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "url/origin.h"
using base::test::RunOnceClosure;
using testing::_;
using testing::ByRef;
using testing::Eq;
using testing::Invoke;
using testing::IsEmpty;
using testing::MakeMatcher;
using testing::Matcher;
using testing::MatcherInterface;
using testing::MatchResultListener;
using testing::Not;
using testing::Return;
using testing::SizeIs;
using testing::StrictMock;
using testing::Truly;
using testing::UnorderedElementsAre;
using testing::WithArgs;
using CookieDeletionFilterPtr = network::mojom::CookieDeletionFilterPtr;
namespace content {
namespace {
struct StoragePartitionRemovalData {
StoragePartitionRemovalData()
: remove_mask(0),
quota_storage_remove_mask(0),
cookie_deletion_filter(network::mojom::CookieDeletionFilter::New()),
remove_code_cache(false) {}
StoragePartitionRemovalData(const StoragePartitionRemovalData& other)
: remove_mask(other.remove_mask),
quota_storage_remove_mask(other.quota_storage_remove_mask),
remove_begin(other.remove_begin),
remove_end(other.remove_end),
filter_builder(other.filter_builder ? other.filter_builder->Copy()
: nullptr),
storage_key_policy_matcher(other.storage_key_policy_matcher),
cookie_deletion_filter(other.cookie_deletion_filter.Clone()),
remove_code_cache(other.remove_code_cache),
url_matcher(other.url_matcher) {}
StoragePartitionRemovalData& operator=(
const StoragePartitionRemovalData& rhs) {
remove_mask = rhs.remove_mask;
quota_storage_remove_mask = rhs.quota_storage_remove_mask;
remove_begin = rhs.remove_begin;
remove_end = rhs.remove_end;
filter_builder = rhs.filter_builder ? rhs.filter_builder->Copy() : nullptr;
storage_key_policy_matcher = rhs.storage_key_policy_matcher;
cookie_deletion_filter = rhs.cookie_deletion_filter.Clone();
remove_code_cache = rhs.remove_code_cache;
url_matcher = rhs.url_matcher;
return *this;
}
uint32_t remove_mask;
uint32_t quota_storage_remove_mask;
base::Time remove_begin;
base::Time remove_end;
std::unique_ptr<BrowsingDataFilterBuilder> filter_builder;
StoragePartition::StorageKeyPolicyMatcherFunction storage_key_policy_matcher;
CookieDeletionFilterPtr cookie_deletion_filter;
bool remove_code_cache;
base::RepeatingCallback<bool(const GURL&)> url_matcher;
};
net::CanonicalCookie CreateCookieWithHost(const url::Origin& origin) {
std::unique_ptr<net::CanonicalCookie> cookie =
net::CanonicalCookie::CreateUnsafeCookieForTesting(
"A", "1", origin.host(), "/", base::Time::Now(), base::Time::Now(),
base::Time(), base::Time(), false, false,
net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_MEDIUM);
EXPECT_TRUE(cookie);
return *cookie;
}
class StoragePartitionRemovalTestStoragePartition
: public TestStoragePartition {
public:
StoragePartitionRemovalTestStoragePartition() {
set_network_context(&network_context_);
}
StoragePartitionRemovalTestStoragePartition(
const StoragePartitionRemovalTestStoragePartition&) = delete;
StoragePartitionRemovalTestStoragePartition& operator=(
const StoragePartitionRemovalTestStoragePartition&) = delete;
~StoragePartitionRemovalTestStoragePartition() override = default;
void ClearDataForOrigin(uint32_t remove_mask,
uint32_t quota_storage_remove_mask,
const GURL& storage_origin,
base::OnceClosure callback) override {}
void ClearData(uint32_t remove_mask,
uint32_t quota_storage_remove_mask,
const blink::StorageKey& storage_key,
const base::Time begin,
const base::Time end,
base::OnceClosure callback) override {
// Store stuff to verify parameters' correctness later.
StoragePartitionRemovalData data;
data.remove_mask = remove_mask;
data.quota_storage_remove_mask = quota_storage_remove_mask;
data.remove_begin = begin;
data.remove_end = end;
storage_partition_removal_data_.push_back(std::move(data));
GetUIThreadTaskRunner({})->PostTask(FROM_HERE, std::move(callback));
}
void ClearData(uint32_t remove_mask,
uint32_t quota_storage_remove_mask,
BrowsingDataFilterBuilder* filter_builder,
StorageKeyPolicyMatcherFunction storage_key_policy_matcher,
CookieDeletionFilterPtr cookie_deletion_filter,
bool perform_storage_cleanup,
const base::Time begin,
const base::Time end,
base::OnceClosure callback) override {
// Store stuff to verify parameters' correctness later.
StoragePartitionRemovalData data;
data.remove_mask = remove_mask;
data.quota_storage_remove_mask = quota_storage_remove_mask;
data.remove_begin = begin;
data.remove_end = end;
data.filter_builder = filter_builder ? filter_builder->Copy() : nullptr;
data.storage_key_policy_matcher = std::move(storage_key_policy_matcher);
data.cookie_deletion_filter = std::move(cookie_deletion_filter);
storage_partition_removal_data_.push_back(std::move(data));
GetUIThreadTaskRunner({})->PostTask(FROM_HERE, std::move(callback));
}
void ClearCodeCaches(
base::Time begin,
base::Time end,
const base::RepeatingCallback<bool(const GURL&)>& url_matcher,
base::OnceClosure callback) override {
StoragePartitionRemovalData data;
data.remove_code_cache = true;
data.remove_begin = begin;
data.remove_end = end;
data.url_matcher = url_matcher;
storage_partition_removal_data_.push_back(std::move(data));
}
std::vector<StoragePartitionRemovalData> GetStoragePartitionRemovalData() {
return std::move(storage_partition_removal_data_);
}
void ClearDataForBuckets(const blink::StorageKey& storage_key,
const std::set<std::string>& buckets,
base::OnceClosure callback) override {
std::move(callback).Run();
}
private:
std::vector<StoragePartitionRemovalData> storage_partition_removal_data_;
network::TestNetworkContext network_context_;
};
// Custom matcher to test the equivalence of two URL filters. Since those are
// blackbox predicates, we can only approximate the equivalence by testing
// whether the filter give the same answer for several URLs. This is currently
// good enough for our testing purposes, to distinguish deletelists and
// preservelists, empty and non-empty filters and such.
//
// TODO(msramek): BrowsingDataRemover and some of its backends support URL
// filters, but its constructor currently only takes a single URL and constructs
// its own url filter. If an url filter was directly passed to
// BrowsingDataRemover (what should eventually be the case), we can use the same
// instance in the test as well, and thus simply test
// base::RepeatingCallback::Equals() in this matcher.
class ProbablySameFilterMatcher
: public MatcherInterface<
const base::RepeatingCallback<bool(const GURL&)>&> {
public:
explicit ProbablySameFilterMatcher(
base::RepeatingCallback<bool(const GURL&)> filter)
: to_match_(std::move(filter)) {}
bool MatchAndExplain(const base::RepeatingCallback<bool(const GURL&)>& filter,
MatchResultListener* listener) const override {
if (!filter && !to_match_) {
return true;
}
if (!filter || !to_match_) {
return false;
}
const GURL urls_to_test_[] = {GURL("a.com"), GURL("b.com"), GURL("c.com"),
GURL("invalid spec")};
for (GURL url : urls_to_test_) {
if (filter.Run(url) != to_match_.Run(url)) {
if (listener)
*listener << "The filters differ on the URL " << url;
return false;
}
}
return true;
}
void DescribeTo(::std::ostream* os) const override {
*os << "is probably the same url filter as " << &to_match_;
}
void DescribeNegationTo(::std::ostream* os) const override {
*os << "is definitely NOT the same url filter as " << &to_match_;
}
private:
const base::RepeatingCallback<bool(const GURL&)> to_match_;
};
inline Matcher<const base::RepeatingCallback<bool(const GURL&)>&>
ProbablySameFilter(base::RepeatingCallback<bool(const GURL&)> filter) {
return MakeMatcher(new ProbablySameFilterMatcher(std::move(filter)));
}
base::Time AnHourAgo() {
return base::Time::Now() - base::Hours(1);
}
bool FilterMatchesCookie(const CookieDeletionFilterPtr& filter,
const net::CanonicalCookie& cookie) {
return network::DeletionFilterToInfo(filter.Clone())
.Matches(cookie, net::CookieAccessParams{
net::CookieAccessSemantics::NONLEGACY,
net::CookieScopeSemantics::UNKNOWN, false});
}
class TestBrowsingDataRemoverDelegate
: public content::BrowsingDataRemoverDelegate {
public:
// BrowsingDataRemoverDelegate:
std::vector<std::string> GetDomainsForDeferredCookieDeletion(
StoragePartition* storage_partition,
uint64_t remove_mask) override {
return deferred_domains_;
}
BrowsingDataRemoverDelegate::EmbedderOriginTypeMatcher GetOriginTypeMatcher()
override {
return base::NullCallback();
}
bool MayRemoveDownloadHistory() override { return false; }
void RemoveEmbedderData(
const base::Time& delete_begin,
const base::Time& delete_end,
uint64_t remove_mask,
BrowsingDataFilterBuilder* filter_builder,
uint64_t origin_type_mask,
base::OnceCallback<void(uint64_t)> callback) override {
std::move(callback).Run(failed_data_types_);
}
void set_deferred_domains(std::vector<std::string> deferred_domains) {
deferred_domains_ = deferred_domains;
}
void set_failed_data_types(uint64_t failed_data_types) {
failed_data_types_ = failed_data_types;
}
private:
std::vector<std::string> deferred_domains_;
uint64_t failed_data_types_ = 0;
};
} // namespace
// Testers -------------------------------------------------------------------
class RemoveDownloadsTester {
public:
explicit RemoveDownloadsTester(BrowserContext* browser_context)
: download_manager_(new MockDownloadManager()) {
browser_context->SetDownloadManagerForTesting(
base::WrapUnique(download_manager_.get()));
EXPECT_EQ(download_manager_, browser_context->GetDownloadManager());
EXPECT_CALL(*download_manager_, Shutdown());
}
RemoveDownloadsTester(const RemoveDownloadsTester&) = delete;
RemoveDownloadsTester& operator=(const RemoveDownloadsTester&) = delete;
~RemoveDownloadsTester() = default;
MockDownloadManager* download_manager() { return download_manager_; }
private:
raw_ptr<MockDownloadManager> download_manager_; // Owned by browser context.
};
// Test Class ----------------------------------------------------------------
class BrowsingDataRemoverImplTest : public testing::Test {
public:
BrowsingDataRemoverImplTest() : BrowsingDataRemoverImplTest(nullptr) {}
explicit BrowsingDataRemoverImplTest(
std::unique_ptr<ContentBrowserClient> browser_client)
: browser_client_(std::move(browser_client)) {
if (browser_client_) {
browser_client_setting_.emplace(browser_client_.get());
}
browser_context_ = std::make_unique<TestBrowserContext>();
remover_ = static_cast<BrowsingDataRemoverImpl*>(
browser_context_->GetBrowsingDataRemover());
storage_partition_ =
std::make_unique<StoragePartitionRemovalTestStoragePartition>();
RegisterStoragePartition(
StoragePartitionConfig::CreateDefault(browser_context_.get()),
storage_partition_.get());
}
BrowsingDataRemoverImplTest(const BrowsingDataRemoverImplTest&) = delete;
BrowsingDataRemoverImplTest& operator=(const BrowsingDataRemoverImplTest&) =
delete;
~BrowsingDataRemoverImplTest() override {
remover_ = nullptr;
}
void TearDown() override {
mock_policy_ = nullptr;
remover_ = nullptr;
// BrowserContext contains a DOMStorageContext. BrowserContext's
// destructor posts a message to the WEBKIT thread to delete some of its
// member variables. We need to ensure that the browser context is
// destroyed, and that the message loop is cleared out, before destroying
// the threads and loop. Otherwise we leak memory.
browser_context_.reset();
RunAllTasksUntilIdle();
}
void RegisterStoragePartition(const StoragePartitionConfig& config,
StoragePartition* storage_partition) {
remover_->OverrideStoragePartitionForTesting(config, storage_partition);
}
void BlockUntilBrowsingDataRemoved(const base::Time& delete_begin,
const base::Time& delete_end,
uint64_t remove_mask,
bool include_protected_origins) {
uint64_t origin_type_mask =
BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB;
if (include_protected_origins)
origin_type_mask |= BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB;
BrowsingDataRemoverCompletionObserver completion_observer(remover_);
remover_->RemoveAndReply(delete_begin, delete_end, remove_mask,
origin_type_mask, &completion_observer);
completion_observer.BlockUntilCompletion();
// Save so we can verify later.
storage_partition_removal_data_ =
storage_partition_->GetStoragePartitionRemovalData();
}
void BlockUntilOriginDataRemoved(
const base::Time& delete_begin,
const base::Time& delete_end,
uint64_t remove_mask,
std::unique_ptr<BrowsingDataFilterBuilder> filter_builder) {
BrowsingDataRemoverCompletionObserver completion_observer(remover_);
remover_->RemoveWithFilterAndReply(
delete_begin, delete_end, remove_mask,
BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
std::move(filter_builder), &completion_observer);
completion_observer.BlockUntilCompletion();
// Save so we can verify later.
storage_partition_removal_data_ =
storage_partition_->GetStoragePartitionRemovalData();
}
BrowserContext* GetBrowserContext() { return browser_context_.get(); }
void DestroyBrowserContext() {
remover_ = nullptr;
browser_context_.reset();
}
const base::Time& GetBeginTime() {
return remover_->GetLastUsedBeginTimeForTesting();
}
uint64_t GetRemovalMask() {
return remover_->GetLastUsedRemovalMaskForTesting();
}
uint64_t GetOriginTypeMask() {
return remover_->GetLastUsedOriginTypeMaskForTesting();
}
// Expects that there is exactly one StoragePartitionRemovalData. Use
// GetStoragePartitionRemovalDataList() for zero or multiple deletions.
const StoragePartitionRemovalData& GetStoragePartitionRemovalData() {
EXPECT_EQ(storage_partition_removal_data_.size(), 1u);
return storage_partition_removal_data_.back();
}
std::vector<StoragePartitionRemovalData>
GetStoragePartitionRemovalDataListAndReset() {
return std::move(storage_partition_removal_data_);
}
storage::MockSpecialStoragePolicy* CreateMockPolicy() {
mock_policy_ = base::MakeRefCounted<storage::MockSpecialStoragePolicy>();
return mock_policy_.get();
}
storage::MockSpecialStoragePolicy* mock_policy() {
return mock_policy_.get();
}
void set_network_context_override(network::mojom::NetworkContext* context) {
network_context_override_ = context;
if (network_context_override_) {
storage_partition_->set_network_context(network_context_override_);
}
}
bool Match(const GURL& origin,
uint64_t mask,
storage::SpecialStoragePolicy* policy) {
return remover_->DoesOriginMatchMaskForTesting(
mask, url::Origin::Create(origin), policy);
}
private:
std::unique_ptr<ContentBrowserClient> browser_client_;
std::optional<ScopedContentBrowserClientSetting> browser_client_setting_;
std::unique_ptr<StoragePartitionRemovalTestStoragePartition>
storage_partition_;
// Cached pointer to BrowsingDataRemoverImpl for access to testing methods.
raw_ptr<BrowsingDataRemoverImpl> remover_;
BrowserTaskEnvironment task_environment_;
std::unique_ptr<BrowserContext> browser_context_;
raw_ptr<network::mojom::NetworkContext> network_context_override_ = nullptr;
std::vector<StoragePartitionRemovalData> storage_partition_removal_data_;
scoped_refptr<storage::MockSpecialStoragePolicy> mock_policy_;
};
// Tests ---------------------------------------------------------------------
TEST_F(BrowsingDataRemoverImplTest, RemoveCookieForever) {
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_COOKIES, false);
EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_COOKIES, GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Verify that storage partition was instructed to remove the cookies.
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_COOKIES |
StoragePartition::REMOVE_DATA_MASK_INTEREST_GROUPS |
StoragePartition::REMOVE_KEEPALIVE_LOADS_ATTEMPTING_RETRY);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
EXPECT_EQ(removal_data.remove_begin, GetBeginTime());
}
TEST_F(BrowsingDataRemoverImplTest, RemoveCookieLastHour) {
BlockUntilBrowsingDataRemoved(AnHourAgo(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_COOKIES, false);
EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_COOKIES, GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Verify that storage partition was instructed to remove the cookies.
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_COOKIES |
StoragePartition::REMOVE_DATA_MASK_INTEREST_GROUPS |
StoragePartition::REMOVE_KEEPALIVE_LOADS_ATTEMPTING_RETRY);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
EXPECT_EQ(removal_data.remove_begin, GetBeginTime());
}
TEST_F(BrowsingDataRemoverImplTest, RemoveCookiesDomainPreserveList) {
std::unique_ptr<BrowsingDataFilterBuilder> filter(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kPreserve));
const GURL kTestUrl1("http://host1.com");
const GURL kTestUrl3("http://host3.com");
filter->AddRegisterableDomain(kTestUrl1.host());
filter->AddRegisterableDomain(kTestUrl3.host());
BlockUntilOriginDataRemoved(AnHourAgo(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_COOKIES,
std::move(filter));
EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_COOKIES, GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Verify that storage partition was instructed to remove the cookies.
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_COOKIES |
StoragePartition::REMOVE_DATA_MASK_INTEREST_GROUPS |
StoragePartition::REMOVE_KEEPALIVE_LOADS_ATTEMPTING_RETRY);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
EXPECT_EQ(removal_data.remove_begin, GetBeginTime());
const url::Origin kTestOrigin1 = url::Origin::Create(kTestUrl1);
const url::Origin kTestOrigin2 =
url::Origin::Create(GURL("http://host2.com"));
const url::Origin kTestOrigin3 = url::Origin::Create(kTestUrl3);
const url::Origin kTestOrigin3Secure =
url::Origin::Create(GURL("https://host3.com"));
ASSERT_TRUE(removal_data.filter_builder);
StoragePartition::StorageKeyMatcherFunction storage_key_matcher =
removal_data.filter_builder->BuildStorageKeyFilter();
EXPECT_FALSE(storage_key_matcher.Run(
blink::StorageKey::CreateFirstParty(kTestOrigin1)));
EXPECT_TRUE(storage_key_matcher.Run(
blink::StorageKey::CreateFirstParty(kTestOrigin2)));
EXPECT_FALSE(storage_key_matcher.Run(
blink::StorageKey::CreateFirstParty(kTestOrigin3)));
// Even though it's a different origin, it's the same domain.
EXPECT_FALSE(storage_key_matcher.Run(
blink::StorageKey::CreateFirstParty(kTestOrigin3Secure)));
EXPECT_FALSE(FilterMatchesCookie(removal_data.cookie_deletion_filter,
CreateCookieWithHost(kTestOrigin1)));
EXPECT_TRUE(FilterMatchesCookie(removal_data.cookie_deletion_filter,
CreateCookieWithHost(kTestOrigin2)));
EXPECT_FALSE(FilterMatchesCookie(removal_data.cookie_deletion_filter,
CreateCookieWithHost(kTestOrigin3)));
// This is false, because this is the same domain as 3, just with a different
// scheme.
EXPECT_FALSE(FilterMatchesCookie(removal_data.cookie_deletion_filter,
CreateCookieWithHost(kTestOrigin3Secure)));
}
TEST_F(BrowsingDataRemoverImplTest, RemoveUnprotectedLocalStorageForever) {
storage::MockSpecialStoragePolicy* policy = CreateMockPolicy();
// Protect the test origin.
const url::Origin kTestOrigin = url::Origin::Create(GURL("http://host1.com"));
policy->AddProtected(kTestOrigin.GetURL());
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_LOCAL_STORAGE,
false);
EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_LOCAL_STORAGE, GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Verify that storage partition was instructed to remove the data correctly.
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
EXPECT_EQ(removal_data.remove_begin, GetBeginTime());
ASSERT_TRUE(removal_data.filter_builder);
EXPECT_TRUE(removal_data.filter_builder->MatchesAllOriginsAndDomains());
// Check storage key policy matcher.
EXPECT_FALSE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFirstParty(kTestOrigin), mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host2.com"),
mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host3.com"),
mock_policy()));
EXPECT_FALSE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting(
"chrome-extension://abcdefghijklmnopqrstuvwxyz/"),
mock_policy()));
}
TEST_F(BrowsingDataRemoverImplTest, RemoveProtectedLocalStorageForever) {
// Protect the test origin.
storage::MockSpecialStoragePolicy* policy = CreateMockPolicy();
const url::Origin kTestOrigin = url::Origin::Create(GURL("http://host1.com"));
policy->AddProtected(kTestOrigin.GetURL());
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_LOCAL_STORAGE,
true);
EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_LOCAL_STORAGE, GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB |
BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB,
GetOriginTypeMask());
// Verify that storage partition was instructed to remove the data correctly.
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
EXPECT_EQ(removal_data.remove_begin, GetBeginTime());
ASSERT_TRUE(removal_data.filter_builder);
EXPECT_TRUE(removal_data.filter_builder->MatchesAllOriginsAndDomains());
// Check storage key policy matcher all http origin will match since we
// specified both protected and unprotected.
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFirstParty(kTestOrigin), mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host2.com"),
mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host3.com"),
mock_policy()));
EXPECT_FALSE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting(
"chrome-extension://abcdefghijklmnopqrstuvwxyz/"),
mock_policy()));
}
TEST_F(BrowsingDataRemoverImplTest, RemoveLocalStorageForLastWeek) {
CreateMockPolicy();
BlockUntilBrowsingDataRemoved(
base::Time::Now() - base::Days(7), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_LOCAL_STORAGE, false);
EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_LOCAL_STORAGE, GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Verify that storage partition was instructed to remove the data correctly.
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
EXPECT_EQ(removal_data.remove_begin, GetBeginTime());
ASSERT_TRUE(removal_data.filter_builder);
EXPECT_TRUE(removal_data.filter_builder->MatchesAllOriginsAndDomains());
// Check storage key policy matcher.
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host1.com"),
mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host2.com"),
mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host3.com"),
mock_policy()));
EXPECT_FALSE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting(
"chrome-extension://abcdefghijklmnopqrstuvwxyz/"),
mock_policy()));
}
TEST_F(BrowsingDataRemoverImplTest, RemoveMultipleTypes) {
// Downloads should be deleted through the DownloadManager, assure it would
// be called.
RemoveDownloadsTester downloads_tester(GetBrowserContext());
EXPECT_CALL(*downloads_tester.download_manager(),
RemoveDownloadsByURLAndTime(_, _, _));
uint64_t removal_mask = BrowsingDataRemover::DATA_TYPE_DOWNLOADS |
BrowsingDataRemover::DATA_TYPE_COOKIES;
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(), removal_mask,
false);
EXPECT_EQ(removal_mask, GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// The cookie would be deleted throught the StorageParition, check if the
// partition was requested to remove cookie.
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_COOKIES |
StoragePartition::REMOVE_DATA_MASK_INTEREST_GROUPS |
StoragePartition::REMOVE_KEEPALIVE_LOADS_ATTEMPTING_RETRY);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
}
TEST_F(BrowsingDataRemoverImplTest, RemoveQuotaManagedDataForeverBoth) {
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
false);
EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Verify storage partition related stuffs.
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS |
StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS |
StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE |
StoragePartition::REMOVE_DATA_MASK_INDEXEDDB);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
}
TEST_F(BrowsingDataRemoverImplTest,
RemoveQuotaManagedDataForeverOnlyTemporary) {
CreateMockPolicy();
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
false);
EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Verify storage partition related stuffs.
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS |
StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS |
StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE |
StoragePartition::REMOVE_DATA_MASK_INDEXEDDB);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
ASSERT_TRUE(removal_data.filter_builder);
EXPECT_TRUE(removal_data.filter_builder->MatchesAllOriginsAndDomains());
// Check that all related origin data would be removed, that is, origin
// matcher would match these origin.
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host1.com"),
mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host2.com"),
mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host3.com"),
mock_policy()));
}
TEST_F(BrowsingDataRemoverImplTest,
RemoveQuotaManagedDataForeverOnlyPersistent) {
CreateMockPolicy();
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
false);
EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Verify storage partition related stuffs.
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS |
StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS |
StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE |
StoragePartition::REMOVE_DATA_MASK_INDEXEDDB);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
ASSERT_TRUE(removal_data.filter_builder);
EXPECT_TRUE(removal_data.filter_builder->MatchesAllOriginsAndDomains());
// Check that all related origin data would be removed, that is, storage key
// policy matcher would match these origin.
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host1.com"),
mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host2.com"),
mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host3.com"),
mock_policy()));
}
TEST_F(BrowsingDataRemoverImplTest, RemoveQuotaManagedDataForeverNeither) {
CreateMockPolicy();
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
false);
EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Verify storage partition related stuffs.
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS |
StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS |
StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE |
StoragePartition::REMOVE_DATA_MASK_INDEXEDDB);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
ASSERT_TRUE(removal_data.filter_builder);
EXPECT_TRUE(removal_data.filter_builder->MatchesAllOriginsAndDomains());
// Check that all related origin data would be removed, that is, storage key
// policy matcher would match these origin.
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host1.com"),
mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host2.com"),
mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host3.com"),
mock_policy()));
}
TEST_F(BrowsingDataRemoverImplTest,
RemoveQuotaManagedDataForeverSpecificOrigin) {
std::unique_ptr<BrowsingDataFilterBuilder> builder(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kDelete));
const GURL kTestUrl("http://host1.com");
builder->AddRegisterableDomain(kTestUrl.host());
// Remove the test origin.
BlockUntilOriginDataRemoved(base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
std::move(builder));
EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Verify storage partition related stuffs.
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS |
StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS |
StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE |
StoragePartition::REMOVE_DATA_MASK_INDEXEDDB);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
ASSERT_TRUE(removal_data.filter_builder);
StoragePartition::StorageKeyMatcherFunction storage_key_matcher =
removal_data.filter_builder->BuildStorageKeyFilter();
EXPECT_TRUE(storage_key_matcher.Run(
blink::StorageKey::CreateFirstParty(url::Origin::Create(kTestUrl))));
EXPECT_FALSE(storage_key_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host2.com")));
EXPECT_FALSE(storage_key_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host3.com")));
EXPECT_FALSE(storage_key_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("https://host3.com")));
}
TEST_F(BrowsingDataRemoverImplTest, RemoveQuotaManagedDataForLastHour) {
BlockUntilBrowsingDataRemoved(
AnHourAgo(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
false);
EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Verify storage partition related stuffs.
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS |
StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS |
StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE |
StoragePartition::REMOVE_DATA_MASK_INDEXEDDB);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
// Check removal begin time.
EXPECT_EQ(removal_data.remove_begin, GetBeginTime());
}
TEST_F(BrowsingDataRemoverImplTest, RemoveQuotaManagedDataForLastWeek) {
BlockUntilBrowsingDataRemoved(
base::Time::Now() - base::Days(7), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
false);
EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Verify storage partition related stuffs.
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS |
StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS |
StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE |
StoragePartition::REMOVE_DATA_MASK_INDEXEDDB);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
// Check removal begin time.
EXPECT_EQ(removal_data.remove_begin, GetBeginTime());
}
TEST_F(BrowsingDataRemoverImplTest, RemoveQuotaManagedUnprotectedOrigins) {
storage::MockSpecialStoragePolicy* policy = CreateMockPolicy();
// Protect the test origin.
const url::Origin kTestOrigin = url::Origin::Create(GURL("http://host1.com"));
policy->AddProtected(kTestOrigin.GetURL());
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
false);
EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Verify storage partition related stuffs.
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS |
StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS |
StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE |
StoragePartition::REMOVE_DATA_MASK_INDEXEDDB);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
ASSERT_TRUE(removal_data.filter_builder);
EXPECT_TRUE(removal_data.filter_builder->MatchesAllOriginsAndDomains());
// Check StorageKeyPolicyMatcherFunction.
EXPECT_FALSE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFirstParty(kTestOrigin), mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host2.com"),
mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host3.com"),
mock_policy()));
}
TEST_F(BrowsingDataRemoverImplTest, RemoveQuotaManagedProtectedSpecificOrigin) {
storage::MockSpecialStoragePolicy* policy = CreateMockPolicy();
// Protect the test origin.
const GURL kTestUrl("http://host1.com");
policy->AddProtected(kTestUrl);
std::unique_ptr<BrowsingDataFilterBuilder> builder(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kDelete));
builder->AddRegisterableDomain(kTestUrl.host());
// Try to remove the test origin. Expect failure.
BlockUntilOriginDataRemoved(base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
std::move(builder));
EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Verify storage partition related stuffs.
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS |
StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS |
StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE |
StoragePartition::REMOVE_DATA_MASK_INDEXEDDB);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
ASSERT_TRUE(removal_data.filter_builder);
StoragePartition::StorageKeyMatcherFunction storage_key_matcher =
removal_data.filter_builder->BuildStorageKeyFilter();
// Check StorageKeyPolicyMatcherFunction.
EXPECT_TRUE(storage_key_matcher.Run(
blink::StorageKey::CreateFirstParty(url::Origin::Create(kTestUrl))));
EXPECT_FALSE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFirstParty(url::Origin::Create(kTestUrl)),
mock_policy()));
// Since we use the matcher function to validate origins now, this should
// return false for the origins we're not trying to clear.
EXPECT_FALSE(storage_key_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host2.com")));
EXPECT_FALSE(storage_key_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host3.com")));
}
TEST_F(BrowsingDataRemoverImplTest, RemoveQuotaManagedProtectedOrigins) {
storage::MockSpecialStoragePolicy* policy = CreateMockPolicy();
// Protect the test origin.
const url::Origin kTestOrigin = url::Origin::Create(GURL("http://host1.com"));
policy->AddProtected(kTestOrigin.GetURL());
// Try to remove the test origin. Expect success.
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
true);
EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB |
BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Verify storage partition related stuffs.
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS |
StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS |
StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE |
StoragePartition::REMOVE_DATA_MASK_INDEXEDDB);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
ASSERT_TRUE(removal_data.filter_builder);
EXPECT_TRUE(removal_data.filter_builder->MatchesAllOriginsAndDomains());
// Check StorageKeyPolicyMatcherFunction, `kTestOrigin` would match mask since
// we would have 'protected' specified in origin_type_mask.
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFirstParty(kTestOrigin), mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host2.com"),
mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host3.com"),
mock_policy()));
}
TEST_F(BrowsingDataRemoverImplTest,
RemoveQuotaManagedIgnoreExtensionsAndDevTools) {
CreateMockPolicy();
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
false);
EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Verify storage partition related stuffs.
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS |
StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS |
StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE |
StoragePartition::REMOVE_DATA_MASK_INDEXEDDB);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
ASSERT_TRUE(removal_data.filter_builder);
EXPECT_TRUE(removal_data.filter_builder->MatchesAllOriginsAndDomains());
// Check that extension and devtools data wouldn't be removed, that is,
// stoarge key policy matcher would not match these origin.
EXPECT_FALSE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting(
"chrome-extension://abcdefghijklmnopqrstuvwxyz/"),
mock_policy()));
EXPECT_FALSE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting(
"devtools://abcdefghijklmnopqrstuvw/"),
mock_policy()));
}
class InspectableCompletionObserver
: public BrowsingDataRemoverCompletionObserver {
public:
explicit InspectableCompletionObserver(BrowsingDataRemover* remover)
: BrowsingDataRemoverCompletionObserver(remover) {}
~InspectableCompletionObserver() override = default;
bool called() { return called_; }
protected:
void OnBrowsingDataRemoverDone(uint64_t failed_data_types) override {
BrowsingDataRemoverCompletionObserver::OnBrowsingDataRemoverDone(
failed_data_types);
called_ = true;
}
private:
bool called_ = false;
};
TEST_F(BrowsingDataRemoverImplTest, CompletionInhibition) {
BrowsingDataRemoverImpl* remover = static_cast<BrowsingDataRemoverImpl*>(
GetBrowserContext()->GetBrowsingDataRemover());
// The |completion_inhibitor| on the stack should prevent removal sessions
// from completing until after ContinueToCompletion() is called.
BrowsingDataRemoverCompletionInhibitor completion_inhibitor(remover);
InspectableCompletionObserver completion_observer(remover);
remover->RemoveAndReply(
base::Time(), base::Time::Max(), BrowsingDataRemover::DATA_TYPE_COOKIES,
BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB, &completion_observer);
// Process messages until the inhibitor is notified, and then some, to make
// sure we do not complete asynchronously before ContinueToCompletion() is
// called.
completion_inhibitor.BlockUntilNearCompletion();
RunAllTasksUntilIdle();
// Verify that the removal has not yet been completed and the observer has
// not been called.
EXPECT_TRUE(remover->IsRemovingForTesting());
EXPECT_FALSE(completion_observer.called());
// Now run the removal process until completion, and verify that observers are
// now notified, and the notifications is sent out.
completion_inhibitor.ContinueToCompletion();
completion_observer.BlockUntilCompletion();
EXPECT_FALSE(remover->IsRemovingForTesting());
EXPECT_TRUE(completion_observer.called());
}
TEST_F(BrowsingDataRemoverImplTest, EarlyShutdown) {
BrowsingDataRemoverImpl* remover = static_cast<BrowsingDataRemoverImpl*>(
GetBrowserContext()->GetBrowsingDataRemover());
InspectableCompletionObserver completion_observer(remover);
BrowsingDataRemoverCompletionInhibitor completion_inhibitor(remover);
remover->RemoveAndReply(
base::Time(), base::Time::Max(), BrowsingDataRemover::DATA_TYPE_COOKIES,
BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB, &completion_observer);
completion_inhibitor.BlockUntilNearCompletion();
completion_inhibitor.Reset();
// Verify that the deletion has not yet been completed and the observer has
// not been called.
EXPECT_TRUE(remover->IsRemovingForTesting());
EXPECT_FALSE(completion_observer.called());
// Destroying the profile should trigger the notification.
DestroyBrowserContext();
EXPECT_TRUE(completion_observer.called());
// Finishing after shutdown shouldn't break anything.
completion_inhibitor.ContinueToCompletion();
completion_observer.BlockUntilCompletion();
}
TEST_F(BrowsingDataRemoverImplTest, RemoveDownloadsByTimeOnly) {
RemoveDownloadsTester tester(GetBrowserContext());
base::RepeatingCallback<bool(const GURL&)> filter =
BrowsingDataFilterBuilder::BuildNoopFilter();
EXPECT_CALL(
*tester.download_manager(),
RemoveDownloadsByURLAndTime(ProbablySameFilter(std::move(filter)), _, _));
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_DOWNLOADS,
false);
}
TEST_F(BrowsingDataRemoverImplTest, RemoveDownloadsByOrigin) {
RemoveDownloadsTester tester(GetBrowserContext());
std::unique_ptr<BrowsingDataFilterBuilder> builder(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kDelete));
builder->AddRegisterableDomain("host1.com");
base::RepeatingCallback<bool(const GURL&)> filter = builder->BuildUrlFilter();
EXPECT_CALL(
*tester.download_manager(),
RemoveDownloadsByURLAndTime(ProbablySameFilter(std::move(filter)), _, _));
BlockUntilOriginDataRemoved(base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_DOWNLOADS,
std::move(builder));
}
TEST_F(BrowsingDataRemoverImplTest, RemoveCodeCache) {
RemoveDownloadsTester tester(GetBrowserContext());
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_CACHE, false);
auto removal_data = GetStoragePartitionRemovalDataListAndReset();
EXPECT_EQ(removal_data.size(), 2u);
EXPECT_TRUE(removal_data[1].remove_code_cache);
}
TEST_F(BrowsingDataRemoverImplTest, RemoveCache) {
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_CACHE, false);
auto removal_data = GetStoragePartitionRemovalDataListAndReset();
EXPECT_EQ(removal_data.size(), 2u);
EXPECT_EQ(
removal_data[0].remove_mask,
StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE |
StoragePartition::REMOVE_DATA_MASK_INTEREST_GROUP_PERMISSIONS_CACHE |
StoragePartition::REMOVE_KEEPALIVE_LOADS_ATTEMPTING_RETRY);
}
TEST_F(BrowsingDataRemoverImplTest, RemoveAttributionReporting) {
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_ATTRIBUTION_REPORTING_SITE_CREATED, false);
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(
removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_ATTRIBUTION_REPORTING_SITE_CREATED);
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_ATTRIBUTION_REPORTING_INTERNAL, false);
removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_ATTRIBUTION_REPORTING_INTERNAL);
}
TEST_F(BrowsingDataRemoverImplTest, RemoveAggregationServiceData) {
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_AGGREGATION_SERVICE, false);
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_AGGREGATION_SERVICE);
}
TEST_F(BrowsingDataRemoverImplTest, RemovePrivateAggregationData) {
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_PRIVATE_AGGREGATION_INTERNAL, false);
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_PRIVATE_AGGREGATION_INTERNAL);
}
TEST_F(BrowsingDataRemoverImplTest, RemoveDeviceBoundSessions) {
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_DEVICE_BOUND_SESSIONS, false);
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_DEVICE_BOUND_SESSIONS);
}
class MultipleTasksObserver {
public:
// A simple implementation of BrowsingDataRemover::Observer.
// MultipleTasksObserver will use several instances of Target to test
// that completion callbacks are returned to the correct one.
class Target : public BrowsingDataRemover::Observer {
public:
Target(MultipleTasksObserver* parent, BrowsingDataRemover* remover)
: parent_(parent) {
observation_.Observe(remover);
}
~Target() override = default;
void OnBrowsingDataRemoverDone(uint64_t failed_data_types) override {
parent_->last_called_targets_.push_back(this);
}
private:
raw_ptr<MultipleTasksObserver> parent_;
base::ScopedObservation<BrowsingDataRemover, BrowsingDataRemover::Observer>
observation_{this};
};
explicit MultipleTasksObserver(BrowsingDataRemover* remover)
: target_a_(this, remover), target_b_(this, remover) {}
~MultipleTasksObserver() = default;
void ClearLastCalledTarget() { last_called_targets_.clear(); }
const std::vector<raw_ptr<BrowsingDataRemover::Observer, VectorExperimental>>
GetLastCalledTargets() {
return last_called_targets_;
}
Target* target_a() { return &target_a_; }
Target* target_b() { return &target_b_; }
private:
Target target_a_;
Target target_b_;
std::vector<raw_ptr<BrowsingDataRemover::Observer, VectorExperimental>>
last_called_targets_;
};
TEST_F(BrowsingDataRemoverImplTest, MultipleTasks) {
BrowsingDataRemoverImpl* remover = static_cast<BrowsingDataRemoverImpl*>(
GetBrowserContext()->GetBrowsingDataRemover());
EXPECT_FALSE(remover->IsRemovingForTesting());
std::unique_ptr<BrowsingDataFilterBuilder> filter_builder_1(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kDelete));
filter_builder_1->AddRegisterableDomain("example.com");
MultipleTasksObserver observer(remover);
BrowsingDataRemoverCompletionInhibitor completion_inhibitor(remover);
// Test several tasks with various configuration of masks, filters, and target
// observers.
std::list<BrowsingDataRemoverImpl::RemovalTask> tasks;
tasks.emplace_back(base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_DOWNLOADS,
BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kPreserve),
observer.target_a());
tasks.emplace_back(base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_COOKIES,
BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB,
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kPreserve),
nullptr);
tasks.emplace_back(base::Time::Now(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_DOWNLOADS,
BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB |
BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB,
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kPreserve),
observer.target_b());
for (BrowsingDataRemoverImpl::RemovalTask& task : tasks) {
// All tasks can be directly translated to a RemoveInternal() call. Since
// that is a private method, we must call the four public versions of
// Remove.* instead. This also serves as a test that those methods are all
// correctly reduced to RemoveInternal().
if (task.observers.empty() &&
task.filter_builder->MatchesAllOriginsAndDomains()) {
remover->Remove(task.delete_begin, task.delete_end, task.remove_mask,
task.origin_type_mask);
} else if (task.filter_builder->MatchesAllOriginsAndDomains()) {
remover->RemoveAndReply(task.delete_begin, task.delete_end,
task.remove_mask, task.origin_type_mask,
task.observers[0]);
} else {
remover->RemoveWithFilterAndReply(task.delete_begin, task.delete_end,
task.remove_mask, task.origin_type_mask,
std::move(task.filter_builder),
task.observers[0]);
}
}
// Use the inhibitor to stop after every task and check the results.
for (BrowsingDataRemoverImpl::RemovalTask& task : tasks) {
EXPECT_TRUE(remover->IsRemovingForTesting());
observer.ClearLastCalledTarget();
// Finish the task execution synchronously.
completion_inhibitor.BlockUntilNearCompletion();
completion_inhibitor.ContinueToCompletion();
// Observers, if any, should have been called by now (since we call
// observers on the same thread).
EXPECT_EQ(task.observers, observer.GetLastCalledTargets());
// TODO(msramek): If BrowsingDataRemover took ownership of the last used
// filter builder and exposed it, we could also test it here. Make it so.
EXPECT_EQ(task.remove_mask, GetRemovalMask());
EXPECT_EQ(task.origin_type_mask, GetOriginTypeMask());
EXPECT_EQ(task.delete_begin, GetBeginTime());
}
EXPECT_FALSE(remover->IsRemovingForTesting());
// Run clean up tasks.
RunAllTasksUntilIdle();
}
// Scheduling multiple identical deletions should immediately execute the first
// deletion and merge all following deletions.
TEST_F(BrowsingDataRemoverImplTest, MultipleIdenticalTasks) {
BrowsingDataRemoverImpl* remover = static_cast<BrowsingDataRemoverImpl*>(
GetBrowserContext()->GetBrowsingDataRemover());
EXPECT_FALSE(remover->IsRemovingForTesting());
std::unique_ptr<BrowsingDataFilterBuilder> filter_builder(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kDelete));
filter_builder->AddRegisterableDomain("example.com");
MultipleTasksObserver observer(remover);
BrowsingDataRemoverCompletionInhibitor completion_inhibitor(remover);
std::list<BrowsingDataRemoverImpl::RemovalTask> tasks;
for (int i = 0; i < 10; i++) {
remover->RemoveWithFilterAndReply(
base::Time(), base::Time::Max(), BrowsingDataRemover::DATA_TYPE_COOKIES,
BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB,
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kPreserve),
observer.target_a());
}
EXPECT_TRUE(remover->IsRemovingForTesting());
observer.ClearLastCalledTarget();
// Finish the task execution synchronously.
completion_inhibitor.BlockUntilNearCompletion();
completion_inhibitor.ContinueToCompletion();
// Expect the first observer to be called.
EXPECT_EQ(1u, observer.GetLastCalledTargets().size());
EXPECT_TRUE(remover->IsRemovingForTesting());
observer.ClearLastCalledTarget();
// Finish the task execution synchronously.
completion_inhibitor.BlockUntilNearCompletion();
completion_inhibitor.ContinueToCompletion();
// Expect the remaining observer to be called by a batched deletion.
EXPECT_EQ(9u, observer.GetLastCalledTargets().size());
EXPECT_FALSE(remover->IsRemovingForTesting());
// Run clean up tasks.
RunAllTasksUntilIdle();
}
// BrowsingDataRemoverTest.MultipleTasks, tests that the tasks are not mixed up
// and they are executed in a correct order. However, the completion inhibitor
// kept synchronizing the execution in order to verify the parameters.
// This test demonstrates that even running the tasks without inhibition is
// executed correctly and doesn't crash.
TEST_F(BrowsingDataRemoverImplTest, MultipleTasksInQuickSuccession) {
BrowsingDataRemoverImpl* remover = static_cast<BrowsingDataRemoverImpl*>(
GetBrowserContext()->GetBrowsingDataRemover());
EXPECT_FALSE(remover->IsRemovingForTesting());
uint64_t test_removal_masks[] = {
BrowsingDataRemover::DATA_TYPE_COOKIES,
BrowsingDataRemover::DATA_TYPE_LOCAL_STORAGE,
BrowsingDataRemover::DATA_TYPE_COOKIES,
BrowsingDataRemover::DATA_TYPE_COOKIES,
BrowsingDataRemover::DATA_TYPE_COOKIES,
BrowsingDataRemover::DATA_TYPE_DOWNLOADS,
BrowsingDataRemover::DATA_TYPE_DOWNLOADS,
BrowsingDataRemover::DATA_TYPE_DOWNLOADS,
BrowsingDataRemover::DATA_TYPE_COOKIES |
BrowsingDataRemover::DATA_TYPE_DOWNLOADS,
BrowsingDataRemover::DATA_TYPE_COOKIES |
BrowsingDataRemover::DATA_TYPE_DOWNLOADS,
BrowsingDataRemover::DATA_TYPE_COOKIES |
BrowsingDataRemover::DATA_TYPE_DOWNLOADS |
BrowsingDataRemover::DATA_TYPE_LOCAL_STORAGE,
BrowsingDataRemover::DATA_TYPE_LOCAL_STORAGE,
BrowsingDataRemover::DATA_TYPE_LOCAL_STORAGE,
};
for (uint64_t removal_mask : test_removal_masks) {
remover->Remove(base::Time(), base::Time::Max(), removal_mask,
BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB);
}
EXPECT_TRUE(remover->IsRemovingForTesting());
// Add one more deletion and wait for it.
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(), BrowsingDataRemover::DATA_TYPE_COOKIES,
BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB);
EXPECT_FALSE(remover->IsRemovingForTesting());
}
namespace {
class MockNetworkContext : public network::TestNetworkContext {
public:
MOCK_METHOD2(
ClearTrustTokenData,
void(network::mojom::ClearDataFilterPtr,
network::mojom::NetworkContext::ClearTrustTokenDataCallback));
};
} // namespace
TEST_F(BrowsingDataRemoverImplTest, ClearsTrustTokens) {
MockNetworkContext context;
set_network_context_override(&context);
EXPECT_CALL(context, ClearTrustTokenData(_, _)).WillOnce(RunOnceClosure<1>());
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_TRUST_TOKENS,
/*include_protected_origins=*/false);
set_network_context_override(nullptr);
}
TEST_F(BrowsingDataRemoverImplTest, PreservesTrustTokens) {
StrictMock<MockNetworkContext> context;
set_network_context_override(&context);
// When DATA_TYPE_TRUST_TOKENS isn't cleared, Trust Tokens state shouldn't be.
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_CACHE, // arbitrary non-Trust Tokens type
/*include_protected_origins=*/false);
// (The strict mock will fail the test if its mocked method is called.)
set_network_context_override(nullptr);
}
TEST_F(BrowsingDataRemoverImplTest, ClearsTrustTokensForSite) {
MockNetworkContext context;
set_network_context_override(&context);
auto expected = network::mojom::ClearDataFilter::New();
expected->domains = {"host1.com"};
EXPECT_CALL(
context,
ClearTrustTokenData(
Truly([&expected](const network::mojom::ClearDataFilterPtr& filter) {
return mojo::Equals(filter, expected);
}),
_))
.WillOnce(RunOnceClosure<1>());
std::unique_ptr<BrowsingDataFilterBuilder> builder(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kDelete));
builder->AddRegisterableDomain("host1.com");
BlockUntilOriginDataRemoved(base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_TRUST_TOKENS,
std::move(builder));
set_network_context_override(nullptr);
}
TEST_F(BrowsingDataRemoverImplTest, ClearsTrustTokensForSiteDespiteTimeRange) {
MockNetworkContext context;
set_network_context_override(&context);
auto expected = network::mojom::ClearDataFilter::New();
expected->domains = {"host1.com"};
EXPECT_CALL(
context,
ClearTrustTokenData(
Truly([&expected](const network::mojom::ClearDataFilterPtr& filter) {
return mojo::Equals(filter, expected);
}),
_))
.WillOnce(RunOnceClosure<1>());
std::unique_ptr<BrowsingDataFilterBuilder> builder(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kDelete));
builder->AddRegisterableDomain("host1.com");
// Since Trust Tokens data is not associated with particular timestamps, we
// should observe the same clearing behavior with a non-default time range as
// with the default time range.
BlockUntilOriginDataRemoved(base::Time(), base::Time() + base::Seconds(1),
BrowsingDataRemover::DATA_TYPE_TRUST_TOKENS,
std::move(builder));
set_network_context_override(nullptr);
}
TEST_F(BrowsingDataRemoverImplTest, DeferCookieDeletion) {
TestBrowsingDataRemoverDelegate delegate;
GetBrowserContext()->GetBrowsingDataRemover()->SetEmbedderDelegate(&delegate);
uint32_t dom_storage_mask =
StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE |
StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS |
StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS |
StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE |
StoragePartition::REMOVE_DATA_MASK_BACKGROUND_FETCH |
StoragePartition::REMOVE_DATA_MASK_INDEXEDDB;
uint32_t dom_storage_and_cookie_mask =
dom_storage_mask | StoragePartition::REMOVE_DATA_MASK_INTEREST_GROUPS |
StoragePartition::REMOVE_DATA_MASK_COOKIES |
StoragePartition::REMOVE_KEEPALIVE_LOADS_ATTEMPTING_RETRY;
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_COOKIES |
BrowsingDataRemover::DATA_TYPE_DOM_STORAGE,
false);
// Verify storage partition deletion happens once without deferred domains.
auto removal_list = GetStoragePartitionRemovalDataListAndReset();
EXPECT_EQ(removal_list.size(), 1u);
EXPECT_EQ(removal_list[0].remove_mask, dom_storage_and_cookie_mask);
EXPECT_FALSE(removal_list[0].cookie_deletion_filter->excluding_domains);
EXPECT_FALSE(removal_list[0].cookie_deletion_filter->including_domains);
// Verify two separate deletions happen with deferred domains.
std::vector<std::string> deferred_domains = {"example.com"};
delegate.set_deferred_domains(deferred_domains);
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_COOKIES |
BrowsingDataRemover::DATA_TYPE_DOM_STORAGE,
false);
removal_list = GetStoragePartitionRemovalDataListAndReset();
EXPECT_EQ(removal_list.size(), 2u);
EXPECT_EQ(removal_list[0].remove_mask, dom_storage_and_cookie_mask);
EXPECT_EQ(removal_list[1].remove_mask,
StoragePartition::REMOVE_DATA_MASK_COOKIES);
EXPECT_EQ(removal_list[0].cookie_deletion_filter->excluding_domains,
deferred_domains);
EXPECT_FALSE(removal_list[0].cookie_deletion_filter->including_domains);
EXPECT_FALSE(removal_list[1].cookie_deletion_filter->excluding_domains);
EXPECT_EQ(removal_list[1].cookie_deletion_filter->including_domains,
deferred_domains);
// Reset delegate.
GetBrowserContext()->GetBrowsingDataRemover()->SetEmbedderDelegate(nullptr);
}
// Tests that the failed_data_types mask is correctly plumbed from the embedder
// delegate to the observer's OnBrowsingDataRemoverDone() method.
TEST_F(BrowsingDataRemoverImplTest, FailedDataTypes) {
const uint64_t kSomeEmbedderType = BrowsingDataRemover::DATA_TYPE_CONTENT_END
<< 1;
BrowsingDataRemover* remover = GetBrowserContext()->GetBrowsingDataRemover();
TestBrowsingDataRemoverDelegate delegate;
remover->SetEmbedderDelegate(&delegate);
{
delegate.set_failed_data_types(kSomeEmbedderType);
BrowsingDataRemoverCompletionObserver completion_observer(remover);
remover->RemoveAndReply(
base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_COOKIES | kSomeEmbedderType,
BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB, &completion_observer);
completion_observer.BlockUntilCompletion();
EXPECT_EQ(completion_observer.failed_data_types(), kSomeEmbedderType);
}
{
delegate.set_failed_data_types(0);
BrowsingDataRemoverCompletionObserver completion_observer(remover);
remover->RemoveAndReply(
base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_COOKIES | kSomeEmbedderType,
BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB, &completion_observer);
completion_observer.BlockUntilCompletion();
EXPECT_EQ(completion_observer.failed_data_types(), 0u);
}
// Reset delegate.
remover->SetEmbedderDelegate(nullptr);
}
TEST_F(BrowsingDataRemoverImplTest, RemoveStorageBucketsAndReply) {
class TestObserver : public BrowsingDataRemover::Observer {
void OnBrowsingDataRemoverDone(uint64_t failed_data_types) override {
EXPECT_EQ(failed_data_types, 0U);
}
public:
void RemoveBuckets() {
auto storage_key =
blink::StorageKey::CreateFromStringForTesting("https://example.com");
std::set<std::string> buckets{"drafts"};
StoragePartitionRemovalTestStoragePartition storage_partition;
TestBrowserContext browser_context;
BrowsingDataRemoverImpl remover =
BrowsingDataRemoverImpl(&browser_context);
remover.OverrideStoragePartitionForTesting(
StoragePartitionConfig::CreateDefault(&browser_context),
&storage_partition);
remover.RemoveStorageBucketsAndReply(
std::nullopt, storage_key, buckets,
base::BindOnce(&TestObserver::OnBrowsingDataRemoverDone,
base::Unretained(this), 0));
}
public:
~TestObserver() override = default;
};
TestObserver observer;
observer.RemoveBuckets();
}
TEST_F(BrowsingDataRemoverImplTest, NonDefaultStoragePartitionInFilter) {
// Create a second StoragePartition.
auto non_default_storage_partition_config = StoragePartitionConfig::Create(
GetBrowserContext(), "domain", "name", /*in_memory=*/false);
auto non_default_storage_partition =
std::make_unique<StoragePartitionRemovalTestStoragePartition>();
RegisterStoragePartition(non_default_storage_partition_config,
non_default_storage_partition.get());
std::unique_ptr<BrowsingDataFilterBuilder> builder(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kDelete));
const GURL kTestUrl("http://host1.com");
builder->AddRegisterableDomain(kTestUrl.host());
builder->SetStoragePartitionConfig(non_default_storage_partition_config);
// Remove the test origin.
BlockUntilOriginDataRemoved(base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
std::move(builder));
EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS |
BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE |
BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS |
BrowsingDataRemover::DATA_TYPE_INDEXED_DB,
GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Check that data wasn't removed from the default StoragePartition.
std::vector<StoragePartitionRemovalData> all_default_removal_data =
GetStoragePartitionRemovalDataListAndReset();
EXPECT_TRUE(all_default_removal_data.empty());
// Check that the data removal was performed on the correct StoragePartition.
std::vector<StoragePartitionRemovalData> all_removal_data =
non_default_storage_partition->GetStoragePartitionRemovalData();
EXPECT_EQ(1UL, all_removal_data.size());
StoragePartitionRemovalData removal_data = all_removal_data.back();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS |
StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS |
StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE |
StoragePartition::REMOVE_DATA_MASK_INDEXEDDB);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
ASSERT_TRUE(removal_data.filter_builder);
EXPECT_EQ(non_default_storage_partition_config,
removal_data.filter_builder->GetStoragePartitionConfig());
RegisterStoragePartition(non_default_storage_partition_config, nullptr);
}
TEST_F(BrowsingDataRemoverImplTest, DeleteInterestGroupsWhenClearingCookies) {
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_COOKIES,
/*include_protected_origins=*/false);
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(
removal_data.remove_mask &
(StoragePartition::REMOVE_DATA_MASK_INTEREST_GROUPS |
StoragePartition::REMOVE_DATA_MASK_INTEREST_GROUPS_INTERNAL |
StoragePartition::REMOVE_DATA_MASK_INTEREST_GROUP_PERMISSIONS_CACHE),
StoragePartition::REMOVE_DATA_MASK_INTEREST_GROUPS);
}
TEST_F(BrowsingDataRemoverImplTest,
IfPartitionedCookiesOnlyDontDeleteInterestGroupsWhenClearingCookies) {
std::unique_ptr<BrowsingDataFilterBuilder> builder(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kPreserve));
builder->SetPartitionedCookiesOnly(true);
BlockUntilOriginDataRemoved(base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_COOKIES,
std::move(builder));
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(
removal_data.remove_mask &
(StoragePartition::REMOVE_DATA_MASK_INTEREST_GROUPS |
StoragePartition::REMOVE_DATA_MASK_INTEREST_GROUPS_INTERNAL |
StoragePartition::REMOVE_DATA_MASK_INTEREST_GROUP_PERMISSIONS_CACHE),
0u);
}
class BrowsingDataRemoverImplSharedStorageTest
: public BrowsingDataRemoverImplTest {
public:
BrowsingDataRemoverImplSharedStorageTest() {
feature_list_.InitAndEnableFeature(network::features::kSharedStorageAPI);
}
private:
base::test::ScopedFeatureList feature_list_;
};
TEST_F(BrowsingDataRemoverImplSharedStorageTest,
RemoveUnprotectedSharedStorageForever) {
storage::MockSpecialStoragePolicy* policy = CreateMockPolicy();
// Protect the test origin.
const url::Origin kTestOrigin = url::Origin::Create(GURL("http://host1.com"));
policy->AddProtected(kTestOrigin.GetURL());
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_SHARED_STORAGE,
false);
EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_SHARED_STORAGE, GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Verify that storage partition was instructed to remove the data correctly.
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_SHARED_STORAGE);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
EXPECT_EQ(removal_data.remove_begin, GetBeginTime());
ASSERT_TRUE(removal_data.filter_builder);
EXPECT_TRUE(removal_data.filter_builder->MatchesAllOriginsAndDomains());
// Check storage key policy matcher.
EXPECT_FALSE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFirstParty(kTestOrigin), mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host2.com"),
mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host3.com"),
mock_policy()));
EXPECT_FALSE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting(
"chrome-extension://abcdefghijklmnopqrstuvwxyz/"),
mock_policy()));
}
TEST_F(BrowsingDataRemoverImplSharedStorageTest,
RemoveProtectedSharedStorageForever) {
// Protect the test origin.
storage::MockSpecialStoragePolicy* policy = CreateMockPolicy();
const url::Origin kTestOrigin = url::Origin::Create(GURL("http://host1.com"));
policy->AddProtected(kTestOrigin.GetURL());
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_SHARED_STORAGE,
true);
EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_SHARED_STORAGE, GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB |
BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB,
GetOriginTypeMask());
// Verify that storage partition was instructed to remove the data correctly.
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_SHARED_STORAGE);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
EXPECT_EQ(removal_data.remove_begin, GetBeginTime());
ASSERT_TRUE(removal_data.filter_builder);
EXPECT_TRUE(removal_data.filter_builder->MatchesAllOriginsAndDomains());
// Check storage key policy matcher all http origin will match since we
// specified both protected and unprotected.
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFirstParty(kTestOrigin), mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host2.com"),
mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host3.com"),
mock_policy()));
EXPECT_FALSE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting(
"chrome-extension://abcdefghijklmnopqrstuvwxyz/"),
mock_policy()));
}
TEST_F(BrowsingDataRemoverImplSharedStorageTest,
RemoveSharedStorageForLastWeek) {
CreateMockPolicy();
BlockUntilBrowsingDataRemoved(
base::Time::Now() - base::Days(7), base::Time::Max(),
BrowsingDataRemover::DATA_TYPE_SHARED_STORAGE, false);
EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_SHARED_STORAGE, GetRemovalMask());
EXPECT_EQ(BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Verify that storage partition was instructed to remove the data correctly.
StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData();
EXPECT_EQ(removal_data.remove_mask,
StoragePartition::REMOVE_DATA_MASK_SHARED_STORAGE);
EXPECT_EQ(removal_data.quota_storage_remove_mask,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
EXPECT_EQ(removal_data.remove_begin, GetBeginTime());
ASSERT_TRUE(removal_data.filter_builder);
EXPECT_TRUE(removal_data.filter_builder->MatchesAllOriginsAndDomains());
// Check storage key policy matcher.
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host1.com"),
mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host2.com"),
mock_policy()));
EXPECT_TRUE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting("http://host3.com"),
mock_policy()));
EXPECT_FALSE(removal_data.storage_key_policy_matcher.Run(
blink::StorageKey::CreateFromStringForTesting(
"chrome-extension://abcdefghijklmnopqrstuvwxyz/"),
mock_policy()));
}
class RemoveBtmEventsTester {
public:
explicit RemoveBtmEventsTester(BrowserContext* browser_context) {
storage_ = BtmServiceImpl::Get(browser_context)->storage();
}
void WriteEventTimes(GURL url,
std::optional<base::Time> storage_time,
std::optional<base::Time> interaction_time) {
if (storage_time.has_value()) {
storage_->AsyncCall(&BtmStorage::RecordStorage)
.WithArgs(url, storage_time.value());
}
if (interaction_time.has_value()) {
storage_->AsyncCall(&BtmStorage::RecordUserActivation)
.WithArgs(url, interaction_time.value());
}
storage_->FlushPostedTasksForTesting();
}
std::optional<StateValue> ReadStateValue(GURL url) {
base::test::TestFuture<BtmState> btm_state;
storage_->AsyncCall(&BtmStorage::Read)
.WithArgs(url)
.Then(btm_state.GetCallback());
const BtmState& state = btm_state.Get();
if (!state.was_loaded()) {
return {};
}
return state.ToStateValue();
}
private:
raw_ptr<base::SequenceBound<BtmStorage>> storage_;
};
class BrowsingDataRemoverImplBtmTest : public BrowsingDataRemoverImplTest {
public:
BrowsingDataRemoverImplBtmTest()
: BrowsingDataRemoverImplTest(
std::make_unique<TpcBlockingBrowserClient>()) {}
};
TEST_F(BrowsingDataRemoverImplBtmTest, RemoveBtmEventsForLastHour) {
RemoveBtmEventsTester tester(GetBrowserContext());
GURL url1("https://example1.com");
GURL url2("https://example2.com");
base::Time two_hours_ago = base::Time::Now() - base::Hours(2);
tester.WriteEventTimes(url1, /*storage_time=*/base::Time::Now(),
/*interaction_time=*/std::nullopt);
tester.WriteEventTimes(url2, /*storage_time=*/std::nullopt,
/*interaction_time=*/two_hours_ago);
{
std::optional<StateValue> state_val1 = tester.ReadStateValue(url1);
std::optional<StateValue> state_val2 = tester.ReadStateValue(url2);
ASSERT_TRUE(state_val1.has_value());
EXPECT_TRUE(state_val1->site_storage_times.has_value());
ASSERT_TRUE(state_val2.has_value());
EXPECT_TRUE(state_val2->user_activation_times.has_value());
}
uint64_t remove_mask = TpcBlockingBrowserClient::DATA_TYPE_HISTORY |
content::BrowsingDataRemover::DATA_TYPE_COOKIES;
BlockUntilBrowsingDataRemoved(AnHourAgo(), base::Time::Max(), remove_mask,
false);
{
std::optional<StateValue> state_val1 = tester.ReadStateValue(url1);
std::optional<StateValue> state_val2 = tester.ReadStateValue(url2);
EXPECT_FALSE(state_val1.has_value());
ASSERT_TRUE(state_val2.has_value());
EXPECT_TRUE(state_val2->user_activation_times.has_value());
}
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(), remove_mask,
false);
{
std::optional<StateValue> state_val1 = tester.ReadStateValue(url1);
std::optional<StateValue> state_val2 = tester.ReadStateValue(url2);
EXPECT_FALSE(state_val1.has_value());
EXPECT_FALSE(state_val2.has_value());
}
}
TEST_F(BrowsingDataRemoverImplBtmTest, RemoveBtmEventsByType) {
RemoveBtmEventsTester tester(GetBrowserContext());
GURL url1("https://example1.com");
GURL url2("https://example2.com");
GURL url3("https://example3.com");
base::Time two_hours_ago = base::Time::Now() - base::Hours(2);
tester.WriteEventTimes(url1, /*storage_time=*/base::Time::Now(),
/*interaction_time=*/std::nullopt);
tester.WriteEventTimes(url2, /*storage_time=*/std::nullopt,
/*interaction_time=*/base::Time::Now());
tester.WriteEventTimes(url3, /*storage_time=*/base::Time::Now(),
/*interaction_time=*/two_hours_ago);
{
std::optional<StateValue> state_val1 = tester.ReadStateValue(url1);
std::optional<StateValue> state_val2 = tester.ReadStateValue(url2);
std::optional<StateValue> state_val3 = tester.ReadStateValue(url3);
ASSERT_TRUE(state_val1.has_value());
EXPECT_TRUE(state_val1->site_storage_times.has_value());
ASSERT_TRUE(state_val2.has_value());
EXPECT_TRUE(state_val2->user_activation_times.has_value());
ASSERT_TRUE(state_val3.has_value());
EXPECT_TRUE(state_val3->site_storage_times.has_value());
EXPECT_TRUE(state_val3->user_activation_times.has_value());
}
// Remove interaction events from DIPS Storage.
BlockUntilBrowsingDataRemoved(AnHourAgo(), base::Time::Max(),
TpcBlockingBrowserClient::DATA_TYPE_HISTORY,
false);
// Verify the interaction event for url2 has been removed.
{
std::optional<StateValue> state_val1 = tester.ReadStateValue(url1);
std::optional<StateValue> state_val2 = tester.ReadStateValue(url2);
std::optional<StateValue> state_val3 = tester.ReadStateValue(url3);
ASSERT_TRUE(state_val1.has_value());
EXPECT_TRUE(state_val1->site_storage_times.has_value());
EXPECT_FALSE(state_val2.has_value());
ASSERT_TRUE(state_val3.has_value());
EXPECT_TRUE(state_val3->site_storage_times.has_value());
EXPECT_TRUE(state_val3->user_activation_times.has_value());
}
// Remove storage events from DIPS Storage.
BlockUntilBrowsingDataRemoved(AnHourAgo(), base::Time::Max(),
content::BrowsingDataRemover::DATA_TYPE_COOKIES,
false);
// Verify the storage events for url1 and url3 have been removed.
{
std::optional<StateValue> state_val1 = tester.ReadStateValue(url1);
std::optional<StateValue> state_val2 = tester.ReadStateValue(url2);
std::optional<StateValue> state_val3 = tester.ReadStateValue(url3);
EXPECT_FALSE(state_val1.has_value());
EXPECT_FALSE(state_val2.has_value());
ASSERT_TRUE(state_val3.has_value());
EXPECT_FALSE(state_val3->site_storage_times.has_value());
EXPECT_TRUE(state_val3->user_activation_times.has_value());
}
}
TEST_F(BrowsingDataRemoverImplTest,
RemoveBrowsingHistoryRegeneratesNoiseToken) {
base::test::ScopedFeatureList features(
fingerprinting_protection_interventions::features::kCanvasNoise);
url::Origin origin = url::Origin::Create(GURL("https://example.test"));
uint64_t original_token =
content::CanvasNoiseTokenData::GetToken(GetBrowserContext(), origin);
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
content::BrowsingDataRemover::DATA_TYPE_COOKIES,
false);
EXPECT_EQ(content::BrowsingDataRemover::DATA_TYPE_COOKIES, GetRemovalMask());
EXPECT_EQ(content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
uint64_t updated_token =
content::CanvasNoiseTokenData::GetToken(GetBrowserContext(), origin);
EXPECT_NE(original_token, updated_token);
}
} // namespace content