Commit b40eed3b authored by Jered Gray's avatar Jered Gray Committed by Commit Bot

Strip disabled optimizations when parsing preview hints

The logic in PreviewsHints::CreateFromConfig() has been modified so that
it now strips out optimizations that are disabled and only allows one of
each optimization type within a PageHint. Duplicate types encountered
are also stripped. This makes it so that enabling an experimental
optimization will automatically disable a subsequent optimization of the
same optimization type in the same PageHint. If all optimizations for a
page hint are stripped, then the page hint is also stripped.

This fixes a bug related to disabled page hint optimizations being
usable, as the disabled optimizations will no longer exist in the
hint cache.

As a result of this change, when the total page hints with resource
hints exceeds the cap, the number of page hints added will always
exactly match the cap. This is due to the logic for stripping hints
allowing us to add hints that only include some of their page hints.

A DCHECK has been added verifying that non-resource loading hint
optimizations never contain resource loading hints.

Additionally, the description of |whitelisted_optimizations| for the
PageHint proto has been updated to match expectations that it will be
provided as an ordered list.

Unittests have been added to verify that the stripping is handled
properly and that the number of page hints allowed stops exactly at the
cap. Some issues with unittests in PreviewsOptimizationGuideUnittest
using InitializeMultipleResourceLoadingHints() have also been fixed.

