IDB: Implement cross-thread and IPC plumbing for 'get' support
[WebKit-https.git] / Source / WebKit2 / WebProcess / Databases / IndexedDB / WebIDBServerConnection.cpp
1 /*
2  * Copyright (C) 2013 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. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26
27 #include "config.h"
28 #include "WebIDBServerConnection.h"
29
30 #if ENABLE(INDEXED_DATABASE) && ENABLE(DATABASE_PROCESS)
31
32 #include "AsyncRequest.h"
33 #include "DataReference.h"
34 #include "DatabaseProcessIDBConnectionMessages.h"
35 #include "DatabaseToWebProcessConnectionMessages.h"
36 #include "Logging.h"
37 #include "SecurityOriginData.h"
38 #include "WebProcess.h"
39 #include "WebToDatabaseProcessConnection.h"
40 #include <WebCore/IDBDatabaseMetadata.h>
41 #include <WebCore/IDBKeyRangeData.h>
42 #include <WebCore/SecurityOrigin.h>
43
44 using namespace WebCore;
45
46 namespace WebKit {
47
48 static uint64_t generateServerConnectionIdentifier()
49 {
50     ASSERT(isMainThread());
51     static uint64_t identifier = 0;
52     return ++identifier;
53 }
54
55 PassRefPtr<WebIDBServerConnection> WebIDBServerConnection::create(const String& databaseName, const SecurityOrigin& openingOrigin, const SecurityOrigin& mainFrameOrigin)
56 {
57     RefPtr<WebIDBServerConnection> result = adoptRef(new WebIDBServerConnection(databaseName, openingOrigin, mainFrameOrigin));
58     WebProcess::shared().webToDatabaseProcessConnection()->registerWebIDBServerConnection(*result);
59     return result.release();
60 }
61
62 WebIDBServerConnection::WebIDBServerConnection(const String& databaseName, const SecurityOrigin& openingOrigin, const SecurityOrigin& mainFrameOrigin)
63     : m_serverConnectionIdentifier(generateServerConnectionIdentifier())
64     , m_databaseName(databaseName)
65     , m_openingOrigin(*openingOrigin.isolatedCopy())
66     , m_mainFrameOrigin(*mainFrameOrigin.isolatedCopy())
67 {
68     send(Messages::DatabaseToWebProcessConnection::EstablishIDBConnection(m_serverConnectionIdentifier));
69     send(Messages::DatabaseProcessIDBConnection::EstablishConnection(databaseName, SecurityOriginData::fromSecurityOrigin(&openingOrigin), SecurityOriginData::fromSecurityOrigin(&mainFrameOrigin)));
70 }
71
72 WebIDBServerConnection::~WebIDBServerConnection()
73 {
74     WebProcess::shared().webToDatabaseProcessConnection()->removeWebIDBServerConnection(*this);
75
76     for (const auto& it : m_serverRequests)
77         it.value->requestAborted();
78 }
79
80 bool WebIDBServerConnection::isClosed()
81 {
82     // FIXME: Return real value here.
83     return true;
84 }
85
86 void WebIDBServerConnection::deleteDatabase(const String& name, BoolCallbackFunction successCallback)
87 {
88 }
89
90 void WebIDBServerConnection::getOrEstablishIDBDatabaseMetadata(GetIDBDatabaseMetadataFunction completionCallback)
91 {
92     RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<const IDBDatabaseMetadata&, bool>::create(completionCallback);
93
94     serverRequest->setAbortHandler([completionCallback]() {
95         IDBDatabaseMetadata metadata;
96         completionCallback(metadata, false);
97     });
98
99     uint64_t requestID = serverRequest->requestID();
100     ASSERT(!m_serverRequests.contains(requestID));
101     m_serverRequests.add(requestID, serverRequest.release());
102
103     LOG(IDB, "WebProcess getOrEstablishIDBDatabaseMetadata request ID %llu", requestID);
104
105     send(Messages::DatabaseProcessIDBConnection::GetOrEstablishIDBDatabaseMetadata(requestID));
106 }
107
108 void WebIDBServerConnection::didGetOrEstablishIDBDatabaseMetadata(uint64_t requestID, bool success, const IDBDatabaseMetadata& metadata)
109 {
110     LOG(IDB, "WebProcess didGetOrEstablishIDBDatabaseMetadata request ID %llu", requestID);
111
112     RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
113
114     if (!serverRequest)
115         return;
116
117     serverRequest->completeRequest(metadata, success);
118 }
119
120 void WebIDBServerConnection::close()
121 {
122 }
123
124 void WebIDBServerConnection::openTransaction(int64_t transactionID, const HashSet<int64_t>& objectStoreIDs, IndexedDB::TransactionMode mode, BoolCallbackFunction successCallback)
125 {
126     RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<bool>::create(successCallback);
127
128     serverRequest->setAbortHandler([successCallback]() {
129         successCallback(false);
130     });
131
132     uint64_t requestID = serverRequest->requestID();
133     ASSERT(!m_serverRequests.contains(requestID));
134     m_serverRequests.add(requestID, serverRequest.release());
135
136     LOG(IDB, "WebProcess openTransaction ID %lli (request ID %llu)", transactionID, requestID);
137
138     Vector<int64_t> objectStoreIDVector;
139     copyToVector(objectStoreIDs, objectStoreIDVector);
140     send(Messages::DatabaseProcessIDBConnection::OpenTransaction(requestID, transactionID, objectStoreIDVector, static_cast<uint64_t>(mode)));
141 }
142
143 void WebIDBServerConnection::didOpenTransaction(uint64_t requestID, bool success)
144 {
145     LOG(IDB, "WebProcess didOpenTransaction request ID %llu", requestID);
146
147     RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
148
149     if (!serverRequest)
150         return;
151
152     serverRequest->completeRequest(success);
153 }
154
155 void WebIDBServerConnection::beginTransaction(int64_t transactionID, std::function<void()> completionCallback)
156 {
157     RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<>::create(completionCallback, completionCallback);
158
159     uint64_t requestID = serverRequest->requestID();
160     ASSERT(!m_serverRequests.contains(requestID));
161     m_serverRequests.add(requestID, serverRequest.release());
162
163     LOG(IDB, "WebProcess beginTransaction ID %lli (request ID %llu)", transactionID, requestID);
164
165     send(Messages::DatabaseProcessIDBConnection::BeginTransaction(requestID, transactionID));
166 }
167
168 void WebIDBServerConnection::didBeginTransaction(uint64_t requestID, bool)
169 {
170     LOG(IDB, "WebProcess didBeginTransaction request ID %llu", requestID);
171
172     RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
173
174     if (!serverRequest)
175         return;
176
177     serverRequest->completeRequest();
178 }
179
180 void WebIDBServerConnection::commitTransaction(int64_t transactionID, BoolCallbackFunction successCallback)
181 {
182     RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<bool>::create(successCallback);
183
184     serverRequest->setAbortHandler([successCallback]() {
185         successCallback(false);
186     });
187
188     uint64_t requestID = serverRequest->requestID();
189     ASSERT(!m_serverRequests.contains(requestID));
190     m_serverRequests.add(requestID, serverRequest.release());
191
192     LOG(IDB, "WebProcess commitTransaction ID %lli (request ID %llu)", transactionID, requestID);
193
194     send(Messages::DatabaseProcessIDBConnection::CommitTransaction(requestID, transactionID));
195 }
196
197 void WebIDBServerConnection::didCommitTransaction(uint64_t requestID, bool success)
198 {
199     LOG(IDB, "WebProcess didCommitTransaction request ID %llu", requestID);
200
201     RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
202
203     if (!serverRequest)
204         return;
205
206     serverRequest->completeRequest(success);
207 }
208
209 void WebIDBServerConnection::resetTransaction(int64_t transactionID, std::function<void()> completionCallback)
210 {
211     RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<>::create(completionCallback, completionCallback);
212
213     uint64_t requestID = serverRequest->requestID();
214     ASSERT(!m_serverRequests.contains(requestID));
215     m_serverRequests.add(requestID, serverRequest.release());
216
217     LOG(IDB, "WebProcess resetTransaction ID %lli (request ID %llu)", transactionID, requestID);
218
219     send(Messages::DatabaseProcessIDBConnection::ResetTransaction(requestID, transactionID));
220 }
221
222 void WebIDBServerConnection::didResetTransaction(uint64_t requestID, bool)
223 {
224     LOG(IDB, "WebProcess didResetTransaction request ID %llu", requestID);
225
226     RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
227
228     if (!serverRequest)
229         return;
230
231     serverRequest->completeRequest();
232 }
233
234 void WebIDBServerConnection::rollbackTransaction(int64_t transactionID, std::function<void()> completionCallback)
235 {
236     RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<>::create(completionCallback, completionCallback);
237
238     uint64_t requestID = serverRequest->requestID();
239     ASSERT(!m_serverRequests.contains(requestID));
240     m_serverRequests.add(requestID, serverRequest.release());
241
242     LOG(IDB, "WebProcess rollbackTransaction ID %lli (request ID %llu)", transactionID, requestID);
243
244     send(Messages::DatabaseProcessIDBConnection::RollbackTransaction(requestID, transactionID));
245 }
246
247 void WebIDBServerConnection::didRollbackTransaction(uint64_t requestID, bool)
248 {
249     LOG(IDB, "WebProcess didRollbackTransaction request ID %llu", requestID);
250
251     RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
252
253     if (!serverRequest)
254         return;
255
256     serverRequest->completeRequest();
257 }
258
259 void WebIDBServerConnection::setIndexKeys(int64_t transactionID, int64_t databaseID, int64_t objectStoreID, const IDBObjectStoreMetadata&, IDBKey& primaryKey, const Vector<int64_t>& indexIDs, const Vector<Vector<RefPtr<IDBKey>>>& indexKeys, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback)
260 {
261 }
262
263 void WebIDBServerConnection::createObjectStore(IDBTransactionBackend& transaction, const CreateObjectStoreOperation& operation, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback)
264 {
265     RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<PassRefPtr<IDBDatabaseError>>::create(completionCallback);
266
267     String objectStoreName = operation.objectStoreMetadata().name;
268     serverRequest->setAbortHandler([objectStoreName, completionCallback]() {
269         completionCallback(IDBDatabaseError::create(IDBDatabaseException::UnknownError, String::format("Unknown error occured creating object store '%s'", objectStoreName.utf8().data())));
270     });
271
272     uint64_t requestID = serverRequest->requestID();
273     ASSERT(!m_serverRequests.contains(requestID));
274     m_serverRequests.add(requestID, serverRequest.release());
275
276     LOG(IDB, "WebProcess createObjectStore '%s' in transaction ID %llu (request ID %llu)", operation.objectStoreMetadata().name.utf8().data(), transaction.id(), requestID);
277
278     send(Messages::DatabaseProcessIDBConnection::CreateObjectStore(requestID, transaction.id(), operation.objectStoreMetadata()));
279 }
280
281 void WebIDBServerConnection::didCreateObjectStore(uint64_t requestID, bool success)
282 {
283     LOG(IDB, "WebProcess didCreateObjectStore request ID %llu", requestID);
284
285     RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
286
287     if (!serverRequest)
288         return;
289
290     serverRequest->completeRequest(success ? nullptr : IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured creating object store"));
291 }
292
293 void WebIDBServerConnection::createIndex(IDBTransactionBackend&, const CreateIndexOperation&, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback)
294 {
295 }
296
297 void WebIDBServerConnection::deleteIndex(IDBTransactionBackend&, const DeleteIndexOperation&, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback)
298 {
299 }
300
301 void WebIDBServerConnection::get(IDBTransactionBackend& transaction, const GetOperation& operation, std::function<void(const IDBGetResult&, PassRefPtr<IDBDatabaseError>)> completionCallback)
302 {
303     RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<const IDBGetResult&, PassRefPtr<IDBDatabaseError>>::create(completionCallback);
304
305     serverRequest->setAbortHandler([completionCallback]() {
306         completionCallback(IDBGetResult(), IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured getting record"));
307     });
308
309     uint64_t requestID = serverRequest->requestID();
310     ASSERT(!m_serverRequests.contains(requestID));
311     m_serverRequests.add(requestID, serverRequest.release());
312
313     LOG(IDB, "WebProcess get request ID %llu", requestID);
314
315     ASSERT(operation.keyRange());
316
317     send(Messages::DatabaseProcessIDBConnection::GetRecord(requestID, transaction.id(), operation.objectStoreID(), operation.indexID(), operation.keyRange(), static_cast<int64_t>(operation.cursorType())));
318 }
319
320 void WebIDBServerConnection::put(IDBTransactionBackend& transaction, const PutOperation& operation, std::function<void(PassRefPtr<IDBKey>, PassRefPtr<IDBDatabaseError>)> completionCallback)
321 {
322     RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<PassRefPtr<IDBKey>, PassRefPtr<IDBDatabaseError>>::create(completionCallback);
323
324     serverRequest->setAbortHandler([completionCallback]() {
325         completionCallback(nullptr, IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured putting record"));
326     });
327
328     uint64_t requestID = serverRequest->requestID();
329     ASSERT(!m_serverRequests.contains(requestID));
330     m_serverRequests.add(requestID, serverRequest.release());
331
332     LOG(IDB, "WebProcess put request ID %llu", requestID);
333
334     ASSERT(operation.key());
335     ASSERT(operation.value());
336
337     IPC::DataReference value(reinterpret_cast<const uint8_t*>(operation.value()->data()), operation.value()->size());
338
339     Vector<Vector<IDBKeyData>> indexKeys;
340     for (auto keys : operation.indexKeys()) {
341         indexKeys.append(Vector<IDBKeyData>());
342         for (auto key : keys)
343             indexKeys.last().append(IDBKeyData(key.get()));
344     }
345
346     send(Messages::DatabaseProcessIDBConnection::PutRecord(requestID, transaction.id(), operation.objectStore().id, IDBKeyData(operation.key()), value, operation.putMode(), operation.indexIDs(), indexKeys));
347 }
348
349 void WebIDBServerConnection::didPutRecord(uint64_t requestID, const WebCore::IDBKeyData& resultKey, uint32_t errorCode, const String& errorMessage)
350 {
351     LOG(IDB, "WebProcess didPutRecord request ID %llu (error - %s)", requestID, errorMessage.utf8().data());
352
353     RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
354
355     if (!serverRequest)
356         return;
357
358     serverRequest->completeRequest(resultKey.isNull ? nullptr : resultKey.maybeCreateIDBKey(), errorCode ? IDBDatabaseError::create(errorCode, errorMessage) : nullptr);
359 }
360
361 void WebIDBServerConnection::didGetRecord(uint64_t requestID, const WebCore::IDBGetResult& getResult, uint32_t errorCode, const String& errorMessage)
362 {
363     LOG(IDB, "WebProcess didGetRecord request ID %llu (error - %s)", requestID, errorMessage.utf8().data());
364
365     RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
366
367     if (!serverRequest)
368         return;
369
370     serverRequest->completeRequest(getResult, errorCode ? IDBDatabaseError::create(errorCode, errorMessage) : nullptr);
371 }
372
373 void WebIDBServerConnection::openCursor(IDBTransactionBackend&, const OpenCursorOperation&, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback)
374 {
375 }
376
377 void WebIDBServerConnection::count(IDBTransactionBackend&, const CountOperation&, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback)
378 {
379 }
380
381 void WebIDBServerConnection::deleteRange(IDBTransactionBackend&, const DeleteRangeOperation&, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback)
382 {
383 }
384
385 void WebIDBServerConnection::clearObjectStore(IDBTransactionBackend&, const ClearObjectStoreOperation&, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback)
386 {
387 }
388
389 void WebIDBServerConnection::deleteObjectStore(IDBTransactionBackend&, const DeleteObjectStoreOperation& operation, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback)
390 {
391     RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<PassRefPtr<IDBDatabaseError>>::create(completionCallback);
392
393     serverRequest->setAbortHandler([completionCallback]() {
394         completionCallback(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured deleting object store"));
395     });
396
397     uint64_t requestID = serverRequest->requestID();
398     ASSERT(!m_serverRequests.contains(requestID));
399     m_serverRequests.add(requestID, serverRequest.release());
400
401     LOG(IDB, "WebProcess deleteObjectStore request ID %llu", requestID);
402
403     send(Messages::DatabaseProcessIDBConnection::DeleteObjectStore(requestID, operation.transaction()->id(), operation.objectStoreMetadata().id));
404 }
405
406 void WebIDBServerConnection::didDeleteObjectStore(uint64_t requestID, bool success)
407 {
408     LOG(IDB, "WebProcess didDeleteObjectStore request ID %llu", requestID);
409
410     RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
411
412     if (!serverRequest)
413         return;
414
415     serverRequest->completeRequest(success ? nullptr : IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured deleting object store"));
416 }
417
418 void WebIDBServerConnection::changeDatabaseVersion(IDBTransactionBackend&, const IDBDatabaseBackend::VersionChangeOperation& operation, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback)
419 {
420     RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<PassRefPtr<IDBDatabaseError>>::create(completionCallback);
421
422     serverRequest->setAbortHandler([completionCallback]() {
423         completionCallback(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured changing database version"));
424     });
425
426     uint64_t requestID = serverRequest->requestID();
427     ASSERT(!m_serverRequests.contains(requestID));
428     m_serverRequests.add(requestID, serverRequest.release());
429
430     LOG(IDB, "WebProcess changeDatabaseVersion request ID %llu", requestID);
431
432     send(Messages::DatabaseProcessIDBConnection::ChangeDatabaseVersion(requestID, operation.transaction()->id(), static_cast<uint64_t>(operation.version())));
433 }
434
435 void WebIDBServerConnection::didChangeDatabaseVersion(uint64_t requestID, bool success)
436 {
437     LOG(IDB, "WebProcess didChangeDatabaseVersion request ID %llu", requestID);
438
439     RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
440
441     if (!serverRequest)
442         return;
443
444     serverRequest->completeRequest(success ? nullptr : IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured changing database version"));
445 }
446
447 void WebIDBServerConnection::cursorAdvance(IDBCursorBackend&, const CursorAdvanceOperation&, std::function<void()> completionCallback)
448 {
449 }
450
451 void WebIDBServerConnection::cursorIterate(IDBCursorBackend&, const CursorIterationOperation&, std::function<void()> completionCallback)
452 {
453 }
454
455 void WebIDBServerConnection::cursorPrefetchIteration(IDBCursorBackend&, const CursorPrefetchIterationOperation&, std::function<void()> completionCallback)
456 {
457 }
458
459 void WebIDBServerConnection::cursorPrefetchReset(IDBCursorBackend&, int usedPrefetches)
460 {
461 }
462
463 IPC::Connection* WebIDBServerConnection::messageSenderConnection()
464 {
465     return WebProcess::shared().webToDatabaseProcessConnection()->connection();
466 }
467
468 } // namespace WebKit
469
470 #endif // ENABLE(INDEXED_DATABASE) && ENABLE(DATABASE_PROCESS)
471