Bug 1412204 - add a member to ChannelMediaResource to indicate Close() has been called. draft
authorJW Wang <jwwang@mozilla.com>
Fri, 27 Oct 2017 13:46:44 +0800
changeset 689189 b8329baf505f4531f7ba881b4f94191b12e3032f
parent 689188 5363517811b913b034368f395dd02d2bf09f0867
child 738265 623a11b04aaaba54b55186e7b6a3f931fa231b36
push id86962
push userjwwang@mozilla.com
push dateTue, 31 Oct 2017 08:14:33 +0000
bugs1412204
milestone58.0a1
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
dom/media/ChannelMediaResource.cpp
dom/media/ChannelMediaResource.h
--- 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