mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-18 07:45:30 +00:00
Bug 1248550 - Part 4: Check FactoryOp objects before running a database maintenance and check for DatabaseMaintenance before dispatching a FactoryOp; r=khuey
This commit is contained in:
parent
1b90de1845
commit
216919952d
@ -7182,6 +7182,7 @@ protected:
|
||||
nsCString mGroup;
|
||||
nsCString mOrigin;
|
||||
nsCString mDatabaseId;
|
||||
nsString mDatabaseFilePath;
|
||||
State mState;
|
||||
bool mIsApp;
|
||||
bool mEnforcingQuota;
|
||||
@ -7205,6 +7206,12 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
const nsString&
|
||||
DatabaseFilePath() const
|
||||
{
|
||||
return mDatabaseFilePath;
|
||||
}
|
||||
|
||||
protected:
|
||||
FactoryOp(Factory* aFactory,
|
||||
already_AddRefed<ContentParent> aContentParent,
|
||||
@ -7295,13 +7302,13 @@ private:
|
||||
CheckAtLeastOneAppHasPermission(ContentParent* aContentParent,
|
||||
const nsACString& aPermissionString);
|
||||
|
||||
void
|
||||
nsresult
|
||||
FinishOpen();
|
||||
|
||||
nsresult
|
||||
QuotaManagerOpen();
|
||||
|
||||
void
|
||||
nsresult
|
||||
OpenDirectory();
|
||||
|
||||
// Test whether this FactoryOp needs to wait for the given op.
|
||||
@ -7360,7 +7367,6 @@ class OpenDatabaseOp final
|
||||
RefPtr<FullDatabaseMetadata> mMetadata;
|
||||
|
||||
uint64_t mRequestedVersion;
|
||||
nsString mDatabaseFilePath;
|
||||
RefPtr<FileManager> mFileManager;
|
||||
|
||||
RefPtr<Database> mDatabase;
|
||||
@ -8838,6 +8844,13 @@ public:
|
||||
return mShutdownRequested;
|
||||
}
|
||||
|
||||
already_AddRefed<Maintenance>
|
||||
GetCurrentMaintenance() const
|
||||
{
|
||||
RefPtr<Maintenance> result = mCurrentMaintenance;
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
void
|
||||
NoteFinishedMaintenance(Maintenance* aMaintenance)
|
||||
{
|
||||
@ -9130,6 +9143,16 @@ public:
|
||||
void
|
||||
UnregisterDatabaseMaintenance(DatabaseMaintenance* aDatabaseMaintenance);
|
||||
|
||||
already_AddRefed<DatabaseMaintenance>
|
||||
GetDatabaseMaintenance(const nsAString& aDatabasePath) const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
RefPtr<DatabaseMaintenance> result =
|
||||
mDatabaseMaintenances.Get(aDatabasePath);
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
private:
|
||||
~Maintenance()
|
||||
{
|
||||
@ -9245,6 +9268,7 @@ class DatabaseMaintenance final
|
||||
const nsCString mGroup;
|
||||
const nsCString mOrigin;
|
||||
const nsString mDatabasePath;
|
||||
nsCOMPtr<nsIRunnable> mCompleteCallback;
|
||||
const PersistenceType mPersistenceType;
|
||||
|
||||
public:
|
||||
@ -9283,6 +9307,15 @@ public:
|
||||
return mDatabasePath;
|
||||
}
|
||||
|
||||
void
|
||||
WaitForComplete(nsIRunnable* aCallback)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(!mCompleteCallback);
|
||||
|
||||
mCompleteCallback = aCallback;
|
||||
}
|
||||
|
||||
private:
|
||||
~DatabaseMaintenance()
|
||||
{ }
|
||||
@ -18044,6 +18077,18 @@ Maintenance::BeginDatabaseMaintenance()
|
||||
static bool
|
||||
IsSafeToRunMaintenance(const nsAString& aDatabasePath)
|
||||
{
|
||||
if (gFactoryOps) {
|
||||
for (uint32_t index = gFactoryOps->Length(); index > 0; index--) {
|
||||
RefPtr<FactoryOp>& existingOp = (*gFactoryOps)[index - 1];
|
||||
|
||||
MOZ_ASSERT(!existingOp->DatabaseFilePath().IsEmpty());
|
||||
|
||||
if (existingOp->DatabaseFilePath() == aDatabasePath) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gLiveDatabaseHashtable) {
|
||||
for (auto iter = gLiveDatabaseHashtable->ConstIter();
|
||||
!iter.Done(); iter.Next()) {
|
||||
@ -18197,6 +18242,12 @@ DatabaseMaintenance::RunOnOwningThread()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
if (mCompleteCallback) {
|
||||
MOZ_ALWAYS_TRUE(
|
||||
NS_SUCCEEDED(NS_DispatchToCurrentThread(mCompleteCallback)));
|
||||
mCompleteCallback = nullptr;
|
||||
}
|
||||
|
||||
mMaintenance->UnregisterDatabaseMaintenance(this);
|
||||
}
|
||||
|
||||
@ -19558,6 +19609,7 @@ FactoryOp::DirectoryOpen()
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mState == State::DirectoryOpenPending);
|
||||
MOZ_ASSERT(mDirectoryLock);
|
||||
MOZ_ASSERT(!mDatabaseFilePath.IsEmpty());
|
||||
|
||||
// gFactoryOps could be null here if the child process crashed or something
|
||||
// and that cleaned up the last Factory actor.
|
||||
@ -19582,6 +19634,20 @@ FactoryOp::DirectoryOpen()
|
||||
// proceeding until this one is done.
|
||||
gFactoryOps->AppendElement(this);
|
||||
|
||||
if (!delayed) {
|
||||
QuotaClient* quotaClient = QuotaClient::GetInstance();
|
||||
MOZ_ASSERT(quotaClient);
|
||||
|
||||
if (RefPtr<Maintenance> currentMaintenance =
|
||||
quotaClient->GetCurrentMaintenance()) {
|
||||
if (RefPtr<DatabaseMaintenance> databaseMaintenance =
|
||||
currentMaintenance->GetDatabaseMaintenance(mDatabaseFilePath)) {
|
||||
databaseMaintenance->WaitForComplete(this);
|
||||
delayed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mBlockedDatabaseOpen = true;
|
||||
|
||||
mState = State::DatabaseOpenPending;
|
||||
@ -19940,7 +20006,7 @@ FactoryOp::CheckAtLeastOneAppHasPermission(ContentParent* aContentParent,
|
||||
#endif // MOZ_CHILD_PERMISSIONS
|
||||
}
|
||||
|
||||
void
|
||||
nsresult
|
||||
FactoryOp::FinishOpen()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
@ -19948,13 +20014,18 @@ FactoryOp::FinishOpen()
|
||||
MOZ_ASSERT(!mContentParent);
|
||||
|
||||
if (QuotaManager::Get()) {
|
||||
OpenDirectory();
|
||||
nsresult rv = OpenDirectory();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mState = State::QuotaManagerPending;
|
||||
QuotaManager::GetOrCreate(this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -19967,12 +20038,15 @@ FactoryOp::QuotaManagerOpen()
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
OpenDirectory();
|
||||
nsresult rv = OpenDirectory();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsresult
|
||||
FactoryOp::OpenDirectory()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
@ -19983,15 +20057,50 @@ FactoryOp::OpenDirectory()
|
||||
MOZ_ASSERT(!QuotaClient::IsShuttingDownOnBackgroundThread());
|
||||
MOZ_ASSERT(QuotaManager::Get());
|
||||
|
||||
// Need to get database file path in advance.
|
||||
const nsString& databaseName = mCommonParams.metadata().name();
|
||||
PersistenceType persistenceType = mCommonParams.metadata().persistenceType();
|
||||
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
MOZ_ASSERT(quotaManager);
|
||||
|
||||
nsCOMPtr<nsIFile> dbFile;
|
||||
nsresult rv = quotaManager->GetDirectoryForOrigin(persistenceType,
|
||||
mOrigin,
|
||||
getter_AddRefs(dbFile));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = dbFile->Append(NS_LITERAL_STRING(IDB_DIRECTORY_NAME));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsAutoString filename;
|
||||
GetDatabaseFilename(databaseName, filename);
|
||||
|
||||
rv = dbFile->Append(filename + NS_LITERAL_STRING(".sqlite"));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = dbFile->GetPath(mDatabaseFilePath);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mState = State::DirectoryOpenPending;
|
||||
|
||||
QuotaManager::Get()->OpenDirectory(mCommonParams.metadata().persistenceType(),
|
||||
mGroup,
|
||||
mOrigin,
|
||||
mIsApp,
|
||||
Client::IDB,
|
||||
/* aExclusive */ false,
|
||||
this);
|
||||
quotaManager->OpenDirectory(persistenceType,
|
||||
mGroup,
|
||||
mOrigin,
|
||||
mIsApp,
|
||||
Client::IDB,
|
||||
/* aExclusive */ false,
|
||||
this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -20059,8 +20168,8 @@ FactoryOp::Run()
|
||||
break;
|
||||
|
||||
case State::FinishOpen:
|
||||
FinishOpen();
|
||||
return NS_OK;
|
||||
rv = FinishOpen();
|
||||
break;
|
||||
|
||||
case State::QuotaManagerPending:
|
||||
rv = QuotaManagerOpen();
|
||||
@ -20290,11 +20399,16 @@ OpenDatabaseOp::DoDatabaseWork()
|
||||
|
||||
mTelemetryId = TelemetryIdForFile(dbFile);
|
||||
|
||||
rv = dbFile->GetPath(mDatabaseFilePath);
|
||||
#ifdef DEBUG
|
||||
nsString databaseFilePath;
|
||||
rv = dbFile->GetPath(databaseFilePath);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(databaseFilePath == mDatabaseFilePath);
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIFile> fmDirectory;
|
||||
rv = dbDirectory->Clone(getter_AddRefs(fmDirectory));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
@ -21620,6 +21734,16 @@ DeleteDatabaseOp::DoDatabaseWork()
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
nsString databaseFilePath;
|
||||
rv = dbFile->GetPath(databaseFilePath);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(databaseFilePath == mDatabaseFilePath);
|
||||
#endif
|
||||
|
||||
bool exists;
|
||||
rv = dbFile->Exists(&exists);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
|
Loading…
Reference in New Issue
Block a user