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/dom/HeadersBinding.h" 11 #include "mozilla/dom/InternalHeaders.h" 12 #include "mozilla/dom/RequestBinding.h" 13 #include "mozilla/LoadTainting.h" 14 #include "mozilla/net/ReferrerPolicy.h" 15 16 #include "nsIContentPolicy.h" 17 #include "nsIInputStream.h" 18 #include "nsISupportsImpl.h" 19 #ifdef DEBUG 20 #include "nsIURLParser.h" 21 #include "nsNetCID.h" 22 #include "nsServiceManagerUtils.h" 23 #endif 24 25 namespace mozilla { 26 27 namespace ipc { 28 class PrincipalInfo; 29 } // namespace ipc 30 31 namespace dom { 32 33 /* 34 * The mapping of RequestContext and nsContentPolicyType is currently as the 35 * following. Note that this mapping is not perfect yet (see the TODO comments 36 * below for examples). 37 * 38 * RequestContext | nsContentPolicyType 39 * ------------------+-------------------- 40 * audio | TYPE_INTERNAL_AUDIO 41 * beacon | TYPE_BEACON 42 * cspreport | TYPE_CSP_REPORT 43 * download | 44 * embed | TYPE_INTERNAL_EMBED 45 * eventsource | 46 * favicon | 47 * fetch | TYPE_FETCH 48 * font | TYPE_FONT 49 * form | 50 * frame | TYPE_INTERNAL_FRAME 51 * hyperlink | 52 * iframe | TYPE_INTERNAL_IFRAME 53 * image | TYPE_INTERNAL_IMAGE, TYPE_INTERNAL_IMAGE_PRELOAD, TYPE_INTERNAL_IMAGE_FAVICON 54 * imageset | TYPE_IMAGESET 55 * import | Not supported by Gecko 56 * internal | TYPE_DOCUMENT, TYPE_XBL, TYPE_OTHER 57 * location | 58 * manifest | TYPE_WEB_MANIFEST 59 * object | TYPE_INTERNAL_OBJECT 60 * ping | TYPE_PING 61 * plugin | TYPE_OBJECT_SUBREQUEST 62 * prefetch | 63 * script | TYPE_INTERNAL_SCRIPT, TYPE_INTERNAL_SCRIPT_PRELOAD 64 * sharedworker | TYPE_INTERNAL_SHARED_WORKER 65 * subresource | Not supported by Gecko 66 * style | TYPE_INTERNAL_STYLESHEET, TYPE_INTERNAL_STYLESHEET_PRELOAD 67 * track | TYPE_INTERNAL_TRACK 68 * video | TYPE_INTERNAL_VIDEO 69 * worker | TYPE_INTERNAL_WORKER 70 * xmlhttprequest | TYPE_INTERNAL_XMLHTTPREQUEST 71 * eventsource | TYPE_INTERNAL_EVENTSOURCE 72 * xslt | TYPE_XSLT 73 * 74 * TODO: Figure out if TYPE_REFRESH maps to anything useful 75 * TODO: Figure out if TYPE_DTD maps to anything useful 76 * TODO: Figure out if TYPE_WEBSOCKET maps to anything useful 77 * TODO: Add a content type for prefetch 78 * TODO: Use the content type for manifest when it becomes available 79 * TODO: Add a content type for location 80 * TODO: Add a content type for hyperlink 81 * TODO: Add a content type for form 82 * TODO: Add a content type for favicon 83 * TODO: Add a content type for download 84 */ 85 86 class Request; 87 class IPCInternalRequest; 88 89 #define kFETCH_CLIENT_REFERRER_STR "about:client" 90 class InternalRequest final 91 { 92 friend class Request; 93 public: 94 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(InternalRequest) 95 InternalRequest(const nsACString& aURL, const nsACString& aFragment); 96 InternalRequest(const nsACString& aURL, 97 const nsACString& aFragment, 98 const nsACString& aMethod, 99 already_AddRefed<InternalHeaders> aHeaders, 100 RequestCache aCacheMode, 101 RequestMode aMode, 102 RequestRedirect aRequestRedirect, 103 RequestCredentials aRequestCredentials, 104 const nsAString& aReferrer, 105 ReferrerPolicy aReferrerPolicy, 106 nsContentPolicyType aContentPolicyType, 107 const nsAString& aIntegrity); 108 109 explicit InternalRequest(const IPCInternalRequest& aIPCRequest); 110 111 void ToIPC(IPCInternalRequest* aIPCRequest); 112 113 already_AddRefed<InternalRequest> Clone(); 114 115 void GetMethod(nsCString & aMethod)116 GetMethod(nsCString& aMethod) const 117 { 118 aMethod.Assign(mMethod); 119 } 120 121 void SetMethod(const nsACString & aMethod)122 SetMethod(const nsACString& aMethod) 123 { 124 mMethod.Assign(aMethod); 125 } 126 127 bool HasSimpleMethod()128 HasSimpleMethod() const 129 { 130 return mMethod.LowerCaseEqualsASCII("get") || 131 mMethod.LowerCaseEqualsASCII("post") || 132 mMethod.LowerCaseEqualsASCII("head"); 133 } 134 // GetURL should get the request's current url with fragment. A request has 135 // an associated current url. It is a pointer to the last fetch URL in 136 // request's url list. 137 void GetURL(nsACString & aURL)138 GetURL(nsACString& aURL) const 139 { 140 aURL.Assign(GetURLWithoutFragment()); 141 if (GetFragment().IsEmpty()) { 142 return; 143 } 144 aURL.Append(NS_LITERAL_CSTRING("#")); 145 aURL.Append(GetFragment()); 146 } 147 148 const nsCString& GetURLWithoutFragment()149 GetURLWithoutFragment() const 150 { 151 MOZ_RELEASE_ASSERT(!mURLList.IsEmpty(), 152 "Internal Request's urlList should not be empty."); 153 154 return mURLList.LastElement(); 155 } 156 // AddURL should append the url into url list. 157 // Normally we strip the fragment from the URL in Request::Constructor and 158 // pass the fragment as the second argument into it. 159 // If a fragment is present in the URL it must be stripped and passed in 160 // separately. 161 void AddURL(const nsACString & aURL,const nsACString & aFragment)162 AddURL(const nsACString& aURL, const nsACString& aFragment) 163 { 164 MOZ_ASSERT(!aURL.IsEmpty()); 165 MOZ_ASSERT(!aURL.Contains('#')); 166 167 mURLList.AppendElement(aURL); 168 169 mFragment.Assign(aFragment); 170 } 171 // Get the URL list without their fragments. 172 void GetURLListWithoutFragment(nsTArray<nsCString> & aURLList)173 GetURLListWithoutFragment(nsTArray<nsCString>& aURLList) 174 { 175 aURLList.Assign(mURLList); 176 } 177 void GetReferrer(nsAString & aReferrer)178 GetReferrer(nsAString& aReferrer) const 179 { 180 aReferrer.Assign(mReferrer); 181 } 182 183 void SetReferrer(const nsAString & aReferrer)184 SetReferrer(const nsAString& aReferrer) 185 { 186 #ifdef DEBUG 187 bool validReferrer = false; 188 if (aReferrer.IsEmpty() || 189 aReferrer.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR)) { 190 validReferrer = true; 191 } else { 192 nsCOMPtr<nsIURLParser> parser = do_GetService(NS_STDURLPARSER_CONTRACTID); 193 if (!parser) { 194 NS_WARNING("Could not get parser to validate URL!"); 195 } else { 196 uint32_t schemePos; 197 int32_t schemeLen; 198 uint32_t authorityPos; 199 int32_t authorityLen; 200 uint32_t pathPos; 201 int32_t pathLen; 202 203 NS_ConvertUTF16toUTF8 ref(aReferrer); 204 nsresult rv = parser->ParseURL(ref.get(), ref.Length(), 205 &schemePos, &schemeLen, 206 &authorityPos, &authorityLen, 207 &pathPos, &pathLen); 208 if (NS_FAILED(rv)) { 209 NS_WARNING("Invalid referrer URL!"); 210 } else if (schemeLen < 0 || authorityLen < 0) { 211 NS_WARNING("Invalid referrer URL!"); 212 } else { 213 validReferrer = true; 214 } 215 } 216 } 217 218 MOZ_ASSERT(validReferrer); 219 #endif 220 221 mReferrer.Assign(aReferrer); 222 } 223 224 ReferrerPolicy ReferrerPolicy_()225 ReferrerPolicy_() const 226 { 227 return mReferrerPolicy; 228 } 229 230 void SetReferrerPolicy(ReferrerPolicy aReferrerPolicy)231 SetReferrerPolicy(ReferrerPolicy aReferrerPolicy) 232 { 233 mReferrerPolicy = aReferrerPolicy; 234 } 235 236 net::ReferrerPolicy GetEnvironmentReferrerPolicy()237 GetEnvironmentReferrerPolicy() const 238 { 239 return mEnvironmentReferrerPolicy; 240 } 241 242 void SetEnvironmentReferrerPolicy(net::ReferrerPolicy aReferrerPolicy)243 SetEnvironmentReferrerPolicy(net::ReferrerPolicy aReferrerPolicy) 244 { 245 mEnvironmentReferrerPolicy = aReferrerPolicy; 246 } 247 248 bool SkipServiceWorker()249 SkipServiceWorker() const 250 { 251 return mSkipServiceWorker; 252 } 253 254 void SetSkipServiceWorker()255 SetSkipServiceWorker() 256 { 257 mSkipServiceWorker = true; 258 } 259 260 bool IsSynchronous()261 IsSynchronous() const 262 { 263 return mSynchronous; 264 } 265 266 RequestMode Mode()267 Mode() const 268 { 269 return mMode; 270 } 271 272 void SetMode(RequestMode aMode)273 SetMode(RequestMode aMode) 274 { 275 mMode = aMode; 276 } 277 278 RequestCredentials GetCredentialsMode()279 GetCredentialsMode() const 280 { 281 return mCredentialsMode; 282 } 283 284 void SetCredentialsMode(RequestCredentials aCredentialsMode)285 SetCredentialsMode(RequestCredentials aCredentialsMode) 286 { 287 mCredentialsMode = aCredentialsMode; 288 } 289 290 LoadTainting GetResponseTainting()291 GetResponseTainting() const 292 { 293 return mResponseTainting; 294 } 295 296 void MaybeIncreaseResponseTainting(LoadTainting aTainting)297 MaybeIncreaseResponseTainting(LoadTainting aTainting) 298 { 299 if (aTainting > mResponseTainting) { 300 mResponseTainting = aTainting; 301 } 302 } 303 304 RequestCache GetCacheMode()305 GetCacheMode() const 306 { 307 return mCacheMode; 308 } 309 310 void SetCacheMode(RequestCache aCacheMode)311 SetCacheMode(RequestCache aCacheMode) 312 { 313 mCacheMode = aCacheMode; 314 } 315 316 RequestRedirect GetRedirectMode()317 GetRedirectMode() const 318 { 319 return mRedirectMode; 320 } 321 322 void SetRedirectMode(RequestRedirect aRedirectMode)323 SetRedirectMode(RequestRedirect aRedirectMode) 324 { 325 mRedirectMode = aRedirectMode; 326 } 327 328 const nsString& GetIntegrity()329 GetIntegrity() const 330 { 331 return mIntegrity; 332 } 333 void SetIntegrity(const nsAString & aIntegrity)334 SetIntegrity(const nsAString& aIntegrity) 335 { 336 MOZ_ASSERT(mIntegrity.IsEmpty()); 337 mIntegrity.Assign(aIntegrity); 338 } 339 const nsCString& GetFragment()340 GetFragment() const 341 { 342 return mFragment; 343 } 344 345 nsContentPolicyType ContentPolicyType()346 ContentPolicyType() const 347 { 348 return mContentPolicyType; 349 } 350 void 351 SetContentPolicyType(nsContentPolicyType aContentPolicyType); 352 353 void 354 OverrideContentPolicyType(nsContentPolicyType aContentPolicyType); 355 356 RequestContext Context()357 Context() const 358 { 359 return MapContentPolicyTypeToRequestContext(mContentPolicyType); 360 } 361 362 bool UnsafeRequest()363 UnsafeRequest() const 364 { 365 return mUnsafeRequest; 366 } 367 368 void SetUnsafeRequest()369 SetUnsafeRequest() 370 { 371 mUnsafeRequest = true; 372 } 373 374 InternalHeaders* Headers()375 Headers() 376 { 377 return mHeaders; 378 } 379 380 bool ForceOriginHeader()381 ForceOriginHeader() 382 { 383 return mForceOriginHeader; 384 } 385 386 bool SameOriginDataURL()387 SameOriginDataURL() const 388 { 389 return mSameOriginDataURL; 390 } 391 392 void UnsetSameOriginDataURL()393 UnsetSameOriginDataURL() 394 { 395 mSameOriginDataURL = false; 396 } 397 398 void SetBody(nsIInputStream * aStream)399 SetBody(nsIInputStream* aStream) 400 { 401 // A request's body may not be reset once set. 402 MOZ_ASSERT_IF(aStream, !mBodyStream); 403 mBodyStream = aStream; 404 } 405 406 // Will return the original stream! 407 // Use a tee or copy if you don't want to erase the original. 408 void GetBody(nsIInputStream ** aStream)409 GetBody(nsIInputStream** aStream) 410 { 411 nsCOMPtr<nsIInputStream> s = mBodyStream; 412 s.forget(aStream); 413 } 414 415 // The global is used as the client for the new object. 416 already_AddRefed<InternalRequest> 417 GetRequestConstructorCopy(nsIGlobalObject* aGlobal, ErrorResult& aRv) const; 418 419 bool WasCreatedByFetchEvent()420 WasCreatedByFetchEvent() const 421 { 422 return mCreatedByFetchEvent; 423 } 424 425 void SetCreatedByFetchEvent()426 SetCreatedByFetchEvent() 427 { 428 mCreatedByFetchEvent = true; 429 } 430 431 void ClearCreatedByFetchEvent()432 ClearCreatedByFetchEvent() 433 { 434 mCreatedByFetchEvent = false; 435 } 436 437 bool 438 IsNavigationRequest() const; 439 440 bool 441 IsWorkerRequest() const; 442 443 bool 444 IsClientRequest() const; 445 446 void 447 MaybeSkipCacheIfPerformingRevalidation(); 448 449 bool IsContentPolicyTypeOverridden()450 IsContentPolicyTypeOverridden() const 451 { 452 return mContentPolicyTypeOverridden; 453 } 454 455 static RequestMode 456 MapChannelToRequestMode(nsIChannel* aChannel); 457 458 static RequestCredentials 459 MapChannelToRequestCredentials(nsIChannel* aChannel); 460 461 // Takes ownership of the principal info. 462 void 463 SetPrincipalInfo(UniquePtr<mozilla::ipc::PrincipalInfo> aPrincipalInfo); 464 465 const UniquePtr<mozilla::ipc::PrincipalInfo>& GetPrincipalInfo()466 GetPrincipalInfo() const 467 { 468 return mPrincipalInfo; 469 } 470 471 private: 472 // Does not copy mBodyStream. Use fallible Clone() for complete copy. 473 explicit InternalRequest(const InternalRequest& aOther); 474 475 ~InternalRequest(); 476 477 static RequestContext 478 MapContentPolicyTypeToRequestContext(nsContentPolicyType aContentPolicyType); 479 480 static bool 481 IsNavigationContentPolicy(nsContentPolicyType aContentPolicyType); 482 483 static bool 484 IsWorkerContentPolicy(nsContentPolicyType aContentPolicyType); 485 486 nsCString mMethod; 487 // mURLList: a list of one or more fetch URLs 488 nsTArray<nsCString> mURLList; 489 RefPtr<InternalHeaders> mHeaders; 490 nsCOMPtr<nsIInputStream> mBodyStream; 491 492 nsContentPolicyType mContentPolicyType; 493 494 // Empty string: no-referrer 495 // "about:client": client (default) 496 // URL: an URL 497 nsString mReferrer; 498 ReferrerPolicy mReferrerPolicy; 499 500 // This will be used for request created from Window or Worker contexts 501 // In case there's no Referrer Policy in Request, this will be passed to 502 // channel. 503 // The Environment Referrer Policy should be net::ReferrerPolicy so that it 504 // could be associated with nsIHttpChannel. 505 net::ReferrerPolicy mEnvironmentReferrerPolicy; 506 RequestMode mMode; 507 RequestCredentials mCredentialsMode; 508 MOZ_INIT_OUTSIDE_CTOR LoadTainting mResponseTainting; 509 RequestCache mCacheMode; 510 RequestRedirect mRedirectMode; 511 nsString mIntegrity; 512 nsCString mFragment; 513 MOZ_INIT_OUTSIDE_CTOR bool mAuthenticationFlag; 514 MOZ_INIT_OUTSIDE_CTOR bool mForceOriginHeader; 515 MOZ_INIT_OUTSIDE_CTOR bool mPreserveContentCodings; 516 MOZ_INIT_OUTSIDE_CTOR bool mSameOriginDataURL; 517 MOZ_INIT_OUTSIDE_CTOR bool mSkipServiceWorker; 518 MOZ_INIT_OUTSIDE_CTOR bool mSynchronous; 519 MOZ_INIT_OUTSIDE_CTOR bool mUnsafeRequest; 520 MOZ_INIT_OUTSIDE_CTOR bool mUseURLCredentials; 521 // This is only set when a Request object is created by a fetch event. We 522 // use it to check if Service Workers are simply fetching intercepted Request 523 // objects without modifying them. 524 bool mCreatedByFetchEvent = false; 525 // This is only set when Request.overrideContentPolicyType() has been set. 526 // It is illegal to pass such a Request object to a fetch() method unless 527 // if the caller has chrome privileges. 528 bool mContentPolicyTypeOverridden = false; 529 530 UniquePtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo; 531 }; 532 533 } // namespace dom 534 } // namespace mozilla 535 536 #endif // mozilla_dom_InternalRequest_h 537