Modern IDB: Add basic transaction committing.
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 15 Oct 2015 16:41:30 +0000 (16:41 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 15 Oct 2015 16:41:30 +0000 (16:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=150147

Reviewed by Alex Christensen.

Source/WebCore:

Test: storage/indexeddb/modern/opendatabase-versions.html

* Modules/indexeddb/IDBTransaction.h:

* Modules/indexeddb/IndexedDB.h:

* Modules/indexeddb/client/IDBConnectionToServer.cpp:
(WebCore::IDBClient::IDBConnectionToServer::commitTransaction):
(WebCore::IDBClient::IDBConnectionToServer::didCommitTransaction):
* Modules/indexeddb/client/IDBConnectionToServer.h:
* Modules/indexeddb/client/IDBConnectionToServerDelegate.h:

* Modules/indexeddb/client/IDBDatabaseImpl.cpp:
(WebCore::IDBClient::IDBDatabase::startVersionChangeTransaction):
(WebCore::IDBClient::IDBDatabase::commitTransaction):
(WebCore::IDBClient::IDBDatabase::didCommitTransaction):
(WebCore::IDBClient::IDBDatabase::didAbortTransaction):
(WebCore::IDBClient::IDBDatabase::didCommitOrAbortTransaction):
* Modules/indexeddb/client/IDBDatabaseImpl.h:

* Modules/indexeddb/client/IDBFactoryImpl.cpp:
(WebCore::IDBClient::IDBFactory::open):

* Modules/indexeddb/client/IDBOpenDBRequestImpl.cpp:
(WebCore::IDBClient::IDBOpenDBRequest::onSuccess):
* Modules/indexeddb/client/IDBOpenDBRequestImpl.h:

* Modules/indexeddb/client/IDBTransactionImpl.cpp:
(WebCore::IDBClient::IDBTransaction::IDBTransaction):
(WebCore::IDBClient::IDBTransaction::db):
(WebCore::IDBClient::IDBTransaction::hasPendingActivity):
(WebCore::IDBClient::IDBTransaction::isActive):
(WebCore::IDBClient::IDBTransaction::scheduleOperationTimer):
(WebCore::IDBClient::IDBTransaction::operationTimerFired):
(WebCore::IDBClient::IDBTransaction::commit):
(WebCore::IDBClient::IDBTransaction::didCommit):
(WebCore::IDBClient::IDBTransaction::fireOnComplete):
(WebCore::IDBClient::IDBTransaction::fireOnAbort):
(WebCore::IDBClient::IDBTransaction::enqueueEvent):
(WebCore::IDBClient::IDBTransaction::dispatchEvent):
* Modules/indexeddb/client/IDBTransactionImpl.h:
(WebCore::IDBClient::IDBTransaction::database):

* Modules/indexeddb/legacy/LegacyTransaction.cpp:
(WebCore::LegacyTransaction::db):
* Modules/indexeddb/legacy/LegacyTransaction.h:

* Modules/indexeddb/server/IDBConnectionToClient.cpp:
(WebCore::IDBServer::IDBConnectionToClient::didCommitTransaction):
* Modules/indexeddb/server/IDBConnectionToClient.h:
* Modules/indexeddb/server/IDBConnectionToClientDelegate.h:

* Modules/indexeddb/server/IDBServer.cpp:
(WebCore::IDBServer::IDBServer::registerTransaction):
(WebCore::IDBServer::IDBServer::unregisterTransaction):
(WebCore::IDBServer::IDBServer::commitTransaction):
* Modules/indexeddb/server/IDBServer.h:

* Modules/indexeddb/server/UniqueIDBDatabase.cpp:
(WebCore::IDBServer::generateUniqueCallbackIdentifier):
(WebCore::IDBServer::UniqueIDBDatabase::storeCallback):
(WebCore::IDBServer::UniqueIDBDatabase::commitTransaction):
(WebCore::IDBServer::UniqueIDBDatabase::performCommitTransaction):
(WebCore::IDBServer::UniqueIDBDatabase::didPerformCommitTransaction):
(WebCore::IDBServer::UniqueIDBDatabase::performErrorCallback):
(WebCore::IDBServer::UniqueIDBDatabase::startVersionChangeTransaction): Deleted.
* Modules/indexeddb/server/UniqueIDBDatabase.h:
(WebCore::IDBServer::UniqueIDBDatabase::server):

* Modules/indexeddb/server/UniqueIDBDatabaseConnection.cpp:
(WebCore::IDBServer::UniqueIDBDatabaseConnection::createVersionChangeTransaction):
(WebCore::IDBServer::UniqueIDBDatabaseConnection::didCommitTransaction):
* Modules/indexeddb/server/UniqueIDBDatabaseConnection.h:

* Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp:
(WebCore::IDBServer::UniqueIDBDatabaseTransaction::UniqueIDBDatabaseTransaction):
(WebCore::IDBServer::UniqueIDBDatabaseTransaction::~UniqueIDBDatabaseTransaction):
(WebCore::IDBServer::UniqueIDBDatabaseTransaction::commit):
* Modules/indexeddb/server/UniqueIDBDatabaseTransaction.h:

* Modules/indexeddb/shared/IDBDatabaseInfo.h:
(WebCore::IDBDatabaseInfo::setVersion):

* Modules/indexeddb/shared/IDBError.cpp:
(WebCore::IDBError::isolatedCopy):
* Modules/indexeddb/shared/IDBError.h:

* Modules/indexeddb/shared/IDBRequestData.h:

* Modules/indexeddb/shared/IDBResourceIdentifier.cpp:
(WebCore::IDBResourceIdentifier::isolatedCopy):
* Modules/indexeddb/shared/IDBResourceIdentifier.h:

* Modules/indexeddb/shared/InProcessIDBServer.cpp:
(WebCore::InProcessIDBServer::didCommitTransaction):
(WebCore::InProcessIDBServer::commitTransaction):
* Modules/indexeddb/shared/InProcessIDBServer.h:

* WebCore.xcodeproj/project.pbxproj:

* platform/CrossThreadCopier.cpp:
(WebCore::IDBResourceIdentifier>::copy):
(WebCore::IDBError>::copy):
* platform/CrossThreadCopier.h:

LayoutTests:

* storage/indexeddb/modern/opendatabase-versions-expected.txt: Added.
* storage/indexeddb/modern/opendatabase-versions.html: Added.

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

40 files changed:
LayoutTests/ChangeLog
LayoutTests/storage/indexeddb/modern/opendatabase-versions-expected.txt [new file with mode: 0644]
LayoutTests/storage/indexeddb/modern/opendatabase-versions.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Modules/indexeddb/IDBTransaction.h
Source/WebCore/Modules/indexeddb/IndexedDB.h
Source/WebCore/Modules/indexeddb/client/IDBConnectionToServer.cpp
Source/WebCore/Modules/indexeddb/client/IDBConnectionToServer.h
Source/WebCore/Modules/indexeddb/client/IDBConnectionToServerDelegate.h
Source/WebCore/Modules/indexeddb/client/IDBDatabaseImpl.cpp
Source/WebCore/Modules/indexeddb/client/IDBDatabaseImpl.h
Source/WebCore/Modules/indexeddb/client/IDBFactoryImpl.cpp
Source/WebCore/Modules/indexeddb/client/IDBOpenDBRequestImpl.cpp
Source/WebCore/Modules/indexeddb/client/IDBOpenDBRequestImpl.h
Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.cpp
Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.h
Source/WebCore/Modules/indexeddb/legacy/LegacyTransaction.cpp
Source/WebCore/Modules/indexeddb/legacy/LegacyTransaction.h
Source/WebCore/Modules/indexeddb/server/IDBConnectionToClient.cpp
Source/WebCore/Modules/indexeddb/server/IDBConnectionToClient.h
Source/WebCore/Modules/indexeddb/server/IDBConnectionToClientDelegate.h
Source/WebCore/Modules/indexeddb/server/IDBServer.cpp
Source/WebCore/Modules/indexeddb/server/IDBServer.h
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseConnection.cpp
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseConnection.h
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.h
Source/WebCore/Modules/indexeddb/shared/IDBDatabaseInfo.h
Source/WebCore/Modules/indexeddb/shared/IDBError.cpp
Source/WebCore/Modules/indexeddb/shared/IDBError.h
Source/WebCore/Modules/indexeddb/shared/IDBRequestData.h
Source/WebCore/Modules/indexeddb/shared/IDBResourceIdentifier.cpp
Source/WebCore/Modules/indexeddb/shared/IDBResourceIdentifier.h
Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.cpp
Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.h
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/platform/CrossThreadCopier.cpp
Source/WebCore/platform/CrossThreadCopier.h

index ddcad46..1f72411 100644 (file)
@@ -1,3 +1,13 @@
+2015-10-14  Brady Eidson  <beidson@apple.com>
+
+        Modern IDB: Add basic transaction committing.
+        https://bugs.webkit.org/show_bug.cgi?id=150147
+
+        Reviewed by Alex Christensen.
+
+        * storage/indexeddb/modern/opendatabase-versions-expected.txt: Added.
+        * storage/indexeddb/modern/opendatabase-versions.html: Added.
+
 2015-10-15  Daniel Bates  <dabates@apple.com>
 
         [iOS] DOM click event may not be dispatched when page has :active style and <input type="search">
diff --git a/LayoutTests/storage/indexeddb/modern/opendatabase-versions-expected.txt b/LayoutTests/storage/indexeddb/modern/opendatabase-versions-expected.txt
new file mode 100644 (file)
index 0000000..ebcc163
--- /dev/null
@@ -0,0 +1,9 @@
+ALERT: [object IDBOpenDBRequest] (firstPhase)
+ALERT: upgradeneeded (firstPhase): old version - 0 new version - 1
+ALERT: [object IDBTransaction]
+ALERT: Version change complete (firstPhase). Database version is now - 1
+ALERT: [object IDBOpenDBRequest] (secondPhase)
+ALERT: Successfully opened database at version 1 (secondPhase)
+ALERT: Done
+This test creates a new database with the default version, commits that versionchange transaction, and then reopens it at different versions to make sure the IDBOpenDBRequests behave appropriately.
+
diff --git a/LayoutTests/storage/indexeddb/modern/opendatabase-versions.html b/LayoutTests/storage/indexeddb/modern/opendatabase-versions.html
new file mode 100644 (file)
index 0000000..7be934c
--- /dev/null
@@ -0,0 +1,122 @@
+This test creates a new database with the default version, commits that versionchange transaction, and then reopens it at different versions to make sure the IDBOpenDBRequests behave appropriately.<br>
+<script>
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+function done()
+{
+    alert("Done");
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+var request = window.indexedDB.open("VersionTestDatabase");
+alert(request + " (firstPhase)");
+
+request.onsuccess = function()
+{
+    alert("Unexpected success (firstPhase)");
+       done();
+}
+request.onerror = function(e)
+{
+    alert("Unexpected error (firstPhase)");
+       done();
+}
+
+request.onupgradeneeded = function(e)
+{
+    alert("upgradeneeded (firstPhase): old version - " + e.oldVersion + " new version - " + e.newVersion);
+    alert(request.transaction);
+    request.transaction.oncomplete = function()
+    {
+        alert("Version change complete (firstPhase). Database version is now - " + request.transaction.db.version);
+        secondPhase();
+    }
+    request.transaction.onabort = function()
+    {
+        alert("Version change transaction unexpected abort! (firstPhase)");
+        done();
+    }
+    request.transaction.onerror = function()
+    {
+        alert("Version change transaction unexpected error! (firstPhase)");
+        done();
+    }
+}
+
+function secondPhase()
+{
+    var request = window.indexedDB.open("VersionTestDatabase", 1);
+    alert(request + " (secondPhase)");
+    request.onsuccess = function()
+    {
+        alert("Successfully opened database at version 1 (secondPhase)");
+
+        // FIXME: The following call will be used once bugs 150147-150150 are resolved.
+        // thirdPhase();
+        done();
+    }
+    request.onerror = function(e)
+    {
+        alert("Unexpected error (secondPhase)" + e);
+        done();
+    }
+    request.onupgradeneeded = function(e)
+    {
+       alert("Unexpected upgrade needed (secondPhase)" + e);
+       done();
+    }
+}
+
+function thirdPhase()
+{
+    var request = window.indexedDB.open("VersionTestDatabase", 2);
+    alert(request + " (thirdPhase)");
+    request.onsuccess = function()
+    {
+     alert("Unexpected success (thirdPhase)");
+     done();
+    }
+    request.onerror = function(e)
+    {
+     alert("Unexpected error (thirdPhase)");
+     done();
+    }
+    request.onupgradeneeded = function(e)
+    {
+        alert("upgradeneeded (thirdPhase): old version - " + e.oldVersion + " new version - " + e.newVersion);
+        alert(request.transaction);
+        request.transaction.oncomplete = function()
+        {
+            alert("Version change complete (thirdPhase). Database version is now - " + request.transaction.db.version);
+            fourthPhase();
+        }
+        request.transaction.onabort = function()
+        {
+            alert("Version change transaction unexpected abort! (thirdPhase)");
+            done();
+        }
+        request.transaction.onerror = function()
+        {
+            alert("Version change transaction unexpected error! (thirdPhase)");
+            done();
+        }
+    } 
+}
+
+function fourthPhase()
+{
+    try {
+        // We've upgraded to version 2, so version 1 should not be openable.
+        window.indexedDB.open("VersionTestDatabase", 1);
+    } catch (e) {
+        alert("Caught exception " + e);
+    }
+    done();
+}
+
+</script>
index 80eb433..225dfb1 100644 (file)
@@ -1,3 +1,115 @@
+2015-10-14  Brady Eidson  <beidson@apple.com>
+
+        Modern IDB: Add basic transaction committing.
+        https://bugs.webkit.org/show_bug.cgi?id=150147
+
+        Reviewed by Alex Christensen.
+
+        Test: storage/indexeddb/modern/opendatabase-versions.html
+
+        * Modules/indexeddb/IDBTransaction.h:
+
+        * Modules/indexeddb/IndexedDB.h:
+
+        * Modules/indexeddb/client/IDBConnectionToServer.cpp:
+        (WebCore::IDBClient::IDBConnectionToServer::commitTransaction):
+        (WebCore::IDBClient::IDBConnectionToServer::didCommitTransaction):
+        * Modules/indexeddb/client/IDBConnectionToServer.h:
+        * Modules/indexeddb/client/IDBConnectionToServerDelegate.h:
+
+        * Modules/indexeddb/client/IDBDatabaseImpl.cpp:
+        (WebCore::IDBClient::IDBDatabase::startVersionChangeTransaction):
+        (WebCore::IDBClient::IDBDatabase::commitTransaction):
+        (WebCore::IDBClient::IDBDatabase::didCommitTransaction):
+        (WebCore::IDBClient::IDBDatabase::didAbortTransaction):
+        (WebCore::IDBClient::IDBDatabase::didCommitOrAbortTransaction):
+        * Modules/indexeddb/client/IDBDatabaseImpl.h:
+
+        * Modules/indexeddb/client/IDBFactoryImpl.cpp:
+        (WebCore::IDBClient::IDBFactory::open):
+
+        * Modules/indexeddb/client/IDBOpenDBRequestImpl.cpp:
+        (WebCore::IDBClient::IDBOpenDBRequest::onSuccess):
+        * Modules/indexeddb/client/IDBOpenDBRequestImpl.h:
+
+        * Modules/indexeddb/client/IDBTransactionImpl.cpp:
+        (WebCore::IDBClient::IDBTransaction::IDBTransaction):
+        (WebCore::IDBClient::IDBTransaction::db):
+        (WebCore::IDBClient::IDBTransaction::hasPendingActivity):
+        (WebCore::IDBClient::IDBTransaction::isActive):
+        (WebCore::IDBClient::IDBTransaction::scheduleOperationTimer):
+        (WebCore::IDBClient::IDBTransaction::operationTimerFired):
+        (WebCore::IDBClient::IDBTransaction::commit):
+        (WebCore::IDBClient::IDBTransaction::didCommit):
+        (WebCore::IDBClient::IDBTransaction::fireOnComplete):
+        (WebCore::IDBClient::IDBTransaction::fireOnAbort):
+        (WebCore::IDBClient::IDBTransaction::enqueueEvent):
+        (WebCore::IDBClient::IDBTransaction::dispatchEvent):
+        * Modules/indexeddb/client/IDBTransactionImpl.h:
+        (WebCore::IDBClient::IDBTransaction::database):
+        
+        * Modules/indexeddb/legacy/LegacyTransaction.cpp:
+        (WebCore::LegacyTransaction::db):
+        * Modules/indexeddb/legacy/LegacyTransaction.h:
+        
+        * Modules/indexeddb/server/IDBConnectionToClient.cpp:
+        (WebCore::IDBServer::IDBConnectionToClient::didCommitTransaction):
+        * Modules/indexeddb/server/IDBConnectionToClient.h:
+        * Modules/indexeddb/server/IDBConnectionToClientDelegate.h:
+        
+        * Modules/indexeddb/server/IDBServer.cpp:
+        (WebCore::IDBServer::IDBServer::registerTransaction):
+        (WebCore::IDBServer::IDBServer::unregisterTransaction):
+        (WebCore::IDBServer::IDBServer::commitTransaction):
+        * Modules/indexeddb/server/IDBServer.h:
+        
+        * Modules/indexeddb/server/UniqueIDBDatabase.cpp:
+        (WebCore::IDBServer::generateUniqueCallbackIdentifier):
+        (WebCore::IDBServer::UniqueIDBDatabase::storeCallback):
+        (WebCore::IDBServer::UniqueIDBDatabase::commitTransaction):
+        (WebCore::IDBServer::UniqueIDBDatabase::performCommitTransaction):
+        (WebCore::IDBServer::UniqueIDBDatabase::didPerformCommitTransaction):
+        (WebCore::IDBServer::UniqueIDBDatabase::performErrorCallback):
+        (WebCore::IDBServer::UniqueIDBDatabase::startVersionChangeTransaction): Deleted.
+        * Modules/indexeddb/server/UniqueIDBDatabase.h:
+        (WebCore::IDBServer::UniqueIDBDatabase::server):
+        
+        * Modules/indexeddb/server/UniqueIDBDatabaseConnection.cpp:
+        (WebCore::IDBServer::UniqueIDBDatabaseConnection::createVersionChangeTransaction):
+        (WebCore::IDBServer::UniqueIDBDatabaseConnection::didCommitTransaction):
+        * Modules/indexeddb/server/UniqueIDBDatabaseConnection.h:
+        
+        * Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp:
+        (WebCore::IDBServer::UniqueIDBDatabaseTransaction::UniqueIDBDatabaseTransaction):
+        (WebCore::IDBServer::UniqueIDBDatabaseTransaction::~UniqueIDBDatabaseTransaction):
+        (WebCore::IDBServer::UniqueIDBDatabaseTransaction::commit):
+        * Modules/indexeddb/server/UniqueIDBDatabaseTransaction.h:
+        
+        * Modules/indexeddb/shared/IDBDatabaseInfo.h:
+        (WebCore::IDBDatabaseInfo::setVersion):
+        
+        * Modules/indexeddb/shared/IDBError.cpp:
+        (WebCore::IDBError::isolatedCopy):
+        * Modules/indexeddb/shared/IDBError.h:
+
+        * Modules/indexeddb/shared/IDBRequestData.h:
+
+        * Modules/indexeddb/shared/IDBResourceIdentifier.cpp:
+        (WebCore::IDBResourceIdentifier::isolatedCopy):
+        * Modules/indexeddb/shared/IDBResourceIdentifier.h:
+
+        * Modules/indexeddb/shared/InProcessIDBServer.cpp:
+        (WebCore::InProcessIDBServer::didCommitTransaction):
+        (WebCore::InProcessIDBServer::commitTransaction):
+        * Modules/indexeddb/shared/InProcessIDBServer.h:
+
+        * WebCore.xcodeproj/project.pbxproj:
+
+        * platform/CrossThreadCopier.cpp:
+        (WebCore::IDBResourceIdentifier>::copy):
+        (WebCore::IDBError>::copy):
+        * platform/CrossThreadCopier.h:
+
 2015-10-15  Daniel Bates  <dabates@apple.com>
 
         [iOS] DOM click event may not be dispatched when page has :active style and <input type="search">
index 5a87518..ed9774f 100644 (file)
@@ -61,7 +61,7 @@ public:
 
     // Implement the IDBTransaction IDL
     virtual const String& mode() const = 0;
-    virtual IDBDatabase* db() const = 0;
+    virtual IDBDatabase* db() = 0;
     virtual RefPtr<DOMError> error() const = 0;
     virtual RefPtr<IDBObjectStore> objectStore(const String& name, ExceptionCode&) = 0;
     virtual void abort(ExceptionCode&) = 0;
index a6a9f10..716efa1 100644 (file)
@@ -39,6 +39,13 @@ enum class TransactionMode {
 };
 const unsigned TransactionModeMaximum = 2;
 
+enum class TransactionState {
+    Unstarted,
+    Running,
+    Committing,
+    Finished,
+};
+
 enum class CursorDirection {
     Next = 0,
     NextNoDuplicate = 1,
index 0638f87..018fc0e 100644 (file)
@@ -93,6 +93,26 @@ void IDBConnectionToServer::didOpenDatabase(const IDBResultData& resultData)
     request->requestCompleted(resultData);
 }
 
+void IDBConnectionToServer::commitTransaction(IDBTransaction& transaction)
+{
+    LOG(IndexedDB, "IDBConnectionToServer::commitTransaction");
+    ASSERT(!m_committingTransactions.contains(transaction.info().identifier()));
+    m_committingTransactions.set(transaction.info().identifier(), &transaction);
+
+    auto identifier = transaction.info().identifier();
+    m_delegate->commitTransaction(identifier);
+}
+
+void IDBConnectionToServer::didCommitTransaction(const IDBResourceIdentifier& transactionIdentifier, const IDBError& error)
+{
+    LOG(IndexedDB, "IDBConnectionToServer::didCommitTransaction");
+
+    auto transaction = m_committingTransactions.take(transactionIdentifier);
+    ASSERT(transaction);
+
+    transaction->didCommit(error);
+}
+
 void IDBConnectionToServer::fireVersionChangeEvent(uint64_t /*databaseConnectionIdentifier*/ , uint64_t /*requestedVersion*/)
 {
     LOG(IndexedDB, "IDBConnectionToServer::fireVersionChangeEvent");
index 81d8fe3..4468f98 100644 (file)
 
 namespace WebCore {
 
+class IDBError;
 class IDBResultData;
 
 namespace IDBClient {
 
 class IDBDatabase;
 class IDBOpenDBRequest;
+class IDBTransaction;
 
 class IDBConnectionToServer : public RefCounted<IDBConnectionToServer> {
 public:
@@ -56,6 +58,9 @@ public:
     void openDatabase(IDBOpenDBRequest&);
     void didOpenDatabase(const IDBResultData&);
 
+    void commitTransaction(IDBTransaction&);
+    void didCommitTransaction(const IDBResourceIdentifier& transactionIdentifier, const IDBError&);
+
     void fireVersionChangeEvent(uint64_t databaseConnectionIdentifier, uint64_t requestedVersion);
 
     void registerDatabaseConnection(IDBDatabase&);
@@ -68,6 +73,7 @@ private:
 
     HashMap<IDBResourceIdentifier, RefPtr<IDBClient::IDBOpenDBRequest>> m_openDBRequestMap;
     HashSet<RefPtr<IDBDatabase>> m_databaseConnections;
+    HashMap<IDBResourceIdentifier, RefPtr<IDBTransaction>> m_committingTransactions;
 };
 
 } // namespace IDBClient
index 8e1efc4..6d2288e 100644 (file)
@@ -31,6 +31,7 @@
 namespace WebCore {
 
 class IDBRequestData;
+class IDBResourceIdentifier;
 
 namespace IDBClient {
 
@@ -41,6 +42,7 @@ public:
     virtual uint64_t identifier() const = 0;
     virtual void deleteDatabase(IDBRequestData&) = 0;
     virtual void openDatabase(IDBRequestData&) = 0;
+    virtual void commitTransaction(IDBResourceIdentifier&) = 0;
 
     virtual void ref() = 0;
     virtual void deref() = 0;
index ab4eedf..6034b3f 100644 (file)
@@ -128,11 +128,52 @@ Ref<IDBTransaction> IDBDatabase::startVersionChangeTransaction(const IDBTransact
 
     Ref<IDBTransaction> transaction = IDBTransaction::create(*this, info);
     m_versionChangeTransaction = &transaction.get();
+
     m_activeTransactions.set(transaction->info().identifier(), &transaction.get());
 
     return WTF::move(transaction);
 }
 
+void IDBDatabase::commitTransaction(IDBTransaction& transaction)
+{
+    LOG(IndexedDB, "IDBDatabase::commitTransaction");
+
+    auto refTransaction = m_activeTransactions.take(transaction.info().identifier());
+    ASSERT(refTransaction);
+    m_committingTransactions.set(transaction.info().identifier(), WTF::move(refTransaction));
+
+    m_connection->commitTransaction(transaction);
+}
+
+void IDBDatabase::didCommitTransaction(IDBTransaction& transaction)
+{
+    LOG(IndexedDB, "IDBDatabase::didCommitTransaction");
+
+    if (m_versionChangeTransaction == &transaction)
+        m_info.setVersion(transaction.info().newVersion());
+
+    didCommitOrAbortTransaction(transaction);
+}
+
+void IDBDatabase::didAbortTransaction(IDBTransaction& transaction)
+{
+    LOG(IndexedDB, "IDBDatabase::didAbortTransaction");
+    didCommitOrAbortTransaction(transaction);
+}
+
+void IDBDatabase::didCommitOrAbortTransaction(IDBTransaction& transaction)
+{
+    LOG(IndexedDB, "IDBDatabase::didCommitOrAbortTransaction");
+
+    if (m_versionChangeTransaction == &transaction)
+        m_versionChangeTransaction = nullptr;
+    
+    ASSERT(m_activeTransactions.contains(transaction.info().identifier()) || m_committingTransactions.contains(transaction.info().identifier()));
+
+    m_activeTransactions.remove(transaction.info().identifier());
+    m_committingTransactions.remove(transaction.info().identifier());
+}
+
 } // namespace IDBClient
 } // namespace WebCore
 
index 5f22b68..fe31c2f 100644 (file)
@@ -72,15 +72,21 @@ public:
     const IDBDatabaseInfo& info() const { return m_info; }
 
     Ref<IDBTransaction> startVersionChangeTransaction(const IDBTransactionInfo&);
+    void commitTransaction(IDBTransaction&);
+    void didCommitTransaction(IDBTransaction&);
+    void didAbortTransaction(IDBTransaction&);
 
 private:
     IDBDatabase(ScriptExecutionContext&, IDBConnectionToServer&, const IDBResultData&);
 
+    void didCommitOrAbortTransaction(IDBTransaction&);
+    
     Ref<IDBConnectionToServer> m_connection;
     IDBDatabaseInfo m_info;
 
     RefPtr<IDBTransaction> m_versionChangeTransaction;
     HashMap<IDBResourceIdentifier, RefPtr<IDBTransaction>> m_activeTransactions;
+    HashMap<IDBResourceIdentifier, RefPtr<IDBTransaction>> m_committingTransactions;
 };
 
 } // namespace IDBClient
index 2d10fe0..ffe67f3 100644 (file)
@@ -91,7 +91,7 @@ RefPtr<WebCore::IDBOpenDBRequest> IDBFactory::open(ScriptExecutionContext* conte
         return nullptr;
     }
 
-    return openInternal(context, name, 0, ec).release();
+    return openInternal(context, name, version, ec).release();
 }
 
 RefPtr<IDBOpenDBRequest> IDBFactory::openInternal(ScriptExecutionContext* context, const String& name, unsigned long long version, ExceptionCode& ec)
index c2db6f4..7995df1 100644 (file)
@@ -62,16 +62,24 @@ IDBOpenDBRequest::~IDBOpenDBRequest()
 {
 }
 
-
 void IDBOpenDBRequest::onError(const IDBResultData& data)
 {
     m_domError = DOMError::create(data.error().name());
     enqueueEvent(Event::create(eventNames().errorEvent, true, true));
 }
 
-void IDBOpenDBRequest::onSuccess(const IDBResultData&)
+void IDBOpenDBRequest::onSuccess(const IDBResultData& resultData)
 {
-    // FIXME: Implement
+    LOG(IndexedDB, "IDBOpenDBRequest::onSuccess()");
+
+    if (!scriptExecutionContext())
+        return;
+
+    Ref<IDBDatabase> database = IDBDatabase::create(*scriptExecutionContext(), connection(), resultData);
+    m_result = IDBAny::create(WTF::move(database));
+    m_readyState = IDBRequestReadyState::Done;
+
+    enqueueEvent(Event::create(eventNames().successEvent, false, false));
 }
 
 void IDBOpenDBRequest::onUpgradeNeeded(const IDBResultData& resultData)
index a6adbcb..a06daeb 100644 (file)
@@ -60,7 +60,7 @@ private:
     void onUpgradeNeeded(const IDBResultData&);
 
     IDBDatabaseIdentifier m_databaseIdentifier;
-    uint64_t m_version;
+    uint64_t m_version { 0 };
     RefPtr<DOMError> m_domError;
 };
 
index 6fb8bdf..d937aaa 100644 (file)
 #if ENABLE(INDEXED_DATABASE)
 
 #include "DOMError.h"
+#include "EventQueue.h"
 #include "IDBDatabaseImpl.h"
+#include "IDBEventDispatcher.h"
 #include "IDBObjectStore.h"
+#include "Logging.h"
+#include "ScriptExecutionContext.h"
 
 namespace WebCore {
 namespace IDBClient {
@@ -42,9 +46,14 @@ Ref<IDBTransaction> IDBTransaction::create(IDBDatabase& database, const IDBTrans
 
 IDBTransaction::IDBTransaction(IDBDatabase& database, const IDBTransactionInfo& info)
     : WebCore::IDBTransaction(database.scriptExecutionContext())
+    , m_database(database)
     , m_info(info)
+    , m_operationTimer(*this, &IDBTransaction::operationTimerFired)
+
 {
     suspendIfNeeded();
+    scheduleOperationTimer();
+    m_state = IndexedDB::TransactionState::Running;
 }
 
 IDBTransaction::~IDBTransaction()
@@ -65,10 +74,9 @@ const String& IDBTransaction::mode() const
     RELEASE_ASSERT_NOT_REACHED();
 }
 
-WebCore::IDBDatabase* IDBTransaction::db() const
+WebCore::IDBDatabase* IDBTransaction::db()
 {
-    ASSERT_NOT_REACHED();
-    return nullptr;
+    return &m_database.get();
 }
 
 RefPtr<DOMError> IDBTransaction::error() const
@@ -98,6 +106,107 @@ bool IDBTransaction::canSuspendForPageCache() const
     return false;
 }
 
+bool IDBTransaction::hasPendingActivity() const
+{
+    return m_state != IndexedDB::TransactionState::Finished;
+}
+
+bool IDBTransaction::isActive() const
+{
+    return m_state == IndexedDB::TransactionState::Running;
+}
+
+void IDBTransaction::scheduleOperationTimer()
+{
+    if (!m_operationTimer.isActive())
+        m_operationTimer.startOneShot(0);
+}
+
+void IDBTransaction::operationTimerFired()
+{
+    LOG(IndexedDB, "IDBTransaction::operationTimerFired");
+
+    if (m_state == IndexedDB::TransactionState::Unstarted)
+        return;
+
+    // FIXME: Once transactions can do things, like configure the database or insert data into it,
+    // those operations will be handled here, and will prevent the transaction from committing
+    // as long as outstanding operations exist.
+
+    if (isActive())
+        commit();
+}
+
+void IDBTransaction::commit()
+{
+    LOG(IndexedDB, "IDBTransaction::commit");
+
+    if (m_state != IndexedDB::TransactionState::Running) {
+        m_state = IndexedDB::TransactionState::Finished;
+        return;
+    }
+
+    m_state = IndexedDB::TransactionState::Committing;
+
+    m_database->commitTransaction(*this);
+}
+
+void IDBTransaction::didCommit(const IDBError& error)
+{
+    LOG(IndexedDB, "IDBTransaction::didCommit");
+
+    ASSERT(m_state == IndexedDB::TransactionState::Committing);
+
+    if (error.isNull()) {
+        m_database->didCommitTransaction(*this);
+        fireOnComplete();
+    } else {
+        m_database->didAbortTransaction(*this);
+        m_idbError = error;
+        fireOnAbort();
+    }
+
+    m_state = IndexedDB::TransactionState::Finished;
+}
+
+void IDBTransaction::fireOnComplete()
+{
+    LOG(IndexedDB, "IDBTransaction::fireOnComplete");
+    enqueueEvent(Event::create(eventNames().completeEvent, false, false));
+}
+
+void IDBTransaction::fireOnAbort()
+{
+    LOG(IndexedDB, "IDBTransaction::fireOnAbort");
+    enqueueEvent(Event::create(eventNames().abortEvent, true, false));
+}
+
+void IDBTransaction::enqueueEvent(Ref<Event> event)
+{
+    ASSERT(m_state != IndexedDB::TransactionState::Finished);
+
+    if (!scriptExecutionContext())
+        return;
+
+    event->setTarget(this);
+    scriptExecutionContext()->eventQueue().enqueueEvent(&event.get());
+}
+
+bool IDBTransaction::dispatchEvent(PassRefPtr<Event> event)
+{
+    LOG(IndexedDB, "IDBTransaction::dispatchEvent");
+
+    ASSERT(scriptExecutionContext());
+    ASSERT(event->target() == this);
+    ASSERT(event->type() == eventNames().completeEvent || event->type() == eventNames().abortEvent);
+
+    Vector<RefPtr<EventTarget>> targets;
+    targets.append(this);
+    targets.append(db());
+
+    return IDBEventDispatcher::dispatch(event.get(), targets);
+}
+
 } // namespace IDBClient
 } // namespace WebCore
 
