OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef NET_PROXY_PROXY_SERVICE_H_ | 5 #ifndef NET_PROXY_SINGLE_THREADED_PROXY_RESOLVER_H_ |
6 #define NET_PROXY_PROXY_SERVICE_H_ | 6 #define NET_PROXY_SINGLE_THREADED_PROXY_RESOLVER_H_ |
7 | 7 |
8 #include <deque> | 8 #include <deque> |
9 #include <string> | 9 #include <string> |
10 | 10 |
11 #include "base/ref_counted.h" | 11 #include "base/ref_counted.h" |
12 #include "base/scoped_ptr.h" | 12 #include "base/scoped_ptr.h" |
13 #include "base/thread.h" | 13 #include "net/proxy/proxy_resolver.h" |
14 #include "base/waitable_event.h" | |
15 #include "net/base/completion_callback.h" | |
16 #include "net/proxy/proxy_server.h" | |
17 #include "net/proxy/proxy_info.h" | |
18 | 14 |
19 class GURL; | 15 namespace base { |
20 class URLRequestContext; | 16 class Thread; |
| 17 } // namespace base |
21 | 18 |
22 namespace net { | 19 namespace net { |
23 | 20 |
24 class ProxyScriptFetcher; | 21 // ProxyResolver implementation that wraps a synchronous ProxyResolver, and |
25 class ProxyConfigService; | 22 // runs it on a single worker thread. If multiple requests accumulate, they |
26 class ProxyResolver; | 23 // are serviced in FIFO order. |
| 24 class SingleThreadedProxyResolver : public ProxyResolver { |
| 25 public: |
27 | 26 |
28 // This class can be used to resolve the proxy server to use when loading a | 27 // |resolver| is a synchronous ProxyResolver implementation. It doesn't |
29 // HTTP(S) URL. It uses the given ProxyResolver to handle the actual proxy | 28 // have to be thread-safe, since it is run on exactly one thread. The |
30 // resolution. See ProxyResolverWinHttp for example. | 29 // constructor takes ownership of |resolver|. |
31 class ProxyService { | 30 explicit SingleThreadedProxyResolver(ProxyResolver* resolver); |
32 public: | |
33 // The instance takes ownership of |config_service| and |resolver|. | |
34 ProxyService(ProxyConfigService* config_service, | |
35 ProxyResolver* resolver); | |
36 | 31 |
37 ~ProxyService(); | 32 virtual ~SingleThreadedProxyResolver(); |
38 | 33 |
39 // Used internally to handle PAC queries. | 34 // ProxyResolver implementation: |
40 class PacRequest; | 35 virtual int GetProxyForURL(const GURL& url, |
| 36 ProxyInfo* results, |
| 37 CompletionCallback* callback, |
| 38 RequestHandle* request); |
| 39 virtual void CancelRequest(RequestHandle request); |
41 | 40 |
42 // Returns ERR_IO_PENDING if the proxy information could not be provided | 41 protected: |
43 // synchronously, to indicate that the result will be available when the | 42 // The wrapped (synchronous) ProxyResolver. |
44 // callback is run. The callback is run on the thread that calls | 43 ProxyResolver* resolver() { return resolver_.get(); } |
45 // ResolveProxy. | |
46 // | |
47 // The caller is responsible for ensuring that |results| and |callback| | |
48 // remain valid until the callback is run or until |pac_request| is cancelled | |
49 // via CancelPacRequest. |pac_request| is only valid while the completion | |
50 // callback is still pending. NULL can be passed for |pac_request| if | |
51 // the caller will not need to cancel the request. | |
52 // | |
53 // We use the three possible proxy access types in the following order, and | |
54 // we only use one of them (no falling back to other access types if the | |
55 // chosen one doesn't work). | |
56 // 1. named proxy | |
57 // 2. PAC URL | |
58 // 3. WPAD auto-detection | |
59 // | |
60 int ResolveProxy(const GURL& url, | |
61 ProxyInfo* results, | |
62 CompletionCallback* callback, | |
63 PacRequest** pac_request); | |
64 | |
65 // This method is called after a failure to connect or resolve a host name. | |
66 // It gives the proxy service an opportunity to reconsider the proxy to use. | |
67 // The |results| parameter contains the results returned by an earlier call | |
68 // to ResolveProxy. The semantics of this call are otherwise similar to | |
69 // ResolveProxy. | |
70 // | |
71 // NULL can be passed for |pac_request| if the caller will not need to | |
72 // cancel the request. | |
73 // | |
74 // Returns ERR_FAILED if there is not another proxy config to try. | |
75 // | |
76 int ReconsiderProxyAfterError(const GURL& url, | |
77 ProxyInfo* results, | |
78 CompletionCallback* callback, | |
79 PacRequest** pac_request); | |
80 | |
81 // Call this method with a non-null |pac_request| to cancel the PAC request. | |
82 void CancelPacRequest(PacRequest* pac_request); | |
83 | |
84 // Sets the ProxyScriptFetcher dependency. This is needed if the ProxyResolver | |
85 // is of type ProxyResolverWithoutFetch. ProxyService takes ownership of | |
86 // |proxy_script_fetcher|. | |
87 void SetProxyScriptFetcher(ProxyScriptFetcher* proxy_script_fetcher); | |
88 | |
89 // Tells this ProxyService to start using a new ProxyConfigService to | |
90 // retrieve its ProxyConfig from. The new ProxyConfigService will immediately | |
91 // be queried for new config info which will be used for all subsequent | |
92 // ResolveProxy calls. ProxyService takes ownership of | |
93 // |new_proxy_config_service|. | |
94 void ResetConfigService(ProxyConfigService* new_proxy_config_service); | |
95 | |
96 // Creates a proxy service using the specified settings. If |pc| is NULL then | |
97 // the system's default proxy settings will be used (on Windows this will | |
98 // use IE's settings). | |
99 // Iff |use_v8_resolver| is true, then the V8 implementation is | |
100 // used. | |
101 // |url_request_context| is only used when use_v8_resolver is true: | |
102 // it specifies the URL request context that will be used if a PAC | |
103 // script needs to be fetched. | |
104 // |io_loop| points to the IO thread's message loop. It is only used | |
105 // when pc is NULL. If both pc and io_loop are NULL, then monitoring | |
106 // of gconf setting changes will be disabled in | |
107 // ProxyConfigServiceLinux. | |
108 // ########################################################################## | |
109 // # See the warnings in net/proxy/proxy_resolver_v8.h describing the | |
110 // # multi-threading model. In order for this to be safe to use, *ALL* the | |
111 // # other V8's running in the process must use v8::Locker. | |
112 // ########################################################################## | |
113 static ProxyService* Create( | |
114 const ProxyConfig* pc, | |
115 bool use_v8_resolver, | |
116 URLRequestContext* url_request_context, | |
117 MessageLoop* io_loop); | |
118 | |
119 // Convenience method that creates a proxy service using the | |
120 // specified fixed settings. |pc| must not be NULL. | |
121 static ProxyService* CreateFixed(const ProxyConfig& pc); | |
122 | |
123 // Creates a proxy service that always fails to fetch the proxy configuration, | |
124 // so it falls back to direct connect. | |
125 static ProxyService* CreateNull(); | |
126 | 44 |
127 private: | 45 private: |
128 friend class PacRequest; | 46 // Refcounted helper class that bridges between origin thread and worker |
| 47 // thread. |
| 48 class Job; |
| 49 friend class Job; |
| 50 // FIFO queue that contains the in-progress job, and any pending jobs. |
| 51 typedef std::deque<scoped_refptr<Job> > PendingJobsQueue; |
129 | 52 |
130 // Creates a config service appropriate for this platform that fetches the | 53 base::Thread* thread() { return thread_.get(); } |
131 // system proxy settings. | |
132 static ProxyConfigService* CreateSystemProxyConfigService( | |
133 MessageLoop* io_loop); | |
134 | 54 |
135 // Creates a proxy resolver appropriate for this platform that doesn't rely | 55 // ProxyResolver implementation: |
136 // on V8. | 56 virtual void SetPacScriptByUrlInternal(const GURL& pac_url); |
137 static ProxyResolver* CreateNonV8ProxyResolver(); | 57 virtual void SetPacScriptByDataInternal(const std::string& bytes); |
138 | 58 |
139 ProxyResolver* resolver() { return resolver_.get(); } | 59 // Helper for shared code between SetPacScriptByUrlInternal() and |
140 base::Thread* pac_thread() { return pac_thread_.get(); } | 60 // SetPacScriptByDataInternal() -- the unused parameter is set to empty. |
| 61 void SetPacScriptHelper(const GURL& pac_url, const std::string& bytes); |
141 | 62 |
142 // Identifies the proxy configuration. | 63 // Starts the worker thread if it isn't already running. |
143 ProxyConfig::ID config_id() const { return config_.id(); } | 64 void EnsureThreadStarted(); |
144 | 65 |
145 // Returns true if we have called UpdateConfig() at least once. | 66 // Starts the next job from |pending_jobs_| if possible. |
146 bool config_has_been_initialized() const { | 67 void ProcessPendingJobs(); |
147 return config_.id() != ProxyConfig::INVALID_ID; | |
148 } | |
149 | 68 |
150 // Checks to see if the proxy configuration changed, and then updates config_ | 69 // Removes the front entry of the jobs queue. |expected_job| is our |
151 // to reference the new configuration. | 70 // expectation of what the front of the job queue is; it is only used by |
152 void UpdateConfig(); | 71 // DCHECK for verification purposes. |
| 72 void RemoveFrontOfJobsQueueAndStartNext(Job* expected_job); |
153 | 73 |
154 // Assign |config| as the current configuration. | 74 // The synchronous resolver implementation. |
155 void SetConfig(const ProxyConfig& config); | 75 scoped_ptr<ProxyResolver> resolver_; |
156 | 76 |
157 // Tries to update the configuration if it hasn't been checked in a while. | 77 // The thread where |resolver_| is run on. |
158 void UpdateConfigIfOld(); | 78 // Note that declaration ordering is important here. |thread_| needs to be |
| 79 // destroyed *before* |resolver_|, in case |resolver_| is currently |
| 80 // executing on |thread_|. |
| 81 scoped_ptr<base::Thread> thread_; |
159 | 82 |
160 // Returns true if this ProxyService is downloading a PAC script on behalf | 83 PendingJobsQueue pending_jobs_; |
161 // of ProxyResolverWithoutFetch. Resolve requests will be frozen until | |
162 // the fetch has completed. | |
163 bool IsFetchingPacScript() const { | |
164 return in_progress_fetch_config_id_ != ProxyConfig::INVALID_ID; | |
165 } | |
166 | |
167 // Callback for when the PAC script has finished downloading. | |
168 void OnScriptFetchCompletion(int result); | |
169 | |
170 // Returns ERR_IO_PENDING if the request cannot be completed synchronously. | |
171 // Otherwise it fills |result| with the proxy information for |url|. | |
172 // Completing synchronously means we don't need to query ProxyResolver. | |
173 // (ProxyResolver runs on PAC thread.) | |
174 int TryToCompleteSynchronously(const GURL& url, ProxyInfo* result); | |
175 | |
176 // Set |result| with the proxy to use for |url|, based on |rules|. | |
177 void ApplyProxyRules(const GURL& url, | |
178 const ProxyConfig::ProxyRules& rules, | |
179 ProxyInfo* result); | |
180 | |
181 // Starts the PAC thread if it isn't already running. | |
182 void InitPacThread(); | |
183 | |
184 // Starts the next request from |pending_requests_| is possible. | |
185 // |recent_req| is the request that just got added, or NULL. | |
186 void ProcessPendingRequests(PacRequest* recent_req); | |
187 | |
188 // Removes the front entry of the requests queue. |expected_req| is our | |
189 // expectation of what the front of the request queue is; it is only used by | |
190 // DCHECK for verification purposes. | |
191 void RemoveFrontOfRequestQueue(PacRequest* expected_req); | |
192 | |
193 // Called to indicate that a PacRequest completed. The |config_id| parameter | |
194 // indicates the proxy configuration that was queried. |result_code| is OK | |
195 // if the PAC file could be downloaded and executed. Otherwise, it is an | |
196 // error code, indicating a bad proxy configuration. | |
197 void DidCompletePacRequest(int config_id, int result_code); | |
198 | |
199 // Returns true if the URL passed in should not go through the proxy server. | |
200 // 1. If the bypass proxy list contains the string <local> and the URL | |
201 // passed in is a local URL, i.e. a URL without a DOT (.) | |
202 // 2. The URL matches one of the entities in the proxy bypass list. | |
203 bool ShouldBypassProxyForURL(const GURL& url); | |
204 | |
205 scoped_ptr<ProxyConfigService> config_service_; | |
206 scoped_ptr<ProxyResolver> resolver_; | |
207 scoped_ptr<base::Thread> pac_thread_; | |
208 | |
209 // We store the proxy config and a counter (ID) that is incremented each time | |
210 // the config changes. | |
211 ProxyConfig config_; | |
212 | |
213 // Increasing ID to give to the next ProxyConfig that we set. | |
214 int next_config_id_; | |
215 | |
216 // Indicates that the configuration is bad and should be ignored. | |
217 bool config_is_bad_; | |
218 | |
219 // The time when the proxy configuration was last read from the system. | |
220 base::TimeTicks config_last_update_time_; | |
221 | |
222 // Map of the known bad proxies and the information about the retry time. | |
223 ProxyRetryInfoMap proxy_retry_info_; | |
224 | |
225 // FIFO queue of pending/inprogress requests. | |
226 typedef std::deque<scoped_refptr<PacRequest> > PendingRequestsQueue; | |
227 PendingRequestsQueue pending_requests_; | |
228 | |
229 // The fetcher to use when downloading PAC scripts for the ProxyResolver. | |
230 // This dependency can be NULL if our ProxyResolver has no need for | |
231 // external PAC script fetching. | |
232 scoped_ptr<ProxyScriptFetcher> proxy_script_fetcher_; | |
233 | |
234 // Callback for when |proxy_script_fetcher_| is done. | |
235 CompletionCallbackImpl<ProxyService> proxy_script_fetcher_callback_; | |
236 | |
237 // The ID of the configuration for which we last downloaded a PAC script. | |
238 // If no PAC script has been fetched yet, will be ProxyConfig::INVALID_ID. | |
239 ProxyConfig::ID fetched_pac_config_id_; | |
240 | |
241 // The error corresponding with |fetched_pac_config_id_|, or OK. | |
242 int fetched_pac_error_; | |
243 | |
244 // The ID of the configuration for which we are currently downloading the | |
245 // PAC script. If no fetch is in progress, will be ProxyConfig::INVALID_ID. | |
246 ProxyConfig::ID in_progress_fetch_config_id_; | |
247 | |
248 // The results of the current in progress fetch, or empty string. | |
249 std::string in_progress_fetch_bytes_; | |
250 | |
251 DISALLOW_COPY_AND_ASSIGN(ProxyService); | |
252 }; | |
253 | |
254 // Wrapper for invoking methods on a ProxyService synchronously. | |
255 class SyncProxyServiceHelper | |
256 : public base::RefCountedThreadSafe<SyncProxyServiceHelper> { | |
257 public: | |
258 SyncProxyServiceHelper(MessageLoop* io_message_loop, | |
259 ProxyService* proxy_service); | |
260 | |
261 int ResolveProxy(const GURL& url, ProxyInfo* proxy_info); | |
262 int ReconsiderProxyAfterError(const GURL& url, ProxyInfo* proxy_info); | |
263 | |
264 private: | |
265 void StartAsyncResolve(const GURL& url); | |
266 void StartAsyncReconsider(const GURL& url); | |
267 | |
268 void OnCompletion(int result); | |
269 | |
270 MessageLoop* io_message_loop_; | |
271 ProxyService* proxy_service_; | |
272 | |
273 base::WaitableEvent event_; | |
274 CompletionCallbackImpl<SyncProxyServiceHelper> callback_; | |
275 ProxyInfo proxy_info_; | |
276 int result_; | |
277 }; | 84 }; |
278 | 85 |
279 } // namespace net | 86 } // namespace net |
280 | 87 |
281 #endif // NET_PROXY_PROXY_SERVICE_H_ | 88 #endif // NET_PROXY_SINGLE_THREADED_PROXY_RESOLVER_H_ |
OLD | NEW |