Bug 1698238 return default dictionary from GetUserMediaRequest#getConstraints() if...
[gecko.git] / dom / fetch / InternalResponse.h
blobf256d3ec5bcde0edd6237a5323a9331d9134497d
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"
21 namespace mozilla {
22 namespace ipc {
23 class AutoIPCStream;
24 class PBackgroundChild;
25 class PrincipalInfo;
26 } // namespace ipc
28 namespace dom {
30 class IPCInternalResponse;
31 class InternalHeaders;
33 class InternalResponse final {
34 friend class FetchDriver;
36 public:
37 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(InternalResponse)
39 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.
47 void ToIPC(
48 IPCInternalResponse* aIPCResponse,
49 mozilla::ipc::PBackgroundChild* aManager,
50 UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoBodyStream,
51 UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoAlternativeBodyStream);
53 enum CloneType {
54 eCloneInputStream,
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);
63 ErrorResult result;
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);
86 return mType;
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();
106 return 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);
119 return list;
122 void SetURLList(const nsTArray<nsCString>& aURLList) {
123 mURLList.Assign(aURLList);
125 #ifdef DEBUG
126 for (uint32_t i = 0; i < mURLList.Length(); ++i) {
127 MOZ_ASSERT(mURLList[i].Find("#"_ns) == kNotFound);
129 #endif
132 uint16_t GetStatus() const { return mStatus; }
134 uint16_t GetUnfilteredStatus() const {
135 if (mWrappedResponse) {
136 return mWrappedResponse->GetStatus();
139 return 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();
159 return Headers();
162 void GetUnfilteredBody(nsIInputStream** aStream,
163 int64_t* aBodySize = nullptr) {
164 if (mWrappedResponse) {
165 MOZ_ASSERT(!mBody);
166 return mWrappedResponse->GetBody(aStream, aBodySize);
168 nsCOMPtr<nsIInputStream> stream = mBody;
169 stream.forget(aStream);
170 if (aBodySize) {
171 *aBodySize = mBodySize;
175 void GetBody(nsIInputStream** aStream, int64_t* aBodySize = nullptr) {
176 if (Type() == ResponseType::Opaque ||
177 Type() == ResponseType::Opaqueredirect) {
178 *aStream = nullptr;
179 if (aBodySize) {
180 *aBodySize = UNKNOWN_BODY_SIZE;
182 return;
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.
213 MOZ_ASSERT(!mBody);
214 MOZ_ASSERT(mBodySize == UNKNOWN_BODY_SIZE);
215 // Check arguments.
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);
220 mBody = aBody;
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) {
266 return nullptr;
269 // cleanup the non-alternative body here.
270 // Once alternative data is used, the real body is no need anymore.
271 mBody = nullptr;
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;
291 return rtn;
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();
330 private:
331 ~InternalResponse();
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();
341 ResponseType mType;
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;
352 int64_t mBodySize;
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;
357 nsresult mErrorCode;
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;
365 public:
366 static const int64_t UNKNOWN_BODY_SIZE = -1;
367 static const int64_t UNKNOWN_PADDING_SIZE = -1;
369 private:
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;
380 } // namespace dom
381 } // namespace mozilla
383 #endif // mozilla_dom_InternalResponse_h