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. 4 5 #include "chrome/browser/net/spdyproxy/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 "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" 37 38 using base::FieldTrialList; 39 using base::StringPrintf; 40 41 namespace { 42 43 // Key of the UMA DataReductionProxy.StartupState histogram. 44 const char kUMAProxyStartupStateHistogram[] = 45 "DataReductionProxy.StartupState"; 46 // Values of the UMA DataReductionProxy.StartupState histogram. 47 enum ProxyStartupState { 48 PROXY_NOT_AVAILABLE = 0, 49 PROXY_DISABLED, 50 PROXY_ENABLED, 51 PROXY_STARTUP_STATE_COUNT, 52 }; 53 54 // Key of the UMA DataReductionProxy.ProbeURL histogram. 55 const char kUMAProxyProbeURL[] = "DataReductionProxy.ProbeURL"; 56 // Values of the UMA DataReductionProxy.ProbeURL histogram. 57 // This enum must remain synchronized with DataReductionProxyProbeURLFetchResult 58 // in metrics/histograms/histograms.xml. 59 enum ProbeURLFetchResult { 60 // The probe failed because the internet was disconnected. 61 INTERNET_DISCONNECTED = 0, 62 63 // The probe failed for any other reason, and as a result, the proxy was 64 // disabled. 65 FAILED_PROXY_DISABLED, 66 67 // The probe failed, but the proxy was already disabled. 68 FAILED_PROXY_ALREADY_DISABLED, 69 70 // THe probe succeeded, and as a result the proxy was enabled. 71 SUCCEEDED_PROXY_ENABLED, 72 73 // The probe succeeded, but the proxy was already enabled. 74 SUCCEEDED_PROXY_ALREADY_ENABLED, 75 76 // This must always be last. 77 FETCH_RESULT_COUNT 78 }; 79 80 void RecordProbeURLFetchResult(ProbeURLFetchResult result) { 81 UMA_HISTOGRAM_ENUMERATION(kUMAProxyProbeURL, result, FETCH_RESULT_COUNT); 82 } 83 84 const char kEnabled[] = "Enabled"; 85 86 // TODO(marq): Factor this string out into a constant here and in 87 // http_auth_handler_spdyproxy. 88 const char kAuthenticationRealmName[] = "SpdyProxy"; 89 90 int64 GetInt64PrefValue(const ListValue& list_value, size_t index) { 91 int64 val = 0; 92 std::string pref_value; 93 bool rv = list_value.GetString(index, &pref_value); 94 DCHECK(rv); 95 if (rv) { 96 rv = base::StringToInt64(pref_value, &val); 97 DCHECK(rv); 98 } 99 return val; 100 } 101 102 bool IsProxyOriginSetOnCommandLine() { 103 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 104 return command_line.HasSwitch(switches::kSpdyProxyAuthOrigin); 105 } 106 107 } // namespace 108 109 DataReductionProxySettings::DataReductionProxySettings() 110 : restricted_by_carrier_(false), 111 enabled_by_user_(false) { 112 } 113 114 DataReductionProxySettings::~DataReductionProxySettings() { 115 if (IsDataReductionProxyAllowed()) 116 spdy_proxy_auth_enabled_.Destroy(); 117 } 118 119 void DataReductionProxySettings::InitPrefMembers() { 120 spdy_proxy_auth_enabled_.Init( 121 prefs::kSpdyProxyAuthEnabled, 122 GetOriginalProfilePrefs(), 123 base::Bind(&DataReductionProxySettings::OnProxyEnabledPrefChange, 124 base::Unretained(this))); 125 } 126 127 void DataReductionProxySettings::InitDataReductionProxySettings() { 128 InitPrefMembers(); 129 130 // Disable the proxy if it is not allowed to be used. 131 if (!IsDataReductionProxyAllowed()) 132 return; 133 134 AddDefaultProxyBypassRules(); 135 net::NetworkChangeNotifier::AddIPAddressObserver(this); 136 137 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 138 139 // Setting the kEnableSpdyProxyAuth switch has the same effect as enabling 140 // the feature via settings, in that once set, the preference will be sticky 141 // across instances of Chrome. Disabling the feature can only be done through 142 // the settings menu. 143 RecordDataReductionInit(); 144 if (spdy_proxy_auth_enabled_.GetValue() || 145 command_line.HasSwitch(switches::kEnableSpdyProxyAuth)) { 146 MaybeActivateDataReductionProxy(true); 147 } else { 148 // This is logged so we can use this information in user feedback. 149 LogProxyState(false /* enabled */, 150 false /* restricted */, 151 true /* at startup */); 152 } 153 } 154 155 // static 156 void DataReductionProxySettings::InitDataReductionProxySession( 157 net::HttpNetworkSession* session) { 158 // This is a no-op unless the authentication parameters are compiled in. 159 // (even though values for them may be specified on the command line). 160 // Authentication will still work if the command line parameters are used, 161 // however there will be a round-trip overhead for each challenge/response 162 // (typically once per session). 163 #if defined(SPDY_PROXY_AUTH_ORIGIN) && defined(SPDY_PROXY_AUTH_VALUE) 164 DCHECK(session); 165 net::HttpAuthCache* auth_cache = session->http_auth_cache(); 166 DCHECK(auth_cache); 167 InitDataReductionAuthentication(auth_cache); 168 #endif // defined(SPDY_PROXY_AUTH_ORIGIN) && defined(SPDY_PROXY_AUTH_VALUE) 169 } 170 171 // static 172 void DataReductionProxySettings::InitDataReductionAuthentication( 173 net::HttpAuthCache* auth_cache) { 174 DCHECK(auth_cache); 175 int64 timestamp = 176 (base::Time::Now() - base::Time::UnixEpoch()).InMilliseconds() / 1000; 177 178 DataReductionProxyList proxies = GetDataReductionProxies(); 179 for (DataReductionProxyList::iterator it = proxies.begin(); 180 it != proxies.end(); ++it) { 181 GURL auth_origin = (*it).GetOrigin(); 182 int32 rand[3]; 183 crypto::RandBytes(rand, 3 * sizeof(rand[0])); 184 185 std::string realm = 186 base::StringPrintf("%s%lld", kAuthenticationRealmName, timestamp); 187 std::string challenge = base::StringPrintf( 188 "%s realm=\"%s\", ps=\"%lld-%u-%u-%u\"", kAuthenticationRealmName, 189 realm.data(), timestamp, rand[0], rand[1], rand[2]); 190 base::string16 password = AuthHashForSalt(timestamp); 191 192 DVLOG(1) << "origin: [" << auth_origin << "] realm: [" << realm 193 << "] challenge: [" << challenge << "] password: [" << password << "]"; 194 195 net::AuthCredentials credentials(base::string16(), password); 196 // |HttpAuthController| searches this cache by origin and path, the latter 197 // being '/' in the case of the data reduction proxy. 198 auth_cache->Add(auth_origin, 199 realm, 200 net::HttpAuth::AUTH_SCHEME_SPDYPROXY, 201 challenge, 202 credentials, 203 std::string("/")); 204 } 205 } 206 207 void DataReductionProxySettings::AddHostPatternToBypass( 208 const std::string& pattern) { 209 bypass_rules_.push_back(pattern); 210 } 211 212 void DataReductionProxySettings::AddURLPatternToBypass( 213 const std::string& pattern) { 214 size_t pos = pattern.find("/"); 215 if (pattern.find("/", pos + 1) == pos + 1) 216 pos = pattern.find("/", pos + 2); 217 218 std::string host_pattern; 219 if (pos != std::string::npos) 220 host_pattern = pattern.substr(0, pos); 221 else 222 host_pattern = pattern; 223 224 AddHostPatternToBypass(host_pattern); 225 } 226 227 // static 228 bool DataReductionProxySettings::IsDataReductionProxyAllowed() { 229 return IsProxyOriginSetOnCommandLine() || 230 (FieldTrialList::FindFullName("DataCompressionProxyRollout") == kEnabled); 231 } 232 233 // static 234 bool DataReductionProxySettings::IsDataReductionProxyPromoAllowed() { 235 return IsProxyOriginSetOnCommandLine() || 236 (IsDataReductionProxyAllowed() && 237 FieldTrialList::FindFullName("DataCompressionProxyPromoVisibility") == 238 kEnabled); 239 } 240 241 // static 242 bool DataReductionProxySettings::IsPreconnectHintingAllowed() { 243 if (!IsDataReductionProxyAllowed()) 244 return false; 245 return FieldTrialList::FindFullName("DataCompressionProxyPreconnectHints") == 246 kEnabled; 247 } 248 249 // static 250 bool DataReductionProxySettings::WasFetchedViaProxy( 251 const net::HttpResponseHeaders* headers) { 252 const char kChromeProxyViaValue[] = "1.1 Chrome Compression Proxy"; 253 void* iter = NULL; 254 std::string value; 255 while (headers->EnumerateHeader(&iter, "via", &value)) 256 if (value == kChromeProxyViaValue) return true; 257 return false; 258 } 259 260 // static 261 std::string DataReductionProxySettings::GetDataReductionProxyOrigin() { 262 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 263 if (command_line.HasSwitch(switches::kSpdyProxyAuthOrigin)) 264 return command_line.GetSwitchValueASCII(switches::kSpdyProxyAuthOrigin); 265 #if defined(SPDY_PROXY_AUTH_ORIGIN) 266 return SPDY_PROXY_AUTH_ORIGIN; 267 #else 268 return std::string(); 269 #endif 270 } 271 272 // static 273 std::string DataReductionProxySettings::GetDataReductionProxyFallback() { 274 // Regardless of what else is defined, only return a value if the main proxy 275 // origin is defined. 276 if (GetDataReductionProxyOrigin().empty()) 277 return std::string(); 278 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 279 if (command_line.HasSwitch(switches::kSpdyProxyAuthFallback)) 280 return command_line.GetSwitchValueASCII(switches::kSpdyProxyAuthFallback); 281 #if defined(DATA_REDUCTION_FALLBACK_HOST) 282 return DATA_REDUCTION_FALLBACK_HOST; 283 #else 284 return std::string(); 285 #endif 286 } 287 288 bool DataReductionProxySettings::IsAcceptableAuthChallenge( 289 net::AuthChallengeInfo* auth_info) { 290 // Challenge realm must start with the authentication realm name. 291 std::string realm_prefix = 292 auth_info->realm.substr(0, strlen(kAuthenticationRealmName)); 293 if (realm_prefix != kAuthenticationRealmName) 294 return false; 295 296 // The challenger must be one of the configured proxies. 297 DataReductionProxyList proxies = GetDataReductionProxies(); 298 for (DataReductionProxyList::iterator it = proxies.begin(); 299 it != proxies.end(); ++it) { 300 net::HostPortPair origin_host = net::HostPortPair::FromURL(*it); 301 if (origin_host.Equals(auth_info->challenger)) 302 return true; 303 } 304 return false; 305 } 306 307 base::string16 DataReductionProxySettings::GetTokenForAuthChallenge( 308 net::AuthChallengeInfo* auth_info) { 309 if (auth_info->realm.length() > strlen(kAuthenticationRealmName)) { 310 int64 salt; 311 std::string realm_suffix = 312 auth_info->realm.substr(strlen(kAuthenticationRealmName)); 313 if (base::StringToInt64(realm_suffix, &salt)) { 314 return AuthHashForSalt(salt); 315 } else { 316 DVLOG(1) << "Unable to parse realm name " << auth_info->realm 317 << "into an int for salting."; 318 return base::string16(); 319 } 320 } else { 321 return base::string16(); 322 } 323 } 324 325 bool DataReductionProxySettings::IsDataReductionProxyEnabled() { 326 return spdy_proxy_auth_enabled_.GetValue(); 327 } 328 329 bool DataReductionProxySettings::IsDataReductionProxyManaged() { 330 return spdy_proxy_auth_enabled_.IsManaged(); 331 } 332 333 // static 334 DataReductionProxySettings::DataReductionProxyList 335 DataReductionProxySettings::GetDataReductionProxies() { 336 DataReductionProxyList proxies; 337 std::string proxy = GetDataReductionProxyOrigin(); 338 std::string fallback = GetDataReductionProxyFallback(); 339 340 if (!proxy.empty()) 341 proxies.push_back(GURL(proxy)); 342 343 if (!fallback.empty()) { 344 // Sanity check: fallback isn't the only proxy. 345 DCHECK(!proxies.empty()); 346 proxies.push_back(GURL(fallback)); 347 } 348 349 return proxies; 350 } 351 352 void DataReductionProxySettings::SetDataReductionProxyEnabled(bool enabled) { 353 // Prevent configuring the proxy when it is not allowed to be used. 354 if (!IsDataReductionProxyAllowed()) 355 return; 356 357 spdy_proxy_auth_enabled_.SetValue(enabled); 358 OnProxyEnabledPrefChange(); 359 } 360 361 int64 DataReductionProxySettings::GetDataReductionLastUpdateTime() { 362 PrefService* local_state = GetLocalStatePrefs(); 363 int64 last_update_internal = 364 local_state->GetInt64(prefs::kDailyHttpContentLengthLastUpdateDate); 365 base::Time last_update = base::Time::FromInternalValue(last_update_internal); 366 return static_cast<int64>(last_update.ToJsTime()); 367 } 368 369 DataReductionProxySettings::ContentLengthList 370 DataReductionProxySettings::GetDailyOriginalContentLengths() { 371 return GetDailyContentLengths(prefs::kDailyHttpOriginalContentLength); 372 } 373 374 DataReductionProxySettings::ContentLengthList 375 DataReductionProxySettings::GetDailyReceivedContentLengths() { 376 return GetDailyContentLengths(prefs::kDailyHttpReceivedContentLength); 377 } 378 379 void DataReductionProxySettings::OnURLFetchComplete( 380 const net::URLFetcher* source) { 381 net::URLRequestStatus status = source->GetStatus(); 382 if (status.status() == net::URLRequestStatus::FAILED && 383 status.error() == net::ERR_INTERNET_DISCONNECTED) { 384 RecordProbeURLFetchResult(INTERNET_DISCONNECTED); 385 return; 386 } 387 388 std::string response; 389 source->GetResponseAsString(&response); 390 391 if ("OK" == response.substr(0, 2)) { 392 DVLOG(1) << "The data reduction proxy is unrestricted."; 393 394 if (enabled_by_user_) { 395 if (restricted_by_carrier_) { 396 // The user enabled the proxy, but sometime previously in the session, 397 // the network operator had blocked the canary and restricted the user. 398 // The current network doesn't block the canary, so don't restrict the 399 // proxy configurations. 400 SetProxyConfigs(true /* enabled */, 401 false /* restricted */, 402 false /* at_startup */); 403 RecordProbeURLFetchResult(SUCCEEDED_PROXY_ENABLED); 404 } else { 405 RecordProbeURLFetchResult(SUCCEEDED_PROXY_ALREADY_ENABLED); 406 } 407 } 408 restricted_by_carrier_ = false; 409 return; 410 } 411 DVLOG(1) << "The data reduction proxy is restricted to the configured " 412 << "fallback proxy."; 413 414 if (enabled_by_user_) { 415 if (!restricted_by_carrier_) { 416 // Restrict the proxy. 417 SetProxyConfigs(true /* enabled */, 418 true /* restricted */, 419 false /* at_startup */); 420 RecordProbeURLFetchResult(FAILED_PROXY_DISABLED); 421 } else { 422 RecordProbeURLFetchResult(FAILED_PROXY_ALREADY_DISABLED); 423 } 424 } 425 restricted_by_carrier_ = true; 426 } 427 428 void DataReductionProxySettings::OnIPAddressChanged() { 429 if (enabled_by_user_) { 430 DCHECK(IsDataReductionProxyAllowed()); 431 ProbeWhetherDataReductionProxyIsAvailable(); 432 } 433 } 434 435 void DataReductionProxySettings::OnProxyEnabledPrefChange() { 436 if (!DataReductionProxySettings::IsDataReductionProxyAllowed()) 437 return; 438 MaybeActivateDataReductionProxy(false); 439 } 440 441 void DataReductionProxySettings::AddDefaultProxyBypassRules() { 442 // localhost 443 AddHostPatternToBypass("<local>"); 444 // RFC1918 private addresses. 445 AddHostPatternToBypass("10.0.0.0/8"); 446 AddHostPatternToBypass("172.16.0.0/12"); 447 AddHostPatternToBypass("192.168.0.0/16"); 448 // RFC4193 private addresses. 449 AddHostPatternToBypass("fc00::/7"); 450 // IPV6 probe addresses. 451 AddHostPatternToBypass("*-ds.metric.gstatic.com"); 452 AddHostPatternToBypass("*-v4.metric.gstatic.com"); 453 } 454 455 void DataReductionProxySettings::LogProxyState( 456 bool enabled, bool restricted, bool at_startup) { 457 // This must stay a LOG(WARNING); the output is used in processing customer 458 // feedback. 459 const char kAtStartup[] = "at startup"; 460 const char kByUser[] = "by user action"; 461 const char kOn[] = "ON"; 462 const char kOff[] = "OFF"; 463 const char kRestricted[] = "(Restricted)"; 464 const char kUnrestricted[] = "(Unrestricted)"; 465 466 std::string annotated_on = 467 kOn + std::string(" ") + (restricted ? kRestricted : kUnrestricted); 468 469 LOG(WARNING) << "SPDY proxy " << (enabled ? annotated_on : kOff) 470 << " " << (at_startup ? kAtStartup : kByUser); 471 } 472 473 PrefService* DataReductionProxySettings::GetOriginalProfilePrefs() { 474 return g_browser_process->profile_manager()->GetLastUsedProfile()-> 475 GetOriginalProfile()->GetPrefs(); 476 } 477 478 PrefService* DataReductionProxySettings::GetLocalStatePrefs() { 479 return g_browser_process->local_state(); 480 } 481 482 void DataReductionProxySettings::ResetDataReductionStatistics() { 483 PrefService* prefs = GetLocalStatePrefs(); 484 if (!prefs) 485 return; 486 ListPrefUpdate original_update(prefs, prefs::kDailyHttpOriginalContentLength); 487 ListPrefUpdate received_update(prefs, prefs::kDailyHttpReceivedContentLength); 488 original_update->Clear(); 489 received_update->Clear(); 490 for (size_t i = 0; i < spdyproxy::kNumDaysInHistory; ++i) { 491 original_update->AppendString(base::Int64ToString(0)); 492 received_update->AppendString(base::Int64ToString(0)); 493 } 494 } 495 496 void DataReductionProxySettings::MaybeActivateDataReductionProxy( 497 bool at_startup) { 498 PrefService* prefs = GetOriginalProfilePrefs(); 499 500 // TODO(marq): Consider moving this so stats are wiped the first time the 501 // proxy settings are actually (not maybe) turned on. 502 if (spdy_proxy_auth_enabled_.GetValue() && 503 !prefs->GetBoolean(prefs::kSpdyProxyAuthWasEnabledBefore)) { 504 prefs->SetBoolean(prefs::kSpdyProxyAuthWasEnabledBefore, true); 505 ResetDataReductionStatistics(); 506 } 507 508 std::string proxy = GetDataReductionProxyOrigin(); 509 // Configure use of the data reduction proxy if it is enabled and the proxy 510 // origin is non-empty. 511 enabled_by_user_= spdy_proxy_auth_enabled_.GetValue() && !proxy.empty(); 512 SetProxyConfigs(enabled_by_user_, restricted_by_carrier_, at_startup); 513 514 // Check if the proxy has been restricted explicitly by the carrier. 515 if (enabled_by_user_) 516 ProbeWhetherDataReductionProxyIsAvailable(); 517 } 518 519 void DataReductionProxySettings::SetProxyConfigs( 520 bool enabled, bool restricted, bool at_startup) { 521 // If |restricted| is true and there is no defined fallback proxy. 522 // treat this as a disable. 523 std::string fallback = GetDataReductionProxyFallback(); 524 if (fallback.empty() && enabled && restricted) 525 enabled = false; 526 527 LogProxyState(enabled, restricted, at_startup); 528 PrefService* prefs = GetOriginalProfilePrefs(); 529 DCHECK(prefs); 530 DictionaryPrefUpdate update(prefs, prefs::kProxy); 531 base::DictionaryValue* dict = update.Get(); 532 if (enabled) { 533 std::string proxy_list; 534 if (restricted) { 535 DCHECK(!fallback.empty()); 536 proxy_list = fallback; 537 } else { 538 proxy_list = GetDataReductionProxyOrigin() + 539 (fallback.empty() ? "" : "," + fallback); 540 } 541 542 std::string proxy_server_config = "http=" + proxy_list + ",direct://;"; 543 dict->SetString("server", proxy_server_config); 544 dict->SetString("mode", 545 ProxyModeToString(ProxyPrefs::MODE_FIXED_SERVERS)); 546 dict->SetString("bypass_list", JoinString(bypass_rules_, ", ")); 547 } else { 548 dict->SetString("mode", ProxyModeToString(ProxyPrefs::MODE_SYSTEM)); 549 dict->SetString("server", ""); 550 dict->SetString("bypass_list", ""); 551 } 552 } 553 554 // Metrics methods 555 void DataReductionProxySettings::RecordDataReductionInit() { 556 ProxyStartupState state = PROXY_NOT_AVAILABLE; 557 if (IsDataReductionProxyAllowed()) 558 state = IsDataReductionProxyEnabled() ? PROXY_ENABLED : PROXY_DISABLED; 559 UMA_HISTOGRAM_ENUMERATION(kUMAProxyStartupStateHistogram, 560 state, 561 PROXY_STARTUP_STATE_COUNT); 562 } 563 564 DataReductionProxySettings::ContentLengthList 565 DataReductionProxySettings::GetDailyContentLengths(const char* pref_name) { 566 DataReductionProxySettings::ContentLengthList content_lengths; 567 const ListValue* list_value = GetLocalStatePrefs()->GetList(pref_name); 568 if (list_value->GetSize() == spdyproxy::kNumDaysInHistory) { 569 for (size_t i = 0; i < spdyproxy::kNumDaysInHistory; ++i) { 570 content_lengths.push_back(GetInt64PrefValue(*list_value, i)); 571 } 572 } 573 return content_lengths; 574 } 575 576 void DataReductionProxySettings::GetContentLengths( 577 unsigned int days, 578 int64* original_content_length, 579 int64* received_content_length, 580 int64* last_update_time) { 581 DCHECK_LE(days, spdyproxy::kNumDaysInHistory); 582 PrefService* local_state = GetLocalStatePrefs(); 583 if (!local_state) { 584 *original_content_length = 0L; 585 *received_content_length = 0L; 586 *last_update_time = 0L; 587 return; 588 } 589 590 const ListValue* original_list = 591 local_state->GetList(prefs::kDailyHttpOriginalContentLength); 592 const ListValue* received_list = 593 local_state->GetList(prefs::kDailyHttpReceivedContentLength); 594 595 if (original_list->GetSize() != spdyproxy::kNumDaysInHistory || 596 received_list->GetSize() != spdyproxy::kNumDaysInHistory) { 597 *original_content_length = 0L; 598 *received_content_length = 0L; 599 *last_update_time = 0L; 600 return; 601 } 602 603 int64 orig = 0L; 604 int64 recv = 0L; 605 // Include days from the end of the list going backwards. 606 for (size_t i = spdyproxy::kNumDaysInHistory - days; 607 i < spdyproxy::kNumDaysInHistory; ++i) { 608 orig += GetInt64PrefValue(*original_list, i); 609 recv += GetInt64PrefValue(*received_list, i); 610 } 611 *original_content_length = orig; 612 *received_content_length = recv; 613 *last_update_time = 614 local_state->GetInt64(prefs::kDailyHttpContentLengthLastUpdateDate); 615 } 616 617 std::string DataReductionProxySettings::GetProxyCheckURL() { 618 if (!IsDataReductionProxyAllowed()) 619 return std::string(); 620 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 621 if (command_line.HasSwitch(switches::kDataReductionProxyProbeURL)) { 622 return command_line.GetSwitchValueASCII( 623 switches::kDataReductionProxyProbeURL); 624 } 625 #if defined(DATA_REDUCTION_PROXY_PROBE_URL) 626 return DATA_REDUCTION_PROXY_PROBE_URL; 627 #else 628 return std::string(); 629 #endif 630 } 631 632 // static 633 base::string16 DataReductionProxySettings::AuthHashForSalt(int64 salt) { 634 if (!IsDataReductionProxyAllowed()) 635 return base::string16(); 636 637 std::string key; 638 639 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 640 if (command_line.HasSwitch(switches::kSpdyProxyAuthOrigin)) { 641 // If an origin is provided via a switch, then only consider the value 642 // that is provided by a switch. Do not use the preprocessor constant. 643 // Don't expose SPDY_PROXY_AUTH_VALUE to a proxy passed in via the command 644 // line. 645 if (!command_line.HasSwitch(switches::kSpdyProxyAuthValue)) 646 return base::string16(); 647 key = command_line.GetSwitchValueASCII(switches::kSpdyProxyAuthValue); 648 } else { 649 #if defined(SPDY_PROXY_AUTH_VALUE) 650 key = SPDY_PROXY_AUTH_VALUE; 651 #else 652 return base::string16(); 653 #endif 654 } 655 656 DCHECK(!key.empty()); 657 658 std::string salted_key = 659 base::StringPrintf("%lld%s%lld", salt, key.c_str(), salt); 660 return UTF8ToUTF16(base::MD5String(salted_key)); 661 } 662 663 net::URLFetcher* DataReductionProxySettings::GetURLFetcher() { 664 std::string url = GetProxyCheckURL(); 665 if (url.empty()) 666 return NULL; 667 net::URLFetcher* fetcher = net::URLFetcher::Create(GURL(url), 668 net::URLFetcher::GET, 669 this); 670 fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE | net::LOAD_BYPASS_PROXY); 671 Profile* profile = g_browser_process->profile_manager()-> 672 GetDefaultProfile(); 673 fetcher->SetRequestContext(profile->GetRequestContext()); 674 // Configure max retries to be at most kMaxRetries times for 5xx errors. 675 static const int kMaxRetries = 5; 676 fetcher->SetMaxRetriesOn5xx(kMaxRetries); 677 return fetcher; 678 } 679 680 void 681 DataReductionProxySettings::ProbeWhetherDataReductionProxyIsAvailable() { 682 net::URLFetcher* fetcher = GetURLFetcher(); 683 if (!fetcher) 684 return; 685 fetcher_.reset(fetcher); 686 fetcher_->Start(); 687 } 688