Bug 1328130. Part 2 - remove MozPromiseRequestHolder::Begin(). draft
authorJW Wang <jwwang@mozilla.com>
Wed, 11 Jan 2017 16:33:29 +0800
changeset 460531 b70a8842085baa6c0a67774f88ba116dcc02ba8f
parent 460530 ceec017e7813760e08fb195a60376f2d37cd2eec
child 460532 27d73e7fdfb66dbfef6847999737199ec23eca3a
push id41407
push userjwwang@mozilla.com
push dateFri, 13 Jan 2017 06:45:41 +0000
bugs1328130
milestone53.0a1
Bug 1328130. Part 2 - remove MozPromiseRequestHolder::Begin(). MozReview-Commit-ID: JL27n0Era6E
dom/media/MediaDecoder.cpp
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaFormatReader.cpp
dom/media/MediaTimer.h
dom/media/android/AndroidMediaReader.cpp
dom/media/gtest/TestMozPromise.cpp
dom/media/mediasink/AudioSinkWrapper.cpp
dom/media/mediasink/VideoSink.cpp
dom/media/mediasource/SourceBuffer.cpp
dom/media/mediasource/TrackBuffersManager.cpp
dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
dom/media/platforms/wrappers/FuzzingWrapper.cpp
dom/media/platforms/wrappers/H264Converter.cpp
xpcom/threads/MozPromise.h
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -747,20 +747,20 @@ MediaDecoder::DiscardOngoingSeekIfExists
 
 void
 MediaDecoder::CallSeek(const SeekTarget& aTarget, dom::Promise* aPromise)
 {
   MOZ_ASSERT(NS_IsMainThread());
   DiscardOngoingSeekIfExists();
 
   mSeekDOMPromise = aPromise;
-  mSeekRequest.Begin(
-    mDecoderStateMachine->InvokeSeek(aTarget)
-    ->Then(AbstractThread::MainThread(), __func__, this,
-           &MediaDecoder::OnSeekResolved, &MediaDecoder::OnSeekRejected));
+  mDecoderStateMachine->InvokeSeek(aTarget)
+  ->Then(AbstractThread::MainThread(), __func__, this,
+         &MediaDecoder::OnSeekResolved, &MediaDecoder::OnSeekRejected)
+  ->Track(mSeekRequest);
 }
 
 double
 MediaDecoder::GetCurrentTime()
 {
   MOZ_ASSERT(NS_IsMainThread());
   return mLogicalPosition;
 }
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -335,24 +335,25 @@ public:
     MOZ_ASSERT(!mMetadataRequest.Exists());
     SLOG("Dispatching AsyncReadMetadata");
 
     // Set mode to METADATA since we are about to read metadata.
     Resource()->SetReadMode(MediaCacheStream::MODE_METADATA);
 
     // We disconnect mMetadataRequest in Exit() so it is fine to capture
     // a raw pointer here.
-    mMetadataRequest.Begin(Reader()->ReadMetadata()
+    Reader()->ReadMetadata()
       ->Then(OwnerThread(), __func__,
         [this] (MetadataHolder* aMetadata) {
           OnMetadataRead(aMetadata);
         },
         [this] (const MediaResult& aError) {
           OnMetadataNotRead(aError);
-        }));
+        })
+      ->Track(mMetadataRequest);
   }
 
   void Exit() override
   {
     mMetadataRequest.DisconnectIfExists();
   }
 
   State GetState() const override
