ChildAccountService: get service flags from AccountTrackerService instead of fetching...
[chromium-blink-merge.git] / net / url_request / url_request_throttler_manager.cc
blob6bf3f5440441436b64fd831d2b431f94764aefed
1 // Copyright (c) 2012 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.
5 #include "net/url_request/url_request_throttler_manager.h"
7 #include "base/logging.h"
8 #include "base/metrics/field_trial.h"
9 #include "base/metrics/histogram.h"
10 #include "base/strings/string_util.h"
11 #include "net/base/net_util.h"
12 #include "net/log/net_log.h"
14 namespace net {
16 const unsigned int URLRequestThrottlerManager::kMaximumNumberOfEntries = 1500;
17 const unsigned int URLRequestThrottlerManager::kRequestsBetweenCollecting = 200;
19 URLRequestThrottlerManager::URLRequestThrottlerManager()
20 : requests_since_last_gc_(0),
21 enable_thread_checks_(false),
22 logged_for_localhost_disabled_(false),
23 registered_from_thread_(base::kInvalidThreadId) {
24 url_id_replacements_.ClearPassword();
25 url_id_replacements_.ClearUsername();
26 url_id_replacements_.ClearQuery();
27 url_id_replacements_.ClearRef();
29 NetworkChangeNotifier::AddIPAddressObserver(this);
30 NetworkChangeNotifier::AddConnectionTypeObserver(this);
33 URLRequestThrottlerManager::~URLRequestThrottlerManager() {
34 NetworkChangeNotifier::RemoveIPAddressObserver(this);
35 NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
37 // Since the manager object might conceivably go away before the
38 // entries, detach the entries' back-pointer to the manager.
39 UrlEntryMap::iterator i = url_entries_.begin();
40 while (i != url_entries_.end()) {
41 if (i->second.get() != NULL) {
42 i->second->DetachManager();
44 ++i;
47 // Delete all entries.
48 url_entries_.clear();
51 scoped_refptr<URLRequestThrottlerEntryInterface>
52 URLRequestThrottlerManager::RegisterRequestUrl(const GURL &url) {
53 DCHECK(!enable_thread_checks_ || CalledOnValidThread());
55 // Normalize the url.
56 std::string url_id = GetIdFromUrl(url);
58 // Periodically garbage collect old entries.
59 GarbageCollectEntriesIfNecessary();
61 // Find the entry in the map or create a new NULL entry.
62 scoped_refptr<URLRequestThrottlerEntry>& entry = url_entries_[url_id];
64 // If the entry exists but could be garbage collected at this point, we
65 // start with a fresh entry so that we possibly back off a bit less
66 // aggressively (i.e. this resets the error count when the entry's URL
67 // hasn't been requested in long enough).
68 if (entry.get() && entry->IsEntryOutdated()) {
69 entry = NULL;
72 // Create the entry if needed.
73 if (entry.get() == NULL) {
74 entry = new URLRequestThrottlerEntry(this, url_id);
76 // We only disable back-off throttling on an entry that we have
77 // just constructed. This is to allow unit tests to explicitly override
78 // the entry for localhost URLs.
79 std::string host = url.host();
80 if (IsLocalhost(host)) {
81 if (!logged_for_localhost_disabled_ && IsLocalhost(host)) {
82 logged_for_localhost_disabled_ = true;
83 net_log_.AddEvent(NetLog::TYPE_THROTTLING_DISABLED_FOR_HOST,
84 NetLog::StringCallback("host", &host));
87 // TODO(joi): Once sliding window is separate from back-off throttling,
88 // we can simply return a dummy implementation of
89 // URLRequestThrottlerEntryInterface here that never blocks anything.
90 entry->DisableBackoffThrottling();
94 return entry;
97 void URLRequestThrottlerManager::OverrideEntryForTests(
98 const GURL& url,
99 URLRequestThrottlerEntry* entry) {
100 // Normalize the url.
101 std::string url_id = GetIdFromUrl(url);
103 // Periodically garbage collect old entries.
104 GarbageCollectEntriesIfNecessary();
106 url_entries_[url_id] = entry;
109 void URLRequestThrottlerManager::EraseEntryForTests(const GURL& url) {
110 // Normalize the url.
111 std::string url_id = GetIdFromUrl(url);
112 url_entries_.erase(url_id);
115 void URLRequestThrottlerManager::set_enable_thread_checks(bool enable) {
116 enable_thread_checks_ = enable;
119 bool URLRequestThrottlerManager::enable_thread_checks() const {
120 return enable_thread_checks_;
123 void URLRequestThrottlerManager::set_net_log(NetLog* net_log) {
124 DCHECK(net_log);
125 net_log_ = BoundNetLog::Make(net_log,
126 NetLog::SOURCE_EXPONENTIAL_BACKOFF_THROTTLING);
129 NetLog* URLRequestThrottlerManager::net_log() const {
130 return net_log_.net_log();
133 void URLRequestThrottlerManager::OnIPAddressChanged() {
134 OnNetworkChange();
137 void URLRequestThrottlerManager::OnConnectionTypeChanged(
138 NetworkChangeNotifier::ConnectionType type) {
139 OnNetworkChange();
142 std::string URLRequestThrottlerManager::GetIdFromUrl(const GURL& url) const {
143 if (!url.is_valid())
144 return url.possibly_invalid_spec();
146 GURL id = url.ReplaceComponents(url_id_replacements_);
147 return base::StringToLowerASCII(id.spec()).c_str();
150 void URLRequestThrottlerManager::GarbageCollectEntriesIfNecessary() {
151 requests_since_last_gc_++;
152 if (requests_since_last_gc_ < kRequestsBetweenCollecting)
153 return;
154 requests_since_last_gc_ = 0;
156 GarbageCollectEntries();
159 void URLRequestThrottlerManager::GarbageCollectEntries() {
160 UrlEntryMap::iterator i = url_entries_.begin();
161 while (i != url_entries_.end()) {
162 if ((i->second)->IsEntryOutdated()) {
163 url_entries_.erase(i++);
164 } else {
165 ++i;
169 // In case something broke we want to make sure not to grow indefinitely.
170 while (url_entries_.size() > kMaximumNumberOfEntries) {
171 url_entries_.erase(url_entries_.begin());
175 void URLRequestThrottlerManager::OnNetworkChange() {
176 // Remove all entries. Any entries that in-flight requests have a reference
177 // to will live until those requests end, and these entries may be
178 // inconsistent with new entries for the same URLs, but since what we
179 // want is a clean slate for the new connection type, this is OK.
180 url_entries_.clear();
181 requests_since_last_gc_ = 0;
184 } // namespace net