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/core/common/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 "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"
26 using base::FieldTrialList;
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";
46 namespace data_reduction_proxy {
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)) {
56 return group_name == kEnabled;
60 bool DataReductionProxyParams::IsIncludedInPromoFieldTrial() {
61 return FieldTrialList::FindFullName(
62 "DataCompressionProxyPromoVisibility") == kEnabled;
66 bool DataReductionProxyParams::IsIncludedInPreconnectHintingFieldTrial() {
67 return FieldTrialList::FindFullName(
68 "DataCompressionProxyPreconnectHints") == kEnabled;
72 bool DataReductionProxyParams::IsIncludedInCriticalPathBypassFieldTrial() {
73 return FieldTrialList::FindFullName(
74 "DataCompressionProxyCriticalBypass") == kEnabled;
78 bool DataReductionProxyParams::IsIncludedInHoldbackFieldTrial() {
79 return FieldTrialList::FindFullName(
80 "DataCompressionProxyHoldback") == kEnabled;
84 bool DataReductionProxyParams::
85 IsIncludedInRemoveMissingViaHeaderOtherBypassFieldTrial() {
86 return FieldTrialList::FindFullName(
87 "DataReductionProxyRemoveMissingViaHeaderOtherBypass") == kEnabled;
90 DataReductionProxyTypeInfo::DataReductionProxyTypeInfo()
93 is_alternative(false),
97 DataReductionProxyTypeInfo::~DataReductionProxyTypeInfo(){
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) {
110 allowed_, fallback_allowed_, alt_allowed_, alt_fallback_allowed_);
114 scoped_ptr<DataReductionProxyParams> DataReductionProxyParams::Clone() {
115 return scoped_ptr<DataReductionProxyParams>(
116 new DataReductionProxyParams(*this));
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_) {
137 DataReductionProxyParams::~DataReductionProxyParams() {
140 DataReductionProxyParams::DataReductionProxyList
141 DataReductionProxyParams::GetAllowedProxies() const {
142 DataReductionProxyList list;
144 list.push_back(origin_);
146 if (allowed_ && fallback_allowed_)
147 list.push_back(fallback_origin_);
149 list.push_back(alt_origin_);
150 list.push_back(ssl_origin_);
152 if (alt_allowed_ && alt_fallback_allowed_)
153 list.push_back(alt_fallback_origin_);
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) {
169 allowed_, fallback_allowed_, alt_allowed_, alt_fallback_allowed_);
174 bool DataReductionProxyParams::Init(bool allowed,
175 bool fallback_allowed,
177 bool alt_fallback_allowed) {
179 // Verify that all necessary params are set.
181 if (!origin_.is_valid()) {
182 DVLOG(1) << "Invalid data reduction proxy origin: " << origin_.spec();
187 if (allowed && fallback_allowed) {
188 if (!fallback_origin_.is_valid()) {
189 DVLOG(1) << "Invalid data reduction proxy fallback origin: "
190 << fallback_origin_.spec();
197 DVLOG(1) << "Alternative data reduction proxy configuration cannot "
198 << "be allowed if the regular configuration is not allowed";
201 if (!alt_origin_.is_valid()) {
202 DVLOG(1) << "Invalid alternative origin:" << alt_origin_.spec();
205 if (!ssl_origin_.is_valid()) {
206 DVLOG(1) << "Invalid ssl origin: " << ssl_origin_.spec();
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();
219 if (allowed && !probe_url_.is_valid()) {
220 DVLOG(1) << "Invalid probe url: <null>";
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";
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";
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";
243 void DataReductionProxyParams::InitWithoutChecks() {
244 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
246 if (!command_line.HasSwitch(switches::kDisableDataReductionProxyDev)) {
247 origin = command_line.GetSwitchValueASCII(
248 switches::kDataReductionProxyDev);
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);
261 configured_on_command_line_ =
262 !(origin.empty() && fallback_origin.empty() && ssl_origin.empty() &&
263 alt_origin.empty() && alt_fallback_origin.empty());
266 // Configuring the proxy on the command line overrides the values of
267 // |allowed_| and |alt_allowed_|.
268 if (configured_on_command_line_)
270 if (!(ssl_origin.empty() &&
274 std::string probe_url = command_line.GetSwitchValueASCII(
275 switches::kDataReductionProxyProbeURL);
276 std::string warmup_url = command_line.GetSwitchValueASCII(
277 switches::kDataReductionProxyWarmupURL);
279 // Set from preprocessor constants those params that are not specified on the
282 origin = GetDefaultDevOrigin();
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();
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);
310 bool DataReductionProxyParams::WasDataReductionProxyUsed(
311 const net::URLRequest* request,
312 DataReductionProxyTypeInfo* proxy_info) const {
314 return IsDataReductionProxy(request->proxy_server(), proxy_info);
317 bool DataReductionProxyParams::IsDataReductionProxy(
318 const net::HostPortPair& host_port_pair,
319 DataReductionProxyTypeInfo* proxy_info) const {
321 net::HostPortPair::FromURL(origin()).Equals(host_port_pair)) {
323 proxy_info->proxy_servers.first = origin();
324 if (fallback_allowed())
325 proxy_info->proxy_servers.second = fallback_origin();
330 if (fallback_allowed() &&
331 net::HostPortPair::FromURL(fallback_origin()).Equals(host_port_pair)) {
333 proxy_info->proxy_servers.first = fallback_origin();
334 proxy_info->proxy_servers.second = GURL();
335 proxy_info->is_fallback = true;
339 if (alternative_allowed() &&
340 net::HostPortPair::FromURL(alt_origin()).Equals(host_port_pair)) {
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();
349 if (alternative_fallback_allowed() &&
350 net::HostPortPair::FromURL(alt_fallback_origin()).Equals(
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;
360 if (net::HostPortPair::FromURL(ssl_origin()).Equals(host_port_pair)) {
362 proxy_info->proxy_servers.first = ssl_origin();
363 proxy_info->proxy_servers.second = GURL();
364 proxy_info->is_ssl = true;
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())
381 if (result.proxy_server().is_direct())
383 return !IsDataReductionProxy(result.proxy_server().host_port_pair(), NULL);
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") ==
395 return std::string();
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") ==
405 return kDevFallbackOrigin;
407 return std::string();
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),
424 bool DataReductionProxyParams::AreProxiesBypassed(
425 const net::ProxyRetryInfoMap& retry_map,
426 const net::ProxyConfig::ProxyRules& proxy_rules,
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)
433 const net::ProxyList* proxies = is_https ?
434 proxy_rules.MapUrlSchemeToProxyList(url::kHttpsScheme) :
435 proxy_rules.MapUrlSchemeToProxyList(url::kHttpScheme);
440 scoped_ptr<base::ListValue> proxy_list =
441 scoped_ptr<base::ListValue>(proxies->ToValue());
443 base::TimeDelta min_delay = base::TimeDelta::Max();
444 base::TimeDelta delay;
445 bool bypassed = false;
447 net::HostPortPair host_port_pair;
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);
455 if (IsDataReductionProxy(host_port_pair, NULL)) {
456 if (!IsProxyBypassed(
458 net::ProxyServer(GURL(proxy).SchemeIs(url::kHttpsScheme) ?
459 net::ProxyServer::SCHEME_HTTPS :
460 net::ProxyServer::SCHEME_HTTP,
464 if (delay < min_delay)
470 if (min_retry_delay && bypassed)
471 *min_retry_delay = min_delay;
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());
483 if (found == retry_map.end() ||
484 found->second.bad_until < base::TimeTicks::Now()) {
489 *retry_delay = found->second.current_delay;
494 // TODO(kundaji): Remove tests for macro definitions.
495 std::string DataReductionProxyParams::GetDefaultOrigin() const {
496 return kDefaultOrigin;
499 std::string DataReductionProxyParams::GetDefaultFallbackOrigin() const {
500 return kDefaultFallbackOrigin;
503 std::string DataReductionProxyParams::GetDefaultSSLOrigin() const {
504 return kDefaultSslOrigin;
507 std::string DataReductionProxyParams::GetDefaultAltOrigin() const {
508 return kDefaultAltOrigin;
511 std::string DataReductionProxyParams::GetDefaultAltFallbackOrigin() const {
512 return kDefaultAltFallbackOrigin;
515 std::string DataReductionProxyParams::GetDefaultProbeURL() const {
516 return kDefaultProbeUrl;
519 std::string DataReductionProxyParams::GetDefaultWarmupURL() const {
520 return kDefaultWarmupUrl;
523 } // namespace data_reduction_proxy