Commit 11202527 authored by Doug Arnett's avatar Doug Arnett Committed by Commit Bot

Adds HintCache to hold PageHint based Cacao hints

This only holds the hint data for now. Another CL to follow will use it.
Moves the recently added activation list into the hint cache as well.

Bug: 867651
Change-Id: I188cab0b8539439d859186eecc8185a66ba34efb
Reviewed-on: https://chromium-review.googlesource.com/1150739
Commit-Queue: Doug Arnett <dougarnett@chromium.org>
Reviewed-by: default avatarTarun Bansal <tbansal@chromium.org>
Cr-Commit-Position: refs/heads/master@{#579842}
parent 23823a1d
......@@ -4,8 +4,8 @@
static_library("content") {
sources = [
"activation_list.cc",
"activation_list.h",
"hint_cache.cc",
"hint_cache.h",
"previews_content_util.cc",
"previews_content_util.h",
"previews_decider_impl.cc",
......@@ -34,7 +34,7 @@ static_library("content") {
source_set("unit_tests") {
testonly = true
sources = [
"activation_list_unittest.cc",
"hint_cache_unittest.cc",
"previews_content_util_unittest.cc",
"previews_decider_impl_unittest.cc",
"previews_optimization_guide_unittest.cc",
......
// Copyright 2018 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 "components/previews/content/activation_list.h"
#include <set>
#include "base/metrics/histogram_macros.h"
#include "url/gurl.h"
namespace previews {
ActivationList::ActivationList(const std::vector<std::string>& url_suffixes) {
url_matcher_ = std::make_unique<url_matcher::URLMatcher>();
url_matcher::URLMatcherConditionSet::Vector all_conditions;
url_matcher::URLMatcherConditionFactory* condition_factory =
url_matcher_->condition_factory();
int id = 0;
for (const auto& url_suffix : url_suffixes) {
DCHECK(!url_suffix.empty());
DCHECK_EQ(std::string::npos, url_suffix.find("/"));
url_matcher::URLMatcherCondition condition =
condition_factory->CreateHostSuffixCondition(url_suffix);
all_conditions.push_back(new url_matcher::URLMatcherConditionSet(
id, std::set<url_matcher::URLMatcherCondition>{condition}));
++id;
}
url_matcher_->AddConditionSets(all_conditions);
DETACH_FROM_SEQUENCE(sequence_checker_);
}
ActivationList::~ActivationList() {}
bool ActivationList::IsHostWhitelistedAtNavigation(const GURL& url,
PreviewsType type) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(PreviewsType::RESOURCE_LOADING_HINTS, type);
DCHECK(url.is_valid());
DCHECK(url.SchemeIsHTTPOrHTTPS());
if (!url_matcher_)
return false;
const std::set<url_matcher::URLMatcherConditionSet::ID>& matches =
url_matcher_->MatchURL(url);
// Only consider the first match in iteration order as it takes precedence
// if there are multiple matches.
return (matches.begin() != matches.end());
}
} // namespace previews
\ No newline at end of file
// Copyright 2018 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.
#ifndef COMPONENTS_PREVIEWS_CONTENT_ACTIVATION_LIST_H_
#define COMPONENTS_PREVIEWS_CONTENT_ACTIVATION_LIST_H_
#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/sequence_checker.h"
#include "components/optimization_guide/proto/hints.pb.h"
#include "components/previews/core/previews_experiments.h"
#include "components/previews/core/previews_user_data.h"
#include "components/url_matcher/url_matcher.h"
class GURL;
namespace previews {
// Holds the activation list of hosts extracted from the server hints
// configuration.
class ActivationList {
public:
// Adds |url_suffixes| to |url_matcher_| for resource loading hints
// optimization.
explicit ActivationList(const std::vector<std::string>& url_suffixes);
~ActivationList();
// Whether |url| is whitelisted for previews type |type|. The method may
// make the decision based only on a partial comparison (e.g., only the
// hostname of |url|). As such, the method may return true even if |type|
// can't be used for the previews.
bool IsHostWhitelistedAtNavigation(const GURL& url, PreviewsType type) const;
private:
// The URLMatcher used to match whether a URL has any previews whitelisted
// with it.
std::unique_ptr<url_matcher::URLMatcher> url_matcher_;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(ActivationList);
};
} // namespace previews
#endif // COMPONENTS_PREVIEWS_CONTENT_ACTIVATION_LIST_H_
// Copyright 2018 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 "components/previews/content/activation_list.h"
#include <string>
#include <vector>
#include "base/macros.h"
#include "components/previews/core/previews_experiments.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace previews {
namespace {
class ActivationListTest : public testing::Test {
public:
ActivationListTest() {}
~ActivationListTest() override {}
protected:
std::unique_ptr<ActivationList> page_host_activation_list_;
DISALLOW_COPY_AND_ASSIGN(ActivationListTest);
};
TEST_F(ActivationListTest, TestInitialization) {
std::vector<std::string> keys;
keys.push_back("example.com");
keys.push_back("m.foo.com");
page_host_activation_list_ = std::make_unique<ActivationList>(keys);
struct {
GURL url;
bool expect_whitelisted;
} test_cases[] = {
{GURL("https://www.example.com"), true},
{GURL("https://www.example.co.in"), false},
{GURL("https://www.example.com/index.html"), true},
{GURL("https://www.example.com/a.html"), true},
{GURL("https://www.example.com/foo/a.html"), true},
{GURL("https://m.example.com"), true},
{GURL("https://m.example.com/foo.html"), true},
{GURL("https://m.example.com/foo/bar/baz.html"), true},
{GURL("https://example.com"), true},
{GURL("https://example2.com"), false},
{GURL("https://m.example2.com"), false},
{GURL("https://example2.com/foo.html"), false},
{GURL("https://m.foo.com"), true},
{GURL("https://en.m.foo.com"), true},
{GURL("https://m.en.foo.com"), false},
{GURL("https://m.foo.com/foo.html"), true},
{GURL("https://m.foo.com/foo/bar/baz.html"), true},
{GURL("https://foo.com"), false},
{GURL("https://en.foo.com"), false},
{GURL("https://m.foo2.com"), false},
{GURL("https://en.foo2.com"), false},
};
for (const auto& test : test_cases) {
EXPECT_TRUE(test.url.is_valid());
EXPECT_EQ(test.expect_whitelisted,
page_host_activation_list_->IsHostWhitelistedAtNavigation(
test.url, PreviewsType::RESOURCE_LOADING_HINTS))
<< " url=" << test.url.spec();
}
}
} // namespace
} // namespace previews
\ No newline at end of file
// Copyright 2018 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 "components/previews/content/hint_cache.h"
#include "url/gurl.h"
namespace previews {
// Realistic minimum length of a host suffix.
const int kMinHostSuffix = 6; // eg., abc.tv
HintCache::HintCache() {
DETACH_FROM_SEQUENCE(sequence_checker_);
}
HintCache::~HintCache() {}
bool HintCache::HasHint(const std::string& host) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return !DetermineHostSuffix(host).empty();
}
void HintCache::LoadHint(const std::string& host) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// TODO(dougarnett): Add backing store support to load from.
}
bool HintCache::IsHintLoaded(const std::string& host) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::string host_suffix = DetermineHostSuffix(host);
if (host_suffix.empty()) {
return false;
}
return memory_cache_.find(host_suffix) != memory_cache_.end();
}
const optimization_guide::proto::Hint* HintCache::GetHint(
const std::string& host) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::string host_suffix = DetermineHostSuffix(host);
if (host_suffix.empty()) {
return nullptr;
}
auto it = memory_cache_.find(host_suffix);
if (it != memory_cache_.end()) {
return &it->second;
}
return nullptr;
}
void HintCache::AddHint(const optimization_guide::proto::Hint& hint) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(optimization_guide::proto::HOST_SUFFIX, hint.key_representation());
activation_list_.insert(hint.key());
// TODO(dougarnett): Limit size of memory cache.
memory_cache_[hint.key()] = hint;
}
void HintCache::AddHints(
const std::vector<optimization_guide::proto::Hint>& hints) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
for (auto hint : hints) {
AddHint(hint);
}
}
std::string HintCache::DetermineHostSuffix(const std::string& host) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::string suffix(host);
// Look for longest host name suffix that has a hint. No need to continue
// lookups and substring work once get to a root domain like ".com" or
// ".co.in" (MinHostSuffix length check is a heuristic for that).
while (suffix.length() >= kMinHostSuffix) {
if (activation_list_.find(suffix) != activation_list_.end()) {
return suffix;
}
size_t pos = suffix.find_first_of('.');
if (pos == std::string::npos) {
return std::string();
}
suffix = suffix.substr(pos + 1);
}
return std::string();
}
} // namespace previews
// Copyright 2018 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.
#ifndef COMPONENTS_PREVIEWS_CONTENT_HINT_CACHE_H_
#define COMPONENTS_PREVIEWS_CONTENT_HINT_CACHE_H_
#include <map>
#include <string>
#include <unordered_set>
#include <vector>
#include "base/macros.h"
#include "base/sequence_checker.h"
#include "components/optimization_guide/proto/hints.pb.h"
namespace previews {
// Holds a set of optimization hints received from the Cacao service.
// This may include hints received from the ComponentUpdater and hints
// fetched from a Cacao Optimization Guide Service API. It will hold
// the host suffix keys of all cached hints (aka, activation list). It
// will manage a set of the associated hints details in memory and all
// of the hints in a persisted backing store.
class HintCache {
public:
HintCache();
~HintCache();
// Returns whether the cache has a hint data for |host| locally (whether
// in memory or persisted on disk).
bool HasHint(const std::string& host) const;
// Requests that hint data for |host| be loaded from disk.
void LoadHint(const std::string& host);
// Returns whether there is hint data available for |host| in memory.
bool IsHintLoaded(const std::string& host);
// Returns the hint data for |host| found in memory, otherwise nullptr.
const optimization_guide::proto::Hint* GetHint(const std::string& host) const;
// Adds |hint| to the cache.
void AddHint(const optimization_guide::proto::Hint& hint);
// Adds |hints| to the cache.
void AddHints(const std::vector<optimization_guide::proto::Hint>& hints);
private:
// Returns the most specific host suffix of the host name that is present
// in the activation list.
std::string DetermineHostSuffix(const std::string& host) const;
// The set of host suffixes that have Hint data.
std::unordered_set<std::string> activation_list_;
// The in-memory cache of hints. Maps host suffix to Hint proto.
// TODO(dougarnett): Add MRU subset support (mru_cache) with backing store.
std::map<std::string, optimization_guide::proto::Hint> memory_cache_;
// TODO(dougarnett): Add a backing store with all hints.
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(HintCache);
};
} // namespace previews
#endif // COMPONENTS_PREVIEWS_CONTENT_HINT_CACHE_H_
// Copyright 2018 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 "components/previews/content/hint_cache.h"
#include <string>
#include <vector>
#include "base/macros.h"
#include "components/previews/core/previews_experiments.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace previews {
namespace {
class HintCacheTest : public testing::Test {
public:
HintCacheTest() {}
~HintCacheTest() override {}
DISALLOW_COPY_AND_ASSIGN(HintCacheTest);
};
TEST_F(HintCacheTest, TestMemoryCache) {
HintCache hint_cache;
optimization_guide::proto::Hint hint1;
hint1.set_key("subdomain.domain.org");
hint1.set_key_representation(optimization_guide::proto::HOST_SUFFIX);
optimization_guide::proto::Hint hint2;
hint2.set_key("host.domain.org");
hint2.set_key_representation(optimization_guide::proto::HOST_SUFFIX);
optimization_guide::proto::Hint hint3;
hint3.set_key("otherhost.subdomain.domain.org");
hint3.set_key_representation(optimization_guide::proto::HOST_SUFFIX);
hint_cache.AddHint(hint1);
hint_cache.AddHint(hint2);
hint_cache.AddHint(hint3);
// Not matched
EXPECT_FALSE(hint_cache.HasHint("domain.org"));
EXPECT_FALSE(hint_cache.HasHint("othersubdomain.domain.org"));
// Matched
EXPECT_TRUE(hint_cache.HasHint("otherhost.subdomain.domain.org"));
EXPECT_TRUE(hint_cache.HasHint("host.subdomain.domain.org"));
EXPECT_TRUE(hint_cache.HasHint("subhost.host.subdomain.domain.org"));
// Cached in memory
EXPECT_TRUE(hint_cache.IsHintLoaded("host.domain.org"));
EXPECT_TRUE(hint_cache.IsHintLoaded("otherhost.subdomain.domain.org"));
EXPECT_TRUE(hint_cache.IsHintLoaded("host.subdomain.domain.org"));
EXPECT_TRUE(hint_cache.IsHintLoaded("subhost.host.subdomain.domain.org"));
// Matched key
EXPECT_EQ(hint2.key(), hint_cache.GetHint("host.domain.org")->key());
EXPECT_EQ(hint3.key(),
hint_cache.GetHint("otherhost.subdomain.domain.org")->key());
EXPECT_EQ(hint1.key(),
hint_cache.GetHint("host.subdomain.domain.org")->key());
}
} // namespace
} // namespace previews
......@@ -14,6 +14,7 @@
#include "base/optional.h"
#include "components/optimization_guide/optimization_guide_service_observer.h"
#include "components/previews/core/previews_features.h"
#include "url/gurl.h"
namespace previews {
......@@ -69,6 +70,14 @@ bool CreateSentinelFile(const base::FilePath& sentinel_path,
return true;
}
// Deletes the sentinel file. This should be done once processing the
// configuration is complete and should be done in the background (e.g.,
// same task as Hints.CreateFromConfig).
void DeleteSentinelFile(const base::FilePath& sentinel_path) {
if (!base::DeleteFile(sentinel_path, false /* recursive */))
DLOG(ERROR) << "Error deleting sentinel file";
}
// Enumerates the possible outcomes of processing previews hints. Used in UMA
// histograms, so the order of enumerators should not be changed.
//
......@@ -97,20 +106,39 @@ ConvertProtoOptimizationTypeToPreviewsOptimizationType(
}
}
// Returns whether any features using page hints are enabled.
bool ShouldProcessPageHints() {
return previews::params::IsResourceLoadingHintsEnabled();
}
bool IsDisabledExperimentalOptimization(
const optimization_guide::proto::Optimization& optimization) {
// If this optimization has been marked with an experiment name, consider it
// disabled unless an experiment with that name is running. Experiment names
// are configured with the experiment_name parameter to the
// kOptimizationHintsExperiments feature.
//
// If kOptimizationHintsExperiments is disabled, getting the param value
// returns an empty string. Since experiment names are not allowed to be
// empty strings, all experiments will be disabled if the feature is
// disabled.
if (optimization.has_experiment_name() &&
!optimization.experiment_name().empty() &&
optimization.experiment_name() !=
base::GetFieldTrialParamValueByFeature(
features::kOptimizationHintsExperiments,
features::kOptimizationHintsExperimentNameParam)) {
return true;
}
return false;
}
void RecordProcessHintsResult(PreviewsProcessHintsResult result) {
UMA_HISTOGRAM_ENUMERATION("Previews.ProcessHintsResult",
static_cast<int>(result),
static_cast<int>(PreviewsProcessHintsResult::MAX));
}
// Deletes the sentinel file. This should be done once processing the
// configuration is complete and should be done in the background (e.g.,
// same task as Hints.CreateFromConfig).
void DeleteSentinelFile(const base::FilePath& sentinel_path) {
if (!base::DeleteFile(sentinel_path, false /* recursive */))
DLOG(ERROR) << "Error deleting sentinel file";
}
} // namespace
PreviewsHints::PreviewsHints() {
......@@ -145,8 +173,6 @@ std::unique_ptr<PreviewsHints> PreviewsHints::CreateFromConfig(
url_matcher::URLMatcherConditionSet::Vector all_conditions;
std::set<std::string> seen_host_suffixes;
std::vector<std::string> activation_list;
// Process hint configuration.
for (const auto hint : config.hints()) {
// We only support host suffixes at the moment. Skip anything else.
......@@ -167,24 +193,11 @@ std::unique_ptr<PreviewsHints> PreviewsHints::CreateFromConfig(
seen_host_suffixes.insert(hint.key());
// Create whitelist condition set out of the optimizations that are
// whitelisted for the host suffix.
// whitelisted for the host suffix at the top level (i.e., not within
// PageHints).
std::set<std::pair<PreviewsType, int>> whitelisted_optimizations;
for (const auto optimization : hint.whitelisted_optimizations()) {
// If this optimization has been marked with an experiment name, skip it
// unless an experiment with that name is running. Experiment names are
// configured with the experiment_name parameter to the
// kOptimizationHintsExperiments feature.
//
// If kOptimizationHintsExperiments is disabled, getting the param value
// returns an empty string. Since experiment names are not allowed to be
// empty strings, all experiments will be disabled if the feature is
// disabled.
if (optimization.has_experiment_name() &&
!optimization.experiment_name().empty() &&
optimization.experiment_name() !=
base::GetFieldTrialParamValueByFeature(
features::kOptimizationHintsExperiments,
features::kOptimizationHintsExperimentNameParam)) {
if (IsDisabledExperimentalOptimization(optimization)) {
continue;
}
base::Optional<PreviewsType> previews_type =
......@@ -193,10 +206,6 @@ std::unique_ptr<PreviewsHints> PreviewsHints::CreateFromConfig(
if (previews_type.has_value()) {
whitelisted_optimizations.insert(std::make_pair(
previews_type.value(), optimization.inflation_percent()));
if (previews_type == previews::PreviewsType::RESOURCE_LOADING_HINTS) {
activation_list.push_back(hint.key());
}
}
}
url_matcher::URLMatcherCondition condition =
......@@ -205,9 +214,13 @@ std::unique_ptr<PreviewsHints> PreviewsHints::CreateFromConfig(
id, std::set<url_matcher::URLMatcherCondition>{condition}));
hints->whitelist_[id] = whitelisted_optimizations;
id++;
// Cache hints that have PageHints.
if (ShouldProcessPageHints() && !hint.page_hints().empty()) {
hints->initial_hints_.push_back(hint);
}
}
hints->url_matcher_.AddConditionSets(all_conditions);
hints->activation_list_ = std::make_unique<ActivationList>(activation_list);
// Completed processing hints data without crashing so clear sentinel.
DeleteSentinelFile(sentinel_path);
......@@ -218,6 +231,16 @@ std::unique_ptr<PreviewsHints> PreviewsHints::CreateFromConfig(
return hints;
}
void PreviewsHints::Initialize() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!initial_hints_.empty()) {
if (!hint_cache_)
hint_cache_ = std::make_unique<HintCache>();
hint_cache_->AddHints(initial_hints_);
initial_hints_.clear();
}
}
bool PreviewsHints::IsWhitelisted(const GURL& url,
PreviewsType type,
int* out_inflation_percent) {
......@@ -247,18 +270,20 @@ bool PreviewsHints::IsWhitelisted(const GURL& url,
return true;
}
}
// TODO(dougarnett): Check the hint cache for whitelisted optmizations too.
return false;
}
bool PreviewsHints::IsHostWhitelistedAtNavigation(
const GURL& url,
previews::PreviewsType type) const {
bool PreviewsHints::MaybeLoadOptimizationHints(const GURL& url) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!activation_list_)
if (!hint_cache_ || !url.has_host())
return false;
return activation_list_->IsHostWhitelistedAtNavigation(url, type);
// TODO(dougarnett): Request loading of hints if not cached in memory.
return hint_cache_->HasHint(url.host());
}
} // namespace previews
......@@ -12,7 +12,7 @@
#include "base/macros.h"
#include "base/sequence_checker.h"
#include "components/optimization_guide/proto/hints.pb.h"
#include "components/previews/content/activation_list.h"
#include "components/previews/content/hint_cache.h"
#include "components/previews/content/previews_hints.h"
#include "components/previews/core/previews_user_data.h"
#include "components/url_matcher/url_matcher.h"
......@@ -35,18 +35,19 @@ class PreviewsHints {
const optimization_guide::proto::Configuration& config,
const optimization_guide::ComponentInfo& info);
void Initialize();
// Whether the URL is whitelisted for the given previews type. If so,
// |out_inflation_percent| will be populated if meta data available for it.
// Note: this is top-level whitelist check which does not include checking
// within PageHints.
bool IsWhitelisted(const GURL& url,
PreviewsType type,
int* out_inflation_percent);
// Whether |url| is whitelisted for previews type |type|. The method may
// make the decision based only on a partial comparison (e.g., only the
// hostname of |url|). As such, the method may return true even if |type|
// can't be used for the previews.
bool IsHostWhitelistedAtNavigation(const GURL& url,
previews::PreviewsType type) const;
// Returns whether |url| may have PageHints and triggers asynchronous load
// of such hints are not currently available synchronously.
bool MaybeLoadOptimizationHints(const GURL& url) const;
private:
PreviewsHints();
......@@ -55,9 +56,8 @@ class PreviewsHints {
// it.
url_matcher::URLMatcher url_matcher_;
// Holds the activation list of hosts extracted from the server hints
// configuration.
std::unique_ptr<ActivationList> activation_list_;
// Holds the hint cache (if any optimizations using it are enabled).
std::unique_ptr<HintCache> hint_cache_;
// A map from the condition set ID to associated whitelist Optimization
// details.
......@@ -65,6 +65,8 @@ class PreviewsHints {
std::set<std::pair<PreviewsType, int>>>
whitelist_;
std::vector<optimization_guide::proto::Hint> initial_hints_;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(PreviewsHints);
......
......@@ -50,14 +50,13 @@ bool PreviewsOptimizationGuide::IsWhitelisted(const net::URLRequest& request,
return true;
}
bool PreviewsOptimizationGuide::IsHostWhitelistedAtNavigation(
const GURL& url,
previews::PreviewsType type) const {
bool PreviewsOptimizationGuide::MaybeLoadOptimizationHints(
const net::URLRequest& request) const {
DCHECK(io_task_runner_->BelongsToCurrentThread());
if (!hints_)
return false;
return hints_->IsHostWhitelistedAtNavigation(url, type);
return hints_->MaybeLoadOptimizationHints(request.url());
}
void PreviewsOptimizationGuide::OnHintsProcessed(
......@@ -76,6 +75,8 @@ void PreviewsOptimizationGuide::UpdateHints(
std::unique_ptr<PreviewsHints> hints) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
hints_ = std::move(hints);
if (hints_)
hints_->Initialize();
}
} // namespace previews
......@@ -15,8 +15,6 @@
#include "components/previews/content/previews_optimization_guide.h"
#include "components/previews/core/previews_experiments.h"
class GURL;
namespace net {
class URLRequest;
} // namespace net
......@@ -48,12 +46,11 @@ class PreviewsOptimizationGuide
virtual bool IsWhitelisted(const net::URLRequest& request,
PreviewsType type) const;
// Whether |url| is whitelisted for previews type |type|. The method may
// make the decision based only on a partial comparison (e.g., only the
// hostname of |url|). As such, the method may return true even if |type|
// can't be used for the previews.
bool IsHostWhitelistedAtNavigation(const GURL& url,
previews::PreviewsType type) const;
// Returns whether |request| may have associated optimization hints
// (specifically, PageHints). If so, but the hints are not available
// synchronously, this method will request that they be loaded (from disk or
// network).
bool MaybeLoadOptimizationHints(const net::URLRequest& request) const;
// optimization_guide::OptimizationGuideServiceObserver implementation:
void OnHintsProcessed(
......
......@@ -102,6 +102,8 @@ class PreviewsOptimizationGuideTest : public testing::Test {
void DoExperimentFlagTest(base::Optional<std::string> experiment_name,
bool expect_enabled);
void InitializeResourceLoadingHints();
private:
base::test::ScopedTaskEnvironment scoped_task_environment_;
base::ScopedTempDir temp_dir_;
......@@ -156,14 +158,6 @@ TEST_F(PreviewsOptimizationGuideTest,
EXPECT_FALSE(
guide()->IsWhitelisted(*CreateRequestWithURL(GURL("https://google.com")),
PreviewsType::NOSCRIPT));
EXPECT_FALSE(guide()->IsHostWhitelistedAtNavigation(
GURL("https://m.facebook.com"), PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsHostWhitelistedAtNavigation(
GURL("https://m.twitter.com/example"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsHostWhitelistedAtNavigation(
GURL("https://google.com"), PreviewsType::RESOURCE_LOADING_HINTS));
}
// Test when resource loading hints are enabled.
......@@ -205,17 +199,6 @@ TEST_F(PreviewsOptimizationGuideTest,
EXPECT_FALSE(
guide()->IsWhitelisted(*CreateRequestWithURL(GURL("https://google.com")),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_TRUE(guide()->IsHostWhitelistedAtNavigation(
GURL("https://m.facebook.com"), PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_TRUE(guide()->IsHostWhitelistedAtNavigation(
GURL("https://m.facebook.com/example.html"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_TRUE(guide()->IsHostWhitelistedAtNavigation(
GURL("https://m.twitter.com/example"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsHostWhitelistedAtNavigation(
GURL("https://google.com"), PreviewsType::RESOURCE_LOADING_HINTS));
}
// Test when both NoScript and resource loading hints are enabled.
......@@ -260,16 +243,6 @@ TEST_F(
EXPECT_FALSE(
guide()->IsWhitelisted(*CreateRequestWithURL(GURL("https://google.com")),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsHostWhitelistedAtNavigation(
GURL("https://m.facebook.com"), PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_TRUE(guide()->IsHostWhitelistedAtNavigation(
GURL("https://m.twitter.com/example"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_TRUE(guide()->IsHostWhitelistedAtNavigation(
GURL("https://m.twitter.com"), PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsHostWhitelistedAtNavigation(
GURL("https://google.com"), PreviewsType::RESOURCE_LOADING_HINTS));
}
// This is a helper function for testing the experiment flags on the config for
......@@ -327,16 +300,11 @@ void PreviewsOptimizationGuideTest::DoExperimentFlagTest(
EXPECT_TRUE(guide()->IsWhitelisted(
*CreateRequestWithURL(GURL("https://m.twitter.com/example")),
PreviewsType::NOSCRIPT));
EXPECT_FALSE(guide()->IsHostWhitelistedAtNavigation(
GURL("https://m.twitter.com/example"),
PreviewsType::RESOURCE_LOADING_HINTS));
// Google (which is not configured at all) should always have both NOSCRIPT
// and RESOURCE_LOADING_HINTS disabled.
EXPECT_FALSE(
guide()->IsWhitelisted(*CreateRequestWithURL(GURL("https://google.com")),
PreviewsType::NOSCRIPT));
EXPECT_FALSE(guide()->IsHostWhitelistedAtNavigation(
GURL("https://google.com"), PreviewsType::RESOURCE_LOADING_HINTS));
}
TEST_F(PreviewsOptimizationGuideTest,
......@@ -610,22 +578,50 @@ TEST_F(PreviewsOptimizationGuideTest, IsWhitelistedWithMultipleHintMatches) {
CreateRequestWithURL(GURL("https://outdoor.sports.yahoo.com"));
// Uses "sports.yahoo.com" match before "yahoo.com" match.
EXPECT_FALSE(guide()->IsWhitelisted(*request5, PreviewsType::NOSCRIPT));
}
EXPECT_FALSE(guide()->IsHostWhitelistedAtNavigation(
GURL("https://yahoo.com"), PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsHostWhitelistedAtNavigation(
GURL("https://m.facebook.com"), PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsHostWhitelistedAtNavigation(
GURL("https://m.twitter.com/example"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsHostWhitelistedAtNavigation(
GURL("https://google.com"), PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsHostWhitelistedAtNavigation(
GURL("https://outdoor.sports.yahoo.com"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsHostWhitelistedAtNavigation(
GURL("https://outdoor.sports.yahoo.com/index.html"),
PreviewsType::RESOURCE_LOADING_HINTS));
// This is a helper function for initializing some ResourceLoading hints.
void PreviewsOptimizationGuideTest::InitializeResourceLoadingHints() {
optimization_guide::proto::Configuration config;
optimization_guide::proto::Hint* hint1 = config.add_hints();
hint1->set_key("somedomain.org");
hint1->set_key_representation(optimization_guide::proto::HOST_SUFFIX);
optimization_guide::proto::PageHint* page_hint1 = hint1->add_page_hints();
page_hint1->set_page_pattern("/news/");
optimization_guide::proto::Optimization* optimization1 =
hint1->add_whitelisted_optimizations();
optimization1->set_optimization_type(
optimization_guide::proto::RESOURCE_LOADING);
ProcessHints(config, "2.0.0");
RunUntilIdle();
}
TEST_F(PreviewsOptimizationGuideTest, MaybeLoadOptimizationHints) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(features::kResourceLoadingHints);
InitializeResourceLoadingHints();
EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
*CreateRequestWithURL(GURL("https://somedomain.org/"))));
EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
*CreateRequestWithURL(GURL("https://www.somedomain.org"))));
EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
*CreateRequestWithURL(GURL("https://www.unknown.com"))));
}
TEST_F(PreviewsOptimizationGuideTest,
MaybeLoadOptimizationHintsWithoutEnabledPageHintsFeature) {
// Without PageHints-oriented feature enabled, never see
// enabled, the optimization should be disabled.
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndDisableFeature(features::kResourceLoadingHints);
InitializeResourceLoadingHints();
EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
*CreateRequestWithURL(GURL("https://www.somedomain.org"))));
}
TEST_F(PreviewsOptimizationGuideTest, RemoveObserverCalledAtDestruction) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment