Backout bug 926746 part 3 (replaced with bug 945334) rs=jesup
authorRandell Jesup <rjesup@jesup.org>
Thu, 05 Dec 2013 16:30:50 -0500
changeset 174706 c4b843dfa9591a6af07829e43f701ea84c251817
parent 174705 223af50b7080cea6ed2079c6b8850455fb21a776
child 174707 d212ce6a9a18e59fcc4bb97871a5a11b725e6cf2
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup
bugs926746, 945334
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backout bug 926746 part 3 (replaced with bug 945334) rs=jesup
dom/media/MediaManager.cpp
dom/media/MediaManager.h
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -137,84 +137,84 @@ static nsresult ValidateTrackConstraints
                                       aNormalized.mMandatory,
                                       aOutUnknownConstraint);
     NS_ENSURE_SUCCESS(rv, rv);
   }
   return NS_OK;
 }
 
 ErrorCallbackRunnable::ErrorCallbackRunnable(
-  nsMainThreadPtrHandle<nsIDOMGetUserMediaSuccessCallback>& aSuccess,
-  nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback>& aError,
+  already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
+  already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
   const nsAString& aErrorMsg, uint64_t aWindowID)
   : mSuccess(aSuccess)
   , mError(aError)
   , mErrorMsg(aErrorMsg)
   , mWindowID(aWindowID)
