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/. */
6 
7 #ifndef mozilla_dom_idbcursor_h__
8 #define mozilla_dom_idbcursor_h__
9 
10 #include "IndexedDatabase.h"
11 #include "js/RootingAPI.h"
12 #include "mozilla/Attributes.h"
13 #include "mozilla/dom/IDBCursorBinding.h"
14 #include "mozilla/dom/indexedDB/Key.h"
15 #include "nsCycleCollectionParticipant.h"
16 #include "nsWrapperCache.h"
17 
18 class nsPIDOMWindowInner;
19 
20 namespace mozilla {
21 
22 class ErrorResult;
23 
24 namespace dom {
25 
26 class IDBIndex;
27 class IDBObjectStore;
28 class IDBRequest;
29 class IDBTransaction;
30 class OwningIDBObjectStoreOrIDBIndex;
31 
32 namespace indexedDB {
33 class BackgroundCursorChild;
34 }
35 
36 class IDBCursor final : public nsISupports, public nsWrapperCache {
37  public:
38   typedef indexedDB::Key Key;
39   typedef indexedDB::StructuredCloneReadInfo StructuredCloneReadInfo;
40 
41   enum Direction {
42     NEXT = 0,
43     NEXT_UNIQUE,
44     PREV,
45     PREV_UNIQUE,
46 
47     // Only needed for IPC serialization helper, should never be used in code.
48     DIRECTION_INVALID
49   };
50 
51  private:
52   enum Type {
53     Type_ObjectStore,
54     Type_ObjectStoreKey,
55     Type_Index,
56     Type_IndexKey,
57   };
58 
59   indexedDB::BackgroundCursorChild* mBackgroundActor;
60 
61   RefPtr<IDBRequest> mRequest;
62   RefPtr<IDBObjectStore> mSourceObjectStore;
63   RefPtr<IDBIndex> mSourceIndex;
64 
65   // mSourceObjectStore or mSourceIndex will hold this alive.
66   IDBTransaction* mTransaction;
67 
68   JS::Heap<JSObject*> mScriptOwner;
69 
70   // These are cycle-collected!
71   JS::Heap<JS::Value> mCachedKey;
72   JS::Heap<JS::Value> mCachedPrimaryKey;
73   JS::Heap<JS::Value> mCachedValue;
74 
75   Key mKey;
76   Key mSortKey;
77   Key mPrimaryKey;
78   StructuredCloneReadInfo mCloneInfo;
79 
80   const Type mType;
81   const Direction mDirection;
82 
83   bool mHaveCachedKey : 1;
84   bool mHaveCachedPrimaryKey : 1;
85   bool mHaveCachedValue : 1;
86   bool mRooted : 1;
87   bool mContinueCalled : 1;
88   bool mHaveValue : 1;
89 
90  public:
91   static already_AddRefed<IDBCursor> Create(
92       indexedDB::BackgroundCursorChild* aBackgroundActor, const Key& aKey,
93       StructuredCloneReadInfo&& aCloneInfo);
94 
95   static already_AddRefed<IDBCursor> Create(
96       indexedDB::BackgroundCursorChild* aBackgroundActor, const Key& aKey);
97 
98   static already_AddRefed<IDBCursor> Create(
99       indexedDB::BackgroundCursorChild* aBackgroundActor, const Key& aKey,
100       const Key& aSortKey, const Key& aPrimaryKey,
101       StructuredCloneReadInfo&& aCloneInfo);
102 
103   static already_AddRefed<IDBCursor> Create(
104       indexedDB::BackgroundCursorChild* aBackgroundActor, const Key& aKey,
105       const Key& aSortKey, const Key& aPrimaryKey);
106 
107   static Direction ConvertDirection(IDBCursorDirection aDirection);
108 
109   void AssertIsOnOwningThread() const
110 #ifdef DEBUG
111       ;
112 #else
113   {
114   }
115 #endif
116 
117   nsPIDOMWindowInner* GetParentObject() const;
118 
119   void GetSource(OwningIDBObjectStoreOrIDBIndex& aSource) const;
120 
121   IDBCursorDirection GetDirection() const;
122 
123   void GetKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
124               ErrorResult& aRv);
125 
126   void GetPrimaryKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
127                      ErrorResult& aRv);
128 
129   void GetValue(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
130                 ErrorResult& aRv);
131 
132   void Continue(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
133 
134   void ContinuePrimaryKey(JSContext* aCx, JS::Handle<JS::Value> aKey,
135                           JS::Handle<JS::Value> aPrimaryKey, ErrorResult& aRv);
136 
137   void Advance(uint32_t aCount, ErrorResult& aRv);
138 
139   already_AddRefed<IDBRequest> Update(JSContext* aCx,
140                                       JS::Handle<JS::Value> aValue,
141                                       ErrorResult& aRv);
142 
143   already_AddRefed<IDBRequest> Delete(JSContext* aCx, ErrorResult& aRv);
144 
145   void Reset();
146 
147   void Reset(Key&& aKey, StructuredCloneReadInfo&& aValue);
148 
149   void Reset(Key&& aKey);
150 
151   void Reset(Key&& aKey, Key&& aSortKey, Key&& aPrimaryKey,
152              StructuredCloneReadInfo&& aValue);
153 
154   void Reset(Key&& aKey, Key&& aSortKey, Key&& aPrimaryKey);
155 
ClearBackgroundActor()156   void ClearBackgroundActor() {
157     AssertIsOnOwningThread();
158 
159     mBackgroundActor = nullptr;
160   }
161 
162   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
163   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBCursor)
164 
165   // nsWrapperCache
166   virtual JSObject* WrapObject(JSContext* aCx,
167                                JS::Handle<JSObject*> aGivenProto) override;
168 
169  private:
170   IDBCursor(Type aType, indexedDB::BackgroundCursorChild* aBackgroundActor,
171             const Key& aKey);
172 
173   ~IDBCursor();
174 
175   // Checks if this is a locale aware cursor (ie. the index's sortKey is unset)
176   bool IsLocaleAware() const;
177 
178   void DropJSObjects();
179 
180   bool IsSourceDeleted() const;
181 };
182 
183 }  // namespace dom
184 }  // namespace mozilla
185 
186 #endif  // mozilla_dom_idbcursor_h__
187