Cross-thread version StorageQuotaManager
authorsihui_liu@apple.com <sihui_liu@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 22 Nov 2019 22:42:59 +0000 (22:42 +0000)
committersihui_liu@apple.com <sihui_liu@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 22 Nov 2019 22:42:59 +0000 (22:42 +0000)
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: https://svn.webkit.org/repository/webkit/trunk@252805 268f45cc-cd09-0410-ab3c-d52691b4dbfc

38 files changed:
Source/WebCore/ChangeLog
Source/WebCore/Headers.cmake
Source/WebCore/Modules/indexeddb/server/IDBServer.cpp
Source/WebCore/Modules/indexeddb/server/IDBServer.h
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseConnection.cpp
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp
Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.cpp
Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.h
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/storage/StorageQuotaManager.cpp
Source/WebCore/storage/StorageQuotaManager.h
Source/WebCore/storage/StorageQuotaUser.h [deleted file]
Source/WebKit/ChangeLog
Source/WebKit/NetworkProcess/NetworkProcess.cpp
Source/WebKit/NetworkProcess/NetworkProcess.h
Source/WebKit/NetworkProcess/NetworkProcess.messages.in
Source/WebKit/NetworkProcess/cache/CacheStorageEngine.cpp
Source/WebKit/NetworkProcess/cache/CacheStorageEngine.h
Source/WebKit/NetworkProcess/cache/CacheStorageEngineCache.cpp
Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.cpp
Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.h
Source/WebKit/Shared/WebsiteDataStoreParameters.cpp
Source/WebKit/Shared/WebsiteDataStoreParameters.h
Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp
Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h
Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp
Source/WebKit/UIProcess/Network/NetworkProcessProxy.h
Source/WebKit/UIProcess/WebProcessPool.cpp
Source/WebKit/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm
Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h
Tools/ChangeLog
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WebCore/StorageQuotaManager.cpp [deleted file]
Tools/WebKitTestRunner/TestController.cpp
Tools/WebKitTestRunner/TestController.h

index 09c9962..53130b1 100644 (file)
@@ -1,3 +1,143 @@
+2019-11-22  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-11-22  Eric Carlson  <eric.carlson@apple.com>
 
         ( r251737 ) media/remoteplayback-prompt.html is a flakey timeout
index efc275f..0ec8051 100644 (file)
@@ -1381,7 +1381,6 @@ set(WebCore_PRIVATE_FRAMEWORK_HEADERS
     storage/StorageNamespace.h
     storage/StorageNamespaceProvider.h
     storage/StorageQuotaManager.h
-    storage/StorageQuotaUser.h
     storage/StorageType.h
 
     style/StyleChange.h
index 631c4ce..bba6623 100644 (file)
 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::performCloseAndDeleteDatabasesForOrigins(const Vector<SecurityOr
 
 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())
-{
-    if (manager)
-        manager->addUser(*this);
-}
-
-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)
+StorageQuotaManager::Decision IDBServer::requestSpace(const ClientOrigin& origin, uint64_t taskSize)
 {
     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));
+    return m_spaceRequester(origin, taskSize);
 }
 
-void IDBServer::resetSpaceUsed(const ClientOrigin& origin)
+uint64_t IDBServer::diskUsage(const String& rootDirectory, 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);
-}
+    ASSERT(!isMainThread());
 
-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()
index 3877a05..fc1604f 100644 (file)
@@ -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 @@ enum class ShouldForceStop : bool { No, Yes };
 
 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 @@ public:
     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 @@ public:
     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 @@ private:
     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 @@ private:
 
     String m_databaseDirectoryPath;
 
-    HashMap<ClientOrigin, std::unique_ptr<QuotaUser>> m_quotaUsers;
-    QuotaManagerGetter m_quotaManagerGetter;
+    StorageQuotaManagerSpaceRequester m_spaceRequester;
 };
 
 } // namespace IDBServer
