diff options
author | bengr@chromium.org <bengr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-10 01:21:39 +0000 |
---|---|---|
committer | bengr@chromium.org <bengr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-10 01:23:02 +0000 |
commit | f09f968f9f0ba892cadca8574a382c41d4a979f9 (patch) | |
tree | 83ad7bc619bf6128199068d6b87776e58a6bfcef | |
parent | 7a6ecef5cd867b2232c7ab9a0f00310ddd271160 (diff) | |
download | chromium_src-f09f968f9f0ba892cadca8574a382c41d4a979f9.zip chromium_src-f09f968f9f0ba892cadca8574a382c41d4a979f9.tar.gz chromium_src-f09f968f9f0ba892cadca8574a382c41d4a979f9.tar.bz2 |
Removed data compression UMA from ProxyService
This change removes logic specific to the data reduction proxy
from net::ProxyService and net::ProxyServer. To do so, it introduces
a new method, net::NetworkDelegate::OnProxyFallback.
BUG=396699
Review URL: https://codereview.chromium.org/425163004
Cr-Commit-Position: refs/heads/master@{#288603}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@288603 0039d316-1c4b-4281-b951-d872f2087c98
21 files changed, 490 insertions, 308 deletions
diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc index 74ecef7..3d0f1b6 100644 --- a/chrome/browser/net/chrome_network_delegate.cc +++ b/chrome/browser/net/chrome_network_delegate.cc @@ -434,6 +434,15 @@ void ChromeNetworkDelegate::OnResolveProxy( } } +void ChromeNetworkDelegate::OnProxyFallback(const net::ProxyServer& bad_proxy, + int net_error, + bool did_fallback) { + if (data_reduction_proxy_usage_stats_) { + data_reduction_proxy_usage_stats_->RecordBypassEventHistograms( + bad_proxy, net_error, did_fallback); + } +} + int ChromeNetworkDelegate::OnBeforeSendHeaders( net::URLRequest* request, const net::CompletionCallback& callback, @@ -469,7 +478,7 @@ int ChromeNetworkDelegate::OnHeadersReceived( const net::HttpResponseHeaders* original_response_headers, scoped_refptr<net::HttpResponseHeaders>* override_response_headers, GURL* allowed_unsafe_redirect_url) { - net::ProxyService::DataReductionProxyBypassType bypass_type; + data_reduction_proxy::DataReductionProxyBypassType bypass_type; if (data_reduction_proxy::MaybeBypassProxyAndPrepareToRetry( data_reduction_proxy_params_, request, diff --git a/chrome/browser/net/chrome_network_delegate.h b/chrome/browser/net/chrome_network_delegate.h index b49d4ab..f7c03dc 100644 --- a/chrome/browser/net/chrome_network_delegate.h +++ b/chrome/browser/net/chrome_network_delegate.h @@ -51,6 +51,7 @@ class InfoMap; namespace net { class ProxyInfo; +class ProxyServer; class URLRequest; } @@ -198,6 +199,9 @@ class ChromeNetworkDelegate : public net::NetworkDelegate { GURL* new_url) OVERRIDE; virtual void OnResolveProxy( const GURL& url, int load_flags, net::ProxyInfo* result) OVERRIDE; + virtual void OnProxyFallback(const net::ProxyServer& bad_proxy, + int net_error, + bool did_fallback) OVERRIDE; virtual int OnBeforeSendHeaders(net::URLRequest* request, const net::CompletionCallback& callback, net::HttpRequestHeaders* headers) OVERRIDE; diff --git a/components/data_reduction_proxy/browser/data_reduction_proxy_params.cc b/components/data_reduction_proxy/browser/data_reduction_proxy_params.cc index 9296a20..1074783 100644 --- a/components/data_reduction_proxy/browser/data_reduction_proxy_params.cc +++ b/components/data_reduction_proxy/browser/data_reduction_proxy_params.cc @@ -4,6 +4,8 @@ #include "components/data_reduction_proxy/browser/data_reduction_proxy_params.h" +#include <vector> + #include "base/command_line.h" #include "base/memory/scoped_ptr.h" #include "base/metrics/field_trial.h" @@ -58,6 +60,16 @@ bool DataReductionProxyParams::IsIncludedInCriticalPathBypassFieldTrial() { "DataCompressionProxyCriticalBypass") == kEnabled; } +DataReductionProxyTypeInfo::DataReductionProxyTypeInfo() + : proxy_servers(), + is_fallback(false), + is_alternative(false), + is_ssl(false) { +} + +DataReductionProxyTypeInfo::~DataReductionProxyTypeInfo(){ +} + bool DataReductionProxyParams::IsIncludedInHoldbackFieldTrial() { return FieldTrialList::FindFullName( "DataCompressionProxyHoldback") == kEnabled; @@ -264,19 +276,19 @@ void DataReductionProxyParams::InitWithoutChecks() { bool DataReductionProxyParams::WasDataReductionProxyUsed( const net::URLRequest* request, - std::pair<GURL, GURL>* proxy_servers) const { + DataReductionProxyTypeInfo* proxy_info) const { DCHECK(request); - return IsDataReductionProxy(request->proxy_server(), proxy_servers); + return IsDataReductionProxy(request->proxy_server(), proxy_info); } bool DataReductionProxyParams::IsDataReductionProxy( const net::HostPortPair& host_port_pair, - std::pair<GURL, GURL>* proxy_servers) const { + DataReductionProxyTypeInfo* proxy_info) const { if (net::HostPortPair::FromURL(origin()).Equals(host_port_pair)) { - if (proxy_servers) { - (*proxy_servers).first = origin(); + if (proxy_info) { + proxy_info->proxy_servers.first = origin(); if (fallback_allowed()) - (*proxy_servers).second = fallback_origin(); + proxy_info->proxy_servers.second = fallback_origin(); } return true; } @@ -288,10 +300,10 @@ bool DataReductionProxyParams::IsDataReductionProxy( if (GURL(GetDefaultDevOrigin()) == origin()) { const GURL& default_origin = GURL(GetDefaultOrigin()); if (net::HostPortPair::FromURL(default_origin).Equals(host_port_pair)) { - if (proxy_servers) { - (*proxy_servers).first = default_origin; + if (proxy_info) { + proxy_info->proxy_servers.first = default_origin; if (fallback_allowed()) - (*proxy_servers).second = fallback_origin(); + proxy_info->proxy_servers.second = fallback_origin(); } return true; } @@ -299,33 +311,38 @@ bool DataReductionProxyParams::IsDataReductionProxy( if (fallback_allowed() && net::HostPortPair::FromURL(fallback_origin()).Equals(host_port_pair)) { - if (proxy_servers) { - (*proxy_servers).first = fallback_origin(); - (*proxy_servers).second = GURL(); + if (proxy_info) { + proxy_info->proxy_servers.first = fallback_origin(); + proxy_info->proxy_servers.second = GURL(); + proxy_info->is_fallback = true; } return true; } if (net::HostPortPair::FromURL(alt_origin()).Equals(host_port_pair)) { - if (proxy_servers) { - (*proxy_servers).first = alt_origin(); + if (proxy_info) { + proxy_info->proxy_servers.first = alt_origin(); + proxy_info->is_alternative = true; if (fallback_allowed()) - (*proxy_servers).second = alt_fallback_origin(); + proxy_info->proxy_servers.second = alt_fallback_origin(); } return true; } if (fallback_allowed() && net::HostPortPair::FromURL(alt_fallback_origin()).Equals( host_port_pair)) { - if (proxy_servers) { - (*proxy_servers).first = alt_fallback_origin(); - (*proxy_servers).second = GURL(); + if (proxy_info) { + proxy_info->proxy_servers.first = alt_fallback_origin(); + proxy_info->proxy_servers.second = GURL(); + proxy_info->is_fallback = true; + proxy_info->is_alternative = true; } return true; } if (net::HostPortPair::FromURL(ssl_origin()).Equals(host_port_pair)) { - if (proxy_servers) { - (*proxy_servers).first = ssl_origin(); - (*proxy_servers).second = GURL(); + if (proxy_info) { + proxy_info->proxy_servers.first = ssl_origin(); + proxy_info->proxy_servers.second = GURL(); + proxy_info->is_ssl = true; } return true; } diff --git a/components/data_reduction_proxy/browser/data_reduction_proxy_params.h b/components/data_reduction_proxy/browser/data_reduction_proxy_params.h index 78a63a4..6517845 100644 --- a/components/data_reduction_proxy/browser/data_reduction_proxy_params.h +++ b/components/data_reduction_proxy/browser/data_reduction_proxy_params.h @@ -23,6 +23,20 @@ class URLRequest; } namespace data_reduction_proxy { + +// Contains information about a given proxy server. |proxy_servers| contains +// the configured data reduction proxy servers. |is_fallback|, |is_alternative| +// and |is_ssl| note whether the given proxy is a fallback, an alternative, +// or a proxy for ssl; these are not mutually exclusive. +struct DataReductionProxyTypeInfo { + DataReductionProxyTypeInfo(); + ~DataReductionProxyTypeInfo(); + std::pair<GURL, GURL> proxy_servers; + bool is_fallback; + bool is_alternative; + bool is_ssl; +}; + // Provides initialization parameters. Proxy origins, and the probe url are // are taken from flags if available and from preprocessor constants otherwise. // The DataReductionProxySettings class and others use this class to determine @@ -88,23 +102,28 @@ class DataReductionProxyParams { virtual ~DataReductionProxyParams(); // Returns true if a data reduction proxy was used for the given |request|. - // If true, |proxy_servers.first| will contain the name of the proxy that was - // used. |proxy_servers.second| will contain the name of the data reduction - // proxy server that would be used if |proxy_server.first| is bypassed, if one - // exists. |proxy_servers| can be NULL if the caller isn't interested in its - // values. + // If true, |proxy_info.proxy_servers.first| will contain the name of the + // proxy that was used. |proxy_info.proxy_servers.second| will contain the + // name of the data reduction proxy server that would be used if + // |proxy_info.proxy_server.first| is bypassed, if one exists. In addition, + // |proxy_info| will note if the proxy used was a fallback, an alternative, + // or a proxy for ssl; these are not mutually exclusive. |proxy_info| can be + // NULL if the caller isn't interested in its values. virtual bool WasDataReductionProxyUsed( const net::URLRequest* request, - std::pair<GURL, GURL>* proxy_servers) const; + DataReductionProxyTypeInfo* proxy_info) const; // Returns true if the specified |host_port_pair| matches a data reduction - // proxy. If true, |proxy_servers.first| will contain the name of the proxy - // that matches. |proxy_servers.second| will contain the name of the - // data reduction proxy server that would be used if |proxy_server.first| is - // bypassed, if one exists. |proxy_servers| can be NULL if the caller isn't - // interested in its values. Virtual for testing. - virtual bool IsDataReductionProxy(const net::HostPortPair& host_port_pair, - std::pair<GURL, GURL>* proxy_servers) const; + // proxy. If true, |proxy_info.proxy_servers.first| will contain the name of + // the proxy that matches. |proxy_info.proxy_servers.second| will contain the + // name of the data reduction proxy server that would be used if + // |proxy_info.proxy_server.first| is bypassed, if one exists. In addition, + // |proxy_info| will note if the proxy was a fallback, an alternative, or a + // proxy for ssl; these are not mutually exclusive. |proxy_info| can be NULL + // if the caller isn't interested in its values. Virtual for testing. + virtual bool IsDataReductionProxy( + const net::HostPortPair& host_port_pair, + DataReductionProxyTypeInfo* proxy_info) const; // Returns true if this request will be sent through the data request proxy // based on applying the param rules to the URL. We do not check bad proxy diff --git a/components/data_reduction_proxy/browser/data_reduction_proxy_params_unittest.cc b/components/data_reduction_proxy/browser/data_reduction_proxy_params_unittest.cc index 4ab9e2d..69a9ab6 100644 --- a/components/data_reduction_proxy/browser/data_reduction_proxy_params_unittest.cc +++ b/components/data_reduction_proxy/browser/data_reduction_proxy_params_unittest.cc @@ -439,6 +439,9 @@ TEST_F(DataReductionProxyParamsTest, IsDataReductionProxy) { bool expected_result; net::HostPortPair expected_first; net::HostPortPair expected_second; + bool expected_is_fallback; + bool expected_is_alternative; + bool expected_is_ssl; } tests[] = { { net::HostPortPair::FromURL(GURL( TestDataReductionProxyParams::DefaultOrigin())), @@ -448,7 +451,10 @@ TEST_F(DataReductionProxyParamsTest, IsDataReductionProxy) { net::HostPortPair::FromURL(GURL( TestDataReductionProxyParams::DefaultOrigin())), net::HostPortPair::FromURL(GURL( - TestDataReductionProxyParams::DefaultFallbackOrigin())) + TestDataReductionProxyParams::DefaultFallbackOrigin())), + false, + false, + false }, { net::HostPortPair::FromURL(GURL( TestDataReductionProxyParams::DefaultOrigin())), @@ -457,7 +463,10 @@ TEST_F(DataReductionProxyParamsTest, IsDataReductionProxy) { true, net::HostPortPair::FromURL(GURL( TestDataReductionProxyParams::DefaultOrigin())), - net::HostPortPair::FromURL(GURL()) + net::HostPortPair::FromURL(GURL()), + false, + false, + false }, { net::HostPortPair::FromURL(GURL( TestDataReductionProxyParams::DefaultFallbackOrigin())), @@ -466,7 +475,10 @@ TEST_F(DataReductionProxyParamsTest, IsDataReductionProxy) { true, net::HostPortPair::FromURL(GURL( TestDataReductionProxyParams::DefaultFallbackOrigin())), - net::HostPortPair::FromURL(GURL()) + net::HostPortPair::FromURL(GURL()), + true, + false, + false }, { net::HostPortPair::FromURL(GURL( TestDataReductionProxyParams::DefaultFallbackOrigin())), @@ -474,7 +486,10 @@ TEST_F(DataReductionProxyParamsTest, IsDataReductionProxy) { false, false, net::HostPortPair::FromURL(GURL()), - net::HostPortPair::FromURL(GURL()) + net::HostPortPair::FromURL(GURL()), + false, + false, + false }, { net::HostPortPair::FromURL(GURL( TestDataReductionProxyParams::DefaultAltOrigin())), @@ -484,7 +499,10 @@ TEST_F(DataReductionProxyParamsTest, IsDataReductionProxy) { net::HostPortPair::FromURL(GURL( TestDataReductionProxyParams::DefaultAltOrigin())), net::HostPortPair::FromURL(GURL( - TestDataReductionProxyParams::DefaultAltFallbackOrigin())) + TestDataReductionProxyParams::DefaultAltFallbackOrigin())), + false, + true, + false }, { net::HostPortPair::FromURL(GURL( TestDataReductionProxyParams::DefaultAltOrigin())), @@ -493,7 +511,10 @@ TEST_F(DataReductionProxyParamsTest, IsDataReductionProxy) { true, net::HostPortPair::FromURL(GURL( TestDataReductionProxyParams::DefaultAltOrigin())), - net::HostPortPair::FromURL(GURL()) + net::HostPortPair::FromURL(GURL()), + false, + true, + false }, { net::HostPortPair::FromURL( GURL(TestDataReductionProxyParams::DefaultAltFallbackOrigin())), @@ -502,7 +523,10 @@ TEST_F(DataReductionProxyParamsTest, IsDataReductionProxy) { true, net::HostPortPair::FromURL(GURL( TestDataReductionProxyParams::DefaultAltFallbackOrigin())), - net::HostPortPair::FromURL(GURL()) + net::HostPortPair::FromURL(GURL()), + true, + true, + false }, { net::HostPortPair::FromURL(GURL( TestDataReductionProxyParams::DefaultAltFallbackOrigin())), @@ -510,7 +534,10 @@ TEST_F(DataReductionProxyParamsTest, IsDataReductionProxy) { false, false, net::HostPortPair::FromURL(GURL()), - net::HostPortPair::FromURL(GURL()) + net::HostPortPair::FromURL(GURL()), + false, + false, + false }, { net::HostPortPair::FromURL(GURL( TestDataReductionProxyParams::DefaultSSLOrigin())), @@ -519,7 +546,10 @@ TEST_F(DataReductionProxyParamsTest, IsDataReductionProxy) { true, net::HostPortPair::FromURL(GURL( TestDataReductionProxyParams::DefaultSSLOrigin())), - net::HostPortPair::FromURL(GURL()) + net::HostPortPair::FromURL(GURL()), + false, + false, + true }, { net::HostPortPair::FromURL(GURL( TestDataReductionProxyParams::DefaultDevOrigin())), @@ -529,7 +559,10 @@ TEST_F(DataReductionProxyParamsTest, IsDataReductionProxy) { net::HostPortPair::FromURL(GURL( TestDataReductionProxyParams::DefaultDevOrigin())), net::HostPortPair::FromURL(GURL( - TestDataReductionProxyParams::DefaultFallbackOrigin())) + TestDataReductionProxyParams::DefaultFallbackOrigin())), + false, + false, + false }, { net::HostPortPair::FromURL(GURL( TestDataReductionProxyParams::DefaultOrigin())), @@ -539,7 +572,10 @@ TEST_F(DataReductionProxyParamsTest, IsDataReductionProxy) { net::HostPortPair::FromURL(GURL( TestDataReductionProxyParams::DefaultOrigin())), net::HostPortPair::FromURL(GURL( - TestDataReductionProxyParams::DefaultFallbackOrigin())) + TestDataReductionProxyParams::DefaultFallbackOrigin())), + false, + false, + false }, }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { @@ -552,14 +588,17 @@ TEST_F(DataReductionProxyParamsTest, IsDataReductionProxy) { has_definitions &= ~TestDataReductionProxyParams::HAS_DEV_ORIGIN; } TestDataReductionProxyParams params(flags, has_definitions); - std::pair<GURL, GURL> proxy_servers; + DataReductionProxyTypeInfo proxy_type_info; EXPECT_EQ(tests[i].expected_result, params.IsDataReductionProxy( - tests[i].host_port_pair, &proxy_servers)); + tests[i].host_port_pair, &proxy_type_info)); EXPECT_TRUE(tests[i].expected_first.Equals( - net::HostPortPair::FromURL(proxy_servers.first))); + net::HostPortPair::FromURL(proxy_type_info.proxy_servers.first))); EXPECT_TRUE(tests[i].expected_second.Equals( - net::HostPortPair::FromURL(proxy_servers.second))); + net::HostPortPair::FromURL(proxy_type_info.proxy_servers.second))); + EXPECT_EQ(tests[i].expected_is_fallback, proxy_type_info.is_fallback); + EXPECT_EQ(tests[i].expected_is_alternative, proxy_type_info.is_alternative); + EXPECT_EQ(tests[i].expected_is_ssl, proxy_type_info.is_ssl); } } diff --git a/components/data_reduction_proxy/browser/data_reduction_proxy_protocol.cc b/components/data_reduction_proxy/browser/data_reduction_proxy_protocol.cc index 8ed54ad..4713a81 100644 --- a/components/data_reduction_proxy/browser/data_reduction_proxy_protocol.cc +++ b/components/data_reduction_proxy/browser/data_reduction_proxy_protocol.cc @@ -8,6 +8,7 @@ #include "base/time/time.h" #include "components/data_reduction_proxy/browser/data_reduction_proxy_params.h" #include "components/data_reduction_proxy/browser/data_reduction_proxy_tamper_detection.h" +#include "components/data_reduction_proxy/browser/data_reduction_proxy_usage_stats.h" #include "components/data_reduction_proxy/common/data_reduction_proxy_headers.h" #include "net/base/load_flags.h" #include "net/http/http_response_headers.h" @@ -42,12 +43,12 @@ bool MaybeBypassProxyAndPrepareToRetry( net::URLRequest* request, const net::HttpResponseHeaders* original_response_headers, scoped_refptr<net::HttpResponseHeaders>* override_response_headers, - net::ProxyService::DataReductionProxyBypassType* proxy_bypass_type) { + DataReductionProxyBypassType* proxy_bypass_type) { if (!data_reduction_proxy_params) return false; - std::pair<GURL, GURL> data_reduction_proxies; + DataReductionProxyTypeInfo data_reduction_proxy_type_info; if (!data_reduction_proxy_params->WasDataReductionProxyUsed( - request, &data_reduction_proxies)) { + request, &data_reduction_proxy_type_info)) { return false; } @@ -56,36 +57,43 @@ bool MaybeBypassProxyAndPrepareToRetry( if (request->proxy_server().IsEmpty()) return false; - if (data_reduction_proxies.first.is_empty()) + if (data_reduction_proxy_type_info.proxy_servers.first.is_empty()) return false; DataReductionProxyTamperDetection::DetectAndReport( original_response_headers, - data_reduction_proxies.first.SchemeIsSecure()); + data_reduction_proxy_type_info.proxy_servers.first.SchemeIsSecure()); DataReductionProxyInfo data_reduction_proxy_info; - net::ProxyService::DataReductionProxyBypassType bypass_type = + DataReductionProxyBypassType bypass_type = GetDataReductionProxyBypassType(original_response_headers, &data_reduction_proxy_info); if (proxy_bypass_type) *proxy_bypass_type = bypass_type; - if (bypass_type == net::ProxyService::BYPASS_EVENT_TYPE_MAX) + if (bypass_type == BYPASS_EVENT_TYPE_MAX) return false; DCHECK(request->context()); DCHECK(request->context()->proxy_service()); net::ProxyServer proxy_server; - SetProxyServerFromGURL(data_reduction_proxies.first, &proxy_server); - request->context()->proxy_service()->RecordDataReductionProxyBypassInfo( - !data_reduction_proxies.second.is_empty(), - data_reduction_proxy_info.bypass_all, - proxy_server, - bypass_type); + SetProxyServerFromGURL( + data_reduction_proxy_type_info.proxy_servers.first, &proxy_server); + + // Only record UMA if the proxy isn't already on the retry list. + const net::ProxyRetryInfoMap& proxy_retry_info = + request->context()->proxy_service()->proxy_retry_info(); + if (proxy_retry_info.find(proxy_server.ToURI()) == proxy_retry_info.end()) { + DataReductionProxyUsageStats::RecordDataReductionProxyBypassInfo( + !data_reduction_proxy_type_info.proxy_servers.second.is_empty(), + data_reduction_proxy_info.bypass_all, + proxy_server, + bypass_type); + } MarkProxiesAsBadUntil(request, data_reduction_proxy_info.bypass_duration, data_reduction_proxy_info.bypass_all, - data_reduction_proxies); + data_reduction_proxy_type_info.proxy_servers); // Only retry idempotent methods. if (!IsRequestIdempotent(request)) diff --git a/components/data_reduction_proxy/browser/data_reduction_proxy_protocol.h b/components/data_reduction_proxy/browser/data_reduction_proxy_protocol.h index 26dca40..b32ed6a 100644 --- a/components/data_reduction_proxy/browser/data_reduction_proxy_protocol.h +++ b/components/data_reduction_proxy/browser/data_reduction_proxy_protocol.h @@ -5,9 +5,8 @@ #ifndef COMPONENTS_DATA_REDUCTION_PROXY_BROWSER_DATA_REDUCTION_PROXY_PROTOCOL_H_ #define COMPONENTS_DATA_REDUCTION_PROXY_BROWSER_DATA_REDUCTION_PROXY_PROTOCOL_H_ -#include "base/macros.h" #include "base/memory/ref_counted.h" -#include "net/proxy/proxy_service.h" +#include "components/data_reduction_proxy/common/data_reduction_proxy_headers.h" namespace base { class TimeDelta; @@ -35,7 +34,7 @@ bool MaybeBypassProxyAndPrepareToRetry( net::URLRequest* request, const net::HttpResponseHeaders* original_response_headers, scoped_refptr<net::HttpResponseHeaders>* override_response_headers, - net::ProxyService::DataReductionProxyBypassType* proxy_bypass_type); + DataReductionProxyBypassType* proxy_bypass_type); // Configure |result| to proceed directly to the origin if |result|'s current // proxy is the data reduction proxy, the diff --git a/components/data_reduction_proxy/browser/data_reduction_proxy_protocol_unittest.cc b/components/data_reduction_proxy/browser/data_reduction_proxy_protocol_unittest.cc index e835c4d..c09ded7 100644 --- a/components/data_reduction_proxy/browser/data_reduction_proxy_protocol_unittest.cc +++ b/components/data_reduction_proxy/browser/data_reduction_proxy_protocol_unittest.cc @@ -12,6 +12,7 @@ #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "components/data_reduction_proxy/browser/data_reduction_proxy_params_test_utils.h" +#include "components/data_reduction_proxy/common/data_reduction_proxy_headers.h" #include "net/base/completion_callback.h" #include "net/base/host_port_pair.h" #include "net/base/load_flags.h" @@ -58,7 +59,7 @@ class TestDataReductionProxyNetworkDelegate : public net::NetworkDelegate { public: TestDataReductionProxyNetworkDelegate( TestDataReductionProxyParams* test_params, - ProxyService::DataReductionProxyBypassType* bypass_type) + DataReductionProxyBypassType* bypass_type) : net::NetworkDelegate(), test_data_reduction_proxy_params_(test_params), bypass_type_(bypass_type) { @@ -80,7 +81,7 @@ class TestDataReductionProxyNetworkDelegate : public net::NetworkDelegate { } TestDataReductionProxyParams* test_data_reduction_proxy_params_; - ProxyService::DataReductionProxyBypassType* bypass_type_; + DataReductionProxyBypassType* bypass_type_; }; // Constructs a |TestURLRequestContext| that uses a |MockSocketFactory| to @@ -99,9 +100,8 @@ class DataReductionProxyProtocolTest : public testing::Test { // Sets up the |TestURLRequestContext| with the provided |ProxyService| and // |bypass_type| to store bypass reasons. - void ConfigureTestDependencies( - ProxyService* proxy_service, - ProxyService::DataReductionProxyBypassType* bypass_type) { + void ConfigureTestDependencies(ProxyService* proxy_service, + DataReductionProxyBypassType* bypass_type) { // Create a context with delayed initialization. context_.reset(new TestURLRequestContext(true)); @@ -367,7 +367,7 @@ TEST_F(DataReductionProxyProtocolTest, BypassLogic) { size_t expected_bad_proxy_count; bool expect_response_body; int expected_duration; - ProxyService::DataReductionProxyBypassType expected_bypass_type; + DataReductionProxyBypassType expected_bypass_type; } tests[] = { // Valid data reduction proxy response with no bypass message. { "GET", @@ -378,7 +378,7 @@ TEST_F(DataReductionProxyProtocolTest, BypassLogic) { 0u, true, -1, - ProxyService::BYPASS_EVENT_TYPE_MAX, + BYPASS_EVENT_TYPE_MAX, }, // Valid data reduction proxy response with older, but still valid via // header. @@ -390,7 +390,7 @@ TEST_F(DataReductionProxyProtocolTest, BypassLogic) { 0u, true, -1, - ProxyService::BYPASS_EVENT_TYPE_MAX + BYPASS_EVENT_TYPE_MAX }, // Valid data reduction proxy response with chained via header, // no bypass message. @@ -402,7 +402,7 @@ TEST_F(DataReductionProxyProtocolTest, BypassLogic) { 0u, true, -1, - ProxyService::BYPASS_EVENT_TYPE_MAX + BYPASS_EVENT_TYPE_MAX }, // Valid data reduction proxy response with a bypass message. { "GET", @@ -414,7 +414,7 @@ TEST_F(DataReductionProxyProtocolTest, BypassLogic) { 1u, true, 0, - ProxyService::MEDIUM_BYPASS + BYPASS_EVENT_TYPE_MEDIUM }, // Valid data reduction proxy response with a bypass message. { "GET", @@ -426,7 +426,7 @@ TEST_F(DataReductionProxyProtocolTest, BypassLogic) { 1u, true, 1, - ProxyService::SHORT_BYPASS + BYPASS_EVENT_TYPE_SHORT }, // Same as above with the OPTIONS method, which is idempotent. { "OPTIONS", @@ -438,7 +438,7 @@ TEST_F(DataReductionProxyProtocolTest, BypassLogic) { 1u, true, 0, - ProxyService::MEDIUM_BYPASS + BYPASS_EVENT_TYPE_MEDIUM }, // Same as above with the HEAD method, which is idempotent. { "HEAD", @@ -450,7 +450,7 @@ TEST_F(DataReductionProxyProtocolTest, BypassLogic) { 1u, false, 0, - ProxyService::MEDIUM_BYPASS + BYPASS_EVENT_TYPE_MEDIUM }, // Same as above with the PUT method, which is idempotent. { "PUT", @@ -462,7 +462,7 @@ TEST_F(DataReductionProxyProtocolTest, BypassLogic) { 1u, true, 0, - ProxyService::MEDIUM_BYPASS + BYPASS_EVENT_TYPE_MEDIUM }, // Same as above with the DELETE method, which is idempotent. { "DELETE", @@ -474,7 +474,7 @@ TEST_F(DataReductionProxyProtocolTest, BypassLogic) { 1u, true, 0, - ProxyService::MEDIUM_BYPASS + BYPASS_EVENT_TYPE_MEDIUM }, // Same as above with the TRACE method, which is idempotent. { "TRACE", @@ -486,7 +486,7 @@ TEST_F(DataReductionProxyProtocolTest, BypassLogic) { 1u, true, 0, - ProxyService::MEDIUM_BYPASS + BYPASS_EVENT_TYPE_MEDIUM }, // 500 responses should be bypassed. { "GET", @@ -497,7 +497,7 @@ TEST_F(DataReductionProxyProtocolTest, BypassLogic) { 1u, true, 0, - ProxyService::STATUS_500_HTTP_INTERNAL_SERVER_ERROR + BYPASS_EVENT_TYPE_STATUS_500_HTTP_INTERNAL_SERVER_ERROR }, // 502 responses should be bypassed. { "GET", @@ -508,7 +508,7 @@ TEST_F(DataReductionProxyProtocolTest, BypassLogic) { 1u, true, 0, - ProxyService::STATUS_502_HTTP_BAD_GATEWAY + BYPASS_EVENT_TYPE_STATUS_502_HTTP_BAD_GATEWAY }, // 503 responses should be bypassed. { "GET", @@ -519,7 +519,7 @@ TEST_F(DataReductionProxyProtocolTest, BypassLogic) { 1u, true, 0, - ProxyService::STATUS_503_HTTP_SERVICE_UNAVAILABLE + BYPASS_EVENT_TYPE_STATUS_503_HTTP_SERVICE_UNAVAILABLE }, // Invalid data reduction proxy response. Missing Via header. { "GET", @@ -529,7 +529,7 @@ TEST_F(DataReductionProxyProtocolTest, BypassLogic) { 1u, true, 0, - ProxyService::MISSING_VIA_HEADER_OTHER + BYPASS_EVENT_TYPE_MISSING_VIA_HEADER_OTHER }, // Invalid data reduction proxy response. Wrong Via header. { "GET", @@ -540,7 +540,7 @@ TEST_F(DataReductionProxyProtocolTest, BypassLogic) { 1u, true, 0, - ProxyService::MISSING_VIA_HEADER_OTHER + BYPASS_EVENT_TYPE_MISSING_VIA_HEADER_OTHER }, // Valid data reduction proxy response. 304 missing Via header. { "GET", @@ -550,7 +550,7 @@ TEST_F(DataReductionProxyProtocolTest, BypassLogic) { 0u, false, 0, - ProxyService::BYPASS_EVENT_TYPE_MAX + BYPASS_EVENT_TYPE_MAX }, // Valid data reduction proxy response with a bypass message. It will // not be retried because the request is non-idempotent. @@ -563,7 +563,7 @@ TEST_F(DataReductionProxyProtocolTest, BypassLogic) { 1u, true, 0, - ProxyService::MEDIUM_BYPASS + BYPASS_EVENT_TYPE_MEDIUM }, // Valid data reduction proxy response with block message. Both proxies // should be on the retry list when it completes. @@ -576,13 +576,13 @@ TEST_F(DataReductionProxyProtocolTest, BypassLogic) { 2u, true, 1, - ProxyService::SHORT_BYPASS + BYPASS_EVENT_TYPE_SHORT } }; std::string primary = proxy_params_->DefaultOrigin(); std::string fallback = proxy_params_->DefaultFallbackOrigin(); for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { - ProxyService::DataReductionProxyBypassType bypass_type; + DataReductionProxyBypassType bypass_type; ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult( "PROXY " + HostPortPair::FromURL(GURL(primary)).ToString() + "; PROXY " + diff --git a/components/data_reduction_proxy/browser/data_reduction_proxy_usage_stats.cc b/components/data_reduction_proxy/browser/data_reduction_proxy_usage_stats.cc index bddfef4..01fbc1b 100644 --- a/components/data_reduction_proxy/browser/data_reduction_proxy_usage_stats.cc +++ b/components/data_reduction_proxy/browser/data_reduction_proxy_usage_stats.cc @@ -8,6 +8,8 @@ #include "base/callback.h" #include "base/message_loop/message_loop_proxy.h" #include "base/metrics/histogram.h" +#include "base/metrics/sparse_histogram.h" +#include "components/data_reduction_proxy/common/data_reduction_proxy_headers.h" #include "net/base/net_errors.h" #include "net/proxy/proxy_retry_info.h" #include "net/proxy/proxy_server.h" @@ -24,11 +26,57 @@ using net::URLRequest; namespace data_reduction_proxy { +namespace { + +// Records a net error code that resulted in bypassing the data reduction +// proxy (|is_primary| is true) or the data reduction proxy fallback. +void RecordDataReductionProxyBypassOnNetworkError( + bool is_primary, + const ProxyServer& proxy_server, + int net_error) { + if (is_primary) { + UMA_HISTOGRAM_SPARSE_SLOWLY( + "DataReductionProxy.BypassOnNetworkErrorPrimary", + std::abs(net_error)); + return; + } + UMA_HISTOGRAM_SPARSE_SLOWLY( + "DataReductionProxy.BypassOnNetworkErrorFallback", + std::abs(net_error)); +} + +} // namespace + +// static +void DataReductionProxyUsageStats::RecordDataReductionProxyBypassInfo( + bool is_primary, + bool bypass_all, + const net::ProxyServer& proxy_server, + DataReductionProxyBypassType bypass_type) { + if (bypass_all) { + if (is_primary) { + UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.BlockTypePrimary", + bypass_type, BYPASS_EVENT_TYPE_MAX); + } else { + UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.BlockTypeFallback", + bypass_type, BYPASS_EVENT_TYPE_MAX); + } + } else { + if (is_primary) { + UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.BypassTypePrimary", + bypass_type, BYPASS_EVENT_TYPE_MAX); + } else { + UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.BypassTypeFallback", + bypass_type, BYPASS_EVENT_TYPE_MAX); + } + } +} + DataReductionProxyUsageStats::DataReductionProxyUsageStats( DataReductionProxyParams* params, MessageLoopProxy* ui_thread_proxy) : data_reduction_proxy_params_(params), - last_bypass_type_(ProxyService::BYPASS_EVENT_TYPE_MAX), + last_bypass_type_(BYPASS_EVENT_TYPE_MAX), triggering_request_(true), ui_thread_proxy_(ui_thread_proxy), eligible_num_requests_through_proxy_(0), @@ -106,7 +154,7 @@ void DataReductionProxyUsageStats::NotifyUnavailabilityOnUIThread( } void DataReductionProxyUsageStats::SetBypassType( - ProxyService::DataReductionProxyBypassType type) { + DataReductionProxyBypassType type) { last_bypass_type_ = type; triggering_request_ = true; } @@ -156,7 +204,7 @@ void DataReductionProxyUsageStats::RecordBypassedBytesHistograms( content_length); } - if (last_bypass_type_ != ProxyService::BYPASS_EVENT_TYPE_MAX) { + if (last_bypass_type_ != BYPASS_EVENT_TYPE_MAX) { RecordBypassedBytes(last_bypass_type_, DataReductionProxyUsageStats::BYPASSED_BYTES_TYPE_MAX, content_length); @@ -171,8 +219,31 @@ void DataReductionProxyUsageStats::RecordBypassedBytesHistograms( } } +void DataReductionProxyUsageStats::RecordBypassEventHistograms( + const net::ProxyServer& bypassed_proxy, + int net_error, + bool did_fallback) const { + DataReductionProxyTypeInfo data_reduction_proxy_info; + if (data_reduction_proxy_params_->IsDataReductionProxy( + bypassed_proxy.host_port_pair(), &data_reduction_proxy_info)) { + if (data_reduction_proxy_info.is_ssl) + return; + if (!data_reduction_proxy_info.is_fallback) { + RecordDataReductionProxyBypassInfo( + true, false, bypassed_proxy, BYPASS_EVENT_TYPE_NETWORK_ERROR); + RecordDataReductionProxyBypassOnNetworkError( + true, bypassed_proxy, net_error); + } else { + RecordDataReductionProxyBypassInfo( + false, false, bypassed_proxy, BYPASS_EVENT_TYPE_NETWORK_ERROR); + RecordDataReductionProxyBypassOnNetworkError( + false, bypassed_proxy, net_error); + } + } +} + void DataReductionProxyUsageStats::RecordBypassedBytes( - ProxyService::DataReductionProxyBypassType bypass_type, + DataReductionProxyBypassType bypass_type, DataReductionProxyUsageStats::BypassedBytesType bypassed_bytes_type, int64 content_length) { // Individual histograms are needed to count the bypassed bytes for each @@ -193,7 +264,7 @@ void DataReductionProxyUsageStats::RecordBypassedBytes( content_length); break; case DataReductionProxyUsageStats::AUDIO_VIDEO: - if (last_bypass_type_ == ProxyService::SHORT_BYPASS) { + if (last_bypass_type_ == BYPASS_EVENT_TYPE_SHORT) { UMA_HISTOGRAM_COUNTS( "DataReductionProxy.BypassedBytes.ShortAudioVideo", content_length); @@ -201,17 +272,17 @@ void DataReductionProxyUsageStats::RecordBypassedBytes( break; case DataReductionProxyUsageStats::TRIGGERING_REQUEST: switch (bypass_type) { - case ProxyService::SHORT_BYPASS: + case BYPASS_EVENT_TYPE_SHORT: UMA_HISTOGRAM_COUNTS( "DataReductionProxy.BypassedBytes.ShortTriggeringRequest", content_length); break; - case ProxyService::MEDIUM_BYPASS: + case BYPASS_EVENT_TYPE_MEDIUM: UMA_HISTOGRAM_COUNTS( "DataReductionProxy.BypassedBytes.MediumTriggeringRequest", content_length); break; - case ProxyService::LONG_BYPASS: + case BYPASS_EVENT_TYPE_LONG: UMA_HISTOGRAM_COUNTS( "DataReductionProxy.BypassedBytes.LongTriggeringRequest", content_length); @@ -227,48 +298,48 @@ void DataReductionProxyUsageStats::RecordBypassedBytes( break; case DataReductionProxyUsageStats::BYPASSED_BYTES_TYPE_MAX: switch (bypass_type) { - case ProxyService::CURRENT_BYPASS: + case BYPASS_EVENT_TYPE_CURRENT: UMA_HISTOGRAM_COUNTS("DataReductionProxy.BypassedBytes.Current", content_length); break; - case ProxyService::SHORT_BYPASS: + case BYPASS_EVENT_TYPE_SHORT: UMA_HISTOGRAM_COUNTS("DataReductionProxy.BypassedBytes.ShortAll", content_length); break; - case ProxyService::MEDIUM_BYPASS: + case BYPASS_EVENT_TYPE_MEDIUM: UMA_HISTOGRAM_COUNTS("DataReductionProxy.BypassedBytes.MediumAll", content_length); break; - case ProxyService::LONG_BYPASS: + case BYPASS_EVENT_TYPE_LONG: UMA_HISTOGRAM_COUNTS("DataReductionProxy.BypassedBytes.LongAll", content_length); break; - case ProxyService::MISSING_VIA_HEADER_4XX: + case BYPASS_EVENT_TYPE_MISSING_VIA_HEADER_4XX: UMA_HISTOGRAM_COUNTS( "DataReductionProxy.BypassedBytes.MissingViaHeader4xx", content_length); break; - case ProxyService::MISSING_VIA_HEADER_OTHER: + case BYPASS_EVENT_TYPE_MISSING_VIA_HEADER_OTHER: UMA_HISTOGRAM_COUNTS( "DataReductionProxy.BypassedBytes.MissingViaHeaderOther", content_length); break; - case ProxyService::MALFORMED_407: + case BYPASS_EVENT_TYPE_MALFORMED_407: UMA_HISTOGRAM_COUNTS("DataReductionProxy.BypassedBytes.Malformed407", content_length); break; - case ProxyService::STATUS_500_HTTP_INTERNAL_SERVER_ERROR: + case BYPASS_EVENT_TYPE_STATUS_500_HTTP_INTERNAL_SERVER_ERROR: UMA_HISTOGRAM_COUNTS( "DataReductionProxy.BypassedBytes." "Status500HttpInternalServerError", content_length); break; - case ProxyService::STATUS_502_HTTP_BAD_GATEWAY: + case BYPASS_EVENT_TYPE_STATUS_502_HTTP_BAD_GATEWAY: UMA_HISTOGRAM_COUNTS( "DataReductionProxy.BypassedBytes.Status502HttpBadGateway", content_length); break; - case ProxyService::STATUS_503_HTTP_SERVICE_UNAVAILABLE: + case BYPASS_EVENT_TYPE_STATUS_503_HTTP_SERVICE_UNAVAILABLE: UMA_HISTOGRAM_COUNTS( "DataReductionProxy.BypassedBytes." "Status503HttpServiceUnavailable", diff --git a/components/data_reduction_proxy/browser/data_reduction_proxy_usage_stats.h b/components/data_reduction_proxy/browser/data_reduction_proxy_usage_stats.h index 4fe9c5e..d73db4b 100644 --- a/components/data_reduction_proxy/browser/data_reduction_proxy_usage_stats.h +++ b/components/data_reduction_proxy/browser/data_reduction_proxy_usage_stats.h @@ -10,16 +10,29 @@ #include "base/prefs/pref_member.h" #include "base/threading/thread_checker.h" #include "components/data_reduction_proxy/browser/data_reduction_proxy_params.h" +#include "components/data_reduction_proxy/common/data_reduction_proxy_headers.h" #include "net/base/host_port_pair.h" #include "net/base/network_change_notifier.h" -#include "net/proxy/proxy_service.h" #include "net/url_request/url_request.h" +namespace net { +class ProxyServer; +} + namespace data_reduction_proxy { class DataReductionProxyUsageStats : public net::NetworkChangeNotifier::NetworkChangeObserver { public: + // Records a data reduction proxy bypass event as a "BlockType" if + // |bypass_all| is true and as a "BypassType" otherwise. Records the event as + // "Primary" if |is_primary| is true and "Fallback" otherwise. + static void RecordDataReductionProxyBypassInfo( + bool is_primary, + bool bypass_all, + const net::ProxyServer& proxy_server, + DataReductionProxyBypassType bypass_type); + // MessageLoopProxy instance is owned by io_thread. |params| outlives // this class instance. DataReductionProxyUsageStats(DataReductionProxyParams* params, @@ -40,7 +53,7 @@ class DataReductionProxyUsageStats // Records the last bypass reason to |bypass_type_| and sets // |triggering_request_| to true. A triggering request is the first request to // cause the current bypass. - void SetBypassType(net::ProxyService::DataReductionProxyBypassType type); + void SetBypassType(DataReductionProxyBypassType type); // Given the |content_length| and associated |request|, records the // number of bypassed bytes for that |request| into UMAs based on bypass type. @@ -50,6 +63,10 @@ class DataReductionProxyUsageStats net::URLRequest& request, const BooleanPrefMember& data_reduction_proxy_enabled); + void RecordBypassEventHistograms(const net::ProxyServer& bypassed_proxy, + int net_error, + bool did_fallback) const; + private: enum BypassedBytesType { NOT_BYPASSED = 0, /* Not bypassed. */ @@ -81,7 +98,7 @@ class DataReductionProxyUsageStats DataReductionProxyParams* data_reduction_proxy_params_; // The last reason for bypass as determined by // MaybeBypassProxyAndPrepareToRetry - net::ProxyService::DataReductionProxyBypassType last_bypass_type_; + DataReductionProxyBypassType last_bypass_type_; // True if the last request triggered the current bypass. bool triggering_request_; base::MessageLoopProxy* ui_thread_proxy_; @@ -107,7 +124,7 @@ class DataReductionProxyUsageStats base::ThreadChecker thread_checker_; void RecordBypassedBytes( - net::ProxyService::DataReductionProxyBypassType bypass_type, + DataReductionProxyBypassType bypass_type, BypassedBytesType bypassed_bytes_type, int64 content_length); diff --git a/components/data_reduction_proxy/browser/data_reduction_proxy_usage_stats_unittest.cc b/components/data_reduction_proxy/browser/data_reduction_proxy_usage_stats_unittest.cc index 3314253..a3f02d3 100644 --- a/components/data_reduction_proxy/browser/data_reduction_proxy_usage_stats_unittest.cc +++ b/components/data_reduction_proxy/browser/data_reduction_proxy_usage_stats_unittest.cc @@ -30,8 +30,10 @@ class DataReductionProxyParamsMock : public DataReductionProxyParams { virtual ~DataReductionProxyParamsMock() {} MOCK_METHOD1(IsDataReductionProxyEligible, bool(const net::URLRequest*)); - MOCK_CONST_METHOD2(WasDataReductionProxyUsed, bool(const net::URLRequest*, - std::pair<GURL, GURL>* proxy_servers)); + MOCK_CONST_METHOD2( + WasDataReductionProxyUsed, + bool(const net::URLRequest*, + data_reduction_proxy::DataReductionProxyTypeInfo* proxy_servers)); private: DISALLOW_COPY_AND_ASSIGN(DataReductionProxyParamsMock); diff --git a/components/data_reduction_proxy/common/data_reduction_proxy_headers.cc b/components/data_reduction_proxy/common/data_reduction_proxy_headers.cc index 9999c39..c68d3e6 100644 --- a/components/data_reduction_proxy/common/data_reduction_proxy_headers.cc +++ b/components/data_reduction_proxy/common/data_reduction_proxy_headers.cc @@ -14,11 +14,9 @@ #include "base/time/time.h" #include "net/http/http_response_headers.h" #include "net/http/http_status_code.h" -#include "net/proxy/proxy_service.h" using base::StringPiece; using base::TimeDelta; -using net::ProxyService; namespace { @@ -174,8 +172,7 @@ bool HasDataReductionProxyViaHeader(const net::HttpResponseHeaders* headers, return false; } -net::ProxyService::DataReductionProxyBypassType -GetDataReductionProxyBypassType( +DataReductionProxyBypassType GetDataReductionProxyBypassType( const net::HttpResponseHeaders* headers, DataReductionProxyInfo* data_reduction_proxy_info) { DCHECK(data_reduction_proxy_info); @@ -183,25 +180,28 @@ GetDataReductionProxyBypassType( // A chrome-proxy response header is only present in a 502. For proper // reporting, this check must come before the 5xx checks below. const TimeDelta& duration = data_reduction_proxy_info->bypass_duration; + // bypass=0 means bypass for a random duration between 1 to 5 minutes + if (duration == TimeDelta()) + return BYPASS_EVENT_TYPE_MEDIUM; if (duration <= TimeDelta::FromSeconds(kShortBypassMaxSeconds)) - return ProxyService::SHORT_BYPASS; + return BYPASS_EVENT_TYPE_SHORT; if (duration <= TimeDelta::FromSeconds(kMediumBypassMaxSeconds)) - return ProxyService::MEDIUM_BYPASS; - return ProxyService::LONG_BYPASS; + return BYPASS_EVENT_TYPE_MEDIUM; + return BYPASS_EVENT_TYPE_LONG; } data_reduction_proxy_info->bypass_duration = GetDefaultBypassDuration(); // Fall back if a 500, 502 or 503 is returned. if (headers->response_code() == net::HTTP_INTERNAL_SERVER_ERROR) - return ProxyService::STATUS_500_HTTP_INTERNAL_SERVER_ERROR; + return BYPASS_EVENT_TYPE_STATUS_500_HTTP_INTERNAL_SERVER_ERROR; if (headers->response_code() == net::HTTP_BAD_GATEWAY) - return ProxyService::STATUS_502_HTTP_BAD_GATEWAY; + return BYPASS_EVENT_TYPE_STATUS_502_HTTP_BAD_GATEWAY; if (headers->response_code() == net::HTTP_SERVICE_UNAVAILABLE) - return ProxyService::STATUS_503_HTTP_SERVICE_UNAVAILABLE; + return BYPASS_EVENT_TYPE_STATUS_503_HTTP_SERVICE_UNAVAILABLE; // TODO(kundaji): Bypass if Proxy-Authenticate header value cannot be // interpreted by data reduction proxy. if (headers->response_code() == net::HTTP_PROXY_AUTHENTICATION_REQUIRED && !headers->HasHeader("Proxy-Authenticate")) { - return ProxyService::MALFORMED_407; + return BYPASS_EVENT_TYPE_MALFORMED_407; } if (!HasDataReductionProxyViaHeader(headers, NULL) && (headers->response_code() != net::HTTP_NOT_MODIFIED)) { @@ -214,12 +214,12 @@ GetDataReductionProxyBypassType( // Separate this case from other responses that are missing the header. if (headers->response_code() >= net::HTTP_BAD_REQUEST && headers->response_code() < net::HTTP_INTERNAL_SERVER_ERROR) { - return ProxyService::MISSING_VIA_HEADER_4XX; + return BYPASS_EVENT_TYPE_MISSING_VIA_HEADER_4XX; } - return ProxyService::MISSING_VIA_HEADER_OTHER; + return BYPASS_EVENT_TYPE_MISSING_VIA_HEADER_OTHER; } // There is no bypass event. - return ProxyService::BYPASS_EVENT_TYPE_MAX; + return BYPASS_EVENT_TYPE_MAX; } bool GetDataReductionProxyActionFingerprintChromeProxy( diff --git a/components/data_reduction_proxy/common/data_reduction_proxy_headers.h b/components/data_reduction_proxy/common/data_reduction_proxy_headers.h index 319d90d..6dc8800 100644 --- a/components/data_reduction_proxy/common/data_reduction_proxy_headers.h +++ b/components/data_reduction_proxy/common/data_reduction_proxy_headers.h @@ -19,6 +19,49 @@ class HttpResponseHeaders; namespace data_reduction_proxy { +// Values of the UMA DataReductionProxy.BypassType{Primary|Fallback} +// and DataReductionProxy.BlockType{Primary|Fallback} histograms. +// This enum must remain synchronized with the enum of the same +// name in metrics/histograms/histograms.xml. +enum DataReductionProxyBypassType { + // Bypass due to explicit instruction for the current request. + // Not yet supported. + BYPASS_EVENT_TYPE_CURRENT = 0, + + // Bypass the proxy for less than one minute. + BYPASS_EVENT_TYPE_SHORT = 1, + + // Bypass the proxy for one to five minutes. + BYPASS_EVENT_TYPE_MEDIUM = 2, + + // Bypass the proxy for more than five minutes. + BYPASS_EVENT_TYPE_LONG = 3, + + // Bypass due to a 4xx missing via header. + BYPASS_EVENT_TYPE_MISSING_VIA_HEADER_4XX = 4, + + // Bypass due to other missing via header, excluding 4xx errors. + BYPASS_EVENT_TYPE_MISSING_VIA_HEADER_OTHER = 5, + + // Bypass due to 407 response from proxy without a challenge. + BYPASS_EVENT_TYPE_MALFORMED_407 = 6, + + // Bypass due to a 500 internal server error + BYPASS_EVENT_TYPE_STATUS_500_HTTP_INTERNAL_SERVER_ERROR = 7, + + // Bypass because the request URI was too long. + BYPASS_EVENT_TYPE_STATUS_502_HTTP_BAD_GATEWAY = 8, + + // Bypass due to a 503 response. + BYPASS_EVENT_TYPE_STATUS_503_HTTP_SERVICE_UNAVAILABLE = 9, + + // Bypass due to any network error. + BYPASS_EVENT_TYPE_NETWORK_ERROR = 10, + + // This must always be last. + BYPASS_EVENT_TYPE_MAX = 11 +}; + // Contains instructions contained in the Chrome-Proxy header. struct DataReductionProxyInfo { DataReductionProxyInfo() : bypass_all(false) {} @@ -51,7 +94,7 @@ bool HasDataReductionProxyViaHeader(const net::HttpResponseHeaders* headers, // Returns the reason why the Chrome proxy should be bypassed or not, and // populates |proxy_info| with information on how long to bypass if // applicable. -net::ProxyService::DataReductionProxyBypassType GetDataReductionProxyBypassType( +DataReductionProxyBypassType GetDataReductionProxyBypassType( const net::HttpResponseHeaders* headers, DataReductionProxyInfo* proxy_info); diff --git a/components/data_reduction_proxy/common/data_reduction_proxy_headers_unittest.cc b/components/data_reduction_proxy/common/data_reduction_proxy_headers_unittest.cc index 6852959..9317168 100644 --- a/components/data_reduction_proxy/common/data_reduction_proxy_headers_unittest.cc +++ b/components/data_reduction_proxy/common/data_reduction_proxy_headers_unittest.cc @@ -428,97 +428,97 @@ TEST_F(DataReductionProxyHeadersTest, HasDataReductionProxyViaHeader) { TEST_F(DataReductionProxyHeadersTest, GetDataReductionProxyBypassEventType) { const struct { const char* headers; - net::ProxyService::DataReductionProxyBypassType expected_result; + DataReductionProxyBypassType expected_result; } tests[] = { { "HTTP/1.1 200 OK\n" "Chrome-Proxy: bypass=0\n" "Via: 1.1 Chrome-Compression-Proxy\n", - net::ProxyService::MEDIUM_BYPASS, + BYPASS_EVENT_TYPE_MEDIUM, }, { "HTTP/1.1 200 OK\n" "Chrome-Proxy: bypass=1\n" "Via: 1.1 Chrome-Compression-Proxy\n", - net::ProxyService::SHORT_BYPASS, + BYPASS_EVENT_TYPE_SHORT, }, { "HTTP/1.1 200 OK\n" "Chrome-Proxy: bypass=59\n" "Via: 1.1 Chrome-Compression-Proxy\n", - net::ProxyService::SHORT_BYPASS, + BYPASS_EVENT_TYPE_SHORT, }, { "HTTP/1.1 200 OK\n" "Chrome-Proxy: bypass=60\n" "Via: 1.1 Chrome-Compression-Proxy\n", - net::ProxyService::MEDIUM_BYPASS, + BYPASS_EVENT_TYPE_MEDIUM, }, { "HTTP/1.1 200 OK\n" "Chrome-Proxy: bypass=300\n" "Via: 1.1 Chrome-Compression-Proxy\n", - net::ProxyService::MEDIUM_BYPASS, + BYPASS_EVENT_TYPE_MEDIUM, }, { "HTTP/1.1 200 OK\n" "Chrome-Proxy: bypass=301\n" "Via: 1.1 Chrome-Compression-Proxy\n", - net::ProxyService::LONG_BYPASS, + BYPASS_EVENT_TYPE_LONG, }, { "HTTP/1.1 500 Internal Server Error\n" "Via: 1.1 Chrome-Compression-Proxy\n", - net::ProxyService::STATUS_500_HTTP_INTERNAL_SERVER_ERROR, + BYPASS_EVENT_TYPE_STATUS_500_HTTP_INTERNAL_SERVER_ERROR, }, { "HTTP/1.1 501 Not Implemented\n" "Via: 1.1 Chrome-Compression-Proxy\n", - net::ProxyService::BYPASS_EVENT_TYPE_MAX, + BYPASS_EVENT_TYPE_MAX, }, { "HTTP/1.1 502 Bad Gateway\n" "Via: 1.1 Chrome-Compression-Proxy\n", - net::ProxyService::STATUS_502_HTTP_BAD_GATEWAY, + BYPASS_EVENT_TYPE_STATUS_502_HTTP_BAD_GATEWAY, }, { "HTTP/1.1 503 Service Unavailable\n" "Via: 1.1 Chrome-Compression-Proxy\n", - net::ProxyService::STATUS_503_HTTP_SERVICE_UNAVAILABLE, + BYPASS_EVENT_TYPE_STATUS_503_HTTP_SERVICE_UNAVAILABLE, }, { "HTTP/1.1 504 Gateway Timeout\n" "Via: 1.1 Chrome-Compression-Proxy\n", - net::ProxyService::BYPASS_EVENT_TYPE_MAX, + BYPASS_EVENT_TYPE_MAX, }, { "HTTP/1.1 505 HTTP Version Not Supported\n" "Via: 1.1 Chrome-Compression-Proxy\n", - net::ProxyService::BYPASS_EVENT_TYPE_MAX, + BYPASS_EVENT_TYPE_MAX, }, { "HTTP/1.1 304 Not Modified\n", - net::ProxyService::BYPASS_EVENT_TYPE_MAX, + BYPASS_EVENT_TYPE_MAX, }, { "HTTP/1.1 200 OK\n", - net::ProxyService::MISSING_VIA_HEADER_OTHER, + BYPASS_EVENT_TYPE_MISSING_VIA_HEADER_OTHER, }, { "HTTP/1.1 200 OK\n" "Chrome-Proxy: bypass=59\n", - net::ProxyService::SHORT_BYPASS, + BYPASS_EVENT_TYPE_SHORT, }, { "HTTP/1.1 502 Bad Gateway\n", - net::ProxyService::STATUS_502_HTTP_BAD_GATEWAY, + BYPASS_EVENT_TYPE_STATUS_502_HTTP_BAD_GATEWAY, }, { "HTTP/1.1 502 Bad Gateway\n" "Chrome-Proxy: bypass=59\n", - net::ProxyService::SHORT_BYPASS, + BYPASS_EVENT_TYPE_SHORT, }, { "HTTP/1.1 502 Bad Gateway\n" "Chrome-Proxy: bypass=59\n", - net::ProxyService::SHORT_BYPASS, + BYPASS_EVENT_TYPE_SHORT, }, { "HTTP/1.1 414 Request-URI Too Long\n", - net::ProxyService::MISSING_VIA_HEADER_4XX, + BYPASS_EVENT_TYPE_MISSING_VIA_HEADER_4XX, }, { "HTTP/1.1 414 Request-URI Too Long\n" "Via: 1.1 Chrome-Compression-Proxy\n", - net::ProxyService::BYPASS_EVENT_TYPE_MAX, + BYPASS_EVENT_TYPE_MAX, }, { "HTTP/1.1 407 Proxy Authentication Required\n", - net::ProxyService::MALFORMED_407, + BYPASS_EVENT_TYPE_MALFORMED_407, }, { "HTTP/1.1 407 Proxy Authentication Required\n" "Proxy-Authenticate: Basic\n" "Via: 1.1 Chrome-Compression-Proxy\n", - net::ProxyService::BYPASS_EVENT_TYPE_MAX, + BYPASS_EVENT_TYPE_MAX, } }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { diff --git a/net/base/network_delegate.cc b/net/base/network_delegate.cc index 448f217..7591752 100644 --- a/net/base/network_delegate.cc +++ b/net/base/network_delegate.cc @@ -28,6 +28,14 @@ void NetworkDelegate::NotifyResolveProxy(const GURL& url, int load_flags, OnResolveProxy(url, load_flags, result); } +void NetworkDelegate::NotifyProxyFallback( + const ProxyServer& bad_proxy, + int net_error, + bool did_fallback) { + DCHECK(CalledOnValidThread()); + OnProxyFallback(bad_proxy, net_error, did_fallback); +} + int NetworkDelegate::NotifyBeforeSendHeaders( URLRequest* request, const CompletionCallback& callback, HttpRequestHeaders* headers) { @@ -166,6 +174,11 @@ void NetworkDelegate::OnResolveProxy(const GURL& url, int load_flags, ProxyInfo* result) { } +void NetworkDelegate::OnProxyFallback(const ProxyServer& bad_proxy, + int net_error, + bool did_fallback) { +} + int NetworkDelegate::OnBeforeSendHeaders(URLRequest* request, const CompletionCallback& callback, HttpRequestHeaders* headers) { diff --git a/net/base/network_delegate.h b/net/base/network_delegate.h index aa8fa9a..eafaca6 100644 --- a/net/base/network_delegate.h +++ b/net/base/network_delegate.h @@ -36,6 +36,7 @@ class CookieOptions; class HttpRequestHeaders; class HttpResponseHeaders; class ProxyInfo; +class ProxyServer; class SocketStream; class URLRequest; @@ -63,6 +64,9 @@ class NET_EXPORT NetworkDelegate : public base::NonThreadSafe { GURL* new_url); void NotifyResolveProxy(const GURL& url, int load_flags, ProxyInfo* result); + void NotifyProxyFallback(const ProxyServer& bad_proxy, + int net_error, + bool did_fallback); int NotifyBeforeSendHeaders(URLRequest* request, const CompletionCallback& callback, HttpRequestHeaders* headers); @@ -130,6 +134,13 @@ class NET_EXPORT NetworkDelegate : public base::NonThreadSafe { int load_flags, ProxyInfo* result); + // Called when use of |bad_proxy| fails due to |net_error|. |did_fallback| is + // true if the proxy service was able to fallback to another proxy + // configuration. + virtual void OnProxyFallback(const ProxyServer& bad_proxy, + int net_error, + bool did_fallback); + // Called right before the HTTP headers are sent. Allows the delegate to // read/write |headers| before they get sent out. |callback| and |headers| are // valid only until OnCompleted or OnURLRequestDestroyed is called for this diff --git a/net/proxy/proxy_server.cc b/net/proxy/proxy_server.cc index b0997e0..09c2538 100644 --- a/net/proxy/proxy_server.cc +++ b/net/proxy/proxy_server.cc @@ -219,27 +219,6 @@ ProxyServer::Scheme ProxyServer::GetSchemeFromURI(const std::string& scheme) { return GetSchemeFromURIInternal(scheme.begin(), scheme.end()); } -// TODO(bengr): Use |scheme_| to indicate that this is the data reduction proxy. -#if defined(SPDY_PROXY_AUTH_ORIGIN) -bool ProxyServer::isDataReductionProxy() const { - bool dev_host = false; -#if defined (DATA_REDUCTION_DEV_HOST) - dev_host = host_port_pair_.Equals( - HostPortPair::FromURL(GURL(DATA_REDUCTION_DEV_HOST))); -#endif - return dev_host || host_port_pair_.Equals( - HostPortPair::FromURL(GURL(SPDY_PROXY_AUTH_ORIGIN))); -} - -bool ProxyServer::isDataReductionProxyFallback() const { -#if defined(DATA_REDUCTION_FALLBACK_HOST) - return host_port_pair_.Equals( - HostPortPair::FromURL(GURL(DATA_REDUCTION_FALLBACK_HOST))); -#endif // defined(DATA_REDUCTION_FALLBACK_HOST) - return false; -} -#endif // defined(SPDY_PROXY_AUTH_ORIGIN) - // static ProxyServer ProxyServer::FromSchemeHostAndPort( Scheme scheme, diff --git a/net/proxy/proxy_server.h b/net/proxy/proxy_server.h index 27b8b04..1ff6536 100644 --- a/net/proxy/proxy_server.h +++ b/net/proxy/proxy_server.h @@ -154,14 +154,6 @@ class NET_EXPORT ProxyServer { return host_port_pair_ < other.host_port_pair_; } -#if defined(SPDY_PROXY_AUTH_ORIGIN) - // Returns true if this proxy server is the data reduction proxy or its - // fallback, respectively, as configured in gyp. These functions will return - // false for data reduction proxy servers specified on the command line. - bool isDataReductionProxy() const; - bool isDataReductionProxyFallback() const; -#endif // defined(SPDY_PROXY_AUTH_ORIGIN) - private: // Creates a ProxyServer given a scheme, and host/port string. If parsing the // host/port string fails, the returned instance will be invalid. diff --git a/net/proxy/proxy_service.cc b/net/proxy/proxy_service.cc index a1d634a7..4006110 100644 --- a/net/proxy/proxy_service.cc +++ b/net/proxy/proxy_service.cc @@ -13,8 +13,6 @@ #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop_proxy.h" -#include "base/metrics/histogram.h" -#include "base/metrics/sparse_histogram.h" #include "base/strings/string_util.h" #include "base/thread_task_runner_handle.h" #include "base/values.h" @@ -1197,6 +1195,7 @@ int ProxyService::ReconsiderProxyAfterError(const GURL& url, // want to re-run ResolveProxy in two cases: 1) we have a new config, or 2) a // direct connection failed and we never tried the current config. + DCHECK(result); bool re_resolve = result->config_id_ != config_.id(); if (re_resolve) { @@ -1207,24 +1206,17 @@ int ProxyService::ReconsiderProxyAfterError(const GURL& url, network_delegate, net_log); } -#if defined(SPDY_PROXY_AUTH_ORIGIN) - if (result->proxy_server().isDataReductionProxy()) { - RecordDataReductionProxyBypassInfo( - true, false, result->proxy_server(), NETWORK_ERROR); - RecordDataReductionProxyBypassOnNetworkError( - true, result->proxy_server(), net_error); - } else if (result->proxy_server().isDataReductionProxyFallback()) { - RecordDataReductionProxyBypassInfo( - false, false, result->proxy_server(), NETWORK_ERROR); - RecordDataReductionProxyBypassOnNetworkError( - false, result->proxy_server(), net_error); - } -#endif + DCHECK(!result->is_empty()); + ProxyServer bad_proxy = result->proxy_server(); // We don't have new proxy settings to try, try to fallback to the next proxy // in the list. bool did_fallback = result->Fallback(net_log); + if (network_delegate) { + network_delegate->NotifyProxyFallback(bad_proxy, net_error, did_fallback); + } + // 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; @@ -1459,53 +1451,6 @@ scoped_ptr<ProxyService::PacPollPolicy> return scoped_ptr<PacPollPolicy>(new DefaultPollPolicy()); } -void ProxyService::RecordDataReductionProxyBypassInfo( - bool is_primary, - bool bypass_all, - const ProxyServer& proxy_server, - DataReductionProxyBypassType bypass_type) const { - // Only record UMA if the proxy isn't already on the retry list. - if (proxy_retry_info_.find(proxy_server.ToURI()) != proxy_retry_info_.end()) - return; - - if (bypass_all) { - if (is_primary) { - UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.BlockTypePrimary", - bypass_type, BYPASS_EVENT_TYPE_MAX); - } else { - UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.BlockTypeFallback", - bypass_type, BYPASS_EVENT_TYPE_MAX); - } - } else { - if (is_primary) { - UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.BypassTypePrimary", - bypass_type, BYPASS_EVENT_TYPE_MAX); - } else { - UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.BypassTypeFallback", - bypass_type, BYPASS_EVENT_TYPE_MAX); - } - } -} - -void ProxyService::RecordDataReductionProxyBypassOnNetworkError( - bool is_primary, - const ProxyServer& proxy_server, - int net_error) { - // Only record UMA if the proxy isn't already on the retry list. - if (proxy_retry_info_.find(proxy_server.ToURI()) != proxy_retry_info_.end()) - return; - - if (is_primary) { - UMA_HISTOGRAM_SPARSE_SLOWLY( - "DataReductionProxy.BypassOnNetworkErrorPrimary", - std::abs(net_error)); - return; - } - UMA_HISTOGRAM_SPARSE_SLOWLY( - "DataReductionProxy.BypassOnNetworkErrorFallback", - std::abs(net_error)); -} - void ProxyService::OnProxyConfigChanged( const ProxyConfig& config, ProxyConfigService::ConfigAvailability availability) { diff --git a/net/proxy/proxy_service.h b/net/proxy/proxy_service.h index baca9da..7b3e5d2 100644 --- a/net/proxy/proxy_service.h +++ b/net/proxy/proxy_service.h @@ -273,65 +273,6 @@ class NET_EXPORT ProxyService : public NetworkChangeNotifier::IPAddressObserver, bool quick_check_enabled() const { return quick_check_enabled_; } - // Values of the UMA DataReductionProxy.BypassType{Primary|Fallback} - // and DataReductionProxy.BlockType{Primary|Fallback} histograms. - // This enum must remain synchronized with the enum of the same - // name in metrics/histograms/histograms.xml. - enum DataReductionProxyBypassType { - // Bypass due to explicit instruction for the current request. - // Not yet supported. - CURRENT_BYPASS = 0, - - // Bypass the proxy for less than one minute. - SHORT_BYPASS = 1, - - // Bypass the proxy for one to five minutes. - MEDIUM_BYPASS = 2, - - // Bypass the proxy for more than five minutes. - LONG_BYPASS = 3, - - // Bypass due to a 4xx missing via header. - MISSING_VIA_HEADER_4XX = 4, - - // Bypass due to other missing via header, excluding 4xx errors. - MISSING_VIA_HEADER_OTHER = 5, - - // Bypass due to 407 response from proxy without a challenge. - MALFORMED_407 = 6, - - // Bypass due to a 500 internal server error - STATUS_500_HTTP_INTERNAL_SERVER_ERROR = 7, - - // Bypass because the request URI was too long. - STATUS_502_HTTP_BAD_GATEWAY = 8, - - // Bypass due to a 503 response. - STATUS_503_HTTP_SERVICE_UNAVAILABLE = 9, - - // Bypass due to any network error. - NETWORK_ERROR = 10, - - // This must always be last. - BYPASS_EVENT_TYPE_MAX = 11 - }; - - // Records a |DataReductionProxyBypassEventType| or - // |DataReductionProxyBlockEventType| for either the data reduction - // proxy (|is_primary| is true) or the data reduction proxy fallback. - void RecordDataReductionProxyBypassInfo( - bool is_primary, - bool bypass_all, - const ProxyServer& proxy_server, - DataReductionProxyBypassType block_type) const; - - // Records a net error code that resulted in bypassing the data reduction - // proxy (|is_primary| is true) or the data reduction proxy fallback. - void RecordDataReductionProxyBypassOnNetworkError( - bool is_primary, - const ProxyServer& proxy_server, - int net_error); - private: FRIEND_TEST_ALL_PREFIXES(ProxyServiceTest, UpdateConfigAfterFailedAutodetect); FRIEND_TEST_ALL_PREFIXES(ProxyServiceTest, UpdateConfigFromPACToDirect); diff --git a/net/proxy/proxy_service_unittest.cc b/net/proxy/proxy_service_unittest.cc index 69ab4ce..a2dcf3f 100644 --- a/net/proxy/proxy_service_unittest.cc +++ b/net/proxy/proxy_service_unittest.cc @@ -193,6 +193,48 @@ class TestResolveProxyNetworkDelegate : public NetworkDelegate { bool remove_proxy_; }; +// A test network delegate that exercises the OnProxyFallback callback. +class TestProxyFallbackNetworkDelegate : public NetworkDelegate { + public: + TestProxyFallbackNetworkDelegate() + : on_proxy_fallback_called_(false), + proxy_fallback_net_error_(0), + proxy_did_fallback_(false) { + } + + virtual void OnProxyFallback( + const ProxyServer& proxy_server, + int net_error, + bool did_fallback) OVERRIDE { + proxy_server_ = proxy_server; + proxy_fallback_net_error_ = net_error; + proxy_did_fallback_ = did_fallback; + on_proxy_fallback_called_ = true; + } + + bool on_proxy_fallback_called() const { + return on_proxy_fallback_called_; + } + + const ProxyServer& proxy_server() const { + return proxy_server_; + } + + int proxy_fallback_net_error() const { + return proxy_fallback_net_error_; + } + + bool proxy_did_fallback() const { + return proxy_did_fallback_; + } + + private: + bool on_proxy_fallback_called_; + ProxyServer proxy_server_; + int proxy_fallback_net_error_; + bool proxy_did_fallback_; +}; + } // namespace TEST_F(ProxyServiceTest, Direct) { @@ -462,13 +504,20 @@ TEST_F(ProxyServiceTest, PAC_FailoverWithoutDirect) { // Now, imagine that connecting to foopy:8080 fails: there is nothing // left to fallback to, since our proxy list was NOT terminated by // DIRECT. + TestProxyFallbackNetworkDelegate network_delegate; TestCompletionCallback callback2; + ProxyServer expected_proxy_server = info.proxy_server(); rv = service.ReconsiderProxyAfterError( url, net::LOAD_NORMAL, net::ERR_PROXY_CONNECTION_FAILED, - &info, callback2.callback(), NULL, NULL, BoundNetLog()); + &info, callback2.callback(), NULL, &network_delegate, BoundNetLog()); // ReconsiderProxyAfterError returns error indicating nothing left. EXPECT_EQ(ERR_FAILED, rv); EXPECT_TRUE(info.is_empty()); + EXPECT_TRUE(network_delegate.on_proxy_fallback_called()); + EXPECT_EQ(expected_proxy_server, network_delegate.proxy_server()); + EXPECT_EQ(net::ERR_PROXY_CONNECTION_FAILED, + network_delegate.proxy_fallback_net_error()); + EXPECT_FALSE(network_delegate.proxy_did_fallback()); } // Test that if the execution of the PAC script fails (i.e. javascript runtime @@ -561,6 +610,7 @@ TEST_F(ProxyServiceTest, PAC_FailoverAfterDirect) { EXPECT_TRUE(info.is_direct()); // Fallback 1. + TestProxyFallbackNetworkDelegate network_delegate2; TestCompletionCallback callback2; rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, net::ERR_PROXY_CONNECTION_FAILED, @@ -569,34 +619,57 @@ TEST_F(ProxyServiceTest, PAC_FailoverAfterDirect) { EXPECT_EQ(OK, rv); EXPECT_FALSE(info.is_direct()); EXPECT_EQ("foobar:10", info.proxy_server().ToURI()); + // No network delegate provided. + EXPECT_FALSE(network_delegate2.on_proxy_fallback_called()); // Fallback 2. + TestProxyFallbackNetworkDelegate network_delegate3; + ProxyServer expected_proxy_server3 = info.proxy_server(); TestCompletionCallback callback3; rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, net::ERR_PROXY_CONNECTION_FAILED, &info, callback3.callback(), NULL, - NULL, BoundNetLog()); + &network_delegate3, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_TRUE(info.is_direct()); + EXPECT_TRUE(network_delegate3.on_proxy_fallback_called()); + EXPECT_EQ(expected_proxy_server3, network_delegate3.proxy_server()); + EXPECT_EQ(net::ERR_PROXY_CONNECTION_FAILED, + network_delegate3.proxy_fallback_net_error()); + EXPECT_TRUE(network_delegate3.proxy_did_fallback()); // Fallback 3. + TestProxyFallbackNetworkDelegate network_delegate4; + ProxyServer expected_proxy_server4 = info.proxy_server(); TestCompletionCallback callback4; rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, net::ERR_PROXY_CONNECTION_FAILED, &info, callback4.callback(), NULL, - NULL, BoundNetLog()); + &network_delegate4, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_FALSE(info.is_direct()); EXPECT_EQ("foobar:20", info.proxy_server().ToURI()); + EXPECT_TRUE(network_delegate4.on_proxy_fallback_called()); + EXPECT_EQ(expected_proxy_server4, network_delegate4.proxy_server()); + EXPECT_EQ(net::ERR_PROXY_CONNECTION_FAILED, + network_delegate4.proxy_fallback_net_error()); + EXPECT_TRUE(network_delegate4.proxy_did_fallback()); // Fallback 4 -- Nothing to fall back to! + TestProxyFallbackNetworkDelegate network_delegate5; + ProxyServer expected_proxy_server5 = info.proxy_server(); TestCompletionCallback callback5; rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, net::ERR_PROXY_CONNECTION_FAILED, &info, callback5.callback(), NULL, - NULL, BoundNetLog()); + &network_delegate5, BoundNetLog()); EXPECT_EQ(ERR_FAILED, rv); EXPECT_TRUE(info.is_empty()); + EXPECT_TRUE(network_delegate5.on_proxy_fallback_called()); + EXPECT_EQ(expected_proxy_server5, network_delegate5.proxy_server()); + EXPECT_EQ(net::ERR_PROXY_CONNECTION_FAILED, + network_delegate5.proxy_fallback_net_error()); + EXPECT_FALSE(network_delegate5.proxy_did_fallback()); } TEST_F(ProxyServiceTest, PAC_ConfigSourcePropagates) { |