Modern IDB (Workers): Get everything to the right threads.
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 6 May 2016 02:33:20 +0000 (02:33 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 6 May 2016 02:33:20 +0000 (02:33 +0000)
https://bugs.webkit.org/show_bug.cgi?id=157398

Reviewed by Alex Christensen.

Source/WebCore:

No new tests (No current change in behavior, will be tested as bug 149953 is resolved, enabling IDB in workers).

* dom/ScriptExecutionContext.h:
(WebCore::ScriptExecutionContext::postCrossThreadTask): Add a helper to post a CrossThreadTask to a context.

* Modules/indexeddb/client/IDBConnectionProxy.cpp:
(WebCore::IDBClient::performCallbackOnCorrectThread): Helper to perform an IDB callback on either the main thread
  or Worker thread as necessary.
(WebCore::IDBClient::IDBConnectionProxy::openDatabase):
(WebCore::IDBClient::IDBConnectionProxy::deleteDatabase):
(WebCore::IDBClient::IDBConnectionProxy::completeOpenDBRequest):
(WebCore::IDBClient::IDBConnectionProxy::createObjectStore):
(WebCore::IDBClient::IDBConnectionProxy::deleteObjectStore):
(WebCore::IDBClient::IDBConnectionProxy::clearObjectStore):
(WebCore::IDBClient::IDBConnectionProxy::createIndex):
(WebCore::IDBClient::IDBConnectionProxy::deleteIndex):
(WebCore::IDBClient::IDBConnectionProxy::putOrAdd):
(WebCore::IDBClient::IDBConnectionProxy::getRecord):
(WebCore::IDBClient::IDBConnectionProxy::getCount):
(WebCore::IDBClient::IDBConnectionProxy::deleteRecord):
(WebCore::IDBClient::IDBConnectionProxy::openCursor):
(WebCore::IDBClient::IDBConnectionProxy::iterateCursor):
(WebCore::IDBClient::IDBConnectionProxy::completeOperation):
(WebCore::IDBClient::IDBConnectionProxy::abortOpenAndUpgradeNeeded):
(WebCore::IDBClient::IDBConnectionProxy::fireVersionChangeEvent):
(WebCore::IDBClient::IDBConnectionProxy::didFireVersionChangeEvent):
(WebCore::IDBClient::IDBConnectionProxy::notifyOpenDBRequestBlocked):
(WebCore::IDBClient::IDBConnectionProxy::establishTransaction):
(WebCore::IDBClient::IDBConnectionProxy::didStartTransaction):
(WebCore::IDBClient::IDBConnectionProxy::commitTransaction):
(WebCore::IDBClient::IDBConnectionProxy::didCommitTransaction):
(WebCore::IDBClient::IDBConnectionProxy::abortTransaction):
(WebCore::IDBClient::IDBConnectionProxy::didAbortTransaction):
(WebCore::IDBClient::IDBConnectionProxy::didFinishHandlingVersionChangeTransaction):
(WebCore::IDBClient::IDBConnectionProxy::databaseConnectionClosed):
(WebCore::IDBClient::IDBConnectionProxy::scheduleMainThreadTasks):
(WebCore::IDBClient::IDBConnectionProxy::handleMainThreadTasks):
* Modules/indexeddb/client/IDBConnectionProxy.h:
(WebCore::IDBClient::IDBConnectionProxy::callConnectionOnMainThread): Helper to marshall IDB operations from the
  Worker thread to the main thread.
(WebCore::IDBClient::IDBConnectionProxy::postMainThreadTask):

* Modules/indexeddb/IDBTransaction.cpp:
(WebCore::IDBTransaction::originThreadID):
* Modules/indexeddb/IDBTransaction.h:

* Modules/indexeddb/client/IDBConnectionToServer.cpp:
(WebCore::IDBClient::IDBConnectionToServer::putOrAdd):
* Modules/indexeddb/client/IDBConnectionToServer.h:

* Modules/indexeddb/client/IDBConnectionToServerDelegate.h:

* Modules/indexeddb/client/TransactionOperation.cpp:
(WebCore::IDBClient::TransactionOperation::scriptExecutionContext):
* Modules/indexeddb/client/TransactionOperation.h:

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

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

Source/WebKit2:

* WebProcess/Databases/IndexedDB/WebIDBConnectionToServer.cpp:
(WebKit::WebIDBConnectionToServer::putOrAdd):
* WebProcess/Databases/IndexedDB/WebIDBConnectionToServer.h:

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

17 files changed:
Source/WebCore/ChangeLog
Source/WebCore/Modules/indexeddb/IDBTransaction.cpp
Source/WebCore/Modules/indexeddb/IDBTransaction.h
Source/WebCore/Modules/indexeddb/client/IDBConnectionProxy.cpp
Source/WebCore/Modules/indexeddb/client/IDBConnectionProxy.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/TransactionOperation.cpp
Source/WebCore/Modules/indexeddb/client/TransactionOperation.h
Source/WebCore/Modules/indexeddb/shared/IDBResourceIdentifier.cpp
Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.cpp
Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.h
Source/WebCore/dom/ScriptExecutionContext.h
Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/Databases/IndexedDB/WebIDBConnectionToServer.cpp
Source/WebKit2/WebProcess/Databases/IndexedDB/WebIDBConnectionToServer.h

index 7c1c307..c186aec 100644 (file)
@@ -1,3 +1,73 @@
+2016-05-05  Brady Eidson  <beidson@apple.com>
+
+        Modern IDB (Workers): Get everything to the right threads.
+        https://bugs.webkit.org/show_bug.cgi?id=157398
+
+        Reviewed by Alex Christensen.
+
+        No new tests (No current change in behavior, will be tested as bug 149953 is resolved, enabling IDB in workers).
+
+        * dom/ScriptExecutionContext.h:
+        (WebCore::ScriptExecutionContext::postCrossThreadTask): Add a helper to post a CrossThreadTask to a context.
+                
+        * Modules/indexeddb/client/IDBConnectionProxy.cpp:
+        (WebCore::IDBClient::performCallbackOnCorrectThread): Helper to perform an IDB callback on either the main thread
+          or Worker thread as necessary.
+        (WebCore::IDBClient::IDBConnectionProxy::openDatabase):
+        (WebCore::IDBClient::IDBConnectionProxy::deleteDatabase):
+        (WebCore::IDBClient::IDBConnectionProxy::completeOpenDBRequest):
+        (WebCore::IDBClient::IDBConnectionProxy::createObjectStore):
+        (WebCore::IDBClient::IDBConnectionProxy::deleteObjectStore):
+        (WebCore::IDBClient::IDBConnectionProxy::clearObjectStore):
+        (WebCore::IDBClient::IDBConnectionProxy::createIndex):
+        (WebCore::IDBClient::IDBConnectionProxy::deleteIndex):
+        (WebCore::IDBClient::IDBConnectionProxy::putOrAdd):
+        (WebCore::IDBClient::IDBConnectionProxy::getRecord):
+        (WebCore::IDBClient::IDBConnectionProxy::getCount):
+        (WebCore::IDBClient::IDBConnectionProxy::deleteRecord):
+        (WebCore::IDBClient::IDBConnectionProxy::openCursor):
+        (WebCore::IDBClient::IDBConnectionProxy::iterateCursor):
+        (WebCore::IDBClient::IDBConnectionProxy::completeOperation):
+        (WebCore::IDBClient::IDBConnectionProxy::abortOpenAndUpgradeNeeded):
+        (WebCore::IDBClient::IDBConnectionProxy::fireVersionChangeEvent):
+        (WebCore::IDBClient::IDBConnectionProxy::didFireVersionChangeEvent):
+        (WebCore::IDBClient::IDBConnectionProxy::notifyOpenDBRequestBlocked):
+        (WebCore::IDBClient::IDBConnectionProxy::establishTransaction):
+        (WebCore::IDBClient::IDBConnectionProxy::didStartTransaction):
+        (WebCore::IDBClient::IDBConnectionProxy::commitTransaction):
+        (WebCore::IDBClient::IDBConnectionProxy::didCommitTransaction):
+        (WebCore::IDBClient::IDBConnectionProxy::abortTransaction):
+        (WebCore::IDBClient::IDBConnectionProxy::didAbortTransaction):
+        (WebCore::IDBClient::IDBConnectionProxy::didFinishHandlingVersionChangeTransaction):
+        (WebCore::IDBClient::IDBConnectionProxy::databaseConnectionClosed):
+        (WebCore::IDBClient::IDBConnectionProxy::scheduleMainThreadTasks):
+        (WebCore::IDBClient::IDBConnectionProxy::handleMainThreadTasks):
+        * Modules/indexeddb/client/IDBConnectionProxy.h:
+        (WebCore::IDBClient::IDBConnectionProxy::callConnectionOnMainThread): Helper to marshall IDB operations from the
+          Worker thread to the main thread.
+        (WebCore::IDBClient::IDBConnectionProxy::postMainThreadTask):
+
+        * Modules/indexeddb/IDBTransaction.cpp:
+        (WebCore::IDBTransaction::originThreadID):
+        * Modules/indexeddb/IDBTransaction.h:
+        
+        * Modules/indexeddb/client/IDBConnectionToServer.cpp:
+        (WebCore::IDBClient::IDBConnectionToServer::putOrAdd):
+        * Modules/indexeddb/client/IDBConnectionToServer.h:
+
+        * Modules/indexeddb/client/IDBConnectionToServerDelegate.h:
+
+        * Modules/indexeddb/client/TransactionOperation.cpp:
+        (WebCore::IDBClient::TransactionOperation::scriptExecutionContext):
+        * Modules/indexeddb/client/TransactionOperation.h:
+
+        * Modules/indexeddb/shared/IDBResourceIdentifier.cpp:
+        (WebCore::nextClientResourceNumber):
+
+        * Modules/indexeddb/shared/InProcessIDBServer.cpp:
+        (WebCore::InProcessIDBServer::putOrAdd):
+        * Modules/indexeddb/shared/InProcessIDBServer.h:
+
 2016-05-05  Dean Jackson  <dino@apple.com>
 
         4 and 8 digit color attributes should use the crazypants algorithm, not the CSS one.
index a301ee1..7de3806 100644 (file)
@@ -1064,6 +1064,11 @@ void IDBTransaction::deactivate()
     scheduleOperationTimer();
 }
 
