Home | History | Annotate | Download | only in proxy
      1 // Copyright (c) 2009 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 #ifndef NET_PROXY_PROXY_SERVICE_H_
      6 #define NET_PROXY_PROXY_SERVICE_H_
      7 
      8 #include <string>
      9 #include <vector>
     10 
     11 #include "base/ref_counted.h"
     12 #include "base/scoped_ptr.h"
     13 #include "base/waitable_event.h"
     14 #include "net/base/completion_callback.h"
     15 #include "net/base/network_change_notifier.h"
     16 #include "net/proxy/proxy_server.h"
     17 #include "net/proxy/proxy_info.h"
     18 #include "testing/gtest/include/gtest/gtest_prod.h"
     19 
     20 class GURL;
     21 class MessageLoop;
     22 class URLRequestContext;
     23 
     24 namespace net {
     25 
     26 class InitProxyResolver;
     27 class LoadLog;
     28 class ProxyConfigService;
     29 class ProxyResolver;
     30 class ProxyScriptFetcher;
     31 
     32 // This class can be used to resolve the proxy server to use when loading a
     33 // HTTP(S) URL.  It uses the given ProxyResolver to handle the actual proxy
     34 // resolution.  See ProxyResolverV8 for example.
     35 class ProxyService : public base::RefCountedThreadSafe<ProxyService>,
     36                      public NetworkChangeNotifier::Observer {
     37  public:
     38   // The instance takes ownership of |config_service| and |resolver|.
     39   // If |network_change_notifier| is non-NULL, the proxy service will register
     40   // with it to detect when the network setup has changed. This is used to
     41   // decide when to re-configure the proxy discovery.
     42   ProxyService(ProxyConfigService* config_service, ProxyResolver* resolver,
     43                NetworkChangeNotifier* network_change_notifier);
     44 
     45   // Used internally to handle PAC queries.
     46   // TODO(eroman): consider naming this simply "Request".
     47   class PacRequest;
     48 
     49   // Returns ERR_IO_PENDING if the proxy information could not be provided
     50   // synchronously, to indicate that the result will be available when the
     51   // callback is run.  The callback is run on the thread that calls
     52   // ResolveProxy.
     53   //
     54   // The caller is responsible for ensuring that |results| and |callback|
     55   // remain valid until the callback is run or until |pac_request| is cancelled
     56   // via CancelPacRequest.  |pac_request| is only valid while the completion
     57   // callback is still pending. NULL can be passed for |pac_request| if
     58   // the caller will not need to cancel the request.
     59   //
     60   // We use the three possible proxy access types in the following order,
     61   // doing fallback if one doesn't work.  See "init_proxy_resolver.h"
     62   // for the specifics.
     63   //   1.  WPAD auto-detection
     64   //   2.  PAC URL
     65   //   3.  named proxy
     66   //
     67   // Profiling information for the request is saved to |load_log| if non-NULL.
     68   int ResolveProxy(const GURL& url,
     69                    ProxyInfo* results,
     70                    CompletionCallback* callback,
     71                    PacRequest** pac_request,
     72                    LoadLog* load_log);
     73 
     74   // This method is called after a failure to connect or resolve a host name.
     75   // It gives the proxy service an opportunity to reconsider the proxy to use.
     76   // The |results| parameter contains the results returned by an earlier call
     77   // to ResolveProxy.  The semantics of this call are otherwise similar to
     78   // ResolveProxy.
     79   //
     80   // NULL can be passed for |pac_request| if the caller will not need to
     81   // cancel the request.
     82   //
     83   // Returns ERR_FAILED if there is not another proxy config to try.
     84   //
     85   // Profiling information for the request is saved to |load_log| if non-NULL.
     86   int ReconsiderProxyAfterError(const GURL& url,
     87                                 ProxyInfo* results,
     88                                 CompletionCallback* callback,
     89                                 PacRequest** pac_request,
     90                                 LoadLog* load_log);
     91 
     92   // Call this method with a non-null |pac_request| to cancel the PAC request.
     93   void CancelPacRequest(PacRequest* pac_request);
     94 
     95   // Sets the ProxyScriptFetcher dependency. This is needed if the ProxyResolver
     96   // is of type ProxyResolverWithoutFetch. ProxyService takes ownership of
     97   // |proxy_script_fetcher|.
     98   void SetProxyScriptFetcher(ProxyScriptFetcher* proxy_script_fetcher);
     99   ProxyScriptFetcher* GetProxyScriptFetcher() const;
    100 
    101   // Tells this ProxyService to start using a new ProxyConfigService to
    102   // retrieve its ProxyConfig from. The new ProxyConfigService will immediately
    103   // be queried for new config info which will be used for all subsequent
    104   // ResolveProxy calls. ProxyService takes ownership of
    105   // |new_proxy_config_service|.
    106   void ResetConfigService(ProxyConfigService* new_proxy_config_service);
    107 
    108   // Tells the resolver to purge any memory it does not need.
    109   void PurgeMemory();
    110 
    111   // Returns the log for the most recent WPAD + PAC initialization.
    112   // (This shows how much time was spent downloading and parsing the
    113   // PAC scripts for the current configuration).
    114   LoadLog* init_proxy_resolver_log() const {
    115     return init_proxy_resolver_log_;
    116   }
    117 
    118   // Returns true if we have called UpdateConfig() at least once.
    119   bool config_has_been_initialized() const {
    120     return config_.id() != ProxyConfig::INVALID_ID;
    121   }
    122 
    123   // Returns the last configuration fetched from ProxyConfigService.
    124   const ProxyConfig& config() {
    125     return config_;
    126   }
    127 
    128   // Returns the map of proxies which have been marked as "bad".
    129   const ProxyRetryInfoMap& proxy_retry_info() const {
    130     return proxy_retry_info_;
    131   }
    132 
    133   // Clears the list of bad proxy servers that has been cached.
    134   void ClearBadProxiesCache() {
    135     proxy_retry_info_.clear();
    136   }
    137 
    138   // Forces refetching the proxy configuration, and applying it.
    139   // This re-does everything from fetching the system configuration,
    140   // to downloading and testing the PAC files.
    141   void ForceReloadProxyConfig();
    142 
    143   // Creates a proxy service that polls |proxy_config_service| to notice when
    144   // the proxy settings change. We take ownership of |proxy_config_service|.
    145   // Iff |use_v8_resolver| is true, then the V8 implementation is
    146   // used.
    147   // |url_request_context| is only used when use_v8_resolver is true:
    148   // it specifies the URL request context that will be used if a PAC
    149   // script needs to be fetched.
    150   // |network_change_notifier| may be NULL. Otherwise it will be used to
    151   // signal the ProxyService when the network setup has changed.
    152   // |io_loop| points to the IO thread's message loop. It is only used
    153   // when pc is NULL.
    154   // ##########################################################################
    155   // # See the warnings in net/proxy/proxy_resolver_v8.h describing the
    156   // # multi-threading model. In order for this to be safe to use, *ALL* the
    157   // # other V8's running in the process must use v8::Locker.
    158   // ##########################################################################
    159   static ProxyService* Create(
    160       ProxyConfigService* proxy_config_service,
    161       bool use_v8_resolver,
    162       URLRequestContext* url_request_context,
    163       NetworkChangeNotifier* network_change_notifier,
    164       MessageLoop* io_loop);
    165 
    166   // Convenience method that creates a proxy service using the
    167   // specified fixed settings. |pc| must not be NULL.
    168   static ProxyService* CreateFixed(const ProxyConfig& pc);
    169 
    170   // Creates a proxy service that always fails to fetch the proxy configuration,
    171   // so it falls back to direct connect.
    172   static ProxyService* CreateNull();
    173 
    174   // Creates a config service appropriate for this platform that fetches the
    175   // system proxy settings.
    176   static ProxyConfigService* CreateSystemProxyConfigService(
    177       MessageLoop* io_loop, MessageLoop* file_loop);
    178 
    179  private:
    180   friend class base::RefCountedThreadSafe<ProxyService>;
    181   FRIEND_TEST(ProxyServiceTest, IsLocalName);
    182   FRIEND_TEST(ProxyServiceTest, UpdateConfigAfterFailedAutodetect);
    183   FRIEND_TEST(ProxyServiceTest, UpdateConfigFromPACToDirect);
    184   friend class PacRequest;
    185 
    186   // TODO(eroman): change this to a std::set. Note that this requires updating
    187   // some tests in proxy_service_unittest.cc such as:
    188   //   ProxyServiceTest.InitialPACScriptDownload
    189   // which expects requests to finish in the order they were added.
    190   typedef std::vector<scoped_refptr<PacRequest> > PendingRequests;
    191 
    192   ~ProxyService();
    193 
    194   // Creates a proxy resolver appropriate for this platform that doesn't rely
    195   // on V8.
    196   static ProxyResolver* CreateNonV8ProxyResolver();
    197 
    198   // Identifies the proxy configuration.
    199   ProxyConfig::ID config_id() const { return config_.id(); }
    200 
    201   // Checks to see if the proxy configuration changed, and then updates config_
    202   // to reference the new configuration.
    203   void UpdateConfig(LoadLog* load_log);
    204 
    205   // Assign |config| as the current configuration.
    206   void SetConfig(const ProxyConfig& config);
    207 
    208   // Starts downloading and testing the various PAC choices.
    209   // Calls OnInitProxyResolverComplete() when completed.
    210   void StartInitProxyResolver();
    211 
    212   // Tries to update the configuration if it hasn't been checked in a while.
    213   void UpdateConfigIfOld(LoadLog* load_log);
    214 
    215   // Returns true if the proxy resolver is being initialized for PAC
    216   // (downloading PAC script(s) + testing).
    217   // Resolve requests will be frozen until the initialization has completed.
    218   bool IsInitializingProxyResolver() const {
    219     return init_proxy_resolver_.get() != NULL;
    220   }
    221 
    222   // Callback for when the proxy resolver has been initialized with a
    223   // PAC script.
    224   void OnInitProxyResolverComplete(int result);
    225 
    226   // Returns ERR_IO_PENDING if the request cannot be completed synchronously.
    227   // Otherwise it fills |result| with the proxy information for |url|.
    228   // Completing synchronously means we don't need to query ProxyResolver.
    229   int TryToCompleteSynchronously(const GURL& url, ProxyInfo* result);
    230 
    231   // Set |result| with the proxy to use for |url|, based on |rules|.
    232   void ApplyProxyRules(const GURL& url,
    233                        const ProxyConfig::ProxyRules& rules,
    234                        ProxyInfo* result);
    235 
    236   // Cancel all of the requests sent to the ProxyResolver. These will be
    237   // restarted when calling ResumeAllPendingRequests().
    238   void SuspendAllPendingRequests();
    239 
    240   // Sends all the unstarted pending requests off to the resolver.
    241   void ResumeAllPendingRequests();
    242 
    243   // Returns true if |pending_requests_| contains |req|.
    244   bool ContainsPendingRequest(PacRequest* req);
    245 
    246   // Removes |req| from the list of pending requests.
    247   void RemovePendingRequest(PacRequest* req);
    248 
    249   // Called when proxy resolution has completed (either synchronously or
    250   // asynchronously). Handles logging the result, and cleaning out
    251   // bad entries from the results list.
    252   int DidFinishResolvingProxy(ProxyInfo* result,
    253                               int result_code,
    254                               LoadLog* load_log);
    255 
    256   // Returns true if the URL passed in should not go through the proxy server.
    257   // 1. If the proxy settings say to bypass local names, and |IsLocalName(url)|.
    258   // 2. The URL matches one of the entities in the proxy bypass list.
    259   bool ShouldBypassProxyForURL(const GURL& url);
    260 
    261   // Returns true if |url| is to an intranet site (using non-FQDN as the
    262   // heuristic).
    263   static bool IsLocalName(const GURL& url);
    264 
    265   // NetworkChangeNotifier::Observer methods:
    266   virtual void OnIPAddressChanged();
    267 
    268   scoped_ptr<ProxyConfigService> config_service_;
    269   scoped_ptr<ProxyResolver> resolver_;
    270 
    271   // We store the proxy config and a counter (ID) that is incremented each time
    272   // the config changes.
    273   ProxyConfig config_;
    274 
    275   // Increasing ID to give to the next ProxyConfig that we set.
    276   int next_config_id_;
    277 
    278   // Indicates whether the ProxyResolver should be sent requests.
    279   bool should_use_proxy_resolver_;
    280 
    281   // The time when the proxy configuration was last read from the system.
    282   base::TimeTicks config_last_update_time_;
    283 
    284   // Map of the known bad proxies and the information about the retry time.
    285   ProxyRetryInfoMap proxy_retry_info_;
    286 
    287   // Set of pending/inprogress requests.
    288   PendingRequests pending_requests_;
    289 
    290   // The fetcher to use when downloading PAC scripts for the ProxyResolver.
    291   // This dependency can be NULL if our ProxyResolver has no need for
    292   // external PAC script fetching.
    293   scoped_ptr<ProxyScriptFetcher> proxy_script_fetcher_;
    294 
    295   // Callback for when |init_proxy_resolver_| is done.
    296   CompletionCallbackImpl<ProxyService> init_proxy_resolver_callback_;
    297 
    298   // Helper to download the PAC script (wpad + custom) and apply fallback rules.
    299   //
    300   // Note that the declaration is important here: |proxy_script_fetcher_| and
    301   // |proxy_resolver_| must outlive |init_proxy_resolver_|.
    302   scoped_ptr<InitProxyResolver> init_proxy_resolver_;
    303 
    304   // Log from the *last* time |init_proxy_resolver_.Init()| was called, or NULL.
    305   scoped_refptr<LoadLog> init_proxy_resolver_log_;
    306 
    307   // The (possibly NULL) network change notifier that we use to decide when
    308   // to refetch PAC scripts or re-run WPAD.
    309   NetworkChangeNotifier* const network_change_notifier_;
    310 
    311   DISALLOW_COPY_AND_ASSIGN(ProxyService);
    312 };
    313 
    314 // Wrapper for invoking methods on a ProxyService synchronously.
    315 class SyncProxyServiceHelper
    316     : public base::RefCountedThreadSafe<SyncProxyServiceHelper> {
    317  public:
    318   SyncProxyServiceHelper(MessageLoop* io_message_loop,
    319                          ProxyService* proxy_service);
    320 
    321   int ResolveProxy(const GURL& url, ProxyInfo* proxy_info, LoadLog* load_log);
    322   int ReconsiderProxyAfterError(const GURL& url,
    323                                 ProxyInfo* proxy_info, LoadLog* load_log);
    324 
    325  private:
    326   friend class base::RefCountedThreadSafe<SyncProxyServiceHelper>;
    327 
    328   ~SyncProxyServiceHelper() {}
    329 
    330   void StartAsyncResolve(const GURL& url, LoadLog* load_log);
    331   void StartAsyncReconsider(const GURL& url, LoadLog* load_log);
    332 
    333   void OnCompletion(int result);
    334 
    335   MessageLoop* io_message_loop_;
    336   ProxyService* proxy_service_;
    337 
    338   base::WaitableEvent event_;
    339   CompletionCallbackImpl<SyncProxyServiceHelper> callback_;
    340   ProxyInfo proxy_info_;
    341   int result_;
    342 };
    343 
    344 }  // namespace net
    345 
    346 #endif  // NET_PROXY_PROXY_SERVICE_H_
    347