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