Bug 1049327 - Assert that public MSE API is only called from the main thread. r=cajbir
authorMatthew Gregan <kinetik@flim.org>
Mon, 11 Aug 2014 13:21:18 +1200
changeset 198815 20bdca5301b06b58b67e7303195d4a90b029efcb
parent 198814 579f8a1cbf34fb13c718474b6bd36aa8b5e85d12
child 198816 9d08e8efdd42b77deb77ec700c2802097de5ad4c
push id47494
push usermgregan@mozilla.com
push dateMon, 11 Aug 2014 02:06:55 +0000
treeherdermozilla-inbound@c9c9e94945fe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscajbir
bugs1049327
milestone34.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 1049327 - Assert that public MSE API is only called from the main thread. r=cajbir
content/media/mediasource/MediaSource.cpp
content/media/mediasource/SourceBuffer.cpp
content/media/mediasource/SourceBufferList.cpp
--- a/content/media/mediasource/MediaSource.cpp
+++ b/content/media/mediasource/MediaSource.cpp
@@ -122,67 +122,74 @@ MediaSource::Constructor(const GlobalObj
   }
 
   nsRefPtr<MediaSource> mediaSource = new MediaSource(window);
   return mediaSource.forget();
 }
 
 MediaSource::~MediaSource()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_API("MediaSource(%p)::~MediaSource()", this);
 }
 
 SourceBufferList*
 MediaSource::SourceBuffers()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT_IF(mReadyState == MediaSourceReadyState::Closed, mSourceBuffers->IsEmpty());
   return mSourceBuffers;
 }
 
 SourceBufferList*
 MediaSource::ActiveSourceBuffers()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT_IF(mReadyState == MediaSourceReadyState::Closed, mActiveSourceBuffers->IsEmpty());
   return mActiveSourceBuffers;
 }
 
 MediaSourceReadyState
 MediaSource::ReadyState()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   return mReadyState;
 }
 
 double
 MediaSource::Duration()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   if (mReadyState == MediaSourceReadyState::Closed) {
     return UnspecifiedNaN<double>();
   }
   return mDuration;
 }
 
 void
 MediaSource::SetDuration(double aDuration, ErrorResult& aRv)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_API("MediaSource(%p)::SetDuration(aDuration=%f)", this, aDuration);
   if (aDuration < 0 || IsNaN(aDuration)) {
     aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return;
   }
   if (mReadyState != MediaSourceReadyState::Open ||
       mSourceBuffers->AnyUpdating()) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
   DurationChange(aDuration, aRv);
 }
 
 already_AddRefed<SourceBuffer>
 MediaSource::AddSourceBuffer(const nsAString& aType, ErrorResult& aRv)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   nsresult rv = mozilla::IsTypeSupported(aType);
   MSE_API("MediaSource(%p)::AddSourceBuffer(aType=%s)%s",
           this, NS_ConvertUTF16toUTF8(aType).get(),
           rv == NS_OK ? "" : " [not supported]");
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return nullptr;
   }
@@ -210,16 +217,17 @@ MediaSource::AddSourceBuffer(const nsASt
   mActiveSourceBuffers->Append(sourceBuffer);
   MSE_DEBUG("MediaSource(%p)::AddSourceBuffer() sourceBuffer=%p", this, sourceBuffer.get());
   return sourceBuffer.forget();
 }
 
 void
 MediaSource::RemoveSourceBuffer(SourceBuffer& aSourceBuffer, ErrorResult& aRv)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   SourceBuffer* sourceBuffer = &aSourceBuffer;
   MSE_API("MediaSource(%p)::RemoveSourceBuffer(aSourceBuffer=%p)", this, sourceBuffer);
   if (!mSourceBuffers->Contains(sourceBuffer)) {
     aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
     return;
   }
   if (sourceBuffer->Updating()) {
     // TODO:
@@ -240,16 +248,17 @@ MediaSource::RemoveSourceBuffer(SourceBu
   }
   mSourceBuffers->Remove(sourceBuffer);
   // TODO: Free all resources associated with sourceBuffer
 }
 
 void
 MediaSource::EndOfStream(const Optional<MediaSourceEndOfStreamError>& aError, ErrorResult& aRv)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_API("MediaSource(%p)::EndOfStream(aError=%d)",
           this, aError.WasPassed() ? uint32_t(aError.Value()) : 0);
   if (mReadyState != MediaSourceReadyState::Open ||
       mSourceBuffers->AnyUpdating()) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
