Home | History | Annotate | Download | only in proxy
      1 // Copyright (c) 2011 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/compiler_specific.h"
     10 #include "base/logging.h"
     11 #include "base/message_loop.h"
     12 #include "base/string_util.h"
     13 #include "base/values.h"
     14 #include "googleurl/src/gurl.h"
     15 #include "net/base/net_errors.h"
     16 #include "net/base/net_log.h"
     17 #include "net/base/net_util.h"
     18 #include "net/proxy/init_proxy_resolver.h"
     19 #include "net/proxy/multi_threaded_proxy_resolver.h"
     20 #include "net/proxy/proxy_config_service_fixed.h"
     21 #include "net/proxy/proxy_resolver.h"
     22 #include "net/proxy/proxy_resolver_js_bindings.h"
     23 #ifndef ANDROID
     24 #include "net/proxy/proxy_resolver_v8.h"
     25 #endif
     26 #include "net/proxy/proxy_script_fetcher.h"
     27 #include "net/proxy/sync_host_resolver_bridge.h"
     28 #include "net/url_request/url_request_context.h"
     29 
     30 #if defined(OS_WIN)
     31 #include "net/proxy/proxy_config_service_win.h"
     32 #include "net/proxy/proxy_resolver_winhttp.h"
     33 #elif defined(OS_MACOSX)
     34 #include "net/proxy/proxy_config_service_mac.h"
     35 #include "net/proxy/proxy_resolver_mac.h"
     36 #elif defined(OS_LINUX) && !defined(OS_CHROMEOS)
     37 #include "net/proxy/proxy_config_service_linux.h"
     38 #endif
     39 
     40 using base::TimeDelta;
     41 using base::TimeTicks;
     42 
     43 namespace net {
     44 
     45 namespace {
     46 
     47 const size_t kMaxNumNetLogEntries = 100;
     48 const size_t kDefaultNumPacThreads = 4;
     49 
     50 // When the IP address changes we don't immediately re-run proxy auto-config.
     51 // Instead, we  wait for |kNumMillisToStallAfterNetworkChanges| before
     52 // attempting to re-valuate proxy auto-config.
     53 //
     54 // During this time window, any resolve requests sent to the ProxyService will
     55 // be queued. Once we have waited the required amount of them, the proxy
     56 // auto-config step will be run, and the queued requests resumed.
     57 //
     58 // The reason we play this game is that our signal for detecting network
     59 // changes (NetworkChangeNotifier) may fire *before* the system's networking
     60 // dependencies are fully configured. This is a problem since it means if
     61 // we were to run proxy auto-config right away, it could fail due to spurious
     62 // DNS failures. (see http://crbug.com/50779 for more details.)
     63 //
     64 // By adding the wait window, we give things a chance to get properly set up.
     65 // Now by the time we run the proxy-autoconfig there is a lower chance of
     66 // getting transient DNS / connect failures.
     67 //
     68 // Admitedly this is a hack. Ideally we would have NetworkChangeNotifier
     69 // deliver a reliable signal indicating that the network has changed AND is
     70 // ready for action... But until then, we can reduce the likelihood of users
     71 // getting wedged because of proxy detection failures on network switch.
     72 //
     73 // The obvious downside to this strategy is it introduces an additional
     74 // latency when switching networks. This delay shouldn't be too disruptive
     75 // assuming network switches are infrequent and user initiated. However if
     76 // NetworkChangeNotifier delivers network changes more frequently this could
     77 // cause jankiness. (NetworkChangeNotifier broadcasts a change event when ANY
     78 // interface goes up/down. So in theory if the non-primary interface were
     79 // hopping on and off wireless networks our constant delayed reconfiguration
     80 // could add noticeable jank.)
     81 //
     82 // The specific hard-coded wait time below is arbitrary.
     83 // Basically I ran some experiments switching between wireless networks on
     84 // a Linux Ubuntu (Lucid) laptop, and experimentally found this timeout fixes
     85 // things. It is entirely possible that the value is insuficient for other
     86 // setups.
     87 const int64 kNumMillisToStallAfterNetworkChanges = 2000;
     88 
     89 // Config getter that always returns direct settings.
     90 class ProxyConfigServiceDirect : public ProxyConfigService {
     91  public:
     92   // ProxyConfigService implementation:
     93   virtual void AddObserver(Observer* observer) {}
     94   virtual void RemoveObserver(Observer* observer) {}
     95   virtual ConfigAvailability GetLatestProxyConfig(ProxyConfig* config) {
     96     *config = ProxyConfig::CreateDirect();
     97     return CONFIG_VALID;
     98   }
     99 };
    100 
    101 // Proxy resolver that fails every time.
    102 class ProxyResolverNull : public ProxyResolver {
    103  public:
    104   ProxyResolverNull() : ProxyResolver(false /*expects_pac_bytes*/) {}
    105 
    106   // ProxyResolver implementation:
    107   virtual int GetProxyForURL(const GURL& url,
    108                              ProxyInfo* results,
    109                              CompletionCallback* callback,
    110                              RequestHandle* request,
    111                              const BoundNetLog& net_log) {
    112     return ERR_NOT_IMPLEMENTED;
    113   }
    114 
    115   virtual void CancelRequest(RequestHandle request) {
    116     NOTREACHED();
    117   }
    118 
    119   virtual void CancelSetPacScript() {
    120     NOTREACHED();
    121   }
    122 
    123   virtual int SetPacScript(
    124       const scoped_refptr<ProxyResolverScriptData>& /*script_data*/,
    125       CompletionCallback* /*callback*/) {
    126     return ERR_NOT_IMPLEMENTED;
    127   }
    128 };
    129 
    130 // ProxyResolver that simulates a PAC script which returns
    131 // |pac_string| for every single URL.
    132 class ProxyResolverFromPacString : public ProxyResolver {
    133  public:
    134   ProxyResolverFromPacString(const std::string& pac_string)
    135       : ProxyResolver(false /*expects_pac_bytes*/),
    136         pac_string_(pac_string) {}
    137 
    138   virtual int GetProxyForURL(const GURL& url,
    139                              ProxyInfo* results,
    140                              CompletionCallback* callback,
    141                              RequestHandle* request,
    142                              const BoundNetLog& net_log) {
    143     results->UsePacString(pac_string_);
    144     return OK;
    145   }
    146 
    147   virtual void CancelRequest(RequestHandle request) {
    148     NOTREACHED();
    149   }
    150 
    151   virtual void CancelSetPacScript() {
    152     NOTREACHED();
    153   }
    154 
    155   virtual int SetPacScript(
    156       const scoped_refptr<ProxyResolverScriptData>& pac_script,
    157       CompletionCallback* callback) {
    158     return OK;
    159   }
    160 
    161  private:
    162   const std::string pac_string_;
    163 };
    164 
    165 #ifndef ANDROID
    166 // This factory creates V8ProxyResolvers with appropriate javascript bindings.
    167 class ProxyResolverFactoryForV8 : public ProxyResolverFactory {
    168  public:
    169   // |async_host_resolver|, |io_loop| and |net_log| must remain
    170   // valid for the duration of our lifetime.
    171   // |async_host_resolver| will only be operated on |io_loop|.
    172   ProxyResolverFactoryForV8(HostResolver* async_host_resolver,
    173                             MessageLoop* io_loop,
    174                             NetLog* net_log)
    175       : ProxyResolverFactory(true /*expects_pac_bytes*/),
    176         async_host_resolver_(async_host_resolver),
    177         io_loop_(io_loop),
    178         net_log_(net_log) {
    179   }
    180 
    181   virtual ProxyResolver* CreateProxyResolver() {
    182     // Create a synchronous host resolver wrapper that operates
    183     // |async_host_resolver_| on |io_loop_|.
    184     SyncHostResolverBridge* sync_host_resolver =
    185         new SyncHostResolverBridge(async_host_resolver_, io_loop_);
    186 
    187     ProxyResolverJSBindings* js_bindings =
    188         ProxyResolverJSBindings::CreateDefault(sync_host_resolver, net_log_);
    189 
    190     // ProxyResolverV8 takes ownership of |js_bindings|.
    191     return new ProxyResolverV8(js_bindings);
    192   }
    193 
    194  private:
    195   HostResolver* const async_host_resolver_;
    196   MessageLoop* io_loop_;
    197   NetLog* net_log_;
    198 };
    199 #endif
    200 
    201 // Creates ProxyResolvers using a platform-specific implementation.
    202 class ProxyResolverFactoryForSystem : public ProxyResolverFactory {
    203  public:
    204   ProxyResolverFactoryForSystem()
    205       : ProxyResolverFactory(false /*expects_pac_bytes*/) {}
    206 
    207   virtual ProxyResolver* CreateProxyResolver() {
    208     DCHECK(IsSupported());
    209 #if defined(OS_WIN)
    210     return new ProxyResolverWinHttp();
    211 #elif defined(OS_MACOSX)
    212     return new ProxyResolverMac();
    213 #else
    214     NOTREACHED();
    215     return NULL;
    216 #endif
    217   }
    218 
    219   static bool IsSupported() {
    220 #if defined(OS_WIN) || defined(OS_MACOSX)
    221     return true;
    222 #else
    223     return false;
    224 #endif
    225   }
    226 };
    227 
    228 // NetLog parameter to describe a proxy configuration change.
    229 class ProxyConfigChangedNetLogParam : public NetLog::EventParameters {
    230  public:
    231   ProxyConfigChangedNetLogParam(const ProxyConfig& old_config,
    232                                 const ProxyConfig& new_config)
    233       : old_config_(old_config),
    234         new_config_(new_config) {
    235   }
    236 
    237   virtual Value* ToValue() const {
    238     DictionaryValue* dict = new DictionaryValue();
    239     // The "old_config" is optional -- the first notification will not have
    240     // any "previous" configuration.
    241     if (old_config_.is_valid())
    242       dict->Set("old_config", old_config_.ToValue());
    243     dict->Set("new_config", new_config_.ToValue());
    244     return dict;
    245   }
    246 
    247  private:
    248   const ProxyConfig old_config_;
    249   const ProxyConfig new_config_;
    250   DISALLOW_COPY_AND_ASSIGN(ProxyConfigChangedNetLogParam);
    251 };
    252 
    253 }  // namespace
    254 
    255 // ProxyService::PacRequest ---------------------------------------------------
    256 
    257 class ProxyService::PacRequest
    258     : public base::RefCounted<ProxyService::PacRequest> {
    259  public:
    260   PacRequest(ProxyService* service,
    261              const GURL& url,
    262              ProxyInfo* results,
    263              CompletionCallback* user_callback,
    264              const BoundNetLog& net_log)
    265       : service_(service),
    266         user_callback_(user_callback),
    267         ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_(
    268             this, &PacRequest::QueryComplete)),
    269         results_(results),
    270         url_(url),
    271         resolve_job_(NULL),
    272         config_id_(ProxyConfig::INVALID_ID),
    273         net_log_(net_log) {
    274     DCHECK(user_callback);
    275   }
    276 
    277   // Starts the resolve proxy request.
    278   int Start() {
    279     DCHECK(!was_cancelled());
    280     DCHECK(!is_started());
    281 
    282     DCHECK(service_->config_.is_valid());
    283 
    284     config_id_ = service_->config_.id();
    285 
    286     return resolver()->GetProxyForURL(
    287         url_, results_, &io_callback_, &resolve_job_, net_log_);
    288   }
    289 
    290   bool is_started() const {
    291     // Note that !! casts to bool. (VS gives a warning otherwise).
    292     return !!resolve_job_;
    293   }
    294 
    295   void StartAndCompleteCheckingForSynchronous() {
    296     int rv = service_->TryToCompleteSynchronously(url_, results_);
    297     if (rv == ERR_IO_PENDING)
    298       rv = Start();
    299     if (rv != ERR_IO_PENDING)
    300       QueryComplete(rv);
    301   }
    302 
    303   void CancelResolveJob() {
    304     DCHECK(is_started());
    305     // The request may already be running in the resolver.
    306     resolver()->CancelRequest(resolve_job_);
    307     resolve_job_ = NULL;
    308     DCHECK(!is_started());
    309   }
    310 
    311   void Cancel() {
    312     net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL);
    313 
    314     if (is_started())
    315       CancelResolveJob();
    316 
    317     // Mark as cancelled, to prevent accessing this again later.
    318     service_ = NULL;
    319     user_callback_ = NULL;
    320     results_ = NULL;
    321 
    322     net_log_.EndEvent(NetLog::TYPE_PROXY_SERVICE, NULL);
    323   }
    324 
    325   // Returns true if Cancel() has been called.
    326   bool was_cancelled() const { return user_callback_ == NULL; }
    327 
    328   // Helper to call after ProxyResolver completion (both synchronous and
    329   // asynchronous). Fixes up the result that is to be returned to user.
    330   int QueryDidComplete(int result_code) {
    331     DCHECK(!was_cancelled());
    332 
    333     // Make a note in the results which configuration was in use at the
    334     // time of the resolve.
    335     results_->config_id_ = config_id_;
    336 
    337     // Reset the state associated with in-progress-resolve.
    338     resolve_job_ = NULL;
    339     config_id_ = ProxyConfig::INVALID_ID;
    340 
    341     return service_->DidFinishResolvingProxy(results_, result_code, net_log_);
    342   }
    343 
    344   BoundNetLog* net_log() { return &net_log_; }
    345 
    346  private:
    347   friend class base::RefCounted<ProxyService::PacRequest>;
    348 
    349   ~PacRequest() {}
    350 
    351   // Callback for when the ProxyResolver request has completed.
    352   void QueryComplete(int result_code) {
    353     result_code = QueryDidComplete(result_code);
    354 
    355     // Remove this completed PacRequest from the service's pending list.
    356     /// (which will probably cause deletion of |this|).
    357     CompletionCallback* callback = user_callback_;
    358     service_->RemovePendingRequest(this);
    359 
    360     callback->Run(result_code);
    361   }
    362 
    363   ProxyResolver* resolver() const { return service_->resolver_.get(); }
    364 
    365   // Note that we don't hold a reference to the ProxyService. Outstanding
    366   // requests are cancelled during ~ProxyService, so this is guaranteed
    367   // to be valid throughout our lifetime.
    368   ProxyService* service_;
    369   CompletionCallback* user_callback_;
    370   CompletionCallbackImpl<PacRequest> io_callback_;
    371   ProxyInfo* results_;
    372   GURL url_;
    373   ProxyResolver::RequestHandle resolve_job_;
    374   ProxyConfig::ID config_id_;  // The config id when the resolve was started.
    375   BoundNetLog net_log_;
    376 };
    377 
    378 // ProxyService ---------------------------------------------------------------
    379 
    380 ProxyService::ProxyService(ProxyConfigService* config_service,
    381                            ProxyResolver* resolver,
    382                            NetLog* net_log)
    383     : resolver_(resolver),
    384       next_config_id_(1),
    385       ALLOW_THIS_IN_INITIALIZER_LIST(init_proxy_resolver_callback_(
    386           this, &ProxyService::OnInitProxyResolverComplete)),
    387       current_state_(STATE_NONE) ,
    388       net_log_(net_log),
    389       stall_proxy_auto_config_delay_(
    390           base::TimeDelta::FromMilliseconds(
    391               kNumMillisToStallAfterNetworkChanges)) {
    392   NetworkChangeNotifier::AddIPAddressObserver(this);
    393   ResetConfigService(config_service);
    394 }
    395 
    396 #ifndef ANDROID
    397 // static
    398 ProxyService* ProxyService::CreateUsingV8ProxyResolver(
    399     ProxyConfigService* proxy_config_service,
    400     size_t num_pac_threads,
    401     ProxyScriptFetcher* proxy_script_fetcher,
    402     HostResolver* host_resolver,
    403     NetLog* net_log) {
    404   DCHECK(proxy_config_service);
    405   DCHECK(proxy_script_fetcher);
    406   DCHECK(host_resolver);
    407 
    408   if (num_pac_threads == 0)
    409     num_pac_threads = kDefaultNumPacThreads;
    410 
    411   ProxyResolverFactory* sync_resolver_factory =
    412       new ProxyResolverFactoryForV8(
    413           host_resolver,
    414           MessageLoop::current(),
    415           net_log);
    416 
    417   ProxyResolver* proxy_resolver =
    418       new MultiThreadedProxyResolver(sync_resolver_factory, num_pac_threads);
    419 
    420   ProxyService* proxy_service =
    421       new ProxyService(proxy_config_service, proxy_resolver, net_log);
    422 
    423   // Configure PAC script downloads to be issued using |proxy_script_fetcher|.
    424   proxy_service->SetProxyScriptFetcher(proxy_script_fetcher);
    425 
    426   return proxy_service;
    427 }
    428 #endif
    429 
    430 // static
    431 ProxyService* ProxyService::CreateUsingSystemProxyResolver(
    432     ProxyConfigService* proxy_config_service,
    433     size_t num_pac_threads,
    434     NetLog* net_log) {
    435   DCHECK(proxy_config_service);
    436 
    437   if (!ProxyResolverFactoryForSystem::IsSupported()) {
    438     LOG(WARNING) << "PAC support disabled because there is no "
    439                     "system implementation";
    440     return CreateWithoutProxyResolver(proxy_config_service, net_log);
    441   }
    442 
    443   if (num_pac_threads == 0)
    444     num_pac_threads = kDefaultNumPacThreads;
    445 
    446   ProxyResolver* proxy_resolver = new MultiThreadedProxyResolver(
    447       new ProxyResolverFactoryForSystem(), num_pac_threads);
    448 
    449   return new ProxyService(proxy_config_service, proxy_resolver, net_log);
    450 }
    451 
    452 // static
    453 ProxyService* ProxyService::CreateWithoutProxyResolver(
    454     ProxyConfigService* proxy_config_service,
    455     NetLog* net_log) {
    456   return new ProxyService(proxy_config_service,
    457                           new ProxyResolverNull(),
    458                           net_log);
    459 }
    460 
    461 // static
    462 ProxyService* ProxyService::CreateFixed(const ProxyConfig& pc) {
    463   // TODO(eroman): This isn't quite right, won't work if |pc| specifies
    464   //               a PAC script.
    465   return CreateUsingSystemProxyResolver(new ProxyConfigServiceFixed(pc),
    466                                         0, NULL);
    467 }
    468 
    469 // static
    470 ProxyService* ProxyService::CreateFixed(const std::string& proxy) {
    471   net::ProxyConfig proxy_config;
    472   proxy_config.proxy_rules().ParseFromString(proxy);
    473   return ProxyService::CreateFixed(proxy_config);
    474 }
    475 
    476 // static
    477 ProxyService* ProxyService::CreateDirect() {
    478   return CreateDirectWithNetLog(NULL);
    479 }
    480 
    481 ProxyService* ProxyService::CreateDirectWithNetLog(NetLog* net_log) {
    482   // Use direct connections.
    483   return new ProxyService(new ProxyConfigServiceDirect, new ProxyResolverNull,
    484                           net_log);
    485 }
    486 
    487 // static
    488 ProxyService* ProxyService::CreateFixedFromPacResult(
    489     const std::string& pac_string) {
    490 
    491   // We need the settings to contain an "automatic" setting, otherwise the
    492   // ProxyResolver dependency we give it will never be used.
    493   scoped_ptr<ProxyConfigService> proxy_config_service(
    494       new ProxyConfigServiceFixed(ProxyConfig::CreateAutoDetect()));
    495 
    496   scoped_ptr<ProxyResolver> proxy_resolver(
    497       new ProxyResolverFromPacString(pac_string));
    498 
    499   return new ProxyService(proxy_config_service.release(),
    500                           proxy_resolver.release(),
    501                           NULL);
    502 }
    503 
    504 int ProxyService::ResolveProxy(const GURL& raw_url,
    505                                ProxyInfo* result,
    506                                CompletionCallback* callback,
    507                                PacRequest** pac_request,
    508                                const BoundNetLog& net_log) {
    509   DCHECK(CalledOnValidThread());
    510   DCHECK(callback);
    511 
    512   net_log.BeginEvent(NetLog::TYPE_PROXY_SERVICE, NULL);
    513 
    514   config_service_->OnLazyPoll();
    515   if (current_state_ == STATE_NONE)
    516     ApplyProxyConfigIfAvailable();
    517 
    518   // Strip away any reference fragments and the username/password, as they
    519   // are not relevant to proxy resolution.
    520   GURL url = SimplifyUrlForRequest(raw_url);
    521 
    522   // Check if the request can be completed right away. (This is the case when
    523   // using a direct connection for example).
    524   int rv = TryToCompleteSynchronously(url, result);
    525   if (rv != ERR_IO_PENDING)
    526     return DidFinishResolvingProxy(result, rv, net_log);
    527 
    528   scoped_refptr<PacRequest> req(
    529       new PacRequest(this, url, result, callback, net_log));
    530 
    531   if (current_state_ == STATE_READY) {
    532     // Start the resolve request.
    533     rv = req->Start();
    534     if (rv != ERR_IO_PENDING)
    535       return req->QueryDidComplete(rv);
    536   } else {
    537     req->net_log()->BeginEvent(NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC,
    538                                NULL);
    539   }
    540 
    541   DCHECK_EQ(ERR_IO_PENDING, rv);
    542   DCHECK(!ContainsPendingRequest(req));
    543   pending_requests_.push_back(req);
    544 
    545   // Completion will be notifed through |callback|, unless the caller cancels
    546   // the request using |pac_request|.
    547   if (pac_request)
    548     *pac_request = req.get();
    549   return rv;  // ERR_IO_PENDING
    550 }
    551 
    552 int ProxyService::TryToCompleteSynchronously(const GURL& url,
    553                                              ProxyInfo* result) {
    554   DCHECK_NE(STATE_NONE, current_state_);
    555 
    556   if (current_state_ != STATE_READY)
    557     return ERR_IO_PENDING;  // Still initializing.
    558 
    559   DCHECK_NE(config_.id(), ProxyConfig::INVALID_ID);
    560 
    561   if (config_.HasAutomaticSettings())
    562     return ERR_IO_PENDING;  // Must submit the request to the proxy resolver.
    563 
    564   // Use the manual proxy settings.
    565   config_.proxy_rules().Apply(url, result);
    566   result->config_id_ = config_.id();
    567   return OK;
    568 }
    569 
    570 ProxyService::~ProxyService() {
    571   NetworkChangeNotifier::RemoveIPAddressObserver(this);
    572   config_service_->RemoveObserver(this);
    573 
    574   // Cancel any inprogress requests.
    575   for (PendingRequests::iterator it = pending_requests_.begin();
    576        it != pending_requests_.end();
    577        ++it) {
    578     (*it)->Cancel();
    579   }
    580 }
    581 
    582 void ProxyService::SuspendAllPendingRequests() {
    583   for (PendingRequests::iterator it = pending_requests_.begin();
    584        it != pending_requests_.end();
    585        ++it) {
    586     PacRequest* req = it->get();
    587     if (req->is_started()) {
    588       req->CancelResolveJob();
    589 
    590       req->net_log()->BeginEvent(
    591           NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC, NULL);
    592     }
    593   }
    594 }
    595 
    596 void ProxyService::SetReady() {
    597   DCHECK(!init_proxy_resolver_.get());
    598   current_state_ = STATE_READY;
    599 
    600   // Make a copy in case |this| is deleted during the synchronous completion
    601   // of one of the requests. If |this| is deleted then all of the PacRequest
    602   // instances will be Cancel()-ed.
    603   PendingRequests pending_copy = pending_requests_;
    604 
    605   for (PendingRequests::iterator it = pending_copy.begin();
    606        it != pending_copy.end();
    607        ++it) {
    608     PacRequest* req = it->get();
    609     if (!req->is_started() && !req->was_cancelled()) {
    610       req->net_log()->EndEvent(NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC,
    611                                NULL);
    612 
    613       // Note that we re-check for synchronous completion, in case we are
    614       // no longer using a ProxyResolver (can happen if we fell-back to manual).
    615       req->StartAndCompleteCheckingForSynchronous();
    616     }
    617   }
    618 }
    619 
    620 void ProxyService::ApplyProxyConfigIfAvailable() {
    621   DCHECK_EQ(STATE_NONE, current_state_);
    622 
    623   config_service_->OnLazyPoll();
    624 
    625   // If we have already fetched the configuration, start applying it.
    626   if (fetched_config_.is_valid()) {
    627     InitializeUsingLastFetchedConfig();
    628     return;
    629   }
    630 
    631   // Otherwise we need to first fetch the configuration.
    632   current_state_ = STATE_WAITING_FOR_PROXY_CONFIG;
    633 
    634   // Retrieve the current proxy configuration from the ProxyConfigService.
    635   // If a configuration is not available yet, we will get called back later
    636   // by our ProxyConfigService::Observer once it changes.
    637   ProxyConfig config;
    638   ProxyConfigService::ConfigAvailability availability =
    639       config_service_->GetLatestProxyConfig(&config);
    640   if (availability != ProxyConfigService::CONFIG_PENDING)
    641     OnProxyConfigChanged(config, availability);
    642 }
    643 
    644 void ProxyService::OnInitProxyResolverComplete(int result) {
    645   DCHECK_EQ(STATE_WAITING_FOR_INIT_PROXY_RESOLVER, current_state_);
    646   DCHECK(init_proxy_resolver_.get());
    647   DCHECK(fetched_config_.HasAutomaticSettings());
    648   init_proxy_resolver_.reset();
    649 
    650   if (result != OK) {
    651     VLOG(1) << "Failed configuring with PAC script, falling-back to manual "
    652                "proxy servers.";
    653     config_ = fetched_config_;
    654     config_.ClearAutomaticSettings();
    655   }
    656 
    657   config_.set_id(fetched_config_.id());
    658 
    659   // Resume any requests which we had to defer until the PAC script was
    660   // downloaded.
    661   SetReady();
    662 }
    663 
    664 int ProxyService::ReconsiderProxyAfterError(const GURL& url,
    665                                             ProxyInfo* result,
    666                                             CompletionCallback* callback,
    667                                             PacRequest** pac_request,
    668                                             const BoundNetLog& net_log) {
    669   DCHECK(CalledOnValidThread());
    670 
    671   // Check to see if we have a new config since ResolveProxy was called.  We
    672   // want to re-run ResolveProxy in two cases: 1) we have a new config, or 2) a
    673   // direct connection failed and we never tried the current config.
    674 
    675   bool re_resolve = result->config_id_ != config_.id();
    676 
    677   if (re_resolve) {
    678     // If we have a new config or the config was never tried, we delete the
    679     // list of bad proxies and we try again.
    680     proxy_retry_info_.clear();
    681     return ResolveProxy(url, result, callback, pac_request, net_log);
    682   }
    683 
    684   // We don't have new proxy settings to try, try to fallback to the next proxy
    685   // in the list.
    686   bool did_fallback = result->Fallback(&proxy_retry_info_);
    687 
    688   // Return synchronous failure if there is nothing left to fall-back to.
    689   // TODO(eroman): This is a yucky API, clean it up.
    690   return did_fallback ? OK : ERR_FAILED;
    691 }
    692 
    693 void ProxyService::CancelPacRequest(PacRequest* req) {
    694   DCHECK(CalledOnValidThread());
    695   DCHECK(req);
    696   req->Cancel();
    697   RemovePendingRequest(req);
    698 }
    699 
    700 bool ProxyService::ContainsPendingRequest(PacRequest* req) {
    701   PendingRequests::iterator it = std::find(
    702       pending_requests_.begin(), pending_requests_.end(), req);
    703   return pending_requests_.end() != it;
    704 }
    705 
    706 void ProxyService::RemovePendingRequest(PacRequest* req) {
    707   DCHECK(ContainsPendingRequest(req));
    708   PendingRequests::iterator it = std::find(
    709       pending_requests_.begin(), pending_requests_.end(), req);
    710   pending_requests_.erase(it);
    711 }
    712 
    713 int ProxyService::DidFinishResolvingProxy(ProxyInfo* result,
    714                                           int result_code,
    715                                           const BoundNetLog& net_log) {
    716   // Log the result of the proxy resolution.
    717   if (result_code == OK) {
    718     // When logging all events is enabled, dump the proxy list.
    719     if (net_log.IsLoggingAllEvents()) {
    720       net_log.AddEvent(
    721           NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST,
    722           make_scoped_refptr(new NetLogStringParameter(
    723               "pac_string", result->ToPacString())));
    724     }
    725     result->DeprioritizeBadProxies(proxy_retry_info_);
    726   } else {
    727     net_log.AddEvent(
    728         NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST,
    729         make_scoped_refptr(new NetLogIntegerParameter(
    730             "net_error", result_code)));
    731 
    732     // Fall-back to direct when the proxy resolver fails. This corresponds
    733     // with a javascript runtime error in the PAC script.
    734     //
    735     // This implicit fall-back to direct matches Firefox 3.5 and
    736     // Internet Explorer 8. For more information, see:
    737     //
    738     // http://www.chromium.org/developers/design-documents/proxy-settings-fallback
    739     result->UseDirect();
    740     result_code = OK;
    741   }
    742 
    743   net_log.EndEvent(NetLog::TYPE_PROXY_SERVICE, NULL);
    744   return result_code;
    745 }
    746 
    747 void ProxyService::SetProxyScriptFetcher(
    748     ProxyScriptFetcher* proxy_script_fetcher) {
    749   DCHECK(CalledOnValidThread());
    750   State previous_state = ResetProxyConfig(false);
    751   proxy_script_fetcher_.reset(proxy_script_fetcher);
    752   if (previous_state != STATE_NONE)
    753     ApplyProxyConfigIfAvailable();
    754 }
    755 
    756 ProxyScriptFetcher* ProxyService::GetProxyScriptFetcher() const {
    757   DCHECK(CalledOnValidThread());
    758   return proxy_script_fetcher_.get();
    759 }
    760 
    761 ProxyService::State ProxyService::ResetProxyConfig(bool reset_fetched_config) {
    762   DCHECK(CalledOnValidThread());
    763   State previous_state = current_state_;
    764 
    765   proxy_retry_info_.clear();
    766   init_proxy_resolver_.reset();
    767   SuspendAllPendingRequests();
    768   config_ = ProxyConfig();
    769   if (reset_fetched_config)
    770     fetched_config_ = ProxyConfig();
    771   current_state_ = STATE_NONE;
    772 
    773   return previous_state;
    774 }
    775 
    776 void ProxyService::ResetConfigService(
    777     ProxyConfigService* new_proxy_config_service) {
    778   DCHECK(CalledOnValidThread());
    779   State previous_state = ResetProxyConfig(true);
    780 
    781   // Release the old configuration service.
    782   if (config_service_.get())
    783     config_service_->RemoveObserver(this);
    784 
    785   // Set the new configuration service.
    786   config_service_.reset(new_proxy_config_service);
    787   config_service_->AddObserver(this);
    788 
    789   if (previous_state != STATE_NONE)
    790     ApplyProxyConfigIfAvailable();
    791 }
    792 
    793 void ProxyService::PurgeMemory() {
    794   DCHECK(CalledOnValidThread());
    795   if (resolver_.get())
    796     resolver_->PurgeMemory();
    797 }
    798 
    799 void ProxyService::ForceReloadProxyConfig() {
    800   DCHECK(CalledOnValidThread());
    801   ResetProxyConfig(false);
    802   ApplyProxyConfigIfAvailable();
    803 }
    804 
    805 // static
    806 ProxyConfigService* ProxyService::CreateSystemProxyConfigService(
    807     MessageLoop* io_loop, MessageLoop* file_loop) {
    808 #if defined(OS_WIN)
    809   return new ProxyConfigServiceWin();
    810 #elif defined(OS_MACOSX)
    811   return new ProxyConfigServiceMac(io_loop);
    812 #elif defined(OS_CHROMEOS)
    813   NOTREACHED() << "ProxyConfigService for ChromeOS should be created in "
    814                << "profile_io_data.cc::CreateProxyConfigService.";
    815   return NULL;
    816 #elif defined(ANDROID)
    817   NOTREACHED() << "ProxyConfigService for Android should be created in "
    818                << "WebCache.cpp: WebCache::WebCache";
    819   return NULL;
    820 #elif defined(OS_LINUX)
    821   ProxyConfigServiceLinux* linux_config_service =
    822       new ProxyConfigServiceLinux();
    823 
    824   // Assume we got called from the UI loop, which runs the default
    825   // glib main loop, so the current thread is where we should be
    826   // running gconf calls from.
    827   MessageLoop* glib_default_loop = MessageLoopForUI::current();
    828 
    829   // The file loop should be a MessageLoopForIO on Linux.
    830   DCHECK_EQ(MessageLoop::TYPE_IO, file_loop->type());
    831 
    832   // Synchronously fetch the current proxy config (since we are
    833   // running on glib_default_loop). Additionally register for
    834   // notifications (delivered in either |glib_default_loop| or
    835   // |file_loop|) to keep us updated when the proxy config changes.
    836   linux_config_service->SetupAndFetchInitialConfig(glib_default_loop, io_loop,
    837       static_cast<MessageLoopForIO*>(file_loop));
    838 
    839   return linux_config_service;
    840 #else
    841   LOG(WARNING) << "Failed to choose a system proxy settings fetcher "
    842                   "for this platform.";
    843   return new ProxyConfigServiceNull();
    844 #endif
    845 }
    846 
    847 void ProxyService::OnProxyConfigChanged(
    848     const ProxyConfig& config,
    849     ProxyConfigService::ConfigAvailability availability) {
    850   // Retrieve the current proxy configuration from the ProxyConfigService.
    851   // If a configuration is not available yet, we will get called back later
    852   // by our ProxyConfigService::Observer once it changes.
    853   ProxyConfig effective_config;
    854   switch (availability) {
    855     case ProxyConfigService::CONFIG_PENDING:
    856       // ProxyConfigService implementors should never pass CONFIG_PENDING.
    857       NOTREACHED() << "Proxy config change with CONFIG_PENDING availability!";
    858       return;
    859     case ProxyConfigService::CONFIG_VALID:
    860       effective_config = config;
    861       break;
    862     case ProxyConfigService::CONFIG_UNSET:
    863       effective_config = ProxyConfig::CreateDirect();
    864       break;
    865   }
    866 
    867   // Emit the proxy settings change to the NetLog stream.
    868   if (net_log_) {
    869     scoped_refptr<NetLog::EventParameters> params(
    870         new ProxyConfigChangedNetLogParam(fetched_config_, effective_config));
    871     net_log_->AddEntry(net::NetLog::TYPE_PROXY_CONFIG_CHANGED,
    872                        base::TimeTicks::Now(),
    873                        NetLog::Source(),
    874                        NetLog::PHASE_NONE,
    875                        params);
    876   }
    877 
    878   // Set the new configuration as the most recently fetched one.
    879   fetched_config_ = effective_config;
    880   fetched_config_.set_id(1);  // Needed for a later DCHECK of is_valid().
    881 
    882   InitializeUsingLastFetchedConfig();
    883 }
    884 
    885 void ProxyService::InitializeUsingLastFetchedConfig() {
    886   ResetProxyConfig(false);
    887 
    888   DCHECK(fetched_config_.is_valid());
    889 
    890   // Increment the ID to reflect that the config has changed.
    891   fetched_config_.set_id(next_config_id_++);
    892 
    893   if (!fetched_config_.HasAutomaticSettings()) {
    894     config_ = fetched_config_;
    895     SetReady();
    896     return;
    897   }
    898 
    899   // Start downloading + testing the PAC scripts for this new configuration.
    900   current_state_ = STATE_WAITING_FOR_INIT_PROXY_RESOLVER;
    901 
    902   init_proxy_resolver_.reset(
    903       new InitProxyResolver(resolver_.get(), proxy_script_fetcher_.get(),
    904                             net_log_));
    905 
    906   // If we changed networks recently, we should delay running proxy auto-config.
    907   base::TimeDelta wait_delay =
    908       stall_proxy_autoconfig_until_ - base::TimeTicks::Now();
    909 
    910   int rv = init_proxy_resolver_->Init(
    911       fetched_config_, wait_delay, &config_, &init_proxy_resolver_callback_);
    912 
    913   if (rv != ERR_IO_PENDING)
    914     OnInitProxyResolverComplete(rv);
    915 }
    916 
    917 void ProxyService::OnIPAddressChanged() {
    918   // See the comment block by |kNumMillisToStallAfterNetworkChanges| for info.
    919   stall_proxy_autoconfig_until_ =
    920       base::TimeTicks::Now() + stall_proxy_auto_config_delay_;
    921 
    922   State previous_state = ResetProxyConfig(false);
    923   if (previous_state != STATE_NONE)
    924     ApplyProxyConfigIfAvailable();
    925 }
    926 
    927 SyncProxyServiceHelper::SyncProxyServiceHelper(MessageLoop* io_message_loop,
    928                                                ProxyService* proxy_service)
    929     : io_message_loop_(io_message_loop),
    930       proxy_service_(proxy_service),
    931       event_(false, false),
    932       ALLOW_THIS_IN_INITIALIZER_LIST(callback_(
    933           this, &SyncProxyServiceHelper::OnCompletion)) {
    934   DCHECK(io_message_loop_ != MessageLoop::current());
    935 }
    936 
    937 int SyncProxyServiceHelper::ResolveProxy(const GURL& url,
    938                                          ProxyInfo* proxy_info,
    939                                          const BoundNetLog& net_log) {
    940   DCHECK(io_message_loop_ != MessageLoop::current());
    941 
    942   io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
    943       this, &SyncProxyServiceHelper::StartAsyncResolve, url, net_log));
    944 
    945   event_.Wait();
    946 
    947   if (result_ == net::OK) {
    948     *proxy_info = proxy_info_;
    949   }
    950   return result_;
    951 }
    952 
    953 int SyncProxyServiceHelper::ReconsiderProxyAfterError(
    954     const GURL& url, ProxyInfo* proxy_info, const BoundNetLog& net_log) {
    955   DCHECK(io_message_loop_ != MessageLoop::current());
    956 
    957   io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
    958       this, &SyncProxyServiceHelper::StartAsyncReconsider, url, net_log));
    959 
    960   event_.Wait();
    961 
    962   if (result_ == net::OK) {
    963     *proxy_info = proxy_info_;
    964   }
    965   return result_;
    966 }
    967 
    968 SyncProxyServiceHelper::~SyncProxyServiceHelper() {}
    969 
    970 void SyncProxyServiceHelper::StartAsyncResolve(const GURL& url,
    971                                                const BoundNetLog& net_log) {
    972   result_ = proxy_service_->ResolveProxy(
    973       url, &proxy_info_, &callback_, NULL, net_log);
    974   if (result_ != net::ERR_IO_PENDING) {
    975     OnCompletion(result_);
    976   }
    977 }
    978 
    979 void SyncProxyServiceHelper::StartAsyncReconsider(const GURL& url,
    980                                                   const BoundNetLog& net_log) {
    981   result_ = proxy_service_->ReconsiderProxyAfterError(
    982       url, &proxy_info_, &callback_, NULL, net_log);
    983   if (result_ != net::ERR_IO_PENDING) {
    984     OnCompletion(result_);
    985   }
    986 }
    987 
    988 void SyncProxyServiceHelper::OnCompletion(int rv) {
    989   result_ = rv;
    990   event_.Signal();
    991 }
    992 
    993 }  // namespace net
    994