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_InternalRequest_h
8 #define mozilla_dom_InternalRequest_h
10 #include "mozilla/dom/HeadersBinding.h"
11 #include "mozilla/dom/InternalHeaders.h"
12 #include "mozilla/dom/RequestBinding.h"
13 #include "mozilla/dom/SafeRefPtr.h"
14 #include "mozilla/LoadTainting.h"
15 #include "mozilla/UniquePtr.h"
17 #include "nsIChannelEventSink.h"
18 #include "nsIInputStream.h"
19 #include "nsISupportsImpl.h"
20 #include "mozilla/net/NeckoChannelParams.h"
22 # include "nsIURLParser.h"
23 # include "nsNetCID.h"
24 # include "nsServiceManagerUtils.h"
27 using mozilla::net::RedirectHistoryEntryInfo
;
32 class PBackgroundChild
;
39 * The mapping of RequestDestination and nsContentPolicyType is currently as the
42 * RequestDestination| nsContentPolicyType
43 * ------------------+--------------------
44 * "audio" | TYPE_INTERNAL_AUDIO
45 * "audioworklet" | TYPE_INTERNAL_AUDIOWORKLET
46 * "document" | TYPE_DOCUMENT
47 * "embed" | TYPE_INTERNAL_EMBED
48 * "font" | TYPE_FONT, TYPE_INTERNAL_FONT_PRELOAD
49 * "frame" | TYPE_INTERNAL_FRAME
50 * "iframe" | TYPE_SUBDOCUMENT, TYPE_INTERNAL_IFRAME
51 * "image" | TYPE_INTERNAL_IMAGE, TYPE_INTERNAL_IMAGE_PRELOAD,
52 * | TYPE_IMAGE, TYPE_INTERNAL_IMAGE_FAVICON, TYPE_IMAGESET
53 * "manifest" | TYPE_WEB_MANIFEST
54 * "object" | TYPE_INTERNAL_OBJECT, TYPE_OBJECT
55 * "paintworklet" | TYPE_INTERNAL_PAINTWORKLET
56 * "report" | TYPE_CSP_REPORT
57 * "script" | TYPE_INTERNAL_SCRIPT, TYPE_INTERNAL_SCRIPT_PRELOAD,
58 * | TYPE_INTERNAL_MODULE, TYPE_INTERNAL_MODULE_PRELOAD,
60 * | TYPE_INTERNAL_SERVICE_WORKER,
61 * | TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS,
62 * | TYPE_INTERNAL_CHROMEUTILS_COMPILED_SCRIPT
63 * | TYPE_INTERNAL_FRAME_MESSAGEMANAGER_SCRIPT
64 * "sharedworker" | TYPE_INTERNAL_SHARED_WORKER
65 * "serviceworker" | The spec lists this as a valid value for the enum,
66 * | however it is impossible to observe a request with this
67 * | destination value.
68 * "style" | TYPE_INTERNAL_STYLESHEET,
69 * | TYPE_INTERNAL_STYLESHEET_PRELOAD,
71 * "track" | TYPE_INTERNAL_TRACK
72 * "video" | TYPE_INTERNAL_VIDEO
73 * "worker" | TYPE_INTERNAL_WORKER, TYPE_INTERNAL_WORKER_STATIC_MODULE
75 * "" | Default for everything else.
79 class IPCInternalRequest
;
82 #define kFETCH_CLIENT_REFERRER_STR "about:client"
83 class InternalRequest final
: public AtomicSafeRefCounted
<InternalRequest
> {
87 MOZ_DECLARE_REFCOUNTED_TYPENAME(InternalRequest
)
88 InternalRequest(const nsACString
& aURL
, const nsACString
& aFragment
);
89 InternalRequest(const nsACString
& aURL
, const nsACString
& aFragment
,
90 const nsACString
& aMethod
,
91 already_AddRefed
<InternalHeaders
> aHeaders
,
92 RequestCache aCacheMode
, RequestMode aMode
,
93 RequestRedirect aRequestRedirect
,
94 RequestCredentials aRequestCredentials
,
95 const nsACString
& aReferrer
, ReferrerPolicy aReferrerPolicy
,
96 RequestPriority aPriority
,
97 nsContentPolicyType aContentPolicyType
,
98 const nsAString
& aIntegrity
);
100 explicit InternalRequest(const IPCInternalRequest
& aIPCRequest
);
102 void ToIPCInternalRequest(IPCInternalRequest
* aIPCRequest
,
103 mozilla::ipc::PBackgroundChild
* aManager
);
105 SafeRefPtr
<InternalRequest
> Clone();
107 void GetMethod(nsCString
& aMethod
) const { aMethod
.Assign(mMethod
); }
109 void SetMethod(const nsACString
& aMethod
) { mMethod
.Assign(aMethod
); }
111 bool HasSimpleMethod() const {
112 return mMethod
.LowerCaseEqualsASCII("get") ||
113 mMethod
.LowerCaseEqualsASCII("post") ||
114 mMethod
.LowerCaseEqualsASCII("head");
116 // GetURL should get the request's current url with fragment. A request has
117 // an associated current url. It is a pointer to the last fetch URL in
118 // request's url list.
119 void GetURL(nsACString
& aURL
) const {
120 aURL
.Assign(GetURLWithoutFragment());
121 if (GetFragment().IsEmpty()) {
124 aURL
.AppendLiteral("#");
125 aURL
.Append(GetFragment());
128 const nsCString
& GetURLWithoutFragment() const {
129 MOZ_RELEASE_ASSERT(!mURLList
.IsEmpty(),
130 "Internal Request's urlList should not be empty.");
132 return mURLList
.LastElement();
135 // A safe guard for ensuring that request's URL is only allowed to be set in a
136 // sw internal redirect.
137 void SetURLForInternalRedirect(const uint32_t aFlag
, const nsACString
& aURL
,
138 const nsACString
& aFragment
) {
139 // Only check in debug build to prevent it from being used unexpectedly.
140 MOZ_ASSERT(aFlag
& nsIChannelEventSink::REDIRECT_INTERNAL
);
142 return SetURL(aURL
, aFragment
);
145 // AddURL should append the url into url list.
146 // Normally we strip the fragment from the URL in Request::Constructor and
147 // pass the fragment as the second argument into it.
148 // If a fragment is present in the URL it must be stripped and passed in
150 void AddURL(const nsACString
& aURL
, const nsACString
& aFragment
) {
151 MOZ_ASSERT(!aURL
.IsEmpty());
152 MOZ_ASSERT(!aURL
.Contains('#'));
154 mURLList
.AppendElement(aURL
);
156 mFragment
.Assign(aFragment
);
158 // Get the URL list without their fragments.
159 void GetURLListWithoutFragment(nsTArray
<nsCString
>& aURLList
) {
160 aURLList
.Assign(mURLList
);
162 void GetReferrer(nsACString
& aReferrer
) const { aReferrer
.Assign(mReferrer
); }
164 void SetReferrer(const nsACString
& aReferrer
) {
166 bool validReferrer
= false;
167 if (aReferrer
.IsEmpty() ||
168 aReferrer
.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR
)) {
169 validReferrer
= true;
171 nsCOMPtr
<nsIURLParser
> parser
= do_GetService(NS_STDURLPARSER_CONTRACTID
);
173 NS_WARNING("Could not get parser to validate URL!");
177 uint32_t authorityPos
;
178 int32_t authorityLen
;
182 nsresult rv
= parser
->ParseURL(
183 aReferrer
.BeginReading(), aReferrer
.Length(), &schemePos
,
184 &schemeLen
, &authorityPos
, &authorityLen
, &pathPos
, &pathLen
);
186 NS_WARNING("Invalid referrer URL!");
187 } else if (schemeLen
< 0 || authorityLen
< 0) {
188 NS_WARNING("Invalid referrer URL!");
190 validReferrer
= true;
195 MOZ_ASSERT(validReferrer
);
198 mReferrer
.Assign(aReferrer
);
201 ReferrerPolicy
ReferrerPolicy_() const { return mReferrerPolicy
; }
203 void SetReferrerPolicy(ReferrerPolicy aReferrerPolicy
) {
204 mReferrerPolicy
= aReferrerPolicy
;
207 ReferrerPolicy
GetEnvironmentReferrerPolicy() const {
208 return mEnvironmentReferrerPolicy
;
211 void SetEnvironmentReferrerPolicy(ReferrerPolicy aReferrerPolicy
) {
212 mEnvironmentReferrerPolicy
= aReferrerPolicy
;
215 bool SkipServiceWorker() const { return mSkipServiceWorker
; }
217 void SetSkipServiceWorker() { mSkipServiceWorker
= true; }
219 bool SkipWasmCaching() const { return mSkipWasmCaching
; }
221 void SetSkipWasmCaching() { mSkipWasmCaching
= true; }
223 bool IsSynchronous() const { return mSynchronous
; }
225 RequestMode
Mode() const { return mMode
; }
227 void SetMode(RequestMode aMode
) { mMode
= aMode
; }
229 RequestCredentials
GetCredentialsMode() const { return mCredentialsMode
; }
231 void SetCredentialsMode(RequestCredentials aCredentialsMode
) {
232 mCredentialsMode
= aCredentialsMode
;
235 LoadTainting
GetResponseTainting() const { return mResponseTainting
; }
237 void MaybeIncreaseResponseTainting(LoadTainting aTainting
) {
238 if (aTainting
> mResponseTainting
) {
239 mResponseTainting
= aTainting
;
243 RequestCache
GetCacheMode() const { return mCacheMode
; }
245 void SetCacheMode(RequestCache aCacheMode
) { mCacheMode
= aCacheMode
; }
247 RequestRedirect
GetRedirectMode() const { return mRedirectMode
; }
249 void SetRedirectMode(RequestRedirect aRedirectMode
) {
250 mRedirectMode
= aRedirectMode
;
253 RequestPriority
GetPriorityMode() const { return mPriorityMode
; }
255 void SetPriorityMode(RequestPriority aPriorityMode
) {
256 mPriorityMode
= aPriorityMode
;
259 const nsString
& GetIntegrity() const { return mIntegrity
; }
261 void SetIntegrity(const nsAString
& aIntegrity
) {
262 mIntegrity
.Assign(aIntegrity
);
265 bool GetKeepalive() const { return mKeepalive
; }
267 void SetKeepalive(const bool aKeepalive
) { mKeepalive
= aKeepalive
; }
269 bool MozErrors() const { return mMozErrors
; }
271 void SetMozErrors() { mMozErrors
= true; }
273 const nsCString
& GetFragment() const { return mFragment
; }
275 nsContentPolicyType
ContentPolicyType() const { return mContentPolicyType
; }
276 void SetContentPolicyType(nsContentPolicyType aContentPolicyType
);
278 void OverrideContentPolicyType(nsContentPolicyType aContentPolicyType
);
280 RequestDestination
Destination() const {
281 return MapContentPolicyTypeToRequestDestination(mContentPolicyType
);
284 bool UnsafeRequest() const { return mUnsafeRequest
; }
286 void SetUnsafeRequest() { mUnsafeRequest
= true; }
288 InternalHeaders
* Headers() const { return mHeaders
; }
290 void SetHeaders(InternalHeaders
* aHeaders
) {
291 MOZ_ASSERT(aHeaders
);
295 void SetBody(nsIInputStream
* aStream
, int64_t aBodyLength
) {
296 // A request's body may not be reset once set.
297 MOZ_ASSERT_IF(aStream
, !mBodyStream
);
298 mBodyStream
= aStream
;
299 mBodyLength
= aBodyLength
;
302 // Will return the original stream!
303 // Use a tee or copy if you don't want to erase the original.
304 void GetBody(nsIInputStream
** aStream
, int64_t* aBodyLength
= nullptr) const {
305 nsCOMPtr
<nsIInputStream
> s
= mBodyStream
;
309 *aBodyLength
= mBodyLength
;
313 void SetBodyBlobURISpec(nsACString
& aBlobURISpec
) {
314 mBodyBlobURISpec
= aBlobURISpec
;
317 const nsACString
& BodyBlobURISpec() const { return mBodyBlobURISpec
; }
319 void SetBodyLocalPath(nsAString
& aLocalPath
) { mBodyLocalPath
= aLocalPath
; }
321 const nsAString
& BodyLocalPath() const { return mBodyLocalPath
; }
323 // The global is used as the client for the new object.
324 SafeRefPtr
<InternalRequest
> GetRequestConstructorCopy(
325 nsIGlobalObject
* aGlobal
, ErrorResult
& aRv
) const;
327 bool IsNavigationRequest() const;
329 bool IsWorkerRequest() const;
331 bool IsClientRequest() const;
333 void MaybeSkipCacheIfPerformingRevalidation();
335 bool IsContentPolicyTypeOverridden() const {
336 return mContentPolicyTypeOverridden
;
339 static RequestMode
MapChannelToRequestMode(nsIChannel
* aChannel
);
341 static RequestCredentials
MapChannelToRequestCredentials(
342 nsIChannel
* aChannel
);
344 // Takes ownership of the principal info.
345 void SetPrincipalInfo(UniquePtr
<mozilla::ipc::PrincipalInfo
> aPrincipalInfo
);
346 const UniquePtr
<mozilla::ipc::PrincipalInfo
>& GetPrincipalInfo() const {
347 return mPrincipalInfo
;
350 const nsCString
& GetPreferredAlternativeDataType() const {
351 return mPreferredAlternativeDataType
;
354 void SetPreferredAlternativeDataType(const nsACString
& aDataType
) {
355 mPreferredAlternativeDataType
= aDataType
;
360 InternalRequest(const InternalRequest
& aOther
) = delete;
362 void SetEmbedderPolicy(nsILoadInfo::CrossOriginEmbedderPolicy aPolicy
) {
363 mEmbedderPolicy
= aPolicy
;
366 nsILoadInfo::CrossOriginEmbedderPolicy
GetEmbedderPolicy() const {
367 return mEmbedderPolicy
;
370 void SetInterceptionTriggeringPrincipalInfo(
371 UniquePtr
<mozilla::ipc::PrincipalInfo
> aPrincipalInfo
);
373 const UniquePtr
<mozilla::ipc::PrincipalInfo
>&
374 GetInterceptionTriggeringPrincipalInfo() const {
375 return mInterceptionTriggeringPrincipalInfo
;
378 nsContentPolicyType
InterceptionContentPolicyType() const {
379 return mInterceptionContentPolicyType
;
381 void SetInterceptionContentPolicyType(nsContentPolicyType aContentPolicyType
);
383 const nsTArray
<RedirectHistoryEntryInfo
>& InterceptionRedirectChain() const {
384 return mInterceptionRedirectChain
;
387 void SetInterceptionRedirectChain(
388 const nsTArray
<RedirectHistoryEntryInfo
>& aRedirectChain
) {
389 mInterceptionRedirectChain
= aRedirectChain
;
392 const bool& InterceptionFromThirdParty() const {
393 return mInterceptionFromThirdParty
;
396 void SetInterceptionFromThirdParty(bool aFromThirdParty
) {
397 mInterceptionFromThirdParty
= aFromThirdParty
;
401 struct ConstructorGuard
{};
404 // Does not copy mBodyStream. Use fallible Clone() for complete copy.
405 InternalRequest(const InternalRequest
& aOther
, ConstructorGuard
);
408 // Map the content policy type to the associated fetch destination, as defined
409 // by the spec at https://fetch.spec.whatwg.org/#concept-request-destination.
410 // Note that while the HTML spec for the "Link" element and its "as" attribute
411 // (https://html.spec.whatwg.org/#attr-link-as) reuse fetch's definition of
413 static RequestDestination
MapContentPolicyTypeToRequestDestination(
414 nsContentPolicyType aContentPolicyType
);
416 static bool IsNavigationContentPolicy(nsContentPolicyType aContentPolicyType
);
418 static bool IsWorkerContentPolicy(nsContentPolicyType aContentPolicyType
);
420 // It should only be called while there is a service-worker-internal-redirect.
421 void SetURL(const nsACString
& aURL
, const nsACString
& aFragment
) {
422 MOZ_ASSERT(!aURL
.IsEmpty());
423 MOZ_ASSERT(!aURL
.Contains('#'));
424 MOZ_ASSERT(mURLList
.Length() > 0);
426 mURLList
.LastElement() = aURL
;
427 mFragment
.Assign(aFragment
);
431 // mURLList: a list of one or more fetch URLs
432 nsTArray
<nsCString
> mURLList
;
433 RefPtr
<InternalHeaders
> mHeaders
;
434 nsCString mBodyBlobURISpec
;
435 nsString mBodyLocalPath
;
436 nsCOMPtr
<nsIInputStream
> mBodyStream
;
439 nsCString mPreferredAlternativeDataType
;
441 nsContentPolicyType mContentPolicyType
;
443 // Empty string: no-referrer
444 // "about:client": client (default)
447 ReferrerPolicy mReferrerPolicy
;
449 // This will be used for request created from Window or Worker contexts
450 // In case there's no Referrer Policy in Request, this will be passed to
452 ReferrerPolicy mEnvironmentReferrerPolicy
;
454 RequestCredentials mCredentialsMode
;
455 LoadTainting mResponseTainting
= LoadTainting::Basic
;
456 RequestCache mCacheMode
;
457 RequestRedirect mRedirectMode
;
458 RequestPriority mPriorityMode
= RequestPriority::Auto
;
460 bool mKeepalive
= false;
461 bool mMozErrors
= false;
463 bool mSkipServiceWorker
= false;
464 bool mSkipWasmCaching
= false;
465 bool mSynchronous
= false;
466 bool mUnsafeRequest
= false;
467 bool mUseURLCredentials
= false;
468 // This is only set when Request.overrideContentPolicyType() has been set.
469 // It is illegal to pass such a Request object to a fetch() method unless
470 // if the caller has chrome privileges.
471 bool mContentPolicyTypeOverridden
= false;
472 nsILoadInfo::CrossOriginEmbedderPolicy mEmbedderPolicy
=
473 nsILoadInfo::EMBEDDER_POLICY_NULL
;
475 UniquePtr
<mozilla::ipc::PrincipalInfo
> mPrincipalInfo
;
477 // Following members are specific for the FetchEvent.request or
478 // NavigationPreload request which is extracted from the
479 // InterceptedHttpChannel.
480 // Notice that these members would not be copied when calling
481 // InternalRequest::GetRequestConstructorCopy() since these information should
482 // not be propagated when copying the Request in ServiceWorker script.
484 // This is the trigging principalInfo of the InterceptedHttpChannel.
485 UniquePtr
<mozilla::ipc::PrincipalInfo
> mInterceptionTriggeringPrincipalInfo
;
487 // This is the contentPolicyType of the InterceptedHttpChannel.
488 nsContentPolicyType mInterceptionContentPolicyType
{
489 nsIContentPolicy::TYPE_INVALID
};
491 // This is the redirect history of the InterceptedHttpChannel.
492 CopyableTArray
<RedirectHistoryEntryInfo
> mInterceptionRedirectChain
;
494 // This indicates that the InterceptedHttpChannel is a third party channel.
495 bool mInterceptionFromThirdParty
{false};
499 } // namespace mozilla
501 #endif // mozilla_dom_InternalRequest_h