Commit 49527403 authored by Alexandr Ilin's avatar Alexandr Ilin Committed by Commit Bot

predictors: Return HostResolver::Request from content::PreresolveUrl()

This CL changes the signature of content::PreresolveUrl() so that the
method returns a net::HostResolver::Request object to a caller instead
of holding it inside of the callback state. It is done to guarantee
that there won't be hanging requests after a caller is shut down.

There are only two callers of this method:
chrome_browser_net::Predictor and predictors::PreconnectManager.
They become responsible for keeping Request objects alive.

Bug: 845648
Change-Id: Ie057cde65288341b14813d4df4d7d90a02f588b6
Reviewed-on: https://chromium-review.googlesource.com/1080818
Commit-Queue: Alexandr Ilin <alexilin@chromium.org>
Reviewed-by: default avatarMatt Menke <mmenke@chromium.org>
Reviewed-by: default avatarCharlie Harrison <csharrison@chromium.org>
Reviewed-by: default avatarBenoit L <lizeb@chromium.org>
Reviewed-by: default avatarCamille Lamy <clamy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#564866}
parent 1f8391bb
...@@ -416,21 +416,21 @@ void Predictor::DiscardAllResults() { ...@@ -416,21 +416,21 @@ void Predictor::DiscardAllResults() {
// Step through result_, recording names of all hosts that can't be erased. // Step through result_, recording names of all hosts that can't be erased.
// We can't erase anything being worked on. // We can't erase anything being worked on.
Results assignees; Results assignees;
for (Results::iterator it = results_.begin(); results_.end() != it; ++it) { for (auto& result : results_) {
GURL url(it->first); const GURL& url = result.first;
UrlInfo* info = &it->second; UrlInfo& info = result.second;
DCHECK(info->HasUrl(url)); DCHECK(info.HasUrl(url));
if (info->is_assigned()) { if (info.is_assigned()) {
info->SetPendingDeleteState(); info.SetPendingDeleteState();
assignees[url] = *info; assignees[url] = std::move(info);
} }
} }
DCHECK_LE(assignees.size(), max_concurrent_dns_lookups_); DCHECK_LE(assignees.size(), max_concurrent_dns_lookups_);
results_.clear(); results_.clear();
// Put back in the names being worked on. // Put back in the names being worked on.
for (Results::iterator it = assignees.begin(); assignees.end() != it; ++it) { for (auto& assignee : assignees) {
DCHECK(it->second.is_marked_to_delete()); DCHECK(assignee.second.is_marked_to_delete());
results_[it->first] = it->second; results_[assignee.first] = std::move(assignee.second);
} }
} }
...@@ -920,10 +920,13 @@ void Predictor::StartSomeQueuedResolutions() { ...@@ -920,10 +920,13 @@ void Predictor::StartSomeQueuedResolutions() {
} }
info->SetPendingDeleteState(); info->SetPendingDeleteState();
std::unique_ptr<net::HostResolver::Request> request;
int status = int status =
content::PreresolveUrl(url_request_context_getter_.get(), url, content::PreresolveUrl(url_request_context_getter_.get(), url,
base::Bind(&Predictor::OnLookupFinished, base::Bind(&Predictor::OnLookupFinished,
io_weak_factory_->GetWeakPtr(), url)); io_weak_factory_->GetWeakPtr(), url),
&request);
info->set_request(std::move(request));
if (status == net::ERR_IO_PENDING) { if (status == net::ERR_IO_PENDING) {
// Will complete asynchronously. // Will complete asynchronously.
num_pending_lookups_++; num_pending_lookups_++;
......
...@@ -79,7 +79,8 @@ UrlInfo::UrlInfo() ...@@ -79,7 +79,8 @@ UrlInfo::UrlInfo()
was_linked_(false) { was_linked_(false) {
} }
UrlInfo::UrlInfo(const UrlInfo& other) = default; UrlInfo::UrlInfo(UrlInfo&& other) = default;
UrlInfo& UrlInfo::operator=(UrlInfo&& other) = default;
UrlInfo::~UrlInfo() {} UrlInfo::~UrlInfo() {}
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "net/base/host_port_pair.h" #include "net/base/host_port_pair.h"
#include "net/dns/host_resolver.h"
#include "url/gurl.h" #include "url/gurl.h"
namespace chrome_browser_net { namespace chrome_browser_net {
...@@ -72,7 +73,8 @@ class UrlInfo { ...@@ -72,7 +73,8 @@ class UrlInfo {
// initializing of the Predictor's map (of info for Hostnames). // initializing of the Predictor's map (of info for Hostnames).
UrlInfo(); UrlInfo();
UrlInfo(const UrlInfo& other); UrlInfo(UrlInfo&& other);
UrlInfo& operator=(UrlInfo&& other);
~UrlInfo(); ~UrlInfo();
...@@ -120,6 +122,10 @@ class UrlInfo { ...@@ -120,6 +122,10 @@ class UrlInfo {
// transition, and this call is not made. // transition, and this call is not made.
void set_time(const base::TimeTicks& time) { time_ = time; } void set_time(const base::TimeTicks& time) { time_ = time; }
void set_request(std::unique_ptr<net::HostResolver::Request> request) {
request_ = std::move(request);
}
private: private:
base::TimeDelta GetDuration() { base::TimeDelta GetDuration() {
base::TimeTicks old_time = time_; base::TimeTicks old_time = time_;
...@@ -159,9 +165,10 @@ class UrlInfo { ...@@ -159,9 +165,10 @@ class UrlInfo {
// Record if the motivation for prefetching was ever a page-link-scan. // Record if the motivation for prefetching was ever a page-link-scan.
bool was_linked_; bool was_linked_;
// We put these objects into a std::map, and hence we // Request object cancels the request to the host resolver on deletion.
// need some "evil" constructors. std::unique_ptr<net::HostResolver::Request> request_;
// DISALLOW_COPY_AND_ASSIGN(UrlInfo);
DISALLOW_COPY_AND_ASSIGN(UrlInfo);
}; };
} // namespace chrome_browser_net } // namespace chrome_browser_net
......
...@@ -55,7 +55,7 @@ PreresolveJob::PreresolveJob(const GURL& url, ...@@ -55,7 +55,7 @@ PreresolveJob::PreresolveJob(const GURL& url,
DCHECK_GE(num_sockets, 0); DCHECK_GE(num_sockets, 0);
} }
PreresolveJob::PreresolveJob(const PreresolveJob& other) = default; PreresolveJob::PreresolveJob(PreresolveJob&& other) = default;
PreresolveJob::~PreresolveJob() = default; PreresolveJob::~PreresolveJob() = default;
PreconnectManager::PreconnectManager( PreconnectManager::PreconnectManager(
...@@ -86,8 +86,10 @@ void PreconnectManager::Start(const GURL& url, ...@@ -86,8 +86,10 @@ void PreconnectManager::Start(const GURL& url,
for (const auto& request : requests) { for (const auto& request : requests) {
DCHECK(request.origin.GetOrigin() == request.origin); DCHECK(request.origin.GetOrigin() == request.origin);
queued_jobs_.emplace_back(request.origin, request.num_sockets, PreresolveJobId job_id = preresolve_jobs_.Add(
request.allow_credentials, info); std::make_unique<PreresolveJob>(request.origin, request.num_sockets,
request.allow_credentials, info));
queued_jobs_.push_back(job_id);
} }
TryToLaunchPreresolveJobs(); TryToLaunchPreresolveJobs();
...@@ -97,8 +99,9 @@ void PreconnectManager::StartPreresolveHost(const GURL& url) { ...@@ -97,8 +99,9 @@ void PreconnectManager::StartPreresolveHost(const GURL& url) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
if (!url.SchemeIsHTTPOrHTTPS()) if (!url.SchemeIsHTTPOrHTTPS())
return; return;
queued_jobs_.emplace_front(url.GetOrigin(), 0, PreresolveJobId job_id = preresolve_jobs_.Add(std::make_unique<PreresolveJob>(
kAllowCredentialsOnPreconnectByDefault, nullptr); url.GetOrigin(), 0, kAllowCredentialsOnPreconnectByDefault, nullptr));
queued_jobs_.push_front(job_id);
TryToLaunchPreresolveJobs(); TryToLaunchPreresolveJobs();
} }
...@@ -108,8 +111,11 @@ void PreconnectManager::StartPreresolveHosts( ...@@ -108,8 +111,11 @@ void PreconnectManager::StartPreresolveHosts(
DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
// Push jobs in front of the queue due to higher priority. // Push jobs in front of the queue due to higher priority.
for (auto it = hostnames.rbegin(); it != hostnames.rend(); ++it) { for (auto it = hostnames.rbegin(); it != hostnames.rend(); ++it) {
queued_jobs_.emplace_front(GURL("http://" + *it), 0, PreresolveJobId job_id =
kAllowCredentialsOnPreconnectByDefault, nullptr); preresolve_jobs_.Add(std::make_unique<PreresolveJob>(
GURL("http://" + *it), 0, kAllowCredentialsOnPreconnectByDefault,
nullptr));
queued_jobs_.push_front(job_id);
} }
TryToLaunchPreresolveJobs(); TryToLaunchPreresolveJobs();
...@@ -120,7 +126,9 @@ void PreconnectManager::StartPreconnectUrl(const GURL& url, ...@@ -120,7 +126,9 @@ void PreconnectManager::StartPreconnectUrl(const GURL& url,
DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
if (!url.SchemeIsHTTPOrHTTPS()) if (!url.SchemeIsHTTPOrHTTPS())
return; return;
queued_jobs_.emplace_front(url.GetOrigin(), 1, allow_credentials, nullptr); PreresolveJobId job_id = preresolve_jobs_.Add(std::make_unique<PreresolveJob>(
url.GetOrigin(), 1, allow_credentials, nullptr));
queued_jobs_.push_front(job_id);
TryToLaunchPreresolveJobs(); TryToLaunchPreresolveJobs();
} }
...@@ -145,12 +153,16 @@ void PreconnectManager::PreconnectUrl(const GURL& url, ...@@ -145,12 +153,16 @@ void PreconnectManager::PreconnectUrl(const GURL& url,
num_sockets, allow_credentials); num_sockets, allow_credentials);
} }
int PreconnectManager::PreresolveUrl( std::pair<int, std::unique_ptr<net::HostResolver::Request>>
PreconnectManager::PreresolveUrl(
const GURL& url, const GURL& url,
const net::CompletionCallback& callback) const { const net::CompletionCallback& callback) const {
DCHECK(url.GetOrigin() == url); DCHECK(url.GetOrigin() == url);
DCHECK(url.SchemeIsHTTPOrHTTPS()); DCHECK(url.SchemeIsHTTPOrHTTPS());
return content::PreresolveUrl(context_getter_.get(), url, callback); std::unique_ptr<net::HostResolver::Request> request;
int status =
content::PreresolveUrl(context_getter_.get(), url, callback, &request);
return {status, std::move(request)};
} }
void PreconnectManager::TryToLaunchPreresolveJobs() { void PreconnectManager::TryToLaunchPreresolveJobs() {
...@@ -158,18 +170,21 @@ void PreconnectManager::TryToLaunchPreresolveJobs() { ...@@ -158,18 +170,21 @@ void PreconnectManager::TryToLaunchPreresolveJobs() {
while (!queued_jobs_.empty() && while (!queued_jobs_.empty() &&
inflight_preresolves_count_ < kMaxInflightPreresolves) { inflight_preresolves_count_ < kMaxInflightPreresolves) {
auto& job = queued_jobs_.front(); auto job_id = queued_jobs_.front();
PreresolveInfo* info = job.info; queued_jobs_.pop_front();
PreresolveJob* job = preresolve_jobs_.Lookup(job_id);
DCHECK(job);
PreresolveInfo* info = job->info;
if (!info || !info->was_canceled) { if (!info || !info->was_canceled) {
int status; int status;
if (WouldLikelyProxyURL(job.url)) { if (WouldLikelyProxyURL(job->url)) {
// Skip preresolve and go straight to preconnect if a proxy is enabled. // Skip preresolve and go straight to preconnect if a proxy is enabled.
status = net::OK; status = net::OK;
} else { } else {
status = PreresolveUrl( std::tie(status, job->request) = PreresolveUrl(
job.url, base::Bind(&PreconnectManager::OnPreresolveFinished, job->url, base::Bind(&PreconnectManager::OnPreresolveFinished,
weak_factory_.GetWeakPtr(), job)); weak_factory_.GetWeakPtr(), job_id));
} }
if (status == net::ERR_IO_PENDING) { if (status == net::ERR_IO_PENDING) {
...@@ -181,11 +196,12 @@ void PreconnectManager::TryToLaunchPreresolveJobs() { ...@@ -181,11 +196,12 @@ void PreconnectManager::TryToLaunchPreresolveJobs() {
// Completed synchronously (was already cached by HostResolver), or else // Completed synchronously (was already cached by HostResolver), or else
// there was (equivalently) some network error that prevents us from // there was (equivalently) some network error that prevents us from
// finding the name. Status net::OK means it was "found." // finding the name. Status net::OK means it was "found."
FinishPreresolve(job, status == net::OK, true); FinishPreresolve(job_id, status == net::OK, true);
} }
} else {
preresolve_jobs_.Remove(job_id);
} }
queued_jobs_.pop_front();
if (info) if (info)
--info->queued_count; --info->queued_count;
if (info && info->is_done()) if (info && info->is_done())
...@@ -193,11 +209,14 @@ void PreconnectManager::TryToLaunchPreresolveJobs() { ...@@ -193,11 +209,14 @@ void PreconnectManager::TryToLaunchPreresolveJobs() {
} }
} }
void PreconnectManager::OnPreresolveFinished(const PreresolveJob& job, void PreconnectManager::OnPreresolveFinished(PreresolveJobId job_id,
int result) { int result) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
FinishPreresolve(job, result == net::OK, false); PreresolveJob* job = preresolve_jobs_.Lookup(job_id);
PreresolveInfo* info = job.info; DCHECK(job);
PreresolveInfo* info = job->info;
FinishPreresolve(job_id, result == net::OK, false);
--inflight_preresolves_count_; --inflight_preresolves_count_;
if (info) if (info)
--info->inflight_count; --info->inflight_count;
...@@ -206,19 +225,23 @@ void PreconnectManager::OnPreresolveFinished(const PreresolveJob& job, ...@@ -206,19 +225,23 @@ void PreconnectManager::OnPreresolveFinished(const PreresolveJob& job,
TryToLaunchPreresolveJobs(); TryToLaunchPreresolveJobs();
} }
void PreconnectManager::FinishPreresolve(const PreresolveJob& job, void PreconnectManager::FinishPreresolve(PreresolveJobId job_id,
bool found, bool found,
bool cached) { bool cached) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
PreresolveInfo* info = job.info; PreresolveJob* job = preresolve_jobs_.Lookup(job_id);
DCHECK(job);
PreresolveInfo* info = job->info;
bool need_preconnect = bool need_preconnect =
found && job.need_preconnect() && (!info || !info->was_canceled); found && job->need_preconnect() && (!info || !info->was_canceled);
if (need_preconnect) { if (need_preconnect) {
PreconnectUrl(GetHSTSRedirect(job.url), info ? info->url : GURL(), PreconnectUrl(GetHSTSRedirect(job->url), info ? info->url : GURL(),
job.num_sockets, job.allow_credentials); job->num_sockets, job->allow_credentials);
} }
if (info && found) if (info && found)
info->stats->requests_stats.emplace_back(job.url, cached, need_preconnect); info->stats->requests_stats.emplace_back(job->url, cached, need_preconnect);
preresolve_jobs_.Remove(job_id);
} }
void PreconnectManager::AllPreresolvesForUrlFinished(PreresolveInfo* info) { void PreconnectManager::AllPreresolvesForUrlFinished(PreresolveInfo* info) {
......
...@@ -11,9 +11,11 @@ ...@@ -11,9 +11,11 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "base/containers/id_map.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "net/base/completion_callback.h" #include "net/base/completion_callback.h"
#include "net/dns/host_resolver.h"
#include "net/http/http_request_info.h" #include "net/http/http_request_info.h"
#include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_context_getter.h"
#include "url/gurl.h" #include "url/gurl.h"
...@@ -69,7 +71,7 @@ struct PreresolveJob { ...@@ -69,7 +71,7 @@ struct PreresolveJob {
int num_sockets, int num_sockets,
bool allow_credentials, bool allow_credentials,
PreresolveInfo* info); PreresolveInfo* info);
PreresolveJob(const PreresolveJob& other); PreresolveJob(PreresolveJob&& other);
~PreresolveJob(); ~PreresolveJob();
bool need_preconnect() const { return num_sockets > 0; } bool need_preconnect() const { return num_sockets > 0; }
...@@ -81,6 +83,9 @@ struct PreresolveJob { ...@@ -81,6 +83,9 @@ struct PreresolveJob {
// 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;
std::unique_ptr<net::HostResolver::Request> request;
DISALLOW_COPY_AND_ASSIGN(PreresolveJob);
}; };
// PreconnectManager is responsible for preresolving and preconnecting to // PreconnectManager is responsible for preresolving and preconnecting to
...@@ -132,20 +137,25 @@ class PreconnectManager { ...@@ -132,20 +137,25 @@ class PreconnectManager {
const GURL& site_for_cookies, const GURL& site_for_cookies,
int num_sockets, int num_sockets,
bool allow_credentials) const; bool allow_credentials) const;
virtual int PreresolveUrl(const GURL& url, virtual std::pair<int, std::unique_ptr<net::HostResolver::Request>>
const net::CompletionCallback& callback) const; PreresolveUrl(const GURL& url, const net::CompletionCallback& callback) const;
private: private:
using PreresolveJobMap = base::IDMap<std::unique_ptr<PreresolveJob>>;
using PreresolveJobId = PreresolveJobMap::KeyType;
friend class PreconnectManagerTest;
void TryToLaunchPreresolveJobs(); void TryToLaunchPreresolveJobs();
void OnPreresolveFinished(const PreresolveJob& job, int result); void OnPreresolveFinished(PreresolveJobId job_id, int result);
void FinishPreresolve(const PreresolveJob& job, bool found, bool cached); void FinishPreresolve(PreresolveJobId job_id, bool found, bool cached);
void AllPreresolvesForUrlFinished(PreresolveInfo* info); void AllPreresolvesForUrlFinished(PreresolveInfo* info);
GURL GetHSTSRedirect(const GURL& url) const; GURL GetHSTSRedirect(const GURL& url) const;
bool WouldLikelyProxyURL(const GURL& url) const; bool WouldLikelyProxyURL(const GURL& url) const;
base::WeakPtr<Delegate> delegate_; base::WeakPtr<Delegate> delegate_;
scoped_refptr<net::URLRequestContextGetter> context_getter_; scoped_refptr<net::URLRequestContextGetter> context_getter_;
std::list<PreresolveJob> queued_jobs_; std::list<PreresolveJobId> queued_jobs_;
PreresolveJobMap preresolve_jobs_;
std::map<std::string, std::unique_ptr<PreresolveInfo>> preresolve_info_; std::map<std::string, std::unique_ptr<PreresolveInfo>> preresolve_info_;
size_t inflight_preresolves_count_ = 0; size_t inflight_preresolves_count_ = 0;
......
...@@ -48,12 +48,18 @@ class MockPreconnectManager : public PreconnectManager { ...@@ -48,12 +48,18 @@ class MockPreconnectManager : public PreconnectManager {
base::WeakPtr<Delegate> delegate, base::WeakPtr<Delegate> delegate,
scoped_refptr<net::URLRequestContextGetter> context_getter); scoped_refptr<net::URLRequestContextGetter> context_getter);
std::pair<int, std::unique_ptr<net::HostResolver::Request>> PreresolveUrl(
const GURL& url,
const net::CompletionCallback& callback) const override {
return {PreresolveUrlProxy(url, callback), nullptr};
}
MOCK_CONST_METHOD4(PreconnectUrl, MOCK_CONST_METHOD4(PreconnectUrl,
void(const GURL& url, void(const GURL& url,
const GURL& site_for_cookies, const GURL& site_for_cookies,
int num_sockets, int num_sockets,
bool allow_credentials)); bool allow_credentials));
MOCK_CONST_METHOD2(PreresolveUrl, MOCK_CONST_METHOD2(PreresolveUrlProxy,
int(const GURL& url, int(const GURL& url,
const net::CompletionCallback& callback)); const net::CompletionCallback& callback));
}; };
...@@ -93,7 +99,7 @@ TEST_F(PreconnectManagerTest, TestStartOneUrlPreresolve) { ...@@ -93,7 +99,7 @@ TEST_F(PreconnectManagerTest, TestStartOneUrlPreresolve) {
GURL main_frame_url("http://google.com"); GURL main_frame_url("http://google.com");
GURL url_to_preresolve("http://cdn.google.com"); GURL url_to_preresolve("http://cdn.google.com");
EXPECT_CALL(*preconnect_manager_, PreresolveUrl(url_to_preresolve, _)) EXPECT_CALL(*preconnect_manager_, PreresolveUrlProxy(url_to_preresolve, _))
.WillOnce(Return(net::OK)); .WillOnce(Return(net::OK));
EXPECT_CALL(*mock_delegate_, PreconnectFinishedProxy(main_frame_url)); EXPECT_CALL(*mock_delegate_, PreconnectFinishedProxy(main_frame_url));
preconnect_manager_->Start(main_frame_url, preconnect_manager_->Start(main_frame_url,
...@@ -106,7 +112,7 @@ TEST_F(PreconnectManagerTest, TestStartOneUrlPreconnect) { ...@@ -106,7 +112,7 @@ TEST_F(PreconnectManagerTest, TestStartOneUrlPreconnect) {
GURL main_frame_url("http://google.com"); GURL main_frame_url("http://google.com");
GURL url_to_preconnect("http://cdn.google.com"); GURL url_to_preconnect("http://cdn.google.com");
EXPECT_CALL(*preconnect_manager_, PreresolveUrl(url_to_preconnect, _)) EXPECT_CALL(*preconnect_manager_, PreresolveUrlProxy(url_to_preconnect, _))
.WillOnce(Return(net::OK)); .WillOnce(Return(net::OK));
EXPECT_CALL(*preconnect_manager_, EXPECT_CALL(*preconnect_manager_,
PreconnectUrl(url_to_preconnect, main_frame_url, 1, true)); PreconnectUrl(url_to_preconnect, main_frame_url, 1, true));
...@@ -122,7 +128,7 @@ TEST_F(PreconnectManagerTest, TestStopOneUrlBeforePreconnect) { ...@@ -122,7 +128,7 @@ TEST_F(PreconnectManagerTest, TestStopOneUrlBeforePreconnect) {
net::CompletionCallback callback; net::CompletionCallback callback;
// Preconnect job isn't started before preresolve is completed asynchronously. // Preconnect job isn't started before preresolve is completed asynchronously.
EXPECT_CALL(*preconnect_manager_, PreresolveUrl(url_to_preconnect, _)) EXPECT_CALL(*preconnect_manager_, PreresolveUrlProxy(url_to_preconnect, _))
.WillOnce(DoAll(SaveArg<1>(&callback), Return(net::ERR_IO_PENDING))); .WillOnce(DoAll(SaveArg<1>(&callback), Return(net::ERR_IO_PENDING)));
preconnect_manager_->Start(main_frame_url, preconnect_manager_->Start(main_frame_url,
{PreconnectRequest(url_to_preconnect, 1)}); {PreconnectRequest(url_to_preconnect, 1)});
...@@ -138,7 +144,7 @@ TEST_F(PreconnectManagerTest, TestGetCallbackAfterDestruction) { ...@@ -138,7 +144,7 @@ TEST_F(PreconnectManagerTest, TestGetCallbackAfterDestruction) {
GURL main_frame_url("http://google.com"); GURL main_frame_url("http://google.com");
GURL url_to_preconnect("http://cdn.google.com"); GURL url_to_preconnect("http://cdn.google.com");
net::CompletionCallback callback; net::CompletionCallback callback;
EXPECT_CALL(*preconnect_manager_, PreresolveUrl(url_to_preconnect, _)) EXPECT_CALL(*preconnect_manager_, PreresolveUrlProxy(url_to_preconnect, _))
.WillOnce(DoAll(SaveArg<1>(&callback), Return(net::ERR_IO_PENDING))); .WillOnce(DoAll(SaveArg<1>(&callback), Return(net::ERR_IO_PENDING)));
preconnect_manager_->Start(main_frame_url, preconnect_manager_->Start(main_frame_url,
{PreconnectRequest(url_to_preconnect, 1)}); {PreconnectRequest(url_to_preconnect, 1)});
...@@ -159,7 +165,8 @@ TEST_F(PreconnectManagerTest, TestUnqueuedPreresolvesCanceled) { ...@@ -159,7 +165,8 @@ TEST_F(PreconnectManagerTest, TestUnqueuedPreresolvesCanceled) {
// Exactly PreconnectManager::kMaxInflightPreresolves should be preresolved. // Exactly PreconnectManager::kMaxInflightPreresolves should be preresolved.
requests.emplace_back( requests.emplace_back(
GURL(base::StringPrintf("http://cdn%" PRIuS ".google.com", i)), 1); GURL(base::StringPrintf("http://cdn%" PRIuS ".google.com", i)), 1);
EXPECT_CALL(*preconnect_manager_, PreresolveUrl(requests.back().origin, _)) EXPECT_CALL(*preconnect_manager_,
PreresolveUrlProxy(requests.back().origin, _))
.WillOnce( .WillOnce(
DoAll(SaveArg<1>(&callbacks[i]), Return(net::ERR_IO_PENDING))); DoAll(SaveArg<1>(&callbacks[i]), Return(net::ERR_IO_PENDING)));
} }
...@@ -182,9 +189,9 @@ TEST_F(PreconnectManagerTest, TestTwoConcurrentMainFrameUrls) { ...@@ -182,9 +189,9 @@ TEST_F(PreconnectManagerTest, TestTwoConcurrentMainFrameUrls) {
GURL url_to_preconnect2("http://cdn.facebook.com"); GURL url_to_preconnect2("http://cdn.facebook.com");
net::CompletionCallback callback2; net::CompletionCallback callback2;
EXPECT_CALL(*preconnect_manager_, PreresolveUrl(url_to_preconnect1, _)) EXPECT_CALL(*preconnect_manager_, PreresolveUrlProxy(url_to_preconnect1, _))
.WillOnce(DoAll(SaveArg<1>(&callback1), Return(net::ERR_IO_PENDING))); .WillOnce(DoAll(SaveArg<1>(&callback1), Return(net::ERR_IO_PENDING)));
EXPECT_CALL(*preconnect_manager_, PreresolveUrl(url_to_preconnect2, _)) EXPECT_CALL(*preconnect_manager_, PreresolveUrlProxy(url_to_preconnect2, _))
.WillOnce(DoAll(SaveArg<1>(&callback2), Return(net::ERR_IO_PENDING))); .WillOnce(DoAll(SaveArg<1>(&callback2), Return(net::ERR_IO_PENDING)));
preconnect_manager_->Start(main_frame_url1, preconnect_manager_->Start(main_frame_url1,
{PreconnectRequest(url_to_preconnect1, 1)}); {PreconnectRequest(url_to_preconnect1, 1)});
...@@ -214,7 +221,7 @@ TEST_F(PreconnectManagerTest, TestTwoConcurrentSameHostMainFrameUrls) { ...@@ -214,7 +221,7 @@ TEST_F(PreconnectManagerTest, TestTwoConcurrentSameHostMainFrameUrls) {
GURL main_frame_url2("http://google.com/search?query=dogs"); GURL main_frame_url2("http://google.com/search?query=dogs");
GURL url_to_preconnect2("http://dogs.google.com"); GURL url_to_preconnect2("http://dogs.google.com");
EXPECT_CALL(*preconnect_manager_, PreresolveUrl(url_to_preconnect1, _)) EXPECT_CALL(*preconnect_manager_, PreresolveUrlProxy(url_to_preconnect1, _))
.WillOnce(DoAll(SaveArg<1>(&callback1), Return(net::ERR_IO_PENDING))); .WillOnce(DoAll(SaveArg<1>(&callback1), Return(net::ERR_IO_PENDING)));
preconnect_manager_->Start(main_frame_url1, preconnect_manager_->Start(main_frame_url1,
{PreconnectRequest(url_to_preconnect1, 1)}); {PreconnectRequest(url_to_preconnect1, 1)});
...@@ -234,7 +241,7 @@ TEST_F(PreconnectManagerTest, TestStartPreresolveHost) { ...@@ -234,7 +241,7 @@ TEST_F(PreconnectManagerTest, TestStartPreresolveHost) {
GURL url("http://cdn.google.com/script.js"); GURL url("http://cdn.google.com/script.js");
GURL origin("http://cdn.google.com"); GURL origin("http://cdn.google.com");
EXPECT_CALL(*preconnect_manager_, PreresolveUrl(origin, _)) EXPECT_CALL(*preconnect_manager_, PreresolveUrlProxy(origin, _))
.WillOnce(Return(net::OK)); .WillOnce(Return(net::OK));
preconnect_manager_->StartPreresolveHost(url); preconnect_manager_->StartPreresolveHost(url);
// PreconnectFinished shouldn't be called. // PreconnectFinished shouldn't be called.
...@@ -250,9 +257,9 @@ TEST_F(PreconnectManagerTest, TestStartPreresolveHosts) { ...@@ -250,9 +257,9 @@ TEST_F(PreconnectManagerTest, TestStartPreresolveHosts) {
GURL cdn("http://cdn.google.com"); GURL cdn("http://cdn.google.com");
GURL fonts("http://fonts.google.com"); GURL fonts("http://fonts.google.com");
EXPECT_CALL(*preconnect_manager_, PreresolveUrl(cdn, _)) EXPECT_CALL(*preconnect_manager_, PreresolveUrlProxy(cdn, _))
.WillOnce(Return(net::OK)); .WillOnce(Return(net::OK));
EXPECT_CALL(*preconnect_manager_, PreresolveUrl(fonts, _)) EXPECT_CALL(*preconnect_manager_, PreresolveUrlProxy(fonts, _))
.WillOnce(Return(net::OK)); .WillOnce(Return(net::OK));
preconnect_manager_->StartPreresolveHosts({cdn.host(), fonts.host()}); preconnect_manager_->StartPreresolveHosts({cdn.host(), fonts.host()});
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
...@@ -263,7 +270,7 @@ TEST_F(PreconnectManagerTest, TestStartPreconnectUrl) { ...@@ -263,7 +270,7 @@ TEST_F(PreconnectManagerTest, TestStartPreconnectUrl) {
GURL origin("http://cdn.google.com"); GURL origin("http://cdn.google.com");
bool allow_credentials = false; bool allow_credentials = false;
EXPECT_CALL(*preconnect_manager_, PreresolveUrl(origin, _)) EXPECT_CALL(*preconnect_manager_, PreresolveUrlProxy(origin, _))
.WillOnce(Return(net::OK)); .WillOnce(Return(net::OK));
EXPECT_CALL(*preconnect_manager_, EXPECT_CALL(*preconnect_manager_,
PreconnectUrl(origin, GURL(), 1, allow_credentials)); PreconnectUrl(origin, GURL(), 1, allow_credentials));
...@@ -285,7 +292,8 @@ TEST_F(PreconnectManagerTest, TestDetachedRequestHasHigherPriority) { ...@@ -285,7 +292,8 @@ TEST_F(PreconnectManagerTest, TestDetachedRequestHasHigherPriority) {
for (size_t i = 0; i < count; ++i) { for (size_t i = 0; i < count; ++i) {
requests.emplace_back( requests.emplace_back(
GURL(base::StringPrintf("http://cdn%" PRIuS ".google.com", i)), 0); GURL(base::StringPrintf("http://cdn%" PRIuS ".google.com", i)), 0);
EXPECT_CALL(*preconnect_manager_, PreresolveUrl(requests.back().origin, _)) EXPECT_CALL(*preconnect_manager_,
PreresolveUrlProxy(requests.back().origin, _))
.WillOnce( .WillOnce(
DoAll(SaveArg<1>(&callbacks[i]), Return(net::ERR_IO_PENDING))); DoAll(SaveArg<1>(&callbacks[i]), Return(net::ERR_IO_PENDING)));
} }
...@@ -300,13 +308,13 @@ TEST_F(PreconnectManagerTest, TestDetachedRequestHasHigherPriority) { ...@@ -300,13 +308,13 @@ TEST_F(PreconnectManagerTest, TestDetachedRequestHasHigherPriority) {
Mock::VerifyAndClearExpectations(preconnect_manager_.get()); Mock::VerifyAndClearExpectations(preconnect_manager_.get());
net::CompletionCallback detached_callback; net::CompletionCallback detached_callback;
EXPECT_CALL(*preconnect_manager_, PreresolveUrl(detached_preresolve, _)) EXPECT_CALL(*preconnect_manager_, PreresolveUrlProxy(detached_preresolve, _))
.WillOnce( .WillOnce(
DoAll(SaveArg<1>(&detached_callback), Return(net::ERR_IO_PENDING))); DoAll(SaveArg<1>(&detached_callback), Return(net::ERR_IO_PENDING)));
callbacks[0].Run(net::OK); callbacks[0].Run(net::OK);
Mock::VerifyAndClearExpectations(preconnect_manager_.get()); Mock::VerifyAndClearExpectations(preconnect_manager_.get());
EXPECT_CALL(*preconnect_manager_, PreresolveUrl(queued_url, _)) EXPECT_CALL(*preconnect_manager_, PreresolveUrlProxy(queued_url, _))
.WillOnce(Return(net::OK)); .WillOnce(Return(net::OK));
detached_callback.Run(net::OK); detached_callback.Run(net::OK);
...@@ -326,7 +334,8 @@ TEST_F(PreconnectManagerTest, TestHSTSRedirectRespectedForPreconnect) { ...@@ -326,7 +334,8 @@ TEST_F(PreconnectManagerTest, TestHSTSRedirectRespectedForPreconnect) {
GURL url("http://google.com/search"); GURL url("http://google.com/search");
bool allow_credentials = false; bool allow_credentials = false;
EXPECT_CALL(*preconnect_manager_, PreresolveUrl(GURL("http://google.com"), _)) EXPECT_CALL(*preconnect_manager_,
PreresolveUrlProxy(GURL("http://google.com"), _))
.WillOnce(Return(net::OK)); .WillOnce(Return(net::OK));
EXPECT_CALL( EXPECT_CALL(
*preconnect_manager_, *preconnect_manager_,
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#include "content/public/browser/resource_hints.h" #include "content/public/browser/resource_hints.h"
#include "net/base/address_list.h" #include "net/base/address_list.h"
#include "net/base/load_flags.h" #include "net/base/load_flags.h"
#include "net/dns/host_resolver.h"
#include "net/http/http_network_session.h" #include "net/http/http_network_session.h"
#include "net/http/http_request_info.h" #include "net/http/http_request_info.h"
#include "net/http/http_stream_factory.h" #include "net/http/http_stream_factory.h"
...@@ -24,18 +23,7 @@ namespace content { ...@@ -24,18 +23,7 @@ namespace content {
namespace { namespace {
class RequestHolder { void OnResolveComplete(std::unique_ptr<net::AddressList> addresses,
public:
std::unique_ptr<net::HostResolver::Request>* GetRequest() {
return &request_;
}
private:
std::unique_ptr<net::HostResolver::Request> request_;
};
void OnResolveComplete(std::unique_ptr<RequestHolder> request_holder,
std::unique_ptr<net::AddressList> addresses,
const net::CompletionCallback& callback, const net::CompletionCallback& callback,
int result) { int result) {
// Plumb the resolution result into the callback if future consumers want // Plumb the resolution result into the callback if future consumers want
...@@ -93,7 +81,8 @@ void PreconnectUrl(net::URLRequestContextGetter* getter, ...@@ -93,7 +81,8 @@ void PreconnectUrl(net::URLRequestContextGetter* getter,
int PreresolveUrl(net::URLRequestContextGetter* getter, int PreresolveUrl(net::URLRequestContextGetter* getter,
const GURL& url, const GURL& url,
const net::CompletionCallback& callback) { const net::CompletionCallback& callback,
std::unique_ptr<net::HostResolver::Request>* out_request) {
DCHECK(ResourceDispatcherHostImpl::Get() DCHECK(ResourceDispatcherHostImpl::Get()
->io_thread_task_runner() ->io_thread_task_runner()
->BelongsToCurrentThread()); ->BelongsToCurrentThread());
...@@ -104,21 +93,17 @@ int PreresolveUrl(net::URLRequestContextGetter* getter, ...@@ -104,21 +93,17 @@ int PreresolveUrl(net::URLRequestContextGetter* getter,
if (!request_context) if (!request_context)
return net::ERR_CONTEXT_SHUT_DOWN; return net::ERR_CONTEXT_SHUT_DOWN;
auto request_holder = std::make_unique<RequestHolder>();
auto addresses = std::make_unique<net::AddressList>(); auto addresses = std::make_unique<net::AddressList>();
// Save raw pointers before the unique_ptr is invalidated by base::Passed. // Save raw pointers before the unique_ptr is invalidated by base::Passed().
net::AddressList* raw_addresses = addresses.get(); net::AddressList* raw_addresses = addresses.get();
std::unique_ptr<net::HostResolver::Request>* out_request =
request_holder->GetRequest();
net::HostResolver* resolver = request_context->host_resolver(); net::HostResolver* resolver = request_context->host_resolver();
net::HostResolver::RequestInfo resolve_info(net::HostPortPair::FromURL(url)); net::HostResolver::RequestInfo resolve_info(net::HostPortPair::FromURL(url));
resolve_info.set_is_speculative(true); resolve_info.set_is_speculative(true);
return resolver->Resolve( return resolver->Resolve(
resolve_info, net::IDLE, raw_addresses, resolve_info, net::IDLE, raw_addresses,
base::Bind(&OnResolveComplete, base::Passed(&request_holder), base::Bind(&OnResolveComplete, base::Passed(&addresses), callback),
base::Passed(&addresses), callback),
out_request, net::NetLogWithSource()); out_request, net::NetLogWithSource());
} }
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "net/base/completion_callback.h" #include "net/base/completion_callback.h"
#include "net/dns/host_resolver.h"
#include "net/http/http_request_info.h" #include "net/http/http_request_info.h"
#include "url/gurl.h" #include "url/gurl.h"
...@@ -16,6 +17,9 @@ namespace net { ...@@ -16,6 +17,9 @@ namespace net {
class URLRequestContextGetter; class URLRequestContextGetter;
} }
// TODO(https://crbug.com/565719): Resource hints aren't used nor implemented in
// content/. Either the preconnect/preresolve code should be moved to content/
// or this should be moved outside of content/.
namespace content { namespace content {
// A Preconnect instance maintains state while a TCP/IP connection is made, and // A Preconnect instance maintains state while a TCP/IP connection is made, and
...@@ -35,9 +39,11 @@ CONTENT_EXPORT void PreconnectUrl(net::URLRequestContextGetter* getter, ...@@ -35,9 +39,11 @@ CONTENT_EXPORT void PreconnectUrl(net::URLRequestContextGetter* getter,
// Issues a DNS request to |url|. Note that these requests are sent to the host // Issues a DNS request to |url|. Note that these requests are sent to the host
// resolver with priority net::IDLE. // resolver with priority net::IDLE.
CONTENT_EXPORT int PreresolveUrl(net::URLRequestContextGetter* getter, CONTENT_EXPORT int PreresolveUrl(
const GURL& url, net::URLRequestContextGetter* getter,
const net::CompletionCallback& callback); const GURL& url,
const net::CompletionCallback& callback,
std::unique_ptr<net::HostResolver::Request>* out_req);
} // namespace content } // namespace content
......
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