Bug 1184634 - Rename MediaPromise to MozPromise. r=gerald
authorBobby Holley <bobbyholley@gmail.com>
Thu, 16 Jul 2015 11:06:49 -0700
changeset 253347 dc714b35dd0419b9ac6951217562aeffa921157a
parent 253346 cd3c9358b57035237d4a6b8682e8ef8abcf1d2bf
child 253348 e522f33ca3e630353d9480e7efe52d533ed5977e
push id62426
push userbobbyholley@gmail.com
push dateFri, 17 Jul 2015 05:23:42 +0000
treeherdermozilla-inbound@9fc592979091 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgerald
bugs1184634
milestone42.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 1184634 - Rename MediaPromise to MozPromise. r=gerald
dom/media/MediaDataDemuxer.h
dom/media/MediaDecoder.cpp
dom/media/MediaDecoder.h
dom/media/MediaDecoderReader.h
dom/media/MediaDecoderStateMachine.h
dom/media/MediaFormatReader.h
dom/media/MediaPromise.h
dom/media/MediaTaskQueue.h
dom/media/MediaTimer.h
dom/media/MozPromise.h
dom/media/StateMirroring.h
dom/media/VideoUtils.h
dom/media/android/AndroidMediaReader.h
dom/media/eme/CDMProxy.h
dom/media/fmp4/MP4Reader.h
dom/media/gtest/TestMediaPromise.cpp
dom/media/gtest/TestMozPromise.cpp
dom/media/gtest/moz.build
dom/media/mediasource/MediaSourceReader.h
dom/media/mediasource/SourceBuffer.h
dom/media/mediasource/SourceBufferContentManager.h
dom/media/mediasource/TrackBuffer.cpp
dom/media/mediasource/TrackBuffer.h
dom/media/mediasource/TrackBuffersManager.h
dom/media/moz.build
dom/media/omx/AudioOffloadPlayer.h
dom/media/omx/MediaCodecReader.h
dom/media/omx/MediaOmxCommonReader.h
dom/media/omx/MediaOmxReader.h
dom/media/omx/OmxDecoder.h
dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
--- a/dom/media/MediaDataDemuxer.h
+++ b/dom/media/MediaDataDemuxer.h
@@ -4,17 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #if !defined(MediaDataDemuxer_h)
 #define MediaDataDemuxer_h
 
 #include "MediaData.h"
 #include "MediaInfo.h"
-#include "MediaPromise.h"
+#include "MozPromise.h"
 #include "TimeUnits.h"
 #include "mozilla/UniquePtr.h"
 #include "nsISupportsImpl.h"
 #include "nsRefPtr.h"
 #include "nsTArray.h"
 
 namespace mozilla {
 
@@ -35,17 +35,17 @@ enum class DemuxerFailureReason : int8_t
 // MediaDataDemuxer isn't designed to be thread safe.
 // When used by the MediaFormatDecoder, care is taken to ensure that the demuxer
 // will never be called from more than one thread at once.
 class MediaDataDemuxer
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDataDemuxer)
 
-  typedef MediaPromise<nsresult, DemuxerFailureReason, /* IsExclusive = */ true> InitPromise;
+  typedef MozPromise<nsresult, DemuxerFailureReason, /* IsExclusive = */ true> InitPromise;
 
   // Initializes the demuxer. Other methods cannot be called unless
   // initialization has completed and succeeded.
   // Typically a demuxer will wait to parse the metadata before resolving the
   // promise. The promise will be rejected with WAITING_FOR_DATA should
   // insufficient data be available at the time. Init() would have to be called
   // again to retry once more data has been received.
   virtual nsRefPtr<InitPromise> Init() = 0;
@@ -128,19 +128,19 @@ public:
     SkipFailureHolder(DemuxerFailureReason aFailure, uint32_t aSkipped)
       : mFailure(aFailure)
       , mSkipped(aSkipped)
     {}
     DemuxerFailureReason mFailure;
     uint32_t mSkipped;
   };
 
-  typedef MediaPromise<media::TimeUnit, DemuxerFailureReason, /* IsExclusive = */ true> SeekPromise;
-  typedef MediaPromise<nsRefPtr<SamplesHolder>, DemuxerFailureReason, /* IsExclusive = */ true> SamplesPromise;
-  typedef MediaPromise<uint32_t, SkipFailureHolder, /* IsExclusive = */ true> SkipAccessPointPromise;
+  typedef MozPromise<media::TimeUnit, DemuxerFailureReason, /* IsExclusive = */ true> SeekPromise;
+  typedef MozPromise<nsRefPtr<SamplesHolder>, DemuxerFailureReason, /* IsExclusive = */ true> SamplesPromise;
+  typedef MozPromise<uint32_t, SkipFailureHolder, /* IsExclusive = */ true> SkipAccessPointPromise;
 
   // Returns the TrackInfo (a.k.a Track Description) for this track.
   // The TrackInfo returned will be:
   // TrackInfo::kVideoTrack -> VideoInfo.
   // TrackInfo::kAudioTrack -> AudioInfo.
   // respectively.
   virtual UniquePtr<TrackInfo> GetInfo() const = 0;
 
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -116,30 +116,30 @@ public:
       sUniqueInstance = nullptr;
     }
   }
 };
 
 StaticRefPtr<MediaMemoryTracker> MediaMemoryTracker::sUniqueInstance;
 
 PRLogModuleInfo* gStateWatchingLog;
-PRLogModuleInfo* gMediaPromiseLog;
+PRLogModuleInfo* gMozPromiseLog;
 PRLogModuleInfo* gMediaTimerLog;
 PRLogModuleInfo* gMediaSampleLog;
 
 void
 MediaDecoder::InitStatics()
 {
   MOZ_ASSERT(NS_IsMainThread());
   AbstractThread::InitStatics();
   SharedThreadPool::InitStatics();
 
   // Log modules.
   gMediaDecoderLog = PR_NewLogModule("MediaDecoder");
-  gMediaPromiseLog = PR_NewLogModule("MediaPromise");
+  gMozPromiseLog = PR_NewLogModule("MozPromise");
   gStateWatchingLog = PR_NewLogModule("StateWatching");
   gMediaTimerLog = PR_NewLogModule("MediaTimer");
   gMediaSampleLog = PR_NewLogModule("MediaSample");
 }
 
 NS_IMPL_ISUPPORTS(MediaMemoryTracker, nsIMemoryReporter)
 
 NS_IMPL_ISUPPORTS0(MediaDecoder)
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -184,17 +184,17 @@ destroying the MediaDecoder object.
 #if !defined(MediaDecoder_h_)
 #define MediaDecoder_h_
 
 #include "nsISupports.h"
 #include "nsCOMPtr.h"
 #include "nsIObserver.h"
 #include "nsAutoPtr.h"
 #include "nsITimer.h"
-#include "MediaPromise.h"
+#include "MozPromise.h"
 #include "MediaResource.h"
 #include "mozilla/dom/AudioChannelBinding.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "MediaDecoderOwner.h"
 #include "MediaStreamGraph.h"
 #include "AbstractMediaDecoder.h"
 #include "DecodedStream.h"
 #include "StateMirroring.h"
@@ -269,17 +269,17 @@ class MediaDecoder : public AbstractMedi
 public:
   struct SeekResolveValue {
     SeekResolveValue(bool aAtEnd, MediaDecoderEventVisibility aEventVisibility)
       : mAtEnd(aAtEnd), mEventVisibility(aEventVisibility) {}
     bool mAtEnd;
     MediaDecoderEventVisibility mEventVisibility;
   };
 
-  typedef MediaPromise<SeekResolveValue, bool /* aIgnored */, /* IsExclusive = */ true> SeekPromise;
+  typedef MozPromise<SeekResolveValue, bool /* aIgnored */, /* IsExclusive = */ true> SeekPromise;
 
   NS_DECL_THREADSAFE_ISUPPORTS
 
   // Enumeration for the valid play states (see mPlayState)
   enum PlayState {
     PLAY_STATE_START,
     PLAY_STATE_LOADING,
     PLAY_STATE_PAUSED,
@@ -981,17 +981,17 @@ private:
 #endif
 
 protected:
   virtual void CallSeek(const SeekTarget& aTarget);
 
   // Returns true if heuristic dormant is supported.
   bool IsHeuristicDormantSupported() const;
 
-  MediaPromiseRequestHolder<SeekPromise> mSeekRequest;
+  MozPromiseRequestHolder<SeekPromise> mSeekRequest;
 
   // True when seeking or otherwise moving the play position around in
   // such a manner that progress event data is inaccurate. This is set
   // during seek and duration operations to prevent the progress indicator
   // from jumping around. Read/Write from any thread. Must have decode monitor
   // locked before accessing.
   bool mIgnoreProgressData;
 
--- a/dom/media/MediaDecoderReader.h
+++ b/dom/media/MediaDecoderReader.h
@@ -4,17 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #if !defined(MediaDecoderReader_h_)
 #define MediaDecoderReader_h_
 
 #include "AbstractMediaDecoder.h"
 #include "MediaInfo.h"
 #include "MediaData.h"
-#include "MediaPromise.h"
+#include "MozPromise.h"
 #include "MediaQueue.h"
 #include "MediaTimer.h"
 #include "AudioCompactor.h"
 #include "Intervals.h"
 #include "TimeUnits.h"
 
 namespace mozilla {
 
@@ -61,26 +61,26 @@ class MediaDecoderReader {
 public:
   enum NotDecodedReason {
     END_OF_STREAM,
     DECODE_ERROR,
     WAITING_FOR_DATA,
     CANCELED
   };
 
-  typedef MediaPromise<nsRefPtr<MetadataHolder>, ReadMetadataFailureReason, /* IsExclusive = */ true> MetadataPromise;
-  typedef MediaPromise<nsRefPtr<AudioData>, NotDecodedReason, /* IsExclusive = */ true> AudioDataPromise;
-  typedef MediaPromise<nsRefPtr<VideoData>, NotDecodedReason, /* IsExclusive = */ true> VideoDataPromise;
-  typedef MediaPromise<int64_t, nsresult, /* IsExclusive = */ true> SeekPromise;
+  typedef MozPromise<nsRefPtr<MetadataHolder>, ReadMetadataFailureReason, /* IsExclusive = */ true> MetadataPromise;
+  typedef MozPromise<nsRefPtr<AudioData>, NotDecodedReason, /* IsExclusive = */ true> AudioDataPromise;
+  typedef MozPromise<nsRefPtr<VideoData>, NotDecodedReason, /* IsExclusive = */ true> VideoDataPromise;
+  typedef MozPromise<int64_t, nsresult, /* IsExclusive = */ true> SeekPromise;
 
   // Note that, conceptually, WaitForData makes sense in a non-exclusive sense.
   // But in the current architecture it's only ever used exclusively (by MDSM),
   // so we mark it that way to verify our assumptions. If you have a use-case
   // for multiple WaitForData consumers, feel free to flip the exclusivity here.
-  typedef MediaPromise<MediaData::Type, WaitForDataRejectValue, /* IsExclusive = */ true> WaitForDataPromise;
+  typedef MozPromise<MediaData::Type, WaitForDataRejectValue, /* IsExclusive = */ true> WaitForDataPromise;
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoderReader)
 
   // The caller must ensure that Shutdown() is called before aDecoder is
   // destroyed.
   explicit MediaDecoderReader(AbstractMediaDecoder* aDecoder, MediaTaskQueue* aBorrowedTaskQueue = nullptr);
 
   // Does any spinup that needs to happen on this task queue. This runs on a
@@ -381,17 +381,17 @@ protected:
 
   // Stores presentation info required for playback.
   MediaInfo mInfo;
 
   // Duration, mirrored from the state machine task queue.
   Mirror<media::NullableTimeUnit> mDuration;
 
   // State for ThrottledNotifyDataArrived.
-  MediaPromiseRequestHolder<MediaTimerPromise> mThrottledNotify;
+  MozPromiseRequestHolder<MediaTimerPromise> mThrottledNotify;
   const TimeDuration mThrottleDuration;
   TimeStamp mLastThrottledNotify;
   Maybe<media::Interval<int64_t>> mThrottledInterval;
 
   // Whether we should accept media that we know we can't play
   // directly, because they have a number of channel higher than
   // what we support.
   bool mIgnoreAudioOutputFormat;
@@ -415,18 +415,18 @@ protected:
   // replace this with a promise-y mechanism as we make this stuff properly
   // async.
   bool mHitAudioDecodeError;
   bool mShutdown;
 
 private:
   // Promises used only for the base-class (sync->async adapter) implementation
   // of Request{Audio,Video}Data.
-  MediaPromiseHolder<AudioDataPromise> mBaseAudioPromise;
-  MediaPromiseHolder<VideoDataPromise> mBaseVideoPromise;
+  MozPromiseHolder<AudioDataPromise> mBaseAudioPromise;
+  MozPromiseHolder<VideoDataPromise> mBaseVideoPromise;
 
   bool mTaskQueueIsBorrowed;
 
   // Flags whether a the next audio/video sample comes after a "gap" or
   // "discontinuity" in the stream. For example after a seek.
   bool mAudioDiscontinuity;
   bool mVideoDiscontinuity;
 };
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -761,29 +761,29 @@ private:
       MOZ_ASSERT(mSelf->OnTaskQueue());
       mRequest.Complete();
       mTarget = TimeStamp();
     }
 
   private:
     MediaDecoderStateMachine* mSelf;
     nsRefPtr<MediaTimer> mMediaTimer;
-    MediaPromiseRequestHolder<mozilla::MediaTimerPromise> mRequest;
+    MozPromiseRequestHolder<mozilla::MediaTimerPromise> mRequest;
     TimeStamp mTarget;
 
   } mDelayedScheduler;
 
   // StartTimeRendezvous is a helper class that quarantines the first sample
   // until it gets a sample from both channels, such that we can be guaranteed
   // to know the start time by the time On{Audio,Video}Decoded is called.
   class StartTimeRendezvous {
   public:
     typedef MediaDecoderReader::AudioDataPromise AudioDataPromise;
     typedef MediaDecoderReader::VideoDataPromise VideoDataPromise;
-    typedef MediaPromise<bool, bool, /* isExclusive = */ false> HaveStartTimePromise;
+    typedef MozPromise<bool, bool, /* isExclusive = */ false> HaveStartTimePromise;
 
     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(StartTimeRendezvous);
     StartTimeRendezvous(AbstractThread* aOwnerThread, bool aHasAudio, bool aHasVideo,
                         bool aForceZeroStartTime)
       : mOwnerThread(aOwnerThread)
     {
       if (aForceZeroStartTime) {
         mAudioStartTime.emplace(0);
@@ -883,17 +883,17 @@ private:
       }
     }
 
     Maybe<int64_t>& ChannelStartTime(MediaData::Type aType)
     {
       return aType == MediaData::AUDIO_DATA ? mAudioStartTime : mVideoStartTime;
     }
 
-    MediaPromiseHolder<HaveStartTimePromise> mHaveStartTimePromise;
+    MozPromiseHolder<HaveStartTimePromise> mHaveStartTimePromise;
     nsRefPtr<AbstractThread> mOwnerThread;
     Maybe<int64_t> mAudioStartTime;
     Maybe<int64_t> mVideoStartTime;
   };
   nsRefPtr<StartTimeRendezvous> mStartTimeRendezvous;
 
   bool HaveStartTime() { return mStartTimeRendezvous && mStartTimeRendezvous->HaveStartTime(); }
   int64_t StartTime() { return mStartTimeRendezvous->StartTime(); }
@@ -994,17 +994,17 @@ private:
 
     ~SeekJob()
     {
       MOZ_DIAGNOSTIC_ASSERT(!mTarget.IsValid());
       MOZ_DIAGNOSTIC_ASSERT(mPromise.IsEmpty());
     }
 
     SeekTarget mTarget;
-    MediaPromiseHolder<MediaDecoder::SeekPromise> mPromise;
+    MozPromiseHolder<MediaDecoder::SeekPromise> mPromise;
   };
 
   // Queued seek - moves to mPendingSeek when DecodeFirstFrame completes.
   SeekJob mQueuedSeek;
 
   // Position to seek to in microseconds when the seek state transition occurs.
   SeekJob mPendingSeek;
 
@@ -1152,45 +1152,45 @@ private:
   // playback. The flags below are true when the corresponding stream is
   // being "prerolled".
   bool mIsAudioPrerolling;
   bool mIsVideoPrerolling;
 
   // Only one of a given pair of ({Audio,Video}DataPromise, WaitForDataPromise)
   // should exist at any given moment.
 
-  MediaPromiseRequestHolder<MediaDecoderReader::AudioDataPromise> mAudioDataRequest;
-  MediaPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise> mAudioWaitRequest;
+  MozPromiseRequestHolder<MediaDecoderReader::AudioDataPromise> mAudioDataRequest;
+  MozPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise> mAudioWaitRequest;
   const char* AudioRequestStatus()
   {
     MOZ_ASSERT(OnTaskQueue());
     if (mAudioDataRequest.Exists()) {
       MOZ_DIAGNOSTIC_ASSERT(!mAudioWaitRequest.Exists());
       return "pending";
     } else if (mAudioWaitRequest.Exists()) {
       return "waiting";
     }
     return "idle";
   }
 
-  MediaPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise> mVideoWaitRequest;
-  MediaPromiseRequestHolder<MediaDecoderReader::VideoDataPromise> mVideoDataRequest;
+  MozPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise> mVideoWaitRequest;
+  MozPromiseRequestHolder<MediaDecoderReader::VideoDataPromise> mVideoDataRequest;
   const char* VideoRequestStatus()
   {
     MOZ_ASSERT(OnTaskQueue());
     if (mVideoDataRequest.Exists()) {
       MOZ_DIAGNOSTIC_ASSERT(!mVideoWaitRequest.Exists());
       return "pending";
     } else if (mVideoWaitRequest.Exists()) {
       return "waiting";
     }
     return "idle";
   }
 
-  MediaPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise>& WaitRequestRef(MediaData::Type aType)
+  MozPromiseRequestHolder<MediaDecoderReader::WaitForDataPromise>& WaitRequestRef(MediaData::Type aType)
   {
     MOZ_ASSERT(OnTaskQueue());
     return aType == MediaData::AUDIO_DATA ? mAudioWaitRequest : mVideoWaitRequest;
   }
 
   // True if we shouldn't play our audio (but still write it to any capturing
   // streams). When this is true, the audio thread will never start again after
   // it has stopped.
@@ -1256,25 +1256,25 @@ private:
   bool mDropAudioUntilNextDiscontinuity;
   bool mDropVideoUntilNextDiscontinuity;
 
   // True if we need to decode forwards to the seek target inside
   // mCurrentSeekTarget.
   bool mDecodeToSeekTarget;
 
   // Track the current seek promise made by the reader.
-  MediaPromiseRequestHolder<MediaDecoderReader::SeekPromise> mSeekRequest;
+  MozPromiseRequestHolder<MediaDecoderReader::SeekPromise> mSeekRequest;
 
   // We record the playback position before we seek in order to
   // determine where the seek terminated relative to the playback position
   // we were at before the seek.
   int64_t mCurrentTimeBeforeSeek;
 
   // Track our request for metadata from the reader.
-  MediaPromiseRequestHolder<MediaDecoderReader::MetadataPromise> mMetadataRequest;
+  MozPromiseRequestHolder<MediaDecoderReader::MetadataPromise> mMetadataRequest;
 
   // Stores presentation info required for playback. The decoder monitor
   // must be held when accessing this.
   MediaInfo mInfo;
 
   nsAutoPtr<MetadataTags> mMetadataTags;
 
   mozilla::MediaMetadataManager mMetadataManager;
--- a/dom/media/MediaFormatReader.h
+++ b/dom/media/MediaFormatReader.h
@@ -222,22 +222,22 @@ private:
     bool mForceDecodeAhead;
     bool mUpdateScheduled;
     bool mDemuxEOS;
     bool mWaitingForData;
     bool mReceivedNewData;
     bool mDiscontinuity;
 
     // Pending seek.
