Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / components / data_reduction_proxy / browser / data_reduction_proxy_params.cc
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.
4
5 #include "components/data_reduction_proxy/browser/data_reduction_proxy_params.h"
6
7 #include <vector>
8
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_config.h"
16 #include "net/proxy/proxy_info.h"
17 #include "net/proxy/proxy_retry_info.h"
18 #include "net/proxy/proxy_server.h"
19 #include "net/proxy/proxy_service.h"
20 #include "net/url_request/url_request.h"
21 #include "net/url_request/url_request_context.h"
22 #include "url/url_constants.h"
23
24 using base::FieldTrialList;
25
26 namespace {
27
28 const char kEnabled[] = "Enabled";
29 const char kDefaultOrigin[] = "https://proxy.googlezip.net:443/";
30 const char kDevOrigin[] = "https://proxy-dev.googlezip.net:443/";
31 const char kDevFallbackOrigin[] = "http://proxy-dev.googlezip.net:80/";
32 const char kDefaultFallbackOrigin[] = "http://compress.googlezip.net:80/";
33 // This is for a proxy that supports HTTP CONNECT to tunnel SSL traffic.
34 // The proxy listens on port 443, but uses the HTTP protocol to set up
35 // the tunnel, not HTTPS.
36 const char kDefaultSslOrigin[] = "http://ssl.googlezip.net:443/";
37 const char kDefaultAltOrigin[] = "http://ssl.googlezip.net:80/";
38 const char kDefaultAltFallbackOrigin[] = "http://ssl.googlezip.net:80/";
39 const char kDefaultProbeUrl[] = "http://check.googlezip.net/connect";
40 const char kDefaultWarmupUrl[] = "http://www.gstatic.com/generate_204";
41
42 }  // namespace
43
44 namespace data_reduction_proxy {
45
46 // static
47 bool DataReductionProxyParams::IsIncludedInAlternativeFieldTrial() {
48   const std::string group_name = base::FieldTrialList::FindFullName(
49       "DataCompressionProxyAlternativeConfiguration");
50   if (CommandLine::ForCurrentProcess()->HasSwitch(
51           data_reduction_proxy::switches::kEnableDataReductionProxyAlt)) {
52     return true;
53   }
54   return group_name == kEnabled;
55 }
56
57 // static
58 bool DataReductionProxyParams::IsIncludedInPromoFieldTrial() {
59   return FieldTrialList::FindFullName(
60       "DataCompressionProxyPromoVisibility") == kEnabled;
61 }
62
63 // static
64 bool DataReductionProxyParams::IsIncludedInPreconnectHintingFieldTrial() {
65   return FieldTrialList::FindFullName(
66           "DataCompressionProxyPreconnectHints") == kEnabled;
67 }
68
69 // static
70 bool DataReductionProxyParams::IsIncludedInCriticalPathBypassFieldTrial() {
71   return FieldTrialList::FindFullName(
72           "DataCompressionProxyCriticalBypass") == kEnabled;
73 }
74
75 // static
76 bool DataReductionProxyParams::IsIncludedInHoldbackFieldTrial() {
77   return FieldTrialList::FindFullName(
78       "DataCompressionProxyHoldback") == kEnabled;
79 }
80
81 // static
82 bool DataReductionProxyParams::
83     IsIncludedInRemoveMissingViaHeaderOtherBypassFieldTrial() {
84   return FieldTrialList::FindFullName(
85       "DataReductionProxyRemoveMissingViaHeaderOtherBypass") == kEnabled;
86 }
87
88 DataReductionProxyTypeInfo::DataReductionProxyTypeInfo()
89     : proxy_servers(),
90       is_fallback(false),
91       is_alternative(false),
92       is_ssl(false) {
93 }
94
95 DataReductionProxyTypeInfo::~DataReductionProxyTypeInfo(){
96 }
97
98 DataReductionProxyParams::DataReductionProxyParams(int flags)
99     : allowed_((flags & kAllowed) == kAllowed),
100       fallback_allowed_((flags & kFallbackAllowed) == kFallbackAllowed),
101       alt_allowed_((flags & kAlternativeAllowed) == kAlternativeAllowed),
102       alt_fallback_allowed_(
103           (flags & kAlternativeFallbackAllowed) == kAlternativeFallbackAllowed),
104       promo_allowed_((flags & kPromoAllowed) == kPromoAllowed),
105       holdback_((flags & kHoldback) == kHoldback),
106       configured_on_command_line_(false) {
107   bool result = Init(
108       allowed_, fallback_allowed_, alt_allowed_, alt_fallback_allowed_);
109   DCHECK(result);
110 }
111
112 scoped_ptr<DataReductionProxyParams> DataReductionProxyParams::Clone() {
113   return scoped_ptr<DataReductionProxyParams>(
114       new DataReductionProxyParams(*this));
115 }
116
117 DataReductionProxyParams::DataReductionProxyParams(
118     const DataReductionProxyParams& other)
119     : origin_(other.origin_),
120       fallback_origin_(other.fallback_origin_),
121       ssl_origin_(other.ssl_origin_),
122       alt_origin_(other.alt_origin_),
123       alt_fallback_origin_(other.alt_fallback_origin_),
124       probe_url_(other.probe_url_),
125       warmup_url_(other.warmup_url_),
126       allowed_(other.allowed_),
127       fallback_allowed_(other.fallback_allowed_),
128       alt_allowed_(other.alt_allowed_),
129       alt_fallback_allowed_(other.alt_fallback_allowed_),
130       promo_allowed_(other.promo_allowed_),
131       holdback_(other.holdback_),
132       configured_on_command_line_(other.configured_on_command_line_) {
133 }
134
135 DataReductionProxyParams::~DataReductionProxyParams() {
136 }
137
138 DataReductionProxyParams::DataReductionProxyList
139 DataReductionProxyParams::GetAllowedProxies() const {
140   DataReductionProxyList list;
141   if (allowed_) {
142     list.push_back(origin_);
143   }
144   if (allowed_ && fallback_allowed_)
145     list.push_back(fallback_origin_);
146   if (alt_allowed_) {
147     list.push_back(alt_origin_);
148     list.push_back(ssl_origin_);
149   }
150   if (alt_allowed_ && alt_fallback_allowed_)
151     list.push_back(alt_fallback_origin_);
152   return list;
153 }
154
155 DataReductionProxyParams::DataReductionProxyParams(int flags,
156                                                    bool should_call_init)
157     : allowed_((flags & kAllowed) == kAllowed),
158       fallback_allowed_((flags & kFallbackAllowed) == kFallbackAllowed),
159       alt_allowed_((flags & kAlternativeAllowed) == kAlternativeAllowed),
160       alt_fallback_allowed_(
161           (flags & kAlternativeFallbackAllowed) == kAlternativeFallbackAllowed),
162       promo_allowed_((flags & kPromoAllowed) == kPromoAllowed),
163       holdback_((flags & kHoldback) == kHoldback),
164       configured_on_command_line_(false) {
165   if (should_call_init) {
166     bool result = Init(
167         allowed_, fallback_allowed_, alt_allowed_, alt_fallback_allowed_);
168     DCHECK(result);
169   }
170 }
171
172 bool DataReductionProxyParams::Init(bool allowed,
173                                     bool fallback_allowed,
174                                     bool alt_allowed,
175                                     bool alt_fallback_allowed) {
176   InitWithoutChecks();
177   // Verify that all necessary params are set.
178   if (allowed) {
179     if (!origin_.is_valid()) {
180       DVLOG(1) << "Invalid data reduction proxy origin: " << origin_.spec();
181       return false;
182     }
183   }
184
185   if (allowed && fallback_allowed) {
186     if (!fallback_origin_.is_valid()) {
187       DVLOG(1) << "Invalid data reduction proxy fallback origin: "
188           << fallback_origin_.spec();
189       return false;
190     }
191   }
192
193   if (alt_allowed) {
194     if (!allowed) {
195       DVLOG(1) << "Alternative data reduction proxy configuration cannot "
196           << "be allowed if the regular configuration is not allowed";
197       return false;
198     }
199     if (!alt_origin_.is_valid()) {
200       DVLOG(1) << "Invalid alternative origin:" << alt_origin_.spec();
201       return false;
202     }
203     if (!ssl_origin_.is_valid()) {
204       DVLOG(1) << "Invalid ssl origin: " << ssl_origin_.spec();
205       return false;
206     }
207   }
208
209   if (alt_allowed && alt_fallback_allowed) {
210     if (!alt_fallback_origin_.is_valid()) {
211       DVLOG(1) << "Invalid alternative fallback origin:"
212           << alt_fallback_origin_.spec();
213       return false;
214     }
215   }
216
217   if (allowed && !probe_url_.is_valid()) {
218     DVLOG(1) << "Invalid probe url: <null>";
219     return false;
220   }
221
222   if (fallback_allowed_ && !allowed_) {
223     DVLOG(1) << "The data reduction proxy fallback cannot be allowed if "
224         << "the data reduction proxy is not allowed";
225     return false;
226   }
227   if (alt_fallback_allowed_ && !alt_allowed_) {
228     DVLOG(1) << "The data reduction proxy alternative fallback cannot be "
229         << "allowed if the alternative data reduction proxy is not allowed";
230     return false;
231   }
232   if (promo_allowed_ && !allowed_) {
233     DVLOG(1) << "The data reduction proxy promo cannot be allowed if the "
234         << "data reduction proxy is not allowed";
235     return false;
236   }
237   return true;
238
239 }
240
241 void DataReductionProxyParams::InitWithoutChecks() {
242   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
243   std::string origin;
244   if (!command_line.HasSwitch(switches::kDisableDataReductionProxyDev)) {
245       origin = command_line.GetSwitchValueASCII(
246           switches::kDataReductionProxyDev);
247   }
248   if (origin.empty())
249     origin = command_line.GetSwitchValueASCII(switches::kDataReductionProxy);
250   std::string fallback_origin =
251       command_line.GetSwitchValueASCII(switches::kDataReductionProxyFallback);
252   std::string ssl_origin =
253       command_line.GetSwitchValueASCII(switches::kDataReductionSSLProxy);
254   std::string alt_origin =
255       command_line.GetSwitchValueASCII(switches::kDataReductionProxyAlt);
256   std::string alt_fallback_origin = command_line.GetSwitchValueASCII(
257       switches::kDataReductionProxyAltFallback);
258
259   configured_on_command_line_ =
260       !(origin.empty() && fallback_origin.empty() && ssl_origin.empty() &&
261           alt_origin.empty() && alt_fallback_origin.empty());
262
263
264   // Configuring the proxy on the command line overrides the values of
265   // |allowed_| and |alt_allowed_|.
266   if (configured_on_command_line_)
267     allowed_ = true;
268   if (!(ssl_origin.empty() &&
269         alt_origin.empty()))
270     alt_allowed_ = true;
271
272   std::string probe_url = command_line.GetSwitchValueASCII(
273       switches::kDataReductionProxyProbeURL);
274   std::string warmup_url = command_line.GetSwitchValueASCII(
275       switches::kDataReductionProxyWarmupURL);
276
277   // Set from preprocessor constants those params that are not specified on the
278   // command line.
279   if (origin.empty())
280     origin = GetDefaultDevOrigin();
281   if (origin.empty())
282     origin = GetDefaultOrigin();
283   if (fallback_origin.empty())
284     fallback_origin = GetDefaultDevFallbackOrigin();
285   if (fallback_origin.empty())
286     fallback_origin = GetDefaultFallbackOrigin();
287   if (ssl_origin.empty())
288     ssl_origin = GetDefaultSSLOrigin();
289   if (alt_origin.empty())
290     alt_origin = GetDefaultAltOrigin();
291   if (alt_fallback_origin.empty())
292     alt_fallback_origin = GetDefaultAltFallbackOrigin();
293   if (probe_url.empty())
294     probe_url = GetDefaultProbeURL();
295   if (warmup_url.empty())
296     warmup_url = GetDefaultWarmupURL();
297
298   origin_ = GURL(origin);
299   fallback_origin_ = GURL(fallback_origin);
300   ssl_origin_ = GURL(ssl_origin);
301   alt_origin_ = GURL(alt_origin);
302   alt_fallback_origin_ = GURL(alt_fallback_origin);
303   probe_url_ = GURL(probe_url);
304   warmup_url_ = GURL(warmup_url);
305
306 }
307
308 bool DataReductionProxyParams::WasDataReductionProxyUsed(
309     const net::URLRequest* request,
310     DataReductionProxyTypeInfo* proxy_info) const {
311   DCHECK(request);
312   return IsDataReductionProxy(request->proxy_server(), proxy_info);
313 }
314
315 bool DataReductionProxyParams::IsDataReductionProxy(
316     const net::HostPortPair& host_port_pair,
317     DataReductionProxyTypeInfo* proxy_info) const {
318   if (net::HostPortPair::FromURL(origin()).Equals(host_port_pair)) {
319     if (proxy_info) {
320       proxy_info->proxy_servers.first = origin();
321       if (fallback_allowed())
322         proxy_info->proxy_servers.second = fallback_origin();
323     }
324     return true;
325   }
326
327   if (fallback_allowed() &&
328       net::HostPortPair::FromURL(fallback_origin()).Equals(host_port_pair)) {
329     if (proxy_info) {
330       proxy_info->proxy_servers.first = fallback_origin();
331       proxy_info->proxy_servers.second = GURL();
332       proxy_info->is_fallback = true;
333     }
334     return true;
335   }
336   if (net::HostPortPair::FromURL(alt_origin()).Equals(host_port_pair)) {
337     if (proxy_info) {
338       proxy_info->proxy_servers.first = alt_origin();
339       proxy_info->is_alternative = true;
340       if (alternative_fallback_allowed())
341         proxy_info->proxy_servers.second = alt_fallback_origin();
342     }
343     return true;
344   }
345   if (alternative_fallback_allowed() &&
346       net::HostPortPair::FromURL(alt_fallback_origin()).Equals(
347       host_port_pair)) {
348     if (proxy_info) {
349       proxy_info->proxy_servers.first = alt_fallback_origin();
350       proxy_info->proxy_servers.second = GURL();
351       proxy_info->is_fallback = true;
352       proxy_info->is_alternative = true;
353     }
354     return true;
355   }
356   if (net::HostPortPair::FromURL(ssl_origin()).Equals(host_port_pair)) {
357     if (proxy_info) {
358       proxy_info->proxy_servers.first = ssl_origin();
359       proxy_info->proxy_servers.second = GURL();
360       proxy_info->is_ssl = true;
361     }
362     return true;
363   }
364   return false;
365 }
366
367 bool DataReductionProxyParams::IsBypassedByDataReductionProxyLocalRules(
368     const net::URLRequest& request,
369     const net::ProxyConfig& data_reduction_proxy_config) const {
370   DCHECK(request.context());
371   DCHECK(request.context()->proxy_service());
372   net::ProxyInfo result;
373   data_reduction_proxy_config.proxy_rules().Apply(
374       request.url(), &result);
375   if (!result.proxy_server().is_valid())
376     return true;
377   if (result.proxy_server().is_direct())
378     return true;
379   return !IsDataReductionProxy(result.proxy_server().host_port_pair(), NULL);
380 }
381
382 std::string DataReductionProxyParams::GetDefaultDevOrigin() const {
383   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
384   if (command_line.HasSwitch(switches::kDisableDataReductionProxyDev))
385     return std::string();
386   if (command_line.HasSwitch(switches::kEnableDataReductionProxyDev) ||
387       (FieldTrialList::FindFullName("DataCompressionProxyDevRollout") ==
388          kEnabled)) {
389     return kDevOrigin;
390   }
391   return std::string();
392 }
393
394 std::string DataReductionProxyParams::GetDefaultDevFallbackOrigin() const {
395   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
396   if (command_line.HasSwitch(switches::kDisableDataReductionProxyDev))
397     return std::string();
398   if (command_line.HasSwitch(switches::kEnableDataReductionProxyDev) ||
399       (FieldTrialList::FindFullName("DataCompressionProxyDevRollout") ==
400            kEnabled)) {
401     return kDevFallbackOrigin;
402   }
403   return std::string();
404 }
405
406 bool DataReductionProxyParams::AreDataReductionProxiesBypassed(
407     const net::URLRequest& request, base::TimeDelta* min_retry_delay) const {
408   if (request.context() != NULL &&
409       request.context()->proxy_service() != NULL) {
410     return AreProxiesBypassed(
411         request.context()->proxy_service()->proxy_retry_info(),
412         request.url().SchemeIs(url::kHttpsScheme),
413         min_retry_delay);
414   }
415
416   return false;
417 }
418
419 bool DataReductionProxyParams::AreProxiesBypassed(
420     const net::ProxyRetryInfoMap& retry_map,
421     bool is_https,
422     base::TimeDelta* min_retry_delay) const {
423   if (retry_map.size() == 0)
424     return false;
425
426   // If the request is https, consider only the ssl proxy.
427   if (is_https) {
428     if (alt_allowed_) {
429       return ArePrimaryAndFallbackBypassed(
430           retry_map, ssl_origin_, GURL(), min_retry_delay);
431     }
432     NOTREACHED();
433     return false;
434   }
435
436   if (allowed_ && ArePrimaryAndFallbackBypassed(
437       retry_map, origin_, fallback_origin_, min_retry_delay)) {
438     return true;
439   }
440
441   if (alt_allowed_ && ArePrimaryAndFallbackBypassed(
442       retry_map, alt_origin_, alt_fallback_origin_, min_retry_delay)) {
443     return true;
444   }
445
446   return false;
447 }
448
449 bool DataReductionProxyParams::ArePrimaryAndFallbackBypassed(
450     const net::ProxyRetryInfoMap& retry_map,
451     const GURL& primary,
452     const GURL& fallback,
453     base::TimeDelta* min_retry_delay) const {
454   net::ProxyRetryInfoMap::const_iterator found = retry_map.end();
455   if (min_retry_delay)
456     *min_retry_delay = base::TimeDelta::Max();
457
458   // Look for the primary proxy in the retry map. This must be done before
459   // looking for the fallback in order to assign |min_retry_delay| if the
460   // primary proxy has a shorter delay.
461   if (!fallback_allowed_ || !fallback.is_valid() || min_retry_delay) {
462     found = retry_map.find(
463         net::ProxyServer(primary.SchemeIs(url::kHttpsScheme) ?
464             net::ProxyServer::SCHEME_HTTPS :
465             net::ProxyServer::SCHEME_HTTP,
466         net::HostPortPair::FromURL(primary)).ToURI());
467     if (found != retry_map.end() && min_retry_delay) {
468       *min_retry_delay = found->second.current_delay;
469     }
470   }
471
472   if (fallback_allowed_ && fallback.is_valid()) {
473     // If fallback is allowed, only the fallback proxy needs to be on the retry
474     // map to know if there was a bypass. We can reset found and forget if the
475     // primary was on the retry map.
476     found = retry_map.find(
477         net::ProxyServer(fallback.SchemeIs(url::kHttpsScheme) ?
478                              net::ProxyServer::SCHEME_HTTPS :
479                              net::ProxyServer::SCHEME_HTTP,
480                          net::HostPortPair::FromURL(fallback)).ToURI());
481     if (found != retry_map.end() &&
482         min_retry_delay &&
483         *min_retry_delay > found->second.current_delay) {
484       *min_retry_delay = found->second.current_delay;
485     }
486   }
487
488   return found != retry_map.end();
489 }
490
491 // TODO(kundaji): Remove tests for macro definitions.
492 std::string DataReductionProxyParams::GetDefaultOrigin() const {
493   return kDefaultOrigin;
494 }
495
496 std::string DataReductionProxyParams::GetDefaultFallbackOrigin() const {
497   return kDefaultFallbackOrigin;
498 }
499
500 std::string DataReductionProxyParams::GetDefaultSSLOrigin() const {
501   return kDefaultSslOrigin;
502 }
503
504 std::string DataReductionProxyParams::GetDefaultAltOrigin() const {
505   return kDefaultAltOrigin;
506 }
507
508 std::string DataReductionProxyParams::GetDefaultAltFallbackOrigin() const {
509   return kDefaultAltFallbackOrigin;
510 }
511
512 std::string DataReductionProxyParams::GetDefaultProbeURL() const {
513   return kDefaultProbeUrl;
514 }
515
516 std::string DataReductionProxyParams::GetDefaultWarmupURL() const {
517   return kDefaultWarmupUrl;
518 }
519
520 }  // namespace data_reduction_proxy