Coverage Report

Created: 2018-09-25 14:53

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