-  , mManager(MediaManager::GetInstance()){
-}
-
-ErrorCallbackRunnable::ErrorCallbackRunnable(
-  nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback>& aError,
-  const nsAString& aErrorMsg, uint64_t aWindowID)
-  : mError(aError)
-  , mErrorMsg(aErrorMsg)
-  , mWindowID(aWindowID)
   , mManager(MediaManager::GetInstance()) {
-}
+  }
 
 NS_IMETHODIMP
 ErrorCallbackRunnable::Run()
 {
   // Only run if the window is still active.
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
-  if (mError.get() && mManager->IsWindowStillActive(mWindowID)) {
-    // This is safe since we're on main-thread, and the windowlist can only
-    // be invalidated from the main-thread (see OnNavigation)
-    mError->OnError(mErrorMsg);
+
+  nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> success(mSuccess);
+  nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error(mError);
+
+  if (!(mManager->IsWindowStillActive(mWindowID))) {
+    return NS_OK;
   }
+  // This is safe since we're on main-thread, and the windowlist can only
+  // be invalidated from the main-thread (see OnNavigation)
+  error->OnError(mErrorMsg);
   return NS_OK;
 }
 
 /**
  * Invoke the "onSuccess" callback in content. The callback will take a
  * DOMBlob in the case of {picture:true}, and a MediaStream in the case of
  * {audio:true} or {video:true}. There is a constructor available for each
  * form. Do this only on the main thread.
  */
 class SuccessCallbackRunnable : public nsRunnable
 {
 public:
   SuccessCallbackRunnable(
-    nsMainThreadPtrHandle<nsIDOMGetUserMediaSuccessCallback>& aSuccess,
-    nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback>& aError,
+    already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
+    already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
     nsIDOMFile* aFile, uint64_t aWindowID)
     : mSuccess(aSuccess)
     , mError(aError)
     , mFile(aFile)
     , mWindowID(aWindowID)
     , mManager(MediaManager::GetInstance()) {}
 
   NS_IMETHOD
   Run()
   {
     // Only run if the window is still active.
     NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
-    if (mSuccess.get() && mManager->IsWindowStillActive(mWindowID)) {
-      // This is safe since we're on main-thread, and the windowlist can only
-      // be invalidated from the main-thread (see OnNavigation)
-      mSuccess->OnSuccess(mFile);
+    nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> success(mSuccess);
+    nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error(mError);
+
+    if (!(mManager->IsWindowStillActive(mWindowID))) {
+      return NS_OK;
     }
+    // This is safe since we're on main-thread, and the windowlist can only
+    // be invalidated from the main-thread (see OnNavigation)
+    success->OnSuccess(mFile);
     return NS_OK;
   }
 
 private:
-  nsMainThreadPtrHandle<nsIDOMGetUserMediaSuccessCallback> mSuccess;
-  nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback> mError;
+  already_AddRefed<nsIDOMGetUserMediaSuccessCallback> mSuccess;
+  already_AddRefed<nsIDOMGetUserMediaErrorCallback> mError;
   nsCOMPtr<nsIDOMFile> mFile;
   uint64_t mWindowID;
   nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable
 };
 
 /**
  * Invoke the GetUserMediaDevices success callback. Wrapped in a runnable
  * so that it may be called on the main thread. The error callback is also
@@ -454,18 +454,18 @@ public:
  * though that would complicate the constructors some.  Currently the
  * GetUserMedia spec does not allow for more than 2 streams to be obtained in
  * one call, to simplify handling of constraints.
  */
 class GetUserMediaStreamRunnable : public nsRunnable
 {
 public:
   GetUserMediaStreamRunnable(
-    nsMainThreadPtrHandle<nsIDOMGetUserMediaSuccessCallback>& aSuccess,
-    nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback>& aError,
+    already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
+    already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
     uint64_t aWindowID,
     GetUserMediaCallbackMediaStreamListener* aListener,
     MediaEngineSource* aAudioSource,
     MediaEngineSource* aVideoSource)
     : mSuccess(aSuccess)
     , mError(aError)
     , mAudioSource(aAudioSource)
     , mVideoSource(aVideoSource)
@@ -474,19 +474,19 @@ public:
     , mManager(MediaManager::GetInstance()) {}
 
   ~GetUserMediaStreamRunnable() {}
 
   class TracksAvailableCallback : public DOMMediaStream::OnTracksAvailableCallback
   {
   public:
     TracksAvailableCallback(MediaManager* aManager,
-      nsMainThreadPtrHandle<nsIDOMGetUserMediaSuccessCallback>& aSuccess,
-      uint64_t aWindowID,
-      DOMMediaStream* aStream)
+                            nsIDOMGetUserMediaSuccessCallback* aSuccess,
+                            uint64_t aWindowID,
+                            DOMMediaStream* aStream)
       : mWindowID(aWindowID), mSuccess(aSuccess), mManager(aManager),
         mStream(aStream) {}
     virtual void NotifyTracksAvailable(DOMMediaStream* aStream) MOZ_OVERRIDE
     {
       // We're in the main thread, so no worries here.
       if (!(mManager->IsWindowStillActive(mWindowID))) {
         return;
       }
@@ -496,17 +496,17 @@ public:
       aStream->SetLogicalStreamStartTime(aStream->GetStream()->GetCurrentTime());
 
       // This is safe since we're on main-thread, and the windowlist can only
       // be invalidated from the main-thread (see OnNavigation)
       LOG(("Returning success for getUserMedia()"));
       mSuccess->OnSuccess(aStream);
     }
     uint64_t mWindowID;
-    nsMainThreadPtrHandle<nsIDOMGetUserMediaSuccessCallback> mSuccess;
+    nsRefPtr<nsIDOMGetUserMediaSuccessCallback> mSuccess;
     nsRefPtr<MediaManager> mManager;
     // Keep the DOMMediaStream alive until the NotifyTracksAvailable callback
     // has fired, otherwise we might immediately destroy the DOMMediaStream and
     // shut down the underlying MediaStream prematurely.
     // This creates a cycle which is broken when NotifyTracksAvailable
     // is fired (which will happen unless the browser shuts down,
     // since we only add this callback when we've successfully appended
     // the desired tracks in the MediaStreamGraph) or when
@@ -532,18 +532,19 @@ public:
     // Create a media stream.
     DOMMediaStream::TrackTypeHints hints =
       (mAudioSource ? DOMMediaStream::HINT_CONTENTS_AUDIO : 0) |
       (mVideoSource ? DOMMediaStream::HINT_CONTENTS_VIDEO : 0);
 
     nsRefPtr<nsDOMUserMediaStream> trackunion =
       nsDOMUserMediaStream::CreateTrackUnionStream(window, hints);
     if (!trackunion) {
+      nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error = mError.forget();
       LOG(("Returning error for getUserMedia() - no stream"));
-      mError->OnError(NS_LITERAL_STRING("NO_STREAM"));
+      error->OnError(NS_LITERAL_STRING("NO_STREAM"));
       return NS_OK;
     }
 
     MediaStreamGraph* gm = MediaStreamGraph::GetInstance();
     nsRefPtr<SourceMediaStream> stream = gm->CreateSourceStream(nullptr);
 
     // connect the source stream to the track union stream to avoid us blocking
     trackunion->GetStream()->AsProcessedStream()->SetAutofinish(true);
@@ -573,17 +574,17 @@ public:
     // because that can take a while.
     // Pass ownership of trackunion to the MediaOperationRunnable
     // to ensure it's kept alive until the MediaOperationRunnable runs (at least).
     nsIThread *mediaThread = MediaManager::GetThread();
     nsRefPtr<MediaOperationRunnable> runnable(
       new MediaOperationRunnable(MEDIA_START, mListener, trackunion,
                                  tracksAvailableCallback,
                                  mAudioSource, mVideoSource, false, mWindowID,
-                                 mError));
+                                 mError.forget()));
     mediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
 
 #ifdef MOZ_WEBRTC
     // Right now these configs are only of use if webrtc is available
     nsresult rv;
     nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv);
     if (NS_SUCCEEDED(rv)) {
       nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
@@ -603,22 +604,24 @@ public:
 
         mListener->AudioConfig(aec_on, (uint32_t) aec,
                                agc_on, (uint32_t) agc,
                                noise_on, (uint32_t) noise);
       }
     }
 #endif
 
