/* 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_FetchService_h #define _mozilla_dom_FetchService_h #include "nsIChannel.h" #include "nsIObserver.h" #include "nsTHashMap.h" #include "mozilla/ErrorResult.h" #include "mozilla/MozPromise.h" #include "mozilla/RefPtr.h" #include "mozilla/dom/FetchDriver.h" #include "mozilla/dom/FetchTypes.h" #include "mozilla/dom/PerformanceTimingTypes.h" #include "mozilla/dom/SafeRefPtr.h" #include "mozilla/ipc/PBackgroundSharedTypes.h" #include "mozilla/net/NeckoChannelParams.h" class nsILoadGroup; class nsIPrincipal; class nsICookieJarSettings; class PerformanceStorage; namespace mozilla::dom { class InternalRequest; class InternalResponse; class ClientInfo; class ServiceWorkerDescriptor; using FetchServiceResponse = SafeRefPtr; using FetchServiceResponseAvailablePromise = MozPromise; using FetchServiceResponseTimingPromise = MozPromise; using FetchServiceResponseEndPromise = MozPromise; class FetchServicePromises final { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FetchServicePromises); public: FetchServicePromises(); RefPtr GetResponseAvailablePromise(); RefPtr GetResponseTimingPromise(); RefPtr GetResponseEndPromise(); void ResolveResponseAvailablePromise(FetchServiceResponse&& aResponse, const char* aMethodName); void RejectResponseAvailablePromise(const CopyableErrorResult&& aError, const char* aMethodName); void ResolveResponseTimingPromise(ResponseTiming&& aTiming, const char* aMethodName); void RejectResponseTimingPromise(const CopyableErrorResult&& aError, const char* aMethodName); void ResolveResponseEndPromise(ResponseEndArgs&& aArgs, const char* aMethodName); void RejectResponseEndPromise(const CopyableErrorResult&& aError, const char* aMethodName); private: ~FetchServicePromises() = default; RefPtr mAvailablePromise; RefPtr mTimingPromise; RefPtr mEndPromise; }; /** * FetchService is a singleton object which designed to be used in parent * process main thread only. It is used to handle the special fetch requests * from ServiceWorkers(by Navigation Preload) and PFetch. * * FetchService creates FetchInstance internally to represent each Fetch * request. It supports an asynchronous fetching, FetchServicePromises is * created when a Fetch starts, once the response is ready or any error happens, * the FetchServicePromises would be resolved or rejected. The promises * consumers can set callbacks to handle the Fetch result. */ class FetchService final : public nsIObserver { public: NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER struct NavigationPreloadArgs { SafeRefPtr mRequest; nsCOMPtr mChannel; }; struct WorkerFetchArgs { SafeRefPtr mRequest; mozilla::ipc::PrincipalInfo mPrincipalInfo; nsCString mWorkerScript; Maybe mClientInfo; Maybe mController; Maybe mCookieJarSettings; bool mNeedOnDataAvailable; nsCOMPtr mCSPEventListener; uint64_t mAssociatedBrowsingContextID; nsCOMPtr mEventTarget; nsID mActorID; }; struct UnknownArgs {}; using FetchArgs = Variant; static already_AddRefed GetInstance(); static RefPtr NetworkErrorResponse(nsresult aRv); FetchService(); // This method creates a FetchInstance to trigger fetch. // The created FetchInstance is saved in mFetchInstanceTable RefPtr Fetch(FetchArgs&& aArgs); void CancelFetch(const RefPtr&& aPromises); private: /** * FetchInstance is an internal representation for each Fetch created by * FetchService. * FetchInstance is also a FetchDriverObserver which has responsibility to * resolve/reject the FetchServicePromises. * FetchInstance triggers fetch by instancing a FetchDriver with proper * initialization. The general usage flow of FetchInstance is as follows * * RefPtr fetch = MakeRefPtr(); * fetch->Initialize(FetchArgs args); * RefPtr fetch->Fetch(); */ class FetchInstance final : public FetchDriverObserver { public: FetchInstance() = default; nsresult Initialize(FetchArgs&& aArgs); RefPtr Fetch(); void Cancel(); /* FetchDriverObserver interface */ void OnResponseEnd(FetchDriverObserver::EndReason aReason, JS::Handle aReasonDetails) override; void OnResponseAvailableInternal( SafeRefPtr aResponse) override; bool NeedOnDataAvailable() override; void OnDataAvailable() override; void FlushConsoleReport() override; void OnReportPerformanceTiming() override; void OnNotifyNetworkMonitorAlternateStack(uint64_t aChannelID) override; private: ~FetchInstance() = default; SafeRefPtr mRequest; nsCOMPtr mPrincipal; nsCOMPtr mLoadGroup; nsCOMPtr mCookieJarSettings; RefPtr mPerformanceStorage; FetchArgs mArgs{AsVariant(FetchService::UnknownArgs())}; RefPtr mFetchDriver; SafeRefPtr mResponse; RefPtr mPromises; bool mIsWorkerFetch{false}; }; ~FetchService(); nsresult RegisterNetworkObserver(); nsresult UnregisterNetworkObserver(); // This is a container to manage the generated fetches. nsTHashMap, RefPtr > mFetchInstanceTable; bool mObservingNetwork{false}; bool mOffline{false}; }; } // namespace mozilla::dom #endif // _mozilla_dom_FetchService_h