Back out bug 666446 due to Talos regression.
authorJustin Lebar <justin.lebar@gmail.com>
Wed, 02 Nov 2011 20:11:01 -0400
changeset 81245 fe4461c7654101502a633734a1a30f698f77cb7b
parent 81185 71aa042699d2c5eb94c5ab5e76f298a665aa4eda
child 81246 b8dd6f6f420756ee87938701b682bd6b85739923
push id90
push userffxbld
push dateSun, 29 Jan 2012 07:46:52 +0000
treeherdermozilla-release@acddb6b6a01c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs666446
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
Back out bug 666446 due to Talos regression.
content/base/public/nsIImageLoadingContent.idl
content/base/src/nsDocument.cpp
content/base/src/nsImageLoadingContent.cpp
content/base/src/nsImageLoadingContent.h
image/public/imgIContainer.idl
image/src/RasterImage.cpp
image/src/RasterImage.h
image/src/VectorImage.cpp
image/src/VectorImage.h
image/test/mochitest/Makefile.in
image/test/mochitest/animated-gif-finalframe.gif
image/test/mochitest/animated-gif.gif
image/test/mochitest/animated-gif2.gif
image/test/mochitest/animation.svg
image/test/mochitest/animationPolling.js
image/test/mochitest/filter-final.svg
image/test/mochitest/filter.svg
image/test/mochitest/iframe.html
image/test/mochitest/purple.gif
image/test/mochitest/ref-iframe.html
image/test/mochitest/test_animation.html
image/test/mochitest/test_background_image_anim.html
image/test/mochitest/test_bullet_animation.html
image/test/mochitest/test_changeOfSource.html
image/test/mochitest/test_changeOfSource2.html
image/test/mochitest/test_svg_animatedGIF.html
image/test/mochitest/test_svg_filter_animation.html
image/test/mochitest/test_undisplayed_iframe.html
image/test/mochitest/test_xultree_animation.xhtml
layout/base/nsImageLoader.cpp
layout/base/nsImageLoader.h
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/base/nsRefreshDriver.cpp
layout/base/nsRefreshDriver.h
layout/generic/nsBulletFrame.cpp
layout/generic/nsBulletFrame.h
layout/generic/nsIFrame.h
layout/generic/nsImageFrame.cpp
layout/svg/base/src/nsSVGImageFrame.cpp
layout/svg/base/src/nsSVGLeafFrame.cpp
layout/xul/base/src/nsImageBoxFrame.cpp
layout/xul/base/src/nsImageBoxFrame.h
layout/xul/base/src/tree/src/nsITreeImageListener.h
layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
layout/xul/base/src/tree/src/nsTreeBodyFrame.h
layout/xul/base/src/tree/src/nsTreeImageListener.cpp
layout/xul/base/src/tree/src/nsTreeImageListener.h
--- a/content/base/public/nsIImageLoadingContent.idl
+++ b/content/base/public/nsIImageLoadingContent.idl
@@ -37,17 +37,16 @@
 
 #include "imgIDecoderObserver.idl"
 
 interface imgIRequest;
 interface nsIChannel;
 interface nsIStreamListener;
 interface nsIURI;
 interface nsIDocument;
-interface nsIFrame;
 
 /**
  * This interface represents a content node that loads images.  The interface
  * exists to allow getting information on the images that the content node
  * loads and to allow registration of observers for the image loads.
  *
  * Implementors of this interface should handle all the mechanics of actually
  * loading an image -- getting the URI, checking with content policies and
@@ -61,17 +60,17 @@ interface nsIFrame;
  * observers to check which request they are getting notifications for.
  *
  * Observers added in mid-load will not get any notifications they
  * missed.  We should NOT freeze this interface without considering
  * this issue.  (It could be that the image status on imgIRequest is
  * sufficient, when combined with the imageBlockingStatus information.)
  */
 
-[scriptable, uuid(f7debb84-2854-4731-a57b-1bd752ad71f8)]
+[scriptable, uuid(95c74255-df9a-4060-b5a0-0d111fcafe08)]
 interface nsIImageLoadingContent : imgIDecoderObserver
 {
   /**
    * Request types.  Image loading content nodes attempt to do atomic
    * image changes when the image url is changed.  This means that
    * when the url changes the new image load will start, but the old
    * image will remain the "current" request until the new image is
    * fully loaded.  At that point, the old "current" request will be
@@ -125,28 +124,16 @@ interface nsIImageLoadingContent : imgID
    * is thrown)
    *
    * @throws NS_ERROR_UNEXPECTED if the request type requested is not
    * known
    */
   imgIRequest getRequest(in long aRequestType);
 
   /**
-   * Used to notify the image loading content node that a frame has been
-   * created.
-   */
-  [notxpcom] void frameCreated(in nsIFrame aFrame);
-
-  /**
-   * Used to notify the image loading content node that a frame has been
-   * destroyed.
-   */
-  [notxpcom] void frameDestroyed(in nsIFrame aFrame);
-
-  /**
    * Used to find out what type of request one is dealing with (eg
    * which request got passed through to the imgIDecoderObserver
    * interface of an observer)
    *
    * @param aRequest the request whose type we want to know
    *
    * @return an enum value saying what type this request is
    *
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -3220,17 +3220,16 @@ nsIDocument::TakeAnimationFrameListeners
 
 void
 nsDocument::DeleteShell()
 {
   mExternalResourceMap.HideViewers();
   if (IsEventHandlingEnabled()) {
     RevokeAnimationFrameNotifications();
   }
-
   mPresShell = nsnull;
 }
 
 void
 nsDocument::RevokeAnimationFrameNotifications()
 {
   if (mHavePendingPaint) {
     mPresShell->GetPresContext()->RefreshDriver()->RevokeBeforePaintEvent(this);
--- a/content/base/src/nsImageLoadingContent.cpp
+++ b/content/base/src/nsImageLoadingContent.cpp
@@ -67,17 +67,16 @@
 
 #include "nsIChannel.h"
 #include "nsIStreamListener.h"
 
 #include "nsIFrame.h"
 #include "nsIDOMNode.h"
 
 #include "nsContentUtils.h"
-#include "nsLayoutUtils.h"
 #include "nsIContentPolicy.h"
 #include "nsContentPolicyUtils.h"
 #include "nsEventDispatcher.h"
 #include "nsSVGEffects.h"
 
 #include "mozAutoDocUpdate.h"
 #include "mozilla/dom/Element.h"
 
@@ -111,19 +110,17 @@ nsImageLoadingContent::nsImageLoadingCon
     // mBroken starts out true, since an image without a URI is broken....
     mBroken(true),
     mUserDisabled(false),
     mSuppressed(false),
     mBlockingOnload(false),
     mNewRequestsWillNeedAnimationReset(false),
     mPendingRequestNeedsResetAnimation(false),
     mCurrentRequestNeedsResetAnimation(false),
-    mStateChangerDepth(0),
-    mCurrentRequestRegistered(false),
-    mPendingRequestRegistered(false)
+    mStateChangerDepth(0)
 {
   if (!nsContentUtils::GetImgLoader()) {
     mLoadingEnabled = false;
   }
 }
 
 void
 nsImageLoadingContent::DestroyImageLoadingContent()
@@ -194,26 +191,17 @@ nsImageLoadingContent::OnStartDecode(img
       (NS_SUCCEEDED(rv) && (loadFlags & nsIRequest::LOAD_BACKGROUND));
 
     // Block onload for non-background requests
     if (!background) {
       NS_ABORT_IF_FALSE(!mBlockingOnload, "Shouldn't already be blocking");
       SetBlockingOnload(true);
     }
   }
-  
-  bool* requestFlag = GetRegisteredFlagForRequest(aRequest);
-  if (requestFlag) {
-    nsLayoutUtils::RegisterImageRequest(GetFramePresContext(), aRequest,
-                                        requestFlag);
-  } else {
-    NS_ERROR("Starting to decode an image other than our current/pending "
-             "request?");
-  }
-  
+
   LOOP_OVER_OBSERVERS(OnStartDecode(aRequest));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsImageLoadingContent::OnStartContainer(imgIRequest* aRequest,
                                         imgIContainer* aContainer)
 {
@@ -336,23 +324,16 @@ nsImageLoadingContent::OnStopDecode(imgI
   // doing a paint first. This means that decode-on-draw images don't start
   // decoding, so we can't wait for them to finish. See bug 512435.
 
   // We can only do this if we have a presshell
   nsIDocument* doc = GetOurDocument();
   nsIPresShell* shell = doc ? doc->GetShell() : nsnull;
   if (shell) {
 
-    // Make sure that our image requests are deregistered from the refresh
-    // driver if they aren't animated. Note that this must be mCurrentRequest,
-    // or we would have aborted up above.
-    nsLayoutUtils::DeregisterImageRequestIfNotAnimated(GetFramePresContext(),
-                                                       mCurrentRequest,
-                                                       &mCurrentRequestRegistered);
-
     // We need to figure out whether to kick off decoding
     bool doRequestDecode = false;
 
     // If we haven't got the initial reflow yet, IsPaintingSuppressed actually
     // returns false
     if (!shell->DidInitialReflow())
       doRequestDecode = true;
 
@@ -515,54 +496,16 @@ nsImageLoadingContent::GetRequest(PRInt3
     *aRequest = nsnull;
     return NS_ERROR_UNEXPECTED;
   }
   
   NS_IF_ADDREF(*aRequest);
   return NS_OK;
 }
 
-NS_IMETHODIMP_(void)
-nsImageLoadingContent::FrameCreated(nsIFrame* aFrame)
-{
-  NS_ASSERTION(aFrame, "aFrame is null");
-
-  // We need to make sure that our image request is registered.
-  nsPresContext* presContext = aFrame->PresContext();
-
-  if (mCurrentRequest) {
-    nsLayoutUtils::RegisterImageRequest(presContext, mCurrentRequest,
-                                        &mCurrentRequestRegistered);
-    nsLayoutUtils::DeregisterImageRequestIfNotAnimated(presContext,
-                                                       mCurrentRequest,
-                                                       &mCurrentRequestRegistered);
-  } else if (mPendingRequest) {
-    // We don't need to do the same check for animation, because this will be
-    // done when decoding is finished.
-    nsLayoutUtils::RegisterImageRequest(presContext, mPendingRequest,
-                                        &mPendingRequestRegistered);
-  }
-}
-
-NS_IMETHODIMP_(void)
-nsImageLoadingContent::FrameDestroyed(nsIFrame* aFrame)
-{
-  NS_ASSERTION(aFrame, "aFrame is null");
-
-  // We need to make sure that our image request is deregistered.
-  if (mCurrentRequest) {
-    nsLayoutUtils::DeregisterImageRequest(GetFramePresContext(),
-                                          mCurrentRequest,
-                                          &mCurrentRequestRegistered);
-  } else if (mPendingRequest) {
-    nsLayoutUtils::DeregisterImageRequest(GetFramePresContext(),
-                                          mPendingRequest,
-                                          &mPendingRequestRegistered);
-  }
-}
 
 NS_IMETHODIMP
 nsImageLoadingContent::GetRequestType(imgIRequest* aRequest,
                                       PRInt32* aRequestType)
 {
   NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
 
   NS_PRECONDITION(aRequestType, "Null out param");
@@ -919,33 +862,16 @@ nsIDocument*
 nsImageLoadingContent::GetOurDocument()
 {
   nsCOMPtr<nsIContent> thisContent = do_QueryInterface(this);
   NS_ENSURE_TRUE(thisContent, nsnull);
 
   return thisContent->OwnerDoc();
 }
 
-nsIFrame*
-nsImageLoadingContent::GetOurPrimaryFrame()
-{
-  nsCOMPtr<nsIContent> thisContent = do_QueryInterface(this);
-  return thisContent->GetPrimaryFrame();
-}
-
-nsPresContext* nsImageLoadingContent::GetFramePresContext()
-{
-  nsIFrame* frame = GetOurPrimaryFrame();
-  if (!frame) {
-    return nsnull;
-  }
-
-  return frame->PresContext();
-}
-
 nsresult
 nsImageLoadingContent::StringToURI(const nsAString& aSpec,
                                    nsIDocument* aDocument,
                                    nsIURI** aURI)
 {
   NS_PRECONDITION(aDocument, "Must have a document");
   NS_PRECONDITION(aURI, "Null out param");
 
@@ -1055,26 +981,16 @@ nsImageLoadingContent::ClearCurrentReque
     // Even if we didn't have a current request, we might have been keeping
     // a URI as a placeholder for a failed load. Clear that now.
     mCurrentURI = nsnull;
     return;
   }
   NS_ABORT_IF_FALSE(!mCurrentURI,
                     "Shouldn't have both mCurrentRequest and mCurrentURI!");
 
-  // Deregister this image from the refresh driver so it no longer receives
-  // notifications.
-  nsLayoutUtils::DeregisterImageRequest(GetFramePresContext(), mCurrentRequest,
-                                        &mCurrentRequestRegistered);
-
-  // Deregister this image from the refresh driver so it no longer receives
-  // notifications.
-  nsLayoutUtils::DeregisterImageRequest(GetFramePresContext(), mCurrentRequest,
-                                        &mCurrentRequestRegistered);
-
   // Clean up the request.
   UntrackImage(mCurrentRequest);
   mCurrentRequest->CancelAndForgetObserver(aReason);
   mCurrentRequest = nsnull;
   mCurrentRequestNeedsResetAnimation = false;
 
   // We only block onload during the decoding of "current" images. This one is
   // going away, so we should unblock unconditionally here.
@@ -1088,39 +1004,22 @@ nsImageLoadingContent::ClearPendingReque
     return;
 
   // Push a null JSContext on the stack so that code that runs within
   // the below code doesn't think it's being called by JS. See bug
   // 604262.
   nsCxPusher pusher;
   pusher.PushNull();
 
-  // Deregister this image from the refresh driver so it no longer receives
-  // notifications.
-  nsLayoutUtils::DeregisterImageRequest(GetFramePresContext(), mPendingRequest,
-                                        &mPendingRequestRegistered);
-
   UntrackImage(mPendingRequest);
   mPendingRequest->CancelAndForgetObserver(aReason);
   mPendingRequest = nsnull;
   mPendingRequestNeedsResetAnimation = false;
 }
 
-bool*
-nsImageLoadingContent::GetRegisteredFlagForRequest(imgIRequest* aRequest)
-{
-  if (aRequest == mCurrentRequest) {
-    return &mCurrentRequestRegistered;
-  } else if (aRequest == mPendingRequest) {
-    return &mPendingRequestRegistered;
-  } else {
-    return nsnull;
-  }
-}
-
 bool
 nsImageLoadingContent::HaveSize(imgIRequest *aImage)
 {
   // Handle the null case
   if (!aImage)
     return false;
 
   // Query the image
--- a/content/base/src/nsImageLoadingContent.h
+++ b/content/base/src/nsImageLoadingContent.h
@@ -142,34 +142,16 @@ protected:
    * and such).  Not named GetDocument to prevent ambiguous method
    * names in subclasses
    *
    * @return the document we belong to
    */
   nsIDocument* GetOurDocument();
 
   /**
-   * Helper function to get the frame associated with this content. Not named
-   * GetPrimaryFrame to prevent ambiguous method names in subclasses.
-   *
-   * @return The frame which we belong to, or nsnull if it doesn't exist.
-   */
-  nsIFrame* GetOurPrimaryFrame();
-
-  /**
-   * Helper function to get the PresContext associated with this content's
-   * frame. Not named GetPresContext to prevent ambiguous method names in
-   * subclasses.
-   *
-   * @return The nsPresContext associated with our frame, or nsnull if either
-   *         the frame doesn't exist, or the frame's prescontext doesn't exist.
-   */
-  nsPresContext* GetFramePresContext();
-
-  /**
    * CancelImageRequests is called by subclasses when they want to
    * cancel all image requests (for example when the subclass is
    * somehow not an image anymore).
    */
   void CancelImageRequests(bool aNotify);
 
   /**
    * UseAsPrimaryRequest is called by subclasses when they have an existing
@@ -316,26 +298,16 @@ protected:
 
   /**
    * Cancels and nulls-out the "current" and "pending" requests if they exist.
    */
   void ClearCurrentRequest(nsresult aReason);
   void ClearPendingRequest(nsresult aReason);
 
   /**
-   * Retrieve a pointer to the 'registered with the refresh driver' flag for
-   * which a particular image request corresponds.
-   *
-   * @returns A pointer to the boolean flag for a given image request, or
-   *          |nsnull| if the request is not either |mPendingRequest| or
-   *          |mCurrentRequest|.
-   */
-  bool* GetRegisteredFlagForRequest(imgIRequest* aRequest);
-
-  /**
    * Static helper method to tell us if we have the size of a request. The
    * image may be null.
    */
   static bool HaveSize(imgIRequest *aImage);
 
   /**
    * Adds/Removes a given imgIRequest from our document's tracker.
    *
@@ -405,16 +377,11 @@ protected:
   bool mNewRequestsWillNeedAnimationReset : 1;
 
 private:
   bool mPendingRequestNeedsResetAnimation : 1;
   bool mCurrentRequestNeedsResetAnimation : 1;
 
   /* The number of nested AutoStateChangers currently tracking our state. */
   PRUint8 mStateChangerDepth;
-
-  // Flags to indicate whether each of the current and pending requests are
-  // registered with the refresh driver.
-  bool mCurrentRequestRegistered;
-  bool mPendingRequestRegistered;
 };
 
 #endif // nsImageLoadingContent_h__
--- a/image/public/imgIContainer.idl
+++ b/image/public/imgIContainer.idl
@@ -51,33 +51,28 @@ interface imgIDecoderObserver;
 #include "gfxRect.h"
 #include "gfxPattern.h"
 #include "gfxASurface.h"
 #include "nsRect.h"
 #include "nsSize.h"
 #include "limits.h"
 
 class nsIFrame;
