InternalRequest.h (17523B)
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/. */ 6 7 #ifndef mozilla_dom_InternalRequest_h 8 #define mozilla_dom_InternalRequest_h 9 10 #include "mozilla/LoadTainting.h" 11 #include "mozilla/UniquePtr.h" 12 #include "mozilla/dom/HeadersBinding.h" 13 #include "mozilla/dom/InternalHeaders.h" 14 #include "mozilla/dom/InternalResponse.h" 15 #include "mozilla/dom/RequestBinding.h" 16 #include "mozilla/dom/SafeRefPtr.h" 17 #include "mozilla/net/NeckoChannelParams.h" 18 #include "nsIChannelEventSink.h" 19 #include "nsIInputStream.h" 20 #include "nsISupportsImpl.h" 21 #include "nsISupportsPriority.h" 22 #ifdef DEBUG 23 # include "nsIURLParser.h" 24 # include "nsNetCID.h" 25 # include "nsServiceManagerUtils.h" 26 #endif 27 28 using mozilla::net::RedirectHistoryEntryInfo; 29 30 namespace mozilla { 31 32 namespace ipc { 33 class PBackgroundChild; 34 class PrincipalInfo; 35 } // namespace ipc 36 37 namespace dom { 38 39 /* 40 * The mapping of RequestDestination and nsContentPolicyType is currently as the 41 * following. 42 * 43 * RequestDestination| nsContentPolicyType 44 * ------------------+-------------------- 45 * "audio" | TYPE_INTERNAL_AUDIO 46 * "audioworklet" | TYPE_INTERNAL_AUDIOWORKLET 47 * "document" | TYPE_DOCUMENT 48 * "embed" | TYPE_INTERNAL_EMBED 49 * "font" | TYPE_FONT, TYPE_INTERNAL_FONT_PRELOAD 50 * "frame" | TYPE_INTERNAL_FRAME 51 * "iframe" | TYPE_SUBDOCUMENT, TYPE_INTERNAL_IFRAME 52 * "image" | TYPE_INTERNAL_IMAGE, TYPE_INTERNAL_IMAGE_PRELOAD, 53 * | TYPE_IMAGE, TYPE_INTERNAL_IMAGE_FAVICON, TYPE_IMAGESET 54 * "json" | TYPE_JSON, TYPE_INTERNAL_JSON_PRELOAD 55 * "manifest" | TYPE_WEB_MANIFEST 56 * "object" | TYPE_INTERNAL_OBJECT, TYPE_OBJECT 57 * "paintworklet" | TYPE_INTERNAL_PAINTWORKLET 58 * "report" | TYPE_CSP_REPORT 59 * "script" | TYPE_INTERNAL_SCRIPT, TYPE_INTERNAL_SCRIPT_PRELOAD, 60 * | TYPE_INTERNAL_MODULE, TYPE_INTERNAL_MODULE_PRELOAD, 61 * | TYPE_SCRIPT, 62 * | TYPE_INTERNAL_SERVICE_WORKER, 63 * | TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS, 64 * | TYPE_INTERNAL_CHROMEUTILS_COMPILED_SCRIPT 65 * | TYPE_INTERNAL_FRAME_MESSAGEMANAGER_SCRIPT 66 * "sharedworker" | TYPE_INTERNAL_SHARED_WORKER 67 * "serviceworker" | The spec lists this as a valid value for the enum, 68 * | however it is impossible to observe a request with this 69 * | destination value. 70 * "style" | TYPE_INTERNAL_STYLESHEET, 71 * | TYPE_INTERNAL_STYLESHEET_PRELOAD, 72 * | TYPE_STYLESHEET 73 * "track" | TYPE_INTERNAL_TRACK 74 * "video" | TYPE_INTERNAL_VIDEO 75 * "worker" | TYPE_INTERNAL_WORKER, TYPE_INTERNAL_WORKER_STATIC_MODULE 76 * "xslt" | TYPE_XSLT 77 * "" | Default for everything else. 78 * 79 */ 80 81 class IPCInternalRequest; 82 class Request; 83 84 #define kFETCH_CLIENT_REFERRER_STR "about:client" 85 class InternalRequest final : public AtomicSafeRefCounted<InternalRequest> { 86 friend class Request; 87 88 public: 89 MOZ_DECLARE_REFCOUNTED_TYPENAME(InternalRequest) 90 InternalRequest(const nsACString& aURL, const nsACString& aFragment); 91 92 explicit InternalRequest(const IPCInternalRequest& aIPCRequest); 93 94 void ToIPCInternalRequest(IPCInternalRequest* aIPCRequest, 95 mozilla::ipc::PBackgroundChild* aManager); 96 97 SafeRefPtr<InternalRequest> Clone(); 98 99 void GetMethod(nsCString& aMethod) const { aMethod.Assign(mMethod); } 100 101 void SetMethod(const nsACString& aMethod) { mMethod.Assign(aMethod); } 102 103 bool HasSimpleMethod() const { 104 return mMethod.LowerCaseEqualsASCII("get") || 105 mMethod.LowerCaseEqualsASCII("post") || 106 mMethod.LowerCaseEqualsASCII("head"); 107 } 108 // GetURL should get the request's current url with fragment. A request has 109 // an associated current url. It is a pointer to the last fetch URL in 110 // request's url list. 111 void GetURL(nsACString& aURL) const { 112 aURL.Assign(GetURLWithoutFragment()); 113 if (GetFragment().IsEmpty()) { 114 return; 115 } 116 aURL.AppendLiteral("#"); 117 aURL.Append(GetFragment()); 118 } 119 120 const nsCString& GetURLWithoutFragment() const { 121 MOZ_RELEASE_ASSERT(!mURLList.IsEmpty(), 122 "Internal Request's urlList should not be empty."); 123 124 return mURLList.LastElement(); 125 } 126 127 // A safe guard for ensuring that request's URL is only allowed to be set in a 128 // sw internal redirect. 129 void SetURLForInternalRedirect(const uint32_t aFlag, const nsACString& aURL, 130 const nsACString& aFragment) { 131 // Only check in debug build to prevent it from being used unexpectedly. 132 MOZ_ASSERT(aFlag & nsIChannelEventSink::REDIRECT_INTERNAL); 133 134 return SetURL(aURL, aFragment); 135 } 136 137 // AddURL should append the url into url list. 138 // Normally we strip the fragment from the URL in Request::Constructor and 139 // pass the fragment as the second argument into it. 140 // If a fragment is present in the URL it must be stripped and passed in 141 // separately. 142 void AddURL(const nsACString& aURL, const nsACString& aFragment) { 143 MOZ_ASSERT(!aURL.IsEmpty()); 144 MOZ_ASSERT(!aURL.Contains('#')); 145 146 mURLList.AppendElement(aURL); 147 148 mFragment.Assign(aFragment); 149 } 150 // Get the URL list without their fragments. 151 void GetURLListWithoutFragment(nsTArray<nsCString>& aURLList) { 152 aURLList.Assign(mURLList); 153 } 154 void GetReferrer(nsACString& aReferrer) const { aReferrer.Assign(mReferrer); } 155 156 void SetReferrer(const nsACString& aReferrer) { 157 #ifdef DEBUG 158 bool validReferrer = false; 159 if (aReferrer.IsEmpty() || 160 aReferrer.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR)) { 161 validReferrer = true; 162 } else { 163 nsCOMPtr<nsIURLParser> parser = do_GetService(NS_STDURLPARSER_CONTRACTID); 164 if (!parser) { 165 NS_WARNING("Could not get parser to validate URL!"); 166 } else { 167 uint32_t schemePos; 168 int32_t schemeLen; 169 uint32_t authorityPos; 170 int32_t authorityLen; 171 uint32_t pathPos; 172 int32_t pathLen; 173 174 nsresult rv = parser->ParseURL( 175 aReferrer.BeginReading(), aReferrer.Length(), &schemePos, 176 &schemeLen, &authorityPos, &authorityLen, &pathPos, &pathLen); 177 if (NS_FAILED(rv)) { 178 NS_WARNING("Invalid referrer URL!"); 179 } else if (schemeLen < 0 || authorityLen < 0) { 180 NS_WARNING("Invalid referrer URL!"); 181 } else { 182 validReferrer = true; 183 } 184 } 185 } 186 187 MOZ_ASSERT(validReferrer); 188 #endif 189 190 mReferrer.Assign(aReferrer); 191 } 192 193 ReferrerPolicy ReferrerPolicy_() const { return mReferrerPolicy; } 194 195 void SetReferrerPolicy(ReferrerPolicy aReferrerPolicy) { 196 mReferrerPolicy = aReferrerPolicy; 197 } 198 199 ReferrerPolicy GetEnvironmentReferrerPolicy() const { 200 return mEnvironmentReferrerPolicy; 201 } 202 203 void SetEnvironmentReferrerPolicy(ReferrerPolicy aReferrerPolicy) { 204 mEnvironmentReferrerPolicy = aReferrerPolicy; 205 } 206 207 bool SkipServiceWorker() const { return mSkipServiceWorker; } 208 209 void SetSkipServiceWorker() { mSkipServiceWorker = true; } 210 211 bool SkipWasmCaching() const { return mSkipWasmCaching; } 212 213 void SetSkipWasmCaching() { mSkipWasmCaching = true; } 214 215 bool IsSynchronous() const { return mSynchronous; } 216 217 RequestMode Mode() const { return mMode; } 218 219 void SetMode(RequestMode aMode) { mMode = aMode; } 220 221 RequestCredentials GetCredentialsMode() const { return mCredentialsMode; } 222 223 void SetCredentialsMode(RequestCredentials aCredentialsMode) { 224 mCredentialsMode = aCredentialsMode; 225 } 226 227 LoadTainting GetResponseTainting() const { return mResponseTainting; } 228 229 void MaybeIncreaseResponseTainting(LoadTainting aTainting) { 230 if (aTainting > mResponseTainting && !mNeverTaint) { 231 mResponseTainting = aTainting; 232 } 233 } 234 235 RequestCache GetCacheMode() const { return mCacheMode; } 236 237 void SetCacheMode(RequestCache aCacheMode) { mCacheMode = aCacheMode; } 238 239 RequestRedirect GetRedirectMode() const { return mRedirectMode; } 240 241 void SetRedirectMode(RequestRedirect aRedirectMode) { 242 mRedirectMode = aRedirectMode; 243 } 244 245 RequestPriority GetPriorityMode() const { return mPriorityMode; } 246 247 void SetPriorityMode(RequestPriority aPriorityMode) { 248 mPriorityMode = aPriorityMode; 249 } 250 251 const nsString& GetIntegrity() const { return mIntegrity; } 252 253 void SetIntegrity(const nsAString& aIntegrity) { 254 mIntegrity.Assign(aIntegrity); 255 } 256 257 bool GetKeepalive() const { return mKeepalive; } 258 259 void SetKeepalive(const bool aKeepalive) { mKeepalive = aKeepalive; } 260 261 bool MozErrors() const { return mMozErrors; } 262 263 void SetMozErrors() { mMozErrors = true; } 264 265 void SetTriggeringPrincipal(nsIPrincipal* aPrincipal) { 266 mTriggeringPrincipalOverride = aPrincipal; 267 } 268 269 nsIPrincipal* GetTriggeringPrincipalOverride() { 270 return mTriggeringPrincipalOverride; 271 } 272 273 void SetNeverTaint(bool aNeverTaint) { mNeverTaint = aNeverTaint; } 274 275 bool GetNeverTaint() { return mNeverTaint; } 276 277 const nsCString& GetFragment() const { return mFragment; } 278 279 nsContentPolicyType ContentPolicyType() const { return mContentPolicyType; } 280 void SetContentPolicyType(nsContentPolicyType aContentPolicyType); 281 282 void OverrideContentPolicyType(nsContentPolicyType aContentPolicyType); 283 284 RequestDestination Destination() const { 285 return MapContentPolicyTypeToRequestDestination(mContentPolicyType); 286 } 287 288 int32_t InternalPriority() const { return mInternalPriority; } 289 void SetInternalPriority(int32_t aInternalPriority) { 290 mInternalPriority = aInternalPriority; 291 } 292 293 bool UnsafeRequest() const { return mUnsafeRequest; } 294 295 void SetUnsafeRequest() { mUnsafeRequest = true; } 296 297 InternalHeaders* Headers() const { return mHeaders; } 298 299 void SetHeaders(InternalHeaders* aHeaders) { 300 MOZ_ASSERT(aHeaders); 301 mHeaders = aHeaders; 302 } 303 304 void SetBody(nsIInputStream* aStream, int64_t aBodyLength) { 305 // A request's body may not be reset once set. 306 MOZ_ASSERT_IF(aStream, !mBodyStream); 307 mBodyStream = aStream; 308 mBodyLength = aBodyLength; 309 } 310 311 // Will return the original stream! 312 // Use a tee or copy if you don't want to erase the original. 313 void GetBody(nsIInputStream** aStream, int64_t* aBodyLength = nullptr) const { 314 nsCOMPtr<nsIInputStream> s = mBodyStream; 315 s.forget(aStream); 316 317 if (aBodyLength) { 318 *aBodyLength = mBodyLength; 319 } 320 } 321 322 int64_t BodyLength() const { return mBodyLength; } 323 324 void SetBodyBlobURISpec(nsACString& aBlobURISpec) { 325 mBodyBlobURISpec = aBlobURISpec; 326 } 327 328 const nsACString& BodyBlobURISpec() const { return mBodyBlobURISpec; } 329 330 void SetBodyLocalPath(nsAString& aLocalPath) { mBodyLocalPath = aLocalPath; } 331 332 const nsAString& BodyLocalPath() const { return mBodyLocalPath; } 333 334 // The global is used as the client for the new object. 335 SafeRefPtr<InternalRequest> GetRequestConstructorCopy( 336 nsIGlobalObject* aGlobal, ErrorResult& aRv) const; 337 338 bool IsNavigationRequest() const; 339 340 bool IsWorkerRequest() const; 341 342 bool IsClientRequest() const; 343 344 void MaybeSkipCacheIfPerformingRevalidation(); 345 346 bool IsContentPolicyTypeOverridden() const { 347 return mContentPolicyTypeOverridden; 348 } 349 350 static RequestMode MapChannelToRequestMode(nsIChannel* aChannel); 351 352 static RequestCredentials MapChannelToRequestCredentials( 353 nsIChannel* aChannel); 354 355 // Takes ownership of the principal info. 356 void SetPrincipalInfo(UniquePtr<mozilla::ipc::PrincipalInfo> aPrincipalInfo); 357 const UniquePtr<mozilla::ipc::PrincipalInfo>& GetPrincipalInfo() const { 358 return mPrincipalInfo; 359 } 360 361 const nsCString& GetPreferredAlternativeDataType() const { 362 return mPreferredAlternativeDataType; 363 } 364 365 void SetPreferredAlternativeDataType(const nsACString& aDataType) { 366 mPreferredAlternativeDataType = aDataType; 367 } 368 369 ~InternalRequest(); 370 371 InternalRequest(const InternalRequest& aOther) = delete; 372 373 void SetEmbedderPolicy(nsILoadInfo::CrossOriginEmbedderPolicy aPolicy) { 374 mEmbedderPolicy = aPolicy; 375 } 376 377 nsILoadInfo::CrossOriginEmbedderPolicy GetEmbedderPolicy() const { 378 return mEmbedderPolicy; 379 } 380 381 void SetInterceptionTriggeringPrincipalInfo( 382 UniquePtr<mozilla::ipc::PrincipalInfo> aPrincipalInfo); 383 384 const UniquePtr<mozilla::ipc::PrincipalInfo>& 385 GetInterceptionTriggeringPrincipalInfo() const { 386 return mInterceptionTriggeringPrincipalInfo; 387 } 388 389 nsContentPolicyType InterceptionContentPolicyType() const { 390 return mInterceptionContentPolicyType; 391 } 392 RequestDestination InterceptionDestination() const { 393 return MapContentPolicyTypeToRequestDestination( 394 mInterceptionContentPolicyType); 395 } 396 void SetInterceptionContentPolicyType(nsContentPolicyType aContentPolicyType); 397 398 const nsTArray<RedirectHistoryEntryInfo>& InterceptionRedirectChain() const { 399 return mInterceptionRedirectChain; 400 } 401 402 void SetInterceptionRedirectChain( 403 const nsTArray<RedirectHistoryEntryInfo>& aRedirectChain) { 404 mInterceptionRedirectChain = aRedirectChain; 405 } 406 407 const bool& InterceptionFromThirdParty() const { 408 return mInterceptionFromThirdParty; 409 } 410 411 void SetInterceptionFromThirdParty(bool aFromThirdParty) { 412 mInterceptionFromThirdParty = aFromThirdParty; 413 } 414 415 private: 416 struct ConstructorGuard {}; 417 418 public: 419 // Does not copy mBodyStream. Use fallible Clone() for complete copy. 420 InternalRequest(const InternalRequest& aOther, ConstructorGuard); 421 422 // Map the content policy type to the associated fetch destination, as defined 423 // by the spec at https://fetch.spec.whatwg.org/#concept-request-destination. 424 // Note that while the HTML spec for the "Link" element and its "as" attribute 425 // (https://html.spec.whatwg.org/#attr-link-as) reuse fetch's definition of 426 // destination. 427 static RequestDestination MapContentPolicyTypeToRequestDestination( 428 nsContentPolicyType aContentPolicyType); 429 static RequestDestination MapContentPolicyTypeToRequestDestination( 430 ExtContentPolicyType aContentPolicyType); 431 432 private: 433 static bool IsNavigationContentPolicy(nsContentPolicyType aContentPolicyType); 434 435 static bool IsWorkerContentPolicy(nsContentPolicyType aContentPolicyType); 436 437 // It should only be called while there is a service-worker-internal-redirect. 438 void SetURL(const nsACString& aURL, const nsACString& aFragment) { 439 MOZ_ASSERT(!aURL.IsEmpty()); 440 MOZ_ASSERT(!aURL.Contains('#')); 441 MOZ_ASSERT(mURLList.Length() > 0); 442 443 mURLList.LastElement() = aURL; 444 mFragment.Assign(aFragment); 445 } 446 447 nsCString mMethod; 448 // mURLList: a list of one or more fetch URLs 449 nsTArray<nsCString> mURLList; 450 RefPtr<InternalHeaders> mHeaders; 451 nsCString mBodyBlobURISpec; 452 nsString mBodyLocalPath; 453 nsCOMPtr<nsIInputStream> mBodyStream; 454 455 nsCOMPtr<nsIPrincipal> mTriggeringPrincipalOverride; 456 bool mNeverTaint = false; 457 int64_t mBodyLength{InternalResponse::UNKNOWN_BODY_SIZE}; 458 459 nsCString mPreferredAlternativeDataType; 460 461 nsContentPolicyType mContentPolicyType; 462 463 int32_t mInternalPriority = nsISupportsPriority::PRIORITY_NORMAL; 464 465 // Empty string: no-referrer 466 // "about:client": client (default) 467 // URL: an URL 468 nsCString mReferrer; 469 ReferrerPolicy mReferrerPolicy; 470 471 // This will be used for request created from Window or Worker contexts 472 // In case there's no Referrer Policy in Request, this will be passed to 473 // channel. 474 ReferrerPolicy mEnvironmentReferrerPolicy; 475 RequestMode mMode; 476 RequestCredentials mCredentialsMode; 477 LoadTainting mResponseTainting = LoadTainting::Basic; 478 RequestCache mCacheMode; 479 RequestRedirect mRedirectMode; 480 RequestPriority mPriorityMode = RequestPriority::Auto; 481 nsString mIntegrity; 482 bool mKeepalive = false; 483 bool mMozErrors = false; 484 nsCString mFragment; 485 bool mSkipServiceWorker = false; 486 bool mSkipWasmCaching = false; 487 bool mSynchronous = false; 488 bool mUnsafeRequest = false; 489 bool mUseURLCredentials = false; 490 // This is only set when Request.overrideContentPolicyType() has been set. 491 // It is illegal to pass such a Request object to a fetch() method unless 492 // if the caller has chrome privileges. 493 bool mContentPolicyTypeOverridden = false; 494 nsILoadInfo::CrossOriginEmbedderPolicy mEmbedderPolicy = 495 nsILoadInfo::EMBEDDER_POLICY_NULL; 496 497 UniquePtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo; 498 499 // Following members are specific for the FetchEvent.request or 500 // NavigationPreload request which is extracted from the 501 // InterceptedHttpChannel. 502 // Notice that these members would not be copied when calling 503 // InternalRequest::GetRequestConstructorCopy() since these information should 504 // not be propagated when copying the Request in ServiceWorker script. 505 506 // This is the trigging principalInfo of the InterceptedHttpChannel. 507 UniquePtr<mozilla::ipc::PrincipalInfo> mInterceptionTriggeringPrincipalInfo; 508 509 // This is the contentPolicyType of the InterceptedHttpChannel. 510 nsContentPolicyType mInterceptionContentPolicyType{ 511 nsIContentPolicy::TYPE_INVALID}; 512 513 // This is the redirect history of the InterceptedHttpChannel. 514 CopyableTArray<RedirectHistoryEntryInfo> mInterceptionRedirectChain; 515 516 // This indicates that the InterceptedHttpChannel is a third party channel. 517 bool mInterceptionFromThirdParty{false}; 518 }; 519 520 } // namespace dom 521 } // namespace mozilla 522 523 #endif // mozilla_dom_InternalRequest_h