index 8243422..ff8ad8a 100644 (file)
@@ -189,56 +189,6 @@ static inline String quotaErrorMessageName(const char* taskName)
     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 @@ void UniqueIDBDatabase::performCurrentOpenOperation()
     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 @@ void UniqueIDBDatabase::addOpenDatabaseConnection(Ref<UniqueIDBDatabaseConnectio
     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 @@ void UniqueIDBDatabase::openBackingStore(const IDBDatabaseIdentifier& identifier
         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 @@ void UniqueIDBDatabase::didOpenBackingStore(const IDBDatabaseInfo& info, const I
     ASSERT(m_isOpeningBackingStore);
     m_isOpeningBackingStore = false;
 
-    finishSpaceIncreaseTask(taskIdentifier, error.isNull());
-
     if (m_hardClosedForUserDelete)
         return;
 
@@ -879,33 +812,22 @@ void UniqueIDBDatabase::createObjectStore(UniqueIDBDatabaseTransaction& transact
     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 @@ void UniqueIDBDatabase::didPerformCreateObjectStore(uint64_t callbackIdentifier,
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformCreateObjectStore");
 
-    finishSpaceIncreaseTask(callbackIdentifier, error.isNull());
     if (error.isNull())
         m_databaseInfo->addExistingObjectStore(info);
 
@@ -936,17 +857,6 @@ void UniqueIDBDatabase::deleteObjectStore(UniqueIDBDatabaseTransaction& transact
     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 @@ void UniqueIDBDatabase::renameObjectStore(UniqueIDBDatabaseTransaction& transact
     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 @@ void UniqueIDBDatabase::performRenameObjectStore(uint64_t callbackIdentifier, co
     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 @@ void UniqueIDBDatabase::didPerformRenameObjectStore(uint64_t callbackIdentifier,
     ASSERT(isMainThread());
     LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformRenameObjectStore");
 
-    finishSpaceIncreaseTask(callbackIdentifier, error.isNull());
     if (error.isNull())
         m_databaseInfo->renameObjectStore(objectStoreIdentifier, newName);
 
@@ -1052,17 +950,6 @@ void UniqueIDBDatabase::clearObjectStore(UniqueIDBDatabaseTransaction& transacti
     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 @@ void UniqueIDBDatabase::createIndex(UniqueIDBDatabaseTransaction& transaction, c
     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 @@ void UniqueIDBDatabase::didPerformCreateIndex(uint64_t callbackIdentifier, const
     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 @@ void UniqueIDBDatabase::deleteIndex(UniqueIDBDatabaseTransaction& transaction, u
     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 @@ void UniqueIDBDatabase::renameIndex(UniqueIDBDatabaseTransaction& transaction, u
     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 @@ void UniqueIDBDatabase::renameIndexAfterQuotaCheck(uint64_t taskSize, UniqueIDBD
     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 @@ void UniqueIDBDatabase::performRenameIndex(uint64_t callbackIdentifier, const ID
     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 @@ void UniqueIDBDatabase::didPerformRenameIndex(uint64_t callbackIdentifier, const
     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 @@ void UniqueIDBDatabase::didPerformRenameIndex(uint64_t callbackIdentifier, const
     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 @@ void UniqueIDBDatabase::didPerformPutOrAdd(uint64_t callbackIdentifier, const ID
     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 @@ void UniqueIDBDatabase::getRecordAfterQuotaCheck(const IDBRequestData& requestDa
         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 @@ void UniqueIDBDatabase::performGetRecord(uint64_t callbackIdentifier, const IDBR
     LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetRecord");
 
     ASSERT(m_backingStore);
-
     IDBGetResult result;
     IDBError error;
     {
@@ -1518,7 +1331,6 @@ void UniqueIDBDatabase::performGetAllRecords(uint64_t callbackIdentifier, const
     LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetAllRecords");
 
     ASSERT(m_backingStore);
-
     IDBGetAllResult result;
     IDBError error;
     {
@@ -1537,22 +1349,11 @@ void UniqueIDBDatabase::didPerformGetAllRecords(uint64_t callbackIdentifier, con
     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 @@ void UniqueIDBDatabase::didPerformGetCount(uint64_t callbackIdentifier, const ID
     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 @@ void UniqueIDBDatabase::didPerformDeleteRecord(uint64_t callbackIdentifier, cons
     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 @@ void UniqueIDBDatabase::didPerformOpenCursor(uint64_t callbackIdentifier, const
     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 @@ void UniqueIDBDatabase::commitTransaction(UniqueIDBDatabaseTransaction& transact
 
     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 @@ void UniqueIDBDatabase::didPerformCommitTransaction(uint64_t callbackIdentifier,
     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;
index c358de4..ebfc1c5 100644 (file)
@@ -44,6 +44,7 @@
 
 namespace WebCore {
 
+struct ClientOrigin;
 class IDBError;
 class IDBGetAllResult;
 struct IDBGetRecordData;
@@ -89,17 +90,15 @@ public:
     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 @@ private:
 
     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 @@ private:
 
     // 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 @@ private:
     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 @@ private:
 
     HashSet<IDBResourceIdentifier> m_cursorPrefetches;
 
-    HashMap<uint64_t, uint64_t> m_pendingSpaceIncreaseTasks;
-
     bool m_isSuspended { false };
+
+    ClientOrigin m_origin;
 };
 
 } // namespace IDBServer
index fe910fa..8006069 100644 (file)
@@ -76,7 +76,7 @@ void UniqueIDBDatabaseConnection::abortTransactionWithoutCallback(UniqueIDBDatab
     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);
     });
index a8d2bdc..76eddc4 100644 (file)
@@ -79,7 +79,7 @@ void UniqueIDBDatabaseTransaction::abort()
     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 @@ void UniqueIDBDatabaseTransaction::putOrAdd(const IDBRequestData& requestData, c
     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 @@ void UniqueIDBDatabaseTransaction::getRecord(const IDBRequestData& requestData,
     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 @@ void UniqueIDBDatabaseTransaction::getAllRecords(const IDBRequestData& requestDa
     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 @@ void UniqueIDBDatabaseTransaction::getCount(const IDBRequestData& requestData, c
     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 @@ void UniqueIDBDatabaseTransaction::deleteRecord(const IDBRequestData& requestDat
     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 @@ void UniqueIDBDatabaseTransaction::openCursor(const IDBRequestData& requestData,
     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 @@ void UniqueIDBDatabaseTransaction::iterateCursor(const IDBRequestData& requestDa
     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;
index 9111f59..d65bd5a 100644 (file)
@@ -64,30 +64,35 @@ InProcessIDBServer::~InProcessIDBServer() = default;
 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);
index c7b5321..8e736a7 100644 (file)
@@ -64,7 +64,6 @@ public:
     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 @@ private:
     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
index 0f48cf0..3d02ed1 100644 (file)
                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, ); }; };
                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>"; };
                                1A37636A1A2E68BB009A7EE2 /* StorageNamespaceProvider.h */,
                                41DE7C7A222DA13D00532B65 /* StorageQuotaManager.cpp */,
                                41DE7C7B222DA13E00532B65 /* StorageQuotaManager.h */,
-                               41DE7C78222DA13C00532B65 /* StorageQuotaUser.h */,
                                5166D3CC1E8ED41100AD62E3 /* StorageType.h */,
                        );
                        indentWidth = 4;
                                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 */,
index 8525752..0c613d1 100644 (file)
 #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);
+    // Fast path.
+    if (m_quotaCountDownLock.tryLock()) {
+        if (tryGrantRequest(spaceRequested)) {
+            m_quotaCountDownLock.unlock();
+            callback(Decision::Grant);
+            return;
         }
+        m_quotaCountDownLock.unlock();
     }
-    for (auto* user : usersToInitialize) {
-        if (m_pendingInitializationUsers.contains(user))
-            askUserToInitialize(*user);
-    }
+
+    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::askUserToInitialize(StorageQuotaUser& user)
+StorageQuotaManager::Decision StorageQuotaManager::requestSpaceOnBackgroundThread(uint64_t spaceRequested)
 {
-    user.whenInitialized([this, &user, weakThis = makeWeakPtr(this)]() {
-        if (!weakThis)
-            return;
+    ASSERT(!isMainThread());
 
-        if (m_pendingInitializationUsers.remove(&user))
-            m_users.add(&user);
+    LockHolder locker(m_quotaCountDownLock);
 
-        if (!m_pendingInitializationUsers.isEmpty())
-            return;
+    if (tryGrantRequest(spaceRequested))
+        return Decision::Grant;
 
-        // Make sure quota is set before handling first request.
-        if (m_state == State::Uninitialized) {
-            updateQuotaBasedOnSpaceUsage();
-            m_state = State::MakingDecisionForRequest;
-        }
+    m_usage = m_usageGetter();
+    updateQuotaBasedOnUsage();
+    m_quotaCountDown = m_usage < m_quota ? m_quota - m_usage : 0;
+    if (tryGrantRequest(spaceRequested))
+        return Decision::Grant;
 
-        processPendingRequests({ });
-    });
-}
+    // 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());
 
-void StorageQuotaManager::addUser(StorageQuotaUser& user)
-{
-    ASSERT(!m_pendingInitializationUsers.contains(&user));
-    ASSERT(!m_users.contains(&user));
-    m_pendingInitializationUsers.add(&user, WhenInitializedCalled::No);
+            if (newQuota)
+                m_quota = *newQuota;
 
-    if (!m_pendingRequests.isEmpty())
-        askUserToInitialize(user);
-}
+            semaphore.signal();
+        });
+    });
 
-bool StorageQuotaManager::shouldAskForMoreSpace(uint64_t spaceIncrease) const
-{
-    if (!spaceIncrease)
-        return false;
+    semaphore.wait();
 
-    return spaceUsage() + spaceIncrease > m_quota;
+    m_usage = m_usageGetter();
+    m_quotaCountDown = m_usage < m_quota ? m_quota - m_usage : 0;
+    return tryGrantRequest(spaceRequested) ? Decision::Grant : Decision::Deny;
 }
 
-void StorageQuotaManager::removeUser(StorageQuotaUser& user)
+bool StorageQuotaManager::tryGrantRequest(uint64_t spaceRequested)
 {
-    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({ });
-        });
+    ASSERT(m_quotaCountDownLock.isLocked());
+    if (spaceRequested <= m_quotaCountDown) {
+        m_quotaCountDown -= spaceRequested;
+        return true;
     }
+    return false;
 }
-
-void StorageQuotaManager::requestSpace(uint64_t spaceIncrease, RequestCallback&& callback)
+    
+void StorageQuotaManager::updateQuotaBasedOnUsage()
 {
-    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;
+    // 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));
     }
-
-    m_state = State::MakingDecisionForRequest;
-    callback(Decision::Grant);
 }
 
-void StorageQuotaManager::askForMoreSpace(uint64_t spaceIncrease)
+void StorageQuotaManager::resetQuotaUpdatedBasedOnUsageForTesting()
 {
-    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);
-    });
+    LockHolder locker(m_quotaCountDownLock);
+    m_quota = m_initialQuota;
+    m_quotaCountDown = 0;
+    m_quotaUpdatedBasedOnUsage = false;
 }
 
-void StorageQuotaManager::processPendingRequests(Optional<uint64_t> newQuota)
+void StorageQuotaManager::resetQuotaForTesting()
 {
-    if (m_pendingRequests.isEmpty())
-        return;
-
-    if (newQuota)
-        m_quota = *newQuota;
-
-    if (m_state == State::WaitingForSpaceIncreaseResponse)
-        return;
-
-    if (!m_pendingInitializationUsers.isEmpty())
-        return;
-
-    if (m_state == State::AskingForMoreSpace) {
-        auto request = m_pendingRequests.takeFirst();
-        bool shouldAllowRequest = !shouldAskForMoreSpace(request.spaceIncrease);
-
-        RELEASE_LOG(Storage, "%p - StorageQuotaManager::processPendingRequests first request decision is %d", this, shouldAllowRequest);
-
-        m_state = State::MakingDecisionForRequest;
-        request.callback(shouldAllowRequest ? Decision::Grant : Decision::Deny);
-    }
-
-    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);
-    }
+    LockHolder locker(m_quotaCountDownLock);
+    m_quota = m_initialQuota;
+    m_quotaCountDown = 0;
 }
 
 } // namespace WebCore
index 0956630..9bdfdd4 100644 (file)
 
 #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);
-
-    void initializeUsersIfNeeded();
-    void askUserToInitialize(StorageQuotaUser&);
+    StorageQuotaManager(uint64_t quota, UsageGetter&&, QuotaIncreaseRequester&&);
+    bool tryGrantRequest(uint64_t);
 
-    void processPendingRequests(Optional<uint64_t>);
+    void updateQuotaBasedOnUsage();
 
+    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 (file)
index b710cee..0000000
+++ /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
index 5f28fd5..32076fd 100644 (file)
@@ -1,3 +1,88 @@
+2019-11-22  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-11-22  Alex Christensen  <achristensen@webkit.org>
 
         Revert r250421
index e934f2c..b54d62a 100644 (file)
@@ -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>
@@ -318,6 +319,9 @@ void NetworkProcess::initializeNetworkProcess(NetworkProcessCreationParameters&&
     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
@@ -328,7 +332,6 @@ void NetworkProcess::initializeNetworkProcess(NetworkProcessCreationParameters&&
         addServiceWorkerSession(PAL::SessionID::defaultSessionID(), serviceWorkerProcessTerminationDelayEnabled, WTFMove(parameters.serviceWorkerRegistrationDirectory), parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
     }
 #endif
-    initializeStorageQuota(parameters.defaultDataStoreParameters);
 
     m_storageManagerSet->add(sessionID, parameters.defaultDataStoreParameters.localStorageDirectory, parameters.defaultDataStoreParameters.localStorageDirectoryExtensionHandle);
 
@@ -436,28 +439,39 @@ void NetworkProcess::clearCachedCredentials()
 
 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)
@@ -578,8 +592,6 @@ void NetworkProcess::destroySession(PAL::SessionID sessionID)
 #endif
 
     m_storageManagerSet->remove(sessionID);
-
-    m_storageQuotaManagers.remove(sessionID);
 }
 
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
@@ -1470,9 +1482,6 @@ void NetworkProcess::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<Websi
     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();
@@ -1565,19 +1574,6 @@ void NetworkProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, Optio
         }
         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)
@@ -2224,10 +2220,9 @@ Ref<IDBServer::IDBServer> NetworkProcess::createIDBServer(PAL::SessionID session
         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;
     });
 }
 
@@ -2314,8 +2309,18 @@ void NetworkProcess::addIndexedDatabaseSession(PAL::SessionID sessionID, String&
         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)
@@ -2332,9 +2337,18 @@ void NetworkProcess::clearLegacyPrivateBrowsingLocalStorage()
 
 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)
@@ -2411,62 +2425,35 @@ void NetworkProcess::requestStorageSpace(PAL::SessionID sessionID, const ClientO
     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;
-    }
+RefPtr<StorageQuotaManager> NetworkProcess::storageQuotaManager(PAL::SessionID sessionID, const ClientOrigin& origin)
+{
+    LockHolder locker(m_sessionStorageQuotaManagersLock);
+    auto* sessionStorageQuotaManager = m_sessionStorageQuotaManagers.get(sessionID);
+    if (!sessionStorageQuotaManager)
+        return nullptr;
 
-    void whenInitialized(CompletionHandler<void()>&& callback) final
-    {
-        m_callback = WTFMove(callback);
-    }
+    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());    
 
-    WeakPtr<StorageQuotaManager> m_manager;
-    CompletionHandler<void()> m_callback;
-};
+        uint64_t usage = CacheStorage::Engine::diskUsage(cacheRootPath, origin);
+#if ENABLE(INDEXED_DATABASE)
+        usage += IDBServer::IDBServer::diskUsage(idbRootPath, origin);
+#endif
 
-void NetworkProcess::initializeQuotaUsers(StorageQuotaManager& manager, PAL::SessionID sessionID, const ClientOrigin& origin)
-{
-    RunLoop::main().dispatch([this, weakThis = makeWeakPtr(this), sessionID, origin, user = makeUnique<QuotaUserInitializer>(manager)]() mutable {
+        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)
index d41708e..0c63718 100644 (file)
@@ -286,6 +286,7 @@ public:
     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&&)>&&);
@@ -329,7 +330,7 @@ public:
     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&);
@@ -445,6 +446,7 @@ private:
     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)
@@ -464,8 +466,44 @@ private:
     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;
@@ -537,23 +575,8 @@ private:
     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;
index 0a856ed..272a550 100644 (file)
@@ -164,4 +164,6 @@ messages -> NetworkProcess LegacyReceiver {
 
     SetServiceWorkerFetchTimeoutForTesting(Seconds seconds) -> () Synchronous
     ResetServiceWorkerFetchTimeoutForTesting() -> () Synchronous
+
+    ResetQuota(PAL::SessionID sessionID) -> () Async
 }
index efe7e15..3d65947 100644 (file)
@@ -196,13 +196,68 @@ void Engine::clearCachesForOrigin(NetworkProcess& networkProcess, PAL::SessionID
     });
 }
 
-void Engine::initializeQuotaUser(NetworkProcess& networkProcess, PAL::SessionID sessionID, const WebCore::ClientOrigin& clientOrigin, CompletionHandler<void()>&& completionHandler)
+static uint64_t getDirectorySize(const String& directoryPath)
+{
+    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)
 {
-    from(networkProcess, sessionID, [clientOrigin, completionHandler = WTFMove(completionHandler)](auto& engine) mutable {
-        engine.readCachesFromDisk(clientOrigin, [completionHandler = WTFMove(completionHandler)](auto&& cachesOrError) mutable {
-            completionHandler();
-        });
-    });
+    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 @@ void Engine::readCachesFromDisk(const WebCore::ClientOrigin& origin, CachesCallb
 
         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::removeFile(const String& filename)
     });
 }
 
-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 @@ void Engine::writeSizeFile(const String& path, uint64_t size)
 
         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,8 +571,8 @@ Optional<uint64_t> Engine::readSizeFile(const String& path)
     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;
 
index a3aaaf0..22ee66b 100644 (file)
@@ -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 @@ public:
 
     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; }
index 6fc53e0..ba134cf 100644 (file)
@@ -414,8 +414,11 @@ void Cache::put(Vector<Record>&& records, RecordIdentifiersCallback&& callback)
         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 @@ void Cache::remove(WebCore::ResourceRequest&& request, WebCore::CacheQueryOption
         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)
index 03a060c..f237451 100644 (file)
@@ -56,36 +56,21 @@ String Caches::cachesSizeFilename(const String& cachesRootsPath)
     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::initialize(WebCore::DOMCacheEngine::CompletionCallback&& callback)
     });
 }
 
-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 @@ void Caches::initializeSize()
                 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 @@ void Caches::clear(CompletionHandler<void()>&& completionHandler)
         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::readRecordsList(Cache& cache, NetworkCache::Storage::TraverseHandle
 
 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 @@ void Caches::writeRecord(const Cache& cache, const RecordInformation& recordInfo
     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 @@ void Caches::writeRecord(const Cache& cache, const RecordInformation& recordInfo
         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 @@ void Caches::removeRecord(const RecordInformation& record)
 
     ASSERT(m_size >= record.size);
     m_size -= record.size;
-    updateSizeFile();
+    updateSizeFile([] { });
 
     removeCacheEntry(record.key);
 }
@@ -621,17 +608,6 @@ void Caches::removeCacheEntry(const NetworkCache::Key& key)
     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();
index 03231f3..5d394a0 100644 (file)
@@ -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 @@ namespace CacheStorage {
 
 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 @@ public:
 
     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 @@ private:
 
     bool hasActiveCache() const;
 
-    void updateSizeFile();
-
     bool m_isInitialized { false };
     Engine* m_engine { nullptr };
     uint64_t m_updateCounter { 0 };
@@ -122,7 +114,6 @@ private:
     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
index c0fcf9c..6d0c129 100644 (file)
@@ -55,6 +55,8 @@ void WebsiteDataStoreParameters::encode(IPC::Encoder& encoder) const
 
     encoder << localStorageDirectory << localStorageDirectoryExtensionHandle;
 
+    encoder << cacheStorageDirectory << cacheStorageDirectoryExtensionHandle;
+
     encoder << perOriginStorageQuota;
     encoder << perThirdPartyOriginStorageQuota;
 }
@@ -141,6 +143,18 @@ Optional<WebsiteDataStoreParameters> WebsiteDataStoreParameters::decode(IPC::Dec
         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)
index 095f09d..f27df48 100644 (file)
@@ -71,6 +71,9 @@ struct WebsiteDataStoreParameters {
     String localStorageDirectory;
     SandboxExtension::Handle localStorageDirectoryExtensionHandle;
 
+    String cacheStorageDirectory;
+    SandboxExtension::Handle cacheStorageDirectoryExtensionHandle;
+
     uint64_t perOriginStorageQuota { WebCore::StorageQuotaManager::defaultQuota() };
     uint64_t perThirdPartyOriginStorageQuota { WebCore::StorageQuotaManager::defaultThirdPartyQuota() };
 };
index 7eb7577..99a4086 100644 (file)
@@ -686,3 +686,11 @@ void WKWebsiteDataStoreSetCacheModelSynchronouslyForTesting(WKWebsiteDataStoreRe
 {
     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);
+    });
+}
index 95239a3..23fc2e7 100644 (file)
@@ -155,6 +155,9 @@ WK_EXPORT void WKWebsiteDataStoreClearAdClickAttributionsThroughWebsiteDataRemov
 
 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
index ad57991..4c41c93 100644 (file)
@@ -1367,6 +1367,11 @@ void NetworkProcessProxy::updateProcessAssertion()
     m_activityFromWebProcesses = nullptr;
 }
 
