Modern IDB: Pipe through cursor functions from client to server.
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / server / UniqueIDBDatabaseTransaction.cpp
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 #include "config.h"
27 #include "UniqueIDBDatabaseTransaction.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "IDBError.h"
32 #include "IDBResultData.h"
33 #include "IDBServer.h"
34 #include "Logging.h"
35 #include "UniqueIDBDatabase.h"
36
37 namespace WebCore {
38 namespace IDBServer {
39
40 Ref<UniqueIDBDatabaseTransaction> UniqueIDBDatabaseTransaction::create(UniqueIDBDatabaseConnection& connection, const IDBTransactionInfo& info)
41 {
42     return adoptRef(*new UniqueIDBDatabaseTransaction(connection, info));
43 }
44
45 UniqueIDBDatabaseTransaction::UniqueIDBDatabaseTransaction(UniqueIDBDatabaseConnection& connection, const IDBTransactionInfo& info)
46     : m_databaseConnection(connection)
47     , m_transactionInfo(info)
48 {
49     if (m_transactionInfo.mode() == IndexedDB::TransactionMode::VersionChange)
50         m_originalDatabaseInfo = std::make_unique<IDBDatabaseInfo>(m_databaseConnection->database().info());
51
52     m_databaseConnection->database().server().registerTransaction(*this);
53 }
54
55 UniqueIDBDatabaseTransaction::~UniqueIDBDatabaseTransaction()
56 {
57     m_databaseConnection->database().transactionDestroyed(*this);
58     m_databaseConnection->database().server().unregisterTransaction(*this);
59 }
60
61 IDBDatabaseInfo* UniqueIDBDatabaseTransaction::originalDatabaseInfo() const
62 {
63     ASSERT(m_transactionInfo.mode() == IndexedDB::TransactionMode::VersionChange);
64     return m_originalDatabaseInfo.get();
65 }
66
67 void UniqueIDBDatabaseTransaction::abort()
68 {
69     LOG(IndexedDB, "UniqueIDBDatabaseTransaction::abort");
70
71     RefPtr<UniqueIDBDatabaseTransaction> self(this);
72     m_databaseConnection->database().abortTransaction(*this, [this, self](const IDBError& error) {
73         LOG(IndexedDB, "UniqueIDBDatabaseTransaction::abort (callback)");
74         m_databaseConnection->didAbortTransaction(*this, error);
75     });
76 }
77
78 bool UniqueIDBDatabaseTransaction::isVersionChange() const
79 {
80     return m_transactionInfo.mode() == IndexedDB::TransactionMode::VersionChange;
81 }
82
83 bool UniqueIDBDatabaseTransaction::isReadOnly() const
84 {
85     return m_transactionInfo.mode() == IndexedDB::TransactionMode::ReadOnly;
86 }   
87
88 void UniqueIDBDatabaseTransaction::commit()
89 {
90     LOG(IndexedDB, "UniqueIDBDatabaseTransaction::commit");
91
92     RefPtr<UniqueIDBDatabaseTransaction> self(this);
93     m_databaseConnection->database().commitTransaction(*this, [this, self](const IDBError& error) {
94         LOG(IndexedDB, "UniqueIDBDatabaseTransaction::commit (callback)");
95         m_databaseConnection->didCommitTransaction(*this, error);
96     });
97 }
98
99 void UniqueIDBDatabaseTransaction::createObjectStore(const IDBRequestData& requestData, const IDBObjectStoreInfo& info)
100 {
101     LOG(IndexedDB, "UniqueIDBDatabaseTransaction::createObjectStore");
102
103     ASSERT(isVersionChange());
104     ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier());
105
106     RefPtr<UniqueIDBDatabaseTransaction> self(this);
107     m_databaseConnection->database().createObjectStore(*this, info, [this, self, requestData](const IDBError& error) {
108         LOG(IndexedDB, "UniqueIDBDatabaseTransaction::createObjectStore (callback)");
109         if (error.isNull())
110             m_databaseConnection->didCreateObjectStore(IDBResultData::createObjectStoreSuccess(requestData.requestIdentifier()));
111         else
112             m_databaseConnection->didCreateObjectStore(IDBResultData::error(requestData.requestIdentifier(), error));
113     });
114 }
115
116 void UniqueIDBDatabaseTransaction::deleteObjectStore(const IDBRequestData& requestData, const String& objectStoreName)
117 {
118     LOG(IndexedDB, "UniqueIDBDatabaseTransaction::deleteObjectStore");
119
120     ASSERT(isVersionChange());
121     ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier());
122
123     RefPtr<UniqueIDBDatabaseTransaction> self(this);
124     m_databaseConnection->database().deleteObjectStore(*this, objectStoreName, [this, self, requestData](const IDBError& error) {
125         LOG(IndexedDB, "UniqueIDBDatabaseTransaction::deleteObjectStore (callback)");
126         if (error.isNull())
127             m_databaseConnection->didDeleteObjectStore(IDBResultData::deleteObjectStoreSuccess(requestData.requestIdentifier()));
128         else
129             m_databaseConnection->didDeleteObjectStore(IDBResultData::error(requestData.requestIdentifier(), error));
130     });
131 }
132
133 void UniqueIDBDatabaseTransaction::clearObjectStore(const IDBRequestData& requestData, uint64_t objectStoreIdentifier)
134 {
135     LOG(IndexedDB, "UniqueIDBDatabaseTransaction::clearObjectStore");
136
137     ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier());
138
139     RefPtr<UniqueIDBDatabaseTransaction> self(this);
140     m_databaseConnection->database().clearObjectStore(*this, objectStoreIdentifier, [this, self, requestData](const IDBError& error) {
141         LOG(IndexedDB, "UniqueIDBDatabaseTransaction::clearObjectStore (callback)");
142         if (error.isNull())
143             m_databaseConnection->didClearObjectStore(IDBResultData::clearObjectStoreSuccess(requestData.requestIdentifier()));
144         else
145             m_databaseConnection->didClearObjectStore(IDBResultData::error(requestData.requestIdentifier(), error));
146     });
147 }
148
149 void UniqueIDBDatabaseTransaction::createIndex(const IDBRequestData& requestData, const IDBIndexInfo& info)
150 {
151     LOG(IndexedDB, "UniqueIDBDatabaseTransaction::createIndex");
152
153     ASSERT(isVersionChange());
154     ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier());
155
156     RefPtr<UniqueIDBDatabaseTransaction> self(this);
157     m_databaseConnection->database().createIndex(*this, info, [this, self, requestData](const IDBError& error) {
158         LOG(IndexedDB, "UniqueIDBDatabaseTransaction::createIndex (callback)");
159         if (error.isNull())
160             m_databaseConnection->didCreateIndex(IDBResultData::createIndexSuccess(requestData.requestIdentifier()));
161         else
162             m_databaseConnection->didCreateIndex(IDBResultData::error(requestData.requestIdentifier(), error));
163     });
164 }
165
166 void UniqueIDBDatabaseTransaction::putOrAdd(const IDBRequestData& requestData, const IDBKeyData& keyData, const ThreadSafeDataBuffer& valueData, IndexedDB::ObjectStoreOverwriteMode overwriteMode)
167 {
168     LOG(IndexedDB, "UniqueIDBDatabaseTransaction::putOrAdd");
169
170     ASSERT(!isReadOnly());
171     ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier());
172
173     RefPtr<UniqueIDBDatabaseTransaction> self(this);
174     m_databaseConnection->database().putOrAdd(requestData, keyData, valueData, overwriteMode, [this, self, requestData](const IDBError& error, const IDBKeyData& key) {
175         LOG(IndexedDB, "UniqueIDBDatabaseTransaction::putOrAdd (callback)");
176
177         if (error.isNull())
178             m_databaseConnection->connectionToClient().didPutOrAdd(IDBResultData::putOrAddSuccess(requestData.requestIdentifier(), key));
179         else
180             m_databaseConnection->connectionToClient().didPutOrAdd(IDBResultData::error(requestData.requestIdentifier(), error));
181     });
182 }
183
184 void UniqueIDBDatabaseTransaction::getRecord(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData)
185 {
186     LOG(IndexedDB, "UniqueIDBDatabaseTransaction::getRecord");
187
188     ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier());
189
190     RefPtr<UniqueIDBDatabaseTransaction> self(this);
191     m_databaseConnection->database().getRecord(requestData, keyRangeData, [this, self, requestData](const IDBError& error, const IDBGetResult& result) {
192         LOG(IndexedDB, "UniqueIDBDatabaseTransaction::getRecord (callback)");
193
194         if (error.isNull())
195             m_databaseConnection->connectionToClient().didGetRecord(IDBResultData::getRecordSuccess(requestData.requestIdentifier(), result));
196         else
197             m_databaseConnection->connectionToClient().didGetRecord(IDBResultData::error(requestData.requestIdentifier(), error));
198     });
199 }
200
201 void UniqueIDBDatabaseTransaction::getCount(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData)
202 {
203     LOG(IndexedDB, "UniqueIDBDatabaseTransaction::getCount");
204
205     ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier());
206
207     RefPtr<UniqueIDBDatabaseTransaction> self(this);
208     m_databaseConnection->database().getCount(requestData, keyRangeData, [this, self, requestData](const IDBError& error, uint64_t count) {
209         LOG(IndexedDB, "UniqueIDBDatabaseTransaction::getCount (callback)");
210
211         if (error.isNull())
212             m_databaseConnection->connectionToClient().didGetCount(IDBResultData::getCountSuccess(requestData.requestIdentifier(), count));
213         else
214             m_databaseConnection->connectionToClient().didGetCount(IDBResultData::error(requestData.requestIdentifier(), error));
215     });
216 }
217
218 void UniqueIDBDatabaseTransaction::deleteRecord(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData)
219 {
220     LOG(IndexedDB, "UniqueIDBDatabaseTransaction::deleteRecord");
221
222     ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier());
223
224     RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this);
225     m_databaseConnection->database().deleteRecord(requestData, keyRangeData, [this, protectedThis, requestData](const IDBError& error) {
226         LOG(IndexedDB, "UniqueIDBDatabaseTransaction::deleteRecord (callback)");
227
228         if (error.isNull())
229             m_databaseConnection->connectionToClient().didDeleteRecord(IDBResultData::deleteRecordSuccess(requestData.requestIdentifier()));
230         else
231             m_databaseConnection->connectionToClient().didDeleteRecord(IDBResultData::error(requestData.requestIdentifier(), error));
232     });
233 }
234
235 void UniqueIDBDatabaseTransaction::openCursor(const IDBRequestData& requestData, const IDBCursorInfo& info)
236 {
237     LOG(IndexedDB, "UniqueIDBDatabaseTransaction::openCursor");
238
239     ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier());
240
241     RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this);
242     m_databaseConnection->database().openCursor(requestData, info, [this, protectedThis, requestData](const IDBError& error, const IDBGetResult& result) {
243         LOG(IndexedDB, "UniqueIDBDatabaseTransaction::openCursor (callback)");
244
245         if (error.isNull())
246             m_databaseConnection->connectionToClient().didOpenCursor(IDBResultData::openCursorSuccess(requestData.requestIdentifier(), result));
247         else
248             m_databaseConnection->connectionToClient().didOpenCursor(IDBResultData::error(requestData.requestIdentifier(), error));
249     });
250 }
251
252 void UniqueIDBDatabaseTransaction::iterateCursor(const IDBRequestData& requestData, const IDBKeyData& key, unsigned long count)
253 {
254     LOG(IndexedDB, "UniqueIDBDatabaseTransaction::iterateCursor");
255
256     ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier());
257
258     RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this);
259     m_databaseConnection->database().iterateCursor(requestData, key, count, [this, protectedThis, requestData](const IDBError& error, const IDBGetResult& result) {
260         LOG(IndexedDB, "UniqueIDBDatabaseTransaction::openCursor (callback)");
261
262         if (error.isNull())
263             m_databaseConnection->connectionToClient().didIterateCursor(IDBResultData::iterateCursorSuccess(requestData.requestIdentifier(), result));
264         else
265             m_databaseConnection->connectionToClient().didIterateCursor(IDBResultData::error(requestData.requestIdentifier(), error));
266     });
267 }
268
269 const Vector<uint64_t>& UniqueIDBDatabaseTransaction::objectStoreIdentifiers()
270 {
271     if (!m_objectStoreIdentifiers.isEmpty())
272         return m_objectStoreIdentifiers;
273
274     auto& info = m_databaseConnection->database().info();
275     for (auto objectStoreName : info.objectStoreNames()) {
276         auto objectStoreInfo = info.infoForExistingObjectStore(objectStoreName);
277         ASSERT(objectStoreInfo);
278         if (!objectStoreInfo)
279             continue;
280
281         if (m_transactionInfo.objectStores().contains(objectStoreName))
282             m_objectStoreIdentifiers.append(objectStoreInfo->identifier());
283     }
284
285     return m_objectStoreIdentifiers;
286 }
287
288 void UniqueIDBDatabaseTransaction::didActivateInBackingStore(const IDBError& error)
289 {
290     LOG(IndexedDB, "UniqueIDBDatabaseTransaction::didActivateInBackingStore");
291
292     m_databaseConnection->connectionToClient().didStartTransaction(m_transactionInfo.identifier(), error);
293 }
294
295 } // namespace IDBServer
296 } // namespace WebCore
297
298 #endif // ENABLE(INDEXED_DATABASE)