Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / components / data_reduction_proxy / browser / data_reduction_proxy_params.cc
blob1dfbaaa89ada462b7362394994b18db2a6effe55
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/browser/data_reduction_proxy_params.h"
7 #include <vector>
9 #include "base/command_line.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/metrics/field_trial.h"
12 #include "base/time/time.h"
13 #include "components/data_reduction_proxy/common/data_reduction_proxy_switches.h"
14 #include "net/base/host_port_pair.h"
15 #include "net/proxy/proxy_info.h"
16 #include "net/proxy/proxy_retry_info.h"
17 #include "net/proxy/proxy_server.h"
18 #include "net/proxy/proxy_service.h"
19 #include "net/url_request/url_request.h"
20 #include "net/url_request/url_request_context.h"
21 #include "url/url_constants.h"
23 using base::FieldTrialList;
25 namespace {
26 const char kEnabled[] = "Enabled";
29 namespace data_reduction_proxy {
31 // static
32 bool DataReductionProxyParams::IsIncludedInFieldTrial() {
33 return base::FieldTrialList::FindFullName(
34 "DataCompressionProxyRollout") == kEnabled;
37 // static
38 bool DataReductionProxyParams::IsIncludedInAlternativeFieldTrial() {
39 return base::FieldTrialList::FindFullName(
40 "DataCompressionProxyAlternativeConfiguration") == kEnabled;
43 // static
44 bool DataReductionProxyParams::IsIncludedInPromoFieldTrial() {
45 return FieldTrialList::FindFullName(
46 "DataCompressionProxyPromoVisibility") == kEnabled;
49 // static
50 bool DataReductionProxyParams::IsIncludedInPreconnectHintingFieldTrial() {
51 return IsIncludedInFieldTrial() &&
52 FieldTrialList::FindFullName(
53 "DataCompressionProxyPreconnectHints") == kEnabled;
56 // static
57 bool DataReductionProxyParams::IsIncludedInCriticalPathBypassFieldTrial() {
58 return IsIncludedInFieldTrial() &&
59 FieldTrialList::FindFullName(
60 "DataCompressionProxyCriticalBypass") == kEnabled;
63 DataReductionProxyTypeInfo::DataReductionProxyTypeInfo()
64 : proxy_servers(),
65 is_fallback(false),
66 is_alternative(false),
67 is_ssl(false) {
70 DataReductionProxyTypeInfo::~DataReductionProxyTypeInfo(){
73 bool DataReductionProxyParams::IsIncludedInHoldbackFieldTrial() {
74 return FieldTrialList::FindFullName(
75 "DataCompressionProxyHoldback") == kEnabled;
78 DataReductionProxyParams::DataReductionProxyParams(int flags)
79 : allowed_((flags & kAllowed) == kAllowed),
80 fallback_allowed_((flags & kFallbackAllowed) == kFallbackAllowed),
81 alt_allowed_((flags & kAlternativeAllowed) == kAlternativeAllowed),
82 promo_allowed_((flags & kPromoAllowed) == kPromoAllowed),
83 holdback_((flags & kHoldback) == kHoldback),
84 configured_on_command_line_(false) {
85 bool result = Init(allowed_, fallback_allowed_, alt_allowed_);
86 DCHECK(result);
89 scoped_ptr<DataReductionProxyParams> DataReductionProxyParams::Clone() {
90 return scoped_ptr<DataReductionProxyParams>(
91 new DataReductionProxyParams(*this));
94 DataReductionProxyParams::DataReductionProxyParams(
95 const DataReductionProxyParams& other)
96 : origin_(other.origin_),
97 fallback_origin_(other.fallback_origin_),
98 ssl_origin_(other.ssl_origin_),
99 alt_origin_(other.alt_origin_),
100 alt_fallback_origin_(other.alt_fallback_origin_),
101 probe_url_(other.probe_url_),
102 warmup_url_(other.warmup_url_),
103 allowed_(other.allowed_),
104 fallback_allowed_(other.fallback_allowed_),
105 alt_allowed_(other.alt_allowed_),
106 promo_allowed_(other.promo_allowed_),
107 holdback_(other.holdback_),
108 configured_on_command_line_(other.configured_on_command_line_) {
111 DataReductionProxyParams::~DataReductionProxyParams() {
114 DataReductionProxyParams::DataReductionProxyList
115 DataReductionProxyParams::GetAllowedProxies() const {
116 DataReductionProxyList list;
117 if (allowed_) {
118 list.push_back(origin_);
119 // TODO(bolian): revert this once the proxy PAC fix is ready.
120 if (GURL(GetDefaultDevOrigin()) == origin()) {
121 list.push_back(GURL(GetDefaultOrigin()));
124 if (allowed_ && fallback_allowed_)
125 list.push_back(fallback_origin_);
126 if (alt_allowed_) {
127 list.push_back(alt_origin_);
128 list.push_back(ssl_origin_);
130 if (alt_allowed_ && fallback_allowed_)
131 list.push_back(alt_fallback_origin_);
132 return list;
135 DataReductionProxyParams::DataReductionProxyParams(int flags,
136 bool should_call_init)
137 : allowed_((flags & kAllowed) == kAllowed),
138 fallback_allowed_((flags & kFallbackAllowed) == kFallbackAllowed),
139 alt_allowed_((flags & kAlternativeAllowed) == kAlternativeAllowed),
140 promo_allowed_((flags & kPromoAllowed) == kPromoAllowed),
141 holdback_((flags & kHoldback) == kHoldback),
142 configured_on_command_line_(false) {
143 if (should_call_init) {
144 bool result = Init(allowed_, fallback_allowed_, alt_allowed_);
145 DCHECK(result);
149 bool DataReductionProxyParams::Init(
150 bool allowed, bool fallback_allowed, bool alt_allowed) {
151 InitWithoutChecks();
152 // Verify that all necessary params are set.
153 if (allowed) {
154 if (!origin_.is_valid()) {
155 DVLOG(1) << "Invalid data reduction proxy origin: " << origin_.spec();
156 return false;
160 if (allowed && fallback_allowed) {
161 if (!fallback_origin_.is_valid()) {
162 DVLOG(1) << "Invalid data reduction proxy fallback origin: "
163 << fallback_origin_.spec();
164 return false;
168 if (alt_allowed) {
169 if (!allowed) {
170 DVLOG(1) << "Alternative data reduction proxy configuration cannot "
171 << "be allowed if the regular configuration is not allowed";
172 return false;
174 if (!alt_origin_.is_valid()) {
175 DVLOG(1) << "Invalid alternative origin:" << alt_origin_.spec();
176 return false;
178 if (!ssl_origin_.is_valid()) {
179 DVLOG(1) << "Invalid ssl origin: " << ssl_origin_.spec();
180 return false;
184 if (alt_allowed && fallback_allowed) {
185 if (!alt_fallback_origin_.is_valid()) {
186 DVLOG(1) << "Invalid alternative fallback origin:"
187 << alt_fallback_origin_.spec();
188 return false;
192 if (allowed && !probe_url_.is_valid()) {
193 DVLOG(1) << "Invalid probe url: <null>";
194 return false;
197 if (fallback_allowed_ && !allowed_) {
198 DVLOG(1) << "The data reduction proxy fallback cannot be allowed if "
199 << "the data reduction proxy is not allowed";
200 return false;
202 if (promo_allowed_ && !allowed_) {
203 DVLOG(1) << "The data reduction proxy promo cannot be allowed if the "
204 << "data reduction proxy is not allowed";
205 return false;
207 return true;
211 void DataReductionProxyParams::InitWithoutChecks() {
212 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
213 std::string origin;
214 if (!command_line.HasSwitch(switches::kDisableDataReductionProxyDev)) {
215 origin = command_line.GetSwitchValueASCII(
216 switches::kDataReductionProxyDev);
218 if (origin.empty())
219 origin = command_line.GetSwitchValueASCII(switches::kDataReductionProxy);
220 std::string fallback_origin =
221 command_line.GetSwitchValueASCII(switches::kDataReductionProxyFallback);
222 std::string ssl_origin =
223 command_line.GetSwitchValueASCII(switches::kDataReductionSSLProxy);
224 std::string alt_origin =
225 command_line.GetSwitchValueASCII(switches::kDataReductionProxyAlt);
226 std::string alt_fallback_origin = command_line.GetSwitchValueASCII(
227 switches::kDataReductionProxyAltFallback);
229 configured_on_command_line_ =
230 !(origin.empty() && fallback_origin.empty() && ssl_origin.empty() &&
231 alt_origin.empty() && alt_fallback_origin.empty());
234 // Configuring the proxy on the command line overrides the values of
235 // |allowed_| and |alt_allowed_|.
236 if (configured_on_command_line_)
237 allowed_ = true;
238 if (!(ssl_origin.empty() &&
239 alt_origin.empty() &&
240 alt_fallback_origin.empty()))
241 alt_allowed_ = true;
243 std::string probe_url = command_line.GetSwitchValueASCII(
244 switches::kDataReductionProxyProbeURL);
245 std::string warmup_url = command_line.GetSwitchValueASCII(
246 switches::kDataReductionProxyWarmupURL);
248 // Set from preprocessor constants those params that are not specified on the
249 // command line.
250 if (origin.empty())
251 origin = GetDefaultDevOrigin();
252 if (origin.empty())
253 origin = GetDefaultOrigin();
254 if (fallback_origin.empty())
255 fallback_origin = GetDefaultFallbackOrigin();
256 if (ssl_origin.empty())
257 ssl_origin = GetDefaultSSLOrigin();
258 if (alt_origin.empty())
259 alt_origin = GetDefaultAltOrigin();
260 if (alt_fallback_origin.empty())
261 alt_fallback_origin = GetDefaultAltFallbackOrigin();
262 if (probe_url.empty())
263 probe_url = GetDefaultProbeURL();
264 if (warmup_url.empty())
265 warmup_url = GetDefaultWarmupURL();
267 origin_ = GURL(origin);
268 fallback_origin_ = GURL(fallback_origin);
269 ssl_origin_ = GURL(ssl_origin);
270 alt_origin_ = GURL(alt_origin);
271 alt_fallback_origin_ = GURL(alt_fallback_origin);
272 probe_url_ = GURL(probe_url);
273 warmup_url_ = GURL(warmup_url);
277 bool DataReductionProxyParams::WasDataReductionProxyUsed(
278 const net::URLRequest* request,
279 DataReductionProxyTypeInfo* proxy_info) const {
280 DCHECK(request);
281 return IsDataReductionProxy(request->proxy_server(), proxy_info);
284 bool DataReductionProxyParams::IsDataReductionProxy(
285 const net::HostPortPair& host_port_pair,
286 DataReductionProxyTypeInfo* proxy_info) const {
287 if (net::HostPortPair::FromURL(origin()).Equals(host_port_pair)) {
288 if (proxy_info) {
289 proxy_info->proxy_servers.first = origin();
290 if (fallback_allowed())
291 proxy_info->proxy_servers.second = fallback_origin();
293 return true;
296 // TODO(bolian): revert this once the proxy PAC fix is ready.
298 // If dev host is configured as the primary proxy, we treat the default
299 // origin as a valid data reduction proxy to workaround PAC script.
300 if (GURL(GetDefaultDevOrigin()) == origin()) {
301 const GURL& default_origin = GURL(GetDefaultOrigin());
302 if (net::HostPortPair::FromURL(default_origin).Equals(host_port_pair)) {
303 if (proxy_info) {
304 proxy_info->proxy_servers.first = default_origin;
305 if (fallback_allowed())
306 proxy_info->proxy_servers.second = fallback_origin();
308 return true;
312 if (fallback_allowed() &&
313 net::HostPortPair::FromURL(fallback_origin()).Equals(host_port_pair)) {
314 if (proxy_info) {
315 proxy_info->proxy_servers.first = fallback_origin();
316 proxy_info->proxy_servers.second = GURL();
317 proxy_info->is_fallback = true;
319 return true;
321 if (net::HostPortPair::FromURL(alt_origin()).Equals(host_port_pair)) {
322 if (proxy_info) {
323 proxy_info->proxy_servers.first = alt_origin();
324 proxy_info->is_alternative = true;
325 if (fallback_allowed())
326 proxy_info->proxy_servers.second = alt_fallback_origin();
328 return true;
330 if (fallback_allowed() &&
331 net::HostPortPair::FromURL(alt_fallback_origin()).Equals(
332 host_port_pair)) {
333 if (proxy_info) {
334 proxy_info->proxy_servers.first = alt_fallback_origin();
335 proxy_info->proxy_servers.second = GURL();
336 proxy_info->is_fallback = true;
337 proxy_info->is_alternative = true;
339 return true;
341 if (net::HostPortPair::FromURL(ssl_origin()).Equals(host_port_pair)) {
342 if (proxy_info) {
343 proxy_info->proxy_servers.first = ssl_origin();
344 proxy_info->proxy_servers.second = GURL();
345 proxy_info->is_ssl = true;
347 return true;
349 return false;
352 // TODO(kundaji): Check that the request will actually be sent through the
353 // proxy.
354 bool DataReductionProxyParams::IsDataReductionProxyEligible(
355 const net::URLRequest* request) {
356 DCHECK(request);
357 DCHECK(request->context());
358 DCHECK(request->context()->proxy_service());
359 net::ProxyInfo result;
360 request->context()->proxy_service()->config().proxy_rules().Apply(
361 request->url(), &result);
362 if (!result.proxy_server().is_valid())
363 return false;
364 if (result.proxy_server().is_direct())
365 return false;
366 return IsDataReductionProxy(result.proxy_server().host_port_pair(), NULL);
369 std::string DataReductionProxyParams::GetDefaultDevOrigin() const {
370 #if defined(DATA_REDUCTION_DEV_HOST)
371 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
372 if (command_line.HasSwitch(switches::kDisableDataReductionProxyDev))
373 return std::string();
374 if (command_line.HasSwitch(switches::kEnableDataReductionProxyDev) ||
375 (FieldTrialList::FindFullName("DataCompressionProxyDevRollout") ==
376 kEnabled)) {
377 return DATA_REDUCTION_DEV_HOST;
379 #endif
380 return std::string();
383 bool DataReductionProxyParams::AreDataReductionProxiesBypassed(
384 const net::URLRequest& request, base::TimeDelta* min_retry_delay) const {
385 if (request.context() != NULL &&
386 request.context()->proxy_service() != NULL) {
387 return AreProxiesBypassed(
388 request.context()->proxy_service()->proxy_retry_info(),
389 request.url().SchemeIs(url::kHttpsScheme),
390 min_retry_delay);
393 return false;
396 bool DataReductionProxyParams::AreProxiesBypassed(
397 const net::ProxyRetryInfoMap& retry_map,
398 bool is_https,
399 base::TimeDelta* min_retry_delay) const {
400 if (retry_map.size() == 0)
401 return false;
403 // If the request is https, consider only the ssl proxy.
404 if (is_https) {
405 if (alt_allowed_) {
406 return ArePrimaryAndFallbackBypassed(
407 retry_map, ssl_origin_, GURL(), min_retry_delay);
409 NOTREACHED();
410 return false;
413 if (allowed_ && ArePrimaryAndFallbackBypassed(
414 retry_map, origin_, fallback_origin_, min_retry_delay)) {
415 return true;
418 if (alt_allowed_ && ArePrimaryAndFallbackBypassed(
419 retry_map, alt_origin_, alt_fallback_origin_, min_retry_delay)) {
420 return true;
423 return false;
426 bool DataReductionProxyParams::ArePrimaryAndFallbackBypassed(
427 const net::ProxyRetryInfoMap& retry_map,
428 const GURL& primary,
429 const GURL& fallback,
430 base::TimeDelta* min_retry_delay) const {
431 net::ProxyRetryInfoMap::const_iterator found = retry_map.end();
432 if (min_retry_delay)
433 *min_retry_delay = base::TimeDelta::Max();
435 // Look for the primary proxy in the retry map. This must be done before
436 // looking for the fallback in order to assign |min_retry_delay| if the
437 // primary proxy has a shorter delay.
438 if (!fallback_allowed_ || !fallback.is_valid() || min_retry_delay) {
439 found = retry_map.find(
440 net::ProxyServer(primary.SchemeIs(url::kHttpsScheme) ?
441 net::ProxyServer::SCHEME_HTTPS :
442 net::ProxyServer::SCHEME_HTTP,
443 net::HostPortPair::FromURL(primary)).ToURI());
444 if (found != retry_map.end() && min_retry_delay) {
445 *min_retry_delay = found->second.current_delay;
449 if (fallback_allowed_ && fallback.is_valid()) {
450 // If fallback is allowed, only the fallback proxy needs to be on the retry
451 // map to know if there was a bypass. We can reset found and forget if the
452 // primary was on the retry map.
453 found = retry_map.find(
454 net::ProxyServer(fallback.SchemeIs(url::kHttpsScheme) ?
455 net::ProxyServer::SCHEME_HTTPS :
456 net::ProxyServer::SCHEME_HTTP,
457 net::HostPortPair::FromURL(fallback)).ToURI());
458 if (found != retry_map.end() &&
459 min_retry_delay &&
460 *min_retry_delay > found->second.current_delay) {
461 *min_retry_delay = found->second.current_delay;
465 return found != retry_map.end();
468 std::string DataReductionProxyParams::GetDefaultOrigin() const {
469 #if defined(SPDY_PROXY_AUTH_ORIGIN)
470 return SPDY_PROXY_AUTH_ORIGIN;
471 #endif
472 return std::string();
475 std::string DataReductionProxyParams::GetDefaultFallbackOrigin() const {
476 #if defined(DATA_REDUCTION_FALLBACK_HOST)
477 return DATA_REDUCTION_FALLBACK_HOST;
478 #endif
479 return std::string();
482 std::string DataReductionProxyParams::GetDefaultSSLOrigin() const {
483 #if defined(DATA_REDUCTION_PROXY_SSL_ORIGIN)
484 return DATA_REDUCTION_PROXY_SSL_ORIGIN;
485 #endif
486 return std::string();
489 std::string DataReductionProxyParams::GetDefaultAltOrigin() const {
490 #if defined(DATA_REDUCTION_PROXY_ALT_ORIGIN)
491 return DATA_REDUCTION_PROXY_ALT_ORIGIN;
492 #endif
493 return std::string();
496 std::string DataReductionProxyParams::GetDefaultAltFallbackOrigin() const {
497 #if defined(DATA_REDUCTION_PROXY_ALT_FALLBACK_ORIGIN)
498 return DATA_REDUCTION_PROXY_ALT_FALLBACK_ORIGIN;
499 #endif
500 return std::string();
503 std::string DataReductionProxyParams::GetDefaultProbeURL() const {
504 #if defined(DATA_REDUCTION_PROXY_PROBE_URL)
505 return DATA_REDUCTION_PROXY_PROBE_URL;
506 #endif
507 return std::string();
510 std::string DataReductionProxyParams::GetDefaultWarmupURL() const {
511 #if defined(DATA_REDUCTION_PROXY_WARMUP_URL)
512 return DATA_REDUCTION_PROXY_WARMUP_URL;
513 #endif
514 return std::string();
517 } // namespace data_reduction_proxy