-
-namespace mozilla {
-class TimeStamp;
-}
 %}
 
 [ptr] native gfxImageSurface(gfxImageSurface);
 [ptr] native gfxASurface(gfxASurface);
 native gfxImageFormat(gfxASurface::gfxImageFormat);
 [ptr] native gfxContext(gfxContext);
 [ref] native gfxMatrix(gfxMatrix);
 [ref] native gfxRect(gfxRect);
 native gfxGraphicsFilter(gfxPattern::GraphicsFilter);
 [ref] native nsIntRect(nsIntRect);
 [ref] native nsIntSize(nsIntSize);
 [ptr] native nsIFrame(nsIFrame);
-[ref] native TimeStamp(mozilla::TimeStamp);
 
 /**
  * imgIContainer is the interface that represents an image. It allows
  * access to frames as Thebes surfaces, and permits users to extract subregions
  * as other imgIContainers. It also allows drawing of images on to Thebes
  * contexts.
  *
  * Internally, imgIContainer also manages animation of images.
@@ -262,23 +257,16 @@ interface imgIContainer : nsISupports
     *
     * Upon instantiation images have a lock count of zero. It is an error to
     * call this method without first having made a matching lockImage() call.
     * In other words, the lock count is not allowed to be negative.
     */
   void unlockImage();
 
   /**
-    * Indicates that this imgIContainer has been triggered to update
-    * its internal animation state. Likely this should only be called
-    * from within nsImageFrame or objects of similar type.
-    */
-  [notxpcom] void requestRefresh([const] in TimeStamp aTime);
-
-  /**
    * Animation mode Constants
    *   0 = normal
    *   1 = don't animate
    *   2 = loop once
    */
   const short kNormalAnimMode   = 0;
   const short kDontAnimMode     = 1;
   const short kLoopOnceAnimMode = 2;
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -168,20 +168,20 @@ DiscardingEnabled()
 
   return enabled;
 }
 
 namespace mozilla {
 namespace imagelib {
 
 #ifndef DEBUG
-NS_IMPL_ISUPPORTS3(RasterImage, imgIContainer, nsIProperties,
+NS_IMPL_ISUPPORTS4(RasterImage, imgIContainer, nsITimerCallback, nsIProperties,
                    nsISupportsWeakReference)
 #else
-NS_IMPL_ISUPPORTS4(RasterImage, imgIContainer, nsIProperties,
+NS_IMPL_ISUPPORTS5(RasterImage, imgIContainer, nsITimerCallback, nsIProperties,
                    imgIContainerDebug, nsISupportsWeakReference)
 #endif
 
 //******************************************************************************
 RasterImage::RasterImage(imgStatusTracker* aStatusTracker) :
   Image(aStatusTracker), // invoke superclass's constructor
   mSize(0,0),
   mFrameDecodeFlags(DECODE_FLAGS_DEFAULT),
@@ -308,179 +308,16 @@ RasterImage::Init(imgIDecoderObserver *a
   CONTAINER_ENSURE_SUCCESS(rv);
 
   // Mark us as initialized
   mInitialized = true;
 
   return NS_OK;
 }
 
-bool
-RasterImage::AdvanceFrame(TimeStamp aTime, nsIntRect* aDirtyRect)
-{
-  NS_ASSERTION(aTime <= TimeStamp::Now(),
-               "Given time appears to be in the future");
-
-  imgFrame* nextFrame = nsnull;
-  PRUint32 currentFrameIndex = mAnim->currentAnimationFrameIndex;
-  PRUint32 nextFrameIndex = mAnim->currentAnimationFrameIndex + 1;
-  PRUint32 timeout = 0;
-
-  // Figure out if we have the next full frame. This is more complicated than
-  // just checking for mFrames.Length() because decoders append their frames
-  // before they're filled in.
-  NS_ABORT_IF_FALSE(mDecoder || nextFrameIndex <= mFrames.Length(),
-                    "How did we get 2 indices too far by incrementing?");
-
-  // If we don't have a decoder, we know we've got everything we're going to
-  // get. If we do, we only display fully-downloaded frames; everything else
-  // gets delayed.
-  bool haveFullNextFrame = !mDecoder ||
-                           nextFrameIndex < mDecoder->GetCompleteFrameCount();
-
-  // If we're done decoding the next frame, go ahead and display it now and
-  // reinit with the next frame's delay time.
-  if (haveFullNextFrame) {
-    if (mFrames.Length() == nextFrameIndex) {
-      // End of Animation, unless we are looping forever
-
-      // If animation mode is "loop once", it's time to stop animating
-      if (mAnimationMode == kLoopOnceAnimMode || mLoopCount == 0) {
-        mAnimationFinished = PR_TRUE;
-        EvaluateAnimation();
-      }
-
-      // We may have used compositingFrame to build a frame, and then copied
-      // it back into mFrames[..].  If so, delete composite to save memory
-      if (mAnim->compositingFrame && mAnim->lastCompositedFrameIndex == -1) {
-        mAnim->compositingFrame = nsnull;
-      }
-
-      nextFrameIndex = 0;
-
-      if (mLoopCount > 0) {
-        mLoopCount--;
-      }
-
-      if (!mAnimating) {
-        // break out early if we are actually done animating
-        return false;
-      }
-    }
-
-    if (!(nextFrame = mFrames[nextFrameIndex])) {
-      // something wrong with the next frame, skip it
-      mAnim->currentAnimationFrameIndex = nextFrameIndex;
-      return false;
-    }
-
-    timeout = nextFrame->GetTimeout();
-
-  } else {
-    // Uh oh, the frame we want to show is currently being decoded (partial)
-    // Wait until the next refresh driver tick and try again
-    return false;
-  }
-
-  if (!(timeout > 0)) {
-    mAnimationFinished = PR_TRUE;
-    EvaluateAnimation();
-  }
-
-  imgFrame *frameToUse = nsnull;
-
-  if (nextFrameIndex == 0) {
-    frameToUse = nextFrame;
-    *aDirtyRect = mAnim->firstFrameRefreshArea;
-  } else {
-    imgFrame *curFrame = mFrames[currentFrameIndex];
-
-    if (!curFrame) {
-      return false;
-    }
-
-    // Change frame
-    if (NS_FAILED(DoComposite(aDirtyRect, curFrame,
-                              nextFrame, nextFrameIndex))) {
-      // something went wrong, move on to next
-      NS_WARNING("RasterImage::AdvanceFrame(): Compositing of frame failed");
-      nextFrame->SetCompositingFailed(PR_TRUE);
-      mAnim->currentAnimationFrameIndex = nextFrameIndex;
-      mAnim->currentAnimationFrameTime = aTime;
-      return false;
-    }
-
-    nextFrame->SetCompositingFailed(PR_FALSE);
-  }
-
-  // Set currentAnimationFrameIndex at the last possible moment
-  mAnim->currentAnimationFrameIndex = nextFrameIndex;
-  mAnim->currentAnimationFrameTime = aTime;
-
-  return true;
-}
-
-//******************************************************************************
-// [notxpcom] void requestRefresh ([const] in TimeStamp aTime);
-NS_IMETHODIMP_(void)
-RasterImage::RequestRefresh(const mozilla::TimeStamp& aTime)
-{
-  if (!mAnimating || !ShouldAnimate()) {
-    return;
-  }
-
-  EnsureAnimExists();
-
-  // only advance the frame if the current time is greater than or
-  // equal to the current frame's end time.
-  TimeStamp currentFrameEndTime = GetCurrentImgFrameEndTime();
-  bool frameAdvanced = false;
-
-  // The dirtyRect variable will contain an accumulation of the sub-rectangles
-  // that are dirty for each frame we advance in AdvanceFrame().
-  nsIntRect dirtyRect;
-
-  while (currentFrameEndTime <= aTime) {
-    TimeStamp oldFrameEndTime = currentFrameEndTime;
-    nsIntRect frameDirtyRect;
-    bool didAdvance = AdvanceFrame(aTime, &frameDirtyRect);
-    frameAdvanced = frameAdvanced || didAdvance;
-    currentFrameEndTime = GetCurrentImgFrameEndTime();
-
-    // Accumulate the dirty area.
-    dirtyRect = dirtyRect.Union(frameDirtyRect);
-
-    // if we didn't advance a frame, and our frame end time didn't change,
-    // then we need to break out of this loop & wait for the frame(s)
-    // to finish downloading
-    if (!frameAdvanced && (currentFrameEndTime == oldFrameEndTime)) {
-      break;
-    }
-  }
-
-  if (frameAdvanced) {
-    nsCOMPtr<imgIContainerObserver> observer(do_QueryReferent(mObserver));
-
-    if (!observer) {
-      NS_ERROR("Refreshing image after its imgRequest is gone");
-      StopAnimation();
-      return;
-    }
-
-    // Notify listeners that our frame has actually changed, but do this only
-    // once for all frames that we've now passed (if AdvanceFrame() was called
-    // more than once).
-    #ifdef DEBUG
-      mFramesNotified++;
-    #endif
-
-    observer->FrameChanged(this, &dirtyRect);
-  }
-}
-
 //******************************************************************************
 /* [noscript] imgIContainer extractFrame(PRUint32 aWhichFrame,
  *                                       [const] in nsIntRect aRegion,
  *                                       in PRUint32 aFlags); */
 NS_IMETHODIMP
 RasterImage::ExtractFrame(PRUint32 aWhichFrame,
                           const nsIntRect &aRegion,
                           PRUint32 aFlags,
@@ -652,37 +489,16 @@ PRUint32
 RasterImage::GetCurrentImgFrameIndex() const
 {
   if (mAnim)
     return mAnim->currentAnimationFrameIndex;
 
   return 0;
 }
 
-TimeStamp
-RasterImage::GetCurrentImgFrameEndTime() const
-{
-  imgFrame* currentFrame = mFrames[mAnim->currentAnimationFrameIndex];
-  TimeStamp currentFrameTime = mAnim->currentAnimationFrameTime;
-  PRInt64 timeout = currentFrame->GetTimeout();
-
-  if (timeout < 0) {
-    // We need to return a sentinel value in this case, because our logic
-    // doesn't work correctly if we have a negative timeout value. The reason
-    // this positive infinity was chosen was because it works with the loop in
-    // RequestRefresh() above.
-    return TimeStamp() + TimeDuration::FromMilliseconds(UINT64_MAX_VAL);
-  }
-
-  TimeDuration durationOfTimeout = TimeDuration::FromMilliseconds(timeout);
-  TimeStamp currentFrameEndTime = currentFrameTime + durationOfTimeout;
-
-  return currentFrameEndTime;
-}
-
 imgFrame*
 RasterImage::GetCurrentImgFrame()
 {
   return GetImgFrame(GetCurrentImgFrameIndex());
 }
 
 imgFrame*
 RasterImage::GetCurrentDrawableImgFrame()
@@ -1317,41 +1133,53 @@ RasterImage::StartAnimation()
 {
   if (mError)
     return NS_ERROR_FAILURE;
 
   NS_ABORT_IF_FALSE(ShouldAnimate(), "Should not animate!");
 
   EnsureAnimExists();
 
-  imgFrame* currentFrame = GetCurrentImgFrame();
+  NS_ABORT_IF_FALSE(mAnim && !mAnim->timer, "Anim must exist and not have a timer yet");
+  
+  // Default timeout to 100: the timer notify code will do the right
+  // thing, so just get that started.
+  PRInt32 timeout = 100;
+  imgFrame *currentFrame = GetCurrentImgFrame();
   if (currentFrame) {
-    if (currentFrame->GetTimeout() < 0) { // -1 means display this frame forever
+    timeout = currentFrame->GetTimeout();
+    if (timeout < 0) { // -1 means display this frame forever
       mAnimationFinished = true;
       return NS_ERROR_ABORT;
     }
-
-    // We need to set the time that this initial frame was first displayed, as
-    // this is used in AdvanceFrame().
-    mAnim->currentAnimationFrameTime = TimeStamp::Now();
   }
   
+  mAnim->timer = do_CreateInstance("@mozilla.org/timer;1");
+  NS_ENSURE_TRUE(mAnim->timer, NS_ERROR_OUT_OF_MEMORY);
+  mAnim->timer->InitWithCallback(static_cast<nsITimerCallback*>(this),
+                                 timeout, nsITimer::TYPE_REPEATING_SLACK);
+  
   return NS_OK;
 }
 
 //******************************************************************************
 /* void stopAnimation (); */
 nsresult
 RasterImage::StopAnimation()
 {
   NS_ABORT_IF_FALSE(mAnimating, "Should be animating!");
 
   if (mError)
     return NS_ERROR_FAILURE;
 
+  if (mAnim->timer) {
+    mAnim->timer->Cancel();
+    mAnim->timer = nsnull;
+  }
+
   return NS_OK;
 }
 
 //******************************************************************************
 /* void resetAnimation (); */
 NS_IMETHODIMP
 RasterImage::ResetAnimation()
 {
@@ -1598,16 +1426,137 @@ nsresult
 RasterImage::SetSourceSizeHint(PRUint32 sizeHint)
 {
   if (sizeHint && StoringSourceData())
     return mSourceData.SetCapacity(sizeHint) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
   return NS_OK;
 }
 
 //******************************************************************************
+/* void notify(in nsITimer timer); */
+NS_IMETHODIMP
+RasterImage::Notify(nsITimer *timer)
+{
+#ifdef DEBUG
+  mFramesNotified++;
+#endif
+
+  // This should never happen since the timer is only set up in StartAnimation()
+  // after mAnim is checked to exist.
+  NS_ABORT_IF_FALSE(mAnim, "Need anim for Notify()");
+  NS_ABORT_IF_FALSE(timer, "Need timer for Notify()");
+  NS_ABORT_IF_FALSE(mAnim->timer == timer,
+                    "RasterImage::Notify() called with incorrect timer");
+
+  if (!mAnimating || !ShouldAnimate())
+    return NS_OK;
+
+  nsCOMPtr<imgIContainerObserver> observer(do_QueryReferent(mObserver));
+  if (!observer) {
+    // the imgRequest that owns us is dead, we should die now too.
+    NS_ABORT_IF_FALSE(mAnimationConsumers == 0,
+                      "If no observer, should have no consumers");
+    if (mAnimating)
+      StopAnimation();
+    return NS_OK;
+  }
+
+  if (mFrames.Length() == 0)
+    return NS_OK;
+  
+  imgFrame *nextFrame = nsnull;
+  PRInt32 previousFrameIndex = mAnim->currentAnimationFrameIndex;
+  PRUint32 nextFrameIndex = mAnim->currentAnimationFrameIndex + 1;
+  PRInt32 timeout = 0;
+
+  // Figure out if we have the next full frame. This is more complicated than
+  // just checking for mFrames.Length() because decoders append their frames
+  // before they're filled in.
+  NS_ABORT_IF_FALSE(mDecoder || nextFrameIndex <= mFrames.Length(),
+                    "How did we get 2 indicies too far by incrementing?");
+
+  // If we don't have a decoder, we know we've got everything we're going to get.
+  // If we do, we only display fully-downloaded frames; everything else gets delayed.
+  bool haveFullNextFrame = !mDecoder || nextFrameIndex < mDecoder->GetCompleteFrameCount();
+
+  // If we're done decoding the next frame, go ahead and display it now and
+  // reinit the timer with the next frame's delay time.
+  if (haveFullNextFrame) {
+    if (mFrames.Length() == nextFrameIndex) {
+      // End of Animation
+
+      // If animation mode is "loop once", it's time to stop animating
+      if (mAnimationMode == kLoopOnceAnimMode || mLoopCount == 0) {
+        mAnimationFinished = true;
+        EvaluateAnimation();
+        return NS_OK;
+      } else {
+        // We may have used compositingFrame to build a frame, and then copied
+        // it back into mFrames[..].  If so, delete composite to save memory
+        if (mAnim->compositingFrame && mAnim->lastCompositedFrameIndex == -1)
+          mAnim->compositingFrame = nsnull;
+      }
+
+      nextFrameIndex = 0;
+      if (mLoopCount > 0)
+        mLoopCount--;
+    }
+
+    if (!(nextFrame = mFrames[nextFrameIndex])) {
+      // something wrong with the next frame, skip it
+      mAnim->currentAnimationFrameIndex = nextFrameIndex;
+      mAnim->timer->SetDelay(100);
+      return NS_OK;
+    }
+    timeout = nextFrame->GetTimeout();
+
+  } else {
+    // Uh oh, the frame we want to show is currently being decoded (partial)
+    // Wait a bit and try again
+    mAnim->timer->SetDelay(100);
+    return NS_OK;
+  }
+
+  if (timeout > 0)
+    mAnim->timer->SetDelay(timeout);
+  else {
+    mAnimationFinished = true;
+    EvaluateAnimation();
+  }
+
+  nsIntRect dirtyRect;
+
+  if (nextFrameIndex == 0) {
+    dirtyRect = mAnim->firstFrameRefreshArea;
+  } else {
+    imgFrame *prevFrame = mFrames[previousFrameIndex];
+    if (!prevFrame)
+      return NS_OK;
+
+    // Change frame and announce it
+    if (NS_FAILED(DoComposite(&dirtyRect, prevFrame,
+                              nextFrame, nextFrameIndex))) {
+      // something went wrong, move on to next
+      NS_WARNING("RasterImage::Notify(): Composing Frame Failed\n");
+      nextFrame->SetCompositingFailed(true);
+      mAnim->currentAnimationFrameIndex = nextFrameIndex;
+      return NS_OK;
+    } else {
+      nextFrame->SetCompositingFailed(false);
+    }
+  }
+  // Set currentAnimationFrameIndex at the last possible moment
+  mAnim->currentAnimationFrameIndex = nextFrameIndex;
+  // Refreshes the screen
+  observer->FrameChanged(this, &dirtyRect);
+  
+  return NS_OK;
+}
+
+//******************************************************************************
 // DoComposite gets called when the timer for animation get fired and we have to
 // update the composited frame of the animation.
 nsresult
 RasterImage::DoComposite(nsIntRect* aDirtyRect,
                          imgFrame* aPrevFrame,
                          imgFrame* aNextFrame,
                          PRInt32 aNextFrameIndex)
 {
--- a/image/src/RasterImage.h
+++ b/image/src/RasterImage.h
@@ -66,61 +66,42 @@
 #include "DiscardTracker.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Telemetry.h"
 #ifdef DEBUG
   #include "imgIContainerDebug.h"
 #endif
 
 class imgIDecoder;
-class imgIContainerObserver;
 class nsIInputStream;
 
 #define NS_RASTERIMAGE_CID \
 { /* 376ff2c1-9bf6-418a-b143-3340c00112f7 */         \
      0x376ff2c1,                                     \
      0x9bf6,                                         \
      0x418a,                                         \
     {0xb1, 0x43, 0x33, 0x40, 0xc0, 0x01, 0x12, 0xf7} \
 }
 
 /**
- * It would be nice if we had a macro for this in prtypes.h.
- * TODO: Place this macro in prtypes.h as PR_UINT64_MAX.
- */
-#define UINT64_MAX_VAL PRUint64(-1)
-
-/**
  * Handles static and animated image containers.
  *
  *
  * @par A Quick Walk Through
  * The decoder initializes this class and calls AppendFrame() to add a frame.
  * Once RasterImage detects more than one frame, it starts the animation
- * with StartAnimation(). Note that the invalidation events for RasterImage are
- * generated automatically using nsRefreshDriver.
- *
- * @par
- * StartAnimation() initializes the animation helper object and sets the time
- * the first frame was displayed to the current clock time.
+ * with StartAnimation().
  *
  * @par
- * When the refresh driver corresponding to the imgIContainer that this image is
- * a part of notifies the RasterImage that it's time to invalidate,
- * RequestRefresh() is called with a given TimeStamp to advance to. As long as
- * the timeout of the given frame (the frame's "delay") plus the time that frame
- * was first displayed is less than or equal to the TimeStamp given,
- * RequestRefresh() calls AdvanceFrame().
+ * StartAnimation() creates a timer.  The timer calls Notify when the
+ * specified frame delay time is up.
  *
  * @par
- * AdvanceFrame() is responsible for advancing a single frame of the animation.
- * It can return true, meaning that the frame advanced, or false, meaning that
- * the frame failed to advance (usually because the next frame hasn't been
- * decoded yet). It is also responsible for performing the final animation stop
- * procedure if the final frame of a non-looping animation is reached.
+ * Notify() moves on to the next frame, sets up the new timer delay, destroys
+ * the old frame, and forces a redraw via observer->FrameChanged().
  *
  * @par
  * Each frame can have a different method of removing itself. These are
  * listed as imgIContainer::cDispose... constants.  Notify() calls 
  * DoComposite() to handle any special frame destruction.
  *
  * @par
  * The basic path through DoComposite() is:
@@ -165,24 +146,26 @@ class nsIInputStream;
 
 namespace mozilla {
 namespace imagelib {
 
 class imgDecodeWorker;
 class Decoder;
 
 class RasterImage : public Image
+                  , public nsITimerCallback
                   , public nsIProperties
                   , public nsSupportsWeakReference
 #ifdef DEBUG
                   , public imgIContainerDebug
 #endif
 {
 public:
   NS_DECL_ISUPPORTS
+  NS_DECL_NSITIMERCALLBACK
   NS_DECL_NSIPROPERTIES
 #ifdef DEBUG
   NS_DECL_IMGICONTAINERDEBUG
 #endif
 
   // BEGIN NS_DECL_IMGICONTAINER (minus GetAnimationMode/SetAnimationMode)
   // ** Don't edit this chunk except to mirror changes in imgIContainer.idl **
   NS_SCRIPTABLE NS_IMETHOD GetWidth(PRInt32 *aWidth);
@@ -195,17 +178,16 @@ public:
   NS_IMETHOD CopyFrame(PRUint32 aWhichFrame, PRUint32 aFlags, gfxImageSurface **_retval NS_OUTPARAM);
   NS_IMETHOD ExtractFrame(PRUint32 aWhichFrame, const nsIntRect & aRect, PRUint32 aFlags, imgIContainer **_retval NS_OUTPARAM);
   NS_IMETHOD Draw(gfxContext *aContext, gfxPattern::GraphicsFilter aFilter, const gfxMatrix & aUserSpaceToImageSpace, const gfxRect & aFill, const nsIntRect & aSubimage, const nsIntSize & aViewportSize, PRUint32 aFlags);
   NS_IMETHOD_(nsIFrame *) GetRootLayoutFrame(void);
   NS_SCRIPTABLE NS_IMETHOD RequestDecode(void);
   NS_SCRIPTABLE NS_IMETHOD LockImage(void);
   NS_SCRIPTABLE NS_IMETHOD UnlockImage(void);
   NS_SCRIPTABLE NS_IMETHOD ResetAnimation(void);
-  NS_IMETHOD_(void) RequestRefresh(const mozilla::TimeStamp& aTime);
   // END NS_DECL_IMGICONTAINER
 
   RasterImage(imgStatusTracker* aStatusTracker = nsnull);
   virtual ~RasterImage();
 
   virtual nsresult StartAnimation();
   virtual nsresult StopAnimation();
 
@@ -347,20 +329,16 @@ public:
   const char* GetURIString() { return mURIString.get();}
 
 private:
   struct Anim
   {
     //! Area of the first frame that needs to be redrawn on subsequent loops.
     nsIntRect                  firstFrameRefreshArea;
     PRUint32                   currentAnimationFrameIndex; // 0 to numFrames-1
-
-    // the time that the animation advanced to the current frame
-    TimeStamp                  currentAnimationFrameTime;
-
     //! Track the last composited frame for Optimizations (See DoComposite code)
     PRInt32                    lastCompositedFrameIndex;
     /** For managing blending of frames
      *
      * Some animations will use the compositingFrame to composite images
      * and just hand this back to the caller when it is time to draw the frame.
      * NOTE: When clearing compositingFrame, remember to set
      *       lastCompositedFrameIndex to -1.  Code assume that if
@@ -369,60 +347,49 @@ private:
     nsAutoPtr<imgFrame>        compositingFrame;
     /** the previous composited frame, for DISPOSE_RESTORE_PREVIOUS
      *
      * The Previous Frame (all frames composited up to the current) needs to be
      * stored in cases where the image specifies it wants the last frame back
      * when it's done with the current frame.
      */
     nsAutoPtr<imgFrame>        compositingPrevFrame;
+    //! Timer to animate multiframed images
+    nsCOMPtr<nsITimer>         timer;
 
     Anim() :
       firstFrameRefreshArea(),
       currentAnimationFrameIndex(0),
-      lastCompositedFrameIndex(-1) {}
-    ~Anim() {}
+      lastCompositedFrameIndex(-1)
+    {
+      ;
+    }
+    ~Anim()
+    {
+      if (timer)
+        timer->Cancel();
+    }
   };
 
   /**
-   * Advances the animation. Typically, this will advance a single frame, but it
-   * may advance multiple frames. This may happen if we have infrequently
-   * "ticking" refresh drivers (e.g. in background tabs), or extremely short-
-   * lived animation frames.
-   *
-   * @param aTime the time that the animation should advance to. This will
-   *              typically be <= TimeStamp::Now().
-   *
-   * @param [out] aDirtyRect a pointer to an nsIntRect which encapsulates the
-   *        area to be repainted after the frame is advanced.
-   *
-   * @returns true, if the frame was successfully advanced, false if it was not
-   *          able to be advanced (e.g. the frame to which we want to advance is
-   *          still decoding). Note: If false is returned, then aDirtyRect will
-   *          remain unmodified.
-   */
-  bool AdvanceFrame(mozilla::TimeStamp aTime, nsIntRect* aDirtyRect);
-
-  /**
    * Deletes and nulls out the frame in mFrames[framenum].
    *
    * Does not change the size of mFrames.
    *
    * @param framenum The index of the frame to be deleted. 
    *                 Must lie in [0, mFrames.Length() )
    */
   void DeleteImgFrame(PRUint32 framenum);
 
   imgFrame* GetImgFrameNoDecode(PRUint32 framenum);
   imgFrame* GetImgFrame(PRUint32 framenum);
   imgFrame* GetDrawableImgFrame(PRUint32 framenum);
   imgFrame* GetCurrentImgFrame();
   imgFrame* GetCurrentDrawableImgFrame();
   PRUint32 GetCurrentImgFrameIndex() const;
-  mozilla::TimeStamp GetCurrentImgFrameEndTime() const;
   
   inline void EnsureAnimExists()
   {
     if (!mAnim) {
 
       // Create the animation context
       mAnim = new Anim();
 
@@ -433,37 +400,37 @@ private:
       // data too. However, doing this is actually hard, because we're probably
       // calling ensureAnimExists mid-decode, and thus we're decoding out of
       // the source buffer. Since we're going to fix this anyway later, and
       // since we didn't kill the source data in the old world either, locking
       // is acceptable for the moment.
       LockImage();
     }
   }
-
+  
   /** Function for doing the frame compositing of animations
    *
    * @param aDirtyRect  Area that the display will need to update
    * @param aPrevFrame  Last Frame seen/processed
    * @param aNextFrame  Frame we need to incorperate/display
    * @param aNextFrameIndex Position of aNextFrame in mFrames list
    */
   nsresult DoComposite(nsIntRect* aDirtyRect,
                        imgFrame* aPrevFrame,
                        imgFrame* aNextFrame,
                        PRInt32 aNextFrameIndex);
-
+  
   /** Clears an area of <aFrame> with transparent black.
    *
    * @param aFrame Target Frame
    *
    * @note Does also clears the transparancy mask
    */
   static void ClearFrame(imgFrame* aFrame);
-
+  
   //! @overload
   static void ClearFrame(imgFrame* aFrame, nsIntRect &aRect);
   
   //! Copy one frames's image and mask into another
   static bool CopyFrameImage(imgFrame *aSrcFrame,
                                imgFrame *aDstFrame);
   
   /** Draws one frames's image to into another,
--- a/image/src/VectorImage.cpp
+++ b/image/src/VectorImage.cpp
@@ -167,16 +167,17 @@ SVGDrawingCallback::operator()(gfxContex
   // Clip to aFillRect so that we don't paint outside.
   aContext->NewPath();
   aContext->Rectangle(aFillRect);
   aContext->Clip();
 
   gfxContextMatrixAutoSaveRestore contextMatrixRestorer(aContext);
   aContext->Multiply(gfxMatrix(aTransform).Invert());
 
+
   nsPresContext* presContext = presShell->GetPresContext();
   NS_ABORT_IF_FALSE(presContext, "pres shell w/out pres context");
 
   nsRect svgRect(presContext->DevPixelsToAppUnits(mViewport.x),
                  presContext->DevPixelsToAppUnits(mViewport.y),
                  presContext->DevPixelsToAppUnits(mViewport.width),
                  presContext->DevPixelsToAppUnits(mViewport.height));
 
@@ -325,24 +326,16 @@ VectorImage::GetWidth(PRInt32* aWidth)
     *aWidth = 0;
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 //******************************************************************************
-/* [notxpcom] void requestRefresh ([const] in TimeStamp aTime); */
-NS_IMETHODIMP_(void)
-VectorImage::RequestRefresh(const mozilla::TimeStamp& aTime)
-{
-  // TODO: Implement for b666446.
-}
-
-//******************************************************************************
 /* readonly attribute PRInt32 height; */
 NS_IMETHODIMP
 VectorImage::GetHeight(PRInt32* aHeight)
 {
   if (mError || !mIsFullyLoaded) {
     *aHeight = 0;
     return NS_ERROR_FAILURE;
   }
--- a/image/src/VectorImage.h
+++ b/image/src/VectorImage.h
@@ -37,17 +37,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozilla_imagelib_VectorImage_h_
 #define mozilla_imagelib_VectorImage_h_
 
 #include "Image.h"
 #include "nsIStreamListener.h"
 #include "nsWeakReference.h"
-#include "mozilla/TimeStamp.h"
 
 class imgIDecoderObserver;
 
 namespace mozilla {
 namespace imagelib {
 
 class SVGDocumentWrapper;
 class SVGRootRenderingObserver;
@@ -72,17 +71,16 @@ public:
   NS_IMETHOD CopyFrame(PRUint32 aWhichFrame, PRUint32 aFlags, gfxImageSurface **_retval NS_OUTPARAM);
   NS_IMETHOD ExtractFrame(PRUint32 aWhichFrame, const nsIntRect & aRect, PRUint32 aFlags, imgIContainer **_retval NS_OUTPARAM);
   NS_IMETHOD Draw(gfxContext *aContext, gfxPattern::GraphicsFilter aFilter, const gfxMatrix & aUserSpaceToImageSpace, const gfxRect & aFill, const nsIntRect & aSubimage, const nsIntSize & aViewportSize, PRUint32 aFlags);
   NS_IMETHOD_(nsIFrame *) GetRootLayoutFrame(void);
   NS_SCRIPTABLE NS_IMETHOD RequestDecode(void);
   NS_SCRIPTABLE NS_IMETHOD LockImage(void);
   NS_SCRIPTABLE NS_IMETHOD UnlockImage(void);
   NS_SCRIPTABLE NS_IMETHOD ResetAnimation(void);
-  NS_IMETHOD_(void) RequestRefresh(const mozilla::TimeStamp& aTime);
   // END NS_DECL_IMGICONTAINER
 
   VectorImage(imgStatusTracker* aStatusTracker = nsnull);
   virtual ~VectorImage();
 
   // Methods inherited from Image
   nsresult Init(imgIDecoderObserver* aObserver,
                 const char* aMimeType,
--- a/image/test/mochitest/Makefile.in
+++ b/image/test/mochitest/Makefile.in
@@ -88,36 +88,17 @@ include $(topsrcdir)/config/rules.mk
                 test_bug671906.html \
                 $(NULL)
 
 # Tests disabled due to intermittent orange
 # test_bug435296.html disabled - See bug 578591
 # test_bug478398.html disabled - See bug 579139
 
 _CHROME_FILES = imgutils.js \
-                animationPolling.js \
                 lime-anim-100x100.svg \
-                animation.svg \
                 test_animSVGImage.html \
-                test_animation.html \
-                animated-gif-finalframe.gif \
-                animated-gif.gif \
-                animated-gif2.gif \
-                purple.gif \
-                test_svg_animatedGIF.html \
-                test_bullet_animation.html \
-                test_background_image_anim.html \
-                filter.svg \
-                filter-final.svg \
-                test_svg_filter_animation.html \
-                test_xultree_animation.xhtml \
-                test_changeOfSource.html \
-                test_changeOfSource2.html \
-                test_undisplayed_iframe.html \
-                iframe.html \
-                ref-iframe.html \
                 $(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
 libs:: $(_CHROME_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
deleted file mode 100644
index 4e80d31a727fc725326082d71ba42ccd33bf3b49..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 001cbfb87a05e518f53707a4237a7034d2111344..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index c66cc4b7344f52e312460d7424cc2cce7f6fd87d..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/image/test/mochitest/animation.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg"
-     xmlns:xlink="http://www.w3.org/1999/xlink">
-	<image id="anim" xlink:href="animated-gif.gif" width="40" height="40"/>
-</svg>
-
deleted file mode 100644
--- a/image/test/mochitest/animationPolling.js
+++ /dev/null
@@ -1,395 +0,0 @@
-var currentTest;
-var gIsImageLoaded = false;
-var gIsRefImageLoaded = false;
-
-function pollForSuccess ()
-{
-  if (!currentTest.isTestFinished) {
-    if (!currentTest.reusingReferenceImage || (currentTest.reusingReferenceImage
-        && gRefImageLoaded)) {
-      currentTest.checkImage();
-    }
-
-    setTimeout(pollForSuccess, currentTest.pollFreq);
-  }
-};
-
-function imageLoadCallback()
-{
-  gIsImageLoaded = true;
-}
-
-function referencePoller()
-{
-  currentTest.takeReferenceSnapshot();
-}
-
-function reuseImageCallback()
-{
-  gIsRefImageLoaded = true;
-}
-
-function failTest ()
-{
-  if (currentTest.isTestFinished || currentTest.closeFunc) {
-    return;
-  }
-
-  ok(false, "timing out after " + currentTest.timeout + "ms.  "
-     + "Animated image still doesn't look correct, " + "after call #"
-     + currentTest.onStopFrameCounter + " to onStopFrame");
-  currentTest.wereFailures = true;
-
-  currentTest.enableDisplay(document.getElementById(currentTest.debugElementId));
-
-  currentTest.cleanUpAndFinish();
-};
-
-/**
- * Create a new AnimationTest object.
- *
- * @param pollFreq The amount of time (in ms) to wait between consecutive
- *        snapshots if the reference image and the test image don't match.
- * @param timeout The total amount of time (in ms) to wait before declaring the
- *        test as failed.
- * @param referenceElementId The id attribute of the reference image element, or
- *        the source of the image to change to, once the reference snapshot has
- *        been successfully taken. This latter option could be used if you don't
- *        want the image to become invisible at any time during the test.
- * @param imageElementId The id attribute of the test image element.
- * @param debugElementId The id attribute of the div where links should be
- *        appended if the test fails.
- * @param cleanId The id attribute of the div or element to use as the 'clean'
- *        test. This element is only enabled when we are testing to verify that
- *        the reference image has been loaded. It can be undefined.
- * @param srcAttr The location of the source of the image, for preloading. This
- *        is usually not required, but it useful for preloading reference
- *        images.
- * @param xulTest A boolean value indicating whether or not this is a XUL test
- *        (uses hidden=true/false rather than display: none to hide/show
- *        elements).
- * @param closeFunc A function that should be called when this test is finished.
- *        If null, then cleanUpAndFinish() will be called. This can be used to
- *        chain tests together, so they are all finished exactly once.
- * @returns {AnimationTest}
- */
-function AnimationTest(pollFreq, timeout, referenceElementId, imageElementId,
-                       debugElementId, cleanId, srcAttr, xulTest, closeFunc)
-{
-  // We want to test the cold loading behavior, so clear cache in case an
-  // earlier test got our image in there already.
-  clearImageCache();
-
-  this.wereFailures = false;
-  this.pollFreq = pollFreq;
-  this.timeout = timeout;
-  this.imageElementId = imageElementId;
-  this.referenceElementId = referenceElementId;
-
-  if (!document.getElementById(referenceElementId)) {
-    // In this case, we're assuming the user passed in a string that
-    // indicates the source of the image they want to change to,
-    // after the reference image has been taken.
-    this.reusingImageAsReference = true;
-  }
-
-  this.srcAttr = srcAttr;
-  this.debugElementId = debugElementId;
-  this.referenceSnapshot = ""; // value will be set in takeReferenceSnapshot()
-  this.onStopFrameCounter = 0;
-  this.isTestFinished = false;
-  this.numRefsTaken = 0;
-  this.blankWaitTime = 0;
-
-  this.cleanId = cleanId ? cleanId : '';
-  this.xulTest = xulTest ? xulTest : '';
-  this.closeFunc = closeFunc ? closeFunc : '';
-
-  if (this.srcAttr) {
-    this.myImage = new Image();
-    this.myImage.onload = imageLoadCallback;
-    this.myImage.src = this.srcAttr;
-  } else {
-    gIsImageLoaded = true;
-  }
-}
-
-AnimationTest.prototype.outputDebugInfo = function(message, id, dataUri)
-{
-  var debugElement = document.getElementById(this.debugElementId);
-  var newDataUriElement = document.createElement("a");
-  newDataUriElement.setAttribute("id", id);
-  newDataUriElement.setAttribute("href", dataUri);
-  newDataUriElement.appendChild(document.createTextNode(message));
-  debugElement.appendChild(newDataUriElement);
-  var brElement = document.createElement("br");
-  debugElement.appendChild(brElement);
-};
-
-AnimationTest.prototype.isFinished = function()
-{
-  return this.isTestFinished;
-};
-
-AnimationTest.prototype.takeCleanSnapshot = function()
-{
-  var cleanElement;
-  if (this.cleanId) {
-    cleanElement = document.getElementById(this.cleanId);
-  }
-
-  // Enable clean page comparison element
-  if (cleanElement) {
-    this.enableDisplay(cleanElement);
-  }
-
-  // Take a snapshot of the initial (clean) page
-  this.cleanSnapshot = snapshotWindow(window, false);
-
-  // Disable the clean page comparison element
-  if (cleanElement) {
-    this.disableDisplay(cleanElement);
-  }
-
-  var dataString1 = "Clean Snapshot";
-  this.outputDebugInfo(dataString1, 'cleanSnap',
-                       this.cleanSnapshot.toDataURL());
-};
-
-AnimationTest.prototype.takeBlankSnapshot = function()
-{
-  // Take a snapshot of the initial (essentially blank) page
-  this.blankSnapshot = snapshotWindow(window, false);
-
-  var dataString1 = "Initial Blank Snapshot";
-  this.outputDebugInfo(dataString1, 'blank1Snap',
-                       this.blankSnapshot.toDataURL());
-};
-
-/**
- * Begin the AnimationTest. This will utilize the information provided in the
- * constructor to invoke a mochitest on animated images. It will automatically
- * fail if allowed to run past the timeout.
- */
-AnimationTest.prototype.beginTest = function ()
-{
-  SimpleTest.waitForExplicitFinish();
-
-  currentTest = this;
-
-  this.takeReferenceSnapshot();
-
-  // In case something goes wrong, fail earlier than mochitest timeout,
-  // and with more information.
-  setTimeout(failTest, this.timeout);
-
-  if (!this.reusingImageAsReference) {
-    this.disableDisplay(document.getElementById(this.imageElementId));
-  }
-
-  this.setupPolledImage();
-  setTimeout(pollForSuccess, 10);
-};
-
-AnimationTest.prototype.setupPolledImage = function ()
-{
-  // Make sure the image is visible
-  if (!this.reusingImageAsReference) {
-    this.enableDisplay(document.getElementById(this.imageElementId));
-    var currentSnapshot = snapshotWindow(window, false);
-    var result = compareSnapshots(currentSnapshot, this.referenceSnapshot, true);
-
-    var dataString = "Snapshot #" + this.onStopFrameCounter;
-    this.outputDebugInfo(dataString, 'snap' + this.onStopFrameCounter,
-                         currentSnapshot.toDataURL());
-
-    if (result[0]) {
-      // SUCCESS!
-      ok(true, "Animated image looks correct, " + "at call #"
-         + this.onStopFrameCounter + " to onStopFrame");
-
-      this.cleanUpAndFinish();
-    }
-  } else {
-    if (!gIsRefImageLoaded) {
-      this.myImage = new Image();
-      this.myImage.onload = reuseImageCallback;
-      document.getElementById(this.imageElementId).setAttribute('src',
-        this.referenceElementId);
-    }
-  }
-}
-
-AnimationTest.prototype.checkImage = function ()
-{
-  if (this.isTestFinished) {
-    return;
-  }
-
-  this.onStopFrameCounter++;
-
-  // We need this for some tests, because we need to force the
-  // test image to be visible.
-  if (!this.reusingImageAsReference) {
-    this.enableDisplay(document.getElementById(this.imageElementId));
-  }
-
-  var currentSnapshot = snapshotWindow(window, false);
-  var result = compareSnapshots(currentSnapshot, this.referenceSnapshot, true);
-
-  var dataString = "Snapshot #" + this.onStopFrameCounter;
-  this.outputDebugInfo(dataString, 'snap' + this.onStopFrameCounter,
-                         currentSnapshot.toDataURL());
-
-  if (result[0]) {
-    // SUCCESS!
-    ok(true, "Animated image looks correct, " + "at call #"
-       + this.onStopFrameCounter + " to onStopFrame");
-
-    this.cleanUpAndFinish();
-  }
-};
-
-AnimationTest.prototype.takeReferenceSnapshot = function ()
-{
-  this.numRefsTaken++;
-
-  // Test to make sure the reference image doesn't match a clean snapshot
-  if (!this.cleanSnapshot) {
-    this.takeCleanSnapshot();
-  }
-
-  // Used later to verify that the reference div disappeared
-  if (!this.blankSnapshot) {
-    this.takeBlankSnapshot();
-  }
-
-  if (this.reusingImageAsReference) {
-    // Show reference div, & take a snapshot
-    var referenceDiv = document.getElementById(this.imageElementId);
-    this.enableDisplay(referenceDiv);
-
-    this.referenceSnapshot = snapshotWindow(window, false);
-    var snapResult = compareSnapshots(this.cleanSnapshot, this.referenceSnapshot,
-                                      false);
-    if (!snapResult[0]) {
-      if (this.blankWaitTime > 2000) {
-        // if it took longer than two seconds to load the image, we probably
-        // have a problem.
-        this.wereFailures = true;
-        ok(snapResult[0],
-           "Reference snapshot shouldn't match clean (non-image) snapshot");
-      } else {
-        this.blankWaitTime += 20;
-        // let's wait a bit and see if it clears up
-        setTimeout(referencePoller, 20);
-        return;
-      }
-    }
-
-    ok(snapResult[0],
-       "Reference snapshot shouldn't match clean (non-image) snapshot");
-
-    var dataString = "Reference Snapshot #" + this.numRefsTaken;
-    this.outputDebugInfo(dataString, 'refSnapId',
-                         this.referenceSnapshot.toDataURL());
-  } else {
-    // Make sure the animation section is hidden
-    this.disableDisplay(document.getElementById(this.imageElementId));
-
-    // Show reference div, & take a snapshot
-    var referenceDiv = document.getElementById(this.referenceElementId);
-    this.enableDisplay(referenceDiv);
-
-    this.referenceSnapshot = snapshotWindow(window, false);
-    var snapResult = compareSnapshots(this.cleanSnapshot, this.referenceSnapshot, false);
-    if (!snapResult[0]) {
-      if (this.blankWaitTime > 2000) {
-        // if it took longer than two seconds to load the image, we probably
-        // have a problem.
-        this.wereFailures = true;
-        ok(snapResult[0],
-           "Reference snapshot shouldn't match clean (non-image) snapshot");
-      } else {
-        this.blankWaitTime += 20;
-        // let's wait a bit and see if it clears up
-        setTimeout(referencePoller, 20);
-        return;
-      }
-    }
-
-    ok(snapResult[0],
-       "Reference snapshot shouldn't match clean (non-image) snapshot");
-
-    var dataString = "Reference Snapshot #" + this.numRefsTaken;
-    this.outputDebugInfo(dataString, 'refSnapId',
-                         this.referenceSnapshot.toDataURL());
-
-    // Re-hide reference div, and take another snapshot to be sure it's gone
-    this.disableDisplay(referenceDiv);
-    this.testBlankCameBack();
-  }
-};
-
-AnimationTest.prototype.enableDisplay = function(element)
-{
-  if (!element) {
-    return;
-  }
-
-  if (!this.xulTest) {
-    element.style.display = '';
-  } else {
-    element.setAttribute('hidden', 'false');
-  }
-};
-
-AnimationTest.prototype.disableDisplay = function(element)
-{
-  if (!element) {
-    return;
-  }
-
-  if (!this.xulTest) {
-    element.style.display = 'none';
-  } else {
-    element.setAttribute('hidden', 'true');
-  }
-};
-
-AnimationTest.prototype.testBlankCameBack = function()
-{
-  var blankSnapshot2 = snapshotWindow(window, false);
-  var result = compareSnapshots(this.blankSnapshot, blankSnapshot2, true);
-  ok(result[0], "Reference image should disappear when it becomes display:none");
-
-  if (!result[0]) {
-    this.wereFailures = true;
-    var dataString = "Second Blank Snapshot";
-    this.outputDebugInfo(dataString, 'blank2SnapId', result[2]);
-  }
-};
-
-AnimationTest.prototype.cleanUpAndFinish = function ()
-{
-  // On the off chance that failTest and checkImage are triggered
-  // back-to-back, use a flag to prevent multiple calls to SimpleTest.finish.
-  if (this.isTestFinished) {
-    return;
-  }
-
-  this.isTestFinished = true;
-
-  // Call our closing function, if one exists
-  if (this.closeFunc) {
-    this.closeFunc();
-    return;
-  }
-
-  if (this.wereFailures) {
-    document.getElementById(this.debugElementId).style.display = 'block';
-  }
-
-  SimpleTest.finish();
-  document.getElementById(this.debugElementId).style.display = "";
-};
deleted file mode 100644
--- a/image/test/mochitest/filter-final.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-
-<filter id="filter1" x="0%" y="0%" width="100%" height="100%">
-  <feImage xlink:href="animated-gif-finalframe.gif"/>
-</filter>
-<g>
-	<rect x="0" y="0" width="100%" height="100%" filter="url(#filter1)"/>
-</g>
-</svg>
deleted file mode 100644
--- a/image/test/mochitest/filter.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-
-<filter id="filter1" x="0%" y="0%" width="100%" height="100%">
-  <feImage xlink:href="animated-gif.gif"/>
-</filter>
-<g>
-	<rect x="0" y="0" width="100%" height="100%" filter="url(#filter1)"/>
-</g>
-</svg>
deleted file mode 100644
--- a/image/test/mochitest/iframe.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="gray">
-  <img src="animated-gif.gif">
-</body>
-</html>
\ No newline at end of file
deleted file mode 100644
index 79826af205d7eceb7763d8a213d3ec28844db363..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/image/test/mochitest/ref-iframe.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<html>
-<body bgcolor="gray">
-  <div id="referenceImage"
-    style="height: 40px; width: 40px; background: #2aff00"></div>
-</body>
-</html>
deleted file mode 100644
--- a/image/test/mochitest/test_animation.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=666446
--->
-<head>
-  <title>Test for Bug 666446 - General Animated GIF Test</title>
-  <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
-  <script type="application/javascript" src="imgutils.js"></script>
-  <script type="application/javascript" src="animationPolling.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
-Mozilla Bug 666446: lots of animated gifs swamp us with paint events
-</a>
-<p id="display"></p>
-
-<div id="content">
-  <div id="referenceDiv" style="height: 40px; width: 40px;
-                                display: none; background: #2aff00"></div>
-  <div id="animatedImage">
-    <img id="animatedGif" src="animated-gif.gif" style="display: none;">
-      <div id="text-descr"></div>
-  </div>
-  <div id="debug" style="display:none">
-  </div>
-</div>
-<pre id="test">
-<script type="text/javascript;version=1.8">
-const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
-
-function main()
-{
-  var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
-                                   'animatedGif', 'debug');
-  animTest.beginTest();
-}
-
-window.onload = main;
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/image/test/mochitest/test_background_image_anim.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=666446
--->
-<head>
-  <title>Test for Bug 666446 - Animated Background Images</title>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
-  <script type="application/javascript" src="imgutils.js"></script>
-  <script type="application/javascript" src="animationPolling.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
-Mozilla Bug 666446: lots of animated gifs swamp us with paint events
-</a>
-<p id="display"></p>
-<div id="content">
-  <div id="referenceDiv" style="height: 140px; width: 140px;
-                                display: none; background: #2aff00"></div>
-  <div id="bgImage" style="height: 140px; width: 140px; background-image: url(animated-gif.gif); display: none;">
-  </div>
-</div>
-<div id="debug" style="display:none"></div>
-<pre id="test">
-<script type="text/javascript;version=1.8">
-
-/** Test for Bug 666446 nsImageLoader/RasterImage**/
-
-const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
-
-function main() {
-  var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
-                                   'bgImage', 'debug');
-  animTest.beginTest();
-}
-
-window.onload = main;
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/image/test/mochitest/test_bullet_animation.html
+++ /dev/null
@@ -1,57 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=666446
--->
-<head>
-  <title>Test for Bug 666446 - Animated Bullets</title>
-  <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
-  <script type="application/javascript" src="imgutils.js"></script>
-  <script type="application/javascript" src="animationPolling.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
-Mozilla Bug 666446: lots of animated gifs swamp us with paint events
-</a>
-<p id="display"></p>
-
-<div id="content">
-  <div id="cleanDiv" style="display: none;">
-    <ul>
-      <li>Test 1</li>
-    </ul>
-  </div>
-  <div id="referenceDiv" style="display: none;">
-    <ul>
-      <li style="list-style-image: url(animated-gif-finalframe.gif);">Test 1</li>
-    </ul>
-  </div>
-  <div id="animatedImage" style="display: none;">
-      <ul>
-        <li style="list-style-image: url(animated-gif.gif);">Test 1</li>
-      </ul>
-  </div>
-  <div id="text-descr"></div>
-  <div id="debug" style="display:none">
-  </div>
-</div>
-<pre id="test">
-<script type="text/javascript;version=1.8">
-const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
-
-function main()
-{
-  var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
-                                   'animatedImage', 'debug', 'cleanDiv',
-                                   'animated-gif-finalframe.gif');
-  animTest.beginTest();
-}
-
-window.onload = main;
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/image/test/mochitest/test_changeOfSource.html
+++ /dev/null
@@ -1,63 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=666446
--->
-<head>
-  <title>Test for Bug 666446 - Change of Source (1st Version)</title>
-  <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
-  <script type="application/javascript" src="imgutils.js"></script>
-  <script type="application/javascript" src="animationPolling.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
-Mozilla Bug 666446: lots of animated gifs swamp us with paint events
-</a>
-<p id="display"></p>
-
-<div id="content">
-  <div id="referenceDiv" style="height: 40px; width: 40px;
-                                display: none; background: #2aff00;">
-  </div>
-  <div id="animatedImage">
-    <img id='animatedGif' src="animated-gif.gif" style="display: none;">
-  </div>
-  <div id="text-descr"></div>
-  <div id="debug" style="display:none">
-  </div>
-</div>
-<pre id="test">
-<script type="text/javascript;version=1.8">
-const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
-
-var gAnimTest;
-var gIntervalId;
-
-function initSecondTest() {
-  document.getElementById('debug').style.display = 'none';
-  document.getElementById('referenceDiv').style.background = "#9600ff";
-  document.getElementById('animatedGif').setAttribute('src',
-                                                      'animated-gif2.gif');
-  document.getElementById('animatedGif').style.display = 'none';
-  var secondTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
-                                     'animatedGif', 'debug', '', '', false);
-  secondTest.beginTest();
-}
-
-function main()
-{
-  gAnimTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
-                                'animatedGif', 'debug', '', '', false,
-                                initSecondTest);
-  gAnimTest.beginTest();
-
-}
-
-window.onload = main;
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/image/test/mochitest/test_changeOfSource2.html
+++ /dev/null
@@ -1,48 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=666446
--->
-<head>
-  <title>Test for Bug 691792 - Change of Source (2nd Version)</title>
-  <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
-  <script type="application/javascript" src="imgutils.js"></script>
-  <script type="application/javascript" src="animationPolling.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=691792">
-Mozilla Bug 691792: Change of src attribute for animated gifs no longer works as expected
-</a>
-<p id="display"></p>
-
-<div id="content">
-  <div id="animatedImage">
-    <img id='animatedGif' src="purple.gif" style="display: none;">
-  </div>
-  <div id="text-descr"></div>
-  <div id="debug" style="display:none">
-  </div>
-</div>
-<pre id="test">
-<script type="text/javascript;version=1.8">
-const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
-
-var gAnimTest;
-var gIntervalId;
-
-function main()
-{
-  gAnimTest = new AnimationTest(20, FAILURE_TIMEOUT, 'animated-gif2.gif',
-                                'animatedGif', 'debug', '', 'animated-gif2.gif',
-                                false);
-  gAnimTest.beginTest();
-}
-
-window.onload = main;
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/image/test/mochitest/test_svg_animatedGIF.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=666446
--->
-<head>
-  <title>Test for Bug 666446 - Animated Raster Images inside of SVG Frames</title>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
-  <script type="application/javascript" src="imgutils.js"></script>
-  <script type="application/javascript" src="animationPolling.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
-</head>
-
-<!--  Make sure embed element is snapped to an exact pixel. -->
-<div class="bug-header" style="height: 100px;">
-  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
-  Mozilla Bug 666446: lots of animated gifs swamp us with paint events
-  </a>
-</div>
-
-<p id="display"></p>
-<div id="content">
-  <div id="referenceDiv" style="height: 40px; width: 40px;
-                                display: none; background: #2aff00"></div>
-    <!--
-        We use <embed> here instead of <img> because the <img> tag utilizes
-        the VectorImage class for SVG, whereas in this test, we are testing
-        RasterImage.
-     -->
-  <embed id="embeddedSVG" src="animation.svg" type="image/svg+xml" style="display: none;"/>
-</div>
-<div id="debug" style="display:none"></div>
-<pre id="test">
-<script type="text/javascript;version=1.8">
-
-/** Test for Bug 666446 nsSVGImageFrame/RasterImage**/
-
-const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
-
-function main() {
-  var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
-      							   'embeddedSVG', 'debug', '', 'src');
-  animTest.beginTest();
-}
-
-window.onload = main;
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/image/test/mochitest/test_svg_filter_animation.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=666446
--->
-<head>
-  <title>Test for Bug 666446 - Animated Images within SVG Filters</title>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
-  <script type="application/javascript" src="imgutils.js"></script>
-  <script type="application/javascript" src="animationPolling.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
-Mozilla Bug 666446: lots of animated gifs swamp us with paint events
-</a>
-<p id="display"></p>
-<div id="content">
-  <embed id="referenceImage" src="filter-final.svg" type="image/svg+xml" style="display: none;"/>
-  <embed id="embeddedSVGFilt" src="filter.svg" type="image/svg+xml" style="display: none;"/>
-</div>
-<div id="debug" style="display:none"></div>
-<pre id="test">
-<script type="text/javascript;version=1.8">
-
-/** Test for Bug 666446 nsSVGFEImageElement/RasterImage**/
-
-const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
-
-function main() {
-  var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceImage',
-                       'embeddedSVGFilt', 'debug', '', 'src');
-  animTest.beginTest();
-}
-
-window.onload = main;
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/image/test/mochitest/test_undisplayed_iframe.html
+++ /dev/null
@@ -1,48 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=666446
--->
-<head>
-<title>Test for Bug 666446 - Test for Animated Gif within IFRAME</title>
-<script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
-<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
-<script type="application/javascript" src="imgutils.js"></script>
-<script type="application/javascript" src="animationPolling.js"></script>
-<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
-</head>
-<body>
-  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
-    Mozilla Bug 666446: lots of animated gifs swamp us with paint events</a>
-  <p id="display"></p>
-
-  <div id="content">
-    <div id="referenceDiv" style="display:none;">
-      <iframe id="referenceIFrame" src="ref-iframe.html" width="50%" height="100">
-        Browser does not support iframes.
-      </iframe>
-    </div>
-    <div id="animatedImage">
-      <iframe id="imageIFrame" src="iframe.html" width="50%" height="100" style="display: none;">
-        Browser does not support iframes.
-      </iframe>
-    </div>
-    <div id="debug" style="display: none"></div>
-  </div>
-  <pre id="test">
-<script type="text/javascript;version=1.8">
-const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
-
-function main()
-{
-  var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
-                                   'imageIFrame', 'debug');
-  animTest.beginTest();
-}
-
-window.onload = main;
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/image/test/mochitest/test_xultree_animation.xhtml
+++ /dev/null
@@ -1,67 +0,0 @@
-<!DOCTYPE HTML>
-<html
-xmlns="http://www.w3.org/1999/xhtml"
-      xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-      xml:lang="en" lang="en">
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=666446
--->
-<head>
-  <title>Test for Bug 666446 - Animated Images within SVG Filters</title>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
-  <script type="application/javascript" src="imgutils.js"></script>
-  <script type="application/javascript" src="animationPolling.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
-Mozilla Bug 666446: lots of animated gifs swamp us with paint events
-</a>
-<p id="display"></p>
-<div id="content">
-  <xul:caption label="Bug 666446 - XULTree Test" />
-  <xul:separator />
-    <br />
-    <xul:window id="main" title="Bug 666446: XUL Tree Testing" width="100" height="100">
-      <xul:tree flex="1">
-        <xul:treecols>
-          <xul:treecol id="icon" label="Icon" flex="1" />
-        </xul:treecols>
-
-        <xul:treechildren>
-          <xul:treeitem id="referenceItem" hidden="true">
-            <xul:treerow>
-              <xul:treecell src="animated-gif-finalframe.gif" width="40" height="40" />
-            </xul:treerow>
-          </xul:treeitem>
-          <xul:treeitem id="imageItem" hidden="true">
-            <xul:treerow>
-              <xul:treecell src="animated-gif.gif" width="40" height="40" />
-            </xul:treerow>
-          </xul:treeitem>
-        </xul:treechildren>
-      </xul:tree>
-    </xul:window>
-  </div>
-<div id="debug" style="display:none"></div>
-<pre id="test">
-<script type="text/javascript;version=1.8">
-
-/** Test for Bug 666446 nsSVGFEImageElement/RasterImage**/
-
-const FAILURE_TIMEOUT = 5000; // Fail early after 120 seconds (2 minutes)
-
-function main() {
-  var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceItem',
-                                   'imageItem', 'debug', '',
-                                   'animated-gif-finalframe.gif', true);
-  animTest.beginTest();
-}
-
-window.onload = main;
-
-</script>
-</pre>
-</body>
-</html>
--- a/layout/base/nsImageLoader.cpp
+++ b/layout/base/nsImageLoader.cpp
@@ -52,35 +52,37 @@
 #include "nsIFrame.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
 
 #include "imgIContainer.h"
 
 #include "nsStyleContext.h"
 #include "nsGkAtoms.h"
-#include "nsLayoutUtils.h"
 
 // Paint forcing
 #include "prenv.h"
 
 NS_IMPL_ISUPPORTS2(nsImageLoader, imgIDecoderObserver, imgIContainerObserver)
 
 nsImageLoader::nsImageLoader(nsIFrame *aFrame, PRUint32 aActions,
                              nsImageLoader *aNextLoader)
   : mFrame(aFrame),
     mActions(aActions),
-    mNextLoader(aNextLoader),
-    mRequestRegistered(false)
+    mNextLoader(aNextLoader)
 {
 }
 
 nsImageLoader::~nsImageLoader()
 {
-  Destroy();
+  mFrame = nsnull;
+
+  if (mRequest) {
+    mRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
+  }
 }
 
 /* static */ already_AddRefed<nsImageLoader>
 nsImageLoader::Create(nsIFrame *aFrame, imgIRequest *aRequest, 
                       PRUint32 aActions, nsImageLoader *aNextLoader)
 {
   nsRefPtr<nsImageLoader> loader =
     new nsImageLoader(aFrame, aActions, aNextLoader);
@@ -98,66 +100,49 @@ nsImageLoader::Destroy()
   mNextLoader = nsnull;
   while (list) {
     nsRefPtr<nsImageLoader> todestroy = list;
     list = todestroy->mNextLoader;
     todestroy->mNextLoader = nsnull;
     todestroy->Destroy();
   }
 
-  if (mRequest && mFrame) {
-    nsPresContext* presContext = mFrame->PresContext();
+  mFrame = nsnull;
 
-    nsLayoutUtils::DeregisterImageRequest(presContext, mRequest,
-                                          &mRequestRegistered);
+  if (mRequest) {
     mRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
   }
 
-  mFrame = nsnull;
   mRequest = nsnull;
 }
 
 nsresult
 nsImageLoader::Load(imgIRequest *aImage)
 {
   NS_ASSERTION(!mRequest, "can't reuse image loaders");
   NS_ASSERTION(mFrame, "not initialized");
   NS_ASSERTION(aImage, "must have non-null image");
 
   if (!mFrame)
     return NS_ERROR_NOT_INITIALIZED;
 
   if (!aImage)
     return NS_ERROR_FAILURE;
 
-  // Deregister mRequest from the refresh driver, since it is no longer
-  // going to be managed by this nsImageLoader.
-  nsPresContext* presContext = mFrame->PresContext();
-
-  nsLayoutUtils::DeregisterImageRequest(presContext, mRequest,
-                                        &mRequestRegistered);
-
   // Make sure to clone into a temporary, then set mRequest, since
   // cloning may notify and we don't want to trigger paints from this
   // code.
   nsCOMPtr<imgIRequest> newRequest;
   nsresult rv = aImage->Clone(this, getter_AddRefs(newRequest));
   mRequest.swap(newRequest);
-
-  // Re-register mRequest with the refresh driver, but immediately deregister
-  // if it isn't animated.
-  nsLayoutUtils::RegisterImageRequest(presContext, mRequest,
-                                      &mRequestRegistered);
-
-  nsLayoutUtils::DeregisterImageRequestIfNotAnimated(presContext, mRequest,
-                                                     &mRequestRegistered);
-
   return rv;
 }
 
+                    
+
 NS_IMETHODIMP nsImageLoader::OnStartContainer(imgIRequest *aRequest,
                                               imgIContainer *aImage)
 {
   NS_ABORT_IF_FALSE(aImage, "Who's calling us then?");
 
   /* Get requested animation policy from the pres context:
    *   normal = 0
    *   one frame = 1
@@ -279,40 +264,8 @@ nsImageLoader::DoRedraw(const nsRect* aD
   }
 
 #endif
 
   if (mFrame->GetStyleVisibility()->IsVisible()) {
     mFrame->Invalidate(bounds);
   }
 }
-
-NS_IMETHODIMP
-nsImageLoader::OnStartDecode(imgIRequest *aRequest)
-{
-  // Register our image request with the refresh driver.
-  nsPresContext* presContext = mFrame->PresContext();
-  if (!presContext) {
-    return NS_OK;
-  }
-
-  if (mRequest == aRequest) {
-    nsLayoutUtils::RegisterImageRequest(presContext, mRequest,
-                                        &mRequestRegistered);
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsImageLoader::OnStopDecode(imgIRequest *aRequest, nsresult status,
-                            const PRUnichar *statusArg)
-{
-  if (mRequest == aRequest) {
-    // Deregister the imgIRequest with the refresh driver if the
-    // image is not animated.
-    nsLayoutUtils::DeregisterImageRequestIfNotAnimated(mFrame->PresContext(),
-                                                       mRequest,
-                                                       &mRequestRegistered);
-  }
-
-  return NS_OK;
-}
--- a/layout/base/nsImageLoader.h
+++ b/layout/base/nsImageLoader.h
@@ -77,20 +77,16 @@ public:
   static already_AddRefed<nsImageLoader>
     Create(nsIFrame *aFrame, imgIRequest *aRequest,
            PRUint32 aActions, nsImageLoader *aNextLoader);
 
   NS_DECL_ISUPPORTS
 
   // imgIDecoderObserver (override nsStubImageDecoderObserver)
   NS_IMETHOD OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage);
-  NS_IMETHOD OnStartDecode(imgIRequest *aRequest);
-  NS_IMETHOD OnStopDecode(imgIRequest *aRequest,
-                          nsresult status,
-                          const PRUnichar *statusArg);
   NS_IMETHOD OnStopFrame(imgIRequest *aRequest, PRUint32 aFrame);
   NS_IMETHOD OnStopRequest(imgIRequest *aRequest, bool aLastPart);
   // Do not override OnDataAvailable since background images are not
   // displayed incrementally; they are displayed after the entire image
   // has been loaded.
   // Note: Images referenced by the <img> element are displayed
   // incrementally in nsImageFrame.cpp.
 
@@ -108,13 +104,9 @@ private:
   void DoReflow();
   /* if aDamageRect is nsnull, the whole frame is redrawn. */
   void DoRedraw(const nsRect* aDamageRect);
 
   nsIFrame *mFrame;
   nsCOMPtr<imgIRequest> mRequest;
   PRUint32 mActions;
   nsRefPtr<nsImageLoader> mNextLoader;
-
-  // This is a boolean flag indicating whether or not the current image request
-  // has been registered with the refresh driver.
-  bool mRequestRegistered;
 };
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -4322,112 +4322,16 @@ void
 nsLayoutUtils::Shutdown()
 {
   if (sContentMap) {
     delete sContentMap;
     sContentMap = NULL;
   }
 }
 
-/* static */
-void
-nsLayoutUtils::RegisterImageRequest(nsPresContext* aPresContext,
-                                    imgIRequest* aRequest,
-                                    bool* aRequestRegistered)
-{
-  if (!aPresContext) {
-    return;
-  }
-
-  if (aRequestRegistered && *aRequestRegistered) {
-    // Our request is already registered with the refresh driver, so
-    // no need to register it again.
-    return;
-  }
-
-  if (aRequest) {
-    nsCOMPtr<imgIContainer> image;
-    aRequest->GetImage(getter_AddRefs(image));
-    if (image) {
-      if (!aPresContext->RefreshDriver()->AddImageRequest(aRequest)) {
-        NS_WARNING("Unable to add image request");
-        return;
-      }
-
-      if (aRequestRegistered) {
-        *aRequestRegistered = true;
-      }
-    }
-  }
-}
-
-/* static */
-void
-nsLayoutUtils::DeregisterImageRequest(nsPresContext* aPresContext,
-                                      imgIRequest* aRequest,
-                                      bool* aRequestRegistered)
-{
-  if (!aPresContext) {
-    return;
-  }
-
-  // Deregister our imgIRequest with the refresh driver to
-  // complete tear-down, but only if it has been registered
-  if (aRequestRegistered && !*aRequestRegistered) {
-    return;
-  }
-
-  if (aRequest) {
-    nsCOMPtr<imgIContainer> image;
-    aRequest->GetImage(getter_AddRefs(image));
-    if (image) {
-      aPresContext->RefreshDriver()->RemoveImageRequest(aRequest);
-
-      if (aRequestRegistered) {
-        *aRequestRegistered = false;
-      }
-    }
-  }
-}
-
-/* static */
-void
-nsLayoutUtils::DeregisterImageRequestIfNotAnimated(nsPresContext* aPresContext,
-                                                   imgIRequest* aRequest,
-                                                   bool* aRequestRegistered)
-{
-  if (!aPresContext) {
-    return;
-  }
-
-  if (aRequestRegistered && !*aRequestRegistered) {
-    // Image request isn't registered with the refresh driver - no need
-    // to try and deregister it.
-    return;
-  }
-
-  // Deregister the imgIRequest with the refresh driver if the
-  // image is not animated
-  nsCOMPtr<imgIContainer> imageContainer;
-  if (aRequest) {
-    aRequest->GetImage(getter_AddRefs(imageContainer));
-    bool animated;
-
-    if (!imageContainer) {
-      return;
-    }
-
-    nsresult rv = imageContainer->GetAnimated(&animated);
-    if (NS_SUCCEEDED(rv) && !animated) {
-      nsLayoutUtils::DeregisterImageRequest(aPresContext, aRequest,
-                                            aRequestRegistered);
-    }
-  }
-}
-
 nsSetAttrRunnable::nsSetAttrRunnable(nsIContent* aContent, nsIAtom* aAttrName,
                                      const nsAString& aValue)
   : mContent(aContent),
     mAttrName(aAttrName),
     mValue(aValue)
 {
   NS_ASSERTION(aContent && aAttrName, "Missing stuff, prepare to crash");
 }
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -1449,73 +1449,16 @@ public:
 
   /**
    * Checks if CSS 3D transforms are currently enabled.
    */
   static bool Are3DTransformsEnabled();
 
   static void Shutdown();
 
-  /**
-   * Register an imgIRequest object with a refresh driver.
-   *
-   * @param aPresContext The nsPresContext whose refresh driver we want to
-   *        register with.
-   * @param aRequest A pointer to the imgIRequest object which the client wants
-   *        to register with the refresh driver.
-   * @param aRequestRegistered A pointer to a boolean value which indicates
-   *        whether the given image request is registered. If
-   *        *aRequestRegistered is true, then this request will not be
-   *        registered again. If the request is registered by this function,
-   *        then *aRequestRegistered will be set to true upon the completion of
-   *        this function.
-   *
-   */
-  static void RegisterImageRequest(nsPresContext* aPresContext,
-                                   imgIRequest* aRequest,
-                                   bool* aRequestRegistered);
-  /**
-   * Deregister an imgIRequest object from a refresh driver.
-   *
-   * @param aPresContext The nsPresContext whose refresh driver we want to
-   *        deregister from.
-   * @param aRequest A pointer to the imgIRequest object with which the client
-   *        previously registered and now wants to deregister from the refresh
-   *        driver.
-   * @param aRequestRegistered A pointer to a boolean value which indicates
-   *        whether the given image request is registered. If
-   *        *aRequestRegistered is false, then this request will not be
-   *        deregistered. If the request is deregistered by this function,
-   *        then *aRequestRegistered will be set to false upon the completion of
-   *        this function.
-   */
-  static void DeregisterImageRequest(nsPresContext* aPresContext,
-                                     imgIRequest* aRequest,
-                                     bool* aRequestRegistered);
-  /**
-   * Deregister an imgIRequest object from a refresh driver, if the
-   * imgIRequest object represents a static (i.e. not animated) image.
-   *
-   * @param aPresContext The nsPresContext whose refresh driver we want to
-   *        deregister from.
-   * @param aRequest A pointer to the imgIRequest object with which the client
-   *        previously registered and now wants to deregister from the refresh
-   *        driver.
-   * @param aRequestRegistered A pointer to a boolean value which indicates
-   *        whether the given image request is registered. If
-   *        *aRequestRegistered is false, then this request will not be
-   *        deregistered. If the request is deregistered by this function,
-   *        then *aRequestRegistered will be set to false upon the completion of
-   *        this function.
-   */
-
-  static void DeregisterImageRequestIfNotAnimated(nsPresContext* aPresContext,
-                                                  imgIRequest* aRequest,
-                                                  bool* aRequestRegistered);
-
 #ifdef DEBUG
   /**
    * Assert that there are no duplicate continuations of the same frame
    * within aFrameList.  Optimize the tests by assuming that all frames
    * in aFrameList have parent aContainer.
    */
   static void
   AssertNoDuplicateContinuations(nsIFrame* aContainer,
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -109,17 +109,16 @@ nsRefreshDriver::GetRefreshTimerType() c
 nsRefreshDriver::nsRefreshDriver(nsPresContext *aPresContext)
   : mPresContext(aPresContext),
     mFrozen(false),
     mThrottled(false),
     mTestControllingRefreshes(false),
     mTimerIsPrecise(false),
     mLastTimerInterval(0)
 {
-  mRequests.Init();
 }
 
 nsRefreshDriver::~nsRefreshDriver()
 {
   NS_ABORT_IF_FALSE(ObserverCount() == 0,
                     "observers should have unregistered");
   NS_ABORT_IF_FALSE(!mTimer, "timer should be gone");
 }
@@ -181,39 +180,16 @@ nsRefreshDriver::AddRefreshObserver(nsAR
 bool
 nsRefreshDriver::RemoveRefreshObserver(nsARefreshObserver *aObserver,
                                        mozFlushType aFlushType)
 {
   ObserverArray& array = ArrayFor(aFlushType);
   return array.RemoveElement(aObserver);
 }
 
-bool
-nsRefreshDriver::AddImageRequest(imgIRequest* aRequest)
-{
-  if (!mRequests.PutEntry(aRequest)) {
-    return false;
-  }
-
-  EnsureTimerStarted(false);
-
-  return true;
-}
-
-void
-nsRefreshDriver::RemoveImageRequest(imgIRequest* aRequest)
-{
-  mRequests.RemoveEntry(aRequest);
-}
-
-void nsRefreshDriver::ClearAllImageRequests()
-{
-  mRequests.Clear();
-}
-
 void
 nsRefreshDriver::EnsureTimerStarted(bool aAdjustingTimer)
 {
   if (mTimer || mFrozen || !mPresContext) {
     // It's already been started, or we don't want to start it now or
     // we've been disconnected.
     return;
   }
@@ -257,34 +233,27 @@ nsRefreshDriver::StopTimer()
 
 PRUint32
 nsRefreshDriver::ObserverCount() const
 {
   PRUint32 sum = 0;
   for (PRUint32 i = 0; i < ArrayLength(mObservers); ++i) {
     sum += mObservers[i].Length();
   }
-
   // Even while throttled, we need to process layout and style changes.  Style
   // changes can trigger transitions which fire events when they complete, and
   // layout changes can affect media queries on child documents, triggering
   // style changes, etc.
   sum += mStyleFlushObservers.Length();
   sum += mLayoutFlushObservers.Length();
   sum += mBeforePaintTargets.Length();
   sum += mAnimationFrameListenerDocs.Length();
   return sum;
 }
 
-PRUint32
-nsRefreshDriver::ImageRequestCount() const
-{
-  return mRequests.Count();
-}
-
 void
 nsRefreshDriver::UpdateMostRecentRefresh()
 {
   if (mTestControllingRefreshes) {
     return;
   }
 
   // Call JS_Now first, since that can have nonzero latency in some rare cases.
@@ -329,17 +298,17 @@ nsRefreshDriver::Notify(nsITimer *aTimer
   if (mTestControllingRefreshes && aTimer) {
     // Ignore real refreshes from our timer (but honor the others).
     return NS_OK;
   }
 
   UpdateMostRecentRefresh();
 
   nsCOMPtr<nsIPresShell> presShell = mPresContext->GetPresShell();
-  if (!presShell || (ObserverCount() == 0 && ImageRequestCount() == 0)) {
+  if (!presShell || ObserverCount() == 0) {
     // Things are being destroyed, or we no longer have any observers.
     // We don't want to stop the timer when observers are initially
     // removed, because sometimes observers can be added and removed
     // often depending on what other things are going on and in that
     // situation we don't want to thrash our timer.  So instead we
     // wait until we get a Notify() call when we have no observers
     // before stopping the timer.
     StopTimer();
@@ -358,17 +327,16 @@ nsRefreshDriver::Notify(nsITimer *aTimer
       nsRefPtr<nsARefreshObserver> obs = etor.GetNext();
       obs->WillRefresh(mMostRecentRefresh);
       
       if (!mPresContext || !mPresContext->GetPresShell()) {
         StopTimer();
         return NS_OK;
       }
     }
-
     if (i == 0) {
       // Don't just loop while we have things in mBeforePaintTargets,
       // the whole point is that event handlers should readd the
       // target as needed.
       nsTArray< nsCOMPtr<nsIDocument> > targets;
       targets.SwapElements(mBeforePaintTargets);
       for (PRUint32 i = 0; i < targets.Length(); ++i) {
         targets[i]->BeforePaintEventFiring();
@@ -431,27 +399,16 @@ nsRefreshDriver::Notify(nsITimer *aTimer
           shell->mSuppressInterruptibleReflows = false;
           shell->FlushPendingNotifications(Flush_InterruptibleLayout);
           NS_RELEASE(shell);
         }
       }
     }
   }
 
-  /*
-   * Perform notification to imgIRequests subscribed to listen
-   * for refresh events.
-   */
-
-  ImageRequestParameters parms = {mMostRecentRefresh};
-  if (mRequests.Count()) {
-    mRequests.EnumerateEntries(nsRefreshDriver::ImageRequestEnumerator, &parms);
-    EnsureTimerStarted(false);
-  }
-
   if (mThrottled ||
       (mTimerIsPrecise !=
        (GetRefreshTimerType() == nsITimer::TYPE_REPEATING_PRECISE_CAN_SKIP))) {
     // Stop the timer now and restart it here.  Stopping is in the mThrottled
     // case ok because either it's already one-shot, and it just fired, and all
     // we need to do is null it out, or it's repeating and we need to reset it
     // to be one-shot.  Stopping and restarting in the case when we need to
     // switch from precise to slack timers or vice versa is unfortunately
@@ -462,48 +419,30 @@ nsRefreshDriver::Notify(nsITimer *aTimer
     // started.
     StopTimer();
     EnsureTimerStarted(true);
   }
 
   return NS_OK;
 }
 
-PLDHashOperator
-nsRefreshDriver::ImageRequestEnumerator(nsISupportsHashKey* aEntry,
-                                        void* aUserArg)
-{
-  ImageRequestParameters* parms =
-    static_cast<ImageRequestParameters*> (aUserArg);
-  mozilla::TimeStamp mostRecentRefresh = parms->ts;
-  imgIRequest* req = static_cast<imgIRequest*>(aEntry->GetKey());
-  NS_ABORT_IF_FALSE(req, "Unable to retrieve the image request");
-  nsCOMPtr<imgIContainer> image;
-  req->GetImage(getter_AddRefs(image));
-  if (image) {
-    image->RequestRefresh(mostRecentRefresh);
-  }
-
-  return PL_DHASH_NEXT;
-}
-
 void
 nsRefreshDriver::Freeze()
 {
   NS_ASSERTION(!mFrozen, "Freeze called on already-frozen refresh driver");
   StopTimer();
   mFrozen = true;
 }
 
 void
 nsRefreshDriver::Thaw()
 {
   NS_ASSERTION(mFrozen, "Thaw called on an unfrozen refresh driver");
   mFrozen = false;
-  if (ObserverCount() || ImageRequestCount()) {
+  if (ObserverCount()) {
     // FIXME: This isn't quite right, since our EnsureTimerStarted call
     // updates our mMostRecentRefresh, but the DoRefresh call won't run
     // and notify our observers until we get back to the event loop.
     // Thus MostRecentRefresh() will lie between now and the DoRefresh.
     NS_DispatchToCurrentThread(NS_NewRunnableMethod(this, &nsRefreshDriver::DoRefresh));
     EnsureTimerStarted(false);
   }
 }
--- a/layout/base/nsRefreshDriver.h
+++ b/layout/base/nsRefreshDriver.h
@@ -45,23 +45,20 @@
 
 #include "mozilla/TimeStamp.h"
 #include "mozFlushType.h"
 #include "nsITimer.h"
 #include "nsCOMPtr.h"
 #include "nsTObserverArray.h"
 #include "nsTArray.h"
 #include "nsAutoPtr.h"
-#include "nsTHashtable.h"
-#include "nsHashKeys.h"
 
 class nsPresContext;
 class nsIPresShell;
 class nsIDocument;
-class imgIRequest;
 
 /**
  * An abstract base class to be implemented by callers wanting to be
  * notified at refresh times.  When nothing needs to be painted, callers
  * may not be notified.
  */
 class nsARefreshObserver {
 public:
@@ -127,34 +124,16 @@ public:
    * they must remove themselves before they are destroyed.
    */
   bool AddRefreshObserver(nsARefreshObserver *aObserver,
                             mozFlushType aFlushType);
   bool RemoveRefreshObserver(nsARefreshObserver *aObserver,
                                mozFlushType aFlushType);
 
   /**
-   * Add/Remove imgIRequest versions of observers.
-   *
-   * These are used for hooking into the refresh driver for
-   * controlling animated images.
-   *
-   * @note The refresh driver owns a reference to these listeners.
-   *
-   * @note Technically, imgIRequest objects are not nsARefreshObservers, but
-   * for controlling animated image repaint events, we subscribe the
-   * imgIRequests to the nsRefreshDriver for notification of paint events.
-   *
-   * @returns whether the operation succeeded, or void in the case of removal.
-   */
-  bool AddImageRequest(imgIRequest* aRequest);
-  void RemoveImageRequest(imgIRequest* aRequest);
-  void ClearAllImageRequests();
-
-  /**
    * Add / remove presshells that we should flush style and layout on
    */
   bool AddStyleFlushObserver(nsIPresShell* aShell) {
     NS_ASSERTION(!mStyleFlushObservers.Contains(aShell),
 		 "Double-adding style flush observer");
     bool appended = mStyleFlushObservers.AppendElement(aShell) != nsnull;
     EnsureTimerStarted(false);
     return appended;
@@ -234,25 +213,20 @@ public:
    * Check whether the given observer is an observer for the given flush type
    */
   bool IsRefreshObserver(nsARefreshObserver *aObserver,
 			   mozFlushType aFlushType);
 #endif
 
 private:
   typedef nsTObserverArray<nsARefreshObserver*> ObserverArray;
-  typedef nsTHashtable<nsISupportsHashKey> RequestTable;
 
   void EnsureTimerStarted(bool aAdjustingTimer);
   void StopTimer();
-
   PRUint32 ObserverCount() const;
-  PRUint32 ImageRequestCount() const;
-  static PLDHashOperator ImageRequestEnumerator(nsISupportsHashKey* aEntry,
-                                          void* aUserArg);
   void UpdateMostRecentRefresh();
   ObserverArray& ArrayFor(mozFlushType aFlushType);
   // Trigger a refresh immediately, if haven't been disconnected or frozen.
   void DoRefresh();
 
   PRInt32 GetRefreshTimerInterval() const;
   PRInt32 GetRefreshTimerType() const;
 
@@ -273,28 +247,21 @@ private:
   bool mTestControllingRefreshes;
   /* If mTimer is non-null, this boolean indicates whether the timer is
      a precise timer.  If mTimer is null, this boolean's value can be
      anything.  */
   bool mTimerIsPrecise;
 
   // separate arrays for each flush type we support
   ObserverArray mObservers[3];
-  RequestTable mRequests;
-
   nsAutoTArray<nsIPresShell*, 16> mStyleFlushObservers;
   nsAutoTArray<nsIPresShell*, 16> mLayoutFlushObservers;
   // nsTArray on purpose, because we want to be able to swap.
   nsTArray< nsCOMPtr<nsIDocument> > mBeforePaintTargets;
   // nsTArray on purpose, because we want to be able to swap.
   nsTArray<nsIDocument*> mAnimationFrameListenerDocs;
 
   // This is the last interval we used for our timer.  May be 0 if we
   // haven't computed a timer interval yet.
   mutable PRInt32 mLastTimerInterval;
-
-  // Helper struct for processing image requests
-  struct ImageRequestParameters {
-      mozilla::TimeStamp ts;
-  };
 };
 
 #endif /* !defined(nsRefreshDriver_h_) */
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -73,17 +73,16 @@ public:
   nsBulletListener();
   virtual ~nsBulletListener();
 
   NS_DECL_ISUPPORTS
   // imgIDecoderObserver (override nsStubImageDecoderObserver)
   NS_IMETHOD OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage);
   NS_IMETHOD OnDataAvailable(imgIRequest *aRequest, bool aCurrentFrame,
                              const nsIntRect *aRect);
-  NS_IMETHOD OnStartDecode(imgIRequest *aRequest);
   NS_IMETHOD OnStopDecode(imgIRequest *aRequest, nsresult status,
                           const PRUnichar *statusArg);
   // imgIContainerObserver (override nsStubImageDecoderObserver)
   NS_IMETHOD FrameChanged(imgIContainer *aContainer,
                           const nsIntRect *dirtyRect);
 
   void SetFrame(nsBulletFrame *frame) { mFrame = frame; }
 
@@ -97,20 +96,16 @@ nsBulletFrame::~nsBulletFrame()
 {
 }
 
 void
 nsBulletFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // Stop image loading first
   if (mImageRequest) {
-    // Deregister our image request from the refresh driver
-    nsLayoutUtils::DeregisterImageRequest(PresContext(),
-                                          mImageRequest,
-                                          &mRequestRegistered);
     mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
     mImageRequest = nsnull;
   }
 
   if (mListener)
     reinterpret_cast<nsBulletListener*>(mListener.get())->SetFrame(nsnull);
 
   // Let base class do the rest
@@ -170,35 +165,28 @@ nsBulletFrame::DidSetStyleContext(nsStyl
       nsCOMPtr<nsIURI> newURI;
       newRequest->GetURI(getter_AddRefs(newURI));
       if (oldURI && newURI) {
         bool same;
         newURI->Equals(oldURI, &same);
         if (same) {
           needNewRequest = false;
         } else {
-          nsLayoutUtils::DeregisterImageRequest(PresContext(), mImageRequest,
-                                                &mRequestRegistered);
           mImageRequest->Cancel(NS_ERROR_FAILURE);
           mImageRequest = nsnull;
         }
       }
     }
 
     if (needNewRequest) {
       newRequest->Clone(mListener, getter_AddRefs(mImageRequest));
-      nsLayoutUtils::RegisterImageRequest(PresContext(), mImageRequest,
-                                          &mRequestRegistered);
     }
   } else {
     // No image request on the new style context
     if (mImageRequest) {
-      nsLayoutUtils::DeregisterImageRequest(PresContext(), mImageRequest,
-                                            &mRequestRegistered);
-
       mImageRequest->Cancel(NS_ERROR_FAILURE);
       mImageRequest = nsnull;
     }
   }
 
 #ifdef ACCESSIBILITY
   // Update the list bullet accessible. If old style list isn't available then
   // no need to update the accessible tree because it's not created yet.
@@ -1528,51 +1516,32 @@ NS_IMETHODIMP nsBulletFrame::OnDataAvail
   // The image has changed.
   // Invalidate the entire content area. Maybe it's not optimal but it's simple and
   // always correct, and I'll be a stunned mullet if it ever matters for performance
   Invalidate(nsRect(0, 0, mRect.width, mRect.height));
 
   return NS_OK;
 }
 
-NS_IMETHODIMP nsBulletFrame::OnStartDecode(imgIRequest* aRequest)
-{
-  // Register the image request with the refresh driver.
-  if (aRequest == mImageRequest) {
-    nsLayoutUtils::RegisterImageRequest(PresContext(), mImageRequest,
-                                        &mRequestRegistered);
-  }
-
-  return NS_OK;
-}
-
 NS_IMETHODIMP nsBulletFrame::OnStopDecode(imgIRequest *aRequest,
                                           nsresult aStatus,
                                           const PRUnichar *aStatusArg)
 {
   // XXX should the bulletframe do anything if the image failed to load?
   //     it didn't in the old code...
 
 #if 0
   if (NS_FAILED(aStatus)) {
     // We failed to load the image. Notify the pres shell
     if (NS_FAILED(aStatus) && (mImageRequest == aRequest || !mImageRequest)) {
       imageFailed = true;
     }
   }
 #endif
 
-    // Deregister the imgIRequest with the refresh driver if the
-    // image is not animated.
-    if (aRequest == mImageRequest) {
-      nsLayoutUtils::DeregisterImageRequestIfNotAnimated(PresContext(),
-                                                         mImageRequest,
-                                                         &mRequestRegistered);
-    }
-
   return NS_OK;
 }
 
 NS_IMETHODIMP nsBulletFrame::FrameChanged(imgIContainer *aContainer,
                                           const nsIntRect *aDirtyRect)
 {
   // Invalidate the entire content area. Maybe it's not optimal but it's simple and
   // always correct.
@@ -1660,39 +1629,31 @@ NS_IMETHODIMP nsBulletListener::OnStartC
   return mFrame->OnStartContainer(aRequest, aImage);
 }
 
 NS_IMETHODIMP nsBulletListener::OnDataAvailable(imgIRequest *aRequest,
                                                 bool aCurrentFrame,
                                                 const nsIntRect *aRect)
 {
   if (!mFrame)
-    return NS_OK;
+    return NS_ERROR_FAILURE;
 
   return mFrame->OnDataAvailable(aRequest, aCurrentFrame, aRect);
 }
 
-NS_IMETHODIMP nsBulletListener::OnStartDecode(imgIRequest *aRequest)
-{
-  if (!mFrame)
-      return NS_OK;
-
-  return mFrame->OnStartDecode(aRequest);
-}
-
 NS_IMETHODIMP nsBulletListener::OnStopDecode(imgIRequest *aRequest,
                                              nsresult status,
                                              const PRUnichar *statusArg)
 {
   if (!mFrame)
-    return NS_OK;
+    return NS_ERROR_FAILURE;
   
   return mFrame->OnStopDecode(aRequest, status, statusArg);
 }
 
 NS_IMETHODIMP nsBulletListener::FrameChanged(imgIContainer *aContainer,
                                              const nsIntRect *aDirtyRect)
 {
   if (!mFrame)
-    return NS_OK;
+    return NS_ERROR_FAILURE;
 
   return mFrame->FrameChanged(aContainer, aDirtyRect);
 }
--- a/layout/generic/nsBulletFrame.h
+++ b/layout/generic/nsBulletFrame.h
@@ -79,17 +79,16 @@ public:
   // nsBulletFrame
   PRInt32 SetListItemOrdinal(PRInt32 aNextOrdinal, bool* aChanged);
 
 
   NS_IMETHOD OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage);
   NS_IMETHOD OnDataAvailable(imgIRequest *aRequest,
                              bool aCurrentFrame,
                              const nsIntRect *aRect);
-  NS_IMETHOD OnStartDecode(imgIRequest *aRequest);
   NS_IMETHOD OnStopDecode(imgIRequest *aRequest,
                           nsresult aStatus,
                           const PRUnichar *aStatusArg);
   NS_IMETHOD FrameChanged(imgIContainer *aContainer,
                           const nsIntRect *aDirtyRect);
 
   /* get list item text, without '.' */
   static bool AppendCounterText(PRInt32 aListStyleType,
@@ -117,17 +116,11 @@ protected:
   nsMargin mPadding;
   nsCOMPtr<imgIRequest> mImageRequest;
   nsCOMPtr<imgIDecoderObserver> mListener;
 
   nsSize mIntrinsicSize;
   nsSize mComputedSize;
   PRInt32 mOrdinal;
   bool mTextIsRTL;
-
-private:
-
-  // This is a boolean flag indicating whether or not the current image request
-  // has been registered with the refresh driver.
-  bool mRequestRegistered;
 };
 
 #endif /* nsBulletFrame_h___ */
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -574,20 +574,16 @@ public:
    * removal and destruction.
    */
   void Destroy() { DestroyFrom(this); }
 
 protected:
   /**
    * Implements Destroy(). Do not call this directly except from within a
    * DestroyFrom() implementation.
-   *
-   * @note This will always be called, so it is not necessary to override
-   *       Destroy() in subclasses of nsFrame, just DestroyFrom().
-   *
    * @param  aDestructRoot is the root of the subtree being destroyed
    */
   virtual void DestroyFrom(nsIFrame* aDestructRoot) = 0;
   friend class nsFrameList; // needed to pass aDestructRoot through to children
   friend class nsLineBox;   // needed to pass aDestructRoot through to children
 public:
 
   /**
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -226,20 +226,16 @@ nsImageFrame::DestroyFrom(nsIFrame* aDes
     nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
     if (imageLoader) {
       // Push a null JSContext on the stack so that code that runs
       // within the below code doesn't think it's being called by
       // JS. See bug 604262.
       nsCxPusher pusher;
       pusher.PushNull();
 
-      // Notify our image loading content that we are going away so it can
-      // deregister with our refresh driver.
-      imageLoader->FrameDestroyed(this);
-
       imageLoader->RemoveObserver(mListener);
     }
     
     reinterpret_cast<nsImageListener*>(mListener.get())->SetFrame(nsnull);
   }
   
   mListener = nsnull;
 
@@ -275,20 +271,16 @@ nsImageFrame::Init(nsIContent*      aCon
     imageLoader->AddObserver(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));
   nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(currentRequest);
   if (p)
     p->AdjustPriority(-1);
 
--- a/layout/svg/base/src/nsSVGImageFrame.cpp
+++ b/layout/svg/base/src/nsSVGImageFrame.cpp
@@ -98,17 +98,16 @@ public:
 
   // nsIFrame interface:
   NS_IMETHOD  AttributeChanged(PRInt32         aNameSpaceID,
                                nsIAtom*        aAttribute,
                                PRInt32         aModType);
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
-  virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   /**
    * Get the "type" of the frame
    *
    * @see nsGkAtoms::svgImageFrame
    */
   virtual nsIAtom* GetType() const;
 
@@ -175,44 +174,27 @@ nsSVGImageFrame::Init(nsIContent* aConte
   nsresult rv = nsSVGImageFrameBase::Init(aContent, aParent, aPrevInFlow);
   if (NS_FAILED(rv)) return rv;
   
   mListener = new nsSVGImageListener(this);
   if (!mListener) return NS_ERROR_OUT_OF_MEMORY;
   nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
   NS_ENSURE_TRUE(imageLoader, NS_ERROR_UNEXPECTED);
 
-  // We should have a PresContext now, so let's notify our image loader that
-  // we need to register any image animations with the refresh driver.
-  imageLoader->FrameCreated(this);
-
   // Push a null JSContext on the stack so that code that runs within
   // the below code doesn't think it's being called by JS. See bug
   // 604262.
   nsCxPusher pusher;
   pusher.PushNull();
 
   imageLoader->AddObserver(mListener);
 
   return NS_OK; 
 }
 
-/* virtual */ void
-nsSVGImageFrame::DestroyFrom(nsIFrame* aDestructRoot)
-{
-  nsCOMPtr<nsIImageLoadingContent> imageLoader =
-    do_QueryInterface(nsFrame::mContent);
-
-  if (imageLoader) {
-    imageLoader->FrameDestroyed(this);
-  }
-
-  nsFrame::DestroyFrom(aDestructRoot);
-}
-
 //----------------------------------------------------------------------
 // nsIFrame methods:
 
 NS_IMETHODIMP
 nsSVGImageFrame::AttributeChanged(PRInt32         aNameSpaceID,
                                   nsIAtom*        aAttribute,
                                   PRInt32         aModType)
 {
--- a/layout/svg/base/src/nsSVGLeafFrame.cpp
+++ b/layout/svg/base/src/nsSVGLeafFrame.cpp
@@ -31,34 +31,27 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsFrame.h"
 #include "nsSVGEffects.h"
-#include "nsImageLoadingContent.h"
 
 class nsSVGLeafFrame : public nsFrame
 {
   friend nsIFrame*
   NS_NewSVGLeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 protected:
   nsSVGLeafFrame(nsStyleContext* aContext) : nsFrame(aContext) {}
 
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
-  NS_IMETHOD Init(nsIContent*      aContent,
-                  nsIFrame*        aParent,
-                  nsIFrame*        asPrevInFlow);
-
-  virtual void DestroyFrom(nsIFrame* aDestructRoot);
-
   virtual bool IsFrameOfType(PRUint32 aFlags) const
   {
     return nsFrame::IsFrameOfType(aFlags & ~(nsIFrame::eSVG));
   }
 
 #ifdef DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const
   {
@@ -72,41 +65,14 @@ public:
 nsIFrame*
 NS_NewSVGLeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsSVGLeafFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsSVGLeafFrame)
 
-NS_IMETHODIMP
-nsSVGLeafFrame::Init(nsIContent* aContent, nsIFrame* aParent, nsIFrame* asPrevInFlow)
-{
-  nsFrame::Init(aContent, aParent, asPrevInFlow);
-  nsCOMPtr<nsIImageLoadingContent> imageLoader =
-    do_QueryInterface(nsFrame::mContent);
-
-  if (imageLoader) {
-    imageLoader->FrameCreated(this);
-  }
-
-  return NS_OK;
-}
-
-/* virtual */ void
-nsSVGLeafFrame::DestroyFrom(nsIFrame* aDestructRoot)
-{
-  nsCOMPtr<nsIImageLoadingContent> imageLoader =
-    do_QueryInterface(nsFrame::mContent);
-
-  if (imageLoader) {
-    imageLoader->FrameDestroyed(this);
-  }
-
-  nsFrame::DestroyFrom(aDestructRoot);
-}
-
 /* virtual */ void
 nsSVGLeafFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
   nsFrame::DidSetStyleContext(aOldStyleContext);
   nsSVGEffects::InvalidateRenderingObservers(this);
 }
--- a/layout/xul/base/src/nsImageBoxFrame.cpp
+++ b/layout/xul/base/src/nsImageBoxFrame.cpp
@@ -67,17 +67,16 @@
 #include "nsIDOMHTMLImageElement.h"
 #include "nsINameSpaceManager.h"
 #include "nsTextFragment.h"
 #include "nsIDOMHTMLMapElement.h"
 #include "nsBoxLayoutState.h"
 #include "nsIDOMDocument.h"
 #include "nsTransform2D.h"
 #include "nsITheme.h"
-#include "nsIImageLoadingContent.h"
 
 #include "nsIServiceManager.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsThreadUtils.h"
 #include "nsGUIEvent.h"
 #include "nsEventDispatcher.h"
 #include "nsDisplayList.h"
@@ -169,17 +168,16 @@ nsImageBoxFrame::AttributeChanged(PRInt3
     UpdateLoadFlags();
 
   return rv;
 }
 
 nsImageBoxFrame::nsImageBoxFrame(nsIPresShell* aShell, nsStyleContext* aContext):
   nsLeafBoxFrame(aShell, aContext),
   mIntrinsicSize(0,0),
-  mRequestRegistered(false),
   mLoadFlags(nsIRequest::LOAD_NORMAL),
   mUseSrcAttr(false),
   mSuppressStyleCheck(false)
 {
   MarkIntrinsicWidthsDirty();
 }
 
 nsImageBoxFrame::~nsImageBoxFrame()
@@ -192,26 +190,19 @@ nsImageBoxFrame::MarkIntrinsicWidthsDirt
 {
   SizeNeedsRecalc(mImageSize);
   nsLeafBoxFrame::MarkIntrinsicWidthsDirty();
 }
 
 void
 nsImageBoxFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
-  if (mImageRequest) {
-    nsPresContext* presContext = PresContext();
-    NS_ASSERTION(presContext, "No PresContext");
-    nsLayoutUtils::DeregisterImageRequest(presContext,
-                                          mImageRequest,
-                                          &mRequestRegistered);
-
-    // Release image loader first so that it's refcnt can go to zero
+  // Release image loader first so that it's refcnt can go to zero
+  if (mImageRequest)
     mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
-  }
 
   if (mListener)
     reinterpret_cast<nsImageBoxListener*>(mListener.get())->SetFrame(nsnull); // set the frame to null so we don't send messages to a dead object.
 
   nsLeafBoxFrame::DestroyFrom(aDestructRoot);
 }
 
 
@@ -236,22 +227,17 @@ nsImageBoxFrame::Init(nsIContent*      a
   UpdateImage();
 
   return rv;
 }
 
 void
 nsImageBoxFrame::UpdateImage()
 {
-  nsPresContext* presContext = PresContext();
-  NS_ASSERTION(presContext, "No PresContext");
-
   if (mImageRequest) {
-    nsLayoutUtils::DeregisterImageRequest(presContext, mImageRequest,
-                                          &mRequestRegistered);
     mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
     mImageRequest = nsnull;
   }
 
   // get the new image src
   nsAutoString src;
   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src);
   mUseSrcAttr = !src.IsEmpty();
@@ -268,22 +254,16 @@ nsImageBoxFrame::UpdateImage()
                                               doc,
                                               baseURI);
 
     if (uri && nsContentUtils::CanLoadImage(uri, mContent, doc,
                                             mContent->NodePrincipal())) {
       nsContentUtils::LoadImage(uri, doc, mContent->NodePrincipal(),
                                 doc->GetDocumentURI(), mListener, mLoadFlags,
                                 getter_AddRefs(mImageRequest));
-
-      // Register our imgIRequest with the refresh driver
-      nsLayoutUtils::RegisterImageRequest(presContext,
-                                          mImageRequest,
-                                          &mRequestRegistered);
-
     }
   } else {
     // Only get the list-style-image if we aren't being drawn
     // by a native theme.
     PRUint8 appearance = GetStyleDisplay()->mAppearance;
     if (!(appearance && nsBox::gTheme && 
           nsBox::gTheme->ThemeSupportsWidget(nsnull, this, appearance))) {
       // get the list-style-image
@@ -598,41 +578,20 @@ NS_IMETHODIMP nsImageBoxFrame::OnStopCon
                                                imgIContainer *image)
 {
   nsBoxLayoutState state(PresContext());
   this->Redraw(state);
 
   return NS_OK;
 }
 
-NS_IMETHODIMP nsImageBoxFrame::OnStartDecode(imgIRequest* aRequest)
-{
-  nsPresContext* presContext = PresContext();
-  NS_ASSERTION(presContext, "No PresContext");
-
-  nsLayoutUtils::RegisterImageRequest(presContext,
-                                      mImageRequest,
-                                      &mRequestRegistered);
-
-  return NS_OK;
-}
-
 NS_IMETHODIMP nsImageBoxFrame::OnStopDecode(imgIRequest *request,
                                             nsresult aStatus,
                                             const PRUnichar *statusArg)
 {
-  // If the imgIRequest does not represent an animated image, then we should
-  // deregister it from our refresh driver.
-  nsPresContext* presContext = PresContext();
-  NS_ASSERTION(presContext, "No PresContext");
-
-  nsLayoutUtils::DeregisterImageRequestIfNotAnimated(presContext,
-                                                     mImageRequest,
-                                                     &mRequestRegistered);
-
   if (NS_SUCCEEDED(aStatus))
     // Fire an onload DOM event.
     FireImageDOMEvent(mContent, NS_LOAD);
   else {
     // Fire an onerror DOM event.
     mIntrinsicSize.SizeTo(0, 0);
     PresContext()->PresShell()->
       FrameNeedsReflow(this, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
@@ -660,45 +619,36 @@ nsImageBoxListener::nsImageBoxListener()
 nsImageBoxListener::~nsImageBoxListener()
 {
 }
 
 NS_IMETHODIMP nsImageBoxListener::OnStartContainer(imgIRequest *request,
                                                    imgIContainer *image)
 {
   if (!mFrame)
-    return NS_OK;
+    return NS_ERROR_FAILURE;
 
   return mFrame->OnStartContainer(request, image);
 }
 
 NS_IMETHODIMP nsImageBoxListener::OnStopContainer(imgIRequest *request,
                                                   imgIContainer *image)
 {
   if (!mFrame)
-    return NS_OK;
+    return NS_ERROR_FAILURE;
 
   return mFrame->OnStopContainer(request, image);
 }
 
-NS_IMETHODIMP nsImageBoxListener::OnStartDecode(imgIRequest *aRequest)
-{
-  if (!mFrame) {
-    return NS_OK;
-  }
-
-  return mFrame->OnStartDecode(aRequest);
-}
-
 NS_IMETHODIMP nsImageBoxListener::OnStopDecode(imgIRequest *request,
                                                nsresult status,
                                                const PRUnichar *statusArg)
 {
   if (!mFrame)
-    return NS_OK;
+    return NS_ERROR_FAILURE;
 
   return mFrame->OnStopDecode(request, status, statusArg);
 }
 
 NS_IMETHODIMP nsImageBoxListener::FrameChanged(imgIContainer *aContainer,
                                                const nsIntRect *aDirtyRect)
 {
   if (!mFrame)
--- a/layout/xul/base/src/nsImageBoxFrame.h
+++ b/layout/xul/base/src/nsImageBoxFrame.h
@@ -51,17 +51,16 @@ class nsImageBoxListener : public nsStub
 public:
   nsImageBoxListener();
   virtual ~nsImageBoxListener();
 
   NS_DECL_ISUPPORTS
   // imgIDecoderObserver (override nsStubImageDecoderObserver)
   NS_IMETHOD OnStartContainer(imgIRequest *request, imgIContainer *image);
   NS_IMETHOD OnStopContainer(imgIRequest *request, imgIContainer *image);
-  NS_IMETHOD OnStartDecode(imgIRequest *aRequest);
   NS_IMETHOD OnStopDecode(imgIRequest *request, nsresult status,
                           const PRUnichar *statusArg);
   // imgIContainerObserver (override nsStubImageDecoderObserver)
   NS_IMETHOD FrameChanged(imgIContainer *aContainer,
                           const nsIntRect *aDirtyRect);
 
   void SetFrame(nsImageBoxFrame *frame) { mFrame = frame; }
 
@@ -115,17 +114,16 @@ public:
   void UpdateLoadFlags();
 
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists);
 
   NS_IMETHOD OnStartContainer(imgIRequest *request, imgIContainer *image);
   NS_IMETHOD OnStopContainer(imgIRequest *request, imgIContainer *image);
-  NS_IMETHOD OnStartDecode(imgIRequest *aRequest);
   NS_IMETHOD OnStopDecode(imgIRequest *request,
                           nsresult status,
                           const PRUnichar *statusArg);
   NS_IMETHOD FrameChanged(imgIContainer *aContainer,
                           const nsIntRect *aDirtyRect);
 
   virtual ~nsImageBoxFrame();
 
@@ -139,20 +137,16 @@ protected:
   virtual void GetImageSize();
 
 private:
 
   nsRect mSubRect; ///< If set, indicates that only the portion of the image specified by the rect should be used.
   nsSize mIntrinsicSize;
   nsSize mImageSize;
 
-  // Boolean variable to determine if the current image request has been
-  // registered with the refresh driver.
-  bool mRequestRegistered;
-
   nsCOMPtr<imgIRequest> mImageRequest;
   nsCOMPtr<imgIDecoderObserver> mListener;
 
   PRInt32 mLoadFlags;
 
   bool mUseSrcAttr; ///< Whether or not the image src comes from an attribute.
   bool mSuppressStyleCheck;
 }; // class nsImageBoxFrame
deleted file mode 100644
--- a/layout/xul/base/src/tree/src/nsITreeImageListener.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Dave Hyatt <hyatt@mozilla.org> (Original Author)
- *   Jan Varga <varga@ku.sk>
- *   Scott Johnson <sjohnson@mozilla.com>, Mozilla Corporation
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef nsITreeImageListener_h__
-#define nsITreeImageListener_h__
-
-// The interface for our image listener.
-// {90586540-2D50-403e-8DCE-981CAA778444}
-#define NS_ITREEIMAGELISTENER_IID \
-{ 0x90586540, 0x2d50, 0x403e, { 0x8d, 0xce, 0x98, 0x1c, 0xaa, 0x77, 0x84, 0x44 } }
-
-class nsITreeImageListener : public nsISupports
-{
-public:
-  NS_DECLARE_STATIC_IID_ACCESSOR(NS_ITREEIMAGELISTENER_IID)
-
-  NS_IMETHOD AddCell(PRInt32 aIndex, nsITreeColumn* aCol) = 0;
-
-  /**
-   * Clear the internal frame pointer to prevent dereferencing an object
-   * that no longer exists.
-   */
-  NS_IMETHOD ClearFrame() = 0;
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsITreeImageListener, NS_ITREEIMAGELISTENER_IID)
-
-#endif
--- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
@@ -49,17 +49,16 @@
 
 #include "nsCOMPtr.h"
 #include "nsISupportsArray.h"
 #include "nsPresContext.h"
 #include "nsINameSpaceManager.h"
 
 #include "nsTreeBodyFrame.h"
 #include "nsTreeSelection.h"
-#include "nsTreeImageListener.h"
 
 #include "nsGkAtoms.h"
 #include "nsCSSAnonBoxes.h"
 
 #include "nsIContent.h"
 #include "nsStyleContext.h"
 #include "nsIBoxObject.h"
 #include "nsGUIEvent.h"
@@ -110,24 +109,16 @@
 
 using namespace mozilla;
 
 // Enumeration function that cancels all the image requests in our cache
 static PLDHashOperator
 CancelImageRequest(const nsAString& aKey,
                    nsTreeImageCacheEntry aEntry, void* aData)
 {
-
-  // If our imgIRequest object was registered with the refresh driver,
-  // then we need to deregister it.
-  nsTreeBodyFrame* frame = static_cast<nsTreeBodyFrame*>(aData);
-
-  nsLayoutUtils::DeregisterImageRequest(frame->PresContext(), aEntry.request,
-                                        nsnull);
-
   aEntry.request->CancelAndForgetObserver(NS_BINDING_ABORTED);
   return PL_DHASH_NEXT;
 }
 
 //
 // NS_NewTreeFrame
 //
 // Creates a new tree frame
@@ -168,18 +159,17 @@ nsTreeBodyFrame::nsTreeBodyFrame(nsIPres
 {
   mColumns = new nsTreeColumns(nsnull);
   NS_NewISupportsArray(getter_AddRefs(mScratchArray));
 }
 
 // Destructor
 nsTreeBodyFrame::~nsTreeBodyFrame()
 {
-  mImageCache.EnumerateRead(CancelImageRequest, this);
-  DetachImageListeners();
+  mImageCache.EnumerateRead(CancelImageRequest, nsnull);
   delete mSlots;
 }
 
 static void
 GetBorderPadding(nsStyleContext* aContext, nsMargin& aMargin)
 {
   aMargin.SizeTo(0, 0, 0, 0);
   if (!aContext->GetStylePadding()->GetPadding(aMargin)) {
@@ -202,21 +192,18 @@ nsTreeBodyFrame::Init(nsIContent*     aC
                       nsIFrame*       aPrevInFlow)
 {
   nsresult rv = nsLeafBoxFrame::Init(aContent, aParent, aPrevInFlow);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mIndentation = GetIndentation();
   mRowHeight = GetRowHeight();
 
-  NS_ENSURE_TRUE(mCreatedListeners.Init(), NS_ERROR_OUT_OF_MEMORY);
-
   NS_ENSURE_TRUE(mImageCache.Init(16), NS_ERROR_OUT_OF_MEMORY);
   EnsureBoxObject();
-
   return rv;
 }
 
 nsSize
 nsTreeBodyFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState)
 {
   EnsureView();
 
@@ -2162,24 +2149,20 @@ nsTreeBodyFrame::GetImage(PRInt32 aRowIn
         listener->AddCell(aRowIndex, aCol);
       return NS_OK;
     }
   }
 
   if (!*aResult) {
     // Create a new nsTreeImageListener object and pass it our row and column
     // information.
-    nsTreeImageListener* listener = new nsTreeImageListener(this);
+    nsTreeImageListener* listener = new nsTreeImageListener(mTreeBoxObject);
     if (!listener)
       return NS_ERROR_OUT_OF_MEMORY;
 
-    if (!mCreatedListeners.PutEntry(listener)) {
-      return NS_ERROR_FAILURE;
-    }
-
     listener->AddCell(aRowIndex, aCol);
     nsCOMPtr<imgIDecoderObserver> imgDecoderObserver = listener;
 
     nsCOMPtr<imgIRequest> imageRequest;
     if (styleRequest) {
       styleRequest->Clone(imgDecoderObserver, getter_AddRefs(imageRequest));
     } else {
       nsIDocument* doc = mContent->GetDocument();
@@ -4248,17 +4231,17 @@ nsTreeBodyFrame::GetBaseElement()
 
   return nsnull;
 }
 
 nsresult
 nsTreeBodyFrame::ClearStyleAndImageCaches()
 {
   mStyleCache.Clear();
-  mImageCache.EnumerateRead(CancelImageRequest, this);
+  mImageCache.EnumerateRead(CancelImageRequest, nsnull);
   mImageCache.Clear();
   return NS_OK;
 }
 
 /* virtual */ void
 nsTreeBodyFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
   nsLeafBoxFrame::DidSetStyleContext(aOldStyleContext);
@@ -4480,30 +4463,16 @@ nsTreeBodyFrame::PostScrollEvent()
   nsRefPtr<ScrollEvent> ev = new ScrollEvent(this);
   if (NS_FAILED(NS_DispatchToCurrentThread(ev))) {
     NS_WARNING("failed to dispatch ScrollEvent");
   } else {
     mScrollEvent = ev;
   }
 }
 
-void
-nsTreeBodyFrame::DetachImageListeners()
-{
-  mCreatedListeners.Clear();
-}
-
-void
-nsTreeBodyFrame::RemoveTreeImageListener(nsTreeImageListener* aListener)
-{
-  if (aListener) {
-    mCreatedListeners.RemoveEntry(aListener);
-  }
-}
-
 #ifdef ACCESSIBILITY
 void
 nsTreeBodyFrame::FireRowCountChangedEvent(PRInt32 aIndex, PRInt32 aCount)
 {
   nsCOMPtr<nsIContent> content(GetBaseElement());
   if (!content)
     return;
 
@@ -4667,24 +4636,8 @@ nsTreeBodyFrame::FullScrollbarsUpdate(bo
   if (aNeedsFullInvalidation) {
     Invalidate();
   }
   InvalidateScrollbars(parts, weakColumnsFrame);
   NS_ENSURE_TRUE(weakFrame.IsAlive(), false);
   nsContentUtils::AddScriptRunner(new nsOverflowChecker(this));
   return weakFrame.IsAlive();
 }
-
-nsresult
-nsTreeBodyFrame::OnStartDecode(imgIRequest* aRequest)
-{
-  nsLayoutUtils::RegisterImageRequest(PresContext(), aRequest, nsnull);
-  return NS_OK;
-}
-
-nsresult
-nsTreeBodyFrame::OnStopDecode(imgIRequest* aRequest, nsresult aStatus,
-                              const PRUnichar* aStatusArg)
-{
-  nsLayoutUtils::DeregisterImageRequestIfNotAnimated(PresContext(), aRequest,
-                                                     nsnull);
-  return NS_OK;
-}
--- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.h
+++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.h
@@ -49,27 +49,26 @@
 #include "nsICSSPseudoComparator.h"
 #include "nsIScrollbarMediator.h"
 #include "nsIDragSession.h"
 #include "nsITimer.h"
 #include "nsIReflowCallback.h"
 #include "nsTArray.h"
 #include "nsTreeStyleCache.h"
 #include "nsTreeColumns.h"
+#include "nsTreeImageListener.h"
 #include "nsAutoPtr.h"
 #include "nsDataHashtable.h"
 #include "imgIRequest.h"
 #include "imgIDecoderObserver.h"
 #include "nsScrollbarFrame.h"
 #include "nsThreadUtils.h"
 #include "mozilla/LookAndFeel.h"
-#include "nsITreeImageListener.h"
 
 class nsOverflowChecker;
-class nsTreeImageListener;
 
 // An entry in the tree's image cache
 struct nsTreeImageCacheEntry
 {
   nsTreeImageCacheEntry() {}
   nsTreeImageCacheEntry(imgIRequest *aRequest, imgIDecoderObserver *aListener)
     : request(aRequest), listener(aListener) {}
 
@@ -87,23 +86,16 @@ class NS_FINAL_CLASS nsTreeBodyFrame
 public:
   nsTreeBodyFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   ~nsTreeBodyFrame();
 
   NS_DECL_QUERYFRAME_TARGET(nsTreeBodyFrame)
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
-  // Callback handler methods for refresh driver based animations.
-  // Calls to these functions are forwarded from nsTreeImageListener. These
-  // mirror how nsImageFrame works.
-  nsresult OnStartDecode(imgIRequest* aRequest);
-  nsresult OnStopDecode(imgIRequest* aRequest, nsresult aStatus,
-                        const PRUnichar* aStatusArg);
-
   // non-virtual signatures like nsITreeBodyFrame
   nsresult GetColumns(nsITreeColumns **aColumns);
   nsresult GetView(nsITreeView **aView);
   nsresult SetView(nsITreeView *aView);
   nsresult GetFocused(bool *aFocused);
   nsresult SetFocused(bool aFocused);
   nsresult GetTreeBody(nsIDOMElement **aElement);
   nsresult GetRowHeight(PRInt32 *aValue);
@@ -438,25 +430,16 @@ public:
     if (!aUnknownCol)
       return nsnull;
 
     nsTreeColumn* col;
     aUnknownCol->QueryInterface(NS_GET_IID(nsTreeColumn), (void**)&col);
     return col;
   }
 
-  /**
-   * Remove an nsITreeImageListener from being tracked by this frame. Only tree
-   * image listeners that are created by this frame are tracked.
-   *
-   * @param aListener A pointer to an nsTreeImageListener to no longer
-   *        track.
-   */
-  void RemoveTreeImageListener(nsTreeImageListener* aListener);
-
 protected:
 
   // Create a new timer. This method is used to delay various actions like
   // opening/closing folders or tree scrolling.
   // aID is type of the action, aFunc is the function to be called when
   // the timer fires and aType is type of timer - one shot or repeating.
   nsresult CreateTimer(const mozilla::LookAndFeel::IntID aID,
                        nsTimerCallbackFunc aFunc, PRInt32 aType,
@@ -477,22 +460,16 @@ protected:
     void Revoke() { mInner = nsnull; }
   private:
     nsTreeBodyFrame* mInner;
   };
 
   void PostScrollEvent();
   void FireScrollEvent();
 
-  /**
-   * Clear the pointer to this frame for all nsTreeImageListeners that were
-   * created by this frame.
-   */
-  void DetachImageListeners();
-
 #ifdef ACCESSIBILITY
   /**
    * Fires 'treeRowCountChanged' event asynchronously. The event supports
    * nsIDOMDataContainerEvent interface that is used to expose the following
    * information structures.
    *
    * @param aIndex  the row index rows are added/removed from
    * @param aCount  the number of added/removed rows (the sign points to
@@ -620,16 +597,11 @@ protected: // Data Members
 
   // Do we have a fixed number of onscreen rows?
   bool mHasFixedRowCount;
 
   bool mVerticalOverflow;
   bool mHorizontalOverflow;
 
   bool mReflowCallbackPosted;
-
-  // Hash table to keep track of which listeners we created and thus
-  // have pointers to us.
-  nsTHashtable<nsPtrHashKey<nsTreeImageListener> > mCreatedListeners;
-
 }; // class nsTreeBodyFrame
 
 #endif
--- a/layout/xul/base/src/tree/src/nsTreeImageListener.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeImageListener.cpp
@@ -39,51 +39,28 @@
 
 #include "nsTreeImageListener.h"
 #include "nsITreeBoxObject.h"
 #include "imgIRequest.h"
 #include "imgIContainer.h"
 
 NS_IMPL_ISUPPORTS3(nsTreeImageListener, imgIDecoderObserver, imgIContainerObserver, nsITreeImageListener)
 
-nsTreeImageListener::nsTreeImageListener(nsTreeBodyFrame* aTreeFrame)
-  : mTreeFrame(aTreeFrame),
+nsTreeImageListener::nsTreeImageListener(nsITreeBoxObject* aTree)
+  : mTree(aTree),
     mInvalidationSuppressed(true),
     mInvalidationArea(nsnull)
 {
 }
 
 nsTreeImageListener::~nsTreeImageListener()
 {
   delete mInvalidationArea;
 }
 
-NS_IMETHODIMP
-nsTreeImageListener::OnStartDecode(imgIRequest *aRequest)
-{
-  if (!mTreeFrame) {
-    return NS_OK;
-  }
-
-  // grab the frame we want to use
-  return mTreeFrame->OnStartDecode(aRequest);
-}
-
-NS_IMETHODIMP
-nsTreeImageListener::OnStopDecode(imgIRequest *aRequest,
-                                  nsresult aStatus,
-                                  const PRUnichar *aStatusArg)
-{
-  if (!mTreeFrame) {
-    return NS_OK;
-  }
-
-  return mTreeFrame->OnStopDecode(aRequest, aStatus, aStatusArg);
-}
-
 NS_IMETHODIMP nsTreeImageListener::OnStartContainer(imgIRequest *aRequest,
                                                     imgIContainer *aImage)
 {
   // Ensure the animation (if any) is started. Note: There is no
   // corresponding call to Decrement for this. This Increment will be
   // 'cleaned up' by the Request when it is destroyed, but only then.
   aRequest->IncrementAnimationConsumers();
   return NS_OK;
@@ -131,26 +108,20 @@ nsTreeImageListener::AddCell(PRInt32 aIn
   return NS_OK;
 }
 
 
 void
 nsTreeImageListener::Invalidate()
 {
   if (!mInvalidationSuppressed) {
-    for (InvalidationArea* currArea = mInvalidationArea; currArea;
-         currArea = currArea->GetNext()) {
+    for (InvalidationArea* currArea = mInvalidationArea; currArea; currArea = currArea->GetNext()) {
       // Loop from min to max, invalidating each cell that was listening for this image.
       for (PRInt32 i = currArea->GetMin(); i <= currArea->GetMax(); ++i) {
-        if (mTreeFrame) {
-          nsITreeBoxObject* tree = mTreeFrame->GetTreeBoxObject();
-          if (tree) {
-            tree->InvalidateCell(i, currArea->GetCol());
-          }
-        }
+        mTree->InvalidateCell(i, currArea->GetCol());
       }
     }
   }
 }
 
 nsTreeImageListener::InvalidationArea::InvalidationArea(nsITreeColumn* aCol)
   : mCol(aCol),
     mMin(-1), // min should start out "undefined"
@@ -164,15 +135,8 @@ nsTreeImageListener::InvalidationArea::A
 {
   if (mMin == -1)
     mMin = mMax = aIndex;
   else if (aIndex < mMin)
     mMin = aIndex;
   else if (aIndex > mMax)
     mMax = aIndex;
 }
-
-NS_IMETHODIMP
-nsTreeImageListener::ClearFrame()
-{
-  mTreeFrame = nsnull;
-  return NS_OK;
-}
--- a/layout/xul/base/src/tree/src/nsTreeImageListener.h
+++ b/layout/xul/base/src/tree/src/nsTreeImageListener.h
@@ -39,49 +39,60 @@
 
 #ifndef nsTreeImageListener_h__
 #define nsTreeImageListener_h__
 
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsITreeColumns.h"
 #include "nsStubImageDecoderObserver.h"
-#include "nsTreeBodyFrame.h"
-#include "nsITreeImageListener.h"
+
+class nsITreeBoxObject;
+
+// The interface for our image listener.
+// {90586540-2D50-403e-8DCE-981CAA778444}
+#define NS_ITREEIMAGELISTENER_IID \
+{ 0x90586540, 0x2d50, 0x403e, { 0x8d, 0xce, 0x98, 0x1c, 0xaa, 0x77, 0x84, 0x44 } }
+
+class nsITreeImageListener : public nsISupports
+{
+public:
+  NS_DECLARE_STATIC_IID_ACCESSOR(NS_ITREEIMAGELISTENER_IID)
+
+  NS_IMETHOD AddCell(PRInt32 aIndex, nsITreeColumn* aCol) = 0;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsITreeImageListener, NS_ITREEIMAGELISTENER_IID)
 
 // This class handles image load observation.
 class nsTreeImageListener : public nsStubImageDecoderObserver, public nsITreeImageListener
 {
 public:
-  nsTreeImageListener(nsTreeBodyFrame *aTreeFrame);
+  nsTreeImageListener(nsITreeBoxObject* aTree);
   ~nsTreeImageListener();
 
   NS_DECL_ISUPPORTS
   // imgIDecoderObserver (override nsStubImageDecoderObserver)
-  NS_IMETHOD OnStartDecode(imgIRequest *aRequest);
-  NS_IMETHOD OnStopDecode(imgIRequest *aRequest,
-                          nsresult aStatus, const PRUnichar *aStatusArg);
   NS_IMETHOD OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage);
   NS_IMETHOD OnDataAvailable(imgIRequest *aRequest, bool aCurrentFrame,
                              const nsIntRect *aRect);
   // imgIContainerObserver (override nsStubImageDecoderObserver)
   NS_IMETHOD FrameChanged(imgIContainer *aContainer,
                           const nsIntRect *aDirtyRect);
 
   NS_IMETHOD AddCell(PRInt32 aIndex, nsITreeColumn* aCol);
-  NS_IMETHOD ClearFrame();
-
+ 
   friend class nsTreeBodyFrame;
 
 protected:
   void UnsuppressInvalidation() { mInvalidationSuppressed = false; }
   void Invalidate();
 
 private:
-  nsTreeBodyFrame* mTreeFrame;
+  nsITreeBoxObject* mTree;
 
   // A guard that prevents us from recursive painting.
   bool mInvalidationSuppressed;
 
   class InvalidationArea {
     public:
       InvalidationArea(nsITreeColumn* aCol);
       ~InvalidationArea() { delete mNext; }