cc: Make ContentLayerClient subclasses create the DisplayItemList.
[chromium-blink-merge.git] / components / data_reduction_proxy / core / browser / data_reduction_proxy_network_delegate.cc
blob706f1729d545ddddcb4a06db53137923cb5ded05
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h"
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/metrics/histogram.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/time/time.h"
12 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h"
13 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h"
14 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h"
15 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_experiments_stats.h"
16 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
17 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h"
18 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
19 #include "net/base/load_flags.h"
20 #include "net/http/http_response_headers.h"
21 #include "net/proxy/proxy_info.h"
22 #include "net/proxy/proxy_server.h"
23 #include "net/proxy/proxy_service.h"
24 #include "net/url_request/url_request.h"
25 #include "net/url_request/url_request_status.h"
27 namespace {
29 void RecordContentLengthHistograms(
30 int64 received_content_length,
31 int64 original_content_length,
32 const base::TimeDelta& freshness_lifetime) {
33 // Add the current resource to these histograms only when a valid
34 // X-Original-Content-Length header is present.
35 if (original_content_length >= 0) {
36 UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthWithValidOCL",
37 received_content_length);
38 UMA_HISTOGRAM_COUNTS("Net.HttpOriginalContentLengthWithValidOCL",
39 original_content_length);
40 UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthDifferenceWithValidOCL",
41 original_content_length - received_content_length);
42 } else {
43 // Presume the original content length is the same as the received content
44 // length if the X-Original-Content-Header is not present.
45 original_content_length = received_content_length;
47 UMA_HISTOGRAM_COUNTS("Net.HttpContentLength", received_content_length);
48 UMA_HISTOGRAM_COUNTS("Net.HttpOriginalContentLength",
49 original_content_length);
50 UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthDifference",
51 original_content_length - received_content_length);
52 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpContentFreshnessLifetime",
53 freshness_lifetime.InSeconds(),
54 base::TimeDelta::FromHours(1).InSeconds(),
55 base::TimeDelta::FromDays(30).InSeconds(),
56 100);
57 if (freshness_lifetime.InSeconds() <= 0)
58 return;
59 UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthCacheable",
60 received_content_length);
61 if (freshness_lifetime.InHours() < 4)
62 return;
63 UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthCacheable4Hours",
64 received_content_length);
66 if (freshness_lifetime.InHours() < 24)
67 return;
68 UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthCacheable24Hours",
69 received_content_length);
72 } // namespace
74 namespace data_reduction_proxy {
76 DataReductionProxyNetworkDelegate::DataReductionProxyNetworkDelegate(
77 scoped_ptr<net::NetworkDelegate> network_delegate,
78 DataReductionProxyConfig* config,
79 DataReductionProxyRequestOptions* request_options,
80 const DataReductionProxyConfigurator* configurator,
81 DataReductionProxyExperimentsStats* experiments_stats)
82 : LayeredNetworkDelegate(network_delegate.Pass()),
83 received_content_length_(0),
84 original_content_length_(0),
85 data_reduction_proxy_config_(config),
86 data_reduction_proxy_bypass_stats_(nullptr),
87 data_reduction_proxy_request_options_(request_options),
88 data_reduction_proxy_io_data_(nullptr),
89 configurator_(configurator),
90 experiments_stats_(experiments_stats) {
91 DCHECK(data_reduction_proxy_config_);
92 DCHECK(data_reduction_proxy_request_options_);
93 DCHECK(experiments_stats_);
96 DataReductionProxyNetworkDelegate::~DataReductionProxyNetworkDelegate() {
99 void DataReductionProxyNetworkDelegate::InitIODataAndUMA(
100 DataReductionProxyIOData* io_data,
101 DataReductionProxyBypassStats* bypass_stats) {
102 DCHECK(bypass_stats);
103 data_reduction_proxy_io_data_ = io_data;
104 data_reduction_proxy_bypass_stats_ = bypass_stats;
107 base::Value*
108 DataReductionProxyNetworkDelegate::SessionNetworkStatsInfoToValue() const {
109 base::DictionaryValue* dict = new base::DictionaryValue();
110 // Use strings to avoid overflow. base::Value only supports 32-bit integers.
111 dict->SetString("session_received_content_length",
112 base::Int64ToString(received_content_length_));
113 dict->SetString("session_original_content_length",
114 base::Int64ToString(original_content_length_));
115 return dict;
118 void DataReductionProxyNetworkDelegate::OnResolveProxyInternal(
119 const GURL& url,
120 int load_flags,
121 const net::ProxyService& proxy_service,
122 net::ProxyInfo* result) {
123 if (configurator_) {
124 OnResolveProxyHandler(url, load_flags, configurator_->GetProxyConfig(),
125 proxy_service.proxy_retry_info(),
126 data_reduction_proxy_config_, result);
130 void DataReductionProxyNetworkDelegate::OnProxyFallbackInternal(
131 const net::ProxyServer& bad_proxy,
132 int net_error) {
133 if (data_reduction_proxy_bypass_stats_) {
134 data_reduction_proxy_bypass_stats_->OnProxyFallback(
135 bad_proxy, net_error);
139 void DataReductionProxyNetworkDelegate::OnBeforeSendProxyHeadersInternal(
140 net::URLRequest* request,
141 const net::ProxyInfo& proxy_info,
142 net::HttpRequestHeaders* headers) {
143 if (data_reduction_proxy_request_options_) {
144 data_reduction_proxy_request_options_->MaybeAddRequestHeader(
145 request, proxy_info.proxy_server(), headers);
149 void DataReductionProxyNetworkDelegate::OnCompletedInternal(
150 net::URLRequest* request,
151 bool started) {
152 DCHECK(request);
153 if (data_reduction_proxy_bypass_stats_)
154 data_reduction_proxy_bypass_stats_->OnUrlRequestCompleted(request, started);
156 // Only record for http or https urls.
157 bool is_http = request->url().SchemeIs("http");
158 bool is_https = request->url().SchemeIs("https");
160 if (request->status().status() != net::URLRequestStatus::SUCCESS)
161 return;
163 // For better accuracy, we use the actual bytes read instead of the length
164 // specified with the Content-Length header, which may be inaccurate,
165 // or missing, as is the case with chunked encoding.
166 int64 received_content_length = request->received_response_content_length();
167 if (!request->was_cached() && // Don't record cached content
168 received_content_length && // Zero-byte responses aren't useful.
169 (is_http || is_https) && // Only record for HTTP or HTTPS urls.
170 configurator_) { // Used by request type and histograms.
171 int64 original_content_length =
172 request->response_info().headers->GetInt64HeaderValue(
173 "x-original-content-length");
174 base::TimeDelta freshness_lifetime =
175 request->response_info().headers->GetFreshnessLifetimes(
176 request->response_info().response_time).freshness;
177 DataReductionProxyRequestType request_type =
178 GetDataReductionProxyRequestType(*request,
179 configurator_->GetProxyConfig(),
180 *data_reduction_proxy_config_);
182 int64 adjusted_original_content_length =
183 GetAdjustedOriginalContentLength(request_type,
184 original_content_length,
185 received_content_length);
186 AccumulateContentLength(received_content_length,
187 adjusted_original_content_length,
188 request_type);
189 RecordContentLengthHistograms(received_content_length,
190 original_content_length,
191 freshness_lifetime);
192 experiments_stats_->RecordBytes(request->request_time(), request_type,
193 received_content_length,
194 original_content_length);
196 if (data_reduction_proxy_io_data_ && data_reduction_proxy_bypass_stats_) {
197 data_reduction_proxy_bypass_stats_->RecordBytesHistograms(
198 *request, data_reduction_proxy_io_data_->IsEnabled(),
199 configurator_->GetProxyConfig());
201 DVLOG(2) << __FUNCTION__
202 << " received content length: " << received_content_length
203 << " original content length: " << original_content_length
204 << " url: " << request->url();
208 void DataReductionProxyNetworkDelegate::AccumulateContentLength(
209 int64 received_content_length,
210 int64 original_content_length,
211 DataReductionProxyRequestType request_type) {
212 DCHECK_GE(received_content_length, 0);
213 DCHECK_GE(original_content_length, 0);
214 if (data_reduction_proxy_io_data_) {
215 data_reduction_proxy_io_data_->UpdateContentLengths(
216 received_content_length, original_content_length,
217 data_reduction_proxy_io_data_->IsEnabled(), request_type);
219 received_content_length_ += received_content_length;
220 original_content_length_ += original_content_length;
223 void OnResolveProxyHandler(const GURL& url,
224 int load_flags,
225 const net::ProxyConfig& data_reduction_proxy_config,
226 const net::ProxyRetryInfoMap& proxy_retry_info,
227 const DataReductionProxyConfig* config,
228 net::ProxyInfo* result) {
229 DCHECK(config);
230 DCHECK(result->is_empty() || result->is_direct() ||
231 !config->IsDataReductionProxy(result->proxy_server().host_port_pair(),
232 NULL));
233 if (data_reduction_proxy_config.is_valid() &&
234 result->proxy_server().is_direct() &&
235 result->proxy_list().size() == 1 &&
236 !url.SchemeIsWSOrWSS()) {
237 net::ProxyInfo data_reduction_proxy_info;
238 data_reduction_proxy_config.proxy_rules().Apply(
239 url, &data_reduction_proxy_info);
240 data_reduction_proxy_info.DeprioritizeBadProxies(proxy_retry_info);
241 if (!data_reduction_proxy_info.proxy_server().is_direct())
242 result->OverrideProxyList(data_reduction_proxy_info.proxy_list());
245 if ((load_flags & net::LOAD_BYPASS_DATA_REDUCTION_PROXY) &&
246 DataReductionProxyParams::IsIncludedInCriticalPathBypassFieldTrial()) {
247 if (!result->is_empty() && !result->is_direct() &&
248 config->IsDataReductionProxy(result->proxy_server().host_port_pair(),
249 NULL)) {
250 result->RemoveProxiesWithoutScheme(net::ProxyServer::SCHEME_DIRECT);
255 } // namespace data_reduction_proxy