OriginOperationBase.cpp (4953B)
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 #include "OriginOperationBase.h" 8 9 #include "mozilla/Assertions.h" 10 #include "mozilla/MozPromise.h" 11 #include "mozilla/StaticPrefs_dom.h" 12 #include "mozilla/dom/quota/OriginOperationCallbacks.h" 13 #include "mozilla/dom/quota/QuotaManager.h" 14 #include "mozilla/dom/quota/ResultExtensions.h" 15 #include "mozilla/dom/quota/TargetPtrHolder.h" 16 #include "nsError.h" 17 #include "nsIThread.h" 18 #include "nsThreadUtils.h" 19 20 namespace mozilla::dom::quota { 21 22 namespace { 23 24 template <class T> 25 void ResolveOrRejectCallback(const BoolPromise::ResolveOrRejectValue& aValue, 26 MozPromiseHolder<T>& aPromiseHolder) { 27 if (aPromiseHolder.IsEmpty()) { 28 return; 29 } 30 31 if constexpr (std::is_same_v<T, ExclusiveBoolPromise>) { 32 aPromiseHolder.UseSynchronousTaskDispatch(__func__); 33 } 34 35 if (aValue.IsResolve()) { 36 aPromiseHolder.Resolve(true, __func__); 37 } else { 38 aPromiseHolder.Reject(aValue.RejectValue(), __func__); 39 } 40 } 41 42 } // namespace 43 44 OriginOperationBase::OriginOperationBase( 45 MovingNotNull<RefPtr<QuotaManager>>&& aQuotaManager, const char* aName) 46 : BackgroundThreadObject(GetCurrentSerialEventTarget()), 47 mQuotaManager(std::move(aQuotaManager)), 48 mResultCode(NS_OK) 49 #ifdef QM_COLLECTING_OPERATION_TELEMETRY 50 , 51 mName(aName) 52 #endif 53 { 54 AssertIsOnOwningThread(); 55 } 56 57 OriginOperationBase::~OriginOperationBase() { AssertIsOnOwningThread(); } 58 59 void OriginOperationBase::RunImmediately() { 60 AssertIsOnOwningThread(); 61 62 [self = RefPtr(this)]() { 63 if (QuotaManager::IsShuttingDown()) { 64 return BoolPromise::CreateAndReject(NS_ERROR_ABORT, __func__); 65 } 66 67 QM_TRY(MOZ_TO_RESULT(self->DoInit(*self->mQuotaManager)), 68 CreateAndRejectBoolPromise); 69 70 return self->Open(); 71 }() 72 #ifdef DEBUG 73 ->Then(GetCurrentSerialEventTarget(), __func__, 74 [self = RefPtr(this)]( 75 const BoolPromise::ResolveOrRejectValue& aValue) { 76 if (aValue.IsReject()) { 77 return BoolPromise::CreateAndReject(aValue.RejectValue(), 78 __func__); 79 } 80 81 // Give derived classes the occasion to add additional debug 82 // only checks after the opening was successfully finished on 83 // the current thread before passing the work to the IO thread. 84 QM_TRY(MOZ_TO_RESULT(self->DirectoryOpen()), 85 CreateAndRejectBoolPromise); 86 87 return BoolPromise::CreateAndResolve(true, __func__); 88 }) 89 #endif 90 ->Then(mQuotaManager->IOThread(), __func__, 91 [selfHolder = TargetPtrHolder(this)]( 92 const BoolPromise::ResolveOrRejectValue& aValue) { 93 if (aValue.IsReject()) { 94 return BoolPromise::CreateAndReject(aValue.RejectValue(), 95 __func__); 96 } 97 98 QM_TRY(MOZ_TO_RESULT(selfHolder->DoDirectoryWork( 99 *selfHolder->mQuotaManager)), 100 CreateAndRejectBoolPromise); 101 102 uint32_t pauseOnIOThreadMs = StaticPrefs:: 103 dom_quotaManager_originOperations_pauseOnIOThreadMs(); 104 if (pauseOnIOThreadMs > 0) { 105 PR_Sleep(PR_MillisecondsToInterval(pauseOnIOThreadMs)); 106 } 107 108 return BoolPromise::CreateAndResolve(true, __func__); 109 }) 110 ->Then( 111 GetCurrentSerialEventTarget(), __func__, 112 [self = 113 RefPtr(this)](const BoolPromise::ResolveOrRejectValue& aValue) { 114 if (aValue.IsReject()) { 115 MOZ_ASSERT(NS_SUCCEEDED(self->mResultCode)); 116 117 self->mResultCode = aValue.RejectValue(); 118 } 119 120 ResolveOrRejectCallback(aValue, self->mWillFinishPromiseHolder); 121 ResolveOrRejectCallback(aValue, self->mWillFinishSyncPromiseHolder); 122 123 self->UnblockOpen(); 124 125 ResolveOrRejectCallback(aValue, self->mDidFinishPromiseHolder); 126 ResolveOrRejectCallback(aValue, self->mDidFinishSyncPromiseHolder); 127 }); 128 } 129 130 OriginOperationCallbacks OriginOperationBase::GetCallbacks( 131 const OriginOperationCallbackOptions& aCallbackOptions) { 132 AssertIsOnOwningThread(); 133 134 return OriginOperationCallbackHolders::GetCallbacks(aCallbackOptions); 135 } 136 137 nsresult OriginOperationBase::DoInit(QuotaManager& aQuotaManager) { 138 AssertIsOnOwningThread(); 139 140 return NS_OK; 141 } 142 143 #ifdef DEBUG 144 nsresult OriginOperationBase::DirectoryOpen() { 145 AssertIsOnOwningThread(); 146 147 return NS_OK; 148 } 149 #endif 150 151 } // namespace mozilla::dom::quota