Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
Line
Count
Source (jump to first uncovered line)
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
  nsUnixSystemProxySettings()
30
    : mSchemeProxySettings(4)
31
0
  {
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
NS_IMPL_ISUPPORTS(nsUnixSystemProxySettings, nsISystemProxySettings)
50
51
NS_IMETHODIMP
52
nsUnixSystemProxySettings::GetMainThreadOnly(bool *aMainThreadOnly)
53
0
{
54
0
  // dbus prevents us from being threadsafe, but this routine should not block anyhow
55
0
  *aMainThreadOnly = true;
56
0
  return NS_OK;
57
0
}
58
59
nsresult
60
nsUnixSystemProxySettings::Init()
61
0
{
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
0
  }
67
0
  if (!mProxySettings) {
68
0
    mGConf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
69
0
  }
70
0
71
0
  return NS_OK;
72
0
}
73
74
bool
75
nsUnixSystemProxySettings::IsProxyMode(const char* aMode)
76
0
{
77
0
  nsAutoCString mode;
78
0
  return NS_SUCCEEDED(mGConf->GetString(NS_LITERAL_CSTRING("/system/proxy/mode"), mode)) &&
79
0
         mode.EqualsASCII(aMode);
80
0
}
81
82
nsresult
83
nsUnixSystemProxySettings::GetPACURI(nsACString& aResult)
84
0
{
85
0
  if (mProxySettings) {
86
0
    nsCString proxyMode;
87
0
    // 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
0
    }
92
0
    /* The org.gnome.system.proxy schema has been found, but auto mode is not set.
93
0
     * Don't try the GConf and return empty string. */
94
0
    aResult.Truncate();
95
0
    return NS_OK;
96
0
  }
97
0
98
0
  if (mGConf && IsProxyMode("auto")) {
99
0
    return mGConf->GetString(NS_LITERAL_CSTRING("/system/proxy/autoconfig_url"),
100
0
                             aResult);
101
0
  }
102
0
  // Return an empty string when auto mode is not set.
103
0
  aResult.Truncate();
104
0
  return NS_OK;
105
0
}
106
107
static bool
108
IsInNoProxyList(const nsACString& aHost, int32_t aPort, const char* noProxyVal)
109
0
{
110
0
  NS_ASSERTION(aPort >= 0, "Negative port?");
111
0
112
0
  nsAutoCString noProxy(noProxyVal);
113
0
  if (noProxy.EqualsLiteral("*"))
114
0
    return true;
115
0
116
0
  noProxy.StripWhitespace();
117
0
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
0
    } else {
129
0
      last = end;
130
0
      nextPos = end;
131
0
    }
132
0
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
0
      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
0
      }
144
0
      --colon;
145
0
    } else {
146
0
      colon = last;
147
0
    }
148
0
149
0
    if (port == -1 || port == aPort) {
150
0
      nsDependentCSubstring hostStr(pos, colon);
151
0
      // 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
0
    }
155
0
156
0
    pos = nextPos;
157
0
  }
158
0
159
0
  return false;
160
0
}
161
162
static void SetProxyResult(const char* aType, const nsACString& aHost,
163
                           int32_t aPort, nsACString& aResult)
164
0
{
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
0
  }
172
0
}
173
174
static nsresult
175
GetProxyFromEnvironment(const nsACString& aScheme,
176
                        const nsACString& aHost,
177
                        int32_t aPort,
178
                        nsACString& aResult)
179
0
{
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
0
      // Return failure so that the caller can detect the failure and
188
0
      // fall back to other proxy detection (e.g., WPAD)
189
0
      return NS_ERROR_FAILURE;
190
0
    }
191
0
  }
192
0
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
0
  }
198
0
199
0
  // 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
0
204
0
  // Is there a way to specify "socks://" or something in these environment
205
0
  // variables? I can't find any documentation.
206
0
  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
0
212
0
  nsAutoCString proxyHost;
