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

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

Issue 9078003: Poll PAC scripts for content changes. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: fix dcheck reached on bot Created 8 years, 11 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
« 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
11 #include "base/compiler_specific.h" 11 #include "base/compiler_specific.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/memory/weak_ptr.h"
13 #include "base/message_loop.h" 14 #include "base/message_loop.h"
14 #include "base/message_loop_proxy.h" 15 #include "base/message_loop_proxy.h"
15 #include "base/string_util.h" 16 #include "base/string_util.h"
16 #include "base/values.h" 17 #include "base/values.h"
17 #include "googleurl/src/gurl.h" 18 #include "googleurl/src/gurl.h"
18 #include "net/base/completion_callback.h" 19 #include "net/base/completion_callback.h"
19 #include "net/base/net_errors.h" 20 #include "net/base/net_errors.h"
20 #include "net/base/net_log.h" 21 #include "net/base/net_log.h"
21 #include "net/base/net_util.h" 22 #include "net/base/net_util.h"
22 #include "net/proxy/dhcp_proxy_script_fetcher.h" 23 #include "net/proxy/dhcp_proxy_script_fetcher.h"
(...skipping 22 matching lines...) Expand all
45 using base::TimeTicks; 46 using base::TimeTicks;
46 47
47 namespace net { 48 namespace net {
48 49
49 namespace { 50 namespace {
50 51
51 const size_t kMaxNumNetLogEntries = 100; 52 const size_t kMaxNumNetLogEntries = 100;
52 const size_t kDefaultNumPacThreads = 4; 53 const size_t kDefaultNumPacThreads = 4;
53 54
54 // When the IP address changes we don't immediately re-run proxy auto-config. 55 // When the IP address changes we don't immediately re-run proxy auto-config.
55 // Instead, we wait for |kNumMillisToStallAfterNetworkChanges| before 56 // Instead, we wait for |kDelayAfterNetworkChangesMs| before
56 // attempting to re-valuate proxy auto-config. 57 // attempting to re-valuate proxy auto-config.
57 // 58 //
58 // During this time window, any resolve requests sent to the ProxyService will 59 // During this time window, any resolve requests sent to the ProxyService will
59 // be queued. Once we have waited the required amount of them, the proxy 60 // be queued. Once we have waited the required amount of them, the proxy
60 // auto-config step will be run, and the queued requests resumed. 61 // auto-config step will be run, and the queued requests resumed.
61 // 62 //
62 // The reason we play this game is that our signal for detecting network 63 // The reason we play this game is that our signal for detecting network
63 // changes (NetworkChangeNotifier) may fire *before* the system's networking 64 // changes (NetworkChangeNotifier) may fire *before* the system's networking
64 // dependencies are fully configured. This is a problem since it means if 65 // dependencies are fully configured. This is a problem since it means if
65 // we were to run proxy auto-config right away, it could fail due to spurious 66 // we were to run proxy auto-config right away, it could fail due to spurious
66 // DNS failures. (see http://crbug.com/50779 for more details.) 67 // DNS failures. (see http://crbug.com/50779 for more details.)
67 // 68 //
68 // By adding the wait window, we give things a chance to get properly set up. 69 // By adding the wait window, we give things a better chance to get properly
69 // Now by the time we run the proxy-autoconfig there is a lower chance of 70 // set up. Network failures can happen at any time though, so we additionally
70 // getting transient DNS / connect failures. 71 // poll the PAC script for changes, which will allow us to recover from these
71 // 72 // sorts of problems.
72 // Admittedly this is a hack. Ideally we would have NetworkChangeNotifier 73 const int64 kDelayAfterNetworkChangesMs = 2000;
73 // deliver a reliable signal indicating that the network has changed AND is 74
74 // ready for action... But until then, we can reduce the likelihood of users 75 // The initial number of milliseconds to wait before refetching PAC script after
75 // getting wedged because of proxy detection failures on network switch. 76 // a fetch error/success.
76 // 77 const int64 kInitialPollDelayForErrorMs = 4000;
77 // The obvious downside to this strategy is it introduces an additional 78 const int64 kInitialPollDelayForSuccessMs = 16000;
78 // latency when switching networks. This delay shouldn't be too disruptive 79
79 // assuming network switches are infrequent and user initiated. However if 80 // The maximum poll delay for checking PAC scripts.
80 // NetworkChangeNotifier delivers network changes more frequently this could 81 const int64 kMaxPollDelayMs = 120000; // 2 minutes.
81 // cause jankiness. (NetworkChangeNotifier broadcasts a change event when ANY
82 // interface goes up/down. So in theory if the non-primary interface were
83 // hopping on and off wireless networks our constant delayed reconfiguration
84 // could add noticeable jank.)
85 //
86 // The specific hard-coded wait time below is arbitrary.
87 // Basically I ran some experiments switching between wireless networks on
88 // a Linux Ubuntu (Lucid) laptop, and experimentally found this timeout fixes
89 // things. It is entirely possible that the value is insufficient for other
90 // setups.
91 const int64 kNumMillisToStallAfterNetworkChanges = 2000;
92 82
93 // Config getter that always returns direct settings. 83 // Config getter that always returns direct settings.
94 class ProxyConfigServiceDirect : public ProxyConfigService { 84 class ProxyConfigServiceDirect : public ProxyConfigService {
95 public: 85 public:
96 // ProxyConfigService implementation: 86 // ProxyConfigService implementation:
97 virtual void AddObserver(Observer* observer) OVERRIDE {} 87 virtual void AddObserver(Observer* observer) OVERRIDE {}
98 virtual void RemoveObserver(Observer* observer) OVERRIDE {} 88 virtual void RemoveObserver(Observer* observer) OVERRIDE {}
99 virtual ConfigAvailability GetLatestProxyConfig(ProxyConfig* config) 89 virtual ConfigAvailability GetLatestProxyConfig(ProxyConfig* config)
100 OVERRIDE { 90 OVERRIDE {
101 *config = ProxyConfig::CreateDirect(); 91 *config = ProxyConfig::CreateDirect();
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 306
317 } // namespace 307 } // namespace
318 308
319 // ProxyService::InitProxyResolver -------------------------------------------- 309 // ProxyService::InitProxyResolver --------------------------------------------
320 310
321 // This glues together two asynchronous steps: 311 // This glues together two asynchronous steps:
322 // (1) ProxyScriptDecider -- try to fetch/validate a sequence of PAC scripts t o 312 // (1) ProxyScriptDecider -- try to fetch/validate a sequence of PAC scripts t o
323 // figure out what we should configure against. 313 // figure out what we should configure against.
324 // (2) Feed the fetched PAC script into the ProxyResolver. 314 // (2) Feed the fetched PAC script into the ProxyResolver.
325 // 315 //
326 // TODO(eroman): This is something of a temporary shim while refactoring to keep 316 // InitProxyResolver is a single-use class which encapsulates cancellation as
327 // things similar. It will probably end up changing while solving bug 90581. 317 // part of its destructor. Start() or StartSkipDecider() should be called just
318 // once. The instance can be destroyed at any time, and the request will be
319 // cancelled.
328 320
329 class ProxyService::InitProxyResolver { 321 class ProxyService::InitProxyResolver {
330 public: 322 public:
331 InitProxyResolver(ProxyResolver* proxy_resolver, 323 InitProxyResolver()
332 ProxyScriptFetcher* proxy_script_fetcher, 324 : proxy_resolver_(NULL),
333 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher, 325 next_state_(STATE_NONE) {
334 NetLog* net_log)
335 : decider_(proxy_script_fetcher, dhcp_proxy_script_fetcher, net_log),
336 effective_config_(NULL),
337 proxy_resolver_(proxy_resolver) {
338 } 326 }
339 327
340 ~InitProxyResolver() { 328 ~InitProxyResolver() {
341 // Note that the destruction of ProxyScriptDecider will automatically cancel 329 // Note that the destruction of ProxyScriptDecider will automatically cancel
342 // any outstanding work. 330 // any outstanding work.
343 if (next_state_ == STATE_SET_PAC_SCRIPT_COMPLETE) { 331 if (next_state_ == STATE_SET_PAC_SCRIPT_COMPLETE) {
344 proxy_resolver_->CancelSetPacScript(); 332 proxy_resolver_->CancelSetPacScript();
345 } 333 }
346 } 334 }
347 335
348 int Init(const ProxyConfig& config, 336 // Begins initializing the proxy resolver; calls |callback| when done.
349 base::TimeDelta wait_delay, 337 int Start(ProxyResolver* proxy_resolver,
350 ProxyConfig* effective_config, 338 ProxyScriptFetcher* proxy_script_fetcher,
351 const CompletionCallback& callback) { 339 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher,
340 NetLog* net_log,
341 const ProxyConfig& config,
342 base::TimeDelta wait_delay,
343 const CompletionCallback& callback) {
344 DCHECK_EQ(STATE_NONE, next_state_);
345 proxy_resolver_ = proxy_resolver;
346
347 decider_.reset(new ProxyScriptDecider(
348 proxy_script_fetcher, dhcp_proxy_script_fetcher, net_log));
352 config_ = config; 349 config_ = config;
353 wait_delay_ = wait_delay; 350 wait_delay_ = wait_delay;
354 effective_config_ = effective_config;
355 callback_ = callback; 351 callback_ = callback;
356 352
357 next_state_ = STATE_DECIDE_PROXY_SCRIPT; 353 next_state_ = STATE_DECIDE_PROXY_SCRIPT;
358 return DoLoop(OK); 354 return DoLoop(OK);
359 } 355 }
360 356
357 // Similar to Start(), however it skips the ProxyScriptDecider stage. Instead
358 // |effective_config|, |decider_result| and |script_data| will be used as the
359 // inputs for initializing the ProxyResolver.
360 int StartSkipDecider(ProxyResolver* proxy_resolver,
361 const ProxyConfig& effective_config,
362 int decider_result,
363 ProxyResolverScriptData* script_data,
364 const CompletionCallback& callback) {
365 DCHECK_EQ(STATE_NONE, next_state_);
366 proxy_resolver_ = proxy_resolver;
367
368 effective_config_ = effective_config;
369 script_data_ = script_data;
370 callback_ = callback;
371
372 if (decider_result != OK)
373 return decider_result;
374
375 next_state_ = STATE_SET_PAC_SCRIPT;
376 return DoLoop(OK);
377 }
378
379 // Returns the proxy configuration that was selected by ProxyScriptDecider.
380 // Should only be called upon completion of the initialization.
381 const ProxyConfig& effective_config() const {
382 DCHECK_EQ(STATE_NONE, next_state_);
383 return effective_config_;
384 }
385
386 // Returns the PAC script data that was selected by ProxyScriptDecider.
387 // Should only be called upon completion of the initialization.
388 ProxyResolverScriptData* script_data() {
389 DCHECK_EQ(STATE_NONE, next_state_);
390 return script_data_.get();
391 }
392
361 private: 393 private:
362 enum State { 394 enum State {
363 STATE_NONE, 395 STATE_NONE,
364 STATE_DECIDE_PROXY_SCRIPT, 396 STATE_DECIDE_PROXY_SCRIPT,
365 STATE_DECIDE_PROXY_SCRIPT_COMPLETE, 397 STATE_DECIDE_PROXY_SCRIPT_COMPLETE,
366 STATE_SET_PAC_SCRIPT, 398 STATE_SET_PAC_SCRIPT,
367 STATE_SET_PAC_SCRIPT_COMPLETE, 399 STATE_SET_PAC_SCRIPT_COMPLETE,
368 }; 400 };
369 401
370 int DoLoop(int result) { 402 int DoLoop(int result) {
(...skipping 22 matching lines...) Expand all
393 rv = ERR_UNEXPECTED; 425 rv = ERR_UNEXPECTED;
394 break; 426 break;
395 } 427 }
396 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 428 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
397 return rv; 429 return rv;
398 } 430 }
399 431
400 int DoDecideProxyScript() { 432 int DoDecideProxyScript() {
401 next_state_ = STATE_DECIDE_PROXY_SCRIPT_COMPLETE; 433 next_state_ = STATE_DECIDE_PROXY_SCRIPT_COMPLETE;
402 434
403 return decider_.Start( 435 return decider_->Start(
404 config_, wait_delay_, proxy_resolver_->expects_pac_bytes(), 436 config_, wait_delay_, proxy_resolver_->expects_pac_bytes(),
405 base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this))); 437 base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this)));
406 } 438 }
407 439
408 int DoDecideProxyScriptComplete(int result) { 440 int DoDecideProxyScriptComplete(int result) {
409 if (result != OK) 441 if (result != OK)
410 return result; 442 return result;
411 443
412 *effective_config_ = decider_.effective_config(); 444 effective_config_ = decider_->effective_config();
445 script_data_ = decider_->script_data();
446
413 next_state_ = STATE_SET_PAC_SCRIPT; 447 next_state_ = STATE_SET_PAC_SCRIPT;
414 return OK; 448 return OK;
415 } 449 }
416 450
417 int DoSetPacScript() { 451 int DoSetPacScript() {
418 DCHECK(decider_.script_data()); 452 DCHECK(script_data_);
419 // TODO(eroman): Should log this latency to the NetLog. 453 // TODO(eroman): Should log this latency to the NetLog.
420 next_state_ = STATE_SET_PAC_SCRIPT_COMPLETE; 454 next_state_ = STATE_SET_PAC_SCRIPT_COMPLETE;
421 return proxy_resolver_->SetPacScript( 455 return proxy_resolver_->SetPacScript(
422 decider_.script_data(), 456 script_data_,
423 base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this))); 457 base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this)));
424 } 458 }
425 459
426 int DoSetPacScriptComplete(int result) { 460 int DoSetPacScriptComplete(int result) {
427 return result; 461 return result;
428 } 462 }
429 463
430 void OnIOCompletion(int result) { 464 void OnIOCompletion(int result) {
431 DCHECK_NE(STATE_NONE, next_state_); 465 DCHECK_NE(STATE_NONE, next_state_);
432 int rv = DoLoop(result); 466 int rv = DoLoop(result);
433 if (rv != ERR_IO_PENDING) 467 if (rv != ERR_IO_PENDING)
434 DoCallback(rv); 468 DoCallback(rv);
435 } 469 }
436 470
437 void DoCallback(int result) { 471 void DoCallback(int result) {
438 DCHECK_NE(ERR_IO_PENDING, result); 472 DCHECK_NE(ERR_IO_PENDING, result);
439 callback_.Run(result); 473 callback_.Run(result);
440 } 474 }
441 475
442 ProxyConfig config_; 476 ProxyConfig config_;
477 ProxyConfig effective_config_;
478 scoped_refptr<ProxyResolverScriptData> script_data_;
443 base::TimeDelta wait_delay_; 479 base::TimeDelta wait_delay_;
444 ProxyScriptDecider decider_; 480 scoped_ptr<ProxyScriptDecider> decider_;
445 ProxyConfig* effective_config_;
446 ProxyResolver* proxy_resolver_; 481 ProxyResolver* proxy_resolver_;
447 CompletionCallback callback_; 482 CompletionCallback callback_;
448 State next_state_; 483 State next_state_;
449 484
450 DISALLOW_COPY_AND_ASSIGN(InitProxyResolver); 485 DISALLOW_COPY_AND_ASSIGN(InitProxyResolver);
451 }; 486 };
452 487
488 // ProxyService::ProxyScriptDeciderPoller -------------------------------------
489
490 // This helper class encapsulates the logic to schedule and run periodic
491 // background checks to see if the PAC script (or effective proxy configuration)
492 // has changed. If a change is detected, then the caller will be notified via
493 // the ChangeCallback.
494 class ProxyService::ProxyScriptDeciderPoller {
495 public:
496 typedef base::Callback<void(int, ProxyResolverScriptData*,
497 const ProxyConfig&)> ChangeCallback;
498
499 // Builds a poller helper, and starts polling for updates. Whenever a change
500 // is observed, |callback| will be invoked with the details.
501 //
502 // |config| specifies the (unresolved) proxy configuration to poll.
503 // |proxy_resolver_expects_pac_bytes| the type of proxy resolver we expect
504 // to use the resulting script data with
505 // (so it can choose the right format).
506 // |proxy_script_fetcher| this pointer must remain alive throughout our
507 // lifetime. It is the dependency that will be used
508 // for downloading proxy scripts.
509 // |dhcp_proxy_script_fetcher| similar to |proxy_script_fetcher|, but for
510 // the DHCP dependency.
511 // |init_net_error| This is the initial network error (possibly success)
512 // encountered by the first PAC fetch attempt. We use it
513 // to schedule updates more aggressively if the initial
514 // fetch resulted in an error.
515 // |init_script_data| the initial script data from the PAC fetch attempt.
516 // This is the baseline used to determine when the
517 // script's contents have changed.
518 // |net_log| the NetLog to log progress into.
519 ProxyScriptDeciderPoller(ChangeCallback callback,
520 const ProxyConfig& config,
521 bool proxy_resolver_expects_pac_bytes,
522 ProxyScriptFetcher* proxy_script_fetcher,
523 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher,
524 int init_net_error,
525 ProxyResolverScriptData* init_script_data,
526 NetLog* net_log)
527 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
528 change_callback_(callback),
529 config_(config),
530 proxy_resolver_expects_pac_bytes_(proxy_resolver_expects_pac_bytes),
531 proxy_script_fetcher_(proxy_script_fetcher),
532 dhcp_proxy_script_fetcher_(dhcp_proxy_script_fetcher),
533 last_error_(init_net_error),
534 last_script_data_(init_script_data) {
535 // Set the initial poll delay -- we check more aggressively right after a
536 // failure in case it was due to a spurious network error.
537 current_poll_delay_ms_ = GetInitialWaitDelayMs(init_net_error);
538
539 StartPollTimer();
540 }
541
542 // ----------------------------------
543 // Policy for the retry scheduling.
544 // ----------------------------------
545
546 static int64 GetInitialWaitDelayMs(int error) {
547 switch (poll_policy_) {
548 case POLL_POLICY_REGULAR:
549 // Use a shorter wait delay if the initial fetch resulted in an error.
550 return (error != OK) ?
551 kInitialPollDelayForErrorMs : kInitialPollDelayForSuccessMs;
552 case POLL_POLICY_IMMEDIATE:
553 // Wait a mere 1 millisecond.
554 return 1;
555 case POLL_POLICY_NEVER:
556 // Unreasonably large wait delay, will never fire the check.
557 return 0xFFFFFFFF;
558 }
559
560 // Shouldn't be reached
561 return -1;
562 }
563
564 static int64 GetNextWaitDelayMs(int64 current_delay_ms) {
565 switch (poll_policy_) {
566 case POLL_POLICY_REGULAR:
567 // Increase the delay exponentially up to 2 minutes.
568 return std::min(current_delay_ms * 2, kMaxPollDelayMs);
569 case POLL_POLICY_IMMEDIATE:
570 case POLL_POLICY_NEVER:
571 return current_delay_ms;
572 }
573
574 // Shouldn't be reached
575 return -1;
576 }
577
578 static PollPolicy set_policy(PollPolicy policy) {
579 PollPolicy prev = poll_policy_;
580 poll_policy_ = policy;
581 return prev;
582 }
583
584 private:
585 void StartPollTimer() {
586 DCHECK(!decider_.get());
587
588 MessageLoop::current()->PostDelayedTask(
589 FROM_HERE,
590 base::Bind(&ProxyScriptDeciderPoller::OnPollTimerFired,
591 weak_factory_.GetWeakPtr()),
592 current_poll_delay_ms_);
593 }
594
595 void OnPollTimerFired() {
596 // Start the proxy script decider to see if anything has changed.
597 // TODO(eroman): Pass a proper NetLog rather than NULL.
598 decider_.reset(new ProxyScriptDecider(
599 proxy_script_fetcher_, dhcp_proxy_script_fetcher_, NULL));
600 int result = decider_->Start(
601 config_, base::TimeDelta(), proxy_resolver_expects_pac_bytes_,
602 base::Bind(&ProxyScriptDeciderPoller::OnProxyScriptDeciderCompleted,
603 base::Unretained(this)));
604
605 if (result != ERR_IO_PENDING)
606 OnProxyScriptDeciderCompleted(result);
607 }
608
609 void OnProxyScriptDeciderCompleted(int result) {
610 if (HasScriptDataChanged(result, decider_->script_data())) {
611 // Something has changed, we must notify the ProxyService so it can
612 // re-initialize its ProxyResolver. Note that we post a notification task
613 // rather than calling it directly -- this is done to avoid an ugly
614 // destruction sequence, since |this| might be destroyed as a result of
615 // the notification.
616 MessageLoop::current()->PostTask(
617 FROM_HERE,
618 base::Bind(
619 &ProxyScriptDeciderPoller::NotifyProxyServiceOfChange,
620 weak_factory_.GetWeakPtr(),
621 result,
622 make_scoped_refptr(decider_->script_data()),
623 decider_->effective_config()));
624 return;
625 }
626
627 decider_.reset();
628
629 // Schedule the next poll check.
630 current_poll_delay_ms_ = GetNextWaitDelayMs(current_poll_delay_ms_);
631 StartPollTimer();
632 }
633
634 bool HasScriptDataChanged(int result, ProxyResolverScriptData* script_data) {
635 if (result != last_error_) {
636 // Something changed -- it was failing before and now it succeeded, or
637 // conversely it succeeded before and now it failed. Or it failed in
638 // both cases, however the specific failure error codes differ.
639 return true;
640 }
641
642 if (result != OK) {
643 // If it failed last time and failed again with the same error code this
644 // time, then nothing has actually changed.
645 return false;
646 }
647
648 // Otherwise if it succeeded both this time and last time, we need to look
649 // closer and see if we ended up downloading different content for the PAC
650 // script.
651 return !script_data->Equals(last_script_data_);
652 }
653
654 void NotifyProxyServiceOfChange(
655 int result,
656 const scoped_refptr<ProxyResolverScriptData>& script_data,
657 const ProxyConfig& effective_config) {
658 // Note that |this| may be deleted after calling into the ProxyService.
659 change_callback_.Run(result, script_data, effective_config);
660 }
661
662 base::WeakPtrFactory<ProxyScriptDeciderPoller> weak_factory_;
663
664 ChangeCallback change_callback_;
665 ProxyConfig config_;
666 bool proxy_resolver_expects_pac_bytes_;
667 ProxyScriptFetcher* proxy_script_fetcher_;
668 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher_;
669
670 int last_error_;
671 scoped_refptr<ProxyResolverScriptData> last_script_data_;
672
673 scoped_ptr<ProxyScriptDecider> decider_;
674 int64 current_poll_delay_ms_;
675
676 static PollPolicy poll_policy_;
677
678 DISALLOW_COPY_AND_ASSIGN(ProxyScriptDeciderPoller);
679 };
680
681 // static
682 ProxyService::PollPolicy ProxyService::ProxyScriptDeciderPoller::poll_policy_ =
683 ProxyService::POLL_POLICY_REGULAR;
684
453 // ProxyService::PacRequest --------------------------------------------------- 685 // ProxyService::PacRequest ---------------------------------------------------
454 686
455 class ProxyService::PacRequest 687 class ProxyService::PacRequest
456 : public base::RefCounted<ProxyService::PacRequest> { 688 : public base::RefCounted<ProxyService::PacRequest> {
457 public: 689 public:
458 PacRequest(ProxyService* service, 690 PacRequest(ProxyService* service,
459 const GURL& url, 691 const GURL& url,
460 ProxyInfo* results, 692 ProxyInfo* results,
461 const net::CompletionCallback& user_callback, 693 const net::CompletionCallback& user_callback,
462 const BoundNetLog& net_log) 694 const BoundNetLog& net_log)
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 817
586 ProxyService::ProxyService(ProxyConfigService* config_service, 818 ProxyService::ProxyService(ProxyConfigService* config_service,
587 ProxyResolver* resolver, 819 ProxyResolver* resolver,
588 NetLog* net_log) 820 NetLog* net_log)
589 : resolver_(resolver), 821 : resolver_(resolver),
590 next_config_id_(1), 822 next_config_id_(1),
591 current_state_(STATE_NONE) , 823 current_state_(STATE_NONE) ,
592 net_log_(net_log), 824 net_log_(net_log),
593 stall_proxy_auto_config_delay_( 825 stall_proxy_auto_config_delay_(
594 base::TimeDelta::FromMilliseconds( 826 base::TimeDelta::FromMilliseconds(
595 kNumMillisToStallAfterNetworkChanges)) { 827 kDelayAfterNetworkChangesMs)) {
596 NetworkChangeNotifier::AddIPAddressObserver(this); 828 NetworkChangeNotifier::AddIPAddressObserver(this);
597 ResetConfigService(config_service); 829 ResetConfigService(config_service);
598 } 830 }
599 831
600 // static 832 // static
601 ProxyService* ProxyService::CreateUsingV8ProxyResolver( 833 ProxyService* ProxyService::CreateUsingV8ProxyResolver(
602 ProxyConfigService* proxy_config_service, 834 ProxyConfigService* proxy_config_service,
603 size_t num_pac_threads, 835 size_t num_pac_threads,
604 ProxyScriptFetcher* proxy_script_fetcher, 836 ProxyScriptFetcher* proxy_script_fetcher,
605 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher, 837 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher,
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 ProxyConfigService::ConfigAvailability availability = 1083 ProxyConfigService::ConfigAvailability availability =
852 config_service_->GetLatestProxyConfig(&config); 1084 config_service_->GetLatestProxyConfig(&config);
853 if (availability != ProxyConfigService::CONFIG_PENDING) 1085 if (availability != ProxyConfigService::CONFIG_PENDING)
854 OnProxyConfigChanged(config, availability); 1086 OnProxyConfigChanged(config, availability);
855 } 1087 }
856 1088
857 void ProxyService::OnInitProxyResolverComplete(int result) { 1089 void ProxyService::OnInitProxyResolverComplete(int result) {
858 DCHECK_EQ(STATE_WAITING_FOR_INIT_PROXY_RESOLVER, current_state_); 1090 DCHECK_EQ(STATE_WAITING_FOR_INIT_PROXY_RESOLVER, current_state_);
859 DCHECK(init_proxy_resolver_.get()); 1091 DCHECK(init_proxy_resolver_.get());
860 DCHECK(fetched_config_.HasAutomaticSettings()); 1092 DCHECK(fetched_config_.HasAutomaticSettings());
1093 config_ = init_proxy_resolver_->effective_config();
1094
1095 // At this point we have decided which proxy settings to use (i.e. which PAC
1096 // script if any). We start up a background poller to periodically revisit
1097 // this decision. If the contents of the PAC script change, or if the
1098 // result of proxy auto-discovery changes, this poller will notice it and
1099 // will trigger a re-initialization using the newly discovered PAC.
1100 script_poller_.reset(new ProxyScriptDeciderPoller(
1101 base::Bind(&ProxyService::InitializeUsingDecidedConfig,
1102 base::Unretained(this)),
1103 fetched_config_,
1104 resolver_->expects_pac_bytes(),
1105 proxy_script_fetcher_.get(),
1106 dhcp_proxy_script_fetcher_.get(),
1107 result,
1108 init_proxy_resolver_->script_data(),
1109 NULL));
1110
861 init_proxy_resolver_.reset(); 1111 init_proxy_resolver_.reset();
862 1112
863 if (result != OK) { 1113 if (result != OK) {
864 if (fetched_config_.pac_mandatory()) { 1114 if (fetched_config_.pac_mandatory()) {
865 VLOG(1) << "Failed configuring with mandatory PAC script, blocking all " 1115 VLOG(1) << "Failed configuring with mandatory PAC script, blocking all "
866 "traffic."; 1116 "traffic.";
867 config_ = fetched_config_; 1117 config_ = fetched_config_;
868 result = ERR_MANDATORY_PROXY_CONFIGURATION_FAILED; 1118 result = ERR_MANDATORY_PROXY_CONFIGURATION_FAILED;
869 } else { 1119 } else {
870 VLOG(1) << "Failed configuring with PAC script, falling-back to manual " 1120 VLOG(1) << "Failed configuring with PAC script, falling-back to manual "
871 "proxy servers."; 1121 "proxy servers.";
872 config_ = fetched_config_; 1122 config_ = fetched_config_;
873 config_.ClearAutomaticSettings(); 1123 config_.ClearAutomaticSettings();
874 result = OK; 1124 result = OK;
875 } 1125 }
876 } 1126 }
877 permanent_error_ = result; 1127 permanent_error_ = result;
878 1128
1129 // TODO(eroman): Make this ID unique in the case where configuration changed
1130 // due to ProxyScriptDeciderPoller.
879 config_.set_id(fetched_config_.id()); 1131 config_.set_id(fetched_config_.id());
880 1132
881 // Resume any requests which we had to defer until the PAC script was 1133 // Resume any requests which we had to defer until the PAC script was
882 // downloaded. 1134 // downloaded.
883 SetReady(); 1135 SetReady();
884 } 1136 }
885 1137
886 int ProxyService::ReconsiderProxyAfterError(const GURL& url, 1138 int ProxyService::ReconsiderProxyAfterError(const GURL& url,
887 ProxyInfo* result, 1139 ProxyInfo* result,
888 const CompletionCallback& callback, 1140 const CompletionCallback& callback,
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1015 DCHECK(CalledOnValidThread()); 1267 DCHECK(CalledOnValidThread());
1016 return proxy_script_fetcher_.get(); 1268 return proxy_script_fetcher_.get();
1017 } 1269 }
1018 1270
1019 ProxyService::State ProxyService::ResetProxyConfig(bool reset_fetched_config) { 1271 ProxyService::State ProxyService::ResetProxyConfig(bool reset_fetched_config) {
1020 DCHECK(CalledOnValidThread()); 1272 DCHECK(CalledOnValidThread());
1021 State previous_state = current_state_; 1273 State previous_state = current_state_;
1022 1274
1023 permanent_error_ = OK; 1275 permanent_error_ = OK;
1024 proxy_retry_info_.clear(); 1276 proxy_retry_info_.clear();
1277 script_poller_.reset();
1025 init_proxy_resolver_.reset(); 1278 init_proxy_resolver_.reset();
1026 SuspendAllPendingRequests(); 1279 SuspendAllPendingRequests();
1027 config_ = ProxyConfig(); 1280 config_ = ProxyConfig();
1028 if (reset_fetched_config) 1281 if (reset_fetched_config)
1029 fetched_config_ = ProxyConfig(); 1282 fetched_config_ = ProxyConfig();
1030 current_state_ = STATE_NONE; 1283 current_state_ = STATE_NONE;
1031 1284
1032 return previous_state; 1285 return previous_state;
1033 } 1286 }
1034 1287
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1092 static_cast<MessageLoopForIO*>(file_loop)); 1345 static_cast<MessageLoopForIO*>(file_loop));
1093 1346
1094 return linux_config_service; 1347 return linux_config_service;
1095 #else 1348 #else
1096 LOG(WARNING) << "Failed to choose a system proxy settings fetcher " 1349 LOG(WARNING) << "Failed to choose a system proxy settings fetcher "
1097 "for this platform."; 1350 "for this platform.";
1098 return new ProxyConfigServiceDirect(); 1351 return new ProxyConfigServiceDirect();
1099 #endif 1352 #endif
1100 } 1353 }
1101 1354
1355 // static
1356 ProxyService::PollPolicy ProxyService::set_pac_script_poll_policy(
1357 PollPolicy policy) {
1358 return ProxyScriptDeciderPoller::set_policy(policy);
1359 }
1360
1102 void ProxyService::OnProxyConfigChanged( 1361 void ProxyService::OnProxyConfigChanged(
1103 const ProxyConfig& config, 1362 const ProxyConfig& config,
1104 ProxyConfigService::ConfigAvailability availability) { 1363 ProxyConfigService::ConfigAvailability availability) {
1105 // Retrieve the current proxy configuration from the ProxyConfigService. 1364 // Retrieve the current proxy configuration from the ProxyConfigService.
1106 // If a configuration is not available yet, we will get called back later 1365 // If a configuration is not available yet, we will get called back later
1107 // by our ProxyConfigService::Observer once it changes. 1366 // by our ProxyConfigService::Observer once it changes.
1108 ProxyConfig effective_config; 1367 ProxyConfig effective_config;
1109 switch (availability) { 1368 switch (availability) {
1110 case ProxyConfigService::CONFIG_PENDING: 1369 case ProxyConfigService::CONFIG_PENDING:
1111 // ProxyConfigService implementors should never pass CONFIG_PENDING. 1370 // ProxyConfigService implementors should never pass CONFIG_PENDING.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1147 1406
1148 if (!fetched_config_.HasAutomaticSettings()) { 1407 if (!fetched_config_.HasAutomaticSettings()) {
1149 config_ = fetched_config_; 1408 config_ = fetched_config_;
1150 SetReady(); 1409 SetReady();
1151 return; 1410 return;
1152 } 1411 }
1153 1412
1154 // Start downloading + testing the PAC scripts for this new configuration. 1413 // Start downloading + testing the PAC scripts for this new configuration.
1155 current_state_ = STATE_WAITING_FOR_INIT_PROXY_RESOLVER; 1414 current_state_ = STATE_WAITING_FOR_INIT_PROXY_RESOLVER;
1156 1415
1157 init_proxy_resolver_.reset(
1158 new InitProxyResolver(resolver_.get(),
1159 proxy_script_fetcher_.get(),
1160 dhcp_proxy_script_fetcher_.get(),
1161 net_log_));
1162
1163 // If we changed networks recently, we should delay running proxy auto-config. 1416 // If we changed networks recently, we should delay running proxy auto-config.
1164 base::TimeDelta wait_delay = 1417 base::TimeDelta wait_delay =
1165 stall_proxy_autoconfig_until_ - base::TimeTicks::Now(); 1418 stall_proxy_autoconfig_until_ - base::TimeTicks::Now();
1166 1419
1167 int rv = init_proxy_resolver_->Init( 1420 init_proxy_resolver_.reset(new InitProxyResolver());
1168 fetched_config_, wait_delay, &config_, 1421 int rv = init_proxy_resolver_->Start(
1422 resolver_.get(),
1423 proxy_script_fetcher_.get(),
1424 dhcp_proxy_script_fetcher_.get(),
1425 net_log_,
1426 fetched_config_,
1427 wait_delay,
1169 base::Bind(&ProxyService::OnInitProxyResolverComplete, 1428 base::Bind(&ProxyService::OnInitProxyResolverComplete,
1170 base::Unretained(this))); 1429 base::Unretained(this)));
1171 1430
1431 if (rv != ERR_IO_PENDING)
1432 OnInitProxyResolverComplete(rv);
1433 }
1434
1435 void ProxyService::InitializeUsingDecidedConfig(
1436 int decider_result,
1437 ProxyResolverScriptData* script_data,
1438 const ProxyConfig& effective_config) {
1439 DCHECK(fetched_config_.is_valid());
1440 DCHECK(fetched_config_.HasAutomaticSettings());
1441
1442 ResetProxyConfig(false);
1443
1444 current_state_ = STATE_WAITING_FOR_INIT_PROXY_RESOLVER;
1445
1446 init_proxy_resolver_.reset(new InitProxyResolver());
1447 int rv = init_proxy_resolver_->StartSkipDecider(
1448 resolver_.get(),
1449 effective_config,
1450 decider_result,
1451 script_data,
1452 base::Bind(&ProxyService::OnInitProxyResolverComplete,
1453 base::Unretained(this)));
1454
1172 if (rv != ERR_IO_PENDING) 1455 if (rv != ERR_IO_PENDING)
1173 OnInitProxyResolverComplete(rv); 1456 OnInitProxyResolverComplete(rv);
1174 } 1457 }
1175 1458
1176 void ProxyService::OnIPAddressChanged() { 1459 void ProxyService::OnIPAddressChanged() {
1177 // See the comment block by |kNumMillisToStallAfterNetworkChanges| for info. 1460 // See the comment block by |kDelayAfterNetworkChangesMs| for info.
1178 stall_proxy_autoconfig_until_ = 1461 stall_proxy_autoconfig_until_ =
1179 base::TimeTicks::Now() + stall_proxy_auto_config_delay_; 1462 base::TimeTicks::Now() + stall_proxy_auto_config_delay_;
1180 1463
1181 State previous_state = ResetProxyConfig(false); 1464 State previous_state = ResetProxyConfig(false);
1182 if (previous_state != STATE_NONE) 1465 if (previous_state != STATE_NONE)
1183 ApplyProxyConfigIfAvailable(); 1466 ApplyProxyConfigIfAvailable();
1184 } 1467 }
1185 1468
1186 SyncProxyServiceHelper::SyncProxyServiceHelper(MessageLoop* io_message_loop, 1469 SyncProxyServiceHelper::SyncProxyServiceHelper(MessageLoop* io_message_loop,
1187 ProxyService* proxy_service) 1470 ProxyService* proxy_service)
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1248 OnCompletion(result_); 1531 OnCompletion(result_);
1249 } 1532 }
1250 } 1533 }
1251 1534
1252 void SyncProxyServiceHelper::OnCompletion(int rv) { 1535 void SyncProxyServiceHelper::OnCompletion(int rv) {
1253 result_ = rv; 1536 result_ = rv;
1254 event_.Signal(); 1537 event_.Signal();
1255 } 1538 }
1256 1539
1257 } // namespace net 1540 } // 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