Bug 1412204 - add a member to ChannelMediaResource to indicate Close() has been called.
So we can check this member without calling mCacheStream.IsClosed() which need
to acquire the lock and might block the main thread.
MozReview-Commit-ID: 4SPooaprrOw
--- a/dom/media/ChannelMediaResource.cpp
+++ b/dom/media/ChannelMediaResource.cpp
@@ -45,16 +45,17 @@ ChannelMediaResource::ChannelMediaResour
, mCacheStream(this, /* aIsPrivateBrowsing = */ false)
, mChannelStatistics(aStatistics)
, mSuspendAgent(mChannel)
{
}
ChannelMediaResource::~ChannelMediaResource()
{
+ MOZ_ASSERT(mClosed);
MOZ_ASSERT(!mChannel);
MOZ_ASSERT(!mListener);
}
// ChannelMediaResource::Listener just observes the channel and
// forwards notifications to the ChannelMediaResource. We use multiple
// listener objects so that when we open a new stream for a seek we can
// disconnect the old listener from the ChannelMediaResource and hook up
@@ -156,17 +157,17 @@ IsPayloadCompressed(nsIHttpChannel* aCha
return encoding.Length() > 0;
}
nsresult
ChannelMediaResource::OnStartRequest(nsIRequest* aRequest,
int64_t aRequestOffset)
{
NS_ASSERTION(mChannel.get() == aRequest, "Wrong channel!");
- MOZ_DIAGNOSTIC_ASSERT(!mCacheStream.IsClosed());
+ MOZ_DIAGNOSTIC_ASSERT(!mClosed);
MediaDecoderOwner* owner = mCallback->GetMediaOwner();
NS_ENSURE_TRUE(owner, NS_ERROR_FAILURE);
dom::HTMLMediaElement* element = owner->GetMediaElement();
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
nsresult status;
nsresult rv = aRequest->GetStatus(&status);
NS_ENSURE_SUCCESS(rv, rv);
@@ -367,17 +368,17 @@ ChannelMediaResource::ParseContentRangeH
}
nsresult
ChannelMediaResource::OnStopRequest(nsIRequest* aRequest, nsresult aStatus)
{
NS_ASSERTION(mChannel.get() == aRequest, "Wrong channel!");
NS_ASSERTION(!mSuspendAgent.IsSuspended(),
"How can OnStopRequest fire while we're suspended?");
- MOZ_DIAGNOSTIC_ASSERT(!mCacheStream.IsClosed());
+ MOZ_DIAGNOSTIC_ASSERT(!mClosed);
mChannelStatistics.Stop();
// Note that aStatus might have succeeded --- this might be a normal close
// --- even in situations where the server cut us off because we were
// suspended. So we need to "reopen on error" in that case too. The only
// cases where we don't need to reopen are when *we* closed the stream.
// But don't reopen if we need to seek and we don't think we can... that would
@@ -500,17 +501,17 @@ ChannelMediaResource::Open(nsIStreamList
NS_ADDREF(*aStreamListener);
return NS_OK;
}
nsresult
ChannelMediaResource::OpenChannel(int64_t aOffset)
{
MOZ_ASSERT(NS_IsMainThread());
- MOZ_DIAGNOSTIC_ASSERT(!mCacheStream.IsClosed());
+ MOZ_DIAGNOSTIC_ASSERT(!mClosed);
MOZ_ASSERT(mChannel);
MOZ_ASSERT(!mListener, "Listener should have been removed by now");
mListener = new Listener(this, aOffset, ++mLoadID);
nsresult rv = mChannel->SetNotificationCallbacks(mListener.get());
NS_ENSURE_SUCCESS(rv, rv);
rv = SetupChannelHeaders(aOffset);
@@ -526,17 +527,17 @@ ChannelMediaResource::OpenChannel(int64_
element->DownloadResumed();
return NS_OK;
}
nsresult
ChannelMediaResource::SetupChannelHeaders(int64_t aOffset)
{
- MOZ_DIAGNOSTIC_ASSERT(!mCacheStream.IsClosed());
+ MOZ_DIAGNOSTIC_ASSERT(!mClosed);
// Always use a byte range request even if we're reading from the start
// of the resource.
// This enables us to detect if the stream supports byte range
// requests, and therefore seeking, early.
nsCOMPtr<nsIHttpChannel> hc = do_QueryInterface(mChannel);
if (hc) {
// Use |mOffset| if seeking in a complete file download.
@@ -559,18 +560,21 @@ ChannelMediaResource::SetupChannelHeader
}
return NS_OK;
}
nsresult ChannelMediaResource::Close()
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
- CloseChannel();
- mCacheStream.Close();
+ if (!mClosed) {
+ CloseChannel();
+ mCacheStream.Close();
+ mClosed = true;
+ }
return NS_OK;
}
already_AddRefed<nsIPrincipal>
ChannelMediaResource::GetCurrentPrincipal()
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
@@ -667,17 +671,17 @@ nsresult ChannelMediaResource::GetCached
return mCacheStream.GetCachedRanges(aRanges);
}
void
ChannelMediaResource::Suspend(bool aCloseImmediately)
{
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
- if (mCacheStream.IsClosed()) {
+ if (mClosed) {
// Nothing to do when we are closed.
return;
}
MediaDecoderOwner* owner = mCallback->GetMediaOwner();
if (!owner) {
// Shutting down; do nothing.
return;
@@ -701,17 +705,17 @@ ChannelMediaResource::Suspend(bool aClos
}
}
void
ChannelMediaResource::Resume()
{
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
- if (mCacheStream.IsClosed()) {
+ if (mClosed) {
// Nothing to do when we are closed.
return;
}
MediaDecoderOwner* owner = mCallback->GetMediaOwner();
if (!owner) {
// Shutting down; do nothing.
return;
@@ -748,17 +752,17 @@ ChannelMediaResource::Resume()
}
}
}
}
nsresult
ChannelMediaResource::RecreateChannel()
{
- MOZ_DIAGNOSTIC_ASSERT(!mCacheStream.IsClosed());
+ MOZ_DIAGNOSTIC_ASSERT(!mClosed);
nsLoadFlags loadFlags =
nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY |
nsIChannel::LOAD_CLASSIFY_URI |
(mLoadInBackground ? nsIRequest::LOAD_BACKGROUND : 0);
MediaDecoderOwner* owner = mCallback->GetMediaOwner();
if (!owner) {
@@ -874,17 +878,17 @@ ChannelMediaResource::CacheClientNotifyS
IsSuspendedByCache()));
}
nsresult
ChannelMediaResource::Seek(int64_t aOffset, bool aResume)
{
MOZ_ASSERT(NS_IsMainThread());
- if (mCacheStream.IsClosed()) {
+ if (mClosed) {
// Nothing to do when we are closed.
return NS_OK;
}
LOG("Seek requested for aOffset [%" PRId64 "]", aOffset);
CloseChannel();
--- a/dom/media/ChannelMediaResource.h
+++ b/dom/media/ChannelMediaResource.h
@@ -239,16 +239,18 @@ protected:
static nsresult CopySegmentToCache(nsIInputStream* aInStream,
void* aClosure,
const char* aFromSegment,
uint32_t aToOffset,
uint32_t aCount,
uint32_t* aWriteCount);
// Main thread access only
+ // True if Close() has been called.
+ bool mClosed = false;
RefPtr<Listener> mListener;
// A mono-increasing integer to uniquely identify the channel we are loading.
uint32_t mLoadID = 0;
// When this flag is set, if we get a network error we should silently
// reopen the stream.
bool mReopenOnError;
// Any thread access