| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/proxy/proxy_service.h" | 5 #include "net/proxy/proxy_service.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 DCHECK(!was_cancelled()); | 150 DCHECK(!was_cancelled()); |
| 151 | 151 |
| 152 // Make a note in the results which configuration was in use at the | 152 // Make a note in the results which configuration was in use at the |
| 153 // time of the resolve. | 153 // time of the resolve. |
| 154 results_->config_id_ = config_id_; | 154 results_->config_id_ = config_id_; |
| 155 | 155 |
| 156 // Reset the state associated with in-progress-resolve. | 156 // Reset the state associated with in-progress-resolve. |
| 157 resolve_job_ = NULL; | 157 resolve_job_ = NULL; |
| 158 config_id_ = ProxyConfig::INVALID_ID; | 158 config_id_ = ProxyConfig::INVALID_ID; |
| 159 | 159 |
| 160 // Notify the service of the completion. | 160 return service_->DidFinishResolvingProxy(results_, result_code, load_log_); |
| 161 service_->DidCompletePacRequest(results_->config_id_, result_code); | |
| 162 | |
| 163 // Clean up the results list. | |
| 164 if (result_code == OK) | |
| 165 results_->RemoveBadProxies(service_->proxy_retry_info_); | |
| 166 | |
| 167 LoadLog::EndEvent(load_log_, LoadLog::TYPE_PROXY_SERVICE); | |
| 168 | |
| 169 return result_code; | |
| 170 } | 161 } |
| 171 | 162 |
| 172 LoadLog* load_log() const { return load_log_; } | 163 LoadLog* load_log() const { return load_log_; } |
| 173 | 164 |
| 174 private: | 165 private: |
| 175 friend class base::RefCounted<ProxyService::PacRequest>; | 166 friend class base::RefCounted<ProxyService::PacRequest>; |
| 176 | 167 |
| 177 ~PacRequest() {} | 168 ~PacRequest() {} |
| 178 | 169 |
| 179 // Callback for when the ProxyResolver request has completed. | 170 // Callback for when the ProxyResolver request has completed. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 203 scoped_refptr<LoadLog> load_log_; | 194 scoped_refptr<LoadLog> load_log_; |
| 204 }; | 195 }; |
| 205 | 196 |
| 206 // ProxyService --------------------------------------------------------------- | 197 // ProxyService --------------------------------------------------------------- |
| 207 | 198 |
| 208 ProxyService::ProxyService(ProxyConfigService* config_service, | 199 ProxyService::ProxyService(ProxyConfigService* config_service, |
| 209 ProxyResolver* resolver) | 200 ProxyResolver* resolver) |
| 210 : config_service_(config_service), | 201 : config_service_(config_service), |
| 211 resolver_(resolver), | 202 resolver_(resolver), |
| 212 next_config_id_(1), | 203 next_config_id_(1), |
| 213 config_is_bad_(false), | |
| 214 should_use_proxy_resolver_(false), | 204 should_use_proxy_resolver_(false), |
| 215 ALLOW_THIS_IN_INITIALIZER_LIST(init_proxy_resolver_callback_( | 205 ALLOW_THIS_IN_INITIALIZER_LIST(init_proxy_resolver_callback_( |
| 216 this, &ProxyService::OnInitProxyResolverComplete)) { | 206 this, &ProxyService::OnInitProxyResolverComplete)) { |
| 217 } | 207 } |
| 218 | 208 |
| 219 // static | 209 // static |
| 220 ProxyService* ProxyService::Create( | 210 ProxyService* ProxyService::Create( |
| 221 ProxyConfigService* proxy_config_service, | 211 ProxyConfigService* proxy_config_service, |
| 222 bool use_v8_resolver, | 212 bool use_v8_resolver, |
| 223 URLRequestContext* url_request_context, | 213 URLRequestContext* url_request_context, |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 LoadLog::BeginEvent(load_log, LoadLog::TYPE_PROXY_SERVICE); | 263 LoadLog::BeginEvent(load_log, LoadLog::TYPE_PROXY_SERVICE); |
| 274 | 264 |
| 275 // Strip away any reference fragments and the username/password, as they | 265 // Strip away any reference fragments and the username/password, as they |
| 276 // are not relevant to proxy resolution. | 266 // are not relevant to proxy resolution. |
| 277 GURL url = SimplifyUrlForRequest(raw_url); | 267 GURL url = SimplifyUrlForRequest(raw_url); |
| 278 | 268 |
| 279 // Check if the request can be completed right away. This is the case when | 269 // Check if the request can be completed right away. This is the case when |
| 280 // using a direct connection, or when the config is bad. | 270 // using a direct connection, or when the config is bad. |
| 281 UpdateConfigIfOld(); | 271 UpdateConfigIfOld(); |
| 282 int rv = TryToCompleteSynchronously(url, result); | 272 int rv = TryToCompleteSynchronously(url, result); |
| 283 if (rv != ERR_IO_PENDING) { | 273 if (rv != ERR_IO_PENDING) |
| 284 LoadLog::EndEvent(load_log, LoadLog::TYPE_PROXY_SERVICE); | 274 return DidFinishResolvingProxy(result, rv, load_log); |
| 285 return rv; | |
| 286 } | |
| 287 | 275 |
| 288 scoped_refptr<PacRequest> req = | 276 scoped_refptr<PacRequest> req = |
| 289 new PacRequest(this, url, result, callback, load_log); | 277 new PacRequest(this, url, result, callback, load_log); |
| 290 | 278 |
| 291 bool resolver_is_ready = !IsInitializingProxyResolver(); | 279 bool resolver_is_ready = !IsInitializingProxyResolver(); |
| 292 | 280 |
| 293 if (resolver_is_ready) { | 281 if (resolver_is_ready) { |
| 294 // Start the resolve request. | 282 // Start the resolve request. |
| 295 rv = req->Start(); | 283 rv = req->Start(); |
| 296 if (rv != ERR_IO_PENDING) | 284 if (rv != ERR_IO_PENDING) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 310 *pac_request = req.get(); | 298 *pac_request = req.get(); |
| 311 return rv; // ERR_IO_PENDING | 299 return rv; // ERR_IO_PENDING |
| 312 } | 300 } |
| 313 | 301 |
| 314 int ProxyService::TryToCompleteSynchronously(const GURL& url, | 302 int ProxyService::TryToCompleteSynchronously(const GURL& url, |
| 315 ProxyInfo* result) { | 303 ProxyInfo* result) { |
| 316 result->config_id_ = config_.id(); | 304 result->config_id_ = config_.id(); |
| 317 | 305 |
| 318 DCHECK(config_.id() != ProxyConfig::INVALID_ID); | 306 DCHECK(config_.id() != ProxyConfig::INVALID_ID); |
| 319 | 307 |
| 320 // Fallback to a "direct" (no proxy) connection if the current configuration | 308 if (should_use_proxy_resolver_ || IsInitializingProxyResolver()) { |
| 321 // is known to be bad. | 309 // May need to go through ProxyResolver for this. |
| 322 if (config_is_bad_) { | 310 return ERR_IO_PENDING; |
| 323 // Reset this flag to false in case the ProxyInfo object is being | 311 } |
| 324 // re-used by the caller. | |
| 325 result->config_was_tried_ = false; | |
| 326 } else { | |
| 327 // Remember that we are trying to use the current proxy configuration. | |
| 328 result->config_was_tried_ = true; | |
| 329 | 312 |
| 330 if (should_use_proxy_resolver_ || IsInitializingProxyResolver()) { | 313 if (!config_.proxy_rules.empty()) { |
| 331 // May need to go through ProxyResolver for this. | 314 ApplyProxyRules(url, config_.proxy_rules, result); |
| 332 return ERR_IO_PENDING; | 315 return OK; |
| 333 } | |
| 334 | |
| 335 if (!config_.proxy_rules.empty()) { | |
| 336 ApplyProxyRules(url, config_.proxy_rules, result); | |
| 337 return OK; | |
| 338 } | |
| 339 } | 316 } |
| 340 | 317 |
| 341 // otherwise, we have no proxy config | 318 // otherwise, we have no proxy config |
| 342 result->UseDirect(); | 319 result->UseDirect(); |
| 343 return OK; | 320 return OK; |
| 344 } | 321 } |
| 345 | 322 |
| 346 void ProxyService::ApplyProxyRules(const GURL& url, | 323 void ProxyService::ApplyProxyRules(const GURL& url, |
| 347 const ProxyConfig::ProxyRules& proxy_rules, | 324 const ProxyConfig::ProxyRules& proxy_rules, |
| 348 ProxyInfo* result) { | 325 ProxyInfo* result) { |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 447 // Check to see if we have a new config since ResolveProxy was called. We | 424 // Check to see if we have a new config since ResolveProxy was called. We |
| 448 // want to re-run ResolveProxy in two cases: 1) we have a new config, or 2) a | 425 // want to re-run ResolveProxy in two cases: 1) we have a new config, or 2) a |
| 449 // direct connection failed and we never tried the current config. | 426 // direct connection failed and we never tried the current config. |
| 450 | 427 |
| 451 bool re_resolve = result->config_id_ != config_.id(); | 428 bool re_resolve = result->config_id_ != config_.id(); |
| 452 if (!re_resolve) { | 429 if (!re_resolve) { |
| 453 UpdateConfig(); | 430 UpdateConfig(); |
| 454 if (result->config_id_ != config_.id()) { | 431 if (result->config_id_ != config_.id()) { |
| 455 // A new configuration! | 432 // A new configuration! |
| 456 re_resolve = true; | 433 re_resolve = true; |
| 457 } else if (!result->config_was_tried_) { | |
| 458 // We never tried the proxy configuration since we thought it was bad, | |
| 459 // but because we failed to establish a connection, let's try the proxy | |
| 460 // configuration again to see if it will work now. | |
| 461 config_is_bad_ = false; | |
| 462 re_resolve = true; | |
| 463 } | 434 } |
| 464 } | 435 } |
| 465 if (re_resolve) { | 436 if (re_resolve) { |
| 466 // If we have a new config or the config was never tried, we delete the | 437 // If we have a new config or the config was never tried, we delete the |
| 467 // list of bad proxies and we try again. | 438 // list of bad proxies and we try again. |
| 468 proxy_retry_info_.clear(); | 439 proxy_retry_info_.clear(); |
| 469 return ResolveProxy(url, result, callback, pac_request, load_log); | 440 return ResolveProxy(url, result, callback, pac_request, load_log); |
| 470 } | 441 } |
| 471 | 442 |
| 472 // We don't have new proxy settings to try, fallback to the next proxy | 443 // We don't have new proxy settings to try, try to fallback to the next proxy |
| 473 // in the list. | 444 // in the list. |
| 474 bool was_direct = result->is_direct(); | 445 bool did_fallback = result->Fallback(&proxy_retry_info_); |
| 475 if (!was_direct && result->Fallback(&proxy_retry_info_)) | |
| 476 return OK; | |
| 477 | 446 |
| 478 // TODO(eroman): Hmm, this doesn't seem right. For starters just because | 447 // Return synchronous failure if there is nothing left to fall-back to. |
| 479 // auto_detect is true doesn't mean we are actually using it. | 448 // TODO(eroman): This is a yucky API, clean it up. |
| 480 if (!config_.auto_detect && !config_.proxy_rules.empty()) { | 449 return did_fallback ? OK : ERR_FAILED; |
| 481 // If auto detect is on, then we should try a DIRECT connection | |
| 482 // as the attempt to reach the proxy failed. | |
| 483 return ERR_FAILED; | |
| 484 } | |
| 485 | |
| 486 // If we already tried a direct connection, then just give up. | |
| 487 if (was_direct) | |
| 488 return ERR_FAILED; | |
| 489 | |
| 490 // Try going direct. | |
| 491 result->UseDirect(); | |
| 492 return OK; | |
| 493 } | 450 } |
| 494 | 451 |
| 495 void ProxyService::CancelPacRequest(PacRequest* req) { | 452 void ProxyService::CancelPacRequest(PacRequest* req) { |
| 496 DCHECK(req); | 453 DCHECK(req); |
| 497 req->Cancel(); | 454 req->Cancel(); |
| 498 RemovePendingRequest(req); | 455 RemovePendingRequest(req); |
| 499 } | 456 } |
| 500 | 457 |
| 501 bool ProxyService::ContainsPendingRequest(PacRequest* req) { | 458 bool ProxyService::ContainsPendingRequest(PacRequest* req) { |
| 502 PendingRequests::iterator it = std::find( | 459 PendingRequests::iterator it = std::find( |
| 503 pending_requests_.begin(), pending_requests_.end(), req); | 460 pending_requests_.begin(), pending_requests_.end(), req); |
| 504 return pending_requests_.end() != it; | 461 return pending_requests_.end() != it; |
| 505 } | 462 } |
| 506 | 463 |
| 507 void ProxyService::RemovePendingRequest(PacRequest* req) { | 464 void ProxyService::RemovePendingRequest(PacRequest* req) { |
| 508 DCHECK(ContainsPendingRequest(req)); | 465 DCHECK(ContainsPendingRequest(req)); |
| 509 PendingRequests::iterator it = std::find( | 466 PendingRequests::iterator it = std::find( |
| 510 pending_requests_.begin(), pending_requests_.end(), req); | 467 pending_requests_.begin(), pending_requests_.end(), req); |
| 511 pending_requests_.erase(it); | 468 pending_requests_.erase(it); |
| 512 } | 469 } |
| 513 | 470 |
| 471 int ProxyService::DidFinishResolvingProxy(ProxyInfo* result, |
| 472 int result_code, |
| 473 LoadLog* load_log) { |
| 474 // Clean up the results list. |
| 475 if (result_code == OK) |
| 476 result->DeprioritizeBadProxies(proxy_retry_info_); |
| 477 |
| 478 LoadLog::EndEvent(load_log, LoadLog::TYPE_PROXY_SERVICE); |
| 479 return result_code; |
| 480 } |
| 481 |
| 514 void ProxyService::SetProxyScriptFetcher( | 482 void ProxyService::SetProxyScriptFetcher( |
| 515 ProxyScriptFetcher* proxy_script_fetcher) { | 483 ProxyScriptFetcher* proxy_script_fetcher) { |
| 516 proxy_script_fetcher_.reset(proxy_script_fetcher); | 484 proxy_script_fetcher_.reset(proxy_script_fetcher); |
| 517 } | 485 } |
| 518 | 486 |
| 519 void ProxyService::ResetConfigService( | 487 void ProxyService::ResetConfigService( |
| 520 ProxyConfigService* new_proxy_config_service) { | 488 ProxyConfigService* new_proxy_config_service) { |
| 521 config_service_.reset(new_proxy_config_service); | 489 config_service_.reset(new_proxy_config_service); |
| 522 UpdateConfig(); | 490 UpdateConfig(); |
| 523 } | 491 } |
| 524 | 492 |
| 525 void ProxyService::PurgeMemory() { | 493 void ProxyService::PurgeMemory() { |
| 526 if (resolver_.get()) | 494 if (resolver_.get()) |
| 527 resolver_->PurgeMemory(); | 495 resolver_->PurgeMemory(); |
| 528 } | 496 } |
| 529 | 497 |
| 530 void ProxyService::DidCompletePacRequest(int config_id, int result_code) { | |
| 531 // If we get an error that indicates a bad PAC config, then we should | |
| 532 // remember that, and not try the PAC config again for a while. | |
| 533 | |
| 534 // Our config may have already changed. | |
| 535 if (result_code == OK || config_id != config_.id()) | |
| 536 return; | |
| 537 | |
| 538 // Remember that this configuration doesn't work. | |
| 539 config_is_bad_ = true; | |
| 540 } | |
| 541 | |
| 542 // static | 498 // static |
| 543 ProxyConfigService* ProxyService::CreateSystemProxyConfigService( | 499 ProxyConfigService* ProxyService::CreateSystemProxyConfigService( |
| 544 MessageLoop* io_loop, MessageLoop* file_loop) { | 500 MessageLoop* io_loop, MessageLoop* file_loop) { |
| 545 #if defined(OS_WIN) | 501 #if defined(OS_WIN) |
| 546 return new ProxyConfigServiceWin(); | 502 return new ProxyConfigServiceWin(); |
| 547 #elif defined(OS_MACOSX) | 503 #elif defined(OS_MACOSX) |
| 548 return new ProxyConfigServiceMac(); | 504 return new ProxyConfigServiceMac(); |
| 549 #elif defined(OS_LINUX) | 505 #elif defined(OS_LINUX) |
| 550 ProxyConfigServiceLinux* linux_config_service | 506 ProxyConfigServiceLinux* linux_config_service |
| 551 = new ProxyConfigServiceLinux(); | 507 = new ProxyConfigServiceLinux(); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 SetConfig(latest); | 562 SetConfig(latest); |
| 607 } | 563 } |
| 608 | 564 |
| 609 void ProxyService::SetConfig(const ProxyConfig& config) { | 565 void ProxyService::SetConfig(const ProxyConfig& config) { |
| 610 config_ = config; | 566 config_ = config; |
| 611 | 567 |
| 612 // Increment the ID to reflect that the config has changed. | 568 // Increment the ID to reflect that the config has changed. |
| 613 config_.set_id(next_config_id_++); | 569 config_.set_id(next_config_id_++); |
| 614 | 570 |
| 615 // Reset state associated with latest config. | 571 // Reset state associated with latest config. |
| 616 config_is_bad_ = false; | |
| 617 proxy_retry_info_.clear(); | 572 proxy_retry_info_.clear(); |
| 618 | 573 |
| 619 // Cancel any PAC fetching / ProxyResolver::SetPacScript() which was | 574 // Cancel any PAC fetching / ProxyResolver::SetPacScript() which was |
| 620 // in progress for the previous configuration. | 575 // in progress for the previous configuration. |
| 621 init_proxy_resolver_.reset(); | 576 init_proxy_resolver_.reset(); |
| 622 should_use_proxy_resolver_ = false; | 577 should_use_proxy_resolver_ = false; |
| 623 | 578 |
| 624 // Start downloading + testing the PAC scripts for this new configuration. | 579 // Start downloading + testing the PAC scripts for this new configuration. |
| 625 if (config_.MayRequirePACResolver()) { | 580 if (config_.MayRequirePACResolver()) { |
| 626 // Since InitProxyResolver will be playing around with the proxy resolver | 581 // Since InitProxyResolver will be playing around with the proxy resolver |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 795 OnCompletion(result_); | 750 OnCompletion(result_); |
| 796 } | 751 } |
| 797 } | 752 } |
| 798 | 753 |
| 799 void SyncProxyServiceHelper::OnCompletion(int rv) { | 754 void SyncProxyServiceHelper::OnCompletion(int rv) { |
| 800 result_ = rv; | 755 result_ = rv; |
| 801 event_.Signal(); | 756 event_.Signal(); |
| 802 } | 757 } |
| 803 | 758 |
| 804 } // namespace net | 759 } // namespace net |
| OLD | NEW |