зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1687321 - Use GetDirEntryKind instead of IsDirectory when iterating over directory entries in dom/cache. r=dom-workers-and-storage-reviewers,janv
Differential Revision: https://phabricator.services.mozilla.com/D103763
This commit is contained in:
Родитель
3521cdde51
Коммит
26725b587f
|
@ -30,6 +30,8 @@ using mozilla::dom::quota::Client;
|
|||
using mozilla::dom::quota::CloneFileAndAppend;
|
||||
using mozilla::dom::quota::FileInputStream;
|
||||
using mozilla::dom::quota::FileOutputStream;
|
||||
using mozilla::dom::quota::GetDirEntryKind;
|
||||
using mozilla::dom::quota::nsIFileKind;
|
||||
using mozilla::dom::quota::PERSISTENCE_TYPE_DEFAULT;
|
||||
using mozilla::dom::quota::QuotaManager;
|
||||
using mozilla::dom::quota::QuotaObject;
|
||||
|
@ -346,41 +348,52 @@ nsresult BodyDeleteOrphanedFiles(const QuotaInfo& aQuotaInfo, nsIFile& aBaseDir,
|
|||
*dir,
|
||||
[&aQuotaInfo, &aKnownBodyIdList](
|
||||
const nsCOMPtr<nsIFile>& subdir) -> Result<Ok, nsresult> {
|
||||
CACHE_TRY_INSPECT(const bool& isDir,
|
||||
MOZ_TO_RESULT_INVOKE(subdir, IsDirectory));
|
||||
CACHE_TRY_INSPECT(const auto& dirEntryKind, GetDirEntryKind(*subdir));
|
||||
|
||||
// If a file got in here somehow, try to remove it and move on
|
||||
CACHE_TRY(OkIf(isDir), Ok{}, ([&aQuotaInfo, &subdir](const auto&) {
|
||||
DebugOnly<nsresult> result = RemoveNsIFile(
|
||||
aQuotaInfo, *subdir, /* aTrackQuota */ false);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(result));
|
||||
}));
|
||||
switch (dirEntryKind) {
|
||||
case nsIFileKind::ExistsAsDirectory: {
|
||||
const auto removeOrphanedFiles =
|
||||
[&aQuotaInfo, &aKnownBodyIdList](
|
||||
nsIFile& bodyFile,
|
||||
const nsACString& leafName) -> Result<bool, nsresult> {
|
||||
// Finally, parse the uuid out of the name. If it fails to parse,
|
||||
// then ignore the file.
|
||||
auto cleanup = MakeScopeExit([&aQuotaInfo, &bodyFile] {
|
||||
DebugOnly<nsresult> result =
|
||||
RemoveNsIFile(aQuotaInfo, bodyFile);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(result));
|
||||
});
|
||||
|
||||
const auto removeOrphanedFiles =
|
||||
[&aQuotaInfo, &aKnownBodyIdList](
|
||||
nsIFile& bodyFile,
|
||||
const nsACString& leafName) -> Result<bool, nsresult> {
|
||||
// Finally, parse the uuid out of the name. If it fails to parse,
|
||||
// then ignore the file.
|
||||
auto cleanup = MakeScopeExit([&aQuotaInfo, &bodyFile] {
|
||||
DebugOnly<nsresult> result = RemoveNsIFile(aQuotaInfo, bodyFile);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(result));
|
||||
});
|
||||
nsID id;
|
||||
CACHE_TRY(OkIf(id.Parse(leafName.BeginReading())), true);
|
||||
|
||||
nsID id;
|
||||
CACHE_TRY(OkIf(id.Parse(leafName.BeginReading())), true);
|
||||
if (!aKnownBodyIdList.Contains(id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!aKnownBodyIdList.Contains(id)) {
|
||||
return true;
|
||||
cleanup.release();
|
||||
|
||||
return false;
|
||||
};
|
||||
CACHE_TRY(BodyTraverseFiles(aQuotaInfo, *subdir,
|
||||
removeOrphanedFiles,
|
||||
/* aCanRemoveFiles */ true,
|
||||
/* aTrackQuota */ true));
|
||||
break;
|
||||
}
|
||||
|
||||
cleanup.release();
|
||||
|
||||
return false;
|
||||
};
|
||||
CACHE_TRY(BodyTraverseFiles(aQuotaInfo, *subdir, removeOrphanedFiles,
|
||||
/* aCanRemoveFiles */ true,
|
||||
/* aTrackQuota */ true));
|
||||
case nsIFileKind::ExistsAsFile: {
|
||||
// If a file got in here somehow, try to remove it and move on
|
||||
DebugOnly<nsresult> result =
|
||||
RemoveNsIFile(aQuotaInfo, *subdir, /* aTrackQuota */ false);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(result));
|
||||
break;
|
||||
}
|
||||
|
||||
case nsIFileKind::DoesNotExist:
|
||||
// Ignore files that got removed externally while iterating.
|
||||
break;
|
||||
}
|
||||
|
||||
return Ok{};
|
||||
}));
|
||||
|
@ -440,32 +453,35 @@ bool MarkerFileExists(const QuotaInfo& aQuotaInfo) {
|
|||
|
||||
nsresult RemoveNsIFileRecursively(const QuotaInfo& aQuotaInfo, nsIFile& aFile,
|
||||
const bool aTrackQuota) {
|
||||
CACHE_TRY_INSPECT(const Maybe<bool>& maybeIsDirectory,
|
||||
MOZ_TO_RESULT_INVOKE(aFile, IsDirectory)
|
||||
.map(Some<bool>)
|
||||
.orElse(MapNotFoundToDefault<Maybe<bool>>));
|
||||
if (!maybeIsDirectory) {
|
||||
return NS_OK;
|
||||
CACHE_TRY_INSPECT(const auto& dirEntryKind, GetDirEntryKind(aFile));
|
||||
|
||||
switch (dirEntryKind) {
|
||||
case nsIFileKind::ExistsAsDirectory:
|
||||
// Unfortunately, we need to traverse all the entries and delete files one
|
||||
// by
|
||||
// one to update their usages to the QuotaManager.
|
||||
CACHE_TRY(quota::CollectEachFile(
|
||||
aFile,
|
||||
[&aQuotaInfo, &aTrackQuota](
|
||||
const nsCOMPtr<nsIFile>& file) -> Result<Ok, nsresult> {
|
||||
CACHE_TRY(RemoveNsIFileRecursively(aQuotaInfo, *file, aTrackQuota));
|
||||
|
||||
return Ok{};
|
||||
}));
|
||||
|
||||
// In the end, remove the folder
|
||||
CACHE_TRY(aFile.Remove(/* recursive */ false));
|
||||
|
||||
break;
|
||||
|
||||
case nsIFileKind::ExistsAsFile:
|
||||
return RemoveNsIFile(aQuotaInfo, aFile, aTrackQuota);
|
||||
|
||||
case nsIFileKind::DoesNotExist:
|
||||
// Ignore files that got removed externally while iterating.
|
||||
break;
|
||||
}
|
||||
|
||||
if (!maybeIsDirectory.value()) {
|
||||
return RemoveNsIFile(aQuotaInfo, aFile, aTrackQuota);
|
||||
}
|
||||
|
||||
// Unfortunately, we need to traverse all the entries and delete files one by
|
||||
// one to update their usages to the QuotaManager.
|
||||
CACHE_TRY(quota::CollectEachFile(
|
||||
aFile,
|
||||
[&aQuotaInfo,
|
||||
&aTrackQuota](const nsCOMPtr<nsIFile>& file) -> Result<Ok, nsresult> {
|
||||
CACHE_TRY(RemoveNsIFileRecursively(aQuotaInfo, *file, aTrackQuota));
|
||||
|
||||
return Ok{};
|
||||
}));
|
||||
|
||||
// In the end, remove the folder
|
||||
CACHE_TRY(aFile.Remove(/* recursive */ false));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,46 +38,56 @@ nsresult BodyTraverseFiles(const QuotaInfo& aQuotaInfo, nsIFile& aBodyDir,
|
|||
aBodyDir,
|
||||
[&isEmpty, &aQuotaInfo, aTrackQuota, &aHandleFileFunc,
|
||||
aCanRemoveFiles](const nsCOMPtr<nsIFile>& file) -> Result<Ok, nsresult> {
|
||||
CACHE_TRY_INSPECT(const bool& isDir,
|
||||
MOZ_TO_RESULT_INVOKE(file, IsDirectory));
|
||||
CACHE_TRY_INSPECT(const auto& dirEntryKind,
|
||||
quota::GetDirEntryKind(*file));
|
||||
|
||||
// If it's a directory somehow, try to remove it and move on
|
||||
CACHE_TRY(OkIf(!isDir), Ok{}, ([&aQuotaInfo, &file](const auto&) {
|
||||
DebugOnly<nsresult> result = RemoveNsIFileRecursively(
|
||||
aQuotaInfo, *file, /* aTrackQuota */ false);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(result));
|
||||
}));
|
||||
|
||||
nsAutoCString leafName;
|
||||
CACHE_TRY(file->GetNativeLeafName(leafName));
|
||||
|
||||
// Delete all tmp files regardless of known bodies. These are all
|
||||
// considered orphans.
|
||||
if (StringEndsWith(leafName, ".tmp"_ns)) {
|
||||
if (aCanRemoveFiles) {
|
||||
DebugOnly<nsresult> result =
|
||||
RemoveNsIFile(aQuotaInfo, *file, aTrackQuota);
|
||||
switch (dirEntryKind) {
|
||||
case quota::nsIFileKind::ExistsAsDirectory: {
|
||||
// If it's a directory somehow, try to remove it and move on
|
||||
DebugOnly<nsresult> result = RemoveNsIFileRecursively(
|
||||
aQuotaInfo, *file, /* aTrackQuota */ false);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(result));
|
||||
return Ok{};
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
CACHE_TRY(OkIf(StringEndsWith(leafName, ".final"_ns)), Ok{},
|
||||
([&aQuotaInfo, &file](const auto&) {
|
||||
// Otherwise, it must be a .final file. If its not, then
|
||||
// try to remove it and move on
|
||||
DebugOnly<nsresult> result = RemoveNsIFile(
|
||||
aQuotaInfo, *file, /* aTrackQuota */ false);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(result));
|
||||
}));
|
||||
}
|
||||
|
||||
CACHE_TRY_INSPECT(const bool& fileDeleted,
|
||||
aHandleFileFunc(*file, leafName));
|
||||
if (fileDeleted) {
|
||||
return Ok{};
|
||||
}
|
||||
case quota::nsIFileKind::ExistsAsFile: {
|
||||
nsAutoCString leafName;
|
||||
CACHE_TRY(file->GetNativeLeafName(leafName));
|
||||
|
||||
isEmpty.EnsureFlipped();
|
||||
// Delete all tmp files regardless of known bodies. These are all
|
||||
// considered orphans.
|
||||
if (StringEndsWith(leafName, ".tmp"_ns)) {
|
||||
if (aCanRemoveFiles) {
|
||||
DebugOnly<nsresult> result =
|
||||
RemoveNsIFile(aQuotaInfo, *file, aTrackQuota);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(result));
|
||||
return Ok{};
|
||||
}
|
||||
} else {
|
||||
CACHE_TRY(OkIf(StringEndsWith(leafName, ".final"_ns)), Ok{},
|
||||
([&aQuotaInfo, &file](const auto&) {
|
||||
// Otherwise, it must be a .final file. If its not,
|
||||
// then try to remove it and move on
|
||||
DebugOnly<nsresult> result = RemoveNsIFile(
|
||||
aQuotaInfo, *file, /* aTrackQuota */ false);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(result));
|
||||
}));
|
||||
}
|
||||
|
||||
CACHE_TRY_INSPECT(const bool& fileDeleted,
|
||||
aHandleFileFunc(*file, leafName));
|
||||
if (fileDeleted) {
|
||||
return Ok{};
|
||||
}
|
||||
|
||||
isEmpty.EnsureFlipped();
|
||||
break;
|
||||
}
|
||||
|
||||
case quota::nsIFileKind::DoesNotExist:
|
||||
// Ignore files that got removed externally while iterating.
|
||||
break;
|
||||
}
|
||||
|
||||
return Ok{};
|
||||
}));
|
||||
|
|
|
@ -415,44 +415,52 @@ Result<UsageInfo, nsresult> CacheQuotaClient::GetUsageForOriginInternal(
|
|||
const auto& leafName,
|
||||
MOZ_TO_RESULT_INVOKE_TYPED(nsAutoString, file, GetLeafName));
|
||||
|
||||
CACHE_TRY_INSPECT(const bool& isDir,
|
||||
MOZ_TO_RESULT_INVOKE(file, IsDirectory));
|
||||
CACHE_TRY_INSPECT(const auto& dirEntryKind, GetDirEntryKind(*file));
|
||||
|
||||
if (isDir) {
|
||||
if (leafName.EqualsLiteral("morgue")) {
|
||||
CACHE_TRY_RETURN(GetBodyUsage(*file, aCanceled, aInitializing));
|
||||
} else {
|
||||
NS_WARNING("Unknown Cache directory found!");
|
||||
}
|
||||
switch (dirEntryKind) {
|
||||
case nsIFileKind::ExistsAsDirectory:
|
||||
if (leafName.EqualsLiteral("morgue")) {
|
||||
CACHE_TRY_RETURN(
|
||||
GetBodyUsage(*file, aCanceled, aInitializing));
|
||||
} else {
|
||||
NS_WARNING("Unknown Cache directory found!");
|
||||
}
|
||||
|
||||
return UsageInfo{};
|
||||
break;
|
||||
|
||||
case nsIFileKind::ExistsAsFile:
|
||||
// Ignore transient sqlite files and marker files
|
||||
if (leafName.EqualsLiteral("caches.sqlite-journal") ||
|
||||
leafName.EqualsLiteral("caches.sqlite-shm") ||
|
||||
leafName.Find("caches.sqlite-mj"_ns, false, 0, 0) == 0 ||
|
||||
leafName.EqualsLiteral("context_open.marker")) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (leafName.Equals(kCachesSQLiteFilename) ||
|
||||
leafName.EqualsLiteral("caches.sqlite-wal")) {
|
||||
CACHE_TRY_INSPECT(const int64_t& fileSize,
|
||||
MOZ_TO_RESULT_INVOKE(file, GetFileSize));
|
||||
MOZ_DIAGNOSTIC_ASSERT(fileSize >= 0);
|
||||
|
||||
return UsageInfo{DatabaseUsageType(Some(fileSize))};
|
||||
}
|
||||
|
||||
// Ignore directory padding file
|
||||
if (leafName.EqualsLiteral(PADDING_FILE_NAME) ||
|
||||
leafName.EqualsLiteral(PADDING_TMP_FILE_NAME)) {
|
||||
break;
|
||||
}
|
||||
|
||||
NS_WARNING("Unknown Cache file found!");
|
||||
|
||||
break;
|
||||
|
||||
case nsIFileKind::DoesNotExist:
|
||||
// Ignore files that got removed externally while iterating.
|
||||
break;
|
||||
}
|
||||
|
||||
// Ignore transient sqlite files and marker files
|
||||
if (leafName.EqualsLiteral("caches.sqlite-journal") ||
|
||||
leafName.EqualsLiteral("caches.sqlite-shm") ||
|
||||
leafName.Find("caches.sqlite-mj"_ns, false, 0, 0) == 0 ||
|
||||
leafName.EqualsLiteral("context_open.marker")) {
|
||||
return UsageInfo{};
|
||||
}
|
||||
|
||||
if (leafName.Equals(kCachesSQLiteFilename) ||
|
||||
leafName.EqualsLiteral("caches.sqlite-wal")) {
|
||||
CACHE_TRY_INSPECT(const int64_t& fileSize,
|
||||
MOZ_TO_RESULT_INVOKE(file, GetFileSize));
|
||||
MOZ_DIAGNOSTIC_ASSERT(fileSize >= 0);
|
||||
|
||||
return UsageInfo{DatabaseUsageType(Some(fileSize))};
|
||||
}
|
||||
|
||||
// Ignore directory padding file
|
||||
if (leafName.EqualsLiteral(PADDING_FILE_NAME) ||
|
||||
leafName.EqualsLiteral(PADDING_TMP_FILE_NAME)) {
|
||||
return UsageInfo{};
|
||||
}
|
||||
|
||||
NS_WARNING("Unknown Cache file found!");
|
||||
|
||||
return UsageInfo{};
|
||||
}));
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче