/* -*- 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 mozilla_dom_idbdatabase_h__ #define mozilla_dom_idbdatabase_h__ #include "mozilla/Attributes.h" #include "mozilla/dom/IDBTransactionBinding.h" #include "mozilla/dom/indexedDB/PBackgroundIDBSharedTypes.h" #include "mozilla/dom/quota/PersistenceType.h" #include "mozilla/DOMEventTargetHelper.h" #include "mozilla/UniquePtr.h" #include "nsTHashMap.h" #include "nsHashKeys.h" #include "nsString.h" #include "nsTHashSet.h" class nsIEventTarget; class nsIGlobalObject; namespace mozilla { class ErrorResult; class EventChainPostVisitor; namespace dom { class Blob; class DOMStringList; class IDBFactory; class IDBObjectStore; struct IDBObjectStoreParameters; class IDBOpenDBRequest; class IDBRequest; class IDBTransaction; template class Optional; class StringOrStringSequence; namespace indexedDB { class BackgroundDatabaseChild; class PBackgroundIDBDatabaseFileChild; } // namespace indexedDB class IDBDatabase final : public DOMEventTargetHelper { using DatabaseSpec = mozilla::dom::indexedDB::DatabaseSpec; using PersistenceType = mozilla::dom::quota::PersistenceType; class Observer; friend class Observer; friend class IDBObjectStore; friend class IDBIndex; // The factory must be kept alive when IndexedDB is used in multiple // processes. If it dies then the entire actor tree will be destroyed with it // and the world will explode. SafeRefPtr mFactory; UniquePtr mSpec; // Normally null except during a versionchange transaction. UniquePtr mPreviousSpec; indexedDB::BackgroundDatabaseChild* mBackgroundActor; nsTHashSet mTransactions; nsTHashMap mFileActors; RefPtr mObserver; bool mClosed; bool mInvalidated; bool mQuotaExceeded; bool mIncreasedActiveDatabaseCount; public: [[nodiscard]] static RefPtr Create( IDBOpenDBRequest* aRequest, SafeRefPtr aFactory, indexedDB::BackgroundDatabaseChild* aActor, UniquePtr aSpec); void AssertIsOnOwningThread() const #ifdef DEBUG ; #else { } #endif nsIEventTarget* EventTarget() const; const nsString& Name() const; void GetName(nsAString& aName) const { AssertIsOnOwningThread(); aName = Name(); } uint64_t Version() const; [[nodiscard]] RefPtr GetOwnerDocument() const; void Close() { AssertIsOnOwningThread(); CloseInternal(); } bool IsClosed() const { AssertIsOnOwningThread(); return mClosed; } void Invalidate(); // Whether or not the database has been invalidated. If it has then no further // transactions for this database will be allowed to run. bool IsInvalidated() const { AssertIsOnOwningThread(); return mInvalidated; } void SetQuotaExceeded() { mQuotaExceeded = true; } void EnterSetVersionTransaction(uint64_t aNewVersion); void ExitSetVersionTransaction(); // Called when a versionchange transaction is aborted to reset the // DatabaseInfo. void RevertToPreviousState(); void RegisterTransaction(IDBTransaction& aTransaction); void UnregisterTransaction(IDBTransaction& aTransaction); void AbortTransactions(bool aShouldWarn); indexedDB::PBackgroundIDBDatabaseFileChild* GetOrCreateFileActorForBlob( Blob& aBlob); void NoteFinishedFileActor( indexedDB::PBackgroundIDBDatabaseFileChild* aFileActor); void NoteActiveTransaction(); void NoteInactiveTransaction(); [[nodiscard]] RefPtr ObjectStoreNames() const; [[nodiscard]] RefPtr CreateObjectStore( const nsAString& aName, const IDBObjectStoreParameters& aOptionalParameters, ErrorResult& aRv); void DeleteObjectStore(const nsAString& name, ErrorResult& aRv); // This will be called from the DOM. [[nodiscard]] RefPtr Transaction( JSContext* aCx, const StringOrStringSequence& aStoreNames, IDBTransactionMode aMode, ErrorResult& aRv); IMPL_EVENT_HANDLER(abort) IMPL_EVENT_HANDLER(close) IMPL_EVENT_HANDLER(error) IMPL_EVENT_HANDLER(versionchange) void ClearBackgroundActor() { AssertIsOnOwningThread(); // Decrease the number of active databases if it was not done in // CloseInternal(). MaybeDecreaseActiveDatabaseCount(); mBackgroundActor = nullptr; } const DatabaseSpec* Spec() const { return mSpec.get(); } template indexedDB::ObjectStoreSpec* LookupModifiableObjectStoreSpec(Pred&& aPred) { auto& objectStores = mSpec->objectStores(); const auto foundIt = std::find_if(objectStores.begin(), objectStores.end(), aPred); return foundIt != objectStores.end() ? &*foundIt : nullptr; } NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBDatabase, DOMEventTargetHelper) // DOMEventTargetHelper void DisconnectFromOwner() override; virtual void LastRelease() override; // nsWrapperCache virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; private: IDBDatabase(IDBOpenDBRequest* aRequest, SafeRefPtr aFactory, indexedDB::BackgroundDatabaseChild* aActor, UniquePtr aSpec); ~IDBDatabase(); void CloseInternal(); void InvalidateInternal(); bool RunningVersionChangeTransaction() const { AssertIsOnOwningThread(); return !!mPreviousSpec; } void RefreshSpec(bool aMayDelete); void ExpireFileActors(bool aExpireAll); void NoteInactiveTransactionDelayed(); void LogWarning(const char* aMessageName, const nsAString& aFilename, uint32_t aLineNumber, uint32_t aColumnNumber); // Only accessed by IDBObjectStore. nsresult RenameObjectStore(int64_t aObjectStoreId, const nsAString& aName); // Only accessed by IDBIndex. nsresult RenameIndex(int64_t aObjectStoreId, int64_t aIndexId, const nsAString& aName); void IncreaseActiveDatabaseCount(); void MaybeDecreaseActiveDatabaseCount(); }; } // namespace dom } // namespace mozilla #endif // mozilla_dom_idbdatabase_h__