index d55a0d6..0d3606c 100644 (file)
 
 #if ENABLE(INDEXED_DATABASE)
 
+#include "IDBError.h"
 #include "IDBTransaction.h"
 #include "IDBTransactionInfo.h"
+#include "IndexedDB.h"
+#include "Timer.h"
+#include <heap/StrongInlines.h>
 
 namespace WebCore {
 namespace IDBClient {
@@ -44,7 +48,7 @@ public:
 
     // IDBTransaction IDL
     virtual const String& mode() const override final;
-    virtual WebCore::IDBDatabase* db() const override final;
+    virtual WebCore::IDBDatabase* db() override final;
     virtual RefPtr<DOMError> error() const override final;
     virtual RefPtr<IDBObjectStore> objectStore(const String& name, ExceptionCode&) override final;
     virtual void abort(ExceptionCode&) override final;
@@ -53,16 +57,39 @@ public:
     virtual ScriptExecutionContext* scriptExecutionContext() const override final { return ActiveDOMObject::scriptExecutionContext(); }
     virtual void refEventTarget() override final { ref(); }
     virtual void derefEventTarget() override final { deref(); }
+    using EventTarget::dispatchEvent;
+    virtual bool dispatchEvent(PassRefPtr<Event>) override final;
 
     virtual const char* activeDOMObjectName() const override final;
     virtual bool canSuspendForPageCache() const override final;
+    virtual bool hasPendingActivity() const override final;
 
     const IDBTransactionInfo info() const { return m_info; }
+    IDBDatabase& database() { return m_database.get(); }
+    const IDBDatabase& database() const { return m_database.get(); }
+
+    void didCommit(const IDBError&);
 
 private:
     IDBTransaction(IDBDatabase&, const IDBTransactionInfo&);
 
+    bool isActive() const;
+    void commit();
+
+    void scheduleOperationTimer();
+    void operationTimerFired();
+
+    void fireOnComplete();
+    void fireOnAbort();
+    void enqueueEvent(Ref<Event>);
+
+    Ref<IDBDatabase> m_database;
     IDBTransactionInfo m_info;
+
+    IndexedDB::TransactionState m_state { IndexedDB::TransactionState::Unstarted };
+    IDBError m_idbError;
+
+    Timer m_operationTimer;
 };
 
 } // namespace IDBClient
