Bug 784591. Part 2. Don't track images that don't have a frame created. r=jlebar
authorTimothy Nikkel <tnikkel@gmail.com>
Thu, 17 Jan 2013 17:58:37 -0600
changeset 119215 4d95a6900a4fd9ecbab34b78edc977007de86ca2
parent 119214 304ee1c25362bab00c152d0d433877378bedefff
child 119216 072531a694bfc261810d45b213435e5a3d9633b8
push id24195
push userMs2ger@gmail.com
push dateSat, 19 Jan 2013 16:10:11 +0000
treeherdermozilla-central@02e12a80aef9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjlebar
bugs784591
milestone21.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 784591. Part 2. Don't track images that don't have a frame created. r=jlebar
content/base/src/nsImageLoadingContent.cpp
content/base/src/nsImageLoadingContent.h
--- a/content/base/src/nsImageLoadingContent.cpp
+++ b/content/base/src/nsImageLoadingContent.cpp
@@ -377,16 +377,31 @@ NS_IMETHODIMP_(void)
 nsImageLoadingContent::FrameCreated(nsIFrame* aFrame)
 {
   NS_ASSERTION(aFrame, "aFrame is null");
 
   // We need to make sure that our image request is registered, if it should
   // be registered.
   nsPresContext* presContext = aFrame->PresContext();
 
+  if (mCurrentRequest && !(mCurrentRequestFlags & REQUEST_IS_TRACKED)) {
+    nsIDocument* doc = GetOurCurrentDoc();
+    if (doc) {
+      mCurrentRequestFlags |= REQUEST_IS_TRACKED;
+      doc->AddImage(mCurrentRequest);
+    }
+  }
+  if (mPendingRequest && !(mPendingRequestFlags & REQUEST_IS_TRACKED)) {
+    nsIDocument* doc = GetOurCurrentDoc();
+    if (doc) {
+      mPendingRequestFlags |= REQUEST_IS_TRACKED;
+      doc->AddImage(mPendingRequest);
+    }
+  }
+
   if (mCurrentRequest) {
     nsLayoutUtils::RegisterImageRequestIfAnimated(presContext, mCurrentRequest,
                                                   &mCurrentRequestRegistered);
   }
 
   if (mPendingRequest) {
     nsLayoutUtils::RegisterImageRequestIfAnimated(presContext, mPendingRequest,
                                                   &mPendingRequestRegistered);
@@ -405,16 +420,31 @@ nsImageLoadingContent::FrameDestroyed(ns
                                           &mCurrentRequestRegistered);
   }
 
   if (mPendingRequest) {
     nsLayoutUtils::DeregisterImageRequest(GetFramePresContext(),
                                           mPendingRequest,
                                           &mPendingRequestRegistered);
   }
+
+  if (mCurrentRequest && (mCurrentRequestFlags & REQUEST_IS_TRACKED)) {
+    nsIDocument* doc = GetOurCurrentDoc();
+    if (doc) {
+      mCurrentRequestFlags &= ~REQUEST_IS_TRACKED;
+      doc->RemoveImage(mCurrentRequest);
+    }
+  }
+  if (mPendingRequest && (mPendingRequestFlags & REQUEST_IS_TRACKED)) {
+    nsIDocument* doc = GetOurCurrentDoc();
+    if (doc) {
+      mPendingRequestFlags &= ~REQUEST_IS_TRACKED;
+      doc->RemoveImage(mPendingRequest);
+    }
+  }
 }
 
 int32_t
 nsImageLoadingContent::GetRequestType(imgIRequest* aRequest,
                                       ErrorResult& aError)
 {
   if (aRequest == mCurrentRequest) {
     return CURRENT_REQUEST;
@@ -1151,20 +1181,26 @@ nsImageLoadingContent::BindToTree(nsIDoc
   if (!aDocument)
     return;
 
   // Push a null JSContext on the stack so that callbacks triggered by the
   // below code won't think they're being called from JS.
   nsCxPusher pusher;
   pusher.PushNull();
 
-  if (mCurrentRequest)
-    aDocument->AddImage(mCurrentRequest);
-  if (mPendingRequest)
-    aDocument->AddImage(mPendingRequest);
+  if (GetOurPrimaryFrame()) {
+    if (mCurrentRequest && !(mCurrentRequestFlags & REQUEST_IS_TRACKED)) {
+      mCurrentRequestFlags |= REQUEST_IS_TRACKED;
+      aDocument->AddImage(mCurrentRequest);
+    }
+    if (mPendingRequest && !(mPendingRequestFlags & REQUEST_IS_TRACKED)) {
+      mPendingRequestFlags |= REQUEST_IS_TRACKED;
+      aDocument->AddImage(mPendingRequest);
+    }
+  }
 
   if (mCurrentRequestFlags & REQUEST_BLOCKS_ONLOAD)
     aDocument->BlockOnload();
 }
 
 void
 nsImageLoadingContent::UnbindFromTree(bool aDeep, bool aNullParent)
 {
@@ -1173,55 +1209,75 @@ nsImageLoadingContent::UnbindFromTree(bo
   if (!doc)
     return;
 
   // Push a null JSContext on the stack so that callbacks triggered by the
   // below code won't think they're being called from JS.
   nsCxPusher pusher;
   pusher.PushNull();
 
-  if (mCurrentRequest)
+  if (mCurrentRequest && (mCurrentRequestFlags & REQUEST_IS_TRACKED)) {
+    mCurrentRequestFlags &= ~REQUEST_IS_TRACKED;
     doc->RemoveImage(mCurrentRequest);
-  if (mPendingRequest)
+  }
+  if (mPendingRequest && (mPendingRequestFlags & REQUEST_IS_TRACKED)) {
+    mPendingRequestFlags &= ~REQUEST_IS_TRACKED;
     doc->RemoveImage(mPendingRequest);
+  }
 
   if (mCurrentRequestFlags & REQUEST_BLOCKS_ONLOAD)
     doc->UnblockOnload(false);
 }
 
 nsresult
 nsImageLoadingContent::TrackImage(imgIRequest* aImage)
 {
   if (!aImage)
     return NS_OK;
 
   MOZ_ASSERT(aImage == mCurrentRequest || aImage == mPendingRequest,
              "Why haven't we heard of this request?");
 
   nsIDocument* doc = GetOurCurrentDoc();
-  if (doc)
-    return doc->AddImage(aImage);
+  if (doc && GetOurPrimaryFrame()) {
+    if (aImage == mCurrentRequest && !(mCurrentRequestFlags & REQUEST_IS_TRACKED)) {
+      mCurrentRequestFlags |= REQUEST_IS_TRACKED;
+      doc->AddImage(mCurrentRequest);
+    }
+    if (aImage == mPendingRequest && !(mPendingRequestFlags & REQUEST_IS_TRACKED)) {
+      mPendingRequestFlags |= REQUEST_IS_TRACKED;
+      doc->AddImage(mPendingRequest);
+    }
+  }
   return NS_OK;
 }
 
 nsresult
 nsImageLoadingContent::UntrackImage(imgIRequest* aImage)
 {
   if (!aImage)
     return NS_OK;
 
   MOZ_ASSERT(aImage == mCurrentRequest || aImage == mPendingRequest,
              "Why haven't we heard of this request?");
 
   // If GetOurDocument() returns null here, we've outlived our document.
   // That's fine, because the document empties out the tracker and unlocks
   // all locked images on destruction.
   nsIDocument* doc = GetOurCurrentDoc();
-  if (doc)
-    return doc->RemoveImage(aImage, nsIDocument::REQUEST_DISCARD);
+  if (doc) {
+    if (aImage == mCurrentRequest && (mCurrentRequestFlags & REQUEST_IS_TRACKED)) {
+      mCurrentRequestFlags &= ~REQUEST_IS_TRACKED;
+      doc->RemoveImage(mCurrentRequest, nsIDocument::REQUEST_DISCARD);
+    }
+    if (aImage == mPendingRequest && (mPendingRequestFlags & REQUEST_IS_TRACKED)) {
+      mPendingRequestFlags &= ~REQUEST_IS_TRACKED;
+      doc->RemoveImage(mPendingRequest, nsIDocument::REQUEST_DISCARD);
+    }
+  }
   return NS_OK;
 }
 
 
 void
 nsImageLoadingContent::CreateStaticImageClone(nsImageLoadingContent* aDest) const
 {
   aDest->mCurrentRequest = nsContentUtils::GetStaticRequest(mCurrentRequest);
--- a/content/base/src/nsImageLoadingContent.h
+++ b/content/base/src/nsImageLoadingContent.h
@@ -337,20 +337,22 @@ protected:
 
   /* MEMBERS */
   nsRefPtr<imgRequestProxy> mCurrentRequest;
   nsRefPtr<imgRequestProxy> mPendingRequest;
   uint32_t mCurrentRequestFlags;
   uint32_t mPendingRequestFlags;
 
   enum {
-    // Set if the request needs 
+    // Set if the request needs ResetAnimation called on it.
     REQUEST_NEEDS_ANIMATION_RESET = 0x00000001U,
     // Set if the request is blocking onload.
-    REQUEST_BLOCKS_ONLOAD = 0x00000002U
+    REQUEST_BLOCKS_ONLOAD = 0x00000002U,
+    // Set if the request is currently tracked with the document.
+    REQUEST_IS_TRACKED = 0x00000004U
   };
 
   // If the image was blocked or if there was an error loading, it's nice to
   // still keep track of what the URI was despite not having an imgIRequest.
   // We only maintain this in those situations (in the common case, this is
   // always null).
   nsCOMPtr<nsIURI>      mCurrentURI;