Changeset 242911 in webkit
- Timestamp:
- Mar 13, 2019 2:47:13 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 27 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r242900 r242911 1 2019-03-13 Youenn Fablet <youenn@apple.com> 2 3 Check IDB quota usage through QuotaManager 4 https://bugs.webkit.org/show_bug.cgi?id=195302 5 6 Reviewed by Chris Dumez. 7 8 Update IDB quota test according quota limit of 400ko. 9 Update WK1 test expectations to skip quota check tests. 10 11 * http/tests/IndexedDB/resources/shared.js: Added. 12 * http/tests/IndexedDB/resources/storage-limit.js: Added. 13 * http/tests/IndexedDB/storage-limit.https-expected.txt: Added. 14 * http/tests/IndexedDB/storage-limit.https.html: Added. 15 * platform/mac-wk1/TestExpectations: 16 * platform/win/TestExpectations: 17 * storage/indexeddb/resources/storage-limit.js: 18 * storage/indexeddb/storage-limit-expected.txt: 19 1 20 2019-03-13 Truitt Savell <tsavell@apple.com> 2 21 -
trunk/LayoutTests/http/tests/IndexedDB/resources/storage-limit.js
r242910 r242911 1 if (this.importScripts) { 2 importScripts('../../../resources/js-test.js'); 3 importScripts('shared.js'); 4 } 1 if (window.testRunner) 2 testRunner.setAllowStorageQuotaIncrease(false); 5 3 6 var quota = 1024 * 1024; // 1 MB7 4 description("This test makes sure that storage of indexedDB does not grow unboundedly."); 8 5 9 if (window.testRunner) 10 testRunner.setIDBPerOriginQuota(quota); 11 12 indexedDBTest(prepareDatabase, onOpenSuccess); 6 window.caches.open("test").then(cache => { 7 return cache.put(new Request("/test"), new Response(new Uint8Array(204800))); 8 }).then(() => { 9 indexedDBTest(prepareDatabase, onOpenSuccess, {'suffix': '-1'}); 10 }).catch(e => { 11 testFailed("Cache API store operation failed: " + e); 12 finishJSTest(); 13 }); 13 14 14 15 function prepareDatabase(event) 15 16 { 16 preamble(event);17 17 evalAndLog("db = event.target.result"); 18 18 evalAndLog("store = db.createObjectStore('store')"); 19 19 } 20 20 21 function onOpenSuccess(event) 21 // Quota for test is 400ko, but IDB is eating some of it when initializing files. 22 // Let's make sure that 200ko is fine but 200ko after 200ko is not fine. 23 async function onOpenSuccess(event) 22 24 { 23 preamble(event);24 25 evalAndLog("db = event.target.result"); 25 26 evalAndLog("store = db.transaction('store', 'readwrite').objectStore('store')"); 26 evalAndLog("request = store.add(new Uint8Array( " + (quota + 1) + "), 0)");27 evalAndLog("request = store.add(new Uint8Array(204800), 'key')"); 27 28 request.onerror = function(event) { 28 29 shouldBeTrue("'error' in request"); -
trunk/LayoutTests/http/tests/IndexedDB/storage-limit.https-expected.txt
r242910 r242911 8 8 indexedDB.deleteDatabase(dbname) 9 9 indexedDB.open(dbname) 10 11 prepareDatabase():12 10 db = event.target.result 13 11 store = db.createObjectStore('store') 14 15 onOpenSuccess():16 12 db = event.target.result 17 13 store = db.transaction('store', 'readwrite').objectStore('store') 18 request = store.add(new Uint8Array( 1048577), 0)14 request = store.add(new Uint8Array(204800), 'key') 19 15 PASS 'error' in request is true 20 16 PASS request.error.code is DOMException.QUOTA_EXCEEDED_ERR -
trunk/LayoutTests/platform/mac-wk1/TestExpectations
r242809 r242911 162 162 imported/w3c/web-platform-tests/fetch/api/request/destination [ Skip ] 163 163 imported/w3c/web-platform-tests/fetch/cross-origin-resource-policy [ Skip ] 164 165 # Quota check missing in WK1 166 http/tests/IndexedDB/storage-limit.https.html [ Skip ] 167 storage/indexeddb/storage-limit.html [ Skip ] 164 168 165 169 # Skip WebRTC for now in WK1 -
trunk/LayoutTests/platform/win/TestExpectations
r242642 r242911 2373 2373 http/tests/xmlhttprequest/web-apps/012.html 2374 2374 http/tests/xmlhttprequest/web-apps/013.html 2375 2376 storage/indexeddb/storage-limit.html [ Skip ] 2377 http/tests/IndexedDB/storage-limit.https.html [ Skip ] 2375 2378 2376 2379 # Assertion failures: Not investigated -
trunk/LayoutTests/storage/indexeddb/resources/storage-limit.js
r237700 r242911 4 4 } 5 5 6 var quota = 1024 * 1024; // 1 MB 6 if (window.testRunner) 7 testRunner.setAllowStorageQuotaIncrease(false); 8 9 var quota = 400 * 1024; // default quota for testing. 7 10 description("This test makes sure that storage of indexedDB does not grow unboundedly."); 8 9 if (window.testRunner)10 testRunner.setIDBPerOriginQuota(quota);11 11 12 12 indexedDBTest(prepareDatabase, onOpenSuccess); -
trunk/LayoutTests/storage/indexeddb/storage-limit-expected.txt
r237700 r242911 16 16 db = event.target.result 17 17 store = db.transaction('store', 'readwrite').objectStore('store') 18 request = store.add(new Uint8Array( 1048577), 0)18 request = store.add(new Uint8Array(409601), 0) 19 19 PASS 'error' in request is true 20 20 PASS request.error.code is DOMException.QUOTA_EXCEEDED_ERR -
trunk/Source/WebCore/ChangeLog
r242909 r242911 1 2019-03-13 Youenn Fablet <youenn@apple.com> 2 3 Check IDB quota usage through QuotaManager 4 https://bugs.webkit.org/show_bug.cgi?id=195302 5 6 Reviewed by Chris Dumez. 7 8 For every write operation, compute an estimate size and check for quota before proceeding. 9 When proceeding, store the estimate size in a map. 10 If size of the database is to be computed when the task is not done, 11 the estimate size will be added to the current size of the databases. 12 At the end of the task, the estimate size is removed from the map, 13 and the databases size is refreshed. 14 15 This patch implements size estimation for write tasks. 16 Put/add operations might overestimate the size 17 when an old value will be replaced by a new value. 18 In that case, we do not substract the old value size since we do not know it. 19 20 This patch implements database opening by adding a fixed small cost, 21 as we do not know whether the database is new or not. 22 23 For the first IDB request, we have not computed the size of the database. 24 To do so, we need to go to a background thread and do that file size computation. 25 For that purpose, we add support for being-initialized quota user. 26 Quota manager is calling whenInitialized on its quota user and will 27 delay any quota check requests until its quota user is answering this callback. 28 29 For in process IDB, use the default storage quota per origin and do not increase it. 30 Future work should move it to NetworkProcess and implement some quota checking. 31 32 Cache API and IDB quota management are not yet fully unified. 33 If IDB is used on start-up, we should check for Cache API storage size. 34 Conversely, on Cache API first wite task, even if IDB is not being used, 35 we should compute the size of the IDB data for the given origin. 36 37 Test: http/tests/IndexedDB/storage-limit.https.html 38 39 * Modules/indexeddb/server/IDBBackingStore.h: 40 * Modules/indexeddb/server/IDBServer.cpp: 41 (WebCore::IDBServer::IDBServer::create): 42 (WebCore::IDBServer::IDBServer::IDBServer): 43 (WebCore::IDBServer::m_quotaManagerGetter): 44 (WebCore::IDBServer::IDBServer::QuotaUser::QuotaUser): 45 (WebCore::IDBServer::IDBServer::QuotaUser::~QuotaUser): 46 (WebCore::IDBServer::IDBServer::QuotaUser::clearSpaceUsed): 47 (WebCore::IDBServer::IDBServer::QuotaUser::whenInitialized): 48 (WebCore::IDBServer::IDBServer::QuotaUser::initializeSpaceUsed): 49 (WebCore::IDBServer::IDBServer::quotaUser): 50 (WebCore::IDBServer::IDBServer::startComputingSpaceUsedForOrigin): 51 (WebCore::IDBServer::IDBServer::computeSpaceUsedForOrigin): 52 (WebCore::IDBServer::IDBServer::finishComputingSpaceUsedForOrigin): 53 (WebCore::IDBServer::IDBServer::requestSpace): 54 (WebCore::IDBServer::IDBServer::clearSpaceUsed): 55 (WebCore::IDBServer::IDBServer::setSpaceUsed): 56 (WebCore::IDBServer::IDBServer::increasePotentialSpaceUsed): 57 (WebCore::IDBServer::IDBServer::decreasePotentialSpaceUsed): 58 * Modules/indexeddb/server/IDBServer.h: 59 (WebCore::IDBServer::IDBServer::create): 60 * Modules/indexeddb/server/MemoryIDBBackingStore.cpp: 61 (WebCore::IDBServer::MemoryIDBBackingStore::databasesSizeForOrigin const): 62 * Modules/indexeddb/server/MemoryIDBBackingStore.h: 63 * Modules/indexeddb/server/SQLiteIDBBackingStore.cpp: 64 (WebCore::IDBServer::SQLiteIDBBackingStore::databasesSizeForFolder): 65 (WebCore::IDBServer::SQLiteIDBBackingStore::databasesSizeForOrigin const): 66 (WebCore::IDBServer::SQLiteIDBBackingStore::maximumSize const): 67 * Modules/indexeddb/server/SQLiteIDBBackingStore.h: 68 * Modules/indexeddb/server/UniqueIDBDatabase.cpp: 69 (WebCore::IDBServer::estimateSize): 70 (WebCore::IDBServer::UniqueIDBDatabase::UniqueIDBDatabase): 71 (WebCore::IDBServer::quotaErrorMessageName): 72 (WebCore::IDBServer::UniqueIDBDatabase::requestSpace): 73 (WebCore::IDBServer::UniqueIDBDatabase::performCurrentOpenOperation): 74 (WebCore::IDBServer::UniqueIDBDatabase::storeCallbackOrFireError): 75 (WebCore::IDBServer::UniqueIDBDatabase::createObjectStore): 76 (WebCore::IDBServer::UniqueIDBDatabase::createObjectStoreAfterQuotaCheck): 77 (WebCore::IDBServer::UniqueIDBDatabase::renameObjectStore): 78 (WebCore::IDBServer::UniqueIDBDatabase::renameObjectStoreAfterQuotaCheck): 79 (WebCore::IDBServer::UniqueIDBDatabase::createIndex): 80 (WebCore::IDBServer::UniqueIDBDatabase::createIndexAfterQuotaCheck): 81 (WebCore::IDBServer::UniqueIDBDatabase::renameIndex): 82 (WebCore::IDBServer::UniqueIDBDatabase::renameIndexAfterQuotaCheck): 83 (WebCore::IDBServer::UniqueIDBDatabase::putOrAdd): 84 (WebCore::IDBServer::UniqueIDBDatabase::putOrAddAfterQuotaCheck): 85 (WebCore::IDBServer::UniqueIDBDatabase::postDatabaseTaskReply): 86 (WebCore::IDBServer::UniqueIDBDatabase::immediateCloseForUserDelete): 87 (WebCore::IDBServer::UniqueIDBDatabase::updateSpaceUsedIfNeeded): 88 (WebCore::IDBServer::UniqueIDBDatabase::performErrorCallback): 89 (WebCore::IDBServer::UniqueIDBDatabase::performKeyDataCallback): 90 * Modules/indexeddb/server/UniqueIDBDatabase.h: 91 (WebCore::IDBServer::UniqueIDBDatabase::server): 92 * Modules/indexeddb/shared/InProcessIDBServer.cpp: 93 (WebCore::InProcessIDBServer::create): 94 (WebCore::InProcessIDBServer::quotaManager): 95 (WebCore::storageQuotaManagerGetter): 96 (WebCore::InProcessIDBServer::InProcessIDBServer): 97 * Modules/indexeddb/shared/InProcessIDBServer.h: 98 * loader/EmptyClients.cpp: 99 * storage/StorageQuotaManager.cpp: 100 (WebCore::StorageQuotaManager::addUser): 101 (WebCore::StorageQuotaManager::requestSpace): 102 * storage/StorageQuotaManager.h: 103 (WebCore::StorageQuotaManager::defaultQuota): 104 (WebCore::StorageQuotaManager::removeUser): 105 * storage/StorageQuotaUser.h: 106 (WebCore::StorageQuotaUser::whenInitialized): 107 1 108 2019-03-13 Chris Dumez <cdumez@apple.com> 2 109 -
trunk/Source/WebCore/Modules/indexeddb/server/IDBBackingStore.h
r238283 r242911 100 100 virtual bool isEphemeral() = 0; 101 101 102 virtual uint64_t databasesSizeForOrigin() const = 0; 102 103 virtual void setQuota(uint64_t) = 0; 103 104 protected: -
trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp
r242136 r242911 36 36 #include "SQLiteIDBBackingStore.h" 37 37 #include "SecurityOrigin.h" 38 #include "StorageQuotaManager.h" 38 39 #include <wtf/CrossThreadCopier.h> 39 40 #include <wtf/Locker.h> … … 43 44 namespace IDBServer { 44 45 45 Ref<IDBServer> IDBServer::create( IDBBackingStoreTemporaryFileHandler& fileHandler, WTF::Function<void(bool)>&& isClosingDatabaseCallback)46 { 47 return adoptRef(*new IDBServer( fileHandler, WTFMove(isClosingDatabaseCallback)));48 } 49 50 Ref<IDBServer> IDBServer::create( const String& databaseDirectoryPath, IDBBackingStoreTemporaryFileHandler& fileHandler, WTF::Function<void(bool)>&& isClosingDatabaseCallback)51 { 52 return adoptRef(*new IDBServer( databaseDirectoryPath, fileHandler, WTFMove(isClosingDatabaseCallback)));53 } 54 55 IDBServer::IDBServer( IDBBackingStoreTemporaryFileHandler& fileHandler, WTF::Function<void(bool)>&& isClosingDatabaseCallback)46 Ref<IDBServer> IDBServer::create(PAL::SessionID sessionID, IDBBackingStoreTemporaryFileHandler& fileHandler, QuotaManagerGetter&& quotaManagerGetter, WTF::Function<void(bool)>&& isClosingDatabaseCallback) 47 { 48 return adoptRef(*new IDBServer(sessionID, fileHandler, WTFMove(quotaManagerGetter), WTFMove(isClosingDatabaseCallback))); 49 } 50 51 Ref<IDBServer> IDBServer::create(PAL::SessionID sessionID, const String& databaseDirectoryPath, IDBBackingStoreTemporaryFileHandler& fileHandler, QuotaManagerGetter&& quotaManagerGetter, WTF::Function<void(bool)>&& isClosingDatabaseCallback) 52 { 53 return adoptRef(*new IDBServer(sessionID, databaseDirectoryPath, fileHandler, WTFMove(quotaManagerGetter), WTFMove(isClosingDatabaseCallback))); 54 } 55 56 IDBServer::IDBServer(PAL::SessionID sessionID, IDBBackingStoreTemporaryFileHandler& fileHandler, QuotaManagerGetter&& quotaManagerGetter, WTF::Function<void(bool)>&& isClosingDatabaseCallback) 56 57 : CrossThreadTaskHandler("IndexedDatabase Server") 58 , m_sessionID(sessionID) 57 59 , m_backingStoreTemporaryFileHandler(fileHandler) 58 60 , m_isClosingDatabaseCallback(WTFMove(isClosingDatabaseCallback)) 59 61 , m_isClosingDatabaseHysteresis([&](PAL::HysteresisState state) { m_isClosingDatabaseCallback(state == PAL::HysteresisState::Started); }) 60 { 61 } 62 63 IDBServer::IDBServer(const String& databaseDirectoryPath, IDBBackingStoreTemporaryFileHandler& fileHandler, WTF::Function<void(bool)>&& isClosingDatabaseCallback) 62 , m_quotaManagerGetter(WTFMove(quotaManagerGetter)) 63 { 64 } 65 66 IDBServer::IDBServer(PAL::SessionID sessionID, const String& databaseDirectoryPath, IDBBackingStoreTemporaryFileHandler& fileHandler, QuotaManagerGetter&& quotaManagerGetter, WTF::Function<void(bool)>&& isClosingDatabaseCallback) 64 67 : CrossThreadTaskHandler("IndexedDatabase Server") 68 , m_sessionID(sessionID) 65 69 , m_databaseDirectoryPath(databaseDirectoryPath) 66 70 , m_backingStoreTemporaryFileHandler(fileHandler) 67 71 , m_isClosingDatabaseCallback(WTFMove(isClosingDatabaseCallback)) 68 72 , m_isClosingDatabaseHysteresis([&](PAL::HysteresisState state) { m_isClosingDatabaseCallback(state == PAL::HysteresisState::Started); }) 73 , m_quotaManagerGetter(WTFMove(quotaManagerGetter)) 69 74 { 70 75 LOG(IndexedDB, "IDBServer created at path %s", databaseDirectoryPath.utf8().data()); … … 680 685 } 681 686 687 IDBServer::QuotaUser::QuotaUser(IDBServer& server, StorageQuotaManager* manager, ClientOrigin&& origin) 688 : m_server(server) 689 , m_manager(makeWeakPtr(manager)) 690 , m_origin(WTFMove(origin)) 691 , m_isInitialized(m_server.m_sessionID.isEphemeral()) 692 { 693 if (manager) 694 manager->addUser(*this); 695 } 696 697 IDBServer::QuotaUser::~QuotaUser() 698 { 699 if (m_manager) 700 m_manager->removeUser(*this); 701 } 702 703 void IDBServer::QuotaUser::resetSpaceUsed() 704 { 705 m_spaceUsed = 0; 706 m_estimatedSpaceIncrease = 0; 707 708 if (!m_manager) 709 return; 710 711 if (m_server.m_sessionID.isEphemeral()) 712 return; 713 714 if (!m_isInitialized) 715 return; 716 717 ASSERT(!m_initializationCallback); 718 719 m_isInitialized = false; 720 721 // Do add/remove to trigger call to whenInitialized. 722 m_manager->removeUser(*this); 723 m_manager->addUser(*this); 724 } 725 726 void IDBServer::QuotaUser::whenInitialized(CompletionHandler<void()>&& callback) 727 { 728 if (m_isInitialized) { 729 callback(); 730 return; 731 } 732 m_initializationCallback = WTFMove(callback); 733 m_server.startComputingSpaceUsedForOrigin(m_origin); 734 } 735 736 void IDBServer::QuotaUser::initializeSpaceUsed(uint64_t spaceUsed) 737 { 738 ASSERT(m_isInitialized || !m_estimatedSpaceIncrease); 739 m_spaceUsed = spaceUsed; 740 m_isInitialized = true; 741 742 if (auto callback = WTFMove(m_initializationCallback)) 743 callback(); 744 } 745 746 IDBServer::QuotaUser& IDBServer::quotaUser(const ClientOrigin& origin) 747 { 748 return *m_quotaUsers.ensure(origin, [this, &origin] { 749 return std::make_unique<QuotaUser>(*this, m_quotaManagerGetter(m_sessionID, origin), ClientOrigin { origin }); 750 }).iterator->value; 751 } 752 753 void IDBServer::startComputingSpaceUsedForOrigin(const ClientOrigin& origin) 754 { 755 ASSERT(!m_sessionID.isEphemeral()); 756 postDatabaseTask(createCrossThreadTask(*this, &IDBServer::computeSpaceUsedForOrigin, origin)); 757 } 758 759 void IDBServer::computeSpaceUsedForOrigin(const ClientOrigin& origin) 760 { 761 ASSERT(!isMainThread()); 762 763 auto path = IDBDatabaseIdentifier::databaseDirectoryRelativeToRoot(origin.topOrigin, origin.clientOrigin, m_databaseDirectoryPath); 764 auto size = SQLiteIDBBackingStore::databasesSizeForFolder(path); 765 766 postDatabaseTaskReply(createCrossThreadTask(*this, &IDBServer::finishComputingSpaceUsedForOrigin, origin, size)); 767 } 768 769 void IDBServer::finishComputingSpaceUsedForOrigin(const ClientOrigin& origin, uint64_t spaceUsed) 770 { 771 quotaUser(origin).initializeSpaceUsed(spaceUsed); 772 } 773 774 void IDBServer::requestSpace(const ClientOrigin& origin, uint64_t taskSize, CompletionHandler<void(StorageQuotaManager::Decision)>&& callback) 775 { 776 auto* quotaManager = quotaUser(origin).manager(); 777 if (!quotaManager) { 778 callback(StorageQuotaManager::Decision::Deny); 779 return; 780 } 781 782 quotaManager->requestSpace(taskSize, WTFMove(callback)); 783 } 784 785 void IDBServer::resetSpaceUsed(const ClientOrigin& origin) 786 { 787 if (auto* user = m_quotaUsers.get(origin)) 788 user->resetSpaceUsed(); 789 } 790 791 void IDBServer::setSpaceUsed(const ClientOrigin& origin, uint64_t taskSize) 792 { 793 quotaUser(origin).setSpaceUsed(taskSize); 794 } 795 796 void IDBServer::increasePotentialSpaceUsed(const ClientOrigin& origin, uint64_t taskSize) 797 { 798 quotaUser(origin).increasePotentialSpaceUsed(taskSize); 799 } 800 801 void IDBServer::decreasePotentialSpaceUsed(const ClientOrigin& origin, uint64_t spaceUsed) 802 { 803 quotaUser(origin).decreasePotentialSpaceUsed(spaceUsed); 804 } 805 682 806 } // namespace IDBServer 683 807 } // namespace WebCore -
trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.h
r242136 r242911 30 30 #include "IDBConnectionToClient.h" 31 31 #include "IDBDatabaseIdentifier.h" 32 #include "StorageQuotaManager.h" 33 #include "StorageQuotaUser.h" 32 34 #include "UniqueIDBDatabase.h" 33 35 #include "UniqueIDBDatabaseConnection.h" 34 36 #include <pal/HysteresisActivity.h> 37 #include <pal/SessionID.h> 35 38 #include <wtf/CrossThreadTaskHandler.h> 36 39 #include <wtf/HashMap.h> … … 45 48 class IDBRequestData; 46 49 class IDBValue; 50 class StorageQuotaManager; 47 51 48 52 struct IDBGetRecordData; … … 56 60 class IDBServer : public RefCounted<IDBServer>, public CrossThreadTaskHandler { 57 61 public: 58 static Ref<IDBServer> create(IDBBackingStoreTemporaryFileHandler&, WTF::Function<void(bool)>&& isClosingDatabaseCallback = [](bool) { }); 59 WEBCORE_EXPORT static Ref<IDBServer> create(const String& databaseDirectoryPath, IDBBackingStoreTemporaryFileHandler&, WTF::Function<void(bool)>&& isClosingDatabaseCallback = [](bool) { }); 62 using QuotaManagerGetter = WTF::Function<StorageQuotaManager*(PAL::SessionID, const ClientOrigin&)>; 63 static Ref<IDBServer> create(PAL::SessionID, IDBBackingStoreTemporaryFileHandler&, QuotaManagerGetter&&, WTF::Function<void(bool)>&& isClosingDatabaseCallback = [](bool) { }); 64 WEBCORE_EXPORT static Ref<IDBServer> create(PAL::SessionID, const String& databaseDirectoryPath, IDBBackingStoreTemporaryFileHandler&, QuotaManagerGetter&&, WTF::Function<void(bool)>&& isClosingDatabaseCallback = [](bool) { }); 60 65 61 66 WEBCORE_EXPORT void registerConnection(IDBConnectionToClient&); … … 115 120 void hysteresisUpdated(PAL::HysteresisState); 116 121 122 void requestSpace(const ClientOrigin&, uint64_t taskSize, CompletionHandler<void(StorageQuotaManager::Decision)>&&); 123 void increasePotentialSpaceUsed(const ClientOrigin&, uint64_t taskSize); 124 void decreasePotentialSpaceUsed(const ClientOrigin&, uint64_t taskSize); 125 void setSpaceUsed(const ClientOrigin&, uint64_t spaceUsed); 126 void resetSpaceUsed(const ClientOrigin&); 127 117 128 private: 118 IDBServer( IDBBackingStoreTemporaryFileHandler&, WTF::Function<void(bool)>&&);119 IDBServer( const String& databaseDirectoryPath, IDBBackingStoreTemporaryFileHandler&, WTF::Function<void(bool)>&&);129 IDBServer(PAL::SessionID, IDBBackingStoreTemporaryFileHandler&, QuotaManagerGetter&&, WTF::Function<void(bool)>&&); 130 IDBServer(PAL::SessionID, const String& databaseDirectoryPath, IDBBackingStoreTemporaryFileHandler&, QuotaManagerGetter&&, WTF::Function<void(bool)>&&); 120 131 121 132 UniqueIDBDatabase& getOrCreateUniqueIDBDatabase(const IDBDatabaseIdentifier&); … … 128 139 void didPerformCloseAndDeleteDatabases(uint64_t callbackID); 129 140 141 class QuotaUser final : public StorageQuotaUser { 142 WTF_MAKE_FAST_ALLOCATED; 143 public: 144 QuotaUser(IDBServer&, StorageQuotaManager*, ClientOrigin&&); 145 ~QuotaUser(); 146 147 StorageQuotaManager* manager() { return m_manager.get(); } 148 149 void setSpaceUsed(uint64_t spaceUsed) { m_spaceUsed = spaceUsed; } 150 void resetSpaceUsed(); 151 152 void increasePotentialSpaceUsed(uint64_t increase) { m_estimatedSpaceIncrease += increase; } 153 void decreasePotentialSpaceUsed(uint64_t decrease) 154 { 155 ASSERT(m_estimatedSpaceIncrease >= decrease); 156 m_estimatedSpaceIncrease -= decrease; 157 } 158 159 void initializeSpaceUsed(uint64_t spaceUsed); 160 161 private: 162 uint64_t spaceUsed() const final { return m_spaceUsed + m_estimatedSpaceIncrease; } 163 void whenInitialized(CompletionHandler<void()>&&) final; 164 165 IDBServer& m_server; 166 WeakPtr<StorageQuotaManager> m_manager; 167 ClientOrigin m_origin; 168 bool m_isInitialized { false }; 169 uint64_t m_spaceUsed { 0 }; 170 uint64_t m_estimatedSpaceIncrease { 0 }; 171 CompletionHandler<void()> m_initializationCallback; 172 }; 173 174 QuotaUser& quotaUser(const ClientOrigin&); 175 void startComputingSpaceUsedForOrigin(const ClientOrigin&); 176 void computeSpaceUsedForOrigin(const ClientOrigin&); 177 void finishComputingSpaceUsedForOrigin(const ClientOrigin&, uint64_t spaceUsed); 178 179 PAL::SessionID m_sessionID; 130 180 HashMap<uint64_t, RefPtr<IDBConnectionToClient>> m_connectionMap; 131 181 HashMap<IDBDatabaseIdentifier, std::unique_ptr<UniqueIDBDatabase>> m_uniqueIDBDatabaseMap; … … 144 194 WTF::Function<void(bool)> m_isClosingDatabaseCallback; 145 195 PAL::HysteresisActivity m_isClosingDatabaseHysteresis; 196 197 HashMap<ClientOrigin, std::unique_ptr<QuotaUser>> m_quotaUsers; 198 QuotaManagerGetter m_quotaManagerGetter; 146 199 }; 147 200 -
trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp
r238130 r242911 593 593 } 594 594 595 uint64_t MemoryIDBBackingStore::databasesSizeForOrigin() const 596 { 597 // FIXME: Implement this. 598 return 0; 599 } 600 595 601 } // namespace IDBServer 596 602 } // namespace WebCore -
trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.h
r241183 r242911 81 81 82 82 void setQuota(uint64_t quota) final { UNUSED_PARAM(quota); }; 83 uint64_t databasesSizeForOrigin() const final; 83 84 84 85 void removeObjectStoreForVersionChangeAbort(MemoryObjectStore&); -
trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp
r240557 r242911 851 851 } 852 852 853 uint64_t SQLiteIDBBackingStore::databasesSizeForFolder(const String& folder) 854 { 855 uint64_t diskUsage = 0; 856 for (auto& directory : FileSystem::listDirectory(folder, "*")) { 857 for (auto& file : FileSystem::listDirectory(directory, "*.sqlite3"_s)) 858 diskUsage += SQLiteFileSystem::getDatabaseFileSize(file); 859 } 860 return diskUsage; 861 } 862 863 uint64_t SQLiteIDBBackingStore::databasesSizeForOrigin() const 864 { 865 return databasesSizeForFolder(m_absoluteDatabaseDirectory); 866 } 867 853 868 uint64_t SQLiteIDBBackingStore::maximumSize() const 854 869 { … … 860 875 uint64_t quota = quotaForOrigin(); 861 876 862 uint64_t diskUsage = 0; 863 for (auto& directory : FileSystem::listDirectory(m_absoluteDatabaseDirectory, "*")) { 864 for (auto& file : FileSystem::listDirectory(directory, "*.sqlite3"_s)) 865 diskUsage += SQLiteFileSystem::getDatabaseFileSize(file); 866 } 877 uint64_t diskUsage = databasesSizeForOrigin(); 867 878 ASSERT(diskUsage >= databaseFileSize); 868 879 -
trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.h
r241183 r242911 83 83 84 84 void setQuota(uint64_t quota) final { m_quota = quota; } 85 uint64_t databasesSizeForOrigin() const final; 85 86 86 87 bool supportsSimultaneousTransactions() final { return false; } … … 96 97 97 98 static String databaseNameFromEncodedFilename(const String&); 99 static uint64_t databasesSizeForFolder(const String& folder); 98 100 99 101 private: -
trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp
r242555 r242911 42 42 #include "Logging.h" 43 43 #include "SerializedScriptValue.h" 44 #include "StorageQuotaManager.h" 44 45 #include "UniqueIDBDatabaseConnection.h" 45 46 #include <JavaScriptCore/AuxiliaryBarrierInlines.h> … … 55 56 namespace IDBServer { 56 57 58 static const uint64_t defaultWriteOperationCost = 4; 59 60 static inline uint64_t estimateSize(const IDBKeyData& keyData) 61 { 62 uint64_t size = 4; 63 switch (keyData.type()) { 64 case IndexedDB::KeyType::String: 65 size += keyData.string().sizeInBytes(); 66 break; 67 case IndexedDB::KeyType::Binary: { 68 size += keyData.binary().size(); 69 break; 70 } 71 case IndexedDB::KeyType::Array: 72 for (auto& data : keyData.array()) 73 size += estimateSize(data); 74 break; 75 default: 76 break; 77 } 78 return size; 79 } 80 81 static inline uint64_t estimateSize(const IDBValue& value) 82 { 83 uint64_t size = 4; 84 size += value.data().size(); 85 for (auto& url : value.blobURLs()) 86 size += url.sizeInBytes(); 87 for (auto& path : value.blobFilePaths()) 88 size += path.sizeInBytes(); 89 return size; 90 } 91 92 static inline uint64_t estimateSize(const IDBIndexInfo& info) 93 { 94 uint64_t size = 4; 95 size += info.name().sizeInBytes(); 96 return size; 97 } 98 99 static inline uint64_t estimateSize(const IDBObjectStoreInfo& info) 100 { 101 uint64_t size = 4; 102 size += info.name().sizeInBytes(); 103 // FIXME: estimate keyPath. 104 for (auto& indexInfo : info.indexMap().values()) 105 size += estimateSize(indexInfo); 106 return size; 107 } 108 57 109 UniqueIDBDatabase::UniqueIDBDatabase(IDBServer& server, const IDBDatabaseIdentifier& identifier) 58 : m_server( &server)110 : m_server(server) 59 111 , m_identifier(identifier) 60 112 , m_operationAndTransactionTimer(*this, &UniqueIDBDatabase::operationAndTransactionTimerFired) … … 119 171 } 120 172 173 static inline String quotaErrorMessageName(const char* taskName) 174 { 175 return makeString("Failed to ", taskName, " in database because not enough space for domain"); 176 } 177 178 void UniqueIDBDatabase::requestSpace(uint64_t taskSize, const char* taskName, CompletionHandler<void(Optional<IDBError>&&)>&& callback) 179 { 180 m_server->requestSpace(m_identifier.origin(), taskSize, [weakThis = makeWeakPtr(this), taskName, callback = WTFMove(callback)](auto decision) mutable { 181 if (!weakThis) { 182 callback(IDBError { UnknownError }); 183 return; 184 } 185 switch (decision) { 186 case StorageQuotaManager::Decision::Deny: 187 callback(IDBError { QuotaExceededError, quotaErrorMessageName(taskName) }); 188 return; 189 case StorageQuotaManager::Decision::Grant: 190 callback({ }); 191 }; 192 }); 193 } 194 121 195 void UniqueIDBDatabase::performCurrentOpenOperation() 122 196 { … … 129 203 if (!m_isOpeningBackingStore) { 130 204 m_isOpeningBackingStore = true; 131 postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::openBackingStore, m_identifier)); 132 } 133 205 // We do not know whether this is an existing or a new database. 206 // We set a small cost so that it is not possible to open an infinite number of database. 207 m_server->requestSpace(m_identifier.origin(), defaultWriteOperationCost, [this, weakThis = makeWeakPtr(this)](auto decision) mutable { 208 if (!weakThis) 209 return; 210 211 switch (decision) { 212 case StorageQuotaManager::Decision::Deny: { 213 auto result = IDBResultData::error(m_currentOpenDBRequest->requestData().requestIdentifier(), IDBError { QuotaExceededError, quotaErrorMessageName("openDatabase") }); 214 m_currentOpenDBRequest->connection().didOpenDatabase(result); 215 m_currentOpenDBRequest = nullptr; 216 break; 217 } 218 case StorageQuotaManager::Decision::Grant: 219 this->postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::openBackingStore, m_identifier)); 220 }; 221 }); 222 } 134 223 return; 135 224 } … … 428 517 } 429 518 430 uint64_t UniqueIDBDatabase::storeCallbackOrFireError(ErrorCallback&& callback )519 uint64_t UniqueIDBDatabase::storeCallbackOrFireError(ErrorCallback&& callback, uint64_t taskSize) 431 520 { 432 521 if (m_hardClosedForUserDelete) { … … 438 527 ASSERT(!m_errorCallbacks.contains(identifier)); 439 528 m_errorCallbacks.add(identifier, WTFMove(callback)); 529 530 if (taskSize) { 531 m_server->increasePotentialSpaceUsed(m_identifier.origin(), taskSize); 532 m_pendingSpaceIncreasingTasks.add(identifier, taskSize); 533 } 534 440 535 m_callbackQueue.append(identifier); 441 536 return identifier; 442 537 } 443 538 444 uint64_t UniqueIDBDatabase::storeCallbackOrFireError(KeyDataCallback&& callback )539 uint64_t UniqueIDBDatabase::storeCallbackOrFireError(KeyDataCallback&& callback, uint64_t taskSize) 445 540 { 446 541 if (m_hardClosedForUserDelete) { … … 452 547 ASSERT(!m_keyDataCallbacks.contains(identifier)); 453 548 m_keyDataCallbacks.add(identifier, WTFMove(callback)); 549 550 if (taskSize) { 551 m_server->increasePotentialSpaceUsed(m_identifier.origin(), taskSize); 552 m_pendingSpaceIncreasingTasks.add(identifier, taskSize); 553 } 554 454 555 m_callbackQueue.append(identifier); 455 556 return identifier; … … 669 770 LOG(IndexedDB, "(main) UniqueIDBDatabase::createObjectStore"); 670 771 671 uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback)); 772 auto taskSize = defaultWriteOperationCost + estimateSize(info); 773 requestSpace(taskSize, "createObjectStore", [this, taskSize, transaction = makeRef(transaction), info, callback = WTFMove(callback)](auto error) mutable { 774 if (error) { 775 callback(WTFMove(error.value())); 776 return; 777 } 778 this->createObjectStoreAfterQuotaCheck(taskSize, transaction.get(), info, WTFMove(callback)); 779 }); 780 } 781 782 void UniqueIDBDatabase::createObjectStoreAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction& transaction, const IDBObjectStoreInfo& info, ErrorCallback callback) 783 { 784 uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback), taskSize); 672 785 if (!callbackID) 673 786 return; … … 745 858 LOG(IndexedDB, "(main) UniqueIDBDatabase::renameObjectStore"); 746 859 747 uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback)); 860 auto taskSize = defaultWriteOperationCost + newName.sizeInBytes(); 861 requestSpace(taskSize, "renameObjectStore", [this, taskSize, transaction = makeRef(transaction), objectStoreIdentifier, newName, callback = WTFMove(callback)](auto error) mutable { 862 if (error) { 863 callback(WTFMove(error.value())); 864 return; 865 } 866 this->renameObjectStoreAfterQuotaCheck(taskSize, transaction.get(), objectStoreIdentifier, newName, WTFMove(callback)); 867 }); 868 } 869 870 void UniqueIDBDatabase::renameObjectStoreAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, const String& newName, ErrorCallback callback) 871 { 872 uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback), taskSize); 748 873 if (!callbackID) 749 874 return; … … 817 942 LOG(IndexedDB, "(main) UniqueIDBDatabase::createIndex"); 818 943 819 uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback)); 944 auto taskSize = defaultWriteOperationCost + estimateSize(info); 945 requestSpace(taskSize, "createIndex", [this, taskSize, transaction = makeRef(transaction), info, callback = WTFMove(callback)](auto error) mutable { 946 if (error) { 947 callback(WTFMove(error.value())); 948 return; 949 } 950 this->createIndexAfterQuotaCheck(taskSize, transaction.get(), info, WTFMove(callback)); 951 }); 952 } 953 954 void UniqueIDBDatabase::createIndexAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction& transaction, const IDBIndexInfo& info, ErrorCallback callback) 955 { 956 uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback), taskSize); 820 957 if (!callbackID) 821 958 return; … … 904 1041 LOG(IndexedDB, "(main) UniqueIDBDatabase::renameIndex"); 905 1042 906 uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback)); 1043 auto taskSize = defaultWriteOperationCost + newName.sizeInBytes(); 1044 requestSpace(taskSize, "renameIndex", [this, taskSize, transaction = makeRef(transaction), objectStoreIdentifier, indexIdentifier, newName, callback = WTFMove(callback)](auto error) mutable { 1045 if (error) { 1046 callback(WTFMove(error.value())); 1047 return; 1048 } 1049 this->renameIndexAfterQuotaCheck(taskSize, transaction.get(), objectStoreIdentifier, indexIdentifier, newName, WTFMove(callback)); 1050 }); 1051 } 1052 1053 void UniqueIDBDatabase::renameIndexAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName, ErrorCallback callback) 1054 { 1055 uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback), taskSize); 907 1056 if (!callbackID) 908 1057 return; … … 958 1107 LOG(IndexedDB, "(main) UniqueIDBDatabase::putOrAdd"); 959 1108 960 uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback)); 1109 auto taskSize = defaultWriteOperationCost + estimateSize(keyData) + estimateSize(value); 1110 requestSpace(taskSize, "putOrAdd", [this, taskSize, requestData, keyData, value, callback = WTFMove(callback), overwriteMode](auto error) mutable { 1111 if (error) { 1112 callback(WTFMove(error.value()), { }); 1113 return; 1114 } 1115 this->putOrAddAfterQuotaCheck(taskSize, requestData, keyData, value, overwriteMode, WTFMove(callback)); 1116 }); 1117 } 1118 1119 void UniqueIDBDatabase::putOrAddAfterQuotaCheck(uint64_t taskSize, const IDBRequestData& requestData, const IDBKeyData& keyData, const IDBValue& value, IndexedDB::ObjectStoreOverwriteMode overwriteMode, KeyDataCallback callback) 1120 { 1121 uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback), taskSize); 961 1122 if (!callbackID) 962 1123 return; … … 1769 1930 void UniqueIDBDatabase::postDatabaseTaskReply(CrossThreadTask&& task) 1770 1931 { 1932 // FIXME: We might want to compute total size only for modification operations. 1933 if (m_backingStore) 1934 m_databasesSizeForOrigin = m_backingStore->databasesSizeForOrigin(); 1771 1935 m_databaseReplyQueue.append(WTFMove(task)); 1772 1936 m_server->postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::executeNextDatabaseTaskReply)); … … 1832 1996 1833 1997 ASSERT(isMainThread()); 1998 1999 m_pendingSpaceIncreasingTasks.clear(); 2000 m_server->resetSpaceUsed(m_identifier.origin()); 1834 2001 1835 2002 // Error out all transactions … … 1903 2070 } 1904 2071 2072 void UniqueIDBDatabase::updateSpaceUsedIfNeeded(uint64_t callbackIdentifier) 2073 { 2074 auto iterator = m_pendingSpaceIncreasingTasks.find(callbackIdentifier); 2075 if (iterator == m_pendingSpaceIncreasingTasks.end()) 2076 return; 2077 2078 m_server->decreasePotentialSpaceUsed(m_identifier.origin(), iterator->value); 2079 m_server->setSpaceUsed(m_identifier.origin(), m_databasesSizeForOrigin); 2080 m_pendingSpaceIncreasingTasks.remove(iterator); 2081 } 2082 1905 2083 void UniqueIDBDatabase::performErrorCallback(uint64_t callbackIdentifier, const IDBError& error) 1906 2084 { 2085 updateSpaceUsedIfNeeded(callbackIdentifier); 2086 1907 2087 auto callback = m_errorCallbacks.take(callbackIdentifier); 1908 2088 ASSERT(callback || m_hardClosedForUserDelete); … … 1916 2096 void UniqueIDBDatabase::performKeyDataCallback(uint64_t callbackIdentifier, const IDBError& error, const IDBKeyData& resultKey) 1917 2097 { 2098 updateSpaceUsedIfNeeded(callbackIdentifier); 2099 1918 2100 auto callback = m_keyDataCallbacks.take(callbackIdentifier); 1919 2101 ASSERT(callback || m_hardClosedForUserDelete); … … 1960 2142 void UniqueIDBDatabase::forgetErrorCallback(uint64_t callbackIdentifier) 1961 2143 { 2144 updateSpaceUsedIfNeeded(callbackIdentifier); 2145 1962 2146 ASSERT(m_errorCallbacks.contains(callbackIdentifier)); 1963 2147 ASSERT(m_callbackQueue.last() == callbackIdentifier); -
trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h
r242555 r242911 55 55 class IDBRequestData; 56 56 class IDBTransactionInfo; 57 class StorageQuotaManager; 57 58 58 59 enum class IDBGetRecordDataType; … … 83 84 84 85 const IDBDatabaseInfo& info() const; 85 IDBServer& server() { return *m_server; }86 IDBServer& server() { return m_server.get(); } 86 87 const IDBDatabaseIdentifier& identifier() const { return m_identifier; } 87 88 … … 120 121 bool hardClosedForUserDelete() const { return m_hardClosedForUserDelete; } 121 122 123 uint64_t spaceUsed() const; 124 122 125 void setQuota(uint64_t); 126 123 127 private: 124 128 enum class CloseState { Start, Done }; … … 143 147 144 148 void scheduleShutdownForClose(); 149 150 void createObjectStoreAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction&, const IDBObjectStoreInfo&, ErrorCallback); 151 void renameObjectStoreAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, const String& newName, ErrorCallback); 152 void createIndexAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction&, const IDBIndexInfo&, ErrorCallback); 153 void renameIndexAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName, ErrorCallback); 154 void putOrAddAfterQuotaCheck(uint64_t taskSize, const IDBRequestData&, const IDBKeyData&, const IDBValue&, IndexedDB::ObjectStoreOverwriteMode, KeyDataCallback); 145 155 146 156 // Database thread operations … … 194 204 void didShutdownForClose(); 195 205 196 uint64_t storeCallbackOrFireError(ErrorCallback&& );197 uint64_t storeCallbackOrFireError(KeyDataCallback&& );206 uint64_t storeCallbackOrFireError(ErrorCallback&&, uint64_t taskSize = 0); 207 uint64_t storeCallbackOrFireError(KeyDataCallback&&, uint64_t taskSize = 0); 198 208 uint64_t storeCallbackOrFireError(GetAllResultsCallback&&); 199 209 uint64_t storeCallbackOrFireError(GetResultCallback&&); … … 230 240 void notifyServerAboutClose(CloseState); 231 241 232 RefPtr<IDBServer> m_server; 242 void requestSpace(uint64_t taskSize, const char* errorMessage, CompletionHandler<void(Optional<IDBError>&&)>&&); 243 void updateSpaceUsedIfNeeded(uint64_t callbackIdentifier); 244 245 Ref<IDBServer> m_server; 233 246 IDBDatabaseIdentifier m_identifier; 234 247 235 248 ListHashSet<RefPtr<ServerOpenDBRequest>> m_pendingOpenDBRequests; 236 249 RefPtr<ServerOpenDBRequest> m_currentOpenDBRequest; … … 280 293 281 294 HashSet<IDBResourceIdentifier> m_cursorPrefetches; 295 296 HashMap<uint64_t, uint64_t> m_pendingSpaceIncreasingTasks; 297 uint64_t m_databasesSizeForOrigin { 0 }; 282 298 }; 283 299 -
trunk/Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.cpp
r240437 r242911 45 45 namespace WebCore { 46 46 47 Ref<InProcessIDBServer> InProcessIDBServer::create( )48 { 49 Ref<InProcessIDBServer> server = adoptRef(*new InProcessIDBServer );47 Ref<InProcessIDBServer> InProcessIDBServer::create(PAL::SessionID sessionID) 48 { 49 Ref<InProcessIDBServer> server = adoptRef(*new InProcessIDBServer(sessionID)); 50 50 server->m_server->registerConnection(server->connectionToClient()); 51 51 return server; 52 52 } 53 53 54 Ref<InProcessIDBServer> InProcessIDBServer::create( const String& databaseDirectoryPath)55 { 56 Ref<InProcessIDBServer> server = adoptRef(*new InProcessIDBServer( databaseDirectoryPath));54 Ref<InProcessIDBServer> InProcessIDBServer::create(PAL::SessionID sessionID, const String& databaseDirectoryPath) 55 { 56 Ref<InProcessIDBServer> server = adoptRef(*new InProcessIDBServer(sessionID, databaseDirectoryPath)); 57 57 server->m_server->registerConnection(server->connectionToClient()); 58 58 return server; 59 59 } 60 60 61 InProcessIDBServer::InProcessIDBServer() 62 : m_server(IDBServer::IDBServer::create(*this)) 61 StorageQuotaManager* InProcessIDBServer::quotaManager(const ClientOrigin& origin) 62 { 63 return m_quotaManagers.ensure(origin, [] { 64 return std::make_unique<StorageQuotaManager>(StorageQuotaManager::defaultQuota(), [](uint64_t quota, uint64_t currentSpace, uint64_t spaceIncrease, auto callback) { 65 callback(quota + currentSpace + spaceIncrease); 66 }); 67 }).iterator->value.get(); 68 } 69 70 static inline IDBServer::IDBServer::QuotaManagerGetter storageQuotaManagerGetter(InProcessIDBServer& server) 71 { 72 return [&server, weakServer = makeWeakPtr(server)](PAL::SessionID, const auto& origin) { 73 return weakServer ? server.quotaManager(origin) : nullptr; 74 }; 75 } 76 77 InProcessIDBServer::InProcessIDBServer(PAL::SessionID sessionID) 78 : m_server(IDBServer::IDBServer::create(sessionID, *this, storageQuotaManagerGetter(*this))) 63 79 { 64 80 relaxAdoptionRequirement(); … … 67 83 } 68 84 69 InProcessIDBServer::InProcessIDBServer( const String& databaseDirectoryPath)70 : m_server(IDBServer::IDBServer::create( databaseDirectoryPath, *this))85 InProcessIDBServer::InProcessIDBServer(PAL::SessionID sessionID, const String& databaseDirectoryPath) 86 : m_server(IDBServer::IDBServer::create(sessionID, databaseDirectoryPath, *this, storageQuotaManagerGetter(*this))) 71 87 { 72 88 relaxAdoptionRequirement(); -
trunk/Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.h
r238283 r242911 31 31 #include "IDBConnectionToServer.h" 32 32 #include "IDBServer.h" 33 #include "StorageQuotaManager.h" 33 34 #include <wtf/RefCounted.h> 34 35 #include <wtf/RefPtr.h> 36 #include <wtf/WeakPtr.h> 37 38 namespace PAL { 39 class SessionID; 40 } 35 41 36 42 namespace WebCore { 43 44 struct ClientOrigin; 37 45 38 46 namespace IDBClient { … … 46 54 class InProcessIDBServer final : public IDBClient::IDBConnectionToServerDelegate, public IDBServer::IDBConnectionToClientDelegate, public RefCounted<InProcessIDBServer>, public IDBServer::IDBBackingStoreTemporaryFileHandler { 47 55 public: 48 WEBCORE_EXPORT static Ref<InProcessIDBServer> create( );49 WEBCORE_EXPORT static Ref<InProcessIDBServer> create( const String& databaseDirectoryPath);56 WEBCORE_EXPORT static Ref<InProcessIDBServer> create(PAL::SessionID); 57 WEBCORE_EXPORT static Ref<InProcessIDBServer> create(PAL::SessionID, const String& databaseDirectoryPath); 50 58 51 59 WEBCORE_EXPORT IDBClient::IDBConnectionToServer& connectionToServer() const; … … 115 123 void accessToTemporaryFileComplete(const String& path) override; 116 124 125 StorageQuotaManager* quotaManager(const ClientOrigin&); 126 127 const WeakPtrFactory<IDBClient::IDBConnectionToServerDelegate>& weakPtrFactory() const { return IDBClient::IDBConnectionToServerDelegate::weakPtrFactory(); } 128 117 129 private: 118 InProcessIDBServer();119 InProcessIDBServer( const String& databaseDirectoryPath);130 explicit InProcessIDBServer(PAL::SessionID); 131 InProcessIDBServer(PAL::SessionID, const String& databaseDirectoryPath); 120 132 121 133 Ref<IDBServer::IDBServer> m_server; 122 134 RefPtr<IDBClient::IDBConnectionToServer> m_connectionToServer; 123 135 RefPtr<IDBServer::IDBConnectionToClient> m_connectionToClient; 136 137 HashMap<ClientOrigin, std::unique_ptr<StorageQuotaManager>> m_quotaManagers; 124 138 }; 125 139 -
trunk/Source/WebCore/loader/EmptyClients.cpp
r242681 r242911 119 119 class EmptyDatabaseProvider final : public DatabaseProvider { 120 120 #if ENABLE(INDEXED_DATABASE) 121 IDBClient::IDBConnectionToServer& idbConnectionToServerForSession(const PAL::SessionID& ) final121 IDBClient::IDBConnectionToServer& idbConnectionToServerForSession(const PAL::SessionID& sessionID) final 122 122 { 123 static auto& sharedConnection = InProcessIDBServer::create( ).leakRef();123 static auto& sharedConnection = InProcessIDBServer::create(sessionID).leakRef(); 124 124 return sharedConnection.connectionToServer(); 125 125 } -
trunk/Source/WebCore/storage/StorageQuotaManager.cpp
r242599 r242911 45 45 } 46 46 47 void StorageQuotaManager::addUser(StorageQuotaUser& user) 48 { 49 ASSERT(!m_pendingInitializationUsers.contains(&user)); 50 ASSERT(!m_users.contains(&user)); 51 m_pendingInitializationUsers.add(&user); 52 user.whenInitialized([this, &user, weakThis = makeWeakPtr(this)]() { 53 if (!weakThis) 54 return; 55 m_pendingInitializationUsers.remove(&user); 56 m_users.add(&user); 57 processPendingRequests({ }); 58 }); 59 } 60 47 61 void StorageQuotaManager::requestSpace(uint64_t spaceIncrease, RequestCallback&& callback) 48 62 { 49 if (!m_pendingRequests.isEmpty() ) {63 if (!m_pendingRequests.isEmpty() || !m_pendingInitializationUsers.isEmpty()) { 50 64 m_pendingRequests.append({ spaceIncrease, WTFMove(callback) }); 51 65 return; -
trunk/Source/WebCore/storage/StorageQuotaManager.h
r242599 r242911 47 47 WEBCORE_EXPORT ~StorageQuotaManager(); 48 48 49 void addUser(StorageQuotaUser& user) 50 { 51 ASSERT(!m_users.contains(&user)); 52 m_users.add(&user); 53 } 49 static constexpr uint64_t defaultQuota() { return 500 * MB; } 54 50 51 WEBCORE_EXPORT void addUser(StorageQuotaUser&); 55 52 void removeUser(StorageQuotaUser& user) 56 53 { 57 ASSERT(m_users.contains(&user)); 54 ASSERT(m_users.contains(&user) || m_pendingInitializationUsers.contains(&user)); 55 m_pendingInitializationUsers.remove(&user); 58 56 m_users.remove(&user); 59 57 } … … 70 68 uint64_t m_quota { 0 }; 71 69 SpaceIncreaseRequester m_spaceIncreaseRequester; 70 HashSet<const StorageQuotaUser*> m_pendingInitializationUsers; 72 71 HashSet<const StorageQuotaUser*> m_users; 73 72 -
trunk/Source/WebCore/storage/StorageQuotaUser.h
r242599 r242911 26 26 #pragma once 27 27 28 #include <wtf/CompletionHandler.h> 29 28 30 namespace WebCore { 29 31 … … 33 35 34 36 virtual uint64_t spaceUsed() const = 0; 37 virtual void whenInitialized(CompletionHandler<void()>&& callback) { callback(); } 35 38 }; 36 39 -
trunk/Source/WebKit/ChangeLog
r242908 r242911 1 2019-03-13 Youenn Fablet <youenn@apple.com> 2 3 Check IDB quota usage through QuotaManager 4 https://bugs.webkit.org/show_bug.cgi?id=195302 5 6 Reviewed by Chris Dumez. 7 8 Set the quota manager getter for IDBServer at creation time. 9 10 * NetworkProcess/NetworkProcess.cpp: 11 (WebKit::NetworkProcess::createIDBServer): 12 (WebKit::NetworkProcess::idbServer): 13 * NetworkProcess/NetworkProcess.h: 14 * WebProcess/Databases/WebDatabaseProvider.cpp: 15 (WebKit::WebDatabaseProvider::idbConnectionToServerForSession): 16 1 17 2019-03-13 Timothy Hatcher <timothy@apple.com> 2 18 -
trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp
r242905 r242911 2036 2036 2037 2037 #if ENABLE(INDEXED_DATABASE) 2038 IDBServer::IDBServer& NetworkProcess::idbServer(PAL::SessionID sessionID) 2039 { 2040 auto addResult = m_idbServers.add(sessionID, nullptr); 2041 if (!addResult.isNewEntry) { 2042 ASSERT(addResult.iterator->value); 2043 return *addResult.iterator->value; 2044 } 2045 2038 Ref<IDBServer::IDBServer> NetworkProcess::createIDBServer(PAL::SessionID sessionID) 2039 { 2046 2040 auto path = m_idbDatabasePaths.get(sessionID); 2047 2041 // There should already be a registered path for this PAL::SessionID. 2048 2042 // If there's not, then where did this PAL::SessionID come from? 2049 2043 ASSERT(!path.isEmpty()); 2050 2051 addResult.iterator->value = IDBServer::IDBServer::create(path, *this, [this](bool isHoldingLockedFiles) { 2052 notifyHoldingLockedFiles(isHoldingLockedFiles); 2044 2045 auto server = IDBServer::IDBServer::create(sessionID, path, *this, [this, weakThis = makeWeakPtr(this)](PAL::SessionID sessionID, const auto& origin) -> StorageQuotaManager* { 2046 if (!weakThis) 2047 return nullptr; 2048 return &this->storageQuotaManager(sessionID, origin); 2049 }, [this, weakThis = makeWeakPtr(this)](bool isHoldingLockedFiles) { 2050 if (!weakThis) 2051 return; 2052 this->notifyHoldingLockedFiles(isHoldingLockedFiles); 2053 2053 }); 2054 addResult.iterator->value->setPerOriginQuota(m_idbPerOriginQuota); 2055 return *addResult.iterator->value; 2054 server->setPerOriginQuota(m_idbPerOriginQuota); 2055 return server; 2056 } 2057 2058 IDBServer::IDBServer& NetworkProcess::idbServer(PAL::SessionID sessionID) 2059 { 2060 return *m_idbServers.ensure(sessionID, [this, sessionID] { 2061 return this->createIDBServer(sessionID); 2062 }).iterator->value; 2056 2063 } 2057 2064 -
trunk/Source/WebKit/NetworkProcess/NetworkProcess.h
r242905 r242911 431 431 void addIndexedDatabaseSession(PAL::SessionID, String&, SandboxExtension::Handle&); 432 432 HashSet<WebCore::SecurityOriginData> indexedDatabaseOrigins(const String& path); 433 Ref<WebCore::IDBServer::IDBServer> createIDBServer(PAL::SessionID); 433 434 #endif 434 435 … … 525 526 526 527 struct StorageQuotaManagers { 527 uint64_t defaultQuota { 0};528 uint64_t defaultQuota { WebCore::StorageQuotaManager::defaultQuota() }; 528 529 HashMap<WebCore::ClientOrigin, std::unique_ptr<WebCore::StorageQuotaManager>> managersPerOrigin; 529 530 }; -
trunk/Source/WebKit/WebProcess/Databases/WebDatabaseProvider.cpp
r236035 r242911 73 73 auto result = m_idbEphemeralConnectionMap.add(sessionID.sessionID(), nullptr); 74 74 if (result.isNewEntry) 75 result.iterator->value = WebCore::InProcessIDBServer::create( );75 result.iterator->value = WebCore::InProcessIDBServer::create(sessionID); 76 76 77 77 return result.iterator->value->connectionToServer(); -
trunk/Source/WebKitLegacy/ChangeLog
r242581 r242911 1 2019-03-13 Youenn Fablet <youenn@apple.com> 2 3 Check IDB quota usage through QuotaManager 4 https://bugs.webkit.org/show_bug.cgi?id=195302 5 6 Reviewed by Chris Dumez. 7 8 * Storage/WebDatabaseProvider.cpp: 9 (WebDatabaseProvider::idbConnectionToServerForSession): 10 1 11 2019-03-06 Sam Weinig <sam@webkit.org> 2 12 -
trunk/Source/WebKitLegacy/Storage/WebDatabaseProvider.cpp
r237700 r242911 49 49 if (result.isNewEntry) { 50 50 if (sessionID.isEphemeral()) 51 result.iterator->value = WebCore::InProcessIDBServer::create( );51 result.iterator->value = WebCore::InProcessIDBServer::create(sessionID); 52 52 else 53 result.iterator->value = WebCore::InProcessIDBServer::create( indexedDatabaseDirectoryPath());53 result.iterator->value = WebCore::InProcessIDBServer::create(sessionID, indexedDatabaseDirectoryPath()); 54 54 } 55 55
Note: See TracChangeset
for help on using the changeset viewer.