blob: b665358c28dc268085c12b362026c287e6ae9b57 [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
5// A DnsMaster object is instantiated once in the browser
[email protected]1933eb202009-02-19 18:23:256// process, and manages asynchronous resolution of DNS hostnames.
initial.commit09911bf2008-07-26 23:55:297// Most hostname lists are sent out by renderer processes, and
8// involve lists of hostnames that *might* be used in the near
9// future by the browsing user. The goal of this class is to
10// cause the underlying DNS structure to lookup a hostname before
11// it is really needed, and hence reduce latency in the standard
[email protected]1933eb202009-02-19 18:23:2512// lookup paths.
initial.commit09911bf2008-07-26 23:55:2913
[email protected]e8013b32008-10-27 18:55:5214#ifndef CHROME_BROWSER_NET_DNS_MASTER_H_
15#define CHROME_BROWSER_NET_DNS_MASTER_H_
initial.commit09911bf2008-07-26 23:55:2916
17#include <map>
18#include <queue>
[email protected]1933eb202009-02-19 18:23:2519#include <set>
initial.commit09911bf2008-07-26 23:55:2920#include <string>
21
[email protected]fd2f8afe2009-06-11 21:53:5522#include "base/ref_counted.h"
initial.commit09911bf2008-07-26 23:55:2923#include "chrome/browser/net/dns_host_info.h"
[email protected]21dae9b2008-11-06 23:32:5324#include "chrome/browser/net/referrer.h"
initial.commit09911bf2008-07-26 23:55:2925#include "chrome/common/net/dns.h"
[email protected]1933eb202009-02-19 18:23:2526#include "testing/gtest/include/gtest/gtest_prod.h"
initial.commit09911bf2008-07-26 23:55:2927
[email protected]602faf3c2009-06-27 14:35:4428using base::TimeDelta;
29
[email protected]fd2f8afe2009-06-11 21:53:5530namespace net {
31class HostResolver;
[email protected]0ac83682010-01-22 17:46:2732} // namespace net
[email protected]fd2f8afe2009-06-11 21:53:5533
initial.commit09911bf2008-07-26 23:55:2934namespace chrome_browser_net {
35
initial.commit09911bf2008-07-26 23:55:2936typedef chrome_common_net::NameList NameList;
37typedef std::map<std::string, DnsHostInfo> Results;
38
[email protected]ec86bea2009-12-08 18:35:1439// Note that DNS master is not thread safe, and must only be called from
40// the IO thread. Failure to do so will result in a DCHECK at runtime.
[email protected]fd2f8afe2009-06-11 21:53:5541class DnsMaster : public base::RefCountedThreadSafe<DnsMaster> {
initial.commit09911bf2008-07-26 23:55:2942 public:
[email protected]3a29e2912009-11-23 18:34:5543 // |max_concurrent| specifies how many concurrent (parallel) prefetches will
[email protected]ec86bea2009-12-08 18:35:1444 // be performed. Host lookups will be issued through |host_resolver|.
[email protected]6fad2632009-11-02 05:59:3745 DnsMaster(net::HostResolver* host_resolver,
[email protected]602faf3c2009-06-27 14:35:4446 TimeDelta max_queue_delay_ms, size_t max_concurrent);
[email protected]b2b8b832009-02-06 19:03:2947
[email protected]1933eb202009-02-19 18:23:2548 // Cancel pending requests and prevent new ones from being made.
49 void Shutdown();
initial.commit09911bf2008-07-26 23:55:2950
51 // In some circumstances, for privacy reasons, all results should be
52 // discarded. This method gracefully handles that activity.
53 // Destroy all our internal state, which shows what names we've looked up, and
54 // how long each has taken, etc. etc. We also destroy records of suggesses
55 // (cache hits etc.).
56 void DiscardAllResults();
57
[email protected]1933eb202009-02-19 18:23:2558 // Add hostname(s) to the queue for processing.
[email protected]21dae9b2008-11-06 23:32:5359 void ResolveList(const NameList& hostnames,
60 DnsHostInfo::ResolutionMotivation motivation);
61 void Resolve(const std::string& hostname,
62 DnsHostInfo::ResolutionMotivation motivation);
initial.commit09911bf2008-07-26 23:55:2963
64 // Get latency benefit of the prefetch that we are navigating to.
[email protected]21dae9b2008-11-06 23:32:5365 bool AccruePrefetchBenefits(const GURL& referrer,
66 DnsHostInfo* navigation_info);
initial.commit09911bf2008-07-26 23:55:2967
[email protected]21dae9b2008-11-06 23:32:5368 // Instigate prefetch of any domains we predict will be needed after this
69 // navigation.
70 void NavigatingTo(const std::string& host_name);
71
72 // Record details of a navigation so that we can preresolve the host name
73 // ahead of time the next time the users navigates to the indicated host.
[email protected]ec86bea2009-12-08 18:35:1474 // TODO(eroman): can this be a const& instead?
75 void NonlinkNavigation(const GURL& referrer,
76 const DnsHostInfo* navigation_info);
[email protected]21dae9b2008-11-06 23:32:5377
78 // Dump HTML table containing list of referrers for about:dns.
79 void GetHtmlReferrerLists(std::string* output);
80
81 // Dump the list of currently know referrer domains and related prefetchable
82 // domains.
initial.commit09911bf2008-07-26 23:55:2983 void GetHtmlInfo(std::string* output);
84
[email protected]03c5e862009-02-17 22:50:1485 // Discard any referrer for which all the suggested host names are currently
86 // annotated with no user latency reduction. Also scale down (diminish) the
87 // total benefit of those that did help, so that their reported contribution
88 // wll go done by a factor of 2 each time we trim (moving the referrer closer
89 // to being discarded at a future Trim).
90 void TrimReferrers();
91
92 // Construct a ListValue object that contains all the data in the referrers_
93 // so that it can be persisted in a pref.
94 void SerializeReferrers(ListValue* referral_list);
95
96 // Process a ListValue that contains all the data from a previous reference
97 // list, as constructed by SerializeReferrers(), and add all the identified
98 // values into the current referrer list.
99 void DeserializeReferrers(const ListValue& referral_list);
100
[email protected]ec86bea2009-12-08 18:35:14101 void DeserializeReferrersThenDelete(ListValue* referral_list) {
102 DeserializeReferrers(*referral_list);
103 delete referral_list;
104 }
105
[email protected]e695fbd62009-06-30 16:31:54106 // For unit test code only.
107 size_t max_concurrent_lookups() const { return max_concurrent_lookups_; }
108
[email protected]b2b8b832009-02-06 19:03:29109 private:
[email protected]7991a232009-11-06 01:55:48110 friend class base::RefCountedThreadSafe<DnsMaster>;
[email protected]1933eb202009-02-19 18:23:25111 FRIEND_TEST(DnsMasterTest, BenefitLookupTest);
112 FRIEND_TEST(DnsMasterTest, ShutdownWhenResolutionIsPendingTest);
113 FRIEND_TEST(DnsMasterTest, SingleLookupTest);
114 FRIEND_TEST(DnsMasterTest, ConcurrentLookupTest);
[email protected]7d1e0d02009-07-29 21:51:41115 FRIEND_TEST(DnsMasterTest, MassiveConcurrentLookupTest);
[email protected]a20bc092009-06-05 01:34:20116 FRIEND_TEST(DnsMasterTest, PriorityQueuePushPopTest);
117 FRIEND_TEST(DnsMasterTest, PriorityQueueReorderTest);
[email protected]1933eb202009-02-19 18:23:25118 friend class WaitForResolutionHelper; // For testing.
119
[email protected]7991a232009-11-06 01:55:48120 ~DnsMaster();
121
[email protected]1933eb202009-02-19 18:23:25122 class LookupRequest;
123
[email protected]a20bc092009-06-05 01:34:20124 // A simple priority queue for handling host names.
125 // Some names that are queued up have |motivation| that requires very rapid
126 // handling. For example, a sub-resource name lookup MUST be done before the
127 // actual sub-resource is fetched. In contrast, a name that was speculatively
128 // noted in a page has to be resolved before the user "gets around to"
129 // clicking on a link. By tagging (with a motivation) each push we make into
130 // this FIFO queue, the queue can re-order the more important names to service
131 // them sooner (relative to some low priority background resolutions).
132 class HostNameQueue {
133 public:
134 HostNameQueue();
135 ~HostNameQueue();
136 void Push(const std::string& hostname,
137 DnsHostInfo::ResolutionMotivation motivation);
138 bool IsEmpty() const;
139 std::string Pop();
140
141 private:
142 // The names in the queue that should be serviced (popped) ASAP.
143 std::queue<std::string> rush_queue_;
144 // The names in the queue that should only be serviced when rush_queue is
145 // empty.
146 std::queue<std::string> background_queue_;
147
148 DISALLOW_COPY_AND_ASSIGN(HostNameQueue);
149 };
150
[email protected]b2b8b832009-02-06 19:03:29151 // A map that is keyed with the hostnames that we've learned were the cause
152 // of loading additional hostnames. The list of additional hostnames in held
153 // in a Referrer instance, which is found in this type.
154 typedef std::map<std::string, Referrer> Referrers;
[email protected]7c19b87b02009-01-26 16:19:44155
[email protected]1933eb202009-02-19 18:23:25156 // Only for testing. Returns true if hostname has been successfully resolved
157 // (name found).
158 bool WasFound(const std::string& hostname) {
[email protected]1933eb202009-02-19 18:23:25159 return (results_.find(hostname) != results_.end()) &&
160 results_[hostname].was_found();
161 }
162
163 // Only for testing. Return how long was the resolution
164 // or DnsHostInfo::kNullDuration if it hasn't been resolved yet.
165 base::TimeDelta GetResolutionDuration(const std::string& hostname) {
[email protected]1933eb202009-02-19 18:23:25166 if (results_.find(hostname) == results_.end())
167 return DnsHostInfo::kNullDuration;
168 return results_[hostname].resolve_duration();
169 }
170
171 // Only for testing;
172 size_t peak_pending_lookups() const { return peak_pending_lookups_; }
173
[email protected]85398532009-06-16 21:32:18174 // Access method for use by async lookup request to pass resolution result.
[email protected]1933eb202009-02-19 18:23:25175 void OnLookupFinished(LookupRequest* request,
176 const std::string& hostname, bool found);
177
[email protected]85398532009-06-16 21:32:18178 // Underlying method for both async and synchronous lookup to update state.
[email protected]ec86bea2009-12-08 18:35:14179 void LookupFinished(LookupRequest* request,
180 const std::string& hostname,
181 bool found);
[email protected]85398532009-06-16 21:32:18182
[email protected]21dae9b2008-11-06 23:32:53183 // Queue hostname for resolution. If queueing was done, return the pointer
184 // to the queued instance, otherwise return NULL.
[email protected]ec86bea2009-12-08 18:35:14185 DnsHostInfo* AppendToResolutionQueue(const std::string& hostname,
186 DnsHostInfo::ResolutionMotivation motivation);
initial.commit09911bf2008-07-26 23:55:29187
[email protected]a20bc092009-06-05 01:34:20188 // Check to see if too much queuing delay has been noted for the given info,
189 // which indicates that there is "congestion" or growing delay in handling the
190 // resolution of names. Rather than letting this congestion potentially grow
191 // without bounds, we abandon our queued efforts at pre-resolutions in such a
192 // case.
193 // To do this, we will recycle |info|, as well as all queued items, back to
194 // the state they had before they were queued up. We can't do anything about
195 // the resolutions we've already sent off for processing on another thread, so
196 // we just let them complete. On a slow system, subject to congestion, this
197 // will greatly reduce the number of resolutions done, but it will assure that
198 // any resolutions that are done, are in a timely and hence potentially
199 // helpful manner.
[email protected]ec86bea2009-12-08 18:35:14200 bool CongestionControlPerformed(DnsHostInfo* info);
[email protected]a20bc092009-06-05 01:34:20201
202 // Take lookup requests from work_queue_ and tell HostResolver to look them up
203 // asynchronously, provided we don't exceed concurrent resolution limit.
[email protected]ec86bea2009-12-08 18:35:14204 void StartSomeQueuedResolutions();
initial.commit09911bf2008-07-26 23:55:29205
[email protected]a20bc092009-06-05 01:34:20206 // work_queue_ holds a list of names we need to look up.
207 HostNameQueue work_queue_;
initial.commit09911bf2008-07-26 23:55:29208
[email protected]21dae9b2008-11-06 23:32:53209 // results_ contains information for existing/prior prefetches.
initial.commit09911bf2008-07-26 23:55:29210 Results results_;
211
[email protected]21dae9b2008-11-06 23:32:53212 // For each hostname that we might navigate to (that we've "learned about")
213 // we have a Referrer list. Each Referrer list has all hostnames we need to
214 // pre-resolve when there is a navigation to the orginial hostname.
215 Referrers referrers_;
216
[email protected]1933eb202009-02-19 18:23:25217 std::set<LookupRequest*> pending_lookups_;
initial.commit09911bf2008-07-26 23:55:29218
[email protected]1933eb202009-02-19 18:23:25219 // For testing, to verify that we don't exceed the limit.
220 size_t peak_pending_lookups_;
[email protected]b2b8b832009-02-06 19:03:29221
[email protected]1933eb202009-02-19 18:23:25222 // When true, we don't make new lookup requests.
[email protected]b2b8b832009-02-06 19:03:29223 bool shutdown_;
224
initial.commit09911bf2008-07-26 23:55:29225 // A list of successful events resulting from pre-fetching.
226 DnsHostInfo::DnsInfoTable cache_hits_;
227 // A map of hosts that were evicted from our cache (after we prefetched them)
228 // and before the HTTP stack tried to look them up.
229 Results cache_eviction_map_;
230
[email protected]e085c302009-06-01 18:31:36231 // The number of concurrent lookups currently allowed.
232 const size_t max_concurrent_lookups_;
233
[email protected]602faf3c2009-06-27 14:35:44234 // The maximum queueing delay that is acceptable before we enter congestion
235 // reduction mode, and discard all queued (but not yet assigned) resolutions.
236 const TimeDelta max_queue_delay_;
237
[email protected]ec86bea2009-12-08 18:35:14238 // The host resovler we warm DNS entries for.
[email protected]94a0d3d92009-06-27 01:50:14239 scoped_refptr<net::HostResolver> host_resolver_;
[email protected]fd2f8afe2009-06-11 21:53:55240
[email protected]e8013b32008-10-27 18:55:52241 DISALLOW_COPY_AND_ASSIGN(DnsMaster);
initial.commit09911bf2008-07-26 23:55:29242};
243
244} // namespace chrome_browser_net
245
[email protected]e8013b32008-10-27 18:55:52246#endif // CHROME_BROWSER_NET_DNS_MASTER_H_