@@ -1103,24 +1104,25 @@ public:
 
     RequestVideoData();
   }
 
 private:
   void DemuxerSeek()
   {
     // Request the demuxer to perform seek.
-    mSeekRequest.Begin(Reader()->Seek(mSeekJob.mTarget.ref())
+    Reader()->Seek(mSeekJob.mTarget.ref())
       ->Then(OwnerThread(), __func__,
              [this] (const media::TimeUnit& aUnit) {
                OnSeekResolved(aUnit);
              },
              [this] (const SeekRejectValue& aReject) {
                OnSeekRejected(aReject);
-             }));
+             })
+      ->Track(mSeekRequest);
   }
 
   void DoSeek() override
   {
     mDoneAudioSeeking = !Info().HasAudio() || mSeekJob.mTarget->IsVideoOnly();
     mDoneVideoSeeking = !Info().HasVideo();
 
     if (mSeekJob.mTarget->IsVideoOnly()) {
@@ -1186,30 +1188,28 @@ private:
     if (aReject.mError == NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA) {
       SLOG("OnSeekRejected reason=WAITING_FOR_DATA type=%d", aReject.mType);
       MOZ_ASSERT(!mMaster->IsRequestingAudioData());
       MOZ_ASSERT(!mMaster->IsRequestingVideoData());
       MOZ_ASSERT(!mMaster->IsWaitingAudioData());
       MOZ_ASSERT(!mMaster->IsWaitingVideoData());
       // Fire 'waiting' to notify the player that we are waiting for data.
       mMaster->UpdateNextFrameStatus(MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_SEEKING);
-      mWaitRequest.Begin(
-        Reader()->WaitForData(aReject.mType)->Then(
-          OwnerThread(), __func__,
-          [this] (MediaData::Type aType) {
-            SLOG("OnSeekRejected wait promise resolved");
-            mWaitRequest.Complete();
-            DemuxerSeek();
-          },
-          [this] (const WaitForDataRejectValue& aRejection) {
-            SLOG("OnSeekRejected wait promise rejected");
-            mWaitRequest.Complete();
-            mMaster->DecodeError(NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA);
-          })
-      );
+      Reader()->WaitForData(aReject.mType)->Then(
+        OwnerThread(), __func__,
+        [this] (MediaData::Type aType) {
+          SLOG("OnSeekRejected wait promise resolved");
+          mWaitRequest.Complete();
+          DemuxerSeek();
+        },
+        [this] (const WaitForDataRejectValue& aRejection) {
+          SLOG("OnSeekRejected wait promise rejected");
+          mWaitRequest.Complete();
+          mMaster->DecodeError(NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA);
+        })->Track(mWaitRequest);
       return;
     }
 
     MOZ_ASSERT(NS_FAILED(aReject.mError), "Cancels should also disconnect mSeekRequest");
     mMaster->DecodeError(aReject.mError);
   }
 
   void RequestAudioData()
@@ -2723,20 +2723,21 @@ nsresult MediaDecoderStateMachine::Init(
 
   mOnMediaNotSeekable = mReader->OnMediaNotSeekable().Connect(
     OwnerThread(), [this] () {
       mMediaSeekable = false;
     });
 
   mMediaSink = CreateMediaSink(mAudioCaptured);
 
-  mCDMProxyPromise.Begin(aDecoder->RequestCDMProxy()->Then(
+  aDecoder->RequestCDMProxy()->Then(
     OwnerThread(), __func__, this,
     &MediaDecoderStateMachine::OnCDMProxyReady,
-    &MediaDecoderStateMachine::OnCDMProxyNotReady));
+    &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->mState == DECODER_STATE_DECODING_METADATA);
     MOZ_ASSERT(!self->mStateObj);
@@ -3003,149 +3004,143 @@ MediaDecoderStateMachine::RequestAudioDa
 {
   MOZ_ASSERT(OnTaskQueue());
   MOZ_ASSERT(IsAudioDecoding());
   MOZ_ASSERT(!IsRequestingAudioData());
   MOZ_ASSERT(!IsWaitingAudioData());
   SAMPLE_LOG("Queueing audio task - queued=%i, decoder-queued=%o",
              AudioQueue().GetSize(), mReader->SizeOfAudioQueueInFrames());
 
-  mAudioDataRequest.Begin(
-    mReader->RequestAudioData()->Then(
-      OwnerThread(), __func__,
-      [this] (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 [%lld,%lld]", aAudio->mTime, aAudio->GetEndTime());
-        mStateObj->HandleAudioDecoded(aAudio);
-      },
-      [this] (const MediaResult& aError) {
-        SAMPLE_LOG("OnAudioNotDecoded aError=%u", 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();
-            break;
-          case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
-            mStateObj->HandleEndOfAudio();
-            break;
-          default:
-            DecodeError(aError);
-        }
-      })
-  );
+  mReader->RequestAudioData()->Then(
+    OwnerThread(), __func__,
+    [this] (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 [%lld,%lld]", aAudio->mTime, aAudio->GetEndTime());
+      mStateObj->HandleAudioDecoded(aAudio);
+    },
+    [this] (const MediaResult& aError) {
+      SAMPLE_LOG("OnAudioNotDecoded aError=%u", 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();
+          break;
+        case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
+          mStateObj->HandleEndOfAudio();
+          break;
+        default:
+          DecodeError(aError);
+      }
+    })->Track(mAudioDataRequest);
 }
 
 void
 MediaDecoderStateMachine::RequestVideoData(bool aSkipToNextKeyframe,
                                            const media::TimeUnit& aCurrentTime)
 {
   MOZ_ASSERT(OnTaskQueue());
   MOZ_ASSERT(IsVideoDecoding());
   MOZ_ASSERT(!IsRequestingVideoData());
   MOZ_ASSERT(!IsWaitingVideoData());
   SAMPLE_LOG("Queueing video task - queued=%i, decoder-queued=%o, skip=%i, time=%lld",
              VideoQueue().GetSize(), mReader->SizeOfVideoQueueInFrames(), aSkipToNextKeyframe,
              aCurrentTime.ToMicroseconds());
 
   TimeStamp videoDecodeStartTime = TimeStamp::Now();
-  mVideoDataRequest.Begin(
-    mReader->RequestVideoData(aSkipToNextKeyframe, aCurrentTime)->Then(
-      OwnerThread(), __func__,
-      [this, videoDecodeStartTime] (MediaData* aVideo) {
-        MOZ_ASSERT(aVideo);
-        mVideoDataRequest.Complete();
-        // Handle abnormal or negative timestamps.
-        mDecodedVideoEndTime = std::max(mDecodedVideoEndTime, aVideo->GetEndTime());
-        SAMPLE_LOG("OnVideoDecoded [%lld,%lld]", aVideo->mTime, aVideo->GetEndTime());
-        mStateObj->HandleVideoDecoded(aVideo, videoDecodeStartTime);
-      },
-      [this] (const MediaResult& aError) {
-        SAMPLE_LOG("OnVideoNotDecoded aError=%u", 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();
-            break;
-          case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
-            mStateObj->HandleEndOfVideo();
-            break;
-          default:
-            DecodeError(aError);
-        }
-      })
-  );
+  mReader->RequestVideoData(aSkipToNextKeyframe, aCurrentTime)->Then(
+    OwnerThread(), __func__,
+    [this, videoDecodeStartTime] (MediaData* aVideo) {
+      MOZ_ASSERT(aVideo);
+      mVideoDataRequest.Complete();
+      // Handle abnormal or negative timestamps.
+      mDecodedVideoEndTime = std::max(mDecodedVideoEndTime, aVideo->GetEndTime());
+      SAMPLE_LOG("OnVideoDecoded [%lld,%lld]", aVideo->mTime, aVideo->GetEndTime());
+      mStateObj->HandleVideoDecoded(aVideo, videoDecodeStartTime);
+    },
+    [this] (const MediaResult& aError) {
+      SAMPLE_LOG("OnVideoNotDecoded aError=%u", 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();
+          break;
+        case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
+          mStateObj->HandleEndOfVideo();
+          break;
+        default:
+          DecodeError(aError);
+      }
+    })->Track(mVideoDataRequest);
 }
 
 void
 MediaDecoderStateMachine::WaitForData(MediaData::Type aType)
 {
   MOZ_ASSERT(OnTaskQueue());
   MOZ_ASSERT(aType == MediaData::AUDIO_DATA || aType == MediaData::VIDEO_DATA);
   if (aType == MediaData::AUDIO_DATA) {
-    mAudioWaitRequest.Begin(
-      mReader->WaitForData(MediaData::AUDIO_DATA)->Then(
-        OwnerThread(), __func__,
-        [this] (MediaData::Type aType) {
-          mAudioWaitRequest.Complete();
-          MOZ_ASSERT(aType == MediaData::AUDIO_DATA);
-          mStateObj->HandleAudioWaited(aType);
-        },
-        [this] (const WaitForDataRejectValue& aRejection) {
-          mAudioWaitRequest.Complete();
-          DecodeError(NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA);
-        })
-    );
+    mReader->WaitForData(MediaData::AUDIO_DATA)->Then(
+      OwnerThread(), __func__,
+      [this] (MediaData::Type aType) {
+        mAudioWaitRequest.Complete();
+        MOZ_ASSERT(aType == MediaData::AUDIO_DATA);
+        mStateObj->HandleAudioWaited(aType);
+      },
+      [this] (const WaitForDataRejectValue& aRejection) {
+        mAudioWaitRequest.Complete();
+        DecodeError(NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA);
+      })->Track(mAudioWaitRequest);
   } else {
-    mVideoWaitRequest.Begin(
-      mReader->WaitForData(MediaData::VIDEO_DATA)->Then(
-        OwnerThread(), __func__,
-        [this] (MediaData::Type aType) {
-          mVideoWaitRequest.Complete();
-          MOZ_ASSERT(aType == MediaData::VIDEO_DATA);
-          mStateObj->HandleVideoWaited(aType);
-        },
-        [this] (const WaitForDataRejectValue& aRejection) {
-          mVideoWaitRequest.Complete();
-          DecodeError(NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA);
-        })
-    );
+    mReader->WaitForData(MediaData::VIDEO_DATA)->Then(
+      OwnerThread(), __func__,
+      [this] (MediaData::Type aType) {
+        mVideoWaitRequest.Complete();
+        MOZ_ASSERT(aType == MediaData::VIDEO_DATA);
+        mStateObj->HandleVideoWaited(aType);
+      },
+      [this] (const WaitForDataRejectValue& aRejection) {
+        mVideoWaitRequest.Complete();
+        DecodeError(NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA);
+      })->Track(mVideoWaitRequest);
   }
 }
 
 void
 MediaDecoderStateMachine::StartMediaSink()
 {
   MOZ_ASSERT(OnTaskQueue());
   if (!mMediaSink->IsStarted()) {
     mAudioCompleted = false;
     mMediaSink->Start(GetMediaTime(), Info());
 
     auto videoPromise = mMediaSink->OnEnded(TrackInfo::kVideoTrack);
     auto audioPromise = mMediaSink->OnEnded(TrackInfo::kAudioTrack);
 
     if (audioPromise) {
-      mMediaSinkAudioPromise.Begin(audioPromise->Then(
+      audioPromise->Then(
         OwnerThread(), __func__, this,
         &MediaDecoderStateMachine::OnMediaSinkAudioComplete,
-        &MediaDecoderStateMachine::OnMediaSinkAudioError));
+        &MediaDecoderStateMachine::OnMediaSinkAudioError)
+      ->Track(mMediaSinkAudioPromise);
     }
     if (videoPromise) {
-      mMediaSinkVideoPromise.Begin(videoPromise->Then(
+      videoPromise->Then(
         OwnerThread(), __func__, this,
         &MediaDecoderStateMachine::OnMediaSinkVideoComplete,
-        &MediaDecoderStateMachine::OnMediaSinkVideoError));
+        &MediaDecoderStateMachine::OnMediaSinkVideoError)
+      ->Track(mMediaSinkVideoPromise);
     }
   }
 }
 
 bool
 MediaDecoderStateMachine::HasLowDecodedAudio()
 {
   MOZ_ASSERT(OnTaskQueue());
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -285,28 +285,28 @@ private:
 void
 MediaFormatReader::DecoderFactory::RunStage(TrackType aTrack)
 {
   auto& data = aTrack == TrackInfo::kAudioTrack ? mAudio : mVideo;
 
   switch (data.mStage) {
     case Stage::None: {
       MOZ_ASSERT(!data.mToken);
-      data.mTokenPromise.Begin(DecoderAllocPolicy::Instance(aTrack).Alloc()->Then(
+      DecoderAllocPolicy::Instance(aTrack).Alloc()->Then(
         mOwner->OwnerThread(), __func__,
         [this, &data, aTrack] (Token* aToken) {
           data.mTokenPromise.Complete();
           data.mToken = aToken;
           data.mStage = Stage::CreateDecoder;
           RunStage(aTrack);
         },
         [&data] () {
           data.mTokenPromise.Complete();
           data.mStage = Stage::None;
-        }));
+        })->Track(data.mTokenPromise);
       data.mStage = Stage::WaitForToken;
       break;
     }
 
     case Stage::WaitForToken: {
       MOZ_ASSERT(!data.mToken);
       MOZ_ASSERT(data.mTokenPromise.Exists());
       break;
@@ -404,34 +404,34 @@ MediaFormatReader::DecoderFactory::DoCre
 }
 
 void
 MediaFormatReader::DecoderFactory::DoInitDecoder(TrackType aTrack)
 {
   auto& ownerData = mOwner->GetDecoderData(aTrack);
   auto& data = aTrack == TrackInfo::kAudioTrack ? mAudio : mVideo;
 
-  data.mInitPromise.Begin(data.mDecoder->Init()->Then(
+  data.mDecoder->Init()->Then(
     mOwner->OwnerThread(), __func__,
     [this, &data, &ownerData] (TrackType aTrack) {
       data.mInitPromise.Complete();
       data.mStage = Stage::None;
       MutexAutoLock lock(ownerData.mMutex);
       ownerData.mDecoder = data.mDecoder.forget();
       ownerData.mDescription = ownerData.mDecoder->GetDescriptionName();
       mOwner->SetVideoDecodeThreshold();
       mOwner->ScheduleUpdate(aTrack);
     },
     [this, &data, aTrack] (MediaResult aError) {
       data.mInitPromise.Complete();
       data.mStage = Stage::None;
       data.mDecoder->Shutdown();
       data.mDecoder = nullptr;
       mOwner->NotifyError(aTrack, aError);
-    }));
+    })->Track(data.mInitPromise);
 }
 
 // DemuxerProxy ensures that the original main demuxer is only ever accessed
 // via its own dedicated task queue.
 // This ensure that the reader's taskqueue will never blocked while a demuxer
 // is itself blocked attempting to access the MediaCache or the MediaResource.
 class MediaFormatReader::DemuxerProxy
 {
@@ -972,20 +972,21 @@ MediaFormatReader::AsyncReadMetadata()
     RefPtr<MetadataHolder> metadata = new MetadataHolder();
     metadata->mInfo = mInfo;
     metadata->mTags = nullptr;
     return MetadataPromise::CreateAndResolve(metadata, __func__);
   }
 
   RefPtr<MetadataPromise> p = mMetadataPromise.Ensure(__func__);
 
-  mDemuxerInitRequest.Begin(mDemuxer->Init()
-                       ->Then(OwnerThread(), __func__, this,
-                              &MediaFormatReader::OnDemuxerInitDone,
-                              &MediaFormatReader::OnDemuxerInitFailed));
+  mDemuxer->Init()
+    ->Then(OwnerThread(), __func__, this,
+           &MediaFormatReader::OnDemuxerInitDone,
+           &MediaFormatReader::OnDemuxerInitFailed)
+    ->Track(mDemuxerInitRequest);
   return p;
 }
 
 void
 MediaFormatReader::OnDemuxerInitDone(nsresult)
 {
   MOZ_ASSERT(OnTaskQueue());
   mDemuxerInitRequest.Complete();
@@ -1272,19 +1273,20 @@ MediaFormatReader::DoDemuxVideo()
                 [self] (RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples) {
                   self->OnFirstDemuxCompleted(TrackInfo::kVideoTrack, aSamples);
                 },
                 [self] (const MediaResult& aError) {
                   self->OnFirstDemuxFailed(TrackInfo::kVideoTrack, aError);
                 });
   }
 
-  mVideo.mDemuxRequest.Begin(p->Then(OwnerThread(), __func__, this,
-                                     &MediaFormatReader::OnVideoDemuxCompleted,
-                                     &MediaFormatReader::OnVideoDemuxFailed));
+  p->Then(OwnerThread(), __func__, this,
+          &MediaFormatReader::OnVideoDemuxCompleted,
+          &MediaFormatReader::OnVideoDemuxFailed)
+   ->Track(mVideo.mDemuxRequest);
 }
 
 void
 MediaFormatReader::OnVideoDemuxCompleted(RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples)
 {
   LOGV("%d video samples demuxed (sid:%d)",
        aSamples->mSamples.Length(),
        aSamples->mSamples[0]->mTrackInfo ? aSamples->mSamples[0]->mTrackInfo->GetID() : 0);
@@ -1338,19 +1340,20 @@ MediaFormatReader::DoDemuxAudio()
                 [self] (RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples) {
                   self->OnFirstDemuxCompleted(TrackInfo::kAudioTrack, aSamples);
                 },
                 [self] (const MediaResult& aError) {
                   self->OnFirstDemuxFailed(TrackInfo::kAudioTrack, aError);
                 });
   }
 
