Bug 1434804 - Pause autoplayed media if they become audible. r=kamidphish
authorChris Pearce <cpearce@mozilla.com>
Mon, 12 Mar 2018 13:05:04 +1300
changeset 407747 09d7852a968dbc0d25ba6e299b78f53ee5ba8ca9
parent 407746 896864ff931dd3d58f8cd55085a912d9b3a4de9c
child 407748 8ea5bbce1d95bed8e4d9cf0fcde372790b181928
push id33619
push usernbeleuzu@mozilla.com
push dateTue, 13 Mar 2018 09:58:16 +0000
treeherdermozilla-central@8f1b2f872f0e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskamidphish
bugs1434804
milestone61.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 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
@@ -2966,16 +2966,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) {
@@ -3015,16 +3019,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) {
@@ -3046,16 +3062,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;