Bug 702344 - Async requests for nsPermissionManager::RemoveAll();r=mak

This commit is contained in:
David Rajchenbach-Teller 2012-04-30 18:21:50 +02:00
Родитель 4090b50573
Коммит 642ec0956f
2 изменённых файлов: 152 добавлений и 23 удалений

Просмотреть файл

@ -18,11 +18,7 @@
#include "nsIIDNService.h"
#include "nsAppDirectoryServiceDefs.h"
#include "prprf.h"
#include "mozIStorageService.h"
#include "mozIStorageStatement.h"
#include "mozIStorageConnection.h"
#include "mozStorageHelper.h"
#include "mozStorageCID.h"
#include "mozilla/storage.h"
#include "nsXULAppAPI.h"
static nsPermissionManager *gPermissionManager = nsnull;
@ -105,6 +101,115 @@ nsHostEntry::nsHostEntry(const nsHostEntry& toCopy)
{
}
////////////////////////////////////////////////////////////////////////////////
/**
* Simple callback used by |AsyncClose| to trigger a treatment once
* the database is closed.
*
* Note: Beware that, if you hold onto a |CloseDatabaseListener| from a
* |nsPermissionManager|, this will create a cycle.
*
* Note: Once the callback has been called this DeleteFromMozHostListener cannot
* be reused.
*/
class CloseDatabaseListener : public mozIStorageCompletionCallback
{
public:
NS_DECL_ISUPPORTS
NS_DECL_MOZISTORAGECOMPLETIONCALLBACK
/**
* @param aManager The owning manager.
* @param aRebuildOnSuccess If |true|, reinitialize the database once
* it has been closed. Otherwise, do nothing such.
*/
CloseDatabaseListener(nsPermissionManager* aManager,
bool aRebuildOnSuccess);
protected:
nsRefPtr<nsPermissionManager> mManager;
bool mRebuildOnSuccess;
};
NS_IMPL_ISUPPORTS1(CloseDatabaseListener, mozIStorageCompletionCallback)
CloseDatabaseListener::CloseDatabaseListener(nsPermissionManager* aManager,
bool aRebuildOnSuccess)
: mManager(aManager)
, mRebuildOnSuccess(aRebuildOnSuccess)
{
}
NS_IMETHODIMP
CloseDatabaseListener::Complete()
{
// Help breaking cycles
nsRefPtr<nsPermissionManager> manager = mManager.forget();
if (mRebuildOnSuccess && !manager->mIsShuttingDown) {
return manager->InitDB(true);
}
return NS_OK;
}
/**
* Simple callback used by |RemoveAllInternal| to trigger closing
* the database and reinitializing it.
*
* Note: Beware that, if you hold onto a |DeleteFromMozHostListener| from a
* |nsPermissionManager|, this will create a cycle.
*
* Note: Once the callback has been called this DeleteFromMozHostListener cannot
* be reused.
*/
class DeleteFromMozHostListener : public mozIStorageStatementCallback
{
public:
NS_DECL_ISUPPORTS
NS_DECL_MOZISTORAGESTATEMENTCALLBACK
/**
* @param aManager The owning manager.
*/
DeleteFromMozHostListener(nsPermissionManager* aManager);
protected:
nsRefPtr<nsPermissionManager> mManager;
};
NS_IMPL_ISUPPORTS1(DeleteFromMozHostListener, mozIStorageStatementCallback)
DeleteFromMozHostListener::
DeleteFromMozHostListener(nsPermissionManager* aManager)
: mManager(aManager)
{
}
NS_IMETHODIMP DeleteFromMozHostListener::HandleResult(mozIStorageResultSet *)
{
MOZ_NOT_REACHED("Should not get any results");
return NS_OK;
}
NS_IMETHODIMP DeleteFromMozHostListener::HandleError(mozIStorageError *)
{
// Errors are handled in |HandleCompletion|
return NS_OK;
}
NS_IMETHODIMP DeleteFromMozHostListener::HandleCompletion(PRUint16 aReason)
{
// Help breaking cycles
nsRefPtr<nsPermissionManager> manager = mManager.forget();
if (aReason == REASON_ERROR) {
manager->CloseDB(true);
}
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsPermissionManager Implementation
@ -119,6 +224,7 @@ NS_IMPL_ISUPPORTS3(nsPermissionManager, nsIPermissionManager, nsIObserver, nsISu
nsPermissionManager::nsPermissionManager()
: mLargestID(0)
, mIsShuttingDown(false)
{
}
@ -578,39 +684,53 @@ NS_IMETHODIMP
nsPermissionManager::RemoveAll()
{
ENSURE_NOT_CHILD_PROCESS;
nsresult rv = RemoveAllInternal();
NotifyObservers(nsnull, NS_LITERAL_STRING("cleared").get());
return rv;
return RemoveAllInternal(true);
}
void
nsPermissionManager::CloseDB()
nsPermissionManager::CloseDB(bool aRebuildOnSuccess)
{
// Null the statements, this will finalize them.
mStmtInsert = nsnull;
mStmtDelete = nsnull;
mStmtUpdate = nsnull;
if (mDBConn) {
mozilla::DebugOnly<nsresult> rv = mDBConn->Close();
mozIStorageCompletionCallback* cb = new CloseDatabaseListener(this,
aRebuildOnSuccess);
mozilla::DebugOnly<nsresult> rv = mDBConn->AsyncClose(cb);
MOZ_ASSERT(NS_SUCCEEDED(rv));
mDBConn = nsnull;
mDBConn = nsnull; // Avoid race conditions
}
}
nsresult
nsPermissionManager::RemoveAllInternal()
nsPermissionManager::RemoveAllInternal(bool aNotifyObservers)
{
// Remove from memory and notify immediately. Since the in-memory
// database is authoritative, we do not need confirmation from the
// on-disk database to notify observers.
RemoveAllFromMemory();
if (aNotifyObservers) {
NotifyObservers(nsnull, NS_LITERAL_STRING("cleared").get());
}
// clear the db
if (mDBConn) {
nsresult rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DELETE FROM moz_hosts"));
if (NS_FAILED(rv)) {
CloseDB();
rv = InitDB(true);
return rv;
nsCOMPtr<mozIStorageAsyncStatement> removeStmt;
nsresult rv = mDBConn->
CreateAsyncStatement(NS_LITERAL_CSTRING(
"DELETE FROM moz_hosts"
), getter_AddRefs(removeStmt));
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (!removeStmt) {
return NS_ERROR_UNEXPECTED;
}
nsCOMPtr<mozIStoragePendingStatement> pending;
mozIStorageStatementCallback* cb = new DeleteFromMozHostListener(this);
rv = removeStmt->ExecuteAsync(cb, getter_AddRefs(pending));
MOZ_ASSERT(NS_SUCCEEDED(rv));
return rv;
}
return NS_OK;
@ -761,13 +881,14 @@ NS_IMETHODIMP nsPermissionManager::Observe(nsISupports *aSubject, const char *aT
if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
// The profile is about to change,
// or is going away because the application is shutting down.
mIsShuttingDown = true;
if (!nsCRT::strcmp(someData, NS_LITERAL_STRING("shutdown-cleanse").get())) {
// clear the permissions file
RemoveAllInternal();
// Clear the permissions file and close the db asynchronously
RemoveAllInternal(false);
} else {
RemoveAllFromMemory();
CloseDB(false);
}
CloseDB();
}
else if (!nsCRT::strcmp(aTopic, "profile-do-change")) {
// the profile has already changed; init the db from the new location

Просмотреть файл

@ -190,9 +190,10 @@ private:
void NotifyObservers(nsIPermission *aPermission, const PRUnichar *aData);
// Finalize all statements, close the DB and null it.
void CloseDB();
// if aRebuildOnSuccess, reinitialize database
void CloseDB(bool aRebuildOnSuccess = false);
nsresult RemoveAllInternal();
nsresult RemoveAllInternal(bool aNotifyObservers);
nsresult RemoveAllFromMemory();
nsresult NormalizeToACE(nsCString &aHost);
nsresult GetHost(nsIURI *aURI, nsACString &aResult);
@ -219,6 +220,13 @@ private:
// An array to store the strings identifying the different types.
nsTArray<nsCString> mTypeArray;
// Initially, |false|. Set to |true| once shutdown has started, to avoid
// reopening the database.
bool mIsShuttingDown;
friend class DeleteFromMozHostListener;
friend class CloseDatabaseListener;
};
// {4F6B5E00-0C36-11d5-A535-0010A401EB10}