-  mAudio.mDemuxRequest.Begin(p->Then(OwnerThread(), __func__, this,
-                                     &MediaFormatReader::OnAudioDemuxCompleted,
-                                     &MediaFormatReader::OnAudioDemuxFailed));
+  p->Then(OwnerThread(), __func__, this,
+          &MediaFormatReader::OnAudioDemuxCompleted,
+          &MediaFormatReader::OnAudioDemuxFailed)
+   ->Track(mAudio.mDemuxRequest);
 }
 
 void
 MediaFormatReader::OnAudioDemuxCompleted(RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples)
 {
   LOGV("%d audio samples demuxed (sid:%d)",
        aSamples->mSamples.Length(),
        aSamples->mSamples[0]->mTrackInfo ? aSamples->mSamples[0]->mTrackInfo->GetID() : 0);
@@ -1700,47 +1703,48 @@ MediaFormatReader::InternalSeek(TrackTyp
   LOG("%s internal seek to %f",
       TrackTypeToStr(aTrack), aTarget.Time().ToSeconds());
 
   auto& decoder = GetDecoderData(aTrack);
   decoder.Flush();
   decoder.ResetDemuxer();
   decoder.mTimeThreshold = Some(aTarget);
   RefPtr<MediaFormatReader> self = this;
-  decoder.mSeekRequest.Begin(decoder.mTrackDemuxer->Seek(decoder.mTimeThreshold.ref().Time())
-             ->Then(OwnerThread(), __func__,
-                    [self, aTrack] (media::TimeUnit aTime) {
-                      auto& decoder = self->GetDecoderData(aTrack);
-                      decoder.mSeekRequest.Complete();
-                      MOZ_ASSERT(decoder.mTimeThreshold,
-                                 "Seek promise must be disconnected when timethreshold is reset");
-                      decoder.mTimeThreshold.ref().mHasSeeked = true;
-                      self->SetVideoDecodeThreshold();
-                      self->ScheduleUpdate(aTrack);
-                    },
-                    [self, aTrack] (const MediaResult& aError) {
-                      auto& decoder = self->GetDecoderData(aTrack);
-                      decoder.mSeekRequest.Complete();
-                      switch (aError.Code()) {
-                        case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
-                          self->NotifyWaitingForData(aTrack);
-                          break;
-                        case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
-                          decoder.mTimeThreshold.reset();
-                          self->NotifyEndOfStream(aTrack);
-                          break;
-                        case NS_ERROR_DOM_MEDIA_CANCELED:
-                          decoder.mTimeThreshold.reset();
-                          break;
-                        default:
-                          decoder.mTimeThreshold.reset();
-                          self->NotifyError(aTrack, aError);
-                          break;
-                      }
-                    }));
+  decoder.mTrackDemuxer->Seek(decoder.mTimeThreshold.ref().Time())
+    ->Then(OwnerThread(), __func__,
+           [self, aTrack] (media::TimeUnit aTime) {
+             auto& decoder = self->GetDecoderData(aTrack);
+             decoder.mSeekRequest.Complete();
+             MOZ_ASSERT(decoder.mTimeThreshold,
+                        "Seek promise must be disconnected when timethreshold is reset");
+             decoder.mTimeThreshold.ref().mHasSeeked = true;
+             self->SetVideoDecodeThreshold();
+             self->ScheduleUpdate(aTrack);
+           },
+           [self, aTrack] (const MediaResult& aError) {
+             auto& decoder = self->GetDecoderData(aTrack);
+             decoder.mSeekRequest.Complete();
+             switch (aError.Code()) {
+               case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
+                 self->NotifyWaitingForData(aTrack);
+                 break;
+               case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
+                 decoder.mTimeThreshold.reset();
+                 self->NotifyEndOfStream(aTrack);
+                 break;
+               case NS_ERROR_DOM_MEDIA_CANCELED:
+                 decoder.mTimeThreshold.reset();
+                 break;
+               default:
+                 decoder.mTimeThreshold.reset();
+                 self->NotifyError(aTrack, aError);
+                 break;
+             }
+           })
+    ->Track(decoder.mSeekRequest);
 }
 
 void
 MediaFormatReader::DrainDecoder(TrackType aTrack)
 {
   MOZ_ASSERT(OnTaskQueue());
 
   auto& decoder = GetDecoderData(aTrack);
@@ -2192,20 +2196,21 @@ MediaFormatReader::SkipVideoDemuxToNextK
   // As such we can drop all already decoded samples and discard all pending
   // samples.
   // TODO: Ideally we should set mOutputRequested to false so that all pending
   // frames are dropped too. However, we can't do such thing as the code assumes
   // that the decoder just got flushed. Once bug 1257107 land, we could set the
   // decoder threshold to the value of currentTime.
   DropDecodedSamples(TrackInfo::kVideoTrack);
 
-  mSkipRequest.Begin(mVideo.mTrackDemuxer->SkipToNextRandomAccessPoint(aTimeThreshold)
-                          ->Then(OwnerThread(), __func__, this,
-                                 &MediaFormatReader::OnVideoSkipCompleted,
-                                 &MediaFormatReader::OnVideoSkipFailed));
+  mVideo.mTrackDemuxer->SkipToNextRandomAccessPoint(aTimeThreshold)
+    ->Then(OwnerThread(), __func__, this,
+           &MediaFormatReader::OnVideoSkipCompleted,
+           &MediaFormatReader::OnVideoSkipFailed)
+    ->Track(mSkipRequest);
   return;
 }
 
 void
 MediaFormatReader::VideoSkipReset(uint32_t aSkipped)
 {
   MOZ_ASSERT(OnTaskQueue());
 
@@ -2403,20 +2408,21 @@ MediaFormatReader::OnSeekFailed(TrackTyp
 }
 
 void
 MediaFormatReader::DoVideoSeek()
 {
   MOZ_ASSERT(mPendingSeekTime.isSome());
   LOGV("Seeking video to %lld", mPendingSeekTime.ref().ToMicroseconds());
   media::TimeUnit seekTime = mPendingSeekTime.ref();
-  mVideo.mSeekRequest.Begin(mVideo.mTrackDemuxer->Seek(seekTime)
-                          ->Then(OwnerThread(), __func__, this,
-                                 &MediaFormatReader::OnVideoSeekCompleted,
-                                 &MediaFormatReader::OnVideoSeekFailed));
+  mVideo.mTrackDemuxer->Seek(seekTime)
+    ->Then(OwnerThread(), __func__, this,
+           &MediaFormatReader::OnVideoSeekCompleted,
+           &MediaFormatReader::OnVideoSeekFailed)
+    ->Track(mVideo.mSeekRequest);
 }
 
 void
 MediaFormatReader::OnVideoSeekCompleted(media::TimeUnit aTime)
 {
   MOZ_ASSERT(OnTaskQueue());
   LOGV("Video seeked to %lld", aTime.ToMicroseconds());
   mVideo.mSeekRequest.Complete();
@@ -2485,20 +2491,21 @@ MediaFormatReader::SetVideoDecodeThresho
 }
 
 void
 MediaFormatReader::DoAudioSeek()
 {
   MOZ_ASSERT(mPendingSeekTime.isSome());
   LOGV("Seeking audio to %lld", mPendingSeekTime.ref().ToMicroseconds());
   media::TimeUnit seekTime = mPendingSeekTime.ref();
-  mAudio.mSeekRequest.Begin(mAudio.mTrackDemuxer->Seek(seekTime)
-                         ->Then(OwnerThread(), __func__, this,
-                                &MediaFormatReader::OnAudioSeekCompleted,
-                                &MediaFormatReader::OnAudioSeekFailed));
+  mAudio.mTrackDemuxer->Seek(seekTime)
+    ->Then(OwnerThread(), __func__, this,
+           &MediaFormatReader::OnAudioSeekCompleted,
+           &MediaFormatReader::OnAudioSeekFailed)
+    ->Track(mAudio.mSeekRequest);
 }
 
 void
 MediaFormatReader::OnAudioSeekCompleted(media::TimeUnit aTime)
 {
   MOZ_ASSERT(OnTaskQueue());
   LOGV("Audio seeked to %lld", aTime.ToMicroseconds());
   mAudio.mSeekRequest.Complete();
@@ -2559,24 +2566,25 @@ MediaFormatReader::NotifyDataArrived()
     // Already one in progress. Reschedule for later.
     RefPtr<nsIRunnable> task(
         NewRunnableMethod(this, &MediaFormatReader::NotifyDataArrived));
     OwnerThread()->Dispatch(task.forget());
     return;
   }
 
   RefPtr<MediaFormatReader> self = this;
-  mNotifyDataArrivedPromise.Begin(mDemuxer->NotifyDataArrived()->Then(
-      OwnerThread(), __func__,
-      [self]() {
-        self->mNotifyDataArrivedPromise.Complete();
-        self->UpdateBuffered();
-        self->NotifyTrackDemuxers();
-      },
-      [self]() { self->mNotifyDataArrivedPromise.Complete(); }));
+  mDemuxer->NotifyDataArrived()
+    ->Then(OwnerThread(), __func__,
+           [self]() {
+             self->mNotifyDataArrivedPromise.Complete();
+             self->UpdateBuffered();
+             self->NotifyTrackDemuxers();
+           },
+           [self]() { self->mNotifyDataArrivedPromise.Complete(); })
+    ->Track(mNotifyDataArrivedPromise);
 }
 
 void
 MediaFormatReader::UpdateBuffered()
 {
   MOZ_ASSERT(OnTaskQueue());
 
   if (mShutdown) {
--- a/dom/media/MediaTimer.h
+++ b/dom/media/MediaTimer.h
@@ -140,20 +140,21 @@ public:
               RejectFunc&& aRejector)
   {
     MOZ_ASSERT(mTargetThread->IsCurrentThreadIn());
     if (IsScheduled() && mTarget <= aTarget) {
       return;
     }
     Reset();
     mTarget = aTarget;
-    mRequest.Begin(mMediaTimer->WaitUntil(mTarget, __func__)->Then(
+    mMediaTimer->WaitUntil(mTarget, __func__)->Then(
       mTargetThread, __func__,
       Forward<ResolveFunc>(aResolver),
-      Forward<RejectFunc>(aRejector)));
+      Forward<RejectFunc>(aRejector))
+    ->Track(mRequest);
   }
 
   void CompleteRequest()
   {
     MOZ_ASSERT(mTargetThread->IsCurrentThreadIn());
     mRequest.Complete();
     mTarget = TimeStamp();
   }
--- a/dom/media/android/AndroidMediaReader.cpp
+++ b/dom/media/android/AndroidMediaReader.cpp
@@ -325,25 +325,25 @@ AndroidMediaReader::Seek(const SeekTarge
     // a sync point, whereas for video there are only keyframes once every few
     // seconds. So if we have both audio and video, we must seek the video
     // stream to the preceeding keyframe first, get the stream time, and then
     // seek the audio stream to match the video stream's time. Otherwise, the
     // audio and video streams won't be in sync after the seek.
     mVideoSeekTimeUs = aTarget.GetTime().ToMicroseconds();
 
     RefPtr<AndroidMediaReader> self = this;
-    mSeekRequest.Begin(DecodeToFirstVideoData()->Then(OwnerThread(), __func__, [self] (MediaData* v) {
+    DecodeToFirstVideoData()->Then(OwnerThread(), __func__, [self] (MediaData* v) {
       self->mSeekRequest.Complete();
       self->mAudioSeekTimeUs = v->mTime;
       self->mSeekPromise.Resolve(media::TimeUnit::FromMicroseconds(self->mAudioSeekTimeUs), __func__);
     }, [self, aTarget] () {
       self->mSeekRequest.Complete();
       self->mAudioSeekTimeUs = aTarget.GetTime().ToMicroseconds();
       self->mSeekPromise.Resolve(aTarget.GetTime(), __func__);
-    }));
+    })->Track(mSeekRequest);
   } else {
     mAudioSeekTimeUs = mVideoSeekTimeUs = aTarget.GetTime().ToMicroseconds();
     mSeekPromise.Resolve(aTarget.GetTime(), __func__);
   }
 
   return p;
 }
 
--- a/dom/media/gtest/TestMozPromise.cpp
+++ b/dom/media/gtest/TestMozPromise.cpp
@@ -275,13 +275,13 @@ TEST(MozPromise, Chaining)
             holder.Disconnect();
             queue->BeginShutdown();
           },
           DO_FAIL);
       }
     }
     // We will hit the assertion if we don't disconnect the leaf Request
     // in the promise chain.
