OpenClientDirectoryUtils.h (6081B)
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 file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef DOM_QUOTA_OPENCLIENTDIRECTORYUTILS_H_ 8 #define DOM_QUOTA_OPENCLIENTDIRECTORYUTILS_H_ 9 10 #include <functional> 11 12 #include "mozilla/MozPromise.h" 13 #include "mozilla/RefPtr.h" 14 #include "mozilla/dom/quota/ArtificialFailure.h" 15 #include "mozilla/dom/quota/ClientDirectoryLock.h" 16 #include "mozilla/dom/quota/ClientDirectoryLockHandle.h" 17 #include "mozilla/dom/quota/DirectoryLock.h" 18 #include "mozilla/dom/quota/DirectoryLockInlines.h" 19 #include "mozilla/dom/quota/ForwardDecls.h" 20 #include "mozilla/dom/quota/QuotaManager.h" 21 #include "mozilla/dom/quota/UniversalDirectoryLock.h" 22 23 namespace mozilla::dom::quota { 24 25 template <typename UninitChecker, typename PromiseArrayIter> 26 RefPtr<UniversalDirectoryLock> CreateDirectoryLockForInitialization( 27 QuotaManager& aQuotaManager, const PersistenceScope& aPersistenceScope, 28 const OriginScope& aOriginScope, 29 const ClientStorageScope& aClientStorageScope, 30 const bool aAlreadyInitialized, UninitChecker&& aUninitChecker, 31 PromiseArrayIter&& aPromiseArrayIter) { 32 RefPtr<UniversalDirectoryLock> directoryLock = 33 aQuotaManager.CreateDirectoryLockInternal(aPersistenceScope, aOriginScope, 34 aClientStorageScope, 35 /* aExclusive */ false); 36 37 auto prepareInfo = directoryLock->Prepare(); 38 39 if (aAlreadyInitialized && 40 !std::forward<UninitChecker>(aUninitChecker)(prepareInfo)) { 41 return nullptr; 42 } 43 44 auto iter = std::forward<PromiseArrayIter>(aPromiseArrayIter); 45 *iter = directoryLock->Acquire(std::move(prepareInfo)); 46 ++iter; 47 48 return directoryLock; 49 } 50 51 template <typename Callable> 52 class MaybeInitializeHelper final { 53 public: 54 MaybeInitializeHelper(RefPtr<UniversalDirectoryLock> aDirectoryLock, 55 Callable&& aCallable) 56 : mDirectoryLock(std::move(aDirectoryLock)), 57 mCallable(std::move(aCallable)) {} 58 59 RefPtr<BoolPromise> operator()( 60 const BoolPromise::ResolveOrRejectValue& aValue) { 61 if (aValue.IsReject()) { 62 SafeDropDirectoryLockIfNotDropped(mDirectoryLock); 63 64 return BoolPromise::CreateAndReject(aValue.RejectValue(), __func__); 65 } 66 67 if (!mDirectoryLock) { 68 return BoolPromise::CreateAndResolve(true, __func__); 69 } 70 71 return mCallable(std::move(mDirectoryLock)); 72 } 73 74 private: 75 RefPtr<UniversalDirectoryLock> mDirectoryLock; 76 Callable mCallable; 77 }; 78 79 template <typename Callable> 80 auto MaybeInitialize(RefPtr<UniversalDirectoryLock> aDirectoryLock, 81 Callable&& aCallable) { 82 return MaybeInitializeHelper(std::move(aDirectoryLock), 83 std::forward<Callable>(aCallable)); 84 } 85 86 auto MaybeInitialize(RefPtr<UniversalDirectoryLock> aDirectoryLock, 87 RefPtr<QuotaManager> aQuotaManager, 88 RefPtr<BoolPromise> (QuotaManager::*aMethod)( 89 RefPtr<UniversalDirectoryLock>)) { 90 return MaybeInitializeHelper( 91 std::move(aDirectoryLock), 92 [quotaManager = std::move(aQuotaManager), 93 method = aMethod](RefPtr<UniversalDirectoryLock> aDirectoryLock) { 94 return (quotaManager->*method)(std::move(aDirectoryLock)); 95 }); 96 } 97 98 // XXX: Consider renaming the finalization class and function below to make 99 // their purpose more specific 100 template <typename Callable> 101 class MaybeFinalizeHelper final { 102 public: 103 MaybeFinalizeHelper(RefPtr<ClientDirectoryLock> aClientDirectoryLock, 104 RefPtr<UniversalDirectoryLock> aFirstAccessDirectoryLock, 105 RefPtr<UniversalDirectoryLock> aLastAccessDirectoryLock, 106 Callable&& aCallable) 107 : mClientDirectoryLock(std::move(aClientDirectoryLock)), 108 mFirstAccessDirectoryLock(std::move(aFirstAccessDirectoryLock)), 109 mLastAccessDirectoryLock(std::move(aLastAccessDirectoryLock)), 110 mCallable(std::move(aCallable)) {} 111 112 RefPtr<QuotaManager::ClientDirectoryLockHandlePromise> operator()( 113 const BoolPromise::ResolveOrRejectValue& aValue) { 114 if (aValue.IsReject()) { 115 DropDirectoryLockIfNotDropped(mClientDirectoryLock); 116 DropDirectoryLockIfNotDropped(mFirstAccessDirectoryLock); 117 DropDirectoryLockIfNotDropped(mLastAccessDirectoryLock); 118 119 return QuotaManager::ClientDirectoryLockHandlePromise::CreateAndReject( 120 aValue.RejectValue(), __func__); 121 } 122 123 QM_TRY(ArtificialFailure( 124 nsIQuotaArtificialFailure::CATEGORY_OPEN_CLIENT_DIRECTORY), 125 [this](nsresult rv) { 126 DropDirectoryLock(mClientDirectoryLock); 127 DropDirectoryLock(mFirstAccessDirectoryLock); 128 DropDirectoryLock(mLastAccessDirectoryLock); 129 130 return QuotaManager::ClientDirectoryLockHandlePromise:: 131 CreateAndReject(rv, __func__); 132 }); 133 134 return mCallable(std::move(mClientDirectoryLock), 135 std::move(mFirstAccessDirectoryLock), 136 std::move(mLastAccessDirectoryLock)); 137 } 138 139 private: 140 RefPtr<ClientDirectoryLock> mClientDirectoryLock; 141 RefPtr<UniversalDirectoryLock> mFirstAccessDirectoryLock; 142 RefPtr<UniversalDirectoryLock> mLastAccessDirectoryLock; 143 Callable mCallable; 144 }; 145 146 template <typename Callable> 147 auto MaybeFinalize(RefPtr<ClientDirectoryLock> aClientDirectoryLock, 148 RefPtr<UniversalDirectoryLock> aFirstAccessDirectoryLock, 149 RefPtr<UniversalDirectoryLock> aLastAccessDirectoryLock, 150 Callable&& aCallable) { 151 return MaybeFinalizeHelper( 152 std::move(aClientDirectoryLock), std::move(aFirstAccessDirectoryLock), 153 std::move(aLastAccessDirectoryLock), std::forward<Callable>(aCallable)); 154 } 155 156 } // namespace mozilla::dom::quota 157 158 #endif // DOM_QUOTA_OPENCLIENTDIRECTORYUTILS_H_