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 Durability
{
71 // Only needed for IPC serialization helper, should never be used in code.
75 enum struct ReadyState
{ Active
, Inactive
, Committing
, Finished
};
78 // TODO: Only non-const because of Bug 1575173.
79 RefPtr
<IDBDatabase
> mDatabase
;
80 RefPtr
<DOMException
> mError
;
81 const nsTArray
<nsString
> mObjectStoreNames
;
82 nsTArray
<RefPtr
<IDBObjectStore
>> mObjectStores
;
83 nsTArray
<RefPtr
<IDBObjectStore
>> mDeletedObjectStores
;
84 RefPtr
<StrongWorkerRef
> mWorkerRef
;
85 nsTArray
<NotNull
<IDBCursor
*>> mCursors
;
87 // Tagged with mMode. If mMode is Mode::VersionChange then mBackgroundActor
88 // will be a BackgroundVersionChangeTransactionChild. Otherwise it will be a
89 // BackgroundTransactionChild.
91 indexedDB::BackgroundTransactionChild
* mNormalBackgroundActor
;
92 indexedDB::BackgroundVersionChangeTransactionChild
*
93 mVersionChangeBackgroundActor
;
96 const int64_t mLoggingSerialNumber
;
98 // Only used for Mode::VersionChange transactions.
99 int64_t mNextObjectStoreId
;
100 int64_t mNextIndexId
;
102 // Request ids are issued starting from 0 and incremented by one as we send
103 // actor creation messages to the parent process. Used to support the
104 // explicit commit() request.
105 int64_t mNextRequestId
;
107 nsresult mAbortCode
; ///< The result that caused the transaction to be
108 ///< aborted, or NS_OK if not aborted.
109 ///< NS_ERROR_DOM_INDEXEDDB_ABORT_ERR indicates that the
110 ///< user explicitly requested aborting. Should be
111 ///< renamed to mResult or so, because it is actually
112 ///< used to check if the transaction has been aborted.
113 uint32_t mPendingRequestCount
; ///< Counted via OnNewRequest and
114 ///< OnRequestFinished, so that the
115 ///< transaction can auto-commit when the last
116 ///< pending request finished.
118 const nsString mFilename
;
119 const uint32_t mLineNo
;
120 const uint32_t mColumn
;
122 ReadyState mReadyState
= ReadyState::Active
;
123 FlippedOnce
<false> mStarted
;
125 const Durability mDurability
;
127 bool mRegistered
; ///< Whether mDatabase->RegisterTransaction() has been
128 ///< called (which may not be the case if construction was
130 FlippedOnce
<false> mAbortedByScript
;
131 bool mNotedActiveTransaction
;
132 FlippedOnce
<false> mSentCommitOrAbort
;
135 FlippedOnce
<false> mFiredCompleteOrAbort
;
136 FlippedOnce
<false> mWasExplicitlyCommitted
;
140 [[nodiscard
]] static SafeRefPtr
<IDBTransaction
> CreateVersionChange(
141 IDBDatabase
* aDatabase
,
142 indexedDB::BackgroundVersionChangeTransactionChild
* aActor
,
143 NotNull
<IDBOpenDBRequest
*> aOpenRequest
, int64_t aNextObjectStoreId
,
144 int64_t aNextIndexId
);
146 [[nodiscard
]] static SafeRefPtr
<IDBTransaction
> Create(
147 JSContext
* aCx
, IDBDatabase
* aDatabase
,
148 const nsTArray
<nsString
>& aObjectStoreNames
, Mode aMode
,
149 Durability aDurability
);
151 static Maybe
<IDBTransaction
&> MaybeCurrent();
153 void AssertIsOnOwningThread() const
161 void SetBackgroundActor(
162 indexedDB::BackgroundTransactionChild
* aBackgroundActor
);
164 void ClearBackgroundActor() {
165 AssertIsOnOwningThread();
167 if (mMode
== Mode::VersionChange
) {
168 mBackgroundActor
.mVersionChangeBackgroundActor
= nullptr;
170 mBackgroundActor
.mNormalBackgroundActor
= nullptr;
173 // Note inactive transaction here if we didn't receive the Complete message
175 MaybeNoteInactiveTransaction();
178 indexedDB::BackgroundRequestChild
* StartRequest(
179 MovingNotNull
<RefPtr
<mozilla::dom::IDBRequest
>> aRequest
,
180 const indexedDB::RequestParams
& aParams
);
182 void OpenCursor(indexedDB::PBackgroundIDBCursorChild
& aBackgroundActor
,
183 const indexedDB::OpenCursorParams
& aParams
);
185 void RefreshSpec(bool aMayDelete
);
187 bool IsCommittingOrFinished() const {
188 AssertIsOnOwningThread();
190 return mReadyState
== ReadyState::Committing
||
191 mReadyState
== ReadyState::Finished
;
194 bool IsActive() const {
195 AssertIsOnOwningThread();
197 return mReadyState
== ReadyState::Active
;
200 bool IsInactive() const {
201 AssertIsOnOwningThread();
203 return mReadyState
== ReadyState::Inactive
;
206 bool IsFinished() const {
207 AssertIsOnOwningThread();
209 return mReadyState
== ReadyState::Finished
;
212 bool IsWriteAllowed() const {
213 AssertIsOnOwningThread();
214 return mMode
== Mode::ReadWrite
|| mMode
== Mode::ReadWriteFlush
||
215 mMode
== Mode::Cleanup
|| mMode
== Mode::VersionChange
;
218 bool IsAborted() const {
219 AssertIsOnOwningThread();
220 return NS_FAILED(mAbortCode
);
224 bool WasExplicitlyCommitted() const { return mWasExplicitlyCommitted
; }
227 void TransitionToActive() {
228 MOZ_ASSERT(mReadyState
== ReadyState::Inactive
);
229 mReadyState
= ReadyState::Active
;
232 void TransitionToInactive() {
233 MOZ_ASSERT(mReadyState
== ReadyState::Active
);
234 mReadyState
= ReadyState::Inactive
;
237 nsresult
AbortCode() const {
238 AssertIsOnOwningThread();
242 void GetCallerLocation(nsAString
& aFilename
, uint32_t* aLineNo
,
243 uint32_t* aColumn
) const;
245 // 'Get' prefix is to avoid name collisions with the enum
246 Mode
GetMode() const {
247 AssertIsOnOwningThread();
251 Durability
GetDurability() const {
252 AssertIsOnOwningThread();
256 uint32_t GetPendingRequestCount() const { return mPendingRequestCount
; }
258 IDBDatabase
* Database() const {
259 AssertIsOnOwningThread();
263 // Only for use by ProfilerHelpers.h
264 const nsTArray
<nsString
>& ObjectStoreNamesInternal() const {
265 AssertIsOnOwningThread();
266 return mObjectStoreNames
;
269 [[nodiscard
]] RefPtr
<IDBObjectStore
> CreateObjectStore(
270 indexedDB::ObjectStoreSpec
& aSpec
);
272 void DeleteObjectStore(int64_t aObjectStoreId
);
274 void RenameObjectStore(int64_t aObjectStoreId
, const nsAString
& aName
) const;
276 void CreateIndex(IDBObjectStore
* aObjectStore
,
277 const indexedDB::IndexMetadata
& aMetadata
) const;
279 void DeleteIndex(IDBObjectStore
* aObjectStore
, int64_t aIndexId
) const;
281 void RenameIndex(IDBObjectStore
* aObjectStore
, int64_t aIndexId
,
282 const nsAString
& aName
) const;
284 void Abort(IDBRequest
* aRequest
);
286 void Abort(nsresult aErrorCode
);
288 int64_t LoggingSerialNumber() const {
289 AssertIsOnOwningThread();
291 return mLoggingSerialNumber
;
294 nsIGlobalObject
* GetParentObject() const;
296 void FireCompleteOrAbortEvents(nsresult aResult
);
298 // Only for Mode::VersionChange transactions.
299 int64_t NextObjectStoreId();
301 // Only for Mode::VersionChange transactions.
302 int64_t NextIndexId();
304 // See the comment for mNextRequestId.
305 int64_t NextRequestId();
307 void InvalidateCursorCaches();
308 void RegisterCursor(IDBCursor
& aCursor
);
309 void UnregisterCursor(IDBCursor
& aCursor
);
311 NS_DECL_ISUPPORTS_INHERITED
313 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBTransaction
, DOMEventTargetHelper
)
315 void CommitIfNotStarted();
318 JSObject
* WrapObject(JSContext
* aCx
,
319 JS::Handle
<JSObject
*> aGivenProto
) override
;
321 // Methods bound via WebIDL.
322 IDBDatabase
* Db() const { return Database(); }
324 IDBTransactionMode
GetMode(ErrorResult
& aRv
) const;
326 IDBTransactionDurability
GetDurability(ErrorResult
& aRv
) const;
328 DOMException
* GetError() const;
330 [[nodiscard
]] RefPtr
<IDBObjectStore
> ObjectStore(const nsAString
& aName
,
333 void Commit(ErrorResult
& aRv
);
335 void Abort(ErrorResult
& aRv
);
337 IMPL_EVENT_HANDLER(abort
)
338 IMPL_EVENT_HANDLER(complete
)
339 IMPL_EVENT_HANDLER(error
)
341 [[nodiscard
]] RefPtr
<DOMStringList
> ObjectStoreNames() const;
344 void GetEventTargetParent(EventChainPreVisitor
& aVisitor
) override
;
347 struct CreatedFromFactoryFunction
{};
350 IDBTransaction(IDBDatabase
* aDatabase
,
351 const nsTArray
<nsString
>& aObjectStoreNames
, Mode aMode
,
352 Durability aDurability
, nsString aFilename
, uint32_t aLineNo
,
353 uint32_t aColumn
, CreatedFromFactoryFunction aDummy
);
358 void AbortInternal(nsresult aAbortCode
, RefPtr
<DOMException
> aError
);
360 void SendCommit(bool aAutoCommit
);
362 void SendAbort(nsresult aResultCode
);
364 void NoteActiveTransaction();
366 void MaybeNoteInactiveTransaction();
368 // TODO consider making private again, or move to the right place
372 void OnRequestFinished(bool aRequestCompletedSuccessfully
);
375 template <typename Func
>
376 auto DoWithTransactionChild(const Func
& aFunc
) const;
378 bool HasTransactionChild() const;
381 inline bool ReferenceEquals(const Maybe
<IDBTransaction
&>& aLHS
,
382 const Maybe
<IDBTransaction
&>& aRHS
) {
383 if (aLHS
.isNothing() != aRHS
.isNothing()) {
386 return aLHS
.isNothing() || &aLHS
.ref() == &aRHS
.ref();
390 } // namespace mozilla
392 #endif // mozilla_dom_idbtransaction_h__