Bug 1336510 - Part 4: Capture a strong reference to this in dom/media, r=jwwang
☠☠ backed out by 3fee518242f6 ☠ ☠
authorMichael Layzell <michael@thelayzells.com>
Fri, 03 Feb 2017 16:57:49 -0500
changeset 344615 57476b9f342d8872813e701261fad2907738c969
parent 344614 e842cdaaa7e5fb44c713917005b19feed9cf5b6e
child 344616 21869174dfd3e1548324f590245ea06d215a5d6a
push id31414
push usercbook@mozilla.com
push dateFri, 24 Feb 2017 10:47:41 +0000
treeherdermozilla-central@be661bae6cb9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwwang
bugs1336510
milestone54.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1336510 - Part 4: Capture a strong reference to this in dom/media, r=jwwang MozReview-Commit-ID: 4lVGrGzhVXh
dom/media/MediaDecoder.cpp
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaManager.cpp
dom/media/mediasink/DecodedStream.cpp
dom/media/ogg/OggDemuxer.cpp
dom/media/systemservices/CamerasChild.cpp
dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
dom/media/webrtc/MediaEngineWebRTCAudio.cpp
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -1808,23 +1808,24 @@ MediaDecoder::DumpDebugInfo()
     str += readerStr;
   }
 
   if (!GetStateMachine()) {
     DUMP_LOG("%s", str.get());
     return;
   }
 