@@ -279,39 +288,42 @@ MediaSource::EndOfStream(const Optional<
   default:
     aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
   }
 }
 
 /* static */ bool
 MediaSource::IsTypeSupported(const GlobalObject&, const nsAString& aType)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   nsresult rv = mozilla::IsTypeSupported(aType);
   MSE_API("MediaSource::IsTypeSupported(aType=%s)%s",
           NS_ConvertUTF16toUTF8(aType).get(), rv == NS_OK ? "" : " [not supported]");
   return NS_SUCCEEDED(rv);
 }
 
 bool
 MediaSource::Attach(MediaSourceDecoder* aDecoder)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("MediaSource(%p)::Attach(aDecoder=%p) owner=%p", this, aDecoder, aDecoder->GetOwner());
   MOZ_ASSERT(aDecoder);
   if (mReadyState != MediaSourceReadyState::Closed) {
     return false;
   }
   mDecoder = aDecoder;
   mDecoder->AttachMediaSource(this);
   SetReadyState(MediaSourceReadyState::Open);
   return true;
 }
 
 void
 MediaSource::Detach()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("MediaSource(%p)::Detach() mDecoder=%p owner=%p",
             this, mDecoder.get(), mDecoder->GetOwner());
   MOZ_ASSERT(mDecoder);
   mDecoder->DetachMediaSource();
   mDecoder = nullptr;
   mDuration = UnspecifiedNaN<double>();
   mActiveSourceBuffers->Clear();
   mSourceBuffers->Clear();
@@ -320,25 +332,27 @@ MediaSource::Detach()
 
 MediaSource::MediaSource(nsPIDOMWindow* aWindow)
   : DOMEventTargetHelper(aWindow)
   , mDuration(UnspecifiedNaN<double>())
   , mDecoder(nullptr)
   , mReadyState(MediaSourceReadyState::Closed)
   , mWaitForDataMonitor("MediaSource.WaitForData.Monitor")
 {
+  MOZ_ASSERT(NS_IsMainThread());
   mSourceBuffers = new SourceBufferList(this);
   mActiveSourceBuffers = new SourceBufferList(this);
   MSE_API("MediaSource(%p)::MediaSource(aWindow=%p) mSourceBuffers=%p mActiveSourceBuffers=%p",
           this, aWindow, mSourceBuffers.get(), mActiveSourceBuffers.get());
 }
 
 void
 MediaSource::SetReadyState(MediaSourceReadyState aState)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aState != mReadyState);
   MSE_DEBUG("MediaSource(%p)::SetReadyState(aState=%d) mReadyState=%d", this, aState, mReadyState);
 
   MediaSourceReadyState oldState = mReadyState;
   mReadyState = aState;
 
   if (mReadyState == MediaSourceReadyState::Open &&
       (oldState == MediaSourceReadyState::Closed ||
@@ -361,31 +375,33 @@ MediaSource::SetReadyState(MediaSourceRe
   }
 
   NS_WARNING("Invalid MediaSource readyState transition");
 }
 
 void
 MediaSource::DispatchSimpleEvent(const char* aName)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_API("MediaSource(%p) Dispatch event '%s'", this, aName);
   DispatchTrustedEvent(NS_ConvertUTF8toUTF16(aName));
 }
 
 void
 MediaSource::QueueAsyncSimpleEvent(const char* aName)
 {
   MSE_DEBUG("MediaSource(%p) Queuing event '%s'", this, aName);
   nsCOMPtr<nsIRunnable> event = new AsyncEventRunner<MediaSource>(this, aName);
   NS_DispatchToMainThread(event);
 }
 
 void
 MediaSource::DurationChange(double aNewDuration, ErrorResult& aRv)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("MediaSource(%p)::DurationChange(aNewDuration=%f)", this, aNewDuration);
   if (mDuration == aNewDuration) {
     return;
   }
   double oldDuration = mDuration;
   mDuration = aNewDuration;
   if (aNewDuration < oldDuration) {
     mSourceBuffers->Remove(aNewDuration, oldDuration, aRv);
@@ -395,16 +411,17 @@ MediaSource::DurationChange(double aNewD
   }
   // TODO: If partial audio frames/text cues exist, clamp duration based on mSourceBuffers.
   // TODO: Update media element's duration and run element's duration change algorithm.
 }
 
 void
 MediaSource::NotifyEvicted(double aStart, double aEnd)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("MediaSource(%p)::NotifyEvicted(aStart=%f, aEnd=%f)", this, aStart, aEnd);
   // Cycle through all SourceBuffers and tell them to evict data in
   // the given range.
   mSourceBuffers->Evict(aStart, aEnd);
 }
 
 void
 MediaSource::WaitForData()
