1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_dom_idbtransaction_h__
8 #define mozilla_dom_idbtransaction_h__
10 #include "FlippedOnce.h"
11 #include "mozilla/Attributes.h"
12 #include "mozilla/dom/IDBTransactionBinding.h"
13 #include "mozilla/dom/quota/CheckedUnsafePtr.h"
14 #include "mozilla/DOMEventTargetHelper.h"
15 #include "nsCycleCollectionParticipant.h"
16 #include "nsIRunnable.h"
19 #include "SafeRefPtr.h"
24 class EventChainPreVisitor
;
33 class IDBOpenDBRequest
;
35 class StrongWorkerRef
;
38 class PBackgroundIDBCursorChild
;
39 class BackgroundRequestChild
;
40 class BackgroundTransactionChild
;
41 class BackgroundVersionChangeTransactionChild
;
43 class ObjectStoreSpec
;
44 class OpenCursorParams
;
46 } // namespace indexedDB
48 class IDBTransaction final
49 : public DOMEventTargetHelper
,
51 public SupportsCheckedUnsafePtr
<CheckIf
<DiagnosticAssertEnabled
>> {
52 friend class indexedDB::BackgroundRequestChild
;
62 // Only needed for IPC serialization helper, should never be used in code.
66 enum struct ReadyState
{ Active
, Inactive
, Committing
, Finished
};
69 // TODO: Only non-const because of Bug 1575173.
70 RefPtr
<IDBDatabase
> mDatabase
;
71 RefPtr
<DOMException
> mError
;
72 const nsTArray
<nsString
> mObjectStoreNames
;
73 nsTArray
<RefPtr
<IDBObjectStore
>> mObjectStores
;
74 nsTArray
<RefPtr
<IDBObjectStore
>> mDeletedObjectStores
;
75 RefPtr
<StrongWorkerRef
> mWorkerRef
;
76 nsTArray
<NotNull
<IDBCursor
*>> mCursors
;
78 // Tagged with mMode. If mMode is Mode::VersionChange then mBackgroundActor
79 // will be a BackgroundVersionChangeTransactionChild. Otherwise it will be a
80 // BackgroundTransactionChild.
82 indexedDB::BackgroundTransactionChild
* mNormalBackgroundActor
;
83 indexedDB::BackgroundVersionChangeTransactionChild
*
84 mVersionChangeBackgroundActor
;
87 const int64_t mLoggingSerialNumber
;
89 // Only used for Mode::VersionChange transactions.
90 int64_t mNextObjectStoreId
;
93 nsresult mAbortCode
; ///< The result that caused the transaction to be
94 ///< aborted, or NS_OK if not aborted.
95 ///< NS_ERROR_DOM_INDEXEDDB_ABORT_ERR indicates that the
96 ///< user explicitly requested aborting. Should be
97 ///< renamed to mResult or so, because it is actually
98 ///< used to check if the transaction has been aborted.
99 uint32_t mPendingRequestCount
; ///< Counted via OnNewRequest and
100 ///< OnRequestFinished, so that the
101 ///< transaction can auto-commit when the last
102 ///< pending request finished.
104 const nsString mFilename
;
105 const uint32_t mLineNo
;
106 const uint32_t mColumn
;
108 ReadyState mReadyState
= ReadyState::Active
;
109 FlippedOnce
<false> mStarted
;
112 bool mRegistered
; ///< Whether mDatabase->RegisterTransaction() has been
113 ///< called (which may not be the case if construction was
115 FlippedOnce
<false> mAbortedByScript
;
116 bool mNotedActiveTransaction
;
117 FlippedOnce
<false> mSentCommitOrAbort
;
120 FlippedOnce
<false> mFiredCompleteOrAbort
;
121 FlippedOnce
<false> mWasExplicitlyCommitted
;
125 [[nodiscard
]] static SafeRefPtr
<IDBTransaction
> CreateVersionChange(
126 IDBDatabase
* aDatabase
,
127 indexedDB::BackgroundVersionChangeTransactionChild
* aActor
,
128 NotNull
<IDBOpenDBRequest
*> aOpenRequest
, int64_t aNextObjectStoreId
,
129 int64_t aNextIndexId
);
131 [[nodiscard
]] static SafeRefPtr
<IDBTransaction
> Create(
132 JSContext
* aCx
, IDBDatabase
* aDatabase
,
133 const nsTArray
<nsString
>& aObjectStoreNames
, Mode aMode
);
135 static Maybe
<IDBTransaction
&> MaybeCurrent();
137 void AssertIsOnOwningThread() const
145 void SetBackgroundActor(
146 indexedDB::BackgroundTransactionChild
* aBackgroundActor
);
148 void ClearBackgroundActor() {
149 AssertIsOnOwningThread();
151 if (mMode
== Mode::VersionChange
) {
152 mBackgroundActor
.mVersionChangeBackgroundActor
= nullptr;
154 mBackgroundActor
.mNormalBackgroundActor
= nullptr;
157 // Note inactive transaction here if we didn't receive the Complete message
159 MaybeNoteInactiveTransaction();
162 indexedDB::BackgroundRequestChild
* StartRequest(
163 MovingNotNull
<RefPtr
<mozilla::dom::IDBRequest
>> aRequest
,
164 const indexedDB::RequestParams
& aParams
);
166 void OpenCursor(indexedDB::PBackgroundIDBCursorChild
& aBackgroundActor
,
167 const indexedDB::OpenCursorParams
& aParams
);
169 void RefreshSpec(bool aMayDelete
);
171 bool IsCommittingOrFinished() const {
172 AssertIsOnOwningThread();
174 return mReadyState
== ReadyState::Committing
||
175 mReadyState
== ReadyState::Finished
;
178 bool IsActive() const {
179 AssertIsOnOwningThread();
181 return mReadyState
== ReadyState::Active
;
184 bool IsInactive() const {
185 AssertIsOnOwningThread();
187 return mReadyState
== ReadyState::Inactive
;
190 bool IsFinished() const {
191 AssertIsOnOwningThread();
193 return mReadyState
== ReadyState::Finished
;
196 bool IsWriteAllowed() const {
197 AssertIsOnOwningThread();
198 return mMode
== Mode::ReadWrite
|| mMode
== Mode::ReadWriteFlush
||
199 mMode
== Mode::Cleanup
|| mMode
== Mode::VersionChange
;
202 bool IsAborted() const {
203 AssertIsOnOwningThread();
204 return NS_FAILED(mAbortCode
);
208 bool WasExplicitlyCommitted() const { return mWasExplicitlyCommitted
; }
211 void TransitionToActive() {
212 MOZ_ASSERT(mReadyState
== ReadyState::Inactive
);
213 mReadyState
= ReadyState::Active
;
216 void TransitionToInactive() {
217 MOZ_ASSERT(mReadyState
== ReadyState::Active
);
218 mReadyState
= ReadyState::Inactive
;
221 nsresult
AbortCode() const {
222 AssertIsOnOwningThread();
226 void GetCallerLocation(nsAString
& aFilename
, uint32_t* aLineNo
,
227 uint32_t* aColumn
) const;
229 // 'Get' prefix is to avoid name collisions with the enum
230 Mode
GetMode() const {
231 AssertIsOnOwningThread();
235 uint32_t GetPendingRequestCount() const { return mPendingRequestCount
; }
237 IDBDatabase
* Database() const {
238 AssertIsOnOwningThread();
242 // Only for use by ProfilerHelpers.h
243 const nsTArray
<nsString
>& ObjectStoreNamesInternal() const {
244 AssertIsOnOwningThread();
245 return mObjectStoreNames
;
248 [[nodiscard
]] RefPtr
<IDBObjectStore
> CreateObjectStore(
249 indexedDB::ObjectStoreSpec
& aSpec
);
251 void DeleteObjectStore(int64_t aObjectStoreId
);
253 void RenameObjectStore(int64_t aObjectStoreId
, const nsAString
& aName
) const;
255 void CreateIndex(IDBObjectStore
* aObjectStore
,
256 const indexedDB::IndexMetadata
& aMetadata
) const;
258 void DeleteIndex(IDBObjectStore
* aObjectStore
, int64_t aIndexId
) const;
260 void RenameIndex(IDBObjectStore
* aObjectStore
, int64_t aIndexId
,
261 const nsAString
& aName
) const;
263 void Abort(IDBRequest
* aRequest
);
265 void Abort(nsresult aErrorCode
);
267 int64_t LoggingSerialNumber() const {
268 AssertIsOnOwningThread();
270 return mLoggingSerialNumber
;
273 nsIGlobalObject
* GetParentObject() const;
275 void FireCompleteOrAbortEvents(nsresult aResult
);
277 // Only for Mode::VersionChange transactions.
278 int64_t NextObjectStoreId();
280 // Only for Mode::VersionChange transactions.
281 int64_t NextIndexId();
283 void InvalidateCursorCaches();
284 void RegisterCursor(IDBCursor
& aCursor
);
285 void UnregisterCursor(IDBCursor
& aCursor
);
287 NS_DECL_ISUPPORTS_INHERITED
289 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBTransaction
, DOMEventTargetHelper
)
291 void CommitIfNotStarted();
294 JSObject
* WrapObject(JSContext
* aCx
,
295 JS::Handle
<JSObject
*> aGivenProto
) override
;
297 // Methods bound via WebIDL.
298 IDBDatabase
* Db() const { return Database(); }
300 IDBTransactionMode
GetMode(ErrorResult
& aRv
) const;
302 DOMException
* GetError() const;
304 [[nodiscard
]] RefPtr
<IDBObjectStore
> ObjectStore(const nsAString
& aName
,
307 void Commit(ErrorResult
& aRv
);
309 void Abort(ErrorResult
& aRv
);
311 IMPL_EVENT_HANDLER(abort
)
312 IMPL_EVENT_HANDLER(complete
)
313 IMPL_EVENT_HANDLER(error
)
315 [[nodiscard
]] RefPtr
<DOMStringList
> ObjectStoreNames() const;
318 void GetEventTargetParent(EventChainPreVisitor
& aVisitor
) override
;
321 struct CreatedFromFactoryFunction
{};
324 IDBTransaction(IDBDatabase
* aDatabase
,
325 const nsTArray
<nsString
>& aObjectStoreNames
, Mode aMode
,
326 nsString aFilename
, uint32_t aLineNo
, uint32_t aColumn
,
327 CreatedFromFactoryFunction aDummy
);
332 void AbortInternal(nsresult aAbortCode
, RefPtr
<DOMException
> aError
);
334 void SendCommit(bool aAutoCommit
);
336 void SendAbort(nsresult aResultCode
);
338 void NoteActiveTransaction();
340 void MaybeNoteInactiveTransaction();
342 // TODO consider making private again, or move to the right place
346 void OnRequestFinished(bool aRequestCompletedSuccessfully
);
349 template <typename Func
>
350 auto DoWithTransactionChild(const Func
& aFunc
) const;
352 bool HasTransactionChild() const;
355 inline bool ReferenceEquals(const Maybe
<IDBTransaction
&>& aLHS
,
356 const Maybe
<IDBTransaction
&>& aRHS
) {
357 if (aLHS
.isNothing() != aRHS
.isNothing()) {
360 return aLHS
.isNothing() || &aLHS
.ref() == &aRHS
.ref();
364 } // namespace mozilla
366 #endif // mozilla_dom_idbtransaction_h__