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"
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"
24 using base::FieldTrialList
;
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";
44 namespace data_reduction_proxy
{
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
)) {
54 return group_name
== kEnabled
;
58 bool DataReductionProxyParams::IsIncludedInPromoFieldTrial() {
59 return FieldTrialList::FindFullName(
60 "DataCompressionProxyPromoVisibility") == kEnabled
;
64 bool DataReductionProxyParams::IsIncludedInPreconnectHintingFieldTrial() {
65 return FieldTrialList::FindFullName(
66 "DataCompressionProxyPreconnectHints") == kEnabled
;
70 bool DataReductionProxyParams::IsIncludedInCriticalPathBypassFieldTrial() {
71 return FieldTrialList::FindFullName(
72 "DataCompressionProxyCriticalBypass") == kEnabled
;
76 bool DataReductionProxyParams::IsIncludedInHoldbackFieldTrial() {
77 return FieldTrialList::FindFullName(
78 "DataCompressionProxyHoldback") == kEnabled
;
82 bool DataReductionProxyParams::
83 IsIncludedInRemoveMissingViaHeaderOtherBypassFieldTrial() {
84 return FieldTrialList::FindFullName(
85 "DataReductionProxyRemoveMissingViaHeaderOtherBypass") == kEnabled
;
88 DataReductionProxyTypeInfo::DataReductionProxyTypeInfo()
91 is_alternative(false),
95 DataReductionProxyTypeInfo::~DataReductionProxyTypeInfo(){
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) {
108 allowed_
, fallback_allowed_
, alt_allowed_
, alt_fallback_allowed_
);
112 scoped_ptr
<DataReductionProxyParams
> DataReductionProxyParams::Clone() {
113 return scoped_ptr
<DataReductionProxyParams
>(
114 new DataReductionProxyParams(*this));
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_
) {
135 DataReductionProxyParams::~DataReductionProxyParams() {
138 DataReductionProxyParams::DataReductionProxyList
139 DataReductionProxyParams::GetAllowedProxies() const {
140 DataReductionProxyList list
;
142 list
.push_back(origin_
);
144 if (allowed_
&& fallback_allowed_
)
145 list
.push_back(fallback_origin_
);
147 list
.push_back(alt_origin_
);
148 list
.push_back(ssl_origin_
);
150 if (alt_allowed_
&& alt_fallback_allowed_
)
151 list
.push_back(alt_fallback_origin_
);
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
) {
167 allowed_
, fallback_allowed_
, alt_allowed_
, alt_fallback_allowed_
);
172 bool DataReductionProxyParams::Init(bool allowed
,
173 bool fallback_allowed
,
175 bool alt_fallback_allowed
) {
177 // Verify that all necessary params are set.
179 if (!origin_
.is_valid()) {
180 DVLOG(1) << "Invalid data reduction proxy origin: " << origin_
.spec();
185 if (allowed
&& fallback_allowed
) {
186 if (!fallback_origin_
.is_valid()) {
187 DVLOG(1) << "Invalid data reduction proxy fallback origin: "
188 << fallback_origin_
.spec();
195 DVLOG(1) << "Alternative data reduction proxy configuration cannot "
196 << "be allowed if the regular configuration is not allowed";
199 if (!alt_origin_
.is_valid()) {
200 DVLOG(1) << "Invalid alternative origin:" << alt_origin_
.spec();
203 if (!ssl_origin_
.is_valid()) {
204 DVLOG(1) << "Invalid ssl origin: " << ssl_origin_
.spec();
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();
217 if (allowed
&& !probe_url_
.is_valid()) {
218 DVLOG(1) << "Invalid probe url: <null>";
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";
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";
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";
241 void DataReductionProxyParams::InitWithoutChecks() {
242 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
244 if (!command_line
.HasSwitch(switches::kDisableDataReductionProxyDev
)) {
245 origin
= command_line
.GetSwitchValueASCII(
246 switches::kDataReductionProxyDev
);
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
);
259 configured_on_command_line_
=
260 !(origin
.empty() && fallback_origin
.empty() && ssl_origin
.empty() &&
261 alt_origin
.empty() && alt_fallback_origin
.empty());
264 // Configuring the proxy on the command line overrides the values of
265 // |allowed_| and |alt_allowed_|.
266 if (configured_on_command_line_
)
268 if (!(ssl_origin
.empty() &&
272 std::string probe_url
= command_line
.GetSwitchValueASCII(
273 switches::kDataReductionProxyProbeURL
);
274 std::string warmup_url
= command_line
.GetSwitchValueASCII(
275 switches::kDataReductionProxyWarmupURL
);
277 // Set from preprocessor constants those params that are not specified on the
280 origin
= GetDefaultDevOrigin();
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();
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
);
308 bool DataReductionProxyParams::WasDataReductionProxyUsed(
309 const net::URLRequest
* request
,
310 DataReductionProxyTypeInfo
* proxy_info
) const {
312 return IsDataReductionProxy(request
->proxy_server(), proxy_info
);
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
)) {
320 proxy_info
->proxy_servers
.first
= origin();
321 if (fallback_allowed())
322 proxy_info
->proxy_servers
.second
= fallback_origin();
327 if (fallback_allowed() &&
328 net::HostPortPair::FromURL(fallback_origin()).Equals(host_port_pair
)) {
330 proxy_info
->proxy_servers
.first
= fallback_origin();
331 proxy_info
->proxy_servers
.second
= GURL();
332 proxy_info
->is_fallback
= true;
336 if (net::HostPortPair::FromURL(alt_origin()).Equals(host_port_pair
)) {
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();
345 if (alternative_fallback_allowed() &&
346 net::HostPortPair::FromURL(alt_fallback_origin()).Equals(
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;
356 if (net::HostPortPair::FromURL(ssl_origin()).Equals(host_port_pair
)) {
358 proxy_info
->proxy_servers
.first
= ssl_origin();
359 proxy_info
->proxy_servers
.second
= GURL();
360 proxy_info
->is_ssl
= true;
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())
377 if (result
.proxy_server().is_direct())
379 return !IsDataReductionProxy(result
.proxy_server().host_port_pair(), NULL
);
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") ==
391 return std::string();
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") ==
401 return kDevFallbackOrigin
;
403 return std::string();
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
),
419 bool DataReductionProxyParams::AreProxiesBypassed(
420 const net::ProxyRetryInfoMap
& retry_map
,
422 base::TimeDelta
* min_retry_delay
) const {
423 if (retry_map
.size() == 0)
426 // If the request is https, consider only the ssl proxy.
429 return ArePrimaryAndFallbackBypassed(
430 retry_map
, ssl_origin_
, GURL(), min_retry_delay
);
436 if (allowed_
&& ArePrimaryAndFallbackBypassed(
437 retry_map
, origin_
, fallback_origin_
, min_retry_delay
)) {
441 if (alt_allowed_
&& ArePrimaryAndFallbackBypassed(
442 retry_map
, alt_origin_
, alt_fallback_origin_
, min_retry_delay
)) {
449 bool DataReductionProxyParams::ArePrimaryAndFallbackBypassed(
450 const net::ProxyRetryInfoMap
& retry_map
,
452 const GURL
& fallback
,
453 base::TimeDelta
* min_retry_delay
) const {
454 net::ProxyRetryInfoMap::const_iterator found
= retry_map
.end();
456 *min_retry_delay
= base::TimeDelta::Max();
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
;
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() &&
483 *min_retry_delay
> found
->second
.current_delay
) {
484 *min_retry_delay
= found
->second
.current_delay
;
488 return found
!= retry_map
.end();
491 // TODO(kundaji): Remove tests for macro definitions.
492 std::string
DataReductionProxyParams::GetDefaultOrigin() const {
493 return kDefaultOrigin
;
496 std::string
DataReductionProxyParams::GetDefaultFallbackOrigin() const {
497 return kDefaultFallbackOrigin
;
500 std::string
DataReductionProxyParams::GetDefaultSSLOrigin() const {
501 return kDefaultSslOrigin
;
504 std::string
DataReductionProxyParams::GetDefaultAltOrigin() const {
505 return kDefaultAltOrigin
;
508 std::string
DataReductionProxyParams::GetDefaultAltFallbackOrigin() const {
509 return kDefaultAltFallbackOrigin
;
512 std::string
DataReductionProxyParams::GetDefaultProbeURL() const {
513 return kDefaultProbeUrl
;
516 std::string
DataReductionProxyParams::GetDefaultWarmupURL() const {
517 return kDefaultWarmupUrl
;
520 } // namespace data_reduction_proxy