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/. */
7 #ifndef mozilla_dom_InternalResponse_h
8 #define mozilla_dom_InternalResponse_h
10 #include "mozilla/dom/FetchTypes.h"
11 #include "nsIInputStream.h"
12 #include "nsICacheInfoChannel.h"
13 #include "nsISupportsImpl.h"
14 #include "nsProxyRelease.h"
16 #include "mozilla/dom/InternalHeaders.h"
17 #include "mozilla/dom/RequestBinding.h"
18 #include "mozilla/dom/ResponseBinding.h"
19 #include "mozilla/dom/ChannelInfo.h"
20 #include "mozilla/dom/SafeRefPtr.h"
21 #include "mozilla/NotNull.h"
22 #include "mozilla/UniquePtr.h"
26 class PBackgroundChild
;
27 class PBackgroundParent
;
33 class ChildToParentInternalResponse
;
34 class InternalHeaders
;
35 class ParentToChildInternalResponse
;
36 class ParentToParentInternalResponse
;
38 class InternalResponse final
: public AtomicSafeRefCounted
<InternalResponse
> {
39 friend class FetchDriver
;
42 MOZ_DECLARE_REFCOUNTED_TYPENAME(InternalResponse
)
45 uint16_t aStatus
, const nsACString
& aStatusText
,
46 RequestCredentials aCredentialsMode
= RequestCredentials::Omit
);
48 static SafeRefPtr
<InternalResponse
> FromIPC(
49 const ParentToChildInternalResponse
& aIPCResponse
);
51 static SafeRefPtr
<InternalResponse
> FromIPC(
52 const ParentToParentInternalResponse
& aIPCResponse
);
54 void ToChildToParentInternalResponse(
55 ChildToParentInternalResponse
* aIPCResponse
,
56 mozilla::ipc::PBackgroundChild
* aManager
);
58 ParentToParentInternalResponse
ToParentToParentInternalResponse();
62 eDontCloneInputStream
,
65 SafeRefPtr
<InternalResponse
> Clone(CloneType aCloneType
);
67 static SafeRefPtr
<InternalResponse
> NetworkError(nsresult aRv
) {
68 MOZ_DIAGNOSTIC_ASSERT(NS_FAILED(aRv
));
69 SafeRefPtr
<InternalResponse
> response
=
70 MakeSafeRefPtr
<InternalResponse
>(0, ""_ns
);
72 response
->Headers()->SetGuard(HeadersGuardEnum::Immutable
, result
);
73 MOZ_ASSERT(!result
.Failed());
74 response
->mType
= ResponseType::Error
;
75 response
->mErrorCode
= aRv
;
79 SafeRefPtr
<InternalResponse
> OpaqueResponse();
81 SafeRefPtr
<InternalResponse
> OpaqueRedirectResponse();
83 SafeRefPtr
<InternalResponse
> BasicResponse();
85 SafeRefPtr
<InternalResponse
> CORSResponse();
87 ResponseType
Type() const {
88 MOZ_ASSERT_IF(mType
== ResponseType::Error
, !mWrappedResponse
);
89 MOZ_ASSERT_IF(mType
== ResponseType::Default
, !mWrappedResponse
);
90 MOZ_ASSERT_IF(mType
== ResponseType::Basic
, mWrappedResponse
);
91 MOZ_ASSERT_IF(mType
== ResponseType::Cors
, mWrappedResponse
);
92 MOZ_ASSERT_IF(mType
== ResponseType::Opaque
, mWrappedResponse
);
93 MOZ_ASSERT_IF(mType
== ResponseType::Opaqueredirect
, mWrappedResponse
);
97 bool IsError() const { return Type() == ResponseType::Error
; }
98 // GetUrl should return last fetch URL in response's url list and null if
99 // response's url list is the empty list.
100 const nsCString
& GetURL() const {
101 // Empty urlList when response is a synthetic response.
102 if (mURLList
.IsEmpty()) {
103 return EmptyCString();
105 return mURLList
.LastElement();
107 void GetURLList(nsTArray
<nsCString
>& aURLList
) const {
108 aURLList
.Assign(mURLList
);
110 const nsCString
& GetUnfilteredURL() const {
111 if (mWrappedResponse
) {
112 return mWrappedResponse
->GetURL();
116 void GetUnfilteredURLList(nsTArray
<nsCString
>& aURLList
) const {
117 if (mWrappedResponse
) {
118 return mWrappedResponse
->GetURLList(aURLList
);
121 return GetURLList(aURLList
);
124 nsTArray
<nsCString
> GetUnfilteredURLList() const {
125 nsTArray
<nsCString
> list
;
126 GetUnfilteredURLList(list
);
130 void SetURLList(const nsTArray
<nsCString
>& aURLList
) {
131 mURLList
.Assign(aURLList
);
134 for (uint32_t i
= 0; i
< mURLList
.Length(); ++i
) {
135 MOZ_ASSERT(mURLList
[i
].Find("#"_ns
) == kNotFound
);
140 uint16_t GetStatus() const { return mStatus
; }
142 uint16_t GetUnfilteredStatus() const {
143 if (mWrappedResponse
) {
144 return mWrappedResponse
->GetStatus();
150 const nsCString
& GetStatusText() const { return mStatusText
; }
152 const nsCString
& GetUnfilteredStatusText() const {
153 if (mWrappedResponse
) {
154 return mWrappedResponse
->GetStatusText();
157 return GetStatusText();
160 InternalHeaders
* Headers() { return mHeaders
; }
162 InternalHeaders
* UnfilteredHeaders() {
163 if (mWrappedResponse
) {
164 return mWrappedResponse
->Headers();
170 void GetUnfilteredBody(nsIInputStream
** aStream
,
171 int64_t* aBodySize
= nullptr) {
172 if (mWrappedResponse
) {
174 return mWrappedResponse
->GetBody(aStream
, aBodySize
);
176 nsCOMPtr
<nsIInputStream
> stream
= mBody
;
177 stream
.forget(aStream
);
179 *aBodySize
= mBodySize
;
183 void GetBody(nsIInputStream
** aStream
, int64_t* aBodySize
= nullptr) {
184 if (Type() == ResponseType::Opaque
||
185 Type() == ResponseType::Opaqueredirect
) {
188 *aBodySize
= UNKNOWN_BODY_SIZE
;
193 GetUnfilteredBody(aStream
, aBodySize
);
196 void SetBodyBlobURISpec(nsACString
& aBlobURISpec
) {
197 mBodyBlobURISpec
= aBlobURISpec
;
200 const nsACString
& BodyBlobURISpec() const {
201 if (mWrappedResponse
) {
202 return mWrappedResponse
->BodyBlobURISpec();
204 return mBodyBlobURISpec
;
207 void SetBodyLocalPath(nsAString
& aLocalPath
) { mBodyLocalPath
= aLocalPath
; }
209 const nsAString
& BodyLocalPath() const {
210 if (mWrappedResponse
) {
211 return mWrappedResponse
->BodyLocalPath();
213 return mBodyLocalPath
;
216 void SetBody(nsIInputStream
* aBody
, int64_t aBodySize
) {
217 if (mWrappedResponse
) {
218 return mWrappedResponse
->SetBody(aBody
, aBodySize
);
220 // A request's body may not be reset once set.
222 MOZ_ASSERT(mBodySize
== UNKNOWN_BODY_SIZE
);
224 MOZ_ASSERT(aBodySize
== UNKNOWN_BODY_SIZE
|| aBodySize
>= 0);
225 // If body is not given, then size must be unknown.
226 MOZ_ASSERT_IF(!aBody
, aBodySize
== UNKNOWN_BODY_SIZE
);
229 mBodySize
= aBodySize
;
232 uint32_t GetPaddingInfo();
234 nsresult
GeneratePaddingInfo();
236 int64_t GetPaddingSize();
238 void SetPaddingSize(int64_t aPaddingSize
);
240 void SetAlternativeDataType(const nsACString
& aAltDataType
) {
241 if (mWrappedResponse
) {
242 return mWrappedResponse
->SetAlternativeDataType(aAltDataType
);
245 MOZ_DIAGNOSTIC_ASSERT(mAlternativeDataType
.IsEmpty());
247 mAlternativeDataType
.Assign(aAltDataType
);
250 const nsCString
& GetAlternativeDataType() {
251 if (mWrappedResponse
) {
252 return mWrappedResponse
->GetAlternativeDataType();
255 return mAlternativeDataType
;
258 void SetAlternativeBody(nsIInputStream
* aAlternativeBody
) {
259 if (mWrappedResponse
) {
260 return mWrappedResponse
->SetAlternativeBody(aAlternativeBody
);
262 // A request's body may not be reset once set.
263 MOZ_DIAGNOSTIC_ASSERT(!mAlternativeBody
);
265 mAlternativeBody
= aAlternativeBody
;
268 already_AddRefed
<nsIInputStream
> TakeAlternativeBody() {
269 if (mWrappedResponse
) {
270 return mWrappedResponse
->TakeAlternativeBody();
273 if (!mAlternativeBody
) {
277 // cleanup the non-alternative body here.
278 // Once alternative data is used, the real body is no need anymore.
280 mBodySize
= UNKNOWN_BODY_SIZE
;
281 return mAlternativeBody
.forget();
284 void SetCacheInfoChannel(
285 const nsMainThreadPtrHandle
<nsICacheInfoChannel
>& aCacheInfoChannel
) {
286 if (mWrappedResponse
) {
287 return mWrappedResponse
->SetCacheInfoChannel(aCacheInfoChannel
);
289 MOZ_ASSERT(!mCacheInfoChannel
);
290 mCacheInfoChannel
= aCacheInfoChannel
;
293 nsMainThreadPtrHandle
<nsICacheInfoChannel
> TakeCacheInfoChannel() {
294 if (mWrappedResponse
) {
295 return mWrappedResponse
->TakeCacheInfoChannel();
297 nsMainThreadPtrHandle
<nsICacheInfoChannel
> rtn
= mCacheInfoChannel
;
298 mCacheInfoChannel
= nullptr;
302 bool HasCacheInfoChannel() const {
303 if (mWrappedResponse
) {
304 return !!mWrappedResponse
->HasCacheInfoChannel();
306 return !!mCacheInfoChannel
;
309 bool HasBeenCloned() const { return mCloned
; }
311 void InitChannelInfo(nsIChannel
* aChannel
) {
312 mChannelInfo
.InitFromChannel(aChannel
);
315 void InitChannelInfo(const mozilla::ipc::IPCChannelInfo
& aChannelInfo
) {
316 mChannelInfo
.InitFromIPCChannelInfo(aChannelInfo
);
319 void InitChannelInfo(const ChannelInfo
& aChannelInfo
) {
320 mChannelInfo
= aChannelInfo
;
323 const ChannelInfo
& GetChannelInfo() const { return mChannelInfo
; }
325 const UniquePtr
<mozilla::ipc::PrincipalInfo
>& GetPrincipalInfo() const {
326 return mPrincipalInfo
;
329 bool IsRedirected() const { return mURLList
.Length() > 1; }
331 nsresult
GetErrorCode() const { return mErrorCode
; }
333 // Takes ownership of the principal info.
334 void SetPrincipalInfo(UniquePtr
<mozilla::ipc::PrincipalInfo
> aPrincipalInfo
);
336 LoadTainting
GetTainting() const;
338 SafeRefPtr
<InternalResponse
> Unfiltered();
343 explicit InternalResponse(const InternalResponse
& aOther
) = delete;
344 InternalResponse
& operator=(const InternalResponse
&) = delete;
346 // Returns an instance of InternalResponse which is a copy of this
347 // InternalResponse, except headers, body and wrapped response (if any) which
348 // are left uninitialized. Used for cloning and filtering.
349 SafeRefPtr
<InternalResponse
> CreateIncompleteCopy();
351 template <typename T
>
352 static SafeRefPtr
<InternalResponse
> FromIPCTemplate(const T
& aIPCResponse
);
354 InternalResponseMetadata
GetMetadata();
357 // A response has an associated url list (a list of zero or more fetch URLs).
358 // Unless stated otherwise, it is the empty list. The current url is the last
359 // element in mURLlist
360 nsTArray
<nsCString
> mURLList
;
361 const uint16_t mStatus
;
362 const nsCString mStatusText
;
363 RefPtr
<InternalHeaders
> mHeaders
;
364 nsCOMPtr
<nsIInputStream
> mBody
;
365 nsCString mBodyBlobURISpec
;
366 nsString mBodyLocalPath
;
368 // It's used to passed to the CacheResponse to generate padding size. Once, we
369 // generate the padding size for resposne, we don't need it anymore.
370 Maybe
<uint32_t> mPaddingInfo
;
371 int64_t mPaddingSize
;
373 RequestCredentials mCredentialsMode
;
375 // For alternative data such as JS Bytecode cached in the HTTP cache.
376 nsCString mAlternativeDataType
;
377 nsCOMPtr
<nsIInputStream
> mAlternativeBody
;
378 nsMainThreadPtrHandle
<nsICacheInfoChannel
> mCacheInfoChannel
;
382 static constexpr int64_t UNKNOWN_BODY_SIZE
= -1;
383 static constexpr int64_t UNKNOWN_PADDING_SIZE
= -1;
386 ChannelInfo mChannelInfo
;
387 UniquePtr
<mozilla::ipc::PrincipalInfo
> mPrincipalInfo
;
389 // For filtered responses.
390 // Cache, and SW interception should always serialize/access the underlying
391 // unfiltered headers and when deserializing, create an InternalResponse
392 // with the unfiltered headers followed by wrapping it.
393 SafeRefPtr
<InternalResponse
> mWrappedResponse
;
396 ParentToChildInternalResponse
ToParentToChild(
397 const ParentToParentInternalResponse
& aResponse
,
398 NotNull
<mozilla::ipc::PBackgroundParent
*> aBackgroundParent
);
401 } // namespace mozilla
403 #endif // mozilla_dom_InternalResponse_h