| Index: net/proxy/proxy_service.cc
|
| diff --git a/net/proxy/proxy_service.cc b/net/proxy/proxy_service.cc
|
| index fbfe21e75b02e49814c56fbf114c99ab9aad79fa..e915c2ed7624ca3e48d5f5eb697bcbe098a627ee 100644
|
| --- a/net/proxy/proxy_service.cc
|
| +++ b/net/proxy/proxy_service.cc
|
| @@ -77,9 +77,43 @@ const int64 kDelayAfterNetworkChangesMs = 2000;
|
| const int64 kInitialPollDelayForErrorMs = 4000;
|
| const int64 kInitialPollDelayForSuccessMs = 16000;
|
|
|
| +// Once the poll delay becomes larger than this, we will stop scheduling using
|
| +// a timer, and instead wait for an incoming request to trigger the poll.
|
| +const int64 kMaxPollDelayUsingTimer = 16000;
|
| +
|
| // The maximum poll delay for checking PAC scripts.
|
| const int64 kMaxPollDelayMs = 120000; // 2 minutes.
|
|
|
| +// This is the default policy for polling the PAC script. Checks happen after an
|
| +// exponentially increasing delay. The first couple checks will be scheduled
|
| +// using a timer. After that the checks will only be done lazily in response to
|
| +// a user request.
|
| +class DefaultPollPolicy : public ProxyService::PacPollPolicy {
|
| + public:
|
| + DefaultPollPolicy() {}
|
| +
|
| + virtual Mode GetInitialDelay(int error, int64* next_delay_ms) const OVERRIDE {
|
| + // Use a shorter wait delay if the initial fetch resulted in an error.
|
| + *next_delay_ms = (error != OK) ?
|
| + kInitialPollDelayForErrorMs : kInitialPollDelayForSuccessMs;
|
| + return MODE_USE_TIMER;
|
| + }
|
| +
|
| + virtual Mode GetNextDelay(int64 current_delay_ms,
|
| + int64* next_delay_ms) const OVERRIDE {
|
| + // Increase the wait delay exponentially up to a maximum.
|
| + *next_delay_ms = std::min(current_delay_ms * 2, kMaxPollDelayMs);
|
| +
|
| + // Once the delays are large enough, stop scheduling using a timer and
|
| + // instead only poll during periods of activity.
|
| + return (*next_delay_ms <= kMaxPollDelayUsingTimer) ?
|
| + MODE_USE_TIMER: MODE_START_AFTER_ACTIVITY;
|
| + }
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(DefaultPollPolicy);
|
| +};
|
| +
|
| // Config getter that always returns direct settings.
|
| class ProxyConfigServiceDirect : public ProxyConfigService {
|
| public:
|
| @@ -531,68 +565,67 @@ class ProxyService::ProxyScriptDeciderPoller {
|
| proxy_script_fetcher_(proxy_script_fetcher),
|
| dhcp_proxy_script_fetcher_(dhcp_proxy_script_fetcher),
|
| last_error_(init_net_error),
|
| - last_script_data_(init_script_data) {
|
| + last_script_data_(init_script_data),
|
| + last_poll_time_(base::TimeTicks::Now()) {
|
| // Set the initial poll delay -- we check more aggressively right after a
|
| // failure in case it was due to a spurious network error.
|
| - current_poll_delay_ms_ = GetInitialWaitDelayMs(init_net_error);
|
| -
|
| - StartPollTimer();
|
| - }
|
| -
|
| - // ----------------------------------
|
| - // Policy for the retry scheduling.
|
| - // ----------------------------------
|
| -
|
| - static int64 GetInitialWaitDelayMs(int error) {
|
| - switch (poll_policy_) {
|
| - case POLL_POLICY_REGULAR:
|
| - // Use a shorter wait delay if the initial fetch resulted in an error.
|
| - return (error != OK) ?
|
| - kInitialPollDelayForErrorMs : kInitialPollDelayForSuccessMs;
|
| - case POLL_POLICY_IMMEDIATE:
|
| - // Wait a mere 1 millisecond.
|
| - return 1;
|
| - case POLL_POLICY_NEVER:
|
| - // Unreasonably large wait delay, will never fire the check.
|
| - return 0xFFFFFFFF;
|
| - }
|
| -
|
| - // Shouldn't be reached
|
| - return -1;
|
| + next_poll_mode_ = poll_policy()->GetInitialDelay(
|
| + init_net_error, &next_poll_delay_ms_);
|
| + TryToStartNextPoll(false);
|
| }
|
|
|
| - static int64 GetNextWaitDelayMs(int64 current_delay_ms) {
|
| - switch (poll_policy_) {
|
| - case POLL_POLICY_REGULAR:
|
| - // Increase the delay exponentially up to 2 minutes.
|
| - return std::min(current_delay_ms * 2, kMaxPollDelayMs);
|
| - case POLL_POLICY_IMMEDIATE:
|
| - case POLL_POLICY_NEVER:
|
| - return current_delay_ms;
|
| - }
|
| -
|
| - // Shouldn't be reached
|
| - return -1;
|
| + void OnLazyPoll() {
|
| + // We have just been notified of network activity. Use this opportunity to
|
| + // see if we can start our next poll.
|
| + TryToStartNextPoll(true);
|
| }
|
|
|
| - static PollPolicy set_policy(PollPolicy policy) {
|
| - PollPolicy prev = poll_policy_;
|
| + static const PacPollPolicy* set_policy(const PacPollPolicy* policy) {
|
| + const PacPollPolicy* prev = poll_policy_;
|
| poll_policy_ = policy;
|
| return prev;
|
| }
|
|
|
| private:
|
| + // Returns the effective poll policy (the one injected by unit-tests, or the
|
| + // default).
|
| + const PacPollPolicy* poll_policy() {
|
| + if (poll_policy_)
|
| + return poll_policy_;
|
| + return &default_poll_policy_;
|
| + }
|
| +
|
| void StartPollTimer() {
|
| DCHECK(!decider_.get());
|
|
|
| MessageLoop::current()->PostDelayedTask(
|
| FROM_HERE,
|
| - base::Bind(&ProxyScriptDeciderPoller::OnPollTimerFired,
|
| + base::Bind(&ProxyScriptDeciderPoller::DoPoll,
|
| weak_factory_.GetWeakPtr()),
|
| - current_poll_delay_ms_);
|
| + next_poll_delay_ms_);
|
| + }
|
| +
|
| + void TryToStartNextPoll(bool triggered_by_activity) {
|
| + switch (next_poll_mode_) {
|
| + case PacPollPolicy::MODE_USE_TIMER:
|
| + if (!triggered_by_activity)
|
| + StartPollTimer();
|
| + break;
|
| +
|
| + case PacPollPolicy::MODE_START_AFTER_ACTIVITY:
|
| + if (triggered_by_activity && !decider_.get()) {
|
| + base::TimeDelta elapsed_time =
|
| + base::TimeTicks::Now() - last_poll_time_;
|
| + if (elapsed_time.InMilliseconds() >= next_poll_delay_ms_)
|
| + DoPoll();
|
| + }
|
| + break;
|
| + }
|
| }
|
|
|
| - void OnPollTimerFired() {
|
| + void DoPoll() {
|
| + last_poll_time_ = base::TimeTicks::Now();
|
| +
|
| // Start the proxy script decider to see if anything has changed.
|
| // TODO(eroman): Pass a proper NetLog rather than NULL.
|
| decider_.reset(new ProxyScriptDecider(
|
| @@ -626,9 +659,11 @@ class ProxyService::ProxyScriptDeciderPoller {
|
|
|
| decider_.reset();
|
|
|
| - // Schedule the next poll check.
|
| - current_poll_delay_ms_ = GetNextWaitDelayMs(current_poll_delay_ms_);
|
| - StartPollTimer();
|
| + // Decide when the next poll should take place, and possibly start the
|
| + // next timer.
|
| + next_poll_mode_ =
|
| + poll_policy()->GetNextDelay(next_poll_delay_ms_, &next_poll_delay_ms_);
|
| + TryToStartNextPoll(false);
|
| }
|
|
|
| bool HasScriptDataChanged(int result, ProxyResolverScriptData* script_data) {
|
| @@ -671,16 +706,23 @@ class ProxyService::ProxyScriptDeciderPoller {
|
| scoped_refptr<ProxyResolverScriptData> last_script_data_;
|
|
|
| scoped_ptr<ProxyScriptDecider> decider_;
|
| - int64 current_poll_delay_ms_;
|
| + int64 next_poll_delay_ms_;
|
| + PacPollPolicy::Mode next_poll_mode_;
|
|
|
| - static PollPolicy poll_policy_;
|
| + base::TimeTicks last_poll_time_;
|
| +
|
| + // Polling policy injected by unit-tests. Otherwise this is NULL and the
|
| + // default policy will be used.
|
| + static const PacPollPolicy* poll_policy_;
|
| +
|
| + const DefaultPollPolicy default_poll_policy_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(ProxyScriptDeciderPoller);
|
| };
|
|
|
| // static
|
| -ProxyService::PollPolicy ProxyService::ProxyScriptDeciderPoller::poll_policy_ =
|
| - ProxyService::POLL_POLICY_REGULAR;
|
| +const ProxyService::PacPollPolicy*
|
| + ProxyService::ProxyScriptDeciderPoller::poll_policy_ = NULL;
|
|
|
| // ProxyService::PacRequest ---------------------------------------------------
|
|
|
| @@ -951,7 +993,12 @@ int ProxyService::ResolveProxy(const GURL& raw_url,
|
|
|
| net_log.BeginEvent(NetLog::TYPE_PROXY_SERVICE, NULL);
|
|
|
| + // Notify our polling-based dependencies that a resolve is taking place.
|
| + // This way they can schedule their polls in response to network activity.
|
| config_service_->OnLazyPoll();
|
| + if (script_poller_.get())
|
| + script_poller_->OnLazyPoll();
|
| +
|
| if (current_state_ == STATE_NONE)
|
| ApplyProxyConfigIfAvailable();
|
|
|
| @@ -1353,11 +1400,17 @@ ProxyConfigService* ProxyService::CreateSystemProxyConfigService(
|
| }
|
|
|
| // static
|
| -ProxyService::PollPolicy ProxyService::set_pac_script_poll_policy(
|
| - PollPolicy policy) {
|
| +const ProxyService::PacPollPolicy* ProxyService::set_pac_script_poll_policy(
|
| + const PacPollPolicy* policy) {
|
| return ProxyScriptDeciderPoller::set_policy(policy);
|
| }
|
|
|
| +// static
|
| +scoped_ptr<ProxyService::PacPollPolicy>
|
| + ProxyService::CreateDefaultPacPollPolicy() {
|
| + return scoped_ptr<PacPollPolicy>(new DefaultPollPolicy());
|
| +}
|
| +
|
| void ProxyService::OnProxyConfigChanged(
|
| const ProxyConfig& config,
|
| ProxyConfigService::ConfigAvailability availability) {
|
|
|