| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/browsing_data/browsing_data_remover_impl.h" |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include <list> |
| #include <memory> |
| #include <set> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/bind.h" |
| #include "base/callback_helpers.h" |
| #include "base/files/file_path.h" |
| #include "base/files/file_util.h" |
| #include "base/location.h" |
| #include "base/macros.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/run_loop.h" |
| #include "base/scoped_observation.h" |
| #include "base/single_thread_task_runner.h" |
| #include "base/strings/strcat.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/task/cancelable_task_tracker.h" |
| #include "base/test/gmock_callback_support.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "base/time/time.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_usage_info.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_deletion_info.h" |
| #include "net/cookies/cookie_store.h" |
| #include "net/http/http_network_session.h" |
| #include "net/http/http_transaction_factory.h" |
| #include "net/ssl/ssl_client_cert_type.h" |
| #include "ppapi/buildflags/buildflags.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 "url/origin.h" |
| |
| #if BUILDFLAG(ENABLE_REPORTING) |
| #include "net/network_error_logging/mock_persistent_nel_store.h" |
| #include "net/network_error_logging/network_error_logging_service.h" |
| #include "net/reporting/mock_persistent_reporting_store.h" |
| #include "net/reporting/reporting_cache.h" |
| #include "net/reporting/reporting_endpoint.h" |
| #include "net/reporting/reporting_report.h" |
| #include "net/reporting/reporting_service.h" |
| #include "net/reporting/reporting_test_util.h" |
| #endif // BUILDFLAG(ENABLE_REPORTING) |
| |
| 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), |
| origin_matcher(other.origin_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; |
| origin_matcher = rhs.origin_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; |
| StoragePartition::OriginMatcherFunction origin_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(), false, false, net::CookieSameSite::NO_RESTRICTION, |
| net::COOKIE_PRIORITY_MEDIUM, false); |
| EXPECT_TRUE(cookie); |
| return *cookie; |
| } |
| |
| class StoragePartitionRemovalTestStoragePartition |
| : public TestStoragePartition { |
| public: |
| StoragePartitionRemovalTestStoragePartition() { |
| set_network_context(&network_context_); |
| } |
| ~StoragePartitionRemovalTestStoragePartition() override = default; |
| |
| void ClearDataForOrigin(uint32_t remove_mask, |
| uint32_t quota_storage_remove_mask, |
| const GURL& storage_origin) override {} |
| |
| void ClearData(uint32_t remove_mask, |
| uint32_t quota_storage_remove_mask, |
| const GURL& storage_origin, |
| 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, |
| OriginMatcherFunction origin_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.origin_matcher = std::move(origin_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_); |
| } |
| |
| private: |
| std::vector<StoragePartitionRemovalData> storage_partition_removal_data_; |
| network::TestNetworkContext network_context_; |
| |
| DISALLOW_COPY_AND_ASSIGN(StoragePartitionRemovalTestStoragePartition); |
| }; |
| |
| // 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( |
| const base::RepeatingCallback<bool(const GURL&)>& filter) |
| : to_match_(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(const base::RepeatingCallback<bool(const GURL&)>& filter) { |
| return MakeMatcher(new ProbablySameFilterMatcher(filter)); |
| } |
| |
| base::Time AnHourAgo() { |
| return base::Time::Now() - base::TimeDelta::FromHours(1); |
| } |
| |
| bool FilterMatchesCookie(const CookieDeletionFilterPtr& filter, |
| const net::CanonicalCookie& cookie) { |
| return network::DeletionFilterToInfo(filter.Clone()) |
| .Matches(cookie, net::CookieAccessParams{ |
| net::CookieAccessSemantics::NONLEGACY, false}); |
| } |
| |
| class TestBrowsingDataRemoverDelegate |
| : public content::BrowsingDataRemoverDelegate { |
| public: |
| // BrowsingDataRemoverDelegate: |
| std::vector<std::string> GetDomainsForDeferredCookieDeletion( |
| 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()) { |
| BrowserContext::SetDownloadManagerForTesting( |
| browser_context, base::WrapUnique(download_manager_)); |
| EXPECT_EQ(download_manager_, |
| BrowserContext::GetDownloadManager(browser_context)); |
| EXPECT_CALL(*download_manager_, Shutdown()); |
| } |
| |
| ~RemoveDownloadsTester() = default; |
| |
| MockDownloadManager* download_manager() { return download_manager_; } |
| |
| private: |
| MockDownloadManager* download_manager_; // Owned by browser context. |
| |
| DISALLOW_COPY_AND_ASSIGN(RemoveDownloadsTester); |
| }; |
| |
| // Test Class ---------------------------------------------------------------- |
| |
| class BrowsingDataRemoverImplTest : public testing::Test { |
| public: |
| BrowsingDataRemoverImplTest() : browser_context_(new TestBrowserContext()) { |
| remover_ = static_cast<BrowsingDataRemoverImpl*>( |
| BrowserContext::GetBrowsingDataRemover(browser_context_.get())); |
| } |
| |
| ~BrowsingDataRemoverImplTest() override = default; |
| |
| void TearDown() override { |
| mock_policy_ = 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 BlockUntilBrowsingDataRemoved(const base::Time& delete_begin, |
| const base::Time& delete_end, |
| uint64_t remove_mask, |
| bool include_protected_origins) { |
| // TODO(msramek): Consider moving |storage_partition| to the test fixture. |
| StoragePartitionRemovalTestStoragePartition storage_partition; |
| |
| if (network_context_override_) { |
| storage_partition.set_network_context(network_context_override_); |
| } |
| |
| remover_->OverrideStoragePartitionForTesting(&storage_partition); |
| |
| 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) { |
| StoragePartitionRemovalTestStoragePartition storage_partition; |
| |
| if (network_context_override_) { |
| storage_partition.set_network_context(network_context_override_); |
| } |
| |
| remover_->OverrideStoragePartitionForTesting(&storage_partition); |
| |
| 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() { 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; |
| } |
| |
| bool Match(const GURL& origin, |
| uint64_t mask, |
| storage::SpecialStoragePolicy* policy) { |
| return remover_->DoesOriginMatchMaskForTesting( |
| mask, url::Origin::Create(origin), policy); |
| } |
| |
| private: |
| // Cached pointer to BrowsingDataRemoverImpl for access to testing methods. |
| BrowsingDataRemoverImpl* remover_; |
| |
| BrowserTaskEnvironment task_environment_; |
| std::unique_ptr<BrowserContext> browser_context_; |
| |
| network::mojom::NetworkContext* network_context_override_ = nullptr; |
| |
| std::vector<StoragePartitionRemovalData> storage_partition_removal_data_; |
| |
| scoped_refptr<storage::MockSpecialStoragePolicy> mock_policy_; |
| |
| DISALLOW_COPY_AND_ASSIGN(BrowsingDataRemoverImplTest); |
| }; |
| |
| // 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); |
| 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); |
| // Removing with time period other than all time should not clear |
| // persistent storage data. |
| EXPECT_EQ(removal_data.quota_storage_remove_mask, |
| ~StoragePartition::QUOTA_MANAGED_STORAGE_MASK_PERSISTENT); |
| 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); |
| // Removing with time period other than all time should not clear |
| // persistent storage data. |
| EXPECT_EQ(removal_data.quota_storage_remove_mask, |
| ~StoragePartition::QUOTA_MANAGED_STORAGE_MASK_PERSISTENT); |
| 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")); |
| EXPECT_FALSE(removal_data.origin_matcher.Run(kTestOrigin1, mock_policy())); |
| EXPECT_TRUE(removal_data.origin_matcher.Run(kTestOrigin2, mock_policy())); |
| EXPECT_FALSE(removal_data.origin_matcher.Run(kTestOrigin3, mock_policy())); |
| // Even though it's a different origin, it's the same domain. |
| EXPECT_FALSE( |
| removal_data.origin_matcher.Run(kTestOrigin3Secure, mock_policy())); |
| |
| 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()); |
| |
| // Check origin matcher. |
| EXPECT_FALSE(removal_data.origin_matcher.Run(kTestOrigin, mock_policy())); |
| EXPECT_TRUE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host2.com")), mock_policy())); |
| EXPECT_TRUE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host3.com")), mock_policy())); |
| EXPECT_FALSE(removal_data.origin_matcher.Run( |
| url::Origin::Create( |
| GURL("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()); |
| |
| // Check origin matcher all http origin will match since we specified |
| // both protected and unprotected. |
| EXPECT_TRUE(removal_data.origin_matcher.Run(kTestOrigin, mock_policy())); |
| EXPECT_TRUE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host2.com")), mock_policy())); |
| EXPECT_TRUE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host3.com")), mock_policy())); |
| EXPECT_FALSE(removal_data.origin_matcher.Run( |
| url::Origin::Create( |
| GURL("chrome-extension://abcdefghijklmnopqrstuvwxyz/")), |
| mock_policy())); |
| } |
| |
| TEST_F(BrowsingDataRemoverImplTest, RemoveLocalStorageForLastWeek) { |
| CreateMockPolicy(); |
| |
| BlockUntilBrowsingDataRemoved( |
| base::Time::Now() - base::TimeDelta::FromDays(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); |
| // Persistent storage won't be deleted. |
| EXPECT_EQ(removal_data.quota_storage_remove_mask, |
| ~StoragePartition::QUOTA_MANAGED_STORAGE_MASK_PERSISTENT); |
| EXPECT_EQ(removal_data.remove_begin, GetBeginTime()); |
| |
| // Check origin matcher. |
| EXPECT_TRUE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host1.com")), mock_policy())); |
| EXPECT_TRUE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host2.com")), mock_policy())); |
| EXPECT_TRUE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host3.com")), mock_policy())); |
| EXPECT_FALSE(removal_data.origin_matcher.Run( |
| url::Origin::Create( |
| GURL("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); |
| 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_WEB_SQL | |
| BrowsingDataRemover::DATA_TYPE_APP_CACHE | |
| 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_WEB_SQL | |
| BrowsingDataRemover::DATA_TYPE_APP_CACHE | |
| 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_WEBSQL | |
| StoragePartition::REMOVE_DATA_MASK_APPCACHE | |
| 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_WEB_SQL | |
| BrowsingDataRemover::DATA_TYPE_APP_CACHE | |
| 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_WEB_SQL | |
| BrowsingDataRemover::DATA_TYPE_APP_CACHE | |
| 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_WEBSQL | |
| StoragePartition::REMOVE_DATA_MASK_APPCACHE | |
| 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 that all related origin data would be removed, that is, origin |
| // matcher would match these origin. |
| EXPECT_TRUE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host1.com")), mock_policy())); |
| EXPECT_TRUE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host2.com")), mock_policy())); |
| EXPECT_TRUE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host3.com")), mock_policy())); |
| } |
| |
| TEST_F(BrowsingDataRemoverImplTest, |
| RemoveQuotaManagedDataForeverOnlyPersistent) { |
| CreateMockPolicy(); |
| |
| BlockUntilBrowsingDataRemoved( |
| base::Time(), base::Time::Max(), |
| BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS | |
| BrowsingDataRemover::DATA_TYPE_WEB_SQL | |
| BrowsingDataRemover::DATA_TYPE_APP_CACHE | |
| 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_WEB_SQL | |
| BrowsingDataRemover::DATA_TYPE_APP_CACHE | |
| 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_WEBSQL | |
| StoragePartition::REMOVE_DATA_MASK_APPCACHE | |
| 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 that all related origin data would be removed, that is, origin |
| // matcher would match these origin. |
| EXPECT_TRUE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host1.com")), mock_policy())); |
| EXPECT_TRUE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host2.com")), mock_policy())); |
| EXPECT_TRUE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host3.com")), mock_policy())); |
| } |
| |
| TEST_F(BrowsingDataRemoverImplTest, RemoveQuotaManagedDataForeverNeither) { |
| CreateMockPolicy(); |
| |
| BlockUntilBrowsingDataRemoved( |
| base::Time(), base::Time::Max(), |
| BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS | |
| BrowsingDataRemover::DATA_TYPE_WEB_SQL | |
| BrowsingDataRemover::DATA_TYPE_APP_CACHE | |
| 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_WEB_SQL | |
| BrowsingDataRemover::DATA_TYPE_APP_CACHE | |
| 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_WEBSQL | |
| StoragePartition::REMOVE_DATA_MASK_APPCACHE | |
| 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 that all related origin data would be removed, that is, origin |
| // matcher would match these origin. |
| EXPECT_TRUE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host1.com")), mock_policy())); |
| EXPECT_TRUE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host2.com")), mock_policy())); |
| EXPECT_TRUE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("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_APP_CACHE | |
| BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS | |
| BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE | |
| BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS | |
| BrowsingDataRemover::DATA_TYPE_INDEXED_DB | |
| BrowsingDataRemover::DATA_TYPE_WEB_SQL, |
| std::move(builder)); |
| |
| EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_APP_CACHE | |
| BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS | |
| BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE | |
| BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS | |
| BrowsingDataRemover::DATA_TYPE_INDEXED_DB | |
| BrowsingDataRemover::DATA_TYPE_WEB_SQL, |
| 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_WEBSQL | |
| StoragePartition::REMOVE_DATA_MASK_APPCACHE | |
| 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); |
| EXPECT_TRUE(removal_data.origin_matcher.Run(url::Origin::Create(kTestUrl), |
| mock_policy())); |
| EXPECT_FALSE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host2.com")), mock_policy())); |
| EXPECT_FALSE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host3.com")), mock_policy())); |
| EXPECT_FALSE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("https://host3.com")), mock_policy())); |
| } |
| |
| TEST_F(BrowsingDataRemoverImplTest, RemoveQuotaManagedDataForLastHour) { |
| BlockUntilBrowsingDataRemoved( |
| AnHourAgo(), base::Time::Max(), |
| BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS | |
| BrowsingDataRemover::DATA_TYPE_WEB_SQL | |
| BrowsingDataRemover::DATA_TYPE_APP_CACHE | |
| 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_WEB_SQL | |
| BrowsingDataRemover::DATA_TYPE_APP_CACHE | |
| 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_WEBSQL | |
| StoragePartition::REMOVE_DATA_MASK_APPCACHE | |
| StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS | |
| StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE | |
| StoragePartition::REMOVE_DATA_MASK_INDEXEDDB); |
| |
| // Persistent data would be left out since we are not removing from |
| // beginning of time. |
| uint32_t expected_quota_mask = |
| ~StoragePartition::QUOTA_MANAGED_STORAGE_MASK_PERSISTENT; |
| EXPECT_EQ(removal_data.quota_storage_remove_mask, expected_quota_mask); |
| // Check removal begin time. |
| EXPECT_EQ(removal_data.remove_begin, GetBeginTime()); |
| } |
| |
| TEST_F(BrowsingDataRemoverImplTest, RemoveQuotaManagedDataForLastWeek) { |
| BlockUntilBrowsingDataRemoved( |
| base::Time::Now() - base::TimeDelta::FromDays(7), base::Time::Max(), |
| BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS | |
| BrowsingDataRemover::DATA_TYPE_WEB_SQL | |
| BrowsingDataRemover::DATA_TYPE_APP_CACHE | |
| 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_WEB_SQL | |
| BrowsingDataRemover::DATA_TYPE_APP_CACHE | |
| 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_WEBSQL | |
| StoragePartition::REMOVE_DATA_MASK_APPCACHE | |
| StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS | |
| StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE | |
| StoragePartition::REMOVE_DATA_MASK_INDEXEDDB); |
| |
| // Persistent data would be left out since we are not removing from |
| // beginning of time. |
| uint32_t expected_quota_mask = |
| ~StoragePartition::QUOTA_MANAGED_STORAGE_MASK_PERSISTENT; |
| EXPECT_EQ(removal_data.quota_storage_remove_mask, expected_quota_mask); |
| // 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_WEB_SQL | |
| BrowsingDataRemover::DATA_TYPE_APP_CACHE | |
| 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_WEB_SQL | |
| BrowsingDataRemover::DATA_TYPE_APP_CACHE | |
| 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_WEBSQL | |
| StoragePartition::REMOVE_DATA_MASK_APPCACHE | |
| 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 OriginMatcherFunction. |
| EXPECT_FALSE(removal_data.origin_matcher.Run(kTestOrigin, mock_policy())); |
| EXPECT_TRUE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host2.com")), mock_policy())); |
| EXPECT_TRUE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("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_APP_CACHE | |
| BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS | |
| BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE | |
| BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS | |
| BrowsingDataRemover::DATA_TYPE_INDEXED_DB | |
| BrowsingDataRemover::DATA_TYPE_WEB_SQL, |
| std::move(builder)); |
| |
| EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_APP_CACHE | |
| BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS | |
| BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE | |
| BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS | |
| BrowsingDataRemover::DATA_TYPE_INDEXED_DB | |
| BrowsingDataRemover::DATA_TYPE_WEB_SQL, |
| 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_WEBSQL | |
| StoragePartition::REMOVE_DATA_MASK_APPCACHE | |
| 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 OriginMatcherFunction. |
| EXPECT_FALSE(removal_data.origin_matcher.Run(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(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host2.com")), mock_policy())); |
| EXPECT_FALSE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host3.com")), mock_policy())); |
| } |
| |
| 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_APP_CACHE | |
| BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS | |
| BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE | |
| BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS | |
| BrowsingDataRemover::DATA_TYPE_INDEXED_DB | |
| BrowsingDataRemover::DATA_TYPE_WEB_SQL, |
| true); |
| |
| EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_APP_CACHE | |
| BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS | |
| BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE | |
| BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS | |
| BrowsingDataRemover::DATA_TYPE_INDEXED_DB | |
| BrowsingDataRemover::DATA_TYPE_WEB_SQL, |
| 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_WEBSQL | |
| StoragePartition::REMOVE_DATA_MASK_APPCACHE | |
| 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 OriginMatcherFunction, |kTestOrigin| would match mask since we |
| // would have 'protected' specified in origin_type_mask. |
| EXPECT_TRUE(removal_data.origin_matcher.Run(kTestOrigin, mock_policy())); |
| EXPECT_TRUE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host2.com")), mock_policy())); |
| EXPECT_TRUE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("http://host3.com")), mock_policy())); |
| } |
| |
| TEST_F(BrowsingDataRemoverImplTest, |
| RemoveQuotaManagedIgnoreExtensionsAndDevTools) { |
| CreateMockPolicy(); |
| |
| BlockUntilBrowsingDataRemoved( |
| base::Time(), base::Time::Max(), |
| BrowsingDataRemover::DATA_TYPE_APP_CACHE | |
| BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS | |
| BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE | |
| BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS | |
| BrowsingDataRemover::DATA_TYPE_INDEXED_DB | |
| BrowsingDataRemover::DATA_TYPE_WEB_SQL, |
| false); |
| |
| EXPECT_EQ(BrowsingDataRemover::DATA_TYPE_APP_CACHE | |
| BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS | |
| BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE | |
| BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS | |
| BrowsingDataRemover::DATA_TYPE_INDEXED_DB | |
| BrowsingDataRemover::DATA_TYPE_WEB_SQL, |
| 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_WEBSQL | |
| StoragePartition::REMOVE_DATA_MASK_APPCACHE | |
| 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 that extension and devtools data wouldn't be removed, that is, |
| // origin matcher would not match these origin. |
| EXPECT_FALSE(removal_data.origin_matcher.Run( |
| url::Origin::Create( |
| GURL("chrome-extension://abcdefghijklmnopqrstuvwxyz/")), |
| mock_policy())); |
| EXPECT_FALSE(removal_data.origin_matcher.Run( |
| url::Origin::Create(GURL("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*>( |
| BrowserContext::GetBrowsingDataRemover(GetBrowserContext())); |
| |
| // 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*>( |
| BrowserContext::GetBrowsingDataRemover(GetBrowserContext())); |
| 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(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(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, RemoveShaderCache) { |
| 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); |
| } |
| |
| TEST_F(BrowsingDataRemoverImplTest, RemoveConversions) { |
| BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(), |
| BrowsingDataRemover::DATA_TYPE_CONVERSIONS, |
| false); |
| StoragePartitionRemovalData removal_data = GetStoragePartitionRemovalData(); |
| EXPECT_EQ(removal_data.remove_mask, |
| StoragePartition::REMOVE_DATA_MASK_CONVERSIONS); |
| } |
| |
| 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: |
| 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<BrowsingDataRemover::Observer*> 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<BrowsingDataRemover::Observer*> last_called_targets_; |
| }; |
| |
| TEST_F(BrowsingDataRemoverImplTest, MultipleTasks) { |
| BrowsingDataRemoverImpl* remover = static_cast<BrowsingDataRemoverImpl*>( |
| BrowserContext::GetBrowsingDataRemover(GetBrowserContext())); |
| EXPECT_FALSE(remover->IsRemovingForTesting()); |
| |
| std::unique_ptr<BrowsingDataFilterBuilder> filter_builder_1( |
| BrowsingDataFilterBuilder::Create( |
| BrowsingDataFilterBuilder::Mode::kDelete)); |
| std::unique_ptr<BrowsingDataFilterBuilder> filter_builder_2( |
| BrowsingDataFilterBuilder::Create( |
| BrowsingDataFilterBuilder::Mode::kPreserve)); |
| filter_builder_2->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()); |
| tasks.emplace_back(base::Time(), base::Time::UnixEpoch(), |
| BrowsingDataRemover::DATA_TYPE_WEB_SQL, |
| BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB, |
| std::move(filter_builder_1), 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*>( |
| BrowserContext::GetBrowsingDataRemover(GetBrowserContext())); |
| 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*>( |
| BrowserContext::GetBrowsingDataRemover(GetBrowserContext())); |
| 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); |
| } |
| |
| 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.) |
| } |
| |
| 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)); |
| } |
| |
| 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::TimeDelta::FromSeconds(1), |
| BrowsingDataRemover::DATA_TYPE_TRUST_TOKENS, std::move(builder)); |
| } |
| |
| TEST_F(BrowsingDataRemoverImplTest, DeferCookieDeletion) { |
| TestBrowsingDataRemoverDelegate delegate; |
| BrowserContext::GetBrowsingDataRemover(GetBrowserContext()) |
| ->SetEmbedderDelegate(&delegate); |
| uint32_t dom_storage_mask = |
| StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE | |
| StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS | |
| StoragePartition::REMOVE_DATA_MASK_WEBSQL | |
| StoragePartition::REMOVE_DATA_MASK_APPCACHE | |
| StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS | |
| StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE | |
| StoragePartition::REMOVE_DATA_MASK_BACKGROUND_FETCH | |
| StoragePartition::REMOVE_DATA_MASK_INDEXEDDB; |
| |
| 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, |
| StoragePartition::REMOVE_DATA_MASK_COOKIES | dom_storage_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, |
| StoragePartition::REMOVE_DATA_MASK_COOKIES | dom_storage_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. |
| BrowserContext::GetBrowsingDataRemover(GetBrowserContext()) |
| ->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 = |
| BrowserContext::GetBrowsingDataRemover(GetBrowserContext()); |
| |
| 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); |
| } |
| |
| } // namespace content |