/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* 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_idbtransaction_h__ #define mozilla_dom_idbtransaction_h__ #include "mozilla/Attributes.h" #include "mozilla/dom/IDBTransactionBinding.h" #include "mozilla/dom/IDBWrapperCache.h" #include "nsAutoPtr.h" #include "nsCycleCollectionParticipant.h" #include "nsIRunnable.h" #include "nsString.h" #include "nsTArray.h" class nsPIDOMWindowInner; namespace mozilla { class ErrorResult; class EventChainPreVisitor; namespace dom { class DOMError; class DOMStringList; class IDBDatabase; class IDBObjectStore; class IDBOpenDBRequest; class IDBRequest; namespace indexedDB { class BackgroundCursorChild; class BackgroundRequestChild; class BackgroundTransactionChild; class BackgroundVersionChangeTransactionChild; class IndexMetadata; class ObjectStoreSpec; class OpenCursorParams; class RequestParams; } class IDBTransaction final : public IDBWrapperCache , public nsIRunnable { friend class indexedDB::BackgroundCursorChild; friend class indexedDB::BackgroundRequestChild; class WorkerHolder; friend class WorkerHolder; public: enum struct Mode { ReadOnly = 0, ReadWrite, ReadWriteFlush, Cleanup, VersionChange, // Only needed for IPC serialization helper, should never be used in code. Invalid }; enum struct ReadyState { Initial = 0, Loading, Inactive, Committing, Done }; private: RefPtr mDatabase; RefPtr mError; nsTArray mObjectStoreNames; nsTArray> mObjectStores; nsTArray> mDeletedObjectStores; nsAutoPtr mWorkerHolder; // Tagged with mMode. If mMode is Mode::VersionChange then mBackgroundActor will be // a BackgroundVersionChangeTransactionChild. Otherwise it will be a // BackgroundTransactionChild. union { indexedDB::BackgroundTransactionChild* mNormalBackgroundActor; indexedDB::BackgroundVersionChangeTransactionChild* mVersionChangeBackgroundActor; } mBackgroundActor; const int64_t mLoggingSerialNumber; // Only used for Mode::VersionChange transactions. int64_t mNextObjectStoreId; int64_t mNextIndexId; nsresult mAbortCode; uint32_t mPendingRequestCount; nsString mFilename; uint32_t mLineNo; uint32_t mColumn; ReadyState mReadyState; Mode mMode; bool mCreating; bool mRegistered; bool mAbortedByScript; #ifdef DEBUG bool mSentCommitOrAbort; bool mFiredCompleteOrAbort; #endif public: static already_AddRefed CreateVersionChange(IDBDatabase* aDatabase, indexedDB::BackgroundVersionChangeTransactionChild* aActor, IDBOpenDBRequest* aOpenRequest, int64_t aNextObjectStoreId, int64_t aNextIndexId); static already_AddRefed Create(JSContext* aCx, IDBDatabase* aDatabase, const nsTArray& aObjectStoreNames, Mode aMode); static IDBTransaction* GetCurrent(); void AssertIsOnOwningThread() const #ifdef DEBUG ; #else { } #endif void SetBackgroundActor(indexedDB::BackgroundTransactionChild* aBackgroundActor); void ClearBackgroundActor() { AssertIsOnOwningThread(); if (mMode == Mode::VersionChange) { mBackgroundActor.mVersionChangeBackgroundActor = nullptr; } else { mBackgroundActor.mNormalBackgroundActor = nullptr; } } indexedDB::BackgroundRequestChild* StartRequest(IDBRequest* aRequest, const indexedDB::RequestParams& aParams); void OpenCursor(indexedDB::BackgroundCursorChild* aBackgroundActor, const indexedDB::OpenCursorParams& aParams); void RefreshSpec(bool aMayDelete); bool IsOpen() const; bool IsCommittingOrDone() const { AssertIsOnOwningThread(); return mReadyState == ReadyState::Committing || mReadyState == ReadyState::Done; } bool IsDone() const { AssertIsOnOwningThread(); return mReadyState == ReadyState::Done; } bool IsWriteAllowed() const { AssertIsOnOwningThread(); return mMode == Mode::ReadWrite || mMode == Mode::ReadWriteFlush || mMode == Mode::Cleanup || mMode == Mode::VersionChange; } bool IsAborted() const { AssertIsOnOwningThread(); return NS_FAILED(mAbortCode); } nsresult AbortCode() const { AssertIsOnOwningThread(); return mAbortCode; } void GetCallerLocation(nsAString& aFilename, uint32_t* aLineNo, uint32_t* aColumn) const; // 'Get' prefix is to avoid name collisions with the enum Mode GetMode() const { AssertIsOnOwningThread(); return mMode; } IDBDatabase* Database() const { AssertIsOnOwningThread(); return mDatabase; } IDBDatabase* Db() const { return Database(); } const nsTArray& ObjectStoreNamesInternal() const { AssertIsOnOwningThread(); return mObjectStoreNames; } already_AddRefed CreateObjectStore(const indexedDB::ObjectStoreSpec& aSpec); void DeleteObjectStore(int64_t aObjectStoreId); void RenameObjectStore(int64_t aObjectStoreId, const nsAString& aName); void CreateIndex(IDBObjectStore* aObjectStore, const indexedDB::IndexMetadata& aMetadata); void DeleteIndex(IDBObjectStore* aObjectStore, int64_t aIndexId); void RenameIndex(IDBObjectStore* aObjectStore, int64_t aIndexId, const nsAString& aName); void Abort(IDBRequest* aRequest); void Abort(nsresult aAbortCode); int64_t LoggingSerialNumber() const { AssertIsOnOwningThread(); return mLoggingSerialNumber; } nsPIDOMWindowInner* GetParentObject() const; IDBTransactionMode GetMode(ErrorResult& aRv) const; DOMError* GetError() const; already_AddRefed ObjectStore(const nsAString& aName, ErrorResult& aRv); void Abort(ErrorResult& aRv); IMPL_EVENT_HANDLER(abort) IMPL_EVENT_HANDLER(complete) IMPL_EVENT_HANDLER(error) already_AddRefed ObjectStoreNames() const; void FireCompleteOrAbortEvents(nsresult aResult); // Only for Mode::VersionChange transactions. int64_t NextObjectStoreId(); // Only for Mode::VersionChange transactions. int64_t NextIndexId(); NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIRUNNABLE NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBTransaction, IDBWrapperCache) // nsWrapperCache virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; // nsIDOMEventTarget virtual nsresult GetEventTargetParent(EventChainPreVisitor& aVisitor) override; private: IDBTransaction(IDBDatabase* aDatabase, const nsTArray& aObjectStoreNames, Mode aMode); ~IDBTransaction(); void AbortInternal(nsresult aAbortCode, already_AddRefed aError); void SendCommit(); void SendAbort(nsresult aResultCode); void OnNewRequest(); void OnRequestFinished(bool aActorDestroyedNormally); }; } // namespace dom } // namespace mozilla #endif // mozilla_dom_idbtransaction_h__