Bug 716140 - Convert the XPCOM imgIDecoderObserver interface into a private C++ interface, imgDecoderObserver, so we can more easily make changes to it. r=jrmuizel
authorJoe Drew <joe@drew.ca>
Tue, 18 Dec 2012 11:37:15 -0500
changeset 125514 3ecf6d05c4e280cf1631e415e58e86c24d1cff23
parent 125513 0bcb93a716beaf14ecf13f5312541474252c0b5a
child 125515 985bab8f84dfe203e9735a1937d2fbfa32f4d3e4
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs716140
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 716140 - Convert the XPCOM imgIDecoderObserver interface into a private C++ interface, imgDecoderObserver, so we can more easily make changes to it. r=jrmuizel
content/base/public/nsIImageLoadingContent.idl
image/decoders/nsBMPDecoder.cpp
image/decoders/nsBMPDecoder.h
image/decoders/nsGIFDecoder2.cpp
image/decoders/nsGIFDecoder2.h
image/decoders/nsICODecoder.cpp
image/decoders/nsICODecoder.h
image/decoders/nsIconDecoder.cpp
image/decoders/nsIconDecoder.h
image/decoders/nsJPEGDecoder.cpp
image/decoders/nsJPEGDecoder.h
image/decoders/nsPNGDecoder.cpp
image/decoders/nsPNGDecoder.h
image/public/Makefile.in
image/public/imgIContainer.idl
image/public/imgIDecoderObserver.idl
image/src/Decoder.cpp
image/src/Decoder.h
image/src/Image.h
image/src/RasterImage.cpp
image/src/RasterImage.h
image/src/VectorImage.cpp
image/src/VectorImage.h
image/src/imgDecoderObserver.h
image/src/imgRequestProxy.cpp
image/src/imgRequestProxy.h
image/src/imgStatusTracker.cpp
image/src/imgStatusTracker.h
image/src/imgTools.cpp
image/test/browser/head.js
image/test/unit/async_load_tests.js
image/test/unit/image_load_helpers.js
layout/generic/nsBulletFrame.h
widget/cocoa/nsMenuItemIconX.mm
widget/gtk2/nsImageToPixbuf.cpp
--- a/content/base/public/nsIImageLoadingContent.idl
+++ b/content/base/public/nsIImageLoadingContent.idl
@@ -106,17 +106,17 @@ interface nsIImageLoadingContent : imgIN
   /**
    * 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
+   * which request got passed through to the imgINotificationObserver
    * interface of an observer)
    *
    * @param aRequest the request whose type we want to know
    *
    * @return an enum value saying what type this request is
    *
    * @throws NS_ERROR_UNEXPECTED if aRequest is not known
    */
--- a/image/decoders/nsBMPDecoder.cpp
+++ b/image/decoders/nsBMPDecoder.cpp
@@ -29,17 +29,17 @@ GetBMPLog()
   return sBMPLog;
 }
 #endif
 
 // Convert from row (1..height) to absolute line (0..height-1)
 #define LINE(row) ((mBIH.height < 0) ? (-mBIH.height - (row)) : ((row) - 1))
 #define PIXEL_OFFSET(row, col) (LINE(row) * mBIH.width + col)
 
