Bug 1434804 - Pause autoplayed media if they become audible. r?kamidphish draft
authorChris Pearce <cpearce@mozilla.com>
Mon, 12 Mar 2018 13:05:04 +1300
changeset 766378 6873d13f40f4c6b5fe81fb006d8b1bb3f1f8e77e
parent 764561 35c9f6fd0ea2a3131779442b5a3335b50683d08a
child 766379 c9739aa902db3556d185022abf7ee24874aae7d2
push id102308
push userbmo:cpearce@mozilla.com
push dateMon, 12 Mar 2018 20:11:44 +0000
reviewerskamidphish
bugs1434804
milestone60.0a1
Bug 1434804 - Pause autoplayed media if they become audible. r?kamidphish Our autoplay blocking is trivial to defeat; just mute or volume=0 a video, play(), and then unmute, and then you're playing audibly. So this patch makes us pause() media that become audible atfter playback has started. MozReview-Commit-ID: 2RAtbohMGJO
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -2965,16 +2965,20 @@ HTMLMediaElement::SetVolume(double aVolu
     return;
 
   mVolume = aVolume;
 
   // Here we want just to update the volume.
   SetVolumeInternal();
 
   DispatchAsyncEvent(NS_LITERAL_STRING("volumechange"));
+
+  // We allow inaudible autoplay. But changing our volume may make this
+  // media audible. So pause if we are no longer supposed to be autoplaying.
+  PauseIfShouldNotBePlaying();
 }
 
 void
 HTMLMediaElement::MozGetMetadata(JSContext* cx,
                                  JS::MutableHandle<JSObject*> aRetval,
                                  ErrorResult& aRv)
 {
   if (mReadyState < HAVE_METADATA) {
@@ -3014,16 +3018,28 @@ HTMLMediaElement::SetMutedInternal(uint3
   if (!!aMuted == !!oldMuted) {
     return;
   }
 
   SetVolumeInternal();
 }
 
 void
+HTMLMediaElement::PauseIfShouldNotBePlaying()
+{
+  if (GetPaused()) {
+    return;
+  }
+  if (!AutoplayPolicy::IsMediaElementAllowedToPlay(WrapNotNull(this))) {
+    ErrorResult rv;
+    Pause(rv);
+  }
+}
+
+void
 HTMLMediaElement::SetVolumeInternal()
 {
   float effectiveVolume = ComputedVolume();
 
   if (mDecoder) {
     mDecoder->SetVolume(effectiveVolume);
   } else if (MediaStream* stream = GetSrcMediaStream()) {
     if (mSrcStreamIsPlaying) {
@@ -3045,16 +3061,20 @@ HTMLMediaElement::SetMuted(bool aMuted)
 
   if (aMuted) {
     SetMutedInternal(mMuted | MUTED_BY_CONTENT);
   } else {
     SetMutedInternal(mMuted & ~MUTED_BY_CONTENT);
   }
 
   DispatchAsyncEvent(NS_LITERAL_STRING("volumechange"));
+
+  // We allow inaudible autoplay. But changing our mute status may make this
+  // media audible. So pause if we are no longer supposed to be autoplaying.
+  PauseIfShouldNotBePlaying();
 }
 
 class HTMLMediaElement::StreamCaptureTrackSource :
   public MediaStreamTrackSource,
   public MediaStreamTrackSource::Sink
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -1363,16 +1363,18 @@ protected:
   bool TryRemoveMediaKeysAssociation();
   void RemoveMediaKeys();
   bool AttachNewMediaKeys();
   bool TryMakeAssociationWithCDM(CDMProxy* aProxy);
   void MakeAssociationWithCDMResolved();
   void SetCDMProxyFailure(const MediaResult& aResult);
   void ResetSetMediaKeysTempVariables();
 
+  void PauseIfShouldNotBePlaying();
+
   // The current decoder. Load() has been called on this decoder.
   // At most one of mDecoder and mSrcStream can be non-null.
   RefPtr<MediaDecoder> mDecoder;
 
   // The DocGroup-specific nsISerialEventTarget of this HTML element on the main
   // thread.
   nsCOMPtr<nsISerialEventTarget> mMainThreadEventTarget;