Cross-thread version StorageQuotaManager
https://bugs.webkit.org/show_bug.cgi?id=203971
<rdar://problem/57290349>

Reviewed by Chris Dumez.

Source/WebCore:

Implement a lock-based StorageQuotaManager so that quota check can be done on different threads.
If space request is made on a background thread, it needs to hold a lock until it is finished, so no request
from different threads can be performed at the same time.
If space request is made on the main thread, we will dispatch it to a background thread and schedule a calllback
to the main thread when result is available, so the main thread will not be blocked.

Covered by existing quota related tests.

* Headers.cmake:
* Modules/indexeddb/server/IDBServer.cpp:
(WebCore::IDBServer::IDBServer::create):
(WebCore::IDBServer::IDBServer::IDBServer):
(WebCore::IDBServer::IDBServer::didPerformCloseAndDeleteDatabases):
(WebCore::IDBServer::IDBServer::requestSpace):
(WebCore::IDBServer::IDBServer::diskUsage):
(WebCore::IDBServer::IDBServer::QuotaUser::QuotaUser): Deleted.
(WebCore::IDBServer::IDBServer::QuotaUser::~QuotaUser): Deleted.
(WebCore::IDBServer::IDBServer::QuotaUser::resetSpaceUsed): Deleted.
(WebCore::IDBServer::IDBServer::QuotaUser::computeSpaceUsed): Deleted.
(WebCore::IDBServer::IDBServer::QuotaUser::increaseSpaceUsed): Deleted.
(WebCore::IDBServer::IDBServer::QuotaUser::decreaseSpaceUsed): Deleted.
(WebCore::IDBServer::IDBServer::QuotaUser::whenInitialized): Deleted.
(WebCore::IDBServer::IDBServer::QuotaUser::initializeSpaceUsed): Deleted.
(WebCore::IDBServer::IDBServer::ensureQuotaUser): Deleted.
(WebCore::IDBServer::IDBServer::startComputingSpaceUsedForOrigin): Deleted.
(WebCore::IDBServer::IDBServer::computeSpaceUsedForOrigin): Deleted.
(WebCore::IDBServer::IDBServer::finishComputingSpaceUsedForOrigin): Deleted.
(WebCore::IDBServer::IDBServer::resetSpaceUsed): Deleted.
(WebCore::IDBServer::IDBServer::increaseSpaceUsed): Deleted.
(WebCore::IDBServer::IDBServer::decreaseSpaceUsed): Deleted.
(WebCore::IDBServer::IDBServer::increasePotentialSpaceUsed): Deleted.
(WebCore::IDBServer::IDBServer::decreasePotentialSpaceUsed): Deleted.
* Modules/indexeddb/server/IDBServer.h:
(WebCore::IDBServer::IDBServer::initializeQuotaUser): Deleted.
(): Deleted.
* Modules/indexeddb/server/UniqueIDBDatabase.cpp:
(WebCore::IDBServer::UniqueIDBDatabase::performCurrentOpenOperation):
(WebCore::IDBServer::UniqueIDBDatabase::openBackingStore):
(WebCore::IDBServer::UniqueIDBDatabase::didOpenBackingStore):
(WebCore::IDBServer::UniqueIDBDatabase::createObjectStore):
(WebCore::IDBServer::UniqueIDBDatabase::performCreateObjectStore):
(WebCore::IDBServer::UniqueIDBDatabase::didPerformCreateObjectStore):
(WebCore::IDBServer::UniqueIDBDatabase::deleteObjectStore):
(WebCore::IDBServer::UniqueIDBDatabase::renameObjectStore):
(WebCore::IDBServer::UniqueIDBDatabase::performRenameObjectStore):
(WebCore::IDBServer::UniqueIDBDatabase::didPerformRenameObjectStore):
(WebCore::IDBServer::UniqueIDBDatabase::clearObjectStore):
(WebCore::IDBServer::UniqueIDBDatabase::createIndex):
(WebCore::IDBServer::UniqueIDBDatabase::performCreateIndex):
(WebCore::IDBServer::UniqueIDBDatabase::didPerformCreateIndex):
(WebCore::IDBServer::UniqueIDBDatabase::deleteIndex):
(WebCore::IDBServer::UniqueIDBDatabase::renameIndex):
(WebCore::IDBServer::UniqueIDBDatabase::performRenameIndex):
(WebCore::IDBServer::UniqueIDBDatabase::didPerformRenameIndex):
(WebCore::IDBServer::UniqueIDBDatabase::putOrAdd):
(WebCore::IDBServer::UniqueIDBDatabase::performPutOrAdd):
(WebCore::IDBServer::UniqueIDBDatabase::didPerformPutOrAdd):
(WebCore::IDBServer::UniqueIDBDatabase::getRecord):
(WebCore::IDBServer::UniqueIDBDatabase::getAllRecords):
(WebCore::IDBServer::UniqueIDBDatabase::performGetRecord):
(WebCore::IDBServer::UniqueIDBDatabase::performGetAllRecords):
(WebCore::IDBServer::UniqueIDBDatabase::getCount):
(WebCore::IDBServer::UniqueIDBDatabase::deleteRecord):
(WebCore::IDBServer::UniqueIDBDatabase::openCursor):
(WebCore::IDBServer::UniqueIDBDatabase::iterateCursor):
(WebCore::IDBServer::UniqueIDBDatabase::commitTransaction):
(WebCore::IDBServer::UniqueIDBDatabase::abortTransaction):
(WebCore::IDBServer::UniqueIDBDatabase::requestSpace): Deleted.
(WebCore::IDBServer::UniqueIDBDatabase::waitForRequestSpaceCompletion): Deleted.
(WebCore::IDBServer::UniqueIDBDatabase::startSpaceIncreaseTask): Deleted.
(WebCore::IDBServer::UniqueIDBDatabase::finishSpaceIncreaseTask): Deleted.
(WebCore::IDBServer::UniqueIDBDatabase::createObjectStoreAfterQuotaCheck): Deleted.
(WebCore::IDBServer::UniqueIDBDatabase::deleteObjectStoreAfterQuotaCheck): Deleted.
(WebCore::IDBServer::UniqueIDBDatabase::renameObjectStoreAfterQuotaCheck): Deleted.
(WebCore::IDBServer::UniqueIDBDatabase::clearObjectStoreAfetQuotaCheck): Deleted.
(WebCore::IDBServer::UniqueIDBDatabase::createIndexAfterQuotaCheck): Deleted.
(WebCore::IDBServer::UniqueIDBDatabase::deleteIndexAfterQuotaCheck): Deleted.
(WebCore::IDBServer::UniqueIDBDatabase::renameIndexAfterQuotaCheck): Deleted.
(WebCore::IDBServer::UniqueIDBDatabase::putOrAddAfterQuotaCheck): Deleted.
(WebCore::IDBServer::UniqueIDBDatabase::getRecordAfterQuotaCheck): Deleted.
(WebCore::IDBServer::UniqueIDBDatabase::getAllRecordsAfterQuotaCheck): Deleted.
(WebCore::IDBServer::UniqueIDBDatabase::getCountAfterQuotaCheck): Deleted.
(WebCore::IDBServer::UniqueIDBDatabase::deleteRecordAfterQuotaCheck): Deleted.
(WebCore::IDBServer::UniqueIDBDatabase::openCursorAfterQuotaCheck): Deleted.
(WebCore::IDBServer::UniqueIDBDatabase::iterateCursorAfterQuotaCheck): Deleted.
(WebCore::IDBServer::UniqueIDBDatabase::commitTransactionAfterQuotaCheck): Deleted.
* Modules/indexeddb/server/UniqueIDBDatabase.h:
* Modules/indexeddb/server/UniqueIDBDatabaseConnection.cpp:
(WebCore::IDBServer::UniqueIDBDatabaseConnection::abortTransactionWithoutCallback):
* Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp:
(WebCore::IDBServer::UniqueIDBDatabaseTransaction::abort):
(WebCore::IDBServer::UniqueIDBDatabaseTransaction::putOrAdd):
(WebCore::IDBServer::UniqueIDBDatabaseTransaction::getRecord):
(WebCore::IDBServer::UniqueIDBDatabaseTransaction::getAllRecords):
(WebCore::IDBServer::UniqueIDBDatabaseTransaction::getCount):
(WebCore::IDBServer::UniqueIDBDatabaseTransaction::deleteRecord):
(WebCore::IDBServer::UniqueIDBDatabaseTransaction::openCursor):
(WebCore::IDBServer::UniqueIDBDatabaseTransaction::iterateCursor):
* Modules/indexeddb/shared/InProcessIDBServer.cpp:
(WebCore::InProcessIDBServer::quotaManager):
(WebCore::storageQuotaManagerSpaceRequester):
(WebCore::InProcessIDBServer::InProcessIDBServer):
(WebCore::storageQuotaManagerGetter): Deleted.
* Modules/indexeddb/shared/InProcessIDBServer.h:
* WebCore.xcodeproj/project.pbxproj:
* storage/StorageQuotaManager.cpp:
(WebCore::StorageQuotaManager::create):
(WebCore::StorageQuotaManager::StorageQuotaManager):
(WebCore::StorageQuotaManager::requestSpaceOnMainThread):
(WebCore::StorageQuotaManager::requestSpaceOnBackgroundThread):
(WebCore::StorageQuotaManager::tryGrantRequest):
(WebCore::StorageQuotaManager::updateQuotaBasedOnUsage):
(WebCore::StorageQuotaManager::resetQuotaUpdatedBasedOnUsageForTesting):
(WebCore::StorageQuotaManager::resetQuotaForTesting):
(WebCore::StorageQuotaManager::~StorageQuotaManager): Deleted.
(WebCore::StorageQuotaManager::spaceUsage const): Deleted.
(WebCore::StorageQuotaManager::updateQuotaBasedOnSpaceUsage): Deleted.
(WebCore::StorageQuotaManager::initializeUsersIfNeeded): Deleted.
(WebCore::StorageQuotaManager::askUserToInitialize): Deleted.
(WebCore::StorageQuotaManager::addUser): Deleted.
(WebCore::StorageQuotaManager::shouldAskForMoreSpace const): Deleted.
(WebCore::StorageQuotaManager::removeUser): Deleted.
(WebCore::StorageQuotaManager::requestSpace): Deleted.
(WebCore::StorageQuotaManager::askForMoreSpace): Deleted.
(WebCore::StorageQuotaManager::processPendingRequests): Deleted.
* storage/StorageQuotaManager.h:
(WebCore::StorageQuotaManager::defaultThirdPartyQuotaFromPerOriginQuota):
(WebCore::StorageQuotaManager::StorageQuotaManager): Deleted.
(WebCore::StorageQuotaManager::resetQuota): Deleted.
(WebCore::StorageQuotaManager::state const): Deleted.
* storage/StorageQuotaUser.h: Removed.

Source/WebKit:

* NetworkProcess/NetworkProcess.cpp: Introduce class SessionStorageQuotaManager to manage all
StorageQuotaManagers of the same session.
(WebKit::NetworkProcess::initializeNetworkProcess):
(WebKit::NetworkProcess::addWebsiteDataStore):
(WebKit::NetworkProcess::addSessionStorageQuotaManager):
(WebKit::NetworkProcess::removeSessionStorageQuotaManager):
(WebKit::NetworkProcess::destroySession):
(WebKit::NetworkProcess::deleteWebsiteData):
(WebKit::NetworkProcess::deleteWebsiteDataForOrigins):
(WebKit::NetworkProcess::createIDBServer):
(WebKit::NetworkProcess::addIndexedDatabaseSession):
(WebKit::NetworkProcess::setSessionStorageQuotaManagerIDBRootPath):
(WebKit::NetworkProcess::updateQuotaBasedOnSpaceUsageForTesting):
(WebKit::NetworkProcess::resetQuota):
(WebKit::NetworkProcess::storageQuotaManager):
(WebKit::NetworkProcess::initializeStorageQuota): Deleted.
(WebKit::NetworkProcess::clearStorageQuota): Deleted.
(): Deleted.
(WebKit::NetworkProcess::initializeQuotaUsers): Deleted.
* NetworkProcess/NetworkProcess.h:
(WebKit::NetworkProcess::SessionStorageQuotaManager::SessionStorageQuotaManager):
(WebKit::NetworkProcess::SessionStorageQuotaManager::defaultQuota const):
(WebKit::NetworkProcess::SessionStorageQuotaManager::ensureOriginStorageQuotaManager):
(WebKit::NetworkProcess::SessionStorageQuotaManager::existingStorageQuotaManagers):
(WebKit::NetworkProcess::SessionStorageQuotaManager::cacheRootPath const):
(WebKit::NetworkProcess::SessionStorageQuotaManager::setIDBRootPath):
(WebKit::NetworkProcess::SessionStorageQuotaManager::idbRootPath const):
(WebKit::NetworkProcess::StorageQuotaManagers::defaultQuota const): Deleted.
(WebKit::NetworkProcess::StorageQuotaManagers::setDefaultQuotas): Deleted.
(WebKit::NetworkProcess::StorageQuotaManagers::managersPerOrigin): Deleted.
* NetworkProcess/NetworkProcess.messages.in:
* NetworkProcess/cache/CacheStorageEngine.cpp:
(WebKit::CacheStorage::getDirectorySize):
(WebKit::CacheStorage::Engine::diskUsage): static function to get the disk usage of CacheStorage given
CacheStorage root directory.
(WebKit::CacheStorage::Engine::requestSpace):
(WebKit::CacheStorage::Engine::readCachesFromDisk):
(WebKit::CacheStorage::Engine::writeSizeFile):
(WebKit::CacheStorage::Engine::readSizeFile):
(WebKit::CacheStorage::Engine::initializeQuotaUser): Deleted.
* NetworkProcess/cache/CacheStorageEngine.h:
* NetworkProcess/cache/CacheStorageEngineCache.cpp:
(WebKit::CacheStorage::Cache::put):
(WebKit::CacheStorage::Cache::remove):
* NetworkProcess/cache/CacheStorageEngineCaches.cpp:
(WebKit::CacheStorage::Caches::create):
(WebKit::CacheStorage::Caches::Caches):
(WebKit::CacheStorage::Caches::~Caches):
(WebKit::CacheStorage::Caches::updateSizeFile):
(WebKit::CacheStorage::Caches::initializeSize):
(WebKit::CacheStorage::Caches::clear):
(WebKit::CacheStorage::Caches::requestSpace):
(WebKit::CacheStorage::Caches::writeRecord):
(WebKit::CacheStorage::Caches::removeRecord):
(WebKit::CacheStorage::Caches::whenInitialized): Deleted.
(WebKit::CacheStorage::Caches::resetSpaceUsed): Deleted.
* NetworkProcess/cache/CacheStorageEngineCaches.h:
* Shared/WebsiteDataStoreParameters.cpp:
(WebKit::WebsiteDataStoreParameters::encode const):
(WebKit::WebsiteDataStoreParameters::decode):
* Shared/WebsiteDataStoreParameters.h: Add a cacheStorageDirectory parameter so we know the direcotry of
CacheStorage when we start using WebsiteDataStore.
* UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
(WKWebsiteDataStoreResetQuota):
* UIProcess/API/C/WKWebsiteDataStoreRef.h: Add a C API for reseting quota in TestRunner.
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::resetQuota):
* UIProcess/Network/NetworkProcessProxy.h:
* UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::ensureNetworkProcess):
* UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm:
(WebKit::WebsiteDataStore::parameters):
* UIProcess/WebsiteData/WebsiteDataStore.cpp:
(WebKit::WebsiteDataStore::parameters):
(WebKit::WebsiteDataStore::resetQuota):
* UIProcess/WebsiteData/WebsiteDataStore.h:

Tools:

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebCore/StorageQuotaManager.cpp: Removed as we have a different StorageQuotaManager
implementation now.
* WebKitTestRunner/TestController.cpp: reset StorageQuotaManager's quota between tests.
(WTR::TestController::resetStateToConsistentValues):
(WTR::TestController::resetQuota):
* WebKitTestRunner/TestController.h:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@253025 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 0e40939..0fd8ed1 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,143 @@
+2019-12-02  Sihui Liu  <sihui_liu@apple.com>
+
+        Cross-thread version StorageQuotaManager
+        https://bugs.webkit.org/show_bug.cgi?id=203971
+        <rdar://problem/57290349>
+
+        Reviewed by Chris Dumez.
+
+        Implement a lock-based StorageQuotaManager so that quota check can be done on different threads.
+        If space request is made on a background thread, it needs to hold a lock until it is finished, so no request
+        from different threads can be performed at the same time.
+        If space request is made on the main thread, we will dispatch it to a background thread and schedule a calllback
+        to the main thread when result is available, so the main thread will not be blocked.
+
+        Covered by existing quota related tests.
+
+        * Headers.cmake:
+        * Modules/indexeddb/server/IDBServer.cpp:
+        (WebCore::IDBServer::IDBServer::create):
+        (WebCore::IDBServer::IDBServer::IDBServer):
+        (WebCore::IDBServer::IDBServer::didPerformCloseAndDeleteDatabases):
+        (WebCore::IDBServer::IDBServer::requestSpace):
+        (WebCore::IDBServer::IDBServer::diskUsage):
+        (WebCore::IDBServer::IDBServer::QuotaUser::QuotaUser): Deleted.
+        (WebCore::IDBServer::IDBServer::QuotaUser::~QuotaUser): Deleted.
+        (WebCore::IDBServer::IDBServer::QuotaUser::resetSpaceUsed): Deleted.
+        (WebCore::IDBServer::IDBServer::QuotaUser::computeSpaceUsed): Deleted.
+        (WebCore::IDBServer::IDBServer::QuotaUser::increaseSpaceUsed): Deleted.
+        (WebCore::IDBServer::IDBServer::QuotaUser::decreaseSpaceUsed): Deleted.
+        (WebCore::IDBServer::IDBServer::QuotaUser::whenInitialized): Deleted.
+        (WebCore::IDBServer::IDBServer::QuotaUser::initializeSpaceUsed): Deleted.
+        (WebCore::IDBServer::IDBServer::ensureQuotaUser): Deleted.
+        (WebCore::IDBServer::IDBServer::startComputingSpaceUsedForOrigin): Deleted.
+        (WebCore::IDBServer::IDBServer::computeSpaceUsedForOrigin): Deleted.
+        (WebCore::IDBServer::IDBServer::finishComputingSpaceUsedForOrigin): Deleted.
+        (WebCore::IDBServer::IDBServer::resetSpaceUsed): Deleted.
+        (WebCore::IDBServer::IDBServer::increaseSpaceUsed): Deleted.
+        (WebCore::IDBServer::IDBServer::decreaseSpaceUsed): Deleted.
+        (WebCore::IDBServer::IDBServer::increasePotentialSpaceUsed): Deleted.
+        (WebCore::IDBServer::IDBServer::decreasePotentialSpaceUsed): Deleted.
+        * Modules/indexeddb/server/IDBServer.h:
+        (WebCore::IDBServer::IDBServer::initializeQuotaUser): Deleted.
+        (): Deleted.
+        * Modules/indexeddb/server/UniqueIDBDatabase.cpp:
+        (WebCore::IDBServer::UniqueIDBDatabase::performCurrentOpenOperation):
+        (WebCore::IDBServer::UniqueIDBDatabase::openBackingStore):
+        (WebCore::IDBServer::UniqueIDBDatabase::didOpenBackingStore):
+        (WebCore::IDBServer::UniqueIDBDatabase::createObjectStore):
+        (WebCore::IDBServer::UniqueIDBDatabase::performCreateObjectStore):
+        (WebCore::IDBServer::UniqueIDBDatabase::didPerformCreateObjectStore):
+        (WebCore::IDBServer::UniqueIDBDatabase::deleteObjectStore):
+        (WebCore::IDBServer::UniqueIDBDatabase::renameObjectStore):
+        (WebCore::IDBServer::UniqueIDBDatabase::performRenameObjectStore):
+        (WebCore::IDBServer::UniqueIDBDatabase::didPerformRenameObjectStore):
+        (WebCore::IDBServer::UniqueIDBDatabase::clearObjectStore):
+        (WebCore::IDBServer::UniqueIDBDatabase::createIndex):
+        (WebCore::IDBServer::UniqueIDBDatabase::performCreateIndex):
+        (WebCore::IDBServer::UniqueIDBDatabase::didPerformCreateIndex):
+        (WebCore::IDBServer::UniqueIDBDatabase::deleteIndex):
+        (WebCore::IDBServer::UniqueIDBDatabase::renameIndex):
+        (WebCore::IDBServer::UniqueIDBDatabase::performRenameIndex):
+        (WebCore::IDBServer::UniqueIDBDatabase::didPerformRenameIndex):
+        (WebCore::IDBServer::UniqueIDBDatabase::putOrAdd):
+        (WebCore::IDBServer::UniqueIDBDatabase::performPutOrAdd):
+        (WebCore::IDBServer::UniqueIDBDatabase::didPerformPutOrAdd):
+        (WebCore::IDBServer::UniqueIDBDatabase::getRecord):
+        (WebCore::IDBServer::UniqueIDBDatabase::getAllRecords):
+        (WebCore::IDBServer::UniqueIDBDatabase::performGetRecord):
+        (WebCore::IDBServer::UniqueIDBDatabase::performGetAllRecords):
+        (WebCore::IDBServer::UniqueIDBDatabase::getCount):
+        (WebCore::IDBServer::UniqueIDBDatabase::deleteRecord):
+        (WebCore::IDBServer::UniqueIDBDatabase::openCursor):
+        (WebCore::IDBServer::UniqueIDBDatabase::iterateCursor):
+        (WebCore::IDBServer::UniqueIDBDatabase::commitTransaction):
+        (WebCore::IDBServer::UniqueIDBDatabase::abortTransaction):
+        (WebCore::IDBServer::UniqueIDBDatabase::requestSpace): Deleted.
+        (WebCore::IDBServer::UniqueIDBDatabase::waitForRequestSpaceCompletion): Deleted.
+        (WebCore::IDBServer::UniqueIDBDatabase::startSpaceIncreaseTask): Deleted.
+        (WebCore::IDBServer::UniqueIDBDatabase::finishSpaceIncreaseTask): Deleted.
+        (WebCore::IDBServer::UniqueIDBDatabase::createObjectStoreAfterQuotaCheck): Deleted.
+        (WebCore::IDBServer::UniqueIDBDatabase::deleteObjectStoreAfterQuotaCheck): Deleted.
+        (WebCore::IDBServer::UniqueIDBDatabase::renameObjectStoreAfterQuotaCheck): Deleted.
+        (WebCore::IDBServer::UniqueIDBDatabase::clearObjectStoreAfetQuotaCheck): Deleted.
+        (WebCore::IDBServer::UniqueIDBDatabase::createIndexAfterQuotaCheck): Deleted.
+        (WebCore::IDBServer::UniqueIDBDatabase::deleteIndexAfterQuotaCheck): Deleted.
+        (WebCore::IDBServer::UniqueIDBDatabase::renameIndexAfterQuotaCheck): Deleted.
+        (WebCore::IDBServer::UniqueIDBDatabase::putOrAddAfterQuotaCheck): Deleted.
+        (WebCore::IDBServer::UniqueIDBDatabase::getRecordAfterQuotaCheck): Deleted.
+        (WebCore::IDBServer::UniqueIDBDatabase::getAllRecordsAfterQuotaCheck): Deleted.
+        (WebCore::IDBServer::UniqueIDBDatabase::getCountAfterQuotaCheck): Deleted.
+        (WebCore::IDBServer::UniqueIDBDatabase::deleteRecordAfterQuotaCheck): Deleted.
+        (WebCore::IDBServer::UniqueIDBDatabase::openCursorAfterQuotaCheck): Deleted.
+        (WebCore::IDBServer::UniqueIDBDatabase::iterateCursorAfterQuotaCheck): Deleted.
+        (WebCore::IDBServer::UniqueIDBDatabase::commitTransactionAfterQuotaCheck): Deleted.
+        * Modules/indexeddb/server/UniqueIDBDatabase.h:
+        * Modules/indexeddb/server/UniqueIDBDatabaseConnection.cpp:
+        (WebCore::IDBServer::UniqueIDBDatabaseConnection::abortTransactionWithoutCallback):
+        * Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp:
+        (WebCore::IDBServer::UniqueIDBDatabaseTransaction::abort):
+        (WebCore::IDBServer::UniqueIDBDatabaseTransaction::putOrAdd):
+        (WebCore::IDBServer::UniqueIDBDatabaseTransaction::getRecord):
+        (WebCore::IDBServer::UniqueIDBDatabaseTransaction::getAllRecords):
+        (WebCore::IDBServer::UniqueIDBDatabaseTransaction::getCount):
+        (WebCore::IDBServer::UniqueIDBDatabaseTransaction::deleteRecord):
+        (WebCore::IDBServer::UniqueIDBDatabaseTransaction::openCursor):
+        (WebCore::IDBServer::UniqueIDBDatabaseTransaction::iterateCursor):
+        * Modules/indexeddb/shared/InProcessIDBServer.cpp:
+        (WebCore::InProcessIDBServer::quotaManager):
+        (WebCore::storageQuotaManagerSpaceRequester):
+        (WebCore::InProcessIDBServer::InProcessIDBServer):
+        (WebCore::storageQuotaManagerGetter): Deleted.
+        * Modules/indexeddb/shared/InProcessIDBServer.h:
+        * WebCore.xcodeproj/project.pbxproj:
+        * storage/StorageQuotaManager.cpp:
+        (WebCore::StorageQuotaManager::create):
+        (WebCore::StorageQuotaManager::StorageQuotaManager):
+        (WebCore::StorageQuotaManager::requestSpaceOnMainThread):
+        (WebCore::StorageQuotaManager::requestSpaceOnBackgroundThread):
+        (WebCore::StorageQuotaManager::tryGrantRequest):
+        (WebCore::StorageQuotaManager::updateQuotaBasedOnUsage):
+        (WebCore::StorageQuotaManager::resetQuotaUpdatedBasedOnUsageForTesting):
+        (WebCore::StorageQuotaManager::resetQuotaForTesting):
+        (WebCore::StorageQuotaManager::~StorageQuotaManager): Deleted.
+        (WebCore::StorageQuotaManager::spaceUsage const): Deleted.
+        (WebCore::StorageQuotaManager::updateQuotaBasedOnSpaceUsage): Deleted.
+        (WebCore::StorageQuotaManager::initializeUsersIfNeeded): Deleted.
+        (WebCore::StorageQuotaManager::askUserToInitialize): Deleted.
+        (WebCore::StorageQuotaManager::addUser): Deleted.
+        (WebCore::StorageQuotaManager::shouldAskForMoreSpace const): Deleted.
+        (WebCore::StorageQuotaManager::removeUser): Deleted.
+        (WebCore::StorageQuotaManager::requestSpace): Deleted.
+        (WebCore::StorageQuotaManager::askForMoreSpace): Deleted.
+        (WebCore::StorageQuotaManager::processPendingRequests): Deleted.
+        * storage/StorageQuotaManager.h:
+        (WebCore::StorageQuotaManager::defaultThirdPartyQuotaFromPerOriginQuota):
+        (WebCore::StorageQuotaManager::StorageQuotaManager): Deleted.
+        (WebCore::StorageQuotaManager::resetQuota): Deleted.
+        (WebCore::StorageQuotaManager::state const): Deleted.
+        * storage/StorageQuotaUser.h: Removed.
+
 2019-12-02  Fujii Hironori  <Hironori.Fujii@sony.com>
 
         [MSVC] Add /experimental:newLambdaProcessor switch for better C++ conformance
