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