NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / net / spdyproxy / data_reduction_proxy_settings.cc
blob52891344c2a34925133bd849dcd3323caa8f67d6
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 bool IsEnableSpdyProxyAuthSetOnCommandLine() {
77 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
78 return command_line.HasSwitch(switches::kEnableSpdyProxyAuth);
81 } // namespace
83 DataReductionProxySettings::DataReductionProxySettings()
84 : restricted_by_carrier_(false),
85 enabled_by_user_(false) {
88 DataReductionProxySettings::~DataReductionProxySettings() {
89 if (IsDataReductionProxyAllowed())
90 spdy_proxy_auth_enabled_.Destroy();
93 void DataReductionProxySettings::InitPrefMembers() {
94 spdy_proxy_auth_enabled_.Init(
95 prefs::kSpdyProxyAuthEnabled,
96 GetOriginalProfilePrefs(),
97 base::Bind(&DataReductionProxySettings::OnProxyEnabledPrefChange,
98 base::Unretained(this)));
101 void DataReductionProxySettings::InitDataReductionProxySettings() {
102 InitPrefMembers();
103 RecordDataReductionInit();
105 // Disable the proxy if it is not allowed to be used.
106 if (!IsDataReductionProxyAllowed())
107 return;
109 AddDefaultProxyBypassRules();
110 net::NetworkChangeNotifier::AddIPAddressObserver(this);
112 // We set or reset the proxy pref at startup.
113 MaybeActivateDataReductionProxy(true);
116 // static
117 void DataReductionProxySettings::InitDataReductionProxySession(
118 net::HttpNetworkSession* session) {
119 // This is a no-op unless the authentication parameters are compiled in.
120 // (even though values for them may be specified on the command line).
121 // Authentication will still work if the command line parameters are used,
122 // however there will be a round-trip overhead for each challenge/response
123 // (typically once per session).
124 #if defined(SPDY_PROXY_AUTH_ORIGIN) && defined(SPDY_PROXY_AUTH_VALUE)
125 DCHECK(session);
126 net::HttpAuthCache* auth_cache = session->http_auth_cache();
127 DCHECK(auth_cache);
128 InitDataReductionAuthentication(auth_cache);
129 #endif // defined(SPDY_PROXY_AUTH_ORIGIN) && defined(SPDY_PROXY_AUTH_VALUE)
132 // static
133 void DataReductionProxySettings::InitDataReductionAuthentication(
134 net::HttpAuthCache* auth_cache) {
135 DCHECK(auth_cache);
136 int64 timestamp =
137 (base::Time::Now() - base::Time::UnixEpoch()).InMilliseconds() / 1000;
139 DataReductionProxyList proxies = GetDataReductionProxies();
140 for (DataReductionProxyList::iterator it = proxies.begin();
141 it != proxies.end(); ++it) {
142 GURL auth_origin = (*it).GetOrigin();
143 int32 rand[3];
144 crypto::RandBytes(rand, 3 * sizeof(rand[0]));
146 std::string realm =
147 base::StringPrintf("%s%lld", kAuthenticationRealmName, timestamp);
148 std::string challenge = base::StringPrintf(
149 "%s realm=\"%s\", ps=\"%lld-%u-%u-%u\"", kAuthenticationRealmName,
150 realm.data(), timestamp, rand[0], rand[1], rand[2]);
151 base::string16 password = AuthHashForSalt(timestamp);
153 DVLOG(1) << "origin: [" << auth_origin << "] realm: [" << realm
154 << "] challenge: [" << challenge << "] password: [" << password << "]";
156 net::AuthCredentials credentials(base::string16(), password);
157 // |HttpAuthController| searches this cache by origin and path, the latter
158 // being '/' in the case of the data reduction proxy.
159 auth_cache->Add(auth_origin,
160 realm,
161 net::HttpAuth::AUTH_SCHEME_SPDYPROXY,
162 challenge,
163 credentials,
164 std::string("/"));
168 void DataReductionProxySettings::AddHostPatternToBypass(
169 const std::string& pattern) {
170 bypass_rules_.push_back(pattern);
173 void DataReductionProxySettings::AddURLPatternToBypass(
174 const std::string& pattern) {
175 size_t pos = pattern.find("/");
176 if (pattern.find("/", pos + 1) == pos + 1)
177 pos = pattern.find("/", pos + 2);
179 std::string host_pattern;
180 if (pos != std::string::npos)
181 host_pattern = pattern.substr(0, pos);
182 else
183 host_pattern = pattern;
185 AddHostPatternToBypass(host_pattern);
188 // static
189 bool DataReductionProxySettings::IsDataReductionProxyAllowed() {
190 return IsProxyOriginSetOnCommandLine() ||
191 (FieldTrialList::FindFullName("DataCompressionProxyRollout") == kEnabled);
194 // static
195 bool DataReductionProxySettings::IsDataReductionProxyPromoAllowed() {
196 return IsProxyOriginSetOnCommandLine() ||
197 (IsDataReductionProxyAllowed() &&
198 FieldTrialList::FindFullName("DataCompressionProxyPromoVisibility") ==
199 kEnabled);
202 // static
203 bool DataReductionProxySettings::IsPreconnectHintingAllowed() {
204 if (!IsDataReductionProxyAllowed())
205 return false;
206 return FieldTrialList::FindFullName("DataCompressionProxyPreconnectHints") ==
207 kEnabled;
210 // static
211 std::string DataReductionProxySettings::GetDataReductionProxyOrigin() {
212 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
213 if (command_line.HasSwitch(switches::kSpdyProxyDevAuthOrigin))
214 return command_line.GetSwitchValueASCII(switches::kSpdyProxyDevAuthOrigin);
215 if (command_line.HasSwitch(switches::kSpdyProxyAuthOrigin))
216 return command_line.GetSwitchValueASCII(switches::kSpdyProxyAuthOrigin);
217 #if defined(DATA_REDUCTION_DEV_HOST)
218 if (FieldTrialList::FindFullName("DataCompressionProxyDevRollout") ==
219 kEnabled) {
220 return DATA_REDUCTION_DEV_HOST;
222 #endif
223 #if defined(SPDY_PROXY_AUTH_ORIGIN)
224 return SPDY_PROXY_AUTH_ORIGIN;
225 #else
226 return std::string();
227 #endif
230 // static
231 std::string DataReductionProxySettings::GetDataReductionProxyFallback() {
232 // Regardless of what else is defined, only return a value if the main proxy
233 // origin is defined.
234 if (GetDataReductionProxyOrigin().empty())
235 return std::string();
236 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
237 if (command_line.HasSwitch(switches::kSpdyProxyAuthFallback))
238 return command_line.GetSwitchValueASCII(switches::kSpdyProxyAuthFallback);
239 #if defined(DATA_REDUCTION_FALLBACK_HOST)
240 return DATA_REDUCTION_FALLBACK_HOST;
241 #else
242 return std::string();
243 #endif
246 bool DataReductionProxySettings::IsAcceptableAuthChallenge(
247 net::AuthChallengeInfo* auth_info) {
248 // Challenge realm must start with the authentication realm name.
249 std::string realm_prefix =
250 auth_info->realm.substr(0, strlen(kAuthenticationRealmName));
251 if (realm_prefix != kAuthenticationRealmName)
252 return false;
254 // The challenger must be one of the configured proxies.
255 DataReductionProxyList proxies = GetDataReductionProxies();
256 for (DataReductionProxyList::iterator it = proxies.begin();
257 it != proxies.end(); ++it) {
258 net::HostPortPair origin_host = net::HostPortPair::FromURL(*it);
259 if (origin_host.Equals(auth_info->challenger))
260 return true;
262 return false;
265 base::string16 DataReductionProxySettings::GetTokenForAuthChallenge(
266 net::AuthChallengeInfo* auth_info) {
267 if (auth_info->realm.length() > strlen(kAuthenticationRealmName)) {
268 int64 salt;
269 std::string realm_suffix =
270 auth_info->realm.substr(strlen(kAuthenticationRealmName));
271 if (base::StringToInt64(realm_suffix, &salt)) {
272 return AuthHashForSalt(salt);
273 } else {
274 DVLOG(1) << "Unable to parse realm name " << auth_info->realm
275 << "into an int for salting.";
276 return base::string16();
278 } else {
279 return base::string16();
283 bool DataReductionProxySettings::IsDataReductionProxyEnabled() {
284 return spdy_proxy_auth_enabled_.GetValue() ||
285 IsEnableSpdyProxyAuthSetOnCommandLine();
288 bool DataReductionProxySettings::IsDataReductionProxyManaged() {
289 return spdy_proxy_auth_enabled_.IsManaged();
292 // static
293 DataReductionProxySettings::DataReductionProxyList
294 DataReductionProxySettings::GetDataReductionProxies() {
295 DataReductionProxyList proxies;
296 std::string proxy = GetDataReductionProxyOrigin();
297 std::string fallback = GetDataReductionProxyFallback();
299 if (!proxy.empty())
300 proxies.push_back(GURL(proxy));
302 if (!fallback.empty()) {
303 // Sanity check: fallback isn't the only proxy.
304 DCHECK(!proxies.empty());
305 proxies.push_back(GURL(fallback));
308 return proxies;
311 void DataReductionProxySettings::SetDataReductionProxyEnabled(bool enabled) {
312 // Prevent configuring the proxy when it is not allowed to be used.
313 if (!IsDataReductionProxyAllowed())
314 return;
316 if (spdy_proxy_auth_enabled_.GetValue() != enabled) {
317 spdy_proxy_auth_enabled_.SetValue(enabled);
318 OnProxyEnabledPrefChange();
322 int64 DataReductionProxySettings::GetDataReductionLastUpdateTime() {
323 PrefService* local_state = GetLocalStatePrefs();
324 int64 last_update_internal =
325 local_state->GetInt64(prefs::kDailyHttpContentLengthLastUpdateDate);
326 base::Time last_update = base::Time::FromInternalValue(last_update_internal);
327 return static_cast<int64>(last_update.ToJsTime());
330 DataReductionProxySettings::ContentLengthList
331 DataReductionProxySettings::GetDailyOriginalContentLengths() {
332 return GetDailyContentLengths(prefs::kDailyHttpOriginalContentLength);
335 DataReductionProxySettings::ContentLengthList
336 DataReductionProxySettings::GetDailyReceivedContentLengths() {
337 return GetDailyContentLengths(prefs::kDailyHttpReceivedContentLength);
340 void DataReductionProxySettings::OnURLFetchComplete(
341 const net::URLFetcher* source) {
342 net::URLRequestStatus status = source->GetStatus();
343 if (status.status() == net::URLRequestStatus::FAILED &&
344 status.error() == net::ERR_INTERNET_DISCONNECTED) {
345 RecordProbeURLFetchResult(spdyproxy::INTERNET_DISCONNECTED);
346 return;
349 std::string response;
350 source->GetResponseAsString(&response);
352 if ("OK" == response.substr(0, 2)) {
353 DVLOG(1) << "The data reduction proxy is unrestricted.";
355 if (enabled_by_user_) {
356 if (restricted_by_carrier_) {
357 // The user enabled the proxy, but sometime previously in the session,
358 // the network operator had blocked the canary and restricted the user.
359 // The current network doesn't block the canary, so don't restrict the
360 // proxy configurations.
361 SetProxyConfigs(true /* enabled */,
362 false /* restricted */,
363 false /* at_startup */);
364 RecordProbeURLFetchResult(spdyproxy::SUCCEEDED_PROXY_ENABLED);
365 } else {
366 RecordProbeURLFetchResult(spdyproxy::SUCCEEDED_PROXY_ALREADY_ENABLED);
369 restricted_by_carrier_ = false;
370 return;
372 DVLOG(1) << "The data reduction proxy is restricted to the configured "
373 << "fallback proxy.";
375 if (enabled_by_user_) {
376 if (!restricted_by_carrier_) {
377 // Restrict the proxy.
378 SetProxyConfigs(true /* enabled */,
379 true /* restricted */,
380 false /* at_startup */);
381 RecordProbeURLFetchResult(spdyproxy::FAILED_PROXY_DISABLED);
382 } else {
383 RecordProbeURLFetchResult(spdyproxy::FAILED_PROXY_ALREADY_DISABLED);
386 restricted_by_carrier_ = true;
389 void DataReductionProxySettings::OnIPAddressChanged() {
390 if (enabled_by_user_) {
391 DCHECK(IsDataReductionProxyAllowed());
392 ProbeWhetherDataReductionProxyIsAvailable();
396 void DataReductionProxySettings::OnProxyEnabledPrefChange() {
397 if (!DataReductionProxySettings::IsDataReductionProxyAllowed())
398 return;
399 MaybeActivateDataReductionProxy(false);
402 void DataReductionProxySettings::AddDefaultProxyBypassRules() {
403 // localhost
404 AddHostPatternToBypass("<local>");
405 // RFC1918 private addresses.
406 AddHostPatternToBypass("10.0.0.0/8");
407 AddHostPatternToBypass("172.16.0.0/12");
408 AddHostPatternToBypass("192.168.0.0/16");
409 // RFC4193 private addresses.
410 AddHostPatternToBypass("fc00::/7");
411 // IPV6 probe addresses.
412 AddHostPatternToBypass("*-ds.metric.gstatic.com");
413 AddHostPatternToBypass("*-v4.metric.gstatic.com");
416 void DataReductionProxySettings::LogProxyState(
417 bool enabled, bool restricted, bool at_startup) {
418 // This must stay a LOG(WARNING); the output is used in processing customer
419 // feedback.
420 const char kAtStartup[] = "at startup";
421 const char kByUser[] = "by user action";
422 const char kOn[] = "ON";
423 const char kOff[] = "OFF";
424 const char kRestricted[] = "(Restricted)";
425 const char kUnrestricted[] = "(Unrestricted)";
427 std::string annotated_on =
428 kOn + std::string(" ") + (restricted ? kRestricted : kUnrestricted);
430 LOG(WARNING) << "SPDY proxy " << (enabled ? annotated_on : kOff)
431 << " " << (at_startup ? kAtStartup : kByUser);
434 PrefService* DataReductionProxySettings::GetOriginalProfilePrefs() {
435 return g_browser_process->profile_manager()->GetLastUsedProfile()->
436 GetOriginalProfile()->GetPrefs();
439 PrefService* DataReductionProxySettings::GetLocalStatePrefs() {
440 return g_browser_process->local_state();
443 void DataReductionProxySettings::ResetDataReductionStatistics() {
444 PrefService* prefs = GetLocalStatePrefs();
445 if (!prefs)
446 return;
447 ListPrefUpdate original_update(prefs, prefs::kDailyHttpOriginalContentLength);
448 ListPrefUpdate received_update(prefs, prefs::kDailyHttpReceivedContentLength);
449 original_update->Clear();
450 received_update->Clear();
451 for (size_t i = 0; i < spdyproxy::kNumDaysInHistory; ++i) {
452 original_update->AppendString(base::Int64ToString(0));
453 received_update->AppendString(base::Int64ToString(0));
457 void DataReductionProxySettings::MaybeActivateDataReductionProxy(
458 bool at_startup) {
459 PrefService* prefs = GetOriginalProfilePrefs();
461 // TODO(marq): Consider moving this so stats are wiped the first time the
462 // proxy settings are actually (not maybe) turned on.
463 if (spdy_proxy_auth_enabled_.GetValue() &&
464 !prefs->GetBoolean(prefs::kSpdyProxyAuthWasEnabledBefore)) {
465 prefs->SetBoolean(prefs::kSpdyProxyAuthWasEnabledBefore, true);
466 ResetDataReductionStatistics();
469 std::string proxy = GetDataReductionProxyOrigin();
470 // Configure use of the data reduction proxy if it is enabled and the proxy
471 // origin is non-empty.
472 enabled_by_user_= IsDataReductionProxyEnabled() && !proxy.empty();
473 SetProxyConfigs(enabled_by_user_, restricted_by_carrier_, at_startup);
475 // Check if the proxy has been restricted explicitly by the carrier.
476 if (enabled_by_user_)
477 ProbeWhetherDataReductionProxyIsAvailable();
480 void DataReductionProxySettings::SetProxyConfigs(
481 bool enabled, bool restricted, bool at_startup) {
482 // If |restricted| is true and there is no defined fallback proxy.
483 // treat this as a disable.
484 std::string fallback = GetDataReductionProxyFallback();
485 if (fallback.empty() && enabled && restricted)
486 enabled = false;
488 LogProxyState(enabled, restricted, at_startup);
489 PrefService* prefs = GetOriginalProfilePrefs();
490 DCHECK(prefs);
491 DictionaryPrefUpdate update(prefs, prefs::kProxy);
492 base::DictionaryValue* dict = update.Get();
493 if (enabled) {
494 std::string proxy_list;
495 if (restricted) {
496 DCHECK(!fallback.empty());
497 proxy_list = fallback;
498 } else {
499 proxy_list = GetDataReductionProxyOrigin() +
500 (fallback.empty() ? "" : "," + fallback);
503 std::string proxy_server_config = "http=" + proxy_list + ",direct://;";
504 dict->SetString("server", proxy_server_config);
505 dict->SetString("mode",
506 ProxyModeToString(ProxyPrefs::MODE_FIXED_SERVERS));
507 dict->SetString("bypass_list", JoinString(bypass_rules_, ", "));
508 } else {
509 dict->SetString("mode", ProxyModeToString(ProxyPrefs::MODE_SYSTEM));
510 dict->SetString("server", "");
511 dict->SetString("bypass_list", "");
515 // Metrics methods
516 void DataReductionProxySettings::RecordDataReductionInit() {
517 ProxyStartupState state = spdyproxy::PROXY_NOT_AVAILABLE;
518 if (IsDataReductionProxyAllowed()) {
519 if (IsDataReductionProxyEnabled())
520 state = spdyproxy::PROXY_ENABLED;
521 else
522 state = spdyproxy::PROXY_DISABLED;
525 RecordStartupState(state);
528 void DataReductionProxySettings::RecordProbeURLFetchResult(
529 ProbeURLFetchResult result) {
530 UMA_HISTOGRAM_ENUMERATION(kUMAProxyProbeURL,
531 result,
532 spdyproxy::PROBE_URL_FETCH_RESULT_COUNT);
535 void DataReductionProxySettings::RecordStartupState(ProxyStartupState state) {
536 UMA_HISTOGRAM_ENUMERATION(kUMAProxyStartupStateHistogram,
537 state,
538 spdyproxy::PROXY_STARTUP_STATE_COUNT);
541 DataReductionProxySettings::ContentLengthList
542 DataReductionProxySettings::GetDailyContentLengths(const char* pref_name) {
543 DataReductionProxySettings::ContentLengthList content_lengths;
544 const base::ListValue* list_value = GetLocalStatePrefs()->GetList(pref_name);
545 if (list_value->GetSize() == spdyproxy::kNumDaysInHistory) {
546 for (size_t i = 0; i < spdyproxy::kNumDaysInHistory; ++i) {
547 content_lengths.push_back(GetInt64PrefValue(*list_value, i));
550 return content_lengths;
553 void DataReductionProxySettings::GetContentLengths(
554 unsigned int days,
555 int64* original_content_length,
556 int64* received_content_length,
557 int64* last_update_time) {
558 DCHECK_LE(days, spdyproxy::kNumDaysInHistory);
559 PrefService* local_state = GetLocalStatePrefs();
560 if (!local_state) {
561 *original_content_length = 0L;
562 *received_content_length = 0L;
563 *last_update_time = 0L;
564 return;
567 const base::ListValue* original_list =
568 local_state->GetList(prefs::kDailyHttpOriginalContentLength);
569 const base::ListValue* received_list =
570 local_state->GetList(prefs::kDailyHttpReceivedContentLength);
572 if (original_list->GetSize() != spdyproxy::kNumDaysInHistory ||
573 received_list->GetSize() != spdyproxy::kNumDaysInHistory) {
574 *original_content_length = 0L;
575 *received_content_length = 0L;
576 *last_update_time = 0L;
577 return;
580 int64 orig = 0L;
581 int64 recv = 0L;
582 // Include days from the end of the list going backwards.
583 for (size_t i = spdyproxy::kNumDaysInHistory - days;
584 i < spdyproxy::kNumDaysInHistory; ++i) {
585 orig += GetInt64PrefValue(*original_list, i);
586 recv += GetInt64PrefValue(*received_list, i);
588 *original_content_length = orig;
589 *received_content_length = recv;
590 *last_update_time =
591 local_state->GetInt64(prefs::kDailyHttpContentLengthLastUpdateDate);
594 std::string DataReductionProxySettings::GetProxyCheckURL() {
595 if (!IsDataReductionProxyAllowed())
596 return std::string();
597 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
598 if (command_line.HasSwitch(switches::kDataReductionProxyProbeURL)) {
599 return command_line.GetSwitchValueASCII(
600 switches::kDataReductionProxyProbeURL);
602 #if defined(DATA_REDUCTION_PROXY_PROBE_URL)
603 return DATA_REDUCTION_PROXY_PROBE_URL;
604 #else
605 return std::string();
606 #endif
609 // static
610 base::string16 DataReductionProxySettings::AuthHashForSalt(int64 salt) {
611 if (!IsDataReductionProxyAllowed())
612 return base::string16();
614 std::string key;
616 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
617 if (command_line.HasSwitch(switches::kSpdyProxyAuthOrigin)) {
618 // If an origin is provided via a switch, then only consider the value
619 // that is provided by a switch. Do not use the preprocessor constant.
620 // Don't expose SPDY_PROXY_AUTH_VALUE to a proxy passed in via the command
621 // line.
622 if (!command_line.HasSwitch(switches::kSpdyProxyAuthValue))
623 return base::string16();
624 key = command_line.GetSwitchValueASCII(switches::kSpdyProxyAuthValue);
625 } else {
626 #if defined(SPDY_PROXY_AUTH_VALUE)
627 key = SPDY_PROXY_AUTH_VALUE;
628 #else
629 return base::string16();
630 #endif
633 DCHECK(!key.empty());
635 std::string salted_key =
636 base::StringPrintf("%lld%s%lld", salt, key.c_str(), salt);
637 return base::UTF8ToUTF16(base::MD5String(salted_key));
640 net::URLFetcher* DataReductionProxySettings::GetURLFetcher() {
641 std::string url = GetProxyCheckURL();
642 if (url.empty())
643 return NULL;
644 net::URLFetcher* fetcher = net::URLFetcher::Create(GURL(url),
645 net::URLFetcher::GET,
646 this);
647 fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE | net::LOAD_BYPASS_PROXY);
648 // If this code ever goes multi profile, the used profile needs to be taken
649 // from the browser context.
650 Profile* profile = ProfileManager::GetActiveUserProfile();
651 fetcher->SetRequestContext(profile->GetRequestContext());
652 // Configure max retries to be at most kMaxRetries times for 5xx errors.
653 static const int kMaxRetries = 5;
654 fetcher->SetMaxRetriesOn5xx(kMaxRetries);
655 return fetcher;
658 void
659 DataReductionProxySettings::ProbeWhetherDataReductionProxyIsAvailable() {
660 net::URLFetcher* fetcher = GetURLFetcher();
661 if (!fetcher)
662 return;
663 fetcher_.reset(fetcher);
664 fetcher_->Start();