Commit 3ce9f4d8 authored by Matt Menke's avatar Matt Menke Committed by Commit Bot

Make ResourcePrefetchPredictor use correct NetworkIsolationKeys.

ResourcePrefetchPredictor was always using the origin of the initial
page being navigated to in constructing the NetworkIsolationKey.
With this CL, it uses the origin it expects the page to redirect to
instead.

Bug: 987735
Change-Id: Ic66c33bb5f99a9a00485ffe46c70e0947e0e430b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1730782Reviewed-by: default avatarTarun Bansal <tbansal@chromium.org>
Reviewed-by: default avatarEgor Pasko <pasko@chromium.org>
Commit-Queue: Matt Menke <mmenke@chromium.org>
Cr-Commit-Position: refs/heads/master@{#685173}
parent e8b38db0
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include "content/public/common/referrer.h" #include "content/public/common/referrer.h"
#include "content/public/test/browser_test_utils.h" #include "content/public/test/browser_test_utils.h"
#include "content/public/test/simple_url_loader_test_helper.h" #include "content/public/test/simple_url_loader_test_helper.h"
#include "net/base/escape.h"
#include "net/base/features.h" #include "net/base/features.h"
#include "net/base/network_isolation_key.h" #include "net/base/network_isolation_key.h"
#include "net/dns/mock_host_resolver.h" #include "net/dns/mock_host_resolver.h"
...@@ -396,6 +397,8 @@ class LoadingPredictorBrowserTest : public InProcessBrowserTest { ...@@ -396,6 +397,8 @@ class LoadingPredictorBrowserTest : public InProcessBrowserTest {
ASSERT_TRUE(embedded_test_server()->InitializeAndListen()); ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
embedded_test_server()->RegisterRequestHandler(base::BindRepeating( embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
&LoadingPredictorBrowserTest::HandleFaviconRequest)); &LoadingPredictorBrowserTest::HandleFaviconRequest));
embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
&LoadingPredictorBrowserTest::HandleCacheRedirectRequest));
InProcessBrowserTest::SetUp(); InProcessBrowserTest::SetUp();
} }
...@@ -486,6 +489,29 @@ class LoadingPredictorBrowserTest : public InProcessBrowserTest { ...@@ -486,6 +489,29 @@ class LoadingPredictorBrowserTest : public InProcessBrowserTest {
return http_response; return http_response;
} }
static std::unique_ptr<net::test_server::HttpResponse>
HandleCacheRedirectRequest(const net::test_server::HttpRequest& request) {
if (!base::StartsWith(request.relative_url, "/cached-redirect?",
base::CompareCase::INSENSITIVE_ASCII)) {
return std::unique_ptr<net::test_server::HttpResponse>();
}
GURL request_url = request.GetURL();
std::string dest =
net::UnescapeBinaryURLComponent(request_url.query_piece());
auto http_response =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response->set_code(net::HTTP_MOVED_PERMANENTLY);
http_response->AddCustomHeader("Location", dest);
http_response->set_content_type("text/html");
http_response->set_content(base::StringPrintf(
"<html><head></head><body>Redirecting to %s</body></html>",
dest.c_str()));
http_response->AddCustomHeader("Cache-Control", "max-age=6000");
return http_response;
}
private: private:
LoadingPredictor* loading_predictor_ = nullptr; LoadingPredictor* loading_predictor_ = nullptr;
std::unique_ptr<ConnectionListener> connection_listener_; std::unique_ptr<ConnectionListener> connection_listener_;
...@@ -700,16 +726,6 @@ IN_PROC_BROWSER_TEST_F(LoadingPredictorBrowserTest, ...@@ -700,16 +726,6 @@ IN_PROC_BROWSER_TEST_F(LoadingPredictorBrowserTest,
prediction = GetPreconnectPrediction(original_url); prediction = GetPreconnectPrediction(original_url);
EXPECT_FALSE(prediction); EXPECT_FALSE(prediction);
// TODO(https://crbug.com/987735): These predictions should match |requests|
// should use |redirect_url|'s origin.
url::Origin original_origin = url::Origin::Create(original_url);
std::vector<PreconnectRequest> requests2;
for (auto* const host : kHtmlSubresourcesHosts) {
requests2.emplace_back(
embedded_test_server()->GetURL(host, "/"), 1,
net::NetworkIsolationKey(original_origin, original_origin));
}
// The predictor will start predict a redirect after the second navigation. // The predictor will start predict a redirect after the second navigation.
ui_test_utils::NavigateToURL(browser(), original_url); ui_test_utils::NavigateToURL(browser(), original_url);
prediction = GetPreconnectPrediction(original_url); prediction = GetPreconnectPrediction(original_url);
...@@ -717,7 +733,7 @@ IN_PROC_BROWSER_TEST_F(LoadingPredictorBrowserTest, ...@@ -717,7 +733,7 @@ IN_PROC_BROWSER_TEST_F(LoadingPredictorBrowserTest,
EXPECT_EQ(prediction->is_redirected, true); EXPECT_EQ(prediction->is_redirected, true);
EXPECT_EQ(prediction->host, redirect_url.host()); EXPECT_EQ(prediction->host, redirect_url.host());
EXPECT_THAT(prediction->requests, EXPECT_THAT(prediction->requests,
testing::UnorderedElementsAreArray(requests2)); testing::UnorderedElementsAreArray(requests));
} }
// Tests that the LoadingPredictor performs preresolving/preconnecting for a // Tests that the LoadingPredictor performs preresolving/preconnecting for a
...@@ -974,7 +990,7 @@ INSTANTIATE_TEST_SUITE_P( ...@@ -974,7 +990,7 @@ INSTANTIATE_TEST_SUITE_P(
// both when the predictor is populated and when it isn't. // both when the predictor is populated and when it isn't.
IN_PROC_BROWSER_TEST_P(LoadingPredictorNetworkIsolationKeyBrowserTest, IN_PROC_BROWSER_TEST_P(LoadingPredictorNetworkIsolationKeyBrowserTest,
LoadingPredictorNoRedirects) { LoadingPredictorNoRedirects) {
// Cache resources needed by navigations, so so the only sockets created // Cache resources needed by navigations, so the only sockets created
// during navigations should be for the two preconnects. // during navigations should be for the two preconnects.
CacheFavIcon(); CacheFavIcon();
GURL cacheable_url = embedded_test_server()->GetURL("/cachetime"); GURL cacheable_url = embedded_test_server()->GetURL("/cachetime");
...@@ -1012,6 +1028,101 @@ IN_PROC_BROWSER_TEST_P(LoadingPredictorNetworkIsolationKeyBrowserTest, ...@@ -1012,6 +1028,101 @@ IN_PROC_BROWSER_TEST_P(LoadingPredictorNetworkIsolationKeyBrowserTest,
} }
} }
// Make sure that the right NetworkIsolationKey is used by the LoadingPredictor,
// both when the predictor is populated and when it isn't.
IN_PROC_BROWSER_TEST_P(LoadingPredictorNetworkIsolationKeyBrowserTest,
LoadingPredictorWithRedirects) {
// Cache resources needed by navigations, so the only connections to the
// tracked server created during navigations should be for preconnects.
CacheFavIcon();
GURL cacheable_url = embedded_test_server()->GetURL("/cachetime");
CacheUrl(cacheable_url);
GURL redirecting_url = preconnecting_test_server()->GetURL(
"/server-redirect?" + cacheable_url.spec());
// It takes two navigations to learn to preconnect based on the redirect.
// Neither will make any connections to the tracked test server, since the
// resource itself is cached.
for (int i = 0; i < 2; ++i) {
auto observer = NavigateToURLAsync(redirecting_url);
observer->WaitForNavigationFinished();
EXPECT_EQ(0u, connection_tracker()->GetAcceptedSocketCount());
EXPECT_EQ(0u, connection_tracker()->GetReadSocketCount());
}
// The third navigation does preconnect. It won't use either of the
// preconnected sockets, since the destination resource is still in the cache.
auto observer = NavigateToURLAsync(redirecting_url);
observer->WaitForNavigationFinished();
connection_tracker()->WaitForAcceptedConnections(1);
EXPECT_EQ(0u, connection_tracker()->GetReadSocketCount());
// Have the page fetch a subresource, which should use one of the
// preconnects triggered by the above navigation, due to the matching
// NetworkIsolationKey. Do this instead of a navigation to a non-cached URL
// to avoid triggering more preconnects.
std::string fetch_resource = base::StringPrintf(
"(async () => {"
" var resp = (await fetch('%s'));"
" return resp.status; })();",
embedded_test_server()->GetURL("/echo").spec().c_str());
EXPECT_EQ(
200,
EvalJs(
browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(),
fetch_resource));
EXPECT_EQ(1u, connection_tracker()->GetAcceptedSocketCount());
EXPECT_EQ(1u, connection_tracker()->GetReadSocketCount());
}
// Checks the opposite of the above test - tests that even when a redirect is
// predicted, preconnects are still made to the original origin using the
// correct NetworkIsolationKey.
IN_PROC_BROWSER_TEST_P(LoadingPredictorNetworkIsolationKeyBrowserTest,
LoadingPredictorWithRedirects2) {
// Cache the redirect, so the only connections to the tracked server created
// during navigations should be for preconnects.
GURL destination_url = preconnecting_test_server()->GetURL("/cachetime");
GURL redirecting_url = embedded_test_server()->GetURL("/cached-redirect?" +
destination_url.spec());
CacheUrl(redirecting_url);
// The first two navigations to learn to preconnect based on the redirect, and
// the third actually preconnects to the untracked server. All navigations
// should preconnect twice to the tracked server.
for (int i = 0; i < 3; ++i) {
auto observer = NavigateToURLAsync(redirecting_url);
observer->WaitForNavigationFinished();
connection_tracker()->WaitForAcceptedConnections(2);
EXPECT_EQ(0u, connection_tracker()->GetReadSocketCount());
// Verify that the preconnects were made using the |redirecting_url|'s
// NetworkIsolationKey. To do this, make a request using the tracked
// server's NetworkIsolationKey, and verify it used one of the existing
// sockets.
auto request = std::make_unique<network::ResourceRequest>();
request->url = embedded_test_server()->GetURL("/echo");
content::SimpleURLLoaderTestHelper simple_loader_helper;
url::Origin origin = url::Origin::Create(request->url);
request->trusted_network_isolation_key =
net::NetworkIsolationKey(origin, origin);
std::unique_ptr<network::SimpleURLLoader> simple_loader =
network::SimpleURLLoader::Create(std::move(request),
TRAFFIC_ANNOTATION_FOR_TESTS);
simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
browser()->profile()->GetURLLoaderFactory().get(),
simple_loader_helper.GetCallback());
simple_loader_helper.WaitForCallback();
ASSERT_TRUE(simple_loader_helper.response_body());
EXPECT_EQ(2u, connection_tracker()->GetAcceptedSocketCount());
EXPECT_EQ(1u, connection_tracker()->GetReadSocketCount());
ResetNetworkState();
}
}
IN_PROC_BROWSER_TEST_P(LoadingPredictorNetworkIsolationKeyBrowserTest, IN_PROC_BROWSER_TEST_P(LoadingPredictorNetworkIsolationKeyBrowserTest,
LinkRelPreconnectMainFrame) { LinkRelPreconnectMainFrame) {
const char kHost1[] = "host1.test"; const char kHost1[] = "host1.test";
......
...@@ -33,10 +33,14 @@ void InitializeRedirectStat(RedirectStat* redirect, ...@@ -33,10 +33,14 @@ void InitializeRedirectStat(RedirectStat* redirect,
const GURL& url, const GURL& url,
int number_of_hits, int number_of_hits,
int number_of_misses, int number_of_misses,
int consecutive_misses) { int consecutive_misses,
bool include_scheme,
bool include_port) {
redirect->set_url(url.host()); redirect->set_url(url.host());
redirect->set_url_scheme(url.scheme()); if (include_scheme)
redirect->set_url_port(url.EffectiveIntPort()); redirect->set_url_scheme(url.scheme());
if (include_port)
redirect->set_url_port(url.EffectiveIntPort());
redirect->set_number_of_hits(number_of_hits); redirect->set_number_of_hits(number_of_hits);
redirect->set_number_of_misses(number_of_misses); redirect->set_number_of_misses(number_of_misses);
redirect->set_consecutive_misses(consecutive_misses); redirect->set_consecutive_misses(consecutive_misses);
......
...@@ -35,11 +35,15 @@ class MockResourcePrefetchPredictor : public ResourcePrefetchPredictor { ...@@ -35,11 +35,15 @@ class MockResourcePrefetchPredictor : public ResourcePrefetchPredictor {
MOCK_METHOD1(RecordPageRequestSummaryProxy, void(PageRequestSummary*)); MOCK_METHOD1(RecordPageRequestSummaryProxy, void(PageRequestSummary*));
}; };
// |include_scheme| and |include_port| can be set to false to simulate legacy
// data, which doesn't have new fields.
void InitializeRedirectStat(RedirectStat* redirect, void InitializeRedirectStat(RedirectStat* redirect,
const GURL& url, const GURL& url,
int number_of_hits, int number_of_hits,
int number_of_misses, int number_of_misses,
int consecutive_misses); int consecutive_misses,
bool include_scheme = true,
bool include_port = true);
void InitializeOriginStat(OriginStat* origin_stat, void InitializeOriginStat(OriginStat* origin_stat,
const std::string& origin, const std::string& origin,
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/rand_util.h" #include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/history/history_service_factory.h"
...@@ -57,6 +58,12 @@ void InitializeOnDBSequence( ...@@ -57,6 +58,12 @@ void InitializeOnDBSequence(
origin_data->InitializeOnDBSequence(); origin_data->InitializeOnDBSequence();
} }
GURL CreateRedirectURL(const std::string& scheme,
const std::string& host,
std::uint16_t port) {
return GURL(scheme + "://" + host + ":" + base::NumberToString(port));
}
} // namespace } // namespace
PreconnectRequest::PreconnectRequest( PreconnectRequest::PreconnectRequest(
...@@ -77,18 +84,18 @@ PreconnectPrediction::~PreconnectPrediction() = default; ...@@ -77,18 +84,18 @@ PreconnectPrediction::~PreconnectPrediction() = default;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// ResourcePrefetchPredictor static functions. // ResourcePrefetchPredictor static functions.
bool ResourcePrefetchPredictor::GetRedirectEndpoint( bool ResourcePrefetchPredictor::GetRedirectOrigin(
const std::string& entry_point, const url::Origin& entry_origin,
const RedirectDataMap& redirect_data, const RedirectDataMap& redirect_data,
std::string* redirect_endpoint) const { url::Origin* redirect_origin) {
DCHECK(redirect_endpoint); DCHECK(redirect_origin);
RedirectData data; RedirectData data;
bool exists = redirect_data.TryGetData(entry_point, &data); bool exists = redirect_data.TryGetData(entry_origin.host(), &data);
if (!exists) { if (!exists) {
// Fallback to fetching URLs based on the incoming URL/host. By default // Fallback to fetching URLs based on the incoming URL/host. By default
// the predictor is confident that there is no redirect. // the predictor is confident that there is no redirect.
*redirect_endpoint = entry_point; *redirect_origin = entry_origin;
return true; return true;
} }
...@@ -109,14 +116,37 @@ bool ResourcePrefetchPredictor::GetRedirectEndpoint( ...@@ -109,14 +116,37 @@ bool ResourcePrefetchPredictor::GetRedirectEndpoint(
// The predictor doesn't apply a minimum-number-of-hits threshold to // The predictor doesn't apply a minimum-number-of-hits threshold to
// the no-redirect case because the no-redirect is a default assumption. // the no-redirect case because the no-redirect is a default assumption.
const RedirectStat& redirect = data.redirect_endpoints(0); const RedirectStat& redirect = data.redirect_endpoints(0);
if (ComputeRedirectConfidence(redirect) < if (ComputeRedirectConfidence(redirect) <
kMinRedirectConfidenceToTriggerPrefetch || kMinRedirectConfidenceToTriggerPrefetch ||
(redirect.number_of_hits() < kMinRedirectHitsToTriggerPrefetch && (redirect.number_of_hits() < kMinRedirectHitsToTriggerPrefetch &&
redirect.url() != entry_point)) { redirect.url() != entry_origin.host())) {
return false; return false;
} }
*redirect_endpoint = redirect.url(); // Create a GURL from |redirect|, and get the origin from it. Origins can
// be created be directly passing in scheme, host, and port, but the class
// DCHECKs if any of them are invalid, and best not to DCHECK when loading bad
// data from disk. GURL does not DCHECK on bad input, so safest to rely on its
// logic, though more computationally expensive.
GURL redirect_url;
// Old entries may have no scheme or port.
if (redirect.has_url_scheme() && redirect.has_url_port()) {
redirect_url = CreateRedirectURL(redirect.url_scheme(), redirect.url(),
redirect.url_port());
}
// If there was no scheme or port, or they don't make for a valid URL (most
// likely due to using 0 or an empty scheme as default values), default to
// HTTPS / port 443.
if (!redirect_url.is_valid())
redirect_url = CreateRedirectURL("https", redirect.url(), 443);
if (!redirect_url.is_valid())
return false;
*redirect_origin = url::Origin::Create(redirect_url);
return true; return true;
} }
...@@ -210,30 +240,25 @@ bool ResourcePrefetchPredictor::PredictPreconnectOrigins( ...@@ -210,30 +240,25 @@ bool ResourcePrefetchPredictor::PredictPreconnectOrigins(
if (initialization_state_ != INITIALIZED) if (initialization_state_ != INITIALIZED)
return false; return false;
std::string host = url.host(); url::Origin url_origin = url::Origin::Create(url);
std::string redirect_endpoint; url::Origin redirect_origin;
if (!GetRedirectEndpoint(host, *host_redirect_data_, &redirect_endpoint)) if (!GetRedirectOrigin(url_origin, *host_redirect_data_, &redirect_origin)) {
return false; return false;
}
OriginData data; OriginData data;
if (!origin_data_->TryGetData(redirect_endpoint, &data)) if (!origin_data_->TryGetData(redirect_origin.host(), &data))
return false; return false;
if (prediction) { if (prediction) {
prediction->host = redirect_endpoint; prediction->host = redirect_origin.host();
prediction->is_redirected = (host != redirect_endpoint); prediction->is_redirected = (redirect_origin != url_origin);
} }
bool has_any_prediction = false; bool has_any_prediction = false;
// TODO(https://crbug.com/987735): Use the NetworkIsolationKey of the final net::NetworkIsolationKey network_isolation_key(redirect_origin,
// destination in the case of redirects. This will require recording the port, redirect_origin);
// which is not currently logged. That will not result in using the correct
// NetworkIsolationKey in the case of intermediary redirects, but given the
// relatively low accurace of redirect predictions, seems likely not worth
// fixing.
url::Origin origin = url::Origin::Create(url);
net::NetworkIsolationKey network_isolation_key(origin, origin);
for (const OriginStat& origin : data.origins()) { for (const OriginStat& origin : data.origins()) {
float confidence = static_cast<float>(origin.number_of_hits()) / float confidence = static_cast<float>(origin.number_of_hits()) /
......
...@@ -190,7 +190,7 @@ class ResourcePrefetchPredictor : public history::HistoryServiceObserver { ...@@ -190,7 +190,7 @@ class ResourcePrefetchPredictor : public history::HistoryServiceObserver {
FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, GetCorrectPLT); FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, GetCorrectPLT);
FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest,
PopulatePrefetcherRequest); PopulatePrefetcherRequest);
FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, GetRedirectEndpoint); FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, GetRedirectOrigin);
FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, GetPrefetchData); FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, GetPrefetchData);
FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest,
TestPredictPreconnectOrigins); TestPredictPreconnectOrigins);
...@@ -208,14 +208,14 @@ class ResourcePrefetchPredictor : public history::HistoryServiceObserver { ...@@ -208,14 +208,14 @@ class ResourcePrefetchPredictor : public history::HistoryServiceObserver {
}; };
// Returns true iff one of the following conditions is true // Returns true iff one of the following conditions is true
// * |redirect_data| contains confident redirect endpoint for |entry_point| // * |redirect_data| contains confident redirect origin for |entry_origin|
// and assigns it to the |redirect_endpoint| // and assigns it to the |redirect_origin|
// //
// * |redirect_data| doens't contain an entry for |entry_point| and assigns // * |redirect_data| doesn't contain an entry for |entry_origin| and assigns
// |entry_point| to the |redirect_endpoint|. // |entry_origin| to the |redirect_origin|.
bool GetRedirectEndpoint(const std::string& entry_point, static bool GetRedirectOrigin(const url::Origin& entry_origin,
const RedirectDataMap& redirect_data, const RedirectDataMap& redirect_data,
std::string* redirect_endpoint) const; url::Origin* redirect_origin);
// Callback for the task to read the predictor database. Takes ownership of // Callback for the task to read the predictor database. Takes ownership of
// all arguments. // all arguments.
......
...@@ -639,33 +639,40 @@ TEST_F(ResourcePrefetchPredictorTest, DeleteAllUrlsUninitialized) { ...@@ -639,33 +639,40 @@ TEST_F(ResourcePrefetchPredictorTest, DeleteAllUrlsUninitialized) {
EXPECT_TRUE(mock_tables_->origin_table_.data_.empty()); EXPECT_TRUE(mock_tables_->origin_table_.data_.empty());
} }
TEST_F(ResourcePrefetchPredictorTest, GetRedirectEndpoint) { TEST_F(ResourcePrefetchPredictorTest, GetRedirectOrigin) {
auto& redirect_data = *predictor_->host_redirect_data_; auto& redirect_data = *predictor_->host_redirect_data_;
std::string redirect_endpoint; url::Origin bbc_origin = url::Origin::Create(GURL("https://bbc.com/"));
url::Origin redirect_origin;
// Returns the initial url if data_map doesn't contain an entry for the url. // Returns the initial url if data_map doesn't contain an entry for the url.
EXPECT_TRUE(predictor_->GetRedirectEndpoint("bbc.com", redirect_data, EXPECT_TRUE(predictor_->GetRedirectOrigin(bbc_origin, redirect_data,
&redirect_endpoint)); &redirect_origin));
EXPECT_EQ(redirect_endpoint, "bbc.com"); EXPECT_EQ(bbc_origin, redirect_origin);
url::Origin nyt_origin = url::Origin::Create(GURL("https://nyt.com/"));
// The data to be requested for the confident endpoint. // The data to be requested for the confident endpoint.
RedirectData nyt = CreateRedirectData("nyt.com", 1); RedirectData nyt = CreateRedirectData(nyt_origin.host(), 1);
InitializeRedirectStat(nyt.add_redirect_endpoints(), GURL nyt_redirect_url("https://mobile.nytimes.com:8080/");
GURL("https://mobile.nytimes.com"), 10, 0, 0); url::Origin nyt_redirect_origin = url::Origin::Create(nyt_redirect_url);
InitializeRedirectStat(nyt.add_redirect_endpoints(), nyt_redirect_url, 10, 0,
0);
redirect_data.UpdateData(nyt.primary_key(), nyt); redirect_data.UpdateData(nyt.primary_key(), nyt);
EXPECT_TRUE(predictor_->GetRedirectEndpoint("nyt.com", redirect_data, EXPECT_TRUE(predictor_->GetRedirectOrigin(nyt_origin, redirect_data,
&redirect_endpoint)); &redirect_origin));
EXPECT_EQ(redirect_endpoint, "mobile.nytimes.com"); EXPECT_EQ(nyt_redirect_origin, redirect_origin);
url::Origin facebook_origin = url::Origin::Create(GURL("http://fb.com/"));
// The data to check negative result due not enough confidence. // The data to check negative result due not enough confidence.
RedirectData facebook = CreateRedirectData("fb.com", 3); RedirectData facebook = CreateRedirectData(facebook_origin.host(), 3);
GURL facebook_redirect_url("https://fb.com/");
InitializeRedirectStat(facebook.add_redirect_endpoints(), InitializeRedirectStat(facebook.add_redirect_endpoints(),
GURL("https://facebook.com"), 5, 5, 0); facebook_redirect_url, 5, 5, 0);
redirect_data.UpdateData(facebook.primary_key(), facebook); redirect_data.UpdateData(facebook.primary_key(), facebook);
EXPECT_FALSE(predictor_->GetRedirectEndpoint("fb.com", redirect_data, EXPECT_FALSE(predictor_->GetRedirectOrigin(facebook_origin, redirect_data,
&redirect_endpoint)); &redirect_origin));
// The data to check negative result due ambiguity. // The data to check negative result due ambiguity.
RedirectData google = CreateRedirectData("google.com", 4); url::Origin google_origin = url::Origin::Create(GURL("https://google.com/"));
RedirectData google = CreateRedirectData(google_origin.host(), 4);
InitializeRedirectStat(google.add_redirect_endpoints(), InitializeRedirectStat(google.add_redirect_endpoints(),
GURL("https://google.com"), 10, 0, 0); GURL("https://google.com"), 10, 0, 0);
InitializeRedirectStat(google.add_redirect_endpoints(), InitializeRedirectStat(google.add_redirect_endpoints(),
...@@ -673,8 +680,40 @@ TEST_F(ResourcePrefetchPredictorTest, GetRedirectEndpoint) { ...@@ -673,8 +680,40 @@ TEST_F(ResourcePrefetchPredictorTest, GetRedirectEndpoint) {
InitializeRedirectStat(google.add_redirect_endpoints(), InitializeRedirectStat(google.add_redirect_endpoints(),
GURL("https://google.ws"), 20, 20, 0); GURL("https://google.ws"), 20, 20, 0);
redirect_data.UpdateData(google.primary_key(), google); redirect_data.UpdateData(google.primary_key(), google);
EXPECT_FALSE(predictor_->GetRedirectEndpoint("google.com", redirect_data, EXPECT_FALSE(predictor_->GetRedirectOrigin(google_origin, redirect_data,
&redirect_endpoint)); &redirect_origin));
// Check the case of a redirect with no port or scheme in the database. The
// redirected origin should default to HTTPS on port 443, if either is
// missing.
url::Origin no_port_origin =
url::Origin::Create(GURL("https://no-port.test/"));
RedirectData no_port = CreateRedirectData(no_port_origin.host(), 1);
GURL no_port_redirect_url("http://redirect-destination.no-port.test/");
url::Origin no_port_redirect_origin =
url::Origin::Create(GURL("https://redirect-destination.no-port.test/"));
InitializeRedirectStat(no_port.add_redirect_endpoints(), no_port_redirect_url,
10, 0, 0, true /* include_scheme */,
false /* include_port */);
redirect_data.UpdateData(no_port.primary_key(), no_port);
EXPECT_TRUE(predictor_->GetRedirectOrigin(no_port_origin, redirect_data,
&redirect_origin));
EXPECT_EQ(no_port_redirect_origin, redirect_origin);
url::Origin no_scheme_origin =
url::Origin::Create(GURL("https://no-scheme.test/"));
RedirectData no_scheme = CreateRedirectData(no_scheme_origin.host(), 1);
GURL no_scheme_redirect_url("http://redirect-destination.no-scheme.test/");
url::Origin no_scheme_redirect_origin =
url::Origin::Create(GURL("https://redirect-destination.no-scheme.test/"));
InitializeRedirectStat(no_scheme.add_redirect_endpoints(),
no_scheme_redirect_url, 10, 0, 0,
true /* include_scheme */, false /* include_port */);
redirect_data.UpdateData(no_scheme.primary_key(), no_scheme);
EXPECT_TRUE(predictor_->GetRedirectOrigin(no_scheme_origin, redirect_data,
&redirect_origin));
EXPECT_EQ(no_scheme_redirect_origin, redirect_origin);
} }
TEST_F(ResourcePrefetchPredictorTest, TestPredictPreconnectOrigins) { TEST_F(ResourcePrefetchPredictorTest, TestPredictPreconnectOrigins) {
...@@ -731,13 +770,18 @@ TEST_F(ResourcePrefetchPredictorTest, TestPredictPreconnectOrigins) { ...@@ -731,13 +770,18 @@ TEST_F(ResourcePrefetchPredictorTest, TestPredictPreconnectOrigins) {
true); // High confidence - preconnect. true); // High confidence - preconnect.
predictor_->origin_data_->UpdateData(www_google.host(), www_google); predictor_->origin_data_->UpdateData(www_google.host(), www_google);
const url::Origin www_google_origin =
url::Origin::Create(GURL("https://www.google.com"));
const net::NetworkIsolationKey www_google_network_isolation_key(
www_google_origin, www_google_origin);
prediction = std::make_unique<PreconnectPrediction>(); prediction = std::make_unique<PreconnectPrediction>();
EXPECT_TRUE(predictor_->IsUrlPreconnectable(main_frame_url)); EXPECT_TRUE(predictor_->IsUrlPreconnectable(main_frame_url));
EXPECT_TRUE( EXPECT_TRUE(
predictor_->PredictPreconnectOrigins(main_frame_url, prediction.get())); predictor_->PredictPreconnectOrigins(main_frame_url, prediction.get()));
EXPECT_EQ(*prediction, CreatePreconnectPrediction("www.google.com", true, EXPECT_EQ(*prediction,
{{GURL(gen_origin(4)), 1, CreatePreconnectPrediction(
network_isolation_key}})); "www.google.com", true,
{{GURL(gen_origin(4)), 1, www_google_network_isolation_key}}));
} }
} // namespace predictors } // namespace predictors
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