-    holder.Begin(p->Then(queue, __func__, [] () {}, [] () {}));
+    p->Then(queue, __func__, [] () {}, [] () {})->Track(holder);
   });
 }
 
 #undef DO_FAIL
--- a/dom/media/mediasink/AudioSinkWrapper.cpp
+++ b/dom/media/mediasink/AudioSinkWrapper.cpp
@@ -188,20 +188,21 @@ AudioSinkWrapper::Start(int64_t aStartTi
 
   // no audio is equivalent to audio ended before video starts.
   mAudioEnded = !aInfo.HasAudio();
 
   if (aInfo.HasAudio()) {
     mAudioSink = mCreator->Create();
     mEndPromise = mAudioSink->Init(mParams);
 
-    mAudioSinkPromise.Begin(mEndPromise->Then(
+    mEndPromise->Then(
       mOwnerThread.get(), __func__, this,
       &AudioSinkWrapper::OnAudioEnded,
-      &AudioSinkWrapper::OnAudioEnded));
+      &AudioSinkWrapper::OnAudioEnded
+    )->Track(mAudioSinkPromise);
   }
 }
 
 void
 AudioSinkWrapper::Stop()
 {
   AssertOwnerThread();
   MOZ_ASSERT(mIsStarted, "playback not started.");
--- a/dom/media/mediasink/VideoSink.cpp
+++ b/dom/media/mediasink/VideoSink.cpp
@@ -180,29 +180,30 @@ VideoSink::Start(int64_t aStartTime, con
     // If the underlying MediaSink has an end promise for the video track (which
     // happens when mAudioSink refers to a DecodedStream), we must wait for it
     // to complete before resolving our own end promise. Otherwise, MDSM might
     // stop playback before DecodedStream plays to the end and cause
     // test_streams_element_capture.html to time out.
     RefPtr<GenericPromise> p = mAudioSink->OnEnded(TrackInfo::kVideoTrack);
     if (p) {
       RefPtr<VideoSink> self = this;
-      mVideoSinkEndRequest.Begin(p->Then(mOwnerThread, __func__,
+      p->Then(mOwnerThread, __func__,
         [self] () {
           self->mVideoSinkEndRequest.Complete();
           self->TryUpdateRenderedVideoFrames();
           // It is possible the video queue size is 0 and we have no frames to
           // render. However, we need to call MaybeResolveEndPromise() to ensure
           // mEndPromiseHolder is resolved.
           self->MaybeResolveEndPromise();
         }, [self] () {
           self->mVideoSinkEndRequest.Complete();
           self->TryUpdateRenderedVideoFrames();
           self->MaybeResolveEndPromise();
-        }));
+        })
+        ->Track(mVideoSinkEndRequest);
     }
 
     ConnectListener();
     // Run the render loop at least once so we can resolve the end promise
     // when video duration is 0.
     UpdateRenderedVideoFrames();
   }
 }