+ThreadIdentifier IDBTransaction::originThreadID() const
+{
+    return m_database->originThreadID();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(INDEXED_DATABASE)
index a8a3291..ca21547 100644 (file)
@@ -143,6 +143,8 @@ public:
 
     IDBClient::IDBConnectionProxy& connectionProxy();
 
+    ThreadIdentifier originThreadID() const;
+
 private:
     IDBTransaction(IDBDatabase&, const IDBTransactionInfo&, IDBOpenDBRequest*);
 
index 7b66023..a23f5bf 100644 (file)
 
 #if ENABLE(INDEXED_DATABASE)
 
+#include "IDBCursorInfo.h"
 #include "IDBDatabase.h"
+#include "IDBKeyRangeData.h"
 #include "IDBOpenDBRequest.h"
 #include "IDBRequestData.h"
 #include "IDBResultData.h"
+#include "ScriptExecutionContext.h"
 #include "SecurityOrigin.h"
 #include <wtf/MainThread.h>
 
 namespace WebCore {
 namespace IDBClient {
 
+template<typename T, typename... Parameters, typename... Arguments>
+void performCallbackOnCorrectThread(T& object, void (T::*method)(Parameters...), Arguments&&... arguments)
+{
+    ASSERT(isMainThread());
+
+    if (object.originThreadID() == currentThread()) {
+        (object.*method)(arguments...);
+        return;
+    }
+
+    ScriptExecutionContext* context = object.scriptExecutionContext();
+    if (!context)
+        return;
+
+    context->postCrossThreadTask(object, method, arguments...);
+}
+
 IDBConnectionProxy::IDBConnectionProxy(IDBConnectionToServer& connection)
     : m_connectionToServer(connection)
     , m_serverConnectionIdentifier(connection.identifier())
@@ -57,10 +77,6 @@ void IDBConnectionProxy::deref()
 
 RefPtr<IDBOpenDBRequest> IDBConnectionProxy::openDatabase(ScriptExecutionContext& context, const IDBDatabaseIdentifier& databaseIdentifier, uint64_t version)
 {
-    // FIXME: Handle Workers
-    if (!isMainThread())
-        return nullptr;
-
     RefPtr<IDBOpenDBRequest> request;
     {
         Locker<Lock> locker(m_openDBRequestMapLock);
@@ -70,20 +86,13 @@ RefPtr<IDBOpenDBRequest> IDBConnectionProxy::openDatabase(ScriptExecutionContext
         m_openDBRequestMap.set(request->resourceIdentifier(), request.get());
     }
 
-    IDBRequestData requestData(*this, *request);
-
-    // FIXME: For workers, marshall this to the main thread if necessary.
-    m_connectionToServer.openDatabase(requestData);
+    callConnectionOnMainThread(&IDBConnectionToServer::openDatabase, IDBRequestData(*this, *request));
 
     return request;
 }
 
 RefPtr<IDBOpenDBRequest> IDBConnectionProxy::deleteDatabase(ScriptExecutionContext& context, const IDBDatabaseIdentifier& databaseIdentifier)
 {
-    // FIXME: Handle Workers
-    if (!isMainThread())
-        return nullptr;
-
     RefPtr<IDBOpenDBRequest> request;
     {
         Locker<Lock> locker(m_openDBRequestMapLock);
@@ -93,10 +102,7 @@ RefPtr<IDBOpenDBRequest> IDBConnectionProxy::deleteDatabase(ScriptExecutionConte
         m_openDBRequestMap.set(request->resourceIdentifier(), request.get());
     }
 
-    IDBRequestData requestData(*this, *request);
-
-    // FIXME: For workers, marshall this to the main thread if necessary.
-    m_connectionToServer.deleteDatabase(requestData);
+    callConnectionOnMainThread(&IDBConnectionToServer::deleteDatabase, IDBRequestData(*this, *request));
 
     return request;
 }
@@ -118,121 +124,101 @@ void IDBConnectionProxy::completeOpenDBRequest(const IDBResultData& resultData)
     RefPtr<IDBOpenDBRequest> request;
     {
         Locker<Lock> locker(m_openDBRequestMapLock);
-        request = m_openDBRequestMap.get(resultData.requestIdentifier());
+        request = m_openDBRequestMap.take(resultData.requestIdentifier());
         ASSERT(request);
     }
 
-    request->requestCompleted(resultData);
+    ASSERT(request);
+
+    performCallbackOnCorrectThread(*request, &IDBOpenDBRequest::requestCompleted, resultData);
 }
 
 void IDBConnectionProxy::createObjectStore(TransactionOperation& operation, const IDBObjectStoreInfo& info)
 {
-    IDBRequestData requestData(operation);
+    const IDBRequestData requestData(operation);
     saveOperation(operation);
 
-    // FIXME: Handle worker thread marshalling.
-
-    m_connectionToServer.createObjectStore(requestData, info);
+    callConnectionOnMainThread(&IDBConnectionToServer::createObjectStore, requestData, info);
 }
 
 void IDBConnectionProxy::deleteObjectStore(TransactionOperation& operation, const String& objectStoreName)
 {
-    IDBRequestData requestData(operation);
+    const IDBRequestData requestData(operation);
     saveOperation(operation);
 
-    // FIXME: Handle worker thread marshalling.
-
-    m_connectionToServer.deleteObjectStore(requestData, objectStoreName);
+    callConnectionOnMainThread(&IDBConnectionToServer::deleteObjectStore, requestData, objectStoreName);
 }
 
 void IDBConnectionProxy::clearObjectStore(TransactionOperation& operation, uint64_t objectStoreIdentifier)
 {
-    IDBRequestData requestData(operation);
+    const IDBRequestData requestData(operation);
     saveOperation(operation);
 
-    // FIXME: Handle worker thread marshalling.
-
-    m_connectionToServer.clearObjectStore(requestData, objectStoreIdentifier);
+    callConnectionOnMainThread(&IDBConnectionToServer::clearObjectStore, requestData, objectStoreIdentifier);
 }
 
 void IDBConnectionProxy::createIndex(TransactionOperation& operation, const IDBIndexInfo& info)
 {
-    IDBRequestData requestData(operation);
+    const IDBRequestData requestData(operation);
     saveOperation(operation);
 
-    // FIXME: Handle worker thread marshalling.
-
-    m_connectionToServer.createIndex(requestData, info);
+    callConnectionOnMainThread(&IDBConnectionToServer::createIndex, requestData, info);
 }
 
 void IDBConnectionProxy::deleteIndex(TransactionOperation& operation, uint64_t objectStoreIdentifier, const String& indexName)
 {
-    IDBRequestData requestData(operation);
+    const IDBRequestData requestData(operation);
     saveOperation(operation);
 
-    // FIXME: Handle worker thread marshalling.
-
-    m_connectionToServer.deleteIndex(requestData, objectStoreIdentifier, indexName);
+    callConnectionOnMainThread(&IDBConnectionToServer::deleteIndex, requestData, WTFMove(objectStoreIdentifier), indexName);
 }
 
 void IDBConnectionProxy::putOrAdd(TransactionOperation& operation, IDBKey* key, const IDBValue& value, const IndexedDB::ObjectStoreOverwriteMode mode)
 {
-    IDBRequestData requestData(operation);
+    const IDBRequestData requestData(operation);
     saveOperation(operation);
 
-    // FIXME: Handle worker thread marshalling.
-
-    m_connectionToServer.putOrAdd(requestData, key, value, mode);
+    callConnectionOnMainThread(&IDBConnectionToServer::putOrAdd, requestData, IDBKeyData(key), value, mode);
 }
 
 void IDBConnectionProxy::getRecord(TransactionOperation& operation, const IDBKeyRangeData& keyRange)
 {
-    IDBRequestData requestData(operation);
+    const IDBRequestData requestData(operation);
     saveOperation(operation);
 
-    // FIXME: Handle worker thread marshalling.
-
-    m_connectionToServer.getRecord(requestData, keyRange);
+    callConnectionOnMainThread(&IDBConnectionToServer::getRecord, requestData, keyRange);
 }
 
 void IDBConnectionProxy::getCount(TransactionOperation& operation, const IDBKeyRangeData& keyRange)
 {
-    IDBRequestData requestData(operation);
+    const IDBRequestData requestData(operation);
     saveOperation(operation);
 
-    // FIXME: Handle worker thread marshalling.
-
-    m_connectionToServer.getCount(requestData, keyRange);
+    callConnectionOnMainThread(&IDBConnectionToServer::getCount, requestData, keyRange);
 }
 
 void IDBConnectionProxy::deleteRecord(TransactionOperation& operation, const IDBKeyRangeData& keyRange)
 {
-    IDBRequestData requestData(operation);
+    const IDBRequestData requestData(operation);
     saveOperation(operation);
 
-    // FIXME: Handle worker thread marshalling.
-
-    m_connectionToServer.deleteRecord(requestData, keyRange);
+    callConnectionOnMainThread(&IDBConnectionToServer::deleteRecord, requestData, keyRange);
 }
 
 void IDBConnectionProxy::openCursor(TransactionOperation& operation, const IDBCursorInfo& info)
 {
-    IDBRequestData requestData(operation);
+    const IDBRequestData requestData(operation);
     saveOperation(operation);
 
-    // FIXME: Handle worker thread marshalling.
-
-    m_connectionToServer.openCursor(requestData, info);
+    callConnectionOnMainThread(&IDBConnectionToServer::openCursor, requestData, info);
 }
 
 void IDBConnectionProxy::iterateCursor(TransactionOperation& operation, const IDBKeyData& key, unsigned long count)
 {
-    IDBRequestData requestData(operation);
+    const IDBRequestData requestData(operation);
     saveOperation(operation);
 
-    // FIXME: Handle worker thread marshalling.
-
-    m_connectionToServer.iterateCursor(requestData, key, count);
+    callConnectionOnMainThread(&IDBConnectionToServer::iterateCursor, requestData, key, count);
 }
 
 void IDBConnectionProxy::saveOperation(TransactionOperation& operation)
@@ -253,24 +239,16 @@ void IDBConnectionProxy::completeOperation(const IDBResultData& resultData)
 
     ASSERT(operation);
 
-    // FIXME: Handle getting operation->completed() onto the correct thread via the IDBTransaction.
-    
-    operation->completed(resultData);
+    performCallbackOnCorrectThread(*operation, &TransactionOperation::completed, resultData);
 }
 
 void IDBConnectionProxy::abortOpenAndUpgradeNeeded(uint64_t databaseConnectionIdentifier, const IDBResourceIdentifier& transactionIdentifier)
 {
-    // FIXME: Handle workers
-    if (!isMainThread())
-        return;
-
-    m_connectionToServer.abortOpenAndUpgradeNeeded(databaseConnectionIdentifier, transactionIdentifier);
+    callConnectionOnMainThread(&IDBConnectionToServer::abortOpenAndUpgradeNeeded, databaseConnectionIdentifier, transactionIdentifier);
 }
 
 void IDBConnectionProxy::fireVersionChangeEvent(uint64_t databaseConnectionIdentifier, const IDBResourceIdentifier& requestIdentifier, uint64_t requestedVersion)
 {
-    ASSERT(isMainThread());
-
     RefPtr<IDBDatabase> database;
     {
         Locker<Lock> locker(m_databaseConnectionMapLock);
@@ -280,16 +258,12 @@ void IDBConnectionProxy::fireVersionChangeEvent(uint64_t databaseConnectionIdent
     if (!database)
         return;
 
-    database->fireVersionChangeEvent(requestIdentifier, requestedVersion);
+    performCallbackOnCorrectThread(*database, &IDBDatabase::fireVersionChangeEvent, requestIdentifier, requestedVersion);
 }
 
 void IDBConnectionProxy::didFireVersionChangeEvent(uint64_t databaseConnectionIdentifier, const IDBResourceIdentifier& requestIdentifier)
 {
-    // FIXME: Handle Workers
-    if (!isMainThread())
-        return;
-
-    m_connectionToServer.didFireVersionChangeEvent(databaseConnectionIdentifier, requestIdentifier);
+    callConnectionOnMainThread(&IDBConnectionToServer::didFireVersionChangeEvent, databaseConnectionIdentifier, requestIdentifier);
 }
 
 void IDBConnectionProxy::notifyOpenDBRequestBlocked(const IDBResourceIdentifier& requestIdentifier, uint64_t oldVersion, uint64_t newVersion)
@@ -304,7 +278,7 @@ void IDBConnectionProxy::notifyOpenDBRequestBlocked(const IDBResourceIdentifier&
 
     ASSERT(request);
 
-    request->requestBlocked(oldVersion, newVersion);
+    performCallbackOnCorrectThread(*request, &IDBOpenDBRequest::requestBlocked, oldVersion, newVersion);
 }
 
 void IDBConnectionProxy::establishTransaction(IDBTransaction& transaction)
@@ -315,11 +289,7 @@ void IDBConnectionProxy::establishTransaction(IDBTransaction& transaction)
         m_pendingTransactions.set(transaction.info().identifier(), &transaction);
     }
 
-    // FIXME: Handle Workers
-    if (!isMainThread())
-        return;
-
-    m_connectionToServer.establishTransaction(transaction.database().databaseConnectionIdentifier(), transaction.info());
+    callConnectionOnMainThread(&IDBConnectionToServer::establishTransaction, transaction.database().databaseConnectionIdentifier(), transaction.info());
 }
 
 void IDBConnectionProxy::didStartTransaction(const IDBResourceIdentifier& transactionIdentifier, const IDBError& error)
@@ -332,9 +302,7 @@ void IDBConnectionProxy::didStartTransaction(const IDBResourceIdentifier& transa
 
     ASSERT(transaction);
 
-    // FIXME: Handle hopping to the Worker thread here if necessary.
-
-    transaction->didStart(error);
+    performCallbackOnCorrectThread(*transaction, &IDBTransaction::didStart, error);
 }
 
 void IDBConnectionProxy::commitTransaction(IDBTransaction& transaction)
@@ -345,11 +313,7 @@ void IDBConnectionProxy::commitTransaction(IDBTransaction& transaction)
         m_committingTransactions.set(transaction.info().identifier(), &transaction);
     }
 
-    // FIXME: Handle Workers
-    if (!isMainThread())
-        return;
-
-    m_connectionToServer.commitTransaction(transaction.info().identifier());
+    callConnectionOnMainThread(&IDBConnectionToServer::commitTransaction, transaction.info().identifier());
 }
 
 void IDBConnectionProxy::didCommitTransaction(const IDBResourceIdentifier& transactionIdentifier, const IDBError& error)
@@ -362,9 +326,7 @@ void IDBConnectionProxy::didCommitTransaction(const IDBResourceIdentifier& trans
 
     ASSERT(transaction);
 
-    // FIXME: Handle hopping to the Worker thread here if necessary.
-
-    transaction->didCommit(error);
+    performCallbackOnCorrectThread(*transaction, &IDBTransaction::didCommit, error);
 }
 
 void IDBConnectionProxy::abortTransaction(IDBTransaction& transaction)
@@ -375,11 +337,7 @@ void IDBConnectionProxy::abortTransaction(IDBTransaction& transaction)
         m_abortingTransactions.set(transaction.info().identifier(), &transaction);
     }
 
-    // FIXME: Handle Workers
-    if (!isMainThread())
-        return;
-
-    m_connectionToServer.abortTransaction(transaction.info().identifier());
+    callConnectionOnMainThread(&IDBConnectionToServer::abortTransaction, transaction.info().identifier());
 }
 
 void IDBConnectionProxy::didAbortTransaction(const IDBResourceIdentifier& transactionIdentifier, const IDBError& error)
@@ -392,9 +350,7 @@ void IDBConnectionProxy::didAbortTransaction(const IDBResourceIdentifier& transa
 
     ASSERT(transaction);
 
-    // FIXME: Handle hopping to the Worker thread here if necessary.
-
-    transaction->didAbort(error);
+    performCallbackOnCorrectThread(*transaction, &IDBTransaction::didAbort, error);
 }
 
 bool IDBConnectionProxy::hasRecordOfTransaction(const IDBTransaction& transaction) const
@@ -407,20 +363,37 @@ bool IDBConnectionProxy::hasRecordOfTransaction(const IDBTransaction& transactio
 
 void IDBConnectionProxy::didFinishHandlingVersionChangeTransaction(IDBTransaction& transaction)
 {
-    // FIXME: Handle Workers
-    if (!isMainThread())
-        return;
-
-    m_connectionToServer.didFinishHandlingVersionChangeTransaction(transaction.info().identifier());
+    callConnectionOnMainThread(&IDBConnectionToServer::didFinishHandlingVersionChangeTransaction, transaction.info().identifier());
 }
 
 void IDBConnectionProxy::databaseConnectionClosed(IDBDatabase& database)
 {
-    // FIXME: Handle Workers
-    if (!isMainThread())
+    callConnectionOnMainThread(&IDBConnectionToServer::databaseConnectionClosed, database.databaseConnectionIdentifier());
+}
+
+void IDBConnectionProxy::scheduleMainThreadTasks()
+{
+    Locker<Lock> locker(m_mainThreadTaskLock);
+    if (m_mainThreadProtector)
         return;
 
-    m_connectionToServer.databaseConnectionClosed(database.databaseConnectionIdentifier());
+    m_mainThreadProtector = &m_connectionToServer;
+    callOnMainThread([this] {
+        handleMainThreadTasks();
+    });
+}
+
+void IDBConnectionProxy::handleMainThreadTasks()
+{
+    RefPtr<IDBConnectionToServer> protector;
+    {
+        Locker<Lock> locker(m_mainThreadTaskLock);
+        ASSERT(m_mainThreadProtector);
+        protector = WTFMove(m_mainThreadProtector);
+    }
+
+    while (auto task = m_mainThreadQueue.tryGetMessage())
+        task->performTask();
 }
 
 void IDBConnectionProxy::getAllDatabaseNames(const SecurityOrigin& mainFrameOrigin, const SecurityOrigin& openingOrigin, std::function<void (const Vector<String>&)> callback)
index bfab6f4..9eca8e2 100644 (file)
 
 #if ENABLE(INDEXED_DATABASE)
 
+#include "CrossThreadTask.h"
 #include "IDBConnectionToServer.h"
 #include "IDBResourceIdentifier.h"
 #include "TransactionOperation.h"
 #include <functional>
 #include <wtf/HashMap.h>
+#include <wtf/MainThread.h>
+#include <wtf/MessageQueue.h>
 #include <wtf/RefPtr.h>
 #include <wtf/Vector.h>
 #include <wtf/text/WTFString.h>
@@ -109,6 +112,27 @@ private:
 
     void saveOperation(TransactionOperation&);
 
+    template<typename... Parameters, typename... Arguments>
+    void callConnectionOnMainThread(void (IDBConnectionToServer::*method)(Parameters...), Arguments&&... arguments)
+    {
+        if (isMainThread())
+            (m_connectionToServer.*method)(arguments...);
+        else
+            postMainThreadTask(m_connectionToServer, method, arguments...);
+    }
+
+    template<typename... Arguments>
+    void postMainThreadTask(Arguments&&... arguments)
+    {
+        auto task = createCrossThreadTask(arguments...);
+        m_mainThreadQueue.append(WTFMove(task));
+
+        scheduleMainThreadTasks();
+    }
+
+    void scheduleMainThreadTasks();
+    void handleMainThreadTasks();
+
     IDBConnectionToServer& m_connectionToServer;
     uint64_t m_serverConnectionIdentifier;
 
@@ -125,6 +149,10 @@ private:
 
     HashMap<IDBResourceIdentifier, RefPtr<TransactionOperation>> m_activeOperations;
     Lock m_transactionOperationLock;
+
+    MessageQueue<CrossThreadTask> m_mainThreadQueue;
+    Lock m_mainThreadTaskLock;
+    RefPtr<IDBConnectionToServer> m_mainThreadProtector;
 };
 
 } // namespace IDBClient
index 40e0c18..2fe7721 100644 (file)
@@ -157,7 +157,7 @@ void IDBConnectionToServer::didDeleteIndex(const IDBResultData& resultData)
     m_proxy->completeOperation(resultData);
 }
 
-void IDBConnectionToServer::putOrAdd(const IDBRequestData& requestData, IDBKey* key, const IDBValue& value, const IndexedDB::ObjectStoreOverwriteMode overwriteMode)
+void IDBConnectionToServer::putOrAdd(const IDBRequestData& requestData, const IDBKeyData& key, const IDBValue& value, const IndexedDB::ObjectStoreOverwriteMode overwriteMode)
 {
     LOG(IndexedDB, "IDBConnectionToServer::putOrAdd");
     ASSERT(isMainThread());
index 234f70c..0de0f06 100644 (file)
@@ -76,7 +76,7 @@ public:
     void deleteIndex(const IDBRequestData&, uint64_t objectStoreIdentifier, const String& indexName);
     WEBCORE_EXPORT void didDeleteIndex(const IDBResultData&);
 
-    void putOrAdd(const IDBRequestData&, IDBKey*, const IDBValue&, const IndexedDB::ObjectStoreOverwriteMode);
+    void putOrAdd(const IDBRequestData&, const IDBKeyData&, const IDBValue&, const IndexedDB::ObjectStoreOverwriteMode);
     WEBCORE_EXPORT void didPutOrAdd(const IDBResultData&);
 
     void getRecord(const IDBRequestData&, const IDBKeyRangeData&);
index bf9f2c2..adc5b8e 100644 (file)
@@ -34,7 +34,6 @@ namespace WebCore {
 
 class IDBCursorInfo;
 class IDBIndexInfo;
-class IDBKey;
 class IDBKeyData;
 class IDBObjectStoreInfo;
 class IDBRequestData;
@@ -67,7 +66,7 @@ public:
     virtual void clearObjectStore(const IDBRequestData&, uint64_t objectStoreIdentifier) = 0;
     virtual void createIndex(const IDBRequestData&, const IDBIndexInfo&) = 0;
     virtual void deleteIndex(const IDBRequestData&, uint64_t objectStoreIdentifier, const String& indexName) = 0;
-    virtual void putOrAdd(const IDBRequestData&, IDBKey*, const IDBValue&, const IndexedDB::ObjectStoreOverwriteMode) = 0;
+    virtual void putOrAdd(const IDBRequestData&, const IDBKeyData&, const IDBValue&, const IndexedDB::ObjectStoreOverwriteMode) = 0;
     virtual void getRecord(const IDBRequestData&, const IDBKeyRangeData&) = 0;
     virtual void getCount(const IDBRequestData&, const IDBKeyRangeData&) = 0;
     virtual void deleteRecord(const IDBRequestData&, const IDBKeyRangeData&) = 0;
index a6ead71..cf8c301 100644 (file)
@@ -44,6 +44,11 @@ TransactionOperation::TransactionOperation(IDBTransaction& transaction, IDBReque
         m_cursorIdentifier = std::make_unique<IDBResourceIdentifier>(cursor->info().identifier());
 }
 
+ScriptExecutionContext* TransactionOperation::scriptExecutionContext() const
+{
+    return m_transaction->scriptExecutionContext();
+}
+
 } // namespace IDBClient
 } // namespace WebCore
 
index 43077a4..b5f9989 100644 (file)
@@ -73,6 +73,8 @@ public:
 
     ThreadIdentifier originThreadID() const { return m_originThreadID; }
 
+    ScriptExecutionContext* scriptExecutionContext() const;
+
 protected:
     TransactionOperation(IDBTransaction& transaction)
         : m_transaction(transaction)
index 8c432b6..1ca06a9 100644 (file)
@@ -37,8 +37,7 @@ namespace WebCore {
 
 static uint64_t nextClientResourceNumber()
 {
-    ASSERT(isMainThread());
-    static uint64_t currentNumber = 1;
+    static std::atomic<uint64_t> currentNumber(1);
     return currentNumber += 2;
 }
 
index 3a08249..0ff41bd 100644 (file)
@@ -289,11 +289,9 @@ void InProcessIDBServer::deleteIndex(const IDBRequestData& requestData, uint64_t
     });
 }
 
-void InProcessIDBServer::putOrAdd(const IDBRequestData& requestData, IDBKey* key, const IDBValue& value, const IndexedDB::ObjectStoreOverwriteMode overwriteMode)
+void InProcessIDBServer::putOrAdd(const IDBRequestData& requestData, const IDBKeyData& keyData, const IDBValue& value, const IndexedDB::ObjectStoreOverwriteMode overwriteMode)
 {
     RefPtr<InProcessIDBServer> self(this);
-    IDBKeyData keyData(key);
-
     RunLoop::current().dispatch([this, self, requestData, keyData, value, overwriteMode] {
         m_server->putOrAdd(requestData, keyData, value, overwriteMode);
     });
index 2edb210..df34315 100644 (file)
@@ -65,7 +65,7 @@ public:
     void clearObjectStore(const IDBRequestData&, uint64_t objectStoreIdentifier) final;
     void createIndex(const IDBRequestData&, const IDBIndexInfo&) final;
     void deleteIndex(const IDBRequestData&, uint64_t objectStoreIdentifier, const String& indexName) final;
-    void putOrAdd(const IDBRequestData&, IDBKey*, const IDBValue&, const IndexedDB::ObjectStoreOverwriteMode) final;
+    void putOrAdd(const IDBRequestData&, const IDBKeyData&, const IDBValue&, const IndexedDB::ObjectStoreOverwriteMode) final;
     void getRecord(const IDBRequestData&, const IDBKeyRangeData&) final;
     void getCount(const IDBRequestData&, const IDBKeyRangeData&) final;
     void deleteRecord(const IDBRequestData&, const IDBKeyRangeData&) final;
index e92c0df..4ad00b3 100644 (file)
@@ -28,6 +28,7 @@
 #pragma once
 
 #include "ActiveDOMObject.h"
+#include "CrossThreadTask.h"
 #include "DOMTimer.h"
 #include "ResourceRequest.h"
 #include "SecurityContext.h"
@@ -167,6 +168,17 @@ public:
 
     virtual void postTask(Task) = 0; // Executes the task on context's thread asynchronously.
 
+    template<typename... Arguments>
+    void postCrossThreadTask(Arguments&&... arguments)
+    {
+        auto crossThreadTask = createCrossThreadTask(arguments...);
+        auto* rawTask = crossThreadTask.release();
+        postTask([=](ScriptExecutionContext&) {
+            std::unique_ptr<CrossThreadTask> task(rawTask);
+            task->performTask();
+        });
+    }
+
     // Gets the next id in a circular sequence from 1 to 2^31-1.
     int circularSequentialID();
 
index e84779d..7cd8da4 100644 (file)
@@ -1,3 +1,14 @@
+2016-05-05  Brady Eidson  <beidson@apple.com>
+
+        Modern IDB (Workers): Get everything to the right threads.
+        https://bugs.webkit.org/show_bug.cgi?id=157398
+
+        Reviewed by Alex Christensen.
+
+        * WebProcess/Databases/IndexedDB/WebIDBConnectionToServer.cpp:
+        (WebKit::WebIDBConnectionToServer::putOrAdd):
+        * WebProcess/Databases/IndexedDB/WebIDBConnectionToServer.h:
+
 2016-05-05  Manuel Rego Casasnovas  <rego@igalia.com>
 
         [GTK] Remove "region based columns" runtime feature remainings
index ec1038b..fe0a8ff 100644 (file)
@@ -131,9 +131,8 @@ void WebIDBConnectionToServer::deleteIndex(const IDBRequestData& requestData, ui
     send(Messages::WebIDBConnectionToClient::DeleteIndex(requestData, objectStoreIdentifier, indexName));
 }
 
-void WebIDBConnectionToServer::putOrAdd(const IDBRequestData& requestData, IDBKey* key, const IDBValue& value, const IndexedDB::ObjectStoreOverwriteMode mode)
+void WebIDBConnectionToServer::putOrAdd(const IDBRequestData& requestData, const IDBKeyData& keyData, const IDBValue& value, const IndexedDB::ObjectStoreOverwriteMode mode)
 {
-    IDBKeyData keyData(key);
     send(Messages::WebIDBConnectionToClient::PutOrAdd(requestData, keyData, value, static_cast<unsigned>(mode)));
 }
 
index 5ea0c4c..25d1021 100644 (file)
@@ -55,7 +55,7 @@ public:
     void clearObjectStore(const WebCore::IDBRequestData&, uint64_t objectStoreIdentifier) final;
     void createIndex(const WebCore::IDBRequestData&, const WebCore::IDBIndexInfo&) final;
     void deleteIndex(const WebCore::IDBRequestData&, uint64_t objectStoreIdentifier, const String& indexName) final;
-    void putOrAdd(const WebCore::IDBRequestData&, WebCore::IDBKey*, const WebCore::IDBValue&, const WebCore::IndexedDB::ObjectStoreOverwriteMode) final;
+    void putOrAdd(const WebCore::IDBRequestData&, const WebCore::IDBKeyData&, const WebCore::IDBValue&, const WebCore::IndexedDB::ObjectStoreOverwriteMode) final;
     void getRecord(const WebCore::IDBRequestData&, const WebCore::IDBKeyRangeData&) final;
     void getCount(const WebCore::IDBRequestData&, const WebCore::IDBKeyRangeData&) final;
     void deleteRecord(const WebCore::IDBRequestData&, const WebCore::IDBKeyRangeData&) final;