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.
4
5 #include "components/data_reduction_proxy/browser/data_reduction_proxy_settings.h"
6
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 "components/data_reduction_proxy/browser/data_reduction_proxy_configurator.h"
19 #include "components/data_reduction_proxy/browser/data_reduction_proxy_params.h"
20 #include "components/data_reduction_proxy/common/data_reduction_proxy_pref_names.h"
21 #include "components/data_reduction_proxy/common/data_reduction_proxy_switches.h"
22 #include "crypto/random.h"
23 #include "net/base/auth.h"
24 #include "net/base/host_port_pair.h"
25 #include "net/base/load_flags.h"
26 #include "net/base/net_errors.h"
27 #include "net/http/http_auth.h"
28 #include "net/http/http_auth_cache.h"
29 #include "net/http/http_network_session.h"
30 #include "net/http/http_response_headers.h"
31 #include "net/url_request/url_fetcher.h"
32 #include "net/url_request/url_fetcher_delegate.h"
33 #include "net/url_request/url_request_context_getter.h"
34 #include "net/url_request/url_request_status.h"
35 #include "url/gurl.h"
36
37
38 using base::StringPrintf;
39
40 namespace {
41
42 // Key of the UMA DataReductionProxy.StartupState histogram.
43 const char kUMAProxyStartupStateHistogram[] =
44 "DataReductionProxy.StartupState";
45
46 // Key of the UMA DataReductionProxy.ProbeURL histogram.
47 const char kUMAProxyProbeURL[] = "DataReductionProxy.ProbeURL";
48
49 // TODO(marq): Factor this string out into a constant here and in
50 // http_auth_handler_spdyproxy.
51 const char kAuthenticationRealmName[] = "SpdyProxy";
52
GetInt64PrefValue(const base::ListValue & list_value,size_t index)53 int64 GetInt64PrefValue(const base::ListValue& list_value, size_t index) {
54 int64 val = 0;
55 std::string pref_value;
56 bool rv = list_value.GetString(index, &pref_value);
57 DCHECK(rv);
58 if (rv) {
59 rv = base::StringToInt64(pref_value, &val);
60 DCHECK(rv);
61 }
62 return val;
63 }
64
65 } // namespace
66
67 namespace data_reduction_proxy {
68
DataReductionProxySettings(DataReductionProxyParams * params)69 DataReductionProxySettings::DataReductionProxySettings(
70 DataReductionProxyParams* params)
71 : restricted_by_carrier_(false),
72 enabled_by_user_(false),
73 prefs_(NULL),
74 local_state_prefs_(NULL),
75 url_request_context_getter_(NULL) {
76 DCHECK(params);
77 params_.reset(params);
78 }
79
~DataReductionProxySettings()80 DataReductionProxySettings::~DataReductionProxySettings() {
81 if (params_->allowed())
82 spdy_proxy_auth_enabled_.Destroy();
83 }
84
InitPrefMembers()85 void DataReductionProxySettings::InitPrefMembers() {
86 DCHECK(thread_checker_.CalledOnValidThread());
87 spdy_proxy_auth_enabled_.Init(
88 prefs::kDataReductionProxyEnabled,
89 GetOriginalProfilePrefs(),
90 base::Bind(&DataReductionProxySettings::OnProxyEnabledPrefChange,
91 base::Unretained(this)));
92 data_reduction_proxy_alternative_enabled_.Init(
93 prefs::kDataReductionProxyAltEnabled,
94 GetOriginalProfilePrefs(),
95 base::Bind(
96 &DataReductionProxySettings::OnProxyAlternativeEnabledPrefChange,
97 base::Unretained(this)));
98 }
99
InitDataReductionProxySettings(PrefService * prefs,PrefService * local_state_prefs,net::URLRequestContextGetter * url_request_context_getter)100 void DataReductionProxySettings::InitDataReductionProxySettings(
101 PrefService* prefs,
102 PrefService* local_state_prefs,
103 net::URLRequestContextGetter* url_request_context_getter) {
104 DCHECK(thread_checker_.CalledOnValidThread());
105 DCHECK(prefs);
106 DCHECK(local_state_prefs);
107 DCHECK(url_request_context_getter);
108 prefs_ = prefs;
109 local_state_prefs_ = local_state_prefs;
110 url_request_context_getter_ = url_request_context_getter;
111 InitPrefMembers();
112 RecordDataReductionInit();
113
114 // Disable the proxy if it is not allowed to be used.
115 if (!params_->allowed())
116 return;
117
118 AddDefaultProxyBypassRules();
119 net::NetworkChangeNotifier::AddIPAddressObserver(this);
120
121 // We set or reset the proxy pref at startup.
122 MaybeActivateDataReductionProxy(true);
123 }
124
InitDataReductionProxySettings(PrefService * prefs,PrefService * local_state_prefs,net::URLRequestContextGetter * url_request_context_getter,scoped_ptr<DataReductionProxyConfigurator> configurator)125 void DataReductionProxySettings::InitDataReductionProxySettings(
126 PrefService* prefs,
127 PrefService* local_state_prefs,
128 net::URLRequestContextGetter* url_request_context_getter,
129 scoped_ptr<DataReductionProxyConfigurator> configurator) {
130 InitDataReductionProxySettings(prefs,
131 local_state_prefs,
132 url_request_context_getter);
133 SetProxyConfigurator(configurator.Pass());
134 }
135
SetProxyConfigurator(scoped_ptr<DataReductionProxyConfigurator> configurator)136 void DataReductionProxySettings::SetProxyConfigurator(
137 scoped_ptr<DataReductionProxyConfigurator> configurator) {
138 DCHECK(configurator);
139 configurator_ = configurator.Pass();
140 }
141
142 // static
InitDataReductionProxySession(net::HttpNetworkSession * session,const DataReductionProxyParams * params)143 void DataReductionProxySettings::InitDataReductionProxySession(
144 net::HttpNetworkSession* session,
145 const DataReductionProxyParams* params) {
146 // This is a no-op unless the authentication parameters are compiled in.
147 // (even though values for them may be specified on the command line).
148 // Authentication will still work if the command line parameters are used,
149 // however there will be a round-trip overhead for each challenge/response
150 // (typically once per session).
151 // TODO(bengr):Pass a configuration struct into DataReductionProxyConfigurator's
152 // constructor. The struct would carry everything in the preprocessor flags.
153 DCHECK(session);
154 net::HttpAuthCache* auth_cache = session->http_auth_cache();
155 DCHECK(auth_cache);
156 InitDataReductionAuthentication(auth_cache, params);
157 }
158
159 // static
InitDataReductionAuthentication(net::HttpAuthCache * auth_cache,const DataReductionProxyParams * params)160 void DataReductionProxySettings::InitDataReductionAuthentication(
161 net::HttpAuthCache* auth_cache,
162 const DataReductionProxyParams* params) {
163 DCHECK(auth_cache);
164 DCHECK(params);
165 int64 timestamp =
166 (base::Time::Now() - base::Time::UnixEpoch()).InMilliseconds() / 1000;
167
168 DataReductionProxyParams::DataReductionProxyList proxies =
169 params->GetAllowedProxies();
170 for (DataReductionProxyParams::DataReductionProxyList::iterator it =
171 proxies.begin();
172 it != proxies.end(); ++it) {
173 GURL auth_origin = (*it).GetOrigin();
174
175 int32 rand[3];
176 crypto::RandBytes(rand, 3 * sizeof(rand[0]));
177
178 std::string realm =
179 base::StringPrintf("%s%lld", kAuthenticationRealmName,
180 static_cast<long long>(timestamp));
181 std::string challenge = base::StringPrintf(
182 "%s realm=\"%s\", ps=\"%lld-%u-%u-%u\"",
183 kAuthenticationRealmName,
184 realm.data(),
185 static_cast<long long>(timestamp),
186 rand[0],
187 rand[1],
188 rand[2]);
189 base::string16 password = AuthHashForSalt(timestamp, params->key());
190
191 DVLOG(1) << "origin: [" << auth_origin << "] realm: [" << realm
192 << "] challenge: [" << challenge << "] password: [" << password << "]";
193
194 net::AuthCredentials credentials(base::string16(), password);
195 // |HttpAuthController| searches this cache by origin and path, the latter
196 // being '/' in the case of the data reduction proxy.
197 auth_cache->Add(auth_origin,
198 realm,
199 net::HttpAuth::AUTH_SCHEME_SPDYPROXY,
200 challenge,
201 credentials,
202 std::string("/"));
203 }
204 }
205
IsAcceptableAuthChallenge(net::AuthChallengeInfo * auth_info)206 bool DataReductionProxySettings::IsAcceptableAuthChallenge(
207 net::AuthChallengeInfo* auth_info) {
208 // Challenge realm must start with the authentication realm name.
209 std::string realm_prefix =
210 auth_info->realm.substr(0, strlen(kAuthenticationRealmName));
211 if (realm_prefix != kAuthenticationRealmName)
212 return false;
213
214 // The challenger must be one of the configured proxies.
215 DataReductionProxyParams::DataReductionProxyList proxies =
216 params_->GetAllowedProxies();
217 for (DataReductionProxyParams::DataReductionProxyList::iterator it =
218 proxies.begin();
219 it != proxies.end(); ++it) {
220 net::HostPortPair origin_host = net::HostPortPair::FromURL(*it);
221 if (origin_host.Equals(auth_info->challenger))
222 return true;
223 }
224 return false;
225 }
226
GetTokenForAuthChallenge(net::AuthChallengeInfo * auth_info)227 base::string16 DataReductionProxySettings::GetTokenForAuthChallenge(
228 net::AuthChallengeInfo* auth_info) {
229 if (auth_info->realm.length() > strlen(kAuthenticationRealmName)) {
230 int64 salt;
231 std::string realm_suffix =
232 auth_info->realm.substr(strlen(kAuthenticationRealmName));
233 if (base::StringToInt64(realm_suffix, &salt)) {
234 return AuthHashForSalt(salt, params_->key());
235 } else {
236 DVLOG(1) << "Unable to parse realm name " << auth_info->realm
237 << "into an int for salting.";
238 return base::string16();
239 }
240 } else {
241 return base::string16();
242 }
243 }
244
IsDataReductionProxyEnabled()245 bool DataReductionProxySettings::IsDataReductionProxyEnabled() {
246 // We should not check for DataReductionProxyParams::IsKeySetOnCommandLine()
247 // here because when we enable drp in cmd and supply a wrong key to drp,
248 // drp is supposed to disable itself and fallback to direct loading after
249 // repeated authentication failures.
250 return spdy_proxy_auth_enabled_.GetValue();
251 }
252
253 bool
IsDataReductionProxyAlternativeEnabled() const254 DataReductionProxySettings::IsDataReductionProxyAlternativeEnabled() const {
255 return data_reduction_proxy_alternative_enabled_.GetValue();
256 }
257
IsDataReductionProxyManaged()258 bool DataReductionProxySettings::IsDataReductionProxyManaged() {
259 return spdy_proxy_auth_enabled_.IsManaged();
260 }
261
SetDataReductionProxyEnabled(bool enabled)262 void DataReductionProxySettings::SetDataReductionProxyEnabled(bool enabled) {
263 DCHECK(thread_checker_.CalledOnValidThread());
264 // Prevent configuring the proxy when it is not allowed to be used.
265 if (!params_->allowed())
266 return;
267
268 if (spdy_proxy_auth_enabled_.GetValue() != enabled) {
269 spdy_proxy_auth_enabled_.SetValue(enabled);
270 OnProxyEnabledPrefChange();
271 }
272 }
273
SetDataReductionProxyAlternativeEnabled(bool enabled)274 void DataReductionProxySettings::SetDataReductionProxyAlternativeEnabled(
275 bool enabled) {
276 DCHECK(thread_checker_.CalledOnValidThread());
277 // Prevent configuring the proxy when it is not allowed to be used.
278 if (!params_->alternative_allowed())
279 return;
280 if (data_reduction_proxy_alternative_enabled_.GetValue() != enabled) {
281 data_reduction_proxy_alternative_enabled_.SetValue(enabled);
282 OnProxyAlternativeEnabledPrefChange();
283 }
284 }
285
GetDataReductionLastUpdateTime()286 int64 DataReductionProxySettings::GetDataReductionLastUpdateTime() {
287 DCHECK(thread_checker_.CalledOnValidThread());
288 PrefService* local_state = GetLocalStatePrefs();
289 int64 last_update_internal =
290 local_state->GetInt64(prefs::kDailyHttpContentLengthLastUpdateDate);
291 base::Time last_update = base::Time::FromInternalValue(last_update_internal);
292 return static_cast<int64>(last_update.ToJsTime());
293 }
294
295 DataReductionProxySettings::ContentLengthList
GetDailyOriginalContentLengths()296 DataReductionProxySettings::GetDailyOriginalContentLengths() {
297 DCHECK(thread_checker_.CalledOnValidThread());
298 return GetDailyContentLengths(prefs::kDailyHttpOriginalContentLength);
299 }
300
301 DataReductionProxySettings::ContentLengthList
GetDailyReceivedContentLengths()302 DataReductionProxySettings::GetDailyReceivedContentLengths() {
303 DCHECK(thread_checker_.CalledOnValidThread());
304 return GetDailyContentLengths(prefs::kDailyHttpReceivedContentLength);
305 }
306
OnURLFetchComplete(const net::URLFetcher * source)307 void DataReductionProxySettings::OnURLFetchComplete(
308 const net::URLFetcher* source) {
309 DCHECK(thread_checker_.CalledOnValidThread());
310
311 // The purpose of sending a request for the warmup URL is to warm the
312 // connection to the data_reduction_proxy. The result is ignored.
313 if (source == warmup_fetcher_.get())
314 return;
315
316 DCHECK(source == fetcher_.get());
317 net::URLRequestStatus status = source->GetStatus();
318 if (status.status() == net::URLRequestStatus::FAILED &&
319 status.error() == net::ERR_INTERNET_DISCONNECTED) {
320 RecordProbeURLFetchResult(INTERNET_DISCONNECTED);
321 return;
322 }
323
324 std::string response;
325 source->GetResponseAsString(&response);
326
327 if ("OK" == response.substr(0, 2)) {
328 DVLOG(1) << "The data reduction proxy is unrestricted.";
329
330 if (enabled_by_user_) {
331 if (restricted_by_carrier_) {
332 // The user enabled the proxy, but sometime previously in the session,
333 // the network operator had blocked the canary and restricted the user.
334 // The current network doesn't block the canary, so don't restrict the
335 // proxy configurations.
336 SetProxyConfigs(true /* enabled */,
337 IsDataReductionProxyAlternativeEnabled(),
338 false /* restricted */,
339 false /* at_startup */);
340 RecordProbeURLFetchResult(SUCCEEDED_PROXY_ENABLED);
341 } else {
342 RecordProbeURLFetchResult(SUCCEEDED_PROXY_ALREADY_ENABLED);
343 }
344 }
345 restricted_by_carrier_ = false;
346 return;
347 }
348 DVLOG(1) << "The data reduction proxy is restricted to the configured "
349 << "fallback proxy.";
350 if (enabled_by_user_) {
351 if (!restricted_by_carrier_) {
352 // Restrict the proxy.
353 SetProxyConfigs(true /* enabled */,
354 IsDataReductionProxyAlternativeEnabled(),
355 true /* restricted */,
356 false /* at_startup */);
357 RecordProbeURLFetchResult(FAILED_PROXY_DISABLED);
358 } else {
359 RecordProbeURLFetchResult(FAILED_PROXY_ALREADY_DISABLED);
360 }
361 }
362 restricted_by_carrier_ = true;
363 }
364
GetOriginalProfilePrefs()365 PrefService* DataReductionProxySettings::GetOriginalProfilePrefs() {
366 DCHECK(thread_checker_.CalledOnValidThread());
367 return prefs_;
368 }
369
GetLocalStatePrefs()370 PrefService* DataReductionProxySettings::GetLocalStatePrefs() {
371 DCHECK(thread_checker_.CalledOnValidThread());
372 return local_state_prefs_;
373 }
374
AddDefaultProxyBypassRules()375 void DataReductionProxySettings::AddDefaultProxyBypassRules() {
376 // localhost
377 configurator_->AddHostPatternToBypass("<local>");
378 // RFC1918 private addresses.
379 configurator_->AddHostPatternToBypass("10.0.0.0/8");
380 configurator_->AddHostPatternToBypass("172.16.0.0/12");
381 configurator_->AddHostPatternToBypass("192.168.0.0/16");
382 // RFC4193 private addresses.
383 configurator_->AddHostPatternToBypass("fc00::/7");
384 // IPV6 probe addresses.
385 configurator_->AddHostPatternToBypass("*-ds.metric.gstatic.com");
386 configurator_->AddHostPatternToBypass("*-v4.metric.gstatic.com");
387 }
388
LogProxyState(bool enabled,bool restricted,bool at_startup)389 void DataReductionProxySettings::LogProxyState(
390 bool enabled, bool restricted, bool at_startup) {
391 // This must stay a LOG(WARNING); the output is used in processing customer
392 // feedback.
393 const char kAtStartup[] = "at startup";
394 const char kByUser[] = "by user action";
395 const char kOn[] = "ON";
396 const char kOff[] = "OFF";
397 const char kRestricted[] = "(Restricted)";
398 const char kUnrestricted[] = "(Unrestricted)";
399
400 std::string annotated_on =
401 kOn + std::string(" ") + (restricted ? kRestricted : kUnrestricted);
402
403 LOG(WARNING) << "SPDY proxy " << (enabled ? annotated_on : kOff)
404 << " " << (at_startup ? kAtStartup : kByUser);
405 }
406
OnIPAddressChanged()407 void DataReductionProxySettings::OnIPAddressChanged() {
408 DCHECK(thread_checker_.CalledOnValidThread());
409 if (enabled_by_user_) {
410 DCHECK(params_->allowed());
411 ProbeWhetherDataReductionProxyIsAvailable();
412 WarmProxyConnection();
413 }
414 }
415
OnProxyEnabledPrefChange()416 void DataReductionProxySettings::OnProxyEnabledPrefChange() {
417 DCHECK(thread_checker_.CalledOnValidThread());
418 if (!params_->allowed())
419 return;
420 MaybeActivateDataReductionProxy(false);
421 }
422
OnProxyAlternativeEnabledPrefChange()423 void DataReductionProxySettings::OnProxyAlternativeEnabledPrefChange() {
424 DCHECK(thread_checker_.CalledOnValidThread());
425 if (!params_->alternative_allowed())
426 return;
427 MaybeActivateDataReductionProxy(false);
428 }
429
ResetDataReductionStatistics()430 void DataReductionProxySettings::ResetDataReductionStatistics() {
431 DCHECK(thread_checker_.CalledOnValidThread());
432 PrefService* prefs = GetLocalStatePrefs();
433 if (!prefs)
434 return;
435 ListPrefUpdate original_update(prefs, prefs::kDailyHttpOriginalContentLength);
436 ListPrefUpdate received_update(prefs, prefs::kDailyHttpReceivedContentLength);
437 original_update->Clear();
438 received_update->Clear();
439 for (size_t i = 0; i < kNumDaysInHistory; ++i) {
440 original_update->AppendString(base::Int64ToString(0));
441 received_update->AppendString(base::Int64ToString(0));
442 }
443 }
444
MaybeActivateDataReductionProxy(bool at_startup)445 void DataReductionProxySettings::MaybeActivateDataReductionProxy(
446 bool at_startup) {
447 DCHECK(thread_checker_.CalledOnValidThread());
448 PrefService* prefs = GetOriginalProfilePrefs();
449 // TODO(marq): Consider moving this so stats are wiped the first time the
450 // proxy settings are actually (not maybe) turned on.
451 if (spdy_proxy_auth_enabled_.GetValue() &&
452 !prefs->GetBoolean(prefs::kDataReductionProxyWasEnabledBefore)) {
453 prefs->SetBoolean(prefs::kDataReductionProxyWasEnabledBefore, true);
454 ResetDataReductionStatistics();
455 }
456
457 // Configure use of the data reduction proxy if it is enabled.
458 enabled_by_user_= IsDataReductionProxyEnabled();
459 SetProxyConfigs(enabled_by_user_,
460 IsDataReductionProxyAlternativeEnabled(),
461 restricted_by_carrier_,
462 at_startup);
463
464 // Check if the proxy has been restricted explicitly by the carrier.
465 if (enabled_by_user_) {
466 ProbeWhetherDataReductionProxyIsAvailable();
467 WarmProxyConnection();
468 }
469 }
470
SetProxyConfigs(bool enabled,bool alternative_enabled,bool restricted,bool at_startup)471 void DataReductionProxySettings::SetProxyConfigs(bool enabled,
472 bool alternative_enabled,
473 bool restricted,
474 bool at_startup) {
475 DCHECK(thread_checker_.CalledOnValidThread());
476 LogProxyState(enabled, restricted, at_startup);
477 // The alternative is only configured if the standard configuration is
478 // is enabled.
479 if (enabled) {
480 if (alternative_enabled) {
481 configurator_->Enable(restricted,
482 !params_->fallback_allowed(),
483 params_->alt_origin().spec(),
484 params_->alt_fallback_origin().spec(),
485 params_->ssl_origin().spec());
486 } else {
487 configurator_->Enable(restricted,
488 !params_->fallback_allowed(),
489 params_->origin().spec(),
490 params_->fallback_origin().spec(),
491 std::string());
492 }
493 } else {
494 configurator_->Disable();
495 }
496 }
497
498 // Metrics methods
RecordDataReductionInit()499 void DataReductionProxySettings::RecordDataReductionInit() {
500 DCHECK(thread_checker_.CalledOnValidThread());
501 ProxyStartupState state = PROXY_NOT_AVAILABLE;
502 if (params_->allowed()) {
503 if (IsDataReductionProxyEnabled())
504 state = PROXY_ENABLED;
505 else
506 state = PROXY_DISABLED;
507 }
508
509 RecordStartupState(state);
510 }
511
RecordProbeURLFetchResult(ProbeURLFetchResult result)512 void DataReductionProxySettings::RecordProbeURLFetchResult(
513 ProbeURLFetchResult result) {
514 UMA_HISTOGRAM_ENUMERATION(kUMAProxyProbeURL,
515 result,
516 PROBE_URL_FETCH_RESULT_COUNT);
517 }
518
RecordStartupState(ProxyStartupState state)519 void DataReductionProxySettings::RecordStartupState(ProxyStartupState state) {
520 UMA_HISTOGRAM_ENUMERATION(kUMAProxyStartupStateHistogram,
521 state,
522 PROXY_STARTUP_STATE_COUNT);
523 }
524
ResetParamsForTest(DataReductionProxyParams * params)525 void DataReductionProxySettings::ResetParamsForTest(
526 DataReductionProxyParams* params) {
527 params_.reset(params);
528 }
529
530 DataReductionProxySettings::ContentLengthList
GetDailyContentLengths(const char * pref_name)531 DataReductionProxySettings::GetDailyContentLengths(const char* pref_name) {
532 DCHECK(thread_checker_.CalledOnValidThread());
533 DataReductionProxySettings::ContentLengthList content_lengths;
534 const base::ListValue* list_value = GetLocalStatePrefs()->GetList(pref_name);
535 if (list_value->GetSize() == kNumDaysInHistory) {
536 for (size_t i = 0; i < kNumDaysInHistory; ++i) {
537 content_lengths.push_back(GetInt64PrefValue(*list_value, i));
538 }
539 }
540 return content_lengths;
541 }
542
GetContentLengths(unsigned int days,int64 * original_content_length,int64 * received_content_length,int64 * last_update_time)543 void DataReductionProxySettings::GetContentLengths(
544 unsigned int days,
545 int64* original_content_length,
546 int64* received_content_length,
547 int64* last_update_time) {
548 DCHECK(thread_checker_.CalledOnValidThread());
549 DCHECK_LE(days, kNumDaysInHistory);
550 PrefService* local_state = GetLocalStatePrefs();
551 if (!local_state) {
552 *original_content_length = 0L;
553 *received_content_length = 0L;
554 *last_update_time = 0L;
555 return;
556 }
557
558 const base::ListValue* original_list =
559 local_state->GetList(prefs::kDailyHttpOriginalContentLength);
560 const base::ListValue* received_list =
561 local_state->GetList(prefs::kDailyHttpReceivedContentLength);
562
563 if (original_list->GetSize() != kNumDaysInHistory ||
564 received_list->GetSize() != kNumDaysInHistory) {
565 *original_content_length = 0L;
566 *received_content_length = 0L;
567 *last_update_time = 0L;
568 return;
569 }
570
571 int64 orig = 0L;
572 int64 recv = 0L;
573 // Include days from the end of the list going backwards.
574 for (size_t i = kNumDaysInHistory - days;
575 i < kNumDaysInHistory; ++i) {
576 orig += GetInt64PrefValue(*original_list, i);
577 recv += GetInt64PrefValue(*received_list, i);
578 }
579 *original_content_length = orig;
580 *received_content_length = recv;
581 *last_update_time =
582 local_state->GetInt64(prefs::kDailyHttpContentLengthLastUpdateDate);
583 }
584
585 // static
AuthHashForSalt(int64 salt,const std::string & key)586 base::string16 DataReductionProxySettings::AuthHashForSalt(
587 int64 salt,
588 const std::string& key) {
589 std::string salted_key =
590 base::StringPrintf("%lld%s%lld",
591 static_cast<long long>(salt),
592 key.c_str(),
593 static_cast<long long>(salt));
594 return base::UTF8ToUTF16(base::MD5String(salted_key));
595 }
596
GetBaseURLFetcher(const GURL & gurl,int load_flags)597 net::URLFetcher* DataReductionProxySettings::GetBaseURLFetcher(
598 const GURL& gurl,
599 int load_flags) {
600
601 net::URLFetcher* fetcher = net::URLFetcher::Create(gurl,
602 net::URLFetcher::GET,
603 this);
604 fetcher->SetLoadFlags(load_flags);
605 DCHECK(url_request_context_getter_);
606 fetcher->SetRequestContext(url_request_context_getter_);
607 // Configure max retries to be at most kMaxRetries times for 5xx errors.
608 static const int kMaxRetries = 5;
609 fetcher->SetMaxRetriesOn5xx(kMaxRetries);
610 fetcher->SetAutomaticallyRetryOnNetworkChanges(kMaxRetries);
611 return fetcher;
612 }
613
614
615 net::URLFetcher*
GetURLFetcherForAvailabilityCheck()616 DataReductionProxySettings::GetURLFetcherForAvailabilityCheck() {
617 return GetBaseURLFetcher(params_->probe_url(),
618 net::LOAD_DISABLE_CACHE | net::LOAD_BYPASS_PROXY);
619 }
620
621
ProbeWhetherDataReductionProxyIsAvailable()622 void DataReductionProxySettings::ProbeWhetherDataReductionProxyIsAvailable() {
623 net::URLFetcher* fetcher = GetURLFetcherForAvailabilityCheck();
624 if (!fetcher)
625 return;
626 fetcher_.reset(fetcher);
627 fetcher_->Start();
628 }
629
GetURLFetcherForWarmup()630 net::URLFetcher* DataReductionProxySettings::GetURLFetcherForWarmup() {
631 return GetBaseURLFetcher(params_->warmup_url(), net::LOAD_DISABLE_CACHE);
632 }
633
WarmProxyConnection()634 void DataReductionProxySettings::WarmProxyConnection() {
635 net::URLFetcher* fetcher = GetURLFetcherForWarmup();
636 if (!fetcher)
637 return;
638 warmup_fetcher_.reset(fetcher);
639 warmup_fetcher_->Start();
640 }
641
642 } // namespace data_reduction_proxy
643