/* 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_cache_BackgroundStorageKey_h #define mozilla_dom_cache_BackgroundStorageKey_h #include "BoundStorageKeyChild.h" #include "ErrorList.h" #include "mozilla/MozPromise.h" #include "mozilla/dom/cache/CacheTypes.h" #include "mozilla/dom/cache/TypeUtils.h" namespace mozilla { namespace ipc { class PrincipalInfo; class PBackgroundChild; } // namespace ipc namespace dom { class Response; namespace cache { extern bool IsTrusted(const ::mozilla::ipc::PrincipalInfo& aPrincipalInfo, bool aTestingPrefEnabled); class CacheStorageChild; class BoundStorageKeyCache; using mozilla::ipc::PrincipalInfo; /* BoundStorageKey ipdl would be used to work with all storage APIs * between child and parent process. BoundStorageKey is a generic * base class and represents all respective derived storage classes. * BoundStorageKeyCacheStorage below is one such class which deals with * cachestorage and like this, there could be more in the future like * BoundStorageKeyIDB for IndexedDB, etc. * * TODO: it might be worth moving BoundStorageKey protocol definition, * implementation into separate directory while more derived implementations * could be under their respective storage directories like dom/cache for * BoundStorageKeyCacheStorage. */ class BoundStorageKey : public nsISupports, public BoundStorageKeyChildListener { public: using PBackgroundChild = ::mozilla::ipc::PBackgroundChild; NS_DECL_ISUPPORTS BoundStorageKey() : mActor(nullptr), mStatus(NS_OK) {} // Overrides Listener methods and are called by // BoundStorageKeyChild and CacheStorageChild void OnActorDestroy(BoundStorageKeyChild* aActor) override; protected: virtual ~BoundStorageKey(); // Initialization is performed here i.e. // 1. Child and parent actors are setup and connection is attempted. // 2. EventTarget has been retargetted to aTarget nsresult Init(Namespace aNamespace, const PrincipalInfo& aPrincipalInfo, nsISerialEventTarget* aTarget = GetCurrentSerialEventTarget()); RefPtr mActor; nsresult mStatus; }; using CacheStoragePromise = MozPromiseBase; using OpenResultPromise = mozilla::MozPromise, ErrorResult, true /*IsExclusive=*/>; using DeleteResultPromise = mozilla::MozPromise; using HasResultPromise = mozilla::MozPromise; using KeysResultPromise = mozilla::MozPromise, ErrorResult, true /* IsExclusive= */>; using MatchResultPromise = mozilla::MozPromise, ErrorResult, true /* IsExclusive= */>; /* This class exposes Cache APIs to be used by internal clients and is currently * used by service workers when performing a lookup for cache'd scripts. This is * intended to be used by internal clients only and is in contrast with * CacheStorage which is used by internal and JS clients; though comparatively, * internal clients would find it easier to work with this class. There are two * major differences between the two: * 1. APIs in CacheStorage return JS promise whereas this class return * MozPromise * 2. Even though both classes uses same underlying actors but actor used here * gets spun off of top-level actor, BoundStorageKeyChild which could be * retargetted to any event target. * TODO: Since we have two implementations now; this class and CacheStorage with * almost similar responsibilities; it maybe worth exploring to consolidate * both. */ class BoundStorageKeyCacheStorage final : public BoundStorageKey, public TypeUtils, public CacheStorageChildListener { public: static already_AddRefed Create( Namespace aNamespace, nsIGlobalObject* aGlobal, WorkerPrivate* aWorkerPrivate, nsISerialEventTarget* aActorTarget, ErrorResult& aRv); #ifdef DEBUG void AssertOwningThread() const override { NS_ASSERT_OWNINGTHREAD(BoundStorageKey); } #else inline void AssertOwningThread() const {} #endif nsresult Init(WorkerPrivate* aWorkerPrivate, Namespace aNamespace, const PrincipalInfo& aPrincipalInfo, nsISerialEventTarget* aTarget = GetCurrentSerialEventTarget()); // Below methods declares the APIs that this class exposes, which looks // similar to CacheStorage but return type is different already_AddRefed Match( JSContext* aCx, const RequestOrUTF8String& aRequest, const MultiCacheQueryOptions& aOptions, ErrorResult& aRv); already_AddRefed Has(const nsAString& aKey, ErrorResult& aRv); already_AddRefed Open(const nsAString& aKey, ErrorResult& aRv); already_AddRefed Delete(const nsAString& aKey, ErrorResult& aRv); already_AddRefed Keys(ErrorResult& aRv); nsIGlobalObject* GetGlobalObject() const override { return mGlobal; } // explicitly exposing below OnActorDestroy to avoid cpp name hidiing using BoundStorageKey::OnActorDestroy; // called by associated CacheStorageChild actor during destruction. void OnActorDestroy(CacheStorageChild* aActor) override; private: template struct Entry; BoundStorageKeyCacheStorage( Namespace aNamespace, nsIGlobalObject* aGlobal, const mozilla::ipc::PrincipalInfo& aPrincipalInfo); already_AddRefed CreateCacheStorageChild( WorkerPrivate* aWorkerPrivate); ~BoundStorageKeyCacheStorage() override; template void RunRequest(EntryType&& aEntry); RefPtr mCacheStorageChild; nsCOMPtr mGlobal; const UniquePtr mPrincipalInfo; const Namespace mNamespace; }; } // namespace cache template struct cachestorage_traits; template <> struct cachestorage_traits< dom::cache::CacheOpResult::Type::TStorageMatchResult> { using PromiseType = cache::MatchResultPromise::Private; }; template <> struct cachestorage_traits { using PromiseType = cache::HasResultPromise::Private; }; template <> struct cachestorage_traits< dom::cache::CacheOpResult::Type::TStorageOpenResult> { using PromiseType = cache::OpenResultPromise::Private; }; template <> struct cachestorage_traits< dom::cache::CacheOpResult::Type::TStorageDeleteResult> { using PromiseType = cache::DeleteResultPromise::Private; }; template <> struct cachestorage_traits< dom::cache::CacheOpResult::Type::TStorageKeysResult> { using PromiseType = cache::KeysResultPromise::Private; }; template <> struct cachestorage_traits { // Tvoid_t is only used to report errors, Resolve value doesn't matter much // here. Just using HasResultPromise has it has simple Resolve value using PromiseType = cache::HasResultPromise::Private; }; } // namespace dom } // namespace mozilla #endif // mozilla_dom_cache_BackgroundStorageKey_h