Bug 1936278 - Prevent search mode chiclet from being dismissed when clicking in page...
[gecko.git] / dom / indexedDB / IDBCursor.h
blobe719c024ec2242bdabb0432a59d57c12c9084226
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_idbcursor_h__
8 #define mozilla_dom_idbcursor_h__
10 #include "IDBCursorType.h"
11 #include "IndexedDatabase.h"
12 #include "js/RootingAPI.h"
13 #include "mozilla/Attributes.h"
14 #include "mozilla/dom/IDBCursorBinding.h"
15 #include "mozilla/dom/IDBTransaction.h"
16 #include "mozilla/dom/indexedDB/Key.h"
17 #include "mozilla/dom/quota/CheckedUnsafePtr.h"
18 #include "mozilla/InitializedOnce.h"
19 #include "nsCycleCollectionParticipant.h"
20 #include "nsWrapperCache.h"
22 class nsIGlobalObject;
24 namespace mozilla {
26 class ErrorResult;
28 namespace dom {
30 class IDBIndex;
31 class IDBObjectStore;
32 class IDBRequest;
33 class OwningIDBObjectStoreOrIDBIndex;
35 class IDBObjectStoreCursor;
36 class IDBObjectStoreKeyCursor;
37 class IDBIndexCursor;
38 class IDBIndexKeyCursor;
40 namespace indexedDB {
41 class BackgroundCursorChildBase;
42 template <IDBCursorType CursorType>
43 class BackgroundCursorChild;
44 } // namespace indexedDB
46 class IDBCursor : public nsISupports, public nsWrapperCache {
47 public:
48 using Key = indexedDB::Key;
49 using StructuredCloneReadInfoChild = indexedDB::StructuredCloneReadInfoChild;
51 using Direction = IDBCursorDirection;
52 using Type = IDBCursorType;
54 protected:
55 InitializedOnce<const NotNull<indexedDB::BackgroundCursorChildBase*>>
56 mBackgroundActor;
58 // TODO: mRequest could be made const if Bug 1575173 is resolved. It is
59 // initialized in the constructor and never modified/cleared.
60 RefPtr<IDBRequest> mRequest;
62 // Sub-classes' mSource will hold this alive.
63 CheckedUnsafePtr<IDBTransaction> mTransaction;
65 protected:
66 // These are cycle-collected!
67 JS::Heap<JS::Value> mCachedKey;
68 JS::Heap<JS::Value> mCachedPrimaryKey;
69 JS::Heap<JS::Value> mCachedValue;
71 const Direction mDirection;
73 bool mHaveCachedKey : 1;
74 bool mHaveCachedPrimaryKey : 1;
75 bool mHaveCachedValue : 1;
76 bool mRooted : 1;
77 bool mContinueCalled : 1;
78 bool mHaveValue : 1;
80 public:
81 [[nodiscard]] static RefPtr<IDBObjectStoreCursor> Create(
82 indexedDB::BackgroundCursorChild<Type::ObjectStore>* aBackgroundActor,
83 Key aKey, StructuredCloneReadInfoChild&& aCloneInfo);
85 [[nodiscard]] static RefPtr<IDBObjectStoreKeyCursor> Create(
86 indexedDB::BackgroundCursorChild<Type::ObjectStoreKey>* aBackgroundActor,
87 Key aKey);
89 [[nodiscard]] static RefPtr<IDBIndexCursor> Create(
90 indexedDB::BackgroundCursorChild<Type::Index>* aBackgroundActor, Key aKey,
91 Key aSortKey, Key aPrimaryKey, StructuredCloneReadInfoChild&& aCloneInfo);
93 [[nodiscard]] static RefPtr<IDBIndexKeyCursor> Create(
94 indexedDB::BackgroundCursorChild<Type::IndexKey>* aBackgroundActor,
95 Key aKey, Key aSortKey, Key aPrimaryKey);
97 void AssertIsOnOwningThread() const
98 #ifdef DEBUG
100 #else
103 #endif
105 nsIGlobalObject* GetParentObject() const;
107 // XXX: The virtual methods that are used by the DOM binding could be removed
108 // on the base class, if we provided a non-polymorphic wrapper instead, which
109 // uses a custom dispatch to the actual implementation type. Don't know if
110 // this is worth it.
112 virtual void GetSource(OwningIDBObjectStoreOrIDBIndex& aSource) const = 0;
114 IDBCursorDirection GetDirection() const;
116 RefPtr<IDBRequest> Request() const;
118 virtual void GetKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
119 ErrorResult& aRv) = 0;
121 virtual void GetPrimaryKey(JSContext* aCx,
122 JS::MutableHandle<JS::Value> aResult,
123 ErrorResult& aRv) = 0;
125 // XXX: We could move this to a sub-class, since this is only present on
126 // IDBCursorWithValue.
127 virtual void GetValue(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
128 ErrorResult& aRv) = 0;
130 virtual void Continue(JSContext* aCx, JS::Handle<JS::Value> aKey,
131 ErrorResult& aRv) = 0;
133 virtual void ContinuePrimaryKey(JSContext* aCx, JS::Handle<JS::Value> aKey,
134 JS::Handle<JS::Value> aPrimaryKey,
135 ErrorResult& aRv) = 0;
137 virtual void Advance(uint32_t aCount, ErrorResult& aRv) = 0;
139 [[nodiscard]] virtual RefPtr<IDBRequest> Update(JSContext* aCx,
140 JS::Handle<JS::Value> aValue,
141 ErrorResult& aRv) = 0;
143 [[nodiscard]] virtual RefPtr<IDBRequest> Delete(JSContext* aCx,
144 ErrorResult& aRv) = 0;
146 void ClearBackgroundActor() {
147 AssertIsOnOwningThread();
149 mBackgroundActor.destroy();
152 virtual void InvalidateCachedResponses() = 0;
154 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
155 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBCursor)
157 protected:
158 IDBCursor(indexedDB::BackgroundCursorChildBase* aBackgroundActor);
160 // TODO: Check if we can remove virtual by changing cycle collection.
161 virtual ~IDBCursor() = default;
163 void ResetBase();
166 template <IDBCursor::Type CursorType>
167 class IDBTypedCursor : public IDBCursor {
168 public:
169 template <typename... DataArgs>
170 explicit IDBTypedCursor(
171 indexedDB::BackgroundCursorChild<CursorType>* aBackgroundActor,
172 DataArgs&&... aDataArgs);
174 static constexpr Type GetType() { return CursorType; }
176 // Checks if this is a locale aware cursor (ie. the index's sortKey is unset)
177 bool IsLocaleAware() const;
179 void GetSource(OwningIDBObjectStoreOrIDBIndex& aSource) const final;
181 void GetKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
182 ErrorResult& aRv) final;
184 void GetPrimaryKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
185 ErrorResult& aRv) final;
187 void GetValue(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
188 ErrorResult& aRv) final;
190 void Continue(JSContext* aCx, JS::Handle<JS::Value> aKey,
191 ErrorResult& aRv) final;
193 void ContinuePrimaryKey(JSContext* aCx, JS::Handle<JS::Value> aKey,
194 JS::Handle<JS::Value> aPrimaryKey,
195 ErrorResult& aRv) final;
197 void Advance(uint32_t aCount, ErrorResult& aRv) final;
199 [[nodiscard]] RefPtr<IDBRequest> Update(JSContext* aCx,
200 JS::Handle<JS::Value> aValue,
201 ErrorResult& aRv) final;
203 [[nodiscard]] RefPtr<IDBRequest> Delete(JSContext* aCx,
204 ErrorResult& aRv) final;
206 // nsWrapperCache
207 JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) final;
209 void InvalidateCachedResponses() final;
211 void Reset();
213 void Reset(CursorData<CursorType>&& aCursorData);
215 private:
216 static constexpr bool IsObjectStoreCursor =
217 CursorTypeTraits<CursorType>::IsObjectStoreCursor;
218 static constexpr bool IsKeyOnlyCursor =
219 CursorTypeTraits<CursorType>::IsKeyOnlyCursor;
221 CursorSourceType<CursorType>& GetSourceRef() const {
222 MOZ_ASSERT(mSource);
223 return *mSource;
226 IDBObjectStore& GetSourceObjectStoreRef() const {
227 if constexpr (IsObjectStoreCursor) {
228 return GetSourceRef();
229 } else {
230 MOZ_ASSERT(!GetSourceRef().IsDeleted());
232 auto res = GetSourceRef().ObjectStore();
233 MOZ_ASSERT(res);
234 return *res;
238 indexedDB::BackgroundCursorChild<CursorType>& GetTypedBackgroundActorRef()
239 const {
240 // We can safely downcast to BackgroundCursorChild<CursorType>*, since we
241 // initialized that in the constructor from that type. We just want to avoid
242 // having a second typed field.
243 return *static_cast<indexedDB::BackgroundCursorChild<CursorType>*>(
244 mBackgroundActor->get());
247 bool IsSourceDeleted() const;
249 protected:
250 virtual ~IDBTypedCursor() override;
252 void DropJSObjects();
254 CursorData<CursorType> mData;
256 // TODO: mSource could be made const if Bug 1575173 is resolved. It is
257 // initialized in the constructor and never modified/cleared.
258 RefPtr<CursorSourceType<CursorType>> mSource;
261 // The subclasses defined by this macro are only needed to be able to use the
262 // cycle collector macros, which do not support templates. If spelled out, the
263 // cycle collection could be implemented directly on IDBTypedCursor, and these
264 // classes were not needed.
265 #define CONCRETE_IDBCURSOR_SUBCLASS(_subclassName, _cursorType) \
266 class _subclassName final : public IDBTypedCursor<_cursorType> { \
267 public: \
268 NS_DECL_ISUPPORTS_INHERITED \
269 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(_subclassName, IDBCursor) \
271 using IDBTypedCursor<_cursorType>::IDBTypedCursor; \
273 private: \
274 ~_subclassName() final = default; \
277 CONCRETE_IDBCURSOR_SUBCLASS(IDBObjectStoreCursor, IDBCursor::Type::ObjectStore)
278 CONCRETE_IDBCURSOR_SUBCLASS(IDBObjectStoreKeyCursor,
279 IDBCursor::Type::ObjectStoreKey)
280 CONCRETE_IDBCURSOR_SUBCLASS(IDBIndexCursor, IDBCursor::Type::Index)
281 CONCRETE_IDBCURSOR_SUBCLASS(IDBIndexKeyCursor, IDBCursor::Type::IndexKey)
283 template <IDBCursor::Type CursorType>
284 using IDBCursorImpl = typename CursorTypeTraits<CursorType>::Type;
286 } // namespace dom
287 } // namespace mozilla
289 #endif // mozilla_dom_idbcursor_h__