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"
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"
38 using base::FieldTrialList
;
39 using base::StringPrintf
;
40 using spdyproxy::ProbeURLFetchResult
;
41 using spdyproxy::ProxyStartupState
;
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
) {
61 std::string pref_value
;
62 bool rv
= list_value
.GetString(index
, &pref_value
);
65 rv
= base::StringToInt64(pref_value
, &val
);
71 bool IsProxyOriginSetOnCommandLine() {
72 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
73 return command_line
.HasSwitch(switches::kSpdyProxyAuthOrigin
);
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() {
98 RecordDataReductionInit();
100 // Disable the proxy if it is not allowed to be used.
101 if (!IsDataReductionProxyAllowed())
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);
117 // This is logged so we can use this information in user feedback.
118 LogProxyState(false /* enabled */,
119 false /* restricted */,
120 true /* at startup */);
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)
134 net::HttpAuthCache
* auth_cache
= session
->http_auth_cache();
136 InitDataReductionAuthentication(auth_cache
);
137 #endif // defined(SPDY_PROXY_AUTH_ORIGIN) && defined(SPDY_PROXY_AUTH_VALUE)
141 void DataReductionProxySettings::InitDataReductionAuthentication(
142 net::HttpAuthCache
* auth_cache
) {
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();
152 crypto::RandBytes(rand
, 3 * sizeof(rand
[0]));
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
,
169 net::HttpAuth::AUTH_SCHEME_SPDYPROXY
,
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
);
191 host_pattern
= pattern
;
193 AddHostPatternToBypass(host_pattern
);
197 bool DataReductionProxySettings::IsDataReductionProxyAllowed() {
198 return IsProxyOriginSetOnCommandLine() ||
199 (FieldTrialList::FindFullName("DataCompressionProxyRollout") == kEnabled
);
203 bool DataReductionProxySettings::IsDataReductionProxyPromoAllowed() {
204 return IsProxyOriginSetOnCommandLine() ||
205 (IsDataReductionProxyAllowed() &&
206 FieldTrialList::FindFullName("DataCompressionProxyPromoVisibility") ==
211 bool DataReductionProxySettings::IsPreconnectHintingAllowed() {
212 if (!IsDataReductionProxyAllowed())
214 return FieldTrialList::FindFullName("DataCompressionProxyPreconnectHints") ==
219 bool DataReductionProxySettings::WasFetchedViaProxy(
220 const net::HttpResponseHeaders
* headers
) {
221 const char kChromeProxyViaValue
[] = "1.1 Chrome Compression Proxy";
224 while (headers
->EnumerateHeader(&iter
, "via", &value
))
225 if (value
== kChromeProxyViaValue
) return true;
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") ==
239 return DATA_REDUCTION_DEV_HOST
;
242 #if defined(SPDY_PROXY_AUTH_ORIGIN)
243 return SPDY_PROXY_AUTH_ORIGIN
;
245 return std::string();
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
;
261 return std::string();
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
)
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
))
284 base::string16
DataReductionProxySettings::GetTokenForAuthChallenge(
285 net::AuthChallengeInfo
* auth_info
) {
286 if (auth_info
->realm
.length() > strlen(kAuthenticationRealmName
)) {
288 std::string realm_suffix
=
289 auth_info
->realm
.substr(strlen(kAuthenticationRealmName
));
290 if (base::StringToInt64(realm_suffix
, &salt
)) {
291 return AuthHashForSalt(salt
);
293 DVLOG(1) << "Unable to parse realm name " << auth_info
->realm
294 << "into an int for salting.";
295 return base::string16();
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();
311 DataReductionProxySettings::DataReductionProxyList
312 DataReductionProxySettings::GetDataReductionProxies() {
313 DataReductionProxyList proxies
;
314 std::string proxy
= GetDataReductionProxyOrigin();
315 std::string fallback
= GetDataReductionProxyFallback();
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
));
329 void DataReductionProxySettings::SetDataReductionProxyEnabled(bool enabled
) {
330 // Prevent configuring the proxy when it is not allowed to be used.
331 if (!IsDataReductionProxyAllowed())
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
);
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
);
384 RecordProbeURLFetchResult(spdyproxy::SUCCEEDED_PROXY_ALREADY_ENABLED
);
387 restricted_by_carrier_
= false;
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
);
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())
417 MaybeActivateDataReductionProxy(false);
420 void DataReductionProxySettings::AddDefaultProxyBypassRules() {
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
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();
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(
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
)
506 LogProxyState(enabled
, restricted
, at_startup
);
507 PrefService
* prefs
= GetOriginalProfilePrefs();
509 DictionaryPrefUpdate
update(prefs
, prefs::kProxy
);
510 base::DictionaryValue
* dict
= update
.Get();
512 std::string proxy_list
;
514 DCHECK(!fallback
.empty());
515 proxy_list
= fallback
;
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_
, ", "));
527 dict
->SetString("mode", ProxyModeToString(ProxyPrefs::MODE_SYSTEM
));
528 dict
->SetString("server", "");
529 dict
->SetString("bypass_list", "");
534 void DataReductionProxySettings::RecordDataReductionInit() {
535 ProxyStartupState state
= spdyproxy::PROXY_NOT_AVAILABLE
;
536 if (IsDataReductionProxyAllowed()) {
537 if (IsDataReductionProxyEnabled())
538 state
= spdyproxy::PROXY_ENABLED
;
540 state
= spdyproxy::PROXY_DISABLED
;
543 RecordStartupState(state
);
546 void DataReductionProxySettings::RecordProbeURLFetchResult(
547 ProbeURLFetchResult result
) {
548 UMA_HISTOGRAM_ENUMERATION(kUMAProxyProbeURL
,
550 spdyproxy::PROBE_URL_FETCH_RESULT_COUNT
);
553 void DataReductionProxySettings::RecordStartupState(ProxyStartupState state
) {
554 UMA_HISTOGRAM_ENUMERATION(kUMAProxyStartupStateHistogram
,
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(
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();
579 *original_content_length
= 0L;
580 *received_content_length
= 0L;
581 *last_update_time
= 0L;
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;
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
;
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
;
623 return std::string();
628 base::string16
DataReductionProxySettings::AuthHashForSalt(int64 salt
) {
629 if (!IsDataReductionProxyAllowed())
630 return base::string16();
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
640 if (!command_line
.HasSwitch(switches::kSpdyProxyAuthValue
))
641 return base::string16();
642 key
= command_line
.GetSwitchValueASCII(switches::kSpdyProxyAuthValue
);
644 #if defined(SPDY_PROXY_AUTH_VALUE)
645 key
= SPDY_PROXY_AUTH_VALUE
;
647 return base::string16();
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();
662 net::URLFetcher
* fetcher
= net::URLFetcher::Create(GURL(url
),
663 net::URLFetcher::GET
,
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
);
677 DataReductionProxySettings::ProbeWhetherDataReductionProxyIsAvailable() {
678 net::URLFetcher
* fetcher
= GetURLFetcher();
681 fetcher_
.reset(fetcher
);