| 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 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
| 8 #include <windows.h> | 8 #include <windows.h> |
| 9 #include <winhttp.h> | 9 #include <winhttp.h> |
| 10 #endif | 10 #endif |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 namespace net { | 31 namespace net { |
| 32 | 32 |
| 33 // Config getter that fails every time. | 33 // Config getter that fails every time. |
| 34 class ProxyConfigServiceNull : public ProxyConfigService { | 34 class ProxyConfigServiceNull : public ProxyConfigService { |
| 35 public: | 35 public: |
| 36 virtual int GetProxyConfig(ProxyConfig* config) { | 36 virtual int GetProxyConfig(ProxyConfig* config) { |
| 37 return ERR_NOT_IMPLEMENTED; | 37 return ERR_NOT_IMPLEMENTED; |
| 38 } | 38 } |
| 39 }; | 39 }; |
| 40 | 40 |
| 41 // Strip away any reference fragments and the username/password, as they |
| 42 // are not relevant to proxy resolution. |
| 43 static GURL SanitizeURLForProxyResolver(const GURL& url) { |
| 44 // TODO(eroman): The following duplicates logic from |
| 45 // HttpUtil::SpecForRequest. Should probably live in net_util.h |
| 46 GURL::Replacements replacements; |
| 47 replacements.ClearUsername(); |
| 48 replacements.ClearPassword(); |
| 49 replacements.ClearRef(); |
| 50 return url.ReplaceComponents(replacements); |
| 51 } |
| 52 |
| 53 // Runs on the PAC thread to notify the proxy resolver of the fetched PAC |
| 54 // script contents. This task shouldn't outlive ProxyService, since |
| 55 // |resolver| is owned by ProxyService. |
| 56 class NotifyFetchCompletionTask : public Task { |
| 57 public: |
| 58 NotifyFetchCompletionTask(ProxyResolver* resolver, const std::string& bytes) |
| 59 : resolver_(resolver), bytes_(bytes) {} |
| 60 |
| 61 virtual void Run() { |
| 62 resolver_->SetPacScript(bytes_); |
| 63 } |
| 64 |
| 65 private: |
| 66 ProxyResolver* resolver_; |
| 67 std::string bytes_; |
| 68 }; |
| 41 | 69 |
| 42 // ProxyConfig ---------------------------------------------------------------- | 70 // ProxyConfig ---------------------------------------------------------------- |
| 43 | 71 |
| 44 // static | 72 // static |
| 45 ProxyConfig::ID ProxyConfig::last_id_ = ProxyConfig::INVALID_ID; | 73 ProxyConfig::ID ProxyConfig::last_id_ = ProxyConfig::INVALID_ID; |
| 46 | 74 |
| 47 ProxyConfig::ProxyConfig() | 75 ProxyConfig::ProxyConfig() |
| 48 : auto_detect(false), | 76 : auto_detect(false), |
| 49 proxy_bypass_local_names(false), | 77 proxy_bypass_local_names(false), |
| 50 id_(++last_id_) { | 78 id_(++last_id_) { |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 } | 215 } |
| 188 | 216 |
| 189 // ProxyService::PacRequest --------------------------------------------------- | 217 // ProxyService::PacRequest --------------------------------------------------- |
| 190 | 218 |
| 191 // We rely on the fact that the origin thread (and its message loop) will not | 219 // We rely on the fact that the origin thread (and its message loop) will not |
| 192 // be destroyed until after the PAC thread is destroyed. | 220 // be destroyed until after the PAC thread is destroyed. |
| 193 | 221 |
| 194 class ProxyService::PacRequest : | 222 class ProxyService::PacRequest : |
| 195 public base::RefCountedThreadSafe<ProxyService::PacRequest> { | 223 public base::RefCountedThreadSafe<ProxyService::PacRequest> { |
| 196 public: | 224 public: |
| 225 // |service| -- the ProxyService that owns this request. |
| 226 // |url| -- the url of the query. |
| 227 // |results| -- the structure to fill with proxy resolve results. |
| 197 PacRequest(ProxyService* service, | 228 PacRequest(ProxyService* service, |
| 198 const GURL& pac_url, | 229 const GURL& url, |
| 230 ProxyInfo* results, |
| 199 CompletionCallback* callback) | 231 CompletionCallback* callback) |
| 200 : service_(service), | 232 : service_(service), |
| 201 callback_(callback), | 233 callback_(callback), |
| 202 results_(NULL), | 234 results_(results), |
| 203 config_id_(service->config_id()), | 235 url_(url), |
| 204 pac_url_(pac_url), | 236 is_started_(false), |
| 205 origin_loop_(MessageLoop::current()) { | 237 origin_loop_(MessageLoop::current()) { |
| 206 DCHECK(callback); | 238 DCHECK(callback); |
| 207 } | 239 } |
| 208 | 240 |
| 209 void Query(const GURL& url, ProxyInfo* results) { | 241 // Start the resolve proxy request on the PAC thread. |
| 210 results_ = results; | 242 void Query() { |
| 211 // Execute Query asynchronously | 243 is_started_ = true; |
| 212 AddRef(); // balanced in QueryComplete | 244 AddRef(); // balanced in QueryComplete |
| 245 |
| 246 GURL query_url = SanitizeURLForProxyResolver(url_); |
| 247 const GURL& pac_url = service_->config_.pac_url; |
| 248 results_->config_id_ = service_->config_.id(); |
| 249 |
| 213 service_->pac_thread()->message_loop()->PostTask(FROM_HERE, | 250 service_->pac_thread()->message_loop()->PostTask(FROM_HERE, |
| 214 NewRunnableMethod(this, &ProxyService::PacRequest::DoQuery, | 251 NewRunnableMethod(this, &ProxyService::PacRequest::DoQuery, |
| 215 service_->resolver(), url, pac_url_)); | 252 service_->resolver(), query_url, pac_url)); |
| 253 } |
| 254 |
| 255 // Run the request's callback on the current message loop. |
| 256 void PostCallback(int result_code) { |
| 257 AddRef(); // balanced in DoCallback |
| 258 MessageLoop::current()->PostTask(FROM_HERE, |
| 259 NewRunnableMethod(this, &ProxyService::PacRequest::DoCallback, |
| 260 result_code)); |
| 216 } | 261 } |
| 217 | 262 |
| 218 void Cancel() { | 263 void Cancel() { |
| 219 // Clear these to inform QueryComplete that it should not try to | 264 // Clear these to inform QueryComplete that it should not try to |
| 220 // access them. | 265 // access them. |
| 221 service_ = NULL; | 266 service_ = NULL; |
| 222 callback_ = NULL; | 267 callback_ = NULL; |
| 223 results_ = NULL; | 268 results_ = NULL; |
| 224 } | 269 } |
| 225 | 270 |
| 271 // Returns true if Cancel() has been called. |
| 272 bool was_cancelled() const { return callback_ == NULL; } |
| 273 |
| 226 private: | 274 private: |
| 275 friend class ProxyService; |
| 276 |
| 227 // Runs on the PAC thread. | 277 // Runs on the PAC thread. |
| 228 void DoQuery(ProxyResolver* resolver, | 278 void DoQuery(ProxyResolver* resolver, |
| 229 const GURL& query_url, | 279 const GURL& query_url, |
| 230 const GURL& pac_url) { | 280 const GURL& pac_url) { |
| 231 int rv = resolver->GetProxyForURL(query_url, pac_url, &results_buf_); | 281 int rv = resolver->GetProxyForURL(query_url, pac_url, &results_buf_); |
| 232 origin_loop_->PostTask(FROM_HERE, | 282 origin_loop_->PostTask(FROM_HERE, |
| 233 NewRunnableMethod(this, &PacRequest::QueryComplete, rv)); | 283 NewRunnableMethod(this, &PacRequest::QueryComplete, rv)); |
| 234 } | 284 } |
| 235 | 285 |
| 236 // Runs the completion callback on the origin thread. | 286 // Runs the completion callback on the origin thread. |
| 237 void QueryComplete(int result_code) { | 287 void QueryComplete(int result_code) { |
| 238 // The PacRequest may have been cancelled after it was started. If it was | 288 // The PacRequest may have been cancelled after it was started. |
| 239 // cancelled then |callback_|, |service_|, and |results_| will be NULL. | 289 if (!was_cancelled()) { |
| 240 bool was_cancelled = callback_ == NULL; | 290 service_->DidCompletePacRequest(results_->config_id_, result_code); |
| 241 | |
| 242 if (!was_cancelled) { | |
| 243 service_->DidCompletePacRequest(config_id_, result_code); | |
| 244 | 291 |
| 245 if (result_code == OK) { | 292 if (result_code == OK) { |
| 246 results_->Use(results_buf_); | 293 results_->Use(results_buf_); |
| 247 results_->RemoveBadProxies(service_->proxy_retry_info_); | 294 results_->RemoveBadProxies(service_->proxy_retry_info_); |
| 248 } | 295 } |
| 249 callback_->Run(result_code); | 296 callback_->Run(result_code); |
| 297 |
| 298 // We check for cancellation once again, in case the callback deleted |
| 299 // the owning ProxyService (whose destructor will in turn cancel us). |
| 300 if (!was_cancelled()) |
| 301 service_->RemoveFrontOfRequestQueue(this); |
| 250 } | 302 } |
| 251 | 303 |
| 252 Release(); // balances the AddRef in Query. we may get deleted after | 304 Release(); // balances the AddRef in Query. we may get deleted after |
| 253 // we return. | 305 // we return. |
| 254 } | 306 } |
| 255 | 307 |
| 308 // Runs the completion callback on the origin thread. |
| 309 void DoCallback(int result_code) { |
| 310 if (!was_cancelled()) { |
| 311 callback_->Run(result_code); |
| 312 } |
| 313 Release(); // balances the AddRef in PostCallback. |
| 314 } |
| 315 |
| 256 // Must only be used on the "origin" thread. | 316 // Must only be used on the "origin" thread. |
| 257 ProxyService* service_; | 317 ProxyService* service_; |
| 258 CompletionCallback* callback_; | 318 CompletionCallback* callback_; |
| 259 ProxyInfo* results_; | 319 ProxyInfo* results_; |
| 260 ProxyConfig::ID config_id_; | 320 GURL url_; |
| 321 bool is_started_; |
| 261 | 322 |
| 262 // Usable from within DoQuery on the PAC thread. | 323 // Usable from within DoQuery on the PAC thread. |
| 263 ProxyInfo results_buf_; | 324 ProxyInfo results_buf_; |
| 264 GURL pac_url_; | |
| 265 MessageLoop* origin_loop_; | 325 MessageLoop* origin_loop_; |
| 266 }; | 326 }; |
| 267 | 327 |
| 268 // ProxyService --------------------------------------------------------------- | 328 // ProxyService --------------------------------------------------------------- |
| 269 | 329 |
| 270 ProxyService::ProxyService(ProxyConfigService* config_service, | 330 ProxyService::ProxyService(ProxyConfigService* config_service, |
| 271 ProxyResolver* resolver) | 331 ProxyResolver* resolver) |
| 272 : config_service_(config_service), | 332 : config_service_(config_service), |
| 273 resolver_(resolver), | 333 resolver_(resolver), |
| 274 config_is_bad_(false), | 334 config_is_bad_(false), |
| 275 config_has_been_updated_(false) { | 335 config_has_been_updated_(false), |
| 336 ALLOW_THIS_IN_INITIALIZER_LIST(proxy_script_fetcher_callback_( |
| 337 this, &ProxyService::OnScriptFetchCompletion)), |
| 338 fetched_pac_config_id_(ProxyConfig::INVALID_ID), |
| 339 fetched_pac_error_(OK), |
| 340 in_progress_fetch_config_id_(ProxyConfig::INVALID_ID) { |
| 276 } | 341 } |
| 277 | 342 |
| 278 // static | 343 // static |
| 279 ProxyService* ProxyService::Create(const ProxyInfo* pi) { | 344 ProxyService* ProxyService::Create(const ProxyInfo* pi) { |
| 280 if (pi) { | 345 if (pi) { |
| 281 // The ProxyResolver is set to NULL, since it should never be called | 346 // The ProxyResolver is set to NULL, since it should never be called |
| 282 // (because the configuration will never require PAC). | 347 // (because the configuration will never require PAC). |
| 283 return new ProxyService(new ProxyConfigServiceFixed(*pi), NULL); | 348 return new ProxyService(new ProxyConfigServiceFixed(*pi), NULL); |
| 284 } | 349 } |
| 285 #if defined(OS_WIN) | 350 #if defined(OS_WIN) |
| (...skipping 16 matching lines...) Expand all Loading... |
| 302 ProxyService* ProxyService::CreateNull() { | 367 ProxyService* ProxyService::CreateNull() { |
| 303 // The ProxyResolver is set to NULL, since it should never be called | 368 // The ProxyResolver is set to NULL, since it should never be called |
| 304 // (because the configuration will never require PAC). | 369 // (because the configuration will never require PAC). |
| 305 return new ProxyService(new ProxyConfigServiceNull, NULL); | 370 return new ProxyService(new ProxyConfigServiceNull, NULL); |
| 306 } | 371 } |
| 307 | 372 |
| 308 int ProxyService::ResolveProxy(const GURL& url, ProxyInfo* result, | 373 int ProxyService::ResolveProxy(const GURL& url, ProxyInfo* result, |
| 309 CompletionCallback* callback, | 374 CompletionCallback* callback, |
| 310 PacRequest** pac_request) { | 375 PacRequest** pac_request) { |
| 311 DCHECK(callback); | 376 DCHECK(callback); |
| 312 // The overhead of calling ProxyConfigService::GetProxyConfig is very low. | |
| 313 const TimeDelta kProxyConfigMaxAge = TimeDelta::FromSeconds(5); | |
| 314 | 377 |
| 315 // Periodically check for a new config. | 378 // Check if the request can be completed right away. This is the case when |
| 316 if (!config_has_been_updated_ || | 379 // using a direct connection, or when the config is bad. |
| 317 (TimeTicks::Now() - config_last_update_time_) > kProxyConfigMaxAge) | 380 UpdateConfigIfOld(); |
| 318 UpdateConfig(); | 381 int rv = TryToCompleteSynchronously(url, result); |
| 382 if (rv != ERR_IO_PENDING) |
| 383 return rv; |
| 384 |
| 385 // Otherwise, push the request into the work queue. |
| 386 scoped_refptr<PacRequest> req = new PacRequest(this, url, result, callback); |
| 387 pending_requests_.push_back(req); |
| 388 ProcessPendingRequests(req.get()); |
| 389 |
| 390 // Completion will be notifed through |callback|, unless the caller cancels |
| 391 // the request using |pac_request|. |
| 392 if (pac_request) |
| 393 *pac_request = req.get(); |
| 394 return rv; // ERR_IO_PENDING |
| 395 } |
| 396 |
| 397 int ProxyService::TryToCompleteSynchronously(const GURL& url, |
| 398 ProxyInfo* result) { |
| 319 result->config_id_ = config_.id(); | 399 result->config_id_ = config_.id(); |
| 320 | 400 |
| 401 DCHECK(config_.id() != ProxyConfig::INVALID_ID); |
| 402 |
| 321 // Fallback to a "direct" (no proxy) connection if the current configuration | 403 // Fallback to a "direct" (no proxy) connection if the current configuration |
| 322 // is known to be bad. | 404 // is known to be bad. |
| 323 if (config_is_bad_) { | 405 if (config_is_bad_) { |
| 324 // Reset this flag to false in case the ProxyInfo object is being | 406 // Reset this flag to false in case the ProxyInfo object is being |
| 325 // re-used by the caller. | 407 // re-used by the caller. |
| 326 result->config_was_tried_ = false; | 408 result->config_was_tried_ = false; |
| 327 } else { | 409 } else { |
| 328 // Remember that we are trying to use the current proxy configuration. | 410 // Remember that we are trying to use the current proxy configuration. |
| 329 result->config_was_tried_ = true; | 411 result->config_was_tried_ = true; |
| 330 | 412 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 } | 444 } |
| 363 } | 445 } |
| 364 // We failed to find a matching proxy server for the current URL | 446 // We failed to find a matching proxy server for the current URL |
| 365 // scheme. Default to direct. | 447 // scheme. Default to direct. |
| 366 result->UseDirect(); | 448 result->UseDirect(); |
| 367 } | 449 } |
| 368 return OK; | 450 return OK; |
| 369 } | 451 } |
| 370 | 452 |
| 371 if (config_.pac_url.is_valid() || config_.auto_detect) { | 453 if (config_.pac_url.is_valid() || config_.auto_detect) { |
| 372 if (!pac_thread_.get()) { | 454 // If we failed to download the PAC script, return the network error |
| 373 pac_thread_.reset(new base::Thread("pac-thread")); | 455 // from the failed download. This is only going to happen for the first |
| 374 pac_thread_->Start(); | 456 // request after the failed download -- after that |config_is_bad_| will |
| 457 // be set to true, so we short-cuircuit sooner. |
| 458 if (fetched_pac_error_ != OK && !IsFetchingPacScript()) { |
| 459 DidCompletePacRequest(fetched_pac_config_id_, fetched_pac_error_); |
| 460 return fetched_pac_error_; |
| 375 } | 461 } |
| 376 | 462 return ERR_IO_PENDING; |
| 377 scoped_refptr<PacRequest> req = | |
| 378 new PacRequest(this, config_.pac_url, callback); | |
| 379 | |
| 380 // Strip away any reference fragments and the username/password, as they | |
| 381 // are not relevant to proxy resolution. | |
| 382 GURL sanitized_url; | |
| 383 { // TODO(eroman): The following duplicates logic from | |
| 384 // HttpUtil::SpecForRequest. Should probably live in net_util.h | |
| 385 GURL::Replacements replacements; | |
| 386 replacements.ClearUsername(); | |
| 387 replacements.ClearPassword(); | |
| 388 replacements.ClearRef(); | |
| 389 sanitized_url = url.ReplaceComponents(replacements); | |
| 390 } | |
| 391 | |
| 392 req->Query(sanitized_url, result); | |
| 393 | |
| 394 if (pac_request) | |
| 395 *pac_request = req; | |
| 396 | |
| 397 return ERR_IO_PENDING; // Wait for callback. | |
| 398 } | 463 } |
| 399 } | 464 } |
| 400 | 465 |
| 401 // otherwise, we have no proxy config | 466 // otherwise, we have no proxy config |
| 402 result->UseDirect(); | 467 result->UseDirect(); |
| 403 return OK; | 468 return OK; |
| 404 } | 469 } |
| 405 | 470 |
| 471 void ProxyService::InitPacThread() { |
| 472 if (!pac_thread_.get()) { |
| 473 pac_thread_.reset(new base::Thread("pac-thread")); |
| 474 pac_thread_->Start(); |
| 475 } |
| 476 } |
| 477 |
| 478 ProxyService::~ProxyService() { |
| 479 // Cancel the inprogress request (if any), and free the rest. |
| 480 for (PendingRequestsQueue::iterator it = pending_requests_.begin(); |
| 481 it != pending_requests_.end(); |
| 482 ++it) { |
| 483 (*it)->Cancel(); |
| 484 } |
| 485 } |
| 486 |
| 487 void ProxyService::ProcessPendingRequests(PacRequest* recent_req) { |
| 488 if (pending_requests_.empty()) |
| 489 return; |
| 490 |
| 491 // While the PAC script is being downloaded, requests are blocked. |
| 492 if (IsFetchingPacScript()) |
| 493 return; |
| 494 |
| 495 // Get the next request to process (FIFO). |
| 496 PacRequest* req = pending_requests_.front().get(); |
| 497 if (req->is_started_) |
| 498 return; |
| 499 |
| 500 // The configuration may have changed since |req| was added to the |
| 501 // queue. It could be this request now completes synchronously. |
| 502 if (req != recent_req) { |
| 503 UpdateConfigIfOld(); |
| 504 int rv = TryToCompleteSynchronously(req->url_, req->results_); |
| 505 if (rv != ERR_IO_PENDING) { |
| 506 req->PostCallback(rv); |
| 507 RemoveFrontOfRequestQueue(req); |
| 508 return; |
| 509 } |
| 510 } |
| 511 |
| 512 // Check if a new PAC script needs to be downloaded. |
| 513 DCHECK(config_.id() != ProxyConfig::INVALID_ID); |
| 514 if (!resolver_->does_fetch() && config_.id() != fetched_pac_config_id_) { |
| 515 // For auto-detect we use the well known WPAD url. |
| 516 GURL pac_url = config_.auto_detect ? |
| 517 GURL("http://wpad/wpad.dat") : config_.pac_url; |
| 518 |
| 519 in_progress_fetch_config_id_ = config_.id(); |
| 520 |
| 521 proxy_script_fetcher_->Fetch( |
| 522 pac_url, &in_progress_fetch_bytes_, &proxy_script_fetcher_callback_); |
| 523 return; |
| 524 } |
| 525 |
| 526 // The only choice left now is to actually run the ProxyResolver on |
| 527 // the PAC thread. |
| 528 InitPacThread(); |
| 529 req->Query(); |
| 530 } |
| 531 |
| 532 void ProxyService::RemoveFrontOfRequestQueue(PacRequest* expected_req) { |
| 533 DCHECK(pending_requests_.front().get() == expected_req); |
| 534 pending_requests_.pop_front(); |
| 535 |
| 536 // Start next work item. |
| 537 ProcessPendingRequests(NULL); |
| 538 } |
| 539 |
| 540 void ProxyService::OnScriptFetchCompletion(int result) { |
| 541 DCHECK(IsFetchingPacScript()); |
| 542 DCHECK(!resolver_->does_fetch()); |
| 543 |
| 544 // Notify the ProxyResolver of the new script data (will be empty string if |
| 545 // result != OK). |
| 546 InitPacThread(); |
| 547 pac_thread()->message_loop()->PostTask(FROM_HERE, |
| 548 new NotifyFetchCompletionTask( |
| 549 resolver_.get(), in_progress_fetch_bytes_)); |
| 550 |
| 551 fetched_pac_config_id_ = in_progress_fetch_config_id_; |
| 552 fetched_pac_error_ = result; |
| 553 in_progress_fetch_config_id_ = ProxyConfig::INVALID_ID; |
| 554 in_progress_fetch_bytes_.clear(); |
| 555 |
| 556 // Start a pending request if any. |
| 557 ProcessPendingRequests(NULL); |
| 558 } |
| 559 |
| 406 int ProxyService::ReconsiderProxyAfterError(const GURL& url, | 560 int ProxyService::ReconsiderProxyAfterError(const GURL& url, |
| 407 ProxyInfo* result, | 561 ProxyInfo* result, |
| 408 CompletionCallback* callback, | 562 CompletionCallback* callback, |
| 409 PacRequest** pac_request) { | 563 PacRequest** pac_request) { |
| 410 // Check to see if we have a new config since ResolveProxy was called. We | 564 // Check to see if we have a new config since ResolveProxy was called. We |
| 411 // want to re-run ResolveProxy in two cases: 1) we have a new config, or 2) a | 565 // want to re-run ResolveProxy in two cases: 1) we have a new config, or 2) a |
| 412 // direct connection failed and we never tried the current config. | 566 // direct connection failed and we never tried the current config. |
| 413 | 567 |
| 414 bool re_resolve = result->config_id_ != config_.id(); | 568 bool re_resolve = result->config_id_ != config_.id(); |
| 415 if (!re_resolve) { | 569 if (!re_resolve) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 446 | 600 |
| 447 // If we already tried a direct connection, then just give up. | 601 // If we already tried a direct connection, then just give up. |
| 448 if (was_direct) | 602 if (was_direct) |
| 449 return ERR_FAILED; | 603 return ERR_FAILED; |
| 450 | 604 |
| 451 // Try going direct. | 605 // Try going direct. |
| 452 result->UseDirect(); | 606 result->UseDirect(); |
| 453 return OK; | 607 return OK; |
| 454 } | 608 } |
| 455 | 609 |
| 456 void ProxyService::CancelPacRequest(PacRequest* pac_request) { | 610 // There are four states of the request we need to handle: |
| 457 pac_request->Cancel(); | 611 // (1) Not started (just sitting in the queue). |
| 612 // (2) Executing PacRequest::DoQuery in the PAC thread. |
| 613 // (3) Waiting for PacRequest::QueryComplete to be run on the origin thread. |
| 614 // (4) Waiting for PacRequest::DoCallback to be run on the origin thread. |
| 615 void ProxyService::CancelPacRequest(PacRequest* req) { |
| 616 DCHECK(req); |
| 617 |
| 618 bool is_active_request = req->is_started_ && !pending_requests_.empty() && |
| 619 pending_requests_.front().get() == req; |
| 620 |
| 621 req->Cancel(); |
| 622 |
| 623 if (is_active_request) { |
| 624 RemoveFrontOfRequestQueue(req); |
| 625 return; |
| 626 } |
| 627 |
| 628 // Otherwise just delete the request from the queue. |
| 629 PendingRequestsQueue::iterator it = std::find( |
| 630 pending_requests_.begin(), pending_requests_.end(), req); |
| 631 if (it != pending_requests_.end()) { |
| 632 pending_requests_.erase(it); |
| 633 } |
| 458 } | 634 } |
| 459 | 635 |
| 460 void ProxyService::DidCompletePacRequest(int config_id, int result_code) { | 636 void ProxyService::DidCompletePacRequest(int config_id, int result_code) { |
| 461 // If we get an error that indicates a bad PAC config, then we should | 637 // If we get an error that indicates a bad PAC config, then we should |
| 462 // remember that, and not try the PAC config again for a while. | 638 // remember that, and not try the PAC config again for a while. |
| 463 | 639 |
| 464 // Our config may have already changed. | 640 // Our config may have already changed. |
| 465 if (result_code == OK || config_id != config_.id()) | 641 if (result_code == OK || config_id != config_.id()) |
| 466 return; | 642 return; |
| 467 | 643 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 480 if (latest.Equals(config_)) | 656 if (latest.Equals(config_)) |
| 481 return; | 657 return; |
| 482 | 658 |
| 483 config_ = latest; | 659 config_ = latest; |
| 484 config_is_bad_ = false; | 660 config_is_bad_ = false; |
| 485 | 661 |
| 486 // We have a new config, we should clear the list of bad proxies. | 662 // We have a new config, we should clear the list of bad proxies. |
| 487 proxy_retry_info_.clear(); | 663 proxy_retry_info_.clear(); |
| 488 } | 664 } |
| 489 | 665 |
| 666 void ProxyService::UpdateConfigIfOld() { |
| 667 // The overhead of calling ProxyConfigService::GetProxyConfig is very low. |
| 668 const TimeDelta kProxyConfigMaxAge = TimeDelta::FromSeconds(5); |
| 669 |
| 670 // Periodically check for a new config. |
| 671 if (!config_has_been_updated_ || |
| 672 (TimeTicks::Now() - config_last_update_time_) > kProxyConfigMaxAge) |
| 673 UpdateConfig(); |
| 674 } |
| 675 |
| 490 bool ProxyService::ShouldBypassProxyForURL(const GURL& url) { | 676 bool ProxyService::ShouldBypassProxyForURL(const GURL& url) { |
| 491 std::string url_domain = url.scheme(); | 677 std::string url_domain = url.scheme(); |
| 492 if (!url_domain.empty()) | 678 if (!url_domain.empty()) |
| 493 url_domain += "://"; | 679 url_domain += "://"; |
| 494 | 680 |
| 495 url_domain += url.host(); | 681 url_domain += url.host(); |
| 496 // This isn't superfluous; GURL case canonicalization doesn't hit the embedded | 682 // This isn't superfluous; GURL case canonicalization doesn't hit the embedded |
| 497 // percent-encoded characters. | 683 // percent-encoded characters. |
| 498 StringToLowerASCII(&url_domain); | 684 StringToLowerASCII(&url_domain); |
| 499 | 685 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 } | 774 } |
| 589 } | 775 } |
| 590 | 776 |
| 591 void SyncProxyServiceHelper::OnCompletion(int rv) { | 777 void SyncProxyServiceHelper::OnCompletion(int rv) { |
| 592 result_ = rv; | 778 result_ = rv; |
| 593 event_.Signal(); | 779 event_.Signal(); |
| 594 } | 780 } |
| 595 | 781 |
| 596 } // namespace net | 782 } // namespace net |
| 597 | 783 |
| OLD | NEW |