| Index: net/url_request/url_request_backoff_manager.cc
|
| diff --git a/net/url_request/url_request_backoff_manager.cc b/net/url_request/url_request_backoff_manager.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..51560e32981c90d13273e93db0476bb2901bde03
|
| --- /dev/null
|
| +++ b/net/url_request/url_request_backoff_manager.cc
|
| @@ -0,0 +1,144 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "net/url_request/url_request_backoff_manager.h"
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/strings/string_number_conversions.h"
|
| +#include "base/strings/string_piece.h"
|
| +#include "base/strings/string_util.h"
|
| +#include "net/http/http_response_headers.h"
|
| +
|
| +namespace net {
|
| +
|
| +const uint16 URLRequestBackoffManager::kMinimumBackoffInSeconds = 1;
|
| +const uint16 URLRequestBackoffManager::kMaximumBackoffInSeconds = 50000;
|
| +const uint16 URLRequestBackoffManager::kNewEntriesBetweenCollecting = 200;
|
| +
|
| +URLRequestBackoffManager::URLRequestBackoffManager()
|
| + : new_entries_since_last_gc_(0) {
|
| + url_id_replacements_.ClearPassword();
|
| + url_id_replacements_.ClearUsername();
|
| + url_id_replacements_.ClearQuery();
|
| + url_id_replacements_.ClearRef();
|
| +
|
| + NetworkChangeNotifier::AddIPAddressObserver(this);
|
| + NetworkChangeNotifier::AddConnectionTypeObserver(this);
|
| +}
|
| +
|
| +URLRequestBackoffManager::~URLRequestBackoffManager() {
|
| + NetworkChangeNotifier::RemoveIPAddressObserver(this);
|
| + NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
|
| + for (UrlEntryMap::iterator it = url_entries_.begin();
|
| + it != url_entries_.end(); ++it) {
|
| + delete it->second;
|
| + }
|
| + url_entries_.clear();
|
| +}
|
| +
|
| +void URLRequestBackoffManager::UpdateWithResponse(
|
| + const GURL& url,
|
| + HttpResponseHeaders* headers,
|
| + const base::Time& response_time) {
|
| + CalledOnValidThread();
|
| + base::TimeDelta result;
|
| + if (GetBackoffTime(headers, &result)) {
|
| + new_entries_since_last_gc_++;
|
| + std::string url_id = GetIdFromUrl(url);
|
| + url_entries_[url_id] =
|
| + new Entry(response_time + result, response_time + result * 1.1);
|
| + GarbageCollectEntriesIfNecessary();
|
| + }
|
| +}
|
| +
|
| +bool URLRequestBackoffManager::ShouldRejectRequest(
|
| + const GURL& url,
|
| + const base::Time& request_time) {
|
| + CalledOnValidThread();
|
| + std::string url_id = GetIdFromUrl(url);
|
| + UrlEntryMap::iterator it = url_entries_.find(url_id);
|
| + if (it == url_entries_.end())
|
| + return false;
|
| + Entry* entry = it->second;
|
| + if (request_time < entry->throttled_time)
|
| + return true;
|
| + // Allow one request between throttled_time and release_time.
|
| + if (request_time >= entry->throttled_time &&
|
| + request_time < entry->release_time) {
|
| + if (entry->used)
|
| + return true;
|
| + entry->used = true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +void URLRequestBackoffManager::OnIPAddressChanged() {
|
| + OnNetworkChange();
|
| +}
|
| +
|
| +void URLRequestBackoffManager::OnConnectionTypeChanged(
|
| + NetworkChangeNotifier::ConnectionType type) {
|
| + OnNetworkChange();
|
| +}
|
| +
|
| +int URLRequestBackoffManager::GetNumberOfEntriesForTests() const {
|
| + return url_entries_.size();
|
| +}
|
| +
|
| +void URLRequestBackoffManager::GarbageCollectEntriesIfNecessary() {
|
| + CalledOnValidThread();
|
| + if (new_entries_since_last_gc_ < kNewEntriesBetweenCollecting)
|
| + return;
|
| +
|
| + new_entries_since_last_gc_ = 0;
|
| + UrlEntryMap::iterator it = url_entries_.begin();
|
| + while (it != url_entries_.end()) {
|
| + Entry* entry = it->second;
|
| + if (entry->IsOutDated()) {
|
| + url_entries_.erase(it++);
|
| + delete entry;
|
| + } else {
|
| + ++it;
|
| + }
|
| + }
|
| +}
|
| +
|
| +bool URLRequestBackoffManager::GetBackoffTime(HttpResponseHeaders* headers,
|
| + base::TimeDelta* result) const {
|
| + base::StringPiece name("Backoff");
|
| + std::string value;
|
| + void* iter = NULL;
|
| + while (headers->EnumerateHeader(&iter, name, &value)) {
|
| + int64 seconds;
|
| + base::StringToInt64(value, &seconds);
|
| + if (seconds >= kMinimumBackoffInSeconds &&
|
| + seconds <= kMaximumBackoffInSeconds) {
|
| + *result = base::TimeDelta::FromSeconds(seconds);
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +std::string URLRequestBackoffManager::GetIdFromUrl(const GURL& url) const {
|
| + if (!url.is_valid())
|
| + return url.possibly_invalid_spec();
|
| +
|
| + GURL id = url.ReplaceComponents(url_id_replacements_);
|
| + return base::StringToLowerASCII(id.spec()).c_str();
|
| +}
|
| +
|
| +void URLRequestBackoffManager::OnNetworkChange() {
|
| + CalledOnValidThread();
|
| +
|
| + new_entries_since_last_gc_ = 0;
|
| + // Remove all entries.
|
| + for (UrlEntryMap::iterator it = url_entries_.begin();
|
| + it != url_entries_.end(); ++it) {
|
| + delete it->second;
|
| + }
|
| + url_entries_.clear();
|
| +}
|
| +
|
| +} // namespace net
|
|
|