diff --git a/Source/WebCore/Headers.cmake b/Source/WebCore/Headers.cmake
index a150a37..cb4fe1a 100644
--- a/Source/WebCore/Headers.cmake
+++ b/Source/WebCore/Headers.cmake
@@ -1384,7 +1384,6 @@
     storage/StorageNamespace.h
     storage/StorageNamespaceProvider.h
     storage/StorageQuotaManager.h
-    storage/StorageQuotaUser.h
     storage/StorageType.h
 
     style/StyleChange.h
diff --git a/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp b/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp
index 631c4ce..bba6623 100644
--- a/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp
+++ b/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp
@@ -46,28 +46,28 @@
 namespace WebCore {
 namespace IDBServer {
 
-Ref<IDBServer> IDBServer::create(PAL::SessionID sessionID, QuotaManagerGetter&& quotaManagerGetter)
+Ref<IDBServer> IDBServer::create(PAL::SessionID sessionID, StorageQuotaManagerSpaceRequester&& quotaManagerGetter)
 {
     return adoptRef(*new IDBServer(sessionID, WTFMove(quotaManagerGetter)));
 }
 
-Ref<IDBServer> IDBServer::create(PAL::SessionID sessionID, const String& databaseDirectoryPath, QuotaManagerGetter&& quotaManagerGetter)
+Ref<IDBServer> IDBServer::create(PAL::SessionID sessionID, const String& databaseDirectoryPath, StorageQuotaManagerSpaceRequester&& quotaManagerGetter)
 {
     return adoptRef(*new IDBServer(sessionID, databaseDirectoryPath, WTFMove(quotaManagerGetter)));
 }
 
-IDBServer::IDBServer(PAL::SessionID sessionID, QuotaManagerGetter&& quotaManagerGetter)
+IDBServer::IDBServer(PAL::SessionID sessionID, StorageQuotaManagerSpaceRequester&& spaceRequester)
     : CrossThreadTaskHandler("IndexedDatabase Server", AutodrainedPoolForRunLoop::Use)
     , m_sessionID(sessionID)
-    , m_quotaManagerGetter(WTFMove(quotaManagerGetter))
+    , m_spaceRequester(WTFMove(spaceRequester))
 {
 }
 
-IDBServer::IDBServer(PAL::SessionID sessionID, const String& databaseDirectoryPath, QuotaManagerGetter&& quotaManagerGetter)
+IDBServer::IDBServer(PAL::SessionID sessionID, const String& databaseDirectoryPath, StorageQuotaManagerSpaceRequester&& spaceRequester)
     : CrossThreadTaskHandler("IndexedDatabase Server", AutodrainedPoolForRunLoop::Use)
     , m_sessionID(sessionID)
     , m_databaseDirectoryPath(databaseDirectoryPath)
-    , m_quotaManagerGetter(WTFMove(quotaManagerGetter))
+    , m_spaceRequester(WTFMove(spaceRequester))
 {
     LOG(IndexedDB, "IDBServer created at path %s", databaseDirectoryPath.utf8().data());
     postDatabaseTask(createCrossThreadTask(*this, &IDBServer::upgradeFilesIfNecessary));
@@ -683,157 +683,24 @@
 
 void IDBServer::didPerformCloseAndDeleteDatabases(uint64_t callbackID)
 {
-    for (auto& user : m_quotaUsers.values())
-        user->resetSpaceUsed();
-
     auto callback = m_deleteDatabaseCompletionHandlers.take(callbackID);
     ASSERT(callback);
     callback();
 }
 
-IDBServer::QuotaUser::QuotaUser(IDBServer& server, StorageQuotaManager* manager, ClientOrigin&& origin)
-    : m_server(server)
-    , m_manager(makeWeakPtr(manager))
-    , m_origin(WTFMove(origin))
-    , m_isInitialized(m_server.m_sessionID.isEphemeral())
+StorageQuotaManager::Decision IDBServer::requestSpace(const ClientOrigin& origin, uint64_t taskSize)
 {
-    if (manager)
-        manager->addUser(*this);
+    ASSERT(!isMainThread());
+    return m_spaceRequester(origin, taskSize);
 }
 
-IDBServer::QuotaUser::~QuotaUser()
-{
-    if (m_manager)
-        m_manager->removeUser(*this);
-}
-
-void IDBServer::QuotaUser::resetSpaceUsed()
-{
-    m_spaceUsed = 0;
-
-    if (!m_manager)
-        return;
-
-    if (m_server.m_sessionID.isEphemeral())
-        return;
-
-    if (!m_isInitialized)
-        return;
-
-    ASSERT(!m_initializationCallback);
-
-    m_isInitialized = false;
-
-    // Do add/remove to trigger call to whenInitialized.
-    m_manager->removeUser(*this);
-    m_manager->addUser(*this);
-}
-
-void IDBServer::QuotaUser::computeSpaceUsed()
-{
-    resetSpaceUsed();
-}
-
-void IDBServer::QuotaUser::increaseSpaceUsed(uint64_t size)
-{
-    if (!m_isInitialized)
-        return;
-    ASSERT(m_spaceUsed + size > m_spaceUsed);
-    m_spaceUsed += size;
-}
-void IDBServer::QuotaUser::decreaseSpaceUsed(uint64_t size)
-{
-    if (!m_isInitialized)
-        return;
-    ASSERT(m_spaceUsed >= size);
-    m_spaceUsed -= size;
-}
-
-void IDBServer::QuotaUser::whenInitialized(CompletionHandler<void()>&& callback)
-{
-    if (m_isInitialized) {
-        callback();
-        return;
-    }
-    m_initializationCallback = WTFMove(callback);
-    m_server.startComputingSpaceUsedForOrigin(m_origin);
-}
-
-void IDBServer::QuotaUser::initializeSpaceUsed(uint64_t spaceUsed)
-{
-    ASSERT(m_isInitialized || !m_estimatedSpaceIncrease);
-    m_spaceUsed = spaceUsed;
-    m_isInitialized = true;
-
-    if (auto callback = WTFMove(m_initializationCallback))
-        callback();
-}
-
-IDBServer::QuotaUser& IDBServer::ensureQuotaUser(const ClientOrigin& origin)
-{
-    return *m_quotaUsers.ensure(origin, [this, &origin] {
-        return makeUnique<QuotaUser>(*this, m_quotaManagerGetter(m_sessionID, origin), ClientOrigin { origin });
-    }).iterator->value;
-}
-
-void IDBServer::startComputingSpaceUsedForOrigin(const ClientOrigin& origin)
-{
-    ASSERT(!m_sessionID.isEphemeral());
-    postDatabaseTask(createCrossThreadTask(*this, &IDBServer::computeSpaceUsedForOrigin, origin));
-}
-
-void IDBServer::computeSpaceUsedForOrigin(const ClientOrigin& origin)
+uint64_t IDBServer::diskUsage(const String& rootDirectory, const ClientOrigin& origin)
 {
     ASSERT(!isMainThread());
 
-    auto databaseDirectoryPath = this->databaseDirectoryPathIsolatedCopy();
-    auto oldVersionOriginDirectory = IDBDatabaseIdentifier::databaseDirectoryRelativeToRoot(origin.topOrigin, origin.clientOrigin, databaseDirectoryPath, "v0");
-    auto newVersionOriginDirectory = IDBDatabaseIdentifier::databaseDirectoryRelativeToRoot(origin.topOrigin, origin.clientOrigin, databaseDirectoryPath, "v1");
-    auto size = SQLiteIDBBackingStore::databasesSizeForDirectory(oldVersionOriginDirectory) + SQLiteIDBBackingStore::databasesSizeForDirectory(newVersionOriginDirectory);
-
-    postDatabaseTaskReply(createCrossThreadTask(*this, &IDBServer::finishComputingSpaceUsedForOrigin, origin, size));
-}
-
-void IDBServer::finishComputingSpaceUsedForOrigin(const ClientOrigin& origin, uint64_t spaceUsed)
-{
-    ensureQuotaUser(origin).initializeSpaceUsed(spaceUsed);
-}
-
-void IDBServer::requestSpace(const ClientOrigin& origin, uint64_t taskSize, CompletionHandler<void(StorageQuotaManager::Decision)>&& callback)
-{
-    auto* quotaManager = ensureQuotaUser(origin).manager();
-    if (!quotaManager) {
-        callback(StorageQuotaManager::Decision::Deny);
-        return;
-    }
-
-    quotaManager->requestSpace(taskSize, WTFMove(callback));
-}
-
-void IDBServer::resetSpaceUsed(const ClientOrigin& origin)
-{
-    if (auto* user = m_quotaUsers.get(origin))
-        user->resetSpaceUsed();
-}
-
-void IDBServer::increaseSpaceUsed(const ClientOrigin& origin, uint64_t size)
-{
-    ensureQuotaUser(origin).increaseSpaceUsed(size);
-}
-
-void IDBServer::decreaseSpaceUsed(const ClientOrigin& origin, uint64_t size)
-{
-    ensureQuotaUser(origin).decreaseSpaceUsed(size);
-}
-
-void IDBServer::increasePotentialSpaceUsed(const ClientOrigin& origin, uint64_t taskSize)
-{
-    ensureQuotaUser(origin).increasePotentialSpaceUsed(taskSize);
-}
-
-void IDBServer::decreasePotentialSpaceUsed(const ClientOrigin& origin, uint64_t spaceUsed)
-{
-    ensureQuotaUser(origin).decreasePotentialSpaceUsed(spaceUsed);
+    auto oldVersionOriginDirectory = IDBDatabaseIdentifier::databaseDirectoryRelativeToRoot(origin.topOrigin, origin.clientOrigin, rootDirectory, "v0"_str);
+    auto newVersionOriginDirectory = IDBDatabaseIdentifier::databaseDirectoryRelativeToRoot(origin.topOrigin, origin.clientOrigin, rootDirectory, "v1"_str);
+    return SQLiteIDBBackingStore::databasesSizeForDirectory(oldVersionOriginDirectory) + SQLiteIDBBackingStore::databasesSizeForDirectory(newVersionOriginDirectory);
 }
 
 void IDBServer::upgradeFilesIfNecessary()
diff --git a/Source/WebCore/Modules/indexeddb/server/IDBServer.h b/Source/WebCore/Modules/indexeddb/server/IDBServer.h
index 3877a05..fc1604f 100644
--- a/Source/WebCore/Modules/indexeddb/server/IDBServer.h
+++ b/Source/WebCore/Modules/indexeddb/server/IDBServer.h
@@ -30,7 +30,6 @@
 #include "IDBConnectionToClient.h"
 #include "IDBDatabaseIdentifier.h"
 #include "StorageQuotaManager.h"
-#include "StorageQuotaUser.h"
 #include "UniqueIDBDatabase.h"
 #include "UniqueIDBDatabaseConnection.h"
 #include <pal/HysteresisActivity.h>
@@ -58,9 +57,9 @@
 
 class IDBServer : public RefCounted<IDBServer>, public CrossThreadTaskHandler, public CanMakeWeakPtr<IDBServer> {
 public:
-    using QuotaManagerGetter = WTF::Function<StorageQuotaManager*(PAL::SessionID, const ClientOrigin&)>;
-    static Ref<IDBServer> create(PAL::SessionID, QuotaManagerGetter&&);
-    WEBCORE_EXPORT static Ref<IDBServer> create(PAL::SessionID, const String& databaseDirectoryPath, QuotaManagerGetter&&);
+    using StorageQuotaManagerSpaceRequester = Function<StorageQuotaManager::Decision(const ClientOrigin&, uint64_t spaceRequested)>;
+    static Ref<IDBServer> create(PAL::SessionID, StorageQuotaManagerSpaceRequester&&);
+    WEBCORE_EXPORT static Ref<IDBServer> create(PAL::SessionID, const String& databaseDirectoryPath, StorageQuotaManagerSpaceRequester&&);
 
     WEBCORE_EXPORT void registerConnection(IDBConnectionToClient&);
     WEBCORE_EXPORT void unregisterConnection(IDBConnectionToClient&);
@@ -111,14 +110,8 @@
     WEBCORE_EXPORT void closeAndDeleteDatabasesModifiedSince(WallTime, Function<void ()>&& completionHandler);
     WEBCORE_EXPORT void closeAndDeleteDatabasesForOrigins(const Vector<SecurityOriginData>&, Function<void ()>&& completionHandler);
 
-    void requestSpace(const ClientOrigin&, uint64_t taskSize, CompletionHandler<void(StorageQuotaManager::Decision)>&&);
-    void increasePotentialSpaceUsed(const ClientOrigin&, uint64_t taskSize);
-    void decreasePotentialSpaceUsed(const ClientOrigin&, uint64_t taskSize);
-    void increaseSpaceUsed(const ClientOrigin&, uint64_t size);
-    void decreaseSpaceUsed(const ClientOrigin&, uint64_t size);
-    void resetSpaceUsed(const ClientOrigin&);
-
-    void initializeQuotaUser(const ClientOrigin& origin) { ensureQuotaUser(origin); }
+    StorageQuotaManager::Decision requestSpace(const ClientOrigin&, uint64_t taskSize);
+    WEBCORE_EXPORT static uint64_t diskUsage(const String& rootDirectory, const ClientOrigin&);
 
     WEBCORE_EXPORT void tryStop(ShouldForceStop);
     WEBCORE_EXPORT void resume();
@@ -127,8 +120,8 @@
     void removeDatabase(UniqueIDBDatabase& database) { m_allUniqueIDBDatabases.remove(database); }
 
 private:
-    IDBServer(PAL::SessionID, QuotaManagerGetter&&);
-    IDBServer(PAL::SessionID, const String& databaseDirectoryPath, QuotaManagerGetter&&);
+    IDBServer(PAL::SessionID, StorageQuotaManagerSpaceRequester&&);
+    IDBServer(PAL::SessionID, const String& databaseDirectoryPath, StorageQuotaManagerSpaceRequester&&);
 
     UniqueIDBDatabase& getOrCreateUniqueIDBDatabase(const IDBDatabaseIdentifier&);
     
@@ -145,51 +138,6 @@
     void removeDatabasesModifiedSinceForVersion(WallTime, const String&);
     void removeDatabasesWithOriginsForVersion(const Vector<SecurityOriginData>&, const String&);
 
-    class QuotaUser final : public StorageQuotaUser {
-        WTF_MAKE_FAST_ALLOCATED;
-    public:
-        QuotaUser(IDBServer&, StorageQuotaManager*, ClientOrigin&&);
-        ~QuotaUser();
-
-        StorageQuotaManager* manager() { return m_manager.get(); }
-
-        void setSpaceUsed(uint64_t spaceUsed) { m_spaceUsed = spaceUsed; }
-        void resetSpaceUsed();
-
-        void increasePotentialSpaceUsed(uint64_t increase) { m_estimatedSpaceIncrease += increase; }
-        void decreasePotentialSpaceUsed(uint64_t decrease)
-        {
-            ASSERT(m_estimatedSpaceIncrease >= decrease);
-            m_estimatedSpaceIncrease -= decrease;
-        }
-        void increaseSpaceUsed(uint64_t size);
-        void decreaseSpaceUsed(uint64_t size);
-
-        void initializeSpaceUsed(uint64_t spaceUsed);
-
-    private:
-        uint64_t spaceUsed() const final
-        {
-            ASSERT(m_isInitialized);
-            return m_spaceUsed + m_estimatedSpaceIncrease;
-        }
-        void computeSpaceUsed() final;
-        void whenInitialized(CompletionHandler<void()>&&) final;
-
-        IDBServer& m_server;
-        WeakPtr<StorageQuotaManager> m_manager;
-        ClientOrigin m_origin;
-        bool m_isInitialized { false };
-        uint64_t m_spaceUsed { 0 };
-        uint64_t m_estimatedSpaceIncrease { 0 };
-        CompletionHandler<void()> m_initializationCallback;
-    };
-
-    WEBCORE_EXPORT QuotaUser& ensureQuotaUser(const ClientOrigin&);
-    void startComputingSpaceUsedForOrigin(const ClientOrigin&);
-    void computeSpaceUsedForOrigin(const ClientOrigin&);
-    void finishComputingSpaceUsedForOrigin(const ClientOrigin&, uint64_t spaceUsed);
-
     PAL::SessionID m_sessionID;
     HashMap<IDBConnectionIdentifier, RefPtr<IDBConnectionToClient>> m_connectionMap;
     HashMap<IDBDatabaseIdentifier, std::unique_ptr<UniqueIDBDatabase>> m_uniqueIDBDatabaseMap;
@@ -202,8 +150,7 @@
 
     String m_databaseDirectoryPath;
 
-    HashMap<ClientOrigin, std::unique_ptr<QuotaUser>> m_quotaUsers;
-    QuotaManagerGetter m_quotaManagerGetter;
+    StorageQuotaManagerSpaceRequester m_spaceRequester;
 };
 
 } // namespace IDBServer
diff --git a/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp b/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp
index 8243422..ff8ad8a 100644
--- a/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp
+++ b/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp
@@ -189,56 +189,6 @@
     return makeString("Failed to ", taskName, " in database because not enough space for domain");
 }
 
-void UniqueIDBDatabase::requestSpace(UniqueIDBDatabaseTransaction& transaction, uint64_t taskSize, const char* taskName, CompletionHandler<void(IDBError&&)>&& callback)
-{
-    m_server->requestSpace(m_identifier.origin(), taskSize, [weakThis = makeWeakPtr(this), this, weakTransaction = makeWeakPtr(transaction), taskName, callback = WTFMove(callback)](auto decision) mutable {
-        if (!weakThis) {
-            callback(IDBError { UnknownError });
-            return;
-        }
-
-        if (!weakTransaction) {
-            callback(IDBError { UnknownError });
-            return;
-        }
-        if (m_owningPointerForClose) {
-            // We are closing the database, there is no point in trying to modify the database at that point.
-            callback(IDBError { UnknownError });
-            return;
-        }
-
-        switch (decision) {
-        case StorageQuotaManager::Decision::Deny:
-            callback(IDBError { QuotaExceededError, quotaErrorMessageName(taskName) });
-            return;
-        case StorageQuotaManager::Decision::Grant:
-            callback(IDBError { });
-        };
-    });
-}
-
-void UniqueIDBDatabase::waitForRequestSpaceCompletion(UniqueIDBDatabaseTransaction& transaction, CompletionHandler<void(IDBError&&)>&& callback)
-{
-    requestSpace(transaction, 0, "", WTFMove(callback));
-}
-
-void UniqueIDBDatabase::startSpaceIncreaseTask(uint64_t identifier, uint64_t taskSize)
-{
-    m_server->increasePotentialSpaceUsed(m_identifier.origin(), taskSize);
-    ASSERT(!m_pendingSpaceIncreaseTasks.contains(identifier));
-    m_pendingSpaceIncreaseTasks.add(identifier, taskSize);
-}
-
-void UniqueIDBDatabase::finishSpaceIncreaseTask(uint64_t identifier, bool isTaskSuccessful)
-{
-    auto iterator = m_pendingSpaceIncreaseTasks.find(identifier);
-    ASSERT(iterator != m_pendingSpaceIncreaseTasks.end());
-    m_server->decreasePotentialSpaceUsed(m_identifier.origin(), iterator->value);
-    if (isTaskSuccessful)
-        m_server->increaseSpaceUsed(m_identifier.origin(), iterator->value);
-    m_pendingSpaceIncreaseTasks.remove(iterator);
-}
-
 void UniqueIDBDatabase::performCurrentOpenOperation()
 {
     LOG(IndexedDB, "(main) UniqueIDBDatabase::performCurrentOpenOperation (%p)", this);
@@ -249,29 +199,7 @@
     if (!m_databaseInfo) {
         if (!m_isOpeningBackingStore) {
             m_isOpeningBackingStore = true;
-            // We do not know whether this is an existing or a new database.
-            // We set a small cost so that it is not possible to open an infinite number of database.
-            m_server->requestSpace(m_identifier.origin(), defaultWriteOperationCost, [this, weakThis = makeWeakPtr(this)](auto decision) mutable {
-                if (!weakThis)
-                    return;
-
-                if (m_owningPointerForClose)
-                    return;
-
-                switch (decision) {
-                case StorageQuotaManager::Decision::Deny: {
-                    auto result = IDBResultData::error(m_currentOpenDBRequest->requestData().requestIdentifier(), IDBError { QuotaExceededError, quotaErrorMessageName("openDatabase") });
-                    m_currentOpenDBRequest->connection().didOpenDatabase(result);
-                    m_currentOpenDBRequest = nullptr;
-                    m_isOpeningBackingStore = false;
-                    break;
-                }
-                case StorageQuotaManager::Decision::Grant:
-                    auto callbackID = this->generateUniqueCallbackIdentifier();
-                    startSpaceIncreaseTask(callbackID, defaultWriteOperationCost);
-                    this->postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::openBackingStore, m_identifier, callbackID));
-                };
-            });
+            postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::openBackingStore, m_identifier));
         }
         return;
     }
