diff options
Diffstat (limited to 'dom/fetch/FetchService.h')
-rw-r--r-- | dom/fetch/FetchService.h | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/dom/fetch/FetchService.h b/dom/fetch/FetchService.h new file mode 100644 index 0000000000..3032c4d2a9 --- /dev/null +++ b/dom/fetch/FetchService.h @@ -0,0 +1,186 @@ +/* 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<InternalResponse>; +using FetchServiceResponseAvailablePromise = + MozPromise<FetchServiceResponse, CopyableErrorResult, true>; +using FetchServiceResponseTimingPromise = + MozPromise<ResponseTiming, CopyableErrorResult, true>; +using FetchServiceResponseEndPromise = + MozPromise<ResponseEndArgs, CopyableErrorResult, true>; + +class FetchServicePromises final { + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FetchServicePromises); + + public: + FetchServicePromises(); + + RefPtr<FetchServiceResponseAvailablePromise> GetResponseAvailablePromise(); + RefPtr<FetchServiceResponseTimingPromise> GetResponseTimingPromise(); + RefPtr<FetchServiceResponseEndPromise> 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<FetchServiceResponseAvailablePromise::Private> mAvailablePromise; + RefPtr<FetchServiceResponseTimingPromise::Private> mTimingPromise; + RefPtr<FetchServiceResponseEndPromise::Private> 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<InternalRequest> mRequest; + nsCOMPtr<nsIChannel> mChannel; + }; + + struct WorkerFetchArgs { + SafeRefPtr<InternalRequest> mRequest; + mozilla::ipc::PrincipalInfo mPrincipalInfo; + nsCString mWorkerScript; + Maybe<ClientInfo> mClientInfo; + Maybe<ServiceWorkerDescriptor> mController; + Maybe<net::CookieJarSettingsArgs> mCookieJarSettings; + bool mNeedOnDataAvailable; + nsCOMPtr<nsICSPEventListener> mCSPEventListener; + uint64_t mAssociatedBrowsingContextID; + nsCOMPtr<nsISerialEventTarget> mEventTarget; + nsID mActorID; + }; + + struct UnknownArgs {}; + + using FetchArgs = + Variant<NavigationPreloadArgs, WorkerFetchArgs, UnknownArgs>; + + static already_AddRefed<FetchService> GetInstance(); + + static RefPtr<FetchServicePromises> NetworkErrorResponse(nsresult aRv); + + FetchService(); + + // This method creates a FetchInstance to trigger fetch. + // The created FetchInstance is saved in mFetchInstanceTable + RefPtr<FetchServicePromises> Fetch(FetchArgs&& aArgs); + + void CancelFetch(const RefPtr<FetchServicePromises>&& 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<FetchInstance> fetch = MakeRefPtr<FetchInstance>(); + * fetch->Initialize(FetchArgs args); + * RefPtr<FetchServicePromises> fetch->Fetch(); + */ + class FetchInstance final : public FetchDriverObserver { + public: + FetchInstance() = default; + + nsresult Initialize(FetchArgs&& aArgs); + + RefPtr<FetchServicePromises> Fetch(); + + void Cancel(); + + /* FetchDriverObserver interface */ + void OnResponseEnd(FetchDriverObserver::EndReason aReason, + JS::Handle<JS::Value> aReasonDetails) override; + void OnResponseAvailableInternal( + SafeRefPtr<InternalResponse> aResponse) override; + bool NeedOnDataAvailable() override; + void OnDataAvailable() override; + void FlushConsoleReport() override; + void OnReportPerformanceTiming() override; + void OnNotifyNetworkMonitorAlternateStack(uint64_t aChannelID) override; + + private: + ~FetchInstance() = default; + + SafeRefPtr<InternalRequest> mRequest; + nsCOMPtr<nsIPrincipal> mPrincipal; + nsCOMPtr<nsILoadGroup> mLoadGroup; + nsCOMPtr<nsICookieJarSettings> mCookieJarSettings; + RefPtr<PerformanceStorage> mPerformanceStorage; + FetchArgs mArgs{AsVariant(FetchService::UnknownArgs())}; + RefPtr<FetchDriver> mFetchDriver; + SafeRefPtr<InternalResponse> mResponse; + RefPtr<FetchServicePromises> mPromises; + bool mIsWorkerFetch{false}; + }; + + ~FetchService(); + + nsresult RegisterNetworkObserver(); + nsresult UnregisterNetworkObserver(); + + // This is a container to manage the generated fetches. + nsTHashMap<nsRefPtrHashKey<FetchServicePromises>, RefPtr<FetchInstance> > + mFetchInstanceTable; + bool mObservingNetwork{false}; + bool mOffline{false}; +}; + +} // namespace mozilla::dom + +#endif // _mozilla_dom_FetchService_h |