• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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