Bug 1415478 - part2 : allow autoplay for non-audible media content and video without audio content. r=jwwang
☠☠ backed out by e6b2a97752a6 ☠ ☠
authorAlastor Wu <alwu@mozilla.com>
Fri, 24 Nov 2017 11:14:26 +0800
changeset 393569 d855c032c8233f9daf0f8beeec1b12321a45b801
parent 393568 6739012c4bdf781f0e4da9d573245fbb5513d7d9
child 393570 447d895b350d0c6743bc151355c45ed49b0c58c4
push id32966
push useraciure@mozilla.com
push dateFri, 24 Nov 2017 22:02:06 +0000
treeherdermozilla-central@f6f7da6085aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwwang
bugs1415478
milestone59.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 1415478 - part2 : allow autoplay for non-audible media content and video without audio content. r=jwwang Per UX spec, we would allow non-audible media (volume 0, muted, video without audio track) to autoplay. MozReview-Commit-ID: HKUyt5Jt4sH
dom/html/HTMLMediaElement.cpp
dom/media/AutoplayPolicy.cpp
dom/media/AutoplayPolicy.h
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -665,21 +665,16 @@ void HTMLMediaElement::ReportLoadError(c
                                   NS_LITERAL_CSTRING("Media"),
                                   OwnerDoc(),
                                   nsContentUtils::eDOM_PROPERTIES,
                                   aMsg,
                                   aParams,
                                   aParamCount);
 }
 
-static bool IsAutoplayEnabled()
-{
-  return Preferences::GetBool("media.autoplay.enabled");
-}
-
 class HTMLMediaElement::AudioChannelAgentCallback final :
   public nsIAudioChannelAgentCallback
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(AudioChannelAgentCallback)
 
   explicit AudioChannelAgentCallback(HTMLMediaElement* aOwner)
@@ -2429,17 +2424,18 @@ void HTMLMediaElement::ResumeLoad(Preloa
   }
 }
 
 void HTMLMediaElement::UpdatePreloadAction()
 {
   PreloadAction nextAction = PRELOAD_UNDEFINED;
   // If autoplay is set, or we're playing, we should always preload data,
   // as we'll need it to play.
-  if ((IsAutoplayEnabled() && HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay)) ||
+  if ((AutoplayPolicy::IsMediaElementAllowedToPlay(WrapNotNull(this)) &&
+       HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay)) ||
       !mPaused)
   {
     nextAction = HTMLMediaElement::PRELOAD_ENOUGH;
   } else {
     // Find the appropriate preload action by looking at the attribute.
     const nsAttrValue* val = mAttrsAndChildren.GetAttr(nsGkAtoms::preload,
                                                        kNameSpaceID_None);
     // MSE doesn't work if preload is none, so it ignores the pref when src is
@@ -6173,17 +6169,17 @@ bool HTMLMediaElement::CanActivateAutopl
 {
   // For stream inputs, we activate autoplay on HAVE_NOTHING because
   // this element itself might be blocking the stream from making progress by
   // being paused. We only check that it has data by checking its active state.
   // We also activate autoplay when playing a media source since the data
   // download is controlled by the script and there is no way to evaluate
   // MediaDecoder::CanPlayThrough().
 
-  if (!IsAutoplayEnabled()) {
+  if (!AutoplayPolicy::IsMediaElementAllowedToPlay(WrapNotNull(this))) {
     return false;
   }
 
   if (!HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay)) {
     return false;
   }
 
   if (!mAutoplaying) {
--- a/dom/media/AutoplayPolicy.cpp
+++ b/dom/media/AutoplayPolicy.cpp
@@ -2,44 +2,51 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "AutoplayPolicy.h"
 
 #include "mozilla/EventStateManager.h"
-#include "mozilla/NotNull.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "nsIDocument.h"
 
 namespace mozilla {
 namespace dom {
 
 /* static */ bool
 AutoplayPolicy::IsDocumentAllowedToPlay(nsIDocument* aDoc)
 {
-  if (!Preferences::GetBool("media.autoplay.enabled.user-gestures-needed")) {
-    return true;
-  }
-
   return aDoc ? aDoc->HasBeenUserActivated() : false;
 }
 
 /* static */ bool
 AutoplayPolicy::IsMediaElementAllowedToPlay(NotNull<HTMLMediaElement*> aElement)
 {
   if (Preferences::GetBool("media.autoplay.enabled")) {
     return true;
   }
 
-  if (Preferences::GetBool("media.autoplay.enabled.user-gestures-needed", false)) {
-    return AutoplayPolicy::IsDocumentAllowedToPlay(aElement->OwnerDoc());
+  // TODO : this old way would be removed when user-gestures-needed becomes
+  // as a default option to block autoplay.
+  if (!Preferences::GetBool("media.autoplay.enabled.user-gestures-needed", false)) {
+    return EventStateManager::IsHandlingUserInput();
+   }
+
+  // Muted content
+  if (aElement->Volume() == 0.0 || aElement->Muted()) {
+    return true;
   }
 
-  // TODO : this old way would be removed when user-gestures-needed becomes
-  // as a default option to block autoplay.
-  return EventStateManager::IsHandlingUserInput();
+  // Media has already loaded metadata and doesn't contain audio track
+  if (aElement->IsVideo() &&
+      aElement->ReadyState() >= nsIDOMHTMLMediaElement::HAVE_METADATA &&
+      !aElement->HasAudio()) {
+    return true;
+  }
+
+  return AutoplayPolicy::IsDocumentAllowedToPlay(aElement->OwnerDoc());
 }
 
 } // namespace dom
 } // namespace mozilla
\ No newline at end of file
--- a/dom/media/AutoplayPolicy.h
+++ b/dom/media/AutoplayPolicy.h
@@ -20,21 +20,22 @@ class HTMLMediaElement;
  * AutoplayPolicy is used to manage autoplay logic for all kinds of media,
  * including MediaElement, Web Audio and Web Speech.
  *
  * Autoplay could be disable by turn off the pref "media.autoplay.enabled".
  * Once user disable autoplay, media could only be played if one of following
  * conditions is true.
  * 1) Owner document is activated by user gestures
  *    We restrict user gestures to "mouse click", "keyboard press" and "touch".
- * 2) TODO...
+ * 2) Muted media content or video without audio content
  */
 class AutoplayPolicy
 {
 public:
+  static bool IsMediaElementAllowedToPlay(NotNull<HTMLMediaElement*> aElement);
+private:
   static bool IsDocumentAllowedToPlay(nsIDocument* aDoc);
-  static bool IsMediaElementAllowedToPlay(NotNull<HTMLMediaElement*> aElement);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif
\ No newline at end of file