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