Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(409)

Side by Side Diff: net/proxy/proxy_service.cc

Issue 160510: Better match IE's proxy settings.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: fix merge conflict Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/proxy/proxy_service.h ('k') | net/proxy/proxy_service_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
11 #include "base/message_loop.h" 11 #include "base/message_loop.h"
12 #include "base/string_util.h" 12 #include "base/string_util.h"
13 #include "googleurl/src/gurl.h" 13 #include "googleurl/src/gurl.h"
14 #include "net/base/net_errors.h" 14 #include "net/base/net_errors.h"
15 #include "net/base/net_util.h" 15 #include "net/base/net_util.h"
16 #include "net/proxy/init_proxy_resolver.h"
16 #include "net/proxy/proxy_config_service_fixed.h" 17 #include "net/proxy/proxy_config_service_fixed.h"
17 #include "net/proxy/proxy_script_fetcher.h" 18 #include "net/proxy/proxy_script_fetcher.h"
18 #if defined(OS_WIN) 19 #if defined(OS_WIN)
19 #include "net/proxy/proxy_config_service_win.h" 20 #include "net/proxy/proxy_config_service_win.h"
20 #include "net/proxy/proxy_resolver_winhttp.h" 21 #include "net/proxy/proxy_resolver_winhttp.h"
21 #elif defined(OS_MACOSX) 22 #elif defined(OS_MACOSX)
22 #include "net/proxy/proxy_resolver_mac.h" 23 #include "net/proxy/proxy_resolver_mac.h"
23 #elif defined(OS_LINUX) 24 #elif defined(OS_LINUX)
24 #include "net/proxy/proxy_config_service_linux.h" 25 #include "net/proxy/proxy_config_service_linux.h"
25 #endif 26 #endif
(...skipping 28 matching lines...) Expand all
54 CompletionCallback* callback, 55 CompletionCallback* callback,
55 RequestHandle* request) { 56 RequestHandle* request) {
56 return ERR_NOT_IMPLEMENTED; 57 return ERR_NOT_IMPLEMENTED;
57 } 58 }
58 59
59 virtual void CancelRequest(RequestHandle request) { 60 virtual void CancelRequest(RequestHandle request) {
60 NOTREACHED(); 61 NOTREACHED();
61 } 62 }
62 63
63 private: 64 private:
64 virtual void SetPacScriptByUrlInternal(const GURL& pac_url) {} 65 virtual int SetPacScript(const GURL& /*pac_url*/,
66 const std::string& /*pac_bytes*/,
67 CompletionCallback* /*callback*/) {
68 return ERR_NOT_IMPLEMENTED;
69 }
65 }; 70 };
66 71
67 // ProxyService::PacRequest --------------------------------------------------- 72 // ProxyService::PacRequest ---------------------------------------------------
68 73
69 class ProxyService::PacRequest 74 class ProxyService::PacRequest
70 : public base::RefCounted<ProxyService::PacRequest> { 75 : public base::RefCounted<ProxyService::PacRequest> {
71 public: 76 public:
72 PacRequest(ProxyService* service, 77 PacRequest(ProxyService* service,
73 const GURL& url, 78 const GURL& url,
74 ProxyInfo* results, 79 ProxyInfo* results,
(...skipping 18 matching lines...) Expand all
93 98
94 return resolver()->GetProxyForURL( 99 return resolver()->GetProxyForURL(
95 url_, results_, &io_callback_, &resolve_job_); 100 url_, results_, &io_callback_, &resolve_job_);
96 } 101 }
97 102
98 bool is_started() const { 103 bool is_started() const {
99 // Note that !! casts to bool. (VS gives a warning otherwise). 104 // Note that !! casts to bool. (VS gives a warning otherwise).
100 return !!resolve_job_; 105 return !!resolve_job_;
101 } 106 }
102 107
103 void StartAndComplete() { 108 void StartAndCompleteCheckingForSynchronous() {
104 int rv = Start(); 109 int rv = service_->TryToCompleteSynchronously(url_, results_);
110 if (rv == ERR_IO_PENDING)
111 rv = Start();
105 if (rv != ERR_IO_PENDING) 112 if (rv != ERR_IO_PENDING)
106 QueryComplete(rv); 113 QueryComplete(rv);
107 } 114 }
108 115
109 void Cancel() { 116 void CancelResolveJob() {
110 // The request may already be running in the resolver. 117 // The request may already be running in the resolver.
111 if (is_started()) { 118 if (is_started()) {
112 resolver()->CancelRequest(resolve_job_); 119 resolver()->CancelRequest(resolve_job_);
113 resolve_job_ = NULL; 120 resolve_job_ = NULL;
114 } 121 }
122 DCHECK(!is_started());
123 }
124
125 void Cancel() {
126 CancelResolveJob();
115 127
116 // Mark as cancelled, to prevent accessing this again later. 128 // Mark as cancelled, to prevent accessing this again later.
117 service_ = NULL; 129 service_ = NULL;
118 user_callback_ = NULL; 130 user_callback_ = NULL;
119 results_ = NULL; 131 results_ = NULL;
120 } 132 }
121 133
122 // Returns true if Cancel() has been called. 134 // Returns true if Cancel() has been called.
123 bool was_cancelled() const { return user_callback_ == NULL; } 135 bool was_cancelled() const { return user_callback_ == NULL; }
124 136
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 }; 182 };
171 183
172 // ProxyService --------------------------------------------------------------- 184 // ProxyService ---------------------------------------------------------------
173 185
174 ProxyService::ProxyService(ProxyConfigService* config_service, 186 ProxyService::ProxyService(ProxyConfigService* config_service,
175 ProxyResolver* resolver) 187 ProxyResolver* resolver)
176 : config_service_(config_service), 188 : config_service_(config_service),
177 resolver_(resolver), 189 resolver_(resolver),
178 next_config_id_(1), 190 next_config_id_(1),
179 config_is_bad_(false), 191 config_is_bad_(false),
180 ALLOW_THIS_IN_INITIALIZER_LIST(proxy_script_fetcher_callback_( 192 ALLOW_THIS_IN_INITIALIZER_LIST(init_proxy_resolver_callback_(
181 this, &ProxyService::OnScriptFetchCompletion)), 193 this, &ProxyService::OnInitProxyResolverComplete)) {
182 fetched_pac_config_id_(ProxyConfig::INVALID_ID),
183 fetched_pac_error_(OK),
184 in_progress_fetch_config_id_(ProxyConfig::INVALID_ID) {
185 } 194 }
186 195
187 // static 196 // static
188 ProxyService* ProxyService::Create( 197 ProxyService* ProxyService::Create(
189 const ProxyConfig* pc, 198 const ProxyConfig* pc,
190 bool use_v8_resolver, 199 bool use_v8_resolver,
191 URLRequestContext* url_request_context, 200 URLRequestContext* url_request_context,
192 MessageLoop* io_loop) { 201 MessageLoop* io_loop) {
193 // Choose the system configuration service appropriate for each platform. 202 // Choose the system configuration service appropriate for each platform.
194 ProxyConfigService* proxy_config_service = pc ? 203 ProxyConfigService* proxy_config_service = pc ?
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 256
248 // Check if the request can be completed right away. This is the case when 257 // Check if the request can be completed right away. This is the case when
249 // using a direct connection, or when the config is bad. 258 // using a direct connection, or when the config is bad.
250 UpdateConfigIfOld(); 259 UpdateConfigIfOld();
251 int rv = TryToCompleteSynchronously(url, result); 260 int rv = TryToCompleteSynchronously(url, result);
252 if (rv != ERR_IO_PENDING) 261 if (rv != ERR_IO_PENDING)
253 return rv; 262 return rv;
254 263
255 scoped_refptr<PacRequest> req = new PacRequest(this, url, result, callback); 264 scoped_refptr<PacRequest> req = new PacRequest(this, url, result, callback);
256 265
257 bool resolver_is_ready = PrepareResolverForRequests(); 266 bool resolver_is_ready = !IsInitializingProxyResolver();
258 267
259 if (resolver_is_ready) { 268 if (resolver_is_ready) {
260 // Start the resolve request. 269 // Start the resolve request.
261 rv = req->Start(); 270 rv = req->Start();
262 if (rv != ERR_IO_PENDING) 271 if (rv != ERR_IO_PENDING)
263 return req->QueryDidComplete(rv); 272 return req->QueryDidComplete(rv);
264 } 273 }
265 274
266 DCHECK_EQ(ERR_IO_PENDING, rv); 275 DCHECK_EQ(ERR_IO_PENDING, rv);
267 DCHECK(!ContainsPendingRequest(req)); 276 DCHECK(!ContainsPendingRequest(req));
(...skipping 15 matching lines...) Expand all
283 // Fallback to a "direct" (no proxy) connection if the current configuration 292 // Fallback to a "direct" (no proxy) connection if the current configuration
284 // is known to be bad. 293 // is known to be bad.
285 if (config_is_bad_) { 294 if (config_is_bad_) {
286 // Reset this flag to false in case the ProxyInfo object is being 295 // Reset this flag to false in case the ProxyInfo object is being
287 // re-used by the caller. 296 // re-used by the caller.
288 result->config_was_tried_ = false; 297 result->config_was_tried_ = false;
289 } else { 298 } else {
290 // Remember that we are trying to use the current proxy configuration. 299 // Remember that we are trying to use the current proxy configuration.
291 result->config_was_tried_ = true; 300 result->config_was_tried_ = true;
292 301
302 if (config_.MayRequirePACResolver()) {
303 // Need to go through ProxyResolver for this.
304 return ERR_IO_PENDING;
305 }
306
293 if (!config_.proxy_rules.empty()) { 307 if (!config_.proxy_rules.empty()) {
294 ApplyProxyRules(url, config_.proxy_rules, result); 308 ApplyProxyRules(url, config_.proxy_rules, result);
295 return OK; 309 return OK;
296 } 310 }
297
298 if (config_.pac_url.is_valid() || config_.auto_detect) {
299 // If we failed to download the PAC script, return the network error
300 // from the failed download. This is only going to happen for the first
301 // request after the failed download -- after that |config_is_bad_| will
302 // be set to true, so we short-cuircuit sooner.
303 if (fetched_pac_error_ != OK && !IsFetchingPacScript()) {
304 DidCompletePacRequest(fetched_pac_config_id_, fetched_pac_error_);
305 return fetched_pac_error_;
306 }
307 return ERR_IO_PENDING;
308 }
309 } 311 }
310 312
311 // otherwise, we have no proxy config 313 // otherwise, we have no proxy config
312 result->UseDirect(); 314 result->UseDirect();
313 return OK; 315 return OK;
314 } 316 }
315 317
316 void ProxyService::ApplyProxyRules(const GURL& url, 318 void ProxyService::ApplyProxyRules(const GURL& url,
317 const ProxyConfig::ProxyRules& proxy_rules, 319 const ProxyConfig::ProxyRules& proxy_rules,
318 ProxyInfo* result) { 320 ProxyInfo* result) {
(...skipping 28 matching lines...) Expand all
347 349
348 ProxyService::~ProxyService() { 350 ProxyService::~ProxyService() {
349 // Cancel any inprogress requests. 351 // Cancel any inprogress requests.
350 for (PendingRequests::iterator it = pending_requests_.begin(); 352 for (PendingRequests::iterator it = pending_requests_.begin();
351 it != pending_requests_.end(); 353 it != pending_requests_.end();
352 ++it) { 354 ++it) {
353 (*it)->Cancel(); 355 (*it)->Cancel();
354 } 356 }
355 } 357 }
356 358
359 void ProxyService::SuspendAllPendingRequests() {
360 for (PendingRequests::iterator it = pending_requests_.begin();
361 it != pending_requests_.end();
362 ++it) {
363 it->get()->CancelResolveJob();
364 }
365 }
366
357 void ProxyService::ResumeAllPendingRequests() { 367 void ProxyService::ResumeAllPendingRequests() {
368 DCHECK(!IsInitializingProxyResolver());
369
358 // Make a copy in case |this| is deleted during the synchronous completion 370 // Make a copy in case |this| is deleted during the synchronous completion
359 // of one of the requests. If |this| is deleted then all of the PacRequest 371 // of one of the requests. If |this| is deleted then all of the PacRequest
360 // instances will be Cancel()-ed. 372 // instances will be Cancel()-ed.
361 PendingRequests pending_copy = pending_requests_; 373 PendingRequests pending_copy = pending_requests_;
362 374
363 for (PendingRequests::iterator it = pending_copy.begin(); 375 for (PendingRequests::iterator it = pending_copy.begin();
364 it != pending_copy.end(); 376 it != pending_copy.end();
365 ++it) { 377 ++it) {
366 PacRequest* req = it->get(); 378 PacRequest* req = it->get();
367 if (!req->is_started() && !req->was_cancelled()) 379 if (!req->is_started() && !req->was_cancelled()) {
368 req->StartAndComplete(); 380 // Note that we re-check for synchronous completion, in case we are
381 // no longer using a ProxyResolver (can happen if we fell-back to manual).
382 req->StartAndCompleteCheckingForSynchronous();
383 }
369 } 384 }
370 } 385 }
371 386
372 bool ProxyService::PrepareResolverForRequests() { 387 void ProxyService::OnInitProxyResolverComplete(int result) {
373 // While the PAC script is being downloaded, block requests. 388 DCHECK(init_proxy_resolver_.get());
374 if (IsFetchingPacScript()) 389 DCHECK(config_.MayRequirePACResolver());
375 return false; 390 init_proxy_resolver_.reset();
376 391
377 // Check if a new PAC script needs to be downloaded. 392 if (result != OK) {
378 DCHECK(config_.id() != ProxyConfig::INVALID_ID); 393 LOG(INFO) << "Failed configuring with PAC script, falling-back to manual "
379 if (resolver_->expects_pac_bytes() && 394 "proxy servers.";
380 config_.id() != fetched_pac_config_id_) { 395 config_.auto_detect = false;
381 // For auto-detect we use the well known WPAD url. 396 config_.pac_url = GURL();
382 GURL pac_url = config_.auto_detect ? 397 DCHECK(!config_.MayRequirePACResolver());
383 GURL("http://wpad/wpad.dat") : config_.pac_url;
384
385 in_progress_fetch_config_id_ = config_.id();
386
387 LOG(INFO) << "Starting fetch of PAC script " << pac_url
388 << " for config_id=" << in_progress_fetch_config_id_;
389
390 proxy_script_fetcher_->Fetch(
391 pac_url, &in_progress_fetch_bytes_, &proxy_script_fetcher_callback_);
392 return false;
393 } 398 }
394 399
395 // We are good to go.
396 return true;
397 }
398
399 void ProxyService::OnScriptFetchCompletion(int result) {
400 DCHECK(IsFetchingPacScript());
401 DCHECK(resolver_->expects_pac_bytes());
402
403 LOG(INFO) << "Completed PAC script fetch for config_id="
404 << in_progress_fetch_config_id_
405 << " with error " << ErrorToString(result)
406 << ". Fetched a total of " << in_progress_fetch_bytes_.size()
407 << " bytes";
408
409 // Notify the ProxyResolver of the new script data (will be empty string if
410 // result != OK).
411 resolver_->SetPacScriptByData(in_progress_fetch_bytes_);
412
413 fetched_pac_config_id_ = in_progress_fetch_config_id_;
414 fetched_pac_error_ = result;
415 in_progress_fetch_config_id_ = ProxyConfig::INVALID_ID;
416 in_progress_fetch_bytes_.clear();
417
418 // Resume any requests which we had to defer until the PAC script was 400 // Resume any requests which we had to defer until the PAC script was
419 // downloaded. 401 // downloaded.
420 ResumeAllPendingRequests(); 402 ResumeAllPendingRequests();
421 } 403 }
422 404
423 int ProxyService::ReconsiderProxyAfterError(const GURL& url, 405 int ProxyService::ReconsiderProxyAfterError(const GURL& url,
424 ProxyInfo* result, 406 ProxyInfo* result,
425 CompletionCallback* callback, 407 CompletionCallback* callback,
426 PacRequest** pac_request) { 408 PacRequest** pac_request) {
427 // Check to see if we have a new config since ResolveProxy was called. We 409 // Check to see if we have a new config since ResolveProxy was called. We
(...skipping 20 matching lines...) Expand all
448 proxy_retry_info_.clear(); 430 proxy_retry_info_.clear();
449 return ResolveProxy(url, result, callback, pac_request); 431 return ResolveProxy(url, result, callback, pac_request);
450 } 432 }
451 433
452 // We don't have new proxy settings to try, fallback to the next proxy 434 // We don't have new proxy settings to try, fallback to the next proxy
453 // in the list. 435 // in the list.
454 bool was_direct = result->is_direct(); 436 bool was_direct = result->is_direct();
455 if (!was_direct && result->Fallback(&proxy_retry_info_)) 437 if (!was_direct && result->Fallback(&proxy_retry_info_))
456 return OK; 438 return OK;
457 439
440 // TODO(eroman): Hmm, this doesn't seem right. For starters just because
441 // auto_detect is true doesn't mean we are actually using it.
458 if (!config_.auto_detect && !config_.proxy_rules.empty()) { 442 if (!config_.auto_detect && !config_.proxy_rules.empty()) {
459 // If auto detect is on, then we should try a DIRECT connection 443 // If auto detect is on, then we should try a DIRECT connection
460 // as the attempt to reach the proxy failed. 444 // as the attempt to reach the proxy failed.
461 return ERR_FAILED; 445 return ERR_FAILED;
462 } 446 }
463 447
464 // If we already tried a direct connection, then just give up. 448 // If we already tried a direct connection, then just give up.
465 if (was_direct) 449 if (was_direct)
466 return ERR_FAILED; 450 return ERR_FAILED;
467 451
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 564
581 // Increment the ID to reflect that the config has changed. 565 // Increment the ID to reflect that the config has changed.
582 config_.set_id(next_config_id_++); 566 config_.set_id(next_config_id_++);
583 567
584 LOG(INFO) << "New proxy configuration was loaded:\n" << config_; 568 LOG(INFO) << "New proxy configuration was loaded:\n" << config_;
585 569
586 // Reset state associated with latest config. 570 // Reset state associated with latest config.
587 config_is_bad_ = false; 571 config_is_bad_ = false;
588 proxy_retry_info_.clear(); 572 proxy_retry_info_.clear();
589 573
590 // Tell the resolver to use the new PAC URL (for resolvers that fetch the 574 // Cancel any PAC fetching / ProxyResolver::SetPacScript() which was
591 // PAC script internally). 575 // in progress for the previous configuration.
592 // TODO(eroman): this isn't quite right. See http://crbug.com/9985 576 init_proxy_resolver_.reset();
593 if ((config_.pac_url.is_valid() || config_.auto_detect) && 577
594 !resolver_->expects_pac_bytes()) { 578 // Start downloading + testing the PAC scripts for this new configuration.
595 const GURL pac_url = config_.auto_detect ? GURL() : config_.pac_url; 579 if (config_.MayRequirePACResolver()) {
596 resolver_->SetPacScriptByUrl(pac_url); 580 // Since InitProxyResolver will be playing around with the proxy resolver
581 // as it tests the parsing of various PAC scripts, make sure there is
582 // nothing in-flight in |resolver_|. These paused requests are resumed by
583 // OnInitProxyResolverComplete().
584 SuspendAllPendingRequests();
585
586 init_proxy_resolver_.reset(
587 new InitProxyResolver(resolver_.get(), proxy_script_fetcher_.get()));
588 int rv = init_proxy_resolver_->Init(
589 config_, &init_proxy_resolver_callback_);
590 if (rv != ERR_IO_PENDING)
591 OnInitProxyResolverComplete(rv);
597 } 592 }
598 } 593 }
599 594
600 void ProxyService::UpdateConfigIfOld() { 595 void ProxyService::UpdateConfigIfOld() {
601 // The overhead of calling ProxyConfigService::GetProxyConfig is very low. 596 // The overhead of calling ProxyConfigService::GetProxyConfig is very low.
602 const TimeDelta kProxyConfigMaxAge = TimeDelta::FromSeconds(5); 597 const TimeDelta kProxyConfigMaxAge = TimeDelta::FromSeconds(5);
603 598
604 // Periodically check for a new config. 599 // Periodically check for a new config.
605 if (!config_has_been_initialized() || 600 if (!config_has_been_initialized() ||
606 (TimeTicks::Now() - config_last_update_time_) > kProxyConfigMaxAge) 601 (TimeTicks::Now() - config_last_update_time_) > kProxyConfigMaxAge)
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 OnCompletion(result_); 741 OnCompletion(result_);
747 } 742 }
748 } 743 }
749 744
750 void SyncProxyServiceHelper::OnCompletion(int rv) { 745 void SyncProxyServiceHelper::OnCompletion(int rv) {
751 result_ = rv; 746 result_ = rv;
752 event_.Signal(); 747 event_.Signal();
753 } 748 }
754 749
755 } // namespace net 750 } // namespace net
OLDNEW
« no previous file with comments | « net/proxy/proxy_service.h ('k') | net/proxy/proxy_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698