blob: c1d20ea33a6dc92e0acbc30d7b139c4946c8920b [file] [log] [blame]
// Copyright 2019 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/previews/previews_top_host_provider_impl.h"
#include "base/values.h"
#include "chrome/browser/engagement/site_engagement_service.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/testing_profile.h"
#include "components/optimization_guide/optimization_guide_prefs.h"
#include "components/prefs/pref_service.h"
#include "components/previews/content/previews_hints_util.h"
#include "components/previews/core/previews_experiments.h"
#include "content/public/test/mock_navigation_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace previews {
// Class to test the TopHostProvider and the HintsFetcherTopHostBlacklist.
class PreviewsTopHostProviderImplTest : public ChromeRenderViewHostTestHarness {
public:
void SetUp() override {
ChromeRenderViewHostTestHarness::SetUp();
top_host_provider_ =
std::make_unique<PreviewsTopHostProviderImpl>(profile());
service_ = SiteEngagementService::Get(profile());
pref_service_ = profile()->GetPrefs();
}
void AddEngagedHosts(size_t num_hosts) {
for (size_t i = 1; i <= num_hosts; i++) {
AddEngagedHost(GURL(base::StringPrintf("https://domain%zu.com", i)),
static_cast<int>(i));
}
}
void AddEngagedHost(GURL url, int num_points) {
service_->AddPointsForTesting(url, num_points);
}
bool IsHostBlacklisted(const std::string& host) {
const base::DictionaryValue* top_host_blacklist =
pref_service_->GetDictionary(
optimization_guide::prefs::kHintsFetcherTopHostBlacklist);
return top_host_blacklist->FindKey(previews::HashHostForDictionary(host));
}
void PopulateTopHostBlacklist(size_t num_hosts) {
std::unique_ptr<base::DictionaryValue> top_host_filter =
pref_service_
->GetDictionary(
optimization_guide::prefs::kHintsFetcherTopHostBlacklist)
->CreateDeepCopy();
for (size_t i = 1; i <= num_hosts; i++) {
top_host_filter->SetBoolKey(
HashHostForDictionary(base::StringPrintf("domain%zu.com", i)), true);
}
pref_service_->Set(optimization_guide::prefs::kHintsFetcherTopHostBlacklist,
*top_host_filter);
}
void AddHostToBlackList(const std::string& host) {
std::unique_ptr<base::DictionaryValue> top_host_filter =
pref_service_
->GetDictionary(
optimization_guide::prefs::kHintsFetcherTopHostBlacklist)
->CreateDeepCopy();
top_host_filter->SetBoolKey(previews::HashHostForDictionary(host), true);
pref_service_->Set(optimization_guide::prefs::kHintsFetcherTopHostBlacklist,
*top_host_filter);
}
void SimulateUniqueNavigationsToTopHosts(size_t num_hosts) {
for (size_t i = 1; i <= num_hosts; i++) {
SimulateNavigation(GURL(base::StringPrintf("https://domain%zu.com", i)));
}
}
void SimulateNavigation(GURL url) {
std::unique_ptr<content::MockNavigationHandle> test_handle_ =
std::make_unique<content::MockNavigationHandle>(url, main_rfh());
PreviewsTopHostProviderImpl::MaybeUpdateTopHostBlacklist(
test_handle_.get());
}
void RemoveHostsFromBlacklist(size_t num_hosts_navigated) {
std::unique_ptr<base::DictionaryValue> top_host_filter =
pref_service_
->GetDictionary(
optimization_guide::prefs::kHintsFetcherTopHostBlacklist)
->CreateDeepCopy();
for (size_t i = 1; i <= num_hosts_navigated; i++) {
top_host_filter->RemoveKey(
HashHostForDictionary(base::StringPrintf("domain%zu.com", i)));
}
pref_service_->Set(optimization_guide::prefs::kHintsFetcherTopHostBlacklist,
*top_host_filter);
}
void SetTopHostBlacklistState(
optimization_guide::prefs::HintsFetcherTopHostBlacklistState
blacklist_state) {
profile()->GetPrefs()->SetInteger(
optimization_guide::prefs::kHintsFetcherTopHostBlacklistState,
static_cast<int>(blacklist_state));
}
optimization_guide::prefs::HintsFetcherTopHostBlacklistState
GetCurrentTopHostBlacklistState() {
return static_cast<
optimization_guide::prefs::HintsFetcherTopHostBlacklistState>(
pref_service_->GetInteger(
optimization_guide::prefs::kHintsFetcherTopHostBlacklistState));
}
void TearDown() override { ChromeRenderViewHostTestHarness::TearDown(); }
PreviewsTopHostProviderImpl* top_host_provider() {
return top_host_provider_.get();
}
private:
std::unique_ptr<PreviewsTopHostProviderImpl> top_host_provider_;
SiteEngagementService* service_;
PrefService* pref_service_;
};
TEST_F(PreviewsTopHostProviderImplTest, GetTopHostsMaxSites) {
SetTopHostBlacklistState(optimization_guide::prefs::
HintsFetcherTopHostBlacklistState::kInitialized);
size_t engaged_hosts = 5;
size_t max_top_hosts = 3;
AddEngagedHosts(engaged_hosts);
std::vector<std::string> hosts =
top_host_provider()->GetTopHosts(max_top_hosts);
EXPECT_EQ(max_top_hosts, hosts.size());
}
TEST_F(PreviewsTopHostProviderImplTest,
GetTopHostsFiltersPrivacyBlackedlistedHosts) {
SetTopHostBlacklistState(optimization_guide::prefs::
HintsFetcherTopHostBlacklistState::kInitialized);
size_t engaged_hosts = 5;
size_t max_top_hosts = 5;
size_t num_hosts_blacklisted = 2;
AddEngagedHosts(engaged_hosts);
PopulateTopHostBlacklist(num_hosts_blacklisted);
std::vector<std::string> hosts =
top_host_provider()->GetTopHosts(max_top_hosts);
EXPECT_EQ(hosts.size(), engaged_hosts - num_hosts_blacklisted);
}
TEST_F(PreviewsTopHostProviderImplTest, GetTopHostsInitializeBlacklistState) {
EXPECT_EQ(GetCurrentTopHostBlacklistState(),
optimization_guide::prefs::HintsFetcherTopHostBlacklistState::
kNotInitialized);
size_t engaged_hosts = 5;
size_t max_top_hosts = 5;
AddEngagedHosts(engaged_hosts);
std::vector<std::string> hosts =
top_host_provider()->GetTopHosts(max_top_hosts);
// On initialization, GetTopHosts should always return zero hosts.
EXPECT_EQ(hosts.size(), 0u);
EXPECT_EQ(GetCurrentTopHostBlacklistState(),
optimization_guide::prefs::HintsFetcherTopHostBlacklistState::
kInitialized);
}
TEST_F(PreviewsTopHostProviderImplTest,
GetTopHostsBlacklistStateNotInitializedToInitialized) {
size_t engaged_hosts = 5;
size_t max_top_hosts = 5;
size_t num_hosts_blacklisted = 5;
AddEngagedHosts(engaged_hosts);
std::vector<std::string> hosts =
top_host_provider()->GetTopHosts(max_top_hosts);
EXPECT_EQ(hosts.size(), 0u);
// Blacklist should now have items removed.
size_t num_navigations = 2;
RemoveHostsFromBlacklist(num_navigations);
hosts = top_host_provider()->GetTopHosts(max_top_hosts);
EXPECT_EQ(hosts.size(),
engaged_hosts - (num_hosts_blacklisted - num_navigations));
EXPECT_EQ(GetCurrentTopHostBlacklistState(),
optimization_guide::prefs::HintsFetcherTopHostBlacklistState::
kInitialized);
}
TEST_F(PreviewsTopHostProviderImplTest,
GetTopHostsBlacklistStateNotInitializedToEmpty) {
size_t engaged_hosts = 5;
size_t max_top_hosts = 5;
size_t num_hosts_blacklisted = 5;
AddEngagedHosts(engaged_hosts);
std::vector<std::string> hosts =
top_host_provider()->GetTopHosts(max_top_hosts);
EXPECT_EQ(hosts.size(), 0u);
// Blacklist should now have items removed.
size_t num_navigations = 5;
RemoveHostsFromBlacklist(num_navigations);
hosts = top_host_provider()->GetTopHosts(max_top_hosts);
EXPECT_EQ(hosts.size(),
engaged_hosts - (num_hosts_blacklisted - num_navigations));
EXPECT_EQ(
GetCurrentTopHostBlacklistState(),
optimization_guide::prefs::HintsFetcherTopHostBlacklistState::kEmpty);
}
TEST_F(PreviewsTopHostProviderImplTest,
MaybeUpdateTopHostBlacklistNavigationsOnBlacklist) {
size_t engaged_hosts = 5;
size_t max_top_hosts = 5;
size_t num_top_hosts = 3;
AddEngagedHosts(engaged_hosts);
// The blacklist should be populated on the first request.
std::vector<std::string> hosts =
top_host_provider()->GetTopHosts(max_top_hosts);
EXPECT_EQ(hosts.size(), 0u);
// Navigate to some engaged hosts to trigger their removal from the top host
// blacklist.
SimulateUniqueNavigationsToTopHosts(num_top_hosts);
hosts = top_host_provider()->GetTopHosts(max_top_hosts);
EXPECT_EQ(hosts.size(), num_top_hosts);
}
TEST_F(PreviewsTopHostProviderImplTest,
MaybeUpdateTopHostBlacklistEmptyBlacklist) {
size_t engaged_hosts = 5;
size_t max_top_hosts = 5;
size_t num_top_hosts = 5;
AddEngagedHosts(engaged_hosts);
std::vector<std::string> hosts =
top_host_provider()->GetTopHosts(max_top_hosts);
EXPECT_EQ(hosts.size(), 0u);
SimulateUniqueNavigationsToTopHosts(num_top_hosts);
EXPECT_EQ(
GetCurrentTopHostBlacklistState(),
optimization_guide::prefs::HintsFetcherTopHostBlacklistState::kEmpty);
hosts = top_host_provider()->GetTopHosts(max_top_hosts);
EXPECT_EQ(hosts.size(), num_top_hosts);
}
TEST_F(PreviewsTopHostProviderImplTest,
HintsFetcherTopHostBlacklistNonHTTPOrHTTPSHost) {
size_t engaged_hosts = 5;
size_t max_top_hosts = 5;
size_t num_hosts_blacklisted = 5;
GURL http_url = GURL("http://anyscheme.com");
GURL file_url = GURL("file://anyscheme.com");
AddEngagedHosts(engaged_hosts);
AddEngagedHost(http_url, 5);
PopulateTopHostBlacklist(num_hosts_blacklisted);
AddHostToBlackList(http_url.host());
SetTopHostBlacklistState(optimization_guide::prefs::
HintsFetcherTopHostBlacklistState::kInitialized);
// A Non HTTP/HTTPS navigation should not remove a host from the blacklist.
SimulateNavigation(file_url);
std::vector<std::string> hosts =
top_host_provider()->GetTopHosts(max_top_hosts);
EXPECT_EQ(hosts.size(), 0u);
// The host, anyscheme.com, should still be on the blacklist.
EXPECT_TRUE(IsHostBlacklisted(file_url.host()));
// TopHostProviderImpl prevents HTTP hosts from being returned.
SimulateNavigation(http_url);
hosts = top_host_provider()->GetTopHosts(max_top_hosts);
EXPECT_EQ(hosts.size(), 0u);
EXPECT_FALSE(IsHostBlacklisted(http_url.host()));
}
TEST_F(PreviewsTopHostProviderImplTest,
IntializeTopHostBlacklistWithMaxTopSites) {
size_t engaged_hosts =
previews::params::MaxHintsFetcherTopHostBlacklistSize() + 1;
size_t max_top_hosts =
previews::params::MaxHintsFetcherTopHostBlacklistSize() + 1;
AddEngagedHosts(engaged_hosts);
// Blacklist should be populated on the first request.
std::vector<std::string> hosts =
top_host_provider()->GetTopHosts(max_top_hosts);
EXPECT_EQ(hosts.size(), 0u);
hosts = top_host_provider()->GetTopHosts(max_top_hosts);
EXPECT_EQ(
hosts.size(),
engaged_hosts - previews::params::MaxHintsFetcherTopHostBlacklistSize());
EXPECT_EQ(GetCurrentTopHostBlacklistState(),
optimization_guide::prefs::HintsFetcherTopHostBlacklistState::
kInitialized);
// The last host has the most engagement points so it will be blacklisted. The
// first host has the lowest engagement score and will not be blacklisted
// because it is not in the top MaxHintsFetcherTopHostBlacklistSize engaged
// hosts by engagement score.
EXPECT_TRUE(IsHostBlacklisted(base::StringPrintf(
"domain%zu.com",
previews::params::MaxHintsFetcherTopHostBlacklistSize())));
EXPECT_FALSE(IsHostBlacklisted(base::StringPrintf("domain%u.com", 1u)));
}
} // namespace previews