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_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
;
26 const char kEnabled
[] = "Enabled";
29 namespace data_reduction_proxy
{
32 bool DataReductionProxyParams::IsIncludedInFieldTrial() {
33 return base::FieldTrialList::FindFullName(
34 "DataCompressionProxyRollout") == kEnabled
;
38 bool DataReductionProxyParams::IsIncludedInAlternativeFieldTrial() {
39 return base::FieldTrialList::FindFullName(
40 "DataCompressionProxyAlternativeConfiguration") == kEnabled
;
44 bool DataReductionProxyParams::IsIncludedInPromoFieldTrial() {
45 return FieldTrialList::FindFullName(
46 "DataCompressionProxyPromoVisibility") == kEnabled
;
50 bool DataReductionProxyParams::IsIncludedInPreconnectHintingFieldTrial() {
51 return IsIncludedInFieldTrial() &&
52 FieldTrialList::FindFullName(
53 "DataCompressionProxyPreconnectHints") == kEnabled
;
57 bool DataReductionProxyParams::IsIncludedInCriticalPathBypassFieldTrial() {
58 return IsIncludedInFieldTrial() &&
59 FieldTrialList::FindFullName(
60 "DataCompressionProxyCriticalBypass") == kEnabled
;
63 DataReductionProxyTypeInfo::DataReductionProxyTypeInfo()
66 is_alternative(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_
);
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
;
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_
);
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_
);
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_
);
149 bool DataReductionProxyParams::Init(
150 bool allowed
, bool fallback_allowed
, bool alt_allowed
) {
152 // Verify that all necessary params are set.
154 if (!origin_
.is_valid()) {
155 DVLOG(1) << "Invalid data reduction proxy origin: " << origin_
.spec();
160 if (allowed
&& fallback_allowed
) {
161 if (!fallback_origin_
.is_valid()) {
162 DVLOG(1) << "Invalid data reduction proxy fallback origin: "
163 << fallback_origin_
.spec();
170 DVLOG(1) << "Alternative data reduction proxy configuration cannot "
171 << "be allowed if the regular configuration is not allowed";
174 if (!alt_origin_
.is_valid()) {
175 DVLOG(1) << "Invalid alternative origin:" << alt_origin_
.spec();
178 if (!ssl_origin_
.is_valid()) {
179 DVLOG(1) << "Invalid ssl origin: " << ssl_origin_
.spec();
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();
192 if (allowed
&& !probe_url_
.is_valid()) {
193 DVLOG(1) << "Invalid probe url: <null>";
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";
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";
211 void DataReductionProxyParams::InitWithoutChecks() {
212 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
214 if (!command_line
.HasSwitch(switches::kDisableDataReductionProxyDev
)) {
215 origin
= command_line
.GetSwitchValueASCII(
216 switches::kDataReductionProxyDev
);
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_
)
238 if (!(ssl_origin
.empty() &&
239 alt_origin
.empty() &&
240 alt_fallback_origin
.empty()))
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
251 origin
= GetDefaultDevOrigin();
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 {
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
)) {
289 proxy_info
->proxy_servers
.first
= origin();
290 if (fallback_allowed())
291 proxy_info
->proxy_servers
.second
= fallback_origin();
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
)) {
304 proxy_info
->proxy_servers
.first
= default_origin
;
305 if (fallback_allowed())
306 proxy_info
->proxy_servers
.second
= fallback_origin();
312 if (fallback_allowed() &&
313 net::HostPortPair::FromURL(fallback_origin()).Equals(host_port_pair
)) {
315 proxy_info
->proxy_servers
.first
= fallback_origin();
316 proxy_info
->proxy_servers
.second
= GURL();
317 proxy_info
->is_fallback
= true;
321 if (net::HostPortPair::FromURL(alt_origin()).Equals(host_port_pair
)) {
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();
330 if (fallback_allowed() &&
331 net::HostPortPair::FromURL(alt_fallback_origin()).Equals(
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;
341 if (net::HostPortPair::FromURL(ssl_origin()).Equals(host_port_pair
)) {
343 proxy_info
->proxy_servers
.first
= ssl_origin();
344 proxy_info
->proxy_servers
.second
= GURL();
345 proxy_info
->is_ssl
= true;
352 // TODO(kundaji): Check that the request will actually be sent through the
354 bool DataReductionProxyParams::IsDataReductionProxyEligible(
355 const net::URLRequest
* 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())
364 if (result
.proxy_server().is_direct())
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") ==
377 return DATA_REDUCTION_DEV_HOST
;
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
),
396 bool DataReductionProxyParams::AreProxiesBypassed(
397 const net::ProxyRetryInfoMap
& retry_map
,
399 base::TimeDelta
* min_retry_delay
) const {
400 if (retry_map
.size() == 0)
403 // If the request is https, consider only the ssl proxy.
406 return ArePrimaryAndFallbackBypassed(
407 retry_map
, ssl_origin_
, GURL(), min_retry_delay
);
413 if (allowed_
&& ArePrimaryAndFallbackBypassed(
414 retry_map
, origin_
, fallback_origin_
, min_retry_delay
)) {
418 if (alt_allowed_
&& ArePrimaryAndFallbackBypassed(
419 retry_map
, alt_origin_
, alt_fallback_origin_
, min_retry_delay
)) {
426 bool DataReductionProxyParams::ArePrimaryAndFallbackBypassed(
427 const net::ProxyRetryInfoMap
& retry_map
,
429 const GURL
& fallback
,
430 base::TimeDelta
* min_retry_delay
) const {
431 net::ProxyRetryInfoMap::const_iterator found
= retry_map
.end();
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() &&
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
;
472 return std::string();
475 std::string
DataReductionProxyParams::GetDefaultFallbackOrigin() const {
476 #if defined(DATA_REDUCTION_FALLBACK_HOST)
477 return DATA_REDUCTION_FALLBACK_HOST
;
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
;
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
;
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
;
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
;
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
;
514 return std::string();
517 } // namespace data_reduction_proxy