diff options
Diffstat (limited to 'net/proxy')
-rw-r--r-- | net/proxy/proxy_info.cc | 10 | ||||
-rw-r--r-- | net/proxy/proxy_info.h | 10 | ||||
-rw-r--r-- | net/proxy/proxy_list.cc | 8 | ||||
-rw-r--r-- | net/proxy/proxy_list.h | 4 | ||||
-rw-r--r-- | net/proxy/proxy_service.cc | 52 | ||||
-rw-r--r-- | net/proxy/proxy_service.h | 5 | ||||
-rw-r--r-- | net/proxy/proxy_service_unittest.cc | 22 |
7 files changed, 103 insertions, 8 deletions
diff --git a/net/proxy/proxy_info.cc b/net/proxy/proxy_info.cc index ebefa84..85d6cae 100644 --- a/net/proxy/proxy_info.cc +++ b/net/proxy/proxy_info.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -16,26 +16,30 @@ ProxyInfo::~ProxyInfo() { void ProxyInfo::Use(const ProxyInfo& other) { proxy_list_ = other.proxy_list_; + proxy_retry_info_ = other.proxy_retry_info_; } void ProxyInfo::UseDirect() { proxy_list_.SetSingleProxyServer(ProxyServer::Direct()); + proxy_retry_info_.clear(); } void ProxyInfo::UseNamedProxy(const std::string& proxy_uri_list) { proxy_list_.Set(proxy_uri_list); + proxy_retry_info_.clear(); } void ProxyInfo::UseProxyServer(const ProxyServer& proxy_server) { proxy_list_.SetSingleProxyServer(proxy_server); + proxy_retry_info_.clear(); } std::string ProxyInfo::ToPacString() const { return proxy_list_.ToPacString(); } -bool ProxyInfo::Fallback(ProxyRetryInfoMap* proxy_retry_info) { - return proxy_list_.Fallback(proxy_retry_info); +bool ProxyInfo::Fallback(const BoundNetLog& net_log) { + return proxy_list_.Fallback(&proxy_retry_info_, net_log); } void ProxyInfo::DeprioritizeBadProxies( diff --git a/net/proxy/proxy_info.h b/net/proxy/proxy_info.h index f965e6b..2ff8136 100644 --- a/net/proxy/proxy_info.h +++ b/net/proxy/proxy_info.h @@ -9,6 +9,7 @@ #include <string> #include "net/base/net_export.h" +#include "net/base/net_log.h" #include "net/proxy/proxy_config.h" #include "net/proxy/proxy_list.h" #include "net/proxy/proxy_retry_info.h" @@ -86,7 +87,7 @@ class NET_EXPORT ProxyInfo { // Marks the current proxy as bad. Returns true if there is another proxy // available to try in proxy list_. - bool Fallback(ProxyRetryInfoMap* proxy_retry_info); + bool Fallback(const BoundNetLog& net_log); // De-prioritizes the proxies that we have cached as not working, by moving // them to the end of the proxy list. @@ -98,10 +99,17 @@ class NET_EXPORT ProxyInfo { private: friend class ProxyService; + const ProxyRetryInfoMap& proxy_retry_info() const { + return proxy_retry_info_; + } + // The ordered list of proxy servers (including DIRECT attempts) remaining to // try. If proxy_list_ is empty, then there is nothing left to fall back to. ProxyList proxy_list_; + // List of proxies that have been tried already. + ProxyRetryInfoMap proxy_retry_info_; + // This value identifies the proxy config used to initialize this object. ProxyConfig::ID config_id_; }; diff --git a/net/proxy/proxy_list.cc b/net/proxy/proxy_list.cc index 011aab9..cdc8cc2 100644 --- a/net/proxy/proxy_list.cc +++ b/net/proxy/proxy_list.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -115,7 +115,8 @@ std::string ProxyList::ToPacString() const { return proxy_list.empty() ? std::string() : proxy_list; } -bool ProxyList::Fallback(ProxyRetryInfoMap* proxy_retry_info) { +bool ProxyList::Fallback(ProxyRetryInfoMap* proxy_retry_info, + const BoundNetLog& net_log) { // Number of minutes to wait before retrying a bad proxy server. const TimeDelta kProxyRetryDelay = TimeDelta::FromMinutes(5); @@ -152,6 +153,9 @@ bool ProxyList::Fallback(ProxyRetryInfoMap* proxy_retry_info) { retry_info.bad_until = TimeTicks().Now() + retry_info.current_delay; (*proxy_retry_info)[key] = retry_info; } + net_log.AddEvent( + NetLog::TYPE_PROXY_LIST_FALLBACK, + make_scoped_refptr(new NetLogStringParameter("bad_proxy", key))); } // Remove this proxy from our list. diff --git a/net/proxy/proxy_list.h b/net/proxy/proxy_list.h index 707ceb6..a377553 100644 --- a/net/proxy/proxy_list.h +++ b/net/proxy/proxy_list.h @@ -10,6 +10,7 @@ #include <vector> #include "net/base/net_export.h" +#include "net/base/net_log.h" #include "net/proxy/proxy_retry_info.h" namespace net { @@ -61,7 +62,8 @@ class NET_EXPORT_PRIVATE ProxyList { // Marks the current proxy server as bad and deletes it from the list. The // list of known bad proxies is given by proxy_retry_info. Returns true if // there is another server available in the list. - bool Fallback(ProxyRetryInfoMap* proxy_retry_info); + bool Fallback(ProxyRetryInfoMap* proxy_retry_info, + const BoundNetLog& net_log); private: // List of proxies. diff --git a/net/proxy/proxy_service.cc b/net/proxy/proxy_service.cc index 66bf929..643b9be 100644 --- a/net/proxy/proxy_service.cc +++ b/net/proxy/proxy_service.cc @@ -264,6 +264,31 @@ class ProxyConfigChangedNetLogParam : public NetLog::EventParameters { DISALLOW_COPY_AND_ASSIGN(ProxyConfigChangedNetLogParam); }; +class BadProxyListNetLogParam : public NetLog::EventParameters { + public: + BadProxyListNetLogParam(const ProxyRetryInfoMap& retry_info) { + proxy_list_.reserve(retry_info.size()); + for (ProxyRetryInfoMap::const_iterator iter = retry_info.begin(); + iter != retry_info.end(); ++iter) { + proxy_list_.push_back(iter->first); + } + } + + virtual Value* ToValue() const OVERRIDE { + DictionaryValue* dict = new DictionaryValue(); + ListValue* list = new ListValue(); + for (std::vector<std::string>::const_iterator iter = proxy_list_.begin(); + iter != proxy_list_.end(); ++iter) + list->Append(Value::CreateStringValue(*iter)); + dict->Set("bad_proxy_list", list); + return dict; + } + + private: + std::vector<std::string> proxy_list_; + DISALLOW_COPY_AND_ASSIGN(BadProxyListNetLogParam); +}; + } // namespace // ProxyService::PacRequest --------------------------------------------------- @@ -715,13 +740,38 @@ int ProxyService::ReconsiderProxyAfterError(const GURL& url, // We don't have new proxy settings to try, try to fallback to the next proxy // in the list. - bool did_fallback = result->Fallback(&proxy_retry_info_); + bool did_fallback = result->Fallback(net_log); // Return synchronous failure if there is nothing left to fall-back to. // TODO(eroman): This is a yucky API, clean it up. return did_fallback ? OK : ERR_FAILED; } +void ProxyService::ReportSuccess(const ProxyInfo& result) { + DCHECK(CalledOnValidThread()); + + const ProxyRetryInfoMap& new_retry_info = result.proxy_retry_info(); + if (new_retry_info.empty()) + return; + + for (ProxyRetryInfoMap::const_iterator iter = new_retry_info.begin(); + iter != new_retry_info.end(); ++iter) { + ProxyRetryInfoMap::iterator existing = proxy_retry_info_.find(iter->first); + if (existing == proxy_retry_info_.end()) + proxy_retry_info_[iter->first] = iter->second; + else if (existing->second.bad_until < iter->second.bad_until) + existing->second.bad_until = iter->second.bad_until; + } + if (net_log_) { + net_log_->AddEntry(NetLog::TYPE_BAD_PROXY_LIST_REPORTED, + base::TimeTicks::Now(), + NetLog::Source(), + NetLog::PHASE_NONE, + make_scoped_refptr( + new BadProxyListNetLogParam(new_retry_info))); + } +} + void ProxyService::CancelPacRequest(PacRequest* req) { DCHECK(CalledOnValidThread()); DCHECK(req); diff --git a/net/proxy/proxy_service.h b/net/proxy/proxy_service.h index ad73b39..cc308dd 100644 --- a/net/proxy/proxy_service.h +++ b/net/proxy/proxy_service.h @@ -97,6 +97,11 @@ class NET_EXPORT ProxyService : public NetworkChangeNotifier::IPAddressObserver, PacRequest** pac_request, const BoundNetLog& net_log); + // Called to report that the last proxy connection succeeded. If |proxy_info| + // has a non empty proxy_retry_info map, the proxies that have been tried (and + // failed) for this request will be marked as bad. + void ReportSuccess(const ProxyInfo& proxy_info); + // Call this method with a non-null |pac_request| to cancel the PAC request. void CancelPacRequest(PacRequest* pac_request); diff --git a/net/proxy/proxy_service_unittest.cc b/net/proxy/proxy_service_unittest.cc index d41f48c..b2345d5 100644 --- a/net/proxy/proxy_service_unittest.cc +++ b/net/proxy/proxy_service_unittest.cc @@ -541,6 +541,9 @@ TEST(ProxyServiceTest, ProxyFallback) { // The second proxy should be specified. EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); + // Report back that the second proxy worked. This will globally mark the + // first proxy as bad. + service.ReportSuccess(info); TestCompletionCallback callback3; rv = service.ResolveProxy(url, &info, &callback3, NULL, BoundNetLog()); @@ -584,6 +587,25 @@ TEST(ProxyServiceTest, ProxyFallback) { EXPECT_FALSE(info.is_direct()); EXPECT_TRUE(info.is_empty()); + // Look up proxies again + TestCompletionCallback callback7; + rv = service.ResolveProxy(url, &info, &callback7, NULL, BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(url, resolver->pending_requests()[0]->url()); + + // This time, the first 3 results have been found to be bad, but only the + // first proxy has been confirmed ... + resolver->pending_requests()[0]->results()->UseNamedProxy( + "foopy1:8080;foopy3:7070;foopy2:9090;foopy4:9091"); + resolver->pending_requests()[0]->CompleteNow(OK); + + // ... therefore, we should see the second proxy first. + EXPECT_EQ(OK, callback7.WaitForResult()); + EXPECT_FALSE(info.is_direct()); + EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI()); + // TODO(nsylvain): Test that the proxy can be retried after the delay. } |