| Index: chrome/browser/chrome_content_browser_client_unittest.cc
|
| diff --git a/chrome/browser/chrome_content_browser_client_unittest.cc b/chrome/browser/chrome_content_browser_client_unittest.cc
|
| index 88a062064fe2be72b758d2c6a23358533310d39c..0f6c43382b2d6759f893e5e1284a32fd651a93f5 100644
|
| --- a/chrome/browser/chrome_content_browser_client_unittest.cc
|
| +++ b/chrome/browser/chrome_content_browser_client_unittest.cc
|
| @@ -4,14 +4,27 @@
|
|
|
| #include "chrome/browser/chrome_content_browser_client.h"
|
|
|
| +#include <list>
|
| #include <map>
|
| +#include <memory>
|
|
|
| +#include "base/bind.h"
|
| #include "base/command_line.h"
|
| #include "base/macros.h"
|
| +#include "base/memory/ptr_util.h"
|
| +#include "base/message_loop/message_loop.h"
|
| #include "base/metrics/field_trial.h"
|
| +#include "base/strings/stringprintf.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "build/build_config.h"
|
| +#include "chrome/browser/browsing_data/browsing_data_filter_builder.h"
|
| +#include "chrome/browser/browsing_data/browsing_data_helper.h"
|
| +#include "chrome/browser/browsing_data/browsing_data_remover.h"
|
| +#include "chrome/browser/browsing_data/browsing_data_remover_factory.h"
|
| +#include "chrome/browser/browsing_data/origin_filter_builder.h"
|
| +#include "chrome/browser/browsing_data/registrable_domain_filter_builder.h"
|
| #include "chrome/browser/search_engines/template_url_service_factory.h"
|
| +#include "chrome/test/base/testing_profile.h"
|
| #include "components/content_settings/core/browser/host_content_settings_map.h"
|
| #include "components/search_engines/template_url_service.h"
|
| #include "components/variations/entropy_provider.h"
|
| @@ -22,6 +35,7 @@
|
| #include "content/public/browser/web_contents.h"
|
| #include "content/public/common/content_switches.h"
|
| #include "content/public/test/test_browser_thread_bundle.h"
|
| +#include "testing/gmock/include/gmock/gmock.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
| #include "url/gurl.h"
|
|
|
| @@ -33,6 +47,7 @@
|
| #include "chrome/test/base/search_test_utils.h"
|
| #endif
|
|
|
| +using testing::_;
|
| using ChromeContentBrowserClientTest = testing::Test;
|
|
|
| TEST_F(ChromeContentBrowserClientTest, ShouldAssignSiteForURL) {
|
| @@ -328,3 +343,371 @@ TEST_F(InstantNTPURLRewriteTest, UberURLHandler_InstantExtendedNewTabPage) {
|
|
|
| } // namespace content
|
| #endif // !defined(OS_ANDROID)
|
| +
|
| +namespace {
|
| +
|
| +// A BrowsingDataRemover that only records calls.
|
| +class MockBrowsingDataRemover : public BrowsingDataRemover {
|
| + public:
|
| + explicit MockBrowsingDataRemover(content::BrowserContext* context)
|
| + : BrowsingDataRemover(context) {}
|
| +
|
| + ~MockBrowsingDataRemover() override {
|
| + DCHECK(!expected_calls_.size())
|
| + << "Expectations were set but not verified.";
|
| + }
|
| +
|
| + void RemoveInternal(const TimeRange& time_range,
|
| + int remove_mask,
|
| + int origin_type_mask,
|
| + std::unique_ptr<BrowsingDataFilterBuilder> filter_builder,
|
| + BrowsingDataRemover::Observer* observer) override {
|
| + actual_calls_.emplace_back(time_range, remove_mask, origin_type_mask,
|
| + std::move(filter_builder), UNKNOWN);
|
| +
|
| + // |observer| is not recorded in |actual_calls_| to be compared with
|
| + // expectations, because it's created internally in ClearSiteData() and
|
| + // it's unknown to this. However, it is tested implicitly, because we use
|
| + // it for the completion callback, so an incorrect |observer| will fail
|
| + // the test by waiting for the callback forever.
|
| + DCHECK(observer);
|
| + observer->OnBrowsingDataRemoverDone();
|
| + }
|
| +
|
| + void ExpectCall(
|
| + const TimeRange& time_range,
|
| + int remove_mask,
|
| + int origin_type_mask,
|
| + std::unique_ptr<RegistrableDomainFilterBuilder> filter_builder) {
|
| + expected_calls_.emplace_back(time_range, remove_mask, origin_type_mask,
|
| + std::move(filter_builder),
|
| + REGISTRABLE_DOMAIN_FILTER_BUILDER);
|
| + }
|
| +
|
| + void ExpectCall(const TimeRange& time_range,
|
| + int remove_mask,
|
| + int origin_type_mask,
|
| + std::unique_ptr<OriginFilterBuilder> filter_builder) {
|
| + expected_calls_.emplace_back(time_range, remove_mask, origin_type_mask,
|
| + std::move(filter_builder),
|
| + ORIGIN_FILTER_BUILDER);
|
| + }
|
| +
|
| + void ExpectCallDontCareAboutFilterBuilder(const TimeRange& time_range,
|
| + int remove_mask,
|
| + int origin_type_mask) {
|
| + expected_calls_.emplace_back(time_range, remove_mask, origin_type_mask,
|
| + std::unique_ptr<BrowsingDataFilterBuilder>(),
|
| + DONT_CARE);
|
| + }
|
| +
|
| + void VerifyAndClearExpectations() {
|
| + EXPECT_EQ(expected_calls_, actual_calls_);
|
| + expected_calls_.clear();
|
| + actual_calls_.clear();
|
| + }
|
| +
|
| + private:
|
| + // Used to further specify the type and intention behind the passed
|
| + // std::unique_ptr<BrowsingDataFilterBuilder>. This is needed for comparison
|
| + // between the expected and actual call parameters.
|
| + enum FilterBuilderType {
|
| + REGISTRABLE_DOMAIN_FILTER_BUILDER, // RegistrableDomainFilterBuilder
|
| + ORIGIN_FILTER_BUILDER, // OriginFilterBuilder
|
| + UNKNOWN, // can't static_cast<>
|
| + DONT_CARE // don't have to compare for equality
|
| + };
|
| +
|
| + class CallParameters {
|
| + public:
|
| + CallParameters(const TimeRange& time_range,
|
| + int remove_mask,
|
| + int origin_type_mask,
|
| + std::unique_ptr<BrowsingDataFilterBuilder> filter_builder,
|
| + FilterBuilderType type)
|
| + : time_range_(time_range),
|
| + remove_mask_(remove_mask),
|
| + origin_type_mask_(origin_type_mask),
|
| + filter_builder_(std::move(filter_builder)),
|
| + type_(type) {}
|
| + ~CallParameters() {}
|
| +
|
| + bool operator==(const CallParameters& other) const {
|
| + const CallParameters& a = *this;
|
| + const CallParameters& b = other;
|
| +
|
| + if (!(a.time_range_ == b.time_range_) ||
|
| + a.remove_mask_ != b.remove_mask_ ||
|
| + a.origin_type_mask_ != b.origin_type_mask_) {
|
| + return false;
|
| + }
|
| +
|
| + if (a.type_ == DONT_CARE || b.type_ == DONT_CARE)
|
| + return true;
|
| + if (a.type_ == UNKNOWN && b.type_ == UNKNOWN)
|
| + return false;
|
| + if (a.type_ != UNKNOWN && b.type_ != UNKNOWN && a.type_ != b.type_)
|
| + return false;
|
| +
|
| + FilterBuilderType resolved_type =
|
| + (a.type_ != UNKNOWN) ? a.type_ : b.type_;
|
| +
|
| + DCHECK(resolved_type == ORIGIN_FILTER_BUILDER ||
|
| + resolved_type == REGISTRABLE_DOMAIN_FILTER_BUILDER);
|
| +
|
| + if (resolved_type == ORIGIN_FILTER_BUILDER) {
|
| + return *static_cast<OriginFilterBuilder*>(a.filter_builder_.get()) ==
|
| + *static_cast<OriginFilterBuilder*>(b.filter_builder_.get());
|
| + } else if (resolved_type == REGISTRABLE_DOMAIN_FILTER_BUILDER) {
|
| + return *static_cast<RegistrableDomainFilterBuilder*>(
|
| + a.filter_builder_.get()) ==
|
| + *static_cast<RegistrableDomainFilterBuilder*>(
|
| + b.filter_builder_.get());
|
| + }
|
| +
|
| + NOTREACHED();
|
| + return false;
|
| + }
|
| +
|
| + private:
|
| + TimeRange time_range_;
|
| + int remove_mask_;
|
| + int origin_type_mask_;
|
| + std::unique_ptr<BrowsingDataFilterBuilder> filter_builder_;
|
| + FilterBuilderType type_;
|
| + };
|
| +
|
| + std::list<CallParameters> actual_calls_;
|
| + std::list<CallParameters> expected_calls_;
|
| +};
|
| +
|
| +// Tests for ChromeContentBrowserClient::ClearSiteData().
|
| +class ChromeContentBrowserClientClearSiteDataTest : public testing::Test {
|
| + public:
|
| + void SetUp() override {
|
| + BrowsingDataRemoverFactory::GetInstance()->SetTestingFactoryAndUse(
|
| + &profile_, &ChromeContentBrowserClientClearSiteDataTest::GetRemover);
|
| + }
|
| +
|
| + content::BrowserContext* profile() { return &profile_; }
|
| +
|
| + MockBrowsingDataRemover* remover() {
|
| + return static_cast<MockBrowsingDataRemover*>(
|
| + BrowsingDataRemoverFactory::GetForBrowserContext(&profile_));
|
| + }
|
| +
|
| + void SetClearingFinished(bool finished) { finished_ = finished; }
|
| +
|
| + bool IsClearingFinished() { return finished_; }
|
| +
|
| + private:
|
| + static std::unique_ptr<KeyedService> GetRemover(
|
| + content::BrowserContext* context) {
|
| + return base::WrapUnique(new MockBrowsingDataRemover(context));
|
| + }
|
| +
|
| + base::MessageLoop loop_;
|
| + TestingProfile profile_;
|
| + bool finished_;
|
| +};
|
| +
|
| +// Tests that the parameters to ClearBrowsingData() are translated to
|
| +// the correct BrowsingDataRemover::RemoveInternal() operation. The fourth
|
| +// parameter, |filter_builder|, is tested in detail in the RegistrableDomains
|
| +// test below.
|
| +TEST_F(ChromeContentBrowserClientClearSiteDataTest, Parameters) {
|
| + ChromeContentBrowserClient client;
|
| +
|
| + struct TestCase {
|
| + bool cookies;
|
| + bool storage;
|
| + bool cache;
|
| + int mask;
|
| + } test_cases[] = {
|
| + {false, false, false, 0},
|
| + {true, false, false, BrowsingDataRemover::REMOVE_COOKIES |
|
| + BrowsingDataRemover::REMOVE_CHANNEL_IDS},
|
| + {false, true, false, BrowsingDataRemover::REMOVE_SITE_DATA &
|
| + ~BrowsingDataRemover::REMOVE_COOKIES &
|
| + ~BrowsingDataRemover::REMOVE_CHANNEL_IDS},
|
| + {false, false, true, BrowsingDataRemover::REMOVE_CACHE},
|
| + {true, true, false, BrowsingDataRemover::REMOVE_SITE_DATA},
|
| + {true, false, true, BrowsingDataRemover::REMOVE_COOKIES |
|
| + BrowsingDataRemover::REMOVE_CHANNEL_IDS |
|
| + BrowsingDataRemover::REMOVE_CACHE},
|
| + {false, true, true, BrowsingDataRemover::REMOVE_CACHE |
|
| + (BrowsingDataRemover::REMOVE_SITE_DATA &
|
| + ~BrowsingDataRemover::REMOVE_COOKIES &
|
| + ~BrowsingDataRemover::REMOVE_CHANNEL_IDS)},
|
| + {true, true, true, BrowsingDataRemover::REMOVE_SITE_DATA |
|
| + BrowsingDataRemover::REMOVE_CACHE},
|
| + };
|
| +
|
| + for (unsigned int i = 0; i < arraysize(test_cases); ++i) {
|
| + SCOPED_TRACE(base::StringPrintf("Test case %d", i));
|
| + const TestCase& test_case = test_cases[i];
|
| +
|
| + // We always delete data for all time and all origin types.
|
| + BrowsingDataRemover::TimeRange all_time(base::Time(), base::Time::Max());
|
| + BrowsingDataHelper::OriginTypeMask all_origin_types =
|
| + BrowsingDataHelper::ALL;
|
| +
|
| + // Some data are deleted for the origin and some for the registrable domain.
|
| + // Depending on the chosen datatypes, this might result into one or two
|
| + // calls. In the latter case, the removal mask will be split into two
|
| + // parts - one for the origin deletion and one for the registrable domain.
|
| + const int domain_scoped_types = BrowsingDataRemover::REMOVE_COOKIES |
|
| + BrowsingDataRemover::REMOVE_CHANNEL_IDS;
|
| + int registrable_domain_deletion_mask = test_case.mask & domain_scoped_types;
|
| + int origin_deletion_mask = test_case.mask & ~domain_scoped_types;
|
| +
|
| + if (registrable_domain_deletion_mask) {
|
| + remover()->ExpectCallDontCareAboutFilterBuilder(
|
| + all_time, registrable_domain_deletion_mask, all_origin_types);
|
| + }
|
| +
|
| + if (origin_deletion_mask) {
|
| + remover()->ExpectCallDontCareAboutFilterBuilder(
|
| + all_time, origin_deletion_mask, all_origin_types);
|
| + }
|
| +
|
| + SetClearingFinished(false);
|
| + client.ClearSiteData(
|
| + profile(), url::Origin(GURL("https://www.example.com")),
|
| + test_case.cookies, test_case.storage, test_case.cache,
|
| + base::Bind(
|
| + &ChromeContentBrowserClientClearSiteDataTest::SetClearingFinished,
|
| + base::Unretained(this), true));
|
| + EXPECT_TRUE(IsClearingFinished());
|
| +
|
| + remover()->VerifyAndClearExpectations();
|
| + }
|
| +}
|
| +
|
| +// Tests that ClearBrowsingData() called for an origin deletes cookies in the
|
| +// scope of the registrable domain corresponding to that origin, while cache
|
| +// is deleted for that exact origin.
|
| +TEST_F(ChromeContentBrowserClientClearSiteDataTest, RegistrableDomains) {
|
| + ChromeContentBrowserClient client;
|
| +
|
| + struct TestCase {
|
| + const char* origin; // origin on which ClearSiteData() is called.
|
| + const char* domain; // domain on which cookies will be deleted.
|
| + } test_cases[] = {
|
| + // TLD has no embedded dot.
|
| + {"https://example.com", "example.com"},
|
| + {"https://www.example.com", "example.com"},
|
| + {"https://www.fourth.third.second.com", "second.com"},
|
| +
|
| + // TLD has one embedded dot.
|
| + {"https://www.example.co.uk", "example.co.uk"},
|
| + {"https://example.co.uk", "example.co.uk"},
|
| +
|
| + // TLD has more embedded dots.
|
| + {"https://www.website.sp.nom.br", "website.sp.nom.br"},
|
| +
|
| + // IP addresses.
|
| + {"http://127.0.0.1", "127.0.0.1"},
|
| + {"http://192.168.0.1", "192.168.0.1"},
|
| + {"http://192.168.0.1", "192.168.0.1"},
|
| +
|
| + // Internal hostnames.
|
| + {"http://localhost", "localhost"},
|
| + {"http://fileserver", "fileserver"},
|
| +
|
| + // These are not subdomains of internal hostnames, but subdomain of
|
| + // unknown TLDs.
|
| + {"http://subdomain.localhost", "subdomain.localhost"},
|
| + {"http://www.subdomain.localhost", "subdomain.localhost"},
|
| + {"http://documents.fileserver", "documents.fileserver"},
|
| +
|
| + // Scheme and port don't matter.
|
| + {"http://example.com", "example.com"},
|
| + {"http://example.com:8080", "example.com"},
|
| + {"https://example.com:4433", "example.com"},
|
| + };
|
| +
|
| + for (const TestCase& test_case : test_cases) {
|
| + SCOPED_TRACE(test_case.origin);
|
| +
|
| + std::unique_ptr<RegistrableDomainFilterBuilder>
|
| + registrable_domain_filter_builder(new RegistrableDomainFilterBuilder(
|
| + BrowsingDataFilterBuilder::WHITELIST));
|
| + registrable_domain_filter_builder->AddRegisterableDomain(test_case.domain);
|
| +
|
| + remover()->ExpectCall(
|
| + BrowsingDataRemover::Period(browsing_data::TimePeriod::ALL_TIME),
|
| + BrowsingDataRemover::REMOVE_COOKIES |
|
| + BrowsingDataRemover::REMOVE_CHANNEL_IDS,
|
| + BrowsingDataHelper::ALL, std::move(registrable_domain_filter_builder));
|
| +
|
| + std::unique_ptr<OriginFilterBuilder> origin_filter_builder(
|
| + new OriginFilterBuilder(BrowsingDataFilterBuilder::WHITELIST));
|
| + origin_filter_builder->AddOrigin(url::Origin(GURL(test_case.origin)));
|
| +
|
| + remover()->ExpectCall(
|
| + BrowsingDataRemover::Period(browsing_data::TimePeriod::ALL_TIME),
|
| + BrowsingDataRemover::REMOVE_CACHE, BrowsingDataHelper::ALL,
|
| + std::move(origin_filter_builder));
|
| +
|
| + SetClearingFinished(false);
|
| + client.ClearSiteData(
|
| + profile(), url::Origin(GURL(test_case.origin)), true /* cookies */,
|
| + false /* storage */, true /* cache */,
|
| + base::Bind(
|
| + &ChromeContentBrowserClientClearSiteDataTest::SetClearingFinished,
|
| + base::Unretained(this), true));
|
| + EXPECT_TRUE(IsClearingFinished());
|
| +
|
| + remover()->VerifyAndClearExpectations();
|
| + }
|
| +}
|
| +
|
| +// Tests that we always wait for all scheduled BrowsingDataRemover tasks and
|
| +// that BrowsingDataRemoverObserver never leaks.
|
| +TEST_F(ChromeContentBrowserClientClearSiteDataTest, Tasks) {
|
| + ChromeContentBrowserClient client;
|
| + url::Origin origin(GURL("https://www.example.com"));
|
| +
|
| + // No removal tasks.
|
| + SetClearingFinished(false);
|
| + client.ClearSiteData(
|
| + profile(), origin, false /* cookies */, false /* storage */,
|
| + false /* cache */,
|
| + base::Bind(
|
| + &ChromeContentBrowserClientClearSiteDataTest::SetClearingFinished,
|
| + base::Unretained(this), true));
|
| + EXPECT_TRUE(IsClearingFinished());
|
| +
|
| + // One removal task: deleting cookies with a domain filter.
|
| + SetClearingFinished(false);
|
| + client.ClearSiteData(
|
| + profile(), origin, true /* cookies */, false /* storage */,
|
| + false /* cache */,
|
| + base::Bind(
|
| + &ChromeContentBrowserClientClearSiteDataTest::SetClearingFinished,
|
| + base::Unretained(this), true));
|
| + EXPECT_TRUE(IsClearingFinished());
|
| +
|
| + // One removal task: deleting cache with a domain filter.
|
| + SetClearingFinished(false);
|
| + client.ClearSiteData(
|
| + profile(), origin, false /* cookies */, false /* storage */,
|
| + true /* cache */,
|
| + base::Bind(
|
| + &ChromeContentBrowserClientClearSiteDataTest::SetClearingFinished,
|
| + base::Unretained(this), true));
|
| + EXPECT_TRUE(IsClearingFinished());
|
| +
|
| + // Two removal tasks, with domain and origin filters respectively.
|
| + SetClearingFinished(false);
|
| + client.ClearSiteData(
|
| + profile(), origin, true /* cookies */, false /* storage */,
|
| + true /* cache */,
|
| + base::Bind(
|
| + &ChromeContentBrowserClientClearSiteDataTest::SetClearingFinished,
|
| + base::Unretained(this), true));
|
| + EXPECT_TRUE(IsClearingFinished());
|
| +}
|
| +
|
| +} // namespace
|
|
|