Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / server / IDBServer.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 "IDBServer.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "IDBRequestData.h"
32 #include "IDBResultData.h"
33 #include "Logging.h"
34 #include "MemoryIDBBackingStore.h"
35 #include <wtf/Locker.h>
36 #include <wtf/MainThread.h>
37
38 namespace WebCore {
39 namespace IDBServer {
40
41 Ref<IDBServer> IDBServer::create()
42 {
43     return adoptRef(*new IDBServer());
44 }
45
46 IDBServer::IDBServer()
47 {
48     Locker<Lock> locker(m_databaseThreadCreationLock);
49     m_threadID = createThread(IDBServer::databaseThreadEntry, this, "IndexedDatabase Server");
50 }
51
52 void IDBServer::registerConnection(IDBConnectionToClient& connection)
53 {
54     ASSERT(!m_connectionMap.contains(connection.identifier()));
55     m_connectionMap.set(connection.identifier(), &connection);
56 }
57
58 void IDBServer::unregisterConnection(IDBConnectionToClient& connection)
59 {
60     ASSERT(m_connectionMap.contains(connection.identifier()));
61     ASSERT(m_connectionMap.get(connection.identifier()) == &connection);
62
63     m_connectionMap.remove(connection.identifier());
64 }
65
66 void IDBServer::registerTransaction(UniqueIDBDatabaseTransaction& transaction)
67 {
68     ASSERT(!m_transactions.contains(transaction.info().identifier()));
69     m_transactions.set(transaction.info().identifier(), &transaction);
70 }
71
72 void IDBServer::unregisterTransaction(UniqueIDBDatabaseTransaction& transaction)
73 {
74     ASSERT(m_transactions.contains(transaction.info().identifier()));
75     ASSERT(m_transactions.get(transaction.info().identifier()) == &transaction);
76
77     m_transactions.remove(transaction.info().identifier());
78 }
79
80 void IDBServer::registerDatabaseConnection(UniqueIDBDatabaseConnection& connection)
81 {
82     ASSERT(!m_databaseConnections.contains(connection.identifier()));
83     m_databaseConnections.set(connection.identifier(), &connection);
84 }
85
86 void IDBServer::unregisterDatabaseConnection(UniqueIDBDatabaseConnection& connection)
87 {
88     ASSERT(m_databaseConnections.contains(connection.identifier()));
89     m_databaseConnections.remove(connection.identifier());
90 }
91
92 UniqueIDBDatabase& IDBServer::getOrCreateUniqueIDBDatabase(const IDBDatabaseIdentifier& identifier)
93 {
94     auto uniqueIDBDatabase = m_uniqueIDBDatabaseMap.add(identifier, nullptr);
95     if (uniqueIDBDatabase.isNewEntry)
96         uniqueIDBDatabase.iterator->value = UniqueIDBDatabase::create(*this, identifier);
97
98     return *uniqueIDBDatabase.iterator->value;
99 }
100
101 std::unique_ptr<IDBBackingStore> IDBServer::createBackingStore(const IDBDatabaseIdentifier& identifier)
102 {
103     ASSERT(!isMainThread());
104
105     // FIXME: For now we only have the in-memory backing store, which we'll continue to use for private browsing.
106     // Once it's time for persistent backing stores this is where we'll calculate the correct path on disk
107     // and create it.
108
109     return MemoryIDBBackingStore::create(identifier);
110 }
111
112 void IDBServer::openDatabase(const IDBRequestData& requestData)
113 {
114     LOG(IndexedDB, "IDBServer::openDatabase");
115
116     auto& uniqueIDBDatabase = getOrCreateUniqueIDBDatabase(requestData.databaseIdentifier());
117
118     auto connection = m_connectionMap.get(requestData.requestIdentifier().connectionIdentifier());
119     if (!connection) {
120         // If the connection back to the client is gone, there's no way to open the database as
121         // well as no way to message back failure.
122         return;
123     }
124
125     uniqueIDBDatabase.openDatabaseConnection(*connection, requestData);
126 }
127
128 void IDBServer::deleteDatabase(const IDBRequestData& requestData)
129 {
130     LOG(IndexedDB, "IDBServer::deleteDatabase - %s", requestData.databaseIdentifier().debugString().utf8().data());
131     
132     auto connection = m_connectionMap.get(requestData.requestIdentifier().connectionIdentifier());
133     if (!connection) {
134         // If the connection back to the client is gone, there's no way to delete the database as
135         // well as no way to message back failure.
136         return;
137     }
138
139     auto* database = m_uniqueIDBDatabaseMap.get(requestData.databaseIdentifier());
140     if (!database) {
141         connection->didDeleteDatabase(IDBResultData::deleteDatabaseSuccess(requestData.requestIdentifier(), IDBDatabaseInfo(requestData.databaseIdentifier().databaseName(), 0)));
142         return;
143     }
144
145     database->handleDelete(*connection, requestData);
146 }
147
148 void IDBServer::deleteUniqueIDBDatabase(UniqueIDBDatabase& database)
149 {
150     LOG(IndexedDB, "IDBServer::deleteUniqueIDBDatabase");
151
152     auto deletedDatabase = m_uniqueIDBDatabaseMap.take(database.identifier());
153     ASSERT_UNUSED(deletedDatabase, deletedDatabase.get() == &database);
154 }
155
156 void IDBServer::abortTransaction(const IDBResourceIdentifier& transactionIdentifier)
157 {
158     LOG(IndexedDB, "IDBServer::abortTransaction");
159
160     auto transaction = m_transactions.get(transactionIdentifier);
161     if (!transaction) {
162         // If there is no transaction there is nothing to abort.
163         // We also have no access to a connection over which to message failure-to-abort.
164         return;
165     }
166
167     transaction->abort();
168 }
169
170 void IDBServer::createObjectStore(const IDBRequestData& requestData, const IDBObjectStoreInfo& info)
171 {
172     LOG(IndexedDB, "IDBServer::createObjectStore");
173
174     auto transaction = m_transactions.get(requestData.transactionIdentifier());
175     if (!transaction)
176         return;
177
178     ASSERT(transaction->isVersionChange());
179     transaction->createObjectStore(requestData, info);
180 }
181
182 void IDBServer::deleteObjectStore(const IDBRequestData& requestData, const String& objectStoreName)
183 {
184     LOG(IndexedDB, "IDBServer::deleteObjectStore");
185
186     auto transaction = m_transactions.get(requestData.transactionIdentifier());
187     if (!transaction)
188         return;
189
190     ASSERT(transaction->isVersionChange());
191     transaction->deleteObjectStore(requestData, objectStoreName);
192 }
193
194 void IDBServer::clearObjectStore(const IDBRequestData& requestData, uint64_t objectStoreIdentifier)
195 {
196     LOG(IndexedDB, "IDBServer::clearObjectStore");
197
198     auto transaction = m_transactions.get(requestData.transactionIdentifier());
199     if (!transaction)
200         return;
201
202     transaction->clearObjectStore(requestData, objectStoreIdentifier);
203 }
204
205 void IDBServer::createIndex(const IDBRequestData& requestData, const IDBIndexInfo& info)
206 {
207     LOG(IndexedDB, "IDBServer::createIndex");
208
209     auto transaction = m_transactions.get(requestData.transactionIdentifier());
210     if (!transaction)
211         return;
212
213     ASSERT(transaction->isVersionChange());
214     transaction->createIndex(requestData, info);
215 }
216
217 void IDBServer::deleteIndex(const IDBRequestData& requestData, uint64_t objectStoreIdentifier, const String& indexName)
218 {
219     LOG(IndexedDB, "IDBServer::deleteIndex");
220
221     auto transaction = m_transactions.get(requestData.transactionIdentifier());
222     if (!transaction)
223         return;
224
225     ASSERT(transaction->isVersionChange());
226     transaction->deleteIndex(requestData, objectStoreIdentifier, indexName);
227 }
228
229 void IDBServer::putOrAdd(const IDBRequestData& requestData, const IDBKeyData& keyData, const ThreadSafeDataBuffer& valueData, IndexedDB::ObjectStoreOverwriteMode overwriteMode)
230 {
231     LOG(IndexedDB, "IDBServer::putOrAdd");
232
233     auto transaction = m_transactions.get(requestData.transactionIdentifier());
234     if (!transaction)
235         return;
236
237     transaction->putOrAdd(requestData, keyData, valueData, overwriteMode);
238 }
239
240 void IDBServer::getRecord(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData)
241 {
242     LOG(IndexedDB, "IDBServer::getRecord");
243
244     auto transaction = m_transactions.get(requestData.transactionIdentifier());
245     if (!transaction)
246         return;
247
248     transaction->getRecord(requestData, keyRangeData);
249 }
250
251 void IDBServer::getCount(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData)
252 {
253     LOG(IndexedDB, "IDBServer::getCount");
254
255     auto transaction = m_transactions.get(requestData.transactionIdentifier());
256     if (!transaction)
257         return;
258
259     transaction->getCount(requestData, keyRangeData);
260 }
261
262 void IDBServer::deleteRecord(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData)
263 {
264     LOG(IndexedDB, "IDBServer::deleteRecord");
265
266     auto transaction = m_transactions.get(requestData.transactionIdentifier());
267     if (!transaction)
268         return;
269
270     transaction->deleteRecord(requestData, keyRangeData);
271 }
272
273 void IDBServer::openCursor(const IDBRequestData& requestData, const IDBCursorInfo& info)
274 {
275     LOG(IndexedDB, "IDBServer::openCursor");
276
277     auto transaction = m_transactions.get(requestData.transactionIdentifier());
278     if (!transaction)
279         return;
280
281     transaction->openCursor(requestData, info);
282 }
283
284 void IDBServer::iterateCursor(const IDBRequestData& requestData, const IDBKeyData& key, unsigned long count)
285 {
286     LOG(IndexedDB, "IDBServer::iterateCursor");
287
288     auto transaction = m_transactions.get(requestData.transactionIdentifier());
289     if (!transaction)
290         return;
291
292     transaction->iterateCursor(requestData, key, count);
293 }
294
295 void IDBServer::establishTransaction(uint64_t databaseConnectionIdentifier, const IDBTransactionInfo& info)
296 {
297     LOG(IndexedDB, "IDBServer::establishTransaction");
298
299     auto databaseConnection = m_databaseConnections.get(databaseConnectionIdentifier);
300     if (!databaseConnection)
301         return;
302
303     databaseConnection->establishTransaction(info);
304 }
305
306 void IDBServer::commitTransaction(const IDBResourceIdentifier& transactionIdentifier)
307 {
308     LOG(IndexedDB, "IDBServer::commitTransaction");
309
310     auto transaction = m_transactions.get(transactionIdentifier);
311     if (!transaction) {
312         // If there is no transaction there is nothing to commit.
313         // We also have no access to a connection over which to message failure-to-commit.
314         return;
315     }
316
317     transaction->commit();
318 }
319
320 void IDBServer::didFinishHandlingVersionChangeTransaction(const IDBResourceIdentifier& transactionIdentifier)
321 {
322     LOG(IndexedDB, "IDBServer::didFinishHandlingVersionChangeTransaction");
323
324     auto transaction = m_transactions.get(transactionIdentifier);
325     if (!transaction)
326         return;
327
328     transaction->didFinishHandlingVersionChange();
329 }
330
331 void IDBServer::databaseConnectionClosed(uint64_t databaseConnectionIdentifier)
332 {
333     LOG(IndexedDB, "IDBServer::databaseConnectionClosed");
334
335     auto databaseConnection = m_databaseConnections.get(databaseConnectionIdentifier);
336     if (!databaseConnection)
337         return;
338
339     databaseConnection->connectionClosedFromClient();
340 }
341
342 void IDBServer::didFireVersionChangeEvent(uint64_t databaseConnectionIdentifier, const IDBResourceIdentifier& requestIdentifier)
343 {
344     LOG(IndexedDB, "IDBServer::didFireVersionChangeEvent");
345
346     if (auto databaseConnection = m_databaseConnections.get(databaseConnectionIdentifier))
347         databaseConnection->didFireVersionChangeEvent(requestIdentifier);
348 }
349
350 void IDBServer::postDatabaseTask(std::unique_ptr<CrossThreadTask>&& task)
351 {
352     ASSERT(isMainThread());
353     m_databaseQueue.append(WTFMove(task));
354 }
355
356 void IDBServer::postDatabaseTaskReply(std::unique_ptr<CrossThreadTask>&& task)
357 {
358     ASSERT(!isMainThread());
359     m_databaseReplyQueue.append(WTFMove(task));
360
361
362     Locker<Lock> locker(m_mainThreadReplyLock);
363     if (m_mainThreadReplyScheduled)
364         return;
365
366     m_mainThreadReplyScheduled = true;
367     callOnMainThread([this] {
368         handleTaskRepliesOnMainThread();
369     });
370 }
371
372 void IDBServer::databaseThreadEntry(void* threadData)
373 {
374     ASSERT(threadData);
375     IDBServer* server = reinterpret_cast<IDBServer*>(threadData);
376     server->databaseRunLoop();
377 }
378
379 void IDBServer::databaseRunLoop()
380 {
381     ASSERT(!isMainThread());
382     {
383         Locker<Lock> locker(m_databaseThreadCreationLock);
384     }
385
386     while (auto task = m_databaseQueue.waitForMessage())
387         task->performTask();
388 }
389
390 void IDBServer::handleTaskRepliesOnMainThread()
391 {
392     {
393         Locker<Lock> locker(m_mainThreadReplyLock);
394         m_mainThreadReplyScheduled = false;
395     }
396
397     while (auto task = m_databaseReplyQueue.tryGetMessage())
398         task->performTask();
399 }
400
401 } // namespace IDBServer
402 } // namespace WebCore
403
404 #endif // ENABLE(INDEXED_DATABASE)