Bug: 900725, 900733
Change-Id: Ic8d8ce2de98e4e2993cab994906c3b2e43c31a22
Reviewed-on: https://chromium-review.googlesource.com/c/1311796Reviewed-by: default avatarDoug Arnett <dougarnett@chromium.org>
Reviewed-by: default avatarTarun Bansal <tbansal@chromium.org>
Commit-Queue: Jered Gray <jegray@chromium.org>
Cr-Commit-Position: refs/heads/master@{#604773}
parent 5d75b735
......@@ -120,8 +120,9 @@ message PageHint {
// The maximum effective connection type threshold for triggering the
// optimization associated with this hint.
optional EffectiveConnectionType max_ect_trigger = 2;
// An unordered set of optimizations that should be whitelisted for this
// page pattern.
// An ordered list of optimizations that should be whitelisted for this page
// pattern. The client uses the first optimization in this list that is
// enabled for it.
repeated Optimization whitelisted_optimizations = 3;
}
......
......@@ -4,9 +4,8 @@
#include "components/previews/content/previews_hints.h"
#include <memory>
#include <array>
#include <string>
#include <utility>
#include "base/files/file.h"
#include "base/files/file_util.h"
......@@ -149,11 +148,6 @@ net::EffectiveConnectionType ConvertProtoEffectiveConnectionType(
}
}
// 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
......@@ -176,6 +170,108 @@ bool IsDisabledExperimentalOptimization(
return false;
}
// If |hint| contains page hints, then this function adds a pared down version
// of the hint to |stripped_hints_with_page_hints|, removing all of the hint's
// top-level optimizations and only retaining the first enabled optimization of
// each preview type within each page hint.
// |total_page_patterns_with_resource_loading_hints_received| and
// |total_resource_loading_hints_received| have their totals updated as
// resource loading hints are encountered.
void MaybeAddHintToStrippedHintsWithPageHints(
const optimization_guide::proto::Hint& hint,
std::vector<optimization_guide::proto::Hint>*
stripped_hints_with_page_hints,
size_t* total_page_patterns_with_resource_loading_hints_received,
size_t* total_resource_loading_hints_received) {
DCHECK(stripped_hints_with_page_hints);
DCHECK(total_page_patterns_with_resource_loading_hints_received);
DCHECK(total_resource_loading_hints_received);
if (hint.page_hints().empty()) {
return;
}
if (previews::params::IsResourceLoadingHintsEnabled()) {
UMA_HISTOGRAM_COUNTS("ResourceLoadingHints.PageHints.ProcessedCount",
hint.page_hints().size());
}
// |stripped_hint| is a copy of |hint| with top-level optimizations and
// disabled experimental optimizations within the page hints stripped out.
optimization_guide::proto::Hint stripped_hint;
for (const auto& page_hint : hint.page_hints()) {
// Track the preview types encountered for |page_hint|. Only the first
// supported one will be kept for any one preview type.
std::array<bool, static_cast<int>(PreviewsType::LAST)>
encountered_preview_types;
encountered_preview_types.fill(false);
// Initially set the added page hint to nullptr. This will be set the first
// time an enabled optimization is encountered.
optimization_guide::proto::PageHint* added_page_hint = nullptr;
for (const auto& optimization : page_hint.whitelisted_optimizations()) {
if (IsDisabledExperimentalOptimization(optimization)) {
continue;
}
base::Optional<PreviewsType> previews_type =
ConvertProtoOptimizationTypeToPreviewsType(
optimization.optimization_type());
// Only add the first encountered optimization of a previews type.
if (!previews_type ||
encountered_preview_types[static_cast<int>(*previews_type)]) {
continue;
}
encountered_preview_types[static_cast<int>(*previews_type)] = true;
// If this is a resource loading hints optimization, then add it to the
// resource loading hints totals.
if (previews_type == PreviewsType::RESOURCE_LOADING_HINTS) {
// Always skip over resource loading hints when they're disabled.
if (!previews::params::IsResourceLoadingHintsEnabled()) {
continue;
}
(*total_page_patterns_with_resource_loading_hints_received)++;
(*total_resource_loading_hints_received) +=
optimization.resource_loading_hints_size();
// If the total page patterns with resource loading hints has reached
// the cap, then no additional resource loading hints optimizations can
// be added to page hints.
if (*total_page_patterns_with_resource_loading_hints_received >
previews::params::GetMaxPageHintsInMemoryThreshhold()) {
continue;
}
} else {
DCHECK_EQ(optimization.resource_loading_hints_size(), 0);
}
// If this page hint hasn't been added to the stripped hint yet, then add
// it now and populate its non-whitelisted optimization fields.
if (!added_page_hint) {
added_page_hint = stripped_hint.add_page_hints();
added_page_hint->set_page_pattern(page_hint.page_pattern());
if (page_hint.has_max_ect_trigger()) {
added_page_hint->set_max_ect_trigger(page_hint.max_ect_trigger());
}
}
auto* added_optimization =
added_page_hint->add_whitelisted_optimizations();
*added_optimization = optimization;
}
}
if (stripped_hint.page_hints_size() > 0) {
stripped_hint.set_key_representation(hint.key_representation());
stripped_hint.set_key(hint.key());
stripped_hints_with_page_hints->push_back(stripped_hint);
}
}
void RecordProcessHintsResult(PreviewsProcessHintsResult result) {
base::UmaHistogramEnumeration("Previews.ProcessHintsResult", result);
}
......@@ -222,33 +318,35 @@ std::unique_ptr<PreviewsHints> PreviewsHints::CreateFromConfig(
url_matcher::URLMatcherConditionSet::Vector all_conditions;
std::set<std::string> seen_host_suffixes;
size_t total_resource_loading_hints_received = 0;
size_t total_page_patterns_with_resource_loading_hints_received = 0;
size_t total_resource_loading_hints_received = 0;
// Process hint configuration.
for (const auto hint : config.hints()) {
for (const auto& hint : config.hints()) {
// We only support host suffixes at the moment. Skip anything else.
// One |hint| applies to one host URL suffix.
if (hint.key_representation() != optimization_guide::proto::HOST_SUFFIX)
continue;
const std::string& hint_key = hint.key();
// Validate configuration keys.
DCHECK(!hint.key().empty());
if (hint.key().empty())
DCHECK(!hint_key.empty());
if (hint_key.empty())
continue;
auto seen_host_suffixes_iter = seen_host_suffixes.find(hint.key());
auto seen_host_suffixes_iter = seen_host_suffixes.find(hint_key);
DCHECK(seen_host_suffixes_iter == seen_host_suffixes.end());
if (seen_host_suffixes_iter != seen_host_suffixes.end()) {
DLOG(WARNING) << "Received config with duplicate key";
continue;
}
seen_host_suffixes.insert(hint.key());
seen_host_suffixes.insert(hint_key);
// Create whitelist condition set out of the optimizations that are
// 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()) {
for (const auto& optimization : hint.whitelisted_optimizations()) {
if (IsDisabledExperimentalOptimization(optimization)) {
continue;
}
......@@ -267,52 +365,31 @@ std::unique_ptr<PreviewsHints> PreviewsHints::CreateFromConfig(
}
url_matcher::URLMatcherCondition condition =
condition_factory->CreateHostSuffixCondition(hint.key());
condition_factory->CreateHostSuffixCondition(hint_key);
all_conditions.push_back(new url_matcher::URLMatcherConditionSet(
id, std::set<url_matcher::URLMatcherCondition>{condition}));
hints->whitelist_[id] = whitelisted_optimizations;
id++;
// Cache hints that have PageHints.
if (ShouldProcessPageHints() && !hint.page_hints().empty()) {
UMA_HISTOGRAM_COUNTS("ResourceLoadingHints.PageHints.ProcessedCount",
hint.page_hints().size());
for (const auto& page_hint : hint.page_hints()) {
for (const auto& optimization : page_hint.whitelisted_optimizations()) {
if (IsDisabledExperimentalOptimization(optimization)) {
// This is an experimental optimization that is not enabled so
// continue in case there is a non-experimental one.
continue;
}
base::Optional<PreviewsType> previews_type =
ConvertProtoOptimizationTypeToPreviewsType(
optimization.optimization_type());
if (!previews_type ||
previews_type != PreviewsType::RESOURCE_LOADING_HINTS) {
continue;
}
total_page_patterns_with_resource_loading_hints_received++;
total_resource_loading_hints_received +=
optimization.resource_loading_hints().size();
}
}
if (total_page_patterns_with_resource_loading_hints_received <=
previews::params::GetMaxPageHintsInMemoryThreshhold()) {
hints->initial_hints_.push_back(hint);
}
}
// If this hint contains page hints, then add a pared down version of the
// hint to the initial hints that are used to populate the hint cache,
// removing all of the hint's top-level optimizations and only retaining the
// first enabled optimization of each preview type within each page hint.
MaybeAddHintToStrippedHintsWithPageHints(
hint, &hints->initial_hints_,
&total_page_patterns_with_resource_loading_hints_received,
&total_resource_loading_hints_received);
}
if (ShouldProcessPageHints()) {
UMA_HISTOGRAM_COUNTS_100000(
"ResourceLoadingHints.ResourceHints.TotalReceived",
total_resource_loading_hints_received);
if (previews::params::IsResourceLoadingHintsEnabled()) {
UMA_HISTOGRAM_COUNTS_1000(
"ResourceLoadingHints.PageHints.TotalReceived",
total_page_patterns_with_resource_loading_hints_received);
UMA_HISTOGRAM_COUNTS_100000(
"ResourceLoadingHints.ResourceHints.TotalReceived",
total_resource_loading_hints_received);
}
if (!all_conditions.empty()) {
hints->url_matcher_.AddConditionSets(all_conditions);
}
......@@ -505,11 +582,8 @@ bool PreviewsHints::IsWhitelistedInPageHints(
matched_page_hint->whitelisted_optimizations()) {
if (ConvertProtoOptimizationTypeToPreviewsType(
optimization.optimization_type()) == type) {
if (IsDisabledExperimentalOptimization(optimization)) {
// This is an experimental optimization that is not enabled so continue
// in case there is a non-experimental one.
continue;
}
// TODO(jegray): When persistence is added for hints, address handling of
// disabled experimental optimizations.
// Found whitelisted optimization.
*out_inflation_percent = optimization.inflation_percent();
if (matched_page_hint->has_max_ect_trigger()) {
......
......@@ -8,6 +8,8 @@
#include <map>
#include <memory>
#include <set>
#include <utility>
#include <vector>
#include "base/macros.h"
#include "base/sequence_checker.h"
......
......@@ -295,6 +295,11 @@ TEST_F(PreviewsHintsTest, IsWhitelistedOutParams) {
optimization_with_inflation_percent->set_inflation_percent(55);
optimization_with_inflation_percent->set_optimization_type(
optimization_guide::proto::RESOURCE_LOADING);
optimization_guide::proto::ResourceLoadingHint* resource_hint1 =
optimization_with_inflation_percent->add_resource_loading_hints();
resource_hint1->set_loading_optimization_type(
optimization_guide::proto::LOADING_BLOCK_RESOURCE);
resource_hint1->set_resource_pattern("default_resource.js");
// Page hint for "/has_max_ect_trigger/"
optimization_guide::proto::PageHint* page_hint2 = hint1->add_page_hints();
page_hint2->set_page_pattern("/has_max_ect_trigger/");
......@@ -306,6 +311,11 @@ TEST_F(PreviewsHintsTest, IsWhitelistedOutParams) {
page_hint2->add_whitelisted_optimizations();
optimization_without_inflation_percent->set_optimization_type(
optimization_guide::proto::RESOURCE_LOADING);
optimization_guide::proto::ResourceLoadingHint* resource_hint2 =
optimization_without_inflation_percent->add_resource_loading_hints();
resource_hint2->set_loading_optimization_type(
optimization_guide::proto::LOADING_BLOCK_RESOURCE);
resource_hint2->set_resource_pattern("default_resource.js");
ParseConfig(config);
// Verify optimization providing inflation_percent.
......@@ -333,6 +343,32 @@ TEST_F(PreviewsHintsTest, IsWhitelistedOutParams) {
ect_threshold);
}
TEST_F(PreviewsHintsTest,
IsWhitelistedForNoScriptInPageHintsWithResourceLoadingHintsDisabled) {
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);
// Page hint with NOSCRIPT optimization
optimization_guide::proto::PageHint* page_hint1 = hint1->add_page_hints();
page_hint1->set_page_pattern("/has_noscript/");
optimization_guide::proto::Optimization* optimization_with_inflation_percent =
page_hint1->add_whitelisted_optimizations();
optimization_with_inflation_percent->set_optimization_type(
optimization_guide::proto::NOSCRIPT);
ParseConfig(config);
int inflation_percent = 0;
net::EffectiveConnectionType ect_threshold =
net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
EXPECT_TRUE(previews_hints()->IsWhitelisted(
GURL("https://www.somedomain.org/has_noscript/"), PreviewsType::NOSCRIPT,
&inflation_percent, &ect_threshold));
}
TEST_F(PreviewsHintsTest, IsWhitelistedForExperimentalPreview) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(features::kResourceLoadingHints);
......@@ -371,28 +407,45 @@ TEST_F(PreviewsHintsTest, IsWhitelistedForExperimentalPreview) {
default_resourcehint->set_loading_optimization_type(
optimization_guide::proto::LOADING_BLOCK_RESOURCE);
default_resourcehint->set_resource_pattern("experimental_resource.js");
ParseConfig(config);
// Verify default resource hint whitelisted (via inflation_percent).
int inflation_percent = 0;
net::EffectiveConnectionType ect_threshold =
net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
EXPECT_TRUE(previews_hints()->IsWhitelisted(
GURL("https://www.somedomain.org/experimental_preview/"
"experimental_resource.js"),
PreviewsType::RESOURCE_LOADING_HINTS, &inflation_percent,
&ect_threshold));
EXPECT_EQ(33, inflation_percent);
EXPECT_EQ(net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_3G,
ect_threshold);
// Test with the experiment disabled.
{
base::HistogramTester histogram_tester;
ParseConfig(config);
// Verify default resource hint whitelisted (via inflation_percent).
int inflation_percent = 0;
net::EffectiveConnectionType ect_threshold =
net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
EXPECT_TRUE(previews_hints()->IsWhitelisted(
GURL("https://www.somedomain.org/experimental_preview/"
"experimental_resource.js"),
PreviewsType::RESOURCE_LOADING_HINTS, &inflation_percent,
&ect_threshold));
EXPECT_EQ(33, inflation_percent);
EXPECT_EQ(net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_3G,
ect_threshold);
// Verify that the experimental optimization was not added when it was
// disabled.
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.ResourceHints.TotalReceived", 1, 1);
}
// Now enable the experiment and verify experimental resource hint chosen.
{
base::HistogramTester histogram_tester;
base::test::ScopedFeatureList scoped_list2;
scoped_list2.InitAndEnableFeatureWithParameters(
features::kOptimizationHintsExperiments,
{{"experiment_name", "foo_experiment"}});
int inflation_percent;
// Parse the config again with the experiment enabled.
ParseConfig(config);
int inflation_percent = 0;
net::EffectiveConnectionType ect_threshold =
net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_2G;
EXPECT_TRUE(previews_hints()->IsWhitelisted(
......@@ -403,6 +456,11 @@ TEST_F(PreviewsHintsTest, IsWhitelistedForExperimentalPreview) {
EXPECT_EQ(99, inflation_percent);
EXPECT_EQ(net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_3G,
ect_threshold);
// Verify that the second optimization was not added when the experimental
// optimization was enabled.
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.ResourceHints.TotalReceived", 1, 1);
}
}
......
......@@ -74,18 +74,23 @@ void PreviewsOptimizationGuide::OnLoadedHint(
std::vector<std::string> resource_patterns_to_block;
for (const auto& optimization :
matched_page_hint->whitelisted_optimizations()) {
if (optimization.optimization_type() ==
if (optimization.optimization_type() !=
optimization_guide::proto::RESOURCE_LOADING) {
for (const auto& resource_loading_hint :
optimization.resource_loading_hints()) {
if (!resource_loading_hint.resource_pattern().empty() &&
resource_loading_hint.loading_optimization_type() ==
optimization_guide::proto::LOADING_BLOCK_RESOURCE) {
resource_patterns_to_block.push_back(
resource_loading_hint.resource_pattern());
}
continue;
}
// TODO(jegray): When persistence is added for hints, address handling of
// disabled experimental optimizations.
for (const auto& resource_loading_hint :
optimization.resource_loading_hints()) {
if (!resource_loading_hint.resource_pattern().empty() &&
resource_loading_hint.loading_optimization_type() ==
optimization_guide::proto::LOADING_BLOCK_RESOURCE) {
resource_patterns_to_block.push_back(
resource_loading_hint.resource_pattern());
}
}
break;
}
if (!resource_patterns_to_block.empty()) {
std::move(callback).Run(document_url, resource_patterns_to_block);
......
......@@ -121,6 +121,10 @@ class PreviewsOptimizationGuideTest : public testing::Test {
// hints.
void InitializeFixedCountResourceLoadingHints();
// This is a helper function for initializing fixed number of ResourceLoading
// hints that contain an experiment
void InitializeFixedCountResourceLoadingHintsWithTwoExperiments();
// This is a helper function for initializing multiple ResourceLoading hints.
// The generated hint proto contains hints for |key_count| keys.
// |page_patterns_per_key| page patterns are specified per key.
......@@ -187,6 +191,43 @@ void PreviewsOptimizationGuideTest::InitializeFixedCountResourceLoadingHints() {
RunUntilIdle();
}
void PreviewsOptimizationGuideTest::
InitializeFixedCountResourceLoadingHintsWithTwoExperiments() {
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);
// Page hint for "/news/"
optimization_guide::proto::PageHint* page_hint1 = hint1->add_page_hints();
page_hint1->set_page_pattern("/news/");
optimization_guide::proto::Optimization* optimization1 =
page_hint1->add_whitelisted_optimizations();
optimization1->set_experiment_name("experiment_1");
optimization1->set_optimization_type(
optimization_guide::proto::RESOURCE_LOADING);
optimization_guide::proto::ResourceLoadingHint* resource_loading_hint1 =
optimization1->add_resource_loading_hints();
resource_loading_hint1->set_loading_optimization_type(
optimization_guide::proto::LOADING_BLOCK_RESOURCE);
resource_loading_hint1->set_resource_pattern("news_cruft.js");
optimization_guide::proto::Optimization* optimization2 =
page_hint1->add_whitelisted_optimizations();
optimization2->set_experiment_name("experiment_2");
optimization2->set_optimization_type(
optimization_guide::proto::RESOURCE_LOADING);
optimization_guide::proto::ResourceLoadingHint* resource_loading_hint2 =
optimization2->add_resource_loading_hints();
resource_loading_hint2->set_loading_optimization_type(
optimization_guide::proto::LOADING_BLOCK_RESOURCE);
resource_loading_hint2->set_resource_pattern("football_cruft.js");
ProcessHints(config, "2.0.0");
RunUntilIdle();
}
void PreviewsOptimizationGuideTest::InitializeMultipleResourceLoadingHints(
size_t key_count,
size_t page_patterns_per_key) {
......@@ -201,8 +242,8 @@ void PreviewsOptimizationGuideTest::InitializeMultipleResourceLoadingHints(
page_pattern_index < page_patterns_per_key; ++page_pattern_index) {
// Page hint for "/news/"
optimization_guide::proto::PageHint* page_hint = hint->add_page_hints();
page_hint->set_page_pattern("/news/" +
base::NumberToString(page_pattern_index));
page_hint->set_page_pattern(
"/news" + base::NumberToString(page_pattern_index) + "/");
optimization_guide::proto::Optimization* optimization1 =
page_hint->add_whitelisted_optimizations();
optimization1->set_optimization_type(
......@@ -306,6 +347,11 @@ TEST_F(PreviewsOptimizationGuideTest,
page_hint1->add_whitelisted_optimizations();
optimization1->set_optimization_type(
optimization_guide::proto::RESOURCE_LOADING);
optimization_guide::proto::ResourceLoadingHint* resource_hint1 =
optimization1->add_resource_loading_hints();
resource_hint1->set_loading_optimization_type(
optimization_guide::proto::LOADING_BLOCK_RESOURCE);
resource_hint1->set_resource_pattern("resource.js");
// Add additional optimizations to ensure that the applicable optimizations
// are still whitelisted.
......@@ -330,6 +376,11 @@ TEST_F(PreviewsOptimizationGuideTest,
page_hint3->add_whitelisted_optimizations();
optimization4->set_optimization_type(
optimization_guide::proto::RESOURCE_LOADING);
optimization_guide::proto::ResourceLoadingHint* resource_hint2 =
optimization4->add_resource_loading_hints();
resource_hint2->set_loading_optimization_type(
optimization_guide::proto::LOADING_BLOCK_RESOURCE);
resource_hint2->set_resource_pattern("resource.js");
ProcessHints(config, "2.0.0");
......@@ -378,6 +429,11 @@ TEST_F(
page_hint1->add_whitelisted_optimizations();
optimization3->set_optimization_type(
optimization_guide::proto::RESOURCE_LOADING);
optimization_guide::proto::ResourceLoadingHint* resource_hint1 =
optimization3->add_resource_loading_hints();
resource_hint1->set_loading_optimization_type(
optimization_guide::proto::LOADING_BLOCK_RESOURCE);
resource_hint1->set_resource_pattern("resource.js");
ProcessHints(config, "2.0.0");
......@@ -422,13 +478,18 @@ void PreviewsOptimizationGuideTest::DoExperimentFlagTest(
}
optimization1->set_optimization_type(optimization_guide::proto::NOSCRIPT);
// RESOURCE_LOADING is never marked experimental.
// RESOURCE_LOADING is not marked experimental.
optimization_guide::proto::PageHint* page_hint1 = hint1->add_page_hints();
page_hint1->set_page_pattern("*");
optimization_guide::proto::Optimization* optimization2 =
page_hint1->add_whitelisted_optimizations();
optimization2->set_optimization_type(
optimization_guide::proto::RESOURCE_LOADING);
optimization_guide::proto::ResourceLoadingHint* resource_hint1 =
optimization2->add_resource_loading_hints();
resource_hint1->set_loading_optimization_type(
optimization_guide::proto::LOADING_BLOCK_RESOURCE);
resource_hint1->set_resource_pattern("resource.js");
// Add a second, non-experimental hint.
optimization_guide::proto::Hint* hint2 = config.add_hints();
......@@ -776,53 +837,275 @@ TEST_F(PreviewsOptimizationGuideTest, MaybeLoadOptimizationHints) {
PreviewsType::RESOURCE_LOADING_HINTS));
}
// Test that optimization hints with multiple page patterns is processed
// correctly.
TEST_F(PreviewsOptimizationGuideTest,
LoadManyResourceLoadingOptimizationHints) {
MaybeLoadPageHintsWithTwoExperimentsDisabled) {
base::HistogramTester histogram_tester;
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(features::kResourceLoadingHints);
const size_t key_count = 20;
const size_t page_patterns_per_key = 25;
InitializeFixedCountResourceLoadingHintsWithTwoExperiments();
ASSERT_EQ(previews::params::GetMaxPageHintsInMemoryThreshhold(),
key_count * page_patterns_per_key);
EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
GURL("https://somedomain.org/"), base::DoNothing()));
EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
GURL("https://www.somedomain.org/news/football"),
base::BindOnce(
&PreviewsOptimizationGuideTest::MaybeLoadOptimizationHintsCallback,
base::Unretained(this))));
EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
GURL("https://www.unknown.com"), base::DoNothing()));
// Count of page patterns is within the threshold.
ASSERT_LE(key_count * page_patterns_per_key,
previews::params::GetMaxPageHintsInMemoryThreshhold());
RunUntilIdle();
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.PageHints.ProcessedCount", 1, 1);
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.ResourceHints.TotalReceived", 0, 1);
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.PageHints.TotalReceived", 0, 1);
InitializeMultipleResourceLoadingHints(key_count, page_patterns_per_key);
// Verify loaded hint data for www.somedomain.org
EXPECT_EQ(GURL(), loaded_hints_document_gurl());
EXPECT_EQ(0ul, loaded_hints_resource_patterns().size());
PreviewsUserData user_data(kDefaultPageId);
// Verify whitelisting from loaded page hints.
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data,
GURL("https://www.somedomain.org/news/weather/raininginseattle"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data,
GURL("https://www.somedomain.org/football/seahawksrebuildingyear"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain.org/unhinted"),
PreviewsType::RESOURCE_LOADING_HINTS));
}
TEST_F(PreviewsOptimizationGuideTest,
MaybeLoadPageHintsWithFirstExperimentEnabled) {
base::HistogramTester histogram_tester;
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(features::kResourceLoadingHints);
base::test::ScopedFeatureList scoped_list2;
scoped_list2.InitAndEnableFeatureWithParameters(
features::kOptimizationHintsExperiments,
{{"experiment_name", "experiment_1"}});
InitializeFixedCountResourceLoadingHintsWithTwoExperiments();
EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
GURL("https://somedomain0.org/"), base::DoNothing()));
GURL("https://somedomain.org/"), base::DoNothing()));
EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
GURL("https://www.somedomain0.org/news0/football"),
GURL("https://www.somedomain.org/news/football"),
base::BindOnce(
&PreviewsOptimizationGuideTest::MaybeLoadOptimizationHintsCallback,
base::Unretained(this))));
EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
GURL("https://www.unknown.com"), base::DoNothing()));
RunUntilIdle();
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.PageHints.ProcessedCount", 1, 1);
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.ResourceHints.TotalReceived", 1, 1);
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.PageHints.TotalReceived", 1, 1);
GURL("https://www.somedomain0.org/news499/football"),
// Verify loaded hint data for www.somedomain.org
EXPECT_EQ(GURL("https://www.somedomain.org/news/football"),
loaded_hints_document_gurl());
EXPECT_EQ(1ul, loaded_hints_resource_patterns().size());
EXPECT_EQ("news_cruft.js", loaded_hints_resource_patterns().front());
PreviewsUserData user_data(kDefaultPageId);
// Verify whitelisting from loaded page hints.
EXPECT_TRUE(guide()->IsWhitelisted(
&user_data,
GURL("https://www.somedomain.org/news/weather/raininginseattle"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data,
GURL("https://www.somedomain.org/football/seahawksrebuildingyear"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain.org/unhinted"),
PreviewsType::RESOURCE_LOADING_HINTS));
}
TEST_F(PreviewsOptimizationGuideTest,
MaybeLoadPageHintsWithSecondExperimentEnabled) {
base::HistogramTester histogram_tester;
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(features::kResourceLoadingHints);
base::test::ScopedFeatureList scoped_list2;
scoped_list2.InitAndEnableFeatureWithParameters(
features::kOptimizationHintsExperiments,
{{"experiment_name", "experiment_2"}});
InitializeFixedCountResourceLoadingHintsWithTwoExperiments();
EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
GURL("https://somedomain.org/"), base::DoNothing()));
EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
GURL("https://www.somedomain.org/news/football"),
base::BindOnce(
&PreviewsOptimizationGuideTest::MaybeLoadOptimizationHintsCallback,
base::Unretained(this))));
EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
GURL("https://www.unknown.com"), base::DoNothing()));
RunUntilIdle();
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.PageHints.ProcessedCount", 1, 1);
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.ResourceHints.TotalReceived", 1, 1);
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.PageHints.TotalReceived", 1, 1);
GURL("https://www.somedomain0.org/news500/football"),
// Verify loaded hint data for www.somedomain.org
EXPECT_EQ(GURL("https://www.somedomain.org/news/football"),
loaded_hints_document_gurl());
EXPECT_EQ(1ul, loaded_hints_resource_patterns().size());
EXPECT_EQ("football_cruft.js", loaded_hints_resource_patterns().front());
PreviewsUserData user_data(kDefaultPageId);
// Verify whitelisting from loaded page hints.
EXPECT_TRUE(guide()->IsWhitelisted(
&user_data,
GURL("https://www.somedomain.org/news/weather/raininginseattle"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data,
GURL("https://www.somedomain.org/football/seahawksrebuildingyear"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain.org/unhinted"),
PreviewsType::RESOURCE_LOADING_HINTS));
}
TEST_F(PreviewsOptimizationGuideTest,
MaybeLoadPageHintsWithBothExperimentEnabled) {
base::HistogramTester histogram_tester;
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(features::kResourceLoadingHints);
base::test::ScopedFeatureList scoped_list2;
scoped_list2.InitAndEnableFeatureWithParameters(
features::kOptimizationHintsExperiments,
{{"experiment_name", "experiment_1"},
{"experiment_name", "experiment_2"}});
InitializeFixedCountResourceLoadingHintsWithTwoExperiments();
EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
GURL("https://somedomain.org/"), base::DoNothing()));
EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
GURL("https://www.somedomain.org/news/football"),
base::BindOnce(
&PreviewsOptimizationGuideTest::MaybeLoadOptimizationHintsCallback,
base::Unretained(this))));
EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
GURL("https://www.unknown.com"), base::DoNothing()));
RunUntilIdle();
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.PageHints.ProcessedCount", 1, 1);
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.ResourceHints.TotalReceived", 1, 1);
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.PageHints.TotalReceived", 1, 1);
// Verify loaded hint data for www.somedomain.org
EXPECT_EQ(GURL("https://www.somedomain.org/news/football"),
loaded_hints_document_gurl());
EXPECT_EQ(1ul, loaded_hints_resource_patterns().size());
EXPECT_EQ("news_cruft.js", loaded_hints_resource_patterns().front());
PreviewsUserData user_data(kDefaultPageId);
// Verify whitelisting from loaded page hints.
EXPECT_TRUE(guide()->IsWhitelisted(
&user_data,
GURL("https://www.somedomain.org/news/weather/raininginseattle"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data,
GURL("https://www.somedomain.org/football/seahawksrebuildingyear"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain.org/unhinted"),
PreviewsType::RESOURCE_LOADING_HINTS));
}
// Test that optimization hints with multiple page patterns is processed
// correctly.
TEST_F(PreviewsOptimizationGuideTest,
LoadManyResourceLoadingOptimizationHints) {
base::HistogramTester histogram_tester;
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(features::kResourceLoadingHints);
const size_t key_count = 20;
const size_t page_patterns_per_key = 25;
PreviewsUserData user_data(kDefaultPageId);
ASSERT_EQ(previews::params::GetMaxPageHintsInMemoryThreshhold(),
key_count * page_patterns_per_key);
// Count of page patterns is within the threshold.
ASSERT_LE(key_count * page_patterns_per_key,
previews::params::GetMaxPageHintsInMemoryThreshhold());
InitializeMultipleResourceLoadingHints(key_count, page_patterns_per_key);
EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
GURL("https://somedomain0.org/"), base::DoNothing()));
EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
GURL("https://somedomain0.org/news0/football"), base::DoNothing()));
EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
GURL("https://somedomain19.org/"), base::DoNothing()));
EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
GURL("https://somedomain19.org/news0/football"), base::DoNothing()));
EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
GURL("https://somedomain20.org/"), base::DoNothing()));
EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
GURL("https://somedomain20.org/news0/football"), base::DoNothing()));
EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
GURL("https://www.unknown.com"), base::DoNothing()));
EXPECT_TRUE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain0.org/news0/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_TRUE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain0.org/news24/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain0.org/news25/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_TRUE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain19.org/news0/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_TRUE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain19.org/news24/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain19.org/news25/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain20.org/news0/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain20.org/news24/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain20.org/news25/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
RunUntilIdle();
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.PageHints.ProcessedCount", page_patterns_per_key,
......@@ -846,6 +1129,8 @@ TEST_F(PreviewsOptimizationGuideTest,
const size_t key_count = 21;
const size_t page_patterns_per_key = 25;
PreviewsUserData user_data(kDefaultPageId);
ASSERT_EQ(previews::params::GetMaxPageHintsInMemoryThreshhold(),
20u * page_patterns_per_key);
......@@ -857,31 +1142,126 @@ TEST_F(PreviewsOptimizationGuideTest,
EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
GURL("https://somedomain0.org/"), base::DoNothing()));
EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
GURL("https://www.somedomain0.org/news0/football"),
base::BindOnce(
&PreviewsOptimizationGuideTest::MaybeLoadOptimizationHintsCallback,
base::Unretained(this))));
EXPECT_TRUE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain0.org/news0/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_TRUE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain0.org/news24/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain0.org/news25/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
GURL("https://somedomain19.org/"), base::DoNothing()));
EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
GURL("https://www.somedomain19.org/news0/football"),
base::BindOnce(
&PreviewsOptimizationGuideTest::MaybeLoadOptimizationHintsCallback,
base::Unretained(this))));
EXPECT_TRUE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain19.org/news0/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_TRUE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain19.org/news24/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain19.org/news25/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
// The last page pattern should be dropped since it exceeds the threshold
// count.
EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
GURL("https://somedomain20.org/"), base::DoNothing()));
EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain20.org/news0/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain20.org/news24/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain20.org/news25/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
GURL("https://www.somedomain20.org/news0/football"),
base::BindOnce(
&PreviewsOptimizationGuideTest::MaybeLoadOptimizationHintsCallback,
base::Unretained(this))));
RunUntilIdle();
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.PageHints.ProcessedCount", page_patterns_per_key,
key_count);
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.ResourceHints.TotalReceived",
key_count * page_patterns_per_key * 2, 1);
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.PageHints.TotalReceived",
key_count * page_patterns_per_key, 1);
}
// Test that only up to GetMaxPageHintsInMemoryThreshhold() page hints
// are loaded to the memory.
TEST_F(PreviewsOptimizationGuideTest,
LoadTooManyResourceLoadingOptimizationHintsWithPartialPageHint) {
base::HistogramTester histogram_tester;
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(features::kResourceLoadingHints);
const size_t key_count = 21;
const size_t page_patterns_per_key = 26;
PreviewsUserData user_data(kDefaultPageId);
// Provide more page patterns than the threshold.
ASSERT_GT(key_count * page_patterns_per_key,
previews::params::GetMaxPageHintsInMemoryThreshhold());
InitializeMultipleResourceLoadingHints(key_count, page_patterns_per_key);
EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
GURL("https://somedomain0.org/"), base::DoNothing()));
EXPECT_TRUE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain0.org/news0/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_TRUE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain0.org/news25/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain0.org/news26/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
// The third to last page pattern has all of its resource loading hints fall
// within the threshold.
EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
GURL("https://somedomain18.org/"), base::DoNothing()));
EXPECT_TRUE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain18.org/news0/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_TRUE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain18.org/news25/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain18.org/news26/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
// The second to last page pattern had some of its resource loading hints
// fall within the threshold.
EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
GURL("https://somedomain19.org/"), base::DoNothing()));
EXPECT_TRUE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain19.org/news0/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain19.org/news25/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain19.org/news26/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
// The last page pattern should be dropped since all of its resource loading
// hints exceeds the threshold count.
EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
GURL("https://somedomain20.org/"), base::DoNothing()));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain20.org/news0/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain20.org/news25/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_FALSE(guide()->IsWhitelisted(
&user_data, GURL("https://www.somedomain20.org/news26/football"),
PreviewsType::RESOURCE_LOADING_HINTS));
RunUntilIdle();
histogram_tester.ExpectUniqueSample(
......
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