Diff
Modified: trunk/LayoutTests/ChangeLog (243338 => 243339)
--- trunk/LayoutTests/ChangeLog 2019-03-21 22:51:32 UTC (rev 243338)
+++ trunk/LayoutTests/ChangeLog 2019-03-21 22:52:18 UTC (rev 243339)
@@ -1,3 +1,22 @@
+2019-03-21 Youenn Fablet <[email protected]>
+
+ Cache API and IDB space usages should be initialized on first quota check
+ https://bugs.webkit.org/show_bug.cgi?id=195707
+
+ Reviewed by Chris Dumez.
+
+ * TestExpectations:
+ Marking http/tests/cache-storage/cache-clearing-origin.https.html as
+ flaky on iOS as it is already marked flaky in MacOS.
+ * platform/mac-wk2/TestExpectations:
+ * http/tests/IndexedDB/storage-limit-1.https-expected.txt: Added.
+ * http/tests/IndexedDB/storage-limit-1.https.html: Added.
+ * http/tests/IndexedDB/storage-limit-2.https-expected.txt: Added.
+ * http/tests/IndexedDB/storage-limit-2.https.html: Added.
+ * http/tests/IndexedDB/storage-limit.https.html:
+ * platform/mac-wk1/TestExpectations:
+ * platform/win/TestExpectations:
+
2019-03-21 Said Abou-Hallawa <[email protected]>
Remove the SVG tear off objects for SVGPoint, SVGPointList and SVGAnimatedPointList
Modified: trunk/LayoutTests/TestExpectations (243338 => 243339)
--- trunk/LayoutTests/TestExpectations 2019-03-21 22:51:32 UTC (rev 243338)
+++ trunk/LayoutTests/TestExpectations 2019-03-21 22:52:18 UTC (rev 243339)
@@ -2236,6 +2236,7 @@
webkit.org/b/90980 fast/forms/textarea/textarea-state-restore.html [ Pass Timeout ]
webkit.org/b/182928 http/tests/cache-storage/cache-representation.https.html [ Pass Failure ]
+webkit.org/b/193976 http/tests/cache-storage/cache-clearing-origin.https.html [ Pass Failure ]
webkit.org/b/116621 fast/replaced/preferred-widths.html [ Pass Failure ]
Deleted: trunk/LayoutTests/http/tests/IndexedDB/resources/storage-limit.js (243338 => 243339)
--- trunk/LayoutTests/http/tests/IndexedDB/resources/storage-limit.js 2019-03-21 22:51:32 UTC (rev 243338)
+++ trunk/LayoutTests/http/tests/IndexedDB/resources/storage-limit.js 2019-03-21 22:52:18 UTC (rev 243339)
@@ -1,39 +0,0 @@
-if (window.testRunner)
- testRunner.setAllowStorageQuotaIncrease(false);
-
-description("This test makes sure that storage of indexedDB does not grow unboundedly.");
-
-window.caches.open("test").then(cache => {
- return cache.put(new Request("/test"), new Response(new Uint8Array(204800)));
-}).then(() => {
- indexedDBTest(prepareDatabase, onOpenSuccess, {'suffix': '-1'});
-}).catch(e => {
- testFailed("Cache API store operation failed: " + e);
- finishJSTest();
-});
-
-function prepareDatabase(event)
-{
- evalAndLog("db = event.target.result");
- evalAndLog("store = db.createObjectStore('store')");
-}
-
-// Quota for test is 400ko, but IDB is eating some of it when initializing files.
-// Let's make sure that 200ko is fine but 200ko after 200ko is not fine.
-async function onOpenSuccess(event)
-{
- evalAndLog("db = event.target.result");
- evalAndLog("store = db.transaction('store', 'readwrite').objectStore('store')");
- evalAndLog("request = store.add(new Uint8Array(204800), 'key')");
- request._onerror_ = function(event) {
- shouldBeTrue("'error' in request");
- shouldBe("request.error.code", "DOMException.QUOTA_EXCEEDED_ERR");
- shouldBeEqualToString("request.error.name", "QuotaExceededError");
- finishJSTest();
- }
-
- request._onsuccess_ = function(event) {
- testFailed("Add operation should fail because storage limit is reached, but succeeded.");
- finishJSTest();
- }
-}
Added: trunk/LayoutTests/http/tests/IndexedDB/storage-limit-1.https-expected.txt (0 => 243339)
--- trunk/LayoutTests/http/tests/IndexedDB/storage-limit-1.https-expected.txt (rev 0)
+++ trunk/LayoutTests/http/tests/IndexedDB/storage-limit-1.https-expected.txt 2019-03-21 22:52:18 UTC (rev 243339)
@@ -0,0 +1,21 @@
+This test makes sure that storage of indexedDB and Cache API do not grow unboundedly.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+indexedDB = self.indexedDB || self.webkitIndexedDB || self.mozIndexedDB || self.msIndexedDB || self.OIndexedDB;
+
+indexedDB.deleteDatabase(dbname)
+indexedDB.open(dbname)
+db = event.target.result
+store = db.createObjectStore('store')
+db = event.target.result
+store = db.transaction('store', 'readwrite').objectStore('store')
+request = store.add(new Uint8Array(300 * 1024), 'key')
+PASS 'error' in request is true
+PASS request.error.code is DOMException.QUOTA_EXCEEDED_ERR
+PASS request.error.name is "QuotaExceededError"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Copied: trunk/LayoutTests/http/tests/IndexedDB/storage-limit-1.https.html (from rev 243338, trunk/LayoutTests/http/tests/IndexedDB/resources/storage-limit.js) (0 => 243339)
--- trunk/LayoutTests/http/tests/IndexedDB/storage-limit-1.https.html (rev 0)
+++ trunk/LayoutTests/http/tests/IndexedDB/storage-limit-1.https.html 2019-03-21 22:52:18 UTC (rev 243339)
@@ -0,0 +1,57 @@
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script>
+if (window.testRunner)
+ testRunner.setAllowStorageQuotaIncrease(false);
+
+description("This test makes sure that storage of indexedDB and Cache API do not grow unboundedly.");
+
+window.caches.open("test").then(cache => {
+ return cache.put(new Request("/test"), new Response(new Uint8Array(200 * 1024)));
+}).then(async() => {
+ // Let's terminate the network process so that all the opened quota users are gone for IDB quota check.
+ if (window.testRunner)
+ testRunner.terminateNetworkProcess();
+ while (true) {
+ try {
+ await fetch(".");
+ break;
+ } catch (e) { }
+ }
+ indexedDBTest(prepareDatabase, onOpenSuccess, {'suffix': '-1'});
+}).catch(e => {
+ testFailed("Cache API store operation failed: " + e);
+ finishJSTest();
+});
+
+function prepareDatabase(event)
+{
+ evalAndLog("db = event.target.result");
+ evalAndLog("store = db.createObjectStore('store')");
+}
+
+// Quota for test is 400ko, but IDB is eating some of it when initializing files.
+// Let's make sure that 200ko is fine but 300ko after 200ko is not fine.
+async function onOpenSuccess(event)
+{
+ evalAndLog("db = event.target.result");
+ evalAndLog("store = db.transaction('store', 'readwrite').objectStore('store')");
+ evalAndLog("request = store.add(new Uint8Array(300 * 1024), 'key')");
+ request._onerror_ = function(event) {
+ shouldBeTrue("'error' in request");
+ shouldBe("request.error.code", "DOMException.QUOTA_EXCEEDED_ERR");
+ shouldBeEqualToString("request.error.name", "QuotaExceededError");
+ finishJSTest();
+ }
+
+ request._onsuccess_ = function(event) {
+ testFailed("Add operation should fail because storage limit is reached, but succeeded.");
+ finishJSTest();
+ }
+}</script>
+</body>
+</html>
Added: trunk/LayoutTests/http/tests/IndexedDB/storage-limit-2.https-expected.txt (0 => 243339)
--- trunk/LayoutTests/http/tests/IndexedDB/storage-limit-2.https-expected.txt (rev 0)
+++ trunk/LayoutTests/http/tests/IndexedDB/storage-limit-2.https-expected.txt 2019-03-21 22:52:18 UTC (rev 243339)
@@ -0,0 +1,21 @@
+CONSOLE MESSAGE: Cache API operation failed: Quota exceeded
+This test makes sure that storage of indexedDB and Cache API do not grow unboundedly.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+indexedDB = self.indexedDB || self.webkitIndexedDB || self.mozIndexedDB || self.msIndexedDB || self.OIndexedDB;
+
+indexedDB.deleteDatabase(dbname)
+indexedDB.open(dbname)
+db = event.target.result
+store = db.createObjectStore('store')
+db = event.target.result
+store = db.transaction('store', 'readwrite').objectStore('store')
+request = store.add(new Uint8Array(204800), 'key')
+finished idb processing
+Cache API store operation failed: QuotaExceededError: Quota exceeded
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/http/tests/IndexedDB/storage-limit-2.https.html (0 => 243339)
--- trunk/LayoutTests/http/tests/IndexedDB/storage-limit-2.https.html (rev 0)
+++ trunk/LayoutTests/http/tests/IndexedDB/storage-limit-2.https.html 2019-03-21 22:52:18 UTC (rev 243339)
@@ -0,0 +1,62 @@
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script>
+if (window.testRunner)
+ testRunner.setAllowStorageQuotaIncrease(false);
+
+description("This test makes sure that storage of indexedDB and Cache API do not grow unboundedly.");
+
+indexedDBTest(prepareDatabase, onOpenSuccess, {'suffix': '-1'});
+
+function prepareDatabase(event)
+{
+ evalAndLog("db = event.target.result");
+ evalAndLog("store = db.createObjectStore('store')");
+}
+
+// Quota for test is 400ko, but IDB is eating some of it when initializing files.
+// Let's make sure that 200ko is fine but 200ko after 200ko is not fine.
+async function onOpenSuccess(event)
+{
+ evalAndLog("db = event.target.result");
+ evalAndLog("store = db.transaction('store', 'readwrite').objectStore('store')");
+ evalAndLog("request = store.add(new Uint8Array(204800), 'key')");
+ request._onerror_ = function(event) {
+ testFailed("Add operation should fail because storage limit is reached, but succeeded.");
+ finishJSTest();
+ }
+
+ request._onsuccess_ = async (event) => {
+ debug("finished idb processing");
+ // Let's terminate the network process so that all the opened quota users are gone for Cache API quota check.
+ if (window.testRunner)
+ testRunner.terminateNetworkProcess();
+ while (true) {
+ try {
+ await fetch(".");
+ break;
+ } catch (e) { }
+ }
+ cacheTest();
+ }
+}
+
+function cacheTest()
+{
+ window.caches.open("test").then(cache => {
+ return cache.put(new Request("/test"), new Response(new Uint8Array(304800)));
+ }).then(() => {
+ testFailed("Cache API store operation succeeded");
+ finishJSTest();
+ }).catch(e => {
+ debug("Cache API store operation failed: " + e);
+ finishJSTest();
+ });
+}
+</script>
+</body>
+</html>
Modified: trunk/LayoutTests/http/tests/IndexedDB/storage-limit.https.html (243338 => 243339)
--- trunk/LayoutTests/http/tests/IndexedDB/storage-limit.https.html 2019-03-21 22:51:32 UTC (rev 243338)
+++ trunk/LayoutTests/http/tests/IndexedDB/storage-limit.https.html 2019-03-21 22:52:18 UTC (rev 243339)
@@ -4,6 +4,46 @@
<script src=""
</head>
<body>
-<script src=""
+<script>
+if (window.testRunner)
+ testRunner.setAllowStorageQuotaIncrease(false);
+
+description("This test makes sure that storage of indexedDB does not grow unboundedly.");
+
+window.caches.open("test").then(cache => {
+ return cache.put(new Request("/test"), new Response(new Uint8Array(204800)));
+}).then(() => {
+ indexedDBTest(prepareDatabase, onOpenSuccess, {'suffix': '-1'});
+}).catch(e => {
+ testFailed("Cache API store operation failed: " + e);
+ finishJSTest();
+});
+
+function prepareDatabase(event)
+{
+ evalAndLog("db = event.target.result");
+ evalAndLog("store = db.createObjectStore('store')");
+}
+
+// Quota for test is 400ko, but IDB is eating some of it when initializing files.
+// Let's make sure that 200ko is fine but 200ko after 200ko is not fine.
+async function onOpenSuccess(event)
+{
+ evalAndLog("db = event.target.result");
+ evalAndLog("store = db.transaction('store', 'readwrite').objectStore('store')");
+ evalAndLog("request = store.add(new Uint8Array(204800), 'key')");
+ request._onerror_ = function(event) {
+ shouldBeTrue("'error' in request");
+ shouldBe("request.error.code", "DOMException.QUOTA_EXCEEDED_ERR");
+ shouldBeEqualToString("request.error.name", "QuotaExceededError");
+ finishJSTest();
+ }
+
+ request._onsuccess_ = function(event) {
+ testFailed("Add operation should fail because storage limit is reached, but succeeded.");
+ finishJSTest();
+ }
+}
+</script>
</body>
</html>
Modified: trunk/LayoutTests/platform/mac-wk1/TestExpectations (243338 => 243339)
--- trunk/LayoutTests/platform/mac-wk1/TestExpectations 2019-03-21 22:51:32 UTC (rev 243338)
+++ trunk/LayoutTests/platform/mac-wk1/TestExpectations 2019-03-21 22:52:18 UTC (rev 243339)
@@ -164,6 +164,8 @@
# Quota check missing in WK1
http/tests/IndexedDB/storage-limit.https.html [ Skip ]
+http/tests/IndexedDB/storage-limit-1.https.html [ Skip ]
+http/tests/IndexedDB/storage-limit-2.https.html [ Skip ]
storage/indexeddb/storage-limit.html [ Skip ]
# Skip WebRTC for now in WK1
Modified: trunk/LayoutTests/platform/mac-wk2/TestExpectations (243338 => 243339)
--- trunk/LayoutTests/platform/mac-wk2/TestExpectations 2019-03-21 22:51:32 UTC (rev 243338)
+++ trunk/LayoutTests/platform/mac-wk2/TestExpectations 2019-03-21 22:52:18 UTC (rev 243339)
@@ -912,8 +912,6 @@
webkit.org/b/191658 [ Sierra Release ] fast/layers/no-clipping-overflow-hidden-added-after-transform.html [ Pass ImageOnlyFailure ]
-webkit.org/b/193976 http/tests/cache-storage/cache-clearing-origin.https.html [ Pass Failure ]
-
webkit.org/b/194826 http/tests/resourceLoadStatistics/do-not-block-top-level-navigation-redirect.html [ Pass Timeout ]
webkit.org/b/194368 http/tests/workers/service/basic-register-exceptions.html [ Pass Failure ]
Modified: trunk/LayoutTests/platform/win/TestExpectations (243338 => 243339)
--- trunk/LayoutTests/platform/win/TestExpectations 2019-03-21 22:51:32 UTC (rev 243338)
+++ trunk/LayoutTests/platform/win/TestExpectations 2019-03-21 22:52:18 UTC (rev 243339)
@@ -2375,6 +2375,8 @@
storage/indexeddb/storage-limit.html [ Skip ]
http/tests/IndexedDB/storage-limit.https.html [ Skip ]
+http/tests/IndexedDB/storage-limit-1.https.html [ Skip ]
+http/tests/IndexedDB/storage-limit-2.https.html [ Skip ]
# Assertion failures: Not investigated
[ Debug ] http/tests/security/isolatedWorld/storage-properties.html [ Skip ]
Modified: trunk/Source/WebCore/ChangeLog (243338 => 243339)
--- trunk/Source/WebCore/ChangeLog 2019-03-21 22:51:32 UTC (rev 243338)
+++ trunk/Source/WebCore/ChangeLog 2019-03-21 22:52:18 UTC (rev 243339)
@@ -1,3 +1,27 @@
+2019-03-21 Youenn Fablet <[email protected]>
+
+ Cache API and IDB space usages should be initialized on first quota check
+ https://bugs.webkit.org/show_bug.cgi?id=195707
+
+ Reviewed by Chris Dumez.
+
+ Add a way to require IDBServer to create a quota user for a given origin.
+ Make sure that removing a user might kick-in processing of pending requests.
+ In the case of processing pending requests, we should not decide on the first task
+ except if it is triggered by a request space response.
+ Update processPendingRequests accordingly.
+
+ Tests: http/tests/IndexedDB/storage-limit-1.https.html
+ http/tests/IndexedDB/storage-limit-2.https.html
+
+ * Modules/indexeddb/server/IDBServer.h:
+ (WebCore::IDBServer::IDBServer::initializeQuotaUser):
+ * storage/StorageQuotaManager.cpp:
+ (WebCore::StorageQuotaManager::removeUser):
+ (WebCore::StorageQuotaManager::askForMoreSpace):
+ (WebCore::StorageQuotaManager::processPendingRequests):
+ * storage/StorageQuotaManager.h:
+
2019-03-21 Alex Christensen <[email protected]>
Fix iOS build after r243337
Modified: trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp (243338 => 243339)
--- trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp 2019-03-21 22:51:32 UTC (rev 243338)
+++ trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp 2019-03-21 22:52:18 UTC (rev 243339)
@@ -784,7 +784,7 @@
callback();
}
-IDBServer::QuotaUser& IDBServer::quotaUser(const ClientOrigin& origin)
+IDBServer::QuotaUser& IDBServer::ensureQuotaUser(const ClientOrigin& origin)
{
return *m_quotaUsers.ensure(origin, [this, &origin] {
return std::make_unique<QuotaUser>(*this, m_quotaManagerGetter(m_sessionID, origin), ClientOrigin { origin });
@@ -810,12 +810,12 @@
void IDBServer::finishComputingSpaceUsedForOrigin(const ClientOrigin& origin, uint64_t spaceUsed)
{
- quotaUser(origin).initializeSpaceUsed(spaceUsed);
+ ensureQuotaUser(origin).initializeSpaceUsed(spaceUsed);
}
void IDBServer::requestSpace(const ClientOrigin& origin, uint64_t taskSize, CompletionHandler<void(StorageQuotaManager::Decision)>&& callback)
{
- auto* quotaManager = quotaUser(origin).manager();
+ auto* quotaManager = ensureQuotaUser(origin).manager();
if (!quotaManager) {
callback(StorageQuotaManager::Decision::Deny);
return;
@@ -832,17 +832,17 @@
void IDBServer::setSpaceUsed(const ClientOrigin& origin, uint64_t taskSize)
{
- quotaUser(origin).setSpaceUsed(taskSize);
+ ensureQuotaUser(origin).setSpaceUsed(taskSize);
}
void IDBServer::increasePotentialSpaceUsed(const ClientOrigin& origin, uint64_t taskSize)
{
- quotaUser(origin).increasePotentialSpaceUsed(taskSize);
+ ensureQuotaUser(origin).increasePotentialSpaceUsed(taskSize);
}
void IDBServer::decreasePotentialSpaceUsed(const ClientOrigin& origin, uint64_t spaceUsed)
{
- quotaUser(origin).decreasePotentialSpaceUsed(spaceUsed);
+ ensureQuotaUser(origin).decreasePotentialSpaceUsed(spaceUsed);
}
void IDBServer::upgradeFilesIfNecessary()
Modified: trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.h (243338 => 243339)
--- trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.h 2019-03-21 22:51:32 UTC (rev 243338)
+++ trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.h 2019-03-21 22:52:18 UTC (rev 243339)
@@ -125,6 +125,8 @@
void setSpaceUsed(const ClientOrigin&, uint64_t spaceUsed);
void resetSpaceUsed(const ClientOrigin&);
+ void initializeQuotaUser(const ClientOrigin& origin) { ensureQuotaUser(origin); }
+
private:
IDBServer(PAL::SessionID, IDBBackingStoreTemporaryFileHandler&, QuotaManagerGetter&&, WTF::Function<void(bool)>&&);
IDBServer(PAL::SessionID, const String& databaseDirectoryPath, IDBBackingStoreTemporaryFileHandler&, QuotaManagerGetter&&, WTF::Function<void(bool)>&&);
@@ -175,7 +177,7 @@
CompletionHandler<void()> m_initializationCallback;
};
- QuotaUser& quotaUser(const ClientOrigin&);
+ WEBCORE_EXPORT QuotaUser& ensureQuotaUser(const ClientOrigin&);
void startComputingSpaceUsedForOrigin(const ClientOrigin&);
void computeSpaceUsedForOrigin(const ClientOrigin&);
void finishComputingSpaceUsedForOrigin(const ClientOrigin&, uint64_t spaceUsed);
Modified: trunk/Source/WebCore/storage/StorageQuotaManager.cpp (243338 => 243339)
--- trunk/Source/WebCore/storage/StorageQuotaManager.cpp 2019-03-21 22:51:32 UTC (rev 243338)
+++ trunk/Source/WebCore/storage/StorageQuotaManager.cpp 2019-03-21 22:52:18 UTC (rev 243339)
@@ -69,7 +69,7 @@
return;
updateQuotaBasedOnSpaceUsage();
- processPendingRequests({ });
+ processPendingRequests({ }, ShouldDequeueFirstPendingRequest::No);
});
}
@@ -81,6 +81,14 @@
return spaceUsage() + spaceIncrease > m_quota;
}
+void StorageQuotaManager::removeUser(StorageQuotaUser& user)
+{
+ ASSERT(m_users.contains(&user) || m_pendingInitializationUsers.contains(&user));
+ m_users.remove(&user);
+ if (m_pendingInitializationUsers.remove(&user) && m_pendingInitializationUsers.isEmpty())
+ processPendingRequests({ }, ShouldDequeueFirstPendingRequest::No);
+}
+
void StorageQuotaManager::requestSpace(uint64_t spaceIncrease, RequestCallback&& callback)
{
if (!m_pendingRequests.isEmpty() || !m_pendingInitializationUsers.isEmpty()) {
@@ -99,14 +107,17 @@
void StorageQuotaManager::askForMoreSpace(uint64_t spaceIncrease)
{
ASSERT(shouldAskForMoreSpace(spaceIncrease));
+ ASSERT(!m_isWaitingForSpaceIncreaseResponse);
+ m_isWaitingForSpaceIncreaseResponse = true;
m_spaceIncreaseRequester(m_quota, spaceUsage(), spaceIncrease, [this, weakThis = makeWeakPtr(*this)](Optional<uint64_t> newQuota) {
if (!weakThis)
return;
- processPendingRequests(newQuota);
+ m_isWaitingForSpaceIncreaseResponse = false;
+ processPendingRequests(newQuota, ShouldDequeueFirstPendingRequest::Yes);
});
}
-void StorageQuotaManager::processPendingRequests(Optional<uint64_t> newQuota)
+void StorageQuotaManager::processPendingRequests(Optional<uint64_t> newQuota, ShouldDequeueFirstPendingRequest shouldDequeueFirstPendingRequest)
{
if (m_pendingRequests.isEmpty())
return;
@@ -114,10 +125,18 @@
if (newQuota)
m_quota = *newQuota;
- auto request = m_pendingRequests.takeFirst();
- auto decision = shouldAskForMoreSpace(request.spaceIncrease) ? Decision::Deny : Decision::Grant;
- request.callback(decision);
+ if (m_isWaitingForSpaceIncreaseResponse)
+ return;
+ if (!m_pendingInitializationUsers.isEmpty())
+ return;
+
+ if (shouldDequeueFirstPendingRequest == ShouldDequeueFirstPendingRequest::Yes) {
+ auto request = m_pendingRequests.takeFirst();
+ auto decision = shouldAskForMoreSpace(request.spaceIncrease) ? Decision::Deny : Decision::Grant;
+ request.callback(decision);
+ }
+
while (!m_pendingRequests.isEmpty()) {
auto& request = m_pendingRequests.first();
Modified: trunk/Source/WebCore/storage/StorageQuotaManager.h (243338 => 243339)
--- trunk/Source/WebCore/storage/StorageQuotaManager.h 2019-03-21 22:51:32 UTC (rev 243338)
+++ trunk/Source/WebCore/storage/StorageQuotaManager.h 2019-03-21 22:52:18 UTC (rev 243339)
@@ -50,12 +50,7 @@
static constexpr uint64_t defaultThirdPartyQuota() { return 100 * MB; }
WEBCORE_EXPORT void addUser(StorageQuotaUser&);
- void removeUser(StorageQuotaUser& user)
- {
- ASSERT(m_users.contains(&user) || m_pendingInitializationUsers.contains(&user));
- m_pendingInitializationUsers.remove(&user);
- m_users.remove(&user);
- }
+ WEBCORE_EXPORT void removeUser(StorageQuotaUser&);
enum class Decision { Deny, Grant };
using RequestCallback = CompletionHandler<void(Decision)>;
@@ -68,9 +63,13 @@
uint64_t spaceUsage() const;
bool shouldAskForMoreSpace(uint64_t spaceIncrease) const;
void askForMoreSpace(uint64_t spaceIncrease);
- void processPendingRequests(Optional<uint64_t>);
+ enum class ShouldDequeueFirstPendingRequest { No, Yes };
+ void processPendingRequests(Optional<uint64_t>, ShouldDequeueFirstPendingRequest);
+
uint64_t m_quota { 0 };
+
+ bool m_isWaitingForSpaceIncreaseResponse { false };
SpaceIncreaseRequester m_spaceIncreaseRequester;
HashSet<const StorageQuotaUser*> m_pendingInitializationUsers;
HashSet<const StorageQuotaUser*> m_users;
Modified: trunk/Source/WebKit/ChangeLog (243338 => 243339)
--- trunk/Source/WebKit/ChangeLog 2019-03-21 22:51:32 UTC (rev 243338)
+++ trunk/Source/WebKit/ChangeLog 2019-03-21 22:52:18 UTC (rev 243339)
@@ -1,3 +1,29 @@
+2019-03-21 Youenn Fablet <[email protected]>
+
+ Cache API and IDB space usages should be initialized on first quota check
+ https://bugs.webkit.org/show_bug.cgi?id=195707
+
+ Reviewed by Chris Dumez.
+
+ When the quota manager is created, make sure it delays quota check decisions until IDB and Cache API quota users are initialized.
+ For IDB, the creation is synchronous but it may not be synchronous for Cache API.
+ For that purpose, add a temporary quota user that will stay uninitialized until these two quota users are added.
+ Once added, the temporary quota user is removed.
+ The addition of the real users is made asynchronously as this is triggered by the creation of one of the two quota users.
+
+ In the case of a Cache API caches being cleared, make sure to reset the size to zero and to redo the quota user initialization dance.
+
+ * NetworkProcess/NetworkProcess.cpp:
+ (WebKit::QuotaUserInitializer::initialize):
+ (WebKit::QuotaUserInitializer::~QuotaUserInitializer):
+ (WebKit::QuotaUserInitializer::QuotaUserInitializer):
+ (WebKit::NetworkProcess::storageQuotaManager):
+ * NetworkProcess/cache/CacheStorageEngine.cpp:
+ (WebKit::CacheStorage::Engine::initializeQuotaUser):
+ * NetworkProcess/cache/CacheStorageEngine.h:
+ * NetworkProcess/cache/CacheStorageEngineCaches.cpp:
+ (WebKit::CacheStorage::Caches::clear):
+
2019-03-21 Per Arne Vollan <[email protected]>
[iOS][macOS] Fix sandbox call violations
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp (243338 => 243339)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp 2019-03-21 22:51:32 UTC (rev 243338)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp 2019-03-21 22:52:18 UTC (rev 243339)
@@ -2394,6 +2394,49 @@
parentProcessConnection()->sendWithAsyncReply(Messages::NetworkProcessProxy::RequestStorageSpace { sessionID, origin, quota, currentSize, spaceRequired }, WTFMove(callback), 0);
}
+class QuotaUserInitializer final : public WebCore::StorageQuotaUser {
+public:
+ explicit QuotaUserInitializer(StorageQuotaManager& manager)
+ : m_manager(makeWeakPtr(manager))
+ {
+ manager.addUser(*this);
+ }
+
+ ~QuotaUserInitializer()
+ {
+ if (m_manager)
+ m_manager->removeUser(*this);
+ if (m_callback)
+ m_callback();
+ }
+
+private:
+ // StorageQuotaUser API.
+ uint64_t spaceUsed() const final
+ {
+ ASSERT_NOT_REACHED();
+ return 0;
+ }
+
+ void whenInitialized(CompletionHandler<void()>&& callback) final
+ {
+ m_callback = WTFMove(callback);
+ }
+
+ WeakPtr<StorageQuotaManager> m_manager;
+ CompletionHandler<void()> m_callback;
+};
+
+void NetworkProcess::initializeQuotaUsers(StorageQuotaManager& manager, PAL::SessionID sessionID, const ClientOrigin& origin)
+{
+ RunLoop::main().dispatch([this, weakThis = makeWeakPtr(this), sessionID, origin, user = std::make_unique<QuotaUserInitializer>(manager)]() mutable {
+ if (!weakThis)
+ return;
+ this->idbServer(sessionID).initializeQuotaUser(origin);
+ CacheStorage::Engine::initializeQuotaUser(*this, sessionID, origin, [user = WTFMove(user)] { });
+ });
+}
+
StorageQuotaManager& NetworkProcess::storageQuotaManager(PAL::SessionID sessionID, const ClientOrigin& origin)
{
auto& storageQuotaManagers = m_storageQuotaManagers.ensure(sessionID, [] {
@@ -2401,9 +2444,11 @@
}).iterator->value;
return *storageQuotaManagers.managersPerOrigin.ensure(origin, [this, &storageQuotaManagers, sessionID, &origin] {
auto quota = origin.topOrigin == origin.clientOrigin ? storageQuotaManagers.defaultQuota : storageQuotaManagers.defaultThirdPartyQuota;
- return std::make_unique<StorageQuotaManager>(quota, [this, sessionID, origin](uint64_t quota, uint64_t currentSpace, uint64_t spaceIncrease, auto callback) {
+ auto manager = std::make_unique<StorageQuotaManager>(quota, [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;
}
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.h (243338 => 243339)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.h 2019-03-21 22:51:32 UTC (rev 243338)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.h 2019-03-21 22:52:18 UTC (rev 243339)
@@ -383,6 +383,7 @@
void clearCachedCredentials();
void setCacheStorageParameters(PAL::SessionID, uint64_t quota, String&& cacheStorageDirectory, SandboxExtension::Handle&&);
+ void initializeQuotaUsers(WebCore::StorageQuotaManager&, PAL::SessionID, const WebCore::ClientOrigin&);
// FIXME: This should take a session ID so we can identify which disk cache to delete.
void clearDiskCache(WallTime modifiedSince, CompletionHandler<void()>&&);
Modified: trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngine.cpp (243338 => 243339)
--- trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngine.cpp 2019-03-21 22:51:32 UTC (rev 243338)
+++ trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngine.cpp 2019-03-21 22:52:18 UTC (rev 243339)
@@ -185,6 +185,15 @@
});
}
+void Engine::initializeQuotaUser(NetworkProcess& networkProcess, PAL::SessionID sessionID, const WebCore::ClientOrigin& clientOrigin, CompletionHandler<void()>&& completionHandler)
+{
+ from(networkProcess, sessionID, [clientOrigin, completionHandler = WTFMove(completionHandler)](auto& engine) mutable {
+ engine.readCachesFromDisk(clientOrigin, [completionHandler = WTFMove(completionHandler)](auto&& cachesOrError) mutable {
+ completionHandler();
+ });
+ });
+}
+
Engine::Engine(PAL::SessionID sessionID, NetworkProcess& process, String&& rootPath)
: m_sessionID(sessionID)
, m_networkProcess(makeWeakPtr(process))
Modified: trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngine.h (243338 => 243339)
--- trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngine.h 2019-03-21 22:51:32 UTC (rev 243338)
+++ trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngine.h 2019-03-21 22:52:18 UTC (rev 243339)
@@ -80,6 +80,8 @@
static void clearAllCaches(NetworkProcess&, PAL::SessionID, CompletionHandler<void()>&&);
static void clearCachesForOrigin(NetworkProcess&, PAL::SessionID, WebCore::SecurityOriginData&&, CompletionHandler<void()>&&);
+ static void initializeQuotaUser(NetworkProcess&, PAL::SessionID, const WebCore::ClientOrigin&, CompletionHandler<void()>&&);
+
bool shouldPersist() const { return !!m_ioQueue;}
void writeFile(const String& filename, NetworkCache::Data&&, WebCore::DOMCacheEngine::CompletionCallback&&);
Modified: trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.cpp (243338 => 243339)
--- trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.cpp 2019-03-21 22:51:32 UTC (rev 243338)
+++ trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.cpp 2019-03-21 22:52:18 UTC (rev 243339)
@@ -260,11 +260,13 @@
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();
}
@@ -601,6 +603,15 @@
m_storage->remove(key);
}
+void Caches::resetSpaceUsed()
+{
+ m_size = 0;
+ if (m_quotaManager) {
+ m_quotaManager->removeUser(*this);
+ m_quotaManager->addUser(*this);
+ }
+}
+
void Caches::clearMemoryRepresentation()
{
if (!m_isInitialized) {
Modified: trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.h (243338 => 243339)
--- trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.h 2019-03-21 22:51:32 UTC (rev 243338)
+++ trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.h 2019-03-21 22:52:18 UTC (rev 243339)
@@ -78,6 +78,7 @@
void clear(WTF::CompletionHandler<void()>&&);
void clearMemoryRepresentation();
+ void resetSpaceUsed();
uint64_t storageSize() const;