+    // We won't need mError now.
+    mError = nullptr;
     return NS_OK;
   }
 
 private:
-  nsMainThreadPtrHandle<nsIDOMGetUserMediaSuccessCallback> mSuccess;
-  nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback> mError;
+  nsRefPtr<nsIDOMGetUserMediaSuccessCallback> mSuccess;
+  nsRefPtr<nsIDOMGetUserMediaErrorCallback> mError;
   nsRefPtr<MediaEngineSource> mAudioSource;
   nsRefPtr<MediaEngineSource> mVideoSource;
   uint64_t mWindowID;
   nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener;
   nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable
 };
 
 /**
@@ -736,45 +739,45 @@ static SourceSet *
  * Do not run this on the main thread. The success and error callbacks *MUST*
  * be dispatched on the main thread!
  */
 class GetUserMediaRunnable : public nsRunnable
 {
 public:
   GetUserMediaRunnable(
     const MediaStreamConstraintsInternal& aConstraints,
-    nsIDOMGetUserMediaSuccessCallback* aSuccess,
-    nsIDOMGetUserMediaErrorCallback* aError,
+    already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
+    already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
     uint64_t aWindowID, GetUserMediaCallbackMediaStreamListener *aListener,
     MediaEnginePrefs &aPrefs)
     : mConstraints(aConstraints)
-    , mSuccess(new nsMainThreadPtrHolder<nsIDOMGetUserMediaSuccessCallback>(aSuccess))
-    , mError(new nsMainThreadPtrHolder<nsIDOMGetUserMediaErrorCallback>(aError))
+    , mSuccess(aSuccess)
+    , mError(aError)
     , mWindowID(aWindowID)
     , mListener(aListener)
     , mPrefs(aPrefs)
     , mDeviceChosen(false)
     , mBackendChosen(false)
     , mManager(MediaManager::GetInstance())
   {}
 
   /**
    * The caller can also choose to provide their own backend instead of
    * using the one provided by MediaManager::GetBackend.
    */
   GetUserMediaRunnable(
     const MediaStreamConstraintsInternal& aConstraints,
-    nsIDOMGetUserMediaSuccessCallback* aSuccess,
-    nsIDOMGetUserMediaErrorCallback* aError,
+    already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
+    already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
     uint64_t aWindowID, GetUserMediaCallbackMediaStreamListener *aListener,
     MediaEnginePrefs &aPrefs,
     MediaEngine* aBackend)
     : mConstraints(aConstraints)
-    , mSuccess(new nsMainThreadPtrHolder<nsIDOMGetUserMediaSuccessCallback>(aSuccess))
-    , mError(new nsMainThreadPtrHolder<nsIDOMGetUserMediaErrorCallback>(aError))
+    , mSuccess(aSuccess)
+    , mError(aError)
     , mWindowID(aWindowID)
     , mListener(aListener)
     , mPrefs(aPrefs)
     , mDeviceChosen(false)
     , mBackendChosen(true)
     , mBackend(aBackend)
     , mManager(MediaManager::GetInstance())
   {}
@@ -837,17 +840,18 @@ public:
 
       // Should happen *after* error runs for consistency, but may not matter
       nsRefPtr<MediaManager> manager(MediaManager::GetInstance());
       manager->RemoveFromWindowList(mWindowID, mListener);
     } else {
       // This will re-check the window being alive on main-thread
       // Note: we must remove the listener on MainThread as well
       NS_DispatchToMainThread(new ErrorCallbackRunnable(
-        mSuccess, mError, aErrorMsg, mWindowID));
+        mSuccess, mError, aErrorMsg, mWindowID
+      ));
 
       // MUST happen after ErrorCallbackRunnable Run()s, as it checks the active window list
       NS_DispatchToMainThread(new GetUserMediaListenerRemove(mWindowID, mListener));
     }
 
     return NS_OK;
   }
 
