Bug 696362: OpenDatabaseHelper can release objects on the wrong thread. r=bent

This commit is contained in:
Kyle Huey 2011-10-22 07:56:19 -04:00
parent 813577c16e
commit 38e8ee61fe
4 changed files with 51 additions and 7 deletions

View File

@ -120,6 +120,24 @@ ConvertCloneBuffersToArrayInternal(
} // anonymous namespace
HelperBase::~HelperBase()
{
if (!NS_IsMainThread()) {
IDBRequest* request;
mRequest.forget(&request);
if (request) {
nsCOMPtr<nsIThread> mainThread;
NS_GetMainThread(getter_AddRefs(mainThread));
NS_WARN_IF_FALSE(mainThread, "Couldn't get the main thread!");
if (mainThread) {
NS_ProxyRelease(mainThread, static_cast<nsIDOMEventTarget*>(request));
}
}
}
}
nsresult
HelperBase::WrapNative(JSContext* aCx,
nsISupports* aNative,
@ -141,6 +159,14 @@ HelperBase::WrapNative(JSContext* aCx,
return NS_OK;
}
void
HelperBase::ReleaseMainThreadObjects()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
mRequest = nsnull;
}
AsyncConnectionHelper::AsyncConnectionHelper(IDBDatabase* aDatabase,
IDBRequest* aRequest)
: HelperBase(aRequest),
@ -173,9 +199,6 @@ AsyncConnectionHelper::~AsyncConnectionHelper()
IDBTransaction* transaction;
mTransaction.forget(&transaction);
IDBRequest* request;
mRequest.forget(&request);
nsCOMPtr<nsIThread> mainThread;
NS_GetMainThread(getter_AddRefs(mainThread));
NS_WARN_IF_FALSE(mainThread, "Couldn't get the main thread!");
@ -188,9 +211,6 @@ AsyncConnectionHelper::~AsyncConnectionHelper()
NS_ProxyRelease(mainThread,
static_cast<nsIIDBTransaction*>(transaction));
}
if (request) {
NS_ProxyRelease(mainThread, static_cast<nsIDOMEventTarget*>(request));
}
}
}
@ -491,7 +511,8 @@ AsyncConnectionHelper::ReleaseMainThreadObjects()
mDatabase = nsnull;
mTransaction = nsnull;
mRequest = nsnull;
HelperBase::ReleaseMainThreadObjects();
}
// static

View File

@ -75,6 +75,8 @@ protected:
: mRequest(aRequest)
{ }
virtual ~HelperBase();
/**
* Helper to wrap a native into a jsval. Uses the global object of the request
* to parent the native.
@ -83,6 +85,13 @@ protected:
nsISupports* aNative,
jsval* aResult);
/**
* Gives the subclass a chance to release any objects that must be released
* on the main thread, regardless of success or failure. Subclasses that
* implement this method *MUST* call the base class implementation as well.
*/
virtual void ReleaseMainThreadObjects();
nsRefPtr<IDBRequest> mRequest;
};

View File

@ -732,6 +732,8 @@ OpenDatabaseHelper::Run()
DispatchSuccessEvent();
}
ReleaseMainThreadObjects();
return NS_OK;
}
@ -901,6 +903,17 @@ OpenDatabaseHelper::DispatchErrorEvent()
mOpenDBRequest->DispatchEvent(event, &dummy);
}
void
OpenDatabaseHelper::ReleaseMainThreadObjects()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
mOpenDBRequest = nsnull;
mDatabase = nsnull;
HelperBase::ReleaseMainThreadObjects();
}
NS_IMPL_ISUPPORTS_INHERITED0(SetVersionHelper, AsyncConnectionHelper);
nsresult

View File

@ -91,6 +91,7 @@ protected:
jsval* aVal);
void DispatchSuccessEvent();
void DispatchErrorEvent();
void ReleaseMainThreadObjects();
// Methods only called on the DB thread
nsresult DoDatabaseWork();