forked from mirrors/gecko-dev
Bug 1810817 - p7: implement CDMProxy for MF CDM and create/init it in MediaKeys. r=alwu
Differential Revision: https://phabricator.services.mozilla.com/D167061
This commit is contained in:
parent
dc8bf99d73
commit
579e5d2ac3
6 changed files with 259 additions and 1 deletions
|
|
@ -108,3 +108,4 @@ speechd init
|
||||||
thread
|
thread
|
||||||
thread shutdown
|
thread shutdown
|
||||||
wifi tickler
|
wifi tickler
|
||||||
|
WMFCDMThread
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,9 @@
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
# include "mozilla/WindowsVersion.h"
|
# include "mozilla/WindowsVersion.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef MOZ_MF_CDM
|
||||||
|
# include "mozilla/WMFCDMProxy.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mozilla::dom {
|
namespace mozilla::dom {
|
||||||
|
|
||||||
|
|
@ -434,6 +437,14 @@ already_AddRefed<CDMProxy> MediaKeys::CreateCDMProxy() {
|
||||||
mConfig.mDistinctiveIdentifier == MediaKeysRequirement::Required,
|
mConfig.mDistinctiveIdentifier == MediaKeysRequirement::Required,
|
||||||
mConfig.mPersistentState == MediaKeysRequirement::Required);
|
mConfig.mPersistentState == MediaKeysRequirement::Required);
|
||||||
} else
|
} else
|
||||||
|
#endif
|
||||||
|
#ifdef MOZ_MF_CDM
|
||||||
|
if (IsPlayReadyKeySystem(mKeySystem)) {
|
||||||
|
proxy = new WMFCDMProxy(
|
||||||
|
this, mKeySystem,
|
||||||
|
mConfig.mDistinctiveIdentifier == MediaKeysRequirement::Required,
|
||||||
|
mConfig.mPersistentState == MediaKeysRequirement::Required);
|
||||||
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
proxy = new ChromiumCDMProxy(
|
proxy = new ChromiumCDMProxy(
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
class MFCDMChild;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WMFCDMImpl is a helper class for MFCDM protocol clients. It creates, manages,
|
* WMFCDMImpl is a helper class for MFCDM protocol clients. It creates, manages,
|
||||||
|
|
|
||||||
117
dom/media/eme/mediafoundation/WMFCDMProxy.cpp
Normal file
117
dom/media/eme/mediafoundation/WMFCDMProxy.cpp
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
/* -*- 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 "WMFCDMProxy.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/MediaKeySession.h"
|
||||||
|
#include "WMFCDMImpl.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
WMFCDMProxy::WMFCDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem,
|
||||||
|
bool aDistinctiveIdentifierRequired,
|
||||||
|
bool aPersistentStateRequired)
|
||||||
|
: CDMProxy(aKeys, aKeySystem, aDistinctiveIdentifierRequired,
|
||||||
|
aPersistentStateRequired) {
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
}
|
||||||
|
|
||||||
|
void WMFCDMProxy::Init(PromiseId aPromiseId, const nsAString& aOrigin,
|
||||||
|
const nsAString& aTopLevelOrigin,
|
||||||
|
const nsAString& aGMPName) {
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
MOZ_ASSERT(!aOrigin.IsEmpty());
|
||||||
|
|
||||||
|
MOZ_ASSERT(!mOwnerThread);
|
||||||
|
if (NS_FAILED(
|
||||||
|
NS_NewNamedThread("WMFCDMThread", getter_AddRefs(mOwnerThread)))) {
|
||||||
|
RejectPromiseWithStateError(
|
||||||
|
aPromiseId,
|
||||||
|
nsLiteralCString("WMFCDMProxy::Init: couldn't create CDM thread"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mCDM = MakeRefPtr<WMFCDMImpl>(mKeySystem);
|
||||||
|
WMFCDMImpl::InitParams params{nsString(aOrigin), mPersistentStateRequired,
|
||||||
|
mDistinctiveIdentifierRequired,
|
||||||
|
false /* HW secure? */};
|
||||||
|
mCDM->Init(params)->Then(
|
||||||
|
mMainThread, __func__,
|
||||||
|
[self = RefPtr{this}, this, aPromiseId](const bool) {
|
||||||
|
MOZ_ASSERT(mCDM->Id() > 0);
|
||||||
|
mKeys->OnCDMCreated(aPromiseId, mCDM->Id());
|
||||||
|
},
|
||||||
|
[self = RefPtr{this}, this, aPromiseId](const nsresult rv) {
|
||||||
|
RejectPromiseWithStateError(
|
||||||
|
aPromiseId,
|
||||||
|
nsLiteralCString("WMFCDMProxy::Init: WMFCDM init error"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void WMFCDMProxy::ResolvePromise(PromiseId aId) {
|
||||||
|
auto resolve = [self = RefPtr{this}, this, aId]() {
|
||||||
|
EME_LOG("WMFCDMProxy::ResolvePromise(this=%p, pid=%" PRIu32 ")", this, aId);
|
||||||
|
if (!mKeys.IsNull()) {
|
||||||
|
mKeys->ResolvePromise(aId);
|
||||||
|
} else {
|
||||||
|
NS_WARNING("WMFCDMProxy unable to resolve promise!");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (NS_IsMainThread()) {
|
||||||
|
resolve();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mMainThread->Dispatch(
|
||||||
|
NS_NewRunnableFunction("WMFCDMProxy::ResolvePromise", resolve));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WMFCDMProxy::RejectPromise(PromiseId aId, ErrorResult&& aException,
|
||||||
|
const nsCString& aReason) {
|
||||||
|
if (!NS_IsMainThread()) {
|
||||||
|
// Use CopyableErrorResult to store our exception in the runnable,
|
||||||
|
// because ErrorResult is not OK to move across threads.
|
||||||
|
mMainThread->Dispatch(
|
||||||
|
NewRunnableMethod<PromiseId, StoreCopyPassByRRef<CopyableErrorResult>,
|
||||||
|
nsCString>("WMFCDMProxy::RejectPromise", this,
|
||||||
|
&WMFCDMProxy::RejectPromiseOnMainThread,
|
||||||
|
aId, std::move(aException), aReason),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EME_LOG("WMFCDMProxy::RejectPromise(this=%p, pid=%" PRIu32
|
||||||
|
", code=0x%x, "
|
||||||
|
"reason='%s')",
|
||||||
|
this, aId, aException.ErrorCodeAsInt(), aReason.get());
|
||||||
|
if (!mKeys.IsNull()) {
|
||||||
|
mKeys->RejectPromise(aId, std::move(aException), aReason);
|
||||||
|
} else {
|
||||||
|
// We don't have a MediaKeys object to pass the exception to, so silence
|
||||||
|
// the exception to avoid it asserting due to being unused.
|
||||||
|
aException.SuppressException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WMFCDMProxy::RejectPromiseOnMainThread(PromiseId aId,
|
||||||
|
CopyableErrorResult&& aException,
|
||||||
|
const nsCString& aReason) {
|
||||||
|
// Moving into or out of a non-copyable ErrorResult will assert that both
|
||||||
|
// ErorResults are from our current thread. Avoid the assertion by moving
|
||||||
|
// into a current-thread CopyableErrorResult first. Note that this is safe,
|
||||||
|
// because CopyableErrorResult never holds state that can't move across
|
||||||
|
// threads.
|
||||||
|
CopyableErrorResult rv(std::move(aException));
|
||||||
|
RejectPromise(aId, std::move(rv), aReason);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WMFCDMProxy::RejectPromiseWithStateError(PromiseId aId,
|
||||||
|
const nsCString& aReason) {
|
||||||
|
ErrorResult rv;
|
||||||
|
rv.ThrowInvalidStateError(aReason);
|
||||||
|
RejectPromise(aId, std::move(rv), aReason);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
124
dom/media/eme/mediafoundation/WMFCDMProxy.h
Normal file
124
dom/media/eme/mediafoundation/WMFCDMProxy.h
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
/* -*- 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 DOM_MEDIA_EME_MEDIAFOUNDATION_WMFCDMPROXY_H_
|
||||||
|
#define DOM_MEDIA_EME_MEDIAFOUNDATION_WMFCDMPROXY_H_
|
||||||
|
|
||||||
|
#include "mozilla/CDMProxy.h"
|
||||||
|
#include "mozilla/CDMCaps.h"
|
||||||
|
#include "mozilla/dom/MediaKeys.h"
|
||||||
|
#include "mozilla/dom/MediaKeySession.h"
|
||||||
|
#include "mozilla/RefPtr.h"
|
||||||
|
#include "mozilla/WMFCDMImpl.h"
|
||||||
|
|
||||||
|
#include "nsString.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
class WMFCDMProxy : public CDMProxy {
|
||||||
|
public:
|
||||||
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WMFCDMProxy, override)
|
||||||
|
|
||||||
|
WMFCDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem,
|
||||||
|
bool aDistinctiveIdentifierRequired,
|
||||||
|
bool aPersistentStateRequired);
|
||||||
|
|
||||||
|
// CDMProxy interface
|
||||||
|
void Init(PromiseId aPromiseId, const nsAString& aOrigin,
|
||||||
|
const nsAString& aTopLevelOrigin,
|
||||||
|
const nsAString& aGMPName) override;
|
||||||
|
|
||||||
|
void CreateSession(uint32_t aCreateSessionToken,
|
||||||
|
MediaKeySessionType aSessionType, PromiseId aPromiseId,
|
||||||
|
const nsAString& aInitDataType,
|
||||||
|
nsTArray<uint8_t>& aInitData) override {}
|
||||||
|
|
||||||
|
void LoadSession(PromiseId aPromiseId, dom::MediaKeySessionType aSessionType,
|
||||||
|
const nsAString& aSessionId) override {}
|
||||||
|
|
||||||
|
void SetServerCertificate(PromiseId aPromiseId,
|
||||||
|
nsTArray<uint8_t>& aCert) override {}
|
||||||
|
|
||||||
|
void UpdateSession(const nsAString& aSessionId, PromiseId aPromiseId,
|
||||||
|
nsTArray<uint8_t>& aResponse) override {}
|
||||||
|
|
||||||
|
void CloseSession(const nsAString& aSessionId,
|
||||||
|
PromiseId aPromiseId) override {}
|
||||||
|
|
||||||
|
void RemoveSession(const nsAString& aSessionId,
|
||||||
|
PromiseId aPromiseId) override {}
|
||||||
|
|
||||||
|
void QueryOutputProtectionStatus() override {}
|
||||||
|
|
||||||
|
void NotifyOutputProtectionStatus(
|
||||||
|
OutputProtectionCheckStatus aCheckStatus,
|
||||||
|
OutputProtectionCaptureStatus aCaptureStatus) override {}
|
||||||
|
|
||||||
|
void Shutdown() override {
|
||||||
|
// TODO: reject pending promise.
|
||||||
|
}
|
||||||
|
|
||||||
|
void Terminated() override {}
|
||||||
|
|
||||||
|
void OnSetSessionId(uint32_t aCreateSessionToken,
|
||||||
|
const nsAString& aSessionId) override {}
|
||||||
|
|
||||||
|
void OnResolveLoadSessionPromise(uint32_t aPromiseId,
|
||||||
|
bool aSuccess) override {}
|
||||||
|
|
||||||
|
void OnSessionMessage(const nsAString& aSessionId,
|
||||||
|
dom::MediaKeyMessageType aMessageType,
|
||||||
|
const nsTArray<uint8_t>& aMessage) override {}
|
||||||
|
|
||||||
|
void OnExpirationChange(const nsAString& aSessionId,
|
||||||
|
UnixTime aExpiryTime) override {}
|
||||||
|
|
||||||
|
void OnSessionClosed(const nsAString& aSessionId) override {}
|
||||||
|
|
||||||
|
void OnSessionError(const nsAString& aSessionId, nsresult aException,
|
||||||
|
uint32_t aSystemCode, const nsAString& aMsg) override {}
|
||||||
|
|
||||||
|
void OnRejectPromise(uint32_t aPromiseId, ErrorResult&& aException,
|
||||||
|
const nsCString& aMsg) override {}
|
||||||
|
|
||||||
|
RefPtr<DecryptPromise> Decrypt(MediaRawData* aSample) override {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
void OnDecrypted(uint32_t aId, DecryptStatus aResult,
|
||||||
|
const nsTArray<uint8_t>& aDecryptedData) override {}
|
||||||
|
|
||||||
|
void ResolvePromise(PromiseId aId) override;
|
||||||
|
void RejectPromise(PromiseId aId, ErrorResult&& aException,
|
||||||
|
const nsCString& aReason) override;
|
||||||
|
|
||||||
|
void OnKeyStatusesChange(const nsAString& aSessionId) override {}
|
||||||
|
|
||||||
|
void GetStatusForPolicy(PromiseId aPromiseId,
|
||||||
|
const nsAString& aMinHdcpVersion) override {}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
bool IsOnOwnerThread() override {
|
||||||
|
return NS_GetCurrentThread() == mOwnerThread;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual ~WMFCDMProxy() = default;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void ResolvePromiseWithResult(PromiseId aId, const T& aResult) {}
|
||||||
|
void RejectPromiseOnMainThread(PromiseId aId,
|
||||||
|
CopyableErrorResult&& aException,
|
||||||
|
const nsCString& aReason);
|
||||||
|
// Reject promise with an InvalidStateError and the given message.
|
||||||
|
void RejectPromiseWithStateError(PromiseId aId, const nsCString& aReason);
|
||||||
|
|
||||||
|
RefPtr<WMFCDMImpl> mCDM;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // DOM_MEDIA_EME_MEDIAFOUNDATION_WMFCDMPROXY_H_
|
||||||
|
|
@ -4,8 +4,14 @@
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
# 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/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
EXPORTS.mozilla += [
|
||||||
|
"WMFCDMImpl.h",
|
||||||
|
"WMFCDMProxy.h",
|
||||||
|
]
|
||||||
|
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
"WMFCDMImpl.cpp",
|
"WMFCDMImpl.cpp",
|
||||||
|
"WMFCDMProxy.cpp",
|
||||||
]
|
]
|
||||||
|
|
||||||
include("/ipc/chromium/chromium-config.mozbuild")
|
include("/ipc/chromium/chromium-config.mozbuild")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue