mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Backed out changeset 2a3316bd2409 (bug 1686191) for causing bustages on QuotaCommon.h. CLOSED TREE
This commit is contained in:
parent
779fd20cc0
commit
9fc0210ad3
6
dom/cache/CacheParent.cpp
vendored
6
dom/cache/CacheParent.cpp
vendored
@ -57,8 +57,10 @@ mozilla::ipc::IPCResult CacheParent::RecvPCacheOpConstructor(
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult CacheParent::RecvTeardown() {
|
||||
// If child process is gone, warn and allow actor to clean up normally
|
||||
QM_WARNONLY_TRY(OkIf(Send__delete__(this)));
|
||||
if (!Send__delete__(this)) {
|
||||
// child process is gone, warn and allow actor to clean up normally
|
||||
NS_WARNING("Cache failed to send delete.");
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
6
dom/cache/CacheStorageParent.cpp
vendored
6
dom/cache/CacheStorageParent.cpp
vendored
@ -99,8 +99,10 @@ mozilla::ipc::IPCResult CacheStorageParent::RecvPCacheOpConstructor(
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult CacheStorageParent::RecvTeardown() {
|
||||
// If child process is gone, warn and allow actor to clean up normally
|
||||
QM_WARNONLY_TRY(OkIf(Send__delete__(this)));
|
||||
if (!Send__delete__(this)) {
|
||||
// child process is gone, warn and allow actor to clean up normally
|
||||
NS_WARNING("CacheStorage failed to delete actor.");
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
8
dom/cache/CacheStreamControlParent.cpp
vendored
8
dom/cache/CacheStreamControlParent.cpp
vendored
@ -145,9 +145,11 @@ void CacheStreamControlParent::CloseAll() {
|
||||
|
||||
void CacheStreamControlParent::Shutdown() {
|
||||
NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
|
||||
|
||||
// If child process is gone, warn and allow actor to clean up normally
|
||||
QM_WARNONLY_TRY(OkIf(Send__delete__(this)));
|
||||
if (!Send__delete__(this)) {
|
||||
// child process is gone, allow actor to be destroyed normally
|
||||
NS_WARNING("Cache failed to delete stream actor.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void CacheStreamControlParent::NotifyCloseAll() {
|
||||
|
15
dom/cache/DBAction.cpp
vendored
15
dom/cache/DBAction.cpp
vendored
@ -172,13 +172,12 @@ Result<nsCOMPtr<mozIStorageConnection>, nsresult> OpenDBConnection(
|
||||
|
||||
CACHE_TRY_UNWRAP(
|
||||
auto conn,
|
||||
QM_OR_ELSE_WARN(
|
||||
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<mozIStorageConnection>,
|
||||
storageService, OpenDatabaseWithFileURL,
|
||||
dbFileUrl, ""_ns),
|
||||
([&aQuotaInfo, &aDBFile, &storageService,
|
||||
&dbFileUrl](const nsresult rv)
|
||||
-> Result<nsCOMPtr<mozIStorageConnection>, nsresult> {
|
||||
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<mozIStorageConnection>,
|
||||
storageService, OpenDatabaseWithFileURL,
|
||||
dbFileUrl, ""_ns)
|
||||
.orElse([&aQuotaInfo, &aDBFile, &storageService,
|
||||
&dbFileUrl](const nsresult rv)
|
||||
-> Result<nsCOMPtr<mozIStorageConnection>, nsresult> {
|
||||
if (IsDatabaseCorruptionError(rv)) {
|
||||
NS_WARNING(
|
||||
"Cache database corrupted. Recreating empty database.");
|
||||
@ -192,7 +191,7 @@ Result<nsCOMPtr<mozIStorageConnection>, nsresult> OpenDBConnection(
|
||||
OpenDatabaseWithFileURL, dbFileUrl, ""_ns));
|
||||
}
|
||||
return Err(rv);
|
||||
})));
|
||||
}));
|
||||
|
||||
// Check the schema to make sure it is not too old.
|
||||
CACHE_TRY_INSPECT(const int32_t& schemaVersion,
|
||||
|
24
dom/cache/DBSchema.cpp
vendored
24
dom/cache/DBSchema.cpp
vendored
@ -421,18 +421,16 @@ class MOZ_RAII AutoDisableForeignKeyChecking {
|
||||
MOZ_TO_RESULT_INVOKE(*state, GetInt32, 0), QM_VOID);
|
||||
|
||||
if (mode) {
|
||||
QM_WARNONLY_TRY(
|
||||
ToResult(mConn->ExecuteSimpleSQL("PRAGMA foreign_keys = OFF;"_ns))
|
||||
.andThen([this](const auto) -> Result<Ok, nsresult> {
|
||||
mForeignKeyCheckingDisabled = true;
|
||||
return Ok{};
|
||||
}));
|
||||
CACHE_TRY(mConn->ExecuteSimpleSQL("PRAGMA foreign_keys = OFF;"_ns),
|
||||
QM_VOID);
|
||||
mForeignKeyCheckingDisabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
~AutoDisableForeignKeyChecking() {
|
||||
if (mForeignKeyCheckingDisabled) {
|
||||
QM_WARNONLY_TRY(mConn->ExecuteSimpleSQL("PRAGMA foreign_keys = ON;"_ns));
|
||||
CACHE_TRY(mConn->ExecuteSimpleSQL("PRAGMA foreign_keys = ON;"_ns),
|
||||
QM_VOID);
|
||||
}
|
||||
}
|
||||
|
||||
@ -554,8 +552,16 @@ nsresult InitializeConnection(mozIStorageConnection& aConn) {
|
||||
kPageSize)));
|
||||
|
||||
// Limit fragmentation by growing the database by many pages at once.
|
||||
QM_TRY(QM_OR_ELSE_WARN(ToResult(aConn.SetGrowthIncrement(kGrowthSize, ""_ns)),
|
||||
ErrToDefaultOkOrErr<NS_ERROR_FILE_TOO_BIG>));
|
||||
CACHE_TRY(
|
||||
ToResult(aConn.SetGrowthIncrement(kGrowthSize, ""_ns))
|
||||
.orElse([](const nsresult rv) -> Result<Ok, nsresult> {
|
||||
if (rv == NS_ERROR_FILE_TOO_BIG) {
|
||||
NS_WARNING(
|
||||
"Not enough disk space to set sqlite growth increment.");
|
||||
return Ok{};
|
||||
}
|
||||
return Err(rv);
|
||||
}));
|
||||
|
||||
// Enable WAL journaling. This must be performed in a separate transaction
|
||||
// after changing the page_size and enabling auto_vacuum.
|
||||
|
43
dom/cache/FileUtils.cpp
vendored
43
dom/cache/FileUtils.cpp
vendored
@ -89,9 +89,8 @@ Result<NotNull<nsCOMPtr<nsIFile>>, nsresult> BodyGetCacheDir(nsIFile& aBaseDir,
|
||||
// the name of the sub-directory.
|
||||
CACHE_TRY(cacheDir->Append(IntToString(aId.m3[7])));
|
||||
|
||||
QM_TRY(
|
||||
QM_OR_ELSE_WARN(ToResult(cacheDir->Create(nsIFile::DIRECTORY_TYPE, 0755)),
|
||||
ErrToDefaultOkOrErr<NS_ERROR_FILE_ALREADY_EXISTS>));
|
||||
CACHE_TRY(ToResult(cacheDir->Create(nsIFile::DIRECTORY_TYPE, 0755))
|
||||
.orElse(ErrToDefaultOkOrErr<NS_ERROR_FILE_ALREADY_EXISTS, Ok>));
|
||||
|
||||
return WrapNotNullUnchecked(std::move(cacheDir));
|
||||
}
|
||||
@ -102,9 +101,8 @@ nsresult BodyCreateDir(nsIFile& aBaseDir) {
|
||||
CACHE_TRY_INSPECT(const auto& bodyDir,
|
||||
CloneFileAndAppend(aBaseDir, kMorgueDirectory));
|
||||
|
||||
QM_TRY(
|
||||
QM_OR_ELSE_WARN(ToResult(bodyDir->Create(nsIFile::DIRECTORY_TYPE, 0755)),
|
||||
ErrToDefaultOkOrErr<NS_ERROR_FILE_ALREADY_EXISTS>));
|
||||
CACHE_TRY(ToResult(bodyDir->Create(nsIFile::DIRECTORY_TYPE, 0755))
|
||||
.orElse(ErrToDefaultOkOrErr<NS_ERROR_FILE_ALREADY_EXISTS, Ok>));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -165,7 +163,7 @@ Result<std::pair<nsID, nsCOMPtr<nsISupports>>, nsresult> BodyStartWriteStream(
|
||||
}
|
||||
|
||||
void BodyCancelWrite(nsISupports& aCopyContext) {
|
||||
QM_WARNONLY_TRY(NS_CancelAsyncCopy(&aCopyContext, NS_ERROR_ABORT));
|
||||
CACHE_TRY(NS_CancelAsyncCopy(&aCopyContext, NS_ERROR_ABORT), QM_VOID);
|
||||
|
||||
// TODO The partially written file must be cleaned up after the async copy
|
||||
// makes its callback.
|
||||
@ -434,9 +432,8 @@ Result<nsCOMPtr<nsIFile>, nsresult> GetMarkerFileHandle(
|
||||
nsresult CreateMarkerFile(const QuotaInfo& aQuotaInfo) {
|
||||
CACHE_TRY_INSPECT(const auto& marker, GetMarkerFileHandle(aQuotaInfo));
|
||||
|
||||
QM_TRY(
|
||||
QM_OR_ELSE_WARN(ToResult(marker->Create(nsIFile::NORMAL_FILE_TYPE, 0644)),
|
||||
MapAlreadyExistsToDefault));
|
||||
CACHE_TRY(ToResult(marker->Create(nsIFile::NORMAL_FILE_TYPE, 0644))
|
||||
.orElse(MapAlreadyExistsToDefault));
|
||||
|
||||
// Note, we don't need to fsync here. We only care about actually
|
||||
// writing the marker if later modifications to the Cache are
|
||||
@ -506,11 +503,10 @@ nsresult RemoveNsIFile(const QuotaInfo& aQuotaInfo, nsIFile& aFile,
|
||||
const bool aTrackQuota) {
|
||||
int64_t fileSize = 0;
|
||||
if (aTrackQuota) {
|
||||
CACHE_TRY_INSPECT(
|
||||
const auto& maybeFileSize,
|
||||
QM_OR_ELSE_WARN(
|
||||
MOZ_TO_RESULT_INVOKE(aFile, GetFileSize).map(Some<int64_t>),
|
||||
MapNotFoundToDefault<Maybe<int64_t>>));
|
||||
CACHE_TRY_INSPECT(const auto& maybeFileSize,
|
||||
MOZ_TO_RESULT_INVOKE(aFile, GetFileSize)
|
||||
.map(Some<int64_t>)
|
||||
.orElse(MapNotFoundToDefault<Maybe<int64_t>>));
|
||||
|
||||
if (!maybeFileSize) {
|
||||
return NS_OK;
|
||||
@ -519,8 +515,8 @@ nsresult RemoveNsIFile(const QuotaInfo& aQuotaInfo, nsIFile& aFile,
|
||||
fileSize = *maybeFileSize;
|
||||
}
|
||||
|
||||
QM_TRY(QM_OR_ELSE_WARN(ToResult(aFile.Remove(/* recursive */ false)),
|
||||
MapNotFoundToDefault<>));
|
||||
CACHE_TRY(ToResult(aFile.Remove(/* recursive */ false))
|
||||
.orElse(MapNotFoundToDefault<>));
|
||||
|
||||
if (fileSize > 0) {
|
||||
MOZ_ASSERT(aTrackQuota);
|
||||
@ -591,11 +587,10 @@ nsresult LockedUpdateDirectoryPaddingFile(nsIFile& aBaseDir,
|
||||
|
||||
const auto directoryPaddingGetResult =
|
||||
aTemporaryFileExist ? Maybe<int64_t>{} : [&aBaseDir] {
|
||||
CACHE_TRY_RETURN(
|
||||
QM_OR_ELSE_WARN(
|
||||
LockedDirectoryPaddingGet(aBaseDir).map(Some<int64_t>),
|
||||
MapNotFoundToDefault<Maybe<int64_t>>),
|
||||
Maybe<int64_t>{});
|
||||
CACHE_TRY_RETURN(LockedDirectoryPaddingGet(aBaseDir)
|
||||
.map(Some<int64_t>)
|
||||
.orElse(MapNotFoundToDefault<Maybe<int64_t>>),
|
||||
Maybe<int64_t>{});
|
||||
}();
|
||||
|
||||
CACHE_TRY_INSPECT(
|
||||
@ -713,8 +708,8 @@ nsresult LockedDirectoryPaddingDeleteFile(nsIFile& aBaseDir,
|
||||
? nsLiteralString(PADDING_TMP_FILE_NAME)
|
||||
: nsLiteralString(PADDING_FILE_NAME)));
|
||||
|
||||
QM_TRY(QM_OR_ELSE_WARN(ToResult(file->Remove(/* recursive */ false)),
|
||||
MapNotFoundToDefault<>));
|
||||
CACHE_TRY(ToResult(file->Remove(/* recursive */ false))
|
||||
.orElse(MapNotFoundToDefault<>));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
11
dom/cache/Manager.cpp
vendored
11
dom/cache/Manager.cpp
vendored
@ -140,10 +140,13 @@ class SetupAction final : public SyncDBAction {
|
||||
// failure, but if we entered it and RestorePaddingFile succeeded, we
|
||||
// would have returned NS_OK. Now, we will never propagate a
|
||||
// MaybeUpdatePaddingFile failure.
|
||||
QM_WARNONLY_TRY(
|
||||
MaybeUpdatePaddingFile(aDBDir, aConn, /* aIncreaceSize */ 0,
|
||||
overallDeletedPaddingSize.value(),
|
||||
[&trans]() { return trans.Commit(); }));
|
||||
[&] {
|
||||
CACHE_TRY(MaybeUpdatePaddingFile(
|
||||
aDBDir, aConn, /* aIncreaceSize */ 0,
|
||||
overallDeletedPaddingSize.value(),
|
||||
[&trans]() mutable { return trans.Commit(); }),
|
||||
QM_VOID);
|
||||
}();
|
||||
}
|
||||
|
||||
if (DirectoryPaddingFileExists(*aDBDir, DirPaddingFile::TMP_FILE) ||
|
||||
|
8
dom/cache/PrincipalVerifier.cpp
vendored
8
dom/cache/PrincipalVerifier.cpp
vendored
@ -177,8 +177,12 @@ void PrincipalVerifier::DispatchToInitiatingThread(nsresult aRv) {
|
||||
// This will result in a new CacheStorage object delaying operations until
|
||||
// shutdown completes and the browser goes away. This is as graceful as
|
||||
// we can get here.
|
||||
QM_WARNONLY_TRY(
|
||||
mInitiatingEventTarget->Dispatch(this, nsIThread::DISPATCH_NORMAL));
|
||||
nsresult rv =
|
||||
mInitiatingEventTarget->Dispatch(this, nsIThread::DISPATCH_NORMAL);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING(
|
||||
"Cache unable to complete principal verification due to shutdown.");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom::cache
|
||||
|
31
dom/cache/QuotaClientImpl.h
vendored
31
dom/cache/QuotaClientImpl.h
vendored
@ -94,24 +94,23 @@ class CacheQuotaClient final : public quota::Client {
|
||||
// the next action recalculate the padding size.
|
||||
CACHE_TRY(aCommitHook());
|
||||
|
||||
QM_TRY(QM_OR_ELSE_WARN(
|
||||
ToResult(LockedDirectoryPaddingFinalizeWrite(aBaseDir)),
|
||||
([&aBaseDir](const nsresult) -> Result<Ok, nsresult> {
|
||||
// Force restore file next time.
|
||||
Unused << LockedDirectoryPaddingDeleteFile(aBaseDir,
|
||||
DirPaddingFile::FILE);
|
||||
CACHE_TRY(
|
||||
ToResult(LockedDirectoryPaddingFinalizeWrite(aBaseDir))
|
||||
.orElse([&aBaseDir](const nsresult) -> Result<Ok, nsresult> {
|
||||
// Force restore file next time.
|
||||
Unused << LockedDirectoryPaddingDeleteFile(
|
||||
aBaseDir, DirPaddingFile::FILE);
|
||||
|
||||
// Ensure that we are able to force the padding file to
|
||||
// be restored.
|
||||
MOZ_ASSERT(
|
||||
DirectoryPaddingFileExists(aBaseDir, DirPaddingFile::TMP_FILE));
|
||||
// Ensure that we are able to force the padding file to be
|
||||
// restored.
|
||||
MOZ_ASSERT(DirectoryPaddingFileExists(
|
||||
aBaseDir, DirPaddingFile::TMP_FILE));
|
||||
|
||||
// Since both the body file and header have been stored
|
||||
// in the file-system, just make the action be resolve
|
||||
// and let the padding file be restored in the next
|
||||
// action.
|
||||
return Ok{};
|
||||
})));
|
||||
// Since both the body file and header have been stored in the
|
||||
// file-system, just make the action be resolve and let the
|
||||
// padding file be restored in the next action.
|
||||
return Ok{};
|
||||
}));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -679,9 +679,9 @@ nsresult SetDefaultPragmas(mozIStorageConnection& aConnection) {
|
||||
if (kSQLiteGrowthIncrement) {
|
||||
// This is just an optimization so ignore the failure if the disk is
|
||||
// currently too full.
|
||||
IDB_TRY(QM_OR_ELSE_WARN(
|
||||
ToResult(aConnection.SetGrowthIncrement(kSQLiteGrowthIncrement, ""_ns)),
|
||||
(ErrToDefaultOkOrErr<NS_ERROR_FILE_TOO_BIG, Ok>)));
|
||||
IDB_TRY(
|
||||
ToResult(aConnection.SetGrowthIncrement(kSQLiteGrowthIncrement, ""_ns))
|
||||
.orElse(ErrToDefaultOkOrErr<NS_ERROR_FILE_TOO_BIG, Ok>));
|
||||
}
|
||||
#endif // IDB_MOBILE
|
||||
|
||||
@ -748,12 +748,11 @@ OpenDatabaseAndHandleBusy(mozIStorageService& aStorageService,
|
||||
|
||||
IDB_TRY_UNWRAP(
|
||||
auto connection,
|
||||
QM_OR_ELSE_WARN(
|
||||
OpenDatabase(aStorageService, aFileURL, aTelemetryId)
|
||||
.map([](auto connection) -> ConnectionType {
|
||||
return Some(std::move(connection));
|
||||
}),
|
||||
(ErrToDefaultOkOrErr<NS_ERROR_STORAGE_BUSY, ConnectionType>)));
|
||||
OpenDatabase(aStorageService, aFileURL, aTelemetryId)
|
||||
.map([](auto connection) -> ConnectionType {
|
||||
return Some(std::move(connection));
|
||||
})
|
||||
.orElse(ErrToDefaultOkOrErr<NS_ERROR_STORAGE_BUSY, ConnectionType>));
|
||||
|
||||
if (connection.isNothing()) {
|
||||
#ifdef DEBUG
|
||||
@ -778,12 +777,12 @@ OpenDatabaseAndHandleBusy(mozIStorageService& aStorageService,
|
||||
|
||||
IDB_TRY_UNWRAP(
|
||||
connection,
|
||||
QM_OR_ELSE_WARN(
|
||||
OpenDatabase(aStorageService, aFileURL, aTelemetryId)
|
||||
.map([](auto connection) -> ConnectionType {
|
||||
return Some(std::move(connection));
|
||||
}),
|
||||
([&start](nsresult aValue) -> Result<ConnectionType, nsresult> {
|
||||
OpenDatabase(aStorageService, aFileURL, aTelemetryId)
|
||||
.map([](auto connection) -> ConnectionType {
|
||||
return Some(std::move(connection));
|
||||
})
|
||||
.orElse([&start](
|
||||
nsresult aValue) -> Result<ConnectionType, nsresult> {
|
||||
if (aValue != NS_ERROR_STORAGE_BUSY ||
|
||||
TimeStamp::NowLoRes() - start >
|
||||
TimeDuration::FromSeconds(10)) {
|
||||
@ -791,7 +790,7 @@ OpenDatabaseAndHandleBusy(mozIStorageService& aStorageService,
|
||||
}
|
||||
|
||||
return ConnectionType();
|
||||
})));
|
||||
}));
|
||||
} while (connection.isNothing());
|
||||
}
|
||||
|
||||
@ -845,13 +844,12 @@ CreateStorageConnection(nsIFile& aDBFile, nsIFile& aFMDirectory,
|
||||
|
||||
IDB_TRY_UNWRAP(
|
||||
auto connection,
|
||||
QM_OR_ELSE_WARN(
|
||||
OpenDatabaseAndHandleBusy(*storageService, *dbFileUrl, aTelemetryId)
|
||||
.map([](auto connection) -> nsCOMPtr<mozIStorageConnection> {
|
||||
return std::move(connection).unwrapBasePtr();
|
||||
}),
|
||||
([&aName](nsresult aValue)
|
||||
-> Result<nsCOMPtr<mozIStorageConnection>, nsresult> {
|
||||
OpenDatabaseAndHandleBusy(*storageService, *dbFileUrl, aTelemetryId)
|
||||
.map([](auto connection) -> nsCOMPtr<mozIStorageConnection> {
|
||||
return std::move(connection).unwrapBasePtr();
|
||||
})
|
||||
.orElse([&aName](nsresult aValue)
|
||||
-> Result<nsCOMPtr<mozIStorageConnection>, nsresult> {
|
||||
// If we're just opening the database during origin initialization,
|
||||
// then we don't want to erase any files. The failure here will fail
|
||||
// origin initialization too.
|
||||
@ -860,7 +858,7 @@ CreateStorageConnection(nsIFile& aDBFile, nsIFile& aFMDirectory,
|
||||
}
|
||||
|
||||
return nsCOMPtr<mozIStorageConnection>();
|
||||
})));
|
||||
}));
|
||||
|
||||
if (!connection) {
|
||||
// XXX Shouldn't we also update quota usage?
|
||||
@ -5738,10 +5736,9 @@ nsresult DeleteFile(nsIFile& aFile, QuotaManager* const aQuotaManager,
|
||||
if (aQuotaManager) {
|
||||
IDB_TRY_INSPECT(
|
||||
const Maybe<int64_t>& fileSize,
|
||||
QM_OR_ELSE_WARN(
|
||||
MOZ_TO_RESULT_INVOKE(aFile, GetFileSize)
|
||||
.map([](const int64_t val) { return Some(val); }),
|
||||
MakeMaybeIdempotentFilter<int64_t>(aIdempotent)));
|
||||
MOZ_TO_RESULT_INVOKE(aFile, GetFileSize)
|
||||
.map([](const int64_t val) { return Some(val); })
|
||||
.orElse(MakeMaybeIdempotentFilter<int64_t>(aIdempotent)));
|
||||
|
||||
// XXX Can we really assert that the file size is not 0 if
|
||||
// it existed? This might be violated by external
|
||||
@ -5759,8 +5756,9 @@ nsresult DeleteFile(nsIFile& aFile, QuotaManager* const aQuotaManager,
|
||||
}
|
||||
|
||||
IDB_TRY_INSPECT(const auto& didExist,
|
||||
QM_OR_ELSE_WARN(ToResult(aFile.Remove(false)).map(Some<Ok>),
|
||||
MakeMaybeIdempotentFilter<Ok>(aIdempotent)));
|
||||
ToResult(aFile.Remove(false))
|
||||
.map(Some<Ok>)
|
||||
.orElse(MakeMaybeIdempotentFilter<Ok>(aIdempotent)));
|
||||
|
||||
if (!didExist) {
|
||||
// XXX If we get here, this means that the file still existed when we
|
||||
@ -5806,9 +5804,9 @@ nsresult DeleteFilesNoQuota(nsIFile* aDirectory, const nsAString& aFilename) {
|
||||
|
||||
IDB_TRY_INSPECT(const auto& file, CloneFileAndAppend(*aDirectory, aFilename));
|
||||
|
||||
IDB_TRY_INSPECT(const auto& didExist,
|
||||
QM_OR_ELSE_WARN(ToResult(file->Remove(true)).map(Some<Ok>),
|
||||
IdempotentFilter<Ok>));
|
||||
IDB_TRY_INSPECT(
|
||||
const auto& didExist,
|
||||
ToResult(file->Remove(true)).map(Some<Ok>).orElse(IdempotentFilter<Ok>));
|
||||
|
||||
Unused << didExist;
|
||||
|
||||
@ -5828,9 +5826,9 @@ Result<nsCOMPtr<nsIFile>, nsresult> CreateMarkerFile(
|
||||
CloneFileAndAppend(aBaseDirectory,
|
||||
kIdbDeletionMarkerFilePrefix + aDatabaseNameBase));
|
||||
|
||||
QM_TRY(QM_OR_ELSE_WARN(
|
||||
ToResult(markerFile->Create(nsIFile::NORMAL_FILE_TYPE, 0644)),
|
||||
ErrToDefaultOkOrErr<NS_ERROR_FILE_ALREADY_EXISTS>));
|
||||
IDB_TRY(
|
||||
MOZ_TO_RESULT_INVOKE(markerFile, Create, nsIFile::NORMAL_FILE_TYPE, 0644)
|
||||
.orElse(ErrToDefaultOkOrErr<NS_ERROR_FILE_ALREADY_EXISTS, Ok>));
|
||||
|
||||
return markerFile;
|
||||
}
|
||||
@ -5862,27 +5860,27 @@ Result<Ok, nsresult> DeleteFileManagerDirectory(
|
||||
|
||||
uint64_t usageValue = fileUsage.GetValue().valueOr(0);
|
||||
|
||||
auto res = QM_OR_ELSE_WARN(
|
||||
MOZ_TO_RESULT_INVOKE(aFileManagerDirectory, Remove, true),
|
||||
([&usageValue, &aFileManagerDirectory](nsresult rv) {
|
||||
// We may have deleted some files, try to update quota
|
||||
// information before returning the error.
|
||||
auto res =
|
||||
MOZ_TO_RESULT_INVOKE(aFileManagerDirectory, Remove, true)
|
||||
.orElse([&usageValue, &aFileManagerDirectory](nsresult rv) {
|
||||
// We may have deleted some files, try to update quota
|
||||
// information before returning the error.
|
||||
|
||||
// failures of GetUsage are intentionally ignored
|
||||
Unused << FileManager::GetUsage(&aFileManagerDirectory)
|
||||
.andThen([&usageValue](const auto& newFileUsage) {
|
||||
const auto newFileUsageValue =
|
||||
newFileUsage.GetValue().valueOr(0);
|
||||
MOZ_ASSERT(newFileUsageValue <= usageValue);
|
||||
usageValue -= newFileUsageValue;
|
||||
// failures of GetUsage are intentionally ignored
|
||||
Unused << FileManager::GetUsage(&aFileManagerDirectory)
|
||||
.andThen([&usageValue](const auto& newFileUsage) {
|
||||
const auto newFileUsageValue =
|
||||
newFileUsage.GetValue().valueOr(0);
|
||||
MOZ_ASSERT(newFileUsageValue <= usageValue);
|
||||
usageValue -= newFileUsageValue;
|
||||
|
||||
// XXX andThen does not support void return
|
||||
// values right now, we must return a Result
|
||||
return Result<Ok, nsresult>{Ok{}};
|
||||
});
|
||||
// XXX andThen does not support void return
|
||||
// values right now, we must return a Result
|
||||
return Result<Ok, nsresult>{Ok{}};
|
||||
});
|
||||
|
||||
return Result<Ok, nsresult>{Err(rv)};
|
||||
}));
|
||||
return Result<Ok, nsresult>{Err(rv)};
|
||||
});
|
||||
|
||||
if (usageValue) {
|
||||
aQuotaManager->DecreaseUsageForClient(
|
||||
@ -6777,8 +6775,11 @@ bool DeallocPBackgroundIndexedDBUtilsParent(
|
||||
bool RecvFlushPendingFileDeletions() {
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
if (QuotaClient* quotaClient = QuotaClient::GetInstance()) {
|
||||
QM_WARNONLY_TRY(quotaClient->FlushPendingFileDeletions());
|
||||
QuotaClient* quotaClient = QuotaClient::GetInstance();
|
||||
if (quotaClient) {
|
||||
if (NS_FAILED(quotaClient->FlushPendingFileDeletions())) {
|
||||
NS_WARNING("Failed to flush pending file deletions!");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -6890,30 +6891,29 @@ nsresult DatabaseConnection::BeginWriteTransaction() {
|
||||
IDB_TRY_INSPECT(const auto& beginStmt,
|
||||
BorrowCachedStatement("BEGIN IMMEDIATE;"_ns));
|
||||
|
||||
QM_TRY(QM_OR_ELSE_WARN(
|
||||
ToResult(beginStmt->Execute()), ([&beginStmt](nsresult rv) {
|
||||
if (rv == NS_ERROR_STORAGE_BUSY) {
|
||||
NS_WARNING(
|
||||
"Received NS_ERROR_STORAGE_BUSY when attempting to start write "
|
||||
"transaction, retrying for up to 10 seconds");
|
||||
IDB_TRY(ToResult(beginStmt->Execute()).orElse([&beginStmt](nsresult rv) {
|
||||
if (rv == NS_ERROR_STORAGE_BUSY) {
|
||||
NS_WARNING(
|
||||
"Received NS_ERROR_STORAGE_BUSY when attempting to start write "
|
||||
"transaction, retrying for up to 10 seconds");
|
||||
|
||||
// Another thread must be using the database. Wait up to 10 seconds
|
||||
// for that to complete.
|
||||
const TimeStamp start = TimeStamp::NowLoRes();
|
||||
// Another thread must be using the database. Wait up to 10 seconds for
|
||||
// that to complete.
|
||||
const TimeStamp start = TimeStamp::NowLoRes();
|
||||
|
||||
while (true) {
|
||||
PR_Sleep(PR_MillisecondsToInterval(100));
|
||||
while (true) {
|
||||
PR_Sleep(PR_MillisecondsToInterval(100));
|
||||
|
||||
rv = beginStmt->Execute();
|
||||
if (rv != NS_ERROR_STORAGE_BUSY ||
|
||||
TimeStamp::NowLoRes() - start > TimeDuration::FromSeconds(10)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
rv = beginStmt->Execute();
|
||||
if (rv != NS_ERROR_STORAGE_BUSY ||
|
||||
TimeStamp::NowLoRes() - start > TimeDuration::FromSeconds(10)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Result<Ok, nsresult>{rv};
|
||||
})));
|
||||
return Result<Ok, nsresult>{rv};
|
||||
}));
|
||||
|
||||
mInWriteTransaction = true;
|
||||
|
||||
@ -6945,21 +6945,14 @@ void DatabaseConnection::RollbackWriteTransaction() {
|
||||
return;
|
||||
}
|
||||
|
||||
QM_WARNONLY_TRY(
|
||||
BorrowCachedStatement("ROLLBACK;"_ns)
|
||||
.andThen([&self = *this](const auto& stmt) -> Result<Ok, nsresult> {
|
||||
// This may fail if SQLite already rolled back the transaction
|
||||
// so ignore any errors.
|
||||
IDB_TRY_INSPECT(const auto& stmt, BorrowCachedStatement("ROLLBACK;"_ns),
|
||||
QM_VOID);
|
||||
|
||||
// XXX ROLLBACK can fail quite normmally if a previous statement
|
||||
// failed to execute successfully so SQLite rolled back the
|
||||
// transaction already. However, if it failed because of some other
|
||||
// reason, we could try to close the connection.
|
||||
Unused << stmt->Execute();
|
||||
// This may fail if SQLite already rolled back the transaction so ignore any
|
||||
// errors.
|
||||
Unused << stmt->Execute();
|
||||
|
||||
self.mInWriteTransaction = false;
|
||||
return Ok{};
|
||||
}));
|
||||
mInWriteTransaction = false;
|
||||
}
|
||||
|
||||
void DatabaseConnection::FinishWriteTransaction() {
|
||||
@ -6974,11 +6967,9 @@ void DatabaseConnection::FinishWriteTransaction() {
|
||||
mUpdateRefcountFunction->Reset();
|
||||
}
|
||||
|
||||
QM_WARNONLY_TRY(ToResult(ExecuteCachedStatement("BEGIN;"_ns))
|
||||
.andThen([&](const auto) -> Result<Ok, nsresult> {
|
||||
mInReadTransaction = true;
|
||||
return Ok{};
|
||||
}));
|
||||
IDB_TRY(ExecuteCachedStatement("BEGIN;"_ns), QM_VOID);
|
||||
|
||||
mInReadTransaction = true;
|
||||
}
|
||||
|
||||
nsresult DatabaseConnection::StartSavepoint() {
|
||||
@ -7129,17 +7120,18 @@ void DatabaseConnection::DoIdleProcessing(bool aNeedsCheckpoint) {
|
||||
|
||||
// Truncate the WAL if we were asked to or if we managed to free some space.
|
||||
if (aNeedsCheckpoint || freedSomePages) {
|
||||
QM_WARNONLY_TRY(CheckpointInternal(CheckpointMode::Truncate));
|
||||
nsresult rv = CheckpointInternal(CheckpointMode::Truncate);
|
||||
Unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
}
|
||||
|
||||
// Finally try to restart the read transaction if we rolled it back earlier.
|
||||
if (beginStmt) {
|
||||
QM_WARNONLY_TRY(
|
||||
ToResult(beginStmt.Borrow()->Execute())
|
||||
.andThen([&self = *this](const Ok) -> Result<Ok, nsresult> {
|
||||
self.mInReadTransaction = true;
|
||||
return Ok{};
|
||||
}));
|
||||
nsresult rv = beginStmt.Borrow()->Execute();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mInReadTransaction = true;
|
||||
} else {
|
||||
NS_WARNING("Failed to restart read transaction!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7381,7 +7373,9 @@ DatabaseConnection::AutoSavepoint::~AutoSavepoint() {
|
||||
mDEBUGTransaction->GetMode() == IDBTransaction::Mode::Cleanup ||
|
||||
mDEBUGTransaction->GetMode() == IDBTransaction::Mode::VersionChange);
|
||||
|
||||
QM_WARNONLY_TRY(mConnection->RollbackSavepoint());
|
||||
if (NS_FAILED(mConnection->RollbackSavepoint())) {
|
||||
NS_WARNING("Failed to rollback savepoint!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7540,7 +7534,9 @@ void DatabaseConnection::UpdateRefcountFunction::DidCommit() {
|
||||
entry.GetData()->MaybeUpdateDBRefs();
|
||||
}
|
||||
|
||||
QM_WARNONLY_TRY(RemoveJournals(mJournalsToRemoveAfterCommit));
|
||||
if (NS_FAILED(RemoveJournals(mJournalsToRemoveAfterCommit))) {
|
||||
NS_WARNING("RemoveJournals failed!");
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseConnection::UpdateRefcountFunction::DidAbort() {
|
||||
@ -7550,7 +7546,9 @@ void DatabaseConnection::UpdateRefcountFunction::DidAbort() {
|
||||
AUTO_PROFILER_LABEL("DatabaseConnection::UpdateRefcountFunction::DidAbort",
|
||||
DOM);
|
||||
|
||||
QM_WARNONLY_TRY(RemoveJournals(mJournalsToRemoveAfterAbort));
|
||||
if (NS_FAILED(RemoveJournals(mJournalsToRemoveAfterAbort))) {
|
||||
NS_WARNING("RemoveJournals failed!");
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseConnection::UpdateRefcountFunction::StartSavepoint() {
|
||||
@ -7698,7 +7696,7 @@ nsresult DatabaseConnection::UpdateRefcountFunction::RemoveJournals(
|
||||
FileManager::GetFileForId(journalDirectory, journal);
|
||||
IDB_TRY(OkIf(file), NS_ERROR_FAILURE);
|
||||
|
||||
QM_WARNONLY_TRY(file->Remove(false));
|
||||
[&file] { IDB_TRY(file->Remove(false), QM_VOID); }();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -9501,9 +9499,13 @@ void Database::Invalidate() {
|
||||
Unused << SendInvalidate();
|
||||
}
|
||||
|
||||
QM_WARNONLY_TRY(OkIf(InvalidateAll(mTransactions)));
|
||||
if (!InvalidateAll(mTransactions)) {
|
||||
NS_WARNING("Failed to abort all transactions!");
|
||||
}
|
||||
|
||||
QM_WARNONLY_TRY(OkIf(InvalidateAll(mMutableFiles)));
|
||||
if (!InvalidateAll(mMutableFiles)) {
|
||||
NS_WARNING("Failed to abort all mutable files!");
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_TRUE(CloseInternal());
|
||||
}
|
||||
@ -12028,8 +12030,10 @@ void Cursor<CursorType>::SendResponseInternal(
|
||||
KeyValueBase::ProcessFiles(aResponse, aFiles);
|
||||
|
||||
// Work around the deleted function by casting to the base class.
|
||||
QM_WARNONLY_TRY(OkIf(
|
||||
static_cast<PBackgroundIDBCursorParent*>(this)->SendResponse(aResponse)));
|
||||
auto* const base = static_cast<PBackgroundIDBCursorParent*>(this);
|
||||
if (!base->SendResponse(aResponse)) {
|
||||
NS_WARNING("Failed to send response!");
|
||||
}
|
||||
|
||||
mCurrentlyRunningOp = nullptr;
|
||||
}
|
||||
@ -12442,21 +12446,21 @@ Result<FileUsageType, nsresult> FileManager::GetUsage(nsIFile* aDirectory) {
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
IDB_TRY_INSPECT(
|
||||
const auto& thisUsage,
|
||||
QM_OR_ELSE_WARN(
|
||||
MOZ_TO_RESULT_INVOKE(file, GetFileSize)
|
||||
.map([](const int64_t fileSize) {
|
||||
return FileUsageType(Some(uint64_t(fileSize)));
|
||||
}),
|
||||
([](const nsresult rv) -> Result<FileUsageType, nsresult> {
|
||||
if (rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST ||
|
||||
rv == NS_ERROR_FILE_NOT_FOUND) {
|
||||
// If the file does no longer exist, treat it as
|
||||
// 0-sized.
|
||||
return FileUsageType{};
|
||||
}
|
||||
MOZ_TO_RESULT_INVOKE(file, GetFileSize)
|
||||
.map([](const int64_t fileSize) {
|
||||
return FileUsageType(Some(uint64_t(fileSize)));
|
||||
})
|
||||
.orElse(
|
||||
[](const nsresult rv) -> Result<FileUsageType, nsresult> {
|
||||
if (rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST ||
|
||||
rv == NS_ERROR_FILE_NOT_FOUND) {
|
||||
// If the file does no longer exist, treat it as
|
||||
// 0-sized.
|
||||
return FileUsageType{};
|
||||
}
|
||||
|
||||
return Err(rv);
|
||||
})));
|
||||
return Err(rv);
|
||||
}));
|
||||
|
||||
usage += thisUsage;
|
||||
|
||||
@ -12786,22 +12790,21 @@ nsresult QuotaClient::GetUsageForOriginInternal(
|
||||
&aOriginMetadata](const nsString& subdirName) -> Result<Ok, nsresult> {
|
||||
// The directory must have the correct suffix.
|
||||
nsDependentSubstring subdirNameBase;
|
||||
IDB_TRY(QM_OR_ELSE_WARN(
|
||||
([&subdirName, &subdirNameBase] {
|
||||
IDB_TRY_RETURN(OkIf(GetFilenameBase(
|
||||
subdirName, kFileManagerDirectoryNameSuffix,
|
||||
subdirNameBase)));
|
||||
}()),
|
||||
([&directory,
|
||||
&subdirName](const NotOk) -> Result<Ok, nsresult> {
|
||||
// If there is an unexpected directory in the idb
|
||||
// directory, trying to delete at first instead of
|
||||
// breaking the whole initialization.
|
||||
IDB_TRY(DeleteFilesNoQuota(directory, subdirName),
|
||||
Err(NS_ERROR_UNEXPECTED));
|
||||
IDB_TRY(([&subdirName, &subdirNameBase] {
|
||||
IDB_TRY_RETURN(OkIf(GetFilenameBase(
|
||||
subdirName, kFileManagerDirectoryNameSuffix,
|
||||
subdirNameBase)));
|
||||
}()
|
||||
.orElse([&directory, &subdirName](
|
||||
const NotOk) -> Result<Ok, nsresult> {
|
||||
// If there is an unexpected directory in the idb
|
||||
// directory, trying to delete at first instead of
|
||||
// breaking the whole initialization.
|
||||
IDB_TRY(DeleteFilesNoQuota(directory, subdirName),
|
||||
Err(NS_ERROR_UNEXPECTED));
|
||||
|
||||
return Ok{};
|
||||
})),
|
||||
return Ok{};
|
||||
})),
|
||||
Ok{});
|
||||
|
||||
if (obsoleteFilenames.Contains(subdirNameBase)) {
|
||||
@ -12820,22 +12823,21 @@ nsresult QuotaClient::GetUsageForOriginInternal(
|
||||
// If there is an unexpected directory in the idb directory, trying to
|
||||
// delete at first instead of breaking the whole initialization.
|
||||
|
||||
// XXX This is still somewhat quirky. It would be nice to make it
|
||||
// clear that the warning handler is infallible, which would also
|
||||
// remove the need for the error type conversion.
|
||||
QM_WARNONLY_TRY(QM_OR_ELSE_WARN(
|
||||
OkIf(databaseFilenames.Contains(subdirNameBase))
|
||||
.mapErr([](const NotOk) { return NS_ERROR_FAILURE; }),
|
||||
([&directory,
|
||||
&subdirName](const nsresult) -> Result<Ok, nsresult> {
|
||||
// XXX It seems if we really got here, we can fail the
|
||||
// MOZ_ASSERT(!quotaManager->IsTemporaryStorageInitialized());
|
||||
// assertion in DeleteFilesNoQuota.
|
||||
IDB_TRY(DeleteFilesNoQuota(directory, subdirName),
|
||||
Err(NS_ERROR_UNEXPECTED));
|
||||
IDB_TRY(([&databaseFilenames, &subdirNameBase] {
|
||||
IDB_TRY_RETURN(
|
||||
OkIf(databaseFilenames.Contains(subdirNameBase)));
|
||||
}()
|
||||
.orElse([&directory, &subdirName](
|
||||
const NotOk) -> Result<Ok, nsresult> {
|
||||
// XXX It seems if we really got here, we can fail the
|
||||
// MOZ_ASSERT(!quotaManager->IsTemporaryStorageInitialized());
|
||||
// assertion in DeleteFilesNoQuota.
|
||||
IDB_TRY(DeleteFilesNoQuota(directory, subdirName),
|
||||
Err(NS_ERROR_UNEXPECTED));
|
||||
|
||||
return Ok{};
|
||||
})));
|
||||
return Ok{};
|
||||
})),
|
||||
Ok{});
|
||||
|
||||
return Ok{};
|
||||
}));
|
||||
@ -12876,15 +12878,14 @@ nsresult QuotaClient::GetUsageForOriginInternal(
|
||||
CloneFileAndAppend(
|
||||
*directory, databaseFilename + kSQLiteWALSuffix));
|
||||
|
||||
IDB_TRY_INSPECT(
|
||||
const int64_t& walFileSize,
|
||||
QM_OR_ELSE_WARN(MOZ_TO_RESULT_INVOKE(walFile, GetFileSize),
|
||||
([](const nsresult rv) {
|
||||
IDB_TRY_INSPECT(const int64_t& walFileSize,
|
||||
MOZ_TO_RESULT_INVOKE(walFile, GetFileSize)
|
||||
.orElse([](const nsresult rv) {
|
||||
return (rv == NS_ERROR_FILE_NOT_FOUND ||
|
||||
rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST)
|
||||
? Result<int64_t, nsresult>{0}
|
||||
: Err(rv);
|
||||
})));
|
||||
}));
|
||||
MOZ_ASSERT(walFileSize >= 0);
|
||||
*aUsageInfo += DatabaseUsageType(Some(uint64_t(walFileSize)));
|
||||
}
|
||||
@ -14247,33 +14248,31 @@ void DatabaseMaintenance::FullVacuum(mozIStorageConnection& aConnection,
|
||||
return;
|
||||
}
|
||||
|
||||
QM_WARNONLY_TRY(([&]() -> Result<Ok, nsresult> {
|
||||
IDB_TRY(aConnection.ExecuteSimpleSQL("VACUUM;"_ns));
|
||||
IDB_TRY(aConnection.ExecuteSimpleSQL("VACUUM;"_ns), QM_VOID);
|
||||
|
||||
const PRTime vacuumTime = PR_Now();
|
||||
MOZ_ASSERT(vacuumTime > 0);
|
||||
const PRTime vacuumTime = PR_Now();
|
||||
MOZ_ASSERT(vacuumTime > 0);
|
||||
|
||||
IDB_TRY_INSPECT(const int64_t& fileSize,
|
||||
MOZ_TO_RESULT_INVOKE(aDatabaseFile, GetFileSize));
|
||||
IDB_TRY_INSPECT(const int64_t& fileSize,
|
||||
MOZ_TO_RESULT_INVOKE(aDatabaseFile, GetFileSize), QM_VOID);
|
||||
|
||||
MOZ_ASSERT(fileSize > 0);
|
||||
MOZ_ASSERT(fileSize > 0);
|
||||
|
||||
// The parameter names are not used, parameters are bound by index only
|
||||
// locally in the same function.
|
||||
IDB_TRY_INSPECT(const auto& stmt, MOZ_TO_RESULT_INVOKE_TYPED(
|
||||
nsCOMPtr<mozIStorageStatement>,
|
||||
aConnection, CreateStatement,
|
||||
"UPDATE database "
|
||||
"SET last_vacuum_time = :time"
|
||||
", last_vacuum_size = :size;"_ns));
|
||||
// The parameter names are not used, parameters are bound by index only
|
||||
// locally in the same function.
|
||||
IDB_TRY_INSPECT(const auto& stmt,
|
||||
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<mozIStorageStatement>,
|
||||
aConnection, CreateStatement,
|
||||
"UPDATE database "
|
||||
"SET last_vacuum_time = :time"
|
||||
", last_vacuum_size = :size;"_ns),
|
||||
QM_VOID);
|
||||
|
||||
IDB_TRY(stmt->BindInt64ByIndex(0, vacuumTime));
|
||||
IDB_TRY(stmt->BindInt64ByIndex(0, vacuumTime), QM_VOID);
|
||||
|
||||
IDB_TRY(stmt->BindInt64ByIndex(1, fileSize));
|
||||
IDB_TRY(stmt->BindInt64ByIndex(1, fileSize), QM_VOID);
|
||||
|
||||
IDB_TRY(stmt->Execute());
|
||||
return Ok{};
|
||||
}()));
|
||||
IDB_TRY(stmt->Execute(), QM_VOID);
|
||||
}
|
||||
|
||||
void DatabaseMaintenance::RunOnOwningThread() {
|
||||
@ -14615,28 +14614,29 @@ nsresult DatabaseOperationBase::InsertIndexTableRows(
|
||||
IDB_TRY(aObjectStoreKey.BindToStatement(&*borrowedStmt,
|
||||
kStmtParamNameObjectDataKey));
|
||||
|
||||
QM_TRY(QM_OR_ELSE_WARN(
|
||||
ToResult(borrowedStmt->Execute()),
|
||||
([&info, index, &aIndexValues](nsresult rv) -> Result<Ok, nsresult> {
|
||||
if (rv == NS_ERROR_STORAGE_CONSTRAINT && info.mUnique) {
|
||||
// If we're inserting multiple entries for the same unique
|
||||
// index, then we might have failed to insert due to
|
||||
// colliding with another entry for the same index in which
|
||||
// case we should ignore it.
|
||||
for (int32_t index2 = int32_t(index) - 1;
|
||||
index2 >= 0 && aIndexValues[index2].mIndexId == info.mIndexId;
|
||||
--index2) {
|
||||
if (info.mPosition == aIndexValues[index2].mPosition) {
|
||||
// We found a key with the same value for the same
|
||||
// index. So we must have had a collision with a value
|
||||
// we just inserted.
|
||||
return Ok{};
|
||||
}
|
||||
}
|
||||
}
|
||||
IDB_TRY(MOZ_TO_RESULT_INVOKE(&*borrowedStmt, Execute)
|
||||
.orElse([&info, index,
|
||||
&aIndexValues](nsresult rv) -> Result<Ok, nsresult> {
|
||||
if (rv == NS_ERROR_STORAGE_CONSTRAINT && info.mUnique) {
|
||||
// If we're inserting multiple entries for the same unique
|
||||
// index, then we might have failed to insert due to
|
||||
// colliding with another entry for the same index in which
|
||||
// case we should ignore it.
|
||||
for (int32_t index2 = int32_t(index) - 1;
|
||||
index2 >= 0 &&
|
||||
aIndexValues[index2].mIndexId == info.mIndexId;
|
||||
--index2) {
|
||||
if (info.mPosition == aIndexValues[index2].mPosition) {
|
||||
// We found a key with the same value for the same
|
||||
// index. So we must have had a collision with a value
|
||||
// we just inserted.
|
||||
return Ok{};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Err(rv);
|
||||
})));
|
||||
return Err(rv);
|
||||
}));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include "FileInfoT.h"
|
||||
|
||||
#include "mozilla/dom/quota/QuotaCommon.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsIFile.h"
|
||||
|
||||
@ -95,7 +94,10 @@ void FileInfoT<FileManager>::UpdateReferences(ThreadSafeAutoRefCnt& aRefCount,
|
||||
|
||||
if (needsCleanup) {
|
||||
if (aSyncDeleteFile) {
|
||||
QM_WARNONLY_TRY(mFileManager->SyncDeleteFile(Id()));
|
||||
nsresult rv = mFileManager->SyncDeleteFile(Id());
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("FileManager cleanup failed!");
|
||||
}
|
||||
} else {
|
||||
Cleanup();
|
||||
}
|
||||
@ -134,7 +136,11 @@ bool FileInfoT<FileManager>::LockedClearDBRefs(
|
||||
|
||||
template <typename FileManager>
|
||||
void FileInfoT<FileManager>::Cleanup() {
|
||||
QM_WARNONLY_TRY(mFileManager->AsyncDeleteFile(Id()));
|
||||
int64_t id = Id();
|
||||
|
||||
if (NS_FAILED(mFileManager->AsyncDeleteFile(id))) {
|
||||
NS_WARNING("Failed to delete file asynchronously!");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename FileManager>
|
||||
|
@ -203,10 +203,12 @@ RefPtr<IDBDatabase> IDBDatabase::Create(IDBOpenDBRequest* aRequest,
|
||||
obsSvc->AddObserver(observer, kWindowObserverTopic, false));
|
||||
|
||||
// These topics are not crucial.
|
||||
QM_WARNONLY_TRY(
|
||||
obsSvc->AddObserver(observer, kCycleCollectionObserverTopic, false));
|
||||
QM_WARNONLY_TRY(
|
||||
obsSvc->AddObserver(observer, kMemoryPressureObserverTopic, false));
|
||||
if (NS_FAILED(obsSvc->AddObserver(observer, kCycleCollectionObserverTopic,
|
||||
false)) ||
|
||||
NS_FAILED(obsSvc->AddObserver(observer, kMemoryPressureObserverTopic,
|
||||
false))) {
|
||||
NS_WARNING("Failed to add additional memory observers!");
|
||||
}
|
||||
|
||||
db->mObserver = std::move(observer);
|
||||
}
|
||||
@ -367,14 +369,11 @@ RefPtr<IDBObjectStore> IDBDatabase::CreateObjectStore(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QM_NOTEONLY_TRY_UNWRAP(const auto maybeKeyPath,
|
||||
KeyPath::Parse(aOptionalParameters.mKeyPath));
|
||||
if (!maybeKeyPath) {
|
||||
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto& keyPath = maybeKeyPath.ref();
|
||||
// XXX This didn't use to warn before in case of a error. Should we remove the
|
||||
// warning again?
|
||||
IDB_TRY_INSPECT(const auto& keyPath,
|
||||
KeyPath::Parse(aOptionalParameters.mKeyPath), nullptr,
|
||||
[&aRv](const auto&) { aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR); });
|
||||
|
||||
auto& objectStores = mSpec->objectStores();
|
||||
const auto end = objectStores.cend();
|
||||
|
@ -1378,6 +1378,8 @@ RefPtr<IDBIndex> IDBObjectStore::CreateIndex(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// XXX This didn't use to warn before in case of a error. Should we remove the
|
||||
// warning again?
|
||||
const auto checkValid = [](const auto& keyPath) -> Result<KeyPath, nsresult> {
|
||||
if (!keyPath.IsValid()) {
|
||||
return Err(NS_ERROR_DOM_SYNTAX_ERR);
|
||||
@ -1386,8 +1388,8 @@ RefPtr<IDBIndex> IDBObjectStore::CreateIndex(
|
||||
return keyPath;
|
||||
};
|
||||
|
||||
QM_NOTEONLY_TRY_UNWRAP(
|
||||
const auto maybeKeyPath,
|
||||
IDB_TRY_INSPECT(
|
||||
const auto& keyPath,
|
||||
([&aKeyPath, checkValid]() -> Result<KeyPath, nsresult> {
|
||||
if (aKeyPath.IsString()) {
|
||||
IDB_TRY_RETURN(
|
||||
@ -1401,13 +1403,8 @@ RefPtr<IDBIndex> IDBObjectStore::CreateIndex(
|
||||
|
||||
IDB_TRY_RETURN(
|
||||
KeyPath::Parse(aKeyPath.GetAsStringSequence()).andThen(checkValid));
|
||||
})());
|
||||
if (!maybeKeyPath) {
|
||||
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto& keyPath = maybeKeyPath.ref();
|
||||
})(),
|
||||
nullptr, [&aRv](const auto&) { aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR); });
|
||||
|
||||
if (aOptionalParameters.mMultiEntry && keyPath.IsArray()) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
|
@ -438,9 +438,9 @@ nsresult SetDefaultPragmas(mozIStorageConnection* aConnection) {
|
||||
if (kSQLiteGrowthIncrement) {
|
||||
// This is just an optimization so ignore the failure if the disk is
|
||||
// currently too full.
|
||||
QM_TRY(QM_OR_ELSE_WARN(ToResult(aConnection->SetGrowthIncrement(
|
||||
kSQLiteGrowthIncrement, ""_ns)),
|
||||
ErrToDefaultOkOrErr<NS_ERROR_FILE_TOO_BIG>));
|
||||
LS_TRY(
|
||||
ToResult(aConnection->SetGrowthIncrement(kSQLiteGrowthIncrement, ""_ns))
|
||||
.orElse(ErrToDefaultOkOrErr<NS_ERROR_FILE_TOO_BIG, Ok>));
|
||||
}
|
||||
#endif // LS_MOBILE
|
||||
|
||||
@ -463,25 +463,23 @@ Result<nsCOMPtr<mozIStorageConnection>, nsresult> CreateStorageConnection(
|
||||
|
||||
LS_TRY_UNWRAP(
|
||||
auto connection,
|
||||
QM_OR_ELSE_WARN(
|
||||
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<mozIStorageConnection>,
|
||||
storageService, OpenDatabase, &aDBFile),
|
||||
([&aUsageFile, &aDBFile, &aCorruptedFileHandler,
|
||||
&storageService](const nsresult rv)
|
||||
-> Result<nsCOMPtr<mozIStorageConnection>, nsresult> {
|
||||
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<mozIStorageConnection>,
|
||||
storageService, OpenDatabase, &aDBFile)
|
||||
.orElse([&aUsageFile, &aDBFile, &aCorruptedFileHandler,
|
||||
&storageService](const nsresult rv)
|
||||
-> Result<nsCOMPtr<mozIStorageConnection>, nsresult> {
|
||||
if (IsDatabaseCorruptionError(rv)) {
|
||||
// Remove the usage file first (it might not exist at all due
|
||||
// to corrupted state, which is ignored here).
|
||||
QM_TRY(QM_OR_ELSE_WARN(
|
||||
ToResult(aUsageFile.Remove(false)),
|
||||
([](const nsresult rv) -> Result<Ok, nsresult> {
|
||||
if (rv == NS_ERROR_FILE_NOT_FOUND ||
|
||||
rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) {
|
||||
return Ok{};
|
||||
}
|
||||
LS_TRY(ToResult(aUsageFile.Remove(false))
|
||||
.orElse([](const nsresult rv) -> Result<Ok, nsresult> {
|
||||
if (rv == NS_ERROR_FILE_NOT_FOUND ||
|
||||
rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) {
|
||||
return Ok{};
|
||||
}
|
||||
|
||||
return Err(rv);
|
||||
})));
|
||||
return Err(rv);
|
||||
}));
|
||||
|
||||
// Call the corrupted file handler before trying to remove the
|
||||
// database file, which might fail.
|
||||
@ -495,7 +493,7 @@ Result<nsCOMPtr<mozIStorageConnection>, nsresult> CreateStorageConnection(
|
||||
&aDBFile));
|
||||
}
|
||||
return Err(rv);
|
||||
})));
|
||||
}));
|
||||
|
||||
LS_TRY(SetDefaultPragmas(connection));
|
||||
|
||||
@ -680,11 +678,10 @@ CreateArchiveStorageConnection(const nsAString& aStoragePath) {
|
||||
|
||||
LS_TRY_UNWRAP(
|
||||
auto connection,
|
||||
QM_OR_ELSE_WARN(
|
||||
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<mozIStorageConnection>, ss,
|
||||
OpenUnsharedDatabase, archiveFile),
|
||||
([](const nsresult rv)
|
||||
-> Result<nsCOMPtr<mozIStorageConnection>, nsresult> {
|
||||
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<mozIStorageConnection>, ss,
|
||||
OpenUnsharedDatabase, archiveFile)
|
||||
.orElse([](const nsresult rv)
|
||||
-> Result<nsCOMPtr<mozIStorageConnection>, nsresult> {
|
||||
if (IsDatabaseCorruptionError(rv)) {
|
||||
// Don't throw an error, leave a corrupted ls-archive database as
|
||||
// it is.
|
||||
@ -692,7 +689,7 @@ CreateArchiveStorageConnection(const nsAString& aStoragePath) {
|
||||
}
|
||||
|
||||
return Err(rv);
|
||||
})));
|
||||
}));
|
||||
|
||||
if (connection) {
|
||||
const nsresult rv = StorageDBUpdater::Update(connection);
|
||||
@ -817,11 +814,10 @@ Result<nsCOMPtr<mozIStorageConnection>, nsresult> CreateShadowStorageConnection(
|
||||
|
||||
LS_TRY_UNWRAP(
|
||||
auto connection,
|
||||
QM_OR_ELSE_WARN(
|
||||
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<mozIStorageConnection>, ss,
|
||||
OpenUnsharedDatabase, shadowFile),
|
||||
([&shadowFile, &ss](const nsresult rv)
|
||||
-> Result<nsCOMPtr<mozIStorageConnection>, nsresult> {
|
||||
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<mozIStorageConnection>, ss,
|
||||
OpenUnsharedDatabase, shadowFile)
|
||||
.orElse([&shadowFile, &ss](const nsresult rv)
|
||||
-> Result<nsCOMPtr<mozIStorageConnection>, nsresult> {
|
||||
if (IsDatabaseCorruptionError(rv)) {
|
||||
LS_TRY(shadowFile->Remove(false));
|
||||
|
||||
@ -831,7 +827,7 @@ Result<nsCOMPtr<mozIStorageConnection>, nsresult> CreateShadowStorageConnection(
|
||||
}
|
||||
|
||||
return Err(rv);
|
||||
})));
|
||||
}));
|
||||
|
||||
LS_TRY(SetShadowJournalMode(connection));
|
||||
|
||||
@ -849,22 +845,23 @@ Result<nsCOMPtr<mozIStorageConnection>, nsresult> CreateShadowStorageConnection(
|
||||
// complicated than it should be. Maybe these two methods can be merged (which
|
||||
// would mean that a parameter must be added that indicates whether it's
|
||||
// handling the shadow file or not).
|
||||
QM_TRY(QM_OR_ELSE_WARN(
|
||||
ToResult(StorageDBUpdater::Update(connection)),
|
||||
([&connection, &shadowFile, &ss](const nsresult) -> Result<Ok, nsresult> {
|
||||
LS_TRY(connection->Close());
|
||||
LS_TRY(shadowFile->Remove(false));
|
||||
LS_TRY(ToResult(StorageDBUpdater::Update(connection))
|
||||
.orElse([&connection, &shadowFile,
|
||||
&ss](const nsresult) -> Result<Ok, nsresult> {
|
||||
LS_TRY(connection->Close());
|
||||
LS_TRY(shadowFile->Remove(false));
|
||||
|
||||
LS_TRY_UNWRAP(connection, MOZ_TO_RESULT_INVOKE_TYPED(
|
||||
nsCOMPtr<mozIStorageConnection>, ss,
|
||||
OpenUnsharedDatabase, shadowFile));
|
||||
LS_TRY_UNWRAP(connection,
|
||||
MOZ_TO_RESULT_INVOKE_TYPED(
|
||||
nsCOMPtr<mozIStorageConnection>, ss,
|
||||
OpenUnsharedDatabase, shadowFile));
|
||||
|
||||
LS_TRY(SetShadowJournalMode(connection));
|
||||
LS_TRY(SetShadowJournalMode(connection));
|
||||
|
||||
LS_TRY(StorageDBUpdater::CreateCurrentSchema(connection));
|
||||
LS_TRY(StorageDBUpdater::CreateCurrentSchema(connection));
|
||||
|
||||
return Ok{};
|
||||
})));
|
||||
return Ok{};
|
||||
}));
|
||||
|
||||
return connection;
|
||||
}
|
||||
@ -963,19 +960,19 @@ Result<bool, nsresult> ExistsAsFile(nsIFile& aFile) {
|
||||
// the path exists.
|
||||
LS_TRY_INSPECT(
|
||||
const auto& res,
|
||||
QM_OR_ELSE_WARN(
|
||||
MOZ_TO_RESULT_INVOKE(aFile, IsDirectory)
|
||||
.map([](const bool isDirectory) {
|
||||
return isDirectory ? ExistsAsFileResult::IsDirectory
|
||||
: ExistsAsFileResult::IsFile;
|
||||
}),
|
||||
([](const nsresult rv) -> Result<ExistsAsFileResult, nsresult> {
|
||||
if (rv != NS_ERROR_FILE_NOT_FOUND &&
|
||||
rv != NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) {
|
||||
return Err(rv);
|
||||
}
|
||||
return ExistsAsFileResult::DoesNotExist;
|
||||
})));
|
||||
MOZ_TO_RESULT_INVOKE(aFile, IsDirectory)
|
||||
.map([](const bool isDirectory) {
|
||||
return isDirectory ? ExistsAsFileResult::IsDirectory
|
||||
: ExistsAsFileResult::IsFile;
|
||||
})
|
||||
.orElse(
|
||||
[](const nsresult rv) -> Result<ExistsAsFileResult, nsresult> {
|
||||
if (rv != NS_ERROR_FILE_NOT_FOUND &&
|
||||
rv != NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) {
|
||||
return Err(rv);
|
||||
}
|
||||
return ExistsAsFileResult::DoesNotExist;
|
||||
}));
|
||||
|
||||
LS_TRY(OkIf(res != ExistsAsFileResult::IsDirectory), Err(NS_ERROR_FAILURE));
|
||||
|
||||
@ -3082,16 +3079,17 @@ void InitializeLocalStorage() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!gLocalStorageInitialized);
|
||||
|
||||
// XXX Isn't this redundant? It's already done in InitializeQuotaManager.
|
||||
if (!QuotaManager::IsRunningGTests()) {
|
||||
// This service has to be started on the main thread currently.
|
||||
const nsCOMPtr<mozIStorageService> ss =
|
||||
do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
|
||||
|
||||
QM_WARNONLY_TRY(OkIf(ss));
|
||||
nsCOMPtr<mozIStorageService> ss;
|
||||
if (NS_WARN_IF(!(ss = do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID)))) {
|
||||
NS_WARNING("Failed to get storage service!");
|
||||
}
|
||||
}
|
||||
|
||||
QM_WARNONLY_TRY(QuotaClient::Initialize());
|
||||
if (NS_FAILED(QuotaClient::Initialize())) {
|
||||
NS_WARNING("Failed to initialize quota client!");
|
||||
}
|
||||
|
||||
Preferences::RegisterCallbackAndCall(ShadowWritesPrefChangedCallback,
|
||||
kShadowWritesPref);
|
||||
@ -8104,29 +8102,31 @@ Result<UsageInfo, nsresult> QuotaClient::InitOrigin(
|
||||
([fileExists, usageFileExists, &file, &usageFile, &usageJournalFile,
|
||||
&aOriginMetadata]() -> Result<UsageInfo, nsresult> {
|
||||
if (fileExists) {
|
||||
LS_TRY_RETURN(QM_OR_ELSE_WARN(
|
||||
LS_TRY_RETURN(
|
||||
// To simplify control flow, we call LoadUsageFile unconditionally
|
||||
// here, even though it will necessarily fail if usageFileExists
|
||||
// is false.
|
||||
LoadUsageFile(*usageFile),
|
||||
([&file, &usageFile, &usageJournalFile, &aOriginMetadata](
|
||||
const nsresult) -> Result<UsageInfo, nsresult> {
|
||||
LS_TRY_INSPECT(
|
||||
const auto& connection,
|
||||
CreateStorageConnection(*file, *usageFile,
|
||||
aOriginMetadata.mOrigin, [] {}));
|
||||
LoadUsageFile(*usageFile)
|
||||
.orElse([&file, &usageFile, &usageJournalFile,
|
||||
&aOriginMetadata](
|
||||
const nsresult) -> Result<UsageInfo, nsresult> {
|
||||
LS_TRY_INSPECT(
|
||||
const auto& connection,
|
||||
CreateStorageConnection(
|
||||
*file, *usageFile, aOriginMetadata.mOrigin, [] {}));
|
||||
|
||||
LS_TRY_INSPECT(const int64_t& usage,
|
||||
GetUsage(*connection,
|
||||
/* aArchivedOriginScope */ nullptr));
|
||||
LS_TRY_INSPECT(
|
||||
const int64_t& usage,
|
||||
GetUsage(*connection,
|
||||
/* aArchivedOriginScope */ nullptr));
|
||||
|
||||
LS_TRY(UpdateUsageFile(usageFile, usageJournalFile, usage));
|
||||
LS_TRY(UpdateUsageFile(usageFile, usageJournalFile, usage));
|
||||
|
||||
LS_TRY(usageJournalFile->Remove(false));
|
||||
LS_TRY(usageJournalFile->Remove(false));
|
||||
|
||||
MOZ_ASSERT(usage >= 0);
|
||||
return UsageInfo{DatabaseUsageType(Some(uint64_t(usage)))};
|
||||
})));
|
||||
MOZ_ASSERT(usage >= 0);
|
||||
return UsageInfo{DatabaseUsageType(Some(uint64_t(usage)))};
|
||||
}));
|
||||
}
|
||||
|
||||
if (usageFileExists) {
|
||||
@ -8741,10 +8741,12 @@ AutoWriteTransaction::~AutoWriteTransaction() {
|
||||
MOZ_COUNT_DTOR(mozilla::dom::AutoWriteTransaction);
|
||||
|
||||
if (mConnection) {
|
||||
QM_WARNONLY_TRY(mConnection->RollbackWriteTransaction());
|
||||
if (NS_FAILED(mConnection->RollbackWriteTransaction())) {
|
||||
NS_WARNING("Failed to rollback write transaction!");
|
||||
}
|
||||
|
||||
if (mShadowWrites) {
|
||||
QM_WARNONLY_TRY(DetachShadowDatabaseAndUnlock());
|
||||
if (mShadowWrites && NS_FAILED(DetachShadowDatabaseAndUnlock())) {
|
||||
NS_WARNING("Failed to detach shadow database!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -429,22 +429,24 @@ nsresult InvalidateCache(mozIStorageConnection& aConnection) {
|
||||
static constexpr auto kDeleteCacheQuery = "DELETE FROM origin;"_ns;
|
||||
static constexpr auto kSetInvalidFlagQuery = "UPDATE cache SET valid = 0"_ns;
|
||||
|
||||
QM_TRY(QM_OR_ELSE_WARN(
|
||||
([&]() -> Result<Ok, nsresult> {
|
||||
mozStorageTransaction transaction(&aConnection, false);
|
||||
// XXX Use QM_TRY_OR_WARN here in/after Bug 1686191.
|
||||
QM_TRY(([&]() -> Result<Ok, nsresult> {
|
||||
mozStorageTransaction transaction(&aConnection, false);
|
||||
|
||||
QM_TRY(transaction.Start());
|
||||
QM_TRY(aConnection.ExecuteSimpleSQL(kDeleteCacheQuery));
|
||||
QM_TRY(aConnection.ExecuteSimpleSQL(kSetInvalidFlagQuery));
|
||||
QM_TRY(transaction.Commit());
|
||||
QM_TRY(transaction.Start());
|
||||
QM_TRY(aConnection.ExecuteSimpleSQL(kDeleteCacheQuery));
|
||||
QM_TRY(aConnection.ExecuteSimpleSQL(kSetInvalidFlagQuery));
|
||||
QM_TRY(transaction.Commit());
|
||||
|
||||
return Ok{};
|
||||
}()),
|
||||
([&](const nsresult rv) -> Result<Ok, nsresult> {
|
||||
QM_TRY(aConnection.ExecuteSimpleSQL(kSetInvalidFlagQuery));
|
||||
return Ok{};
|
||||
}()
|
||||
.orElse([&](const nsresult rv) -> Result<Ok, nsresult> {
|
||||
QM_TRY(aConnection.ExecuteSimpleSQL(
|
||||
kSetInvalidFlagQuery));
|
||||
|
||||
return Ok{};
|
||||
})));
|
||||
|
||||
return Ok{};
|
||||
})));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -569,21 +571,21 @@ Result<nsCOMPtr<mozIStorageConnection>, nsresult> CreateWebAppsStoreConnection(
|
||||
return nsCOMPtr<mozIStorageConnection>{};
|
||||
}
|
||||
|
||||
QM_TRY_INSPECT(const auto& connection,
|
||||
QM_OR_ELSE_WARN(
|
||||
MOZ_TO_RESULT_INVOKE_TYPED(
|
||||
nsCOMPtr<mozIStorageConnection>, aStorageService,
|
||||
OpenUnsharedDatabase, &aWebAppsStoreFile),
|
||||
([](const nsresult rv)
|
||||
-> Result<nsCOMPtr<mozIStorageConnection>, nsresult> {
|
||||
if (IsDatabaseCorruptionError(rv)) {
|
||||
// Don't throw an error, leave a corrupted webappsstore
|
||||
// database as it is.
|
||||
return nsCOMPtr<mozIStorageConnection>{};
|
||||
}
|
||||
QM_TRY_INSPECT(
|
||||
const auto& connection,
|
||||
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<mozIStorageConnection>,
|
||||
aStorageService, OpenUnsharedDatabase,
|
||||
&aWebAppsStoreFile)
|
||||
.orElse([](const nsresult rv)
|
||||
-> Result<nsCOMPtr<mozIStorageConnection>, nsresult> {
|
||||
if (IsDatabaseCorruptionError(rv)) {
|
||||
// Don't throw an error, leave a corrupted webappsstore database
|
||||
// as it is.
|
||||
return nsCOMPtr<mozIStorageConnection>{};
|
||||
}
|
||||
|
||||
return Err(rv);
|
||||
})));
|
||||
return Err(rv);
|
||||
}));
|
||||
|
||||
if (connection) {
|
||||
// Don't propagate an error, leave a non-updateable webappsstore database as
|
||||
@ -2389,12 +2391,12 @@ int64_t GetLastModifiedTime(PersistenceType aPersistenceType, nsIFile& aFile) {
|
||||
Result<bool, nsresult> EnsureDirectory(nsIFile& aDirectory) {
|
||||
AssertIsOnIOThread();
|
||||
|
||||
// TODO: Convert to mapOrElse once mozilla::Result supports it.
|
||||
QM_TRY_INSPECT(
|
||||
const auto& exists,
|
||||
QM_OR_ELSE_WARN(MOZ_TO_RESULT_INVOKE(aDirectory, Create,
|
||||
nsIFile::DIRECTORY_TYPE, 0755)
|
||||
.map([](Ok) { return false; }),
|
||||
(ErrToOkOrErr<NS_ERROR_FILE_ALREADY_EXISTS, true>)));
|
||||
MOZ_TO_RESULT_INVOKE(aDirectory, Create, nsIFile::DIRECTORY_TYPE, 0755)
|
||||
.andThen(OkToOk<false>)
|
||||
.orElse(ErrToOkOrErr<NS_ERROR_FILE_ALREADY_EXISTS, true>));
|
||||
|
||||
if (exists) {
|
||||
QM_TRY_INSPECT(const bool& isDirectory,
|
||||
@ -2629,19 +2631,17 @@ void InitializeQuotaManager() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!gQuotaManagerInitialized);
|
||||
|
||||
#ifdef QM_ENABLE_SCOPED_LOG_EXTRA_INFO
|
||||
ScopedLogExtraInfo::Initialize();
|
||||
#endif
|
||||
|
||||
if (!QuotaManager::IsRunningGTests()) {
|
||||
// This service has to be started on the main thread currently.
|
||||
const nsCOMPtr<mozIStorageService> ss =
|
||||
do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
|
||||
|
||||
QM_WARNONLY_TRY(OkIf(ss));
|
||||
nsCOMPtr<mozIStorageService> ss;
|
||||
if (NS_WARN_IF(!(ss = do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID)))) {
|
||||
NS_WARNING("Failed to get storage service!");
|
||||
}
|
||||
}
|
||||
|
||||
QM_WARNONLY_TRY(QuotaManager::Initialize());
|
||||
if (NS_FAILED(QuotaManager::Initialize())) {
|
||||
NS_WARNING("Failed to initialize quota manager!");
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
gQuotaManagerInitialized = true;
|
||||
@ -3225,6 +3225,10 @@ QuotaManager::~QuotaManager() {
|
||||
nsresult QuotaManager::Initialize() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
#ifdef QM_ENABLE_SCOPED_LOG_EXTRA_INFO
|
||||
ScopedLogExtraInfo::Initialize();
|
||||
#endif
|
||||
|
||||
nsresult rv = Observer::Initialize();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
@ -3794,7 +3798,9 @@ void QuotaManager::Shutdown() {
|
||||
}
|
||||
|
||||
// Cancel the timer regardless of whether it actually fired.
|
||||
QM_WARNONLY_TRY((*mShutdownTimer)->Cancel());
|
||||
if (NS_FAILED((*mShutdownTimer)->Cancel())) {
|
||||
NS_WARNING("Failed to cancel shutdown timer!");
|
||||
}
|
||||
|
||||
// NB: It's very important that runnable is destroyed on this thread
|
||||
// (i.e. after we join the IO thread) because we can't release the
|
||||
@ -3806,10 +3812,14 @@ void QuotaManager::Shutdown() {
|
||||
MOZ_ASSERT(runnable);
|
||||
|
||||
// Give clients a chance to cleanup IO thread only objects.
|
||||
QM_WARNONLY_TRY((*mIOThread)->Dispatch(runnable, NS_DISPATCH_NORMAL));
|
||||
if (NS_FAILED((*mIOThread)->Dispatch(runnable, NS_DISPATCH_NORMAL))) {
|
||||
NS_WARNING("Failed to dispatch runnable!");
|
||||
}
|
||||
|
||||
// Make sure to join with our IO thread.
|
||||
QM_WARNONLY_TRY((*mIOThread)->Shutdown());
|
||||
if (NS_FAILED((*mIOThread)->Shutdown())) {
|
||||
NS_WARNING("Failed to shutdown IO thread!");
|
||||
}
|
||||
|
||||
for (RefPtr<DirectoryLockImpl>& lock : mPendingDirectoryLocks) {
|
||||
lock->Invalidate();
|
||||
@ -4610,14 +4620,21 @@ QuotaManager::LoadFullOriginMetadataWithRestore(nsIFile* aDirectory) {
|
||||
|
||||
const auto& persistenceType = maybePersistenceType.value();
|
||||
|
||||
QM_TRY_RETURN(QM_OR_ELSE_WARN(
|
||||
LoadFullOriginMetadata(aDirectory, persistenceType),
|
||||
([&aDirectory, &persistenceType,
|
||||
this](const nsresult rv) -> Result<FullOriginMetadata, nsresult> {
|
||||
QM_TRY(RestoreDirectoryMetadata2(aDirectory));
|
||||
QM_TRY_UNWRAP(auto maybeFirstAttemptResult,
|
||||
([&]() -> Result<Maybe<FullOriginMetadata>, nsresult> {
|
||||
QM_TRY_RETURN(
|
||||
LoadFullOriginMetadata(aDirectory, persistenceType)
|
||||
.map(Some<FullOriginMetadata, FullOriginMetadata>),
|
||||
Maybe<FullOriginMetadata>{});
|
||||
}()));
|
||||
|
||||
QM_TRY_RETURN(LoadFullOriginMetadata(aDirectory, persistenceType));
|
||||
})));
|
||||
if (!maybeFirstAttemptResult) {
|
||||
QM_TRY(RestoreDirectoryMetadata2(aDirectory));
|
||||
|
||||
QM_TRY_RETURN(LoadFullOriginMetadata(aDirectory, persistenceType));
|
||||
}
|
||||
|
||||
return maybeFirstAttemptResult.extract();
|
||||
}
|
||||
|
||||
nsresult QuotaManager::InitializeRepository(PersistenceType aPersistenceType) {
|
||||
@ -4711,26 +4728,26 @@ nsresult QuotaManager::InitializeRepository(PersistenceType aPersistenceType) {
|
||||
// they won't be accessed after initialization.
|
||||
}
|
||||
|
||||
QM_TRY(QM_OR_ELSE_WARN(
|
||||
QM_TRY(
|
||||
ToResult(InitializeOrigin(
|
||||
aPersistenceType, metadata,
|
||||
metadata.mLastAccessTime, metadata.mPersisted,
|
||||
childDirectory)),
|
||||
([&childDirectory](
|
||||
const nsresult rv) -> Result<Ok, nsresult> {
|
||||
if (IsDatabaseCorruptionError(rv)) {
|
||||
// If the origin can't be initialized due to
|
||||
// corruption, this is a permanent
|
||||
// condition, and we need to remove all data
|
||||
// for the origin on disk.
|
||||
aPersistenceType, metadata,
|
||||
metadata.mLastAccessTime,
|
||||
metadata.mPersisted, childDirectory))
|
||||
.orElse([&childDirectory](const nsresult rv)
|
||||
-> Result<Ok, nsresult> {
|
||||
if (IsDatabaseCorruptionError(rv)) {
|
||||
// If the origin can't be initialized due
|
||||
// to corruption, this is a permanent
|
||||
// condition, and we need to remove all
|
||||
// data for the origin on disk.
|
||||
|
||||
QM_TRY(childDirectory->Remove(true));
|
||||
QM_TRY(childDirectory->Remove(true));
|
||||
|
||||
return Ok{};
|
||||
}
|
||||
return Ok{};
|
||||
}
|
||||
|
||||
return Err(rv);
|
||||
})));
|
||||
return Err(rv);
|
||||
}));
|
||||
|
||||
break;
|
||||
}
|
||||
@ -5987,13 +6004,11 @@ nsresult QuotaManager::EnsureStorageIsInitialized() {
|
||||
MOZ_SELECT_OVERLOAD(do_GetService),
|
||||
MOZ_STORAGE_SERVICE_CONTRACTID));
|
||||
|
||||
QM_TRY_UNWRAP(
|
||||
auto connection,
|
||||
QM_OR_ELSE_WARN(
|
||||
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<mozIStorageConnection>, ss,
|
||||
OpenUnsharedDatabase, storageFile),
|
||||
(FilterDatabaseCorruptionError<nullptr,
|
||||
nsCOMPtr<mozIStorageConnection>>)));
|
||||
QM_TRY_UNWRAP(auto connection,
|
||||
MOZ_TO_RESULT_INVOKE_TYPED(nsCOMPtr<mozIStorageConnection>, ss,
|
||||
OpenUnsharedDatabase, storageFile)
|
||||
.orElse(FilterDatabaseCorruptionError<
|
||||
nullptr, nsCOMPtr<mozIStorageConnection>>));
|
||||
|
||||
if (!connection) {
|
||||
// Nuke the database file.
|
||||
@ -6016,14 +6031,14 @@ nsresult QuotaManager::EnsureStorageIsInitialized() {
|
||||
GetLocalStorageArchiveFile(*mStoragePath));
|
||||
|
||||
if (CachedNextGenLocalStorageEnabled()) {
|
||||
QM_TRY(QM_OR_ELSE_WARN(
|
||||
MaybeCreateOrUpgradeLocalStorageArchive(*lsArchiveFile),
|
||||
([&](const nsresult rv) -> Result<Ok, nsresult> {
|
||||
if (IsDatabaseCorruptionError(rv)) {
|
||||
QM_TRY_RETURN(CreateEmptyLocalStorageArchive(*lsArchiveFile));
|
||||
}
|
||||
return Err(rv);
|
||||
})));
|
||||
QM_TRY(MaybeCreateOrUpgradeLocalStorageArchive(*lsArchiveFile)
|
||||
.orElse([&](const nsresult rv) -> Result<Ok, nsresult> {
|
||||
if (IsDatabaseCorruptionError(rv)) {
|
||||
QM_TRY_RETURN(
|
||||
CreateEmptyLocalStorageArchive(*lsArchiveFile));
|
||||
}
|
||||
return Err(rv);
|
||||
}));
|
||||
} else {
|
||||
QM_TRY(MaybeRemoveLocalStorageDataAndArchive(*lsArchiveFile));
|
||||
}
|
||||
@ -8994,9 +9009,11 @@ void ClearRequestBase::DeleteFiles(QuotaManager& aQuotaManager,
|
||||
|
||||
// We can't guarantee that this will always succeed on
|
||||
// Windows...
|
||||
QM_WARNONLY_TRY(file->Remove(true), [&](const auto&) {
|
||||
if (NS_FAILED((file->Remove(true)))) {
|
||||
NS_WARNING("Failed to remove directory, retrying later.");
|
||||
|
||||
directoriesForRemovalRetry.AppendElement(std::move(file));
|
||||
});
|
||||
}
|
||||
|
||||
const bool initialized =
|
||||
aPersistenceType == PERSISTENCE_TYPE_PERSISTENT
|
||||
@ -10546,20 +10563,22 @@ nsresult CreateOrUpgradeDirectoryMetadataHelper::MaybeUpgradeOriginDirectory(
|
||||
QM_TRY_INSPECT(const auto& idbDirectory,
|
||||
CloneFileAndAppend(*aDirectory, idbDirectoryName));
|
||||
|
||||
QM_TRY(QM_OR_ELSE_WARN(
|
||||
ToResult(idbDirectory->Create(nsIFile::DIRECTORY_TYPE, 0755)),
|
||||
([&idbDirectory](const nsresult rv) -> Result<Ok, nsresult> {
|
||||
if (rv == NS_ERROR_FILE_ALREADY_EXISTS) {
|
||||
QM_TRY_INSPECT(const bool& isDirectory,
|
||||
MOZ_TO_RESULT_INVOKE(idbDirectory, IsDirectory));
|
||||
QM_TRY(
|
||||
ToResult(idbDirectory->Create(nsIFile::DIRECTORY_TYPE, 0755))
|
||||
.orElse([&idbDirectory](const nsresult rv) -> Result<Ok, nsresult> {
|
||||
if (rv == NS_ERROR_FILE_ALREADY_EXISTS) {
|
||||
NS_WARNING("IDB directory already exists!");
|
||||
|
||||
QM_TRY(OkIf(isDirectory), Err(NS_ERROR_UNEXPECTED));
|
||||
QM_TRY_INSPECT(const bool& isDirectory,
|
||||
MOZ_TO_RESULT_INVOKE(idbDirectory, IsDirectory));
|
||||
|
||||
return Ok{};
|
||||
}
|
||||
QM_TRY(OkIf(isDirectory), Err(NS_ERROR_UNEXPECTED));
|
||||
|
||||
return Err(rv);
|
||||
})));
|
||||
return Ok{};
|
||||
}
|
||||
|
||||
return Err(rv);
|
||||
}));
|
||||
|
||||
QM_TRY(CollectEachFile(
|
||||
*aDirectory,
|
||||
|
@ -164,26 +164,27 @@ Result<nsCOMPtr<nsIFile>, nsresult> CloneFileAndAppend(
|
||||
}
|
||||
|
||||
Result<nsIFileKind, nsresult> GetDirEntryKind(nsIFile& aFile) {
|
||||
QM_TRY_RETURN(QM_OR_ELSE_WARN(
|
||||
MOZ_TO_RESULT_INVOKE(aFile, IsDirectory).map([](const bool isDirectory) {
|
||||
return isDirectory ? nsIFileKind::ExistsAsDirectory
|
||||
: nsIFileKind::ExistsAsFile;
|
||||
}),
|
||||
([](const nsresult rv) -> Result<nsIFileKind, nsresult> {
|
||||
if (rv == NS_ERROR_FILE_NOT_FOUND ||
|
||||
rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST
|
||||
QM_TRY_RETURN(
|
||||
MOZ_TO_RESULT_INVOKE(aFile, IsDirectory)
|
||||
.map([](const bool isDirectory) {
|
||||
return isDirectory ? nsIFileKind::ExistsAsDirectory
|
||||
: nsIFileKind::ExistsAsFile;
|
||||
})
|
||||
.orElse([](const nsresult rv) -> Result<nsIFileKind, nsresult> {
|
||||
if (rv == NS_ERROR_FILE_NOT_FOUND ||
|
||||
rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST
|
||||
#ifdef WIN32
|
||||
// We treat ERROR_FILE_CORRUPT as if the file did not exist at
|
||||
// all.
|
||||
|| (NS_ERROR_GET_MODULE(rv) == NS_ERROR_MODULE_WIN32 &&
|
||||
NS_ERROR_GET_CODE(rv) == ERROR_FILE_CORRUPT)
|
||||
// We treat ERROR_FILE_CORRUPT as if the file did not exist at
|
||||
// all.
|
||||
|| (NS_ERROR_GET_MODULE(rv) == NS_ERROR_MODULE_WIN32 &&
|
||||
NS_ERROR_GET_CODE(rv) == ERROR_FILE_CORRUPT)
|
||||
#endif
|
||||
) {
|
||||
return nsIFileKind::DoesNotExist;
|
||||
}
|
||||
) {
|
||||
return nsIFileKind::DoesNotExist;
|
||||
}
|
||||
|
||||
return Err(rv);
|
||||
})));
|
||||
return Err(rv);
|
||||
}));
|
||||
}
|
||||
|
||||
Result<nsCOMPtr<mozIStorageStatement>, nsresult> CreateStatement(
|
||||
@ -347,9 +348,9 @@ nsDependentCSubstring MakeRelativeSourceFileName(
|
||||
|
||||
} // namespace detail
|
||||
|
||||
void LogError(const nsACString& aExpr, const Maybe<nsresult> aRv,
|
||||
const nsACString& aSourceFile, const int32_t aSourceLine,
|
||||
const Severity aSeverity) {
|
||||
void LogError(const nsACString& aExpr, const nsACString& aSourceFile,
|
||||
const int32_t aSourceLine, const Maybe<nsresult> aRv,
|
||||
const bool aIsWarning) {
|
||||
#if defined(EARLY_BETA_OR_EARLIER) || defined(DEBUG)
|
||||
nsAutoCString extraInfosString;
|
||||
|
||||
@ -370,18 +371,6 @@ void LogError(const nsACString& aExpr, const Maybe<nsresult> aRv,
|
||||
|
||||
const auto relativeSourceFile =
|
||||
detail::MakeRelativeSourceFileName(aSourceFile);
|
||||
|
||||
const auto severityString = [&aSeverity]() -> nsLiteralCString {
|
||||
switch (aSeverity) {
|
||||
case Severity::Error:
|
||||
return "ERROR"_ns;
|
||||
case Severity::Warning:
|
||||
return "WARNING"_ns;
|
||||
case Severity::Note:
|
||||
return "NOTE"_ns;
|
||||
}
|
||||
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Bad severity value!");
|
||||
}();
|
||||
#endif
|
||||
|
||||
#ifdef QM_ENABLE_SCOPED_LOG_EXTRA_INFO
|
||||
@ -393,22 +382,20 @@ void LogError(const nsACString& aExpr, const Maybe<nsresult> aRv,
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_DebugBreak(
|
||||
NS_DEBUG_WARNING,
|
||||
nsAutoCString("QM_TRY failure ("_ns + severityString + ")"_ns).get(),
|
||||
(extraInfosString.IsEmpty() ? nsPromiseFlatCString(aExpr)
|
||||
: static_cast<const nsCString&>(nsAutoCString(
|
||||
aExpr + extraInfosString)))
|
||||
.get(),
|
||||
nsPromiseFlatCString(relativeSourceFile).get(), aSourceLine);
|
||||
NS_DebugBreak(NS_DEBUG_WARNING, nsAutoCString("QM_TRY failure"_ns).get(),
|
||||
(extraInfosString.IsEmpty()
|
||||
? nsPromiseFlatCString(aExpr)
|
||||
: static_cast<const nsCString&>(
|
||||
nsAutoCString(aExpr + extraInfosString)))
|
||||
.get(),
|
||||
nsPromiseFlatCString(relativeSourceFile).get(), aSourceLine);
|
||||
#endif
|
||||
|
||||
#if defined(EARLY_BETA_OR_EARLIER) || defined(DEBUG)
|
||||
nsCOMPtr<nsIConsoleService> console =
|
||||
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
||||
if (console) {
|
||||
NS_ConvertUTF8toUTF16 message("QM_TRY failure ("_ns + severityString +
|
||||
")"_ns + ": '"_ns + aExpr + "' at "_ns +
|
||||
NS_ConvertUTF8toUTF16 message("QM_TRY failure: '"_ns + aExpr + "' at "_ns +
|
||||
relativeSourceFile + ":"_ns +
|
||||
IntToCString(aSourceLine) + extraInfosString);
|
||||
|
||||
@ -436,7 +423,8 @@ void LogError(const nsACString& aExpr, const Maybe<nsresult> aRv,
|
||||
EventExtraEntry{"source_line"_ns, IntToCString(aSourceLine)});
|
||||
res.AppendElement(EventExtraEntry{
|
||||
"context"_ns, nsPromiseFlatCString{*contextIt->second}});
|
||||
res.AppendElement(EventExtraEntry{"severity"_ns, severityString});
|
||||
res.AppendElement(EventExtraEntry{
|
||||
"severity"_ns, aIsWarning ? "WARNING"_ns : "ERROR"_ns});
|
||||
|
||||
if (!rvName.IsEmpty()) {
|
||||
res.AppendElement(EventExtraEntry{"result"_ns, nsCString{rvName}});
|
||||
|
@ -447,31 +447,11 @@ class NotNull;
|
||||
} while (0)
|
||||
|
||||
#ifdef DEBUG
|
||||
# define QM_HANDLE_ERROR(expr, error, severity) \
|
||||
HandleError(#expr, error, __FILE__, __LINE__, severity)
|
||||
# define QM_HANDLE_ERROR(expr, error) \
|
||||
HandleError(#expr, error, __FILE__, __LINE__)
|
||||
#else
|
||||
# define QM_HANDLE_ERROR(expr, error, severity) \
|
||||
HandleError("Unavailable", error, __FILE__, __LINE__, severity)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
# define QM_HANDLE_ERROR_RETURN_NOTHING(expr, error, severity) \
|
||||
HandleErrorReturnNothing(#expr, error, __FILE__, __LINE__, severity)
|
||||
#else
|
||||
# define QM_HANDLE_ERROR_RETURN_NOTHING(expr, error, severity) \
|
||||
HandleErrorReturnNothing("Unavailable", error, __FILE__, __LINE__, severity)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
# define QM_HANDLE_ERROR_WITH_CLEANUP_RETURN_NOTHING(expr, error, severity, \
|
||||
cleanup) \
|
||||
HandleErrorWithCleanupReturnNothing(#expr, error, __FILE__, __LINE__, \
|
||||
severity, cleanup)
|
||||
#else
|
||||
# define QM_HANDLE_ERROR_WITH_CLEANUP_RETURN_NOTHING(expr, error, severity, \
|
||||
cleanup) \
|
||||
HandleErrorWithCleanupReturnNothing("Unavailable", error, __FILE__, \
|
||||
__LINE__, severity, cleanup)
|
||||
# define QM_HANDLE_ERROR(expr, error) \
|
||||
HandleError("Unavailable", error, __FILE__, __LINE__)
|
||||
#endif
|
||||
|
||||
// QM_TRY_PROPAGATE_ERR, QM_TRY_CUSTOM_RET_VAL,
|
||||
@ -483,8 +463,7 @@ class NotNull;
|
||||
auto tryResult = ::mozilla::ToResult(expr); \
|
||||
static_assert(std::is_empty_v<typename decltype(tryResult)::ok_type>); \
|
||||
if (MOZ_UNLIKELY(tryResult.isErr())) { \
|
||||
ns::QM_HANDLE_ERROR(expr, tryResult.inspectErr(), \
|
||||
mozilla::dom::quota::Severity::Error); \
|
||||
ns::QM_HANDLE_ERROR(expr, tryResult.inspectErr()); \
|
||||
return tryResult.propagateErr(); \
|
||||
}
|
||||
|
||||
@ -495,8 +474,7 @@ class NotNull;
|
||||
static_assert(std::is_empty_v<typename decltype(tryResult)::ok_type>); \
|
||||
if (MOZ_UNLIKELY(tryResult.isErr())) { \
|
||||
auto tryTempError MOZ_MAYBE_UNUSED = tryResult.unwrapErr(); \
|
||||
ns::QM_HANDLE_ERROR(expr, tryTempError, \
|
||||
mozilla::dom::quota::Severity::Error); \
|
||||
ns::QM_HANDLE_ERROR(expr, tryTempError); \
|
||||
return customRetVal; \
|
||||
}
|
||||
|
||||
@ -508,8 +486,7 @@ class NotNull;
|
||||
static_assert(std::is_empty_v<typename decltype(tryResult)::ok_type>); \
|
||||
if (MOZ_UNLIKELY(tryResult.isErr())) { \
|
||||
auto tryTempError = tryResult.unwrapErr(); \
|
||||
ns::QM_HANDLE_ERROR(expr, tryTempError, \
|
||||
mozilla::dom::quota::Severity::Error); \
|
||||
ns::QM_HANDLE_ERROR(expr, tryTempError); \
|
||||
cleanup(tryTempError); \
|
||||
return customRetVal; \
|
||||
}
|
||||
@ -536,8 +513,8 @@ class NotNull;
|
||||
|
||||
/**
|
||||
* QM_TRY(expr[, customRetVal, cleanup]) is the C++ equivalent of Rust's
|
||||
* `try!(expr);`. First, it evaluates expr, which must produce a Result value
|
||||
* with empty ok_type. On Success, it does nothing else. On error, it calls
|
||||
* `try!(expr);`. First, it evaluates expr, which must produce a Result value.
|
||||
* On success, it discards the result altogether. On error, it calls
|
||||
* HandleError and an additional cleanup function (if the third argument was
|
||||
* passed) and finally returns an error Result from the enclosing function or a
|
||||
* custom return value (if the second argument was passed).
|
||||
@ -554,8 +531,7 @@ class NotNull;
|
||||
expr) \
|
||||
auto tryResult = (expr); \
|
||||
if (MOZ_UNLIKELY(tryResult.isErr())) { \
|
||||
ns::QM_HANDLE_ERROR(expr, tryResult.inspectErr(), \
|
||||
mozilla::dom::quota::Severity::Error); \
|
||||
ns::QM_HANDLE_ERROR(expr, tryResult.inspectErr()); \
|
||||
return tryResult.propagateErr(); \
|
||||
} \
|
||||
MOZ_REMOVE_PAREN(target) = tryResult.accessFunction();
|
||||
@ -567,8 +543,7 @@ class NotNull;
|
||||
auto tryResult = (expr); \
|
||||
if (MOZ_UNLIKELY(tryResult.isErr())) { \
|
||||
auto tryTempError MOZ_MAYBE_UNUSED = tryResult.unwrapErr(); \
|
||||
ns::QM_HANDLE_ERROR(expr, tryTempError, \
|
||||
mozilla::dom::quota::Severity::Error); \
|
||||
ns::QM_HANDLE_ERROR(expr, tryTempError); \
|
||||
return customRetVal; \
|
||||
} \
|
||||
MOZ_REMOVE_PAREN(target) = tryResult.accessFunction();
|
||||
@ -580,8 +555,7 @@ class NotNull;
|
||||
auto tryResult = (expr); \
|
||||
if (MOZ_UNLIKELY(tryResult.isErr())) { \
|
||||
auto tryTempError = tryResult.unwrapErr(); \
|
||||
ns::QM_HANDLE_ERROR(expr, tryTempError, \
|
||||
mozilla::dom::quota::Severity::Error); \
|
||||
ns::QM_HANDLE_ERROR(expr, tryTempError); \
|
||||
cleanup(tryTempError); \
|
||||
return customRetVal; \
|
||||
} \
|
||||
@ -638,12 +612,11 @@ class NotNull;
|
||||
// Note that this deliberately uses a single return statement without going
|
||||
// through unwrap/unwrapErr/propagateErr, so that this does not prevent NRVO or
|
||||
// tail call optimizations when possible.
|
||||
#define QM_TRY_RETURN_PROPAGATE_ERR(ns, tryResult, expr) \
|
||||
auto tryResult = ::mozilla::ToResult(expr); \
|
||||
if (MOZ_UNLIKELY(tryResult.isErr())) { \
|
||||
ns::QM_HANDLE_ERROR(expr, tryResult.inspectErr(), \
|
||||
mozilla::dom::quota::Severity::Error); \
|
||||
} \
|
||||
#define QM_TRY_RETURN_PROPAGATE_ERR(ns, tryResult, expr) \
|
||||
auto tryResult = ::mozilla::ToResult(expr); \
|
||||
if (MOZ_UNLIKELY(tryResult.isErr())) { \
|
||||
ns::QM_HANDLE_ERROR(expr, tryResult.inspectErr()); \
|
||||
} \
|
||||
return tryResult;
|
||||
|
||||
// Handles the four arguments case when a custom return value needs to be
|
||||
@ -652,8 +625,7 @@ class NotNull;
|
||||
auto tryResult = ::mozilla::ToResult(expr); \
|
||||
if (MOZ_UNLIKELY(tryResult.isErr())) { \
|
||||
auto tryTempError MOZ_MAYBE_UNUSED = tryResult.unwrapErr(); \
|
||||
ns::QM_HANDLE_ERROR(expr, tryResult.inspectErr(), \
|
||||
mozilla::dom::quota::Severity::Error); \
|
||||
ns::QM_HANDLE_ERROR(expr, tryResult.inspectErr()); \
|
||||
return customRetVal; \
|
||||
} \
|
||||
return tryResult.unwrap();
|
||||
@ -665,8 +637,7 @@ class NotNull;
|
||||
auto tryResult = ::mozilla::ToResult(expr); \
|
||||
if (MOZ_UNLIKELY(tryResult.isErr())) { \
|
||||
auto tryTempError = tryResult.unwrapErr(); \
|
||||
ns::QM_HANDLE_ERROR(expr, tryTempError, \
|
||||
mozilla::dom::quota::Severity::Error); \
|
||||
ns::QM_HANDLE_ERROR(expr, tryTempError); \
|
||||
cleanup(tryTempError); \
|
||||
return customRetVal; \
|
||||
} \
|
||||
@ -704,15 +675,15 @@ class NotNull;
|
||||
// details of QM_FAIL and shouldn't be used directly.
|
||||
|
||||
// Handles the two arguments case when just an error is returned
|
||||
#define QM_FAIL_RET_VAL(ns, retVal) \
|
||||
ns::QM_HANDLE_ERROR(Failure, 0, mozilla::dom::quota::Severity::Error); \
|
||||
#define QM_FAIL_RET_VAL(ns, retVal) \
|
||||
ns::QM_HANDLE_ERROR(Failure, 0); \
|
||||
return retVal;
|
||||
|
||||
// Handles the three arguments case when a cleanup function needs to be called
|
||||
// before a return value is returned
|
||||
#define QM_FAIL_RET_VAL_WITH_CLEANUP(ns, retVal, cleanup) \
|
||||
ns::QM_HANDLE_ERROR(Failure, 0, mozilla::dom::quota::Severity::Error); \
|
||||
cleanup(); \
|
||||
#define QM_FAIL_RET_VAL_WITH_CLEANUP(ns, retVal, cleanup) \
|
||||
ns::QM_HANDLE_ERROR(Failure, 0); \
|
||||
cleanup(); \
|
||||
return retVal;
|
||||
|
||||
// Chooses the final implementation macro for given argument count.
|
||||
@ -732,159 +703,6 @@ class NotNull;
|
||||
*/
|
||||
#define QM_FAIL(...) QM_FAIL_GLUE(__VA_ARGS__)
|
||||
|
||||
// QM_REPORTONLY_TRY, QM_REPORTONLY_TRY_WITH_CLEANUP, QM_REPORTONLY_TRY_GLUE
|
||||
// macros are implementation details of QM_WARNONLY_TRY/QM_NOTEONLY_TRY and
|
||||
// shouldn't be used directly.
|
||||
|
||||
// Handles the four arguments case when only a warning/note is reported.
|
||||
#define QM_REPORTONLY_TRY(ns, tryResult, severity, expr) \
|
||||
auto tryResult = ::mozilla::ToResult(expr); \
|
||||
static_assert(std::is_empty_v<typename decltype(tryResult)::ok_type>); \
|
||||
if (MOZ_UNLIKELY(tryResult.isErr())) { \
|
||||
ns::QM_HANDLE_ERROR(expr, tryResult.unwrapErr(), \
|
||||
mozilla::dom::quota::Severity::severity); \
|
||||
}
|
||||
|
||||
// Handles the five arguments case when a cleanup function needs to be called
|
||||
#define QM_REPORTONLY_TRY_WITH_CLEANUP(ns, tryResult, severity, expr, cleanup) \
|
||||
auto tryResult = ::mozilla::ToResult(expr); \
|
||||
static_assert(std::is_empty_v<typename decltype(tryResult)::ok_type>); \
|
||||
if (MOZ_UNLIKELY(tryResult.isErr())) { \
|
||||
auto tryTempError = tryResult.unwrapErr(); \
|
||||
ns::QM_HANDLE_ERROR(expr, tryTempError, \
|
||||
mozilla::dom::quota::Severity::severity); \
|
||||
cleanup(tryTempError); \
|
||||
}
|
||||
|
||||
// Chooses the final implementation macro for given argument count.
|
||||
// It can be used by other modules to define module specific error handling.
|
||||
// See also the comment for QM_TRY_META.
|
||||
#define QM_REPORTONLY_TRY_META(...) \
|
||||
{ \
|
||||
MOZ_ARG_7(, ##__VA_ARGS__, QM_REPORTONLY_TRY_WITH_CLEANUP(__VA_ARGS__), \
|
||||
QM_REPORTONLY_TRY(__VA_ARGS__), QM_MISSING_ARGS(__VA_ARGS__), \
|
||||
QM_MISSING_ARGS(__VA_ARGS__), QM_MISSING_ARGS(__VA_ARGS__), \
|
||||
QM_MISSING_ARGS(__VA_ARGS__)) \
|
||||
}
|
||||
|
||||
// Specifies the namespace and generates unique variable name. This extra
|
||||
// internal macro (along with __COUNTER__) allows nesting of the final macro.
|
||||
#define QM_REPORTONLY_TRY_GLUE(severity, ...) \
|
||||
QM_REPORTONLY_TRY_META(mozilla::dom::quota, MOZ_UNIQUE_VAR(tryResult), \
|
||||
severity, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* QM_WARNONLY_TRY(expr[, cleanup]) evaluates expr, which must produce a
|
||||
* Result value with empty ok_type. On Success, it does nothing else. On error,
|
||||
* it calls HandleError and an additional cleanup function (if the second
|
||||
* argument was passed). This macro never returns and failures are always
|
||||
* reported using a lower level of severity relative to failures reported by
|
||||
* QM_TRY. The macro is intended for failures that should not be propagated.
|
||||
*/
|
||||
#define QM_WARNONLY_TRY(...) QM_REPORTONLY_TRY_GLUE(Warning, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* QM_NOTEONLY_TRY is like QM_WARNONLY_TRY. The only difference is that
|
||||
* failures are reported using a lower level of severity relative to failures
|
||||
* reported by QM_WARNONLY_TRY.
|
||||
*/
|
||||
#define QM_NOTEONLY_TRY(...) QM_REPORTONLY_TRY_GLUE(Note, __VA_ARGS__)
|
||||
|
||||
// QM_REPORTONLY_TRY_ASSIGN, QM_REPORTONLY_TRY_ASSIGN_WITH_CLEANUP,
|
||||
// QM_REPORTONLY_TRY_ASSIGN_GLUE macros are implementation details of
|
||||
// QM_WARNONLY_TRY_UNWRAP/QM_NOTEONLY_TRY_UNWRAP and shouldn't be used
|
||||
// directly.
|
||||
|
||||
// Handles the five arguments case when only a warning/note is reported.
|
||||
#define QM_REPORTONLY_TRY_ASSIGN(ns, tryResult, severity, target, expr) \
|
||||
auto tryResult = (expr); \
|
||||
MOZ_REMOVE_PAREN(target) = \
|
||||
MOZ_LIKELY(tryResult.isOk()) \
|
||||
? Some(tryResult.unwrap()) \
|
||||
: ns::QM_HANDLE_ERROR_RETURN_NOTHING( \
|
||||
expr, tryResult.unwrapErr(), \
|
||||
mozilla::dom::quota::Severity::severity);
|
||||
|
||||
// Handles the six arguments case when a cleanup function needs to be called
|
||||
#define QM_REPORTONLY_TRY_ASSIGN_WITH_CLEANUP(ns, tryResult, severity, target, \
|
||||
expr, cleanup) \
|
||||
auto tryResult = (expr); \
|
||||
MOZ_REMOVE_PAREN(target) = \
|
||||
MOZ_LIKELY(tryResult.isOk()) \
|
||||
? Some(tryResult.unwrap()) \
|
||||
: ns::QM_HANDLE_ERROR_WITH_CLEANUP_RETURN_NOTHING( \
|
||||
expr, tryResult.unwrapErr(), \
|
||||
mozilla::dom::quota::Severity::severity, cleanup);
|
||||
|
||||
// Chooses the final implementation macro for given argument count.
|
||||
// It can be used by other modules to define module specific error handling.
|
||||
// See also the comment for QM_TRY_META.
|
||||
#define QM_REPORTONLY_TRY_ASSIGN_META(...) \
|
||||
MOZ_ARG_8( \
|
||||
, ##__VA_ARGS__, QM_REPORTONLY_TRY_ASSIGN_WITH_CLEANUP(__VA_ARGS__), \
|
||||
QM_REPORTONLY_TRY_ASSIGN(__VA_ARGS__), QM_MISSING_ARGS(__VA_ARGS__), \
|
||||
QM_MISSING_ARGS(__VA_ARGS__), QM_MISSING_ARGS(__VA_ARGS__), \
|
||||
QM_MISSING_ARGS(__VA_ARGS__), QM_MISSING_ARGS(__VA_ARGS__))
|
||||
|
||||
// Specifies the namespace and generates unique variable name. This extra
|
||||
// internal macro (along with __COUNTER__) allows nesting of the final macro.
|
||||
#define QM_REPORTONLY_TRY_ASSIGN_GLUE(severity, ...) \
|
||||
QM_REPORTONLY_TRY_ASSIGN_META( \
|
||||
mozilla::dom::quota, MOZ_UNIQUE_VAR(tryResult), severity, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* QM_WARNONLY_TRY_UNWRAP(target, expr[, cleanup]) evaluates expr, which must
|
||||
* produce a Result value. On success, the result's success value is first
|
||||
* unwrapped from the Result, then wrapped in a Maybe and finally assigned to
|
||||
* target. On error, it calls HandleError and an additional cleanup
|
||||
* function (if the third argument was passed) and finally assigns Nothing to
|
||||
* target. |target| must be an lvalue. This macro never returns and failures
|
||||
* are always reported using a lower level of severity relative to failures
|
||||
* reported by QM_TRY_UNWRAP/QM_TRY_INSPECT. The macro is intended for failures
|
||||
* that should not be propagated.
|
||||
*/
|
||||
#define QM_WARNONLY_TRY_UNWRAP(...) \
|
||||
QM_REPORTONLY_TRY_ASSIGN_GLUE(Warning, __VA_ARGS__)
|
||||
|
||||
// QM_WARNONLY_TRY_INSPECT doesn't make sense.
|
||||
|
||||
/**
|
||||
* QM_NOTEONLY_TRY_UNWRAP is like QM_WARN_CHECK_UNWRAP. The only difference is
|
||||
* that failures are reported using a lower level of severity relative to
|
||||
* failures reported by QM_WARN_CHECK_UNWRAP.
|
||||
*/
|
||||
#define QM_NOTEONLY_TRY_UNWRAP(...) \
|
||||
QM_REPORTONLY_TRY_ASSIGN_GLUE(Note, __VA_ARGS__)
|
||||
|
||||
// QM_NOTEONLY_TRY_INSPECT doesn't make sense.
|
||||
|
||||
/*
|
||||
* QM_OR_ELSE_WARN(expr, orElse) evaluates expr, which must produce a Result
|
||||
* value. On Success, it just moves the success over. On error, it calls
|
||||
* HandleError and a custom orElse function (passed as the second argument).
|
||||
* Failures are always reported as warnings. The macro essentially wraps the
|
||||
* orElse function with a warning. The macro is a sub macro and is intended to
|
||||
* be used along with one of the main macros such as QM_TRY.
|
||||
*/
|
||||
#define QM_OR_ELSE_WARN(expr, orElseFunc) \
|
||||
(expr).orElse([&](const auto& firstRes) { \
|
||||
mozilla::dom::quota::QM_HANDLE_ERROR( \
|
||||
#expr, firstRes, mozilla::dom::quota::Severity::Warning); \
|
||||
return orElseFunc(firstRes); \
|
||||
})
|
||||
|
||||
/**
|
||||
* QM_OR_ELSE_NOTE is like QM_OR_ELSE_WARN. The only difference is that
|
||||
* failures are reported using a lower level of severity relative to failures
|
||||
* reported by QM_OR_ELSE_WARN.
|
||||
*/
|
||||
#define QM_OR_ELSE_NOTE(expr, orElseFunc) \
|
||||
(expr).orElse([&](const auto& firstRes) { \
|
||||
mozilla::dom::quota::QM_HANDLE_ERROR(#expr, firstRes, \
|
||||
mozilla::dom::quota::Severity::Note); \
|
||||
return orElseFunc(firstRes); \
|
||||
})
|
||||
|
||||
// Telemetry probes to collect number of failure during the initialization.
|
||||
#ifdef NIGHTLY_BUILD
|
||||
# define RECORD_IN_NIGHTLY(_recorder, _status) \
|
||||
@ -942,7 +760,7 @@ auto ErrToOkOrErr(nsresult aValue) -> Result<V, nsresult> {
|
||||
return Err(aValue);
|
||||
}
|
||||
|
||||
template <nsresult ErrorValue, typename V = mozilla::Ok>
|
||||
template <nsresult ErrorValue, typename V>
|
||||
auto ErrToDefaultOkOrErr(nsresult aValue) -> Result<V, nsresult> {
|
||||
if (aValue == ErrorValue) {
|
||||
return V{};
|
||||
@ -1198,15 +1016,9 @@ nsDependentCSubstring MakeRelativeSourceFileName(const nsACString& aSourceFile);
|
||||
|
||||
} // namespace detail
|
||||
|
||||
enum class Severity {
|
||||
Error,
|
||||
Warning,
|
||||
Note,
|
||||
};
|
||||
|
||||
void LogError(const nsACString& aExpr, Maybe<nsresult> aRv,
|
||||
const nsACString& aSourceFile, int32_t aSourceLine,
|
||||
Severity aSeverity);
|
||||
void LogError(const nsACString& aExpr, const nsACString& aSourceFile,
|
||||
int32_t aSourceLine, Maybe<nsresult> aRv,
|
||||
bool aIsWarning = false);
|
||||
|
||||
#ifdef DEBUG
|
||||
Result<bool, nsresult> WarnIfFileIsUnknown(nsIFile& aFile,
|
||||
@ -1284,45 +1096,24 @@ struct MOZ_STACK_CLASS ScopedLogExtraInfo {
|
||||
#if defined(EARLY_BETA_OR_EARLIER) || defined(DEBUG)
|
||||
template <typename T>
|
||||
MOZ_COLD void HandleError(const char* aExpr, const T& aRv,
|
||||
const char* aSourceFile, int32_t aSourceLine,
|
||||
const Severity aSeverity) {
|
||||
const char* aSourceFile, int32_t aSourceLine) {
|
||||
if constexpr (std::is_same_v<T, nsresult>) {
|
||||
mozilla::dom::quota::LogError(nsDependentCString(aExpr), Some(aRv),
|
||||
mozilla::dom::quota::LogError(nsDependentCString(aExpr),
|
||||
nsDependentCString(aSourceFile), aSourceLine,
|
||||
aSeverity);
|
||||
Some(aRv));
|
||||
} else {
|
||||
mozilla::dom::quota::LogError(nsDependentCString(aExpr), Nothing{},
|
||||
mozilla::dom::quota::LogError(nsDependentCString(aExpr),
|
||||
nsDependentCString(aSourceFile), aSourceLine,
|
||||
aSeverity);
|
||||
Nothing{});
|
||||
}
|
||||
}
|
||||
#else
|
||||
template <typename T>
|
||||
MOZ_ALWAYS_INLINE constexpr void HandleError(const char* aExpr, const T& aRv,
|
||||
const char* aSourceFile,
|
||||
int32_t aSourceLine,
|
||||
const Severity aSeverity) {}
|
||||
int32_t aSourceLine) {}
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
Nothing HandleErrorReturnNothing(const char* aExpr, const T& aRv,
|
||||
const char* aSourceFile, int32_t aSourceLine,
|
||||
const Severity aSeverity) {
|
||||
HandleError(aExpr, aRv, aSourceFile, aSourceLine, aSeverity);
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
template <typename T, typename CleanupFunc>
|
||||
Nothing HandleErrorWithCleanupReturnNothing(const char* aExpr, const T& aRv,
|
||||
const char* aSourceFile,
|
||||
int32_t aSourceLine,
|
||||
const Severity aSeverity,
|
||||
CleanupFunc&& aCleanupFunc) {
|
||||
HandleError(aExpr, aRv, aSourceFile, aSourceLine, aSeverity);
|
||||
std::forward<CleanupFunc>(aCleanupFunc)(aRv);
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
template <SingleStepResult ResultHandling = SingleStepResult::AssertHasResult,
|
||||
typename BindFunctor>
|
||||
Result<SingleStepSuccessType<ResultHandling>, nsresult>
|
||||
|
@ -1022,228 +1022,6 @@ TEST(QuotaCommon_Fail, ReturnValue_WithCleanup)
|
||||
EXPECT_EQ(rv, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
TEST(QuotaCommon_WarnOnlyTry, Success)
|
||||
{
|
||||
bool warnOnlyTryDidNotReturn = false;
|
||||
|
||||
const auto res =
|
||||
[&warnOnlyTryDidNotReturn]() -> mozilla::Result<mozilla::Ok, NotOk> {
|
||||
QM_WARNONLY_TRY(OkIf(true));
|
||||
|
||||
warnOnlyTryDidNotReturn = true;
|
||||
return mozilla::Ok{};
|
||||
}();
|
||||
|
||||
EXPECT_TRUE(res.isOk());
|
||||
EXPECT_TRUE(warnOnlyTryDidNotReturn);
|
||||
}
|
||||
|
||||
TEST(QuotaCommon_WarnOnlyTry, Success_WithCleanup)
|
||||
{
|
||||
bool warnOnlyTryCleanupRan = false;
|
||||
bool warnOnlyTryDidNotReturn = false;
|
||||
|
||||
const auto res =
|
||||
[&warnOnlyTryCleanupRan,
|
||||
&warnOnlyTryDidNotReturn]() -> mozilla::Result<mozilla::Ok, NotOk> {
|
||||
QM_WARNONLY_TRY(OkIf(true), [&warnOnlyTryCleanupRan](const auto&) {
|
||||
warnOnlyTryCleanupRan = true;
|
||||
});
|
||||
|
||||
warnOnlyTryDidNotReturn = true;
|
||||
return mozilla::Ok{};
|
||||
}();
|
||||
|
||||
EXPECT_TRUE(res.isOk());
|
||||
EXPECT_FALSE(warnOnlyTryCleanupRan);
|
||||
EXPECT_TRUE(warnOnlyTryDidNotReturn);
|
||||
}
|
||||
|
||||
TEST(QuotaCommon_WarnOnlyTry, Failure)
|
||||
{
|
||||
bool warnOnlyTryDidNotReturn = false;
|
||||
|
||||
const auto res =
|
||||
[&warnOnlyTryDidNotReturn]() -> mozilla::Result<mozilla::Ok, NotOk> {
|
||||
QM_WARNONLY_TRY(OkIf(false));
|
||||
|
||||
warnOnlyTryDidNotReturn = true;
|
||||
return mozilla::Ok{};
|
||||
}();
|
||||
|
||||
EXPECT_TRUE(res.isOk());
|
||||
EXPECT_TRUE(warnOnlyTryDidNotReturn);
|
||||
}
|
||||
|
||||
TEST(QuotaCommon_WarnOnlyTry, Failure_WithCleanup)
|
||||
{
|
||||
bool warnOnlyTryCleanupRan = false;
|
||||
bool warnOnlyTryDidNotReturn = false;
|
||||
|
||||
const auto res =
|
||||
[&warnOnlyTryCleanupRan,
|
||||
&warnOnlyTryDidNotReturn]() -> mozilla::Result<mozilla::Ok, NotOk> {
|
||||
QM_WARNONLY_TRY(OkIf(false), ([&warnOnlyTryCleanupRan](const auto&) {
|
||||
warnOnlyTryCleanupRan = true;
|
||||
}));
|
||||
|
||||
warnOnlyTryDidNotReturn = true;
|
||||
return mozilla::Ok{};
|
||||
}();
|
||||
|
||||
EXPECT_TRUE(res.isOk());
|
||||
EXPECT_TRUE(warnOnlyTryCleanupRan);
|
||||
EXPECT_TRUE(warnOnlyTryDidNotReturn);
|
||||
}
|
||||
|
||||
TEST(QuotaCommon_WarnOnlyTryUnwrap, Success)
|
||||
{
|
||||
bool warnOnlyTryUnwrapDidNotReturn = false;
|
||||
|
||||
const auto res = [&warnOnlyTryUnwrapDidNotReturn]()
|
||||
-> mozilla::Result<mozilla::Ok, NotOk> {
|
||||
QM_WARNONLY_TRY_UNWRAP(const auto x, (Result<int32_t, NotOk>{42}));
|
||||
EXPECT_TRUE(x);
|
||||
EXPECT_EQ(*x, 42);
|
||||
|
||||
warnOnlyTryUnwrapDidNotReturn = true;
|
||||
return mozilla::Ok{};
|
||||
}();
|
||||
|
||||
EXPECT_TRUE(res.isOk());
|
||||
EXPECT_TRUE(warnOnlyTryUnwrapDidNotReturn);
|
||||
}
|
||||
|
||||
TEST(QuotaCommon_WarnOnlyTryUnwrap, Success_WithCleanup)
|
||||
{
|
||||
bool warnOnlyTryUnwrapCleanupRan = false;
|
||||
bool warnOnlyTryUnwrapDidNotReturn = false;
|
||||
|
||||
const auto res = [&warnOnlyTryUnwrapCleanupRan,
|
||||
&warnOnlyTryUnwrapDidNotReturn]()
|
||||
-> mozilla::Result<mozilla::Ok, NotOk> {
|
||||
QM_WARNONLY_TRY_UNWRAP(const auto x, (Result<int32_t, NotOk>{42}),
|
||||
[&warnOnlyTryUnwrapCleanupRan](const auto&) {
|
||||
warnOnlyTryUnwrapCleanupRan = true;
|
||||
});
|
||||
EXPECT_TRUE(x);
|
||||
EXPECT_EQ(*x, 42);
|
||||
|
||||
warnOnlyTryUnwrapDidNotReturn = true;
|
||||
return mozilla::Ok{};
|
||||
}();
|
||||
|
||||
EXPECT_TRUE(res.isOk());
|
||||
EXPECT_FALSE(warnOnlyTryUnwrapCleanupRan);
|
||||
EXPECT_TRUE(warnOnlyTryUnwrapDidNotReturn);
|
||||
}
|
||||
|
||||
TEST(QuotaCommon_WarnOnlyTryUnwrap, Failure)
|
||||
{
|
||||
bool warnOnlyTryUnwrapDidNotReturn = false;
|
||||
|
||||
const auto res = [&warnOnlyTryUnwrapDidNotReturn]()
|
||||
-> mozilla::Result<mozilla::Ok, NotOk> {
|
||||
QM_WARNONLY_TRY_UNWRAP(const auto x,
|
||||
(Result<int32_t, NotOk>{Err(NotOk{})}));
|
||||
EXPECT_FALSE(x);
|
||||
|
||||
warnOnlyTryUnwrapDidNotReturn = true;
|
||||
return mozilla::Ok{};
|
||||
}();
|
||||
|
||||
EXPECT_TRUE(res.isOk());
|
||||
EXPECT_TRUE(warnOnlyTryUnwrapDidNotReturn);
|
||||
}
|
||||
|
||||
TEST(QuotaCommon_WarnOnlyTryUnwrap, Failure_WithCleanup)
|
||||
{
|
||||
bool warnOnlyTryUnwrapCleanupRan = false;
|
||||
bool warnOnlyTryUnwrapDidNotReturn = false;
|
||||
|
||||
const auto res = [&warnOnlyTryUnwrapCleanupRan,
|
||||
&warnOnlyTryUnwrapDidNotReturn]()
|
||||
-> mozilla::Result<mozilla::Ok, NotOk> {
|
||||
QM_WARNONLY_TRY_UNWRAP(const auto x, (Result<int32_t, NotOk>{Err(NotOk{})}),
|
||||
[&warnOnlyTryUnwrapCleanupRan](const auto&) {
|
||||
warnOnlyTryUnwrapCleanupRan = true;
|
||||
});
|
||||
EXPECT_FALSE(x);
|
||||
|
||||
warnOnlyTryUnwrapDidNotReturn = true;
|
||||
return mozilla::Ok{};
|
||||
}();
|
||||
|
||||
EXPECT_TRUE(res.isOk());
|
||||
EXPECT_TRUE(warnOnlyTryUnwrapCleanupRan);
|
||||
EXPECT_TRUE(warnOnlyTryUnwrapDidNotReturn);
|
||||
}
|
||||
|
||||
TEST(QuotaCommon_OrElseWarn, Success)
|
||||
{
|
||||
bool orElseWarnRun = false;
|
||||
bool tryContinued = false;
|
||||
|
||||
const auto res = [&]() -> mozilla::Result<mozilla::Ok, NotOk> {
|
||||
QM_TRY(QM_OR_ELSE_WARN(OkIf(true), ([&orElseWarnRun](const NotOk) {
|
||||
orElseWarnRun = true;
|
||||
return mozilla::Result<mozilla::Ok, NotOk>{
|
||||
mozilla::Ok{}};
|
||||
})));
|
||||
|
||||
tryContinued = true;
|
||||
return mozilla::Ok{};
|
||||
}();
|
||||
|
||||
EXPECT_TRUE(res.isOk());
|
||||
EXPECT_FALSE(orElseWarnRun);
|
||||
EXPECT_TRUE(tryContinued);
|
||||
}
|
||||
|
||||
TEST(QuotaCommon_OrElseWarn, Failure_MappedToSuccess)
|
||||
{
|
||||
bool orElseWarnRun = false;
|
||||
bool tryContinued = false;
|
||||
|
||||
// XXX Consider allowing to set a custom error handler, so that we can
|
||||
// actually assert that a warning was emitted.
|
||||
const auto res = [&]() -> mozilla::Result<mozilla::Ok, NotOk> {
|
||||
QM_TRY(QM_OR_ELSE_WARN(OkIf(false), ([&orElseWarnRun](const NotOk) {
|
||||
orElseWarnRun = true;
|
||||
return mozilla::Result<mozilla::Ok, NotOk>{
|
||||
mozilla::Ok{}};
|
||||
})));
|
||||
tryContinued = true;
|
||||
return mozilla::Ok{};
|
||||
}();
|
||||
|
||||
EXPECT_TRUE(res.isOk());
|
||||
EXPECT_TRUE(orElseWarnRun);
|
||||
EXPECT_TRUE(tryContinued);
|
||||
}
|
||||
|
||||
TEST(QuotaCommon_OrElseWarn, Failure_MappedToError)
|
||||
{
|
||||
bool orElseWarnRun = false;
|
||||
bool tryContinued = false;
|
||||
|
||||
// XXX Consider allowing to set a custom error handler, so that we can
|
||||
// actually assert that a warning was emitted.
|
||||
const auto res = [&]() -> mozilla::Result<mozilla::Ok, NotOk> {
|
||||
QM_TRY(QM_OR_ELSE_WARN(OkIf(false), ([&orElseWarnRun](const NotOk) {
|
||||
orElseWarnRun = true;
|
||||
return mozilla::Result<mozilla::Ok, NotOk>{
|
||||
NotOk{}};
|
||||
})));
|
||||
tryContinued = true;
|
||||
return mozilla::Ok{};
|
||||
}();
|
||||
|
||||
EXPECT_TRUE(res.isErr());
|
||||
EXPECT_TRUE(orElseWarnRun);
|
||||
EXPECT_FALSE(tryContinued);
|
||||
}
|
||||
|
||||
TEST(QuotaCommon_OkIf, True)
|
||||
{
|
||||
auto res = OkIf(true);
|
||||
|
Loading…
Reference in New Issue
Block a user