summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/net/dns_global.cc51
-rw-r--r--chrome/browser/net/dns_master.cc12
-rw-r--r--chrome/browser/net/dns_master_unittest.cc3
-rw-r--r--net/base/client_socket_handle.cc5
-rw-r--r--net/base/client_socket_handle.h8
-rw-r--r--net/base/client_socket_pool.h5
-rw-r--r--net/base/dns_resolution_observer.cc60
-rw-r--r--net/base/dns_resolution_observer.h42
-rw-r--r--net/base/host_resolver.cc115
-rw-r--r--net/base/host_resolver.h80
-rw-r--r--net/base/host_resolver_unittest.cc208
-rw-r--r--net/base/ssl_client_socket_unittest.cc25
-rw-r--r--net/base/ssl_test_util.cc3
-rw-r--r--net/base/tcp_client_socket_pool.cc41
-rw-r--r--net/base/tcp_client_socket_pool.h20
-rw-r--r--net/base/tcp_client_socket_pool_unittest.cc51
-rw-r--r--net/base/tcp_client_socket_unittest.cc3
-rw-r--r--net/base/tcp_pinger_unittest.cc6
-rw-r--r--net/ftp/ftp_network_transaction.cc14
-rw-r--r--net/http/http_network_transaction.cc21
-rw-r--r--net/net.gyp1
-rw-r--r--net/proxy/proxy_resolver_v8.cc13
22 files changed, 523 insertions, 264 deletions
diff --git a/chrome/browser/net/dns_global.cc b/chrome/browser/net/dns_global.cc
index c54b14d..1d808cb 100644
--- a/chrome/browser/net/dns_global.cc
+++ b/chrome/browser/net/dns_global.cc
@@ -133,7 +133,7 @@ static void NavigatingTo(const std::string& host_name) {
// The observer class needs to connect starts and finishes of HTTP network
// resolutions. We use the following type for that map.
-typedef std::map<void*, DnsHostInfo> ObservedResolutionMap;
+typedef std::map<int, DnsHostInfo> ObservedResolutionMap;
// There will only be one instance ever created of the following Observer
// class. As a result, we get away with using static members for data local
@@ -143,11 +143,13 @@ class PrefetchObserver : public net::DnsResolutionObserver {
PrefetchObserver();
~PrefetchObserver();
- virtual void OnStartResolution(const std::string& host_name,
- void* context);
- virtual void OnFinishResolutionWithStatus(bool was_resolved,
- const GURL& referrer,
- void* context);
+ virtual void OnStartResolution(
+ int request_id,
+ const net::HostResolver::RequestInfo& request_info);
+ virtual void OnFinishResolutionWithStatus(
+ int request_id,
+ bool was_resolved,
+ const net::HostResolver::RequestInfo& request_info);
static void DnsGetFirstResolutionsHtml(std::string* output);
static void SaveStartupListAsPref(PrefService* local_state);
@@ -189,27 +191,37 @@ PrefetchObserver::~PrefetchObserver() {
lock = NULL;
}
-void PrefetchObserver::OnStartResolution(const std::string& host_name,
- void* context) {
- DCHECK_NE(0U, host_name.length());
+void PrefetchObserver::OnStartResolution(
+ int request_id,
+ const net::HostResolver::RequestInfo& request_info) {
+ if (request_info.is_speculative())
+ return; // One of our own requests.
+ DCHECK_NE(0U, request_info.hostname().length());
DnsHostInfo navigation_info;
- navigation_info.SetHostname(host_name);
+ navigation_info.SetHostname(request_info.hostname());
navigation_info.SetStartedState();
- NavigatingTo(host_name);
+ NavigatingTo(request_info.hostname());
+
+ // TODO(eroman): If the resolve request is cancelled, then
+ // OnFinishResolutionWithStatus will not be called, and |resolutions| will
+ // grow unbounded!
AutoLock auto_lock(*lock);
- (*resolutions)[context] = navigation_info;
+ (*resolutions)[request_id] = navigation_info;
}
-void PrefetchObserver::OnFinishResolutionWithStatus(bool was_resolved,
- const GURL& referrer,
- void* context) {
+void PrefetchObserver::OnFinishResolutionWithStatus(
+ int request_id,
+ bool was_resolved,
+ const net::HostResolver::RequestInfo& request_info) {
+ if (request_info.is_speculative())
+ return; // One of our own requests.
DnsHostInfo navigation_info;
size_t startup_count;
{
AutoLock auto_lock(*lock);
- ObservedResolutionMap::iterator it = resolutions->find(context);
+ ObservedResolutionMap::iterator it = resolutions->find(request_id);
if (resolutions->end() == it) {
DCHECK(false);
return;
@@ -219,7 +231,7 @@ void PrefetchObserver::OnFinishResolutionWithStatus(bool was_resolved,
startup_count = first_resolutions->size();
}
navigation_info.SetFinishedState(was_resolved); // Get timing info
- AccruePrefetchBenefits(referrer, &navigation_info);
+ AccruePrefetchBenefits(request_info.referrer(), &navigation_info);
if (kStartupResolutionCount <= startup_count || !was_resolved)
return;
// TODO(jar): Don't add host to our list if it is a non-linked lookup, and
@@ -399,7 +411,10 @@ void InitDnsPrefetch(size_t max_concurrent, PrefService* user_prefs) {
DLOG(INFO) << "DNS Prefetch service started";
// Start observing real HTTP stack resolutions.
- net::AddDnsResolutionObserver(&dns_resolution_observer);
+ // TODO(eroman): really this should be called from IO thread (since that is
+ // where the host resolver lives). Since this occurs before requests have
+ // started it is not a race yet.
+ GetGlobalHostResolver()->AddObserver(&dns_resolution_observer);
}
}
diff --git a/chrome/browser/net/dns_master.cc b/chrome/browser/net/dns_master.cc
index 6151087..a256aa6 100644
--- a/chrome/browser/net/dns_master.cc
+++ b/chrome/browser/net/dns_master.cc
@@ -35,8 +35,16 @@ class DnsMaster::LookupRequest {
}
bool Start() {
- const int result = resolver_.Resolve(hostname_, 80, &addresses_,
- &net_callback_);
+ // Port doesn't really matter.
+ net::HostResolver::RequestInfo resolve_info(hostname_, 80);
+
+ // Make a note that this is a speculative resolve request. This allows us
+ // to separate it from real navigations in the observer's callback, and
+ // lets the HostResolver know it can de-prioritize it.
+ resolve_info.set_is_speculative(true);
+
+ const int result = resolver_.Resolve(
+ resolve_info, &addresses_, &net_callback_);
return (result == net::ERR_IO_PENDING);
}
diff --git a/chrome/browser/net/dns_master_unittest.cc b/chrome/browser/net/dns_master_unittest.cc
index be68dfb..e056555 100644
--- a/chrome/browser/net/dns_master_unittest.cc
+++ b/chrome/browser/net/dns_master_unittest.cc
@@ -113,7 +113,8 @@ TimeDelta BlockingDnsLookup(const std::string& hostname) {
net::HostResolver resolver;
net::AddressList addresses;
- resolver.Resolve(hostname, 80, &addresses, NULL, NULL);
+ net::HostResolver::RequestInfo info(hostname, 80);
+ resolver.Resolve(info, &addresses, NULL, NULL);
return Time::Now() - start;
}
diff --git a/net/base/client_socket_handle.cc b/net/base/client_socket_handle.cc
index 043cefd..adedcd4 100644
--- a/net/base/client_socket_handle.cc
+++ b/net/base/client_socket_handle.cc
@@ -24,15 +24,14 @@ ClientSocketHandle::~ClientSocketHandle() {
}
int ClientSocketHandle::Init(const std::string& group_name,
- const std::string& host,
- int port,
+ const HostResolver::RequestInfo& resolve_info,
int priority,
CompletionCallback* callback) {
ResetInternal(true);
group_name_ = group_name;
user_callback_ = callback;
return pool_->RequestSocket(
- group_name, host, port, priority, this, &callback_);
+ group_name, resolve_info, priority, this, &callback_);
}
void ClientSocketHandle::Reset() {
diff --git a/net/base/client_socket_handle.h b/net/base/client_socket_handle.h
index 5bac2c8..777c752 100644
--- a/net/base/client_socket_handle.h
+++ b/net/base/client_socket_handle.h
@@ -11,6 +11,7 @@
#include "base/scoped_ptr.h"
#include "net/base/client_socket.h"
#include "net/base/completion_callback.h"
+#include "net/base/host_resolver.h"
#include "net/base/load_states.h"
namespace net {
@@ -37,8 +38,8 @@ class ClientSocketHandle {
// connected socket if an existing connected socket was available to reuse,
// otherwise it will be set to a new connected socket. Consumers can then
// call is_reused() to see if the socket was reused. If not reusing an
- // existing socket, ClientSocketPool may need to establish a new
- // connection to the |host| |port| pair.
+ // existing socket, ClientSocketPool may need to establish a new
+ // connection to the |resolve_info.host| |resolve_info.port| pair.
//
// This method returns ERR_IO_PENDING if it cannot complete synchronously, in
// which case the consumer will be notified of completion via |callback|.
@@ -46,8 +47,7 @@ class ClientSocketHandle {
// Init may be called multiple times.
//
int Init(const std::string& group_name,
- const std::string& host,
- int port,
+ const HostResolver::RequestInfo& resolve_info,
int priority,
CompletionCallback* callback);
diff --git a/net/base/client_socket_pool.h b/net/base/client_socket_pool.h
index 6d200c0..86c67b8 100644
--- a/net/base/client_socket_pool.h
+++ b/net/base/client_socket_pool.h
@@ -11,13 +11,13 @@
#include "base/ref_counted.h"
#include "net/base/completion_callback.h"
+#include "net/base/host_resolver.h"
#include "net/base/load_states.h"
namespace net {
class ClientSocket;
class ClientSocketHandle;
-class HostResolver;
// A ClientSocketPool is used to restrict the number of sockets open at a time.
// It also maintains a list of idle persistent sockets.
@@ -47,8 +47,7 @@ class ClientSocketPool : public base::RefCounted<ClientSocketPool> {
// client of completion.
//
virtual int RequestSocket(const std::string& group_name,
- const std::string& host,
- int port,
+ const HostResolver::RequestInfo& resolve_info,
int priority,
ClientSocketHandle* handle,
CompletionCallback* callback) = 0;
diff --git a/net/base/dns_resolution_observer.cc b/net/base/dns_resolution_observer.cc
deleted file mode 100644
index 179a15c..0000000
--- a/net/base/dns_resolution_observer.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) 2006-2008 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.
-
-// This file supports network stack independent notification of progress
-// towards resolving a hostname.
-
-#include "net/base/dns_resolution_observer.h"
-
-#include <string>
-
-#include "base/logging.h"
-
-namespace net {
-
-static DnsResolutionObserver* dns_resolution_observer;
-
-void AddDnsResolutionObserver(DnsResolutionObserver* new_observer) {
- if (new_observer == dns_resolution_observer)
- return; // Facilitate unit tests that init/teardown repeatedly.
- DCHECK(!dns_resolution_observer);
- dns_resolution_observer = new_observer;
-}
-
-DnsResolutionObserver* RemoveDnsResolutionObserver() {
- // We really need to check that the entire network subsystem is shutting down,
- // and hence no additional calls can even *possibly* still be lingering in the
- // notification path that includes our observer. Until we have a way to
- // really assert that fact, we will outlaw the calling of this function.
- // Darin suggested that the caller use a static initializer for the observer,
- // so that it can safely be destroyed after process termination, and without
- // inducing a memory leak.
- // Bottom line: Don't call this function! You will crash for now.
- CHECK(0);
- DnsResolutionObserver* old_observer = dns_resolution_observer;
- dns_resolution_observer = NULL;
- return old_observer;
-}
-
-// Locking access to dns_resolution_observer is not really critical... but we
-// should test the value of dns_resolution_observer that we use.
-// Worst case, we'll get an "out of date" value... which is no big deal for the
-// DNS prefetching system (the most common (only?) observer).
-void DidStartDnsResolution(const std::string& name, void* context) {
- DnsResolutionObserver* current_observer = dns_resolution_observer;
- if (current_observer)
- current_observer->OnStartResolution(name, context);
-}
-
-void DidFinishDnsResolutionWithStatus(bool was_resolved,
- const GURL& referrer,
- void* context) {
- DnsResolutionObserver* current_observer = dns_resolution_observer;
- if (current_observer) {
- current_observer->OnFinishResolutionWithStatus(was_resolved, referrer,
- context);
- }
-}
-
-} // namspace net
diff --git a/net/base/dns_resolution_observer.h b/net/base/dns_resolution_observer.h
index 9dd9a90..1651308 100644
--- a/net/base/dns_resolution_observer.h
+++ b/net/base/dns_resolution_observer.h
@@ -15,10 +15,13 @@
#include <string>
+#include "net/base/host_resolver.h"
+
class GURL;
namespace net {
+// TODO(eroman): Move this interface to HostResolver::Observer.
class DnsResolutionObserver {
public:
virtual ~DnsResolutionObserver() {}
@@ -26,40 +29,17 @@ class DnsResolutionObserver {
// For each OnStartResolution() notification, there should be a later
// OnFinishResolutionWithStatus() indicating completion of the resolution
// activity.
- // Related pairs of notification will arrive with matching context values.
- // A caller may use the context values to match up these asynchronous calls
+ // Related pairs of notification will arrive with matching id values.
+ // A caller may use the id values to match up these asynchronous calls
// from among a larger call stream.
- // Once a matching pair of notifications has been provided (i.e., a pair with
- // identical context values), and the notification methods (below) have
- // returned, the context values *might* be reused.
- virtual void OnStartResolution(const std::string& host_name,
- void* context) = 0;
- virtual void OnFinishResolutionWithStatus(bool was_resolved,
- const GURL& referrer,
- void* context) = 0;
+ virtual void OnStartResolution(int id,
+ const HostResolver::RequestInfo& info) = 0;
+ virtual void OnFinishResolutionWithStatus(
+ int id,
+ bool was_resolved,
+ const HostResolver::RequestInfo& info) = 0;
};
-
-// Note that *exactly* one observer is currently supported, and any attempt to
-// add a second observer via AddDnsResolutionObserver() before removing the
-// first DnsResolutionObserver will induce a DCHECK() assertion.
-void AddDnsResolutionObserver(DnsResolutionObserver* new_observer);
-
-// Note that the RemoveDnsResolutionObserver() will NOT perform any delete
-// operations, and it is the responsibility of the code that called
-// AddDnsResolutionObserver() to make a corresponding call to
-// RemoveDnsResolutionObserver() and then delete the returned
-// DnsResolutionObserver instance.
-DnsResolutionObserver* RemoveDnsResolutionObserver();
-
-// The following functions are expected to be called only by network stack
-// implementations. This above observer class will relay the notifications
-// to any registered observer.
-void DidStartDnsResolution(const std::string& name,
- void* context);
-void DidFinishDnsResolutionWithStatus(bool was_resolved,
- const GURL& url,
- void* context);
} // namspace net
#endif // NET_BASE_DNS_RESOLUTION_OBSERVER_H_
diff --git a/net/base/host_resolver.cc b/net/base/host_resolver.cc
index 40ed8fd..6dcef85 100644
--- a/net/base/host_resolver.cc
+++ b/net/base/host_resolver.cc
@@ -22,6 +22,7 @@
#include "base/time.h"
#include "base/worker_pool.h"
#include "net/base/address_list.h"
+#include "net/base/dns_resolution_observer.h"
#include "net/base/net_errors.h"
#if defined(OS_LINUX)
@@ -178,8 +179,10 @@ static int ResolveAddrInfo(HostMapper* mapper, const std::string& host,
class HostResolver::Request {
public:
- Request(CompletionCallback* callback, AddressList* addresses, int port)
- : job_(NULL), callback_(callback), addresses_(addresses), port_(port) {}
+ Request(int id, const RequestInfo& info, CompletionCallback* callback,
+ AddressList* addresses)
+ : id_(id), info_(info), job_(NULL), callback_(callback),
+ addresses_(addresses) {}
// Mark the request as cancelled.
void Cancel() {
@@ -200,19 +203,33 @@ class HostResolver::Request {
void OnComplete(int error, const AddressList& addrlist) {
if (error == OK)
- addresses_->SetFrom(addrlist, port_);
+ addresses_->SetFrom(addrlist, port());
callback_->Run(error);
}
int port() const {
- return port_;
+ return info_.port();
}
Job* job() const {
return job_;
}
+ int id() const {
+ return id_;
+ }
+
+ const RequestInfo& info() const {
+ return info_;
+ }
+
private:
+ // Unique ID for this request. Used by observers to identify requests.
+ int id_;
+
+ // The request info that started the request.
+ RequestInfo info_;
+
// The resolve job (running in worker pool) that this request is dependent on.
Job* job_;
@@ -222,9 +239,6 @@ class HostResolver::Request {
// The address list to save result into.
AddressList* addresses_;
- // The desired port number for the socket addresses.
- int port_;
-
DISALLOW_COPY_AND_ASSIGN(Request);
};
@@ -369,7 +383,7 @@ class HostResolver::Job : public base::RefCountedThreadSafe<HostResolver::Job> {
//-----------------------------------------------------------------------------
HostResolver::HostResolver(int max_cache_entries, int cache_duration_ms)
- : cache_(max_cache_entries, cache_duration_ms) {
+ : cache_(max_cache_entries, cache_duration_ms), next_request_id_(0) {
#if defined(OS_WIN)
EnsureWinsockInit();
#endif
@@ -388,40 +402,51 @@ HostResolver::~HostResolver() {
// TODO(eroman): Don't create cache entries for hostnames which are simply IP
// address literals.
-int HostResolver::Resolve(const std::string& hostname, int port,
+int HostResolver::Resolve(const RequestInfo& info,
AddressList* addresses,
CompletionCallback* callback,
Request** out_req) {
+ // Choose a unique ID number for observers to see.
+ int request_id = next_request_id_++;
+
+ // Notify registered observers.
+ NotifyObserversStartRequest(request_id, info);
+
// If we have an unexpired cache entry, use it.
- const HostCache::Entry* cache_entry = cache_.Lookup(
- hostname, base::TimeTicks::Now());
- if (cache_entry) {
- addresses->SetFrom(cache_entry->addrlist, port);
- return OK;
+ if (info.allow_cached_response()) {
+ const HostCache::Entry* cache_entry = cache_.Lookup(
+ info.hostname(), base::TimeTicks::Now());
+ if (cache_entry) {
+ addresses->SetFrom(cache_entry->addrlist, info.port());
+ return OK;
+ }
}
// If no callback was specified, do a synchronous resolution.
if (!callback) {
struct addrinfo* results;
- int error = ResolveAddrInfo(host_mapper, hostname, &results);
+ int error = ResolveAddrInfo(host_mapper, info.hostname(), &results);
// Adopt the address list.
AddressList addrlist;
if (error == OK) {
addrlist.Adopt(results);
- addrlist.SetPort(port);
+ addrlist.SetPort(info.port());
*addresses = addrlist;
}
// Write to cache.
- cache_.Set(hostname, error, addrlist, base::TimeTicks::Now());
+ cache_.Set(info.hostname(), error, addrlist, base::TimeTicks::Now());
+
+ // Notify registered observers.
+ NotifyObserversFinishRequest(request_id, info, error);
return error;
}
// Create a handle for this request, and pass it back to the user if they
// asked for it (out_req != NULL).
- Request* req = new Request(callback, addresses, port);
+ Request* req = new Request(request_id, info, callback, addresses);
if (out_req)
*out_req = req;
@@ -429,14 +454,14 @@ int HostResolver::Resolve(const std::string& hostname, int port,
// calling "getaddrinfo(hostname)" on a worker thread.
scoped_refptr<Job> job;
- // If there is already an outstanding job to resolve |hostname|, use it.
- // This prevents starting concurrent resolves for the same hostname.
- job = FindOutstandingJob(hostname);
+ // If there is already an outstanding job to resolve |info.hostname()|, use
+ // it. This prevents starting concurrent resolves for the same hostname.
+ job = FindOutstandingJob(info.hostname());
if (job) {
job->AddRequest(req);
} else {
// Create a new job for this request.
- job = new Job(this, hostname);
+ job = new Job(this, info.hostname());
job->AddRequest(req);
AddOutstandingJob(job);
// TODO(eroman): Bound the total number of concurrent jobs.
@@ -457,6 +482,20 @@ void HostResolver::CancelRequest(Request* req) {
req->Cancel();
}
+void HostResolver::AddObserver(DnsResolutionObserver* observer) {
+ observers_.push_back(observer);
+}
+
+void HostResolver::RemoveObserver(DnsResolutionObserver* observer) {
+ ObserversList::iterator it =
+ std::find(observers_.begin(), observers_.end(), observer);
+
+ // Observer must exist.
+ DCHECK(it != observers_.end());
+
+ observers_.erase(it);
+}
+
void HostResolver::AddOutstandingJob(Job* job) {
scoped_refptr<Job>& found_job = jobs_[job->host()];
DCHECK(!found_job);
@@ -497,6 +536,10 @@ void HostResolver::OnJobComplete(Job* job,
Request* req = *it;
if (!req->was_cancelled()) {
DCHECK_EQ(job, req->job());
+
+ // Notify registered observers.
+ NotifyObserversFinishRequest(req->id(), req->info(), error);
+
req->OnComplete(error, addrlist);
// Check if the job was cancelled as a result of running the callback.
@@ -509,6 +552,24 @@ void HostResolver::OnJobComplete(Job* job,
cur_completing_job_ = NULL;
}
+void HostResolver::NotifyObserversStartRequest(int request_id,
+ const RequestInfo& info) {
+ for (ObserversList::iterator it = observers_.begin();
+ it != observers_.end(); ++it) {
+ (*it)->OnStartResolution(request_id, info);
+ }
+}
+
+void HostResolver::NotifyObserversFinishRequest(int request_id,
+ const RequestInfo& info,
+ int error) {
+ bool was_resolved = error == OK;
+ for (ObserversList::iterator it = observers_.begin();
+ it != observers_.end(); ++it) {
+ (*it)->OnFinishResolutionWithStatus(request_id, was_resolved, info);
+ }
+}
+
//-----------------------------------------------------------------------------
SingleRequestHostResolver::SingleRequestHostResolver(HostResolver* resolver)
@@ -526,10 +587,9 @@ SingleRequestHostResolver::~SingleRequestHostResolver() {
}
}
-int SingleRequestHostResolver::Resolve(
- const std::string& hostname, int port,
- AddressList* addresses,
- CompletionCallback* callback) {
+int SingleRequestHostResolver::Resolve(const HostResolver::RequestInfo& info,
+ AddressList* addresses,
+ CompletionCallback* callback) {
DCHECK(!cur_request_ && !cur_request_callback_) << "resolver already in use";
HostResolver::Request* request = NULL;
@@ -538,8 +598,7 @@ int SingleRequestHostResolver::Resolve(
// we can clear out |cur_request_*|.
CompletionCallback* transient_callback = callback ? &callback_ : NULL;
- int rv = resolver_->Resolve(
- hostname, port, addresses, transient_callback, &request);
+ int rv = resolver_->Resolve(info, addresses, transient_callback, &request);
if (rv == ERR_IO_PENDING) {
// Cleared in OnResolveCompletion().
diff --git a/net/base/host_resolver.h b/net/base/host_resolver.h
index a67419a..9a7b7b9 100644
--- a/net/base/host_resolver.h
+++ b/net/base/host_resolver.h
@@ -11,6 +11,7 @@
#include "base/basictypes.h"
#include "base/lock.h"
#include "base/ref_counted.h"
+#include "googleurl/src/gurl.h"
#include "net/base/completion_callback.h"
#include "net/base/host_cache.h"
@@ -19,6 +20,7 @@ class MessageLoop;
namespace net {
class AddressList;
+class DnsResolutionObserver;
class HostMapper;
// This class represents the task of resolving hostnames (or IP address
@@ -58,6 +60,46 @@ class HostMapper;
//
class HostResolver {
public:
+ // The parameters for doing a Resolve(). |hostname| and |port| are required,
+ // the rest are optional (and have reasonable defaults).
+ class RequestInfo {
+ public:
+ RequestInfo(const std::string& hostname, int port)
+ : hostname_(hostname),
+ port_(port),
+ allow_cached_response_(true),
+ is_speculative_(false) {}
+
+ const int port() const { return port_; }
+ const std::string& hostname() const { return hostname_; }
+
+ bool allow_cached_response() const { return allow_cached_response_; }
+ void set_allow_cached_response(bool b) { allow_cached_response_ = b; }
+
+ bool is_speculative() const { return is_speculative_; }
+ void set_is_speculative(bool b) { is_speculative_ = b; }
+
+ const GURL& referrer() const { return referrer_; }
+ void set_referrer(const GURL& referrer) { referrer_ = referrer; }
+
+ private:
+ // The hostname to resolve.
+ std::string hostname_;
+
+ // The port number to set in the result's sockaddrs.
+ int port_;
+
+ // Whether it is ok to return a result from the host cache.
+ bool allow_cached_response_;
+
+ // Whether this request was started by the DNS prefetcher.
+ bool is_speculative_;
+
+ // Optional data for consumption by observers. This is the URL of the
+ // page that lead us to the navigation, for DNS prefetcher's benefit.
+ GURL referrer_;
+ };
+
// Creates a HostResolver that caches up to |max_cache_entries| for
// |cache_duration_ms| milliseconds.
//
@@ -74,9 +116,9 @@ class HostResolver {
class Request;
// Resolves the given hostname (or IP address literal), filling out the
- // |addresses| object upon success. The |port| parameter will be set as the
- // sin(6)_port field of the sockaddr_in{6} struct. Returns OK if successful
- // or an error code upon failure.
+ // |addresses| object upon success. The |info.port| parameter will be set as
+ // the sin(6)_port field of the sockaddr_in{6} struct. Returns OK if
+ // successful or an error code upon failure.
//
// When callback is null, the operation completes synchronously.
//
@@ -85,18 +127,26 @@ class HostResolver {
// result code will be passed to the completion callback. If |req| is
// non-NULL, then |*req| will be filled with a handle to the async request.
// This handle is not valid after the request has completed.
- int Resolve(const std::string& hostname, int port,
- AddressList* addresses, CompletionCallback* callback,
- Request** req);
+ int Resolve(const RequestInfo& info, AddressList* addresses,
+ CompletionCallback* callback, Request** req);
// Cancels the specified request. |req| is the handle returned by Resolve().
// After a request is cancelled, its completion callback will not be called.
void CancelRequest(Request* req);
+ // Adds an observer to this resolver. The observer will be notified of the
+ // start and completion of all requests (excluding cancellation). |observer|
+ // must remain valid for the duration of this HostResolver's lifetime.
+ void AddObserver(DnsResolutionObserver* observer);
+
+ // Unregisters an observer previously added by AddObserver().
+ void RemoveObserver(DnsResolutionObserver* observer);
+
private:
class Job;
typedef std::vector<Request*> RequestsList;
typedef base::hash_map<std::string, scoped_refptr<Job> > JobMap;
+ typedef std::vector<DnsResolutionObserver*> ObserversList;
// Adds a job to outstanding jobs list.
void AddOutstandingJob(Job* job);
@@ -110,6 +160,15 @@ class HostResolver {
// Callback for when |job| has completed with |error| and |addrlist|.
void OnJobComplete(Job* job, int error, const AddressList& addrlist);
+ // Notify all obsevers of the start of a resolve request.
+ void NotifyObserversStartRequest(int request_id,
+ const RequestInfo& info);
+
+ // Notify all obsevers of the completion of a resolve request.
+ void NotifyObserversFinishRequest(int request_id,
+ const RequestInfo& info,
+ int error);
+
// Cache of host resolution results.
HostCache cache_;
@@ -120,6 +179,13 @@ class HostResolver {
// HostResolver gets deleted from within the callback).
scoped_refptr<Job> cur_completing_job_;
+ // The observers to notify when a request starts/ends.
+ ObserversList observers_;
+
+ // Monotonically increasing ID number to assign to the next request.
+ // Observers are the only consumers of this ID number.
+ int next_request_id_;
+
DISALLOW_COPY_AND_ASSIGN(HostResolver);
};
@@ -137,7 +203,7 @@ class SingleRequestHostResolver {
// Resolves the given hostname (or IP address literal), filling out the
// |addresses| object upon success. See HostResolver::Resolve() for details.
- int Resolve(const std::string& hostname, int port,
+ int Resolve(const HostResolver::RequestInfo& info,
AddressList* addresses, CompletionCallback* callback);
private:
diff --git a/net/base/host_resolver_unittest.cc b/net/base/host_resolver_unittest.cc
index 090fd5c..393385af 100644
--- a/net/base/host_resolver_unittest.cc
+++ b/net/base/host_resolver_unittest.cc
@@ -18,6 +18,7 @@
#include "base/ref_counted.h"
#include "net/base/address_list.h"
#include "net/base/completion_callback.h"
+#include "net/base/dns_resolution_observer.h"
#include "net/base/host_resolver_unittest.h"
#include "net/base/net_errors.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -82,12 +83,22 @@ class ResolveRequest {
const std::string& hostname,
int port,
Delegate* delegate)
- : hostname_(hostname), port_(port), resolver_(resolver),
- delegate_(delegate),
+ : info_(hostname, port), resolver_(resolver), delegate_(delegate),
ALLOW_THIS_IN_INITIALIZER_LIST(
callback_(this, &ResolveRequest::OnLookupFinished)) {
// Start the request.
- int err = resolver->Resolve(hostname, port, &addrlist_, &callback_, &req_);
+ int err = resolver->Resolve(info_, &addrlist_, &callback_, &req_);
+ EXPECT_EQ(net::ERR_IO_PENDING, err);
+ }
+
+ ResolveRequest(net::HostResolver* resolver,
+ const net::HostResolver::RequestInfo& info,
+ Delegate* delegate)
+ : info_(info), resolver_(resolver), delegate_(delegate),
+ ALLOW_THIS_IN_INITIALIZER_LIST(
+ callback_(this, &ResolveRequest::OnLookupFinished)) {
+ // Start the request.
+ int err = resolver->Resolve(info, &addrlist_, &callback_, &req_);
EXPECT_EQ(net::ERR_IO_PENDING, err);
}
@@ -96,11 +107,11 @@ class ResolveRequest {
}
const std::string& hostname() const {
- return hostname_;
+ return info_.hostname();
}
int port() const {
- return port_;
+ return info_.port();
}
int result() const {
@@ -122,8 +133,7 @@ class ResolveRequest {
}
// The request details.
- std::string hostname_;
- int port_;
+ net::HostResolver::RequestInfo info_;
net::HostResolver::Request* req_;
// The result of the resolve.
@@ -168,8 +178,8 @@ TEST_F(HostResolverTest, SynchronousLookup) {
mapper->AddRule("just.testing", "192.168.1.42");
ScopedHostMapper scoped_mapper(mapper.get());
- int err = host_resolver.Resolve("just.testing", kPortnum, &adrlist, NULL,
- NULL);
+ net::HostResolver::RequestInfo info("just.testing", kPortnum);
+ int err = host_resolver.Resolve(info, &adrlist, NULL, NULL);
EXPECT_EQ(net::OK, err);
const struct addrinfo* ainfo = adrlist.head();
@@ -191,8 +201,8 @@ TEST_F(HostResolverTest, AsynchronousLookup) {
mapper->AddRule("just.testing", "192.168.1.42");
ScopedHostMapper scoped_mapper(mapper.get());
- int err = host_resolver.Resolve("just.testing", kPortnum, &adrlist,
- &callback_, NULL);
+ net::HostResolver::RequestInfo info("just.testing", kPortnum);
+ int err = host_resolver.Resolve(info, &adrlist, &callback_, NULL);
EXPECT_EQ(net::ERR_IO_PENDING, err);
MessageLoop::current()->Run();
@@ -219,8 +229,8 @@ TEST_F(HostResolverTest, CanceledAsynchronousLookup) {
net::AddressList adrlist;
const int kPortnum = 80;
- int err = host_resolver.Resolve("just.testing", kPortnum, &adrlist,
- &callback_, NULL);
+ net::HostResolver::RequestInfo info("just.testing", kPortnum);
+ int err = host_resolver.Resolve(info, &adrlist, &callback_, NULL);
EXPECT_EQ(net::ERR_IO_PENDING, err);
// Make sure we will exit the queue even when callback is not called.
@@ -245,7 +255,8 @@ TEST_F(HostResolverTest, NumericIPv4Address) {
net::HostResolver host_resolver;
net::AddressList adrlist;
const int kPortnum = 5555;
- int err = host_resolver.Resolve("127.1.2.3", kPortnum, &adrlist, NULL, NULL);
+ net::HostResolver::RequestInfo info("127.1.2.3", kPortnum);
+ int err = host_resolver.Resolve(info, &adrlist, NULL, NULL);
EXPECT_EQ(net::OK, err);
const struct addrinfo* ainfo = adrlist.head();
@@ -268,8 +279,8 @@ TEST_F(HostResolverTest, NumericIPv6Address) {
net::HostResolver host_resolver;
net::AddressList adrlist;
const int kPortnum = 5555;
- int err = host_resolver.Resolve("2001:db8::1", kPortnum, &adrlist, NULL,
- NULL);
+ net::HostResolver::RequestInfo info("2001:db8::1", kPortnum);
+ int err = host_resolver.Resolve(info, &adrlist, NULL, NULL);
// On computers without IPv6 support, getaddrinfo cannot convert IPv6
// address literals to addresses (getaddrinfo returns EAI_NONAME). So this
// test has to allow host_resolver.Resolve to fail.
@@ -302,7 +313,8 @@ TEST_F(HostResolverTest, EmptyHost) {
net::HostResolver host_resolver;
net::AddressList adrlist;
const int kPortnum = 5555;
- int err = host_resolver.Resolve("", kPortnum, &adrlist, NULL, NULL);
+ net::HostResolver::RequestInfo info("", kPortnum);
+ int err = host_resolver.Resolve(info, &adrlist, NULL, NULL);
EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, err);
}
@@ -457,7 +469,7 @@ class CancelWithinCallbackVerifier : public ResolveRequest::Delegate {
// Start a request (so we can make sure the canceled requests don't
// complete before "finalrequest" finishes.
final_request_.reset(new ResolveRequest(
- resolve->resolver(), "finalrequest", 70, this));
+ resolve->resolver(), "finalrequest", 70, this));
} else if (83 == resolve->port()) {
EXPECT_EQ("a", resolve->hostname());
@@ -618,4 +630,164 @@ TEST_F(HostResolverTest, StartWithinCallback) {
MessageLoop::current()->Run();
}
+// Helper class used by HostResolverTest.BypassCache.
+class BypassCacheVerifier : public ResolveRequest::Delegate {
+ public:
+ BypassCacheVerifier() {}
+
+ virtual void OnCompleted(ResolveRequest* resolve) {
+ EXPECT_EQ("a", resolve->hostname());
+ net::HostResolver* resolver = resolve->resolver();
+
+ if (80 == resolve->port()) {
+ // On completing the first request, start another request for "a".
+ // Since caching is enabled, this should complete synchronously.
+
+ // Note that |junk_callback| shouldn't be used since we are going to
+ // complete synchronously. We can't specify NULL though since that would
+ // mean synchronous mode so we give it a value of 1.
+ net::CompletionCallback* junk_callback =
+ reinterpret_cast<net::CompletionCallback*> (1);
+ net::AddressList addrlist;
+
+ net::HostResolver::RequestInfo info("a", 70);
+ int error = resolver->Resolve(info, &addrlist, junk_callback, NULL);
+ EXPECT_EQ(net::OK, error);
+
+ // Ok good. Now make sure that if we ask to bypass the cache, it can no
+ // longer service the request synchronously.
+ info = net::HostResolver::RequestInfo("a", 71);
+ info.set_allow_cached_response(false);
+ final_request_.reset(new ResolveRequest(resolver, info, this));
+ } else if (71 == resolve->port()) {
+ // Test is done.
+ MessageLoop::current()->Quit();
+ } else {
+ FAIL() << "Unexpected port number";
+ }
+ }
+
+ private:
+ scoped_ptr<ResolveRequest> final_request_;
+ DISALLOW_COPY_AND_ASSIGN(BypassCacheVerifier);
+};
+
+TEST_F(HostResolverTest, BypassCache) {
+ net::HostResolver host_resolver;
+
+ // The class will receive callbacks for when each resolve completes. It
+ // checks that the right things happened.
+ BypassCacheVerifier verifier;
+
+ // Start a request.
+ ResolveRequest req1(&host_resolver, "a", 80, &verifier);
+
+ // |verifier| will send quit message once all the requests have finished.
+ MessageLoop::current()->Run();
+}
+
+bool operator==(const net::HostResolver::RequestInfo& a,
+ const net::HostResolver::RequestInfo& b) {
+ return a.hostname() == b.hostname() &&
+ a.port() == b.port() &&
+ a.allow_cached_response() == b.allow_cached_response() &&
+ a.is_speculative() == b.is_speculative() &&
+ a.referrer() == b.referrer();
+}
+
+// Observer that just makes note of how it was called. The test code can then
+// inspect to make sure it was called with the right parameters.
+class CapturingObserver : public net::DnsResolutionObserver {
+ public:
+ // DnsResolutionObserver methods:
+ virtual void OnStartResolution(int id,
+ const net::HostResolver::RequestInfo& info) {
+ start_log.push_back(StartEntry(id, info));
+ }
+
+ virtual void OnFinishResolutionWithStatus(
+ int id,
+ bool was_resolved,
+ const net::HostResolver::RequestInfo& info) {
+ finish_log.push_back(FinishEntry(id, was_resolved, info));
+ }
+
+ // Tuple (id, info).
+ struct StartEntry {
+ StartEntry(int id, const net::HostResolver::RequestInfo& info)
+ : id(id), info(info) {}
+
+ bool operator==(const StartEntry& other) const {
+ return id == other.id && info == other.info;
+ }
+
+ int id;
+ net::HostResolver::RequestInfo info;
+ };
+
+ // Tuple (id, was_resolved, info).
+ struct FinishEntry {
+ FinishEntry(int id, bool was_resolved,
+ const net::HostResolver::RequestInfo& info)
+ : id(id), was_resolved(was_resolved), info(info) {}
+
+ bool operator==(const FinishEntry& other) const {
+ return id == other.id &&
+ was_resolved == other.was_resolved &&
+ info == other.info;
+ }
+
+ int id;
+ bool was_resolved;
+ net::HostResolver::RequestInfo info;
+ };
+
+ std::vector<StartEntry> start_log;
+ std::vector<FinishEntry> finish_log;
+};
+
+// Test that registering, unregistering, and notifying of observers works.
+TEST_F(HostResolverTest, Observers) {
+ net::HostResolver host_resolver;
+
+ CapturingObserver observer;
+
+ host_resolver.AddObserver(&observer);
+
+ net::AddressList addrlist;
+
+ // Resolve "host1".
+ net::HostResolver::RequestInfo info1("host1", 70);
+ host_resolver.Resolve(info1, &addrlist, NULL, NULL);
+
+ EXPECT_EQ(1U, observer.start_log.size());
+ EXPECT_EQ(1U, observer.finish_log.size());
+ EXPECT_TRUE(
+ observer.start_log[0] == CapturingObserver::StartEntry(0, info1));
+ EXPECT_TRUE(
+ observer.finish_log[0] == CapturingObserver::FinishEntry(0, true, info1));
+
+ // Resolve "host2", setting referrer to "http://foobar.com"
+ net::HostResolver::RequestInfo info2("host2", 70);
+ info2.set_referrer(GURL("http://foobar.com"));
+ host_resolver.Resolve(info2, &addrlist, NULL, NULL);
+
+ EXPECT_EQ(2U, observer.start_log.size());
+ EXPECT_EQ(2U, observer.finish_log.size());
+ EXPECT_TRUE(observer.start_log[1] == CapturingObserver::StartEntry(1, info2));
+ EXPECT_TRUE(observer.finish_log[1] == CapturingObserver::FinishEntry(
+ 1, true, info2));
+
+ // Unregister the observer.
+ host_resolver.RemoveObserver(&observer);
+
+ // Resolve "host3"
+ net::HostResolver::RequestInfo info3("host3", 70);
+ host_resolver.Resolve(info3, &addrlist, NULL, NULL);
+
+ // No effect this time, since observer was removed.
+ EXPECT_EQ(2U, observer.start_log.size());
+ EXPECT_EQ(2U, observer.finish_log.size());
+}
+
} // namespace
diff --git a/net/base/ssl_client_socket_unittest.cc b/net/base/ssl_client_socket_unittest.cc
index ab29cc4..ef308a1 100644
--- a/net/base/ssl_client_socket_unittest.cc
+++ b/net/base/ssl_client_socket_unittest.cc
@@ -76,8 +76,8 @@ TEST_F(SSLClientSocketTest, MAYBE_Connect) {
net::HostResolver resolver;
TestCompletionCallback callback;
- int rv = resolver.Resolve(server_.kHostName, server_.kOKHTTPSPort,
- &addr, NULL, NULL);
+ net::HostResolver::RequestInfo info(server_.kHostName, server_.kOKHTTPSPort);
+ int rv = resolver.Resolve(info, &addr, NULL, NULL);
EXPECT_EQ(net::OK, rv);
net::ClientSocket *transport = new net::TCPClientSocket(addr);
@@ -114,8 +114,8 @@ TEST_F(SSLClientSocketTest, MAYBE_ConnectExpired) {
net::HostResolver resolver;
TestCompletionCallback callback;
- int rv = resolver.Resolve(server_.kHostName, server_.kBadHTTPSPort,
- &addr, NULL, NULL);
+ net::HostResolver::RequestInfo info(server_.kHostName, server_.kBadHTTPSPort);
+ int rv = resolver.Resolve(info, &addr, NULL, NULL);
EXPECT_EQ(net::OK, rv);
net::ClientSocket *transport = new net::TCPClientSocket(addr);
@@ -151,8 +151,9 @@ TEST_F(SSLClientSocketTest, MAYBE_ConnectMismatched) {
net::HostResolver resolver;
TestCompletionCallback callback;
- int rv = resolver.Resolve(server_.kMismatchedHostName, server_.kOKHTTPSPort,
- &addr, NULL, NULL);
+ net::HostResolver::RequestInfo info(server_.kMismatchedHostName,
+ server_.kOKHTTPSPort);
+ int rv = resolver.Resolve(info, &addr, NULL, NULL);
EXPECT_EQ(net::OK, rv);
net::ClientSocket *transport = new net::TCPClientSocket(addr);
@@ -193,8 +194,8 @@ TEST_F(SSLClientSocketTest, MAYBE_Read) {
net::HostResolver resolver;
TestCompletionCallback callback;
- int rv = resolver.Resolve(server_.kHostName, server_.kOKHTTPSPort,
- &addr, &callback, NULL);
+ net::HostResolver::RequestInfo info(server_.kHostName, server_.kOKHTTPSPort);
+ int rv = resolver.Resolve(info, &addr, &callback, NULL);
EXPECT_EQ(net::ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
@@ -254,8 +255,8 @@ TEST_F(SSLClientSocketTest, MAYBE_Read_SmallChunks) {
net::HostResolver resolver;
TestCompletionCallback callback;
- int rv = resolver.Resolve(server_.kHostName, server_.kOKHTTPSPort,
- &addr, NULL, NULL);
+ net::HostResolver::RequestInfo info(server_.kHostName, server_.kOKHTTPSPort);
+ int rv = resolver.Resolve(info, &addr, NULL, NULL);
EXPECT_EQ(net::OK, rv);
net::ClientSocket *transport = new net::TCPClientSocket(addr);
@@ -310,8 +311,8 @@ TEST_F(SSLClientSocketTest, MAYBE_Read_Interrupted) {
net::HostResolver resolver;
TestCompletionCallback callback;
- int rv = resolver.Resolve(server_.kHostName, server_.kOKHTTPSPort,
- &addr, NULL, NULL);
+ net::HostResolver::RequestInfo info(server_.kHostName, server_.kOKHTTPSPort);
+ int rv = resolver.Resolve(info, &addr, NULL, NULL);
EXPECT_EQ(net::OK, rv);
net::ClientSocket *transport = new net::TCPClientSocket(addr);
diff --git a/net/base/ssl_test_util.cc b/net/base/ssl_test_util.cc
index cac5d04..f470139 100644
--- a/net/base/ssl_test_util.cc
+++ b/net/base/ssl_test_util.cc
@@ -247,7 +247,8 @@ bool TestServerLauncher::WaitToStart(const std::string& host_name, int port) {
// Otherwise tests can fail if they run faster than Python can start.
net::AddressList addr;
net::HostResolver resolver;
- int rv = resolver.Resolve(host_name, port, &addr, NULL, NULL);
+ net::HostResolver::RequestInfo info(host_name, port);
+ int rv = resolver.Resolve(info, &addr, NULL, NULL);
if (rv != net::OK)
return false;
diff --git a/net/base/tcp_client_socket_pool.cc b/net/base/tcp_client_socket_pool.cc
index 4a52c10..c5e961e 100644
--- a/net/base/tcp_client_socket_pool.cc
+++ b/net/base/tcp_client_socket_pool.cc
@@ -58,11 +58,9 @@ TCPClientSocketPool::ConnectingSocket::~ConnectingSocket() {
}
int TCPClientSocketPool::ConnectingSocket::Connect(
- const std::string& host,
- int port) {
+ const HostResolver::RequestInfo& resolve_info) {
CHECK(!canceled_);
- DidStartDnsResolution(host, this);
- int rv = resolver_.Resolve(host, port, &addresses_, &callback_);
+ int rv = resolver_.Resolve(resolve_info, &addresses_, &callback_);
if (rv != ERR_IO_PENDING)
rv = OnIOCompleteInternal(rv, true /* synchronous */);
return rv;
@@ -186,26 +184,20 @@ void TCPClientSocketPool::InsertRequestIntoQueue(
pending_requests->insert(it, r);
}
-int TCPClientSocketPool::RequestSocket(const std::string& group_name,
- const std::string& host,
- int port,
- int priority,
- ClientSocketHandle* handle,
- CompletionCallback* callback) {
- DCHECK(!host.empty());
+int TCPClientSocketPool::RequestSocket(
+ const std::string& group_name,
+ const HostResolver::RequestInfo& resolve_info,
+ int priority,
+ ClientSocketHandle* handle,
+ CompletionCallback* callback) {
+ DCHECK(!resolve_info.hostname().empty());
DCHECK_GE(priority, 0);
Group& group = group_map_[group_name];
// Can we make another active socket now?
if (group.active_socket_count == max_sockets_per_group_) {
- Request r;
- r.handle = handle;
CHECK(callback);
- r.callback = callback;
- r.priority = priority;
- r.host = host;
- r.port = port;
- r.load_state = LOAD_STATE_IDLE;
+ Request r(handle, callback, priority, resolve_info, LOAD_STATE_IDLE);
InsertRequestIntoQueue(r, &group.pending_requests);
return ERR_IO_PENDING;
}
@@ -234,20 +226,15 @@ int TCPClientSocketPool::RequestSocket(const std::string& group_name,
if (ContainsKey(connecting_socket_map_, handle))
connecting_socket_map_[handle]->Cancel();
- Request r;
- r.handle = handle;
CHECK(callback);
- r.callback = callback;
- r.priority = priority;
- r.host = host;
- r.port = port;
- r.load_state = LOAD_STATE_RESOLVING_HOST;
+ Request r(handle, callback, priority, resolve_info,
+ LOAD_STATE_RESOLVING_HOST);
group_map_[group_name].connecting_requests[handle] = r;
// connecting_socket will delete itself.
ConnectingSocket* connecting_socket =
new ConnectingSocket(group_name, handle, client_socket_factory_, this);
- int rv = connecting_socket->Connect(host, port);
+ int rv = connecting_socket->Connect(resolve_info);
return rv;
}
@@ -419,7 +406,7 @@ void TCPClientSocketPool::DoReleaseSocket(const std::string& group_name,
group.pending_requests.pop_front();
int rv = RequestSocket(
- group_name, r.host, r.port, r.priority, r.handle, r.callback);
+ group_name, r.resolve_info, r.priority, r.handle, r.callback);
if (rv != ERR_IO_PENDING)
r.callback->Run(rv);
return;
diff --git a/net/base/tcp_client_socket_pool.h b/net/base/tcp_client_socket_pool.h
index 82255c5..ad75585 100644
--- a/net/base/tcp_client_socket_pool.h
+++ b/net/base/tcp_client_socket_pool.h
@@ -31,8 +31,7 @@ class TCPClientSocketPool : public ClientSocketPool {
// ClientSocketPool methods:
virtual int RequestSocket(const std::string& group_name,
- const std::string& host,
- int port,
+ const HostResolver::RequestInfo& resolve_info,
int priority,
ClientSocketHandle* handle,
CompletionCallback* callback);
@@ -62,11 +61,22 @@ class TCPClientSocketPool : public ClientSocketPool {
// A Request is allocated per call to RequestSocket that results in
// ERR_IO_PENDING.
struct Request {
+ // HostResolver::RequestInfo has no default constructor, so fudge something.
+ Request() : resolve_info(std::string(), 0) {}
+
+ Request(ClientSocketHandle* handle,
+ CompletionCallback* callback,
+ int priority,
+ const HostResolver::RequestInfo& resolve_info,
+ LoadState load_state)
+ : handle(handle), callback(callback), priority(priority),
+ resolve_info(resolve_info), load_state(load_state) {
+ }
+
ClientSocketHandle* handle;
CompletionCallback* callback;
int priority;
- std::string host;
- int port;
+ HostResolver::RequestInfo resolve_info;
LoadState load_state;
};
@@ -118,7 +128,7 @@ class TCPClientSocketPool : public ClientSocketPool {
// Begins the host resolution and the TCP connect. Returns OK on success
// and ERR_IO_PENDING if it cannot immediately service the request.
// Otherwise, it returns a net error code.
- int Connect(const std::string& host, int port);
+ int Connect(const HostResolver::RequestInfo& resolve_info);
// Called by the TCPClientSocketPool to cancel this ConnectingSocket. Only
// necessary if a ClientSocketHandle is reused.
diff --git a/net/base/tcp_client_socket_pool_unittest.cc b/net/base/tcp_client_socket_pool_unittest.cc
index 54b6330..2d19605 100644
--- a/net/base/tcp_client_socket_pool_unittest.cc
+++ b/net/base/tcp_client_socket_pool_unittest.cc
@@ -232,7 +232,8 @@ class TCPClientSocketPoolTest : public testing::Test {
TEST_F(TCPClientSocketPoolTest, Basic) {
TestCompletionCallback callback;
ClientSocketHandle handle(pool_.get());
- int rv = handle.Init("a", "www.google.com", 80, 0, &callback);
+ HostResolver::RequestInfo info("www.google.com", 80);
+ int rv = handle.Init("a", info, 0, &callback);
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -252,8 +253,8 @@ TEST_F(TCPClientSocketPoolTest, InitHostResolutionFailure) {
host_mapper->AddSimulatedFailure("unresolvable.host.name");
ScopedHostMapper scoped_host_mapper(host_mapper);
TestSocketRequest req(pool_.get(), &request_order_);
- EXPECT_EQ(ERR_IO_PENDING,
- req.handle.Init("a", "unresolvable.host.name", 80, 5, &req));
+ HostResolver::RequestInfo info("unresolvable.host.name", 80);
+ EXPECT_EQ(ERR_IO_PENDING, req.handle.Init("a", info, 5, &req));
EXPECT_EQ(ERR_NAME_NOT_RESOLVED, req.WaitForResult());
}
@@ -261,8 +262,9 @@ TEST_F(TCPClientSocketPoolTest, InitConnectionFailure) {
client_socket_factory_.set_client_socket_type(
MockClientSocketFactory::MOCK_FAILING_CLIENT_SOCKET);
TestSocketRequest req(pool_.get(), &request_order_);
+ HostResolver::RequestInfo info("unresolvable.host.name", 80);
EXPECT_EQ(ERR_IO_PENDING,
- req.handle.Init("a", "unresolvable.host.name", 80, 5, &req));
+ req.handle.Init("a", info, 5, &req));
EXPECT_EQ(ERR_CONNECTION_FAILED, req.WaitForResult());
}
@@ -275,13 +277,14 @@ TEST_F(TCPClientSocketPoolTest, PendingRequests) {
// Create connections or queue up requests.
// First request finishes asynchronously.
- int rv = reqs[0]->handle.Init("a", "www.google.com", 80, 5, reqs[0].get());
+ HostResolver::RequestInfo info("www.google.com", 80);
+ int rv = reqs[0]->handle.Init("a", info, 5, reqs[0].get());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, reqs[0]->WaitForResult());
// Rest of them finish synchronously, since they're in the HostCache.
for (int i = 1; i < kMaxSocketsPerGroup; ++i) {
- rv = reqs[i]->handle.Init("a", "www.google.com", 80, 5, reqs[i].get());
+ rv = reqs[i]->handle.Init("a", info, 5, reqs[i].get());
EXPECT_EQ(OK, rv);
request_order_.push_back(reqs[i].get());
}
@@ -289,8 +292,7 @@ TEST_F(TCPClientSocketPoolTest, PendingRequests) {
// The rest are pending since we've used all active sockets.
for (int i = 0; i < kNumPendingRequests; ++i) {
rv = reqs[kMaxSocketsPerGroup + i]->handle.Init(
- "a", "www.google.com", 80, kPriorities[i],
- reqs[kMaxSocketsPerGroup + i].get());
+ "a", info, kPriorities[i], reqs[kMaxSocketsPerGroup + i].get());
EXPECT_EQ(ERR_IO_PENDING, rv);
}
@@ -336,13 +338,14 @@ TEST_F(TCPClientSocketPoolTest, PendingRequests_NoKeepAlive) {
// Create connections or queue up requests.
// First request finishes asynchronously.
- int rv = reqs[0]->handle.Init("a", "www.google.com", 80, 5, reqs[0].get());
+ HostResolver::RequestInfo info("www.google.com", 80);
+ int rv = reqs[0]->handle.Init("a", info, 5, reqs[0].get());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, reqs[0]->WaitForResult());
// Rest of them finish synchronously, since they're in the HostCache.
for (int i = 1; i < kMaxSocketsPerGroup; ++i) {
- rv = reqs[i]->handle.Init("a", "www.google.com", 80, 5, reqs[i].get());
+ rv = reqs[i]->handle.Init("a", info, 5, reqs[i].get());
EXPECT_EQ(OK, rv);
request_order_.push_back(reqs[i].get());
}
@@ -350,7 +353,7 @@ TEST_F(TCPClientSocketPoolTest, PendingRequests_NoKeepAlive) {
// The rest are pending since we've used all active sockets.
for (int i = 0; i < kNumPendingRequests; ++i) {
EXPECT_EQ(ERR_IO_PENDING, reqs[kMaxSocketsPerGroup + i]->handle.Init(
- "a", "www.google.com", 80, 0, reqs[kMaxSocketsPerGroup + i].get()));
+ "a", info, 0, reqs[kMaxSocketsPerGroup + i].get()));
}
// Release any connections until we have no connections.
@@ -379,8 +382,8 @@ TEST_F(TCPClientSocketPoolTest, PendingRequests_NoKeepAlive) {
// ClientSocketPool which will crash if the group was not cleared properly.
TEST_F(TCPClientSocketPoolTest, CancelRequestClearGroup) {
TestSocketRequest req(pool_.get(), &request_order_);
- EXPECT_EQ(ERR_IO_PENDING,
- req.handle.Init("a", "www.google.com", 80, 5, &req));
+ HostResolver::RequestInfo info("www.google.com", 80);
+ EXPECT_EQ(ERR_IO_PENDING, req.handle.Init("a", info, 5, &req));
req.handle.Reset();
PlatformThread::Sleep(100);
@@ -397,10 +400,9 @@ TEST_F(TCPClientSocketPoolTest, TwoRequestsCancelOne) {
TestSocketRequest req(pool_.get(), &request_order_);
TestSocketRequest req2(pool_.get(), &request_order_);
- EXPECT_EQ(ERR_IO_PENDING,
- req.handle.Init("a", "www.google.com", 80, 5, &req));
- EXPECT_EQ(ERR_IO_PENDING,
- req2.handle.Init("a", "www.google.com", 80, 5, &req2));
+ HostResolver::RequestInfo info("www.google.com", 80);
+ EXPECT_EQ(ERR_IO_PENDING, req.handle.Init("a", info, 5, &req));
+ EXPECT_EQ(ERR_IO_PENDING, req2.handle.Init("a", info, 5, &req2));
req.handle.Reset();
@@ -417,14 +419,13 @@ TEST_F(TCPClientSocketPoolTest, ConnectCancelConnect) {
TestCompletionCallback callback;
TestSocketRequest req(pool_.get(), &request_order_);
- EXPECT_EQ(ERR_IO_PENDING,
- handle.Init("a", "www.google.com", 80, 5, &callback));
+ HostResolver::RequestInfo info("www.google.com", 80);
+ EXPECT_EQ(ERR_IO_PENDING, handle.Init("a", info, 5, &callback));
handle.Reset();
TestCompletionCallback callback2;
- EXPECT_EQ(ERR_IO_PENDING,
- handle.Init("a", "www.google.com", 80, 5, &callback2));
+ EXPECT_EQ(ERR_IO_PENDING, handle.Init("a", info, 5, &callback2));
// At this point, handle has two ConnectingSockets out for it. Due to the
// host cache, the host resolution for both will return in the same loop of
@@ -449,15 +450,16 @@ TEST_F(TCPClientSocketPoolTest, CancelRequest) {
reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_));
// Create connections or queue up requests.
+ HostResolver::RequestInfo info("www.google.com", 80);
// First request finishes asynchronously.
- int rv = reqs[0]->handle.Init("a", "www.google.com", 80, 5, reqs[0].get());
+ int rv = reqs[0]->handle.Init("a", info, 5, reqs[0].get());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, reqs[0]->WaitForResult());
// Rest of them finish synchronously, since they're in the HostCache.
for (int i = 1; i < kMaxSocketsPerGroup; ++i) {
- rv = reqs[i]->handle.Init("a", "www.google.com", 80, 5, reqs[i].get());
+ rv = reqs[i]->handle.Init("a", info, 5, reqs[i].get());
EXPECT_EQ(OK, rv);
request_order_.push_back(reqs[i].get());
}
@@ -465,8 +467,7 @@ TEST_F(TCPClientSocketPoolTest, CancelRequest) {
// The rest are pending since we've used all active sockets.
for (int i = 0; i < kNumPendingRequests; ++i) {
EXPECT_EQ(ERR_IO_PENDING, reqs[kMaxSocketsPerGroup + i]->handle.Init(
- "a", "www.google.com", 80, kPriorities[i],
- reqs[kMaxSocketsPerGroup + i].get()));
+ "a", info, kPriorities[i], reqs[kMaxSocketsPerGroup + i].get()));
}
// Cancel a request.
diff --git a/net/base/tcp_client_socket_unittest.cc b/net/base/tcp_client_socket_unittest.cc
index fe37c71..21f524e 100644
--- a/net/base/tcp_client_socket_unittest.cc
+++ b/net/base/tcp_client_socket_unittest.cc
@@ -87,7 +87,8 @@ void TCPClientSocketTest::SetUp() {
AddressList addr;
HostResolver resolver;
- int rv = resolver.Resolve("localhost", listen_port_, &addr, NULL, NULL);
+ HostResolver::RequestInfo info("localhost", listen_port_);
+ int rv = resolver.Resolve(info, &addr, NULL, NULL);
CHECK(rv == OK);
sock_.reset(new TCPClientSocket(addr));
}
diff --git a/net/base/tcp_pinger_unittest.cc b/net/base/tcp_pinger_unittest.cc
index edf29a5..d09f42a 100644
--- a/net/base/tcp_pinger_unittest.cc
+++ b/net/base/tcp_pinger_unittest.cc
@@ -67,7 +67,8 @@ TEST_F(TCPPingerTest, Ping) {
net::AddressList addr;
net::HostResolver resolver;
- int rv = resolver.Resolve("localhost", listen_port_, &addr, NULL, NULL);
+ net::HostResolver::RequestInfo info("localhost", listen_port_);
+ int rv = resolver.Resolve(info, &addr, NULL, NULL);
EXPECT_EQ(rv, net::OK);
net::TCPPinger pinger(addr);
@@ -82,7 +83,8 @@ TEST_F(TCPPingerTest, PingFail) {
// "Kill" "server"
listen_sock_ = NULL;
- int rv = resolver.Resolve("localhost", listen_port_, &addr, NULL, NULL);
+ net::HostResolver::RequestInfo info("localhost", listen_port_);
+ int rv = resolver.Resolve(info, &addr, NULL, NULL);
EXPECT_EQ(rv, net::OK);
net::TCPPinger pinger(addr);
diff --git a/net/ftp/ftp_network_transaction.cc b/net/ftp/ftp_network_transaction.cc
index 87f9217..18bd808 100644
--- a/net/ftp/ftp_network_transaction.cc
+++ b/net/ftp/ftp_network_transaction.cc
@@ -339,13 +339,13 @@ int FtpNetworkTransaction::DoCtrlResolveHost() {
host = request_->url.host();
port = request_->url.EffectiveIntPort();
- DidStartDnsResolution(host, this);
- return resolver_.Resolve(host, port, &addresses_, &io_callback_);
+ HostResolver::RequestInfo info(host, port);
+ // No known referrer.
+ return resolver_.Resolve(info, &addresses_, &io_callback_);
}
int FtpNetworkTransaction::DoCtrlResolveHostComplete(int result) {
bool ok = (result == OK);
- DidFinishDnsResolutionWithStatus(ok, GURL(), this);
if (ok) {
next_state_ = STATE_CTRL_CONNECT;
return result;
@@ -832,14 +832,14 @@ int FtpNetworkTransaction::DoDataResolveHost() {
next_state_ = STATE_DATA_RESOLVE_HOST_COMPLETE;
- DidStartDnsResolution(data_connection_ip_, this);
- return resolver_.Resolve(data_connection_ip_, data_connection_port_,
- &addresses_, &io_callback_);
+ HostResolver::RequestInfo info(data_connection_ip_,
+ data_connection_port_);
+ // No known referrer.
+ return resolver_.Resolve(info, &addresses_, &io_callback_);
}
int FtpNetworkTransaction::DoDataResolveHostComplete(int result) {
bool ok = (result == OK);
- DidFinishDnsResolutionWithStatus(ok, GURL(), this);
if (ok) {
next_state_ = STATE_DATA_CONNECT;
return result;
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 4fbd5cb..d5cd81f 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -570,7 +570,26 @@ int HttpNetworkTransaction::DoInitConnection() {
connection_group.append(request_->url.GetOrigin().spec());
DCHECK(!connection_group.empty());
- int rv = connection_.Init(connection_group, host, port, request_->priority,
+
+ HostResolver::RequestInfo resolve_info(host, port);
+
+ // The referrer is used by the DNS prefetch system to corellate resolutions
+ // with the page that triggered them. It doesn't impact the actual addresses
+ // that we resolve to.
+ resolve_info.set_referrer(request_->referrer);
+
+// TODO(eroman): Enable this!
+// Needs some unit-tests before turning on.
+// http://crbug.com/13163
+#if 0
+ // If the user is refreshing the page, bypass the host cache.
+ if (request_->load_flags & LOAD_BYPASS_CACHE ||
+ request_->load_flags & LOAD_DISABLE_CACHE) {
+ resolve_info.allow_cached_response = false;
+ }
+#endif
+
+ int rv = connection_.Init(connection_group, resolve_info, request_->priority,
&io_callback_);
return rv;
}
diff --git a/net/net.gyp b/net/net.gyp
index c6c92b5..d187781 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -61,7 +61,6 @@
'base/data_url.h',
'base/directory_lister.cc',
'base/directory_lister.h',
- 'base/dns_resolution_observer.cc',
'base/dns_resolution_observer.h',
'base/effective_tld_names.cc',
'base/effective_tld_names.dat',
diff --git a/net/proxy/proxy_resolver_v8.cc b/net/proxy/proxy_resolver_v8.cc
index 38e0a83..ad4f1eb6 100644
--- a/net/proxy/proxy_resolver_v8.cc
+++ b/net/proxy/proxy_resolver_v8.cc
@@ -70,15 +70,16 @@ class SyncHostResolverBridge
// Run the resolve on host_resolver_loop, and wait for result.
int Resolve(const std::string& hostname, net::AddressList* addresses) {
- int kPort = 80; // Doesn't matter.
+ // Port number doesn't matter.
+ HostResolver::RequestInfo info(hostname, 80);
// Hack for tests -- run synchronously on current thread.
if (!host_resolver_loop_)
- return host_resolver_->Resolve(hostname, kPort, addresses, NULL, NULL);
+ return host_resolver_->Resolve(info, addresses, NULL, NULL);
// Otherwise start an async resolve on the resolver's thread.
host_resolver_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
- &SyncHostResolverBridge::StartResolve, hostname, kPort, addresses));
+ &SyncHostResolverBridge::StartResolve, info, addresses));
// Wait for the resolve to complete in the resolver's thread.
event_.Wait();
@@ -87,12 +88,10 @@ class SyncHostResolverBridge
private:
// Called on host_resolver_loop_.
- void StartResolve(const std::string& hostname,
- int port,
+ void StartResolve(const HostResolver::RequestInfo& info,
net::AddressList* addresses) {
DCHECK_EQ(host_resolver_loop_, MessageLoop::current());
- int error = host_resolver_->Resolve(
- hostname, port, addresses, &callback_, NULL);
+ int error = host_resolver_->Resolve(info, addresses, &callback_, NULL);
if (error != ERR_IO_PENDING)
OnResolveCompletion(error); // Completed synchronously.
}