Bug 1415478 - part2 : allow autoplay for non-audible media content and video without audio content. r=jwwang
authorAlastor Wu <alwu@mozilla.com>
Thu, 30 Nov 2017 10:50:21 +0800
changeset 394272 4a4b3c541465e385f05330c7e568a65c5be7cbec
parent 394271 972288371a57691249477424305da83f9f2e9a6c
child 394273 1762ac4166c92a39fc8eaac2f77fd346ab9a7da3
push id32997
push usershindli@mozilla.com
push dateThu, 30 Nov 2017 09:58:19 +0000
treeherdermozilla-central@1762ac4166c9 [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)
@@ -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
@@ -6187,17 +6183,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,46 +2,53 @@
 /* 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 elelement is blessed, it would always be allowed to play().
+    return aElement->IsBlessed() ||
+           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 elelement is blessed, it would always be allowed to play().
-  return aElement->IsBlessed() ||
-         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