+void NetworkProcessProxy::resetQuota(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
+{
+    sendWithAsyncReply(Messages::NetworkProcess::ResetQuota(sessionID), WTFMove(completionHandler));
+}
+
 } // namespace WebKit
 
 #undef MESSAGE_CHECK
index 72ce425..b77ce7d 100644 (file)
@@ -56,6 +56,7 @@ enum class StorageAccessPromptWasShown : bool;
 enum class StorageAccessWasGranted : bool;
 class SecurityOrigin;
 struct SecurityOriginData;
+struct ClientOrigin;
 }
 
 namespace WebKit {
@@ -196,6 +197,8 @@ public:
     void registerSchemeForLegacyCustomProtocol(const String&);
     void unregisterSchemeForLegacyCustomProtocol(const String&);
 
+    void resetQuota(PAL::SessionID, CompletionHandler<void()>&&);
+
 private:
     // AuxiliaryProcessProxy
     void getLaunchOptions(ProcessLauncher::LaunchOptions&) override;
index 5e81649..e8ac67d 100644 (file)
@@ -556,6 +556,12 @@ NetworkProcessProxy& WebProcessPool::ensureNetworkProcess(WebsiteDataStore* with
     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())
index 0ff3ea0..07199ec 100644 (file)
@@ -191,6 +191,10 @@ WebsiteDataStoreParameters WebsiteDataStore::parameters()
     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();
 
index bb98416..ac2f38d 100644 (file)
@@ -2083,6 +2083,12 @@ WebsiteDataStoreParameters WebsiteDataStore::parameters()
         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())
