Bug 1336356 - Ensure MediaDecode::Shutdown() is called by MediaShutdownManager::BlockShutdown(). draft
authorJW Wang <jwwang@mozilla.com>
Fri, 03 Feb 2017 17:12:38 +0800
changeset 479661 435c01fa93ecb60e1ca794d44cd1d96bce4493f4
parent 479213 d7b04a0b30acaf48d99104036363e3d9c6c02710
child 544745 7858d53f8e82975c9afab02789f15a034b0ccf7f
push id44320
push userjwwang@mozilla.com
push dateTue, 07 Feb 2017 02:50:16 +0000
bugs1336356
milestone54.0a1
Bug 1336356 - Ensure MediaDecode::Shutdown() is called by MediaShutdownManager::BlockShutdown(). MozReview-Commit-ID: 80AFMafXoeB
dom/media/MediaDecoder.cpp
dom/media/MediaDecoder.h
dom/media/MediaDecoderOwner.h
dom/media/MediaShutdownManager.cpp
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -514,16 +514,32 @@ MediaDecoder::Shutdown()
   if (mResource) {
     mResource->Close();
   }
 
   ChangeState(PLAY_STATE_SHUTDOWN);
   mOwner = nullptr;
 }
 
+void
+MediaDecoder::NotifyXPCOMShutdown()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  if (auto owner = GetOwner()) {
+    owner->NotifyXPCOMShutdown();
+  }
+  MOZ_DIAGNOSTIC_ASSERT(IsShutdown());
+
+  // Don't cause grief to release builds by ensuring Shutdown()
+  // is always called during shutdown phase.
+  if (!IsShutdown()) {
+    Shutdown();
+  }
+}
+
 MediaDecoder::~MediaDecoder()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_DIAGNOSTIC_ASSERT(IsShutdown());
   mResourceCallback->Disconnect();
   MediaMemoryTracker::RemoveMediaDecoder(this);
   UnpinForSeek();
 }
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -125,16 +125,21 @@ public:
   // Create a new state machine to run this decoder.
   // Subclasses must implement this.
   virtual MediaDecoderStateMachine* CreateStateMachine() = 0;
 
   // Cleanup internal data structures. Must be called on the main
   // thread by the owning object before that object disposes of this object.
   virtual void Shutdown();
 
+  // Notified by the shutdown manager that XPCOM shutdown has begun.
+  // The decoder should notify its owner to drop the reference to the decoder
+  // to prevent further calls into the decoder.
+  void NotifyXPCOMShutdown();
+
   // Start downloading the media. Decode the downloaded data up to the
   // point of the first frame of data.
   // This is called at most once per decoder, after Init().
   virtual nsresult Load(nsIStreamListener** aListener);
 
   // Called in |Load| to open mResource.
   nsresult OpenResource(nsIStreamListener** aStreamListener);
 
--- a/dom/media/MediaDecoderOwner.h
+++ b/dom/media/MediaDecoderOwner.h
@@ -137,17 +137,17 @@ public:
 
   // Called by the media decoder and the video frame to get the
   // ImageContainer containing the video data.
   virtual VideoFrameContainer* GetVideoFrameContainer() = 0;
 
   // Called by media decoder when the audible state changed
   virtual void SetAudibleState(bool aAudible) = 0;
 
-  // Notified by the shutdown manager that XPCOM shutdown has begun.
+  // Notified by the decoder that XPCOM shutdown has begun.
   // The decoder owner should call Shutdown() on the decoder and drop the
   // reference to the decoder to prevent further calls into the decoder.
   virtual void NotifyXPCOMShutdown() = 0;
 
   // Dispatches a "encrypted" event to the HTMLMediaElement, with the
   // provided init data. Actual dispatch may be delayed until HAVE_METADATA.
   // Main thread only.
   virtual void DispatchEncrypted(const nsTArray<uint8_t>& aInitData,
--- a/dom/media/MediaShutdownManager.cpp
+++ b/dom/media/MediaShutdownManager.cpp
@@ -149,22 +149,17 @@ MediaShutdownManager::BlockShutdown(nsIA
   auto oldCount = mDecoders.Count();
   if (oldCount == 0) {
     RemoveBlocker();
     return NS_OK;
   }
 
   // Iterate over the decoders and shut them down.
   for (auto iter = mDecoders.Iter(); !iter.Done(); iter.Next()) {
-    MediaDecoderOwner* owner = iter.Get()->GetKey()->GetOwner();
-    if (owner) {
-      // The owner will call MediaDecoder::Shutdown() and
-      // drop its reference to the decoder.
-      owner->NotifyXPCOMShutdown();
-    }
+    iter.Get()->GetKey()->NotifyXPCOMShutdown();
     // Check MediaDecoder::Shutdown doesn't call Unregister() synchronously in
     // order not to corrupt our hashtable traversal.
     MOZ_ASSERT(mDecoders.Count() == oldCount);
   }
 
   return NS_OK;
 }