-nsBMPDecoder::nsBMPDecoder(RasterImage &aImage, imgIDecoderObserver* aObserver)
+nsBMPDecoder::nsBMPDecoder(RasterImage &aImage, imgDecoderObserver* aObserver)
  : Decoder(aImage, aObserver)
 {
   mColors = nullptr;
   mRow = nullptr;
   mImageData = nullptr;
   mCurPos = mPos = mNumColors = mRowBytes = 0;
   mOldLine = mCurLine = 1; // Otherwise decoder will never start
   mState = eRLEStateInitial;
--- a/image/decoders/nsBMPDecoder.h
+++ b/image/decoders/nsBMPDecoder.h
@@ -3,34 +3,34 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #ifndef _nsBMPDecoder_h
 #define _nsBMPDecoder_h
 
 #include "nsAutoPtr.h"
-#include "imgIDecoderObserver.h"
+#include "imgDecoderObserver.h"
 #include "gfxColor.h"
 #include "Decoder.h"
 #include "BMPFileHeaders.h"
 
 namespace mozilla {
 namespace image {
 
 class RasterImage;
 
 /**
  * Decoder for BMP-Files, as used by Windows and OS/2
  */
 class nsBMPDecoder : public Decoder
 {
 public:
 
-    nsBMPDecoder(RasterImage &aImage, imgIDecoderObserver* aObserver);
+    nsBMPDecoder(RasterImage &aImage, imgDecoderObserver* aObserver);
     ~nsBMPDecoder();
 
     // Specifies whether or not the BMP file will contain alpha data
     // If set to true and the BMP is 32BPP, the alpha data will be
     // retrieved from the 4th byte of image data per pixel 
     void SetUseAlphaData(bool useAlphaData);
     // Obtains the bits per pixel from the internal BIH header
     int32_t GetBitsPerPixel() const;
--- a/image/decoders/nsGIFDecoder2.cpp
+++ b/image/decoders/nsGIFDecoder2.cpp
@@ -66,17 +66,17 @@ namespace image {
     mGIFStruct.state = (s);            \
   PR_END_MACRO
 
 /* Get a 16-bit value stored in little-endian format */
 #define GETINT16(p)   ((p)[1]<<8|(p)[0])
 //////////////////////////////////////////////////////////////////////
 // GIF Decoder Implementation
 
-nsGIFDecoder2::nsGIFDecoder2(RasterImage &aImage, imgIDecoderObserver* aObserver)
+nsGIFDecoder2::nsGIFDecoder2(RasterImage &aImage, imgDecoderObserver* aObserver)
   : Decoder(aImage, aObserver)
   , mCurrentRow(-1)
   , mLastFlushedRow(-1)
   , mImageData(nullptr)
   , mColormap(nullptr)
   , mOldColor(0)
   , mCurrentFrame(-1)
   , mCurrentPass(0)
--- a/image/decoders/nsGIFDecoder2.h
+++ b/image/decoders/nsGIFDecoder2.h
@@ -4,32 +4,32 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef _nsGIFDecoder2_h
 #define _nsGIFDecoder2_h
 
 #include "nsCOMPtr.h"
 #include "Decoder.h"
-#include "imgIDecoderObserver.h"
+#include "imgDecoderObserver.h"
 
 #include "GIF2.h"
 
 namespace mozilla {
 namespace image {
 class RasterImage;
 
 //////////////////////////////////////////////////////////////////////
 // nsGIFDecoder2 Definition
 
 class nsGIFDecoder2 : public Decoder
 {
 public:
 
-  nsGIFDecoder2(RasterImage &aImage, imgIDecoderObserver* aObserver);
+  nsGIFDecoder2(RasterImage &aImage, imgDecoderObserver* aObserver);
   ~nsGIFDecoder2();
 
   virtual void WriteInternal(const char* aBuffer, uint32_t aCount);
   virtual void FinishInternal();
   virtual Telemetry::ID SpeedHistogram();
 
 private:
   /* These functions will be called when the decoder has a decoded row,
--- a/image/decoders/nsICODecoder.cpp
+++ b/image/decoders/nsICODecoder.cpp
@@ -57,17 +57,17 @@ nsICODecoder::GetNumColors()
     default:
       numColors = (uint16_t)-1;
     }
   }
   return numColors;
 }
 
 
-nsICODecoder::nsICODecoder(RasterImage &aImage, imgIDecoderObserver* aObserver)
+nsICODecoder::nsICODecoder(RasterImage &aImage, imgDecoderObserver* aObserver)
  : Decoder(aImage, aObserver)
 {
   mPos = mImageOffset = mCurrIcon = mNumIcons = mBPP = mRowBytes = 0;
   mIsPNG = false;
   mRow = nullptr;
   mOldLine = mCurLine = 1; // Otherwise decoder will never start
 }
 
--- a/image/decoders/nsICODecoder.h
+++ b/image/decoders/nsICODecoder.h
@@ -4,31 +4,31 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #ifndef _nsICODecoder_h
 #define _nsICODecoder_h
 
 #include "nsAutoPtr.h"
 #include "Decoder.h"
-#include "imgIDecoderObserver.h"
+#include "imgDecoderObserver.h"
 #include "nsBMPDecoder.h"
 #include "nsPNGDecoder.h"
 #include "ICOFileHeaders.h"
 
 namespace mozilla {
 namespace image {
 
 class RasterImage;
 
 class nsICODecoder : public Decoder
 {
 public:
 
-  nsICODecoder(RasterImage &aImage, imgIDecoderObserver* aObserver);
+  nsICODecoder(RasterImage &aImage, imgDecoderObserver* aObserver);
   virtual ~nsICODecoder();
 
   // Obtains the width of the icon directory entry
   uint32_t GetRealWidth() const
   {
     return mDirEntry.mWidth == 0 ? 256 : mDirEntry.mWidth; 
   }
 
--- a/image/decoders/nsIconDecoder.cpp
+++ b/image/decoders/nsIconDecoder.cpp
@@ -10,17 +10,17 @@
 #include "nspr.h"
 #include "nsRect.h"
 
 #include "nsError.h"
 
 namespace mozilla {
 namespace image {
 
-nsIconDecoder::nsIconDecoder(RasterImage &aImage, imgIDecoderObserver* aObserver)
+nsIconDecoder::nsIconDecoder(RasterImage &aImage, imgDecoderObserver* aObserver)
  : Decoder(aImage, aObserver),
    mWidth(-1),
    mHeight(-1),
    mPixBytesRead(0),
    mPixBytesTotal(0),
    mImageData(nullptr),
    mState(iconStateStart)
 {
--- a/image/decoders/nsIconDecoder.h
+++ b/image/decoders/nsIconDecoder.h
@@ -6,17 +6,17 @@
 
 #ifndef nsIconDecoder_h__
 #define nsIconDecoder_h__
 
 #include "Decoder.h"
 
 #include "nsCOMPtr.h"
 
-#include "imgIDecoderObserver.h"
+#include "imgDecoderObserver.h"
 
 namespace mozilla {
 namespace image {
 class RasterImage;
 
 //////////////////////////////////////////////////////////////////////////////////////////////
 // The icon decoder is a decoder specifically tailored for loading icons 
 // from the OS. We've defined our own little format to represent these icons
@@ -35,17 +35,17 @@ class RasterImage;
 //
 //
 //////////////////////////////////////////////////////////////////////////////////////////////
 
 class nsIconDecoder : public Decoder
 {
 public:
 
-  nsIconDecoder(RasterImage &aImage, imgIDecoderObserver* aObserver);
+  nsIconDecoder(RasterImage &aImage, imgDecoderObserver* aObserver);
   virtual ~nsIconDecoder();
 
   virtual void WriteInternal(const char* aBuffer, uint32_t aCount);
 
   uint8_t mWidth;
   uint8_t mHeight;
   uint32_t mPixBytesRead;
   uint32_t mPixBytesTotal;
--- a/image/decoders/nsJPEGDecoder.cpp
+++ b/image/decoders/nsJPEGDecoder.cpp
@@ -75,17 +75,17 @@ METHODDEF(boolean) fill_input_buffer (j_
 METHODDEF(void) skip_input_data (j_decompress_ptr jd, long num_bytes);
 METHODDEF(void) term_source (j_decompress_ptr jd);
 METHODDEF(void) my_error_exit (j_common_ptr cinfo);
 
 /* Normal JFIF markers can't have more bytes than this. */
 #define MAX_JPEG_MARKER_LENGTH  (((uint32_t)1 << 16) - 1)
 
 
-nsJPEGDecoder::nsJPEGDecoder(RasterImage& aImage, imgIDecoderObserver* aObserver, Decoder::DecodeStyle aDecodeStyle)
+nsJPEGDecoder::nsJPEGDecoder(RasterImage& aImage, imgDecoderObserver* aObserver, Decoder::DecodeStyle aDecodeStyle)
  : Decoder(aImage, aObserver)
  , mDecodeStyle(aDecodeStyle)
 {
   mState = JPEG_HEADER;
   mReading = true;
   mImageData = nullptr;
 
   mBytesToSkip = 0;
--- a/image/decoders/nsJPEGDecoder.h
+++ b/image/decoders/nsJPEGDecoder.h
@@ -12,17 +12,17 @@
  * But the jpeg decoder has its own definition of INT32. To avoid build issues,
  * we need to undefine the version from 'windows.h'. */
 #undef INT32
 
 #include "Decoder.h"
 
 #include "nsAutoPtr.h"
 
-#include "imgIDecoderObserver.h"
+#include "imgDecoderObserver.h"
 #include "nsIInputStream.h"
 #include "nsIPipe.h"
 #include "qcms.h"
 
 extern "C" {
 #include "jpeglib.h"
 }
 
@@ -47,17 +47,17 @@ typedef enum {
     JPEG_ERROR    
 } jstate;
 
 class RasterImage;
 
 class nsJPEGDecoder : public Decoder
 {
 public:
-  nsJPEGDecoder(RasterImage &aImage, imgIDecoderObserver* aObserver, Decoder::DecodeStyle aDecodeStyle);
+  nsJPEGDecoder(RasterImage &aImage, imgDecoderObserver* aObserver, Decoder::DecodeStyle aDecodeStyle);
   virtual ~nsJPEGDecoder();
 
   virtual void InitInternal();
   virtual void WriteInternal(const char* aBuffer, uint32_t aCount);
   virtual void FinishInternal();
 
   virtual Telemetry::ID SpeedHistogram();
   void NotifyDone();
--- a/image/decoders/nsPNGDecoder.cpp
+++ b/image/decoders/nsPNGDecoder.cpp
@@ -52,17 +52,17 @@ GetPNGDecoderAccountingLog()
 #define WIDTH_OFFSET 16
 #define HEIGHT_OFFSET (WIDTH_OFFSET + 4)
 #define BYTES_NEEDED_FOR_DIMENSIONS (HEIGHT_OFFSET + 4)
 
 // First 8 bytes of a PNG file
 const uint8_t 
 nsPNGDecoder::pngSignatureBytes[] = { 137, 80, 78, 71, 13, 10, 26, 10 };
 
-nsPNGDecoder::nsPNGDecoder(RasterImage &aImage, imgIDecoderObserver* aObserver)
+nsPNGDecoder::nsPNGDecoder(RasterImage &aImage, imgDecoderObserver* aObserver)
  : Decoder(aImage, aObserver),
    mPNG(nullptr), mInfo(nullptr),
    mCMSLine(nullptr), interlacebuf(nullptr),
    mInProfile(nullptr), mTransform(nullptr),
    mHeaderBuf(nullptr), mHeaderBytesRead(0),
    mChannels(0), mFrameIsHidden(false),
    mCMSMode(0), mDisablePremultipliedAlpha(false)
 {
--- a/image/decoders/nsPNGDecoder.h
+++ b/image/decoders/nsPNGDecoder.h
@@ -4,33 +4,33 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsPNGDecoder_h__
 #define nsPNGDecoder_h__
 
 #include "Decoder.h"
 
-#include "imgIDecoderObserver.h"
+#include "imgDecoderObserver.h"
 #include "gfxASurface.h"
 
 #include "nsCOMPtr.h"
 
 #include "png.h"
 
 #include "qcms.h"
 
 namespace mozilla {
 namespace image {
 class RasterImage;
 
 class nsPNGDecoder : public Decoder
 {
 public:
-  nsPNGDecoder(RasterImage &aImage, imgIDecoderObserver* aObserver);
+  nsPNGDecoder(RasterImage &aImage, imgDecoderObserver* aObserver);
   virtual ~nsPNGDecoder();
 
   virtual void InitInternal();
   virtual void WriteInternal(const char* aBuffer, uint32_t aCount);
   virtual Telemetry::ID SpeedHistogram();
 
   void CreateFrame(png_uint_32 x_offset, png_uint_32 y_offset,
                    int32_t width, int32_t height,
--- a/image/public/Makefile.in
+++ b/image/public/Makefile.in
@@ -14,17 +14,16 @@ MODULE		= imglib2
 GRE_MODULE	= 1
 
 EXPORTS		= ImageLogging.h
 
 XPIDLSRCS	= \
 		imgICache.idl             \
 		imgIContainer.idl         \
 		imgIContainerDebug.idl    \
-		imgIDecoderObserver.idl   \
 		imgIEncoder.idl           \
 		imgILoader.idl            \
 		imgINotificationObserver.idl \
 		imgIOnloadBlocker.idl     \
 		imgIRequest.idl           \
 		imgIScriptedNotificationObserver.idl \
 		imgITools.idl             \
 		$(NULL)
--- a/image/public/imgIContainer.idl
+++ b/image/public/imgIContainer.idl
@@ -1,18 +1,16 @@
 /** -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
-interface imgIDecoderObserver;
-
 %{C++
 #include "gfxImageSurface.h"
 #include "gfxContext.h"
 #include "gfxMatrix.h"
 #include "gfxRect.h"
 #include "gfxPattern.h"
 #include "gfxASurface.h"
 #include "nsRect.h"
deleted file mode 100644
--- a/image/public/imgIDecoderObserver.idl
+++ /dev/null
@@ -1,121 +0,0 @@
-/** -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-%{C++
-#include "nsRect.h"
-%}
-
-[ptr] native nsIntRect(nsIntRect);
-
-/**
- * imgIDecoderObserver interface
- *
- * This interface is used both for observing imgIDecoder objects and for
- * observing imgIRequest objects.  In the former case, aRequest is
- * always null.
- *
- * We make the distinction here between "load" and "decode" notifications. Load
- * notifications are fired as the image is loaded from the network or
- * filesystem. Decode notifications are fired as the image is decoded. If an
- * image is decoded on load and not visibly discarded, decode notifications are
- * nested logically inside load notifications as one might expect. However, with
- * decode-on-draw, the set of decode notifications can imgRcome completely _after_
- * the load notifications, and can come multiple times if the image is
- * discardable. Moreover, they can be interleaved in various ways. In general,
- * any presumed ordering between load and decode notifications should not be
- * relied upon.
- *
- * Decode notifications may or may not be synchronous, depending on the
- * situation. If imgIDecoder::FLAG_SYNC_DECODE is passed to a function that
- * triggers a decode, all notifications that can be generated from the currently
- * loaded data fire before the call returns. If FLAG_SYNC_DECODE is not passed,
- * all, some, or none of the notifications may fire before the call returns.
- *
- * This interface will be cleaned up in bug 505385.
- *
- * @author Stuart Parmenter <pavlov@netscape.com>
- * @version 0.1
- * @see imagelib2
- */
-[scriptable, uuid(eb9f4145-247e-44f5-961d-50da7d08fba7)]
-interface imgIDecoderObserver : nsISupports
-{
-  /**
-   * Load notification.
-   *
-   * called at the same time that nsIRequestObserver::onStartRequest would be
-   * (used only for observers of imgIRequest objects, which are nsIRequests,
-   * not imgIDecoder objects)
-   */
-  void onStartRequest();
-
-  /**
-   * Decode notification.
-   *
-   * Called as soon as the image begins getting decoded. This does not include
-   * "header-only" decodes used by decode-on-draw to parse the width/height
-   * out of the image. Thus, it is a decode notification only.
-   */
-  void onStartDecode();
-
-  /**
-   * Load notification.
-   *
-   * Called once enough data has been loaded from the network that we were able
-   * to parse the width/height from the image. By the time this callback is been
-   * called, the size has been set on the container and STATUS_SIZE_AVAILABLE
-   * has been set on the associated imgRequest.
-   */
-  void onStartContainer();
-
-  /**
-   * Decode notification.
-   *
-   * called when there is more to paint.
-   */
-  [noscript] void onDataAvailable([const] in nsIntRect aRect);
-
-  [noscript] void frameChanged([const] in nsIntRect aDirtyRect);
-
-  /**
-   * Decode notification.
-   *
-   * called when a frame is finished decoding.
-   */
-  void onStopFrame();
-
-  /**
-   * Notification for when an image is known to be animated. This should be
-   * fired at the earliest possible time.
-   */
-  void onImageIsAnimated();
-
-  /**
-   * Decode notification.
-   *
-   * Called when all decoding has terminated.
-   */
-  void onStopDecode(in nsresult status);
-
-  /**
-   * Load notification.
-   *
-   * called at the same time that nsIRequestObserver::onStopRequest would be
-   * (used only for observers of imgIRequest objects, which are nsIRequests,
-   * not imgIDecoder objects)
-   */
-  void onStopRequest(in boolean aIsLastPart);
-
-  /**
-   * Called when the decoded image data is discarded. This means that the frames
-   * no longer exist in decoded form, and any attempt to access or draw the
-   * image will initiate a new series of progressive decode notifications.
-   */
-  void onDiscard();
-
-};
--- a/image/src/Decoder.cpp
+++ b/image/src/Decoder.cpp
@@ -7,17 +7,17 @@
 #include "Decoder.h"
 #include "nsIServiceManager.h"
 #include "nsIConsoleService.h"
 #include "nsIScriptError.h"
 
 namespace mozilla {
 namespace image {
 
-Decoder::Decoder(RasterImage &aImage, imgIDecoderObserver* aObserver)
+Decoder::Decoder(RasterImage &aImage, imgDecoderObserver* aObserver)
   : mImage(aImage)
   , mObserver(aObserver)
   , mDecodeFlags(0)
   , mDecodeDone(false)
   , mDataError(false)
   , mFrameCount(0)
   , mFailCode(NS_OK)
   , mInitialized(false)
--- a/image/src/Decoder.h
+++ b/image/src/Decoder.h
@@ -2,27 +2,27 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_IMAGELIB_DECODER_H_
 #define MOZILLA_IMAGELIB_DECODER_H_
 
 #include "RasterImage.h"
-
-#include "imgIDecoderObserver.h"
+#include "imgDecoderObserver.h"
+#include "mozilla/RefPtr.h"
 
 namespace mozilla {
 namespace image {
 
 class Decoder
 {
 public:
 
-  Decoder(RasterImage& aImage, imgIDecoderObserver* aObserver);
+  Decoder(RasterImage& aImage, imgDecoderObserver* aObserver);
   virtual ~Decoder();
 
   /**
    * Initialize an image decoder. Decoders may not be re-initialized.
    *
    * @param aContainer The image container to decode to.
    * @param aObserver The observer for decode notification events.
    *
@@ -170,17 +170,17 @@ protected:
   void PostDataError();
   void PostDecoderError(nsresult aFailCode);
 
   /*
    * Member variables.
    *
    */
   RasterImage &mImage;
-  nsCOMPtr<imgIDecoderObserver> mObserver;
+  RefPtr<imgDecoderObserver> mObserver;
 
   uint32_t mDecodeFlags;
   bool mDecodeDone;
   bool mDataError;
 
 private:
   uint32_t mFrameCount; // Number of frames, including anything in-progress
 
--- a/image/src/Image.h
+++ b/image/src/Image.h
@@ -42,17 +42,17 @@ public:
 
   /**
    * Creates a new image container.
    *
    * @param aObserver Observer to send decoder and animation notifications to.
    * @param aMimeType The mimetype of the image.
    * @param aFlags Initialization flags of the INIT_FLAG_* variety.
    */
-  virtual nsresult Init(imgIDecoderObserver* aObserver,
+  virtual nsresult Init(imgDecoderObserver* aObserver,
                         const char* aMimeType,
                         const char* aURIString,
                         uint32_t aFlags) = 0;
 
   /**
    * The rectangle defining the location and size of the currently displayed
    * frame.
    */
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -1,20 +1,19 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "base/histogram.h"
 #include "ImageLogging.h"
 #include "nsComponentManagerUtils.h"
-#include "imgIDecoderObserver.h"
+#include "imgDecoderObserver.h"
 #include "nsError.h"
 #include "Decoder.h"
-#include "imgIDecoderObserver.h"
 #include "RasterImage.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsAutoPtr.h"
 #include "nsStringStream.h"
 #include "prenv.h"
 #include "ImageContainer.h"
 #include "Layers.h"
@@ -353,17 +352,16 @@ NS_IMPL_ISUPPORTS3(RasterImage, imgICont
 
 //******************************************************************************
 RasterImage::RasterImage(imgStatusTracker* aStatusTracker) :
   Image(aStatusTracker), // invoke superclass's constructor
   mSize(0,0),
   mFrameDecodeFlags(DECODE_FLAGS_DEFAULT),
   mAnim(nullptr),
   mLoopCount(-1),
-  mObserver(nullptr),
   mLockCount(0),
   mDecoder(nullptr),
   mDecodeRequest(this),
   mBytesDecoded(0),
   mDecodeCount(0),
 #ifdef DEBUG
   mFramesNotified(0),
 #endif
@@ -434,17 +432,17 @@ RasterImage::Initialize()
   InitPrefCaches();
 
   // Create our singletons now, so we don't have to worry about what thread
   // they're created on.
   DecodeWorker::Singleton();
 }
 
 nsresult
-RasterImage::Init(imgIDecoderObserver *aObserver,
+RasterImage::Init(imgDecoderObserver *aObserver,
                   const char* aMimeType,
                   const char* aURIString,
                   uint32_t aFlags)
 {
   // We don't support re-initialization
   if (mInitialized)
     return NS_ERROR_ILLEGAL_VALUE;
 
@@ -457,17 +455,19 @@ RasterImage::Init(imgIDecoderObserver *a
   // We must be non-discardable and non-decode-on-draw for
   // multipart channels
   NS_ABORT_IF_FALSE(!(aFlags & INIT_FLAG_MULTIPART) ||
                     (!(aFlags & INIT_FLAG_DISCARDABLE) &&
                      !(aFlags & INIT_FLAG_DECODE_ON_DRAW)),
                     "Can't be discardable or decode-on-draw for multipart");
 
   // Store initialization data
-  mObserver = do_GetWeakReference(aObserver);
+  if (aObserver) {
+    mObserver = aObserver->asWeakPtr();
+  }
   mSourceDataMimeType.Assign(aMimeType);
   mURIString.Assign(aURIString);
   mDiscardable = !!(aFlags & INIT_FLAG_DISCARDABLE);
   mDecodeOnDraw = !!(aFlags & INIT_FLAG_DECODE_ON_DRAW);
   mMultipart = !!(aFlags & INIT_FLAG_MULTIPART);
 
   // Statistics
   if (mDiscardable) {
@@ -633,33 +633,31 @@ RasterImage::RequestRefresh(const mozill
     // 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<imgIDecoderObserver> observer(do_QueryReferent(mObserver));
-
-    if (!observer) {
+    if (!mObserver) {
       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
 
     UpdateImageContainer();
-    observer->FrameChanged(&dirtyRect);
+    mObserver->FrameChanged(&dirtyRect);
   }
 }
 
 //******************************************************************************
 /* [noscript] imgIContainer extractFrame(uint32_t aWhichFrame,
  *                                       [const] in nsIntRect aRegion,
  *                                       in uint32_t aFlags); */
 NS_IMETHODIMP
@@ -1655,19 +1653,18 @@ RasterImage::ResetAnimation()
   mAnim->lastCompositedFrameIndex = -1;
   mAnim->currentAnimationFrameIndex = 0;
   UpdateImageContainer();
 
   // Note - We probably want to kick off a redecode somewhere around here when
   // we fix bug 500402.
 
   // Update display if we were animating before
-  nsCOMPtr<imgIDecoderObserver> observer(do_QueryReferent(mObserver));
-  if (mAnimating && observer)
-    observer->FrameChanged(&(mAnim->firstFrameRefreshArea));
+  if (mAnimating && mObserver)
+    mObserver->FrameChanged(&(mAnim->firstFrameRefreshArea));
 
   if (ShouldAnimate()) {
     StartAnimation();
     // The animation may not have been running before, if mAnimationFinished
     // was false (before we changed it to true in this function). So, mark the
     // animation as running.
     mAnimating = true;
   }
@@ -2463,19 +2460,18 @@ RasterImage::Discard(bool force)
   // Clear our downscaled frame.
   mScaleResult.status = SCALE_INVALID;
   mScaleResult.frame = nullptr;
 
   // Flag that we no longer have decoded frames for this image
   mDecoded = false;
 
   // Notify that we discarded
-  nsCOMPtr<imgIDecoderObserver> observer(do_QueryReferent(mObserver));
-  if (observer)
-    observer->OnDiscard();
+  if (mObserver)
+    mObserver->OnDiscard();
 
   if (force)
     DiscardTracker::Remove(&mDiscardTrackerNode);
 
   // Log
   PR_LOG(GetCompressedImageAccountingLog(), PR_LOG_DEBUG,
          ("CompressedImageAccounting: discarded uncompressed image "
           "data from RasterImage %p (%s) - %d frames (cached count: %d); "
@@ -2535,40 +2531,39 @@ RasterImage::InitDecoder(bool aDoSizeDec
 
   // Since we're not decoded, we should not have a discard timer active
   NS_ABORT_IF_FALSE(!DiscardingActive(), "Discard Timer active in InitDecoder()!");
 
   // Figure out which decoder we want
   eDecoderType type = GetDecoderType(mSourceDataMimeType.get());
   CONTAINER_ENSURE_TRUE(type != eDecoderType_unknown, NS_IMAGELIB_ERROR_NO_DECODER);
 
-  nsCOMPtr<imgIDecoderObserver> observer(do_QueryReferent(mObserver));
   // Instantiate the appropriate decoder
   switch (type) {
     case eDecoderType_png:
-      mDecoder = new nsPNGDecoder(*this, observer);
+      mDecoder = new nsPNGDecoder(*this, mObserver);
       break;
     case eDecoderType_gif:
-      mDecoder = new nsGIFDecoder2(*this, observer);
+      mDecoder = new nsGIFDecoder2(*this, mObserver);
       break;
     case eDecoderType_jpeg:
       // If we have all the data we don't want to waste cpu time doing
       // a progressive decode
-      mDecoder = new nsJPEGDecoder(*this, observer,
+      mDecoder = new nsJPEGDecoder(*this, mObserver,
                                    mHasBeenDecoded ? Decoder::SEQUENTIAL :
                                                      Decoder::PROGRESSIVE);
       break;
     case eDecoderType_bmp:
-      mDecoder = new nsBMPDecoder(*this, observer);
+      mDecoder = new nsBMPDecoder(*this, mObserver);
       break;
     case eDecoderType_ico:
-      mDecoder = new nsICODecoder(*this, observer);
+      mDecoder = new nsICODecoder(*this, mObserver);
       break;
     case eDecoderType_icon:
-      mDecoder = new nsIconDecoder(*this, observer);
+      mDecoder = new nsIconDecoder(*this, mObserver);
       break;
     default:
       NS_ABORT_IF_FALSE(0, "Shouldn't get here!");
   }
 
   // Initialize the decoder
   mDecoder->SetSizeDecode(aDoSizeDecode);
   mDecoder->SetDecodeFlags(mFrameDecodeFlags);
@@ -2907,17 +2902,17 @@ void
 RasterImage::ScalingDone(ScaleRequest* request, ScaleStatus status)
 {
   MOZ_ASSERT(status == SCALE_DONE || status == SCALE_INVALID);
   MOZ_ASSERT(request);
 
   if (status == SCALE_DONE) {
     MOZ_ASSERT(request->done);
 
-    nsCOMPtr<imgIDecoderObserver> observer(do_QueryReferent(mObserver));
+    RefPtr<imgDecoderObserver> observer(mObserver);
     if (observer) {
       imgFrame *scaledFrame = request->dstFrame.get();
       scaledFrame->ImageUpdated(scaledFrame->GetRect());
       observer->FrameChanged(&request->srcRect);
     }
 
     mScaleResult.status = SCALE_DONE;
     mScaleResult.frame = request->dstFrame;
--- a/image/src/RasterImage.h
+++ b/image/src/RasterImage.h
@@ -19,32 +19,30 @@
 
 #include "Image.h"
 #include "nsCOMArray.h"
 #include "nsCOMPtr.h"
 #include "imgIContainer.h"
 #include "nsIProperties.h"
 #include "nsITimer.h"
 #include "nsIRequest.h"
-#include "nsWeakReference.h"
 #include "nsTArray.h"
 #include "imgFrame.h"
 #include "nsThreadUtils.h"
 #include "DiscardTracker.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/WeakPtr.h"
 #include "gfx2DGlue.h"
 #ifdef DEBUG
   #include "imgIContainerDebug.h"
 #endif
 
-class imgIDecoder;
 class nsIInputStream;
 
 #define NS_RASTERIMAGE_CID \
 { /* 376ff2c1-9bf6-418a-b143-3340c00112f7 */         \
      0x376ff2c1,                                     \
      0x9bf6,                                         \
      0x418a,                                         \
     {0xb1, 0x43, 0x33, 0x40, 0xc0, 0x01, 0x12, 0xf7} \
@@ -154,17 +152,17 @@ public:
 
   // (no public constructor - use ImageFactory)
   virtual ~RasterImage();
 
   virtual nsresult StartAnimation();
   virtual nsresult StopAnimation();
 
   // Methods inherited from Image
-  nsresult Init(imgIDecoderObserver* aObserver,
+  nsresult Init(imgDecoderObserver* aObserver,
                 const char* aMimeType,
                 const char* aURIString,
                 uint32_t aFlags);
   virtual void  GetCurrentFrameRect(nsIntRect& aRect) MOZ_OVERRIDE;
 
   // Raster-specific methods
   static NS_METHOD WriteToRasterImage(nsIInputStream* aIn, void* aClosure,
                                       const char* aFromRawSegment,
@@ -636,18 +634,17 @@ private: // data
   // IMPORTANT: if you use mAnim in a method, call EnsureImageIsDecoded() first to ensure
   // that the frames actually exist (they may have been discarded to save memory, or
   // we maybe decoding on draw).
   RasterImage::Anim*        mAnim;
   
   //! # loops remaining before animation stops (-1 no stop)
   int32_t                    mLoopCount;
   
-  //! imgIDecoderObserver
-  nsWeakPtr                  mObserver;
+  mozilla::WeakPtr<imgDecoderObserver> mObserver;
 
   // Discard members
   uint32_t                   mLockCount;
   DiscardTracker::Node       mDiscardTrackerNode;
 
   // Source data members
   FallibleTArray<char>       mSourceData;
   nsCString                  mSourceDataMimeType;
--- a/image/src/VectorImage.cpp
+++ b/image/src/VectorImage.cpp
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "VectorImage.h"
 
-#include "imgIDecoderObserver.h"
+#include "imgDecoderObserver.h"
 #include "SVGDocumentWrapper.h"
 #include "gfxContext.h"
 #include "gfxPlatform.h"
 #include "nsPresContext.h"
 #include "nsRect.h"
 #include "nsIObserverService.h"
 #include "nsIPresShell.h"
 #include "nsIStreamListener.h"
@@ -183,30 +183,32 @@ VectorImage::VectorImage(imgStatusTracke
 VectorImage::~VectorImage()
 {
 }
 
 //------------------------------------------------------------------------------
 // Methods inherited from Image.h
 
 nsresult
-VectorImage::Init(imgIDecoderObserver* aObserver,
+VectorImage::Init(imgDecoderObserver* aObserver,
                   const char* aMimeType,
                   const char* aURIString,
                   uint32_t aFlags)
 {
   // We don't support re-initialization
   if (mIsInitialized)
     return NS_ERROR_ILLEGAL_VALUE;
 
   NS_ABORT_IF_FALSE(!mIsFullyLoaded && !mHaveAnimations &&
                     !mHaveRestrictedRegion && !mError,
                     "Flags unexpectedly set before initialization");
 
-  mObserver = do_GetWeakReference(aObserver);
+  if (aObserver) {
+    mObserver = aObserver->asWeakPtr();
+  }
   NS_ABORT_IF_FALSE(!strcmp(aMimeType, SVG_MIMETYPE), "Unexpected mimetype");
 
   mIsInitialized = true;
 
   return NS_OK;
 }
 
 void
@@ -704,17 +706,17 @@ VectorImage::OnStopRequest(nsIRequest* a
 
   mIsFullyLoaded = true;
   mHaveAnimations = mSVGDocumentWrapper->IsAnimated();
 
   // Start listening to our image for rendering updates
   mRenderingObserver = new SVGRootRenderingObserver(mSVGDocumentWrapper, this);
 
   // Tell *our* observers that we're done loading
-  nsCOMPtr<imgIDecoderObserver> observer = do_QueryReferent(mObserver);
+  RefPtr<imgDecoderObserver> observer(mObserver);
   if (observer) {
     // NOTE: This signals that width/height are available.
     observer->OnStartContainer();
 
     observer->FrameChanged(&nsIntRect::GetMaxSizedIntRect());
     observer->OnStopFrame();
     observer->OnStopDecode(NS_OK);
   }
@@ -743,20 +745,17 @@ VectorImage::OnDataAvailable(nsIRequest*
 }
 
 // --------------------------
 // Invalidation helper method
 
 void
 VectorImage::InvalidateObserver()
 {
-  if (!mObserver)
-    return;
-
-  nsCOMPtr<imgIDecoderObserver> obs(do_QueryReferent(mObserver));
-  if (obs) {
-    obs->FrameChanged(&nsIntRect::GetMaxSizedIntRect());
-    obs->OnStopFrame();
+  RefPtr<imgDecoderObserver> observer(mObserver);
+  if (observer) {
+    observer->FrameChanged(&nsIntRect::GetMaxSizedIntRect());
+    observer->OnStopFrame();
   }
 }
 
 } // namespace image
 } // namespace mozilla
--- a/image/src/VectorImage.h
+++ b/image/src/VectorImage.h
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_imagelib_VectorImage_h_
 #define mozilla_imagelib_VectorImage_h_
 
 #include "Image.h"
 #include "nsIStreamListener.h"
 #include "nsIRequest.h"
-#include "nsWeakReference.h"
 #include "mozilla/TimeStamp.h"
+#include "mozilla/WeakPtr.h"
 
-class imgIDecoderObserver;
+class imgDecoderObserver;
 
 namespace mozilla {
 namespace layers {
 class LayerManager;
 class ImageContainer;
 }
 namespace image {
 
@@ -32,17 +32,17 @@ public:
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_IMGICONTAINER
 
   // (no public constructor - use ImageFactory)
   virtual ~VectorImage();
 
   // Methods inherited from Image
-  nsresult Init(imgIDecoderObserver* aObserver,
+  nsresult Init(imgDecoderObserver* aObserver,
                 const char* aMimeType,
                 const char* aURIString,
                 uint32_t aFlags);
   virtual void GetCurrentFrameRect(nsIntRect& aRect) MOZ_OVERRIDE;
 
   virtual size_t HeapSizeOfSourceWithComputedFallback(nsMallocSizeOfFun aMallocSizeOf) const;
   virtual size_t HeapSizeOfDecodedWithComputedFallback(nsMallocSizeOfFun aMallocSizeOf) const;
   virtual size_t NonHeapSizeOfDecoded() const;
@@ -64,17 +64,17 @@ public:
 protected:
   VectorImage(imgStatusTracker* aStatusTracker = nullptr);
 
   virtual nsresult StartAnimation();
   virtual nsresult StopAnimation();
   virtual bool     ShouldAnimate();
 
 private:
-  nsWeakPtr                          mObserver;   //! imgIDecoderObserver
+  WeakPtr<imgDecoderObserver>        mObserver;
   nsRefPtr<SVGDocumentWrapper>       mSVGDocumentWrapper;
   nsRefPtr<SVGRootRenderingObserver> mRenderingObserver;
 
   nsIntRect      mRestrictedRegion;       // If we were created by
                                           // ExtractFrame, this is the region
                                           // that we're restricted to using.
                                           // Otherwise, this is ignored.
 
new file mode 100644
--- /dev/null
+++ b/image/src/imgDecoderObserver.h
@@ -0,0 +1,121 @@
+/** -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZILLA_IMAGELIB_IMGDECODEROBSERVER_H_
+#define MOZILLA_IMAGELIB_IMGDECODEROBSERVER_H_
+
+#include "nsRect.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/WeakPtr.h"
+
+/**
+ * imgDecoderObserver interface
+ *
+ * This interface is used to observe Decoder objects.
+ *
+ * We make the distinction here between "load" and "decode" notifications. Load
+ * notifications are fired as the image is loaded from the network or
+ * filesystem. Decode notifications are fired as the image is decoded. If an
+ * image is decoded on load and not visibly discarded, decode notifications are
+ * nested logically inside load notifications as one might expect. However, with
+ * decode-on-draw, the set of decode notifications can come completely _after_
+ * the load notifications, and can come multiple times if the image is
+ * discardable. Moreover, they can be interleaved in various ways. In general,
+ * any presumed ordering between load and decode notifications should not be
+ * relied upon.
+ *
+ * Decode notifications may or may not be synchronous, depending on the
+ * situation. If imgIDecoder::FLAG_SYNC_DECODE is passed to a function that
+ * triggers a decode, all notifications that can be generated from the currently
+ * loaded data fire before the call returns. If FLAG_SYNC_DECODE is not passed,
+ * all, some, or none of the notifications may fire before the call returns.
+ */
+class imgDecoderObserver : public mozilla::RefCounted<imgDecoderObserver>,
+                           public mozilla::SupportsWeakPtr<imgDecoderObserver>
+{
+public:
+  virtual ~imgDecoderObserver() = 0;
+
+  /**
+   * Load notification.
+   *
+   * called at the same time that nsIRequestObserver::onStartRequest would be
+   * (used only for observers of imgIRequest objects, which are nsIRequests,
+   * not imgIDecoder objects)
+   */
+  virtual void OnStartRequest() = 0;
+
+  /**
+   * Decode notification.
+   *
+   * Called as soon as the image begins getting decoded. This does not include
+   * "header-only" decodes used by decode-on-draw to parse the width/height
+   * out of the image. Thus, it is a decode notification only.
+   */
+  virtual void OnStartDecode() = 0;
+
+  /**
+   * Load notification.
+   *
+   * Called once enough data has been loaded from the network that we were able
+   * to parse the width/height from the image. By the time this callback is been
+   * called, the size has been set on the container and STATUS_SIZE_AVAILABLE
+   * has been set on the associated imgRequest.
+   */
+  virtual void OnStartContainer() = 0;
+
+  /**
+   * Decode notification.
+   *
+   * called when there is more to paint.
+   */
+  virtual void OnDataAvailable(const nsIntRect * aRect) = 0;
+
+  virtual void FrameChanged(const nsIntRect * aDirtyRect) = 0;
+
+  /**
+   * Decode notification.
+   *
+   * called when a frame is finished decoding.
+   */
+  virtual void OnStopFrame() = 0;
+
+  /**
+   * Notification for when an image is known to be animated. This should be
+   * fired at the earliest possible time.
+   */
+  virtual void OnImageIsAnimated() = 0;
+
+  /**
+   * Decode notification.
+   *
+   * Called when all decoding has terminated.
+   */
+  virtual void OnStopDecode(nsresult status) = 0;
+
+  /**
+   * Load notification.
+   *
+   * called at the same time that nsIRequestObserver::onStopRequest would be
+   * (used only for observers of imgIRequest objects, which are nsIRequests,
+   * not imgIDecoder objects)
+   */
+  virtual void OnStopRequest(bool aIsLastPart) = 0;
+
+  /**
+   * Called when the decoded image data is discarded. This means that the frames
+   * no longer exist in decoded form, and any attempt to access or draw the
+   * image will initiate a new series of progressive decode notifications.
+   */
+  virtual void OnDiscard() = 0;
+};
+
+// We must define a destructor because derived classes call our destructor from
+// theirs.  Pure virtual destructors only requires that child classes implement
+// a virtual destructor, not that we can't have one too!
+inline imgDecoderObserver::~imgDecoderObserver()
+{}
+
+#endif // MOZILLA_IMAGELIB_IMGDECODEROBSERVER_H
--- a/image/src/imgRequestProxy.cpp
+++ b/image/src/imgRequestProxy.cpp
@@ -672,17 +672,17 @@ NS_IMETHODIMP imgRequestProxy::GetHasTra
     *hasData = GetOwner()->HasTransferredData();
   } else {
     // The safe thing to do is to claim we have data
     *hasData = true;
   }
   return NS_OK;
 }
 
-/** imgIDecoderObserver methods **/
+/** imgDecoderObserver methods **/
 
 void imgRequestProxy::OnStartContainer()
 {
   LOG_FUNC(GetImgLog(), "imgRequestProxy::OnStartContainer");
 
   if (mListener && !mCanceled && !mSentStartContainer) {
     // Hold a ref to the listener while we call it, just in case.
     nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener);
--- a/image/src/imgRequestProxy.h
+++ b/image/src/imgRequestProxy.h
@@ -130,17 +130,17 @@ protected:
       nsRefPtr<imgRequestProxy> mOwner;
       nsresult mStatus;
   };
 
   // The following notification functions are protected to ensure that (friend
   // class) imgStatusTracker is the only class allowed to send us
   // notifications.
 
-  /* non-virtual imgIDecoderObserver methods */
+  /* non-virtual imgDecoderObserver methods */
   void OnStartContainer  ();
   void OnFrameUpdate     (const nsIntRect * aRect);
   void OnStopFrame       ();
   void OnStopDecode      ();
   void OnDiscard         ();
   void OnImageIsAnimated ();
 
   /* non-virtual sort-of-nsIRequestObserver methods */
--- a/image/src/imgStatusTracker.cpp
+++ b/image/src/imgStatusTracker.cpp
@@ -4,247 +4,216 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "imgStatusTracker.h"
 
 #include "imgRequest.h"
 #include "imgIContainer.h"
 #include "imgRequestProxy.h"
-#include "imgIDecoderObserver.h"
+#include "imgDecoderObserver.h"
 #include "Image.h"
 #include "ImageLogging.h"
 #include "RasterImage.h"
 #include "nsIObserverService.h"
 
 #include "mozilla/Util.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Services.h"
 
 using namespace mozilla::image;
 
-class imgStatusTrackerObserver : public imgIDecoderObserver,
-                                 public nsSupportsWeakReference
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_IMGIDECODEROBSERVER
-
-  imgStatusTrackerObserver(imgStatusTracker* aTracker)
-  : mTracker(aTracker) {}
-
-  virtual ~imgStatusTrackerObserver() {}
-
-  void SetTracker(imgStatusTracker* aTracker) {
-    mTracker = aTracker;
-  }
-
-private:
-  imgStatusTracker* mTracker;
-};
-
-NS_IMPL_ISUPPORTS2(imgStatusTrackerObserver,
-                   imgIDecoderObserver,
-                   nsISupportsWeakReference)
-
-/** imgIDecoderObserver methods **/
-
-NS_IMETHODIMP imgStatusTrackerObserver::OnStartDecode()
-{
-  LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::OnStartDecode");
-  NS_ABORT_IF_FALSE(mTracker->GetImage(),
-                    "OnStartDecode callback before we've created our image");
-
-  if (mTracker->GetRequest() && !mTracker->GetRequest()->GetMultipart()) {
-    MOZ_ASSERT(!mTracker->mBlockingOnload);
-    mTracker->mBlockingOnload = true;
-
-    mTracker->RecordBlockOnload();
-
-    nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
-    while (iter.HasMore()) {
-      mTracker->SendBlockOnload(iter.GetNext());
-    }
-  }
-
-  /* In the case of streaming jpegs, it is possible to get multiple OnStartDecodes which
-     indicates the beginning of a new decode.
-     The cache entry's size therefore needs to be reset to 0 here.  If we do not do this,
-     the code in imgStatusTrackerObserver::OnStopFrame will continue to increase the data size cumulatively.
-  */
-  if (mTracker->GetRequest()) {
-    mTracker->GetRequest()->ResetCacheEntry();
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP imgStatusTrackerObserver::OnStartRequest()
-{
-  NS_NOTREACHED("imgRequest(imgIDecoderObserver)::OnStartRequest");
-  return NS_OK;
-}
-
-/* void onStartContainer (); */
-NS_IMETHODIMP imgStatusTrackerObserver::OnStartContainer()
-{
-  LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::OnStartContainer");
-
-  NS_ABORT_IF_FALSE(mTracker->GetImage(),
-                    "OnStartContainer callback before we've created our image");
-  mTracker->RecordStartContainer(mTracker->GetImage());
-
-  nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
-  while (iter.HasMore()) {
-    mTracker->SendStartContainer(iter.GetNext());
-  }
-
-  return NS_OK;
-}
-
-/* [noscript] void onDataAvailable ([const] in nsIntRect rect); */
-NS_IMETHODIMP imgStatusTrackerObserver::OnDataAvailable(const nsIntRect * rect)
-{
-  LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::OnDataAvailable");
-  NS_ABORT_IF_FALSE(mTracker->GetImage(),
-                    "OnDataAvailable callback before we've created our image");
-
-  mTracker->RecordDataAvailable();
-
-  nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
-  while (iter.HasMore()) {
-    mTracker->SendDataAvailable(iter.GetNext(), rect);
-  }
-
-  return NS_OK;
-}
-
-/* [noscript] void frameChanged (in nsIntRect dirtyRect); */
-NS_IMETHODIMP imgStatusTrackerObserver::FrameChanged(const nsIntRect *dirtyRect)
-{
-  LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::FrameChanged");
-  NS_ABORT_IF_FALSE(mTracker->GetImage(),
-                    "FrameChanged callback before we've created our image");
-
-  mTracker->RecordFrameChanged(dirtyRect);
-
-  nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
-  while (iter.HasMore()) {
-    mTracker->SendFrameChanged(iter.GetNext(), dirtyRect);
-  }
-
-  return NS_OK;
-}
-
-/* void onStopFrame (); */
-NS_IMETHODIMP imgStatusTrackerObserver::OnStopFrame()
-{
-  LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::OnStopFrame");
-  NS_ABORT_IF_FALSE(mTracker->GetImage(),
-                    "OnStopFrame callback before we've created our image");
-
-  mTracker->RecordStopFrame();
-
-  nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
-  while (iter.HasMore()) {
-    mTracker->SendStopFrame(iter.GetNext());
-  }
-
-  mTracker->MaybeUnblockOnload();
-
-  return NS_OK;
-}
-
 static void
 FireFailureNotification(imgRequest* aRequest)
 {
   // Some kind of problem has happened with image decoding.
   // Report the URI to net:failed-to-process-uri-conent observers.
 
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   if (os) {
     nsCOMPtr<nsIURI> uri;
     aRequest->GetURI(getter_AddRefs(uri));
     os->NotifyObservers(uri, "net:failed-to-process-uri-content", nullptr);
   }
 }
 
-/* void onStopDecode (in nsresult status); */
-NS_IMETHODIMP imgStatusTrackerObserver::OnStopDecode(nsresult aStatus)
+class imgStatusTrackerObserver : public imgDecoderObserver
 {
-  LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::OnStopDecode");
-  NS_ABORT_IF_FALSE(mTracker->GetImage(),
-                    "OnStopDecode callback before we've created our image");
+public:
+  imgStatusTrackerObserver(imgStatusTracker* aTracker)
+  : mTracker(aTracker) {}
 
-  // We finished the decode, and thus have the decoded frames. Update the cache
-  // entry size to take this into account.
-  if (mTracker->GetRequest()) {
-    mTracker->GetRequest()->UpdateCacheEntrySize();
+  virtual ~imgStatusTrackerObserver() {}
+
+  void SetTracker(imgStatusTracker* aTracker) {
+    mTracker = aTracker;
   }
 
-  bool preexistingError = mTracker->GetImageStatus() == imgIRequest::STATUS_ERROR;
+  /** imgDecoderObserver methods **/
 
-  mTracker->RecordStopDecode(aStatus);
+  virtual void OnStartDecode()
+  {
+    LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::OnStartDecode");
+    NS_ABORT_IF_FALSE(mTracker->GetImage(),
+                      "OnStartDecode callback before we've created our image");
+
+    if (mTracker->GetRequest() && !mTracker->GetRequest()->GetMultipart()) {
+      MOZ_ASSERT(!mTracker->mBlockingOnload);
+      mTracker->mBlockingOnload = true;
+
+      mTracker->RecordBlockOnload();
 
-  nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
-  while (iter.HasMore()) {
-    mTracker->SendStopDecode(iter.GetNext(), aStatus);
+      nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
+      while (iter.HasMore()) {
+        mTracker->SendBlockOnload(iter.GetNext());
+      }
+    }
+
+    /* In the case of streaming jpegs, it is possible to get multiple OnStartDecodes which
+       indicates the beginning of a new decode.
+       The cache entry's size therefore needs to be reset to 0 here.  If we do not do this,
+       the code in imgStatusTrackerObserver::OnStopFrame will continue to increase the data size cumulatively.
+    */
+    if (mTracker->GetRequest()) {
+      mTracker->GetRequest()->ResetCacheEntry();
+    }
   }
 
-  // This is really hacky. We need to handle the case where we start decoding,
-  // block onload, but then hit an error before we get to our first frame.
-  mTracker->MaybeUnblockOnload();
+  virtual void OnStartRequest()
+  {
+    NS_NOTREACHED("imgRequest(imgDecoderObserver)::OnStartRequest");
+  }
+
+  virtual void OnStartContainer()
+  {
+    LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::OnStartContainer");
+
+    NS_ABORT_IF_FALSE(mTracker->GetImage(),
+                      "OnStartContainer callback before we've created our image");
+    mTracker->RecordStartContainer(mTracker->GetImage());
 
-  if (NS_FAILED(aStatus) && !preexistingError && mTracker->GetRequest()) {
-    FireFailureNotification(mTracker->GetRequest());
+    nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
+    while (iter.HasMore()) {
+      mTracker->SendStartContainer(iter.GetNext());
+    }
+  }
+
+  virtual void OnDataAvailable(const nsIntRect* rect)
+  {
+    LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::OnDataAvailable");
+    NS_ABORT_IF_FALSE(mTracker->GetImage(),
+                      "OnDataAvailable callback before we've created our image");
+
+    mTracker->RecordDataAvailable();
+
+    nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
+    while (iter.HasMore()) {
+      mTracker->SendDataAvailable(iter.GetNext(), rect);
+    }
   }
 
-  return NS_OK;
-}
+  virtual void FrameChanged(const nsIntRect* dirtyRect)
+  {
+    LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::FrameChanged");
+    NS_ABORT_IF_FALSE(mTracker->GetImage(),
+                      "FrameChanged callback before we've created our image");
 
-NS_IMETHODIMP imgStatusTrackerObserver::OnStopRequest(bool aLastPart)
-{
-  NS_NOTREACHED("imgRequest(imgIDecoderObserver)::OnStopRequest");
-  return NS_OK;
-}
+    mTracker->RecordFrameChanged(dirtyRect);
+
+    nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
+    while (iter.HasMore()) {
+      mTracker->SendFrameChanged(iter.GetNext(), dirtyRect);
+    }
+  }
 
-/* void onDiscard (); */
-NS_IMETHODIMP imgStatusTrackerObserver::OnDiscard()
-{
-  NS_ABORT_IF_FALSE(mTracker->GetImage(),
-                    "OnDiscard callback before we've created our image");
+  virtual void OnStopFrame()
+  {
+    LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::OnStopFrame");
+    NS_ABORT_IF_FALSE(mTracker->GetImage(),
+                      "OnStopFrame callback before we've created our image");
 
-  mTracker->RecordDiscard();
+    mTracker->RecordStopFrame();
 
-  // Update the cache entry size, since we just got rid of frame data
-  if (mTracker->GetRequest()) {
-    mTracker->GetRequest()->UpdateCacheEntrySize();
+    nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
+    while (iter.HasMore()) {
+      mTracker->SendStopFrame(iter.GetNext());
+    }
+
+    mTracker->MaybeUnblockOnload();
   }
 
-  nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
-  while (iter.HasMore()) {
-    mTracker->SendDiscard(iter.GetNext());
+  virtual void OnStopDecode(nsresult aStatus)
+  {
+    LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::OnStopDecode");
+    NS_ABORT_IF_FALSE(mTracker->GetImage(),
+                      "OnStopDecode callback before we've created our image");
+
+    // We finished the decode, and thus have the decoded frames. Update the cache
+    // entry size to take this into account.
+    if (mTracker->GetRequest()) {
+      mTracker->GetRequest()->UpdateCacheEntrySize();
+    }
+
+    bool preexistingError = mTracker->GetImageStatus() == imgIRequest::STATUS_ERROR;
+
+    mTracker->RecordStopDecode(aStatus);
+
+    nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
+    while (iter.HasMore()) {
+      mTracker->SendStopDecode(iter.GetNext(), aStatus);
+    }
+
+    // This is really hacky. We need to handle the case where we start decoding,
+    // block onload, but then hit an error before we get to our first frame.
+    mTracker->MaybeUnblockOnload();
+
+    if (NS_FAILED(aStatus) && !preexistingError && mTracker->GetRequest()) {
+      FireFailureNotification(mTracker->GetRequest());
+    }
+  }
+
+  virtual void OnStopRequest(bool aLastPart)
+  {
+    NS_NOTREACHED("imgRequest(imgDecoderObserver)::OnStopRequest");
   }
 
-  return NS_OK;
-}
+  virtual void OnDiscard()
+  {
+    NS_ABORT_IF_FALSE(mTracker->GetImage(),
+                      "OnDiscard callback before we've created our image");
+
+    mTracker->RecordDiscard();
 
-NS_IMETHODIMP imgStatusTrackerObserver::OnImageIsAnimated()
-{
-  NS_ABORT_IF_FALSE(mTracker->GetImage(),
-                    "OnImageIsAnimated callback before we've created our image");
-  mTracker->RecordImageIsAnimated();
+    // Update the cache entry size, since we just got rid of frame data
+    if (mTracker->GetRequest()) {
+      mTracker->GetRequest()->UpdateCacheEntrySize();
+    }
 
-  nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
-  while (iter.HasMore()) {
-    mTracker->SendImageIsAnimated(iter.GetNext());
+    nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
+    while (iter.HasMore()) {
+      mTracker->SendDiscard(iter.GetNext());
+    }
   }
 
-  return NS_OK;
-}
+  virtual void OnImageIsAnimated()
+  {
+    NS_ABORT_IF_FALSE(mTracker->GetImage(),
+                      "OnImageIsAnimated callback before we've created our image");
+    mTracker->RecordImageIsAnimated();
+
+    nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
+    while (iter.HasMore()) {
+      mTracker->SendImageIsAnimated(iter.GetNext());
+    }
+  }
+
+private:
+  imgStatusTracker* mTracker;
+};
+
 
 // imgStatusTracker methods
 
 imgStatusTracker::imgStatusTracker(Image* aImage, imgRequest* aRequest)
   : mImage(aImage),
     mRequest(aRequest),
     mState(0),
     mImageStatus(imgIRequest::STATUS_NONE),
--- a/image/src/imgStatusTracker.h
+++ b/image/src/imgStatusTracker.h
@@ -21,18 +21,17 @@ class Image;
 } // namespace mozilla
 
 
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsTObserverArray.h"
 #include "nsIRunnable.h"
 #include "nscore.h"
-#include "nsWeakReference.h"
-#include "imgIDecoderObserver.h"
+#include "imgDecoderObserver.h"
 
 enum {
   stateRequestStarted    = 1u << 0,
   stateHasSize           = 1u << 1,
   stateDecodeStopped     = 1u << 3,
   stateFrameStopped      = 1u << 4,
   stateRequestStopped    = 1u << 5,
   stateBlockingOnload    = 1u << 6
@@ -122,17 +121,17 @@ public:
   // Shorthand for recording all the load notifications: StartRequest,
   // StartContainer, StopRequest.
   void RecordLoaded();
 
   // Shorthand for recording all the decode notifications: StartDecode,
   // StartFrame, DataAvailable, StopFrame, StopDecode.
   void RecordDecoded();
 
-  /* non-virtual imgIDecoderObserver methods */
+  /* non-virtual imgDecoderObserver methods */
   void RecordStartContainer(imgIContainer* aContainer);
   void SendStartContainer(imgRequestProxy* aProxy);
   void RecordDataAvailable();
   void SendDataAvailable(imgRequestProxy* aProxy, const nsIntRect* aRect);
   void RecordFrameChanged(const nsIntRect* aDirtyRect);
   void SendFrameChanged(imgRequestProxy* aProxy, const nsIntRect* aDirtyRect);
   void RecordStopFrame();
   void SendStopFrame(imgRequestProxy* aProxy);
@@ -166,17 +165,17 @@ public:
 
   // Null out any reference to an associated image request
   void ClearRequest();
 
   // Weak pointer getters - no AddRefs.
   inline mozilla::image::Image* GetImage() const { return mImage; }
   inline imgRequest* GetRequest() const { return mRequest; }
 
-  inline imgIDecoderObserver* GetDecoderObserver() { return mTrackerObserver.get(); }
+  inline imgDecoderObserver* GetDecoderObserver() { return mTrackerObserver.get(); }
 
 private:
   friend class imgStatusNotifyRunnable;
   friend class imgRequestNotifyRunnable;
   friend class imgStatusTrackerObserver;
 
   nsCOMPtr<nsIRunnable> mRequestRunnable;
 
@@ -188,12 +187,12 @@ private:
   uint32_t mImageStatus;
   bool mHadLastPart;
   bool mBlockingOnload;
 
   // List of proxies attached to the image. Each proxy represents a consumer
   // using the image.
   nsTObserverArray<imgRequestProxy*> mConsumers;
 
-  nsRefPtr<imgIDecoderObserver> mTrackerObserver;
+  mozilla::RefPtr<imgDecoderObserver> mTrackerObserver;
 };
 
 #endif
--- a/image/src/imgTools.cpp
+++ b/image/src/imgTools.cpp
@@ -7,17 +7,16 @@
 #include "imgTools.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsError.h"
 #include "imgLoader.h"
 #include "imgICache.h"
 #include "imgIContainer.h"
 #include "imgIEncoder.h"
-#include "imgIDecoderObserver.h"
 #include "gfxContext.h"
 #include "nsStringStream.h"
 #include "nsComponentManagerUtils.h"
 #include "nsWeakReference.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsStreamUtils.h"
 #include "nsNetUtil.h"
 #include "nsContentUtils.h"
--- a/image/test/browser/head.js
+++ b/image/test/browser/head.js
@@ -19,19 +19,8 @@ function actOnMozImage(doc, id, func) {
     mozImage = imgContainer.QueryInterface(Ci.imgIContainerDebug);
   }
   catch (e) {
     return false;
   }
   func(mozImage);
   return true;
 }
-
-function awaitImageContainer(doc, id, func) {
-  getImageLoading(doc, id).addObserver({
-    QueryInterface: XPCOMUtils.generateQI([Ci.imgIDecoderObserver]),
-    onStartContainer: function(aRequest, aContainer) {
-      getImageLoading(doc, id).removeObserver(this);
-      func(aContainer);
-    },
-  });
-}
-
--- a/image/test/unit/async_load_tests.js
+++ b/image/test/unit/async_load_tests.js
@@ -121,19 +121,19 @@ function getChannelLoadImageStartCallbac
   }
 }
 
 // Return a closure that allows us to check the stream listener's status when the
 // image finishes loading.
 function getChannelLoadImageStopCallback(streamlistener, next)
 {
   return function channelLoadStop(imglistener, aRequest) {
-    // We absolutely must not get imgIDecoderObserver::onStopRequest after
-    // nsIRequestObserver::onStopRequest has fired. If we do that, we've broken
-    // people's expectations by delaying events from a channel we were given.
+    // We absolutely must not get imgIScriptedNotificationObserver::onStopRequest
+    // after nsIRequestObserver::onStopRequest has fired. If we do that, we've
+    // broken people's expectations by delaying events from a channel we were given.
     do_check_eq(streamlistener.requestStatus & STOP_REQUEST, 0);
 
     next();
 
     do_test_finished();
   }
 }
 
--- a/image/test/unit/image_load_helpers.js
+++ b/image/test/unit/image_load_helpers.js
@@ -12,18 +12,18 @@ const DATA_AVAILABLE = 0x04;
 // ImageListener.state.
 const SIZE_AVAILABLE = 0x01;
 const FRAME_UPDATE = 0x02;
 const FRAME_COMPLETE = 0x04;
 const LOAD_COMPLETE = 0x08;
 const DECODE_COMPLETE = 0x10;
 const ALL_BITS = SIZE_AVAILABLE | FRAME_COMPLETE | DECODE_COMPLETE | LOAD_COMPLETE;
 
-// An implementation of imgIDecoderObserver with the ability to call specified
-// functions on onStartRequest and onStopRequest.
+// An implementation of imgIScriptedNotificationObserver with the ability to
+// call specified functions on onStartRequest and onStopRequest.
 function ImageListener(start_callback, stop_callback)
 {
   this.sizeAvailable = function onSizeAvailable(aRequest)
   {
     do_check_false(this.synchronous);
 
     this.state |= SIZE_AVAILABLE;
 
--- a/layout/generic/nsBulletFrame.h
+++ b/layout/generic/nsBulletFrame.h
@@ -8,17 +8,16 @@
 #ifndef nsBulletFrame_h___
 #define nsBulletFrame_h___
 
 #include "mozilla/Attributes.h"
 #include "nsFrame.h"
 #include "nsStyleContext.h"
 
 #include "imgIRequest.h"
-#include "imgIDecoderObserver.h"
 #include "imgINotificationObserver.h"
 
 class imgRequestProxy;
 
 #define BULLET_FRAME_IMAGE_LOADING NS_FRAME_STATE_BIT(63)
 #define BULLET_FRAME_HAS_FONT_INFLATION NS_FRAME_STATE_BIT(62)
 
 class nsBulletFrame;
--- a/widget/cocoa/nsMenuItemIconX.mm
+++ b/widget/cocoa/nsMenuItemIconX.mm
@@ -69,17 +69,17 @@ nsMenuItemIconX::nsMenuItemIconX(nsMenuO
 
 nsMenuItemIconX::~nsMenuItemIconX()
 {
   if (mIconRequest)
     mIconRequest->CancelAndForgetObserver(NS_BINDING_ABORTED);
 }
 
 // Called from mMenuObjectX's destructor, to prevent us from outliving it
-// (as might otherwise happen if calls to our imgIDecoderObserver methods
+// (as might otherwise happen if calls to our imgINotificationObserver methods
 // are still outstanding).  mMenuObjectX owns our nNativeMenuItem.
 void nsMenuItemIconX::Destroy()
 {
   if (mIconRequest) {
     mIconRequest->CancelAndForgetObserver(NS_BINDING_ABORTED);
     mIconRequest = nullptr;
   }
   mMenuObject = nullptr;
--- a/widget/gtk2/nsImageToPixbuf.cpp
+++ b/widget/gtk2/nsImageToPixbuf.cpp
@@ -37,17 +37,17 @@ GdkPixbuf*
 nsImageToPixbuf::ImageToPixbuf(imgIContainer* aImage)
 {
     nsRefPtr<gfxImageSurface> frame;
     nsresult rv = aImage->CopyFrame(imgIContainer::FRAME_CURRENT,
                                     imgIContainer::FLAG_SYNC_DECODE,
                                     getter_AddRefs(frame));
 
     // If the last call failed, it was probably because our call stack originates
-    // in an imgIDecoderObserver event, meaning that we're not allowed request
+    // in an imgINotificationObserver event, meaning that we're not allowed request
     // a sync decode. Presumably the originating event is something sensible like
     // OnStopFrame(), so we can just retry the call without a sync decode.
     if (NS_FAILED(rv))
         aImage->CopyFrame(imgIContainer::FRAME_CURRENT,
                           imgIContainer::FLAG_NONE,
                           getter_AddRefs(frame));
 
     if (!frame)