index 089ad3d..f0b34a0 100644 (file)
@@ -94,7 +94,7 @@ const String& LegacyTransaction::mode() const
     return modeToString(m_mode);
 }
 
-IDBDatabase* LegacyTransaction::db() const
+IDBDatabase* LegacyTransaction::db()
 {
     return m_database.get();
 }
index f59a272..83b7971 100644 (file)
@@ -66,7 +66,7 @@ public:
     bool isVersionChange() const { return m_mode == IndexedDB::TransactionMode::VersionChange; }
 
     virtual const String& mode() const override final;
-    virtual IDBDatabase* db() const override final;
+    virtual IDBDatabase* db() override final;
     virtual RefPtr<DOMError> error() const override final { return m_error; }
     virtual RefPtr<IDBObjectStore> objectStore(const String& name, ExceptionCode&) override final;
     virtual void abort(ExceptionCode&) override final;
index eed8245..4cf36f7 100644 (file)
@@ -58,6 +58,11 @@ void IDBConnectionToClient::didOpenDatabase(const IDBResultData& result)
     m_delegate->didOpenDatabase(result);
 }
 
+void IDBConnectionToClient::didCommitTransaction(const IDBResourceIdentifier& transactionIdentifier, const IDBError& error)
+{
+    m_delegate->didCommitTransaction(transactionIdentifier, error);
+}
+
 void IDBConnectionToClient::fireVersionChangeEvent(UniqueIDBDatabaseConnection& connection, uint64_t requestedVersion)
 {
     m_delegate->fireVersionChangeEvent(connection, requestedVersion);
index 876cb63..1f0e534 100644 (file)
@@ -34,6 +34,8 @@
 
 namespace WebCore {
 
+class IDBError;
+class IDBResourceIdentifier;
 class IDBResultData;
 
 namespace IDBServer {
@@ -48,6 +50,7 @@ public:
 
     void didDeleteDatabase(const IDBResultData&);
     void didOpenDatabase(const IDBResultData&);
+    void didCommitTransaction(const IDBResourceIdentifier& transactionIdentifier, const IDBError&);
 
     void fireVersionChangeEvent(UniqueIDBDatabaseConnection&, uint64_t requestedVersion);
 
index 7418fab..28eccb2 100644 (file)
@@ -30,6 +30,8 @@
 
 namespace WebCore {
 
+class IDBError;
+class IDBResourceIdentifier;
 class IDBResultData;
 
 namespace IDBServer {
@@ -44,6 +46,7 @@ public:
 
     virtual void didDeleteDatabase(const IDBResultData&) = 0;
     virtual void didOpenDatabase(const IDBResultData&) = 0;
+    virtual void didCommitTransaction(const IDBResourceIdentifier& transactionIdentifier, const IDBError&) = 0;
 
     virtual void fireVersionChangeEvent(UniqueIDBDatabaseConnection&, uint64_t requestedVersion) = 0;
 
index 1116a10..6e91285 100644 (file)
@@ -63,6 +63,20 @@ void IDBServer::unregisterConnection(IDBConnectionToClient& connection)
     m_connectionMap.remove(connection.identifier());
 }
 
+void IDBServer::registerTransaction(UniqueIDBDatabaseTransaction& transaction)
+{
+    ASSERT(!m_transactions.contains(transaction.info().identifier()));
+    m_transactions.set(transaction.info().identifier(), &transaction);
+}
+
+void IDBServer::unregisterTransaction(UniqueIDBDatabaseTransaction& transaction)
+{
+    ASSERT(m_transactions.contains(transaction.info().identifier()));
+    ASSERT(m_transactions.get(transaction.info().identifier()) == &transaction);
+
+    m_transactions.remove(transaction.info().identifier());
+}
+
 void IDBServer::registerDatabaseConnection(UniqueIDBDatabaseConnection& connection)
 {
     ASSERT(!m_databaseConnections.contains(connection.identifier()));
@@ -128,6 +142,20 @@ void IDBServer::deleteDatabase(const IDBRequestData& requestData)
     connection->didDeleteDatabase(result);
 }
 
+void IDBServer::commitTransaction(const IDBResourceIdentifier& transactionIdentifier)
+{
+    LOG(IndexedDB, "IDBServer::commitTransaction");
+
+    auto transaction = m_transactions.get(transactionIdentifier);
+    if (!transaction) {
+        // If there is no transaction there is nothing to commit.
+        // We also have no access to a connection over which to message failure-to-commit.
+        return;
+    }
+
+    transaction->commit();
+}
+
 void IDBServer::postDatabaseTask(std::unique_ptr<CrossThreadTask>&& task)
 {
     ASSERT(isMainThread());
index ca0340a..00d71ae 100644 (file)
@@ -57,12 +57,15 @@ public:
     // Operations requested by the client.
     void openDatabase(const IDBRequestData&);
     void deleteDatabase(const IDBRequestData&);
+    void commitTransaction(const IDBResourceIdentifier&);
 
     void postDatabaseTask(std::unique_ptr<CrossThreadTask>&&);
     void postDatabaseTaskReply(std::unique_ptr<CrossThreadTask>&&);
 
     void registerDatabaseConnection(UniqueIDBDatabaseConnection&);
     void unregisterDatabaseConnection(UniqueIDBDatabaseConnection&);
+    void registerTransaction(UniqueIDBDatabaseTransaction&);
+    void unregisterTransaction(UniqueIDBDatabaseTransaction&);
 
     std::unique_ptr<IDBBackingStore> createBackingStore(const IDBDatabaseIdentifier&);
 
@@ -87,6 +90,7 @@ private:
     MessageQueue<CrossThreadTask> m_databaseReplyQueue;
 
     HashMap<uint64_t, UniqueIDBDatabaseConnection*> m_databaseConnections;
+    HashMap<IDBResourceIdentifier, UniqueIDBDatabaseTransaction*> m_transactions;
 };
 
 } // namespace IDBServer
index 1eaa6f4..9ff1c8e 100644 (file)
@@ -124,6 +124,20 @@ bool UniqueIDBDatabase::hasAnyOpenConnections() const
     return !m_openDatabaseConnections.isEmpty();
 }
 
+static uint64_t generateUniqueCallbackIdentifier()
+{
+    ASSERT(isMainThread());
+    static uint64_t currentID = 0;
+    return ++currentID;
+}
+
+uint64_t UniqueIDBDatabase::storeCallback(ErrorCallback callback)
+{
+    uint64_t identifier = generateUniqueCallbackIdentifier();
+    m_errorCallbacks.set(identifier, callback);
+    return identifier;
+}
+
 void UniqueIDBDatabase::startVersionChangeTransaction()
 {
     LOG(IndexedDB, "(main) UniqueIDBDatabase::startVersionChangeTransaction");
@@ -141,8 +155,7 @@ void UniqueIDBDatabase::startVersionChangeTransaction()
 
     addOpenDatabaseConnection(*m_versionChangeDatabaseConnection);
 
-    m_versionChangeTransaction = m_versionChangeDatabaseConnection->createVersionChangeTransaction(requestedVersion);
-    m_inProgressTransactions.set(m_versionChangeTransaction->info().identifier(), m_versionChangeTransaction);
+    m_versionChangeTransaction = &m_versionChangeDatabaseConnection->createVersionChangeTransaction(requestedVersion);
 
     auto result = IDBResultData::openDatabaseUpgradeNeeded(operation->requestData().requestIdentifier(), *m_versionChangeTransaction);
     operation->connection().didOpenDatabase(result);
@@ -196,6 +209,55 @@ void UniqueIDBDatabase::didOpenBackingStore(const IDBDatabaseInfo& info)
     handleOpenDatabaseOperations();
 }
 
+void UniqueIDBDatabase::commitTransaction(UniqueIDBDatabaseTransaction& transaction, ErrorCallback callback)
+{
+    ASSERT(isMainThread());
+    LOG(IndexedDB, "(main) UniqueIDBDatabase::commitTransaction");
+
+    if (m_versionChangeTransaction == &transaction) {
+        ASSERT(&m_versionChangeTransaction->databaseConnection() == m_versionChangeDatabaseConnection);
+        m_databaseInfo->setVersion(transaction.info().newVersion());
+        m_versionChangeTransaction = nullptr;
+        m_versionChangeDatabaseConnection = nullptr;
+    }
+
+    uint64_t callbackID = storeCallback(callback);
+    m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCommitTransaction, callbackID, transaction.info().identifier()));
+}
+
+void UniqueIDBDatabase::performCommitTransaction(uint64_t callbackIdentifier, const IDBResourceIdentifier&)
+{
+    ASSERT(!isMainThread());
+    LOG(IndexedDB, "(db) UniqueIDBDatabase::performCommitTransaction");
+
+    // FIXME: Commit transaction in backing store, once that exists.
+
+    IDBError error;
+    m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCommitTransaction, callbackIdentifier, error));
+
+}
+
+void UniqueIDBDatabase::didPerformCommitTransaction(uint64_t callbackIdentifier, const IDBError& error)
+{
+    ASSERT(isMainThread());
+    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformCommitTransaction");
+
+    performErrorCallback(callbackIdentifier, error);
+}
+
+void UniqueIDBDatabase::transactionDestroyed(UniqueIDBDatabaseTransaction& transaction)
+{
+    if (m_versionChangeTransaction == &transaction)
+        m_versionChangeTransaction = nullptr;
+}
+
+void UniqueIDBDatabase::performErrorCallback(uint64_t callbackIdentifier, const IDBError& error)
+{
+    auto callback = m_errorCallbacks.take(callbackIdentifier);
+    ASSERT(callback);
+    callback(error);
+}
+
 } // namespace IDBServer
 } // namespace WebCore
 
