Bug 984786 part 8: Give NS_INLINE_DECL_*REFCOUNTING classes private destructor & MOZ_FINAL annotation where appropriate, in /gfx and /content/canvas. r=bjacob
authorDaniel Holbert <dholbert@cs.stanford.edu>
Fri, 04 Apr 2014 09:27:02 -0700
changeset 189177 50e3d7132fa9ebd99ace0aef3179ad032333b5af
parent 189138 fcd79d6f4a7e4b4c0004952c692cbdee0fef0b2a
child 189178 9ed8b82d0548471717136cd8bcdda31ad9b7176d
push id5832
push userraliiev@mozilla.com
push dateMon, 28 Apr 2014 18:43:22 +0000
treeherdermozilla-aurora@4974d9da2f7d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbjacob
bugs984786
milestone31.0a1
Bug 984786 part 8: Give NS_INLINE_DECL_*REFCOUNTING classes private destructor & MOZ_FINAL annotation where appropriate, in /gfx and /content/canvas. r=bjacob
content/canvas/src/WebGLActiveInfo.h
content/canvas/src/WebGLShaderPrecisionFormat.h
gfx/gl/GLTextureImage.h
gfx/gl/TextureGarbageBin.h
gfx/layers/ImageContainer.h
gfx/layers/Layers.h
gfx/layers/composite/APZCTreeManager.h
gfx/layers/d3d9/DeviceManagerD3D9.h
gfx/layers/ipc/AsyncPanZoomController.h
gfx/layers/ipc/CompositorChild.h
gfx/layers/ipc/CompositorParent.cpp
gfx/layers/ipc/CompositorParent.h
gfx/layers/ipc/GeckoContentController.h
gfx/layers/ipc/GestureEventListener.h
gfx/layers/opengl/Composer2D.h
gfx/src/nsDeviceContext.h
gfx/src/nsFontMetrics.h
gfx/thebes/gfxDrawable.h
gfx/thebes/gfxFont.h
gfx/thebes/gfxFontFeatures.h
gfx/thebes/gfxFontInfoLoader.h
gfx/thebes/gfxPangoFonts.cpp
gfx/thebes/gfxPattern.h
gfx/thebes/gfxReusableSurfaceWrapper.h
gfx/thebes/gfxUserFontSet.h
gfx/thebes/nsSurfaceTexture.h
layout/style/nsFontFaceLoader.h
--- a/content/canvas/src/WebGLActiveInfo.h
+++ b/content/canvas/src/WebGLActiveInfo.h
@@ -34,17 +34,22 @@ public:
     void GetName(nsString& retval) const {
         retval = mName;
     }
 
     JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> scope);
 
    NS_INLINE_DECL_REFCOUNTING(WebGLActiveInfo)
 
-protected:
+private:
+    // Private destructor, to discourage deletion outside of Release():
+    ~WebGLActiveInfo()
+    {
+    }
+
     GLint mSize;
     GLenum mType;
     nsString mName;
 };
 
 } // namespace mozilla
 
 #endif
--- a/content/canvas/src/WebGLShaderPrecisionFormat.h
+++ b/content/canvas/src/WebGLShaderPrecisionFormat.h
@@ -34,17 +34,22 @@ public:
         return mRangeMax;
     }
     GLint Precision() const {
         return mPrecision;
     }
 
     NS_INLINE_DECL_REFCOUNTING(WebGLShaderPrecisionFormat)
 
-protected:
+private:
+    // Private destructor, to discourage deletion outside of Release():
+    ~WebGLShaderPrecisionFormat()
+    {
+    }
+
     GLint mRangeMin;
     GLint mRangeMax;
     GLint mPrecision;
 };
 
 } // namespace mozilla
 
 #endif
--- a/gfx/gl/GLTextureImage.h
+++ b/gfx/gl/GLTextureImage.h
@@ -74,18 +74,16 @@ public:
     // Moz2D equivalent...
     static already_AddRefed<TextureImage> Create(
                        GLContext* gl,
                        const gfx::IntSize& aSize,
                        TextureImage::ContentType aContentType,
                        GLenum aWrapMode,
                        TextureImage::Flags aFlags = TextureImage::NoFlags);
 
-    virtual ~TextureImage() {}
-
     /**
      * Returns a gfxASurface for updating |aRegion| of the client's
      * image if successul, nullptr if not.  |aRegion|'s bounds must fit
      * within Size(); its coordinate space (if any) is ignored.  If
      * the update begins successfully, the returned gfxASurface is
      * owned by this.  Otherwise, nullptr is returned.
      *
      * |aRegion| is an inout param: the returned region is what the
@@ -232,16 +230,19 @@ protected:
         , mFlags(aFlags)
     {}
 
     // Moz2D equivalent...
     TextureImage(const gfx::IntSize& aSize,
                  GLenum aWrapMode, ContentType aContentType,
                  Flags aFlags = NoFlags);
 
+    // Protected destructor, to discourage deletion outside of Release():
+    virtual ~TextureImage() {}
+
     virtual gfx::IntRect GetSrcTileRect();
 
     gfx::IntSize mSize;
     GLenum mWrapMode;
     ContentType mContentType;
     ImageFormat mImageFormat;
     gfx::SurfaceFormat mTextureFormat;
     GraphicsFilter mFilter;
--- a/gfx/gl/TextureGarbageBin.h
+++ b/gfx/gl/TextureGarbageBin.h
@@ -12,20 +12,25 @@
 #include "mozilla/Mutex.h"
 #include "nsISupportsImpl.h"
 
 #include "GLContextTypes.h"
 
 namespace mozilla {
 namespace gl {
 
-class TextureGarbageBin {
+class TextureGarbageBin MOZ_FINAL {
     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureGarbageBin)
 
-protected:
+private:
+    // Private destructor, to discourage deletion outside of Release():
+    ~TextureGarbageBin()
+    {
+    }
+
     GLContext* mGL;
     Mutex mMutex;
     std::stack<GLuint> mGarbageTextures;
 
 public:
     TextureGarbageBin(GLContext* gl)
         : mGL(gl)
         , mMutex("TextureGarbageBin mutex")
--- a/gfx/layers/ImageContainer.h
+++ b/gfx/layers/ImageContainer.h
@@ -184,18 +184,16 @@ public:
  * 
  * When resampling an Image, only pixels within the buffer should be
  * sampled. For example, cairo images should be sampled in EXTEND_PAD mode.
  */
 class Image {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Image)
 
 public:
