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
This commit is contained in:
alwu 2020-05-15 01:39:31 +00:00
Родитель cae38bcf26
Коммит 8ed9cb7dbc
4 изменённых файлов: 40 добавлений и 14 удалений

Просмотреть файл

@ -1481,7 +1481,7 @@ 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);
pref("media.autoplay.blocking_policy", 0);
// Set Firefox to block autoplay, asking for permission by default.
pref("media.autoplay.default", 1); // 0=Allowed, 1=Blocked, 5=All Blocked

Просмотреть файл

@ -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

Просмотреть файл

@ -474,7 +474,7 @@ 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);
pref("media.autoplay.blocking_policy", 0);
// Set Fennec to block autoplay by default.
pref("media.autoplay.default", 1); // 0=Allowed, 1=Blocked

Просмотреть файл

@ -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.