Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / net / spdyproxy / data_reduction_proxy_settings.cc
blob5e70162e37027946b703d2a6bb94747369c7304e
1 // Copyright 2013 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 "chrome/browser/net/spdyproxy/data_reduction_proxy_settings.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/metrics/field_trial.h"
10 #include "base/metrics/histogram.h"
11 #include "base/prefs/pref_member.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/prefs/scoped_user_pref_update.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "chrome/browser/browser_process.h"
19 #include "chrome/browser/prefs/proxy_prefs.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/profiles/profile_manager.h"
22 #include "chrome/common/chrome_switches.h"
23 #include "chrome/common/pref_names.h"
24 #include "crypto/random.h"
25 #include "net/base/auth.h"
26 #include "net/base/host_port_pair.h"
27 #include "net/base/load_flags.h"
28 #include "net/base/net_errors.h"
29 #include "net/http/http_auth.h"
30 #include "net/http/http_auth_cache.h"
31 #include "net/http/http_network_session.h"
32 #include "net/http/http_response_headers.h"
33 #include "net/url_request/url_fetcher.h"
34 #include "net/url_request/url_fetcher_delegate.h"
35 #include "net/url_request/url_request_status.h"
36 #include "url/gurl.h"
38 using base::FieldTrialList;
39 using base::StringPrintf;
40 using spdyproxy::ProbeURLFetchResult;
41 using spdyproxy::ProxyStartupState;
43 namespace {
45 // Key of the UMA DataReductionProxy.StartupState histogram.
46 const char kUMAProxyStartupStateHistogram[] =
47 "DataReductionProxy.StartupState";
49 // Key of the UMA DataReductionProxy.ProbeURL histogram.
50 const char kUMAProxyProbeURL[] = "DataReductionProxy.ProbeURL";
53 const char kEnabled[] = "Enabled";
55 // TODO(marq): Factor this string out into a constant here and in
56 // http_auth_handler_spdyproxy.
57 const char kAuthenticationRealmName[] = "SpdyProxy";
59 int64 GetInt64PrefValue(const base::ListValue& list_value, size_t index) {
60 int64 val = 0;
61 std::string pref_value;
62 bool rv = list_value.GetString(index, &pref_value);
63 DCHECK(rv);
64 if (rv) {
65 rv = base::StringToInt64(pref_value, &val);
66 DCHECK(rv);
68 return val;
71 bool IsProxyOriginSetOnCommandLine() {
72 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
73 return command_line.HasSwitch(switches::kSpdyProxyAuthOrigin);
76 } // namespace
78 DataReductionProxySettings::DataReductionProxySettings()
79 : restricted_by_carrier_(false),
80 enabled_by_user_(false) {
83 DataReductionProxySettings::~DataReductionProxySettings() {
84 if (IsDataReductionProxyAllowed())
85 spdy_proxy_auth_enabled_.Destroy();
88 void DataReductionProxySettings::InitPrefMembers() {
89 spdy_proxy_auth_enabled_.Init(
90 prefs::kSpdyProxyAuthEnabled,
91 GetOriginalProfilePrefs(),
92 base::Bind(&DataReductionProxySettings::OnProxyEnabledPrefChange,
93 base::Unretained(this)));
96 void DataReductionProxySettings::InitDataReductionProxySettings() {
97 InitPrefMembers();
98 RecordDataReductionInit();
100 // Disable the proxy if it is not allowed to be used.
101 if (!IsDataReductionProxyAllowed())
102 return;
104 AddDefaultProxyBypassRules();
105 net::NetworkChangeNotifier::AddIPAddressObserver(this);
107 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
109 // Setting the kEnableSpdyProxyAuth switch has the same effect as enabling
110 // the feature via settings, in that once set, the preference will be sticky
111 // across instances of Chrome. Disabling the feature can only be done through
112 // the settings menu.
113 if (spdy_proxy_auth_enabled_.GetValue() ||
114 command_line.HasSwitch(switches::kEnableSpdyProxyAuth)) {
115 MaybeActivateDataReductionProxy(true);
116 } else {
117 // This is logged so we can use this information in user feedback.
118 LogProxyState(false /* enabled */,
119 false /* restricted */,
120 true /* at startup */);
124 // static
125 void DataReductionProxySettings::InitDataReductionProxySession(
126 net::HttpNetworkSession* session) {
127 // This is a no-op unless the authentication parameters are compiled in.
128 // (even though values for them may be specified on the command line).
129 // Authentication will still work if the command line parameters are used,
130 // however there will be a round-trip overhead for each challenge/response
131 // (typically once per session).
132 #if defined(SPDY_PROXY_AUTH_ORIGIN) && defined(SPDY_PROXY_AUTH_VALUE)
133 DCHECK(session);
134 net::HttpAuthCache* auth_cache = session->http_auth_cache();
135 DCHECK(auth_cache);
136 InitDataReductionAuthentication(auth_cache);
137 #endif // defined(SPDY_PROXY_AUTH_ORIGIN) && defined(SPDY_PROXY_AUTH_VALUE)
140 // static
141 void DataReductionProxySettings::InitDataReductionAuthentication(
142 net::HttpAuthCache* auth_cache) {
143 DCHECK(auth_cache);
144 int64 timestamp =
145 (base::Time::Now() - base::Time::UnixEpoch()).InMilliseconds() / 1000;
147 DataReductionProxyList proxies = GetDataReductionProxies();
148 for (DataReductionProxyList::iterator it = proxies.begin();
149 it != proxies.end(); ++it) {
150 GURL auth_origin = (*it).GetOrigin();
151 int32 rand[3];
152 crypto::RandBytes(rand, 3 * sizeof(rand[0]));
154 std::string realm =
155 base::StringPrintf("%s%lld", kAuthenticationRealmName, timestamp);
156 std::string challenge = base::StringPrintf(
157 "%s realm=\"%s\", ps=\"%lld-%u-%u-%u\"", kAuthenticationRealmName,
158 realm.data(), timestamp, rand[0], rand[1], rand[2]);
159 base::string16 password = AuthHashForSalt(timestamp);
161 DVLOG(1) << "origin: [" << auth_origin << "] realm: [" << realm
162 << "] challenge: [" << challenge << "] password: [" << password << "]";
164 net::AuthCredentials credentials(base::string16(), password);
165 // |HttpAuthController| searches this cache by origin and path, the latter
166 // being '/' in the case of the data reduction proxy.
167 auth_cache->Add(auth_origin,
168 realm,
169 net::HttpAuth::AUTH_SCHEME_SPDYPROXY,
170 challenge,
171 credentials,
172 std::string("/"));
176 void DataReductionProxySettings::AddHostPatternToBypass(
177 const std::string& pattern) {
178 bypass_rules_.push_back(pattern);
181 void DataReductionProxySettings::AddURLPatternToBypass(
182 const std::string& pattern) {
183 size_t pos = pattern.find("/");
184 if (pattern.find("/", pos + 1) == pos + 1)
185 pos = pattern.find("/", pos + 2);
187 std::string host_pattern;
188 if (pos != std::string::npos)
189 host_pattern = pattern.substr(0, pos);
190 else
191 host_pattern = pattern;
193 AddHostPatternToBypass(host_pattern);
196 // static
197 bool DataReductionProxySettings::IsDataReductionProxyAllowed() {
198 return IsProxyOriginSetOnCommandLine() ||
199 (FieldTrialList::FindFullName("DataCompressionProxyRollout") == kEnabled);
202 // static
203 bool DataReductionProxySettings::IsDataReductionProxyPromoAllowed() {
204 return IsProxyOriginSetOnCommandLine() ||
205 (IsDataReductionProxyAllowed() &&
206 FieldTrialList::FindFullName("DataCompressionProxyPromoVisibility") ==
207 kEnabled);
210 // static
211 bool DataReductionProxySettings::IsPreconnectHintingAllowed() {
212 if (!IsDataReductionProxyAllowed())
213 return false;
214 return FieldTrialList::FindFullName("DataCompressionProxyPreconnectHints") ==
215 kEnabled;
218 // static
219 bool DataReductionProxySettings::WasFetchedViaProxy(
220 const net::HttpResponseHeaders* headers) {
221 const char kChromeProxyViaValue[] = "1.1 Chrome Compression Proxy";
222 void* iter = NULL;
223 std::string value;
224 while (headers->EnumerateHeader(&iter, "via", &value))
225 if (value == kChromeProxyViaValue) return true;
226 return false;
229 // static
230 std::string DataReductionProxySettings::GetDataReductionProxyOrigin() {
231 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
232 if (command_line.HasSwitch(switches::kSpdyProxyDevAuthOrigin))
233 return command_line.GetSwitchValueASCII(switches::kSpdyProxyDevAuthOrigin);
234 if (command_line.HasSwitch(switches::kSpdyProxyAuthOrigin))
235 return command_line.GetSwitchValueASCII(switches::kSpdyProxyAuthOrigin);
236 #if defined(DATA_REDUCTION_DEV_HOST)
237 if (FieldTrialList::FindFullName("DataCompressionProxyDevRollout") ==
238 kEnabled) {
239 return DATA_REDUCTION_DEV_HOST;
241 #endif
242 #if defined(SPDY_PROXY_AUTH_ORIGIN)
243 return SPDY_PROXY_AUTH_ORIGIN;
244 #else
245 return std::string();
246 #endif
249 // static
250 std::string DataReductionProxySettings::GetDataReductionProxyFallback() {
251 // Regardless of what else is defined, only return a value if the main proxy
252 // origin is defined.
253 if (GetDataReductionProxyOrigin().empty())
254 return std::string();
255 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
256 if (command_line.HasSwitch(switches::kSpdyProxyAuthFallback))
257 return command_line.GetSwitchValueASCII(switches::kSpdyProxyAuthFallback);
258 #if defined(DATA_REDUCTION_FALLBACK_HOST)
259 return DATA_REDUCTION_FALLBACK_HOST;
260 #else
261 return std::string();
262 #endif
265 bool DataReductionProxySettings::IsAcceptableAuthChallenge(
266 net::AuthChallengeInfo* auth_info) {
267 // Challenge realm must start with the authentication realm name.
268 std::string realm_prefix =
269 auth_info->realm.substr(0, strlen(kAuthenticationRealmName));
270 if (realm_prefix != kAuthenticationRealmName)
271 return false;
273 // The challenger must be one of the configured proxies.
274 DataReductionProxyList proxies = GetDataReductionProxies();
275 for (DataReductionProxyList::iterator it = proxies.begin();
276 it != proxies.end(); ++it) {
277 net::HostPortPair origin_host = net::HostPortPair::FromURL(*it);
278 if (origin_host.Equals(auth_info->challenger))
279 return true;
281 return false;
284 base::string16 DataReductionProxySettings::GetTokenForAuthChallenge(
285 net::AuthChallengeInfo* auth_info) {
286 if (auth_info->realm.length() > strlen(kAuthenticationRealmName)) {
287 int64 salt;
288 std::string realm_suffix =
289 auth_info->realm.substr(strlen(kAuthenticationRealmName));
290 if (base::StringToInt64(realm_suffix, &salt)) {
291 return AuthHashForSalt(salt);
292 } else {
293 DVLOG(1) << "Unable to parse realm name " << auth_info->realm
294 << "into an int for salting.";
295 return base::string16();
297 } else {
298 return base::string16();
302 bool DataReductionProxySettings::IsDataReductionProxyEnabled() {
303 return spdy_proxy_auth_enabled_.GetValue();
306 bool DataReductionProxySettings::IsDataReductionProxyManaged() {
307 return spdy_proxy_auth_enabled_.IsManaged();
310 // static
311 DataReductionProxySettings::DataReductionProxyList
312 DataReductionProxySettings::GetDataReductionProxies() {
313 DataReductionProxyList proxies;
314 std::string proxy = GetDataReductionProxyOrigin();
315 std::string fallback = GetDataReductionProxyFallback();
317 if (!proxy.empty())
318 proxies.push_back(GURL(proxy));
320 if (!fallback.empty()) {
321 // Sanity check: fallback isn't the only proxy.
322 DCHECK(!proxies.empty());
323 proxies.push_back(GURL(fallback));
326 return proxies;
329 void DataReductionProxySettings::SetDataReductionProxyEnabled(bool enabled) {
330 // Prevent configuring the proxy when it is not allowed to be used.
331 if (!IsDataReductionProxyAllowed())
332 return;
334 if (spdy_proxy_auth_enabled_.GetValue() != enabled) {
335 spdy_proxy_auth_enabled_.SetValue(enabled);
336 OnProxyEnabledPrefChange();
340 int64 DataReductionProxySettings::GetDataReductionLastUpdateTime() {
341 PrefService* local_state = GetLocalStatePrefs();
342 int64 last_update_internal =
343 local_state->GetInt64(prefs::kDailyHttpContentLengthLastUpdateDate);
344 base::Time last_update = base::Time::FromInternalValue(last_update_internal);
345 return static_cast<int64>(last_update.ToJsTime());
348 DataReductionProxySettings::ContentLengthList
349 DataReductionProxySettings::GetDailyOriginalContentLengths() {
350 return GetDailyContentLengths(prefs::kDailyHttpOriginalContentLength);
353 DataReductionProxySettings::ContentLengthList
354 DataReductionProxySettings::GetDailyReceivedContentLengths() {
355 return GetDailyContentLengths(prefs::kDailyHttpReceivedContentLength);
358 void DataReductionProxySettings::OnURLFetchComplete(
359 const net::URLFetcher* source) {
360 net::URLRequestStatus status = source->GetStatus();
361 if (status.status() == net::URLRequestStatus::FAILED &&
362 status.error() == net::ERR_INTERNET_DISCONNECTED) {
363 RecordProbeURLFetchResult(spdyproxy::INTERNET_DISCONNECTED);
364 return;
367 std::string response;
368 source->GetResponseAsString(&response);
370 if ("OK" == response.substr(0, 2)) {
371 DVLOG(1) << "The data reduction proxy is unrestricted.";
373 if (enabled_by_user_) {
374 if (restricted_by_carrier_) {
375 // The user enabled the proxy, but sometime previously in the session,
376 // the network operator had blocked the canary and restricted the user.
377 // The current network doesn't block the canary, so don't restrict the
378 // proxy configurations.
379 SetProxyConfigs(true /* enabled */,
380 false /* restricted */,
381 false /* at_startup */);
382 RecordProbeURLFetchResult(spdyproxy::SUCCEEDED_PROXY_ENABLED);
383 } else {
384 RecordProbeURLFetchResult(spdyproxy::SUCCEEDED_PROXY_ALREADY_ENABLED);
387 restricted_by_carrier_ = false;
388 return;
390 DVLOG(1) << "The data reduction proxy is restricted to the configured "
391 << "fallback proxy.";
393 if (enabled_by_user_) {
394 if (!restricted_by_carrier_) {
395 // Restrict the proxy.
396 SetProxyConfigs(true /* enabled */,
397 true /* restricted */,
398 false /* at_startup */);
399 RecordProbeURLFetchResult(spdyproxy::FAILED_PROXY_DISABLED);
400 } else {
401 RecordProbeURLFetchResult(spdyproxy::FAILED_PROXY_ALREADY_DISABLED);
404 restricted_by_carrier_ = true;
407 void DataReductionProxySettings::OnIPAddressChanged() {
408 if (enabled_by_user_) {
409 DCHECK(IsDataReductionProxyAllowed());
410 ProbeWhetherDataReductionProxyIsAvailable();
414 void DataReductionProxySettings::OnProxyEnabledPrefChange() {
415 if (!DataReductionProxySettings::IsDataReductionProxyAllowed())
416 return;
417 MaybeActivateDataReductionProxy(false);
420 void DataReductionProxySettings::AddDefaultProxyBypassRules() {
421 // localhost
422 AddHostPatternToBypass("<local>");
423 // RFC1918 private addresses.
424 AddHostPatternToBypass("10.0.0.0/8");
425 AddHostPatternToBypass("172.16.0.0/12");
426 AddHostPatternToBypass("192.168.0.0/16");
427 // RFC4193 private addresses.
428 AddHostPatternToBypass("fc00::/7");
429 // IPV6 probe addresses.
430 AddHostPatternToBypass("*-ds.metric.gstatic.com");
431 AddHostPatternToBypass("*-v4.metric.gstatic.com");
434 void DataReductionProxySettings::LogProxyState(
435 bool enabled, bool restricted, bool at_startup) {
436 // This must stay a LOG(WARNING); the output is used in processing customer
437 // feedback.
438 const char kAtStartup[] = "at startup";
439 const char kByUser[] = "by user action";
440 const char kOn[] = "ON";
441 const char kOff[] = "OFF";
442 const char kRestricted[] = "(Restricted)";
443 const char kUnrestricted[] = "(Unrestricted)";
445 std::string annotated_on =
446 kOn + std::string(" ") + (restricted ? kRestricted : kUnrestricted);
448 LOG(WARNING) << "SPDY proxy " << (enabled ? annotated_on : kOff)
449 << " " << (at_startup ? kAtStartup : kByUser);
452 PrefService* DataReductionProxySettings::GetOriginalProfilePrefs() {
453 return g_browser_process->profile_manager()->GetLastUsedProfile()->
454 GetOriginalProfile()->GetPrefs();
457 PrefService* DataReductionProxySettings::GetLocalStatePrefs() {
458 return g_browser_process->local_state();
461 void DataReductionProxySettings::ResetDataReductionStatistics() {
462 PrefService* prefs = GetLocalStatePrefs();
463 if (!prefs)
464 return;
465 ListPrefUpdate original_update(prefs, prefs::kDailyHttpOriginalContentLength);
466 ListPrefUpdate received_update(prefs, prefs::kDailyHttpReceivedContentLength);
467 original_update->Clear();
468 received_update->Clear();
469 for (size_t i = 0; i < spdyproxy::kNumDaysInHistory; ++i) {
470 original_update->AppendString(base::Int64ToString(0));
471 received_update->AppendString(base::Int64ToString(0));
475 void DataReductionProxySettings::MaybeActivateDataReductionProxy(
476 bool at_startup) {
477 PrefService* prefs = GetOriginalProfilePrefs();
479 // TODO(marq): Consider moving this so stats are wiped the first time the
480 // proxy settings are actually (not maybe) turned on.
481 if (spdy_proxy_auth_enabled_.GetValue() &&
482 !prefs->GetBoolean(prefs::kSpdyProxyAuthWasEnabledBefore)) {
483 prefs->SetBoolean(prefs::kSpdyProxyAuthWasEnabledBefore, true);
484 ResetDataReductionStatistics();
487 std::string proxy = GetDataReductionProxyOrigin();
488 // Configure use of the data reduction proxy if it is enabled and the proxy
489 // origin is non-empty.
490 enabled_by_user_= spdy_proxy_auth_enabled_.GetValue() && !proxy.empty();
491 SetProxyConfigs(enabled_by_user_, restricted_by_carrier_, at_startup);
493 // Check if the proxy has been restricted explicitly by the carrier.
494 if (enabled_by_user_)
495 ProbeWhetherDataReductionProxyIsAvailable();
498 void DataReductionProxySettings::SetProxyConfigs(
499 bool enabled, bool restricted, bool at_startup) {
500 // If |restricted| is true and there is no defined fallback proxy.
501 // treat this as a disable.
502 std::string fallback = GetDataReductionProxyFallback();
503 if (fallback.empty() && enabled && restricted)
504 enabled = false;
506 LogProxyState(enabled, restricted, at_startup);
507 PrefService* prefs = GetOriginalProfilePrefs();
508 DCHECK(prefs);
509 DictionaryPrefUpdate update(prefs, prefs::kProxy);
510 base::DictionaryValue* dict = update.Get();
511 if (enabled) {
512 std::string proxy_list;
513 if (restricted) {
514 DCHECK(!fallback.empty());
515 proxy_list = fallback;
516 } else {
517 proxy_list = GetDataReductionProxyOrigin() +
518 (fallback.empty() ? "" : "," + fallback);
521 std::string proxy_server_config = "http=" + proxy_list + ",direct://;";
522 dict->SetString("server", proxy_server_config);
523 dict->SetString("mode",
524 ProxyModeToString(ProxyPrefs::MODE_FIXED_SERVERS));
525 dict->SetString("bypass_list", JoinString(bypass_rules_, ", "));
526 } else {
527 dict->SetString("mode", ProxyModeToString(ProxyPrefs::MODE_SYSTEM));
528 dict->SetString("server", "");
529 dict->SetString("bypass_list", "");
533 // Metrics methods
534 void DataReductionProxySettings::RecordDataReductionInit() {
535 ProxyStartupState state = spdyproxy::PROXY_NOT_AVAILABLE;
536 if (IsDataReductionProxyAllowed()) {
537 if (IsDataReductionProxyEnabled())
538 state = spdyproxy::PROXY_ENABLED;
539 else
540 state = spdyproxy::PROXY_DISABLED;
543 RecordStartupState(state);
546 void DataReductionProxySettings::RecordProbeURLFetchResult(
547 ProbeURLFetchResult result) {
548 UMA_HISTOGRAM_ENUMERATION(kUMAProxyProbeURL,
549 result,
550 spdyproxy::PROBE_URL_FETCH_RESULT_COUNT);
553 void DataReductionProxySettings::RecordStartupState(ProxyStartupState state) {
554 UMA_HISTOGRAM_ENUMERATION(kUMAProxyStartupStateHistogram,
555 state,
556 spdyproxy::PROXY_STARTUP_STATE_COUNT);
559 DataReductionProxySettings::ContentLengthList
560 DataReductionProxySettings::GetDailyContentLengths(const char* pref_name) {
561 DataReductionProxySettings::ContentLengthList content_lengths;
562 const base::ListValue* list_value = GetLocalStatePrefs()->GetList(pref_name);
563 if (list_value->GetSize() == spdyproxy::kNumDaysInHistory) {
564 for (size_t i = 0; i < spdyproxy::kNumDaysInHistory; ++i) {
565 content_lengths.push_back(GetInt64PrefValue(*list_value, i));
568 return content_lengths;
571 void DataReductionProxySettings::GetContentLengths(
572 unsigned int days,
573 int64* original_content_length,
574 int64* received_content_length,
575 int64* last_update_time) {
576 DCHECK_LE(days, spdyproxy::kNumDaysInHistory);
577 PrefService* local_state = GetLocalStatePrefs();
578 if (!local_state) {
579 *original_content_length = 0L;
580 *received_content_length = 0L;
581 *last_update_time = 0L;
582 return;
585 const base::ListValue* original_list =
586 local_state->GetList(prefs::kDailyHttpOriginalContentLength);
587 const base::ListValue* received_list =
588 local_state->GetList(prefs::kDailyHttpReceivedContentLength);
590 if (original_list->GetSize() != spdyproxy::kNumDaysInHistory ||
591 received_list->GetSize() != spdyproxy::kNumDaysInHistory) {
592 *original_content_length = 0L;
593 *received_content_length = 0L;
594 *last_update_time = 0L;
595 return;
598 int64 orig = 0L;
599 int64 recv = 0L;
600 // Include days from the end of the list going backwards.
601 for (size_t i = spdyproxy::kNumDaysInHistory - days;
602 i < spdyproxy::kNumDaysInHistory; ++i) {
603 orig += GetInt64PrefValue(*original_list, i);
604 recv += GetInt64PrefValue(*received_list, i);
606 *original_content_length = orig;
607 *received_content_length = recv;
608 *last_update_time =
609 local_state->GetInt64(prefs::kDailyHttpContentLengthLastUpdateDate);
612 std::string DataReductionProxySettings::GetProxyCheckURL() {
613 if (!IsDataReductionProxyAllowed())
614 return std::string();
615 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
616 if (command_line.HasSwitch(switches::kDataReductionProxyProbeURL)) {
617 return command_line.GetSwitchValueASCII(
618 switches::kDataReductionProxyProbeURL);
620 #if defined(DATA_REDUCTION_PROXY_PROBE_URL)
621 return DATA_REDUCTION_PROXY_PROBE_URL;
622 #else
623 return std::string();
624 #endif
627 // static
628 base::string16 DataReductionProxySettings::AuthHashForSalt(int64 salt) {
629 if (!IsDataReductionProxyAllowed())
630 return base::string16();
632 std::string key;
634 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
635 if (command_line.HasSwitch(switches::kSpdyProxyAuthOrigin)) {
636 // If an origin is provided via a switch, then only consider the value
637 // that is provided by a switch. Do not use the preprocessor constant.
638 // Don't expose SPDY_PROXY_AUTH_VALUE to a proxy passed in via the command
639 // line.
640 if (!command_line.HasSwitch(switches::kSpdyProxyAuthValue))
641 return base::string16();
642 key = command_line.GetSwitchValueASCII(switches::kSpdyProxyAuthValue);
643 } else {
644 #if defined(SPDY_PROXY_AUTH_VALUE)
645 key = SPDY_PROXY_AUTH_VALUE;
646 #else
647 return base::string16();
648 #endif
651 DCHECK(!key.empty());
653 std::string salted_key =
654 base::StringPrintf("%lld%s%lld", salt, key.c_str(), salt);
655 return base::UTF8ToUTF16(base::MD5String(salted_key));
658 net::URLFetcher* DataReductionProxySettings::GetURLFetcher() {
659 std::string url = GetProxyCheckURL();
660 if (url.empty())
661 return NULL;
662 net::URLFetcher* fetcher = net::URLFetcher::Create(GURL(url),
663 net::URLFetcher::GET,
664 this);
665 fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE | net::LOAD_BYPASS_PROXY);
666 // If this code ever goes multi profile, the used profile needs to be taken
667 // from the browser context.
668 Profile* profile = ProfileManager::GetActiveUserProfile();
669 fetcher->SetRequestContext(profile->GetRequestContext());
670 // Configure max retries to be at most kMaxRetries times for 5xx errors.
671 static const int kMaxRetries = 5;
672 fetcher->SetMaxRetriesOn5xx(kMaxRetries);
673 return fetcher;
676 void
677 DataReductionProxySettings::ProbeWhetherDataReductionProxyIsAvailable() {
678 net::URLFetcher* fetcher = GetURLFetcher();
679 if (!fetcher)
680 return;
681 fetcher_.reset(fetcher);
682 fetcher_->Start();