Upstream changes for NetworkQualityProvider
[chromium-blink-merge.git] / net / url_request / url_request_backoff_manager.cc
blob51560e32981c90d13273e93db0476bb2901bde03
1 // Copyright 2015 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_backoff_manager.h"
7 #include "base/logging.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_piece.h"
10 #include "base/strings/string_util.h"
11 #include "net/http/http_response_headers.h"
13 namespace net {
15 const uint16 URLRequestBackoffManager::kMinimumBackoffInSeconds = 1;
16 const uint16 URLRequestBackoffManager::kMaximumBackoffInSeconds = 50000;
17 const uint16 URLRequestBackoffManager::kNewEntriesBetweenCollecting = 200;
19 URLRequestBackoffManager::URLRequestBackoffManager()
20 : new_entries_since_last_gc_(0) {
21 url_id_replacements_.ClearPassword();
22 url_id_replacements_.ClearUsername();
23 url_id_replacements_.ClearQuery();
24 url_id_replacements_.ClearRef();
26 NetworkChangeNotifier::AddIPAddressObserver(this);
27 NetworkChangeNotifier::AddConnectionTypeObserver(this);
30 URLRequestBackoffManager::~URLRequestBackoffManager() {
31 NetworkChangeNotifier::RemoveIPAddressObserver(this);
32 NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
33 for (UrlEntryMap::iterator it = url_entries_.begin();
34 it != url_entries_.end(); ++it) {
35 delete it->second;
37 url_entries_.clear();
40 void URLRequestBackoffManager::UpdateWithResponse(
41 const GURL& url,
42 HttpResponseHeaders* headers,
43 const base::Time& response_time) {
44 CalledOnValidThread();
45 base::TimeDelta result;
46 if (GetBackoffTime(headers, &result)) {
47 new_entries_since_last_gc_++;
48 std::string url_id = GetIdFromUrl(url);
49 url_entries_[url_id] =
50 new Entry(response_time + result, response_time + result * 1.1);
51 GarbageCollectEntriesIfNecessary();
55 bool URLRequestBackoffManager::ShouldRejectRequest(
56 const GURL& url,
57 const base::Time& request_time) {
58 CalledOnValidThread();
59 std::string url_id = GetIdFromUrl(url);
60 UrlEntryMap::iterator it = url_entries_.find(url_id);
61 if (it == url_entries_.end())
62 return false;
63 Entry* entry = it->second;
64 if (request_time < entry->throttled_time)
65 return true;
66 // Allow one request between throttled_time and release_time.
67 if (request_time >= entry->throttled_time &&
68 request_time < entry->release_time) {
69 if (entry->used)
70 return true;
71 entry->used = true;
73 return false;
76 void URLRequestBackoffManager::OnIPAddressChanged() {
77 OnNetworkChange();
80 void URLRequestBackoffManager::OnConnectionTypeChanged(
81 NetworkChangeNotifier::ConnectionType type) {
82 OnNetworkChange();
85 int URLRequestBackoffManager::GetNumberOfEntriesForTests() const {
86 return url_entries_.size();
89 void URLRequestBackoffManager::GarbageCollectEntriesIfNecessary() {
90 CalledOnValidThread();
91 if (new_entries_since_last_gc_ < kNewEntriesBetweenCollecting)
92 return;
94 new_entries_since_last_gc_ = 0;
95 UrlEntryMap::iterator it = url_entries_.begin();
96 while (it != url_entries_.end()) {
97 Entry* entry = it->second;
98 if (entry->IsOutDated()) {
99 url_entries_.erase(it++);
100 delete entry;
101 } else {
102 ++it;
107 bool URLRequestBackoffManager::GetBackoffTime(HttpResponseHeaders* headers,
108 base::TimeDelta* result) const {
109 base::StringPiece name("Backoff");
110 std::string value;
111 void* iter = NULL;
112 while (headers->EnumerateHeader(&iter, name, &value)) {
113 int64 seconds;
114 base::StringToInt64(value, &seconds);
115 if (seconds >= kMinimumBackoffInSeconds &&
116 seconds <= kMaximumBackoffInSeconds) {
117 *result = base::TimeDelta::FromSeconds(seconds);
118 return true;
121 return false;
124 std::string URLRequestBackoffManager::GetIdFromUrl(const GURL& url) const {
125 if (!url.is_valid())
126 return url.possibly_invalid_spec();
128 GURL id = url.ReplaceComponents(url_id_replacements_);
129 return base::StringToLowerASCII(id.spec()).c_str();
132 void URLRequestBackoffManager::OnNetworkChange() {
133 CalledOnValidThread();
135 new_entries_since_last_gc_ = 0;
136 // Remove all entries.
137 for (UrlEntryMap::iterator it = url_entries_.begin();
138 it != url_entries_.end(); ++it) {
139 delete it->second;
141 url_entries_.clear();
144 } // namespace net