Bug 1289649 - HTMLMediaElement should clear mDecoder when XPCOM shutdown begins. r=gerald
authorJW Wang <jwwang@mozilla.com>
Wed, 27 Jul 2016 10:26:21 +0800
changeset 347474 fa550705a937975a81c816d0d846a8ebfcaa0bcb
parent 347473 cf46248f894fb1e6785f8e8e8d9c3d67bd6612c8
child 347475 9966bbe6b5349f00563cddfe52c3aead1c44a116
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgerald
bugs1289649
milestone50.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 1289649 - HTMLMediaElement should clear mDecoder when XPCOM shutdown begins. r=gerald MozReview-Commit-ID: A3ECReCgiD7
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
dom/media/AbstractMediaDecoder.h
dom/media/MediaDecoderOwner.h
dom/media/MediaShutdownManager.cpp
dom/media/gtest/MockMediaDecoderOwner.h
dom/media/gtest/TestMediaFormatReader.cpp
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -2601,16 +2601,22 @@ void HTMLMediaElement::SetPlayedOrSeeked
     return;
   }
   frame->PresContext()->PresShell()->FrameNeedsReflow(frame,
                                                       nsIPresShell::eTreeChange,
                                                       NS_FRAME_IS_DIRTY);
 }
 
 void
+HTMLMediaElement::NotifyXPCOMShutdown()
+{
+  ShutdownDecoder();
+}
+
+void
 HTMLMediaElement::ResetConnectionState()
 {
   SetCurrentTime(0);
   FireTimeUpdate(false);
   DispatchAsyncEvent(NS_LITERAL_STRING("ended"));
   ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_EMPTY);
   ChangeDelayLoadStatus(false);
   ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_NOTHING);
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -438,16 +438,18 @@ public:
   {
     return mNetworkState;
   }
 
   // Called by the media decoder object, on the main thread,
   // when the connection between Rtsp server and client gets lost.
   virtual void ResetConnectionState() final override;
 
+  void NotifyXPCOMShutdown() final override;
+
   // Called by media decoder when the audible state changed or when input is
   // a media stream.
   virtual void SetAudibleState(bool aAudible) final override;
 
   // Notify agent when the MediaElement changes its audible state.
   void NotifyAudioPlaybackChanged(AudibleChangedReasons aReason);
 
   // XPCOM GetPreload() is OK
--- a/dom/media/AbstractMediaDecoder.h
+++ b/dom/media/AbstractMediaDecoder.h
@@ -79,18 +79,18 @@ public:
     NS_DispatchToMainThread(NewRunnableMethod<int64_t>(this,
                                                        &AbstractMediaDecoder::UpdateEstimatedMediaDuration,
                                                        aDuration));
   }
 
   virtual VideoFrameContainer* GetVideoFrameContainer() = 0;
   virtual mozilla::layers::ImageContainer* GetImageContainer() = 0;
 
-  // Returns the owner of this media decoder. The owner should only be used
-  // on the main thread.
+  // Returns the owner of this decoder or null when the decoder is shutting
+  // down. The owner should only be used on the main thread.
   virtual MediaDecoderOwner* GetOwner() = 0;
 
   // Set by Reader if the current audio track can be offloaded
   virtual void SetPlatformCanOffloadAudio(bool aCanOffloadAudio) {}
 
   virtual already_AddRefed<GMPCrashHelper> GetCrashHelper() { return nullptr; }
 
   // Stack based class to assist in notifying the frame statistics of
--- a/dom/media/MediaDecoderOwner.h
+++ b/dom/media/MediaDecoderOwner.h
@@ -138,16 +138,21 @@ public:
   // when the connection between Rtsp server and client gets lost.
   // 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 ResetConnectionState() = 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.
+  // 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;
+
 #ifdef MOZ_EME
   // 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,
                                  const nsAString& aInitDataType) = 0;
 #endif // MOZ_EME
 };
--- a/dom/media/MediaShutdownManager.cpp
+++ b/dom/media/MediaShutdownManager.cpp
@@ -132,17 +132,22 @@ MediaShutdownManager::BlockShutdown(nsIA
   // Set this flag to ensure no Register() is allowed when Shutdown() begins.
   mIsDoingXPCOMShutDown = true;
 
   DebugOnly<uint32_t> oldCount = mDecoders.Count();
   MOZ_ASSERT(oldCount > 0);
 
   // Iterate over the decoders and shut them down.
   for (auto iter = mDecoders.Iter(); !iter.Done(); iter.Next()) {
-    iter.Get()->GetKey()->Shutdown();
+    MediaDecoderOwner* owner = iter.Get()->GetKey()->GetOwner();
+    if (owner) {
+      // The owner will call MediaDecoder::Shutdown() and
+      // drop its reference to the decoder.
+      owner->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;
 }
 
--- a/dom/media/gtest/MockMediaDecoderOwner.h
+++ b/dom/media/gtest/MockMediaDecoderOwner.h
@@ -45,12 +45,13 @@ public:
   void NotifySuspendedByCache(bool aIsSuspended) override {}
   void NotifyDecoderPrincipalChanged() override {}
   VideoFrameContainer* GetVideoFrameContainer() override
   {
     return nullptr;
   }
   void ResetConnectionState() override {}
   void SetAudibleState(bool aAudible) override {}
+  void NotifyXPCOMShutdown() override {}
 };
 }
 
 #endif
--- a/dom/media/gtest/TestMediaFormatReader.cpp
+++ b/dom/media/gtest/TestMediaFormatReader.cpp
@@ -129,17 +129,19 @@ public:
   void RunTestAndWait(Function&& aFunction)
   {
     RefPtr<Runnable> r = NS_NewRunnableFunction(Forward<Function>(aFunction));
     mTaskQueue->Dispatch(r.forget());
     mTaskQueue->AwaitShutdownAndIdle();
   }
 private:
   ~MediaFormatReaderBinding()
-  {}
+  {
+    mDecoder->Shutdown();
+  }
 };
 
 
 template <typename T>
 T GetPref(const char* aPrefKey);
 
 template <>
 bool GetPref<bool>(const char* aPrefKey)