diff options
13 files changed, 432 insertions, 54 deletions
diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc index 093139d..ca6c04a 100644 --- a/chrome/browser/net/chrome_network_delegate.cc +++ b/chrome/browser/net/chrome_network_delegate.cc @@ -582,11 +582,12 @@ void ChromeNetworkDelegate::OnCompleted(net::URLRequest* request, RecordContentLengthHistograms(received_content_length, original_content_length, freshness_lifetime); + if (data_reduction_proxy_enabled_ && data_reduction_proxy_usage_stats_ && !proxy_config_getter_.is_null()) { - data_reduction_proxy_usage_stats_->RecordBypassedBytesHistograms( - *request, + data_reduction_proxy_usage_stats_->RecordBytesHistograms( + request, *data_reduction_proxy_enabled_, proxy_config_getter_.Run()); } diff --git a/components/data_reduction_proxy.gypi b/components/data_reduction_proxy.gypi index bc0f00c..0fa2bab 100644 --- a/components/data_reduction_proxy.gypi +++ b/components/data_reduction_proxy.gypi @@ -89,6 +89,8 @@ 'data_reduction_proxy/browser/data_reduction_proxy_params_test_utils.h', 'data_reduction_proxy/browser/data_reduction_proxy_settings_test_utils.cc', 'data_reduction_proxy/browser/data_reduction_proxy_settings_test_utils.h', + 'data_reduction_proxy/common/data_reduction_proxy_headers_test_utils.cc', + 'data_reduction_proxy/common/data_reduction_proxy_headers_test_utils.h', ], }, { 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 565621d..b638c2c 100644 --- a/components/data_reduction_proxy/browser/data_reduction_proxy_protocol.cc +++ b/components/data_reduction_proxy/browser/data_reduction_proxy_protocol.cc @@ -65,6 +65,12 @@ bool MaybeBypassProxyAndPrepareToRetry( if (data_reduction_proxy_type_info.proxy_servers.first.is_empty()) return false; + // At this point, the response is expected to have the data reduction proxy + // via header, so detect and report cases where the via header is missing. + DataReductionProxyUsageStats::DetectAndRecordMissingViaHeaderResponseCode( + !data_reduction_proxy_type_info.proxy_servers.second.is_empty(), + original_response_headers); + DataReductionProxyTamperDetection::DetectAndReport( original_response_headers, data_reduction_proxy_type_info.proxy_servers.first.SchemeIsSecure()); 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 c4c13ee..d54aa86 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 @@ -13,6 +13,7 @@ #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 "components/data_reduction_proxy/common/data_reduction_proxy_headers_test_utils.h" #include "net/base/completion_callback.h" #include "net/base/host_port_pair.h" #include "net/base/load_flags.h" @@ -39,18 +40,6 @@ using net::URLRequest; using net::TestURLRequestContext; -namespace { -// Transform "normal"-looking headers (\n-separated) to the appropriate -// input format for ParseRawHeaders (\0-separated). -void HeadersToRaw(std::string* headers) { - std::replace(headers->begin(), headers->end(), '\n', '\0'); - if (!headers->empty()) - *headers += '\0'; -} - -} // namespace - - namespace data_reduction_proxy { // A test network delegate that exercises the bypass logic of the data diff --git a/components/data_reduction_proxy/browser/data_reduction_proxy_settings_test_utils.cc b/components/data_reduction_proxy/browser/data_reduction_proxy_settings_test_utils.cc index de7d983..e2b1d68 100644 --- a/components/data_reduction_proxy/browser/data_reduction_proxy_settings_test_utils.cc +++ b/components/data_reduction_proxy/browser/data_reduction_proxy_settings_test_utils.cc @@ -14,6 +14,7 @@ #include "base/time/time.h" #include "components/data_reduction_proxy/browser/data_reduction_proxy_prefs.h" #include "components/data_reduction_proxy/browser/data_reduction_proxy_statistics_prefs.h" +#include "components/data_reduction_proxy/common/data_reduction_proxy_headers_test_utils.h" #include "components/data_reduction_proxy/common/data_reduction_proxy_pref_names.h" #include "components/data_reduction_proxy/common/data_reduction_proxy_switches.h" @@ -31,14 +32,6 @@ const char kProxy[] = "proxy"; namespace data_reduction_proxy { -// Transform "normal"-looking headers (\n-separated) to the appropriate -// input format for ParseRawHeaders (\0-separated). -void HeadersToRaw(std::string* headers) { - std::replace(headers->begin(), headers->end(), '\n', '\0'); - if (!headers->empty()) - *headers += '\0'; -} - ProbeURLFetchResult FetchResult(bool enabled, bool success) { if (enabled) { if (success) diff --git a/components/data_reduction_proxy/browser/data_reduction_proxy_tamper_detection_unittest.cc b/components/data_reduction_proxy/browser/data_reduction_proxy_tamper_detection_unittest.cc index 6c28806..6f48752 100644 --- a/components/data_reduction_proxy/browser/data_reduction_proxy_tamper_detection_unittest.cc +++ b/components/data_reduction_proxy/browser/data_reduction_proxy_tamper_detection_unittest.cc @@ -15,6 +15,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "components/data_reduction_proxy/common/data_reduction_proxy_headers.h" +#include "components/data_reduction_proxy/common/data_reduction_proxy_headers_test_utils.h" #include "net/http/http_response_headers.h" #include "testing/gtest/include/gtest/gtest.h" @@ -25,12 +26,6 @@ namespace { -void HeadersToRaw(std::string* headers) { - std::replace(headers->begin(), headers->end(), '\n', '\0'); - if (!headers->empty()) - *headers += '\0'; -} - // Calcuates MD5 hash value for a string and then base64 encode it. Testcases // contain expected fingerprint in plain text, which needs to be encoded before // comparison. 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 adda1d3..a7426f5 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 @@ -9,8 +9,11 @@ #include "base/message_loop/message_loop_proxy.h" #include "base/metrics/histogram.h" #include "base/metrics/sparse_histogram.h" +#include "base/prefs/pref_member.h" #include "components/data_reduction_proxy/common/data_reduction_proxy_headers.h" #include "net/base/net_errors.h" +#include "net/http/http_response_headers.h" +#include "net/http/http_status_code.h" #include "net/proxy/proxy_retry_info.h" #include "net/proxy/proxy_server.h" #include "net/proxy/proxy_service.h" @@ -76,6 +79,26 @@ void DataReductionProxyUsageStats::RecordDataReductionProxyBypassInfo( } } +// static +void DataReductionProxyUsageStats::DetectAndRecordMissingViaHeaderResponseCode( + bool is_primary, + const net::HttpResponseHeaders* headers) { + if (HasDataReductionProxyViaHeader(headers, NULL)) { + // The data reduction proxy via header is present, so don't record anything. + return; + } + + if (is_primary) { + UMA_HISTOGRAM_SPARSE_SLOWLY( + "DataReductionProxy.MissingViaHeader.ResponseCode.Primary", + headers->response_code()); + } else { + UMA_HISTOGRAM_SPARSE_SLOWLY( + "DataReductionProxy.MissingViaHeader.ResponseCode.Fallback", + headers->response_code()); + } +} + DataReductionProxyUsageStats::DataReductionProxyUsageStats( DataReductionProxyParams* params, const scoped_refptr<MessageLoopProxy>& ui_thread_proxy) @@ -145,22 +168,31 @@ void DataReductionProxyUsageStats::SetBypassType( triggering_request_ = true; } +void DataReductionProxyUsageStats::RecordBytesHistograms( + net::URLRequest* request, + const BooleanPrefMember& data_reduction_proxy_enabled, + const net::ProxyConfig& data_reduction_proxy_config) { + RecordBypassedBytesHistograms(request, data_reduction_proxy_enabled, + data_reduction_proxy_config); + RecordMissingViaHeaderBytes(request); +} + void DataReductionProxyUsageStats::RecordBypassedBytesHistograms( - net::URLRequest& request, + net::URLRequest* request, const BooleanPrefMember& data_reduction_proxy_enabled, const net::ProxyConfig& data_reduction_proxy_config) { - int64 content_length = request.received_response_content_length(); + int64 content_length = request->received_response_content_length(); if (data_reduction_proxy_enabled.GetValue() && !data_reduction_proxy_config.Equals( - request.context()->proxy_service()->config())) { + request->context()->proxy_service()->config())) { RecordBypassedBytes(last_bypass_type_, DataReductionProxyUsageStats::MANAGED_PROXY_CONFIG, content_length); return; } - if (data_reduction_proxy_params_->WasDataReductionProxyUsed(&request, NULL)) { + if (data_reduction_proxy_params_->WasDataReductionProxyUsed(request, NULL)) { RecordBypassedBytes(last_bypass_type_, DataReductionProxyUsageStats::NOT_BYPASSED, content_length); @@ -168,7 +200,7 @@ void DataReductionProxyUsageStats::RecordBypassedBytesHistograms( } if (data_reduction_proxy_enabled.GetValue() && - request.url().SchemeIs(url::kHttpsScheme)) { + request->url().SchemeIs(url::kHttpsScheme)) { RecordBypassedBytes(last_bypass_type_, DataReductionProxyUsageStats::SSL, content_length); @@ -177,7 +209,7 @@ void DataReductionProxyUsageStats::RecordBypassedBytesHistograms( if (data_reduction_proxy_enabled.GetValue() && data_reduction_proxy_params_->IsBypassedByDataReductionProxyLocalRules( - request, data_reduction_proxy_config)) { + *request, data_reduction_proxy_config)) { RecordBypassedBytes(last_bypass_type_, DataReductionProxyUsageStats::LOCAL_BYPASS_RULES, content_length); @@ -191,7 +223,7 @@ void DataReductionProxyUsageStats::RecordBypassedBytesHistograms( last_bypass_type_ == BYPASS_EVENT_TYPE_MEDIUM || last_bypass_type_ == BYPASS_EVENT_TYPE_LONG)) { std::string mime_type; - request.GetMimeType(&mime_type); + request->GetMimeType(&mime_type); // MIME types are named by <media-type>/<subtype>. Check to see if the // media type is audio or video. Only record when triggered by short bypass, // there isn't an audio or video bucket for medium or long bypasses. @@ -218,7 +250,7 @@ void DataReductionProxyUsageStats::RecordBypassedBytesHistograms( return; } - if (data_reduction_proxy_params_->AreDataReductionProxiesBypassed(request, + if (data_reduction_proxy_params_->AreDataReductionProxiesBypassed(*request, NULL)) { RecordBypassedBytes(last_bypass_type_, DataReductionProxyUsageStats::NETWORK_ERROR, @@ -378,6 +410,30 @@ void DataReductionProxyUsageStats::RecordBypassedBytes( } } +void DataReductionProxyUsageStats::RecordMissingViaHeaderBytes( + URLRequest* request) { + // Responses that were served from cache should have been filtered out + // already. + DCHECK(!request->was_cached()); + + if (!data_reduction_proxy_params_->WasDataReductionProxyUsed(request, NULL) || + HasDataReductionProxyViaHeader(request->response_headers(), NULL)) { + // Only track requests that used the data reduction proxy and had responses + // that were missing the data reduction proxy via header. + return; + } + + if (request->GetResponseCode() >= net::HTTP_BAD_REQUEST && + request->GetResponseCode() < net::HTTP_INTERNAL_SERVER_ERROR) { + // Track 4xx responses that are missing via headers separately. + UMA_HISTOGRAM_COUNTS("DataReductionProxy.MissingViaHeader.Bytes.4xx", + request->received_response_content_length()); + } else { + UMA_HISTOGRAM_COUNTS("DataReductionProxy.MissingViaHeader.Bytes.Other", + request->received_response_content_length()); + } +} + } // namespace data_reduction_proxy 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 9ab5fef..b56abc6 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 @@ -16,6 +16,8 @@ #include "net/url_request/url_request.h" namespace net { +class HttpResponseHeaders; +class ProxyConfig; class ProxyServer; } @@ -33,6 +35,13 @@ class DataReductionProxyUsageStats const net::ProxyServer& proxy_server, DataReductionProxyBypassType bypass_type); + // For the given response |headers| that are expected to include the data + // reduction proxy via header, records response code UMA if the data reduction + // proxy via header is not present. + static void DetectAndRecordMissingViaHeaderResponseCode( + bool is_primary, + const net::HttpResponseHeaders* headers); + // MessageLoopProxy instance is owned by io_thread. |params| outlives // this class instance. DataReductionProxyUsageStats( @@ -56,12 +65,10 @@ class DataReductionProxyUsageStats // cause the current bypass. void SetBypassType(DataReductionProxyBypassType type); - // Given |data_reduction_proxy_enabled|, a |request|, and the - // |data_reduction_proxy_config| records the number of bypassed bytes for that - // |request| into UMAs based on bypass type. |data_reduction_proxy_enabled| - // tells us the state of the kDataReductionProxyEnabled preference. - void RecordBypassedBytesHistograms( - net::URLRequest& request, + // Records all the data reduction proxy bytes-related histograms for the + // completed URLRequest |request|. + void RecordBytesHistograms( + net::URLRequest* request, const BooleanPrefMember& data_reduction_proxy_enabled, const net::ProxyConfig& data_reduction_proxy_config); @@ -71,6 +78,10 @@ class DataReductionProxyUsageStats int net_error); private: + friend class DataReductionProxyUsageStatsTest; + FRIEND_TEST_ALL_PREFIXES(DataReductionProxyUsageStatsTest, + RecordMissingViaHeaderBytes); + enum BypassedBytesType { NOT_BYPASSED = 0, /* Not bypassed. */ SSL, /* Bypass due to SSL. */ @@ -82,6 +93,20 @@ class DataReductionProxyUsageStats BYPASSED_BYTES_TYPE_MAX /* This must always be last.*/ }; + // Given |data_reduction_proxy_enabled|, a |request|, and the + // |data_reduction_proxy_config| records the number of bypassed bytes for that + // |request| into UMAs based on bypass type. |data_reduction_proxy_enabled| + // tells us the state of the kDataReductionProxyEnabled preference. + void RecordBypassedBytesHistograms( + net::URLRequest* request, + const BooleanPrefMember& data_reduction_proxy_enabled, + const net::ProxyConfig& data_reduction_proxy_config); + + // Records UMA of the number of response bytes of responses that are expected + // to have the data reduction proxy via header, but where the data reduction + // proxy via header is not present. + void RecordMissingViaHeaderBytes(net::URLRequest* request); + // NetworkChangeNotifier::NetworkChangeObserver: virtual void OnNetworkChanged( net::NetworkChangeNotifier::ConnectionType type) OVERRIDE; 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 2ae4986..b6100fa 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 @@ -4,12 +4,21 @@ #include "components/data_reduction_proxy/browser/data_reduction_proxy_usage_stats.h" +#include <string> + #include "base/bind.h" #include "base/memory/scoped_ptr.h" +#include "base/metrics/histogram.h" +#include "base/test/histogram_tester.h" +#include "components/data_reduction_proxy/common/data_reduction_proxy_headers_test_utils.h" #include "net/base/host_port_pair.h" #include "net/base/request_priority.h" +#include "net/http/http_response_headers.h" +#include "net/http/http_util.h" #include "net/url_request/url_request.h" +#include "net/url_request/url_request_job_factory_impl.h" #include "net/url_request/url_request_status.h" +#include "net/url_request/url_request_test_job.h" #include "net/url_request/url_request_test_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -49,6 +58,14 @@ class DataReductionProxyUsageStatsTest : public testing::Test { context_(true), unavailable_(false) { context_.Init(); + + // The |test_job_factory_| takes ownership of the interceptor. + test_job_interceptor_ = new net::TestJobInterceptor(); + EXPECT_TRUE(test_job_factory_.SetProtocolHandler(url::kHttpScheme, + test_job_interceptor_)); + + context_.set_job_factory(&test_job_factory_); + mock_url_request_ = context_.CreateRequest(GURL(), net::IDLE, &delegate_, NULL); } @@ -57,6 +74,28 @@ class DataReductionProxyUsageStatsTest : public testing::Test { unavailable_ = unavailable; } + scoped_ptr<net::URLRequest> CreateURLRequestWithResponseHeaders( + const GURL& url, + const std::string& raw_response_headers) { + scoped_ptr<net::URLRequest> fake_request = context_.CreateRequest( + url, net::IDLE, &delegate_, NULL); + + // Create a test job that will fill in the given response headers for the + // |fake_request|. + scoped_refptr<net::URLRequestTestJob> test_job( + new net::URLRequestTestJob(fake_request.get(), + context_.network_delegate(), + raw_response_headers, std::string(), true)); + + // Configure the interceptor to use the test job to handle the next request. + test_job_interceptor_->set_main_intercept_job(test_job.get()); + fake_request->Start(); + base::MessageLoop::current()->RunUntilIdle(); + + EXPECT_TRUE(fake_request->response_headers() != NULL); + return fake_request.Pass(); + } + // Required for base::MessageLoopProxy::current(). base::MessageLoopForUI loop_; base::MessageLoopProxy* loop_proxy_; @@ -66,6 +105,9 @@ class DataReductionProxyUsageStatsTest : public testing::Test { net::TestDelegate delegate_; DataReductionProxyParamsMock mock_params_; scoped_ptr<net::URLRequest> mock_url_request_; + // |test_job_interceptor_| is owned by |test_job_factory_|. + net::TestJobInterceptor* test_job_interceptor_; + net::URLRequestJobFactoryImpl test_job_factory_; bool unavailable_; }; @@ -187,4 +229,215 @@ TEST_F(DataReductionProxyUsageStatsTest, ProxyReachableThenUnreachable) { EXPECT_TRUE(unavailable_); } +TEST_F(DataReductionProxyUsageStatsTest, + DetectAndRecordMissingViaHeaderResponseCode) { + const std::string kPrimaryHistogramName = + "DataReductionProxy.MissingViaHeader.ResponseCode.Primary"; + const std::string kFallbackHistogramName = + "DataReductionProxy.MissingViaHeader.ResponseCode.Fallback"; + + struct TestCase { + bool is_primary; + const char* headers; + int expected_primary_sample; // -1 indicates no expected sample. + int expected_fallback_sample; // -1 indicates no expected sample. + }; + const TestCase test_cases[] = { + { + true, + "HTTP/1.1 200 OK\n" + "Via: 1.1 Chrome-Compression-Proxy\n", + -1, + -1 + }, + { + false, + "HTTP/1.1 200 OK\n" + "Via: 1.1 Chrome-Compression-Proxy\n", + -1, + -1 + }, + { + true, + "HTTP/1.1 200 OK\n", + 200, + -1 + }, + { + false, + "HTTP/1.1 200 OK\n", + -1, + 200 + }, + { + true, + "HTTP/1.1 304 Not Modified\n", + 304, + -1 + }, + { + false, + "HTTP/1.1 304 Not Modified\n", + -1, + 304 + }, + { + true, + "HTTP/1.1 404 Not Found\n", + 404, + -1 + }, + { + false, + "HTTP/1.1 404 Not Found\n", + -1, + 404 + } + }; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { + base::HistogramTester histogram_tester; + std::string raw_headers(test_cases[i].headers); + HeadersToRaw(&raw_headers); + scoped_refptr<net::HttpResponseHeaders> headers( + new net::HttpResponseHeaders(raw_headers)); + + DataReductionProxyUsageStats::DetectAndRecordMissingViaHeaderResponseCode( + test_cases[i].is_primary, headers.get()); + + if (test_cases[i].expected_primary_sample == -1) { + histogram_tester.ExpectTotalCount(kPrimaryHistogramName, 0); + } else { + histogram_tester.ExpectUniqueSample( + kPrimaryHistogramName, test_cases[i].expected_primary_sample, 1); + } + + if (test_cases[i].expected_fallback_sample == -1) { + histogram_tester.ExpectTotalCount(kFallbackHistogramName, 0); + } else { + histogram_tester.ExpectUniqueSample( + kFallbackHistogramName, test_cases[i].expected_fallback_sample, 1); + } + } +} + +TEST_F(DataReductionProxyUsageStatsTest, RecordMissingViaHeaderBytes) { + const std::string k4xxHistogramName = + "DataReductionProxy.MissingViaHeader.Bytes.4xx"; + const std::string kOtherHistogramName = + "DataReductionProxy.MissingViaHeader.Bytes.Other"; + const int64 kResponseContentLength = 100; + + struct TestCase { + bool was_proxy_used; + const char* headers; + bool is_4xx_sample_expected; + bool is_other_sample_expected; + }; + const TestCase test_cases[] = { + // Nothing should be recorded for requests that don't use the proxy. + { + false, + "HTTP/1.1 404 Not Found\n", + false, + false + }, + { + false, + "HTTP/1.1 200 OK\n", + false, + false + }, + // Nothing should be recorded for responses that have the via header. + { + true, + "HTTP/1.1 404 Not Found\n" + "Via: 1.1 Chrome-Compression-Proxy\n", + false, + false + }, + { + true, + "HTTP/1.1 200 OK\n" + "Via: 1.1 Chrome-Compression-Proxy\n", + false, + false + }, + // 4xx responses that used the proxy and don't have the via header should be + // recorded. + { + true, + "HTTP/1.1 404 Not Found\n", + true, + false + }, + { + true, + "HTTP/1.1 400 Bad Request\n", + true, + false + }, + { + true, + "HTTP/1.1 499 Big Client Error Response Code\n", + true, + false + }, + // Non-4xx responses that used the proxy and don't have the via header + // should be recorded. + { + true, + "HTTP/1.1 200 OK\n", + false, + true + }, + { + true, + "HTTP/1.1 399 Big Redirection Response Code\n", + false, + true + }, + { + true, + "HTTP/1.1 500 Internal Server Error\n", + false, + true + } + }; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { + base::HistogramTester histogram_tester; + scoped_ptr<DataReductionProxyUsageStats> usage_stats( + new DataReductionProxyUsageStats(&mock_params_, loop_proxy_)); + + std::string raw_headers(test_cases[i].headers); + HeadersToRaw(&raw_headers); + + scoped_ptr<net::URLRequest> fake_request( + CreateURLRequestWithResponseHeaders(GURL("http://www.google.com/"), + raw_headers)); + fake_request->set_received_response_content_length(kResponseContentLength); + + EXPECT_CALL(mock_params_, + WasDataReductionProxyUsed(fake_request.get(), NULL)) + .WillRepeatedly(Return(test_cases[i].was_proxy_used)); + + usage_stats->RecordMissingViaHeaderBytes(fake_request.get()); + + if (test_cases[i].is_4xx_sample_expected) { + histogram_tester.ExpectUniqueSample(k4xxHistogramName, + kResponseContentLength, 1); + } else { + histogram_tester.ExpectTotalCount(k4xxHistogramName, 0); + } + + if (test_cases[i].is_other_sample_expected) { + histogram_tester.ExpectUniqueSample(kOtherHistogramName, + kResponseContentLength, 1); + } else { + histogram_tester.ExpectTotalCount(kOtherHistogramName, 0); + } + } +} + } // namespace data_reduction_proxy diff --git a/components/data_reduction_proxy/common/data_reduction_proxy_headers_test_utils.cc b/components/data_reduction_proxy/common/data_reduction_proxy_headers_test_utils.cc new file mode 100644 index 0000000..1540c80 --- /dev/null +++ b/components/data_reduction_proxy/common/data_reduction_proxy_headers_test_utils.cc @@ -0,0 +1,17 @@ +// Copyright 2014 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 "components/data_reduction_proxy/common/data_reduction_proxy_headers_test_utils.h" + +#include <algorithm> + +namespace data_reduction_proxy { + +void HeadersToRaw(std::string* headers) { + std::replace(headers->begin(), headers->end(), '\n', '\0'); + if (!headers->empty()) + *headers += '\0'; +} + +} // namespace data_reduction_proxy diff --git a/components/data_reduction_proxy/common/data_reduction_proxy_headers_test_utils.h b/components/data_reduction_proxy/common/data_reduction_proxy_headers_test_utils.h new file mode 100644 index 0000000..143dcd5d --- /dev/null +++ b/components/data_reduction_proxy/common/data_reduction_proxy_headers_test_utils.h @@ -0,0 +1,17 @@ +// Copyright 2014 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. + +#ifndef COMPONENTS_DATA_REDUCTION_PROXY_COMMON_DATA_REDUCTION_PROXY_HEADERS_TEST_UTILS_H_ +#define COMPONENTS_DATA_REDUCTION_PROXY_COMMON_DATA_REDUCTION_PROXY_HEADERS_TEST_UTILS_H_ + +#include <string> + +namespace data_reduction_proxy { + +// Transform "normal"-looking headers (\n-separated) to the appropriate +// input format for ParseRawHeaders (\0-separated). +void HeadersToRaw(std::string* headers); + +} // namespace data_reduction_proxy +#endif // COMPONENTS_DATA_REDUCTION_PROXY_COMMON_DATA_REDUCTION_PROXY_HEADERS_TEST_UTILS_H_ 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 61bad7e..a8984ce 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 @@ -6,22 +6,11 @@ #include <vector> +#include "components/data_reduction_proxy/common/data_reduction_proxy_headers_test_utils.h" #include "net/http/http_response_headers.h" #include "net/proxy/proxy_service.h" #include "testing/gtest/include/gtest/gtest.h" -namespace { - -// Transform "normal"-looking headers (\n-separated) to the appropriate -// input format for ParseRawHeaders (\0-separated). -void HeadersToRaw(std::string* headers) { - std::replace(headers->begin(), headers->end(), '\n', '\0'); - if (!headers->empty()) - *headers += '\0'; -} - -} // namespace - namespace data_reduction_proxy { class DataReductionProxyHeadersTest : public testing::Test {}; diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 0c722c2..6feef49 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -3582,6 +3582,27 @@ Therefore, the affected-histogram name has to have at least one dot in it. </summary> </histogram> +<histogram name="DataReductionProxy.MissingViaHeader.Bytes" units="bytes"> + <owner>bengr@chromium.org</owner> + <owner>sclittle@chromium.org</owner> + <summary> + Counts the response bytes of responses that Chrome expected to come through + a data reduction proxy and have the data reduction proxy via header, but + where the data reduction proxy via header was missing. Note that this does + not include responses that were bypassed. + </summary> +</histogram> + +<histogram name="DataReductionProxy.MissingViaHeader.ResponseCode"> + <owner>bengr@chromium.org</owner> + <owner>sclittle@chromium.org</owner> + <summary> + Counts the different HTTP response codes of responses that Chrome expected + to come through a data reduction proxy and have the data reduction proxy via + header, but where the data reduction proxy via header was missing. + </summary> +</histogram> + <histogram name="DataReductionProxy.NetworkChangeEvents" enum="DataReductionProxyNetworkChangeEvent"> <owner>bengr@chromium.org</owner> @@ -53121,6 +53142,20 @@ To add a new entry, add it with any value and run test to compute valid value. <affected-histogram name="DataReductionProxy.BypassedBytes"/> </histogram_suffixes> +<histogram_suffixes name="DataReductionProxyMissingViaHeaderBytes" + separator="."> + <suffix name="4xx" label="Response with 4xx response code"/> + <suffix name="Other" label="Other response"/> + <affected-histogram name="DataReductionProxy.MissingViaHeader.Bytes"/> +</histogram_suffixes> + +<histogram_suffixes name="DataReductionProxyMissingViaHeaderResponseCode" + separator="."> + <suffix name="Primary" label="Primary data reduction proxy"/> + <suffix name="Fallback" label="Fallback data reduction proxy"/> + <affected-histogram name="DataReductionProxy.MissingViaHeader.ResponseCode"/> +</histogram_suffixes> + <histogram_suffixes name="DefaultAppsExperiment"> <suffix name="NoDefaultApps" label="User's without default apps installed"/> <suffix name="WithDefaultApps" label="User's with default apps installed"/> |