Bug 432391 part 1. Fix CancelAndForgetObserver to work correctly even if Cancel has been called. r=joe
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 14 Oct 2011 16:15:56 -0400
changeset 80263 81665fc485ddda69e8d198eed5b3648cbcbfdb83
parent 80262 a86a80a91234351550798859aca18a49c1f6acb3
child 80264 0d2caaf1d0a87d6f5db2073f31034c8740abda9d
push id434
push userclegnitto@mozilla.com
push dateWed, 21 Dec 2011 12:10:54 +0000
treeherdermozilla-beta@bddb6ed8dd47 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjoe
bugs432391
milestone10.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 432391 part 1. Fix CancelAndForgetObserver to work correctly even if Cancel has been called. r=joe
image/src/imgRequest.cpp
image/src/imgRequestProxy.cpp
--- a/image/src/imgRequest.cpp
+++ b/image/src/imgRequest.cpp
@@ -304,17 +304,20 @@ nsresult imgRequest::RemoveProxy(imgRequ
 {
   LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::RemoveProxy", "proxy", proxy);
 
   // This will remove our animation consumers, so after removing
   // this proxy, we don't end up without proxies with observers, but still
   // have animation consumers.
   proxy->ClearAnimationConsumers();
 
-  mObservers.RemoveElement(proxy);
+  if (!mObservers.RemoveElement(proxy)) {
+    // Not one of our proxies; we're done
+    return NS_OK;
+  }
 
   // Let the status tracker do its thing before we potentially call Cancel()
   // below, because Cancel() may result in OnStopRequest being called back
   // before Cancel() returns, leaving the image in a different state then the
   // one it was in at this point.
 
   imgStatusTracker& statusTracker = GetStatusTracker();
   statusTracker.EmulateRequestFinished(proxy, aStatus, !aNotify);
--- a/image/src/imgRequestProxy.cpp
+++ b/image/src/imgRequestProxy.cpp
@@ -294,17 +294,23 @@ imgRequestProxy::DoCancel(nsresult statu
     mOwner->RemoveProxy(this, status, false);
 
   NullOutListener();
 }
 
 /* void cancelAndForgetObserver (in nsresult aStatus); */
 NS_IMETHODIMP imgRequestProxy::CancelAndForgetObserver(nsresult aStatus)
 {
-  if (mCanceled)
+  // 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 = true;
 
   // Now cheat and make sure our removal from loadgroup happens async
   bool oldIsInLoadGroup = mIsInLoadGroup;