diff --git a/dom/media/MediaRecorder.cpp b/dom/media/MediaRecorder.cpp index 407881425a7c..60b7b5650024 100644 --- a/dom/media/MediaRecorder.cpp +++ b/dom/media/MediaRecorder.cpp @@ -499,7 +499,7 @@ class MediaRecorder::Session : public PrincipalChangeObserver, } } - static const bool IsExclusive = true; + static const bool IsExclusive = false; using BlobPromise = MozPromise, nsresult, IsExclusive>; class BlobStorer : public MutableBlobStorageCallback { @@ -528,19 +528,42 @@ class MediaRecorder::Session : public PrincipalChangeObserver, RefPtr Promise() { return mHolder.Ensure(__func__); } }; - // Stops gathering data into the current blob and resolves when the current - // blob is available. Future data will be stored in a new blob. - RefPtr GatherBlob() { - MOZ_ASSERT(NS_IsMainThread()); + protected: + RefPtr GatherBlobImpl() { RefPtr storer = MakeAndAddRef(); MaybeCreateMutableBlobStorage(); mMutableBlobStorage->GetBlobWhenReady( mRecorder->GetOwner(), NS_ConvertUTF16toUTF8(mMimeType), storer); mMutableBlobStorage = nullptr; + storer->Promise()->Then( + mMainThread, __func__, + [self = RefPtr(this), p = storer->Promise()] { + if (self->mBlobPromise == p) { + // Reset BlobPromise. + self->mBlobPromise = nullptr; + } + }); + return storer->Promise(); } + public: + // Stops gathering data into the current blob and resolves when the current + // blob is available. Future data will be stored in a new blob. + // Should a previous async GatherBlob() operation still be in progress, we'll + // wait for it to finish before starting this one. + RefPtr GatherBlob() { + MOZ_ASSERT(NS_IsMainThread()); + if (!mBlobPromise) { + return mBlobPromise = GatherBlobImpl(); + } + return mBlobPromise = mBlobPromise->Then(mMainThread, __func__, + [self = RefPtr(this)] { + return self->GatherBlobImpl(); + }); + } + RefPtr SizeOfExcludingThis( mozilla::MallocSizeOf aMallocSizeOf) { MOZ_ASSERT(NS_IsMainThread()); @@ -1142,6 +1165,9 @@ class MediaRecorder::Session : public PrincipalChangeObserver, RefPtr mMutableBlobStorage; // Max memory to use for the MutableBlobStorage. uint64_t mMaxMemory; + // If set, is a promise for the latest GatherBlob() operation. Allows + // GatherBlob() operations to be serialized in order to avoid races. + RefPtr mBlobPromise; // Current session mimeType nsString mMimeType; // Timestamp of the last fired dataavailable event.