Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/extensions/ChannelWrapper.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=8 sts=2 et sw=2 tw=80: */
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 mozilla_extensions_ChannelWrapper_h
8
#define mozilla_extensions_ChannelWrapper_h
9
10
#include "mozilla/dom/BindingDeclarations.h"
11
#include "mozilla/dom/ChannelWrapperBinding.h"
12
13
#include "mozilla/WebRequestService.h"
14
#include "mozilla/extensions/MatchPattern.h"
15
#include "mozilla/extensions/WebExtensionPolicy.h"
16
17
#include "mozilla/Attributes.h"
18
#include "mozilla/Maybe.h"
19
#include "mozilla/UniquePtr.h"
20
#include "mozilla/WeakPtr.h"
21
22
#include "mozilla/DOMEventTargetHelper.h"
23
#include "nsCOMPtr.h"
24
#include "nsCycleCollectionParticipant.h"
25
#include "nsIChannel.h"
26
#include "nsIHttpChannel.h"
27
#include "nsIStreamListener.h"
28
#include "nsITabParent.h"
29
#include "nsIThreadRetargetableStreamListener.h"
30
#include "nsPointerHashKeys.h"
31
#include "nsInterfaceHashtable.h"
32
#include "nsWeakPtr.h"
33
#include "nsWrapperCache.h"
34
35
#define NS_CHANNELWRAPPER_IID \
36
{ 0xc06162d2, 0xb803, 0x43b4, \
37
  { 0xaa, 0x31, 0xcf, 0x69, 0x7f, 0x93, 0x68, 0x1c } }