-  virtual ~Image() {}
-
   virtual ISharedImage* AsSharedImage() { return nullptr; }
 
   ImageFormat GetFormat() { return mFormat; }
   void* GetImplData() { return mImplData; }
 
   virtual already_AddRefed<gfxASurface> DeprecatedGetAsSurface() = 0;
   virtual gfx::IntSize GetSize() = 0;
   virtual nsIntRect GetPictureRect()
@@ -218,47 +216,55 @@ public:
 protected:
   Image(void* aImplData, ImageFormat aFormat) :
     mImplData(aImplData),
     mSerial(++sSerialCounter),
     mFormat(aFormat),
     mSent(false)
   {}
 
+  // Protected destructor, to discourage deletion outside of Release():
+  virtual ~Image() {}
+
   nsAutoPtr<ImageBackendData> mBackendData[size_t(mozilla::layers::LayersBackend::LAYERS_LAST)];
 
   void* mImplData;
   int32_t mSerial;
   ImageFormat mFormat;
   static mozilla::Atomic<int32_t> sSerialCounter;
   bool mSent;
 };
 
 /**
  * A RecycleBin is owned by an ImageContainer. We store buffers in it that we
  * want to recycle from one image to the next.It's a separate object from 
  * ImageContainer because images need to store a strong ref to their RecycleBin
  * and we must avoid creating a reference loop between an ImageContainer and
  * its active image.
  */