index 8c48715..ce68452 100644 (file)
@@ -41,6 +41,7 @@
 
 namespace WebCore {
 
+class IDBError;
 class IDBRequestData;
 
 namespace IDBServer {
@@ -48,6 +49,8 @@ namespace IDBServer {
 class IDBConnectionToClient;
 class IDBServer;
 
+typedef std::function<void(const IDBError&)> ErrorCallback;
+
 class UniqueIDBDatabase : public ThreadSafeRefCounted<UniqueIDBDatabase> {
 public:
     static Ref<UniqueIDBDatabase> create(IDBServer& server, const IDBDatabaseIdentifier& identifier)
@@ -58,6 +61,10 @@ public:
     void openDatabaseConnection(IDBConnectionToClient&, const IDBRequestData&);
 
     const IDBDatabaseInfo& info() const;
+    IDBServer& server() { return m_server; }
+
+    void commitTransaction(UniqueIDBDatabaseTransaction&, ErrorCallback);
+    void transactionDestroyed(UniqueIDBDatabaseTransaction&);
 
 private:
     UniqueIDBDatabase(IDBServer&, const IDBDatabaseIdentifier&);
@@ -68,12 +75,18 @@ private:
 
     void startVersionChangeTransaction();
     void notifyConnectionsOfVersionChange();
+
+    uint64_t storeCallback(ErrorCallback);
     
     // Database thread operations
     void openBackingStore(const IDBDatabaseIdentifier&);
+    void performCommitTransaction(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier);
 
     // Main thread callbacks
     void didOpenBackingStore(const IDBDatabaseInfo&);
+    void didPerformCommitTransaction(uint64_t callbackIdentifier, const IDBError&);
+
+    void performErrorCallback(uint64_t callbackIdentifier, const IDBError&);
 
     IDBServer& m_server;
     IDBDatabaseIdentifier m_identifier;
@@ -84,12 +97,12 @@ private:
 
     RefPtr<IDBServerOperation> m_versionChangeOperation;
     RefPtr<UniqueIDBDatabaseConnection> m_versionChangeDatabaseConnection;
-
-    RefPtr<UniqueIDBDatabaseTransaction> m_versionChangeTransaction;
-    HashMap<IDBResourceIdentifier, RefPtr<UniqueIDBDatabaseTransaction>> m_inProgressTransactions;
+    UniqueIDBDatabaseTransaction* m_versionChangeTransaction { nullptr };
 
     std::unique_ptr<IDBBackingStore> m_backingStore;
     std::unique_ptr<IDBDatabaseInfo> m_databaseInfo;
+
+    HashMap<uint64_t, ErrorCallback> m_errorCallbacks;
 };
 
 } // namespace IDBServer
index 27468c6..d7c4ac2 100644 (file)
@@ -59,7 +59,7 @@ void UniqueIDBDatabaseConnection::fireVersionChangeEvent(uint64_t requestedVersi
     m_connectionToClient.fireVersionChangeEvent(*this, requestedVersion);
 }
 
-Ref<UniqueIDBDatabaseTransaction> UniqueIDBDatabaseConnection::createVersionChangeTransaction(uint64_t newVersion)
+UniqueIDBDatabaseTransaction& UniqueIDBDatabaseConnection::createVersionChangeTransaction(uint64_t newVersion)
 {
     LOG(IndexedDB, "UniqueIDBDatabaseConnection::createVersionChangeTransaction");
     ASSERT(!m_closePending);
@@ -69,7 +69,19 @@ Ref<UniqueIDBDatabaseTransaction> UniqueIDBDatabaseConnection::createVersionChan
     Ref<UniqueIDBDatabaseTransaction> transaction = UniqueIDBDatabaseTransaction::create(*this, info);
     m_transactionMap.set(transaction->info().identifier(), &transaction.get());
 
-    return WTF::move(transaction);
+    return transaction.get();
+}
+
+void UniqueIDBDatabaseConnection::didCommitTransaction(UniqueIDBDatabaseTransaction& transaction, const IDBError& error)
+{
+    LOG(IndexedDB, "UniqueIDBDatabaseConnection::didCommitTransaction");
+
+    auto transactionIdentifier = transaction.info().identifier();
+
+    ASSERT(m_transactionMap.contains(transactionIdentifier));
+    m_transactionMap.remove(transactionIdentifier);
+
+    m_connectionToClient.didCommitTransaction(transactionIdentifier, error);
 }
 
 } // namespace IDBServer
index ff735ee..59850a8 100644 (file)
@@ -34,6 +34,9 @@
 #include <wtf/RefCounted.h>
 
 namespace WebCore {
+
+class IDBError;
+
 namespace IDBServer {
 
 class IDBConnectionToClient;
@@ -51,7 +54,9 @@ public:
     bool closePending() const { return m_closePending; }
 
     void fireVersionChangeEvent(uint64_t requestedVersion);
-    Ref<UniqueIDBDatabaseTransaction> createVersionChangeTransaction(uint64_t newVersion);
+    UniqueIDBDatabaseTransaction& createVersionChangeTransaction(uint64_t newVersion);
+
+    void didCommitTransaction(UniqueIDBDatabaseTransaction&, const IDBError&);
 
 private:
     UniqueIDBDatabaseConnection(UniqueIDBDatabase&, IDBConnectionToClient&);
index 473a62d..c8b2fde 100644 (file)
 
 #if ENABLE(INDEXED_DATABASE)
 
+#include "IDBServer.h"
+#include "Logging.h"
+#include "UniqueIDBDatabase.h"
+
 namespace WebCore {
 namespace IDBServer {
 
@@ -40,6 +44,24 @@ UniqueIDBDatabaseTransaction::UniqueIDBDatabaseTransaction(UniqueIDBDatabaseConn
     : m_databaseConnection(connection)
     , m_transactionInfo(info)
 {
+    m_databaseConnection->database().server().registerTransaction(*this);
+}
+
+UniqueIDBDatabaseTransaction::~UniqueIDBDatabaseTransaction()
+{
+    m_databaseConnection->database().transactionDestroyed(*this);
+    m_databaseConnection->database().server().unregisterTransaction(*this);
+}
+
+void UniqueIDBDatabaseTransaction::commit()
+{
+    LOG(IndexedDB, "UniqueIDBDatabaseTransaction::commit");
+
+    RefPtr<UniqueIDBDatabaseTransaction> self(this);
+    m_databaseConnection->database().commitTransaction(*this, [this, self](const IDBError& error) {
+        LOG(IndexedDB, "UniqueIDBDatabaseTransaction::commit (callback)");
+        m_databaseConnection->didCommitTransaction(*this, error);
+    });
 }
 
 } // namespace IDBServer
index 653431a..b2cacca 100644 (file)
@@ -42,9 +42,13 @@ class UniqueIDBDatabaseTransaction : public RefCounted<UniqueIDBDatabaseTransact
 public:
     static Ref<UniqueIDBDatabaseTransaction> create(UniqueIDBDatabaseConnection&, IDBTransactionInfo&);
 
+    ~UniqueIDBDatabaseTransaction();
+
     UniqueIDBDatabaseConnection& databaseConnection() { return m_databaseConnection.get(); }
     const IDBTransactionInfo& info() const { return m_transactionInfo; }
 
+    void commit();
+
 private:
     UniqueIDBDatabaseTransaction(UniqueIDBDatabaseConnection&, IDBTransactionInfo&);
 
index 4e5859a..d6c56a7 100644 (file)
@@ -39,6 +39,8 @@ public:
     IDBDatabaseInfo isolatedCopy() const;
 
     const String& name() const { return m_name; }
+
+    void setVersion(uint64_t version) { m_version = version; }
     uint64_t version() const { return m_version; }
 
 private:
index b8e16ab..d993628 100644 (file)
@@ -55,6 +55,11 @@ IDBError::IDBError(IDBExceptionCode code, const String& message)
 {
 }
 
+IDBError IDBError::isolatedCopy() const
+{
+    return { m_code, m_message.isolatedCopy() };
+}
+
 IDBError& IDBError::operator=(const IDBError& other)
 {
     m_code = other.m_code;
index b2d723a..407034c 100644 (file)
@@ -51,6 +51,8 @@ public:
 
     bool isNull() const { return m_code == IDBExceptionCode::None; }
 
+    IDBError isolatedCopy() const;
+
 private:
     IDBExceptionCode m_code { IDBExceptionCode::None };
     String m_message;
index a1f802a..2973922 100644 (file)
@@ -36,6 +36,7 @@ namespace WebCore {
 namespace IDBClient {
 class IDBConnectionToServer;
 class IDBOpenDBRequest;
+class IDBTransaction;
 }
 
 class IDBRequestData {
@@ -51,7 +52,7 @@ private:
     IDBResourceIdentifier m_requestIdentifier;
     IDBDatabaseIdentifier m_databaseIdentifier;
 
-    uint64_t m_requestedVersion;
+    uint64_t m_requestedVersion { 0 };
 };
 
 } // namespace WebCore
index 1971247..17e0302 100644 (file)
@@ -73,6 +73,11 @@ IDBResourceIdentifier::IDBResourceIdentifier(const IDBServer::IDBConnectionToCli
 {
 }
 
+IDBResourceIdentifier IDBResourceIdentifier::isolatedCopy() const
+{
+    return IDBResourceIdentifier(m_idbConnectionIdentifier, m_resourceNumber);
+}
+
 IDBResourceIdentifier IDBResourceIdentifier::emptyValue()
 {
     return IDBResourceIdentifier(0, 0);
index d87c4ca..9354624 100644 (file)
@@ -69,7 +69,9 @@ public:
     }
     
     uint64_t connectionIdentifier() const { return m_idbConnectionIdentifier; }
-    
+
+    IDBResourceIdentifier isolatedCopy() const;
+
 private:
     IDBResourceIdentifier() = delete;
     IDBResourceIdentifier(uint64_t connectionIdentifier, uint64_t resourceIdentifier);
index 72922dd..080a186 100644 (file)
@@ -102,6 +102,22 @@ void InProcessIDBServer::didOpenDatabase(const IDBResultData& resultData)
     });
 }
 
+void InProcessIDBServer::didCommitTransaction(const IDBResourceIdentifier& transactionIdentifier, const IDBError& error)
+{
+    RefPtr<InProcessIDBServer> self(this);
+    RunLoop::current().dispatch([this, self, transactionIdentifier, error] {
+        m_connectionToServer->didCommitTransaction(transactionIdentifier, error);
+    });
+}
+
+void InProcessIDBServer::commitTransaction(IDBResourceIdentifier& resourceIdentifier)
+{
+    RefPtr<InProcessIDBServer> self(this);
+    RunLoop::current().dispatch([this, self, resourceIdentifier] {
+        m_server->commitTransaction(resourceIdentifier);
+    });
+}
+
 void InProcessIDBServer::fireVersionChangeEvent(IDBServer::UniqueIDBDatabaseConnection& connection, uint64_t requestedVersion)
 {
     RefPtr<InProcessIDBServer> self(this);
index 05369a2..0f1c393 100644 (file)
@@ -56,11 +56,13 @@ public:
     // IDBConnectionToServer
     virtual void deleteDatabase(IDBRequestData&) override final;
     virtual void openDatabase(IDBRequestData&) override final;
+    virtual void commitTransaction(IDBResourceIdentifier&) override final;
 
     // IDBConnectionToClient
     virtual uint64_t identifier() const override;
     virtual void didDeleteDatabase(const IDBResultData&) override final;
     virtual void didOpenDatabase(const IDBResultData&) override final;
+    virtual void didCommitTransaction(const IDBResourceIdentifier& transactionIdentifier, const IDBError&) override final;
     virtual void fireVersionChangeEvent(IDBServer::UniqueIDBDatabaseConnection&, uint64_t requestedVersion) override final;
 
     virtual void ref() override { RefCounted<InProcessIDBServer>::ref(); }
index 351e4ce..a2684c5 100644 (file)
                5145B1091BC48E2E00E86219 /* IDBResourceIdentifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5145B1071BC4890B00E86219 /* IDBResourceIdentifier.cpp */; };
                5145B10A1BC48E2E00E86219 /* IDBResourceIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 5145B1081BC4890B00E86219 /* IDBResourceIdentifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5148453E1BB9D07E006A72ED /* IDBError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5148453C1BB9D076006A72ED /* IDBError.cpp */; };
-               5148453F1BB9D07E006A72ED /* IDBError.h in Headers */ = {isa = PBXBuildFile; fileRef = 5148453D1BB9D076006A72ED /* IDBError.h */; };
+               5148453F1BB9D07E006A72ED /* IDBError.h in Headers */ = {isa = PBXBuildFile; fileRef = 5148453D1BB9D076006A72ED /* IDBError.h */; settings = {ATTRIBUTES = (Private, ); }; };
                514B3F730C722047000530DF /* FileSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 514B3F720C722047000530DF /* FileSystem.h */; settings = {ATTRIBUTES = (Private, ); }; };
                514B3F760C722055000530DF /* FileSystemMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 514B3F750C722055000530DF /* FileSystemMac.mm */; };
                514C76370CE9225E007EF3CD /* JSSQLError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 514C76350CE9225E007EF3CD /* JSSQLError.cpp */; };
