Bug 1957367 - QM: Convert OpenClientDirectory and its callers to use ClientDirectoryLockHandle; r=dom-storage-reviewers,jstutte

Converts OpenClientDirectory to return ClientDirectoryLockHandle instead of
RefPtr<ClientDirectoryLock>, and updates all its callers accordingly.

ClientDirectoryLockHandle is a move-only RAII wrapper that ensures the lock
is automatically dropped when the handle goes out of scope. This simplifies
ownership semantics and aligns with diagnostic assertions that verify proper
lock dropping.

This patch finalizes the transition for quota clients to use
ClientDirectoryLockHandle instead of client directory locks directly.

Differential Revision: https://phabricator.services.mozilla.com/D243665
This commit is contained in:
Jan Varga
2025-04-15 12:25:49 +00:00
parent 895d756ece
commit d5cca7bb2d
13 changed files with 432 additions and 336 deletions

65
dom/cache/Context.cpp vendored
View File

@@ -16,8 +16,7 @@
#include "mozilla/dom/cache/ManagerId.h" #include "mozilla/dom/cache/ManagerId.h"
#include "mozilla/dom/quota/Assertions.h" #include "mozilla/dom/quota/Assertions.h"
#include "mozilla/dom/quota/ClientDirectoryLock.h" #include "mozilla/dom/quota/ClientDirectoryLock.h"
#include "mozilla/dom/quota/DirectoryLock.h" #include "mozilla/dom/quota/ClientDirectoryLockHandle.h"
#include "mozilla/dom/quota/DirectoryLockInlines.h"
#include "mozilla/dom/quota/PrincipalUtils.h" #include "mozilla/dom/quota/PrincipalUtils.h"
#include "mozilla/dom/quota/QuotaManager.h" #include "mozilla/dom/quota/QuotaManager.h"
#include "mozilla/dom/quota/ResultExtensions.h" #include "mozilla/dom/quota/ResultExtensions.h"
@@ -57,6 +56,7 @@ namespace mozilla::dom::cache {
using mozilla::dom::quota::AssertIsOnIOThread; using mozilla::dom::quota::AssertIsOnIOThread;
using mozilla::dom::quota::ClientDirectoryLock; using mozilla::dom::quota::ClientDirectoryLock;
using mozilla::dom::quota::ClientDirectoryLockHandle;
using mozilla::dom::quota::PERSISTENCE_TYPE_DEFAULT; using mozilla::dom::quota::PERSISTENCE_TYPE_DEFAULT;
using mozilla::dom::quota::PersistenceType; using mozilla::dom::quota::PersistenceType;
using mozilla::dom::quota::QuotaManager; using mozilla::dom::quota::QuotaManager;
@@ -126,7 +126,7 @@ class Context::QuotaInitRunnable final : public nsIRunnable {
Maybe<ClientDirectoryLock&> MaybeDirectoryLockRef() const { Maybe<ClientDirectoryLock&> MaybeDirectoryLockRef() const {
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable); NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
return ToMaybeRef(mDirectoryLock.get()); return ToMaybeRef(mDirectoryLockHandle.get());
} }
nsresult Dispatch() { nsresult Dispatch() {
@@ -149,7 +149,7 @@ class Context::QuotaInitRunnable final : public nsIRunnable {
mInitAction->CancelOnInitiatingThread(); mInitAction->CancelOnInitiatingThread();
} }
void DirectoryLockAcquired(ClientDirectoryLock* aLock); void DirectoryLockAcquired(ClientDirectoryLockHandle aLockHandle);
void DirectoryLockFailed(); void DirectoryLockFailed();
@@ -224,7 +224,7 @@ class Context::QuotaInitRunnable final : public nsIRunnable {
nsresult mResult; nsresult mResult;
Maybe<mozilla::ipc::PrincipalInfo> mPrincipalInfo; Maybe<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
Maybe<CacheDirectoryMetadata> mDirectoryMetadata; Maybe<CacheDirectoryMetadata> mDirectoryMetadata;
RefPtr<ClientDirectoryLock> mDirectoryLock; ClientDirectoryLockHandle mDirectoryLockHandle;
RefPtr<CipherKeyManager> mCipherKeyManager; RefPtr<CipherKeyManager> mCipherKeyManager;
State mState; State mState;
Atomic<bool> mCanceled; Atomic<bool> mCanceled;
@@ -235,18 +235,18 @@ class Context::QuotaInitRunnable final : public nsIRunnable {
}; };
void Context::QuotaInitRunnable::DirectoryLockAcquired( void Context::QuotaInitRunnable::DirectoryLockAcquired(
ClientDirectoryLock* aLock) { ClientDirectoryLockHandle aLockHandle) {
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable); NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
MOZ_DIAGNOSTIC_ASSERT(aLock); MOZ_DIAGNOSTIC_ASSERT(aLockHandle);
MOZ_DIAGNOSTIC_ASSERT(mState == STATE_WAIT_FOR_DIRECTORY_LOCK); MOZ_DIAGNOSTIC_ASSERT(mState == STATE_WAIT_FOR_DIRECTORY_LOCK);
MOZ_DIAGNOSTIC_ASSERT(!mDirectoryLock); MOZ_DIAGNOSTIC_ASSERT(!mDirectoryLockHandle);
mDirectoryLock = aLock; mDirectoryLockHandle = std::move(aLockHandle);
MOZ_DIAGNOSTIC_ASSERT(mDirectoryLock->Id() >= 0); MOZ_DIAGNOSTIC_ASSERT(mDirectoryLockHandle->Id() >= 0);
mDirectoryMetadata->mDirectoryLockId = mDirectoryLock->Id(); mDirectoryMetadata->mDirectoryLockId = mDirectoryLockHandle->Id();
if (mCanceled || mDirectoryLock->Invalidated()) { if (mCanceled || mDirectoryLockHandle->Invalidated()) {
Complete(NS_ERROR_ABORT); Complete(NS_ERROR_ABORT);
return; return;
} }
@@ -267,7 +267,7 @@ void Context::QuotaInitRunnable::DirectoryLockAcquired(
void Context::QuotaInitRunnable::DirectoryLockFailed() { void Context::QuotaInitRunnable::DirectoryLockFailed() {
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable); NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
MOZ_DIAGNOSTIC_ASSERT(mState == STATE_WAIT_FOR_DIRECTORY_LOCK); MOZ_DIAGNOSTIC_ASSERT(mState == STATE_WAIT_FOR_DIRECTORY_LOCK);
MOZ_DIAGNOSTIC_ASSERT(!mDirectoryLock); MOZ_DIAGNOSTIC_ASSERT(!mDirectoryLockHandle);
NS_WARNING("Failed to acquire a directory lock!"); NS_WARNING("Failed to acquire a directory lock!");
@@ -386,10 +386,10 @@ Context::QuotaInitRunnable::Run() {
->Then( ->Then(
GetCurrentSerialEventTarget(), __func__, GetCurrentSerialEventTarget(), __func__,
[self = RefPtr(this)]( [self = RefPtr(this)](
const quota::ClientDirectoryLockPromise::ResolveOrRejectValue& QuotaManager::ClientDirectoryLockHandlePromise::
aValue) { ResolveOrRejectValue&& aValue) {
if (aValue.IsResolve()) { if (aValue.IsResolve()) {
self->DirectoryLockAcquired(aValue.ResolveValue()); self->DirectoryLockAcquired(std::move(aValue.ResolveValue()));
} else { } else {
self->DirectoryLockFailed(); self->DirectoryLockFailed();
} }
@@ -468,7 +468,7 @@ Context::QuotaInitRunnable::Run() {
mInitAction->CompleteOnInitiatingThread(mResult); mInitAction->CompleteOnInitiatingThread(mResult);
mContext->OnQuotaInit(mResult, mDirectoryMetadata, mContext->OnQuotaInit(mResult, mDirectoryMetadata,
std::move(mDirectoryLock), std::move(mDirectoryLockHandle),
std::move(mCipherKeyManager)); std::move(mCipherKeyManager));
mState = STATE_COMPLETE; mState = STATE_COMPLETE;
@@ -866,18 +866,18 @@ Maybe<ClientDirectoryLock&> Context::MaybeDirectoryLockRef() const {
if (mState == STATE_CONTEXT_PREINIT) { if (mState == STATE_CONTEXT_PREINIT) {
MOZ_DIAGNOSTIC_ASSERT(!mInitRunnable); MOZ_DIAGNOSTIC_ASSERT(!mInitRunnable);
MOZ_DIAGNOSTIC_ASSERT(!mDirectoryLock); MOZ_DIAGNOSTIC_ASSERT(!mDirectoryLockHandle);
return Nothing(); return Nothing();
} }
if (mState == STATE_CONTEXT_INIT) { if (mState == STATE_CONTEXT_INIT) {
MOZ_DIAGNOSTIC_ASSERT(!mDirectoryLock); MOZ_DIAGNOSTIC_ASSERT(!mDirectoryLockHandle);
return mInitRunnable->MaybeDirectoryLockRef(); return mInitRunnable->MaybeDirectoryLockRef();
} }
return ToMaybeRef(mDirectoryLock.get()); return ToMaybeRef(mDirectoryLockHandle.get());
} }
CipherKeyManager& Context::MutableCipherKeyManagerRef() { CipherKeyManager& Context::MutableCipherKeyManagerRef() {
@@ -963,7 +963,9 @@ Context::~Context() {
mThreadsafeHandle->ContextDestroyed(*this); mThreadsafeHandle->ContextDestroyed(*this);
} }
SafeDropDirectoryLock(mDirectoryLock); {
auto destroyingDirectoryLockHandle = std::move(mDirectoryLockHandle);
}
// Note, this may set the mOrphanedData flag. // Note, this may set the mOrphanedData flag.
mManager->RemoveContext(*this); mManager->RemoveContext(*this);
@@ -1043,7 +1045,7 @@ void Context::DispatchAction(SafeRefPtr<Action> aAction, bool aDoomData) {
void Context::OnQuotaInit( void Context::OnQuotaInit(
nsresult aRv, const Maybe<CacheDirectoryMetadata>& aDirectoryMetadata, nsresult aRv, const Maybe<CacheDirectoryMetadata>& aDirectoryMetadata,
RefPtr<ClientDirectoryLock> aDirectoryLock, ClientDirectoryLockHandle aDirectoryLockHandle,
RefPtr<CipherKeyManager> aCipherKeyManager) { RefPtr<CipherKeyManager> aCipherKeyManager) {
NS_ASSERT_OWNINGTHREAD(Context); NS_ASSERT_OWNINGTHREAD(Context);
@@ -1055,8 +1057,8 @@ void Context::OnQuotaInit(
// Always save the directory lock to ensure QuotaManager does not shutdown // Always save the directory lock to ensure QuotaManager does not shutdown
// before the Context has gone away. // before the Context has gone away.
MOZ_DIAGNOSTIC_ASSERT(!mDirectoryLock); MOZ_DIAGNOSTIC_ASSERT(!mDirectoryLockHandle);
mDirectoryLock = std::move(aDirectoryLock); mDirectoryLockHandle = std::move(aDirectoryLockHandle);
MOZ_DIAGNOSTIC_ASSERT(!mCipherKeyManager); MOZ_DIAGNOSTIC_ASSERT(!mCipherKeyManager);
mCipherKeyManager = std::move(aCipherKeyManager); mCipherKeyManager = std::move(aCipherKeyManager);
@@ -1085,8 +1087,8 @@ void Context::OnQuotaInit(
// We could only assert below if quota initialization was a success which // We could only assert below if quota initialization was a success which
// is ensured by NS_FAILED(aRv) above // is ensured by NS_FAILED(aRv) above
MOZ_DIAGNOSTIC_ASSERT(mDirectoryMetadata); MOZ_DIAGNOSTIC_ASSERT(mDirectoryMetadata);
MOZ_DIAGNOSTIC_ASSERT(mDirectoryLock); MOZ_DIAGNOSTIC_ASSERT(mDirectoryLockHandle);
MOZ_DIAGNOSTIC_ASSERT(!mDirectoryLock->Invalidated()); MOZ_DIAGNOSTIC_ASSERT(!mDirectoryLockHandle->Invalidated());
MOZ_DIAGNOSTIC_ASSERT_IF(mDirectoryMetadata->mIsPrivate, mCipherKeyManager); MOZ_DIAGNOSTIC_ASSERT_IF(mDirectoryMetadata->mIsPrivate, mCipherKeyManager);
MOZ_DIAGNOSTIC_ASSERT(mState == STATE_CONTEXT_INIT); MOZ_DIAGNOSTIC_ASSERT(mState == STATE_CONTEXT_INIT);
@@ -1180,13 +1182,14 @@ void Context::DoStringify(nsACString& aData) {
aData.Append(kStringifyEndSet); aData.Append(kStringifyEndSet);
}; };
aData.Append( aData.Append(kStringifyDelimiter +
//
"DirectoryLock:"_ns +
IntToCString(static_cast<bool>(mDirectoryLockHandle)) +
kStringifyDelimiter + kStringifyDelimiter +
// //
"DirectoryLock:"_ns + IntToCString(static_cast<bool>(mDirectoryLock)) + "NextContext:"_ns +
kStringifyDelimiter + IntToCString(static_cast<bool>(mNextContext)) +
//
"NextContext:"_ns + IntToCString(static_cast<bool>(mNextContext)) +
// //
kStringifyEndInstance); kStringifyEndInstance);

7
dom/cache/Context.h vendored
View File

@@ -10,6 +10,7 @@
#include "CacheCipherKeyManager.h" #include "CacheCipherKeyManager.h"
#include "mozilla/dom/SafeRefPtr.h" #include "mozilla/dom/SafeRefPtr.h"
#include "mozilla/dom/cache/Types.h" #include "mozilla/dom/cache/Types.h"
#include "mozilla/dom/quota/ClientDirectoryLockHandle.h"
#include "mozilla/dom/quota/StringifyUtils.h" #include "mozilla/dom/quota/StringifyUtils.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsISupportsImpl.h" #include "nsISupportsImpl.h"
@@ -66,6 +67,8 @@ class Manager;
// via the code in ShutdownObserver.cpp. // via the code in ShutdownObserver.cpp.
class Context final : public SafeRefCounted<Context>, public Stringifyable { class Context final : public SafeRefCounted<Context>, public Stringifyable {
using ClientDirectoryLock = mozilla::dom::quota::ClientDirectoryLock; using ClientDirectoryLock = mozilla::dom::quota::ClientDirectoryLock;
using ClientDirectoryLockHandle =
mozilla::dom::quota::ClientDirectoryLockHandle;
public: public:
// Define a class allowing other threads to hold the Context alive. This also // Define a class allowing other threads to hold the Context alive. This also
@@ -184,7 +187,7 @@ class Context final : public SafeRefCounted<Context>, public Stringifyable {
void DispatchAction(SafeRefPtr<Action> aAction, bool aDoomData = false); void DispatchAction(SafeRefPtr<Action> aAction, bool aDoomData = false);
void OnQuotaInit(nsresult aRv, void OnQuotaInit(nsresult aRv,
const Maybe<CacheDirectoryMetadata>& aDirectoryMetadata, const Maybe<CacheDirectoryMetadata>& aDirectoryMetadata,
RefPtr<ClientDirectoryLock> aDirectoryLock, ClientDirectoryLockHandle aDirectoryLockHandle,
RefPtr<CipherKeyManager> aCipherKeyManager); RefPtr<CipherKeyManager> aCipherKeyManager);
SafeRefPtr<ThreadsafeHandle> CreateThreadsafeHandle(); SafeRefPtr<ThreadsafeHandle> CreateThreadsafeHandle();
@@ -214,7 +217,7 @@ class Context final : public SafeRefCounted<Context>, public Stringifyable {
// when ThreadsafeHandle::AllowToClose() is called. // when ThreadsafeHandle::AllowToClose() is called.
SafeRefPtr<ThreadsafeHandle> mThreadsafeHandle; SafeRefPtr<ThreadsafeHandle> mThreadsafeHandle;
RefPtr<ClientDirectoryLock> mDirectoryLock; ClientDirectoryLockHandle mDirectoryLockHandle;
RefPtr<CipherKeyManager> mCipherKeyManager; RefPtr<CipherKeyManager> mCipherKeyManager;
SafeRefPtr<Context> mNextContext; SafeRefPtr<Context> mNextContext;

View File

@@ -27,8 +27,6 @@
#include "mozilla/dom/QMResult.h" #include "mozilla/dom/QMResult.h"
#include "mozilla/dom/quota/ClientDirectoryLock.h" #include "mozilla/dom/quota/ClientDirectoryLock.h"
#include "mozilla/dom/quota/ClientImpl.h" #include "mozilla/dom/quota/ClientImpl.h"
#include "mozilla/dom/quota/DirectoryLock.h"
#include "mozilla/dom/quota/DirectoryLockInlines.h"
#include "mozilla/dom/quota/HashKeys.h" #include "mozilla/dom/quota/HashKeys.h"
#include "mozilla/dom/quota/QuotaCommon.h" #include "mozilla/dom/quota/QuotaCommon.h"
#include "mozilla/dom/quota/QuotaManager.h" #include "mozilla/dom/quota/QuotaManager.h"
@@ -321,7 +319,7 @@ void FileSystemDataManager::RegisterActor(
NotNull<FileSystemManagerParent*> aActor) { NotNull<FileSystemManagerParent*> aActor) {
MOZ_ASSERT(!mBackgroundThreadAccessible.Access()->mActors.Contains(aActor)); MOZ_ASSERT(!mBackgroundThreadAccessible.Access()->mActors.Contains(aActor));
MOZ_ASSERT(mState == State::Open); MOZ_ASSERT(mState == State::Open);
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
mBackgroundThreadAccessible.Access()->mActors.Insert(aActor); mBackgroundThreadAccessible.Access()->mActors.Insert(aActor);
@@ -335,7 +333,7 @@ void FileSystemDataManager::RegisterActor(
// directory lock if it has been invalidated and eventually notify the actor // directory lock if it has been invalidated and eventually notify the actor
// about the abort. // about the abort.
if (mDirectoryLock->Invalidated()) { if (mDirectoryLockHandle->Invalidated()) {
aActor->RequestAllowToClose(); aActor->RequestAllowToClose();
} }
} }
@@ -344,7 +342,7 @@ void FileSystemDataManager::UnregisterActor(
NotNull<FileSystemManagerParent*> aActor) { NotNull<FileSystemManagerParent*> aActor) {
MOZ_ASSERT(mBackgroundThreadAccessible.Access()->mActors.Contains(aActor)); MOZ_ASSERT(mBackgroundThreadAccessible.Access()->mActors.Contains(aActor));
MOZ_ASSERT(mState == State::Open); MOZ_ASSERT(mState == State::Open);
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
mBackgroundThreadAccessible.Access()->mActors.Remove(aActor); mBackgroundThreadAccessible.Access()->mActors.Remove(aActor);
@@ -616,21 +614,21 @@ RefPtr<BoolPromise> FileSystemDataManager::BeginOpen() {
mQuotaManager mQuotaManager
->OpenClientDirectory( ->OpenClientDirectory(
{mOriginMetadata, mozilla::dom::quota::Client::FILESYSTEM}) {mOriginMetadata, mozilla::dom::quota::Client::FILESYSTEM})
->Then( ->Then(GetCurrentSerialEventTarget(), __func__,
GetCurrentSerialEventTarget(), __func__,
[self = RefPtr<FileSystemDataManager>(this)]( [self = RefPtr<FileSystemDataManager>(this)](
quota::ClientDirectoryLockPromise::ResolveOrRejectValue&& value) { quota::QuotaManager::ClientDirectoryLockHandlePromise::
ResolveOrRejectValue&& value) {
if (value.IsReject()) { if (value.IsReject()) {
return BoolPromise::CreateAndReject(value.RejectValue(), return BoolPromise::CreateAndReject(value.RejectValue(),
__func__); __func__);
} }
self->mDirectoryLock = std::move(value.ResolveValue()); self->mDirectoryLockHandle = std::move(value.ResolveValue());
MOZ_ASSERT(self->mDirectoryLock->Id() >= 0); MOZ_ASSERT(self->mDirectoryLockHandle->Id() >= 0);
self->mDirectoryLockId = self->mDirectoryLock->Id(); self->mDirectoryLockId = self->mDirectoryLockHandle->Id();
if (self->mDirectoryLock->Invalidated()) { if (self->mDirectoryLockHandle->Invalidated()) {
return BoolPromise::CreateAndReject(NS_ERROR_ABORT, __func__); return BoolPromise::CreateAndReject(NS_ERROR_ABORT, __func__);
} }
@@ -758,7 +756,10 @@ RefPtr<BoolPromise> FileSystemDataManager::BeginClose() {
->Then(MutableBackgroundTargetPtr(), __func__, ->Then(MutableBackgroundTargetPtr(), __func__,
[self = RefPtr<FileSystemDataManager>(this)]( [self = RefPtr<FileSystemDataManager>(this)](
const ShutdownPromise::ResolveOrRejectValue&) { const ShutdownPromise::ResolveOrRejectValue&) {
SafeDropDirectoryLock(self->mDirectoryLock); {
auto destroyingDirectoryLockHandle =
std::move(self->mDirectoryLockHandle);
}
RemoveFileSystemDataManager(self->mOriginMetadata.mOrigin); RemoveFileSystemDataManager(self->mOriginMetadata.mOrigin);

View File

@@ -15,6 +15,7 @@
#include "mozilla/dom/FileSystemHelpers.h" #include "mozilla/dom/FileSystemHelpers.h"
#include "mozilla/dom/FileSystemTypes.h" #include "mozilla/dom/FileSystemTypes.h"
#include "mozilla/dom/quota/CheckedUnsafePtr.h" #include "mozilla/dom/quota/CheckedUnsafePtr.h"
#include "mozilla/dom/quota/ClientDirectoryLockHandle.h"
#include "mozilla/dom/quota/CommonMetadata.h" #include "mozilla/dom/quota/CommonMetadata.h"
#include "mozilla/dom/quota/ForwardDecls.h" #include "mozilla/dom/quota/ForwardDecls.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
@@ -100,7 +101,7 @@ class FileSystemDataManager
} }
Maybe<quota::ClientDirectoryLock&> MaybeDirectoryLockRef() const { Maybe<quota::ClientDirectoryLock&> MaybeDirectoryLockRef() const {
return ToMaybeRef(mDirectoryLock.get()); return ToMaybeRef(mDirectoryLockHandle.get());
} }
FileSystemDatabaseManager* MutableDatabaseManagerPtr() const { FileSystemDatabaseManager* MutableDatabaseManagerPtr() const {
@@ -178,7 +179,7 @@ class FileSystemDataManager
const NotNull<nsCOMPtr<nsISerialEventTarget>> mBackgroundTarget; const NotNull<nsCOMPtr<nsISerialEventTarget>> mBackgroundTarget;
const NotNull<nsCOMPtr<nsIEventTarget>> mIOTarget; const NotNull<nsCOMPtr<nsIEventTarget>> mIOTarget;
const NotNull<RefPtr<TaskQueue>> mIOTaskQueue; const NotNull<RefPtr<TaskQueue>> mIOTaskQueue;
RefPtr<quota::ClientDirectoryLock> mDirectoryLock; quota::ClientDirectoryLockHandle mDirectoryLockHandle;
UniquePtr<FileSystemDatabaseManager> mDatabaseManager; UniquePtr<FileSystemDatabaseManager> mDatabaseManager;
MozPromiseHolder<BoolPromise> mOpenPromiseHolder; MozPromiseHolder<BoolPromise> mOpenPromiseHolder;
MozPromiseHolder<BoolPromise> mClosePromiseHolder; MozPromiseHolder<BoolPromise> mClosePromiseHolder;

View File

@@ -123,6 +123,7 @@
#include "mozilla/dom/quota/CheckedUnsafePtr.h" #include "mozilla/dom/quota/CheckedUnsafePtr.h"
#include "mozilla/dom/quota/Client.h" #include "mozilla/dom/quota/Client.h"
#include "mozilla/dom/quota/ClientDirectoryLock.h" #include "mozilla/dom/quota/ClientDirectoryLock.h"
#include "mozilla/dom/quota/ClientDirectoryLockHandle.h"
#include "mozilla/dom/quota/ClientImpl.h" #include "mozilla/dom/quota/ClientImpl.h"
#include "mozilla/dom/quota/ConditionalCompilation.h" #include "mozilla/dom/quota/ConditionalCompilation.h"
#include "mozilla/dom/quota/DirectoryLock.h" #include "mozilla/dom/quota/DirectoryLock.h"
@@ -2137,7 +2138,7 @@ class Database final
SafeRefPtr<Factory> mFactory; SafeRefPtr<Factory> mFactory;
SafeRefPtr<FullDatabaseMetadata> mMetadata; SafeRefPtr<FullDatabaseMetadata> mMetadata;
SafeRefPtr<DatabaseFileManager> mFileManager; SafeRefPtr<DatabaseFileManager> mFileManager;
RefPtr<ClientDirectoryLock> mDirectoryLock; ClientDirectoryLockHandle mDirectoryLockHandle;
nsTHashSet<TransactionBase*> mTransactions; nsTHashSet<TransactionBase*> mTransactions;
nsTHashMap<nsIDHashKey, SafeRefPtr<DatabaseFileInfo>> mMappedBlobs; nsTHashMap<nsIDHashKey, SafeRefPtr<DatabaseFileInfo>> mMappedBlobs;
RefPtr<DatabaseConnection> mConnection; RefPtr<DatabaseConnection> mConnection;
@@ -2168,8 +2169,8 @@ class Database final
const quota::OriginMetadata& aOriginMetadata, uint32_t aTelemetryId, const quota::OriginMetadata& aOriginMetadata, uint32_t aTelemetryId,
SafeRefPtr<FullDatabaseMetadata> aMetadata, SafeRefPtr<FullDatabaseMetadata> aMetadata,
SafeRefPtr<DatabaseFileManager> aFileManager, SafeRefPtr<DatabaseFileManager> aFileManager,
RefPtr<ClientDirectoryLock> aDirectoryLock, bool aInPrivateBrowsing, ClientDirectoryLockHandle aDirectoryLockHandle,
const Maybe<const CipherKey>& aMaybeKey); bool aInPrivateBrowsing, const Maybe<const CipherKey>& aMaybeKey);
void AssertIsOnConnectionThread() const { void AssertIsOnConnectionThread() const {
#ifdef DEBUG #ifdef DEBUG
@@ -2216,7 +2217,7 @@ class Database final
Maybe<ClientDirectoryLock&> MaybeDirectoryLockRef() const { Maybe<ClientDirectoryLock&> MaybeDirectoryLockRef() const {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
return ToMaybeRef(mDirectoryLock.get()); return ToMaybeRef(mDirectoryLockHandle.get());
} }
int64_t DirectoryLockId() const { return mDirectoryLockId; } int64_t DirectoryLockId() const { return mDirectoryLockId; }
@@ -3036,7 +3037,7 @@ class FactoryOp
Maybe<ContentParentId> mContentParentId; Maybe<ContentParentId> mContentParentId;
// Must be released on the main thread! // Must be released on the main thread!
RefPtr<ClientDirectoryLock> mDirectoryLock; ClientDirectoryLockHandle mDirectoryLockHandle;
nsTArray<NotNull<RefPtr<FactoryOp>>> mBlocking; nsTArray<NotNull<RefPtr<FactoryOp>>> mBlocking;
nsTArray<NotNull<RefPtr<FactoryOp>>> mBlockedOn; nsTArray<NotNull<RefPtr<FactoryOp>>> mBlockedOn;
@@ -3152,7 +3153,7 @@ class FactoryOp
NS_IMETHOD NS_IMETHOD
Run() final; Run() final;
void DirectoryLockAcquired(ClientDirectoryLock* aLock); void DirectoryLockAcquired(ClientDirectoryLockHandle aLockHandle);
void DirectoryLockFailed(); void DirectoryLockFailed();
@@ -4967,7 +4968,7 @@ class DeleteFilesRunnable final : public Runnable {
nsCOMPtr<nsIEventTarget> mOwningEventTarget; nsCOMPtr<nsIEventTarget> mOwningEventTarget;
SafeRefPtr<DatabaseFileManager> mFileManager; SafeRefPtr<DatabaseFileManager> mFileManager;
RefPtr<ClientDirectoryLock> mDirectoryLock; ClientDirectoryLockHandle mDirectoryLockHandle;
nsTArray<int64_t> mFileIds; nsTArray<int64_t> mFileIds;
State mState; State mState;
DEBUGONLY(bool mDEBUGCountsAsPending = false); DEBUGONLY(bool mDEBUGCountsAsPending = false);
@@ -4999,7 +5000,7 @@ class DeleteFilesRunnable final : public Runnable {
NS_DECL_NSIRUNNABLE NS_DECL_NSIRUNNABLE
void DirectoryLockAcquired(ClientDirectoryLock* aLock); void DirectoryLockAcquired(ClientDirectoryLockHandle aLockHandle);
void DirectoryLockFailed(); void DirectoryLockFailed();
}; };
@@ -9240,13 +9241,13 @@ Database::Database(SafeRefPtr<Factory> aFactory,
uint32_t aTelemetryId, uint32_t aTelemetryId,
SafeRefPtr<FullDatabaseMetadata> aMetadata, SafeRefPtr<FullDatabaseMetadata> aMetadata,
SafeRefPtr<DatabaseFileManager> aFileManager, SafeRefPtr<DatabaseFileManager> aFileManager,
RefPtr<ClientDirectoryLock> aDirectoryLock, ClientDirectoryLockHandle aDirectoryLockHandle,
bool aInPrivateBrowsing, bool aInPrivateBrowsing,
const Maybe<const CipherKey>& aMaybeKey) const Maybe<const CipherKey>& aMaybeKey)
: mFactory(std::move(aFactory)), : mFactory(std::move(aFactory)),
mMetadata(std::move(aMetadata)), mMetadata(std::move(aMetadata)),
mFileManager(std::move(aFileManager)), mFileManager(std::move(aFileManager)),
mDirectoryLock(std::move(aDirectoryLock)), mDirectoryLockHandle(std::move(aDirectoryLockHandle)),
mPrincipalInfo(aPrincipalInfo), mPrincipalInfo(aPrincipalInfo),
mOptionalContentParentId(aOptionalContentParentId), mOptionalContentParentId(aOptionalContentParentId),
mOriginMetadata(aOriginMetadata), mOriginMetadata(aOriginMetadata),
@@ -9267,9 +9268,9 @@ Database::Database(SafeRefPtr<Factory> aFactory,
MOZ_ASSERT(mMetadata); MOZ_ASSERT(mMetadata);
MOZ_ASSERT(mFileManager); MOZ_ASSERT(mFileManager);
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
MOZ_ASSERT(mDirectoryLock->Id() >= 0); MOZ_ASSERT(mDirectoryLockHandle->Id() >= 0);
mDirectoryLockId = mDirectoryLock->Id(); mDirectoryLockId = mDirectoryLockHandle->Id();
} }
template <typename T> template <typename T>
@@ -9334,7 +9335,7 @@ nsresult Database::EnsureConnection() {
bool Database::RegisterTransaction(TransactionBase& aTransaction) { bool Database::RegisterTransaction(TransactionBase& aTransaction) {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(!mTransactions.Contains(&aTransaction)); MOZ_ASSERT(!mTransactions.Contains(&aTransaction));
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
MOZ_ASSERT(!mInvalidated); MOZ_ASSERT(!mInvalidated);
MOZ_ASSERT(!mClosed); MOZ_ASSERT(!mClosed);
@@ -9389,7 +9390,7 @@ void Database::Stringify(nsACString& aResult) const {
constexpr auto kQuotaGenericDelimiterString = "|"_ns; constexpr auto kQuotaGenericDelimiterString = "|"_ns;
aResult.Append( aResult.Append(
"DirectoryLock:"_ns + IntToCString(!!mDirectoryLock) + "DirectoryLock:"_ns + IntToCString(!!mDirectoryLockHandle) +
kQuotaGenericDelimiterString + kQuotaGenericDelimiterString +
// //
"Transactions:"_ns + IntToCString(mTransactions.Count()) + "Transactions:"_ns + IntToCString(mTransactions.Count()) +
@@ -9511,7 +9512,7 @@ bool Database::CloseInternal() {
void Database::MaybeCloseConnection() { void Database::MaybeCloseConnection() {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
if (!mTransactions.Count() && IsClosed() && mDirectoryLock) { if (!mTransactions.Count() && IsClosed() && mDirectoryLockHandle) {
nsCOMPtr<nsIRunnable> callback = nsCOMPtr<nsIRunnable> callback =
NewRunnableMethod("dom::indexedDB::Database::ConnectionClosedCallback", NewRunnableMethod("dom::indexedDB::Database::ConnectionClosedCallback",
this, &Database::ConnectionClosedCallback); this, &Database::ConnectionClosedCallback);
@@ -9527,7 +9528,9 @@ void Database::ConnectionClosedCallback() {
MOZ_ASSERT(mClosed); MOZ_ASSERT(mClosed);
MOZ_ASSERT(!mTransactions.Count()); MOZ_ASSERT(!mTransactions.Count());
DropDirectoryLock(mDirectoryLock); {
auto destroyingDirectoryLockHandle = std::move(mDirectoryLockHandle);
}
CleanupMetadata(); CleanupMetadata();
@@ -12878,10 +12881,10 @@ void DeleteFilesRunnable::Open() {
{mFileManager->OriginMetadata(), quota::Client::IDB}) {mFileManager->OriginMetadata(), quota::Client::IDB})
->Then( ->Then(
GetCurrentSerialEventTarget(), __func__, GetCurrentSerialEventTarget(), __func__,
[self = RefPtr(this)]( [self = RefPtr(this)](QuotaManager::ClientDirectoryLockHandlePromise::
const ClientDirectoryLockPromise::ResolveOrRejectValue& aValue) { ResolveOrRejectValue&& aValue) {
if (aValue.IsResolve()) { if (aValue.IsResolve()) {
self->DirectoryLockAcquired(aValue.ResolveValue()); self->DirectoryLockAcquired(std::move(aValue.ResolveValue()));
} else { } else {
self->DirectoryLockFailed(); self->DirectoryLockFailed();
} }
@@ -12917,7 +12920,9 @@ void DeleteFilesRunnable::UnblockOpen() {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(mState == State_UnblockingOpen); MOZ_ASSERT(mState == State_UnblockingOpen);
SafeDropDirectoryLock(mDirectoryLock); {
auto destroyingDirectoryLockHandle = std::move(mDirectoryLockHandle);
}
MOZ_ASSERT(mDEBUGCountsAsPending); MOZ_ASSERT(mDEBUGCountsAsPending);
sPendingRunnables--; sPendingRunnables--;
@@ -12949,12 +12954,13 @@ DeleteFilesRunnable::Run() {
return NS_OK; return NS_OK;
} }
void DeleteFilesRunnable::DirectoryLockAcquired(ClientDirectoryLock* aLock) { void DeleteFilesRunnable::DirectoryLockAcquired(
ClientDirectoryLockHandle aLockHandle) {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(mState == State_DirectoryOpenPending); MOZ_ASSERT(mState == State_DirectoryOpenPending);
MOZ_ASSERT(!mDirectoryLock); MOZ_ASSERT(!mDirectoryLockHandle);
mDirectoryLock = aLock; mDirectoryLockHandle = std::move(aLockHandle);
QuotaManager* const quotaManager = QuotaManager::Get(); QuotaManager* const quotaManager = QuotaManager::Get();
MOZ_ASSERT(quotaManager); MOZ_ASSERT(quotaManager);
@@ -12970,7 +12976,7 @@ void DeleteFilesRunnable::DirectoryLockAcquired(ClientDirectoryLock* aLock) {
void DeleteFilesRunnable::DirectoryLockFailed() { void DeleteFilesRunnable::DirectoryLockFailed() {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(mState == State_DirectoryOpenPending); MOZ_ASSERT(mState == State_DirectoryOpenPending);
MOZ_ASSERT(!mDirectoryLock); MOZ_ASSERT(!mDirectoryLockHandle);
Finish(); Finish();
} }
@@ -14757,7 +14763,7 @@ nsresult FactoryOp::Open() {
AssertIsOnOwningThread(); AssertIsOnOwningThread();
MOZ_ASSERT(mState == State::Initial); MOZ_ASSERT(mState == State::Initial);
MOZ_ASSERT(mOriginMetadata.mOrigin.IsEmpty()); MOZ_ASSERT(mOriginMetadata.mOrigin.IsEmpty());
MOZ_ASSERT(!mDirectoryLock); MOZ_ASSERT(!mDirectoryLockHandle);
if (NS_WARN_IF(QuotaClient::IsShuttingDownOnBackgroundThread()) || if (NS_WARN_IF(QuotaClient::IsShuttingDownOnBackgroundThread()) ||
IsActorDestroyed()) { IsActorDestroyed()) {
@@ -14849,10 +14855,10 @@ nsresult FactoryOp::Open() {
quotaManager->OpenClientDirectory({mOriginMetadata, Client::IDB}) quotaManager->OpenClientDirectory({mOriginMetadata, Client::IDB})
->Then( ->Then(
GetCurrentSerialEventTarget(), __func__, GetCurrentSerialEventTarget(), __func__,
[self = RefPtr(this)]( [self = RefPtr(this)](QuotaManager::ClientDirectoryLockHandlePromise::
const ClientDirectoryLockPromise::ResolveOrRejectValue& aValue) { ResolveOrRejectValue&& aValue) {
if (aValue.IsResolve()) { if (aValue.IsResolve()) {
self->DirectoryLockAcquired(aValue.ResolveValue()); self->DirectoryLockAcquired(std::move(aValue.ResolveValue()));
} else { } else {
self->DirectoryLockFailed(); self->DirectoryLockFailed();
} }
@@ -14864,7 +14870,7 @@ nsresult FactoryOp::Open() {
nsresult FactoryOp::DirectoryOpen() { nsresult FactoryOp::DirectoryOpen() {
AssertIsOnOwningThread(); AssertIsOnOwningThread();
MOZ_ASSERT(mState == State::DirectoryOpenPending); MOZ_ASSERT(mState == State::DirectoryOpenPending);
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
if (mDatabaseName.isNothing()) { if (mDatabaseName.isNothing()) {
QuotaManager* const quotaManager = QuotaManager::Get(); QuotaManager* const quotaManager = QuotaManager::Get();
@@ -14890,7 +14896,7 @@ nsresult FactoryOp::DirectoryOpen() {
nsresult FactoryOp::DirectoryWorkDone() { nsresult FactoryOp::DirectoryWorkDone() {
AssertIsOnOwningThread(); AssertIsOnOwningThread();
MOZ_ASSERT(mState == State::DirectoryWorkDone); MOZ_ASSERT(mState == State::DirectoryWorkDone);
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
MOZ_ASSERT(gFactoryOps); MOZ_ASSERT(gFactoryOps);
// See if this FactoryOp needs to wait. // See if this FactoryOp needs to wait.
@@ -15142,16 +15148,16 @@ FactoryOp::Run() {
return NS_OK; return NS_OK;
} }
void FactoryOp::DirectoryLockAcquired(ClientDirectoryLock* aLock) { void FactoryOp::DirectoryLockAcquired(ClientDirectoryLockHandle aLockHandle) {
AssertIsOnOwningThread(); AssertIsOnOwningThread();
MOZ_ASSERT(aLock); MOZ_ASSERT(aLockHandle);
MOZ_ASSERT(mState == State::DirectoryOpenPending); MOZ_ASSERT(mState == State::DirectoryOpenPending);
MOZ_ASSERT(!mDirectoryLock); MOZ_ASSERT(!mDirectoryLockHandle);
mDirectoryLock = aLock; mDirectoryLockHandle = std::move(aLockHandle);
MOZ_ASSERT(mDirectoryLock->Id() >= 0); MOZ_ASSERT(mDirectoryLockHandle->Id() >= 0);
mDirectoryLockId = mDirectoryLock->Id(); mDirectoryLockId = mDirectoryLockHandle->Id();
auto cleanupAndReturn = [self = RefPtr(this)](const nsresult rv) { auto cleanupAndReturn = [self = RefPtr(this)](const nsresult rv) {
self->SetFailureCodeIfUnset(rv); self->SetFailureCodeIfUnset(rv);
@@ -15163,7 +15169,7 @@ void FactoryOp::DirectoryLockAcquired(ClientDirectoryLock* aLock) {
MOZ_ALWAYS_SUCCEEDS(self->Run()); MOZ_ALWAYS_SUCCEEDS(self->Run());
}; };
if (mDirectoryLock->Invalidated()) { if (mDirectoryLockHandle->Invalidated()) {
return cleanupAndReturn(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR); return cleanupAndReturn(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
} }
@@ -15173,7 +15179,7 @@ void FactoryOp::DirectoryLockAcquired(ClientDirectoryLock* aLock) {
void FactoryOp::DirectoryLockFailed() { void FactoryOp::DirectoryLockFailed() {
AssertIsOnOwningThread(); AssertIsOnOwningThread();
MOZ_ASSERT(mState == State::DirectoryOpenPending); MOZ_ASSERT(mState == State::DirectoryOpenPending);
MOZ_ASSERT(!mDirectoryLock); MOZ_ASSERT(!mDirectoryLockHandle);
if (!HasFailed()) { if (!HasFailed()) {
IDB_REPORT_INTERNAL_ERR(); IDB_REPORT_INTERNAL_ERR();
@@ -15999,7 +16005,7 @@ void OpenDatabaseOp::SendResults() {
} }
if (mDatabase) { if (mDatabase) {
MOZ_ASSERT(!mDirectoryLock); MOZ_ASSERT(!mDirectoryLockHandle);
if (HasFailed()) { if (HasFailed()) {
mDatabase->Invalidate(); mDatabase->Invalidate();
@@ -16009,7 +16015,7 @@ void OpenDatabaseOp::SendResults() {
mDatabase = nullptr; mDatabase = nullptr;
CleanupMetadata(); CleanupMetadata();
} else if (mDirectoryLock) { } else if (mDirectoryLockHandle) {
// ConnectionClosedCallback will call CleanupMetadata(). // ConnectionClosedCallback will call CleanupMetadata().
nsCOMPtr<nsIRunnable> callback = NewRunnableMethod( nsCOMPtr<nsIRunnable> callback = NewRunnableMethod(
"dom::indexedDB::OpenDatabaseOp::ConnectionClosedCallback", this, "dom::indexedDB::OpenDatabaseOp::ConnectionClosedCallback", this,
@@ -16028,9 +16034,11 @@ void OpenDatabaseOp::SendResults() {
void OpenDatabaseOp::ConnectionClosedCallback() { void OpenDatabaseOp::ConnectionClosedCallback() {
AssertIsOnOwningThread(); AssertIsOnOwningThread();
MOZ_ASSERT(HasFailed()); MOZ_ASSERT(HasFailed());
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
DropDirectoryLock(mDirectoryLock); {
auto destroyingDirectoryLockHandle = std::move(mDirectoryLockHandle);
}
CleanupMetadata(); CleanupMetadata();
} }
@@ -16066,7 +16074,7 @@ void OpenDatabaseOp::EnsureDatabaseActor() {
MOZ_RELEASE_ASSERT(mInPrivateBrowsing == maybeKey.isSome()); MOZ_RELEASE_ASSERT(mInPrivateBrowsing == maybeKey.isSome());
const bool directoryLockInvalidated = mDirectoryLock->Invalidated(); const bool directoryLockInvalidated = mDirectoryLockHandle->Invalidated();
// XXX Shouldn't Manager() return already_AddRefed when // XXX Shouldn't Manager() return already_AddRefed when
// PBackgroundIDBFactoryParent is declared refcounted? // PBackgroundIDBFactoryParent is declared refcounted?
@@ -16075,7 +16083,7 @@ void OpenDatabaseOp::EnsureDatabaseActor() {
AcquireStrongRefFromRawPtr{}}, AcquireStrongRefFromRawPtr{}},
mCommonParams.principalInfo(), mContentParentId, mOriginMetadata, mCommonParams.principalInfo(), mContentParentId, mOriginMetadata,
mTelemetryId, mMetadata.clonePtr(), mFileManager.clonePtr(), mTelemetryId, mMetadata.clonePtr(), mFileManager.clonePtr(),
std::move(mDirectoryLock), mInPrivateBrowsing, maybeKey); std::move(mDirectoryLockHandle), mInPrivateBrowsing, maybeKey);
if (info) { if (info) {
info->mLiveDatabases.AppendElement( info->mLiveDatabases.AppendElement(
@@ -16627,7 +16635,9 @@ void DeleteDatabaseOp::SendResults() {
response); response);
} }
SafeDropDirectoryLock(mDirectoryLock); {
auto destroyingDirectoryLockHandle = std::move(mDirectoryLockHandle);
}
CleanupMetadata(); CleanupMetadata();
@@ -16987,7 +16997,9 @@ void GetDatabasesOp::SendResults() {
mResolver(mDatabaseMetadataArray); mResolver(mDatabaseMetadataArray);
} }
SafeDropDirectoryLock(mDirectoryLock); {
auto destroyingDirectoryLockHandle = std::move(mDirectoryLockHandle);
}
CleanupMetadata(); CleanupMetadata();

View File

@@ -76,9 +76,8 @@
#include "mozilla/dom/quota/CheckedUnsafePtr.h" #include "mozilla/dom/quota/CheckedUnsafePtr.h"
#include "mozilla/dom/quota/Client.h" #include "mozilla/dom/quota/Client.h"
#include "mozilla/dom/quota/ClientDirectoryLock.h" #include "mozilla/dom/quota/ClientDirectoryLock.h"
#include "mozilla/dom/quota/ClientDirectoryLockHandle.h"
#include "mozilla/dom/quota/ClientImpl.h" #include "mozilla/dom/quota/ClientImpl.h"
#include "mozilla/dom/quota/DirectoryLock.h"
#include "mozilla/dom/quota/DirectoryLockInlines.h"
#include "mozilla/dom/quota/FirstInitializationAttemptsImpl.h" #include "mozilla/dom/quota/FirstInitializationAttemptsImpl.h"
#include "mozilla/dom/quota/HashKeys.h" #include "mozilla/dom/quota/HashKeys.h"
#include "mozilla/dom/quota/OriginScope.h" #include "mozilla/dom/quota/OriginScope.h"
@@ -1470,7 +1469,7 @@ class ConnectionThread final {
*/ */
class Datastore final class Datastore final
: public SupportsCheckedUnsafePtr<CheckIf<DiagnosticAssertEnabled>> { : public SupportsCheckedUnsafePtr<CheckIf<DiagnosticAssertEnabled>> {
RefPtr<ClientDirectoryLock> mDirectoryLock; ClientDirectoryLockHandle mDirectoryLockHandle;
RefPtr<Connection> mConnection; RefPtr<Connection> mConnection;
RefPtr<QuotaObject> mQuotaObject; RefPtr<QuotaObject> mQuotaObject;
nsCOMPtr<nsIRunnable> mCompleteCallback; nsCOMPtr<nsIRunnable> mCompleteCallback;
@@ -1525,7 +1524,7 @@ class Datastore final
// Created by PrepareDatastoreOp. // Created by PrepareDatastoreOp.
Datastore(const OriginMetadata& aOriginMetadata, uint32_t aPrivateBrowsingId, Datastore(const OriginMetadata& aOriginMetadata, uint32_t aPrivateBrowsingId,
int64_t aUsage, int64_t aSizeOfKeys, int64_t aSizeOfItems, int64_t aUsage, int64_t aSizeOfKeys, int64_t aSizeOfItems,
RefPtr<ClientDirectoryLock>&& aDirectoryLock, ClientDirectoryLockHandle&& aDirectoryLockHandle,
RefPtr<Connection>&& aConnection, RefPtr<Connection>&& aConnection,
RefPtr<QuotaObject>&& aQuotaObject, RefPtr<QuotaObject>&& aQuotaObject,
nsTHashMap<nsStringHashKey, LSValue>& aValues, nsTHashMap<nsStringHashKey, LSValue>& aValues,
@@ -1534,7 +1533,7 @@ class Datastore final
Maybe<ClientDirectoryLock&> MaybeDirectoryLockRef() const { Maybe<ClientDirectoryLock&> MaybeDirectoryLockRef() const {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
return ToMaybeRef(mDirectoryLock.get()); return ToMaybeRef(mDirectoryLockHandle.get());
} }
const nsCString& Origin() const { return mOriginMetadata.mOrigin; } const nsCString& Origin() const { return mOriginMetadata.mOrigin; }
@@ -2285,8 +2284,8 @@ class PrepareDatastoreOp
mozilla::glean::TimerId mProcessingTimerId; mozilla::glean::TimerId mProcessingTimerId;
RefPtr<ClientDirectoryLock> mPendingDirectoryLock; RefPtr<ClientDirectoryLock> mPendingDirectoryLock;
RefPtr<ClientDirectoryLock> mDirectoryLock; ClientDirectoryLockHandle mDirectoryLockHandle;
RefPtr<ClientDirectoryLock> mExtraDirectoryLock; ClientDirectoryLockHandle mExtraDirectoryLockHandle;
RefPtr<Connection> mConnection; RefPtr<Connection> mConnection;
RefPtr<Datastore> mDatastore; RefPtr<Datastore> mDatastore;
UniquePtr<ArchivedOriginScope> mArchivedOriginScope; UniquePtr<ArchivedOriginScope> mArchivedOriginScope;
@@ -2325,11 +2324,11 @@ class PrepareDatastoreOp
Maybe<ClientDirectoryLock&> MaybeDirectoryLockRef() const { Maybe<ClientDirectoryLock&> MaybeDirectoryLockRef() const {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
if (mDirectoryLock) { if (mDirectoryLockHandle) {
return SomeRef(*mDirectoryLock); return SomeRef(*mDirectoryLockHandle);
} }
if (mExtraDirectoryLock) { if (mExtraDirectoryLockHandle) {
return SomeRef(*mExtraDirectoryLock); return SomeRef(*mExtraDirectoryLockHandle);
} }
return Nothing(); return Nothing();
} }
@@ -2413,7 +2412,7 @@ class PrepareDatastoreOp
// IPDL overrides. // IPDL overrides.
void ActorDestroy(ActorDestroyReason aWhy) override; void ActorDestroy(ActorDestroyReason aWhy) override;
void DirectoryLockAcquired(ClientDirectoryLock* aLock); void DirectoryLockAcquired(ClientDirectoryLockHandle aLockHandle);
void DirectoryLockFailed(); void DirectoryLockFailed();
}; };
@@ -4443,12 +4442,12 @@ void ConnectionThread::Shutdown() {
Datastore::Datastore(const OriginMetadata& aOriginMetadata, Datastore::Datastore(const OriginMetadata& aOriginMetadata,
uint32_t aPrivateBrowsingId, int64_t aUsage, uint32_t aPrivateBrowsingId, int64_t aUsage,
int64_t aSizeOfKeys, int64_t aSizeOfItems, int64_t aSizeOfKeys, int64_t aSizeOfItems,
RefPtr<ClientDirectoryLock>&& aDirectoryLock, ClientDirectoryLockHandle&& aDirectoryLockHandle,
RefPtr<Connection>&& aConnection, RefPtr<Connection>&& aConnection,
RefPtr<QuotaObject>&& aQuotaObject, RefPtr<QuotaObject>&& aQuotaObject,
nsTHashMap<nsStringHashKey, LSValue>& aValues, nsTHashMap<nsStringHashKey, LSValue>& aValues,
nsTArray<LSItemInfo>&& aOrderedItems) nsTArray<LSItemInfo>&& aOrderedItems)
: mDirectoryLock(std::move(aDirectoryLock)), : mDirectoryLockHandle(std::move(aDirectoryLockHandle)),
mConnection(std::move(aConnection)), mConnection(std::move(aConnection)),
mQuotaObject(std::move(aQuotaObject)), mQuotaObject(std::move(aQuotaObject)),
mOrderedItems(std::move(aOrderedItems)), mOrderedItems(std::move(aOrderedItems)),
@@ -4477,7 +4476,7 @@ void Datastore::Close() {
MOZ_ASSERT(!mPrepareDatastoreOps.Count()); MOZ_ASSERT(!mPrepareDatastoreOps.Count());
MOZ_ASSERT(!mPreparedDatastores.Count()); MOZ_ASSERT(!mPreparedDatastores.Count());
MOZ_ASSERT(!mDatabases.Count()); MOZ_ASSERT(!mDatabases.Count());
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
mClosed = true; mClosed = true;
@@ -4498,7 +4497,9 @@ void Datastore::Close() {
// There's no connection, so it's safe to release the directory lock and // There's no connection, so it's safe to release the directory lock and
// unregister itself from the hashtable. // unregister itself from the hashtable.
DropDirectoryLock(mDirectoryLock); {
auto destroyingDirectoryLockHandle = std::move(mDirectoryLockHandle);
}
CleanupMetadata(); CleanupMetadata();
} }
@@ -4518,7 +4519,7 @@ void Datastore::NoteLivePrepareDatastoreOp(
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(aPrepareDatastoreOp); MOZ_ASSERT(aPrepareDatastoreOp);
MOZ_ASSERT(!mPrepareDatastoreOps.Contains(aPrepareDatastoreOp)); MOZ_ASSERT(!mPrepareDatastoreOps.Contains(aPrepareDatastoreOp));
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
MOZ_ASSERT(!mClosed); MOZ_ASSERT(!mClosed);
mPrepareDatastoreOps.Insert(aPrepareDatastoreOp); mPrepareDatastoreOps.Insert(aPrepareDatastoreOp);
@@ -4529,7 +4530,7 @@ void Datastore::NoteFinishedPrepareDatastoreOp(
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(aPrepareDatastoreOp); MOZ_ASSERT(aPrepareDatastoreOp);
MOZ_ASSERT(mPrepareDatastoreOps.Contains(aPrepareDatastoreOp)); MOZ_ASSERT(mPrepareDatastoreOps.Contains(aPrepareDatastoreOp));
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
MOZ_ASSERT(!mClosed); MOZ_ASSERT(!mClosed);
mPrepareDatastoreOps.Remove(aPrepareDatastoreOp); mPrepareDatastoreOps.Remove(aPrepareDatastoreOp);
@@ -4543,7 +4544,7 @@ void Datastore::NoteFinishedPrepareDatastoreOp(
void Datastore::NoteLivePrivateDatastore() { void Datastore::NoteLivePrivateDatastore() {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(!mHasLivePrivateDatastore); MOZ_ASSERT(!mHasLivePrivateDatastore);
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
MOZ_ASSERT(!mClosed); MOZ_ASSERT(!mClosed);
mHasLivePrivateDatastore = true; mHasLivePrivateDatastore = true;
@@ -4552,7 +4553,7 @@ void Datastore::NoteLivePrivateDatastore() {
void Datastore::NoteFinishedPrivateDatastore() { void Datastore::NoteFinishedPrivateDatastore() {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(mHasLivePrivateDatastore); MOZ_ASSERT(mHasLivePrivateDatastore);
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
MOZ_ASSERT(!mClosed); MOZ_ASSERT(!mClosed);
mHasLivePrivateDatastore = false; mHasLivePrivateDatastore = false;
@@ -4568,7 +4569,7 @@ void Datastore::NoteLivePreparedDatastore(
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(aPreparedDatastore); MOZ_ASSERT(aPreparedDatastore);
MOZ_ASSERT(!mPreparedDatastores.Contains(aPreparedDatastore)); MOZ_ASSERT(!mPreparedDatastores.Contains(aPreparedDatastore));
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
MOZ_ASSERT(!mClosed); MOZ_ASSERT(!mClosed);
mPreparedDatastores.Insert(aPreparedDatastore); mPreparedDatastores.Insert(aPreparedDatastore);
@@ -4579,7 +4580,7 @@ void Datastore::NoteFinishedPreparedDatastore(
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(aPreparedDatastore); MOZ_ASSERT(aPreparedDatastore);
MOZ_ASSERT(mPreparedDatastores.Contains(aPreparedDatastore)); MOZ_ASSERT(mPreparedDatastores.Contains(aPreparedDatastore));
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
MOZ_ASSERT(!mClosed); MOZ_ASSERT(!mClosed);
mPreparedDatastores.Remove(aPreparedDatastore); mPreparedDatastores.Remove(aPreparedDatastore);
@@ -4606,7 +4607,7 @@ void Datastore::NoteLiveDatabase(Database* aDatabase) {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(aDatabase); MOZ_ASSERT(aDatabase);
MOZ_ASSERT(!mDatabases.Contains(aDatabase)); MOZ_ASSERT(!mDatabases.Contains(aDatabase));
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
MOZ_ASSERT(!mClosed); MOZ_ASSERT(!mClosed);
mDatabases.Insert(aDatabase); mDatabases.Insert(aDatabase);
@@ -4619,7 +4620,7 @@ void Datastore::NoteFinishedDatabase(Database* aDatabase) {
MOZ_ASSERT(aDatabase); MOZ_ASSERT(aDatabase);
MOZ_ASSERT(mDatabases.Contains(aDatabase)); MOZ_ASSERT(mDatabases.Contains(aDatabase));
MOZ_ASSERT(!mActiveDatabases.Contains(aDatabase)); MOZ_ASSERT(!mActiveDatabases.Contains(aDatabase));
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
MOZ_ASSERT(!mClosed); MOZ_ASSERT(!mClosed);
mDatabases.Remove(aDatabase); mDatabases.Remove(aDatabase);
@@ -5170,7 +5171,7 @@ void Datastore::Stringify(nsACString& aResult) const {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
aResult.AppendLiteral("DirectoryLock:"); aResult.AppendLiteral("DirectoryLock:");
aResult.AppendInt(!!mDirectoryLock); aResult.AppendInt(!!mDirectoryLockHandle);
aResult.Append(kQuotaGenericDelimiter); aResult.Append(kQuotaGenericDelimiter);
aResult.AppendLiteral("Connection:"); aResult.AppendLiteral("Connection:");
@@ -5247,7 +5248,7 @@ void Datastore::MaybeClose() {
void Datastore::ConnectionClosedCallback() { void Datastore::ConnectionClosedCallback() {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
MOZ_ASSERT(mConnection); MOZ_ASSERT(mConnection);
MOZ_ASSERT(mQuotaObject); MOZ_ASSERT(mQuotaObject);
MOZ_ASSERT(mClosed); MOZ_ASSERT(mClosed);
@@ -5274,7 +5275,9 @@ void Datastore::ConnectionClosedCallback() {
// Now it's safe to release the directory lock and unregister itself from // Now it's safe to release the directory lock and unregister itself from
// the hashtable. // the hashtable.
DropDirectoryLock(mDirectoryLock); {
auto destroyingDirectoryLockHandle = std::move(mDirectoryLockHandle);
}
CleanupMetadata(); CleanupMetadata();
@@ -6633,8 +6636,8 @@ PrepareDatastoreOp::PrepareDatastoreOp(
} }
PrepareDatastoreOp::~PrepareDatastoreOp() { PrepareDatastoreOp::~PrepareDatastoreOp() {
MOZ_DIAGNOSTIC_ASSERT(!mDirectoryLock); MOZ_DIAGNOSTIC_ASSERT(mDirectoryLockHandle.IsInert());
MOZ_DIAGNOSTIC_ASSERT(!mExtraDirectoryLock); MOZ_DIAGNOSTIC_ASSERT(mExtraDirectoryLockHandle.IsInert());
MOZ_ASSERT_IF(MayProceedOnNonOwningThread(), MOZ_ASSERT_IF(MayProceedOnNonOwningThread(),
mState == State::Initial || mState == State::Completed); mState == State::Initial || mState == State::Completed);
MOZ_ASSERT(!mLoadDataOp); MOZ_ASSERT(!mLoadDataOp);
@@ -6793,7 +6796,7 @@ nsresult PrepareDatastoreOp::OpenDirectory() {
AssertIsOnOwningThread(); AssertIsOnOwningThread();
MOZ_ASSERT(mState == State::Nesting); MOZ_ASSERT(mState == State::Nesting);
MOZ_ASSERT(mNestedState == NestedState::OpenDirectory); MOZ_ASSERT(mNestedState == NestedState::OpenDirectory);
MOZ_ASSERT(!mDirectoryLock); MOZ_ASSERT(!mDirectoryLockHandle);
if (NS_WARN_IF(QuotaClient::IsShuttingDownOnBackgroundThread()) || if (NS_WARN_IF(QuotaClient::IsShuttingDownOnBackgroundThread()) ||
!MayProceed()) { !MayProceed()) {
@@ -6853,12 +6856,12 @@ nsresult PrepareDatastoreOp::OpenDirectory() {
/* aCreateIfNonExistent */ false, SomeRef(mPendingDirectoryLock)) /* aCreateIfNonExistent */ false, SomeRef(mPendingDirectoryLock))
->Then( ->Then(
GetCurrentSerialEventTarget(), __func__, GetCurrentSerialEventTarget(), __func__,
[self = RefPtr(this)]( [self = RefPtr(this)](QuotaManager::ClientDirectoryLockHandlePromise::
const ClientDirectoryLockPromise::ResolveOrRejectValue& aValue) { ResolveOrRejectValue&& aValue) {
self->mPendingDirectoryLock = nullptr; self->mPendingDirectoryLock = nullptr;
if (aValue.IsResolve()) { if (aValue.IsResolve()) {
self->DirectoryLockAcquired(aValue.ResolveValue()); self->DirectoryLockAcquired(std::move(aValue.ResolveValue()));
} else { } else {
self->DirectoryLockFailed(); self->DirectoryLockFailed();
} }
@@ -6968,7 +6971,7 @@ nsresult PrepareDatastoreOp::BeginDatastorePreparationInternal() {
if ((mDatastore = GetDatastore(Origin()))) { if ((mDatastore = GetDatastore(Origin()))) {
MOZ_ASSERT(!mDatastore->IsClosed()); MOZ_ASSERT(!mDatastore->IsClosed());
mExtraDirectoryLock = std::move(mDirectoryLock); mExtraDirectoryLockHandle = std::move(mDirectoryLockHandle);
mDatastore->NoteLivePrepareDatastoreOp(this); mDatastore->NoteLivePrepareDatastoreOp(this);
@@ -7542,12 +7545,12 @@ void PrepareDatastoreOp::GetResponse(LSRequestResponse& aResponse) {
} }
} }
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
MOZ_ASSERT_IF(mDirectoryLock->Invalidated(), mInvalidated); MOZ_ASSERT_IF(mDirectoryLockHandle->Invalidated(), mInvalidated);
mDatastore = new Datastore( mDatastore = new Datastore(
mOriginMetadata, mPrivateBrowsingId, mUsage, mSizeOfKeys, mSizeOfItems, mOriginMetadata, mPrivateBrowsingId, mUsage, mSizeOfKeys, mSizeOfItems,
std::move(mDirectoryLock), std::move(mConnection), std::move(mDirectoryLockHandle), std::move(mConnection),
std::move(quotaObject), mValues, std::move(mOrderedItems)); std::move(quotaObject), mValues, std::move(mOrderedItems));
mDatastore->NoteLivePrepareDatastoreOp(this); mDatastore->NoteLivePrepareDatastoreOp(this);
@@ -7628,7 +7631,7 @@ void PrepareDatastoreOp::Cleanup() {
AssertIsOnOwningThread(); AssertIsOnOwningThread();
if (mDatastore) { if (mDatastore) {
MOZ_ASSERT(!mDirectoryLock); MOZ_ASSERT(!mDirectoryLockHandle);
MOZ_ASSERT(!mConnection); MOZ_ASSERT(!mConnection);
if (NS_FAILED(ResultCode())) { if (NS_FAILED(ResultCode())) {
@@ -7663,15 +7666,17 @@ void PrepareDatastoreOp::Cleanup() {
mDatastore = nullptr; mDatastore = nullptr;
SafeDropDirectoryLock(mExtraDirectoryLock); {
auto extraDirectoryLockHandle = std::move(mExtraDirectoryLockHandle);
}
CleanupMetadata(); CleanupMetadata();
} else if (mConnection) { } else if (mConnection) {
// If we have a connection then the operation must have failed and there // If we have a connection then the operation must have failed and there
// must be a directory lock too. // must be a directory lock too.
MOZ_ASSERT(NS_FAILED(ResultCode())); MOZ_ASSERT(NS_FAILED(ResultCode()));
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
MOZ_ASSERT(!mExtraDirectoryLock); MOZ_ASSERT(!mExtraDirectoryLockHandle);
// We must close the connection on the connection thread before releasing // We must close the connection on the connection thread before releasing
// it on this thread. The directory lock can't be released either. // it on this thread. The directory lock can't be released either.
@@ -7684,14 +7689,16 @@ void PrepareDatastoreOp::Cleanup() {
// If we don't have a connection, but we do have a directory lock then the // If we don't have a connection, but we do have a directory lock then the
// operation must have failed or we were preloading a datastore and there // operation must have failed or we were preloading a datastore and there
// was no physical database on disk. // was no physical database on disk.
MOZ_ASSERT_IF(mDirectoryLock, MOZ_ASSERT_IF(mDirectoryLockHandle,
NS_FAILED(ResultCode()) || mDatabaseNotAvailable); NS_FAILED(ResultCode()) || mDatabaseNotAvailable);
MOZ_ASSERT(!mExtraDirectoryLock); MOZ_ASSERT(!mExtraDirectoryLockHandle);
// There's no connection, so it's safe to release the directory lock and // There's no connection, so it's safe to release the directory lock and
// unregister itself from the array. // unregister itself from the array.
SafeDropDirectoryLock(mDirectoryLock); {
auto destroyingDdirectoryLockHandle = std::move(mDirectoryLockHandle);
}
CleanupMetadata(); CleanupMetadata();
} }
@@ -7700,12 +7707,14 @@ void PrepareDatastoreOp::Cleanup() {
void PrepareDatastoreOp::ConnectionClosedCallback() { void PrepareDatastoreOp::ConnectionClosedCallback() {
AssertIsOnOwningThread(); AssertIsOnOwningThread();
MOZ_ASSERT(NS_FAILED(ResultCode())); MOZ_ASSERT(NS_FAILED(ResultCode()));
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
MOZ_ASSERT(mConnection); MOZ_ASSERT(mConnection);
mConnection = nullptr; mConnection = nullptr;
DropDirectoryLock(mDirectoryLock); {
auto destroyingDirectoryLockHandle = std::move(mDirectoryLockHandle);
}
CleanupMetadata(); CleanupMetadata();
} }
@@ -7747,18 +7756,19 @@ void PrepareDatastoreOp::ActorDestroy(ActorDestroyReason aWhy) {
} }
} }
void PrepareDatastoreOp::DirectoryLockAcquired(ClientDirectoryLock* aLock) { void PrepareDatastoreOp::DirectoryLockAcquired(
ClientDirectoryLockHandle aLockHandle) {
AssertIsOnOwningThread(); AssertIsOnOwningThread();
MOZ_ASSERT(mState == State::Nesting); MOZ_ASSERT(mState == State::Nesting);
MOZ_ASSERT(mNestedState == NestedState::DirectoryOpenPending); MOZ_ASSERT(mNestedState == NestedState::DirectoryOpenPending);
MOZ_ASSERT(!mDirectoryLock); MOZ_ASSERT(!mDirectoryLockHandle);
mPendingDirectoryLock = nullptr; mPendingDirectoryLock = nullptr;
mDirectoryLock = aLock; mDirectoryLockHandle = std::move(aLockHandle);
if (NS_WARN_IF(QuotaClient::IsShuttingDownOnBackgroundThread()) || if (NS_WARN_IF(QuotaClient::IsShuttingDownOnBackgroundThread()) ||
!MayProceed() || mDirectoryLock->Invalidated()) { !MayProceed() || mDirectoryLockHandle->Invalidated()) {
MaybeSetFailureCode(NS_ERROR_ABORT); MaybeSetFailureCode(NS_ERROR_ABORT);
FinishNesting(); FinishNesting();
@@ -7777,7 +7787,7 @@ void PrepareDatastoreOp::DirectoryLockFailed() {
AssertIsOnOwningThread(); AssertIsOnOwningThread();
MOZ_ASSERT(mState == State::Nesting); MOZ_ASSERT(mState == State::Nesting);
MOZ_ASSERT(mNestedState == NestedState::DirectoryOpenPending); MOZ_ASSERT(mNestedState == NestedState::DirectoryOpenPending);
MOZ_ASSERT(!mDirectoryLock); MOZ_ASSERT(!mDirectoryLockHandle);
mPendingDirectoryLock = nullptr; mPendingDirectoryLock = nullptr;

View File

@@ -94,6 +94,7 @@
#include "mozilla/dom/quota/CheckedUnsafePtr.h" #include "mozilla/dom/quota/CheckedUnsafePtr.h"
#include "mozilla/dom/quota/Client.h" #include "mozilla/dom/quota/Client.h"
#include "mozilla/dom/quota/ClientDirectoryLock.h" #include "mozilla/dom/quota/ClientDirectoryLock.h"
#include "mozilla/dom/quota/ClientDirectoryLockHandle.h"
#include "mozilla/dom/quota/Config.h" #include "mozilla/dom/quota/Config.h"
#include "mozilla/dom/quota/Constants.h" #include "mozilla/dom/quota/Constants.h"
#include "mozilla/dom/quota/DirectoryLockInlines.h" #include "mozilla/dom/quota/DirectoryLockInlines.h"
@@ -5486,7 +5487,8 @@ RefPtr<UniversalDirectoryLockPromise> QuotaManager::OpenStorageDirectory(
}); });
} }
RefPtr<ClientDirectoryLockPromise> QuotaManager::OpenClientDirectory( RefPtr<QuotaManager::ClientDirectoryLockHandlePromise>
QuotaManager::OpenClientDirectory(
const ClientMetadata& aClientMetadata, bool aInitializeOrigin, const ClientMetadata& aClientMetadata, bool aInitializeOrigin,
bool aCreateIfNonExistent, bool aCreateIfNonExistent,
Maybe<RefPtr<ClientDirectoryLock>&> aPendingDirectoryLockOut) { Maybe<RefPtr<ClientDirectoryLock>&> aPendingDirectoryLockOut) {
@@ -5554,7 +5556,7 @@ RefPtr<ClientDirectoryLockPromise> QuotaManager::OpenClientDirectory(
aPendingDirectoryLockOut.ref() = clientDirectoryLock; aPendingDirectoryLockOut.ref() = clientDirectoryLock;
} }
RefPtr<ClientDirectoryLockPromise> promise = RefPtr<ClientDirectoryLockHandlePromise> promise =
BoolPromise::All(GetCurrentSerialEventTarget(), promises) BoolPromise::All(GetCurrentSerialEventTarget(), promises)
->Then( ->Then(
GetCurrentSerialEventTarget(), __func__, GetCurrentSerialEventTarget(), __func__,
@@ -5595,27 +5597,32 @@ RefPtr<ClientDirectoryLockPromise> QuotaManager::OpenClientDirectory(
aClientMetadata, aCreateIfNonExistent, aClientMetadata, aCreateIfNonExistent,
std::move(originDirectoryLock)); std::move(originDirectoryLock));
})) }))
->Then(GetCurrentSerialEventTarget(), __func__, ->Then(
GetCurrentSerialEventTarget(), __func__,
[clientDirectoryLock = std::move(clientDirectoryLock)]( [clientDirectoryLock = std::move(clientDirectoryLock)](
const BoolPromise::ResolveOrRejectValue& aValue) mutable { const BoolPromise::ResolveOrRejectValue& aValue) mutable {
if (aValue.IsReject()) { if (aValue.IsReject()) {
DropDirectoryLockIfNotDropped(clientDirectoryLock); DropDirectoryLockIfNotDropped(clientDirectoryLock);
return ClientDirectoryLockPromise::CreateAndReject( return ClientDirectoryLockHandlePromise::CreateAndReject(
aValue.RejectValue(), __func__); aValue.RejectValue(), __func__);
} }
QM_TRY(ArtificialFailure(nsIQuotaArtificialFailure:: QM_TRY(
ArtificialFailure(nsIQuotaArtificialFailure::
CATEGORY_OPEN_CLIENT_DIRECTORY), CATEGORY_OPEN_CLIENT_DIRECTORY),
[&clientDirectoryLock](nsresult rv) { [&clientDirectoryLock](nsresult rv) {
DropDirectoryLockIfNotDropped(clientDirectoryLock); DropDirectoryLockIfNotDropped(clientDirectoryLock);
return ClientDirectoryLockPromise::CreateAndReject( return ClientDirectoryLockHandlePromise::CreateAndReject(
rv, __func__); rv, __func__);
}); });
return ClientDirectoryLockPromise::CreateAndResolve( auto clientDirectoryLockHandle =
std::move(clientDirectoryLock), __func__); ClientDirectoryLockHandle(std::move(clientDirectoryLock));
return ClientDirectoryLockHandlePromise::CreateAndResolve(
std::move(clientDirectoryLockHandle), __func__);
}); });
NotifyClientDirectoryOpeningStarted(*this); NotifyClientDirectoryOpeningStarted(*this);

View File

@@ -20,15 +20,14 @@ class ClientDirectoryLock;
* @brief RAII-style wrapper for managing a ClientDirectoryLock. * @brief RAII-style wrapper for managing a ClientDirectoryLock.
* *
* ClientDirectoryLockHandle is a RAII-style wrapper that manages a * ClientDirectoryLockHandle is a RAII-style wrapper that manages a
* ClientDirectoryLock. It is designed to ensure that the associated directory * ClientDirectoryLock created by QuotaManager::OpenClientDirectory.
* lock remains acquired while the handle is in scope and is automatically
* released when destroyed.
* *
* This class will be used by OpenClientDirectory to manage the lifetime of * This class ensures that the associated directory lock remains acquired
* directory locks in a safer and clearer way. * while the handle is in scope and automatically drops it when destroyed.
* *
* ## Usage: * ## Usage:
* - Intended for use with QuotaManager::OpenClientDirectory. * - See QuotaManager::OpenClientDirectory for details on obtaining a
* ClientDirectoryLockHandle.
* - The handle should be retained for as long as access to the directory is * - The handle should be retained for as long as access to the directory is
* needed. * needed.
* *

View File

@@ -73,6 +73,7 @@ class ClearRequestBase;
class ClientStorageScope; class ClientStorageScope;
class ClientUsageArray; class ClientUsageArray;
class ClientDirectoryLock; class ClientDirectoryLock;
class ClientDirectoryLockHandle;
class DirectoryLockImpl; class DirectoryLockImpl;
class GroupInfo; class GroupInfo;
class GroupInfoPair; class GroupInfoPair;
@@ -121,6 +122,9 @@ class QuotaManager final : public BackgroundThreadObject {
class Observer; class Observer;
public: public:
using ClientDirectoryLockHandlePromise =
MozPromise<ClientDirectoryLockHandle, nsresult, true>;
QuotaManager(const nsAString& aBasePath, const nsAString& aStorageName); QuotaManager(const nsAString& aBasePath, const nsAString& aStorageName);
NS_INLINE_DECL_REFCOUNTING(QuotaManager) NS_INLINE_DECL_REFCOUNTING(QuotaManager)
@@ -303,23 +307,29 @@ class QuotaManager final : public BackgroundThreadObject {
// This is the main entry point into the QuotaManager API. // This is the main entry point into the QuotaManager API.
// Any storage API implementation (quota client) that participates in // Any storage API implementation (quota client) that participates in
// centralized quota and storage handling should call this method to get // centralized quota and storage handling should call this method to obtain
// a directory lock which will protect client's files from being deleted // a directory lock, ensuring the clients files are protected from deletion
// while they are still in use. // while in use.
// After a lock is acquired, client is notified by resolving the returned //
// promise. If the lock couldn't be acquired, client is notified by rejecting // After a lock is acquired, the client is notified by resolving the returned
// the returned promise. The returned lock could have been invalidated by a // promise. If the lock couldn't be acquired, the promise is rejected.
// clear operation so consumers are supposed to check that and eventually //
// release the lock as soon as possible (this is usually not needed for short // The returned lock is encapsulated in ClientDirectoryLockHandle, which
// lived operations). // manages ownership and automatically drops the lock when destroyed. Clients
// A lock is a reference counted object and at the time the returned promise // should retain ownership of the handle for as long as the lock is needed.
// is resolved, there are no longer other strong references except the one //
// held by the resolve value itself. So it's up to client to add a new // The lock may still be invalidated by a clear operation, so consumers
// reference in order to keep the lock alive. // should check its validity and release it as soon as it is no longer
// Unlocking is simply done by calling lock object's Drop method. Unlocking // required.
// must be always done explicitly before the lock object is destroyed (when //
// the last strong reference is removed). // Internally, QuotaManager may perform various initialization steps before
RefPtr<ClientDirectoryLockPromise> OpenClientDirectory( // resolving the promise. This can include storage, temporary storage, group
// and origin initialization.
//
// Optionally, an output parameter (aPendingDirectoryLockOut) can be provided
// to receive a reference to the ClientDirectoryLock before wrapping it in
// ClientDirectoryLockHandle. This allows tracking pending locks separately.
RefPtr<ClientDirectoryLockHandlePromise> OpenClientDirectory(
const ClientMetadata& aClientMetadata, bool aInitializeOrigins = true, const ClientMetadata& aClientMetadata, bool aInitializeOrigins = true,
bool aCreateIfNonExistent = true, bool aCreateIfNonExistent = true,
Maybe<RefPtr<ClientDirectoryLock>&> aPendingDirectoryLockOut = Nothing()); Maybe<RefPtr<ClientDirectoryLock>&> aPendingDirectoryLockOut = Nothing());

View File

@@ -11,6 +11,7 @@
#include "mozilla/MozPromise.h" #include "mozilla/MozPromise.h"
#include "mozilla/SpinEventLoopUntil.h" #include "mozilla/SpinEventLoopUntil.h"
#include "mozilla/dom/quota/ClientDirectoryLock.h" #include "mozilla/dom/quota/ClientDirectoryLock.h"
#include "mozilla/dom/quota/ClientDirectoryLockHandle.h"
#include "mozilla/dom/quota/DirectoryLock.h" #include "mozilla/dom/quota/DirectoryLock.h"
#include "mozilla/dom/quota/DirectoryLockInlines.h" #include "mozilla/dom/quota/DirectoryLockInlines.h"
#include "mozilla/dom/quota/ForwardDecls.h" #include "mozilla/dom/quota/ForwardDecls.h"
@@ -156,7 +157,7 @@ class QuotaManagerDependencyFixture : public testing::Test {
Task&& aTask) { Task&& aTask) {
PerformOnBackgroundThread([clientMetadata = aClientMetadata, PerformOnBackgroundThread([clientMetadata = aClientMetadata,
task = std::forward<Task>(aTask)]() mutable { task = std::forward<Task>(aTask)]() mutable {
RefPtr<ClientDirectoryLock> directoryLock; ClientDirectoryLockHandle directoryLockHandle;
QuotaManager* quotaManager = QuotaManager::Get(); QuotaManager* quotaManager = QuotaManager::Get();
ASSERT_TRUE(quotaManager); ASSERT_TRUE(quotaManager);
@@ -166,9 +167,9 @@ class QuotaManagerDependencyFixture : public testing::Test {
quotaManager->OpenClientDirectory(clientMetadata) quotaManager->OpenClientDirectory(clientMetadata)
->Then( ->Then(
GetCurrentSerialEventTarget(), __func__, GetCurrentSerialEventTarget(), __func__,
[&directoryLock, [&directoryLockHandle,
&done](RefPtr<ClientDirectoryLock> aResolveValue) { &done](ClientDirectoryLockHandle&& aResolveValue) {
directoryLock = std::move(aResolveValue); directoryLockHandle = std::move(aResolveValue);
done = true; done = true;
}, },
@@ -180,11 +181,13 @@ class QuotaManagerDependencyFixture : public testing::Test {
SpinEventLoopUntil("Promise is fulfilled"_ns, [&done]() { return done; }); SpinEventLoopUntil("Promise is fulfilled"_ns, [&done]() { return done; });
ASSERT_TRUE(directoryLock); ASSERT_TRUE(directoryLockHandle);
PerformOnIOThread(std::move(task), directoryLock->Id()); PerformOnIOThread(std::move(task), directoryLockHandle->Id());
DropDirectoryLock(directoryLock); {
auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
}
}); });
} }

View File

@@ -6,6 +6,7 @@
#include "mozilla/dom/quota/Client.h" #include "mozilla/dom/quota/Client.h"
#include "mozilla/dom/quota/ClientDirectoryLock.h" #include "mozilla/dom/quota/ClientDirectoryLock.h"
#include "mozilla/dom/quota/ClientDirectoryLockHandle.h"
#include "mozilla/dom/quota/CommonMetadata.h" #include "mozilla/dom/quota/CommonMetadata.h"
#include "mozilla/dom/quota/FileStreams.h" #include "mozilla/dom/quota/FileStreams.h"
#include "mozilla/dom/quota/QuotaManager.h" #include "mozilla/dom/quota/QuotaManager.h"
@@ -181,7 +182,7 @@ TEST_F(TestFileOutputStream, extendFileStreamWithSetEOF) {
ASSERT_TRUE(0 == avail); ASSERT_TRUE(0 == avail);
}; };
RefPtr<ClientDirectoryLock> directoryLock; ClientDirectoryLockHandle directoryLockHandle;
QuotaManager* quotaManager = QuotaManager::Get(); QuotaManager* quotaManager = QuotaManager::Get();
ASSERT_TRUE(quotaManager); ASSERT_TRUE(quotaManager);
@@ -193,8 +194,9 @@ TEST_F(TestFileOutputStream, extendFileStreamWithSetEOF) {
{GetOutputStreamTestOriginMetadata(), Client::SDB}) {GetOutputStreamTestOriginMetadata(), Client::SDB})
->Then( ->Then(
GetCurrentSerialEventTarget(), __func__, GetCurrentSerialEventTarget(), __func__,
[&directoryLock, &done](RefPtr<ClientDirectoryLock> aResolveValue) { [&directoryLockHandle,
directoryLock = std::move(aResolveValue); &done](ClientDirectoryLockHandle&& aResolveValue) {
directoryLockHandle = std::move(aResolveValue);
done = true; done = true;
}, },
@@ -206,11 +208,13 @@ TEST_F(TestFileOutputStream, extendFileStreamWithSetEOF) {
SpinEventLoopUntil("Promise is fulfilled"_ns, [&done]() { return done; }); SpinEventLoopUntil("Promise is fulfilled"_ns, [&done]() { return done; });
ASSERT_TRUE(directoryLock); ASSERT_TRUE(directoryLockHandle);
PerformOnIOThread(std::move(ioTask)); PerformOnIOThread(std::move(ioTask));
DropDirectoryLock(directoryLock); {
auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
}
}; };
PerformOnBackgroundThread(std::move(backgroundTask)); PerformOnBackgroundThread(std::move(backgroundTask));

View File

@@ -8,6 +8,7 @@
#include "mozilla/BasePrincipal.h" #include "mozilla/BasePrincipal.h"
#include "mozilla/ipc/PBackgroundSharedTypes.h" #include "mozilla/ipc/PBackgroundSharedTypes.h"
#include "mozilla/dom/quota/ClientDirectoryLock.h" #include "mozilla/dom/quota/ClientDirectoryLock.h"
#include "mozilla/dom/quota/ClientDirectoryLockHandle.h"
#include "mozilla/dom/quota/DirectoryLock.h" #include "mozilla/dom/quota/DirectoryLock.h"
#include "mozilla/dom/quota/DirectoryLockInlines.h" #include "mozilla/dom/quota/DirectoryLockInlines.h"
#include "mozilla/dom/quota/OriginScope.h" #include "mozilla/dom/quota/OriginScope.h"
@@ -423,16 +424,16 @@ TEST_F(TestQuotaManager, OpenClientDirectory_OngoingWithScheduledShutdown) {
QuotaManager* quotaManager = QuotaManager::Get(); QuotaManager* quotaManager = QuotaManager::Get();
ASSERT_TRUE(quotaManager); ASSERT_TRUE(quotaManager);
RefPtr<ClientDirectoryLock> directoryLock; ClientDirectoryLockHandle directoryLockHandle;
nsTArray<RefPtr<BoolPromise>> promises; nsTArray<RefPtr<BoolPromise>> promises;
promises.AppendElement( promises.AppendElement(
quotaManager->OpenClientDirectory(GetTestClientMetadata()) quotaManager->OpenClientDirectory(GetTestClientMetadata())
->Then( ->Then(GetCurrentSerialEventTarget(), __func__,
GetCurrentSerialEventTarget(), __func__, [&directoryLockHandle](
[&directoryLock]( QuotaManager::ClientDirectoryLockHandlePromise::
ClientDirectoryLockPromise::ResolveOrRejectValue&& aValue) { ResolveOrRejectValue&& aValue) {
if (aValue.IsReject()) { if (aValue.IsReject()) {
return BoolPromise::CreateAndReject(aValue.RejectValue(), return BoolPromise::CreateAndReject(aValue.RejectValue(),
__func__); __func__);
@@ -440,7 +441,7 @@ TEST_F(TestQuotaManager, OpenClientDirectory_OngoingWithScheduledShutdown) {
[&aValue]() { ASSERT_TRUE(aValue.ResolveValue()); }(); [&aValue]() { ASSERT_TRUE(aValue.ResolveValue()); }();
directoryLock = std::move(aValue.ResolveValue()); directoryLockHandle = std::move(aValue.ResolveValue());
return BoolPromise::CreateAndResolve(true, __func__); return BoolPromise::CreateAndResolve(true, __func__);
}) })
@@ -462,9 +463,12 @@ TEST_F(TestQuotaManager, OpenClientDirectory_OngoingWithScheduledShutdown) {
return BoolPromise::CreateAndResolve(true, __func__); return BoolPromise::CreateAndResolve(true, __func__);
}) })
->Then(GetCurrentSerialEventTarget(), __func__, ->Then(GetCurrentSerialEventTarget(), __func__,
[&directoryLock]( [&directoryLockHandle](
const BoolPromise::ResolveOrRejectValue& aValue) { const BoolPromise::ResolveOrRejectValue& aValue) {
DropDirectoryLock(directoryLock); {
auto destroyingDirectoryLockHandle =
std::move(directoryLockHandle);
}
if (aValue.IsReject()) { if (aValue.IsReject()) {
return BoolPromise::CreateAndReject(aValue.RejectValue(), return BoolPromise::CreateAndReject(aValue.RejectValue(),
@@ -476,17 +480,21 @@ TEST_F(TestQuotaManager, OpenClientDirectory_OngoingWithScheduledShutdown) {
promises.AppendElement(quotaManager->ShutdownStorage()); promises.AppendElement(quotaManager->ShutdownStorage());
promises.AppendElement( promises.AppendElement(
quotaManager->OpenClientDirectory(GetTestClientMetadata()) quotaManager->OpenClientDirectory(GetTestClientMetadata())
->Then( ->Then(GetCurrentSerialEventTarget(), __func__,
GetCurrentSerialEventTarget(), __func__, [](QuotaManager::ClientDirectoryLockHandlePromise::
[](ClientDirectoryLockPromise::ResolveOrRejectValue&& aValue) { ResolveOrRejectValue&& aValue) {
if (aValue.IsReject()) { if (aValue.IsReject()) {
return BoolPromise::CreateAndReject(aValue.RejectValue(), return BoolPromise::CreateAndReject(aValue.RejectValue(),
__func__); __func__);
} }
RefPtr<ClientDirectoryLock> directoryLock = ClientDirectoryLockHandle directoryLockHandle =
std::move(aValue.ResolveValue()); std::move(aValue.ResolveValue());
DropDirectoryLock(directoryLock);
{
auto destroyingDirectoryLockHandle =
std::move(directoryLockHandle);
}
return BoolPromise::CreateAndResolve(true, __func__); return BoolPromise::CreateAndResolve(true, __func__);
})); }));
@@ -527,10 +535,10 @@ TEST_F(TestQuotaManager,
promises.AppendElement( promises.AppendElement(
quotaManager->OpenClientDirectory(GetTestClientMetadata()) quotaManager->OpenClientDirectory(GetTestClientMetadata())
->Then( ->Then(GetCurrentSerialEventTarget(), __func__,
GetCurrentSerialEventTarget(), __func__,
[&directoryLock]( [&directoryLock](
ClientDirectoryLockPromise::ResolveOrRejectValue&& aValue) { QuotaManager::ClientDirectoryLockHandlePromise::
ResolveOrRejectValue&& aValue) {
DropDirectoryLock(directoryLock); DropDirectoryLock(directoryLock);
if (aValue.IsReject()) { if (aValue.IsReject()) {
@@ -538,26 +546,34 @@ TEST_F(TestQuotaManager,
__func__); __func__);
} }
RefPtr<ClientDirectoryLock> directoryLock = ClientDirectoryLockHandle directoryLockHandle =
std::move(aValue.ResolveValue()); std::move(aValue.ResolveValue());
DropDirectoryLock(directoryLock);
{
auto destroyingDirectoryLockHandle =
std::move(directoryLockHandle);
}
return BoolPromise::CreateAndResolve(true, __func__); return BoolPromise::CreateAndResolve(true, __func__);
})); }));
promises.AppendElement(directoryLock->Acquire()); promises.AppendElement(directoryLock->Acquire());
promises.AppendElement( promises.AppendElement(
quotaManager->OpenClientDirectory(GetTestClientMetadata()) quotaManager->OpenClientDirectory(GetTestClientMetadata())
->Then( ->Then(GetCurrentSerialEventTarget(), __func__,
GetCurrentSerialEventTarget(), __func__, [](QuotaManager::ClientDirectoryLockHandlePromise::
[](ClientDirectoryLockPromise::ResolveOrRejectValue&& aValue) { ResolveOrRejectValue&& aValue) {
if (aValue.IsReject()) { if (aValue.IsReject()) {
return BoolPromise::CreateAndReject(aValue.RejectValue(), return BoolPromise::CreateAndReject(aValue.RejectValue(),
__func__); __func__);
} }
RefPtr<ClientDirectoryLock> directoryLock = ClientDirectoryLockHandle directoryLockHandle =
std::move(aValue.ResolveValue()); std::move(aValue.ResolveValue());
DropDirectoryLock(directoryLock);
{
auto destroyingDirectoryLockHandle =
std::move(directoryLockHandle);
}
return BoolPromise::CreateAndResolve(true, __func__); return BoolPromise::CreateAndResolve(true, __func__);
})); }));
@@ -592,9 +608,12 @@ TEST_F(TestQuotaManager, OpenClientDirectory_Finished) {
Await(quotaManager->OpenClientDirectory(GetTestClientMetadata())); Await(quotaManager->OpenClientDirectory(GetTestClientMetadata()));
ASSERT_TRUE(value.IsResolve()); ASSERT_TRUE(value.IsResolve());
RefPtr<ClientDirectoryLock> directoryLock = ClientDirectoryLockHandle directoryLockHandle =
std::move(value.ResolveValue()); std::move(value.ResolveValue());
DropDirectoryLock(directoryLock);
{
auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
}
ASSERT_TRUE(quotaManager->IsStorageInitialized()); ASSERT_TRUE(quotaManager->IsStorageInitialized());
} }
@@ -604,9 +623,12 @@ TEST_F(TestQuotaManager, OpenClientDirectory_Finished) {
Await(quotaManager->OpenClientDirectory(GetTestClientMetadata())); Await(quotaManager->OpenClientDirectory(GetTestClientMetadata()));
ASSERT_TRUE(value.IsResolve()); ASSERT_TRUE(value.IsResolve());
RefPtr<ClientDirectoryLock> directoryLock = ClientDirectoryLockHandle directoryLockHandle =
std::move(value.ResolveValue()); std::move(value.ResolveValue());
DropDirectoryLock(directoryLock);
{
auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
}
ASSERT_TRUE(quotaManager->IsStorageInitialized()); ASSERT_TRUE(quotaManager->IsStorageInitialized());
} }
@@ -633,9 +655,12 @@ TEST_F(TestQuotaManager, OpenClientDirectory_FinishedWithScheduledShutdown) {
Await(quotaManager->OpenClientDirectory(GetTestClientMetadata())); Await(quotaManager->OpenClientDirectory(GetTestClientMetadata()));
ASSERT_TRUE(value.IsResolve()); ASSERT_TRUE(value.IsResolve());
RefPtr<ClientDirectoryLock> directoryLock = ClientDirectoryLockHandle directoryLockHandle =
std::move(value.ResolveValue()); std::move(value.ResolveValue());
DropDirectoryLock(directoryLock);
{
auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
}
ASSERT_TRUE(quotaManager->IsStorageInitialized()); ASSERT_TRUE(quotaManager->IsStorageInitialized());
} }
@@ -645,17 +670,21 @@ TEST_F(TestQuotaManager, OpenClientDirectory_FinishedWithScheduledShutdown) {
promises.AppendElement(quotaManager->ShutdownStorage()); promises.AppendElement(quotaManager->ShutdownStorage());
promises.AppendElement( promises.AppendElement(
quotaManager->OpenClientDirectory(GetTestClientMetadata()) quotaManager->OpenClientDirectory(GetTestClientMetadata())
->Then( ->Then(GetCurrentSerialEventTarget(), __func__,
GetCurrentSerialEventTarget(), __func__, [](QuotaManager::ClientDirectoryLockHandlePromise::
[](ClientDirectoryLockPromise::ResolveOrRejectValue&& aValue) { ResolveOrRejectValue&& aValue) {
if (aValue.IsReject()) { if (aValue.IsReject()) {
return BoolPromise::CreateAndReject(aValue.RejectValue(), return BoolPromise::CreateAndReject(aValue.RejectValue(),
__func__); __func__);
} }
RefPtr<ClientDirectoryLock> directoryLock = ClientDirectoryLockHandle directoryLockHandle =
std::move(aValue.ResolveValue()); std::move(aValue.ResolveValue());
DropDirectoryLock(directoryLock);
{
auto destroyingDirectoryLockHandle =
std::move(directoryLockHandle);
}
return BoolPromise::CreateAndResolve(true, __func__); return BoolPromise::CreateAndResolve(true, __func__);
})); }));
@@ -692,9 +721,12 @@ TEST_F(TestQuotaManager,
Await(quotaManager->OpenClientDirectory(GetTestClientMetadata())); Await(quotaManager->OpenClientDirectory(GetTestClientMetadata()));
ASSERT_TRUE(value.IsResolve()); ASSERT_TRUE(value.IsResolve());
RefPtr<ClientDirectoryLock> directoryLock = ClientDirectoryLockHandle directoryLockHandle =
std::move(value.ResolveValue()); std::move(value.ResolveValue());
DropDirectoryLock(directoryLock);
{
auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
}
ASSERT_TRUE(quotaManager->IsStorageInitialized()); ASSERT_TRUE(quotaManager->IsStorageInitialized());
} }
@@ -713,9 +745,12 @@ TEST_F(TestQuotaManager,
Await(quotaManager->OpenClientDirectory(GetTestClientMetadata())); Await(quotaManager->OpenClientDirectory(GetTestClientMetadata()));
ASSERT_TRUE(value.IsResolve()); ASSERT_TRUE(value.IsResolve());
RefPtr<ClientDirectoryLock> directoryLock = ClientDirectoryLockHandle directoryLockHandle =
std::move(value.ResolveValue()); std::move(value.ResolveValue());
DropDirectoryLock(directoryLock);
{
auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
}
ASSERT_TRUE(quotaManager->IsStorageInitialized()); ASSERT_TRUE(quotaManager->IsStorageInitialized());
} }
@@ -737,15 +772,15 @@ TEST_F(TestQuotaManager, OpenClientDirectory_InitializeOrigin) {
QuotaManager* quotaManager = QuotaManager::Get(); QuotaManager* quotaManager = QuotaManager::Get();
ASSERT_TRUE(quotaManager); ASSERT_TRUE(quotaManager);
RefPtr<ClientDirectoryLock> directoryLock; ClientDirectoryLockHandle directoryLockHandle;
RefPtr<BoolPromise> promise = RefPtr<BoolPromise> promise =
quotaManager quotaManager
->OpenClientDirectory(GetTestClientMetadata(), aInitializeOrigin) ->OpenClientDirectory(GetTestClientMetadata(), aInitializeOrigin)
->Then( ->Then(GetCurrentSerialEventTarget(), __func__,
GetCurrentSerialEventTarget(), __func__, [&directoryLockHandle](
[&directoryLock]( QuotaManager::ClientDirectoryLockHandlePromise::
ClientDirectoryLockPromise::ResolveOrRejectValue&& aValue) { ResolveOrRejectValue&& aValue) {
if (aValue.IsReject()) { if (aValue.IsReject()) {
return BoolPromise::CreateAndReject(aValue.RejectValue(), return BoolPromise::CreateAndReject(aValue.RejectValue(),
__func__); __func__);
@@ -753,7 +788,7 @@ TEST_F(TestQuotaManager, OpenClientDirectory_InitializeOrigin) {
[&aValue]() { ASSERT_TRUE(aValue.ResolveValue()); }(); [&aValue]() { ASSERT_TRUE(aValue.ResolveValue()); }();
directoryLock = std::move(aValue.ResolveValue()); directoryLockHandle = std::move(aValue.ResolveValue());
return BoolPromise::CreateAndResolve(true, __func__); return BoolPromise::CreateAndResolve(true, __func__);
}) })
@@ -778,9 +813,12 @@ TEST_F(TestQuotaManager, OpenClientDirectory_InitializeOrigin) {
return BoolPromise::CreateAndResolve(true, __func__); return BoolPromise::CreateAndResolve(true, __func__);
}) })
->Then(GetCurrentSerialEventTarget(), __func__, ->Then(GetCurrentSerialEventTarget(), __func__,
[&directoryLock]( [&directoryLockHandle](
const BoolPromise::ResolveOrRejectValue& aValue) { const BoolPromise::ResolveOrRejectValue& aValue) {
DropDirectoryLock(directoryLock); {
auto destroyingDirectoryLockHandle =
std::move(directoryLockHandle);
}
if (aValue.IsReject()) { if (aValue.IsReject()) {
return BoolPromise::CreateAndReject(aValue.RejectValue(), return BoolPromise::CreateAndReject(aValue.RejectValue(),

View File

@@ -36,9 +36,8 @@
#include "mozilla/dom/ipc/IdType.h" #include "mozilla/dom/ipc/IdType.h"
#include "mozilla/dom/quota/Client.h" #include "mozilla/dom/quota/Client.h"
#include "mozilla/dom/quota/ClientDirectoryLock.h" #include "mozilla/dom/quota/ClientDirectoryLock.h"
#include "mozilla/dom/quota/ClientDirectoryLockHandle.h"
#include "mozilla/dom/quota/ClientImpl.h" #include "mozilla/dom/quota/ClientImpl.h"
#include "mozilla/dom/quota/DirectoryLock.h"
#include "mozilla/dom/quota/DirectoryLockInlines.h"
#include "mozilla/dom/quota/FileStreams.h" #include "mozilla/dom/quota/FileStreams.h"
#include "mozilla/dom/quota/PrincipalUtils.h" #include "mozilla/dom/quota/PrincipalUtils.h"
#include "mozilla/dom/quota/QuotaCommon.h" #include "mozilla/dom/quota/QuotaCommon.h"
@@ -117,7 +116,7 @@ class StreamHelper final : public Runnable {
}; };
class Connection final : public PBackgroundSDBConnectionParent { class Connection final : public PBackgroundSDBConnectionParent {
RefPtr<ClientDirectoryLock> mDirectoryLock; ClientDirectoryLockHandle mDirectoryLockHandle;
nsCOMPtr<nsIFileRandomAccessStream> mFileRandomAccessStream; nsCOMPtr<nsIFileRandomAccessStream> mFileRandomAccessStream;
const PrincipalInfo mPrincipalInfo; const PrincipalInfo mPrincipalInfo;
nsCString mOrigin; nsCString mOrigin;
@@ -138,7 +137,7 @@ class Connection final : public PBackgroundSDBConnectionParent {
Maybe<ClientDirectoryLock&> MaybeDirectoryLockRef() const { Maybe<ClientDirectoryLock&> MaybeDirectoryLockRef() const {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
return ToMaybeRef(mDirectoryLock.get()); return ToMaybeRef(mDirectoryLockHandle.get());
} }
nsIFileRandomAccessStream* GetFileRandomAccessStream() const { nsIFileRandomAccessStream* GetFileRandomAccessStream() const {
@@ -175,7 +174,7 @@ class Connection final : public PBackgroundSDBConnectionParent {
void OnOpen( void OnOpen(
const nsACString& aOrigin, const nsAString& aName, const nsACString& aOrigin, const nsAString& aName,
already_AddRefed<ClientDirectoryLock> aDirectoryLock, ClientDirectoryLockHandle aDirectoryLockHandle,
already_AddRefed<nsIFileRandomAccessStream> aFileRandomAccessStream); already_AddRefed<nsIFileRandomAccessStream> aFileRandomAccessStream);
void OnClose(); void OnClose();
@@ -336,7 +335,7 @@ class OpenOp final : public ConnectionOperationBase {
}; };
const SDBRequestOpenParams mParams; const SDBRequestOpenParams mParams;
RefPtr<ClientDirectoryLock> mDirectoryLock; ClientDirectoryLockHandle mDirectoryLockHandle;
nsCOMPtr<nsIFileRandomAccessStream> mFileRandomAccessStream; nsCOMPtr<nsIFileRandomAccessStream> mFileRandomAccessStream;
// XXX Consider changing this to ClientMetadata. // XXX Consider changing this to ClientMetadata.
quota::OriginMetadata mOriginMetadata; quota::OriginMetadata mOriginMetadata;
@@ -374,7 +373,7 @@ class OpenOp final : public ConnectionOperationBase {
NS_IMETHOD NS_IMETHOD
Run() override; Run() override;
void DirectoryLockAcquired(ClientDirectoryLock* aLock); void DirectoryLockAcquired(ClientDirectoryLockHandle aLockHandle);
void DirectoryLockFailed(); void DirectoryLockFailed();
}; };
@@ -689,20 +688,20 @@ void Connection::OnRequestFinished() {
void Connection::OnOpen( void Connection::OnOpen(
const nsACString& aOrigin, const nsAString& aName, const nsACString& aOrigin, const nsAString& aName,
already_AddRefed<ClientDirectoryLock> aDirectoryLock, ClientDirectoryLockHandle aDirectoryLockHandle,
already_AddRefed<nsIFileRandomAccessStream> aFileRandomAccessStream) { already_AddRefed<nsIFileRandomAccessStream> aFileRandomAccessStream) {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(!aOrigin.IsEmpty()); MOZ_ASSERT(!aOrigin.IsEmpty());
MOZ_ASSERT(!aName.IsEmpty()); MOZ_ASSERT(!aName.IsEmpty());
MOZ_ASSERT(mOrigin.IsEmpty()); MOZ_ASSERT(mOrigin.IsEmpty());
MOZ_ASSERT(mName.IsEmpty()); MOZ_ASSERT(mName.IsEmpty());
MOZ_ASSERT(!mDirectoryLock); MOZ_ASSERT(!mDirectoryLockHandle);
MOZ_ASSERT(!mFileRandomAccessStream); MOZ_ASSERT(!mFileRandomAccessStream);
MOZ_ASSERT(!mOpen); MOZ_ASSERT(!mOpen);
mOrigin = aOrigin; mOrigin = aOrigin;
mName = aName; mName = aName;
mDirectoryLock = aDirectoryLock; mDirectoryLockHandle = std::move(aDirectoryLockHandle);
mFileRandomAccessStream = aFileRandomAccessStream; mFileRandomAccessStream = aFileRandomAccessStream;
mOpen = true; mOpen = true;
@@ -712,7 +711,7 @@ void Connection::OnOpen(
gOpenConnections->AppendElement(WrapNotNullUnchecked(this)); gOpenConnections->AppendElement(WrapNotNullUnchecked(this));
if (mDirectoryLock->Invalidated()) { if (mDirectoryLockHandle->Invalidated()) {
AllowToClose(); AllowToClose();
} }
} }
@@ -720,14 +719,16 @@ void Connection::OnOpen(
void Connection::OnClose() { void Connection::OnClose() {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(!mOrigin.IsEmpty()); MOZ_ASSERT(!mOrigin.IsEmpty());
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
MOZ_ASSERT(mFileRandomAccessStream); MOZ_ASSERT(mFileRandomAccessStream);
MOZ_ASSERT(mOpen); MOZ_ASSERT(mOpen);
mOrigin.Truncate(); mOrigin.Truncate();
mName.Truncate(); mName.Truncate();
DropDirectoryLock(mDirectoryLock); {
auto destroyingDirectoryLockHandle = std::move(mDirectoryLockHandle);
}
mFileRandomAccessStream = nullptr; mFileRandomAccessStream = nullptr;
mOpen = false; mOpen = false;
@@ -1052,7 +1053,7 @@ OpenOp::OpenOp(Connection* aConnection, const SDBRequestParams& aParams)
} }
OpenOp::~OpenOp() { OpenOp::~OpenOp() {
MOZ_ASSERT(!mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle.IsInert());
MOZ_ASSERT(!mFileRandomAccessStream); MOZ_ASSERT(!mFileRandomAccessStream);
MOZ_ASSERT(!mFileRandomAccessStreamOpen); MOZ_ASSERT(!mFileRandomAccessStreamOpen);
MOZ_ASSERT_IF(OperationMayProceed(), MOZ_ASSERT_IF(OperationMayProceed(),
@@ -1087,7 +1088,7 @@ nsresult OpenOp::Open() {
nsresult OpenOp::FinishOpen() { nsresult OpenOp::FinishOpen() {
AssertIsOnOwningThread(); AssertIsOnOwningThread();
MOZ_ASSERT(mOriginMetadata.mOrigin.IsEmpty()); MOZ_ASSERT(mOriginMetadata.mOrigin.IsEmpty());
MOZ_ASSERT(!mDirectoryLock); MOZ_ASSERT(!mDirectoryLockHandle);
MOZ_ASSERT(mState == State::FinishOpen); MOZ_ASSERT(mState == State::FinishOpen);
if (NS_WARN_IF(QuotaClient::IsShuttingDownOnBackgroundThread()) || if (NS_WARN_IF(QuotaClient::IsShuttingDownOnBackgroundThread()) ||
@@ -1131,10 +1132,10 @@ nsresult OpenOp::FinishOpen() {
->OpenClientDirectory({mOriginMetadata, mozilla::dom::quota::Client::SDB}) ->OpenClientDirectory({mOriginMetadata, mozilla::dom::quota::Client::SDB})
->Then( ->Then(
GetCurrentSerialEventTarget(), __func__, GetCurrentSerialEventTarget(), __func__,
[self = RefPtr(this)]( [self = RefPtr(this)](QuotaManager::ClientDirectoryLockHandlePromise::
const ClientDirectoryLockPromise::ResolveOrRejectValue& aValue) { ResolveOrRejectValue&& aValue) {
if (aValue.IsResolve()) { if (aValue.IsResolve()) {
self->DirectoryLockAcquired(aValue.ResolveValue()); self->DirectoryLockAcquired(std::move(aValue.ResolveValue()));
} else { } else {
self->DirectoryLockFailed(); self->DirectoryLockFailed();
} }
@@ -1268,11 +1269,13 @@ nsresult OpenOp::DatabaseWork() {
void OpenOp::StreamClosedCallback() { void OpenOp::StreamClosedCallback() {
AssertIsOnOwningThread(); AssertIsOnOwningThread();
MOZ_ASSERT(NS_FAILED(ResultCode())); MOZ_ASSERT(NS_FAILED(ResultCode()));
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
MOZ_ASSERT(mFileRandomAccessStream); MOZ_ASSERT(mFileRandomAccessStream);
MOZ_ASSERT(mFileRandomAccessStreamOpen); MOZ_ASSERT(mFileRandomAccessStreamOpen);
DropDirectoryLock(mDirectoryLock); {
auto destroyingDirectoryLockHandle = std::move(mDirectoryLockHandle);
}
mFileRandomAccessStream = nullptr; mFileRandomAccessStream = nullptr;
mFileRandomAccessStreamOpen = false; mFileRandomAccessStreamOpen = false;
@@ -1298,19 +1301,19 @@ void OpenOp::OnSuccess() {
AssertIsOnOwningThread(); AssertIsOnOwningThread();
MOZ_ASSERT(NS_SUCCEEDED(ResultCode())); MOZ_ASSERT(NS_SUCCEEDED(ResultCode()));
MOZ_ASSERT(!mOriginMetadata.mOrigin.IsEmpty()); MOZ_ASSERT(!mOriginMetadata.mOrigin.IsEmpty());
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
MOZ_ASSERT(mFileRandomAccessStream); MOZ_ASSERT(mFileRandomAccessStream);
MOZ_ASSERT(mFileRandomAccessStreamOpen); MOZ_ASSERT(mFileRandomAccessStreamOpen);
RefPtr<ClientDirectoryLock> directoryLock; ClientDirectoryLockHandle directoryLockHandle;
nsCOMPtr<nsIFileRandomAccessStream> fileRandomAccessStream; nsCOMPtr<nsIFileRandomAccessStream> fileRandomAccessStream;
mDirectoryLock.swap(directoryLock); directoryLockHandle = std::move(mDirectoryLockHandle);
mFileRandomAccessStream.swap(fileRandomAccessStream); mFileRandomAccessStream.swap(fileRandomAccessStream);
mFileRandomAccessStreamOpen = false; mFileRandomAccessStreamOpen = false;
GetConnection()->OnOpen(mOriginMetadata.mOrigin, mParams.name(), GetConnection()->OnOpen(mOriginMetadata.mOrigin, mParams.name(),
directoryLock.forget(), std::move(directoryLockHandle),
fileRandomAccessStream.forget()); fileRandomAccessStream.forget());
} }
@@ -1322,7 +1325,7 @@ void OpenOp::Cleanup() {
// If we have an initialized file stream then the operation must have failed // If we have an initialized file stream then the operation must have failed
// and there must be a directory lock too. // and there must be a directory lock too.
MOZ_ASSERT(NS_FAILED(ResultCode())); MOZ_ASSERT(NS_FAILED(ResultCode()));
MOZ_ASSERT(mDirectoryLock); MOZ_ASSERT(mDirectoryLockHandle);
// We must close the stream on the I/O thread before releasing it on this // We must close the stream on the I/O thread before releasing it on this
// thread. The directory lock can't be released either. // thread. The directory lock can't be released either.
@@ -1334,7 +1337,9 @@ void OpenOp::Cleanup() {
new StreamHelper(mFileRandomAccessStream, callback); new StreamHelper(mFileRandomAccessStream, callback);
helper->AsyncClose(); helper->AsyncClose();
} else { } else {
SafeDropDirectoryLock(mDirectoryLock); {
auto destroyingDirectoryLockHandle = std::move(mDirectoryLockHandle);
}
mFileRandomAccessStream = nullptr; mFileRandomAccessStream = nullptr;
MOZ_ASSERT(!mFileRandomAccessStreamOpen); MOZ_ASSERT(!mFileRandomAccessStreamOpen);
@@ -1386,12 +1391,12 @@ OpenOp::Run() {
return NS_OK; return NS_OK;
} }
void OpenOp::DirectoryLockAcquired(ClientDirectoryLock* aLock) { void OpenOp::DirectoryLockAcquired(ClientDirectoryLockHandle aLockHandle) {
AssertIsOnOwningThread(); AssertIsOnOwningThread();
MOZ_ASSERT(mState == State::DirectoryOpenPending); MOZ_ASSERT(mState == State::DirectoryOpenPending);
MOZ_ASSERT(!mDirectoryLock); MOZ_ASSERT(!mDirectoryLockHandle);
mDirectoryLock = aLock; mDirectoryLockHandle = std::move(aLockHandle);
auto cleanupAndReturn = [self = RefPtr(this)](const nsresult rv) { auto cleanupAndReturn = [self = RefPtr(this)](const nsresult rv) {
self->MaybeSetFailureCode(rv); self->MaybeSetFailureCode(rv);
@@ -1403,7 +1408,7 @@ void OpenOp::DirectoryLockAcquired(ClientDirectoryLock* aLock) {
MOZ_ALWAYS_SUCCEEDS(self->Run()); MOZ_ALWAYS_SUCCEEDS(self->Run());
}; };
if (mDirectoryLock->Invalidated()) { if (mDirectoryLockHandle->Invalidated()) {
return cleanupAndReturn(NS_ERROR_ABORT); return cleanupAndReturn(NS_ERROR_ABORT);
} }
@@ -1413,7 +1418,7 @@ void OpenOp::DirectoryLockAcquired(ClientDirectoryLock* aLock) {
void OpenOp::DirectoryLockFailed() { void OpenOp::DirectoryLockFailed() {
AssertIsOnOwningThread(); AssertIsOnOwningThread();
MOZ_ASSERT(mState == State::DirectoryOpenPending); MOZ_ASSERT(mState == State::DirectoryOpenPending);
MOZ_ASSERT(!mDirectoryLock); MOZ_ASSERT(!mDirectoryLockHandle);
MaybeSetFailureCode(NS_ERROR_FAILURE); MaybeSetFailureCode(NS_ERROR_FAILURE);