Bug 215083: Implement content: url(..) for elements. r?tnikkel,dholbert draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Wed, 16 May 2018 19:18:54 +0200
changeset 795839 eaa7c31a919e0a97eca2f877ce480d81190cb81f
parent 795838 12b22aff50251b7faf7d4e38ca8faa426cde07a9
push id110095
push userbmo:emilio@crisal.io
push dateWed, 16 May 2018 17:27:42 +0000
reviewerstnikkel, dholbert
bugs215083, 1149357
milestone62.0a1
Bug 215083: Implement content: url(..) for elements. r?tnikkel,dholbert Take the review request as a feedback request for now. Pretty sure there's a bunch of image tracking stuff that could (should?) be done which is not done. Also need to figure out the right thing to do for animated images and that. That being said, this works. Dynamic changes are handled correctly because content property changes already cause a reframe. The mImage change for intrinsic sizing also fixes bug 1149357, since HTMLImageElement mungles the image natural width otherwise. I can (and will) submit that fix separately. This implements the same bits as Blink / WebKit do (single content item which is an image, otherwise gets ignored). MozReview-Commit-ID: JUurhC60hWr
layout/base/nsCSSFrameConstructor.cpp
layout/generic/nsImageFrame.cpp
layout/generic/nsImageFrame.h
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -5614,16 +5614,27 @@ ShouldSuppressFrameInNonOpenDetails(cons
       !aChild->IsGeneratedContentContainerForBefore() &&
       !aChild->IsGeneratedContentContainerForAfter()) {
     return false;
   }
 
   return true;
 }
 
+static bool
+ShouldCreateImageFrameForContent(ComputedStyle& aStyle)
+{
+  auto& content = *aStyle.StyleContent();
+  if (content.ContentCount() != 1) {
+    return false;
+  }
+
+  return content.ContentAt(0).GetType() == eStyleContentType_Image;
+}
+
 void
 nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState& aState,
                                                          nsIContent* aContent,
                                                          nsContainerFrame* aParentFrame,
                                                          bool aSuppressWhiteSpaceOptimizations,
                                                          ComputedStyle* aComputedStyle,
                                                          uint32_t aFlags,
                                                          nsTArray<nsIAnonymousContentCreator::ContentInfo>* aAnonChildren,
@@ -5787,16 +5798,22 @@ nsCSSFrameConstructor::AddFrameConstruct
                          computedStyle);
     }
 
     // Now check for XUL display types
     if (!data) {
       data = FindXULDisplayData(display, element, computedStyle);
     }
 
+    if (!data && ShouldCreateImageFrameForContent(*computedStyle)) {
+      static const FrameConstructionData sImgData =
+        SIMPLE_FCDATA(NS_NewImageFrame);
+      data = &sImgData;
+    }
+
     // And general display types
     if (!data) {
       data = FindDisplayData(display, element, computedStyle);
     }
 
     MOZ_ASSERT(data, "Should have frame construction data now");
 
     if (data->mBits & FCDATA_SUPPRESS_FRAME) {
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -191,33 +191,35 @@ nsImageFrame::DisconnectMap()
 void
 nsImageFrame::DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData)
 {
   if (mReflowCallbackPosted) {
     PresShell()->CancelReflowCallback(this);
     mReflowCallbackPosted = false;
   }
 
+  if (mContentURLRequest) {
+    mContentURLRequest->CancelAndForgetObserver(NS_BINDING_ABORTED);
+  }
+
   // Tell our image map, if there is one, to clean up
   // This causes the nsImageMap to unregister itself as
   // a DOM listener.
   DisconnectMap();
 
   // set the frame to null so we don't send messages to a dead object.
   if (mListener) {
-    nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
-    if (imageLoader) {
+    if (nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent)) {
       // Notify our image loading content that we are going away so it can
       // deregister with our refresh driver.
       imageLoader->FrameDestroyed(this);
-
       imageLoader->RemoveNativeObserver(mListener);
     }
 
-    reinterpret_cast<nsImageListener*>(mListener.get())->SetFrame(nullptr);
+    mListener->SetFrame(nullptr);
   }
 
   mListener = nullptr;
 
   // If we were displaying an icon, take ourselves off the list
   if (mDisplayingIcon)
     gIconLoad->RemoveIconObserver(this);
 
@@ -247,47 +249,53 @@ nsImageFrame::DidSetComputedStyle(Comput
     nsCOMPtr<imgIContainer> image(mImage->Unwrap());
     mImage = nsLayoutUtils::OrientImage(image, newOrientation);
 
     UpdateIntrinsicSize(mImage);
     UpdateIntrinsicRatio(mImage);
   }
 }
 