--- a/content/media/mediasource/SourceBuffer.cpp
+++ b/content/media/mediasource/SourceBuffer.cpp
@@ -209,16 +209,17 @@ ContainerParser::CreateForMIMEType(const
   return new ContainerParser();
 }
 
 namespace dom {
 
 void
 SourceBuffer::SetMode(SourceBufferAppendMode aMode, ErrorResult& aRv)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_API("SourceBuffer(%p)::SetMode(aMode=%d)", this, aMode);
   if (!IsAttached() || mUpdating) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
   MOZ_ASSERT(mMediaSource->ReadyState() != MediaSourceReadyState::Closed);
   if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
     mMediaSource->SetReadyState(MediaSourceReadyState::Open);
@@ -226,16 +227,17 @@ SourceBuffer::SetMode(SourceBufferAppend
   // TODO: Test append state.
   // TODO: If aMode is "sequence", set sequence start time.
   mAppendMode = aMode;
 }
 
 void
 SourceBuffer::SetTimestampOffset(double aTimestampOffset, ErrorResult& aRv)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_API("SourceBuffer(%p)::SetTimestampOffset(aTimestampOffset=%d)", this, aTimestampOffset);
   if (!IsAttached() || mUpdating) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
   MOZ_ASSERT(mMediaSource->ReadyState() != MediaSourceReadyState::Closed);
   if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
     mMediaSource->SetReadyState(MediaSourceReadyState::Open);
@@ -243,16 +245,17 @@ SourceBuffer::SetTimestampOffset(double 
   // TODO: Test append state.
   // TODO: If aMode is "sequence", set sequence start time.
   mTimestampOffset = aTimestampOffset;
 }
 
 already_AddRefed<TimeRanges>
 SourceBuffer::GetBuffered(ErrorResult& aRv)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   if (!IsAttached()) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return nullptr;
   }
   nsRefPtr<TimeRanges> ranges = new TimeRanges();
   if (mDecoder) {
     mDecoder->GetBuffered(ranges);
   }
@@ -260,63 +263,68 @@ SourceBuffer::GetBuffered(ErrorResult& a
   MSE_DEBUG("SourceBuffer(%p)::GetBuffered startTime=%f endTime=%f",
             this, ranges->GetStartTime(), ranges->GetEndTime());
   return ranges.forget();
 }
 
 void
 SourceBuffer::SetAppendWindowStart(double aAppendWindowStart, ErrorResult& aRv)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_API("SourceBuffer(%p)::SetAppendWindowStart(aAppendWindowStart=%d)", this, aAppendWindowStart);
   if (!IsAttached() || mUpdating) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
   if (aAppendWindowStart < 0 || aAppendWindowStart >= mAppendWindowEnd) {
     aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return;
   }
   mAppendWindowStart = aAppendWindowStart;
 }
 
 void
 SourceBuffer::SetAppendWindowEnd(double aAppendWindowEnd, ErrorResult& aRv)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_API("SourceBuffer(%p)::SetAppendWindowEnd(aAppendWindowEnd=%d)", this, aAppendWindowEnd);
   if (!IsAttached() || mUpdating) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
   if (IsNaN(aAppendWindowEnd) ||
       aAppendWindowEnd <= mAppendWindowStart) {
     aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return;
   }
   mAppendWindowEnd = aAppendWindowEnd;
 }
 
 void
 SourceBuffer::AppendBuffer(const ArrayBuffer& aData, ErrorResult& aRv)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_API("SourceBuffer(%p)::AppendBuffer(ArrayBuffer)", this);
   aData.ComputeLengthAndData();
   AppendData(aData.Data(), aData.Length(), aRv);
 }
 
 void
 SourceBuffer::AppendBuffer(const ArrayBufferView& aData, ErrorResult& aRv)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_API("SourceBuffer(%p)::AppendBuffer(ArrayBufferView)", this);
   aData.ComputeLengthAndData();
   AppendData(aData.Data(), aData.Length(), aRv);
 }
 
 void
 SourceBuffer::Abort(ErrorResult& aRv)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_API("SourceBuffer(%p)::Abort()", this);
   if (!IsAttached()) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
   if (mMediaSource->ReadyState() != MediaSourceReadyState::Open) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
@@ -331,16 +339,17 @@ SourceBuffer::Abort(ErrorResult& aRv)
 
   MSE_DEBUG("SourceBuffer(%p)::Abort() Discarding decoder", this);
   DiscardDecoder();
 }
 
 void
 SourceBuffer::Remove(double aStart, double aEnd, ErrorResult& aRv)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_API("SourceBuffer(%p)::Remove(aStart=%f, aEnd=%f)", this, aStart, aEnd);
   if (!IsAttached() || mUpdating ||
       mMediaSource->ReadyState() != MediaSourceReadyState::Open) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
   if (aStart < 0 || aStart > mMediaSource->Duration() ||
       aEnd <= aStart) {
@@ -350,25 +359,27 @@ SourceBuffer::Remove(double aStart, doub
   StartUpdating();
   /// TODO: Run coded frame removal algorithm asynchronously (would call StopUpdating()).
   StopUpdating();
 }
 
 void
 SourceBuffer::Detach()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("SourceBuffer(%p)::Detach", this);
   Ended();
   DiscardDecoder();
   mMediaSource = nullptr;
 }
 
 void
 SourceBuffer::Ended()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("SourceBuffer(%p)::Ended", this);
   if (mDecoder) {
     mDecoder->GetResource()->Ended();
   }
 }
 
 SourceBuffer::SourceBuffer(MediaSource* aMediaSource, const nsACString& aType)
   : DOMEventTargetHelper(aMediaSource->GetParentObject())
@@ -376,31 +387,33 @@ SourceBuffer::SourceBuffer(MediaSource* 
   , mType(aType)
   , mAppendWindowStart(0)
   , mAppendWindowEnd(PositiveInfinity<double>())
   , mTimestampOffset(0)
   , mAppendMode(SourceBufferAppendMode::Segments)
   , mUpdating(false)
   , mDecoderInitialized(false)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aMediaSource);
   mParser = ContainerParser::CreateForMIMEType(aType);
   MSE_DEBUG("SourceBuffer(%p)::SourceBuffer: Creating initial decoder.", this);
   InitNewDecoder();
 }
 
 already_AddRefed<SourceBuffer>
 SourceBuffer::Create(MediaSource* aMediaSource, const nsACString& aType)
 {
   nsRefPtr<SourceBuffer> sourceBuffer = new SourceBuffer(aMediaSource, aType);
   return sourceBuffer.forget();
 }
 
 SourceBuffer::~SourceBuffer()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("SourceBuffer(%p)::~SourceBuffer", this);
   DiscardDecoder();
 }
 
 MediaSource*
 SourceBuffer::GetParentObject() const
 {
   return mMediaSource;
@@ -410,74 +423,80 @@ JSObject*
 SourceBuffer::WrapObject(JSContext* aCx)
 {
   return SourceBufferBinding::Wrap(aCx, this);
 }
 
 void
 SourceBuffer::DispatchSimpleEvent(const char* aName)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_API("SourceBuffer(%p) Dispatch event '%s'", this, aName);
   DispatchTrustedEvent(NS_ConvertUTF8toUTF16(aName));
 }
 
 void
 SourceBuffer::QueueAsyncSimpleEvent(const char* aName)
 {
   MSE_DEBUG("SourceBuffer(%p) Queuing event '%s'", this, aName);
   nsCOMPtr<nsIRunnable> event = new AsyncEventRunner<SourceBuffer>(this, aName);
   NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
 }
 
 bool
 SourceBuffer::InitNewDecoder()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("SourceBuffer(%p)::InitNewDecoder", this);
   MOZ_ASSERT(!mDecoder);
   MediaSourceDecoder* parentDecoder = mMediaSource->GetDecoder();
   nsRefPtr<SubBufferDecoder> decoder = parentDecoder->CreateSubDecoder(mType);
   if (!decoder) {
     return false;
   }
   mDecoder = decoder;
   mDecoderInitialized = false;
   return true;
 }
 
 void
 SourceBuffer::DiscardDecoder()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("SourceBuffer(%p)::DiscardDecoder mDecoder=%p", this, mDecoder.get());
   if (mDecoder) {
     mDecoder->SetDiscarded();
   }
   mDecoder = nullptr;
   mDecoderInitialized = false;
 }
 
 void
 SourceBuffer::StartUpdating()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mUpdating);
   mUpdating = true;
   QueueAsyncSimpleEvent("updatestart");
 }
 
 void
 SourceBuffer::StopUpdating()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mUpdating);
   mUpdating = false;
   QueueAsyncSimpleEvent("update");
   QueueAsyncSimpleEvent("updateend");
 }
 
 void
 SourceBuffer::AbortUpdating()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mUpdating);
   mUpdating = false;
   QueueAsyncSimpleEvent("abort");
   QueueAsyncSimpleEvent("updateend");
 }
 
 void
 SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
