Commit f986ca0c authored by alwu's avatar alwu
Browse files

Bug 1509933 - part1 : add new pref 'media.autoplay.blocking_policy'....

Bug 1509933 - part1 : add new pref 'media.autoplay.blocking_policy'. r=geckoview-reviewers,snorp,padenot

This patch will do :
- rename the old pref `media.autoplay.enabled.user-gestures-needed` to  the new pref `media.autoplay.blocking_policy`
- modify the value of the pref to `int` in order to introduce new policy
- implement new policy in `AutoplayPoliocy`

The advantage of doing so :
- rename the pref to explicitly indicate that it's related the block policy we use
- use the transient user gesture activation as a new policy to replace the old one using the user input, which doesn't work on the async handler

More details :
The old `click-to-play` policy we use is using the user input to determine if the play invocation is called by users or by scripts. But `UserActivation::IsHandlingUserInput()` is buggy which would fail when you call `video.play()` inside an async event handler. So we would like to replace it with the new transient user activation, which would treat the action as an user input if the action is performed within a certain period of time after a user interacts (eg. click) with the page.

[1] https://html.spec.whatwg.org/multipage/interaction.html#transient-activation

Differential Revision: https://phabricator.services.mozilla.com/D73971
parent c6e5d7a8
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -1480,8 +1480,6 @@ pref("media.gmp.trial-create.enabled", true);
pref("media.gmp-gmpopenh264.visible", true);
pref("media.gmp-gmpopenh264.enabled", true);

// Switch block autoplay logic to v2, and enable UI.
pref("media.autoplay.enabled.user-gestures-needed", true);
// Set Firefox to block autoplay, asking for permission by default.
pref("media.autoplay.default", 1); // 0=Allowed, 1=Blocked, 5=All Blocked

+28 −6
Original line number Diff line number Diff line
@@ -33,6 +33,10 @@ mozilla::LazyLogModule gAutoplayPermissionLog("Autoplay");
namespace mozilla {
namespace dom {

static const uint32_t sPOLICY_STICKY_ACTIVATION = 0;
static const uint32_t sPOLICY_TRANSIENT_ACTIVATION = 1;
static const uint32_t sPOLICY_USER_INPUT_DEPTH = 2;

static Document* ApproverDocOf(const Document& aDocument) {
  nsCOMPtr<nsIDocShell> ds = aDocument.GetDocShell();
  if (!ds) {
@@ -161,15 +165,33 @@ static bool IsAudioContextAllowedToPlay(const AudioContext& aContext) {

static bool IsEnableBlockingWebAudioByUserGesturePolicy() {
  return Preferences::GetBool("media.autoplay.block-webaudio", false) &&
         StaticPrefs::media_autoplay_enabled_user_gestures_needed();
         StaticPrefs::media_autoplay_blocking_policy() ==
             sPOLICY_STICKY_ACTIVATION;
}

static bool IsAllowedToPlayByBlockingModel(const HTMLMediaElement& aElement) {
  if (!StaticPrefs::media_autoplay_enabled_user_gestures_needed()) {
    // If element is blessed, it would always be allowed to play().
    return aElement.IsBlessed() || UserActivation::IsHandlingUserInput();
  const uint32_t policy = StaticPrefs::media_autoplay_blocking_policy();
  if (policy == sPOLICY_STICKY_ACTIVATION) {
    const bool isAllowed =
        IsWindowAllowedToPlay(aElement.OwnerDoc()->GetInnerWindow());
    AUTOPLAY_LOG("Use 'sticky-activation', isAllowed=%d", isAllowed);
    return isAllowed;
  }
  return IsWindowAllowedToPlay(aElement.OwnerDoc()->GetInnerWindow());
  // If element is blessed, it would always be allowed to play().
  const bool isElementBlessed = aElement.IsBlessed();
  if (policy == sPOLICY_USER_INPUT_DEPTH) {
    const bool isUserInput = UserActivation::IsHandlingUserInput();
    AUTOPLAY_LOG("Use 'User-Input-Depth', isBlessed=%d, isUserInput=%d",
                 isElementBlessed, isUserInput);
    return isElementBlessed || isUserInput;
  }
  const bool hasTransientActivation =
      aElement.OwnerDoc()->HasValidTransientUserGestureActivation();
  AUTOPLAY_LOG(
      "Use 'transient-activation', isBlessed=%d, "
      "hasValidTransientActivation=%d",
      isElementBlessed, hasTransientActivation);
  return isElementBlessed || hasTransientActivation;
}

// On GeckoView, we don't store any site's permission in permission manager, we
+0 −2
Original line number Diff line number Diff line
@@ -473,8 +473,6 @@ pref("media.video-queue.send-to-compositor-size", 1);

pref("media.mediadrm-widevinecdm.visible", true);

// Switch block autoplay logic to v2.
pref("media.autoplay.enabled.user-gestures-needed", true);
// Set Fennec to block autoplay by default.
pref("media.autoplay.default", 1); // 0=Allowed, 1=Blocked

+11 −7
Original line number Diff line number Diff line
@@ -6350,13 +6350,17 @@
#---------------------------------------------------------------------------


# If "media.autoplay.default" is not ALLOWED, and this pref is true,
# then audible media would only be allowed to autoplay after website has
# been activated by specific user gestures, but non-audible
# media won't be restricted.
- name: media.autoplay.enabled.user-gestures-needed
  type: bool
  value: false
# This pref defines what the blocking policy would be used in blocking autoplay.
# 0 : use sticky activation (default)
# https://html.spec.whatwg.org/multipage/interaction.html#sticky-activation
# 1 : use transient activation (the transient activation duration can be
#     adjusted by the pref `dom.user_activation.transient.timeout`)
# https://html.spec.whatwg.org/multipage/interaction.html#transient-activation
# 2 : user input depth (allow autoplay when the play is trigged by user input
#     which is determined by the user input depth)
- name: media.autoplay.blocking_policy
  type: uint32_t
  value: 0
  mirror: always

# File-backed MediaCache size.