Bug 1679540 - Extract CollectEachFile function and use in quota manager and clients. r=dom-workers-and-storage-reviewers,ttung,janv

Differential Revision: https://phabricator.services.mozilla.com/D98075
This commit is contained in:
Simon Giesecke 2021-01-05 09:27:18 +00:00
parent 2a747a1490
commit aa680355aa
8 changed files with 632 additions and 904 deletions

View File

@ -360,9 +360,10 @@ nsresult BodyDeleteFiles(const QuotaInfo& aQuotaInfo, nsIFile* aBaseDir,
return rv; return rv;
} }
const auto removeFileForId = [&aQuotaInfo, &id](nsIFile* bodyFile, const auto removeFileForId =
const nsACString& leafName, [&aQuotaInfo, &id](
bool& fileDeleted) { nsIFile* bodyFile,
const nsACString& leafName) -> Result<bool, nsresult> {
MOZ_DIAGNOSTIC_ASSERT(bodyFile); MOZ_DIAGNOSTIC_ASSERT(bodyFile);
nsID fileId; nsID fileId;
@ -370,19 +371,16 @@ nsresult BodyDeleteFiles(const QuotaInfo& aQuotaInfo, nsIFile* aBaseDir,
DebugOnly<nsresult> result = DebugOnly<nsresult> result =
RemoveNsIFile(aQuotaInfo, bodyFile, /* aTrackQuota */ false); RemoveNsIFile(aQuotaInfo, bodyFile, /* aTrackQuota */ false);
MOZ_ASSERT(NS_SUCCEEDED(result)); MOZ_ASSERT(NS_SUCCEEDED(result));
fileDeleted = true; return true;
return NS_OK;
} }
if (id.Equals(fileId)) { if (id.Equals(fileId)) {
DebugOnly<nsresult> result = RemoveNsIFile(aQuotaInfo, bodyFile); DebugOnly<nsresult> result = RemoveNsIFile(aQuotaInfo, bodyFile);
MOZ_ASSERT(NS_SUCCEEDED(result)); MOZ_ASSERT(NS_SUCCEEDED(result));
fileDeleted = true; return true;
return NS_OK;
} }
fileDeleted = false; return false;
return NS_OK;
}; };
rv = BodyTraverseFiles(aQuotaInfo, bodyDir, removeFileForId, rv = BodyTraverseFiles(aQuotaInfo, bodyDir, removeFileForId,
/* aCanRemoveFiles */ false, /* aCanRemoveFiles */ false,
@ -508,33 +506,26 @@ nsresult BodyDeleteOrphanedFiles(const QuotaInfo& aQuotaInfo, nsIFile* aBaseDir,
return rv; return rv;
} }
nsCOMPtr<nsIDirectoryEnumerator> entries;
rv = dir->GetDirectoryEntries(getter_AddRefs(entries));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// Iterate over all the intermediate morgue subdirs // Iterate over all the intermediate morgue subdirs
nsCOMPtr<nsIFile> subdir; CACHE_TRY(quota::CollectEachFile(
while (NS_SUCCEEDED(rv = entries->GetNextFile(getter_AddRefs(subdir))) && *dir,
subdir) { [&aQuotaInfo, &aKnownBodyIdList](
bool isDir = false; const nsCOMPtr<nsIFile>& subdir) -> Result<Ok, nsresult> {
rv = subdir->IsDirectory(&isDir); CACHE_TRY_INSPECT(const bool& isDir,
if (NS_WARN_IF(NS_FAILED(rv))) { MOZ_TO_RESULT_INVOKE(subdir, IsDirectory));
return rv;
}
// If a file got in here somehow, try to remove it and move on // If a file got in here somehow, try to remove it and move on
if (NS_WARN_IF(!isDir)) { if (NS_WARN_IF(!isDir)) {
DebugOnly<nsresult> result = DebugOnly<nsresult> result =
RemoveNsIFile(aQuotaInfo, subdir, /* aTrackQuota */ false); RemoveNsIFile(aQuotaInfo, subdir, /* aTrackQuota */ false);
MOZ_ASSERT(NS_SUCCEEDED(result)); MOZ_ASSERT(NS_SUCCEEDED(result));
continue; return Ok{};
} }
const auto removeOrphanedFiles = const auto removeOrphanedFiles =
[&aQuotaInfo, &aKnownBodyIdList]( [&aQuotaInfo, &aKnownBodyIdList](
nsIFile* bodyFile, const nsACString& leafName, bool& fileDeleted) { nsIFile* bodyFile,
const nsACString& leafName) -> Result<bool, nsresult> {
MOZ_DIAGNOSTIC_ASSERT(bodyFile); MOZ_DIAGNOSTIC_ASSERT(bodyFile);
// Finally, parse the uuid out of the name. If its fails to parse, // Finally, parse the uuid out of the name. If its fails to parse,
// the ignore the file. // the ignore the file.
@ -542,32 +533,25 @@ nsresult BodyDeleteOrphanedFiles(const QuotaInfo& aQuotaInfo, nsIFile* aBaseDir,
if (NS_WARN_IF(!id.Parse(leafName.BeginReading()))) { if (NS_WARN_IF(!id.Parse(leafName.BeginReading()))) {
DebugOnly<nsresult> result = RemoveNsIFile(aQuotaInfo, bodyFile); DebugOnly<nsresult> result = RemoveNsIFile(aQuotaInfo, bodyFile);
MOZ_ASSERT(NS_SUCCEEDED(result)); MOZ_ASSERT(NS_SUCCEEDED(result));
fileDeleted = true; return true;
return NS_OK;
} }
if (!aKnownBodyIdList.Contains(id)) { if (!aKnownBodyIdList.Contains(id)) {
DebugOnly<nsresult> result = RemoveNsIFile(aQuotaInfo, bodyFile); DebugOnly<nsresult> result = RemoveNsIFile(aQuotaInfo, bodyFile);
MOZ_ASSERT(NS_SUCCEEDED(result)); MOZ_ASSERT(NS_SUCCEEDED(result));
fileDeleted = true; return true;
return NS_OK;
} }
fileDeleted = false; return false;
return NS_OK;
}; };
rv = BodyTraverseFiles(aQuotaInfo, subdir, removeOrphanedFiles, CACHE_TRY(BodyTraverseFiles(aQuotaInfo, subdir, removeOrphanedFiles,
/* aCanRemoveFiles */ true, /* aCanRemoveFiles */ true,
/* aTrackQuota */ true); /* aTrackQuota */ true));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return rv; return Ok{};
}));
return NS_OK;
} }
namespace { namespace {
@ -675,23 +659,14 @@ nsresult RemoveNsIFileRecursively(const QuotaInfo& aQuotaInfo, nsIFile* aFile,
// Unfortunately, we need to traverse all the entries and delete files one by // Unfortunately, we need to traverse all the entries and delete files one by
// one to update their usages to the QuotaManager. // one to update their usages to the QuotaManager.
nsCOMPtr<nsIDirectoryEnumerator> entries; CACHE_TRY(quota::CollectEachFile(
rv = aFile->GetDirectoryEntries(getter_AddRefs(entries)); *aFile,
if (NS_WARN_IF(NS_FAILED(rv))) { [&aQuotaInfo,
return rv; &aTrackQuota](const nsCOMPtr<nsIFile>& file) -> Result<Ok, nsresult> {
} CACHE_TRY(RemoveNsIFileRecursively(aQuotaInfo, file, aTrackQuota));
nsCOMPtr<nsIFile> file; return Ok{};
while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(file)))) && }));
file) {
rv = RemoveNsIFileRecursively(aQuotaInfo, file, aTrackQuota);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// In the end, remove the folder // In the end, remove the folder
rv = aFile->Remove(/* recursive */ false); rv = aFile->Remove(/* recursive */ false);

View File

@ -33,35 +33,24 @@ nsresult BodyTraverseFiles(const QuotaInfo& aQuotaInfo, nsIFile* aBodyDir,
MOZ_DIAGNOSTIC_ASSERT(StringEndsWith(nativeLeafName, "morgue"_ns)); MOZ_DIAGNOSTIC_ASSERT(StringEndsWith(nativeLeafName, "morgue"_ns));
#endif #endif
nsCOMPtr<nsIDirectoryEnumerator> entries;
rv = aBodyDir->GetDirectoryEntries(getter_AddRefs(entries));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
bool isEmpty = true; bool isEmpty = true;
nsCOMPtr<nsIFile> file; CACHE_TRY(quota::CollectEachFile(
while (NS_SUCCEEDED(rv = entries->GetNextFile(getter_AddRefs(file))) && *aBodyDir,
file) { [&isEmpty, &aQuotaInfo, aTrackQuota, &aHandleFileFunc,
bool isDir = false; aCanRemoveFiles](const nsCOMPtr<nsIFile>& file) -> Result<Ok, nsresult> {
rv = file->IsDirectory(&isDir); CACHE_TRY_INSPECT(const bool& isDir,
if (NS_WARN_IF(NS_FAILED(rv))) { MOZ_TO_RESULT_INVOKE(file, IsDirectory));
return rv;
}
// If it's a directory somehow, try to remove it and move on // If it's a directory somehow, try to remove it and move on
if (NS_WARN_IF(isDir)) { if (NS_WARN_IF(isDir)) {
DebugOnly<nsresult> result = DebugOnly<nsresult> result = RemoveNsIFileRecursively(
RemoveNsIFileRecursively(aQuotaInfo, file, /* aTrackQuota */ false); aQuotaInfo, file, /* aTrackQuota */ false);
MOZ_ASSERT(NS_SUCCEEDED(result)); MOZ_ASSERT(NS_SUCCEEDED(result));
continue; return Ok{};
} }
nsAutoCString leafName; nsAutoCString leafName;
rv = file->GetNativeLeafName(leafName); CACHE_TRY(file->GetNativeLeafName(leafName));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// Delete all tmp files regardless of known bodies. These are all // Delete all tmp files regardless of known bodies. These are all
// considered orphans. // considered orphans.
@ -70,31 +59,27 @@ nsresult BodyTraverseFiles(const QuotaInfo& aQuotaInfo, nsIFile* aBodyDir,
DebugOnly<nsresult> result = DebugOnly<nsresult> result =
RemoveNsIFile(aQuotaInfo, file, aTrackQuota); RemoveNsIFile(aQuotaInfo, file, aTrackQuota);
MOZ_ASSERT(NS_SUCCEEDED(result)); MOZ_ASSERT(NS_SUCCEEDED(result));
continue; return Ok{};
} }
} else if (NS_WARN_IF(!StringEndsWith(leafName, ".final"_ns))) { } else if (NS_WARN_IF(!StringEndsWith(leafName, ".final"_ns))) {
// Otherwise, it must be a .final file. If its not, then try to remove it // Otherwise, it must be a .final file. If its not, then try to
// and move on // remove it and move on
DebugOnly<nsresult> result = DebugOnly<nsresult> result =
RemoveNsIFile(aQuotaInfo, file, /* aTrackQuota */ false); RemoveNsIFile(aQuotaInfo, file, /* aTrackQuota */ false);
MOZ_ASSERT(NS_SUCCEEDED(result)); MOZ_ASSERT(NS_SUCCEEDED(result));
continue; return Ok{};
} }
bool fileDeleted; CACHE_TRY_INSPECT(const bool& fileDeleted,
rv = aHandleFileFunc(file, leafName, fileDeleted); aHandleFileFunc(file, leafName));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (fileDeleted) { if (fileDeleted) {
continue; return Ok{};
} }
isEmpty = false; isEmpty = false;
}
if (NS_WARN_IF(NS_FAILED(rv))) { return Ok{};
return rv; }));
}
if (isEmpty && aCanRemoveFiles) { if (isEmpty && aCanRemoveFiles) {
DebugOnly<nsresult> result = DebugOnly<nsresult> result =

View File

@ -38,22 +38,8 @@ template <typename StepFunc>
Result<UsageInfo, nsresult> ReduceUsageInfo(nsIFile& aDir, Result<UsageInfo, nsresult> ReduceUsageInfo(nsIFile& aDir,
const Atomic<bool>& aCanceled, const Atomic<bool>& aCanceled,
const StepFunc& aStepFunc) { const StepFunc& aStepFunc) {
// XXX The following loop (including the cancellation check) is very similar CACHE_TRY_RETURN(quota::ReduceEachFileAtomicCancelable(
// to QuotaClient::GetDatabaseFilenames in dom/indexedDB/ActorsParent.cpp aDir, aCanceled, UsageInfo{},
CACHE_TRY_INSPECT(const auto& entries,
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<nsIDirectoryEnumerator>,
aDir, GetDirectoryEntries));
CACHE_TRY_RETURN(ReduceEach(
[&entries, &aCanceled]() -> Result<nsCOMPtr<nsIFile>, nsresult> {
if (aCanceled) {
return nsCOMPtr<nsIFile>{};
}
CACHE_TRY_RETURN(MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<nsIFile>, entries,
GetNextFile));
},
UsageInfo{},
[&aStepFunc](UsageInfo usageInfo, const nsCOMPtr<nsIFile>& bodyDir) [&aStepFunc](UsageInfo usageInfo, const nsCOMPtr<nsIFile>& bodyDir)
-> Result<UsageInfo, nsresult> { -> Result<UsageInfo, nsresult> {
CACHE_TRY(OkIf(!QuotaManager::IsShuttingDown()), Err(NS_ERROR_ABORT)); CACHE_TRY(OkIf(!QuotaManager::IsShuttingDown()), Err(NS_ERROR_ABORT));
@ -86,9 +72,9 @@ Result<UsageInfo, nsresult> GetBodyUsage(nsIFile& aMorgueDir,
} }
UsageInfo usageInfo; UsageInfo usageInfo;
const auto getUsage = [&usageInfo](nsIFile* bodyFile, const auto getUsage =
const nsACString& leafName, [&usageInfo](nsIFile* bodyFile,
bool& fileDeleted) -> nsresult { const nsACString& leafName) -> Result<bool, nsresult> {
MOZ_DIAGNOSTIC_ASSERT(bodyFile); MOZ_DIAGNOSTIC_ASSERT(bodyFile);
Unused << leafName; Unused << leafName;
@ -111,9 +97,7 @@ Result<UsageInfo, nsresult> GetBodyUsage(nsIFile& aMorgueDir,
// tests. Note that file usage hasn't been exposed to users yet. // tests. Note that file usage hasn't been exposed to users yet.
usageInfo += DatabaseUsageType(Some(fileSize)); usageInfo += DatabaseUsageType(Some(fileSize));
fileDeleted = false; return false;
return NS_OK;
}; };
CACHE_TRY(BodyTraverseFiles(QuotaInfo{}, bodyDir, getUsage, CACHE_TRY(BodyTraverseFiles(QuotaInfo{}, bodyDir, getUsage,
/* aCanRemoveFiles */ /* aCanRemoveFiles */

View File

@ -12650,18 +12650,10 @@ nsresult FileManager::InitDirectory(nsIFile& aDirectory, nsIFile& aDatabaseFile,
MOZ_TO_RESULT_INVOKE(journalDirectory, IsDirectory)); MOZ_TO_RESULT_INVOKE(journalDirectory, IsDirectory));
IDB_TRY(OkIf(isDirectory), NS_ERROR_FAILURE); IDB_TRY(OkIf(isDirectory), NS_ERROR_FAILURE);
IDB_TRY_INSPECT(
const auto& entries,
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<nsIDirectoryEnumerator>,
journalDirectory, GetDirectoryEntries));
bool hasJournals = false; bool hasJournals = false;
IDB_TRY(CollectEach( IDB_TRY(CollectEachFile(
[&entries] { *journalDirectory,
IDB_TRY_RETURN(MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<nsIFile>, entries,
GetNextFile));
},
[&hasJournals](const nsCOMPtr<nsIFile>& file) -> Result<Ok, nsresult> { [&hasJournals](const nsCOMPtr<nsIFile>& file) -> Result<Ok, nsresult> {
IDB_TRY_INSPECT( IDB_TRY_INSPECT(
const auto& leafName, const auto& leafName,
@ -12755,17 +12747,10 @@ Result<FileUsageType, nsresult> FileManager::GetUsage(nsIFile* aDirectory) {
return FileUsageType{}; return FileUsageType{};
} }
IDB_TRY_INSPECT(const auto& entries,
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<nsIDirectoryEnumerator>,
aDirectory, GetDirectoryEntries));
FileUsageType usage; FileUsageType usage;
IDB_TRY(CollectEach( IDB_TRY(CollectEachFile(
[&entries] { *aDirectory,
IDB_TRY_RETURN(MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<nsIFile>, entries,
GetNextFile));
},
[&usage](const nsCOMPtr<nsIFile>& file) -> Result<Ok, nsresult> { [&usage](const nsCOMPtr<nsIFile>& file) -> Result<Ok, nsresult> {
IDB_TRY_INSPECT(const auto& leafName, MOZ_TO_RESULT_INVOKE_TYPED( IDB_TRY_INSPECT(const auto& leafName, MOZ_TO_RESULT_INVOKE_TYPED(
nsString, file, GetLeafName)); nsString, file, GetLeafName));
@ -13013,16 +12998,8 @@ nsresult QuotaClient::UpgradeStorageFrom2_1To2_2(nsIFile* aDirectory) {
AssertIsOnIOThread(); AssertIsOnIOThread();
MOZ_ASSERT(aDirectory); MOZ_ASSERT(aDirectory);
IDB_TRY_INSPECT(const auto& entries, IDB_TRY(CollectEachFile(
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<nsIDirectoryEnumerator>, *aDirectory, [](const nsCOMPtr<nsIFile>& file) -> Result<Ok, nsresult> {
aDirectory, GetDirectoryEntries));
IDB_TRY(CollectEach(
[&entries] {
IDB_TRY_RETURN(MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<nsIFile>, entries,
GetNextFile));
},
[](const nsCOMPtr<nsIFile>& file) -> Result<Ok, nsresult> {
IDB_TRY_INSPECT(const auto& leafName, MOZ_TO_RESULT_INVOKE_TYPED( IDB_TRY_INSPECT(const auto& leafName, MOZ_TO_RESULT_INVOKE_TYPED(
nsString, file, GetLeafName)); nsString, file, GetLeafName));
@ -13438,21 +13415,10 @@ QuotaClient::GetDatabaseFilenames(nsIFile& aDirectory,
const AtomicBool& aCanceled) { const AtomicBool& aCanceled) {
AssertIsOnIOThread(); AssertIsOnIOThread();
IDB_TRY_INSPECT(const auto& entries,
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<nsIDirectoryEnumerator>,
&aDirectory, GetDirectoryEntries));
GetDatabaseFilenamesResult<ObsoleteFilenames> result; GetDatabaseFilenamesResult<ObsoleteFilenames> result;
IDB_TRY(CollectEach( IDB_TRY(CollectEachFileAtomicCancelable(
[&entries, &aCanceled]() -> Result<nsCOMPtr<nsIFile>, nsresult> { aDirectory, aCanceled,
if (aCanceled) {
return nsCOMPtr<nsIFile>{};
}
IDB_TRY_RETURN(MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<nsIFile>, entries,
GetNextFile));
},
[&result](const nsCOMPtr<nsIFile>& file) -> Result<Ok, nsresult> { [&result](const nsCOMPtr<nsIFile>& file) -> Result<Ok, nsresult> {
IDB_TRY_INSPECT(const auto& leafName, MOZ_TO_RESULT_INVOKE_TYPED( IDB_TRY_INSPECT(const auto& leafName, MOZ_TO_RESULT_INVOKE_TYPED(
nsString, file, GetLeafName)); nsString, file, GetLeafName));
@ -13894,21 +13860,9 @@ nsresult Maintenance::DirectoryWork() {
} }
} }
IDB_TRY_INSPECT(
const auto& persistenceDirEntries,
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<nsIDirectoryEnumerator>,
persistenceDir, GetDirectoryEntries));
if (!persistenceDirEntries) {
continue;
}
// Loop over "<origin>/idb" directories. // Loop over "<origin>/idb" directories.
IDB_TRY(CollectEach( IDB_TRY(CollectEachFile(
[&persistenceDirEntries] { *persistenceDir,
IDB_TRY_RETURN(MOZ_TO_RESULT_INVOKE_TYPED(
nsCOMPtr<nsIFile>, persistenceDirEntries, GetNextFile));
},
[this, &quotaManager, persistent, persistenceType, &idbDirName]( [this, &quotaManager, persistent, persistenceType, &idbDirName](
const nsCOMPtr<nsIFile>& originDir) -> Result<Ok, nsresult> { const nsCOMPtr<nsIFile>& originDir) -> Result<Ok, nsresult> {
if (NS_WARN_IF(QuotaClient::IsShuttingDownOnNonBackgroundThread()) || if (NS_WARN_IF(QuotaClient::IsShuttingDownOnNonBackgroundThread()) ||
@ -13982,23 +13936,11 @@ nsresult Maintenance::DirectoryWork() {
IDB_TRY(OkIf(isDirectory), Ok{}); IDB_TRY(OkIf(isDirectory), Ok{});
IDB_TRY_INSPECT(
const auto& idbDirEntries,
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<nsIDirectoryEnumerator>,
idbDir, GetDirectoryEntries));
if (!idbDirEntries) {
return Ok{};
}
nsTArray<nsString> databasePaths; nsTArray<nsString> databasePaths;
// Loop over files in the "idb" directory. // Loop over files in the "idb" directory.
IDB_TRY(CollectEach( IDB_TRY(CollectEachFile(
[&idbDirEntries] { *idbDir,
IDB_TRY_RETURN(MOZ_TO_RESULT_INVOKE_TYPED(
nsCOMPtr<nsIFile>, idbDirEntries, GetNextFile));
},
[this, &databasePaths]( [this, &databasePaths](
const nsCOMPtr<nsIFile>& idbDirFile) -> Result<Ok, nsresult> { const nsCOMPtr<nsIFile>& idbDirFile) -> Result<Ok, nsresult> {
if (NS_WARN_IF( if (NS_WARN_IF(

View File

@ -8824,21 +8824,8 @@ Result<UsageInfo, nsresult> QuotaClient::InitOrigin(
// Report unknown files in debug builds, but don't fail, just warn. // Report unknown files in debug builds, but don't fail, just warn.
#ifdef DEBUG #ifdef DEBUG
{ LS_TRY(CollectEachFileAtomicCancelable(
LS_TRY_INSPECT(const auto& directoryEntries, *directory, aCanceled,
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<nsIDirectoryEnumerator>,
directory, GetDirectoryEntries));
LS_TRY(CollectEach(
[&directoryEntries,
&aCanceled]() -> Result<nsCOMPtr<nsIFile>, nsresult> {
if (aCanceled) {
return nsCOMPtr<nsIFile>{};
}
LS_TRY_RETURN(MOZ_TO_RESULT_INVOKE_TYPED(
nsCOMPtr<nsIFile>, directoryEntries, GetNextFile));
},
[](const nsCOMPtr<nsIFile>& file) -> Result<Ok, nsresult> { [](const nsCOMPtr<nsIFile>& file) -> Result<Ok, nsresult> {
LS_TRY_INSPECT(const bool& isDirectory, LS_TRY_INSPECT(const bool& isDirectory,
MOZ_TO_RESULT_INVOKE(file, IsDirectory)); MOZ_TO_RESULT_INVOKE(file, IsDirectory));
@ -8848,8 +8835,7 @@ Result<UsageInfo, nsresult> QuotaClient::InitOrigin(
return Ok{}; return Ok{};
} }
LS_TRY_INSPECT( LS_TRY_INSPECT(const auto& leafName,
const auto& leafName,
MOZ_TO_RESULT_INVOKE_TYPED(nsString, file, GetLeafName)); MOZ_TO_RESULT_INVOKE_TYPED(nsString, file, GetLeafName));
if (leafName.Equals(kDataFileName) || if (leafName.Equals(kDataFileName) ||
@ -8863,7 +8849,6 @@ Result<UsageInfo, nsresult> QuotaClient::InitOrigin(
return Ok{}; return Ok{};
})); }));
}
#endif #endif
return res; return res;

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,7 @@
#include <utility> #include <utility>
#include "mozIStorageStatement.h" #include "mozIStorageStatement.h"
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
#include "mozilla/Atomics.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/Likely.h" #include "mozilla/Likely.h"
#include "mozilla/MacroArgs.h" #include "mozilla/MacroArgs.h"
@ -26,7 +27,9 @@
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsDebug.h" #include "nsDebug.h"
#include "nsError.h" #include "nsError.h"
#include "nsIDirectoryEnumerator.h"
#include "nsIEventTarget.h" #include "nsIEventTarget.h"
#include "nsIFile.h"
#include "nsLiteralString.h" #include "nsLiteralString.h"
#include "nsPrintfCString.h" #include "nsPrintfCString.h"
#include "nsReadableUtils.h" #include "nsReadableUtils.h"
@ -704,13 +707,6 @@ class NotNull;
mozilla::dom::quota::_key, \ mozilla::dom::quota::_key, \
mozilla::Telemetry::LABELS_QM_INIT_TELEMETRY_ERROR::_label); mozilla::Telemetry::LABELS_QM_INIT_TELEMETRY_ERROR::_label);
# define REPORT_TELEMETRY_ERR_IN_INIT(_initializing, _key, _label) \
do { \
if (_initializing) { \
REPORT_TELEMETRY_INIT_ERR(_key, _label) \
} \
} while (0)
# define RECORD_IN_NIGHTLY(_recorder, _status) \ # define RECORD_IN_NIGHTLY(_recorder, _status) \
do { \ do { \
if (NS_SUCCEEDED(_recorder)) { \ if (NS_SUCCEEDED(_recorder)) { \
@ -718,23 +714,21 @@ class NotNull;
} \ } \
} while (0) } while (0)
# define CONTINUE_IN_NIGHTLY_RETURN_IN_OTHERS(_dummy) continue # define OK_IN_NIGHTLY_PROPAGATE_IN_OTHERS \
Ok {}
# define RETURN_STATUS_OR_RESULT(_status, _rv) \ # define RETURN_STATUS_OR_RESULT(_status, _rv) \
return NS_FAILED(_status) ? _status : _rv return Err(NS_FAILED(_status) ? (_status) : (_rv))
#else #else
# define REPORT_TELEMETRY_INIT_ERR(_key, _label) \ # define REPORT_TELEMETRY_INIT_ERR(_key, _label) \
{} {}
# define REPORT_TELEMETRY_ERR_IN_INIT(_initializing, _key, _label) \
{}
# define RECORD_IN_NIGHTLY(_dummy, _status) \ # define RECORD_IN_NIGHTLY(_dummy, _status) \
{} {}
# define CONTINUE_IN_NIGHTLY_RETURN_IN_OTHERS(_rv) return _rv # define OK_IN_NIGHTLY_PROPAGATE_IN_OTHERS QM_PROPAGATE
# define RETURN_STATUS_OR_RESULT(_status, _rv) return _rv # define RETURN_STATUS_OR_RESULT(_status, _rv) return Err(_rv)
#endif #endif
class mozIStorageConnection; class mozIStorageConnection;
@ -1168,6 +1162,62 @@ auto CollectElementsWhileHasResultTyped(mozIStorageStatement& aStmt,
aStmt, std::forward<StepFunc>(aStepFunc)); aStmt, std::forward<StepFunc>(aStepFunc));
} }
namespace detail {
template <typename Cancel, typename Body>
Result<mozilla::Ok, nsresult> CollectEachFile(nsIFile& aDirectory,
const Cancel& aCancel,
const Body& aBody) {
QM_TRY_INSPECT(const auto& entries,
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<nsIDirectoryEnumerator>,
aDirectory, GetDirectoryEntries));
return CollectEach(
[&entries, &aCancel]() -> Result<nsCOMPtr<nsIFile>, nsresult> {
if (aCancel()) {
return nsCOMPtr<nsIFile>{};
}
QM_TRY_RETURN(MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<nsIFile>, entries,
GetNextFile));
},
aBody);
}
} // namespace detail
template <typename Body>
Result<mozilla::Ok, nsresult> CollectEachFile(nsIFile& aDirectory,
const Body& aBody) {
return detail::CollectEachFile(
aDirectory, [] { return false; }, aBody);
}
template <typename Body>
Result<mozilla::Ok, nsresult> CollectEachFileAtomicCancelable(
nsIFile& aDirectory, const Atomic<bool>& aCanceled, const Body& aBody) {
return detail::CollectEachFile(
aDirectory, [&aCanceled] { return static_cast<bool>(aCanceled); }, aBody);
}
template <typename T, typename Body>
auto ReduceEachFileAtomicCancelable(nsIFile& aDirectory,
const Atomic<bool>& aCanceled, T aInit,
const Body& aBody) -> Result<T, nsresult> {
QM_TRY_INSPECT(const auto& entries,
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<nsIDirectoryEnumerator>,
aDirectory, GetDirectoryEntries));
return ReduceEach(
[&entries, &aCanceled]() -> Result<nsCOMPtr<nsIFile>, nsresult> {
if (aCanceled) {
return nsCOMPtr<nsIFile>{};
}
QM_TRY_RETURN(MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<nsIFile>, entries,
GetNextFile));
},
std::move(aInit), aBody);
}
} // namespace quota } // namespace quota
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

View File

@ -1735,60 +1735,35 @@ Result<UsageInfo, nsresult> QuotaClient::GetUsageForOrigin(
DebugOnly<bool> exists; DebugOnly<bool> exists;
MOZ_ASSERT(NS_SUCCEEDED(directory->Exists(&exists)) && exists); MOZ_ASSERT(NS_SUCCEEDED(directory->Exists(&exists)) && exists);
nsCOMPtr<nsIDirectoryEnumerator> directoryEntries; SDB_TRY_RETURN(ReduceEachFileAtomicCancelable(
rv = directory->GetDirectoryEntries(getter_AddRefs(directoryEntries)); *directory, aCanceled, UsageInfo{},
if (NS_WARN_IF(NS_FAILED(rv))) { [](UsageInfo usageInfo,
return Err(rv); const nsCOMPtr<nsIFile>& file) -> Result<UsageInfo, nsresult> {
} SDB_TRY_INSPECT(const bool& isDirectory,
MOZ_TO_RESULT_INVOKE(file, IsDirectory));
UsageInfo res;
while (!aCanceled) {
nsCOMPtr<nsIFile> file;
rv = directoryEntries->GetNextFile(getter_AddRefs(file));
if (NS_WARN_IF(NS_FAILED(rv))) {
return Err(rv);
}
if (!file) {
break;
}
bool isDirectory;
rv = file->IsDirectory(&isDirectory);
if (NS_WARN_IF(NS_FAILED(rv))) {
return Err(rv);
}
if (isDirectory) { if (isDirectory) {
Unused << WARN_IF_FILE_IS_UNKNOWN(*file); Unused << WARN_IF_FILE_IS_UNKNOWN(*file);
continue; return usageInfo;
} }
nsString leafName; nsString leafName;
rv = file->GetLeafName(leafName); SDB_TRY(file->GetLeafName(leafName));
if (NS_WARN_IF(NS_FAILED(rv))) {
return Err(rv);
}
if (StringEndsWith(leafName, kSDBSuffix)) { if (StringEndsWith(leafName, kSDBSuffix)) {
int64_t fileSize; SDB_TRY_INSPECT(const int64_t& fileSize,
rv = file->GetFileSize(&fileSize); MOZ_TO_RESULT_INVOKE(file, GetFileSize));
if (NS_WARN_IF(NS_FAILED(rv))) {
return Err(rv);
}
MOZ_ASSERT(fileSize >= 0); MOZ_ASSERT(fileSize >= 0);
res += DatabaseUsageType(Some(uint64_t(fileSize))); return usageInfo +
UsageInfo{DatabaseUsageType(Some(uint64_t(fileSize)))};
continue;
} }
Unused << WARN_IF_FILE_IS_UNKNOWN(*file); Unused << WARN_IF_FILE_IS_UNKNOWN(*file);
}
return res; return usageInfo;
}));
} }
void QuotaClient::OnOriginClearCompleted(PersistenceType aPersistenceType, void QuotaClient::OnOriginClearCompleted(PersistenceType aPersistenceType,