@@ -835,14 +763,21 @@
     m_openDatabaseConnections.add(adoptRef(connection.leakRef()));
 }
 
-void UniqueIDBDatabase::openBackingStore(const IDBDatabaseIdentifier& identifier, uint64_t taskIdentifier)
+void UniqueIDBDatabase::openBackingStore(const IDBDatabaseIdentifier& identifier)
 {
     ASSERT(!isMainThread());
     LOG(IndexedDB, "(db) UniqueIDBDatabase::openBackingStore (%p)", this);
 
-    ASSERT(!m_backingStore);
-
     IDBDatabaseInfo databaseInfo;
+    m_origin = identifier.origin();
+    // Quota check.
+    auto decision = m_server->requestSpace(m_origin, defaultWriteOperationCost);
+    if (decision == StorageQuotaManager::Decision::Deny) {
+        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didOpenBackingStore, databaseInfo, IDBError(QuotaExceededError, quotaErrorMessageName("OpenBackingStore"))));
+        return;
+    }
+
+    ASSERT(!m_backingStore);
     IDBError error;
     {
         LockHolder locker(m_backingStoreLock);
@@ -852,10 +787,10 @@
         error = m_backingStore->getOrEstablishDatabaseInfo(databaseInfo, locker);
     }
 
-    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didOpenBackingStore, databaseInfo, error,  taskIdentifier));
+    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didOpenBackingStore, databaseInfo, error));
 }
 
-void UniqueIDBDatabase::didOpenBackingStore(const IDBDatabaseInfo& info, const IDBError& error, uint64_t taskIdentifier)
+void UniqueIDBDatabase::didOpenBackingStore(const IDBDatabaseInfo& info, const IDBError& error)
 {
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::didOpenBackingStore");
@@ -866,8 +801,6 @@
     ASSERT(m_isOpeningBackingStore);
     m_isOpeningBackingStore = false;
 
-    finishSpaceIncreaseTask(taskIdentifier, error.isNull());
-
     if (m_hardClosedForUserDelete)
         return;
 
@@ -879,33 +812,22 @@
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::createObjectStore");
 
-    auto taskSize = defaultWriteOperationCost + estimateSize(info);
-    requestSpace(transaction, taskSize, "createObjectStore", [this, taskSize, &transaction, info, callback = WTFMove(callback)](auto error) mutable {
-        if (!error.isNull() && *error.code() != QuotaExceededError) {
-            callback(WTFMove(error));
-            return;
-        }
-        this->createObjectStoreAfterQuotaCheck(taskSize, transaction, info, WTFMove(callback), error);
-    });
-}
-
-void UniqueIDBDatabase::createObjectStoreAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction& transaction, const IDBObjectStoreInfo& info, ErrorCallback callback, const IDBError& quotaError)
-{
     uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
     if (!callbackID)
         return;
 
-    startSpaceIncreaseTask(callbackID, taskSize);
-    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCreateObjectStore, callbackID, transaction.info().identifier(), info,  quotaError));
+    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCreateObjectStore, callbackID, transaction.info().identifier(), info));
 }
 
-void UniqueIDBDatabase::performCreateObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo& info, const IDBError& quotaError)
+void UniqueIDBDatabase::performCreateObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo& info)
 {
     ASSERT(!isMainThread());
     LOG(IndexedDB, "(db) UniqueIDBDatabase::performCreateObjectStore");
 
-    if (!quotaError.isNull()) {
-        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCreateObjectStore, callbackIdentifier, quotaError, info));
+    // Quota check.
+    auto taskSize = defaultWriteOperationCost + estimateSize(info);
+    if (m_server->requestSpace(m_origin, taskSize) == StorageQuotaManager::Decision::Deny) {
+        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCreateObjectStore, callbackIdentifier, IDBError(QuotaExceededError, quotaErrorMessageName("CreateObjectStore")), info));
         return;
     }
 
@@ -924,7 +846,6 @@
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformCreateObjectStore");
 
-    finishSpaceIncreaseTask(callbackIdentifier, error.isNull());
     if (error.isNull())
         m_databaseInfo->addExistingObjectStore(info);
 
@@ -936,17 +857,6 @@
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::deleteObjectStore");
 
-    waitForRequestSpaceCompletion(transaction, [this, &transaction, objectStoreName, callback = WTFMove(callback)](auto&& error) mutable {
-        if (!error.isNull()) {
-            callback(WTFMove(error));
-            return;
-        }
-        this->deleteObjectStoreAfterQuotaCheck(transaction, objectStoreName, WTFMove(callback));
-    });
-}
-
-void UniqueIDBDatabase::deleteObjectStoreAfterQuotaCheck(UniqueIDBDatabaseTransaction& transaction, const String& objectStoreName, ErrorCallback callback)
-{
     uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
     if (!callbackID)
         return;
@@ -991,28 +901,15 @@
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::renameObjectStore");
 
-    auto taskSize = defaultWriteOperationCost + newName.sizeInBytes();
-    requestSpace(transaction, taskSize, "renameObjectStore", [this, taskSize, &transaction, objectStoreIdentifier, newName, callback = WTFMove(callback)](auto error) mutable {
-        if (!error.isNull() && *error.code() != QuotaExceededError) {
-            callback(WTFMove(error));
-            return;
-        }
-        this->renameObjectStoreAfterQuotaCheck(taskSize, transaction, objectStoreIdentifier, newName, WTFMove(callback), error);
-    });
-}
-
-void UniqueIDBDatabase::renameObjectStoreAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, const String& newName, ErrorCallback callback, const IDBError& quotaError)
-{
     uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
     if (!callbackID)
         return;
 
-    IDBError error = quotaError;
+    IDBError error;
     auto* info = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
     if (!info)
         error = IDBError { UnknownError, "Attempt to rename non-existant object store"_s };
 
-    startSpaceIncreaseTask(callbackID, taskSize);
     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performRenameObjectStore, callbackID, transaction.info().identifier(), objectStoreIdentifier, newName, error));
 }
 
@@ -1021,8 +918,10 @@
     ASSERT(!isMainThread());
     LOG(IndexedDB, "(db) UniqueIDBDatabase::performRenameObjectStore");
 
-    if (!error.isNull()) {
-        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformRenameObjectStore, callbackIdentifier, error, objectStoreIdentifier, newName));
+    // Quota check.
+    auto taskSize = defaultWriteOperationCost + newName.sizeInBytes();
+    if (m_server->requestSpace(m_origin, taskSize) == StorageQuotaManager::Decision::Deny) {
+        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformRenameObjectStore, callbackIdentifier, IDBError(QuotaExceededError, quotaErrorMessageName("RenameObjectStore")), objectStoreIdentifier, newName));
         return;
     }
 
@@ -1040,7 +939,6 @@
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformRenameObjectStore");
 
-    finishSpaceIncreaseTask(callbackIdentifier, error.isNull());
     if (error.isNull())
         m_databaseInfo->renameObjectStore(objectStoreIdentifier, newName);
 
@@ -1052,17 +950,6 @@
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::clearObjectStore");
 
-    waitForRequestSpaceCompletion(transaction, [this, &transaction, objectStoreIdentifier, callback = WTFMove(callback)](auto&& error) mutable {
-        if (!error.isNull()) {
-            callback(WTFMove(error));
-            return;
-        }
-        this->clearObjectStoreAfetQuotaCheck(transaction, objectStoreIdentifier, WTFMove(callback));
-    });
-}
-
-void UniqueIDBDatabase::clearObjectStoreAfetQuotaCheck(UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, ErrorCallback callback)
-{
     uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
     if (!callbackID)
         return;
@@ -1097,33 +984,21 @@
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::createIndex");
 
-    auto taskSize = defaultWriteOperationCost + estimateSize(info);
-    requestSpace(transaction, taskSize, "createIndex", [this, taskSize, &transaction, info, callback = WTFMove(callback)](auto error) mutable {
-        if (!error.isNull() && *error.code() != QuotaExceededError) {
-            callback(WTFMove(error));
-            return;
-        }
-        this->createIndexAfterQuotaCheck(taskSize, transaction, info, WTFMove(callback), error);
-    });
-}
-
-void UniqueIDBDatabase::createIndexAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction& transaction, const IDBIndexInfo& info, ErrorCallback callback, const IDBError& quotaError)
-{
     uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
     if (!callbackID)
         return;
 
-    startSpaceIncreaseTask(callbackID, taskSize);
-    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCreateIndex, callbackID, transaction.info().identifier(), info, quotaError));
+    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCreateIndex, callbackID, transaction.info().identifier(), info));
 }
 
-void UniqueIDBDatabase::performCreateIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBIndexInfo& info, const IDBError& quotaError)
+void UniqueIDBDatabase::performCreateIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBIndexInfo& info)
 {
     ASSERT(!isMainThread());
     LOG(IndexedDB, "(db) UniqueIDBDatabase::performCreateIndex");
 
-    if (!quotaError.isNull()) {
-        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCreateIndex, callbackIdentifier, quotaError, info));
+    auto taskSize = defaultWriteOperationCost + estimateSize(info);
+    if (m_server->requestSpace(m_origin, taskSize) == StorageQuotaManager::Decision::Deny) {
+        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCreateIndex, callbackIdentifier, IDBError(QuotaExceededError, quotaErrorMessageName("CreateIndex")), info));
         return;
     }
 
@@ -1148,8 +1023,6 @@
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformCreateIndex");
 
-    finishSpaceIncreaseTask(callbackIdentifier, error.isNull());
-
     if (error.isNull()) {
         ASSERT(m_databaseInfo);
         auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(info.objectStoreIdentifier());
@@ -1165,17 +1038,6 @@
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::deleteIndex");
 
-    waitForRequestSpaceCompletion(transaction, [this, &transaction, objectStoreIdentifier, indexName, callback = WTFMove(callback)](auto&& error) mutable {
-        if (!error.isNull()) {
-            callback(WTFMove(error));
-            return;
-        }
-        this->deleteIndexAfterQuotaCheck(transaction, objectStoreIdentifier, indexName, WTFMove(callback));
-    });
-}
-
-void UniqueIDBDatabase::deleteIndexAfterQuotaCheck(UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, const String& indexName, ErrorCallback callback)
-{
     uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
     if (!callbackID)
         return;
@@ -1229,23 +1091,11 @@
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::renameIndex");
 
-    auto taskSize = defaultWriteOperationCost + newName.sizeInBytes();
-    requestSpace(transaction, taskSize, "renameIndex", [this, taskSize, &transaction, objectStoreIdentifier, indexIdentifier, newName, callback = WTFMove(callback)](auto error) mutable {
-        if (!error.isNull() && *error.code() != QuotaExceededError) {
-            callback(WTFMove(error));
-            return;
-        }
-        this->renameIndexAfterQuotaCheck(taskSize, transaction, objectStoreIdentifier, indexIdentifier, newName, WTFMove(callback), error);
-    });
-}
-
-void UniqueIDBDatabase::renameIndexAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName, ErrorCallback callback, const IDBError& quotaError)
-{
     uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
     if (!callbackID)
         return;
 
-    IDBError error = quotaError;
+    IDBError error;
     auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
     if (!objectStoreInfo)
         error = IDBError { UnknownError, "Attempt to rename index in non-existant object store"_s };
@@ -1254,7 +1104,6 @@
     if (!indexInfo)
         error = IDBError { UnknownError, "Attempt to rename non-existant index"_s };
 
-    startSpaceIncreaseTask(callbackID, taskSize);
     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performRenameIndex, callbackID, transaction.info().identifier(), objectStoreIdentifier, indexIdentifier, newName, error));
 }
 
@@ -1263,8 +1112,10 @@
     ASSERT(!isMainThread());
     LOG(IndexedDB, "(db) UniqueIDBDatabase::performRenameIndex");
 
-    if (!error.isNull()) {
-        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformRenameIndex, callbackIdentifier, error, objectStoreIdentifier, indexIdentifier, newName));
+    // Quota check.
+    auto taskSize = defaultWriteOperationCost + newName.sizeInBytes();
+    if (m_server->requestSpace(m_origin, taskSize) == StorageQuotaManager::Decision::Deny) {
+        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformRenameIndex, callbackIdentifier, IDBError(QuotaExceededError, quotaErrorMessageName("RenameIndex")), objectStoreIdentifier, indexIdentifier, newName));
         return;
     }
 
@@ -1282,7 +1133,6 @@
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformRenameIndex");
 
-    finishSpaceIncreaseTask(callbackIdentifier, error.isNull());
     if (error.isNull()) {
         auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
         ASSERT(objectStoreInfo);
@@ -1296,52 +1146,39 @@
     performErrorCallback(callbackIdentifier, error);
 }
 
-void UniqueIDBDatabase::putOrAdd(UniqueIDBDatabaseTransaction& transaction, const IDBRequestData& requestData, const IDBKeyData& keyData, const IDBValue& value, IndexedDB::ObjectStoreOverwriteMode overwriteMode, KeyDataCallback callback)
+void UniqueIDBDatabase::putOrAdd(const IDBRequestData& requestData, const IDBKeyData& keyData, const IDBValue& value, IndexedDB::ObjectStoreOverwriteMode overwriteMode, KeyDataCallback callback)
 {
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::putOrAdd");
 
-    auto taskSize = defaultWriteOperationCost + estimateSize(keyData) + estimateSize(value);
-    ASSERT(m_databaseInfo);
-    auto* objectStore = m_databaseInfo->infoForExistingObjectStore(requestData.objectStoreIdentifier());
-    if (objectStore)
-        taskSize += objectStore->indexNames().size() * taskSize;
-
-    requestSpace(transaction, taskSize, "putOrAdd", [this, taskSize, requestData, keyData, value, callback = WTFMove(callback), overwriteMode](auto error) mutable {
-        if (!error.isNull() && *error.code() != QuotaExceededError) {
-            callback(WTFMove(error), { });
-            return;
-        }
-        this->putOrAddAfterQuotaCheck(taskSize, requestData, keyData, value, overwriteMode, WTFMove(callback), error);
-    });
-}
-
-void UniqueIDBDatabase::putOrAddAfterQuotaCheck(uint64_t taskSize, const IDBRequestData& requestData, const IDBKeyData& keyData, const IDBValue& value, IndexedDB::ObjectStoreOverwriteMode overwriteMode, KeyDataCallback callback, const IDBError& quotaError)
-{
     uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
     if (!callbackID)
         return;
 
-    startSpaceIncreaseTask(callbackID, taskSize);
-    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performPutOrAdd, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), keyData, value, overwriteMode, quotaError));
+    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performPutOrAdd, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), keyData, value, overwriteMode));
 }
 
-void UniqueIDBDatabase::performPutOrAdd(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData& keyData, const IDBValue& originalRecordValue, IndexedDB::ObjectStoreOverwriteMode overwriteMode, const IDBError& quotaError)
+void UniqueIDBDatabase::performPutOrAdd(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData& keyData, const IDBValue& originalRecordValue, IndexedDB::ObjectStoreOverwriteMode overwriteMode)
 {
     ASSERT(!isMainThread());
     LOG(IndexedDB, "(db) UniqueIDBDatabase::performPutOrAdd");
 
-    ASSERT(m_backingStore);
-    ASSERT(objectStoreIdentifier);
-
     IDBKeyData usedKey;
     IDBError error;
 
-    if (!quotaError.isNull()) {
-        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, quotaError, usedKey));
+    // Quota check.
+    auto taskSize = defaultWriteOperationCost + estimateSize(keyData) + estimateSize(originalRecordValue);
+    ASSERT(m_databaseInfo);
+    auto* objectStore = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
+    if (objectStore)
+        taskSize += objectStore->indexNames().size() * taskSize;
+    if (m_server->requestSpace(m_origin, taskSize) == StorageQuotaManager::Decision::Deny) {
+        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, IDBError(QuotaExceededError, quotaErrorMessageName("PutOrAdd")), usedKey));
         return;
     }
 
+    ASSERT(m_backingStore);
+    ASSERT(objectStoreIdentifier);
     {
         LockHolder locker(m_backingStoreLock);
         if (!m_backingStore) {
@@ -1418,26 +1255,14 @@
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformPutOrAdd");
 
-    finishSpaceIncreaseTask(callbackIdentifier, error.isNull());
     performKeyDataCallback(callbackIdentifier, error, resultKey);
 }
 
-void UniqueIDBDatabase::getRecord(UniqueIDBDatabaseTransaction& transaction, const IDBRequestData& requestData, const IDBGetRecordData& getRecordData, GetResultCallback callback)
+void UniqueIDBDatabase::getRecord(const IDBRequestData& requestData, const IDBGetRecordData& getRecordData, GetResultCallback callback)
 {
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::getRecord");
 
-    waitForRequestSpaceCompletion(transaction, [this, requestData, getRecordData, callback = WTFMove(callback)](auto&& error) mutable {
-        if (!error.isNull()) {
-            callback(WTFMove(error), { });
-            return;
-        }
-        this->getRecordAfterQuotaCheck(requestData, getRecordData, WTFMove(callback));
-    });
-}
-
-void UniqueIDBDatabase::getRecordAfterQuotaCheck(const IDBRequestData& requestData, const IDBGetRecordData& getRecordData, GetResultCallback callback)
-{
     uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
     if (!callbackID)
         return;
@@ -1448,22 +1273,11 @@
         postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetRecord, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), getRecordData.keyRangeData, getRecordData.type));
 }
 
