Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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 : #include "nsISystemProxySettings.h"
7 : #include "mozilla/ModuleUtils.h"
8 : #include "nsIServiceManager.h"
9 : #include "nsIGConfService.h"
10 : #include "nsIURI.h"
11 : #include "nsReadableUtils.h"
12 : #include "nsArrayUtils.h"
13 : #include "prnetdb.h"
14 : #include "prenv.h"
15 : #include "nsPrintfCString.h"
16 : #include "nsNetCID.h"
17 : #include "nsNetUtil.h"
18 : #include "nsISupportsPrimitives.h"
19 : #include "nsIGSettingsService.h"
20 : #include "nsInterfaceHashtable.h"
21 : #include "mozilla/Attributes.h"
22 : #include "nsIURI.h"
23 :
24 : class nsUnixSystemProxySettings final : public nsISystemProxySettings {
25 : public:
26 : NS_DECL_ISUPPORTS
27 : NS_DECL_NSISYSTEMPROXYSETTINGS
28 :
29 0 : nsUnixSystemProxySettings()
30 0 : : mSchemeProxySettings(4)
31 : {
32 0 : }
33 : nsresult Init();
34 :
35 : private:
36 0 : ~nsUnixSystemProxySettings() = default;
37 :
38 : nsCOMPtr<nsIGConfService> mGConf;
39 : nsCOMPtr<nsIGSettingsService> mGSettings;
40 : nsCOMPtr<nsIGSettingsCollection> mProxySettings;
41 : nsInterfaceHashtable<nsCStringHashKey, nsIGSettingsCollection> mSchemeProxySettings;
42 : bool IsProxyMode(const char* aMode);
43 : nsresult SetProxyResultFromGConf(const char* aKeyBase, const char* aType, nsACString& aResult);
44 : nsresult GetProxyFromGConf(const nsACString& aScheme, const nsACString& aHost, int32_t aPort, nsACString& aResult);
45 : nsresult GetProxyFromGSettings(const nsACString& aScheme, const nsACString& aHost, int32_t aPort, nsACString& aResult);
46 : nsresult SetProxyResultFromGSettings(const char* aKeyBase, const char* aType, nsACString& aResult);
47 : };
48 :
49 0 : NS_IMPL_ISUPPORTS(nsUnixSystemProxySettings, nsISystemProxySettings)
50 :
51 : NS_IMETHODIMP
52 0 : nsUnixSystemProxySettings::GetMainThreadOnly(bool *aMainThreadOnly)
53 : {
54 : // dbus prevents us from being threadsafe, but this routine should not block anyhow
55 0 : *aMainThreadOnly = true;
56 0 : return NS_OK;
57 : }
58 :
59 : nsresult
60 0 : nsUnixSystemProxySettings::Init()
61 : {
62 0 : mGSettings = do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
63 0 : if (mGSettings) {
64 0 : mGSettings->GetCollectionForSchema(NS_LITERAL_CSTRING("org.gnome.system.proxy"),
65 0 : getter_AddRefs(mProxySettings));
66 : }
67 0 : if (!mProxySettings) {
68 0 : mGConf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
69 : }
70 :
71 0 : return NS_OK;
72 : }
73 :
74 : bool
75 0 : nsUnixSystemProxySettings::IsProxyMode(const char* aMode)
76 : {
77 0 : nsAutoCString mode;
78 0 : return NS_SUCCEEDED(mGConf->GetString(NS_LITERAL_CSTRING("/system/proxy/mode"), mode)) &&
79 0 : mode.EqualsASCII(aMode);
80 : }
81 :
82 : nsresult
83 0 : nsUnixSystemProxySettings::GetPACURI(nsACString& aResult)
84 : {
85 0 : if (mProxySettings) {
86 0 : nsCString proxyMode;
87 : // Check if mode is auto
88 0 : nsresult rv = mProxySettings->GetString(NS_LITERAL_CSTRING("mode"), proxyMode);
89 0 : if (rv == NS_OK && proxyMode.EqualsLiteral("auto")) {
90 0 : return mProxySettings->GetString(NS_LITERAL_CSTRING("autoconfig-url"), aResult);
91 : }
92 : /* The org.gnome.system.proxy schema has been found, but auto mode is not set.
93 : * Don't try the GConf and return empty string. */
94 0 : aResult.Truncate();
95 0 : return NS_OK;
96 : }
97 :
98 0 : if (mGConf && IsProxyMode("auto")) {
99 0 : return mGConf->GetString(NS_LITERAL_CSTRING("/system/proxy/autoconfig_url"),
100 0 : aResult);
101 : }
102 : // Return an empty string when auto mode is not set.
103 0 : aResult.Truncate();
104 0 : return NS_OK;
105 : }
106 :
107 : static bool
108 0 : IsInNoProxyList(const nsACString& aHost, int32_t aPort, const char* noProxyVal)
109 : {
110 0 : NS_ASSERTION(aPort >= 0, "Negative port?");
111 :
112 0 : nsAutoCString noProxy(noProxyVal);
113 0 : if (noProxy.EqualsLiteral("*"))
114 0 : return true;
115 :
116 0 : noProxy.StripWhitespace();
117 :
118 0 : nsReadingIterator<char> pos;
119 0 : nsReadingIterator<char> end;
120 0 : noProxy.BeginReading(pos);
121 0 : noProxy.EndReading(end);
122 0 : while (pos != end) {
123 0 : nsReadingIterator<char> last = pos;
124 0 : nsReadingIterator<char> nextPos;
125 0 : if (FindCharInReadable(',', last, end)) {
126 0 : nextPos = last;
127 0 : ++nextPos;
128 : } else {
129 0 : last = end;
130 0 : nextPos = end;
131 : }
132 :
133 0 : nsReadingIterator<char> colon = pos;
134 0 : int32_t port = -1;
135 0 : if (FindCharInReadable(':', colon, last)) {
136 0 : ++colon;
137 0 : nsDependentCSubstring portStr(colon, last);
138 0 : nsAutoCString portStr2(portStr); // We need this for ToInteger. String API's suck.
139 : nsresult err;
140 0 : port = portStr2.ToInteger(&err);
141 0 : if (NS_FAILED(err)) {
142 0 : port = -2; // don't match any port, so we ignore this pattern
143 : }
144 0 : --colon;
145 : } else {
146 0 : colon = last;
147 : }
148 :
149 0 : if (port == -1 || port == aPort) {
150 0 : nsDependentCSubstring hostStr(pos, colon);
151 : // By using StringEndsWith instead of an equality comparator, we can include sub-domains
152 0 : if (StringEndsWith(aHost, hostStr, nsCaseInsensitiveCStringComparator()))
153 0 : return true;
154 : }
155 :
156 0 : pos = nextPos;
157 : }
158 :
159 0 : return false;
160 : }
161 :
162 0 : static void SetProxyResult(const char* aType, const nsACString& aHost,
163 : int32_t aPort, nsACString& aResult)
164 : {
165 0 : aResult.AppendASCII(aType);
166 0 : aResult.Append(' ');
167 0 : aResult.Append(aHost);
168 0 : if (aPort > 0) {
169 0 : aResult.Append(':');
170 0 : aResult.Append(nsPrintfCString("%d", aPort));
171 : }
172 0 : }
173 :
174 : static nsresult
175 0 : GetProxyFromEnvironment(const nsACString& aScheme,
176 : const nsACString& aHost,
177 : int32_t aPort,
178 : nsACString& aResult)
179 : {
180 0 : nsAutoCString envVar;
181 0 : envVar.Append(aScheme);
182 0 : envVar.AppendLiteral("_proxy");
183 0 : const char* proxyVal = PR_GetEnv(envVar.get());
184 0 : if (!proxyVal) {
185 0 : proxyVal = PR_GetEnv("all_proxy");
186 0 : if (!proxyVal) {
187 : // Return failure so that the caller can detect the failure and
188 : // fall back to other proxy detection (e.g., WPAD)
189 0 : return NS_ERROR_FAILURE;
190 : }
191 : }
192 :
193 0 : const char* noProxyVal = PR_GetEnv("no_proxy");
194 0 : if (noProxyVal && IsInNoProxyList(aHost, aPort, noProxyVal)) {
195 0 : aResult.AppendLiteral("DIRECT");
196 0 : return NS_OK;
197 : }
198 :
199 : // Use our URI parser to crack the proxy URI
200 0 : nsCOMPtr<nsIURI> proxyURI;
201 0 : nsresult rv = NS_NewURI(getter_AddRefs(proxyURI), proxyVal);
202 0 : NS_ENSURE_SUCCESS(rv, rv);
203 :
204 : // Is there a way to specify "socks://" or something in these environment
205 : // variables? I can't find any documentation.
206 : bool isHTTP;
207 0 : rv = proxyURI->SchemeIs("http", &isHTTP);
208 0 : NS_ENSURE_SUCCESS(rv, rv);
209 0 : if (!isHTTP)
210 0 : return NS_ERROR_UNKNOWN_PROTOCOL;
211 :
212 0 : nsAutoCString proxyHost;
213 0 : rv = proxyURI->GetHost(proxyHost);
214 0 : NS_ENSURE_SUCCESS(rv, rv);
215 :
216 : int32_t proxyPort;
217 0 : rv = proxyURI->GetPort(&proxyPort);
218 0 : NS_ENSURE_SUCCESS(rv, rv);
219 :
220 0 : SetProxyResult("PROXY", proxyHost, proxyPort, aResult);
221 0 : return NS_OK;
222 : }
223 :
224 : nsresult
225 0 : nsUnixSystemProxySettings::SetProxyResultFromGConf(const char* aKeyBase, const char* aType,
226 : nsACString& aResult)
227 : {
228 0 : nsAutoCString hostKey;
229 0 : hostKey.AppendASCII(aKeyBase);
230 0 : hostKey.AppendLiteral("host");
231 0 : nsAutoCString host;
232 0 : nsresult rv = mGConf->GetString(hostKey, host);
233 0 : NS_ENSURE_SUCCESS(rv, rv);
234 0 : if (host.IsEmpty())
235 0 : return NS_ERROR_FAILURE;
236 :
237 0 : nsAutoCString portKey;
238 0 : portKey.AppendASCII(aKeyBase);
239 0 : portKey.AppendLiteral("port");
240 : int32_t port;
241 0 : rv = mGConf->GetInt(portKey, &port);
242 0 : NS_ENSURE_SUCCESS(rv, rv);
243 :
244 : /* When port is 0, proxy is not considered as enabled even if host is set. */
245 0 : if (port == 0)
246 0 : return NS_ERROR_FAILURE;
247 :
248 0 : SetProxyResult(aType, host, port, aResult);
249 0 : return NS_OK;
250 : }
251 :
252 : nsresult
253 0 : nsUnixSystemProxySettings::SetProxyResultFromGSettings(const char* aKeyBase, const char* aType,
254 : nsACString& aResult)
255 : {
256 0 : nsDependentCString key(aKeyBase);
257 :
258 0 : nsCOMPtr<nsIGSettingsCollection> proxy_settings = mSchemeProxySettings.Get(key);
259 : nsresult rv;
260 0 : if (!proxy_settings) {
261 0 : rv = mGSettings->GetCollectionForSchema(key, getter_AddRefs(proxy_settings));
262 0 : NS_ENSURE_SUCCESS(rv, rv);
263 :
264 0 : mSchemeProxySettings.Put(key, proxy_settings);
265 : }
266 :
267 0 : nsAutoCString host;
268 0 : rv = proxy_settings->GetString(NS_LITERAL_CSTRING("host"), host);
269 0 : NS_ENSURE_SUCCESS(rv, rv);
270 0 : if (host.IsEmpty())
271 0 : return NS_ERROR_FAILURE;
272 :
273 : int32_t port;
274 0 : rv = proxy_settings->GetInt(NS_LITERAL_CSTRING("port"), &port);
275 0 : NS_ENSURE_SUCCESS(rv, rv);
276 :
277 : /* When port is 0, proxy is not considered as enabled even if host is set. */
278 0 : if (port == 0)
279 0 : return NS_ERROR_FAILURE;
280 :
281 0 : SetProxyResult(aType, host, port, aResult);
282 0 : return NS_OK;
283 : }
284 :
285 : /* copied from nsProtocolProxyService.cpp --- we should share this! */
286 : static void
287 0 : proxy_MaskIPv6Addr(PRIPv6Addr &addr, uint16_t mask_len)
288 : {
289 0 : if (mask_len == 128)
290 0 : return;
291 :
292 0 : if (mask_len > 96) {
293 0 : addr.pr_s6_addr32[3] = PR_htonl(
294 0 : PR_ntohl(addr.pr_s6_addr32[3]) & (~0L << (128 - mask_len)));
295 : }
296 0 : else if (mask_len > 64) {
297 0 : addr.pr_s6_addr32[3] = 0;
298 0 : addr.pr_s6_addr32[2] = PR_htonl(
299 0 : PR_ntohl(addr.pr_s6_addr32[2]) & (~0L << (96 - mask_len)));
300 : }
301 0 : else if (mask_len > 32) {
302 0 : addr.pr_s6_addr32[3] = 0;
303 0 : addr.pr_s6_addr32[2] = 0;
304 0 : addr.pr_s6_addr32[1] = PR_htonl(
305 0 : PR_ntohl(addr.pr_s6_addr32[1]) & (~0L << (64 - mask_len)));
306 : }
307 : else {
308 0 : addr.pr_s6_addr32[3] = 0;
309 0 : addr.pr_s6_addr32[2] = 0;
310 0 : addr.pr_s6_addr32[1] = 0;
311 0 : addr.pr_s6_addr32[0] = PR_htonl(
312 0 : PR_ntohl(addr.pr_s6_addr32[0]) & (~0L << (32 - mask_len)));
313 : }
314 : }
315 :
316 0 : static bool ConvertToIPV6Addr(const nsACString& aName,
317 : PRIPv6Addr* aAddr, int32_t* aMask)
318 : {
319 : PRNetAddr addr;
320 : // try to convert hostname to IP
321 0 : if (PR_StringToNetAddr(PromiseFlatCString(aName).get(), &addr) != PR_SUCCESS)
322 0 : return false;
323 :
324 : // convert parsed address to IPv6
325 0 : if (addr.raw.family == PR_AF_INET) {
326 : // convert to IPv4-mapped address
327 0 : PR_ConvertIPv4AddrToIPv6(addr.inet.ip, aAddr);
328 0 : if (aMask) {
329 0 : if (*aMask <= 32)
330 0 : *aMask += 96;
331 : else
332 0 : return false;
333 : }
334 0 : } else if (addr.raw.family == PR_AF_INET6) {
335 : // copy the address
336 0 : memcpy(aAddr, &addr.ipv6.ip, sizeof(PRIPv6Addr));
337 : } else {
338 0 : return false;
339 : }
340 :
341 0 : return true;
342 : }
343 :
344 0 : static bool HostIgnoredByProxy(const nsACString& aIgnore,
345 : const nsACString& aHost)
346 : {
347 0 : if (aIgnore.Equals(aHost, nsCaseInsensitiveCStringComparator()))
348 0 : return true;
349 :
350 0 : if (aIgnore.First() == '*' &&
351 0 : StringEndsWith(aHost, nsDependentCSubstring(aIgnore, 1),
352 0 : nsCaseInsensitiveCStringComparator()))
353 0 : return true;
354 :
355 0 : int32_t mask = 128;
356 0 : nsReadingIterator<char> start;
357 0 : nsReadingIterator<char> slash;
358 0 : nsReadingIterator<char> end;
359 0 : aIgnore.BeginReading(start);
360 0 : aIgnore.BeginReading(slash);
361 0 : aIgnore.EndReading(end);
362 0 : if (FindCharInReadable('/', slash, end)) {
363 0 : ++slash;
364 0 : nsDependentCSubstring maskStr(slash, end);
365 0 : nsAutoCString maskStr2(maskStr);
366 : nsresult err;
367 0 : mask = maskStr2.ToInteger(&err);
368 0 : if (NS_FAILED(err)) {
369 0 : mask = 128;
370 : }
371 0 : --slash;
372 : } else {
373 0 : slash = end;
374 : }
375 :
376 0 : nsDependentCSubstring ignoreStripped(start, slash);
377 : PRIPv6Addr ignoreAddr, hostAddr;
378 0 : if (!ConvertToIPV6Addr(ignoreStripped, &ignoreAddr, &mask) ||
379 0 : !ConvertToIPV6Addr(aHost, &hostAddr, nullptr))
380 0 : return false;
381 :
382 0 : proxy_MaskIPv6Addr(ignoreAddr, mask);
383 0 : proxy_MaskIPv6Addr(hostAddr, mask);
384 :
385 0 : return memcmp(&ignoreAddr, &hostAddr, sizeof(PRIPv6Addr)) == 0;
386 : }
387 :
388 : nsresult
389 0 : nsUnixSystemProxySettings::GetProxyFromGConf(const nsACString& aScheme,
390 : const nsACString& aHost,
391 : int32_t aPort,
392 : nsACString& aResult)
393 : {
394 0 : bool masterProxySwitch = false;
395 0 : mGConf->GetBool(NS_LITERAL_CSTRING("/system/http_proxy/use_http_proxy"), &masterProxySwitch);
396 : // if no proxy is set in GConf return NS_ERROR_FAILURE
397 0 : if (!(IsProxyMode("manual") || masterProxySwitch)) {
398 0 : return NS_ERROR_FAILURE;
399 : }
400 :
401 0 : nsCOMPtr<nsIArray> ignoreList;
402 0 : if (NS_SUCCEEDED(mGConf->GetStringList(NS_LITERAL_CSTRING("/system/http_proxy/ignore_hosts"),
403 0 : getter_AddRefs(ignoreList))) && ignoreList) {
404 0 : uint32_t len = 0;
405 0 : ignoreList->GetLength(&len);
406 0 : for (uint32_t i = 0; i < len; ++i) {
407 0 : nsCOMPtr<nsISupportsString> str = do_QueryElementAt(ignoreList, i);
408 0 : if (str) {
409 0 : nsAutoString s;
410 0 : if (NS_SUCCEEDED(str->GetData(s)) && !s.IsEmpty()) {
411 0 : if (HostIgnoredByProxy(NS_ConvertUTF16toUTF8(s), aHost)) {
412 0 : aResult.AppendLiteral("DIRECT");
413 0 : return NS_OK;
414 : }
415 : }
416 : }
417 : }
418 : }
419 :
420 0 : bool useHttpProxyForAll = false;
421 : // This setting sometimes doesn't exist, don't bail on failure
422 0 : mGConf->GetBool(NS_LITERAL_CSTRING("/system/http_proxy/use_same_proxy"), &useHttpProxyForAll);
423 :
424 : nsresult rv;
425 0 : if (!useHttpProxyForAll) {
426 0 : rv = SetProxyResultFromGConf("/system/proxy/socks_", "SOCKS", aResult);
427 0 : if (NS_SUCCEEDED(rv))
428 0 : return rv;
429 : }
430 :
431 0 : if (aScheme.LowerCaseEqualsLiteral("http") || useHttpProxyForAll) {
432 0 : rv = SetProxyResultFromGConf("/system/http_proxy/", "PROXY", aResult);
433 0 : } else if (aScheme.LowerCaseEqualsLiteral("https")) {
434 0 : rv = SetProxyResultFromGConf("/system/proxy/secure_", "PROXY", aResult);
435 0 : } else if (aScheme.LowerCaseEqualsLiteral("ftp")) {
436 0 : rv = SetProxyResultFromGConf("/system/proxy/ftp_", "PROXY", aResult);
437 : } else {
438 0 : rv = NS_ERROR_FAILURE;
439 : }
440 :
441 0 : return rv;
442 : }
443 :
444 : nsresult
445 0 : nsUnixSystemProxySettings::GetProxyFromGSettings(const nsACString& aScheme,
446 : const nsACString& aHost,
447 : int32_t aPort,
448 : nsACString& aResult)
449 : {
450 0 : nsCString proxyMode;
451 0 : nsresult rv = mProxySettings->GetString(NS_LITERAL_CSTRING("mode"), proxyMode);
452 0 : NS_ENSURE_SUCCESS(rv, rv);
453 :
454 : // return NS_ERROR_FAILURE when no proxy is set
455 0 : if (!proxyMode.EqualsLiteral("manual")) {
456 0 : return NS_ERROR_FAILURE;
457 : }
458 :
459 0 : nsCOMPtr<nsIArray> ignoreList;
460 0 : if (NS_SUCCEEDED(mProxySettings->GetStringList(NS_LITERAL_CSTRING("ignore-hosts"),
461 0 : getter_AddRefs(ignoreList))) && ignoreList) {
462 0 : uint32_t len = 0;
463 0 : ignoreList->GetLength(&len);
464 0 : for (uint32_t i = 0; i < len; ++i) {
465 0 : nsCOMPtr<nsISupportsCString> str = do_QueryElementAt(ignoreList, i);
466 0 : if (str) {
467 0 : nsCString s;
468 0 : if (NS_SUCCEEDED(str->GetData(s)) && !s.IsEmpty()) {
469 0 : if (HostIgnoredByProxy(s, aHost)) {
470 0 : aResult.AppendLiteral("DIRECT");
471 0 : return NS_OK;
472 : }
473 : }
474 : }
475 : }
476 : }
477 :
478 0 : if (aScheme.LowerCaseEqualsLiteral("http")) {
479 0 : rv = SetProxyResultFromGSettings("org.gnome.system.proxy.http", "PROXY", aResult);
480 0 : } else if (aScheme.LowerCaseEqualsLiteral("https")) {
481 0 : rv = SetProxyResultFromGSettings("org.gnome.system.proxy.https", "PROXY", aResult);
482 : /* Try to use HTTP proxy when HTTPS proxy is not explicitly defined */
483 0 : if (rv != NS_OK)
484 0 : rv = SetProxyResultFromGSettings("org.gnome.system.proxy.http", "PROXY", aResult);
485 0 : } else if (aScheme.LowerCaseEqualsLiteral("ftp")) {
486 0 : rv = SetProxyResultFromGSettings("org.gnome.system.proxy.ftp", "PROXY", aResult);
487 : } else {
488 0 : rv = NS_ERROR_FAILURE;
489 : }
490 0 : if (rv != NS_OK) {
491 : /* If proxy for scheme is not specified, use SOCKS proxy for all schemes */
492 0 : rv = SetProxyResultFromGSettings("org.gnome.system.proxy.socks", "SOCKS", aResult);
493 : }
494 :
495 0 : if (NS_FAILED(rv)) {
496 0 : aResult.AppendLiteral("DIRECT");
497 : }
498 :
499 0 : return NS_OK;
500 : }
501 :
502 : nsresult
503 0 : nsUnixSystemProxySettings::GetProxyForURI(const nsACString & aSpec,
504 : const nsACString & aScheme,
505 : const nsACString & aHost,
506 : const int32_t aPort,
507 : nsACString & aResult)
508 : {
509 0 : if (mProxySettings) {
510 0 : nsresult rv = GetProxyFromGSettings(aScheme, aHost, aPort, aResult);
511 0 : if (NS_SUCCEEDED(rv))
512 0 : return rv;
513 : }
514 0 : if (mGConf)
515 0 : return GetProxyFromGConf(aScheme, aHost, aPort, aResult);
516 :
517 0 : return GetProxyFromEnvironment(aScheme, aHost, aPort, aResult);
518 : }
519 :
520 : #define NS_UNIXSYSTEMPROXYSERVICE_CID /* 0fa3158c-d5a7-43de-9181-a285e74cf1d4 */\
521 : { 0x0fa3158c, 0xd5a7, 0x43de, \
522 : {0x91, 0x81, 0xa2, 0x85, 0xe7, 0x4c, 0xf1, 0xd4 } }
523 :
524 0 : NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsUnixSystemProxySettings, Init)
525 : NS_DEFINE_NAMED_CID(NS_UNIXSYSTEMPROXYSERVICE_CID);
526 :
527 : static const mozilla::Module::CIDEntry kUnixProxyCIDs[] = {
528 : { &kNS_UNIXSYSTEMPROXYSERVICE_CID, false, nullptr, nsUnixSystemProxySettingsConstructor },
529 : { nullptr }
530 : };
531 :
532 : static const mozilla::Module::ContractIDEntry kUnixProxyContracts[] = {
533 : { NS_SYSTEMPROXYSETTINGS_CONTRACTID, &kNS_UNIXSYSTEMPROXYSERVICE_CID },
534 : { nullptr }
535 : };
536 :
537 : static const mozilla::Module kUnixProxyModule = {
538 : mozilla::Module::kVersion,
539 : kUnixProxyCIDs,
540 : kUnixProxyContracts
541 : };
542 :
543 : NSMODULE_DEFN(nsUnixProxyModule) = &kUnixProxyModule;
|