blob: 0f388a1244a6127a7fee145216a3855ea4c0e04a [file] [log] [blame]
// 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 "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h"
#include <stdint.h>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/containers/contains.h"
#include "base/files/file_util.h"
#include "base/guid.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_path_override.h"
#include "base/test/simple_test_clock.h"
#include "base/test/test_timeouts.h"
#include "base/time/time.h"
#include "base/util/values/values_util.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/autofill/personal_data_manager_factory.h"
#include "chrome/browser/autofill/strike_database_factory.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/browsing_data/chrome_browsing_data_remover_constants.h"
#include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_factory.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
#include "chrome/browser/custom_handlers/test_protocol_handler_registry_delegate.h"
#include "chrome/browser/domain_reliability/service_factory.h"
#include "chrome/browser/download/chrome_download_manager_delegate.h"
#include "chrome/browser/download/download_core_service_factory.h"
#include "chrome/browser/download/download_core_service_impl.h"
#include "chrome/browser/favicon/favicon_service_factory.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/language/url_language_histogram_factory.h"
#include "chrome/browser/lite_video/lite_video_keyed_service.h"
#include "chrome/browser/lite_video/lite_video_keyed_service_factory.h"
#include "chrome/browser/password_manager/account_password_store_factory.h"
#include "chrome/browser/password_manager/password_store_factory.h"
#include "chrome/browser/permissions/permission_actions_history.h"
#include "chrome/browser/permissions/permission_decision_auto_blocker_factory.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
#include "chrome/browser/signin/chrome_signin_client_factory.h"
#include "chrome/browser/signin/test_signin_client_builder.h"
#include "chrome/browser/spellchecker/spellcheck_custom_dictionary.h"
#include "chrome/browser/spellchecker/spellcheck_factory.h"
#include "chrome/browser/spellchecker/spellcheck_service.h"
#include "chrome/browser/ssl/stateful_ssl_host_state_delegate_factory.h"
#include "chrome/browser/storage/durable_storage_permission_context.h"
#include "chrome/browser/subresource_filter/subresource_filter_profile_context_factory.h"
#include "chrome/browser/sync/sync_service_factory.h"
#include "chrome/browser/translate/chrome_translate_client.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/personal_data_manager_observer.h"
#include "components/autofill/core/browser/strike_database.h"
#include "components/autofill/core/browser/test_autofill_clock.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/test/bookmark_test_helpers.h"
#include "components/browsing_data/content/browsing_data_helper.h"
#include "components/browsing_data/core/browsing_data_utils.h"
#include "components/content_settings/core/browser/content_settings_info.h"
#include "components/content_settings/core/browser/content_settings_registry.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/browser/website_settings_info.h"
#include "components/content_settings/core/browser/website_settings_registry.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_pattern.h"
#include "components/domain_reliability/clear_mode.h"
#include "components/domain_reliability/monitor.h"
#include "components/favicon/core/favicon_service.h"
#include "components/history/core/browser/history_service.h"
#include "components/language/core/browser/url_language_histogram.h"
#include "components/omnibox/browser/omnibox_prefs.h"
#include "components/os_crypt/os_crypt_mocker.h"
#include "components/password_manager/core/browser/mock_password_store.h"
#include "components/password_manager/core/browser/mock_password_sync_metadata_store.h"
#include "components/password_manager/core/browser/password_manager_test_utils.h"
#include "components/password_manager/core/browser/password_store_consumer.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "components/permissions/features.h"
#include "components/permissions/permission_decision_auto_blocker.h"
#include "components/permissions/permission_request_enums.h"
#include "components/permissions/permission_util.h"
#include "components/permissions/request_type.h"
#include "components/prefs/testing_pref_service.h"
#include "components/safe_browsing/core/browser/verdict_cache_manager.h"
#include "components/security_interstitials/content/stateful_ssl_host_state_delegate.h"
#include "components/site_isolation/pref_names.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browsing_data_filter_builder.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/storage_partition.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_utils.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/network_isolation_key.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_access_result.h"
#include "net/http/http_auth.h"
#include "net/http/http_auth_cache.h"
#include "net/http/http_transaction_factory.h"
#include "net/net_buildflags.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_test_util.h"
#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/favicon_size.h"
#include "url/gurl.h"
#include "url/origin.h"
#if defined(OS_ANDROID)
#include "chrome/browser/android/customtabs/origin_verifier.h"
#include "chrome/browser/android/search_permissions/search_permissions_service.h"
#include "chrome/browser/android/webapps/webapp_registry.h"
#include "components/feed/buildflags.h"
#else // !defined(OS_ANDROID)
#include "content/public/browser/host_zoom_map.h"
#endif // !defined(OS_ANDROID)
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chrome/browser/ash/login/users/mock_user_manager.h"
#include "chromeos/dbus/attestation/fake_attestation_client.h"
#include "components/account_id/account_id.h"
#include "components/user_manager/scoped_user_manager.h"
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
#include "components/crash/core/app/crashpad.h"
#include "components/upload_list/crash_upload_list.h"
#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "chrome/browser/extensions/mock_extension_special_storage_policy.h"
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
#if BUILDFLAG(ENABLE_PLUGINS)
#include "chrome/browser/plugins/chrome_plugin_service_filter.h"
#include "chrome/browser/plugins/plugin_utils.h"
#endif // BUILDFLAG(ENABLE_PLUGINS)
#if BUILDFLAG(ENABLE_REPORTING)
#include "base/containers/flat_map.h"
#include "net/network_error_logging/network_error_logging_service.h"
#include "net/reporting/reporting_browsing_data_remover.h"
#include "net/reporting/reporting_policy.h"
#include "net/reporting/reporting_service.h"
#endif // BUILDFLAG(ENABLE_REPORTING)
using content::BrowsingDataFilterBuilder;
using domain_reliability::DomainReliabilityClearMode;
using domain_reliability::DomainReliabilityMonitor;
using testing::_;
using testing::ByRef;
using testing::Eq;
using testing::FloatEq;
using testing::Invoke;
using testing::MakeMatcher;
using testing::Matcher;
using testing::MatcherInterface;
using testing::MatchResultListener;
using testing::Return;
using testing::SizeIs;
using testing::WithArgs;
namespace constants = chrome_browsing_data_remover;
namespace {
const char kTestRegisterableDomain1[] = "host1.com";
const char kTestRegisterableDomain3[] = "host3.com";
// For HTTP auth.
const char kTestRealm[] = "TestRealm";
// For Autofill.
const char kWebOrigin[] = "https://www.example.com/";
// Shorthands for origin types.
#if BUILDFLAG(ENABLE_EXTENSIONS)
const uint64_t kExtension = constants::ORIGIN_TYPE_EXTENSION;
#endif
const uint64_t kProtected =
content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB;
const uint64_t kUnprotected =
content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB;
// Testers --------------------------------------------------------------------
#if defined(OS_ANDROID)
class TestWebappRegistry : public WebappRegistry {
public:
TestWebappRegistry() : WebappRegistry() {}
void UnregisterWebappsForUrls(
const base::RepeatingCallback<bool(const GURL&)>& url_filter) override {
// Mocks out a JNI call.
}
void ClearWebappHistoryForUrls(
const base::RepeatingCallback<bool(const GURL&)>& url_filter) override {
// Mocks out a JNI call.
}
};
// TestSearchEngineDelegate
class TestSearchEngineDelegate
: public SearchPermissionsService::SearchEngineDelegate {
public:
std::u16string GetDSEName() override { return std::u16string(); }
url::Origin GetDSEOrigin() override {
return url::Origin::Create(GURL("https://search.com"));
}
void SetDSEChangedCallback(base::RepeatingClosure callback) override {
dse_changed_callback_ = std::move(callback);
}
void UpdateDSEOrigin() { dse_changed_callback_.Run(); }
private:
base::RepeatingClosure dse_changed_callback_;
};
#endif
class RemoveCookieTester {
public:
RemoveCookieTester() = default;
RemoveCookieTester(const RemoveCookieTester&) = delete;
RemoveCookieTester& operator=(const RemoveCookieTester&) = delete;
// Returns true, if the given cookie exists in the cookie store.
bool ContainsCookie() {
bool result = false;
base::RunLoop run_loop;
cookie_manager_->GetCookieList(
cookie_url_, net::CookieOptions::MakeAllInclusive(),
base::BindLambdaForTesting(
[&](const net::CookieAccessResultList& cookie_list,
const net::CookieAccessResultList& excluded_cookies) {
std::string cookie_line =
net::CanonicalCookie::BuildCookieLine(cookie_list);
if (cookie_line == "A=1") {
result = true;
} else {
EXPECT_EQ("", cookie_line);
result = false;
}
run_loop.Quit();
}));
run_loop.Run();
return result;
}
void AddCookie() {
base::RunLoop run_loop;
auto cookie = net::CanonicalCookie::Create(
cookie_url_, "A=1", base::Time::Now(), absl::nullopt /* server_time */);
cookie_manager_->SetCanonicalCookie(
*cookie, cookie_url_, net::CookieOptions::MakeAllInclusive(),
base::BindLambdaForTesting([&](net::CookieAccessResult result) {
EXPECT_TRUE(result.status.IsInclude());
run_loop.Quit();
}));
run_loop.Run();
}
protected:
void SetCookieManager(
mojo::Remote<network::mojom::CookieManager> cookie_manager) {
cookie_manager_ = std::move(cookie_manager);
}
private:
const GURL cookie_url_{"http://host1.com:1"};
mojo::Remote<network::mojom::CookieManager> cookie_manager_;
};
class RemoveSafeBrowsingCookieTester : public RemoveCookieTester {
public:
RemoveSafeBrowsingCookieTester()
: browser_process_(TestingBrowserProcess::GetGlobal()) {
// TODO(crbug/925153): Port consumers of the |sb_service| to use the
// interface in components/safe_browsing, and remove this cast.
scoped_refptr<safe_browsing::SafeBrowsingService> sb_service =
static_cast<safe_browsing::SafeBrowsingService*>(
safe_browsing::SafeBrowsingService::CreateSafeBrowsingService());
browser_process_->SetSafeBrowsingService(sb_service.get());
sb_service->Initialize();
base::RunLoop().RunUntilIdle();
// Make sure the safe browsing cookie store has no cookies.
// TODO(mmenke): Is this really needed?
base::RunLoop run_loop;
mojo::Remote<network::mojom::CookieManager> cookie_manager;
sb_service->GetNetworkContext()->GetCookieManager(
cookie_manager.BindNewPipeAndPassReceiver());
cookie_manager->DeleteCookies(
network::mojom::CookieDeletionFilter::New(),
base::BindLambdaForTesting(
[&](uint32_t num_deleted) { run_loop.Quit(); }));
run_loop.Run();
SetCookieManager(std::move(cookie_manager));
}
RemoveSafeBrowsingCookieTester(const RemoveSafeBrowsingCookieTester&) =
delete;
RemoveSafeBrowsingCookieTester& operator=(
const RemoveSafeBrowsingCookieTester&) = delete;
virtual ~RemoveSafeBrowsingCookieTester() {
browser_process_->safe_browsing_service()->ShutDown();
base::RunLoop().RunUntilIdle();
browser_process_->SetSafeBrowsingService(nullptr);
}
private:
TestingBrowserProcess* browser_process_;
};
class RemoveHistoryTester {
public:
RemoveHistoryTester() = default;
RemoveHistoryTester(const RemoveHistoryTester&) = delete;
RemoveHistoryTester& operator=(const RemoveHistoryTester&) = delete;
bool Init(Profile* profile) WARN_UNUSED_RESULT {
history_service_ = HistoryServiceFactory::GetForProfile(
profile, ServiceAccessType::EXPLICIT_ACCESS);
if (!history_service_)
return false;
return true;
}
// Returns true, if the given URL exists in the history service.
bool HistoryContainsURL(const GURL& url) {
bool contains_url = false;
base::RunLoop run_loop;
base::CancelableTaskTracker tracker;
history_service_->QueryURL(
url, true,
base::BindLambdaForTesting([&](history::QueryURLResult result) {
contains_url = result.success;
run_loop.Quit();
}),
&tracker);
run_loop.Run();
return contains_url;
}
void AddHistory(const GURL& url, base::Time time) {
history_service_->AddPage(url, time, nullptr, 0, GURL(),
history::RedirectList(), ui::PAGE_TRANSITION_LINK,
history::SOURCE_BROWSED, false, false);
}
private:
// TestingProfile owns the history service; we shouldn't delete it.
history::HistoryService* history_service_ = nullptr;
};
class RemoveFaviconTester {
public:
RemoveFaviconTester() = default;
RemoveFaviconTester(const RemoveFaviconTester&) = delete;
RemoveFaviconTester& operator=(const RemoveFaviconTester&) = delete;
bool Init(Profile* profile) WARN_UNUSED_RESULT {
// Create the history service if it has not been created yet.
history_service_ = HistoryServiceFactory::GetForProfile(
profile, ServiceAccessType::EXPLICIT_ACCESS);
if (!history_service_)
return false;
favicon_service_ = FaviconServiceFactory::GetForProfile(
profile, ServiceAccessType::EXPLICIT_ACCESS);
if (!favicon_service_)
return false;
return true;
}
// Returns true if there is a favicon stored for |page_url| in the favicon
// database.
bool HasFaviconForPageURL(const GURL& page_url) {
RequestFaviconSyncForPageURL(page_url);
return got_favicon_;
}
// Returns true if:
// - There is a favicon stored for |page_url| in the favicon database.
// - The stored favicon is expired.
bool HasExpiredFaviconForPageURL(const GURL& page_url) {
RequestFaviconSyncForPageURL(page_url);
return got_expired_favicon_;
}
// Adds a visit to history and stores an arbitrary favicon bitmap for
// |page_url|.
void VisitAndAddFavicon(const GURL& page_url) {
history_service_->AddPage(page_url, base::Time::Now(), nullptr, 0, GURL(),
history::RedirectList(), ui::PAGE_TRANSITION_LINK,
history::SOURCE_BROWSED, false, false);
SkBitmap bitmap;
bitmap.allocN32Pixels(gfx::kFaviconSize, gfx::kFaviconSize);
bitmap.eraseColor(SK_ColorBLUE);
favicon_service_->SetFavicons({page_url}, page_url,
favicon_base::IconType::kFavicon,
gfx::Image::CreateFrom1xBitmap(bitmap));
}
private:
// Synchronously requests the favicon for |page_url| from the favicon
// database.
void RequestFaviconSyncForPageURL(const GURL& page_url) {
base::RunLoop run_loop;
quit_closure_ = run_loop.QuitClosure();
favicon_service_->GetRawFaviconForPageURL(
page_url, {favicon_base::IconType::kFavicon}, gfx::kFaviconSize,
/*fallback_to_host=*/false,
base::BindOnce(&RemoveFaviconTester::SaveResultAndQuit,
base::Unretained(this)),
&tracker_);
run_loop.Run();
}
// Callback for HistoryService::QueryURL.
void SaveResultAndQuit(const favicon_base::FaviconRawBitmapResult& result) {
got_favicon_ = result.is_valid();
got_expired_favicon_ = result.is_valid() && result.expired;
std::move(quit_closure_).Run();
}
// For favicon requests.
base::CancelableTaskTracker tracker_;
bool got_favicon_ = false;
bool got_expired_favicon_ = false;
base::OnceClosure quit_closure_;
// Owned by TestingProfile.
history::HistoryService* history_service_ = nullptr;
favicon::FaviconService* favicon_service_ = nullptr;
};
std::unique_ptr<KeyedService> BuildProtocolHandlerRegistry(
content::BrowserContext* context) {
Profile* profile = Profile::FromBrowserContext(context);
return std::make_unique<ProtocolHandlerRegistry>(
profile, std::make_unique<TestProtocolHandlerRegistryDelegate>());
}
class ClearDomainReliabilityTester {
public:
explicit ClearDomainReliabilityTester(TestingProfile* profile) {
static_cast<ChromeBrowsingDataRemoverDelegate*>(
profile->GetBrowsingDataRemoverDelegate())
->OverrideDomainReliabilityClearerForTesting(base::BindRepeating(
&ClearDomainReliabilityTester::Clear, base::Unretained(this)));
}
unsigned clear_count() const { return clear_count_; }
network::mojom::NetworkContext::DomainReliabilityClearMode last_clear_mode()
const {
return last_clear_mode_;
}
const base::RepeatingCallback<bool(const GURL&)>& last_filter() const {
return last_filter_;
}
private:
void Clear(
content::BrowsingDataFilterBuilder* filter_builder,
network::mojom::NetworkContext_DomainReliabilityClearMode mode,
network::mojom::NetworkContext::ClearDomainReliabilityCallback callback) {
++clear_count_;
last_clear_mode_ = mode;
std::move(callback).Run();
last_filter_ = filter_builder->MatchesAllOriginsAndDomains()
? base::RepeatingCallback<bool(const GURL&)>()
: filter_builder->BuildUrlFilter();
}
unsigned clear_count_ = 0;
network::mojom::NetworkContext::DomainReliabilityClearMode last_clear_mode_;
base::RepeatingCallback<bool(const GURL&)> last_filter_;
};
class RemovePasswordsTester {
public:
explicit RemovePasswordsTester(TestingProfile* testing_profile) {
PasswordStoreFactory::GetInstance()->SetTestingFactory(
testing_profile,
base::BindRepeating(
&password_manager::BuildPasswordStore<
content::BrowserContext,
testing::NiceMock<password_manager::MockPasswordStore>>));
profile_store_ = static_cast<password_manager::MockPasswordStore*>(
PasswordStoreFactory::GetForProfile(testing_profile,
ServiceAccessType::EXPLICIT_ACCESS)
.get());
if (base::FeatureList::IsEnabled(
password_manager::features::kEnablePasswordsAccountStorage)) {
AccountPasswordStoreFactory::GetInstance()->SetTestingFactory(
testing_profile,
base::BindRepeating(
&password_manager::BuildPasswordStore<
content::BrowserContext,
testing::NiceMock<password_manager::MockPasswordStore>>));
account_store_ = static_cast<password_manager::MockPasswordStore*>(
AccountPasswordStoreFactory::GetForProfile(
testing_profile, ServiceAccessType::EXPLICIT_ACCESS)
.get());
ON_CALL(*account_store_, GetMetadataStore())
.WillByDefault(Return(&account_metadata_store_));
}
OSCryptMocker::SetUp();
}
RemovePasswordsTester(const RemovePasswordsTester&) = delete;
RemovePasswordsTester& operator=(const RemovePasswordsTester&) = delete;
~RemovePasswordsTester() { OSCryptMocker::TearDown(); }
password_manager::MockPasswordStore* profile_store() {
return profile_store_;
}
password_manager::MockPasswordStore* account_store() {
return account_store_;
}
password_manager::MockPasswordSyncMetadataStore* account_metadata_store() {
return &account_metadata_store_;
}
private:
password_manager::MockPasswordStore* profile_store_;
password_manager::MockPasswordStore* account_store_;
password_manager::MockPasswordSyncMetadataStore account_metadata_store_;
};
class RemovePermissionPromptCountsTest {
public:
explicit RemovePermissionPromptCountsTest(TestingProfile* profile)
: autoblocker_(
PermissionDecisionAutoBlockerFactory::GetForProfile(profile)) {}
RemovePermissionPromptCountsTest(const RemovePermissionPromptCountsTest&) =
delete;
RemovePermissionPromptCountsTest& operator=(
const RemovePermissionPromptCountsTest&) = delete;
int GetDismissCount(const GURL& url, ContentSettingsType permission) {
return autoblocker_->GetDismissCount(url, permission);
}
int GetIgnoreCount(const GURL& url, ContentSettingsType permission) {
return autoblocker_->GetIgnoreCount(url, permission);
}
bool RecordIgnoreAndEmbargo(const GURL& url, ContentSettingsType permission) {
return autoblocker_->RecordIgnoreAndEmbargo(url, permission, false);
}
bool RecordDismissAndEmbargo(const GURL& url,
ContentSettingsType permission) {
return autoblocker_->RecordDismissAndEmbargo(url, permission, false);
}
void CheckEmbargo(const GURL& url,
ContentSettingsType permission,
ContentSetting expected_setting) {
EXPECT_EQ(expected_setting,
autoblocker_->GetEmbargoResult(url, permission).content_setting);
}
private:
permissions::PermissionDecisionAutoBlocker* autoblocker_;
};
// 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 filters that delete or
// preserve origins, 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) {}
virtual bool MatchAndExplain(
const base::RepeatingCallback<bool(const GURL&)>& filter,
MatchResultListener* listener) const {
if (filter.is_null() && to_match_.is_null())
return true;
if (filter.is_null() != to_match_.is_null())
return false;
const GURL urls_to_test_[] = {
GURL("http://host1.com:1"), GURL("http://host2.com:1"),
GURL("http://host3.com:1"), 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;
}
virtual void DescribeTo(::std::ostream* os) const {
*os << "is probably the same url filter as " << &to_match_;
}
virtual void DescribeNegationTo(::std::ostream* os) const {
*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));
}
bool ProbablySameFilters(
const base::RepeatingCallback<bool(const GURL&)>& filter1,
const base::RepeatingCallback<bool(const GURL&)>& filter2) {
return ProbablySameFilter(filter1).MatchAndExplain(filter2, nullptr);
}
base::Time AnHourAgo() {
return base::Time::Now() - base::TimeDelta::FromHours(1);
}
class RemoveDownloadsTester {
public:
explicit RemoveDownloadsTester(TestingProfile* testing_profile)
: download_manager_(new testing::NiceMock<content::MockDownloadManager>) {
testing_profile->SetDownloadManagerForTesting(
base::WrapUnique(download_manager_));
std::unique_ptr<ChromeDownloadManagerDelegate> delegate =
std::make_unique<ChromeDownloadManagerDelegate>(testing_profile);
chrome_download_manager_delegate_ = delegate.get();
service_ =
DownloadCoreServiceFactory::GetForBrowserContext(testing_profile);
service_->SetDownloadManagerDelegateForTesting(std::move(delegate));
EXPECT_CALL(*download_manager_, GetBrowserContext())
.WillRepeatedly(Return(testing_profile));
EXPECT_CALL(*download_manager_, Shutdown());
}
RemoveDownloadsTester(const RemoveDownloadsTester&) = delete;
RemoveDownloadsTester& operator=(const RemoveDownloadsTester&) = delete;
~RemoveDownloadsTester() {
service_->SetDownloadManagerDelegateForTesting(nullptr);
}
content::MockDownloadManager* download_manager() { return download_manager_; }
private:
DownloadCoreService* service_;
content::MockDownloadManager* download_manager_; // Owned by testing profile.
ChromeDownloadManagerDelegate* chrome_download_manager_delegate_;
};
} // namespace
ACTION(QuitMainMessageLoop) {
base::RunLoop::QuitCurrentWhenIdleDeprecated();
}
class PersonalDataLoadedObserverMock
: public autofill::PersonalDataManagerObserver {
public:
PersonalDataLoadedObserverMock() = default;
~PersonalDataLoadedObserverMock() override {}
MOCK_METHOD0(OnPersonalDataChanged, void());
MOCK_METHOD0(OnPersonalDataFinishedProfileTasks, void());
};
// RemoveAutofillTester is not a part of the anonymous namespace above, as
// PersonalDataManager declares it a friend in an empty namespace.
class RemoveAutofillTester {
public:
explicit RemoveAutofillTester(TestingProfile* profile)
: personal_data_manager_(
autofill::PersonalDataManagerFactory::GetForProfile(profile)) {
autofill::test::DisableSystemServices(profile->GetPrefs());
personal_data_manager_->AddObserver(&personal_data_observer_);
}
RemoveAutofillTester(const RemoveAutofillTester&) = delete;
RemoveAutofillTester& operator=(const RemoveAutofillTester&) = delete;
~RemoveAutofillTester() {
personal_data_manager_->RemoveObserver(&personal_data_observer_);
autofill::test::ReenableSystemServices();
}
// Returns true if there are autofill profiles.
bool HasProfile() {
return !personal_data_manager_->GetProfiles().empty() &&
!personal_data_manager_->GetCreditCards().empty();
}
bool HasOrigin(const std::string& origin) {
const std::vector<autofill::AutofillProfile*>& profiles =
personal_data_manager_->GetProfiles();
for (const autofill::AutofillProfile* profile : profiles) {
if (profile->origin() == origin)
return true;
}
const std::vector<autofill::CreditCard*>& credit_cards =
personal_data_manager_->GetCreditCards();
for (const autofill::CreditCard* credit_card : credit_cards) {
if (credit_card->origin() == origin)
return true;
}
return false;
}
// Add two profiles and two credit cards to the database. In each pair, one
// entry has a web origin and the other has a Chrome origin.
void AddProfilesAndCards() {
std::vector<autofill::AutofillProfile> profiles;
autofill::AutofillProfile profile;
profile.set_guid(base::GenerateGUID());
profile.set_origin(kWebOrigin);
profile.SetRawInfo(autofill::NAME_FIRST, u"Bob");
profile.SetRawInfo(autofill::NAME_LAST, u"Smith");
profile.SetRawInfo(autofill::ADDRESS_HOME_ZIP, u"94043");
profile.SetRawInfo(autofill::EMAIL_ADDRESS, u"sue@example.com");
profile.SetRawInfo(autofill::COMPANY_NAME, u"Company X");
profiles.push_back(profile);
profile.set_guid(base::GenerateGUID());
profile.set_origin(autofill::kSettingsOrigin);
profiles.push_back(profile);
personal_data_manager_->SetProfiles(&profiles);
WaitForOnPersonalDataFinishedProfileTasks();
std::vector<autofill::CreditCard> cards;
autofill::CreditCard card;
card.set_guid(base::GenerateGUID());
card.set_origin(kWebOrigin);
card.SetRawInfo(autofill::CREDIT_CARD_NUMBER, u"1234-5678-9012-3456");
cards.push_back(card);
card.set_guid(base::GenerateGUID());
card.set_origin(autofill::kSettingsOrigin);
cards.push_back(card);
personal_data_manager_->SetCreditCards(&cards);
WaitForOnPersonalDataChanged();
}
private:
void WaitForOnPersonalDataChanged() {
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillRepeatedly(QuitMainMessageLoop());
base::RunLoop().Run();
}
void WaitForOnPersonalDataFinishedProfileTasks() {
EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
.WillRepeatedly(QuitMainMessageLoop());
base::RunLoop().Run();
}
autofill::PersonalDataManager* personal_data_manager_;
testing::NiceMock<PersonalDataLoadedObserverMock> personal_data_observer_;
};
#if BUILDFLAG(ENABLE_REPORTING)
class MockReportingService : public net::ReportingService {
public:
MockReportingService() = default;
MockReportingService(const MockReportingService&) = delete;
MockReportingService& operator=(const MockReportingService&) = delete;
~MockReportingService() override = default;
// net::ReportingService implementation:
void SetDocumentReportingEndpoints(
const url::Origin& origin,
const net::NetworkIsolationKey& network_isolation_key,
const base::flat_map<std::string, std::string>& endpoints) override {
NOTREACHED();
}
void QueueReport(const GURL& url,
const net::NetworkIsolationKey& network_isolation_key,
const std::string& user_agent,
const std::string& group,
const std::string& type,
std::unique_ptr<const base::Value> body,
int depth) override {
NOTREACHED();
}
void ProcessReportToHeader(
const GURL& url,
const net::NetworkIsolationKey& network_isolation_key,
const std::string& header_value) override {
NOTREACHED();
}
void RemoveBrowsingData(uint64_t data_type_mask,
const base::RepeatingCallback<bool(const GURL&)>&
origin_filter) override {
++remove_calls_;
last_data_type_mask_ = data_type_mask;
last_origin_filter_ = origin_filter;
}
void RemoveAllBrowsingData(uint64_t data_type_mask) override {
++remove_all_calls_;
last_data_type_mask_ = data_type_mask;
last_origin_filter_ = base::RepeatingCallback<bool(const GURL&)>();
}
void OnShutdown() override {}
const net::ReportingPolicy& GetPolicy() const override {
static net::ReportingPolicy dummy_policy_;
NOTREACHED();
return dummy_policy_;
}
net::ReportingContext* GetContextForTesting() const override {
NOTREACHED();
return nullptr;
}
int remove_calls() const { return remove_calls_; }
int remove_all_calls() const { return remove_all_calls_; }
uint64_t last_data_type_mask() const { return last_data_type_mask_; }
const base::RepeatingCallback<bool(const GURL&)>& last_origin_filter() const {
return last_origin_filter_;
}
private:
int remove_calls_ = 0;
int remove_all_calls_ = 0;
uint64_t last_data_type_mask_ = 0;
base::RepeatingCallback<bool(const GURL&)> last_origin_filter_;
};
namespace autofill {
// StrikeDatabaseTester is in the autofill namespace since
// StrikeDatabase declares it as a friend in the autofill namespace.
class StrikeDatabaseTester {
public:
explicit StrikeDatabaseTester(Profile* profile)
: strike_database_(
autofill::StrikeDatabaseFactory::GetForProfile(profile)) {}
bool IsEmpty() {
int num_keys;
base::RunLoop run_loop;
strike_database_->LoadKeys(base::BindLambdaForTesting(
[&](bool success, std::unique_ptr<std::vector<std::string>> keys) {
num_keys = keys.get()->size();
run_loop.Quit();
}));
run_loop.Run();
return (num_keys == 0);
}
private:
autofill::StrikeDatabase* strike_database_;
};
} // namespace autofill
class ClearReportingCacheTester {
public:
ClearReportingCacheTester(network::NetworkContext* network_context,
bool create_service)
: url_request_context_(network_context->url_request_context()) {
if (create_service)
service_ = std::make_unique<MockReportingService>();
old_service_ = url_request_context_->reporting_service();
url_request_context_->set_reporting_service(service_.get());
}
~ClearReportingCacheTester() {
DCHECK_EQ(service_.get(), url_request_context_->reporting_service());
url_request_context_->set_reporting_service(old_service_);
}
const MockReportingService& mock() { return *service_; }
private:
net::URLRequestContext* url_request_context_;
std::unique_ptr<MockReportingService> service_;
net::ReportingService* old_service_;
};
class MockNetworkErrorLoggingService : public net::NetworkErrorLoggingService {
public:
MockNetworkErrorLoggingService() = default;
MockNetworkErrorLoggingService(const MockNetworkErrorLoggingService&) =
delete;
MockNetworkErrorLoggingService& operator=(
const MockNetworkErrorLoggingService&) = delete;
~MockNetworkErrorLoggingService() override = default;
// net::NetworkErrorLoggingService implementation:
void OnHeader(const net::NetworkIsolationKey& network_isolation_key,
const url::Origin& origin,
const net::IPAddress& received_ip_address,
const std::string& value) override {
NOTREACHED();
}
void OnRequest(RequestDetails details) override { NOTREACHED(); }
void QueueSignedExchangeReport(SignedExchangeReportDetails details) override {
NOTREACHED();
}
void RemoveBrowsingData(const base::RepeatingCallback<bool(const GURL&)>&
origin_filter) override {
++remove_calls_;
last_origin_filter_ = origin_filter;
}
void RemoveAllBrowsingData() override {
++remove_all_calls_;
last_origin_filter_ = base::RepeatingCallback<bool(const GURL&)>();
}
int remove_calls() const { return remove_calls_; }
int remove_all_calls() const { return remove_all_calls_; }
const base::RepeatingCallback<bool(const GURL&)>& last_origin_filter() const {
return last_origin_filter_;
}
private:
int remove_calls_ = 0;
int remove_all_calls_ = 0;
base::RepeatingCallback<bool(const GURL&)> last_origin_filter_;
};
class ClearNetworkErrorLoggingTester {
public:
ClearNetworkErrorLoggingTester(network::NetworkContext* network_context,
bool create_service)
: url_request_context_(network_context->url_request_context()) {
if (create_service)
service_ = std::make_unique<MockNetworkErrorLoggingService>();
url_request_context_->set_network_error_logging_service(service_.get());
}
ClearNetworkErrorLoggingTester(const ClearNetworkErrorLoggingTester&) =
delete;
ClearNetworkErrorLoggingTester& operator=(
const ClearNetworkErrorLoggingTester&) = delete;
~ClearNetworkErrorLoggingTester() {
DCHECK_EQ(service_.get(),
url_request_context_->network_error_logging_service());
url_request_context_->set_network_error_logging_service(nullptr);
}
const MockNetworkErrorLoggingService& mock() { return *service_; }
private:
net::URLRequestContext* url_request_context_;
std::unique_ptr<MockNetworkErrorLoggingService> service_;
};
#endif // BUILDFLAG(ENABLE_REPORTING)
// Test Class -----------------------------------------------------------------
class ChromeBrowsingDataRemoverDelegateTest : public testing::Test {
public:
ChromeBrowsingDataRemoverDelegateTest() = default;
ChromeBrowsingDataRemoverDelegateTest(
const ChromeBrowsingDataRemoverDelegateTest&) = delete;
ChromeBrowsingDataRemoverDelegateTest& operator=(
const ChromeBrowsingDataRemoverDelegateTest&) = delete;
~ChromeBrowsingDataRemoverDelegateTest() override = default;
void SetUp() override {
// Make sure the Network Service is started before making a NetworkContext.
content::GetNetworkService();
task_environment_.RunUntilIdle();
// This needs to be done after the test constructor, so that subclasses
// that initialize a ScopedFeatureList in their constructors can do so
// before the code below potentially kicks off tasks on other threads that
// check if a feature is enabled, to avoid tsan data races.
TestingProfile::Builder profile_builder;
profile_builder.AddTestingFactory(
StatefulSSLHostStateDelegateFactory::GetInstance(),
StatefulSSLHostStateDelegateFactory::GetDefaultFactoryForTesting());
profile_builder.AddTestingFactory(
BookmarkModelFactory::GetInstance(),
BookmarkModelFactory::GetDefaultFactory());
profile_builder.AddTestingFactory(
HistoryServiceFactory::GetInstance(),
HistoryServiceFactory::GetDefaultFactory());
profile_builder.AddTestingFactory(
FaviconServiceFactory::GetInstance(),
FaviconServiceFactory::GetDefaultFactory());
profile_builder.AddTestingFactory(
SpellcheckServiceFactory::GetInstance(),
base::BindRepeating([](content::BrowserContext* profile) {
return std::unique_ptr<KeyedService>(
new SpellcheckService(static_cast<Profile*>(profile)));
}));
profile_builder.AddTestingFactory(SyncServiceFactory::GetInstance(),
SyncServiceFactory::GetDefaultFactory());
profile_builder.AddTestingFactory(
ChromeSigninClientFactory::GetInstance(),
base::BindRepeating(&signin::BuildTestSigninClient));
profile_ = profile_builder.Build();
remover_ = profile_->GetBrowsingDataRemover();
auto network_context_params = network::mojom::NetworkContextParams::New();
network_context_params->cert_verifier_params =
content::GetCertVerifierParams(
cert_verifier::mojom::CertVerifierCreationParams::New());
mojo::PendingRemote<network::mojom::NetworkContext> network_context_remote;
network_context_ = std::make_unique<network::NetworkContext>(
network::NetworkService::GetNetworkServiceForTesting(),
network_context_remote.InitWithNewPipeAndPassReceiver(),
std::move(network_context_params));
profile_->GetDefaultStoragePartition()->SetNetworkContextForTesting(
std::move(network_context_remote));
ProtocolHandlerRegistryFactory::GetInstance()->SetTestingFactory(
profile_.get(), base::BindRepeating(&BuildProtocolHandlerRegistry));
#if defined(OS_ANDROID)
static_cast<ChromeBrowsingDataRemoverDelegate*>(
profile_->GetBrowsingDataRemoverDelegate())
->OverrideWebappRegistryForTesting(
std::make_unique<TestWebappRegistry>());
SearchPermissionsService* service =
SearchPermissionsService::Factory::GetForBrowserContext(profile_.get());
auto delegate = std::make_unique<TestSearchEngineDelegate>();
dse_origin_ = delegate->GetDSEOrigin().GetURL();
TestSearchEngineDelegate* delegate_ptr = delegate.get();
service->SetSearchEngineDelegateForTest(std::move(delegate));
delegate_ptr->UpdateDSEOrigin();
#endif
}
void TearDown() override {
// Destroying the profile triggers a call to leveldb_proto::
// ProtoDatabaseProvider::SetSharedDBDeleteObsoleteDelayForTesting, which
// can race with leveldb_proto::SharedProtoDatabase::OnDatabaseInit
// on another thread. Allowing those tasks to complete before we destroy
// the profile should fix the race.
content::RunAllTasksUntilIdle();
// TestingProfile 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 profile is destroyed, and that
// the message loop is cleared out, before destroying the threads and loop.
// Otherwise we leak memory.
profile_.reset();
base::RunLoop().RunUntilIdle();
TestingBrowserProcess::GetGlobal()->SetLocalState(nullptr);
}
// Returns the set of data types for which the deletion failed.
uint64_t BlockUntilBrowsingDataRemoved(const base::Time& delete_begin,
const base::Time& delete_end,
uint64_t remove_mask,
bool include_protected_origins) {
uint64_t origin_type_mask =
content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB;
if (include_protected_origins) {
origin_type_mask |=
content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB;
}
content::BrowsingDataRemoverCompletionObserver completion_observer(
remover_);
remover_->RemoveAndReply(delete_begin, delete_end, remove_mask,
origin_type_mask, &completion_observer);
base::ThreadPoolInstance::Get()->FlushForTesting();
completion_observer.BlockUntilCompletion();
return completion_observer.failed_data_types();
}
void BlockUntilOriginDataRemoved(
const base::Time& delete_begin,
const base::Time& delete_end,
uint64_t remove_mask,
std::unique_ptr<BrowsingDataFilterBuilder> filter_builder) {
content::BrowsingDataRemoverCompletionObserver completion_observer(
remover_);
remover_->RemoveWithFilterAndReply(
delete_begin, delete_end, remove_mask,
content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
std::move(filter_builder), &completion_observer);
base::ThreadPoolInstance::Get()->FlushForTesting();
completion_observer.BlockUntilCompletion();
}
const base::Time& GetBeginTime() {
return remover_->GetLastUsedBeginTimeForTesting();
}
uint64_t GetRemovalMask() {
return remover_->GetLastUsedRemovalMaskForTesting();
}
uint64_t GetOriginTypeMask() {
return remover_->GetLastUsedOriginTypeMaskForTesting();
}
network::NetworkContext* network_context() { return network_context_.get(); }
TestingProfile* GetProfile() { return profile_.get(); }
GURL dse_origin() const { return dse_origin_; }
bool Match(const GURL& origin,
uint64_t mask,
storage::SpecialStoragePolicy* policy) {
return remover_->DoesOriginMatchMaskForTesting(
mask, url::Origin::Create(origin), policy);
}
content::BrowserTaskEnvironment* task_environment() {
return &task_environment_;
}
protected:
// |feature_list_| needs to be destroyed after |task_environment_|, to avoid
// tsan flakes caused by other tasks running while |feature_list_| is
// destroyed.
base::test::ScopedFeatureList feature_list_;
private:
// Cached pointer to BrowsingDataRemover for access to testing methods.
content::BrowsingDataRemover* remover_;
content::BrowserTaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
std::unique_ptr<network::NetworkContext> network_context_;
std::unique_ptr<TestingProfile> profile_;
GURL dse_origin_;
};
// TODO(crbug.com/812589): Disabled due to flakiness in cookie store
// initialization.
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
DISABLED_RemoveSafeBrowsingCookieForever) {
RemoveSafeBrowsingCookieTester tester;
tester.AddCookie();
ASSERT_TRUE(tester.ContainsCookie());
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());
EXPECT_FALSE(tester.ContainsCookie());
}
// TODO(crbug.com/812589): Disabled due to flakiness in cookie store
// initialization.
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
DISABLED_RemoveSafeBrowsingCookieLastHour) {
RemoveSafeBrowsingCookieTester tester;
tester.AddCookie();
ASSERT_TRUE(tester.ContainsCookie());
BlockUntilBrowsingDataRemoved(AnHourAgo(), 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());
// Removing with time period other than all time should not clear safe
// browsing cookies.
EXPECT_TRUE(tester.ContainsCookie());
}
// TODO(crbug.com/812589): Disabled due to flakiness in cookie store
// initialization.
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
DISABLED_RemoveSafeBrowsingCookieForeverWithPredicate) {
RemoveSafeBrowsingCookieTester tester;
tester.AddCookie();
ASSERT_TRUE(tester.ContainsCookie());
std::unique_ptr<BrowsingDataFilterBuilder> filter(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kPreserve));
filter->AddRegisterableDomain(kTestRegisterableDomain1);
BlockUntilOriginDataRemoved(base::Time(), base::Time::Max(),
content::BrowsingDataRemover::DATA_TYPE_COOKIES,
std::move(filter));
EXPECT_EQ(content::BrowsingDataRemover::DATA_TYPE_COOKIES, GetRemovalMask());
EXPECT_EQ(content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
EXPECT_TRUE(tester.ContainsCookie());
std::unique_ptr<BrowsingDataFilterBuilder> filter2(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kDelete));
filter2->AddRegisterableDomain(kTestRegisterableDomain1);
BlockUntilOriginDataRemoved(base::Time(), base::Time::Max(),
content::BrowsingDataRemover::DATA_TYPE_COOKIES,
std::move(filter2));
EXPECT_FALSE(tester.ContainsCookie());
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest, RemoveHistoryForever) {
RemoveHistoryTester tester;
ASSERT_TRUE(tester.Init(GetProfile()));
const GURL kOrigin1("http://host1.com:1");
tester.AddHistory(kOrigin1, base::Time::Now());
ASSERT_TRUE(tester.HistoryContainsURL(kOrigin1));
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, false);
EXPECT_EQ(constants::DATA_TYPE_HISTORY, GetRemovalMask());
EXPECT_EQ(content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
EXPECT_FALSE(tester.HistoryContainsURL(kOrigin1));
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest, RemoveHistoryForLastHour) {
RemoveHistoryTester tester;
ASSERT_TRUE(tester.Init(GetProfile()));
base::Time two_hours_ago = base::Time::Now() - base::TimeDelta::FromHours(2);
const GURL kOrigin1("http://host1.com:1");
const GURL kOrigin2("http://host2.com:1");
tester.AddHistory(kOrigin1, base::Time::Now());
tester.AddHistory(kOrigin2, two_hours_ago);
ASSERT_TRUE(tester.HistoryContainsURL(kOrigin1));
ASSERT_TRUE(tester.HistoryContainsURL(kOrigin2));
BlockUntilBrowsingDataRemoved(AnHourAgo(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, false);
EXPECT_EQ(constants::DATA_TYPE_HISTORY, GetRemovalMask());
EXPECT_EQ(content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
EXPECT_FALSE(tester.HistoryContainsURL(kOrigin1));
EXPECT_TRUE(tester.HistoryContainsURL(kOrigin2));
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest, RemoveHistoryForOlderThan30Days) {
RemoveHistoryTester tester;
ASSERT_TRUE(tester.Init(GetProfile()));
base::Time older_than_29days =
base::Time::Now() - base::TimeDelta::FromDays(29);
base::Time older_than_30days =
base::Time::Now() - base::TimeDelta::FromDays(30);
base::Time older_than_31days =
base::Time::Now() - base::TimeDelta::FromDays(31);
const GURL kOrigin1("http://host1.com:1");
const GURL kOrigin2("http://host2.com:1");
const GURL kOrigin3("http://host3.com:1");
tester.AddHistory(kOrigin1, base::Time::Now());
tester.AddHistory(kOrigin2, older_than_29days);
tester.AddHistory(kOrigin3, older_than_31days);
ASSERT_TRUE(tester.HistoryContainsURL(kOrigin1));
ASSERT_TRUE(tester.HistoryContainsURL(kOrigin2));
ASSERT_TRUE(tester.HistoryContainsURL(kOrigin3));
BlockUntilBrowsingDataRemoved(base::Time(), older_than_30days,
constants::DATA_TYPE_HISTORY, false);
EXPECT_EQ(constants::DATA_TYPE_HISTORY, GetRemovalMask());
EXPECT_EQ(content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
EXPECT_TRUE(tester.HistoryContainsURL(kOrigin1));
EXPECT_TRUE(tester.HistoryContainsURL(kOrigin2));
EXPECT_FALSE(tester.HistoryContainsURL(kOrigin3));
}
// This should crash (DCHECK) in Debug, but death tests don't work properly
// here.
// TODO(msramek): To make this testable, the refusal to delete history should
// be made a part of interface (e.g. a success value) as opposed to a DCHECK.
#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
TEST_F(ChromeBrowsingDataRemoverDelegateTest, RemoveHistoryProhibited) {
RemoveHistoryTester tester;
ASSERT_TRUE(tester.Init(GetProfile()));
PrefService* prefs = GetProfile()->GetPrefs();
prefs->SetBoolean(prefs::kAllowDeletingBrowserHistory, false);
base::Time two_hours_ago = base::Time::Now() - base::TimeDelta::FromHours(2);
const GURL kOrigin1("http://host1.com:1");
const GURL kOrigin2("http://host2.com:1");
tester.AddHistory(kOrigin1, base::Time::Now());
tester.AddHistory(kOrigin2, two_hours_ago);
ASSERT_TRUE(tester.HistoryContainsURL(kOrigin1));
ASSERT_TRUE(tester.HistoryContainsURL(kOrigin2));
BlockUntilBrowsingDataRemoved(AnHourAgo(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, false);
EXPECT_EQ(constants::DATA_TYPE_HISTORY, GetRemovalMask());
EXPECT_EQ(content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Nothing should have been deleted.
EXPECT_TRUE(tester.HistoryContainsURL(kOrigin1));
EXPECT_TRUE(tester.HistoryContainsURL(kOrigin2));
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
RemoveMultipleTypesHistoryProhibited) {
PrefService* prefs = GetProfile()->GetPrefs();
prefs->SetBoolean(prefs::kAllowDeletingBrowserHistory, false);
// Add some history.
const GURL kOrigin1("http://host1.com:1");
RemoveHistoryTester history_tester;
ASSERT_TRUE(history_tester.Init(GetProfile()));
history_tester.AddHistory(kOrigin1, base::Time::Now());
ASSERT_TRUE(history_tester.HistoryContainsURL(kOrigin1));
// Expect that passwords will be deleted, as they do not depend
// on |prefs::kAllowDeletingBrowserHistory|.
RemovePasswordsTester tester(GetProfile());
EXPECT_CALL(*tester.profile_store(), RemoveLoginsByURLAndTimeImpl(_, _, _));
uint64_t removal_mask =
constants::DATA_TYPE_HISTORY | constants::DATA_TYPE_PASSWORDS;
BlockUntilBrowsingDataRemoved(AnHourAgo(), base::Time::Max(), removal_mask,
false);
EXPECT_EQ(removal_mask, GetRemovalMask());
EXPECT_EQ(content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Verify that history was not deleted.
EXPECT_TRUE(history_tester.HistoryContainsURL(kOrigin1));
}
#endif
TEST_F(ChromeBrowsingDataRemoverDelegateTest, RemoveExternalProtocolData) {
TestingProfile* profile = GetProfile();
url::Origin test_origin = url::Origin::Create(GURL("https://example.test"));
const std::string serialized_test_origin = test_origin.Serialize();
// Add external protocol data on profile.
base::DictionaryValue prefs;
prefs.SetKey(serialized_test_origin,
base::Value(base::Value::Type::DICTIONARY));
base::Value* allowed_protocols_for_origin =
prefs.FindDictKey(serialized_test_origin);
allowed_protocols_for_origin->SetBoolKey("tel", true);
profile->GetPrefs()->Set(prefs::kProtocolHandlerPerOriginAllowedProtocols,
prefs);
EXPECT_FALSE(
profile->GetPrefs()
->GetDictionary(prefs::kProtocolHandlerPerOriginAllowedProtocols)
->DictEmpty());
BlockUntilBrowsingDataRemoved(AnHourAgo(), base::Time::Max(),
constants::DATA_TYPE_EXTERNAL_PROTOCOL_DATA,
false);
EXPECT_TRUE(
profile->GetPrefs()
->GetDictionary(prefs::kProtocolHandlerPerOriginAllowedProtocols)
->DictEmpty());
}
// Check that clearing browsing data (either history or cookies with other site
// data) clears any saved isolated origins.
TEST_F(ChromeBrowsingDataRemoverDelegateTest, RemovePersistentIsolatedOrigins) {
PrefService* prefs = GetProfile()->GetPrefs();
// Add foo.com to the list of stored user-triggered isolated origins and
// bar.com to the list of stored web-triggered isolated origins.
base::ListValue list;
list.AppendString("http://foo.com");
prefs->Set(site_isolation::prefs::kUserTriggeredIsolatedOrigins, list);
EXPECT_FALSE(
prefs->GetList(site_isolation::prefs::kUserTriggeredIsolatedOrigins)
->GetList()
.empty());
base::DictionaryValue dict;
dict.SetKey("https://bar.com", util::TimeToValue(base::Time::Now()));
prefs->Set(site_isolation::prefs::kWebTriggeredIsolatedOrigins, dict);
EXPECT_FALSE(
prefs->GetDictionary(site_isolation::prefs::kWebTriggeredIsolatedOrigins)
->DictEmpty());
// Clear history and ensure the stored isolated origins are cleared.
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, false);
EXPECT_TRUE(
prefs->GetList(site_isolation::prefs::kUserTriggeredIsolatedOrigins)
->GetList()
.empty());
EXPECT_TRUE(
prefs->GetDictionary(site_isolation::prefs::kWebTriggeredIsolatedOrigins)
->DictEmpty());
// Re-add foo.com and bar.com to stored isolated origins.
prefs->Set(site_isolation::prefs::kUserTriggeredIsolatedOrigins, list);
EXPECT_FALSE(
prefs->GetList(site_isolation::prefs::kUserTriggeredIsolatedOrigins)
->GetList()
.empty());
prefs->Set(site_isolation::prefs::kWebTriggeredIsolatedOrigins, dict);
EXPECT_FALSE(
prefs->GetDictionary(site_isolation::prefs::kWebTriggeredIsolatedOrigins)
->DictEmpty());
// Now clear cookies and other site data, and ensure foo.com is cleared.
// Note that this uses a short time period to document that time ranges are
// currently ignored by stored isolated origins.
BlockUntilBrowsingDataRemoved(AnHourAgo(), base::Time::Max(),
constants::DATA_TYPE_SITE_DATA, false);
EXPECT_TRUE(
prefs->GetList(site_isolation::prefs::kUserTriggeredIsolatedOrigins)
->GetList()
.empty());
EXPECT_TRUE(
prefs->GetDictionary(site_isolation::prefs::kWebTriggeredIsolatedOrigins)
->DictEmpty());
// Re-add foo.com and bar.com.
prefs->Set(site_isolation::prefs::kUserTriggeredIsolatedOrigins, list);
EXPECT_FALSE(
prefs->GetList(site_isolation::prefs::kUserTriggeredIsolatedOrigins)
->GetList()
.empty());
prefs->Set(site_isolation::prefs::kWebTriggeredIsolatedOrigins, dict);
EXPECT_FALSE(
prefs->GetDictionary(site_isolation::prefs::kWebTriggeredIsolatedOrigins)
->DictEmpty());
// Clear the isolated origins data type.
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_ISOLATED_ORIGINS, false);
EXPECT_TRUE(
prefs->GetList(site_isolation::prefs::kUserTriggeredIsolatedOrigins)
->GetList()
.empty());
EXPECT_TRUE(
prefs->GetDictionary(site_isolation::prefs::kWebTriggeredIsolatedOrigins)
->DictEmpty());
// Re-add foo.com and bar.com.
prefs->Set(site_isolation::prefs::kUserTriggeredIsolatedOrigins, list);
EXPECT_FALSE(
prefs->GetList(site_isolation::prefs::kUserTriggeredIsolatedOrigins)
->GetList()
.empty());
prefs->Set(site_isolation::prefs::kWebTriggeredIsolatedOrigins, dict);
EXPECT_FALSE(
prefs->GetDictionary(site_isolation::prefs::kWebTriggeredIsolatedOrigins)
->DictEmpty());
// Clear both history and site data, and ensure the stored isolated origins
// are cleared.
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(),
constants::DATA_TYPE_HISTORY | constants::DATA_TYPE_SITE_DATA, false);
EXPECT_TRUE(
prefs->GetList(site_isolation::prefs::kUserTriggeredIsolatedOrigins)
->GetList()
.empty());
EXPECT_TRUE(
prefs->GetDictionary(site_isolation::prefs::kWebTriggeredIsolatedOrigins)
->DictEmpty());
}
// Test that clearing history deletes favicons not associated with bookmarks.
TEST_F(ChromeBrowsingDataRemoverDelegateTest, RemoveFaviconsForever) {
GURL page_url("http://a");
RemoveFaviconTester favicon_tester;
ASSERT_TRUE(favicon_tester.Init(GetProfile()));
favicon_tester.VisitAndAddFavicon(page_url);
ASSERT_TRUE(favicon_tester.HasFaviconForPageURL(page_url));
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, false);
EXPECT_EQ(constants::DATA_TYPE_HISTORY, GetRemovalMask());
EXPECT_FALSE(favicon_tester.HasFaviconForPageURL(page_url));
}
// Test that a bookmark's favicon is expired and not deleted when clearing
// history. Expiring the favicon causes the bookmark's favicon to be updated
// when the user next visits the bookmarked page. Expiring the bookmark's
// favicon is useful when the bookmark's favicon becomes incorrect (See
// crbug.com/474421 for a sample bug which causes this).
TEST_F(ChromeBrowsingDataRemoverDelegateTest, ExpireBookmarkFavicons) {
GURL bookmarked_page("http://a");
TestingProfile* profile = GetProfile();
bookmarks::BookmarkModel* bookmark_model =
BookmarkModelFactory::GetForBrowserContext(profile);
bookmarks::test::WaitForBookmarkModelToLoad(bookmark_model);
bookmark_model->AddURL(bookmark_model->bookmark_bar_node(), 0, u"a",
bookmarked_page);
RemoveFaviconTester favicon_tester;
ASSERT_TRUE(favicon_tester.Init(GetProfile()));
favicon_tester.VisitAndAddFavicon(bookmarked_page);
ASSERT_TRUE(favicon_tester.HasFaviconForPageURL(bookmarked_page));
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, false);
EXPECT_EQ(constants::DATA_TYPE_HISTORY, GetRemovalMask());
EXPECT_TRUE(favicon_tester.HasExpiredFaviconForPageURL(bookmarked_page));
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest, DeleteBookmarks) {
GURL bookmarked_page("http://a");
TestingProfile* profile = GetProfile();
bookmarks::BookmarkModel* bookmark_model =
BookmarkModelFactory::GetForBrowserContext(profile);
bookmarks::test::WaitForBookmarkModelToLoad(bookmark_model);
bookmark_model->AddURL(bookmark_model->bookmark_bar_node(), 0, u"a",
bookmarked_page);
EXPECT_EQ(1u, bookmark_model->bookmark_bar_node()->children().size());
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_BOOKMARKS, false);
EXPECT_EQ(0u, bookmark_model->bookmark_bar_node()->children().size());
}
// Verifies deleting does not crash if BookmarkModel has not been loaded.
// Regression test for: https://crbug.com/1207632.
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
DeleteBookmarksDoesNothingWhenModelNotLoaded) {
TestingProfile* profile = GetProfile();
bookmarks::BookmarkModel* bookmark_model =
BookmarkModelFactory::GetForBrowserContext(profile);
// For this test to exercise the code path that lead to the crash the
// model must not be loaded yet.
EXPECT_FALSE(bookmark_model->loaded());
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_BOOKMARKS, false);
// No crash means test passes.
}
// TODO(crbug.com/589586): Disabled, since history is not yet marked as
// a filterable datatype.
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
DISABLED_TimeBasedHistoryRemoval) {
RemoveHistoryTester tester;
ASSERT_TRUE(tester.Init(GetProfile()));
base::Time two_hours_ago = base::Time::Now() - base::TimeDelta::FromHours(2);
const GURL kOrigin1("http://host1.com:1");
const GURL kOrigin2("http://host2.com:1");
tester.AddHistory(kOrigin1, base::Time::Now());
tester.AddHistory(kOrigin2, two_hours_ago);
ASSERT_TRUE(tester.HistoryContainsURL(kOrigin1));
ASSERT_TRUE(tester.HistoryContainsURL(kOrigin2));
std::unique_ptr<BrowsingDataFilterBuilder> builder(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kPreserve));
BlockUntilOriginDataRemoved(AnHourAgo(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, std::move(builder));
EXPECT_EQ(constants::DATA_TYPE_HISTORY, GetRemovalMask());
EXPECT_EQ(content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
EXPECT_FALSE(tester.HistoryContainsURL(kOrigin1));
EXPECT_TRUE(tester.HistoryContainsURL(kOrigin2));
}
// Verify that clearing autofill form data works.
TEST_F(ChromeBrowsingDataRemoverDelegateTest, AutofillRemovalLastHour) {
GetProfile()->CreateWebDataService();
RemoveAutofillTester tester(GetProfile());
// Initialize sync service so that PersonalDatabaseHelper::server_database_
// gets initialized:
SyncServiceFactory::GetForProfile(GetProfile());
ASSERT_FALSE(tester.HasProfile());
tester.AddProfilesAndCards();
ASSERT_TRUE(tester.HasProfile());
BlockUntilBrowsingDataRemoved(AnHourAgo(), base::Time::Max(),
constants::DATA_TYPE_FORM_DATA, false);
EXPECT_EQ(constants::DATA_TYPE_FORM_DATA, GetRemovalMask());
EXPECT_EQ(content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
ASSERT_FALSE(tester.HasProfile());
}
// Verify the clearing of autofill profiles added / modified more than 30 days
// ago.
TEST_F(ChromeBrowsingDataRemoverDelegateTest, AutofillRemovalOlderThan30Days) {
GetProfile()->CreateWebDataService();
RemoveAutofillTester tester(GetProfile());
// Initialize sync service so that PersonalDatabaseHelper::server_database_
// gets initialized:
SyncServiceFactory::GetForProfile(GetProfile());
const base::Time k32DaysOld = base::Time::Now();
task_environment()->AdvanceClock(base::TimeDelta::FromDays(1));
const base::Time k31DaysOld = base::Time::Now();
task_environment()->AdvanceClock(base::TimeDelta::FromDays(1));
const base::Time k30DaysOld = base::Time::Now();
task_environment()->AdvanceClock(base::TimeDelta::FromDays(30));
// Add profiles and cards with modification date as 31 days old from now.
autofill::TestAutofillClock test_clock;
test_clock.SetNow(k31DaysOld);
ASSERT_FALSE(tester.HasProfile());
tester.AddProfilesAndCards();
ASSERT_TRUE(tester.HasProfile());
BlockUntilBrowsingDataRemoved(base::Time(), k32DaysOld,
constants::DATA_TYPE_FORM_DATA, false);
ASSERT_TRUE(tester.HasProfile());
BlockUntilBrowsingDataRemoved(k30DaysOld, base::Time::Max(),
constants::DATA_TYPE_FORM_DATA, false);
ASSERT_TRUE(tester.HasProfile());
BlockUntilBrowsingDataRemoved(base::Time(), k30DaysOld,
constants::DATA_TYPE_FORM_DATA, false);
EXPECT_EQ(constants::DATA_TYPE_FORM_DATA, GetRemovalMask());
EXPECT_EQ(content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
ASSERT_FALSE(tester.HasProfile());
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest, AutofillRemovalEverything) {
GetProfile()->CreateWebDataService();
RemoveAutofillTester tester(GetProfile());
// Initialize sync service so that PersonalDatabaseHelper::server_database_
// gets initialized:
SyncServiceFactory::GetForProfile(GetProfile());
ASSERT_FALSE(tester.HasProfile());
tester.AddProfilesAndCards();
ASSERT_TRUE(tester.HasProfile());
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_FORM_DATA, false);
EXPECT_EQ(constants::DATA_TYPE_FORM_DATA, GetRemovalMask());
EXPECT_EQ(content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
ASSERT_FALSE(tester.HasProfile());
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
StrikeDatabaseEmptyOnAutofillRemoveEverything) {
GetProfile()->CreateWebDataService();
RemoveAutofillTester tester(GetProfile());
// Initialize sync service so that PersonalDatabaseHelper::server_database_
// gets initialized:
SyncServiceFactory::GetForProfile(GetProfile());
ASSERT_FALSE(tester.HasProfile());
tester.AddProfilesAndCards();
ASSERT_TRUE(tester.HasProfile());
autofill::StrikeDatabaseTester strike_database_tester(GetProfile());
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_FORM_DATA, false);
// StrikeDatabase should be empty when DATA_TYPE_FORM_DATA browsing data
// gets deleted.
ASSERT_TRUE(strike_database_tester.IsEmpty());
EXPECT_EQ(constants::DATA_TYPE_FORM_DATA, GetRemovalMask());
EXPECT_EQ(content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
ASSERT_FALSE(tester.HasProfile());
}
// Verify that clearing autofill form data works.
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
AutofillOriginsRemovedWithHistory) {
GetProfile()->CreateWebDataService();
RemoveAutofillTester tester(GetProfile());
// Initialize sync service so that PersonalDatabaseHelper::server_database_
// gets initialized:
SyncServiceFactory::GetForProfile(GetProfile());
tester.AddProfilesAndCards();
EXPECT_FALSE(tester.HasOrigin(std::string()));
EXPECT_TRUE(tester.HasOrigin(kWebOrigin));
EXPECT_TRUE(tester.HasOrigin(autofill::kSettingsOrigin));
BlockUntilBrowsingDataRemoved(AnHourAgo(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, false);
EXPECT_EQ(constants::DATA_TYPE_HISTORY, GetRemovalMask());
EXPECT_EQ(content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
EXPECT_TRUE(tester.HasOrigin(std::string()));
EXPECT_FALSE(tester.HasOrigin(kWebOrigin));
EXPECT_TRUE(tester.HasOrigin(autofill::kSettingsOrigin));
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest, ZeroSuggestCacheClear) {
PrefService* prefs = GetProfile()->GetPrefs();
prefs->SetString(omnibox::kZeroSuggestCachedResults,
"[\"\", [\"foo\", \"bar\"]]");
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
content::BrowsingDataRemover::DATA_TYPE_COOKIES,
false);
// Expect the prefs to be cleared when cookies are removed.
EXPECT_TRUE(prefs->GetString(omnibox::kZeroSuggestCachedResults).empty());
EXPECT_EQ(content::BrowsingDataRemover::DATA_TYPE_COOKIES, GetRemovalMask());
EXPECT_EQ(content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
}
#if BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
ContentProtectionPlatformKeysRemoval) {
ash::MockUserManager* mock_user_manager =
new testing::NiceMock<ash::MockUserManager>();
mock_user_manager->SetActiveUser(
AccountId::FromUserEmail("test@example.com"));
user_manager::ScopedUserManager user_manager_enabler(
base::WrapUnique(mock_user_manager));
chromeos::AttestationClient::InitializeFake();
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(),
content::BrowsingDataRemover::DATA_TYPE_MEDIA_LICENSES, false);
const std::vector<::attestation::DeleteKeysRequest>& history =
chromeos::AttestationClient::Get()
->GetTestInterface()
->delete_keys_history();
EXPECT_EQ(history.size(), 1);
chromeos::AttestationClient::Shutdown();
}
#endif
TEST_F(ChromeBrowsingDataRemoverDelegateTest, DomainReliability_Null) {
ClearDomainReliabilityTester tester(GetProfile());
EXPECT_EQ(0u, tester.clear_count());
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest, DomainReliability_Beacons) {
ClearDomainReliabilityTester tester(GetProfile());
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, false);
EXPECT_EQ(1u, tester.clear_count());
EXPECT_EQ(
network::mojom::NetworkContext::DomainReliabilityClearMode::CLEAR_BEACONS,
tester.last_clear_mode());
EXPECT_TRUE(tester.last_filter().is_null());
}
// TODO(crbug.com/589586): Disabled, since history is not yet marked as
// a filterable datatype.
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
DISABLED_DomainReliability_Beacons_WithFilter) {
ClearDomainReliabilityTester tester(GetProfile());
std::unique_ptr<BrowsingDataFilterBuilder> builder(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kDelete));
builder->AddRegisterableDomain(kTestRegisterableDomain1);
BlockUntilOriginDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, builder->Copy());
EXPECT_EQ(1u, tester.clear_count());
EXPECT_EQ(
network::mojom::NetworkContext::DomainReliabilityClearMode::CLEAR_BEACONS,
tester.last_clear_mode());
EXPECT_TRUE(
ProbablySameFilters(builder->BuildUrlFilter(), tester.last_filter()));
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest, DomainReliability_Contexts) {
ClearDomainReliabilityTester tester(GetProfile());
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
content::BrowsingDataRemover::DATA_TYPE_COOKIES,
false);
EXPECT_EQ(1u, tester.clear_count());
EXPECT_EQ(network::mojom::NetworkContext::DomainReliabilityClearMode::
CLEAR_CONTEXTS,
tester.last_clear_mode());
EXPECT_TRUE(tester.last_filter().is_null());
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
DomainReliability_Contexts_WithFilter) {
ClearDomainReliabilityTester tester(GetProfile());
std::unique_ptr<BrowsingDataFilterBuilder> builder(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kDelete));
builder->AddRegisterableDomain(kTestRegisterableDomain1);
BlockUntilOriginDataRemoved(base::Time(), base::Time::Max(),
content::BrowsingDataRemover::DATA_TYPE_COOKIES,
builder->Copy());
EXPECT_EQ(1u, tester.clear_count());
EXPECT_EQ(network::mojom::NetworkContext::DomainReliabilityClearMode::
CLEAR_CONTEXTS,
tester.last_clear_mode());
EXPECT_TRUE(
ProbablySameFilters(builder->BuildUrlFilter(), tester.last_filter()));
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest, DomainReliability_ContextsWin) {
ClearDomainReliabilityTester tester(GetProfile());
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(),
constants::DATA_TYPE_HISTORY |
content::BrowsingDataRemover::DATA_TYPE_COOKIES,
false);
EXPECT_EQ(1u, tester.clear_count());
EXPECT_EQ(network::mojom::NetworkContext::DomainReliabilityClearMode::
CLEAR_CONTEXTS,
tester.last_clear_mode());
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
DomainReliability_ProtectedOrigins) {
ClearDomainReliabilityTester tester(GetProfile());
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
content::BrowsingDataRemover::DATA_TYPE_COOKIES,
true);
EXPECT_EQ(1u, tester.clear_count());
EXPECT_EQ(network::mojom::NetworkContext::DomainReliabilityClearMode::
CLEAR_CONTEXTS,
tester.last_clear_mode());
}
// TODO(juliatuttle): This isn't actually testing the no-monitor case, since
// BrowsingDataRemoverTest now creates one unconditionally, since it's needed
// for some unrelated test cases. This should be fixed so it tests the no-
// monitor case again.
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
DISABLED_DomainReliability_NoMonitor) {
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(),
constants::DATA_TYPE_HISTORY |
content::BrowsingDataRemover::DATA_TYPE_COOKIES,
false);
}
// Tests that the deletion of downloads completes successfully and that
// ChromeDownloadManagerDelegate is correctly created and shut down.
TEST_F(ChromeBrowsingDataRemoverDelegateTest, RemoveDownloads) {
RemoveDownloadsTester tester(GetProfile());
EXPECT_CALL(*tester.download_manager(), RemoveDownloadsByURLAndTime(_, _, _));
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(),
content::BrowsingDataRemover::DATA_TYPE_DOWNLOADS, false);
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest, RemovePasswordStatistics) {
RemovePasswordsTester tester(GetProfile());
base::RepeatingCallback<bool(const GURL&)> empty_filter;
EXPECT_CALL(*tester.profile_store(), RemoveStatisticsByOriginAndTimeImpl(
ProbablySameFilter(empty_filter),
base::Time(), base::Time::Max()));
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, false);
}
// TODO(crbug.com/589586): Disabled, since history is not yet marked as
// a filterable datatype.
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
DISABLED_RemovePasswordStatisticsByOrigin) {
RemovePasswordsTester tester(GetProfile());
std::unique_ptr<BrowsingDataFilterBuilder> builder(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kDelete));
builder->AddRegisterableDomain(kTestRegisterableDomain1);
base::RepeatingCallback<bool(const GURL&)> filter = builder->BuildUrlFilter();
EXPECT_CALL(*tester.profile_store(),
RemoveStatisticsByOriginAndTimeImpl(
ProbablySameFilter(filter), base::Time(), base::Time::Max()));
BlockUntilOriginDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, std::move(builder));
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest, RemovePasswordsByTimeOnly) {
RemovePasswordsTester tester(GetProfile());
base::RepeatingCallback<bool(const GURL&)> filter =
BrowsingDataFilterBuilder::BuildNoopFilter();
EXPECT_CALL(*tester.profile_store(),
RemoveLoginsByURLAndTimeImpl(ProbablySameFilter(filter), _, _))
.WillOnce(Return(password_manager::PasswordStoreChangeList()));
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_PASSWORDS, false);
}
// Disabled, since passwords are not yet marked as a filterable datatype.
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
DISABLED_RemovePasswordsByOrigin) {
RemovePasswordsTester tester(GetProfile());
std::unique_ptr<BrowsingDataFilterBuilder> builder(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kDelete));
builder->AddRegisterableDomain(kTestRegisterableDomain1);
base::RepeatingCallback<bool(const GURL&)> filter = builder->BuildUrlFilter();
EXPECT_CALL(*tester.profile_store(),
RemoveLoginsByURLAndTimeImpl(ProbablySameFilter(filter), _, _))
.WillOnce(Return(password_manager::PasswordStoreChangeList()));
BlockUntilOriginDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_PASSWORDS,
std::move(builder));
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest, DisableAutoSignIn) {
RemovePasswordsTester tester(GetProfile());
base::RepeatingCallback<bool(const GURL&)> empty_filter =
BrowsingDataFilterBuilder::BuildNoopFilter();
EXPECT_CALL(*tester.profile_store(),
DisableAutoSignInForOriginsImpl(ProbablySameFilter(empty_filter)))
.WillOnce(Return(password_manager::PasswordStoreChangeList()));
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
content::BrowsingDataRemover::DATA_TYPE_COOKIES,
false);
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
DisableAutoSignInAfterRemovingPasswords) {
RemovePasswordsTester tester(GetProfile());
base::RepeatingCallback<bool(const GURL&)> empty_filter =
BrowsingDataFilterBuilder::BuildNoopFilter();
EXPECT_CALL(*tester.profile_store(), RemoveLoginsByURLAndTimeImpl(_, _, _))
.WillOnce(Return(password_manager::PasswordStoreChangeList()));
EXPECT_CALL(*tester.profile_store(),
DisableAutoSignInForOriginsImpl(ProbablySameFilter(empty_filter)))
.WillOnce(Return(password_manager::PasswordStoreChangeList()));
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(),
content::BrowsingDataRemover::DATA_TYPE_COOKIES |
constants::DATA_TYPE_PASSWORDS,
false);
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
RemoveContentSettingsWithPreserveFilter) {
// This test relies on async loading to complete. RunUntilIdle() should be
// removed and an explicit wait should be added.
task_environment()->RunUntilIdle();
// Add our settings.
const GURL kOrigin1("http://host1.com:1");
const GURL kOrigin2("http://host2.com:1");
const GURL kOrigin3("http://host3.com:1");
const GURL kOrigin4("https://host3.com:1");
HostContentSettingsMap* host_content_settings_map =
HostContentSettingsMapFactory::GetForProfile(GetProfile());
host_content_settings_map->SetWebsiteSettingDefaultScope(
kOrigin1, GURL(), ContentSettingsType::SITE_ENGAGEMENT,
std::make_unique<base::DictionaryValue>());
host_content_settings_map->SetWebsiteSettingDefaultScope(
kOrigin2, GURL(), ContentSettingsType::SITE_ENGAGEMENT,
std::make_unique<base::DictionaryValue>());
host_content_settings_map->SetWebsiteSettingDefaultScope(
kOrigin3, GURL(), ContentSettingsType::SITE_ENGAGEMENT,
std::make_unique<base::DictionaryValue>());
host_content_settings_map->SetWebsiteSettingDefaultScope(
kOrigin4, GURL(), ContentSettingsType::SITE_ENGAGEMENT,
std::make_unique<base::DictionaryValue>());
// Clear all except for origin1 and origin3.
std::unique_ptr<BrowsingDataFilterBuilder> filter(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kPreserve));
filter->AddRegisterableDomain(kTestRegisterableDomain1);
filter->AddRegisterableDomain(kTestRegisterableDomain3);
BlockUntilOriginDataRemoved(AnHourAgo(), base::Time::Max(),
constants::DATA_TYPE_SITE_USAGE_DATA,
std::move(filter));
EXPECT_EQ(constants::DATA_TYPE_SITE_USAGE_DATA, GetRemovalMask());
EXPECT_EQ(content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Verify we only have true, and they're origin1, origin3, and origin4.
ContentSettingsForOneType host_settings;
host_content_settings_map->GetSettingsForOneType(
ContentSettingsType::SITE_ENGAGEMENT, &host_settings);
EXPECT_EQ(3u, host_settings.size());
EXPECT_EQ(ContentSettingsPattern::FromURLNoWildcard(kOrigin1),
host_settings[0].primary_pattern)
<< host_settings[0].primary_pattern.ToString();
EXPECT_EQ(ContentSettingsPattern::FromURLNoWildcard(kOrigin4),
host_settings[1].primary_pattern)
<< host_settings[1].primary_pattern.ToString();
EXPECT_EQ(ContentSettingsPattern::FromURLNoWildcard(kOrigin3),
host_settings[2].primary_pattern)
<< host_settings[2].primary_pattern.ToString();
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest, RemoveContentSettings) {
// This test relies on async loading to complete. RunUntilIdle() should be
// removed and an explicit wait should be added.
task_environment()->RunUntilIdle();
const GURL kOrigin1("http://host1.com:1");
const GURL kOrigin2("http://host2.com:1");
const GURL kOrigin3("http://host3.com:1");
const bool has_dse_origin = !dse_origin().is_empty();
auto* map = HostContentSettingsMapFactory::GetForProfile(GetProfile());
map->SetContentSettingDefaultScope(kOrigin1, kOrigin1,
ContentSettingsType::GEOLOCATION,
CONTENT_SETTING_ALLOW);
if (has_dse_origin) {
map->SetContentSettingDefaultScope(dse_origin(), dse_origin(),
ContentSettingsType::GEOLOCATION,
CONTENT_SETTING_BLOCK);
}
map->SetContentSettingDefaultScope(kOrigin2, kOrigin2,
ContentSettingsType::NOTIFICATIONS,
CONTENT_SETTING_ALLOW);
map->SetContentSettingDefaultScope(
kOrigin3, GURL(), ContentSettingsType::COOKIES, CONTENT_SETTING_BLOCK);
ContentSettingsPattern pattern =
ContentSettingsPattern::FromString("[*.]example.com");
map->SetContentSettingCustomScope(pattern, ContentSettingsPattern::Wildcard(),
ContentSettingsType::COOKIES,
CONTENT_SETTING_BLOCK);
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_CONTENT_SETTINGS, false);
ContentSettingsForOneType host_settings;
map->GetSettingsForOneType(ContentSettingsType::GEOLOCATION, &host_settings);
if (has_dse_origin) {
ASSERT_EQ(2u, host_settings.size());
EXPECT_EQ(ContentSettingsPattern::FromURLNoWildcard(dse_origin()),
host_settings[0].primary_pattern)
<< host_settings[0].primary_pattern.ToString();
EXPECT_EQ(ContentSettingsPattern::Wildcard(),
host_settings[0].secondary_pattern)
<< host_settings[0].secondary_pattern.ToString();
EXPECT_EQ(CONTENT_SETTING_ALLOW, host_settings[0].GetContentSetting());
EXPECT_EQ(ContentSettingsPattern::Wildcard(),
host_settings[1].primary_pattern)
<< host_settings[1].primary_pattern.ToString();
EXPECT_EQ(CONTENT_SETTING_ASK, host_settings[1].GetContentSetting());
} else {
ASSERT_EQ(1u, host_settings.size());
EXPECT_EQ(ContentSettingsPattern::Wildcard(),
host_settings[0].primary_pattern)
<< host_settings[0].primary_pattern.ToString();
EXPECT_EQ(CONTENT_SETTING_ASK, host_settings[0].GetContentSetting());
}
map->GetSettingsForOneType(ContentSettingsType::NOTIFICATIONS,
&host_settings);
if (has_dse_origin) {
ASSERT_EQ(2u, host_settings.size());
EXPECT_EQ(ContentSettingsPattern::FromURLNoWildcard(dse_origin()),
host_settings[0].primary_pattern)
<< host_settings[0].primary_pattern.ToString();
EXPECT_EQ(CONTENT_SETTING_ALLOW, host_settings[0].GetContentSetting());
EXPECT_EQ(ContentSettingsPattern::Wildcard(),
host_settings[1].primary_pattern)
<< host_settings[1].primary_pattern.ToString();
EXPECT_EQ(CONTENT_SETTING_ASK, host_settings[1].GetContentSetting());
} else {
ASSERT_EQ(1u, host_settings.size());
EXPECT_EQ(ContentSettingsPattern::Wildcard(),
host_settings[0].primary_pattern)
<< host_settings[0].primary_pattern.ToString();
EXPECT_EQ(CONTENT_SETTING_ASK, host_settings[0].GetContentSetting());
}
map->GetSettingsForOneType(ContentSettingsType::COOKIES, &host_settings);
ASSERT_EQ(1u, host_settings.size());
EXPECT_EQ(ContentSettingsPattern::Wildcard(),
host_settings[0].primary_pattern)
<< host_settings[0].primary_pattern.ToString();
EXPECT_EQ(CONTENT_SETTING_ALLOW, host_settings[0].GetContentSetting());
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest, RemoveProtocolHandler) {
// This test relies on async loading to complete. RunUntilIdle() should be
// removed and an explicit wait should be added.
task_environment()->RunUntilIdle();
auto* registry =
ProtocolHandlerRegistryFactory::GetForBrowserContext(GetProfile());
const GURL kOrigin("https://host3.com:1");
base::Time one_hour_ago = base::Time::Now() - base::TimeDelta::FromHours(1);
base::Time yesterday = base::Time::Now() - base::TimeDelta::FromDays(1);
registry->OnAcceptRegisterProtocolHandler(
ProtocolHandler::CreateProtocolHandler("news", kOrigin));
registry->OnAcceptRegisterProtocolHandler(
ProtocolHandler("mailto", kOrigin, yesterday,
blink::ProtocolHandlerSecurityLevel::kStrict));
EXPECT_TRUE(registry->IsHandledProtocol("news"));
EXPECT_TRUE(registry->IsHandledProtocol("mailto"));
EXPECT_EQ(
2U,
registry->GetUserDefinedHandlers(base::Time(), base::Time::Max()).size());
// Delete last hour.
BlockUntilBrowsingDataRemoved(one_hour_ago, base::Time::Max(),
constants::DATA_TYPE_CONTENT_SETTINGS, false);
EXPECT_FALSE(registry->IsHandledProtocol("news"));
EXPECT_TRUE(registry->IsHandledProtocol("mailto"));
EXPECT_EQ(
1U,
registry->GetUserDefinedHandlers(base::Time(), base::Time::Max()).size());
// Delete everything.
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_CONTENT_SETTINGS, false);
EXPECT_FALSE(registry->IsHandledProtocol("news"));
EXPECT_FALSE(registry->IsHandledProtocol("mailto"));
EXPECT_EQ(
0U,
registry->GetUserDefinedHandlers(base::Time(), base::Time::Max()).size());
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest, RemoveSelectedClientHints) {
// This test relies on async loading to complete. RunUntilIdle() should be
// removed and an explicit wait should be added.
task_environment()->RunUntilIdle();
// Add our settings.
HostContentSettingsMap* host_content_settings_map =
HostContentSettingsMapFactory::GetForProfile(GetProfile());
std::unique_ptr<base::ListValue> expiration_times_list =
std::make_unique<base::ListValue>();
expiration_times_list->AppendInteger(0);
expiration_times_list->AppendInteger(2);
double expiration_time =
(base::Time::Now() + base::TimeDelta::FromHours(24)).ToDoubleT();
auto expiration_times_dictionary = std::make_unique<base::DictionaryValue>();
expiration_times_dictionary->SetList("client_hints",
std::move(expiration_times_list));
expiration_times_dictionary->SetDouble("expiration_time", expiration_time);
const GURL kOrigin1("http://host1.com:1");
const GURL kOrigin2("http://host2.com:1");
const GURL kOrigin3("http://host3.com:1");
host_content_settings_map->SetWebsiteSettingDefaultScope(
kOrigin1, GURL(), ContentSettingsType::CLIENT_HINTS,
expiration_times_dictionary->CreateDeepCopy());
host_content_settings_map->SetWebsiteSettingDefaultScope(
kOrigin2, GURL(), ContentSettingsType::CLIENT_HINTS,
expiration_times_dictionary->CreateDeepCopy());
host_content_settings_map->SetWebsiteSettingDefaultScope(
kOrigin3, GURL(), ContentSettingsType::CLIENT_HINTS,
expiration_times_dictionary->CreateDeepCopy());
// Clear all except for origin1 and origin3.
std::unique_ptr<BrowsingDataFilterBuilder> filter(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kPreserve));
filter->AddRegisterableDomain(kTestRegisterableDomain1);
filter->AddRegisterableDomain(kTestRegisterableDomain3);
BlockUntilOriginDataRemoved(AnHourAgo(), base::Time::Max(),
content::BrowsingDataRemover::DATA_TYPE_COOKIES,
std::move(filter));
ContentSettingsForOneType host_settings;
host_content_settings_map->GetSettingsForOneType(
ContentSettingsType::CLIENT_HINTS, &host_settings);
ASSERT_EQ(2u, host_settings.size());
EXPECT_EQ(ContentSettingsPattern::FromURLNoWildcard(kOrigin1),
host_settings[0].primary_pattern)
<< host_settings[0].primary_pattern.ToString();
EXPECT_EQ(ContentSettingsPattern::FromURLNoWildcard(kOrigin3),
host_settings[1].primary_pattern)
<< host_settings[1].primary_pattern.ToString();
for (size_t i = 0; i < host_settings.size(); ++i) {
EXPECT_EQ(ContentSettingsPattern::Wildcard(),
host_settings.at(i).secondary_pattern);
EXPECT_EQ(*expiration_times_dictionary, host_settings.at(i).setting_value);
}
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest, RemoveAllClientHints) {
// Add our settings.
HostContentSettingsMap* host_content_settings_map =
HostContentSettingsMapFactory::GetForProfile(GetProfile());
std::unique_ptr<base::ListValue> expiration_times_list =
std::make_unique<base::ListValue>();
expiration_times_list->AppendInteger(0);
expiration_times_list->AppendInteger(2);
double expiration_time =
(base::Time::Now() + base::TimeDelta::FromHours(24)).ToDoubleT();
auto expiration_times_dictionary = std::make_unique<base::DictionaryValue>();
expiration_times_dictionary->SetList("client_hints",
std::move(expiration_times_list));
expiration_times_dictionary->SetDouble("expiration_time", expiration_time);
host_content_settings_map->SetWebsiteSettingDefaultScope(
GURL("http://host1.com:1"), GURL(), ContentSettingsType::CLIENT_HINTS,
expiration_times_dictionary->CreateDeepCopy());
host_content_settings_map->SetWebsiteSettingDefaultScope(
GURL("http://host2.com:1"), GURL(), ContentSettingsType::CLIENT_HINTS,
expiration_times_dictionary->CreateDeepCopy());
host_content_settings_map->SetWebsiteSettingDefaultScope(
GURL("http://host3.com:1"), GURL(), ContentSettingsType::CLIENT_HINTS,
expiration_times_dictionary->CreateDeepCopy());
// Clear all.
BlockUntilBrowsingDataRemoved(AnHourAgo(), base::Time::Max(),
content::BrowsingDataRemover::DATA_TYPE_COOKIES,
false);
ContentSettingsForOneType host_settings;
host_content_settings_map->GetSettingsForOneType(
ContentSettingsType::CLIENT_HINTS, &host_settings);
ASSERT_EQ(0u, host_settings.size());
}
#if !defined(OS_ANDROID)
TEST_F(ChromeBrowsingDataRemoverDelegateTest, RemoveZoomLevel) {
content::HostZoomMap* zoom_map =
content::HostZoomMap::GetDefaultForBrowserContext(GetProfile());
EXPECT_EQ(0u, zoom_map->GetAllZoomLevels().size());
base::SimpleTestClock test_clock;
zoom_map->SetClockForTesting(&test_clock);
base::Time now = base::Time::Now();
zoom_map->InitializeZoomLevelForHost(kTestRegisterableDomain1, 1.5,
now - base::TimeDelta::FromHours(5));
test_clock.SetNow(now - base::TimeDelta::FromHours(2));
zoom_map->SetZoomLevelForHost(kTestRegisterableDomain3, 2.0);
EXPECT_EQ(2u, zoom_map->GetAllZoomLevels().size());
// Remove everything created during the last hour.
BlockUntilBrowsingDataRemoved(now - base::TimeDelta::FromHours(1),
base::Time::Max(),
constants::DATA_TYPE_CONTENT_SETTINGS, false);
// Nothing should be deleted as the zoomlevels were created earlier.
EXPECT_EQ(2u, zoom_map->GetAllZoomLevels().size());
test_clock.SetNow(now);
zoom_map->SetZoomLevelForHost(kTestRegisterableDomain3, 2.0);
// Remove everything changed during the last hour (domain3).
BlockUntilBrowsingDataRemoved(now - base::TimeDelta::FromHours(1),
base::Time::Max(),
constants::DATA_TYPE_CONTENT_SETTINGS, false);
// Verify we still have the zoom_level for domain1.
auto levels = zoom_map->GetAllZoomLevels();
EXPECT_EQ(1u, levels.size());
EXPECT_EQ(kTestRegisterableDomain1, levels[0].host);
zoom_map->SetZoomLevelForHostAndScheme("chrome", "print", 4.0);
// Remove everything.
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_CONTENT_SETTINGS, false);
// Host and scheme zoomlevels should not be affected.
levels = zoom_map->GetAllZoomLevels();
EXPECT_EQ(1u, levels.size());
EXPECT_EQ("chrome", levels[0].scheme);
EXPECT_EQ("print", levels[0].host);
}
#endif
TEST_F(ChromeBrowsingDataRemoverDelegateTest, RemoveTranslateBlocklist) {
auto translate_prefs =
ChromeTranslateClient::CreateTranslatePrefs(GetProfile()->GetPrefs());
translate_prefs->AddSiteToNeverPromptList("google.com");
task_environment()->AdvanceClock(base::TimeDelta::FromDays(1));
base::Time t = base::Time::Now();
translate_prefs->AddSiteToNeverPromptList("maps.google.com");
EXPECT_TRUE(translate_prefs->IsSiteOnNeverPromptList("google.com"));
EXPECT_TRUE(translate_prefs->IsSiteOnNeverPromptList("maps.google.com"));
BlockUntilBrowsingDataRemoved(t, base::Time::Max(),
constants::DATA_TYPE_CONTENT_SETTINGS, false);
EXPECT_TRUE(translate_prefs->IsSiteOnNeverPromptList("google.com"));
EXPECT_FALSE(translate_prefs->IsSiteOnNeverPromptList("maps.google.com"));
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_CONTENT_SETTINGS, false);
EXPECT_FALSE(translate_prefs->IsSiteOnNeverPromptList("google.com"));
EXPECT_FALSE(translate_prefs->IsSiteOnNeverPromptList("maps.google.com"));
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest, RemoveDurablePermission) {
// Add our settings.
const GURL kOrigin1("http://host1.com:1");
const GURL kOrigin2("http://host2.com:1");
HostContentSettingsMap* host_content_settings_map =
HostContentSettingsMapFactory::GetForProfile(GetProfile());
DurableStoragePermissionContext durable_permission(GetProfile());
durable_permission.UpdateContentSetting(
kOrigin1, GURL(), CONTENT_SETTING_ALLOW, /*is_one_time=*/false);
durable_permission.UpdateContentSetting(
kOrigin2, GURL(), CONTENT_SETTING_ALLOW, /*is_one_time=*/false);
// Clear all except for origin1 and origin3.
std::unique_ptr<BrowsingDataFilterBuilder> filter(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kPreserve));
filter->AddRegisterableDomain(kTestRegisterableDomain1);
filter->AddRegisterableDomain(kTestRegisterableDomain3);
BlockUntilOriginDataRemoved(AnHourAgo(), base::Time::Max(),
constants::DATA_TYPE_DURABLE_PERMISSION,
std::move(filter));
EXPECT_EQ(constants::DATA_TYPE_DURABLE_PERMISSION, GetRemovalMask());
EXPECT_EQ(content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
GetOriginTypeMask());
// Verify we only have allow for the first origin.
ContentSettingsForOneType host_settings;
host_content_settings_map->GetSettingsForOneType(
ContentSettingsType::DURABLE_STORAGE, &host_settings);
ASSERT_EQ(2u, host_settings.size());
// Only the first should should have a setting.
EXPECT_EQ(ContentSettingsPattern::FromURLNoWildcard(kOrigin1),
host_settings[0].primary_pattern)
<< host_settings[0].primary_pattern.ToString();
EXPECT_EQ(CONTENT_SETTING_ALLOW, host_settings[0].GetContentSetting());
// And our wildcard.
EXPECT_EQ(ContentSettingsPattern::Wildcard(),
host_settings[1].primary_pattern)
<< host_settings[1].primary_pattern.ToString();
EXPECT_EQ(CONTENT_SETTING_ASK, host_settings[1].GetContentSetting());
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
DurablePermissionIsPartOfEmbedderDOMStorage) {
HostContentSettingsMap* host_content_settings_map =
HostContentSettingsMapFactory::GetForProfile(GetProfile());
DurableStoragePermissionContext durable_permission(GetProfile());
durable_permission.UpdateContentSetting(GURL("http://host1.com:1"), GURL(),
CONTENT_SETTING_ALLOW,
/*is_one_time=*/false);
ContentSettingsForOneType host_settings;
host_content_settings_map->GetSettingsForOneType(
ContentSettingsType::DURABLE_STORAGE, &host_settings);
EXPECT_EQ(2u, host_settings.size());
BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(),
content::BrowsingDataRemover::DATA_TYPE_EMBEDDER_DOM_STORAGE, false);
// After the deletion, only the wildcard should remain.
host_content_settings_map->GetSettingsForOneType(
ContentSettingsType::DURABLE_STORAGE, &host_settings);
EXPECT_EQ(1u, host_settings.size());
EXPECT_EQ(ContentSettingsPattern::Wildcard(),
host_settings[0].primary_pattern)
<< host_settings[0].primary_pattern.ToString();
}
// Test that removing passwords clears HTTP auth data.
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
ClearHttpAuthCache_RemovePasswords) {
net::HttpNetworkSession* http_session = network_context()
->url_request_context()
->http_transaction_factory()
->GetSession();
DCHECK(http_session);
net::HttpAuthCache* http_auth_cache = http_session->http_auth_cache();
const GURL kOrigin1("http://host1.com:1");
http_auth_cache->Add(kOrigin1, net::HttpAuth::AUTH_SERVER, kTestRealm,
net::HttpAuth::AUTH_SCHEME_BASIC,
net::NetworkIsolationKey(), "test challenge",
net::AuthCredentials(u"foo", u"bar"), "/");
CHECK(http_auth_cache->Lookup(kOrigin1, net::HttpAuth::AUTH_SERVER,
kTestRealm, net::HttpAuth::AUTH_SCHEME_BASIC,
net::NetworkIsolationKey()));
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_PASSWORDS, false);
EXPECT_EQ(nullptr,
http_auth_cache->Lookup(
kOrigin1, net::HttpAuth::AUTH_SERVER, kTestRealm,
net::HttpAuth::AUTH_SCHEME_BASIC, net::NetworkIsolationKey()));
}
class ChromeBrowsingDataRemoverDelegateBlockPromptsTest
: public ChromeBrowsingDataRemoverDelegateTest {
public:
ChromeBrowsingDataRemoverDelegateBlockPromptsTest() {
// This needs to be done before SetUp, to avoid tsan flakes due to tasks
// running on other threads checking if a feature is enabled.
feature_list_.InitWithFeatures(
{permissions::features::kBlockPromptsIfDismissedOften}, {});
}
};
TEST_F(ChromeBrowsingDataRemoverDelegateBlockPromptsTest,
ClearPermissionPromptCounts) {
RemovePermissionPromptCountsTest tester(GetProfile());
std::unique_ptr<BrowsingDataFilterBuilder> filter_builder_1(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kDelete));
filter_builder_1->AddRegisterableDomain(kTestRegisterableDomain1);
std::unique_ptr<BrowsingDataFilterBuilder> filter_builder_2(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kPreserve));
filter_builder_2->AddRegisterableDomain(kTestRegisterableDomain1);
const GURL kOrigin1("http://host1.com:1");
const GURL kOrigin2("http://host2.com:1");
{
// Test REMOVE_HISTORY.
EXPECT_FALSE(tester.RecordIgnoreAndEmbargo(
kOrigin1, ContentSettingsType::GEOLOCATION));
EXPECT_FALSE(tester.RecordIgnoreAndEmbargo(
kOrigin1, ContentSettingsType::GEOLOCATION));
EXPECT_FALSE(tester.RecordIgnoreAndEmbargo(
kOrigin1, ContentSettingsType::NOTIFICATIONS));
EXPECT_FALSE(tester.RecordDismissAndEmbargo(
kOrigin1, ContentSettingsType::MIDI_SYSEX));
EXPECT_FALSE(tester.RecordIgnoreAndEmbargo(
kOrigin2, ContentSettingsType::DURABLE_STORAGE));
tester.CheckEmbargo(kOrigin2, ContentSettingsType::NOTIFICATIONS,
CONTENT_SETTING_ASK);
EXPECT_FALSE(tester.RecordDismissAndEmbargo(
kOrigin2, ContentSettingsType::NOTIFICATIONS));
EXPECT_FALSE(tester.RecordDismissAndEmbargo(
kOrigin2, ContentSettingsType::NOTIFICATIONS));
EXPECT_TRUE(tester.RecordDismissAndEmbargo(
kOrigin2, ContentSettingsType::NOTIFICATIONS));
tester.CheckEmbargo(kOrigin2, ContentSettingsType::NOTIFICATIONS,
CONTENT_SETTING_BLOCK);
BlockUntilOriginDataRemoved(AnHourAgo(), base::Time::Max(),
constants::DATA_TYPE_SITE_USAGE_DATA,
std::move(filter_builder_1));
// kOrigin1 should be gone, but kOrigin2 remains.
EXPECT_EQ(
0, tester.GetIgnoreCount(kOrigin1, ContentSettingsType::GEOLOCATION));
EXPECT_EQ(
0, tester.GetIgnoreCount(kOrigin1, ContentSettingsType::NOTIFICATIONS));
EXPECT_EQ(
0, tester.GetDismissCount(kOrigin1, ContentSettingsType::MIDI_SYSEX));
EXPECT_EQ(1, tester.GetIgnoreCount(kOrigin2,
ContentSettingsType::DURABLE_STORAGE));
EXPECT_EQ(3, tester.GetDismissCount(kOrigin2,
ContentSettingsType::NOTIFICATIONS));
tester.CheckEmbargo(kOrigin2, ContentSettingsType::NOTIFICATIONS,
CONTENT_SETTING_BLOCK);
BlockUntilBrowsingDataRemoved(AnHourAgo(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, false);
// Everything should be gone.
EXPECT_EQ(
0, tester.GetIgnoreCount(kOrigin1, ContentSettingsType::GEOLOCATION));
EXPECT_EQ(
0, tester.GetIgnoreCount(kOrigin1, ContentSettingsType::NOTIFICATIONS));
EXPECT_EQ(
0, tester.GetDismissCount(kOrigin1, ContentSettingsType::MIDI_SYSEX));
EXPECT_EQ(0, tester.GetIgnoreCount(kOrigin2,
ContentSettingsType::DURABLE_STORAGE));
EXPECT_EQ(0, tester.GetDismissCount(kOrigin2,
ContentSettingsType::NOTIFICATIONS));
tester.CheckEmbargo(kOrigin2, ContentSettingsType::NOTIFICATIONS,
CONTENT_SETTING_ASK);
}
{
// Test REMOVE_SITE_DATA.
EXPECT_FALSE(tester.RecordIgnoreAndEmbargo(
kOrigin1, ContentSettingsType::GEOLOCATION));
EXPECT_FALSE(tester.RecordIgnoreAndEmbargo(
kOrigin1, ContentSettingsType::GEOLOCATION));
EXPECT_FALSE(tester.RecordIgnoreAndEmbargo(
kOrigin1, ContentSettingsType::NOTIFICATIONS));
EXPECT_FALSE(tester.RecordDismissAndEmbargo(
kOrigin1, ContentSettingsType::MIDI_SYSEX));
tester.CheckEmbargo(kOrigin1, ContentSettingsType::MIDI_SYSEX,
CONTENT_SETTING_ASK);
EXPECT_FALSE(tester.RecordIgnoreAndEmbargo(
kOrigin2, ContentSettingsType::DURABLE_STORAGE));
EXPECT_FALSE(tester.RecordDismissAndEmbargo(
kOrigin2, ContentSettingsType::NOTIFICATIONS));
BlockUntilOriginDataRemoved(AnHourAgo(), base::Time::Max(),
constants::DATA_TYPE_SITE_USAGE_DATA,
std::move(filter_builder_2));
// kOrigin2 should be gone, but kOrigin1 remains.
EXPECT_EQ(
2, tester.GetIgnoreCount(kOrigin1, ContentSettingsType::GEOLOCATION));
EXPECT_EQ(
1, tester.GetIgnoreCount(kOrigin1, ContentSettingsType::NOTIFICATIONS));
EXPECT_EQ(
1, tester.GetDismissCount(kOrigin1, ContentSettingsType::MIDI_SYSEX));
EXPECT_EQ(0, tester.GetIgnoreCount(kOrigin2,
ContentSettingsType::DURABLE_STORAGE));
EXPECT_EQ(0, tester.GetDismissCount(kOrigin2,
ContentSettingsType::NOTIFICATIONS));
EXPECT_FALSE(tester.RecordDismissAndEmbargo(
kOrigin1, ContentSettingsType::MIDI_SYSEX));
EXPECT_TRUE(tester.RecordDismissAndEmbargo(
kOrigin1, ContentSettingsType::MIDI_SYSEX));
EXPECT_EQ(
3, tester.GetDismissCount(kOrigin1, ContentSettingsType::MIDI_SYSEX));
tester.CheckEmbargo(kOrigin1, ContentSettingsType::MIDI_SYSEX,
CONTENT_SETTING_BLOCK);
BlockUntilBrowsingDataRemoved(AnHourAgo(), base::Time::Max(),
constants::DATA_TYPE_SITE_USAGE_DATA, false);
// Everything should be gone.
EXPECT_EQ(
0, tester.GetIgnoreCount(kOrigin1, ContentSettingsType::GEOLOCATION));
EXPECT_EQ(
0, tester.GetIgnoreCount(kOrigin1, ContentSettingsType::NOTIFICATIONS));
EXPECT_EQ(
0, tester.GetDismissCount(kOrigin1, ContentSettingsType::MIDI_SYSEX));
EXPECT_EQ(0, tester.GetIgnoreCount(kOrigin2,
ContentSettingsType::DURABLE_STORAGE));
EXPECT_EQ(0, tester.GetDismissCount(kOrigin2,
ContentSettingsType::NOTIFICATIONS));
tester.CheckEmbargo(kOrigin1, ContentSettingsType::MIDI_SYSEX,
CONTENT_SETTING_ASK);
}
}
// Test that the remover clears language model data (normally added by the
// LanguageDetectionDriver).
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
LanguageHistogramClearedOnClearingCompleteHistory) {
language::UrlLanguageHistogram* language_histogram =
UrlLanguageHistogramFactory::GetForBrowserContext(GetProfile());
// Simulate browsing.
for (int i = 0; i < 100; i++) {
language_histogram->OnPageVisited("en");
language_histogram->OnPageVisited("en");
language_histogram->OnPageVisited("en");
language_histogram->OnPageVisited("es");
}
// Clearing a part of the history has no effect.
BlockUntilBrowsingDataRemoved(AnHourAgo(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, false);
EXPECT_THAT(language_histogram->GetTopLanguages(), SizeIs(2));
EXPECT_THAT(language_histogram->GetLanguageFrequency("en"), FloatEq(0.75));
EXPECT_THAT(language_histogram->GetLanguageFrequency("es"), FloatEq(0.25));
// Clearing the full history does the trick.
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, false);
EXPECT_THAT(language_histogram->GetTopLanguages(), SizeIs(0));
EXPECT_THAT(language_histogram->GetLanguageFrequency("en"), FloatEq(0.0));
EXPECT_THAT(language_histogram->GetLanguageFrequency("es"), FloatEq(0.0));
}
#if BUILDFLAG(ENABLE_EXTENSIONS)
TEST_F(ChromeBrowsingDataRemoverDelegateTest, OriginTypeMasks) {
const GURL kOriginProtected("http://protected.com");
const GURL kOriginUnprotected("http://unprotected.com");
const GURL kOriginExtension("chrome-extension://abcdefghijklmnopqrstuvwxyz");
const GURL kOriginDevTools("devtools://abcdefghijklmnopqrstuvw");
auto mock_policy = base::MakeRefCounted<MockExtensionSpecialStoragePolicy>();
// Protect |kOriginProtected|.
mock_policy->AddProtected(kOriginProtected.GetOrigin());
EXPECT_FALSE(Match(kOriginProtected, kUnprotected, mock_policy.get()));
EXPECT_TRUE(Match(kOriginUnprotected, kUnprotected, mock_policy.get()));
EXPECT_FALSE(Match(kOriginExtension, kUnprotected, mock_policy.get()));
EXPECT_FALSE(Match(kOriginDevTools, kUnprotected, mock_policy.get()));
EXPECT_TRUE(Match(kOriginProtected, kProtected, mock_policy.get()));
EXPECT_FALSE(Match(kOriginUnprotected, kProtected, mock_policy.get()));
EXPECT_FALSE(Match(kOriginExtension, kProtected, mock_policy.get()));
EXPECT_FALSE(Match(kOriginDevTools, kProtected, mock_policy.get()));
EXPECT_FALSE(Match(kOriginProtected, kExtension, mock_policy.get()));
EXPECT_FALSE(Match(kOriginUnprotected, kExtension, mock_policy.get()));
EXPECT_TRUE(Match(kOriginExtension, kExtension, mock_policy.get()));
EXPECT_FALSE(Match(kOriginDevTools, kExtension, mock_policy.get()));
EXPECT_TRUE(
Match(kOriginProtected, kUnprotected | kProtected, mock_policy.get()));
EXPECT_TRUE(
Match(kOriginUnprotected, kUnprotected | kProtected, mock_policy.get()));
EXPECT_FALSE(
Match(kOriginExtension, kUnprotected | kProtected, mock_policy.get()));
EXPECT_FALSE(
Match(kOriginDevTools, kUnprotected | kProtected, mock_policy.get()));
EXPECT_FALSE(
Match(kOriginProtected, kUnprotected | kExtension, mock_policy.get()));
EXPECT_TRUE(
Match(kOriginUnprotected, kUnprotected | kExtension, mock_policy.get()));
EXPECT_TRUE(
Match(kOriginExtension, kUnprotected | kExtension, mock_policy.get()));
EXPECT_FALSE(
Match(kOriginDevTools, kUnprotected | kExtension, mock_policy.get()));
EXPECT_TRUE(
Match(kOriginProtected, kProtected | kExtension, mock_policy.get()));
EXPECT_FALSE(
Match(kOriginUnprotected, kProtected | kExtension, mock_policy.get()));
EXPECT_TRUE(
Match(kOriginExtension, kProtected | kExtension, mock_policy.get()));
EXPECT_FALSE(
Match(kOriginDevTools, kProtected | kExtension, mock_policy.get()));
EXPECT_TRUE(Match(kOriginProtected, kUnprotected | kProtected | kExtension,
mock_policy.get()));
EXPECT_TRUE(Match(kOriginUnprotected, kUnprotected | kProtected | kExtension,
mock_policy.get()));
EXPECT_TRUE(Match(kOriginExtension, kUnprotected | kProtected | kExtension,
mock_policy.get()));
EXPECT_FALSE(Match(kOriginDevTools, kUnprotected | kProtected | kExtension,
mock_policy.get()));
}
#endif
// If extensions are disabled, there is no policy.
TEST_F(ChromeBrowsingDataRemoverDelegateTest, OriginTypeMasksNoPolicy) {
const GURL kOriginStandard("http://test.com");
const GURL kOriginExtension("chrome-extension://abcdefghijklmnopqrstuvwxyz");
const GURL kOriginDevTools("devtools://abcdefghijklmnopqrstuvw");
EXPECT_TRUE(Match(kOriginStandard, kUnprotected, nullptr));
EXPECT_FALSE(Match(kOriginExtension, kUnprotected, nullptr));
EXPECT_FALSE(Match(kOriginDevTools, kUnprotected, nullptr));
EXPECT_FALSE(Match(kOriginStandard, kProtected, nullptr));
EXPECT_FALSE(Match(kOriginExtension, kProtected, nullptr));
EXPECT_FALSE(Match(kOriginDevTools, kProtected, nullptr));
#if BUILDFLAG(ENABLE_EXTENSIONS)
EXPECT_FALSE(Match(kOriginStandard, kExtension, nullptr));
EXPECT_TRUE(Match(kOriginExtension, kExtension, nullptr));
EXPECT_FALSE(Match(kOriginDevTools, kExtension, nullptr));
#endif
}
#if BUILDFLAG(ENABLE_REPORTING)
TEST_F(ChromeBrowsingDataRemoverDelegateTest, ReportingCache_NoService) {
ClearReportingCacheTester tester(network_context(), false);
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, true);
// Nothing to check, since there's no mock service; we're just making sure
// nothing crashes without a service.
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest, ReportingCache) {
ClearReportingCacheTester tester(network_context(), true);
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, true);
EXPECT_EQ(0, tester.mock().remove_calls());
EXPECT_EQ(1, tester.mock().remove_all_calls());
EXPECT_EQ(net::ReportingBrowsingDataRemover::DATA_TYPE_REPORTS,
tester.mock().last_data_type_mask());
EXPECT_TRUE(ProbablySameFilters(base::RepeatingCallback<bool(const GURL&)>(),
tester.mock().last_origin_filter()));
}
// TODO(crbug.com/589586): Disabled, since history is not yet marked as
// a filterable datatype.
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
DISABLED_ReportingCache_WithFilter) {
ClearReportingCacheTester tester(network_context(), true);
std::unique_ptr<BrowsingDataFilterBuilder> builder(
BrowsingDataFilterBuilder::Create(
BrowsingDataFilterBuilder::Mode::kDelete));
builder->AddRegisterableDomain(kTestRegisterableDomain1);
BlockUntilOriginDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, builder->Copy());
EXPECT_EQ(1, tester.mock().remove_calls());
EXPECT_EQ(0, tester.mock().remove_all_calls());
EXPECT_EQ(net::ReportingBrowsingDataRemover::DATA_TYPE_REPORTS,
tester.mock().last_data_type_mask());
EXPECT_TRUE(ProbablySameFilters(builder->BuildUrlFilter(),
tester.mock().last_origin_filter()));
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest, NetworkErrorLogging_NoDelegate) {
ClearNetworkErrorLoggingTester tester(network_context(), false);
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, true);
// Nothing to check, since there's no mock service; we're just making sure
// nothing crashes without a service.
}
// This would use an origin filter, but history isn't yet filterable.
TEST_F(ChromeBrowsingDataRemoverDelegateTest, NetworkErrorLogging_History) {
ClearNetworkErrorLoggingTester tester(network_context(), true);
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, true);
EXPECT_EQ(0, tester.mock().remove_calls());
EXPECT_EQ(1, tester.mock().remove_all_calls());
EXPECT_TRUE(ProbablySameFilters(base::RepeatingCallback<bool(const GURL&)>(),
tester.mock().last_origin_filter()));
}
#endif // BUILDFLAG(ENABLE_REPORTING)
// Test that all WebsiteSettings are getting deleted by creating a
// value for each of them and removing data.
TEST_F(ChromeBrowsingDataRemoverDelegateTest, AllTypesAreGettingDeleted) {
TestingProfile* profile = GetProfile();
ASSERT_TRUE(SubresourceFilterProfileContextFactory::GetForProfile(profile));
auto* map = HostContentSettingsMapFactory::GetForProfile(profile);
auto* registry = content_settings::WebsiteSettingsRegistry::GetInstance();
auto* content_setting_registry =
content_settings::ContentSettingsRegistry::GetInstance();
auto* history_service =
HistoryServiceFactory::GetForProfileWithoutCreating(profile);
// Create a safe_browsing::VerdictCacheManager that will handle deletion of
// ContentSettingsType::PASSWORD_PROTECTION entries.
safe_browsing::VerdictCacheManager sb_cache_manager(history_service, map);
GURL url("https://example.com");
// List of types that don't have to be deletable.
static const ContentSettingsType non_deletable_types[] = {
// Doesn't allow any values.
ContentSettingsType::PROTOCOL_HANDLERS,
// Doesn't allow any values.
ContentSettingsType::MIXEDSCRIPT,
// Only policy provider sets exceptions for this type.
ContentSettingsType::AUTO_SELECT_CERTIFICATE,
// TODO(710873): Make sure that these get fixed:
// Not deleted but should be deleted with history?
ContentSettingsType::IMPORTANT_SITE_INFO,
};
// Set a value for every WebsiteSetting.
for (const content_settings::WebsiteSettingsInfo* info : *registry) {
if (base::Contains(non_deletable_types, info->type()))
continue;
base::Value some_value;
auto* content_setting = content_setting_registry->Get(info->type());
if (content_setting) {
// Content Settings only allow integers.
if (content_setting->IsSettingValid(CONTENT_SETTING_ALLOW)) {
some_value = base::Value(CONTENT_SETTING_ALLOW);
} else {
ASSERT_TRUE(content_setting->IsSettingValid(CONTENT_SETTING_ASK));
some_value = base::Value(CONTENT_SETTING_ASK);
}
ASSERT_TRUE(content_setting->IsDefaultSettingValid(CONTENT_SETTING_BLOCK))
<< info->name();
// Set default to BLOCK to be able to differentiate an exception from the
// default.
map->SetDefaultContentSetting(info->type(), CONTENT_SETTING_BLOCK);
} else {
// Other website settings only allow dictionaries.
base::DictionaryValue dict;
dict.SetKey("foo", base::Value(42));
some_value = std::move(dict);
}
// Create an exception.
map->SetWebsiteSettingDefaultScope(
url, url, info->type(),
std::make_unique<base::Value>(some_value.Clone()));
// Check that the exception was created.
std::unique_ptr<base::Value> value =
map->GetWebsiteSetting(url, url, info->type(), nullptr);
EXPECT_TRUE(value) << "Not created: " << info->name();
if (value)
EXPECT_EQ(some_value, *value) << "Not created: " << info->name();
}
// Delete all data types that trigger website setting deletions.
uint64_t mask = constants::DATA_TYPE_HISTORY |
constants::DATA_TYPE_SITE_DATA |
constants::DATA_TYPE_CONTENT_SETTINGS;
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(), mask, false);
// All settings should be deleted now.
for (const content_settings::WebsiteSettingsInfo* info : *registry) {
if (base::Contains(non_deletable_types, info->type()))
continue;
std::unique_ptr<base::Value> value =
map->GetWebsiteSetting(url, url, info->type(), nullptr);
if (value && value->is_int()) {
EXPECT_EQ(CONTENT_SETTING_BLOCK, value->GetInt())
<< "Not deleted: " << info->name() << " value: " << *value;
} else {
EXPECT_FALSE(value) << "Not deleted: " << info->name()
<< " value: " << *value;
}
}
}
#if defined(OS_ANDROID)
TEST_F(ChromeBrowsingDataRemoverDelegateTest, WipeOriginVerifierData) {
int before =
customtabs::OriginVerifier::GetClearBrowsingDataCallCountForTesting();
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, false);
EXPECT_EQ(
before + 1,
customtabs::OriginVerifier::GetClearBrowsingDataCallCountForTesting());
}
#endif // defined(OS_ANDROID)
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
TEST_F(ChromeBrowsingDataRemoverDelegateTest, WipeCrashData) {
#if !BUILDFLAG(IS_CHROMEOS_ASH)
// This test applies only when using a logfile of Crash uploads. Chrome Linux
// will use Crashpad's database instead of the logfile. Chrome Chrome OS
// continues to use the logfile even when Crashpad is enabled.
if (crash_reporter::IsCrashpadEnabled()) {
GTEST_SKIP();
}
#endif
base::ScopedPathOverride override_crash_dumps(chrome::DIR_CRASH_DUMPS);
base::FilePath crash_dir_path;
base::PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dir_path);
base::FilePath upload_log_path =
crash_dir_path.AppendASCII(CrashUploadList::kReporterLogFilename);
constexpr char kCrashEntry1[] = "12345,abc\n";
constexpr char kCrashEntry2[] = "67890,def\n";
std::string initial_contents = kCrashEntry1;
initial_contents.append(kCrashEntry2);
ASSERT_TRUE(base::WriteFile(upload_log_path, initial_contents));
BlockUntilBrowsingDataRemoved(base::Time::FromTimeT(67890u),
base::Time::Max(), constants::DATA_TYPE_HISTORY,
false);
std::string contents;
base::ReadFileToString(upload_log_path, &contents);
EXPECT_EQ(kCrashEntry1, contents);
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, false);
EXPECT_FALSE(base::PathExists(upload_log_path));
}
#endif
TEST_F(ChromeBrowsingDataRemoverDelegateTest, WipeCustomDictionaryData) {
base::FilePath dict_path =
GetProfile()->GetPath().Append(chrome::kCustomDictionaryFileName);
base::FilePath backup_path = dict_path.AddExtensionASCII("backup");
auto* spellcheck = SpellcheckServiceFactory::GetForContext(GetProfile());
ASSERT_NE(nullptr, spellcheck);
auto* dict = spellcheck->GetCustomDictionary();
ASSERT_NE(nullptr, dict);
auto change1 = std::make_unique<SpellcheckCustomDictionary::Change>();
change1->AddWord("wug");
dict->UpdateDictionaryFile(std::move(change1), dict_path);
auto change2 = std::make_unique<SpellcheckCustomDictionary::Change>();
change2->AddWord("spowing");
dict->UpdateDictionaryFile(std::move(change2), dict_path);
EXPECT_TRUE(base::PathExists(dict_path));
EXPECT_TRUE(base::PathExists(backup_path));
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_LOCAL_CUSTOM_DICTIONARY,
false);
std::string contents;
base::ReadFileToString(dict_path, &contents);
EXPECT_EQ(std::string::npos, contents.find("wug"));
EXPECT_EQ(std::string::npos, contents.find("spowing"));
EXPECT_FALSE(base::PathExists(backup_path));
}
TEST_F(ChromeBrowsingDataRemoverDelegateTest,
WipeNotificationPermissionPromptOutcomesData) {
PrefService* prefs = GetProfile()->GetPrefs();
base::Time first_recorded_time = base::Time::Now();
auto* action_history = PermissionActionsHistory::GetForProfile(GetProfile());
action_history->RecordAction(permissions::PermissionAction::DENIED,
permissions::RequestType::kNotifications);
task_environment()->AdvanceClock(base::TimeDelta::FromDays(1));
action_history->RecordAction(permissions::PermissionAction::DENIED,
permissions::RequestType::kNotifications);
task_environment()->AdvanceClock(base::TimeDelta::FromDays(1));
base::Time third_recorded_time = base::Time::Now();
action_history->RecordAction(permissions::PermissionAction::DENIED,
permissions::RequestType::kNotifications);
constexpr char kPermissionActionsPrefPath[] =
"profile.content_settings.permission_actions";
EXPECT_EQ(3u, prefs->GetDictionary(kPermissionActionsPrefPath)
->FindKey("notifications")
->GetList()
.size());
// Remove the first and the second element.
BlockUntilBrowsingDataRemoved(first_recorded_time, third_recorded_time,
constants::DATA_TYPE_SITE_USAGE_DATA, false);
// There is only one element left.
EXPECT_EQ(1u, prefs->GetDictionary(kPermissionActionsPrefPath)
->FindKey("notifications")
->GetList()
.size());
EXPECT_EQ((util::ValueToTime(prefs->GetDictionary(kPermissionActionsPrefPath)
->FindKey("notifications")
->GetList()
.begin()
->FindKey("time")))
.value_or(base::Time()),
third_recorded_time);
// Test we wiped all the elements left.
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_SITE_USAGE_DATA, false);
EXPECT_TRUE(prefs->GetDictionary(kPermissionActionsPrefPath)->DictEmpty());
}
class ChromeBrowsingDataRemoverDelegateEnabledPasswordsTest
: public ChromeBrowsingDataRemoverDelegateTest {
public:
ChromeBrowsingDataRemoverDelegateEnabledPasswordsTest() {
feature_list_.InitAndEnableFeature(
password_manager::features::kEnablePasswordsAccountStorage);
}
};
TEST_F(ChromeBrowsingDataRemoverDelegateEnabledPasswordsTest,
RemovePasswordsByTimeOnly_WithAccountStore) {
RemovePasswordsTester tester(GetProfile());
EXPECT_CALL(*tester.profile_store(), RemoveLoginsByURLAndTimeImpl(_, _, _))
.WillOnce(Return(password_manager::PasswordStoreChangeList()));
// Only DATA_TYPE_PASSWORDS is cleared. Accounts passwords are not affected.
EXPECT_CALL(*tester.account_store(), RemoveLoginsByURLAndTimeImpl(_, _, _))
.Times(0);
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_PASSWORDS, false);
}
TEST_F(ChromeBrowsingDataRemoverDelegateEnabledPasswordsTest,
RemoveAccountPasswordsByTimeOnly_WithAccountStore) {
RemovePasswordsTester tester(GetProfile());
EXPECT_CALL(*tester.profile_store(), RemoveLoginsByURLAndTimeImpl(_, _, _))
.Times(0);
EXPECT_CALL(*tester.account_store(), RemoveLoginsByURLAndTimeImpl(_, _, _))
.WillOnce(Return(password_manager::PasswordStoreChangeList()));
// For the account store, the remover delegate also waits until all the
// deletions have propagated to the Sync server. Pretend that happens
// immediately.
EXPECT_CALL(*tester.account_metadata_store(), HasUnsyncedDeletions())
.WillRepeatedly(Return(false));
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_ACCOUNT_PASSWORDS, false);
}
TEST_F(ChromeBrowsingDataRemoverDelegateEnabledPasswordsTest,
RemoveAccountPasswordsByTimeOnly_WithAccountStore_Failure) {
RemovePasswordsTester tester(GetProfile());
EXPECT_CALL(*tester.profile_store(), RemoveLoginsByURLAndTimeImpl(_, _, _))
.Times(0);
EXPECT_CALL(*tester.account_store(), RemoveLoginsByURLAndTimeImpl(_, _, _))
.WillOnce(Return(password_manager::PasswordStoreChangeList()));
// For the account store, the remover delegate also waits until all the
// deletions have propagated to the Sync server. In this test, that never
// happens.
EXPECT_CALL(*tester.account_metadata_store(), HasUnsyncedDeletions())
.WillRepeatedly(Return(true));
// Bypass the (usually 30-second) timeout until the PasswordStore reports
// failure.
tester.account_store()->SetSyncTaskTimeoutForTest(base::TimeDelta());
uint64_t failed_data_types = BlockUntilBrowsingDataRemoved(
base::Time(), base::Time::Max(), constants::DATA_TYPE_ACCOUNT_PASSWORDS,
false);
EXPECT_EQ(failed_data_types, constants::DATA_TYPE_ACCOUNT_PASSWORDS);
}
TEST_F(ChromeBrowsingDataRemoverDelegateEnabledPasswordsTest,
GetDomainsForDeferredCookieDeletion) {
auto* delegate = GetProfile()->GetBrowsingDataRemoverDelegate();
auto domains = delegate->GetDomainsForDeferredCookieDeletion(
constants::DATA_TYPE_ACCOUNT_PASSWORDS);
EXPECT_EQ(domains.size(), 1u);
EXPECT_EQ(domains[0], "google.com");
domains = delegate->GetDomainsForDeferredCookieDeletion(
constants::DATA_TYPE_PASSWORDS);
EXPECT_EQ(domains.size(), 0u);
domains =
delegate->GetDomainsForDeferredCookieDeletion(constants::ALL_DATA_TYPES);
EXPECT_EQ(domains.size(), 0u);
}
class ChromeBrowsingDataRemoverDelegateLiteVideoTest
: public ChromeBrowsingDataRemoverDelegateTest {
public:
ChromeBrowsingDataRemoverDelegateLiteVideoTest() {
// Both LiteVideo and Lite mode must be enabled for the
// LiteVideoKeyedService to be created.
feature_list_.InitAndEnableFeature(features::kLiteVideo);
}
};
TEST_F(ChromeBrowsingDataRemoverDelegateLiteVideoTest,
LiteVideoClearHistoryData) {
base::HistogramTester histogram_tester;
base::CommandLine::ForCurrentProcess()->AppendSwitch(
"enable-spdy-proxy-auth");
LiteVideoKeyedService* lite_video_keyed_service =
LiteVideoKeyedServiceFactory::GetForProfile(GetProfile());
lite_video_keyed_service->Initialize(GetProfile()->GetPath());
BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
constants::DATA_TYPE_HISTORY, false);
histogram_tester.ExpectUniqueSample("LiteVideo.UserBlocklist.ClearBlocklist",
true, 1);
}