Commit 25b2d89d authored by Matt Menke's avatar Matt Menke Committed by Commit Bot

Add NetworkIsolationKey support to PreconnectManager.

Currently, nothing passes in anything other than a default constructed
one. Consumers will be updated one-at-a-time in followup CLs, and the
default empty NetworkIsolationKey will be removed from method
declarations.

Bug: 966896
Change-Id: If5cc69299de2b0fc6886c304710ffa40423f9536
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1672147
Commit-Queue: Matt Menke <mmenke@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarAlex Ilin <alexilin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#680037}
parent c88869d0
...@@ -49,8 +49,10 @@ class MockPreconnectManager : public PreconnectManager { ...@@ -49,8 +49,10 @@ class MockPreconnectManager : public PreconnectManager {
MOCK_METHOD1(StartPreresolveHost, void(const GURL& url)); MOCK_METHOD1(StartPreresolveHost, void(const GURL& url));
MOCK_METHOD1(StartPreresolveHosts, MOCK_METHOD1(StartPreresolveHosts,
void(const std::vector<std::string>& hostnames)); void(const std::vector<std::string>& hostnames));
MOCK_METHOD2(StartPreconnectUrl, MOCK_METHOD3(StartPreconnectUrl,
void(const GURL& url, bool allow_credentials)); void(const GURL& url,
bool allow_credentials,
net::NetworkIsolationKey network_isolation_key));
MOCK_METHOD1(Stop, void(const GURL& url)); MOCK_METHOD1(Stop, void(const GURL& url));
void Start(const GURL& url, void Start(const GURL& url,
...@@ -303,7 +305,8 @@ TEST_F(LoadingPredictorTest, TestDontPredictOmniboxHints) { ...@@ -303,7 +305,8 @@ TEST_F(LoadingPredictorTest, TestDontPredictOmniboxHints) {
TEST_F(LoadingPredictorPreconnectTest, TestHandleOmniboxHint) { TEST_F(LoadingPredictorPreconnectTest, TestHandleOmniboxHint) {
const GURL preconnect_suggestion = GURL("http://search.com/kittens"); const GURL preconnect_suggestion = GURL("http://search.com/kittens");
EXPECT_CALL(*mock_preconnect_manager_, EXPECT_CALL(*mock_preconnect_manager_,
StartPreconnectUrl(preconnect_suggestion, true)); StartPreconnectUrl(preconnect_suggestion, true,
net::NetworkIsolationKey()));
predictor_->PrepareForPageLoad(preconnect_suggestion, HintOrigin::OMNIBOX, predictor_->PrepareForPageLoad(preconnect_suggestion, HintOrigin::OMNIBOX,
true); true);
// The second suggestion for the same host should be filtered out. // The second suggestion for the same host should be filtered out.
......
...@@ -46,10 +46,23 @@ PreresolveInfo::~PreresolveInfo() = default; ...@@ -46,10 +46,23 @@ PreresolveInfo::~PreresolveInfo() = default;
PreresolveJob::PreresolveJob(const GURL& url, PreresolveJob::PreresolveJob(const GURL& url,
int num_sockets, int num_sockets,
bool allow_credentials, bool allow_credentials,
net::NetworkIsolationKey network_isolation_key,
PreresolveInfo* info) PreresolveInfo* info)
: url(url), : url(url),
num_sockets(num_sockets), num_sockets(num_sockets),
allow_credentials(allow_credentials), allow_credentials(allow_credentials),
network_isolation_key(std::move(network_isolation_key)),
info(info) {
DCHECK_GE(num_sockets, 0);
}
PreresolveJob::PreresolveJob(PreconnectRequest preconnect_request,
PreresolveInfo* info)
: url(std::move(preconnect_request.origin)),
num_sockets(preconnect_request.num_sockets),
allow_credentials(preconnect_request.allow_credentials),
network_isolation_key(
std::move(preconnect_request.network_isolation_key)),
info(info) { info(info) {
DCHECK_GE(num_sockets, 0); DCHECK_GE(num_sockets, 0);
} }
...@@ -79,11 +92,11 @@ void PreconnectManager::Start(const GURL& url, ...@@ -79,11 +92,11 @@ void PreconnectManager::Start(const GURL& url,
host, std::make_unique<PreresolveInfo>(url, requests.size())); host, std::make_unique<PreresolveInfo>(url, requests.size()));
PreresolveInfo* info = iterator_and_whether_inserted.first->second.get(); PreresolveInfo* info = iterator_and_whether_inserted.first->second.get();
for (const auto& request : requests) { for (auto request_it = requests.begin(); request_it != requests.end();
DCHECK(request.origin.GetOrigin() == request.origin); ++request_it) {
DCHECK(request_it->origin.GetOrigin() == request_it->origin);
PreresolveJobId job_id = preresolve_jobs_.Add( PreresolveJobId job_id = preresolve_jobs_.Add(
std::make_unique<PreresolveJob>(request.origin, request.num_sockets, std::make_unique<PreresolveJob>(std::move(*request_it), info));
request.allow_credentials, info));
queued_jobs_.push_back(job_id); queued_jobs_.push_back(job_id);
} }
...@@ -95,7 +108,8 @@ void PreconnectManager::StartPreresolveHost(const GURL& url) { ...@@ -95,7 +108,8 @@ void PreconnectManager::StartPreresolveHost(const GURL& url) {
if (!url.SchemeIsHTTPOrHTTPS()) if (!url.SchemeIsHTTPOrHTTPS())
return; return;
PreresolveJobId job_id = preresolve_jobs_.Add(std::make_unique<PreresolveJob>( PreresolveJobId job_id = preresolve_jobs_.Add(std::make_unique<PreresolveJob>(
url.GetOrigin(), 0, kAllowCredentialsOnPreconnectByDefault, nullptr)); url.GetOrigin(), 0, kAllowCredentialsOnPreconnectByDefault,
net::NetworkIsolationKey(), nullptr));
queued_jobs_.push_front(job_id); queued_jobs_.push_front(job_id);
TryToLaunchPreresolveJobs(); TryToLaunchPreresolveJobs();
...@@ -109,20 +123,23 @@ void PreconnectManager::StartPreresolveHosts( ...@@ -109,20 +123,23 @@ void PreconnectManager::StartPreresolveHosts(
PreresolveJobId job_id = PreresolveJobId job_id =
preresolve_jobs_.Add(std::make_unique<PreresolveJob>( preresolve_jobs_.Add(std::make_unique<PreresolveJob>(
GURL("http://" + *it), 0, kAllowCredentialsOnPreconnectByDefault, GURL("http://" + *it), 0, kAllowCredentialsOnPreconnectByDefault,
nullptr)); net::NetworkIsolationKey(), nullptr));
queued_jobs_.push_front(job_id); queued_jobs_.push_front(job_id);
} }
TryToLaunchPreresolveJobs(); TryToLaunchPreresolveJobs();
} }
void PreconnectManager::StartPreconnectUrl(const GURL& url, void PreconnectManager::StartPreconnectUrl(
bool allow_credentials) { const GURL& url,
bool allow_credentials,
net::NetworkIsolationKey network_isolation_key) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (!url.SchemeIsHTTPOrHTTPS()) if (!url.SchemeIsHTTPOrHTTPS())
return; return;
PreresolveJobId job_id = preresolve_jobs_.Add(std::make_unique<PreresolveJob>( PreresolveJobId job_id = preresolve_jobs_.Add(std::make_unique<PreresolveJob>(
url.GetOrigin(), 1, allow_credentials, nullptr)); url.GetOrigin(), 1, allow_credentials, std::move(network_isolation_key),
nullptr));
queued_jobs_.push_front(job_id); queued_jobs_.push_front(job_id);
TryToLaunchPreresolveJobs(); TryToLaunchPreresolveJobs();
...@@ -138,9 +155,11 @@ void PreconnectManager::Stop(const GURL& url) { ...@@ -138,9 +155,11 @@ void PreconnectManager::Stop(const GURL& url) {
it->second->was_canceled = true; it->second->was_canceled = true;
} }
void PreconnectManager::PreconnectUrl(const GURL& url, void PreconnectManager::PreconnectUrl(
int num_sockets, const GURL& url,
bool allow_credentials) const { int num_sockets,
bool allow_credentials,
const net::NetworkIsolationKey& network_isolation_key) const {
DCHECK(url.GetOrigin() == url); DCHECK(url.GetOrigin() == url);
DCHECK(url.SchemeIsHTTPOrHTTPS()); DCHECK(url.SchemeIsHTTPOrHTTPS());
if (observer_) if (observer_)
...@@ -159,9 +178,8 @@ void PreconnectManager::PreconnectUrl(const GURL& url, ...@@ -159,9 +178,8 @@ void PreconnectManager::PreconnectUrl(const GURL& url,
net::LOAD_DO_NOT_SEND_AUTH_DATA; net::LOAD_DO_NOT_SEND_AUTH_DATA;
} }
// TODO(mmenke): Use an appropriate NetworkIsolationKey().
network_context->PreconnectSockets(num_sockets, url, load_flags, privacy_mode, network_context->PreconnectSockets(num_sockets, url, load_flags, privacy_mode,
net::NetworkIsolationKey()); network_isolation_key);
} }
std::unique_ptr<ResolveHostClientImpl> PreconnectManager::PreresolveUrl( std::unique_ptr<ResolveHostClientImpl> PreconnectManager::PreresolveUrl(
...@@ -275,8 +293,10 @@ void PreconnectManager::FinishPreresolveJob(PreresolveJobId job_id, ...@@ -275,8 +293,10 @@ void PreconnectManager::FinishPreresolveJob(PreresolveJobId job_id,
DCHECK(job); DCHECK(job);
bool need_preconnect = success && job->need_preconnect(); bool need_preconnect = success && job->need_preconnect();
if (need_preconnect) if (need_preconnect) {
PreconnectUrl(job->url, job->num_sockets, job->allow_credentials); PreconnectUrl(job->url, job->num_sockets, job->allow_credentials,
job->network_isolation_key);
}
PreresolveInfo* info = job->info; PreresolveInfo* info = job->info;
if (info) if (info)
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "chrome/browser/predictors/proxy_lookup_client_impl.h" #include "chrome/browser/predictors/proxy_lookup_client_impl.h"
#include "chrome/browser/predictors/resolve_host_client_impl.h" #include "chrome/browser/predictors/resolve_host_client_impl.h"
#include "chrome/browser/predictors/resource_prefetch_predictor.h" #include "chrome/browser/predictors/resource_prefetch_predictor.h"
#include "net/base/network_isolation_key.h"
#include "url/gurl.h" #include "url/gurl.h"
class Profile; class Profile;
...@@ -75,7 +76,9 @@ struct PreresolveJob { ...@@ -75,7 +76,9 @@ struct PreresolveJob {
PreresolveJob(const GURL& url, PreresolveJob(const GURL& url,
int num_sockets, int num_sockets,
bool allow_credentials, bool allow_credentials,
net::NetworkIsolationKey network_isolation_key,
PreresolveInfo* info); PreresolveInfo* info);
PreresolveJob(PreconnectRequest preconnect_request, PreresolveInfo* info);
PreresolveJob(PreresolveJob&& other); PreresolveJob(PreresolveJob&& other);
~PreresolveJob(); ~PreresolveJob();
bool need_preconnect() const { bool need_preconnect() const {
...@@ -85,8 +88,9 @@ struct PreresolveJob { ...@@ -85,8 +88,9 @@ struct PreresolveJob {
GURL url; GURL url;
int num_sockets; int num_sockets;
bool allow_credentials; bool allow_credentials;
net::NetworkIsolationKey network_isolation_key;
// Raw pointer usage is fine here because even though PreresolveJob can // Raw pointer usage is fine here because even though PreresolveJob can
// outlive PreresolveInfo it's only accessed on PreconnectManager class // outlive PreresolveInfo. It's only accessed on PreconnectManager class
// context and PreresolveInfo lifetime is tied to PreconnectManager. // context and PreresolveInfo lifetime is tied to PreconnectManager.
// May be equal to nullptr in case of detached job. // May be equal to nullptr in case of detached job.
PreresolveInfo* info; PreresolveInfo* info;
...@@ -145,7 +149,19 @@ class PreconnectManager { ...@@ -145,7 +149,19 @@ class PreconnectManager {
// than trackable requests thus they are put in the front of the jobs queue. // than trackable requests thus they are put in the front of the jobs queue.
virtual void StartPreresolveHost(const GURL& url); virtual void StartPreresolveHost(const GURL& url);
virtual void StartPreresolveHosts(const std::vector<std::string>& hostnames); virtual void StartPreresolveHosts(const std::vector<std::string>& hostnames);
virtual void StartPreconnectUrl(const GURL& url, bool allow_credentials); // |network_isolation_key| specifies the key that network requests for the
// preconnected URL are expected to use. If a request is issued with a
// different key, it may not use the preconnected socket.
//
// TODO(https://crbug.com/966896): Update consumers and make
// |network_isolation_key| a mandatory argument. Note that this is a temporary
// style guide violation, but keeping this until all consumers correctly fill
// the argument reduces the chances of forgetting to update one.
virtual void StartPreconnectUrl(
const GURL& url,
bool allow_credentials,
net::NetworkIsolationKey network_isolation_key =
net::NetworkIsolationKey());
// No additional jobs keyed by the |url| will be queued after this. // No additional jobs keyed by the |url| will be queued after this.
virtual void Stop(const GURL& url); virtual void Stop(const GURL& url);
...@@ -166,9 +182,11 @@ class PreconnectManager { ...@@ -166,9 +182,11 @@ class PreconnectManager {
using PreresolveJobId = PreresolveJobMap::KeyType; using PreresolveJobId = PreresolveJobMap::KeyType;
friend class PreconnectManagerTest; friend class PreconnectManagerTest;
void PreconnectUrl(const GURL& url, void PreconnectUrl(
int num_sockets, const GURL& url,
bool allow_credentials) const; int num_sockets,
bool allow_credentials,
const net::NetworkIsolationKey& network_isolation_key) const;
std::unique_ptr<ResolveHostClientImpl> PreresolveUrl( std::unique_ptr<ResolveHostClientImpl> PreresolveUrl(
const GURL& url, const GURL& url,
ResolveHostCallback callback) const; ResolveHostCallback callback) const;
......
...@@ -219,6 +219,27 @@ TEST_F(PreconnectManagerTest, TestStartOneUrlPreconnect) { ...@@ -219,6 +219,27 @@ TEST_F(PreconnectManagerTest, TestStartOneUrlPreconnect) {
mock_network_context_->CompleteHostLookup(url_to_preconnect.host(), net::OK); mock_network_context_->CompleteHostLookup(url_to_preconnect.host(), net::OK);
} }
TEST_F(PreconnectManagerTest,
TestStartOneUrlPreconnectWithNetworkIsolationKey) {
GURL main_frame_url("http://google.com");
GURL url_to_preconnect("http://cdn.google.com");
url::Origin requesting_origin = url::Origin::Create(GURL("http://foo.test"));
net::NetworkIsolationKey network_isolation_key(requesting_origin,
requesting_origin);
EXPECT_CALL(*mock_network_context_,
ResolveHostProxy(url_to_preconnect.host()));
preconnect_manager_->Start(
main_frame_url,
{PreconnectRequest(url_to_preconnect, 1, network_isolation_key)});
EXPECT_CALL(*mock_network_context_,
PreconnectSockets(1, url_to_preconnect, kNormalLoadFlags,
false /* privacy_mode_enabled */,
network_isolation_key));
EXPECT_CALL(*mock_delegate_, PreconnectFinishedProxy(main_frame_url));
mock_network_context_->CompleteHostLookup(url_to_preconnect.host(), net::OK);
}
// Sends preconnect request for a webpage, and stops the request before // Sends preconnect request for a webpage, and stops the request before
// all pertaining preconnect requests finish. Next, preconnect request // all pertaining preconnect requests finish. Next, preconnect request
// for the same webpage is sent again. Verifies that all the preconnects // for the same webpage is sent again. Verifies that all the preconnects
...@@ -599,7 +620,8 @@ TEST_F(PreconnectManagerTest, TestStartPreconnectUrl) { ...@@ -599,7 +620,8 @@ TEST_F(PreconnectManagerTest, TestStartPreconnectUrl) {
bool allow_credentials = false; bool allow_credentials = false;
EXPECT_CALL(*mock_network_context_, ResolveHostProxy(origin.host())); EXPECT_CALL(*mock_network_context_, ResolveHostProxy(origin.host()));
preconnect_manager_->StartPreconnectUrl(url, allow_credentials); preconnect_manager_->StartPreconnectUrl(url, allow_credentials,
net::NetworkIsolationKey());
EXPECT_CALL( EXPECT_CALL(
*mock_network_context_, *mock_network_context_,
...@@ -609,7 +631,26 @@ TEST_F(PreconnectManagerTest, TestStartPreconnectUrl) { ...@@ -609,7 +631,26 @@ TEST_F(PreconnectManagerTest, TestStartPreconnectUrl) {
// Non http url shouldn't be preconnected. // Non http url shouldn't be preconnected.
GURL non_http_url("file:///tmp/index.html"); GURL non_http_url("file:///tmp/index.html");
preconnect_manager_->StartPreconnectUrl(non_http_url, allow_credentials); preconnect_manager_->StartPreconnectUrl(non_http_url, allow_credentials,
net::NetworkIsolationKey());
}
TEST_F(PreconnectManagerTest, TestStartPreconnectUrlWithNetworkIsolationKey) {
GURL url("http://cdn.google.com/script.js");
GURL origin("http://cdn.google.com");
bool allow_credentials = false;
url::Origin requesting_origin = url::Origin::Create(GURL("http://foo.test"));
net::NetworkIsolationKey network_isolation_key(requesting_origin,
requesting_origin);
EXPECT_CALL(*mock_network_context_, ResolveHostProxy(origin.host()));
preconnect_manager_->StartPreconnectUrl(url, allow_credentials,
network_isolation_key);
EXPECT_CALL(*mock_network_context_,
PreconnectSockets(1, origin, kPrivateLoadFlags,
!allow_credentials, network_isolation_key));
mock_network_context_->CompleteHostLookup(origin.host(), net::OK);
} }
TEST_F(PreconnectManagerTest, TestDetachedRequestHasHigherPriority) { TEST_F(PreconnectManagerTest, TestDetachedRequestHasHigherPriority) {
......
...@@ -59,8 +59,13 @@ void InitializeOnDBSequence( ...@@ -59,8 +59,13 @@ void InitializeOnDBSequence(
} // namespace } // namespace
PreconnectRequest::PreconnectRequest(const GURL& origin, int num_sockets) PreconnectRequest::PreconnectRequest(
: origin(origin), num_sockets(num_sockets) { const GURL& origin,
int num_sockets,
net::NetworkIsolationKey network_isolation_key)
: origin(origin),
num_sockets(num_sockets),
network_isolation_key(std::move(network_isolation_key)) {
DCHECK_GE(num_sockets, 0); DCHECK_GE(num_sockets, 0);
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "base/gtest_prod_util.h" #include "base/gtest_prod_util.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/scoped_observer.h" #include "base/scoped_observer.h"
#include "base/task/cancelable_task_tracker.h" #include "base/task/cancelable_task_tracker.h"
#include "base/time/time.h" #include "base/time/time.h"
...@@ -28,6 +29,7 @@ ...@@ -28,6 +29,7 @@
#include "components/history/core/browser/history_types.h" #include "components/history/core/browser/history_types.h"
#include "components/keyed_service/core/keyed_service.h" #include "components/keyed_service/core/keyed_service.h"
#include "content/public/common/resource_type.h" #include "content/public/common/resource_type.h"
#include "net/base/network_isolation_key.h"
#include "url/gurl.h" #include "url/gurl.h"
class PredictorsHandler; class PredictorsHandler;
...@@ -54,12 +56,23 @@ class ResourcePrefetcherManager; ...@@ -54,12 +56,23 @@ class ResourcePrefetcherManager;
// Stores all values needed to trigger a preconnect/preresolve job to a single // Stores all values needed to trigger a preconnect/preresolve job to a single
// origin. // origin.
struct PreconnectRequest { struct PreconnectRequest {
PreconnectRequest(const GURL& origin, int num_sockets); // |network_isolation_key| specifies the key that network requests for the
// preconnected URL are expected to use. If a request is issued with a
// different key, it may not use the preconnected socket. It has no effect
// when |num_sockets| == 0.
//
// TODO(https://crbug.com/966896): Update consumers and make
// |network_isolation_key| a mandatory argument.
PreconnectRequest(const GURL& origin,
int num_sockets,
net::NetworkIsolationKey network_isolation_key =
net::NetworkIsolationKey());
GURL origin; GURL origin;
// A zero-value means that we need to preresolve a host only. // A zero-value means that we need to preresolve a host only.
int num_sockets = 0; int num_sockets = 0;
bool allow_credentials = true; bool allow_credentials = true;
net::NetworkIsolationKey network_isolation_key;
}; };
// Stores a result of preconnect prediction. The |requests| vector is the main // Stores a result of preconnect prediction. The |requests| vector is the main
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "content/public/browser/notification_service.h" #include "content/public/browser/notification_service.h"
#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host.h"
#include "extensions/buildflags/buildflags.h" #include "extensions/buildflags/buildflags.h"
#include "net/base/network_isolation_key.h"
#include "ppapi/buildflags/buildflags.h" #include "ppapi/buildflags/buildflags.h"
#if BUILDFLAG(ENABLE_EXTENSIONS) #if BUILDFLAG(ENABLE_EXTENSIONS)
...@@ -130,12 +131,17 @@ void ChromeRenderMessageFilter::OnPreconnect(const GURL& url, ...@@ -130,12 +131,17 @@ void ChromeRenderMessageFilter::OnPreconnect(const GURL& url,
return; return;
} }
if (preconnect_manager_initialized_) { if (!preconnect_manager_initialized_)
base::PostTaskWithTraits( return;
FROM_HERE, {BrowserThread::UI},
base::BindOnce(&predictors::PreconnectManager::StartPreconnectUrl, // TODO(mmenke): Use process and frame ids to populate NetworkIsolationKey.
preconnect_manager_, url, allow_credentials)); // May also need to think about enabling cross-site preconnects, though that
} // will result in at least some cross-site information leakage.
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(&predictors::PreconnectManager::StartPreconnectUrl,
preconnect_manager_, url, allow_credentials,
net::NetworkIsolationKey()));
} }
void ChromeRenderMessageFilter::OnAllowDatabase( void ChromeRenderMessageFilter::OnAllowDatabase(
......
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