зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
dc8bf99d73
Коммит
579e5d2ac3
|
@ -108,3 +108,4 @@ speechd init
|
|||
thread
|
||||
thread shutdown
|
||||
wifi tickler
|
||||
WMFCDMThread
|
||||
|
|
|
@ -36,6 +36,9 @@
|
|||
#ifdef XP_WIN
|
||||
# include "mozilla/WindowsVersion.h"
|
||||
#endif
|
||||
#ifdef MOZ_MF_CDM
|
||||
# include "mozilla/WMFCDMProxy.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
|
@ -434,6 +437,14 @@ already_AddRefed<CDMProxy> MediaKeys::CreateCDMProxy() {
|
|||
mConfig.mDistinctiveIdentifier == MediaKeysRequirement::Required,
|
||||
mConfig.mPersistentState == MediaKeysRequirement::Required);
|
||||
} else
|
||||
#endif
|
||||
#ifdef MOZ_MF_CDM
|
||||
if (IsPlayReadyKeySystem(mKeySystem)) {
|
||||
proxy = new WMFCDMProxy(
|
||||
this, mKeySystem,
|
||||
mConfig.mDistinctiveIdentifier == MediaKeysRequirement::Required,
|
||||
mConfig.mPersistentState == MediaKeysRequirement::Required);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
proxy = new ChromiumCDMProxy(
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
class MFCDMChild;
|
||||
|
||||
/**
|
||||
* WMFCDMImpl is a helper class for MFCDM protocol clients. It creates, manages,
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXPORTS.mozilla += [
|
||||
"WMFCDMImpl.h",
|
||||
"WMFCDMProxy.h",
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
"WMFCDMImpl.cpp",
|
||||
"WMFCDMProxy.cpp",
|
||||
]
|
||||
|
||||
include("/ipc/chromium/chromium-config.mozbuild")
|
||||
|
|
Загрузка…
Ссылка в новой задаче