forked from mirrors/gecko-dev
Bug 1846848 - part5 : display MFCDM capabilites in about:support. r=fluent-reviewers,gerard-majax,jolin,niklas
This patch implements retrieving the capabilities from MFCDMs. I will add non-MFCDM support in following patches, eg. Widevine L3, and ClearKey. Differential Revision: https://phabricator.services.mozilla.com/D194837
This commit is contained in:
parent
45a1d5d754
commit
d9836bbabe
13 changed files with 311 additions and 44 deletions
|
|
@ -52,6 +52,8 @@
|
||||||
#include "mozilla/ipc/UtilityProcessManager.h"
|
#include "mozilla/ipc/UtilityProcessManager.h"
|
||||||
#include "mozilla/ipc/UtilityProcessHost.h"
|
#include "mozilla/ipc/UtilityProcessHost.h"
|
||||||
#include "mozilla/net/UrlClassifierFeatureFactory.h"
|
#include "mozilla/net/UrlClassifierFeatureFactory.h"
|
||||||
|
#include "mozilla/RemoteDecoderManagerChild.h"
|
||||||
|
#include "mozilla/KeySystemConfig.h"
|
||||||
#include "mozilla/WheelHandlingHelper.h"
|
#include "mozilla/WheelHandlingHelper.h"
|
||||||
#include "IOActivityMonitor.h"
|
#include "IOActivityMonitor.h"
|
||||||
#include "nsNativeTheme.h"
|
#include "nsNativeTheme.h"
|
||||||
|
|
@ -74,6 +76,10 @@
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MOZ_WMF_CDM
|
||||||
|
# include "mozilla/MFCDMParent.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mozilla::dom {
|
namespace mozilla::dom {
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
|
|
@ -1922,4 +1928,20 @@ void ChromeUtils::NotifyDevToolsClosed(GlobalObject& aGlobal) {
|
||||||
ChromeUtils::sDevToolsOpenedCount--;
|
ChromeUtils::sDevToolsOpenedCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_WMF_CDM
|
||||||
|
/* static */
|
||||||
|
already_AddRefed<Promise> ChromeUtils::GetWMFContentDecryptionModuleInformation(
|
||||||
|
GlobalObject& aGlobal, ErrorResult& aRv) {
|
||||||
|
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||||
|
MOZ_ASSERT(global);
|
||||||
|
RefPtr<Promise> domPromise = Promise::Create(global, aRv);
|
||||||
|
if (NS_WARN_IF(aRv.Failed())) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(domPromise);
|
||||||
|
MFCDMCapabilities::GetAllKeySystemsCapabilities(domPromise);
|
||||||
|
return domPromise.forget();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace mozilla::dom
|
} // namespace mozilla::dom
|
||||||
|
|
|
||||||
|
|
@ -308,6 +308,11 @@ class ChromeUtils {
|
||||||
GlobalObject& aGlobal, JSRFPTarget aTarget,
|
GlobalObject& aGlobal, JSRFPTarget aTarget,
|
||||||
const Nullable<uint64_t>& aOverriddenFingerprintingSettings);
|
const Nullable<uint64_t>& aOverriddenFingerprintingSettings);
|
||||||
|
|
||||||
|
#ifdef MOZ_WMF_CDM
|
||||||
|
static already_AddRefed<Promise> GetWMFContentDecryptionModuleInformation(
|
||||||
|
GlobalObject& aGlobal, ErrorResult& aRv);
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Number of DevTools session debugging the current process
|
// Number of DevTools session debugging the current process
|
||||||
static std::atomic<uint32_t> sDevToolsOpenedCount;
|
static std::atomic<uint32_t> sDevToolsOpenedCount;
|
||||||
|
|
|
||||||
|
|
@ -297,6 +297,15 @@ namespace ChromeUtils {
|
||||||
LibcConstants getLibcConstants();
|
LibcConstants getLibcConstants();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MOZ_WMF_CDM
|
||||||
|
/**
|
||||||
|
* Returns the information about all Media Foundation based content decryption
|
||||||
|
* modules, which would include key system names and their capabilities.
|
||||||
|
*/
|
||||||
|
[NewObject]
|
||||||
|
Promise<sequence<CDMInformation>> getWMFContentDecryptionModuleInformation();
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IF YOU ADD NEW METHODS HERE, MAKE SURE THEY ARE THREAD-SAFE.
|
* IF YOU ADD NEW METHODS HERE, MAKE SURE THEY ARE THREAD-SAFE.
|
||||||
*/
|
*/
|
||||||
|
|
@ -1079,3 +1088,8 @@ dictionary LibcConstants {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
dictionary CDMInformation {
|
||||||
|
required DOMString keySystemName;
|
||||||
|
required DOMString capabilities;
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,11 @@
|
||||||
#include "mozilla/dom/KeySystemNames.h"
|
#include "mozilla/dom/KeySystemNames.h"
|
||||||
#include "mozilla/dom/UnionTypes.h"
|
#include "mozilla/dom/UnionTypes.h"
|
||||||
|
|
||||||
|
#ifdef MOZ_WMF_CDM
|
||||||
|
# include "mozilla/PMFCDM.h"
|
||||||
|
# include "KeySystemConfig.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
LogModule* GetEMELog() {
|
LogModule* GetEMELog() {
|
||||||
|
|
@ -142,4 +147,45 @@ const char* EncryptionSchemeStr(const CryptoScheme& aScheme) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_WMF_CDM
|
||||||
|
void MFCDMCapabilitiesIPDLToKeySystemConfig(
|
||||||
|
const MFCDMCapabilitiesIPDL& aCDMConfig,
|
||||||
|
KeySystemConfig& aKeySystemConfig) {
|
||||||
|
aKeySystemConfig.mKeySystem = aCDMConfig.keySystem();
|
||||||
|
|
||||||
|
for (const auto& type : aCDMConfig.initDataTypes()) {
|
||||||
|
aKeySystemConfig.mInitDataTypes.AppendElement(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& type : aCDMConfig.sessionTypes()) {
|
||||||
|
aKeySystemConfig.mSessionTypes.AppendElement(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& c : aCDMConfig.videoCapabilities()) {
|
||||||
|
if (!c.robustness().IsEmpty() &&
|
||||||
|
!aKeySystemConfig.mVideoRobustness.Contains(c.robustness())) {
|
||||||
|
aKeySystemConfig.mVideoRobustness.AppendElement(c.robustness());
|
||||||
|
}
|
||||||
|
aKeySystemConfig.mMP4.SetCanDecryptAndDecode(
|
||||||
|
NS_ConvertUTF16toUTF8(c.contentType()));
|
||||||
|
}
|
||||||
|
for (const auto& c : aCDMConfig.audioCapabilities()) {
|
||||||
|
if (!c.robustness().IsEmpty() &&
|
||||||
|
!aKeySystemConfig.mAudioRobustness.Contains(c.robustness())) {
|
||||||
|
aKeySystemConfig.mAudioRobustness.AppendElement(c.robustness());
|
||||||
|
}
|
||||||
|
aKeySystemConfig.mMP4.SetCanDecryptAndDecode(
|
||||||
|
NS_ConvertUTF16toUTF8(c.contentType()));
|
||||||
|
}
|
||||||
|
aKeySystemConfig.mPersistentState = aCDMConfig.persistentState();
|
||||||
|
aKeySystemConfig.mDistinctiveIdentifier = aCDMConfig.distinctiveID();
|
||||||
|
for (const auto& scheme : aCDMConfig.encryptionSchemes()) {
|
||||||
|
aKeySystemConfig.mEncryptionSchemes.AppendElement(
|
||||||
|
NS_ConvertUTF8toUTF16(EncryptionSchemeStr(scheme)));
|
||||||
|
}
|
||||||
|
EME_LOG("New Capabilities=%s",
|
||||||
|
NS_ConvertUTF16toUTF8(aKeySystemConfig.GetDebugInfo()).get());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,10 @@
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
enum class CryptoScheme : uint8_t;
|
enum class CryptoScheme : uint8_t;
|
||||||
|
#ifdef MOZ_WMF_CDM
|
||||||
|
class MFCDMCapabilitiesIPDL;
|
||||||
|
#endif
|
||||||
|
struct KeySystemConfig;
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
class ArrayBufferViewOrArrayBuffer;
|
class ArrayBufferViewOrArrayBuffer;
|
||||||
|
|
@ -82,6 +86,11 @@ bool IsHardwareDecryptionSupported(
|
||||||
|
|
||||||
const char* EncryptionSchemeStr(const CryptoScheme& aScheme);
|
const char* EncryptionSchemeStr(const CryptoScheme& aScheme);
|
||||||
|
|
||||||
|
#ifdef MOZ_WMF_CDM
|
||||||
|
void MFCDMCapabilitiesIPDLToKeySystemConfig(
|
||||||
|
const MFCDMCapabilitiesIPDL& aCDMConfig, KeySystemConfig& aKeySystemConfig);
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
#endif // EME_LOG_H_
|
#endif // EME_LOG_H_
|
||||||
|
|
|
||||||
|
|
@ -29,47 +29,6 @@ bool WMFCDMImpl::Supports(const nsAString& aKeySystem) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MFCDMCapabilitiesIPDLToKeySystemConfig(
|
|
||||||
const MFCDMCapabilitiesIPDL& aCDMConfig,
|
|
||||||
KeySystemConfig& aKeySystemConfig) {
|
|
||||||
aKeySystemConfig.mKeySystem = aCDMConfig.keySystem();
|
|
||||||
|
|
||||||
for (const auto& type : aCDMConfig.initDataTypes()) {
|
|
||||||
aKeySystemConfig.mInitDataTypes.AppendElement(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& type : aCDMConfig.sessionTypes()) {
|
|
||||||
aKeySystemConfig.mSessionTypes.AppendElement(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& c : aCDMConfig.videoCapabilities()) {
|
|
||||||
if (!c.robustness().IsEmpty() &&
|
|
||||||
!aKeySystemConfig.mVideoRobustness.Contains(c.robustness())) {
|
|
||||||
aKeySystemConfig.mVideoRobustness.AppendElement(c.robustness());
|
|
||||||
}
|
|
||||||
aKeySystemConfig.mMP4.SetCanDecryptAndDecode(
|
|
||||||
NS_ConvertUTF16toUTF8(c.contentType()));
|
|
||||||
}
|
|
||||||
for (const auto& c : aCDMConfig.audioCapabilities()) {
|
|
||||||
if (!c.robustness().IsEmpty() &&
|
|
||||||
!aKeySystemConfig.mAudioRobustness.Contains(c.robustness())) {
|
|
||||||
aKeySystemConfig.mAudioRobustness.AppendElement(c.robustness());
|
|
||||||
}
|
|
||||||
aKeySystemConfig.mMP4.SetCanDecryptAndDecode(
|
|
||||||
NS_ConvertUTF16toUTF8(c.contentType()));
|
|
||||||
}
|
|
||||||
aKeySystemConfig.mPersistentState = aCDMConfig.persistentState();
|
|
||||||
aKeySystemConfig.mDistinctiveIdentifier = aCDMConfig.distinctiveID();
|
|
||||||
|
|
||||||
for (const auto& scheme : aCDMConfig.encryptionSchemes()) {
|
|
||||||
aKeySystemConfig.mEncryptionSchemes.AppendElement(
|
|
||||||
NS_ConvertUTF8toUTF16(CryptoSchemeToString(scheme)));
|
|
||||||
}
|
|
||||||
|
|
||||||
EME_LOG("New Capabilities=%s",
|
|
||||||
NS_ConvertUTF16toUTF8(aKeySystemConfig.GetDebugInfo()).get());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WMFCDMImpl::GetCapabilities(nsTArray<KeySystemConfig>& aOutConfigs) {
|
bool WMFCDMImpl::GetCapabilities(nsTArray<KeySystemConfig>& aOutConfigs) {
|
||||||
nsCOMPtr<nsISerialEventTarget> backgroundTaskQueue;
|
nsCOMPtr<nsISerialEventTarget> backgroundTaskQueue;
|
||||||
NS_CreateBackgroundTaskQueue(__func__, getter_AddRefs(backgroundTaskQueue));
|
NS_CreateBackgroundTaskQueue(__func__, getter_AddRefs(backgroundTaskQueue));
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,11 @@
|
||||||
#include <propkeydef.h> // For DEFINE_PROPERTYKEY() definition
|
#include <propkeydef.h> // For DEFINE_PROPERTYKEY() definition
|
||||||
#include <propvarutil.h> // For InitPropVariantFrom*()
|
#include <propvarutil.h> // For InitPropVariantFrom*()
|
||||||
|
|
||||||
|
#include "mozilla/dom/Promise.h"
|
||||||
#include "mozilla/dom/KeySystemNames.h"
|
#include "mozilla/dom/KeySystemNames.h"
|
||||||
|
#include "mozilla/ipc/UtilityAudioDecoderChild.h"
|
||||||
|
#include "mozilla/ipc/UtilityProcessManager.h"
|
||||||
|
#include "mozilla/ipc/UtilityProcessParent.h"
|
||||||
#include "mozilla/EMEUtils.h"
|
#include "mozilla/EMEUtils.h"
|
||||||
#include "mozilla/StaticMutex.h"
|
#include "mozilla/StaticMutex.h"
|
||||||
#include "mozilla/StaticPrefs_media.h"
|
#include "mozilla/StaticPrefs_media.h"
|
||||||
|
|
@ -1067,6 +1071,76 @@ already_AddRefed<MFCDMProxy> MFCDMParent::GetMFCDMProxy() {
|
||||||
return proxy.forget();
|
return proxy.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
void MFCDMCapabilities::GetAllKeySystemsCapabilities(dom::Promise* aPromise) {
|
||||||
|
const static auto kSandboxKind = ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM;
|
||||||
|
LaunchMFCDMProcessIfNeeded(kSandboxKind)
|
||||||
|
->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
[promise = RefPtr(aPromise)]() {
|
||||||
|
RefPtr<ipc::UtilityAudioDecoderChild> uadc =
|
||||||
|
ipc::UtilityAudioDecoderChild::GetSingleton(kSandboxKind);
|
||||||
|
if (NS_WARN_IF(!uadc)) {
|
||||||
|
promise->MaybeReject(NS_ERROR_FAILURE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uadc->GetKeySystemCapabilities(promise);
|
||||||
|
},
|
||||||
|
[promise = RefPtr(aPromise)](nsresult aError) {
|
||||||
|
promise->MaybeReject(NS_ERROR_FAILURE);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
RefPtr<GenericNonExclusivePromise>
|
||||||
|
MFCDMCapabilities::LaunchMFCDMProcessIfNeeded(ipc::SandboxingKind aSandbox) {
|
||||||
|
MOZ_ASSERT(aSandbox == ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM);
|
||||||
|
RefPtr<ipc::UtilityProcessManager> utilityProc =
|
||||||
|
ipc::UtilityProcessManager::GetSingleton();
|
||||||
|
if (NS_WARN_IF(!utilityProc)) {
|
||||||
|
NS_WARNING("Failed to get UtilityProcessManager");
|
||||||
|
return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
|
||||||
|
__func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the MFCDM process exists or not. If not, launch it.
|
||||||
|
if (utilityProc->Process(aSandbox)) {
|
||||||
|
return GenericNonExclusivePromise::CreateAndResolve(true, __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<ipc::UtilityAudioDecoderChild> uadc =
|
||||||
|
ipc::UtilityAudioDecoderChild::GetSingleton(aSandbox);
|
||||||
|
if (NS_WARN_IF(!uadc)) {
|
||||||
|
NS_WARNING("Failed to get UtilityAudioDecoderChild");
|
||||||
|
return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
|
||||||
|
__func__);
|
||||||
|
}
|
||||||
|
return utilityProc->StartUtility(uadc, aSandbox)
|
||||||
|
->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
[uadc, utilityProc, aSandbox]() {
|
||||||
|
RefPtr<ipc::UtilityProcessParent> parent =
|
||||||
|
utilityProc->GetProcessParent(aSandbox);
|
||||||
|
if (!parent) {
|
||||||
|
NS_WARNING("UtilityAudioDecoderParent lost in the middle");
|
||||||
|
return GenericNonExclusivePromise::CreateAndReject(
|
||||||
|
NS_ERROR_FAILURE, __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!uadc->CanSend()) {
|
||||||
|
NS_WARNING("UtilityAudioDecoderChild lost in the middle");
|
||||||
|
return GenericNonExclusivePromise::CreateAndReject(
|
||||||
|
NS_ERROR_FAILURE, __func__);
|
||||||
|
}
|
||||||
|
return GenericNonExclusivePromise::CreateAndResolve(true, __func__);
|
||||||
|
},
|
||||||
|
[](nsresult aError) {
|
||||||
|
NS_WARNING("Failed to start the MFCDM process!");
|
||||||
|
return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
|
||||||
|
__func__);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#undef MFCDM_REJECT_IF_FAILED
|
#undef MFCDM_REJECT_IF_FAILED
|
||||||
#undef MFCDM_REJECT_IF
|
#undef MFCDM_REJECT_IF
|
||||||
#undef MFCDM_RETURN_IF_FAILED
|
#undef MFCDM_RETURN_IF_FAILED
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,16 @@ class MFCDMParent final : public PMFCDMParent {
|
||||||
MediaEventListener mExpirationListener;
|
MediaEventListener mExpirationListener;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A helper class to display CDM capabilites in `about:support`.
|
||||||
|
class MFCDMCapabilities {
|
||||||
|
public:
|
||||||
|
static void GetAllKeySystemsCapabilities(dom::Promise* aPromise);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static RefPtr<GenericNonExclusivePromise> LaunchMFCDMProcessIfNeeded(
|
||||||
|
ipc::SandboxingKind aSandbox);
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
#endif // DOM_MEDIA_IPC_MFCDMPARENT_H_
|
#endif // DOM_MEDIA_IPC_MFCDMPARENT_H_
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MOZ_WMF_CDM
|
#ifdef MOZ_WMF_CDM
|
||||||
|
# include "mozilla/dom/Promise.h"
|
||||||
# include "mozilla/EMEUtils.h"
|
# include "mozilla/EMEUtils.h"
|
||||||
# include "mozilla/PMFCDM.h"
|
# include "mozilla/PMFCDM.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -179,11 +180,14 @@ bool UtilityAudioDecoderChild::CreateVideoBridge() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MOZ_WMF_CDM
|
#ifdef MOZ_WMF_CDM
|
||||||
void UtilityAudioDecoderChild::GetKeySystemCapabilities() {
|
void UtilityAudioDecoderChild::GetKeySystemCapabilities(
|
||||||
|
dom::Promise* aPromise) {
|
||||||
EME_LOG("Ask capabilities for all supported CDMs");
|
EME_LOG("Ask capabilities for all supported CDMs");
|
||||||
SendGetKeySystemCapabilities()->Then(
|
SendGetKeySystemCapabilities()->Then(
|
||||||
NS_GetCurrentThread(), __func__,
|
NS_GetCurrentThread(), __func__,
|
||||||
[](CopyableTArray<MFCDMCapabilitiesIPDL>&& result) {
|
[promise = RefPtr<dom::Promise>(aPromise)](
|
||||||
|
CopyableTArray<MFCDMCapabilitiesIPDL>&& result) {
|
||||||
|
FallibleTArray<dom::CDMInformation> cdmInfo;
|
||||||
for (const auto& capabilities : result) {
|
for (const auto& capabilities : result) {
|
||||||
EME_LOG("Received capabilities for %s",
|
EME_LOG("Received capabilities for %s",
|
||||||
NS_ConvertUTF16toUTF8(capabilities.keySystem()).get());
|
NS_ConvertUTF16toUTF8(capabilities.keySystem()).get());
|
||||||
|
|
@ -199,7 +203,18 @@ void UtilityAudioDecoderChild::GetKeySystemCapabilities() {
|
||||||
EME_LOG(" capabilities: encryptionScheme=%s",
|
EME_LOG(" capabilities: encryptionScheme=%s",
|
||||||
EncryptionSchemeStr(e));
|
EncryptionSchemeStr(e));
|
||||||
}
|
}
|
||||||
|
auto* info = cdmInfo.AppendElement(fallible);
|
||||||
|
if (!info) {
|
||||||
|
promise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
info->mKeySystemName = capabilities.keySystem();
|
||||||
|
|
||||||
|
KeySystemConfig config;
|
||||||
|
MFCDMCapabilitiesIPDLToKeySystemConfig(capabilities, config);
|
||||||
|
info->mCapabilities = config.GetDebugInfo();
|
||||||
|
}
|
||||||
|
promise->MaybeResolve(cdmInfo);
|
||||||
},
|
},
|
||||||
[](const mozilla::ipc::ResponseRejectReason& aReason) {
|
[](const mozilla::ipc::ResponseRejectReason& aReason) {
|
||||||
EME_LOG("IPC failure for GetKeySystemCapabilities!");
|
EME_LOG("IPC failure for GetKeySystemCapabilities!");
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ class UtilityAudioDecoderChild final : public PUtilityAudioDecoderChild
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MOZ_WMF_CDM
|
#ifdef MOZ_WMF_CDM
|
||||||
void GetKeySystemCapabilities();
|
void GetKeySystemCapabilities(dom::Promise* aPromise);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -1105,6 +1105,94 @@ var snapshotFormatters = {
|
||||||
.catch(e => {});
|
.catch(e => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createCDMInfoRow(cdmInfo) {
|
||||||
|
function findElementInArray(array, name) {
|
||||||
|
const rv = array.find(element => element.includes(name));
|
||||||
|
return rv ? rv.split("=")[1] : "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAudioRobustness(array) {
|
||||||
|
return findElementInArray(array, "audio-robustness");
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVideoRobustness(array) {
|
||||||
|
return findElementInArray(array, "video-robustness");
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSupportedCodecs(array) {
|
||||||
|
const mp4Content = findElementInArray(array, "MP4");
|
||||||
|
const webContent = findElementInArray(array, "WEBM");
|
||||||
|
|
||||||
|
const mp4DecodingAndDecryptingCodecs = mp4Content
|
||||||
|
.match(/decoding-and-decrypting:\[([^\]]*)\]/)[1]
|
||||||
|
.split(",");
|
||||||
|
const webmDecodingAndDecryptingCodecs = webContent
|
||||||
|
.match(/decoding-and-decrypting:\[([^\]]*)\]/)[1]
|
||||||
|
.split(",");
|
||||||
|
|
||||||
|
const mp4DecryptingOnlyCodecs = mp4Content
|
||||||
|
.match(/decrypting-only:\[([^\]]*)\]/)[1]
|
||||||
|
.split(",");
|
||||||
|
const webmDecryptingOnlyCodecs = webContent
|
||||||
|
.match(/decrypting-only:\[([^\]]*)\]/)[1]
|
||||||
|
.split(",");
|
||||||
|
|
||||||
|
// Combine and get unique codecs for decoding-and-decrypting (always)
|
||||||
|
// and decrypting-only (only set when it's not empty)
|
||||||
|
let rv = {};
|
||||||
|
rv.decodingAndDecrypting = [
|
||||||
|
...new Set(
|
||||||
|
[
|
||||||
|
...mp4DecodingAndDecryptingCodecs,
|
||||||
|
...webmDecodingAndDecryptingCodecs,
|
||||||
|
].filter(Boolean)
|
||||||
|
),
|
||||||
|
];
|
||||||
|
let temp = [
|
||||||
|
...new Set(
|
||||||
|
[...mp4DecryptingOnlyCodecs, ...webmDecryptingOnlyCodecs].filter(
|
||||||
|
Boolean
|
||||||
|
)
|
||||||
|
),
|
||||||
|
];
|
||||||
|
if (temp.length) {
|
||||||
|
rv.decryptingOnly = temp;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCapabilities(array) {
|
||||||
|
let capabilities = {};
|
||||||
|
capabilities.persistent = findElementInArray(array, "persistent");
|
||||||
|
capabilities.distinctive = findElementInArray(array, "distinctive");
|
||||||
|
capabilities.sessionType = findElementInArray(array, "sessionType");
|
||||||
|
capabilities.scheme = findElementInArray(array, "scheme");
|
||||||
|
capabilities.codec = getSupportedCodecs(array);
|
||||||
|
return JSON.stringify(capabilities);
|
||||||
|
}
|
||||||
|
|
||||||
|
const rvArray = cdmInfo.capabilities.split(" ");
|
||||||
|
return $.new("tr", [
|
||||||
|
$.new("td", cdmInfo.keySystemName),
|
||||||
|
$.new("td", getVideoRobustness(rvArray)),
|
||||||
|
$.new("td", getAudioRobustness(rvArray)),
|
||||||
|
$.new("td", getCapabilities(rvArray)),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function insertContentDecryptionModuleInfo() {
|
||||||
|
let rows = [];
|
||||||
|
// Retrieve information from WMFCDM, only works when MOZ_WMF_CDM is true
|
||||||
|
if (ChromeUtils.getWMFContentDecryptionModuleInformation !== undefined) {
|
||||||
|
const cdmInfo =
|
||||||
|
await ChromeUtils.getWMFContentDecryptionModuleInformation();
|
||||||
|
for (let info of cdmInfo) {
|
||||||
|
rows.push(createCDMInfoRow(info));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$.append($("media-content-decryption-modules-tbody"), rows);
|
||||||
|
}
|
||||||
|
|
||||||
// Basic information
|
// Basic information
|
||||||
insertBasicInfo("audio-backend", data.currentAudioBackend);
|
insertBasicInfo("audio-backend", data.currentAudioBackend);
|
||||||
insertBasicInfo("max-audio-channels", data.currentMaxAudioChannels);
|
insertBasicInfo("max-audio-channels", data.currentMaxAudioChannels);
|
||||||
|
|
@ -1258,6 +1346,9 @@ var snapshotFormatters = {
|
||||||
if (["win", "macosx", "linux", "android"].includes(AppConstants.platform)) {
|
if (["win", "macosx", "linux", "android"].includes(AppConstants.platform)) {
|
||||||
insertBasicInfo("media-codec-support-info", supportInfo);
|
insertBasicInfo("media-codec-support-info", supportInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CDM info
|
||||||
|
insertContentDecryptionModuleInfo();
|
||||||
},
|
},
|
||||||
|
|
||||||
remoteAgent(data) {
|
remoteAgent(data) {
|
||||||
|
|
|
||||||
|
|
@ -565,6 +565,18 @@
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
||||||
|
<tbody id="media-content-decryption-modules-tbody">
|
||||||
|
<tr>
|
||||||
|
<th colspan="4" class="title-column" data-l10n-id="media-content-decryption-modules-title"/>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th data-l10n-id="media-key-system-name"/>
|
||||||
|
<th data-l10n-id="media-video-robustness"/>
|
||||||
|
<th data-l10n-id="media-audio-robustness"/>
|
||||||
|
<th data-l10n-id="media-cdm-capabilities"/>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<!-- - - - - - - - - - - - - - - - - - - - - -->
|
<!-- - - - - - - - - - - - - - - - - - - - - -->
|
||||||
|
|
|
||||||
|
|
@ -192,6 +192,16 @@ media-codec-support-unsupported = Unsupported
|
||||||
media-codec-support-error = Codec support information unavailable. Try again after playing back a media file.
|
media-codec-support-error = Codec support information unavailable. Try again after playing back a media file.
|
||||||
media-codec-support-lack-of-extension = Install extension
|
media-codec-support-lack-of-extension = Install extension
|
||||||
|
|
||||||
|
## Media Content Decryption Modules (CDM)
|
||||||
|
## See EME Spec for more explanation for following technical terms
|
||||||
|
## https://w3c.github.io/encrypted-media/
|
||||||
|
|
||||||
|
media-content-decryption-modules-title = Content Decryption Modules Information
|
||||||
|
media-key-system-name = Key System Name
|
||||||
|
media-video-robustness = Video Robustness
|
||||||
|
media-audio-robustness = Audio Robustness
|
||||||
|
media-cdm-capabilities = Capabilities
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|
||||||
intl-title = Internationalization & Localization
|
intl-title = Internationalization & Localization
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue