https://bugs.webkit.org/show_bug.cgi?id=135218
Source/WebCore:
Reviewed by David Kilzer.
No new tests (Covered by existing tests).
* Modules/indexeddb/IDBServerConnection.h: Add sync versions of reset/rollback.
* Modules/indexeddb/IDBTransactionBackend.cpp:
(WebCore::IDBTransactionBackend::abort): Call the sync versions.
Source/WebKit2:
Reviewed by Darin Adler and David Kilzer.
* DatabaseProcess/DatabaseToWebProcessConnection.cpp:
(WebKit::DatabaseToWebProcessConnection::didReceiveMessage):
(WebKit::DatabaseToWebProcessConnection::didReceiveSyncMessage): Added.
(WebKit::DatabaseToWebProcessConnection::didClose):
* DatabaseProcess/DatabaseToWebProcessConnection.h:
* DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.cpp:
(WebKit::DatabaseProcessIDBConnection::resetTransactionSync): Added
Wait until the reset is complete before sending the sync reply.
(WebKit::DatabaseProcessIDBConnection::rollbackTransactionSync): Added.
Ditto.
* DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.h:
* DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.messages.in:
Keep track of all in progress transactions and make sure they’re cleaned up
whenever a connection to a WebProcess is broken:
* DatabaseProcess/IndexedDB/UniqueIDBDatabase.cpp:
(WebKit::UniqueIDBDatabase::unregisterConnection):
(WebKit::UniqueIDBDatabase::didCompleteTransactionOperation):
(WebKit::UniqueIDBDatabase::openBackingStoreTransaction):
(WebKit::UniqueIDBDatabase::resetBackingStoreTransaction):
(WebKit::UniqueIDBDatabase::didEstablishTransaction):
(WebKit::UniqueIDBDatabase::didResetTransaction):
(WebKit::UniqueIDBDatabase::resetAllTransactions):
(WebKit::UniqueIDBDatabase::finalizeRollback):
* DatabaseProcess/IndexedDB/UniqueIDBDatabase.h:
* DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.cpp:
(WebKit::UniqueIDBDatabaseBackingStoreSQLite::rollbackTransaction):
Add sync versions of reset/rollback:
* WebProcess/Databases/IndexedDB/WebIDBServerConnection.cpp:
(WebKit::WebIDBServerConnection::resetTransactionSync):
(WebKit::WebIDBServerConnection::rollbackTransactionSync):
* WebProcess/Databases/IndexedDB/WebIDBServerConnection.h:
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@172193
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2014-08-06 Brady Eidson <beidson@apple.com>
+
+ IDB transactions never reset if the Web Process ends before cleaning up
+ https://bugs.webkit.org/show_bug.cgi?id=135218
+
+ Reviewed by David Kilzer.
+
+ No new tests (Covered by existing tests).
+
+ * Modules/indexeddb/IDBServerConnection.h: Add sync versions of reset/rollback.
+
+ * Modules/indexeddb/IDBTransactionBackend.cpp:
+ (WebCore::IDBTransactionBackend::abort): Call the sync versions.
+
2014-08-06 Wenson Hsieh <wenson_hsieh@apple.com>
Implement parsing for CSS scroll snap points
virtual void beginTransaction(int64_t transactionID, std::function<void()> completionCallback) = 0;
virtual void commitTransaction(int64_t transactionID, BoolCallbackFunction successCallback) = 0;
virtual void resetTransaction(int64_t transactionID, std::function<void()> completionCallback) = 0;
+ virtual bool resetTransactionSync(int64_t transactionID) = 0;
virtual void rollbackTransaction(int64_t transactionID, std::function<void()> completionCallback) = 0;
+ virtual bool rollbackTransactionSync(int64_t transactionID) = 0;
virtual void setIndexKeys(int64_t transactionID, int64_t databaseID, int64_t objectStoreID, const IDBObjectStoreMetadata&, IDBKey& primaryKey, const Vector<int64_t>& indexIDs, const Vector<Vector<RefPtr<IDBKey>>>& indexKeys, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback) = 0;
m_taskTimer.stop();
if (wasRunning)
- m_database->serverConnection().rollbackTransaction(m_id, []() { });
+ m_database->serverConnection().rollbackTransactionSync(m_id);
// Run the abort tasks, if any.
while (!m_abortTaskQueue.isEmpty()) {
// itself to be released, and order is critical.
closeOpenCursors();
- m_database->serverConnection().resetTransaction(m_id, []() { });
+ m_database->serverConnection().resetTransactionSync(m_id);
// Transactions must also be marked as completed before the front-end is notified, as
// the transaction completion unblocks operations like closing connections.
+2014-08-06 Brady Eidson and Jeffrey Pfau <beidson@apple.com>
+
+ IDB transactions never reset if the Web Process ends before cleaning up
+ https://bugs.webkit.org/show_bug.cgi?id=135218
+
+ Reviewed by Darin Adler and David Kilzer.
+
+ * DatabaseProcess/DatabaseToWebProcessConnection.cpp:
+ (WebKit::DatabaseToWebProcessConnection::didReceiveMessage):
+ (WebKit::DatabaseToWebProcessConnection::didReceiveSyncMessage): Added.
+ (WebKit::DatabaseToWebProcessConnection::didClose):
+ * DatabaseProcess/DatabaseToWebProcessConnection.h:
+
+ * DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.cpp:
+ (WebKit::DatabaseProcessIDBConnection::resetTransactionSync): Added
+ Wait until the reset is complete before sending the sync reply.
+ (WebKit::DatabaseProcessIDBConnection::rollbackTransactionSync): Added.
+ Ditto.
+ * DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.h:
+ * DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.messages.in:
+
+ Keep track of all in progress transactions and make sure they’re cleaned up
+ whenever a connection to a WebProcess is broken:
+ * DatabaseProcess/IndexedDB/UniqueIDBDatabase.cpp:
+ (WebKit::UniqueIDBDatabase::unregisterConnection):
+ (WebKit::UniqueIDBDatabase::didCompleteTransactionOperation):
+ (WebKit::UniqueIDBDatabase::openBackingStoreTransaction):
+ (WebKit::UniqueIDBDatabase::resetBackingStoreTransaction):
+ (WebKit::UniqueIDBDatabase::didEstablishTransaction):
+ (WebKit::UniqueIDBDatabase::didResetTransaction):
+ (WebKit::UniqueIDBDatabase::resetAllTransactions):
+ (WebKit::UniqueIDBDatabase::finalizeRollback):
+ * DatabaseProcess/IndexedDB/UniqueIDBDatabase.h:
+
+ * DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.cpp:
+ (WebKit::UniqueIDBDatabaseBackingStoreSQLite::rollbackTransaction):
+
+ Add sync versions of reset/rollback:
+ * WebProcess/Databases/IndexedDB/WebIDBServerConnection.cpp:
+ (WebKit::WebIDBServerConnection::resetTransactionSync):
+ (WebKit::WebIDBServerConnection::rollbackTransactionSync):
+ * WebProcess/Databases/IndexedDB/WebIDBServerConnection.h:
+
2014-08-06 Wenson Hsieh <wenson_hsieh@apple.com>
Implement parsing for CSS scroll snap points
backendIterator->value->didReceiveDatabaseProcessIDBConnectionMessage(connection, decoder);
return;
}
-
+
ASSERT_NOT_REACHED();
}
-void DatabaseToWebProcessConnection::didClose(IPC::Connection*)
+void DatabaseToWebProcessConnection::didReceiveSyncMessage(IPC::Connection* connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& reply)
{
+ if (decoder.messageReceiverName() == Messages::DatabaseProcessIDBConnection::messageReceiverName()) {
+ IDBConnectionMap::iterator backendIterator = m_idbConnections.find(decoder.destinationID());
+ if (backendIterator != m_idbConnections.end())
+ backendIterator->value->didReceiveSyncDatabaseProcessIDBConnectionMessage(connection, decoder, reply);
+ return;
+ }
+
+ ASSERT_NOT_REACHED();
+}
+void DatabaseToWebProcessConnection::didClose(IPC::Connection*)
+{
+ // The WebProcess has disconnected, close all of the connections associated with it
+ while (!m_idbConnections.isEmpty())
+ removeDatabaseProcessIDBConnection(m_idbConnections.begin()->key);
}
void DatabaseToWebProcessConnection::didReceiveInvalidMessage(IPC::Connection*, IPC::StringReference messageReceiverName, IPC::StringReference messageName)
// IPC::Connection::Client
virtual void didReceiveMessage(IPC::Connection*, IPC::MessageDecoder&) override;
+ virtual void didReceiveSyncMessage(IPC::Connection*, IPC::MessageDecoder&, std::unique_ptr<IPC::MessageEncoder>&) override;
virtual void didClose(IPC::Connection*) override;
virtual void didReceiveInvalidMessage(IPC::Connection*, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override;
void didReceiveDatabaseToWebProcessConnectionMessage(IPC::Connection*, IPC::MessageDecoder&);
});
}
+void DatabaseProcessIDBConnection::resetTransactionSync(int64_t transactionID, PassRefPtr<Messages::DatabaseProcessIDBConnection::ResetTransactionSync::DelayedReply> prpReply)
+{
+ RefPtr<Messages::DatabaseProcessIDBConnection::ResetTransactionSync::DelayedReply> reply(prpReply);
+ RefPtr<DatabaseProcessIDBConnection> connection(this);
+ m_uniqueIDBDatabase->resetTransaction(IDBIdentifier(*this, transactionID), [connection, reply](bool success) {
+ reply->send(success);
+ });
+}
+
+void DatabaseProcessIDBConnection::rollbackTransactionSync(int64_t transactionID, PassRefPtr<Messages::DatabaseProcessIDBConnection::RollbackTransactionSync::DelayedReply> prpReply)
+{
+ RefPtr<Messages::DatabaseProcessIDBConnection::RollbackTransactionSync::DelayedReply> reply(prpReply);
+ RefPtr<DatabaseProcessIDBConnection> connection(this);
+ m_uniqueIDBDatabase->rollbackTransaction(IDBIdentifier(*this, transactionID), [connection, reply](bool success) {
+ reply->send(success);
+ });
+}
+
void DatabaseProcessIDBConnection::changeDatabaseVersion(uint64_t requestID, int64_t transactionID, uint64_t newVersion)
{
ASSERT(m_uniqueIDBDatabase);
#if ENABLE(INDEXED_DATABASE) && ENABLE(DATABASE_PROCESS)
+#include "DatabaseProcessIDBConnectionMessages.h"
#include "SecurityOriginData.h"
#include "UniqueIDBDatabaseIdentifier.h"
#include <wtf/text/WTFString.h>
// Message handlers.
void didReceiveDatabaseProcessIDBConnectionMessage(IPC::Connection*, IPC::MessageDecoder&);
+ void didReceiveSyncDatabaseProcessIDBConnectionMessage(IPC::Connection*, IPC::MessageDecoder&, std::unique_ptr<IPC::MessageEncoder>&);
void disconnectedFromWebProcess();
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 resetTransactionSync(int64_t transactionID, PassRefPtr<Messages::DatabaseProcessIDBConnection::ResetTransactionSync::DelayedReply>);
+ void rollbackTransactionSync(int64_t transactionID, PassRefPtr<Messages::DatabaseProcessIDBConnection::RollbackTransactionSync::DelayedReply>);
void changeDatabaseVersion(uint64_t requestID, int64_t transactionID, uint64_t newVersion);
void createObjectStore(uint64_t requestID, int64_t transactionID, WebCore::IDBObjectStoreMetadata);
void deleteObjectStore(uint64_t requestID, int64_t transactionID, int64_t objectStoreID);
CommitTransaction(uint64_t requestID, int64_t transactionID)
ResetTransaction(uint64_t requestID, int64_t transactionID)
RollbackTransaction(uint64_t requestID, int64_t transactionID)
+
+ ResetTransactionSync(int64_t transactionID) -> (bool success) Delayed
+ RollbackTransactionSync(int64_t transactionID) -> (bool success) Delayed
ChangeDatabaseVersion(uint64_t requestID, int64_t transactionID, uint64_t newVersion)
CreateObjectStore(uint64_t requestID, int64_t transactionID, WebCore::IDBObjectStoreMetadata objectStoreMetadata)
void UniqueIDBDatabase::unregisterConnection(DatabaseProcessIDBConnection& connection)
{
ASSERT(m_connections.contains(&connection));
+ resetAllTransactions(connection);
m_connections.remove(&connection);
- if (m_connections.isEmpty()) {
+ if (m_connections.isEmpty() && m_pendingTransactionRollbacks.isEmpty()) {
shutdown(UniqueIDBDatabaseShutdownType::NormalShutdown);
DatabaseProcess::shared().removeUniqueIDBDatabase(*this);
}
ASSERT(RunLoop::isMain());
RefPtr<AsyncRequest> request = m_pendingTransactionRequests.take(transactionIdentifier);
- if (!request)
- return;
- request->completeRequest(success);
+ if (request)
+ request->completeRequest(success);
+
+ if (m_pendingTransactionRollbacks.contains(transactionIdentifier))
+ finalizeRollback(transactionIdentifier);
}
void UniqueIDBDatabase::changeDatabaseVersion(const IDBIdentifier& transactionIdentifier, uint64_t newVersion, std::function<void(bool)> successCallback)
bool success = m_backingStore->establishTransaction(transactionIdentifier, objectStoreIDs, mode);
+ postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didEstablishTransaction, transactionIdentifier, success));
postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didCompleteTransactionOperation, transactionIdentifier, success));
}
bool success = m_backingStore->resetTransaction(transactionIdentifier);
+ postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didResetTransaction, transactionIdentifier, success));
postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didCompleteTransactionOperation, transactionIdentifier, success));
}
request->completeRequest(errorCode, errorMessage);
}
+void UniqueIDBDatabase::didEstablishTransaction(const IDBIdentifier& transactionIdentifier, bool success)
+{
+ ASSERT(RunLoop::isMain());
+ if (!success)
+ return;
+
+ auto transactions = m_establishedTransactions.add(&transactionIdentifier.connection(), HashSet<IDBIdentifier>());
+ transactions.iterator->value.add(transactionIdentifier);
+}
+
+void UniqueIDBDatabase::didResetTransaction(const IDBIdentifier& transactionIdentifier, bool success)
+{
+ ASSERT(RunLoop::isMain());
+ if (!success)
+ return;
+
+ auto transactions = m_establishedTransactions.find(&transactionIdentifier.connection());
+ if (transactions != m_establishedTransactions.end())
+ transactions.get()->value.remove(transactionIdentifier);
+}
+
+void UniqueIDBDatabase::resetAllTransactions(const DatabaseProcessIDBConnection& connection)
+{
+ ASSERT(RunLoop::isMain());
+ auto transactions = m_establishedTransactions.find(&connection);
+ if (transactions == m_establishedTransactions.end() || !m_acceptingNewRequests)
+ return;
+
+ for (auto& transactionIdentifier : transactions.get()->value) {
+ m_pendingTransactionRollbacks.add(transactionIdentifier);
+ if (!m_pendingTransactionRequests.contains(transactionIdentifier))
+ finalizeRollback(transactionIdentifier);
+ }
+}
+
+void UniqueIDBDatabase::finalizeRollback(const WebKit::IDBIdentifier& transactionId)
+{
+ ASSERT(RunLoop::isMain());
+ ASSERT(m_pendingTransactionRollbacks.contains(transactionId));
+ ASSERT(!m_pendingTransactionRequests.contains(transactionId));
+ rollbackTransaction(transactionId, [this, transactionId](bool) {
+ ASSERT(RunLoop::isMain());
+ if (m_pendingTransactionRequests.contains(transactionId))
+ return;
+
+ ASSERT(m_pendingTransactionRollbacks.contains(transactionId));
+ m_pendingTransactionRollbacks.remove(transactionId);
+ resetTransaction(transactionId, [this, transactionId](bool) {
+ if (m_acceptingNewRequests && m_connections.isEmpty() && m_pendingTransactionRollbacks.isEmpty()) {
+ shutdown(UniqueIDBDatabaseShutdownType::NormalShutdown);
+ DatabaseProcess::shared().removeUniqueIDBDatabase(*this);
+ }
+ });
+ });
+}
+
String UniqueIDBDatabase::absoluteDatabaseDirectory() const
{
ASSERT(RunLoop::isMain());
void didShutdownBackingStore(UniqueIDBDatabaseShutdownType);
void didCompleteBoolRequest(uint64_t requestID, bool success);
+ void didEstablishTransaction(const IDBIdentifier& transactionIdentifier, bool success);
+ void didResetTransaction(const IDBIdentifier& transactionIdentifier, bool success);
+ void resetAllTransactions(const DatabaseProcessIDBConnection&);
+ void finalizeRollback(const IDBIdentifier& transactionId);
+
bool m_acceptingNewRequests;
+ HashMap<const DatabaseProcessIDBConnection*, HashSet<IDBIdentifier>> m_establishedTransactions;
Deque<RefPtr<AsyncRequest>> m_pendingMetadataRequests;
HashMap<IDBIdentifier, RefPtr<AsyncRequest>> m_pendingTransactionRequests;
+ HashSet<IDBIdentifier> m_pendingTransactionRollbacks;
HashMap<uint64_t, RefPtr<AsyncRequest>> m_pendingDatabaseTasks;
RefPtr<AsyncRequest> m_pendingShutdownTask;
return false;
}
+ if (!transaction->inProgress()) {
+ LOG_ERROR("Attempt to rollback a transaction that hasn't begun");
+ return false;
+ }
+
return transaction->rollback();
}
serverRequest->completeRequest();
}
+bool WebIDBServerConnection::resetTransactionSync(int64_t transactionID)
+{
+ bool success;
+ sendSync(Messages::DatabaseProcessIDBConnection::ResetTransactionSync(transactionID), Messages::DatabaseProcessIDBConnection::ResetTransactionSync::Reply(success));
+ return success;
+}
+
void WebIDBServerConnection::rollbackTransaction(int64_t transactionID, std::function<void()> completionCallback)
{
RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<>::create(completionCallback, completionCallback);
serverRequest->completeRequest();
}
+bool WebIDBServerConnection::rollbackTransactionSync(int64_t transactionID)
+{
+ bool success;
+ sendSync(Messages::DatabaseProcessIDBConnection::RollbackTransactionSync(transactionID), Messages::DatabaseProcessIDBConnection::RollbackTransactionSync::Reply(success));
+ return success;
+}
+
void WebIDBServerConnection::setIndexKeys(int64_t transactionID, int64_t databaseID, int64_t objectStoreID, const IDBObjectStoreMetadata&, IDBKey& primaryKey, const Vector<int64_t>& indexIDs, const Vector<Vector<RefPtr<IDBKey>>>& indexKeys, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback)
{
}
virtual void beginTransaction(int64_t transactionID, std::function<void()> completionCallback) override;
virtual void commitTransaction(int64_t transactionID, BoolCallbackFunction successCallback) override;
virtual void resetTransaction(int64_t transactionID, std::function<void()> completionCallback) override;
+ virtual bool resetTransactionSync(int64_t transactionID) override;
virtual void rollbackTransaction(int64_t transactionID, std::function<void()> completionCallback) override;
+ virtual bool rollbackTransactionSync(int64_t transactionID) override;
virtual void setIndexKeys(int64_t transactionID, int64_t databaseID, int64_t objectStoreID, const WebCore::IDBObjectStoreMetadata&, WebCore::IDBKey& primaryKey, const Vector<int64_t>& indexIDs, const Vector<Vector<RefPtr<WebCore::IDBKey>>>& indexKeys, std::function<void(PassRefPtr<WebCore::IDBDatabaseError>)> completionCallback) override;