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 "base/command_line.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/metrics/field_trial.h"
10 #include "base/time/time.h"
11 #include "components/data_reduction_proxy/common/data_reduction_proxy_switches.h"
12 #include "net/base/host_port_pair.h"
13 #include "net/proxy/proxy_info.h"
14 #include "net/proxy/proxy_retry_info.h"
15 #include "net/proxy/proxy_server.h"
16 #include "net/proxy/proxy_service.h"
17 #include "net/url_request/url_request.h"
18 #include "net/url_request/url_request_context.h"
19 #include "url/url_constants.h"
21 using base::FieldTrialList
;
24 const char kEnabled
[] = "Enabled";
27 namespace data_reduction_proxy
{
30 bool DataReductionProxyParams::IsIncludedInFieldTrial() {
31 return base::FieldTrialList::FindFullName(
32 "DataCompressionProxyRollout") == kEnabled
;
36 bool DataReductionProxyParams::IsIncludedInAlternativeFieldTrial() {
37 return base::FieldTrialList::FindFullName(
38 "DataCompressionProxyAlternativeConfiguration") == kEnabled
;
42 bool DataReductionProxyParams::IsIncludedInPromoFieldTrial() {
43 return FieldTrialList::FindFullName(
44 "DataCompressionProxyPromoVisibility") == kEnabled
;
48 bool DataReductionProxyParams::IsIncludedInPreconnectHintingFieldTrial() {
49 return IsIncludedInFieldTrial() &&
50 FieldTrialList::FindFullName(
51 "DataCompressionProxyPreconnectHints") == kEnabled
;
55 bool DataReductionProxyParams::IsIncludedInCriticalPathBypassFieldTrial() {
56 return IsIncludedInFieldTrial() &&
57 FieldTrialList::FindFullName(
58 "DataCompressionProxyCriticalBypass") == kEnabled
;
61 bool DataReductionProxyParams::IsIncludedInHoldbackFieldTrial() {
62 return FieldTrialList::FindFullName(
63 "DataCompressionProxyHoldback") == kEnabled
;
66 DataReductionProxyParams::DataReductionProxyParams(int flags
)
67 : allowed_((flags
& kAllowed
) == kAllowed
),
68 fallback_allowed_((flags
& kFallbackAllowed
) == kFallbackAllowed
),
69 alt_allowed_((flags
& kAlternativeAllowed
) == kAlternativeAllowed
),
70 promo_allowed_((flags
& kPromoAllowed
) == kPromoAllowed
),
71 holdback_((flags
& kHoldback
) == kHoldback
),
72 configured_on_command_line_(false) {
73 bool result
= Init(allowed_
, fallback_allowed_
, alt_allowed_
);
77 scoped_ptr
<DataReductionProxyParams
> DataReductionProxyParams::Clone() {
78 return scoped_ptr
<DataReductionProxyParams
>(
79 new DataReductionProxyParams(*this));
82 DataReductionProxyParams::DataReductionProxyParams(
83 const DataReductionProxyParams
& other
)
84 : origin_(other
.origin_
),
85 fallback_origin_(other
.fallback_origin_
),
86 ssl_origin_(other
.ssl_origin_
),
87 alt_origin_(other
.alt_origin_
),
88 alt_fallback_origin_(other
.alt_fallback_origin_
),
89 probe_url_(other
.probe_url_
),
90 warmup_url_(other
.warmup_url_
),
91 allowed_(other
.allowed_
),
92 fallback_allowed_(other
.fallback_allowed_
),
93 alt_allowed_(other
.alt_allowed_
),
94 promo_allowed_(other
.promo_allowed_
),
95 holdback_(other
.holdback_
),
96 configured_on_command_line_(other
.configured_on_command_line_
) {
99 DataReductionProxyParams::~DataReductionProxyParams() {
102 DataReductionProxyParams::DataReductionProxyList
103 DataReductionProxyParams::GetAllowedProxies() const {
104 DataReductionProxyList list
;
106 list
.push_back(origin_
);
107 // TODO(bolian): revert this once the proxy PAC fix is ready.
108 if (GURL(GetDefaultDevOrigin()) == origin()) {
109 list
.push_back(GURL(GetDefaultOrigin()));
112 if (allowed_
&& fallback_allowed_
)
113 list
.push_back(fallback_origin_
);
115 list
.push_back(alt_origin_
);
116 list
.push_back(ssl_origin_
);
118 if (alt_allowed_
&& fallback_allowed_
)
119 list
.push_back(alt_fallback_origin_
);
123 DataReductionProxyParams::DataReductionProxyParams(int flags
,
124 bool should_call_init
)
125 : allowed_((flags
& kAllowed
) == kAllowed
),
126 fallback_allowed_((flags
& kFallbackAllowed
) == kFallbackAllowed
),
127 alt_allowed_((flags
& kAlternativeAllowed
) == kAlternativeAllowed
),
128 promo_allowed_((flags
& kPromoAllowed
) == kPromoAllowed
),
129 holdback_((flags
& kHoldback
) == kHoldback
),
130 configured_on_command_line_(false) {
131 if (should_call_init
) {
132 bool result
= Init(allowed_
, fallback_allowed_
, alt_allowed_
);
137 bool DataReductionProxyParams::Init(
138 bool allowed
, bool fallback_allowed
, bool alt_allowed
) {
140 // Verify that all necessary params are set.
142 if (!origin_
.is_valid()) {
143 DVLOG(1) << "Invalid data reduction proxy origin: " << origin_
.spec();
148 if (allowed
&& fallback_allowed
) {
149 if (!fallback_origin_
.is_valid()) {
150 DVLOG(1) << "Invalid data reduction proxy fallback origin: "
151 << fallback_origin_
.spec();
158 DVLOG(1) << "Alternative data reduction proxy configuration cannot "
159 << "be allowed if the regular configuration is not allowed";
162 if (!alt_origin_
.is_valid()) {
163 DVLOG(1) << "Invalid alternative origin:" << alt_origin_
.spec();
166 if (!ssl_origin_
.is_valid()) {
167 DVLOG(1) << "Invalid ssl origin: " << ssl_origin_
.spec();
172 if (alt_allowed
&& fallback_allowed
) {
173 if (!alt_fallback_origin_
.is_valid()) {
174 DVLOG(1) << "Invalid alternative fallback origin:"
175 << alt_fallback_origin_
.spec();
180 if (allowed
&& !probe_url_
.is_valid()) {
181 DVLOG(1) << "Invalid probe url: <null>";
185 if (fallback_allowed_
&& !allowed_
) {
186 DVLOG(1) << "The data reduction proxy fallback cannot be allowed if "
187 << "the data reduction proxy is not allowed";
190 if (promo_allowed_
&& !allowed_
) {
191 DVLOG(1) << "The data reduction proxy promo cannot be allowed if the "
192 << "data reduction proxy is not allowed";
199 void DataReductionProxyParams::InitWithoutChecks() {
200 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
202 if (!command_line
.HasSwitch(switches::kDisableDataReductionProxyDev
)) {
203 origin
= command_line
.GetSwitchValueASCII(
204 switches::kDataReductionProxyDev
);
207 origin
= command_line
.GetSwitchValueASCII(switches::kDataReductionProxy
);
208 std::string fallback_origin
=
209 command_line
.GetSwitchValueASCII(switches::kDataReductionProxyFallback
);
210 std::string ssl_origin
=
211 command_line
.GetSwitchValueASCII(switches::kDataReductionSSLProxy
);
212 std::string alt_origin
=
213 command_line
.GetSwitchValueASCII(switches::kDataReductionProxyAlt
);
214 std::string alt_fallback_origin
= command_line
.GetSwitchValueASCII(
215 switches::kDataReductionProxyAltFallback
);
217 configured_on_command_line_
=
218 !(origin
.empty() && fallback_origin
.empty() && ssl_origin
.empty() &&
219 alt_origin
.empty() && alt_fallback_origin
.empty());
222 // Configuring the proxy on the command line overrides the values of
223 // |allowed_| and |alt_allowed_|.
224 if (configured_on_command_line_
)
226 if (!(ssl_origin
.empty() &&
227 alt_origin
.empty() &&
228 alt_fallback_origin
.empty()))
231 std::string probe_url
= command_line
.GetSwitchValueASCII(
232 switches::kDataReductionProxyProbeURL
);
233 std::string warmup_url
= command_line
.GetSwitchValueASCII(
234 switches::kDataReductionProxyWarmupURL
);
236 // Set from preprocessor constants those params that are not specified on the
239 origin
= GetDefaultDevOrigin();
241 origin
= GetDefaultOrigin();
242 if (fallback_origin
.empty())
243 fallback_origin
= GetDefaultFallbackOrigin();
244 if (ssl_origin
.empty())
245 ssl_origin
= GetDefaultSSLOrigin();
246 if (alt_origin
.empty())
247 alt_origin
= GetDefaultAltOrigin();
248 if (alt_fallback_origin
.empty())
249 alt_fallback_origin
= GetDefaultAltFallbackOrigin();
250 if (probe_url
.empty())
251 probe_url
= GetDefaultProbeURL();
252 if (warmup_url
.empty())
253 warmup_url
= GetDefaultWarmupURL();
255 origin_
= GURL(origin
);
256 fallback_origin_
= GURL(fallback_origin
);
257 ssl_origin_
= GURL(ssl_origin
);
258 alt_origin_
= GURL(alt_origin
);
259 alt_fallback_origin_
= GURL(alt_fallback_origin
);
260 probe_url_
= GURL(probe_url
);
261 warmup_url_
= GURL(warmup_url
);
265 bool DataReductionProxyParams::WasDataReductionProxyUsed(
266 const net::URLRequest
* request
,
267 std::pair
<GURL
, GURL
>* proxy_servers
) const {
269 return IsDataReductionProxy(request
->proxy_server(), proxy_servers
);
272 bool DataReductionProxyParams::IsDataReductionProxy(
273 const net::HostPortPair
& host_port_pair
,
274 std::pair
<GURL
, GURL
>* proxy_servers
) const {
275 if (net::HostPortPair::FromURL(origin()).Equals(host_port_pair
)) {
277 (*proxy_servers
).first
= origin();
278 if (fallback_allowed())
279 (*proxy_servers
).second
= fallback_origin();
284 // TODO(bolian): revert this once the proxy PAC fix is ready.
286 // If dev host is configured as the primary proxy, we treat the default
287 // origin as a valid data reduction proxy to workaround PAC script.
288 if (GURL(GetDefaultDevOrigin()) == origin()) {
289 const GURL
& default_origin
= GURL(GetDefaultOrigin());
290 if (net::HostPortPair::FromURL(default_origin
).Equals(host_port_pair
)) {
292 (*proxy_servers
).first
= default_origin
;
293 if (fallback_allowed())
294 (*proxy_servers
).second
= fallback_origin();
300 if (fallback_allowed() &&
301 net::HostPortPair::FromURL(fallback_origin()).Equals(host_port_pair
)) {
303 (*proxy_servers
).first
= fallback_origin();
304 (*proxy_servers
).second
= GURL();
308 if (net::HostPortPair::FromURL(alt_origin()).Equals(host_port_pair
)) {
310 (*proxy_servers
).first
= alt_origin();
311 if (fallback_allowed())
312 (*proxy_servers
).second
= alt_fallback_origin();
316 if (fallback_allowed() &&
317 net::HostPortPair::FromURL(alt_fallback_origin()).Equals(
320 (*proxy_servers
).first
= alt_fallback_origin();
321 (*proxy_servers
).second
= GURL();
325 if (net::HostPortPair::FromURL(ssl_origin()).Equals(host_port_pair
)) {
327 (*proxy_servers
).first
= ssl_origin();
328 (*proxy_servers
).second
= GURL();
335 // TODO(kundaji): Check that the request will actually be sent through the
337 bool DataReductionProxyParams::IsDataReductionProxyEligible(
338 const net::URLRequest
* request
) {
340 DCHECK(request
->context());
341 DCHECK(request
->context()->proxy_service());
342 net::ProxyInfo result
;
343 request
->context()->proxy_service()->config().proxy_rules().Apply(
344 request
->url(), &result
);
345 if (!result
.proxy_server().is_valid())
347 if (result
.proxy_server().is_direct())
349 return IsDataReductionProxy(result
.proxy_server().host_port_pair(), NULL
);
352 std::string
DataReductionProxyParams::GetDefaultDevOrigin() const {
353 #if defined(DATA_REDUCTION_DEV_HOST)
354 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
355 if (command_line
.HasSwitch(switches::kDisableDataReductionProxyDev
))
356 return std::string();
357 if (command_line
.HasSwitch(switches::kEnableDataReductionProxyDev
) ||
358 (FieldTrialList::FindFullName("DataCompressionProxyDevRollout") ==
360 return DATA_REDUCTION_DEV_HOST
;
363 return std::string();
366 bool DataReductionProxyParams::AreDataReductionProxiesBypassed(
367 const net::URLRequest
& request
, base::TimeDelta
* min_retry_delay
) const {
368 if (request
.context() != NULL
&&
369 request
.context()->proxy_service() != NULL
) {
370 return AreProxiesBypassed(
371 request
.context()->proxy_service()->proxy_retry_info(),
372 request
.url().SchemeIs(url::kHttpsScheme
),
379 bool DataReductionProxyParams::AreProxiesBypassed(
380 const net::ProxyRetryInfoMap
& retry_map
,
382 base::TimeDelta
* min_retry_delay
) const {
383 if (retry_map
.size() == 0)
386 if (is_https
&& alt_allowed_
) {
387 return ArePrimaryAndFallbackBypassed(
388 retry_map
, ssl_origin_
, GURL(), min_retry_delay
);
391 if (allowed_
&& ArePrimaryAndFallbackBypassed(
392 retry_map
, origin_
, fallback_origin_
, min_retry_delay
)) {
396 if (alt_allowed_
&& ArePrimaryAndFallbackBypassed(
397 retry_map
, alt_origin_
, alt_fallback_origin_
, min_retry_delay
)) {
404 bool DataReductionProxyParams::ArePrimaryAndFallbackBypassed(
405 const net::ProxyRetryInfoMap
& retry_map
,
407 const GURL
& fallback
,
408 base::TimeDelta
* min_retry_delay
) const {
409 net::ProxyRetryInfoMap::const_iterator found
= retry_map
.find(
410 net::ProxyServer(primary
.SchemeIs(url::kHttpsScheme
) ?
411 net::ProxyServer::SCHEME_HTTPS
: net::ProxyServer::SCHEME_HTTP
,
412 net::HostPortPair::FromURL(primary
)).ToURI());
414 if (found
== retry_map
.end())
417 base::TimeDelta min_delay
= found
->second
.current_delay
;
418 if (!fallback_allowed_
|| !fallback
.is_valid()) {
419 if (min_retry_delay
!= NULL
)
420 *min_retry_delay
= min_delay
;
424 found
= retry_map
.find(
425 net::ProxyServer(fallback
.SchemeIs(url::kHttpsScheme
) ?
426 net::ProxyServer::SCHEME_HTTPS
: net::ProxyServer::SCHEME_HTTP
,
427 net::HostPortPair::FromURL(fallback
)).ToURI());
429 if (found
== retry_map
.end())
432 if (min_delay
> found
->second
.current_delay
)
433 min_delay
= found
->second
.current_delay
;
434 if (min_retry_delay
!= NULL
)
435 *min_retry_delay
= min_delay
;
439 std::string
DataReductionProxyParams::GetDefaultOrigin() const {
440 #if defined(SPDY_PROXY_AUTH_ORIGIN)
441 return SPDY_PROXY_AUTH_ORIGIN
;
443 return std::string();
446 std::string
DataReductionProxyParams::GetDefaultFallbackOrigin() const {
447 #if defined(DATA_REDUCTION_FALLBACK_HOST)
448 return DATA_REDUCTION_FALLBACK_HOST
;
450 return std::string();
453 std::string
DataReductionProxyParams::GetDefaultSSLOrigin() const {
454 #if defined(DATA_REDUCTION_PROXY_SSL_ORIGIN)
455 return DATA_REDUCTION_PROXY_SSL_ORIGIN
;
457 return std::string();
460 std::string
DataReductionProxyParams::GetDefaultAltOrigin() const {
461 #if defined(DATA_REDUCTION_PROXY_ALT_ORIGIN)
462 return DATA_REDUCTION_PROXY_ALT_ORIGIN
;
464 return std::string();
467 std::string
DataReductionProxyParams::GetDefaultAltFallbackOrigin() const {
468 #if defined(DATA_REDUCTION_PROXY_ALT_FALLBACK_ORIGIN)
469 return DATA_REDUCTION_PROXY_ALT_FALLBACK_ORIGIN
;
471 return std::string();
474 std::string
DataReductionProxyParams::GetDefaultProbeURL() const {
475 #if defined(DATA_REDUCTION_PROXY_PROBE_URL)
476 return DATA_REDUCTION_PROXY_PROBE_URL
;
478 return std::string();
481 std::string
DataReductionProxyParams::GetDefaultWarmupURL() const {
482 #if defined(DATA_REDUCTION_PROXY_WARMUP_URL)
483 return DATA_REDUCTION_PROXY_WARMUP_URL
;
485 return std::string();
488 } // namespace data_reduction_proxy