Source code

Revision control

Line Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef nsProtocolProxyService_h__
#define nsProtocolProxyService_h__

#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
#include "nsTArray.h"
#include "nsIProtocolProxyService2.h"
#include "nsIProtocolProxyFilter.h"
#include "nsIProxyInfo.h"
#include "nsIObserver.h"
#include "nsIThread.h"
#include "nsDataHashtable.h"
#include "nsHashKeys.h"
#include "prio.h"
#include "mozilla/Attributes.h"

class nsIPrefBranch;
class nsISystemProxySettings;

namespace mozilla {
namespace net {

typedef nsDataHashtable<nsCStringHashKey, uint32_t> nsFailedProxyTable;

class nsPACMan;
class nsProxyInfo;
struct nsProtocolInfo;

// CID for the nsProtocolProxyService class
// 091eedd8-8bae-4fe3-ad62-0c87351e640d
#define NS_PROTOCOL_PROXY_SERVICE_IMPL_CID           \
  {                                                  \
    0x091eedd8, 0x8bae, 0x4fe3, {                    \
      0xad, 0x62, 0x0c, 0x87, 0x35, 0x1e, 0x64, 0x0d \
    }                                                \
  }

class nsProtocolProxyService final : public nsIProtocolProxyService2,
                                     public nsIObserver {
 public:
  NS_DECL_ISUPPORTS
  NS_DECL_NSIPROTOCOLPROXYSERVICE2
  NS_DECL_NSIPROTOCOLPROXYSERVICE
  NS_DECL_NSIOBSERVER

  NS_DECLARE_STATIC_IID_ACCESSOR(NS_PROTOCOL_PROXY_SERVICE_IMPL_CID)

  nsProtocolProxyService();

  nsresult Init();

 public:
  // An instance of this struct is allocated for each registered
  // nsIProtocolProxyFilter and each nsIProtocolProxyChannelFilter.
  class FilterLink {
   public:
    NS_INLINE_DECL_REFCOUNTING(FilterLink)

    uint32_t position;
    nsCOMPtr<nsIProtocolProxyFilter> filter;
    nsCOMPtr<nsIProtocolProxyChannelFilter> channelFilter;

    FilterLink(uint32_t p, nsIProtocolProxyFilter *f);
    FilterLink(uint32_t p, nsIProtocolProxyChannelFilter *cf);

   private:
    ~FilterLink();
  };

 protected:
  friend class nsAsyncResolveRequest;
  friend class TestProtocolProxyService_LoadHostFilters_Test;  // for gtest

  ~nsProtocolProxyService();

  /**
   * This method is called whenever a preference may have changed or
   * to initialize all preferences.
   *
   * @param prefs
   *        This must be a pointer to the root pref branch.
   * @param name
   *        This can be the name of a fully-qualified preference, or it can
   *        be null, in which case all preferences will be initialized.
   */
  void PrefsChanged(nsIPrefBranch *prefs, const char *name);

  /**
   * This method is called to create a nsProxyInfo instance from the given
   * PAC-style proxy string.  It parses up to the end of the string, or to
   * the next ';' character.
   *
   * @param proxy
   *        The PAC-style proxy string to parse.  This must not be null.
   * @param aResolveFlags
   *        The flags passed to Resolve or AsyncResolve that are stored in
   *        proxyInfo.
   * @param result
   *        Upon return this points to a newly allocated nsProxyInfo or null
   *        if the proxy string was invalid.
   *
   * @return A pointer beyond the parsed proxy string (never null).
   */
  const char *ExtractProxyInfo(const char *proxy, uint32_t aResolveFlags,
                               nsProxyInfo **result);

  /**
   * Load the specified PAC file.
   *
   * @param pacURI
   *        The URI spec of the PAC file to load.
   */
  nsresult ConfigureFromPAC(const nsCString &pacURI, bool forceReload);

  /**
   * This method builds a list of nsProxyInfo objects from the given PAC-
   * style string.
   *
   * @param pacString
   *        The PAC-style proxy string to parse.  This may be empty.
   * @param aResolveFlags
   *        The flags passed to Resolve or AsyncResolve that are stored in
   *        proxyInfo.
   * @param result
   *        The resulting list of proxy info objects.
   */
  void ProcessPACString(const nsCString &pacString, uint32_t aResolveFlags,
                        nsIProxyInfo **result);

  /**
   * This method generates a string valued identifier for the given
   * nsProxyInfo object.
   *
   * @param pi
   *        The nsProxyInfo object from which to generate the key.
   * @param result
   *        Upon return, this parameter holds the generated key.
   */
  void GetProxyKey(nsProxyInfo *pi, nsCString &result);

  /**
   * @return Seconds since start of session.
   */
  uint32_t SecondsSinceSessionStart();

  /**
   * This method removes the specified proxy from the disabled list.
   *
   * @param pi
   *        The nsProxyInfo object identifying the proxy to enable.
   */
  void EnableProxy(nsProxyInfo *pi);

  /**
   * This method adds the specified proxy to the disabled list.
   *
   * @param pi
   *        The nsProxyInfo object identifying the proxy to disable.
   */
  void DisableProxy(nsProxyInfo *pi);

  /**
   * This method tests to see if the given proxy is disabled.
   *
   * @param pi
   *        The nsProxyInfo object identifying the proxy to test.
   *
   * @return True if the specified proxy is disabled.
   */
  bool IsProxyDisabled(nsProxyInfo *pi);

  /**
   * This method queries the protocol handler for the given scheme to check
   * for the protocol flags and default port.
   *
   * @param uri
   *        The URI to query.
   * @param info
   *        Holds information about the protocol upon return.  Pass address
   *        of structure when you call this method.  This parameter must not
   *        be null.
   */
  nsresult GetProtocolInfo(nsIURI *uri, nsProtocolInfo *result);

  /**
   * This method is an internal version nsIProtocolProxyService::newProxyInfo
   * that expects a string literal for the type.
   *
   * @param type
   *        The proxy type.
   * @param host
   *        The proxy host name (UTF-8 ok).
   * @param port
   *        The proxy port number.
   * @param username
   *        The username for the proxy (ASCII). May be "", but not null.
   * @param password
   *        The password for the proxy (ASCII). May be "", but not null.
   * @param flags
   *        The proxy flags (nsIProxyInfo::flags).
   * @param timeout
   *        The failover timeout for this proxy.
   * @param next
   *        The next proxy to try if this one fails.
   * @param aResolveFlags
   *        The flags passed to resolve (from nsIProtocolProxyService).
   * @param result
   *        The resulting nsIProxyInfo object.
   */
  nsresult NewProxyInfo_Internal(const char *type, const nsACString &host,
                                 int32_t port, const nsACString &username,
                                 const nsACString &password, uint32_t flags,
                                 uint32_t timeout, nsIProxyInfo *next,
                                 uint32_t aResolveFlags, nsIProxyInfo **result);

  /**
   * This method is an internal version of Resolve that does not query PAC.
   * It performs all of the built-in processing, and reports back to the
   * caller with either the proxy info result or a flag to instruct the
   * caller to use PAC instead.
   *
   * @param channel
   *        The channel to test.
   * @param info
   *        Information about the URI's protocol.
   * @param flags
   *        The flags passed to either the resolve or the asyncResolve method.
   * @param usePAC
   *        If this flag is set upon return, then PAC should be queried to
   *        resolve the proxy info.
   * @param result
   *        The resulting proxy info or null.
   */
  nsresult Resolve_Internal(nsIChannel *channel, const nsProtocolInfo &info,
                            uint32_t flags, bool *usePAC,
                            nsIProxyInfo **result);

  /**
   * Shallow copy of the current list of registered filters so that
   * we can safely let them asynchronously process a single proxy
   * resolution request.
   */
  void CopyFilters(nsTArray<RefPtr<FilterLink>> &aCopy);

  /**
   * This method applies the provided filter to the given proxy info
   * list, and expects |callback| be called on (synchronously or
   * asynchronously) to provide the updated proxyinfo list.
   */
  bool ApplyFilter(FilterLink const *filterLink, nsIChannel *channel,
                   const nsProtocolInfo &info, nsCOMPtr<nsIProxyInfo> proxyInfo,
                   nsIProxyProtocolFilterResult *callback);

  /**
   * This method prunes out disabled and disallowed proxies from a given
   * proxy info list.
   *
   * @param info
   *        Information about the URI's protocol.
   * @param proxyInfo
   *        The proxy info list to be modified.  This is an inout param.
   */
  void PruneProxyInfo(const nsProtocolInfo &info, nsIProxyInfo **proxyInfo);

  /**
   * This method is a simple wrapper around PruneProxyInfo that takes the
   * proxy info list inout param as a nsCOMPtr.
   */
  void PruneProxyInfo(const nsProtocolInfo &info,
                      nsCOMPtr<nsIProxyInfo> &proxyInfo) {
    nsIProxyInfo *pi = nullptr;
    proxyInfo.swap(pi);
    PruneProxyInfo(info, &pi);
    proxyInfo.swap(pi);
  }

  /**
   * This method populates mHostFiltersArray from the given string.
   *
   * @param hostFilters
   *        A "no-proxy-for" exclusion list.
   */
  void LoadHostFilters(const nsACString &hostFilters);

  /**
   * This method checks the given URI against mHostFiltersArray.
   *
   * @param uri
   *        The URI to test.
   * @param defaultPort
   *        The default port for the given URI.
   *
   * @return True if the URI can use the specified proxy.
   */
  bool CanUseProxy(nsIURI *uri, int32_t defaultPort);

  /**
   * Disable Prefetch in the DNS service if a proxy is in use.
   *
   * @param aProxy
   *        The proxy information
   */
  void MaybeDisableDNSPrefetch(nsIProxyInfo *aProxy);

 private:
  nsresult SetupPACThread(nsIEventTarget *mainThreadEventTarget = nullptr);
  nsresult ResetPACThread();
  nsresult ReloadNetworkPAC();

  nsresult AsyncConfigureFromPAC(bool aForceReload, bool aResetPACThread);
  nsresult OnAsyncGetPACURI(bool aForceReload, bool aResetPACThread,
                            nsresult aResult, const nsACString &aUri);

 public:
  // The Sun Forte compiler and others implement older versions of the
  // C++ standard's rules on access and nested classes.  These structs
  // need to be public in order to deal with those compilers.

  struct HostInfoIP {
    uint16_t family;
    uint16_t mask_len;
    PRIPv6Addr addr;  // possibly IPv4-mapped address
  };

  struct HostInfoName {
    char *host;
    uint32_t host_len;
  };

 protected:
  // simplified array of filters defined by this struct
  struct HostInfo {
    bool is_ipaddr;
    int32_t port;
    union {
      HostInfoIP ip;
      HostInfoName name;
    };

    HostInfo()
        : is_ipaddr(false),
          port(0) { /* other members intentionally uninitialized */
    }
    ~HostInfo() {
      if (!is_ipaddr && name.host) free(name.host);
    }
  };

 private:
  // Private methods to insert and remove FilterLinks from the FilterLink chain.
  nsresult InsertFilterLink(RefPtr<FilterLink> &&link);
  nsresult RemoveFilterLink(nsISupports *givenObject);

 protected:
  // Indicates if local hosts (plain hostnames, no dots) should use the proxy
  bool mFilterLocalHosts;

  // Holds an array of HostInfo objects
  nsTArray<nsAutoPtr<HostInfo>> mHostFiltersArray;

  // Filters, always sorted by the position.
  nsTArray<RefPtr<FilterLink>> mFilters;

  uint32_t mProxyConfig;

  nsCString mHTTPProxyHost;
  int32_t mHTTPProxyPort;

  nsCString mFTPProxyHost;
  int32_t mFTPProxyPort;

  nsCString mHTTPSProxyHost;
  int32_t mHTTPSProxyPort;

  // mSOCKSProxyTarget could be a host, a domain socket path,
  // or a named-pipe name.
  nsCString mSOCKSProxyTarget;
  int32_t mSOCKSProxyPort;
  int32_t mSOCKSProxyVersion;
  bool mSOCKSProxyRemoteDNS;
  bool mProxyOverTLS;
  bool mWPADOverDHCPEnabled;

  RefPtr<nsPACMan> mPACMan;  // non-null if we are using PAC
  nsCOMPtr<nsISystemProxySettings> mSystemProxySettings;

  PRTime mSessionStart;
  nsFailedProxyTable mFailedProxies;
  int32_t mFailedProxyTimeout;

 private:
  nsresult AsyncResolveInternal(nsIChannel *channel, uint32_t flags,
                                nsIProtocolProxyCallback *callback,
                                nsICancelable **result, bool isSyncOK,
                                nsIEventTarget *mainThreadEventTarget);
  bool mIsShutdown;
  nsCOMPtr<nsIEventTarget> mProxySettingTarget;
};

NS_DEFINE_STATIC_IID_ACCESSOR(nsProtocolProxyService,
                              NS_PROTOCOL_PROXY_SERVICE_IMPL_CID)

}  // namespace net
}  // namespace mozilla

#endif  // !nsProtocolProxyService_h__