index 6a31939..2aa40cb 100644 (file)
 #include "IDBDatabaseIdentifier.h"
 #include "IDBDatabaseInfo.h"
 #include "IDBDatabaseMetadata.h"
+#include "IDBError.h"
 #include "IDBGetResult.h"
 #include "IDBKeyData.h"
 #include "IDBKeyRangeData.h"
+#include "IDBResourceIdentifier.h"
 #include "IDBTransactionInfo.h"
 #endif
 
@@ -145,6 +147,16 @@ CrossThreadCopierBase<false, false, IDBTransactionInfo>::Type CrossThreadCopierB
     return info.isolatedCopy();
 }
 
+CrossThreadCopierBase<false, false, IDBResourceIdentifier>::Type CrossThreadCopierBase<false, false, IDBResourceIdentifier>::copy(const IDBResourceIdentifier& identifier)
+{
+    return identifier.isolatedCopy();
+}
+
+CrossThreadCopierBase<false, false, IDBError>::Type CrossThreadCopierBase<false, false, IDBError>::copy(const IDBError& error)
+{
+    return error.isolatedCopy();
+}
+
 #endif // ENABLE(INDEXED_DATABASE)
 
 // Test CrossThreadCopier using COMPILE_ASSERT.
index 7a2f519..4392abe 100644 (file)
@@ -203,6 +203,18 @@ namespace WebCore {
         static Type copy(const IDBDatabaseIdentifier&);
     };
 
+    class IDBError;
+    template<> struct WEBCORE_EXPORT CrossThreadCopierBase<false, false, IDBError> {
+        typedef IDBError Type;
+        static Type copy(const IDBError&);
+    };
+
+    class IDBResourceIdentifier;
+    template<> struct WEBCORE_EXPORT CrossThreadCopierBase<false, false, IDBResourceIdentifier> {
+        typedef IDBResourceIdentifier Type;
+        static Type copy(const IDBResourceIdentifier&);
+    };
+
     class IDBTransactionInfo;
     template<> struct WEBCORE_EXPORT CrossThreadCopierBase<false, false, IDBTransactionInfo> {
         typedef IDBTransactionInfo Type;