--- a/dom/media/mediasource/SourceBuffer.cpp
+++ b/dom/media/mediasource/SourceBuffer.cpp
@@ -253,25 +253,25 @@ SourceBuffer::Remove(double aStart, doub
 }
 
 void
 SourceBuffer::RangeRemoval(double aStart, double aEnd)
 {
   StartUpdating();
 
   RefPtr<SourceBuffer> self = this;
-  mPendingRemoval.Begin(
     mTrackBuffersManager->RangeRemoval(TimeUnit::FromSeconds(aStart),
                                        TimeUnit::FromSeconds(aEnd))
       ->Then(AbstractThread::MainThread(), __func__,
              [self] (bool) {
                self->mPendingRemoval.Complete();
                self->StopUpdating();
              },
-             []() { MOZ_ASSERT(false); }));
+             []() { MOZ_ASSERT(false); })
+      ->Track(mPendingRemoval);
 }
 
 void
 SourceBuffer::Detach()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("Detach");
   if (!mMediaSource) {
@@ -410,20 +410,21 @@ SourceBuffer::AppendData(const uint8_t* 
   MSE_DEBUG("AppendData(aLength=%u)", aLength);
 
   RefPtr<MediaByteBuffer> data = PrepareAppend(aData, aLength, aRv);
   if (!data) {
     return;
   }
   StartUpdating();
 
-  mPendingAppend.Begin(mTrackBuffersManager->AppendData(data, mCurrentAttributes)
-                       ->Then(AbstractThread::MainThread(), __func__, this,
-                              &SourceBuffer::AppendDataCompletedWithSuccess,
-                              &SourceBuffer::AppendDataErrored));
+  mTrackBuffersManager->AppendData(data, mCurrentAttributes)
+    ->Then(AbstractThread::MainThread(), __func__, this,
+           &SourceBuffer::AppendDataCompletedWithSuccess,
+           &SourceBuffer::AppendDataErrored)
+    ->Track(mPendingAppend);
 }
 
 void
 SourceBuffer::AppendDataCompletedWithSuccess(SourceBufferTask::AppendBufferResult aResult)
 {
   MOZ_ASSERT(mUpdating);
   mPendingAppend.Complete();
 
--- a/dom/media/mediasource/TrackBuffersManager.cpp
+++ b/dom/media/mediasource/TrackBuffersManager.cpp
@@ -728,30 +728,31 @@ TrackBuffersManager::SegmentParserLoop()
           mInputBuffer = nullptr;
           NeedMoreData();
           return;
         }
       }
 
       // 3. If the input buffer contains one or more complete coded frames, then run the coded frame processing algorithm.
       RefPtr<TrackBuffersManager> self = this;