+already_AddRefed<imgIRequest>
+nsImageFrame::GetCurrentRequest() const
+{
+  nsCOMPtr<imgIRequest> request;
+  if (nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent)) {
+    imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
+                            getter_AddRefs(request));
+  } else {
+    request = mContentURLRequest;
+  }
+  return request.forget();
+}
+
 void
 nsImageFrame::Init(nsIContent*       aContent,
                    nsContainerFrame* aParent,
                    nsIFrame*         aPrevInFlow)
 {
   nsAtomicContainerFrame::Init(aContent, aParent, aPrevInFlow);
 
+  if (!gIconLoad)
+    LoadIcons(PresContext());
+
   mListener = new nsImageListener(this);
 
-  nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(aContent);
-  if (!imageLoader) {
-    MOZ_CRASH("Why do we have an nsImageFrame here at all?");
+  if (nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(aContent)) {
+    imageLoader->AddNativeObserver(mListener);
+    // We have a PresContext now, so we need to notify the image content node
+    // that it can register images.
+    imageLoader->FrameCreated(this);
+  } else if (auto* proxy = StyleContent()->ContentAt(0).GetImage()) {
+    proxy->SyncClone(mListener,
+                     mContent->OwnerDoc(),
+                     getter_AddRefs(mContentURLRequest));
   }
 
-  imageLoader->AddNativeObserver(mListener);
-
-  nsPresContext *aPresContext = PresContext();
-
-  if (!gIconLoad)
-    LoadIcons(aPresContext);
-
-  // We have a PresContext now, so we need to notify the image content node
-  // that it can register images.
-  imageLoader->FrameCreated(this);
-
-  // Give image loads associated with an image frame a small priority boost!
-  nsCOMPtr<imgIRequest> currentRequest;
-  imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
-                          getter_AddRefs(currentRequest));
-
-  if (currentRequest) {
+  if (nsCOMPtr<imgIRequest> currentRequest = GetCurrentRequest()) {
     uint32_t categoryToBoostPriority = imgIRequest::CATEGORY_FRAME_INIT;
 
     // Increase load priority further if intrinsic size might be important for layout.
     if (!HaveSpecifiedSize(StylePosition())) {
       categoryToBoostPriority |= imgIRequest::CATEGORY_SIZE_QUERY;
     }
 
     currentRequest->BoostPriority(categoryToBoostPriority);
@@ -383,17 +391,20 @@ nsImageFrame::GetSourceToDestTransform(n
 
 // This function checks whether the given request is the current request for our
 // mContent.
 bool
 nsImageFrame::IsPendingLoad(imgIRequest* aRequest) const
 {
   // Default to pending load in case of errors
   nsCOMPtr<nsIImageLoadingContent> imageLoader(do_QueryInterface(mContent));
-  NS_ASSERTION(imageLoader, "No image loading content?");
+  if (!imageLoader) {
+    MOZ_ASSERT(aRequest == mContentURLRequest);
+    return false;
+  }
 
   int32_t requestType = nsIImageLoadingContent::UNKNOWN_REQUEST;
   imageLoader->GetRequestType(aRequest, &requestType);
 
   return requestType != nsIImageLoadingContent::CURRENT_REQUEST;
 }
 
 nsRect
@@ -532,24 +543,25 @@ nsImageFrame::Notify(imgIRequest* aReque
 static bool
 SizeIsAvailable(imgIRequest* aRequest)
 {
   if (!aRequest)
     return false;
 
   uint32_t imageStatus = 0;
   nsresult rv = aRequest->GetImageStatus(&imageStatus);
-
   return NS_SUCCEEDED(rv) && (imageStatus & imgIRequest::STATUS_SIZE_AVAILABLE);
 }
 
 nsresult
 nsImageFrame::OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage)
 {
-  if (!aImage) return NS_ERROR_INVALID_ARG;
+  if (!aImage) {
+    return NS_ERROR_INVALID_ARG;
+  }
 
   /* Get requested animation policy from the pres context:
    *   normal = 0
    *   one frame = 1
    *   one loop = 2
    */
   nsPresContext *presContext = PresContext();
   aImage->SetAnimationMode(presContext->ImageAnimationMode());
@@ -660,33 +672,22 @@ nsImageFrame::InvalidateSelf(const nsInt
                     aLayerInvalidRect,
                     aFrameInvalidRect);
   }
 }
 
 nsresult
 nsImageFrame::OnLoadComplete(imgIRequest* aRequest, nsresult aStatus)
 {
-  // Check what request type we're dealing with
-  nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
-  NS_ASSERTION(imageLoader, "Who's notifying us??");
-  int32_t loadType = nsIImageLoadingContent::UNKNOWN_REQUEST;
-  imageLoader->GetRequestType(aRequest, &loadType);
-  if (loadType != nsIImageLoadingContent::CURRENT_REQUEST &&
-      loadType != nsIImageLoadingContent::PENDING_REQUEST) {
-    return NS_ERROR_FAILURE;
-  }
-
   NotifyNewCurrentRequest(aRequest, aStatus);
   return NS_OK;
 }
 
 void
-nsImageFrame::NotifyNewCurrentRequest(imgIRequest *aRequest,
-                                      nsresult aStatus)
+nsImageFrame::NotifyNewCurrentRequest(imgIRequest* aRequest, nsresult aStatus)
 {
   nsCOMPtr<imgIContainer> image;
   aRequest->GetImage(getter_AddRefs(image));
   NS_ASSERTION(image || NS_FAILED(aStatus), "Successful load with no container?");
 
   // May have to switch sizes here!
   bool intrinsicSizeChanged = true;
   if (NS_SUCCEEDED(aStatus) && image && SizeIsAvailable(aRequest)) {
@@ -806,37 +807,32 @@ nsImageFrame::EnsureIntrinsicSizeAndRati
       mIntrinsicSize.height.GetCoordValue() == 0) {
 
     if (mImage) {
       UpdateIntrinsicSize(mImage);
       UpdateIntrinsicRatio(mImage);
     } else {
       // image request is null or image size not known, probably an
       // invalid image specified
+      //
+      // TODO(emilio): Do we really want to do this for content: url(..)?
       if (!(GetStateBits() & NS_FRAME_GENERATED_CONTENT)) {
         bool imageInvalid = false;
         // check for broken images. valid null images (eg. img src="") are
         // not considered broken because they have no image requests
-        nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
-        if (imageLoader) {
-          nsCOMPtr<imgIRequest> currentRequest;
-          imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
-                                  getter_AddRefs(currentRequest));
-          if (currentRequest) {
-            uint32_t imageStatus;
-            imageInvalid =
-              NS_SUCCEEDED(currentRequest->GetImageStatus(&imageStatus)) &&
-              (imageStatus & imgIRequest::STATUS_ERROR);
-          } else {
-            // check if images are user-disabled (or blocked for other
-            // reasons)
-            int16_t imageBlockingStatus;
-            imageLoader->GetImageBlockingStatus(&imageBlockingStatus);
-            imageInvalid = imageBlockingStatus != nsIContentPolicy::ACCEPT;
-          }
+        if (nsCOMPtr<imgIRequest> currentRequest = GetCurrentRequest()) {
+          uint32_t imageStatus;
+          imageInvalid =
+            NS_SUCCEEDED(currentRequest->GetImageStatus(&imageStatus)) &&
+            (imageStatus & imgIRequest::STATUS_ERROR);
+        } else if (nsCOMPtr<nsIImageLoadingContent> loader = do_QueryInterface(mContent)) {
+          // check if images are user-disabled (or blocked for other reasons)
+          int16_t imageBlockingStatus;
+          loader->GetImageBlockingStatus(&imageBlockingStatus);
+          imageInvalid = imageBlockingStatus != nsIContentPolicy::ACCEPT;
         }
         // invalid image specified. make the image big enough for the "broken" icon
         if (imageInvalid) {
           nscoord edgeLengthToUse =
             nsPresContext::CSSPixelsToAppUnits(
               ICON_SIZE + (2 * (ICON_PADDING + ALT_BORDER_WIDTH)));
           mIntrinsicSize.width.SetCoordValue(edgeLengthToUse);
           mIntrinsicSize.height.SetCoordValue(edgeLengthToUse);
@@ -855,51 +851,46 @@ nsImageFrame::ComputeSize(gfxContext *aR
                           nscoord aAvailableISize,
                           const LogicalSize& aMargin,
                           const LogicalSize& aBorder,
                           const LogicalSize& aPadding,
                           ComputeSizeFlags aFlags)
 {
   EnsureIntrinsicSizeAndRatio();
 
-  nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
-  NS_ASSERTION(imageLoader, "No content node??");
   mozilla::IntrinsicSize intrinsicSize(mIntrinsicSize);
 
+  nsCOMPtr<imgIRequest> currentRequest = GetCurrentRequest();
+
   // XXX(seth): We may sometimes find ourselves in the situation where we have
   // mImage, but imageLoader's current request does not have a size yet.
   // This can happen when we load an image speculatively from cache, it fails
   // to validate, and the new image load hasn't fired SIZE_AVAILABLE yet. In
   // this situation we should always use mIntrinsicSize, because
   // GetNaturalWidth/Height will return 0, so we check CurrentRequestHasSize()
   // below. See bug 1019840. We will fix this in bug 1141395.
 
   // Content may override our default dimensions. This is termed as overriding
   // the intrinsic size by the spec, but all other consumers of mIntrinsic*
   // values are being used to refer to the real/true size of the image data.
-  if (imageLoader && imageLoader->CurrentRequestHasSize() && mImage &&
+  if (currentRequest && SizeIsAvailable(currentRequest) && mImage &&
       intrinsicSize.width.GetUnit() == eStyleUnit_Coord &&
       intrinsicSize.height.GetUnit() == eStyleUnit_Coord) {
-    uint32_t width;
-    uint32_t height;
-    if (NS_SUCCEEDED(imageLoader->GetNaturalWidth(&width)) &&
-        NS_SUCCEEDED(imageLoader->GetNaturalHeight(&height))) {
-      nscoord appWidth = nsPresContext::CSSPixelsToAppUnits((int32_t)width);
-      nscoord appHeight = nsPresContext::CSSPixelsToAppUnits((int32_t)height);
-      // If this image is rotated, we'll need to transpose the natural
-      // width/height.
-      bool coordFlip;
-      if (StyleVisibility()->mImageOrientation.IsFromImage()) {
-        coordFlip = mImage->GetOrientation().SwapsWidthAndHeight();
-      } else {
-        coordFlip = StyleVisibility()->mImageOrientation.SwapsWidthAndHeight();
-      }
-      intrinsicSize.width.SetCoordValue(coordFlip ? appHeight : appWidth);
-      intrinsicSize.height.SetCoordValue(coordFlip ? appWidth : appHeight);
-    }
+    int32_t width = 0;
+    int32_t height = 0;
+    Unused << mImage->GetWidth(&width);
+    Unused << mImage->GetHeight(&height);
+
+    nscoord appWidth = nsPresContext::CSSPixelsToAppUnits(width);
+    nscoord appHeight = nsPresContext::CSSPixelsToAppUnits(height);
+
+    // NOTE(emilio): image-orientation should be accounted for because we're
+    // using mImage.
+    intrinsicSize.width.SetCoordValue(appWidth);
+    intrinsicSize.height.SetCoordValue(appHeight);
   }
 
   return ComputeSizeWithIntrinsicDimensions(aRenderingContext, aWM,
                                             intrinsicSize, mIntrinsicRatio,
                                             aCBSize, aMargin, aBorder, aPadding,
                                             aFlags);
 }
 
@@ -1017,26 +1008,20 @@ nsImageFrame::Reflow(nsPresContext*     
     aMetrics.Height() -= y + aReflowInput.ComputedPhysicalBorderPadding().top;
     aMetrics.Height() = std::max(0, aMetrics.Height());
   }
 
 
   // we have to split images if we are:
   //  in Paginated mode, we need to have a constrained height, and have a height larger than our available height
   uint32_t loadStatus = imgIRequest::STATUS_NONE;
-  nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
-  NS_ASSERTION(imageLoader, "No content node??");
-  if (imageLoader) {
-    nsCOMPtr<imgIRequest> currentRequest;
-    imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
-                            getter_AddRefs(currentRequest));
-    if (currentRequest) {
-      currentRequest->GetImageStatus(&loadStatus);
-    }
+  if (nsCOMPtr<imgIRequest> currentRequest = GetCurrentRequest()) {
+    currentRequest->GetImageStatus(&loadStatus);
   }
+
   if (aPresContext->IsPaginated() &&
       ((loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE) || (mState & IMAGE_SIZECONSTRAINED)) &&
       NS_UNCONSTRAINEDSIZE != aReflowInput.AvailableHeight() &&
       aMetrics.Height() > aReflowInput.AvailableHeight()) {
     // our desired height was greater than 0, so to avoid infinite
     // splitting, use 1 pixel as the min
     aMetrics.Height() = std::max(nsPresContext::CSSPixelsToAppUnits(1), aReflowInput.AvailableHeight());
     aStatus.SetIncomplete();
@@ -1822,24 +1807,17 @@ nsImageFrame::BuildDisplayList(nsDisplay
   uint32_t clipFlags =
     nsStyleUtil::ObjectPropsMightCauseOverflow(StylePosition()) ?
     0 : DisplayListClipState::ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT;
 
   DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox
     clip(aBuilder, this, clipFlags);
 
   if (mComputedSize.width != 0 && mComputedSize.height != 0) {
-    nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
-    NS_ASSERTION(imageLoader, "Not an image loading content?");
-
-    nsCOMPtr<imgIRequest> currentRequest;
-    if (imageLoader) {
-      imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
-                              getter_AddRefs(currentRequest));
-    }
+    nsCOMPtr<imgIRequest> currentRequest = GetCurrentRequest();
 
     EventStates contentState = mContent->AsElement()->State();
     bool imageOK = IMAGE_OK(contentState, true);
 
     // XXX(seth): The SizeIsAvailable check here should not be necessary - the
     // intention is that a non-null mImage means we have a size, but there is
     // currently some code that violates this invariant.
     if (!imageOK || !mImage || !SizeIsAvailable(currentRequest)) {
@@ -2140,25 +2118,20 @@ nsImageFrame::AttributeChanged(int32_t a
 
   return NS_OK;
 }
 
 void
 nsImageFrame::OnVisibilityChange(Visibility aNewVisibility,
                                  const Maybe<OnNonvisible>& aNonvisibleAction)
 {
-  nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
-  if (!imageLoader) {
-    MOZ_ASSERT_UNREACHABLE("Should have an nsIImageLoadingContent");
-    nsAtomicContainerFrame::OnVisibilityChange(aNewVisibility, aNonvisibleAction);
-    return;
+  if (nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent)) {
+    imageLoader->OnVisibilityChange(aNewVisibility, aNonvisibleAction);
   }
 
-  imageLoader->OnVisibilityChange(aNewVisibility, aNonvisibleAction);
-
   if (aNewVisibility == Visibility::APPROXIMATELY_VISIBLE) {
     MaybeDecodeForPredictedSize();
   }
 
   nsAtomicContainerFrame::OnVisibilityChange(aNewVisibility, aNonvisibleAction);
 }
 
 #ifdef DEBUG_FRAME_DUMP
@@ -2170,28 +2143,22 @@ nsImageFrame::GetFrameName(nsAString& aR
 
 void
 nsImageFrame::List(FILE* out, const char* aPrefix, uint32_t aFlags) const
 {
   nsCString str;
   ListGeneric(str, aPrefix, aFlags);
 
   // output the img src url
-  nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
-  if (imageLoader) {
-    nsCOMPtr<imgIRequest> currentRequest;
-    imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
-                            getter_AddRefs(currentRequest));
-    if (currentRequest) {
-      nsCOMPtr<nsIURI> uri;
-      currentRequest->GetURI(getter_AddRefs(uri));
-      nsAutoCString uristr;
-      uri->GetAsciiSpec(uristr);
-      str += nsPrintfCString(" [src=%s]", uristr.get());
-    }
+  if (nsCOMPtr<imgIRequest> currentRequest = GetCurrentRequest()) {
+    nsCOMPtr<nsIURI> uri;
+    currentRequest->GetURI(getter_AddRefs(uri));
+    nsAutoCString uristr;
+    uri->GetAsciiSpec(uristr);
+    str += nsPrintfCString(" [src=%s]", uristr.get());
   }
   fprintf_stderr(out, "%s\n", str.get());
 }
 #endif
 
 nsIFrame::LogicalSides
 nsImageFrame::GetLogicalSkipSides(const ReflowInput* aReflowInput) const
 {
@@ -2442,24 +2409,22 @@ nsImageFrame::IconLoad::Notify(imgIReque
     frame->InvalidateFrame();
   }
 
   return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS(nsImageListener, imgINotificationObserver)
 
-nsImageListener::nsImageListener(nsImageFrame *aFrame) :
-  mFrame(aFrame)
+nsImageListener::nsImageListener(nsImageFrame* aFrame)
+  : mFrame(aFrame)
 {
 }
 
-nsImageListener::~nsImageListener()
-{
-}
+nsImageListener::~nsImageListener() = default;
 
 NS_IMETHODIMP
 nsImageListener::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData)
 {
   if (!mFrame)
     return NS_ERROR_FAILURE;
 
   return mFrame->Notify(aRequest, aType, aData);
--- a/layout/generic/nsImageFrame.h
+++ b/layout/generic/nsImageFrame.h
@@ -321,19 +321,24 @@ private:
    * @param aLayerInvalidRect The area to invalidate in layer space. If null, the
    *                          entire layer will be invalidated.
    * @param aFrameInvalidRect The area to invalidate in frame space. If null, the
    *                          entire frame will be invalidated.
    */
   void InvalidateSelf(const nsIntRect* aLayerInvalidRect,
                       const nsRect* aFrameInvalidRect);
 
+  already_AddRefed<imgIRequest> GetCurrentRequest() const;
+
   RefPtr<nsImageMap> mImageMap;
 
-  nsCOMPtr<imgINotificationObserver> mListener;
+  RefPtr<nsImageListener> mListener;
+
+  // An image request created for content: url(..).
+  RefPtr<imgRequestProxy> mContentURLRequest;
 
   nsCOMPtr<imgIContainer> mImage;
   nsCOMPtr<imgIContainer> mPrevImage;
   nsSize mComputedSize;
   mozilla::IntrinsicSize mIntrinsicSize;
   nsSize mIntrinsicRatio;
 
   bool mDisplayingIcon;