@@ -908,30 +912,32 @@ public:
   void
   ProcessGetUserMedia(MediaEngineSource* aAudioSource, MediaEngineSource* aVideoSource)
   {
     nsresult rv;
     if (aAudioSource) {
       rv = aAudioSource->Allocate(mPrefs);
       if (NS_FAILED(rv)) {
         LOG(("Failed to allocate audiosource %d",rv));
-        NS_DispatchToMainThread(new ErrorCallbackRunnable(mSuccess, mError,
-          NS_LITERAL_STRING("HARDWARE_UNAVAILABLE"), mWindowID));
+        NS_DispatchToMainThread(new ErrorCallbackRunnable(
+                                  mSuccess, mError, NS_LITERAL_STRING("HARDWARE_UNAVAILABLE"), mWindowID
+                                                          ));
         return;
       }
     }
     if (aVideoSource) {
       rv = aVideoSource->Allocate(mPrefs);
       if (NS_FAILED(rv)) {
         LOG(("Failed to allocate videosource %d\n",rv));
         if (aAudioSource) {
           aAudioSource->Deallocate();
         }
-        NS_DispatchToMainThread(new ErrorCallbackRunnable(mSuccess, mError,
-          NS_LITERAL_STRING("HARDWARE_UNAVAILABLE"), mWindowID));
+        NS_DispatchToMainThread(new ErrorCallbackRunnable(
+          mSuccess, mError, NS_LITERAL_STRING("HARDWARE_UNAVAILABLE"), mWindowID
+                                                          ));
         return;
       }
     }
 
     NS_DispatchToMainThread(new GetUserMediaStreamRunnable(
       mSuccess, mError, mWindowID, mListener, aAudioSource, aVideoSource
     ));
     return;
@@ -941,18 +947,19 @@ public:
    * Allocates a video device, takes a snapshot and returns a DOMFile via
    * a SuccessRunnable or an error via the ErrorRunnable. Off the main thread.
    */
   void
   ProcessGetUserMediaSnapshot(MediaEngineSource* aSource, int aDuration)
   {
     nsresult rv = aSource->Allocate(mPrefs);
     if (NS_FAILED(rv)) {
-      NS_DispatchToMainThread(new ErrorCallbackRunnable(mSuccess, mError,
-        NS_LITERAL_STRING("HARDWARE_UNAVAILABLE"), mWindowID));
+      NS_DispatchToMainThread(new ErrorCallbackRunnable(
+        mSuccess, mError, NS_LITERAL_STRING("HARDWARE_UNAVAILABLE"), mWindowID
+      ));
       return;
     }
 
     /**
      * Display picture capture UI here before calling Snapshot() - Bug 748835.
      */
     nsCOMPtr<nsIDOMFile> file;
     aSource->Snapshot(aDuration, getter_AddRefs(file));
@@ -962,18 +969,18 @@ public:
       mSuccess, mError, file, mWindowID
     ));
     return;
   }
 
 private:
   MediaStreamConstraintsInternal mConstraints;
 
-  nsMainThreadPtrHandle<nsIDOMGetUserMediaSuccessCallback> mSuccess;
-  nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback> mError;
+  already_AddRefed<nsIDOMGetUserMediaSuccessCallback> mSuccess;
+  already_AddRefed<nsIDOMGetUserMediaErrorCallback> mError;
   uint64_t mWindowID;
   nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener;
   nsRefPtr<MediaDevice> mAudioDevice;
   nsRefPtr<MediaDevice> mVideoDevice;
   MediaEnginePrefs mPrefs;
 
   bool mDeviceChosen;
   bool mBackendChosen;
@@ -1307,22 +1314,22 @@ MediaManager::GetUserMedia(JSContext* aC
   }
 
   /**
    * Pass runnables along to GetUserMediaRunnable so it can add the
    * MediaStreamListener to the runnable list.
    */
   if (c.mFake) {
     // Fake stream from default backend.
-    gUMRunnable = new GetUserMediaRunnable(c, onSuccess,
-      onError, windowID, listener, mPrefs, new MediaEngineDefault());
+    gUMRunnable = new GetUserMediaRunnable(c, onSuccess.forget(),
+      onError.forget(), windowID, listener, mPrefs, new MediaEngineDefault());
   } else {
     // Stream from default device from WebRTC backend.
-    gUMRunnable = new GetUserMediaRunnable(c, onSuccess,
-      onError, windowID, listener, mPrefs);
+    gUMRunnable = new GetUserMediaRunnable(c, onSuccess.forget(),
+      onError.forget(), windowID, listener, mPrefs);
   }
 
 #ifdef MOZ_B2G_CAMERA
   if (mCameraManager == nullptr) {
     mCameraManager = nsDOMCameraManager::CreateInstance(aWindow);
   }
 #endif
 