@@ -549,44 +568,47 @@ SourceBuffer::AppendData(const uint8_t* 
   mMediaSource->GetDecoder()->ScheduleStateMachineThread();
 
   mMediaSource->NotifyGotData();
 }
 
 void
 SourceBuffer::GetBufferedStartEndTime(double* aStart, double* aEnd)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   ErrorResult dummy;
   nsRefPtr<TimeRanges> ranges = GetBuffered(dummy);
   if (!ranges || ranges->Length() == 0) {
     *aStart = *aEnd = 0.0;
     return;
   }
   *aStart = ranges->Start(0, dummy);
   *aEnd = ranges->End(ranges->Length() - 1, dummy);
 }
 
 void
 SourceBuffer::Evict(double aStart, double aEnd)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("SourceBuffer(%p)::Evict(aStart=%f, aEnd=%f)", this, aStart, aEnd);
   if (!mDecoder) {
     return;
   }
   // Need to map time to byte offset then evict
   int64_t end = mDecoder->ConvertToByteOffset(aEnd);
   if (end > 0) {
     mDecoder->GetResource()->EvictBefore(end);
   }
   MSE_DEBUG("SourceBuffer(%p)::Evict offset=%lld", this, end);
 }
 
 bool
 SourceBuffer::ContainsTime(double aTime)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   ErrorResult dummy;
   nsRefPtr<TimeRanges> ranges = GetBuffered(dummy);
   if (!ranges || ranges->Length() == 0) {
     return false;
   }
   for (uint32_t i = 0; i < ranges->Length(); ++i) {
     if (aTime >= ranges->Start(i, dummy) &&
         aTime <= ranges->End(i, dummy)) {
--- a/content/media/mediasource/SourceBufferList.cpp
+++ b/content/media/mediasource/SourceBufferList.cpp
@@ -37,117 +37,130 @@ namespace dom {
 
 SourceBufferList::~SourceBufferList()
 {
 }
 
 SourceBuffer*
 SourceBufferList::IndexedGetter(uint32_t aIndex, bool& aFound)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   aFound = aIndex < mSourceBuffers.Length();
   return aFound ? mSourceBuffers[aIndex] : nullptr;
 }
 
 uint32_t
 SourceBufferList::Length()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   return mSourceBuffers.Length();
 }
 
 void
 SourceBufferList::Append(SourceBuffer* aSourceBuffer)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   mSourceBuffers.AppendElement(aSourceBuffer);
   QueueAsyncSimpleEvent("addsourcebuffer");
 }
 
 void
 SourceBufferList::Remove(SourceBuffer* aSourceBuffer)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ALWAYS_TRUE(mSourceBuffers.RemoveElement(aSourceBuffer));
   aSourceBuffer->Detach();
   QueueAsyncSimpleEvent("removesourcebuffer");
 }
 
 bool
 SourceBufferList::Contains(SourceBuffer* aSourceBuffer)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   return mSourceBuffers.Contains(aSourceBuffer);
 }
 
 void
 SourceBufferList::Clear()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
     mSourceBuffers[i]->Detach();
   }
   mSourceBuffers.Clear();
   QueueAsyncSimpleEvent("removesourcebuffer");
 }
 
 bool
 SourceBufferList::IsEmpty()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   return mSourceBuffers.IsEmpty();
 }
 
 bool
 SourceBufferList::AnyUpdating()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
     if (mSourceBuffers[i]->Updating()) {
       return true;
     }
   }
   return false;
 }
 
 void
 SourceBufferList::Remove(double aStart, double aEnd, ErrorResult& aRv)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("SourceBufferList(%p)::Remove(aStart=%f, aEnd=%f", this, aStart, aEnd);
   for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
     mSourceBuffers[i]->Remove(aStart, aEnd, aRv);
     if (aRv.Failed()) {
       return;
     }
   }
 }
 
 void
 SourceBufferList::Evict(double aStart, double aEnd)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("SourceBufferList(%p)::Evict(aStart=%f, aEnd=%f)", this, aStart, aEnd);
   for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
     mSourceBuffers[i]->Evict(aStart, aEnd);
   }
 }
 
 bool
 SourceBufferList::AllContainsTime(double aTime)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
     if (!mSourceBuffers[i]->ContainsTime(aTime)) {
       return false;
     }
   }
   return mSourceBuffers.Length() > 0;
 }
 
 void
 SourceBufferList::Ended()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
     mSourceBuffers[i]->Ended();
   }
 }
 
 void
 SourceBufferList::DispatchSimpleEvent(const char* aName)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MSE_API("SourceBufferList(%p) Dispatch event '%s'", this, aName);
   DispatchTrustedEvent(NS_ConvertUTF8toUTF16(aName));
 }
 
 void
 SourceBufferList::QueueAsyncSimpleEvent(const char* aName)
 {
   MSE_DEBUG("SourceBufferList(%p) Queuing event '%s'", this, aName);