Bug 1886946: Remove incorrect assertion that buffer is not-pinned. r=sfink
[gecko.git] / dom / indexedDB / IDBTransaction.h
blob9feafb3c68ae4264f89667969d95d0c56b29021b
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"
17 #include "nsString.h"
18 #include "nsTArray.h"
19 #include "SafeRefPtr.h"
21 namespace mozilla {
23 class ErrorResult;
24 class EventChainPreVisitor;
26 namespace dom {
28 class DOMException;
29 class DOMStringList;
30 class IDBCursor;
31 class IDBDatabase;
32 class IDBObjectStore;
33 class IDBOpenDBRequest;
34 class IDBRequest;
35 class StrongWorkerRef;
37 namespace indexedDB {
38 class PBackgroundIDBCursorChild;
39 class BackgroundRequestChild;
40 class BackgroundTransactionChild;
41 class BackgroundVersionChangeTransactionChild;
42 class IndexMetadata;
43 class ObjectStoreSpec;
44 class OpenCursorParams;
45 class RequestParams;
46 } // namespace indexedDB
48 class IDBTransaction final
49 : public DOMEventTargetHelper,
50 public nsIRunnable,
51 public SupportsCheckedUnsafePtr<CheckIf<DiagnosticAssertEnabled>> {
52 friend class indexedDB::BackgroundRequestChild;
54 public:
55 enum struct Mode {
56 ReadOnly = 0,
57 ReadWrite,
58 ReadWriteFlush,
59 Cleanup,
60 VersionChange,
62 // Only needed for IPC serialization helper, should never be used in code.
63 Invalid
66 enum struct Durability {
67 Default = 0,
68 Strict,
69 Relaxed,
71 // Only needed for IPC serialization helper, should never be used in code.
72 Invalid
75 enum struct ReadyState { Active, Inactive, Committing, Finished };
77 private:
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.
90 union {
91 indexedDB::BackgroundTransactionChild* mNormalBackgroundActor;
92 indexedDB::BackgroundVersionChangeTransactionChild*
93 mVersionChangeBackgroundActor;
94 } mBackgroundActor;
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;
124 const Mode mMode;
125 const Durability mDurability;
127 bool mRegistered; ///< Whether mDatabase->RegisterTransaction() has been
128 ///< called (which may not be the case if construction was
129 ///< incomplete).
130 FlippedOnce<false> mAbortedByScript;
131 bool mNotedActiveTransaction;
132 FlippedOnce<false> mSentCommitOrAbort;
134 #ifdef DEBUG
135 FlippedOnce<false> mFiredCompleteOrAbort;
136 FlippedOnce<false> mWasExplicitlyCommitted;
137 #endif
139 public:
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
154 #ifdef DEBUG
156 #else
159 #endif
161 void SetBackgroundActor(
162 indexedDB::BackgroundTransactionChild* aBackgroundActor);
164 void ClearBackgroundActor() {
165 AssertIsOnOwningThread();
167 if (mMode == Mode::VersionChange) {
168 mBackgroundActor.mVersionChangeBackgroundActor = nullptr;
169 } else {
170 mBackgroundActor.mNormalBackgroundActor = nullptr;
173 // Note inactive transaction here if we didn't receive the Complete message
174 // from the parent.
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);
223 #ifdef DEBUG
224 bool WasExplicitlyCommitted() const { return mWasExplicitlyCommitted; }
225 #endif
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();
239 return mAbortCode;
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();
248 return mMode;
251 Durability GetDurability() const {
252 AssertIsOnOwningThread();
253 return mDurability;
256 uint32_t GetPendingRequestCount() const { return mPendingRequestCount; }
258 IDBDatabase* Database() const {
259 AssertIsOnOwningThread();
260 return mDatabase;
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
312 NS_DECL_NSIRUNNABLE
313 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBTransaction, DOMEventTargetHelper)
315 void CommitIfNotStarted();
317 // nsWrapperCache
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,
331 ErrorResult& aRv);
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;
343 // EventTarget
344 void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
346 private:
347 struct CreatedFromFactoryFunction {};
349 public:
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);
355 private:
356 ~IDBTransaction();
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
369 public:
370 void OnNewRequest();
372 void OnRequestFinished(bool aRequestCompletedSuccessfully);
374 private:
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()) {
384 return false;
386 return aLHS.isNothing() || &aLHS.ref() == &aRHS.ref();
389 } // namespace dom
390 } // namespace mozilla
392 #endif // mozilla_dom_idbtransaction_h__