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