Bug 1777562 [wpt PR 34663] - [FedCM] Rename FederatedCredential to IdentityCredential...
[gecko.git] / dom / fetch / InternalResponse.h
blob41530db49ba360e8fad434de3c91ed0201010606
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"
24 namespace mozilla {
25 namespace ipc {
26 class PBackgroundChild;
27 class PBackgroundParent;
28 class PrincipalInfo;
29 } // namespace ipc
31 namespace dom {
33 class ChildToParentInternalResponse;
34 class InternalHeaders;
35 class ParentToChildInternalResponse;
36 class ParentToParentInternalResponse;
38 class InternalResponse final : public AtomicSafeRefCounted<InternalResponse> {
39 friend class FetchDriver;
41 public:
42 MOZ_DECLARE_REFCOUNTED_TYPENAME(InternalResponse)
44 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();
60 enum CloneType {
61 eCloneInputStream,
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);
71 ErrorResult result;
72 response->Headers()->SetGuard(HeadersGuardEnum::Immutable, result);
73 MOZ_ASSERT(!result.Failed());
74 response->mType = ResponseType::Error;
75 response->mErrorCode = aRv;
76 return response;
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);
94 return mType;
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();
114 return 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);
127 return list;
130 void SetURLList(const nsTArray<nsCString>& aURLList) {
131 mURLList.Assign(aURLList);
133 #ifdef DEBUG
134 for (uint32_t i = 0; i < mURLList.Length(); ++i) {
135 MOZ_ASSERT(mURLList[i].Find("#"_ns) == kNotFound);
137 #endif
140 uint16_t GetStatus() const { return mStatus; }
142 uint16_t GetUnfilteredStatus() const {
143 if (mWrappedResponse) {
144 return mWrappedResponse->GetStatus();
147 return 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();
167 return Headers();
170 void GetUnfilteredBody(nsIInputStream** aStream,
171 int64_t* aBodySize = nullptr) {
172 if (mWrappedResponse) {
173 MOZ_ASSERT(!mBody);
174 return mWrappedResponse->GetBody(aStream, aBodySize);
176 nsCOMPtr<nsIInputStream> stream = mBody;
177 stream.forget(aStream);
178 if (aBodySize) {
179 *aBodySize = mBodySize;
183 void GetBody(nsIInputStream** aStream, int64_t* aBodySize = nullptr) {
184 if (Type() == ResponseType::Opaque ||
185 Type() == ResponseType::Opaqueredirect) {
186 *aStream = nullptr;
187 if (aBodySize) {
188 *aBodySize = UNKNOWN_BODY_SIZE;
190 return;
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.
221 MOZ_ASSERT(!mBody);
222 MOZ_ASSERT(mBodySize == UNKNOWN_BODY_SIZE);
223 // Check arguments.
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);
228 mBody = aBody;
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) {
274 return nullptr;
277 // cleanup the non-alternative body here.
278 // Once alternative data is used, the real body is no need anymore.
279 mBody = nullptr;
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;
299 return rtn;
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();
340 ~InternalResponse();
342 private:
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();
356 ResponseType mType;
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;
367 int64_t mBodySize;
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;
372 nsresult mErrorCode;
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;
379 bool mCloned;
381 public:
382 static constexpr int64_t UNKNOWN_BODY_SIZE = -1;
383 static constexpr int64_t UNKNOWN_PADDING_SIZE = -1;
385 private:
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);
400 } // namespace dom
401 } // namespace mozilla
403 #endif // mozilla_dom_InternalResponse_h