mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 07:13:20 +00:00
Bug 1773551 - part2 : implement the navigator autoplay policy API. r=media-playback-reviewers,webidl,smaug,padenot
Differential Revision: https://phabricator.services.mozilla.com/D164750
This commit is contained in:
parent
60bbc8ab3d
commit
db2a9a2552
@ -91,7 +91,6 @@
|
||||
|
||||
#include "nsJSUtils.h"
|
||||
|
||||
#include "mozilla/dom/NavigatorBinding.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
|
||||
#include "nsIUploadChannel2.h"
|
||||
@ -113,6 +112,9 @@
|
||||
#include "mozilla/dom/WindowGlobalChild.h"
|
||||
|
||||
#include "mozilla/intl/LocaleService.h"
|
||||
#include "mozilla/dom/AudioContext.h"
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#include "AutoplayPolicy.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
@ -2271,4 +2273,23 @@ bool Navigator::Webdriver() {
|
||||
return false;
|
||||
}
|
||||
|
||||
AutoplayPolicy Navigator::GetAutoplayPolicy(AutoplayPolicyMediaType aType) {
|
||||
if (!mWindow) {
|
||||
return AutoplayPolicy::Disallowed;
|
||||
}
|
||||
nsCOMPtr<Document> doc = mWindow->GetExtantDoc();
|
||||
if (!doc) {
|
||||
return AutoplayPolicy::Disallowed;
|
||||
}
|
||||
return media::AutoplayPolicy::GetAutoplayPolicy(aType, *doc);
|
||||
}
|
||||
|
||||
AutoplayPolicy Navigator::GetAutoplayPolicy(HTMLMediaElement& aElement) {
|
||||
return media::AutoplayPolicy::GetAutoplayPolicy(aElement);
|
||||
}
|
||||
|
||||
AutoplayPolicy Navigator::GetAutoplayPolicy(AudioContext& aContext) {
|
||||
return media::AutoplayPolicy::GetAutoplayPolicy(aContext);
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "mozilla/dom/AddonManagerBinding.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/Fetch.h"
|
||||
#include "mozilla/dom/NavigatorBinding.h"
|
||||
#include "mozilla/dom/Nullable.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsHashKeys.h"
|
||||
@ -43,6 +44,8 @@ class DOMRequest;
|
||||
class CredentialsContainer;
|
||||
class Clipboard;
|
||||
class LockManager;
|
||||
class HTMLMediaElement;
|
||||
class AudioContext;
|
||||
} // namespace dom
|
||||
namespace webgpu {
|
||||
class Instance;
|
||||
@ -244,6 +247,12 @@ class Navigator final : public nsISupports, public nsWrapperCache {
|
||||
|
||||
bool HasCreatedMediaSession() const;
|
||||
|
||||
// Following methods are for the Autoplay Policy Detection API.
|
||||
// https://w3c.github.io/autoplay/#autoplay-detection-methods
|
||||
AutoplayPolicy GetAutoplayPolicy(AutoplayPolicyMediaType aType);
|
||||
AutoplayPolicy GetAutoplayPolicy(HTMLMediaElement& aElement);
|
||||
AutoplayPolicy GetAutoplayPolicy(AudioContext& aContext);
|
||||
|
||||
private:
|
||||
void ValidateShareData(const ShareData& aData, ErrorResult& aRv);
|
||||
RefPtr<MediaKeySystemAccessManager> mMediaKeySystemAccessManager;
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "mozilla/dom/FeaturePolicyUtils.h"
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#include "mozilla/dom/HTMLMediaElementBinding.h"
|
||||
#include "mozilla/dom/NavigatorBinding.h"
|
||||
#include "mozilla/dom/UserActivation.h"
|
||||
#include "mozilla/dom/WindowContext.h"
|
||||
#include "mozilla/Logging.h"
|
||||
@ -192,7 +193,8 @@ static bool IsGVAutoplayRequestAllowed(nsPIDOMWindowInner* aWindow,
|
||||
return status == GVAutoplayRequestStatus::eALLOWED;
|
||||
}
|
||||
|
||||
static bool IsGVAutoplayRequestAllowed(const HTMLMediaElement& aElement) {
|
||||
static bool IsGVAutoplayRequestAllowed(const HTMLMediaElement& aElement,
|
||||
RType aType) {
|
||||
// On GV, blocking model is the first thing we would check inside Gecko, and
|
||||
// if the media is not allowed by that, then we would check the response from
|
||||
// the embedding app to decide the final result.
|
||||
@ -204,17 +206,16 @@ static bool IsGVAutoplayRequestAllowed(const HTMLMediaElement& aElement) {
|
||||
if (!window) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const RType type =
|
||||
IsMediaElementInaudible(aElement) ? RType::eINAUDIBLE : RType::eAUDIBLE;
|
||||
return IsGVAutoplayRequestAllowed(window, type);
|
||||
return IsGVAutoplayRequestAllowed(window, aType);
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool IsAllowedToPlayInternal(const HTMLMediaElement& aElement) {
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
if (StaticPrefs::media_geckoview_autoplay_request()) {
|
||||
return IsGVAutoplayRequestAllowed(aElement);
|
||||
return IsGVAutoplayRequestAllowed(
|
||||
aElement, IsMediaElementInaudible(aElement) ? RType::eINAUDIBLE
|
||||
: RType::eAUDIBLE);
|
||||
}
|
||||
#endif
|
||||
bool isInaudible = IsMediaElementInaudible(aElement);
|
||||
@ -359,4 +360,96 @@ bool AutoplayPolicyTelemetryUtils::WouldBeAllowedToPlayIfAutoplayDisabled(
|
||||
return IsAudioContextAllowedToPlay(aContext);
|
||||
}
|
||||
|
||||
/* static */
|
||||
dom::AutoplayPolicy AutoplayPolicy::GetAutoplayPolicy(
|
||||
const dom::HTMLMediaElement& aElement) {
|
||||
// Note, the site permission can contain following values :
|
||||
// - UNKNOWN_ACTION : no permission set for this site
|
||||
// - ALLOW_ACTION : allowed to autoplay
|
||||
// - DENY_ACTION : allowed inaudible autoplay, disallowed inaudible autoplay
|
||||
// - nsIAutoplay::BLOCKED_ALL : autoplay disallowed
|
||||
// and the global permissions would be nsIAutoplay::{BLOCKED, ALLOWED,
|
||||
// BLOCKED_ALL}
|
||||
const uint32_t sitePermission =
|
||||
SiteAutoplayPerm(aElement.OwnerDoc()->GetInnerWindow());
|
||||
const uint32_t globalPermission = DefaultAutoplayBehaviour();
|
||||
const bool isAllowedToPlayByBlockingModel =
|
||||
IsAllowedToPlayByBlockingModel(aElement);
|
||||
|
||||
AUTOPLAY_LOG(
|
||||
"IsAllowedToPlay(element), sitePermission=%d, globalPermission=%d, "
|
||||
"isAllowedToPlayByBlockingModel=%d",
|
||||
sitePermission, globalPermission, isAllowedToPlayByBlockingModel);
|
||||
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
if (StaticPrefs::media_geckoview_autoplay_request()) {
|
||||
if (IsGVAutoplayRequestAllowed(aElement, RType::eAUDIBLE)) {
|
||||
return dom::AutoplayPolicy::Allowed;
|
||||
} else if (IsGVAutoplayRequestAllowed(aElement, RType::eINAUDIBLE)) {
|
||||
return isAllowedToPlayByBlockingModel
|
||||
? dom::AutoplayPolicy::Allowed
|
||||
: dom::AutoplayPolicy::Allowed_muted;
|
||||
} else {
|
||||
return isAllowedToPlayByBlockingModel ? dom::AutoplayPolicy::Allowed
|
||||
: dom::AutoplayPolicy::Disallowed;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// These are situations when an element is allowed to autoplay
|
||||
// 1. The site permission is explicitly allowed
|
||||
// 2. The global permission is allowed, and the site isn't explicitly
|
||||
// disallowed
|
||||
// 3. The blocking model is explicitly allowed this element
|
||||
if (sitePermission == nsIPermissionManager::ALLOW_ACTION ||
|
||||
(globalPermission == nsIAutoplay::ALLOWED &&
|
||||
(sitePermission != nsIPermissionManager::DENY_ACTION &&
|
||||
sitePermission != nsIAutoplay::BLOCKED_ALL)) ||
|
||||
isAllowedToPlayByBlockingModel) {
|
||||
return dom::AutoplayPolicy::Allowed;
|
||||
}
|
||||
|
||||
// These are situations when a element is allowed to autoplay only when it's
|
||||
// inaudible.
|
||||
// 1. The site permission is block-audible-autoplay
|
||||
// 2. The global permission is block-audible-autoplay, and the site permission
|
||||
// isn't block-all-autoplay
|
||||
if (sitePermission == nsIPermissionManager::DENY_ACTION ||
|
||||
(globalPermission == nsIAutoplay::BLOCKED &&
|
||||
sitePermission != nsIAutoplay::BLOCKED_ALL)) {
|
||||
return dom::AutoplayPolicy::Allowed_muted;
|
||||
}
|
||||
|
||||
return dom::AutoplayPolicy::Disallowed;
|
||||
}
|
||||
|
||||
/* static */
|
||||
dom::AutoplayPolicy AutoplayPolicy::GetAutoplayPolicy(
|
||||
const dom::AudioContext& aContext) {
|
||||
if (AutoplayPolicy::IsAllowedToPlay(aContext)) {
|
||||
return dom::AutoplayPolicy::Allowed;
|
||||
}
|
||||
return dom::AutoplayPolicy::Disallowed;
|
||||
}
|
||||
|
||||
/* static */
|
||||
dom::AutoplayPolicy AutoplayPolicy::GetAutoplayPolicy(
|
||||
const dom::AutoplayPolicyMediaType& aType, const dom::Document& aDoc) {
|
||||
dom::DocumentAutoplayPolicy policy = AutoplayPolicy::IsAllowedToPlay(aDoc);
|
||||
// https://w3c.github.io/autoplay/#query-by-a-media-type
|
||||
if (aType == dom::AutoplayPolicyMediaType::Audiocontext) {
|
||||
return policy == dom::DocumentAutoplayPolicy::Allowed
|
||||
? dom::AutoplayPolicy::Allowed
|
||||
: dom::AutoplayPolicy::Disallowed;
|
||||
}
|
||||
MOZ_ASSERT(aType == dom::AutoplayPolicyMediaType::Mediaelement);
|
||||
if (policy == dom::DocumentAutoplayPolicy::Allowed) {
|
||||
return dom::AutoplayPolicy::Allowed;
|
||||
}
|
||||
if (policy == dom::DocumentAutoplayPolicy::Allowed_muted) {
|
||||
return dom::AutoplayPolicy::Allowed_muted;
|
||||
}
|
||||
return dom::AutoplayPolicy::Disallowed;
|
||||
}
|
||||
|
||||
} // namespace mozilla::media
|
||||
|
@ -16,6 +16,8 @@ namespace mozilla::dom {
|
||||
class HTMLMediaElement;
|
||||
class AudioContext;
|
||||
class Document;
|
||||
enum class AutoplayPolicy : uint8_t;
|
||||
enum class AutoplayPolicyMediaType : uint8_t;
|
||||
enum class DocumentAutoplayPolicy : uint8_t;
|
||||
|
||||
} // namespace mozilla::dom
|
||||
@ -48,6 +50,18 @@ class AutoplayPolicy {
|
||||
// Return the value of the autoplay permission for given principal. The return
|
||||
// value can be 0=unknown, 1=allow, 2=block audio, 5=block audio and video.
|
||||
static uint32_t GetSiteAutoplayPermission(nsIPrincipal* aPrincipal);
|
||||
|
||||
// Following methods are used for the internal implementation for the Autoplay
|
||||
// Policy Detection API, the public JS interfaces are in exposed on Navigator.
|
||||
// https://w3c.github.io/autoplay/#autoplay-detection-methods
|
||||
static dom::AutoplayPolicy GetAutoplayPolicy(
|
||||
const dom::HTMLMediaElement& aElement);
|
||||
|
||||
static dom::AutoplayPolicy GetAutoplayPolicy(
|
||||
const dom::AudioContext& aContext);
|
||||
|
||||
static dom::AutoplayPolicy GetAutoplayPolicy(
|
||||
const dom::AutoplayPolicyMediaType& aType, const dom::Document& aDoc);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -344,3 +344,27 @@ interface mixin NavigatorLocks {
|
||||
readonly attribute LockManager locks;
|
||||
};
|
||||
Navigator includes NavigatorLocks;
|
||||
|
||||
// https://w3c.github.io/autoplay/#autoplay-policy
|
||||
enum AutoplayPolicy {
|
||||
"allowed",
|
||||
"allowed-muted",
|
||||
"disallowed"
|
||||
};
|
||||
|
||||
enum AutoplayPolicyMediaType {
|
||||
"mediaelement",
|
||||
"audiocontext"
|
||||
};
|
||||
|
||||
// https://w3c.github.io/autoplay/#autoplay-detection-methods
|
||||
partial interface Navigator {
|
||||
[Pref="dom.media.autoplay-policy-detection.enabled"]
|
||||
AutoplayPolicy getAutoplayPolicy(AutoplayPolicyMediaType type);
|
||||
|
||||
[Pref="dom.media.autoplay-policy-detection.enabled"]
|
||||
AutoplayPolicy getAutoplayPolicy(HTMLMediaElement element);
|
||||
|
||||
[Pref="dom.media.autoplay-policy-detection.enabled"]
|
||||
AutoplayPolicy getAutoplayPolicy(AudioContext context);
|
||||
};
|
||||
|
@ -3000,6 +3000,12 @@
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# Autoplay Policy Detection https://w3c.github.io/autoplay/
|
||||
- name: dom.media.autoplay-policy-detection.enabled
|
||||
type: RelaxedAtomicBool
|
||||
value: @IS_NIGHTLY_BUILD@
|
||||
mirror: always
|
||||
|
||||
# Media Session API
|
||||
- name: dom.media.mediasession.enabled
|
||||
type: bool
|
||||
|
Loading…
Reference in New Issue
Block a user