From 2e530eeede2cee008c567c29d9845c04ba2bb4a5 Mon Sep 17 00:00:00 2001 From: Jari Jalkanen Date: Wed, 27 Mar 2024 12:47:15 +0000 Subject: [PATCH] Bug 1874334 - Update cached quota usage when OPFS temporary file is copied. r=dom-storage-reviewers,janv Differential Revision: https://phabricator.services.mozilla.com/D204780 --- .../FileSystemDatabaseManagerVersion001.cpp | 2 +- .../FileSystemDatabaseManagerVersion001.h | 2 +- .../FileSystemDatabaseManagerVersion002.cpp | 3 + dom/fs/test/common/test_writableFileStream.js | 106 ++++++++++++++++++ 4 files changed, 111 insertions(+), 2 deletions(-) diff --git a/dom/fs/parent/datamodel/FileSystemDatabaseManagerVersion001.cpp b/dom/fs/parent/datamodel/FileSystemDatabaseManagerVersion001.cpp index c65bf0150836..a898f1afb61c 100644 --- a/dom/fs/parent/datamodel/FileSystemDatabaseManagerVersion001.cpp +++ b/dom/fs/parent/datamodel/FileSystemDatabaseManagerVersion001.cpp @@ -1233,7 +1233,7 @@ void FileSystemDatabaseManagerVersion001::DecreaseCachedQuotaUsage( } nsresult FileSystemDatabaseManagerVersion001::UpdateCachedQuotaUsage( - const FileId& aFileId, Usage aOldUsage, Usage aNewUsage) { + const FileId& aFileId, Usage aOldUsage, Usage aNewUsage) const { quota::QuotaManager* quotaManager = quota::QuotaManager::Get(); MOZ_ASSERT(quotaManager); diff --git a/dom/fs/parent/datamodel/FileSystemDatabaseManagerVersion001.h b/dom/fs/parent/datamodel/FileSystemDatabaseManagerVersion001.h index 333c5af6c259..64ecfa5b01c9 100644 --- a/dom/fs/parent/datamodel/FileSystemDatabaseManagerVersion001.h +++ b/dom/fs/parent/datamodel/FileSystemDatabaseManagerVersion001.h @@ -130,7 +130,7 @@ class FileSystemDatabaseManagerVersion001 : public FileSystemDatabaseManager { void DecreaseCachedQuotaUsage(int64_t aDelta); nsresult UpdateCachedQuotaUsage(const FileId& aFileId, Usage aOldUsage, - Usage aNewUsage); + Usage aNewUsage) const; nsresult ClearDestinationIfNotLocked( const FileSystemConnection& aConnection, diff --git a/dom/fs/parent/datamodel/FileSystemDatabaseManagerVersion002.cpp b/dom/fs/parent/datamodel/FileSystemDatabaseManagerVersion002.cpp index 3543346ff071..a6c61b0e3e26 100644 --- a/dom/fs/parent/datamodel/FileSystemDatabaseManagerVersion002.cpp +++ b/dom/fs/parent/datamodel/FileSystemDatabaseManagerVersion002.cpp @@ -463,6 +463,9 @@ nsresult FileSystemDatabaseManagerVersion002::GetFile( if (mainFileId) { QM_TRY_UNWRAP(aFile, mFileManager->CreateFileFrom(aFileId, mainFileId.value())); + int64_t fileSize = 0; + QM_TRY(QM_TO_RESULT(aFile->GetFileSize(&fileSize))); + UpdateCachedQuotaUsage(aFileId, 0, fileSize); } else { // LockShared/EnsureTemporaryFileId has provided a brand new fileId. QM_TRY_UNWRAP(aFile, mFileManager->GetOrCreateFile(aFileId)); diff --git a/dom/fs/test/common/test_writableFileStream.js b/dom/fs/test/common/test_writableFileStream.js index 016c53bf3b00..5b6caa0d2057 100644 --- a/dom/fs/test/common/test_writableFileStream.js +++ b/dom/fs/test/common/test_writableFileStream.js @@ -2,6 +2,7 @@ http://creativecommons.org/publicdomain/zero/1.0/ */ const allowCreate = { create: true }; +const denyCreate = { create: false }; exported_symbols.test0 = async function () { let root = await navigator.storage.getDirectory(); @@ -145,6 +146,111 @@ exported_symbols.bug1825018 = async function () { } }; +exported_symbols.usageTest = async function () { + const bufferSize = 1024; + const keepData = { keepExistingData: true }; + const fromEmpty = { keepExistingData: false }; + + let root = await navigator.storage.getDirectory(); + Assert.ok(root, "Can we access the root directory?"); + + const baseUsage = await Utils.getCachedOriginUsage(); + Assert.ok(true, "Usage " + baseUsage); + // Create a file. + { + const fileHandle = await root.getFileHandle("usagetest.txt", allowCreate); + Assert.ok(!!fileHandle, "Can we get file handle?"); + + const writable = await fileHandle.createWritable(fromEmpty); + Assert.ok(!!writable, "Can we create writable file stream?"); + + const buffer = new ArrayBuffer(bufferSize); + Assert.ok(!!buffer, "Can we create array buffer?"); + + const result = await writable.write(buffer); + Assert.equal(result, undefined, "Can we write entire buffer?"); + + await writable.close(); + } + + { + const fileUsage = await Utils.getCachedOriginUsage(); + Assert.ok(true, "Usage " + fileUsage); + Assert.ok(fileUsage >= baseUsage + bufferSize); + + const fileHandle = await root.getFileHandle("usagetest.txt", denyCreate); + Assert.ok(!!fileHandle, "Can we get file handle?"); + + { + const usageNow = await Utils.getCachedOriginUsage(); + Assert.equal(usageNow, fileUsage); + } + + const writableA = await fileHandle.createWritable(keepData); + Assert.ok(!!writableA, "Can we create writable file stream?"); + + { + const usageNow = await Utils.getCachedOriginUsage(); + Assert.ok(true, "Usage " + usageNow.usage); + Assert.equal(usageNow, fileUsage + bufferSize); + } + + const writableB = await fileHandle.createWritable(keepData); + Assert.ok(!!writableB, "Can we create writable file stream?"); + + { + const usageNow = await Utils.getCachedOriginUsage(); + Assert.equal(usageNow, fileUsage + 2 * bufferSize); + } + + const writableC = await fileHandle.createWritable(keepData); + Assert.ok(!!writableC, "Can we create writable file stream?"); + + { + const usageNow = await Utils.getCachedOriginUsage(); + Assert.equal(usageNow, fileUsage + 3 * bufferSize); + } + + const writableD = await fileHandle.createWritable(fromEmpty); + Assert.ok(!!writableD, "Can we create writable file stream?"); + + { + const usageNow = await Utils.getCachedOriginUsage(); + // We did not keep existing data for this writable + Assert.equal(usageNow, fileUsage + 3 * bufferSize); + } + + await writableA.abort(); + + { + const usageNow = await Utils.getCachedOriginUsage(); + Assert.equal(usageNow, fileUsage + 2 * bufferSize); + } + + await writableB.close(); + + { + const usageNow = await Utils.getCachedOriginUsage(); + Assert.equal(usageNow, fileUsage + bufferSize); + } + + await writableC.abort(); + + { + const usageNow = await Utils.getCachedOriginUsage(); + Assert.equal(usageNow, fileUsage); + } + + await writableD.close(); + + { + const usageNow = await Utils.getCachedOriginUsage(); + // Buffer was overwritten with nothing. + Assert.equal(usageNow, fileUsage - bufferSize); + } + } +}; + for (const [key, value] of Object.entries(exported_symbols)) { Object.defineProperty(value, "name", { value: key,