Support speculative pre-connection to search URLs
Implement several flavors of TCP/IP speculative preconnection
under a command line flag (not yet on by default).
The first area of preconnection takes place when a user types
a query into the omnibox, as we preconnect to the search service
when the omnibox suggests it is going to do a search.
The second area involves subresources, such as images.
When a navigation takes place, and we've seen navigations
to that domain/port before, and the history-based
probabability that we'll need to make a connection to
a second site (host/port) is sufficiently large, then we
preconnect to that second site while we are still connecting
to the primary site (and before we've gotten content from
the primary site.
We also fall-back to mere DNS pre-resolution of subresource
hostnames when the probability of a connection to the
subresource is not high enough.
BUG=42694
r=pkasting,willchan,mbelshe
Review URL: http://codereview.chromium.org/1585029
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@47479 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/net/dns_master.h b/chrome/browser/net/dns_master.h
index b665358..84497317 100644
--- a/chrome/browser/net/dns_master.h
+++ b/chrome/browser/net/dns_master.h
@@ -23,10 +23,9 @@
#include "chrome/browser/net/dns_host_info.h"
#include "chrome/browser/net/referrer.h"
#include "chrome/common/net/dns.h"
+#include "net/base/host_port_pair.h"
#include "testing/gtest/include/gtest/gtest_prod.h"
-using base::TimeDelta;
-
namespace net {
class HostResolver;
} // namespace net
@@ -34,16 +33,21 @@
namespace chrome_browser_net {
typedef chrome_common_net::NameList NameList;
-typedef std::map<std::string, DnsHostInfo> Results;
+typedef std::map<net::HostPortPair, DnsHostInfo> Results;
// Note that DNS master is not thread safe, and must only be called from
// the IO thread. Failure to do so will result in a DCHECK at runtime.
class DnsMaster : public base::RefCountedThreadSafe<DnsMaster> {
public:
- // |max_concurrent| specifies how many concurrent (parallel) prefetches will
+ // A version number for prefs that are saved. This should be incremented when
+ // we change the format so that we discard old data.
+ enum {DNS_REFERRER_VERSION = 0 };
+
+// |max_concurrent| specifies how many concurrent (parallel) prefetches will
// be performed. Host lookups will be issued through |host_resolver|.
DnsMaster(net::HostResolver* host_resolver,
- TimeDelta max_queue_delay_ms, size_t max_concurrent);
+ base::TimeDelta max_queue_delay_ms, size_t max_concurrent,
+ bool preconnect_enabled);
// Cancel pending requests and prevent new ones from being made.
void Shutdown();
@@ -58,21 +62,21 @@
// Add hostname(s) to the queue for processing.
void ResolveList(const NameList& hostnames,
DnsHostInfo::ResolutionMotivation motivation);
- void Resolve(const std::string& hostname,
+ void Resolve(const net::HostPortPair& hostport,
DnsHostInfo::ResolutionMotivation motivation);
// Get latency benefit of the prefetch that we are navigating to.
- bool AccruePrefetchBenefits(const GURL& referrer,
+ bool AccruePrefetchBenefits(const net::HostPortPair& referrer,
DnsHostInfo* navigation_info);
// Instigate prefetch of any domains we predict will be needed after this
// navigation.
- void NavigatingTo(const std::string& host_name);
+ void NavigatingTo(const net::HostPortPair& hostport);
// Record details of a navigation so that we can preresolve the host name
// ahead of time the next time the users navigates to the indicated host.
// TODO(eroman): can this be a const& instead?
- void NonlinkNavigation(const GURL& referrer,
+ void NonlinkNavigation(const net::HostPortPair& referrer,
const DnsHostInfo* navigation_info);
// Dump HTML table containing list of referrers for about:dns.
@@ -106,6 +110,9 @@
// For unit test code only.
size_t max_concurrent_lookups() const { return max_concurrent_lookups_; }
+ // Flag setting to use preconnection instead of just DNS pre-fetching.
+ bool preconnect_enabled() const { return preconnect_enabled_; }
+
private:
friend class base::RefCountedThreadSafe<DnsMaster>;
FRIEND_TEST(DnsMasterTest, BenefitLookupTest);
@@ -133,39 +140,41 @@
public:
HostNameQueue();
~HostNameQueue();
- void Push(const std::string& hostname,
+ void Push(const net::HostPortPair& hostport,
DnsHostInfo::ResolutionMotivation motivation);
bool IsEmpty() const;
- std::string Pop();
+ net::HostPortPair Pop();
private:
// The names in the queue that should be serviced (popped) ASAP.
- std::queue<std::string> rush_queue_;
+ std::queue<net::HostPortPair> rush_queue_;
// The names in the queue that should only be serviced when rush_queue is
// empty.
- std::queue<std::string> background_queue_;
+ std::queue<net::HostPortPair> background_queue_;
DISALLOW_COPY_AND_ASSIGN(HostNameQueue);
};
- // A map that is keyed with the hostnames that we've learned were the cause
- // of loading additional hostnames. The list of additional hostnames in held
- // in a Referrer instance, which is found in this type.
- typedef std::map<std::string, Referrer> Referrers;
+ // A map that is keyed with the host/port that we've learned were the cause
+ // of loading additional URLs. The list of additional targets is held
+ // in a Referrer instance, which is a value in this map.
+ typedef std::map<net::HostPortPair, Referrer> Referrers;
// Only for testing. Returns true if hostname has been successfully resolved
// (name found).
- bool WasFound(const std::string& hostname) {
- return (results_.find(hostname) != results_.end()) &&
- results_[hostname].was_found();
+ bool WasFound(const net::HostPortPair& hostport) const {
+ Results::const_iterator it(results_.find(hostport));
+ return (it != results_.end()) &&
+ it->second.was_found();
}
// Only for testing. Return how long was the resolution
// or DnsHostInfo::kNullDuration if it hasn't been resolved yet.
- base::TimeDelta GetResolutionDuration(const std::string& hostname) {
- if (results_.find(hostname) == results_.end())
+ base::TimeDelta GetResolutionDuration(const net::HostPortPair& hostport) {
+
+ if (results_.find(hostport) == results_.end())
return DnsHostInfo::kNullDuration;
- return results_[hostname].resolve_duration();
+ return results_[hostport].resolve_duration();
}
// Only for testing;
@@ -173,16 +182,15 @@
// Access method for use by async lookup request to pass resolution result.
void OnLookupFinished(LookupRequest* request,
- const std::string& hostname, bool found);
+ const net::HostPortPair& hostport, bool found);
// Underlying method for both async and synchronous lookup to update state.
void LookupFinished(LookupRequest* request,
- const std::string& hostname,
- bool found);
+ const net::HostPortPair& hostport, bool found);
// Queue hostname for resolution. If queueing was done, return the pointer
// to the queued instance, otherwise return NULL.
- DnsHostInfo* AppendToResolutionQueue(const std::string& hostname,
+ DnsHostInfo* AppendToResolutionQueue(const net::HostPortPair& hostport,
DnsHostInfo::ResolutionMotivation motivation);
// Check to see if too much queuing delay has been noted for the given info,
@@ -209,7 +217,7 @@
// results_ contains information for existing/prior prefetches.
Results results_;
- // For each hostname that we might navigate to (that we've "learned about")
+ // For each URL that we might navigate to (that we've "learned about")
// we have a Referrer list. Each Referrer list has all hostnames we need to
// pre-resolve when there is a navigation to the orginial hostname.
Referrers referrers_;
@@ -233,11 +241,15 @@
// The maximum queueing delay that is acceptable before we enter congestion
// reduction mode, and discard all queued (but not yet assigned) resolutions.
- const TimeDelta max_queue_delay_;
+ const base::TimeDelta max_queue_delay_;
// The host resovler we warm DNS entries for.
scoped_refptr<net::HostResolver> host_resolver_;
+ // Are we currently using preconnection, rather than just DNS resolution, for
+ // subresources and omni-box search URLs.
+ bool preconnect_enabled_;
+
DISALLOW_COPY_AND_ASSIGN(DnsMaster);
};