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 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
44using namespace WebCore;
45
46namespace WebKit {
47
48static uint64_t generateServerConnectionIdentifier()
49{
50    ASSERT(RunLoop::isMain());
51    static uint64_t identifier = 0;
52    return ++identifier;
53}
54
55PassRefPtr<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
62WebIDBServerConnection::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
72WebIDBServerConnection::~WebIDBServerConnection()
73{
74    WebProcess::shared().webToDatabaseProcessConnection()->removeWebIDBServerConnection(*this);
75
76    for (const auto& it : m_serverRequests)
77        it.value->requestAborted();
78}
79
80bool WebIDBServerConnection::isClosed()
81{
82    // FIXME: Return real value here.
83    return true;
84}
85
86void WebIDBServerConnection::deleteDatabase(const String& name, BoolCallbackFunction successCallback)
87{
88    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<bool>::create(successCallback);
89
90    serverRequest->setAbortHandler([successCallback]() {
91        successCallback(false);
92    });
93
94    uint64_t requestID = serverRequest->requestID();
95    ASSERT(!m_serverRequests.contains(requestID));
96    m_serverRequests.add(requestID, serverRequest.release());
97
98    LOG(IDB, "WebProcess deleteDatabase request ID %llu", requestID);
99
100    send(Messages::DatabaseProcessIDBConnection::DeleteDatabase(requestID, name));
101}
102
103void WebIDBServerConnection::didDeleteDatabase(uint64_t requestID, bool success)
104{
105    LOG(IDB, "WebProcess didDeleteDatabase request ID %llu", requestID);
106
107    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
108
109    if (!serverRequest)
110        return;
111
112    serverRequest->completeRequest(success);
113}
114
115void WebIDBServerConnection::getOrEstablishIDBDatabaseMetadata(GetIDBDatabaseMetadataFunction completionCallback)
116{
117    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<const IDBDatabaseMetadata&, bool>::create(completionCallback);
118
119    serverRequest->setAbortHandler([completionCallback]() {
120        IDBDatabaseMetadata metadata;
121        completionCallback(metadata, false);
122    });
123
124    uint64_t requestID = serverRequest->requestID();
125    ASSERT(!m_serverRequests.contains(requestID));
126    m_serverRequests.add(requestID, serverRequest.release());
127
128    LOG(IDB, "WebProcess getOrEstablishIDBDatabaseMetadata request ID %llu", requestID);
129
130    send(Messages::DatabaseProcessIDBConnection::GetOrEstablishIDBDatabaseMetadata(requestID));
131}
132
133void WebIDBServerConnection::didGetOrEstablishIDBDatabaseMetadata(uint64_t requestID, bool success, const IDBDatabaseMetadata& metadata)
134{
135    LOG(IDB, "WebProcess didGetOrEstablishIDBDatabaseMetadata request ID %llu", requestID);
136
137    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
138
139    if (!serverRequest)
140        return;
141
142    serverRequest->completeRequest(metadata, success);
143}
144
145void WebIDBServerConnection::close()
146{
147    LOG(IDB, "WebProcess close");
148
149    RefPtr<WebIDBServerConnection> protector(this);
150
151    for (auto& request : m_serverRequests)
152        request.value->requestAborted();
153
154    m_serverRequests.clear();
155
156    send(Messages::DatabaseProcessIDBConnection::Close());
157}
158
159void WebIDBServerConnection::openTransaction(int64_t transactionID, const HashSet<int64_t>& objectStoreIDs, IndexedDB::TransactionMode mode, BoolCallbackFunction successCallback)
160{
161    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<bool>::create(successCallback);
162
163    serverRequest->setAbortHandler([successCallback]() {
164        successCallback(false);
165    });
166
167    uint64_t requestID = serverRequest->requestID();
168    ASSERT(!m_serverRequests.contains(requestID));
169    m_serverRequests.add(requestID, serverRequest.release());
170
171    LOG(IDB, "WebProcess openTransaction ID %lli (request ID %llu)", transactionID, requestID);
172
173    Vector<int64_t> objectStoreIDVector;
174    copyToVector(objectStoreIDs, objectStoreIDVector);
175    send(Messages::DatabaseProcessIDBConnection::OpenTransaction(requestID, transactionID, objectStoreIDVector, static_cast<uint64_t>(mode)));
176}
177
178void WebIDBServerConnection::didOpenTransaction(uint64_t requestID, bool success)
179{
180    LOG(IDB, "WebProcess didOpenTransaction request ID %llu", requestID);
181
182    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
183
184    if (!serverRequest)
185        return;
186
187    serverRequest->completeRequest(success);
188}
189
190void WebIDBServerConnection::beginTransaction(int64_t transactionID, std::function<void()> completionCallback)
191{
192    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<>::create(completionCallback, completionCallback);
193
194    uint64_t requestID = serverRequest->requestID();
195    ASSERT(!m_serverRequests.contains(requestID));
196    m_serverRequests.add(requestID, serverRequest.release());
197
198    LOG(IDB, "WebProcess beginTransaction ID %lli (request ID %llu)", transactionID, requestID);
199
200    send(Messages::DatabaseProcessIDBConnection::BeginTransaction(requestID, transactionID));
201}
202
203void WebIDBServerConnection::didBeginTransaction(uint64_t requestID, bool)
204{
205    LOG(IDB, "WebProcess didBeginTransaction request ID %llu", requestID);
206
207    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
208
209    if (!serverRequest)
210        return;
211
212    serverRequest->completeRequest();
213}
214
215void WebIDBServerConnection::commitTransaction(int64_t transactionID, BoolCallbackFunction successCallback)
216{
217    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<bool>::create(successCallback);
218
219    serverRequest->setAbortHandler([successCallback]() {
220        successCallback(false);
221    });
222
223    uint64_t requestID = serverRequest->requestID();
224    ASSERT(!m_serverRequests.contains(requestID));
225    m_serverRequests.add(requestID, serverRequest.release());
226
227    LOG(IDB, "WebProcess commitTransaction ID %lli (request ID %llu)", transactionID, requestID);
228
229    send(Messages::DatabaseProcessIDBConnection::CommitTransaction(requestID, transactionID));
230}
231
232void WebIDBServerConnection::didCommitTransaction(uint64_t requestID, bool success)
233{
234    LOG(IDB, "WebProcess didCommitTransaction request ID %llu", requestID);
235
236    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
237
238    if (!serverRequest)
239        return;
240
241    serverRequest->completeRequest(success);
242}
243
244void WebIDBServerConnection::resetTransaction(int64_t transactionID, std::function<void()> completionCallback)
245{
246    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<>::create(completionCallback, completionCallback);
247
248    uint64_t requestID = serverRequest->requestID();
249    ASSERT(!m_serverRequests.contains(requestID));
250    m_serverRequests.add(requestID, serverRequest.release());
251
252    LOG(IDB, "WebProcess resetTransaction ID %lli (request ID %llu)", transactionID, requestID);
253
254    send(Messages::DatabaseProcessIDBConnection::ResetTransaction(requestID, transactionID));
255}
256
257void WebIDBServerConnection::didResetTransaction(uint64_t requestID, bool)
258{
259    LOG(IDB, "WebProcess didResetTransaction request ID %llu", requestID);
260
261    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
262
263    if (!serverRequest)
264        return;
265
266    serverRequest->completeRequest();
267}
268
269bool WebIDBServerConnection::resetTransactionSync(int64_t transactionID)
270{
271    bool success;
272    sendSync(Messages::DatabaseProcessIDBConnection::ResetTransactionSync(transactionID), Messages::DatabaseProcessIDBConnection::ResetTransactionSync::Reply(success));
273    return success;
274}
275
276void WebIDBServerConnection::rollbackTransaction(int64_t transactionID, std::function<void()> completionCallback)
277{
278    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<>::create(completionCallback, completionCallback);
279
280    uint64_t requestID = serverRequest->requestID();
281    ASSERT(!m_serverRequests.contains(requestID));
282    m_serverRequests.add(requestID, serverRequest.release());
283
284    LOG(IDB, "WebProcess rollbackTransaction ID %lli (request ID %llu)", transactionID, requestID);
285
286    send(Messages::DatabaseProcessIDBConnection::RollbackTransaction(requestID, transactionID));
287}
288
289void WebIDBServerConnection::didRollbackTransaction(uint64_t requestID, bool)
290{
291    LOG(IDB, "WebProcess didRollbackTransaction request ID %llu", requestID);
292
293    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
294
295    if (!serverRequest)
296        return;
297
298    serverRequest->completeRequest();
299}
300
301bool WebIDBServerConnection::rollbackTransactionSync(int64_t transactionID)
302{
303    bool success;
304    sendSync(Messages::DatabaseProcessIDBConnection::RollbackTransactionSync(transactionID), Messages::DatabaseProcessIDBConnection::RollbackTransactionSync::Reply(success));
305    return success;
306}
307
308void 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)
309{
310}
311
312void WebIDBServerConnection::createObjectStore(IDBTransactionBackend& transaction, const CreateObjectStoreOperation& operation, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback)
313{
314    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<PassRefPtr<IDBDatabaseError>>::create(completionCallback);
315
316    String objectStoreName = operation.objectStoreMetadata().name;
317    serverRequest->setAbortHandler([objectStoreName, completionCallback]() {
318        completionCallback(IDBDatabaseError::create(IDBDatabaseException::UnknownError, String::format("Unknown error occured creating object store '%s'", objectStoreName.utf8().data())));
319    });
320
321    uint64_t requestID = serverRequest->requestID();
322    ASSERT(!m_serverRequests.contains(requestID));
323    m_serverRequests.add(requestID, serverRequest.release());
324
325    LOG(IDB, "WebProcess createObjectStore '%s' in transaction ID %llu (request ID %llu)", operation.objectStoreMetadata().name.utf8().data(), transaction.id(), requestID);
326
327    send(Messages::DatabaseProcessIDBConnection::CreateObjectStore(requestID, transaction.id(), operation.objectStoreMetadata()));
328}
329
330void WebIDBServerConnection::didCreateObjectStore(uint64_t requestID, bool success)
331{
332    LOG(IDB, "WebProcess didCreateObjectStore request ID %llu", requestID);
333
334    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
335
336    if (!serverRequest)
337        return;
338
339    serverRequest->completeRequest(success ? nullptr : IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured creating object store"));
340}
341
342void WebIDBServerConnection::createIndex(IDBTransactionBackend&transaction, const CreateIndexOperation& operation, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback)
343{
344    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<PassRefPtr<IDBDatabaseError>>::create(completionCallback);
345
346    serverRequest->setAbortHandler([completionCallback]() {
347        completionCallback(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured creating index"));
348    });
349
350    uint64_t requestID = serverRequest->requestID();
351    ASSERT(!m_serverRequests.contains(requestID));
352    m_serverRequests.add(requestID, serverRequest.release());
353
354    LOG(IDB, "WebProcess create index request ID %llu", requestID);
355
356    send(Messages::DatabaseProcessIDBConnection::CreateIndex(requestID, transaction.id(), operation.objectStoreID(), operation.idbIndexMetadata()));
357}
358
359void WebIDBServerConnection::didCreateIndex(uint64_t requestID, bool success)
360{
361    LOG(IDB, "WebProcess didCreateIndex request ID %llu", requestID);
362
363    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
364
365    if (!serverRequest)
366        return;
367
368    serverRequest->completeRequest(success ? nullptr : IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured creating index"));
369}
370
371void WebIDBServerConnection::deleteIndex(IDBTransactionBackend&transaction, const DeleteIndexOperation& operation, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback)
372{
373    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<PassRefPtr<IDBDatabaseError>>::create(completionCallback);
374
375    serverRequest->setAbortHandler([completionCallback]() {
376        completionCallback(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured deleting index"));
377    });
378
379    uint64_t requestID = serverRequest->requestID();
380    ASSERT(!m_serverRequests.contains(requestID));
381    m_serverRequests.add(requestID, serverRequest.release());
382
383    LOG(IDB, "WebProcess delete index request ID %llu", requestID);
384
385    send(Messages::DatabaseProcessIDBConnection::DeleteIndex(requestID, transaction.id(), operation.objectStoreID(), operation.idbIndexMetadata().id));
386}
387
388void WebIDBServerConnection::didDeleteIndex(uint64_t requestID, bool success)
389{
390    LOG(IDB, "WebProcess didDeleteIndex request ID %llu", requestID);
391
392    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
393
394    if (!serverRequest)
395        return;
396
397    serverRequest->completeRequest(success ? nullptr : IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured deleting index"));
398}
399
400void WebIDBServerConnection::get(IDBTransactionBackend& transaction, const GetOperation& operation, std::function<void(const IDBGetResult&, PassRefPtr<IDBDatabaseError>)> completionCallback)
401{
402    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<const IDBGetResult&, PassRefPtr<IDBDatabaseError>>::create(completionCallback);
403
404    serverRequest->setAbortHandler([completionCallback]() {
405        completionCallback(IDBGetResult(), IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured getting record"));
406    });
407
408    uint64_t requestID = serverRequest->requestID();
409    ASSERT(!m_serverRequests.contains(requestID));
410    m_serverRequests.add(requestID, serverRequest.release());
411
412    LOG(IDB, "WebProcess get request ID %llu", requestID);
413
414    ASSERT(operation.keyRange());
415
416    send(Messages::DatabaseProcessIDBConnection::GetRecord(requestID, transaction.id(), operation.objectStoreID(), operation.indexID(), operation.keyRange(), static_cast<int64_t>(operation.cursorType())));
417}
418
419void WebIDBServerConnection::put(IDBTransactionBackend& transaction, const PutOperation& operation, std::function<void(PassRefPtr<IDBKey>, PassRefPtr<IDBDatabaseError>)> completionCallback)
420{
421    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<PassRefPtr<IDBKey>, PassRefPtr<IDBDatabaseError>>::create(completionCallback);
422
423    serverRequest->setAbortHandler([completionCallback]() {
424        completionCallback(nullptr, IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured putting record"));
425    });
426
427    uint64_t requestID = serverRequest->requestID();
428    ASSERT(!m_serverRequests.contains(requestID));
429    m_serverRequests.add(requestID, serverRequest.release());
430
431    LOG(IDB, "WebProcess put request ID %llu", requestID);
432
433    ASSERT(operation.value());
434
435    IPC::DataReference value(reinterpret_cast<const uint8_t*>(operation.value()->data()), operation.value()->size());
436
437    Vector<Vector<IDBKeyData>> indexKeys;
438    for (const auto& keys : operation.indexKeys()) {
439        indexKeys.append(Vector<IDBKeyData>());
440        for (const auto& key : keys)
441            indexKeys.last().append(IDBKeyData(key.get()));
442    }
443
444    send(Messages::DatabaseProcessIDBConnection::PutRecord(requestID, transaction.id(), operation.objectStore().id, IDBKeyData(operation.key()), value, operation.putMode(), operation.indexIDs(), indexKeys));
445}
446
447void WebIDBServerConnection::didPutRecord(uint64_t requestID, const WebCore::IDBKeyData& resultKey, uint32_t errorCode, const String& errorMessage)
448{
449    LOG(IDB, "WebProcess didPutRecord request ID %llu (error - %s)", requestID, errorMessage.utf8().data());
450
451    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
452
453    if (!serverRequest)
454        return;
455
456    serverRequest->completeRequest(resultKey.isNull ? nullptr : resultKey.maybeCreateIDBKey(), errorCode ? IDBDatabaseError::create(errorCode, errorMessage) : nullptr);
457}
458
459void WebIDBServerConnection::didGetRecord(uint64_t requestID, const WebCore::IDBGetResult& getResult, uint32_t errorCode, const String& errorMessage)
460{
461    LOG(IDB, "WebProcess didGetRecord request ID %llu (error - %s)", requestID, errorMessage.utf8().data());
462
463    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
464
465    if (!serverRequest)
466        return;
467
468    serverRequest->completeRequest(getResult, errorCode ? IDBDatabaseError::create(errorCode, errorMessage) : nullptr);
469}
470
471void WebIDBServerConnection::didOpenCursor(uint64_t requestID, int64_t cursorID, const IDBKeyData& key, const IDBKeyData& primaryKey, const IPC::DataReference& valueData, uint32_t errorCode, const String& errorMessage)
472{
473    LOG(IDB, "WebProcess didOpenCursor request ID %llu (error - %s)", requestID, errorMessage.utf8().data());
474
475    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
476
477    if (!serverRequest)
478        return;
479
480    RefPtr<SharedBuffer> value = SharedBuffer::create(valueData.data(), valueData.size());
481    serverRequest->completeRequest(cursorID, key.maybeCreateIDBKey(), primaryKey.maybeCreateIDBKey(), value.release(), errorCode ? IDBDatabaseError::create(errorCode, errorMessage) : nullptr);
482}
483
484void WebIDBServerConnection::didAdvanceCursor(uint64_t requestID, const IDBKeyData& key, const IDBKeyData& primaryKey, const IPC::DataReference& valueData, uint32_t errorCode, const String& errorMessage)
485{
486    LOG(IDB, "WebProcess didAdvanceCursor request ID %llu (error - %s)", requestID, errorMessage.utf8().data());
487
488    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
489
490    if (!serverRequest)
491        return;
492
493    RefPtr<SharedBuffer> value = SharedBuffer::create(valueData.data(), valueData.size());
494    serverRequest->completeRequest(key.maybeCreateIDBKey(), primaryKey.maybeCreateIDBKey(), value.release(), errorCode ? IDBDatabaseError::create(errorCode, errorMessage) : nullptr);
495}
496
497void WebIDBServerConnection::didIterateCursor(uint64_t requestID, const IDBKeyData& key, const IDBKeyData& primaryKey, const IPC::DataReference& valueData, uint32_t errorCode, const String& errorMessage)
498{
499    LOG(IDB, "WebProcess didIterateCursor request ID %llu (error - %s)", requestID, errorMessage.utf8().data());
500
501    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
502
503    if (!serverRequest)
504        return;
505
506    RefPtr<SharedBuffer> value = SharedBuffer::create(valueData.data(), valueData.size());
507    serverRequest->completeRequest(key.maybeCreateIDBKey(), primaryKey.maybeCreateIDBKey(), value.release(), errorCode ? IDBDatabaseError::create(errorCode, errorMessage) : nullptr);
508}
509
510void WebIDBServerConnection::count(IDBTransactionBackend& transaction, const CountOperation& operation, std::function<void(int64_t, PassRefPtr<IDBDatabaseError>)> completionCallback)
511{
512    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<int64_t, PassRefPtr<IDBDatabaseError>>::create(completionCallback);
513
514    serverRequest->setAbortHandler([completionCallback]() {
515        completionCallback(0, IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured getting count"));
516    });
517
518    uint64_t requestID = serverRequest->requestID();
519    ASSERT(!m_serverRequests.contains(requestID));
520    m_serverRequests.add(requestID, serverRequest.release());
521
522    LOG(IDB, "WebProcess count request ID %llu", requestID);
523
524    send(Messages::DatabaseProcessIDBConnection::Count(requestID, transaction.id(), operation.objectStoreID(), operation.indexID(), IDBKeyRangeData(operation.keyRange())));
525}
526
527void WebIDBServerConnection::didCount(uint64_t requestID, int64_t count, uint32_t errorCode, const String& errorMessage)
528{
529    LOG(IDB, "WebProcess didCount %lli request ID %llu (error - %s)", count, requestID, errorMessage.utf8().data());
530
531    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
532
533    if (!serverRequest)
534        return;
535
536    serverRequest->completeRequest(count, errorCode ? IDBDatabaseError::create(errorCode, errorMessage) : nullptr);
537}
538
539void WebIDBServerConnection::deleteRange(IDBTransactionBackend& transaction, const DeleteRangeOperation& operation, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback)
540{
541    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<PassRefPtr<IDBDatabaseError>>::create(completionCallback);
542
543    serverRequest->setAbortHandler([completionCallback]() {
544        completionCallback(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured getting count"));
545    });
546
547    uint64_t requestID = serverRequest->requestID();
548    ASSERT(!m_serverRequests.contains(requestID));
549    m_serverRequests.add(requestID, serverRequest.release());
550
551    LOG(IDB, "WebProcess deleteRange request ID %llu", requestID);
552
553    send(Messages::DatabaseProcessIDBConnection::DeleteRange(requestID, transaction.id(), operation.objectStoreID(), IDBKeyRangeData(operation.keyRange())));
554}
555
556void WebIDBServerConnection::didDeleteRange(uint64_t requestID, uint32_t errorCode, const String& errorMessage)
557{
558    LOG(IDB, "WebProcess didDeleteRange request ID %llu", requestID);
559
560    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
561
562    if (!serverRequest)
563        return;
564
565    serverRequest->completeRequest(errorCode ? IDBDatabaseError::create(errorCode, errorMessage) : nullptr);
566}
567
568void WebIDBServerConnection::clearObjectStore(IDBTransactionBackend&, const ClearObjectStoreOperation& operation, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback)
569{
570    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<PassRefPtr<IDBDatabaseError>>::create(completionCallback);
571
572    serverRequest->setAbortHandler([completionCallback]() {
573        completionCallback(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured clearing object store"));
574    });
575
576    uint64_t requestID = serverRequest->requestID();
577    ASSERT(!m_serverRequests.contains(requestID));
578    m_serverRequests.add(requestID, serverRequest.release());
579
580    LOG(IDB, "WebProcess clearObjectStore request ID %llu", requestID);
581
582    send(Messages::DatabaseProcessIDBConnection::ClearObjectStore(requestID, operation.transaction()->id(), operation.objectStoreID()));
583}
584
585void WebIDBServerConnection::didClearObjectStore(uint64_t requestID, bool success)
586{
587    LOG(IDB, "WebProcess didClearObjectStore request ID %llu", requestID);
588
589    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
590
591    if (!serverRequest)
592        return;
593
594    serverRequest->completeRequest(success ? nullptr : IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured clearing object store"));
595}
596
597void WebIDBServerConnection::deleteObjectStore(IDBTransactionBackend&, const DeleteObjectStoreOperation& operation, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback)
598{
599    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<PassRefPtr<IDBDatabaseError>>::create(completionCallback);
600
601    serverRequest->setAbortHandler([completionCallback]() {
602        completionCallback(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured deleting object store"));
603    });
604
605    uint64_t requestID = serverRequest->requestID();
606    ASSERT(!m_serverRequests.contains(requestID));
607    m_serverRequests.add(requestID, serverRequest.release());
608
609    LOG(IDB, "WebProcess deleteObjectStore request ID %llu", requestID);
610
611    send(Messages::DatabaseProcessIDBConnection::DeleteObjectStore(requestID, operation.transaction()->id(), operation.objectStoreMetadata().id));
612}
613
614void WebIDBServerConnection::didDeleteObjectStore(uint64_t requestID, bool success)
615{
616    LOG(IDB, "WebProcess didDeleteObjectStore request ID %llu", requestID);
617
618    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
619
620    if (!serverRequest)
621        return;
622
623    serverRequest->completeRequest(success ? nullptr : IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured deleting object store"));
624}
625
626void WebIDBServerConnection::changeDatabaseVersion(IDBTransactionBackend&, const IDBDatabaseBackend::VersionChangeOperation& operation, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback)
627{
628    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<PassRefPtr<IDBDatabaseError>>::create(completionCallback);
629
630    serverRequest->setAbortHandler([completionCallback]() {
631        completionCallback(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured changing database version"));
632    });
633
634    uint64_t requestID = serverRequest->requestID();
635    ASSERT(!m_serverRequests.contains(requestID));
636    m_serverRequests.add(requestID, serverRequest.release());
637
638    LOG(IDB, "WebProcess changeDatabaseVersion request ID %llu", requestID);
639
640    send(Messages::DatabaseProcessIDBConnection::ChangeDatabaseVersion(requestID, operation.transaction()->id(), static_cast<uint64_t>(operation.version())));
641}
642
643void WebIDBServerConnection::didChangeDatabaseVersion(uint64_t requestID, bool success)
644{
645    LOG(IDB, "WebProcess didChangeDatabaseVersion request ID %llu", requestID);
646
647    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
648
649    if (!serverRequest)
650        return;
651
652    serverRequest->completeRequest(success ? nullptr : IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured changing database version"));
653}
654
655void WebIDBServerConnection::openCursor(IDBTransactionBackend&, const OpenCursorOperation& operation, std::function<void(int64_t, PassRefPtr<IDBKey>, PassRefPtr<IDBKey>, PassRefPtr<SharedBuffer>, PassRefPtr<IDBDatabaseError>)> completionCallback)
656{
657    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<int64_t, PassRefPtr<IDBKey>, PassRefPtr<IDBKey>, PassRefPtr<SharedBuffer>, PassRefPtr<IDBDatabaseError>>::create(completionCallback);
658
659    serverRequest->setAbortHandler([completionCallback]() {
660        completionCallback(0, nullptr, nullptr, nullptr, IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured opening database cursor"));
661    });
662
663    uint64_t requestID = serverRequest->requestID();
664    ASSERT(!m_serverRequests.contains(requestID));
665    m_serverRequests.add(requestID, serverRequest.release());
666
667    LOG(IDB, "WebProcess openCursor request ID %llu", requestID);
668
669    send(Messages::DatabaseProcessIDBConnection::OpenCursor(requestID, operation.transactionID(), operation.objectStoreID(), operation.indexID(), static_cast<int64_t>(operation.direction()), static_cast<int64_t>(operation.cursorType()), static_cast<int64_t>(operation.taskType()), operation.keyRange()));
670}
671
672void WebIDBServerConnection::cursorAdvance(IDBCursorBackend&, const CursorAdvanceOperation& operation, std::function<void(PassRefPtr<IDBKey>, PassRefPtr<IDBKey>, PassRefPtr<SharedBuffer>, PassRefPtr<IDBDatabaseError>)> completionCallback)
673{
674    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<PassRefPtr<IDBKey>, PassRefPtr<IDBKey>, PassRefPtr<SharedBuffer>, PassRefPtr<IDBDatabaseError>>::create(completionCallback);
675
676    serverRequest->setAbortHandler([completionCallback]() {
677        completionCallback(nullptr, nullptr, nullptr, IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured advancing database cursor"));
678    });
679
680    uint64_t requestID = serverRequest->requestID();
681    ASSERT(!m_serverRequests.contains(requestID));
682    m_serverRequests.add(requestID, serverRequest.release());
683
684    LOG(IDB, "WebProcess cursorAdvance request ID %llu", requestID);
685
686    send(Messages::DatabaseProcessIDBConnection::CursorAdvance(requestID, operation.cursorID(), operation.count()));
687}
688
689void WebIDBServerConnection::cursorIterate(IDBCursorBackend&, const CursorIterationOperation& operation, std::function<void(PassRefPtr<IDBKey>, PassRefPtr<IDBKey>, PassRefPtr<SharedBuffer>, PassRefPtr<IDBDatabaseError>)> completionCallback)
690{
691    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<PassRefPtr<IDBKey>, PassRefPtr<IDBKey>, PassRefPtr<SharedBuffer>, PassRefPtr<IDBDatabaseError>>::create(completionCallback);
692
693    serverRequest->setAbortHandler([completionCallback]() {
694        completionCallback(nullptr, nullptr, nullptr, IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured iterating database cursor"));
695    });
696
697    uint64_t requestID = serverRequest->requestID();
698    ASSERT(!m_serverRequests.contains(requestID));
699    m_serverRequests.add(requestID, serverRequest.release());
700
701    LOG(IDB, "WebProcess cursorIterate request ID %llu", requestID);
702
703    send(Messages::DatabaseProcessIDBConnection::CursorIterate(requestID, operation.cursorID(), operation.key()));
704}
705
706IPC::Connection* WebIDBServerConnection::messageSenderConnection()
707{
708    return WebProcess::shared().webToDatabaseProcessConnection()->connection();
709}
710
711} // namespace WebKit
712
713#endif // ENABLE(INDEXED_DATABASE) && ENABLE(DATABASE_PROCESS)
714
715