213
0
  rv = proxyURI->GetHost(proxyHost);
214
0
  NS_ENSURE_SUCCESS(rv, rv);
215
0
216
0
  int32_t proxyPort;
217
0
  rv = proxyURI->GetPort(&proxyPort);
218
0
  NS_ENSURE_SUCCESS(rv, rv);
219
0
220
0
  SetProxyResult("PROXY", proxyHost, proxyPort, aResult);
221
0
  return NS_OK;
222
0
}
223
224
nsresult
225
nsUnixSystemProxySettings::SetProxyResultFromGConf(const char* aKeyBase, const char* aType,
226
                                                   nsACString& aResult)
227
0
{
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
0
237
0
  nsAutoCString portKey;
238
0
  portKey.AppendASCII(aKeyBase);
239
0
  portKey.AppendLiteral("port");
240
0
  int32_t port;
241
0
  rv = mGConf->GetInt(portKey, &port);
242
0
  NS_ENSURE_SUCCESS(rv, rv);
243
0
244
0
  /* 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
0
248
0
  SetProxyResult(aType, host, port, aResult);
249
0
  return NS_OK;
250
0
}
251
252
nsresult
253
nsUnixSystemProxySettings::SetProxyResultFromGSettings(const char* aKeyBase, const char* aType,
254
                                                       nsACString& aResult)
255
0
{
256
0
  nsDependentCString key(aKeyBase);
257
0
258
0
  nsCOMPtr<nsIGSettingsCollection> proxy_settings = mSchemeProxySettings.Get(key);
259
0
  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
0
264
0
    mSchemeProxySettings.Put(key, proxy_settings);
265
0
  }
266
0
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
0
273
0
  int32_t port;
274
0
  rv = proxy_settings->GetInt(NS_LITERAL_CSTRING("port"), &port);
275
0
  NS_ENSURE_SUCCESS(rv, rv);
276
0
277
0
  /* 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
0
281
0
  SetProxyResult(aType, host, port, aResult);
282
0
  return NS_OK;
283
0
}
284
285
/* copied from nsProtocolProxyService.cpp --- we should share this! */
286
static void
287
proxy_MaskIPv6Addr(PRIPv6Addr &addr, uint16_t mask_len)
288
0
{
289
0
  if (mask_len == 128)
290
0
    return;
291
0
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
0
  }
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
0
  }
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
0
  }
307
0
  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
0
  }
314
0
}
315
316
static bool ConvertToIPV6Addr(const nsACString& aName,
317
                                PRIPv6Addr* aAddr, int32_t* aMask)
318
0
{
319
0
  PRNetAddr addr;
320
0
  // try to convert hostname to IP
321
0
  if (PR_StringToNetAddr(PromiseFlatCString(aName).get(), &addr) != PR_SUCCESS)
322
0
    return false;
323
0
324
0
  // convert parsed address to IPv6
325
0
  if (addr.raw.family == PR_AF_INET) {
326
0
    // 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
0
      else
332
0
        return false;
333
0
    }
334
0
  } else if (addr.raw.family == PR_AF_INET6) {
335
0
    // copy the address
336
0
    memcpy(aAddr, &addr.ipv6.ip, sizeof(PRIPv6Addr));
337
0
  } else {
338
0
    return false;
339
0
  }
340
0
341
0
  return true;
342
0
}
343
344
static bool HostIgnoredByProxy(const nsACString& aIgnore,
345
                               const nsACString& aHost)
346
0
{
347
0
  if (aIgnore.Equals(aHost, nsCaseInsensitiveCStringComparator()))
348
0
    return true;
349
0
350
0
  if (aIgnore.First() == '*' &&
351
0
      StringEndsWith(aHost, nsDependentCSubstring(aIgnore, 1),
352
0
                     nsCaseInsensitiveCStringComparator()))
353
0
    return true;
354
0
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
0
    nsresult err;
367
0
    mask = maskStr2.ToInteger(&err);
368
0
    if (NS_FAILED(err)) {
369
0
      mask = 128;
370
0
    }
371
0
    --slash;
372
0
  } else {
373
0
    slash = end;
374
0
  }