@@ -1777,17 +1784,17 @@ GetUserMediaCallbackMediaStreamListener:
   nsRefPtr<MediaOperationRunnable> runnable;
   // We can't take a chance on blocking here, so proxy this to another
   // thread.
   // Pass a ref to us (which is threadsafe) so it can query us for the
   // source stream info.
   runnable = new MediaOperationRunnable(MEDIA_STOP,
                                         this, nullptr, nullptr,
                                         mAudioSource, mVideoSource,
-                                        mFinished, mWindowID);
+                                        mFinished, mWindowID, nullptr);
   mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
 }
 
 // Called from the MediaStreamGraph thread
 void
 GetUserMediaCallbackMediaStreamListener::NotifyFinished(MediaStreamGraph* aGraph)
 {
   mFinished = true;
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -9,17 +9,16 @@
 
 #include "nsHashKeys.h"
 #include "nsGlobalWindow.h"
 #include "nsClassHashtable.h"
 #include "nsRefPtrHashtable.h"
 #include "nsObserverService.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
-#include "nsProxyRelease.h"
 
 #include "nsPIDOMWindow.h"
 #include "nsIDOMNavigatorUserMedia.h"
 #include "nsXULAppAPI.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/dom/MediaStreamTrackBinding.h"
 #include "prlog.h"
@@ -209,17 +208,17 @@ class GetUserMediaNotificationEvent: pub
                                   bool aIsAudio, bool aIsVideo, uint64_t aWindowID)
     : mListener(aListener) , mStatus(aStatus) , mIsAudio(aIsAudio)
     , mIsVideo(aIsVideo), mWindowID(aWindowID) {}
 
     GetUserMediaNotificationEvent(GetUserMediaStatus aStatus,
                                   already_AddRefed<DOMMediaStream> aStream,
                                   DOMMediaStream::OnTracksAvailableCallback* aOnTracksAvailableCallback,
                                   bool aIsAudio, bool aIsVideo, uint64_t aWindowID,
-                                  nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback> aError)
+                                  already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError)
     : mStream(aStream), mOnTracksAvailableCallback(aOnTracksAvailableCallback),
       mStatus(aStatus), mIsAudio(aIsAudio), mIsVideo(aIsVideo), mWindowID(aWindowID),
       mError(aError) {}
     virtual ~GetUserMediaNotificationEvent()
     {
 
     }
 
@@ -228,17 +227,17 @@ class GetUserMediaNotificationEvent: pub
   protected:
     nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener; // threadsafe
     nsRefPtr<DOMMediaStream> mStream;
     nsAutoPtr<DOMMediaStream::OnTracksAvailableCallback> mOnTracksAvailableCallback;
     GetUserMediaStatus mStatus;
     bool mIsAudio;
     bool mIsVideo;
     uint64_t mWindowID;
-    nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback> mError;
+    nsRefPtr<nsIDOMGetUserMediaErrorCallback> mError;
 };
 
 typedef enum {
   MEDIA_START,
   MEDIA_STOP
 } MediaOperation;
 
 class MediaManager;
