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

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: remove static since it was causing an AtExit destructor 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 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 return dict; 333 return dict;
300 } 334 }
301 335
302 private: 336 private:
303 std::vector<std::string> proxy_list_; 337 std::vector<std::string> proxy_list_;
304 DISALLOW_COPY_AND_ASSIGN(BadProxyListNetLogParam); 338 DISALLOW_COPY_AND_ASSIGN(BadProxyListNetLogParam);
305 }; 339 };
306 340
307 } // namespace 341 } // namespace
308 342
343 // ProxyService::PacPollPolicy ------------------------------------------------
344
345 ProxyService::PacPollPolicy::~PacPollPolicy() {}
wtc 2012/01/13 01:08:45 Nit: why can't this destructor be defined in the h
eroman 2012/01/13 01:29:10 @erg has gone to a lot of effort to remove code fr
eroman 2012/01/13 20:05:27 Done.
346
309 // ProxyService::InitProxyResolver -------------------------------------------- 347 // ProxyService::InitProxyResolver --------------------------------------------
310 348
311 // This glues together two asynchronous steps: 349 // This glues together two asynchronous steps:
312 // (1) ProxyScriptDecider -- try to fetch/validate a sequence of PAC scripts t o 350 // (1) ProxyScriptDecider -- try to fetch/validate a sequence of PAC scripts t o
313 // figure out what we should configure against. 351 // figure out what we should configure against.
314 // (2) Feed the fetched PAC script into the ProxyResolver. 352 // (2) Feed the fetched PAC script into the ProxyResolver.
315 // 353 //
316 // InitProxyResolver is a single-use class which encapsulates cancellation as 354 // InitProxyResolver is a single-use class which encapsulates cancellation as
317 // part of its destructor. Start() or StartSkipDecider() should be called just 355 // 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 356 // once. The instance can be destroyed at any time, and the request will be
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 int init_net_error, 562 int init_net_error,
525 ProxyResolverScriptData* init_script_data, 563 ProxyResolverScriptData* init_script_data,
526 NetLog* net_log) 564 NetLog* net_log)
527 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), 565 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
528 change_callback_(callback), 566 change_callback_(callback),
529 config_(config), 567 config_(config),
530 proxy_resolver_expects_pac_bytes_(proxy_resolver_expects_pac_bytes), 568 proxy_resolver_expects_pac_bytes_(proxy_resolver_expects_pac_bytes),
531 proxy_script_fetcher_(proxy_script_fetcher), 569 proxy_script_fetcher_(proxy_script_fetcher),
532 dhcp_proxy_script_fetcher_(dhcp_proxy_script_fetcher), 570 dhcp_proxy_script_fetcher_(dhcp_proxy_script_fetcher),
533 last_error_(init_net_error), 571 last_error_(init_net_error),
534 last_script_data_(init_script_data) { 572 last_script_data_(init_script_data),
573 last_poll_time_(base::TimeTicks::Now()) {
535 // Set the initial poll delay -- we check more aggressively right after a 574 // Set the initial poll delay -- we check more aggressively right after a
536 // failure in case it was due to a spurious network error. 575 // failure in case it was due to a spurious network error.
537 current_poll_delay_ms_ = GetInitialWaitDelayMs(init_net_error); 576 next_poll_mode_ = poll_policy()->GetInitialDelay(
538 577 init_net_error, &next_poll_delay_ms_);
539 StartPollTimer(); 578 TryToStartNextPoll(false);
540 } 579 }
541 580
542 // ---------------------------------- 581 void OnLazyPoll() {
543 // Policy for the retry scheduling. 582 // We have just been notified of network activity. Use this opportunity to
544 // ---------------------------------- 583 // see if we can start our next poll.
545 584 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 } 585 }
563 586
564 static int64 GetNextWaitDelayMs(int64 current_delay_ms) { 587 static const PacPollPolicy* set_policy(const PacPollPolicy* policy) {
565 switch (poll_policy_) { 588 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; 589 poll_policy_ = policy;
581 return prev; 590 return prev;
582 } 591 }
583 592
584 private: 593 private:
594 // Returns the effective poll policy (the one injected by unit-tests, or the
595 // default).
596 const PacPollPolicy* poll_policy() {
597 if (poll_policy_)
598 return poll_policy_;
599 return &default_poll_policy_;
600 }
601
585 void StartPollTimer() { 602 void StartPollTimer() {
586 DCHECK(!decider_.get()); 603 DCHECK(!decider_.get());
587 604
588 MessageLoop::current()->PostDelayedTask( 605 MessageLoop::current()->PostDelayedTask(
589 FROM_HERE, 606 FROM_HERE,
590 base::Bind(&ProxyScriptDeciderPoller::OnPollTimerFired, 607 base::Bind(&ProxyScriptDeciderPoller::DoPoll,
591 weak_factory_.GetWeakPtr()), 608 weak_factory_.GetWeakPtr()),
592 current_poll_delay_ms_); 609 next_poll_delay_ms_);
593 } 610 }
594 611
595 void OnPollTimerFired() { 612 void TryToStartNextPoll(bool triggered_by_activity) {
613 switch (next_poll_mode_) {
614 case PacPollPolicy::MODE_USE_TIMER:
615 if (!triggered_by_activity)
616 StartPollTimer();
617 break;
618
619 case PacPollPolicy::MODE_START_AFTER_ACTIVITY:
620 if (triggered_by_activity && !decider_.get()) {
621 base::TimeDelta elapsed_time =
622 base::TimeTicks::Now() - last_poll_time_;
623 if (elapsed_time.InMilliseconds() >= next_poll_delay_ms_)
624 DoPoll();
625 }
626 break;
627 }
628 }
629
630 void DoPoll() {
631 last_poll_time_ = base::TimeTicks::Now();
632
596 // Start the proxy script decider to see if anything has changed. 633 // Start the proxy script decider to see if anything has changed.
597 // TODO(eroman): Pass a proper NetLog rather than NULL. 634 // TODO(eroman): Pass a proper NetLog rather than NULL.
598 decider_.reset(new ProxyScriptDecider( 635 decider_.reset(new ProxyScriptDecider(
599 proxy_script_fetcher_, dhcp_proxy_script_fetcher_, NULL)); 636 proxy_script_fetcher_, dhcp_proxy_script_fetcher_, NULL));
600 int result = decider_->Start( 637 int result = decider_->Start(
601 config_, base::TimeDelta(), proxy_resolver_expects_pac_bytes_, 638 config_, base::TimeDelta(), proxy_resolver_expects_pac_bytes_,
602 base::Bind(&ProxyScriptDeciderPoller::OnProxyScriptDeciderCompleted, 639 base::Bind(&ProxyScriptDeciderPoller::OnProxyScriptDeciderCompleted,
603 base::Unretained(this))); 640 base::Unretained(this)));
604 641
605 if (result != ERR_IO_PENDING) 642 if (result != ERR_IO_PENDING)
(...skipping 13 matching lines...) Expand all
619 &ProxyScriptDeciderPoller::NotifyProxyServiceOfChange, 656 &ProxyScriptDeciderPoller::NotifyProxyServiceOfChange,
620 weak_factory_.GetWeakPtr(), 657 weak_factory_.GetWeakPtr(),
621 result, 658 result,
622 make_scoped_refptr(decider_->script_data()), 659 make_scoped_refptr(decider_->script_data()),
623 decider_->effective_config())); 660 decider_->effective_config()));
624 return; 661 return;
625 } 662 }
626 663
627 decider_.reset(); 664 decider_.reset();
628 665
629 // Schedule the next poll check. 666 // Decide when the next poll should take place, and possibly start the
630 current_poll_delay_ms_ = GetNextWaitDelayMs(current_poll_delay_ms_); 667 // next timer.
631 StartPollTimer(); 668 next_poll_mode_ =
669 poll_policy()->GetNextDelay(next_poll_delay_ms_, &next_poll_delay_ms_);
670 TryToStartNextPoll(false);
632 } 671 }
633 672
634 bool HasScriptDataChanged(int result, ProxyResolverScriptData* script_data) { 673 bool HasScriptDataChanged(int result, ProxyResolverScriptData* script_data) {
635 if (result != last_error_) { 674 if (result != last_error_) {
636 // Something changed -- it was failing before and now it succeeded, or 675 // Something changed -- it was failing before and now it succeeded, or
637 // conversely it succeeded before and now it failed. Or it failed in 676 // conversely it succeeded before and now it failed. Or it failed in
638 // both cases, however the specific failure error codes differ. 677 // both cases, however the specific failure error codes differ.
639 return true; 678 return true;
640 } 679 }
641 680
(...skipping 22 matching lines...) Expand all
664 ChangeCallback change_callback_; 703 ChangeCallback change_callback_;
665 ProxyConfig config_; 704 ProxyConfig config_;
666 bool proxy_resolver_expects_pac_bytes_; 705 bool proxy_resolver_expects_pac_bytes_;
667 ProxyScriptFetcher* proxy_script_fetcher_; 706 ProxyScriptFetcher* proxy_script_fetcher_;
668 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher_; 707 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher_;
669 708
670 int last_error_; 709 int last_error_;
671 scoped_refptr<ProxyResolverScriptData> last_script_data_; 710 scoped_refptr<ProxyResolverScriptData> last_script_data_;
672 711
673 scoped_ptr<ProxyScriptDecider> decider_; 712 scoped_ptr<ProxyScriptDecider> decider_;
674 int64 current_poll_delay_ms_; 713 int64 next_poll_delay_ms_;
714 PacPollPolicy::Mode next_poll_mode_;
675 715
676 static PollPolicy poll_policy_; 716 base::TimeTicks last_poll_time_;
717
718 // Polling policy injected by unit-tests. Otherwise this is NULL and the
719 // default policy will be used.
720 static const PacPollPolicy* poll_policy_;
721
722 const DefaultPollPolicy default_poll_policy_;
677 723
678 DISALLOW_COPY_AND_ASSIGN(ProxyScriptDeciderPoller); 724 DISALLOW_COPY_AND_ASSIGN(ProxyScriptDeciderPoller);
679 }; 725 };
680 726
681 // static 727 // static
682 ProxyService::PollPolicy ProxyService::ProxyScriptDeciderPoller::poll_policy_ = 728 const ProxyService::PacPollPolicy*
683 ProxyService::POLL_POLICY_REGULAR; 729 ProxyService::ProxyScriptDeciderPoller::poll_policy_ = NULL;
684 730
685 // ProxyService::PacRequest --------------------------------------------------- 731 // ProxyService::PacRequest ---------------------------------------------------
686 732
687 class ProxyService::PacRequest 733 class ProxyService::PacRequest
688 : public base::RefCounted<ProxyService::PacRequest> { 734 : public base::RefCounted<ProxyService::PacRequest> {
689 public: 735 public:
690 PacRequest(ProxyService* service, 736 PacRequest(ProxyService* service,
691 const GURL& url, 737 const GURL& url,
692 ProxyInfo* results, 738 ProxyInfo* results,
693 const net::CompletionCallback& user_callback, 739 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, 990 int ProxyService::ResolveProxy(const GURL& raw_url,
945 ProxyInfo* result, 991 ProxyInfo* result,
946 const net::CompletionCallback& callback, 992 const net::CompletionCallback& callback,
947 PacRequest** pac_request, 993 PacRequest** pac_request,
948 const BoundNetLog& net_log) { 994 const BoundNetLog& net_log) {
949 DCHECK(CalledOnValidThread()); 995 DCHECK(CalledOnValidThread());
950 DCHECK(!callback.is_null()); 996 DCHECK(!callback.is_null());
951 997
952 net_log.BeginEvent(NetLog::TYPE_PROXY_SERVICE, NULL); 998 net_log.BeginEvent(NetLog::TYPE_PROXY_SERVICE, NULL);
953 999
1000 // Notify our polling-based dependencies that a resolve is taking place.
1001 // This way they can schedule their polls in response to network activity.
954 config_service_->OnLazyPoll(); 1002 config_service_->OnLazyPoll();
1003 if (script_poller_.get())
1004 script_poller_->OnLazyPoll();
1005
955 if (current_state_ == STATE_NONE) 1006 if (current_state_ == STATE_NONE)
956 ApplyProxyConfigIfAvailable(); 1007 ApplyProxyConfigIfAvailable();
957 1008
958 // Strip away any reference fragments and the username/password, as they 1009 // Strip away any reference fragments and the username/password, as they
959 // are not relevant to proxy resolution. 1010 // are not relevant to proxy resolution.
960 GURL url = SimplifyUrlForRequest(raw_url); 1011 GURL url = SimplifyUrlForRequest(raw_url);
961 1012
962 // Check if the request can be completed right away. (This is the case when 1013 // Check if the request can be completed right away. (This is the case when
963 // using a direct connection for example). 1014 // using a direct connection for example).
964 int rv = TryToCompleteSynchronously(url, result); 1015 int rv = TryToCompleteSynchronously(url, result);
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
1346 1397
1347 return linux_config_service; 1398 return linux_config_service;
1348 #else 1399 #else
1349 LOG(WARNING) << "Failed to choose a system proxy settings fetcher " 1400 LOG(WARNING) << "Failed to choose a system proxy settings fetcher "
1350 "for this platform."; 1401 "for this platform.";
1351 return new ProxyConfigServiceDirect(); 1402 return new ProxyConfigServiceDirect();
1352 #endif 1403 #endif
1353 } 1404 }
1354 1405
1355 // static 1406 // static
1356 ProxyService::PollPolicy ProxyService::set_pac_script_poll_policy( 1407 const ProxyService::PacPollPolicy* ProxyService::set_pac_script_poll_policy(
1357 PollPolicy policy) { 1408 const PacPollPolicy* policy) {
1358 return ProxyScriptDeciderPoller::set_policy(policy); 1409 return ProxyScriptDeciderPoller::set_policy(policy);
1359 } 1410 }
1360 1411
1412 // static
1413 scoped_ptr<ProxyService::PacPollPolicy>
1414 ProxyService::CreateDefaultPacPollPolicy() {
1415 return scoped_ptr<PacPollPolicy>(new DefaultPollPolicy());
1416 }
1417
1361 void ProxyService::OnProxyConfigChanged( 1418 void ProxyService::OnProxyConfigChanged(
1362 const ProxyConfig& config, 1419 const ProxyConfig& config,
1363 ProxyConfigService::ConfigAvailability availability) { 1420 ProxyConfigService::ConfigAvailability availability) {
1364 // Retrieve the current proxy configuration from the ProxyConfigService. 1421 // Retrieve the current proxy configuration from the ProxyConfigService.
1365 // If a configuration is not available yet, we will get called back later 1422 // If a configuration is not available yet, we will get called back later
1366 // by our ProxyConfigService::Observer once it changes. 1423 // by our ProxyConfigService::Observer once it changes.
1367 ProxyConfig effective_config; 1424 ProxyConfig effective_config;
1368 switch (availability) { 1425 switch (availability) {
1369 case ProxyConfigService::CONFIG_PENDING: 1426 case ProxyConfigService::CONFIG_PENDING:
1370 // ProxyConfigService implementors should never pass CONFIG_PENDING. 1427 // ProxyConfigService implementors should never pass CONFIG_PENDING.
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1531 OnCompletion(result_); 1588 OnCompletion(result_);
1532 } 1589 }
1533 } 1590 }
1534 1591
1535 void SyncProxyServiceHelper::OnCompletion(int rv) { 1592 void SyncProxyServiceHelper::OnCompletion(int rv) {
1536 result_ = rv; 1593 result_ = rv;
1537 event_.Signal(); 1594 event_.Signal();
1538 } 1595 }
1539 1596
1540 } // namespace net 1597 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698