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.");
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
47 : nsIContentPolicy::TYPE_FETCH
;
49 copy
->mCredentialsMode
= mCredentialsMode
;
50 copy
->mCacheMode
= mCacheMode
;
51 copy
->mRedirectMode
= mRedirectMode
;
52 copy
->mContentPolicyTypeOverridden
= mContentPolicyTypeOverridden
;
54 copy
->mPreferredAlternativeDataType
= mPreferredAlternativeDataType
;
58 SafeRefPtr
<InternalRequest
> InternalRequest::Clone() {
59 auto clone
= MakeSafeRefPtr
<InternalRequest
>(*this, ConstructorGuard
{});
65 nsCOMPtr
<nsIInputStream
> clonedBody
;
66 nsCOMPtr
<nsIInputStream
> replacementBody
;
68 nsresult rv
= NS_CloneInputStream(mBodyStream
, getter_AddRefs(clonedBody
),
69 getter_AddRefs(replacementBody
));
70 if (NS_WARN_IF(NS_FAILED(rv
))) {
74 clone
->mBodyStream
.swap(clonedBody
);
75 if (replacementBody
) {
76 mBodyStream
.swap(replacementBody
);
80 InternalRequest::InternalRequest(const nsACString
& aURL
,
81 const nsACString
& aFragment
)
83 mHeaders(new InternalHeaders(HeadersGuardEnum::None
)),
84 mBodyLength(InternalResponse::UNKNOWN_BODY_SIZE
),
85 mContentPolicyType(nsIContentPolicy::TYPE_FETCH
),
86 mReferrer(NS_LITERAL_STRING_FROM_CSTRING(kFETCH_CLIENT_REFERRER_STR
)),
87 mReferrerPolicy(ReferrerPolicy::_empty
),
88 mEnvironmentReferrerPolicy(ReferrerPolicy::_empty
),
89 mMode(RequestMode::No_cors
),
90 mCredentialsMode(RequestCredentials::Omit
),
91 mCacheMode(RequestCache::Default
),
92 mRedirectMode(RequestRedirect::Follow
) {
93 MOZ_ASSERT(!aURL
.IsEmpty());
94 AddURL(aURL
, aFragment
);
96 InternalRequest::InternalRequest(
97 const nsACString
& aURL
, const nsACString
& aFragment
,
98 const nsACString
& aMethod
, already_AddRefed
<InternalHeaders
> aHeaders
,
99 RequestCache aCacheMode
, RequestMode aMode
,
100 RequestRedirect aRequestRedirect
, RequestCredentials aRequestCredentials
,
101 const nsAString
& aReferrer
, ReferrerPolicy aReferrerPolicy
,
102 nsContentPolicyType aContentPolicyType
, const nsAString
& aIntegrity
)
105 mBodyLength(InternalResponse::UNKNOWN_BODY_SIZE
),
106 mContentPolicyType(aContentPolicyType
),
107 mReferrer(aReferrer
),
108 mReferrerPolicy(aReferrerPolicy
),
109 mEnvironmentReferrerPolicy(ReferrerPolicy::_empty
),
111 mCredentialsMode(aRequestCredentials
),
112 mCacheMode(aCacheMode
),
113 mRedirectMode(aRequestRedirect
),
114 mIntegrity(aIntegrity
) {
115 MOZ_ASSERT(!aURL
.IsEmpty());
116 AddURL(aURL
, aFragment
);
118 InternalRequest::InternalRequest(const InternalRequest
& aOther
,
120 : mMethod(aOther
.mMethod
),
121 mURLList(aOther
.mURLList
.Clone()),
122 mHeaders(new InternalHeaders(*aOther
.mHeaders
)),
123 mBodyLength(InternalResponse::UNKNOWN_BODY_SIZE
),
124 mContentPolicyType(aOther
.mContentPolicyType
),
125 mReferrer(aOther
.mReferrer
),
126 mReferrerPolicy(aOther
.mReferrerPolicy
),
127 mEnvironmentReferrerPolicy(aOther
.mEnvironmentReferrerPolicy
),
129 mCredentialsMode(aOther
.mCredentialsMode
),
130 mResponseTainting(aOther
.mResponseTainting
),
131 mCacheMode(aOther
.mCacheMode
),
132 mRedirectMode(aOther
.mRedirectMode
),
133 mIntegrity(aOther
.mIntegrity
),
134 mMozErrors(aOther
.mMozErrors
),
135 mFragment(aOther
.mFragment
),
136 mSkipServiceWorker(aOther
.mSkipServiceWorker
),
137 mSynchronous(aOther
.mSynchronous
),
138 mUnsafeRequest(aOther
.mUnsafeRequest
),
139 mUseURLCredentials(aOther
.mUseURLCredentials
),
140 mContentPolicyTypeOverridden(aOther
.mContentPolicyTypeOverridden
) {
141 // NOTE: does not copy body stream... use the fallible Clone() for that
144 InternalRequest::InternalRequest(const IPCInternalRequest
& aIPCRequest
)
145 : mMethod(aIPCRequest
.method()),
146 mURLList(aIPCRequest
.urlList().Clone()),
147 mHeaders(new InternalHeaders(aIPCRequest
.headers(),
148 aIPCRequest
.headersGuard())),
149 mBodyLength(aIPCRequest
.bodySize()),
150 mPreferredAlternativeDataType(aIPCRequest
.preferredAlternativeDataType()),
152 static_cast<nsContentPolicyType
>(aIPCRequest
.contentPolicyType())),
153 mReferrer(aIPCRequest
.referrer()),
154 mReferrerPolicy(aIPCRequest
.referrerPolicy()),
155 mMode(aIPCRequest
.requestMode()),
156 mCredentialsMode(aIPCRequest
.requestCredentials()),
157 mCacheMode(aIPCRequest
.cacheMode()),
158 mRedirectMode(aIPCRequest
.requestRedirect()),
159 mIntegrity(aIPCRequest
.integrity()),
160 mFragment(aIPCRequest
.fragment()) {
161 if (aIPCRequest
.principalInfo()) {
162 mPrincipalInfo
= MakeUnique
<mozilla::ipc::PrincipalInfo
>(
163 aIPCRequest
.principalInfo().ref());
166 const Maybe
<BodyStreamVariant
>& body
= aIPCRequest
.body();
168 // This constructor is (currently) only used for parent -> child communication
169 // (constructed on the child side).
171 MOZ_ASSERT(body
->type() == BodyStreamVariant::TParentToChildStream
);
172 mBodyStream
= static_cast<RemoteLazyInputStreamChild
*>(
173 body
->get_ParentToChildStream().actorChild())
178 InternalRequest::~InternalRequest() = default;
180 void InternalRequest::SetContentPolicyType(
181 nsContentPolicyType aContentPolicyType
) {
182 mContentPolicyType
= aContentPolicyType
;
185 void InternalRequest::OverrideContentPolicyType(
186 nsContentPolicyType aContentPolicyType
) {
187 SetContentPolicyType(aContentPolicyType
);
188 mContentPolicyTypeOverridden
= true;
192 RequestDestination
InternalRequest::MapContentPolicyTypeToRequestDestination(
193 nsContentPolicyType aContentPolicyType
) {
194 switch (aContentPolicyType
) {
195 case nsIContentPolicy::TYPE_OTHER
:
196 return RequestDestination::_empty
;
197 case nsIContentPolicy::TYPE_INTERNAL_SCRIPT
:
198 case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD
:
199 case nsIContentPolicy::TYPE_INTERNAL_MODULE
:
200 case nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD
:
201 case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER
:
202 case nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS
:
203 case nsIContentPolicy::TYPE_INTERNAL_CHROMEUTILS_COMPILED_SCRIPT
:
204 case nsIContentPolicy::TYPE_INTERNAL_FRAME_MESSAGEMANAGER_SCRIPT
:
205 case nsIContentPolicy::TYPE_SCRIPT
:
206 return RequestDestination::Script
;
207 case nsIContentPolicy::TYPE_INTERNAL_WORKER
:
208 return RequestDestination::Worker
;
209 case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER
:
210 return RequestDestination::Sharedworker
;
211 case nsIContentPolicy::TYPE_IMAGESET
:
212 case nsIContentPolicy::TYPE_INTERNAL_IMAGE
:
213 case nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD
:
214 case nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON
:
215 case nsIContentPolicy::TYPE_IMAGE
:
216 return RequestDestination::Image
;
217 case nsIContentPolicy::TYPE_STYLESHEET
:
218 case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET
:
219 case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD
:
220 return RequestDestination::Style
;
221 case nsIContentPolicy::TYPE_OBJECT
:
222 case nsIContentPolicy::TYPE_INTERNAL_OBJECT
:
223 return RequestDestination::Object
;
224 case nsIContentPolicy::TYPE_INTERNAL_EMBED
:
225 return RequestDestination::Embed
;
226 case nsIContentPolicy::TYPE_DOCUMENT
:
227 return RequestDestination::Document
;
228 case nsIContentPolicy::TYPE_SUBDOCUMENT
:
229 case nsIContentPolicy::TYPE_INTERNAL_IFRAME
:
230 return RequestDestination::Iframe
;
231 case nsIContentPolicy::TYPE_INTERNAL_FRAME
:
232 return RequestDestination::Frame
;
233 case nsIContentPolicy::TYPE_PING
:
234 return RequestDestination::_empty
;
235 case nsIContentPolicy::TYPE_XMLHTTPREQUEST
:
236 case nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST
:
237 return RequestDestination::_empty
;
238 case nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE
:
239 return RequestDestination::_empty
;
240 case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST
:
241 return RequestDestination::_empty
;
242 case nsIContentPolicy::TYPE_DTD
:
243 case nsIContentPolicy::TYPE_INTERNAL_DTD
:
244 case nsIContentPolicy::TYPE_INTERNAL_FORCE_ALLOWED_DTD
:
245 return RequestDestination::_empty
;
246 case nsIContentPolicy::TYPE_FONT
:
247 case nsIContentPolicy::TYPE_INTERNAL_FONT_PRELOAD
:
248 return RequestDestination::Font
;
249 case nsIContentPolicy::TYPE_MEDIA
:
250 return RequestDestination::_empty
;
251 case nsIContentPolicy::TYPE_INTERNAL_AUDIO
:
252 return RequestDestination::Audio
;
253 case nsIContentPolicy::TYPE_INTERNAL_VIDEO
:
254 return RequestDestination::Video
;
255 case nsIContentPolicy::TYPE_INTERNAL_TRACK
:
256 return RequestDestination::Track
;
257 case nsIContentPolicy::TYPE_WEBSOCKET
:
258 return RequestDestination::_empty
;
259 case nsIContentPolicy::TYPE_CSP_REPORT
:
260 return RequestDestination::Report
;
261 case nsIContentPolicy::TYPE_XSLT
:
262 return RequestDestination::Xslt
;
263 case nsIContentPolicy::TYPE_BEACON
:
264 return RequestDestination::_empty
;
265 case nsIContentPolicy::TYPE_FETCH
:
266 case nsIContentPolicy::TYPE_INTERNAL_FETCH_PRELOAD
:
267 return RequestDestination::_empty
;
268 case nsIContentPolicy::TYPE_WEB_MANIFEST
:
269 return RequestDestination::Manifest
;
270 case nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD
:
271 return RequestDestination::_empty
;
272 case nsIContentPolicy::TYPE_SPECULATIVE
:
273 return RequestDestination::_empty
;
274 case nsIContentPolicy::TYPE_INTERNAL_AUDIOWORKLET
:
275 return RequestDestination::Audioworklet
;
276 case nsIContentPolicy::TYPE_INTERNAL_PAINTWORKLET
:
277 return RequestDestination::Paintworklet
;
278 case nsIContentPolicy::TYPE_INVALID
:
280 // Do not add default: so that compilers can catch the missing case.
283 MOZ_ASSERT(false, "Unhandled nsContentPolicyType value");
284 return RequestDestination::_empty
;
288 bool InternalRequest::IsNavigationContentPolicy(
289 nsContentPolicyType aContentPolicyType
) {
290 // https://fetch.spec.whatwg.org/#navigation-request-context
292 // A navigation request context is one of "form", "frame", "hyperlink",
293 // "iframe", "internal" (as long as context frame type is not "none"),
294 // "location", "metarefresh", and "prerender".
296 // Note, all of these request types are effectively initiated by nsDocShell.
297 return aContentPolicyType
== nsIContentPolicy::TYPE_DOCUMENT
||
298 aContentPolicyType
== nsIContentPolicy::TYPE_SUBDOCUMENT
||
299 aContentPolicyType
== nsIContentPolicy::TYPE_INTERNAL_FRAME
||
300 aContentPolicyType
== nsIContentPolicy::TYPE_INTERNAL_IFRAME
;
304 bool InternalRequest::IsWorkerContentPolicy(
305 nsContentPolicyType aContentPolicyType
) {
306 // https://fetch.spec.whatwg.org/#worker-request-context
308 // A worker request context is one of "serviceworker", "sharedworker", and
311 // Note, service workers are not included here because currently there is
312 // no way to generate a Request with a "serviceworker" RequestDestination.
313 // ServiceWorker scripts cannot be intercepted.
314 return aContentPolicyType
== nsIContentPolicy::TYPE_INTERNAL_WORKER
||
315 aContentPolicyType
== nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER
;
318 bool InternalRequest::IsNavigationRequest() const {
319 return IsNavigationContentPolicy(mContentPolicyType
);
322 bool InternalRequest::IsWorkerRequest() const {
323 return IsWorkerContentPolicy(mContentPolicyType
);
326 bool InternalRequest::IsClientRequest() const {
327 return IsNavigationRequest() || IsWorkerRequest();
331 RequestMode
InternalRequest::MapChannelToRequestMode(nsIChannel
* aChannel
) {
332 MOZ_ASSERT(aChannel
);
334 nsCOMPtr
<nsILoadInfo
> loadInfo
= aChannel
->LoadInfo();
336 nsContentPolicyType contentPolicy
= loadInfo
->InternalContentPolicyType();
337 if (IsNavigationContentPolicy(contentPolicy
)) {
338 return RequestMode::Navigate
;
341 // TODO: remove the worker override once securityMode is fully implemented
343 if (IsWorkerContentPolicy(contentPolicy
)) {
344 return RequestMode::Same_origin
;
347 uint32_t securityMode
= loadInfo
->GetSecurityMode();
349 switch (securityMode
) {
350 case nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_INHERITS_SEC_CONTEXT
:
351 case nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED
:
352 return RequestMode::Same_origin
;
353 case nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT
:
354 case nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL
:
355 return RequestMode::No_cors
;
356 case nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT
:
357 // TODO: Check additional flag force-preflight after bug 1199693 (bug
359 return RequestMode::Cors
;
361 MOZ_ASSERT_UNREACHABLE("Unexpected security mode!");
362 return RequestMode::Same_origin
;
367 RequestCredentials
InternalRequest::MapChannelToRequestCredentials(
368 nsIChannel
* aChannel
) {
369 MOZ_ASSERT(aChannel
);
371 nsCOMPtr
<nsILoadInfo
> loadInfo
= aChannel
->LoadInfo();
373 uint32_t cookiePolicy
= loadInfo
->GetCookiePolicy();
375 if (cookiePolicy
== nsILoadInfo::SEC_COOKIES_INCLUDE
) {
376 return RequestCredentials::Include
;
377 } else if (cookiePolicy
== nsILoadInfo::SEC_COOKIES_OMIT
) {
378 return RequestCredentials::Omit
;
379 } else if (cookiePolicy
== nsILoadInfo::SEC_COOKIES_SAME_ORIGIN
) {
380 return RequestCredentials::Same_origin
;
383 MOZ_ASSERT_UNREACHABLE("Unexpected cookie policy!");
384 return RequestCredentials::Same_origin
;
387 void InternalRequest::MaybeSkipCacheIfPerformingRevalidation() {
388 if (mCacheMode
== RequestCache::Default
&&
389 mHeaders
->HasRevalidationHeaders()) {
390 mCacheMode
= RequestCache::No_store
;
394 void InternalRequest::SetPrincipalInfo(
395 UniquePtr
<mozilla::ipc::PrincipalInfo
> aPrincipalInfo
) {
396 mPrincipalInfo
= std::move(aPrincipalInfo
);
399 } // namespace mozilla::dom