38
39
class nsILoadContext;
40
class nsITraceableChannel;
41
42
namespace mozilla {
43
namespace dom {
44
  class nsIContentParent;
45
  class Element;
46
} // namespace dom
47
namespace extensions {
48
49
namespace detail {
50
51
  // We need to store our wrapped channel as a weak reference, since channels
52
  // are not cycle collected, and we're going to be hanging this wrapper
53
  // instance off the channel in order to ensure the same channel always has
54
  // the same wrapper.
55
  //
56
  // But since performance matters here, and we don't want to have to
57
  // QueryInterface the channel every time we touch it, we store separate
58
  // nsIChannel and nsIHttpChannel weak references, and check that the WeakPtr
59
  // is alive before returning it.
60
  //
61
  // This holder class prevents us from accidentally touching the weak pointer
62
  // members directly from our ChannelWrapper class.
63
  struct ChannelHolder
64
  {
65
    explicit ChannelHolder(nsIChannel* aChannel)
66
      : mChannel(do_GetWeakReference(aChannel))
67
      , mWeakChannel(aChannel)
68
0
    {}
69
70
0
    bool HaveChannel() const { return mChannel && mChannel->IsAlive(); }
71
72
    void SetChannel(nsIChannel* aChannel)
73
0
    {
74
0
      mChannel = do_GetWeakReference(aChannel);
75
0
      mWeakChannel = aChannel;
76
0
      mWeakHttpChannel.reset();
77
0
    }
78
79
    already_AddRefed<nsIChannel> MaybeChannel() const
80
0
    {
81
0
      if (!HaveChannel()) {
82
0
        mWeakChannel = nullptr;
83
0
      }
84
0
      return do_AddRef(mWeakChannel);
85
0
    }
86
87
    already_AddRefed<nsIHttpChannel> MaybeHttpChannel() const
88
0
    {
89
0
      if (mWeakHttpChannel.isNothing()) {
90
0
        nsCOMPtr<nsIHttpChannel> chan = QueryChannel();
91
0
        mWeakHttpChannel.emplace(chan.get());
92
0
      }
93
0
94
0
      if (!HaveChannel()) {
95
0
        mWeakHttpChannel.ref() = nullptr;
96
0
      }
97
0
      return do_AddRef(mWeakHttpChannel.value());
98
0
    }
99
100
0
    const nsQueryReferent QueryChannel() const { return do_QueryReferent(mChannel); }
101
102
  private:
103
    nsWeakPtr mChannel;
104
105
    mutable nsIChannel* MOZ_NON_OWNING_REF mWeakChannel;
106
    mutable Maybe<nsIHttpChannel*> MOZ_NON_OWNING_REF mWeakHttpChannel;
107
  };
108
}
109
110
class WebRequestChannelEntry;
111
112
class ChannelWrapper final : public DOMEventTargetHelper
113
                           , public SupportsWeakPtr<ChannelWrapper>
114
                           , private detail::ChannelHolder
115
{
116
public:
117
  MOZ_DECLARE_WEAKREFERENCE_TYPENAME(ChannelWrapper)
118
  NS_DECL_ISUPPORTS_INHERITED
119
  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(ChannelWrapper, DOMEventTargetHelper)
120
121
  NS_DECLARE_STATIC_IID_ACCESSOR(NS_CHANNELWRAPPER_IID)
122
123
  static already_AddRefed<extensions::ChannelWrapper> Get(const dom::GlobalObject& global, nsIChannel* channel);
124
  static already_AddRefed<extensions::ChannelWrapper> GetRegisteredChannel(const dom::GlobalObject& global, uint64_t aChannelId, const WebExtensionPolicy& aAddon, nsITabParent* aTabParent);
125
126
0
  uint64_t Id() const { return mId; }
127
128
0
  already_AddRefed<nsIChannel> GetChannel() const { return MaybeChannel(); }
129
130
  void SetChannel(nsIChannel* aChannel);
131
132
133
  void Cancel(uint32_t result, ErrorResult& aRv);
134
135
  void RedirectTo(nsIURI* uri, ErrorResult& aRv);
136
  void UpgradeToSecure(ErrorResult& aRv);
137
138
139
0
  bool Suspended() const { return mSuspended; }
140
141
  void SetSuspended(bool aSuspended, ErrorResult& aRv);
142
143
144
  void GetContentType(nsCString& aContentType) const;
145
  void SetContentType(const nsACString& aContentType);
146
147
148
  void RegisterTraceableChannel(const WebExtensionPolicy& aAddon, nsITabParent* aTabParent);
149
150
  already_AddRefed<nsITraceableChannel> GetTraceableChannel(nsAtom* aAddonId, dom::nsIContentParent* aContentParent) const;
151
152
153
  void GetMethod(nsCString& aRetVal) const;
154
155
  dom::MozContentPolicyType Type() const;
156
157
158
  uint32_t StatusCode() const;
159
160
  void GetStatusLine(nsCString& aRetVal) const;
161
162
  void GetErrorString(nsString& aRetVal) const;
163
164
  void ErrorCheck();
165
166
  IMPL_EVENT_HANDLER(error);
167
  IMPL_EVENT_HANDLER(start);
168
  IMPL_EVENT_HANDLER(stop);
169
170
171
  already_AddRefed<nsIURI> FinalURI() const;
172
173
  void GetFinalURL(nsString& aRetVal) const;
174
175
176
  bool Matches(const dom::MozRequestFilter& aFilter,
177
               const WebExtensionPolicy* aExtension,
178
               const dom::MozRequestMatchOptions& aOptions) const;
179
180
181
  already_AddRefed<nsILoadInfo> GetLoadInfo() const
182
0
  {
183
0
    nsCOMPtr<nsIChannel> chan = MaybeChannel();
184
0
    if (chan) {
185
0
      return chan->GetLoadInfo();
186
0
    }
187
0
    return nullptr;
188
0
  }
189
190
  int64_t WindowId() const;
191
192
  int64_t ParentWindowId() const;
193
194
  void GetFrameAncestors(dom::Nullable<nsTArray<dom::MozFrameAncestorInfo>>& aFrameAncestors, ErrorResult& aRv) const;
195
196
  bool IsSystemLoad() const;
197
198
  void GetOriginURL(nsCString& aRetVal) const;
199
200
  void GetDocumentURL(nsCString& aRetVal) const;
201
202
  already_AddRefed<nsIURI> GetOriginURI() const;
203
204
  already_AddRefed<nsIURI> GetDocumentURI() const;
205
206
207
  already_AddRefed<nsILoadContext> GetLoadContext() const;
208
209
  already_AddRefed<dom::Element> GetBrowserElement() const;
210
211
212
  bool CanModify() const;
213
  bool GetCanModify(ErrorResult& aRv) const
214
0
  {
215
0
    return CanModify();
216
0
  }
217
218
219
  void GetProxyInfo(dom::Nullable<dom::MozProxyInfo>& aRetVal, ErrorResult& aRv) const;
220
221
  void GetRemoteAddress(nsCString& aRetVal) const;
222
223
224
  void GetRequestHeaders(nsTArray<dom::MozHTTPHeader>& aRetVal, ErrorResult& aRv) const;
225
226
  void GetResponseHeaders(nsTArray<dom::MozHTTPHeader>& aRetVal, ErrorResult& aRv) const;
227
228
  void SetRequestHeader(const nsCString& header, const nsCString& value, bool merge, ErrorResult& aRv);
229
230
  void SetResponseHeader(const nsCString& header, const nsCString& value, bool merge, ErrorResult& aRv);
231
232
233
  using EventTarget::EventListenerAdded;
234
  using EventTarget::EventListenerRemoved;
235
  virtual void EventListenerAdded(nsAtom* aType) override;
236
  virtual void EventListenerRemoved(nsAtom* aType) override;
237
238
239
0
  nsISupports* GetParentObject() const { return mParent; }
240
241
  JSObject* WrapObject(JSContext* aCx, JS::HandleObject aGivenProto) override;
242
243
protected:
244
0
  ~ChannelWrapper() = default;
245
246
private:
247
  ChannelWrapper(nsISupports* aParent, nsIChannel* aChannel)
248
    : ChannelHolder(aChannel)
249
    , mParent(aParent)
250
0
  {}
251
252
  void ClearCachedAttributes();
253
254
  bool CheckAlive(ErrorResult& aRv) const
255
0
  {
256
0
    if (!HaveChannel()) {
257
0
      aRv.Throw(NS_ERROR_UNEXPECTED);
258
0
      return false;
259
0
    }
260
0
    return true;
261
0
  }
262
263
  void FireEvent(const nsAString& aType);
264
265
266
  const URLInfo& FinalURLInfo() const;
267
  const URLInfo* DocumentURLInfo() const;
268
269
270
  uint64_t WindowId(nsILoadInfo* aLoadInfo) const;
271
272
  nsresult GetFrameAncestors(nsILoadInfo* aLoadInfo, nsTArray<dom::MozFrameAncestorInfo>& aFrameAncestors) const;
273
274
  static uint64_t GetNextId()
275
0
  {
276
0
    static uint64_t sNextId = 1;
277
0
    return ++sNextId;
278
0
  }
279
280
  void CheckEventListeners();
281
282
  mutable Maybe<URLInfo> mFinalURLInfo;
283
  mutable Maybe<URLInfo> mDocumentURLInfo;
284
285
  UniquePtr<WebRequestChannelEntry> mChannelEntry;
286
287
  // The overridden Content-Type header value.
288
  nsCString mContentTypeHdr = VoidCString();
289
290
  const uint64_t mId = GetNextId();
291
  nsCOMPtr<nsISupports> mParent;
292
293
  bool mAddedStreamListener = false;
294
  bool mFiredErrorEvent = false;
295
  bool mSuspended = false;
296
  bool mResponseStarted = false;
297
298
299
  nsInterfaceHashtable<nsPtrHashKey<const nsAtom>, nsITabParent> mAddonEntries;
300
301
302
  class RequestListener final : public nsIStreamListener
303
                              , public nsIThreadRetargetableStreamListener
304
  {
305
  public:
306
    NS_DECL_THREADSAFE_ISUPPORTS
307
    NS_DECL_NSIREQUESTOBSERVER
308
    NS_DECL_NSISTREAMLISTENER
309
    NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
310
311
    explicit RequestListener(ChannelWrapper* aWrapper)
312
0
      : mChannelWrapper(aWrapper) {}
313
314
    nsresult Init();
315
316
  protected:
317
    virtual ~RequestListener();
318
319
  private:
320
    RefPtr<ChannelWrapper> mChannelWrapper;
321
    nsCOMPtr<nsIStreamListener> mOrigStreamListener;
322
  };
323
};
324
325
NS_DEFINE_STATIC_IID_ACCESSOR(ChannelWrapper,
326
                              NS_CHANNELWRAPPER_IID)
327
328
} // namespace extensions
329
} // namespace mozilla
330
331
#endif // mozilla_extensions_ChannelWrapper_h