mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1095257 - Implement Navigator.requestMediaKeySystemAccess(). r=edwin r=bz r=peterv
This commit is contained in:
parent
0b1a324eb4
commit
fc70ad371b
@ -2533,5 +2533,43 @@ Navigator::GetUserAgent(nsPIDOMWindow* aWindow, nsIURI* aURI,
|
||||
return siteSpecificUA->GetUserAgentForURIAndWindow(aURI, aWindow, aUserAgent);
|
||||
}
|
||||
|
||||
#ifdef MOZ_EME
|
||||
already_AddRefed<Promise>
|
||||
Navigator::RequestMediaKeySystemAccess(const nsAString& aKeySystem,
|
||||
const Optional<Sequence<MediaKeySystemOptions>>& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
|
||||
nsRefPtr<Promise> p = Promise::Create(go, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aKeySystem.IsEmpty() ||
|
||||
(aOptions.WasPassed() && aOptions.Value().IsEmpty())) {
|
||||
p->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
if (!MediaKeySystemAccess::IsKeySystemSupported(aKeySystem)) {
|
||||
p->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
// TODO: Wait (async) until the CDM is downloaded, if it's not already.
|
||||
|
||||
if (!aOptions.WasPassed() ||
|
||||
MediaKeySystemAccess::IsSupported(aKeySystem, aOptions.Value())) {
|
||||
nsRefPtr<MediaKeySystemAccess> access(new MediaKeySystemAccess(mWindow, aKeySystem));
|
||||
p->MaybeResolve(access);
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
p->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
|
||||
return p.forget();
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -18,6 +18,9 @@
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#ifdef MOZ_EME
|
||||
#include "mozilla/dom/MediaKeySystemAccess.h"
|
||||
#endif
|
||||
|
||||
class nsPluginArray;
|
||||
class nsMimeTypeArray;
|
||||
@ -316,6 +319,13 @@ public:
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE;
|
||||
|
||||
#ifdef MOZ_EME
|
||||
already_AddRefed<Promise>
|
||||
RequestMediaKeySystemAccess(const nsAString& aKeySystem,
|
||||
const Optional<Sequence<MediaKeySystemOptions>>& aOptions,
|
||||
ErrorResult& aRv);
|
||||
#endif
|
||||
|
||||
private:
|
||||
virtual ~Navigator();
|
||||
|
||||
|
@ -335,8 +335,9 @@ IsMP4SupportedType(const nsACString& aType,
|
||||
#ifdef MOZ_OMX_DECODER
|
||||
return false;
|
||||
#else
|
||||
bool haveAAC, haveMP3, haveH264;
|
||||
return Preferences::GetBool("media.fragmented-mp4.exposed", false) &&
|
||||
MP4Decoder::CanHandleMediaType(aType, aCodecs);
|
||||
MP4Decoder::CanHandleMediaType(aType, aCodecs, haveAAC, haveH264, haveMP3);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
212
dom/media/eme/MediaKeySystemAccess.cpp
Normal file
212
dom/media/eme/MediaKeySystemAccess.cpp
Normal file
@ -0,0 +1,212 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 "mozilla/dom/MediaKeySystemAccess.h"
|
||||
#include "mozilla/dom/MediaKeySystemAccessBinding.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsContentTypeParser.h"
|
||||
#ifdef MOZ_FMP4
|
||||
#include "MP4Decoder.h"
|
||||
#endif
|
||||
#ifdef XP_WIN
|
||||
#include "mozilla/WindowsVersion.h"
|
||||
#endif
|
||||
#include "nsContentCID.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "mozIGeckoMediaPluginService.h"
|
||||
#include "VideoUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MediaKeySystemAccess,
|
||||
mParent)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaKeySystemAccess)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaKeySystemAccess)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaKeySystemAccess)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
MediaKeySystemAccess::MediaKeySystemAccess(nsPIDOMWindow* aParent,
|
||||
const nsAString& aKeySystem)
|
||||
: mParent(aParent)
|
||||
, mKeySystem(aKeySystem)
|
||||
{
|
||||
}
|
||||
|
||||
MediaKeySystemAccess::~MediaKeySystemAccess()
|
||||
{
|
||||
}
|
||||
|
||||
JSObject*
|
||||
MediaKeySystemAccess::WrapObject(JSContext* aCx)
|
||||
{
|
||||
return MediaKeySystemAccessBinding::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
nsPIDOMWindow*
|
||||
MediaKeySystemAccess::GetParentObject() const
|
||||
{
|
||||
return mParent;
|
||||
}
|
||||
|
||||
void
|
||||
MediaKeySystemAccess::GetKeySystem(nsString& aRetVal) const
|
||||
{
|
||||
aRetVal = mKeySystem;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
MediaKeySystemAccess::CreateMediaKeys(ErrorResult& aRv)
|
||||
{
|
||||
nsRefPtr<MediaKeys> keys(new MediaKeys(mParent, mKeySystem));
|
||||
return keys->Init(aRv);
|
||||
}
|
||||
|
||||
static bool
|
||||
HaveGMPFor(mozIGeckoMediaPluginService* aGMPService,
|
||||
const nsCString& aKeySystem,
|
||||
const nsCString& aAPI,
|
||||
const nsCString& aTag = EmptyCString())
|
||||
{
|
||||
nsTArray<nsCString> tags;
|
||||
tags.AppendElement(aKeySystem);
|
||||
if (!aTag.IsEmpty()) {
|
||||
tags.AppendElement(aTag);
|
||||
}
|
||||
// Note: EME plugins need a non-null nodeId here, as they must
|
||||
// not be shared across origins.
|
||||
bool hasPlugin = false;
|
||||
if (NS_FAILED(aGMPService->HasPluginForAPI(aAPI,
|
||||
&tags,
|
||||
&hasPlugin))) {
|
||||
return false;
|
||||
}
|
||||
return hasPlugin;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
MediaKeySystemAccess::IsKeySystemSupported(const nsAString& aKeySystem)
|
||||
{
|
||||
nsCOMPtr<mozIGeckoMediaPluginService> mps =
|
||||
do_GetService("@mozilla.org/gecko-media-plugin-service;1");
|
||||
if (NS_WARN_IF(!mps)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aKeySystem.EqualsLiteral("org.w3.clearkey") &&
|
||||
HaveGMPFor(mps,
|
||||
NS_LITERAL_CSTRING("org.w3.clearkey"),
|
||||
NS_LITERAL_CSTRING("eme-decrypt"))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
if (aKeySystem.EqualsLiteral("com.adobe.access") &&
|
||||
Preferences::GetBool("media.eme.adobe-access.enabled", false) &&
|
||||
IsVistaOrLater() && // Win Vista and later only.
|
||||
HaveGMPFor(mps,
|
||||
NS_LITERAL_CSTRING("com.adobe.access"),
|
||||
NS_LITERAL_CSTRING("eme-decrypt"))) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsPlayableWithGMP(mozIGeckoMediaPluginService* aGMPS,
|
||||
const nsAString& aKeySystem,
|
||||
const nsAString& aContentType)
|
||||
{
|
||||
#ifdef MOZ_FMP4
|
||||
nsContentTypeParser parser(aContentType);
|
||||
nsAutoString mimeType;
|
||||
nsresult rv = parser.GetType(mimeType);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mimeType.EqualsLiteral("audio/mp4") &&
|
||||
!mimeType.EqualsLiteral("audio/x-m4a") &&
|
||||
!mimeType.EqualsLiteral("video/mp4")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoString codecs;
|
||||
parser.GetParameter("codecs", codecs);
|
||||
|
||||
NS_ConvertUTF16toUTF8 mimeTypeUTF8(mimeType);
|
||||
bool hasAAC = false;
|
||||
bool hasH264 = false;
|
||||
bool hasMP3 = false;
|
||||
if (!MP4Decoder::CanHandleMediaType(mimeTypeUTF8,
|
||||
codecs,
|
||||
hasAAC,
|
||||
hasH264,
|
||||
hasMP3) ||
|
||||
hasMP3) {
|
||||
return false;
|
||||
}
|
||||
return (!hasAAC || !HaveGMPFor(aGMPS,
|
||||
NS_ConvertUTF16toUTF8(aKeySystem),
|
||||
NS_LITERAL_CSTRING("eme-decrypt"),
|
||||
NS_LITERAL_CSTRING("aac"))) &&
|
||||
(!hasH264 || !HaveGMPFor(aGMPS,
|
||||
NS_ConvertUTF16toUTF8(aKeySystem),
|
||||
NS_LITERAL_CSTRING("eme-decrypt"),
|
||||
NS_LITERAL_CSTRING("h264")));
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
MediaKeySystemAccess::IsSupported(const nsAString& aKeySystem,
|
||||
const Sequence<MediaKeySystemOptions>& aOptions)
|
||||
{
|
||||
nsCOMPtr<mozIGeckoMediaPluginService> mps =
|
||||
do_GetService("@mozilla.org/gecko-media-plugin-service;1");
|
||||
if (NS_WARN_IF(!mps)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < aOptions.Length(); i++) {
|
||||
const MediaKeySystemOptions& options = aOptions[i];
|
||||
if (!options.mInitDataType.EqualsLiteral("cenc")) {
|
||||
continue;
|
||||
}
|
||||
if (!options.mAudioCapability.IsEmpty() ||
|
||||
!options.mVideoCapability.IsEmpty()) {
|
||||
// Don't support any capabilites until we know we have a CDM with
|
||||
// capabilities...
|
||||
continue;
|
||||
}
|
||||
if (!options.mAudioType.IsEmpty() &&
|
||||
!IsPlayableWithGMP(mps, aKeySystem, options.mAudioType)) {
|
||||
continue;
|
||||
}
|
||||
if (!options.mVideoType.IsEmpty() &&
|
||||
!IsPlayableWithGMP(mps, aKeySystem, options.mVideoType)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Our sandbox provides an origin specific unique identifier, and the
|
||||
// ability to persist data. We don't yet have a way to turn those off
|
||||
// and on for specific GMPs/CDMs, so we don't check the uniqueidentifier
|
||||
// and stateful attributes here.
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
58
dom/media/eme/MediaKeySystemAccess.h
Normal file
58
dom/media/eme/MediaKeySystemAccess.h
Normal file
@ -0,0 +1,58 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_MediaKeySystemAccess_h
|
||||
#define mozilla_dom_MediaKeySystemAccess_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/MediaKeySystemAccessBinding.h"
|
||||
#include "js/TypeDecls.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class MediaKeySystemAccess MOZ_FINAL : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaKeySystemAccess)
|
||||
|
||||
public:
|
||||
explicit MediaKeySystemAccess(nsPIDOMWindow* aParent,
|
||||
const nsAString& aKeySystem);
|
||||
|
||||
protected:
|
||||
~MediaKeySystemAccess();
|
||||
|
||||
public:
|
||||
nsPIDOMWindow* GetParentObject() const;
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
void GetKeySystem(nsString& aRetVal) const;
|
||||
|
||||
already_AddRefed<Promise> CreateMediaKeys(ErrorResult& aRv);
|
||||
|
||||
static bool IsKeySystemSupported(const nsAString& aKeySystem);
|
||||
|
||||
static bool IsSupported(const nsAString& aKeySystem,
|
||||
const Sequence<MediaKeySystemOptions>& aOptions);
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsPIDOMWindow> mParent;
|
||||
const nsString mKeySystem;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_MediaKeySystemAccess_h
|
@ -114,111 +114,6 @@ MediaKeys::SetServerCertificate(const ArrayBufferViewOrArrayBuffer& aCert, Error
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
static bool
|
||||
HaveGMPFor(const nsCString& aKeySystem,
|
||||
const nsCString& aAPI,
|
||||
const nsCString& aTag = EmptyCString())
|
||||
{
|
||||
nsCOMPtr<mozIGeckoMediaPluginService> mps =
|
||||
do_GetService("@mozilla.org/gecko-media-plugin-service;1");
|
||||
if (NS_WARN_IF(!mps)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsTArray<nsCString> tags;
|
||||
tags.AppendElement(aKeySystem);
|
||||
if (!aTag.IsEmpty()) {
|
||||
tags.AppendElement(aTag);
|
||||
}
|
||||
// Note: EME plugins need a non-null nodeId here, as they must
|
||||
// not be shared across origins.
|
||||
bool hasPlugin = false;
|
||||
if (NS_FAILED(mps->HasPluginForAPI(aAPI,
|
||||
&tags,
|
||||
&hasPlugin))) {
|
||||
return false;
|
||||
}
|
||||
return hasPlugin;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsPlayableMP4Type(const nsAString& aContentType)
|
||||
{
|
||||
#ifdef MOZ_FMP4
|
||||
nsContentTypeParser parser(aContentType);
|
||||
nsAutoString mimeType;
|
||||
nsresult rv = parser.GetType(mimeType);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
nsAutoString codecs;
|
||||
parser.GetParameter("codecs", codecs);
|
||||
|
||||
NS_ConvertUTF16toUTF8 mimeTypeUTF8(mimeType);
|
||||
return MP4Decoder::CanHandleMediaType(mimeTypeUTF8, codecs);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
MediaKeys::IsTypeSupported(const nsAString& aKeySystem,
|
||||
const Optional<nsAString>& aInitDataType,
|
||||
const Optional<nsAString>& aContentType)
|
||||
{
|
||||
if (aKeySystem.EqualsLiteral("org.w3.clearkey") &&
|
||||
(!aInitDataType.WasPassed() || aInitDataType.Value().EqualsLiteral("cenc")) &&
|
||||
(!aContentType.WasPassed() || IsPlayableMP4Type(aContentType.Value())) &&
|
||||
HaveGMPFor(NS_LITERAL_CSTRING("org.w3.clearkey"),
|
||||
NS_LITERAL_CSTRING("eme-decrypt"))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
// Note: Adobe Access's GMP uses WMF to decode, so anything our MP4Reader
|
||||
// thinks it can play on Windows, the Access GMP should be able to play.
|
||||
if (aKeySystem.EqualsLiteral("com.adobe.access") &&
|
||||
Preferences::GetBool("media.eme.adobe-access.enabled", false) &&
|
||||
IsVistaOrLater() && // Win Vista and later only.
|
||||
(!aInitDataType.WasPassed() || aInitDataType.Value().EqualsLiteral("cenc")) &&
|
||||
(!aContentType.WasPassed() || IsPlayableMP4Type(aContentType.Value())) &&
|
||||
HaveGMPFor(NS_LITERAL_CSTRING("com.adobe.access"),
|
||||
NS_LITERAL_CSTRING("eme-decrypt")) &&
|
||||
HaveGMPFor(NS_LITERAL_CSTRING("com.adobe.access"),
|
||||
NS_LITERAL_CSTRING("decode-video"),
|
||||
NS_LITERAL_CSTRING("h264")) &&
|
||||
HaveGMPFor(NS_LITERAL_CSTRING("com.adobe.access"),
|
||||
NS_LITERAL_CSTRING("decode-audio"),
|
||||
NS_LITERAL_CSTRING("aac"))) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */
|
||||
IsTypeSupportedResult
|
||||
MediaKeys::IsTypeSupported(const GlobalObject& aGlobal,
|
||||
const nsAString& aKeySystem,
|
||||
const Optional<nsAString>& aInitDataType,
|
||||
const Optional<nsAString>& aContentType,
|
||||
const Optional<nsAString>& aCapability)
|
||||
{
|
||||
// TODO: Should really get spec changed to this is async, so we can wait
|
||||
// for user to consent to running plugin.
|
||||
bool supported = IsTypeSupported(aKeySystem, aInitDataType, aContentType);
|
||||
|
||||
EME_LOG("MediaKeys::IsTypeSupported keySystem='%s' initDataType='%s' contentType='%s' supported=%d",
|
||||
NS_ConvertUTF16toUTF8(aKeySystem).get(),
|
||||
(aInitDataType.WasPassed() ? NS_ConvertUTF16toUTF8(aInitDataType.Value()).get() : ""),
|
||||
(aContentType.WasPassed() ? NS_ConvertUTF16toUTF8(aContentType.Value()).get() : ""),
|
||||
supported);
|
||||
|
||||
return supported ? IsTypeSupportedResult::Probably
|
||||
: IsTypeSupportedResult::_empty;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
MediaKeys::MakePromise(ErrorResult& aRv)
|
||||
{
|
||||
@ -303,24 +198,6 @@ MediaKeys::ResolvePromise(PromiseId aId)
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<Promise>
|
||||
MediaKeys::Create(const GlobalObject& aGlobal,
|
||||
const nsAString& aKeySystem,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
// CDMProxy keeps MediaKeys alive until it resolves the promise and thus
|
||||
// returns the MediaKeys object to JS.
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
if (!window || !window->GetExtantDoc()) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<MediaKeys> keys = new MediaKeys(window, aKeySystem);
|
||||
return keys->Init(aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
MediaKeys::Init(ErrorResult& aRv)
|
||||
{
|
||||
@ -329,11 +206,6 @@ MediaKeys::Init(ErrorResult& aRv)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!IsTypeSupported(mKeySystem)) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
mProxy = new CDMProxy(this, mKeySystem);
|
||||
|
||||
// Determine principal (at creation time) of the MediaKeys object.
|
||||
|
@ -53,6 +53,8 @@ public:
|
||||
|
||||
MediaKeys(nsPIDOMWindow* aParentWindow, const nsAString& aKeySystem);
|
||||
|
||||
already_AddRefed<Promise> Init(ErrorResult& aRv);
|
||||
|
||||
nsPIDOMWindow* GetParentObject() const;
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
@ -70,19 +72,6 @@ public:
|
||||
already_AddRefed<Promise> SetServerCertificate(const ArrayBufferViewOrArrayBuffer& aServerCertificate,
|
||||
ErrorResult& aRv);
|
||||
|
||||
// JavaScript: MediaKeys.create()
|
||||
static
|
||||
already_AddRefed<Promise> Create(const GlobalObject& aGlobal,
|
||||
const nsAString& aKeySystem,
|
||||
ErrorResult& aRv);
|
||||
|
||||
// JavaScript: MediaKeys.IsTypeSupported()
|
||||
static IsTypeSupportedResult IsTypeSupported(const GlobalObject& aGlobal,
|
||||
const nsAString& aKeySystem,
|
||||
const Optional<nsAString>& aInitDataType,
|
||||
const Optional<nsAString>& aContentType,
|
||||
const Optional<nsAString>& aCapability);
|
||||
|
||||
already_AddRefed<MediaKeySession> GetSession(const nsAString& aSessionId);
|
||||
|
||||
// Called once a Create() operation succeeds.
|
||||
@ -128,12 +117,7 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
static bool IsTypeSupported(const nsAString& aKeySystem,
|
||||
const Optional<nsAString>& aInitDataType = Optional<nsAString>(),
|
||||
const Optional<nsAString>& aContentType = Optional<nsAString>());
|
||||
|
||||
bool IsInPrivateBrowsing();
|
||||
already_AddRefed<Promise> Init(ErrorResult& aRv);
|
||||
|
||||
// Removes promise from mPromises, and returns it.
|
||||
already_AddRefed<Promise> RetrievePromise(PromiseId aId);
|
||||
|
@ -10,6 +10,7 @@ EXPORTS.mozilla.dom += [
|
||||
'MediaKeyMessageEvent.h',
|
||||
'MediaKeys.h',
|
||||
'MediaKeySession.h',
|
||||
'MediaKeySystemAccess.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla += [
|
||||
@ -29,6 +30,7 @@ UNIFIED_SOURCES += [
|
||||
'MediaKeyMessageEvent.cpp',
|
||||
'MediaKeys.cpp',
|
||||
'MediaKeySession.cpp',
|
||||
'MediaKeySystemAccess.cpp',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
@ -54,14 +54,25 @@ MP4Decoder::SetCDMProxy(CDMProxy* aProxy)
|
||||
#endif
|
||||
|
||||
static bool
|
||||
IsSupportedAudioCodec(const nsAString& aCodec)
|
||||
IsSupportedAudioCodec(const nsAString& aCodec,
|
||||
bool& aOutContainsAAC,
|
||||
bool& aOutContainsMP3)
|
||||
{
|
||||
// AAC-LC, HE-AAC or MP3 in M4A.
|
||||
return aCodec.EqualsASCII("mp4a.40.2") ||
|
||||
// AAC-LC or HE-AAC in M4A.
|
||||
aOutContainsAAC = aCodec.EqualsASCII("mp4a.40.2") ||
|
||||
aCodec.EqualsASCII("mp4a.40.5");
|
||||
if (aOutContainsAAC) {
|
||||
return true;
|
||||
}
|
||||
#ifndef MOZ_GONK_MEDIACODEC // B2G doesn't support MP3 in MP4 yet.
|
||||
aCodec.EqualsASCII("mp3") ||
|
||||
aOutContainsMP3 = aCodec.EqualsASCII("mp3");
|
||||
if (aOutContainsMP3) {
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
aOutContainsMP3 = false;
|
||||
#endif
|
||||
aCodec.EqualsASCII("mp4a.40.5");
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -92,14 +103,20 @@ IsSupportedH264Codec(const nsAString& aCodec)
|
||||
/* static */
|
||||
bool
|
||||
MP4Decoder::CanHandleMediaType(const nsACString& aType,
|
||||
const nsAString& aCodecs)
|
||||
const nsAString& aCodecs,
|
||||
bool& aOutContainsAAC,
|
||||
bool& aOutContainsH264,
|
||||
bool& aOutContainsMP3)
|
||||
{
|
||||
if (!IsEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aType.EqualsASCII("audio/mp4") || aType.EqualsASCII("audio/x-m4a")) {
|
||||
return aCodecs.IsEmpty() || IsSupportedAudioCodec(aCodecs);
|
||||
return aCodecs.IsEmpty() ||
|
||||
IsSupportedAudioCodec(aCodecs,
|
||||
aOutContainsAAC,
|
||||
aOutContainsMP3);
|
||||
}
|
||||
|
||||
if (!aType.EqualsASCII("video/mp4")) {
|
||||
@ -113,7 +130,13 @@ MP4Decoder::CanHandleMediaType(const nsACString& aType,
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
const nsSubstring& token = tokenizer.nextToken();
|
||||
expectMoreTokens = tokenizer.separatorAfterCurrentToken();
|
||||
if (IsSupportedAudioCodec(token) || IsSupportedH264Codec(token)) {
|
||||
if (IsSupportedAudioCodec(token,
|
||||
aOutContainsAAC,
|
||||
aOutContainsMP3)) {
|
||||
continue;
|
||||
}
|
||||
if (IsSupportedH264Codec(token)) {
|
||||
aOutContainsH264 = true;
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
@ -122,8 +145,8 @@ MP4Decoder::CanHandleMediaType(const nsACString& aType,
|
||||
// Last codec name was empty
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -30,9 +30,13 @@ public:
|
||||
|
||||
// Returns true if aMIMEType is a type that we think we can render with the
|
||||
// a MP4 platform decoder backend. If aCodecs is non emtpy, it is filled
|
||||
// with a comma-delimited list of codecs to check support for.
|
||||
// with a comma-delimited list of codecs to check support for. Notes in
|
||||
// out params wether the codecs string contains AAC or H.264.
|
||||
static bool CanHandleMediaType(const nsACString& aMIMEType,
|
||||
const nsAString& aCodecs = EmptyString());
|
||||
const nsAString& aCodecs,
|
||||
bool& aOutContainsAAC,
|
||||
bool& aOutContainsH264,
|
||||
bool& aOutContainsMP3);
|
||||
|
||||
// Returns true if the MP4 backend is preffed on, and we're running on a
|
||||
// platform that is likely to have decoders for the contained formats.
|
||||
|
@ -192,23 +192,37 @@ function SetupEME(test, token, params)
|
||||
|
||||
v.addEventListener("encrypted", function(ev) {
|
||||
Log(token, "got encrypted event");
|
||||
MediaKeys.create(KEYSYSTEM_TYPE).then(function(mediaKeys) {
|
||||
Log(token, "created MediaKeys object ok");
|
||||
mediaKeys.sessions = [];
|
||||
return v.setMediaKeys(mediaKeys);
|
||||
}, bail("failed to create MediaKeys object")).then(function() {
|
||||
Log(token, "set MediaKeys on <video> element ok");
|
||||
|
||||
var session = v.mediaKeys.createSession(test.sessionType);
|
||||
if (params && params.onsessioncreated) {
|
||||
params.onsessioncreated(session);
|
||||
var options = [
|
||||
{
|
||||
initDataType: ev.initDataType,
|
||||
videoType: test.type,
|
||||
}
|
||||
session.addEventListener("message", UpdateSessionFunc(test, token));
|
||||
session.generateRequest(ev.initDataType, ev.initData).then(function() {
|
||||
}, bail(token + " Failed to initialise MediaKeySession"));
|
||||
];
|
||||
navigator.requestMediaKeySystemAccess(KEYSYSTEM_TYPE, options)
|
||||
.then(function(keySystemAccess) {
|
||||
return keySystemAccess.createMediaKeys();
|
||||
}, bail(token + " Failed to request key system access."))
|
||||
|
||||
.then(function(mediaKeys) {
|
||||
Log(token, "created MediaKeys object ok");
|
||||
mediaKeys.sessions = [];
|
||||
return v.setMediaKeys(mediaKeys);
|
||||
}, bail("failed to create MediaKeys object"))
|
||||
|
||||
.then(function() {
|
||||
Log(token, "set MediaKeys on <video> element ok");
|
||||
|
||||
}, onSetKeysFail);
|
||||
var session = v.mediaKeys.createSession(test.sessionType);
|
||||
if (params && params.onsessioncreated) {
|
||||
params.onsessioncreated(session);
|
||||
}
|
||||
session.addEventListener("message", UpdateSessionFunc(test, token));
|
||||
return session.generateRequest(ev.initDataType, ev.initData);
|
||||
}, onSetKeysFail)
|
||||
|
||||
.then(function() {
|
||||
Log(token, "generated request");
|
||||
}, bail(token + " Failed to request key system access2."));
|
||||
});
|
||||
|
||||
return v;
|
||||
}
|
||||
|
@ -364,6 +364,8 @@ skip-if = buildapp == 'b2g' && toolkit != 'gonk' # bug 1082984
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # bug 1043403, bug 1057908
|
||||
[test_eme_playback.html]
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # bug 1043403, bug 1057908
|
||||
[test_eme_requestKeySystemAccess.html]
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # bug 1043403, bug 1057908
|
||||
[test_eme_stream_capture_blocked.html]
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # bug 1043403, bug 1057908
|
||||
[test_empty_resource.html]
|
||||
|
@ -51,8 +51,6 @@ function startTest(test, token)
|
||||
var gotPlaying = false;
|
||||
|
||||
v.addEventListener("encrypted", function(ev) {
|
||||
ok(MediaKeys.isTypeSupported(KEYSYSTEM_TYPE, ev.initDataType, test.type),
|
||||
TimeStamp(token) + " MediaKeys should support this keysystem");
|
||||
gotEncrypted = true;
|
||||
});
|
||||
|
||||
@ -88,23 +86,7 @@ function startTest(test, token)
|
||||
LoadTest(test, v, token).then(function(){v.play();}, bail(token + " failed to load"));
|
||||
}
|
||||
|
||||
function testIsTypeSupported()
|
||||
{
|
||||
var t = MediaKeys.isTypeSupported;
|
||||
const clearkey = "org.w3.clearkey";
|
||||
ok(!t("bogus", "bogon", "video/bogus"), "Invalid type.");
|
||||
ok(t(clearkey), "ClearKey supported.");
|
||||
ok(!t(clearkey, "bogus"), "ClearKey bogus initDataType not supported.");
|
||||
ok(t(clearkey, "cenc"), "ClearKey/cenc should be supported.");
|
||||
ok(!t(clearkey, "cenc", "bogus"), "ClearKey/cenc bogus content type should be supported.");
|
||||
ok(t(clearkey, "cenc", 'video/mp4'), "ClearKey/cenc video/mp4 supported.");
|
||||
ok(t(clearkey, "cenc", 'video/mp4; codecs="avc1.4d4015,mp4a.40.2"'), "ClearKey/cenc H.264/AAC supported.");
|
||||
ok(t(clearkey, "cenc", 'audio/mp4'), "ClearKey/cenc audio/mp4 supported.");
|
||||
ok(t(clearkey, "cenc", 'audio/mp4; codecs="mp4a.40.2"'), "ClearKey/cenc AAC LC supported.");
|
||||
}
|
||||
|
||||
function beginTest() {
|
||||
testIsTypeSupported();
|
||||
manager.runTests(gEMETests, startTest);
|
||||
}
|
||||
|
||||
|
293
dom/media/test/test_eme_requestKeySystemAccess.html
Normal file
293
dom/media/test/test_eme_requestKeySystemAccess.html
Normal file
@ -0,0 +1,293 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test Encrypted Media Extensions</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<script type="text/javascript" src="manifest.js"></script>
|
||||
<script type="text/javascript" src="eme.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
function Test(test) {
|
||||
var name = "'" + test.name + "'";
|
||||
return new Promise(function(resolve, reject) {
|
||||
var p;
|
||||
if (test.options) {
|
||||
p = navigator.requestMediaKeySystemAccess(test.keySystem, test.options);
|
||||
} else {
|
||||
p = navigator.requestMediaKeySystemAccess(test.keySystem);
|
||||
}
|
||||
p.then(
|
||||
function(keySystemAccess) {
|
||||
ok(test.shouldPass, name + " passed and was expected to " + (test.shouldPass ? "pass" : "fail"));
|
||||
resolve();
|
||||
},
|
||||
function(ex) {
|
||||
if (test.shouldPass) {
|
||||
info(name + " failed: " + ex);
|
||||
}
|
||||
ok(!test.shouldPass, name + " failed and was expected to " + (test.shouldPass ? "pass" : "fail"));
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const CLEARKEY_ID = 'org.w3.clearkey';
|
||||
|
||||
var tests = [
|
||||
{
|
||||
name: 'Empty keySystem string',
|
||||
keySystem: '',
|
||||
options: [ ],
|
||||
shouldPass: false,
|
||||
},
|
||||
{
|
||||
name: 'Empty options specified',
|
||||
keySystem: CLEARKEY_ID,
|
||||
options: [ ],
|
||||
shouldPass: false,
|
||||
},
|
||||
{
|
||||
name: 'Undefined options',
|
||||
keySystem: CLEARKEY_ID,
|
||||
shouldPass: true,
|
||||
},
|
||||
{
|
||||
name: 'Basic MP4 cenc',
|
||||
keySystem: CLEARKEY_ID,
|
||||
options: [
|
||||
{
|
||||
initDataType: 'cenc',
|
||||
videoType: 'video/mp4',
|
||||
}
|
||||
],
|
||||
shouldPass: true,
|
||||
},
|
||||
{
|
||||
name: 'Invalid keysystem failure',
|
||||
keySystem: 'bogusKeySystem',
|
||||
options: [],
|
||||
shouldPass: false,
|
||||
},
|
||||
{
|
||||
name: 'Invalid initDataType',
|
||||
keySystem: CLEARKEY_ID,
|
||||
options: [
|
||||
{
|
||||
initDataType: 'bogus',
|
||||
}
|
||||
],
|
||||
shouldPass: false,
|
||||
},
|
||||
{
|
||||
name: 'Invalid videoType',
|
||||
keySystem: CLEARKEY_ID,
|
||||
options: [
|
||||
{
|
||||
initDataType: 'cenc',
|
||||
videoType: 'video/bogus',
|
||||
}
|
||||
],
|
||||
shouldPass: false,
|
||||
},
|
||||
{
|
||||
name: 'Invalid statefulness',
|
||||
keySystem: CLEARKEY_ID,
|
||||
options: [
|
||||
{
|
||||
initDataType: 'cenc',
|
||||
videoType: 'video/mp4',
|
||||
stateful: 'bogus',
|
||||
}
|
||||
],
|
||||
shouldPass: false,
|
||||
},
|
||||
{
|
||||
name: 'Invalid uniqueidentifier',
|
||||
keySystem: CLEARKEY_ID,
|
||||
options: [
|
||||
{
|
||||
initDataType: 'cenc',
|
||||
videoType: 'video/mp4',
|
||||
uniqueidentifier: 'bogus',
|
||||
}
|
||||
],
|
||||
shouldPass: false,
|
||||
},
|
||||
{
|
||||
name: 'Audio capabilities not supported by CLEARKEY_ID',
|
||||
keySystem: CLEARKEY_ID,
|
||||
options: [
|
||||
{
|
||||
initDataType: 'cenc',
|
||||
videoType: 'video/mp4',
|
||||
audioCapability: 'bogus',
|
||||
}
|
||||
],
|
||||
shouldPass: false,
|
||||
},
|
||||
{
|
||||
name: 'Video capabilities not supported by CLEARKEY_ID',
|
||||
keySystem: CLEARKEY_ID,
|
||||
options: [
|
||||
{
|
||||
initDataType: 'cenc',
|
||||
videoType: 'video/mp4',
|
||||
videoCapability: 'bogus',
|
||||
}
|
||||
],
|
||||
shouldPass: false,
|
||||
},
|
||||
{
|
||||
name: 'Invalid option followed by valid',
|
||||
keySystem: CLEARKEY_ID,
|
||||
options: [
|
||||
{
|
||||
bogus: 'bogon',
|
||||
},
|
||||
{
|
||||
initDataType: 'cenc',
|
||||
videoType: 'video/mp4',
|
||||
}
|
||||
],
|
||||
shouldPass: true,
|
||||
},
|
||||
{
|
||||
name: 'MP4 audio container',
|
||||
keySystem: CLEARKEY_ID,
|
||||
options: [
|
||||
{
|
||||
initDataType: 'cenc',
|
||||
audioType: 'audio/mp4',
|
||||
}
|
||||
],
|
||||
shouldPass: true,
|
||||
},
|
||||
{
|
||||
name: 'MP4 audio container with AAC-LC',
|
||||
keySystem: CLEARKEY_ID,
|
||||
options: [
|
||||
{
|
||||
initDataType: 'cenc',
|
||||
audioType: 'audio/mp4; codecs="mp4a.40.2"',
|
||||
}
|
||||
],
|
||||
shouldPass: true,
|
||||
},
|
||||
{
|
||||
name: 'MP4 audio container with invalid codecs',
|
||||
keySystem: CLEARKEY_ID,
|
||||
options: [
|
||||
{
|
||||
initDataType: 'cenc',
|
||||
audioType: 'audio/mp4; codecs="bogus"',
|
||||
}
|
||||
],
|
||||
shouldPass: false,
|
||||
},
|
||||
{
|
||||
name: 'MP4 audio container with mp3 is unsupported',
|
||||
keySystem: CLEARKEY_ID,
|
||||
options: [
|
||||
{
|
||||
initDataType: 'cenc',
|
||||
audioType: 'audio/mp4; codecs="mp3"',
|
||||
}
|
||||
],
|
||||
shouldPass: false,
|
||||
},
|
||||
{
|
||||
name: 'MP4 video container with mp3 and h264 is unsupported',
|
||||
keySystem: CLEARKEY_ID,
|
||||
options: [
|
||||
{
|
||||
initDataType: 'cenc',
|
||||
videoType: 'video/mp4; codecs="avc1.42E01E,mp3"',
|
||||
}
|
||||
],
|
||||
shouldPass: false,
|
||||
},
|
||||
{
|
||||
name: 'MP4 video container with constrained baseline h.264',
|
||||
keySystem: CLEARKEY_ID,
|
||||
options: [
|
||||
{
|
||||
initDataType: 'cenc',
|
||||
audioType: 'video/mp4; codecs="avc1.42E01E"',
|
||||
}
|
||||
],
|
||||
shouldPass: true,
|
||||
},
|
||||
{
|
||||
name: 'MP4 video container with invalid codecs',
|
||||
keySystem: CLEARKEY_ID,
|
||||
options: [
|
||||
{
|
||||
initDataType: 'cenc',
|
||||
videoType: 'video/mp4; codecs="bogus"',
|
||||
}
|
||||
],
|
||||
shouldPass: false,
|
||||
},
|
||||
{
|
||||
name: 'MP4 video container with constrained baseline h.264 and AAC-LC',
|
||||
keySystem: CLEARKEY_ID,
|
||||
options: [
|
||||
{
|
||||
initDataType: 'cenc',
|
||||
videoType: 'video/mp4; codecs="avc1.42E01E,mp4a.40.2"',
|
||||
}
|
||||
],
|
||||
shouldPass: true,
|
||||
},
|
||||
{
|
||||
name: 'MP4 audio and video type both specified',
|
||||
keySystem: CLEARKEY_ID,
|
||||
options: [
|
||||
{
|
||||
initDataType: 'cenc',
|
||||
videoType: 'video/mp4; codecs="avc1.42E01E"',
|
||||
audioType: 'audio/mp4; codecs="mp4a.40.2"',
|
||||
}
|
||||
],
|
||||
shouldPass: true,
|
||||
},
|
||||
{
|
||||
name: 'WebM CLEARKEY_ID not supported',
|
||||
keySystem: CLEARKEY_ID,
|
||||
options: [
|
||||
{
|
||||
initDataType: 'webm',
|
||||
videoType: 'video/webm',
|
||||
}
|
||||
],
|
||||
shouldPass: false,
|
||||
},
|
||||
];
|
||||
|
||||
function beginTest() {
|
||||
Promise.all(tests.map(Test)).then(function() { SimpleTest.finish(); });
|
||||
}
|
||||
|
||||
var prefs = [
|
||||
[ "media.mediasource.enabled", true ],
|
||||
[ "media.mediasource.mp4.enabled", true ],
|
||||
];
|
||||
|
||||
if (/Linux/.test(navigator.userAgent) ||
|
||||
!document.createElement('video').canPlayType("video/mp4")) {
|
||||
// XXX remove once we have mp4 PlatformDecoderModules on all platforms.
|
||||
prefs.push([ "media.fragmented-mp4.exposed", true ]);
|
||||
prefs.push([ "media.fragmented-mp4.use-blank-decoder", true ]);
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({ "set" : prefs }, beginTest);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -661,6 +661,8 @@ var interfaceNamesInGlobalScope =
|
||||
{name: "MediaKeys", pref: "media.eme.enabled"},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "MediaKeySession", pref: "media.eme.enabled"},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "MediaKeySystemAccess", pref: "media.eme.enabled"},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "MediaKeyMessageEvent", pref: "media.eme.enabled"},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
34
dom/webidl/MediaKeySystemAccess.webidl
Normal file
34
dom/webidl/MediaKeySystemAccess.webidl
Normal file
@ -0,0 +1,34 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html
|
||||
*
|
||||
* Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved.
|
||||
* W3C liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
enum MediaKeysRequirement {
|
||||
"required",
|
||||
"optional",
|
||||
"disallowed"
|
||||
};
|
||||
|
||||
dictionary MediaKeySystemOptions {
|
||||
DOMString initDataType = "";
|
||||
DOMString audioType = "";
|
||||
DOMString audioCapability = "";
|
||||
DOMString videoType = "";
|
||||
DOMString videoCapability = "";
|
||||
MediaKeysRequirement uniqueidentifier = "optional";
|
||||
MediaKeysRequirement stateful = "optional";
|
||||
};
|
||||
|
||||
[Pref="media.eme.enabled"]
|
||||
interface MediaKeySystemAccess {
|
||||
readonly attribute DOMString keySystem;
|
||||
[NewObject, Throws]
|
||||
Promise<MediaKeys> createMediaKeys();
|
||||
};
|
@ -22,9 +22,4 @@ interface MediaKeys {
|
||||
|
||||
[NewObject, Throws]
|
||||
Promise<void> setServerCertificate((ArrayBufferView or ArrayBuffer) serverCertificate);
|
||||
|
||||
[Throws,NewObject]
|
||||
static Promise<MediaKeys> create(DOMString keySystem);
|
||||
static IsTypeSupportedResult isTypeSupported(DOMString keySystem, optional DOMString initDataType, optional DOMString contentType, optional DOMString capability);
|
||||
|
||||
};
|
||||
|
@ -397,3 +397,12 @@ partial interface Navigator {
|
||||
[Pref="dom.tv.enabled", CheckPermissions="tv", Func="Navigator::HasTVSupport"]
|
||||
readonly attribute TVManager? tv;
|
||||
};
|
||||
|
||||
#ifdef MOZ_EME
|
||||
partial interface Navigator {
|
||||
[Pref="media.eme.enabled", Throws, NewObject]
|
||||
Promise<MediaKeySystemAccess>
|
||||
requestMediaKeySystemAccess(DOMString keySystem,
|
||||
optional sequence<MediaKeySystemOptions> supportedConfigurations);
|
||||
};
|
||||
#endif
|
||||
|
@ -798,4 +798,5 @@ if CONFIG['MOZ_EME']:
|
||||
'MediaKeyMessageEvent.webidl',
|
||||
'MediaKeys.webidl',
|
||||
'MediaKeySession.webidl',
|
||||
'MediaKeySystemAccess.webidl',
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user