Bug 1415478 - part2 : allow autoplay for non-audible media content and video without audio content. r=jwwang
☠☠ backed out by cd5278f13651 ☠ ☠
authorAlastor Wu <alwu@mozilla.com>
Mon, 27 Nov 2017 19:20:15 +0800
changeset 438335 df6721a3584f2a0e0ba87476ca4c3b28f2b55dd4
parent 438334 8a802839959b19f78cc3f31cff5a530a64a98f18
child 438336 6ba103fe1caf880b9ae817869d405e1d6f009f38
push id117
push userfmarier@mozilla.com
push dateTue, 28 Nov 2017 20:17:16 +0000
reviewersjwwang
bugs1415478
milestone59.0a1
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)
@@ -2434,17 +2429,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
@@ -6185,17 +6181,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,47 +2,54 @@
 /* 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)) {
+    // If user triggers load() or seek() before play(), we would also allow the
+    // following play().
+    return aElement->GetAndClearHasUserInteractedLoadOrSeek() ||
+           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.
-  // If user triggers load() or seek() before play(), we would also allow the
-  // following play().
-  return aElement->GetAndClearHasUserInteractedLoadOrSeek() ||
-         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