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