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

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

Issue 9139070: Don't poll the PAC script during periods of network inactivity. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: address wtc comments 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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"
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 // set up. Network failures can happen at any time though, so we additionally 70 // set up. Network failures can happen at any time though, so we additionally
71 // poll the PAC script for changes, which will allow us to recover from these 71 // poll the PAC script for changes, which will allow us to recover from these
72 // sorts of problems. 72 // sorts of problems.
73 const int64 kDelayAfterNetworkChangesMs = 2000; 73 const int64 kDelayAfterNetworkChangesMs = 2000;
74 74
75 // The initial number of milliseconds to wait before refetching PAC script after 75 // The initial number of milliseconds to wait before refetching PAC script after
76 // a fetch error/success. 76 // a fetch error/success.
77 const int64 kInitialPollDelayForErrorMs = 4000; 77 const int64 kInitialPollDelayForErrorMs = 4000;
78 const int64 kInitialPollDelayForSuccessMs = 16000; 78 const int64 kInitialPollDelayForSuccessMs = 16000;
79 79
80 // Once the poll delay becomes larger than this, we will stop scheduling using
81 // a timer, and instead wait for an incoming request to trigger the poll.
82 const int64 kMaxPollDelayUsingTimer = 16000;
83
80 // The maximum poll delay for checking PAC scripts. 84 // The maximum poll delay for checking PAC scripts.
81 const int64 kMaxPollDelayMs = 120000; // 2 minutes. 85 const int64 kMaxPollDelayMs = 120000; // 2 minutes.
82 86
87 // This is the default policy for polling the PAC script. Checks happen after an
88 // exponentially increasing delay. The first couple checks will be scheduled
89 // using a timer. After that the checks will only be done lazily in response to
90 // a user request.
91 class DefaultPollPolicy : public ProxyService::PacPollPolicy {
92 public:
93 DefaultPollPolicy() {}
94
95 virtual Mode GetInitialDelay(int error, int64* next_delay_ms) const OVERRIDE {
96 // Use a shorter wait delay if the initial fetch resulted in an error.
97 *next_delay_ms = (error != OK) ?
98 kInitialPollDelayForErrorMs : kInitialPollDelayForSuccessMs;
99 return MODE_USE_TIMER;
100 }
101
102 virtual Mode GetNextDelay(int64 current_delay_ms,
103 int64* next_delay_ms) const OVERRIDE {
104 // Increase the wait delay exponentially up to a maximum.
105 *next_delay_ms = std::min(current_delay_ms * 2, kMaxPollDelayMs);
106
107 // Once the delays are large enough, stop scheduling using a timer and
108 // instead only poll during periods of activity.
109 return (*next_delay_ms <= kMaxPollDelayUsingTimer) ?
110 MODE_USE_TIMER: MODE_START_AFTER_ACTIVITY;
111 }
112
113 private:
114 DISALLOW_COPY_AND_ASSIGN(DefaultPollPolicy);
115 };
116
83 // Config getter that always returns direct settings. 117 // Config getter that always returns direct settings.
84 class ProxyConfigServiceDirect : public ProxyConfigService { 118 class ProxyConfigServiceDirect : public ProxyConfigService {
85 public: 119 public:
86 // ProxyConfigService implementation: 120 // ProxyConfigService implementation:
87 virtual void AddObserver(Observer* observer) OVERRIDE {} 121 virtual void AddObserver(Observer* observer) OVERRIDE {}
88 virtual void RemoveObserver(Observer* observer) OVERRIDE {} 122 virtual void RemoveObserver(Observer* observer) OVERRIDE {}
89 virtual ConfigAvailability GetLatestProxyConfig(ProxyConfig* config) 123 virtual ConfigAvailability GetLatestProxyConfig(ProxyConfig* config)
90 OVERRIDE { 124 OVERRIDE {
91 *config = ProxyConfig::CreateDirect(); 125 *config = ProxyConfig::CreateDirect();
92 return CONFIG_VALID; 126 return CONFIG_VALID;
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 int init_net_error, 558 int init_net_error,
525 ProxyResolverScriptData* init_script_data, 559 ProxyResolverScriptData* init_script_data,
526 NetLog* net_log) 560 NetLog* net_log)
527 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), 561 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
528 change_callback_(callback), 562 change_callback_(callback),
529 config_(config), 563 config_(config),
530 proxy_resolver_expects_pac_bytes_(proxy_resolver_expects_pac_bytes), 564 proxy_resolver_expects_pac_bytes_(proxy_resolver_expects_pac_bytes),
531 proxy_script_fetcher_(proxy_script_fetcher), 565 proxy_script_fetcher_(proxy_script_fetcher),
532 dhcp_proxy_script_fetcher_(dhcp_proxy_script_fetcher), 566 dhcp_proxy_script_fetcher_(dhcp_proxy_script_fetcher),
533 last_error_(init_net_error), 567 last_error_(init_net_error),
534 last_script_data_(init_script_data) { 568 last_script_data_(init_script_data),
569 last_poll_time_(base::TimeTicks::Now()) {
535 // Set the initial poll delay -- we check more aggressively right after a 570 // Set the initial poll delay -- we check more aggressively right after a
536 // failure in case it was due to a spurious network error. 571 // failure in case it was due to a spurious network error.
537 current_poll_delay_ms_ = GetInitialWaitDelayMs(init_net_error); 572 next_poll_mode_ = poll_policy()->GetInitialDelay(
538 573 init_net_error, &next_poll_delay_ms_);
539 StartPollTimer(); 574 TryToStartNextPoll(false);
540 } 575 }
541 576
542 // ---------------------------------- 577 void OnLazyPoll() {
543 // Policy for the retry scheduling. 578 // We have just been notified of network activity. Use this opportunity to
544 // ---------------------------------- 579 // see if we can start our next poll.
545 580 TryToStartNextPoll(true);
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 } 581 }
563 582
564 static int64 GetNextWaitDelayMs(int64 current_delay_ms) { 583 static const PacPollPolicy* set_policy(const PacPollPolicy* policy) {
565 switch (poll_policy_) { 584 const PacPollPolicy* prev = 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; 585 poll_policy_ = policy;
581 return prev; 586 return prev;
582 } 587 }
583 588
584 private: 589 private:
590 // Returns the effective poll policy (the one injected by unit-tests, or the
591 // default).
592 const PacPollPolicy* poll_policy() {
593 if (poll_policy_)
594 return poll_policy_;
595 return &default_poll_policy_;
596 }
597
585 void StartPollTimer() { 598 void StartPollTimer() {
586 DCHECK(!decider_.get()); 599 DCHECK(!decider_.get());
587 600
588 MessageLoop::current()->PostDelayedTask( 601 MessageLoop::current()->PostDelayedTask(
589 FROM_HERE, 602 FROM_HERE,
590 base::Bind(&ProxyScriptDeciderPoller::OnPollTimerFired, 603 base::Bind(&ProxyScriptDeciderPoller::DoPoll,
591 weak_factory_.GetWeakPtr()), 604 weak_factory_.GetWeakPtr()),
592 current_poll_delay_ms_); 605 next_poll_delay_ms_);
593 } 606 }
594 607
595 void OnPollTimerFired() { 608 void TryToStartNextPoll(bool triggered_by_activity) {
609 switch (next_poll_mode_) {
610 case PacPollPolicy::MODE_USE_TIMER:
611 if (!triggered_by_activity)
612 StartPollTimer();
613 break;
614
615 case PacPollPolicy::MODE_START_AFTER_ACTIVITY:
616 if (triggered_by_activity && !decider_.get()) {
617 base::TimeDelta elapsed_time =
618 base::TimeTicks::Now() - last_poll_time_;
619 if (elapsed_time.InMilliseconds() >= next_poll_delay_ms_)
620 DoPoll();
621 }
622 break;
623 }
624 }
625
626 void DoPoll() {
627 last_poll_time_ = base::TimeTicks::Now();
628
596 // Start the proxy script decider to see if anything has changed. 629 // Start the proxy script decider to see if anything has changed.
597 // TODO(eroman): Pass a proper NetLog rather than NULL. 630 // TODO(eroman): Pass a proper NetLog rather than NULL.
598 decider_.reset(new ProxyScriptDecider( 631 decider_.reset(new ProxyScriptDecider(
599 proxy_script_fetcher_, dhcp_proxy_script_fetcher_, NULL)); 632 proxy_script_fetcher_, dhcp_proxy_script_fetcher_, NULL));
600 int result = decider_->Start( 633 int result = decider_->Start(
601 config_, base::TimeDelta(), proxy_resolver_expects_pac_bytes_, 634 config_, base::TimeDelta(), proxy_resolver_expects_pac_bytes_,
602 base::Bind(&ProxyScriptDeciderPoller::OnProxyScriptDeciderCompleted, 635 base::Bind(&ProxyScriptDeciderPoller::OnProxyScriptDeciderCompleted,
603 base::Unretained(this))); 636 base::Unretained(this)));
604 637
605 if (result != ERR_IO_PENDING) 638 if (result != ERR_IO_PENDING)
(...skipping 13 matching lines...) Expand all
619 &ProxyScriptDeciderPoller::NotifyProxyServiceOfChange, 652 &ProxyScriptDeciderPoller::NotifyProxyServiceOfChange,
620 weak_factory_.GetWeakPtr(), 653 weak_factory_.GetWeakPtr(),
621 result, 654 result,
622 make_scoped_refptr(decider_->script_data()), 655 make_scoped_refptr(decider_->script_data()),
623 decider_->effective_config())); 656 decider_->effective_config()));
624 return; 657 return;
625 } 658 }
626 659
627 decider_.reset(); 660 decider_.reset();
628 661
629 // Schedule the next poll check. 662 // Decide when the next poll should take place, and possibly start the
630 current_poll_delay_ms_ = GetNextWaitDelayMs(current_poll_delay_ms_); 663 // next timer.
631 StartPollTimer(); 664 next_poll_mode_ =
665 poll_policy()->GetNextDelay(next_poll_delay_ms_, &next_poll_delay_ms_);
666 TryToStartNextPoll(false);
632 } 667 }
633 668
634 bool HasScriptDataChanged(int result, ProxyResolverScriptData* script_data) { 669 bool HasScriptDataChanged(int result, ProxyResolverScriptData* script_data) {
635 if (result != last_error_) { 670 if (result != last_error_) {
636 // Something changed -- it was failing before and now it succeeded, or 671 // Something changed -- it was failing before and now it succeeded, or
637 // conversely it succeeded before and now it failed. Or it failed in 672 // conversely it succeeded before and now it failed. Or it failed in
638 // both cases, however the specific failure error codes differ. 673 // both cases, however the specific failure error codes differ.
639 return true; 674 return true;
640 } 675 }
641 676
(...skipping 22 matching lines...) Expand all
664 ChangeCallback change_callback_; 699 ChangeCallback change_callback_;
665 ProxyConfig config_; 700 ProxyConfig config_;
666 bool proxy_resolver_expects_pac_bytes_; 701 bool proxy_resolver_expects_pac_bytes_;
667 ProxyScriptFetcher* proxy_script_fetcher_; 702 ProxyScriptFetcher* proxy_script_fetcher_;
668 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher_; 703 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher_;
669 704
670 int last_error_; 705 int last_error_;
671 scoped_refptr<ProxyResolverScriptData> last_script_data_; 706 scoped_refptr<ProxyResolverScriptData> last_script_data_;
672 707
673 scoped_ptr<ProxyScriptDecider> decider_; 708 scoped_ptr<ProxyScriptDecider> decider_;
674 int64 current_poll_delay_ms_; 709 int64 next_poll_delay_ms_;
710 PacPollPolicy::Mode next_poll_mode_;
675 711
676 static PollPolicy poll_policy_; 712 base::TimeTicks last_poll_time_;
713
714 // Polling policy injected by unit-tests. Otherwise this is NULL and the
715 // default policy will be used.
716 static const PacPollPolicy* poll_policy_;
717
718 const DefaultPollPolicy default_poll_policy_;
677 719
678 DISALLOW_COPY_AND_ASSIGN(ProxyScriptDeciderPoller); 720 DISALLOW_COPY_AND_ASSIGN(ProxyScriptDeciderPoller);
679 }; 721 };
680 722
681 // static 723 // static
682 ProxyService::PollPolicy ProxyService::ProxyScriptDeciderPoller::poll_policy_ = 724 const ProxyService::PacPollPolicy*
683 ProxyService::POLL_POLICY_REGULAR; 725 ProxyService::ProxyScriptDeciderPoller::poll_policy_ = NULL;
684 726
685 // ProxyService::PacRequest --------------------------------------------------- 727 // ProxyService::PacRequest ---------------------------------------------------
686 728
687 class ProxyService::PacRequest 729 class ProxyService::PacRequest
688 : public base::RefCounted<ProxyService::PacRequest> { 730 : public base::RefCounted<ProxyService::PacRequest> {
689 public: 731 public:
690 PacRequest(ProxyService* service, 732 PacRequest(ProxyService* service,
691 const GURL& url, 733 const GURL& url,
692 ProxyInfo* results, 734 ProxyInfo* results,
693 const net::CompletionCallback& user_callback, 735 const net::CompletionCallback& user_callback,
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
944 int ProxyService::ResolveProxy(const GURL& raw_url, 986 int ProxyService::ResolveProxy(const GURL& raw_url,
945 ProxyInfo* result, 987 ProxyInfo* result,
946 const net::CompletionCallback& callback, 988 const net::CompletionCallback& callback,
947 PacRequest** pac_request, 989 PacRequest** pac_request,
948 const BoundNetLog& net_log) { 990 const BoundNetLog& net_log) {
949 DCHECK(CalledOnValidThread()); 991 DCHECK(CalledOnValidThread());
950 DCHECK(!callback.is_null()); 992 DCHECK(!callback.is_null());
951 993
952 net_log.BeginEvent(NetLog::TYPE_PROXY_SERVICE, NULL); 994 net_log.BeginEvent(NetLog::TYPE_PROXY_SERVICE, NULL);
953 995
996 // Notify our polling-based dependencies that a resolve is taking place.
997 // This way they can schedule their polls in response to network activity.
954 config_service_->OnLazyPoll(); 998 config_service_->OnLazyPoll();
999 if (script_poller_.get())
1000 script_poller_->OnLazyPoll();
1001
955 if (current_state_ == STATE_NONE) 1002 if (current_state_ == STATE_NONE)
956 ApplyProxyConfigIfAvailable(); 1003 ApplyProxyConfigIfAvailable();
957 1004
958 // Strip away any reference fragments and the username/password, as they 1005 // Strip away any reference fragments and the username/password, as they
959 // are not relevant to proxy resolution. 1006 // are not relevant to proxy resolution.
960 GURL url = SimplifyUrlForRequest(raw_url); 1007 GURL url = SimplifyUrlForRequest(raw_url);
961 1008
962 // Check if the request can be completed right away. (This is the case when 1009 // Check if the request can be completed right away. (This is the case when
963 // using a direct connection for example). 1010 // using a direct connection for example).
964 int rv = TryToCompleteSynchronously(url, result); 1011 int rv = TryToCompleteSynchronously(url, result);
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
1346 1393
1347 return linux_config_service; 1394 return linux_config_service;
1348 #else 1395 #else
1349 LOG(WARNING) << "Failed to choose a system proxy settings fetcher " 1396 LOG(WARNING) << "Failed to choose a system proxy settings fetcher "
1350 "for this platform."; 1397 "for this platform.";
1351 return new ProxyConfigServiceDirect(); 1398 return new ProxyConfigServiceDirect();
1352 #endif 1399 #endif
1353 } 1400 }
1354 1401
1355 // static 1402 // static
1356 ProxyService::PollPolicy ProxyService::set_pac_script_poll_policy( 1403 const ProxyService::PacPollPolicy* ProxyService::set_pac_script_poll_policy(
1357 PollPolicy policy) { 1404 const PacPollPolicy* policy) {
1358 return ProxyScriptDeciderPoller::set_policy(policy); 1405 return ProxyScriptDeciderPoller::set_policy(policy);
1359 } 1406 }
1360 1407
1408 // static
1409 scoped_ptr<ProxyService::PacPollPolicy>
1410 ProxyService::CreateDefaultPacPollPolicy() {
1411 return scoped_ptr<PacPollPolicy>(new DefaultPollPolicy());
1412 }
1413
1361 void ProxyService::OnProxyConfigChanged( 1414 void ProxyService::OnProxyConfigChanged(
1362 const ProxyConfig& config, 1415 const ProxyConfig& config,
1363 ProxyConfigService::ConfigAvailability availability) { 1416 ProxyConfigService::ConfigAvailability availability) {
1364 // Retrieve the current proxy configuration from the ProxyConfigService. 1417 // Retrieve the current proxy configuration from the ProxyConfigService.
1365 // If a configuration is not available yet, we will get called back later 1418 // If a configuration is not available yet, we will get called back later
1366 // by our ProxyConfigService::Observer once it changes. 1419 // by our ProxyConfigService::Observer once it changes.
1367 ProxyConfig effective_config; 1420 ProxyConfig effective_config;
1368 switch (availability) { 1421 switch (availability) {
1369 case ProxyConfigService::CONFIG_PENDING: 1422 case ProxyConfigService::CONFIG_PENDING:
1370 // ProxyConfigService implementors should never pass CONFIG_PENDING. 1423 // ProxyConfigService implementors should never pass CONFIG_PENDING.
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1531 OnCompletion(result_); 1584 OnCompletion(result_);
1532 } 1585 }
1533 } 1586 }
1534 1587
1535 void SyncProxyServiceHelper::OnCompletion(int rv) { 1588 void SyncProxyServiceHelper::OnCompletion(int rv) {
1536 result_ = rv; 1589 result_ = rv;
1537 event_.Signal(); 1590 event_.Signal();
1538 } 1591 }
1539 1592
1540 } // namespace net 1593 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698