Bug 1371719 - Don't create a MediaStreamGraph without doing anything with it. r?jesup draft
authorPaul Adenot <paul@paul.cx>
Wed, 07 Jun 2017 18:05:50 +0200
changeset 591828 739cba01677453df08433cb7f648fe6b09db9d23
parent 589544 4dd1d17ba22660b8f5869a707f2e4e9f9dd5be5b
child 632636 1ce8194b6ba7eb0334133f8dce32692dafbb3d41
push id63187
push userpaul@paul.cx
push dateFri, 09 Jun 2017 16:26:25 +0000
reviewersjesup
bugs1371719
milestone55.0a1
Bug 1371719 - Don't create a MediaStreamGraph without doing anything with it. r?jesup The MediaStreamGraph relies on having at least one message sent to its message queue on creation, or it will just sit there and do nothing, and block shutdown because its not running its rendering loop, so it's not progressing in the MediaStreamGraph life cycle state machine. This patch makes sure the `captureStream` will succeed before creating an MSG. MozReview-Commit-ID: CN1arWydmxC
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -3345,41 +3345,52 @@ HTMLMediaElement::AddCaptureMediaTrackTo
   }
 
   LOG(LogLevel::Debug,
       ("Created %s track %p with id %d from track %p through MediaInputPort %p",
        inputTrack->AsAudioStreamTrack() ? "audio" : "video",
        track.get(), destinationTrackID, inputTrack, port.get()));
 }
 
+bool
+HTMLMediaElement::CanBeCaptured(bool aCaptureAudio)
+{
+  // Don't bother capturing when the document has gone away
+  nsPIDOMWindowInner* window = OwnerDoc()->GetInnerWindow();
+  if (!window) {
+    return false;
+  }
+
+  // Prevent capturing restricted video
+  if (!aCaptureAudio && ContainsRestrictedContent()) {
+    return false;
+  }
+  return true;
+}
+
 already_AddRefed<DOMMediaStream>
 HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded,
                                         bool aCaptureAudio,
                                         MediaStreamGraph* aGraph)
 {
   MOZ_RELEASE_ASSERT(aGraph);
+  MOZ_ASSERT(CanBeCaptured(aCaptureAudio));
 
   MarkAsContentSource(CallerAPI::CAPTURE_STREAM);
   MarkAsTainted();
 
-  nsPIDOMWindowInner* window = OwnerDoc()->GetInnerWindow();
-  if (!window) {
-    return nullptr;
-  }
-  if (!aCaptureAudio && ContainsRestrictedContent()) {
-    return nullptr;
-  }
-
+  // We don't support routing to a different graph.
   if (!mOutputStreams.IsEmpty() &&
       aGraph != mOutputStreams[0].mStream->GetInputStream()->Graph()) {
     return nullptr;
   }
 
   OutputMediaStream* out = mOutputStreams.AppendElement();
   MediaStreamTrackSourceGetter* getter = new CaptureStreamTrackSourceGetter(this);
+  nsPIDOMWindowInner* window = OwnerDoc()->GetInnerWindow();
   out->mStream = DOMMediaStream::CreateTrackUnionStreamAsInput(window, aGraph, getter);
   out->mStream->SetInactiveOnFinish();
   out->mFinishWhenEnded = aFinishWhenEnded;
   out->mCapturingAudioOnly = aCaptureAudio;
 
   if (aCaptureAudio) {
     if (mSrcStream) {
       // We don't support applying volume and mute to the captured stream, when
@@ -3476,16 +3487,23 @@ HTMLMediaElement::CaptureAudio(ErrorResu
 }
 
 already_AddRefed<DOMMediaStream>
 HTMLMediaElement::MozCaptureStream(ErrorResult& aRv)
 {
   MediaStreamGraph::GraphDriverType graphDriverType =
     HasAudio() ? MediaStreamGraph::AUDIO_THREAD_DRIVER
                : MediaStreamGraph::SYSTEM_THREAD_DRIVER;
+
+
+  nsPIDOMWindowInner* window = OwnerDoc()->GetInnerWindow();
+  if (!window) {
+    return nullptr;
+  }
+
   MediaStreamGraph* graph =
     MediaStreamGraph::GetInstance(graphDriverType, mAudioChannel);
 
   RefPtr<DOMMediaStream> stream =
     CaptureStreamInternal(false, false, graph);
   if (!stream) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
@@ -3495,16 +3513,22 @@ HTMLMediaElement::MozCaptureStream(Error
 }
 
 already_AddRefed<DOMMediaStream>
 HTMLMediaElement::MozCaptureStreamUntilEnded(ErrorResult& aRv)
 {
   MediaStreamGraph::GraphDriverType graphDriverType =
     HasAudio() ? MediaStreamGraph::AUDIO_THREAD_DRIVER
                : MediaStreamGraph::SYSTEM_THREAD_DRIVER;
+
+  nsPIDOMWindowInner* window = OwnerDoc()->GetInnerWindow();
+  if (!window) {
+    return nullptr;
+  }
+
   MediaStreamGraph* graph =
     MediaStreamGraph::GetInstance(graphDriverType, mAudioChannel);
 
   RefPtr<DOMMediaStream> stream =
     CaptureStreamInternal(true, false, graph);
   if (!stream) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -1274,16 +1274,19 @@ protected:
   bool IsAllowedToPlay();
 
   // If the network state is empty and then we would trigger DoLoad().
   void MaybeDoLoad();
 
   // Anything we need to check after played success and not related with spec.
   void UpdateCustomPolicyAfterPlayed();
 
+  // True if this element can be captured, false otherwise.
+  bool CanBeCaptured(bool aCaptureAudio);
+
   class nsAsyncEventRunner;
   class nsNotifyAboutPlayingRunner;
   class nsResolveOrRejectPendingPlayPromisesRunner;
   using nsGenericHTMLElement::DispatchEvent;
   // For nsAsyncEventRunner.
   nsresult DispatchEvent(const nsAString& aName);
 
   // Open unsupported types media with the external app when the media element