@@ -247,26 +246,23 @@ class MediaManager;
  * Send an error back to content. The error is the form a string.
  * Do this only on the main thread. The success callback is also passed here
  * so it can be released correctly.
  */
 class ErrorCallbackRunnable : public nsRunnable
 {
 public:
   ErrorCallbackRunnable(
-    nsMainThreadPtrHandle<nsIDOMGetUserMediaSuccessCallback>& aSuccess,
-    nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback>& aError,
-    const nsAString& aErrorMsg, uint64_t aWindowID);
-  ErrorCallbackRunnable(
-    nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback>& aError,
+    already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
+    already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
     const nsAString& aErrorMsg, uint64_t aWindowID);
   NS_IMETHOD Run();
 private:
-  nsMainThreadPtrHandle<nsIDOMGetUserMediaSuccessCallback> mSuccess;
-  nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback> mError;
+  already_AddRefed<nsIDOMGetUserMediaSuccessCallback> mSuccess;
+  already_AddRefed<nsIDOMGetUserMediaErrorCallback> mError;
   const nsString mErrorMsg;
   uint64_t mWindowID;
   nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable
 };
 
 class ReleaseMediaOperationResource : public nsRunnable
 {
 public:
@@ -290,61 +286,43 @@ public:
   MediaOperationRunnable(MediaOperation aType,
     GetUserMediaCallbackMediaStreamListener* aListener,
     DOMMediaStream* aStream,
     DOMMediaStream::OnTracksAvailableCallback* aOnTracksAvailableCallback,
     MediaEngineSource* aAudioSource,
     MediaEngineSource* aVideoSource,
     bool aNeedsFinish,
     uint64_t aWindowID,
-    nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback> aError)
+    already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError)
     : mType(aType)
     , mStream(aStream)
     , mOnTracksAvailableCallback(aOnTracksAvailableCallback)
     , mAudioSource(aAudioSource)
     , mVideoSource(aVideoSource)
     , mListener(aListener)
     , mFinish(aNeedsFinish)
     , mWindowID(aWindowID)
     , mError(aError)
   {}
 
-  MediaOperationRunnable(MediaOperation aType,
-    GetUserMediaCallbackMediaStreamListener* aListener,
-    DOMMediaStream* aStream,
-    DOMMediaStream::OnTracksAvailableCallback* aOnTracksAvailableCallback,
-    MediaEngineSource* aAudioSource,
-    MediaEngineSource* aVideoSource,
-    bool aNeedsFinish,
-    uint64_t aWindowID)
-    : mType(aType)
-    , mStream(aStream)
-    , mOnTracksAvailableCallback(aOnTracksAvailableCallback)
-    , mAudioSource(aAudioSource)
-    , mVideoSource(aVideoSource)
-    , mListener(aListener)
-    , mFinish(aNeedsFinish)
-    , mWindowID(aWindowID)
-    , mError(nullptr)
-  {}
-
   ~MediaOperationRunnable()
   {
     // MediaStreams can be released on any thread.
   }
 
   nsresult returnAndCallbackError(nsresult rv, const char* errorLog)
   {
     MM_LOG(("%s , rv=%d", errorLog, rv));
     NS_DispatchToMainThread(new ReleaseMediaOperationResource(mStream.forget(),
           mOnTracksAvailableCallback.forget()));
     nsString log;
 
     log.AssignASCII(errorLog, strlen(errorLog));
-    NS_DispatchToMainThread(new ErrorCallbackRunnable(mError, log, mWindowID));
+    NS_DispatchToMainThread(new ErrorCallbackRunnable(nullptr, mError.forget(),
+      log, mWindowID));
     return NS_OK;
   }
 
   NS_IMETHOD
   Run() MOZ_OVERRIDE
   {
     SourceMediaStream *source = mListener->GetSourceStream();
     // No locking between these is required as all the callbacks for the
@@ -385,17 +363,17 @@ public:
           // because mOnTracksAvailableCallback needs to be added to mStream
           // on the main thread.
           nsRefPtr<GetUserMediaNotificationEvent> event =
             new GetUserMediaNotificationEvent(GetUserMediaNotificationEvent::STARTING,
                                               mStream.forget(),
                                               mOnTracksAvailableCallback.forget(),
                                               mAudioSource != nullptr,
                                               mVideoSource != nullptr,
-                                              mWindowID, mError);
+                                              mWindowID, mError.forget());
           NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
         }
         break;
 
       case MEDIA_STOP:
         {
           NS_ASSERTION(!NS_IsMainThread(), "Never call on main thread");
           if (mAudioSource) {
@@ -432,17 +410,17 @@ private:
   MediaOperation mType;
   nsRefPtr<DOMMediaStream> mStream;
   nsAutoPtr<DOMMediaStream::OnTracksAvailableCallback> mOnTracksAvailableCallback;
   nsRefPtr<MediaEngineSource> mAudioSource; // threadsafe
   nsRefPtr<MediaEngineSource> mVideoSource; // threadsafe
   nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener; // threadsafe
   bool mFinish;
   uint64_t mWindowID;
-  nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback> mError;
+  nsRefPtr<nsIDOMGetUserMediaErrorCallback> mError;
 };
 
 typedef nsTArray<nsRefPtr<GetUserMediaCallbackMediaStreamListener> > StreamListeners;
 typedef nsClassHashtable<nsUint64HashKey, StreamListeners> WindowTable;
 
 class MediaDevice : public nsIMediaDevice
 {
 public: