Index: net/proxy/single_threaded_proxy_resolver.h |
=================================================================== |
--- net/proxy/single_threaded_proxy_resolver.h (revision 20322) |
+++ net/proxy/single_threaded_proxy_resolver.h (working copy) |
@@ -1,281 +1,88 @@ |
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
+// Copyright (c) 2009 The Chromium Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#ifndef NET_PROXY_PROXY_SERVICE_H_ |
-#define NET_PROXY_PROXY_SERVICE_H_ |
+#ifndef NET_PROXY_SINGLE_THREADED_PROXY_RESOLVER_H_ |
+#define NET_PROXY_SINGLE_THREADED_PROXY_RESOLVER_H_ |
#include <deque> |
#include <string> |
#include "base/ref_counted.h" |
#include "base/scoped_ptr.h" |
-#include "base/thread.h" |
-#include "base/waitable_event.h" |
-#include "net/base/completion_callback.h" |
-#include "net/proxy/proxy_server.h" |
-#include "net/proxy/proxy_info.h" |
+#include "net/proxy/proxy_resolver.h" |
-class GURL; |
-class URLRequestContext; |
+namespace base { |
+class Thread; |
+} // namespace base |
namespace net { |
-class ProxyScriptFetcher; |
-class ProxyConfigService; |
-class ProxyResolver; |
- |
-// This class can be used to resolve the proxy server to use when loading a |
-// HTTP(S) URL. It uses the given ProxyResolver to handle the actual proxy |
-// resolution. See ProxyResolverWinHttp for example. |
-class ProxyService { |
+// ProxyResolver implementation that wraps a synchronous ProxyResolver, and |
+// runs it on a single worker thread. If multiple requests accumulate, they |
+// are serviced in FIFO order. |
+class SingleThreadedProxyResolver : public ProxyResolver { |
public: |
- // The instance takes ownership of |config_service| and |resolver|. |
- ProxyService(ProxyConfigService* config_service, |
- ProxyResolver* resolver); |
- ~ProxyService(); |
+ // |resolver| is a synchronous ProxyResolver implementation. It doesn't |
+ // have to be thread-safe, since it is run on exactly one thread. The |
+ // constructor takes ownership of |resolver|. |
+ explicit SingleThreadedProxyResolver(ProxyResolver* resolver); |
- // Used internally to handle PAC queries. |
- class PacRequest; |
+ virtual ~SingleThreadedProxyResolver(); |
- // Returns ERR_IO_PENDING if the proxy information could not be provided |
- // synchronously, to indicate that the result will be available when the |
- // callback is run. The callback is run on the thread that calls |
- // ResolveProxy. |
- // |
- // The caller is responsible for ensuring that |results| and |callback| |
- // remain valid until the callback is run or until |pac_request| is cancelled |
- // via CancelPacRequest. |pac_request| is only valid while the completion |
- // callback is still pending. NULL can be passed for |pac_request| if |
- // the caller will not need to cancel the request. |
- // |
- // We use the three possible proxy access types in the following order, and |
- // we only use one of them (no falling back to other access types if the |
- // chosen one doesn't work). |
- // 1. named proxy |
- // 2. PAC URL |
- // 3. WPAD auto-detection |
- // |
- int ResolveProxy(const GURL& url, |
- ProxyInfo* results, |
- CompletionCallback* callback, |
- PacRequest** pac_request); |
+ // ProxyResolver implementation: |
+ virtual int GetProxyForURL(const GURL& url, |
+ ProxyInfo* results, |
+ CompletionCallback* callback, |
+ RequestHandle* request); |
+ virtual void CancelRequest(RequestHandle request); |
- // This method is called after a failure to connect or resolve a host name. |
- // It gives the proxy service an opportunity to reconsider the proxy to use. |
- // The |results| parameter contains the results returned by an earlier call |
- // to ResolveProxy. The semantics of this call are otherwise similar to |
- // ResolveProxy. |
- // |
- // NULL can be passed for |pac_request| if the caller will not need to |
- // cancel the request. |
- // |
- // Returns ERR_FAILED if there is not another proxy config to try. |
- // |
- int ReconsiderProxyAfterError(const GURL& url, |
- ProxyInfo* results, |
- CompletionCallback* callback, |
- PacRequest** pac_request); |
+ protected: |
+ // The wrapped (synchronous) ProxyResolver. |
+ ProxyResolver* resolver() { return resolver_.get(); } |
- // Call this method with a non-null |pac_request| to cancel the PAC request. |
- void CancelPacRequest(PacRequest* pac_request); |
- |
- // Sets the ProxyScriptFetcher dependency. This is needed if the ProxyResolver |
- // is of type ProxyResolverWithoutFetch. ProxyService takes ownership of |
- // |proxy_script_fetcher|. |
- void SetProxyScriptFetcher(ProxyScriptFetcher* proxy_script_fetcher); |
- |
- // Tells this ProxyService to start using a new ProxyConfigService to |
- // retrieve its ProxyConfig from. The new ProxyConfigService will immediately |
- // be queried for new config info which will be used for all subsequent |
- // ResolveProxy calls. ProxyService takes ownership of |
- // |new_proxy_config_service|. |
- void ResetConfigService(ProxyConfigService* new_proxy_config_service); |
- |
- // Creates a proxy service using the specified settings. If |pc| is NULL then |
- // the system's default proxy settings will be used (on Windows this will |
- // use IE's settings). |
- // Iff |use_v8_resolver| is true, then the V8 implementation is |
- // used. |
- // |url_request_context| is only used when use_v8_resolver is true: |
- // it specifies the URL request context that will be used if a PAC |
- // script needs to be fetched. |
- // |io_loop| points to the IO thread's message loop. It is only used |
- // when pc is NULL. If both pc and io_loop are NULL, then monitoring |
- // of gconf setting changes will be disabled in |
- // ProxyConfigServiceLinux. |
- // ########################################################################## |
- // # See the warnings in net/proxy/proxy_resolver_v8.h describing the |
- // # multi-threading model. In order for this to be safe to use, *ALL* the |
- // # other V8's running in the process must use v8::Locker. |
- // ########################################################################## |
- static ProxyService* Create( |
- const ProxyConfig* pc, |
- bool use_v8_resolver, |
- URLRequestContext* url_request_context, |
- MessageLoop* io_loop); |
- |
- // Convenience method that creates a proxy service using the |
- // specified fixed settings. |pc| must not be NULL. |
- static ProxyService* CreateFixed(const ProxyConfig& pc); |
- |
- // Creates a proxy service that always fails to fetch the proxy configuration, |
- // so it falls back to direct connect. |
- static ProxyService* CreateNull(); |
- |
private: |
- friend class PacRequest; |
+ // Refcounted helper class that bridges between origin thread and worker |
+ // thread. |
+ class Job; |
+ friend class Job; |
+ // FIFO queue that contains the in-progress job, and any pending jobs. |
+ typedef std::deque<scoped_refptr<Job> > PendingJobsQueue; |
- // Creates a config service appropriate for this platform that fetches the |
- // system proxy settings. |
- static ProxyConfigService* CreateSystemProxyConfigService( |
- MessageLoop* io_loop); |
+ base::Thread* thread() { return thread_.get(); } |
- // Creates a proxy resolver appropriate for this platform that doesn't rely |
- // on V8. |
- static ProxyResolver* CreateNonV8ProxyResolver(); |
+ // ProxyResolver implementation: |
+ virtual void SetPacScriptByUrlInternal(const GURL& pac_url); |
+ virtual void SetPacScriptByDataInternal(const std::string& bytes); |
- ProxyResolver* resolver() { return resolver_.get(); } |
- base::Thread* pac_thread() { return pac_thread_.get(); } |
+ // Helper for shared code between SetPacScriptByUrlInternal() and |
+ // SetPacScriptByDataInternal() -- the unused parameter is set to empty. |
+ void SetPacScriptHelper(const GURL& pac_url, const std::string& bytes); |
- // Identifies the proxy configuration. |
- ProxyConfig::ID config_id() const { return config_.id(); } |
+ // Starts the worker thread if it isn't already running. |
+ void EnsureThreadStarted(); |
- // Returns true if we have called UpdateConfig() at least once. |
- bool config_has_been_initialized() const { |
- return config_.id() != ProxyConfig::INVALID_ID; |
- } |
+ // Starts the next job from |pending_jobs_| if possible. |
+ void ProcessPendingJobs(); |
- // Checks to see if the proxy configuration changed, and then updates config_ |
- // to reference the new configuration. |
- void UpdateConfig(); |
- |
- // Assign |config| as the current configuration. |
- void SetConfig(const ProxyConfig& config); |
- |
- // Tries to update the configuration if it hasn't been checked in a while. |
- void UpdateConfigIfOld(); |
- |
- // Returns true if this ProxyService is downloading a PAC script on behalf |
- // of ProxyResolverWithoutFetch. Resolve requests will be frozen until |
- // the fetch has completed. |
- bool IsFetchingPacScript() const { |
- return in_progress_fetch_config_id_ != ProxyConfig::INVALID_ID; |
- } |
- |
- // Callback for when the PAC script has finished downloading. |
- void OnScriptFetchCompletion(int result); |
- |
- // Returns ERR_IO_PENDING if the request cannot be completed synchronously. |
- // Otherwise it fills |result| with the proxy information for |url|. |
- // Completing synchronously means we don't need to query ProxyResolver. |
- // (ProxyResolver runs on PAC thread.) |
- int TryToCompleteSynchronously(const GURL& url, ProxyInfo* result); |
- |
- // Set |result| with the proxy to use for |url|, based on |rules|. |
- void ApplyProxyRules(const GURL& url, |
- const ProxyConfig::ProxyRules& rules, |
- ProxyInfo* result); |
- |
- // Starts the PAC thread if it isn't already running. |
- void InitPacThread(); |
- |
- // Starts the next request from |pending_requests_| is possible. |
- // |recent_req| is the request that just got added, or NULL. |
- void ProcessPendingRequests(PacRequest* recent_req); |
- |
- // Removes the front entry of the requests queue. |expected_req| is our |
- // expectation of what the front of the request queue is; it is only used by |
+ // Removes the front entry of the jobs queue. |expected_job| is our |
+ // expectation of what the front of the job queue is; it is only used by |
// DCHECK for verification purposes. |
- void RemoveFrontOfRequestQueue(PacRequest* expected_req); |
+ void RemoveFrontOfJobsQueueAndStartNext(Job* expected_job); |
- // Called to indicate that a PacRequest completed. The |config_id| parameter |
- // indicates the proxy configuration that was queried. |result_code| is OK |
- // if the PAC file could be downloaded and executed. Otherwise, it is an |
- // error code, indicating a bad proxy configuration. |
- void DidCompletePacRequest(int config_id, int result_code); |
- |
- // Returns true if the URL passed in should not go through the proxy server. |
- // 1. If the bypass proxy list contains the string <local> and the URL |
- // passed in is a local URL, i.e. a URL without a DOT (.) |
- // 2. The URL matches one of the entities in the proxy bypass list. |
- bool ShouldBypassProxyForURL(const GURL& url); |
- |
- scoped_ptr<ProxyConfigService> config_service_; |
+ // The synchronous resolver implementation. |
scoped_ptr<ProxyResolver> resolver_; |
- scoped_ptr<base::Thread> pac_thread_; |
- // We store the proxy config and a counter (ID) that is incremented each time |
- // the config changes. |
- ProxyConfig config_; |
+ // The thread where |resolver_| is run on. |
+ // Note that declaration ordering is important here. |thread_| needs to be |
+ // destroyed *before* |resolver_|, in case |resolver_| is currently |
+ // executing on |thread_|. |
+ scoped_ptr<base::Thread> thread_; |
- // Increasing ID to give to the next ProxyConfig that we set. |
- int next_config_id_; |
- |
- // Indicates that the configuration is bad and should be ignored. |
- bool config_is_bad_; |
- |
- // The time when the proxy configuration was last read from the system. |
- base::TimeTicks config_last_update_time_; |
- |
- // Map of the known bad proxies and the information about the retry time. |
- ProxyRetryInfoMap proxy_retry_info_; |
- |
- // FIFO queue of pending/inprogress requests. |
- typedef std::deque<scoped_refptr<PacRequest> > PendingRequestsQueue; |
- PendingRequestsQueue pending_requests_; |
- |
- // The fetcher to use when downloading PAC scripts for the ProxyResolver. |
- // This dependency can be NULL if our ProxyResolver has no need for |
- // external PAC script fetching. |
- scoped_ptr<ProxyScriptFetcher> proxy_script_fetcher_; |
- |
- // Callback for when |proxy_script_fetcher_| is done. |
- CompletionCallbackImpl<ProxyService> proxy_script_fetcher_callback_; |
- |
- // The ID of the configuration for which we last downloaded a PAC script. |
- // If no PAC script has been fetched yet, will be ProxyConfig::INVALID_ID. |
- ProxyConfig::ID fetched_pac_config_id_; |
- |
- // The error corresponding with |fetched_pac_config_id_|, or OK. |
- int fetched_pac_error_; |
- |
- // The ID of the configuration for which we are currently downloading the |
- // PAC script. If no fetch is in progress, will be ProxyConfig::INVALID_ID. |
- ProxyConfig::ID in_progress_fetch_config_id_; |
- |
- // The results of the current in progress fetch, or empty string. |
- std::string in_progress_fetch_bytes_; |
- |
- DISALLOW_COPY_AND_ASSIGN(ProxyService); |
+ PendingJobsQueue pending_jobs_; |
}; |
-// Wrapper for invoking methods on a ProxyService synchronously. |
-class SyncProxyServiceHelper |
- : public base::RefCountedThreadSafe<SyncProxyServiceHelper> { |
- public: |
- SyncProxyServiceHelper(MessageLoop* io_message_loop, |
- ProxyService* proxy_service); |
- |
- int ResolveProxy(const GURL& url, ProxyInfo* proxy_info); |
- int ReconsiderProxyAfterError(const GURL& url, ProxyInfo* proxy_info); |
- |
- private: |
- void StartAsyncResolve(const GURL& url); |
- void StartAsyncReconsider(const GURL& url); |
- |
- void OnCompletion(int result); |
- |
- MessageLoop* io_message_loop_; |
- ProxyService* proxy_service_; |
- |
- base::WaitableEvent event_; |
- CompletionCallbackImpl<SyncProxyServiceHelper> callback_; |
- ProxyInfo proxy_info_; |
- int result_; |
-}; |
- |
} // namespace net |
-#endif // NET_PROXY_PROXY_SERVICE_H_ |
+#endif // NET_PROXY_SINGLE_THREADED_PROXY_RESOLVER_H_ |