blob: 557b56957664025ad686af59f3659f060271a17e [file] [log] [blame]
// 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 <map>
#include <string>
#include <vector>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/metrics/subprocess_metrics_provider.h"
#include "chrome/browser/previews/resource_loading_hints/resource_loading_hints_web_contents_observer.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
#include "components/optimization_guide/hints_component_info.h"
#include "components/optimization_guide/hints_component_util.h"
#include "components/optimization_guide/optimization_guide_constants.h"
#include "components/optimization_guide/optimization_guide_features.h"
#include "components/optimization_guide/optimization_guide_service.h"
#include "components/optimization_guide/proto/hints.pb.h"
#include "components/optimization_guide/test_hints_component_creator.h"
#include "components/previews/core/previews_black_list.h"
#include "components/previews/core/previews_features.h"
#include "components/previews/core/previews_switches.h"
#include "components/ukm/test_ukm_recorder.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/test/browser_test_utils.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/network/public/cpp/network_quality_tracker.h"
#include "third_party/blink/public/common/features.h"
namespace {
constexpr char kMockHost[] = "mock.host";
// Retries fetching |histogram_name| until it contains at least |count| samples.
void RetryForHistogramUntilCountReached(base::HistogramTester* histogram_tester,
const std::string& histogram_name,
size_t count) {
while (true) {
base::ThreadPoolInstance::Get()->FlushForTesting();
base::RunLoop().RunUntilIdle();
content::FetchHistogramsFromChildProcesses();
SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
const std::vector<base::Bucket> buckets =
histogram_tester->GetAllSamples(histogram_name);
size_t total_count = 0;
for (const auto& bucket : buckets) {
total_count += bucket.count;
}
if (total_count >= count) {
break;
}
}
}
} // namespace
// This test class sets up everything but does not enable any features.
class ResourceLoadingNoFeaturesBrowserTest : public InProcessBrowserTest {
public:
ResourceLoadingNoFeaturesBrowserTest() = default;
~ResourceLoadingNoFeaturesBrowserTest() override = default;
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
g_browser_process->network_quality_tracker()
->ReportEffectiveConnectionTypeForTesting(
net::EFFECTIVE_CONNECTION_TYPE_2G);
// Set up https server with resource monitor.
https_server_.reset(
new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTPS));
https_server_->ServeFilesFromSourceDirectory("chrome/test/data/previews");
https_server_->RegisterRequestMonitor(base::BindRepeating(
&ResourceLoadingNoFeaturesBrowserTest::MonitorResourceRequest,
base::Unretained(this)));
ASSERT_TRUE(https_server_->Start());
https_url_ = https_server_->GetURL("/resource_loading_hints.html");
ASSERT_TRUE(https_url_.SchemeIs(url::kHttpsScheme));
https_url_iframe_ =
https_server_->GetURL("/resource_loading_hints_iframe.html");
ASSERT_TRUE(https_url_.SchemeIs(url::kHttpsScheme));
https_url_iframe_preload_ =
https_server_->GetURL("/resource_loading_hints_iframe_preload.html");
ASSERT_TRUE(https_url_.SchemeIs(url::kHttpsScheme));
https_url_preload_ =
https_server_->GetURL("/resource_loading_hints_preload.html");
https_second_url_ =
https_server_->GetURL("/resource_loading_hints_second.html");
ASSERT_TRUE(https_second_url_.SchemeIs(url::kHttpsScheme));
https_no_transform_url_ = https_server_->GetURL(
"/resource_loading_hints_with_no_transform_header.html");
ASSERT_TRUE(https_no_transform_url_.SchemeIs(url::kHttpsScheme));
https_hint_setup_url_ = https_server_->GetURL("/hint_setup.html");
ASSERT_TRUE(https_hint_setup_url_.SchemeIs(url::kHttpsScheme));
ASSERT_EQ(https_hint_setup_url_.host(), https_url_.host());
// Set up http server with resource monitor and redirect handler.
http_server_.reset(
new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTP));
http_server_->ServeFilesFromSourceDirectory("chrome/test/data/previews");
http_server_->RegisterRequestMonitor(base::BindRepeating(
&ResourceLoadingNoFeaturesBrowserTest::MonitorResourceRequest,
base::Unretained(this)));
http_server_->RegisterRequestHandler(base::BindRepeating(
&ResourceLoadingNoFeaturesBrowserTest::HandleRedirectRequest,
base::Unretained(this)));
ASSERT_TRUE(http_server_->Start());
http_url_ = http_server_->GetURL("/resource_loading_hints.html");
ASSERT_TRUE(http_url_.SchemeIs(url::kHttpScheme));
redirect_url_ = http_server_->GetURL("/redirect.html");
ASSERT_TRUE(redirect_url_.SchemeIs(url::kHttpScheme));
http_hint_setup_url_ = http_server_->GetURL("/hint_setup.html");
ASSERT_TRUE(http_hint_setup_url_.SchemeIs(url::kHttpScheme));
ASSERT_EQ(http_hint_setup_url_.host(), http_url_.host());
InProcessBrowserTest::SetUpOnMainThread();
}
void SetUpCommandLine(base::CommandLine* cmd) override {
cmd->AppendSwitch("enable-spdy-proxy-auth");
cmd->AppendSwitch("optimization-guide-disable-installer");
// Needed so that the browser can connect to kMockHost.
cmd->AppendSwitch("ignore-certificate-errors");
cmd->AppendSwitch("purge_hint_cache_store");
// Due to race conditions, it's possible that blacklist data is not loaded
// at the time of first navigation. That may prevent Preview from
// triggering, and causing the test to flake.
cmd->AppendSwitch(previews::switches::kIgnorePreviewsBlacklist);
}
// Creates hint data from the |component_info| and waits for it to be fully
// processed before returning.
void ProcessHintsComponent(
const optimization_guide::HintsComponentInfo& component_info) {
base::HistogramTester histogram_tester;
g_browser_process->optimization_guide_service()->MaybeUpdateHintsComponent(
component_info);
RetryForHistogramUntilCountReached(
&histogram_tester,
optimization_guide::kComponentHintsUpdatedResultHistogramString, 1);
}
void InitializeOptimizationHints() {
ProcessHintsComponent(
test_hints_component_creator_.CreateHintsComponentInfoWithPageHints(
optimization_guide::proto::RESOURCE_LOADING, {"doesntmatter.com"},
"*", {}));
}
// Performs a navigation to |url| and waits for the the url's host's hints to
// load before returning. This ensures that the hints will be available in the
// hint cache for a subsequent navigation to a test url with the same host.
void LoadHintsForUrl(const GURL& url) {
base::HistogramTester histogram_tester;
// Navigate to |hint_setup_url| to prime the OptimizationGuide hints for the
// url's host and ensure that they have been loaded from the store (via
// histogram) prior to the navigation that tests functionality.
ui_test_utils::NavigateToURL(browser(), url);
RetryForHistogramUntilCountReached(
&histogram_tester, optimization_guide::kLoadedHintLocalHistogramString,
1);
}
void SetDefaultOnlyResourceLoadingHints(const GURL& hint_setup_url) {
SetDefaultOnlyResourceLoadingHintsWithPagePattern(hint_setup_url, "*");
}
void SetDefaultOnlyResourceLoadingHintsWithPagePattern(
const GURL& hint_setup_url,
const std::string& page_pattern) {
std::vector<std::string> resource_patterns;
resource_patterns.push_back("foo.jpg");
resource_patterns.push_back("png");
resource_patterns.push_back("woff2");
ProcessHintsComponent(
test_hints_component_creator_.CreateHintsComponentInfoWithPageHints(
optimization_guide::proto::RESOURCE_LOADING,
{hint_setup_url.host(), kMockHost}, page_pattern,
resource_patterns));
LoadHintsForUrl(hint_setup_url);
}
// Sets the resource loading hints in optimization guide service. The hints
// are set as experimental.
void SetExperimentOnlyResourceLoadingHints(const GURL& hint_setup_url) {
std::vector<std::string> resource_patterns;
resource_patterns.push_back("foo.jpg");
resource_patterns.push_back("png");
resource_patterns.push_back("woff2");
ProcessHintsComponent(
test_hints_component_creator_
.CreateHintsComponentInfoWithExperimentalPageHints(
optimization_guide::proto::RESOURCE_LOADING,
{hint_setup_url.host()}, resource_patterns));
LoadHintsForUrl(hint_setup_url);
}
// Sets the resource loading hints in optimization guide service. Some hints
// are set as experimental, while others are set as default.
void SetMixResourceLoadingHints(const GURL& hint_setup_url) {
std::vector<std::string> experimental_resource_patterns;
experimental_resource_patterns.push_back("foo.jpg");
experimental_resource_patterns.push_back("png");
experimental_resource_patterns.push_back("woff2");
std::vector<std::string> default_resource_patterns;
default_resource_patterns.push_back("bar.jpg");
default_resource_patterns.push_back("woff2");
ProcessHintsComponent(
test_hints_component_creator_.CreateHintsComponentInfoWithMixPageHints(
optimization_guide::proto::RESOURCE_LOADING,
{hint_setup_url.host()}, experimental_resource_patterns,
default_resource_patterns));
LoadHintsForUrl(hint_setup_url);
}
virtual const GURL& https_url() const { return https_url_; }
// URL that loads blocked resources uses link-rel preload in <head>.
const GURL& https_url_preload() const { return https_url_preload_; }
// URL that loads a woff2 resource and https_url() webpage in an iframe.
virtual const GURL& https_url_iframe() const { return https_url_iframe_; }
// URL that loads a woff2 resource and https_url_preload() webpage in an
// iframe.
virtual const GURL& https_url_iframe_preload() const {
return https_url_iframe_preload_;
}
const GURL& https_second_url() const { return https_second_url_; }
const GURL& https_no_transform_url() const { return https_no_transform_url_; }
const GURL& https_hint_setup_url() const { return https_hint_setup_url_; }
const GURL& http_url() const { return http_url_; }
const GURL& redirect_url() const { return redirect_url_; }
const GURL& http_hint_setup_url() const { return http_hint_setup_url_; }
void SetExpectedFooJpgRequest(bool expect_foo_jpg_requested) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
subresource_expected_["/foo.jpg"] = expect_foo_jpg_requested;
}
void SetExpectedBarJpgRequest(bool expect_bar_jpg_requested) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
subresource_expected_["/bar.jpg"] = expect_bar_jpg_requested;
}
void SetExpectedBazWoff2Request(bool expect_woff_requested) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
subresource_expected_["/baz.woff2"] = expect_woff_requested;
}
int GetProcessID() const {
return browser()
->tab_strip_model()
->GetActiveWebContents()
->GetMainFrame()
->GetProcess()
->GetID();
}
void RetryUntilAllExpectedSubresourcesSeen() {
while (true) {
base::ThreadPoolInstance::Get()->FlushForTesting();
base::RunLoop().RunUntilIdle();
bool have_seen_all_expected_subresources = true;
for (const auto& expect : subresource_expected_) {
if (expect.second) {
have_seen_all_expected_subresources = false;
break;
}
}
if (have_seen_all_expected_subresources)
break;
}
}
protected:
std::unique_ptr<net::EmbeddedTestServer> https_server_;
private:
void TearDownOnMainThread() override {
EXPECT_TRUE(https_server_->ShutdownAndWaitUntilComplete());
EXPECT_TRUE(http_server_->ShutdownAndWaitUntilComplete());
InProcessBrowserTest::TearDownOnMainThread();
}
// Called by |https_server_|.
void MonitorResourceRequest(const net::test_server::HttpRequest& request) {
// This method is called on embedded test server thread. Post the
// information on UI thread.
base::PostTask(FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&ResourceLoadingNoFeaturesBrowserTest::
MonitorResourceRequestOnUIThread,
base::Unretained(this), request.GetURL()));
}
std::unique_ptr<net::test_server::HttpResponse> HandleRedirectRequest(
const net::test_server::HttpRequest& request) {
std::unique_ptr<net::test_server::BasicHttpResponse> response;
if (request.GetURL().spec().find("redirect") != std::string::npos) {
response.reset(new net::test_server::BasicHttpResponse);
response->set_code(net::HTTP_FOUND);
response->AddCustomHeader("Location", https_url().spec());
}
return std::move(response);
}
void MonitorResourceRequestOnUIThread(const GURL& gurl) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
for (const auto& expect : subresource_expected_) {
if (gurl.path() == expect.first) {
// Verify that |gurl| is expected to be fetched. This ensures that a
// resource whose loading is blocked is not loaded.
EXPECT_TRUE(expect.second)
<< " GURL " << gurl
<< " was expected to be blocked, but was actually fetched";
// Subresource should not be fetched again.
subresource_expected_[gurl.path()] = false;
return;
}
}
}
optimization_guide::testing::TestHintsComponentCreator
test_hints_component_creator_;
std::unique_ptr<net::EmbeddedTestServer> http_server_;
GURL https_url_;
GURL https_url_preload_;
GURL https_url_iframe_;
GURL https_url_iframe_preload_;
GURL https_second_url_;
GURL https_no_transform_url_;
GURL https_hint_setup_url_;
GURL http_url_;
GURL redirect_url_;
GURL http_hint_setup_url_;
// Mapping from a subresource path to whether the resource is expected to be
// fetched. Once a subresource present in this map is fetched, the
// corresponding value is set to false.
// Must only be accessed on UI thread.
std::map<std::string, bool> subresource_expected_;
DISALLOW_COPY_AND_ASSIGN(ResourceLoadingNoFeaturesBrowserTest);
};
// This test class enables ResourceLoadingHints with OptimizationHints.
// First parameter is true if the test should be run with a webpage that
// preloads resources in the HTML head using link-rel preload.
// Second parameter is true if the OptimizationGuideKeyedService feature is
// enabled.
// All tests should pass in the same way for all cases.
class ResourceLoadingHintsBrowserTest
: public ::testing::WithParamInterface<std::tuple<bool, bool>>,
public ResourceLoadingNoFeaturesBrowserTest {
public:
ResourceLoadingHintsBrowserTest()
: use_preload_resources_webpage_(std::get<0>(GetParam())),
use_optimization_guide_keyed_service_(std::get<1>(GetParam())) {}
~ResourceLoadingHintsBrowserTest() override = default;
void SetUp() override {
// Enabling NoScript should have no effect since resource loading takes
// priority over NoScript.
scoped_feature_list_.InitWithFeatures(
{previews::features::kPreviews, previews::features::kNoScriptPreviews,
optimization_guide::features::kOptimizationHints,
previews::features::kResourceLoadingHints,
data_reduction_proxy::features::
kDataReductionProxyEnabledWithNetworkService},
{});
if (use_optimization_guide_keyed_service_) {
ogks_feature_list_.InitWithFeatures(
{optimization_guide::features::kOptimizationGuideKeyedService}, {});
} else {
ogks_feature_list_.InitWithFeatures(
{}, {optimization_guide::features::kOptimizationGuideKeyedService});
}
ResourceLoadingNoFeaturesBrowserTest::SetUp();
}
GURL GetURLWithMockHost(const net::EmbeddedTestServer& server,
const std::string& relative_url) const {
return server.GetURL(kMockHost, relative_url);
}
const GURL& https_url() const override {
if (use_preload_resources_webpage_)
return ResourceLoadingNoFeaturesBrowserTest::https_url_preload();
return ResourceLoadingNoFeaturesBrowserTest::https_url();
}
const GURL& https_url_iframe() const override {
if (use_preload_resources_webpage_)
return ResourceLoadingNoFeaturesBrowserTest::https_url_iframe_preload();
return ResourceLoadingNoFeaturesBrowserTest::https_url_iframe();
}
protected:
base::test::ScopedFeatureList scoped_feature_list_;
base::test::ScopedFeatureList ogks_feature_list_;
private:
const bool use_preload_resources_webpage_;
const bool use_optimization_guide_keyed_service_;
DISALLOW_COPY_AND_ASSIGN(ResourceLoadingHintsBrowserTest);
};
// First parameter is true if the test should be run with a webpage that
// preloads resources in the HTML head using link-rel preload. Second parameter
// is true if the OptimizationGuideKeyedService feature is enabled.
INSTANTIATE_TEST_SUITE_P(,
ResourceLoadingHintsBrowserTest,
::testing::Combine(::testing::Bool(),
::testing::Bool()));
// Previews InfoBar (which these tests triggers) does not work on Mac.
// See https://crbug.com/782322 for details. Also occasional flakes on win7
// (https://crbug.com/789542).
#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
#define DISABLE_ON_WIN_MAC_CHROMESOS(x) DISABLED_##x
#else
#define DISABLE_ON_WIN_MAC_CHROMESOS(x) x
#endif
IN_PROC_BROWSER_TEST_P(
ResourceLoadingHintsBrowserTest,
DISABLE_ON_WIN_MAC_CHROMESOS(ResourceLoadingHintsHttpsWhitelisted)) {
GURL url = https_url();
// Whitelist resource loading hints for https_hint_setup_url()'s' host.
SetDefaultOnlyResourceLoadingHints(https_hint_setup_url());
SetExpectedFooJpgRequest(false);
SetExpectedBarJpgRequest(true);
base::HistogramTester histogram_tester;
ui_test_utils::NavigateToURL(browser(), url);
RetryUntilAllExpectedSubresourcesSeen();
RetryForHistogramUntilCountReached(
&histogram_tester, "ResourceLoadingHints.CountBlockedSubresourcePatterns",
1);
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.ResourcePatternsAvailableAtCommit", 1, 1);
histogram_tester.ExpectTotalCount(
"ResourceLoadingHints.ResourcePatternsAvailableAtCommitForRedirect", 0);
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason.ResourceLoadingHints",
static_cast<int>(previews::PreviewsEligibilityReason::ALLOWED), 1);
histogram_tester.ExpectBucketCount(
"Previews.PreviewShown.ResourceLoadingHints", true, 1);
// SetDefaultOnlyResourceLoadingHints sets 3 resource loading hints patterns.
histogram_tester.ExpectBucketCount(
"ResourceLoadingHints.CountBlockedSubresourcePatterns", 3, 1);
// Load the same webpage to ensure that the resource loading hints are sent
// again.
SetExpectedFooJpgRequest(false);
SetExpectedBarJpgRequest(true);
ui_test_utils::NavigateToURL(browser(), url);
RetryUntilAllExpectedSubresourcesSeen();
RetryForHistogramUntilCountReached(
&histogram_tester, "ResourceLoadingHints.CountBlockedSubresourcePatterns",
2);
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.ResourcePatternsAvailableAtCommit", 1, 2);
histogram_tester.ExpectTotalCount(
"ResourceLoadingHints.ResourcePatternsAvailableAtCommitForRedirect", 0);
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason.ResourceLoadingHints",
static_cast<int>(previews::PreviewsEligibilityReason::ALLOWED), 2);
histogram_tester.ExpectBucketCount(
"Previews.PreviewShown.ResourceLoadingHints", true, 2);
// SetDefaultOnlyResourceLoadingHints sets 3 resource loading hints patterns.
histogram_tester.ExpectBucketCount(
"ResourceLoadingHints.CountBlockedSubresourcePatterns", 3, 2);
int previous_process_id = GetProcessID();
{
// Navigate to a cross-origin URL. Ensure that (i) there is no browser
// crash; and (ii) web contents observer sends the hints to the correct
// agent on the renderer side.
SetExpectedFooJpgRequest(false);
SetExpectedBarJpgRequest(true);
base::HistogramTester histogram_tester_2;
ui_test_utils::NavigateToURL(
browser(),
GetURLWithMockHost(*https_server_, "/resource_loading_hints.html"));
RetryUntilAllExpectedSubresourcesSeen();
int current_process_id = GetProcessID();
EXPECT_NE(previous_process_id, current_process_id);
base::RunLoop().RunUntilIdle();
RetryForHistogramUntilCountReached(
&histogram_tester_2,
"ResourceLoadingHints.CountBlockedSubresourcePatterns", 1);
}
}
// The test loads https_url_iframe() which is whitelisted for resource blocking.
// This webpage loads a woff2 resource whose loading should be blocked.
// https_url_iframe() also loads https_url() in an iframe. https_url()
// contains two resources whose URL match blocked patterns. However, since
// https_url() is inside an iframe, loading of those two resources should not
// be blocked.
IN_PROC_BROWSER_TEST_P(
ResourceLoadingHintsBrowserTest,
DISABLE_ON_WIN_MAC_CHROMESOS(ResourceLoadingHintsHttpsWhitelisted_Iframe)) {
GURL url = https_url_iframe();
// Whitelist resource loading hints for https_url_iframe()'s' host, which is
// the same as the hint setup URL. Having this be https_url_iframe() makes the
// test flaky.
SetDefaultOnlyResourceLoadingHints(https_hint_setup_url());
// Loading of these two resources should not be blocked since they are loaded
// by a webpage inside an iframe.
SetExpectedFooJpgRequest(true);
SetExpectedBarJpgRequest(true);
// Woff2 subresource is loaded by the https_url_iframe() and its loading
// should be blocked.
SetExpectedBazWoff2Request(false);
base::HistogramTester histogram_tester;
ui_test_utils::NavigateToURL(browser(), url);
RetryUntilAllExpectedSubresourcesSeen();
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason.ResourceLoadingHints",
static_cast<int>(previews::PreviewsEligibilityReason::ALLOWED), 1);
histogram_tester.ExpectTotalCount(
"Previews.PreviewShown.ResourceLoadingHints", 1);
histogram_tester.ExpectTotalCount(
"ResourceLoadingHints.CountBlockedSubresourcePatterns", 0);
}
// The test loads https_url_iframe() which is NOT whitelisted for resource
// blocking. This webpage loads a woff2 resource whose loading should NOT be
// blocked. https_url_iframe() also loads https_url() in an iframe. https_url()
// contains two resources whose URL match blocked patterns. Loading of those two
// resources should not be blocked either since https_url_iframe() is not
// whitelisted.
IN_PROC_BROWSER_TEST_P(ResourceLoadingHintsBrowserTest,
DISABLE_ON_WIN_MAC_CHROMESOS(
ResourceLoadingHintsHttpsNotWhitelisted_Iframe)) {
GURL url = https_url_iframe();
// Do not whitelist resource loading hints for https_url_iframe()'s' host.
SetExpectedFooJpgRequest(true);
SetExpectedBarJpgRequest(true);
// Woff2 subresource is loaded by the https_url_iframe(). The other two
// resources are loaded by the webpage inside the iframe. None of these
// resources should be blocked from loading.
SetExpectedBazWoff2Request(true);
base::HistogramTester histogram_tester;
ui_test_utils::NavigateToURL(browser(), url);
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason.ResourceLoadingHints",
static_cast<int>(previews::PreviewsEligibilityReason::ALLOWED), 1);
histogram_tester.ExpectTotalCount(
"Previews.PreviewShown.ResourceLoadingHints", 0);
histogram_tester.ExpectTotalCount(
"ResourceLoadingHints.CountBlockedSubresourcePatterns", 0);
}
// Sets only the experimental hints, but does not enable the matching
// experiment. Verifies that the hints are not used, and the resource loading is
// not blocked.
IN_PROC_BROWSER_TEST_P(
ResourceLoadingHintsBrowserTest,
DISABLE_ON_WIN_MAC_CHROMESOS(ExperimentalHints_ExperimentIsNotEnabled)) {
GURL url = https_url();
// Whitelist resource loading hints for https_hint_setup_url()'s' host.
SetExperimentOnlyResourceLoadingHints(https_hint_setup_url());
SetExpectedFooJpgRequest(true);
SetExpectedBarJpgRequest(true);
base::HistogramTester histogram_tester;
ui_test_utils::NavigateToURL(browser(), url);
RetryUntilAllExpectedSubresourcesSeen();
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason.ResourceLoadingHints",
static_cast<int>(previews::PreviewsEligibilityReason::ALLOWED), 1);
histogram_tester.ExpectTotalCount(
"Previews.PreviewShown.ResourceLoadingHints", 0);
histogram_tester.ExpectTotalCount(
"ResourceLoadingHints.CountBlockedSubresourcePatterns", 0);
}
// Sets only the experimental hints, and enables the matching experiment.
// Verifies that the hints are used, and the resource loading is blocked.
IN_PROC_BROWSER_TEST_P(
ResourceLoadingHintsBrowserTest,
DISABLE_ON_WIN_MAC_CHROMESOS(ExperimentalHints_ExperimentIsEnabled)) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeatureWithParameters(
optimization_guide::features::kOptimizationHintsExperiments,
{{optimization_guide::features::kOptimizationHintsExperimentNameParam,
optimization_guide::testing::kFooExperimentName}});
GURL url = https_url();
// Whitelist resource loading hints for https_hint_setup_url()'s' host.
SetExperimentOnlyResourceLoadingHints(https_hint_setup_url());
SetExpectedFooJpgRequest(false);
SetExpectedBarJpgRequest(true);
base::HistogramTester histogram_tester;
ui_test_utils::NavigateToURL(browser(), url);
RetryUntilAllExpectedSubresourcesSeen();
RetryForHistogramUntilCountReached(
&histogram_tester, "ResourceLoadingHints.CountBlockedSubresourcePatterns",
1);
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.ResourcePatternsAvailableAtCommit", 1, 1);
histogram_tester.ExpectTotalCount(
"ResourceLoadingHints.ResourcePatternsAvailableAtCommitForRedirect", 0);
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason.ResourceLoadingHints",
static_cast<int>(previews::PreviewsEligibilityReason::ALLOWED), 1);
histogram_tester.ExpectBucketCount(
"Previews.PreviewShown.ResourceLoadingHints", true, 1);
// SetDefaultOnlyResourceLoadingHints sets 3 resource loading hints patterns.
histogram_tester.ExpectBucketCount(
"ResourceLoadingHints.CountBlockedSubresourcePatterns", 3, 1);
}
// Sets both the experimental and default hints, and enables the matching
// experiment. Verifies that the hints are used, and the resource loading is
// blocked.
IN_PROC_BROWSER_TEST_P(
ResourceLoadingHintsBrowserTest,
DISABLE_ON_WIN_MAC_CHROMESOS(MixExperimentalHints_ExperimentIsEnabled)) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeatureWithParameters(
optimization_guide::features::kOptimizationHintsExperiments,
{{optimization_guide::features::kOptimizationHintsExperimentNameParam,
optimization_guide::testing::kFooExperimentName}});
GURL url = https_url();
// Whitelist resource loading hints for https_hint_setup_url()'s' host. Set
// both experimental and non-experimental hints.
SetMixResourceLoadingHints(https_hint_setup_url());
SetExpectedFooJpgRequest(false);
SetExpectedBarJpgRequest(true);
base::HistogramTester histogram_tester;
ui_test_utils::NavigateToURL(browser(), url);
RetryUntilAllExpectedSubresourcesSeen();
RetryForHistogramUntilCountReached(
&histogram_tester, "ResourceLoadingHints.CountBlockedSubresourcePatterns",
1);
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.ResourcePatternsAvailableAtCommit", 1, 1);
histogram_tester.ExpectTotalCount(
"ResourceLoadingHints.ResourcePatternsAvailableAtCommitForRedirect", 0);
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason.ResourceLoadingHints",
static_cast<int>(previews::PreviewsEligibilityReason::ALLOWED), 1);
histogram_tester.ExpectBucketCount(
"Previews.PreviewShown.ResourceLoadingHints", true, 1);
// SetDefaultOnlyResourceLoadingHints sets 3 resource loading hints patterns.
histogram_tester.ExpectBucketCount(
"ResourceLoadingHints.CountBlockedSubresourcePatterns", 3, 1);
}
// Sets the default hints with a non-wildcard page pattern. Loads a webpage from
// an origin for which the hints are present, but the page pattern does not
// match. Verifies that the hints are not used on that webpage.
IN_PROC_BROWSER_TEST_P(
ResourceLoadingHintsBrowserTest,
DISABLE_ON_WIN_MAC_CHROMESOS(MatchingOrigin_NonMatchingPagePattern)) {
const GURL url = https_url();
// Whitelist resource loading hints for https_hint_setup_url()'s' host.
// Set pattern to a string that does not matches https_url() path.
ASSERT_EQ(std::string::npos, https_url().path().find("mismatched_pattern"));
SetDefaultOnlyResourceLoadingHintsWithPagePattern(https_hint_setup_url(),
"mismatched_pattern");
SetExpectedFooJpgRequest(true);
SetExpectedBarJpgRequest(true);
base::HistogramTester histogram_tester;
// The URL is not whitelisted. Verify that the hints are not used.
ui_test_utils::NavigateToURL(browser(), url);
RetryUntilAllExpectedSubresourcesSeen();
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason.ResourceLoadingHints",
static_cast<int>(previews::PreviewsEligibilityReason::
NOT_ALLOWED_BY_OPTIMIZATION_GUIDE),
1);
histogram_tester.ExpectTotalCount(
"Previews.PreviewShown.ResourceLoadingHints", 0);
histogram_tester.ExpectTotalCount(
"ResourceLoadingHints.CountBlockedSubresourcePatterns", 0);
}
// Sets the default hints with a non-wildcard page pattern. First loads a
// webpage from a host for which the hints are present (page pattern matches).
// Next, loads a webpage from the same host but the webpage's URL does not match
// the page patterns. Verifies that the hints are not used on that webpage.
IN_PROC_BROWSER_TEST_P(
ResourceLoadingHintsBrowserTest,
DISABLE_ON_WIN_MAC_CHROMESOS(SameOriginDifferentPattern)) {
// Whitelist resource loading hints for https_url()'s' host and pattern.
SetDefaultOnlyResourceLoadingHintsWithPagePattern(https_hint_setup_url(),
https_url().path());
// Hints should be used when loading https_url().
SetExpectedFooJpgRequest(false);
SetExpectedBarJpgRequest(true);
base::HistogramTester histogram_tester_1;
ui_test_utils::NavigateToURL(browser(), https_url());
RetryUntilAllExpectedSubresourcesSeen();
RetryForHistogramUntilCountReached(
&histogram_tester_1,
"ResourceLoadingHints.CountBlockedSubresourcePatterns", 1);
histogram_tester_1.ExpectUniqueSample(
"ResourceLoadingHints.ResourcePatternsAvailableAtCommit", 1, 1);
histogram_tester_1.ExpectTotalCount(
"ResourceLoadingHints.ResourcePatternsAvailableAtCommitForRedirect", 0);
histogram_tester_1.ExpectBucketCount(
"Previews.EligibilityReason.ResourceLoadingHints",
static_cast<int>(previews::PreviewsEligibilityReason::ALLOWED), 1);
histogram_tester_1.ExpectBucketCount(
"Previews.PreviewShown.ResourceLoadingHints", true, 1);
// SetDefaultOnlyResourceLoadingHints sets 3 resource loading hints patterns.
histogram_tester_1.ExpectBucketCount(
"ResourceLoadingHints.CountBlockedSubresourcePatterns", 3, 1);
// Load a different webpage on the same origin to ensure that the resource
// loading hints are not reused.
SetExpectedFooJpgRequest(true);
SetExpectedBarJpgRequest(true);
base::HistogramTester histogram_tester_2;
// https_second_url() is hosted on the same host as https_url(), but the path
// for https_second_url() is not whitelisted.
ASSERT_EQ(https_url().host(), https_second_url().host());
ASSERT_NE(https_url().path(), https_second_url().path());
ui_test_utils::NavigateToURL(browser(), https_second_url());
base::RunLoop().RunUntilIdle();
histogram_tester_2.ExpectBucketCount(
"Previews.EligibilityReason.ResourceLoadingHints",
static_cast<int>(previews::PreviewsEligibilityReason::
NOT_ALLOWED_BY_OPTIMIZATION_GUIDE),
1);
histogram_tester_2.ExpectTotalCount(
"Previews.PreviewShown.ResourceLoadingHints", 0);
histogram_tester_2.ExpectTotalCount(
"ResourceLoadingHints.CountBlockedSubresourcePatterns", 0);
}
// Sets both the experimental and default hints, but does not enable the
// matching experiment. Verifies that the hints from the experiment are not
// used.
IN_PROC_BROWSER_TEST_P(
ResourceLoadingHintsBrowserTest,
DISABLE_ON_WIN_MAC_CHROMESOS(MixExperimentalHints_ExperimentIsNotEnabled)) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeatureWithParameters(
optimization_guide::features::kOptimizationHintsExperiments,
{{optimization_guide::features::kOptimizationHintsExperimentNameParam,
"some_other_experiment"}});
GURL url = https_url();
// Whitelist resource loading hints for https_hint_setup_url()'s' host.
SetMixResourceLoadingHints(https_hint_setup_url());
SetExpectedFooJpgRequest(true);
SetExpectedBarJpgRequest(false);
base::HistogramTester histogram_tester;
ui_test_utils::NavigateToURL(browser(), url);
RetryUntilAllExpectedSubresourcesSeen();
RetryForHistogramUntilCountReached(
&histogram_tester, "ResourceLoadingHints.CountBlockedSubresourcePatterns",
1);
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason.ResourceLoadingHints",
static_cast<int>(previews::PreviewsEligibilityReason::ALLOWED), 1);
// Infobar would still be shown since there were at least one resource
// loading hints available, even though none of them matched.
RetryForHistogramUntilCountReached(
&histogram_tester, "Previews.PreviewShown.ResourceLoadingHints", 1);
}
IN_PROC_BROWSER_TEST_P(
ResourceLoadingHintsBrowserTest,
DISABLE_ON_WIN_MAC_CHROMESOS(
ResourceLoadingHintsHttpsWhitelistedRedirectToHttps)) {
GURL url = redirect_url();
// Whitelist resource loading hints for https_hint_setup_url()'s' host.
SetDefaultOnlyResourceLoadingHints(https_hint_setup_url());
SetExpectedFooJpgRequest(false);
SetExpectedBarJpgRequest(true);
base::HistogramTester histogram_tester;
ui_test_utils::NavigateToURL(browser(), url);
RetryUntilAllExpectedSubresourcesSeen();
RetryForHistogramUntilCountReached(
&histogram_tester, "ResourceLoadingHints.CountBlockedSubresourcePatterns",
1);
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.ResourcePatternsAvailableAtCommit", 1, 1);
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.ResourcePatternsAvailableAtCommitForRedirect", 1,
1);
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason.ResourceLoadingHints",
static_cast<int>(previews::PreviewsEligibilityReason::ALLOWED), 2);
RetryForHistogramUntilCountReached(
&histogram_tester, "Previews.PreviewShown.ResourceLoadingHints", 1);
// SetDefaultOnlyResourceLoadingHints sets 3 resource loading hints patterns.
histogram_tester.ExpectBucketCount(
"ResourceLoadingHints.CountBlockedSubresourcePatterns", 3, 1);
}
IN_PROC_BROWSER_TEST_P(
ResourceLoadingHintsBrowserTest,
DISABLE_ON_WIN_MAC_CHROMESOS(ResourceLoadingHintsHttpsNotWhitelisted)) {
GURL url = https_url();
SetExpectedFooJpgRequest(true);
SetExpectedBarJpgRequest(true);
InitializeOptimizationHints();
base::HistogramTester histogram_tester;
// The URL is not whitelisted.
ui_test_utils::NavigateToURL(browser(), url);
RetryUntilAllExpectedSubresourcesSeen();
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason.ResourceLoadingHints",
static_cast<int>(previews::PreviewsEligibilityReason::
NOT_ALLOWED_BY_OPTIMIZATION_GUIDE),
1);
histogram_tester.ExpectTotalCount(
"Previews.PreviewShown.ResourceLoadingHints", 0);
histogram_tester.ExpectTotalCount(
"ResourceLoadingHints.CountBlockedSubresourcePatterns", 0);
}
IN_PROC_BROWSER_TEST_P(ResourceLoadingHintsBrowserTest,
DISABLE_ON_WIN_MAC_CHROMESOS(ResourceLoadingHintsHttp)) {
GURL url = http_url();
// Whitelist resource loading hints for http_hint_setup_url()'s' host.
SetDefaultOnlyResourceLoadingHints(http_hint_setup_url());
SetExpectedFooJpgRequest(true);
SetExpectedBarJpgRequest(true);
base::HistogramTester histogram_tester;
ui_test_utils::NavigateToURL(browser(), url);
RetryUntilAllExpectedSubresourcesSeen();
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason.ResourceLoadingHints",
static_cast<int>(previews::PreviewsEligibilityReason::ALLOWED), 1);
histogram_tester.ExpectTotalCount(
"Previews.PreviewShown.ResourceLoadingHints", 0);
histogram_tester.ExpectTotalCount(
"ResourceLoadingHints.CountBlockedSubresourcePatterns", 0);
}
IN_PROC_BROWSER_TEST_P(ResourceLoadingHintsBrowserTest,
DISABLE_ON_WIN_MAC_CHROMESOS(
ResourceLoadingHintsHttpsWhitelistedNoTransform)) {
GURL url = https_no_transform_url();
// Whitelist resource loading hints for http_hint_setup_url()'s' host.
SetDefaultOnlyResourceLoadingHints(http_hint_setup_url());
SetExpectedFooJpgRequest(true);
SetExpectedBarJpgRequest(true);
base::HistogramTester histogram_tester;
ui_test_utils::NavigateToURL(browser(), url);
RetryUntilAllExpectedSubresourcesSeen();
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason.ResourceLoadingHints",
static_cast<int>(previews::PreviewsEligibilityReason::ALLOWED), 1);
histogram_tester.ExpectTotalCount(
"Previews.PreviewShown.ResourceLoadingHints", 0);
histogram_tester.ExpectTotalCount(
"ResourceLoadingHints.CountBlockedSubresourcePatterns", 0);
}
IN_PROC_BROWSER_TEST_P(
ResourceLoadingHintsBrowserTest,
DISABLE_ON_WIN_MAC_CHROMESOS(
ResourceLoadingHintsHttpsWhitelistedButShouldNotApplyBecauseCoinFlipHoldback)) {
// Holdback the page load from previews and also disable offline previews to
// ensure that only post-commit previews are enabled.
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitWithFeaturesAndParameters(
{{previews::features::kCoinFlipHoldback,
{{"force_coin_flip_always_holdback", "true"}}}},
{previews::features::kOfflinePreviews});
ukm::TestAutoSetUkmRecorder test_ukm_recorder;
GURL url = https_url();
// Whitelist resource loading hints for https_hint_setup_url()'s' host.
SetDefaultOnlyResourceLoadingHints(https_hint_setup_url());
SetExpectedFooJpgRequest(true);
SetExpectedBarJpgRequest(true);
base::HistogramTester histogram_tester;
ui_test_utils::NavigateToURL(browser(), url);
RetryUntilAllExpectedSubresourcesSeen();
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason.ResourceLoadingHints",
static_cast<int>(previews::PreviewsEligibilityReason::COMMITTED), 1);
histogram_tester.ExpectTotalCount(
"Previews.PreviewShown.ResourceLoadingHints", 0);
histogram_tester.ExpectTotalCount(
"ResourceLoadingHints.CountBlockedSubresourcePatterns", 0);
// Make sure we did not record a PreviewsResourceLoadingHints UKM for it.
auto rlh_ukm_entries = test_ukm_recorder.GetEntriesByName(
ukm::builders::PreviewsResourceLoadingHints::kEntryName);
ASSERT_EQ(0u, rlh_ukm_entries.size());
}