Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #ifndef nsProtocolProxyService_h__
7 : #define nsProtocolProxyService_h__
8 :
9 : #include "nsString.h"
10 : #include "nsCOMPtr.h"
11 : #include "nsAutoPtr.h"
12 : #include "nsTArray.h"
13 : #include "nsIProtocolProxyService2.h"
14 : #include "nsIProtocolProxyFilter.h"
15 : #include "nsIProxyInfo.h"
16 : #include "nsIObserver.h"
17 : #include "nsIThread.h"
18 : #include "nsDataHashtable.h"
19 : #include "nsHashKeys.h"
20 : #include "prio.h"
21 : #include "mozilla/Attributes.h"
22 :
23 : class nsIPrefBranch;
24 : class nsISystemProxySettings;
25 :
26 : namespace mozilla {
27 : namespace net {
28 :
29 : typedef nsDataHashtable<nsCStringHashKey, uint32_t> nsFailedProxyTable;
30 :
31 : class nsPACMan;
32 : class nsProxyInfo;
33 : struct nsProtocolInfo;
34 :
35 : // CID for the nsProtocolProxyService class
36 : // 091eedd8-8bae-4fe3-ad62-0c87351e640d
37 : #define NS_PROTOCOL_PROXY_SERVICE_IMPL_CID \
38 : { 0x091eedd8, 0x8bae, 0x4fe3, \
39 : { 0xad, 0x62, 0x0c, 0x87, 0x35, 0x1e, 0x64, 0x0d } }
40 :
41 : class nsProtocolProxyService final : public nsIProtocolProxyService2
42 : , public nsIObserver
43 : {
44 : public:
45 : NS_DECL_ISUPPORTS
46 : NS_DECL_NSIPROTOCOLPROXYSERVICE2
47 : NS_DECL_NSIPROTOCOLPROXYSERVICE
48 : NS_DECL_NSIOBSERVER
49 :
50 : NS_DECLARE_STATIC_IID_ACCESSOR(NS_PROTOCOL_PROXY_SERVICE_IMPL_CID)
51 :
52 : nsProtocolProxyService();
53 :
54 : nsresult Init();
55 :
56 : protected:
57 : friend class nsAsyncResolveRequest;
58 : friend class TestProtocolProxyService_LoadHostFilters_Test; // for gtest
59 :
60 : ~nsProtocolProxyService();
61 :
62 : /**
63 : * This method is called whenever a preference may have changed or
64 : * to initialize all preferences.
65 : *
66 : * @param prefs
67 : * This must be a pointer to the root pref branch.
68 : * @param name
69 : * This can be the name of a fully-qualified preference, or it can
70 : * be null, in which case all preferences will be initialized.
71 : */
72 : void PrefsChanged(nsIPrefBranch *prefs, const char *name);
73 :
74 : /**
75 : * This method is called to create a nsProxyInfo instance from the given
76 : * PAC-style proxy string. It parses up to the end of the string, or to
77 : * the next ';' character.
78 : *
79 : * @param proxy
80 : * The PAC-style proxy string to parse. This must not be null.
81 : * @param aResolveFlags
82 : * The flags passed to Resolve or AsyncResolve that are stored in
83 : * proxyInfo.
84 : * @param result
85 : * Upon return this points to a newly allocated nsProxyInfo or null
86 : * if the proxy string was invalid.
87 : *
88 : * @return A pointer beyond the parsed proxy string (never null).
89 : */
90 : const char * ExtractProxyInfo(const char *proxy,
91 : uint32_t aResolveFlags,
92 : nsProxyInfo **result);
93 :
94 : /**
95 : * Load the specified PAC file.
96 : *
97 : * @param pacURI
98 : * The URI spec of the PAC file to load.
99 : */
100 : nsresult ConfigureFromPAC(const nsCString &pacURI, bool forceReload);
101 :
102 : /**
103 : * This method builds a list of nsProxyInfo objects from the given PAC-
104 : * style string.
105 : *
106 : * @param pacString
107 : * The PAC-style proxy string to parse. This may be empty.
108 : * @param aResolveFlags
109 : * The flags passed to Resolve or AsyncResolve that are stored in
110 : * proxyInfo.
111 : * @param result
112 : * The resulting list of proxy info objects.
113 : */
114 : void ProcessPACString(const nsCString &pacString,
115 : uint32_t aResolveFlags,
116 : nsIProxyInfo **result);
117 :
118 : /**
119 : * This method generates a string valued identifier for the given
120 : * nsProxyInfo object.
121 : *
122 : * @param pi
123 : * The nsProxyInfo object from which to generate the key.
124 : * @param result
125 : * Upon return, this parameter holds the generated key.
126 : */
127 : void GetProxyKey(nsProxyInfo *pi, nsCString &result);
128 :
129 : /**
130 : * @return Seconds since start of session.
131 : */
132 : uint32_t SecondsSinceSessionStart();
133 :
134 : /**
135 : * This method removes the specified proxy from the disabled list.
136 : *
137 : * @param pi
138 : * The nsProxyInfo object identifying the proxy to enable.
139 : */
140 : void EnableProxy(nsProxyInfo *pi);
141 :
142 : /**
143 : * This method adds the specified proxy to the disabled list.
144 : *
145 : * @param pi
146 : * The nsProxyInfo object identifying the proxy to disable.
147 : */
148 : void DisableProxy(nsProxyInfo *pi);
149 :
150 : /**
151 : * This method tests to see if the given proxy is disabled.
152 : *
153 : * @param pi
154 : * The nsProxyInfo object identifying the proxy to test.
155 : *
156 : * @return True if the specified proxy is disabled.
157 : */
158 : bool IsProxyDisabled(nsProxyInfo *pi);
159 :
160 : /**
161 : * This method queries the protocol handler for the given scheme to check
162 : * for the protocol flags and default port.
163 : *
164 : * @param uri
165 : * The URI to query.
166 : * @param info
167 : * Holds information about the protocol upon return. Pass address
168 : * of structure when you call this method. This parameter must not
169 : * be null.
170 : */
171 : nsresult GetProtocolInfo(nsIURI *uri, nsProtocolInfo *result);
172 :
173 : /**
174 : * This method is an internal version nsIProtocolProxyService::newProxyInfo
175 : * that expects a string literal for the type.
176 : *
177 : * @param type
178 : * The proxy type.
179 : * @param host
180 : * The proxy host name (UTF-8 ok).
181 : * @param port
182 : * The proxy port number.
183 : * @param username
184 : * The username for the proxy (ASCII). May be "", but not null.
185 : * @param password
186 : * The password for the proxy (ASCII). May be "", but not null.
187 : * @param flags
188 : * The proxy flags (nsIProxyInfo::flags).
189 : * @param timeout
190 : * The failover timeout for this proxy.
191 : * @param next
192 : * The next proxy to try if this one fails.
193 : * @param aResolveFlags
194 : * The flags passed to resolve (from nsIProtocolProxyService).
195 : * @param result
196 : * The resulting nsIProxyInfo object.
197 : */
198 : nsresult NewProxyInfo_Internal(const char *type,
199 : const nsACString &host,
200 : int32_t port,
201 : const nsACString &username,
202 : const nsACString &password,
203 : uint32_t flags,
204 : uint32_t timeout,
205 : nsIProxyInfo *next,
206 : uint32_t aResolveFlags,
207 : nsIProxyInfo **result);
208 :
209 : /**
210 : * This method is an internal version of Resolve that does not query PAC.
211 : * It performs all of the built-in processing, and reports back to the
212 : * caller with either the proxy info result or a flag to instruct the
213 : * caller to use PAC instead.
214 : *
215 : * @param channel
216 : * The channel to test.
217 : * @param info
218 : * Information about the URI's protocol.
219 : * @param flags
220 : * The flags passed to either the resolve or the asyncResolve method.
221 : * @param usePAC
222 : * If this flag is set upon return, then PAC should be queried to
223 : * resolve the proxy info.
224 : * @param result
225 : * The resulting proxy info or null.
226 : */
227 : nsresult Resolve_Internal(nsIChannel *channel,
228 : const nsProtocolInfo &info,
229 : uint32_t flags,
230 : bool *usePAC,
231 : nsIProxyInfo **result);
232 :
233 : /**
234 : * This method applies the registered filters to the given proxy info
235 : * list, and returns a possibly modified list.
236 : *
237 : * @param channel
238 : * The channel corresponding to this proxy info list.
239 : * @param info
240 : * Information about the URI's protocol.
241 : * @param proxyInfo
242 : * The proxy info list to be modified. This is an inout param.
243 : */
244 : void ApplyFilters(nsIChannel *channel, const nsProtocolInfo &info,
245 : nsIProxyInfo **proxyInfo);
246 :
247 : /**
248 : * This method is a simple wrapper around ApplyFilters that takes the
249 : * proxy info list inout param as a nsCOMPtr.
250 : */
251 6 : inline void ApplyFilters(nsIChannel *channel, const nsProtocolInfo &info,
252 : nsCOMPtr<nsIProxyInfo> &proxyInfo)
253 : {
254 6 : nsIProxyInfo *pi = nullptr;
255 6 : proxyInfo.swap(pi);
256 6 : ApplyFilters(channel, info, &pi);
257 6 : proxyInfo.swap(pi);
258 6 : }
259 :
260 : /**
261 : * This method prunes out disabled and disallowed proxies from a given
262 : * proxy info list.
263 : *
264 : * @param info
265 : * Information about the URI's protocol.
266 : * @param proxyInfo
267 : * The proxy info list to be modified. This is an inout param.
268 : */
269 : void PruneProxyInfo(const nsProtocolInfo &info,
270 : nsIProxyInfo **proxyInfo);
271 :
272 : /**
273 : * This method populates mHostFiltersArray from the given string.
274 : *
275 : * @param hostFilters
276 : * A "no-proxy-for" exclusion list.
277 : */
278 : void LoadHostFilters(const nsACString& hostFilters);
279 :
280 : /**
281 : * This method checks the given URI against mHostFiltersArray.
282 : *
283 : * @param uri
284 : * The URI to test.
285 : * @param defaultPort
286 : * The default port for the given URI.
287 : *
288 : * @return True if the URI can use the specified proxy.
289 : */
290 : bool CanUseProxy(nsIURI *uri, int32_t defaultPort);
291 :
292 : /**
293 : * Disable Prefetch in the DNS service if a proxy is in use.
294 : *
295 : * @param aProxy
296 : * The proxy information
297 : */
298 : void MaybeDisableDNSPrefetch(nsIProxyInfo *aProxy);
299 :
300 : private:
301 : nsresult SetupPACThread(nsIEventTarget *mainThreadEventTarget = nullptr);
302 : nsresult ResetPACThread();
303 : nsresult ReloadNetworkPAC();
304 :
305 : nsresult AsyncConfigureFromPAC(bool aForceReload, bool aResetPACThread);
306 : nsresult OnAsyncGetPACURI(bool aForceReload,
307 : bool aResetPACThread,
308 : nsresult aResult,
309 : const nsACString& aUri);
310 :
311 : public:
312 : // The Sun Forte compiler and others implement older versions of the
313 : // C++ standard's rules on access and nested classes. These structs
314 : // need to be public in order to deal with those compilers.
315 :
316 : struct HostInfoIP {
317 : uint16_t family;
318 : uint16_t mask_len;
319 : PRIPv6Addr addr; // possibly IPv4-mapped address
320 : };
321 :
322 : struct HostInfoName {
323 : char *host;
324 : uint32_t host_len;
325 : };
326 :
327 : protected:
328 :
329 : // simplified array of filters defined by this struct
330 : struct HostInfo {
331 : bool is_ipaddr;
332 : int32_t port;
333 : union {
334 : HostInfoIP ip;
335 : HostInfoName name;
336 : };
337 :
338 2 : HostInfo()
339 2 : : is_ipaddr(false)
340 2 : , port(0)
341 2 : { /* other members intentionally uninitialized */ }
342 0 : ~HostInfo() {
343 0 : if (!is_ipaddr && name.host)
344 0 : free(name.host);
345 0 : }
346 : };
347 :
348 : // An instance of this struct is allocated for each registered
349 : // nsIProtocolProxyFilter and each nsIProtocolProxyChannelFilter.
350 : struct FilterLink {
351 : struct FilterLink *next;
352 : uint32_t position;
353 : nsCOMPtr<nsIProtocolProxyFilter> filter;
354 : nsCOMPtr<nsIProtocolProxyChannelFilter> channelFilter;
355 0 : FilterLink(uint32_t p, nsIProtocolProxyFilter *f)
356 0 : : next(nullptr), position(p), filter(f), channelFilter(nullptr) {}
357 0 : FilterLink(uint32_t p, nsIProtocolProxyChannelFilter *cf)
358 0 : : next(nullptr), position(p), filter(nullptr), channelFilter(cf) {}
359 : // Chain deletion to simplify cleaning up the filter links
360 0 : ~FilterLink() { if (next) delete next; }
361 : };
362 :
363 : private:
364 : // Private methods to insert and remove FilterLinks from the FilterLink chain.
365 : nsresult InsertFilterLink(FilterLink *link, uint32_t position);
366 : nsresult RemoveFilterLink(nsISupports *givenObject);
367 :
368 : protected:
369 : // Indicates if local hosts (plain hostnames, no dots) should use the proxy
370 : bool mFilterLocalHosts;
371 :
372 : // Holds an array of HostInfo objects
373 : nsTArray<nsAutoPtr<HostInfo> > mHostFiltersArray;
374 :
375 : // Points to the start of a sorted by position, singly linked list
376 : // of FilterLink objects.
377 : FilterLink *mFilters;
378 :
379 : uint32_t mProxyConfig;
380 :
381 : nsCString mHTTPProxyHost;
382 : int32_t mHTTPProxyPort;
383 :
384 : nsCString mFTPProxyHost;
385 : int32_t mFTPProxyPort;
386 :
387 : nsCString mHTTPSProxyHost;
388 : int32_t mHTTPSProxyPort;
389 :
390 : // mSOCKSProxyTarget could be a host, a domain socket path,
391 : // or a named-pipe name.
392 : nsCString mSOCKSProxyTarget;
393 : int32_t mSOCKSProxyPort;
394 : int32_t mSOCKSProxyVersion;
395 : bool mSOCKSProxyRemoteDNS;
396 : bool mProxyOverTLS;
397 :
398 : RefPtr<nsPACMan> mPACMan; // non-null if we are using PAC
399 : nsCOMPtr<nsISystemProxySettings> mSystemProxySettings;
400 :
401 : PRTime mSessionStart;
402 : nsFailedProxyTable mFailedProxies;
403 : int32_t mFailedProxyTimeout;
404 :
405 : private:
406 : nsresult AsyncResolveInternal(nsIChannel *channel, uint32_t flags,
407 : nsIProtocolProxyCallback *callback,
408 : nsICancelable **result,
409 : bool isSyncOK,
410 : nsIEventTarget *mainThreadEventTarget);
411 : bool mIsShutdown;
412 : nsCOMPtr<nsIThread> mProxySettingThread;
413 : };
414 :
415 : NS_DEFINE_STATIC_IID_ACCESSOR(nsProtocolProxyService, NS_PROTOCOL_PROXY_SERVICE_IMPL_CID)
416 :
417 : } // namespace net
418 : } // namespace mozilla
419 :
420 : #endif // !nsProtocolProxyService_h__
|