-      mProcessingRequest.Begin(CodedFrameProcessing()
-          ->Then(GetTaskQueue(), __func__,
-                 [self] (bool aNeedMoreData) {
-                   self->mProcessingRequest.Complete();
-                   if (aNeedMoreData) {
-                     self->NeedMoreData();
-                   } else {
-                     self->ScheduleSegmentParserLoop();
-                   }
-                 },
-                 [self] (const MediaResult& aRejectValue) {
-                   self->mProcessingRequest.Complete();
-                   self->RejectAppend(aRejectValue, __func__);
-                 }));
+      CodedFrameProcessing()
+        ->Then(GetTaskQueue(), __func__,
+               [self] (bool aNeedMoreData) {
+                 self->mProcessingRequest.Complete();
+                 if (aNeedMoreData) {
+                   self->NeedMoreData();
+                 } else {
+                   self->ScheduleSegmentParserLoop();
+                 }
+               },
+               [self] (const MediaResult& aRejectValue) {
+                 self->mProcessingRequest.Complete();
+                 self->RejectAppend(aRejectValue, __func__);
+               })
+        ->Track(mProcessingRequest);
       return;
     }
   }
 }
 
 void
 TrackBuffersManager::NeedMoreData()
 {
@@ -837,21 +838,22 @@ TrackBuffersManager::ResetDemuxingState(
   // that data has been appended yet ; so we simply append the init segment
   // to the resource.
   mCurrentInputBuffer->AppendData(mParser->InitData());
   CreateDemuxerforMIMEType();
   if (!mInputDemuxer) {
     RejectAppend(NS_ERROR_FAILURE, __func__);
     return;
   }
-  mDemuxerInitRequest.Begin(mInputDemuxer->Init()
-                      ->Then(GetTaskQueue(), __func__,
-                             this,
-                             &TrackBuffersManager::OnDemuxerResetDone,
-                             &TrackBuffersManager::OnDemuxerInitFailed));
+  mInputDemuxer->Init()
+    ->Then(GetTaskQueue(), __func__,
+           this,
+           &TrackBuffersManager::OnDemuxerResetDone,
+           &TrackBuffersManager::OnDemuxerInitFailed)
+    ->Track(mDemuxerInitRequest);
 }
 
 void
 TrackBuffersManager::OnDemuxerResetDone(nsresult)
 {
   MOZ_ASSERT(OnTaskQueue());
   mDemuxerInitRequest.Complete();
   // mInputDemuxer shouldn't have been destroyed while a demuxer init/reset
@@ -911,21 +913,22 @@ TrackBuffersManager::InitializationSegme
     mInputBuffer->RemoveElementsAt(0, length);
   }
   CreateDemuxerforMIMEType();
   if (!mInputDemuxer) {
     NS_WARNING("TODO type not supported");
     RejectAppend(NS_ERROR_DOM_NOT_SUPPORTED_ERR, __func__);
     return;
   }
-  mDemuxerInitRequest.Begin(mInputDemuxer->Init()
-                      ->Then(GetTaskQueue(), __func__,
-                             this,
-                             &TrackBuffersManager::OnDemuxerInitDone,
-                             &TrackBuffersManager::OnDemuxerInitFailed));
+  mInputDemuxer->Init()
+    ->Then(GetTaskQueue(), __func__,
+           this,
+           &TrackBuffersManager::OnDemuxerInitDone,
+           &TrackBuffersManager::OnDemuxerInitFailed)
+    ->Track(mDemuxerInitRequest);
 }
 
 void
 TrackBuffersManager::OnDemuxerInitDone(nsresult)
 {
   MOZ_ASSERT(OnTaskQueue());
   MOZ_DIAGNOSTIC_ASSERT(mInputDemuxer, "mInputDemuxer has been destroyed");
 
@@ -1195,20 +1198,21 @@ TrackBuffersManager::OnDemuxFailed(Track
 void
 TrackBuffersManager::DoDemuxVideo()
 {
   MOZ_ASSERT(OnTaskQueue());
   if (!HasVideo()) {
     DoDemuxAudio();
     return;
   }
-  mVideoTracks.mDemuxRequest.Begin(mVideoTracks.mDemuxer->GetSamples(-1)
-                             ->Then(GetTaskQueue(), __func__, this,
-                                    &TrackBuffersManager::OnVideoDemuxCompleted,
-                                    &TrackBuffersManager::OnVideoDemuxFailed));
+  mVideoTracks.mDemuxer->GetSamples(-1)
+    ->Then(GetTaskQueue(), __func__, this,
+           &TrackBuffersManager::OnVideoDemuxCompleted,
+           &TrackBuffersManager::OnVideoDemuxFailed)
+    ->Track(mVideoTracks.mDemuxRequest);
 }
 
 void
 TrackBuffersManager::OnVideoDemuxCompleted(RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples)
 {
   MOZ_ASSERT(OnTaskQueue());
   MSE_DEBUG("%d video samples demuxed", aSamples->mSamples.Length());
   mVideoTracks.mDemuxRequest.Complete();
@@ -1219,20 +1223,21 @@ TrackBuffersManager::OnVideoDemuxComplet
 void
 TrackBuffersManager::DoDemuxAudio()
 {
   MOZ_ASSERT(OnTaskQueue());
   if (!HasAudio()) {
     CompleteCodedFrameProcessing();
     return;
   }
-  mAudioTracks.mDemuxRequest.Begin(mAudioTracks.mDemuxer->GetSamples(-1)
-                             ->Then(GetTaskQueue(), __func__, this,
-                                    &TrackBuffersManager::OnAudioDemuxCompleted,
-                                    &TrackBuffersManager::OnAudioDemuxFailed));
+  mAudioTracks.mDemuxer->GetSamples(-1)
+    ->Then(GetTaskQueue(), __func__, this,
+           &TrackBuffersManager::OnAudioDemuxCompleted,
+           &TrackBuffersManager::OnAudioDemuxFailed)
+    ->Track(mAudioTracks.mDemuxRequest);
 }
 
 void
 TrackBuffersManager::OnAudioDemuxCompleted(RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples)
 {
   MOZ_ASSERT(OnTaskQueue());
   MSE_DEBUG("%d audio samples demuxed", aSamples->mSamples.Length());
   mAudioTracks.mDemuxRequest.Complete();
--- a/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
@@ -55,20 +55,21 @@ public:
       return;
     }
 
     nsAutoPtr<MediaRawDataWriter> writer(aSample->CreateWriter());
     mProxy->GetSessionIdsForKeyId(aSample->mCrypto.mKeyId,
                                   writer->mCrypto.mSessionIds);
 
     mDecrypts.Put(aSample, new DecryptPromiseRequestHolder());
-    mDecrypts.Get(aSample)->Begin(mProxy->Decrypt(aSample)->Then(
+    mProxy->Decrypt(aSample)->Then(
       mTaskQueue, __func__, this,
       &EMEDecryptor::Decrypted,
-      &EMEDecryptor::Decrypted));
+      &EMEDecryptor::Decrypted)
+    ->Track(*mDecrypts.Get(aSample));
     return;
   }
 
   void Decrypted(const DecryptResult& aDecrypted) {
     MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
     MOZ_ASSERT(aDecrypted.mSample);
 
     nsAutoPtr<DecryptPromiseRequestHolder> holder;
--- a/dom/media/platforms/wrappers/FuzzingWrapper.cpp
+++ b/dom/media/platforms/wrappers/FuzzingWrapper.cpp
@@ -237,33 +237,33 @@ void
 DecoderCallbackFuzzingWrapper::ScheduleOutputDelayedFrame()
 {
   MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
   if (mDelayedOutputRequest.Exists()) {
     // A delayed output is already scheduled, no need for more than one timer.
     return;
   }
   RefPtr<DecoderCallbackFuzzingWrapper> self = this;
-  mDelayedOutputRequest.Begin(
-    mDelayedOutputTimer->WaitUntil(
-      mPreviousOutput + mFrameOutputMinimumInterval,
-      __func__)
-    ->Then(mTaskQueue, __func__,
-           [self] () -> void {
-             if (self->mDelayedOutputRequest.Exists()) {
-               self->mDelayedOutputRequest.Complete();
-               self->OutputDelayedFrame();
-             }
-           },
-           [self] () -> void {
-             if (self->mDelayedOutputRequest.Exists()) {
-               self->mDelayedOutputRequest.Complete();
-               self->ClearDelayedOutput();
-             }
-           }));
+  mDelayedOutputTimer->WaitUntil(
+    mPreviousOutput + mFrameOutputMinimumInterval,
+    __func__)
+  ->Then(mTaskQueue, __func__,
+         [self] () -> void {
+           if (self->mDelayedOutputRequest.Exists()) {
+             self->mDelayedOutputRequest.Complete();
+             self->OutputDelayedFrame();
+           }
+         },
+         [self] () -> void {
+           if (self->mDelayedOutputRequest.Exists()) {
+             self->mDelayedOutputRequest.Complete();
+             self->ClearDelayedOutput();
+           }
+         })
+  ->Track(mDelayedOutputRequest);
 }
 
 void
 DecoderCallbackFuzzingWrapper::OutputDelayedFrame()
 {
   MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
   if (mDelayedOutput.empty()) {
     if (mDraining) {
--- a/dom/media/platforms/wrappers/H264Converter.cpp
+++ b/dom/media/platforms/wrappers/H264Converter.cpp
@@ -226,20 +226,21 @@ H264Converter::CreateDecoderAndInit(Medi
   UpdateConfigFromExtraData(extra_data);
 
   nsresult rv = CreateDecoder(/* DecoderDoctorDiagnostics* */ nullptr);
 
   if (NS_SUCCEEDED(rv)) {
     // Queue the incoming sample.
     mMediaRawSamples.AppendElement(aSample);
 
-    mInitPromiseRequest.Begin(mDecoder->Init()
+    mDecoder->Init()
       ->Then(AbstractThread::GetCurrent()->AsTaskQueue(), __func__, this,
              &H264Converter::OnDecoderInitDone,
-             &H264Converter::OnDecoderInitFailed));
+             &H264Converter::OnDecoderInitFailed)
+      ->Track(mInitPromiseRequest);
     return NS_ERROR_NOT_INITIALIZED;
   }
   return rv;
 }
 
 void
 H264Converter::OnDecoderInitDone(const TrackType aTrackType)
 {
--- a/xpcom/threads/MozPromise.h
+++ b/xpcom/threads/MozPromise.h
@@ -1055,28 +1055,16 @@ private:
  */
 template<typename PromiseType>
 class MozPromiseRequestHolder
 {
 public:
   MozPromiseRequestHolder() {}
   ~MozPromiseRequestHolder() { MOZ_ASSERT(!mRequest); }
 
-  void Begin(RefPtr<typename PromiseType::Request>&& aRequest)
-  {
-    MOZ_DIAGNOSTIC_ASSERT(!Exists());
-    mRequest = Move(aRequest);
-  }
-
-  void Begin(typename PromiseType::Request* aRequest)
-  {
-    MOZ_DIAGNOSTIC_ASSERT(!Exists());
-    mRequest = aRequest;
-  }
-
   void Track(RefPtr<typename PromiseType::Request>&& aRequest)
   {
     MOZ_DIAGNOSTIC_ASSERT(!Exists());
     mRequest = Move(aRequest);
   }
 
   void Complete()
   {