Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/dom/InternalResponse.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; 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_dom_InternalResponse_h
8
#define mozilla_dom_InternalResponse_h
9
10
#include "nsIInputStream.h"
11
#include "nsICacheInfoChannel.h"
12
#include "nsISupportsImpl.h"
13
#include "nsProxyRelease.h"
14
15
#include "mozilla/dom/InternalHeaders.h"
16
#include "mozilla/dom/ResponseBinding.h"
17
#include "mozilla/dom/ChannelInfo.h"
18
#include "mozilla/UniquePtr.h"
19
20
namespace mozilla {
21
namespace ipc {
22
class PrincipalInfo;
23
class AutoIPCStream;
24
} // namespace ipc
25
26
namespace dom {
27
28
class InternalHeaders;
29
class IPCInternalResponse;
30
31
class InternalResponse final
32
{
33
  friend class FetchDriver;
34
35
public:
36
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(InternalResponse)
37
38
  InternalResponse(uint16_t aStatus, const nsACString& aStatusText);
39
40
  static already_AddRefed<InternalResponse>
41
  FromIPC(const IPCInternalResponse& aIPCResponse);
42
43
  template<typename M>
44
  void
45
  ToIPC(IPCInternalResponse* aIPCResponse,
46
        M* aManager,
47
        UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoStream);
48
49
  enum CloneType
50
  {
51
    eCloneInputStream,
52
    eDontCloneInputStream,
53
  };
54
55
  already_AddRefed<InternalResponse> Clone(CloneType eCloneType);
56
57
  static already_AddRefed<InternalResponse>
58
  NetworkError(nsresult aRv)
59
0
  {
60
0
    MOZ_DIAGNOSTIC_ASSERT(NS_FAILED(aRv));
61
0
    RefPtr<InternalResponse> response = new InternalResponse(0, EmptyCString());
62
0
    ErrorResult result;
63
0
    response->Headers()->SetGuard(HeadersGuardEnum::Immutable, result);
64
0
    MOZ_ASSERT(!result.Failed());
65
0
    response->mType = ResponseType::Error;
66
0
    response->mErrorCode = aRv;
67
0
    return response.forget();
68
0
  }
69
70
  already_AddRefed<InternalResponse>
71
  OpaqueResponse();
72
73
  already_AddRefed<InternalResponse>
74
  OpaqueRedirectResponse();
75
76
  already_AddRefed<InternalResponse>
77
  BasicResponse();
78
79
  already_AddRefed<InternalResponse>
80
  CORSResponse();
81
82
  ResponseType
83
  Type() const
84
0
  {
85
0
    MOZ_ASSERT_IF(mType == ResponseType::Error, !mWrappedResponse);
86
0
    MOZ_ASSERT_IF(mType == ResponseType::Default, !mWrappedResponse);
87
0
    MOZ_ASSERT_IF(mType == ResponseType::Basic, mWrappedResponse);
88
0
    MOZ_ASSERT_IF(mType == ResponseType::Cors, mWrappedResponse);
89
0
    MOZ_ASSERT_IF(mType == ResponseType::Opaque, mWrappedResponse);
90
0
    MOZ_ASSERT_IF(mType == ResponseType::Opaqueredirect, mWrappedResponse);
91
0
    return mType;
92
0
  }
93
94
  bool
95
  IsError() const
96
0
  {
97
0
    return Type() == ResponseType::Error;
98
0
  }
99
  // GetUrl should return last fetch URL in response's url list and null if
100
  // response's url list is the empty list.
101
  const nsCString&
102
  GetURL() const
103
0
  {
104
0
    // Empty urlList when response is a synthetic response.
105
0
    if (mURLList.IsEmpty()) {
106
0
      return EmptyCString();
107
0
    }
108
0
    return mURLList.LastElement();
109
0
  }
110
  void
111
  GetURLList(nsTArray<nsCString>& aURLList) const
112
0
  {
113
0
    aURLList.Assign(mURLList);
114
0
  }
115
  const nsCString&
116
  GetUnfilteredURL() const
117
0
  {
118
0
    if (mWrappedResponse) {
119
0
      return mWrappedResponse->GetURL();
120
0
    }
121
0
    return GetURL();
122
0
  }
123
  void
124
  GetUnfilteredURLList(nsTArray<nsCString>& aURLList) const
125
0
  {
126
0
    if (mWrappedResponse) {
127
0
      return mWrappedResponse->GetURLList(aURLList);
128
0
    }
129
0
130
0
    return GetURLList(aURLList);
131
0
  }
132
133
  void
134
  SetURLList(const nsTArray<nsCString>& aURLList)
135
0
  {
136
0
    mURLList.Assign(aURLList);
137
0
138
#ifdef DEBUG
139
    for(uint32_t i = 0; i < mURLList.Length(); ++i) {
140
      MOZ_ASSERT(mURLList[i].Find(NS_LITERAL_CSTRING("#")) == kNotFound);
141
    }
142
#endif
143
  }
144
145
  uint16_t
146
  GetStatus() const
147
0
  {
148
0
    return mStatus;
149
0
  }
150
151
  uint16_t
152
  GetUnfilteredStatus() const
153
0
  {
154
0
    if (mWrappedResponse) {
155
0
      return mWrappedResponse->GetStatus();
156
0
    }
157
0
158
0
    return GetStatus();
159
0
  }
160
161
  const nsCString&
162
  GetStatusText() const
163
0
  {
164
0
    return mStatusText;
165
0
  }
166
167
  const nsCString&
168
  GetUnfilteredStatusText() const
169
0
  {
170
0
    if (mWrappedResponse) {
171
0
      return mWrappedResponse->GetStatusText();
172
0
    }
173
0
174
0
    return GetStatusText();
175
0
  }
176
177
  InternalHeaders*
178
  Headers()
179
0
  {
180
0
    return mHeaders;
181
0
  }
182
183
  InternalHeaders*
184
  UnfilteredHeaders()
185
0
  {
186
0
    if (mWrappedResponse) {
187
0
      return mWrappedResponse->Headers();
188
0
    };
189
0
190
0
    return Headers();
191
0
  }
192
193
  void
194
  GetUnfilteredBody(nsIInputStream** aStream, int64_t* aBodySize = nullptr)
195
0
  {
196
0
    if (mWrappedResponse) {
197
0
      MOZ_ASSERT(!mBody);
198
0
      return mWrappedResponse->GetBody(aStream, aBodySize);
199
0
    }
200
0
    nsCOMPtr<nsIInputStream> stream = mBody;
201
0
    stream.forget(aStream);
202
0
    if (aBodySize) {
203
0
      *aBodySize = mBodySize;
204
0
    }
205
0
  }
206
207
  void
208
  GetBody(nsIInputStream** aStream, int64_t* aBodySize = nullptr)
209
0
  {
210
0
    if (Type() == ResponseType::Opaque ||
211
0
        Type() == ResponseType::Opaqueredirect) {
212
0
      *aStream = nullptr;
213
0
      if (aBodySize) {
214
0
        *aBodySize = UNKNOWN_BODY_SIZE;
215
0
      }
216
0
      return;
217
0
    }
218
0
219
0
    GetUnfilteredBody(aStream, aBodySize);
220
0
  }
221
222
  void
223
  SetBodyLocalPath(nsAString& aLocalPath)
224
  {
225
    mBodyLocalPath = aLocalPath;
226
  }
227
228
  const nsAString&
229
  BodyLocalPath() const
230
  {
231
    if (mWrappedResponse) {
232
      return mWrappedResponse->BodyLocalPath();
233
    }
234
    return mBodyLocalPath;
235
  }
236
237
  void
238
  SetBody(nsIInputStream* aBody, int64_t aBodySize)
239
0
  {
240
0
    if (mWrappedResponse) {
241
0
      return mWrappedResponse->SetBody(aBody, aBodySize);
242
0
    }
243
0
    // A request's body may not be reset once set.
244
0
    MOZ_ASSERT(!mBody);
245
0
    MOZ_ASSERT(mBodySize == UNKNOWN_BODY_SIZE);
246
0
    // Check arguments.
247
0
    MOZ_ASSERT(aBodySize == UNKNOWN_BODY_SIZE || aBodySize >= 0);
248
0
    // If body is not given, then size must be unknown.
249
0
    MOZ_ASSERT_IF(!aBody, aBodySize == UNKNOWN_BODY_SIZE);
250
0
251
0
    mBody = aBody;
252
0
    mBodySize = aBodySize;
253
0
  }
254
255
  uint32_t
256
  GetPaddingInfo();
257
258
  nsresult
259
  GeneratePaddingInfo();
260
261
  int64_t
262
  GetPaddingSize();
263
264
  void
265
  SetPaddingSize(int64_t aPaddingSize);
266
267
  void
268
  SetAlternativeBody(nsIInputStream* aAlternativeBody)
269
  {
270
    if (mWrappedResponse) {
271
      return mWrappedResponse->SetAlternativeBody(aAlternativeBody);
272
    }
273
    // A request's body may not be reset once set.
274
    MOZ_DIAGNOSTIC_ASSERT(!mAlternativeBody);
275
276
    mAlternativeBody = aAlternativeBody;
277
  }
278
279
  already_AddRefed<nsIInputStream>
280
  TakeAlternativeBody()
281
0
  {
282
0
    if (mWrappedResponse) {
283
0
      return mWrappedResponse->TakeAlternativeBody();
284
0
    }
285
0
286
0
    if (!mAlternativeBody) {
287
0
      return nullptr;
288
0
    }
289
0
290
0
    // cleanup the non-alternative body here.
291
0
    // Once alternative data is used, the real body is no need anymore.
292
0
    mBody = nullptr;
293
0
    mBodySize = UNKNOWN_BODY_SIZE;
294
0
    return mAlternativeBody.forget();
295
0
  }
296
297
  void
298
  SetCacheInfoChannel(const nsMainThreadPtrHandle<nsICacheInfoChannel>& aCacheInfoChannel)
299
  {
300
    if (mWrappedResponse) {
301
      return mWrappedResponse->SetCacheInfoChannel(aCacheInfoChannel);
302
    }
303
    MOZ_ASSERT(!mCacheInfoChannel);
304
    mCacheInfoChannel = aCacheInfoChannel;
305
  }
306
307
  nsMainThreadPtrHandle<nsICacheInfoChannel>
308
  TakeCacheInfoChannel()
309
0
  {
310
0
    if (mWrappedResponse) {
311
0
      return mWrappedResponse->TakeCacheInfoChannel();
312
0
    }
313
0
    nsMainThreadPtrHandle<nsICacheInfoChannel> rtn = mCacheInfoChannel;
314
0
    mCacheInfoChannel = nullptr;
315
0
    return rtn;
316
0
  }
317
318
  void
319
  InitChannelInfo(nsIChannel* aChannel)
320
  {
321
    mChannelInfo.InitFromChannel(aChannel);
322
  }
323
324
  void
325
  InitChannelInfo(const mozilla::ipc::IPCChannelInfo& aChannelInfo)
326
0
  {
327
0
    mChannelInfo.InitFromIPCChannelInfo(aChannelInfo);
328
0
  }
329
330
  void
331
  InitChannelInfo(const ChannelInfo& aChannelInfo)
332
  {
333
    mChannelInfo = aChannelInfo;
334
  }
335
336
  const ChannelInfo&
337
  GetChannelInfo() const
338
0
  {
339
0
    return mChannelInfo;
340
0
  }
341
342
  const UniquePtr<mozilla::ipc::PrincipalInfo>&
343
  GetPrincipalInfo() const
344
0
  {
345
0
    return mPrincipalInfo;
346
0
  }
347
348
  bool
349
  IsRedirected() const
350
0
  {
351
0
    return mURLList.Length() > 1;
352
0
  }
353
354
  nsresult
355
  GetErrorCode() const
356
  {
357
    return mErrorCode;
358
  }
359
360
  // Takes ownership of the principal info.
361
  void
362
  SetPrincipalInfo(UniquePtr<mozilla::ipc::PrincipalInfo> aPrincipalInfo);
363
364
  LoadTainting
365
  GetTainting() const;
366
367
  already_AddRefed<InternalResponse>
368
  Unfiltered();
369
370
private:
371
  ~InternalResponse();
372
373
  explicit InternalResponse(const InternalResponse& aOther) = delete;
374
  InternalResponse& operator=(const InternalResponse&) = delete;
375
376
  // Returns an instance of InternalResponse which is a copy of this
377
  // InternalResponse, except headers, body and wrapped response (if any) which
378
  // are left uninitialized. Used for cloning and filtering.
379
  already_AddRefed<InternalResponse> CreateIncompleteCopy();
380
381
  ResponseType mType;
382
  nsCString mTerminationReason;
383
  // A response has an associated url list (a list of zero or more fetch URLs).
384
  // Unless stated otherwise, it is the empty list. The current url is the last
385
  // element in mURLlist
386
  nsTArray<nsCString> mURLList;
387
  const uint16_t mStatus;
388
  const nsCString mStatusText;
389
  RefPtr<InternalHeaders> mHeaders;
390
  nsCOMPtr<nsIInputStream> mBody;
391
  nsString mBodyLocalPath;
392
  int64_t mBodySize;
393
  // It's used to passed to the CacheResponse to generate padding size. Once, we
394
  // generate the padding size for resposne, we don't need it anymore.
395
  Maybe<uint32_t> mPaddingInfo;
396
  int64_t mPaddingSize;
397
  nsresult mErrorCode;
398
399
  // For alternative data such as JS Bytecode cached in the HTTP cache.
400
  nsCOMPtr<nsIInputStream> mAlternativeBody;
401
  nsMainThreadPtrHandle<nsICacheInfoChannel> mCacheInfoChannel;
402
403
public:
404
  static const int64_t UNKNOWN_BODY_SIZE = -1;
405
  static const int64_t UNKNOWN_PADDING_SIZE = -1;
406
private:
407
  ChannelInfo mChannelInfo;
408
  UniquePtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
409
410
  // For filtered responses.
411
  // Cache, and SW interception should always serialize/access the underlying
412
  // unfiltered headers and when deserializing, create an InternalResponse
413
  // with the unfiltered headers followed by wrapping it.
414
  RefPtr<InternalResponse> mWrappedResponse;
415
};
416
417
} // namespace dom
418
} // namespace mozilla
419
420
#endif // mozilla_dom_InternalResponse_h