+  RefPtr<MediaDecoder> self = this;
   GetStateMachine()->RequestDebugInfo()->Then(
     AbstractThread::MainThread(), __func__,
-    [this, str] (const nsACString& aString) {
+    [this, self, str] (const nsACString& aString) {
       DUMP_LOG("%s", str.get());
       DUMP_LOG("%s", aString.Data());
     },
-    [this, str] () {
+    [this, self, str] () {
       DUMP_LOG("%s", str.get());
     });
 }
 
 RefPtr<MediaDecoder::DebugInfoPromise>
 MediaDecoder::RequestDebugInfo()
 {
   MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -2816,33 +2816,33 @@ nsresult MediaDecoderStateMachine::Init(
 
   mAudioQueueListener = AudioQueue().PopEvent().Connect(
     mTaskQueue, this, &MediaDecoderStateMachine::OnAudioPopped);
   mVideoQueueListener = VideoQueue().PopEvent().Connect(
     mTaskQueue, this, &MediaDecoderStateMachine::OnVideoPopped);
 
   mMetadataManager.Connect(mReader->TimedMetadataEvent(), OwnerThread());
 
+  RefPtr<MediaDecoderStateMachine> self = this;
   mOnMediaNotSeekable = mReader->OnMediaNotSeekable().Connect(
-    OwnerThread(), [this] () {
-      mMediaSeekable = false;
+    OwnerThread(), [self] () {
+      self->mMediaSeekable = false;
     });
 
   mMediaSink = CreateMediaSink(mAudioCaptured);
 
   aDecoder->RequestCDMProxy()->Then(
     OwnerThread(), __func__, this,
     &MediaDecoderStateMachine::OnCDMProxyReady,
     &MediaDecoderStateMachine::OnCDMProxyNotReady)
   ->Track(mCDMProxyPromise);
 
   nsresult rv = mReader->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  RefPtr<MediaDecoderStateMachine> self = this;
   OwnerThread()->Dispatch(NS_NewRunnableFunction([self] () {
     MOZ_ASSERT(!self->mStateObj);
     auto s = new DecodeMetadataState(self);
     self->mStateObj.reset(s);
     s->Enter();
   }));
 
   return NS_OK;
@@ -3107,29 +3107,30 @@ MediaDecoderStateMachine::RequestAudioDa
 {
   MOZ_ASSERT(OnTaskQueue());
   MOZ_ASSERT(IsAudioDecoding());
   MOZ_ASSERT(!IsRequestingAudioData());
   MOZ_ASSERT(!IsWaitingAudioData());
   SAMPLE_LOG("Queueing audio task - queued=%" PRIuSIZE ", decoder-queued=%" PRIuSIZE,
              AudioQueue().GetSize(), mReader->SizeOfAudioQueueInFrames());
 
+  RefPtr<MediaDecoderStateMachine> self = this;
   mReader->RequestAudioData()->Then(
     OwnerThread(), __func__,
-    [this] (MediaData* aAudio) {
+    [this, self] (MediaData* aAudio) {
       MOZ_ASSERT(aAudio);
       mAudioDataRequest.Complete();
       // audio->GetEndTime() is not always mono-increasing in chained ogg.
       mDecodedAudioEndTime =
         std::max(aAudio->GetEndTime(), mDecodedAudioEndTime);
       SAMPLE_LOG("OnAudioDecoded [%" PRId64 ",%" PRId64 "]", aAudio->mTime,
                  aAudio->GetEndTime());
       mStateObj->HandleAudioDecoded(aAudio);
     },
-    [this] (const MediaResult& aError) {
+    [this, self] (const MediaResult& aError) {
       SAMPLE_LOG("OnAudioNotDecoded aError=%" PRIu32, static_cast<uint32_t>(aError.Code()));
       mAudioDataRequest.Complete();
       switch (aError.Code()) {
         case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
           mStateObj->HandleWaitingForAudio();
           break;
         case NS_ERROR_DOM_MEDIA_CANCELED:
           mStateObj->HandleAudioCanceled();
@@ -3153,29 +3154,30 @@ MediaDecoderStateMachine::RequestVideoDa
   MOZ_ASSERT(!IsWaitingVideoData());
   SAMPLE_LOG(
     "Queueing video task - queued=%" PRIuSIZE ", decoder-queued=%" PRIoSIZE
     ", skip=%i, time=%" PRId64,
     VideoQueue().GetSize(), mReader->SizeOfVideoQueueInFrames(),
     aSkipToNextKeyframe, aCurrentTime.ToMicroseconds());
 
   TimeStamp videoDecodeStartTime = TimeStamp::Now();
+  RefPtr<MediaDecoderStateMachine> self = this;
   mReader->RequestVideoData(aSkipToNextKeyframe, aCurrentTime)->Then(
     OwnerThread(), __func__,
-    [this, videoDecodeStartTime] (MediaData* aVideo) {
+    [this, self, videoDecodeStartTime] (MediaData* aVideo) {
       MOZ_ASSERT(aVideo);
       mVideoDataRequest.Complete();
       // Handle abnormal or negative timestamps.
       mDecodedVideoEndTime =
         std::max(mDecodedVideoEndTime, aVideo->GetEndTime());
       SAMPLE_LOG("OnVideoDecoded [%" PRId64 ",%" PRId64 "]", aVideo->mTime,
                  aVideo->GetEndTime());
       mStateObj->HandleVideoDecoded(aVideo, videoDecodeStartTime);
     },
-    [this] (const MediaResult& aError) {
+    [this, self] (const MediaResult& aError) {
       SAMPLE_LOG("OnVideoNotDecoded aError=%" PRIu32 , static_cast<uint32_t>(aError.Code()));
       mVideoDataRequest.Complete();
       switch (aError.Code()) {
         case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
           mStateObj->HandleWaitingForVideo();
           break;
         case NS_ERROR_DOM_MEDIA_CANCELED:
           mStateObj->HandleVideoCanceled();
@@ -3189,39 +3191,40 @@ MediaDecoderStateMachine::RequestVideoDa
     })->Track(mVideoDataRequest);
 }
 
 void
 MediaDecoderStateMachine::WaitForData(MediaData::Type aType)
 {
   MOZ_ASSERT(OnTaskQueue());
   MOZ_ASSERT(aType == MediaData::AUDIO_DATA || aType == MediaData::VIDEO_DATA);
+  RefPtr<MediaDecoderStateMachine> self = this;
   if (aType == MediaData::AUDIO_DATA) {
     mReader->WaitForData(MediaData::AUDIO_DATA)->Then(
       OwnerThread(), __func__,
-      [this] (MediaData::Type aType) {
-        mAudioWaitRequest.Complete();
+      [self] (MediaData::Type aType) {
+        self->mAudioWaitRequest.Complete();
         MOZ_ASSERT(aType == MediaData::AUDIO_DATA);
-        mStateObj->HandleAudioWaited(aType);
+        self->mStateObj->HandleAudioWaited(aType);
       },
-      [this] (const WaitForDataRejectValue& aRejection) {
-        mAudioWaitRequest.Complete();
-        DecodeError(NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA);
+      [self] (const WaitForDataRejectValue& aRejection) {
+        self->mAudioWaitRequest.Complete();
+        self->DecodeError(NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA);
       })->Track(mAudioWaitRequest);
   } else {
     mReader->WaitForData(MediaData::VIDEO_DATA)->Then(
       OwnerThread(), __func__,
-      [this] (MediaData::Type aType) {
-        mVideoWaitRequest.Complete();
+      [self] (MediaData::Type aType) {
+        self->mVideoWaitRequest.Complete();
         MOZ_ASSERT(aType == MediaData::VIDEO_DATA);
-        mStateObj->HandleVideoWaited(aType);
+        self->mStateObj->HandleVideoWaited(aType);
       },
-      [this] (const WaitForDataRejectValue& aRejection) {
-        mVideoWaitRequest.Complete();
-        DecodeError(NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA);
+      [self] (const WaitForDataRejectValue& aRejection) {
+        self->mVideoWaitRequest.Complete();
+        self->DecodeError(NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA);
       })->Track(mVideoWaitRequest);
   }
 }
 
 void
 MediaDecoderStateMachine::StartMediaSink()
 {
   MOZ_ASSERT(OnTaskQueue());
@@ -3572,19 +3575,20 @@ MediaDecoderStateMachine::ScheduleStateM
     return;
   }
 
   TimeStamp now = TimeStamp::Now();
   TimeStamp target = now + TimeDuration::FromMicroseconds(aMicroseconds);
 
   // It is OK to capture 'this' without causing UAF because the callback
   // always happens before shutdown.
-  mDelayedScheduler.Ensure(target, [this] () {
-    mDelayedScheduler.CompleteRequest();
-    RunStateMachine();
+  RefPtr<MediaDecoderStateMachine> self = this;
+  mDelayedScheduler.Ensure(target, [self] () {
+    self->mDelayedScheduler.CompleteRequest();
+    self->RunStateMachine();
   }, [] () {
     MOZ_DIAGNOSTIC_ASSERT(false);
   });
 }
 
 bool MediaDecoderStateMachine::OnTaskQueue() const
 {
   return OwnerThread()->IsCurrentThreadIn();
@@ -3791,18 +3795,19 @@ MediaDecoderStateMachine::GetDebugInfo()
          + mMediaSink->GetDebugInfo();
 }
 
 RefPtr<MediaDecoder::DebugInfoPromise>
 MediaDecoderStateMachine::RequestDebugInfo()
 {
   using PromiseType = MediaDecoder::DebugInfoPromise;
   RefPtr<PromiseType::Private> p = new PromiseType::Private(__func__);
-  OwnerThread()->Dispatch(NS_NewRunnableFunction([this, p] () {
-    p->Resolve(GetDebugInfo(), __func__);
+  RefPtr<MediaDecoderStateMachine> self = this;
+  OwnerThread()->Dispatch(NS_NewRunnableFunction([self, p] () {
+    p->Resolve(self->GetDebugInfo(), __func__);
   }), AbstractThread::AssertDispatchSuccess, AbstractThread::TailDispatch);
   return p.forget();
 }
 
 void MediaDecoderStateMachine::AddOutputStream(ProcessedMediaStream* aStream,
                                                bool aFinishWhenEnded)
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -2290,33 +2290,33 @@ if (privileged) {
       Preferences::GetBool("media.navigator.streams.fake");
 
   bool askPermission =
       (!privileged || Preferences::GetBool("media.navigator.permission.force")) &&
       (!fake || Preferences::GetBool("media.navigator.permission.fake"));
 
   RefPtr<PledgeSourceSet> p = EnumerateDevicesImpl(windowID, videoType,
                                                    audioType, fake);
-  p->Then([this, onSuccess, onFailure, windowID, c, listener, askPermission,
+  RefPtr<MediaManager> self = this;
+  p->Then([self, onSuccess, onFailure, windowID, c, listener, askPermission,
            prefs, isHTTPS, callID, principalInfo,
            isChrome](SourceSet*& aDevices) mutable {
 
     RefPtr<Refcountable<UniquePtr<SourceSet>>> devices(
          new Refcountable<UniquePtr<SourceSet>>(aDevices)); // grab result
 
-    // Ensure that the captured 'this' pointer and our windowID are still good.
-    if (!MediaManager::Exists() ||
-        !nsGlobalWindow::GetInnerWindowWithId(windowID)) {
+    // Ensure that our windowID is still good.
+    if (!nsGlobalWindow::GetInnerWindowWithId(windowID)) {
       return;
     }
 
     // Apply any constraints. This modifies the passed-in list.
-    RefPtr<PledgeChar> p2 = SelectSettings(c, isChrome, devices);
-
-    p2->Then([this, onSuccess, onFailure, windowID, c,
+    RefPtr<PledgeChar> p2 = self->SelectSettings(c, isChrome, devices);
+
+    p2->Then([self, onSuccess, onFailure, windowID, c,
               listener, askPermission, prefs, isHTTPS, callID, principalInfo,
               isChrome, devices](const char*& badConstraint) mutable {
 
       // Ensure that the captured 'this' pointer and our windowID are still good.
       auto* globalWindow = nsGlobalWindow::GetInnerWindowWithId(windowID);
       RefPtr<nsPIDOMWindowInner> window = globalWindow ? globalWindow->AsInner()
                                                        : nullptr;
       if (!MediaManager::Exists() || !window) {
@@ -2354,23 +2354,23 @@ if (privileged) {
       // Pass callbacks and MediaStreamListener along to GetUserMediaTask.
       RefPtr<GetUserMediaTask> task (new GetUserMediaTask(c, onSuccess.forget(),
                                                           onFailure.forget(),
                                                           windowID, listener,
                                                           prefs, principalInfo,
                                                           isChrome,
                                                           devices->release()));
       // Store the task w/callbacks.
-      mActiveCallbacks.Put(callID, task.forget());
+      self->mActiveCallbacks.Put(callID, task.forget());
 
       // Add a WindowID cross-reference so OnNavigation can tear things down
       nsTArray<nsString>* array;
-      if (!mCallIds.Get(windowID, &array)) {
+      if (!self->mCallIds.Get(windowID, &array)) {
         array = new nsTArray<nsString>();
-        mCallIds.Put(windowID, array);
+        self->mCallIds.Put(windowID, array);
       }
       array->AppendElement(callID);
 
       nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
       if (!askPermission) {
         obs->NotifyObservers(devicesCopy, "getUserMedia:privileged:allow",
                              callID.BeginReading());
       } else {
@@ -2997,17 +2997,19 @@ MediaManager::Shutdown()
   // Post ShutdownTask to execute on mMediaThread and pass in a lambda
   // callback to be executed back on this thread once it is done.
   //
   // The lambda callback "captures" the 'this' pointer for member access.
   // This is safe since this is guaranteed to be here since sSingleton isn't
   // cleared until the lambda function clears it.
 
   // note that this == sSingleton
-  RefPtr<MediaManager> that(sSingleton);
+  MOZ_ASSERT(this == sSingleton);
+  RefPtr<MediaManager> that = this;
+
   // Release the backend (and call Shutdown()) from within the MediaManager thread
   // Don't use MediaManager::PostTask() because we're sInShutdown=true here!
   RefPtr<ShutdownTask> shutdown = new ShutdownTask(this,
       media::NewRunnableFrom([this, that]() mutable {
     LOG(("MediaManager shutdown lambda running, releasing MediaManager singleton and thread"));
     if (mMediaThread) {
       mMediaThread->Stop();
     }
--- a/dom/media/mediasink/DecodedStream.cpp
+++ b/dom/media/mediasink/DecodedStream.cpp
@@ -65,19 +65,20 @@ public:
   void DoNotifyFinished()
   {
     MOZ_ASSERT(NS_IsMainThread());
     mFinishPromise.ResolveIfExists(true, __func__);
   }
 
   void Forget()
   {
-    mAbstractMainThread->Dispatch(NS_NewRunnableFunction([this] () {
+    RefPtr<DecodedStreamGraphListener> self = this;
+    mAbstractMainThread->Dispatch(NS_NewRunnableFunction([self] () {
       MOZ_ASSERT(NS_IsMainThread());
-      mFinishPromise.ResolveIfExists(true, __func__);
+      self->mFinishPromise.ResolveIfExists(true, __func__);
     }));
     MutexAutoLock lock(mMutex);
     mStream = nullptr;
   }
 
   MediaEventSource<int64_t>& OnOutput()
   {
     return mOnOutput;
--- a/dom/media/ogg/OggDemuxer.cpp
+++ b/dom/media/ogg/OggDemuxer.cpp
@@ -123,17 +123,18 @@ OggDemuxer::~OggDemuxer()
 {
   MOZ_COUNT_DTOR(OggDemuxer);
   Reset(TrackInfo::kAudioTrack);
   Reset(TrackInfo::kVideoTrack);
   if (HasAudio() || HasVideo()) {
     // If we were able to initialize our decoders, report whether we encountered
     // a chained stream or not.
     bool isChained = mIsChained;
-    nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction([=]() -> void {
+    RefPtr<OggDemuxer> self = this;
+    nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction([this, self, isChained]() -> void {
       OGG_DEBUG("Reporting telemetry MEDIA_OGG_LOADED_IS_CHAINED=%d", isChained);
       Telemetry::Accumulate(Telemetry::HistogramID::MEDIA_OGG_LOADED_IS_CHAINED, isChained);
     });
     // Non-DocGroup version of AbstractThread::MainThread is fine for Telemetry.
     AbstractThread::MainThread()->Dispatch(task.forget());
   }
 }
 
--- a/dom/media/systemservices/CamerasChild.cpp
+++ b/dom/media/systemservices/CamerasChild.cpp
@@ -279,35 +279,37 @@ CamerasChild::DispatchToParent(nsIRunnab
 
 int
 CamerasChild::NumberOfCapabilities(CaptureEngine aCapEngine,
                                    const char* deviceUniqueIdUTF8)
 {
   LOG((__PRETTY_FUNCTION__));
   LOG(("NumberOfCapabilities for %s", deviceUniqueIdUTF8));
   nsCString unique_id(deviceUniqueIdUTF8);
+  RefPtr<CamerasChild> self = this;
   nsCOMPtr<nsIRunnable> runnable =
-    media::NewRunnableFrom([this, aCapEngine, unique_id]() -> nsresult {
-      if (this->SendNumberOfCapabilities(aCapEngine, unique_id)) {
+    media::NewRunnableFrom([self, aCapEngine, unique_id]() -> nsresult {
+      if (self->SendNumberOfCapabilities(aCapEngine, unique_id)) {
         return NS_OK;
       }
       return NS_ERROR_FAILURE;
     });
   LockAndDispatch<> dispatcher(this, __func__, runnable, 0, mReplyInteger);
   LOG(("Capture capability count: %d", dispatcher.ReturnValue()));
   return dispatcher.ReturnValue();
 }
 
 int
 CamerasChild::NumberOfCaptureDevices(CaptureEngine aCapEngine)
 {
   LOG((__PRETTY_FUNCTION__));
+  RefPtr<CamerasChild> self = this;
   nsCOMPtr<nsIRunnable> runnable =
-    media::NewRunnableFrom([this, aCapEngine]() -> nsresult {
-      if (this->SendNumberOfCaptureDevices(aCapEngine)) {
+    media::NewRunnableFrom([self, aCapEngine]() -> nsresult {
+      if (self->SendNumberOfCaptureDevices(aCapEngine)) {
         return NS_OK;
       }
       return NS_ERROR_FAILURE;
     });
   LockAndDispatch<> dispatcher(this, __func__, runnable, 0, mReplyInteger);
   LOG(("Capture Devices: %d", dispatcher.ReturnValue()));
   return dispatcher.ReturnValue();
 }
@@ -323,19 +325,20 @@ CamerasChild::RecvReplyNumberOfCaptureDe
   monitor.Notify();
   return IPC_OK();
 }
 
 int
 CamerasChild::EnsureInitialized(CaptureEngine aCapEngine)
 {
   LOG((__PRETTY_FUNCTION__));
+  RefPtr<CamerasChild> self = this;
   nsCOMPtr<nsIRunnable> runnable =
-    media::NewRunnableFrom([this, aCapEngine]() -> nsresult {
-      if (this->SendEnsureInitialized(aCapEngine)) {
+    media::NewRunnableFrom([self, aCapEngine]() -> nsresult {
+      if (self->SendEnsureInitialized(aCapEngine)) {
         return NS_OK;
       }
       return NS_ERROR_FAILURE;
     });
   LockAndDispatch<> dispatcher(this, __func__, runnable, 0, mReplyInteger);
   LOG(("Capture Devices: %d", dispatcher.ReturnValue()));
   return dispatcher.ReturnValue();
 }
@@ -343,19 +346,20 @@ CamerasChild::EnsureInitialized(CaptureE
 int
 CamerasChild::GetCaptureCapability(CaptureEngine aCapEngine,
                                    const char* unique_idUTF8,
                                    const unsigned int capability_number,
                                    webrtc::VideoCaptureCapability& capability)
 {
   LOG(("GetCaptureCapability: %s %d", unique_idUTF8, capability_number));
   nsCString unique_id(unique_idUTF8);
+  RefPtr<CamerasChild> self = this;
   nsCOMPtr<nsIRunnable> runnable =
-    media::NewRunnableFrom([this, aCapEngine, unique_id, capability_number]() -> nsresult {
-      if (this->SendGetCaptureCapability(aCapEngine, unique_id, capability_number)) {
+    media::NewRunnableFrom([self, aCapEngine, unique_id, capability_number]() -> nsresult {
+      if (self->SendGetCaptureCapability(aCapEngine, unique_id, capability_number)) {
         return NS_OK;
       }
       return NS_ERROR_FAILURE;
     });
   LockAndDispatch<> dispatcher(this, __func__, runnable);
   if (dispatcher.Success()) {
     capability = mReplyCapability;
   }
@@ -384,19 +388,20 @@ int
 CamerasChild::GetCaptureDevice(CaptureEngine aCapEngine,
                                unsigned int list_number, char* device_nameUTF8,
                                const unsigned int device_nameUTF8Length,
                                char* unique_idUTF8,
                                const unsigned int unique_idUTF8Length,
                                bool* scary)
 {
   LOG((__PRETTY_FUNCTION__));
+  RefPtr<CamerasChild> self = this;
   nsCOMPtr<nsIRunnable> runnable =
-    media::NewRunnableFrom([this, aCapEngine, list_number]() -> nsresult {
-      if (this->SendGetCaptureDevice(aCapEngine, list_number)) {
+    media::NewRunnableFrom([self, aCapEngine, list_number]() -> nsresult {
+      if (self->SendGetCaptureDevice(aCapEngine, list_number)) {
         return NS_OK;
       }
       return NS_ERROR_FAILURE;
     });
   LockAndDispatch<> dispatcher(this, __func__, runnable);
   if (dispatcher.Success()) {
     base::strlcpy(device_nameUTF8, mReplyDeviceName.get(), device_nameUTF8Length);
     base::strlcpy(unique_idUTF8, mReplyDeviceID.get(), unique_idUTF8Length);
@@ -428,19 +433,20 @@ int
 CamerasChild::AllocateCaptureDevice(CaptureEngine aCapEngine,
                                     const char* unique_idUTF8,
                                     const unsigned int unique_idUTF8Length,
                                     int& aStreamId,
                                     const mozilla::ipc::PrincipalInfo& aPrincipalInfo)
 {
   LOG((__PRETTY_FUNCTION__));
   nsCString unique_id(unique_idUTF8);
+  RefPtr<CamerasChild> self = this;
   nsCOMPtr<nsIRunnable> runnable =
-    media::NewRunnableFrom([this, aCapEngine, unique_id, aPrincipalInfo]() -> nsresult {
-      if (this->SendAllocateCaptureDevice(aCapEngine, unique_id, aPrincipalInfo)) {
+    media::NewRunnableFrom([self, aCapEngine, unique_id, aPrincipalInfo]() -> nsresult {
+      if (self->SendAllocateCaptureDevice(aCapEngine, unique_id, aPrincipalInfo)) {
         return NS_OK;
       }
       return NS_ERROR_FAILURE;
     });
   LockAndDispatch<> dispatcher(this, __func__, runnable);
   if (dispatcher.Success()) {
     LOG(("Capture Device allocated: %d", mReplyInteger));
     aStreamId = mReplyInteger;
@@ -461,19 +467,20 @@ CamerasChild::RecvReplyAllocateCaptureDe
   return IPC_OK();
 }
 
 int
 CamerasChild::ReleaseCaptureDevice(CaptureEngine aCapEngine,
                                    const int capture_id)
 {
   LOG((__PRETTY_FUNCTION__));
+  RefPtr<CamerasChild> self = this;
   nsCOMPtr<nsIRunnable> runnable =
-    media::NewRunnableFrom([this, aCapEngine, capture_id]() -> nsresult {
-      if (this->SendReleaseCaptureDevice(aCapEngine, capture_id)) {
+    media::NewRunnableFrom([self, aCapEngine, capture_id]() -> nsresult {
+      if (self->SendReleaseCaptureDevice(aCapEngine, capture_id)) {
         return NS_OK;
       }
       return NS_ERROR_FAILURE;
     });
   LockAndDispatch<> dispatcher(this, __func__, runnable);
   return dispatcher.ReturnValue();
 }
 
@@ -512,34 +519,36 @@ CamerasChild::StartCapture(CaptureEngine
   AddCallback(aCapEngine, capture_id, cb);
   VideoCaptureCapability capCap(webrtcCaps.width,
                            webrtcCaps.height,
                            webrtcCaps.maxFPS,
                            webrtcCaps.expectedCaptureDelay,
                            webrtcCaps.rawType,
                            webrtcCaps.codecType,
                            webrtcCaps.interlaced);
+  RefPtr<CamerasChild> self = this;
   nsCOMPtr<nsIRunnable> runnable =
-    media::NewRunnableFrom([this, aCapEngine, capture_id, capCap]() -> nsresult {
-      if (this->SendStartCapture(aCapEngine, capture_id, capCap)) {
+    media::NewRunnableFrom([self, aCapEngine, capture_id, capCap]() -> nsresult {
+      if (self->SendStartCapture(aCapEngine, capture_id, capCap)) {
         return NS_OK;
       }
       return NS_ERROR_FAILURE;
     });
   LockAndDispatch<> dispatcher(this, __func__, runnable);
   return dispatcher.ReturnValue();
 }
 
 int
 CamerasChild::StopCapture(CaptureEngine aCapEngine, const int capture_id)
 {
   LOG((__PRETTY_FUNCTION__));
+  RefPtr<CamerasChild> self = this;
   nsCOMPtr<nsIRunnable> runnable =
-    media::NewRunnableFrom([this, aCapEngine, capture_id]() -> nsresult {
-      if (this->SendStopCapture(aCapEngine, capture_id)) {
+    media::NewRunnableFrom([self, aCapEngine, capture_id]() -> nsresult {
+      if (self->SendStopCapture(aCapEngine, capture_id)) {
         return NS_OK;
       }
       return NS_ERROR_FAILURE;
     });
   LockAndDispatch<> dispatcher(this, __func__, runnable);
   if (dispatcher.Success()) {
     RemoveCallback(aCapEngine, capture_id);
   }
@@ -594,21 +603,22 @@ CamerasChild::ShutdownParent()
   {
     MonitorAutoLock monitor(mReplyMonitor);
     mIPCIsAlive = false;
     monitor.NotifyAll();
   }
   if (CamerasSingleton::Thread()) {
     LOG(("Dispatching actor deletion"));
     // Delete the parent actor.
+    RefPtr<CamerasChild> self = this;
     RefPtr<Runnable> deleteRunnable =
       // CamerasChild (this) will remain alive and is only deleted by the
       // IPC layer when SendAllDone returns.
-      media::NewRunnableFrom([this]() -> nsresult {
-        Unused << this->SendAllDone();
+      media::NewRunnableFrom([self]() -> nsresult {
+        Unused << self->SendAllDone();
         return NS_OK;
       });
     CamerasSingleton::Thread()->Dispatch(deleteRunnable, NS_DISPATCH_NORMAL);
   } else {
     LOG(("ShutdownParent called without PBackground thread"));
   }
 }
 
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
@@ -311,20 +311,20 @@ void
 MediaEngineRemoteVideoSource::SetLastCapability(
     const webrtc::CaptureCapability& aCapability)
 {
   mLastCapability = mCapability;
 
   webrtc::CaptureCapability cap = aCapability;
   RefPtr<MediaEngineRemoteVideoSource> that = this;
 
-  NS_DispatchToMainThread(media::NewRunnableFrom([this, that, cap]() mutable {
-    mSettings.mWidth.Value() = cap.width;
-    mSettings.mHeight.Value() = cap.height;
-    mSettings.mFrameRate.Value() = cap.maxFPS;
+  NS_DispatchToMainThread(media::NewRunnableFrom([that, cap]() mutable {
+    that->mSettings.mWidth.Value() = cap.width;
+    that->mSettings.mHeight.Value() = cap.height;
+    that->mSettings.mFrameRate.Value() = cap.maxFPS;
     return NS_OK;
   }));
 }
 
 void
 MediaEngineRemoteVideoSource::NotifyPull(MediaStreamGraph* aGraph,
                                          SourceMediaStream* aSource,
                                          TrackID aID, StreamTime aDesiredTime,
--- a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
@@ -368,20 +368,20 @@ MediaEngineWebRTCMicrophoneSource::Updat
 void
 MediaEngineWebRTCMicrophoneSource::SetLastPrefs(
     const MediaEnginePrefs& aPrefs)
 {
   mLastPrefs = aPrefs;
 
   RefPtr<MediaEngineWebRTCMicrophoneSource> that = this;
 
-  NS_DispatchToMainThread(media::NewRunnableFrom([this, that, aPrefs]() mutable {
-    mSettings.mEchoCancellation.Value() = aPrefs.mAecOn;
-    mSettings.mMozAutoGainControl.Value() = aPrefs.mAgcOn;
-    mSettings.mMozNoiseSuppression.Value() = aPrefs.mNoiseOn;
+  NS_DispatchToMainThread(media::NewRunnableFrom([that, aPrefs]() mutable {
+    that->mSettings.mEchoCancellation.Value() = aPrefs.mAecOn;
+    that->mSettings.mMozAutoGainControl.Value() = aPrefs.mAgcOn;
+    that->mSettings.mMozNoiseSuppression.Value() = aPrefs.mNoiseOn;
     return NS_OK;
   }));
 }
 
 
 nsresult
 MediaEngineWebRTCMicrophoneSource::Deallocate(AllocationHandle* aHandle)
 {