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 #ifndef NET_PROXY_PROXY_SERVICE_H_ 6 #define NET_PROXY_PROXY_SERVICE_H_ 7 #pragma once 8 9 #include <vector> 10 11 #include "base/gtest_prod_util.h" 12 #include "base/memory/ref_counted.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "base/synchronization/waitable_event.h" 15 #include "base/threading/non_thread_safe.h" 16 #include "net/base/completion_callback.h" 17 #include "net/base/net_export.h" 18 #include "net/base/net_log.h" 19 #include "net/base/network_change_notifier.h" 20 #include "net/proxy/proxy_config_service.h" 21 #include "net/proxy/proxy_info.h" 22 #include "net/proxy/proxy_server.h" 23 24 class GURL; 25 class MessageLoop; 26 27 namespace net { 28 29 class HostResolver; 30 class InitProxyResolver; 31 class ProxyResolver; 32 class ProxyScriptFetcher; 33 class URLRequestContext; 34 35 // This class can be used to resolve the proxy server to use when loading a 36 // HTTP(S) URL. It uses the given ProxyResolver to handle the actual proxy 37 // resolution. See ProxyResolverV8 for example. 38 class NET_EXPORT ProxyService : public base::RefCounted<ProxyService>, 39 public NetworkChangeNotifier::IPAddressObserver, 40 public ProxyConfigService::Observer, 41 public base::NonThreadSafe { 42 public: 43 // The instance takes ownership of |config_service| and |resolver|. 44 // |net_log| is a possibly NULL destination to send log events to. It must 45 // remain alive for the lifetime of this ProxyService. 46 ProxyService(ProxyConfigService* config_service, 47 ProxyResolver* resolver, 48 NetLog* net_log); 49 50 // Used internally to handle PAC queries. 51 // TODO(eroman): consider naming this simply "Request". 52 class PacRequest; 53 54 // Returns ERR_IO_PENDING if the proxy information could not be provided 55 // synchronously, to indicate that the result will be available when the 56 // callback is run. The callback is run on the thread that calls 57 // ResolveProxy. 58 // 59 // The caller is responsible for ensuring that |results| and |callback| 60 // remain valid until the callback is run or until |pac_request| is cancelled 61 // via CancelPacRequest. |pac_request| is only valid while the completion 62 // callback is still pending. NULL can be passed for |pac_request| if 63 // the caller will not need to cancel the request. 64 // 65 // We use the three possible proxy access types in the following order, 66 // doing fallback if one doesn't work. See "init_proxy_resolver.h" 67 // for the specifics. 68 // 1. WPAD auto-detection 69 // 2. PAC URL 70 // 3. named proxy 71 // 72 // Profiling information for the request is saved to |net_log| if non-NULL. 73 int ResolveProxy(const GURL& url, 74 ProxyInfo* results, 75 CompletionCallback* callback, 76 PacRequest** pac_request, 77 const BoundNetLog& net_log); 78 79 // This method is called after a failure to connect or resolve a host name. 80 // It gives the proxy service an opportunity to reconsider the proxy to use. 81 // The |results| parameter contains the results returned by an earlier call 82 // to ResolveProxy. The semantics of this call are otherwise similar to 83 // ResolveProxy. 84 // 85 // NULL can be passed for |pac_request| if the caller will not need to 86 // cancel the request. 87 // 88 // Returns ERR_FAILED if there is not another proxy config to try. 89 // 90 // Profiling information for the request is saved to |net_log| if non-NULL. 91 int ReconsiderProxyAfterError(const GURL& url, 92 ProxyInfo* results, 93 CompletionCallback* callback, 94 PacRequest** pac_request, 95 const BoundNetLog& net_log); 96 97 // Call this method with a non-null |pac_request| to cancel the PAC request. 98 void CancelPacRequest(PacRequest* pac_request); 99 100 // Sets the ProxyScriptFetcher dependency. This is needed if the ProxyResolver 101 // is of type ProxyResolverWithoutFetch. ProxyService takes ownership of 102 // |proxy_script_fetcher|. 103 void SetProxyScriptFetcher(ProxyScriptFetcher* proxy_script_fetcher); 104 ProxyScriptFetcher* GetProxyScriptFetcher() const; 105 106 // Tells this ProxyService to start using a new ProxyConfigService to 107 // retrieve its ProxyConfig from. The new ProxyConfigService will immediately 108 // be queried for new config info which will be used for all subsequent 109 // ResolveProxy calls. ProxyService takes ownership of 110 // |new_proxy_config_service|. 111 void ResetConfigService(ProxyConfigService* new_proxy_config_service); 112 113 // Tells the resolver to purge any memory it does not need. 114 void PurgeMemory(); 115 116 117 // Returns the last configuration fetched from ProxyConfigService. 118 const ProxyConfig& fetched_config() { 119 return fetched_config_; 120 } 121 122 // Returns the current configuration being used by ProxyConfigService. 123 const ProxyConfig& config() { 124 return config_; 125 } 126 127 // Returns the map of proxies which have been marked as "bad". 128 const ProxyRetryInfoMap& proxy_retry_info() const { 129 return proxy_retry_info_; 130 } 131 132 // Clears the list of bad proxy servers that has been cached. 133 void ClearBadProxiesCache() { 134 proxy_retry_info_.clear(); 135 } 136 137 // Forces refetching the proxy configuration, and applying it. 138 // This re-does everything from fetching the system configuration, 139 // to downloading and testing the PAC files. 140 void ForceReloadProxyConfig(); 141 142 // Creates a proxy service that polls |proxy_config_service| to notice when 143 // the proxy settings change. We take ownership of |proxy_config_service|. 144 // 145 // |num_pac_threads| specifies the maximum number of threads to use for 146 // executing PAC scripts. Threads are created lazily on demand. 147 // If |0| is specified, then a default number of threads will be selected. 148 // 149 // Having more threads avoids stalling proxy resolve requests when the 150 // PAC script takes a while to run. This is particularly a problem when PAC 151 // scripts do synchronous DNS resolutions, since that can take on the order 152 // of seconds. 153 // 154 // However, the disadvantages of using more than 1 thread are: 155 // (a) can cause compatibility issues for scripts that rely on side effects 156 // between runs (such scripts should not be common though). 157 // (b) increases the memory used by proxy resolving, as each thread will 158 // duplicate its own script context. 159 160 // |proxy_script_fetcher| specifies the dependency to use for downloading 161 // any PAC scripts. The resulting ProxyService will take ownership of it. 162 // 163 // |host_resolver| points to the host resolving dependency the PAC script 164 // should use for any DNS queries. It must remain valid throughout the 165 // lifetime of the ProxyService. 166 // 167 // ########################################################################## 168 // # See the warnings in net/proxy/proxy_resolver_v8.h describing the 169 // # multi-threading model. In order for this to be safe to use, *ALL* the 170 // # other V8's running in the process must use v8::Locker. 171 // ########################################################################## 172 static ProxyService* CreateUsingV8ProxyResolver( 173 ProxyConfigService* proxy_config_service, 174 size_t num_pac_threads, 175 ProxyScriptFetcher* proxy_script_fetcher, 176 HostResolver* host_resolver, 177 NetLog* net_log); 178 179 // Same as CreateUsingV8ProxyResolver, except it uses system libraries 180 // for evaluating the PAC script if available, otherwise skips 181 // proxy autoconfig. 182 static ProxyService* CreateUsingSystemProxyResolver( 183 ProxyConfigService* proxy_config_service, 184 size_t num_pac_threads, 185 NetLog* net_log); 186 187 // Creates a ProxyService without support for proxy autoconfig. 188 static ProxyService* CreateWithoutProxyResolver( 189 ProxyConfigService* proxy_config_service, 190 NetLog* net_log); 191 192 // Convenience methods that creates a proxy service using the 193 // specified fixed settings. 194 static ProxyService* CreateFixed(const ProxyConfig& pc); 195 static ProxyService* CreateFixed(const std::string& proxy); 196 197 // Creates a proxy service that uses a DIRECT connection for all requests. 198 static ProxyService* CreateDirect(); 199 // |net_log|'s lifetime must exceed ProxyService. 200 static ProxyService* CreateDirectWithNetLog(NetLog* net_log); 201 202 // This method is used by tests to create a ProxyService that returns a 203 // hardcoded proxy fallback list (|pac_string|) for every URL. 204 // 205 // |pac_string| is a list of proxy servers, in the format that a PAC script 206 // would return it. For example, "PROXY foobar:99; SOCKS fml:2; DIRECT" 207 static ProxyService* CreateFixedFromPacResult(const std::string& pac_string); 208 209 // Creates a config service appropriate for this platform that fetches the 210 // system proxy settings. 211 static ProxyConfigService* CreateSystemProxyConfigService( 212 MessageLoop* io_loop, MessageLoop* file_loop); 213 214 #if UNIT_TEST 215 void set_stall_proxy_auto_config_delay(base::TimeDelta delay) { 216 stall_proxy_auto_config_delay_ = delay; 217 } 218 #endif 219 220 private: 221 friend class base::RefCounted<ProxyService>; 222 FRIEND_TEST_ALL_PREFIXES(ProxyServiceTest, UpdateConfigAfterFailedAutodetect); 223 FRIEND_TEST_ALL_PREFIXES(ProxyServiceTest, UpdateConfigFromPACToDirect); 224 friend class PacRequest; 225 226 // TODO(eroman): change this to a std::set. Note that this requires updating 227 // some tests in proxy_service_unittest.cc such as: 228 // ProxyServiceTest.InitialPACScriptDownload 229 // which expects requests to finish in the order they were added. 230 typedef std::vector<scoped_refptr<PacRequest> > PendingRequests; 231 232 enum State { 233 STATE_NONE, 234 STATE_WAITING_FOR_PROXY_CONFIG, 235 STATE_WAITING_FOR_INIT_PROXY_RESOLVER, 236 STATE_READY, 237 }; 238 239 virtual ~ProxyService(); 240 241 // Resets all the variables associated with the current proxy configuration, 242 // and rewinds the current state to |STATE_NONE|. Returns the previous value 243 // of |current_state_|. If |reset_fetched_config| is true then 244 // |fetched_config_| will also be reset, otherwise it will be left as-is. 245 // Resetting it means that we will have to re-fetch the configuration from 246 // the ProxyConfigService later. 247 State ResetProxyConfig(bool reset_fetched_config); 248 249 // Retrieves the current proxy configuration from the ProxyConfigService, and 250 // starts initializing for it. 251 void ApplyProxyConfigIfAvailable(); 252 253 // Callback for when the proxy resolver has been initialized with a 254 // PAC script. 255 void OnInitProxyResolverComplete(int result); 256 257 // Returns ERR_IO_PENDING if the request cannot be completed synchronously. 258 // Otherwise it fills |result| with the proxy information for |url|. 259 // Completing synchronously means we don't need to query ProxyResolver. 260 int TryToCompleteSynchronously(const GURL& url, ProxyInfo* result); 261 262 // Cancels all of the requests sent to the ProxyResolver. These will be 263 // restarted when calling ResumeAllPendingRequests(). 264 void SuspendAllPendingRequests(); 265 266 // Advances the current state to |STATE_READY|, and resumes any pending 267 // requests which had been stalled waiting for initialization to complete. 268 void SetReady(); 269 270 // Returns true if |pending_requests_| contains |req|. 271 bool ContainsPendingRequest(PacRequest* req); 272 273 // Removes |req| from the list of pending requests. 274 void RemovePendingRequest(PacRequest* req); 275 276 // Called when proxy resolution has completed (either synchronously or 277 // asynchronously). Handles logging the result, and cleaning out 278 // bad entries from the results list. 279 int DidFinishResolvingProxy(ProxyInfo* result, 280 int result_code, 281 const BoundNetLog& net_log); 282 283 // Start initialization using |fetched_config_|. 284 void InitializeUsingLastFetchedConfig(); 285 286 // NetworkChangeNotifier::IPAddressObserver 287 // When this is called, we re-fetch PAC scripts and re-run WPAD. 288 virtual void OnIPAddressChanged(); 289 290 // ProxyConfigService::Observer 291 virtual void OnProxyConfigChanged( 292 const ProxyConfig& config, 293 ProxyConfigService::ConfigAvailability availability); 294 295 scoped_ptr<ProxyConfigService> config_service_; 296 scoped_ptr<ProxyResolver> resolver_; 297 298 // We store the proxy configuration that was last fetched from the 299 // ProxyConfigService, as well as the resulting "effective" configuration. 300 // The effective configuration is what we condense the original fetched 301 // settings to after testing the various automatic settings (auto-detect 302 // and custom PAC url). 303 ProxyConfig fetched_config_; 304 ProxyConfig config_; 305 306 // Increasing ID to give to the next ProxyConfig that we set. 307 int next_config_id_; 308 309 // The time when the proxy configuration was last read from the system. 310 base::TimeTicks config_last_update_time_; 311 312 // Map of the known bad proxies and the information about the retry time. 313 ProxyRetryInfoMap proxy_retry_info_; 314 315 // Set of pending/inprogress requests. 316 PendingRequests pending_requests_; 317 318 // The fetcher to use when downloading PAC scripts for the ProxyResolver. 319 // This dependency can be NULL if our ProxyResolver has no need for 320 // external PAC script fetching. 321 scoped_ptr<ProxyScriptFetcher> proxy_script_fetcher_; 322 323 // Callback for when |init_proxy_resolver_| is done. 324 CompletionCallbackImpl<ProxyService> init_proxy_resolver_callback_; 325 326 // Helper to download the PAC script (wpad + custom) and apply fallback rules. 327 // 328 // Note that the declaration is important here: |proxy_script_fetcher_| and 329 // |proxy_resolver_| must outlive |init_proxy_resolver_|. 330 scoped_ptr<InitProxyResolver> init_proxy_resolver_; 331 332 State current_state_; 333 334 // This is the log where any events generated by |init_proxy_resolver_| are 335 // sent to. 336 NetLog* net_log_; 337 338 // The earliest time at which we should run any proxy auto-config. (Used to 339 // stall re-configuration following an IP address change). 340 base::TimeTicks stall_proxy_autoconfig_until_; 341 342 // The amount of time to stall requests following IP address changes. 343 base::TimeDelta stall_proxy_auto_config_delay_; 344 345 DISALLOW_COPY_AND_ASSIGN(ProxyService); 346 }; 347 348 // Wrapper for invoking methods on a ProxyService synchronously. 349 class SyncProxyServiceHelper 350 : public base::RefCountedThreadSafe<SyncProxyServiceHelper> { 351 public: 352 SyncProxyServiceHelper(MessageLoop* io_message_loop, 353 ProxyService* proxy_service); 354 355 int ResolveProxy(const GURL& url, 356 ProxyInfo* proxy_info, 357 const BoundNetLog& net_log); 358 int ReconsiderProxyAfterError(const GURL& url, 359 ProxyInfo* proxy_info, 360 const BoundNetLog& net_log); 361 362 private: 363 friend class base::RefCountedThreadSafe<SyncProxyServiceHelper>; 364 365 virtual ~SyncProxyServiceHelper(); 366 367 void StartAsyncResolve(const GURL& url, const BoundNetLog& net_log); 368 void StartAsyncReconsider(const GURL& url, const BoundNetLog& net_log); 369 370 void OnCompletion(int result); 371 372 MessageLoop* io_message_loop_; 373 ProxyService* proxy_service_; 374 375 base::WaitableEvent event_; 376 CompletionCallbackImpl<SyncProxyServiceHelper> callback_; 377 ProxyInfo proxy_info_; 378 int result_; 379 }; 380 381 } // namespace net 382 383 #endif // NET_PROXY_PROXY_SERVICE_H_ 384