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/SourceLocation.h"
13 #include "mozilla/dom/IDBTransactionBinding.h"
14 #include "mozilla/dom/quota/CheckedUnsafePtr.h"
15 #include "mozilla/DOMEventTargetHelper.h"
16 #include "nsCycleCollectionParticipant.h"
17 #include "nsIRunnable.h"
20 #include "SafeRefPtr.h"
25 class EventChainPreVisitor
;
34 class IDBOpenDBRequest
;
36 class StrongWorkerRef
;
39 class PBackgroundIDBCursorChild
;
40 class BackgroundRequestChild
;
41 class BackgroundTransactionChild
;
42 class BackgroundVersionChangeTransactionChild
;
44 class ObjectStoreSpec
;
45 class OpenCursorParams
;
47 } // namespace indexedDB
49 class IDBTransaction final
50 : public DOMEventTargetHelper
,
52 public SupportsCheckedUnsafePtr
<CheckIf
<DiagnosticAssertEnabled
>> {
53 friend class indexedDB::BackgroundRequestChild
;
63 // Only needed for IPC serialization helper, should never be used in code.
67 enum struct Durability
{
72 // Only needed for IPC serialization helper, should never be used in code.
76 enum struct ReadyState
{ Active
, Inactive
, Committing
, Finished
};
79 // TODO: Only non-const because of Bug 1575173.
80 RefPtr
<IDBDatabase
> mDatabase
;
81 RefPtr
<DOMException
> mError
;
82 const nsTArray
<nsString
> mObjectStoreNames
;
83 nsTArray
<RefPtr
<IDBObjectStore
>> mObjectStores
;
84 nsTArray
<RefPtr
<IDBObjectStore
>> mDeletedObjectStores
;
85 RefPtr
<StrongWorkerRef
> mWorkerRef
;
86 nsTArray
<NotNull
<IDBCursor
*>> mCursors
;
88 // Tagged with mMode. If mMode is Mode::VersionChange then mBackgroundActor
89 // will be a BackgroundVersionChangeTransactionChild. Otherwise it will be a
90 // BackgroundTransactionChild.
92 indexedDB::BackgroundTransactionChild
* mNormalBackgroundActor
;
93 indexedDB::BackgroundVersionChangeTransactionChild
*
94 mVersionChangeBackgroundActor
;
97 const int64_t mLoggingSerialNumber
;
99 // Only used for Mode::VersionChange transactions.
100 int64_t mNextObjectStoreId
;
101 int64_t mNextIndexId
;
103 // Request ids are issued starting from 0 and incremented by one as we send
104 // actor creation messages to the parent process. Used to support the
105 // explicit commit() request.
106 int64_t mNextRequestId
;
108 nsresult mAbortCode
; ///< The result that caused the transaction to be
109 ///< aborted, or NS_OK if not aborted.
110 ///< NS_ERROR_DOM_INDEXEDDB_ABORT_ERR indicates that the
111 ///< user explicitly requested aborting. Should be
112 ///< renamed to mResult or so, because it is actually
113 ///< used to check if the transaction has been aborted.
114 uint32_t mPendingRequestCount
; ///< Counted via OnNewRequest and
115 ///< OnRequestFinished, so that the
116 ///< transaction can auto-commit when the last
117 ///< pending request finished.
119 const JSCallingLocation mCallerLocation
;
121 ReadyState mReadyState
= ReadyState::Active
;
122 FlippedOnce
<false> mStarted
;
124 const Durability mDurability
;
126 bool mRegistered
; ///< Whether mDatabase->RegisterTransaction() has been
127 ///< called (which may not be the case if construction was
129 FlippedOnce
<false> mAbortedByScript
;
130 bool mNotedActiveTransaction
;
131 FlippedOnce
<false> mSentCommitOrAbort
;
134 FlippedOnce
<false> mFiredCompleteOrAbort
;
135 FlippedOnce
<false> mWasExplicitlyCommitted
;
139 [[nodiscard
]] static SafeRefPtr
<IDBTransaction
> CreateVersionChange(
140 IDBDatabase
* aDatabase
,
141 indexedDB::BackgroundVersionChangeTransactionChild
* aActor
,
142 NotNull
<IDBOpenDBRequest
*> aOpenRequest
, int64_t aNextObjectStoreId
,
143 int64_t aNextIndexId
);
145 [[nodiscard
]] static SafeRefPtr
<IDBTransaction
> Create(
146 JSContext
* aCx
, IDBDatabase
* aDatabase
,
147 const nsTArray
<nsString
>& aObjectStoreNames
, Mode aMode
,
148 Durability aDurability
);
150 static Maybe
<IDBTransaction
&> MaybeCurrent();
152 void AssertIsOnOwningThread() const
160 void SetBackgroundActor(
161 indexedDB::BackgroundTransactionChild
* aBackgroundActor
);
163 void ClearBackgroundActor() {
164 AssertIsOnOwningThread();
166 if (mMode
== Mode::VersionChange
) {
167 mBackgroundActor
.mVersionChangeBackgroundActor
= nullptr;
169 mBackgroundActor
.mNormalBackgroundActor
= nullptr;
172 // Note inactive transaction here if we didn't receive the Complete message
174 MaybeNoteInactiveTransaction();
177 indexedDB::BackgroundRequestChild
* StartRequest(
178 MovingNotNull
<RefPtr
<mozilla::dom::IDBRequest
>> aRequest
,
179 const indexedDB::RequestParams
& aParams
);
181 void OpenCursor(indexedDB::PBackgroundIDBCursorChild
& aBackgroundActor
,
182 const indexedDB::OpenCursorParams
& aParams
);
184 void RefreshSpec(bool aMayDelete
);
186 bool IsCommittingOrFinished() const {
187 AssertIsOnOwningThread();
189 return mReadyState
== ReadyState::Committing
||
190 mReadyState
== ReadyState::Finished
;
193 bool IsActive() const {
194 AssertIsOnOwningThread();
196 return mReadyState
== ReadyState::Active
;
199 bool IsInactive() const {
200 AssertIsOnOwningThread();
202 return mReadyState
== ReadyState::Inactive
;
205 bool IsFinished() const {
206 AssertIsOnOwningThread();
208 return mReadyState
== ReadyState::Finished
;
211 bool IsWriteAllowed() const {
212 AssertIsOnOwningThread();
213 return mMode
== Mode::ReadWrite
|| mMode
== Mode::ReadWriteFlush
||
214 mMode
== Mode::Cleanup
|| mMode
== Mode::VersionChange
;
217 bool IsAborted() const {
218 AssertIsOnOwningThread();
219 return NS_FAILED(mAbortCode
);
223 bool WasExplicitlyCommitted() const { return mWasExplicitlyCommitted
; }
226 void TransitionToActive() {
227 MOZ_ASSERT(mReadyState
== ReadyState::Inactive
);
228 mReadyState
= ReadyState::Active
;
231 void TransitionToInactive() {
232 MOZ_ASSERT(mReadyState
== ReadyState::Active
);
233 mReadyState
= ReadyState::Inactive
;
236 nsresult
AbortCode() const {
237 AssertIsOnOwningThread();
241 const JSCallingLocation
& GetCallerLocation() const {
242 AssertIsOnOwningThread();
243 return mCallerLocation
;
246 // 'Get' prefix is to avoid name collisions with the enum
247 Mode
GetMode() const {
248 AssertIsOnOwningThread();
252 Durability
GetDurability() const {
253 AssertIsOnOwningThread();
257 uint32_t GetPendingRequestCount() const { return mPendingRequestCount
; }
259 IDBDatabase
* Database() const {
260 AssertIsOnOwningThread();
264 // Only for use by ProfilerHelpers.h
265 const nsTArray
<nsString
>& ObjectStoreNamesInternal() const {
266 AssertIsOnOwningThread();
267 return mObjectStoreNames
;
270 [[nodiscard
]] RefPtr
<IDBObjectStore
> CreateObjectStore(
271 indexedDB::ObjectStoreSpec
& aSpec
);
273 void DeleteObjectStore(int64_t aObjectStoreId
);
275 void RenameObjectStore(int64_t aObjectStoreId
, const nsAString
& aName
) const;
277 void CreateIndex(IDBObjectStore
* aObjectStore
,
278 const indexedDB::IndexMetadata
& aMetadata
) const;
280 void DeleteIndex(IDBObjectStore
* aObjectStore
, int64_t aIndexId
) const;
282 void RenameIndex(IDBObjectStore
* aObjectStore
, int64_t aIndexId
,
283 const nsAString
& aName
) const;
285 void Abort(IDBRequest
* aRequest
);
287 void Abort(nsresult aErrorCode
);
289 int64_t LoggingSerialNumber() const {
290 AssertIsOnOwningThread();
292 return mLoggingSerialNumber
;
295 nsIGlobalObject
* GetParentObject() const;
297 void FireCompleteOrAbortEvents(nsresult aResult
);
299 // Only for Mode::VersionChange transactions.
300 int64_t NextObjectStoreId();
302 // Only for Mode::VersionChange transactions.
303 int64_t NextIndexId();
305 // See the comment for mNextRequestId.
306 int64_t NextRequestId();
308 void InvalidateCursorCaches();
309 void RegisterCursor(IDBCursor
& aCursor
);
310 void UnregisterCursor(IDBCursor
& aCursor
);
312 NS_DECL_ISUPPORTS_INHERITED
314 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBTransaction
, DOMEventTargetHelper
)
316 void CommitIfNotStarted();
319 JSObject
* WrapObject(JSContext
* aCx
,
320 JS::Handle
<JSObject
*> aGivenProto
) override
;
322 // Methods bound via WebIDL.
323 IDBDatabase
* Db() const { return Database(); }
325 IDBTransactionMode
GetMode(ErrorResult
& aRv
) const;
327 IDBTransactionDurability
GetDurability(ErrorResult
& aRv
) const;
329 DOMException
* GetError() const;
331 [[nodiscard
]] RefPtr
<IDBObjectStore
> ObjectStore(const nsAString
& aName
,
334 void Commit(ErrorResult
& aRv
);
336 void Abort(ErrorResult
& aRv
);
338 IMPL_EVENT_HANDLER(abort
)
339 IMPL_EVENT_HANDLER(complete
)
340 IMPL_EVENT_HANDLER(error
)
342 [[nodiscard
]] RefPtr
<DOMStringList
> ObjectStoreNames() const;
345 void GetEventTargetParent(EventChainPreVisitor
& aVisitor
) override
;
348 struct CreatedFromFactoryFunction
{};
351 IDBTransaction(IDBDatabase
* aDatabase
,
352 const nsTArray
<nsString
>& aObjectStoreNames
, Mode aMode
,
353 Durability aDurability
, JSCallingLocation
&& aCallerLocation
,
354 CreatedFromFactoryFunction aDummy
);
359 void AbortInternal(nsresult aAbortCode
, RefPtr
<DOMException
> aError
);
361 void SendCommit(bool aAutoCommit
);
363 void SendAbort(nsresult aResultCode
);
365 void NoteActiveTransaction();
367 void MaybeNoteInactiveTransaction();
369 // TODO consider making private again, or move to the right place
373 void OnRequestFinished(bool aRequestCompletedSuccessfully
);
376 template <typename Func
>
377 auto DoWithTransactionChild(const Func
& aFunc
) const;
379 bool HasTransactionChild() const;
382 inline bool ReferenceEquals(const Maybe
<IDBTransaction
&>& aLHS
,
383 const Maybe
<IDBTransaction
&>& aRHS
) {
384 if (aLHS
.isNothing() != aRHS
.isNothing()) {
387 return aLHS
.isNothing() || &aLHS
.ref() == &aRHS
.ref();
391 } // namespace mozilla
393 #endif // mozilla_dom_idbtransaction_h__