/src/mozilla-central/netwerk/base/nsPACMan.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim:set ts=2 sw=2 sts=2 et cindent: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #ifndef nsPACMan_h__ |
8 | | #define nsPACMan_h__ |
9 | | |
10 | | #include "mozilla/Atomics.h" |
11 | | #include "mozilla/Attributes.h" |
12 | | #include "mozilla/LinkedList.h" |
13 | | #include "mozilla/Logging.h" |
14 | | #include "mozilla/net/NeckoTargetHolder.h" |
15 | | #include "mozilla/TimeStamp.h" |
16 | | #include "nsAutoPtr.h" |
17 | | #include "nsCOMPtr.h" |
18 | | #include "nsIChannelEventSink.h" |
19 | | #include "nsIInterfaceRequestor.h" |
20 | | #include "nsIStreamLoader.h" |
21 | | #include "nsThreadUtils.h" |
22 | | #include "nsIURI.h" |
23 | | #include "nsString.h" |
24 | | #include "ProxyAutoConfig.h" |
25 | | |
26 | | class nsISystemProxySettings; |
27 | | class nsIDHCPClient; |
28 | | class nsIThread; |
29 | | |
30 | | namespace mozilla { |
31 | | namespace net { |
32 | | |
33 | | class nsPACMan; |
34 | | class WaitForThreadShutdown; |
35 | | |
36 | | /** |
37 | | * This class defines a callback interface used by AsyncGetProxyForURI. |
38 | | */ |
39 | | class NS_NO_VTABLE nsPACManCallback : public nsISupports |
40 | | { |
41 | | public: |
42 | | /** |
43 | | * This method is invoked on the same thread that called AsyncGetProxyForURI. |
44 | | * |
45 | | * @param status |
46 | | * This parameter indicates whether or not the PAC query succeeded. |
47 | | * @param pacString |
48 | | * This parameter holds the value of the PAC string. It is empty when |
49 | | * status is a failure code. |
50 | | * @param newPACURL |
51 | | * This parameter holds the URL of a new PAC file that should be loaded |
52 | | * before the query is evaluated again. At least one of pacString and |
53 | | * newPACURL should be 0 length. |
54 | | */ |
55 | | virtual void OnQueryComplete(nsresult status, |
56 | | const nsACString &pacString, |
57 | | const nsACString &newPACURL) = 0; |
58 | | }; |
59 | | |
60 | | class PendingPACQuery final : public Runnable, |
61 | | public LinkedListElement<PendingPACQuery> |
62 | | { |
63 | | public: |
64 | | PendingPACQuery(nsPACMan *pacMan, nsIURI *uri, |
65 | | nsPACManCallback *callback, |
66 | | bool mainThreadResponse); |
67 | | |
68 | | // can be called from either thread |
69 | | void Complete(nsresult status, const nsACString &pacString); |
70 | | void UseAlternatePACFile(const nsACString &pacURL); |
71 | | |
72 | | nsCString mSpec; |
73 | | nsCString mScheme; |
74 | | nsCString mHost; |
75 | | int32_t mPort; |
76 | | |
77 | | NS_IMETHOD Run(void) override; /* Runnable */ |
78 | | |
79 | | private: |
80 | | nsPACMan *mPACMan; // weak reference |
81 | | |
82 | | private: |
83 | | RefPtr<nsPACManCallback> mCallback; |
84 | | bool mOnMainThreadOnly; |
85 | | }; |
86 | | |
87 | | /** |
88 | | * This class provides an abstraction layer above the PAC thread. The methods |
89 | | * defined on this class are intended to be called on the main thread only. |
90 | | */ |
91 | | |
92 | | class nsPACMan final : public nsIStreamLoaderObserver |
93 | | , public nsIInterfaceRequestor |
94 | | , public nsIChannelEventSink |
95 | | , public NeckoTargetHolder |
96 | | { |
97 | | public: |
98 | | NS_DECL_THREADSAFE_ISUPPORTS |
99 | | |
100 | | explicit nsPACMan(nsIEventTarget *mainThreadEventTarget); |
101 | | |
102 | | /** |
103 | | * This method may be called to shutdown the PAC manager. Any async queries |
104 | | * that have not yet completed will either finish normally or be canceled by |
105 | | * the time this method returns. |
106 | | */ |
107 | | void Shutdown(); |
108 | | |
109 | | /** |
110 | | * This method queries a PAC result asynchronously. The callback runs on the |
111 | | * calling thread. If the PAC file has not yet been loaded, then this method |
112 | | * will queue up the request, and complete it once the PAC file has been |
113 | | * loaded. |
114 | | * |
115 | | * @param uri |
116 | | * The URI to query. |
117 | | * @param callback |
118 | | * The callback to run once the PAC result is available. |
119 | | * @param mustCallbackOnMainThread |
120 | | * If set to false the callback can be made from the PAC thread |
121 | | */ |
122 | | nsresult AsyncGetProxyForURI(nsIURI *uri, |
123 | | nsPACManCallback *callback, |
124 | | bool mustCallbackOnMainThread); |
125 | | |
126 | | /** |
127 | | * This method may be called to reload the PAC file. While we are loading |
128 | | * the PAC file, any asynchronous PAC queries will be queued up to be |
129 | | * processed once the PAC file finishes loading. |
130 | | * |
131 | | * @param aSpec |
132 | | * The non normalized uri spec of this URI used for comparison with |
133 | | * system proxy settings to determine if the PAC uri has changed. |
134 | | */ |
135 | | nsresult LoadPACFromURI(const nsACString &aSpec); |
136 | | |
137 | | /** |
138 | | * Returns true if we are currently loading the PAC file. |
139 | | */ |
140 | 0 | bool IsLoading() { return mLoader != nullptr; } |
141 | | |
142 | | /** |
143 | | * Returns true if the given URI matches the URI of our PAC file or the |
144 | | * URI it has been redirected to. In the case of a chain of redirections |
145 | | * only the current one being followed and the original are considered |
146 | | * becuase this information is used, respectively, to determine if we |
147 | | * should bypass the proxy (to fetch the pac file) or if the pac |
148 | | * configuration has changed (and we should reload the pac file) |
149 | | */ |
150 | | bool IsPACURI(const nsACString &spec) |
151 | 0 | { |
152 | 0 | return mPACURISpec.Equals(spec) || mPACURIRedirectSpec.Equals(spec) || |
153 | 0 | mNormalPACURISpec.Equals(spec); |
154 | 0 | } |
155 | | |
156 | 0 | bool IsPACURI(nsIURI *uri) { |
157 | 0 | if (mPACURISpec.IsEmpty() && mPACURIRedirectSpec.IsEmpty()) { |
158 | 0 | return false; |
159 | 0 | } |
160 | 0 | |
161 | 0 | nsAutoCString tmp; |
162 | 0 | nsresult rv = uri->GetSpec(tmp); |
163 | 0 | if (NS_FAILED(rv)) { |
164 | 0 | return false; |
165 | 0 | } |
166 | 0 | |
167 | 0 | return IsPACURI(tmp); |
168 | 0 | } |
169 | | |
170 | 0 | bool IsUsingWPAD() { |
171 | 0 | return mAutoDetect; |
172 | 0 | } |
173 | | |
174 | | nsresult Init(nsISystemProxySettings *); |
175 | | static nsPACMan *sInstance; |
176 | | |
177 | | // PAC thread operations only |
178 | | void ProcessPendingQ(); |
179 | | void CancelPendingQ(nsresult, bool aShutdown); |
180 | | |
181 | 0 | void SetWPADOverDHCPEnabled(bool aValue) { mWPADOverDHCPEnabled = aValue; } |
182 | | |
183 | | private: |
184 | | NS_DECL_NSISTREAMLOADEROBSERVER |
185 | | NS_DECL_NSIINTERFACEREQUESTOR |
186 | | NS_DECL_NSICHANNELEVENTSINK |
187 | | |
188 | | friend class PendingPACQuery; |
189 | | friend class PACLoadComplete; |
190 | | friend class ConfigureWPADComplete; |
191 | | friend class ExecutePACThreadAction; |
192 | | friend class WaitForThreadShutdown; |
193 | | friend class TestPACMan; |
194 | | |
195 | | ~nsPACMan(); |
196 | | |
197 | | /** |
198 | | * Cancel any existing load if any. |
199 | | */ |
200 | | void CancelExistingLoad(); |
201 | | |
202 | | /** |
203 | | * Start loading the PAC file. |
204 | | */ |
205 | | void StartLoading(); |
206 | | |
207 | | /** |
208 | | * Continue loading the PAC file. |
209 | | */ |
210 | | void ContinueLoadingAfterPACUriKnown(); |
211 | | |
212 | | /** |
213 | | * Reload the PAC file if there is reason to. |
214 | | */ |
215 | | void MaybeReloadPAC(); |
216 | | |
217 | | /** |
218 | | * Called when we fail to load the PAC file. |
219 | | */ |
220 | | void OnLoadFailure(); |
221 | | |
222 | | /** |
223 | | * PostQuery() only runs on the PAC thread and it is used to |
224 | | * place a pendingPACQuery into the queue and potentially |
225 | | * execute the queue if it was otherwise empty |
226 | | */ |
227 | | nsresult PostQuery(PendingPACQuery *query); |
228 | | |
229 | | // Having found the PAC URI on the PAC thread, copy it to a string which |
230 | | // can be altered on the main thread. |
231 | | void AssignPACURISpec(const nsACString &aSpec); |
232 | | |
233 | | // PAC thread operations only |
234 | | void PostProcessPendingQ(); |
235 | | void PostCancelPendingQ(nsresult, bool aShutdown = false); |
236 | | bool ProcessPending(); |
237 | | nsresult GetPACFromDHCP(nsACString &aSpec); |
238 | | nsresult ConfigureWPAD(nsACString &aSpec); |
239 | | |
240 | | private: |
241 | | /** |
242 | | * Dispatches a runnable to the PAC processing thread. Handles lazy |
243 | | * instantiation of the thread. |
244 | | * |
245 | | * @param aEvent The event to disptach. |
246 | | * @param aSync Whether or not this should be synchronous dispatch. |
247 | | */ |
248 | | nsresult DispatchToPAC(already_AddRefed<nsIRunnable> aEvent, bool aSync = false); |
249 | | |
250 | | ProxyAutoConfig mPAC; |
251 | | nsCOMPtr<nsIThread> mPACThread; |
252 | | nsCOMPtr<nsISystemProxySettings> mSystemProxySettings; |
253 | | nsCOMPtr<nsIDHCPClient> mDHCPClient; |
254 | | |
255 | | LinkedList<PendingPACQuery> mPendingQ; /* pac thread only */ |
256 | | |
257 | | // These specs are not nsIURI so that they can be used off the main thread. |
258 | | // The non-normalized versions are directly from the configuration, the |
259 | | // normalized version has been extracted from an nsIURI |
260 | | nsCString mPACURISpec; |
261 | | nsCString mPACURIRedirectSpec; |
262 | | nsCString mNormalPACURISpec; |
263 | | |
264 | | nsCOMPtr<nsIStreamLoader> mLoader; |
265 | | bool mLoadPending; |
266 | | Atomic<bool, Relaxed> mShutdown; |
267 | | TimeStamp mScheduledReload; |
268 | | uint32_t mLoadFailureCount; |
269 | | |
270 | | bool mInProgress; |
271 | | bool mIncludePath; |
272 | | bool mAutoDetect; |
273 | | bool mWPADOverDHCPEnabled; |
274 | | int32_t mProxyConfigType; |
275 | | }; |
276 | | |
277 | | extern LazyLogModule gProxyLog; |
278 | | |
279 | | } // namespace net |
280 | | } // namespace mozilla |
281 | | |
282 | | #endif // nsPACMan_h__ |