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