IndexedDB 2.0: Encapsulate cursor iteration parameters for easy future expansion.
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / IDBTransaction.h
1 /*
2  * Copyright (C) 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #if ENABLE(INDEXED_DATABASE)
29
30 #include "EventTarget.h"
31 #include "IDBActiveDOMObject.h"
32 #include "IDBError.h"
33 #include "IDBGetAllRecordsData.h"
34 #include "IDBGetRecordData.h"
35 #include "IDBKeyRangeData.h"
36 #include "IDBOpenDBRequest.h"
37 #include "IDBTransactionInfo.h"
38 #include "IDBTransactionMode.h"
39 #include "IndexedDB.h"
40 #include "Timer.h"
41 #include <wtf/Deque.h>
42 #include <wtf/HashMap.h>
43
44 namespace WebCore {
45
46 class DOMError;
47 class DOMStringList;
48 class IDBCursor;
49 class IDBCursorInfo;
50 class IDBDatabase;
51 class IDBIndex;
52 class IDBIndexInfo;
53 class IDBKey;
54 class IDBKeyData;
55 class IDBObjectStore;
56 class IDBObjectStoreInfo;
57 class IDBResultData;
58 class SerializedScriptValue;
59
60 struct IDBIterateCursorData;
61 struct IDBKeyRangeData;
62
63 namespace IDBClient {
64 class IDBConnectionProxy;
65 class TransactionOperation;
66 }
67
68 class IDBTransaction : public ThreadSafeRefCounted<IDBTransaction>, public EventTargetWithInlineData, public IDBActiveDOMObject {
69 public:
70     static Ref<IDBTransaction> create(IDBDatabase&, const IDBTransactionInfo&);
71     static Ref<IDBTransaction> create(IDBDatabase&, const IDBTransactionInfo&, IDBOpenDBRequest&);
72
73     ~IDBTransaction() final;
74
75     // IDBTransaction IDL
76     Ref<DOMStringList> objectStoreNames() const;
77     IDBTransactionMode mode() const { return m_info.mode(); }
78     IDBDatabase* db();
79     DOMError* error() const;
80     ExceptionOr<Ref<IDBObjectStore>> objectStore(const String& name);
81     ExceptionOr<void> abort();
82
83     EventTargetInterface eventTargetInterface() const final { return IDBTransactionEventTargetInterfaceType; }
84     ScriptExecutionContext* scriptExecutionContext() const final { return ActiveDOMObject::scriptExecutionContext(); }
85     void refEventTarget() final { ThreadSafeRefCounted::ref(); }
86     void derefEventTarget() final { ThreadSafeRefCounted::deref(); }
87     using EventTarget::dispatchEvent;
88     bool dispatchEvent(Event&) final;
89
90     using ThreadSafeRefCounted<IDBTransaction>::ref;
91     using ThreadSafeRefCounted<IDBTransaction>::deref;
92
93     const char* activeDOMObjectName() const final;
94     bool canSuspendForDocumentSuspension() const final;
95     bool hasPendingActivity() const final;
96     void stop() final;
97
98     const IDBTransactionInfo& info() const { return m_info; }
99     IDBDatabase& database() { return m_database.get(); }
100     const IDBDatabase& database() const { return m_database.get(); }
101     IDBDatabaseInfo* originalDatabaseInfo() const { return m_info.originalDatabaseInfo(); }
102
103     void didStart(const IDBError&);
104     void didAbort(const IDBError&);
105     void didCommit(const IDBError&);
106
107     bool isVersionChange() const { return mode() == IDBTransactionMode::Versionchange; }
108     bool isReadOnly() const { return mode() == IDBTransactionMode::Readonly; }
109     bool isActive() const;
110
111     Ref<IDBObjectStore> createObjectStore(const IDBObjectStoreInfo&);
112     void renameObjectStore(IDBObjectStore&, const String& newName);
113     std::unique_ptr<IDBIndex> createIndex(IDBObjectStore&, const IDBIndexInfo&);
114     void renameIndex(IDBIndex&, const String& newName);
115
116     Ref<IDBRequest> requestPutOrAdd(JSC::ExecState&, IDBObjectStore&, IDBKey*, SerializedScriptValue&, IndexedDB::ObjectStoreOverwriteMode);
117     Ref<IDBRequest> requestGetRecord(JSC::ExecState&, IDBObjectStore&, const IDBGetRecordData&);
118     Ref<IDBRequest> requestGetAllObjectStoreRecords(JSC::ExecState&, IDBObjectStore&, const IDBKeyRangeData&, IndexedDB::GetAllType, Optional<uint32_t> count);
119     Ref<IDBRequest> requestGetAllIndexRecords(JSC::ExecState&, IDBIndex&, const IDBKeyRangeData&, IndexedDB::GetAllType, Optional<uint32_t> count);
120     Ref<IDBRequest> requestDeleteRecord(JSC::ExecState&, IDBObjectStore&, const IDBKeyRangeData&);
121     Ref<IDBRequest> requestClearObjectStore(JSC::ExecState&, IDBObjectStore&);
122     Ref<IDBRequest> requestCount(JSC::ExecState&, IDBObjectStore&, const IDBKeyRangeData&);
123     Ref<IDBRequest> requestCount(JSC::ExecState&, IDBIndex&, const IDBKeyRangeData&);
124     Ref<IDBRequest> requestGetValue(JSC::ExecState&, IDBIndex&, const IDBKeyRangeData&);
125     Ref<IDBRequest> requestGetKey(JSC::ExecState&, IDBIndex&, const IDBKeyRangeData&);
126     Ref<IDBRequest> requestOpenCursor(JSC::ExecState&, IDBObjectStore&, const IDBCursorInfo&);
127     Ref<IDBRequest> requestOpenCursor(JSC::ExecState&, IDBIndex&, const IDBCursorInfo&);
128     void iterateCursor(IDBCursor&, const IDBIterateCursorData&);
129
130     void deleteObjectStore(const String& objectStoreName);
131     void deleteIndex(uint64_t objectStoreIdentifier, const String& indexName);
132
133     void addRequest(IDBRequest&);
134     void removeRequest(IDBRequest&);
135
136     void abortDueToFailedRequest(DOMError&);
137
138     void activate();
139     void deactivate();
140
141     void operationDidComplete(IDBClient::TransactionOperation&);
142
143     bool isFinishedOrFinishing() const;
144     bool isFinished() const { return m_state == IndexedDB::TransactionState::Finished; }
145
146     IDBClient::IDBConnectionProxy& connectionProxy();
147
148     void connectionClosedFromServer(const IDBError&);
149
150     void visitReferencedObjectStores(JSC::SlotVisitor&) const;
151
152 private:
153     IDBTransaction(IDBDatabase&, const IDBTransactionInfo&, IDBOpenDBRequest*);
154
155     void commit();
156
157     void internalAbort();
158     void notifyDidAbort(const IDBError&);
159     void finishAbortOrCommit();
160
161     void scheduleOperation(RefPtr<IDBClient::TransactionOperation>&&);
162     void operationTimerFired();
163
164     void fireOnComplete();
165     void fireOnAbort();
166     void enqueueEvent(Ref<Event>&&);
167
168     Ref<IDBRequest> requestIndexRecord(JSC::ExecState&, IDBIndex&, IndexedDB::IndexRecordType, const IDBKeyRangeData&);
169
170     void commitOnServer(IDBClient::TransactionOperation&);
171     void abortOnServerAndCancelRequests(IDBClient::TransactionOperation&);
172
173     void createObjectStoreOnServer(IDBClient::TransactionOperation&, const IDBObjectStoreInfo&);
174     void didCreateObjectStoreOnServer(const IDBResultData&);
175
176     void renameObjectStoreOnServer(IDBClient::TransactionOperation&, const uint64_t& objectStoreIdentifier, const String& newName);
177     void didRenameObjectStoreOnServer(const IDBResultData&);
178
179     void createIndexOnServer(IDBClient::TransactionOperation&, const IDBIndexInfo&);
180     void didCreateIndexOnServer(const IDBResultData&);
181
182     void renameIndexOnServer(IDBClient::TransactionOperation&, const uint64_t& objectStoreIdentifier, const uint64_t& indexIdentifier, const String& newName);
183     void didRenameIndexOnServer(const IDBResultData&);
184
185     void clearObjectStoreOnServer(IDBClient::TransactionOperation&, const uint64_t& objectStoreIdentifier);
186     void didClearObjectStoreOnServer(IDBRequest&, const IDBResultData&);
187
188     void putOrAddOnServer(IDBClient::TransactionOperation&, RefPtr<IDBKey>, RefPtr<SerializedScriptValue>, const IndexedDB::ObjectStoreOverwriteMode&);
189     void didPutOrAddOnServer(IDBRequest&, const IDBResultData&);
190
191     void getRecordOnServer(IDBClient::TransactionOperation&, const IDBGetRecordData&);
192     void didGetRecordOnServer(IDBRequest&, const IDBResultData&);
193
194     void getAllRecordsOnServer(IDBClient::TransactionOperation&, const IDBGetAllRecordsData&);
195     void didGetAllRecordsOnServer(IDBRequest&, const IDBResultData&);
196
197     void getCountOnServer(IDBClient::TransactionOperation&, const IDBKeyRangeData&);
198     void didGetCountOnServer(IDBRequest&, const IDBResultData&);
199
200     void deleteRecordOnServer(IDBClient::TransactionOperation&, const IDBKeyRangeData&);
201     void didDeleteRecordOnServer(IDBRequest&, const IDBResultData&);
202
203     void deleteObjectStoreOnServer(IDBClient::TransactionOperation&, const String& objectStoreName);
204     void didDeleteObjectStoreOnServer(const IDBResultData&);
205
206     void deleteIndexOnServer(IDBClient::TransactionOperation&, const uint64_t& objectStoreIdentifier, const String& indexName);
207     void didDeleteIndexOnServer(const IDBResultData&);
208
209     Ref<IDBRequest> doRequestOpenCursor(JSC::ExecState&, Ref<IDBCursor>&&);
210     void openCursorOnServer(IDBClient::TransactionOperation&, const IDBCursorInfo&);
211     void didOpenCursorOnServer(IDBRequest&, const IDBResultData&);
212
213     void iterateCursorOnServer(IDBClient::TransactionOperation&, const IDBIterateCursorData&);
214     void didIterateCursorOnServer(IDBRequest&, const IDBResultData&);
215
216     void transitionedToFinishing(IndexedDB::TransactionState);
217
218     void establishOnServer();
219
220     void scheduleOperationTimer();
221
222     Ref<IDBDatabase> m_database;
223     IDBTransactionInfo m_info;
224
225     IndexedDB::TransactionState m_state { IndexedDB::TransactionState::Inactive };
226     bool m_startedOnServer { false };
227
228     IDBError m_idbError;
229     RefPtr<DOMError> m_domError;
230
231     Timer m_operationTimer;
232     std::unique_ptr<Timer> m_activationTimer;
233
234     RefPtr<IDBOpenDBRequest> m_openDBRequest;
235
236     Deque<RefPtr<IDBClient::TransactionOperation>> m_transactionOperationQueue;
237     Deque<RefPtr<IDBClient::TransactionOperation>> m_abortQueue;
238     HashMap<IDBResourceIdentifier, RefPtr<IDBClient::TransactionOperation>> m_transactionOperationMap;
239
240     mutable Lock m_referencedObjectStoreLock;
241     HashMap<String, std::unique_ptr<IDBObjectStore>> m_referencedObjectStores;
242     HashMap<uint64_t, std::unique_ptr<IDBObjectStore>> m_deletedObjectStores;
243
244     HashSet<RefPtr<IDBRequest>> m_openRequests;
245
246     bool m_contextStopped { false };
247 };
248
249 class TransactionActivator {
250     WTF_MAKE_NONCOPYABLE(TransactionActivator);
251 public:
252     TransactionActivator(IDBTransaction* transaction)
253         : m_transaction(transaction)
254     {
255         if (m_transaction)
256             m_transaction->activate();
257     }
258
259     ~TransactionActivator()
260     {
261         if (m_transaction)
262             m_transaction->deactivate();
263     }
264
265 private:
266     IDBTransaction* m_transaction;
267 };
268
269 } // namespace WebCore
270
271 #endif // ENABLE(INDEXED_DATABASE)