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 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 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 80 DataReductionProxySettings::~DataReductionProxySettings() { 81 if (params_->allowed()) 82 spdy_proxy_auth_enabled_.Destroy(); 83 } 84 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 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 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 136 void DataReductionProxySettings::SetProxyConfigurator( 137 scoped_ptr<DataReductionProxyConfigurator> configurator) { 138 DCHECK(configurator); 139 configurator_ = configurator.Pass(); 140 } 141 142 // static 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 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 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 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 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 254 DataReductionProxySettings::IsDataReductionProxyAlternativeEnabled() const { 255 return data_reduction_proxy_alternative_enabled_.GetValue(); 256 } 257 258 bool DataReductionProxySettings::IsDataReductionProxyManaged() { 259 return spdy_proxy_auth_enabled_.IsManaged(); 260 } 261 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 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 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 296 DataReductionProxySettings::GetDailyOriginalContentLengths() { 297 DCHECK(thread_checker_.CalledOnValidThread()); 298 return GetDailyContentLengths(prefs::kDailyHttpOriginalContentLength); 299 } 300 301 DataReductionProxySettings::ContentLengthList 302 DataReductionProxySettings::GetDailyReceivedContentLengths() { 303 DCHECK(thread_checker_.CalledOnValidThread()); 304 return GetDailyContentLengths(prefs::kDailyHttpReceivedContentLength); 305 } 306 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 365 PrefService* DataReductionProxySettings::GetOriginalProfilePrefs() { 366 DCHECK(thread_checker_.CalledOnValidThread()); 367 return prefs_; 368 } 369 370 PrefService* DataReductionProxySettings::GetLocalStatePrefs() { 371 DCHECK(thread_checker_.CalledOnValidThread()); 372 return local_state_prefs_; 373 } 374 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 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 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 416 void DataReductionProxySettings::OnProxyEnabledPrefChange() { 417 DCHECK(thread_checker_.CalledOnValidThread()); 418 if (!params_->allowed()) 419 return; 420 MaybeActivateDataReductionProxy(false); 421 } 422 423 void DataReductionProxySettings::OnProxyAlternativeEnabledPrefChange() { 424 DCHECK(thread_checker_.CalledOnValidThread()); 425 if (!params_->alternative_allowed()) 426 return; 427 MaybeActivateDataReductionProxy(false); 428 } 429 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 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 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 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 512 void DataReductionProxySettings::RecordProbeURLFetchResult( 513 ProbeURLFetchResult result) { 514 UMA_HISTOGRAM_ENUMERATION(kUMAProxyProbeURL, 515 result, 516 PROBE_URL_FETCH_RESULT_COUNT); 517 } 518 519 void DataReductionProxySettings::RecordStartupState(ProxyStartupState state) { 520 UMA_HISTOGRAM_ENUMERATION(kUMAProxyStartupStateHistogram, 521 state, 522 PROXY_STARTUP_STATE_COUNT); 523 } 524 525 void DataReductionProxySettings::ResetParamsForTest( 526 DataReductionProxyParams* params) { 527 params_.reset(params); 528 } 529 530 DataReductionProxySettings::ContentLengthList 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 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 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 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* 616 DataReductionProxySettings::GetURLFetcherForAvailabilityCheck() { 617 return GetBaseURLFetcher(params_->probe_url(), 618 net::LOAD_DISABLE_CACHE | net::LOAD_BYPASS_PROXY); 619 } 620 621 622 void DataReductionProxySettings::ProbeWhetherDataReductionProxyIsAvailable() { 623 net::URLFetcher* fetcher = GetURLFetcherForAvailabilityCheck(); 624 if (!fetcher) 625 return; 626 fetcher_.reset(fetcher); 627 fetcher_->Start(); 628 } 629 630 net::URLFetcher* DataReductionProxySettings::GetURLFetcherForWarmup() { 631 return GetBaseURLFetcher(params_->warmup_url(), net::LOAD_DISABLE_CACHE); 632 } 633 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