DatabaseProcess: Implement version changing
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 26 Dec 2013 00:29:03 +0000 (00:29 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 26 Dec 2013 00:29:03 +0000 (00:29 +0000)
https://bugs.webkit.org/show_bug.cgi?id=126099

Reviewed by Sam Weinig.

Source/WebCore:

No new tests (No change in WebCore behavior).

* Modules/indexeddb/IDBTransactionBackend.cpp:
(WebCore::IDBTransactionBackend::commit): Update some logging.

* Modules/indexeddb/IDBTransactionBackendOperations.cpp:
(WebCore::IDBDatabaseBackend::VersionChangeOperation::perform): Move some things that used to be in
  IDBServerConnectionLevelDB::changeDatabaseVersion to this cross-platform location.
* Modules/indexeddb/IDBTransactionBackendOperations.h:
(WebCore::IDBDatabaseBackend::VersionChangeOperation::transaction):

* Modules/indexeddb/leveldb/IDBServerConnectionLevelDB.cpp:
(WebCore::IDBServerConnectionLevelDB::changeDatabaseVersion): Move the actual updating of the database backend
  metadata to the VersionChangeOperation.

Source/WebKit2:

* DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.cpp:
(WebKit::DatabaseProcessIDBConnection::getOrEstablishIDBDatabaseMetadata): Add logging.
(WebKit::DatabaseProcessIDBConnection::openTransaction): Ditto.
(WebKit::DatabaseProcessIDBConnection::beginTransaction): Ditto.
(WebKit::DatabaseProcessIDBConnection::commitTransaction): Ditto.
(WebKit::DatabaseProcessIDBConnection::resetTransaction): Ditto.
(WebKit::DatabaseProcessIDBConnection::rollbackTransaction): Ditto.
(WebKit::DatabaseProcessIDBConnection::changeDatabaseVersion): Implement this!
* DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.h:
* DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.messages.in:

* DatabaseProcess/IndexedDB/UniqueIDBDatabase.cpp:
(WebKit::UniqueIDBDatabase::shutdown): Clean up all requests, and also cleanup the backing store
  on the database queue.
(WebKit::UniqueIDBDatabase::shutdownBackingStore): Shutdown the backing store.
(WebKit::UniqueIDBDatabase::didShutdownBackingStore):
(WebKit::UniqueIDBDatabase::changeDatabaseVersion): Pass along the new version to the database queue.
(WebKit::UniqueIDBDatabase::didChangeDatabaseVersion):
(WebKit::UniqueIDBDatabase::changeDatabaseVersionInBackingStore): Set the new version in the backing store.
(WebKit::UniqueIDBDatabase::postMainThreadTask): Add a ref() to keep the database alive incase it is being
  shutdown on the main thread.
(WebKit::UniqueIDBDatabase::performNextMainThreadTask): Balance the ref() from postMainThreadTask, and
  accept an empty mainThreadTask queue.
* DatabaseProcess/IndexedDB/UniqueIDBDatabase.h:

* DatabaseProcess/IndexedDB/UniqueIDBDatabaseBackingStore.h: Add changeDatabaseVersion.

Flesh out SQLiteIDBTransaction to actually operation on a SQLiteTransaction in a real SQLiteDatabase:
* DatabaseProcess/IndexedDB/sqlite/SQLiteIDBTransaction.cpp:
(WebKit::SQLiteIDBTransaction::SQLiteIDBTransaction):
(WebKit::SQLiteIDBTransaction::~SQLiteIDBTransaction):
(WebKit::SQLiteIDBTransaction::begin):
(WebKit::SQLiteIDBTransaction::commit):
(WebKit::SQLiteIDBTransaction::reset):
(WebKit::SQLiteIDBTransaction::rollback):
(WebKit::SQLiteIDBTransaction::inProgress):
* DatabaseProcess/IndexedDB/sqlite/SQLiteIDBTransaction.h:
(WebKit::SQLiteIDBTransaction::create):
(WebKit::SQLiteIDBTransaction::mode):

Rename m_metadataDB to m_sqliteDB,
* DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.cpp:
(WebKit::UniqueIDBDatabaseBackingStoreSQLite::createAndPopulateInitialMetadata):
(WebKit::UniqueIDBDatabaseBackingStoreSQLite::extractExistingMetadata):
(WebKit::UniqueIDBDatabaseBackingStoreSQLite::openSQLiteDatabaseAtPath): Disable threading checks on the DB
  as work queues can change threads.
(WebKit::UniqueIDBDatabaseBackingStoreSQLite::getOrEstablishMetadata):
(WebKit::UniqueIDBDatabaseBackingStoreSQLite::establishTransaction):
(WebKit::UniqueIDBDatabaseBackingStoreSQLite::beginTransaction):
(WebKit::UniqueIDBDatabaseBackingStoreSQLite::changeDatabaseVersion): After validating the transaction, actually
  update the version number on disk.
* DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.h:

* WebProcess/Databases/IndexedDB/WebIDBServerConnection.cpp:
(WebKit::WebIDBServerConnection::~WebIDBServerConnection): Make sure to abort in-flight requests.
(WebKit::WebIDBServerConnection::changeDatabaseVersion):
(WebKit::WebIDBServerConnection::didChangeDatabaseVersion):
* WebProcess/Databases/IndexedDB/WebIDBServerConnection.h:
* WebProcess/Databases/IndexedDB/WebIDBServerConnection.messages.in:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@161076 268f45cc-cd09-0410-ab3c-d52691b4dbfc

19 files changed:
Source/WebCore/ChangeLog
Source/WebCore/Modules/indexeddb/IDBTransactionBackend.cpp
Source/WebCore/Modules/indexeddb/IDBTransactionBackendOperations.cpp
Source/WebCore/Modules/indexeddb/IDBTransactionBackendOperations.h
Source/WebCore/Modules/indexeddb/leveldb/IDBServerConnectionLevelDB.cpp
Source/WebKit2/ChangeLog
Source/WebKit2/DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.cpp
Source/WebKit2/DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.h
Source/WebKit2/DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.messages.in
Source/WebKit2/DatabaseProcess/IndexedDB/UniqueIDBDatabase.cpp
Source/WebKit2/DatabaseProcess/IndexedDB/UniqueIDBDatabase.h
Source/WebKit2/DatabaseProcess/IndexedDB/UniqueIDBDatabaseBackingStore.h
Source/WebKit2/DatabaseProcess/IndexedDB/sqlite/SQLiteIDBTransaction.cpp
Source/WebKit2/DatabaseProcess/IndexedDB/sqlite/SQLiteIDBTransaction.h
Source/WebKit2/DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.cpp
Source/WebKit2/DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.h
Source/WebKit2/WebProcess/Databases/IndexedDB/WebIDBServerConnection.cpp
Source/WebKit2/WebProcess/Databases/IndexedDB/WebIDBServerConnection.h
Source/WebKit2/WebProcess/Databases/IndexedDB/WebIDBServerConnection.messages.in

index 5482ca4..9811f3b 100644 (file)
@@ -1,3 +1,25 @@
+2013-12-25  Brady Eidson  <beidson@apple.com>
+
+        DatabaseProcess: Implement version changing
+        https://bugs.webkit.org/show_bug.cgi?id=126099
+
+        Reviewed by Sam Weinig.
+
+        No new tests (No change in WebCore behavior).
+
+        * Modules/indexeddb/IDBTransactionBackend.cpp:
+        (WebCore::IDBTransactionBackend::commit): Update some logging.
+
+        * Modules/indexeddb/IDBTransactionBackendOperations.cpp:
+        (WebCore::IDBDatabaseBackend::VersionChangeOperation::perform): Move some things that used to be in
+          IDBServerConnectionLevelDB::changeDatabaseVersion to this cross-platform location.
+        * Modules/indexeddb/IDBTransactionBackendOperations.h:
+        (WebCore::IDBDatabaseBackend::VersionChangeOperation::transaction):
+
+        * Modules/indexeddb/leveldb/IDBServerConnectionLevelDB.cpp:
+        (WebCore::IDBServerConnectionLevelDB::changeDatabaseVersion): Move the actual updating of the database backend
+          metadata to the VersionChangeOperation.
+
 2013-12-25  Martin Robinson  <mrobinson@igalia.com>
 
         [GTK] [CMake] Clean up generated sources directories
index 29a5bc4..1fe1435 100644 (file)
@@ -201,7 +201,7 @@ void IDBTransactionBackend::start()
 
 void IDBTransactionBackend::commit()
 {
-    LOG(StorageAPI, "IDBTransactionBackend::commit");
+    LOG(StorageAPI, "IDBTransactionBackend::commit (Transaction %lli)", m_id);
 
     // In multiprocess ports, front-end may have requested a commit but an abort has already
     // been initiated asynchronously by the back-end.
@@ -213,8 +213,10 @@ void IDBTransactionBackend::commit()
 
     // Front-end has requested a commit, but there may be tasks like createIndex which
     // are considered synchronous by the front-end but are processed asynchronously.
-    if (hasPendingTasks())
+    if (hasPendingTasks()) {
+        LOG(StorageAPI, "IDBTransactionBackend::commit - Not committing now, transaction still has pending tasks (Transaction %lli)", m_id);
         return;
+    }
 
     // The last reference to this object may be released while performing the
     // commit steps below. We therefore take a self reference to keep ourselves
index 841ff7c..c6d81c9 100644 (file)
@@ -173,8 +173,23 @@ void IDBDatabaseBackend::VersionChangeOperation::perform(std::function<void()> c
 {
     LOG(StorageAPI, "VersionChangeOperation");
 
+    uint64_t oldVersion = m_transaction->database().metadata().version;
     RefPtr<IDBDatabaseBackend::VersionChangeOperation> operation(this);
-    STANDARD_DATABASE_ERROR_CALLBACK;
+    ASSERT(static_cast<uint64_t>(m_version) > oldVersion);
+
+    std::function<void(PassRefPtr<IDBDatabaseError>)> operationCallback = [oldVersion, operation, this, completionCallback](PassRefPtr<IDBDatabaseError> prpError) {
+        RefPtr<IDBDatabaseError> error = prpError;
+        if (error) {
+            m_callbacks->onError(error);
+            m_transaction->abort(error);
+        } else {
+            ASSERT(!m_transaction->database().hasPendingSecondHalfOpen());
+            m_transaction->database().setCurrentVersion(m_version);
+            m_transaction->database().setPendingSecondHalfOpen(IDBPendingOpenCall::create(*m_callbacks, *m_databaseCallbacks, m_transaction->id(), m_version));
+            m_callbacks->onUpgradeNeeded(oldVersion, &m_transaction->database(), m_transaction->database().metadata());
+        }
+        completionCallback();
+    };
 
     m_transaction->database().serverConnection().changeDatabaseVersion(*m_transaction, *this, operationCallback);
 }
index 92baa30..f713a9d 100644 (file)
@@ -86,6 +86,7 @@ public:
     }
     virtual void perform(std::function<void()> successCallback) OVERRIDE FINAL;
 
+    IDBTransactionBackend* transaction() const { return m_transaction.get(); }
     int64_t version() const { return m_version; }
     IDBCallbacks* callbacks() const { return m_callbacks.get(); }
     IDBDatabaseCallbacks* databaseCallbacks() const { return m_databaseCallbacks.get(); }
index 4eb6f40..b8f45d8 100644 (file)
@@ -562,20 +562,12 @@ void IDBServerConnectionLevelDB::changeDatabaseVersion(IDBTransactionBackend& tr
 
     IDBDatabaseBackend& database = transaction.database();
     int64_t databaseId = database.id();
-    uint64_t oldVersion = database.metadata().version;
 
-    // FIXME: Database versions are now of type uint64_t, but this code expected int64_t.
-    ASSERT(operation.version() > (int64_t)oldVersion);
-    database.setCurrentVersion(operation.version());
     if (!m_backingStore->updateIDBDatabaseVersion(*backingStoreTransaction, databaseId, database.metadata().version)) {
         RefPtr<IDBDatabaseError> error = IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Error writing data to stable storage when updating version.");
-        operation.callbacks()->onError(error);
         ASYNC_COMPLETION_CALLBACK_WITH_ARG(completionCallback, error);
         return;
     }
-    ASSERT(!database.hasPendingSecondHalfOpen());
-    database.setPendingSecondHalfOpen(IDBPendingOpenCall::create(*operation.callbacks(), *operation.databaseCallbacks(), transaction.id(), operation.version()));
-    operation.callbacks()->onUpgradeNeeded(oldVersion, &database, database.metadata());
 
     ASYNC_COMPLETION_CALLBACK_WITH_NULL_ARG(completionCallback);
 }
index b201f1a..8ba44fb 100644 (file)
@@ -1,3 +1,70 @@
+2013-12-25  Brady Eidson  <beidson@apple.com>
+
+        DatabaseProcess: Implement version changing
+        https://bugs.webkit.org/show_bug.cgi?id=126099
+
+        Reviewed by Sam Weinig.
+
+        * DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.cpp:
+        (WebKit::DatabaseProcessIDBConnection::getOrEstablishIDBDatabaseMetadata): Add logging.
+        (WebKit::DatabaseProcessIDBConnection::openTransaction): Ditto.
+        (WebKit::DatabaseProcessIDBConnection::beginTransaction): Ditto.
+        (WebKit::DatabaseProcessIDBConnection::commitTransaction): Ditto.
+        (WebKit::DatabaseProcessIDBConnection::resetTransaction): Ditto.
+        (WebKit::DatabaseProcessIDBConnection::rollbackTransaction): Ditto.
+        (WebKit::DatabaseProcessIDBConnection::changeDatabaseVersion): Implement this!
+        * DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.h:
+        * DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.messages.in:
+
+        * DatabaseProcess/IndexedDB/UniqueIDBDatabase.cpp:
+        (WebKit::UniqueIDBDatabase::shutdown): Clean up all requests, and also cleanup the backing store
+          on the database queue.
+        (WebKit::UniqueIDBDatabase::shutdownBackingStore): Shutdown the backing store.
+        (WebKit::UniqueIDBDatabase::didShutdownBackingStore):
+        (WebKit::UniqueIDBDatabase::changeDatabaseVersion): Pass along the new version to the database queue.
+        (WebKit::UniqueIDBDatabase::didChangeDatabaseVersion):
+        (WebKit::UniqueIDBDatabase::changeDatabaseVersionInBackingStore): Set the new version in the backing store.
+        (WebKit::UniqueIDBDatabase::postMainThreadTask): Add a ref() to keep the database alive incase it is being
+          shutdown on the main thread.
+        (WebKit::UniqueIDBDatabase::performNextMainThreadTask): Balance the ref() from postMainThreadTask, and
+          accept an empty mainThreadTask queue.
+        * DatabaseProcess/IndexedDB/UniqueIDBDatabase.h:
+
+        * DatabaseProcess/IndexedDB/UniqueIDBDatabaseBackingStore.h: Add changeDatabaseVersion.
+
+        Flesh out SQLiteIDBTransaction to actually operation on a SQLiteTransaction in a real SQLiteDatabase:
+        * DatabaseProcess/IndexedDB/sqlite/SQLiteIDBTransaction.cpp:
+        (WebKit::SQLiteIDBTransaction::SQLiteIDBTransaction):
+        (WebKit::SQLiteIDBTransaction::~SQLiteIDBTransaction):
+        (WebKit::SQLiteIDBTransaction::begin):
+        (WebKit::SQLiteIDBTransaction::commit):
+        (WebKit::SQLiteIDBTransaction::reset):
+        (WebKit::SQLiteIDBTransaction::rollback):
+        (WebKit::SQLiteIDBTransaction::inProgress):
+        * DatabaseProcess/IndexedDB/sqlite/SQLiteIDBTransaction.h:
+        (WebKit::SQLiteIDBTransaction::create):
+        (WebKit::SQLiteIDBTransaction::mode):
+
+        Rename m_metadataDB to m_sqliteDB, 
+        * DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.cpp:
+        (WebKit::UniqueIDBDatabaseBackingStoreSQLite::createAndPopulateInitialMetadata):
+        (WebKit::UniqueIDBDatabaseBackingStoreSQLite::extractExistingMetadata):
+        (WebKit::UniqueIDBDatabaseBackingStoreSQLite::openSQLiteDatabaseAtPath): Disable threading checks on the DB
+          as work queues can change threads.
+        (WebKit::UniqueIDBDatabaseBackingStoreSQLite::getOrEstablishMetadata):
+        (WebKit::UniqueIDBDatabaseBackingStoreSQLite::establishTransaction):
+        (WebKit::UniqueIDBDatabaseBackingStoreSQLite::beginTransaction):
+        (WebKit::UniqueIDBDatabaseBackingStoreSQLite::changeDatabaseVersion): After validating the transaction, actually
+          update the version number on disk.
+        * DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.h:
+
+        * WebProcess/Databases/IndexedDB/WebIDBServerConnection.cpp:
+        (WebKit::WebIDBServerConnection::~WebIDBServerConnection): Make sure to abort in-flight requests.
+        (WebKit::WebIDBServerConnection::changeDatabaseVersion): 
+        (WebKit::WebIDBServerConnection::didChangeDatabaseVersion):
+        * WebProcess/Databases/IndexedDB/WebIDBServerConnection.h:
+        * WebProcess/Databases/IndexedDB/WebIDBServerConnection.messages.in:
+
 2013-12-25  Martin Robinson  <mrobinson@igalia.com>
 
         [GTK] [CMake] Fix CMake style errors in Source/WebKit2/PlatformGTK.cmake
index 97713f5..887d6d3 100644 (file)
@@ -31,6 +31,7 @@
 #include "DatabaseProcess.h"
 #include "DatabaseToWebProcessConnection.h"
 #include "IDBTransactionIdentifier.h"
+#include "Logging.h"
 #include "UniqueIDBDatabase.h"
 #include "WebCoreArgumentCoders.h"
 #include "WebIDBServerConnectionMessages.h"
@@ -68,6 +69,8 @@ void DatabaseProcessIDBConnection::getOrEstablishIDBDatabaseMetadata(uint64_t re
 {
     ASSERT(m_uniqueIDBDatabase);
 
+    LOG(IDB, "DatabaseProcess getOrEstablishIDBDatabaseMetadata request ID %llu", requestID);
+
     RefPtr<DatabaseProcessIDBConnection> connection(this);
     m_uniqueIDBDatabase->getOrEstablishIDBDatabaseMetadata([connection, requestID](bool success, const IDBDatabaseMetadata& metadata) {
         connection->send(Messages::WebIDBServerConnection::DidGetOrEstablishIDBDatabaseMetadata(requestID, success, metadata));
@@ -78,6 +81,8 @@ void DatabaseProcessIDBConnection::openTransaction(uint64_t requestID, int64_t t
 {
     ASSERT(m_uniqueIDBDatabase);
 
+    LOG(IDB, "DatabaseProcess openTransaction request ID %llu", requestID);
+
     if (intMode > IndexedDB::TransactionModeMaximum) {
         send(Messages::WebIDBServerConnection::DidOpenTransaction(requestID, false));
         return;
@@ -94,6 +99,8 @@ void DatabaseProcessIDBConnection::beginTransaction(uint64_t requestID, int64_t
 {
     ASSERT(m_uniqueIDBDatabase);
 
+    LOG(IDB, "DatabaseProcess beginTransaction request ID %llu", requestID);
+
     RefPtr<DatabaseProcessIDBConnection> connection(this);
     m_uniqueIDBDatabase->beginTransaction(IDBTransactionIdentifier(*this, transactionID), [connection, requestID](bool success) {
         connection->send(Messages::WebIDBServerConnection::DidBeginTransaction(requestID, success));
@@ -104,6 +111,8 @@ void DatabaseProcessIDBConnection::commitTransaction(uint64_t requestID, int64_t
 {
     ASSERT(m_uniqueIDBDatabase);
 
+    LOG(IDB, "DatabaseProcess commitTransaction request ID %llu", requestID);
+
     RefPtr<DatabaseProcessIDBConnection> connection(this);
     m_uniqueIDBDatabase->commitTransaction(IDBTransactionIdentifier(*this, transactionID), [connection, requestID](bool success) {
         connection->send(Messages::WebIDBServerConnection::DidCommitTransaction(requestID, success));
@@ -114,6 +123,8 @@ void DatabaseProcessIDBConnection::resetTransaction(uint64_t requestID, int64_t
 {
     ASSERT(m_uniqueIDBDatabase);
 
+    LOG(IDB, "DatabaseProcess resetTransaction request ID %llu", requestID);
+
     RefPtr<DatabaseProcessIDBConnection> connection(this);
     m_uniqueIDBDatabase->resetTransaction(IDBTransactionIdentifier(*this, transactionID), [connection, requestID](bool success) {
         connection->send(Messages::WebIDBServerConnection::DidResetTransaction(requestID, success));
@@ -124,12 +135,26 @@ void DatabaseProcessIDBConnection::rollbackTransaction(uint64_t requestID, int64
 {
     ASSERT(m_uniqueIDBDatabase);
 
+    LOG(IDB, "DatabaseProcess rollbackTransaction request ID %llu", requestID);
+
     RefPtr<DatabaseProcessIDBConnection> connection(this);
     m_uniqueIDBDatabase->rollbackTransaction(IDBTransactionIdentifier(*this, transactionID), [connection, requestID](bool success) {
         connection->send(Messages::WebIDBServerConnection::DidRollbackTransaction(requestID, success));
     });
 }
 
+void DatabaseProcessIDBConnection::changeDatabaseVersion(uint64_t requestID, int64_t transactionID, uint64_t newVersion)
+{
+    ASSERT(m_uniqueIDBDatabase);
+
+    LOG(IDB, "DatabaseProcess changeDatabaseVersion request ID %llu, new version %llu", requestID, newVersion);
+
+    RefPtr<DatabaseProcessIDBConnection> connection(this);
+    m_uniqueIDBDatabase->changeDatabaseVersion(IDBTransactionIdentifier(*this, transactionID), newVersion, [connection, requestID](bool success) {
+        connection->send(Messages::WebIDBServerConnection::DidChangeDatabaseVersion(requestID, success));
+    });
+}
+
 CoreIPC::Connection* DatabaseProcessIDBConnection::messageSenderConnection()
 {
     return m_connection->connection();
index a283063..ad62eb7 100644 (file)
@@ -68,6 +68,8 @@ private:
     void commitTransaction(uint64_t requestID, int64_t transactionID);
     void resetTransaction(uint64_t requestID, int64_t transactionID);
     void rollbackTransaction(uint64_t requestID, int64_t transactionID);
+    void changeDatabaseVersion(uint64_t requestID, int64_t transactionID, uint64_t newVersion);
+
 
     Ref<DatabaseToWebProcessConnection> m_connection;
     uint64_t m_serverConnectionIdentifier;
index 0b8e16d..da6e524 100644 (file)
@@ -31,6 +31,8 @@ messages -> DatabaseProcessIDBConnection LegacyReceiver {
     CommitTransaction(uint64_t requestID, int64_t transactionID)
     ResetTransaction(uint64_t requestID, int64_t transactionID)
     RollbackTransaction(uint64_t requestID, int64_t transactionID)
+    
+    ChangeDatabaseVersion(uint64_t requestID, int64_t transactionID, uint64_t newVersion)
 }
 
 #endif // ENABLE(INDEXED_DATABASE) && ENABLE(DATABASE_PROCESS)
index 2ed7a3c..ae16f9d 100644 (file)
@@ -122,10 +122,36 @@ void UniqueIDBDatabase::shutdown()
         m_mainThreadTasks.clear();
     }
 
-    while (!m_pendingMetadataRequests.isEmpty()) {
-        auto request = m_pendingMetadataRequests.takeFirst();
-        request->requestAborted();
-    }
+    for (const auto& it : m_pendingMetadataRequests)
+        it->requestAborted();
+
+    for (const auto& it : m_pendingTransactionRequests)
+        it.value->requestAborted();
+
+    for (const auto& it : m_pendingDatabaseTasks)
+        it.value->requestAborted();
+        
+    // Balanced by an adoptRef in ::didShutdownBackingStore()
+    ref();
+
+    DatabaseProcess::shared().queue().dispatch(bind(&UniqueIDBDatabase::shutdownBackingStore, this));
+}
+
+void UniqueIDBDatabase::shutdownBackingStore()
+{
+    ASSERT(!isMainThread());
+    if (m_backingStore)
+        m_backingStore.clear();
+
+    RunLoop::main()->dispatch(bind(&UniqueIDBDatabase::didShutdownBackingStore, this));
+}
+
+void UniqueIDBDatabase::didShutdownBackingStore()
+{
+    ASSERT(isMainThread());
+
+    // Balanced by a ref in ::shutdown()
+    RefPtr<UniqueIDBDatabase> protector(adoptRef(this));
 }
 
 void UniqueIDBDatabase::getOrEstablishIDBDatabaseMetadata(std::function<void(bool, const IDBDatabaseMetadata&)> completionCallback)
@@ -258,6 +284,41 @@ void UniqueIDBDatabase::didCompleteTransactionOperation(const IDBTransactionIden
     request->completeRequest(success);
 }
 
+void UniqueIDBDatabase::changeDatabaseVersion(const IDBTransactionIdentifier& identifier, uint64_t newVersion, std::function<void(bool)> successCallback)
+{
+    ASSERT(isMainThread());
+
+    if (!m_acceptingNewRequests) {
+        successCallback(false);
+        return;
+    }
+
+    uint64_t oldVersion = m_metadata->version;
+    m_metadata->version = newVersion;
+
+    RefPtr<AsyncRequest> request = AsyncRequestImpl<bool>::create([this, oldVersion, successCallback](bool success) {
+        if (!success)
+            m_metadata->version = oldVersion;
+        successCallback(success);
+    }, [this, oldVersion, successCallback]() {
+        m_metadata->version = oldVersion;
+        successCallback(false);
+    });
+
+    uint64_t requestID = request->requestID();
+    m_pendingDatabaseTasks.add(requestID, request.release());
+
+    postDatabaseTask(createAsyncTask(*this, &UniqueIDBDatabase::changeDatabaseVersionInBackingStore, requestID, identifier, newVersion));
+}
+
+void UniqueIDBDatabase::didChangeDatabaseVersion(uint64_t requestID, bool success)
+{
+    RefPtr<AsyncRequest> request = m_pendingDatabaseTasks.take(requestID);
+    ASSERT(request);
+
+    request->completeRequest(success);
+}
+
 void UniqueIDBDatabase::openBackingStoreTransaction(const IDBTransactionIdentifier& identifier, const Vector<int64_t>& objectStoreIDs, WebCore::IndexedDB::TransactionMode mode)
 {
     ASSERT(!isMainThread());
@@ -308,6 +369,16 @@ void UniqueIDBDatabase::rollbackBackingStoreTransaction(const IDBTransactionIden
     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didCompleteTransactionOperation, identifier, success));
 }
 
+void UniqueIDBDatabase::changeDatabaseVersionInBackingStore(uint64_t requestID, const IDBTransactionIdentifier& identifier, uint64_t newVersion)
+{
+    ASSERT(!isMainThread());
+    ASSERT(m_backingStore);
+
+    bool success = m_backingStore->changeDatabaseVersion(identifier, newVersion);
+
+    postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didChangeDatabaseVersion, requestID, success));
+}
+
 String UniqueIDBDatabase::absoluteDatabaseDirectory() const
 {
     ASSERT(isMainThread());
@@ -325,6 +396,8 @@ void UniqueIDBDatabase::postMainThreadTask(std::unique_ptr<AsyncTask> task)
 
     m_mainThreadTasks.append(std::move(task));
 
+    // Balanced by an adoptRef() in ::performNextMainThreadTask
+    ref();
     RunLoop::main()->dispatch(bind(&UniqueIDBDatabase::performNextMainThreadTask, this));
 }
 
@@ -332,10 +405,17 @@ void UniqueIDBDatabase::performNextMainThreadTask()
 {
     ASSERT(isMainThread());
 
+    // Balanced by a ref() in ::postMainThreadTask
+    RefPtr<UniqueIDBDatabase> protector(adoptRef(this));
+
     std::unique_ptr<AsyncTask> task;
     {
         MutexLocker locker(m_mainThreadTaskMutex);
-        ASSERT(!m_mainThreadTasks.isEmpty());
+
+        // This database might be shutting down, in which case the task queue might be empty.
+        if (m_mainThreadTasks.isEmpty())
+            return;
+
         task = m_mainThreadTasks.takeFirst();
     }
 
index aa8cfb1..a2a57cd 100644 (file)
@@ -73,6 +73,8 @@ public:
     void resetTransaction(const IDBTransactionIdentifier&, std::function<void(bool)> successCallback);
     void rollbackTransaction(const IDBTransactionIdentifier&, std::function<void(bool)> successCallback);
 
+    void changeDatabaseVersion(const IDBTransactionIdentifier&, uint64_t newVersion, std::function<void(bool)> successCallback);
+
 private:
     UniqueIDBDatabase(const UniqueIDBDatabaseIdentifier&);
 
@@ -110,15 +112,22 @@ private:
     void resetBackingStoreTransaction(const IDBTransactionIdentifier&);
     void rollbackBackingStoreTransaction(const IDBTransactionIdentifier&);
 
+    void changeDatabaseVersionInBackingStore(uint64_t requestID, const IDBTransactionIdentifier&, uint64_t newVersion);
+
+    void shutdownBackingStore();
+
     // Callbacks from the database workqueue thread, to be performed on the main thread only
     void performNextMainThreadTask();
     void didOpenBackingStoreAndReadMetadata(const WebCore::IDBDatabaseMetadata&, bool success);
     void didCompleteTransactionOperation(const IDBTransactionIdentifier&, bool success);
+    void didChangeDatabaseVersion(uint64_t requestID, bool success);
+    void didShutdownBackingStore();
 
     bool m_acceptingNewRequests;
 
     Deque<RefPtr<AsyncRequest>> m_pendingMetadataRequests;
     HashMap<IDBTransactionIdentifier, RefPtr<AsyncRequest>> m_pendingTransactionRequests;
+    HashMap<uint64_t, RefPtr<AsyncRequest>> m_pendingDatabaseTasks;
 
     std::unique_ptr<WebCore::IDBDatabaseMetadata> m_metadata;
     bool m_didGetMetadataFromBackingStore;
index 9297e14..de0c661 100644 (file)
@@ -50,6 +50,8 @@ public:
     virtual bool commitTransaction(const IDBTransactionIdentifier&) = 0;
     virtual bool resetTransaction(const IDBTransactionIdentifier&) = 0;
     virtual bool rollbackTransaction(const IDBTransactionIdentifier&) = 0;
+
+    virtual bool changeDatabaseVersion(const IDBTransactionIdentifier&, uint64_t newVersion) = 0;
 };
 
 } // namespace WebKit
index 1c70386..1d3e492 100644 (file)
 
 #if ENABLE(INDEXED_DATABASE) && ENABLE(DATABASE_PROCESS)
 
+#include <WebCore/IndexedDB.h>
+#include <WebCore/SQLiteTransaction.h>
+
+using namespace WebCore;
+
 namespace WebKit {
 
-SQLiteIDBTransaction::SQLiteIDBTransaction(const IDBTransactionIdentifier& identifier)
+SQLiteIDBTransaction::SQLiteIDBTransaction(const IDBTransactionIdentifier& identifier, IndexedDB::TransactionMode mode)
     : m_identifier(identifier)
+    , m_mode(mode)
+{
+}
+
+SQLiteIDBTransaction::~SQLiteIDBTransaction()
 {
+    if (inProgress())
+        m_sqliteTransaction->rollback();
 }
 
-bool SQLiteIDBTransaction::begin()
+
+bool SQLiteIDBTransaction::begin(SQLiteDatabase& database)
 {
-    return false;
+    ASSERT(!m_sqliteTransaction);
+    m_sqliteTransaction = std::make_unique<SQLiteTransaction>(database, m_mode == IndexedDB::TransactionMode::ReadOnly);
+
+    m_sqliteTransaction->begin();
+
+    return m_sqliteTransaction->inProgress();
 }
 
 bool SQLiteIDBTransaction::commit()
 {
-    return false;
+    ASSERT(m_sqliteTransaction);
+    if (!m_sqliteTransaction->inProgress())
+        return false;
+
+    m_sqliteTransaction->commit();
+
+    return !m_sqliteTransaction->inProgress();
 }
 
 bool SQLiteIDBTransaction::reset()
 {
-    return false;
+    m_sqliteTransaction = nullptr;
+
+    return true;
 }
 
 bool SQLiteIDBTransaction::rollback()
 {
-    return false;
+    ASSERT(m_sqliteTransaction);
+    if (m_sqliteTransaction->inProgress())
+        m_sqliteTransaction->rollback();
+
+    return true;
+}
+
+bool SQLiteIDBTransaction::inProgress() const
+{
+    return m_sqliteTransaction && m_sqliteTransaction->inProgress();
 }
 
 } // namespace WebKit
index 1de6d14..f6f8c60 100644 (file)
 #include "IDBTransactionIdentifier.h"
 #include <wtf/Noncopyable.h>
 
+namespace WebCore {
+
+class SQLiteDatabase;
+class SQLiteTransaction;
+
+namespace IndexedDB {
+enum class TransactionMode;
+}
+
+}
+
 namespace WebKit {
 
 class SQLiteIDBTransaction {
     WTF_MAKE_NONCOPYABLE(SQLiteIDBTransaction);
 public:
-    static std::unique_ptr<SQLiteIDBTransaction> create(const IDBTransactionIdentifier& identifier)
+    static std::unique_ptr<SQLiteIDBTransaction> create(const IDBTransactionIdentifier& identifier, WebCore::IndexedDB::TransactionMode mode)
     {
-        return std::unique_ptr<SQLiteIDBTransaction>(new SQLiteIDBTransaction(identifier));
+        return std::unique_ptr<SQLiteIDBTransaction>(new SQLiteIDBTransaction(identifier, mode));
     }
 
+    ~SQLiteIDBTransaction();
+
     const IDBTransactionIdentifier& identifier() const { return m_identifier; }
 
-    bool begin();
+    bool begin(WebCore::SQLiteDatabase&);
     bool commit();
     bool reset();
     bool rollback();
 
+    WebCore::IndexedDB::TransactionMode mode() const { return m_mode; }
+    bool inProgress() const;
+
 private:
-    SQLiteIDBTransaction(const IDBTransactionIdentifier&);
+    SQLiteIDBTransaction(const IDBTransactionIdentifier&, WebCore::IndexedDB::TransactionMode);
 
     IDBTransactionIdentifier m_identifier;
+    WebCore::IndexedDB::TransactionMode m_mode;
+
+    std::unique_ptr<WebCore::SQLiteTransaction> m_sqliteTransaction;
 };
 
 } // namespace WebKit
index 72d83f5..1903758 100644 (file)
@@ -66,44 +66,44 @@ UniqueIDBDatabaseBackingStoreSQLite::~UniqueIDBDatabaseBackingStoreSQLite()
 std::unique_ptr<WebCore::IDBDatabaseMetadata> UniqueIDBDatabaseBackingStoreSQLite::createAndPopulateInitialMetadata()
 {
     ASSERT(!isMainThread());
-    ASSERT(m_metadataDB);
-    ASSERT(m_metadataDB->isOpen());
+    ASSERT(m_sqliteDB);
+    ASSERT(m_sqliteDB->isOpen());
 
-    if (!m_metadataDB->executeCommand("CREATE TABLE IDBDatabaseInfo (key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE, value TEXT NOT NULL ON CONFLICT FAIL);")) {
-        LOG_ERROR("Could not create IDBDatabaseInfo table in database (%i) - %s", m_metadataDB->lastError(), m_metadataDB->lastErrorMsg());
-        m_metadataDB = nullptr;
+    if (!m_sqliteDB->executeCommand("CREATE TABLE IDBDatabaseInfo (key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE, value TEXT NOT NULL ON CONFLICT FAIL);")) {
+        LOG_ERROR("Could not create IDBDatabaseInfo table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
+        m_sqliteDB = nullptr;
         return nullptr;
     }
 
     {
-        SQLiteStatement sql(*m_metadataDB, "INSERT INTO IDBDatabaseInfo VALUES ('MetadataVersion', ?);");
+        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO IDBDatabaseInfo VALUES ('MetadataVersion', ?);"));
         if (sql.prepare() != SQLResultOk
             || sql.bindInt(1, currentMetadataVersion) != SQLResultOk
             || sql.step() != SQLResultDone) {
-            LOG_ERROR("Could not insert database metadata version into IDBDatabaseInfo table (%i) - %s", m_metadataDB->lastError(), m_metadataDB->lastErrorMsg());
-            m_metadataDB = nullptr;
+            LOG_ERROR("Could not insert database metadata version into IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
+            m_sqliteDB = nullptr;
             return nullptr;
         }
     }
     {
-        SQLiteStatement sql(*m_metadataDB, "INSERT INTO IDBDatabaseInfo VALUES ('DatabaseName', ?);");
+        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO IDBDatabaseInfo VALUES ('DatabaseName', ?);"));
         if (sql.prepare() != SQLResultOk
             || sql.bindText(1, m_identifier.databaseName()) != SQLResultOk
             || sql.step() != SQLResultDone) {
-            LOG_ERROR("Could not insert database name into IDBDatabaseInfo table (%i) - %s", m_metadataDB->lastError(), m_metadataDB->lastErrorMsg());
-            m_metadataDB = nullptr;
+            LOG_ERROR("Could not insert database name into IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
+            m_sqliteDB = nullptr;
             return nullptr;
         }
     }
     {
         // Database versions are defined to be a uin64_t in the spec but sqlite3 doesn't support native binding of unsigned integers.
         // Therefore we'll store the version as a String.
-        SQLiteStatement sql(*m_metadataDB, "INSERT INTO IDBDatabaseInfo VALUES ('DatabaseVersion', ?);");
+        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO IDBDatabaseInfo VALUES ('DatabaseVersion', ?);"));
         if (sql.prepare() != SQLResultOk
             || sql.bindText(1, String::number(0)) != SQLResultOk
             || sql.step() != SQLResultDone) {
-            LOG_ERROR("Could not insert default version into IDBDatabaseInfo table (%i) - %s", m_metadataDB->lastError(), m_metadataDB->lastErrorMsg());
-            m_metadataDB = nullptr;
+            LOG_ERROR("Could not insert default version into IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
+            m_sqliteDB = nullptr;
             return nullptr;
         }
     }
@@ -119,20 +119,20 @@ std::unique_ptr<WebCore::IDBDatabaseMetadata> UniqueIDBDatabaseBackingStoreSQLit
 std::unique_ptr<IDBDatabaseMetadata> UniqueIDBDatabaseBackingStoreSQLite::extractExistingMetadata()
 {
     ASSERT(!isMainThread());
-    ASSERT(m_metadataDB);
+    ASSERT(m_sqliteDB);
 
-    if (!m_metadataDB->tableExists("IDBDatabaseInfo"))
+    if (!m_sqliteDB->tableExists(ASCIILiteral("IDBDatabaseInfo")))
         return nullptr;
 
     auto metadata = std::make_unique<IDBDatabaseMetadata>();
     {
-        SQLiteStatement sql(*m_metadataDB, "SELECT value FROM IDBDatabaseInfo WHERE key = 'MetadataVersion';");
+        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT value FROM IDBDatabaseInfo WHERE key = 'MetadataVersion';"));
         if (sql.isColumnNull(0))
             return nullptr;
         metadata->version = sql.getColumnInt(0);
     }
     {
-        SQLiteStatement sql(*m_metadataDB, "SELECT value FROM IDBDatabaseInfo WHERE key = 'DatabaseName';");
+        SQLiteStatement sql(*m_sqliteDB, "SELECT value FROM IDBDatabaseInfo WHERE key = 'DatabaseName';");
         if (sql.isColumnNull(0))
             return nullptr;
         metadata->name = sql.getColumnText(0);
@@ -142,7 +142,7 @@ std::unique_ptr<IDBDatabaseMetadata> UniqueIDBDatabaseBackingStoreSQLite::extrac
         }
     }
     {
-        SQLiteStatement sql(*m_metadataDB, "SELECT value FROM IDBDatabaseInfo WHERE key = 'DatabaseVersion';");
+        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("SELECT value FROM IDBDatabaseInfo WHERE key = 'DatabaseVersion';"));
         if (sql.isColumnNull(0))
             return nullptr;
         String stringVersion = sql.getColumnText(0);
@@ -168,6 +168,10 @@ std::unique_ptr<SQLiteDatabase> UniqueIDBDatabaseBackingStoreSQLite::openSQLiteD
         return nullptr;
     }
 
+    // Since a WorkQueue isn't bound to a specific thread, we have to disable threading checks
+    // even though we never access the database from different threads simultaneously.
+    sqliteDatabase->disableThreadingChecks();
+
     return sqliteDatabase;
 }
 
@@ -175,9 +179,9 @@ std::unique_ptr<IDBDatabaseMetadata> UniqueIDBDatabaseBackingStoreSQLite::getOrE
 {
     ASSERT(!isMainThread());
 
-    String metadataDBFilename = pathByAppendingComponent(m_absoluteDatabaseDirectory, "IDBMetadata.sqlite3");
-    m_metadataDB = openSQLiteDatabaseAtPath(metadataDBFilename);
-    if (!m_metadataDB)
+    String dbFilename = pathByAppendingComponent(m_absoluteDatabaseDirectory, "IndexedDB.sqlite3");
+    m_sqliteDB = openSQLiteDatabaseAtPath(dbFilename);
+    if (!m_sqliteDB)
         return nullptr;
 
     std::unique_ptr<IDBDatabaseMetadata> metadata = extractExistingMetadata();
@@ -185,7 +189,7 @@ std::unique_ptr<IDBDatabaseMetadata> UniqueIDBDatabaseBackingStoreSQLite::getOrE
         metadata = createAndPopulateInitialMetadata();
 
     if (!metadata)
-        LOG_ERROR("Unable to establish IDB database at path '%s'", metadataDBFilename.utf8().data());
+        LOG_ERROR("Unable to establish IDB database at path '%s'", dbFilename.utf8().data());
 
     // The database id is a runtime concept and doesn't need to be stored in the metadata database.
     metadata->id = generateDatabaseId();
@@ -193,11 +197,11 @@ std::unique_ptr<IDBDatabaseMetadata> UniqueIDBDatabaseBackingStoreSQLite::getOrE
     return metadata;
 }
 
-bool UniqueIDBDatabaseBackingStoreSQLite::establishTransaction(const IDBTransactionIdentifier& identifier, const Vector<int64_t>&, WebCore::IndexedDB::TransactionMode)
+bool UniqueIDBDatabaseBackingStoreSQLite::establishTransaction(const IDBTransactionIdentifier& identifier, const Vector<int64_t>&, WebCore::IndexedDB::TransactionMode mode)
 {
     ASSERT(!isMainThread());
 
-    if (!m_transactions.add(identifier, SQLiteIDBTransaction::create(identifier)).isNewEntry) {
+    if (!m_transactions.add(identifier, SQLiteIDBTransaction::create(identifier, mode)).isNewEntry) {
         LOG_ERROR("Attempt to establish transaction identifier that already exists");
         return false;
     }
@@ -215,7 +219,7 @@ bool UniqueIDBDatabaseBackingStoreSQLite::beginTransaction(const IDBTransactionI
         return false;
     }
 
-    return transaction->begin();
+    return transaction->begin(*m_sqliteDB);
 }
 
 bool UniqueIDBDatabaseBackingStoreSQLite::commitTransaction(const IDBTransactionIdentifier& identifier)
@@ -257,6 +261,35 @@ bool UniqueIDBDatabaseBackingStoreSQLite::rollbackTransaction(const IDBTransacti
     return transaction->rollback();
 }
 
+bool UniqueIDBDatabaseBackingStoreSQLite::changeDatabaseVersion(const IDBTransactionIdentifier& identifier, uint64_t newVersion)
+{
+    ASSERT(!isMainThread());
+    ASSERT(m_sqliteDB);
+    ASSERT(m_sqliteDB->isOpen());
+
+    SQLiteIDBTransaction* transaction = m_transactions.get(identifier);
+    if (!transaction || !transaction->inProgress()) {
+        LOG_ERROR("Attempt to change database version with an establish, in-progress transaction");
+        return false;
+    }
+    if (transaction->mode() != IndexedDB::TransactionMode::VersionChange) {
+        LOG_ERROR("Attempt to change database version during a non version-change transaction");
+        return false;
+    }
+
+    {
+        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("UPDATE IDBDatabaseInfo SET value = ? where key = 'DatabaseVersion';"));
+        if (sql.prepare() != SQLResultOk
+            || sql.bindText(1, String::number(newVersion)) != SQLResultOk
+            || sql.step() != SQLResultDone) {
+            LOG_ERROR("Could not update database version in IDBDatabaseInfo table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
+            return false;
+        }
+    }
+
+    return true;
+}
+
 } // namespace WebKit
 
 #endif // ENABLE(INDEXED_DATABASE) && ENABLE(DATABASE_PROCESS)
index 4efd3d0..b35677e 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "UniqueIDBDatabase.h" 
 #include "UniqueIDBDatabaseBackingStore.h"
+#include <wtf/OwnPtr.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/text/WTFString.h>
 
@@ -59,6 +60,8 @@ public:
     virtual bool resetTransaction(const IDBTransactionIdentifier&) OVERRIDE;
     virtual bool rollbackTransaction(const IDBTransactionIdentifier&) OVERRIDE;
 
+    virtual bool changeDatabaseVersion(const IDBTransactionIdentifier&, uint64_t newVersion) OVERRIDE;
+
 private:
     UniqueIDBDatabaseBackingStoreSQLite(const UniqueIDBDatabaseIdentifier&, const String& databaseDirectory);
 
@@ -69,7 +72,7 @@ private:
     UniqueIDBDatabaseIdentifier m_identifier;
     String m_absoluteDatabaseDirectory;
 
-    std::unique_ptr<WebCore::SQLiteDatabase> m_metadataDB;
+    std::unique_ptr<WebCore::SQLiteDatabase> m_sqliteDB;
 
     HashMap<IDBTransactionIdentifier, std::unique_ptr<SQLiteIDBTransaction>> m_transactions;
 };
index 6bb0676..aea65ca 100644 (file)
@@ -70,6 +70,9 @@ WebIDBServerConnection::WebIDBServerConnection(const String& databaseName, const
 WebIDBServerConnection::~WebIDBServerConnection()
 {
     WebProcess::shared().webToDatabaseProcessConnection()->removeWebIDBServerConnection(*this);
+
+    for (const auto& it : m_serverRequests)
+        it.value->requestAborted();
 }
 
 bool WebIDBServerConnection::isClosed()
@@ -295,8 +298,33 @@ void WebIDBServerConnection::deleteObjectStore(IDBTransactionBackend&, const Del
 {
 }
 
-void WebIDBServerConnection::changeDatabaseVersion(IDBTransactionBackend&, const IDBDatabaseBackend::VersionChangeOperation&, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback)
+void WebIDBServerConnection::changeDatabaseVersion(IDBTransactionBackend&, const IDBDatabaseBackend::VersionChangeOperation& operation, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback)
 {
+    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<PassRefPtr<IDBDatabaseError>>::create(completionCallback);
+
+    serverRequest->setAbortHandler([completionCallback]() {
+        completionCallback(IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured changing database version"));
+    });
+
+    uint64_t requestID = serverRequest->requestID();
+    ASSERT(!m_serverRequests.contains(requestID));
+    m_serverRequests.add(requestID, serverRequest.release());
+
+    LOG(IDB, "WebProcess changeDatabaseVersion request ID %llu", requestID);
+
+    send(Messages::DatabaseProcessIDBConnection::ChangeDatabaseVersion(requestID, operation.transaction()->id(), static_cast<uint64_t>(operation.version())));
+}
+
+void WebIDBServerConnection::didChangeDatabaseVersion(uint64_t requestID, bool success)
+{
+    LOG(IDB, "WebProcess didChangeDatabaseVersion request ID %llu", requestID);
+
+    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
+
+    if (!serverRequest)
+        return;
+
+    serverRequest->completeRequest(success ? nullptr : IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured changing database version"));
 }
 
 void WebIDBServerConnection::cursorAdvance(IDBCursorBackend&, const CursorAdvanceOperation&, std::function<void()> completionCallback)
index 9783ec0..7db5af7 100644 (file)
@@ -99,6 +99,7 @@ private:
     void didCommitTransaction(uint64_t requestID, bool success);
     void didResetTransaction(uint64_t requestID, bool success);
     void didRollbackTransaction(uint64_t requestID, bool success);
+    void didChangeDatabaseVersion(uint64_t requestID, bool success);
 
     uint64_t m_serverConnectionIdentifier;
 
index 61110d0..41aaa19 100644 (file)
@@ -30,6 +30,8 @@ messages -> WebIDBServerConnection LegacyReceiver {
     DidCommitTransaction(uint64_t requestID, bool success)
     DidResetTransaction(uint64_t requestID, bool success)
     DidRollbackTransaction(uint64_t requestID, bool success)
+
+    DidChangeDatabaseVersion(uint64_t requestID, bool success)
 }
 
 #endif // ENABLE(INDEXED_DATABASE) && ENABLE(DATABASE_PROCESS)