Merge inbound to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Tue, 15 Apr 2014 23:26:35 -0400
changeset 197225 dd50745d7f35796adf7b037c2e60c3f6809a7347
parent 197142 26209c17215041ecee2d7542839553a9754bbee6 (current diff)
parent 197224 fcb4575e90d9bf72c7fd12a17e2423760ac61570 (diff)
child 197245 b73ad6f8bf2618b8e9b077e1839c3c30f4d1aae6
child 197269 025a433dd5eb133140b0ff7c46731d4c28c110b1
child 197289 eb732605c93a2189df07b025df172a9356db2037
push id3624
push userasasaki@mozilla.com
push dateMon, 09 Jun 2014 21:49:01 +0000
treeherdermozilla-beta@b1a5da15899a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone31.0a1
first release with
nightly linux32
dd50745d7f35 / 31.0a1 / 20140416030202 / files
nightly linux64
dd50745d7f35 / 31.0a1 / 20140416030202 / files
nightly mac
dd50745d7f35 / 31.0a1 / 20140416030202 / files
nightly win32
dd50745d7f35 / 31.0a1 / 20140416030202 / files
nightly win64
dd50745d7f35 / 31.0a1 / 20140416030202 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to m-c.
dom/camera/CameraControlImpl.h
dom/camera/ICameraControl.h
gfx/thebes/gfxPlatform.cpp
--- a/accessible/src/jsat/Utils.jsm
+++ b/accessible/src/jsat/Utils.jsm
@@ -592,17 +592,17 @@ PivotContext.prototype = {
    */
   _getAncestry: function _getAncestry(aAccessible) {
     let ancestry = [];
     let parent = aAccessible;
     try {
       while (parent && (parent = parent.parent)) {
        ancestry.push(parent);
       }
-    } catch (e) {
+    } catch (x) {
       // A defunct accessible will raise an exception geting parent.
       Logger.debug('Failed to get parent:', x);
     }
     return ancestry.reverse();
   },
 
   /**
    * A list of the old accessible's ancestry.
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -269,17 +269,16 @@ pref("editor.singleLine.pasteNewlines", 
 pref("ui.dragThresholdX", 25);
 pref("ui.dragThresholdY", 25);
 
 // Layers Acceleration.  We can only have nice things on gonk, because
 // they're not maintained anywhere else.
 pref("layers.offmainthreadcomposition.enabled", true);
 #ifndef MOZ_WIDGET_GONK
 pref("dom.ipc.tabs.disabled", true);
-pref("layers.acceleration.disabled", true);
 pref("layers.offmainthreadcomposition.async-animations", false);
 pref("layers.async-video.enabled", false);
 #else
 pref("dom.ipc.tabs.disabled", false);
 pref("layers.acceleration.disabled", false);
 pref("layers.offmainthreadcomposition.async-animations", true);
 pref("layers.async-video.enabled", true);
 pref("layers.async-pan-zoom.enabled", true);
--- a/b2g/config/mozconfigs/macosx64_gecko/debug
+++ b/b2g/config/mozconfigs/macosx64_gecko/debug
@@ -1,8 +1,9 @@
+. "$topsrcdir/b2g/config/mozconfigs/common"
 . $topsrcdir/build/macosx/mozconfig.common
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
--- a/b2g/config/mozconfigs/macosx64_gecko/nightly
+++ b/b2g/config/mozconfigs/macosx64_gecko/nightly
@@ -1,8 +1,9 @@
+. "$topsrcdir/b2g/config/mozconfigs/common"
 . $topsrcdir/build/macosx/mozconfig.common
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
--- a/browser/components/shell/src/nsWindowsShellService.cpp
+++ b/browser/components/shell/src/nsWindowsShellService.cpp
@@ -748,27 +748,29 @@ nsWindowsShellService::SetShouldCheckDef
   return prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, aShouldCheck);
 }
 
 static nsresult
 WriteBitmap(nsIFile* aFile, imgIContainer* aImage)
 {
   nsresult rv;
 
-  nsRefPtr<gfxASurface> thebesSurface =
+  RefPtr<SourceSurface> surface =
     aImage->GetFrame(imgIContainer::FRAME_FIRST,
                      imgIContainer::FLAG_SYNC_DECODE);
-  NS_ENSURE_TRUE(thebesSurface, NS_ERROR_FAILURE);
+  NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
 
-  nsRefPtr<gfxImageSurface> thebesImageSurface =
-    thebesSurface->GetAsReadableARGB32ImageSurface();
-  NS_ENSURE_TRUE(thebesImageSurface, NS_ERROR_FAILURE);
+  // For either of the following formats we want to set the biBitCount member
+  // of the BITMAPINFOHEADER struct to 32, below. For that value the bitmap
+  // format defines that the A8/X8 WORDs in the bitmap byte stream be ignored
+  // for the BI_RGB value we use for the biCompression member.
+  MOZ_ASSERT(surface->GetFormat() == SurfaceFormat::B8G8R8A8 ||
+             surface->GetFormat() == SurfaceFormat::B8G8R8X8);
 
-  RefPtr<DataSourceSurface> dataSurface =
-    thebesImageSurface->CopyToB8G8R8A8DataSourceSurface();
+  RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface();
   NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
 
   int32_t width = dataSurface->GetSize().width;
   int32_t height = dataSurface->GetSize().height;
   int32_t bytesPerPixel = 4 * sizeof(uint8_t);
   uint32_t bytesPerRow = bytesPerPixel * width;
 
   // initialize these bitmap structs which we will later
--- a/content/base/src/moz.build
+++ b/content/base/src/moz.build
@@ -224,13 +224,14 @@ LOCAL_INCLUDES += [
     '/js/xpconnect/src',
     '/js/xpconnect/wrappers',
     '/layout/base',
     '/layout/generic',
     '/layout/style',
     '/layout/svg',
     '/layout/xul',
     '/netwerk/base/src',
+    '/xpcom/ds',
 ]
 
 if CONFIG['GNU_CC'] and CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
     # Work around bug 986928
     CXXFLAGS += ['-Wno-error=format']
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -119,16 +119,17 @@
 #include "nsIImageLoadingContent.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIIOService.h"
 #include "nsIJSRuntimeService.h"
 #include "nsILineBreaker.h"
 #include "nsILoadContext.h"
 #include "nsILoadGroup.h"
+#include "nsIMemoryReporter.h"
 #include "nsIMIMEService.h"
 #include "nsINode.h"
 #include "nsINodeInfo.h"
 #include "nsIObjectLoadingContent.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
 #include "nsIOfflineCacheUpdate.h"
 #include "nsIParser.h"
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -95,19 +95,21 @@
 #include "nsGlobalWindow.h"
 #include "GLContext.h"
 #include "GLContextProvider.h"
 #include "SVGContentUtils.h"
 #include "nsIScreenManager.h"
 
 #undef free // apparently defined by some windows header, clashing with a free()
             // method in SkTypes.h
+#ifdef USE_SKIA
 #include "SkiaGLGlue.h"
 #include "SurfaceStream.h"
 #include "SurfaceTypes.h"
+#endif
 
 using mozilla::gl::GLContext;
 using mozilla::gl::SkiaGLGlue;
 using mozilla::gl::GLContextProvider;
 
 #ifdef XP_WIN
 #include "gfxWindowsPlatform.h"
 #endif
@@ -895,25 +897,27 @@ CanvasRenderingContext2D::EnsureTarget()
      if (layerManager) {
       if (gfxPlatform::GetPlatform()->UseAcceleratedSkiaCanvas() &&
           !mForceSoftware &&
           CheckSizeForSkiaGL(size)) {
         DemoteOldestContextIfNecessary();
 
         SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
 
+#if USE_SKIA
         if (glue && glue->GetGrContext() && glue->GetGLContext()) {
           mTarget = Factory::CreateDrawTargetSkiaWithGrContext(glue->GetGrContext(), size, format);
           if (mTarget) {
             mStream = gfx::SurfaceStream::CreateForType(SurfaceStreamType::TripleBuffer, glue->GetGLContext());
             AddDemotableContext(this);
           } else {
             printf_stderr("Failed to create a SkiaGL DrawTarget, falling back to software\n");
           }
         }
+#endif
         if (!mTarget) {
           mTarget = layerManager->CreateDrawTarget(size, format);
         }
       } else
         mTarget = layerManager->CreateDrawTarget(size, format);
      } else {
         mTarget = gfxPlatform::GetPlatform()->CreateOffscreenCanvasDrawTarget(size, format);
      }
@@ -4239,22 +4243,24 @@ CanvasRenderingContext2D::GetCanvasLayer
 
   if (!mResetLayer && aOldLayer) {
     CanvasRenderingContext2DUserData* userData =
       static_cast<CanvasRenderingContext2DUserData*>(
         aOldLayer->GetUserData(&g2DContextLayerUserData));
 
     CanvasLayer::Data data;
     if (mStream) {
+#ifdef USE_SKIA
       SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
 
       if (glue) {
         data.mGLContext = glue->GetGLContext();
         data.mStream = mStream.get();
       }
+#endif
     } else {
       data.mDrawTarget = mTarget;
     }
 
     if (userData && userData->IsForContext(this) && aOldLayer->IsDataValid(data)) {
       nsRefPtr<CanvasLayer> ret = aOldLayer;
       return ret.forget();
     }
@@ -4287,17 +4293,19 @@ CanvasRenderingContext2D::GetCanvasLayer
 
   CanvasLayer::Data data;
   if (mStream) {
     SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
 
     if (glue) {
       canvasLayer->SetPreTransactionCallback(
               CanvasRenderingContext2DUserData::PreTransactionCallback, userData);
+#if USE_SKIA
       data.mGLContext = glue->GetGLContext();
+#endif
       data.mStream = mStream.get();
       data.mTexID = (uint32_t)((uintptr_t)mTarget->GetNativeSurface(NativeSurfaceType::OPENGL_TEXTURE));
     }
   } else {
     data.mDrawTarget = mTarget;
   }
 
   data.mSize = nsIntSize(mWidth, mHeight);
--- a/content/html/content/src/HTMLInputElement.cpp
+++ b/content/html/content/src/HTMLInputElement.cpp
@@ -4669,34 +4669,25 @@ HTMLInputElement::GetValueAsDate(const n
  * -The day must be exactly 2 digit long, and 01 <= day <= maxday
  *  Where maxday is the number of days in the month 'month' and year 'year'
  */
 
   if (aValue.Length() < 10) {
     return false;
   }
 
-  uint32_t endOfYearOffset = 0;
-  for (; NS_IsAsciiDigit(aValue[endOfYearOffset]); ++endOfYearOffset);
-
-  // The year must be at least 4 digits long.
-  if (aValue[endOfYearOffset] != '-' || endOfYearOffset < 4) {
+  uint32_t endOfYearOffset = aValue.Length() - 6;
+  
+  if (aValue[endOfYearOffset]     != '-' ||
+      aValue[endOfYearOffset + 3] != '-') {
     return false;
   }
 
-  // Now, we know where is the next '-' and what should be the size of the
-  // string.
-  if (aValue[endOfYearOffset + 3] != '-' ||
-      aValue.Length() != 10 + (endOfYearOffset - 4)) {
-    return false;
-  }
-
-  nsresult ec;
-  *aYear = PromiseFlatString(StringHead(aValue, endOfYearOffset)).ToInteger(&ec);
-  if (NS_FAILED(ec) || *aYear == 0) {
+  if (!DigitSubStringToNumber(aValue, 0, endOfYearOffset, aYear) ||
+      *aYear < 1) {
     return false;
   }
 
   if (!DigitSubStringToNumber(aValue, endOfYearOffset + 1, 2, aMonth) ||
       *aMonth < 1 || *aMonth > 12) {
     return false;
   }
 
--- a/content/media/Latency.h
+++ b/content/media/Latency.h
@@ -8,17 +8,17 @@
 #define MOZILLA_LATENCY_H
 
 #include "mozilla/TimeStamp.h"
 #include "prlog.h"
 #include "nsCOMPtr.h"
 #include "nsIThread.h"
 #include "mozilla/Monitor.h"
 #include "nsISupportsImpl.h"
-#include "nsObserverService.h"
+#include "nsIObserver.h"
 
 class AsyncLatencyLogger;
 class LogEvent;
 
 PRLogModuleInfo* GetLatencyLog();
 
 // This class is a singleton. It is refcounted.
 class AsyncLatencyLogger : public nsIObserver
--- a/content/media/MediaTaskQueue.h
+++ b/content/media/MediaTaskQueue.h
@@ -18,21 +18,23 @@ namespace mozilla {
 
 class SharedThreadPool;
 
 // Abstracts executing runnables in order in a thread pool. The runnables
 // dispatched to the MediaTaskQueue will be executed in the order in which
 // they're received, and are guaranteed to not be executed concurrently.
 // They may be executed on different threads, and a memory barrier is used
 // to make this threadsafe for objects that aren't already threadsafe.
-class MediaTaskQueue : public AtomicRefCounted<MediaTaskQueue> {
+class MediaTaskQueue MOZ_FINAL {
+  ~MediaTaskQueue();
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(MediaTaskQueue)
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaTaskQueue)
+
   MediaTaskQueue(TemporaryRef<SharedThreadPool> aPool);
-  ~MediaTaskQueue();
 
   nsresult Dispatch(nsIRunnable* aRunnable);
 
   // Removes all pending tasks from the task queue, and blocks until
   // the currently running task (if any) finishes.
   void Flush();
 
   // Blocks until all tasks finish executing, then shuts down the task queue
--- a/content/media/fmp4/PlatformDecoderModule.h
+++ b/content/media/fmp4/PlatformDecoderModule.h
@@ -138,20 +138,22 @@ public:
 //
 // All functions must be threadsafe, and be able to be called on an
 // arbitrary thread.
 //
 // Decoding is done asynchronously. Any async work can be done on the
 // MediaTaskQueue passed into the PlatformDecoderModules's Create*Decoder()
 // function. This may not be necessary for platforms with async APIs
 // for decoding.
-class MediaDataDecoder : public AtomicRefCounted<MediaDataDecoder> {
+class MediaDataDecoder {
+protected:
+  virtual ~MediaDataDecoder() {};
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(MediaDataDecoder)
-  virtual ~MediaDataDecoder() {};
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDataDecoder)
 
   // Initialize the decoder. The decoder should be ready to decode after
   // this returns. The decoder should do any initialization here, rather
   // than in its constructor or PlatformDecoderModule::Create*Decoder(),
   // so that if the MP4Reader needs to shutdown during initialization,
   // it can call Shutdown() to cancel this operation. Any initialization
   // that requires blocking the calling thread in this function *must*
   // be done here so that it can be canceled by calling Shutdown()!
--- a/content/media/fmp4/wmf/MFTDecoder.h
+++ b/content/media/fmp4/wmf/MFTDecoder.h
@@ -9,21 +9,23 @@
 
 #include "WMF.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "nsIThread.h"
 
 namespace mozilla {
 
-class MFTDecoder : public AtomicRefCounted<MFTDecoder> {
+class MFTDecoder MOZ_FINAL {
+  ~MFTDecoder();
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(MTFDecoder)
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MFTDecoder)
+
   MFTDecoder();
-  ~MFTDecoder();
 
   // Creates the MFT. First thing to do as part of setup.
   //
   // Params:
   //  - aMFTClsID the clsid used by CoCreateInstance to instantiate the
   //    decoder MFT.
   HRESULT Create(const GUID& aMFTClsID);
 
new file mode 100644
--- /dev/null
+++ b/content/media/gtest/TestVideoTrackEncoder.cpp
@@ -0,0 +1,296 @@
+/* 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 "gtest/gtest.h"
+#include <algorithm>
+
+#include "mozilla/ArrayUtils.h"
+#include "VP8TrackEncoder.h"
+#include "ImageContainer.h"
+#include "MediaStreamGraph.h"
+#include "WebMWriter.h" // TODO: it's weird to include muxer header to get the class definition of VP8 METADATA
+
+using ::testing::TestWithParam;
+using ::testing::Values;
+
+using namespace mozilla::layers;
+using namespace mozilla;
+
+// A helper object to generate of different YUV planes.
+class YUVBufferGenerator {
+public:
+  YUVBufferGenerator() {}
+
+  void Init(const mozilla::gfx::IntSize &aSize)
+  {
+    mImageSize = aSize;
+
+    int yPlaneLen = aSize.width * aSize.height;
+    int cbcrPlaneLen = (yPlaneLen + 1) / 2;
+    int frameLen = yPlaneLen + cbcrPlaneLen;
+
+    // Generate source buffer.
+    mSourceBuffer.SetLength(frameLen);
+
+    // Fill Y plane.
+    memset(mSourceBuffer.Elements(), 0x10, yPlaneLen);
+
+    // Fill Cb/Cr planes.
+    memset(mSourceBuffer.Elements() + yPlaneLen, 0x80, cbcrPlaneLen);
+  }
+
+  mozilla::gfx::IntSize GetSize() const
+  {
+    return mImageSize;
+  }
+
+  void Generate(nsTArray<nsRefPtr<Image> > &aImages)
+  {
+    aImages.AppendElement(CreateI420Image());
+    aImages.AppendElement(CreateNV12Image());
+    aImages.AppendElement(CreateNV21Image());
+  }
+
+private:
+  Image *CreateI420Image()
+  {
+    PlanarYCbCrImage *image = new PlanarYCbCrImage(new BufferRecycleBin());
+    PlanarYCbCrData data;
+
+    const uint32_t yPlaneSize = mImageSize.width * mImageSize.height;
+    const uint32_t halfWidth = (mImageSize.width + 1) / 2;
+    const uint32_t halfHeight = (mImageSize.height + 1) / 2;
+    const uint32_t uvPlaneSize = halfWidth * halfHeight;
+
+    // Y plane.
+    uint8_t *y = mSourceBuffer.Elements();
+    data.mYChannel = y;
+    data.mYSize.width = mImageSize.width;
+    data.mYSize.height = mImageSize.height;
+    data.mYStride = mImageSize.width;
+    data.mYSkip = 0;
+
+    // Cr plane.
+    uint8_t *cr = y + yPlaneSize + uvPlaneSize;
+    data.mCrChannel = cr;
+    data.mCrSkip = 0;
+
+    // Cb plane
+    uint8_t *cb = y + yPlaneSize;
+    data.mCbChannel = cb;
+    data.mCbSkip = 0;
+
+    // CrCb plane vectors.
+    data.mCbCrStride = halfWidth;
+    data.mCbCrSize.width = halfWidth;
+    data.mCbCrSize.height = halfHeight;
+
+    image->SetData(data);
+    return image;
+  }
+
+  Image *CreateNV12Image()
+  {
+    PlanarYCbCrImage *image = new PlanarYCbCrImage(new BufferRecycleBin());
+    PlanarYCbCrData data;
+
+    const uint32_t yPlaneSize = mImageSize.width * mImageSize.height;
+    const uint32_t halfWidth = (mImageSize.width + 1) / 2;
+    const uint32_t halfHeight = (mImageSize.height + 1) / 2;
+
+    // Y plane.
+    uint8_t *y = mSourceBuffer.Elements();
+    data.mYChannel = y;
+    data.mYSize.width = mImageSize.width;
+    data.mYSize.height = mImageSize.height;
+    data.mYStride = mImageSize.width;
+    data.mYSkip = 0;
+
+    // Cr plane.
+    uint8_t *cr = y + yPlaneSize;
+    data.mCrChannel = cr;
+    data.mCrSkip = 1;
+
+    // Cb plane
+    uint8_t *cb = y + yPlaneSize + 1;
+    data.mCbChannel = cb;
+    data.mCbSkip = 1;
+
+    // 4:2:0.
+    data.mCbCrStride = mImageSize.width;
+    data.mCbCrSize.width = halfWidth;
+    data.mCbCrSize.height = halfHeight;
+
+    image->SetData(data);
+    return image;
+  }
+
+  Image *CreateNV21Image()
+  {
+    PlanarYCbCrImage *image = new PlanarYCbCrImage(new BufferRecycleBin());
+    PlanarYCbCrData data;
+
+    const uint32_t yPlaneSize = mImageSize.width * mImageSize.height;
+    const uint32_t halfWidth = (mImageSize.width + 1) / 2;
+    const uint32_t halfHeight = (mImageSize.height + 1) / 2;
+
+    // Y plane.
+    uint8_t *y = mSourceBuffer.Elements();
+    data.mYChannel = y;
+    data.mYSize.width = mImageSize.width;
+    data.mYSize.height = mImageSize.height;
+    data.mYStride = mImageSize.width;
+    data.mYSkip = 0;
+
+    // Cr plane.
+    uint8_t *cr = y + yPlaneSize + 1;
+    data.mCrChannel = cr;
+    data.mCrSkip = 1;
+
+    // Cb plane
+    uint8_t *cb = y + yPlaneSize;
+    data.mCbChannel = cb;
+    data.mCbSkip = 1;
+
+    // 4:2:0.
+    data.mCbCrStride = mImageSize.width;
+    data.mCbCrSize.width = halfWidth;
+    data.mCbCrSize.height = halfHeight;
+
+    image->SetData(data);
+    return image;
+  }
+
+private:
+  mozilla::gfx::IntSize mImageSize;
+  nsTArray<uint8_t> mSourceBuffer;
+};
+
+struct InitParam {
+  bool mShouldSucceed;  // This parameter should cause success or fail result
+  int  mWidth;          // frame width
+  int  mHeight;         // frame height
+  mozilla::TrackRate mTrackRate; // track rate. 90K is the most commond track rate.
+};
+
+class TestVP8TrackEncoder: public VP8TrackEncoder
+{
+public:
+  ::testing::AssertionResult TestInit(const InitParam &aParam)
+  {
+    nsresult result = Init(aParam.mWidth, aParam.mHeight, aParam.mWidth, aParam.mHeight, aParam.mTrackRate);
+
+    if (((NS_FAILED(result) && aParam.mShouldSucceed)) || (NS_SUCCEEDED(result) && !aParam.mShouldSucceed))
+    {
+      return ::testing::AssertionFailure()
+                << " width = " << aParam.mWidth
+                << " height = " << aParam.mHeight
+                << " TrackRate = " << aParam.mTrackRate << ".";
+    }
+    else
+    {
+      return ::testing::AssertionSuccess();
+    }
+  }
+};
+
+// Init test
+TEST(VP8VideoTrackEncoder, Initialization)
+{
+  InitParam params[] = {
+    // Failure cases.
+    { false, 640, 480, 0 },      // Trackrate should be larger than 1.
+    { false, 640, 480, -1 },     // Trackrate should be larger than 1.
+    { false, 0, 0, 90000 },      // Height/ width should be larger than 1.
+    { false, 0, 1, 90000 },      // Height/ width should be larger than 1.
+    { false, 1, 0, 90000},       // Height/ width should be larger than 1.
+
+    // Success cases
+    { true, 640, 480, 90000},    // Standard VGA
+    { true, 800, 480, 90000},    // Standard WVGA
+    { true, 960, 540, 90000},    // Standard qHD
+    { true, 1280, 720, 90000}    // Standard HD
+  };
+
+  for (size_t i = 0; i < ArrayLength(params); i++)
+  {
+    TestVP8TrackEncoder encoder;
+    EXPECT_TRUE(encoder.TestInit(params[i]));
+  }
+}
+
+// Get MetaData test
+TEST(VP8VideoTrackEncoder, FetchMetaData)
+{
+  InitParam params[] = {
+    // Success cases
+    { true, 640, 480, 90000},    // Standard VGA
+    { true, 800, 480, 90000},    // Standard WVGA
+    { true, 960, 540, 90000},    // Standard qHD
+    { true, 1280, 720, 90000}    // Standard HD
+  };
+
+  for (size_t i = 0; i < ArrayLength(params); i++)
+  {
+    TestVP8TrackEncoder encoder;
+    EXPECT_TRUE(encoder.TestInit(params[i]));
+
+    nsRefPtr<TrackMetadataBase> meta = encoder.GetMetadata();
+    nsRefPtr<VP8Metadata> vp8Meta(static_cast<VP8Metadata*>(meta.get()));
+
+    // METADATA should be depend on how to initiate encoder.
+    EXPECT_TRUE(vp8Meta->mWidth == params[i].mWidth);
+    EXPECT_TRUE(vp8Meta->mHeight == params[i].mHeight);
+  }
+}
+
+// Encode test
+TEST(VP8VideoTrackEncoder, FrameEncode)
+{
+  // Initiate VP8 encoder
+  TestVP8TrackEncoder encoder;
+  InitParam param = {true, 640, 480, 90000};
+  encoder.TestInit(param);
+
+  // Create YUV images as source.
+  nsTArray<nsRefPtr<Image>> images;
+  YUVBufferGenerator generator;
+  generator.Init(mozilla::gfx::IntSize(640, 480));
+  generator.Generate(images);
+
+  // Put generated YUV frame into video segment.
+  // Duration of each frame is 1 second.
+  VideoSegment segment;
+  for (nsTArray<nsRefPtr<Image>>::size_type i = 0; i < images.Length(); i++)
+  {
+    nsRefPtr<Image> image = images[i];
+    segment.AppendFrame(image.forget(), mozilla::TrackTicks(90000), generator.GetSize());
+  }
+
+  // track change notification.
+  encoder.NotifyQueuedTrackChanges(nullptr, 0, 0, 0, 0, segment);
+
+  // Pull Encoded Data back from encoder.
+  EncodedFrameContainer container;
+  EXPECT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
+}
+
+// EOS test
+TEST(VP8VideoTrackEncoder, EncodeComplete)
+{
+  // Initiate VP8 encoder
+  TestVP8TrackEncoder encoder;
+  InitParam param = {true, 640, 480, 90000};
+  encoder.TestInit(param);
+
+  // track end notification.
+  VideoSegment segment;
+  encoder.NotifyQueuedTrackChanges(nullptr, 0, 0, 0, MediaStreamListener::TRACK_EVENT_ENDED, segment);
+
+  // Pull Encoded Data back from encoder. Since we have sent
+  // EOS to encoder, encoder.GetEncodedTrack should return
+  // NS_OK immidiately.
+  EncodedFrameContainer container;
+  EXPECT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
+}
--- a/content/media/gtest/moz.build
+++ b/content/media/gtest/moz.build
@@ -6,16 +6,20 @@
 
 LIBRARY_NAME = 'media_gtest'
 
 UNIFIED_SOURCES += [
     'TestAudioCompactor.cpp',
     'TestTrackEncoder.cpp',
 ]
 
+if CONFIG['MOZ_WEBM_ENCODER']:
+    UNIFIED_SOURCES += ['TestVideoTrackEncoder.cpp',
+]
+
 EXPORT_LIBRARY = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '/content/media/encoder',
 ]
 
--- a/content/svg/content/src/SVGFEImageElement.cpp
+++ b/content/svg/content/src/SVGFEImageElement.cpp
@@ -3,16 +3,18 @@
  * 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 "mozilla/dom/SVGFEImageElement.h"
 
 #include "mozilla/EventStates.h"
 #include "mozilla/dom/SVGFEImageElementBinding.h"
 #include "mozilla/dom/SVGFilterElement.h"
+#include "mozilla/gfx/2D.h"
+#include "mozilla/RefPtr.h"
 #include "nsContentUtils.h"
 #include "nsLayoutUtils.h"
 #include "nsSVGUtils.h"
 #include "nsNetUtil.h"
 #include "imgIContainer.h"
 #include "gfx2DGlue.h"
 
 NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEImage)
@@ -206,32 +208,26 @@ SVGFEImageElement::GetPrimitiveDescripti
   GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
              getter_AddRefs(currentRequest));
 
   nsCOMPtr<imgIContainer> imageContainer;
   if (currentRequest) {
     currentRequest->GetImage(getter_AddRefs(imageContainer));
   }
 
-  nsRefPtr<gfxASurface> currentFrame;
+  RefPtr<SourceSurface> image;
   if (imageContainer) {
-    currentFrame =
-      imageContainer->GetFrame(imgIContainer::FRAME_CURRENT,
-                               imgIContainer::FLAG_SYNC_DECODE);
+    image = imageContainer->GetFrame(imgIContainer::FRAME_CURRENT,
+                                     imgIContainer::FLAG_SYNC_DECODE);
   }
 
-  if (!currentFrame) {
+  if (!image) {
     return FilterPrimitiveDescription(PrimitiveType::Empty);
   }
 
-  gfxPlatform* platform = gfxPlatform::GetPlatform();
-  DrawTarget* dt = platform->ScreenReferenceDrawTarget();
-  RefPtr<SourceSurface> image =
-    platform->GetSourceSurfaceForSurface(dt, currentFrame);
-
   IntSize nativeSize;
   imageContainer->GetWidth(&nativeSize.width);
   imageContainer->GetHeight(&nativeSize.height);
 
   Matrix viewBoxTM =
     SVGContentUtils::GetViewBoxTransform(aFilterSubregion.width, aFilterSubregion.height,
                                          0, 0, nativeSize.width, nativeSize.height,
                                          mPreserveAspectRatio);
--- a/dom/apps/src/AppsUtils.jsm
+++ b/dom/apps/src/AppsUtils.jsm
@@ -4,27 +4,27 @@
 
 "use strict";
 
 const Cu = Components.utils;
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
 
-Cu.import("resource://gre/modules/FileUtils.jsm");
 Cu.import("resource://gre/modules/osfile.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/Task.jsm");
-Cu.import("resource://gre/modules/WebappOSUtils.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Promise.jsm");
 
-XPCOMUtils.defineLazyServiceGetter(this, "NetworkUtil",
-                                   "@mozilla.org/network/util;1",
-                                   "nsINetUtil");
+XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
+  "resource://gre/modules/FileUtils.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "WebappOSUtils",
+  "resource://gre/modules/WebappOSUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
   "resource://gre/modules/NetUtil.jsm");
 
 // Shared code for AppsServiceChild.jsm, Webapps.jsm and Webapps.js
 
 this.EXPORTED_SYMBOLS = ["AppsUtils", "ManifestHelper", "isAbsoluteURI"];
 
@@ -337,17 +337,18 @@ this.AppsUtils = {
     }
     return true;
   },
 
   checkManifestContentType: function
      checkManifestContentType(aInstallOrigin, aWebappOrigin, aContentType) {
     let hadCharset = { };
     let charset = { };
-    let contentType = NetworkUtil.parseContentType(aContentType, charset, hadCharset);
+    let netutil = Cc["@mozilla.org/network/util;1"].getService(Ci.nsINetUtil);
+    let contentType = netutil.parseContentType(aContentType, charset, hadCharset);
     if (aInstallOrigin != aWebappOrigin &&
         contentType != "application/x-web-app-manifest+json") {
       return false;
     }
     return true;
   },
 
   /**
--- a/dom/bluetooth/BluetoothProfileController.h
+++ b/dom/bluetooth/BluetoothProfileController.h
@@ -3,17 +3,17 @@
 /* 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_dom_bluetooth_bluetoothprofilecontroller_h__
 #define mozilla_dom_bluetooth_bluetoothprofilecontroller_h__
 
 #include "BluetoothUuid.h"
-#include "mozilla/RefPtr.h"
+#include "nsISupportsImpl.h"
 #include "nsAutoPtr.h"
 #include "nsITimer.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 /*
  * Class of Device(CoD): 32-bit unsigned integer
  *
@@ -52,20 +52,22 @@ BEGIN_BLUETOOTH_NAMESPACE
 
 // Pointing device: sub-field of minor device class (Bit 7)
 #define IS_POINTING_DEVICE(cod)      ((GET_MINOR_DEVICE_CLASS(cod) & 0x20) >> 5)
 
 class BluetoothProfileManagerBase;
 class BluetoothReplyRunnable;
 typedef void (*BluetoothProfileControllerCallback)();
 
-class BluetoothProfileController : public RefCounted<BluetoothProfileController>
+class BluetoothProfileController MOZ_FINAL
 {
+  ~BluetoothProfileController();
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(BluetoothProfileController)
+  NS_INLINE_DECL_REFCOUNTING(BluetoothProfileController)
   /**
    * @param aConnect:       If it's a connect request, the value should be set
    *                        to true. For disconnect request, set it to false.
    * @param aDeviceAddress: The address of remote device.
    * @param aRunnable:      Once the controller has done, the runnable will be
    *                        replied. When all connection/disconnection attemps
    *                        have failed, an error is fired. In other words,
    *                        reply a success if any attemp successes.
@@ -78,17 +80,16 @@ public:
    *                        aCod or disconnect all connected profiles.
    */
   BluetoothProfileController(bool aConnect,
                              const nsAString& aDeviceAddress,
                              BluetoothReplyRunnable* aRunnable,
                              BluetoothProfileControllerCallback aCallback,
                              uint16_t aServiceUuid,
                              uint32_t aCod = 0);
-  ~BluetoothProfileController();
 
   /**
    * The controller starts connecting/disconnecting profiles one by one
    * according to the order in array mProfiles.
    */
   void StartSession();
 
   /**
--- a/dom/browser-element/BrowserElementPanning.js
+++ b/dom/browser-element/BrowserElementPanning.js
@@ -24,16 +24,37 @@ const ContentPanning = {
   // Are we listening to touch or mouse events?
   watchedEventsType: '',
 
   // Are mouse events being delivered to this content along with touch
   // events, in violation of spec?
   hybridEvents: false,
 
   init: function cp_init() {
+    // If APZ is enabled, we do active element handling in C++
+    // (see widget/xpwidgets/ActiveElementManager.h), and panning
+    // itself in APZ, so we don't need to handle any touch events here.
+    if (docShell.asyncPanZoomEnabled === false) {
+      this._setupListenersForPanning();
+    }
+
+    addEventListener("unload",
+		     this._unloadHandler.bind(this),
+		     /* useCapture = */ false,
+		     /* wantsUntrusted = */ false);
+
+    addMessageListener("Viewport:Change", this._recvViewportChange.bind(this));
+    addMessageListener("Gesture:DoubleTap", this._recvDoubleTap.bind(this));
+    addEventListener("visibilitychange", this._handleVisibilityChange.bind(this));
+    kObservedEvents.forEach((topic) => {
+      Services.obs.addObserver(this, topic, false);
+    });
+  },
+
+  _setupListenersForPanning: function cp_setupListenersForPanning() {
     var events;
     try {
       content.document.createEvent('TouchEvent');
       events = ['touchstart', 'touchend', 'touchmove'];
       this.watchedEventsType = 'touch';
 #ifdef MOZ_WIDGET_GONK
       // The gonk widget backend does not deliver mouse events per
       // spec.  Third-party content isn't exposed to this behavior,
@@ -55,28 +76,16 @@ const ContentPanning = {
 
     events.forEach(function(type) {
       // Using the system group for mouse/touch events to avoid
       // missing events if .stopPropagation() has been called.
       els.addSystemEventListener(global, type,
                                  this.handleEvent.bind(this),
                                  /* useCapture = */ false);
     }.bind(this));
-
-    addEventListener("unload",
-		     this._unloadHandler.bind(this),
-		     /* useCapture = */ false,
-		     /* wantsUntrusted = */ false);
-
-    addMessageListener("Viewport:Change", this._recvViewportChange.bind(this));
-    addMessageListener("Gesture:DoubleTap", this._recvDoubleTap.bind(this));
-    addEventListener("visibilitychange", this._handleVisibilityChange.bind(this));
-    kObservedEvents.forEach((topic) => {
-      Services.obs.addObserver(this, topic, false);
-    });
   },
 
   handleEvent: function cp_handleEvent(evt) {
     // Ignore events targeting a <iframe mozbrowser> since those will be
     // handle by the BrowserElementPanning.js instance of it.
     if (evt.target instanceof Ci.nsIMozBrowserFrame) {
       return;
     }
@@ -190,18 +199,17 @@ const ContentPanning = {
     }
 
     this.position.set(screenX, screenY);
     KineticPanning.reset();
     KineticPanning.record(new Point(0, 0), evt.timeStamp);
 
     // We prevent start events to avoid sending a focus event at the end of this
     // touch series. See bug 889717.
-    if (docShell.asyncPanZoomEnabled === false &&
-        (this.panning || this.preventNextClick)) {
+    if ((this.panning || this.preventNextClick)) {
       evt.preventDefault();
     }
   },
 
   onTouchEnd: function cp_onTouchEnd(evt) {
     let touch = null;
     if (!this.dragging ||
         (this.watchedEventsType == 'touch' &&
@@ -230,17 +238,17 @@ const ContentPanning = {
     }
 
     if (this.target && click && (this.panning || this.preventNextClick)) {
       if (this.hybridEvents) {
         let target = this.target;
         let view = target.ownerDocument ? target.ownerDocument.defaultView
                                         : target;
         view.addEventListener('click', this, true, true);
-      } else if (docShell.asyncPanZoomEnabled === false) {
+      } else {
         // We prevent end events to avoid sending a focus event. See bug 889717.
         evt.preventDefault();
       }
     } else if (this.target && click && !this.panning) {
       this.notify(this._activationTimer);
     }
 
     this._finishPanning();
@@ -279,28 +287,25 @@ const ContentPanning = {
       this._resetActive();
     }
 
     // There's no possibility of us panning anything.
     if (!this.scrollCallback) {
       return;
     }
 
-    // If the application is not managed by the AsyncPanZoomController, then
-    // scroll manually.
-    if (docShell.asyncPanZoomEnabled === false) {
-      this.scrollCallback(delta.scale(-1));
-    }
+    // Scroll manually.
+    this.scrollCallback(delta.scale(-1));
 
     if (!this.panning && isPan) {
       this.panning = true;
       this._activationTimer.cancel();
     }
 
-    if (this.panning && docShell.asyncPanZoomEnabled === false) {
+    if (this.panning) {
       // Only do this when we're actually executing a pan gesture.
       // Otherwise synthetic mouse events will be canceled.
       evt.stopPropagation();
       evt.preventDefault();
     }
   },
 
   // nsITimerCallback
@@ -587,19 +592,18 @@ const ContentPanning = {
     return (showing > 0.9 && (ratioW > 0.9 || ratioH > 0.9)); 
   },
 
   _finishPanning: function() {
     this.dragging = false;
     delete this.primaryPointerId;
     this._activationTimer.cancel();
 
-    // If there is a scroll action but the application is not managed by
-    // the AsyncPanZoom controller, let's do a manual kinetic panning action.
-    if (this.panning && docShell.asyncPanZoomEnabled === false) {
+    // If there is a scroll action, let's do a manual kinetic panning action.
+    if (this.panning) {
       KineticPanning.start(this);
     }
   },
 
   _unloadHandler: function() {
     kObservedEvents.forEach((topic) => {
       Services.obs.removeObserver(this, topic);
     });
--- a/dom/camera/CameraControlImpl.h
+++ b/dom/camera/CameraControlImpl.h
@@ -14,18 +14,16 @@
 #include "AutoRwLock.h"
 #include "nsIDOMDeviceStorage.h"
 #include "ICameraControl.h"
 #include "CameraCommon.h"
 #include "DeviceStorage.h"
 #include "DeviceStorageFileDescriptor.h"
 #include "CameraControlListener.h"
 
-class DeviceStorageFileDescriptor;
-
 namespace mozilla {
 
 namespace layers {
   class Image;
 }
 
 class RecorderProfileManager;
 
--- a/dom/camera/DOMCameraManager.cpp
+++ b/dom/camera/DOMCameraManager.cpp
@@ -4,17 +4,17 @@
 
 #include "DOMCameraManager.h"
 #include "nsDebug.h"
 #include "jsapi.h"
 #include "Navigator.h"
 #include "nsPIDOMWindow.h"
 #include "mozilla/Services.h"
 #include "nsContentPermissionHelper.h"
-#include "nsObserverService.h"
+#include "nsIObserverService.h"
 #include "nsIPermissionManager.h"
 #include "DOMCameraControl.h"
 #include "nsDOMClassInfo.h"
 #include "CameraCommon.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/CameraManagerBinding.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 #include "mozilla/dom/TabChild.h"
--- a/dom/camera/ICameraControl.h
+++ b/dom/camera/ICameraControl.h
@@ -5,17 +5,17 @@
 #ifndef DOM_CAMERA_ICAMERACONTROL_H
 #define DOM_CAMERA_ICAMERACONTROL_H
 
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "nsISupportsImpl.h"
 
-class DeviceStorageFileDescriptor;
+struct DeviceStorageFileDescriptor;
 
 class nsIFile;
 
 namespace mozilla {
 
 class CameraControlListener;
 class RecorderProfileManager;
 
--- a/dom/devicestorage/DeviceStorage.h
+++ b/dom/devicestorage/DeviceStorage.h
@@ -316,23 +316,17 @@ private:
   bool mIsWatchingFile;
   bool mAllowedToWatchFile;
 
   nsresult Notify(const char* aReason, class DeviceStorageFile* aFile);
 
   friend class WatchFileEvent;
   friend class DeviceStorageRequest;
 
-  class VolumeNameCache : public mozilla::RefCounted<VolumeNameCache>
-  {
-  public:
-    MOZ_DECLARE_REFCOUNTED_TYPENAME(VolumeNameCache)
-    nsTArray<nsString>  mVolumeNames;
-  };
-  static mozilla::StaticRefPtr<VolumeNameCache> sVolumeNameCache;
+  static mozilla::StaticAutoPtr<nsTArray<nsString>> sVolumeNameCache;
 
 #ifdef MOZ_WIDGET_GONK
   nsString mLastStatus;
   void DispatchMountChangeEvent(nsAString& aVolumeStatus);
 #endif
 
   // nsIDOMDeviceStorage.type
   enum {
--- a/dom/devicestorage/DeviceStorageFileDescriptor.h
+++ b/dom/devicestorage/DeviceStorageFileDescriptor.h
@@ -4,18 +4,16 @@
  * 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 DeviceStorageFileDescriptor_h
 #define DeviceStorageFileDescriptor_h
 
 #include "mozilla/ipc/FileDescriptor.h"
 
-class DeviceStorageFileDescriptor MOZ_FINAL
-  : public mozilla::RefCounted<DeviceStorageFileDescriptor>
+struct DeviceStorageFileDescriptor MOZ_FINAL
 {
-public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(DeviceStorageFileDescriptor)
+  NS_INLINE_DECL_REFCOUNTING(DeviceStorageFileDescriptor)
   nsRefPtr<DeviceStorageFile> mDSFile;
   mozilla::ipc::FileDescriptor mFileDescriptor;
 };
 
 #endif
--- a/dom/devicestorage/DeviceStorageRequestChild.h
+++ b/dom/devicestorage/DeviceStorageRequestChild.h
@@ -4,17 +4,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_devicestorage_DeviceStorageRequestChild_h
 #define mozilla_dom_devicestorage_DeviceStorageRequestChild_h
 
 #include "mozilla/dom/devicestorage/PDeviceStorageRequestChild.h"
 
 class DeviceStorageFile;
-class DeviceStorageFileDescriptor;
+struct DeviceStorageFileDescriptor;
 
 namespace mozilla {
 namespace dom {
 
 class DOMRequest;
 
 namespace devicestorage {
 
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -110,25 +110,26 @@ DeviceStorageUsedSpaceCache::CreateOrGet
 
   MOZ_ASSERT(NS_IsMainThread());
 
   sDeviceStorageUsedSpaceCache = new DeviceStorageUsedSpaceCache();
   ClearOnShutdown(&sDeviceStorageUsedSpaceCache);
   return sDeviceStorageUsedSpaceCache;
 }
 
-TemporaryRef<DeviceStorageUsedSpaceCache::CacheEntry>
+already_AddRefed<DeviceStorageUsedSpaceCache::CacheEntry>
 DeviceStorageUsedSpaceCache::GetCacheEntry(const nsAString& aStorageName)
 {
-  nsTArray<RefPtr<CacheEntry> >::size_type numEntries = mCacheEntries.Length();
-  nsTArray<RefPtr<CacheEntry> >::index_type i;
+  nsTArray<nsRefPtr<CacheEntry>>::size_type numEntries = mCacheEntries.Length();
+  nsTArray<nsRefPtr<CacheEntry>>::index_type i;
   for (i = 0; i < numEntries; i++) {
-    RefPtr<CacheEntry> cacheEntry = mCacheEntries[i];
+    nsRefPtr<CacheEntry>& cacheEntry = mCacheEntries[i];
     if (cacheEntry->mStorageName.Equals(aStorageName)) {
-      return cacheEntry;
+      nsRefPtr<CacheEntry> addRefedCacheEntry = cacheEntry;
+      return addRefedCacheEntry.forget();
     }
   }
   return nullptr;
 }
 
 static int64_t
 GetFreeBytes(const nsAString& aStorageName)
 {
@@ -144,17 +145,17 @@ GetFreeBytes(const nsAString& aStorageNa
 
 nsresult
 DeviceStorageUsedSpaceCache::AccumUsedSizes(const nsAString& aStorageName,
                                             uint64_t* aPicturesSoFar,
                                             uint64_t* aVideosSoFar,
                                             uint64_t* aMusicSoFar,
                                             uint64_t* aTotalSoFar)
 {
-  RefPtr<CacheEntry> cacheEntry = GetCacheEntry(aStorageName);
+  nsRefPtr<CacheEntry> cacheEntry = GetCacheEntry(aStorageName);
   if (!cacheEntry || cacheEntry->mDirty) {
     return NS_ERROR_NOT_AVAILABLE;
   }
   int64_t freeBytes = GetFreeBytes(cacheEntry->mStorageName);
   if (freeBytes != cacheEntry->mFreeBytes) {
     // Free space changed, so our cached results are no longer valid.
     return NS_ERROR_NOT_AVAILABLE;
   }
@@ -169,35 +170,35 @@ DeviceStorageUsedSpaceCache::AccumUsedSi
 
 void
 DeviceStorageUsedSpaceCache::SetUsedSizes(const nsAString& aStorageName,
                                           uint64_t aPictureSize,
                                           uint64_t aVideosSize,
                                           uint64_t aMusicSize,
                                           uint64_t aTotalUsedSize)
 {
-  RefPtr<CacheEntry> cacheEntry = GetCacheEntry(aStorageName);
+  nsRefPtr<CacheEntry> cacheEntry = GetCacheEntry(aStorageName);
   if (!cacheEntry) {
     cacheEntry = new CacheEntry;
     cacheEntry->mStorageName = aStorageName;
     mCacheEntries.AppendElement(cacheEntry);
   }
   cacheEntry->mFreeBytes = GetFreeBytes(cacheEntry->mStorageName);
 
   cacheEntry->mPicturesUsedSize = aPictureSize;
   cacheEntry->mVideosUsedSize = aVideosSize;
   cacheEntry->mMusicUsedSize = aMusicSize;
   cacheEntry->mTotalUsedSize = aTotalUsedSize;
   cacheEntry->mDirty = false;
 }
 
-class GlobalDirs : public RefCounted<GlobalDirs>
+class GlobalDirs
 {
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(GlobalDirs)
+  NS_INLINE_DECL_REFCOUNTING(GlobalDirs)
 #if !defined(MOZ_WIDGET_GONK)
   nsCOMPtr<nsIFile> pictures;
   nsCOMPtr<nsIFile> videos;
   nsCOMPtr<nsIFile> music;
   nsCOMPtr<nsIFile> sdcard;
 #endif
   nsCOMPtr<nsIFile> apps;
   nsCOMPtr<nsIFile> crashes;
@@ -3174,26 +3175,25 @@ nsDOMDeviceStorage::Shutdown()
     UnregisterForSDCardChanges(this);
   }
 
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   obs->RemoveObserver(this, "file-watcher-update");
   obs->RemoveObserver(this, "disk-space-watcher");
 }
 
-StaticRefPtr<nsDOMDeviceStorage::VolumeNameCache>
-  nsDOMDeviceStorage::sVolumeNameCache;
+StaticAutoPtr<nsTArray<nsString>> nsDOMDeviceStorage::sVolumeNameCache;
 
 // static
 void
 nsDOMDeviceStorage::GetOrderedVolumeNames(
   nsDOMDeviceStorage::VolumeNameArray &aVolumeNames)
 {
-  if (sVolumeNameCache && sVolumeNameCache->mVolumeNames.Length() > 0) {
-    aVolumeNames.AppendElements(sVolumeNameCache->mVolumeNames);
+  if (sVolumeNameCache && sVolumeNameCache->Length() > 0) {
+    aVolumeNames.AppendElements(*sVolumeNameCache);
     return;
   }
 #ifdef MOZ_WIDGET_GONK
   nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
   if (vs) {
     vs->GetVolumeNames(aVolumeNames);
 
     // If the volume sdcard exists, then we want it to be first.
@@ -3204,18 +3204,18 @@ nsDOMDeviceStorage::GetOrderedVolumeName
       aVolumeNames.RemoveElementAt(sdcardIndex);
       aVolumeNames.InsertElementAt(0, NS_LITERAL_STRING("sdcard"));
     }
   }
 #endif
   if (aVolumeNames.IsEmpty()) {
     aVolumeNames.AppendElement(EmptyString());
   }
-  sVolumeNameCache = new VolumeNameCache;
-  sVolumeNameCache->mVolumeNames.AppendElements(aVolumeNames);
+  sVolumeNameCache = new nsTArray<nsString>;
+  sVolumeNameCache->AppendElements(aVolumeNames);
 }
 
 // static
 void
 nsDOMDeviceStorage::CreateDeviceStorageFor(nsPIDOMWindow* aWin,
                                            const nsAString &aType,
                                            nsDOMDeviceStorage** aStore)
 {
--- a/dom/devicestorage/nsDeviceStorage.h
+++ b/dom/devicestorage/nsDeviceStorage.h
@@ -24,17 +24,16 @@ class nsPIDOMWindow;
 #include "nsWeakPtr.h"
 #include "nsIDOMEventListener.h"
 #include "nsIObserver.h"
 #include "nsIStringBundle.h"
 #include "mozilla/Mutex.h"
 #include "prtime.h"
 #include "DeviceStorage.h"
 #include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h"
-#include "mozilla/RefPtr.h"
 #include "mozilla/StaticPtr.h"
 
 namespace mozilla {
 class ErrorResult;
 } // namespace mozilla
 
 #define POST_ERROR_EVENT_FILE_EXISTS                 "NoModificationAllowedError"
 #define POST_ERROR_EVENT_FILE_DOES_NOT_EXIST         "NotFoundError"
@@ -75,17 +74,17 @@ public:
                          const nsAString& aStorageName)
         : mCache(aCache)
         , mStorageName(aStorageName) {}
 
       ~InvalidateRunnable() {}
 
       NS_IMETHOD Run() MOZ_OVERRIDE
       {
-        mozilla::RefPtr<DeviceStorageUsedSpaceCache::CacheEntry> cacheEntry;
+        nsRefPtr<DeviceStorageUsedSpaceCache::CacheEntry> cacheEntry;
         cacheEntry = mCache->GetCacheEntry(mStorageName);
         if (cacheEntry) {
           cacheEntry->mDirty = true;
         }
         return NS_OK;
       }
     private:
       DeviceStorageUsedSpaceCache* mCache;
@@ -115,31 +114,31 @@ public:
 
   void SetUsedSizes(const nsAString& aStorageName,
                     uint64_t aPictureSize, uint64_t aVideosSize,
                     uint64_t aMusicSize, uint64_t aTotalSize);
 
 private:
   friend class InvalidateRunnable;
 
-  class CacheEntry : public mozilla::RefCounted<CacheEntry> 
+  struct CacheEntry
   {
-  public:
-    MOZ_DECLARE_REFCOUNTED_TYPENAME(DeviceStorageUsedSpaceCache::CacheEntry)
+    NS_INLINE_DECL_REFCOUNTING(DeviceStorageUsedSpaceCache::CacheEntry)
+
     bool mDirty;
     nsString mStorageName;
     int64_t  mFreeBytes;
     uint64_t mPicturesUsedSize;
     uint64_t mVideosUsedSize;
     uint64_t mMusicUsedSize;
     uint64_t mTotalUsedSize;
   };
-  mozilla::TemporaryRef<CacheEntry> GetCacheEntry(const nsAString& aStorageName);
+  already_AddRefed<CacheEntry> GetCacheEntry(const nsAString& aStorageName);
 
-  nsTArray<mozilla::RefPtr<CacheEntry> > mCacheEntries;
+  nsTArray<nsRefPtr<CacheEntry>> mCacheEntries;
 
   nsCOMPtr<nsIThread> mIOThread;
 
   static mozilla::StaticAutoPtr<DeviceStorageUsedSpaceCache> sDeviceStorageUsedSpaceCache;
 };
 
 class DeviceStorageTypeChecker MOZ_FINAL
 {
--- a/dom/interfaces/devicestorage/nsIDOMDeviceStorage.idl
+++ b/dom/interfaces/devicestorage/nsIDOMDeviceStorage.idl
@@ -7,17 +7,17 @@
 interface nsIDOMBlob;
 interface nsIDOMDOMRequest;
 interface nsIDOMDOMCursor;
 interface nsIDOMDeviceStorageChangeEvent;
 interface nsIDOMEventListener;
 interface nsIFile;
 
 %{C++
-class DeviceStorageFileDescriptor;
+struct DeviceStorageFileDescriptor;
 %}
 [ptr] native DeviceStorageFdPtr(DeviceStorageFileDescriptor);
 
 [scriptable, uuid(8b724547-3c78-4244-969a-f00a1f4ae0c3), builtinclass]
 interface nsIDOMDeviceStorage : nsIDOMEventTarget
 {
     [implicit_jscontext] attribute jsval onchange;
     nsIDOMDOMRequest add(in nsIDOMBlob aBlob);
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -45,16 +45,17 @@ using class mozilla::WidgetSelectionEven
 using class mozilla::WidgetTextEvent from "ipc/nsGUIEventIPC.h";
 using class mozilla::WidgetTouchEvent from "ipc/nsGUIEventIPC.h";
 using struct mozilla::dom::RemoteDOMEvent from "mozilla/dom/TabMessageUtils.h";
 using mozilla::dom::ScreenOrientation from "mozilla/dom/ScreenOrientation.h";
 using struct mozilla::layers::TextureFactoryIdentifier from "mozilla/layers/CompositorTypes.h";
 using mozilla::CSSPoint from "Units.h";
 using mozilla::CSSToScreenScale from "Units.h";
 using mozilla::CommandInt from "mozilla/EventForwards.h";
+using mozilla::layers::GeckoContentController::APZStateChange from "mozilla/layers/GeckoContentController.h";
 
 namespace mozilla {
 namespace dom {
 
 struct NativeKeyBinding
 {
   CommandInt[] singleLineCommands;
   CommandInt[] multiLineCommands;
@@ -405,21 +406,20 @@ child:
      * relative to the current scroll offset. In the case the "contextmenu"
      * event generated by the preceding HandleLongTap call was not handled,
      * this message is expected to generate a "mousedown" and "mouseup"
      * series of events
      */
     HandleLongTapUp(CSSPoint point, ScrollableLayerGuid aGuid);
 
     /**
-     * Notifies the child that the parent has begun or finished transforming
-     * the visible child content area. Useful for showing/hiding scrollbars.
+     * Notifies the child about various APZ state changes.
+     * See GeckoContentController::NotifyAPZStateChange() for details.
      */
-    NotifyTransformBegin(ViewID aViewId);
-    NotifyTransformEnd(ViewID aViewId);
+    NotifyAPZStateChange(ViewID aViewId, APZStateChange aChange, int aArg);
 
     /**
      * Sending an activate message moves focus to the child.
      */
     Activate();
 
     Deactivate();
 
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -69,16 +69,17 @@
 #include "nsViewportInfo.h"
 #include "JavaScriptChild.h"
 #include "APZCCallbackHelper.h"
 #include "nsILoadContext.h"
 #include "ipc/nsGUIEventIPC.h"
 #include "mozilla/gfx/Matrix.h"
 #include "UnitTransforms.h"
 #include "ClientLayerManager.h"
+#include "ActiveElementManager.h"
 
 #include "nsColorPickerProxy.h"
 
 #ifdef DEBUG
 #include "PCOMContentPermissionRequestChild.h"
 #endif /* DEBUG */
 
 #define BROWSER_ELEMENT_CHILD_SCRIPT \
@@ -682,16 +683,17 @@ TabChild::TabChild(ContentChild* aManage
   , mDidFakeShow(false)
   , mNotified(false)
   , mTriedBrowserInit(false)
   , mOrientation(eScreenOrientation_PortraitPrimary)
   , mUpdateHitRegion(false)
   , mContextMenuHandled(false)
   , mWaitingTouchListeners(false)
   , mIgnoreKeyPressEvent(false)
+  , mActiveElementManager(new ActiveElementManager())
 {
   if (!sActiveDurationMsSet) {
     Preferences::AddIntVarCache(&sActiveDurationMs,
                                 "ui.touch_activation.duration_ms",
                                 sActiveDurationMs);
     sActiveDurationMsSet = true;
   }
 }
@@ -1725,33 +1727,59 @@ TabChild::RecvHandleLongTapUp(const CSSP
     return true;
   }
 
   RecvHandleSingleTap(aPoint, aGuid);
   return true;
 }
 
 bool
-TabChild::RecvNotifyTransformBegin(const ViewID& aViewId)
+TabChild::RecvNotifyAPZStateChange(const ViewID& aViewId,
+                                   const APZStateChange& aChange,
+                                   const int& aArg)
 {
-  nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aViewId);
-  nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(sf);
-  if (scrollbarOwner) {
-    scrollbarOwner->ScrollbarActivityStarted();
+  switch (aChange)
+  {
+  case APZStateChange::TransformBegin:
+  {
+    nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aViewId);
+    nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(sf);
+    if (scrollbarOwner) {
+      scrollbarOwner->ScrollbarActivityStarted();
+    }
+    break;
   }
-  return true;
-}
-
-bool
-TabChild::RecvNotifyTransformEnd(const ViewID& aViewId)
-{
-  nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aViewId);
-  nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(sf);
-  if (scrollbarOwner) {
-    scrollbarOwner->ScrollbarActivityStopped();
+  case APZStateChange::TransformEnd:
+  {
+    nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aViewId);
+    nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(sf);
+    if (scrollbarOwner) {
+      scrollbarOwner->ScrollbarActivityStopped();
+    }
+    break;
+  }
+  case APZStateChange::StartTouch:
+  {
+    mActiveElementManager->HandleTouchStart(aArg);
+    break;
+  }
+  case APZStateChange::StartPanning:
+  {
+    mActiveElementManager->HandlePanStart();
+    break;
+  }
+  case APZStateChange::EndTouch:
+  {
+    mActiveElementManager->HandleTouchEnd(aArg);
+    break;
+  }
+  default:
+    // APZStateChange has a 'sentinel' value, and the compiler complains
+    // if an enumerator is not handled and there is no 'default' case.
+    break;
   }
   return true;
 }
 
 bool
 TabChild::RecvActivate()
 {
   nsCOMPtr<nsIWebBrowserFocus> browser = do_QueryInterface(WebNavigation());
@@ -1946,16 +1974,20 @@ TabChild::RecvRealTouchEvent(const Widge
 
   nsEventStatus status = DispatchWidgetEvent(localEvent);
 
   if (!IsAsyncPanZoomEnabled()) {
     UpdateTapState(localEvent, status);
     return true;
   }
 
+  if (aEvent.message == NS_TOUCH_START && localEvent.touches.Length() > 0) {
+    mActiveElementManager->SetTargetElement(localEvent.touches[0]->Target());
+  }
+
   nsCOMPtr<nsPIDOMWindow> outerWindow = do_GetInterface(WebNavigation());
   nsCOMPtr<nsPIDOMWindow> innerWindow = outerWindow->GetCurrentInnerWindow();
 
   if (!innerWindow || !innerWindow->HasTouchEventListeners()) {
     SendContentReceivedTouch(aGuid, false);
     return true;
   }
 
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -37,16 +37,20 @@
 class nsICachedFileDescriptorListener;
 class nsIDOMWindowUtils;
 
 namespace mozilla {
 namespace layout {
 class RenderFrameChild;
 }
 
+namespace widget {
+class ActiveElementManager;
+}
+
 namespace dom {
 
 class TabChild;
 class ClonedMessageData;
 class TabChildBase;
 
 class TabChildGlobal : public DOMEventTargetHelper,
                        public nsIContentFrameMessageManager,
@@ -223,16 +227,17 @@ class TabChild : public PBrowserChild,
                  public nsIObserver,
                  public TabContext,
                  public nsITooltipListener,
                  public TabChildBase
 {
     typedef mozilla::dom::ClonedMessageData ClonedMessageData;
     typedef mozilla::layout::RenderFrameChild RenderFrameChild;
     typedef mozilla::layout::ScrollingBehavior ScrollingBehavior;
+    typedef mozilla::widget::ActiveElementManager ActiveElementManager;
 
 public:
     /** 
      * This is expected to be called off the critical path to content
      * startup.  This is an opportunity to load things that are slow
      * on the critical path.
      */
     static void PreloadSlowThings();
@@ -291,18 +296,19 @@ public:
     virtual bool RecvHandleDoubleTap(const CSSPoint& aPoint,
                                      const mozilla::layers::ScrollableLayerGuid& aGuid) MOZ_OVERRIDE;
     virtual bool RecvHandleSingleTap(const CSSPoint& aPoint,
                                      const mozilla::layers::ScrollableLayerGuid& aGuid) MOZ_OVERRIDE;
     virtual bool RecvHandleLongTap(const CSSPoint& aPoint,
                                    const mozilla::layers::ScrollableLayerGuid& aGuid) MOZ_OVERRIDE;
     virtual bool RecvHandleLongTapUp(const CSSPoint& aPoint,
                                      const mozilla::layers::ScrollableLayerGuid& aGuid) MOZ_OVERRIDE;
-    virtual bool RecvNotifyTransformBegin(const ViewID& aViewId) MOZ_OVERRIDE;
-    virtual bool RecvNotifyTransformEnd(const ViewID& aViewId) MOZ_OVERRIDE;
+    virtual bool RecvNotifyAPZStateChange(const ViewID& aViewId,
+                                          const APZStateChange& aChange,
+                                          const int& aArg) MOZ_OVERRIDE;
     virtual bool RecvActivate() MOZ_OVERRIDE;
     virtual bool RecvDeactivate() MOZ_OVERRIDE;
     virtual bool RecvMouseEvent(const nsString& aType,
                                 const float&    aX,
                                 const float&    aY,
                                 const int32_t&  aButton,
                                 const int32_t&  aClickCount,
                                 const int32_t&  aModifiers,
@@ -539,16 +545,17 @@ private:
     bool mTriedBrowserInit;
     ScreenOrientation mOrientation;
     bool mUpdateHitRegion;
     bool mContextMenuHandled;
     bool mWaitingTouchListeners;
     void FireSingleTapEvent(LayoutDevicePoint aPoint);
 
     bool mIgnoreKeyPressEvent;
+    nsRefPtr<ActiveElementManager> mActiveElementManager;
 
     DISALLOW_EVIL_CONSTRUCTORS(TabChild);
 };
 
 }
 }
 
 #endif // mozilla_dom_TabChild_h
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -549,27 +549,22 @@ void TabParent::HandleLongTapUp(const CS
                                 int32_t aModifiers,
                                 const ScrollableLayerGuid &aGuid)
 {
   if (!mIsDestroyed) {
     unused << SendHandleLongTapUp(aPoint, aGuid);
   }
 }
 
-void TabParent::NotifyTransformBegin(ViewID aViewId)
+void TabParent::NotifyAPZStateChange(ViewID aViewId,
+                                     APZStateChange aChange,
+                                     int aArg)
 {
   if (!mIsDestroyed) {
-    unused << SendNotifyTransformBegin(aViewId);
-  }
-}
-
-void TabParent::NotifyTransformEnd(ViewID aViewId)
-{
-  if (!mIsDestroyed) {
-    unused << SendNotifyTransformEnd(aViewId);
+    unused << SendNotifyAPZStateChange(aViewId, aChange, aArg);
   }
 }
 
 void
 TabParent::Activate()
 {
   if (!mIsDestroyed) {
     unused << SendActivate();
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -207,18 +207,19 @@ public:
                          int32_t aModifiers,
                          const ScrollableLayerGuid& aGuid);
     void HandleLongTap(const CSSPoint& aPoint,
                        int32_t aModifiers,
                        const ScrollableLayerGuid& aGuid);
     void HandleLongTapUp(const CSSPoint& aPoint,
                          int32_t aModifiers,
                          const ScrollableLayerGuid& aGuid);
-    void NotifyTransformBegin(ViewID aViewId);
-    void NotifyTransformEnd(ViewID aViewId);
+    void NotifyAPZStateChange(ViewID aViewId,
+                              APZStateChange aChange,
+                              int aArg);
     void Activate();
     void Deactivate();
 
     bool MapEventCoordinatesForChildProcess(mozilla::WidgetEvent* aEvent);
     void MapEventCoordinatesForChildProcess(const LayoutDeviceIntPoint& aOffset,
                                             mozilla::WidgetEvent* aEvent);
 
     void SendMouseEvent(const nsAString& aType, float aX, float aY,
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -6,17 +6,17 @@
 #include "mozilla/Services.h"
 #include "mozilla/unused.h"
 #include "nsIMediaManager.h"
 
 #include "nsHashKeys.h"
 #include "nsGlobalWindow.h"
 #include "nsClassHashtable.h"
 #include "nsRefPtrHashtable.h"
-#include "nsObserverService.h"
+#include "nsIObserver.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 
 #include "nsPIDOMWindow.h"
 #include "nsIDOMNavigatorUserMedia.h"
 #include "nsXULAppAPI.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Preferences.h"
--- a/dom/system/gonk/AutoMounter.cpp
+++ b/dom/system/gonk/AutoMounter.cpp
@@ -158,22 +158,22 @@ protected:
 private:
     const static int kMaxErrorCount = 3; // Max number of errors before we give up
 
     int   mErrorCount;
 };
 
 /***************************************************************************/
 
-class AutoMounter : public RefCounted<AutoMounter>
+class AutoMounter
 {
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(AutoMounter)
+  NS_INLINE_DECL_REFCOUNTING(AutoMounter)
 
-  typedef nsTArray<RefPtr<Volume> > VolumeArray;
+  typedef nsTArray<RefPtr<Volume>> VolumeArray;
 
   AutoMounter()
     : mResponseCallback(new AutoMounterResponseCallback),
       mMode(AUTOMOUNTER_DISABLE)
   {
     VolumeManager::RegisterStateObserver(&mVolumeManagerStateObserver);
     Volume::RegisterObserver(&mVolumeEventObserver);
 
@@ -687,31 +687,31 @@ UsbCableEventIOThread()
 *
 *   Public API
 *
 *   Since the AutoMounter runs in IO Thread context, we need to switch
 *   to IOThread context before we can do anything.
 *
 **************************************************************************/
 
-class UsbCableObserver : public SwitchObserver,
-                         public RefCounted<UsbCableObserver>
+class UsbCableObserver MOZ_FINAL : public SwitchObserver
 {
+  ~UsbCableObserver()
+  {
+    UnregisterSwitchObserver(SWITCH_USB, this);
+  }
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(UsbCableObserver)
+  NS_INLINE_DECL_REFCOUNTING(UsbCableObserver)
+
   UsbCableObserver()
   {
     RegisterSwitchObserver(SWITCH_USB, this);
   }
 
-  ~UsbCableObserver()
-  {
-    UnregisterSwitchObserver(SWITCH_USB, this);
-  }
-
   virtual void Notify(const SwitchEvent& aEvent)
   {
     DBG("UsbCable switch device: %d state: %s\n",
         aEvent.device(), SwitchStateStr(aEvent));
     XRE_GetIOMessageLoop()->PostTask(
         FROM_HERE,
         NewRunnableFunction(UsbCableEventIOThread));
   }
--- a/dom/system/gonk/Volume.h
+++ b/dom/system/gonk/Volume.h
@@ -4,35 +4,36 @@
 
 #ifndef mozilla_system_volume_h__
 #define mozilla_system_volume_h__
 
 #include "VolumeCommand.h"
 #include "nsIVolume.h"
 #include "nsString.h"
 #include "mozilla/Observer.h"
-#include "mozilla/RefPtr.h"
+#include "nsISupportsImpl.h"
 #include "nsWhitespaceTokenizer.h"
 
 namespace mozilla {
 namespace system {
 
 /***************************************************************************
 *
 *   There is an instance of the Volume class for each volume reported
 *   from vold.
 *
 *   Each volume originates from the /system/etv/vold.fstab file.
 *
 ***************************************************************************/
 
-class Volume : public RefCounted<Volume>
+class Volume MOZ_FINAL
 {
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(Volume)
+  NS_INLINE_DECL_REFCOUNTING(Volume)
+
   Volume(const nsCSubstring& aVolumeName);
 
   typedef long STATE; // States are now defined in nsIVolume.idl
 
   static const char* StateStr(STATE aState) { return NS_VolumeStateStr(aState); }
   const char* StateStr() const  { return StateStr(mState); }
   STATE State() const           { return mState; }
 
--- a/dom/system/gonk/VolumeCommand.h
+++ b/dom/system/gonk/VolumeCommand.h
@@ -1,16 +1,17 @@
 /* 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_system_volumecommand_h__
 #define mozilla_system_volumecommand_h__
 
 #include "nsString.h"
+#include "nsISupportsImpl.h"
 #include "mozilla/RefPtr.h"
 #include <algorithm>
 #include <vold/ResponseCode.h>
 
 namespace mozilla {
 namespace system {
 
 class Volume;
@@ -27,25 +28,26 @@ class VolumeCommand;
 *   The responses from vold are all of the form:
 *
 *     <ResponseCode> <String>
 *
 *   Valid Response codes can be found in the vold/ResponseCode.h header.
 *
 ***************************************************************************/
 
-class VolumeResponseCallback : public RefCounted<VolumeResponseCallback>
+class VolumeResponseCallback
 {
+protected:
+  virtual ~VolumeResponseCallback() {}
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(VolumeResponseCallback)
+  NS_INLINE_DECL_REFCOUNTING(VolumeResponseCallback)
   VolumeResponseCallback()
     : mResponseCode(0), mPending(false) {}
 
-  virtual ~VolumeResponseCallback() {}
-
   bool Done() const
   {
     // Response codes from the 200, 400, and 500 series all indicated that
     // the command has completed.
 
     return (mResponseCode >= ResponseCode::CommandOkay)
         && (mResponseCode < ResponseCode::UnsolicitedInformational);
   }
@@ -101,36 +103,38 @@ private:
 *   Commands sent to vold need an explicit null character so we add one
 *   to the command to ensure that it's included in the length.
 *
 *   All of these commands are asynchronous in nature, and the
 *   ResponseReceived callback will be called when a response is available.
 *
 ***************************************************************************/
 
-class VolumeCommand : public RefCounted<VolumeCommand>
+class VolumeCommand
 {
+protected:
+  virtual ~VolumeCommand() {}
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(VolumeCommand)
+  NS_INLINE_DECL_REFCOUNTING(VolumeCommand)
+
   VolumeCommand(VolumeResponseCallback* aCallback)
     : mBytesConsumed(0),
       mCallback(aCallback)
   {
     SetCmd(NS_LITERAL_CSTRING(""));
   }
 
   VolumeCommand(const nsACString& aCommand, VolumeResponseCallback* aCallback)
     : mBytesConsumed(0),
       mCallback(aCallback)
   {
     SetCmd(aCommand);
   }
 
-  virtual ~VolumeCommand() {}
-
   void SetCmd(const nsACString& aCommand)
   {
     mCmd.Truncate();
 #if ANDROID_VERSION >= 17
     // JB requires a sequence number at the beginning of messages.
     // It doesn't matter what we use, so we use 0.
     mCmd = "0 ";
 #endif
--- a/dom/system/gonk/VolumeManager.h
+++ b/dom/system/gonk/VolumeManager.h
@@ -6,17 +6,17 @@
 #define mozilla_system_volumemanager_h__
 
 #include <vector>
 #include <queue>
 
 #include "base/message_loop.h"
 #include "mozilla/FileUtils.h"
 #include "mozilla/Observer.h"
-#include "mozilla/RefPtr.h"
+#include "nsISupportsImpl.h"
 #include "nsString.h"
 #include "nsTArray.h"
 
 #include "Volume.h"
 #include "VolumeCommand.h"
 
 namespace mozilla {
 namespace system {
@@ -68,26 +68,26 @@ namespace system {
 *   There is also a command line tool called vdc, which can be used to send
 *   the above commands to vold.
 *
 *   Currently, only the volume list, share/unshare, and mount/unmount
 *   commands are being used.
 *
 ***************************************************************************/
 
-class VolumeManager : public MessageLoopForIO::LineWatcher,
-                      public RefCounted<VolumeManager>
+class VolumeManager MOZ_FINAL : public MessageLoopForIO::LineWatcher
 {
+  virtual ~VolumeManager();
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(VolumeManager)
+  NS_INLINE_DECL_REFCOUNTING(VolumeManager)
 
-  typedef nsTArray<RefPtr<Volume> > VolumeArray;
+  typedef nsTArray<RefPtr<Volume>> VolumeArray;
 
   VolumeManager();
-  virtual ~VolumeManager();
 
   //-----------------------------------------------------------------------
   //
   // State related methods.
   //
   // The VolumeManager starts off in the STARTING state. Once a connection
   // is established with vold, it asks for a list of volumes, and once the
   // volume list has been received, then the VolumeManager enters the
--- a/dom/system/gonk/VolumeServiceIOThread.h
+++ b/dom/system/gonk/VolumeServiceIOThread.h
@@ -14,23 +14,24 @@ namespace system {
 
 class nsVolumeService;
 
 /***************************************************************************
 * The nsVolumeServiceIOThread is a companion class to the nsVolumeService
 * class, but whose methods are called from IOThread.
 */
 class VolumeServiceIOThread : public VolumeManager::StateObserver,
-                              public Volume::EventObserver,
-                              public RefCounted<VolumeServiceIOThread>
+                              public Volume::EventObserver
 {
+  ~VolumeServiceIOThread();
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(VolumeServiceIOThread)
+  NS_INLINE_DECL_REFCOUNTING(VolumeServiceIOThread)
+
   VolumeServiceIOThread(nsVolumeService* aVolumeService);
-  ~VolumeServiceIOThread();
 
 private:
   void  UpdateAllVolumes();
 
   virtual void Notify(const VolumeManager::StateChangedEvent& aEvent);
   virtual void Notify(Volume* const & aVolume);
 
   RefPtr<nsVolumeService>   mVolumeService;
--- a/dom/xbl/test/file_bug821850.xhtml
+++ b/dom/xbl/test/file_bug821850.xhtml
@@ -48,21 +48,22 @@ https://bugzilla.mozilla.org/show_bug.cg
              "Unexposed method should be visible to XBL");
           is(typeof bound.wrappedJSObject.unexposedMethod, 'undefined',
              "Unexposed method should not be defined in content");
           is(typeof bound.unexposedProperty, 'number',
              "Unexposed property should be visible to XBL");
           is(typeof bound.wrappedJSObject.unexposedProperty, 'undefined',
              "Unexposed property should not be defined in content");
 
-          // Check that here document.QueryInterface works
-          ok("QueryInterface" in document,
-             "Should have a document.QueryInterface here");
-          is(document.QueryInterface(Components.interfaces.nsIDOMDocument),
-             document, "Should be able to QI the document");
+          // Check that here HTMLImageElement.QueryInterface works
+          var img = document.querySelector("img");
+          ok("QueryInterface" in img,
+             "Should have a img.QueryInterface here");
+          is(img.QueryInterface(Components.interfaces.nsIImageLoadingContent),
+             img, "Should be able to QI the image");
 
           // Make sure standard constructors work right in the presence of
           // sandboxPrototype and Xray-resolved constructors.
           is(window.Function, XPCNativeWrapper(window.wrappedJSObject.Function),
              "window.Function comes from the window, not the global");
           ok(Function != window.Function, "Function constructors are distinct");
           is(Object.getPrototypeOf(Function.prototype), Object.getPrototypeOf({foo: 42}),
              "Function constructor is local");
@@ -284,13 +285,14 @@ https://bugzilla.mozilla.org/show_bug.cg
 </script>
 </head>
 <body onload="setup()">
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=821850">Mozilla Bug 821850</a>
 <p id="display"></p>
 <div id="content">
   <div id="bound">Bound element</div>
   <div id="bound2">Bound element</div>
+  <img/>
 </div>
 <pre id="test">
 </pre>
 </body>
 </html>
--- a/editor/libeditor/html/tests/browserscope/lib/richtext2/richtext2/tests/insert.py
+++ b/editor/libeditor/html/tests/browserscope/lib/richtext2/richtext2/tests/insert.py
@@ -160,55 +160,55 @@ INSERT_TESTS = {
       ]
     },
 
     { 'desc':       'insert <img>',
       'command':    'insertimage',
       'tests':      [
         { 'id':         'IIMG:url_TEXT-1_SC',
           'rte1-id':    'a-insertimage-0',
-          'desc':       'Insert image with URL "http://goo.gl/bar.png"',
-          'value':      'http://goo.gl/bar.png',
+          'desc':       'Insert image with URL "bar.png"',
+          'value':      'bar.png',
           'checkAttrs':  True,
           'pad':        'foo^bar',
-          'expected':   [ 'foo<img src="http://goo.gl/bar.png">|bar',
-                          'foo<img src="http://goo.gl/bar.png">^bar' ] },
+          'expected':   [ 'foo<img src="bar.png">|bar',
+                          'foo<img src="bar.png">^bar' ] },
 
         { 'id':         'IIMG:url_IMG-1_SO',
           'desc':       'Change existing image to new URL, selection on <img>',
-          'value':      'http://baz.com/quz.png',
+          'value':      'quz.png',
           'checkAttrs':  True,
-          'pad':        '<span>foo{<img src="http://goo.gl/bar.png">}bar</span>',
-          'expected':   [ '<span>foo<img src="http://baz.com/quz.png"/>|bar</span>',
-                          '<span>foo<img src="http://baz.com/quz.png"/>^bar</span>' ] },
+          'pad':        '<span>foo{<img src="bar.png">}bar</span>',
+          'expected':   [ '<span>foo<img src="quz.png"/>|bar</span>',
+                          '<span>foo<img src="quz.png"/>^bar</span>' ] },
 
         { 'id':         'IIMG:url_SPAN-IMG-1_SO',
           'desc':       'Change existing image to new URL, selection in text surrounding <img>',
-          'value':      'http://baz.com/quz.png',
+          'value':      'quz.png',
           'checkAttrs':  True,
-          'pad':        'foo[<img src="http://goo.gl/bar.png">]bar',
-          'expected':   [ 'foo<img src="http://baz.com/quz.png"/>|bar',
-                          'foo<img src="http://baz.com/quz.png"/>^bar' ] },
+          'pad':        'foo[<img src="bar.png">]bar',
+          'expected':   [ 'foo<img src="quz.png"/>|bar',
+                          'foo<img src="quz.png"/>^bar' ] },
 
         { 'id':         'IIMG:._SPAN-IMG-1_SO',
           'desc':       'Remove existing image or URL, selection on <img>',
           'value':      '',
           'checkAttrs':  True,
-          'pad':        '<span>foo{<img src="http://goo.gl/bar.png">}bar</span>',
+          'pad':        '<span>foo{<img src="bar.png">}bar</span>',
           'expected':   [ '<span>foo^bar</span>',
                           '<span>foo<img>|bar</span>',
                           '<span>foo<img>^bar</span>',
                           '<span>foo<img src="">|bar</span>',
                           '<span>foo<img src="">^bar</span>' ] },
 
         { 'id':         'IIMG:._IMG-1_SO',
           'desc':       'Remove existing image or URL, selection in text surrounding <img>',
           'value':      '',
           'checkAttrs':  True,
-          'pad':        'foo[<img src="http://goo.gl/bar.png">]bar',
+          'pad':        'foo[<img src="bar.png">]bar',
           'expected':   [ 'foo^bar',
                           'foo<img>|bar',
                           'foo<img>^bar',
                           'foo<img src="">|bar',
                           'foo<img src="">^bar' ] }
       ]
     },
 
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -411,17 +411,17 @@ public:
   }
 
   /*
    * Returns a DataSourceSurface with the same data as this one, but
    * guaranteed to have surface->GetType() == SurfaceType::DATA.
    */
   virtual TemporaryRef<DataSourceSurface> GetDataSurface();
 
-  DebugOnly<bool> mIsMapped;
+  bool mIsMapped;
 };
 
 /* This is an abstract object that accepts path segments. */
 class PathSink : public RefCounted<PathSink>
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathSink)
   virtual ~PathSink() {}
--- a/gfx/2d/DataSurfaceHelpers.h
+++ b/gfx/2d/DataSurfaceHelpers.h
@@ -20,27 +20,29 @@ ConvertBGRXToBGRA(uint8_t* aData, const 
  * contain |aSrcSize.width * aSrcSize.height * aBytesPerPixel| bytes.
  */
 void
 CopySurfaceDataToPackedArray(uint8_t* aSrc, uint8_t* aDst, IntSize aSrcSize,
                              int32_t aSrcStride, int32_t aBytesPerPixel);
 
 /**
  * Convert aSurface to a packed buffer in BGRA format. The pixel data is
- * returned in a buffer allocated with new uint8_t[].
+ * returned in a buffer allocated with new uint8_t[]. The caller then has
+ * ownership of the buffer and is responsible for delete[]'ing it.
  */
 uint8_t*
 SurfaceToPackedBGRA(DataSourceSurface *aSurface);
 
 /**
  * Convert aSurface to a packed buffer in BGR format. The pixel data is
- * returned in a buffer allocated with new uint8_t[].
+ * returned in a buffer allocated with new uint8_t[]. The caller then has
+ * ownership of the buffer and is responsible for delete[]'ing it.
  *
  * This function is currently only intended for use with surfaces of format
- * SurfaceFormat::B8G8R8X8 since the X components of the pixel data are simply
- * dropped (no attempt is made to un-pre-multiply alpha from the color
- * components).
+ * SurfaceFormat::B8G8R8X8 since the X components of the pixel data (if any)
+ * are simply dropped (no attempt is made to un-pre-multiply alpha from the
+ * color components).
  */
 uint8_t*
 SurfaceToPackedBGR(DataSourceSurface *aSurface);
 
 }
 }
--- a/gfx/ipc/GfxMessageUtils.h
+++ b/gfx/ipc/GfxMessageUtils.h
@@ -21,16 +21,17 @@
 #include "gfxRect.h"
 #include "nsRect.h"
 #include "nsRegion.h"
 #include "gfxTypes.h"
 #include "mozilla/layers/LayersTypes.h"
 #include "mozilla/layers/CompositorTypes.h"
 #include "FrameMetrics.h"
 #include "FilterSupport.h"
+#include "mozilla/layers/GeckoContentController.h"
 
 #ifdef _MSC_VER
 #pragma warning( disable : 4800 )
 #endif
 
 namespace mozilla {
 
 typedef gfxImageFormat PixelFormat;
@@ -1064,11 +1065,21 @@ struct ParamTraits<mozilla::gfx::FilterD
 
   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
   {
     return (ReadParam(aMsg, aIter, &aResult->mFilterSpaceBounds) &&
             ReadParam(aMsg, aIter, &aResult->mPrimitives));
   }
 };
 
+typedef mozilla::layers::GeckoContentController::APZStateChange APZStateChange;
+
+template <>
+struct ParamTraits<APZStateChange>
+  : public ContiguousTypedEnumSerializer<
+             APZStateChange,
+             APZStateChange::TransformBegin,
+             APZStateChange::APZStateChangeSentinel>
+{};
+
 } /* namespace IPC */
 
 #endif /* __GFXMESSAGEUTILS_H__ */
--- a/gfx/layers/Compositor.h
+++ b/gfx/layers/Compositor.h
@@ -132,28 +132,22 @@ enum SurfaceInitMode
 {
   INIT_MODE_NONE,
   INIT_MODE_CLEAR
 };
 
 /**
  * A base class for a platform-dependent helper for use by TextureHost.
  */
-class CompositorBackendSpecificData : public RefCounted<CompositorBackendSpecificData>
+class CompositorBackendSpecificData
 {
-public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(CompositorBackendSpecificData)
-  CompositorBackendSpecificData()
-  {
-    MOZ_COUNT_CTOR(CompositorBackendSpecificData);
-  }
-  virtual ~CompositorBackendSpecificData()
-  {
-    MOZ_COUNT_DTOR(CompositorBackendSpecificData);
-  }
+  NS_INLINE_DECL_REFCOUNTING(CompositorBackendSpecificData)
+
+protected:
+  virtual ~CompositorBackendSpecificData() {}
 };
 
 /**
  * Common interface for compositor backends.
  *
  * Compositor provides a cross-platform interface to a set of operations for
  * compositing quads. Compositor knows nothing about the layer tree. It must be
  * told everything about each composited quad - contents, location, transform,
@@ -190,31 +184,30 @@ public:
  *
  * By default, the compositor will render to the screen, to render to a target,
  * call SetTargetContext or SetRenderTarget, the latter with a target created
  * by CreateRenderTarget or CreateRenderTargetFromSource.
  *
  * The target and viewport methods can be called before any DrawQuad call and
  * affect any subsequent DrawQuad calls.
  */
-class Compositor : public RefCounted<Compositor>
+class Compositor
 {
+protected:
+  virtual ~Compositor() {}
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(Compositor)
+  NS_INLINE_DECL_REFCOUNTING(Compositor)
+
   Compositor(PCompositorParent* aParent = nullptr)
     : mCompositorID(0)
     , mDiagnosticTypes(DIAGNOSTIC_NONE)
     , mParent(aParent)
     , mScreenRotation(ROTATION_0)
   {
-    MOZ_COUNT_CTOR(Compositor);
-  }
-  virtual ~Compositor()
-  {
-    MOZ_COUNT_DTOR(Compositor);
   }
 
   virtual TemporaryRef<DataTextureSource> CreateDataTextureSource(TextureFlags aFlags = 0) = 0;
   virtual bool Initialize() = 0;
   virtual void Destroy() = 0;
 
   /**
    * Return true if the effect type is supported.
--- a/gfx/layers/Effects.h
+++ b/gfx/layers/Effects.h
@@ -32,25 +32,28 @@ namespace layers {
  * - any way in which rendering can be changed, e.g., applying a mask layer.
  *
  * During the rendering process, an effect chain is created by the layer being
  * rendered and the primary effect is added by the compositable host. Secondary
  * effects may be added by the layer or compositable. The effect chain is passed
  * to the compositor by the compositable host as a parameter to DrawQuad.
  */
 
-struct Effect : public RefCounted<Effect>
+struct Effect
 {
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(Effect)
+  NS_INLINE_DECL_REFCOUNTING(Effect)
+
   Effect(EffectTypes aType) : mType(aType) {}
 
   EffectTypes mType;
 
+  virtual void PrintInfo(nsACString& aTo, const char* aPrefix) = 0;
+
+protected:
   virtual ~Effect() {}
-  virtual void PrintInfo(nsACString& aTo, const char* aPrefix) =0;
 };
 
 // Render from a texture
 struct TexturedEffect : public Effect
 {
   TexturedEffect(EffectTypes aType,
                  TextureSource *aTexture,
                  bool aPremultiplied,
--- a/gfx/layers/client/CompositableClient.h
+++ b/gfx/layers/client/CompositableClient.h
@@ -63,24 +63,26 @@ class TextureClientData;
  * by this layer forwarder (the matching uses a global map on the compositor side,
  * see CompositableMap in ImageBridgeParent.cpp)
  *
  * Subclasses: Thebes layers use ContentClients, ImageLayers use ImageClients,
  * Canvas layers use CanvasClients (but ImageHosts). We have a different subclass
  * where we have a different way of interfacing with the textures - in terms of
  * drawing into the compositable and/or passing its contents to the compostior.
  */
-class CompositableClient : public AtomicRefCounted<CompositableClient>
+class CompositableClient
 {
+protected:
+  virtual ~CompositableClient();
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(CompositableClient)
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositableClient)
+
   CompositableClient(CompositableForwarder* aForwarder, TextureFlags aFlags = 0);
 
-  virtual ~CompositableClient();
-
   virtual TextureInfo GetTextureInfo() const = 0;
 
   LayersBackend GetCompositorBackendType() const;
 
   TemporaryRef<BufferTextureClient>
   CreateBufferTextureClient(gfx::SurfaceFormat aFormat,
                             TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT,
                             gfx::BackendType aMoz2dBackend = gfx::BackendType::NONE);
--- a/gfx/layers/client/SimpleTextureClientPool.h
+++ b/gfx/layers/client/SimpleTextureClientPool.h
@@ -14,31 +14,31 @@
 #include <stack>
 #include <list>
 
 namespace mozilla {
 namespace layers {
 
 class ISurfaceAllocator;
 
-class SimpleTextureClientPool : public RefCounted<SimpleTextureClientPool>
+class SimpleTextureClientPool
 {
-public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(SimpleTextureClientPool)
-
-  SimpleTextureClientPool(gfx::SurfaceFormat aFormat, gfx::IntSize aSize,
-                          ISurfaceAllocator *aAllocator);
-
   ~SimpleTextureClientPool()
   {
     for (auto it = mOutstandingTextureClients.begin(); it != mOutstandingTextureClients.end(); ++it) {
       (*it)->ClearRecycleCallback();
     }
   }
 
+public:
+  NS_INLINE_DECL_REFCOUNTING(SimpleTextureClientPool)
+
+  SimpleTextureClientPool(gfx::SurfaceFormat aFormat, gfx::IntSize aSize,
+                          ISurfaceAllocator *aAllocator);
+
   /**
    * If a TextureClient is AutoRecycled, when the last reference is
    * released this object will be automatically return to the pool as
    * soon as the compositor informs us it is done with it.
    */
   TemporaryRef<TextureClient> GetTextureClient(bool aAutoRecycle = false);
   TemporaryRef<TextureClient> GetTextureClientWithAutoRecycle() { return GetTextureClient(true); }
 
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -70,33 +70,27 @@ namespace layers {
  * TextureChild is used to synchronize a texture client and its corresponding
  * TextureHost if needed (a TextureClient that is not shared with the compositor
  * does not have a TextureChild)
  *
  * During the deallocation phase, a TextureChild may hold its recently destroyed
  * TextureClient's data until the compositor side confirmed that it is safe to
  * deallocte or recycle the it.
  */
-class TextureChild : public PTextureChild
-                   , public AtomicRefCounted<TextureChild>
+class TextureChild MOZ_FINAL : public PTextureChild
 {
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(TextureChild)
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureChild)
+
   TextureChild()
   : mForwarder(nullptr)
   , mTextureData(nullptr)
   , mTextureClient(nullptr)
   , mIPCOpen(false)
   {
-    MOZ_COUNT_CTOR(TextureChild);
-  }
-
-  ~TextureChild()
-  {
-    MOZ_COUNT_DTOR(TextureChild);
   }
 
   bool Recv__delete__() MOZ_OVERRIDE;
 
   bool RecvCompositorRecycle(const MaybeFenceHandle& aFence)
   {
     RECYCLE_LOG("Receive recycle %p (%p)\n", mTextureClient, mWaitForRecycle.get());
     if (aFence.type() != aFence.Tnull_t) {
--- a/gfx/layers/client/TextureClientPool.h
+++ b/gfx/layers/client/TextureClientPool.h
@@ -13,23 +13,25 @@
 #include "nsITimer.h"
 #include <stack>
 
 namespace mozilla {
 namespace layers {
 
 class ISurfaceAllocator;
 
-class TextureClientPool : public RefCounted<TextureClientPool>
+class TextureClientPool MOZ_FINAL
 {
+  ~TextureClientPool();
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(TextureClientPool)
+  NS_INLINE_DECL_REFCOUNTING(TextureClientPool)
+
   TextureClientPool(gfx::SurfaceFormat aFormat, gfx::IntSize aSize,
                     ISurfaceAllocator *aAllocator);
-  ~TextureClientPool();
 
   /**
    * Gets an allocated TextureClient of size and format that are determined
    * by the initialisation parameters given to the pool. This will either be
    * a cached client that was returned to the pool, or a newly allocated
    * client if one isn't available.
    *
    * All clients retrieved by this method should be returned using the return
--- a/gfx/layers/client/TiledContentClient.h
+++ b/gfx/layers/client/TiledContentClient.h
@@ -42,20 +42,22 @@ namespace mozilla {
 namespace layers {
 
 class BasicTileDescriptor;
 class ClientTiledThebesLayer;
 class ClientLayerManager;
 
 
 // A class to help implement copy-on-write semantics for shared tiles.
-class gfxSharedReadLock : public AtomicRefCounted<gfxSharedReadLock> {
+class gfxSharedReadLock {
+protected:
+  virtual ~gfxSharedReadLock() {}
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(gfxSharedReadLock)
-  virtual ~gfxSharedReadLock() {}
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxSharedReadLock)
 
   virtual int32_t ReadLock() = 0;
   virtual int32_t ReadUnlock() = 0;
   virtual int32_t GetReadCount() = 0;
   virtual bool IsValid() const = 0;
 
   enum gfxSharedReadLockType {
     TYPE_MEMORY,
--- a/gfx/layers/composite/APZCTreeManager.cpp
+++ b/gfx/layers/composite/APZCTreeManager.cpp
@@ -774,17 +774,16 @@ APZCTreeManager::HandOffFling(AsyncPanZo
   ScreenPoint endPoint = startPoint + aVelocity;
   TransformDisplacement(this, aPrev, next, startPoint, endPoint);
   ScreenPoint transformedVelocity = endPoint - startPoint;
 
   // Tell |next| to start a fling with the transformed velocity.
   next->TakeOverFling(transformedVelocity);
 }
 
-
 bool
 APZCTreeManager::FlushRepaintsForOverscrollHandoffChain()
 {
   MonitorAutoLock lock(mTreeLock);  // to access mOverscrollHandoffChain
   if (mOverscrollHandoffChain.length() == 0) {
     return false;
   }
   for (uint32_t i = 0; i < mOverscrollHandoffChain.length(); i++) {
@@ -792,16 +791,40 @@ APZCTreeManager::FlushRepaintsForOverscr
     if (item) {
       item->FlushRepaintForOverscrollHandoff();
     }
   }
   return true;
 }
 
 bool
+APZCTreeManager::CanBePanned(AsyncPanZoomController* aApzc)
+{
+  MonitorAutoLock lock(mTreeLock);  // to access mOverscrollHandoffChain
+
+  // Find |aApzc| in the handoff chain.
+  uint32_t i;
+  for (i = 0; i < mOverscrollHandoffChain.length(); ++i) {
+    if (mOverscrollHandoffChain[i] == aApzc) {
+      break;
+    }
+  }
+
+  // See whether any APZC in the handoff chain starting from |aApzc|
+  // has room to be panned.
+  for (uint32_t j = i; j < mOverscrollHandoffChain.length(); ++j) {
+    if (mOverscrollHandoffChain[j]->IsPannable()) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+bool
 APZCTreeManager::HitTestAPZC(const ScreenIntPoint& aPoint)
 {
   MonitorAutoLock lock(mTreeLock);
   nsRefPtr<AsyncPanZoomController> target;
   // The root may have siblings, so check those too
   gfxPoint point(aPoint.x, aPoint.y);
   for (AsyncPanZoomController* apzc = mRootApzc; apzc; apzc = apzc->GetPrevSibling()) {
     target = GetAPZCAtPoint(apzc, point);
--- a/gfx/layers/composite/APZCTreeManager.h
+++ b/gfx/layers/composite/APZCTreeManager.h
@@ -209,16 +209,17 @@ public:
    */
   void GetAllowedTouchBehavior(WidgetInputEvent* aEvent,
                                nsTArray<TouchBehaviorFlags>& aOutValues);
 
   /**
    * Sets allowed touch behavior values for current touch-session for specific apzc (determined by guid).
    * Should be invoked by the widget. Each value of the aValues arrays corresponds to the different
    * touch point that is currently active.
+   * Must be called after receiving the TOUCH_START event that starts the touch-session.
    */
   void SetAllowedTouchBehavior(const ScrollableLayerGuid& aGuid,
                                const nsTArray<TouchBehaviorFlags>& aValues);
 
   /**
    * This is a callback for AsyncPanZoomController to call when it wants to
    * scroll in response to a touch-move event, or when it needs to hand off
    * overscroll to the next APZC. Note that because of scroll grabbing, the
@@ -266,16 +267,23 @@ public:
    * @param aApzc the APZC that is handing off the fling
    * @param aVelocity the current velocity of the fling, in |aApzc|'s screen
    *                  pixels per millisecond
    */
   void HandOffFling(AsyncPanZoomController* aApzc, ScreenPoint aVelocity);
 
   bool FlushRepaintsForOverscrollHandoffChain();
 
+  /**
+   * Determine whether |aApzc|, or any APZC along its overscroll handoff chain,
+   * has room to be panned.
+   * Expects the overscroll handoff chain to already be built.
+   */
+  bool CanBePanned(AsyncPanZoomController* aApzc);
+
 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.
    */
--- a/gfx/layers/composite/AsyncCompositionManager.h
+++ b/gfx/layers/composite/AsyncCompositionManager.h
@@ -56,32 +56,31 @@ struct ViewTransform {
 /**
  * Manage async composition effects. This class is only used with OMTC and only
  * lives on the compositor thread. It is a layer on top of the layer manager
  * (LayerManagerComposite) which deals with elements of composition which are
  * usually dealt with by dom or layout when main thread rendering, but which can
  * short circuit that stuff to directly affect layers as they are composited,
  * for example, off-main thread animation, async video, async pan/zoom.
  */
-class AsyncCompositionManager MOZ_FINAL : public RefCounted<AsyncCompositionManager>
+class AsyncCompositionManager MOZ_FINAL
 {
   friend class AutoResolveRefLayers;
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(AsyncCompositionManager)
+  NS_INLINE_DECL_REFCOUNTING(AsyncCompositionManager)
+
   AsyncCompositionManager(LayerManagerComposite* aManager)
     : mLayerManager(aManager)
     , mIsFirstPaint(false)
     , mLayersUpdated(false)
     , mReadyForCompose(true)
   {
-    MOZ_COUNT_CTOR(AsyncCompositionManager);
   }
   ~AsyncCompositionManager()
   {
-    MOZ_COUNT_DTOR(AsyncCompositionManager);
   }
 
   /**
    * This forces the is-first-paint flag to true. This is intended to
    * be called by the widget code when it loses its viewport information
    * (or for whatever reason wants to refresh the viewport information).
    * The information refresh happens because the compositor will call
    * SetFirstPaintViewport on the next frame of composition.
--- a/gfx/layers/composite/CompositableHost.h
+++ b/gfx/layers/composite/CompositableHost.h
@@ -51,28 +51,28 @@ class Compositor;
 class ISurfaceAllocator;
 class ThebesBufferData;
 class TiledLayerComposer;
 struct EffectChain;
 
 /**
  * A base class for doing CompositableHost and platform dependent task on TextureHost.
  */
-class CompositableBackendSpecificData : public RefCounted<CompositableBackendSpecificData>
+class CompositableBackendSpecificData
 {
+protected:
+  virtual ~CompositableBackendSpecificData() { }
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(CompositableBackendSpecificData)
+  NS_INLINE_DECL_REFCOUNTING(CompositableBackendSpecificData)
+
   CompositableBackendSpecificData()
   {
-    MOZ_COUNT_CTOR(CompositableBackendSpecificData);
   }
-  virtual ~CompositableBackendSpecificData()
-  {
-    MOZ_COUNT_DTOR(CompositableBackendSpecificData);
-  }
+
   virtual void SetCompositor(Compositor* aCompositor) {}
   virtual void ClearData()
   {
     mCurrentReleaseFenceTexture = nullptr;
     ClearPendingReleaseFenceTextureList();
   }
 
   /**
@@ -119,24 +119,25 @@ protected:
  * the layers transaction to update the Compositbale's textures from the
  * content side. The actual update (and any syncronous upload) is done by the
  * TextureHost, but it is coordinated by the CompositableHost.
  *
  * Composite is called by the owning layer when it is composited. CompositableHost
  * will use its TextureHost(s) and call Compositor::DrawQuad to do the actual
  * rendering.
  */
-class CompositableHost : public RefCounted<CompositableHost>
+class CompositableHost
 {
+protected:
+  virtual ~CompositableHost();
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(CompositableHost)
+  NS_INLINE_DECL_REFCOUNTING(CompositableHost)
   CompositableHost(const TextureInfo& aTextureInfo);
 
-  virtual ~CompositableHost();
-
   static TemporaryRef<CompositableHost> Create(const TextureInfo& aTextureInfo);
 
   virtual CompositableType GetType() = 0;
 
   virtual CompositableBackendSpecificData* GetCompositableBackendSpecificData()
   {
     return mBackendData;
   }
--- a/gfx/layers/composite/TextRenderer.h
+++ b/gfx/layers/composite/TextRenderer.h
@@ -2,27 +2,29 @@
 /* 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 GFX_TextRenderer_H
 #define GFX_TextRenderer_H
 
 #include "mozilla/gfx/2D.h"
+#include "nsISupportsImpl.h"
 #include <string>
 
 namespace mozilla {
 namespace layers {
 
 class Compositor;
 
-class TextRenderer : public RefCounted<TextRenderer>
+class TextRenderer
 {
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(TextRenderer)
+  NS_INLINE_DECL_REFCOUNTING(TextRenderer)
+
   TextRenderer(Compositor *aCompositor)
     : mCompositor(aCompositor)
   {
   }
 
   ~TextRenderer();
 
   void RenderText(const std::string& aText, const gfx::IntPoint& aOrigin,
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -75,22 +75,25 @@ public:
  * TextureSource is the interface for texture objects that can be composited
  * by a given compositor backend. Since the drawing APIs are different
  * between backends, the TextureSource interface is split into different
  * interfaces (TextureSourceOGL, etc.), and TextureSource mostly provide
  * access to these interfaces.
  *
  * This class is used on the compositor side.
  */
-class TextureSource : public RefCounted<TextureSource>
+class TextureSource
 {
+protected:
+  virtual ~TextureSource();
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(TextureSource)
+  NS_INLINE_DECL_REFCOUNTING(TextureSource)
+
   TextureSource();
-  virtual ~TextureSource();
 
   /**
    * Return the size of the texture in texels.
    * If this is a tile iterator, GetSize must return the size of the current tile.
    */
   virtual gfx::IntSize GetSize() const = 0;
 
   /**
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp
+++ b/gfx/layers/ipc/AsyncPanZoomController.cpp
@@ -127,16 +127,17 @@ WidgetModifiersToDOMModifiers(mozilla::M
 }
 
 using namespace mozilla::css;
 
 namespace mozilla {
 namespace layers {
 
 typedef mozilla::layers::AllowedTouchBehavior AllowedTouchBehavior;
+typedef GeckoContentController::APZStateChange APZStateChange;
 
 /*
  * The following prefs are used to control the behaviour of the APZC.
  * The default values are provided in gfxPrefs.h.
  *
  * "apz.allow-checkerboarding"
  * Pref that allows or disallows checkerboarding
  *
@@ -415,19 +416,16 @@ AsyncPanZoomController::AsyncPanZoomCont
      mZoomConstraints(false, false, MIN_ZOOM, MAX_ZOOM),
      mLastSampleTime(GetFrameTime()),
      mState(NOTHING),
      mLastAsyncScrollTime(GetFrameTime()),
      mLastAsyncScrollOffset(0, 0),
      mCurrentAsyncScrollOffset(0, 0),
      mAsyncScrollTimeoutTask(nullptr),
      mHandlingTouchQueue(false),
-     mAllowedTouchBehaviorSet(false),
-     mPreventDefault(false),
-     mPreventDefaultSet(false),
      mTreeManager(aTreeManager),
      mScrollParentId(FrameMetrics::NULL_SCROLL_ID),
      mAPZCId(sAsyncPanZoomControllerCount++),
      mSharedFrameMetricsBuffer(nullptr),
      mSharedLock(nullptr)
 {
   MOZ_COUNT_CTOR(AsyncPanZoomController);
 
@@ -493,31 +491,33 @@ AsyncPanZoomController::GetTouchStartTol
 }
 
 /* static */AsyncPanZoomController::AxisLockMode AsyncPanZoomController::GetAxisLockMode()
 {
   return static_cast<AxisLockMode>(gfxPrefs::APZAxisLockMode());
 }
 
 nsEventStatus AsyncPanZoomController::ReceiveInputEvent(const InputData& aEvent) {
+  if (aEvent.mInputType == MULTITOUCH_INPUT &&
+      aEvent.AsMultiTouchInput().mType == MultiTouchInput::MULTITOUCH_START) {
+    // Starting a new touch block, clear old touch block state.
+    mTouchBlockState = TouchBlockState();
+  }
+
   // If we may have touch listeners and touch action property is enabled, we
   // enable the machinery that allows touch listeners to preventDefault any touch inputs
   // and also waits for the allowed touch behavior values to be received from the outside.
   // This should not happen unless there are actually touch listeners and touch-action property
   // enable as it introduces potentially unbounded lag because it causes a round-trip through
   // content.  Usually, if content is responding in a timely fashion, this only introduces a
   // nearly constant few hundred ms of lag.
   if (mFrameMetrics.mMayHaveTouchListeners && aEvent.mInputType == MULTITOUCH_INPUT &&
       (mState == NOTHING || mState == TOUCHING || IsPanningState(mState))) {
     const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput();
     if (multiTouchInput.mType == MultiTouchInput::MULTITOUCH_START) {
-      mAllowedTouchBehaviors.Clear();
-      mAllowedTouchBehaviorSet = false;
-      mPreventDefault = false;
-      mPreventDefaultSet = false;
       SetState(WAITING_CONTENT_RESPONSE);
     }
   }
 
   if (mState == WAITING_CONTENT_RESPONSE || mHandlingTouchQueue) {
     if (aEvent.mInputType == MULTITOUCH_INPUT) {
       const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput();
       mTouchQueue.AppendElement(multiTouchInput);
@@ -610,21 +610,28 @@ nsEventStatus AsyncPanZoomController::On
         RequestContentRepaint();
         ScheduleComposite();
         UpdateSharedCompositorFrameMetrics();
       }
       // Fall through.
     case FLING:
       CancelAnimation();
       // Fall through.
-    case NOTHING:
+    case NOTHING: {
       mX.StartTouch(point.x);
       mY.StartTouch(point.y);
+      APZCTreeManager* treeManagerLocal = mTreeManager;
+      if (treeManagerLocal) {
+        bool touchCanBePan = treeManagerLocal->CanBePanned(this);
+        mGeckoContentController->NotifyAPZStateChange(
+            GetGuid(), APZStateChange::StartTouch, touchCanBePan);
+      }
       SetState(TOUCHING);
       break;
+    }
     case TOUCHING:
     case PANNING:
     case PANNING_LOCKED_X:
     case PANNING_LOCKED_Y:
     case CROSS_SLIDING_X:
     case CROSS_SLIDING_Y:
     case PINCHING:
     case WAITING_CONTENT_RESPONSE:
@@ -693,16 +700,18 @@ nsEventStatus AsyncPanZoomController::On
   }
 
   return nsEventStatus_eConsumeNoDefault;
 }
 
 nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) {
   APZC_LOG("%p got a touch-end in state %d\n", this, mState);
 
+  OnTouchEndOrCancel();
+
   // In case no touch behavior triggered previously we can avoid sending
   // scroll events or requesting content repaint. This condition is added
   // to make tests consistent - in case touch-action is NONE (and therefore
   // no pans/zooms can be performed) we expected neither scroll or repaint
   // events.
   if (mState != NOTHING) {
     ReentrantMonitorAutoEnter lock(mMonitor);
     SendAsyncScrollEvent();
@@ -759,16 +768,17 @@ nsEventStatus AsyncPanZoomController::On
     break;
   }
 
   return nsEventStatus_eConsumeNoDefault;
 }
 
 nsEventStatus AsyncPanZoomController::OnTouchCancel(const MultiTouchInput& aEvent) {
   APZC_LOG("%p got a touch-cancel in state %d\n", this, mState);
+  OnTouchEndOrCancel();
   SetState(NOTHING);
   return nsEventStatus_eConsumeNoDefault;
 }
 
 nsEventStatus AsyncPanZoomController::OnScaleBegin(const PinchGestureInput& aEvent) {
   APZC_LOG("%p got a scale-begin in state %d\n", this, mState);
 
   if (!TouchActionAllowZoom()) {
@@ -924,56 +934,56 @@ nsEventStatus AsyncPanZoomController::On
     if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
       controller->HandleLongTapUp(geckoScreenPoint, modifiers, GetGuid());
       return nsEventStatus_eConsumeNoDefault;
     }
   }
   return nsEventStatus_eIgnore;
 }
 
-nsEventStatus AsyncPanZoomController::OnSingleTapUp(const TapGestureInput& aEvent) {
-  APZC_LOG("%p got a single-tap-up in state %d\n", this, mState);
+nsEventStatus AsyncPanZoomController::GenerateSingleTap(const ScreenIntPoint& aPoint, mozilla::Modifiers aModifiers) {
   nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
-  // If mZoomConstraints.mAllowDoubleTapZoom is true we wait for a call to OnSingleTapConfirmed before
-  // sending event to content
-  if (controller && !mZoomConstraints.mAllowDoubleTapZoom) {
-    int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers);
+  if (controller) {
     CSSPoint geckoScreenPoint;
-    if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
+    if (ConvertToGecko(aPoint, &geckoScreenPoint)) {
+      int32_t modifiers = WidgetModifiersToDOMModifiers(aModifiers);
       // Because this may be being running as part of APZCTreeManager::ReceiveInputEvent,
       // calling controller->HandleSingleTap directly might mean that content receives
       // the single tap message before the corresponding touch-up. To avoid that we
       // schedule the singletap message to run on the next spin of the event loop.
       // See bug 965381 for the issue this was causing.
       controller->PostDelayedTask(
         NewRunnableMethod(controller.get(), &GeckoContentController::HandleSingleTap,
                           geckoScreenPoint, modifiers, GetGuid()),
         0);
+      mTouchBlockState.mSingleTapOccurred = true;
       return nsEventStatus_eConsumeNoDefault;
     }
   }
   return nsEventStatus_eIgnore;
 }
 
+void AsyncPanZoomController::OnTouchEndOrCancel() {
+  mGeckoContentController->NotifyAPZStateChange(
+      GetGuid(), APZStateChange::EndTouch, mTouchBlockState.mSingleTapOccurred);
+}
+
+nsEventStatus AsyncPanZoomController::OnSingleTapUp(const TapGestureInput& aEvent) {
+  APZC_LOG("%p got a single-tap-up in state %d\n", this, mState);
+  // If mZoomConstraints.mAllowDoubleTapZoom is true we wait for a call to OnSingleTapConfirmed before
+  // sending event to content
+  if (!mZoomConstraints.mAllowDoubleTapZoom) {
+    return GenerateSingleTap(aEvent.mPoint, aEvent.modifiers);
+  }
+  return nsEventStatus_eIgnore;
+}
+
 nsEventStatus AsyncPanZoomController::OnSingleTapConfirmed(const TapGestureInput& aEvent) {
   APZC_LOG("%p got a single-tap-confirmed in state %d\n", this, mState);
-  nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
-  if (controller) {
-    int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers);
-    CSSPoint geckoScreenPoint;
-    if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
-      // See comment in OnSingleTapUp as to why we do this in PostDelayedTask.
-      controller->PostDelayedTask(
-        NewRunnableMethod(controller.get(), &GeckoContentController::HandleSingleTap,
-                          geckoScreenPoint, modifiers, GetGuid()),
-        0);
-      return nsEventStatus_eConsumeNoDefault;
-    }
-  }
-  return nsEventStatus_eIgnore;
+  return GenerateSingleTap(aEvent.mPoint, aEvent.modifiers);
 }
 
 nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent) {
   APZC_LOG("%p got a double-tap in state %d\n", this, mState);
   nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
   if (controller) {
     if (mZoomConstraints.mAllowDoubleTapZoom) {
       int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers);
@@ -1087,25 +1097,27 @@ nsEventStatus AsyncPanZoomController::St
   double angle = atan2(dy, dx); // range [-pi, pi]
   angle = fabs(angle); // range [0, pi]
 
   if (mTouchActionPropertyEnabled) {
     HandlePanningWithTouchAction(angle, GetTouchBehavior(0));
   } else {
     if (GetAxisLockMode() == FREE) {
       SetState(PANNING);
-      return nsEventStatus_eConsumeNoDefault;
+    } else {
+      HandlePanning(angle);
     }
-
-    HandlePanning(angle);
   }
 
+  if (IsPanningState(mState)) {
+    mGeckoContentController->NotifyAPZStateChange(GetGuid(), APZStateChange::StartPanning);
+    return nsEventStatus_eConsumeNoDefault;
+  }
   // Don't consume an event that didn't trigger a panning.
-  return IsPanningState(mState) ? nsEventStatus_eConsumeNoDefault
-                                : nsEventStatus_eIgnore;
+  return nsEventStatus_eIgnore;
 }
 
 void AsyncPanZoomController::UpdateWithTouchAtDevicePoint(const MultiTouchInput& aEvent) {
   ScreenIntPoint point = GetFirstTouchScreenPoint(aEvent);
   TimeDuration timeDelta = TimeDuration().FromMilliseconds(aEvent.mTime - mLastEventTime);
 
   // Probably a duplicate event, just throw it away.
   if (timeDelta.ToMilliseconds() <= EPSILON) {
@@ -1440,16 +1452,21 @@ void AsyncPanZoomController::ScheduleCom
 }
 
 void AsyncPanZoomController::FlushRepaintForOverscrollHandoff() {
   ReentrantMonitorAutoEnter lock(mMonitor);
   RequestContentRepaint();
   UpdateSharedCompositorFrameMetrics();
 }
 
+bool AsyncPanZoomController::IsPannable() const {
+  ReentrantMonitorAutoEnter lock(mMonitor);
+  return mX.HasRoomToPan() || mY.HasRoomToPan();
+}
+
 void AsyncPanZoomController::RequestContentRepaint() {
   RequestContentRepaint(mFrameMetrics);
 }
 
 void AsyncPanZoomController::RequestContentRepaint(FrameMetrics& aFrameMetrics) {
   aFrameMetrics.SetDisplayPortMargins(
     CalculatePendingDisplayPort(aFrameMetrics,
                                 GetVelocityVector(),
@@ -1885,50 +1902,50 @@ void AsyncPanZoomController::ZoomToRect(
 
     // Schedule a repaint now, so the new displayport will be painted before the
     // animation finishes.
     RequestContentRepaint(endZoomToMetrics);
   }
 }
 
 void AsyncPanZoomController::ContentReceivedTouch(bool aPreventDefault) {
-  mPreventDefaultSet = true;
-  mPreventDefault = aPreventDefault;
+  mTouchBlockState.mPreventDefaultSet = true;
+  mTouchBlockState.mPreventDefault = aPreventDefault;
   CheckContentResponse();
 }
 
 void AsyncPanZoomController::CheckContentResponse() {
   bool canProceedToTouchState = true;
 
   if (mFrameMetrics.mMayHaveTouchListeners) {
-    canProceedToTouchState &= mPreventDefaultSet;
+    canProceedToTouchState &= mTouchBlockState.mPreventDefaultSet;
   }
 
   if (mTouchActionPropertyEnabled) {
-    canProceedToTouchState &= mAllowedTouchBehaviorSet;
+    canProceedToTouchState &= mTouchBlockState.mAllowedTouchBehaviorSet;
   }
 
   if (!canProceedToTouchState) {
     return;
   }
 
   if (mContentResponseTimeoutTask) {
     mContentResponseTimeoutTask->Cancel();
     mContentResponseTimeoutTask = nullptr;
   }
 
   if (mState == WAITING_CONTENT_RESPONSE) {
-    if (!mPreventDefault) {
+    if (!mTouchBlockState.mPreventDefault) {
       SetState(NOTHING);
     }
 
     mHandlingTouchQueue = true;
 
     while (!mTouchQueue.IsEmpty()) {
-      if (!mPreventDefault) {
+      if (!mTouchBlockState.mPreventDefault) {
         HandleInputEvent(mTouchQueue[0]);
       }
 
       if (mTouchQueue[0].mType == MultiTouchInput::MULTITOUCH_END ||
           mTouchQueue[0].mType == MultiTouchInput::MULTITOUCH_CANCEL) {
         mTouchQueue.RemoveElementAt(0);
         break;
       }
@@ -1942,66 +1959,66 @@ void AsyncPanZoomController::CheckConten
 
 bool AsyncPanZoomController::TouchActionAllowZoom() {
   if (!mTouchActionPropertyEnabled) {
     return true;
   }
 
   // Pointer events specification implies all touch points to allow zoom
   // to perform it.
-  for (size_t i = 0; i < mAllowedTouchBehaviors.Length(); i++) {
-    if (!(mAllowedTouchBehaviors[i] & AllowedTouchBehavior::ZOOM)) {
+  for (size_t i = 0; i < mTouchBlockState.mAllowedTouchBehaviors.Length(); i++) {
+    if (!(mTouchBlockState.mAllowedTouchBehaviors[i] & AllowedTouchBehavior::ZOOM)) {
       return false;
     }
   }
 
   return true;
 }
 
 AsyncPanZoomController::TouchBehaviorFlags
 AsyncPanZoomController::GetTouchBehavior(uint32_t touchIndex) {
-  if (touchIndex < mAllowedTouchBehaviors.Length()) {
-    return mAllowedTouchBehaviors[touchIndex];
+  if (touchIndex < mTouchBlockState.mAllowedTouchBehaviors.Length()) {
+    return mTouchBlockState.mAllowedTouchBehaviors[touchIndex];
   }
   return DefaultTouchBehavior;
 }
 
 AsyncPanZoomController::TouchBehaviorFlags
 AsyncPanZoomController::GetAllowedTouchBehavior(ScreenIntPoint& aPoint) {
   // Here we need to perform a hit testing over the touch-action regions attached to the
   // layer associated with current apzc.
   // Currently they are in progress, for more info see bug 928833.
   return AllowedTouchBehavior::UNKNOWN;
 }
 
 void AsyncPanZoomController::SetAllowedTouchBehavior(const nsTArray<TouchBehaviorFlags>& aBehaviors) {
-  mAllowedTouchBehaviors.Clear();
-  mAllowedTouchBehaviors.AppendElements(aBehaviors);
-  mAllowedTouchBehaviorSet = true;
+  mTouchBlockState.mAllowedTouchBehaviors.Clear();
+  mTouchBlockState.mAllowedTouchBehaviors.AppendElements(aBehaviors);
+  mTouchBlockState.mAllowedTouchBehaviorSet = true;
   CheckContentResponse();
 }
 
 void AsyncPanZoomController::SetState(PanZoomState aNewState) {
 
   PanZoomState oldState;
 
   // Intentional scoping for mutex
   {
     ReentrantMonitorAutoEnter lock(mMonitor);
     oldState = mState;
     mState = aNewState;
   }
 
   if (mGeckoContentController) {
     if (!IsTransformingState(oldState) && IsTransformingState(aNewState)) {
-      mGeckoContentController->NotifyTransformBegin(
-        ScrollableLayerGuid(mLayersId, mFrameMetrics.mPresShellId, mFrameMetrics.GetScrollId()));
+      mGeckoContentController->NotifyAPZStateChange(
+          GetGuid(), APZStateChange::TransformBegin);
     } else if (IsTransformingState(oldState) && !IsTransformingState(aNewState)) {
-      mGeckoContentController->NotifyTransformEnd(
-        ScrollableLayerGuid(mLayersId, mFrameMetrics.mPresShellId, mFrameMetrics.GetScrollId()));
+      mGeckoContentController->NotifyAPZStateChange(
+          GetGuid(), APZStateChange::TransformEnd);
     }
   }
 }
 
 bool AsyncPanZoomController::IsTransformingState(PanZoomState aState) {
   return !(aState == NOTHING || aState == TOUCHING || aState == WAITING_CONTENT_RESPONSE);
 }
 
--- a/gfx/layers/ipc/AsyncPanZoomController.h
+++ b/gfx/layers/ipc/AsyncPanZoomController.h
@@ -310,16 +310,18 @@ public:
    * is done we should integrate its logic here.
    */
   TouchBehaviorFlags GetAllowedTouchBehavior(ScreenIntPoint& aPoint);
 
   /**
    * Sets allowed touch behavior for current touch session.
    * This method is invoked by the APZCTreeManager which in its turn invoked by
    * the widget after performing touch-action values retrieving.
+   * Must be called after receiving the TOUCH_START even that started the
+   * touch session.
    */
   void SetAllowedTouchBehavior(const nsTArray<TouchBehaviorFlags>& aBehaviors);
 
   /**
    * Returns whether this APZC is for an element marked with the 'scrollgrab'
    * attribute.
    */
   bool HasScrollgrab() const { return mFrameMetrics.mHasScrollgrab; }
@@ -327,16 +329,21 @@ public:
   /**
    * Set an extra offset for testing async scrolling.
    */
   void SetTestAsyncScrollOffset(const CSSPoint& aPoint)
   {
     mTestAsyncScrollOffset = aPoint;
   }
 
+  /**
+   * Returns whether this APZC has room to be panned (in any direction).
+   */
+  bool IsPannable() const;
+
 protected:
   // Protected destructor, to discourage deletion outside of Release():
   ~AsyncPanZoomController();
 
   /**
    * Helper method for touches beginning. Sets everything up for panning and any
    * multitouch gestures.
    */
@@ -552,16 +559,46 @@ private:
     PINCHING,                 /* nth touch-start, where n > 1. this mode allows pan and zoom */
     ANIMATING_ZOOM,           /* animated zoom to a new rect */
     WAITING_CONTENT_RESPONSE, /* a state halfway between NOTHING and TOUCHING - the user has
                                  put a finger down, but we don't yet know if a touch listener has
                                  prevented the default actions yet and the allowed touch behavior
                                  was not set yet. we still need to abort animations. */
   };
 
+  // State related to a single touch block. Does not persist across touch blocks.
+  struct TouchBlockState {
+
+    TouchBlockState()
+      :  mAllowedTouchBehaviorSet(false),
+         mPreventDefault(false),
+         mPreventDefaultSet(false),
+         mSingleTapOccurred(false)
+    {}
+
+    // Values of allowed touch behavior for touch points of this touch block.
+    // Since there are maybe a few current active touch points per time (multitouch case)
+    // and each touch point should have its own value of allowed touch behavior- we're
+    // keeping an array of allowed touch behavior values, not the single value.
+    nsTArray<TouchBehaviorFlags> mAllowedTouchBehaviors;
+
+    // Specifies whether mAllowedTouchBehaviors is set for this touch events block.
+    bool mAllowedTouchBehaviorSet;
+
+    // Flag used to specify that content prevented the default behavior of this
+    // touch events block.
+    bool mPreventDefault;
+
+    // Specifies whether mPreventDefault property is set for this touch events block.
+    bool mPreventDefaultSet;
+
+    // Specifies whether a single tap event was generated during this touch block.
+    bool mSingleTapOccurred;
+  };
+
   /*
    * Returns whether current touch behavior values allow zooming.
    */
   bool TouchActionAllowZoom();
 
   /*
    * Returns allowed touch behavior from the mAllowedTouchBehavior array.
    * In case apzc didn't receive touch behavior values within the timeout
@@ -612,16 +649,22 @@ private:
   // coordinates but the composition bounds is in parent layer coordinates.
   ParentLayerPoint ToParentLayerCoords(const ScreenPoint& aPoint);
 
   // Update mFrameMetrics.mTransformScale. This should be called whenever
   // our CSS transform or the non-transient part of our async transform
   // changes, as it corresponds to the scale portion of those transforms.
   void UpdateTransformScale();
 
+  // Helper function for OnSingleTapUp() and OnSingleTapConfirmed().
+  nsEventStatus GenerateSingleTap(const ScreenIntPoint& aPoint, mozilla::Modifiers aModifiers);
+
+  // Common processing at the end of a touch block.
+  void OnTouchEndOrCancel();
+
   uint64_t mLayersId;
   nsRefPtr<CompositorParent> mCompositorParent;
   PCompositorParent* mCrossProcessCompositorParent;
   TaskThrottler mPaintThrottler;
 
   /* Access to the following two fields is protected by the mRefPtrMonitor,
      since they are accessed on the UI thread but can be cleared on the
      compositor thread. */
@@ -638,17 +681,19 @@ protected:
   // monitor. Do not read from or modify either of them without locking.
   FrameMetrics mFrameMetrics;
 
   // Protects |mFrameMetrics|, |mLastContentPaintMetrics|, and |mState|.
   // Before manipulating |mFrameMetrics| or |mLastContentPaintMetrics|, the
   // monitor should be held. When setting |mState|, either the SetState()
   // function can be used, or the monitor can be held and then |mState| updated.
   // IMPORTANT: See the note about lock ordering at the top of APZCTreeManager.h.
-  ReentrantMonitor mMonitor;
+  // This is mutable to allow entering it from 'const' methods; doing otherwise
+  // would significantly limit what methods could be 'const'.
+  mutable ReentrantMonitor mMonitor;
 
   // Specifies whether we should use touch-action css property. Initialized from
   // the preferences. This property (in comparison with the global one) simplifies
   // testing apzc with (and without) touch-action property enabled concurrently
   // (e.g. with the gtest framework).
   bool mTouchActionPropertyEnabled;
 
 private:
@@ -713,31 +758,18 @@ private:
   CancelableTask* mAsyncScrollTimeoutTask;
 
   // Flag used to determine whether or not we should try to enter the
   // WAITING_LISTENERS state. This is used in the case that we are processing a
   // queued up event block. If set, this means that we are handling this queue
   // and we don't want to queue the events back up again.
   bool mHandlingTouchQueue;
 
-  // Values of allowed touch behavior for current touch points.
-  // Since there are maybe a few current active touch points per time (multitouch case)
-  // and each touch point should have its own value of allowed touch behavior- we're
-  // keeping an array of allowed touch behavior values, not the single value.
-  nsTArray<TouchBehaviorFlags> mAllowedTouchBehaviors;
-
-  // Specifies whether mAllowedTouchBehaviors is set for current touch events block.
-  bool mAllowedTouchBehaviorSet;
-
-  // Flag used to specify that content prevented the default behavior of the current
-  // touch events block.
-  bool mPreventDefault;
-
-  // Specifies whether mPreventDefault property is set for current touch events block.
-  bool mPreventDefaultSet;
+  // Stores information about the current touch block.
+  TouchBlockState mTouchBlockState;
 
   // Extra offset to add in SampleContentTransformForFrame for testing
   CSSPoint mTestAsyncScrollOffset;
 
   RefPtr<AsyncPanZoomAnimation> mAnimation;
 
   friend class Axis;
   friend class FlingAnimation;
--- a/gfx/layers/ipc/Axis.cpp
+++ b/gfx/layers/ipc/Axis.cpp
@@ -202,89 +202,95 @@ float Axis::ScaleWillOverscrollAmount(fl
 float Axis::GetVelocity() {
   return mAxisLocked ? 0 : mVelocity;
 }
 
 void Axis::SetVelocity(float aVelocity) {
   mVelocity = aVelocity;
 }
 
-float Axis::GetCompositionEnd() {
+float Axis::GetCompositionEnd() const {
   return GetOrigin() + GetCompositionLength();
 }
 
-float Axis::GetPageEnd() {
+float Axis::GetPageEnd() const {
   return GetPageStart() + GetPageLength();
 }
 
-float Axis::GetOrigin() {
+float Axis::GetOrigin() const {
   CSSPoint origin = mAsyncPanZoomController->GetFrameMetrics().GetScrollOffset();
   return GetPointOffset(origin);
 }
 
-float Axis::GetCompositionLength() {
+float Axis::GetCompositionLength() const {
   const FrameMetrics& metrics = mAsyncPanZoomController->GetFrameMetrics();
   return GetRectLength(metrics.CalculateCompositedRectInCssPixels());
 }
 
-float Axis::GetPageStart() {
+float Axis::GetPageStart() const {
   CSSRect pageRect = mAsyncPanZoomController->GetFrameMetrics().mScrollableRect;
   return GetRectOffset(pageRect);
 }
 
-float Axis::GetPageLength() {
+float Axis::GetPageLength() const {
   CSSRect pageRect = mAsyncPanZoomController->GetFrameMetrics().mScrollableRect;
   return GetRectLength(pageRect);
 }
 
 bool Axis::ScaleWillOverscrollBothSides(float aScale) {
   const FrameMetrics& metrics = mAsyncPanZoomController->GetFrameMetrics();
 
   CSSToParentLayerScale scale(metrics.GetZoomToParent().scale * aScale);
   CSSRect cssCompositionBounds = metrics.mCompositionBounds / scale;
 
   return GetRectLength(metrics.mScrollableRect) < GetRectLength(cssCompositionBounds);
 }
 
+bool Axis::HasRoomToPan() const {
+  return GetOrigin() > GetPageStart()
+      || GetCompositionEnd() < GetPageEnd();
+}
+
+
 AxisX::AxisX(AsyncPanZoomController* aAsyncPanZoomController)
   : Axis(aAsyncPanZoomController)
 {
 
 }
 
-float AxisX::GetPointOffset(const CSSPoint& aPoint)
+float AxisX::GetPointOffset(const CSSPoint& aPoint) const
 {
   return aPoint.x;
 }
 
-float AxisX::GetRectLength(const CSSRect& aRect)
+float AxisX::GetRectLength(const CSSRect& aRect) const
 {
   return aRect.width;
 }
 
-float AxisX::GetRectOffset(const CSSRect& aRect)
+float AxisX::GetRectOffset(const CSSRect& aRect) const
 {
   return aRect.x;
 }
 
 AxisY::AxisY(AsyncPanZoomController* aAsyncPanZoomController)
   : Axis(aAsyncPanZoomController)
 {
 
 }
 
-float AxisY::GetPointOffset(const CSSPoint& aPoint)
+float AxisY::GetPointOffset(const CSSPoint& aPoint) const
 {
   return aPoint.y;
 }
 
-float AxisY::GetRectLength(const CSSRect& aRect)
+float AxisY::GetRectLength(const CSSRect& aRect) const
 {
   return aRect.height;
 }
 
-float AxisY::GetRectOffset(const CSSRect& aRect)
+float AxisY::GetRectOffset(const CSSRect& aRect) const
 {
   return aRect.y;
 }
 
 }
 }
--- a/gfx/layers/ipc/Axis.h
+++ b/gfx/layers/ipc/Axis.h
@@ -165,50 +165,55 @@ public:
    * Checks if an axis will overscroll in both directions by computing the
    * content rect and checking that its height/width (depending on the axis)
    * does not overextend past the viewport.
    *
    * This gets called by ScaleWillOverscroll().
    */
   bool ScaleWillOverscrollBothSides(float aScale);
 
-  float GetOrigin();
-  float GetCompositionLength();
-  float GetPageStart();
-  float GetPageLength();
-  float GetCompositionEnd();
-  float GetPageEnd();
+  /**
+   * Returns whether there is room to pan on this axis in either direction.
+   */
+  bool HasRoomToPan() const;
+
+  float GetOrigin() const;
+  float GetCompositionLength() const;
+  float GetPageStart() const;
+  float GetPageLength() const;
+  float GetCompositionEnd() const;
+  float GetPageEnd() const;
 
   int32_t GetPos() const { return mPos; }
 
-  virtual float GetPointOffset(const CSSPoint& aPoint) = 0;
-  virtual float GetRectLength(const CSSRect& aRect) = 0;
-  virtual float GetRectOffset(const CSSRect& aRect) = 0;
+  virtual float GetPointOffset(const CSSPoint& aPoint) const = 0;
+  virtual float GetRectLength(const CSSRect& aRect) const = 0;
+  virtual float GetRectOffset(const CSSRect& aRect) const = 0;
 
 protected:
   int32_t mPos;
   int32_t mStartPos;
   float mVelocity;
   bool mAxisLocked;     // Whether movement on this axis is locked.
   AsyncPanZoomController* mAsyncPanZoomController;
   nsTArray<float> mVelocityQueue;
 };
 
 class AxisX : public Axis {
 public:
   AxisX(AsyncPanZoomController* mAsyncPanZoomController);
-  virtual float GetPointOffset(const CSSPoint& aPoint);
-  virtual float GetRectLength(const CSSRect& aRect);
-  virtual float GetRectOffset(const CSSRect& aRect);
+  virtual float GetPointOffset(const CSSPoint& aPoint) const;
+  virtual float GetRectLength(const CSSRect& aRect) const;
+  virtual float GetRectOffset(const CSSRect& aRect) const;
 };
 
 class AxisY : public Axis {
 public:
   AxisY(AsyncPanZoomController* mAsyncPanZoomController);
-  virtual float GetPointOffset(const CSSPoint& aPoint);
-  virtual float GetRectLength(const CSSRect& aRect);
-  virtual float GetRectOffset(const CSSRect& aRect);
+  virtual float GetPointOffset(const CSSPoint& aPoint) const;
+  virtual float GetRectLength(const CSSRect& aRect) const;
+  virtual float GetRectOffset(const CSSRect& aRect) const;
 };
 
 }
 }
 
 #endif
--- a/gfx/layers/ipc/GeckoContentController.h
+++ b/gfx/layers/ipc/GeckoContentController.h
@@ -108,27 +108,58 @@ public:
    * APZ can then get the correct touch-sensitive region for each frame
    * directly from the layer.
    */
   virtual bool GetTouchSensitiveRegion(CSSRect* aOutRegion)
   {
     return false;
   }
 
+  MOZ_BEGIN_NESTED_ENUM_CLASS(APZStateChange, int8_t)
+    /**
+     * APZ started modifying the view (including panning, zooming, and fling).
+     */
+    TransformBegin,
+    /**
+     * APZ finished modifying the view.
+     */
+    TransformEnd,
+    /**
+     * APZ started a touch.
+     * |aArg| is 1 if touch can be a pan, 0 otherwise.
+     */
+    StartTouch,
+    /**
+     * APZ started a pan.
+     */
+    StartPanning,
+    /**
+     * APZ finished processing a touch.
+     * |aArg| is 1 if touch was a click, 0 otherwise.
+     */
+    EndTouch,
+    APZStateChangeSentinel
+  MOZ_END_NESTED_ENUM_CLASS(APZStateChange)
+
   /**
-   * General tranformation notices for consumers. These fire any time
-   * the apzc is modifying the view, including panning, zooming, and
-   * fling.
+   * General notices of APZ state changes for consumers.
+   * |aGuid| identifies the APZC originating the state change.
+   * |aChange| identifies the type of state change
+   * |aArg| is used by some state changes to pass extra information (see
+   *        the documentation for each state change above)
    */
-  virtual void NotifyTransformBegin(const ScrollableLayerGuid& aGuid) {}
-  virtual void NotifyTransformEnd(const ScrollableLayerGuid& aGuid) {}
+  virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
+                                    APZStateChange aChange,
+                                    int aArg = 0) {}
 
   GeckoContentController() {}
 
 protected:
   // Protected destructor, to discourage deletion outside of Release():
   virtual ~GeckoContentController() {}
 };
 
+MOZ_FINISH_NESTED_ENUM_CLASS(GeckoContentController::APZStateChange)
+
 }
 }
 
 #endif // mozilla_layers_GeckoContentController_h
--- a/gfx/layers/ipc/LayerTransactionChild.h
+++ b/gfx/layers/ipc/LayerTransactionChild.h
@@ -18,38 +18,35 @@ namespace mozilla {
 
 namespace layout {
 class RenderFrameChild;
 }
 
 namespace layers {
 
 class LayerTransactionChild : public PLayerTransactionChild
-                            , public AtomicRefCounted<LayerTransactionChild>
 {
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(LayerTransactionChild)
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(LayerTransactionChild)
   /**
    * Clean this up, finishing with Send__delete__().
    *
    * It is expected (checked with an assert) that all shadow layers
    * created by this have already been destroyed and
    * Send__delete__()d by the time this method is called.
    */
   void Destroy();
 
   bool IPCOpen() const { return mIPCOpen; }
 
 protected:
   LayerTransactionChild()
     : mIPCOpen(false)
   {}
   ~LayerTransactionChild() { }
-  friend class AtomicRefCounted<LayerTransactionChild>;
-  friend class detail::RefCounted<LayerTransactionChild, detail::AtomicRefCount>;
 
   virtual PGrallocBufferChild*
   AllocPGrallocBufferChild(const IntSize&,
                            const uint32_t&, const uint32_t&,
                            MaybeMagicGrallocBufferHandle*) MOZ_OVERRIDE;
   virtual bool
   DeallocPGrallocBufferChild(PGrallocBufferChild* actor) MOZ_OVERRIDE;
 
--- a/gfx/layers/opengl/CompositorOGL.h
+++ b/gfx/layers/opengl/CompositorOGL.h
@@ -59,22 +59,23 @@ struct EffectChain;
  * Interface for pools of temporary gl textures for the compositor.
  * The textures are fully owned by the pool, so the latter is responsible
  * calling fDeleteTextures accordingly.
  * Users of GetTexture receive a texture that is only valid for the duration
  * of the current frame.
  * This is primarily intended for direct texturing APIs that need to attach
  * shared objects (such as an EGLImage) to a gl texture.
  */
-class CompositorTexturePoolOGL : public RefCounted<CompositorTexturePoolOGL>
+class CompositorTexturePoolOGL
 {
+protected:
+  virtual ~CompositorTexturePoolOGL() {}
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(CompositorTexturePoolOGL)
-
-  virtual ~CompositorTexturePoolOGL() {}
+  NS_INLINE_DECL_REFCOUNTING(CompositorTexturePoolOGL)
 
   virtual void Clear() = 0;
 
   virtual GLuint GetTexture(GLenum aTarget, GLenum aEnum) = 0;
 
   virtual void EndFrame() = 0;
 };
 
--- a/gfx/src/FilterSupport.cpp
+++ b/gfx/src/FilterSupport.cpp
@@ -225,20 +225,20 @@ namespace FilterWrappers {
 // A class that wraps a FilterNode and handles conversion between different
 // color models. Create FilterCachedColorModels with your original filter and
 // the color model that this filter outputs in natively, and then call
 // ->ForColorModel(colorModel) in order to get a FilterNode which outputs to
 // the specified colorModel.
 // Internally, this is achieved by wrapping the original FilterNode with
 // conversion FilterNodes. These filter nodes are cached in such a way that no
 // repeated or back-and-forth conversions happen.
-class FilterCachedColorModels : public RefCounted<FilterCachedColorModels>
+class FilterCachedColorModels
 {
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(FilterCachedColorModels)
+  NS_INLINE_DECL_REFCOUNTING(FilterCachedColorModels)
   // aFilter can be null. In that case, ForColorModel will return a non-null
   // completely transparent filter for all color models.
   FilterCachedColorModels(DrawTarget* aDT,
                           FilterNode* aFilter,
                           ColorModel aOriginalColorModel);
 
   // Get a FilterNode for the specified color model, guaranteed to be non-null.
   TemporaryRef<FilterNode> ForColorModel(ColorModel aColorModel);
--- a/gfx/src/nsRenderingContext.h
+++ b/gfx/src/nsRenderingContext.h
@@ -29,25 +29,24 @@ struct nsRect;
 
 typedef enum {
     nsLineStyle_kNone   = 0,
     nsLineStyle_kSolid  = 1,
     nsLineStyle_kDashed = 2,
     nsLineStyle_kDotted = 3
 } nsLineStyle;
 
-class nsRenderingContext
+class nsRenderingContext MOZ_FINAL
 {
     typedef mozilla::gfx::UserData UserData;
     typedef mozilla::gfx::UserDataKey UserDataKey;
     typedef mozilla::gfx::DrawTarget DrawTarget;
 
 public:
     nsRenderingContext() : mP2A(0.) {}
-    // ~nsRenderingContext() {}
 
     NS_INLINE_DECL_REFCOUNTING(nsRenderingContext)
 
     void Init(nsDeviceContext* aContext, gfxASurface* aThebesSurface);
     void Init(nsDeviceContext* aContext, gfxContext* aThebesContext);
     void Init(nsDeviceContext* aContext, DrawTarget* aDrawTarget);
 
     // These accessors will never return null.
@@ -125,17 +124,22 @@ public:
     }
     void *GetUserData(UserDataKey *key) {
       return mUserData.Get(key);
     }
     void *RemoveUserData(UserDataKey *key) {
       return mUserData.Remove(key);
     }
 
-protected:
+private:
+    // Private destructor, to discourage deletion outside of Release():
+    ~nsRenderingContext()
+    {
+    }
+
     int32_t GetMaxChunkLength();
 
     nsRefPtr<gfxContext> mThebes;
     nsRefPtr<nsDeviceContext> mDeviceContext;
     nsRefPtr<nsFontMetrics> mFontMetrics;
 
     double mP2A; // cached app units per device pixel value
 
--- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp
+++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp
@@ -163,17 +163,24 @@ FrameMetrics TestFrameMetrics() {
   return fm;
 }
 
 /*
  * Dispatches mock touch events to the apzc and checks whether apzc properly
  * consumed them and triggered scrolling behavior.
  */
 static
-void ApzcPan(AsyncPanZoomController* apzc, TestAPZCTreeManager* aTreeManager, int& aTime, int aTouchStartY, int aTouchEndY, bool expectIgnoredPan = false, bool hasTouchListeners = false) {
+void ApzcPan(AsyncPanZoomController* apzc,
+             TestAPZCTreeManager* aTreeManager,
+             int& aTime,
+             int aTouchStartY,
+             int aTouchEndY,
+             bool expectIgnoredPan = false,
+             bool hasTouchListeners = false,
+             nsTArray<uint32_t>* aAllowedTouchBehaviors = nullptr) {
 
   const int TIME_BETWEEN_TOUCH_EVENT = 100;
   const int OVERCOME_TOUCH_TOLERANCE = 100;
   MultiTouchInput mti;
   nsEventStatus status;
 
   // Since we're passing inputs directly to the APZC instead of going through
   // the tree manager, we need to build the overscroll handoff chain explicitly
@@ -193,16 +200,21 @@ void ApzcPan(AsyncPanZoomController* apz
   mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, aTime, 0);
   aTime += TIME_BETWEEN_TOUCH_EVENT;
   // Make sure the move is large enough to not be handled as a tap
   mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(10, aTouchStartY+OVERCOME_TOUCH_TOLERANCE), ScreenSize(0, 0), 0, 0));
   status = apzc->ReceiveInputEvent(mti);
   EXPECT_EQ(status, touchStartStatus);
   // APZC should be in TOUCHING state
 
+  // Allowed touch behaviours must be set after sending touch-start.
+  if (aAllowedTouchBehaviors) {
+    apzc->SetAllowedTouchBehavior(*aAllowedTouchBehaviors);
+  }
+
   nsEventStatus touchMoveStatus;
   if (expectIgnoredPan) {
     // APZC should ignore panning, be in TOUCHING state and therefore return eIgnore.
     // The same applies to all consequent touch move events.
     touchMoveStatus = nsEventStatus_eIgnore;
   } else {
     // APZC should go into the panning state and therefore consume the event.
     touchMoveStatus = nsEventStatus_eConsumeNoDefault;
@@ -249,35 +261,33 @@ void DoPanTest(bool aShouldTriggerScroll
   }
 
   int time = 0;
   int touchStart = 50;
   int touchEnd = 10;
   ScreenPoint pointOut;
   ViewTransform viewTransformOut;
 
-  nsTArray<uint32_t> values;
-  values.AppendElement(aBehavior);
+  nsTArray<uint32_t> allowedTouchBehaviors;
+  allowedTouchBehaviors.AppendElement(aBehavior);
 
   // Pan down
-  apzc->SetAllowedTouchBehavior(values);
-  ApzcPan(apzc, tm, time, touchStart, touchEnd, !aShouldTriggerScroll);
+  ApzcPan(apzc, tm, time, touchStart, touchEnd, !aShouldTriggerScroll, false, &allowedTouchBehaviors);
   apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
 
   if (aShouldTriggerScroll) {
     EXPECT_EQ(pointOut, ScreenPoint(0, -(touchEnd-touchStart)));
     EXPECT_NE(viewTransformOut, ViewTransform());
   } else {
     EXPECT_EQ(pointOut, ScreenPoint());
     EXPECT_EQ(viewTransformOut, ViewTransform());
   }
 
   // Pan back
-  apzc->SetAllowedTouchBehavior(values);
-  ApzcPan(apzc, tm, time, touchEnd, touchStart, !aShouldTriggerScroll);
+  ApzcPan(apzc, tm, time, touchEnd, touchStart, !aShouldTriggerScroll, false, &allowedTouchBehaviors);
   apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
 
   EXPECT_EQ(pointOut, ScreenPoint());
   EXPECT_EQ(viewTransformOut, ViewTransform());
 
   apzc->Destroy();
 }
 
@@ -608,21 +618,20 @@ TEST_F(AsyncPanZoomControllerTester, Pan
 
   int time = 0;
   int touchStart = 50;
   int touchEnd = 10;
   ScreenPoint pointOut;
   ViewTransform viewTransformOut;
 
   // Pan down
-  nsTArray<uint32_t> values;
-  values.AppendElement(mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN);
+  nsTArray<uint32_t> allowedTouchBehaviors;
+  allowedTouchBehaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN);
   apzc->SetTouchActionEnabled(true);
-  apzc->SetAllowedTouchBehavior(values);
-  ApzcPan(apzc, tm, time, touchStart, touchEnd, true, true);
+  ApzcPan(apzc, tm, time, touchStart, touchEnd, true, true, &allowedTouchBehaviors);
 
   // Send the signal that content has handled and preventDefaulted the touch
   // events. This flushes the event queue.
   apzc->ContentReceivedTouch(true);
 
   apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
   EXPECT_EQ(pointOut, ScreenPoint());
   EXPECT_EQ(viewTransformOut, ViewTransform());
@@ -741,26 +750,28 @@ DoLongPressTest(bool aShouldUseTouchActi
   nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
   nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(
     0, mcc, tm, AsyncPanZoomController::USE_GESTURE_DETECTOR);
 
   apzc->SetFrameMetrics(TestFrameMetrics());
   apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
   apzc->UpdateZoomConstraints(ZoomConstraints(false, false, CSSToScreenScale(1.0), CSSToScreenScale(1.0)));
 
-  nsTArray<uint32_t> values;
-  values.AppendElement(aBehavior);
   apzc->SetTouchActionEnabled(aShouldUseTouchAction);
-  apzc->SetAllowedTouchBehavior(values);
 
   int time = 0;
 
   nsEventStatus status = ApzcDown(apzc, 10, 10, time);
   EXPECT_EQ(nsEventStatus_eConsumeNoDefault, status);
 
+  // SetAllowedTouchBehavior() must be called after sending touch-start.
+  nsTArray<uint32_t> allowedTouchBehaviors;
+  allowedTouchBehaviors.AppendElement(aBehavior);
+  apzc->SetAllowedTouchBehavior(allowedTouchBehaviors);
+
   MockFunction<void(std::string checkPointName)> check;
 
   {
     InSequence s;
 
     EXPECT_CALL(check, Call("preHandleLongTap"));
     EXPECT_CALL(*mcc, HandleLongTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
     EXPECT_CALL(check, Call("postHandleLongTap"));
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -68,22 +68,24 @@
 #include "nsCRT.h"
 #include "GLContext.h"
 #include "GLContextProvider.h"
 
 #ifdef MOZ_WIDGET_ANDROID
 #include "TexturePoolOGL.h"
 #endif
 
+#include "mozilla/Hal.h"
 #ifdef USE_SKIA
-#include "mozilla/Hal.h"
 #include "skia/SkGraphics.h"
 
 #include "SkiaGLGlue.h"
-
+#else
+class mozilla::gl::SkiaGLGlue : public GenericAtomicRefCounted {
+};
 #endif
 
 #include "mozilla/Preferences.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Mutex.h"
 
 #include "nsIGfxInfo.h"
@@ -923,17 +925,19 @@ gfxPlatform::InitializeSkiaCacheLimits()
         cacheSizeLimit = totalMemory / 16;
       }
     }
 
   #ifdef DEBUG
     printf_stderr("Determined SkiaGL cache limits: Size %i, Items: %i\n", cacheSizeLimit, cacheItemLimit);
   #endif
 
+#ifdef USE_SKIA_GPU
     mSkiaGlue->GetGrContext()->setTextureCacheLimits(cacheItemLimit, cacheSizeLimit);
+#endif
   }
 }
 
 mozilla::gl::SkiaGLGlue*
 gfxPlatform::GetSkiaGLGlue()
 {
 #ifdef USE_SKIA_GPU
   if (!mSkiaGlue) {
--- a/hal/HalWakeLock.cpp
+++ b/hal/HalWakeLock.cpp
@@ -7,17 +7,17 @@
 #include "mozilla/HalWakeLock.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/dom/ContentParent.h"
 #include "nsClassHashtable.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsIPropertyBag2.h"
-#include "nsObserverService.h"
+#include "nsIObserverService.h"
 
 using namespace mozilla;
 using namespace mozilla::hal;
 
 namespace {
 
 struct LockCount {
   LockCount()
--- a/hal/cocoa/CocoaBattery.cpp
+++ b/hal/cocoa/CocoaBattery.cpp
@@ -7,17 +7,18 @@
 #import <CoreFoundation/CoreFoundation.h>
 #import <IOKit/ps/IOPowerSources.h>
 #import <IOKit/ps/IOPSKeys.h>
 
 #include <mozilla/Hal.h>
 #include <mozilla/dom/battery/Constants.h>
 #include <mozilla/Services.h>
 
-#include <nsObserverService.h>
+#include <nsIObserverService.h>
+#include <nsIObserver.h>
 
 #include <dlfcn.h>
 
 #define IOKIT_FRAMEWORK_PATH "/System/Library/Frameworks/IOKit.framework/IOKit"
 
 #ifndef kIOPSTimeRemainingUnknown
   #define kIOPSTimeRemainingUnknown ((CFTimeInterval)-1.0)
 #endif
--- a/hal/gonk/GonkHal.cpp
+++ b/hal/gonk/GonkHal.cpp
@@ -289,21 +289,21 @@ public:
 
     hal::NotifyBatteryChange(info);
     return NS_OK;
   }
 };
 
 } // anonymous namespace
 
-class BatteryObserver : public IUeventObserver,
-                        public RefCounted<BatteryObserver>
+class BatteryObserver : public IUeventObserver
 {
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(BatteryObserver)
+  NS_INLINE_DECL_REFCOUNTING(BatteryObserver)
+
   BatteryObserver()
     :mUpdater(new BatteryUpdater())
   {
   }
 
   virtual void Notify(const NetlinkEvent &aEvent)
   {
     // this will run on IO thread
--- a/hal/gonk/GonkSwitch.cpp
+++ b/hal/gonk/GonkSwitch.cpp
@@ -46,20 +46,21 @@ namespace hal_impl {
  *  change@/devices/virtual/switch/usb_configuration
  *    ACTION=change
  *    DEVPATH=/devices/virtual/switch/usb_configuration
  *    SUBSYSTEM=switch
  *    SWITCH_NAME=usb_configuration
  *    SWITCH_STATE=0
  *    SEQNUM=5038
  */
-class SwitchHandler : public RefCounted<SwitchHandler>
+class SwitchHandler
 {
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(SwitchHandler)
+  NS_INLINE_DECL_REFCOUNTING(SwitchHandler)
+
   SwitchHandler(const char* aDevPath, SwitchDevice aDevice)
     : mDevPath(aDevPath),
       mState(SWITCH_STATE_UNKNOWN),
       mDevice(aDevice)
   {
     GetInitialState();
   }
 
@@ -225,31 +226,30 @@ public:
   {
     NotifySwitchChange(mEvent);
     return NS_OK;
   }
 private:
   SwitchEvent mEvent;
 };
 
-class SwitchEventObserver : public IUeventObserver,
-                            public RefCounted<SwitchEventObserver>
+class SwitchEventObserver MOZ_FINAL : public IUeventObserver
 {
+  ~SwitchEventObserver()
+  {
+    mHandler.Clear();
+  }
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(SwitchEventObserver)
+  NS_INLINE_DECL_REFCOUNTING(SwitchEventObserver)
   SwitchEventObserver() : mEnableCount(0)
   {
     Init();
   }
 
-  ~SwitchEventObserver()
-  {
-    mHandler.Clear();
-  }
-
   int GetEnableCount()
   {
     return mEnableCount;
   }
 
   void EnableSwitch(SwitchDevice aDevice)
   {
     mEventInfo[aDevice].mEnabled = true;
--- a/image/public/imgIContainer.idl
+++ b/image/public/imgIContainer.idl
@@ -8,16 +8,18 @@
 
 %{C++
 #include "gfxImageSurface.h"
 #include "gfxContext.h"
 #include "gfxMatrix.h"
 #include "gfxRect.h"
 #include "GraphicsFilter.h"
 #include "gfxASurface.h"
+#include "mozilla/gfx/2D.h"
+#include "mozilla/RefPtr.h"
 #include "nsRect.h"
 #include "nsSize.h"
 #include "limits.h"
 
 namespace mozilla {
 namespace layers {
 class LayerManager;
 class ImageContainer;
@@ -50,27 +52,27 @@ native gfxGraphicsFilter(GraphicsFilter)
 [ref] native nsIntSize(nsIntSize);
 native nsSize(nsSize);
 [ptr] native nsIFrame(nsIFrame);
 [ptr] native ImageContainer(mozilla::layers::ImageContainer);
 [ptr] native LayerManager(mozilla::layers::LayerManager);
 native Orientation(mozilla::image::Orientation);
 [ref] native TimeStamp(mozilla::TimeStamp);
 [ptr] native SVGImageContext(mozilla::SVGImageContext);
-native already_AddRefed_gfxASurface(already_AddRefed<gfxASurface>);
+native TempRefSourceSurface(mozilla::TemporaryRef<mozilla::gfx::SourceSurface>);
 
 
 /**
  * imgIContainer is the interface that represents an image. It allows
  * access to frames as Thebes surfaces. It also allows drawing of images
  * onto Thebes contexts.
  *
  * Internally, imgIContainer also manages animation of images.
  */
-[scriptable, builtinclass, uuid(8b7db7dd-bfe9-40d3-9114-3a79c0658afd)]
+[scriptable, builtinclass, uuid(503a830c-734d-4362-91f6-73f83ac59646)]
 interface imgIContainer : nsISupports
 {
   /**
    * The width of the container rectangle.  In the case of any error,
    * zero is returned, and an exception will be thrown.
    */
   readonly attribute int32_t width;
 
@@ -145,16 +147,17 @@ interface imgIContainer : nsISupports
    */
 
   const long FLAG_NONE            = 0x0;
   const long FLAG_SYNC_DECODE     = 0x1;
   const long FLAG_DECODE_NO_PREMULTIPLY_ALPHA = 0x2;
   const long FLAG_DECODE_NO_COLORSPACE_CONVERSION = 0x4;
   const long FLAG_CLAMP           = 0x8;
   const long FLAG_HIGH_QUALITY_SCALING = 0x10;
+  const long FLAG_WANT_DATA_SURFACE = 0x20;
 
   /**
     * Constants for specifying various "special" frames.
     *
     * FRAME_FIRST: The first frame
     * FRAME_CURRENT: The current frame
     *
     * FRAME_MAX_VALUE should be set to the value of the maximum constant above,
@@ -168,19 +171,18 @@ interface imgIContainer : nsISupports
    * Get a surface for the given frame. This may be a platform-native,
    * optimized surface, so you cannot inspect its pixel data. If you
    * need that, use gfxASurface::GetAsReadableARGB32ImageSurface or
    * gfxASurface::CopyToARGB32ImageSurface.
    *
    * @param aWhichFrame Frame specifier of the FRAME_* variety.
    * @param aFlags Flags of the FLAG_* variety
    */
-  [noscript, notxpcom] already_AddRefed_gfxASurface
-                         getFrame(in uint32_t aWhichFrame,
-                                  in uint32_t aFlags);
+  [noscript, notxpcom] TempRefSourceSurface getFrame(in uint32_t aWhichFrame,
+                                                     in uint32_t aFlags);
 
   /**
    * Whether the given frame is opaque; that is, needs the background painted
    * behind it.
    *
    * @param aWhichFrame Frame specifier of the FRAME_* variety.
    */
   [notxpcom] boolean frameIsOpaque(in uint32_t aWhichFrame);
--- a/image/src/ClippedImage.cpp
+++ b/image/src/ClippedImage.cpp
@@ -1,31 +1,35 @@
 /* -*- 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 "gfxDrawable.h"
 #include "gfxPlatform.h"
 #include "gfxUtils.h"
+#include "mozilla/gfx/2D.h"
+#include "mozilla/RefPtr.h"
 
 #include "ClippedImage.h"
 #include "Orientation.h"
 #include "SVGImageContext.h"
 
+using namespace mozilla;
+using namespace mozilla::gfx;
 using mozilla::layers::LayerManager;
 using mozilla::layers::ImageContainer;
 
 namespace mozilla {
 namespace image {
 
 class ClippedImageCachedSurface
 {
 public:
-  ClippedImageCachedSurface(mozilla::gfx::DrawTarget* aSurface,
+  ClippedImageCachedSurface(TemporaryRef<SourceSurface> aSurface,
                             const nsIntSize& aViewportSize,
                             const SVGImageContext* aSVGContext,
                             float aFrame,
                             uint32_t aFlags)
     : mSurface(aSurface)
     , mViewportSize(aViewportSize)
     , mFrame(aFrame)
     , mFlags(aFlags)
@@ -44,23 +48,22 @@ public:
     bool matchesSVGContext = (!aSVGContext && mSVGContext.empty()) ||
                              *aSVGContext == mSVGContext.ref();
     return mViewportSize == aViewportSize &&
            matchesSVGContext &&
            mFrame == aFrame &&
            mFlags == aFlags;
   }
 
-  already_AddRefed<gfxASurface> Surface() {
-    nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mSurface);
-    return surf.forget();
+  TemporaryRef<SourceSurface> Surface() {
+    return mSurface;
   }
 
 private:
-  nsRefPtr<mozilla::gfx::DrawTarget> mSurface;
+  RefPtr<SourceSurface>              mSurface;
   const nsIntSize                    mViewportSize;
   Maybe<SVGImageContext>             mSVGContext;
   const float                        mFrame;
   const uint32_t                     mFlags;
 };
 
 class DrawSingleTileCallback : public gfxDrawingCallback
 {
@@ -204,62 +207,60 @@ ClippedImage::GetIntrinsicRatio(nsSize* 
   if (!ShouldClip()) {
     return InnerImage()->GetIntrinsicRatio(aRatio);
   }
 
   *aRatio = nsSize(mClip.width, mClip.height);
   return NS_OK;
 }
 
-NS_IMETHODIMP_(already_AddRefed<gfxASurface>)
+NS_IMETHODIMP_(TemporaryRef<SourceSurface>)
 ClippedImage::GetFrame(uint32_t aWhichFrame,
                        uint32_t aFlags)
 {
   return GetFrameInternal(mClip.Size(), nullptr, aWhichFrame, aFlags);
 }
 
-already_AddRefed<gfxASurface>
+TemporaryRef<SourceSurface>
 ClippedImage::GetFrameInternal(const nsIntSize& aViewportSize,
                                const SVGImageContext* aSVGContext,
                                uint32_t aWhichFrame,
                                uint32_t aFlags)
 {
   if (!ShouldClip()) {
     return InnerImage()->GetFrame(aWhichFrame, aFlags);
   }
 
   float frameToDraw = InnerImage()->GetFrameIndex(aWhichFrame);
   if (!mCachedSurface || !mCachedSurface->Matches(aViewportSize,
                                                   aSVGContext,
                                                   frameToDraw,
                                                   aFlags)) {
     // Create a surface to draw into.
-    mozilla::RefPtr<mozilla::gfx::DrawTarget> target;
-    nsRefPtr<gfxContext> ctx;
+    RefPtr<DrawTarget> target = gfxPlatform::GetPlatform()->
+      CreateOffscreenContentDrawTarget(IntSize(mClip.width, mClip.height),
+                                       SurfaceFormat::B8G8R8A8);
 
-    target = gfxPlatform::GetPlatform()->
-      CreateOffscreenContentDrawTarget(gfx::IntSize(mClip.width, mClip.height),
-                                       gfx::SurfaceFormat::B8G8R8A8);
-    ctx = new gfxContext(target);
+    nsRefPtr<gfxContext> ctx = new gfxContext(target);
 
     // Create our callback.
     nsRefPtr<gfxDrawingCallback> drawTileCallback =
       new DrawSingleTileCallback(this, mClip, aViewportSize, aSVGContext, aWhichFrame, aFlags);
     nsRefPtr<gfxDrawable> drawable =
       new gfxCallbackDrawable(drawTileCallback, mClip.Size());
 
     // Actually draw. The callback will end up invoking DrawSingleTile.
     gfxRect imageRect(0, 0, mClip.width, mClip.height);
     gfxUtils::DrawPixelSnapped(ctx, drawable, gfxMatrix(),
                                imageRect, imageRect, imageRect, imageRect,
                                gfxImageFormat::ARGB32,
                                GraphicsFilter::FILTER_FAST);
 
     // Cache the resulting surface.
-    mCachedSurface = new ClippedImageCachedSurface(target,
+    mCachedSurface = new ClippedImageCachedSurface(target->Snapshot(),
                                                    aViewportSize,
                                                    aSVGContext,
                                                    frameToDraw,
                                                    aFlags);
   }
 
   MOZ_ASSERT(mCachedSurface, "Should have a cached surface now");
   return mCachedSurface->Surface();
@@ -317,17 +318,17 @@ ClippedImage::Draw(gfxContext* aContext,
   }
 
   // Check for tiling. If we need to tile then we need to create a
   // gfxCallbackDrawable to handle drawing for us.
   gfxRect sourceRect = aUserSpaceToImageSpace.Transform(aFill);
   if (MustCreateSurface(aContext, aUserSpaceToImageSpace, sourceRect, aSubimage, aFlags)) {
     // Create a temporary surface containing a single tile of this image.
     // GetFrame will call DrawSingleTile internally.
-    nsRefPtr<gfxASurface> surface =
+    RefPtr<SourceSurface> surface =
       GetFrameInternal(aViewportSize, aSVGContext, aWhichFrame, aFlags);
     NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
 
     // Create a drawable from that surface.
     nsRefPtr<gfxSurfaceDrawable> drawable =
       new gfxSurfaceDrawable(surface, gfxIntSize(mClip.width, mClip.height));
 
     // Draw.
--- a/image/src/ClippedImage.h
+++ b/image/src/ClippedImage.h
@@ -2,46 +2,50 @@
 /* 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_CLIPPEDIMAGE_H_
 #define MOZILLA_IMAGELIB_CLIPPEDIMAGE_H_
 
 #include "ImageWrapper.h"
+#include "mozilla/gfx/2D.h"
 #include "mozilla/Maybe.h"
+#include "mozilla/RefPtr.h"
 
 namespace mozilla {
 namespace image {
 
 class ClippedImageCachedSurface;
 class DrawSingleTileCallback;
 
 /**
  * An Image wrapper that clips an image against a rectangle. Right now only
  * absolute coordinates in pixels are supported.
  *
  * XXX(seth): There a known (performance, not correctness) issue with
  * GetImageContainer. See the comments for that method for more information.
  */
 class ClippedImage : public ImageWrapper
 {
+  typedef mozilla::gfx::SourceSurface SourceSurface;
+
 public:
   NS_DECL_ISUPPORTS
 
   virtual ~ClippedImage();
 
   virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE;
 
   NS_IMETHOD GetWidth(int32_t* aWidth) MOZ_OVERRIDE;
   NS_IMETHOD GetHeight(int32_t* aHeight) MOZ_OVERRIDE;
   NS_IMETHOD GetIntrinsicSize(nsSize* aSize) MOZ_OVERRIDE;
   NS_IMETHOD GetIntrinsicRatio(nsSize* aRatio) MOZ_OVERRIDE;
-  NS_IMETHOD_(already_AddRefed<gfxASurface>) GetFrame(uint32_t aWhichFrame,
-                                                      uint32_t aFlags) MOZ_OVERRIDE;
+  NS_IMETHOD_(mozilla::TemporaryRef<SourceSurface>)
+    GetFrame(uint32_t aWhichFrame, uint32_t aFlags) MOZ_OVERRIDE;
   NS_IMETHOD GetImageContainer(mozilla::layers::LayerManager* aManager,
                                mozilla::layers::ImageContainer** _retval) MOZ_OVERRIDE;
   NS_IMETHOD Draw(gfxContext* aContext,
                   GraphicsFilter aFilter,
                   const gfxMatrix& aUserSpaceToImageSpace,
                   const gfxRect& aFill,
                   const nsIntRect& aSubimage,
                   const nsIntSize& aViewportSize,
@@ -50,20 +54,21 @@ public:
                   uint32_t aFlags) MOZ_OVERRIDE;
   NS_IMETHOD RequestDiscard() MOZ_OVERRIDE;
   NS_IMETHOD_(Orientation) GetOrientation() MOZ_OVERRIDE;
 
 protected:
   ClippedImage(Image* aImage, nsIntRect aClip);
 
 private:
-  already_AddRefed<gfxASurface> GetFrameInternal(const nsIntSize& aViewportSize,
-                                                 const SVGImageContext* aSVGContext,
-                                                 uint32_t aWhichFrame,
-                                                 uint32_t aFlags);
+  mozilla::TemporaryRef<SourceSurface>
+    GetFrameInternal(const nsIntSize& aViewportSize,
+                     const SVGImageContext* aSVGContext,
+                     uint32_t aWhichFrame,
+                     uint32_t aFlags);
   bool ShouldClip();
   bool MustCreateSurface(gfxContext* aContext,
                          const gfxMatrix& aTransform,
                          const gfxRect& aSourceRect,
                          const nsIntRect& aSubimage,
                          const uint32_t aFlags) const;
   gfxFloat ClampFactor(const gfxFloat aToClamp, const int aReference) const;
   nsresult DrawSingleTile(gfxContext* aContext,
--- a/image/src/FrozenImage.cpp
+++ b/image/src/FrozenImage.cpp
@@ -1,15 +1,17 @@
 /* -*- 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 "FrozenImage.h"
 
+using namespace mozilla::gfx;
+
 namespace mozilla {
 namespace image {
 
 NS_IMPL_ISUPPORTS1(FrozenImage, imgIContainer)
 
 nsIntRect
 FrozenImage::FrameRect(uint32_t /* aWhichFrame - ignored */)
 {
@@ -35,17 +37,17 @@ FrozenImage::GetAnimated(bool* aAnimated
   bool dummy;
   nsresult rv = InnerImage()->GetAnimated(&dummy);
   if (NS_SUCCEEDED(rv)) {
     *aAnimated = false;
   }
   return rv;
 }
 
-NS_IMETHODIMP_(already_AddRefed<gfxASurface>)
+NS_IMETHODIMP_(TemporaryRef<SourceSurface>)
 FrozenImage::GetFrame(uint32_t aWhichFrame,
                       uint32_t aFlags)
 {
   return InnerImage()->GetFrame(FRAME_FIRST, aFlags);
 }
 
 NS_IMETHODIMP_(bool)
 FrozenImage::FrameIsOpaque(uint32_t aWhichFrame)
--- a/image/src/FrozenImage.h
+++ b/image/src/FrozenImage.h
@@ -2,16 +2,18 @@
 /* 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_FROZENIMAGE_H_
 #define MOZILLA_IMAGELIB_FROZENIMAGE_H_
 
 #include "ImageWrapper.h"
+#include "mozilla/gfx/2D.h"
+#include "mozilla/RefPtr.h"
 
 namespace mozilla {
 namespace image {
 
 /**
  * An Image wrapper that disables animation, freezing the image at its first
  * frame. It does this using two strategies. If this is the only instance of the
  * image, animation will never start, because IncrementAnimationConsumers is
@@ -19,28 +21,30 @@ namespace image {
  * because any imgIContainer method that is affected by animation gets its
  * aWhichFrame argument set to FRAME_FIRST when it passes through FrozenImage.
  *
  * XXX(seth): There a known (performance, not correctness) issue with
  * GetImageContainer. See the comments for that method for more information.
  */
 class FrozenImage : public ImageWrapper
 {
+  typedef mozilla::gfx::SourceSurface SourceSurface;
+
 public:
   NS_DECL_ISUPPORTS
 
   virtual ~FrozenImage() { }
 
   virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE;
   virtual void IncrementAnimationConsumers() MOZ_OVERRIDE;
   virtual void DecrementAnimationConsumers() MOZ_OVERRIDE;
 
   NS_IMETHOD GetAnimated(bool* aAnimated) MOZ_OVERRIDE;
-  NS_IMETHOD_(already_AddRefed<gfxASurface>) GetFrame(uint32_t aWhichFrame,
-                                                      uint32_t aFlags) MOZ_OVERRIDE;
+  NS_IMETHOD_(TemporaryRef<SourceSurface>)
+    GetFrame(uint32_t aWhichFrame, uint32_t aFlags) MOZ_OVERRIDE;
   NS_IMETHOD_(bool) FrameIsOpaque(uint32_t aWhichFrame) MOZ_OVERRIDE;
   NS_IMETHOD GetImageContainer(layers::LayerManager* aManager,
                                layers::ImageContainer** _retval) MOZ_OVERRIDE;
   NS_IMETHOD Draw(gfxContext* aContext,
                   GraphicsFilter aFilter,
                   const gfxMatrix& aUserSpaceToImageSpace,
                   const gfxRect& aFill,
                   const nsIntRect& aSubimage,
--- a/image/src/ImageWrapper.cpp
+++ b/image/src/ImageWrapper.cpp
@@ -1,18 +1,22 @@
 /* -*- 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 "ImageWrapper.h"
+#include "mozilla/gfx/2D.h"
+#include "mozilla/RefPtr.h"
 #include "Orientation.h"
 
 #include "mozilla/MemoryReporting.h"
 
+using mozilla::gfx::DataSourceSurface;
+using mozilla::gfx::SourceSurface;
 using mozilla::layers::LayerManager;
 using mozilla::layers::ImageContainer;
 
 namespace mozilla {
 namespace image {
 
 // Inherited methods from Image.
 
@@ -191,17 +195,17 @@ ImageWrapper::GetType()
 }
 
 NS_IMETHODIMP
 ImageWrapper::GetAnimated(bool* aAnimated)
 {
   return mInnerImage->GetAnimated(aAnimated);
 }
 
-NS_IMETHODIMP_(already_AddRefed<gfxASurface>)
+NS_IMETHODIMP_(TemporaryRef<SourceSurface>)
 ImageWrapper::GetFrame(uint32_t aWhichFrame,
                        uint32_t aFlags)
 {
   return mInnerImage->GetFrame(aWhichFrame, aFlags);
 }
 
 NS_IMETHODIMP_(bool)
 ImageWrapper::FrameIsOpaque(uint32_t aWhichFrame)
--- a/image/src/OrientedImage.cpp
+++ b/image/src/OrientedImage.cpp
@@ -6,16 +6,18 @@
 #include <algorithm>
 
 #include "gfxDrawable.h"
 #include "gfxPlatform.h"
 #include "gfxUtils.h"
 
 #include "OrientedImage.h"
 
+using namespace mozilla::gfx;
+
 using std::swap;
 using mozilla::layers::LayerManager;
 using mozilla::layers::ImageContainer;
 
 namespace mozilla {
 namespace image {
 
 NS_IMPL_ISUPPORTS1(OrientedImage, imgIContainer)
@@ -70,71 +72,68 @@ OrientedImage::GetIntrinsicRatio(nsSize*
 
   if (mOrientation.SwapsWidthAndHeight()) {
     swap(aRatio->width, aRatio->height);
   }
 
   return rv;
 }
 
-NS_IMETHODIMP_(already_AddRefed<gfxASurface>)
+NS_IMETHODIMP_(TemporaryRef<SourceSurface>)
 OrientedImage::GetFrame(uint32_t aWhichFrame,
                         uint32_t aFlags)
 {
   nsresult rv;
 
   if (mOrientation.IsIdentity()) {
     return InnerImage()->GetFrame(aWhichFrame, aFlags);
   }
 
   // Get the underlying dimensions.
   int32_t width, height;
+  rv = InnerImage()->GetWidth(&width);
+  NS_ENSURE_SUCCESS(rv, nullptr);
+  rv = InnerImage()->GetHeight(&height);
+  NS_ENSURE_SUCCESS(rv, nullptr);
   if (mOrientation.SwapsWidthAndHeight()) {
-    rv = InnerImage()->GetWidth(&height);
-    rv = NS_FAILED(rv) ? rv : InnerImage()->GetHeight(&width);
-  } else {
-    rv = InnerImage()->GetWidth(&width);
-    rv = NS_FAILED(rv) ? rv : InnerImage()->GetHeight(&height);
+    swap(width, height);
   }
   NS_ENSURE_SUCCESS(rv, nullptr);
 
   // Determine an appropriate format for the surface.
   gfx::SurfaceFormat surfaceFormat;
   gfxImageFormat imageFormat;
   if (InnerImage()->FrameIsOpaque(aWhichFrame)) {
     surfaceFormat = gfx::SurfaceFormat::B8G8R8X8;
     imageFormat = gfxImageFormat::ARGB32;
   } else {
     surfaceFormat = gfx::SurfaceFormat::B8G8R8A8;
     imageFormat = gfxImageFormat::ARGB32;
   }
 
   // Create a surface to draw into.
-  mozilla::RefPtr<mozilla::gfx::DrawTarget> target;
-  target = gfxPlatform::GetPlatform()->
-    CreateOffscreenContentDrawTarget(gfx::IntSize(width, height), surfaceFormat);
+  mozilla::RefPtr<DrawTarget> target =
+    gfxPlatform::GetPlatform()->
+      CreateOffscreenContentDrawTarget(IntSize(width, height), surfaceFormat);
 
   // Create our drawable.
-  nsRefPtr<gfxASurface> innerSurface =
+  RefPtr<SourceSurface> innerSurface =
     InnerImage()->GetFrame(aWhichFrame, aFlags);
   NS_ENSURE_TRUE(innerSurface, nullptr);
   nsRefPtr<gfxDrawable> drawable =
     new gfxSurfaceDrawable(innerSurface, gfxIntSize(width, height));
 
   // Draw.
   nsRefPtr<gfxContext> ctx = new gfxContext(target);
   gfxRect imageRect(0, 0, width, height);
   gfxUtils::DrawPixelSnapped(ctx, drawable, OrientationMatrix(nsIntSize(width, height)),
                              imageRect, imageRect, imageRect, imageRect,
                              imageFormat, GraphicsFilter::FILTER_FAST);
   
-  nsRefPtr<gfxASurface> surface = gfxPlatform::GetPlatform()->
-    GetThebesSurfaceForDrawTarget(target);
-
-  return surface.forget();
+  return target->Snapshot();
 }
 
 NS_IMETHODIMP
 OrientedImage::GetImageContainer(LayerManager* aManager, ImageContainer** _retval)
 {
   // XXX(seth): We currently don't have a way of orienting the result of
   // GetImageContainer. We work around this by always returning null, but if it
   // ever turns out that OrientedImage is widely used on codepaths that can
--- a/image/src/OrientedImage.h
+++ b/image/src/OrientedImage.h
@@ -2,43 +2,47 @@
 /* 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_ORIENTEDIMAGE_H_
 #define MOZILLA_IMAGELIB_ORIENTEDIMAGE_H_
 
 #include "ImageWrapper.h"
+#include "mozilla/gfx/2D.h"
+#include "mozilla/RefPtr.h"
 #include "Orientation.h"
 
 namespace mozilla {
 namespace image {
 
 /**
  * An Image wrapper that rotates and/or flips an image according to a specified
  * Orientation.
  *
  * XXX(seth): There a known (performance, not correctness) issue with
  * GetImageContainer. See the comments for that method for more information.
  */
 class OrientedImage : public ImageWrapper
 {
+  typedef mozilla::gfx::SourceSurface SourceSurface;
+
 public:
   NS_DECL_ISUPPORTS
 
   virtual ~OrientedImage() { }
 
   virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE;
 
   NS_IMETHOD GetWidth(int32_t* aWidth) MOZ_OVERRIDE;
   NS_IMETHOD GetHeight(int32_t* aHeight) MOZ_OVERRIDE;
   NS_IMETHOD GetIntrinsicSize(nsSize* aSize) MOZ_OVERRIDE;
   NS_IMETHOD GetIntrinsicRatio(nsSize* aRatio) MOZ_OVERRIDE;
-  NS_IMETHOD_(already_AddRefed<gfxASurface>) GetFrame(uint32_t aWhichFrame,
-                                                      uint32_t aFlags) MOZ_OVERRIDE;
+  NS_IMETHOD_(mozilla::TemporaryRef<SourceSurface>)
+    GetFrame(uint32_t aWhichFrame, uint32_t aFlags) MOZ_OVERRIDE;
   NS_IMETHOD GetImageContainer(mozilla::layers::LayerManager* aManager,
                                mozilla::layers::ImageContainer** _retval) MOZ_OVERRIDE;
   NS_IMETHOD Draw(gfxContext* aContext,
                   GraphicsFilter aFilter,
                   const gfxMatrix& aUserSpaceToImageSpace,
                   const gfxRect& aFill,
                   const nsIntRect& aSubimage,
                   const nsIntSize& aViewportSize,
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -1,20 +1,24 @@
 /* -*- 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/. */
 
+// Must #include ImageLogging.h before any IPDL-generated files or other files that #include prlog.h
+#include "ImageLogging.h"
+
+#include "RasterImage.h"
+
 #include "base/histogram.h"
-#include "ImageLogging.h"
+#include "gfxPlatform.h"
 #include "nsComponentManagerUtils.h"
 #include "imgDecoderObserver.h"
 #include "nsError.h"
 #include "Decoder.h"
-#include "RasterImage.h"
 #include "nsAutoPtr.h"
 #include "prenv.h"
 #include "prsystem.h"
 #include "ImageContainer.h"
 #include "Layers.h"
 #include "nsPresContext.h"
 #include "nsIThreadPool.h"
 #include "nsXPCOMCIDInternal.h"
@@ -25,16 +29,18 @@
 #include "nsGIFDecoder2.h"
 #include "nsJPEGDecoder.h"
 #include "nsBMPDecoder.h"
 #include "nsICODecoder.h"
 #include "nsIconDecoder.h"
 
 #include "gfxContext.h"
 
+#include "mozilla/gfx/2D.h"
+#include "mozilla/RefPtr.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Services.h"
 #include "mozilla/Preferences.h"
 #include <stdint.h>
 #include "mozilla/Telemetry.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/gfx/Scale.h"
@@ -43,16 +49,17 @@
 #include "gfx2DGlue.h"
 #include <algorithm>
 
 #ifdef MOZ_NUWA_PROCESS
 #include "ipc/Nuwa.h"
 #endif
 
 using namespace mozilla;
+using namespace mozilla::gfx;
 using namespace mozilla::image;
 using namespace mozilla::layers;
 
 // a mask for flags that will affect the decoding
 #define DECODE_FLAGS_MASK (imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA | imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION)
 #define DECODE_FLAGS_DEFAULT 0
 
 /* Accounting for compressed data */
@@ -875,19 +882,19 @@ RasterImage::CopyFrame(uint32_t aWhichFr
   ctx.SetPattern(pattern);
   ctx.Fill();
 
   imgsurface.forget(_retval);
   return NS_OK;
 }
 
 //******************************************************************************
-/* [noscript] gfxASurface getFrame(in uint32_t aWhichFrame,
- *                                 in uint32_t aFlags); */
-NS_IMETHODIMP_(already_AddRefed<gfxASurface>)
+/* [noscript] SourceSurface getFrame(in uint32_t aWhichFrame,
+ *                                   in uint32_t aFlags); */
+NS_IMETHODIMP_(TemporaryRef<SourceSurface>)
 RasterImage::GetFrame(uint32_t aWhichFrame,
                       uint32_t aFlags)
 {
   MOZ_ASSERT(aWhichFrame <= FRAME_MAX_VALUE);
 
   if (aWhichFrame > FRAME_MAX_VALUE)
     return nullptr;
 
@@ -946,48 +953,63 @@ RasterImage::GetFrame(uint32_t aWhichFra
   // The image doesn't have a surface because it's been optimized away. Create
   // one.
   if (!framesurf) {
     nsRefPtr<gfxImageSurface> imgsurf;
     CopyFrame(aWhichFrame, aFlags, getter_AddRefs(imgsurf));
     framesurf = imgsurf;
   }
 
-  return framesurf.forget();
+  RefPtr<SourceSurface> result;
+
+  // As far as Moz2D is concerned, SourceSurface contains premultiplied alpha.
+  // If we're abusing it to contain non-premultiplied alpha then we want to
+  // avoid having Moz2D do any conversions on it (like copy to another
+  // surface). Hence why we try to wrap framesurf's data here for
+  // FLAG_DECODE_NO_PREMULTIPLY_ALPHA.
+  if ((aFlags & FLAG_WANT_DATA_SURFACE) != 0 ||
+      (aFlags & FLAG_DECODE_NO_PREMULTIPLY_ALPHA) != 0) {
+    result = gfxPlatform::GetPlatform()->GetWrappedDataSourceSurface(framesurf);
+  }
+  if (!result) {
+    result = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr,
+                                                                    framesurf);
+  }
+  return result.forget();
 }
 
 already_AddRefed<layers::Image>
 RasterImage::GetCurrentImage()
 {
   if (!mDecoded) {
     // We can't call StartDecoding because that can synchronously notify
     // which can cause DOM modification
     RequestDecodeCore(ASYNCHRONOUS);
     return nullptr;
   }
 
-  nsRefPtr<gfxASurface> imageSurface = GetFrame(FRAME_CURRENT, FLAG_NONE);
-  if (!imageSurface) {
+  RefPtr<SourceSurface> surface = GetFrame(FRAME_CURRENT, FLAG_NONE);
+  if (!surface) {
     // The OS threw out some or all of our buffer. Start decoding again.
     // GetFrame will only return null in the case that the image was
     // discarded. We already checked that the image is decoded, so other
     // error paths are not possible.
     ForceDiscard();
     RequestDecodeCore(ASYNCHRONOUS);
     return nullptr;
   }
 
   if (!mImageContainer) {
     mImageContainer = LayerManager::CreateImageContainer();
   }
 
   CairoImage::Data cairoData;
   GetWidth(&cairoData.mSize.width);
   GetHeight(&cairoData.mSize.height);
-  cairoData.mSourceSurface = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, imageSurface);
+  cairoData.mSourceSurface = surface;
 
   nsRefPtr<layers::Image> image = mImageContainer->CreateImage(ImageFormat::CAIRO_SURFACE);
   NS_ASSERTION(image, "Failed to create Image");
 
   static_cast<CairoImage*>(image.get())->SetData(cairoData);
 
   return image.forget();
 }
--- a/image/src/SurfaceCache.cpp
+++ b/image/src/SurfaceCache.cpp
@@ -105,20 +105,21 @@ private:
   CachedSurface* mSurface;
   Cost           mCost;
 };
 
 /*
  * A CachedSurface associates a surface with a key that uniquely identifies that
  * surface.
  */
-class CachedSurface : public RefCounted<CachedSurface>
+class CachedSurface
 {
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(CachedSurface)
+  NS_INLINE_DECL_REFCOUNTING(CachedSurface)
+
   CachedSurface(DrawTarget*       aTarget,
                 const IntSize     aTargetSize,
                 const Cost        aCost,
                 const ImageKey    aImageKey,
                 const SurfaceKey& aSurfaceKey)
     : mTarget(aTarget)
     , mTargetSize(aTargetSize)
     , mCost(aCost)
@@ -151,20 +152,21 @@ private:
 };
 
 /*
  * An ImageSurfaceCache is a per-image surface cache. For correctness we must be
  * able to remove all surfaces associated with an image when the image is
  * destroyed or invalidated. Since this will happen frequently, it makes sense
  * to make it cheap by storing the surfaces for each image separately.
  */
-class ImageSurfaceCache : public RefCounted<ImageSurfaceCache>
+class ImageSurfaceCache
 {
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(ImageSurfaceCache)
+  NS_INLINE_DECL_REFCOUNTING(ImageSurfaceCache)
+
   typedef nsRefPtrHashtable<nsGenericHashKey<SurfaceKey>, CachedSurface> SurfaceTable;
 
   bool IsEmpty() const { return mSurfaces.Count() == 0; }
   
   void Insert(const SurfaceKey& aKey, CachedSurface* aSurface)
   {
     MOZ_ASSERT(aSurface, "Should have a surface");
     mSurfaces.Put(aKey, aSurface);
--- a/image/src/VectorImage.cpp
+++ b/image/src/VectorImage.cpp
@@ -644,19 +644,19 @@ VectorImage::FrameIsOpaque(uint32_t aWhi
 {
   if (aWhichFrame > FRAME_MAX_VALUE)
     NS_WARNING("aWhichFrame outside valid range!");
 
   return false; // In general, SVG content is not opaque.
 }
 
 //******************************************************************************
-/* [noscript] gfxASurface getFrame(in uint32_t aWhichFrame,
- *                                 in uint32_t aFlags; */
-NS_IMETHODIMP_(already_AddRefed<gfxASurface>)
+/* [noscript] SourceSurface getFrame(in uint32_t aWhichFrame,
+ *                                   in uint32_t aFlags; */
+NS_IMETHODIMP_(TemporaryRef<SourceSurface>)
 VectorImage::GetFrame(uint32_t aWhichFrame,
                       uint32_t aFlags)
 {
   MOZ_ASSERT(aWhichFrame <= FRAME_MAX_VALUE);
 
   if (aWhichFrame > FRAME_MAX_VALUE)
     return nullptr;
 
@@ -669,45 +669,32 @@ VectorImage::GetFrame(uint32_t aWhichFra
   if (!mSVGDocumentWrapper->GetWidthOrHeight(SVGDocumentWrapper::eWidth,
                                              imageIntSize.width) ||
       !mSVGDocumentWrapper->GetWidthOrHeight(SVGDocumentWrapper::eHeight,
                                              imageIntSize.height)) {
     // We'll get here if our SVG doc has a percent-valued width or height.
     return nullptr;
   }
 
-  // Create a surface that we'll ultimately return
-  // ---------------------------------------------
   // Make our surface the size of what will ultimately be drawn to it.
   // (either the full image size, or the restricted region)
-  gfxIntSize surfaceSize(imageIntSize.width, imageIntSize.height);
-
-  nsRefPtr<gfxImageSurface> surface =
-    new gfxImageSurface(surfaceSize, gfxImageFormat::ARGB32);
+  RefPtr<DrawTarget> dt = gfxPlatform::GetPlatform()->
+    CreateOffscreenContentDrawTarget(IntSize(imageIntSize.width,
+                                             imageIntSize.height),
+                                     SurfaceFormat::B8G8R8A8);
+  nsRefPtr<gfxContext> context = new gfxContext(dt);
 
-  RefPtr<DrawTarget> drawTarget =
-    Factory::CreateDrawTargetForData(BackendType::CAIRO,
-                                     surface->Data(),
-                                     IntSize(imageIntSize.width,
-                                             imageIntSize.height),
-                                     surface->Stride(),
-                                     SurfaceFormat::B8G8R8A8);
-
-  nsRefPtr<gfxContext> context = new gfxContext(drawTarget);
-
-  // Draw to our surface!
-  // --------------------
   nsresult rv = Draw(context, GraphicsFilter::FILTER_NEAREST, gfxMatrix(),
                      gfxRect(gfxPoint(0,0), gfxIntSize(imageIntSize.width,
                                                        imageIntSize.height)),
                      nsIntRect(nsIntPoint(0,0), imageIntSize),
                      imageIntSize, nullptr, aWhichFrame, aFlags);
 
   NS_ENSURE_SUCCESS(rv, nullptr);
-  return surface.forget();
+  return dt->Snapshot();
 }
 
 //******************************************************************************
 /* [noscript] ImageContainer getImageContainer(); */
 NS_IMETHODIMP
 VectorImage::GetImageContainer(LayerManager* aManager,
                                mozilla::layers::ImageContainer** _retval)
 {
--- a/image/src/imgTools.cpp
+++ b/image/src/imgTools.cpp
@@ -1,16 +1,17 @@
 /* -*- 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 "imgTools.h"
 
+#include "gfxUtils.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/RefPtr.h"
 #include "nsCOMPtr.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsError.h"
 #include "imgLoader.h"
 #include "imgICache.h"
@@ -92,30 +93,16 @@ NS_IMETHODIMP imgTools::DecodeImage(nsII
   rv = image->OnImageDataComplete(nullptr, nullptr, NS_OK, true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // All done.
   NS_ADDREF(*aContainer = image.get());
   return NS_OK;
 }
 
-static TemporaryRef<SourceSurface>
-GetFirstImageFrame(imgIContainer *aContainer)
-{
-  nsRefPtr<gfxASurface> frame =
-    aContainer->GetFrame(imgIContainer::FRAME_FIRST,
-                         imgIContainer::FLAG_SYNC_DECODE);
-  NS_ENSURE_TRUE(frame, nullptr);
-
-  nsRefPtr<gfxImageSurface> imageSurface = frame->CopyToARGB32ImageSurface();
-  NS_ENSURE_TRUE(imageSurface, nullptr);
-
-  return imageSurface->CopyToB8G8R8A8DataSourceSurface();
-}
-
 /**
  * This takes a DataSourceSurface rather than a SourceSurface because some
  * of the callers have a DataSourceSurface and we don't want to call
  * GetDataSurface on such surfaces since that may incure a conversion to
  * SurfaceType::DATA which we don't need.
  */
 static nsresult EncodeImageData(DataSourceSurface* aDataSurface,
                                 const nsACString& aMimeType,
@@ -156,20 +143,32 @@ static nsresult EncodeImageData(DataSour
 }
 
 NS_IMETHODIMP imgTools::EncodeImage(imgIContainer *aContainer,
                                     const nsACString& aMimeType,
                                     const nsAString& aOutputOptions,
                                     nsIInputStream **aStream)
 {
   // Use frame 0 from the image container.
-  RefPtr<SourceSurface> frame = GetFirstImageFrame(aContainer);
+  RefPtr<SourceSurface> frame =
+    aContainer->GetFrame(imgIContainer::FRAME_FIRST,
+                         imgIContainer::FLAG_SYNC_DECODE);
   NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
 
-  RefPtr<DataSourceSurface> dataSurface = frame->GetDataSurface();
+  RefPtr<DataSourceSurface> dataSurface;
+
+  if (frame->GetFormat() == SurfaceFormat::B8G8R8A8) {
+    dataSurface = frame->GetDataSurface();
+  } else {
+    // Convert format to SurfaceFormat::B8G8R8A8
+    dataSurface = gfxUtils::
+      CopySurfaceToDataSourceSurfaceWithFormat(frame,
+                                               SurfaceFormat::B8G8R8A8);
+  }
+
   NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
 
   return EncodeImageData(dataSurface, aMimeType, aOutputOptions, aStream);
 }
 
 NS_IMETHODIMP imgTools::EncodeScaledImage(imgIContainer *aContainer,
                                           const nsACString& aMimeType,
                                           int32_t aScaledWidth,
@@ -181,17 +180,19 @@ NS_IMETHODIMP imgTools::EncodeScaledImag
 
   // If no scaled size is specified, we'll just encode the image at its
   // original size (no scaling).
   if (aScaledWidth == 0 && aScaledHeight == 0) {
     return EncodeImage(aContainer, aMimeType, aOutputOptions, aStream);
   }
 
   // Use frame 0 from the image container.
-  RefPtr<SourceSurface> frame = GetFirstImageFrame(aContainer);
+  RefPtr<SourceSurface> frame =
+    aContainer->GetFrame(imgIContainer::FRAME_FIRST,
+                         imgIContainer::FLAG_SYNC_DECODE);
   NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
 
   int32_t frameWidth = frame->GetSize().width;
   int32_t frameHeight = frame->GetSize().height;
 
   // If the given width or height is zero we'll replace it with the image's
   // original dimensions.
   if (aScaledWidth == 0) {
@@ -242,17 +243,19 @@ NS_IMETHODIMP imgTools::EncodeCroppedIma
 
   // If no size is specified then we'll preserve the image's original dimensions
   // and don't need to crop.
   if (aWidth == 0 && aHeight == 0) {
     return EncodeImage(aContainer, aMimeType, aOutputOptions, aStream);
   }
 
   // Use frame 0 from the image container.
-  RefPtr<SourceSurface> frame = GetFirstImageFrame(aContainer);
+  RefPtr<SourceSurface> frame =
+    aContainer->GetFrame(imgIContainer::FRAME_FIRST,
+                         imgIContainer::FLAG_SYNC_DECODE);
   NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
 
   int32_t frameWidth = frame->GetSize().width;
   int32_t frameHeight = frame->GetSize().height;
 
   // If the given width or height is zero we'll replace it with the image's
   // original dimensions.
   if (aWidth == 0) {
--- a/ipc/netd/Netd.cpp
+++ b/ipc/netd/Netd.cpp
@@ -11,16 +11,17 @@
 #include "cutils/properties.h"
 #include "android/log.h"
 
 #include "nsWhitespaceTokenizer.h"
 #include "nsXULAppAPI.h"
 #include "nsAutoPtr.h"
 #include "nsString.h"
 #include "nsThreadUtils.h"
+#include "mozilla/RefPtr.h"
 
 
 #define CHROMIUM_LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gonk", args)
 #define ICS_SYS_USB_RNDIS_MAC "/sys/class/android_usb/android0/f_rndis/ethaddr"
 #define INVALID_SOCKET -1
 #define MAX_RECONNECT_TIMES 10
 
 namespace {
--- a/ipc/netd/Netd.h
+++ b/ipc/netd/Netd.h
@@ -1,16 +1,16 @@
 /* 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_system_netd_h__
 #define mozilla_system_netd_h__
 
-#include "mozilla/RefPtr.h"
+#include "nsISupportsImpl.h"
 #include "nsAutoPtr.h"
 #include "base/message_loop.h"
 #include "mozilla/FileUtils.h"
 
 #define MAX_COMMAND_SIZE  4096
 
 namespace mozilla {
 namespace ipc {
@@ -21,38 +21,41 @@ namespace ipc {
 struct NetdCommand
 {
   uint8_t mData[MAX_COMMAND_SIZE];
 
   // Number of octets in mData.
   size_t mSize;
 };
 
-class NetdConsumer : public mozilla::RefCounted<NetdConsumer>
+class NetdConsumer
 {
+protected:
+  virtual ~NetdConsumer() { }
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(NetdConsumer)
-  virtual ~NetdConsumer() { }
+  NS_INLINE_DECL_REFCOUNTING(NetdConsumer)
+
   virtual void MessageReceived(NetdCommand* aMessage) = 0;
 };
 
 class NetdWriteTask : public Task
 {
   virtual void Run();
 };
 
-class NetdClient : public MessageLoopForIO::LineWatcher,
-                   public RefCounted<NetdClient>
+class NetdClient : public MessageLoopForIO::LineWatcher
 {
+  virtual ~NetdClient();
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(NetdClient)
+  NS_INLINE_DECL_REFCOUNTING(NetdClient)
   typedef std::queue<NetdCommand*> NetdCommandQueue;
 
   NetdClient();
-  virtual ~NetdClient();
   static void Start();
   static void SendNetdCommandIOThread(NetdCommand* aMessage);
 
 private:
   void WriteNetdCommand();
   virtual void OnError();
   virtual void OnLineRead(int aFd, nsDependentCSubstring& aMessage);
   virtual void OnFileCanWriteWithoutBlocking(int aFd);
--- a/ipc/unixsocket/UnixSocket.h
+++ b/ipc/unixsocket/UnixSocket.h
@@ -130,24 +130,26 @@ public:
 
 enum SocketConnectionStatus {
   SOCKET_DISCONNECTED = 0,
   SOCKET_LISTENING = 1,
   SOCKET_CONNECTING = 2,
   SOCKET_CONNECTED = 3
 };
 
-class UnixSocketConsumer : public AtomicRefCounted<UnixSocketConsumer>
+class UnixSocketConsumer
 {
+protected:
+  virtual ~UnixSocketConsumer();
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(UnixSocketConsumer)
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(UnixSocketConsumer)
+
   UnixSocketConsumer();
 
-  virtual ~UnixSocketConsumer();
-
   SocketConnectionStatus GetConnectionStatus() const
   {
     MOZ_ASSERT(NS_IsMainThread());
     return mConnectionStatus;
   }
 
   int GetSuggestedConnectDelayMs() const
   {
--- a/js/ipc/JavaScriptChild.cpp
+++ b/js/ipc/JavaScriptChild.cpp
@@ -434,16 +434,18 @@ JavaScriptChild::AnswerIsExtensible(cons
     JSAutoRequest request(cx);
 
     *result = false;
 
     RootedObject obj(cx, findObject(objId));
     if (!obj)
         return false;
 
+    JSAutoCompartment comp(cx, obj);
+
     bool extensible;
     if (!JS_IsExtensible(cx, obj, &extensible))
         return fail(cx, rs);
 
     *result = !!extensible;
     return ok(rs);
 }
 
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug892794.js
@@ -0,0 +1,13 @@
+// |jit-test| ion-eager
+
+function test0(v) {
+  return (2147483648-Math.max(1.1,-(((2<<(-v|v))-3)|0)))|0;
+}
+assertEq(test0(1.6), 2147483645);
+assertEq(test0(437348122.9), 2147483646);
+
+function test1(v) {
+  return (2147483648+Math.min(v,0))|0;
+}
+assertEq(test1(2.1), -2147483648)
+assertEq(test1(-0.1), 2147483647)
--- a/js/src/jit-test/tests/proxy/testDirectProxyConstruct2.js
+++ b/js/src/jit-test/tests/proxy/testDirectProxyConstruct2.js
@@ -1,15 +1,18 @@
+load(libdir + "asserts.js");
 /*
  * Call the trap with the handler as the this value, the target as the first
  * argument, and the original arguments as the third argument.
+ *
+ * Hooks that don't return an object must throw.
  */
 var target = function () {};
 var handler = {
     construct: function (target1, args) {
         assertEq(this, handler);
         assertEq(target1, target);
         assertEq(args.length, 2);
         assertEq(args[0], 2);
         assertEq(args[1], 3);
     }
 }
-assertEq(new (new Proxy(target, handler))(2, 3), undefined);
+assertThrowsInstanceOf(function () {new (new Proxy(target, handler))(2, 3)}, TypeError);
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -4369,16 +4369,17 @@ ICGetElemNativeCompiler::generateStubCod
             emitCallNative(masm, objReg);
 
         } else {
             JS_ASSERT(acctype_ == ICGetElemNativeStub::ScriptedGetter);
 
             // Load function in scratchReg and ensure that it has a jit script.
             masm.loadPtr(Address(BaselineStubReg, ICGetElemNativeGetterStub::offsetOfGetter()),
                          scratchReg);
+            masm.branchIfFunctionHasNoScript(scratchReg, popR1 ? &failurePopR1 : &failure);
             masm.loadPtr(Address(scratchReg, JSFunction::offsetOfNativeOrScript()), scratchReg);
             masm.loadBaselineOrIonRaw(scratchReg, scratchReg, SequentialExecution,
                                       popR1 ? &failurePopR1 : &failure);
 
             // At this point, we are guaranteed to successfully complete.
             if (popR1)
                 masm.addPtr(Imm32(sizeof(size_t)), BaselineStackReg);
 
@@ -4801,34 +4802,47 @@ ICGetElem_Arguments::Compiler::generateS
     return true;
 }
 
 //
 // SetElem_Fallback
 //
 
 static bool
+SetElemDenseAddHasSameShapes(ICSetElem_DenseAdd *stub, JSObject *obj)
+{
+    size_t numShapes = stub->protoChainDepth() + 1;
+    for (size_t i = 0; i < numShapes; i++) {
+        static const size_t MAX_DEPTH = ICSetElem_DenseAdd::MAX_PROTO_CHAIN_DEPTH;
+        if (obj->lastProperty() != stub->toImplUnchecked<MAX_DEPTH>()->shape(i))
+            return false;
+        obj = obj->getProto();
+        if (!obj && i != numShapes - 1)
+            return false;
+    }
+
+    return true;
+}
+
+static bool
 DenseSetElemStubExists(JSContext *cx, ICStub::Kind kind, ICSetElem_Fallback *stub, HandleObject obj)
 {
     JS_ASSERT(kind == ICStub::SetElem_Dense || kind == ICStub::SetElem_DenseAdd);
 
     for (ICStubConstIterator iter = stub->beginChainConst(); !iter.atEnd(); iter++) {
         if (kind == ICStub::SetElem_Dense && iter->isSetElem_Dense()) {
             ICSetElem_Dense *dense = iter->toSetElem_Dense();
             if (obj->lastProperty() == dense->shape() && obj->getType(cx) == dense->type())
                 return true;
         }
 
         if (kind == ICStub::SetElem_DenseAdd && iter->isSetElem_DenseAdd()) {
             ICSetElem_DenseAdd *dense = iter->toSetElem_DenseAdd();
-            if (obj->lastProperty() == dense->toImplUnchecked<0>()->shape(0) &&
-                obj->getType(cx) == dense->type())
-            {
+            if (obj->getType(cx) == dense->type() && SetElemDenseAddHasSameShapes(dense, obj))
                 return true;
-            }
         }
     }
     return false;
 }
 
 static bool
 TypedArraySetElemStubExists(ICSetElem_Fallback *stub, HandleObject obj, bool expectOOB)
 {
--- a/js/src/jit/BaselineIC.h
+++ b/js/src/jit/BaselineIC.h
@@ -3550,16 +3550,17 @@ class ICSetElem_DenseAdd : public ICUpda
     static size_t offsetOfType() {
         return offsetof(ICSetElem_DenseAdd, type_);
     }
 
     HeapPtrTypeObject &type() {
         return type_;
     }
     size_t protoChainDepth() const {
+        MOZ_ASSERT(extra_ <= MAX_PROTO_CHAIN_DEPTH);
         return extra_;
     }
 
     template <size_t ProtoChainDepth>
     ICSetElem_DenseAddImpl<ProtoChainDepth> *toImplUnchecked() {
         return static_cast<ICSetElem_DenseAddImpl<ProtoChainDepth> *>(this);
     }
 
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -3011,53 +3011,43 @@ jit::TraceIonScripts(JSTracer* trc, JSSc
 
 AutoDebugModeInvalidation::~AutoDebugModeInvalidation()
 {
     MOZ_ASSERT(!!comp_ != !!zone_);
 
     if (needInvalidation_ == NoNeed)
         return;
 
-    // Invalidate the stack if any compartments toggled from on->off, because
-    // we allow scripts to be on stack when turning off debug mode.
-    bool invalidateStack = needInvalidation_ == ToggledOff;
     Zone *zone = zone_ ? zone_ : comp_->zone();
     JSRuntime *rt = zone->runtimeFromMainThread();
     FreeOp *fop = rt->defaultFreeOp();
 
     if (comp_) {
         StopAllOffThreadCompilations(comp_);
     } else {
         for (CompartmentsInZoneIter comp(zone_); !comp.done(); comp.next())
             StopAllOffThreadCompilations(comp);
     }
 
-    if (invalidateStack) {
-        jit::MarkActiveBaselineScripts(zone);
-
-        for (JitActivationIterator iter(rt); !iter.done(); ++iter) {
-            JSCompartment *comp = iter.activation()->compartment();
-            if ((comp_ && comp_ == comp) ||
-                (zone_ && zone_ == comp->zone() && comp->principals))
-            {
-                IonContext ictx(CompileRuntime::get(rt));
-                AutoFlushCache afc("AutoDebugModeInvalidation", rt->jitRuntime());
-                IonSpew(IonSpew_Invalidate, "Invalidating frames for debug mode toggle");
-                InvalidateActivation(fop, iter.jitTop(), true);
-            }
+    jit::MarkActiveBaselineScripts(zone);
+
+    for (JitActivationIterator iter(rt); !iter.done(); ++iter) {
+        JSCompartment *comp = iter.activation()->compartment();
+        if ((comp_ && comp_ == comp) || (zone_ && zone_ == comp->zone())) {
+            IonContext ictx(CompileRuntime::get(rt));
+            AutoFlushCache afc("AutoDebugModeInvalidation", rt->jitRuntime());
+            IonSpew(IonSpew_Invalidate, "Invalidating frames for debug mode toggle");
+            InvalidateActivation(fop, iter.jitTop(), true);
         }
     }
 
     for (gc::CellIter i(zone, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
         JSScript *script = i.get<JSScript>();
-        if ((comp_ && script->compartment() == comp_) ||
-            (zone_ && script->compartment()->principals))
-        {
+        if ((comp_ && script->compartment() == comp_) || zone_) {
             FinishInvalidation<SequentialExecution>(fop, script);
             FinishInvalidation<ParallelExecution>(fop, script);
             FinishDiscardBaselineScript(fop, script);
-            // script->clearAnalysis();
             script->resetUseCount();
         } else if (script->hasBaselineScript()) {
             script->baselineScript()->resetActive();
         }
     }
 }
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -432,8 +432,10 @@ MSG_DEF(JSMSG_RC_AFTER_EXPORT_SPEC_LIST,
 MSG_DEF(JSMSG_NO_EXPORT_NAME,           378, 0, JSEXN_SYNTAXERR, "missing export name")
 MSG_DEF(JSMSG_DECLARATION_AFTER_EXPORT, 379, 0, JSEXN_SYNTAXERR, "missing declaration after 'export' keyword")
 MSG_DEF(JSMSG_INVALID_PROTOTYPE,        380, 0, JSEXN_TYPEERR, "prototype field is not an object")
 MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_TO_UNSIZED, 381, 0, JSEXN_TYPEERR, "cannot create a handle to an unsized type")
 MSG_DEF(JSMSG_SETPROTOTYPEOF_FAIL,      382, 1, JSEXN_TYPEERR, "[[SetPrototypeOf]] failed on {0}")
 MSG_DEF(JSMSG_INVALID_ARG_TYPE,         383, 3, JSEXN_TYPEERR, "Invalid type: {0} can't be a{1} {2}")
 MSG_DEF(JSMSG_TERMINATED,               384, 1, JSEXN_ERR, "Script terminated by timeout at:\n{0}")
 MSG_DEF(JSMSG_NO_SUCH_SELF_HOSTED_PROP, 385, 1, JSEXN_ERR, "No such property on self-hosted object: {0}")
+MSG_DEF(JSMSG_PROXY_EXTENSIBILITY,      386, 0, JSEXN_TYPEERR, "proxy must report same extensiblitity as target")
+MSG_DEF(JSMSG_PROXY_CONSTRUCT_OBJECT,   387, 0, JSEXN_TYPEERR, "proxy [[Construct]] must return an object")
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -1072,22 +1072,16 @@ ScriptedIndirectProxyHandler::fun_toStri
         return nullptr;
     }
     RootedObject obj(cx, &proxy->as<ProxyObject>().extra(0).toObject().getReservedSlot(0).toObject());
     return fun_toStringHelper(cx, obj, indent);
 }
 
 ScriptedIndirectProxyHandler ScriptedIndirectProxyHandler::singleton;
 
-static JSObject *
-GetDirectProxyHandlerObject(JSObject *proxy)
-{
-    return proxy->as<ProxyObject>().extra(0).toObjectOrNull();
-}
-
 /* Derived class for all scripted direct proxy handlers. */
 class ScriptedDirectProxyHandler : public DirectProxyHandler {
   public:
     ScriptedDirectProxyHandler();
     virtual ~ScriptedDirectProxyHandler();
 
     /* ES5 Harmony fundamental proxy traps. */
     virtual bool preventExtensions(JSContext *cx, HandleObject proxy) MOZ_OVERRIDE;
@@ -1109,16 +1103,19 @@ class ScriptedDirectProxyHandler : publi
     virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
                      MutableHandleValue vp) MOZ_OVERRIDE;
     virtual bool set(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
                      bool strict, MutableHandleValue vp) MOZ_OVERRIDE;
     virtual bool keys(JSContext *cx, HandleObject proxy, AutoIdVector &props) MOZ_OVERRIDE;
     virtual bool iterate(JSContext *cx, HandleObject proxy, unsigned flags,
                          MutableHandleValue vp) MOZ_OVERRIDE;
 
+    /* ES6 Harmony traps */
+    virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) MOZ_OVERRIDE;
+
     /* Spidermonkey extensions. */
     virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args) MOZ_OVERRIDE;
     virtual bool construct(JSContext *cx, HandleObject proxy, const CallArgs &args) MOZ_OVERRIDE;
     virtual bool isScripted() MOZ_OVERRIDE { return true; }
 
     static ScriptedDirectProxyHandler singleton;
 };
 
@@ -1360,16 +1357,26 @@ IdToValue(JSContext *cx, HandleId id, Mu
     value.set(IdToValue(id)); // Re-use out-param to avoid Rooted overhead.
     JSString *name = ToString<CanGC>(cx, value);
     if (!name)
         return false;
     value.set(StringValue(name));
     return true;
 }
 
+// Get the [[ProxyHandler]] of a scripted direct proxy.
+//
+// NB: This *must* stay synched with proxy().
+static JSObject *
+GetDirectProxyHandlerObject(JSObject *proxy)
+{
+    JS_ASSERT(proxy->as<ProxyObject>().handler() == &ScriptedDirectProxyHandler::singleton);
+    return proxy->as<ProxyObject>().extra(0).toObjectOrNull();
+}
+
 // TrapGetOwnProperty(O, P)
 static bool
 TrapGetOwnProperty(JSContext *cx, HandleObject proxy, HandleId id, MutableHandleValue rval)
 {
     // step 1
     RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
 
     // step 2
@@ -2220,16 +2227,52 @@ ScriptedDirectProxyHandler::keys(JSConte
                              v, js::NullPtr(), bytes.ptr());
         return false;
     }
 
     // steps g-n are shared
     return ArrayToIdVector(cx, proxy, target, trapResult, props, JSITER_OWNONLY, cx->names().keys);
 }
 
+// ES6 (5 April, 2014) 9.5.3 Proxy.[[IsExtensible]](P)
+bool
+ScriptedDirectProxyHandler::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible)
+{
+    RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
+
+    RootedObject target(cx, proxy->as<ProxyObject>().target());
+
+    RootedValue trap(cx);
+    if (!JSObject::getProperty(cx, handler, handler, cx->names().isExtensible, &trap))
+        return false;
+
+    if (trap.isUndefined())
+        return DirectProxyHandler::isExtensible(cx, proxy, extensible);
+
+    Value argv[] = {
+        ObjectValue(*target)
+    };
+    RootedValue trapResult(cx);
+    if (!Invoke(cx, ObjectValue(*handler), trap, ArrayLength(argv), argv, &trapResult))
+        return false;
+
+    bool booleanTrapResult = ToBoolean(trapResult);
+    bool targetResult;
+    if (!JSObject::isExtensible(cx, target, &targetResult))
+        return false;
+
+    if (targetResult != booleanTrapResult) {
+       JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_EXTENSIBILITY);
+       return false;
+    }
+
+    *extensible = booleanTrapResult;
+    return true;
+}
+
 bool
 ScriptedDirectProxyHandler::iterate(JSContext *cx, HandleObject proxy, unsigned flags,
                                     MutableHandleValue vp)
 {
     // FIXME: Provide a proper implementation for this trap, see bug 787004
     return DirectProxyHandler::iterate(cx, proxy, flags, vp);
 }
 
@@ -2300,17 +2343,23 @@ ScriptedDirectProxyHandler::construct(JS
         return DirectProxyHandler::construct(cx, proxy, args);
 
     // step 6
     Value constructArgv[] = {
         ObjectValue(*target),
         ObjectValue(*argsArray)
     };
     RootedValue thisValue(cx, ObjectValue(*handler));
-    return Invoke(cx, thisValue, trap, ArrayLength(constructArgv), constructArgv, args.rval());
+    if (!Invoke(cx, thisValue, trap, ArrayLength(constructArgv), constructArgv, args.rval()))
+        return false;
+    if (!args.rval().isObject()) {
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_PROXY_CONSTRUCT_OBJECT);
+        return false;
+    }
+    return true;
 }
 
 ScriptedDirectProxyHandler ScriptedDirectProxyHandler::singleton;
 
 #define INVOKE_ON_PROTOTYPE(cx, handler, proxy, protoCall)                   \
     JS_BEGIN_MACRO                                                           \
         RootedObject proto(cx);                                              \
         if (!JSObject::getProto(cx, proxy, &proto))                          \
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Proxy/proxy-constructNonObject.js
@@ -0,0 +1,18 @@
+function bogusConstruct(target) { return 4; }
+function bogusConstructUndefined(target) { }
+
+var handler = { construct: bogusConstruct }
+
+function callable() {}
+
+var p = new Proxy(callable, handler);
+
+assertThrowsInstanceOf(function () { new p(); }, TypeError,
+                       "[[Construct must throw if an object is not returned.");
+
+handler.construct = bogusConstructUndefined;
+assertThrowsInstanceOf(function () { new p(); }, TypeError,
+                       "[[Construct must throw if an object is not returned.");
+
+if (typeof reportCompare === "function")
+    reportCompare(0,0, "OK");
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Proxy/proxy-isExtensible.js
@@ -0,0 +1,94 @@
+// Test ES6 Proxy trap compliance for Object.isExtensible() on exotic proxy
+// objects.
+var unsealed = {};
+var sealed = Object.seal({});
+var handler = {};
+
+assertEq(Object.isExtensible(unsealed), true);
+assertEq(Object.isExtensible(sealed), false);
+
+var targetSealed = new Proxy(sealed, handler);
+var targetUnsealed = new Proxy(unsealed, handler);
+
+var handlerCalled = false;
+
+// without traps, forward to the target
+// First, make sure we get the obvious answer on a non-exotic target.
+assertEq(Object.isExtensible(targetSealed), false, "Must forward to target without hook.");
+assertEq(Object.isExtensible(targetUnsealed), true, "Must forward to target without hook.");
+
+// Now, keep everyone honest. What if the target itself is a proxy?
+function ensureCalled() { handlerCalled = true; return true; }
+var proxyTarget = new Proxy({}, { isExtensible : ensureCalled });
+assertEq(Object.isExtensible(new Proxy(proxyTarget, {})), true, "Must forward to target without hook.");
+assertEq(handlerCalled, true, "Must forward to target without hook.");
+
+// with traps, makes sure that the handler is called, and that we throw if the
+// trap disagrees with the target
+function testExtensible(obj, shouldThrow, expectedResult)
+{
+    handlerCalled = false;
+    if (shouldThrow)
+        assertThrowsInstanceOf(function () { Object.isExtensible(obj); },
+                               TypeError, "Must throw if handler and target disagree.");
+    else
+        assertEq(Object.isExtensible(obj), expectedResult, "Must return the correct value.");
+    assertEq(handlerCalled, true, "Must call handler trap if present");
+}
+
+// What if the trap says it's necessarily sealed?
+function fakeSealed() { handlerCalled = true; return false; }
+handler.isExtensible = fakeSealed;
+testExtensible(targetSealed, false, false);
+testExtensible(targetUnsealed, true);
+
+// What if the trap says it's never sealed?
+function fakeUnsealed() { handlerCalled = true; return true; }
+handler.isExtensible = fakeUnsealed;
+testExtensible(targetSealed, true);
+testExtensible(targetUnsealed, false, true);
+
+// make sure we are able to prevent further extensions mid-flight and throw if the
+// hook tries to lie.
+function makeSealedTruth(target) { handlerCalled = true; Object.preventExtensions(target); return false; }
+function makeSealedLie(target) { handlerCalled = true; Object.preventExtensions(target); return true; }
+handler.isExtensible = makeSealedTruth;
+testExtensible(new Proxy({}, handler), false, false);
+handler.isExtensible = makeSealedLie;
+testExtensible(new Proxy({}, handler), true);
+
+// What if the trap doesn't directly return a boolean?
+function falseyNonBool() { handlerCalled = true; return undefined; }
+handler.isExtensible = falseyNonBool;
+testExtensible(targetSealed, false, false);
+testExtensible(targetUnsealed, true);
+
+function truthyNonBool() { handlerCalled = true; return {}; }
+handler.isExtensible = truthyNonBool;
+testExtensible(targetSealed, true);
+testExtensible(targetUnsealed, false, true);
+
+// What if the trap throws?
+function ExtensibleError() { }
+ExtensibleError.prototype = new Error();
+ExtensibleError.prototype.constructor = ExtensibleError;
+function throwFromTrap() { throw new ExtensibleError(); }
+handler.isExtensible = throwFromTrap;
+
+// exercise some other code paths and make sure that they invoke the trap and
+// can handle the ensuing error.
+assertThrowsInstanceOf(function () { Object.isExtensible(targetSealed); },
+                       ExtensibleError, "Must throw if the trap does.");
+assertThrowsInstanceOf(function () { Object.isFrozen(targetSealed); },
+                       ExtensibleError, "Must throw if the trap does.");
+assertThrowsInstanceOf(function () { Object.isSealed(targetSealed); },
+                       ExtensibleError, "Must throw if the trap does.");
+
+
+// What if the trap likes to re-ask old questions?
+function recurse() { return Object.isExtensible(targetSealed); }
+handler.isExtensible = recurse;
+assertThrowsInstanceOf(function () { Object.isExtensible(targetSealed); },
+                       InternalError, "Should allow and detect infinite recurison.");
+
+reportCompare(0, 0, "OK");
--- a/js/src/vm/CommonPropertyNames.h
+++ b/js/src/vm/CommonPropertyNames.h
@@ -98,16 +98,17 @@
     macro(isFinite, isFinite, "isFinite") \
     macro(isNaN, isNaN, "isNaN") \
     macro(isPrototypeOf, isPrototypeOf, "isPrototypeOf") \
     macro(iterate, iterate, "iterate") \
     macro(Infinity, Infinity, "Infinity") \
     macro(int8, int8, "int8") \
     macro(int16, int16, "int16") \
     macro(int32, int32, "int32") \
+    macro(isExtensible, isExtensible, "isExtensible") \
     macro(iterator, iterator, "iterator") \
     macro(iteratorIntrinsic, iteratorIntrinsic, "__iterator__") \
     macro(join, join, "join") \
     macro(keys, keys, "keys") \
     macro(lastIndex, lastIndex, "lastIndex") \
     macro(length, length, "length") \
     macro(let, let, "let") \
     macro(line, line, "line") \
--- a/js/src/vm/Opcodes.h
+++ b/js/src/vm/Opcodes.h
@@ -281,17 +281,17 @@ 1234567890123456789012345678901234567890
     macro(JSOP_UNUSED47,  47, "unused47",   NULL,         1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED48,  48, "unused48",   NULL,         1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED49,  49, "unused49",   NULL,         1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED50,  50, "unused50",   NULL,         1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED51,  51, "unused51",   NULL,         1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED52,  52, "unused52",   NULL,         1,  0,  0,  JOF_BYTE) \
     \
     macro(JSOP_GETPROP,   53, "getprop",    NULL,         5,  1,  1, JOF_ATOM|JOF_PROP|JOF_TYPESET|JOF_TMPSLOT3) \
-    macro(JSOP_SETPROP,   54, "setprop",    NULL,         5,  2,  1, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING|JOF_TMPSLOT) \
+    macro(JSOP_SETPROP,   54, "setprop",    NULL,         5,  2,  1, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING) \
     macro(JSOP_GETELEM,   55, "getelem",    NULL,         1,  2,  1, JOF_BYTE |JOF_ELEM|JOF_TYPESET|JOF_LEFTASSOC) \
     macro(JSOP_SETELEM,   56, "setelem",    NULL,         1,  3,  1, JOF_BYTE |JOF_ELEM|JOF_SET|JOF_DETECTING) \
     macro(JSOP_UNUSED57,  57, "unused57",   NULL,         1,  0,  0, JOF_BYTE) \
     macro(JSOP_CALL,      58, "call",       NULL,         3, -1,  1, JOF_UINT16|JOF_INVOKE|JOF_TYPESET) \
     macro(JSOP_NAME,      59, "name",       NULL,         5,  0,  1, JOF_ATOM|JOF_NAME|JOF_TYPESET) \
     macro(JSOP_DOUBLE,    60, "double",     NULL,         5,  0,  1, JOF_DOUBLE) \
     macro(JSOP_STRING,    61, "string",     NULL,         5,  0,  1, JOF_ATOM) \
     macro(JSOP_ZERO,      62, "zero",       "0",          1,  0,  1, JOF_BYTE) \
--- a/layout/base/FrameLayerBuilder.h
+++ b/layout/base/FrameLayerBuilder.h
@@ -41,19 +41,20 @@ enum LayerState {
   // when the layer has rounded rect clips.
   LAYER_ACTIVE_FORCE,
   // Special layer that is metadata only.
   LAYER_ACTIVE_EMPTY,
   // Inactive style layer for rendering SVG effects.
   LAYER_SVG_EFFECTS
 };
 
-class RefCountedRegion : public RefCounted<RefCountedRegion> {
+class RefCountedRegion {
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(RefCountedRegion)
+  NS_INLINE_DECL_REFCOUNTING(RefCountedRegion)
+
   RefCountedRegion() : mIsInfinite(false) {}
   nsRegion mRegion;
   bool mIsInfinite;
 };
 
 struct ContainerLayerParameters {
   ContainerLayerParameters() :
     mXScale(1), mYScale(1), mAncestorClipRect(nullptr),
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -5392,31 +5392,22 @@ nsLayoutUtils::SurfaceFromElement(nsIIma
 
   int32_t imgWidth, imgHeight;
   rv = imgContainer->GetWidth(&imgWidth);
   nsresult rv2 = imgContainer->GetHeight(&imgHeight);
   if (NS_FAILED(rv) || NS_FAILED(rv2))
     return result;
 
   if (!noRasterize || imgContainer->GetType() == imgIContainer::TYPE_RASTER) {
-    bool wantImageSurface = (aSurfaceFlags & SFE_WANT_IMAGE_SURFACE) != 0;
-    if (aSurfaceFlags & SFE_NO_PREMULTIPLY_ALPHA) {
-      wantImageSurface = true;
+    if (aSurfaceFlags & SFE_WANT_IMAGE_SURFACE) {
+      frameFlags |= imgIContainer::FLAG_WANT_DATA_SURFACE;
     }
-    
-    nsRefPtr<gfxASurface> gfxsurf =
-      imgContainer->GetFrame(whichFrame, frameFlags);
-    if (!gfxsurf)
+    result.mSourceSurface = imgContainer->GetFrame(whichFrame, frameFlags);
+    if (!result.mSourceSurface) {
       return result;
-
-    if (wantImageSurface) {
-      result.mSourceSurface = gfxPlatform::GetPlatform()->GetWrappedDataSourceSurface(gfxsurf);
-    }
-    if (!result.mSourceSurface) {
-      result.mSourceSurface = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(aTarget, gfxsurf);
     }
   } else {
     result.mDrawInfo.mImgContainer = imgContainer;
     result.mDrawInfo.mWhichFrame = whichFrame;
     result.mDrawInfo.mDrawingFlags = frameFlags;
   }
 
   int32_t corsmode;
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -1079,17 +1079,17 @@ static const mozilla::Module::ContractID
   { "@mozilla.org/layout/xul-boxobject-tree;1", &kNS_TREEBOXOBJECT_CID },
 #endif // MOZ_XUL
 #ifdef MOZ_XUL
   { "@mozilla.org/inspector/dom-view;1", &kIN_DOMVIEW_CID },
 #endif
   { "@mozilla.org/inspector/deep-tree-walker;1", &kIN_DEEPTREEWALKER_CID },
   { "@mozilla.org/inspector/flasher;1", &kIN_FLASHER_CID },
   { "@mozilla.org/inspector/search;1?type=cssvalue", &kIN_CSSVALUESEARCH_CID },
-  { "@mozilla.org/inspector/dom-utils;1", &kIN_DOMUTILS_CID },
+  { IN_DOMUTILS_CONTRACTID, &kIN_DOMUTILS_CID },
   { "@mozilla.org/xml/xml-document;1", &kNS_XMLDOCUMENT_CID },
   { "@mozilla.org/svg/svg-document;1", &kNS_SVGDOCUMENT_CID },
   { NS_DOMMULTIPARTBLOB_CONTRACTID, &kNS_DOMMULTIPARTBLOB_CID },
   { NS_DOMMULTIPARTFILE_CONTRACTID, &kNS_DOMMULTIPARTFILE_CID },
   { "@mozilla.org/content/dom-selection;1", &kNS_DOMSELECTION_CID },
   { "@mozilla.org/content/post-content-iterator;1", &kNS_CONTENTITERATOR_CID },
   { "@mozilla.org/content/pre-content-iterator;1", &kNS_PRECONTENTITERATOR_CID },
   { "@mozilla.org/content/subtree-content-iterator;1", &kNS_SUBTREEITERATOR_CID },
--- a/layout/generic/nsCanvasFrame.cpp
+++ b/layout/generic/nsCanvasFrame.cpp
@@ -210,17 +210,17 @@ static void BlitSurface(DrawTarget* aDes
 void
 nsDisplayCanvasBackgroundImage::Paint(nsDisplayListBuilder* aBuilder,
                                       nsRenderingContext* aCtx)
 {
   nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
   nsPoint offset = ToReferenceFrame();
   nsRect bgClipRect = frame->CanvasArea() + offset;
 
-  nsRenderingContext context;
+  nsRefPtr<nsRenderingContext> context;
   nsRefPtr<gfxContext> dest = aCtx->ThebesContext();
   nsRefPtr<gfxASurface> surf;
   RefPtr<DrawTarget> dt;
   nsRefPtr<gfxContext> ctx;
   gfxRect destRect;
 #ifndef MOZ_GFX_OPTIMIZE_MOBILE
   if (IsSingleFixedPositionImage(aBuilder, bgClipRect, &destRect) &&
       aBuilder->IsPaintingToWindow() && !aBuilder->IsCompositingCheap() &&
@@ -249,23 +249,24 @@ nsDisplayCanvasBackgroundImage::Paint(ns
     }
     if (surf || dt) {
       if (surf) {
         ctx = new gfxContext(surf);
       } else {
         ctx = new gfxContext(dt);
       }
       ctx->Translate(-gfxPoint(destRect.x, destRect.y));
-      context.Init(aCtx->DeviceContext(), ctx);
+      context = new nsRenderingContext();
+      context->Init(aCtx->DeviceContext(), ctx);
     }
   }
 #endif
 
   PaintInternal(aBuilder,
-                (surf || dt) ? &context : aCtx,
+                (surf || dt) ? context.get() : aCtx,
                 (surf || dt) ? bgClipRect: mVisibleRect,
                 &bgClipRect);
 
   if (surf) {
     BlitSurface(dest, destRect, surf);
     frame->Properties().Set(nsIFrame::CachedBackgroundImage(),
                             surf.forget().take());
   }
--- a/layout/inspector/inDOMView.cpp
+++ b/layout/inspector/inDOMView.cpp
@@ -19,16 +19,17 @@
 #include "nsIDOMMutationEvent.h"
 #include "nsBindingManager.h"
 #include "nsNameSpaceManager.h"
 #include "nsIDocument.h"
 #include "nsIServiceManager.h"
 #include "nsITreeColumns.h"
 #include "nsITreeBoxObject.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/Services.h"
 
 #ifdef ACCESSIBILITY
 #include "nsIAccessible.h"
 #include "nsIAccessibilityService.h"
 #endif
 
 using namespace mozilla;
 
@@ -785,17 +786,17 @@ inDOMView::ContentInserted(nsIDocument *
 {
   if (!mTree)
     return;
 
   nsresult rv;
   nsCOMPtr<nsIDOMNode> childDOMNode(do_QueryInterface(aChild));
   nsCOMPtr<nsIDOMNode> parent;
   if (!mDOMUtils) {
-    mDOMUtils = do_GetService("@mozilla.org/inspector/dom-utils;1");
+    mDOMUtils = services::GetInDOMUtils();
     if (!mDOMUtils) {
       return;
     }
   }
   mDOMUtils->GetParentForNode(childDOMNode, mShowAnonymous,
                               getter_AddRefs(parent));
 
   // find the inDOMViewNode for the parent of the inserted content
@@ -1184,17 +1185,17 @@ inDOMView::GetChildNodesFor(nsIDOMNode* 
         AppendAttrsToArray(attrs, aResult);
       }
     }
   }
 
   if (mWhatToShow & nsIDOMNodeFilter::SHOW_ELEMENT) {
     nsCOMPtr<nsIDOMNodeList> kids;
     if (!mDOMUtils) {
-      mDOMUtils = do_GetService("@mozilla.org/inspector/dom-utils;1");
+      mDOMUtils = services::GetInDOMUtils();
       if (!mDOMUtils) {
         return NS_ERROR_FAILURE;
       }
     }
 
     mDOMUtils->GetChildrenForNode(aNode, mShowAnonymous,
                                   getter_AddRefs(kids));
 
@@ -1229,17 +1230,17 @@ inDOMView::AppendKidsToArray(nsIDOMNodeL
 {
   uint32_t l = 0;
   aKids->GetLength(&l);
   nsCOMPtr<nsIDOMNode> kid;
   uint16_t nodeType = 0;
 
   // Try and get DOM Utils in case we don't have one yet.
   if (!mShowWhitespaceNodes && !mDOMUtils) {
-    mDOMUtils = do_CreateInstance("@mozilla.org/inspector/dom-utils;1");
+    mDOMUtils = services::GetInDOMUtils();
   }
 
   for (uint32_t i = 0; i < l; ++i) {
     aKids->Item(i, getter_AddRefs(kid));
     kid->GetNodeType(&nodeType);
 
     NS_ASSERTION(nodeType && nodeType <= nsIDOMNode::NOTATION_NODE,
                  "Unknown node type. "
--- a/layout/inspector/inIDOMUtils.idl
+++ b/layout/inspector/inIDOMUtils.idl
@@ -99,8 +99,12 @@ interface inIDOMUtils : nsISupports
    * Parse CSS and update the style sheet in place.
    *
    * @param DOMCSSStyleSheet aSheet
    * @param DOMString aInput
    *        The new source string for the style sheet.
    */
   void parseStyleSheet(in nsIDOMCSSStyleSheet aSheet, in DOMString aInput);
 };
+
+%{ C++
+#define IN_DOMUTILS_CONTRACTID "@mozilla.org/inspector/dom-utils;1"
+%}
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -653,43 +653,30 @@ public:
   {
     if (mTouchSensitiveRegion.IsEmpty())
       return false;
 
     *aOutRegion = CSSRect::FromAppUnits(mTouchSensitiveRegion.GetBounds());
     return true;
   }
 
-  virtual void NotifyTransformBegin(const ScrollableLayerGuid& aGuid)
+  virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
+                                    APZStateChange aChange,
+                                    int aArg)
   {
     if (MessageLoop::current() != mUILoop) {
       mUILoop->PostTask(
         FROM_HERE,
-        NewRunnableMethod(this, &RemoteContentController::NotifyTransformBegin,
-                          aGuid));
+        NewRunnableMethod(this, &RemoteContentController::NotifyAPZStateChange,
+                          aGuid, aChange, aArg));
       return;
     }
     if (mRenderFrame) {
       TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager());
-      browser->NotifyTransformBegin(aGuid.mScrollId);
-    }
-  }
-
-  virtual void NotifyTransformEnd(const ScrollableLayerGuid& aGuid)
-  {
-    if (MessageLoop::current() != mUILoop) {
-      mUILoop->PostTask(
-        FROM_HERE,
-        NewRunnableMethod(this, &RemoteContentController::NotifyTransformEnd,
-                          aGuid));
-      return;
-    }
-    if (mRenderFrame) {
-      TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager());
-      browser->NotifyTransformEnd(aGuid.mScrollId);
+      browser->NotifyAPZStateChange(aGuid.mScrollId, aChange, aArg);
     }
   }
 
   // Methods used by RenderFrameParent to set fields stored here.
 
   void SaveZoomConstraints(const ZoomConstraints& aConstraints)
   {
     mHaveZoomConstraints = true;
--- a/layout/svg/nsFilterInstance.cpp
+++ b/layout/svg/nsFilterInstance.cpp
@@ -313,21 +313,21 @@ nsFilterInstance::BuildSourcePaint(Sourc
     if (!offscreenDT) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
     ctx = new gfxContext(offscreenDT);
   }
 
   ctx->Translate(-neededRect.TopLeft());
 
-  nsRenderingContext tmpCtx;
-  tmpCtx.Init(mTargetFrame->PresContext()->DeviceContext(), ctx);
+  nsRefPtr<nsRenderingContext> tmpCtx(new nsRenderingContext());
+  tmpCtx->Init(mTargetFrame->PresContext()->DeviceContext(), ctx);
 
   gfxMatrix deviceToFilterSpace = GetFilterSpaceToDeviceSpaceTransform().Invert();
-  gfxContext *gfx = tmpCtx.ThebesContext();
+  gfxContext *gfx = tmpCtx->ThebesContext();
   gfx->Multiply(deviceToFilterSpace);
 
   gfx->Save();
 
   gfxMatrix matrix =
     nsSVGUtils::GetCanvasTM(mTargetFrame, nsISVGChildFrame::FOR_PAINTING,
                             mTransformRoot);
   if (!matrix.IsSingular()) {
@@ -396,18 +396,18 @@ nsFilterInstance::BuildSourceImage(gfxAS
     if (!offscreenDT) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
     ctx = new gfxContext(offscreenDT);
   }
 
   ctx->Translate(-neededRect.TopLeft());
 
-  nsRenderingContext tmpCtx;
-  tmpCtx.Init(mTargetFrame->PresContext()->DeviceContext(), ctx);
+  nsRefPtr<nsRenderingContext> tmpCtx(new nsRenderingContext());
+  tmpCtx->Init(mTargetFrame->PresContext()->DeviceContext(), ctx);
 
   gfxRect r = FilterSpaceToUserSpace(neededRect);
   r.RoundOut();
   nsIntRect dirty;
   if (!gfxUtils::GfxRectToIntRect(r, &dirty))
     return NS_ERROR_FAILURE;
 
   // SVG graphics paint to device space, so we need to set an initial device
@@ -417,18 +417,18 @@ nsFilterInstance::BuildSourceImage(gfxAS
   // (In theory it would be better to minimize error by having filtered SVG
   // graphics temporarily paint to user space when painting the sources and
   // only set a user space to filter space transform on the gfxContext
   // (since that would eliminate the transform multiplications from user
   // space to device space and back again). However, that would make the
   // code more complex while being hard to get right without introducing
   // subtle bugs, and in practice it probably makes no real difference.)
   gfxMatrix deviceToFilterSpace = GetFilterSpaceToDeviceSpaceTransform().Invert();
-  tmpCtx.ThebesContext()->Multiply(deviceToFilterSpace);
-  mPaintCallback->Paint(&tmpCtx, mTargetFrame, &dirty, mTransformRoot);
+  tmpCtx->ThebesContext()->Multiply(deviceToFilterSpace);
+  mPaintCallback->Paint(tmpCtx, mTargetFrame, &dirty, mTransformRoot);
 
   RefPtr<SourceSurface> sourceGraphicSource;
 
   if (offscreenSurface) {
     sourceGraphicSource =
       gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(aTargetDT, offscreenSurface);
   } else {
     sourceGraphicSource = offscreenDT->Snapshot();
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -600,18 +600,18 @@ PaintFrameCallback::operator()(gfxContex
                                const GraphicsFilter& aFilter,
                                const gfxMatrix& aTransform)
 {
   if (mFrame->GetStateBits() & NS_FRAME_DRAWING_AS_PAINTSERVER)
     return false;
 
   mFrame->AddStateBits(NS_FRAME_DRAWING_AS_PAINTSERVER);
 
-  nsRenderingContext context;
-  context.Init(mFrame->PresContext()->DeviceContext(), aContext);
+  nsRefPtr<nsRenderingContext> context(new nsRenderingContext());
+  context->Init(mFrame->PresContext()->DeviceContext(), aContext);
   aContext->Save();
 
   // Clip to aFillRect so that we don't paint outside.
   aContext->NewPath();
   aContext->Rectangle(aFillRect);
   aContext->Clip();
 
   aContext->Multiply(gfxMatrix(aTransform).Invert());
@@ -639,17 +639,17 @@ PaintFrameCallback::operator()(gfxContex
   nsRect dirty(-offset.x, -offset.y,
                mPaintServerSize.width, mPaintServerSize.height);
 
   uint32_t flags = nsLayoutUtils::PAINT_IN_TRANSFORM |
                    nsLayoutUtils::PAINT_ALL_CONTINUATIONS;
   if (mFlags & nsSVGIntegrationUtils::FLAG_SYNC_DECODE_IMAGES) {
     flags |= nsLayoutUtils::PAINT_SYNC_DECODE_IMAGES;
   }
-  nsLayoutUtils::PaintFrame(&context, mFrame,
+  nsLayoutUtils::PaintFrame(context, mFrame,
                             dirty, NS_RGBA(0, 0, 0, 0),
                             flags);
 
   aContext->Restore();
 
   mFrame->RemoveStateBits(NS_FRAME_DRAWING_AS_PAINTSERVER);
 
   return true;
--- a/layout/svg/nsSVGMaskFrame.cpp
+++ b/layout/svg/nsSVGMaskFrame.cpp
@@ -221,35 +221,35 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsRende
   // 'image'. However, we need to set the same matrix on the temporary context
   // and pattern that we create below as is currently set on 'gfx'.
   // Unfortunately, any device offset set by SetDeviceOffset() is affected by
   // the transform passed to the SetMatrix() calls, so to avoid that we account
   // for the device offset in the transform rather than use SetDeviceOffset().
   gfxMatrix matrix =
     gfx->CurrentMatrix() * gfxMatrix().Translate(-clipExtents.TopLeft());
 
-  nsRenderingContext tmpCtx;
-  tmpCtx.Init(this->PresContext()->DeviceContext(), image);
-  tmpCtx.ThebesContext()->SetMatrix(matrix);
+  nsRefPtr<nsRenderingContext> tmpCtx(new nsRenderingContext);
+  tmpCtx->Init(this->PresContext()->DeviceContext(), image);
+  tmpCtx->ThebesContext()->SetMatrix(matrix);
 
   mMaskParent = aParent;
   if (mMaskParentMatrix) {
     *mMaskParentMatrix = aMatrix;
   } else {
     mMaskParentMatrix = new gfxMatrix(aMatrix);
   }
 
   for (nsIFrame* kid = mFrames.FirstChild(); kid;
        kid = kid->GetNextSibling()) {
     // The CTM of each frame referencing us can be different
     nsISVGChildFrame* SVGFrame = do_QueryFrame(kid);
     if (SVGFrame) {
       SVGFrame->NotifySVGChanged(nsISVGChildFrame::TRANSFORM_CHANGED);
     }
-    nsSVGUtils::PaintFrameWithEffects(&tmpCtx, nullptr, kid);
+    nsSVGUtils::PaintFrameWithEffects(tmpCtx, nullptr, kid);
   }
 
   uint8_t *data   = image->Data();
   int32_t  stride = image->Stride();
   nsIntRect rect(0, 0, surfaceSize.width, surfaceSize.height);
 
   if (StyleSVGReset()->mMaskType == NS_STYLE_MASK_TYPE_LUMINANCE) {
     if (StyleSVG()->mColorInterpolation ==
--- a/layout/svg/nsSVGPatternFrame.cpp
+++ b/layout/svg/nsSVGPatternFrame.cpp
@@ -367,19 +367,19 @@ nsSVGPatternFrame::PaintPattern(gfxASurf
   }
 
   nsRefPtr<gfxASurface> tmpSurface =
     gfxPlatform::GetPlatform()->CreateOffscreenSurface(surfaceSize,
                                                        gfxContentType::COLOR_ALPHA);
   if (!tmpSurface || tmpSurface->CairoStatus())
     return NS_ERROR_FAILURE;
 
-  nsRenderingContext context;
-  context.Init(aSource->PresContext()->DeviceContext(), tmpSurface);
-  gfxContext* gfx = context.ThebesContext();
+  nsRefPtr<nsRenderingContext> context(new nsRenderingContext());
+  context->Init(aSource->PresContext()->DeviceContext(), tmpSurface);
+  gfxContext* gfx = context->ThebesContext();
 
   // Fill with transparent black
   gfx->SetOperator(gfxContext::OPERATOR_CLEAR);
   gfx->Paint();
   gfx->SetOperator(gfxContext::OPERATOR_OVER);
 
   if (aGraphicOpacity != 1.0f) {
     gfx->Save();
@@ -401,17 +401,17 @@ nsSVGPatternFrame::PaintPattern(gfxASurf
     patternFrame->AddStateBits(NS_FRAME_DRAWING_AS_PAINTSERVER);
     for (nsIFrame* kid = firstKid; kid;
          kid = kid->GetNextSibling()) {
       // The CTM of each frame referencing us can be different
       nsISVGChildFrame* SVGFrame = do_QueryFrame(kid);
       if (SVGFrame) {
         SVGFrame->NotifySVGChanged(nsISVGChildFrame::TRANSFORM_CHANGED);
       }
-      nsSVGUtils::PaintFrameWithEffects(&context, nullptr, kid);
+      nsSVGUtils::PaintFrameWithEffects(context, nullptr, kid);
     }
     patternFrame->RemoveStateBits(NS_FRAME_DRAWING_AS_PAINTSERVER);
   }
 
   patternFrame->mSource = nullptr;
 
   if (aGraphicOpacity != 1.0f) {
     gfx->PopGroupToSource();
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -1466,21 +1466,22 @@ nsSVGUtils::PaintSVGGlyph(Element* aElem
                           DrawMode aDrawMode,
                           gfxTextContextPaint* aContextPaint)
 {
   nsIFrame* frame = aElement->GetPrimaryFrame();
   nsISVGChildFrame* svgFrame = do_QueryFrame(frame);
   if (!svgFrame) {
     return false;
   }
-  nsRenderingContext context;
-  context.Init(frame->PresContext()->DeviceContext(), aContext);
-  context.AddUserData(&gfxTextContextPaint::sUserDataKey, aContextPaint, nullptr);
+  nsRefPtr<nsRenderingContext> context(new nsRenderingContext());
+  context->Init(frame->PresContext()->DeviceContext(), aContext);
+  context->AddUserData(&gfxTextContextPaint::sUserDataKey, aContextPaint,
+                       nullptr);
   svgFrame->NotifySVGChanged(nsISVGChildFrame::TRANSFORM_CHANGED);
-  nsresult rv = svgFrame->PaintSVG(&context, nullptr, frame);
+  nsresult rv = svgFrame->PaintSVG(context, nullptr, frame);
   return NS_SUCCEEDED(rv);
 }
 
 bool
 nsSVGUtils::GetSVGGlyphExtents(Element* aElement,
                                const gfxMatrix& aSVGToAppSpace,
                                gfxRect* aResult)
 {
--- a/media/webrtc/signaling/src/sipcc/core/sdp/sdp_token.c
+++ b/media/webrtc/signaling/src/sipcc/core/sdp/sdp_token.c
@@ -1573,17 +1573,17 @@ sdp_result_e sdp_build_media (sdp_t *sdp
                 flex_string_sprintf(fs, " %s",
                                  sdp_get_payload_name((sdp_payload_e)mca_p->payload_type[i]));
             } else {
                 flex_string_sprintf(fs, " %u", mca_p->payload_type[i]);
             }
         }
     } else {
         /* Add port to SDP if transport is DTLS/SCTP */
-    	flex_string_sprintf(fs, " %u ", (u32)mca_p->sctpport);
+    	flex_string_sprintf(fs, " %u", (u32)mca_p->sctpport);
     }
 
     flex_string_sprintf(fs, "\r\n");
 
     if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
         SDP_PRINT("%s Built m= media line", sdp_p->debug_str);
     }
     return (SDP_SUCCESS);
--- a/media/webrtc/signaling/test/signaling_unittests.cpp
+++ b/media/webrtc/signaling/test/signaling_unittests.cpp
@@ -2812,17 +2812,17 @@ TEST_F(SignalingTest, missingUfrag)
     "a=rtpmap:120 VP8/90000\r\n"
     "a=recvonly\r\n"
     "a=candidate:0 1 UDP 2113601791 192.168.178.20 49929 typ host\r\n"
     "a=candidate:1 1 UDP 1694236671 77.9.79.167 49929 typ srflx raddr "
       "192.168.178.20 rport 49929\r\n"
     "a=candidate:0 2 UDP 2113601790 192.168.178.20 50769 typ host\r\n"
     "a=candidate:1 2 UDP 1694236670 77.9.79.167 50769 typ srflx raddr "
       "192.168.178.20 rport 50769\r\n"
-    "m=application 54054 DTLS/SCTP 5000 \r\n"
+    "m=application 54054 DTLS/SCTP 5000\r\n"
     "c=IN IP4 77.9.79.167\r\n"
     "a=fmtp:HuRUu]Dtcl\\zM,7(OmEU%O$gU]x/z\tD protocol=webrtc-datachannel;"
       "streams=16\r\n"
     "a=sendrecv\r\n";
 
   // Need to create an offer, since that's currently required by our
   // FSM. This may change in the future.
   a1_->CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV);
--- a/netwerk/base/src/NetworkActivityMonitor.cpp
+++ b/netwerk/base/src/NetworkActivityMonitor.cpp
@@ -146,47 +146,54 @@ nsNetMon_AcceptRead(PRFileDesc *listenSo
   if (ret > 0)
     NetworkActivityMonitor::DataInOut(NetworkActivityMonitor::kDownload);
   return ret;
 }
 
 
 class NotifyNetworkActivity : public nsRunnable {
 public:
-  NotifyNetworkActivity(nsIObserverService* aObs,
-                        NetworkActivityMonitor::Direction aDirection)
-    : mObs(aObs)
-    , mDirection(aDirection)
+  NotifyNetworkActivity(NetworkActivityMonitor::Direction aDirection)
+    : mDirection(aDirection)
   {}
   NS_IMETHOD Run()
   {
-    mObs->NotifyObservers(nullptr,
-                          mDirection == NetworkActivityMonitor::kUpload
-                            ? NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC
-                            : NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC,
-                          nullptr);
+    MOZ_ASSERT(NS_IsMainThread());
+
+    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+    if (!obs)
+      return NS_ERROR_FAILURE;
+
+    obs->NotifyObservers(nullptr,
+                         mDirection == NetworkActivityMonitor::kUpload
+                           ? NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC
+                           : NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC,
+                         nullptr);
     return NS_OK;
   }
 private:
   nsCOMPtr<nsIObserverService>      mObs;
   NetworkActivityMonitor::Direction mDirection;
 };
 
 NetworkActivityMonitor * NetworkActivityMonitor::gInstance = nullptr;
 
 NetworkActivityMonitor::NetworkActivityMonitor()
   : mLayerIdentity(PR_INVALID_IO_LAYER)
   , mBlipInterval(PR_INTERVAL_NO_TIMEOUT)
 {
+  MOZ_COUNT_CTOR(NetworkActivityMonitor);
+
   NS_ASSERTION(gInstance==nullptr,
                "multiple NetworkActivityMonitor instances!");
 }
 
 NetworkActivityMonitor::~NetworkActivityMonitor()
 {
+  MOZ_COUNT_DTOR(NetworkActivityMonitor);
   gInstance = nullptr;
 }
 
 nsresult
 NetworkActivityMonitor::Init(int32_t blipInterval)
 {
   nsresult rv;
 
@@ -224,20 +231,16 @@ NetworkActivityMonitor::Init_Internal(in
   mLayerMethods.write      = nsNetMon_Write;
   mLayerMethods.writev     = nsNetMon_Writev;
   mLayerMethods.recv       = nsNetMon_Recv;
   mLayerMethods.send       = nsNetMon_Send;
   mLayerMethods.recvfrom   = nsNetMon_RecvFrom;
   mLayerMethods.sendto     = nsNetMon_SendTo;
   mLayerMethods.acceptread = nsNetMon_AcceptRead;
 
-  mObserverService = mozilla::services::GetObserverService();
-  if (!mObserverService)
-    return NS_ERROR_FAILURE;
-
   mBlipInterval = PR_MillisecondsToInterval(blipInterval);
   // Set the last notification times to time that has just expired, so any
   // activity even right now will trigger notification.
   mLastNotificationTime[kUpload] = PR_IntervalNow() - mBlipInterval;
   mLastNotificationTime[kDownload] = mLastNotificationTime[kUpload];
 
   return NS_OK;
 }
@@ -282,12 +285,11 @@ NetworkActivityMonitor::DataInOut(Direct
   }
 
   return NS_OK;
 }
 
 void
 NetworkActivityMonitor::PostNotification(Direction direction)
 {
-  nsRefPtr<nsIRunnable> ev = new NotifyNetworkActivity(mObserverService,
-                                                       direction);
+  nsRefPtr<nsIRunnable> ev = new NotifyNetworkActivity(direction);
   NS_DispatchToMainThread(ev);
 }
--- a/netwerk/base/src/NetworkActivityMonitor.h
+++ b/netwerk/base/src/NetworkActivityMonitor.h
@@ -2,22 +2,21 @@
  *
  * 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 NetworkActivityMonitor_h___
 #define NetworkActivityMonitor_h___
 
-#include "nsCOMPtr.h"
+#include <stdint.h>
+#include "nscore.h"
 #include "prio.h"
 #include "prinrval.h"
 
-class nsIObserverService;
-
 namespace mozilla { namespace net {
 
 class NetworkActivityMonitor
 {
 public:
   enum Direction {
     kUpload   = 0,
     kDownload = 1
@@ -36,14 +35,13 @@ private:
   nsresult Init_Internal(int32_t blipInterval);
   void PostNotification(Direction direction);
 
   static NetworkActivityMonitor * gInstance;
   PRDescIdentity                  mLayerIdentity;
   PRIOMethods                     mLayerMethods;
   PRIntervalTime                  mBlipInterval;
   PRIntervalTime                  mLastNotificationTime[2];
-  nsCOMPtr<nsIObserverService>    mObserverService;
 };
 
 }} // namespace mozilla::net
 
 #endif /* NetworkActivityMonitor_h___ */
--- a/security/manager/ssl/src/SharedCertVerifier.h
+++ b/security/manager/ssl/src/SharedCertVerifier.h
@@ -6,32 +6,34 @@
 #define mozilla_psm__SharedCertVerifier_h
 
 #include "certt.h"
 #include "CertVerifier.h"
 #include "mozilla/RefPtr.h"
 
 namespace mozilla { namespace psm {
 
-class SharedCertVerifier : public mozilla::psm::CertVerifier,
-                           public mozilla::AtomicRefCounted<SharedCertVerifier>
+class SharedCertVerifier : public mozilla::psm::CertVerifier
 {
+protected:
+  ~SharedCertVerifier();
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(SharedCertVerifier)
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedCertVerifier)
+
   SharedCertVerifier(implementation_config ic,
 #ifndef NSS_NO_LIBPKIX
                      missing_cert_download_config ac, crl_download_config cdc,
 #endif
                      ocsp_download_config odc, ocsp_strict_config osc,
                      ocsp_get_config ogc)
     : mozilla::psm::CertVerifier(ic,
 #ifndef NSS_NO_LIBPKIX
                                  ac, cdc,
 #endif
                                  odc, osc, ogc)
   {
   }
-  ~SharedCertVerifier();
 };
 
 } } // namespace mozilla::psm
 
 #endif // mozilla_psm__SharedCertVerifier_h
--- a/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.cpp
+++ b/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.cpp
@@ -134,13 +134,17 @@ GetOCSPResponseForType(OCSPResponseType 
 
   SECItem* response = CreateEncodedOCSPResponse(context);
   if (!response) {
     PrintPRError("CreateEncodedOCSPResponse failed");
     return nullptr;
   }
 
   SECItemArray* arr = SECITEM_AllocArray(aArena, nullptr, 1);
-  arr->items[0].data = response ? response->data : nullptr;
-  arr->items[0].len = response ? response->len : 0;
+  if (!arr) {
+    PrintPRError("SECITEM_AllocArray failed");
+    return nullptr;
+  }
+  arr->items[0].data = response->data;
+  arr->items[0].len = response->len;
 
   return arr;
 }
--- a/testing/xpcshell/head.js
+++ b/testing/xpcshell/head.js
@@ -14,16 +14,18 @@ var _quit = false;
 var _passed = true;
 var _tests_pending = 0;
 var _passedChecks = 0, _falsePassedChecks = 0;
 var _todoChecks = 0;
 var _cleanupFunctions = [];
 var _pendingTimers = [];
 var _profileInitialized = false;
 
+let _Promise = Components.utils.import("resource://gre/modules/Promise.jsm", this).Promise;
+
 let _log = function (action, params) {
   if (typeof _XPCSHELL_PROCESS != "undefined") {
     params.process = _XPCSHELL_PROCESS;
   }
   params.action = action;
   params._time = Date.now();
   dump("\n" + JSON.stringify(params) + "\n");
 }
@@ -175,17 +177,17 @@ function _do_main() {
 
   while (thr.hasPendingEvents())
     thr.processNextEvent(true);
 }
 
 function _do_quit() {
   _log("test_info",
        {_message: "TEST-INFO | (xpcshell/head.js) | exiting test\n"});
-
+  _Promise.Debugging.flushUncaughtErrors();
   _quit = true;
 }
 
 function _format_exception_stack(stack) {
   if (typeof stack == "object" && stack.caller) {
     let frame = stack;
     let strStack = "";
     while (frame != null) {
@@ -343,16 +345,25 @@ function _register_protocol_handlers() {
 
 function _execute_test() {
   _register_protocol_handlers();
 
   // Override idle service by default.
   // Call do_get_idle() to restore the factory and get the service.
   _fakeIdleService.activate();
 
+  _Promise.Debugging.clearUncaughtErrorObservers();
+  _Promise.Debugging.addUncaughtErrorObserver(function observer({message, date, fileName, stack, lineNumber}) {
+    let text = "Once bug 976205 has landed, THIS ERROR WILL CAUSE A TEST FAILURE.\n" +
+        " A promise chain failed to handle a rejection: " +
+        message + " - rejection date: " + date;
+    _log_message_with_stack("test_known_fail",
+                            text, stack, fileName);
+  });
+
   // _HEAD_FILES is dynamically defined by <runxpcshelltests.py>.
   _load_files(_HEAD_FILES);
   // _TEST_FILE is dynamically defined by <runxpcshelltests.py>.
   _load_files(_TEST_FILE);
 
   // Support a common assertion library, Assert.jsm.
   let Assert = Components.utils.import("resource://testing-common/Assert.jsm", null).Assert;
   // Pass a custom report function for xpcshell-test style reporting.
@@ -1423,20 +1434,22 @@ let _gTestIndex = 0; // The index of the
 let _gTaskRunning = false;
 function run_next_test()
 {
   if (_gTaskRunning) {
     throw new Error("run_next_test() called from an add_task() test function. " +
                     "run_next_test() should not be called from inside add_task() " +
                     "under any circumstances!");
   }
-
+ 
   function _run_next_test()
   {
     if (_gTestIndex < _gTests.length) {
+      // Flush uncaught errors as early and often as possible.
+      _Promise.Debugging.flushUncaughtErrors();
       let _isTask;
       [_isTask, _gRunningTest] = _gTests[_gTestIndex++];
       print("TEST-INFO | " + _TEST_FILE + " | Starting " + _gRunningTest.name);
       do_test_pending(_gRunningTest.name);
 
       if (_isTask) {
         _gTaskRunning = true;
         _Task.spawn(_gRunningTest).then(
--- a/toolkit/content/widgets/findbar.xml
+++ b/toolkit/content/widgets/findbar.xml
@@ -169,23 +169,16 @@
                            xbl:inherits="accesskey=findpreviousaccesskey"/>
         <xul:toolbarbutton anonid="find-next"
                            class="findbar-find-next tabbable"
                            tooltiptext="&next.tooltip;"
                            oncommand="onFindAgainCommand(false);"
                            disabled="true"
                            xbl:inherits="accesskey=findnextaccesskey"/>
       </xul:hbox>
-      <xul:image anonid="find-status-icon" class="findbar-find-fast find-status-icon"/>
-      <xul:description anonid="find-status"
-                       control="findbar-textbox"
-                       class="findbar-find-fast findbar-find-status">
-      <!-- Do not use value, first child is used because it provides a11y with text change events -->
-      </xul:description>
-      <xul:spacer flex="1"/>
       <xul:toolbarbutton anonid="highlight"
                          class="findbar-highlight tabbable"
                          label="&highlightAll.label;"
                          accesskey="&highlightAll.accesskey;"
                          tooltiptext="&highlightAll.tooltiptext;"
                          oncommand="toggleHighlight(this.checked);"
                          type="checkbox"
                          xbl:inherits="accesskey=highlightaccesskey"/>
@@ -193,16 +186,22 @@
                          class="findbar-case-sensitive tabbable"
                          label="&caseSensitive.label;"
                          accesskey="&caseSensitive.accesskey;"
                          tooltiptext="&caseSensitive.tooltiptext;"
                          oncommand="_setCaseSensitivity(this.checked);"
                          type="checkbox"
                          xbl:inherits="accesskey=matchcaseaccesskey"/>
       <xul:label anonid="match-case-status" class="findbar-find-fast"/>
+      <xul:image anonid="find-status-icon" class="findbar-find-fast find-status-icon"/>
+      <xul:description anonid="find-status"
+                       control="findbar-textbox"
+                       class="findbar-find-fast findbar-find-status">
+      <!-- Do not use value, first child is used because it provides a11y with text change events -->
+      </xul:description>
     </xul:hbox>
     <xul:toolbarbutton anonid="find-closebutton"
                        class="findbar-closebutton close-icon"
                        tooltiptext="&findCloseButton.tooltip;"
                        oncommand="close();"/>
     </content>
 
     <implementation implements="nsIDOMEventListener, nsIEditActionListener">
--- a/toolkit/modules/Promise-backend.js
+++ b/toolkit/modules/Promise-backend.js
@@ -73,18 +73,37 @@ const N_WITNESS = Name("witness");
 // In this snippet, the error is reported both by p1 and by p2.
 //
 
 XPCOMUtils.defineLazyServiceGetter(this, "FinalizationWitnessService",
                                    "@mozilla.org/toolkit/finalizationwitness;1",
                                    "nsIFinalizationWitnessService");
 
 let PendingErrors = {
+  // An internal counter, used to generate unique id.
   _counter: 0,
+  // Functions registered to be notified when a pending error
+  // is reported as uncaught.
+  _observers: new Set(),
   _map: new Map(),
+
+  /**
+   * Initialize PendingErrors
+   */
+  init: function() {
+    Services.obs.addObserver(function observe(aSubject, aTopic, aValue) {
+      PendingErrors.report(aValue);
+    }, "promise-finalization-witness", false);
+  },
+
+  /**
+   * Register an error as tracked.
+   *
+   * @return The unique identifier of the error.
+   */
   register: function(error) {
     let id = "pending-error-" + (this._counter++);
     //
     // At this stage, ideally, we would like to store the error itself
     // and delay any treatment until we are certain that we will need
     // to report that error. However, in the (unlikely but possible)
     // case the error holds a reference to the promise itself, doing so
     // would prevent the promise from being garbabe-collected, which
@@ -161,56 +180,112 @@ let PendingErrors = {
         }
       }
     } catch (ex) {
       // Ignore value
     }
     this._map.set(id, value);
     return id;
   },
-  extract: function(id) {
+
+  /**
+   * Notify all observers that a pending error is now uncaught.
+   *
+   * @param id The identifier of the pending error, as returned by
+   * |register|.
+   */
+  report: function(id) {
     let value = this._map.get(id);
+    if (!value) {
+      return; // The error has already been reported
+    }
     this._map.delete(id);
-    return value;
+    for (let obs of this._observers.values()) {
+      obs(value);
+    }
   },
+
+  /**
+   * Mark all pending errors are uncaught, notify the observers.
+   */
+  flush: function() {
+    // Since we are going to modify the map while walking it,
+    // let's copying the keys first.
+    let keys = [key for (key of this._map.keys())];
+    for (let key of keys) {
+      this.report(key);
+    }
+  },
+
+  /**
+   * Stop tracking an error, as this error has been caught,
+   * eventually.
+   */
   unregister: function(id) {
     this._map.delete(id);
+  },
+
+  /**
+   * Add an observer notified when an error is reported as uncaught.
+   *
+   * @param {function} observer A function notified when an error is
+   * reported as uncaught. Its arguments are
+   *   {message, date, fileName, stack, lineNumber}
+   * All arguments are optional.
+   */
+  addObserver: function(observer) {
+    this._observers.add(observer);
+  },
+
+  /**
+   * Remove an observer added with addObserver
+   */
+  removeObserver: function(observer) {
+    this._observers.delete(observer);
+  },
+
+  /**
+   * Remove all the observers added with addObserver
+   */
+  removeAllObservers: function() {
+    this._observers.clear();
   }
 };
+PendingErrors.init();
 
-// Actually print the finalization warning.
-Services.obs.addObserver(function observe(aSubject, aTopic, aValue) {
-  let error = PendingErrors.extract(aValue);
-  let {message, date, fileName, stack, lineNumber} = error;
+// Default mechanism for displaying errors
+PendingErrors.addObserver(function(details) {
   let error = Cc['@mozilla.org/scripterror;1'].createInstance(Ci.nsIScriptError);
   if (!error || !Services.console) {
     // Too late during shutdown to use the nsIConsole
     dump("*************************\n");
     dump("A promise chain failed to handle a rejection\n\n");
-    dump("On: " + date + "\n");
-    dump("Full message: " + message + "\n");
+    dump("On: " + details.date + "\n");
+    dump("Full message: " + details.message + "\n");
     dump("See https://developer.mozilla.org/Mozilla/JavaScript_code_modules/Promise.jsm/Promise\n");
-    dump("Full stack: " + (stack||"not available") + "\n");
+    dump("Full stack: " + (details.stack||"not available") + "\n");
     dump("*************************\n");
     return;
   }
-  if (stack) {
-    message += "\nFull Stack: " + stack;
+  let message = details.message;
+  if (details.stack) {
+    message += "\nFull Stack: " + details.stack;
   }
   error.init(
              /*message*/"A promise chain failed to handle a rejection.\n\n" +
-             "Date: " + date + "\nFull Message: " + message,
-             /*sourceName*/ fileName,
-             /*sourceLine*/ lineNumber?("" + lineNumber):0,
-             /*lineNumber*/ lineNumber || 0,
+             "Date: " + details.date + "\nFull Message: " + details.message,
+             /*sourceName*/ details.fileName,
+             /*sourceLine*/ details.lineNumber?("" + details.lineNumber):0,
+             /*lineNumber*/ details.lineNumber || 0,
              /*columnNumber*/ 0,
              /*flags*/ Ci.nsIScriptError.errorFlag,
              /*category*/ "chrome javascript");
   Services.console.logMessage(error);
-}, "promise-finalization-witness", false);
+});
+
 
 ///////// Additional warnings for developers
 //
 // The following error types are considered programmer errors, which should be
 // reported (possibly redundantly) so as to let programmers fix their code.
 const ERRORS_TO_REPORT = ["EvalError", "RangeError", "ReferenceError", "TypeError"];
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -491,16 +566,56 @@ Promise.race = function (aValues)
 
   return new Promise((resolve, reject) => {
     for (let value of aValues) {
       Promise.resolve(value).then(resolve, reject);
     }
   });
 };
 
+Promise.Debugging = {
+  /**
+   * Add an observer notified when an error is reported as uncaught.
+   *
+   * @param {function} observer A function notified when an error is
+   * reported as uncaught. Its arguments are
+   *   {message, date, fileName, stack, lineNumber}
+   * All arguments are optional.
+   */
+  addUncaughtErrorObserver: function(observer) {
+    PendingErrors.addObserver(observer);
+  },
+
+  /**
+   * Remove an observer added with addUncaughtErrorObserver
+   *
+   * @param {function} An observer registered with
+   * addUncaughtErrorObserver.
+   */
+  removeUncaughtErrorObserver: function(observer) {
+    PendingErrors.removeObserver(observer);
+  },
+
+  /**
+   * Remove all the observers added with addUncaughtErrorObserver
+   */
+  clearUncaughtErrorObservers: function() {
+    PendingErrors.removeAllObservers();
+  },
+
+  /**
+   * Force all pending errors to be reported immediately as uncaught.
+   * Note that this may cause some false positives.
+   */
+  flushUncaughtErrors: function() {
+    PendingErrors.flush();
+  },
+};
+Object.freeze(Promise.Debugging);
+
 Object.freeze(Promise);
 
 ////////////////////////////////////////////////////////////////////////////////
 //// PromiseWalker
 
 /**
  * This singleton object invokes the handlers registered on resolved and
  * rejected promises, ensuring that processing is not recursive and is done in
--- a/toolkit/modules/tests/xpcshell/test_Promise.js
+++ b/toolkit/modules/tests/xpcshell/test_Promise.js
@@ -1,16 +1,20 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 "use strict";
 
 Components.utils.import("resource://gre/modules/Promise.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
 Components.utils.import("resource://gre/modules/Task.jsm");
 
+// Deactivate the standard xpcshell observer, as it turns uncaught
+// rejections into failures, which we don't want here.
+Promise.Debugging.clearUncaughtErrorObservers();
+
 ////////////////////////////////////////////////////////////////////////////////
 //// Test runner
 
 let run_promise_tests = function run_promise_tests(tests, cb) {
   let loop = function loop(index) {
     if (index >= tests.length) {
       if (cb) {
         cb.call();
@@ -954,38 +958,36 @@ tests.push(
 function wait_for_uncaught(aMustAppear, aTimeout = undefined) {
   let remaining = new Set();
   for (let k of aMustAppear) {
     remaining.add(k);
   }
   let deferred = Promise.defer();
   let print = do_print;
   let execute_soon = do_execute_soon;
-  let observer = function(aMessage) {
-    execute_soon(function() {
-      let message = aMessage.message;
-      print("Observing " + message);
-      for (let expected of remaining) {
-        if (message.indexOf(expected) != -1) {
-          print("I found " + expected);
-          remaining.delete(expected);
-        }
+  let observer = function({message, stack}) {
+    let data = message + stack;
+    print("Observing " + message + ", looking for " + aMustAppear.join(", "));
+    for (let expected of remaining) {
+      if (data.indexOf(expected) != -1) {
+        print("I found " + expected);
+        remaining.delete(expected);
       }
       if (remaining.size == 0 && observer) {
-        Services.console.unregisterListener(observer);
+        Promise.Debugging.removeUncaughtErrorObserver(observer);
         observer = null;
         deferred.resolve();
       }
-    });
+    }
   };
-  Services.console.registerListener(observer);
+  Promise.Debugging.addUncaughtErrorObserver(observer);
   if (aTimeout) {
     do_timeout(aTimeout, function timeout() {
       if (observer) {
-        Services.console.unregisterListener(observer);
+        Promise.Debugging.removeUncaughtErrorObserver(observer);
         observer = null;
       }
       deferred.reject(new Error("Timeout"));
     });
   }
   return deferred.promise;
 }
 
@@ -1050,16 +1052,17 @@ function wait_for_uncaught(aMustAppear, 
           //
           // Unfortunately, we might still have intermittent failures,
           // materialized as timeouts.
           //
           for (let i = 0; i < 100; ++i) {
             Promise.reject(error);
           }
         })();
+        do_print("Posted all rejections");
         Components.utils.forceGC();
         Components.utils.forceCC();
         Components.utils.forceShrinkingGC();
         return promise;
       }));
   }
 })();
 
--- a/widget/cocoa/nsClipboard.mm
+++ b/widget/cocoa/nsClipboard.mm
@@ -461,25 +461,19 @@ nsClipboard::PasteboardDictFromTransfera
       ptrPrimitive->GetData(getter_AddRefs(primitiveData));
 
       nsCOMPtr<imgIContainer> image(do_QueryInterface(primitiveData));
       if (!image) {
         NS_WARNING("Image isn't an imgIContainer in transferable");
         continue;
       }
 
-      nsRefPtr<gfxASurface> thebesSurface =
+      RefPtr<SourceSurface> surface =
         image->GetFrame(imgIContainer::FRAME_CURRENT,
                         imgIContainer::FLAG_SYNC_DECODE);
-      if (!thebesSurface) {
-        continue;
-      }
-      RefPtr<SourceSurface> surface =
-        gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(
-          gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget(), thebesSurface);
       if (!surface) {
         continue;
       }
       CGImageRef imageRef = NULL;
       nsresult rv = nsCocoaUtils::CreateCGImageFromSurface(surface, &imageRef);
       if (NS_FAILED(rv) || !imageRef) {
         continue;
       }
--- a/widget/cocoa/nsCocoaUtils.mm
+++ b/widget/cocoa/nsCocoaUtils.mm
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 20; 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 "gfxImageSurface.h"
 #include "gfxPlatform.h"
+#include "gfxUtils.h"
 #include "nsCocoaUtils.h"
 #include "nsChildView.h"
 #include "nsMenuBarX.h"
 #include "nsCocoaWindow.h"
 #include "nsCOMPtr.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIAppShellService.h"
 #include "nsIXULWindow.h"
@@ -21,17 +22,22 @@
 #include "mozilla/gfx/2D.h"
 #include "mozilla/MiscEvents.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/TextEvents.h"
 
 using namespace mozilla;
 using namespace mozilla::widget;
 
+using mozilla::gfx::BackendType;
 using mozilla::gfx::DataSourceSurface;
+using mozilla::gfx::DrawTarget;
+using mozilla::gfx::Factory;
+using mozilla::gfx::IntPoint;
+using mozilla::gfx::IntRect;
 using mozilla::gfx::IntSize;
 using mozilla::gfx::SurfaceFormat;
 using mozilla::gfx::SourceSurface;
 
 static float
 MenuBarScreenHeight()
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
@@ -273,20 +279,29 @@ void data_ss_release_callback(void *aDat
     static_cast<DataSourceSurface*>(aDataSourceSurface)->Unmap();
     static_cast<DataSourceSurface*>(aDataSourceSurface)->Release();
   }
 }
 
 nsresult nsCocoaUtils::CreateCGImageFromSurface(SourceSurface* aSurface,
                                                 CGImageRef* aResult)
 {
-  RefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface();
+  RefPtr<DataSourceSurface> dataSurface;
 
-  MOZ_ASSERT(dataSurface->GetFormat() ==  SurfaceFormat::B8G8R8A8,
-             "We assume B8G8R8A8 when calling CGImageCreate");
+  if (aSurface->GetFormat() ==  SurfaceFormat::B8G8R8A8) {
+    dataSurface = aSurface->GetDataSurface();
+  } else {
+    // CGImageCreate only supports 16- and 32-bit bit-depth
+    // Convert format to SurfaceFormat::B8G8R8A8
+    dataSurface = gfxUtils::
+      CopySurfaceToDataSourceSurfaceWithFormat(aSurface,
+                                               SurfaceFormat::B8G8R8A8);
+  }
+
+  NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
 
   int32_t width = dataSurface->GetSize().width;
   int32_t height = dataSurface->GetSize().height;
   if (height < 1 || width < 1) {
     return NS_ERROR_FAILURE;
   }
 
   DataSourceSurface::MappedSurface map;
@@ -396,27 +411,17 @@ nsresult nsCocoaUtils::CreateNSImageFrom
       gfxRect(0.0f, 0.0f, scaledWidth, scaledHeight),
       nsIntRect(0, 0, width, height),
       nsIntSize(scaledWidth, scaledHeight),
       nullptr, aWhichFrame, imgIContainer::FLAG_SYNC_DECODE);
 
     surface =
       gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, frame);
   } else {
-    nsRefPtr<gfxASurface> thebesSurface =
-      aImage->GetFrame(aWhichFrame, imgIContainer::FLAG_SYNC_DECODE);
-    NS_ENSURE_TRUE(thebesSurface, NS_ERROR_FAILURE);
-
-    nsRefPtr<gfxImageSurface> thebesImageSurface =
-      thebesSurface->GetAsReadableARGB32ImageSurface();
-    NS_ENSURE_TRUE(thebesImageSurface, NS_ERROR_FAILURE);
-
-    surface =
-      gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr,
-                                                             thebesImageSurface);
+    surface = aImage->GetFrame(aWhichFrame, imgIContainer::FLAG_SYNC_DECODE);
   }
 
   NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
 
   CGImageRef imageRef = NULL;
   nsresult rv = nsCocoaUtils::CreateCGImageFromSurface(surface, &imageRef);
   if (NS_FAILED(rv) || !imageRef) {
     return NS_ERROR_FAILURE;
--- a/widget/cocoa/nsMenuItemIconX.mm
+++ b/widget/cocoa/nsMenuItemIconX.mm
@@ -382,28 +382,24 @@ nsMenuItemIconX::OnStopFrame(imgIRequest
        mImageRegionRect.YMost() > origHeight)) {
     [mNativeMenuItem setImage:nil];
     return NS_ERROR_FAILURE;
   }
 
   if (mImageRegionRect.IsEmpty()) {
     mImageRegionRect.SetRect(0, 0, origWidth, origHeight);
   }
-  
-  nsRefPtr<gfxASurface> thebesSurface =
+
+  RefPtr<SourceSurface> surface =
     imageContainer->GetFrame(imgIContainer::FRAME_CURRENT,
                              imgIContainer::FLAG_NONE);
-  if (!thebesSurface) {
+  if (!surface) {
     [mNativeMenuItem setImage:nil];
     return NS_ERROR_FAILURE;
   }
-  RefPtr<SourceSurface> surface =
-    gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr,
-                                                           thebesSurface);
-  NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
 
   CGImageRef origImage = NULL;
   nsresult rv = nsCocoaUtils::CreateCGImageFromSurface(surface, &origImage);
   if (NS_FAILED(rv) || !origImage) {
     [mNativeMenuItem setImage:nil];
     return NS_ERROR_FAILURE;
   }
 
--- a/widget/gtk/nsImageToPixbuf.cpp
+++ b/widget/gtk/nsImageToPixbuf.cpp
@@ -38,33 +38,28 @@ NS_IMETHODIMP_(GdkPixbuf*)
 nsImageToPixbuf::ConvertImageToPixbuf(imgIContainer* aImage)
 {
     return ImageToPixbuf(aImage);
 }
 
 GdkPixbuf*
 nsImageToPixbuf::ImageToPixbuf(imgIContainer* aImage)
 {
-    nsRefPtr<gfxASurface> thebesSurface =
+    RefPtr<SourceSurface> surface =
       aImage->GetFrame(imgIContainer::FRAME_CURRENT,
                        imgIContainer::FLAG_SYNC_DECODE);
 
     // If the last call failed, it was probably because our call stack originates
     // 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 (!thebesSurface)
-      thebesSurface = aImage->GetFrame(imgIContainer::FRAME_CURRENT,
-                                       imgIContainer::FLAG_NONE);
+    if (!surface)
+      surface = aImage->GetFrame(imgIContainer::FRAME_CURRENT,
+                                 imgIContainer::FLAG_NONE);
 
-    NS_ENSURE_TRUE(thebesSurface, nullptr);
-
-    RefPtr<SourceSurface> surface =
-      gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr,
-                                                             thebesSurface);
     NS_ENSURE_TRUE(surface, nullptr);
 
     return SourceSurfaceToPixbuf(surface,
                                  surface->GetSize().width,
                                  surface->GetSize().height);
 }
 
 GdkPixbuf*
--- a/widget/qt/nsClipboard.cpp
+++ b/widget/qt/nsClipboard.cpp
@@ -174,25 +174,19 @@ nsClipboard::SetNativeClipboardData( nsI
                     continue;
 
                 nsCOMPtr<nsISupports> primitiveData;
                 ptrPrimitive->GetData(getter_AddRefs(primitiveData));
                 nsCOMPtr<imgIContainer> image(do_QueryInterface(primitiveData));
                 if (!image)  // Not getting an image for an image mime type!?
                    continue;
 
-                nsRefPtr<gfxASurface> thebesSurface =
+                RefPtr<SourceSurface> surface =
                   image->GetFrame(imgIContainer::FRAME_CURRENT,
                                   imgIContainer::FLAG_SYNC_DECODE);
-                if (!thebesSurface)
-                  continue;
-
-                RefPtr<SourceSurface> surface =
-                  gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr,
-                                                                         thebesSurface);
                 if (!surface)
                   continue;
 
                 RefPtr<DataSourceSurface> dataSurface =
                   surface->GetDataSurface();
                 if (!dataSurface)
                   continue;
 
--- a/widget/windows/WinUtils.cpp
+++ b/widget/windows/WinUtils.cpp
@@ -726,22 +726,18 @@ AsyncFaviconDataReady::OnComplete(nsIURI
   nsAutoCString mimeTypeOfInputData;
   mimeTypeOfInputData.AssignLiteral("image/vnd.microsoft.icon");
   nsCOMPtr<imgIContainer> container;
   nsCOMPtr<imgITools> imgtool = do_CreateInstance("@mozilla.org/image/tools;1");
   rv = imgtool->DecodeImageData(stream, aMimeType,
                                 getter_AddRefs(container));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsRefPtr<gfxASurface> imgFrame =
+  RefPtr<SourceSurface> surface =
     container->GetFrame(imgIContainer::FRAME_FIRST, 0);
-  NS_ENSURE_TRUE(imgFrame, NS_ERROR_FAILURE);
-
-  RefPtr<SourceSurface> surface =
-    gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, imgFrame);
   NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
 
   RefPtr<DataSourceSurface> dataSurface;
   IntSize size;
 
   if (mURLShortcut) {
     // Create a 48x48 surface and paint the icon into the central 16x16 rect.
     size.width = 48;
--- a/widget/windows/nsImageClipboard.cpp
+++ b/widget/windows/nsImageClipboard.cpp
@@ -1,17 +1,20 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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 "nsImageClipboard.h"
+
+#include "gfxUtils.h"
 #include "mozilla/gfx/2D.h"
+#include "mozilla/gfx/DataSurfaceHelpers.h"
 #include "mozilla/RefPtr.h"
 #include "nsITransferable.h"
-#include "nsImageClipboard.h"
 #include "nsGfxCIID.h"
 #include "nsMemory.h"
 #include "prmem.h"
 #include "imgIEncoder.h"
 #include "nsLiteralString.h"
 #include "nsComponentManagerUtils.h"
 
 #define BFH_LENGTH 14
@@ -115,32 +118,34 @@ nsImageToClipboard::CalcSpanLength(uint3
 // image. 
 //
 nsresult
 nsImageToClipboard::CreateFromImage ( imgIContainer* inImage, HANDLE* outBitmap )
 {
     nsresult rv;
     *outBitmap = nullptr;
 
-    nsRefPtr<gfxASurface> thebesSurface =
+    RefPtr<SourceSurface> surface =
       inImage->GetFrame(imgIContainer::FRAME_CURRENT,
                         imgIContainer::FLAG_SYNC_DECODE);
-    NS_ENSURE_TRUE(thebesSurface, NS_ERROR_FAILURE);
+    NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
 
-    nsRefPtr<gfxImageSurface> thebesImageSurface =
-      thebesSurface->GetAsReadableARGB32ImageSurface();
-    NS_ENSURE_TRUE(thebesImageSurface, NS_ERROR_FAILURE);
+    MOZ_ASSERT(surface->GetFormat() == SurfaceFormat::B8G8R8A8 ||
+               surface->GetFormat() == SurfaceFormat::B8G8R8X8);
 
-    IntSize surfaceSize(thebesImageSurface->GetSize().width,
-                        thebesImageSurface->GetSize().height);
-    RefPtr<DataSourceSurface> dataSurface =
-      Factory::CreateWrappingDataSourceSurface(thebesImageSurface->Data(),
-                                               thebesImageSurface->Stride(),
-                                               surfaceSize,
-                                               SurfaceFormat::B8G8R8A8);
+    RefPtr<DataSourceSurface> dataSurface;
+    if (surface->GetFormat() == SurfaceFormat::B8G8R8A8) {
+      dataSurface = surface->GetDataSurface();
+    } else {
+      // XXXjwatt Bug 995923 - get rid of this copy and handle B8G8R8X8
+      // directly below once bug 995807 is fixed.
+      dataSurface = gfxUtils::
+        CopySurfaceToDataSourceSurfaceWithFormat(surface,
+                                                 SurfaceFormat::B8G8R8A8);
+    }
     NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
 
     nsCOMPtr<imgIEncoder> encoder = do_CreateInstance("@mozilla.org/image/encoder;2?type=image/bmp", &rv);
     NS_ENSURE_SUCCESS(rv, rv);
     
     uint32_t format;
     nsAutoString options;
     if (mWantDIBV5) {
@@ -148,21 +153,25 @@ nsImageToClipboard::CreateFromImage ( im
     } else {
       options.AppendLiteral("version=3;bpp=");
     }
     switch (dataSurface->GetFormat()) {
     case SurfaceFormat::B8G8R8A8:
         format = imgIEncoder::INPUT_FORMAT_HOSTARGB;
         options.AppendInt(32);
         break;
+#if 0
+    // XXXjwatt Bug 995923 - fix |format| and reenable once bug 995807 is fixed.
     case SurfaceFormat::B8G8R8X8:
         format = imgIEncoder::INPUT_FORMAT_RGB;
         options.AppendInt(24);
         break;
+#endif
     default:
+        NS_NOTREACHED("Unexpected surface format");
         return NS_ERROR_INVALID_ARG;  
     }
 
     DataSourceSurface::MappedSurface map;
     bool mappedOK = dataSurface->Map(DataSourceSurface::MapType::READ, &map);
     NS_ENSURE_TRUE(mappedOK, NS_ERROR_FAILURE);
 
     rv = encoder->InitFromData(map.mData, 0,
--- a/widget/windows/nsWindowGfx.cpp
+++ b/widget/windows/nsWindowGfx.cpp
@@ -48,17 +48,16 @@ using mozilla::plugins::PluginInstancePa
 #ifdef MOZ_ENABLE_D3D10_LAYER
 #include "LayerManagerD3D10.h"
 #endif
 #include "mozilla/layers/CompositorParent.h"
 #include "ClientLayerManager.h"
 
 #include "nsUXThemeData.h"
 #include "nsUXThemeConstants.h"
-#include "mozilla/gfx/2D.h"
 
 extern "C" {
 #define PIXMAN_DONT_DEFINE_STDINT
 #include "pixman.h"
 }
 
 using namespace mozilla;
 using namespace mozilla::gfx;
@@ -611,57 +610,52 @@ nsresult nsWindowGfx::CreateIcon(imgICon
                                   uint32_t aHotspotY,
                                   gfxIntSize aScaledSize,
                                   HICON *aIcon) {
 
   MOZ_ASSERT((aScaledSize.width > 0 && aScaledSize.height > 0) ||
              (aScaledSize.width == 0 && aScaledSize.height == 0));
 
   // Get the image data
-  nsRefPtr<gfxASurface> thebesSurface =
+  RefPtr<SourceSurface> surface =
     aContainer->GetFrame(imgIContainer::FRAME_CURRENT,
                          imgIContainer::FLAG_SYNC_DECODE);
-  NS_ENSURE_TRUE(thebesSurface, NS_ERROR_NOT_AVAILABLE);
+  NS_ENSURE_TRUE(surface, NS_ERROR_NOT_AVAILABLE);
 
-  RefPtr<SourceSurface> surface =
-    gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr,
-                                                           thebesSurface);
-  NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
-
-  IntSize surfaceSize(surface->GetSize().width, surface->GetSize().height);
-  if (surfaceSize.IsEmpty()) {
+  IntSize frameSize = surface->GetSize();
+  if (frameSize.IsEmpty()) {
     return NS_ERROR_FAILURE;
   }
 
   IntSize iconSize(aScaledSize.width, aScaledSize.height);
   if (iconSize == IntSize(0, 0)) { // use frame's intrinsic size
-    iconSize = surfaceSize;
+    iconSize = frameSize;
   }
 
   RefPtr<DataSourceSurface> dataSurface;
   bool mappedOK;
   DataSourceSurface::MappedSurface map;
 
-  if (iconSize != surfaceSize) {
+  if (iconSize != frameSize) {
     // Scale the surface
     dataSurface = Factory::CreateDataSourceSurface(iconSize,
                                                    SurfaceFormat::B8G8R8A8);
     NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
     mappedOK = dataSurface->Map(DataSourceSurface::MapType::READ_WRITE, &map);
     NS_ENSURE_TRUE(mappedOK, NS_ERROR_FAILURE);
 
     RefPtr<DrawTarget> dt =
       Factory::CreateDrawTargetForData(BackendType::CAIRO,
                                        map.mData,
                                        dataSurface->GetSize(),
                                        map.mStride,
                                        SurfaceFormat::B8G8R8A8);
     dt->DrawSurface(surface,
                     Rect(0, 0, iconSize.width, iconSize.height),
-                    Rect(0, 0, surfaceSize.width, surfaceSize.height),
+                    Rect(0, 0, frameSize.width, frameSize.height),
                     DrawSurfaceOptions(),
                     DrawOptions(1.0f, CompositionOp::OP_SOURCE));
   } else if (surface->GetFormat() != SurfaceFormat::B8G8R8A8) {
     // Convert format to SurfaceFormat::B8G8R8A8
     dataSurface = gfxUtils::
       CopySurfaceToDataSourceSurfaceWithFormat(surface,
                                                SurfaceFormat::B8G8R8A8);
     NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
--- a/widget/windows/winrt/APZController.cpp
+++ b/widget/windows/winrt/APZController.cpp
@@ -298,30 +298,42 @@ class TransformedEndEvent : public nsRun
 {
   NS_IMETHOD Run() {
     MetroUtils::FireObserver("apzc-transform-end", L"");
     return NS_OK;
   }
 };
 
 void
-APZController::NotifyTransformBegin(const ScrollableLayerGuid& aGuid)
+APZController::NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
+                                    APZStateChange aChange,
+                                    int aArg)
 {
-  if (NS_IsMainThread()) {
-    MetroUtils::FireObserver("apzc-transform-begin", L"");
-    return;
+  switch (aChange) {
+    case APZStateChange::TransformBegin:
+    {
+      if (NS_IsMainThread()) {
+        MetroUtils::FireObserver("apzc-transform-begin", L"");
+        return;
+      }
+      nsCOMPtr<nsIRunnable> runnable = new TransformedStartEvent();
+      NS_DispatchToMainThread(runnable);
+      break;
+    }
+    case APZStateChange::TransformEnd:
+    {
+      if (NS_IsMainThread()) {
+        MetroUtils::FireObserver("apzc-transform-end", L"");
+        return;
+      }
+      nsCOMPtr<nsIRunnable> runnable = new TransformedEndEvent();
+      NS_DispatchToMainThread(runnable);
+      break;
+    }
+    default:
+    {
+      // We don't currently care about other state changes.
+      break;
+    }
   }
-  nsCOMPtr<nsIRunnable> runnable = new TransformedStartEvent();
-  NS_DispatchToMainThread(runnable);
-}
-
-void
-APZController::NotifyTransformEnd(const ScrollableLayerGuid& aGuid)
-{
-  if (NS_IsMainThread()) {
-    MetroUtils::FireObserver("apzc-transform-end", L"");
-    return;
-  }
-  nsCOMPtr<nsIRunnable> runnable = new TransformedEndEvent();
-  NS_DispatchToMainThread(runnable);
 }
 
 } } }
--- a/widget/windows/winrt/APZController.h
+++ b/widget/windows/winrt/APZController.h
@@ -44,18 +44,19 @@ public:
                              int32_t aModifiers,
                              const mozilla::layers::ScrollableLayerGuid& aGuid);
   virtual void HandleLongTapUp(const mozilla::CSSPoint& aPoint,
                                int32_t aModifiers,
                                const mozilla::layers::ScrollableLayerGuid& aGuid);
   virtual void SendAsyncScrollDOMEvent(bool aIsRoot, const mozilla::CSSRect &aContentRect, const mozilla::CSSSize &aScrollableSize);
   virtual void PostDelayedTask(Task* aTask, int aDelayMs);
   virtual bool GetRootZoomConstraints(ZoomConstraints* aOutConstraints);
-  virtual void NotifyTransformBegin(const ScrollableLayerGuid& aGuid);
-  virtual void NotifyTransformEnd(const ScrollableLayerGuid& aGuid);
+  virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
+                                    APZStateChange aChange,
+                                    int aArg);
   
   void SetWidgetListener(nsIWidgetListener* aWidgetListener);
 
   bool HitTestAPZC(mozilla::ScreenIntPoint& aPoint);
   void TransformCoordinateToGecko(const mozilla::ScreenIntPoint& aPoint,
                                   LayoutDeviceIntPoint* aRefPointOut);
   void ContentReceivedTouch(const ScrollableLayerGuid& aGuid, bool aPreventDefault);
   nsEventStatus ReceiveInputEvent(mozilla::WidgetInputEvent* aEvent,
new file mode 100644
--- /dev/null
+++ b/widget/xpwidgets/ActiveElementManager.cpp
@@ -0,0 +1,151 @@
+/* -*- 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 "ActiveElementManager.h"
+#include "mozilla/EventStates.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/Services.h"
+#include "inIDOMUtils.h"
+#include "nsIDOMDocument.h"
+#include "nsIDOMElement.h"
+#include "nsIDOMEventTarget.h"
+#include "base/message_loop.h"
+#include "base/task.h"
+
+namespace mozilla {
+namespace widget {
+
+static int32_t sActivationDelayMs = 100;
+static bool sActivationDelayMsSet = false;
+
+ActiveElementManager::ActiveElementManager()
+  : mDomUtils(services::GetInDOMUtils()),
+    mCanBePan(false),
+    mCanBePanSet(false),
+    mSetActiveTask(nullptr)
+{
+  if (!sActivationDelayMsSet) {
+    Preferences::AddIntVarCache(&sActivationDelayMs,
+                                "ui.touch_activation.delay_ms",
+                                sActivationDelayMs);
+    sActivationDelayMsSet = true;
+  }
+}
+
+ActiveElementManager::~ActiveElementManager() {}
+
+void
+ActiveElementManager::SetTargetElement(nsIDOMEventTarget* aTarget)
+{
+  if (mTarget) {
+    // Multiple fingers on screen (since HandleTouchEnd clears mTarget).
+    ResetActive();
+    return;
+  }
+
+  mTarget = do_QueryInterface(aTarget);
+  TriggerElementActivation();
+}
+
+void
+ActiveElementManager::HandleTouchStart(bool aCanBePan)
+{
+  mCanBePan = aCanBePan;
+  mCanBePanSet = true;
+  TriggerElementActivation();
+}
+
+void
+ActiveElementManager::TriggerElementActivation()
+{
+  // Both HandleTouchStart() and SetTargetElement() call this. They can be
+  // called in either order. One will set mCanBePanSet, and the other, mTarget.
+  // We want to actually trigger the activation once both are set.
+  if (!(mTarget && mCanBePanSet)) {
+    return;
+  }
+
+  // If the touch cannot be a pan, make mTarget :active right away.
+  // Otherwise, wait a bit to see if the user will pan or not.
+  if (!mCanBePan) {
+    SetActive(mTarget);
+  } else {
+    mSetActiveTask = NewRunnableMethod(
+        this, &ActiveElementManager::SetActiveTask, mTarget);
+    MessageLoop::current()->PostDelayedTask(
+        FROM_HERE, mSetActiveTask, sActivationDelayMs);
+  }
+}
+
+void
+ActiveElementManager::HandlePanStart()
+{
+  // The user started to pan, so we don't want mTarget to be :active.
+  // Make it not :active, and clear any pending task to make it :active.
+  CancelTask();
+  ResetActive();
+}
+
+void
+ActiveElementManager::HandleTouchEnd(bool aWasClick)
+{
+  // If the touch was a click, make mTarget :active right away.
+  // nsEventStateManager will reset the active element when processing
+  // the mouse-down event generated by the click.
+  CancelTask();
+  if (aWasClick) {
+    SetActive(mTarget);
+  }
+
+  // Clear mTarget for next touch.
+  mTarget = nullptr;
+}
+
+void
+ActiveElementManager::SetActive(nsIDOMElement* aTarget)
+{
+  if (mDomUtils) {
+    mDomUtils->SetContentState(aTarget, NS_EVENT_STATE_ACTIVE.GetInternalValue());;
+  }
+}
+
+void
+ActiveElementManager::ResetActive()
+{
+  // Clear the :active flag from mTarget by setting it on the document root.
+  if (mTarget) {
+    nsCOMPtr<nsIDOMDocument> doc;
+    mTarget->GetOwnerDocument(getter_AddRefs(doc));
+    if (doc) {
+      nsCOMPtr<nsIDOMElement> root;
+      doc->GetDocumentElement(getter_AddRefs(root));
+      if (root) {
+        SetActive(root);
+      }
+    }
+  }
+}
+
+void
+ActiveElementManager::SetActiveTask(nsIDOMElement* aTarget)
+{
+  // This gets called from mSetActiveTask's Run() method. The message loop
+  // deletes the task right after running it, so we need to null out
+  // mSetActiveTask to make sure we're not left with a dangling pointer.
+  mSetActiveTask = nullptr;
+  SetActive(aTarget);
+}
+
+void
+ActiveElementManager::CancelTask()
+{
+  if (mSetActiveTask) {
+    mSetActiveTask->Cancel();
+    mSetActiveTask = nullptr;
+  }
+}
+
+}
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/widget/xpwidgets/ActiveElementManager.h
@@ -0,0 +1,85 @@
+/* -*- 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_widget_ActiveElementManager_h__
+#define __mozilla_widget_ActiveElementManager_h__
+
+#include "nsCOMPtr.h"
+#include "nsISupportsImpl.h"
+
+class inIDOMUtils;
+class nsIDOMEventTarget;
+class nsIDOMElement;
+class CancelableTask;
+
+namespace mozilla {
+namespace widget {
+
+/**
+ * Manages setting and clearing the ':active' CSS pseudostate in the presence
+ * of touch input.
+ */
+class ActiveElementManager {
+public:
+  NS_INLINE_DECL_REFCOUNTING(ActiveElementManager)
+
+  ActiveElementManager();
+  ~ActiveElementManager();
+
+  /**
+   * Specify the target of a touch. Typically this should be called right
+   * before HandleTouchStart(), but we give callers the flexibility to specify
+   * the target later if they don't know it at the time they call
+   * HandleTouchStart().
+   * |aTarget| may be nullptr.
+   */
+  void SetTargetElement(nsIDOMEventTarget* aTarget);
+  /**
+   * Handle a touch-start event.
+   * @param aCanBePan whether the touch can be a pan
+   */
+  void HandleTouchStart(bool aCanBePan);
+  /**
+   * Handle the start of panning.
+   */
+  void HandlePanStart();
+  /**
+   * Handle a touch-end or touch-cancel event.
+   * @param aWasClick whether the touch was a click
+   */
+  void HandleTouchEnd(bool aWasClick);
+private:
+  nsCOMPtr<inIDOMUtils> mDomUtils;
+  /**
+   * The target of the first touch point in the current touch block.
+   */
+  nsCOMPtr<nsIDOMElement> mTarget;
+  /**
+   * Whether the current touch block can be a pan. Set in HandleTouchStart().
+   */
+  bool mCanBePan;
+  /**
+   * Whether mCanBePan has been set for the current touch block.
+   * We need to keep track of this to allow HandleTouchStart() and
+   * SetTargetElement() to be called in either order.
+   */
+  bool mCanBePanSet;
+  /**
+   * A task for calling SetActive() after a timeout.
+   */
+  CancelableTask* mSetActiveTask;
+
+  // Helpers
+  void TriggerElementActivation();
+  void SetActive(nsIDOMElement* aTarget);
+  void ResetActive();
+  void SetActiveTask(nsIDOMElement* aTarget);
+  void CancelTask();
+};
+
+}
+}
+
+#endif /*__mozilla_widget_ActiveElementManager_h__ */
--- a/widget/xpwidgets/moz.build
+++ b/widget/xpwidgets/moz.build
@@ -1,23 +1,25 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 EXPORTS += [
+    'ActiveElementManager.h',
     'APZCCallbackHelper.h',
     'ContentHelper.h',
     'GfxDriverInfo.h',
     'GfxInfoBase.h',
     'GfxInfoCollector.h',
 ]
 
 UNIFIED_SOURCES += [
+    'ActiveElementManager.cpp',
     'APZCCallbackHelper.cpp',
     'ContentHelper.cpp',
     'GfxDriverInfo.cpp',
     'GfxInfoBase.cpp',
     'GfxInfoCollector.cpp',
     'GfxInfoWebGL.cpp',
     'InputData.cpp',
     'nsBaseAppShell.cpp',
--- a/xpcom/build/ServiceList.h
+++ b/xpcom/build/ServiceList.h
@@ -9,16 +9,17 @@ MOZ_SERVICE(AccessibilityService, nsIAcc
 MOZ_SERVICE(ChromeRegistryService, nsIChromeRegistry, "@mozilla.org/chrome/chrome-registry;1")
 MOZ_SERVICE(ToolkitChromeRegistryService, nsIToolkitChromeRegistry, "@mozilla.org/chrome/chrome-registry;1")
 MOZ_SERVICE(XULChromeRegistryService, nsIXULChromeRegistry, "@mozilla.org/chrome/chrome-registry;1")
 MOZ_SERVICE(XULOverlayProviderService, nsIXULOverlayProvider, "@mozilla.org/chrome/chrome-registry;1")
 MOZ_SERVICE(IOService, nsIIOService, "@mozilla.org/network/io-service;1")
 MOZ_SERVICE(ObserverService, nsIObserverService, "@mozilla.org/observer-service;1")
 MOZ_SERVICE(StringBundleService, nsIStringBundleService, "@mozilla.org/intl/stringbundle;1")
 MOZ_SERVICE(XPConnect, nsIXPConnect, "@mozilla.org/js/xpc/XPConnect;1")
+MOZ_SERVICE(InDOMUtils, inIDOMUtils, "@mozilla.org/inspector/dom-utils;1")
 
 #ifdef MOZ_USE_NAMESPACE
 namespace mozilla
 {
 #endif
 
 MOZ_SERVICE(HistoryService, IHistory, "@mozilla.org/browser/history;1")
 
--- a/xpcom/build/Services.cpp
+++ b/xpcom/build/Services.cpp
@@ -15,16 +15,17 @@
 #include "nsNetCID.h"
 #include "nsObserverService.h"
 #include "nsXPCOMPrivate.h"
 #include "nsIStringBundle.h"
 #include "nsIToolkitChromeRegistry.h"
 #include "nsIXULOverlayProvider.h"
 #include "IHistory.h"
 #include "nsIXPConnect.h"
+#include "inIDOMUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::services;
 
 /*
  * Define a global variable and a getter for every service in ServiceList.
  * eg. gIOService and GetIOService()
  */
--- a/xpcom/ds/moz.build
+++ b/xpcom/ds/moz.build
@@ -48,18 +48,16 @@ EXPORTS += [
     'nsAtomService.h',
     'nsCharSeparatedTokenizer.h',
     'nsCheapSets.h',
     'nsCRT.h',
     'nsExpirationTracker.h',
     'nsHashPropertyBag.h',
     'nsHashtable.h',
     'nsMathUtils.h',
-    'nsObserverList.h',
-    'nsObserverService.h',
     'nsStaticAtom.h',
     'nsStaticNameTable.h',
     'nsStringEnumerator.h',
     'nsSupportsArray.h',
     'nsSupportsPrimitives.h',
     'nsVariant.h',
     'nsWhitespaceTokenizer.h',
 ]
--- a/xpcom/ds/nsObserverService.cpp
+++ b/xpcom/ds/nsObserverService.cpp
@@ -217,17 +217,17 @@ nsObserverService::Create(nsISupports* o
         NS_NewRunnableMethod(os, &nsObserverService::RegisterReporter);
     NS_DispatchToCurrentThread(registerRunnable);
 
     return os->QueryInterface(aIID, aInstancePtr);
 }
 
 #define NS_ENSURE_VALIDCALL \
     if (!NS_IsMainThread()) {                                     \
-        NS_ERROR("Using observer service off the main thread!");  \
+        MOZ_CRASH("Using observer service off the main thread!"); \
         return NS_ERROR_UNEXPECTED;                               \
     }                                                             \
     if (mShuttingDown) {                                          \
         NS_ERROR("Using observer service after XPCOM shutdown!"); \
         return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;                  \
     }
 
 NS_IMETHODIMP
--- a/xpcom/ds/nsObserverService.h
+++ b/xpcom/ds/nsObserverService.h
@@ -22,17 +22,17 @@ class nsObserverService MOZ_FINAL
   : public nsIObserverService
   , public nsIMemoryReporter
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_OBSERVERSERVICE_CID)
 
   nsObserverService();
 
-  NS_DECL_THREADSAFE_ISUPPORTS
+  NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVERSERVICE
   NS_DECL_NSIMEMORYREPORTER
 
   void Shutdown();
 
   static nsresult
   Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
 
--- a/xpcom/threads/BackgroundHangMonitor.cpp
+++ b/xpcom/threads/BackgroundHangMonitor.cpp
@@ -23,17 +23,17 @@
 #include <algorithm>
 
 namespace mozilla {
 
 /**
  * BackgroundHangManager is the global object that
  * manages all instances of BackgroundHangThread.
  */
-class BackgroundHangManager : public AtomicRefCounted<BackgroundHangManager>
+class BackgroundHangManager
 {
 private:
   // Background hang monitor thread function
   static void MonitorThread(void* aData)
   {
     PR_SetCurrentThreadName("BgHangManager");
 
 #ifdef MOZ_NUWA_PROCESS
@@ -57,17 +57,17 @@ private:
   // Stop hang monitoring
   bool mShutdown;
 
   BackgroundHangManager(const BackgroundHangManager&);
   BackgroundHangManager& operator=(const BackgroundHangManager&);
   void RunMonitorThread();
 
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(BackgroundHangManager)
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BackgroundHangManager)
   static StaticRefPtr<BackgroundHangManager> sInstance;
 
   // Lock for access to members of this class
   Monitor mLock;
   // Current time as seen by hang monitors
   PRIntervalTime mIntervalNow;
   // List of BackgroundHangThread instances associated with each thread
   LinkedList<BackgroundHangThread> mHangThreads;