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