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
3// found in the LICENSE file.
4
5#include "net/proxy/proxy_service.h"
6
7#include <algorithm>
8
9#include "base/bind.h"
10#include "base/bind_helpers.h"
11#include "base/compiler_specific.h"
12#include "base/logging.h"
13#include "base/memory/weak_ptr.h"
14#include "base/message_loop/message_loop.h"
15#include "base/message_loop/message_loop_proxy.h"
16#include "base/strings/string_util.h"
17#include "base/thread_task_runner_handle.h"
18#include "base/values.h"
19#include "net/base/completion_callback.h"
20#include "net/base/load_flags.h"
21#include "net/base/net_errors.h"
22#include "net/base/net_log.h"
23#include "net/base/net_util.h"
24#include "net/proxy/dhcp_proxy_script_fetcher.h"
25#include "net/proxy/multi_threaded_proxy_resolver.h"
26#include "net/proxy/network_delegate_error_observer.h"
27#include "net/proxy/proxy_config_service_fixed.h"
28#include "net/proxy/proxy_resolver.h"
29#include "net/proxy/proxy_script_decider.h"
30#include "net/proxy/proxy_script_fetcher.h"
31#include "net/url_request/url_request_context.h"
32#include "url/gurl.h"
33
34#if defined(OS_WIN)
35#include "net/proxy/proxy_config_service_win.h"
36#include "net/proxy/proxy_resolver_winhttp.h"
37#elif defined(OS_IOS)
38#include "net/proxy/proxy_config_service_ios.h"
39#include "net/proxy/proxy_resolver_mac.h"
40#elif defined(OS_MACOSX)
41#include "net/proxy/proxy_config_service_mac.h"
42#include "net/proxy/proxy_resolver_mac.h"
43#elif defined(OS_LINUX) && !defined(OS_CHROMEOS)
44#include "net/proxy/proxy_config_service_linux.h"
45#elif defined(OS_ANDROID)
46#include "net/proxy/proxy_config_service_android.h"
47#endif
48
49using base::TimeDelta;
50using base::TimeTicks;
51
52namespace net {
53
54namespace {
55
56// When the IP address changes we don't immediately re-run proxy auto-config.
57// Instead, we  wait for |kDelayAfterNetworkChangesMs| before
58// attempting to re-valuate proxy auto-config.
59//
60// During this time window, any resolve requests sent to the ProxyService will
61// be queued. Once we have waited the required amount of them, the proxy
62// auto-config step will be run, and the queued requests resumed.
63//
64// The reason we play this game is that our signal for detecting network
65// changes (NetworkChangeNotifier) may fire *before* the system's networking
66// dependencies are fully configured. This is a problem since it means if
67// we were to run proxy auto-config right away, it could fail due to spurious
68// DNS failures. (see http://crbug.com/50779 for more details.)
69//
70// By adding the wait window, we give things a better chance to get properly
71// set up. Network failures can happen at any time though, so we additionally
72// poll the PAC script for changes, which will allow us to recover from these
73// sorts of problems.
74const int64 kDelayAfterNetworkChangesMs = 2000;
75
76// This is the default policy for polling the PAC script.
77//
78// In response to a failure, the poll intervals are:
79//    0: 8 seconds  (scheduled on timer)
80//    1: 32 seconds
81//    2: 2 minutes
82//    3+: 4 hours
83//
84// In response to a success, the poll intervals are:
85//    0+: 12 hours
86//
87// Only the 8 second poll is scheduled on a timer, the rest happen in response
88// to network activity (and hence will take longer than the written time).
89//
90// Explanation for these values:
91//
92// TODO(eroman): These values are somewhat arbitrary, and need to be tuned
93// using some histograms data. Trying to be conservative so as not to break
94// existing setups when deployed. A simple exponential retry scheme would be
95// more elegant, but places more load on server.
96//
97// The motivation for trying quickly after failures (8 seconds) is to recover
98// from spurious network failures, which are common after the IP address has
99// just changed (like DNS failing to resolve). The next 32 second boundary is
100// to try and catch other VPN weirdness which anecdotally I have seen take
101// 10+ seconds for some users.
102//
103// The motivation for re-trying after a success is to check for possible
104// content changes to the script, or to the WPAD auto-discovery results. We are
105// not very aggressive with these checks so as to minimize the risk of
106// overloading existing PAC setups. Moreover it is unlikely that PAC scripts
107// change very frequently in existing setups. More research is needed to
108// motivate what safe values are here, and what other user agents do.
109//
110// Comparison to other browsers:
111//
112// In Firefox the PAC URL is re-tried on failures according to
113// network.proxy.autoconfig_retry_interval_min and
114// network.proxy.autoconfig_retry_interval_max. The defaults are 5 seconds and
115// 5 minutes respectively. It doubles the interval at each attempt.
116//
117// TODO(eroman): Figure out what Internet Explorer does.
118class DefaultPollPolicy : public ProxyService::PacPollPolicy {
119 public:
120  DefaultPollPolicy() {}
121
122  virtual Mode GetNextDelay(int initial_error,
123                            TimeDelta current_delay,
124                            TimeDelta* next_delay) const OVERRIDE {
125    if (initial_error != OK) {
126      // Re-try policy for failures.
127      const int kDelay1Seconds = 8;
128      const int kDelay2Seconds = 32;
129      const int kDelay3Seconds = 2 * 60;  // 2 minutes
130      const int kDelay4Seconds = 4 * 60 * 60;  // 4 Hours
131
132      // Initial poll.
133      if (current_delay < TimeDelta()) {
134        *next_delay = TimeDelta::FromSeconds(kDelay1Seconds);
135        return MODE_USE_TIMER;
136      }
137      switch (current_delay.InSeconds()) {
138        case kDelay1Seconds:
139          *next_delay = TimeDelta::FromSeconds(kDelay2Seconds);
140          return MODE_START_AFTER_ACTIVITY;
141        case kDelay2Seconds:
142          *next_delay = TimeDelta::FromSeconds(kDelay3Seconds);
143          return MODE_START_AFTER_ACTIVITY;
144        default:
145          *next_delay = TimeDelta::FromSeconds(kDelay4Seconds);
146          return MODE_START_AFTER_ACTIVITY;
147      }
148    } else {
149      // Re-try policy for succeses.
150      *next_delay = TimeDelta::FromHours(12);
151      return MODE_START_AFTER_ACTIVITY;
152    }
153  }
154
155 private:
156  DISALLOW_COPY_AND_ASSIGN(DefaultPollPolicy);
157};
158
159// Config getter that always returns direct settings.
160class ProxyConfigServiceDirect : public ProxyConfigService {
161 public:
162  // ProxyConfigService implementation:
163  virtual void AddObserver(Observer* observer) OVERRIDE {}
164  virtual void RemoveObserver(Observer* observer) OVERRIDE {}
165  virtual ConfigAvailability GetLatestProxyConfig(ProxyConfig* config)
166      OVERRIDE {
167    *config = ProxyConfig::CreateDirect();
168    config->set_source(PROXY_CONFIG_SOURCE_UNKNOWN);
169    return CONFIG_VALID;
170  }
171};
172
173// Proxy resolver that fails every time.
174class ProxyResolverNull : public ProxyResolver {
175 public:
176  ProxyResolverNull() : ProxyResolver(false /*expects_pac_bytes*/) {}
177
178  // ProxyResolver implementation.
179  virtual int GetProxyForURL(const GURL& url,
180                             ProxyInfo* results,
181                             const CompletionCallback& callback,
182                             RequestHandle* request,
183                             const BoundNetLog& net_log) OVERRIDE {
184    return ERR_NOT_IMPLEMENTED;
185  }
186
187  virtual void CancelRequest(RequestHandle request) OVERRIDE {
188    NOTREACHED();
189  }
190
191  virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
192    NOTREACHED();
193    return LOAD_STATE_IDLE;
194  }
195
196  virtual void CancelSetPacScript() OVERRIDE {
197    NOTREACHED();
198  }
199
200  virtual int SetPacScript(
201      const scoped_refptr<ProxyResolverScriptData>& /*script_data*/,
202      const CompletionCallback& /*callback*/) OVERRIDE {
203    return ERR_NOT_IMPLEMENTED;
204  }
205};
206
207// ProxyResolver that simulates a PAC script which returns
208// |pac_string| for every single URL.
209class ProxyResolverFromPacString : public ProxyResolver {
210 public:
211  explicit ProxyResolverFromPacString(const std::string& pac_string)
212      : ProxyResolver(false /*expects_pac_bytes*/),
213        pac_string_(pac_string) {}
214
215  virtual int GetProxyForURL(const GURL& url,
216                             ProxyInfo* results,
217                             const CompletionCallback& callback,
218                             RequestHandle* request,
219                             const BoundNetLog& net_log) OVERRIDE {
220    results->UsePacString(pac_string_);
221    return OK;
222  }
223
224  virtual void CancelRequest(RequestHandle request) OVERRIDE {
225    NOTREACHED();
226  }
227
228  virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
229    NOTREACHED();
230    return LOAD_STATE_IDLE;
231  }
232
233  virtual void CancelSetPacScript() OVERRIDE {
234    NOTREACHED();
235  }
236
237  virtual int SetPacScript(
238      const scoped_refptr<ProxyResolverScriptData>& pac_script,
239      const CompletionCallback& callback) OVERRIDE {
240    return OK;
241  }
242
243 private:
244  const std::string pac_string_;
245};
246
247// Creates ProxyResolvers using a platform-specific implementation.
248class ProxyResolverFactoryForSystem : public ProxyResolverFactory {
249 public:
250  ProxyResolverFactoryForSystem()
251      : ProxyResolverFactory(false /*expects_pac_bytes*/) {}
252
253  virtual ProxyResolver* CreateProxyResolver() OVERRIDE {
254    DCHECK(IsSupported());
255#if defined(OS_WIN)
256    return new ProxyResolverWinHttp();
257#elif defined(OS_MACOSX)
258    return new ProxyResolverMac();
259#else
260    NOTREACHED();
261    return NULL;
262#endif
263  }
264
265  static bool IsSupported() {
266#if defined(OS_WIN) || defined(OS_MACOSX)
267    return true;
268#else
269    return false;
270#endif
271  }
272};
273
274// Returns NetLog parameters describing a proxy configuration change.
275base::Value* NetLogProxyConfigChangedCallback(
276    const ProxyConfig* old_config,
277    const ProxyConfig* new_config,
278    NetLog::LogLevel /* log_level */) {
279  base::DictionaryValue* dict = new base::DictionaryValue();
280  // The "old_config" is optional -- the first notification will not have
281  // any "previous" configuration.
282  if (old_config->is_valid())
283    dict->Set("old_config", old_config->ToValue());
284  dict->Set("new_config", new_config->ToValue());
285  return dict;
286}
287
288base::Value* NetLogBadProxyListCallback(const ProxyRetryInfoMap* retry_info,
289                                        NetLog::LogLevel /* log_level */) {
290  base::DictionaryValue* dict = new base::DictionaryValue();
291  base::ListValue* list = new base::ListValue();
292
293  for (ProxyRetryInfoMap::const_iterator iter = retry_info->begin();
294       iter != retry_info->end(); ++iter) {
295    list->Append(new base::StringValue(iter->first));
296  }
297  dict->Set("bad_proxy_list", list);
298  return dict;
299}
300
301// Returns NetLog parameters on a successfuly proxy resolution.
302base::Value* NetLogFinishedResolvingProxyCallback(
303    ProxyInfo* result,
304    NetLog::LogLevel /* log_level */) {
305  base::DictionaryValue* dict = new base::DictionaryValue();
306  dict->SetString("pac_string", result->ToPacString());
307  return dict;
308}
309
310#if defined(OS_CHROMEOS)
311class UnsetProxyConfigService : public ProxyConfigService {
312 public:
313  UnsetProxyConfigService() {}
314  virtual ~UnsetProxyConfigService() {}
315
316  virtual void AddObserver(Observer* observer) OVERRIDE {}
317  virtual void RemoveObserver(Observer* observer) OVERRIDE {}
318  virtual ConfigAvailability GetLatestProxyConfig(
319      ProxyConfig* config) OVERRIDE {
320    return CONFIG_UNSET;
321  }
322};
323#endif
324
325}  // namespace
326
327// ProxyService::InitProxyResolver --------------------------------------------
328
329// This glues together two asynchronous steps:
330//   (1) ProxyScriptDecider -- try to fetch/validate a sequence of PAC scripts
331//       to figure out what we should configure against.
332//   (2) Feed the fetched PAC script into the ProxyResolver.
333//
334// InitProxyResolver is a single-use class which encapsulates cancellation as
335// part of its destructor. Start() or StartSkipDecider() should be called just
336// once. The instance can be destroyed at any time, and the request will be
337// cancelled.
338
339class ProxyService::InitProxyResolver {
340 public:
341  InitProxyResolver()
342      : proxy_resolver_(NULL),
343        next_state_(STATE_NONE),
344        quick_check_enabled_(true) {
345  }
346
347  ~InitProxyResolver() {
348    // Note that the destruction of ProxyScriptDecider will automatically cancel
349    // any outstanding work.
350    if (next_state_ == STATE_SET_PAC_SCRIPT_COMPLETE) {
351      proxy_resolver_->CancelSetPacScript();
352    }
353  }
354
355  // Begins initializing the proxy resolver; calls |callback| when done.
356  int Start(ProxyResolver* proxy_resolver,
357            ProxyScriptFetcher* proxy_script_fetcher,
358            DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher,
359            NetLog* net_log,
360            const ProxyConfig& config,
361            TimeDelta wait_delay,
362            const CompletionCallback& callback) {
363    DCHECK_EQ(STATE_NONE, next_state_);
364    proxy_resolver_ = proxy_resolver;
365
366    decider_.reset(new ProxyScriptDecider(
367        proxy_script_fetcher, dhcp_proxy_script_fetcher, net_log));
368    decider_->set_quick_check_enabled(quick_check_enabled_);
369    config_ = config;
370    wait_delay_ = wait_delay;
371    callback_ = callback;
372
373    next_state_ = STATE_DECIDE_PROXY_SCRIPT;
374    return DoLoop(OK);
375  }
376
377  // Similar to Start(), however it skips the ProxyScriptDecider stage. Instead
378  // |effective_config|, |decider_result| and |script_data| will be used as the
379  // inputs for initializing the ProxyResolver.
380  int StartSkipDecider(ProxyResolver* proxy_resolver,
381                       const ProxyConfig& effective_config,
382                       int decider_result,
383                       ProxyResolverScriptData* script_data,
384                       const CompletionCallback& callback) {
385    DCHECK_EQ(STATE_NONE, next_state_);
386    proxy_resolver_ = proxy_resolver;
387
388    effective_config_ = effective_config;
389    script_data_ = script_data;
390    callback_ = callback;
391
392    if (decider_result != OK)
393      return decider_result;
394
395    next_state_ = STATE_SET_PAC_SCRIPT;
396    return DoLoop(OK);
397  }
398
399  // Returns the proxy configuration that was selected by ProxyScriptDecider.
400  // Should only be called upon completion of the initialization.
401  const ProxyConfig& effective_config() const {
402    DCHECK_EQ(STATE_NONE, next_state_);
403    return effective_config_;
404  }
405
406  // Returns the PAC script data that was selected by ProxyScriptDecider.
407  // Should only be called upon completion of the initialization.
408  ProxyResolverScriptData* script_data() {
409    DCHECK_EQ(STATE_NONE, next_state_);
410    return script_data_.get();
411  }
412
413  LoadState GetLoadState() const {
414    if (next_state_ == STATE_DECIDE_PROXY_SCRIPT_COMPLETE) {
415      // In addition to downloading, this state may also include the stall time
416      // after network change events (kDelayAfterNetworkChangesMs).
417      return LOAD_STATE_DOWNLOADING_PROXY_SCRIPT;
418    }
419    return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
420  }
421
422  void set_quick_check_enabled(bool enabled) { quick_check_enabled_ = enabled; }
423  bool quick_check_enabled() const { return quick_check_enabled_; }
424
425 private:
426  enum State {
427    STATE_NONE,
428    STATE_DECIDE_PROXY_SCRIPT,
429    STATE_DECIDE_PROXY_SCRIPT_COMPLETE,
430    STATE_SET_PAC_SCRIPT,
431    STATE_SET_PAC_SCRIPT_COMPLETE,
432  };
433
434  int DoLoop(int result) {
435    DCHECK_NE(next_state_, STATE_NONE);
436    int rv = result;
437    do {
438      State state = next_state_;
439      next_state_ = STATE_NONE;
440      switch (state) {
441        case STATE_DECIDE_PROXY_SCRIPT:
442          DCHECK_EQ(OK, rv);
443          rv = DoDecideProxyScript();
444          break;
445        case STATE_DECIDE_PROXY_SCRIPT_COMPLETE:
446          rv = DoDecideProxyScriptComplete(rv);
447          break;
448        case STATE_SET_PAC_SCRIPT:
449          DCHECK_EQ(OK, rv);
450          rv = DoSetPacScript();
451          break;
452        case STATE_SET_PAC_SCRIPT_COMPLETE:
453          rv = DoSetPacScriptComplete(rv);
454          break;
455        default:
456          NOTREACHED() << "bad state: " << state;
457          rv = ERR_UNEXPECTED;
458          break;
459      }
460    } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
461    return rv;
462  }
463
464  int DoDecideProxyScript() {
465    next_state_ = STATE_DECIDE_PROXY_SCRIPT_COMPLETE;
466
467    return decider_->Start(
468        config_, wait_delay_, proxy_resolver_->expects_pac_bytes(),
469        base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this)));
470  }
471
472  int DoDecideProxyScriptComplete(int result) {
473    if (result != OK)
474      return result;
475
476    effective_config_ = decider_->effective_config();
477    script_data_ = decider_->script_data();
478
479    next_state_ = STATE_SET_PAC_SCRIPT;
480    return OK;
481  }
482
483  int DoSetPacScript() {
484    DCHECK(script_data_.get());
485    // TODO(eroman): Should log this latency to the NetLog.
486    next_state_ = STATE_SET_PAC_SCRIPT_COMPLETE;
487    return proxy_resolver_->SetPacScript(
488        script_data_,
489        base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this)));
490  }
491
492  int DoSetPacScriptComplete(int result) {
493    return result;
494  }
495
496  void OnIOCompletion(int result) {
497    DCHECK_NE(STATE_NONE, next_state_);
498    int rv = DoLoop(result);
499    if (rv != ERR_IO_PENDING)
500      DoCallback(rv);
501  }
502
503  void DoCallback(int result) {
504    DCHECK_NE(ERR_IO_PENDING, result);
505    callback_.Run(result);
506  }
507
508  ProxyConfig config_;
509  ProxyConfig effective_config_;
510  scoped_refptr<ProxyResolverScriptData> script_data_;
511  TimeDelta wait_delay_;
512  scoped_ptr<ProxyScriptDecider> decider_;
513  ProxyResolver* proxy_resolver_;
514  CompletionCallback callback_;
515  State next_state_;
516  bool quick_check_enabled_;
517
518  DISALLOW_COPY_AND_ASSIGN(InitProxyResolver);
519};
520
521// ProxyService::ProxyScriptDeciderPoller -------------------------------------
522
523// This helper class encapsulates the logic to schedule and run periodic
524// background checks to see if the PAC script (or effective proxy configuration)
525// has changed. If a change is detected, then the caller will be notified via
526// the ChangeCallback.
527class ProxyService::ProxyScriptDeciderPoller {
528 public:
529  typedef base::Callback<void(int, ProxyResolverScriptData*,
530                              const ProxyConfig&)> ChangeCallback;
531
532  // Builds a poller helper, and starts polling for updates. Whenever a change
533  // is observed, |callback| will be invoked with the details.
534  //
535  //   |config| specifies the (unresolved) proxy configuration to poll.
536  //   |proxy_resolver_expects_pac_bytes| the type of proxy resolver we expect
537  //                                      to use the resulting script data with
538  //                                      (so it can choose the right format).
539  //   |proxy_script_fetcher| this pointer must remain alive throughout our
540  //                          lifetime. It is the dependency that will be used
541  //                          for downloading proxy scripts.
542  //   |dhcp_proxy_script_fetcher| similar to |proxy_script_fetcher|, but for
543  //                               the DHCP dependency.
544  //   |init_net_error| This is the initial network error (possibly success)
545  //                    encountered by the first PAC fetch attempt. We use it
546  //                    to schedule updates more aggressively if the initial
547  //                    fetch resulted in an error.
548  //   |init_script_data| the initial script data from the PAC fetch attempt.
549  //                      This is the baseline used to determine when the
550  //                      script's contents have changed.
551  //   |net_log| the NetLog to log progress into.
552  ProxyScriptDeciderPoller(ChangeCallback callback,
553                           const ProxyConfig& config,
554                           bool proxy_resolver_expects_pac_bytes,
555                           ProxyScriptFetcher* proxy_script_fetcher,
556                           DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher,
557                           int init_net_error,
558                           ProxyResolverScriptData* init_script_data,
559                           NetLog* net_log)
560      : weak_factory_(this),
561        change_callback_(callback),
562        config_(config),
563        proxy_resolver_expects_pac_bytes_(proxy_resolver_expects_pac_bytes),
564        proxy_script_fetcher_(proxy_script_fetcher),
565        dhcp_proxy_script_fetcher_(dhcp_proxy_script_fetcher),
566        last_error_(init_net_error),
567        last_script_data_(init_script_data),
568        last_poll_time_(TimeTicks::Now()) {
569    // Set the initial poll delay.
570    next_poll_mode_ = poll_policy()->GetNextDelay(
571        last_error_, TimeDelta::FromSeconds(-1), &next_poll_delay_);
572    TryToStartNextPoll(false);
573  }
574
575  void OnLazyPoll() {
576    // We have just been notified of network activity. Use this opportunity to
577    // see if we can start our next poll.
578    TryToStartNextPoll(true);
579  }
580
581  static const PacPollPolicy* set_policy(const PacPollPolicy* policy) {
582    const PacPollPolicy* prev = poll_policy_;
583    poll_policy_ = policy;
584    return prev;
585  }
586
587  void set_quick_check_enabled(bool enabled) { quick_check_enabled_ = enabled; }
588  bool quick_check_enabled() const { return quick_check_enabled_; }
589
590 private:
591  // Returns the effective poll policy (the one injected by unit-tests, or the
592  // default).
593  const PacPollPolicy* poll_policy() {
594    if (poll_policy_)
595      return poll_policy_;
596    return &default_poll_policy_;
597  }
598
599  void StartPollTimer() {
600    DCHECK(!decider_.get());
601
602    base::MessageLoop::current()->PostDelayedTask(
603        FROM_HERE,
604        base::Bind(&ProxyScriptDeciderPoller::DoPoll,
605                   weak_factory_.GetWeakPtr()),
606        next_poll_delay_);
607  }
608
609  void TryToStartNextPoll(bool triggered_by_activity) {
610    switch (next_poll_mode_) {
611      case PacPollPolicy::MODE_USE_TIMER:
612        if (!triggered_by_activity)
613          StartPollTimer();
614        break;
615
616      case PacPollPolicy::MODE_START_AFTER_ACTIVITY:
617        if (triggered_by_activity && !decider_.get()) {
618          TimeDelta elapsed_time = TimeTicks::Now() - last_poll_time_;
619          if (elapsed_time >= next_poll_delay_)
620            DoPoll();
621        }
622        break;
623    }
624  }
625
626  void DoPoll() {
627    last_poll_time_ = TimeTicks::Now();
628
629    // Start the proxy script decider to see if anything has changed.
630    // TODO(eroman): Pass a proper NetLog rather than NULL.
631    decider_.reset(new ProxyScriptDecider(
632        proxy_script_fetcher_, dhcp_proxy_script_fetcher_, NULL));
633    decider_->set_quick_check_enabled(quick_check_enabled_);
634    int result = decider_->Start(
635        config_, TimeDelta(), proxy_resolver_expects_pac_bytes_,
636        base::Bind(&ProxyScriptDeciderPoller::OnProxyScriptDeciderCompleted,
637                   base::Unretained(this)));
638
639    if (result != ERR_IO_PENDING)
640      OnProxyScriptDeciderCompleted(result);
641  }
642
643  void OnProxyScriptDeciderCompleted(int result) {
644    if (HasScriptDataChanged(result, decider_->script_data())) {
645      // Something has changed, we must notify the ProxyService so it can
646      // re-initialize its ProxyResolver. Note that we post a notification task
647      // rather than calling it directly -- this is done to avoid an ugly
648      // destruction sequence, since |this| might be destroyed as a result of
649      // the notification.
650      base::MessageLoop::current()->PostTask(
651          FROM_HERE,
652          base::Bind(&ProxyScriptDeciderPoller::NotifyProxyServiceOfChange,
653                     weak_factory_.GetWeakPtr(),
654                     result,
655                     make_scoped_refptr(decider_->script_data()),
656                     decider_->effective_config()));
657      return;
658    }
659
660    decider_.reset();
661
662    // Decide when the next poll should take place, and possibly start the
663    // next timer.
664    next_poll_mode_ = poll_policy()->GetNextDelay(
665        last_error_, next_poll_delay_, &next_poll_delay_);
666    TryToStartNextPoll(false);
667  }
668
669  bool HasScriptDataChanged(int result, ProxyResolverScriptData* script_data) {
670    if (result != last_error_) {
671      // Something changed -- it was failing before and now it succeeded, or
672      // conversely it succeeded before and now it failed. Or it failed in
673      // both cases, however the specific failure error codes differ.
674      return true;
675    }
676
677    if (result != OK) {
678      // If it failed last time and failed again with the same error code this
679      // time, then nothing has actually changed.
680      return false;
681    }
682
683    // Otherwise if it succeeded both this time and last time, we need to look
684    // closer and see if we ended up downloading different content for the PAC
685    // script.
686    return !script_data->Equals(last_script_data_.get());
687  }
688
689  void NotifyProxyServiceOfChange(
690      int result,
691      const scoped_refptr<ProxyResolverScriptData>& script_data,
692      const ProxyConfig& effective_config) {
693    // Note that |this| may be deleted after calling into the ProxyService.
694    change_callback_.Run(result, script_data.get(), effective_config);
695  }
696
697  base::WeakPtrFactory<ProxyScriptDeciderPoller> weak_factory_;
698
699  ChangeCallback change_callback_;
700  ProxyConfig config_;
701  bool proxy_resolver_expects_pac_bytes_;
702  ProxyScriptFetcher* proxy_script_fetcher_;
703  DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher_;
704
705  int last_error_;
706  scoped_refptr<ProxyResolverScriptData> last_script_data_;
707
708  scoped_ptr<ProxyScriptDecider> decider_;
709  TimeDelta next_poll_delay_;
710  PacPollPolicy::Mode next_poll_mode_;
711
712  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_;
719
720  bool quick_check_enabled_;
721
722  DISALLOW_COPY_AND_ASSIGN(ProxyScriptDeciderPoller);
723};
724
725// static
726const ProxyService::PacPollPolicy*
727    ProxyService::ProxyScriptDeciderPoller::poll_policy_ = NULL;
728
729// ProxyService::PacRequest ---------------------------------------------------
730
731class ProxyService::PacRequest
732    : public base::RefCounted<ProxyService::PacRequest> {
733 public:
734    PacRequest(ProxyService* service,
735               const GURL& url,
736               int load_flags,
737               NetworkDelegate* network_delegate,
738               ProxyInfo* results,
739               const net::CompletionCallback& user_callback,
740               const BoundNetLog& net_log)
741      : service_(service),
742        user_callback_(user_callback),
743        results_(results),
744        url_(url),
745        load_flags_(load_flags),
746        network_delegate_(network_delegate),
747        resolve_job_(NULL),
748        config_id_(ProxyConfig::kInvalidConfigID),
749        config_source_(PROXY_CONFIG_SOURCE_UNKNOWN),
750        net_log_(net_log) {
751    DCHECK(!user_callback.is_null());
752  }
753
754  // Starts the resolve proxy request.
755  int Start() {
756    DCHECK(!was_cancelled());
757    DCHECK(!is_started());
758
759    DCHECK(service_->config_.is_valid());
760
761    config_id_ = service_->config_.id();
762    config_source_ = service_->config_.source();
763    proxy_resolve_start_time_ = TimeTicks::Now();
764
765    return resolver()->GetProxyForURL(
766        url_, results_,
767        base::Bind(&PacRequest::QueryComplete, base::Unretained(this)),
768        &resolve_job_, net_log_);
769  }
770
771  bool is_started() const {
772    // Note that !! casts to bool. (VS gives a warning otherwise).
773    return !!resolve_job_;
774  }
775
776  void StartAndCompleteCheckingForSynchronous() {
777    int rv = service_->TryToCompleteSynchronously(url_, load_flags_,
778                                                  network_delegate_, results_);
779    if (rv == ERR_IO_PENDING)
780      rv = Start();
781    if (rv != ERR_IO_PENDING)
782      QueryComplete(rv);
783  }
784
785  void CancelResolveJob() {
786    DCHECK(is_started());
787    // The request may already be running in the resolver.
788    resolver()->CancelRequest(resolve_job_);
789    resolve_job_ = NULL;
790    DCHECK(!is_started());
791  }
792
793  void Cancel() {
794    net_log_.AddEvent(NetLog::TYPE_CANCELLED);
795
796    if (is_started())
797      CancelResolveJob();
798
799    // Mark as cancelled, to prevent accessing this again later.
800    service_ = NULL;
801    user_callback_.Reset();
802    results_ = NULL;
803
804    net_log_.EndEvent(NetLog::TYPE_PROXY_SERVICE);
805  }
806
807  // Returns true if Cancel() has been called.
808  bool was_cancelled() const {
809    return user_callback_.is_null();
810  }
811
812  // Helper to call after ProxyResolver completion (both synchronous and
813  // asynchronous). Fixes up the result that is to be returned to user.
814  int QueryDidComplete(int result_code) {
815    DCHECK(!was_cancelled());
816
817    // Note that DidFinishResolvingProxy might modify |results_|.
818    int rv = service_->DidFinishResolvingProxy(url_, load_flags_,
819                                               network_delegate_, results_,
820                                               result_code, net_log_);
821
822    // Make a note in the results which configuration was in use at the
823    // time of the resolve.
824    results_->config_id_ = config_id_;
825    results_->config_source_ = config_source_;
826    results_->did_use_pac_script_ = true;
827    results_->proxy_resolve_start_time_ = proxy_resolve_start_time_;
828    results_->proxy_resolve_end_time_ = TimeTicks::Now();
829
830    // Reset the state associated with in-progress-resolve.
831    resolve_job_ = NULL;
832    config_id_ = ProxyConfig::kInvalidConfigID;
833    config_source_ = PROXY_CONFIG_SOURCE_UNKNOWN;
834
835    return rv;
836  }
837
838  BoundNetLog* net_log() { return &net_log_; }
839
840  LoadState GetLoadState() const {
841    if (is_started())
842      return resolver()->GetLoadState(resolve_job_);
843    return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
844  }
845
846 private:
847  friend class base::RefCounted<ProxyService::PacRequest>;
848
849  ~PacRequest() {}
850
851  // Callback for when the ProxyResolver request has completed.
852  void QueryComplete(int result_code) {
853    result_code = QueryDidComplete(result_code);
854
855    // Remove this completed PacRequest from the service's pending list.
856    /// (which will probably cause deletion of |this|).
857    if (!user_callback_.is_null()) {
858      net::CompletionCallback callback = user_callback_;
859      service_->RemovePendingRequest(this);
860      callback.Run(result_code);
861    }
862  }
863
864  ProxyResolver* resolver() const { return service_->resolver_.get(); }
865
866  // Note that we don't hold a reference to the ProxyService. Outstanding
867  // requests are cancelled during ~ProxyService, so this is guaranteed
868  // to be valid throughout our lifetime.
869  ProxyService* service_;
870  net::CompletionCallback user_callback_;
871  ProxyInfo* results_;
872  GURL url_;
873  int load_flags_;
874  NetworkDelegate* network_delegate_;
875  ProxyResolver::RequestHandle resolve_job_;
876  ProxyConfig::ID config_id_;  // The config id when the resolve was started.
877  ProxyConfigSource config_source_;  // The source of proxy settings.
878  BoundNetLog net_log_;
879  // Time when the PAC is started.  Cached here since resetting ProxyInfo also
880  // clears the proxy times.
881  TimeTicks proxy_resolve_start_time_;
882};
883
884// ProxyService ---------------------------------------------------------------
885
886ProxyService::ProxyService(ProxyConfigService* config_service,
887                           ProxyResolver* resolver,
888                           NetLog* net_log)
889    : resolver_(resolver),
890      next_config_id_(1),
891      current_state_(STATE_NONE),
892      net_log_(net_log),
893      stall_proxy_auto_config_delay_(TimeDelta::FromMilliseconds(
894          kDelayAfterNetworkChangesMs)),
895      quick_check_enabled_(true) {
896  NetworkChangeNotifier::AddIPAddressObserver(this);
897  NetworkChangeNotifier::AddDNSObserver(this);
898  ResetConfigService(config_service);
899}
900
901// static
902ProxyService* ProxyService::CreateUsingSystemProxyResolver(
903    ProxyConfigService* proxy_config_service,
904    size_t num_pac_threads,
905    NetLog* net_log) {
906  DCHECK(proxy_config_service);
907
908  if (!ProxyResolverFactoryForSystem::IsSupported()) {
909    LOG(WARNING) << "PAC support disabled because there is no "
910                    "system implementation";
911    return CreateWithoutProxyResolver(proxy_config_service, net_log);
912  }
913
914  if (num_pac_threads == 0)
915    num_pac_threads = kDefaultNumPacThreads;
916
917  ProxyResolver* proxy_resolver = new MultiThreadedProxyResolver(
918      new ProxyResolverFactoryForSystem(), num_pac_threads);
919
920  return new ProxyService(proxy_config_service, proxy_resolver, net_log);
921}
922
923// static
924ProxyService* ProxyService::CreateWithoutProxyResolver(
925    ProxyConfigService* proxy_config_service,
926    NetLog* net_log) {
927  return new ProxyService(proxy_config_service,
928                          new ProxyResolverNull(),
929                          net_log);
930}
931
932// static
933ProxyService* ProxyService::CreateFixed(const ProxyConfig& pc) {
934  // TODO(eroman): This isn't quite right, won't work if |pc| specifies
935  //               a PAC script.
936  return CreateUsingSystemProxyResolver(new ProxyConfigServiceFixed(pc),
937                                        0, NULL);
938}
939
940// static
941ProxyService* ProxyService::CreateFixed(const std::string& proxy) {
942  net::ProxyConfig proxy_config;
943  proxy_config.proxy_rules().ParseFromString(proxy);
944  return ProxyService::CreateFixed(proxy_config);
945}
946
947// static
948ProxyService* ProxyService::CreateDirect() {
949  return CreateDirectWithNetLog(NULL);
950}
951
952ProxyService* ProxyService::CreateDirectWithNetLog(NetLog* net_log) {
953  // Use direct connections.
954  return new ProxyService(new ProxyConfigServiceDirect, new ProxyResolverNull,
955                          net_log);
956}
957
958// static
959ProxyService* ProxyService::CreateFixedFromPacResult(
960    const std::string& pac_string) {
961
962  // We need the settings to contain an "automatic" setting, otherwise the
963  // ProxyResolver dependency we give it will never be used.
964  scoped_ptr<ProxyConfigService> proxy_config_service(
965      new ProxyConfigServiceFixed(ProxyConfig::CreateAutoDetect()));
966
967  scoped_ptr<ProxyResolver> proxy_resolver(
968      new ProxyResolverFromPacString(pac_string));
969
970  return new ProxyService(proxy_config_service.release(),
971                          proxy_resolver.release(),
972                          NULL);
973}
974
975int ProxyService::ResolveProxy(const GURL& raw_url,
976                               int load_flags,
977                               ProxyInfo* result,
978                               const net::CompletionCallback& callback,
979                               PacRequest** pac_request,
980                               NetworkDelegate* network_delegate,
981                               const BoundNetLog& net_log) {
982  DCHECK(CalledOnValidThread());
983  DCHECK(!callback.is_null());
984
985  net_log.BeginEvent(NetLog::TYPE_PROXY_SERVICE);
986
987  // Notify our polling-based dependencies that a resolve is taking place.
988  // This way they can schedule their polls in response to network activity.
989  config_service_->OnLazyPoll();
990  if (script_poller_.get())
991     script_poller_->OnLazyPoll();
992
993  if (current_state_ == STATE_NONE)
994    ApplyProxyConfigIfAvailable();
995
996  // Strip away any reference fragments and the username/password, as they
997  // are not relevant to proxy resolution.
998  GURL url = SimplifyUrlForRequest(raw_url);
999
1000  // Check if the request can be completed right away. (This is the case when
1001  // using a direct connection for example).
1002  int rv = TryToCompleteSynchronously(url, load_flags,
1003                                      network_delegate, result);
1004  if (rv != ERR_IO_PENDING)
1005    return DidFinishResolvingProxy(url, load_flags, network_delegate,
1006                                   result, rv, net_log);
1007
1008  scoped_refptr<PacRequest> req(
1009      new PacRequest(this, url, load_flags, network_delegate,
1010                     result, callback, net_log));
1011
1012  if (current_state_ == STATE_READY) {
1013    // Start the resolve request.
1014    rv = req->Start();
1015    if (rv != ERR_IO_PENDING)
1016      return req->QueryDidComplete(rv);
1017  } else {
1018    req->net_log()->BeginEvent(NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC);
1019  }
1020
1021  DCHECK_EQ(ERR_IO_PENDING, rv);
1022  DCHECK(!ContainsPendingRequest(req.get()));
1023  pending_requests_.push_back(req);
1024
1025  // Completion will be notified through |callback|, unless the caller cancels
1026  // the request using |pac_request|.
1027  if (pac_request)
1028    *pac_request = req.get();
1029  return rv;  // ERR_IO_PENDING
1030}
1031
1032int ProxyService::TryToCompleteSynchronously(const GURL& url,
1033                                             int load_flags,
1034                                             NetworkDelegate* network_delegate,
1035                                             ProxyInfo* result) {
1036  DCHECK_NE(STATE_NONE, current_state_);
1037
1038  if (current_state_ != STATE_READY)
1039    return ERR_IO_PENDING;  // Still initializing.
1040
1041  DCHECK_NE(config_.id(), ProxyConfig::kInvalidConfigID);
1042
1043  // If it was impossible to fetch or parse the PAC script, we cannot complete
1044  // the request here and bail out.
1045  if (permanent_error_ != OK)
1046    return permanent_error_;
1047
1048  if (config_.HasAutomaticSettings())
1049    return ERR_IO_PENDING;  // Must submit the request to the proxy resolver.
1050
1051  // Use the manual proxy settings.
1052  config_.proxy_rules().Apply(url, result);
1053  result->config_source_ = config_.source();
1054  result->config_id_ = config_.id();
1055
1056  return OK;
1057}
1058
1059ProxyService::~ProxyService() {
1060  NetworkChangeNotifier::RemoveIPAddressObserver(this);
1061  NetworkChangeNotifier::RemoveDNSObserver(this);
1062  config_service_->RemoveObserver(this);
1063
1064  // Cancel any inprogress requests.
1065  for (PendingRequests::iterator it = pending_requests_.begin();
1066       it != pending_requests_.end();
1067       ++it) {
1068    (*it)->Cancel();
1069  }
1070}
1071
1072void ProxyService::SuspendAllPendingRequests() {
1073  for (PendingRequests::iterator it = pending_requests_.begin();
1074       it != pending_requests_.end();
1075       ++it) {
1076    PacRequest* req = it->get();
1077    if (req->is_started()) {
1078      req->CancelResolveJob();
1079
1080      req->net_log()->BeginEvent(
1081          NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC);
1082    }
1083  }
1084}
1085
1086void ProxyService::SetReady() {
1087  DCHECK(!init_proxy_resolver_.get());
1088  current_state_ = STATE_READY;
1089
1090  // Make a copy in case |this| is deleted during the synchronous completion
1091  // of one of the requests. If |this| is deleted then all of the PacRequest
1092  // instances will be Cancel()-ed.
1093  PendingRequests pending_copy = pending_requests_;
1094
1095  for (PendingRequests::iterator it = pending_copy.begin();
1096       it != pending_copy.end();
1097       ++it) {
1098    PacRequest* req = it->get();
1099    if (!req->is_started() && !req->was_cancelled()) {
1100      req->net_log()->EndEvent(NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC);
1101
1102      // Note that we re-check for synchronous completion, in case we are
1103      // no longer using a ProxyResolver (can happen if we fell-back to manual).
1104      req->StartAndCompleteCheckingForSynchronous();
1105    }
1106  }
1107}
1108
1109void ProxyService::ApplyProxyConfigIfAvailable() {
1110  DCHECK_EQ(STATE_NONE, current_state_);
1111
1112  config_service_->OnLazyPoll();
1113
1114  // If we have already fetched the configuration, start applying it.
1115  if (fetched_config_.is_valid()) {
1116    InitializeUsingLastFetchedConfig();
1117    return;
1118  }
1119
1120  // Otherwise we need to first fetch the configuration.
1121  current_state_ = STATE_WAITING_FOR_PROXY_CONFIG;
1122
1123  // Retrieve the current proxy configuration from the ProxyConfigService.
1124  // If a configuration is not available yet, we will get called back later
1125  // by our ProxyConfigService::Observer once it changes.
1126  ProxyConfig config;
1127  ProxyConfigService::ConfigAvailability availability =
1128      config_service_->GetLatestProxyConfig(&config);
1129  if (availability != ProxyConfigService::CONFIG_PENDING)
1130    OnProxyConfigChanged(config, availability);
1131}
1132
1133void ProxyService::OnInitProxyResolverComplete(int result) {
1134  DCHECK_EQ(STATE_WAITING_FOR_INIT_PROXY_RESOLVER, current_state_);
1135  DCHECK(init_proxy_resolver_.get());
1136  DCHECK(fetched_config_.HasAutomaticSettings());
1137  config_ = init_proxy_resolver_->effective_config();
1138
1139  // At this point we have decided which proxy settings to use (i.e. which PAC
1140  // script if any). We start up a background poller to periodically revisit
1141  // this decision. If the contents of the PAC script change, or if the
1142  // result of proxy auto-discovery changes, this poller will notice it and
1143  // will trigger a re-initialization using the newly discovered PAC.
1144  script_poller_.reset(new ProxyScriptDeciderPoller(
1145      base::Bind(&ProxyService::InitializeUsingDecidedConfig,
1146                 base::Unretained(this)),
1147      fetched_config_,
1148      resolver_->expects_pac_bytes(),
1149      proxy_script_fetcher_.get(),
1150      dhcp_proxy_script_fetcher_.get(),
1151      result,
1152      init_proxy_resolver_->script_data(),
1153      NULL));
1154  script_poller_->set_quick_check_enabled(quick_check_enabled_);
1155
1156  init_proxy_resolver_.reset();
1157
1158  if (result != OK) {
1159    if (fetched_config_.pac_mandatory()) {
1160      VLOG(1) << "Failed configuring with mandatory PAC script, blocking all "
1161                 "traffic.";
1162      config_ = fetched_config_;
1163      result = ERR_MANDATORY_PROXY_CONFIGURATION_FAILED;
1164    } else {
1165      VLOG(1) << "Failed configuring with PAC script, falling-back to manual "
1166                 "proxy servers.";
1167      config_ = fetched_config_;
1168      config_.ClearAutomaticSettings();
1169      result = OK;
1170    }
1171  }
1172  permanent_error_ = result;
1173
1174  // TODO(eroman): Make this ID unique in the case where configuration changed
1175  //               due to ProxyScriptDeciderPoller.
1176  config_.set_id(fetched_config_.id());
1177  config_.set_source(fetched_config_.source());
1178
1179  // Resume any requests which we had to defer until the PAC script was
1180  // downloaded.
1181  SetReady();
1182}
1183
1184int ProxyService::ReconsiderProxyAfterError(const GURL& url,
1185                                            int load_flags,
1186                                            int net_error,
1187                                            ProxyInfo* result,
1188                                            const CompletionCallback& callback,
1189                                            PacRequest** pac_request,
1190                                            NetworkDelegate* network_delegate,
1191                                            const BoundNetLog& net_log) {
1192  DCHECK(CalledOnValidThread());
1193
1194  // Check to see if we have a new config since ResolveProxy was called.  We
1195  // want to re-run ResolveProxy in two cases: 1) we have a new config, or 2) a
1196  // direct connection failed and we never tried the current config.
1197
1198  DCHECK(result);
1199  bool re_resolve = result->config_id_ != config_.id();
1200
1201  if (re_resolve) {
1202    // If we have a new config or the config was never tried, we delete the
1203    // list of bad proxies and we try again.
1204    proxy_retry_info_.clear();
1205    return ResolveProxy(url, load_flags, result, callback, pac_request,
1206                        network_delegate, net_log);
1207  }
1208
1209  DCHECK(!result->is_empty());
1210  ProxyServer bad_proxy = result->proxy_server();
1211
1212  // We don't have new proxy settings to try, try to fallback to the next proxy
1213  // in the list.
1214  bool did_fallback = result->Fallback(net_error, net_log);
1215
1216  // Return synchronous failure if there is nothing left to fall-back to.
1217  // TODO(eroman): This is a yucky API, clean it up.
1218  return did_fallback ? OK : ERR_FAILED;
1219}
1220
1221bool ProxyService::MarkProxiesAsBadUntil(
1222    const ProxyInfo& result,
1223    base::TimeDelta retry_delay,
1224    const ProxyServer& another_bad_proxy,
1225    const BoundNetLog& net_log) {
1226  result.proxy_list_.UpdateRetryInfoOnFallback(&proxy_retry_info_,
1227                                               retry_delay,
1228                                               false,
1229                                               another_bad_proxy,
1230                                               OK,
1231                                               net_log);
1232  if (another_bad_proxy.is_valid())
1233    return result.proxy_list_.size() > 2;
1234  else
1235    return result.proxy_list_.size() > 1;
1236}
1237
1238void ProxyService::ReportSuccess(const ProxyInfo& result,
1239                                 NetworkDelegate* network_delegate) {
1240  DCHECK(CalledOnValidThread());
1241
1242  const ProxyRetryInfoMap& new_retry_info = result.proxy_retry_info();
1243  if (new_retry_info.empty())
1244    return;
1245
1246  for (ProxyRetryInfoMap::const_iterator iter = new_retry_info.begin();
1247       iter != new_retry_info.end(); ++iter) {
1248    ProxyRetryInfoMap::iterator existing = proxy_retry_info_.find(iter->first);
1249    if (existing == proxy_retry_info_.end()) {
1250      proxy_retry_info_[iter->first] = iter->second;
1251      if (network_delegate) {
1252        const ProxyServer& bad_proxy =
1253            ProxyServer::FromURI(iter->first, ProxyServer::SCHEME_HTTP);
1254        const ProxyRetryInfo& proxy_retry_info = iter->second;
1255        network_delegate->NotifyProxyFallback(bad_proxy,
1256                                              proxy_retry_info.net_error);
1257      }
1258    }
1259    else if (existing->second.bad_until < iter->second.bad_until)
1260      existing->second.bad_until = iter->second.bad_until;
1261  }
1262  if (net_log_) {
1263    net_log_->AddGlobalEntry(
1264        NetLog::TYPE_BAD_PROXY_LIST_REPORTED,
1265        base::Bind(&NetLogBadProxyListCallback, &new_retry_info));
1266  }
1267}
1268
1269void ProxyService::CancelPacRequest(PacRequest* req) {
1270  DCHECK(CalledOnValidThread());
1271  DCHECK(req);
1272  req->Cancel();
1273  RemovePendingRequest(req);
1274}
1275
1276LoadState ProxyService::GetLoadState(const PacRequest* req) const {
1277  CHECK(req);
1278  if (current_state_ == STATE_WAITING_FOR_INIT_PROXY_RESOLVER)
1279    return init_proxy_resolver_->GetLoadState();
1280  return req->GetLoadState();
1281}
1282
1283bool ProxyService::ContainsPendingRequest(PacRequest* req) {
1284  PendingRequests::iterator it = std::find(
1285      pending_requests_.begin(), pending_requests_.end(), req);
1286  return pending_requests_.end() != it;
1287}
1288
1289void ProxyService::RemovePendingRequest(PacRequest* req) {
1290  DCHECK(ContainsPendingRequest(req));
1291  PendingRequests::iterator it = std::find(
1292      pending_requests_.begin(), pending_requests_.end(), req);
1293  pending_requests_.erase(it);
1294}
1295
1296int ProxyService::DidFinishResolvingProxy(const GURL& url,
1297                                          int load_flags,
1298                                          NetworkDelegate* network_delegate,
1299                                          ProxyInfo* result,
1300                                          int result_code,
1301                                          const BoundNetLog& net_log) {
1302  // Log the result of the proxy resolution.
1303  if (result_code == OK) {
1304    // Allow the network delegate to interpose on the resolution decision,
1305    // possibly modifying the ProxyInfo.
1306    if (network_delegate)
1307      network_delegate->NotifyResolveProxy(url, load_flags, *this, result);
1308
1309    // When logging all events is enabled, dump the proxy list.
1310    if (net_log.IsLogging()) {
1311      net_log.AddEvent(
1312          NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST,
1313          base::Bind(&NetLogFinishedResolvingProxyCallback, result));
1314    }
1315    result->DeprioritizeBadProxies(proxy_retry_info_);
1316  } else {
1317    net_log.AddEventWithNetErrorCode(
1318        NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST, result_code);
1319
1320    if (!config_.pac_mandatory()) {
1321      // Fall-back to direct when the proxy resolver fails. This corresponds
1322      // with a javascript runtime error in the PAC script.
1323      //
1324      // This implicit fall-back to direct matches Firefox 3.5 and
1325      // Internet Explorer 8. For more information, see:
1326      //
1327      // http://www.chromium.org/developers/design-documents/proxy-settings-fallback
1328      result->UseDirect();
1329      result_code = OK;
1330
1331      // Allow the network delegate to interpose on the resolution decision,
1332      // possibly modifying the ProxyInfo.
1333      if (network_delegate)
1334        network_delegate->NotifyResolveProxy(url, load_flags, *this, result);
1335    } else {
1336      result_code = ERR_MANDATORY_PROXY_CONFIGURATION_FAILED;
1337    }
1338  }
1339
1340  net_log.EndEvent(NetLog::TYPE_PROXY_SERVICE);
1341  return result_code;
1342}
1343
1344void ProxyService::SetProxyScriptFetchers(
1345    ProxyScriptFetcher* proxy_script_fetcher,
1346    DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher) {
1347  DCHECK(CalledOnValidThread());
1348  State previous_state = ResetProxyConfig(false);
1349  proxy_script_fetcher_.reset(proxy_script_fetcher);
1350  dhcp_proxy_script_fetcher_.reset(dhcp_proxy_script_fetcher);
1351  if (previous_state != STATE_NONE)
1352    ApplyProxyConfigIfAvailable();
1353}
1354
1355ProxyScriptFetcher* ProxyService::GetProxyScriptFetcher() const {
1356  DCHECK(CalledOnValidThread());
1357  return proxy_script_fetcher_.get();
1358}
1359
1360ProxyService::State ProxyService::ResetProxyConfig(bool reset_fetched_config) {
1361  DCHECK(CalledOnValidThread());
1362  State previous_state = current_state_;
1363
1364  permanent_error_ = OK;
1365  proxy_retry_info_.clear();
1366  script_poller_.reset();
1367  init_proxy_resolver_.reset();
1368  SuspendAllPendingRequests();
1369  config_ = ProxyConfig();
1370  if (reset_fetched_config)
1371    fetched_config_ = ProxyConfig();
1372  current_state_ = STATE_NONE;
1373
1374  return previous_state;
1375}
1376
1377void ProxyService::ResetConfigService(
1378    ProxyConfigService* new_proxy_config_service) {
1379  DCHECK(CalledOnValidThread());
1380  State previous_state = ResetProxyConfig(true);
1381
1382  // Release the old configuration service.
1383  if (config_service_.get())
1384    config_service_->RemoveObserver(this);
1385
1386  // Set the new configuration service.
1387  config_service_.reset(new_proxy_config_service);
1388  config_service_->AddObserver(this);
1389
1390  if (previous_state != STATE_NONE)
1391    ApplyProxyConfigIfAvailable();
1392}
1393
1394void ProxyService::ForceReloadProxyConfig() {
1395  DCHECK(CalledOnValidThread());
1396  ResetProxyConfig(false);
1397  ApplyProxyConfigIfAvailable();
1398}
1399
1400// static
1401ProxyConfigService* ProxyService::CreateSystemProxyConfigService(
1402    const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
1403    const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner) {
1404#if defined(OS_WIN)
1405  return new ProxyConfigServiceWin();
1406#elif defined(OS_IOS)
1407  return new ProxyConfigServiceIOS();
1408#elif defined(OS_MACOSX)
1409  return new ProxyConfigServiceMac(io_task_runner);
1410#elif defined(OS_CHROMEOS)
1411  LOG(ERROR) << "ProxyConfigService for ChromeOS should be created in "
1412             << "profile_io_data.cc::CreateProxyConfigService and this should "
1413             << "be used only for examples.";
1414  return new UnsetProxyConfigService;
1415#elif defined(OS_LINUX)
1416  ProxyConfigServiceLinux* linux_config_service =
1417      new ProxyConfigServiceLinux();
1418
1419  // Assume we got called on the thread that runs the default glib
1420  // main loop, so the current thread is where we should be running
1421  // gconf calls from.
1422  scoped_refptr<base::SingleThreadTaskRunner> glib_thread_task_runner =
1423      base::ThreadTaskRunnerHandle::Get();
1424
1425  // Synchronously fetch the current proxy config (since we are running on
1426  // glib_default_loop). Additionally register for notifications (delivered in
1427  // either |glib_default_loop| or |file_task_runner|) to keep us updated when
1428  // the proxy config changes.
1429  linux_config_service->SetupAndFetchInitialConfig(
1430      glib_thread_task_runner, io_task_runner, file_task_runner);
1431
1432  return linux_config_service;
1433#elif defined(OS_ANDROID)
1434  return new ProxyConfigServiceAndroid(
1435      io_task_runner, base::MessageLoop::current()->message_loop_proxy());
1436#else
1437  LOG(WARNING) << "Failed to choose a system proxy settings fetcher "
1438                  "for this platform.";
1439  return new ProxyConfigServiceDirect();
1440#endif
1441}
1442
1443// static
1444const ProxyService::PacPollPolicy* ProxyService::set_pac_script_poll_policy(
1445    const PacPollPolicy* policy) {
1446  return ProxyScriptDeciderPoller::set_policy(policy);
1447}
1448
1449// static
1450scoped_ptr<ProxyService::PacPollPolicy>
1451  ProxyService::CreateDefaultPacPollPolicy() {
1452  return scoped_ptr<PacPollPolicy>(new DefaultPollPolicy());
1453}
1454
1455void ProxyService::OnProxyConfigChanged(
1456    const ProxyConfig& config,
1457    ProxyConfigService::ConfigAvailability availability) {
1458  // Retrieve the current proxy configuration from the ProxyConfigService.
1459  // If a configuration is not available yet, we will get called back later
1460  // by our ProxyConfigService::Observer once it changes.
1461  ProxyConfig effective_config;
1462  switch (availability) {
1463    case ProxyConfigService::CONFIG_PENDING:
1464      // ProxyConfigService implementors should never pass CONFIG_PENDING.
1465      NOTREACHED() << "Proxy config change with CONFIG_PENDING availability!";
1466      return;
1467    case ProxyConfigService::CONFIG_VALID:
1468      effective_config = config;
1469      break;
1470    case ProxyConfigService::CONFIG_UNSET:
1471      effective_config = ProxyConfig::CreateDirect();
1472      break;
1473  }
1474
1475  // Emit the proxy settings change to the NetLog stream.
1476  if (net_log_) {
1477    net_log_->AddGlobalEntry(
1478        net::NetLog::TYPE_PROXY_CONFIG_CHANGED,
1479        base::Bind(&NetLogProxyConfigChangedCallback,
1480                   &fetched_config_, &effective_config));
1481  }
1482
1483  // Set the new configuration as the most recently fetched one.
1484  fetched_config_ = effective_config;
1485  fetched_config_.set_id(1);  // Needed for a later DCHECK of is_valid().
1486
1487  InitializeUsingLastFetchedConfig();
1488}
1489
1490void ProxyService::InitializeUsingLastFetchedConfig() {
1491  ResetProxyConfig(false);
1492
1493  DCHECK(fetched_config_.is_valid());
1494
1495  // Increment the ID to reflect that the config has changed.
1496  fetched_config_.set_id(next_config_id_++);
1497
1498  if (!fetched_config_.HasAutomaticSettings()) {
1499    config_ = fetched_config_;
1500    SetReady();
1501    return;
1502  }
1503
1504  // Start downloading + testing the PAC scripts for this new configuration.
1505  current_state_ = STATE_WAITING_FOR_INIT_PROXY_RESOLVER;
1506
1507  // If we changed networks recently, we should delay running proxy auto-config.
1508  TimeDelta wait_delay =
1509      stall_proxy_autoconfig_until_ - TimeTicks::Now();
1510
1511  init_proxy_resolver_.reset(new InitProxyResolver());
1512  init_proxy_resolver_->set_quick_check_enabled(quick_check_enabled_);
1513  int rv = init_proxy_resolver_->Start(
1514      resolver_.get(),
1515      proxy_script_fetcher_.get(),
1516      dhcp_proxy_script_fetcher_.get(),
1517      net_log_,
1518      fetched_config_,
1519      wait_delay,
1520      base::Bind(&ProxyService::OnInitProxyResolverComplete,
1521                 base::Unretained(this)));
1522
1523  if (rv != ERR_IO_PENDING)
1524    OnInitProxyResolverComplete(rv);
1525}
1526
1527void ProxyService::InitializeUsingDecidedConfig(
1528    int decider_result,
1529    ProxyResolverScriptData* script_data,
1530    const ProxyConfig& effective_config) {
1531  DCHECK(fetched_config_.is_valid());
1532  DCHECK(fetched_config_.HasAutomaticSettings());
1533
1534  ResetProxyConfig(false);
1535
1536  current_state_ = STATE_WAITING_FOR_INIT_PROXY_RESOLVER;
1537
1538  init_proxy_resolver_.reset(new InitProxyResolver());
1539  int rv = init_proxy_resolver_->StartSkipDecider(
1540      resolver_.get(),
1541      effective_config,
1542      decider_result,
1543      script_data,
1544      base::Bind(&ProxyService::OnInitProxyResolverComplete,
1545                 base::Unretained(this)));
1546
1547  if (rv != ERR_IO_PENDING)
1548    OnInitProxyResolverComplete(rv);
1549}
1550
1551void ProxyService::OnIPAddressChanged() {
1552  // See the comment block by |kDelayAfterNetworkChangesMs| for info.
1553  stall_proxy_autoconfig_until_ =
1554      TimeTicks::Now() + stall_proxy_auto_config_delay_;
1555
1556  State previous_state = ResetProxyConfig(false);
1557  if (previous_state != STATE_NONE)
1558    ApplyProxyConfigIfAvailable();
1559}
1560
1561void ProxyService::OnDNSChanged() {
1562  OnIPAddressChanged();
1563}
1564
1565}  // namespace net
1566