BoundStorageKey.h (7734B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 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 mozilla_dom_cache_BackgroundStorageKey_h 8 #define mozilla_dom_cache_BackgroundStorageKey_h 9 10 #include "BoundStorageKeyChild.h" 11 #include "ErrorList.h" 12 #include "mozilla/MozPromise.h" 13 #include "mozilla/dom/cache/CacheTypes.h" 14 #include "mozilla/dom/cache/TypeUtils.h" 15 16 namespace mozilla { 17 namespace ipc { 18 class PrincipalInfo; 19 class PBackgroundChild; 20 } // namespace ipc 21 22 namespace dom { 23 class Response; 24 25 namespace cache { 26 extern bool IsTrusted(const ::mozilla::ipc::PrincipalInfo& aPrincipalInfo, 27 bool aTestingPrefEnabled); 28 class CacheStorageChild; 29 class BoundStorageKeyCache; 30 31 using mozilla::ipc::PrincipalInfo; 32 33 /* BoundStorageKey ipdl would be used to work with all storage APIs 34 * between child and parent process. BoundStorageKey is a generic 35 * base class and represents all respective derived storage classes. 36 * BoundStorageKeyCacheStorage below is one such class which deals with 37 * cachestorage and like this, there could be more in the future like 38 * BoundStorageKeyIDB for IndexedDB, etc. 39 * 40 * TODO: it might be worth moving BoundStorageKey protocol definition, 41 * implementation into separate directory while more derived implementations 42 * could be under their respective storage directories like dom/cache for 43 * BoundStorageKeyCacheStorage. 44 */ 45 class BoundStorageKey : public nsISupports, 46 public BoundStorageKeyChildListener { 47 public: 48 using PBackgroundChild = ::mozilla::ipc::PBackgroundChild; 49 50 NS_DECL_ISUPPORTS 51 BoundStorageKey() : mActor(nullptr), mStatus(NS_OK) {} 52 53 // Overrides Listener methods and are called by 54 // BoundStorageKeyChild and CacheStorageChild 55 void OnActorDestroy(BoundStorageKeyChild* aActor) override; 56 57 protected: 58 virtual ~BoundStorageKey(); 59 60 // Initialization is performed here i.e. 61 // 1. Child and parent actors are setup and connection is attempted. 62 // 2. EventTarget has been retargetted to aTarget 63 nsresult Init(Namespace aNamespace, const PrincipalInfo& aPrincipalInfo, 64 nsISerialEventTarget* aTarget = GetCurrentSerialEventTarget()); 65 66 RefPtr<BoundStorageKeyChild> mActor; 67 nsresult mStatus; 68 }; 69 70 using CacheStoragePromise = MozPromiseBase; 71 using OpenResultPromise = 72 mozilla::MozPromise<RefPtr<BoundStorageKeyCache>, ErrorResult, 73 true /*IsExclusive=*/>; 74 using DeleteResultPromise = 75 mozilla::MozPromise<bool, ErrorResult, true /* IsExclusive= */>; 76 using HasResultPromise = 77 mozilla::MozPromise<bool, ErrorResult, true /* IsExclusive= */>; 78 using KeysResultPromise = 79 mozilla::MozPromise<CopyableTArray<nsString>, ErrorResult, 80 true /* IsExclusive= */>; 81 using MatchResultPromise = 82 mozilla::MozPromise<RefPtr<Response>, ErrorResult, true /* IsExclusive= */>; 83 84 /* This class exposes Cache APIs to be used by internal clients and is currently 85 * used by service workers when performing a lookup for cache'd scripts. This is 86 * intended to be used by internal clients only and is in contrast with 87 * CacheStorage which is used by internal and JS clients; though comparatively, 88 * internal clients would find it easier to work with this class. There are two 89 * major differences between the two: 90 * 1. APIs in CacheStorage return JS promise whereas this class return 91 * MozPromise 92 * 2. Even though both classes uses same underlying actors but actor used here 93 * gets spun off of top-level actor, BoundStorageKeyChild which could be 94 * retargetted to any event target. 95 * TODO: Since we have two implementations now; this class and CacheStorage with 96 * almost similar responsibilities; it maybe worth exploring to consolidate 97 * both. 98 */ 99 class BoundStorageKeyCacheStorage final : public BoundStorageKey, 100 public TypeUtils, 101 public CacheStorageChildListener { 102 public: 103 static already_AddRefed<BoundStorageKeyCacheStorage> Create( 104 Namespace aNamespace, nsIGlobalObject* aGlobal, 105 WorkerPrivate* aWorkerPrivate, nsISerialEventTarget* aActorTarget, 106 ErrorResult& aRv); 107 108 #ifdef DEBUG 109 void AssertOwningThread() const override { 110 NS_ASSERT_OWNINGTHREAD(BoundStorageKey); 111 } 112 #else 113 inline void AssertOwningThread() const {} 114 #endif 115 116 nsresult Init(WorkerPrivate* aWorkerPrivate, Namespace aNamespace, 117 const PrincipalInfo& aPrincipalInfo, 118 nsISerialEventTarget* aTarget = GetCurrentSerialEventTarget()); 119 120 // Below methods declares the APIs that this class exposes, which looks 121 // similar to CacheStorage but return type is different 122 already_AddRefed<CacheStoragePromise> Match( 123 JSContext* aCx, const RequestOrUTF8String& aRequest, 124 const MultiCacheQueryOptions& aOptions, ErrorResult& aRv); 125 already_AddRefed<CacheStoragePromise> Has(const nsAString& aKey, 126 ErrorResult& aRv); 127 already_AddRefed<CacheStoragePromise> Open(const nsAString& aKey, 128 ErrorResult& aRv); 129 already_AddRefed<CacheStoragePromise> Delete(const nsAString& aKey, 130 ErrorResult& aRv); 131 already_AddRefed<CacheStoragePromise> Keys(ErrorResult& aRv); 132 133 nsIGlobalObject* GetGlobalObject() const override { return mGlobal; } 134 135 // explicitly exposing below OnActorDestroy to avoid cpp name hidiing 136 using BoundStorageKey::OnActorDestroy; 137 138 // called by associated CacheStorageChild actor during destruction. 139 void OnActorDestroy(CacheStorageChild* aActor) override; 140 141 private: 142 template <typename PromiseType> 143 struct Entry; 144 145 BoundStorageKeyCacheStorage( 146 Namespace aNamespace, nsIGlobalObject* aGlobal, 147 const mozilla::ipc::PrincipalInfo& aPrincipalInfo); 148 149 already_AddRefed<CacheStorageChild> CreateCacheStorageChild( 150 WorkerPrivate* aWorkerPrivate); 151 ~BoundStorageKeyCacheStorage() override; 152 153 template <typename EntryType> 154 void RunRequest(EntryType&& aEntry); 155 156 RefPtr<CacheStorageChild> mCacheStorageChild; 157 158 nsCOMPtr<nsIGlobalObject> mGlobal; 159 const UniquePtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo; 160 const Namespace mNamespace; 161 }; 162 163 } // namespace cache 164 165 template <dom::cache::CacheOpResult::Type OP_TYPE> 166 struct cachestorage_traits; 167 168 template <> 169 struct cachestorage_traits< 170 dom::cache::CacheOpResult::Type::TStorageMatchResult> { 171 using PromiseType = cache::MatchResultPromise::Private; 172 }; 173 174 template <> 175 struct cachestorage_traits<dom::cache::CacheOpResult::Type::TStorageHasResult> { 176 using PromiseType = cache::HasResultPromise::Private; 177 }; 178 179 template <> 180 struct cachestorage_traits< 181 dom::cache::CacheOpResult::Type::TStorageOpenResult> { 182 using PromiseType = cache::OpenResultPromise::Private; 183 }; 184 185 template <> 186 struct cachestorage_traits< 187 dom::cache::CacheOpResult::Type::TStorageDeleteResult> { 188 using PromiseType = cache::DeleteResultPromise::Private; 189 }; 190 191 template <> 192 struct cachestorage_traits< 193 dom::cache::CacheOpResult::Type::TStorageKeysResult> { 194 using PromiseType = cache::KeysResultPromise::Private; 195 }; 196 197 template <> 198 struct cachestorage_traits<dom::cache::CacheOpResult::Type::Tvoid_t> { 199 // Tvoid_t is only used to report errors, Resolve value doesn't matter much 200 // here. Just using HasResultPromise has it has simple Resolve value 201 using PromiseType = cache::HasResultPromise::Private; 202 }; 203 204 } // namespace dom 205 } // namespace mozilla 206 207 #endif // mozilla_dom_cache_BackgroundStorageKey_h