375
0
376
0
  nsDependentCSubstring ignoreStripped(start, slash);
377
0
  PRIPv6Addr ignoreAddr, hostAddr;
378
0
  if (!ConvertToIPV6Addr(ignoreStripped, &ignoreAddr, &mask) ||
379
0
      !ConvertToIPV6Addr(aHost, &hostAddr, nullptr))
380
0
    return false;
381
0
382
0
  proxy_MaskIPv6Addr(ignoreAddr, mask);
383
0
  proxy_MaskIPv6Addr(hostAddr, mask);
384
0
385
0
  return memcmp(&ignoreAddr, &hostAddr, sizeof(PRIPv6Addr)) == 0;
386
0
}
387
388
nsresult
389
nsUnixSystemProxySettings::GetProxyFromGConf(const nsACString& aScheme,
390
                                             const nsACString& aHost,
391
                                             int32_t aPort,
392
                                             nsACString& aResult)
393
0
{
394
0
  bool masterProxySwitch = false;
395
0
  mGConf->GetBool(NS_LITERAL_CSTRING("/system/http_proxy/use_http_proxy"), &masterProxySwitch);
396
0
  // if no proxy is set in GConf return NS_ERROR_FAILURE
397
0
  if (!(IsProxyMode("manual") || masterProxySwitch)) {
398
0
    return NS_ERROR_FAILURE;
399
0
  }
400
0
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
0
          }
415
0
        }
416
0
      }
417
0
    }
418
0
  }
419
0
420
0
  bool useHttpProxyForAll = false;
421
0
  // 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
0
424
0
  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
0
  }
430
0
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
0
  } else {
438
0
    rv = NS_ERROR_FAILURE;
439
0
  }
440
0
441
0
  return rv;
442
0
}
443
444
nsresult
445
nsUnixSystemProxySettings::GetProxyFromGSettings(const nsACString& aScheme,
446
                                                 const nsACString& aHost,
447
                                                 int32_t aPort,
448
                                                 nsACString& aResult)
449
0
{
450
0
  nsCString proxyMode;
451
0
  nsresult rv = mProxySettings->GetString(NS_LITERAL_CSTRING("mode"), proxyMode);
452
0
  NS_ENSURE_SUCCESS(rv, rv);
453
0
454
0
  // return NS_ERROR_FAILURE when no proxy is set
455
0
  if (!proxyMode.EqualsLiteral("manual")) {
456
0
    return NS_ERROR_FAILURE;
457
0
  }
458
0
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
0
          }
473
0
        }
474
0
      }
475
0
    }
476
0
  }
477
0
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
0
    /* 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
0
  } else {
488
0
    rv = NS_ERROR_FAILURE;
489
0
  }
490
0
  if (rv != NS_OK) {
491
0
     /* 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
0
  }
494
0
495
0
  if (NS_FAILED(rv)) {
496
0
    aResult.AppendLiteral("DIRECT");
497
0
  }
498
0
499
0
  return NS_OK;
500
0
}
501
502
nsresult
503
nsUnixSystemProxySettings::GetProxyForURI(const nsACString & aSpec,
504
                                          const nsACString & aScheme,
505
                                          const nsACString & aHost,
506
                                          const int32_t      aPort,
507
                                          nsACString & aResult)
508
0
{
509
0
  if (mProxySettings) {
510
0
    nsresult rv = GetProxyFromGSettings(aScheme, aHost, aPort, aResult);
511
0
    if (NS_SUCCEEDED(rv))
512
0
      return rv;
513
0
  }
514
0
  if (mGConf)
515
0
    return GetProxyFromGConf(aScheme, aHost, aPort, aResult);
516
0
517
0
  return GetProxyFromEnvironment(aScheme, aHost, aPort, aResult);
518
0
}
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
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;