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 "nsIInputStream.h"
11 #include "nsICacheInfoChannel.h"
12 #include "nsISupportsImpl.h"
13 #include "nsProxyRelease.h"
15 #include "mozilla/dom/InternalHeaders.h"
16 #include "mozilla/dom/RequestBinding.h"
17 #include "mozilla/dom/ResponseBinding.h"
18 #include "mozilla/dom/ChannelInfo.h"
19 #include "mozilla/UniquePtr.h"
24 class PBackgroundChild
;
30 class IPCInternalResponse
;
31 class InternalHeaders
;
33 class InternalResponse final
{
34 friend class FetchDriver
;
37 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(InternalResponse
)
40 uint16_t aStatus
, const nsACString
& aStatusText
,
41 RequestCredentials aCredentialsMode
= RequestCredentials::Omit
);
43 static RefPtr
<InternalResponse
> FromIPC(
44 const IPCInternalResponse
& aIPCResponse
);
46 // Note: the AutoIPCStreams must outlive the IPCInternalResponse.
48 IPCInternalResponse
* aIPCResponse
,
49 mozilla::ipc::PBackgroundChild
* aManager
,
50 UniquePtr
<mozilla::ipc::AutoIPCStream
>& aAutoBodyStream
,
51 UniquePtr
<mozilla::ipc::AutoIPCStream
>& aAutoAlternativeBodyStream
);
55 eDontCloneInputStream
,
58 already_AddRefed
<InternalResponse
> Clone(CloneType eCloneType
);
60 static already_AddRefed
<InternalResponse
> NetworkError(nsresult aRv
) {
61 MOZ_DIAGNOSTIC_ASSERT(NS_FAILED(aRv
));
62 RefPtr
<InternalResponse
> response
= new InternalResponse(0, ""_ns
);
64 response
->Headers()->SetGuard(HeadersGuardEnum::Immutable
, result
);
65 MOZ_ASSERT(!result
.Failed());
66 response
->mType
= ResponseType::Error
;
67 response
->mErrorCode
= aRv
;
68 return response
.forget();
71 already_AddRefed
<InternalResponse
> OpaqueResponse();
73 already_AddRefed
<InternalResponse
> OpaqueRedirectResponse();
75 already_AddRefed
<InternalResponse
> BasicResponse();
77 already_AddRefed
<InternalResponse
> CORSResponse();
79 ResponseType
Type() const {
80 MOZ_ASSERT_IF(mType
== ResponseType::Error
, !mWrappedResponse
);
81 MOZ_ASSERT_IF(mType
== ResponseType::Default
, !mWrappedResponse
);
82 MOZ_ASSERT_IF(mType
== ResponseType::Basic
, mWrappedResponse
);
83 MOZ_ASSERT_IF(mType
== ResponseType::Cors
, mWrappedResponse
);
84 MOZ_ASSERT_IF(mType
== ResponseType::Opaque
, mWrappedResponse
);
85 MOZ_ASSERT_IF(mType
== ResponseType::Opaqueredirect
, mWrappedResponse
);
89 bool IsError() const { return Type() == ResponseType::Error
; }
90 // GetUrl should return last fetch URL in response's url list and null if
91 // response's url list is the empty list.
92 const nsCString
& GetURL() const {
93 // Empty urlList when response is a synthetic response.
94 if (mURLList
.IsEmpty()) {
95 return EmptyCString();
97 return mURLList
.LastElement();
99 void GetURLList(nsTArray
<nsCString
>& aURLList
) const {
100 aURLList
.Assign(mURLList
);
102 const nsCString
& GetUnfilteredURL() const {
103 if (mWrappedResponse
) {
104 return mWrappedResponse
->GetURL();
108 void GetUnfilteredURLList(nsTArray
<nsCString
>& aURLList
) const {
109 if (mWrappedResponse
) {
110 return mWrappedResponse
->GetURLList(aURLList
);
113 return GetURLList(aURLList
);
116 nsTArray
<nsCString
> GetUnfilteredURLList() const {
117 nsTArray
<nsCString
> list
;
118 GetUnfilteredURLList(list
);
122 void SetURLList(const nsTArray
<nsCString
>& aURLList
) {
123 mURLList
.Assign(aURLList
);
126 for (uint32_t i
= 0; i
< mURLList
.Length(); ++i
) {
127 MOZ_ASSERT(mURLList
[i
].Find("#"_ns
) == kNotFound
);
132 uint16_t GetStatus() const { return mStatus
; }
134 uint16_t GetUnfilteredStatus() const {
135 if (mWrappedResponse
) {
136 return mWrappedResponse
->GetStatus();
142 const nsCString
& GetStatusText() const { return mStatusText
; }
144 const nsCString
& GetUnfilteredStatusText() const {
145 if (mWrappedResponse
) {
146 return mWrappedResponse
->GetStatusText();
149 return GetStatusText();
152 InternalHeaders
* Headers() { return mHeaders
; }
154 InternalHeaders
* UnfilteredHeaders() {
155 if (mWrappedResponse
) {
156 return mWrappedResponse
->Headers();
162 void GetUnfilteredBody(nsIInputStream
** aStream
,
163 int64_t* aBodySize
= nullptr) {
164 if (mWrappedResponse
) {
166 return mWrappedResponse
->GetBody(aStream
, aBodySize
);
168 nsCOMPtr
<nsIInputStream
> stream
= mBody
;
169 stream
.forget(aStream
);
171 *aBodySize
= mBodySize
;
175 void GetBody(nsIInputStream
** aStream
, int64_t* aBodySize
= nullptr) {
176 if (Type() == ResponseType::Opaque
||
177 Type() == ResponseType::Opaqueredirect
) {
180 *aBodySize
= UNKNOWN_BODY_SIZE
;
185 GetUnfilteredBody(aStream
, aBodySize
);
188 void SetBodyBlobURISpec(nsACString
& aBlobURISpec
) {
189 mBodyBlobURISpec
= aBlobURISpec
;
192 const nsACString
& BodyBlobURISpec() const {
193 if (mWrappedResponse
) {
194 return mWrappedResponse
->BodyBlobURISpec();
196 return mBodyBlobURISpec
;
199 void SetBodyLocalPath(nsAString
& aLocalPath
) { mBodyLocalPath
= aLocalPath
; }
201 const nsAString
& BodyLocalPath() const {
202 if (mWrappedResponse
) {
203 return mWrappedResponse
->BodyLocalPath();
205 return mBodyLocalPath
;
208 void SetBody(nsIInputStream
* aBody
, int64_t aBodySize
) {
209 if (mWrappedResponse
) {
210 return mWrappedResponse
->SetBody(aBody
, aBodySize
);
212 // A request's body may not be reset once set.
214 MOZ_ASSERT(mBodySize
== UNKNOWN_BODY_SIZE
);
216 MOZ_ASSERT(aBodySize
== UNKNOWN_BODY_SIZE
|| aBodySize
>= 0);
217 // If body is not given, then size must be unknown.
218 MOZ_ASSERT_IF(!aBody
, aBodySize
== UNKNOWN_BODY_SIZE
);
221 mBodySize
= aBodySize
;
224 uint32_t GetPaddingInfo();
226 nsresult
GeneratePaddingInfo();
228 int64_t GetPaddingSize();
230 void SetPaddingSize(int64_t aPaddingSize
);
232 void SetAlternativeDataType(const nsACString
& aAltDataType
) {
233 if (mWrappedResponse
) {
234 return mWrappedResponse
->SetAlternativeDataType(aAltDataType
);
237 MOZ_DIAGNOSTIC_ASSERT(mAlternativeDataType
.IsEmpty());
239 mAlternativeDataType
.Assign(aAltDataType
);
242 const nsCString
& GetAlternativeDataType() {
243 if (mWrappedResponse
) {
244 return mWrappedResponse
->GetAlternativeDataType();
247 return mAlternativeDataType
;
250 void SetAlternativeBody(nsIInputStream
* aAlternativeBody
) {
251 if (mWrappedResponse
) {
252 return mWrappedResponse
->SetAlternativeBody(aAlternativeBody
);
254 // A request's body may not be reset once set.
255 MOZ_DIAGNOSTIC_ASSERT(!mAlternativeBody
);
257 mAlternativeBody
= aAlternativeBody
;
260 already_AddRefed
<nsIInputStream
> TakeAlternativeBody() {
261 if (mWrappedResponse
) {
262 return mWrappedResponse
->TakeAlternativeBody();
265 if (!mAlternativeBody
) {
269 // cleanup the non-alternative body here.
270 // Once alternative data is used, the real body is no need anymore.
272 mBodySize
= UNKNOWN_BODY_SIZE
;
273 return mAlternativeBody
.forget();
276 void SetCacheInfoChannel(
277 const nsMainThreadPtrHandle
<nsICacheInfoChannel
>& aCacheInfoChannel
) {
278 if (mWrappedResponse
) {
279 return mWrappedResponse
->SetCacheInfoChannel(aCacheInfoChannel
);
281 MOZ_ASSERT(!mCacheInfoChannel
);
282 mCacheInfoChannel
= aCacheInfoChannel
;
285 nsMainThreadPtrHandle
<nsICacheInfoChannel
> TakeCacheInfoChannel() {
286 if (mWrappedResponse
) {
287 return mWrappedResponse
->TakeCacheInfoChannel();
289 nsMainThreadPtrHandle
<nsICacheInfoChannel
> rtn
= mCacheInfoChannel
;
290 mCacheInfoChannel
= nullptr;
294 bool HasCacheInfoChannel() const {
295 if (mWrappedResponse
) {
296 return !!mWrappedResponse
->HasCacheInfoChannel();
298 return !!mCacheInfoChannel
;
301 void InitChannelInfo(nsIChannel
* aChannel
) {
302 mChannelInfo
.InitFromChannel(aChannel
);
305 void InitChannelInfo(const mozilla::ipc::IPCChannelInfo
& aChannelInfo
) {
306 mChannelInfo
.InitFromIPCChannelInfo(aChannelInfo
);
309 void InitChannelInfo(const ChannelInfo
& aChannelInfo
) {
310 mChannelInfo
= aChannelInfo
;
313 const ChannelInfo
& GetChannelInfo() const { return mChannelInfo
; }
315 const UniquePtr
<mozilla::ipc::PrincipalInfo
>& GetPrincipalInfo() const {
316 return mPrincipalInfo
;
319 bool IsRedirected() const { return mURLList
.Length() > 1; }
321 nsresult
GetErrorCode() const { return mErrorCode
; }
323 // Takes ownership of the principal info.
324 void SetPrincipalInfo(UniquePtr
<mozilla::ipc::PrincipalInfo
> aPrincipalInfo
);
326 LoadTainting
GetTainting() const;
328 already_AddRefed
<InternalResponse
> Unfiltered();
333 explicit InternalResponse(const InternalResponse
& aOther
) = delete;
334 InternalResponse
& operator=(const InternalResponse
&) = delete;
336 // Returns an instance of InternalResponse which is a copy of this
337 // InternalResponse, except headers, body and wrapped response (if any) which
338 // are left uninitialized. Used for cloning and filtering.
339 already_AddRefed
<InternalResponse
> CreateIncompleteCopy();
342 // A response has an associated url list (a list of zero or more fetch URLs).
343 // Unless stated otherwise, it is the empty list. The current url is the last
344 // element in mURLlist
345 nsTArray
<nsCString
> mURLList
;
346 const uint16_t mStatus
;
347 const nsCString mStatusText
;
348 RefPtr
<InternalHeaders
> mHeaders
;
349 nsCOMPtr
<nsIInputStream
> mBody
;
350 nsCString mBodyBlobURISpec
;
351 nsString mBodyLocalPath
;
353 // It's used to passed to the CacheResponse to generate padding size. Once, we
354 // generate the padding size for resposne, we don't need it anymore.
355 Maybe
<uint32_t> mPaddingInfo
;
356 int64_t mPaddingSize
;
358 RequestCredentials mCredentialsMode
;
360 // For alternative data such as JS Bytecode cached in the HTTP cache.
361 nsCString mAlternativeDataType
;
362 nsCOMPtr
<nsIInputStream
> mAlternativeBody
;
363 nsMainThreadPtrHandle
<nsICacheInfoChannel
> mCacheInfoChannel
;
366 static const int64_t UNKNOWN_BODY_SIZE
= -1;
367 static const int64_t UNKNOWN_PADDING_SIZE
= -1;
370 ChannelInfo mChannelInfo
;
371 UniquePtr
<mozilla::ipc::PrincipalInfo
> mPrincipalInfo
;
373 // For filtered responses.
374 // Cache, and SW interception should always serialize/access the underlying
375 // unfiltered headers and when deserializing, create an InternalResponse
376 // with the unfiltered headers followed by wrapping it.
377 RefPtr
<InternalResponse
> mWrappedResponse
;
381 } // namespace mozilla
383 #endif // mozilla_dom_InternalResponse_h