-void UniqueIDBDatabase::getAllRecords(UniqueIDBDatabaseTransaction& transaction, const IDBRequestData& requestData, const IDBGetAllRecordsData& getAllRecordsData, GetAllResultsCallback callback)
+void UniqueIDBDatabase::getAllRecords(const IDBRequestData& requestData, const IDBGetAllRecordsData& getAllRecordsData, GetAllResultsCallback callback)
 {
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::getAllRecords");
 
-    waitForRequestSpaceCompletion(transaction, [this, requestData, getAllRecordsData, callback = WTFMove(callback)](auto&& error) mutable {
-        if (!error.isNull()) {
-            callback(WTFMove(error), { });
-            return;
-        }
-        this->getAllRecordsAfterQuotaCheck(requestData, getAllRecordsData, WTFMove(callback));
-    });
-}
-
-void UniqueIDBDatabase::getAllRecordsAfterQuotaCheck(const IDBRequestData& requestData, const IDBGetAllRecordsData& getAllRecordsData, GetAllResultsCallback callback)
-{
     uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
     if (!callbackID)
         return;
@@ -1477,7 +1291,6 @@
     LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetRecord");
 
     ASSERT(m_backingStore);
-
     IDBGetResult result;
     IDBError error;
     {
@@ -1518,7 +1331,6 @@
     LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetAllRecords");
 
     ASSERT(m_backingStore);
-
     IDBGetAllResult result;
     IDBError error;
     {
@@ -1537,22 +1349,11 @@
     performGetAllResultsCallback(callbackIdentifier, error, result);
 }
 
-void UniqueIDBDatabase::getCount(UniqueIDBDatabaseTransaction& transaction, const IDBRequestData& requestData, const IDBKeyRangeData& range, CountCallback callback)
+void UniqueIDBDatabase::getCount(const IDBRequestData& requestData, const IDBKeyRangeData& range, CountCallback callback)
 {
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::getCount");
 
-    waitForRequestSpaceCompletion(transaction, [this, requestData, range, callback = WTFMove(callback)](auto&& error) mutable {
-        if (!error.isNull()) {
-            callback(WTFMove(error), { });
-            return;
-        }
-        this->getCountAfterQuotaCheck(requestData, range, WTFMove(callback));
-    });
-}
-
-void UniqueIDBDatabase::getCountAfterQuotaCheck(const IDBRequestData& requestData, const IDBKeyRangeData& range, CountCallback callback)
-{
     uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
     if (!callbackID)
         return;
@@ -1585,22 +1386,11 @@
     performCountCallback(callbackIdentifier, error, count);
 }
 
-void UniqueIDBDatabase::deleteRecord(UniqueIDBDatabaseTransaction& transaction, const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData, ErrorCallback callback)
+void UniqueIDBDatabase::deleteRecord(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData, ErrorCallback callback)
 {
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::deleteRecord");
 
-    waitForRequestSpaceCompletion(transaction, [this, requestData, keyRangeData, callback = WTFMove(callback)](auto&& error) mutable {
-        if (!error.isNull()) {
-            callback(WTFMove(error));
-            return;
-        }
-        this->deleteRecordAfterQuotaCheck(requestData, keyRangeData, WTFMove(callback));
-    });
-}
-
-void UniqueIDBDatabase::deleteRecordAfterQuotaCheck(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData, ErrorCallback callback)
-{
     uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
     if (!callbackID)
         return;
@@ -1629,22 +1419,11 @@
     performErrorCallback(callbackIdentifier, error);
 }
 
-void UniqueIDBDatabase::openCursor(UniqueIDBDatabaseTransaction& transaction, const IDBRequestData& requestData, const IDBCursorInfo& info, GetResultCallback callback)
+void UniqueIDBDatabase::openCursor(const IDBRequestData& requestData, const IDBCursorInfo& info, GetResultCallback callback)
 {
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::openCursor");
 
-    waitForRequestSpaceCompletion(transaction, [this, requestData, info, callback = WTFMove(callback)](auto&& error) mutable {
-        if (!error.isNull()) {
-            callback(WTFMove(error), { });
-            return;
-        }
-        this->openCursorAfterQuotaCheck(requestData, info, WTFMove(callback));
-    });
-}
-
-void UniqueIDBDatabase::openCursorAfterQuotaCheck(const IDBRequestData& requestData, const IDBCursorInfo& info, GetResultCallback callback)
-{
     uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
     if (!callbackID)
         return;
@@ -1674,22 +1453,11 @@
     performGetResultCallback(callbackIdentifier, error, result);
 }
 
-void UniqueIDBDatabase::iterateCursor(UniqueIDBDatabaseTransaction& transaction, const IDBRequestData& requestData, const IDBIterateCursorData& data, GetResultCallback callback)
+void UniqueIDBDatabase::iterateCursor(const IDBRequestData& requestData, const IDBIterateCursorData& data, GetResultCallback callback)
 {
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::iterateCursor");
 
-    waitForRequestSpaceCompletion(transaction, [this, requestData, data, callback = WTFMove(callback)](auto&& error) mutable {
-        if (!error.isNull()) {
-            callback(WTFMove(error), { });
-            return;
-        }
-        this->iterateCursorAfterQuotaCheck(requestData, data, WTFMove(callback));
-    });
-}
-
-void UniqueIDBDatabase::iterateCursorAfterQuotaCheck(const IDBRequestData& requestData, const IDBIterateCursorData& data, GetResultCallback callback)
-{
     uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
     if (!callbackID)
         return;
@@ -1767,17 +1535,6 @@
 
     ASSERT(transaction.databaseConnection().database() == this);
 
-    waitForRequestSpaceCompletion(transaction, [this, &transaction, callback = WTFMove(callback)](auto&& error) mutable {
-        if (!error.isNull()) {
-            callback(WTFMove(error));
-            return;
-        }
-        this->commitTransactionAfterQuotaCheck(transaction, WTFMove(callback));
-    });
-}
-
-void UniqueIDBDatabase::commitTransactionAfterQuotaCheck(UniqueIDBDatabaseTransaction& transaction, ErrorCallback callback)
-{
     uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
     if (!callbackID)
         return;
@@ -1835,24 +1592,13 @@
     transactionCompleted(m_finishingTransactions.take(transactionIdentifier));
 }
 
-void UniqueIDBDatabase::abortTransaction(UniqueIDBDatabaseTransaction& transaction, WaitForPendingTasks waitForPendingTasks, ErrorCallback callback)
+void UniqueIDBDatabase::abortTransaction(UniqueIDBDatabaseTransaction& transaction, ErrorCallback callback)
 {
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::abortTransaction - %s", transaction.info().identifier().loggingString().utf8().data());
 
     ASSERT(transaction.databaseConnection().database() == this);
 
-    if (waitForPendingTasks == WaitForPendingTasks::Yes) {
-        waitForRequestSpaceCompletion(transaction, [this, &transaction, callback = WTFMove(callback)](auto&& error) mutable {
-            if (!error.isNull()) {
-                callback(WTFMove(error));
-                return;
-            }
-            this->abortTransaction(transaction, WaitForPendingTasks::No, WTFMove(callback));
-        });
-        return;
-    }
-
     uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
     if (!callbackID)
         return;
diff --git a/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h b/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h
index c358de49..ebfc1c5 100644
--- a/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h
+++ b/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h
@@ -44,6 +44,7 @@
 
 namespace WebCore {
 
+struct ClientOrigin;
 class IDBError;
 class IDBGetAllResult;
 struct IDBGetRecordData;
@@ -89,17 +90,15 @@
     void createIndex(UniqueIDBDatabaseTransaction&, const IDBIndexInfo&, ErrorCallback);
     void deleteIndex(UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, const String& indexName, ErrorCallback);
     void renameIndex(UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName, ErrorCallback);
-    void putOrAdd(UniqueIDBDatabaseTransaction&, const IDBRequestData&, const IDBKeyData&, const IDBValue&, IndexedDB::ObjectStoreOverwriteMode, KeyDataCallback);
-    void getRecord(UniqueIDBDatabaseTransaction&, const IDBRequestData&, const IDBGetRecordData&, GetResultCallback);
-    void getAllRecords(UniqueIDBDatabaseTransaction&, const IDBRequestData&, const IDBGetAllRecordsData&, GetAllResultsCallback);
-    void getCount(UniqueIDBDatabaseTransaction&, const IDBRequestData&, const IDBKeyRangeData&, CountCallback);
-    void deleteRecord(UniqueIDBDatabaseTransaction&, const IDBRequestData&, const IDBKeyRangeData&, ErrorCallback);
-    void openCursor(UniqueIDBDatabaseTransaction&, const IDBRequestData&, const IDBCursorInfo&, GetResultCallback);
-    void iterateCursor(UniqueIDBDatabaseTransaction&, const IDBRequestData&, const IDBIterateCursorData&, GetResultCallback);
+    void putOrAdd(const IDBRequestData&, const IDBKeyData&, const IDBValue&, IndexedDB::ObjectStoreOverwriteMode, KeyDataCallback);
+    void getRecord(const IDBRequestData&, const IDBGetRecordData&, GetResultCallback);
+    void getAllRecords(const IDBRequestData&, const IDBGetAllRecordsData&, GetAllResultsCallback);
+    void getCount(const IDBRequestData&, const IDBKeyRangeData&, CountCallback);
+    void deleteRecord(const IDBRequestData&, const IDBKeyRangeData&, ErrorCallback);
+    void openCursor(const IDBRequestData&, const IDBCursorInfo&, GetResultCallback);
+    void iterateCursor(const IDBRequestData&, const IDBIterateCursorData&, GetResultCallback);
     void commitTransaction(UniqueIDBDatabaseTransaction&, ErrorCallback);
-
-    enum class WaitForPendingTasks { No, Yes };
-    void abortTransaction(UniqueIDBDatabaseTransaction&, WaitForPendingTasks, ErrorCallback);
+    void abortTransaction(UniqueIDBDatabaseTransaction&, ErrorCallback);
 
     void didFinishHandlingVersionChange(UniqueIDBDatabaseConnection&, const IDBResourceIdentifier& transactionIdentifier);
     void transactionDestroyed(UniqueIDBDatabaseTransaction&);
@@ -140,37 +139,20 @@
 
     void scheduleShutdownForClose();
 
-    void createObjectStoreAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction&, const IDBObjectStoreInfo&, ErrorCallback, const IDBError&);
-    void renameObjectStoreAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, const String& newName, ErrorCallback, const IDBError&);
-    void createIndexAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction&, const IDBIndexInfo&, ErrorCallback, const IDBError&);
-    void renameIndexAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName, ErrorCallback, const IDBError&);
-    void putOrAddAfterQuotaCheck(uint64_t taskSize, const IDBRequestData&, const IDBKeyData&, const IDBValue&, IndexedDB::ObjectStoreOverwriteMode, KeyDataCallback, const IDBError&);
-    void deleteRecordAfterQuotaCheck(const IDBRequestData&, const IDBKeyRangeData&, ErrorCallback);
-
-    void deleteObjectStoreAfterQuotaCheck(UniqueIDBDatabaseTransaction&, const String& objectStoreName, ErrorCallback);
-    void clearObjectStoreAfetQuotaCheck(UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, ErrorCallback);
-    void deleteIndexAfterQuotaCheck(UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, const String&, ErrorCallback);
-    void getRecordAfterQuotaCheck(const IDBRequestData&, const IDBGetRecordData&, GetResultCallback);
-    void getAllRecordsAfterQuotaCheck(const IDBRequestData&, const IDBGetAllRecordsData&, GetAllResultsCallback);
-    void getCountAfterQuotaCheck(const IDBRequestData&, const IDBKeyRangeData&, CountCallback);
-    void openCursorAfterQuotaCheck(const IDBRequestData&, const IDBCursorInfo&, GetResultCallback);
-    void iterateCursorAfterQuotaCheck(const IDBRequestData&, const IDBIterateCursorData&, GetResultCallback);
-    void commitTransactionAfterQuotaCheck(UniqueIDBDatabaseTransaction&, ErrorCallback);
-
     // Database thread operations
     void deleteBackingStore(const IDBDatabaseIdentifier&);
-    void openBackingStore(const IDBDatabaseIdentifier&, uint64_t taskIdentifier);
+    void openBackingStore(const IDBDatabaseIdentifier&);
     void performCommitTransaction(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier);
     void performAbortTransaction(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier);
     void beginTransactionInBackingStore(const IDBTransactionInfo&);
-    void performCreateObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo&, const IDBError&);
+    void performCreateObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo&);
     void performDeleteObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier);
     void performRenameObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const String& newName, const IDBError&);
     void performClearObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier);
-    void performCreateIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBIndexInfo&, const IDBError&);
+    void performCreateIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBIndexInfo&);
     void performDeleteIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier);
     void performRenameIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName, const IDBError&);
-    void performPutOrAdd(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData&, const IDBValue&, IndexedDB::ObjectStoreOverwriteMode, const IDBError&);
+    void performPutOrAdd(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData&, const IDBValue&, IndexedDB::ObjectStoreOverwriteMode);
     void performGetRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&, IDBGetRecordDataType);
     void performGetAllRecords(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBGetAllRecordsData&);
     void performGetIndexRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, IndexedDB::IndexRecordType, const IDBKeyRangeData&);
@@ -187,7 +169,7 @@
 
     // Main thread callbacks
     void didDeleteBackingStore(uint64_t deletedVersion);
-    void didOpenBackingStore(const IDBDatabaseInfo&, const IDBError&, uint64_t taskIdentifier);
+    void didOpenBackingStore(const IDBDatabaseInfo&, const IDBError&);
     void didPerformCreateObjectStore(uint64_t callbackIdentifier, const IDBError&, const IDBObjectStoreInfo&);
     void didPerformDeleteObjectStore(uint64_t callbackIdentifier, const IDBError&, uint64_t objectStoreIdentifier);
     void didPerformRenameObjectStore(uint64_t callbackIdentifier, const IDBError&, uint64_t objectStoreIdentifier, const String& newName);
@@ -246,11 +228,6 @@
     void maybeFinishHardClose();
     bool isDoneWithHardClose();
 
-    void requestSpace(UniqueIDBDatabaseTransaction&, uint64_t taskSize, const char* errorMessage, CompletionHandler<void(IDBError&&)>&&);
-    void waitForRequestSpaceCompletion(UniqueIDBDatabaseTransaction&, CompletionHandler<void(IDBError&&)>&&);
-    void startSpaceIncreaseTask(uint64_t identifier, uint64_t taskSize);
-    void finishSpaceIncreaseTask(uint64_t identifier, bool isTaskSuccessful);
-
     void clearTransactionsOnConnection(UniqueIDBDatabaseConnection&);
 
     static uint64_t generateUniqueCallbackIdentifier();
@@ -311,9 +288,9 @@
 
     HashSet<IDBResourceIdentifier> m_cursorPrefetches;
 
-    HashMap<uint64_t, uint64_t> m_pendingSpaceIncreaseTasks;
-
     bool m_isSuspended { false };
+
+    ClientOrigin m_origin;
 };
 
 } // namespace IDBServer
diff --git a/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseConnection.cpp b/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseConnection.cpp
index fe910fa..8006069 100644
--- a/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseConnection.cpp
+++ b/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseConnection.cpp
@@ -76,7 +76,7 @@
     if (!m_database)
         return;
     
