nsHttpChannel.h (40258B)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set et cin ts=4 sw=2 sts=2: */ 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 nsHttpChannel_h__ 8 #define nsHttpChannel_h__ 9 10 #include "AlternateServices.h" 11 #include "AutoClose.h" 12 #include "HttpBaseChannel.h" 13 #include "nsIReplacedHttpResponse.h" 14 #include "TimingStruct.h" 15 #include "mozilla/AtomicBitfields.h" 16 #include "mozilla/Atomics.h" 17 #include "mozilla/Mutex.h" 18 #include "mozilla/extensions/PStreamFilterParent.h" 19 #include "mozilla/net/DocumentLoadListener.h" 20 #include "nsIAsyncVerifyRedirectCallback.h" 21 #include "nsICacheEntry.h" 22 #include "nsICacheEntryOpenCallback.h" 23 #include "nsICachingChannel.h" 24 #include "nsICorsPreflightCallback.h" 25 #include "nsIDNSListener.h" 26 #include "nsIEarlyHintObserver.h" 27 #include "nsIHttpAuthenticableChannel.h" 28 #include "nsIProtocolProxyCallback.h" 29 #include "nsIRaceCacheWithNetwork.h" 30 #include "nsIRequestContext.h" 31 #include "nsIStreamListener.h" 32 #include "nsIThreadRetargetableRequest.h" 33 #include "nsIThreadRetargetableStreamListener.h" 34 #include "nsITransportSecurityInfo.h" 35 #include "nsTArray.h" 36 #include "nsWeakReference.h" 37 38 class nsDNSPrefetch; 39 class nsICancelable; 40 class nsIDNSRecord; 41 class nsIDNSHTTPSSVCRecord; 42 class nsIHttpChannelAuthProvider; 43 class nsInputStreamPump; 44 class nsITransportSecurityInfo; 45 46 namespace mozilla { 47 namespace net { 48 49 class nsChannelClassifier; 50 class HttpChannelSecurityWarningReporter; 51 52 using DNSPromise = MozPromise<nsCOMPtr<nsIDNSRecord>, nsresult, false>; 53 54 //----------------------------------------------------------------------------- 55 // nsHttpChannel 56 //----------------------------------------------------------------------------- 57 58 // Use to support QI nsIChannel to nsHttpChannel 59 #define NS_HTTPCHANNEL_IID \ 60 {0x301bf95b, 0x7bb3, 0x4ae1, {0xa9, 0x71, 0x40, 0xbc, 0xfa, 0x81, 0xde, 0x12}} 61 62 class nsHttpChannel final : public HttpBaseChannel, 63 public HttpAsyncAborter<nsHttpChannel>, 64 public nsICachingChannel, 65 public nsICacheEntryOpenCallback, 66 public nsITransportEventSink, 67 public nsIProtocolProxyCallback, 68 public nsIHttpAuthenticableChannel, 69 public nsIAsyncVerifyRedirectCallback, 70 public nsIThreadRetargetableRequest, 71 public nsIThreadRetargetableStreamListener, 72 public nsIDNSListener, 73 public nsSupportsWeakReference, 74 public nsICorsPreflightCallback, 75 public nsIRaceCacheWithNetwork, 76 public nsIRequestTailUnblockCallback, 77 public nsIEarlyHintObserver { 78 public: 79 NS_DECL_ISUPPORTS_INHERITED 80 NS_DECL_NSIREQUESTOBSERVER 81 NS_DECL_NSISTREAMLISTENER 82 NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER 83 NS_DECL_NSICACHEINFOCHANNEL 84 NS_DECL_NSICACHINGCHANNEL 85 NS_DECL_NSICACHEENTRYOPENCALLBACK 86 NS_DECL_NSITRANSPORTEVENTSINK 87 NS_DECL_NSIPROTOCOLPROXYCALLBACK 88 NS_DECL_NSIPROXIEDCHANNEL 89 NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK 90 NS_DECL_NSITHREADRETARGETABLEREQUEST 91 NS_DECL_NSIDNSLISTENER 92 NS_INLINE_DECL_STATIC_IID(NS_HTTPCHANNEL_IID) 93 NS_DECL_NSIRACECACHEWITHNETWORK 94 NS_DECL_NSIREQUESTTAILUNBLOCKCALLBACK 95 NS_DECL_NSIEARLYHINTOBSERVER 96 97 // nsIHttpAuthenticableChannel. We can't use 98 // NS_DECL_NSIHTTPAUTHENTICABLECHANNEL because it duplicates cancel() and 99 // others. 100 NS_IMETHOD GetIsSSL(bool* aIsSSL) override; 101 NS_IMETHOD GetProxyMethodIsConnect(bool* aProxyMethodIsConnect) override; 102 NS_IMETHOD GetServerResponseHeader( 103 nsACString& aServerResponseHeader) override; 104 NS_IMETHOD GetProxyChallenges(nsACString& aChallenges) override; 105 NS_IMETHOD GetWWWChallenges(nsACString& aChallenges) override; 106 NS_IMETHOD SetProxyCredentials(const nsACString& aCredentials) override; 107 NS_IMETHOD SetWWWCredentials(const nsACString& aCredentials) override; 108 NS_IMETHOD OnAuthAvailable() override; 109 NS_IMETHOD OnAuthCancelled(bool userCancel) override; 110 NS_IMETHOD CloseStickyConnection() override; 111 NS_IMETHOD ConnectionRestartable(bool) override; 112 // Functions we implement from nsIHttpAuthenticableChannel but are 113 // declared in HttpBaseChannel must be implemented in this class. We 114 // just call the HttpBaseChannel:: impls. 115 NS_IMETHOD GetLoadFlags(nsLoadFlags* aLoadFlags) override; 116 NS_IMETHOD GetURI(nsIURI** aURI) override; 117 NS_IMETHOD GetNotificationCallbacks( 118 nsIInterfaceRequestor** aCallbacks) override; 119 NS_IMETHOD GetLoadGroup(nsILoadGroup** aLoadGroup) override; 120 NS_IMETHOD GetRequestMethod(nsACString& aMethod) override; 121 122 nsHttpChannel(); 123 124 [[nodiscard]] virtual nsresult Init(nsIURI* aURI, uint32_t aCaps, 125 nsProxyInfo* aProxyInfo, 126 uint32_t aProxyResolveFlags, 127 nsIURI* aProxyURI, uint64_t aChannelId, 128 nsILoadInfo* aLoadInfo) override; 129 130 static bool IsRedirectStatus(uint32_t status); 131 static bool WillRedirect(const nsHttpResponseHead& response); 132 133 // Methods HttpBaseChannel didn't implement for us or that we override. 134 // 135 // nsIRequest 136 NS_IMETHOD SetCanceledReason(const nsACString& aReason) override; 137 NS_IMETHOD GetCanceledReason(nsACString& aReason) override; 138 NS_IMETHOD CancelWithReason(nsresult status, 139 const nsACString& reason) override; 140 NS_IMETHOD Cancel(nsresult status) override; 141 NS_IMETHOD Suspend() override; 142 static void StaticSuspend(nsHttpChannel* aChan); 143 NS_IMETHOD Resume() override; 144 // nsIChannel 145 NS_IMETHOD 146 GetSecurityInfo(nsITransportSecurityInfo** aSecurityInfo) override; 147 NS_IMETHOD AsyncOpen(nsIStreamListener* aListener) override; 148 // nsIHttpChannel 149 NS_IMETHOD GetEncodedBodySize(uint64_t* aEncodedBodySize) override; 150 // nsIHttpChannelInternal 151 NS_IMETHOD GetIsAuthChannel(bool* aIsAuthChannel) override; 152 NS_IMETHOD SetChannelIsForDownload(bool aChannelIsForDownload) override; 153 NS_IMETHOD GetNavigationStartTimeStamp(TimeStamp* aTimeStamp) override; 154 NS_IMETHOD SetNavigationStartTimeStamp(TimeStamp aTimeStamp) override; 155 NS_IMETHOD CancelByURLClassifier(nsresult aErrorCode) override; 156 NS_IMETHOD GetLastTransportStatus(nsresult* aLastTransportStatus) override; 157 // nsISupportsPriority 158 NS_IMETHOD SetPriority(int32_t value) override; 159 // nsIClassOfService 160 NS_IMETHOD SetClassFlags(uint32_t inFlags) override; 161 NS_IMETHOD AddClassFlags(uint32_t inFlags) override; 162 NS_IMETHOD ClearClassFlags(uint32_t inFlags) override; 163 NS_IMETHOD SetClassOfService(ClassOfService cos) override; 164 NS_IMETHOD SetIncremental(bool incremental) override; 165 166 // nsIResumableChannel 167 NS_IMETHOD ResumeAt(uint64_t startPos, const nsACString& entityID) override; 168 169 NS_IMETHOD SetNotificationCallbacks( 170 nsIInterfaceRequestor* aCallbacks) override; 171 NS_IMETHOD SetLoadGroup(nsILoadGroup* aLoadGroup) override; 172 // nsITimedChannel 173 NS_IMETHOD GetDomainLookupStart( 174 mozilla::TimeStamp* aDomainLookupStart) override; 175 NS_IMETHOD GetDomainLookupEnd(mozilla::TimeStamp* aDomainLookupEnd) override; 176 NS_IMETHOD GetConnectStart(mozilla::TimeStamp* aConnectStart) override; 177 NS_IMETHOD GetTcpConnectEnd(mozilla::TimeStamp* aTcpConnectEnd) override; 178 NS_IMETHOD GetSecureConnectionStart( 179 mozilla::TimeStamp* aSecureConnectionStart) override; 180 NS_IMETHOD GetConnectEnd(mozilla::TimeStamp* aConnectEnd) override; 181 NS_IMETHOD GetRequestStart(mozilla::TimeStamp* aRequestStart) override; 182 NS_IMETHOD GetResponseStart(mozilla::TimeStamp* aResponseStart) override; 183 NS_IMETHOD GetResponseEnd(mozilla::TimeStamp* aResponseEnd) override; 184 185 NS_IMETHOD GetTransactionPending( 186 mozilla::TimeStamp* aTransactionPending) override; 187 188 // nsICorsPreflightCallback 189 NS_IMETHOD OnPreflightSucceeded() override; 190 NS_IMETHOD OnPreflightFailed(nsresult aError) override; 191 192 [[nodiscard]] nsresult AddSecurityMessage( 193 const nsAString& aMessageTag, const nsAString& aMessageCategory) override; 194 NS_IMETHOD LogBlockedCORSRequest(const nsAString& aMessage, 195 const nsACString& aCategory, 196 bool aIsWarning) override; 197 NS_IMETHOD LogMimeTypeMismatch(const nsACString& aMessageName, bool aWarning, 198 const nsAString& aURL, 199 const nsAString& aContentType) override; 200 201 NS_IMETHOD SetEarlyHintObserver(nsIEarlyHintObserver* aObserver) override; 202 NS_IMETHOD SetWebTransportSessionEventListener( 203 WebTransportSessionEventListener* aListener) override; 204 NS_IMETHOD SetResponseOverride( 205 nsIReplacedHttpResponse* aReplacedHttpResponse) override; 206 NS_IMETHOD SetResponseStatus(uint32_t aStatus, 207 const nsACString& aStatusText) override; 208 209 NS_IMETHOD GetDecompressDictionary( 210 DictionaryCacheEntry** aDictionary) override; 211 NS_IMETHOD SetDecompressDictionary( 212 DictionaryCacheEntry* aDictionary) override; 213 214 void SetWarningReporter(HttpChannelSecurityWarningReporter* aReporter); 215 HttpChannelSecurityWarningReporter* GetWarningReporter(); 216 217 bool DataSentToChildProcess() { return LoadDataSentToChildProcess(); } 218 219 enum class SnifferType { Media, Image }; 220 void DisableIsOpaqueResponseAllowedAfterSniffCheck(SnifferType aType); 221 222 public: /* internal necko use only */ 223 uint32_t GetRequestTime() const { return mRequestTime; } 224 const nsACString& GetLNAPromptAction() const { return mLNAPromptAction; } 225 226 void AsyncOpenFinal(TimeStamp aTimeStamp); 227 228 [[nodiscard]] nsresult OpenCacheEntry(bool isHttps); 229 [[nodiscard]] nsresult OpenCacheEntryInternal(bool isHttps); 230 [[nodiscard]] nsresult ContinueConnect(); 231 232 [[nodiscard]] nsresult StartRedirectChannelToURI(nsIURI*, uint32_t); 233 [[nodiscard]] nsresult StartRedirectChannelToURI( 234 nsIURI*, uint32_t, std::function<void(nsIChannel*)>&&); 235 236 SnifferCategoryType GetSnifferCategoryType() const { 237 return mSnifferCategoryType; 238 } 239 240 // Helper to keep cache callbacks wait flags consistent 241 class AutoCacheWaitFlags { 242 public: 243 explicit AutoCacheWaitFlags(nsHttpChannel* channel) 244 : mChannel(channel), mKeep(0) { 245 // Flags must be set before entering any AsyncOpenCacheEntry call. 246 mChannel->StoreWaitForCacheEntry(nsHttpChannel::WAIT_FOR_CACHE_ENTRY); 247 } 248 249 void Keep(uint32_t flags) { 250 // Called after successful call to appropriate AsyncOpenCacheEntry call. 251 mKeep |= flags; 252 } 253 254 ~AutoCacheWaitFlags() { 255 // Keep only flags those are left to be wait for. 256 mChannel->StoreWaitForCacheEntry(mChannel->LoadWaitForCacheEntry() & 257 mKeep); 258 } 259 260 private: 261 nsHttpChannel* mChannel; 262 uint32_t mKeep : 1; 263 }; 264 265 bool AwaitingCacheCallbacks(); 266 void SetCouldBeSynthesized(); 267 268 // Return true if the latest ODA is invoked by mCachePump. 269 // Should only be called on the same thread as ODA. 270 bool IsReadingFromCache() const { return mIsReadingFromCache; } 271 272 base::ProcessId ProcessId(); 273 274 using ChildEndpointPromise = 275 MozPromise<mozilla::ipc::Endpoint<extensions::PStreamFilterChild>, bool, 276 true>; 277 [[nodiscard]] RefPtr<ChildEndpointPromise> AttachStreamFilter(); 278 279 already_AddRefed<WebTransportSessionEventListener> 280 GetWebTransportSessionEventListener(); 281 282 private: // used for alternate service validation 283 RefPtr<TransactionObserver> mTransactionObserver; 284 285 public: 286 void SetTransactionObserver(TransactionObserver* arg) { 287 mTransactionObserver = arg; 288 } 289 TransactionObserver* GetTransactionObserver() { return mTransactionObserver; } 290 291 CacheDisposition mCacheDisposition{kCacheUnresolved}; 292 293 protected: 294 virtual ~nsHttpChannel(); 295 296 private: 297 using nsContinueRedirectionFunc = nsresult (nsHttpChannel::*)(nsresult); 298 299 // Directly call |aFunc| if the channel is not canceled and not suspended. 300 // Otherwise, set |aFunc| to |mCallOnResume| and wait until the channel 301 // resumes. 302 nsresult CallOrWaitForResume( 303 const std::function<nsresult(nsHttpChannel*)>& aFunc); 304 305 bool RequestIsConditional(); 306 void HandleContinueCancellingByURLClassifier(nsresult aErrorCode); 307 nsresult CancelInternal(nsresult status); 308 void ContinueCancellingByURLClassifier(nsresult aErrorCode); 309 310 // Connections will only be established in this function. 311 // (including DNS prefetch and speculative connection.) 312 void MaybeResolveProxyAndBeginConnect(); 313 void MaybeStartDNSPrefetch(); 314 315 // Based on the proxy configuration determine the strategy for resolving the 316 // end server host name. 317 ProxyDNSStrategy GetProxyDNSStrategy(); 318 319 // Add Sec-Fetch-Storage-Access headers based on cookie partitioning 320 void AddStorageAccessHeadersToRequest(); 321 322 public: 323 // returns whether this channel is a retry after receiving the 324 // "Activate-Storage-Access"-header for a request that is eligable for 325 // unpartitioned cookies. Therefore needs to have still valid 326 // storage-permission granted. Public to be accible from AntiTrackingUtils. 327 bool StorageAccessReloadedChannel(); 328 329 private: 330 // We might synchronously or asynchronously call BeginConnect, 331 // which includes DNS prefetch and speculative connection, according to 332 // whether an async tracker lookup is required. If the tracker lookup 333 // is required, this funciton will just return NS_OK and BeginConnect() 334 // will be called when callback. See Bug 1325054 for more information. 335 nsresult BeginConnect(); 336 [[nodiscard]] nsresult PrepareToConnect(); 337 [[nodiscard]] nsresult ContinuePrepareToConnect(); 338 [[nodiscard]] nsresult OnBeforeConnect(); 339 [[nodiscard]] nsresult ContinueOnBeforeConnect( 340 bool aShouldUpgrade, nsresult aStatus, bool aUpgradeWithHTTPSRR = false); 341 nsresult MaybeUseHTTPSRRForUpgrade(bool aShouldUpgrade, nsresult aStatus); 342 void OnHTTPSRRAvailable(nsIDNSHTTPSSVCRecord* aRecord); 343 [[nodiscard]] nsresult Connect(); 344 void SpeculativeConnect(); 345 [[nodiscard]] nsresult SetupChannelForTransaction(); 346 [[nodiscard]] nsresult InitTransaction(); 347 [[nodiscard]] nsresult DispatchTransaction( 348 HttpTransactionShell* aTransWithStickyConn); 349 [[nodiscard]] nsresult CallOnStartRequest(); 350 [[nodiscard]] nsresult ProcessResponse(nsHttpConnectionInfo* aConnInfo); 351 void AsyncContinueProcessResponse(nsHttpConnectionInfo* aConnInfo); 352 [[nodiscard]] nsresult ContinueProcessResponse1( 353 nsHttpConnectionInfo* aConnInfo); 354 [[nodiscard]] nsresult ContinueProcessResponse2(nsresult); 355 nsresult HandleOverrideResponse(); 356 nsresult OnPermissionPromptResult(bool aGranted, const nsACString& aType); 357 LNAPermission UpdateLocalNetworkAccessPermissions( 358 const nsACString& aPermissionType); 359 void MaybeUpdateDocumentIPAddressSpaceFromCache(); 360 nsresult ProcessLNAActions(); 361 void UpdateCurrentIpAddressSpace(); 362 363 public: 364 void UpdateCacheDisposition(bool aSuccessfulReval, bool aPartialContentUsed); 365 [[nodiscard]] nsresult ContinueProcessResponse3(nsresult); 366 [[nodiscard]] nsresult ContinueProcessResponse4(nsresult); 367 [[nodiscard]] nsresult ProcessNormal(); 368 [[nodiscard]] nsresult ContinueProcessNormal(nsresult); 369 void ProcessAltService(nsHttpConnectionInfo* aTransConnInfo = nullptr); 370 bool ShouldBypassProcessNotModified(); 371 [[nodiscard]] nsresult ProcessNotModified( 372 const std::function<nsresult(nsHttpChannel*, nsresult)>& 373 aContinueProcessResponseFunc); 374 [[nodiscard]] nsresult ContinueProcessResponseAfterNotModified(nsresult aRv); 375 376 [[nodiscard]] nsresult AsyncProcessRedirection(uint32_t redirectType); 377 [[nodiscard]] nsresult ContinueProcessRedirection(nsresult); 378 [[nodiscard]] nsresult ContinueProcessRedirectionAfterFallback(nsresult); 379 [[nodiscard]] nsresult ProcessFailedProxyConnect(uint32_t httpStatus); 380 void HandleAsyncAbort(); 381 [[nodiscard]] nsresult EnsureAssocReq(); 382 void ProcessSSLInformation(); 383 bool IsHTTPS(); 384 385 [[nodiscard]] nsresult ContinueOnStartRequest1(nsresult); 386 [[nodiscard]] nsresult ContinueOnStartRequest2(nsresult); 387 [[nodiscard]] nsresult ContinueOnStartRequest3(nsresult); 388 389 void OnClassOfServiceUpdated(); 390 391 // redirection specific methods 392 void HandleAsyncRedirect(); 393 void HandleAsyncAPIRedirect(); 394 [[nodiscard]] nsresult ContinueHandleAsyncRedirect(nsresult); 395 void HandleAsyncNotModified(); 396 [[nodiscard]] nsresult PromptTempRedirect(); 397 [[nodiscard]] virtual nsresult SetupReplacementChannel( 398 nsIURI*, nsIChannel*, bool preserveMethod, 399 uint32_t redirectFlags) override; 400 void HandleAsyncRedirectToUnstrippedURI(); 401 402 // proxy specific methods 403 [[nodiscard]] nsresult ProxyFailover(); 404 [[nodiscard]] nsresult AsyncDoReplaceWithProxy(nsIProxyInfo*); 405 [[nodiscard]] nsresult ResolveProxy(); 406 407 // cache specific methods 408 [[nodiscard]] nsresult OnNormalCacheEntryAvailable(nsICacheEntry* aEntry, 409 bool aNew, 410 nsresult aEntryStatus); 411 [[nodiscard]] nsresult OnCacheEntryAvailableInternal(nsICacheEntry* entry, 412 bool aNew, 413 nsresult status); 414 [[nodiscard]] nsresult GenerateCacheKey(uint32_t postID, nsACString& key); 415 [[nodiscard]] nsresult UpdateExpirationTime(); 416 [[nodiscard]] nsresult CheckPartial(nsICacheEntry* aEntry, int64_t* aSize, 417 int64_t* aContentLength); 418 [[nodiscard]] nsresult ReadFromCache(void); 419 void CloseCacheEntry(bool doomOnFailure); 420 [[nodiscard]] nsresult InitCacheEntry(); 421 void UpdateInhibitPersistentCachingFlag(); 422 bool ParseDictionary(nsICacheEntry* aEntry, nsHttpResponseHead* aResponseHead, 423 bool aModified); 424 [[nodiscard]] nsresult AddCacheEntryHeaders(nsICacheEntry* entry, 425 bool aModified); 426 [[nodiscard]] nsresult UpdateCacheEntryHeaders(nsICacheEntry* entry, 427 const nsHttpAtom* aAtom); 428 [[nodiscard]] nsresult FinalizeCacheEntry(); 429 [[nodiscard]] nsresult InstallCacheListener(int64_t offset = 0); 430 [[nodiscard]] nsresult DoInstallCacheListener(bool aIsDictionaryCompressed, 431 nsACString* aDictionary, 432 int64_t offset = 0); 433 void MaybeInvalidateCacheEntryForSubsequentGet(); 434 void AsyncOnExamineCachedResponse(); 435 436 // byte range request specific methods 437 [[nodiscard]] nsresult ProcessPartialContent( 438 const std::function<nsresult(nsHttpChannel*, nsresult)>& 439 aContinueProcessResponseFunc); 440 [[nodiscard]] nsresult ContinueProcessResponseAfterPartialContent( 441 nsresult aRv); 442 [[nodiscard]] nsresult OnDoneReadingPartialCacheEntry(bool* streamDone); 443 444 [[nodiscard]] nsresult DoAuthRetry( 445 HttpTransactionShell* aTransWithStickyConn, 446 const std::function<nsresult(nsHttpChannel*, nsresult)>& 447 aContinueOnStopRequestFunc); 448 [[nodiscard]] nsresult ContinueDoAuthRetry( 449 HttpTransactionShell* aTransWithStickyConn, 450 const std::function<nsresult(nsHttpChannel*, nsresult)>& 451 aContinueOnStopRequestFunc); 452 [[nodiscard]] MOZ_NEVER_INLINE nsresult 453 DoConnect(HttpTransactionShell* aTransWithStickyConn = nullptr); 454 [[nodiscard]] nsresult DoConnectActual( 455 HttpTransactionShell* aTransWithStickyConn); 456 [[nodiscard]] nsresult ContinueOnStopRequestAfterAuthRetry( 457 nsresult aStatus, bool aAuthRetry, bool aIsFromNet, bool aContentComplete, 458 HttpTransactionShell* aTransWithStickyConn); 459 [[nodiscard]] nsresult ContinueOnStopRequest(nsresult status, bool aIsFromNet, 460 bool aContentComplete); 461 462 void HandleAsyncRedirectChannelToHttps(); 463 [[nodiscard]] nsresult StartRedirectChannelToHttps(); 464 [[nodiscard]] nsresult ContinueAsyncRedirectChannelToURI(nsresult rv); 465 [[nodiscard]] nsresult OpenRedirectChannel(nsresult rv); 466 467 HttpTrafficCategory CreateTrafficCategory(); 468 469 /** 470 * A function that takes care of reading STS and PKP headers and enforcing 471 * STS and PKP load rules. After a secure channel is erected, STS and PKP 472 * requires the channel to be trusted or any STS or PKP header data on 473 * the channel is ignored. This is called from ProcessResponse. 474 */ 475 [[nodiscard]] nsresult ProcessSecurityHeaders(); 476 477 /** 478 * Taking care of the Content-Signature header and fail the channel if 479 * the signature verification fails or is required but the header is not 480 * present. 481 * This sets mListener to ContentVerifier, which buffers the entire response 482 * before verifying the Content-Signature header. If the verification is 483 * successful, the load proceeds as usual. If the verification fails, a 484 * NS_ERROR_INVALID_SIGNATURE is thrown and a fallback loaded in nsDocShell 485 */ 486 [[nodiscard]] nsresult ProcessContentSignatureHeader( 487 nsHttpResponseHead* aResponseHead); 488 489 /** 490 * A function to process HTTP Strict Transport Security (HSTS) headers. 491 * Some basic consistency checks have been applied to the channel. Called 492 * from ProcessSecurityHeaders. 493 */ 494 [[nodiscard]] nsresult ProcessHSTSHeader(nsITransportSecurityInfo* aSecInfo); 495 496 void InvalidateCacheEntryForLocation(const char* location); 497 void AssembleCacheKey(const char* spec, uint32_t postID, nsACString& key); 498 [[nodiscard]] nsresult CreateNewURI(const char* loc, nsIURI** newURI); 499 void DoInvalidateCacheEntry(nsIURI* aURI); 500 501 // Ref RFC2616 13.10: "invalidation... MUST only be performed if 502 // the host part is the same as in the Request-URI" 503 inline bool HostPartIsTheSame(nsIURI* uri) { 504 nsAutoCString tmpHost1, tmpHost2; 505 return (NS_SUCCEEDED(mURI->GetAsciiHost(tmpHost1)) && 506 NS_SUCCEEDED(uri->GetAsciiHost(tmpHost2)) && 507 (tmpHost1 == tmpHost2)); 508 } 509 510 inline static bool DoNotRender3xxBody(nsresult rv) { 511 return rv == NS_ERROR_REDIRECT_LOOP || rv == NS_ERROR_CORRUPTED_CONTENT || 512 rv == NS_ERROR_UNKNOWN_PROTOCOL || rv == NS_ERROR_MALFORMED_URI || 513 rv == NS_ERROR_PORT_ACCESS_NOT_ALLOWED; 514 } 515 516 // Report telemetry for system principal request success rate 517 void ReportSystemChannelTelemetry(nsresult status); 518 // Report telemetry and stats to about:networking 519 void ReportRcwnStats(bool isFromNet); 520 521 // Create a aggregate set of the current notification callbacks 522 // and ensure the transaction is updated to use it. 523 void UpdateAggregateCallbacks(); 524 525 static bool HasQueryString(nsHttpRequestHead::ParsedMethodType method, 526 nsIURI* uri); 527 bool ResponseWouldVary(nsICacheEntry* entry); 528 bool IsResumable(int64_t partialLen, int64_t contentLength, 529 bool ignoreMissingPartialLen = false) const; 530 [[nodiscard]] nsresult MaybeSetupByteRangeRequest( 531 int64_t partialLen, int64_t contentLength, 532 bool ignoreMissingPartialLen = false); 533 [[nodiscard]] nsresult SetupByteRangeRequest(int64_t partialLen); 534 void UntieByteRangeRequest(); 535 void UntieValidationRequest(); 536 [[nodiscard]] nsresult OpenCacheInputStream(nsICacheEntry* cacheEntry, 537 bool startBuffering); 538 539 void SetOriginHeader(); 540 void SetDoNotTrack(); 541 void SetGlobalPrivacyControl(); 542 543 already_AddRefed<nsChannelClassifier> GetOrCreateChannelClassifier(); 544 545 // Start an internal redirect to a new InterceptedHttpChannel which will 546 // resolve in firing a ServiceWorker FetchEvent. 547 [[nodiscard]] nsresult RedirectToInterceptedChannel(); 548 549 // Start an internal redirect to a new channel for auth retry 550 [[nodiscard]] nsresult RedirectToNewChannelForAuthRetry(); 551 552 // Determines and sets content type in the cache entry. It's called when 553 // writing a new entry. The content type is used in cache internally only. 554 void SetCachedContentType(); 555 556 private: 557 // this section is for main-thread-only object 558 // all the references need to be proxy released on main thread. 559 // auth specific data 560 nsCOMPtr<nsIHttpChannelAuthProvider> mAuthProvider; 561 nsCOMPtr<nsIURI> mRedirectURI; 562 nsCOMPtr<nsIURI> mUnstrippedRedirectURI; 563 nsCOMPtr<nsIChannel> mRedirectChannel; 564 nsCOMPtr<nsIChannel> mPreflightChannel; 565 566 // nsChannelClassifier checks this channel's URI against 567 // the URI classifier service. 568 // nsChannelClassifier will be invoked twice in InitLocalBlockList() and 569 // BeginConnect(), so save the nsChannelClassifier here to keep the 570 // state of whether tracking protection is enabled or not. 571 RefPtr<nsChannelClassifier> mChannelClassifier; 572 573 // Dictionary entry for the entry being used to decompress this stream 574 // (i.e. we added Dictionary-Available to the request). 575 RefPtr<DictionaryCacheEntry> mDictDecompress; 576 // This is for channels we're going to use a dictionaries in the future 577 // (i.e. ResponseHeaders has Use-As-Dictionary) 578 RefPtr<DictionaryCacheEntry> mDictSaving; 579 // Note that in the case of using a file to be a dictionary for future 580 // versions of itself, these may have the same URI (but likely different 581 // hashes). 582 583 // Proxy release all members above on main thread. 584 void ReleaseMainThreadOnlyReferences(); 585 586 // Called after the channel is made aware of its tracking status in order 587 // to readjust the referrer if needed according to the referrer default 588 // policy preferences. 589 void ReEvaluateReferrerAfterTrackingStatusIsKnown(); 590 591 // Create a dummy channel for the same principal, out of the load group 592 // just to revalidate the cache entry. We don't care if this fails. 593 // This method can be called on any thread, and creates an idle task 594 // to perform the revalidation with delay. 595 void PerformBackgroundCacheRevalidation(); 596 // This method can only be called on the main thread. 597 void PerformBackgroundCacheRevalidationNow(); 598 599 void SetPriorityHeader(); 600 601 private: 602 nsCOMPtr<nsICancelable> mProxyRequest; 603 604 nsCOMPtr<nsIRequest> mTransactionPump; 605 RefPtr<HttpTransactionShell> mTransaction; 606 RefPtr<HttpTransactionShell> mTransactionSticky; 607 608 uint64_t mLogicalOffset{0}; 609 610 // cache specific data 611 nsCOMPtr<nsICacheEntry> mCacheEntry; 612 // This will be set during OnStopRequest() before calling CloseCacheEntry(), 613 // but only if the listener wants to use alt-data (signaled by 614 // HttpBaseChannel::mPreferredCachedAltDataType being not empty) 615 // Needed because calling openAlternativeOutputStream needs a reference 616 // to the cache entry. 617 nsCOMPtr<nsICacheEntry> mAltDataCacheEntry; 618 619 nsCOMPtr<nsIURI> mCacheEntryURI; 620 nsCString mCacheIdExtension; 621 622 // We must close mCacheInputStream explicitly to avoid leaks. 623 AutoClose<nsIInputStream> mCacheInputStream; 624 RefPtr<nsInputStreamPump> mCachePump; 625 UniquePtr<nsHttpResponseHead> mCachedResponseHead; 626 nsCOMPtr<nsITransportSecurityInfo> mCachedSecurityInfo; 627 uint32_t mPostID{0}; 628 uint32_t mRequestTime{0}; 629 nsresult mLastTransportStatus{NS_OK}; 630 631 nsTArray<StreamFilterRequest> mStreamFilterRequests; 632 633 mozilla::TimeStamp mOnStartRequestTimestamp; 634 // Timestamp of the time the channel was suspended. 635 mozilla::TimeStamp mSuspendTimestamp; 636 mozilla::TimeStamp mOnCacheEntryCheckTimestamp; 637 638 // Properties used for the profiler markers 639 // This keeps the timestamp for the start marker, to be reused for the end 640 // marker. 641 mozilla::TimeStamp mLastStatusReported; 642 // This is true when one end marker is output, so that we never output more 643 // than one. 644 bool mEndMarkerAdded = false; 645 // Is set to true when the NEL report is queued. 646 bool mReportedNEL = false; 647 648 // Total time the channel spent suspended. This value is reported to 649 // telemetry in nsHttpChannel::OnStartRequest(). 650 TimeDuration mSuspendTotalTime{0}; 651 652 friend class AutoRedirectVetoNotifier; 653 friend class HttpAsyncAborter<nsHttpChannel>; 654 655 uint32_t mRedirectType{0}; 656 657 static const uint32_t WAIT_FOR_CACHE_ENTRY = 1; 658 659 bool mCacheOpenWithPriority{false}; 660 uint32_t mCacheQueueSizeWhenOpen{0}; 661 662 Atomic<bool> mIsAuthChannel{false}; 663 Atomic<bool> mAuthRetryPending{false}; 664 665 // clang-format off 666 // state flags 667 MOZ_ATOMIC_BITFIELDS(mAtomicBitfields5, 32, ( 668 (uint32_t, CachedContentIsPartial, 1), 669 (uint32_t, CacheOnlyMetadata, 1), 670 (uint32_t, TransactionReplaced, 1), 671 (uint32_t, ProxyAuthPending, 1), 672 // Set if before the first authentication attempt a custom authorization 673 // header has been set on the channel. This will make that custom header 674 // go to the server instead of any cached credentials. 675 (uint32_t, CustomAuthHeader, 1), 676 (uint32_t, Resuming, 1), 677 (uint32_t, InitedCacheEntry, 1), 678 // True if consumer added its own If-None-Match or If-Modified-Since 679 // headers. In such a case we must not override them in the cache code 680 // and also we want to pass possible 304 code response through. 681 (uint32_t, CustomConditionalRequest, 1), 682 (uint32_t, WaitingForRedirectCallback, 1), 683 // True if mRequestTime has been set. In such a case it is safe to update 684 // the cache entry's expiration time. Otherwise, it is not(see bug 567360). 685 (uint32_t, RequestTimeInitialized, 1), 686 (uint32_t, CacheEntryIsReadOnly, 1), 687 (uint32_t, CacheEntryIsWriteOnly, 1), 688 // see WAIT_FOR_* constants above 689 (uint32_t, WaitForCacheEntry, 1), 690 // whether cache entry data write was in progress during cache entry check 691 // when true, after we finish read from cache we must check all data 692 // had been loaded from cache. If not, then an error has to be propagated 693 // to the consumer. 694 (uint32_t, ConcurrentCacheAccess, 1), 695 // whether the request is setup be byte-range 696 (uint32_t, IsPartialRequest, 1), 697 // true iff there is AutoRedirectVetoNotifier on the stack 698 (uint32_t, HasAutoRedirectVetoNotifier, 1), 699 // consumers set this to true to use cache pinning, this has effect 700 // only when the channel is in an app context 701 (uint32_t, PinCacheContent, 1), 702 // True if CORS preflight has been performed 703 (uint32_t, IsCorsPreflightDone, 1), 704 705 // if the http transaction was performed (i.e. not cached) and 706 // the result in OnStopRequest was known to be correctly delimited 707 // by chunking, content-length, or h2 end-stream framing 708 (uint32_t, StronglyFramed, 1), 709 710 // true if an HTTP transaction is created for the socket thread 711 (uint32_t, UsedNetwork, 1), 712 713 // the next authentication request can be sent on a whole new connection 714 (uint32_t, AuthConnectionRestartable, 1), 715 716 // True if the channel classifier has marked the channel to be cancelled due 717 // to the safe-browsing classifier rules, but the asynchronous cancellation 718 // process hasn't finished yet. 719 (uint32_t, ChannelClassifierCancellationPending, 1), 720 721 // True only when we are between Resume and async fire of mCallOnResume. 722 // Used to suspend any newly created pumps in mCallOnResume handler. 723 (uint32_t, AsyncResumePending, 1), 724 725 // True if the data will be sent from the socket process to the 726 // content process directly. 727 (uint32_t, DataSentToChildProcess, 1), 728 729 (uint32_t, UseHTTPSSVC, 1), 730 (uint32_t, WaitHTTPSSVCRecord, 1) 731 )) 732 733 // Broken up into two bitfields to avoid alignment requirements of uint64_t. 734 // (Too many bits used for one uint32_t.) 735 MOZ_ATOMIC_BITFIELDS(mAtomicBitfields6, 32, ( 736 // True if network request gets to OnStart before we get a response from the cache 737 (uint32_t, NetworkWonRace, 1), 738 // Valid values are CachedContentValidity::Unset/Invalid/Valid 739 (uint32_t, CachedContentIsValid, 2), 740 // Only set to true when we receive an HTTPSSVC record before the 741 // transaction is created. 742 (uint32_t, HTTPSSVCTelemetryReported, 1), 743 (uint32_t, EchConfigUsed, 1), 744 (uint32_t, AuthRedirectedChannel, 1), 745 (uint32_t, StorageAccessReloadChannel, 1) 746 )) 747 // clang-format on 748 enum CachedContentValidity : uint8_t { Unset = 0, Invalid = 1, Valid = 2 }; 749 750 bool CachedContentIsValid() { 751 return LoadCachedContentIsValid() == CachedContentValidity::Valid; 752 } 753 754 nsTArray<nsContinueRedirectionFunc> mRedirectFuncStack; 755 756 // Needed for accurate DNS timing 757 RefPtr<nsDNSPrefetch> mDNSPrefetch; 758 759 // True if the channel's principal was found on a phishing, malware, or 760 // tracking (if tracking protection is enabled) blocklist 761 bool mLocalBlocklist{false}; 762 763 [[nodiscard]] nsresult WaitForRedirectCallback(); 764 void PushRedirectAsyncFunc(nsContinueRedirectionFunc func); 765 void PopRedirectAsyncFunc(nsContinueRedirectionFunc func); 766 767 // If this resource is eligible for tailing based on class-of-service flags 768 // and load flags. We don't tail Leaders/Unblocked/UrgentStart and 769 // top-level loads. 770 bool EligibleForTailing(); 771 772 // Called exclusively only from AsyncOpen or after all classification 773 // callbacks. If this channel is 1) Tail, 2) assigned a request context, 3) 774 // the context is still in the tail-blocked phase, then the method will 775 // queue this channel. OnTailUnblock will be called after the context is 776 // tail-unblocked or canceled. 777 bool WaitingForTailUnblock(); 778 779 // A function we trigger when untail callback is triggered by our request 780 // context in case this channel was tail-blocked. 781 using TailUnblockCallback = nsresult (nsHttpChannel::*)(); 782 TailUnblockCallback mOnTailUnblock{nullptr}; 783 // Called on untail when tailed during AsyncOpen execution. 784 nsresult AsyncOpenOnTailUnblock(); 785 // Called on untail when tailed because of being a tracking resource. 786 nsresult ConnectOnTailUnblock(); 787 788 nsCString mUsername; 789 790 // If non-null, warnings should be reported to this object. 791 RefPtr<HttpChannelSecurityWarningReporter> mWarningReporter; 792 793 // True if the channel is reading from cache. 794 Atomic<bool> mIsReadingFromCache{false}; 795 796 // nsITimerCallback is implemented on a subclass so that the name attribute 797 // doesn't conflict with the name attribute of the nsIRequest interface that 798 // might be present on the same object (as seen from JavaScript code). 799 class TimerCallback final : public nsITimerCallback, public nsINamed { 800 public: 801 NS_DECL_ISUPPORTS 802 NS_DECL_NSITIMERCALLBACK 803 NS_DECL_NSINAMED 804 805 explicit TimerCallback(nsHttpChannel* aChannel); 806 807 private: 808 ~TimerCallback() = default; 809 810 RefPtr<nsHttpChannel> mChannel; 811 }; 812 813 // These next members are only used in unit tests to delay the call to 814 // cache->AsyncOpenURI in order to race the cache with the network. 815 nsCOMPtr<nsITimer> mCacheOpenTimer; 816 std::function<void(nsHttpChannel*)> mCacheOpenFunc; 817 uint32_t mCacheOpenDelay = 0; 818 uint32_t mNetworkTriggerDelay = 0; 819 820 // We need to remember which is the source of the response we are using. 821 enum ResponseSource { 822 RESPONSE_PENDING = 0, // response is pending 823 RESPONSE_FROM_CACHE = 1, // response coming from cache. no network. 824 RESPONSE_FROM_NETWORK = 2 // response coming from the network 825 }; 826 Atomic<ResponseSource, Relaxed> mFirstResponseSource{RESPONSE_PENDING}; 827 828 // Determines if it's possible and advisable to race the network request 829 // with the cache fetch, and proceeds to do so. 830 void MaybeRaceCacheWithNetwork(); 831 832 // Creates a new cache entry when network wins the race to ensure we have 833 // the latest version of the resource in the cache. Otherwise we might 834 // return an old content when navigating back in history. 835 void MaybeCreateCacheEntryWhenRCWN(); 836 837 nsresult TriggerNetworkWithDelay(uint32_t aDelay); 838 nsresult TriggerNetwork(); 839 nsresult OnSuspendTimeout(); 840 void CancelNetworkRequest(nsresult aStatus); 841 842 nsresult LogConsoleError(const char* aTag); 843 844 void SetHTTPSSVCRecord(already_AddRefed<nsIDNSHTTPSSVCRecord>&& aRecord); 845 846 void RecordOnStartTelemetry(nsresult aStatus, bool aIsNavigation); 847 848 void MaybeGenerateNELReport(); 849 850 // Timer used to delay the network request, or to trigger the network 851 // request if retrieving the cache entry takes too long. 852 nsCOMPtr<nsITimer> mNetworkTriggerTimer; 853 // Is true if the network request has been triggered. 854 bool mNetworkTriggered = false; 855 856 // Timer to detect if channel has been suspended too long while writing to 857 // cache. When the timer fires we'll notify the cache entry to make 858 // all other listeners continue. 859 nsCOMPtr<nsITimer> mSuspendTimer; 860 bool mWritingToCache = false; 861 bool mWaitingForProxy = false; 862 bool mStaleRevalidation = false; 863 // Will be true if the onCacheEntryAvailable callback is not called by the 864 // time we send the network request 865 Atomic<bool> mRaceCacheWithNetwork{false}; 866 uint32_t mRaceDelay{0}; 867 // If true then OnCacheEntryAvailable should ignore the entry, because 868 // SetupTransaction removed conditional headers and decisions made in 869 // OnCacheEntryCheck are no longer valid. 870 bool mIgnoreCacheEntry{false}; 871 bool mAllowRCWN{true}; 872 // Lock preventing SetupTransaction/MaybeCreateCacheEntryWhenRCWN and 873 // OnCacheEntryCheck being called at the same time. 874 mozilla::Mutex mRCWNLock MOZ_UNANNOTATED{"nsHttpChannel.mRCWNLock"}; 875 876 // Set to true when OnSuspendTimeout calls SetBypassWriterLock(true) 877 // for the cache entry. Gets reset back to false when Resume calls 878 // SetBypassWriterLock(false) 879 bool mBypassCacheWriterSet{false}; 880 881 TimeStamp mNavigationStartTimeStamp; 882 883 // Promise that blocks connection creation when we want to resolve the 884 // origin host name to be able to give the configured proxy only the 885 // resolved IP to not leak names. 886 MozPromiseHolder<DNSPromise> mDNSBlockingPromise; 887 // When we hit DoConnect before the resolution is done, Then() will be set 888 // here to resume DoConnect. 889 RefPtr<DNSPromise> mDNSBlockingThenable; 890 891 // We update the value of mProxyConnectResponseCode when OnStartRequest is 892 // called and reset the value when we switch to another failover proxy. 893 int32_t mProxyConnectResponseCode{0}; 894 895 // If mHTTPSSVCRecord has value, it means OnHTTPSRRAvailable() is called and 896 // we got the result of HTTPS RR query. Otherwise, it means we are still 897 // waiting for the result or the query is not performed. 898 Maybe<nsCOMPtr<nsIDNSHTTPSSVCRecord>> mHTTPSSVCRecord; 899 900 enum class EssentialDomainCategory { 901 SubAddonsMozillaOrg, 902 AddonsMozillaOrg, 903 Aus5MozillaOrg, 904 RemoteSettings, 905 Telemetry, 906 Other, 907 }; 908 909 // When an essential domain request gets retried this variable is set on the 910 // redirected channel. This is important so we can track the success 911 // rates of retried channels to the fallback domain. 912 Maybe<EssentialDomainCategory> mEssentialDomainCategory; 913 static EssentialDomainCategory GetEssentialDomainCategory(nsCString& domain); 914 915 // Permissions for the request to make local network access 916 LNAPerms mLNAPermission{}; 917 918 // Track if we are waiting for OnPermissionPromptResult callback 919 // Used to handle cancellation while suspended waiting for LNA permission 920 bool mWaitingForLNAPermission{false}; 921 922 bool mUsingDictionary{false}; // we added Available-Dictionary 923 bool mShouldSuspendForDictionary{false}; 924 bool mSuspendedForDictionary{false}; 925 926 protected: 927 virtual void DoNotifyListenerCleanup() override; 928 929 // Override ReleaseListeners() because mChannelClassifier only exists 930 // in nsHttpChannel and it will be released in ReleaseListeners(). 931 virtual void ReleaseListeners() override; 932 933 virtual void DoAsyncAbort(nsresult aStatus) override; 934 935 private: // cache telemetry 936 bool mDidReval{false}; 937 938 RefPtr<nsIEarlyHintObserver> mEarlyHintObserver; 939 Maybe<nsCString> mOpenerCallingScriptLocation; 940 RefPtr<WebTransportSessionEventListener> mWebTransportSessionEventListener; 941 nsMainThreadPtrHandle<nsIReplacedHttpResponse> mOverrideResponse; 942 // LNA telemetry: stores the user's action on the permission prompt 943 // Values: "allow", "deny", or empty string (no prompt shown) 944 nsCString mLNAPromptAction; 945 }; 946 947 } // namespace net 948 } // namespace mozilla 949 950 inline nsISupports* ToSupports(mozilla::net::nsHttpChannel* aChannel) { 951 return static_cast<nsIHttpChannel*>(aChannel); 952 } 953 954 #endif // nsHttpChannel_h__