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. 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 "DatabaseProcessIDBConnection.h" 28 29#if ENABLE(INDEXED_DATABASE) && ENABLE(DATABASE_PROCESS) 30 31#include "DataReference.h" 32#include "DatabaseProcess.h" 33#include "DatabaseToWebProcessConnection.h" 34#include "IDBIdentifier.h" 35#include "Logging.h" 36#include "UniqueIDBDatabase.h" 37#include "WebCoreArgumentCoders.h" 38#include "WebIDBServerConnectionMessages.h" 39#include <WebCore/IDBDatabaseMetadata.h> 40#include <WebCore/IDBServerConnection.h> 41#include <WebCore/IndexedDB.h> 42 43using namespace WebCore; 44 45namespace WebKit { 46 47DatabaseProcessIDBConnection::DatabaseProcessIDBConnection(DatabaseToWebProcessConnection& connection, uint64_t serverConnectionIdentifier) 48 : m_connection(connection) 49 , m_serverConnectionIdentifier(serverConnectionIdentifier) 50{ 51} 52 53DatabaseProcessIDBConnection::~DatabaseProcessIDBConnection() 54{ 55 ASSERT(!m_uniqueIDBDatabase); 56} 57 58void DatabaseProcessIDBConnection::disconnectedFromWebProcess() 59{ 60 // It's possible that the m_uniqueIDBDatabase pointer has already been cleared 61 // if the represented database was deleted, or if it was closed between delete 62 // and the delete callback 63 if (!m_uniqueIDBDatabase) 64 return; 65 66 m_uniqueIDBDatabase->unregisterConnection(*this); 67 m_uniqueIDBDatabase = nullptr; 68} 69 70void DatabaseProcessIDBConnection::establishConnection(const String& databaseName, const SecurityOriginData& openingOrigin, const SecurityOriginData& mainFrameOrigin) 71{ 72 m_uniqueIDBDatabase = DatabaseProcess::shared().getOrCreateUniqueIDBDatabase(UniqueIDBDatabaseIdentifier(databaseName, openingOrigin, mainFrameOrigin)); 73 m_uniqueIDBDatabase->registerConnection(*this); 74} 75 76void DatabaseProcessIDBConnection::getOrEstablishIDBDatabaseMetadata(uint64_t requestID) 77{ 78 ASSERT(m_uniqueIDBDatabase); 79 80 LOG(IDB, "DatabaseProcess getOrEstablishIDBDatabaseMetadata request ID %llu (connection %p)", requestID, this); 81 82 RefPtr<DatabaseProcessIDBConnection> connection(this); 83 m_uniqueIDBDatabase->getOrEstablishIDBDatabaseMetadata([connection, requestID](bool success, const IDBDatabaseMetadata& metadata) { 84 connection->send(Messages::WebIDBServerConnection::DidGetOrEstablishIDBDatabaseMetadata(requestID, success, metadata)); 85 }); 86} 87 88void DatabaseProcessIDBConnection::deleteDatabase(uint64_t requestID, const String& databaseName) 89{ 90 ASSERT(m_uniqueIDBDatabase); 91 92 LOG(IDB, "DatabaseProcess deleteDatabase request ID %llu (connection %p)", requestID, this); 93 94 if (databaseName != m_uniqueIDBDatabase->identifier().databaseName()) { 95 LOG_ERROR("Request to delete database name that doesn't match with this database connection's database name"); 96 send(Messages::WebIDBServerConnection::DidDeleteDatabase(requestID, false)); 97 } 98 99 RefPtr<DatabaseProcessIDBConnection> connection(this); 100 m_uniqueIDBDatabase->deleteDatabase([connection, this, requestID](bool success) { 101 if (success) 102 disconnectedFromWebProcess(); 103 104 connection->send(Messages::WebIDBServerConnection::DidDeleteDatabase(requestID, success)); 105 }); 106} 107 108void DatabaseProcessIDBConnection::openTransaction(uint64_t requestID, int64_t transactionID, const Vector<int64_t>& objectStoreIDs, uint64_t intMode) 109{ 110 ASSERT(m_uniqueIDBDatabase); 111 112#ifndef NDEBUG 113 const char* modeString = nullptr; 114 switch (static_cast<IndexedDB::TransactionMode>(intMode)) { 115 case IndexedDB::TransactionMode::ReadOnly: 116 modeString = "readonly"; 117 break; 118 case IndexedDB::TransactionMode::ReadWrite: 119 modeString = "readwrite"; 120 break; 121 case IndexedDB::TransactionMode::VersionChange: 122 modeString = "versionchange"; 123 break; 124 } 125 126 LOG(IDB, "DatabaseProcess openTransaction id %llu in mode '%s', request ID %llu", transactionID, modeString, requestID); 127#endif 128 129 if (intMode > IndexedDB::TransactionModeMaximum) { 130 send(Messages::WebIDBServerConnection::DidOpenTransaction(requestID, false)); 131 return; 132 } 133 134 IndexedDB::TransactionMode mode = static_cast<IndexedDB::TransactionMode>(intMode); 135 RefPtr<DatabaseProcessIDBConnection> connection(this); 136 m_uniqueIDBDatabase->openTransaction(IDBIdentifier(*this, transactionID), objectStoreIDs, mode, [connection, requestID](bool success) { 137 connection->send(Messages::WebIDBServerConnection::DidOpenTransaction(requestID, success)); 138 }); 139} 140 141void DatabaseProcessIDBConnection::beginTransaction(uint64_t requestID, int64_t transactionID) 142{ 143 ASSERT(m_uniqueIDBDatabase); 144 145 LOG(IDB, "DatabaseProcess beginTransaction request ID %llu", requestID); 146 147 RefPtr<DatabaseProcessIDBConnection> connection(this); 148 m_uniqueIDBDatabase->beginTransaction(IDBIdentifier(*this, transactionID), [connection, requestID](bool success) { 149 connection->send(Messages::WebIDBServerConnection::DidBeginTransaction(requestID, success)); 150 }); 151} 152 153void DatabaseProcessIDBConnection::commitTransaction(uint64_t requestID, int64_t transactionID) 154{ 155 ASSERT(m_uniqueIDBDatabase); 156 157 LOG(IDB, "DatabaseProcess commitTransaction request ID %llu", requestID); 158 159 RefPtr<DatabaseProcessIDBConnection> connection(this); 160 m_uniqueIDBDatabase->commitTransaction(IDBIdentifier(*this, transactionID), [connection, requestID](bool success) { 161 connection->send(Messages::WebIDBServerConnection::DidCommitTransaction(requestID, success)); 162 }); 163} 164 165void DatabaseProcessIDBConnection::resetTransaction(uint64_t requestID, int64_t transactionID) 166{ 167 ASSERT(m_uniqueIDBDatabase); 168 169 LOG(IDB, "DatabaseProcess resetTransaction request ID %llu", requestID); 170 171 RefPtr<DatabaseProcessIDBConnection> connection(this); 172 m_uniqueIDBDatabase->resetTransaction(IDBIdentifier(*this, transactionID), [connection, requestID](bool success) { 173 connection->send(Messages::WebIDBServerConnection::DidResetTransaction(requestID, success)); 174 }); 175} 176 177void DatabaseProcessIDBConnection::rollbackTransaction(uint64_t requestID, int64_t transactionID) 178{ 179 ASSERT(m_uniqueIDBDatabase); 180 181 LOG(IDB, "DatabaseProcess rollbackTransaction request ID %llu", requestID); 182 183 RefPtr<DatabaseProcessIDBConnection> connection(this); 184 m_uniqueIDBDatabase->rollbackTransaction(IDBIdentifier(*this, transactionID), [connection, requestID](bool success) { 185 connection->send(Messages::WebIDBServerConnection::DidRollbackTransaction(requestID, success)); 186 }); 187} 188 189void DatabaseProcessIDBConnection::resetTransactionSync(int64_t transactionID, PassRefPtr<Messages::DatabaseProcessIDBConnection::ResetTransactionSync::DelayedReply> prpReply) 190{ 191 RefPtr<Messages::DatabaseProcessIDBConnection::ResetTransactionSync::DelayedReply> reply(prpReply); 192 RefPtr<DatabaseProcessIDBConnection> connection(this); 193 m_uniqueIDBDatabase->resetTransaction(IDBIdentifier(*this, transactionID), [connection, reply](bool success) { 194 reply->send(success); 195 }); 196} 197 198void DatabaseProcessIDBConnection::rollbackTransactionSync(int64_t transactionID, PassRefPtr<Messages::DatabaseProcessIDBConnection::RollbackTransactionSync::DelayedReply> prpReply) 199{ 200 RefPtr<Messages::DatabaseProcessIDBConnection::RollbackTransactionSync::DelayedReply> reply(prpReply); 201 RefPtr<DatabaseProcessIDBConnection> connection(this); 202 m_uniqueIDBDatabase->rollbackTransaction(IDBIdentifier(*this, transactionID), [connection, reply](bool success) { 203 reply->send(success); 204 }); 205} 206 207void DatabaseProcessIDBConnection::changeDatabaseVersion(uint64_t requestID, int64_t transactionID, uint64_t newVersion) 208{ 209 ASSERT(m_uniqueIDBDatabase); 210 211 LOG(IDB, "DatabaseProcess changeDatabaseVersion request ID %llu, new version %llu", requestID, newVersion); 212 213 RefPtr<DatabaseProcessIDBConnection> connection(this); 214 m_uniqueIDBDatabase->changeDatabaseVersion(IDBIdentifier(*this, transactionID), newVersion, [connection, requestID](bool success) { 215 connection->send(Messages::WebIDBServerConnection::DidChangeDatabaseVersion(requestID, success)); 216 }); 217} 218 219void DatabaseProcessIDBConnection::createObjectStore(uint64_t requestID, int64_t transactionID, IDBObjectStoreMetadata metadata) 220{ 221 ASSERT(m_uniqueIDBDatabase); 222 223 LOG(IDB, "DatabaseProcess createObjectStore request ID %llu, object store name '%s'", requestID, metadata.name.utf8().data()); 224 RefPtr<DatabaseProcessIDBConnection> connection(this); 225 m_uniqueIDBDatabase->createObjectStore(IDBIdentifier(*this, transactionID), metadata, [connection, requestID](bool success) { 226 connection->send(Messages::WebIDBServerConnection::DidCreateObjectStore(requestID, success)); 227 }); 228} 229 230void DatabaseProcessIDBConnection::deleteObjectStore(uint64_t requestID, int64_t transactionID, int64_t objectStoreID) 231{ 232 ASSERT(m_uniqueIDBDatabase); 233 234 LOG(IDB, "DatabaseProcess deleteObjectStore request ID %llu, object store id %lli", requestID, objectStoreID); 235 RefPtr<DatabaseProcessIDBConnection> connection(this); 236 m_uniqueIDBDatabase->deleteObjectStore(IDBIdentifier(*this, transactionID), objectStoreID, [connection, requestID](bool success) { 237 connection->send(Messages::WebIDBServerConnection::DidDeleteObjectStore(requestID, success)); 238 }); 239} 240 241void DatabaseProcessIDBConnection::clearObjectStore(uint64_t requestID, int64_t transactionID, int64_t objectStoreID) 242{ 243 ASSERT(m_uniqueIDBDatabase); 244 245 LOG(IDB, "DatabaseProcess clearObjectStore request ID %llu, object store id %lli", requestID, objectStoreID); 246 RefPtr<DatabaseProcessIDBConnection> connection(this); 247 m_uniqueIDBDatabase->clearObjectStore(IDBIdentifier(*this, transactionID), objectStoreID, [connection, requestID](bool success) { 248 connection->send(Messages::WebIDBServerConnection::DidClearObjectStore(requestID, success)); 249 }); 250} 251 252void DatabaseProcessIDBConnection::createIndex(uint64_t requestID, int64_t transactionID, int64_t objectStoreID, const IDBIndexMetadata& metadata) 253{ 254 ASSERT(m_uniqueIDBDatabase); 255 256 LOG(IDB, "DatabaseProcess createIndex request ID %llu, object store id %lli", requestID, objectStoreID); 257 RefPtr<DatabaseProcessIDBConnection> connection(this); 258 m_uniqueIDBDatabase->createIndex(IDBIdentifier(*this, transactionID), objectStoreID, metadata, [connection, requestID](bool success) { 259 connection->send(Messages::WebIDBServerConnection::DidCreateIndex(requestID, success)); 260 }); 261} 262 263void DatabaseProcessIDBConnection::deleteIndex(uint64_t requestID, int64_t transactionID, int64_t objectStoreID, int64_t indexID) 264{ 265 ASSERT(m_uniqueIDBDatabase); 266 267 LOG(IDB, "DatabaseProcess deleteIndex request ID %llu, object store id %lli", requestID, objectStoreID); 268 RefPtr<DatabaseProcessIDBConnection> connection(this); 269 m_uniqueIDBDatabase->deleteIndex(IDBIdentifier(*this, transactionID), objectStoreID, indexID, [connection, requestID](bool success) { 270 connection->send(Messages::WebIDBServerConnection::DidDeleteIndex(requestID, success)); 271 }); 272} 273 274void DatabaseProcessIDBConnection::putRecord(uint64_t requestID, int64_t transactionID, int64_t objectStoreID, const IDBKeyData& key, const IPC::DataReference& value, int64_t putMode, const Vector<int64_t>& indexIDs, const Vector<Vector<IDBKeyData>>& indexKeys) 275{ 276 ASSERT(m_uniqueIDBDatabase); 277 278 LOG(IDB, "DatabaseProcess putRecord request ID %llu, object store id %lli", requestID, objectStoreID); 279 RefPtr<DatabaseProcessIDBConnection> connection(this); 280 m_uniqueIDBDatabase->putRecord(IDBIdentifier(*this, transactionID), objectStoreID, key, value, putMode, indexIDs, indexKeys, [connection, requestID](const IDBKeyData& keyData, uint32_t errorCode, const String& errorMessage) { 281 connection->send(Messages::WebIDBServerConnection::DidPutRecord(requestID, keyData, errorCode, errorMessage)); 282 }); 283} 284 285void DatabaseProcessIDBConnection::getRecord(uint64_t requestID, int64_t transactionID, int64_t objectStoreID, int64_t indexID, const IDBKeyRangeData& keyRange, int64_t cursorType) 286{ 287 ASSERT(m_uniqueIDBDatabase); 288 289 LOG(IDB, "DatabaseProcess getRecord request ID %llu, object store id %lli", requestID, objectStoreID); 290 RefPtr<DatabaseProcessIDBConnection> connection(this); 291 m_uniqueIDBDatabase->getRecord(IDBIdentifier(*this, transactionID), objectStoreID, indexID, keyRange, static_cast<IndexedDB::CursorType>(cursorType), [connection, requestID](const IDBGetResult& getResult, uint32_t errorCode, const String& errorMessage) { 292 connection->send(Messages::WebIDBServerConnection::DidGetRecord(requestID, getResult, errorCode, errorMessage)); 293 }); 294} 295 296void DatabaseProcessIDBConnection::count(uint64_t requestID, int64_t transactionID, int64_t objectStoreID, int64_t indexID, const IDBKeyRangeData& keyRangeData) 297{ 298 ASSERT(m_uniqueIDBDatabase); 299 300 LOG(IDB, "DatabaseProcess count request ID %llu, object store id %lli", requestID, objectStoreID); 301 302 RefPtr<DatabaseProcessIDBConnection> connection(this); 303 m_uniqueIDBDatabase->count(IDBIdentifier(*this, transactionID), objectStoreID, indexID, keyRangeData, [connection, requestID](int64_t count, uint32_t errorCode, const String& errorMessage) { 304 connection->send(Messages::WebIDBServerConnection::DidCount(requestID, count, errorCode, errorMessage)); 305 }); 306} 307 308void DatabaseProcessIDBConnection::deleteRange(uint64_t requestID, int64_t transactionID, int64_t objectStoreID, const IDBKeyRangeData& keyRangeData) 309{ 310 ASSERT(m_uniqueIDBDatabase); 311 312 LOG(IDB, "DatabaseProcess deleteRange request ID %llu, object store id %lli", requestID, objectStoreID); 313 314 RefPtr<DatabaseProcessIDBConnection> connection(this); 315 m_uniqueIDBDatabase->deleteRange(IDBIdentifier(*this, transactionID), objectStoreID, keyRangeData, [connection, requestID](uint32_t errorCode, const String& errorMessage) { 316 connection->send(Messages::WebIDBServerConnection::DidDeleteRange(requestID, errorCode, errorMessage)); 317 }); 318} 319 320void DatabaseProcessIDBConnection::openCursor(uint64_t requestID, int64_t transactionID, int64_t objectStoreID, int64_t indexID, int64_t cursorDirection, int64_t cursorType, int64_t taskType, const IDBKeyRangeData& keyRangeData) 321{ 322 ASSERT(m_uniqueIDBDatabase); 323 324 LOG(IDB, "DatabaseProcess openCursor request ID %llu, object store id %lli", requestID, objectStoreID); 325 RefPtr<DatabaseProcessIDBConnection> connection(this); 326 m_uniqueIDBDatabase->openCursor(IDBIdentifier(*this, transactionID), objectStoreID, indexID, static_cast<IndexedDB::CursorDirection>(cursorDirection), static_cast<IndexedDB::CursorType>(cursorType), static_cast<IDBDatabaseBackend::TaskType>(taskType), keyRangeData, [connection, requestID](int64_t cursorID, const IDBKeyData& resultKey, const IDBKeyData& primaryKey, PassRefPtr<SharedBuffer> value, uint32_t errorCode, const String& errorMessage) { 327 IPC::DataReference data = value ? IPC::DataReference(reinterpret_cast<const uint8_t*>(value->data()), value->size()) : IPC::DataReference(); 328 connection->send(Messages::WebIDBServerConnection::DidOpenCursor(requestID, cursorID, resultKey, primaryKey, data, errorCode, errorMessage)); 329 }); 330} 331 332void DatabaseProcessIDBConnection::cursorAdvance(uint64_t requestID, int64_t cursorID, uint64_t count) 333{ 334 ASSERT(m_uniqueIDBDatabase); 335 336 LOG(IDB, "DatabaseProcess cursorAdvance request ID %llu, cursor id %lli", requestID, cursorID); 337 RefPtr<DatabaseProcessIDBConnection> connection(this); 338 m_uniqueIDBDatabase->cursorAdvance(IDBIdentifier(*this, cursorID), count, [connection, requestID](const IDBKeyData& resultKey, const IDBKeyData& primaryKey, PassRefPtr<SharedBuffer> value, uint32_t errorCode, const String& errorMessage) { 339 IPC::DataReference data = value ? IPC::DataReference(reinterpret_cast<const uint8_t*>(value->data()), value->size()) : IPC::DataReference(); 340 connection->send(Messages::WebIDBServerConnection::DidAdvanceCursor(requestID, resultKey, primaryKey, data, errorCode, errorMessage)); 341 }); 342} 343 344void DatabaseProcessIDBConnection::cursorIterate(uint64_t requestID, int64_t cursorID, const IDBKeyData& key) 345{ 346 ASSERT(m_uniqueIDBDatabase); 347 348 LOG(IDB, "DatabaseProcess cursorIterate request ID %llu, cursor id %lli", requestID, cursorID); 349 RefPtr<DatabaseProcessIDBConnection> connection(this); 350 m_uniqueIDBDatabase->cursorIterate(IDBIdentifier(*this, cursorID), key, [connection, requestID](const IDBKeyData& resultKey, const IDBKeyData& primaryKey, PassRefPtr<SharedBuffer> value, uint32_t errorCode, const String& errorMessage) { 351 IPC::DataReference data = value ? IPC::DataReference(reinterpret_cast<const uint8_t*>(value->data()), value->size()) : IPC::DataReference(); 352 connection->send(Messages::WebIDBServerConnection::DidIterateCursor(requestID, resultKey, primaryKey, data, errorCode, errorMessage)); 353 }); 354} 355 356void DatabaseProcessIDBConnection::close() 357{ 358 LOG(IDB, "DatabaseProcessIDBConnection close"); 359 360 disconnectedFromWebProcess(); 361} 362 363IPC::Connection* DatabaseProcessIDBConnection::messageSenderConnection() 364{ 365 return m_connection->connection(); 366} 367 368} // namespace WebKit 369 370#endif // ENABLE(INDEXED_DATABASE) && ENABLE(DATABASE_PROCESS) 371