Bug 1645943 - Check results from nsIFile's functions rather than mozStorage's/SQLite's in LockedGetPaddingSizeFromDB; r=janv,dom-workers-and-storage-reviewers,sg

Differential Revision: https://phabricator.services.mozilla.com/D79959
This commit is contained in:
Tom Tung 2020-06-23 06:38:25 +00:00
parent b5493ef467
commit ad521d4997
4 changed files with 64 additions and 42 deletions

View File

@ -33,12 +33,18 @@ using mozilla::dom::quota::PersistenceType;
namespace {
nsresult WipeDatabase(const QuotaInfo& aQuotaInfo, nsIFile* aDBFile,
nsIFile* aDBDir) {
nsresult WipeDatabase(const QuotaInfo& aQuotaInfo, nsIFile* aDBFile) {
MOZ_DIAGNOSTIC_ASSERT(aDBFile);
MOZ_DIAGNOSTIC_ASSERT(aDBDir);
nsresult rv = RemoveNsIFile(aQuotaInfo, aDBFile);
nsCOMPtr<nsIFile> dbDir;
nsresult rv = aDBFile->GetParent(getter_AddRefs(dbDir));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(dbDir);
rv = RemoveNsIFile(aQuotaInfo, aDBFile);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -47,12 +53,12 @@ nsresult WipeDatabase(const QuotaInfo& aQuotaInfo, nsIFile* aDBFile,
// the new database is created. No need to explicitly delete it here.
// Delete the morgue as well.
rv = BodyDeleteDir(aQuotaInfo, aDBDir);
rv = BodyDeleteDir(aQuotaInfo, dbDir);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = WipePaddingFile(aQuotaInfo, aDBDir);
rv = WipePaddingFile(aQuotaInfo, dbDir);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -144,11 +150,20 @@ nsresult DBAction::OpenConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
}
}
rv = OpenDBConnection(aQuotaInfo, aDBDir, aConnOut);
nsCOMPtr<nsIFile> dbFile;
rv = aDBDir->Clone(getter_AddRefs(dbFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = dbFile->Append(kCachesSQLiteFilename);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return OpenDBConnection(aQuotaInfo, dbFile, aConnOut);
}
SyncDBAction::SyncDBAction(Mode aMode) : DBAction(aMode) {}
SyncDBAction::~SyncDBAction() = default;
@ -167,44 +182,25 @@ void SyncDBAction::RunWithDBOnTarget(Resolver* aResolver,
}
// static
nsresult OpenDBConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
nsresult OpenDBConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBFile,
mozIStorageConnection** aConnOut) {
MOZ_ASSERT(!NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(aQuotaInfo.mDirectoryLockId >= -1);
MOZ_DIAGNOSTIC_ASSERT(aDBDir);
MOZ_DIAGNOSTIC_ASSERT(aDBFile);
MOZ_DIAGNOSTIC_ASSERT(aConnOut);
nsCOMPtr<mozIStorageConnection> conn;
nsCOMPtr<nsIFile> dbFile;
nsresult rv = aDBDir->Clone(getter_AddRefs(dbFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = dbFile->Append(NS_LITERAL_STRING("caches.sqlite"));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
bool exists = false;
rv = dbFile->Exists(&exists);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// Use our default file:// protocol handler directly to construct the database
// URL. This avoids any problems if a plugin registers a custom file://
// handler. If such a custom handler used javascript, then we would have a
// bad time running off the main thread here.
RefPtr<nsFileProtocolHandler> handler = new nsFileProtocolHandler();
rv = handler->Init();
nsresult rv = handler->Init();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsIURIMutator> mutator;
rv = handler->NewFileURIMutator(dbFile, getter_AddRefs(mutator));
rv = handler->NewFileURIMutator(aDBFile, getter_AddRefs(mutator));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -231,6 +227,7 @@ nsresult OpenDBConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
return NS_ERROR_UNEXPECTED;
}
nsCOMPtr<mozIStorageConnection> conn;
rv = ss->OpenDatabaseWithFileURL(dbFileUrl, getter_AddRefs(conn));
if (rv == NS_ERROR_FILE_CORRUPTED) {
NS_WARNING("Cache database corrupted. Recreating empty database.");
@ -239,7 +236,7 @@ nsresult OpenDBConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
// There is nothing else we can do to recover. Also, this data can
// be deleted by QuotaManager at any time anyways.
rv = WipeDatabase(aQuotaInfo, dbFile, aDBDir);
rv = WipeDatabase(aQuotaInfo, aDBFile);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -258,7 +255,7 @@ nsresult OpenDBConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
}
if (schemaVersion > 0 && schemaVersion < db::kFirstShippedSchemaVersion) {
conn = nullptr;
rv = WipeDatabase(aQuotaInfo, dbFile, aDBDir);
rv = WipeDatabase(aQuotaInfo, aDBFile);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}

View File

@ -18,7 +18,7 @@ namespace mozilla {
namespace dom {
namespace cache {
nsresult OpenDBConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
nsresult OpenDBConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBFile,
mozIStorageConnection** aConnOut);
class DBAction : public Action {

View File

@ -27,6 +27,7 @@ using mozilla::Some;
using mozilla::Unused;
using mozilla::dom::ContentParentId;
using mozilla::dom::cache::DirPaddingFile;
using mozilla::dom::cache::kCachesSQLiteFilename;
using mozilla::dom::cache::Manager;
using mozilla::dom::cache::QuotaInfo;
using mozilla::dom::quota::AssertIsOnIOThread;
@ -124,15 +125,35 @@ static nsresult LockedGetPaddingSizeFromDB(nsIFile* aDir,
// for the SQLite file).
MOZ_DIAGNOSTIC_ASSERT(quotaInfo.mDirectoryLockId == -1);
nsCOMPtr<mozIStorageConnection> conn;
nsresult rv = mozilla::dom::cache::OpenDBConnection(quotaInfo, aDir,
getter_AddRefs(conn));
if (rv == NS_ERROR_FILE_NOT_FOUND ||
rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) {
// Return NS_OK with size = 0 if both the db and padding file don't exist.
nsCOMPtr<nsIFile> dbFile;
nsresult rv = aDir->Clone(getter_AddRefs(dbFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = dbFile->Append(kCachesSQLiteFilename);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
bool exists = false;
rv = dbFile->Exists(&exists);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// Return NS_OK with size = 0 if caches.sqlite doesn't exist.
// This function is only called if the value of the padding size couldn't be
// determined from the padding file, possibly because it doesn't exist, or a
// leftover temporary padding file was found.
// There is no other way to get the overall padding size of an origin.
if (!exists) {
return NS_OK;
}
nsCOMPtr<mozIStorageConnection> conn;
rv = mozilla::dom::cache::OpenDBConnection(quotaInfo, dbFile,
getter_AddRefs(conn));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -165,6 +186,8 @@ namespace mozilla {
namespace dom {
namespace cache {
NS_NAMED_LITERAL_STRING(kCachesSQLiteFilename, "caches.sqlite");
CacheQuotaClient::CacheQuotaClient()
: mDirPaddingFileMutex("DOMCacheQuotaClient.mDirPaddingFileMutex") {
AssertIsOnBackgroundThread();
@ -460,7 +483,7 @@ nsresult CacheQuotaClient::GetUsageForOriginInternal(
continue;
}
if (leafName.EqualsLiteral("caches.sqlite") ||
if (leafName.Equals(kCachesSQLiteFilename) ||
leafName.EqualsLiteral("caches.sqlite-wal")) {
int64_t fileSize;
rv = file->GetFileSize(&fileSize);

View File

@ -41,6 +41,8 @@ nsresult RestorePaddingFile(nsIFile* aBaseDir, mozIStorageConnection* aConn);
nsresult WipePaddingFile(const QuotaInfo& aQuotaInfo, nsIFile* aBaseDir);
extern const nsLiteralString kCachesSQLiteFilename;
} // namespace cache
} // namespace dom
} // namespace mozilla