/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef DOM_QUOTA_DIRTYTRACKINGAUTOLOCK_H_ #define DOM_QUOTA_DIRTYTRACKINGAUTOLOCK_H_ #include "mozilla/Mutex.h" #include "mozilla/RefPtr.h" #include "mozilla/dom/quota/ForwardDecls.h" #include "nsClassHashtable.h" #include "nsHashKeys.h" #include "nsStringFwd.h" namespace mozilla::dom::quota { struct OriginMetadata; class GroupInfoPair; class OriginInfo; // RAII lock for quota operations that mutate origin metadata. Like // MutexAutoLock, it acquires the quota mutex on construction and releases it // on destruction. In addition, on construction it eagerly writes the dirty // flag to the storage database so that a crash mid-operation leaves the // origin marked as needing a full metadata resync on next startup. class MOZ_RAII MOZ_SCOPED_CAPABILITY MOZ_CAPABILITY("dirty_tracking_autolock") DirtyTrackingAutoLock { public: // RAII helper that temporarily releases the quota mutex held by a // DirtyTrackingAutoLock, allowing file I/O to proceed without holding // the lock. The mutex is re-acquired when the PauseLock is destroyed. // Analogous to MutexAutoUnlock. class MOZ_RAII MOZ_SCOPED_CAPABILITY PauseLock { public: explicit PauseLock(DirtyTrackingAutoLock& aAutoLock) MOZ_CAPABILITY_ACQUIRE(mLock) : mLock(aAutoLock) { mLock.Unlock(); } ~PauseLock() MOZ_CAPABILITY_RELEASE() { mLock.Lock(); } PauseLock() = delete; PauseLock(const PauseLock&) = delete; PauseLock(PauseLock&&) = delete; PauseLock& operator=(const PauseLock&) = delete; PauseLock& operator=(PauseLock&&) = delete; private: static void* operator new(size_t) noexcept(true); DirtyTrackingAutoLock& mLock; }; DirtyTrackingAutoLock(Mutex& aLock, RefPtr aOriginInfo); DirtyTrackingAutoLock( Mutex& aLock, const nsClassHashtable& aGroupInfoPairs, const OriginMetadata& aOriginMetadata); DirtyTrackingAutoLock() = delete; DirtyTrackingAutoLock(const DirtyTrackingAutoLock&) = delete; DirtyTrackingAutoLock& operator=(const DirtyTrackingAutoLock&) = delete; ~DirtyTrackingAutoLock() { Unlock(); } bool IsValid() const { return !!mOriginInfo; } void Touch() { mTouched = true; } RefPtr GetOriginInfo() const { MOZ_DIAGNOSTIC_ASSERT(IsValid()); return mOriginInfo; } private: template void Unlock() MOZ_CAPABILITY_RELEASE() { MOZ_ASSERT(mLock); if (mLock) { mLock->Unlock(); } if constexpr (IsFinal) { mLock = nullptr; } } void Lock() MOZ_CAPABILITY_ACQUIRE() { MOZ_ASSERT(mLock); if (mLock) { mLock->Lock(); } } void EagerMarkAsDirty(); DirtyTrackingAutoLock(DirtyTrackingAutoLock&&) = default; DirtyTrackingAutoLock& operator=(DirtyTrackingAutoLock&&) = default; static void* operator new(size_t) noexcept(true); static RefPtr GetOriginInfo( const nsClassHashtable& aGroupInfoPairs, const OriginMetadata& aOriginMetadata); Mutex* mLock; mutable RefPtr mOriginInfo; bool mTouched; }; } // namespace mozilla::dom::quota #endif // DOM_QUOTA_DIRTYTRACKINGAUTOLOCK_H_