Bug 1890793: Assert CallArgs::newTarget is not gray. r=spidermonkey-reviewers,sfink...
[gecko.git] / dom / fetch / InternalRequest.cpp
blobd2086e58ebd171ae1f3aeb9950bb089fc68b9e7c
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 #include "InternalRequest.h"
9 #include "InternalResponse.h"
10 #include "mozilla/ErrorResult.h"
11 #include "mozilla/dom/Document.h"
12 #include "mozilla/dom/FetchTypes.h"
13 #include "mozilla/dom/ScriptSettings.h"
14 #include "mozilla/dom/WorkerCommon.h"
15 #include "mozilla/dom/WorkerPrivate.h"
16 #include "mozilla/ipc/IPCStreamUtils.h"
17 #include "mozilla/ipc/PBackgroundChild.h"
18 #include "mozilla/RemoteLazyInputStreamChild.h"
19 #include "nsIContentPolicy.h"
20 #include "nsStreamUtils.h"
22 namespace mozilla::dom {
23 // The global is used to extract the principal.
24 SafeRefPtr<InternalRequest> InternalRequest::GetRequestConstructorCopy(
25 nsIGlobalObject* aGlobal, ErrorResult& aRv) const {
26 MOZ_RELEASE_ASSERT(!mURLList.IsEmpty(),
27 "Internal Request's urlList should not be empty when "
28 "copied from constructor.");
29 auto copy =
30 MakeSafeRefPtr<InternalRequest>(mURLList.LastElement(), mFragment);
31 copy->SetMethod(mMethod);
32 copy->mHeaders = new InternalHeaders(*mHeaders);
33 copy->SetUnsafeRequest();
34 copy->mBodyStream = mBodyStream;
35 copy->mBodyLength = mBodyLength;
36 // The "client" is not stored in our implementation. Fetch API users should
37 // use the appropriate window/document/principal and other Gecko security
38 // mechanisms as appropriate.
39 copy->mReferrer = mReferrer;
40 copy->mReferrerPolicy = mReferrerPolicy;
41 copy->mEnvironmentReferrerPolicy = mEnvironmentReferrerPolicy;
42 copy->mIntegrity = mIntegrity;
43 copy->mMozErrors = mMozErrors;
45 copy->mContentPolicyType = mContentPolicyTypeOverridden
46 ? mContentPolicyType
47 : nsIContentPolicy::TYPE_FETCH;
48 copy->mMode = mMode;
49 copy->mCredentialsMode = mCredentialsMode;
50 copy->mCacheMode = mCacheMode;
51 copy->mRedirectMode = mRedirectMode;
52 copy->mPriorityMode = mPriorityMode;
53 copy->mContentPolicyTypeOverridden = mContentPolicyTypeOverridden;
55 copy->mPreferredAlternativeDataType = mPreferredAlternativeDataType;
56 copy->mSkipWasmCaching = mSkipWasmCaching;
57 copy->mEmbedderPolicy = mEmbedderPolicy;
58 return copy;
61 SafeRefPtr<InternalRequest> InternalRequest::Clone() {
62 auto clone = MakeSafeRefPtr<InternalRequest>(*this, ConstructorGuard{});
64 if (!mBodyStream) {
65 return clone;
68 nsCOMPtr<nsIInputStream> clonedBody;
69 nsCOMPtr<nsIInputStream> replacementBody;
71 nsresult rv = NS_CloneInputStream(mBodyStream, getter_AddRefs(clonedBody),
72 getter_AddRefs(replacementBody));
73 if (NS_WARN_IF(NS_FAILED(rv))) {
74 return nullptr;
77 clone->mBodyStream.swap(clonedBody);
78 if (replacementBody) {
79 mBodyStream.swap(replacementBody);
81 return clone;
83 InternalRequest::InternalRequest(const nsACString& aURL,
84 const nsACString& aFragment)
85 : mMethod("GET"),
86 mHeaders(new InternalHeaders(HeadersGuardEnum::None)),
87 mBodyLength(InternalResponse::UNKNOWN_BODY_SIZE),
88 mContentPolicyType(nsIContentPolicy::TYPE_FETCH),
89 mReferrer(nsLiteralCString(kFETCH_CLIENT_REFERRER_STR)),
90 mReferrerPolicy(ReferrerPolicy::_empty),
91 mEnvironmentReferrerPolicy(ReferrerPolicy::_empty),
92 mMode(RequestMode::No_cors),
93 mCredentialsMode(RequestCredentials::Omit),
94 mCacheMode(RequestCache::Default),
95 mRedirectMode(RequestRedirect::Follow),
96 mPriorityMode(RequestPriority::Auto) {
97 MOZ_ASSERT(!aURL.IsEmpty());
98 AddURL(aURL, aFragment);
100 InternalRequest::InternalRequest(
101 const nsACString& aURL, const nsACString& aFragment,
102 const nsACString& aMethod, already_AddRefed<InternalHeaders> aHeaders,
103 RequestCache aCacheMode, RequestMode aMode,
104 RequestRedirect aRequestRedirect, RequestCredentials aRequestCredentials,
105 const nsACString& aReferrer, ReferrerPolicy aReferrerPolicy,
106 RequestPriority aPriority, nsContentPolicyType aContentPolicyType,
107 const nsAString& aIntegrity)
108 : mMethod(aMethod),
109 mHeaders(aHeaders),
110 mBodyLength(InternalResponse::UNKNOWN_BODY_SIZE),
111 mContentPolicyType(aContentPolicyType),
112 mReferrer(aReferrer),
113 mReferrerPolicy(aReferrerPolicy),
114 mEnvironmentReferrerPolicy(ReferrerPolicy::_empty),
115 mMode(aMode),
116 mCredentialsMode(aRequestCredentials),
117 mCacheMode(aCacheMode),
118 mRedirectMode(aRequestRedirect),
119 mPriorityMode(aPriority),
120 mIntegrity(aIntegrity) {
121 MOZ_ASSERT(!aURL.IsEmpty());
122 AddURL(aURL, aFragment);
124 InternalRequest::InternalRequest(const InternalRequest& aOther,
125 ConstructorGuard)
126 : mMethod(aOther.mMethod),
127 mURLList(aOther.mURLList.Clone()),
128 mHeaders(new InternalHeaders(*aOther.mHeaders)),
129 mBodyLength(InternalResponse::UNKNOWN_BODY_SIZE),
130 mContentPolicyType(aOther.mContentPolicyType),
131 mReferrer(aOther.mReferrer),
132 mReferrerPolicy(aOther.mReferrerPolicy),
133 mEnvironmentReferrerPolicy(aOther.mEnvironmentReferrerPolicy),
134 mMode(aOther.mMode),
135 mCredentialsMode(aOther.mCredentialsMode),
136 mResponseTainting(aOther.mResponseTainting),
137 mCacheMode(aOther.mCacheMode),
138 mRedirectMode(aOther.mRedirectMode),
139 mPriorityMode(aOther.mPriorityMode),
140 mIntegrity(aOther.mIntegrity),
141 mMozErrors(aOther.mMozErrors),
142 mFragment(aOther.mFragment),
143 mSkipServiceWorker(aOther.mSkipServiceWorker),
144 mSkipWasmCaching(aOther.mSkipWasmCaching),
145 mSynchronous(aOther.mSynchronous),
146 mUnsafeRequest(aOther.mUnsafeRequest),
147 mUseURLCredentials(aOther.mUseURLCredentials),
148 mContentPolicyTypeOverridden(aOther.mContentPolicyTypeOverridden),
149 mEmbedderPolicy(aOther.mEmbedderPolicy),
150 mInterceptionContentPolicyType(aOther.mInterceptionContentPolicyType),
151 mInterceptionRedirectChain(aOther.mInterceptionRedirectChain),
152 mInterceptionFromThirdParty(aOther.mInterceptionFromThirdParty) {
153 // NOTE: does not copy body stream... use the fallible Clone() for that
155 if (aOther.GetInterceptionTriggeringPrincipalInfo()) {
156 mInterceptionTriggeringPrincipalInfo =
157 MakeUnique<mozilla::ipc::PrincipalInfo>(
158 *(aOther.GetInterceptionTriggeringPrincipalInfo().get()));
162 InternalRequest::InternalRequest(const IPCInternalRequest& aIPCRequest)
163 : mMethod(aIPCRequest.method()),
164 mURLList(aIPCRequest.urlList().Clone()),
165 mHeaders(new InternalHeaders(aIPCRequest.headers(),
166 aIPCRequest.headersGuard())),
167 mBodyLength(aIPCRequest.bodySize()),
168 mPreferredAlternativeDataType(aIPCRequest.preferredAlternativeDataType()),
169 mContentPolicyType(
170 static_cast<nsContentPolicyType>(aIPCRequest.contentPolicyType())),
171 mReferrer(aIPCRequest.referrer()),
172 mReferrerPolicy(aIPCRequest.referrerPolicy()),
173 mEnvironmentReferrerPolicy(aIPCRequest.environmentReferrerPolicy()),
174 mMode(aIPCRequest.requestMode()),
175 mCredentialsMode(aIPCRequest.requestCredentials()),
176 mCacheMode(aIPCRequest.cacheMode()),
177 mRedirectMode(aIPCRequest.requestRedirect()),
178 mIntegrity(aIPCRequest.integrity()),
179 mFragment(aIPCRequest.fragment()),
180 mEmbedderPolicy(aIPCRequest.embedderPolicy()),
181 mInterceptionContentPolicyType(static_cast<nsContentPolicyType>(
182 aIPCRequest.interceptionContentPolicyType())),
183 mInterceptionRedirectChain(aIPCRequest.interceptionRedirectChain()),
184 mInterceptionFromThirdParty(aIPCRequest.interceptionFromThirdParty()) {
185 if (aIPCRequest.principalInfo()) {
186 mPrincipalInfo = MakeUnique<mozilla::ipc::PrincipalInfo>(
187 aIPCRequest.principalInfo().ref());
190 if (aIPCRequest.interceptionTriggeringPrincipalInfo()) {
191 mInterceptionTriggeringPrincipalInfo =
192 MakeUnique<mozilla::ipc::PrincipalInfo>(
193 aIPCRequest.interceptionTriggeringPrincipalInfo().ref());
196 const Maybe<BodyStreamVariant>& body = aIPCRequest.body();
198 if (body) {
199 if (body->type() == BodyStreamVariant::TParentToChildStream) {
200 mBodyStream = body->get_ParentToChildStream().get_RemoteLazyInputStream();
202 if (body->type() == BodyStreamVariant::TChildToParentStream) {
203 mBodyStream =
204 DeserializeIPCStream(body->get_ChildToParentStream().stream());
209 void InternalRequest::ToIPCInternalRequest(
210 IPCInternalRequest* aIPCRequest, mozilla::ipc::PBackgroundChild* aManager) {
211 aIPCRequest->method() = mMethod;
212 for (const auto& url : mURLList) {
213 aIPCRequest->urlList().AppendElement(url);
215 mHeaders->ToIPC(aIPCRequest->headers(), aIPCRequest->headersGuard());
216 aIPCRequest->bodySize() = mBodyLength;
217 aIPCRequest->preferredAlternativeDataType() = mPreferredAlternativeDataType;
218 aIPCRequest->contentPolicyType() = mContentPolicyType;
219 aIPCRequest->referrer() = mReferrer;
220 aIPCRequest->referrerPolicy() = mReferrerPolicy;
221 aIPCRequest->environmentReferrerPolicy() = mEnvironmentReferrerPolicy;
222 aIPCRequest->requestMode() = mMode;
223 aIPCRequest->requestCredentials() = mCredentialsMode;
224 aIPCRequest->cacheMode() = mCacheMode;
225 aIPCRequest->requestRedirect() = mRedirectMode;
226 aIPCRequest->integrity() = mIntegrity;
227 aIPCRequest->fragment() = mFragment;
228 aIPCRequest->embedderPolicy() = mEmbedderPolicy;
230 if (mPrincipalInfo) {
231 aIPCRequest->principalInfo() = Some(*mPrincipalInfo);
234 if (mBodyStream) {
235 nsCOMPtr<nsIInputStream> body = mBodyStream;
236 aIPCRequest->body().emplace(ChildToParentStream());
237 DebugOnly<bool> ok = mozilla::ipc::SerializeIPCStream(
238 body.forget(), aIPCRequest->body()->get_ChildToParentStream().stream(),
239 /* aAllowLazy */ false);
240 MOZ_ASSERT(ok);
244 InternalRequest::~InternalRequest() = default;
246 void InternalRequest::SetContentPolicyType(
247 nsContentPolicyType aContentPolicyType) {
248 mContentPolicyType = aContentPolicyType;
251 void InternalRequest::OverrideContentPolicyType(
252 nsContentPolicyType aContentPolicyType) {
253 SetContentPolicyType(aContentPolicyType);
254 mContentPolicyTypeOverridden = true;
257 void InternalRequest::SetInterceptionContentPolicyType(
258 nsContentPolicyType aContentPolicyType) {
259 mInterceptionContentPolicyType = aContentPolicyType;
262 /* static */
263 RequestDestination InternalRequest::MapContentPolicyTypeToRequestDestination(
264 nsContentPolicyType aContentPolicyType) {
265 switch (aContentPolicyType) {
266 case nsIContentPolicy::TYPE_OTHER:
267 return RequestDestination::_empty;
268 case nsIContentPolicy::TYPE_INTERNAL_SCRIPT:
269 case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD:
270 case nsIContentPolicy::TYPE_INTERNAL_MODULE:
271 case nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD:
272 case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER:
273 case nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS:
274 case nsIContentPolicy::TYPE_INTERNAL_CHROMEUTILS_COMPILED_SCRIPT:
275 case nsIContentPolicy::TYPE_INTERNAL_FRAME_MESSAGEMANAGER_SCRIPT:
276 case nsIContentPolicy::TYPE_SCRIPT:
277 return RequestDestination::Script;
278 case nsIContentPolicy::TYPE_INTERNAL_WORKER:
279 case nsIContentPolicy::TYPE_INTERNAL_WORKER_STATIC_MODULE:
280 return RequestDestination::Worker;
281 case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER:
282 return RequestDestination::Sharedworker;
283 case nsIContentPolicy::TYPE_IMAGESET:
284 case nsIContentPolicy::TYPE_INTERNAL_IMAGE:
285 case nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD:
286 case nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON:
287 case nsIContentPolicy::TYPE_IMAGE:
288 return RequestDestination::Image;
289 case nsIContentPolicy::TYPE_STYLESHEET:
290 case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET:
291 case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD:
292 return RequestDestination::Style;
293 case nsIContentPolicy::TYPE_OBJECT:
294 case nsIContentPolicy::TYPE_INTERNAL_OBJECT:
295 return RequestDestination::Object;
296 case nsIContentPolicy::TYPE_INTERNAL_EMBED:
297 return RequestDestination::Embed;
298 case nsIContentPolicy::TYPE_DOCUMENT:
299 return RequestDestination::Document;
300 case nsIContentPolicy::TYPE_SUBDOCUMENT:
301 case nsIContentPolicy::TYPE_INTERNAL_IFRAME:
302 return RequestDestination::Iframe;
303 case nsIContentPolicy::TYPE_INTERNAL_FRAME:
304 return RequestDestination::Frame;
305 case nsIContentPolicy::TYPE_PING:
306 return RequestDestination::_empty;
307 case nsIContentPolicy::TYPE_XMLHTTPREQUEST:
308 case nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST:
309 return RequestDestination::_empty;
310 case nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE:
311 return RequestDestination::_empty;
312 case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST:
313 return RequestDestination::_empty;
314 case nsIContentPolicy::TYPE_DTD:
315 case nsIContentPolicy::TYPE_INTERNAL_DTD:
316 case nsIContentPolicy::TYPE_INTERNAL_FORCE_ALLOWED_DTD:
317 return RequestDestination::_empty;
318 case nsIContentPolicy::TYPE_FONT:
319 case nsIContentPolicy::TYPE_INTERNAL_FONT_PRELOAD:
320 case nsIContentPolicy::TYPE_UA_FONT:
321 return RequestDestination::Font;
322 case nsIContentPolicy::TYPE_MEDIA:
323 return RequestDestination::_empty;
324 case nsIContentPolicy::TYPE_INTERNAL_AUDIO:
325 return RequestDestination::Audio;
326 case nsIContentPolicy::TYPE_INTERNAL_VIDEO:
327 return RequestDestination::Video;
328 case nsIContentPolicy::TYPE_INTERNAL_TRACK:
329 return RequestDestination::Track;
330 case nsIContentPolicy::TYPE_WEBSOCKET:
331 return RequestDestination::_empty;
332 case nsIContentPolicy::TYPE_CSP_REPORT:
333 return RequestDestination::Report;
334 case nsIContentPolicy::TYPE_XSLT:
335 return RequestDestination::Xslt;
336 case nsIContentPolicy::TYPE_BEACON:
337 return RequestDestination::_empty;
338 case nsIContentPolicy::TYPE_FETCH:
339 case nsIContentPolicy::TYPE_INTERNAL_FETCH_PRELOAD:
340 return RequestDestination::_empty;
341 case nsIContentPolicy::TYPE_WEB_MANIFEST:
342 return RequestDestination::Manifest;
343 case nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD:
344 return RequestDestination::_empty;
345 case nsIContentPolicy::TYPE_SPECULATIVE:
346 return RequestDestination::_empty;
347 case nsIContentPolicy::TYPE_INTERNAL_AUDIOWORKLET:
348 return RequestDestination::Audioworklet;
349 case nsIContentPolicy::TYPE_INTERNAL_PAINTWORKLET:
350 return RequestDestination::Paintworklet;
351 case nsIContentPolicy::TYPE_PROXIED_WEBRTC_MEDIA:
352 return RequestDestination::_empty;
353 case nsIContentPolicy::TYPE_WEB_IDENTITY:
354 return RequestDestination::_empty;
355 case nsIContentPolicy::TYPE_WEB_TRANSPORT:
356 return RequestDestination::_empty;
357 case nsIContentPolicy::TYPE_INVALID:
358 case nsIContentPolicy::TYPE_END:
359 break;
360 // Do not add default: so that compilers can catch the missing case.
363 MOZ_ASSERT(false, "Unhandled nsContentPolicyType value");
364 return RequestDestination::_empty;
367 // static
368 bool InternalRequest::IsNavigationContentPolicy(
369 nsContentPolicyType aContentPolicyType) {
370 // https://fetch.spec.whatwg.org/#navigation-request-context
372 // A navigation request context is one of "form", "frame", "hyperlink",
373 // "iframe", "internal" (as long as context frame type is not "none"),
374 // "location", "metarefresh", and "prerender".
376 // Note, all of these request types are effectively initiated by nsDocShell.
377 return aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
378 aContentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT ||
379 aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME ||
380 aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME;
383 // static
384 bool InternalRequest::IsWorkerContentPolicy(
385 nsContentPolicyType aContentPolicyType) {
386 // https://fetch.spec.whatwg.org/#worker-request-context
388 // A worker request context is one of "serviceworker", "sharedworker", and
389 // "worker".
391 // Note, service workers are not included here because currently there is
392 // no way to generate a Request with a "serviceworker" RequestDestination.
393 // ServiceWorker scripts cannot be intercepted.
394 return aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
395 aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
398 bool InternalRequest::IsNavigationRequest() const {
399 return IsNavigationContentPolicy(mContentPolicyType);
402 bool InternalRequest::IsWorkerRequest() const {
403 return IsWorkerContentPolicy(mContentPolicyType);
406 bool InternalRequest::IsClientRequest() const {
407 return IsNavigationRequest() || IsWorkerRequest();
410 // static
411 RequestMode InternalRequest::MapChannelToRequestMode(nsIChannel* aChannel) {
412 MOZ_ASSERT(aChannel);
414 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
416 nsContentPolicyType contentPolicy = loadInfo->InternalContentPolicyType();
417 if (IsNavigationContentPolicy(contentPolicy)) {
418 return RequestMode::Navigate;
421 // TODO: remove the worker override once securityMode is fully implemented
422 // (bug 1189945)
423 if (IsWorkerContentPolicy(contentPolicy)) {
424 return RequestMode::Same_origin;
427 uint32_t securityMode = loadInfo->GetSecurityMode();
429 switch (securityMode) {
430 case nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_INHERITS_SEC_CONTEXT:
431 case nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED:
432 return RequestMode::Same_origin;
433 case nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT:
434 case nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL:
435 return RequestMode::No_cors;
436 case nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT:
437 // TODO: Check additional flag force-preflight after bug 1199693 (bug
438 // 1189945)
439 return RequestMode::Cors;
440 default:
441 MOZ_ASSERT_UNREACHABLE("Unexpected security mode!");
442 return RequestMode::Same_origin;
446 // static
447 RequestCredentials InternalRequest::MapChannelToRequestCredentials(
448 nsIChannel* aChannel) {
449 MOZ_ASSERT(aChannel);
451 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
453 uint32_t cookiePolicy = loadInfo->GetCookiePolicy();
455 if (cookiePolicy == nsILoadInfo::SEC_COOKIES_INCLUDE) {
456 return RequestCredentials::Include;
457 } else if (cookiePolicy == nsILoadInfo::SEC_COOKIES_OMIT) {
458 return RequestCredentials::Omit;
459 } else if (cookiePolicy == nsILoadInfo::SEC_COOKIES_SAME_ORIGIN) {
460 return RequestCredentials::Same_origin;
463 MOZ_ASSERT_UNREACHABLE("Unexpected cookie policy!");
464 return RequestCredentials::Same_origin;
467 void InternalRequest::MaybeSkipCacheIfPerformingRevalidation() {
468 if (mCacheMode == RequestCache::Default &&
469 mHeaders->HasRevalidationHeaders()) {
470 mCacheMode = RequestCache::No_store;
474 void InternalRequest::SetPrincipalInfo(
475 UniquePtr<mozilla::ipc::PrincipalInfo> aPrincipalInfo) {
476 mPrincipalInfo = std::move(aPrincipalInfo);
479 void InternalRequest::SetInterceptionTriggeringPrincipalInfo(
480 UniquePtr<mozilla::ipc::PrincipalInfo> aPrincipalInfo) {
481 mInterceptionTriggeringPrincipalInfo = std::move(aPrincipalInfo);
483 } // namespace mozilla::dom