Bug 432391 part 1. Fix CancelAndForgetObserver to work correctly even if Cancel has been called. r=joe, a=dveditz
--- a/modules/libpr0n/src/imgRequest.cpp
+++ b/modules/libpr0n/src/imgRequest.cpp
@@ -175,17 +175,20 @@ nsresult imgRequest::AddProxy(imgRequest
return mObservers.AppendElementUnlessExists(proxy) ?
NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
nsresult imgRequest::RemoveProxy(imgRequestProxy *proxy, nsresult aStatus, PRBool aNotify)
{
LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::RemoveProxy", "proxy", proxy);
- mObservers.RemoveElement(proxy);
+ if (!mObservers.RemoveElement(proxy)) {
+ // Not one of our proxies; we're done
+ return NS_OK;
+ }
/* Check mState below before we potentially call Cancel() below. Since
Cancel() may result in OnStopRequest being called back before Cancel()
returns, leaving mState in a different state then the one it was in at
this point.
*/
if (aNotify) {
--- a/modules/libpr0n/src/imgRequestProxy.cpp
+++ b/modules/libpr0n/src/imgRequestProxy.cpp
@@ -221,27 +221,36 @@ imgRequestProxy::DoCancel(nsresult statu
mOwner->RemoveProxy(this, status, PR_FALSE);
NullOutListener();
}
/* void cancelAndForgetObserver (in nsresult aStatus); */
NS_IMETHODIMP imgRequestProxy::CancelAndForgetObserver(nsresult aStatus)
{
- if (mCanceled || !mOwner)
+ if (!mOwner)
+ return NS_ERROR_FAILURE;
+
+ // If mCanceled is true but mListener is non-null, that means
+ // someone called Cancel() on us but the imgCancelRunnable is still
+ // pending. We still need to null out mListener before returning
+ // from this function in this case. That means we want to do the
+ // RemoveProxy call right now, because we need to deliver the
+ // onStopRequest.
+ if (mCanceled && !mListener)
return NS_ERROR_FAILURE;
LOG_SCOPE(gImgLog, "imgRequestProxy::CancelAndForgetObserver");
mCanceled = PR_TRUE;
// Now cheat and make sure our removal from loadgroup happens async
PRBool oldIsInLoadGroup = mIsInLoadGroup;
mIsInLoadGroup = PR_FALSE;
-
+
// Passing false to aNotify means that mListener will still get
// OnStopRequest, if needed.
mOwner->RemoveProxy(this, aStatus, PR_FALSE);
mIsInLoadGroup = oldIsInLoadGroup;
if (mIsInLoadGroup) {
nsCOMPtr<nsIRunnable> ev =