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