-class BufferRecycleBin {
+class BufferRecycleBin MOZ_FINAL {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RecycleBin)
 
   //typedef mozilla::gl::GLContext GLContext;
 
 public:
   BufferRecycleBin();
 
   void RecycleBuffer(uint8_t* aBuffer, uint32_t aSize);
   // Returns a recycled buffer of the right size, or allocates a new buffer.
   uint8_t* GetBuffer(uint32_t aSize);
 
 private:
   typedef mozilla::Mutex Mutex;
 
+  // Private destructor, to discourage deletion outside of Release():
+  ~BufferRecycleBin()
+  {
+  }
+
   // This protects mRecycledBuffers, mRecycledBufferSize, mRecycledTextures
   // and mRecycledTextureSizes
   Mutex mLock;
 
   // We should probably do something to prune this list on a timer so we don't
   // eat excess memory while video is paused...
   nsTArray<nsAutoArrayPtr<uint8_t> > mRecycledBuffers;
   // This is only valid if mRecycledBuffers is non-empty
@@ -375,27 +381,25 @@ struct RemoteImageData {
  * a layer transaction.
  * 3) Remote. Initiated by calling SetRemoteImageData on the ImageContainer
  * before any other activity.
  * The ImageContainer uses a shared memory block containing a cross-process mutex
  * to communicate with the compositor thread. SetCurrentImage synchronously
  * updates the shared state to point to the new image and the old image
  * is immediately released (not true in Normal or Asynchronous modes).
  */
-class ImageContainer : public SupportsWeakPtr<ImageContainer> {
+class ImageContainer MOZ_FINAL : public SupportsWeakPtr<ImageContainer> {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageContainer)
 public:
   MOZ_DECLARE_REFCOUNTED_TYPENAME(ImageContainer)
 
   enum { DISABLE_ASYNC = 0x0, ENABLE_ASYNC = 0x01 };
 
   ImageContainer(int flag = 0);
 
-  ~ImageContainer();
-
   /**
    * Create an Image in one of the given formats.
    * Picks the "best" format from the list and creates an Image of that
    * format.
    * Returns null if this backend does not support any of the formats.
    * Can be called on any thread. This method takes mReentrantMonitor
    * when accessing thread-shared state.
    */
@@ -625,19 +629,22 @@ public:
    */
   void SetRemoteImageData(RemoteImageData *aRemoteData,
                           CrossProcessMutex *aRemoteDataMutex);
   /**
    * This can be used to check if the container has RemoteData set.
    */
   RemoteImageData *GetRemoteImageData() { return mRemoteData; }
 
-protected:
+private:
   typedef mozilla::ReentrantMonitor ReentrantMonitor;
 
+  // Private destructor, to discourage deletion outside of Release():
+  ~ImageContainer();
+
   void SetCurrentImageInternal(Image* aImage);
 
   // This is called to ensure we have an active image, this may not be true
   // when we're storing image information in a RemoteImageData structure.
   // NOTE: If we have remote data mRemoteDataMutex should be locked when
   // calling this function!
   void EnsureActiveImage();
 
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -169,17 +169,16 @@ public:
   LayerManager()
     : mDestroyed(false)
     , mSnapEffectiveTransforms(true)
     , mId(0)
     , mInTransaction(false)
   {
     InitLog();
   }
-  virtual ~LayerManager() {}
 
   /**
    * Release layers and resources held by this layer manager, and mark
    * it as destroyed.  Should do any cleanup necessary in preparation
    * for its widget going away.  After this call, only user data calls
    * are valid on the layer manager.
    */
   virtual void Destroy()
@@ -604,16 +603,19 @@ public:
 protected:
   nsRefPtr<Layer> mRoot;
   gfx::UserData mUserData;
   bool mDestroyed;
   bool mSnapEffectiveTransforms;
 
   nsIntRegion mRegionToClear;
 
+  // Protected destructor, to discourage deletion outside of Release():
+  virtual ~LayerManager() {}
+
   // Print interesting information about this into aTo.  Internally
   // used to implement Dump*() and Log*().
   virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
 
   static void InitLog();
   static PRLogModuleInfo* sLog;
   uint64_t mId;
   bool mInTransaction;
@@ -661,18 +663,16 @@ public:
     TYPE_CONTAINER,
     TYPE_IMAGE,
     TYPE_READBACK,
     TYPE_REF,
     TYPE_SHADOW,
     TYPE_THEBES
   };
 
-  virtual ~Layer();
-
   /**
    * Returns the LayerManager this Layer belongs to. Note that the layer
    * manager might be in a destroyed state, at which point it's only
    * valid to set/get user data from it.
    */
   LayerManager* Manager() { return mManager; }
 
   enum {
@@ -1353,16 +1353,19 @@ public:
   void Mutated()
   {
     mManager->Mutated(this);
   }
 
 protected:
   Layer(LayerManager* aManager, void* aImplData);
 
+  // Protected destructor, to discourage deletion outside of Release():
+  virtual ~Layer();
+
   /**
    * We can snap layer transforms for two reasons:
    * 1) To avoid unnecessary resampling when a transform is a translation
    * by a non-integer number of pixels.
    * Snapping the translation to an integer number of pixels avoids
    * blurring the layer and can be faster to composite.
    * 2) When a layer is used to render a rectangular object, we need to
    * emulate the rendering of rectangular inactive content and snap the
--- a/gfx/layers/composite/APZCTreeManager.h
+++ b/gfx/layers/composite/APZCTreeManager.h
@@ -81,17 +81,16 @@ class CompositorParent;
 class APZCTreeManager {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(APZCTreeManager)
 
   typedef mozilla::layers::AllowedTouchBehavior AllowedTouchBehavior;
   typedef uint32_t TouchBehaviorFlags;
 
 public:
   APZCTreeManager();
-  virtual ~APZCTreeManager();
 
   /**
    * Rebuild the APZC tree based on the layer update that just came up. Preserve
    * APZC instances where possible, but retire those whose layers are no longer
    * in the layer tree.
    *
    * This must be called on the compositor thread as it walks the layer tree.
    *
@@ -268,16 +267,19 @@ public:
    * @param aVelocity the current velocity of the fling, in |aApzc|'s screen
    *                  pixels per millisecond
    */
   void HandOffFling(AsyncPanZoomController* aApzc, ScreenPoint aVelocity);
 
   bool FlushRepaintsForOverscrollHandoffChain();
 
 protected:
+  // Protected destructor, to discourage deletion outside of Release():
+  virtual ~APZCTreeManager();
+
   /**
    * Debug-build assertion that can be called to ensure code is running on the
    * compositor thread.
    */
   virtual void AssertOnCompositorThread();
 
   /*
    * Build the chain of APZCs that will handle overscroll for a pan starting at |aInitialTarget|.
--- a/gfx/layers/d3d9/DeviceManagerD3D9.h
+++ b/gfx/layers/d3d9/DeviceManagerD3D9.h
@@ -74,21 +74,20 @@ struct ShaderConstantRect
   // For easy passing to SetVertexShaderConstantF.
   operator float* () { return &mX; }
 };
 
 /**
  * SwapChain class, this class manages the swap chain belonging to a
  * LayerManagerD3D9.
  */
-class SwapChainD3D9
+class SwapChainD3D9 MOZ_FINAL
 {
   NS_INLINE_DECL_REFCOUNTING(SwapChainD3D9)
 public:
-  ~SwapChainD3D9();
 
   /**
    * This function will prepare the device this swap chain belongs to for
    * rendering to this swap chain. Only after calling this function can the
    * swap chain be drawn to, and only until this function is called on another
    * swap chain belonging to this device will the device draw to it. Passed in
    * is the size of the swap chain. If the window size differs from the size
    * during the last call to this function the swap chain will resize. Note that
@@ -105,16 +104,19 @@ public:
    */
   void Present(const nsIntRect &aRect);
   void Present();
 
 private:
   friend class DeviceManagerD3D9;
 
   SwapChainD3D9(DeviceManagerD3D9 *aDeviceManager);
+
+  // Private destructor, to discourage deletion outside of Release():
+  ~SwapChainD3D9();
   
   bool Init(HWND hWnd);
 
   /**
    * This causes us to release our swap chain, clearing out our resource usage
    * so the master device may reset.
    */
   void Reset();
--- a/gfx/layers/ipc/AsyncPanZoomController.h
+++ b/gfx/layers/ipc/AsyncPanZoomController.h
@@ -85,17 +85,16 @@ public:
    * touches moving the screen.
    */
   static float GetTouchStartTolerance();
 
   AsyncPanZoomController(uint64_t aLayersId,
                          APZCTreeManager* aTreeManager,
                          GeckoContentController* aController,
                          GestureBehavior aGestures = DEFAULT_GESTURES);
-  ~AsyncPanZoomController();
 
   // --------------------------------------------------------------------------
   // These methods must only be called on the gecko thread.
   //
 
   /**
    * Read the various prefs and do any global initialization for all APZC instances.
    * This must be run on the gecko thread before any APZC instances are actually
@@ -355,16 +354,19 @@ public:
    * Set an extra offset for testing async scrolling.
    */
   void SetTestAsyncScrollOffset(const CSSPoint& aPoint)
   {
     mTestAsyncScrollOffset = aPoint;
   }
 
 protected:
+  // Protected destructor, to discourage deletion outside of Release():
+  ~AsyncPanZoomController();
+
   /**
    * Helper method for touches beginning. Sets everything up for panning and any
    * multitouch gestures.
    */
   nsEventStatus OnTouchStart(const MultiTouchInput& aEvent);
 
   /**
    * Helper method for touches moving. Does any transforms needed when panning.
@@ -879,19 +881,16 @@ class AsyncPanZoomAnimation {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncPanZoomAnimation)
 
 public:
   AsyncPanZoomAnimation(const TimeDuration& aRepaintInterval =
                         TimeDuration::Forever())
     : mRepaintInterval(aRepaintInterval)
   { }
 
-  virtual ~AsyncPanZoomAnimation()
-  { }
-
   virtual bool Sample(FrameMetrics& aFrameMetrics,
                       const TimeDuration& aDelta) = 0;
 
   /**
    * Execute the tasks in |mDeferredTasks| in order. See |mDeferredTasks|
    * for more information.
    */
   void ExecuteDeferredTasks() {
@@ -904,16 +903,20 @@ public:
   /**
    * Specifies how frequently (at most) we want to do repaints during the
    * animation sequence. TimeDuration::Forever() will cause it to only repaint
    * at the end of the animation.
    */
   TimeDuration mRepaintInterval;
 
 protected:
+  // Protected destructor, to discourage deletion outside of Release():
+  virtual ~AsyncPanZoomAnimation()
+  { }
+
   /**
    * Tasks scheduled for execution after the APZC's mMonitor is released.
    * Derived classes can add tasks here in Sample(), and the APZC can call
    * ExecuteDeferredTasks() to execute them.
    */
   Vector<Task*> mDeferredTasks;
 };
 
--- a/gfx/layers/ipc/CompositorChild.h
+++ b/gfx/layers/ipc/CompositorChild.h
@@ -22,22 +22,21 @@ class nsIObserver;
 
 namespace mozilla {
 namespace layers {
 
 class ClientLayerManager;
 class CompositorParent;
 class FrameMetrics;
 
-class CompositorChild : public PCompositorChild
+class CompositorChild MOZ_FINAL : public PCompositorChild
 {
   NS_INLINE_DECL_REFCOUNTING(CompositorChild)
 public:
   CompositorChild(ClientLayerManager *aLayerManager);
-  virtual ~CompositorChild();
 
   void Destroy();
 
   /**
    * Lookup the FrameMetrics shared by the compositor process with the
    * associated FrameMetrics::ViewID. The returned FrameMetrics is used
    * in progressive paint calculations.
    */
@@ -52,17 +51,20 @@ public:
   Create(Transport* aTransport, ProcessId aOtherProcess);
 
   static CompositorChild* Get();
 
   static bool ChildProcessHasCompositor() { return sCompositor != nullptr; }
 
   virtual bool RecvInvalidateAll() MOZ_OVERRIDE;
 
-protected:
+private:
+  // Private destructor, to discourage deletion outside of Release():
+  virtual ~CompositorChild();
+
   virtual PLayerTransactionChild*
     AllocPLayerTransactionChild(const nsTArray<LayersBackend>& aBackendHints,
                                 const uint64_t& aId,
                                 TextureFactoryIdentifier* aTextureFactoryIdentifier,
                                 bool* aSuccess) MOZ_OVERRIDE;
 
   virtual bool DeallocPLayerTransactionChild(PLayerTransactionChild *aChild) MOZ_OVERRIDE;
 
@@ -70,17 +72,16 @@ protected:
 
   virtual bool RecvSharedCompositorFrameMetrics(const mozilla::ipc::SharedMemoryBasic::Handle& metrics,
                                                 const CrossProcessMutexHandle& handle,
                                                 const uint32_t& aAPZCId) MOZ_OVERRIDE;
 
   virtual bool RecvReleaseSharedCompositorFrameMetrics(const ViewID& aId,
                                                        const uint32_t& aAPZCId) MOZ_OVERRIDE;
 
-private:
   // Class used to store the shared FrameMetrics, mutex, and APZCId  in a hash table
   class SharedFrameMetricsData {
   public:
     SharedFrameMetricsData(
         const mozilla::ipc::SharedMemoryBasic::Handle& metrics,
         const CrossProcessMutexHandle& handle,
         const uint32_t& aAPZCId);
 
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -1033,27 +1033,26 @@ CompositorParent::ComputeRenderIntegrity
 /**
  * This class handles layer updates pushed directly from child
  * processes to the compositor thread.  It's associated with a
  * CompositorParent on the compositor thread.  While it uses the
  * PCompositor protocol to manage these updates, it doesn't actually
  * drive compositing itself.  For that it hands off work to the
  * CompositorParent it's associated with.
  */
-class CrossProcessCompositorParent : public PCompositorParent,
-                                     public ShadowLayersManager
+class CrossProcessCompositorParent MOZ_FINAL : public PCompositorParent,
+                                               public ShadowLayersManager
 {
   friend class CompositorParent;
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CrossProcessCompositorParent)
 public:
   CrossProcessCompositorParent(Transport* aTransport)
     : mTransport(aTransport)
   {}
-  virtual ~CrossProcessCompositorParent();
 
   // IToplevelProtocol::CloneToplevel()
   virtual IToplevelProtocol*
   CloneToplevel(const InfallibleTArray<mozilla::ipc::ProtocolFdMapping>& aFds,
                 base::ProcessHandle aPeerProcess,
                 mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
@@ -1087,16 +1086,19 @@ public:
   virtual void ForceComposite(LayerTransactionParent* aLayerTree) MOZ_OVERRIDE;
   virtual bool SetTestSampleTime(LayerTransactionParent* aLayerTree,
                                  const TimeStamp& aTime) MOZ_OVERRIDE;
   virtual void LeaveTestMode(LayerTransactionParent* aLayerTree) MOZ_OVERRIDE;
 
   virtual AsyncCompositionManager* GetCompositionManager(LayerTransactionParent* aParent) MOZ_OVERRIDE;
 
 private:
+  // Private destructor, to discourage deletion outside of Release():
+  virtual ~CrossProcessCompositorParent();
+
   void DeferredDestroy();
 
   // There can be many CPCPs, and IPDL-generated code doesn't hold a
   // reference to top-level actors.  So we hold a reference to
   // ourself.  This is released (deferred) in ActorDestroy().
   nsRefPtr<CrossProcessCompositorParent> mSelfRef;
   Transport* mTransport;
 };
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/ipc/CompositorParent.h
@@ -57,28 +57,26 @@ struct ScopedLayerTreeRegistration
                               Layer* aRoot,
                               GeckoContentController* aController);
   ~ScopedLayerTreeRegistration();
 
 private:
   uint64_t mLayersId;
 };
 
-class CompositorParent : public PCompositorParent,
-                         public ShadowLayersManager
+class CompositorParent MOZ_FINAL : public PCompositorParent,
+                                   public ShadowLayersManager
 {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorParent)
 
 public:
   CompositorParent(nsIWidget* aWidget,
                    bool aUseExternalSurfaceSize = false,
                    int aSurfaceWidth = -1, int aSurfaceHeight = -1);
 
-  virtual ~CompositorParent();
-
   // IToplevelProtocol::CloneToplevel()
   virtual IToplevelProtocol*
   CloneToplevel(const InfallibleTArray<mozilla::ipc::ProtocolFdMapping>& aFds,
                 base::ProcessHandle aPeerProcess,
                 mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
 
   virtual bool RecvWillStop() MOZ_OVERRIDE;
   virtual bool RecvStop() MOZ_OVERRIDE;
@@ -226,31 +224,33 @@ public:
 
   float ComputeRenderIntegrity();
 
   /**
    * Returns true if the calling thread is the compositor thread.
    */
   static bool IsInCompositorThread();
 
-protected:
+private:
+  // Private destructor, to discourage deletion outside of Release():
+  virtual ~CompositorParent();
+
   virtual PLayerTransactionParent*
     AllocPLayerTransactionParent(const nsTArray<LayersBackend>& aBackendHints,
                                  const uint64_t& aId,
                                  TextureFactoryIdentifier* aTextureFactoryIdentifier,
                                  bool* aSuccess) MOZ_OVERRIDE;
   virtual bool DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers) MOZ_OVERRIDE;
   virtual void ScheduleTask(CancelableTask*, int);
   void Composite();
   void CompositeToTarget(gfx::DrawTarget* aTarget);
   void ForceComposeToTarget(gfx::DrawTarget* aTarget);
 
   void SetEGLSurfaceSize(int width, int height);
 
-private:
   void InitializeLayerManager(const nsTArray<LayersBackend>& aBackendHints);
   void PauseComposition();
   void ResumeComposition();
   void ResumeCompositionAndResize(int width, int height);
   void ForceComposition();
   void CancelCurrentCompositeTask();
 
   inline static PlatformThreadId CompositorThreadID();
--- a/gfx/layers/ipc/GeckoContentController.h
+++ b/gfx/layers/ipc/GeckoContentController.h
@@ -117,15 +117,18 @@ public:
    * General tranformation notices for consumers. These fire any time
    * the apzc is modifying the view, including panning, zooming, and
    * fling.
    */
   virtual void NotifyTransformBegin(const ScrollableLayerGuid& aGuid) {}
   virtual void NotifyTransformEnd(const ScrollableLayerGuid& aGuid) {}
 
   GeckoContentController() {}
+
+protected:
+  // Protected destructor, to discourage deletion outside of Release():
   virtual ~GeckoContentController() {}
 };
 
 }
 }
 
 #endif // mozilla_layers_GeckoContentController_h
--- a/gfx/layers/ipc/GestureEventListener.h
+++ b/gfx/layers/ipc/GestureEventListener.h
@@ -31,35 +31,36 @@ class AsyncPanZoomController;
  * AsyncPanZoomController since it will think that they are just trying to pan
  * the screen. Instead, we generate a PinchGestureInput and send that. If the
  * touch event is not part of a gesture, we just return nsEventStatus_eIgnore
  * and AsyncPanZoomController is expected to handle it.
  *
  * Android doesn't use this class because it has its own built-in gesture event
  * listeners that should generally be preferred.
  */
-class GestureEventListener {
+class GestureEventListener MOZ_FINAL {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GestureEventListener)
 
   GestureEventListener(AsyncPanZoomController* aAsyncPanZoomController);
-  ~GestureEventListener();
 
   // --------------------------------------------------------------------------
   // These methods must only be called on the controller/UI thread.
   //
 
   /**
    * General input handler for a touch event. If the touch event is not a part
    * of a gesture, then we pass it along to AsyncPanZoomController. Otherwise,
    * it gets consumed here and never forwarded along.
    */
   nsEventStatus HandleInputEvent(const MultiTouchInput& aEvent);
 
-protected:
+private:
+  // Private destructor, to discourage deletion outside of Release():
+  ~GestureEventListener();
 
   /**
    * States of GEL finite-state machine.
    */
   enum GestureState {
     // This is the initial and final state of any gesture.
     // In this state there's no gesture going on, and we don't think we're
     // about to enter one.
--- a/gfx/layers/opengl/Composer2D.h
+++ b/gfx/layers/opengl/Composer2D.h
@@ -34,19 +34,21 @@ struct Matrix;
 
 namespace layers {
 
 class Layer;
 
 class Composer2D {
   NS_INLINE_DECL_REFCOUNTING(Composer2D)
 
-public:
+protected:
+  // Protected destructor, to discourage deletion outside of Release():
   virtual ~Composer2D() {}
 
+public:
   /**
    * Return true if |aRoot| met the implementation's criteria for fast
    * composition and the render was successful.  Return false to fall
    * back on the GPU.
    *
    * |aWorldTransform| must be applied to |aRoot|'s subtree when
    * rendering to the framebuffer.  This is a global transform on the
    * entire scene, defined in GL space.  If the Composer2D
--- a/gfx/src/nsDeviceContext.h
+++ b/gfx/src/nsDeviceContext.h
@@ -28,21 +28,20 @@ class nsFontMetrics;
 class nsIAtom;
 class nsIDeviceContextSpec;
 class nsIScreen;
 class nsIScreenManager;
 class nsIWidget;
 class nsRect;
 class nsRenderingContext;
 
-class nsDeviceContext
+class nsDeviceContext MOZ_FINAL
 {
 public:
     nsDeviceContext();
-    ~nsDeviceContext();
 
     NS_INLINE_DECL_REFCOUNTING(nsDeviceContext)
 
     /**
      * Initialize the device context from a widget
      * @param aWidget a widget to initialize the device context from
      * @return error status
      */
@@ -244,17 +243,20 @@ public:
      */
     float GetPixelScale() const { return mPixelScale; }
 
     /**
      * True if this device context was created for printing.
      */
     bool IsPrinterSurface();
 
-protected:
+private:
+    // Private destructor, to discourage deletion outside of Release():
+    ~nsDeviceContext();
+
     void SetDPI();
     void ComputeClientRectUsingScreen(nsRect *outRect);
     void ComputeFullAreaUsingScreen(nsRect *outRect);
     void FindScreen(nsIScreen **outScreen);
     void CalcPrintingSize();
     void UpdateScaledAppUnits();
 
     nscoord  mWidth;
--- a/gfx/src/nsFontMetrics.h
+++ b/gfx/src/nsFontMetrics.h
@@ -38,21 +38,20 @@ struct nsBoundingMetrics;
  * list).
  *
  * The style system needs to have access to certain metrics, such as
  * the em height (for the CSS "em" unit), and we use the first Western
  * font's metrics for that purpose. The platform-specific
  * implementations are expected to select non-Western fonts that "fit"
  * reasonably well with the Western font that is loaded at Init time.
  */
-class nsFontMetrics
+class nsFontMetrics MOZ_FINAL
 {
 public:
     nsFontMetrics();
-    ~nsFontMetrics();
 
     NS_INLINE_DECL_REFCOUNTING(nsFontMetrics)
 
     /**
      * Initialize the font metrics. Call this after creating the font metrics.
      * Font metrics you get from the font cache do NOT need to be initialized
      *
      * @see nsDeviceContext#GetMetricsFor()
@@ -207,17 +206,20 @@ public:
     void SetTextRunRTL(bool aIsRTL) { mTextRunRTL = aIsRTL; }
     bool GetTextRunRTL() { return mTextRunRTL; }
 
     gfxFontGroup* GetThebesFontGroup() { return mFontGroup; }
     gfxUserFontSet* GetUserFontSet() { return mFontGroup->GetUserFontSet(); }
 
     int32_t AppUnitsPerDevPixel() { return mP2A; }
 
-protected:
+private:
+    // Private destructor, to discourage deletion outside of Release():
+    ~nsFontMetrics();
+
     const gfxFont::Metrics& GetMetrics() const;
 
     nsFont mFont;
     nsRefPtr<gfxFontGroup> mFontGroup;
     nsCOMPtr<nsIAtom> mLanguage;
     nsDeviceContext *mDeviceContext;
     int32_t mP2A;
     bool mTextRunRTL;
--- a/gfx/thebes/gfxDrawable.h
+++ b/gfx/thebes/gfxDrawable.h
@@ -22,17 +22,16 @@ class gfxPattern;
  * An Interface representing something that has an intrinsic size and can draw
  * itself repeatedly.
  */
 class gfxDrawable {
     NS_INLINE_DECL_REFCOUNTING(gfxDrawable)
 public:
     gfxDrawable(const gfxIntSize aSize)
      : mSize(aSize) {}
-    virtual ~gfxDrawable() {}
 
     /**
      * Draw into aContext filling aFillRect, possibly repeating, using aFilter.
      * aTransform is a userspace to "image"space matrix. For example, if Draw
      * draws using a gfxPattern, this is the matrix that should be set on the
      * pattern prior to rendering it.
      *  @return whether drawing was successful
      */
@@ -40,16 +39,19 @@ public:
                         const gfxRect& aFillRect,
                         bool aRepeat,
                         const GraphicsFilter& aFilter,
                         const gfxMatrix& aTransform = gfxMatrix()) = 0;
     virtual already_AddRefed<gfxImageSurface> GetAsImageSurface() { return nullptr; }
     virtual gfxIntSize Size() { return mSize; }
 
 protected:
+    // Protected destructor, to discourage deletion outside of Release():
+    virtual ~gfxDrawable() {}
+
     const gfxIntSize mSize;
 };
 
 /**
  * gfxSurfaceDrawable
  * A convenience implementation of gfxDrawable for surfaces.
  */
 class gfxSurfaceDrawable : public gfxDrawable {
@@ -78,19 +80,21 @@ protected:
 };
 
 /**
  * gfxDrawingCallback
  * A simple drawing functor.
  */
 class gfxDrawingCallback {
     NS_INLINE_DECL_REFCOUNTING(gfxDrawingCallback)
-public:
+protected:
+    // Protected destructor, to discourage deletion outside of Release():
     virtual ~gfxDrawingCallback() {}
 
+public:
     /**
      * Draw into aContext filling aFillRect using aFilter.
      * aTransform is a userspace to "image"space matrix. For example, if Draw
      * draws using a gfxPattern, this is the matrix that should be set on the
      * pattern prior to rendering it.
      *  @return whether drawing was successful
      */
     virtual bool operator()(gfxContext* aContext,
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -230,17 +230,16 @@ private:
     gfxCharacterMap& operator=(const gfxCharacterMap&);
 };
 
 class gfxFontEntry {
 public:
     NS_INLINE_DECL_REFCOUNTING(gfxFontEntry)
 
     gfxFontEntry(const nsAString& aName, bool aIsStandardFace = false);
-    virtual ~gfxFontEntry();
 
     // unique name for the face, *not* the family; not necessarily the
     // "real" or user-friendly name, may be an internal identifier
     const nsString& Name() const { return mName; }
 
     // family name
     const nsString& FamilyName() const { return mFamilyName; }
 
@@ -466,16 +465,19 @@ protected:
     friend class gfxPlatformFontList;
     friend class gfxMacPlatformFontList;
     friend class gfxUserFcFontEntry;
     friend class gfxFontFamily;
     friend class gfxSingleFaceMacFontFamily;
 
     gfxFontEntry();
 
+    // Protected destructor, to discourage deletion outside of Release():
+    virtual ~gfxFontEntry();
+
     virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold) {
         NS_NOTREACHED("oops, somebody didn't override CreateFontInstance");
         return nullptr;
     }
 
     virtual void CheckForGraphiteTables();
 
     // Copy a font table into aBuffer.
@@ -676,18 +678,16 @@ public:
         mFaceNamesInitialized(false),
         mHasStyles(false),
         mIsSimpleFamily(false),
         mIsBadUnderlineFamily(false),
         mFamilyCharacterMapInitialized(false),
         mSkipDefaultFeatureSpaceCheck(false)
         { }
 
-    virtual ~gfxFontFamily() { }
-
     const nsString& Name() { return mName; }
 
     virtual void LocalizedName(nsAString& aLocalizedName);
     virtual bool HasOtherFamilyNames();
     
     nsTArray<nsRefPtr<gfxFontEntry> >& GetFontList() { return mAvailableFonts; }
     
     void AddFontEntry(nsRefPtr<gfxFontEntry> aFontEntry) {
@@ -801,16 +801,21 @@ public:
         return false;
     }
 
     void SetSkipSpaceFeatureCheck(bool aSkipCheck) {
         mSkipDefaultFeatureSpaceCheck = aSkipCheck;
     }
 
 protected:
+    // Protected destructor, to discourage deletion outside of Release():
+    virtual ~gfxFontFamily()
+    {
+    }
+
     // fills in an array with weights of faces that match style,
     // returns whether any matching entries found
     virtual bool FindWeightsForStyle(gfxFontEntry* aFontsForWeights[],
                                        bool anItalic, int16_t aStretch);
 
     bool ReadOtherFamilyNamesForFace(gfxPlatformFontList *aPlatformFontList,
                                      hb_blob_t           *aNameTable,
                                      bool                 useFullName = false);
@@ -1186,16 +1191,18 @@ public:
         // A list of where linebreaks are currently placed in the textrun. May
         // be null if mInitialBreakCount is zero.
         uint32_t     *mInitialBreaks;
         uint32_t      mInitialBreakCount;
         // The ratio to use to convert device pixels to application layout units
         int32_t       mAppUnitsPerDevUnit;
     };
 
+protected:
+    // Protected destructor, to discourage deletion outside of Release():
     virtual ~gfxTextRunFactory() {}
 };
 
 /**
  * This stores glyph bounds information for a particular gfxFont, at
  * a particular appunits-per-dev-pixel ratio (because the compressed glyph
  * width array is stored in appunits).
  * 
--- a/gfx/thebes/gfxFontFeatures.h
+++ b/gfx/thebes/gfxFontFeatures.h
@@ -43,22 +43,21 @@ operator<(const gfxAlternateValue& a, co
 }
 
 inline bool
 operator==(const gfxAlternateValue& a, const gfxAlternateValue& b)
 {
     return (a.alternate == b.alternate) && (a.value == b.value);
 }
 
-class gfxFontFeatureValueSet {
+class gfxFontFeatureValueSet MOZ_FINAL {
 public:
     NS_INLINE_DECL_REFCOUNTING(gfxFontFeatureValueSet)
 
     gfxFontFeatureValueSet();
-    virtual ~gfxFontFeatureValueSet() {}
 
     struct ValueList {
         ValueList(const nsAString& aName, const nsTArray<uint32_t>& aSelectors)
           : name(aName), featureSelectors(aSelectors)
         {}
         nsString             name;
         nsTArray<uint32_t>   featureSelectors;
     };
@@ -73,17 +72,20 @@ public:
     GetFontFeatureValuesFor(const nsAString& aFamily,
                             uint32_t aVariantProperty,
                             const nsAString& aName,
                             nsTArray<uint32_t>& aValues);
     void
     AddFontFeatureValues(const nsAString& aFamily,
                 const nsTArray<gfxFontFeatureValueSet::FeatureValues>& aValues);
 
-protected:
+private:
+    // Private destructor, to discourage deletion outside of Release():
+    ~gfxFontFeatureValueSet() {}
+
     struct FeatureValueHashKey {
         nsString mFamily;
         uint32_t mPropVal;
         nsString mName;
 
         FeatureValueHashKey()
             : mPropVal(0)
         { }
--- a/gfx/thebes/gfxFontInfoLoader.h
+++ b/gfx/thebes/gfxFontInfoLoader.h
@@ -50,24 +50,27 @@ public:
     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FontInfoData)
 
     FontInfoData(bool aLoadOtherNames,
                  bool aLoadFaceNames,
                  bool aLoadCmaps) :
         mLoadOtherNames(aLoadOtherNames),
         mLoadFaceNames(aLoadFaceNames),
         mLoadCmaps(aLoadCmaps)
-   {
+    {
         MOZ_COUNT_CTOR(FontInfoData);
-   }
+    }
 
+protected:
+    // Protected destructor, to discourage deletion outside of Release():
     virtual ~FontInfoData() {
         MOZ_COUNT_DTOR(FontInfoData);
     }
 
+public:
     virtual void Load();
 
     // loads font data for all fonts of a given family
     // (called on async thread)
     virtual void LoadFontFamilyData(const nsAString& aFamilyName) = 0;
 
     // -- methods overriden by platform-specific versions --
 
--- a/gfx/thebes/gfxPangoFonts.cpp
+++ b/gfx/thebes/gfxPangoFonts.cpp
@@ -685,17 +685,17 @@ private:
 
 /**
  * gfxFcFontSet:
  *
  * Translation from a desired FcPattern to a sorted set of font references
  * (fontconfig cache data) and (when needed) fonts.
  */
 
-class gfxFcFontSet {
+class gfxFcFontSet MOZ_FINAL {
 public:
     NS_INLINE_DECL_REFCOUNTING(gfxFcFontSet)
     
     explicit gfxFcFontSet(FcPattern *aPattern,
                                gfxUserFontSet *aUserFontSet)
         : mSortPattern(aPattern), mUserFontSet(aUserFontSet),
           mFcFontsTrimmed(0),
           mHaveFallbackFonts(false)
@@ -724,16 +724,21 @@ public:
 
     FcPattern *GetFontPatternAt(uint32_t i);
 
     bool WaitingForUserFont() const {
         return mWaitingForUserFont;
     }
 
 private:
+    // Private destructor, to discourage deletion outside of Release():
+    ~gfxFcFontSet()
+    {
+    }
+
     nsReturnRef<FcFontSet> SortPreferredFonts(bool& aWaitForUserFont);
     nsReturnRef<FcFontSet> SortFallbackFonts();
 
     struct FontEntry {
         explicit FontEntry(FcPattern *aPattern) : mPattern(aPattern) {}
         nsCountedRef<FcPattern> mPattern;
         nsRefPtr<gfxFcFont> mFont;
     };
--- a/gfx/thebes/gfxPattern.h
+++ b/gfx/thebes/gfxPattern.h
@@ -17,30 +17,29 @@
 #include "nsTArray.h"
 
 class gfxContext;
 class gfxASurface;
 struct gfxRGBA;
 typedef struct _cairo_pattern cairo_pattern_t;
 
 
-class gfxPattern {
+class gfxPattern MOZ_FINAL{
     NS_INLINE_DECL_REFCOUNTING(gfxPattern)
 
 public:
     gfxPattern(cairo_pattern_t *aPattern);
     gfxPattern(const gfxRGBA& aColor);
     gfxPattern(gfxASurface *surface); // from another surface
     // linear
     gfxPattern(gfxFloat x0, gfxFloat y0, gfxFloat x1, gfxFloat y1); // linear
     gfxPattern(gfxFloat cx0, gfxFloat cy0, gfxFloat radius0,
                gfxFloat cx1, gfxFloat cy1, gfxFloat radius1); // radial
     gfxPattern(mozilla::gfx::SourceSurface *aSurface,
                const mozilla::gfx::Matrix &aTransform); // Azure
-    virtual ~gfxPattern();
 
     cairo_pattern_t *CairoPattern();
     void AddColorStop(gfxFloat offset, const gfxRGBA& c);
     void SetColorStops(mozilla::RefPtr<mozilla::gfx::GradientStops> aStops);
 
     // This should only be called on a cairo pattern that we want to use with
     // Azure. We will read back the color stops from cairo and try to look
     // them up in the cache.
@@ -98,17 +97,20 @@ public:
     bool GetSolidColor(gfxRGBA& aColor);
 
     already_AddRefed<gfxASurface> GetSurface();
 
     bool IsAzure() { return !mPattern; }
 
     mozilla::TemporaryRef<mozilla::gfx::SourceSurface> GetAzureSurface() { return mSourceSurface; }
 
-protected:
+private:
+    // Private destructor, to discourage deletion outside of Release():
+    ~gfxPattern();
+
     cairo_pattern_t *mPattern;
 
     /**
      * aPatternTransform is the cairo pattern transform --- from user space at
      * the time the pattern was set, to pattern space.
      * aCurrentTransform is the DrawTarget's CTM --- from user space to device
      * space.
      * aOriginalTransform, if non-null, is the DrawTarget's TM when
--- a/gfx/thebes/gfxReusableSurfaceWrapper.h
+++ b/gfx/thebes/gfxReusableSurfaceWrapper.h
@@ -28,17 +28,16 @@
  *    read lock.
  * 4) Once the compositor has processed the surface and uploaded
  *    the content, it then releases the read lock by dereferencing
  *    its wrapper.
  */
 class gfxReusableSurfaceWrapper {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxReusableSurfaceWrapper)
 public:
-  virtual ~gfxReusableSurfaceWrapper() {}
 
   /**
    * Returns a read-only pointer to the image data.
    */
   virtual const unsigned char* GetReadOnlyData() const = 0;
 
   /**
    * Returns the image surface format.
@@ -76,12 +75,15 @@ public:
   };
 
   /**
    * Returns a unique ID for each implementation of gfxReusableSurfaceWrapper.
    */
   virtual Type GetType() = 0;
 
 protected:
+  // Protected destructor, to discourage deletion outside of Release():
+  virtual ~gfxReusableSurfaceWrapper() {}
+
   NS_DECL_OWNINGTHREAD
 };
 
 #endif // GFXCOWSURFACEWRAPPER
--- a/gfx/thebes/gfxUserFontSet.h
+++ b/gfx/thebes/gfxUserFontSet.h
@@ -136,17 +136,16 @@ class gfxProxyFontEntry;
 
 class gfxUserFontSet {
 
 public:
 
     NS_INLINE_DECL_REFCOUNTING(gfxUserFontSet)
 
     gfxUserFontSet();
-    virtual ~gfxUserFontSet();
 
     enum {
         // no flags ==> no hint set
         // unknown ==> unknown format hint set
         FLAG_FORMAT_UNKNOWN        = 1,
         FLAG_FORMAT_OPENTYPE       = 1 << 1,
         FLAG_FORMAT_TRUETYPE       = 1 << 2,
         FLAG_FORMAT_TRUETYPE_AAT   = 1 << 3,
@@ -373,16 +372,19 @@ public:
             // Whether this font was loaded from a private window.
             bool                   mPrivate;
         };
 
         static nsTHashtable<Entry> *sUserFonts;
     };
 
 protected:
+    // Protected destructor, to discourage deletion outside of Release():
+    virtual ~gfxUserFontSet();
+
     // Return whether the font set is associated with a private-browsing tab.
     virtual bool GetPrivateBrowsing() = 0;
 
     // for a given proxy font entry, attempt to load the next resource
     // in the src list
     LoadStatus LoadNext(gfxMixedFontFamily *aFamily,
                         gfxProxyFontEntry *aProxyEntry);
 
--- a/gfx/thebes/nsSurfaceTexture.h
+++ b/gfx/thebes/nsSurfaceTexture.h
@@ -21,28 +21,26 @@ class Matrix4x4;
 }
 }
 
 /**
  * This class is a wrapper around Android's SurfaceTexture class.
  * Usage is pretty much exactly like the Java class, so see
  * the Android documentation for details.
  */
-class nsSurfaceTexture {
+class nsSurfaceTexture MOZ_FINAL {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsSurfaceTexture)
 
 public:
   static nsSurfaceTexture* Create(GLuint aTexture);
   static nsSurfaceTexture* Find(int id);
 
   // Returns with reasonable certainty whether or not we'll
   // be able to create and use a SurfaceTexture
   static bool Check();
-  
-  ~nsSurfaceTexture();
 
   // This is an ANativeWindow. Use AndroidBridge::LockWindow and
   // friends for manipulating it.
   void* GetNativeWindow();
 
   // This attaches the updated data to the TEXTURE_EXTERNAL target
   void UpdateTexImage();
 
@@ -54,16 +52,19 @@ public:
   void SetFrameAvailableCallback(nsIRunnable* aRunnable);
 
   // Only should be called by AndroidJNI when we get a
   // callback from the underlying SurfaceTexture instance
   void NotifyFrameAvailable();
 private:
   nsSurfaceTexture();
 
+  // Private destructor, to discourage deletion outside of Release():
+  ~nsSurfaceTexture();
+
   bool Init(GLuint aTexture);
 
   jobject mSurfaceTexture;
   void* mNativeWindow;
   int mID;
   nsRefPtr<nsIRunnable> mFrameAvailableCallback;
 };
 
--- a/layout/style/nsFontFaceLoader.h
+++ b/layout/style/nsFontFaceLoader.h
@@ -23,17 +23,16 @@ class nsIPrincipal;
 
 class nsFontFaceLoader;
 
 // nsUserFontSet - defines the loading mechanism for downloadable fonts
 class nsUserFontSet : public gfxUserFontSet
 {
 public:
   nsUserFontSet(nsPresContext* aContext);
-  ~nsUserFontSet();
 
   // Called when this font set is no longer associated with a presentation.
   void Destroy();
 
   // starts loading process, creating and initializing a nsFontFaceLoader obj
   // returns whether load process successfully started or not
   nsresult StartLoad(gfxMixedFontFamily* aFamily,
                      gfxProxyFontEntry* aFontToLoad,
@@ -49,16 +48,20 @@ public:
 
   virtual void ReplaceFontEntry(gfxMixedFontFamily* aFamily,
                                 gfxProxyFontEntry* aProxy,
                                 gfxFontEntry* aFontEntry) MOZ_OVERRIDE;
 
   nsCSSFontFaceRule* FindRuleForEntry(gfxFontEntry* aFontEntry);
 
 protected:
+  // Protected destructor, to discourage deletion outside of Release()
+  // (since we inherit from refcounted class gfxUserFontSet):
+  ~nsUserFontSet();
+
   // The font-set keeps track of the collection of rules, and their
   // corresponding font entries (whether proxies or real entries),
   // so that we can update the set without having to throw away
   // all the existing fonts.
   struct FontFaceRuleRecord {
     nsRefPtr<gfxFontEntry>       mFontEntry;
     nsFontFaceRuleContainer      mContainer;
   };