From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- dom/fetch/FetchDriver.h | 232 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 dom/fetch/FetchDriver.h (limited to 'dom/fetch/FetchDriver.h') diff --git a/dom/fetch/FetchDriver.h b/dom/fetch/FetchDriver.h new file mode 100644 index 0000000000..84391ef951 --- /dev/null +++ b/dom/fetch/FetchDriver.h @@ -0,0 +1,232 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_FetchDriver_h +#define mozilla_dom_FetchDriver_h + +#include "nsIChannelEventSink.h" +#include "nsIInterfaceRequestor.h" +#include "nsINetworkInterceptController.h" +#include "nsIStreamListener.h" +#include "nsIThreadRetargetableStreamListener.h" +#include "mozilla/ConsoleReportCollector.h" +#include "mozilla/dom/AbortSignal.h" +#include "mozilla/dom/SafeRefPtr.h" +#include "mozilla/dom/SerializedStackHolder.h" +#include "mozilla/dom/SRIMetadata.h" +#include "mozilla/RefPtr.h" +#include "mozilla/UniquePtr.h" + +#include "mozilla/DebugOnly.h" + +class nsIConsoleReportCollector; +class nsICookieJarSettings; +class nsICSPEventListener; +class nsIEventTarget; +class nsIOutputStream; +class nsILoadGroup; +class nsIPrincipal; + +namespace mozilla { +class PreloaderBase; + +namespace dom { + +class Document; +class InternalRequest; +class InternalResponse; +class PerformanceStorage; +class PerformanceTimingData; + +/** + * Provides callbacks to be called when response is available or on error. + * Implemenations usually resolve or reject the promise returned from fetch(). + * The callbacks can be called synchronously or asynchronously from + * FetchDriver::Fetch. + */ +class FetchDriverObserver { + public: + FetchDriverObserver() + : mReporter(new ConsoleReportCollector()), mGotResponseAvailable(false) {} + + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FetchDriverObserver); + void OnResponseAvailable(SafeRefPtr aResponse); + + enum EndReason { + eAborted, + eByNetworking, + }; + + virtual void OnResponseEnd(EndReason aReason, + JS::Handle aReasonDetails){}; + + nsIConsoleReportCollector* GetReporter() const { return mReporter; } + + virtual void FlushConsoleReport() = 0; + + // Called in OnStartRequest() to determine if the OnDataAvailable() method + // needs to be called. Invoking that method may generate additional main + // thread runnables. + virtual bool NeedOnDataAvailable() = 0; + + // Called once when the first byte of data is received iff + // NeedOnDataAvailable() returned true when called in OnStartRequest(). + virtual void OnDataAvailable() = 0; + + virtual void OnReportPerformanceTiming() {} + + virtual void OnNotifyNetworkMonitorAlternateStack(uint64_t aChannelID) {} + + protected: + virtual ~FetchDriverObserver() = default; + + virtual void OnResponseAvailableInternal( + SafeRefPtr aResponse) = 0; + + nsCOMPtr mReporter; + + private: + bool mGotResponseAvailable; +}; + +class AlternativeDataStreamListener; + +class FetchDriver final : public nsIStreamListener, + public nsIChannelEventSink, + public nsIInterfaceRequestor, + public nsINetworkInterceptController, + public nsIThreadRetargetableStreamListener, + public AbortFollower { + public: + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSIREQUESTOBSERVER + NS_DECL_NSISTREAMLISTENER + NS_DECL_NSICHANNELEVENTSINK + NS_DECL_NSIINTERFACEREQUESTOR + NS_DECL_NSINETWORKINTERCEPTCONTROLLER + NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER + + FetchDriver(SafeRefPtr aRequest, nsIPrincipal* aPrincipal, + nsILoadGroup* aLoadGroup, nsIEventTarget* aMainThreadEventTarget, + nsICookieJarSettings* aCookieJarSettings, + PerformanceStorage* aPerformanceStorage, bool aIsTrackingFetch); + + nsresult Fetch(AbortSignalImpl* aSignalImpl, FetchDriverObserver* aObserver); + + void SetDocument(Document* aDocument); + + void SetCSPEventListener(nsICSPEventListener* aCSPEventListener); + + void SetClientInfo(const ClientInfo& aClientInfo); + + void SetController(const Maybe& aController); + + void SetWorkerScript(const nsACString& aWorkerScript) { + MOZ_ASSERT(!aWorkerScript.IsEmpty()); + mWorkerScript = aWorkerScript; + } + + void SetOriginStack(UniquePtr&& aOriginStack) { + mOriginStack = std::move(aOriginStack); + } + + PerformanceTimingData* GetPerformanceTimingData(nsAString& aInitiatorType, + nsAString& aEntryName); + + // AbortFollower + void RunAbortAlgorithm() override; + void FetchDriverAbortActions(AbortSignalImpl* aSignalImpl); + + void EnableNetworkInterceptControl(); + + void SetAssociatedBrowsingContextID(uint64_t aID) { + mAssociatedBrowsingContextID = aID; + } + + private: + nsCOMPtr mPrincipal; + nsCOMPtr mLoadGroup; + SafeRefPtr mRequest; + SafeRefPtr mResponse; + nsCOMPtr mPipeOutputStream; + // Access to mObserver can be racy from OnDataAvailable and + // FetchAbortActions. This must not be modified + // in either of these functions. + RefPtr mObserver; + RefPtr mDocument; + nsCOMPtr mCSPEventListener; + Maybe mClientInfo; + Maybe mController; + nsCOMPtr mChannel; + UniquePtr mSRIDataVerifier; + nsCOMPtr mMainThreadEventTarget; + + nsCOMPtr mCookieJarSettings; + + // This is set only when Fetch is used in workers. + RefPtr mPerformanceStorage; + + SRIMetadata mSRIMetadata; + nsCString mWorkerScript; + UniquePtr mOriginStack; + + // This is written once in OnStartRequest on the main thread and then + // written/read in OnDataAvailable() on any thread. Necko guarantees + // that these do not overlap. + bool mNeedToObserveOnDataAvailable; + + bool mIsTrackingFetch; + + RefPtr mAltDataListener; + bool mOnStopRequestCalled; + + // This flag is true when this fetch has found a matching preload and is being + // satisfied by a its response. + bool mFromPreload = false; + // This flag is set in call to Abort() and spans the possible window this + // fetch doesn't have mChannel (to be cancelled) between reuse of the matching + // preload, that has already finished and dropped reference to its channel, + // and OnStartRequest notification. It let's us cancel the load when we get + // the channel in OnStartRequest. + bool mAborted = false; + +#ifdef DEBUG + bool mResponseAvailableCalled; + bool mFetchCalled; +#endif + nsCOMPtr mInterceptController; + + uint64_t mAssociatedBrowsingContextID{0}; + + friend class AlternativeDataStreamListener; + + FetchDriver() = delete; + FetchDriver(const FetchDriver&) = delete; + FetchDriver& operator=(const FetchDriver&) = delete; + ~FetchDriver(); + + already_AddRefed FindPreload(nsIURI* aURI); + + void UpdateReferrerInfoFromNewChannel(nsIChannel* aChannel); + + nsresult HttpFetch(const nsACString& aPreferredAlternativeDataType = ""_ns); + // Returns the filtered response sent to the observer. + SafeRefPtr BeginAndGetFilteredResponse( + SafeRefPtr aResponse, bool aFoundOpaqueRedirect); + // Utility since not all cases need to do any post processing of the filtered + // response. + void FailWithNetworkError(nsresult rv); + + void SetRequestHeaders(nsIHttpChannel* aChannel, bool aStripRequestBodyHeader, + bool aStripAuthHeader) const; + + void FinishOnStopRequest(AlternativeDataStreamListener* aAltDataListener); +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_FetchDriver_h -- cgit v1.2.3