-    MediaPromiseRequestHolder<MediaTrackDemuxer::SeekPromise> mSeekRequest;
+    MozPromiseRequestHolder<MediaTrackDemuxer::SeekPromise> mSeekRequest;
 
     // Queued demux samples waiting to be decoded.
     nsTArray<nsRefPtr<MediaRawData>> mQueuedSamples;
-    MediaPromiseRequestHolder<MediaTrackDemuxer::SamplesPromise> mDemuxRequest;
-    MediaPromiseHolder<WaitForDataPromise> mWaitingPromise;
+    MozPromiseRequestHolder<MediaTrackDemuxer::SamplesPromise> mDemuxRequest;
+    MozPromiseHolder<WaitForDataPromise> mWaitingPromise;
     bool HasWaitingPromise()
     {
       MOZ_ASSERT(mOwner->OnTaskQueue());
       return !mWaitingPromise.IsEmpty();
     }
 
     // MediaDataDecoder handler's variables.
     bool mOutputRequested;
@@ -303,17 +303,17 @@ private:
   template<typename PromiseType>
   struct DecoderDataWithPromise : public DecoderData {
     DecoderDataWithPromise(MediaFormatReader* aOwner,
                            MediaData::Type aType,
                            uint32_t aDecodeAhead) :
       DecoderData(aOwner, aType, aDecodeAhead)
     {}
 
-    MediaPromiseHolder<PromiseType> mPromise;
+    MozPromiseHolder<PromiseType> mPromise;
 
     bool HasPromise() override
     {
       MOZ_ASSERT(mOwner->OnTaskQueue());
       return !mPromise.IsEmpty();
     }
 
     void RejectPromise(MediaDecoderReader::NotDecodedReason aReason,
@@ -330,17 +330,17 @@ private:
   // Returns true when the decoder for this track needs input.
   bool NeedInput(DecoderData& aDecoder);
 
   DecoderData& GetDecoderData(TrackType aTrack);
 
   // Demuxer objects.
   void OnDemuxerInitDone(nsresult);
   void OnDemuxerInitFailed(DemuxerFailureReason aFailure);
-  MediaPromiseRequestHolder<MediaDataDemuxer::InitPromise> mDemuxerInitRequest;
+  MozPromiseRequestHolder<MediaDataDemuxer::InitPromise> mDemuxerInitRequest;
   void OnDemuxFailed(TrackType aTrack, DemuxerFailureReason aFailure);
 
   void DoDemuxVideo();
   void OnVideoDemuxCompleted(nsRefPtr<MediaTrackDemuxer::SamplesHolder> aSamples);
   void OnVideoDemuxFailed(DemuxerFailureReason aFailure)
   {
     OnDemuxFailed(TrackType::kVideoTrack, aFailure);
   }
@@ -348,32 +348,32 @@ private:
   void DoDemuxAudio();
   void OnAudioDemuxCompleted(nsRefPtr<MediaTrackDemuxer::SamplesHolder> aSamples);
   void OnAudioDemuxFailed(DemuxerFailureReason aFailure)
   {
     OnDemuxFailed(TrackType::kAudioTrack, aFailure);
   }
 
   void SkipVideoDemuxToNextKeyFrame(media::TimeUnit aTimeThreshold);
-  MediaPromiseRequestHolder<MediaTrackDemuxer::SkipAccessPointPromise> mSkipRequest;
+  MozPromiseRequestHolder<MediaTrackDemuxer::SkipAccessPointPromise> mSkipRequest;
   void OnVideoSkipCompleted(uint32_t aSkipped);
   void OnVideoSkipFailed(MediaTrackDemuxer::SkipFailureHolder aFailure);
 
   // The last number of decoded output frames that we've reported to
   // MediaDecoder::NotifyDecoded(). We diff the number of output video
   // frames every time that DecodeVideoData() is called, and report the
   // delta there.
   uint64_t mLastReportedNumDecodedFrames;
 
   layers::LayersBackend mLayersBackendType;
 
   // Metadata objects
   // True if we've read the streams' metadata.
   bool mInitDone;
-  MediaPromiseHolder<MetadataPromise> mMetadataPromise;
+  MozPromiseHolder<MetadataPromise> mMetadataPromise;
   // Accessed from multiple thread, in particular the MediaDecoderStateMachine,
   // however the value doesn't change after reading the metadata.
   bool mSeekable;
   bool IsEncrypted()
   {
     return mIsEncrypted;
   }
   // Accessed from multiple thread, in particular the MediaDecoderStateMachine,
@@ -399,17 +399,17 @@ private:
   void DoAudioSeek();
   void OnAudioSeekCompleted(media::TimeUnit aTime);
   void OnAudioSeekFailed(DemuxerFailureReason aFailure)
   {
     OnSeekFailed(TrackType::kAudioTrack, aFailure);
   }
   // Temporary seek information while we wait for the data
   Maybe<media::TimeUnit> mPendingSeekTime;
-  MediaPromiseHolder<SeekPromise> mSeekPromise;
+  MozPromiseHolder<SeekPromise> mSeekPromise;
 
 #ifdef MOZ_EME
   nsRefPtr<CDMProxy> mCDMProxy;
 #endif
 
   nsRefPtr<SharedDecoderManager> mSharedDecoderManager;
 
   // Main thread objects
deleted file mode 100644
--- a/dom/media/MediaPromise.h
+++ /dev/null
@@ -1,1006 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#if !defined(MediaPromise_h_)
-#define MediaPromise_h_
-
-#include "mozilla/Logging.h"
-
-#include "AbstractThread.h"
-
-#include "nsTArray.h"
-#include "nsThreadUtils.h"
-
-#include "mozilla/DebugOnly.h"
-#include "mozilla/Maybe.h"
-#include "mozilla/Mutex.h"
-#include "mozilla/Monitor.h"
-#include "mozilla/unused.h"
-
-/* Polyfill __func__ on MSVC for consumers to pass to the MediaPromise API. */
-#ifdef _MSC_VER
-#define __func__ __FUNCTION__
-#endif
-
-namespace mozilla {
-
-extern PRLogModuleInfo* gMediaPromiseLog;
-
-#define PROMISE_LOG(x, ...) \
-  MOZ_ASSERT(gMediaPromiseLog); \
-  MOZ_LOG(gMediaPromiseLog, mozilla::LogLevel::Debug, (x, ##__VA_ARGS__))
-
-namespace detail {
-template<typename ThisType, typename Ret, typename ArgType>
-static TrueType TakesArgumentHelper(Ret (ThisType::*)(ArgType));
-template<typename ThisType, typename Ret, typename ArgType>
-static TrueType TakesArgumentHelper(Ret (ThisType::*)(ArgType) const);
-template<typename ThisType, typename Ret>
-static FalseType TakesArgumentHelper(Ret (ThisType::*)());
-template<typename ThisType, typename Ret>
-static FalseType TakesArgumentHelper(Ret (ThisType::*)() const);
-
-template<typename ThisType, typename Ret, typename ArgType>
-static Ret ReturnTypeHelper(Ret (ThisType::*)(ArgType));
-template<typename ThisType, typename Ret, typename ArgType>
-static Ret ReturnTypeHelper(Ret (ThisType::*)(ArgType) const);
-template<typename ThisType, typename Ret>
-static Ret ReturnTypeHelper(Ret (ThisType::*)());
-template<typename ThisType, typename Ret>
-static Ret ReturnTypeHelper(Ret (ThisType::*)() const);
-
-template<typename MethodType>
-struct ReturnType {
-  typedef decltype(detail::ReturnTypeHelper(DeclVal<MethodType>())) Type;
-};
-
-} // namespace detail
-
-template<typename MethodType>
-struct TakesArgument {
-  static const bool value = decltype(detail::TakesArgumentHelper(DeclVal<MethodType>()))::value;
-};
-
-template<typename MethodType, typename TargetType>
-struct ReturnTypeIs {
-  static const bool value = IsConvertible<typename detail::ReturnType<MethodType>::Type, TargetType>::value;
-};
-
-/*
- * A promise manages an asynchronous request that may or may not be able to be
- * fulfilled immediately. When an API returns a promise, the consumer may attach
- * callbacks to be invoked (asynchronously, on a specified thread) when the
- * request is either completed (resolved) or cannot be completed (rejected).
- *
- * MediaPromises attempt to mirror the spirit of JS Promises to the extent that
- * is possible (and desirable) in C++. While the intent is that MediaPromises
- * feel familiar to programmers who are accustomed to their JS-implemented cousin,
- * we don't shy away from imposing restrictions and adding features that make
- * sense for the use cases we encounter.
- *
- * A MediaPromise is ThreadSafe, and may be ->Then()ed on any thread. The Then()
- * call accepts resolve and reject callbacks, and returns a MediaPromise::Request.
- * The Request object serves several purposes for the consumer.
- *
- *   (1) It allows the caller to cancel the delivery of the resolve/reject value
- *       if it has not already occurred, via Disconnect() (this must be done on
- *       the target thread to avoid racing).
- *
- *   (2) It provides access to a "Completion Promise", which is roughly analagous
- *       to the Promise returned directly by ->then() calls on JS promises. If
- *       the resolve/reject callback returns a new MediaPromise, that promise is
- *       chained to the completion promise, such that its resolve/reject value
- *       will be forwarded along when it arrives. If the resolve/reject callback
- *       returns void, the completion promise is resolved/rejected with the same
- *       value that was passed to the callback.
- *
- * The MediaPromise APIs skirt traditional XPCOM convention by returning nsRefPtrs
- * (rather than already_AddRefed) from various methods. This is done to allow elegant
- * chaining of calls without cluttering up the code with intermediate variables, and
- * without introducing separate API variants for callers that want a return value
- * (from, say, ->Then()) from those that don't.
- *
- * When IsExclusive is true, the MediaPromise does a release-mode assertion that
- * there is at most one call to either Then(...) or ChainTo(...).
- */
-
-class MediaPromiseRefcountable
-{
-public:
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaPromiseRefcountable)
-protected:
-  virtual ~MediaPromiseRefcountable() {}
-};
-
-template<typename T> class MediaPromiseHolder;
-template<typename ResolveValueT, typename RejectValueT, bool IsExclusive>
-class MediaPromise : public MediaPromiseRefcountable
-{
-public:
-  typedef ResolveValueT ResolveValueType;
-  typedef RejectValueT RejectValueType;
-  class ResolveOrRejectValue
-  {
-  public:
-    template<typename ResolveValueType_>
-    void SetResolve(ResolveValueType_&& aResolveValue)
-    {
-      MOZ_ASSERT(IsNothing());
-      mResolveValue.emplace(Forward<ResolveValueType_>(aResolveValue));
-    }
-
-    template<typename RejectValueType_>
-    void SetReject(RejectValueType_&& aRejectValue)
-    {
-      MOZ_ASSERT(IsNothing());
-      mRejectValue.emplace(Forward<RejectValueType_>(aRejectValue));
-    }
-
-    template<typename ResolveValueType_>
-    static ResolveOrRejectValue MakeResolve(ResolveValueType_&& aResolveValue)
-    {
-      ResolveOrRejectValue val;
-      val.SetResolve(Forward<ResolveValueType_>(aResolveValue));
-      return val;
-    }
-
-    template<typename RejectValueType_>
-    static ResolveOrRejectValue MakeReject(RejectValueType_&& aRejectValue)
-    {
-      ResolveOrRejectValue val;
-      val.SetReject(Forward<RejectValueType_>(aRejectValue));
-      return val;
-    }
-
-    bool IsResolve() const { return mResolveValue.isSome(); }
-    bool IsReject() const { return mRejectValue.isSome(); }
-    bool IsNothing() const { return mResolveValue.isNothing() && mRejectValue.isNothing(); }
-
-    const ResolveValueType& ResolveValue() const { return mResolveValue.ref(); }
-    const RejectValueType& RejectValue() const { return mRejectValue.ref(); }
-
-  private:
-    Maybe<ResolveValueType> mResolveValue;
-    Maybe<RejectValueType> mRejectValue;
-  };
-
-protected:
-  // MediaPromise is the public type, and never constructed directly. Construct
-  // a MediaPromise::Private, defined below.
-  explicit MediaPromise(const char* aCreationSite)
-    : mCreationSite(aCreationSite)
-    , mMutex("MediaPromise Mutex")
-    , mHaveRequest(false)
-  {
-    PROMISE_LOG("%s creating MediaPromise (%p)", mCreationSite, this);
-  }
-
-public:
-  // MediaPromise::Private allows us to separate the public interface (upon which
-  // consumers of the promise may invoke methods like Then()) from the private
-  // interface (upon which the creator of the promise may invoke Resolve() or
-  // Reject()). APIs should create and store a MediaPromise::Private (usually
-  // via a MediaPromiseHolder), and return a MediaPromise to consumers.
-  //
-  // NB: We can include the definition of this class inline once B2G ICS is gone.
-  class Private;
-
-  template<typename ResolveValueType_>
-  static nsRefPtr<MediaPromise>
-  CreateAndResolve(ResolveValueType_&& aResolveValue, const char* aResolveSite)
-  {
-    nsRefPtr<typename MediaPromise::Private> p = new MediaPromise::Private(aResolveSite);
-    p->Resolve(Forward<ResolveValueType_>(aResolveValue), aResolveSite);
-    return p.forget();
-  }
-
-  template<typename RejectValueType_>
-  static nsRefPtr<MediaPromise>
-  CreateAndReject(RejectValueType_&& aRejectValue, const char* aRejectSite)
-  {
-    nsRefPtr<typename MediaPromise::Private> p = new MediaPromise::Private(aRejectSite);
-    p->Reject(Forward<RejectValueType_>(aRejectValue), aRejectSite);
-    return p.forget();
-  }
-
-  typedef MediaPromise<nsTArray<ResolveValueType>, RejectValueType, IsExclusive> AllPromiseType;
-private:
-  class AllPromiseHolder : public MediaPromiseRefcountable
-  {
-  public:
-    explicit AllPromiseHolder(size_t aDependentPromises)
-      : mPromise(new typename AllPromiseType::Private(__func__))
-      , mOutstandingPromises(aDependentPromises)
-    {
-      mResolveValues.SetLength(aDependentPromises);
-    }
-
-    void Resolve(size_t aIndex, const ResolveValueType& aResolveValue)
-    {
-      if (!mPromise) {
-        // Already rejected.
-        return;
-      }
-
-      mResolveValues[aIndex].emplace(aResolveValue);
-      if (--mOutstandingPromises == 0) {
-        nsTArray<ResolveValueType> resolveValues;
-        resolveValues.SetCapacity(mResolveValues.Length());
-        for (size_t i = 0; i < mResolveValues.Length(); ++i) {
-          resolveValues.AppendElement(mResolveValues[i].ref());
-        }
-
-        mPromise->Resolve(resolveValues, __func__);
-        mPromise = nullptr;
-        mResolveValues.Clear();
-      }
-    }
-
-    void Reject(const RejectValueType& aRejectValue)
-    {
-      mPromise->Reject(aRejectValue, __func__);
-      mPromise = nullptr;
-      mResolveValues.Clear();
-    }
-
-    AllPromiseType* Promise() { return mPromise; }
-
-  private:
-    nsTArray<Maybe<ResolveValueType>> mResolveValues;
-    nsRefPtr<typename AllPromiseType::Private> mPromise;
-    size_t mOutstandingPromises;
-  };
-public:
-
-  static nsRefPtr<AllPromiseType> All(AbstractThread* aProcessingThread, nsTArray<nsRefPtr<MediaPromise>>& aPromises)
-  {
-    nsRefPtr<AllPromiseHolder> holder = new AllPromiseHolder(aPromises.Length());
-    for (size_t i = 0; i < aPromises.Length(); ++i) {
-      aPromises[i]->Then(aProcessingThread, __func__,
-        [holder, i] (ResolveValueType aResolveValue) -> void { holder->Resolve(i, aResolveValue); },
-        [holder] (RejectValueType aRejectValue) -> void { holder->Reject(aRejectValue); }
-      );
-    }
-    return holder->Promise();
-  }
-
-  class Request : public MediaPromiseRefcountable
-  {
-  public:
-    virtual void Disconnect() = 0;
-
-    // MSVC complains when an inner class (ThenValueBase::{Resolve,Reject}Runnable)
-    // tries to access an inherited protected member.
-    bool IsDisconnected() const { return mDisconnected; }
-
-    virtual MediaPromise* CompletionPromise() = 0;
-
-  protected:
-    Request() : mComplete(false), mDisconnected(false) {}
-    virtual ~Request() {}
-
-    bool mComplete;
-    bool mDisconnected;
-  };
-
-protected:
-
-  /*
-   * A ThenValue tracks a single consumer waiting on the promise. When a consumer
-   * invokes promise->Then(...), a ThenValue is created. Once the Promise is
-   * resolved or rejected, a {Resolve,Reject}Runnable is dispatched, which
-   * invokes the resolve/reject method and then deletes the ThenValue.
-   */
-  class ThenValueBase : public Request
-  {
-  public:
-    class ResolveOrRejectRunnable : public nsRunnable
-    {
-    public:
-      ResolveOrRejectRunnable(ThenValueBase* aThenValue, MediaPromise* aPromise)
-        : mThenValue(aThenValue)
-        , mPromise(aPromise)
-      {
-        MOZ_DIAGNOSTIC_ASSERT(!mPromise->IsPending());
-      }
-
-      ~ResolveOrRejectRunnable()
-      {
-        MOZ_DIAGNOSTIC_ASSERT(!mThenValue || mThenValue->IsDisconnected());
-      }
-
-      NS_IMETHODIMP Run()
-      {
-        PROMISE_LOG("ResolveOrRejectRunnable::Run() [this=%p]", this);
-        mThenValue->DoResolveOrReject(mPromise->Value());
-        mThenValue = nullptr;
-        mPromise = nullptr;
-        return NS_OK;
-      }
-
-    private:
-      nsRefPtr<ThenValueBase> mThenValue;
-      nsRefPtr<MediaPromise> mPromise;
-    };
-
-    explicit ThenValueBase(AbstractThread* aResponseTarget, const char* aCallSite)
-      : mResponseTarget(aResponseTarget), mCallSite(aCallSite) {}
-
-    MediaPromise* CompletionPromise() override
-    {
-      MOZ_DIAGNOSTIC_ASSERT(mResponseTarget->IsCurrentThreadIn());
-      MOZ_DIAGNOSTIC_ASSERT(!Request::mComplete);
-      if (!mCompletionPromise) {
-        mCompletionPromise = new MediaPromise::Private("<completion promise>");
-      }
-      return mCompletionPromise;
-    }
-
-    void Dispatch(MediaPromise *aPromise)
-    {
-      aPromise->mMutex.AssertCurrentThreadOwns();
-      MOZ_ASSERT(!aPromise->IsPending());
-
-      nsRefPtr<nsRunnable> runnable =
-        static_cast<nsRunnable*>(new (typename ThenValueBase::ResolveOrRejectRunnable)(this, aPromise));
-      PROMISE_LOG("%s Then() call made from %s [Runnable=%p, Promise=%p, ThenValue=%p]",
-                  aPromise->mValue.IsResolve() ? "Resolving" : "Rejecting", ThenValueBase::mCallSite,
-                  runnable.get(), aPromise, this);
-
-      // Promise consumers are allowed to disconnect the Request object and
-      // then shut down the thread or task queue that the promise result would
-      // be dispatched on. So we unfortunately can't assert that promise
-      // dispatch succeeds. :-(
-      mResponseTarget->Dispatch(runnable.forget(), AbstractThread::DontAssertDispatchSuccess);
-    }
-
-    virtual void Disconnect() override
-    {
-      MOZ_ASSERT(ThenValueBase::mResponseTarget->IsCurrentThreadIn());
-      MOZ_DIAGNOSTIC_ASSERT(!Request::mComplete);
-      Request::mDisconnected = true;
-
-      // We could support rejecting the completion promise on disconnection, but
-      // then we'd need to have some sort of default reject value. The use cases
-      // of disconnection and completion promise chaining seem pretty orthogonal,
-      // so let's use assert against it.
-      MOZ_DIAGNOSTIC_ASSERT(!mCompletionPromise);
-    }
-
-  protected:
-    virtual already_AddRefed<MediaPromise> DoResolveOrRejectInternal(const ResolveOrRejectValue& aValue) = 0;
-
-    void DoResolveOrReject(const ResolveOrRejectValue& aValue)
-    {
-      Request::mComplete = true;
-      if (Request::mDisconnected) {
-        PROMISE_LOG("ThenValue::DoResolveOrReject disconnected - bailing out [this=%p]", this);
-        return;
-      }
-
-      // Invoke the resolve or reject method.
-      nsRefPtr<MediaPromise> p = DoResolveOrRejectInternal(aValue);
-
-      // If there's a completion promise, resolve it appropriately with the
-      // result of the method.
-      //
-      // We jump through some hoops to cast to MediaPromise::Private here. This
-      // can go away when we can just declare mCompletionPromise as
-      // MediaPromise::Private. See the declaration below.
-      nsRefPtr<MediaPromise::Private> completionPromise =
-        dont_AddRef(static_cast<MediaPromise::Private*>(mCompletionPromise.forget().take()));
-      if (completionPromise) {
-        if (p) {
-          p->ChainTo(completionPromise.forget(), "<chained completion promise>");
-        } else {
-          completionPromise->ResolveOrReject(aValue, "<completion of non-promise-returning method>");
-        }
-      }
-    }
-
-    nsRefPtr<AbstractThread> mResponseTarget; // May be released on any thread.
-
-    // Declaring nsRefPtr<MediaPromise::Private> here causes build failures
-    // on MSVC because MediaPromise::Private is only forward-declared at this
-    // point. This hack can go away when we inline-declare MediaPromise::Private,
-    // which is blocked on the B2G ICS compiler being too old.
-    nsRefPtr<MediaPromise> mCompletionPromise;
-
-    const char* mCallSite;
-  };
-
-  /*
-   * We create two overloads for invoking Resolve/Reject Methods so as to
-   * make the resolve/reject value argument "optional".
-   */
-
-  template<typename ThisType, typename MethodType, typename ValueType>
-  static typename EnableIf<ReturnTypeIs<MethodType, nsRefPtr<MediaPromise>>::value &&
-                           TakesArgument<MethodType>::value,
-                           already_AddRefed<MediaPromise>>::Type
-  InvokeCallbackMethod(ThisType* aThisVal, MethodType aMethod, ValueType&& aValue)
-  {
-    return ((*aThisVal).*aMethod)(Forward<ValueType>(aValue)).forget();
-  }
-
-  template<typename ThisType, typename MethodType, typename ValueType>
-  static typename EnableIf<ReturnTypeIs<MethodType, void>::value &&
-                           TakesArgument<MethodType>::value,
-                           already_AddRefed<MediaPromise>>::Type
-  InvokeCallbackMethod(ThisType* aThisVal, MethodType aMethod, ValueType&& aValue)
-  {
-    ((*aThisVal).*aMethod)(Forward<ValueType>(aValue));
-    return nullptr;
-  }
-
-  template<typename ThisType, typename MethodType, typename ValueType>
-  static typename EnableIf<ReturnTypeIs<MethodType, nsRefPtr<MediaPromise>>::value &&
-                           !TakesArgument<MethodType>::value,
-                           already_AddRefed<MediaPromise>>::Type
-  InvokeCallbackMethod(ThisType* aThisVal, MethodType aMethod, ValueType&& aValue)
-  {
-    return ((*aThisVal).*aMethod)().forget();
-  }
-
-  template<typename ThisType, typename MethodType, typename ValueType>
-  static typename EnableIf<ReturnTypeIs<MethodType, void>::value &&
-                           !TakesArgument<MethodType>::value,
-                           already_AddRefed<MediaPromise>>::Type
-  InvokeCallbackMethod(ThisType* aThisVal, MethodType aMethod, ValueType&& aValue)
-  {
-    ((*aThisVal).*aMethod)();
-    return nullptr;
-  }
-
-  template<typename ThisType, typename ResolveMethodType, typename RejectMethodType>
-  class MethodThenValue : public ThenValueBase
-  {
-  public:
-    MethodThenValue(AbstractThread* aResponseTarget, ThisType* aThisVal,
-                    ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod,
-                    const char* aCallSite)
-      : ThenValueBase(aResponseTarget, aCallSite)
-      , mThisVal(aThisVal)
-      , mResolveMethod(aResolveMethod)
-      , mRejectMethod(aRejectMethod) {}
-
-  virtual void Disconnect() override
-  {
-    ThenValueBase::Disconnect();
-
-    // If a Request has been disconnected, we don't guarantee that the
-    // resolve/reject runnable will be dispatched. Null out our refcounted
-    // this-value now so that it's released predictably on the dispatch thread.
-    mThisVal = nullptr;
-  }
-
-  protected:
-    virtual already_AddRefed<MediaPromise> DoResolveOrRejectInternal(const ResolveOrRejectValue& aValue) override
-    {
-      nsRefPtr<MediaPromise> completion;
-      if (aValue.IsResolve()) {
-        completion = InvokeCallbackMethod(mThisVal.get(), mResolveMethod, aValue.ResolveValue());
-      } else {
-        completion = InvokeCallbackMethod(mThisVal.get(), mRejectMethod, aValue.RejectValue());
-      }
-
-      // Null out mThisVal after invoking the callback so that any references are
-      // released predictably on the dispatch thread. Otherwise, it would be
-      // released on whatever thread last drops its reference to the ThenValue,
-      // which may or may not be ok.
-      mThisVal = nullptr;
-
-      return completion.forget();
-    }
-
-  private:
-    nsRefPtr<ThisType> mThisVal; // Only accessed and refcounted on dispatch thread.
-    ResolveMethodType mResolveMethod;
-    RejectMethodType mRejectMethod;
-  };
-
-  // NB: We could use std::function here instead of a template if it were supported. :-(
-  template<typename ResolveFunction, typename RejectFunction>
-  class FunctionThenValue : public ThenValueBase
-  {
-  public:
-    FunctionThenValue(AbstractThread* aResponseTarget,
-                      ResolveFunction&& aResolveFunction,
-                      RejectFunction&& aRejectFunction,
-                      const char* aCallSite)
-      : ThenValueBase(aResponseTarget, aCallSite)
-    {
-      mResolveFunction.emplace(Move(aResolveFunction));
-      mRejectFunction.emplace(Move(aRejectFunction));
-    }
-
-  virtual void Disconnect() override
-  {
-    ThenValueBase::Disconnect();
-
-    // If a Request has been disconnected, we don't guarantee that the
-    // resolve/reject runnable will be dispatched. Destroy our callbacks
-    // now so that any references in closures are released predictable on
-    // the dispatch thread.
-    mResolveFunction.reset();
-    mRejectFunction.reset();
-  }
-
-  protected:
-    virtual already_AddRefed<MediaPromise> DoResolveOrRejectInternal(const ResolveOrRejectValue& aValue) override
-    {
-      // Note: The usage of InvokeCallbackMethod here requires that
-      // ResolveFunction/RejectFunction are capture-lambdas (i.e. anonymous
-      // classes with ::operator()), since it allows us to share code more easily.
-      // We could fix this if need be, though it's quite easy to work around by
-      // just capturing something.
-      nsRefPtr<MediaPromise> completion;
-      if (aValue.IsResolve()) {
-        completion = InvokeCallbackMethod(mResolveFunction.ptr(), &ResolveFunction::operator(), aValue.ResolveValue());
-      } else {
-        completion = InvokeCallbackMethod(mRejectFunction.ptr(), &RejectFunction::operator(), aValue.RejectValue());
-      }
-
-      // Destroy callbacks after invocation so that any references in closures are
-      // released predictably on the dispatch thread. Otherwise, they would be
-      // released on whatever thread last drops its reference to the ThenValue,
-      // which may or may not be ok.
-      mResolveFunction.reset();
-      mRejectFunction.reset();
-
-      return completion.forget();
-    }
-
-  private:
-    Maybe<ResolveFunction> mResolveFunction; // Only accessed and deleted on dispatch thread.
-    Maybe<RejectFunction> mRejectFunction; // Only accessed and deleted on dispatch thread.
-  };
-
-public:
-  void ThenInternal(AbstractThread* aResponseThread, ThenValueBase* aThenValue,
-                    const char* aCallSite)
-  {
-    MutexAutoLock lock(mMutex);
-    MOZ_ASSERT(aResponseThread->IsDispatchReliable());
-    MOZ_DIAGNOSTIC_ASSERT(!IsExclusive || !mHaveRequest);
-    mHaveRequest = true;
-    PROMISE_LOG("%s invoking Then() [this=%p, aThenValue=%p, isPending=%d]",
-                aCallSite, this, aThenValue, (int) IsPending());
-    if (!IsPending()) {
-      aThenValue->Dispatch(this);
-    } else {
-      mThenValues.AppendElement(aThenValue);
-    }
-  }
-
-public:
-
-  template<typename ThisType, typename ResolveMethodType, typename RejectMethodType>
-  nsRefPtr<Request> Then(AbstractThread* aResponseThread, const char* aCallSite, ThisType* aThisVal,
-                         ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod)
-  {
-    nsRefPtr<ThenValueBase> thenValue = new MethodThenValue<ThisType, ResolveMethodType, RejectMethodType>(
-                                              aResponseThread, aThisVal, aResolveMethod, aRejectMethod, aCallSite);
-    ThenInternal(aResponseThread, thenValue, aCallSite);
-    return thenValue.forget(); // Implicit conversion from already_AddRefed<ThenValueBase> to nsRefPtr<Request>.
-  }
-
-  template<typename ResolveFunction, typename RejectFunction>
-  nsRefPtr<Request> Then(AbstractThread* aResponseThread, const char* aCallSite,
-                         ResolveFunction&& aResolveFunction, RejectFunction&& aRejectFunction)
-  {
-    nsRefPtr<ThenValueBase> thenValue = new FunctionThenValue<ResolveFunction, RejectFunction>(aResponseThread,
-                                              Move(aResolveFunction), Move(aRejectFunction), aCallSite);
-    ThenInternal(aResponseThread, thenValue, aCallSite);
-    return thenValue.forget(); // Implicit conversion from already_AddRefed<ThenValueBase> to nsRefPtr<Request>.
-  }
-
-  void ChainTo(already_AddRefed<Private> aChainedPromise, const char* aCallSite)
-  {
-    MutexAutoLock lock(mMutex);
-    MOZ_DIAGNOSTIC_ASSERT(!IsExclusive || !mHaveRequest);
-    mHaveRequest = true;
-    nsRefPtr<Private> chainedPromise = aChainedPromise;
-    PROMISE_LOG("%s invoking Chain() [this=%p, chainedPromise=%p, isPending=%d]",
-                aCallSite, this, chainedPromise.get(), (int) IsPending());
-    if (!IsPending()) {
-      ForwardTo(chainedPromise);
-    } else {
-      mChainedPromises.AppendElement(chainedPromise);
-    }
-  }
-
-protected:
-  bool IsPending() const { return mValue.IsNothing(); }
-  const ResolveOrRejectValue& Value() const
-  {
-    // This method should only be called once the value has stabilized. As
-    // such, we don't need to acquire the lock here.
-    MOZ_DIAGNOSTIC_ASSERT(!IsPending());
-    return mValue;
-  }
-
-  void DispatchAll()
-  {
-    mMutex.AssertCurrentThreadOwns();
-    for (size_t i = 0; i < mThenValues.Length(); ++i) {
-      mThenValues[i]->Dispatch(this);
-    }
-    mThenValues.Clear();
-
-    for (size_t i = 0; i < mChainedPromises.Length(); ++i) {
-      ForwardTo(mChainedPromises[i]);
-    }
-    mChainedPromises.Clear();
-  }
-
-  void ForwardTo(Private* aOther)
-  {
-    MOZ_ASSERT(!IsPending());
-    if (mValue.IsResolve()) {
-      aOther->Resolve(mValue.ResolveValue(), "<chained promise>");
-    } else {
-      aOther->Reject(mValue.RejectValue(), "<chained promise>");
-    }
-  }
-
-  virtual ~MediaPromise()
-  {
-    PROMISE_LOG("MediaPromise::~MediaPromise [this=%p]", this);
-    MOZ_ASSERT(!IsPending());
-    MOZ_ASSERT(mThenValues.IsEmpty());
-    MOZ_ASSERT(mChainedPromises.IsEmpty());
-  };
-
-  const char* mCreationSite; // For logging
-  Mutex mMutex;
-  ResolveOrRejectValue mValue;
-  nsTArray<nsRefPtr<ThenValueBase>> mThenValues;
-  nsTArray<nsRefPtr<Private>> mChainedPromises;
-  bool mHaveRequest;
-};
-
-template<typename ResolveValueT, typename RejectValueT, bool IsExclusive>
-class MediaPromise<ResolveValueT, RejectValueT, IsExclusive>::Private
-  : public MediaPromise<ResolveValueT, RejectValueT, IsExclusive>
-{
-public:
-  explicit Private(const char* aCreationSite) : MediaPromise(aCreationSite) {}
-
-  template<typename ResolveValueT_>
-  void Resolve(ResolveValueT_&& aResolveValue, const char* aResolveSite)
-  {
-    MutexAutoLock lock(mMutex);
-    MOZ_ASSERT(IsPending());
-    PROMISE_LOG("%s resolving MediaPromise (%p created at %s)", aResolveSite, this, mCreationSite);
-    mValue.SetResolve(Forward<ResolveValueT_>(aResolveValue));
-    DispatchAll();
-  }
-
-  template<typename RejectValueT_>
-  void Reject(RejectValueT_&& aRejectValue, const char* aRejectSite)
-  {
-    MutexAutoLock lock(mMutex);
-    MOZ_ASSERT(IsPending());
-    PROMISE_LOG("%s rejecting MediaPromise (%p created at %s)", aRejectSite, this, mCreationSite);
-    mValue.SetReject(Forward<RejectValueT_>(aRejectValue));
-    DispatchAll();
-  }
-
-  template<typename ResolveOrRejectValue_>
-  void ResolveOrReject(ResolveOrRejectValue_&& aValue, const char* aSite)
-  {
-    MutexAutoLock lock(mMutex);
-    MOZ_ASSERT(IsPending());
-    PROMISE_LOG("%s resolveOrRejecting MediaPromise (%p created at %s)", aSite, this, mCreationSite);
-    mValue = Forward<ResolveOrRejectValue_>(aValue);
-    DispatchAll();
-  }
-};
-
-// A generic promise type that does the trick for simple use cases.
-typedef MediaPromise<bool, nsresult, /* IsExclusive = */ false> GenericPromise;
-
-/*
- * Class to encapsulate a promise for a particular role. Use this as the member
- * variable for a class whose method returns a promise.
- */
-template<typename PromiseType>
-class MediaPromiseHolder
-{
-public:
-  MediaPromiseHolder()
-    : mMonitor(nullptr) {}
-
-  // Move semantics.
-  MediaPromiseHolder& operator=(MediaPromiseHolder&& aOther)
-  {
-    MOZ_ASSERT(!mMonitor && !aOther.mMonitor);
-    MOZ_DIAGNOSTIC_ASSERT(!mPromise);
-    mPromise = aOther.mPromise;
-    aOther.mPromise = nullptr;
-    return *this;
-  }
-
-  ~MediaPromiseHolder() { MOZ_ASSERT(!mPromise); }
-
-  already_AddRefed<PromiseType> Ensure(const char* aMethodName) {
-    if (mMonitor) {
-      mMonitor->AssertCurrentThreadOwns();
-    }
-    if (!mPromise) {
-      mPromise = new (typename PromiseType::Private)(aMethodName);
-    }
-    nsRefPtr<PromiseType> p = mPromise.get();
-    return p.forget();
-  }
-
-  // Provide a Monitor that should always be held when accessing this instance.
-  void SetMonitor(Monitor* aMonitor) { mMonitor = aMonitor; }
-
-  bool IsEmpty()
-  {
-    if (mMonitor) {
-      mMonitor->AssertCurrentThreadOwns();
-    }
-    return !mPromise;
-  }
-
-  already_AddRefed<typename PromiseType::Private> Steal()
-  {
-    if (mMonitor) {
-      mMonitor->AssertCurrentThreadOwns();
-    }
-
-    nsRefPtr<typename PromiseType::Private> p = mPromise;
-    mPromise = nullptr;
-    return p.forget();
-  }
-
-  void Resolve(typename PromiseType::ResolveValueType aResolveValue,
-               const char* aMethodName)
-  {
-    if (mMonitor) {
-      mMonitor->AssertCurrentThreadOwns();
-    }
-    MOZ_ASSERT(mPromise);
-    mPromise->Resolve(aResolveValue, aMethodName);
-    mPromise = nullptr;
-  }
-
-
-  void ResolveIfExists(typename PromiseType::ResolveValueType aResolveValue,
-                       const char* aMethodName)
-  {
-    if (!IsEmpty()) {
-      Resolve(aResolveValue, aMethodName);
-    }
-  }
-
-  void Reject(typename PromiseType::RejectValueType aRejectValue,
-              const char* aMethodName)
-  {
-    if (mMonitor) {
-      mMonitor->AssertCurrentThreadOwns();
-    }
-    MOZ_ASSERT(mPromise);
-    mPromise->Reject(aRejectValue, aMethodName);
-    mPromise = nullptr;
-  }
-
-
-  void RejectIfExists(typename PromiseType::RejectValueType aRejectValue,
-                      const char* aMethodName)
-  {
-    if (!IsEmpty()) {
-      Reject(aRejectValue, aMethodName);
-    }
-  }
-
-private:
-  Monitor* mMonitor;
-  nsRefPtr<typename PromiseType::Private> mPromise;
-};
-
-/*
- * Class to encapsulate a MediaPromise::Request reference. Use this as the member
- * variable for a class waiting on a media promise.
- */
-template<typename PromiseType>
-class MediaPromiseRequestHolder
-{
-public:
-  MediaPromiseRequestHolder() {}
-  ~MediaPromiseRequestHolder() { MOZ_ASSERT(!mRequest); }
-
-  void Begin(typename PromiseType::Request* aRequest)
-  {
-    MOZ_DIAGNOSTIC_ASSERT(!Exists());
-    mRequest = aRequest;
-  }
-
-  void Complete()
-  {
-    MOZ_DIAGNOSTIC_ASSERT(Exists());
-    mRequest = nullptr;
-  }
-
-  // Disconnects and forgets an outstanding promise. The resolve/reject methods
-  // will never be called.
-  void Disconnect() {
-    MOZ_ASSERT(Exists());
-    mRequest->Disconnect();
-    mRequest = nullptr;
-  }
-
-  void DisconnectIfExists() {
-    if (Exists()) {
-      Disconnect();
-    }
-  }
-
-  bool Exists() { return !!mRequest; }
-
-private:
-  nsRefPtr<typename PromiseType::Request> mRequest;
-};
-
-// Proxy Media Calls.
-//
-// This machinery allows callers to schedule a promise-returning method to be
-// invoked asynchronously on a given thread, while at the same time receiving
-// a promise upon which to invoke Then() immediately. ProxyMediaCall dispatches
-// a task to invoke the method on the proper thread and also chain the resulting
-// promise to the one that the caller received, so that resolve/reject values
-// are forwarded through.
-
-namespace detail {
-
-template<typename PromiseType>
-class MethodCallBase
-{
-public:
-  MethodCallBase() { MOZ_COUNT_CTOR(MethodCallBase); }
-  virtual nsRefPtr<PromiseType> Invoke() = 0;
-  virtual ~MethodCallBase() { MOZ_COUNT_DTOR(MethodCallBase); };
-};
-
-template<typename PromiseType, typename ThisType>
-class MethodCallWithNoArgs : public MethodCallBase<PromiseType>
-{
-public:
-  typedef nsRefPtr<PromiseType>(ThisType::*Type)();
-  MethodCallWithNoArgs(ThisType* aThisVal, Type aMethod)
-    : mThisVal(aThisVal), mMethod(aMethod) {}
-  nsRefPtr<PromiseType> Invoke() override { return ((*mThisVal).*mMethod)(); }
-protected:
-  nsRefPtr<ThisType> mThisVal;
-  Type mMethod;
-};
-
-template<typename PromiseType, typename ThisType, typename Arg1Type>
-class MethodCallWithOneArg : public MethodCallBase<PromiseType>
-{
-public:
-  typedef nsRefPtr<PromiseType>(ThisType::*Type)(Arg1Type);
-  MethodCallWithOneArg(ThisType* aThisVal, Type aMethod, Arg1Type aArg1)
-    : mThisVal(aThisVal), mMethod(aMethod), mArg1(aArg1) {}
-  nsRefPtr<PromiseType> Invoke() override { return ((*mThisVal).*mMethod)(mArg1); }
-protected:
-  nsRefPtr<ThisType> mThisVal;
-  Type mMethod;
-  Arg1Type mArg1;
-};
-
-template<typename PromiseType, typename ThisType, typename Arg1Type, typename Arg2Type>
-class MethodCallWithTwoArgs : public MethodCallBase<PromiseType>
-{
-public:
-  typedef nsRefPtr<PromiseType>(ThisType::*Type)(Arg1Type, Arg2Type);
-  MethodCallWithTwoArgs(ThisType* aThisVal, Type aMethod, Arg1Type aArg1, Arg2Type aArg2)
-    : mThisVal(aThisVal), mMethod(aMethod), mArg1(aArg1), mArg2(aArg2) {}
-  nsRefPtr<PromiseType> Invoke() override { return ((*mThisVal).*mMethod)(mArg1, mArg2); }
-protected:
-  nsRefPtr<ThisType> mThisVal;
-  Type mMethod;
-  Arg1Type mArg1;
-  Arg2Type mArg2;
-};
-
-template<typename PromiseType, typename ThisType, typename Arg1Type, typename Arg2Type, typename Arg3Type>
-class MethodCallWithThreeArgs : public MethodCallBase<PromiseType>
-{
-public:
-  typedef nsRefPtr<PromiseType>(ThisType::*Type)(Arg1Type, Arg2Type, Arg3Type);
-  MethodCallWithThreeArgs(ThisType* aThisVal, Type aMethod, Arg1Type aArg1, Arg2Type aArg2, Arg3Type aArg3)
-    : mThisVal(aThisVal), mMethod(aMethod), mArg1(aArg1), mArg2(aArg2), mArg3(aArg3) {}
-  nsRefPtr<PromiseType> Invoke() override { return ((*mThisVal).*mMethod)(mArg1, mArg2, mArg3); }
-protected:
-  nsRefPtr<ThisType> mThisVal;
-  Type mMethod;
-  Arg1Type mArg1;
-  Arg2Type mArg2;
-  Arg3Type mArg3;
-};
-
-template<typename PromiseType>
-class ProxyRunnable : public nsRunnable
-{
-public:
-  ProxyRunnable(typename PromiseType::Private* aProxyPromise, MethodCallBase<PromiseType>* aMethodCall)
-    : mProxyPromise(aProxyPromise), mMethodCall(aMethodCall) {}
-
-  NS_IMETHODIMP Run()
-  {
-    nsRefPtr<PromiseType> p = mMethodCall->Invoke();
-    mMethodCall = nullptr;
-    p->ChainTo(mProxyPromise.forget(), "<Proxy Promise>");
-    return NS_OK;
-  }
-
-private:
-  nsRefPtr<typename PromiseType::Private> mProxyPromise;
-  nsAutoPtr<MethodCallBase<PromiseType>> mMethodCall;
-};
-
-template<typename PromiseType>
-static nsRefPtr<PromiseType>
-ProxyInternal(AbstractThread* aTarget, MethodCallBase<PromiseType>* aMethodCall, const char* aCallerName)
-{
-  nsRefPtr<typename PromiseType::Private> p = new (typename PromiseType::Private)(aCallerName);
-  nsRefPtr<ProxyRunnable<PromiseType>> r = new ProxyRunnable<PromiseType>(p, aMethodCall);
-  MOZ_ASSERT(aTarget->IsDispatchReliable());
-  aTarget->Dispatch(r.forget());
-  return p.forget();
-}
-
-} // namespace detail
-
-template<typename PromiseType, typename ThisType>
-static nsRefPtr<PromiseType>
-ProxyMediaCall(AbstractThread* aTarget, ThisType* aThisVal, const char* aCallerName,
-               nsRefPtr<PromiseType>(ThisType::*aMethod)())
-{
-  typedef detail::MethodCallWithNoArgs<PromiseType, ThisType> MethodCallType;
-  MethodCallType* methodCall = new MethodCallType(aThisVal, aMethod);
-  return detail::ProxyInternal(aTarget, methodCall, aCallerName);
-}
-
-template<typename PromiseType, typename ThisType, typename Arg1Type>
-static nsRefPtr<PromiseType>
-ProxyMediaCall(AbstractThread* aTarget, ThisType* aThisVal, const char* aCallerName,
-               nsRefPtr<PromiseType>(ThisType::*aMethod)(Arg1Type), Arg1Type aArg1)
-{
-  typedef detail::MethodCallWithOneArg<PromiseType, ThisType, Arg1Type> MethodCallType;
-  MethodCallType* methodCall = new MethodCallType(aThisVal, aMethod, aArg1);
-  return detail::ProxyInternal(aTarget, methodCall, aCallerName);
-}
-
-template<typename PromiseType, typename ThisType, typename Arg1Type, typename Arg2Type>
-static nsRefPtr<PromiseType>
-ProxyMediaCall(AbstractThread* aTarget, ThisType* aThisVal, const char* aCallerName,
-               nsRefPtr<PromiseType>(ThisType::*aMethod)(Arg1Type, Arg2Type), Arg1Type aArg1, Arg2Type aArg2)
-{
-  typedef detail::MethodCallWithTwoArgs<PromiseType, ThisType, Arg1Type, Arg2Type> MethodCallType;
-  MethodCallType* methodCall = new MethodCallType(aThisVal, aMethod, aArg1, aArg2);
-  return detail::ProxyInternal(aTarget, methodCall, aCallerName);
-}
-
-template<typename PromiseType, typename ThisType, typename Arg1Type, typename Arg2Type, typename Arg3Type>
-static nsRefPtr<PromiseType>
-ProxyMediaCall(AbstractThread* aTarget, ThisType* aThisVal, const char* aCallerName,
-               nsRefPtr<PromiseType>(ThisType::*aMethod)(Arg1Type, Arg2Type, Arg3Type), Arg1Type aArg1, Arg2Type aArg2, Arg3Type aArg3)
-{
-  typedef detail::MethodCallWithThreeArgs<PromiseType, ThisType, Arg1Type, Arg2Type, Arg3Type> MethodCallType;
-  MethodCallType* methodCall = new MethodCallType(aThisVal, aMethod, aArg1, aArg2, aArg3);
-  return detail::ProxyInternal(aTarget, methodCall, aCallerName);
-}
-
-#undef PROMISE_LOG
-
-} // namespace mozilla
-
-#endif
--- a/dom/media/MediaTaskQueue.h
+++ b/dom/media/MediaTaskQueue.h
@@ -8,26 +8,26 @@
 #define MediaTaskQueue_h_
 
 #include <queue>
 #include "mozilla/RefPtr.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/unused.h"
 #include "SharedThreadPool.h"
 #include "nsThreadUtils.h"
-#include "MediaPromise.h"
+#include "MozPromise.h"
 #include "TaskDispatcher.h"
 
 class nsIRunnable;
 
 namespace mozilla {
 
 class SharedThreadPool;
 
-typedef MediaPromise<bool, bool, false> ShutdownPromise;
+typedef MozPromise<bool, bool, false> ShutdownPromise;
 
 // Abstracts executing runnables in order in a thread pool. The runnables
 // dispatched to the MediaTaskQueue will be executed in the order in which
 // they're received, and are guaranteed to not be executed concurrently.
 // They may be executed on different threads, and a memory barrier is used
 // to make this threadsafe for objects that aren't already threadsafe.
 class MediaTaskQueue : public AbstractThread {
 public:
@@ -151,17 +151,17 @@ protected:
   TaskDispatcher* mTailDispatcher;
 
   // True if we've dispatched an event to the pool to execute events from
   // the queue.
   bool mIsRunning;
 
   // True if we've started our shutdown process.
   bool mIsShutdown;
-  MediaPromiseHolder<ShutdownPromise> mShutdownPromise;
+  MozPromiseHolder<ShutdownPromise> mShutdownPromise;
 
   // True if we're flushing; we reject new tasks if we're flushing.
   bool mIsFlushing;
 
   class Runner : public nsRunnable {
   public:
     explicit Runner(MediaTaskQueue* aQueue)
       : mQueue(aQueue)
--- a/dom/media/MediaTimer.h
+++ b/dom/media/MediaTimer.h
@@ -2,17 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #if !defined(MediaTimer_h_)
 #define MediaTimer_h_
 
-#include "MediaPromise.h"
+#include "MozPromise.h"
 
 #include <queue>
 
 #include "nsITimer.h"
 #include "nsRefPtr.h"
 
 #include "mozilla/Monitor.h"
 #include "mozilla/TimeStamp.h"
@@ -23,21 +23,21 @@ extern PRLogModuleInfo* gMediaTimerLog;
 
 #define TIMER_LOG(x, ...) \
   MOZ_ASSERT(gMediaTimerLog); \
   MOZ_LOG(gMediaTimerLog, LogLevel::Debug, ("[MediaTimer=%p relative_t=%lld]" x, this, \
                                         RelativeMicroseconds(TimeStamp::Now()), ##__VA_ARGS__))
 
 // This promise type is only exclusive because so far there isn't a reason for
 // it not to be. Feel free to change that.
-typedef MediaPromise<bool, bool, /* IsExclusive = */ true> MediaTimerPromise;
+typedef MozPromise<bool, bool, /* IsExclusive = */ true> MediaTimerPromise;
 
 // Timers only know how to fire at a given thread, which creates an impedence
 // mismatch with code that operates with MediaTaskQueues. This class solves
-// that mismatch with a dedicated (but shared) thread and a nice MediaPromise-y
+// that mismatch with a dedicated (but shared) thread and a nice MozPromise-y
 // interface.
 class MediaTimer
 {
 public:
   MediaTimer();
 
   // We use a release with a custom Destroy().
   NS_IMETHOD_(MozExternalRefCountType) AddRef(void);
new file mode 100644
--- /dev/null
+++ b/dom/media/MozPromise.h
@@ -0,0 +1,1006 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#if !defined(MozPromise_h_)
+#define MozPromise_h_
+
+#include "mozilla/Logging.h"
+
+#include "AbstractThread.h"
+
+#include "nsTArray.h"
+#include "nsThreadUtils.h"
+
+#include "mozilla/DebugOnly.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/Mutex.h"
+#include "mozilla/Monitor.h"
+#include "mozilla/unused.h"
+
+/* Polyfill __func__ on MSVC for consumers to pass to the MozPromise API. */
+#ifdef _MSC_VER
+#define __func__ __FUNCTION__
+#endif
+
+namespace mozilla {
+
+extern PRLogModuleInfo* gMozPromiseLog;
+
+#define PROMISE_LOG(x, ...) \
+  MOZ_ASSERT(gMozPromiseLog); \
+  MOZ_LOG(gMozPromiseLog, mozilla::LogLevel::Debug, (x, ##__VA_ARGS__))
+
+namespace detail {
+template<typename ThisType, typename Ret, typename ArgType>
+static TrueType TakesArgumentHelper(Ret (ThisType::*)(ArgType));
+template<typename ThisType, typename Ret, typename ArgType>
+static TrueType TakesArgumentHelper(Ret (ThisType::*)(ArgType) const);
+template<typename ThisType, typename Ret>
+static FalseType TakesArgumentHelper(Ret (ThisType::*)());
+template<typename ThisType, typename Ret>
+static FalseType TakesArgumentHelper(Ret (ThisType::*)() const);
+
+template<typename ThisType, typename Ret, typename ArgType>
+static Ret ReturnTypeHelper(Ret (ThisType::*)(ArgType));
+template<typename ThisType, typename Ret, typename ArgType>
+static Ret ReturnTypeHelper(Ret (ThisType::*)(ArgType) const);
+template<typename ThisType, typename Ret>
+static Ret ReturnTypeHelper(Ret (ThisType::*)());
+template<typename ThisType, typename Ret>
+static Ret ReturnTypeHelper(Ret (ThisType::*)() const);
+
+template<typename MethodType>
+struct ReturnType {
+  typedef decltype(detail::ReturnTypeHelper(DeclVal<MethodType>())) Type;
+};
+
+} // namespace detail
+
+template<typename MethodType>
+struct TakesArgument {
+  static const bool value = decltype(detail::TakesArgumentHelper(DeclVal<MethodType>()))::value;
+};
+
+template<typename MethodType, typename TargetType>
+struct ReturnTypeIs {
+  static const bool value = IsConvertible<typename detail::ReturnType<MethodType>::Type, TargetType>::value;
+};
+
+/*
+ * A promise manages an asynchronous request that may or may not be able to be
+ * fulfilled immediately. When an API returns a promise, the consumer may attach
+ * callbacks to be invoked (asynchronously, on a specified thread) when the
+ * request is either completed (resolved) or cannot be completed (rejected).
+ *
+ * MozPromises attempt to mirror the spirit of JS Promises to the extent that
+ * is possible (and desirable) in C++. While the intent is that MozPromises
+ * feel familiar to programmers who are accustomed to their JS-implemented cousin,
+ * we don't shy away from imposing restrictions and adding features that make
+ * sense for the use cases we encounter.
+ *
+ * A MozPromise is ThreadSafe, and may be ->Then()ed on any thread. The Then()
+ * call accepts resolve and reject callbacks, and returns a MozPromise::Request.
+ * The Request object serves several purposes for the consumer.
+ *
+ *   (1) It allows the caller to cancel the delivery of the resolve/reject value
+ *       if it has not already occurred, via Disconnect() (this must be done on
+ *       the target thread to avoid racing).
+ *
+ *   (2) It provides access to a "Completion Promise", which is roughly analagous
+ *       to the Promise returned directly by ->then() calls on JS promises. If
+ *       the resolve/reject callback returns a new MozPromise, that promise is
+ *       chained to the completion promise, such that its resolve/reject value
+ *       will be forwarded along when it arrives. If the resolve/reject callback
+ *       returns void, the completion promise is resolved/rejected with the same
+ *       value that was passed to the callback.
+ *
+ * The MozPromise APIs skirt traditional XPCOM convention by returning nsRefPtrs
+ * (rather than already_AddRefed) from various methods. This is done to allow elegant
+ * chaining of calls without cluttering up the code with intermediate variables, and
+ * without introducing separate API variants for callers that want a return value
+ * (from, say, ->Then()) from those that don't.
+ *
+ * When IsExclusive is true, the MozPromise does a release-mode assertion that
+ * there is at most one call to either Then(...) or ChainTo(...).
+ */
+
+class MozPromiseRefcountable
+{
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MozPromiseRefcountable)
+protected:
+  virtual ~MozPromiseRefcountable() {}
+};
+
+template<typename T> class MozPromiseHolder;
+template<typename ResolveValueT, typename RejectValueT, bool IsExclusive>
+class MozPromise : public MozPromiseRefcountable
+{
+public:
+  typedef ResolveValueT ResolveValueType;
+  typedef RejectValueT RejectValueType;
+  class ResolveOrRejectValue
+  {
+  public:
+    template<typename ResolveValueType_>
+    void SetResolve(ResolveValueType_&& aResolveValue)
+    {
+      MOZ_ASSERT(IsNothing());
+      mResolveValue.emplace(Forward<ResolveValueType_>(aResolveValue));
+    }
+
+    template<typename RejectValueType_>
+    void SetReject(RejectValueType_&& aRejectValue)
+    {
+      MOZ_ASSERT(IsNothing());
+      mRejectValue.emplace(Forward<RejectValueType_>(aRejectValue));
+    }
+
+    template<typename ResolveValueType_>
+    static ResolveOrRejectValue MakeResolve(ResolveValueType_&& aResolveValue)
+    {
+      ResolveOrRejectValue val;
+      val.SetResolve(Forward<ResolveValueType_>(aResolveValue));
+      return val;
+    }
+
+    template<typename RejectValueType_>
+    static ResolveOrRejectValue MakeReject(RejectValueType_&& aRejectValue)
+    {
+      ResolveOrRejectValue val;
+      val.SetReject(Forward<RejectValueType_>(aRejectValue));
+      return val;
+    }
+
+    bool IsResolve() const { return mResolveValue.isSome(); }
+    bool IsReject() const { return mRejectValue.isSome(); }
+    bool IsNothing() const { return mResolveValue.isNothing() && mRejectValue.isNothing(); }
+
+    const ResolveValueType& ResolveValue() const { return mResolveValue.ref(); }
+    const RejectValueType& RejectValue() const { return mRejectValue.ref(); }
+
+  private:
+    Maybe<ResolveValueType> mResolveValue;
+    Maybe<RejectValueType> mRejectValue;
+  };
+
+protected:
+  // MozPromise is the public type, and never constructed directly. Construct
+  // a MozPromise::Private, defined below.
+  explicit MozPromise(const char* aCreationSite)
+    : mCreationSite(aCreationSite)
+    , mMutex("MozPromise Mutex")
+    , mHaveRequest(false)
+  {
+    PROMISE_LOG("%s creating MozPromise (%p)", mCreationSite, this);
+  }
+
+public:
+  // MozPromise::Private allows us to separate the public interface (upon which
+  // consumers of the promise may invoke methods like Then()) from the private
+  // interface (upon which the creator of the promise may invoke Resolve() or
+  // Reject()). APIs should create and store a MozPromise::Private (usually
+  // via a MozPromiseHolder), and return a MozPromise to consumers.
+  //
+  // NB: We can include the definition of this class inline once B2G ICS is gone.
+  class Private;
+
+  template<typename ResolveValueType_>
+  static nsRefPtr<MozPromise>
+  CreateAndResolve(ResolveValueType_&& aResolveValue, const char* aResolveSite)
+  {
+    nsRefPtr<typename MozPromise::Private> p = new MozPromise::Private(aResolveSite);
+    p->Resolve(Forward<ResolveValueType_>(aResolveValue), aResolveSite);
+    return p.forget();
+  }
+
+  template<typename RejectValueType_>
+  static nsRefPtr<MozPromise>
+  CreateAndReject(RejectValueType_&& aRejectValue, const char* aRejectSite)
+  {
+    nsRefPtr<typename MozPromise::Private> p = new MozPromise::Private(aRejectSite);
+    p->Reject(Forward<RejectValueType_>(aRejectValue), aRejectSite);
+    return p.forget();
+  }
+
+  typedef MozPromise<nsTArray<ResolveValueType>, RejectValueType, IsExclusive> AllPromiseType;
+private:
+  class AllPromiseHolder : public MozPromiseRefcountable
+  {
+  public:
+    explicit AllPromiseHolder(size_t aDependentPromises)
+      : mPromise(new typename AllPromiseType::Private(__func__))
+      , mOutstandingPromises(aDependentPromises)
+    {
+      mResolveValues.SetLength(aDependentPromises);
+    }
+
+    void Resolve(size_t aIndex, const ResolveValueType& aResolveValue)
+    {
+      if (!mPromise) {
+        // Already rejected.
+        return;
+      }
+
+      mResolveValues[aIndex].emplace(aResolveValue);
+      if (--mOutstandingPromises == 0) {
+        nsTArray<ResolveValueType> resolveValues;
+        resolveValues.SetCapacity(mResolveValues.Length());
+        for (size_t i = 0; i < mResolveValues.Length(); ++i) {
+          resolveValues.AppendElement(mResolveValues[i].ref());
+        }
+
+        mPromise->Resolve(resolveValues, __func__);
+        mPromise = nullptr;
+        mResolveValues.Clear();
+      }
+    }
+
+    void Reject(const RejectValueType& aRejectValue)
+    {
+      mPromise->Reject(aRejectValue, __func__);
+      mPromise = nullptr;
+      mResolveValues.Clear();
+    }
+
+    AllPromiseType* Promise() { return mPromise; }
+
+  private:
+    nsTArray<Maybe<ResolveValueType>> mResolveValues;
+    nsRefPtr<typename AllPromiseType::Private> mPromise;
+    size_t mOutstandingPromises;
+  };
+public:
+
+  static nsRefPtr<AllPromiseType> All(AbstractThread* aProcessingThread, nsTArray<nsRefPtr<MozPromise>>& aPromises)
+  {
+    nsRefPtr<AllPromiseHolder> holder = new AllPromiseHolder(aPromises.Length());
+    for (size_t i = 0; i < aPromises.Length(); ++i) {
+      aPromises[i]->Then(aProcessingThread, __func__,
+        [holder, i] (ResolveValueType aResolveValue) -> void { holder->Resolve(i, aResolveValue); },
+        [holder] (RejectValueType aRejectValue) -> void { holder->Reject(aRejectValue); }
+      );
+    }
+    return holder->Promise();
+  }
+
+  class Request : public MozPromiseRefcountable
+  {
+  public:
+    virtual void Disconnect() = 0;
+
+    // MSVC complains when an inner class (ThenValueBase::{Resolve,Reject}Runnable)
+    // tries to access an inherited protected member.
+    bool IsDisconnected() const { return mDisconnected; }
+
+    virtual MozPromise* CompletionPromise() = 0;
+
+  protected:
+    Request() : mComplete(false), mDisconnected(false) {}
+    virtual ~Request() {}
+
+    bool mComplete;
+    bool mDisconnected;
+  };
+
+protected:
+
+  /*
+   * A ThenValue tracks a single consumer waiting on the promise. When a consumer
+   * invokes promise->Then(...), a ThenValue is created. Once the Promise is
+   * resolved or rejected, a {Resolve,Reject}Runnable is dispatched, which
+   * invokes the resolve/reject method and then deletes the ThenValue.
+   */
+  class ThenValueBase : public Request
+  {
+  public:
+    class ResolveOrRejectRunnable : public nsRunnable
+    {
+    public:
+      ResolveOrRejectRunnable(ThenValueBase* aThenValue, MozPromise* aPromise)
+        : mThenValue(aThenValue)
+        , mPromise(aPromise)
+      {
+        MOZ_DIAGNOSTIC_ASSERT(!mPromise->IsPending());
+      }
+
+      ~ResolveOrRejectRunnable()
+      {
+        MOZ_DIAGNOSTIC_ASSERT(!mThenValue || mThenValue->IsDisconnected());
+      }
+
+      NS_IMETHODIMP Run()
+      {
+        PROMISE_LOG("ResolveOrRejectRunnable::Run() [this=%p]", this);
+        mThenValue->DoResolveOrReject(mPromise->Value());
+        mThenValue = nullptr;
+        mPromise = nullptr;
+        return NS_OK;
+      }
+
+    private:
+      nsRefPtr<ThenValueBase> mThenValue;
+      nsRefPtr<MozPromise> mPromise;
+    };
+
+    explicit ThenValueBase(AbstractThread* aResponseTarget, const char* aCallSite)
+      : mResponseTarget(aResponseTarget), mCallSite(aCallSite) {}
+
+    MozPromise* CompletionPromise() override
+    {
+      MOZ_DIAGNOSTIC_ASSERT(mResponseTarget->IsCurrentThreadIn());
+      MOZ_DIAGNOSTIC_ASSERT(!Request::mComplete);
+      if (!mCompletionPromise) {
+        mCompletionPromise = new MozPromise::Private("<completion promise>");
+      }
+      return mCompletionPromise;
+    }
+
+    void Dispatch(MozPromise *aPromise)
+    {
+      aPromise->mMutex.AssertCurrentThreadOwns();
+      MOZ_ASSERT(!aPromise->IsPending());
+
+      nsRefPtr<nsRunnable> runnable =
+        static_cast<nsRunnable*>(new (typename ThenValueBase::ResolveOrRejectRunnable)(this, aPromise));
+      PROMISE_LOG("%s Then() call made from %s [Runnable=%p, Promise=%p, ThenValue=%p]",
+                  aPromise->mValue.IsResolve() ? "Resolving" : "Rejecting", ThenValueBase::mCallSite,
+                  runnable.get(), aPromise, this);
+
+      // Promise consumers are allowed to disconnect the Request object and
+      // then shut down the thread or task queue that the promise result would
+      // be dispatched on. So we unfortunately can't assert that promise
+      // dispatch succeeds. :-(
+      mResponseTarget->Dispatch(runnable.forget(), AbstractThread::DontAssertDispatchSuccess);
+    }
+
+    virtual void Disconnect() override
+    {
+      MOZ_ASSERT(ThenValueBase::mResponseTarget->IsCurrentThreadIn());
+      MOZ_DIAGNOSTIC_ASSERT(!Request::mComplete);
+      Request::mDisconnected = true;
+
+      // We could support rejecting the completion promise on disconnection, but
+      // then we'd need to have some sort of default reject value. The use cases
+      // of disconnection and completion promise chaining seem pretty orthogonal,
+      // so let's use assert against it.
+      MOZ_DIAGNOSTIC_ASSERT(!mCompletionPromise);
+    }
+
+  protected:
+    virtual already_AddRefed<MozPromise> DoResolveOrRejectInternal(const ResolveOrRejectValue& aValue) = 0;
+
+    void DoResolveOrReject(const ResolveOrRejectValue& aValue)
+    {
+      Request::mComplete = true;
+      if (Request::mDisconnected) {
+        PROMISE_LOG("ThenValue::DoResolveOrReject disconnected - bailing out [this=%p]", this);
+        return;
+      }
+
+      // Invoke the resolve or reject method.
+      nsRefPtr<MozPromise> p = DoResolveOrRejectInternal(aValue);
+
+      // If there's a completion promise, resolve it appropriately with the
+      // result of the method.
+      //
+      // We jump through some hoops to cast to MozPromise::Private here. This
+      // can go away when we can just declare mCompletionPromise as
+      // MozPromise::Private. See the declaration below.
+      nsRefPtr<MozPromise::Private> completionPromise =
+        dont_AddRef(static_cast<MozPromise::Private*>(mCompletionPromise.forget().take()));
+      if (completionPromise) {
+        if (p) {
+          p->ChainTo(completionPromise.forget(), "<chained completion promise>");
+        } else {
+          completionPromise->ResolveOrReject(aValue, "<completion of non-promise-returning method>");
+        }
+      }
+    }
+
+    nsRefPtr<AbstractThread> mResponseTarget; // May be released on any thread.
+
+    // Declaring nsRefPtr<MozPromise::Private> here causes build failures
+    // on MSVC because MozPromise::Private is only forward-declared at this
+    // point. This hack can go away when we inline-declare MozPromise::Private,
+    // which is blocked on the B2G ICS compiler being too old.
+    nsRefPtr<MozPromise> mCompletionPromise;
+
+    const char* mCallSite;
+  };
+
+  /*
+   * We create two overloads for invoking Resolve/Reject Methods so as to
+   * make the resolve/reject value argument "optional".
+   */
+
+  template<typename ThisType, typename MethodType, typename ValueType>
+  static typename EnableIf<ReturnTypeIs<MethodType, nsRefPtr<MozPromise>>::value &&
+                           TakesArgument<MethodType>::value,
+                           already_AddRefed<MozPromise>>::Type
+  InvokeCallbackMethod(ThisType* aThisVal, MethodType aMethod, ValueType&& aValue)
+  {
+    return ((*aThisVal).*aMethod)(Forward<ValueType>(aValue)).forget();
+  }
+
+  template<typename ThisType, typename MethodType, typename ValueType>
+  static typename EnableIf<ReturnTypeIs<MethodType, void>::value &&
+                           TakesArgument<MethodType>::value,
+                           already_AddRefed<MozPromise>>::Type
+  InvokeCallbackMethod(ThisType* aThisVal, MethodType aMethod, ValueType&& aValue)
+  {
+    ((*aThisVal).*aMethod)(Forward<ValueType>(aValue));
+    return nullptr;
+  }
+
+  template<typename ThisType, typename MethodType, typename ValueType>
+  static typename EnableIf<ReturnTypeIs<MethodType, nsRefPtr<MozPromise>>::value &&
+                           !TakesArgument<MethodType>::value,
+                           already_AddRefed<MozPromise>>::Type
+  InvokeCallbackMethod(ThisType* aThisVal, MethodType aMethod, ValueType&& aValue)
+  {
+    return ((*aThisVal).*aMethod)().forget();
+  }
+
+  template<typename ThisType, typename MethodType, typename ValueType>
+  static typename EnableIf<ReturnTypeIs<MethodType, void>::value &&
+                           !TakesArgument<MethodType>::value,
+                           already_AddRefed<MozPromise>>::Type
+  InvokeCallbackMethod(ThisType* aThisVal, MethodType aMethod, ValueType&& aValue)
+  {
+    ((*aThisVal).*aMethod)();
+    return nullptr;
+  }
+
+  template<typename ThisType, typename ResolveMethodType, typename RejectMethodType>
+  class MethodThenValue : public ThenValueBase
+  {
+  public:
+    MethodThenValue(AbstractThread* aResponseTarget, ThisType* aThisVal,
+                    ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod,
+                    const char* aCallSite)
+      : ThenValueBase(aResponseTarget, aCallSite)
+      , mThisVal(aThisVal)
+      , mResolveMethod(aResolveMethod)
+      , mRejectMethod(aRejectMethod) {}
+
+  virtual void Disconnect() override
+  {
+    ThenValueBase::Disconnect();
+
+    // If a Request has been disconnected, we don't guarantee that the
+    // resolve/reject runnable will be dispatched. Null out our refcounted
+    // this-value now so that it's released predictably on the dispatch thread.
+    mThisVal = nullptr;
+  }
+
+  protected:
+    virtual already_AddRefed<MozPromise> DoResolveOrRejectInternal(const ResolveOrRejectValue& aValue) override
+    {
+      nsRefPtr<MozPromise> completion;
+      if (aValue.IsResolve()) {
+        completion = InvokeCallbackMethod(mThisVal.get(), mResolveMethod, aValue.ResolveValue());
+      } else {
+        completion = InvokeCallbackMethod(mThisVal.get(), mRejectMethod, aValue.RejectValue());
+      }
+
+      // Null out mThisVal after invoking the callback so that any references are
+      // released predictably on the dispatch thread. Otherwise, it would be
+      // released on whatever thread last drops its reference to the ThenValue,
+      // which may or may not be ok.
+      mThisVal = nullptr;
+
+      return completion.forget();
+    }
+
+  private:
+    nsRefPtr<ThisType> mThisVal; // Only accessed and refcounted on dispatch thread.
+    ResolveMethodType mResolveMethod;
+    RejectMethodType mRejectMethod;
+  };
+
+  // NB: We could use std::function here instead of a template if it were supported. :-(
+  template<typename ResolveFunction, typename RejectFunction>
+  class FunctionThenValue : public ThenValueBase
+  {
+  public:
+    FunctionThenValue(AbstractThread* aResponseTarget,
+                      ResolveFunction&& aResolveFunction,
+                      RejectFunction&& aRejectFunction,
+                      const char* aCallSite)
+      : ThenValueBase(aResponseTarget, aCallSite)
+    {
+      mResolveFunction.emplace(Move(aResolveFunction));
+      mRejectFunction.emplace(Move(aRejectFunction));
+    }
+
+  virtual void Disconnect() override
+  {
+    ThenValueBase::Disconnect();
+
+    // If a Request has been disconnected, we don't guarantee that the
+    // resolve/reject runnable will be dispatched. Destroy our callbacks
+    // now so that any references in closures are released predictable on
+    // the dispatch thread.
+    mResolveFunction.reset();
+    mRejectFunction.reset();
+  }
+
+  protected:
+    virtual already_AddRefed<MozPromise> DoResolveOrRejectInternal(const ResolveOrRejectValue& aValue) override
+    {
+      // Note: The usage of InvokeCallbackMethod here requires that
+      // ResolveFunction/RejectFunction are capture-lambdas (i.e. anonymous
+      // classes with ::operator()), since it allows us to share code more easily.
+      // We could fix this if need be, though it's quite easy to work around by
+      // just capturing something.
+      nsRefPtr<MozPromise> completion;
+      if (aValue.IsResolve()) {
+        completion = InvokeCallbackMethod(mResolveFunction.ptr(), &ResolveFunction::operator(), aValue.ResolveValue());
+      } else {
+        completion = InvokeCallbackMethod(mRejectFunction.ptr(), &RejectFunction::operator(), aValue.RejectValue());
+      }
+
+      // Destroy callbacks after invocation so that any references in closures are
+      // released predictably on the dispatch thread. Otherwise, they would be
+      // released on whatever thread last drops its reference to the ThenValue,
+      // which may or may not be ok.
+      mResolveFunction.reset();
+      mRejectFunction.reset();
+
+      return completion.forget();
+    }
+
+  private:
+    Maybe<ResolveFunction> mResolveFunction; // Only accessed and deleted on dispatch thread.
+    Maybe<RejectFunction> mRejectFunction; // Only accessed and deleted on dispatch thread.
+  };
+
+public:
+  void ThenInternal(AbstractThread* aResponseThread, ThenValueBase* aThenValue,
+                    const char* aCallSite)
+  {
+    MutexAutoLock lock(mMutex);
+    MOZ_ASSERT(aResponseThread->IsDispatchReliable());
+    MOZ_DIAGNOSTIC_ASSERT(!IsExclusive || !mHaveRequest);
+    mHaveRequest = true;
+    PROMISE_LOG("%s invoking Then() [this=%p, aThenValue=%p, isPending=%d]",
+                aCallSite, this, aThenValue, (int) IsPending());
+    if (!IsPending()) {
+      aThenValue->Dispatch(this);
+    } else {
+      mThenValues.AppendElement(aThenValue);
+    }
+  }
+
+public:
+
+  template<typename ThisType, typename ResolveMethodType, typename RejectMethodType>
+  nsRefPtr<Request> Then(AbstractThread* aResponseThread, const char* aCallSite, ThisType* aThisVal,
+                         ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod)
+  {
+    nsRefPtr<ThenValueBase> thenValue = new MethodThenValue<ThisType, ResolveMethodType, RejectMethodType>(
+                                              aResponseThread, aThisVal, aResolveMethod, aRejectMethod, aCallSite);
+    ThenInternal(aResponseThread, thenValue, aCallSite);
+    return thenValue.forget(); // Implicit conversion from already_AddRefed<ThenValueBase> to nsRefPtr<Request>.
+  }
+
+  template<typename ResolveFunction, typename RejectFunction>
+  nsRefPtr<Request> Then(AbstractThread* aResponseThread, const char* aCallSite,
+                         ResolveFunction&& aResolveFunction, RejectFunction&& aRejectFunction)
+  {
+    nsRefPtr<ThenValueBase> thenValue = new FunctionThenValue<ResolveFunction, RejectFunction>(aResponseThread,
+                                              Move(aResolveFunction), Move(aRejectFunction), aCallSite);
+    ThenInternal(aResponseThread, thenValue, aCallSite);
+    return thenValue.forget(); // Implicit conversion from already_AddRefed<ThenValueBase> to nsRefPtr<Request>.
+  }
+
+  void ChainTo(already_AddRefed<Private> aChainedPromise, const char* aCallSite)
+  {
+    MutexAutoLock lock(mMutex);
+    MOZ_DIAGNOSTIC_ASSERT(!IsExclusive || !mHaveRequest);
+    mHaveRequest = true;
+    nsRefPtr<Private> chainedPromise = aChainedPromise;
+    PROMISE_LOG("%s invoking Chain() [this=%p, chainedPromise=%p, isPending=%d]",
+                aCallSite, this, chainedPromise.get(), (int) IsPending());
+    if (!IsPending()) {
+      ForwardTo(chainedPromise);
+    } else {
+      mChainedPromises.AppendElement(chainedPromise);
+    }
+  }
+
+protected:
+  bool IsPending() const { return mValue.IsNothing(); }
+  const ResolveOrRejectValue& Value() const
+  {
+    // This method should only be called once the value has stabilized. As
+    // such, we don't need to acquire the lock here.
+    MOZ_DIAGNOSTIC_ASSERT(!IsPending());
+    return mValue;
+  }
+
+  void DispatchAll()
+  {
+    mMutex.AssertCurrentThreadOwns();
+    for (size_t i = 0; i < mThenValues.Length(); ++i) {
+      mThenValues[i]->Dispatch(this);
+    }
+    mThenValues.Clear();
+
+    for (size_t i = 0; i < mChainedPromises.Length(); ++i) {
+      ForwardTo(mChainedPromises[i]);
+    }
+    mChainedPromises.Clear();
+  }
+
+  void ForwardTo(Private* aOther)
+  {
+    MOZ_ASSERT(!IsPending());
+    if (mValue.IsResolve()) {
+      aOther->Resolve(mValue.ResolveValue(), "<chained promise>");
+    } else {
+      aOther->Reject(mValue.RejectValue(), "<chained promise>");
+    }
+  }
+
+  virtual ~MozPromise()
+  {
+    PROMISE_LOG("MozPromise::~MozPromise [this=%p]", this);
+    MOZ_ASSERT(!IsPending());
+    MOZ_ASSERT(mThenValues.IsEmpty());
+    MOZ_ASSERT(mChainedPromises.IsEmpty());
+  };
+
+  const char* mCreationSite; // For logging
+  Mutex mMutex;
+  ResolveOrRejectValue mValue;
+  nsTArray<nsRefPtr<ThenValueBase>> mThenValues;
+  nsTArray<nsRefPtr<Private>> mChainedPromises;
+  bool mHaveRequest;
+};
+
+template<typename ResolveValueT, typename RejectValueT, bool IsExclusive>
+class MozPromise<ResolveValueT, RejectValueT, IsExclusive>::Private
+  : public MozPromise<ResolveValueT, RejectValueT, IsExclusive>
+{
+public:
+  explicit Private(const char* aCreationSite) : MozPromise(aCreationSite) {}
+
+  template<typename ResolveValueT_>
+  void Resolve(ResolveValueT_&& aResolveValue, const char* aResolveSite)
+  {
+    MutexAutoLock lock(mMutex);
+    MOZ_ASSERT(IsPending());
+    PROMISE_LOG("%s resolving MozPromise (%p created at %s)", aResolveSite, this, mCreationSite);
+    mValue.SetResolve(Forward<ResolveValueT_>(aResolveValue));
+    DispatchAll();
+  }
+
+  template<typename RejectValueT_>
+  void Reject(RejectValueT_&& aRejectValue, const char* aRejectSite)
+  {
+    MutexAutoLock lock(mMutex);
+    MOZ_ASSERT(IsPending());
+    PROMISE_LOG("%s rejecting MozPromise (%p created at %s)", aRejectSite, this, mCreationSite);
+    mValue.SetReject(Forward<RejectValueT_>(aRejectValue));
+    DispatchAll();
+  }
+
+  template<typename ResolveOrRejectValue_>
+  void ResolveOrReject(ResolveOrRejectValue_&& aValue, const char* aSite)
+  {
+    MutexAutoLock lock(mMutex);
+    MOZ_ASSERT(IsPending());
+    PROMISE_LOG("%s resolveOrRejecting MozPromise (%p created at %s)", aSite, this, mCreationSite);
+    mValue = Forward<ResolveOrRejectValue_>(aValue);
+    DispatchAll();
+  }
+};
+
+// A generic promise type that does the trick for simple use cases.
+typedef MozPromise<bool, nsresult, /* IsExclusive = */ false> GenericPromise;
+
+/*
+ * Class to encapsulate a promise for a particular role. Use this as the member
+ * variable for a class whose method returns a promise.
+ */
+template<typename PromiseType>
+class MozPromiseHolder
+{
+public:
+  MozPromiseHolder()
+    : mMonitor(nullptr) {}
+
+  // Move semantics.
+  MozPromiseHolder& operator=(MozPromiseHolder&& aOther)
+  {
+    MOZ_ASSERT(!mMonitor && !aOther.mMonitor);
+    MOZ_DIAGNOSTIC_ASSERT(!mPromise);
+    mPromise = aOther.mPromise;
+    aOther.mPromise = nullptr;
+    return *this;
+  }
+
+  ~MozPromiseHolder() { MOZ_ASSERT(!mPromise); }
+
+  already_AddRefed<PromiseType> Ensure(const char* aMethodName) {
+    if (mMonitor) {
+      mMonitor->AssertCurrentThreadOwns();
+    }
+    if (!mPromise) {
+      mPromise = new (typename PromiseType::Private)(aMethodName);
+    }
+    nsRefPtr<PromiseType> p = mPromise.get();
+    return p.forget();
+  }
+
+  // Provide a Monitor that should always be held when accessing this instance.
+  void SetMonitor(Monitor* aMonitor) { mMonitor = aMonitor; }
+
+  bool IsEmpty()
+  {
+    if (mMonitor) {
+      mMonitor->AssertCurrentThreadOwns();
+    }
+    return !mPromise;
+  }
+
+  already_AddRefed<typename PromiseType::Private> Steal()
+  {
+    if (mMonitor) {
+      mMonitor->AssertCurrentThreadOwns();
+    }
+
+    nsRefPtr<typename PromiseType::Private> p = mPromise;
+    mPromise = nullptr;
+    return p.forget();
+  }
+
+  void Resolve(typename PromiseType::ResolveValueType aResolveValue,
+               const char* aMethodName)
+  {
+    if (mMonitor) {
+      mMonitor->AssertCurrentThreadOwns();
+    }
+    MOZ_ASSERT(mPromise);
+    mPromise->Resolve(aResolveValue, aMethodName);
+    mPromise = nullptr;
+  }
+
+
+  void ResolveIfExists(typename PromiseType::ResolveValueType aResolveValue,
+                       const char* aMethodName)
+  {
+    if (!IsEmpty()) {
+      Resolve(aResolveValue, aMethodName);
+    }
+  }
+
+  void Reject(typename PromiseType::RejectValueType aRejectValue,
+              const char* aMethodName)
+  {
+    if (mMonitor) {
+      mMonitor->AssertCurrentThreadOwns();
+    }
+    MOZ_ASSERT(mPromise);
+    mPromise->Reject(aRejectValue, aMethodName);
+    mPromise = nullptr;
+  }
+
+
+  void RejectIfExists(typename PromiseType::RejectValueType aRejectValue,
+                      const char* aMethodName)
+  {
+    if (!IsEmpty()) {
+      Reject(aRejectValue, aMethodName);
+    }
+  }
+
+private:
+  Monitor* mMonitor;
+  nsRefPtr<typename PromiseType::Private> mPromise;
+};
+
+/*
+ * Class to encapsulate a MozPromise::Request reference. Use this as the member
+ * variable for a class waiting on a MozPromise.
+ */
+template<typename PromiseType>
+class MozPromiseRequestHolder
+{
+public:
+  MozPromiseRequestHolder() {}
+  ~MozPromiseRequestHolder() { MOZ_ASSERT(!mRequest); }
+
+  void Begin(typename PromiseType::Request* aRequest)
+  {
+    MOZ_DIAGNOSTIC_ASSERT(!Exists());
+    mRequest = aRequest;
+  }
+
+  void Complete()
+  {
+    MOZ_DIAGNOSTIC_ASSERT(Exists());
+    mRequest = nullptr;
+  }
+
+  // Disconnects and forgets an outstanding promise. The resolve/reject methods
+  // will never be called.
+  void Disconnect() {
+    MOZ_ASSERT(Exists());
+    mRequest->Disconnect();
+    mRequest = nullptr;
+  }
+
+  void DisconnectIfExists() {
+    if (Exists()) {
+      Disconnect();
+    }
+  }
+
+  bool Exists() { return !!mRequest; }
+
+private:
+  nsRefPtr<typename PromiseType::Request> mRequest;
+};
+
+// Proxy Media Calls.
+//
+// This machinery allows callers to schedule a promise-returning method to be
+// invoked asynchronously on a given thread, while at the same time receiving
+// a promise upon which to invoke Then() immediately. ProxyMediaCall dispatches
+// a task to invoke the method on the proper thread and also chain the resulting
+// promise to the one that the caller received, so that resolve/reject values
+// are forwarded through.
+
+namespace detail {
+
+template<typename PromiseType>
+class MethodCallBase
+{
+public:
+  MethodCallBase() { MOZ_COUNT_CTOR(MethodCallBase); }
+  virtual nsRefPtr<PromiseType> Invoke() = 0;
+  virtual ~MethodCallBase() { MOZ_COUNT_DTOR(MethodCallBase); };
+};
+
+template<typename PromiseType, typename ThisType>
+class MethodCallWithNoArgs : public MethodCallBase<PromiseType>
+{
+public:
+  typedef nsRefPtr<PromiseType>(ThisType::*Type)();
+  MethodCallWithNoArgs(ThisType* aThisVal, Type aMethod)
+    : mThisVal(aThisVal), mMethod(aMethod) {}
+  nsRefPtr<PromiseType> Invoke() override { return ((*mThisVal).*mMethod)(); }
+protected:
+  nsRefPtr<ThisType> mThisVal;
+  Type mMethod;
+};
+
+template<typename PromiseType, typename ThisType, typename Arg1Type>
+class MethodCallWithOneArg : public MethodCallBase<PromiseType>
+{
+public:
+  typedef nsRefPtr<PromiseType>(ThisType::*Type)(Arg1Type);
+  MethodCallWithOneArg(ThisType* aThisVal, Type aMethod, Arg1Type aArg1)
+    : mThisVal(aThisVal), mMethod(aMethod), mArg1(aArg1) {}
+  nsRefPtr<PromiseType> Invoke() override { return ((*mThisVal).*mMethod)(mArg1); }
+protected:
+  nsRefPtr<ThisType> mThisVal;
+  Type mMethod;
+  Arg1Type mArg1;
+};
+
+template<typename PromiseType, typename ThisType, typename Arg1Type, typename Arg2Type>
+class MethodCallWithTwoArgs : public MethodCallBase<PromiseType>
+{
+public:
+  typedef nsRefPtr<PromiseType>(ThisType::*Type)(Arg1Type, Arg2Type);
+  MethodCallWithTwoArgs(ThisType* aThisVal, Type aMethod, Arg1Type aArg1, Arg2Type aArg2)
+    : mThisVal(aThisVal), mMethod(aMethod), mArg1(aArg1), mArg2(aArg2) {}
+  nsRefPtr<PromiseType> Invoke() override { return ((*mThisVal).*mMethod)(mArg1, mArg2); }
+protected:
+  nsRefPtr<ThisType> mThisVal;
+  Type mMethod;
+  Arg1Type mArg1;
+  Arg2Type mArg2;
+};
+
+template<typename PromiseType, typename ThisType, typename Arg1Type, typename Arg2Type, typename Arg3Type>
+class MethodCallWithThreeArgs : public MethodCallBase<PromiseType>
+{
+public:
+  typedef nsRefPtr<PromiseType>(ThisType::*Type)(Arg1Type, Arg2Type, Arg3Type);
+  MethodCallWithThreeArgs(ThisType* aThisVal, Type aMethod, Arg1Type aArg1, Arg2Type aArg2, Arg3Type aArg3)
+    : mThisVal(aThisVal), mMethod(aMethod), mArg1(aArg1), mArg2(aArg2), mArg3(aArg3) {}
+  nsRefPtr<PromiseType> Invoke() override { return ((*mThisVal).*mMethod)(mArg1, mArg2, mArg3); }
+protected:
+  nsRefPtr<ThisType> mThisVal;
+  Type mMethod;
+  Arg1Type mArg1;
+  Arg2Type mArg2;
+  Arg3Type mArg3;
+};
+
+template<typename PromiseType>
+class ProxyRunnable : public nsRunnable
+{
+public:
+  ProxyRunnable(typename PromiseType::Private* aProxyPromise, MethodCallBase<PromiseType>* aMethodCall)
+    : mProxyPromise(aProxyPromise), mMethodCall(aMethodCall) {}
+
+  NS_IMETHODIMP Run()
+  {
+    nsRefPtr<PromiseType> p = mMethodCall->Invoke();
+    mMethodCall = nullptr;
+    p->ChainTo(mProxyPromise.forget(), "<Proxy Promise>");
+    return NS_OK;
+  }
+
+private:
+  nsRefPtr<typename PromiseType::Private> mProxyPromise;
+  nsAutoPtr<MethodCallBase<PromiseType>> mMethodCall;
+};
+
+template<typename PromiseType>
+static nsRefPtr<PromiseType>
+ProxyInternal(AbstractThread* aTarget, MethodCallBase<PromiseType>* aMethodCall, const char* aCallerName)
+{
+  nsRefPtr<typename PromiseType::Private> p = new (typename PromiseType::Private)(aCallerName);
+  nsRefPtr<ProxyRunnable<PromiseType>> r = new ProxyRunnable<PromiseType>(p, aMethodCall);
+  MOZ_ASSERT(aTarget->IsDispatchReliable());
+  aTarget->Dispatch(r.forget());
+  return p.forget();
+}
+
+} // namespace detail
+
+template<typename PromiseType, typename ThisType>
+static nsRefPtr<PromiseType>
+ProxyMediaCall(AbstractThread* aTarget, ThisType* aThisVal, const char* aCallerName,
+               nsRefPtr<PromiseType>(ThisType::*aMethod)())
+{
+  typedef detail::MethodCallWithNoArgs<PromiseType, ThisType> MethodCallType;
+  MethodCallType* methodCall = new MethodCallType(aThisVal, aMethod);
+  return detail::ProxyInternal(aTarget, methodCall, aCallerName);
+}
+
+template<typename PromiseType, typename ThisType, typename Arg1Type>
+static nsRefPtr<PromiseType>
+ProxyMediaCall(AbstractThread* aTarget, ThisType* aThisVal, const char* aCallerName,
+               nsRefPtr<PromiseType>(ThisType::*aMethod)(Arg1Type), Arg1Type aArg1)
+{
+  typedef detail::MethodCallWithOneArg<PromiseType, ThisType, Arg1Type> MethodCallType;
+  MethodCallType* methodCall = new MethodCallType(aThisVal, aMethod, aArg1);
+  return detail::ProxyInternal(aTarget, methodCall, aCallerName);
+}
+
+template<typename PromiseType, typename ThisType, typename Arg1Type, typename Arg2Type>
+static nsRefPtr<PromiseType>
+ProxyMediaCall(AbstractThread* aTarget, ThisType* aThisVal, const char* aCallerName,
+               nsRefPtr<PromiseType>(ThisType::*aMethod)(Arg1Type, Arg2Type), Arg1Type aArg1, Arg2Type aArg2)
+{
+  typedef detail::MethodCallWithTwoArgs<PromiseType, ThisType, Arg1Type, Arg2Type> MethodCallType;
+  MethodCallType* methodCall = new MethodCallType(aThisVal, aMethod, aArg1, aArg2);
+  return detail::ProxyInternal(aTarget, methodCall, aCallerName);
+}
+
+template<typename PromiseType, typename ThisType, typename Arg1Type, typename Arg2Type, typename Arg3Type>
+static nsRefPtr<PromiseType>
+ProxyMediaCall(AbstractThread* aTarget, ThisType* aThisVal, const char* aCallerName,
+               nsRefPtr<PromiseType>(ThisType::*aMethod)(Arg1Type, Arg2Type, Arg3Type), Arg1Type aArg1, Arg2Type aArg2, Arg3Type aArg3)
+{
+  typedef detail::MethodCallWithThreeArgs<PromiseType, ThisType, Arg1Type, Arg2Type, Arg3Type> MethodCallType;
+  MethodCallType* methodCall = new MethodCallType(aThisVal, aMethod, aArg1, aArg2, aArg3);
+  return detail::ProxyInternal(aTarget, methodCall, aCallerName);
+}
+
+#undef PROMISE_LOG
+
+} // namespace mozilla
+
+#endif
--- a/dom/media/StateMirroring.h
+++ b/dom/media/StateMirroring.h
@@ -2,17 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #if !defined(StateMirroring_h_)
 #define StateMirroring_h_
 
-#include "MediaPromise.h"
+#include "MozPromise.h"
 
 #include "StateWatching.h"
 #include "TaskDispatcher.h"
 
 #include "mozilla/Maybe.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/unused.h"
 
--- a/dom/media/VideoUtils.h
+++ b/dom/media/VideoUtils.h
@@ -8,17 +8,17 @@
 #define VideoUtils_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "mozilla/CheckedInt.h"
 #include "nsIThread.h"
 #include "nsSize.h"
 #include "nsRect.h"
-#include "MediaPromise.h"
+#include "MozPromise.h"
 
 #if !(defined(XP_WIN) || defined(XP_MACOSX) || defined(LINUX)) || \
     defined(MOZ_ASAN)
 // For MEDIA_THREAD_STACK_SIZE
 #include "nsIThreadManager.h"
 #endif
 #include "nsThreadUtils.h"
 #include "prtime.h"
@@ -210,17 +210,17 @@ class SharedThreadPool;
 
 // The MediaDataDecoder API blocks, with implementations waiting on platform
 // decoder tasks.  These platform decoder tasks are queued on a separate
 // thread pool to ensure they can run when the MediaDataDecoder clients'
 // thread pool is blocked.  Tasks on the PLATFORM_DECODER thread pool must not
 // wait on tasks in the PLAYBACK thread pool.
 //
 // No new dependencies on this mechanism should be added, as methods are being
-// made async supported by MediaPromise, making this unnecessary and
+// made async supported by MozPromise, making this unnecessary and
 // permitting unifying the pool.
 enum class MediaThreadType {
   PLAYBACK, // MediaDecoderStateMachine and MediaDecoderReader
   PLATFORM_DECODER
 };
 // Returns the thread pool that is shared amongst all decoder state machines
 // for decoding streams.
 already_AddRefed<SharedThreadPool> GetMediaThreadPool(MediaThreadType aType);
--- a/dom/media/android/AndroidMediaReader.h
+++ b/dom/media/android/AndroidMediaReader.h
@@ -31,18 +31,18 @@ class AndroidMediaReader : public MediaD
   MPAPI::Decoder *mPlugin;
   bool mHasAudio;
   bool mHasVideo;
   nsIntRect mPicture;
   nsIntSize mInitialFrame;
   int64_t mVideoSeekTimeUs;
   int64_t mAudioSeekTimeUs;
   nsRefPtr<VideoData> mLastVideoFrame;
-  MediaPromiseHolder<MediaDecoderReader::SeekPromise> mSeekPromise;
-  MediaPromiseRequestHolder<MediaDecoderReader::VideoDataPromise> mSeekRequest;
+  MozPromiseHolder<MediaDecoderReader::SeekPromise> mSeekPromise;
+  MozPromiseRequestHolder<MediaDecoderReader::VideoDataPromise> mSeekRequest;
 public:
   AndroidMediaReader(AbstractMediaDecoder* aDecoder,
                      const nsACString& aContentType);
 
   virtual nsresult Init(MediaDecoderReader* aCloneDonor);
   virtual nsresult ResetDecode();
 
   virtual bool DecodeAudioData();
--- a/dom/media/eme/CDMProxy.h
+++ b/dom/media/eme/CDMProxy.h
@@ -9,17 +9,17 @@
 
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "mozilla/dom/MediaKeys.h"
 #include "mozilla/Monitor.h"
 #include "nsIThread.h"
 #include "GMPDecryptorProxy.h"
 #include "mozilla/CDMCaps.h"
-#include "MediaPromise.h"
+#include "MozPromise.h"
 
 namespace mozilla {
 class MediaRawData;
 class CDMCallbackProxy;
 
 namespace dom {
 class MediaKeySession;
 } // namespace dom
@@ -39,17 +39,17 @@ struct DecryptResult {
 // resolve the promise using its PromiseId.
 class CDMProxy {
   typedef dom::PromiseId PromiseId;
   typedef dom::SessionType SessionType;
 public:
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CDMProxy)
 
-  typedef MediaPromise<DecryptResult, DecryptResult, /* IsExclusive = */ true> DecryptPromise;
+  typedef MozPromise<DecryptResult, DecryptResult, /* IsExclusive = */ true> DecryptPromise;
 
   // Main thread only.
   CDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem);
 
   // Main thread only.
   // Loads the CDM corresponding to mKeySystem.
   // Calls MediaKeys::OnCDMCreated() when the CDM is created.
   void Init(PromiseId aPromiseId,
@@ -254,17 +254,17 @@ private:
     nsRefPtr<DecryptPromise> Ensure() {
       return mPromise.Ensure(__func__);
     }
 
     uint32_t mId;
     nsRefPtr<MediaRawData> mSample;
   private:
     ~DecryptJob() {}
-    MediaPromiseHolder<DecryptPromise> mPromise;
+    MozPromiseHolder<DecryptPromise> mPromise;
   };
   // GMP thread only.
   void gmp_Decrypt(nsRefPtr<DecryptJob> aJob);
 
   class RejectPromiseTask : public nsRunnable {
   public:
     RejectPromiseTask(CDMProxy* aProxy,
                       PromiseId aId,
--- a/dom/media/fmp4/MP4Reader.h
+++ b/dom/media/fmp4/MP4Reader.h
@@ -219,17 +219,17 @@ private:
   template<typename PromiseType>
   struct DecoderDataWithPromise : public DecoderData {
     DecoderDataWithPromise(MediaData::Type aType, uint32_t aDecodeAhead) :
       DecoderData(aType, aDecodeAhead)
     {
       mPromise.SetMonitor(&mMonitor);
     }
 
-    MediaPromiseHolder<PromiseType> mPromise;
+    MozPromiseHolder<PromiseType> mPromise;
 
     bool HasPromise() override { return !mPromise.IsEmpty(); }
     void RejectPromise(MediaDecoderReader::NotDecodedReason aReason,
                        const char* aMethodName) override
     {
       mPromise.Reject(aReason, aMethodName);
     }
   };
deleted file mode 100644
--- a/dom/media/gtest/TestMediaPromise.cpp
+++ /dev/null
@@ -1,219 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "gtest/gtest.h"
-#include "nsISupportsImpl.h"
-#include "MediaTaskQueue.h"
-#include "MediaPromise.h"
-#include "SharedThreadPool.h"
-#include "VideoUtils.h"
-
-using namespace mozilla;
-
-typedef MediaPromise<int, double, false> TestPromise;
-typedef TestPromise::ResolveOrRejectValue RRValue;
-
-class MOZ_STACK_CLASS AutoTaskQueue
-{
-public:
-  AutoTaskQueue()
-    : mTaskQueue(new MediaTaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK)))
-  {}
-
-  ~AutoTaskQueue()
-  {
-    mTaskQueue->AwaitShutdownAndIdle();
-  }
-
-  MediaTaskQueue* TaskQueue() { return mTaskQueue; }
-private:
-  nsRefPtr<MediaTaskQueue> mTaskQueue;
-};
-
-class DelayedResolveOrReject : public nsRunnable
-{
-public:
-  DelayedResolveOrReject(MediaTaskQueue* aTaskQueue,
-                         TestPromise::Private* aPromise,
-                         TestPromise::ResolveOrRejectValue aValue,
-                         int aIterations)
-  : mTaskQueue(aTaskQueue)
-  , mPromise(aPromise)
-  , mValue(aValue)
-  , mIterations(aIterations)
-  {}
-
-  NS_IMETHODIMP Run()
-  {
-    MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
-    if (!mPromise) {
-      // Canceled.
-      return NS_OK;
-    }
-
-    if (--mIterations == 0) {
-      mPromise->ResolveOrReject(mValue, __func__);
-    } else {
-      nsCOMPtr<nsIRunnable> r = this;
-      mTaskQueue->Dispatch(r.forget());
-    }
-
-    return NS_OK;
-  }
-
-  void Cancel() {
-    mPromise = nullptr;
-  }
-
-protected:
-  ~DelayedResolveOrReject() {}
-
-private:
-  nsRefPtr<MediaTaskQueue> mTaskQueue;
-  nsRefPtr<TestPromise::Private> mPromise;
-  TestPromise::ResolveOrRejectValue mValue;
-  int mIterations;
-};
-
-template<typename FunctionType>
-void
-RunOnTaskQueue(MediaTaskQueue* aQueue, FunctionType aFun)
-{
-  nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(aFun);
-  aQueue->Dispatch(r.forget());
-}
-
-// std::function can't come soon enough. :-(
-#define DO_FAIL []()->void { EXPECT_TRUE(false); }
-
-TEST(MediaPromise, BasicResolve)
-{
-  AutoTaskQueue atq;
-  nsRefPtr<MediaTaskQueue> queue = atq.TaskQueue();
-  RunOnTaskQueue(queue, [queue] () -> void {
-    TestPromise::CreateAndResolve(42, __func__)->Then(queue, __func__,
-      [queue] (int aResolveValue) -> void { EXPECT_EQ(aResolveValue, 42); queue->BeginShutdown(); },
-      DO_FAIL);
-  });
-}
-
-TEST(MediaPromise, BasicReject)
-{
-  AutoTaskQueue atq;
-  nsRefPtr<MediaTaskQueue> queue = atq.TaskQueue();
-  RunOnTaskQueue(queue, [queue] () -> void {
-    TestPromise::CreateAndReject(42.0, __func__)->Then(queue, __func__,
-      DO_FAIL,
-      [queue] (int aRejectValue) -> void { EXPECT_EQ(aRejectValue, 42.0); queue->BeginShutdown(); });
-  });
-}
-
-TEST(MediaPromise, AsyncResolve)
-{
-  AutoTaskQueue atq;
-  nsRefPtr<MediaTaskQueue> queue = atq.TaskQueue();
-  RunOnTaskQueue(queue, [queue] () -> void {
-    nsRefPtr<TestPromise::Private> p = new TestPromise::Private(__func__);
-
-    // Kick off three racing tasks, and make sure we get the one that finishes earliest.
-    nsRefPtr<DelayedResolveOrReject> a = new DelayedResolveOrReject(queue, p, RRValue::MakeResolve(32), 10);
-    nsRefPtr<DelayedResolveOrReject> b = new DelayedResolveOrReject(queue, p, RRValue::MakeResolve(42), 5);
-    nsRefPtr<DelayedResolveOrReject> c = new DelayedResolveOrReject(queue, p, RRValue::MakeReject(32.0), 7);
-
-    nsCOMPtr<nsIRunnable> ref = a.get();
-    queue->Dispatch(ref.forget());
-    ref = b.get();
-    queue->Dispatch(ref.forget());
-    ref = c.get();
-    queue->Dispatch(ref.forget());
-
-    p->Then(queue, __func__, [queue, a, b, c] (int aResolveValue) -> void {
-      EXPECT_EQ(aResolveValue, 42);
-      a->Cancel();
-      b->Cancel();
-      c->Cancel();
-      queue->BeginShutdown();
-    }, DO_FAIL);
-  });
-}
-
-TEST(MediaPromise, CompletionPromises)
-{
-  bool invokedPass = false;
-  AutoTaskQueue atq;
-  nsRefPtr<MediaTaskQueue> queue = atq.TaskQueue();
-  RunOnTaskQueue(queue, [queue, &invokedPass] () -> void {
-    TestPromise::CreateAndResolve(40, __func__)
-    ->Then(queue, __func__,
-      [] (int aVal) -> nsRefPtr<TestPromise> { return TestPromise::CreateAndResolve(aVal + 10, __func__); },
-      DO_FAIL)
-    ->CompletionPromise()
-    ->Then(queue, __func__, [&invokedPass] () -> void { invokedPass = true; }, DO_FAIL)
-    ->CompletionPromise()
-    ->Then(queue, __func__,
-      [queue] (int aVal) -> nsRefPtr<TestPromise> {
-        nsRefPtr<TestPromise::Private> p = new TestPromise::Private(__func__);
-        nsCOMPtr<nsIRunnable> resolver = new DelayedResolveOrReject(queue, p, RRValue::MakeResolve(aVal - 8), 10);
-        queue->Dispatch(resolver.forget());
-        return nsRefPtr<TestPromise>(p);
-      },
-      DO_FAIL)
-    ->CompletionPromise()
-    ->Then(queue, __func__,
-      [queue] (int aVal) -> nsRefPtr<TestPromise> { return TestPromise::CreateAndReject(double(aVal - 42) + 42.0, __func__); },
-      DO_FAIL)
-    ->CompletionPromise()
-    ->Then(queue, __func__,
-      DO_FAIL,
-      [queue, &invokedPass] (double aVal) -> void { EXPECT_EQ(aVal, 42.0); EXPECT_TRUE(invokedPass); queue->BeginShutdown(); });
-  });
-}
-
-TEST(MediaPromise, PromiseAllResolve)
-{
-  AutoTaskQueue atq;
-  nsRefPtr<MediaTaskQueue> queue = atq.TaskQueue();
-  RunOnTaskQueue(queue, [queue] () -> void {
-
-    nsTArray<nsRefPtr<TestPromise>> promises;
-    promises.AppendElement(TestPromise::CreateAndResolve(22, __func__));
-    promises.AppendElement(TestPromise::CreateAndResolve(32, __func__));
-    promises.AppendElement(TestPromise::CreateAndResolve(42, __func__));
-
-    TestPromise::All(queue, promises)->Then(queue, __func__,
-      [queue] (const nsTArray<int>& aResolveValues) -> void {
-        EXPECT_EQ(aResolveValues.Length(), 3UL);
-        EXPECT_EQ(aResolveValues[0], 22);
-        EXPECT_EQ(aResolveValues[1], 32);
-        EXPECT_EQ(aResolveValues[2], 42);
-        queue->BeginShutdown();
-      },
-      DO_FAIL
-    );
-  });
-}
-
-TEST(MediaPromise, PromiseAllReject)
-{
-  AutoTaskQueue atq;
-  nsRefPtr<MediaTaskQueue> queue = atq.TaskQueue();
-  RunOnTaskQueue(queue, [queue] () -> void {
-
-    nsTArray<nsRefPtr<TestPromise>> promises;
-    promises.AppendElement(TestPromise::CreateAndResolve(22, __func__));
-    promises.AppendElement(TestPromise::CreateAndReject(32.0, __func__));
-    promises.AppendElement(TestPromise::CreateAndResolve(42, __func__));
-
-    TestPromise::All(queue, promises)->Then(queue, __func__,
-      DO_FAIL,
-      [queue] (float aRejectValue) -> void {
-        EXPECT_EQ(aRejectValue, 32.0);
-        queue->BeginShutdown();
-      }
-    );
-  });
-}
-
-#undef DO_FAIL
new file mode 100644
--- /dev/null
+++ b/dom/media/gtest/TestMozPromise.cpp
@@ -0,0 +1,219 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "gtest/gtest.h"
+#include "nsISupportsImpl.h"
+#include "MediaTaskQueue.h"
+#include "MozPromise.h"
+#include "SharedThreadPool.h"
+#include "VideoUtils.h"
+
+using namespace mozilla;
+
+typedef MozPromise<int, double, false> TestPromise;
+typedef TestPromise::ResolveOrRejectValue RRValue;
+
+class MOZ_STACK_CLASS AutoTaskQueue
+{
+public:
+  AutoTaskQueue()
+    : mTaskQueue(new MediaTaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK)))
+  {}
+
+  ~AutoTaskQueue()
+  {
+    mTaskQueue->AwaitShutdownAndIdle();
+  }
+
+  MediaTaskQueue* TaskQueue() { return mTaskQueue; }
+private:
+  nsRefPtr<MediaTaskQueue> mTaskQueue;
+};
+
+class DelayedResolveOrReject : public nsRunnable
+{
+public:
+  DelayedResolveOrReject(MediaTaskQueue* aTaskQueue,
+                         TestPromise::Private* aPromise,
+                         TestPromise::ResolveOrRejectValue aValue,
+                         int aIterations)
+  : mTaskQueue(aTaskQueue)
+  , mPromise(aPromise)
+  , mValue(aValue)
+  , mIterations(aIterations)
+  {}
+
+  NS_IMETHODIMP Run()
+  {
+    MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
+    if (!mPromise) {
+      // Canceled.
+      return NS_OK;
+    }
+
+    if (--mIterations == 0) {
+      mPromise->ResolveOrReject(mValue, __func__);
+    } else {
+      nsCOMPtr<nsIRunnable> r = this;
+      mTaskQueue->Dispatch(r.forget());
+    }
+
+    return NS_OK;
+  }
+
+  void Cancel() {
+    mPromise = nullptr;
+  }
+
+protected:
+  ~DelayedResolveOrReject() {}
+
+private:
+  nsRefPtr<MediaTaskQueue> mTaskQueue;
+  nsRefPtr<TestPromise::Private> mPromise;
+  TestPromise::ResolveOrRejectValue mValue;
+  int mIterations;
+};
+
+template<typename FunctionType>
+void
+RunOnTaskQueue(MediaTaskQueue* aQueue, FunctionType aFun)
+{
+  nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(aFun);
+  aQueue->Dispatch(r.forget());
+}
+
+// std::function can't come soon enough. :-(
+#define DO_FAIL []()->void { EXPECT_TRUE(false); }
+
+TEST(MozPromise, BasicResolve)
+{
+  AutoTaskQueue atq;
+  nsRefPtr<MediaTaskQueue> queue = atq.TaskQueue();
+  RunOnTaskQueue(queue, [queue] () -> void {
+    TestPromise::CreateAndResolve(42, __func__)->Then(queue, __func__,
+      [queue] (int aResolveValue) -> void { EXPECT_EQ(aResolveValue, 42); queue->BeginShutdown(); },
+      DO_FAIL);
+  });
+}
+
+TEST(MozPromise, BasicReject)
+{
+  AutoTaskQueue atq;
+  nsRefPtr<MediaTaskQueue> queue = atq.TaskQueue();
+  RunOnTaskQueue(queue, [queue] () -> void {
+    TestPromise::CreateAndReject(42.0, __func__)->Then(queue, __func__,
+      DO_FAIL,
+      [queue] (int aRejectValue) -> void { EXPECT_EQ(aRejectValue, 42.0); queue->BeginShutdown(); });
+  });
+}
+
+TEST(MozPromise, AsyncResolve)
+{
+  AutoTaskQueue atq;
+  nsRefPtr<MediaTaskQueue> queue = atq.TaskQueue();
+  RunOnTaskQueue(queue, [queue] () -> void {
+    nsRefPtr<TestPromise::Private> p = new TestPromise::Private(__func__);
+
+    // Kick off three racing tasks, and make sure we get the one that finishes earliest.
+    nsRefPtr<DelayedResolveOrReject> a = new DelayedResolveOrReject(queue, p, RRValue::MakeResolve(32), 10);
+    nsRefPtr<DelayedResolveOrReject> b = new DelayedResolveOrReject(queue, p, RRValue::MakeResolve(42), 5);
+    nsRefPtr<DelayedResolveOrReject> c = new DelayedResolveOrReject(queue, p, RRValue::MakeReject(32.0), 7);
+
+    nsCOMPtr<nsIRunnable> ref = a.get();
+    queue->Dispatch(ref.forget());
+    ref = b.get();
+    queue->Dispatch(ref.forget());
+    ref = c.get();
+    queue->Dispatch(ref.forget());
+
+    p->Then(queue, __func__, [queue, a, b, c] (int aResolveValue) -> void {
+      EXPECT_EQ(aResolveValue, 42);
+      a->Cancel();
+      b->Cancel();
+      c->Cancel();
+      queue->BeginShutdown();
+    }, DO_FAIL);
+  });
+}
+
+TEST(MozPromise, CompletionPromises)
+{
+  bool invokedPass = false;
+  AutoTaskQueue atq;
+  nsRefPtr<MediaTaskQueue> queue = atq.TaskQueue();
+  RunOnTaskQueue(queue, [queue, &invokedPass] () -> void {
+    TestPromise::CreateAndResolve(40, __func__)
+    ->Then(queue, __func__,
+      [] (int aVal) -> nsRefPtr<TestPromise> { return TestPromise::CreateAndResolve(aVal + 10, __func__); },
+      DO_FAIL)
+    ->CompletionPromise()
+    ->Then(queue, __func__, [&invokedPass] () -> void { invokedPass = true; }, DO_FAIL)
+    ->CompletionPromise()
+    ->Then(queue, __func__,
+      [queue] (int aVal) -> nsRefPtr<TestPromise> {
+        nsRefPtr<TestPromise::Private> p = new TestPromise::Private(__func__);
+        nsCOMPtr<nsIRunnable> resolver = new DelayedResolveOrReject(queue, p, RRValue::MakeResolve(aVal - 8), 10);
+        queue->Dispatch(resolver.forget());
+        return nsRefPtr<TestPromise>(p);
+      },
+      DO_FAIL)
+    ->CompletionPromise()
+    ->Then(queue, __func__,
+      [queue] (int aVal) -> nsRefPtr<TestPromise> { return TestPromise::CreateAndReject(double(aVal - 42) + 42.0, __func__); },
+      DO_FAIL)
+    ->CompletionPromise()
+    ->Then(queue, __func__,
+      DO_FAIL,
+      [queue, &invokedPass] (double aVal) -> void { EXPECT_EQ(aVal, 42.0); EXPECT_TRUE(invokedPass); queue->BeginShutdown(); });
+  });
+}
+
+TEST(MozPromise, PromiseAllResolve)
+{
+  AutoTaskQueue atq;
+  nsRefPtr<MediaTaskQueue> queue = atq.TaskQueue();
+  RunOnTaskQueue(queue, [queue] () -> void {
+
+    nsTArray<nsRefPtr<TestPromise>> promises;
+    promises.AppendElement(TestPromise::CreateAndResolve(22, __func__));
+    promises.AppendElement(TestPromise::CreateAndResolve(32, __func__));
+    promises.AppendElement(TestPromise::CreateAndResolve(42, __func__));
+
+    TestPromise::All(queue, promises)->Then(queue, __func__,
+      [queue] (const nsTArray<int>& aResolveValues) -> void {
+        EXPECT_EQ(aResolveValues.Length(), 3UL);
+        EXPECT_EQ(aResolveValues[0], 22);
+        EXPECT_EQ(aResolveValues[1], 32);
+        EXPECT_EQ(aResolveValues[2], 42);
+        queue->BeginShutdown();
+      },
+      DO_FAIL
+    );
+  });
+}
+
+TEST(MozPromise, PromiseAllReject)
+{
+  AutoTaskQueue atq;
+  nsRefPtr<MediaTaskQueue> queue = atq.TaskQueue();
+  RunOnTaskQueue(queue, [queue] () -> void {
+
+    nsTArray<nsRefPtr<TestPromise>> promises;
+    promises.AppendElement(TestPromise::CreateAndResolve(22, __func__));
+    promises.AppendElement(TestPromise::CreateAndReject(32.0, __func__));
+    promises.AppendElement(TestPromise::CreateAndResolve(42, __func__));
+
+    TestPromise::All(queue, promises)->Then(queue, __func__,
+      DO_FAIL,
+      [queue] (float aRejectValue) -> void {
+        EXPECT_EQ(aRejectValue, 32.0);
+        queue->BeginShutdown();
+      }
+    );
+  });
+}
+
+#undef DO_FAIL
--- a/dom/media/gtest/moz.build
+++ b/dom/media/gtest/moz.build
@@ -5,17 +5,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 UNIFIED_SOURCES += [
     'MockMediaResource.cpp',
     'TestAudioCompactor.cpp',
     'TestGMPCrossOrigin.cpp',
     'TestGMPRemoveAndDelete.cpp',
     'TestIntervalSet.cpp',
-    'TestMediaPromise.cpp',
+    'TestMozPromise.cpp',
     'TestMP3Demuxer.cpp',
     'TestMP4Demuxer.cpp',
     # 'TestMP4Reader.cpp', disabled so we can turn check tests back on (bug 1175752)
     'TestTrackEncoder.cpp',
     'TestVideoSegment.cpp',
     'TestWebMBuffered.cpp',
 ]
 
--- a/dom/media/mediasource/MediaSourceReader.h
+++ b/dom/media/mediasource/MediaSourceReader.h
@@ -201,17 +201,17 @@ private:
     mVideoPromise.Reject(DECODE_ERROR, __func__);
   }
 
   MediaDecoderReader* GetAudioReader() const;
   MediaDecoderReader* GetVideoReader() const;
   int64_t GetReaderAudioTime(int64_t aTime) const;
   int64_t GetReaderVideoTime(int64_t aTime) const;
 
-  // Will reject the MediaPromise with END_OF_STREAM if mediasource has ended
+  // Will reject the MozPromise with END_OF_STREAM if mediasource has ended
   // or with WAIT_FOR_DATA otherwise.
   void CheckForWaitOrEndOfStream(MediaData::Type aType, int64_t aTime /* microseconds */);
 
   // Return a decoder from the set available in aTrackDecoders that has data
   // available in the range requested by aTarget.
   friend class TrackBuffer;
   already_AddRefed<SourceBufferDecoder> SelectDecoder(int64_t aTarget /* microseconds */,
                                                       int64_t aTolerance /* microseconds */,
@@ -229,42 +229,42 @@ private:
   nsRefPtr<SourceBufferDecoder> mVideoSourceDecoder;
 
   nsTArray<nsRefPtr<TrackBuffer>> mTrackBuffers;
   nsTArray<nsRefPtr<TrackBuffer>> mShutdownTrackBuffers;
   nsTArray<nsRefPtr<TrackBuffer>> mEssentialTrackBuffers;
   nsRefPtr<TrackBuffer> mAudioTrack;
   nsRefPtr<TrackBuffer> mVideoTrack;
 
-  MediaPromiseRequestHolder<AudioDataPromise> mAudioRequest;
-  MediaPromiseRequestHolder<VideoDataPromise> mVideoRequest;
+  MozPromiseRequestHolder<AudioDataPromise> mAudioRequest;
+  MozPromiseRequestHolder<VideoDataPromise> mVideoRequest;
 
-  MediaPromiseHolder<AudioDataPromise> mAudioPromise;
-  MediaPromiseHolder<VideoDataPromise> mVideoPromise;
+  MozPromiseHolder<AudioDataPromise> mAudioPromise;
+  MozPromiseHolder<VideoDataPromise> mVideoPromise;
 
-  MediaPromiseHolder<WaitForDataPromise> mAudioWaitPromise;
-  MediaPromiseHolder<WaitForDataPromise> mVideoWaitPromise;
-  MediaPromiseHolder<WaitForDataPromise>& WaitPromise(MediaData::Type aType)
+  MozPromiseHolder<WaitForDataPromise> mAudioWaitPromise;
+  MozPromiseHolder<WaitForDataPromise> mVideoWaitPromise;
+  MozPromiseHolder<WaitForDataPromise>& WaitPromise(MediaData::Type aType)
   {
     return aType == MediaData::AUDIO_DATA ? mAudioWaitPromise : mVideoWaitPromise;
   }
 
 #ifdef MOZ_EME
   nsRefPtr<CDMProxy> mCDMProxy;
 #endif
 
   // These are read and written on the decode task queue threads.
   int64_t mLastAudioTime;
   int64_t mLastVideoTime;
 
   bool mForceVideoDecodeAhead;
 
-  MediaPromiseRequestHolder<SeekPromise> mAudioSeekRequest;
-  MediaPromiseRequestHolder<SeekPromise> mVideoSeekRequest;
-  MediaPromiseHolder<SeekPromise> mSeekPromise;
+  MozPromiseRequestHolder<SeekPromise> mAudioSeekRequest;
+  MozPromiseRequestHolder<SeekPromise> mVideoSeekRequest;
+  MozPromiseHolder<SeekPromise> mSeekPromise;
 
   // Temporary seek information while we wait for the data
   // to be added to the track buffer.
   int64_t mOriginalSeekTime;
   int64_t mPendingSeekTime;
   bool mWaitingForSeekData;
   bool mSeekToEnd;
 
@@ -276,17 +276,17 @@ private:
   bool mVideoDiscontinuity;
 
   bool mEnded;
   double mMediaSourceDuration;
 
   bool mHasEssentialTrackBuffers;
 
   void ContinueShutdown();
-  MediaPromiseHolder<ShutdownPromise> mMediaSourceShutdownPromise;
+  MozPromiseHolder<ShutdownPromise> mMediaSourceShutdownPromise;
 #ifdef MOZ_FMP4
   nsRefPtr<SharedDecoderManager> mSharedDecoderManager;
 #endif
 };
 
 } // namespace mozilla
 
 #endif /* MOZILLA_MEDIASOURCEREADER_H_ */
--- a/dom/media/mediasource/SourceBuffer.h
+++ b/dom/media/mediasource/SourceBuffer.h
@@ -2,17 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_SourceBuffer_h_
 #define mozilla_dom_SourceBuffer_h_
 
-#include "MediaPromise.h"
+#include "MozPromise.h"
 #include "MediaSource.h"
 #include "js/RootingAPI.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "mozilla/dom/SourceBufferBinding.h"
 #include "mozilla/dom/TypedArray.h"
@@ -190,17 +190,17 @@ private:
   mozilla::Atomic<bool> mActive;
 
   // Each time mUpdating is set to true, mUpdateID will be incremented.
   // This allows for a queued AppendData task to identify if it was earlier
   // aborted and another AppendData queued.
   uint32_t mUpdateID;
   int64_t mReportedOffset;
 
-  MediaPromiseRequestHolder<SourceBufferContentManager::AppendPromise> mPendingAppend;
+  MozPromiseRequestHolder<SourceBufferContentManager::AppendPromise> mPendingAppend;
   const nsCString mType;
 };
 
 } // namespace dom
 
 } // namespace mozilla
 
 #endif /* mozilla_dom_SourceBuffer_h_ */
--- a/dom/media/mediasource/SourceBufferContentManager.h
+++ b/dom/media/mediasource/SourceBufferContentManager.h
@@ -3,32 +3,32 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_SOURCEBUFFERCONTENTMANAGER_H_
 #define MOZILLA_SOURCEBUFFERCONTENTMANAGER_H_
 
 #include "MediaData.h"
-#include "MediaPromise.h"
+#include "MozPromise.h"
 #include "MediaSourceDecoder.h"
 #include "SourceBuffer.h"
 #include "TimeUnits.h"
 #include "nsString.h"
 
 namespace mozilla {
 
 using media::TimeUnit;
 using media::TimeIntervals;
 
 class SourceBufferContentManager {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SourceBufferContentManager);
 
-  typedef MediaPromise<bool, nsresult, /* IsExclusive = */ true> AppendPromise;
+  typedef MozPromise<bool, nsresult, /* IsExclusive = */ true> AppendPromise;
   typedef AppendPromise RangeRemovalPromise;
 
   static already_AddRefed<SourceBufferContentManager>
   CreateManager(dom::SourceBuffer* aParent, MediaSourceDecoder* aParentDecoder,
                 const nsACString& aType);
 
   // Add data to the end of the input buffer.
   // Returns false if the append failed.
--- a/dom/media/mediasource/TrackBuffer.cpp
+++ b/dom/media/mediasource/TrackBuffer.cpp
@@ -1088,17 +1088,17 @@ TrackBuffer::AbortAppendData()
   nsRefPtr<SourceBufferDecoder> current = mCurrentDecoder;
   DiscardCurrentDecoder();
 
   if (mMetadataRequest.Exists() || !mInitializationPromise.IsEmpty()) {
     MOZ_ASSERT(current);
     RemoveDecoder(current);
   }
   // The SourceBuffer would have disconnected its promise.
-  // However we must ensure that the MediaPromiseHolder handle all pending
+  // However we must ensure that the MozPromiseHolder handle all pending
   // promises.
   mInitializationPromise.RejectIfExists(NS_ERROR_ABORT, __func__);
 }
 
 const nsTArray<nsRefPtr<SourceBufferDecoder>>&
 TrackBuffer::Decoders()
 {
   // XXX assert OnDecodeTaskQueue
--- a/dom/media/mediasource/TrackBuffer.h
+++ b/dom/media/mediasource/TrackBuffer.h
@@ -133,17 +133,17 @@ private:
   // data is appended to the current decoder's SourceBufferResource.
   int64_t AppendDataToCurrentResource(MediaByteBuffer* aData,
                                    uint32_t aDuration /* microseconds */);
   // Queue on the parent's decoder task queue a call to NotifyTimeRangesChanged.
   void NotifyTimeRangesChanged();
   // Queue on the parent's decoder task queue a call to NotifyDataRemoved.
   void NotifyReaderDataRemoved(MediaDecoderReader* aReader);
 
-  typedef MediaPromise<bool, nsresult, /* IsExclusive = */ true> BufferedRangesUpdatedPromise;
+  typedef MozPromise<bool, nsresult, /* IsExclusive = */ true> BufferedRangesUpdatedPromise;
   nsRefPtr<BufferedRangesUpdatedPromise> UpdateBufferedRanges(Interval<int64_t> aByteRange, bool aNotifyParent);
 
   // Queue execution of InitializeDecoder on mTaskQueue.
   bool QueueInitializeDecoder(SourceBufferDecoder* aDecoder);
 
   // Runs decoder initialization including calling ReadMetadata.  Runs as an
   // event on the decode thread pool.
   void InitializeDecoder(SourceBufferDecoder* aDecoder);
@@ -221,25 +221,25 @@ private:
   // True if at least one of our decoders has encrypted content.
   bool mIsWaitingOnCDM;
 
   // Set when the first decoder used by this TrackBuffer is initialized.
   // Protected by mParentDecoder's monitor.
   MediaInfo mInfo;
 
   void ContinueShutdown();
-  MediaPromiseHolder<ShutdownPromise> mShutdownPromise;
+  MozPromiseHolder<ShutdownPromise> mShutdownPromise;
   bool mDecoderPerSegment;
   bool mShutdown;
 
-  MediaPromiseHolder<AppendPromise> mInitializationPromise;
+  MozPromiseHolder<AppendPromise> mInitializationPromise;
   // Track our request for metadata from the reader.
-  MediaPromiseRequestHolder<MediaDecoderReader::MetadataPromise> mMetadataRequest;
+  MozPromiseRequestHolder<MediaDecoderReader::MetadataPromise> mMetadataRequest;
 
-  MediaPromiseHolder<RangeRemovalPromise> mRangeRemovalPromise;
+  MozPromiseHolder<RangeRemovalPromise> mRangeRemovalPromise;
 
   Interval<int64_t> mLastAppendRange;
 
   // Protected by Parent's decoder Monitor.
   media::TimeIntervals mBufferedRanges;
 
   DecoderBufferedMap mReadersBuffered;
 };
--- a/dom/media/mediasource/TrackBuffersManager.h
+++ b/dom/media/mediasource/TrackBuffersManager.h
@@ -29,17 +29,17 @@ class SourceBufferResource;
 
 using media::TimeUnit;
 using media::TimeInterval;
 using media::TimeIntervals;
 using dom::SourceBufferAppendMode;
 
 class TrackBuffersManager : public SourceBufferContentManager {
 public:
-  typedef MediaPromise<bool, nsresult, /* IsExclusive = */ true> CodedFrameProcessingPromise;
+  typedef MozPromise<bool, nsresult, /* IsExclusive = */ true> CodedFrameProcessingPromise;
   typedef TrackInfo::TrackType TrackType;
   typedef MediaData::Type MediaType;
   typedef nsTArray<nsRefPtr<MediaRawData>> TrackBuffer;
 
   TrackBuffersManager(dom::SourceBuffer* aParent, MediaSourceDecoder* aParentDecoder, const nsACString& aType);
 
   bool AppendData(MediaByteBuffer* aData, TimeUnit aTimestampOffset) override;
 
@@ -161,17 +161,17 @@ private:
   nsRefPtr<MediaByteBuffer> mInitData;
   nsRefPtr<SourceBufferResource> mCurrentInputBuffer;
   nsRefPtr<MediaDataDemuxer> mInputDemuxer;
   // Length already processed in current media segment.
   uint32_t mProcessedInput;
 
   void OnDemuxerInitDone(nsresult);
   void OnDemuxerInitFailed(DemuxerFailureReason aFailure);
-  MediaPromiseRequestHolder<MediaDataDemuxer::InitPromise> mDemuxerInitRequest;
+  MozPromiseRequestHolder<MediaDataDemuxer::InitPromise> mDemuxerInitRequest;
   bool mEncrypted;
 
   void OnDemuxFailed(TrackType aTrack, DemuxerFailureReason aFailure);
   void DoDemuxVideo();
   void OnVideoDemuxCompleted(nsRefPtr<MediaTrackDemuxer::SamplesHolder> aSamples);
   void OnVideoDemuxFailed(DemuxerFailureReason aFailure)
   {
     mVideoTracks.mDemuxRequest.Complete();
@@ -216,17 +216,17 @@ private:
     Maybe<TimeUnit> mLongestFrameDuration;
     // Need random access point flag variable that keeps track of whether the
     // track buffer is waiting for a random access point coded frame.
     // The variable is initially set to true to indicate that random access
     // point coded frame is needed before anything can be added to the track
     // buffer.
     bool mNeedRandomAccessPoint;
     nsRefPtr<MediaTrackDemuxer> mDemuxer;
-    MediaPromiseRequestHolder<MediaTrackDemuxer::SamplesPromise> mDemuxRequest;
+    MozPromiseRequestHolder<MediaTrackDemuxer::SamplesPromise> mDemuxRequest;
     // If set, position where the next contiguous frame will be inserted.
     // If a discontinuity is detected, it will be unset and recalculated upon
     // the next insertion.
     Maybe<size_t> mNextInsertionIndex;
     // Samples just demuxed, but not yet parsed.
     TrackBuffer mQueuedSamples;
     // We only manage a single track of each type at this time.
     nsTArray<TrackBuffer> mBuffers;
@@ -267,20 +267,20 @@ private:
                     const TimeIntervals& aIntervals,
                     TrackData& aTrackData);
   void RemoveFrames(const TimeIntervals& aIntervals,
                     TrackData& aTrackData,
                     uint32_t aStartIndex);
   void UpdateBufferedRanges();
   void RejectProcessing(nsresult aRejectValue, const char* aName);
   void ResolveProcessing(bool aResolveValue, const char* aName);
-  MediaPromiseRequestHolder<CodedFrameProcessingPromise> mProcessingRequest;
-  MediaPromiseHolder<CodedFrameProcessingPromise> mProcessingPromise;
+  MozPromiseRequestHolder<CodedFrameProcessingPromise> mProcessingRequest;
+  MozPromiseHolder<CodedFrameProcessingPromise> mProcessingPromise;
 
-  MediaPromiseHolder<AppendPromise> mAppendPromise;
+  MozPromiseHolder<AppendPromise> mAppendPromise;
   // Set to true while SegmentParserLoop is running. This is used for diagnostic
   // purposes only. We can't rely on mAppendPromise to be empty as it is only
   // cleared in a follow up task.
   bool mAppendRunning;
 
   // Trackbuffers definition.
   nsTArray<TrackData*> GetTracksList();
   TrackData& GetTracksData(TrackType aTrack)
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -119,26 +119,26 @@ EXPORTS += [
     'MediaDataDemuxer.h',
     'MediaDecoder.h',
     'MediaDecoderOwner.h',
     'MediaDecoderReader.h',
     'MediaDecoderStateMachine.h',
     'MediaFormatReader.h',
     'MediaInfo.h',
     'MediaMetadataManager.h',
-    'MediaPromise.h',
     'MediaQueue.h',
     'MediaRecorder.h',
     'MediaResource.h',
     'MediaSegment.h',
     'MediaStreamGraph.h',
     'MediaTaskQueue.h',
     'MediaTimer.h',
     'MediaTrack.h',
     'MediaTrackList.h',
+    'MozPromise.h',
     'MP3Decoder.h',
     'MP3Demuxer.h',
     'MP3FrameParser.h',
     'nsIDocumentActivity.h',
     'RtspMediaResource.h',
     'SelfRef.h',
     'SharedBuffer.h',
     'SharedThreadPool.h',
--- a/dom/media/omx/AudioOffloadPlayer.h
+++ b/dom/media/omx/AudioOffloadPlayer.h
@@ -141,20 +141,20 @@ private:
   // mLock
   int64_t mStartPosUs;
 
   // The target of current seek when there is a request to seek
   // Used in main thread and offload callback thread, protected by Mutex
   // mLock
   SeekTarget mSeekTarget;
 
-  // MediaPromise of current seek.
+  // MozPromise of current seek.
   // Used in main thread and offload callback thread, protected by Mutex
   // mLock
-  MediaPromiseHolder<MediaDecoder::SeekPromise> mSeekPromise;
+  MozPromiseHolder<MediaDecoder::SeekPromise> mSeekPromise;
 
   // Positions obtained from offlaoded tracks (DSP)
   // Used in main thread and offload callback thread, protected by Mutex
   // mLock
   int64_t mPositionTimeMediaUs;
 
   // State obtained from MediaOmxCommonDecoder. Used only in main thread
   MediaDecoder::PlayState mPlayState;
--- a/dom/media/omx/MediaCodecReader.h
+++ b/dom/media/omx/MediaCodecReader.h
@@ -173,20 +173,20 @@ protected:
   virtual void VideoCodecCanceled();
 
   virtual bool CreateExtractor();
 
   virtual void HandleResourceAllocated();
 
   android::sp<android::MediaExtractor> mExtractor;
 
-  MediaPromiseHolder<MediaDecoderReader::MetadataPromise> mMetadataPromise;
+  MozPromiseHolder<MediaDecoderReader::MetadataPromise> mMetadataPromise;
   // XXX Remove after bug 1168008 land.
-  MediaPromiseRequestHolder<MediaResourcePromise> mMediaResourceRequest;
-  MediaPromiseHolder<MediaResourcePromise> mMediaResourcePromise;
+  MozPromiseRequestHolder<MediaResourcePromise> mMediaResourceRequest;
+  MozPromiseHolder<MediaResourcePromise> mMediaResourcePromise;
 
 private:
 
   // An intermediary class that can be managed by android::sp<T>.
   // Redirect codecReserved() and codecCanceled() to MediaCodecReader.
   class VideoResourceListener : public android::MediaCodecProxy::CodecResourceListener
   {
   public:
@@ -211,17 +211,17 @@ private:
     virtual bool Copy(android::MediaBuffer* aSourceBuffer,
                       android::sp<android::ABuffer> aCodecBuffer);
   };
 
   struct AudioTrack : public Track
   {
     AudioTrack();
     // Protected by mTrackMonitor.
-    MediaPromiseHolder<AudioDataPromise> mAudioPromise;
+    MozPromiseHolder<AudioDataPromise> mAudioPromise;
 
   private:
     // Forbidden
     AudioTrack(const AudioTrack &rhs) = delete;
     const AudioTrack &operator=(const AudioTrack &rhs) = delete;
   };
 
   struct VideoTrack : public Track
@@ -233,17 +233,17 @@ private:
     int32_t mStride;
     int32_t mSliceHeight;
     int32_t mColorFormat;
     int32_t mRotation;
     nsIntSize mFrameSize;
     nsIntRect mPictureRect;
     gfx::IntRect mRelativePictureRect;
     // Protected by mTrackMonitor.
-    MediaPromiseHolder<VideoDataPromise> mVideoPromise;
+    MozPromiseHolder<VideoDataPromise> mVideoPromise;
 
     nsRefPtr<MediaTaskQueue> mReleaseBufferTaskQueue;
   private:
     // Forbidden
     VideoTrack(const VideoTrack &rhs) = delete;
     const VideoTrack &operator=(const VideoTrack &rhs) = delete;
   };
 
--- a/dom/media/omx/MediaOmxCommonReader.h
+++ b/dom/media/omx/MediaOmxCommonReader.h
@@ -19,17 +19,17 @@ struct MOZ_EXPORT MediaSource;
 
 namespace mozilla {
 
 class AbstractMediaDecoder;
 
 class MediaOmxCommonReader : public MediaDecoderReader
 {
 public:
-  typedef MediaPromise<bool /* aIgnored */, bool /* aIgnored */, /* IsExclusive = */ true> MediaResourcePromise;
+  typedef MozPromise<bool /* aIgnored */, bool /* aIgnored */, /* IsExclusive = */ true> MediaResourcePromise;
 
   MediaOmxCommonReader(AbstractMediaDecoder* aDecoder);
 
   void SetAudioChannel(dom::AudioChannel aAudioChannel) {
     mAudioChannel = aAudioChannel;
   }
 
   virtual android::sp<android::MediaSource> GetAudioOffloadTrack() = 0;
--- a/dom/media/omx/MediaOmxReader.h
+++ b/dom/media/omx/MediaOmxReader.h
@@ -39,21 +39,21 @@ class MediaOmxReader : public MediaOmxCo
   nsIntSize mInitialFrame;
   int64_t mVideoSeekTimeUs;
   int64_t mAudioSeekTimeUs;
   int64_t mLastParserDuration;
   int32_t mSkipCount;
   // If mIsShutdown is false, and mShutdownMutex is held, then
   // AbstractMediaDecoder::mDecoder will be non-null.
   bool mIsShutdown;
-  MediaPromiseHolder<MediaDecoderReader::MetadataPromise> mMetadataPromise;
-  MediaPromiseRequestHolder<MediaResourcePromise> mMediaResourceRequest;
+  MozPromiseHolder<MediaDecoderReader::MetadataPromise> mMetadataPromise;
+  MozPromiseRequestHolder<MediaResourcePromise> mMediaResourceRequest;
 
-  MediaPromiseHolder<MediaDecoderReader::SeekPromise> mSeekPromise;
-  MediaPromiseRequestHolder<MediaDecoderReader::VideoDataPromise> mSeekRequest;
+  MozPromiseHolder<MediaDecoderReader::SeekPromise> mSeekPromise;
+  MozPromiseRequestHolder<MediaDecoderReader::VideoDataPromise> mSeekRequest;
 protected:
   android::sp<android::OmxDecoder> mOmxDecoder;
   android::sp<android::MediaExtractor> mExtractor;
   MP3FrameParser mMP3FrameParser;
 
   // Called by ReadMetadata() during MediaDecoderStateMachine::DecodeMetadata()
   // on decode thread. It create and initialize the OMX decoder including
   // setting up custom extractor. The extractor provide the essential
@@ -108,17 +108,17 @@ public:
 
   virtual void SetIdle() override;
 
   virtual nsRefPtr<ShutdownPromise> Shutdown() override;
 
   android::sp<android::MediaSource> GetAudioOffloadTrack();
 
   // This method is intended only for private use but public only for
-  // MediaPromise::InvokeCallbackMethod().
+  // MozPromise::InvokeCallbackMethod().
   void ReleaseDecoder();
 
 private:
   class ProcessCachedDataTask;
   class NotifyDataArrivedRunnable;
 
   bool IsShutdown() {
     MutexAutoLock lock(mShutdownMutex);
--- a/dom/media/omx/OmxDecoder.h
+++ b/dom/media/omx/OmxDecoder.h
@@ -116,17 +116,17 @@ class OmxDecoder : public OMXCodecProxy:
   // deliver a message to a wrapped object(OmxDecoder).
   // AHandlerReflector is similar to Handler in android Java.
   // http://developer.android.com/reference/android/os/Handler.html
   sp<AHandlerReflector<OmxDecoder> > mReflector;
 
   // 'true' if a read from the audio stream was done while reading the metadata
   bool mAudioMetadataRead;
 
-  mozilla::MediaPromiseHolder<MediaResourcePromise> mMediaResourcePromise;
+  mozilla::MozPromiseHolder<MediaResourcePromise> mMediaResourcePromise;
 
   void ReleaseVideoBuffer();
   void ReleaseAudioBuffer();
   // Call with mSeekLock held.
   void ReleaseAllPendingVideoBuffersLocked();
 
   void PlanarYUV420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame);
   void CbYCrYFrame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame);
--- a/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
@@ -12,17 +12,17 @@
 #include "mozilla/CDMProxy.h"
 #include "mozilla/unused.h"
 #include "nsServiceManagerUtils.h"
 #include "MediaInfo.h"
 #include "nsClassHashtable.h"
 
 namespace mozilla {
 
-typedef MediaPromiseRequestHolder<CDMProxy::DecryptPromise> DecryptPromiseRequestHolder;
+typedef MozPromiseRequestHolder<CDMProxy::DecryptPromise> DecryptPromiseRequestHolder;
 
 static PLDHashOperator
 DropDecryptPromises(MediaRawData* aKey,
                     nsAutoPtr<DecryptPromiseRequestHolder>& aData,
                     void* aUserArg)
 {
   aData->DisconnectIfExists();
   return PL_DHASH_REMOVE;