OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/url_request/url_request_throttler_manager.h" | 5 #include "net/url_request/url_request_throttler_manager.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/metrics/field_trial.h" | |
9 #include "base/metrics/histogram.h" | |
8 #include "base/string_util.h" | 10 #include "base/string_util.h" |
11 #include "net/base/net_log.h" | |
9 #include "net/base/net_util.h" | 12 #include "net/base/net_util.h" |
13 #include "net/base/network_change_notifier.h" | |
wtc
2011/05/25 23:12:06
Nit: This header is already included by url_reques
Jói
2011/05/26 14:53:42
Done.
| |
10 | 14 |
11 namespace net { | 15 namespace net { |
12 | 16 |
13 const unsigned int URLRequestThrottlerManager::kMaximumNumberOfEntries = 1500; | 17 const unsigned int URLRequestThrottlerManager::kMaximumNumberOfEntries = 1500; |
14 const unsigned int URLRequestThrottlerManager::kRequestsBetweenCollecting = 200; | 18 const unsigned int URLRequestThrottlerManager::kRequestsBetweenCollecting = 200; |
15 | 19 |
16 URLRequestThrottlerManager* URLRequestThrottlerManager::GetInstance() { | 20 URLRequestThrottlerManager* URLRequestThrottlerManager::GetInstance() { |
17 return Singleton<URLRequestThrottlerManager>::get(); | 21 return Singleton<URLRequestThrottlerManager>::get(); |
18 } | 22 } |
19 | 23 |
20 scoped_refptr<URLRequestThrottlerEntryInterface> | 24 scoped_refptr<URLRequestThrottlerEntryInterface> |
21 URLRequestThrottlerManager::RegisterRequestUrl(const GURL &url) { | 25 URLRequestThrottlerManager::RegisterRequestUrl(const GURL &url) { |
22 DCHECK(!enable_thread_checks_ || CalledOnValidThread()); | 26 DCHECK(!enable_thread_checks_ || CalledOnValidThread()); |
23 | 27 |
24 // Normalize the url. | 28 // Normalize the url. |
25 std::string url_id = GetIdFromUrl(url); | 29 std::string url_id = GetIdFromUrl(url); |
26 | 30 |
27 // Periodically garbage collect old entries. | 31 // Periodically garbage collect old entries. |
28 GarbageCollectEntriesIfNecessary(); | 32 GarbageCollectEntriesIfNecessary(); |
29 | 33 |
30 // Find the entry in the map or create it. | 34 // Find the entry in the map or create a new NULL entry. |
31 scoped_refptr<URLRequestThrottlerEntry>& entry = url_entries_[url_id]; | 35 scoped_refptr<URLRequestThrottlerEntry>& entry = url_entries_[url_id]; |
36 | |
37 // If the entry exists but could be garbage collected at this point, we | |
38 // start with a fresh entry so that we possibly back off a bit less | |
39 // aggressively (i.e. this resets the error count when the entry's URL | |
40 // hasn't been requested in long enough). | |
41 if (entry.get() && entry->IsEntryOutdated()) { | |
42 entry = NULL; | |
43 } | |
44 | |
45 // Create the entry if needed. | |
32 if (entry.get() == NULL) { | 46 if (entry.get() == NULL) { |
33 entry = new URLRequestThrottlerEntry(this); | 47 entry = new URLRequestThrottlerEntry(this, url_id); |
34 | 48 |
35 // We only disable back-off throttling on an entry that we have | 49 // We only disable back-off throttling on an entry that we have |
36 // just constructed. This is to allow unit tests to explicitly override | 50 // just constructed. This is to allow unit tests to explicitly override |
37 // the entry for localhost URLs. Given that we do not attempt to | 51 // the entry for localhost URLs. Given that we do not attempt to |
38 // disable throttling for entries already handed out (see comment | 52 // disable throttling for entries already handed out (see comment |
39 // in AddToOptOutList), this is not a problem. | 53 // in AddToOptOutList), this is not a problem. |
40 std::string host = url.host(); | 54 std::string host = url.host(); |
41 if (opt_out_hosts_.find(host) != opt_out_hosts_.end() || | 55 if (opt_out_hosts_.find(host) != opt_out_hosts_.end() || |
42 IsLocalhost(host)) { | 56 IsLocalhost(host)) { |
57 if (!logged_for_localhost_disabled_ && IsLocalhost(host)) { | |
58 logged_for_localhost_disabled_ = true; | |
59 net_log_->AddEvent( | |
60 NetLog::TYPE_THROTTLING_DISABLED_FOR_HOST, | |
61 make_scoped_refptr(new NetLogStringParameter("host", host))); | |
62 } | |
63 | |
43 // TODO(joi): Once sliding window is separate from back-off throttling, | 64 // TODO(joi): Once sliding window is separate from back-off throttling, |
44 // we can simply return a dummy implementation of | 65 // we can simply return a dummy implementation of |
45 // URLRequestThrottlerEntryInterface here that never blocks anything (and | 66 // URLRequestThrottlerEntryInterface here that never blocks anything (and |
46 // not keep entries in url_entries_ for opted-out sites). | 67 // not keep entries in url_entries_ for opted-out sites). |
47 entry->DisableBackoffThrottling(); | 68 entry->DisableBackoffThrottling(); |
48 } | 69 } |
49 } | 70 } |
50 | 71 |
51 return entry; | 72 return entry; |
52 } | 73 } |
53 | 74 |
54 void URLRequestThrottlerManager::AddToOptOutList(const std::string& host) { | 75 void URLRequestThrottlerManager::AddToOptOutList(const std::string& host) { |
55 // There is an edge case here that we are not handling, to keep things | 76 // There is an edge case here that we are not handling, to keep things |
56 // simple. If a host starts adding the opt-out header to its responses | 77 // simple. If a host starts adding the opt-out header to its responses |
57 // after there are already one or more entries in url_entries_ for that | 78 // after there are already one or more entries in url_entries_ for that |
58 // host, the pre-existing entries may still perform back-off throttling. | 79 // host, the pre-existing entries may still perform back-off throttling. |
59 // In practice, this would almost never occur. | 80 // In practice, this would almost never occur. |
60 opt_out_hosts_.insert(host); | 81 if (opt_out_hosts_.find(host) == opt_out_hosts_.end()) { |
82 UMA_HISTOGRAM_COUNTS("Throttling.SiteOptedOut", 1); | |
83 if (base::FieldTrialList::TrialExists("ThrottlingEnabled")) { | |
84 UMA_HISTOGRAM_COUNTS(base::FieldTrial::MakeName( | |
85 "Throttling.SiteOptedOut", "ThrottlingEnabled"), 1); | |
86 } | |
87 | |
88 net_log_->EndEvent( | |
89 NetLog::TYPE_THROTTLING_DISABLED_FOR_HOST, | |
90 make_scoped_refptr(new NetLogStringParameter("host", host))); | |
91 opt_out_hosts_.insert(host); | |
92 } | |
61 } | 93 } |
62 | 94 |
63 void URLRequestThrottlerManager::OverrideEntryForTests( | 95 void URLRequestThrottlerManager::OverrideEntryForTests( |
64 const GURL& url, | 96 const GURL& url, |
65 URLRequestThrottlerEntry* entry) { | 97 URLRequestThrottlerEntry* entry) { |
66 // Normalize the url. | 98 // Normalize the url. |
67 std::string url_id = GetIdFromUrl(url); | 99 std::string url_id = GetIdFromUrl(url); |
68 | 100 |
69 // Periodically garbage collect old entries. | 101 // Periodically garbage collect old entries. |
70 GarbageCollectEntriesIfNecessary(); | 102 GarbageCollectEntriesIfNecessary(); |
(...skipping 16 matching lines...) Expand all Loading... | |
87 } | 119 } |
88 | 120 |
89 void URLRequestThrottlerManager::set_enforce_throttling(bool enforce) { | 121 void URLRequestThrottlerManager::set_enforce_throttling(bool enforce) { |
90 enforce_throttling_ = enforce; | 122 enforce_throttling_ = enforce; |
91 } | 123 } |
92 | 124 |
93 bool URLRequestThrottlerManager::enforce_throttling() { | 125 bool URLRequestThrottlerManager::enforce_throttling() { |
94 return enforce_throttling_; | 126 return enforce_throttling_; |
95 } | 127 } |
96 | 128 |
129 void URLRequestThrottlerManager::set_net_log(NetLog* net_log) { | |
130 DCHECK(net_log); | |
131 NetLog::Source source(NetLog::SOURCE_EXPONENTIAL_BACKOFF_THROTTLING, | |
132 net_log->NextID()); | |
133 net_log_.reset(new BoundNetLog(source, net_log)); | |
134 } | |
135 | |
136 NetLog* URLRequestThrottlerManager::net_log() const { | |
137 return net_log_->net_log(); | |
138 } | |
139 | |
140 void URLRequestThrottlerManager::OnIPAddressChanged() { | |
141 OnNetworkChange(); | |
142 } | |
143 | |
144 void URLRequestThrottlerManager::OnOnlineStateChanged(bool online) { | |
145 OnNetworkChange(); | |
146 } | |
147 | |
97 // TODO(joi): Turn throttling on by default when appropriate. | 148 // TODO(joi): Turn throttling on by default when appropriate. |
98 URLRequestThrottlerManager::URLRequestThrottlerManager() | 149 URLRequestThrottlerManager::URLRequestThrottlerManager() |
99 : requests_since_last_gc_(0), | 150 : requests_since_last_gc_(0), |
100 enforce_throttling_(false), | 151 enforce_throttling_(false), |
101 enable_thread_checks_(false) { | 152 enable_thread_checks_(false), |
153 logged_for_localhost_disabled_(false) { | |
102 // Construction/destruction is on main thread (because BrowserMain | 154 // Construction/destruction is on main thread (because BrowserMain |
103 // retrieves an instance to call InitializeOptions), but is from then on | 155 // retrieves an instance to call InitializeOptions), but is from then on |
104 // used on I/O thread. | 156 // used on I/O thread. |
105 DetachFromThread(); | 157 DetachFromThread(); |
106 | 158 |
107 url_id_replacements_.ClearPassword(); | 159 url_id_replacements_.ClearPassword(); |
108 url_id_replacements_.ClearUsername(); | 160 url_id_replacements_.ClearUsername(); |
109 url_id_replacements_.ClearQuery(); | 161 url_id_replacements_.ClearQuery(); |
110 url_id_replacements_.ClearRef(); | 162 url_id_replacements_.ClearRef(); |
163 | |
164 // Make sure there is always a net_log_ instance, even if it logs to | |
165 // nowhere. | |
166 net_log_.reset(new BoundNetLog()); | |
167 | |
168 NetworkChangeNotifier::AddIPAddressObserver(this); | |
169 NetworkChangeNotifier::AddOnlineStateObserver(this); | |
111 } | 170 } |
112 | 171 |
113 URLRequestThrottlerManager::~URLRequestThrottlerManager() { | 172 URLRequestThrottlerManager::~URLRequestThrottlerManager() { |
114 // Destruction is on main thread (AtExit), but real use is on I/O thread. | 173 // Destruction is on main thread (AtExit), but real use is on I/O thread. |
115 DetachFromThread(); | 174 DetachFromThread(); |
116 | 175 |
176 NetworkChangeNotifier::RemoveIPAddressObserver(this); | |
177 NetworkChangeNotifier::RemoveOnlineStateObserver(this); | |
178 | |
117 // Since, for now, the manager object might conceivably go away before | 179 // Since, for now, the manager object might conceivably go away before |
118 // the entries, detach the entries' back-pointer to the manager. | 180 // the entries, detach the entries' back-pointer to the manager. |
119 // | 181 // |
120 // TODO(joi): Revisit whether to make entries non-refcounted. | 182 // TODO(joi): Revisit whether to make entries non-refcounted. |
121 UrlEntryMap::iterator i = url_entries_.begin(); | 183 UrlEntryMap::iterator i = url_entries_.begin(); |
122 while (i != url_entries_.end()) { | 184 while (i != url_entries_.end()) { |
123 if (i->second != NULL) { | 185 if (i->second != NULL) { |
124 i->second->DetachManager(); | 186 i->second->DetachManager(); |
125 } | 187 } |
126 ++i; | 188 ++i; |
(...skipping 29 matching lines...) Expand all Loading... | |
156 ++i; | 218 ++i; |
157 } | 219 } |
158 } | 220 } |
159 | 221 |
160 // In case something broke we want to make sure not to grow indefinitely. | 222 // In case something broke we want to make sure not to grow indefinitely. |
161 while (url_entries_.size() > kMaximumNumberOfEntries) { | 223 while (url_entries_.size() > kMaximumNumberOfEntries) { |
162 url_entries_.erase(url_entries_.begin()); | 224 url_entries_.erase(url_entries_.begin()); |
163 } | 225 } |
164 } | 226 } |
165 | 227 |
228 void URLRequestThrottlerManager::OnNetworkChange() { | |
229 // Remove all entries. Any entries that in-flight requests have a reference | |
230 // to will live until those requests end, and these entries may be | |
231 // inconsistent with new entries for the same URLs, but since what we | |
232 // want is a clean slate for the new connection state, this is OK. | |
233 url_entries_.clear(); | |
234 requests_since_last_gc_ = 0; | |
235 } | |
236 | |
166 } // namespace net | 237 } // namespace net |
OLD | NEW |