-    m_database->abortTransaction(transaction, UniqueIDBDatabase::WaitForPendingTasks::No, [this, protectedThis, transactionIdentifier](const IDBError&) {
+    m_database->abortTransaction(transaction, [this, protectedThis, transactionIdentifier](const IDBError&) {
         ASSERT(m_transactionMap.contains(transactionIdentifier));
         m_transactionMap.remove(transactionIdentifier);
     });
diff --git a/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp b/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp
index a8d2bdc..76eddc4 100644
--- a/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp
+++ b/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp
@@ -79,7 +79,7 @@
     auto database = m_databaseConnection->database();
     ASSERT(database);
 
-    database->abortTransaction(*this, UniqueIDBDatabase::WaitForPendingTasks::Yes, [this, weakThis = makeWeakPtr(*this)](auto& error) {
+    database->abortTransaction(*this, [this, weakThis = makeWeakPtr(*this)](auto& error) {
         LOG(IndexedDB, "UniqueIDBDatabaseTransaction::abort (callback)");
         if (!weakThis)
             return;
@@ -286,7 +286,7 @@
     auto database = m_databaseConnection->database();
     ASSERT(database);
     
-    database->putOrAdd(*this, requestData, keyData, value, overwriteMode, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, const IDBKeyData& key) {
+    database->putOrAdd(requestData, keyData, value, overwriteMode, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, const IDBKeyData& key) {
         LOG(IndexedDB, "UniqueIDBDatabaseTransaction::putOrAdd (callback)");
         if (!weakThis)
             return;
@@ -307,7 +307,7 @@
     auto database = m_databaseConnection->database();
     ASSERT(database);
     
-    database->getRecord(*this, requestData, getRecordData, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, const IDBGetResult& result) {
+    database->getRecord(requestData, getRecordData, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, const IDBGetResult& result) {
         LOG(IndexedDB, "UniqueIDBDatabaseTransaction::getRecord (callback)");
         if (!weakThis)
             return;
@@ -328,7 +328,7 @@
     auto database = m_databaseConnection->database();
     ASSERT(database);
     
-    database->getAllRecords(*this, requestData, getAllRecordsData, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, const IDBGetAllResult& result) {
+    database->getAllRecords(requestData, getAllRecordsData, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, const IDBGetAllResult& result) {
         LOG(IndexedDB, "UniqueIDBDatabaseTransaction::getAllRecords (callback)");
         if (!weakThis)
             return;
@@ -349,7 +349,7 @@
     auto database = m_databaseConnection->database();
     ASSERT(database);
     
-    database->getCount(*this, requestData, keyRangeData, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, uint64_t count) {
+    database->getCount(requestData, keyRangeData, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, uint64_t count) {
         LOG(IndexedDB, "UniqueIDBDatabaseTransaction::getCount (callback)");
         if (!weakThis)
             return;
@@ -370,7 +370,7 @@
     auto database = m_databaseConnection->database();
     ASSERT(database);
     
-    database->deleteRecord(*this, requestData, keyRangeData, [this, weakThis = makeWeakPtr(*this), requestData](auto& error) {
+    database->deleteRecord(requestData, keyRangeData, [this, weakThis = makeWeakPtr(*this), requestData](auto& error) {
         LOG(IndexedDB, "UniqueIDBDatabaseTransaction::deleteRecord (callback)");
         if (!weakThis)
             return;
@@ -391,7 +391,7 @@
     auto database = m_databaseConnection->database();
     ASSERT(database);
     
-    database->openCursor(*this, requestData, info, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, const IDBGetResult& result) {
+    database->openCursor(requestData, info, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, const IDBGetResult& result) {
         LOG(IndexedDB, "UniqueIDBDatabaseTransaction::openCursor (callback)");
         if (!weakThis)
             return;
@@ -412,7 +412,7 @@
     auto database = m_databaseConnection->database();
     ASSERT(database);
     
-    database->iterateCursor(*this, requestData, data, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, const IDBGetResult& result) {
+    database->iterateCursor(requestData, data, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, const IDBGetResult& result) {
         LOG(IndexedDB, "UniqueIDBDatabaseTransaction::iterateCursor (callback)");
         if (!weakThis)
             return;
diff --git a/Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.cpp b/Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.cpp
index 9111f59..d65bd5a 100644
--- a/Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.cpp
+++ b/Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.cpp
@@ -64,30 +64,35 @@
 StorageQuotaManager* InProcessIDBServer::quotaManager(const ClientOrigin& origin)
 {
     return m_quotaManagers.ensure(origin, [] {
-        return makeUnique<StorageQuotaManager>(StorageQuotaManager::defaultQuota(), [](uint64_t quota, uint64_t currentSpace, uint64_t spaceIncrease, auto callback) {
+        return StorageQuotaManager::create(StorageQuotaManager::defaultQuota(), [] {
+            return 0;
+        }, [](uint64_t quota, uint64_t currentSpace, uint64_t spaceIncrease, auto callback) {
             callback(quota + currentSpace + spaceIncrease);
         });
     }).iterator->value.get();
 }
 
-static inline IDBServer::IDBServer::QuotaManagerGetter storageQuotaManagerGetter(InProcessIDBServer& server)
+static inline IDBServer::IDBServer::StorageQuotaManagerSpaceRequester storageQuotaManagerSpaceRequester(InProcessIDBServer& server)
 {
-    return [weakServer = makeWeakPtr(server)](PAL::SessionID, const auto& origin) {
-        return weakServer ? weakServer->quotaManager(origin) : nullptr;
+    return [server = &server, weakServer = makeWeakPtr(server)](const ClientOrigin& origin, uint64_t spaceRequested) mutable {
+        auto* storageQuotaManager = weakServer ? server->quotaManager(origin) : nullptr;
+        return storageQuotaManager ? storageQuotaManager->requestSpaceOnBackgroundThread(spaceRequested) : StorageQuotaManager::Decision::Deny;
     };
 }
 
 InProcessIDBServer::InProcessIDBServer(PAL::SessionID sessionID)
-    : m_server(IDBServer::IDBServer::create(sessionID, storageQuotaManagerGetter(*this)))
+    : m_server(IDBServer::IDBServer::create(sessionID, storageQuotaManagerSpaceRequester(*this)))
 {
+    ASSERT(isMainThread());
     relaxAdoptionRequirement();
     m_connectionToServer = IDBClient::IDBConnectionToServer::create(*this);
     m_connectionToClient = IDBServer::IDBConnectionToClient::create(*this);
 }
 
 InProcessIDBServer::InProcessIDBServer(PAL::SessionID sessionID, const String& databaseDirectoryPath)
-    : m_server(IDBServer::IDBServer::create(sessionID, databaseDirectoryPath, storageQuotaManagerGetter(*this)))
+    : m_server(IDBServer::IDBServer::create(sessionID, databaseDirectoryPath, storageQuotaManagerSpaceRequester(*this)))
 {
+    ASSERT(isMainThread());
     relaxAdoptionRequirement();
     m_connectionToServer = IDBClient::IDBConnectionToServer::create(*this);
     m_connectionToClient = IDBServer::IDBConnectionToClient::create(*this);
diff --git a/Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.h b/Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.h
index c7b5321..8e736a7 100644
--- a/Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.h
+++ b/Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.h
@@ -64,7 +64,6 @@
     WEBCORE_EXPORT IDBClient::IDBConnectionToServer& connectionToServer() const;
     IDBServer::IDBConnectionToClient& connectionToClient() const;
     IDBServer::IDBServer& server() { return m_server.get(); }
-
     IDBServer::IDBServer& idbServer() { return m_server.get(); }
 
     // IDBConnectionToServer
@@ -135,7 +134,7 @@
     RefPtr<IDBClient::IDBConnectionToServer> m_connectionToServer;
     RefPtr<IDBServer::IDBConnectionToClient> m_connectionToClient;
 
-    HashMap<ClientOrigin, std::unique_ptr<StorageQuotaManager>> m_quotaManagers;
+    HashMap<ClientOrigin, RefPtr<StorageQuotaManager>> m_quotaManagers;
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
index 6a4785b..9475d06 100644
--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -1129,7 +1129,6 @@
 		41D28D0D2139E05800F4206F /* LibWebRTCStatsCollector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41D28D0B2139E01D00F4206F /* LibWebRTCStatsCollector.cpp */; };
 		41D41C672256874F00697942 /* ServiceWorkerInternals.mm in Sources */ = {isa = PBXBuildFile; fileRef = 41D41C652256859200697942 /* ServiceWorkerInternals.mm */; };
 		41DE7C7C222DA14300532B65 /* StorageQuotaManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 41DE7C7B222DA13E00532B65 /* StorageQuotaManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
-		41DE7C7D222DA14800532B65 /* StorageQuotaUser.h in Headers */ = {isa = PBXBuildFile; fileRef = 41DE7C78222DA13C00532B65 /* StorageQuotaUser.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		41DEFCB61E56C1BD000D9E5F /* JSDOMMapLike.h in Headers */ = {isa = PBXBuildFile; fileRef = 41DEFCB41E56C1B9000D9E5F /* JSDOMMapLike.h */; };
 		41E1B1D10FF5986900576B3B /* AbstractWorker.h in Headers */ = {isa = PBXBuildFile; fileRef = 41E1B1CB0FF5986900576B3B /* AbstractWorker.h */; };
 		41E9DCE7231974BF00F35949 /* BlobLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 41E9DCE4231973FE00F35949 /* BlobLoader.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -7472,7 +7471,6 @@
 		41D28D0C2139E01E00F4206F /* LibWebRTCStatsCollector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LibWebRTCStatsCollector.h; path = libwebrtc/LibWebRTCStatsCollector.h; sourceTree = "<group>"; };
 		41D41C652256859200697942 /* ServiceWorkerInternals.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ServiceWorkerInternals.mm; sourceTree = "<group>"; };
 		41D51BB21E4E2E8100131A5B /* LibWebRTCAudioFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LibWebRTCAudioFormat.h; path = libwebrtc/LibWebRTCAudioFormat.h; sourceTree = "<group>"; };
-		41DE7C78222DA13C00532B65 /* StorageQuotaUser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageQuotaUser.h; sourceTree = "<group>"; };
 		41DE7C7A222DA13D00532B65 /* StorageQuotaManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StorageQuotaManager.cpp; sourceTree = "<group>"; };
 		41DE7C7B222DA13E00532B65 /* StorageQuotaManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageQuotaManager.h; sourceTree = "<group>"; };
 		41DEFCB21E56C1B9000D9E5F /* JSDOMBindingInternals.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = JSDOMBindingInternals.js; sourceTree = "<group>"; };
@@ -17118,7 +17116,6 @@
 				1A37636A1A2E68BB009A7EE2 /* StorageNamespaceProvider.h */,
 				41DE7C7A222DA13D00532B65 /* StorageQuotaManager.cpp */,
 				41DE7C7B222DA13E00532B65 /* StorageQuotaManager.h */,
-				41DE7C78222DA13C00532B65 /* StorageQuotaUser.h */,
 				5166D3CC1E8ED41100AD62E3 /* StorageType.h */,
 			);
 			indentWidth = 4;
@@ -29535,6 +29532,7 @@
 				F47A09D120A93A9700240FAE /* DisabledAdaptations.h in Headers */,
 				7EDAAFC919A2CCDC0034DFD1 /* DiskCacheMonitorCocoa.h in Headers */,
 				1199FA5B208E3C7F002358CC /* DisplayBox.h in Headers */,
+				E451C6342394058F00993190 /* DisplayInlineContent.h in Headers */,
 				0FE5FBD31C3DD51E0007A2CA /* DisplayList.h in Headers */,
 				0FE5FBD51C3DD51E0007A2CA /* DisplayListItems.h in Headers */,
 				0FE5FBD71C3DD51E0007A2CA /* DisplayListRecorder.h in Headers */,
@@ -30048,7 +30046,6 @@
 				A871DB2B0A150BD600B12A68 /* HTMLTableCaptionElement.h in Headers */,
 				A871DB2A0A150BD600B12A68 /* HTMLTableCellElement.h in Headers */,
 				A871DB2F0A150BD600B12A68 /* HTMLTableColElement.h in Headers */,
-				E451C628239293EC00993190 /* LineLayoutTraversalDisplayRunPath.h in Headers */,
 				A871DB270A150BD600B12A68 /* HTMLTableElement.h in Headers */,
 				A871DB2C0A150BD600B12A68 /* HTMLTablePartElement.h in Headers */,
 				A871DB310A150BD600B12A68 /* HTMLTableRowElement.h in Headers */,
@@ -30160,7 +30157,6 @@
 				BC7F44A80B9E324E00A9D081 /* ImageObserver.h in Headers */,
 				2D5A5931152525D00036EE51 /* ImageOrientation.h in Headers */,
 				72283F0E230B268C00F5D828 /* ImagePaintingOptions.h in Headers */,
-				E451C6322394031A00993190 /* MarginTypes.h in Headers */,
 				B51A2F3F17D7D3AE0072517A /* ImageQualityController.h in Headers */,
 				49291E4B134172C800E753DE /* ImageRenderingMode.h in Headers */,
 				CD27AE5022A9868700947FF9 /* ImageRotationSessionVT.h in Headers */,
@@ -30553,7 +30549,6 @@
 				837056901F50915C00D93425 /* JSFileSystemEntryCallback.h in Headers */,
 				833B9E361F508D8500E0E428 /* JSFileSystemFileEntry.h in Headers */,
 				712BE4881FE8686A002031CC /* JSFillMode.h in Headers */,
-				E4343D252392779000EBBB66 /* LineLayoutTraversalComplexPath.h in Headers */,
 				B6D9D27B14EAC0860090D75E /* JSFocusEvent.h in Headers */,
 				C280833F1C6DC26F001451B6 /* JSFontFace.h in Headers */,
 				1C24EEA91C72A7B40080F8FC /* JSFontFaceSet.h in Headers */,
@@ -31177,6 +31172,7 @@
 				6F7CA3C6208C2957002F29AB /* LayoutState.h in Headers */,
 				11310CF220BA4A320065A8D0 /* LayoutTreeBuilder.h in Headers */,
 				141DC0481648348F00371E5A /* LayoutUnit.h in Headers */,
+				E451C6312394027900993190 /* LayoutUnits.h in Headers */,
 				CDE8B5ED1A69777300B4B66A /* LegacyCDMPrivateClearKey.h in Headers */,
 				CDF4B7121E0087AE00E235A2 /* LegacyCDMSession.h in Headers */,
 				CDE8B5F11A69778B00B4B66A /* LegacyCDMSessionClearKey.h in Headers */,
@@ -31208,6 +31204,9 @@
 				6F26EB48234004A5006906E2 /* LineLayoutContext.h in Headers */,
 				FFEFAB2A18380DA000514534 /* LineLayoutState.h in Headers */,
 				E484A33E23055325009ADE6A /* LineLayoutTraversal.h in Headers */,
+				E4343D252392779000EBBB66 /* LineLayoutTraversalComplexPath.h in Headers */,
+				E451C628239293EC00993190 /* LineLayoutTraversalDisplayRunPath.h in Headers */,
+				E4343D232392778400EBBB66 /* LineLayoutTraversalSimplePath.h in Headers */,
 				FFDBC047183D27B700407109 /* LineWidth.h in Headers */,
 				CBA9DC0B1DF44DF40005675C /* LinkHeader.h in Headers */,
 				5143B2631DDD15200014FAC6 /* LinkIcon.h in Headers */,
@@ -31241,6 +31240,7 @@
 				46EFAF121E5FB9F100E7F34B /* LowPowerModeNotifier.h in Headers */,
 				7AE6C93C1BE0C60100E19E03 /* MainThreadSharedTimer.h in Headers */,
 				1A8F6BC60DB55CDC001DB794 /* ManifestParser.h in Headers */,
+				E451C6322394031A00993190 /* MarginTypes.h in Headers */,
 				CE1866451F72E5B400A0CAB6 /* MarkedText.h in Headers */,
 				93309DF8099E64920056E581 /* markup.h in Headers */,
 				9728C3141268E4390041E89B /* MarkupAccumulator.h in Headers */,
@@ -31701,7 +31701,6 @@
 				57DCED74214305F00016B847 /* PublicKeyCredentialData.h in Headers */,
 				57303BEF200980C600355965 /* PublicKeyCredentialDescriptor.h in Headers */,
 				57303C0A20099BAD00355965 /* PublicKeyCredentialRequestOptions.h in Headers */,
-				E4343D232392778400EBBB66 /* LineLayoutTraversalSimplePath.h in Headers */,
 				57303BEB20097F4000355965 /* PublicKeyCredentialType.h in Headers */,
 				0081FF0016B0A2D3008AAA7A /* PublicSuffix.h in Headers */,
 				10FB084B14E15C7E00A3DB98 /* PublicURLManager.h in Headers */,
@@ -32245,7 +32244,6 @@
 				C50D0E830FF4272900AC2644 /* StorageNamespace.h in Headers */,
 				1A37636C1A2E68BB009A7EE2 /* StorageNamespaceProvider.h in Headers */,
 				41DE7C7C222DA14300532B65 /* StorageQuotaManager.h in Headers */,
-				41DE7C7D222DA14800532B65 /* StorageQuotaUser.h in Headers */,
 				5C9EF2F321F06190003BDC56 /* StorageSessionProvider.h in Headers */,
 				5166D3CD1E8ED48F00AD62E3 /* StorageType.h in Headers */,
 				4682D2001F79783000C863DB /* StoredCredentialsPolicy.h in Headers */,
@@ -32496,7 +32494,6 @@
 				B2227ADA0D00BF220071B782 /* SVGTransformable.h in Headers */,
 				B2227ADD0D00BF220071B782 /* SVGTransformDistance.h in Headers */,
 				B2227ADF0D00BF220071B782 /* SVGTransformList.h in Headers */,
-				E451C6312394027900993190 /* LayoutUnits.h in Headers */,
 				7CE58D581DD7D96D00128552 /* SVGTransformValue.h in Headers */,
 				B2227AE20D00BF220071B782 /* SVGTRefElement.h in Headers */,
 				B2227AE50D00BF220071B782 /* SVGTSpanElement.h in Headers */,
@@ -32826,7 +32823,6 @@
 				49C7B9E01042D32F0009D447 /* WebGLRenderingContext.h in Headers */,
 				D3F3D36A1A69B7B90059FC2B /* WebGLRenderingContextBase.h in Headers */,
 				6F995A221A7078B100A735F4 /* WebGLSampler.h in Headers */,
-				E451C6342394058F00993190 /* DisplayInlineContent.h in Headers */,
 				49C7B9E31042D32F0009D447 /* WebGLShader.h in Headers */,
 				A07D3358152B632D001B6393 /* WebGLShaderPrecisionFormat.h in Headers */,
 				01D3CF8714BD0A3000FE9970 /* WebGLSharedObject.h in Headers */,
diff --git a/Source/WebCore/storage/StorageQuotaManager.cpp b/Source/WebCore/storage/StorageQuotaManager.cpp
index 8525752..0c613d1 100644
--- a/Source/WebCore/storage/StorageQuotaManager.cpp
+++ b/Source/WebCore/storage/StorageQuotaManager.cpp
@@ -27,213 +27,120 @@
 #include "StorageQuotaManager.h"
 
 #include "Logging.h"
-#include "StorageQuotaUser.h"
+#include <wtf/Ref.h>
+#include <wtf/RefCounted.h>
+#include <wtf/threads/BinarySemaphore.h>
 
 namespace WebCore {
 
-StorageQuotaManager::~StorageQuotaManager()
+Ref<StorageQuotaManager> StorageQuotaManager::create(uint64_t quota, UsageGetter&& usageGetter, QuotaIncreaseRequester&& quotaIncreaseRequester)
 {
-    while (!m_pendingRequests.isEmpty())
-        m_pendingRequests.takeFirst().callback(Decision::Deny);
+    return adoptRef(*new StorageQuotaManager(quota, WTFMove(usageGetter), WTFMove(quotaIncreaseRequester)));
 }
 
-uint64_t StorageQuotaManager::spaceUsage() const
+StorageQuotaManager::StorageQuotaManager(uint64_t quota, UsageGetter&& usageGetter, QuotaIncreaseRequester&& quotaIncreaseRequester)
+    : m_quota(quota)
+    , m_usageGetter(WTFMove(usageGetter))
+    , m_quotaIncreaseRequester(WTFMove(quotaIncreaseRequester))
+    , m_workQueue(WorkQueue::create("StorageQuotaManager Background Queue", WorkQueue::Type::Serial))
+    , m_initialQuota(quota)
 {
-    uint64_t usage = 0;
-    for (auto& user : m_users)
-        usage += user->spaceUsed();
-    return usage;
 }
 
-void StorageQuotaManager::updateQuotaBasedOnSpaceUsage()
+void StorageQuotaManager::requestSpaceOnMainThread(uint64_t spaceRequested, RequestCallback&& callback)
 {
-    if (!m_quota)
-        return;
+    ASSERT(isMainThread());
 
-    auto defaultQuotaStep = m_quota / 10;
-    m_quota = std::max(m_quota, defaultQuotaStep * ((spaceUsage() / defaultQuotaStep) + 1));
-}
-
-void StorageQuotaManager::initializeUsersIfNeeded()
-{
-    if (m_pendingInitializationUsers.isEmpty())
-        return;
-
-    Vector<StorageQuotaUser*> usersToInitialize;
-    for (auto& keyValue : m_pendingInitializationUsers) {
-        if (keyValue.value == WhenInitializedCalled::No) {
-            keyValue.value = WhenInitializedCalled::Yes;
-            usersToInitialize.append(keyValue.key);
-        }
-    }
-    for (auto* user : usersToInitialize) {
-        if (m_pendingInitializationUsers.contains(user))
-            askUserToInitialize(*user);
-    }
-}
-
-void StorageQuotaManager::askUserToInitialize(StorageQuotaUser& user)
-{
-    user.whenInitialized([this, &user, weakThis = makeWeakPtr(this)]() {
-        if (!weakThis)
+    // Fast path.
+    if (m_quotaCountDownLock.tryLock()) {
+        if (tryGrantRequest(spaceRequested)) {
+            m_quotaCountDownLock.unlock();
+            callback(Decision::Grant);
             return;
-
-        if (m_pendingInitializationUsers.remove(&user))
-            m_users.add(&user);
-
-        if (!m_pendingInitializationUsers.isEmpty())
-            return;
-
-        // Make sure quota is set before handling first request.
-        if (m_state == State::Uninitialized) {
-            updateQuotaBasedOnSpaceUsage();
-            m_state = State::MakingDecisionForRequest;
         }
+        m_quotaCountDownLock.unlock();
+    }
 
-        processPendingRequests({ });
-    });
-}
-
-void StorageQuotaManager::addUser(StorageQuotaUser& user)
-{
-    ASSERT(!m_pendingInitializationUsers.contains(&user));
-    ASSERT(!m_users.contains(&user));
-    m_pendingInitializationUsers.add(&user, WhenInitializedCalled::No);
-
-    if (!m_pendingRequests.isEmpty())
-        askUserToInitialize(user);
-}
-
-bool StorageQuotaManager::shouldAskForMoreSpace(uint64_t spaceIncrease) const
-{
-    if (!spaceIncrease)
-        return false;
-
-    return spaceUsage() + spaceIncrease > m_quota;
-}
-
-void StorageQuotaManager::removeUser(StorageQuotaUser& user)
-{
-    ASSERT(m_users.contains(&user) || m_pendingInitializationUsers.contains(&user));
-    m_users.remove(&user);
-    if (m_pendingInitializationUsers.remove(&user) && m_pendingInitializationUsers.isEmpty()) {
-        // When being cleared, quota users may remove themselves and add themselves to trigger reinitialization.
-        // Let's wait for addUser to be called before processing pending requests.
-        callOnMainThread([this, weakThis = makeWeakPtr(this)] {
-            if (!weakThis)
-                return;
-
-            if (m_pendingInitializationUsers.isEmpty())
-                this->processPendingRequests({ });
+    m_workQueue->dispatch([this, protectedThis = makeRef(*this), spaceRequested, callback = WTFMove(callback)]() mutable {
+        auto decision = requestSpaceOnBackgroundThread(spaceRequested);
+        callOnMainThread([callback = WTFMove(callback), decision]() mutable {
+            callback(decision);
         });
-    }
-}
-
-void StorageQuotaManager::requestSpace(uint64_t spaceIncrease, RequestCallback&& callback)
-{
-    if (!m_pendingRequests.isEmpty()) {
-        m_pendingRequests.append({ spaceIncrease, WTFMove(callback) });
-        return;
-    }
-
-    if (!spaceIncrease) {
-        callback(Decision::Grant);
-        return;
-    }
-
-    initializeUsersIfNeeded();
-
-    if (!m_pendingInitializationUsers.isEmpty()) {
-        m_pendingRequests.append({ spaceIncrease, WTFMove(callback) });
-        return;
-    }
-
-    if (shouldAskForMoreSpace(spaceIncrease)) {
-        m_pendingRequests.append({ spaceIncrease, WTFMove(callback) });
-
-        // Try processing request again after making sure usage is accurate.
-        m_state = State::ComputingSpaceUsed;
-        for (auto& user : copyToVector(m_users))
-            user->computeSpaceUsed();
-
-        if (!m_pendingInitializationUsers.isEmpty())
-            return;
-
-        m_state = State::AskingForMoreSpace;
-        askForMoreSpace(spaceIncrease);
-        return;
-    }
-
-    m_state = State::MakingDecisionForRequest;
-    callback(Decision::Grant);
-}
-
-void StorageQuotaManager::askForMoreSpace(uint64_t spaceIncrease)
-{
-    ASSERT(shouldAskForMoreSpace(spaceIncrease));
-    ASSERT(m_state == State::AskingForMoreSpace);
-
-    RELEASE_LOG(Storage, "%p - StorageQuotaManager::askForMoreSpace %" PRIu64, this, spaceIncrease);
-    m_state = State::WaitingForSpaceIncreaseResponse;
-    m_spaceIncreaseRequester(m_quota, spaceUsage(), spaceIncrease, [this, weakThis = makeWeakPtr(*this)](Optional<uint64_t> newQuota) {
-        if (!weakThis)
-            return;
-
-        RELEASE_LOG(Storage, "%p - StorageQuotaManager::askForMoreSpace received response %" PRIu64, this, newQuota ? *newQuota : 0);
-
-        m_state = State::AskingForMoreSpace;
-        processPendingRequests(newQuota);
     });
 }
 
-void StorageQuotaManager::processPendingRequests(Optional<uint64_t> newQuota)
+StorageQuotaManager::Decision StorageQuotaManager::requestSpaceOnBackgroundThread(uint64_t spaceRequested)
 {
-    if (m_pendingRequests.isEmpty())
-        return;
+    ASSERT(!isMainThread());
 
-    if (newQuota)
-        m_quota = *newQuota;
+    LockHolder locker(m_quotaCountDownLock);
 
-    if (m_state == State::WaitingForSpaceIncreaseResponse)
-        return;
+    if (tryGrantRequest(spaceRequested))
+        return Decision::Grant;
 
-    if (!m_pendingInitializationUsers.isEmpty())
-        return;
+    m_usage = m_usageGetter();
+    updateQuotaBasedOnUsage();
+    m_quotaCountDown = m_usage < m_quota ? m_quota - m_usage : 0;
+    if (tryGrantRequest(spaceRequested))
+        return Decision::Grant;
 
-    if (m_state == State::AskingForMoreSpace) {
-        auto request = m_pendingRequests.takeFirst();
-        bool shouldAllowRequest = !shouldAskForMoreSpace(request.spaceIncrease);
+    // Block this thread until getting decsion for quota increase.
+    BinarySemaphore semaphore;
+    callOnMainThread([this, protectedThis = makeRef(*this), spaceRequested, &semaphore]() mutable {
+        RELEASE_LOG(Storage, "%p - StorageQuotaManager asks for quota increase %" PRIu64, this, spaceRequested);
+        m_quotaIncreaseRequester(m_quota, m_usage, spaceRequested, [this, protectedThis = WTFMove(protectedThis), &semaphore](Optional<uint64_t> newQuota) mutable {
+            RELEASE_LOG(Storage, "%p - StorageQuotaManager receives quota increase response %" PRIu64, this, newQuota ? *newQuota : 0);
+            ASSERT(isMainThread());
 
-        RELEASE_LOG(Storage, "%p - StorageQuotaManager::processPendingRequests first request decision is %d", this, shouldAllowRequest);
+            if (newQuota)
+                m_quota = *newQuota;
 
-        m_state = State::MakingDecisionForRequest;
-        request.callback(shouldAllowRequest ? Decision::Grant : Decision::Deny);
+            semaphore.signal();
+        });
+    });
+
+    semaphore.wait();
+
+    m_usage = m_usageGetter();
+    m_quotaCountDown = m_usage < m_quota ? m_quota - m_usage : 0;
+    return tryGrantRequest(spaceRequested) ? Decision::Grant : Decision::Deny;
+}
+
+bool StorageQuotaManager::tryGrantRequest(uint64_t spaceRequested)
+{
+    ASSERT(m_quotaCountDownLock.isLocked());
+    if (spaceRequested <= m_quotaCountDown) {
+        m_quotaCountDown -= spaceRequested;
+        return true;
     }
-
-    while (!m_pendingRequests.isEmpty()) {
-        auto& request = m_pendingRequests.first();
-
-        if (shouldAskForMoreSpace(request.spaceIncrease)) {
-            if (m_state == State::MakingDecisionForRequest) {
-                m_state = State::ComputingSpaceUsed;
-                for (auto& user : copyToVector(m_users))
-                    user->computeSpaceUsed();
-
-                if (!m_pendingInitializationUsers.isEmpty())
-                    return;
-            }
-
-            m_state = State::AskingForMoreSpace;
-            uint64_t spaceIncrease = 0;
-            for (auto& pendingRequest : m_pendingRequests)
-                spaceIncrease += pendingRequest.spaceIncrease;
-            askForMoreSpace(spaceIncrease);
-            return;
-        }
-
-        m_state = State::MakingDecisionForRequest;
-        m_pendingRequests.takeFirst().callback(Decision::Grant);
+    return false;
+}
+    
+void StorageQuotaManager::updateQuotaBasedOnUsage()
+{
+    // When StorageQuotaManager is used for the first time, we want to make sure its initial quota is bigger than current disk usage,
+    // based on the assumption that the quota was increased to at least the disk usage under user's permission before.
+    ASSERT(m_quotaCountDownLock.isLocked());
+    if (!m_quotaUpdatedBasedOnUsage) {
+        m_quotaUpdatedBasedOnUsage = true;
+        auto defaultQuotaStep = m_quota / 10;
+        m_quota = std::max(m_quota, defaultQuotaStep * ((m_usage / defaultQuotaStep) + 1));
     }
 }
 
+void StorageQuotaManager::resetQuotaUpdatedBasedOnUsageForTesting()
+{
+    LockHolder locker(m_quotaCountDownLock);
+    m_quota = m_initialQuota;
+    m_quotaCountDown = 0;
+    m_quotaUpdatedBasedOnUsage = false;
+}
+
+void StorageQuotaManager::resetQuotaForTesting()
+{
+    LockHolder locker(m_quotaCountDownLock);
+    m_quota = m_initialQuota;
+    m_quotaCountDown = 0;
+}
+
 } // namespace WebCore
diff --git a/Source/WebCore/storage/StorageQuotaManager.h b/Source/WebCore/storage/StorageQuotaManager.h
index 0956630..9bdfdd4 100644
--- a/Source/WebCore/storage/StorageQuotaManager.h
+++ b/Source/WebCore/storage/StorageQuotaManager.h
@@ -25,77 +25,54 @@
 
 #pragma once
 
-#include "ClientOrigin.h"
 #include <wtf/CompletionHandler.h>
 #include <wtf/Deque.h>
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
 #include <wtf/WeakPtr.h>
+#include <wtf/WorkQueue.h>
 
 namespace WebCore {
 
-class StorageQuotaUser;
-
-class StorageQuotaManager : public CanMakeWeakPtr<StorageQuotaManager> {
+class StorageQuotaManager : public ThreadSafeRefCounted<StorageQuotaManager>, public CanMakeWeakPtr<StorageQuotaManager> {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    using SpaceIncreaseRequester = WTF::Function<void(uint64_t quota, uint64_t currentSpace, uint64_t spaceIncrease, CompletionHandler<void(Optional<uint64_t>)>&&)>;
-    StorageQuotaManager(uint64_t quota, SpaceIncreaseRequester&& spaceIncreaseRequester)
-        : m_quota(quota)
-        , m_spaceIncreaseRequester(WTFMove(spaceIncreaseRequester))
-    {
-    }
-    WEBCORE_EXPORT ~StorageQuotaManager();
+    using UsageGetter = Function<uint64_t()>;
+    using QuotaIncreaseRequester = Function<void(uint64_t currentQuota, uint64_t currentUsage, uint64_t requestedIncrease, CompletionHandler<void(Optional<uint64_t>)>&&)>;
+    WEBCORE_EXPORT static Ref<StorageQuotaManager> create(uint64_t quota, UsageGetter&&, QuotaIncreaseRequester&&);
 
     static constexpr uint64_t defaultThirdPartyQuotaFromPerOriginQuota(uint64_t quota) { return quota / 10; }
-
     static constexpr uint64_t defaultQuota() { return 1000 * MB; }
     static constexpr uint64_t defaultThirdPartyQuota() { return defaultThirdPartyQuotaFromPerOriginQuota(defaultQuota()); }
 
-    WEBCORE_EXPORT void addUser(StorageQuotaUser&);
-    WEBCORE_EXPORT void removeUser(StorageQuotaUser&);
-
     enum class Decision { Deny, Grant };
     using RequestCallback = CompletionHandler<void(Decision)>;
-    WEBCORE_EXPORT void requestSpace(uint64_t, RequestCallback&&);
-    void resetQuota(uint64_t newQuota) { m_quota = newQuota; }
+    WEBCORE_EXPORT void requestSpaceOnMainThread(uint64_t, RequestCallback&&);
+    WEBCORE_EXPORT Decision requestSpaceOnBackgroundThread(uint64_t);
 
-    WEBCORE_EXPORT void updateQuotaBasedOnSpaceUsage();
-
-    enum class State {
-        Uninitialized,
-        ComputingSpaceUsed,
-        WaitingForSpaceIncreaseResponse,
-        AskingForMoreSpace,
-        MakingDecisionForRequest,
-    };
-    State state() const { return m_state; }
+    WEBCORE_EXPORT void resetQuotaUpdatedBasedOnUsageForTesting();
+    WEBCORE_EXPORT void resetQuotaForTesting();
 
 private:
-    uint64_t spaceUsage() const;
-    bool shouldAskForMoreSpace(uint64_t spaceIncrease) const;
-    void askForMoreSpace(uint64_t spaceIncrease);
+    StorageQuotaManager(uint64_t quota, UsageGetter&&, QuotaIncreaseRequester&&);
+    bool tryGrantRequest(uint64_t);
 
-    void initializeUsersIfNeeded();
-    void askUserToInitialize(StorageQuotaUser&);
+    void updateQuotaBasedOnUsage();
 
-    void processPendingRequests(Optional<uint64_t>);
-
+    Lock m_quotaCountDownLock;
+    uint64_t m_quotaCountDown { 0 };
     uint64_t m_quota { 0 };
+    uint64_t m_usage { 0 };
 
-    SpaceIncreaseRequester m_spaceIncreaseRequester;
+    UsageGetter m_usageGetter;
+    QuotaIncreaseRequester m_quotaIncreaseRequester;
 
-    enum class WhenInitializedCalled { No, Yes };
-    HashMap<StorageQuotaUser*, WhenInitializedCalled> m_pendingInitializationUsers;
-    HashSet<StorageQuotaUser*> m_users;
+    Ref<WorkQueue> m_workQueue;
 
-    struct PendingRequest {
-        uint64_t spaceIncrease;
-        RequestCallback callback;
-    };
-    Deque<PendingRequest> m_pendingRequests;
+    bool m_quotaUpdatedBasedOnUsage { false };
 
-    State m_state { State::Uninitialized };
+    // Test only.
+    uint64_t m_initialQuota { 0 };
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/storage/StorageQuotaUser.h b/Source/WebCore/storage/StorageQuotaUser.h
deleted file mode 100644
index b710cee..0000000
--- a/Source/WebCore/storage/StorageQuotaUser.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2019 Apple Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#include <wtf/CompletionHandler.h>
-
-namespace WebCore {
-
-class StorageQuotaUser {
-public:
-    virtual ~StorageQuotaUser() = default;
-
-    virtual uint64_t spaceUsed() const = 0;
-    virtual void computeSpaceUsed() { };
-    virtual void whenInitialized(CompletionHandler<void()>&& callback) { callback(); }
-};
-
-} // namespace WebCore
diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog
index 9db954b..3902c7a 100644
--- a/Source/WebKit/ChangeLog
+++ b/Source/WebKit/ChangeLog
@@ -1,3 +1,88 @@
+2019-12-02  Sihui Liu  <sihui_liu@apple.com>
+
+        Cross-thread version StorageQuotaManager
+        https://bugs.webkit.org/show_bug.cgi?id=203971
+        <rdar://problem/57290349>
+
+        Reviewed by Chris Dumez.
+
+        * NetworkProcess/NetworkProcess.cpp: Introduce class SessionStorageQuotaManager to manage all 
+        StorageQuotaManagers of the same session. 
+        (WebKit::NetworkProcess::initializeNetworkProcess):
+        (WebKit::NetworkProcess::addWebsiteDataStore):
+        (WebKit::NetworkProcess::addSessionStorageQuotaManager):
+        (WebKit::NetworkProcess::removeSessionStorageQuotaManager):
+        (WebKit::NetworkProcess::destroySession):
+        (WebKit::NetworkProcess::deleteWebsiteData):
+        (WebKit::NetworkProcess::deleteWebsiteDataForOrigins):
+        (WebKit::NetworkProcess::createIDBServer):
+        (WebKit::NetworkProcess::addIndexedDatabaseSession):
+        (WebKit::NetworkProcess::setSessionStorageQuotaManagerIDBRootPath):
+        (WebKit::NetworkProcess::updateQuotaBasedOnSpaceUsageForTesting):
+        (WebKit::NetworkProcess::resetQuota):
+        (WebKit::NetworkProcess::storageQuotaManager):
+        (WebKit::NetworkProcess::initializeStorageQuota): Deleted.
+        (WebKit::NetworkProcess::clearStorageQuota): Deleted.
+        (): Deleted.
+        (WebKit::NetworkProcess::initializeQuotaUsers): Deleted.
+        * NetworkProcess/NetworkProcess.h:
+        (WebKit::NetworkProcess::SessionStorageQuotaManager::SessionStorageQuotaManager):
+        (WebKit::NetworkProcess::SessionStorageQuotaManager::defaultQuota const):
+        (WebKit::NetworkProcess::SessionStorageQuotaManager::ensureOriginStorageQuotaManager):
+        (WebKit::NetworkProcess::SessionStorageQuotaManager::existingStorageQuotaManagers):
+        (WebKit::NetworkProcess::SessionStorageQuotaManager::cacheRootPath const):
+        (WebKit::NetworkProcess::SessionStorageQuotaManager::setIDBRootPath):
+        (WebKit::NetworkProcess::SessionStorageQuotaManager::idbRootPath const):
+        (WebKit::NetworkProcess::StorageQuotaManagers::defaultQuota const): Deleted.
+        (WebKit::NetworkProcess::StorageQuotaManagers::setDefaultQuotas): Deleted.
+        (WebKit::NetworkProcess::StorageQuotaManagers::managersPerOrigin): Deleted.
+        * NetworkProcess/NetworkProcess.messages.in:
+        * NetworkProcess/cache/CacheStorageEngine.cpp:
+        (WebKit::CacheStorage::getDirectorySize):
+        (WebKit::CacheStorage::Engine::diskUsage): static function to get the disk usage of CacheStorage given 
+        CacheStorage root directory.
+        (WebKit::CacheStorage::Engine::requestSpace):
+        (WebKit::CacheStorage::Engine::readCachesFromDisk):
+        (WebKit::CacheStorage::Engine::writeSizeFile):
+        (WebKit::CacheStorage::Engine::readSizeFile):
+        (WebKit::CacheStorage::Engine::initializeQuotaUser): Deleted.
+        * NetworkProcess/cache/CacheStorageEngine.h:
+        * NetworkProcess/cache/CacheStorageEngineCache.cpp:
+        (WebKit::CacheStorage::Cache::put):
+        (WebKit::CacheStorage::Cache::remove):
+        * NetworkProcess/cache/CacheStorageEngineCaches.cpp:
+        (WebKit::CacheStorage::Caches::create):
+        (WebKit::CacheStorage::Caches::Caches):
+        (WebKit::CacheStorage::Caches::~Caches):
+        (WebKit::CacheStorage::Caches::updateSizeFile):
+        (WebKit::CacheStorage::Caches::initializeSize):
+        (WebKit::CacheStorage::Caches::clear):
+        (WebKit::CacheStorage::Caches::requestSpace):
+        (WebKit::CacheStorage::Caches::writeRecord):
+        (WebKit::CacheStorage::Caches::removeRecord):
+        (WebKit::CacheStorage::Caches::whenInitialized): Deleted.
+        (WebKit::CacheStorage::Caches::resetSpaceUsed): Deleted.
+        * NetworkProcess/cache/CacheStorageEngineCaches.h:
+        * Shared/WebsiteDataStoreParameters.cpp:
+        (WebKit::WebsiteDataStoreParameters::encode const):
+        (WebKit::WebsiteDataStoreParameters::decode):
+        * Shared/WebsiteDataStoreParameters.h: Add a cacheStorageDirectory parameter so we know the direcotry of 
+        CacheStorage when we start using WebsiteDataStore.
+        * UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
+        (WKWebsiteDataStoreResetQuota):
+        * UIProcess/API/C/WKWebsiteDataStoreRef.h: Add a C API for reseting quota in TestRunner.
+        * UIProcess/Network/NetworkProcessProxy.cpp:
+        (WebKit::NetworkProcessProxy::resetQuota):
+        * UIProcess/Network/NetworkProcessProxy.h:
+        * UIProcess/WebProcessPool.cpp:
+        (WebKit::WebProcessPool::ensureNetworkProcess):
+        * UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm:
+        (WebKit::WebsiteDataStore::parameters):
+        * UIProcess/WebsiteData/WebsiteDataStore.cpp:
+        (WebKit::WebsiteDataStore::parameters):
+        (WebKit::WebsiteDataStore::resetQuota):
+        * UIProcess/WebsiteData/WebsiteDataStore.h:
+
 2019-12-02  Per Arne Vollan  <pvollan@apple.com>
 
         [iOS] Create sandbox extension for "com.apple.tccd"
diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.cpp b/Source/WebKit/NetworkProcess/NetworkProcess.cpp
index 13fce2e..4e5b3b0 100644
--- a/Source/WebKit/NetworkProcess/NetworkProcess.cpp
+++ b/Source/WebKit/NetworkProcess/NetworkProcess.cpp
@@ -65,6 +65,7 @@
 #include "WebsiteDataStore.h"
 #include "WebsiteDataStoreParameters.h"
 #include "WebsiteDataType.h"
+#include <WebCore/ClientOrigin.h>
 #include <WebCore/CookieJar.h>
 #include <WebCore/DNS.h>
 #include <WebCore/DeprecatedGlobalSettings.h>
@@ -316,6 +317,9 @@
     auto sessionID = parameters.defaultDataStoreParameters.networkSessionParameters.sessionID;
     setSession(sessionID, NetworkSession::create(*this, WTFMove(parameters.defaultDataStoreParameters.networkSessionParameters)));
 
+    SandboxExtension::consumePermanently(parameters.defaultDataStoreParameters.cacheStorageDirectoryExtensionHandle);
+    addSessionStorageQuotaManager(sessionID, parameters.defaultDataStoreParameters.perOriginStorageQuota, parameters.defaultDataStoreParameters.perThirdPartyOriginStorageQuota, parameters.defaultDataStoreParameters.cacheStorageDirectory, parameters.defaultDataStoreParameters.cacheStorageDirectoryExtensionHandle);
+
 #if ENABLE(INDEXED_DATABASE)
     addIndexedDatabaseSession(sessionID, parameters.defaultDataStoreParameters.indexedDatabaseDirectory, parameters.defaultDataStoreParameters.indexedDatabaseDirectoryExtensionHandle);
 #endif
@@ -326,7 +330,6 @@
         addServiceWorkerSession(PAL::SessionID::defaultSessionID(), serviceWorkerProcessTerminationDelayEnabled, WTFMove(parameters.serviceWorkerRegistrationDirectory), parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
     }
 #endif
-    initializeStorageQuota(parameters.defaultDataStoreParameters);
 
     m_storageManagerSet->add(sessionID, parameters.defaultDataStoreParameters.localStorageDirectory, parameters.defaultDataStoreParameters.localStorageDirectoryExtensionHandle);
 
@@ -434,28 +437,39 @@
 
 void NetworkProcess::addWebsiteDataStore(WebsiteDataStoreParameters&& parameters)
 {
+    auto sessionID = parameters.networkSessionParameters.sessionID;
+
+    addSessionStorageQuotaManager(sessionID, parameters.perOriginStorageQuota, parameters.perThirdPartyOriginStorageQuota, parameters.cacheStorageDirectory, parameters.cacheStorageDirectoryExtensionHandle);
+
 #if ENABLE(INDEXED_DATABASE)
-    addIndexedDatabaseSession(parameters.networkSessionParameters.sessionID, parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);
+    addIndexedDatabaseSession(sessionID, parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);
 #endif
 
 #if ENABLE(SERVICE_WORKER)
     if (parentProcessHasServiceWorkerEntitlement())
-        addServiceWorkerSession(parameters.networkSessionParameters.sessionID, parameters.serviceWorkerProcessTerminationDelayEnabled, WTFMove(parameters.serviceWorkerRegistrationDirectory), parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
+        addServiceWorkerSession(sessionID, parameters.serviceWorkerProcessTerminationDelayEnabled, WTFMove(parameters.serviceWorkerRegistrationDirectory), parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
 #endif
 
-    m_storageManagerSet->add(parameters.networkSessionParameters.sessionID, parameters.localStorageDirectory, parameters.localStorageDirectoryExtensionHandle);
-
-    initializeStorageQuota(parameters);
+    m_storageManagerSet->add(sessionID, parameters.localStorageDirectory, parameters.localStorageDirectoryExtensionHandle);
 
     RemoteNetworkingContext::ensureWebsiteDataStoreSession(*this, WTFMove(parameters));
 }
 
-void NetworkProcess::initializeStorageQuota(const WebsiteDataStoreParameters& parameters)
+void NetworkProcess::addSessionStorageQuotaManager(PAL::SessionID sessionID, uint64_t defaultQuota, uint64_t defaultThirdPartyQuota, const String& cacheRootPath, SandboxExtension::Handle& cacheRootPathHandle)
 {
-    auto& managers =  m_storageQuotaManagers.ensure(parameters.networkSessionParameters.sessionID, [] {
-        return StorageQuotaManagers { };
-    }).iterator->value;
-    managers.setDefaultQuotas(parameters.perOriginStorageQuota, parameters.perThirdPartyOriginStorageQuota);
+    LockHolder locker(m_sessionStorageQuotaManagersLock);
+    auto [iter, isNewEntry] = m_sessionStorageQuotaManagers.ensure(sessionID, [defaultQuota, defaultThirdPartyQuota, &cacheRootPath] {
+        return makeUnique<SessionStorageQuotaManager>(cacheRootPath, defaultQuota, defaultThirdPartyQuota);
+    });
+    if (isNewEntry)
+        SandboxExtension::consumePermanently(cacheRootPathHandle);
+}
+
+void NetworkProcess::removeSessionStorageQuotaManager(PAL::SessionID sessionID)
+{
+    LockHolder locker(m_sessionStorageQuotaManagersLock);
+    ASSERT(m_sessionStorageQuotaManagers.contains(sessionID));
+    m_sessionStorageQuotaManagers.remove(sessionID);
 }
 
 void NetworkProcess::forEachNetworkSession(const Function<void(NetworkSession&)>& functor)
@@ -576,8 +590,6 @@
 #endif
 
     m_storageManagerSet->remove(sessionID);
-
-    m_storageQuotaManagers.remove(sessionID);
 }
 
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
@@ -1468,9 +1480,6 @@
     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
         clearDiskCache(modifiedSince, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
 
-    if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases) || websiteDataTypes.contains(WebsiteDataType::DOMCache))
-        clearStorageQuota(sessionID);
-
     if (websiteDataTypes.contains(WebsiteDataType::AdClickAttributions)) {
         if (auto* networkSession = this->networkSession(sessionID))
             networkSession->clearAdClickAttribution();
@@ -1563,19 +1572,6 @@
         }
         WebCore::CredentialStorage::removeSessionCredentialsWithOrigins(originDatas);
     }
-
-    // FIXME: Implement storage quota clearing for these origins.
-}
-
-void NetworkProcess::clearStorageQuota(PAL::SessionID sessionID)
-{
-    auto iterator = m_storageQuotaManagers.find(sessionID);
-    if (iterator == m_storageQuotaManagers.end())
-        return;
-
-    auto& managers = iterator->value;
-    for (auto& manager : managers.managersPerOrigin())
-        manager.value->resetQuota(managers.defaultQuota(manager.key));
 }
 
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
@@ -2217,10 +2213,9 @@
         path = m_idbDatabasePaths.get(sessionID);
     }
 
-    return IDBServer::IDBServer::create(sessionID, path, [this, weakThis = makeWeakPtr(this)](PAL::SessionID sessionID, const auto& origin) -> StorageQuotaManager* {
-        if (!weakThis)
-            return nullptr;
-        return &this->storageQuotaManager(sessionID, origin);
+    return IDBServer::IDBServer::create(sessionID, path, [this, weakThis = makeWeakPtr(this), sessionID](const auto& origin, uint64_t spaceRequested) {
+        RefPtr<StorageQuotaManager> storageQuotaManager = weakThis ? this->storageQuotaManager(sessionID, origin) : nullptr;
+        return storageQuotaManager ? storageQuotaManager->requestSpaceOnBackgroundThread(spaceRequested) : StorageQuotaManager::Decision::Deny;
     });
 }
 
@@ -2307,8 +2302,18 @@
         SandboxExtension::consumePermanently(handle);
         if (!indexedDatabaseDirectory.isEmpty())
             postStorageTask(createCrossThreadTask(*this, &NetworkProcess::ensurePathExists, indexedDatabaseDirectory));
+        setSessionStorageQuotaManagerIDBRootPath(sessionID, indexedDatabaseDirectory);
     }
 }
+
+void NetworkProcess::setSessionStorageQuotaManagerIDBRootPath(PAL::SessionID sessionID, const String& idbRootPath)
+{
+    LockHolder locker(m_sessionStorageQuotaManagersLock);
+    auto* sessionStorageQuotaManager = m_sessionStorageQuotaManagers.get(sessionID);
+    ASSERT(sessionStorageQuotaManager);
+    sessionStorageQuotaManager->setIDBRootPath(idbRootPath);
+}
+
 #endif // ENABLE(INDEXED_DATABASE)
 
 void NetworkProcess::syncLocalStorage(CompletionHandler<void()>&& completionHandler)
@@ -2325,9 +2330,18 @@
 
 void NetworkProcess::updateQuotaBasedOnSpaceUsageForTesting(PAL::SessionID sessionID, const ClientOrigin& origin)
 {
-    auto& manager = storageQuotaManager(sessionID, origin);
-    manager.resetQuota(m_storageQuotaManagers.find(sessionID)->value.defaultQuota(origin));
-    manager.updateQuotaBasedOnSpaceUsage();
+    auto storageQuotaManager = this->storageQuotaManager(sessionID, origin);
+    storageQuotaManager->resetQuotaUpdatedBasedOnUsageForTesting();
+}
+
+void NetworkProcess::resetQuota(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
+{
+    LockHolder locker(m_sessionStorageQuotaManagersLock);
+    if (auto* sessionStorageQuotaManager = m_sessionStorageQuotaManagers.get(sessionID)) {
+        for (auto storageQuotaManager : sessionStorageQuotaManager->existingStorageQuotaManagers())
+            storageQuotaManager->resetQuotaForTesting();
+    }
+    completionHandler();
 }
 
 #if ENABLE(SANDBOX_EXTENSIONS)
@@ -2404,62 +2418,35 @@
     parentProcessConnection()->sendWithAsyncReply(Messages::NetworkProcessProxy::RequestStorageSpace { sessionID, origin, quota, currentSize, spaceRequired }, WTFMove(callback), 0);
 }
 
-class QuotaUserInitializer final : public WebCore::StorageQuotaUser {
-    WTF_MAKE_FAST_ALLOCATED;
-public:
-    explicit QuotaUserInitializer(StorageQuotaManager& manager)
-        : m_manager(makeWeakPtr(manager))
-    {
-        manager.addUser(*this);
-    }
-
-    ~QuotaUserInitializer()
-    {
-        if (m_manager)
-            m_manager->removeUser(*this);
-        if (m_callback)
-            m_callback();
-    }
-
-private:
-    // StorageQuotaUser API.
-    uint64_t spaceUsed() const final
-    {
-        ASSERT_NOT_REACHED();
-        return 0;
-    }
-
-    void whenInitialized(CompletionHandler<void()>&& callback) final
-    {
-        m_callback = WTFMove(callback);
-    }
-
-    WeakPtr<StorageQuotaManager> m_manager;
-    CompletionHandler<void()> m_callback;
-};
-
-void NetworkProcess::initializeQuotaUsers(StorageQuotaManager& manager, PAL::SessionID sessionID, const ClientOrigin& origin)
+RefPtr<StorageQuotaManager> NetworkProcess::storageQuotaManager(PAL::SessionID sessionID, const ClientOrigin& origin)
 {
-    RunLoop::main().dispatch([this, weakThis = makeWeakPtr(this), sessionID, origin, user = makeUnique<QuotaUserInitializer>(manager)]() mutable {
+    LockHolder locker(m_sessionStorageQuotaManagersLock);
+    auto* sessionStorageQuotaManager = m_sessionStorageQuotaManagers.get(sessionID);
+    if (!sessionStorageQuotaManager)
+        return nullptr;
+
+    String idbRootPath;
+#if ENABLE(INDEXED_DATABASE)
+    idbRootPath = sessionStorageQuotaManager->idbRootPath();
+#endif
+    StorageQuotaManager::UsageGetter usageGetter = [cacheRootPath = sessionStorageQuotaManager->cacheRootPath().isolatedCopy(), idbRootPath = idbRootPath.isolatedCopy(), origin = origin.isolatedCopy()]() {
+        ASSERT(!isMainThread());    
+
+        uint64_t usage = CacheStorage::Engine::diskUsage(cacheRootPath, origin);
+#if ENABLE(INDEXED_DATABASE)
+        usage += IDBServer::IDBServer::diskUsage(idbRootPath, origin);
+#endif
+
+        return usage;
+    };
+    StorageQuotaManager::QuotaIncreaseRequester quotaIncreaseRequester = [this, weakThis = makeWeakPtr(*this), sessionID, origin] (uint64_t currentQuota, uint64_t currentSpace, uint64_t requestedIncrease, auto&& callback) {
+        ASSERT(isMainThread());
         if (!weakThis)
-            return;
-        this->idbServer(sessionID).initializeQuotaUser(origin);
-        CacheStorage::Engine::initializeQuotaUser(*this, sessionID, origin, [user = WTFMove(user)] { });
-    });
-}
+            callback({ });
+        requestStorageSpace(sessionID, origin, currentQuota, currentSpace, requestedIncrease, WTFMove(callback));
+    };
 
-StorageQuotaManager& NetworkProcess::storageQuotaManager(PAL::SessionID sessionID, const ClientOrigin& origin)
-{
-    auto& storageQuotaManagers = m_storageQuotaManagers.ensure(sessionID, [] {
-        return StorageQuotaManagers { };
-    }).iterator->value;
-    return *storageQuotaManagers.managersPerOrigin().ensure(origin, [this, &storageQuotaManagers, sessionID, &origin] {
-        auto manager = makeUnique<StorageQuotaManager>(storageQuotaManagers.defaultQuota(origin), [this, sessionID, origin](uint64_t quota, uint64_t currentSpace, uint64_t spaceIncrease, auto callback) {
-            this->requestStorageSpace(sessionID, origin, quota, currentSpace, spaceIncrease, WTFMove(callback));
-        });
-        initializeQuotaUsers(*manager, sessionID, origin);
-        return manager;
-    }).iterator->value;
+    return sessionStorageQuotaManager->ensureOriginStorageQuotaManager(origin, sessionStorageQuotaManager->defaultQuota(origin), WTFMove(usageGetter), WTFMove(quotaIncreaseRequester)).ptr();
 }
 
 #if !PLATFORM(COCOA)
diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.h b/Source/WebKit/NetworkProcess/NetworkProcess.h
index f0806b2..d7e4a95 100644
--- a/Source/WebKit/NetworkProcess/NetworkProcess.h
+++ b/Source/WebKit/NetworkProcess/NetworkProcess.h
@@ -284,6 +284,7 @@
     void clearLegacyPrivateBrowsingLocalStorage();
 
     void updateQuotaBasedOnSpaceUsageForTesting(PAL::SessionID, const WebCore::ClientOrigin&);
+    void resetQuota(PAL::SessionID, CompletionHandler<void()>&&);
 
 #if ENABLE(SANDBOX_EXTENSIONS)
     void getSandboxExtensionsForBlobFiles(const Vector<String>& filenames, CompletionHandler<void(SandboxExtension::HandleArray&&)>&&);
@@ -327,7 +328,7 @@
     void setAdClickAttributionConversionURLForTesting(PAL::SessionID, URL&&, CompletionHandler<void()>&&);
     void markAdClickAttributionsAsExpiredForTesting(PAL::SessionID, CompletionHandler<void()>&&);
 
-    WebCore::StorageQuotaManager& storageQuotaManager(PAL::SessionID, const WebCore::ClientOrigin&);
+    RefPtr<WebCore::StorageQuotaManager> storageQuotaManager(PAL::SessionID, const WebCore::ClientOrigin&);
 
     void addKeptAliveLoad(Ref<NetworkResourceLoader>&&);
     void removeKeptAliveLoad(NetworkResourceLoader&);
@@ -442,6 +443,7 @@
     void collectIndexedDatabaseOriginsForVersion(const String&, HashSet<WebCore::SecurityOriginData>&);
     HashSet<WebCore::SecurityOriginData> indexedDatabaseOrigins(const String& path);
     Ref<WebCore::IDBServer::IDBServer> createIDBServer(PAL::SessionID);
+    void setSessionStorageQuotaManagerIDBRootPath(PAL::SessionID, const String& idbRootPath);
 #endif
 
 #if ENABLE(SERVICE_WORKER)
@@ -461,8 +463,44 @@
     void performNextStorageTask();
     void ensurePathExists(const String& path);
 
-    void clearStorageQuota(PAL::SessionID);
-    void initializeStorageQuota(const WebsiteDataStoreParameters&);
+    class SessionStorageQuotaManager {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        SessionStorageQuotaManager(const String& cacheRootPath, uint64_t defaultQuota, uint64_t defaultThirdPartyQuota)
+            : m_cacheRootPath(cacheRootPath)
+            , m_defaultQuota(defaultQuota)
+            , m_defaultThirdPartyQuota(defaultThirdPartyQuota)
+        {
+        }
+        uint64_t defaultQuota(const WebCore::ClientOrigin& origin) const { return origin.topOrigin == origin.clientOrigin ? m_defaultQuota : m_defaultThirdPartyQuota; }
+
+        Ref<WebCore::StorageQuotaManager> ensureOriginStorageQuotaManager(WebCore::ClientOrigin origin, uint64_t quota, WebCore::StorageQuotaManager::UsageGetter&& usageGetter, WebCore::StorageQuotaManager::QuotaIncreaseRequester&& quotaIncreaseRequester)
+        {
+            auto [iter, isNewEntry] = m_storageQuotaManagers.ensure(origin, [quota, usageGetter = WTFMove(usageGetter), quotaIncreaseRequester = WTFMove(quotaIncreaseRequester)]() mutable {
+                return WebCore::StorageQuotaManager::create(quota, WTFMove(usageGetter), WTFMove(quotaIncreaseRequester));
+            });
+            return makeRef(*iter->value);
+        }
+
+        auto existingStorageQuotaManagers() { return m_storageQuotaManagers.values(); }
+
+        const String& cacheRootPath() const { return m_cacheRootPath; }
+#if ENABLE(INDEXED_DATABASE)
+        void setIDBRootPath(const String& idbRootPath) { m_idbRootPath = idbRootPath; }
+        const String& idbRootPath() const { return m_idbRootPath; }
+#endif
+
+    private:
+        String m_cacheRootPath;
+#if ENABLE(INDEXED_DATABASE)
+        String m_idbRootPath;
+#endif
+        uint64_t m_defaultQuota { WebCore::StorageQuotaManager::defaultQuota() };
+        uint64_t m_defaultThirdPartyQuota { WebCore::StorageQuotaManager::defaultThirdPartyQuota() };
+        HashMap<WebCore::ClientOrigin, RefPtr<WebCore::StorageQuotaManager>> m_storageQuotaManagers;
+    };
+    void addSessionStorageQuotaManager(PAL::SessionID, uint64_t defaultQuota, uint64_t defaultThirdPartyQuota, const String& cacheRootPath, SandboxExtension::Handle&);
+    void removeSessionStorageQuotaManager(PAL::SessionID);
 
     // Connections to WebProcesses.
     HashMap<WebCore::ProcessIdentifier, Ref<NetworkConnectionToWebProcess>> m_webProcessConnections;
@@ -533,23 +571,8 @@
     bool m_isITPDatabaseEnabled { false };
 #endif
     
-    class StorageQuotaManagers {
-    public:
-        uint64_t defaultQuota(const WebCore::ClientOrigin& origin) const { return origin.topOrigin == origin.clientOrigin ? m_defaultQuota : m_defaultThirdPartyQuota; }
-        void setDefaultQuotas(uint64_t defaultQuota, uint64_t defaultThirdPartyQuota)
-        {
-            m_defaultQuota = defaultQuota;
-            m_defaultThirdPartyQuota = defaultThirdPartyQuota;
-        }
-
-        HashMap<WebCore::ClientOrigin, std::unique_ptr<WebCore::StorageQuotaManager>>& managersPerOrigin() { return m_managersPerOrigin; }
-
-    private:
-        uint64_t m_defaultQuota { WebCore::StorageQuotaManager::defaultQuota() };
-        uint64_t m_defaultThirdPartyQuota { WebCore::StorageQuotaManager::defaultThirdPartyQuota() };
-        HashMap<WebCore::ClientOrigin, std::unique_ptr<WebCore::StorageQuotaManager>> m_managersPerOrigin;
-    };
-    HashMap<PAL::SessionID, StorageQuotaManagers> m_storageQuotaManagers;
+    Lock m_sessionStorageQuotaManagersLock;
+    HashMap<PAL::SessionID, std::unique_ptr<SessionStorageQuotaManager>> m_sessionStorageQuotaManagers;
 
     OptionSet<NetworkCache::CacheOption> m_cacheOptions;
     WebCore::MessagePortChannelRegistry m_messagePortChannelRegistry;
diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in
index e1ee174..9dbac68 100644
--- a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in
+++ b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in
@@ -164,4 +164,6 @@
 
     SetServiceWorkerFetchTimeoutForTesting(Seconds seconds) -> () Synchronous
     ResetServiceWorkerFetchTimeoutForTesting() -> () Synchronous
+
+    ResetQuota(PAL::SessionID sessionID) -> () Async
 }
diff --git a/Source/WebKit/NetworkProcess/cache/CacheStorageEngine.cpp b/Source/WebKit/NetworkProcess/cache/CacheStorageEngine.cpp
index efe7e15..07772a6 100644
--- a/Source/WebKit/NetworkProcess/cache/CacheStorageEngine.cpp
+++ b/Source/WebKit/NetworkProcess/cache/CacheStorageEngine.cpp
@@ -196,13 +196,68 @@
     });
 }
 
-void Engine::initializeQuotaUser(NetworkProcess& networkProcess, PAL::SessionID sessionID, const WebCore::ClientOrigin& clientOrigin, CompletionHandler<void()>&& completionHandler)
+static uint64_t getDirectorySize(const String& directoryPath)
 {
-    from(networkProcess, sessionID, [clientOrigin, completionHandler = WTFMove(completionHandler)](auto& engine) mutable {
-        engine.readCachesFromDisk(clientOrigin, [completionHandler = WTFMove(completionHandler)](auto&& cachesOrError) mutable {
-            completionHandler();
-        });
-    });
+    ASSERT(!isMainThread());
+
+    uint64_t directorySize = 0;
+    Deque<String> paths;
+    paths.append(directoryPath);
+    while (!paths.isEmpty()) {
+        auto path = paths.takeFirst();
+        if (FileSystem::fileIsDirectory(path, FileSystem::ShouldFollowSymbolicLinks::No)) {
+            auto newPaths = FileSystem::listDirectory(path, "*"_s);
+            for (auto& newPath : newPaths) {
+                // Files in /Blobs directory are hard link.
+                auto fileName = FileSystem::lastComponentOfPathIgnoringTrailingSlash(newPath);
+                if (fileName == "Blobs")
+                    continue;
+                paths.append(newPath);
+            }
+            continue;
+        }
+
+        long long fileSize = 0;
+        FileSystem::getFileSize(path, fileSize);
+        directorySize += fileSize;
+    }
+    return directorySize;
+}
+
+uint64_t Engine::diskUsage(const String& rootPath, const WebCore::ClientOrigin& origin)
+{
+    ASSERT(!isMainThread());
+
+    if (rootPath.isEmpty())
+        return 0;
+
+    String saltPath = FileSystem::pathByAppendingComponent(rootPath, "salt"_s);
+    auto salt = readOrMakeSalt(saltPath);
+    if (!salt)
+        return 0;
+
+    Key key(origin.topOrigin.toString(), origin.clientOrigin.toString(), { }, { }, *salt);
+    String directoryPath = FileSystem::pathByAppendingComponent(rootPath, key.hashAsString());
+
+    String sizeFilePath = Caches::cachesSizeFilename(directoryPath);
+    if (auto recordedSize = readSizeFile(sizeFilePath))
+        return *recordedSize;
+
+    return getDirectorySize(directoryPath);
+}
+
+void Engine::requestSpace(const ClientOrigin& origin, uint64_t spaceRequested, CompletionHandler<void(WebCore::StorageQuotaManager::Decision)>&& callback)
+{
+    ASSERT(isMainThread());
+
+    if (!m_networkProcess)
+        callback(WebCore::StorageQuotaManager::Decision::Deny);
+
+    RefPtr<WebCore::StorageQuotaManager> storageQuotaManager = m_networkProcess->storageQuotaManager(m_sessionID, origin);
+    if (!storageQuotaManager)
+        callback(WebCore::StorageQuotaManager::Decision::Deny);
+
+    storageQuotaManager->requestSpaceOnMainThread(spaceRequested, WTFMove(callback));
 }
 
 Engine::Engine(PAL::SessionID sessionID, NetworkProcess& process, String&& rootPath)
@@ -341,7 +396,7 @@
 
         auto& caches = m_caches.ensure(origin, [&origin, this] {
             auto path = cachesRootPath(origin);
-            return Caches::create(*this, WebCore::ClientOrigin { origin }, WTFMove(path), m_networkProcess->storageQuotaManager(m_sessionID, origin));
+            return Caches::create(*this, WebCore::ClientOrigin { origin }, WTFMove(path));
         }).iterator->value;
 
         if (caches->isInitialized()) {
@@ -473,12 +528,13 @@
     });
 }
 
-void Engine::writeSizeFile(const String& path, uint64_t size)
+void Engine::writeSizeFile(const String& path, uint64_t size, CompletionHandler<void()>&& completionHandler)
 {
+    CompletionHandlerCallingScope completionHandlerCaller(WTFMove(completionHandler));
     if (!shouldPersist())
         return;
 
-    m_ioQueue->dispatch([path = path.isolatedCopy(), size]() {
+    m_ioQueue->dispatch([path = path.isolatedCopy(), size, completionHandlerCaller = WTFMove(completionHandlerCaller)]() mutable {
         LockHolder locker(globalSizeFileLock);
         auto fileHandle = FileSystem::openFile(path, FileSystem::FileOpenMode::Write);
         auto closeFileHandler = makeScopeExit([&] {
@@ -489,6 +545,8 @@
 
         FileSystem::truncateFile(fileHandle, 0);
         FileSystem::writeToFile(fileHandle, String::number(size).utf8().data(), String::number(size).utf8().length());
+
+        RunLoop::main().dispatch([completionHandlerCaller = WTFMove(completionHandlerCaller)]() mutable { });
     });
 }
 
@@ -513,12 +571,12 @@
     if (!WTF::convertSafely(fileSize, bytesToRead))
         return WTF::nullopt;
 
-    Vector<char> buffer(bytesToRead);
-    size_t totalBytesRead = FileSystem::readFromFile(fileHandle, buffer.data(), buffer.size());
+    Vector<unsigned char> buffer(bytesToRead);
+    size_t totalBytesRead = FileSystem::readFromFile(fileHandle, reinterpret_cast<char*>(buffer.data()), buffer.size());
     if (totalBytesRead != bytesToRead)
         return WTF::nullopt;
 
-    return String::fromUTF8(buffer.data()).toUInt64Strict();
+    return charactersToUIntStrict(buffer.data(), totalBytesRead);
 }
 
 class ReadOriginsTaskCounter : public RefCounted<ReadOriginsTaskCounter> {
diff --git a/Source/WebKit/NetworkProcess/cache/CacheStorageEngine.h b/Source/WebKit/NetworkProcess/cache/CacheStorageEngine.h
index a3aaaf0..22ee66b 100644
--- a/Source/WebKit/NetworkProcess/cache/CacheStorageEngine.h
+++ b/Source/WebKit/NetworkProcess/cache/CacheStorageEngine.h
@@ -29,6 +29,7 @@
 #include "NetworkCacheData.h"
 #include "WebsiteData.h"
 #include <WebCore/ClientOrigin.h>
+#include <WebCore/StorageQuotaManager.h>
 #include <pal/SessionID.h>
 #include <wtf/HashMap.h>
 #include <wtf/RefCounted.h>
@@ -79,12 +80,15 @@
 
     static void initializeQuotaUser(NetworkProcess&, PAL::SessionID, const WebCore::ClientOrigin&, CompletionHandler<void()>&&);
 
+    static uint64_t diskUsage(const String& rootPath, const WebCore::ClientOrigin&);
+    void requestSpace(const WebCore::ClientOrigin&, uint64_t spaceRequested, CompletionHandler<void(WebCore::StorageQuotaManager::Decision)>&&);
+
     bool shouldPersist() const { return !!m_ioQueue;}
 
     void writeFile(const String& filename, NetworkCache::Data&&, WebCore::DOMCacheEngine::CompletionCallback&&);
     void readFile(const String& filename, CompletionHandler<void(const NetworkCache::Data&, int error)>&&);
     void removeFile(const String& filename);
-    void writeSizeFile(const String&, uint64_t size);
+    void writeSizeFile(const String&, uint64_t size, CompletionHandler<void()>&&);
     static Optional<uint64_t> readSizeFile(const String&);
 
     const String& rootPath() const { return m_rootPath; }
diff --git a/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCache.cpp b/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCache.cpp
index 6fc53e0..ba134cf 100644
--- a/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCache.cpp
+++ b/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCache.cpp
@@ -414,8 +414,11 @@
         auto position = (sameURLRecords && !matchingRecords.isEmpty()) ? sameURLRecords->findMatching([&](const auto& item) { return item.identifier == matchingRecords[0]; }) : notFound;
 
         spaceRequired += record.responseBodySize;
-        if (position != notFound)
-            spaceRequired -= sameURLRecords->at(position).size;
+        if (position != notFound) {
+            uint64_t spaceDecreased = sameURLRecords->at(position).size;
+            if (spaceRequired >= spaceDecreased)
+                spaceRequired -= spaceDecreased;
+        }
     }
 
     m_caches.requestSpace(spaceRequired, [caches = makeRef(m_caches), identifier = m_identifier, records = WTFMove(records), callback = WTFMove(callback)](Optional<DOMCacheEngine::Error>&& error) mutable {
@@ -450,7 +453,10 @@
         return shouldRemove;
     });
 
-    callback(WTFMove(recordIdentifiers));
+    // This operation would change caches size, so make sure callback finishes after size file is updated.
+    m_caches.updateSizeFile([callback = WTFMove(callback), recordIdentifiers = WTFMove(recordIdentifiers)]() mutable {
+        callback(WTFMove(recordIdentifiers));
+    });
 }
 
 void Cache::removeFromRecordList(const Vector<uint64_t>& recordIdentifiers)
diff --git a/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.cpp b/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.cpp
index 03a060c..f237451 100644
--- a/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.cpp
+++ b/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.cpp
@@ -56,36 +56,21 @@
     return FileSystem::pathByAppendingComponent(cachesRootsPath, "estimatedsize"_s);
 }
 
-Ref<Caches> Caches::create(Engine& engine, WebCore::ClientOrigin&& origin, String&& rootPath, WebCore::StorageQuotaManager& quotaManager)
+Ref<Caches> Caches::create(Engine& engine, WebCore::ClientOrigin&& origin, String&& rootPath)
 {
-    auto caches = adoptRef(*new Caches { engine, WTFMove(origin), WTFMove(rootPath), quotaManager });
-    quotaManager.addUser(caches.get());
-    return caches;
+    return adoptRef(*new Caches { engine, WTFMove(origin), WTFMove(rootPath) });
 }
 
-Caches::Caches(Engine& engine, WebCore::ClientOrigin&& origin, String&& rootPath, WebCore::StorageQuotaManager& quotaManager)
+Caches::Caches(Engine& engine, WebCore::ClientOrigin&& origin, String&& rootPath)
     : m_engine(&engine)
     , m_origin(WTFMove(origin))
     , m_rootPath(WTFMove(rootPath))
-    , m_quotaManager(makeWeakPtr(quotaManager))
 {
 }
 
 Caches::~Caches()
 {
     ASSERT(m_pendingWritingCachesToDiskCallbacks.isEmpty());
-
-    if (m_quotaManager)
-        m_quotaManager->removeUser(*this);
-}
-
-void Caches::whenInitialized(CompletionHandler<void()>&& callback)
-{
-    initialize([callback = WTFMove(callback)](auto&& error) mutable {
-        if (error)
-            RELEASE_LOG_ERROR(CacheStorage, "Caches::initialize failed, reported space used will be zero");
-        callback();
-    });
 }
 
 void Caches::retrieveOriginFromDirectory(const String& folderPath, WorkQueue& queue, WTF::CompletionHandler<void(Optional<WebCore::ClientOrigin>&&)>&& completionHandler)
@@ -208,10 +193,14 @@
     });
 }
 
-void Caches::updateSizeFile()
+void Caches::updateSizeFile(CompletionHandler<void()>&& completionHandler)
 {
-    if (m_engine)
-        m_engine->writeSizeFile(cachesSizeFilename(m_rootPath), m_size);
+    if (!m_engine) {
+        completionHandler();
+        return;
+    }
+
+    m_engine->writeSizeFile(cachesSizeFilename(m_rootPath), m_size, WTFMove(completionHandler));
 }
 
 void Caches::initializeSize()
@@ -232,13 +221,12 @@
                 return;
             }
             m_size = size;
-            updateSizeFile();
-
-            m_isInitialized = true;
-            auto pendingCallbacks = WTFMove(m_pendingInitializationCallbacks);
-            for (auto& callback : pendingCallbacks)
-                callback(WTF::nullopt);
-
+            updateSizeFile([this, protectedThis = WTFMove(protectedThis)]() mutable {
+                m_isInitialized = true;
+                auto pendingCallbacks = WTFMove(m_pendingInitializationCallbacks);
+                for (auto& callback : pendingCallbacks)
+                    callback(WTF::nullopt);
+            });
             return;
         }
         auto decoded = Cache::decodeRecordHeader(*storage);
@@ -273,13 +261,11 @@
         m_storage->clear(String { }, -WallTime::infinity(), [protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)]() mutable {
             ASSERT(RunLoop::isMain());
             protectedThis->clearMemoryRepresentation();
-            protectedThis->resetSpaceUsed();
             completionHandler();
         });
         return;
     }
     clearMemoryRepresentation();
-    resetSpaceUsed();
     clearPendingWritingCachesToDiskCallbacks();
     completionHandler();
 }
@@ -525,12 +511,12 @@
 
 void Caches::requestSpace(uint64_t spaceRequired, WebCore::DOMCacheEngine::CompletionCallback&& callback)
 {
-    if (!m_quotaManager) {
+    if (!m_engine) {
         callback(Error::QuotaExceeded);
         return;
     }
 
-    m_quotaManager->requestSpace(spaceRequired, [callback = WTFMove(callback)](auto decision) mutable {
+    m_engine->requestSpace(m_origin, spaceRequired, [callback = WTFMove(callback)](auto decision) mutable {
         switch (decision) {
         case WebCore::StorageQuotaManager::Decision::Deny:
             callback(Error::QuotaExceeded);
@@ -548,7 +534,6 @@
     ASSERT(m_size >= previousRecordSize);
     m_size += recordInformation.size;
     m_size -= previousRecordSize;
-    updateSizeFile();
 
     if (!shouldPersist()) {
         m_volatileStorage.set(recordInformation.key, WTFMove(record));
@@ -556,13 +541,15 @@
         return;
     }
 
-    m_storage->store(Cache::encode(recordInformation, record), { }, [protectedStorage = makeRef(*m_storage), callback = WTFMove(callback)](int error) mutable {
+    m_storage->store(Cache::encode(recordInformation, record), { }, [this, protectedThis = makeRef(*this), protectedStorage = makeRef(*m_storage), callback = WTFMove(callback)](int error) mutable {
         if (error) {
             RELEASE_LOG_ERROR(CacheStorage, "Caches::writeRecord failed with error %d", error);
             callback(Error::WriteDisk);
             return;
         }
-        callback(WTF::nullopt);
+        updateSizeFile([callback = WTFMove(callback)]() mutable {
+            callback(WTF::nullopt);
+        });
     });
 }
 
@@ -605,7 +592,7 @@
 
     ASSERT(m_size >= record.size);
     m_size -= record.size;
-    updateSizeFile();
+    updateSizeFile([] { });
 
     removeCacheEntry(record.key);
 }
@@ -621,17 +608,6 @@
     m_storage->remove(key);
 }
 
-void Caches::resetSpaceUsed()
-{
-    m_size = 0;
-    updateSizeFile();
-
-    if (m_quotaManager) {
-        m_quotaManager->removeUser(*this);
-        m_quotaManager->addUser(*this);
-    }
-}
-
 void Caches::clearMemoryRepresentation()
 {
     makeDirty();
diff --git a/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.h b/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.h
index 03231f3..5d394a0 100644
--- a/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.h
+++ b/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.h
@@ -28,7 +28,6 @@
 #include "CacheStorageEngineCache.h"
 #include "NetworkCacheStorage.h"
 #include <WebCore/ClientOrigin.h>
-#include <WebCore/StorageQuotaUser.h>
 #include <wtf/CompletionHandler.h>
 #include <wtf/Deque.h>
 
@@ -42,10 +41,10 @@
 
 class Engine;
 
-class Caches final : public RefCounted<Caches>, private WebCore::StorageQuotaUser {
+class Caches final : public RefCounted<Caches> {
 public:
-    static String cachesSizeFilename(const String&);
-    static Ref<Caches> create(Engine&, WebCore::ClientOrigin&&, String&& rootPath, WebCore::StorageQuotaManager&);
+    static String cachesSizeFilename(const String& cachesRootsPath);
+    static Ref<Caches> create(Engine&, WebCore::ClientOrigin&&, String&& rootPath);
     ~Caches();
 
     static void retrieveOriginFromDirectory(const String& folderPath, WorkQueue&, WTF::CompletionHandler<void(Optional<WebCore::ClientOrigin>&&)>&&);
@@ -79,22 +78,17 @@
 
     void clear(WTF::CompletionHandler<void()>&&);
     void clearMemoryRepresentation();
-    void resetSpaceUsed();
 
     uint64_t storageSize() const;
+    void updateSizeFile(CompletionHandler<void()>&&);
 
 private:
-    Caches(Engine&, WebCore::ClientOrigin&&, String&& rootPath, WebCore::StorageQuotaManager&);
-
-    // StorageQuotaUser API.
-    uint64_t spaceUsed() const final { return m_size; }
+    Caches(Engine&, WebCore::ClientOrigin&&, String&& rootPath);
 
     void initializeSize();
     void readCachesFromDisk(WTF::Function<void(Expected<Vector<Cache>, WebCore::DOMCacheEngine::Error>&&)>&&);
     void writeCachesToDisk(WebCore::DOMCacheEngine::CompletionCallback&&);
 
-    void whenInitialized(CompletionHandler<void()>&&) final;
-
     void storeOrigin(WebCore::DOMCacheEngine::CompletionCallback&&);
     static Optional<WebCore::ClientOrigin> readOrigin(const NetworkCache::Data&);
 
@@ -106,8 +100,6 @@
 
     bool hasActiveCache() const;
 
-    void updateSizeFile();
-
     bool m_isInitialized { false };
     Engine* m_engine { nullptr };
     uint64_t m_updateCounter { 0 };
@@ -122,7 +114,6 @@
     Vector<WebCore::DOMCacheEngine::CompletionCallback> m_pendingInitializationCallbacks;
     bool m_isWritingCachesToDisk { false };
     Deque<CompletionHandler<void(Optional<WebCore::DOMCacheEngine::Error>)>> m_pendingWritingCachesToDiskCallbacks;
-    WeakPtr<WebCore::StorageQuotaManager> m_quotaManager;
 };
 
 } // namespace CacheStorage
diff --git a/Source/WebKit/Shared/WebsiteDataStoreParameters.cpp b/Source/WebKit/Shared/WebsiteDataStoreParameters.cpp
index c0fcf9c..6d0c129 100644
--- a/Source/WebKit/Shared/WebsiteDataStoreParameters.cpp
+++ b/Source/WebKit/Shared/WebsiteDataStoreParameters.cpp
@@ -55,6 +55,8 @@
 
     encoder << localStorageDirectory << localStorageDirectoryExtensionHandle;
 
+    encoder << cacheStorageDirectory << cacheStorageDirectoryExtensionHandle;
+
     encoder << perOriginStorageQuota;
     encoder << perThirdPartyOriginStorageQuota;
 }
@@ -141,6 +143,18 @@
         return WTF::nullopt;
     parameters.localStorageDirectoryExtensionHandle = WTFMove(*localStorageDirectoryExtensionHandle);
 
+    Optional<String> cacheStorageDirectory;
+    decoder >> cacheStorageDirectory;
+    if (!cacheStorageDirectory)
+        return WTF::nullopt;
+    parameters.cacheStorageDirectory = WTFMove(*cacheStorageDirectory);
+
+    Optional<SandboxExtension::Handle> cacheStorageDirectoryExtensionHandle;
+    decoder >> cacheStorageDirectoryExtensionHandle;
+    if (!cacheStorageDirectoryExtensionHandle)
+        return WTF::nullopt;
+    parameters.cacheStorageDirectoryExtensionHandle = WTFMove(*cacheStorageDirectoryExtensionHandle);
+
     Optional<uint64_t> perOriginStorageQuota;
     decoder >> perOriginStorageQuota;
     if (!perOriginStorageQuota)
diff --git a/Source/WebKit/Shared/WebsiteDataStoreParameters.h b/Source/WebKit/Shared/WebsiteDataStoreParameters.h
index 095f09d..f27df48 100644
--- a/Source/WebKit/Shared/WebsiteDataStoreParameters.h
+++ b/Source/WebKit/Shared/WebsiteDataStoreParameters.h
@@ -71,6 +71,9 @@
     String localStorageDirectory;
     SandboxExtension::Handle localStorageDirectoryExtensionHandle;
 
+    String cacheStorageDirectory;
+    SandboxExtension::Handle cacheStorageDirectoryExtensionHandle;
+
     uint64_t perOriginStorageQuota { WebCore::StorageQuotaManager::defaultQuota() };
     uint64_t perThirdPartyOriginStorageQuota { WebCore::StorageQuotaManager::defaultThirdPartyQuota() };
 };
diff --git a/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp b/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp
index 24cc1af..6f5a907 100644
--- a/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp
+++ b/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp
@@ -686,3 +686,11 @@
 {
     WebKit::toImpl(dataStoreRef)->setCacheModelSynchronouslyForTesting(WebKit::toCacheModel(cacheModel));
 }
+
+void WKWebsiteDataStoreResetQuota(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreResetQuotaCallback callback)
+{
+    WebKit::toImpl(dataStoreRef)->resetQuota([context, callback] {
+        if (callback)
+            callback(context);
+    });
+}
diff --git a/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h b/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h
index 10baf7e..12119a5 100644
--- a/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h
+++ b/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h
@@ -155,6 +155,9 @@
 
 WK_EXPORT void WKWebsiteDataStoreSetCacheModelSynchronouslyForTesting(WKWebsiteDataStoreRef dataStoreRef, WKCacheModel cacheModel);
 
+typedef void (*WKWebsiteDataStoreResetQuotaCallback)(void* functionContext);
+WK_EXPORT void WKWebsiteDataStoreResetQuota(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreResetQuotaCallback callback);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp b/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp
index 172bb33..45aeba4 100644
--- a/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp
+++ b/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp
@@ -1367,6 +1367,11 @@
     m_activityFromWebProcesses = nullptr;
 }
 
+void NetworkProcessProxy::resetQuota(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
+{
+    sendWithAsyncReply(Messages::NetworkProcess::ResetQuota(sessionID), WTFMove(completionHandler));
+}
+
 } // namespace WebKit
 
 #undef MESSAGE_CHECK
diff --git a/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h b/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h
index b1322bb..0c69a76 100644
--- a/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h
+++ b/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h
@@ -56,6 +56,7 @@
 enum class StorageAccessWasGranted : bool;
 class SecurityOrigin;
 struct SecurityOriginData;
+struct ClientOrigin;
 }
 
 namespace WebKit {
@@ -196,6 +197,8 @@
     void registerSchemeForLegacyCustomProtocol(const String&);
     void unregisterSchemeForLegacyCustomProtocol(const String&);
 
+    void resetQuota(PAL::SessionID, CompletionHandler<void()>&&);
+
 private:
     // AuxiliaryProcessProxy
     void getLaunchOptions(ProcessLauncher::LaunchOptions&) override;
diff --git a/Source/WebKit/UIProcess/WebProcessPool.cpp b/Source/WebKit/UIProcess/WebProcessPool.cpp
index 4025556..a6887b9 100644
--- a/Source/WebKit/UIProcess/WebProcessPool.cpp
+++ b/Source/WebKit/UIProcess/WebProcessPool.cpp
@@ -551,6 +551,12 @@
     parameters.defaultDataStoreParameters.localStorageDirectory = localStorageDirectory;
     SandboxExtension::createHandleForReadWriteDirectory(localStorageDirectory, parameters.defaultDataStoreParameters.localStorageDirectoryExtensionHandle);
 
+    auto cacheStorageDirectory = m_websiteDataStore ? m_websiteDataStore->cacheStorageDirectory() : nullString();
+    if (!cacheStorageDirectory.isEmpty()) {
+        SandboxExtension::createHandleForReadWriteDirectory(cacheStorageDirectory, parameters.defaultDataStoreParameters.cacheStorageDirectoryExtensionHandle);
+        parameters.defaultDataStoreParameters.cacheStorageDirectory = WTFMove(cacheStorageDirectory);
+    }
+
     if (m_websiteDataStore)
         parameters.defaultDataStoreParameters.networkSessionParameters.resourceLoadStatisticsDirectory = m_websiteDataStore->resolvedResourceLoadStatisticsDirectory();
     if (parameters.defaultDataStoreParameters.networkSessionParameters.resourceLoadStatisticsDirectory.isEmpty())
diff --git a/Source/WebKit/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm b/Source/WebKit/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm
index b1f5401..2904b07 100644
--- a/Source/WebKit/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm
+++ b/Source/WebKit/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm
@@ -195,6 +195,10 @@
     if (!parameters.localStorageDirectory.isEmpty())
         SandboxExtension::createHandleForReadWriteDirectory(parameters.localStorageDirectory, parameters.localStorageDirectoryExtensionHandle);
 
+    parameters.cacheStorageDirectory = cacheStorageDirectory();
+    if (!parameters.cacheStorageDirectory.isEmpty())
+        SandboxExtension::createHandleForReadWriteDirectory(parameters.cacheStorageDirectory, parameters.cacheStorageDirectoryExtensionHandle);
+
     parameters.perOriginStorageQuota = perOriginStorageQuota();
     parameters.perThirdPartyOriginStorageQuota = perThirdPartyOriginStorageQuota();
 
diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
index 6b4b02c..e654e74 100644
--- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
+++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
@@ -2087,6 +2087,12 @@
         SandboxExtension::createHandleForReadWriteDirectory(localStorageDirectory, parameters.localStorageDirectoryExtensionHandle);
     }
 
+    auto cacheStorageDirectory = this->cacheStorageDirectory();
+    if (!cacheStorageDirectory.isEmpty()) {
+        SandboxExtension::createHandleForReadWriteDirectory(cacheStorageDirectory, parameters.cacheStorageDirectoryExtensionHandle);
+        parameters.cacheStorageDirectory = cacheStorageDirectory;
+    }
+
 #if ENABLE(INDEXED_DATABASE)
     parameters.indexedDatabaseDirectory = resolvedIndexedDatabaseDirectory();
     if (!parameters.indexedDatabaseDirectory.isEmpty())
@@ -2173,6 +2179,15 @@
     ASSERT(!completionHandler);
 }
 
+void WebsiteDataStore::resetQuota(CompletionHandler<void()>&& completionHandler)
+{
+    auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
+    for (auto& processPool : processPools()) {
+        if (auto* process = processPool->networkProcess())
+            process->resetQuota(m_sessionID, [callbackAggregator = callbackAggregator.copyRef()] { });
+    }
+}
+
 #if !PLATFORM(COCOA)
 WTF::String WebsiteDataStore::defaultMediaCacheDirectory()
 {
diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h
index eb9604e..44f4fdd 100644
--- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h
+++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h
@@ -291,7 +291,9 @@
     static WTF::String defaultMediaKeysStorageDirectory();
     static WTF::String defaultDeviceIdHashSaltsStorageDirectory();
     static WTF::String defaultJavaScriptConfigurationDirectory();
-    
+
+    void resetQuota(CompletionHandler<void()>&&);
+
 private:
     void fetchDataAndApply(OptionSet<WebsiteDataType>, OptionSet<WebsiteDataFetchOption>, RefPtr<WorkQueue>&&, Function<void(Vector<WebsiteDataRecord>)>&& apply);
 
diff --git a/Tools/ChangeLog b/Tools/ChangeLog
index fa0a466..86a1da0 100644
--- a/Tools/ChangeLog
+++ b/Tools/ChangeLog
@@ -1,3 +1,19 @@
+2019-12-02  Sihui Liu  <sihui_liu@apple.com>
+
+        Cross-thread version StorageQuotaManager
+        https://bugs.webkit.org/show_bug.cgi?id=203971
+        <rdar://problem/57290349>
+
+        Reviewed by Chris Dumez.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebCore/StorageQuotaManager.cpp: Removed as we have a different StorageQuotaManager 
+        implementation now.
+        * WebKitTestRunner/TestController.cpp: reset StorageQuotaManager's quota between tests.
+        (WTR::TestController::resetStateToConsistentValues):
+        (WTR::TestController::resetQuota):
+        * WebKitTestRunner/TestController.h:
+
 2019-12-02  Saam Barati  <sbarati@apple.com>
 
         run-jsc should exit with the same signal or exit status that the `jsc` shell does
diff --git a/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj b/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
index d5768ed..8252f98 100644
--- a/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
+++ b/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
@@ -738,7 +738,6 @@
 		9399BA062371114F008392BF /* IndexedDBNotInPageCache.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 9399BA03237110BF008392BF /* IndexedDBNotInPageCache.html */; };
 		93AF4ECE1506F064007FD57E /* NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93AF4ECD1506F064007FD57E /* NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp */; };
 		93AF4ED11506F130007FD57E /* lots-of-images.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 93AF4ECF1506F123007FD57E /* lots-of-images.html */; };
-		93B62054234EA62C00D49B97 /* StorageQuotaManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93B62053234EA32B00D49B97 /* StorageQuotaManager.cpp */; };
 		93CFA8671CEB9E38000565A8 /* autofocused-text-input.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 93CFA8661CEB9DE1000565A8 /* autofocused-text-input.html */; };
 		93D119FC22C680F7009BE3C7 /* localstorage-open-window-private.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 93D119FB22C57112009BE3C7 /* localstorage-open-window-private.html */; };
 		93E2C5551FD3204100E1DF6A /* LineEnding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93E2C5541FD3204100E1DF6A /* LineEnding.cpp */; };
@@ -1143,7 +1142,6 @@
 			dstPath = TestWebKitAPI.resources;
 			dstSubfolderSpec = 7;
 			files = (
-				CD8394DF232AF7C000149495 /* media-loading.html in Copy Resources */,
 				55A817FF2181021A0004A39A /* 100x100-red.tga in Copy Resources */,
 				1A9E52C913E65EF4006917F5 /* 18-characters.html in Copy Resources */,
 				55A81800218102210004A39A /* 400x400-green.png in Copy Resources */,
@@ -1376,6 +1374,7 @@
 				930AD402150698D00067970F /* lots-of-text.html in Copy Resources */,
 				AD57AC221DA7466E00FF1BDE /* many-iframes.html in Copy Resources */,
 				7772ECE122FE06C60009A799 /* many-same-origin-iframes.html in Copy Resources */,
+				CD8394DF232AF7C000149495 /* media-loading.html in Copy Resources */,
 				CDA3159A1ED548F1009F60D3 /* MediaPlaybackSleepAssertion.html in Copy Resources */,
 				CDC9442F1EF205D60059C3C4 /* mediastreamtrack-detached.html in Copy Resources */,
 				E1220DCA155B28AA0013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.html in Copy Resources */,
@@ -2149,7 +2148,6 @@
 		93AF4ECA1506F035007FD57E /* NewFirstVisuallyNonEmptyLayoutForImages.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewFirstVisuallyNonEmptyLayoutForImages.cpp; sourceTree = "<group>"; };
 		93AF4ECD1506F064007FD57E /* NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp; sourceTree = "<group>"; };
 		93AF4ECF1506F123007FD57E /* lots-of-images.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "lots-of-images.html"; sourceTree = "<group>"; };
-		93B62053234EA32B00D49B97 /* StorageQuotaManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StorageQuotaManager.cpp; sourceTree = "<group>"; };
 		93CFA8661CEB9DE1000565A8 /* autofocused-text-input.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "autofocused-text-input.html"; sourceTree = "<group>"; };
 		93CFA8681CEBCFED000565A8 /* CandidateTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CandidateTests.mm; sourceTree = "<group>"; };
 		93D119FB22C57112009BE3C7 /* localstorage-open-window-private.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "localstorage-open-window-private.html"; sourceTree = "<group>"; };
@@ -3127,7 +3125,6 @@
 				41973B5C1AF22875006C7B36 /* SharedBuffer.cpp */,
 				A17991891E1CA24100A505ED /* SharedBufferTest.cpp */,
 				A179918A1E1CA24100A505ED /* SharedBufferTest.h */,
-				93B62053234EA32B00D49B97 /* StorageQuotaManager.cpp */,
 				ECA680CD1E68CC0900731D20 /* StringUtilities.mm */,
 				CE4D5DE51F6743BA0072CFC6 /* StringWithDirection.cpp */,
 				93A258981F92FF15003E510C /* TextCodec.cpp */,
@@ -3855,6 +3852,7 @@
 				930AD401150698B30067970F /* lots-of-text.html */,
 				AD57AC1D1DA7463800FF1BDE /* many-iframes.html */,
 				7772ECE022FE05E10009A799 /* many-same-origin-iframes.html */,
+				CD8394DE232AF15E00149495 /* media-loading.html */,
 				CDC9442B1EF1FBD20059C3C4 /* mediastreamtrack-detached.html */,
 				51CD1C711B38D48400142CA5 /* modal-alerts-in-new-about-blank-window.html */,
 				7A1458FB1AD5C03500E06772 /* mouse-button-listener.html */,
@@ -3886,7 +3884,6 @@
 				07CD32F72065B72A0064A4BE /* video.html */,
 				1C2B81841C8924A200A5529F /* webfont.html */,
 				468F2F932368DAA700F4B864 /* window-open-then-document-open.html */,
-				CD8394DE232AF15E00149495 /* media-loading.html */,
 			);
 			name = Resources;
 			sourceTree = "<group>";
@@ -4868,7 +4865,6 @@
 				7CCE7ECF1A411A7E00447C4C /* StopLoadingFromDidReceiveResponse.mm in Sources */,
 				CDC0932E21C993440030C4B0 /* StopSuspendResumeAllMedia.mm in Sources */,
 				414AD6862285D1C000777F2D /* StorageQuota.mm in Sources */,
-				93B62054234EA62C00D49B97 /* StorageQuotaManager.cpp in Sources */,
 				515BE1711D428E4B00DD7C68 /* StoreBlobThenDelete.mm in Sources */,
 				7CCE7ED01A411A7E00447C4C /* StringByEvaluatingJavaScriptFromString.mm in Sources */,
 				7CCE7ED11A411A7E00447C4C /* StringTruncator.mm in Sources */,
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/StorageQuotaManager.cpp b/Tools/TestWebKitAPI/Tests/WebCore/StorageQuotaManager.cpp
deleted file mode 100644
index ad1c67b..0000000
--- a/Tools/TestWebKitAPI/Tests/WebCore/StorageQuotaManager.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
-* Copyright (C) 2019 Apple Inc. All Rights Reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
-* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
-* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
-* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include "config.h"
-
-#include <WebCore/StorageQuotaManager.h>
-#include <WebCore/StorageQuotaUser.h>
-
-using namespace WebCore;
-
-namespace TestWebKitAPI {
-
-static const int defaultQuota = 1 * KB;
-
-class MockQuotaUser final : public WebCore::StorageQuotaUser {
-public:
-    explicit MockQuotaUser(StorageQuotaManager& manager)
-        : m_manager(&manager)
-    {
-        manager.addUser(*this);
-    }
-
-    void setSpaceUsed(uint64_t spaceUsed) { m_spaceUsed = spaceUsed; }
-
-private:
-    uint64_t spaceUsed() const final
-    {
-        return m_spaceUsed;
-    }
-
-    void whenInitialized(CompletionHandler<void()>&& callback) final
-    {
-        if (!m_spaceUsed)
-            ASSERT_EQ(m_manager->state(), StorageQuotaManager::State::Uninitialized);
-        else
-            ASSERT_EQ(m_manager->state(), StorageQuotaManager::State::ComputingSpaceUsed);
-
-        // Reset usage to mock deletion.
-        m_spaceUsed = 0;
-        callback();
-    }
-
-    uint64_t m_spaceUsed { 0 };
-    StorageQuotaManager* m_manager;
-};
-    
-TEST(StorageQuotaManagerTest, Basic)
-{
-    StorageQuotaManager* storageQuotaManagerPtr = nullptr;
-    StorageQuotaManager storageQuotaManager(defaultQuota, [&storageQuotaManagerPtr](uint64_t quota, uint64_t currentSpace, uint64_t spaceIncrease, CompletionHandler<void(Optional<uint64_t>)>&& completionHanlder) {
-        ASSERT_TRUE(storageQuotaManagerPtr);
-        ASSERT_EQ(storageQuotaManagerPtr->state(), StorageQuotaManager::State::WaitingForSpaceIncreaseResponse);
-
-        // Allow all space increase requests.
-        completionHanlder(spaceIncrease + currentSpace);
-    });
-    storageQuotaManagerPtr = &storageQuotaManager;
-
-
-    MockQuotaUser mockUser(storageQuotaManager);
-
-    // Grant directly.
-    storageQuotaManager.requestSpace(0.1 * KB, [&](WebCore::StorageQuotaManager::Decision decision) {
-        ASSERT_EQ(decision, WebCore::StorageQuotaManager::Decision::Grant);
-        mockUser.setSpaceUsed(0.1 * KB);
-    });
-
-    // Grant after computing accurate usage.
-    storageQuotaManager.requestSpace(1.0 * KB, [&](WebCore::StorageQuotaManager::Decision decision) {
-        ASSERT_EQ(decision, WebCore::StorageQuotaManager::Decision::Grant);
-        mockUser.setSpaceUsed(1.0 * KB);
-    });
-
-    // Grant after computing accurate usage and requesting space increase.
-    storageQuotaManager.requestSpace(10 * KB, [&](WebCore::StorageQuotaManager::Decision decision) {
-        ASSERT_EQ(storageQuotaManagerPtr->state(), StorageQuotaManager::State::MakingDecisionForRequest);
-        ASSERT_EQ(decision, WebCore::StorageQuotaManager::Decision::Grant);
-    });
-}
-
-} // namespace TestWebKitAPI
diff --git a/Tools/WebKitTestRunner/TestController.cpp b/Tools/WebKitTestRunner/TestController.cpp
index f21e89b..14db2d2 100644
--- a/Tools/WebKitTestRunner/TestController.cpp
+++ b/Tools/WebKitTestRunner/TestController.cpp
@@ -983,6 +983,8 @@
     clearServiceWorkerRegistrations();
     clearDOMCaches();
 
+    resetQuota();
+
     WKContextSetAllowsAnySSLCertificateForServiceWorkerTesting(platformContext(), true);
 
     WKContextClearCurrentModifierStateForTesting(TestController::singleton().context());
@@ -3149,6 +3151,13 @@
     runUntil(context.done, noTimeout);
 }
 
+void TestController::resetQuota()
+{
+    StorageVoidCallbackContext context(*this);
+    WKWebsiteDataStoreResetQuota(TestController::websiteDataStore(), &context, StorageVoidCallback);
+    runUntil(context.done, noTimeout);
+}
+
 struct FetchCacheOriginsCallbackContext {
     FetchCacheOriginsCallbackContext(TestController& controller, WKStringRef origin)
         : testController(controller)
diff --git a/Tools/WebKitTestRunner/TestController.h b/Tools/WebKitTestRunner/TestController.h
index d6cb0e2..4e87508 100644
--- a/Tools/WebKitTestRunner/TestController.h
+++ b/Tools/WebKitTestRunner/TestController.h
@@ -269,6 +269,8 @@
     void terminateNetworkProcess();
     void terminateServiceWorkerProcess();
 
+    void resetQuota();
+
     void removeAllSessionCredentials();
 
     void clearIndexedDatabases();