diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/http/http_response_headers.cc | 7 | ||||
-rw-r--r-- | net/http/http_response_headers_unittest.cc | 11 | ||||
-rw-r--r-- | net/http/http_stream_factory_impl_job.cc | 3 | ||||
-rw-r--r-- | net/proxy/proxy_service.cc | 33 | ||||
-rw-r--r-- | net/proxy/proxy_service.h | 22 | ||||
-rw-r--r-- | net/proxy/proxy_service_unittest.cc | 57 |
6 files changed, 107 insertions, 26 deletions
diff --git a/net/http/http_response_headers.cc b/net/http/http_response_headers.cc index 7ecf37a..f07fbaf 100644 --- a/net/http/http_response_headers.cc +++ b/net/http/http_response_headers.cc @@ -1504,6 +1504,13 @@ HttpResponseHeaders::GetDataReductionProxyBypassEventType( // response is to minimize information transfer, a sender in general // should not generate representation metadata other than Cache-Control, // Content-Location, Date, ETag, Expires, and Vary. + + // The proxy Via header might also not be present in a 4xx response. + // Separate this case from other responses that are missing the header. + if (response_code() >= HTTP_BAD_REQUEST && + response_code() < HTTP_INTERNAL_SERVER_ERROR) { + return ProxyService::PROXY_4XX_BYPASS; + } return ProxyService::MISSING_VIA_HEADER; } // There is no bypass event. diff --git a/net/http/http_response_headers_unittest.cc b/net/http/http_response_headers_unittest.cc index c9c8c46..b097a18 100644 --- a/net/http/http_response_headers_unittest.cc +++ b/net/http/http_response_headers_unittest.cc @@ -2245,6 +2245,17 @@ TEST(HttpResponseHeadersTest, GetDataReductionProxyBypassEventType) { "Chrome-Proxy: bypass=1799\n", net::ProxyService::SHORT_BYPASS, }, + { "HTTP/1.1 502 Bad Gateway\n" + "Chrome-Proxy: bypass=1799\n", + net::ProxyService::SHORT_BYPASS, + }, + { "HTTP/1.1 414 Request-URI Too Long\n", + net::ProxyService::PROXY_4XX_BYPASS, + }, + { "HTTP/1.1 414 Request-URI Too Long\n" + "Via: 1.1 Chrome-Compression-Proxy\n", + net::ProxyService::BYPASS_EVENT_TYPE_MAX, + } }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { std::string headers(tests[i].headers); diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc index 647172d..93b9ef2 100644 --- a/net/http/http_stream_factory_impl_job.cc +++ b/net/http/http_stream_factory_impl_job.cc @@ -1317,7 +1317,8 @@ int HttpStreamFactoryImpl::Job::ReconsiderProxyAfterError(int error) { } int rv = session_->proxy_service()->ReconsiderProxyAfterError( - request_info_.url, &proxy_info_, io_callback_, &pac_request_, net_log_); + request_info_.url, error, &proxy_info_, io_callback_, &pac_request_, + net_log_); if (rv == OK || rv == ERR_IO_PENDING) { // If the error was during connection setup, there is no socket to // disconnect. diff --git a/net/proxy/proxy_service.cc b/net/proxy/proxy_service.cc index b2fcc0e..b70ea2c 100644 --- a/net/proxy/proxy_service.cc +++ b/net/proxy/proxy_service.cc @@ -47,6 +47,7 @@ #if defined(SPDY_PROXY_AUTH_ORIGIN) #include "base/metrics/histogram.h" +#include "base/metrics/sparse_histogram.h" #endif using base::TimeDelta; @@ -1168,6 +1169,7 @@ void ProxyService::OnInitProxyResolverComplete(int result) { } int ProxyService::ReconsiderProxyAfterError(const GURL& url, + int net_error, ProxyInfo* result, const CompletionCallback& callback, PacRequest** pac_request, @@ -1191,9 +1193,13 @@ int ProxyService::ReconsiderProxyAfterError(const GURL& url, if (result->proxy_server().isDataReductionProxy()) { RecordDataReductionProxyBypassInfo( true, result->proxy_server(), ERROR_BYPASS); + RecordDataReductionProxyBypassOnNetworkError( + true, result->proxy_server(), net_error); } else if (result->proxy_server().isDataReductionProxyFallback()) { RecordDataReductionProxyBypassInfo( false, result->proxy_server(), ERROR_BYPASS); + RecordDataReductionProxyBypassOnNetworkError( + false, result->proxy_server(), net_error); } #endif @@ -1439,6 +1445,25 @@ void ProxyService::RecordDataReductionProxyBypassInfo( 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)); +} #endif // defined(SPDY_PROXY_AUTH_ORIGIN) void ProxyService::OnProxyConfigChanged( @@ -1581,13 +1606,14 @@ int SyncProxyServiceHelper::ResolveProxy(const GURL& url, } int SyncProxyServiceHelper::ReconsiderProxyAfterError( - const GURL& url, ProxyInfo* proxy_info, const BoundNetLog& net_log) { + const GURL& url, int net_error, ProxyInfo* proxy_info, + const BoundNetLog& net_log) { DCHECK(io_message_loop_ != base::MessageLoop::current()); io_message_loop_->PostTask( FROM_HERE, base::Bind(&SyncProxyServiceHelper::StartAsyncReconsider, this, url, - net_log)); + net_error, net_log)); event_.Wait(); @@ -1609,9 +1635,10 @@ void SyncProxyServiceHelper::StartAsyncResolve(const GURL& url, } void SyncProxyServiceHelper::StartAsyncReconsider(const GURL& url, + int net_error, const BoundNetLog& net_log) { result_ = proxy_service_->ReconsiderProxyAfterError( - url, &proxy_info_, callback_, NULL, net_log); + url, net_error, &proxy_info_, callback_, NULL, net_log); if (result_ != net::ERR_IO_PENDING) { OnCompletion(result_); } diff --git a/net/proxy/proxy_service.h b/net/proxy/proxy_service.h index 36b4589..6f85568 100644 --- a/net/proxy/proxy_service.h +++ b/net/proxy/proxy_service.h @@ -132,8 +132,10 @@ class NET_EXPORT ProxyService : public NetworkChangeNotifier::IPAddressObserver, // This method is called after a failure to connect or resolve a host name. // It gives the proxy service an opportunity to reconsider the proxy to use. // The |results| parameter contains the results returned by an earlier call - // to ResolveProxy. The semantics of this call are otherwise similar to - // ResolveProxy. + // to ResolveProxy. The |net_error| parameter contains the network error + // code associated with the failure. See "net/base/net_error_list.h" for a + // list of possible values. The semantics of this call are otherwise + // similar to ResolveProxy. // // NULL can be passed for |pac_request| if the caller will not need to // cancel the request. @@ -142,6 +144,7 @@ class NET_EXPORT ProxyService : public NetworkChangeNotifier::IPAddressObserver, // // Profiling information for the request is saved to |net_log| if non-NULL. int ReconsiderProxyAfterError(const GURL& url, + int net_error, ProxyInfo* results, const CompletionCallback& callback, PacRequest** pac_request, @@ -286,6 +289,9 @@ class NET_EXPORT ProxyService : public NetworkChangeNotifier::IPAddressObserver, // Bypass the proxy because responses appear not to be coming via it. MISSING_VIA_HEADER, + // Bypass the proxy because the proxy, not the origin, sent a 4xx response. + PROXY_4XX_BYPASS, + // This must always be last. BYPASS_EVENT_TYPE_MAX }; @@ -296,6 +302,13 @@ class NET_EXPORT ProxyService : public NetworkChangeNotifier::IPAddressObserver, bool is_primary, const ProxyServer& proxy_server, DataReductionProxyBypassEventType bypass_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); #endif private: @@ -458,6 +471,7 @@ class NET_EXPORT SyncProxyServiceHelper ProxyInfo* proxy_info, const BoundNetLog& net_log); int ReconsiderProxyAfterError(const GURL& url, + int net_error, ProxyInfo* proxy_info, const BoundNetLog& net_log); @@ -467,7 +481,9 @@ class NET_EXPORT SyncProxyServiceHelper virtual ~SyncProxyServiceHelper(); void StartAsyncResolve(const GURL& url, const BoundNetLog& net_log); - void StartAsyncReconsider(const GURL& url, const BoundNetLog& net_log); + void StartAsyncReconsider(const GURL& url, + int net_error, + const BoundNetLog& net_log); void OnCompletion(int result); diff --git a/net/proxy/proxy_service_unittest.cc b/net/proxy/proxy_service_unittest.cc index bad5afd..cc245b6 100644 --- a/net/proxy/proxy_service_unittest.cc +++ b/net/proxy/proxy_service_unittest.cc @@ -315,7 +315,8 @@ TEST_F(ProxyServiceTest, PAC_FailoverWithoutDirect) { // DIRECT. TestCompletionCallback callback2; rv = service.ReconsiderProxyAfterError( - url, &info, callback2.callback(), NULL, BoundNetLog()); + url, net::ERR_PROXY_CONNECTION_FAILED, + &info, callback2.callback(), NULL, BoundNetLog()); // ReconsiderProxyAfterError returns error indicating nothing left. EXPECT_EQ(ERR_FAILED, rv); EXPECT_TRUE(info.is_empty()); @@ -410,7 +411,8 @@ TEST_F(ProxyServiceTest, PAC_FailoverAfterDirect) { // Fallback 1. TestCompletionCallback callback2; - rv = service.ReconsiderProxyAfterError(url, &info, callback2.callback(), NULL, + rv = service.ReconsiderProxyAfterError(url, net::ERR_PROXY_CONNECTION_FAILED, + &info, callback2.callback(), NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_FALSE(info.is_direct()); @@ -418,14 +420,16 @@ TEST_F(ProxyServiceTest, PAC_FailoverAfterDirect) { // Fallback 2. TestCompletionCallback callback3; - rv = service.ReconsiderProxyAfterError(url, &info, callback3.callback(), NULL, + rv = service.ReconsiderProxyAfterError(url, net::ERR_PROXY_CONNECTION_FAILED, + &info, callback3.callback(), NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_TRUE(info.is_direct()); // Fallback 3. TestCompletionCallback callback4; - rv = service.ReconsiderProxyAfterError(url, &info, callback4.callback(), NULL, + rv = service.ReconsiderProxyAfterError(url, net::ERR_PROXY_CONNECTION_FAILED, + &info, callback4.callback(), NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_FALSE(info.is_direct()); @@ -433,7 +437,8 @@ TEST_F(ProxyServiceTest, PAC_FailoverAfterDirect) { // Fallback 4 -- Nothing to fall back to! TestCompletionCallback callback5; - rv = service.ReconsiderProxyAfterError(url, &info, callback5.callback(), NULL, + rv = service.ReconsiderProxyAfterError(url, net::ERR_PROXY_CONNECTION_FAILED, + &info, callback5.callback(), NULL, BoundNetLog()); EXPECT_EQ(ERR_FAILED, rv); EXPECT_TRUE(info.is_empty()); @@ -728,7 +733,8 @@ TEST_F(ProxyServiceTest, ProxyFallback) { // Fake an error on the proxy. TestCompletionCallback callback2; - rv = service.ReconsiderProxyAfterError(url, &info, callback2.callback(), NULL, + rv = service.ReconsiderProxyAfterError(url, net::ERR_PROXY_CONNECTION_FAILED, + &info, callback2.callback(), NULL, BoundNetLog()); EXPECT_EQ(OK, rv); @@ -770,7 +776,8 @@ TEST_F(ProxyServiceTest, ProxyFallback) { // We fake another error. It should now try the third one. TestCompletionCallback callback4; - rv = service.ReconsiderProxyAfterError(url, &info, callback4.callback(), NULL, + rv = service.ReconsiderProxyAfterError(url, net::ERR_PROXY_CONNECTION_FAILED, + &info, callback4.callback(), NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); @@ -779,7 +786,8 @@ TEST_F(ProxyServiceTest, ProxyFallback) { // proxy servers we thought were valid; next we try the proxy server // that was in our bad proxies map (foopy1:8080). TestCompletionCallback callback5; - rv = service.ReconsiderProxyAfterError(url, &info, callback5.callback(), NULL, + rv = service.ReconsiderProxyAfterError(url, net::ERR_PROXY_CONNECTION_FAILED, + &info, callback5.callback(), NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); @@ -787,7 +795,8 @@ TEST_F(ProxyServiceTest, ProxyFallback) { // Fake another error, the last proxy is gone, the list should now be empty, // so there is nothing left to try. TestCompletionCallback callback6; - rv = service.ReconsiderProxyAfterError(url, &info, callback6.callback(), NULL, + rv = service.ReconsiderProxyAfterError(url, net::ERR_PROXY_CONNECTION_FAILED, + &info, callback6.callback(), NULL, BoundNetLog()); EXPECT_EQ(ERR_FAILED, rv); EXPECT_FALSE(info.is_direct()); @@ -861,7 +870,8 @@ TEST_F(ProxyServiceTest, ProxyFallbackToDirect) { // Fake an error on the proxy. TestCompletionCallback callback2; - rv = service.ReconsiderProxyAfterError(url, &info, callback2.callback(), NULL, + rv = service.ReconsiderProxyAfterError(url, net::ERR_PROXY_CONNECTION_FAILED, + &info, callback2.callback(), NULL, BoundNetLog()); EXPECT_EQ(OK, rv); @@ -870,7 +880,8 @@ TEST_F(ProxyServiceTest, ProxyFallbackToDirect) { // Fake an error on this proxy as well. TestCompletionCallback callback3; - rv = service.ReconsiderProxyAfterError(url, &info, callback3.callback(), NULL, + rv = service.ReconsiderProxyAfterError(url, net::ERR_PROXY_CONNECTION_FAILED, + &info, callback3.callback(), NULL, BoundNetLog()); EXPECT_EQ(OK, rv); @@ -883,7 +894,8 @@ TEST_F(ProxyServiceTest, ProxyFallbackToDirect) { // Now we tell the proxy service that even DIRECT failed. TestCompletionCallback callback4; - rv = service.ReconsiderProxyAfterError(url, &info, callback4.callback(), NULL, + rv = service.ReconsiderProxyAfterError(url, net::ERR_PROXY_CONNECTION_FAILED, + &info, callback4.callback(), NULL, BoundNetLog()); // There was nothing left to try after DIRECT, so we are out of // choices. @@ -931,7 +943,8 @@ TEST_F(ProxyServiceTest, ProxyFallback_NewSettings) { ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy-new/proxy.pac"))); TestCompletionCallback callback2; - rv = service.ReconsiderProxyAfterError(url, &info, callback2.callback(), NULL, + rv = service.ReconsiderProxyAfterError(url, net::ERR_PROXY_CONNECTION_FAILED, + &info, callback2.callback(), NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -952,7 +965,8 @@ TEST_F(ProxyServiceTest, ProxyFallback_NewSettings) { // We fake another error. It should now ignore the first one. TestCompletionCallback callback3; - rv = service.ReconsiderProxyAfterError(url, &info, callback3.callback(), NULL, + rv = service.ReconsiderProxyAfterError(url, net::ERR_PROXY_CONNECTION_FAILED, + &info, callback3.callback(), NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); @@ -964,7 +978,8 @@ TEST_F(ProxyServiceTest, ProxyFallback_NewSettings) { // We fake another error. It should go back to the first proxy. TestCompletionCallback callback4; - rv = service.ReconsiderProxyAfterError(url, &info, callback4.callback(), NULL, + rv = service.ReconsiderProxyAfterError(url, net::ERR_PROXY_CONNECTION_FAILED, + &info, callback4.callback(), NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -1023,7 +1038,8 @@ TEST_F(ProxyServiceTest, ProxyFallback_BadConfig) { // Fake a proxy error. TestCompletionCallback callback2; - rv = service.ReconsiderProxyAfterError(url, &info, callback2.callback(), NULL, + rv = service.ReconsiderProxyAfterError(url, net::ERR_PROXY_CONNECTION_FAILED, + &info, callback2.callback(), NULL, BoundNetLog()); EXPECT_EQ(OK, rv); @@ -1055,7 +1071,8 @@ TEST_F(ProxyServiceTest, ProxyFallback_BadConfig) { // "just work" the next time we call it. ProxyInfo info3; TestCompletionCallback callback4; - rv = service.ReconsiderProxyAfterError(url, &info3, callback4.callback(), + rv = service.ReconsiderProxyAfterError(url, net::ERR_PROXY_CONNECTION_FAILED, + &info3, callback4.callback(), NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -1116,7 +1133,8 @@ TEST_F(ProxyServiceTest, ProxyFallback_BadConfigMandatory) { // Fake a proxy error. TestCompletionCallback callback2; - rv = service.ReconsiderProxyAfterError(url, &info, callback2.callback(), NULL, + rv = service.ReconsiderProxyAfterError(url, net::ERR_PROXY_CONNECTION_FAILED, + &info, callback2.callback(), NULL, BoundNetLog()); EXPECT_EQ(OK, rv); @@ -1149,7 +1167,8 @@ TEST_F(ProxyServiceTest, ProxyFallback_BadConfigMandatory) { // "just work" the next time we call it. ProxyInfo info3; TestCompletionCallback callback4; - rv = service.ReconsiderProxyAfterError(url, &info3, callback4.callback(), + rv = service.ReconsiderProxyAfterError(url, net::ERR_PROXY_CONNECTION_FAILED, + &info3, callback4.callback(), NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); |