@@ -2169,6 +2175,15 @@ void WebsiteDataStore::getLocalStorageDetails(Function<void(Vector<LocalStorageD
     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()
 {
index 2784fe3..f5ee422 100644 (file)
@@ -291,7 +291,9 @@ public:
     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);
 
index ee0b326..325da6d 100644 (file)
@@ -1,3 +1,19 @@
+2019-11-22  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-11-22  Jonathan Bedard  <jbedard@apple.com>
 
         Unreviewed, rolling out r252791.
index 7319d2f..b3ba9a2 100644 (file)
                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 */; };
                        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 */,
                                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 */,
                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>"; };
                                41973B5C1AF22875006C7B36 /* SharedBuffer.cpp */,
                                A17991891E1CA24100A505ED /* SharedBufferTest.cpp */,
                                A179918A1E1CA24100A505ED /* SharedBufferTest.h */,
-                               93B62053234EA32B00D49B97 /* StorageQuotaManager.cpp */,
                                ECA680CD1E68CC0900731D20 /* StringUtilities.mm */,
                                CE4D5DE51F6743BA0072CFC6 /* StringWithDirection.cpp */,
                                93A258981F92FF15003E510C /* TextCodec.cpp */,
                                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 */,
                                07CD32F72065B72A0064A4BE /* video.html */,
                                1C2B81841C8924A200A5529F /* webfont.html */,
                                468F2F932368DAA700F4B864 /* window-open-then-document-open.html */,
-                               CD8394DE232AF15E00149495 /* media-loading.html */,
                        );
                        name = Resources;
                        sourceTree = "<group>";
                                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 (file)
index ad1c67b..0000000
+++ /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
index 3a07c13..29214bf 100644 (file)
@@ -981,6 +981,8 @@ bool TestController::resetStateToConsistentValues(const TestOptions& options, Re
     clearServiceWorkerRegistrations();
     clearDOMCaches();
 
+    resetQuota();
+
     WKContextSetAllowsAnySSLCertificateForServiceWorkerTesting(platformContext(), true);
 
     WKContextClearCurrentModifierStateForTesting(TestController::singleton().context());
@@ -3142,6 +3144,13 @@ void TestController::syncLocalStorage()
     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)
index 1b261bc..ad71c86 100644 (file)
@@ -269,6 +269,8 @@ public:
     void terminateNetworkProcess();
     void terminateServiceWorkerProcess();
 
+    void resetQuota();
+
     void removeAllSessionCredentials();
 
     void clearIndexedDatabases();