|
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 "nsIStreamLoader.h" |
|
11 #include "nsIInterfaceRequestor.h" |
|
12 #include "nsIChannelEventSink.h" |
|
13 #include "ProxyAutoConfig.h" |
|
14 #include "nsThreadUtils.h" |
|
15 #include "nsIURI.h" |
|
16 #include "nsCOMPtr.h" |
|
17 #include "nsString.h" |
|
18 #include "mozilla/Attributes.h" |
|
19 #include "mozilla/LinkedList.h" |
|
20 #include "nsAutoPtr.h" |
|
21 #include "mozilla/TimeStamp.h" |
|
22 #include "prlog.h" |
|
23 |
|
24 class nsPACMan; |
|
25 class nsISystemProxySettings; |
|
26 class nsIThread; |
|
27 class WaitForThreadShutdown; |
|
28 |
|
29 /** |
|
30 * This class defines a callback interface used by AsyncGetProxyForChannel. |
|
31 */ |
|
32 class NS_NO_VTABLE nsPACManCallback : public nsISupports |
|
33 { |
|
34 public: |
|
35 /** |
|
36 * This method is invoked on the same thread that called AsyncGetProxyForChannel. |
|
37 * |
|
38 * @param status |
|
39 * This parameter indicates whether or not the PAC query succeeded. |
|
40 * @param pacString |
|
41 * This parameter holds the value of the PAC string. It is empty when |
|
42 * status is a failure code. |
|
43 * @param newPACURL |
|
44 * This parameter holds the URL of a new PAC file that should be loaded |
|
45 * before the query is evaluated again. At least one of pacString and |
|
46 * newPACURL should be 0 length. |
|
47 */ |
|
48 virtual void OnQueryComplete(nsresult status, |
|
49 const nsCString &pacString, |
|
50 const nsCString &newPACURL) = 0; |
|
51 }; |
|
52 |
|
53 class PendingPACQuery MOZ_FINAL : public nsRunnable, |
|
54 public mozilla::LinkedListElement<PendingPACQuery> |
|
55 { |
|
56 public: |
|
57 PendingPACQuery(nsPACMan *pacMan, nsIURI *uri, |
|
58 nsPACManCallback *callback, bool mainThreadResponse); |
|
59 |
|
60 // can be called from either thread |
|
61 void Complete(nsresult status, const nsCString &pacString); |
|
62 void UseAlternatePACFile(const nsCString &pacURL); |
|
63 |
|
64 nsCString mSpec; |
|
65 nsCString mScheme; |
|
66 nsCString mHost; |
|
67 int32_t mPort; |
|
68 |
|
69 NS_IMETHOD Run(void); /* nsRunnable */ |
|
70 |
|
71 private: |
|
72 nsPACMan *mPACMan; // weak reference |
|
73 nsRefPtr<nsPACManCallback> mCallback; |
|
74 bool mOnMainThreadOnly; |
|
75 }; |
|
76 |
|
77 /** |
|
78 * This class provides an abstraction layer above the PAC thread. The methods |
|
79 * defined on this class are intended to be called on the main thread only. |
|
80 */ |
|
81 |
|
82 class nsPACMan MOZ_FINAL : public nsIStreamLoaderObserver |
|
83 , public nsIInterfaceRequestor |
|
84 , public nsIChannelEventSink |
|
85 { |
|
86 public: |
|
87 NS_DECL_THREADSAFE_ISUPPORTS |
|
88 |
|
89 nsPACMan(); |
|
90 |
|
91 /** |
|
92 * This method may be called to shutdown the PAC manager. Any async queries |
|
93 * that have not yet completed will either finish normally or be canceled by |
|
94 * the time this method returns. |
|
95 */ |
|
96 void Shutdown(); |
|
97 |
|
98 /** |
|
99 * This method queries a PAC result asynchronously. The callback runs on the |
|
100 * calling thread. If the PAC file has not yet been loaded, then this method |
|
101 * will queue up the request, and complete it once the PAC file has been |
|
102 * loaded. |
|
103 * |
|
104 * @param channel |
|
105 * The channel to query. |
|
106 * @param callback |
|
107 * The callback to run once the PAC result is available. |
|
108 * @param mustCallbackOnMainThread |
|
109 * If set to false the callback can be made from the PAC thread |
|
110 */ |
|
111 nsresult AsyncGetProxyForChannel(nsIChannel *channel, nsPACManCallback *callback, |
|
112 bool mustCallbackOnMainThread); |
|
113 |
|
114 /** |
|
115 * This method may be called to reload the PAC file. While we are loading |
|
116 * the PAC file, any asynchronous PAC queries will be queued up to be |
|
117 * processed once the PAC file finishes loading. |
|
118 * |
|
119 * @param pacSpec |
|
120 * The non normalized uri spec of this URI used for comparison with |
|
121 * system proxy settings to determine if the PAC uri has changed. |
|
122 */ |
|
123 nsresult LoadPACFromURI(const nsCString &pacSpec); |
|
124 |
|
125 /** |
|
126 * Returns true if we are currently loading the PAC file. |
|
127 */ |
|
128 bool IsLoading() { return mLoader != nullptr; } |
|
129 |
|
130 /** |
|
131 * Returns true if the given URI matches the URI of our PAC file or the |
|
132 * URI it has been redirected to. In the case of a chain of redirections |
|
133 * only the current one being followed and the original are considered |
|
134 * becuase this information is used, respectively, to determine if we |
|
135 * should bypass the proxy (to fetch the pac file) or if the pac |
|
136 * configuration has changed (and we should reload the pac file) |
|
137 */ |
|
138 bool IsPACURI(const nsACString &spec) |
|
139 { |
|
140 return mPACURISpec.Equals(spec) || mPACURIRedirectSpec.Equals(spec) || |
|
141 mNormalPACURISpec.Equals(spec); |
|
142 } |
|
143 |
|
144 bool IsPACURI(nsIURI *uri) { |
|
145 if (mPACURISpec.IsEmpty() && mPACURIRedirectSpec.IsEmpty()) |
|
146 return false; |
|
147 |
|
148 nsAutoCString tmp; |
|
149 uri->GetSpec(tmp); |
|
150 return IsPACURI(tmp); |
|
151 } |
|
152 |
|
153 NS_HIDDEN_(nsresult) Init(nsISystemProxySettings *); |
|
154 static nsPACMan *sInstance; |
|
155 |
|
156 // PAC thread operations only |
|
157 void ProcessPendingQ(); |
|
158 void CancelPendingQ(nsresult); |
|
159 |
|
160 private: |
|
161 NS_DECL_NSISTREAMLOADEROBSERVER |
|
162 NS_DECL_NSIINTERFACEREQUESTOR |
|
163 NS_DECL_NSICHANNELEVENTSINK |
|
164 |
|
165 friend class PendingPACQuery; |
|
166 friend class PACLoadComplete; |
|
167 friend class ExecutePACThreadAction; |
|
168 friend class WaitForThreadShutdown; |
|
169 |
|
170 ~nsPACMan(); |
|
171 |
|
172 /** |
|
173 * Cancel any existing load if any. |
|
174 */ |
|
175 void CancelExistingLoad(); |
|
176 |
|
177 /** |
|
178 * Start loading the PAC file. |
|
179 */ |
|
180 void StartLoading(); |
|
181 |
|
182 /** |
|
183 * Reload the PAC file if there is reason to. |
|
184 */ |
|
185 void MaybeReloadPAC(); |
|
186 |
|
187 /** |
|
188 * Called when we fail to load the PAC file. |
|
189 */ |
|
190 void OnLoadFailure(); |
|
191 |
|
192 /** |
|
193 * PostQuery() only runs on the PAC thread and it is used to |
|
194 * place a pendingPACQuery into the queue and potentially |
|
195 * execute the queue if it was otherwise empty |
|
196 */ |
|
197 nsresult PostQuery(PendingPACQuery *query); |
|
198 |
|
199 // PAC thread operations only |
|
200 void PostProcessPendingQ(); |
|
201 void PostCancelPendingQ(nsresult); |
|
202 bool ProcessPending(); |
|
203 void NamePACThread(); |
|
204 |
|
205 private: |
|
206 mozilla::net::ProxyAutoConfig mPAC; |
|
207 nsCOMPtr<nsIThread> mPACThread; |
|
208 nsCOMPtr<nsISystemProxySettings> mSystemProxySettings; |
|
209 |
|
210 mozilla::LinkedList<PendingPACQuery> mPendingQ; /* pac thread only */ |
|
211 |
|
212 // These specs are not nsIURI so that they can be used off the main thread. |
|
213 // The non-normalized versions are directly from the configuration, the |
|
214 // normalized version has been extracted from an nsIURI |
|
215 nsCString mPACURISpec; |
|
216 nsCString mPACURIRedirectSpec; |
|
217 nsCString mNormalPACURISpec; |
|
218 |
|
219 nsCOMPtr<nsIStreamLoader> mLoader; |
|
220 bool mLoadPending; |
|
221 bool mShutdown; |
|
222 mozilla::TimeStamp mScheduledReload; |
|
223 uint32_t mLoadFailureCount; |
|
224 |
|
225 bool mInProgress; |
|
226 }; |
|
227 |
|
228 namespace mozilla { |
|
229 namespace net { |
|
230 PRLogModuleInfo* GetProxyLog(); |
|
231 } |
|
232 } |
|
233 |
|
234 #endif // nsPACMan_h__ |