mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-27 21:00:50 +00:00
Bug 1306572 - Part3 - Implement MediaCDMProxy and the callback proxy. r=cpearce
MozReview-Commit-ID: 3dFawuvhfWu --HG-- extra : rebase_source : 2c77a0c1b9e7a3c1067f12ebf4a416ae4417f3e6
This commit is contained in:
parent
34683786c0
commit
15a599af5d
140
dom/media/eme/mediadrm/MediaDrmCDMCallbackProxy.cpp
Normal file
140
dom/media/eme/mediadrm/MediaDrmCDMCallbackProxy.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 "MediaDrmCDMCallbackProxy.h"
|
||||
#include "mozilla/CDMProxy.h"
|
||||
#include "nsString.h"
|
||||
#include "mozilla/dom/MediaKeys.h"
|
||||
#include "mozilla/dom/MediaKeySession.h"
|
||||
#include "mozIGeckoMediaPluginService.h"
|
||||
#include "nsContentCID.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "mozilla/EMEUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
MediaDrmCDMCallbackProxy::MediaDrmCDMCallbackProxy(CDMProxy* aProxy)
|
||||
: mProxy(aProxy)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMCallbackProxy::SetSessionId(uint32_t aToken,
|
||||
const nsCString& aSessionId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mProxy->OnSetSessionId(aToken, NS_ConvertUTF8toUTF16(aSessionId));
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMCallbackProxy::ResolveLoadSessionPromise(uint32_t aPromiseId,
|
||||
bool aSuccess)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mProxy->OnResolveLoadSessionPromise(aPromiseId, aSuccess);
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMCallbackProxy::ResolvePromise(uint32_t aPromiseId)
|
||||
{
|
||||
// Note: CDMProxy proxies this from non-main threads to main thread.
|
||||
mProxy->ResolvePromise(aPromiseId);
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMCallbackProxy::RejectPromise(uint32_t aPromiseId,
|
||||
nsresult aException,
|
||||
const nsCString& aMessage)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mProxy->OnRejectPromise(aPromiseId, aException, aMessage);
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMCallbackProxy::SessionMessage(const nsCString& aSessionId,
|
||||
dom::MediaKeyMessageType aMessageType,
|
||||
const nsTArray<uint8_t>& aMessage)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// For removing constness
|
||||
nsTArray<uint8_t> message(aMessage);
|
||||
mProxy->OnSessionMessage(NS_ConvertUTF8toUTF16(aSessionId), aMessageType, message);
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMCallbackProxy::ExpirationChange(const nsCString& aSessionId,
|
||||
UnixTime aExpiryTime)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mProxy->OnExpirationChange(NS_ConvertUTF8toUTF16(aSessionId), aExpiryTime);
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMCallbackProxy::SessionClosed(const nsCString& aSessionId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
bool keyStatusesChange = false;
|
||||
{
|
||||
CDMCaps::AutoLock caps(mProxy->Capabilites());
|
||||
keyStatusesChange = caps.RemoveKeysForSession(NS_ConvertUTF8toUTF16(aSessionId));
|
||||
}
|
||||
if (keyStatusesChange) {
|
||||
mProxy->OnKeyStatusesChange(NS_ConvertUTF8toUTF16(aSessionId));
|
||||
}
|
||||
mProxy->OnSessionClosed(NS_ConvertUTF8toUTF16(aSessionId));
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMCallbackProxy::SessionError(const nsCString& aSessionId,
|
||||
nsresult aException,
|
||||
uint32_t aSystemCode,
|
||||
const nsCString& aMessage)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mProxy->OnSessionError(NS_ConvertUTF8toUTF16(aSessionId),
|
||||
aException,
|
||||
aSystemCode,
|
||||
NS_ConvertUTF8toUTF16(aMessage));
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMCallbackProxy::BatchedKeyStatusChanged(const nsCString& aSessionId,
|
||||
const nsTArray<CDMKeyInfo>& aKeyInfos)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
BatchedKeyStatusChangedInternal(aSessionId, aKeyInfos);
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMCallbackProxy::BatchedKeyStatusChangedInternal(const nsCString& aSessionId,
|
||||
const nsTArray<CDMKeyInfo>& aKeyInfos)
|
||||
{
|
||||
bool keyStatusesChange = false;
|
||||
{
|
||||
CDMCaps::AutoLock caps(mProxy->Capabilites());
|
||||
for (size_t i = 0; i < aKeyInfos.Length(); i++) {
|
||||
keyStatusesChange |=
|
||||
caps.SetKeyStatus(aKeyInfos[i].mKeyId,
|
||||
NS_ConvertUTF8toUTF16(aSessionId),
|
||||
aKeyInfos[i].mStatus);
|
||||
}
|
||||
}
|
||||
if (keyStatusesChange) {
|
||||
mProxy->OnKeyStatusesChange(NS_ConvertUTF8toUTF16(aSessionId));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMCallbackProxy::Decrypted(uint32_t aId,
|
||||
DecryptStatus aResult,
|
||||
const nsTArray<uint8_t>& aDecryptedData)
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("Fennec could not handle decrypted event");
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
66
dom/media/eme/mediadrm/MediaDrmCDMCallbackProxy.h
Normal file
66
dom/media/eme/mediadrm/MediaDrmCDMCallbackProxy.h
Normal file
@ -0,0 +1,66 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 MediaDrmCDMCallbackProxy_h_
|
||||
#define MediaDrmCDMCallbackProxy_h_
|
||||
|
||||
#include "mozilla/CDMProxy.h"
|
||||
#include "mozilla/DecryptorProxyCallback.h"
|
||||
|
||||
namespace mozilla {
|
||||
class CDMProxy;
|
||||
// Proxies call backs from the MediaDrmProxy -> MediaDrmProxySupport back to the MediaKeys
|
||||
// object on the main thread.
|
||||
// We used annotation calledFrom = "gecko" to ensure running on main thread.
|
||||
class MediaDrmCDMCallbackProxy : public DecryptorProxyCallback {
|
||||
public:
|
||||
void SetSessionId(uint32_t aCreateSessionToken,
|
||||
const nsCString& aSessionId) override;
|
||||
|
||||
void ResolveLoadSessionPromise(uint32_t aPromiseId,
|
||||
bool aSuccess) override;
|
||||
|
||||
void ResolvePromise(uint32_t aPromiseId) override;
|
||||
|
||||
void RejectPromise(uint32_t aPromiseId,
|
||||
nsresult aException,
|
||||
const nsCString& aSessionId) override;
|
||||
|
||||
void SessionMessage(const nsCString& aSessionId,
|
||||
dom::MediaKeyMessageType aMessageType,
|
||||
const nsTArray<uint8_t>& aMessage) override;
|
||||
|
||||
void ExpirationChange(const nsCString& aSessionId,
|
||||
UnixTime aExpiryTime) override;
|
||||
|
||||
void SessionClosed(const nsCString& aSessionId) override;
|
||||
|
||||
void SessionError(const nsCString& aSessionId,
|
||||
nsresult aException,
|
||||
uint32_t aSystemCode,
|
||||
const nsCString& aMessage) override;
|
||||
|
||||
void Decrypted(uint32_t aId,
|
||||
DecryptStatus aResult,
|
||||
const nsTArray<uint8_t>& aDecryptedData) override;
|
||||
|
||||
void BatchedKeyStatusChanged(const nsCString& aSessionId,
|
||||
const nsTArray<CDMKeyInfo>& aKeyInfos) override;
|
||||
|
||||
~MediaDrmCDMCallbackProxy() {}
|
||||
|
||||
private:
|
||||
friend class MediaDrmCDMProxy;
|
||||
explicit MediaDrmCDMCallbackProxy(CDMProxy* aProxy);
|
||||
|
||||
void BatchedKeyStatusChangedInternal(const nsCString& aSessionId,
|
||||
const nsTArray<CDMKeyInfo>& aKeyInfos);
|
||||
// Warning: Weak ref.
|
||||
CDMProxy* mProxy;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
#endif
|
467
dom/media/eme/mediadrm/MediaDrmCDMProxy.cpp
Normal file
467
dom/media/eme/mediadrm/MediaDrmCDMProxy.cpp
Normal file
@ -0,0 +1,467 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/MediaKeySession.h"
|
||||
#include "mozilla/MediaDrmCDMProxy.h"
|
||||
#include "MediaDrmCDMCallbackProxy.h"
|
||||
|
||||
using namespace mozilla::java::sdk;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
MediaDrmSessionType
|
||||
ToMediaDrmSessionType(dom::MediaKeySessionType aSessionType)
|
||||
{
|
||||
switch (aSessionType) {
|
||||
case dom::MediaKeySessionType::Temporary: return kKeyStreaming;
|
||||
case dom::MediaKeySessionType::Persistent_license: return kKeyOffline;
|
||||
default: return kKeyStreaming;
|
||||
};
|
||||
}
|
||||
|
||||
MediaDrmCDMProxy::MediaDrmCDMProxy(dom::MediaKeys* aKeys,
|
||||
const nsAString& aKeySystem,
|
||||
bool aDistinctiveIdentifierRequired,
|
||||
bool aPersistentStateRequired)
|
||||
: CDMProxy(aKeys,
|
||||
aKeySystem,
|
||||
aDistinctiveIdentifierRequired,
|
||||
aPersistentStateRequired)
|
||||
, mCDM(nullptr)
|
||||
, mShutdownCalled(false)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_COUNT_CTOR(MediaDrmCDMProxy);
|
||||
}
|
||||
|
||||
MediaDrmCDMProxy::~MediaDrmCDMProxy()
|
||||
{
|
||||
MOZ_COUNT_DTOR(MediaDrmCDMProxy);
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::Init(PromiseId aPromiseId,
|
||||
const nsAString& aOrigin,
|
||||
const nsAString& aTopLevelOrigin,
|
||||
const nsAString& aName,
|
||||
bool aInPrivateBrowsing)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
|
||||
|
||||
EME_LOG("MediaDrmCDMProxy::Init (%s, %s) %s",
|
||||
NS_ConvertUTF16toUTF8(aOrigin).get(),
|
||||
NS_ConvertUTF16toUTF8(aTopLevelOrigin).get(),
|
||||
(aInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing"));
|
||||
|
||||
// Create a thread to work with cdm.
|
||||
if (!mOwnerThread) {
|
||||
nsresult rv = NS_NewNamedThread("MDCDMThread", getter_AddRefs(mOwnerThread));
|
||||
if (NS_FAILED(rv)) {
|
||||
RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
|
||||
NS_LITERAL_CSTRING("Couldn't create CDM thread MediaDrmCDMProxy::Init"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mCDM = mozilla::MakeUnique<MediaDrmProxySupport>(mKeySystem);
|
||||
nsCOMPtr<nsIRunnable> task(NewRunnableMethod<uint32_t>(this,
|
||||
&MediaDrmCDMProxy::md_Init,
|
||||
aPromiseId));
|
||||
mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::CreateSession(uint32_t aCreateSessionToken,
|
||||
MediaKeySessionType aSessionType,
|
||||
PromiseId aPromiseId,
|
||||
const nsAString& aInitDataType,
|
||||
nsTArray<uint8_t>& aInitData)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mOwnerThread);
|
||||
|
||||
nsAutoPtr<CreateSessionData> data(new CreateSessionData());
|
||||
data->mSessionType = aSessionType;
|
||||
data->mCreateSessionToken = aCreateSessionToken;
|
||||
data->mPromiseId = aPromiseId;
|
||||
data->mInitDataType = NS_ConvertUTF16toUTF8(aInitDataType);
|
||||
data->mInitData = Move(aInitData);
|
||||
|
||||
nsCOMPtr<nsIRunnable> task(
|
||||
NewRunnableMethod<nsAutoPtr<CreateSessionData>>(this,
|
||||
&MediaDrmCDMProxy::md_CreateSession,
|
||||
data));
|
||||
mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::LoadSession(PromiseId aPromiseId,
|
||||
const nsAString& aSessionId)
|
||||
{
|
||||
// TODO: Implement LoadSession.
|
||||
RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
|
||||
NS_LITERAL_CSTRING("Currently Fennec did not support LoadSession"));
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::SetServerCertificate(PromiseId aPromiseId,
|
||||
nsTArray<uint8_t>& aCert)
|
||||
{
|
||||
// TODO: Implement SetServerCertificate.
|
||||
RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
|
||||
NS_LITERAL_CSTRING("Currently Fennec did not support SetServerCertificate"));
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::UpdateSession(const nsAString& aSessionId,
|
||||
PromiseId aPromiseId,
|
||||
nsTArray<uint8_t>& aResponse)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mOwnerThread);
|
||||
NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
|
||||
|
||||
nsAutoPtr<UpdateSessionData> data(new UpdateSessionData());
|
||||
data->mPromiseId = aPromiseId;
|
||||
data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
|
||||
data->mResponse = Move(aResponse);
|
||||
|
||||
nsCOMPtr<nsIRunnable> task(
|
||||
NewRunnableMethod<nsAutoPtr<UpdateSessionData>>(this,
|
||||
&MediaDrmCDMProxy::md_UpdateSession,
|
||||
data));
|
||||
mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::CloseSession(const nsAString& aSessionId,
|
||||
PromiseId aPromiseId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mOwnerThread);
|
||||
NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
|
||||
|
||||
nsAutoPtr<SessionOpData> data(new SessionOpData());
|
||||
data->mPromiseId = aPromiseId;
|
||||
data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
|
||||
|
||||
nsCOMPtr<nsIRunnable> task(
|
||||
NewRunnableMethod<nsAutoPtr<SessionOpData>>(this,
|
||||
&MediaDrmCDMProxy::md_CloseSession,
|
||||
data));
|
||||
mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::RemoveSession(const nsAString& aSessionId,
|
||||
PromiseId aPromiseId)
|
||||
{
|
||||
// TODO: Implement RemoveSession.
|
||||
RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
|
||||
NS_LITERAL_CSTRING("Currently Fennec did not support RemoveSession"));
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::Shutdown()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mOwnerThread);
|
||||
nsCOMPtr<nsIRunnable> task(
|
||||
NewRunnableMethod(this, &MediaDrmCDMProxy::md_Shutdown));
|
||||
|
||||
mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
|
||||
mOwnerThread->Shutdown();
|
||||
mOwnerThread = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::Terminated()
|
||||
{
|
||||
// TODO: Implement Terminated.
|
||||
// Should find a way to handle the case when remote side MediaDrm crashed.
|
||||
}
|
||||
|
||||
const nsCString&
|
||||
MediaDrmCDMProxy::GetNodeId() const
|
||||
{
|
||||
return mNodeId;
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::OnSetSessionId(uint32_t aCreateSessionToken,
|
||||
const nsAString& aSessionId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mKeys.IsNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<dom::MediaKeySession> session(mKeys->GetPendingSession(aCreateSessionToken));
|
||||
if (session) {
|
||||
session->SetSessionId(aSessionId);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mKeys.IsNull()) {
|
||||
return;
|
||||
}
|
||||
mKeys->OnSessionLoaded(aPromiseId, aSuccess);
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::OnSessionMessage(const nsAString& aSessionId,
|
||||
dom::MediaKeyMessageType aMessageType,
|
||||
nsTArray<uint8_t>& aMessage)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mKeys.IsNull()) {
|
||||
return;
|
||||
}
|
||||
RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
|
||||
if (session) {
|
||||
session->DispatchKeyMessage(aMessageType, aMessage);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::OnExpirationChange(const nsAString& aSessionId,
|
||||
UnixTime aExpiryTime)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mKeys.IsNull()) {
|
||||
return;
|
||||
}
|
||||
RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
|
||||
if (session) {
|
||||
session->SetExpiration(static_cast<double>(aExpiryTime));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::OnSessionClosed(const nsAString& aSessionId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mKeys.IsNull()) {
|
||||
return;
|
||||
}
|
||||
RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
|
||||
if (session) {
|
||||
session->OnClosed();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::OnSessionError(const nsAString& aSessionId,
|
||||
nsresult aException,
|
||||
uint32_t aSystemCode,
|
||||
const nsAString& aMsg)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mKeys.IsNull()) {
|
||||
return;
|
||||
}
|
||||
RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
|
||||
if (session) {
|
||||
session->DispatchKeyError(aSystemCode);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::OnRejectPromise(uint32_t aPromiseId,
|
||||
nsresult aDOMException,
|
||||
const nsCString& aMsg)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
RejectPromise(aPromiseId, aDOMException, aMsg);
|
||||
}
|
||||
|
||||
RefPtr<MediaDrmCDMProxy::DecryptPromise>
|
||||
MediaDrmCDMProxy::Decrypt(MediaRawData* aSample)
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("Fennec could not handle decrypting individually");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::OnDecrypted(uint32_t aId,
|
||||
DecryptStatus aResult,
|
||||
const nsTArray<uint8_t>& aDecryptedData)
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("Fennec could not handle decrypted event");
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::RejectPromise(PromiseId aId, nsresult aCode,
|
||||
const nsCString& aReason)
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
if (!mKeys.IsNull()) {
|
||||
mKeys->RejectPromise(aId, aCode, aReason);
|
||||
}
|
||||
} else {
|
||||
nsCOMPtr<nsIRunnable> task(new RejectPromiseTask(this, aId, aCode,
|
||||
aReason));
|
||||
NS_DispatchToMainThread(task);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::ResolvePromise(PromiseId aId)
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
if (!mKeys.IsNull()) {
|
||||
mKeys->ResolvePromise(aId);
|
||||
} else {
|
||||
NS_WARNING("MediaDrmCDMProxy unable to resolve promise!");
|
||||
}
|
||||
} else {
|
||||
nsCOMPtr<nsIRunnable> task;
|
||||
task = NewRunnableMethod<PromiseId>(this,
|
||||
&MediaDrmCDMProxy::ResolvePromise,
|
||||
aId);
|
||||
NS_DispatchToMainThread(task);
|
||||
}
|
||||
}
|
||||
|
||||
const nsString&
|
||||
MediaDrmCDMProxy::KeySystem() const
|
||||
{
|
||||
return mKeySystem;
|
||||
}
|
||||
|
||||
CDMCaps&
|
||||
MediaDrmCDMProxy::Capabilites()
|
||||
{
|
||||
return mCapabilites;
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::OnKeyStatusesChange(const nsAString& aSessionId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mKeys.IsNull()) {
|
||||
return;
|
||||
}
|
||||
RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
|
||||
if (session) {
|
||||
session->DispatchKeyStatusesChange();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId,
|
||||
nsTArray<nsCString>& aSessionIds)
|
||||
{
|
||||
CDMCaps::AutoLock caps(Capabilites());
|
||||
caps.GetSessionIdsForKeyId(aKeyId, aSessionIds);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool
|
||||
MediaDrmCDMProxy::IsOnOwnerThread()
|
||||
{
|
||||
return NS_GetCurrentThread() == mOwnerThread;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::OnCDMCreated(uint32_t aPromiseId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mKeys.IsNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mCDM) {
|
||||
mKeys->OnCDMCreated(aPromiseId, GetNodeId(), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// No CDM? Just reject the promise.
|
||||
mKeys->RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
|
||||
NS_LITERAL_CSTRING("Null CDM in OnCDMCreated()"));
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::md_Init(uint32_t aPromiseId)
|
||||
{
|
||||
MOZ_ASSERT(IsOnOwnerThread());
|
||||
MOZ_ASSERT(mCDM);
|
||||
|
||||
mCallback = new MediaDrmCDMCallbackProxy(this);
|
||||
mCDM->Init(mCallback);
|
||||
nsCOMPtr<nsIRunnable> task(
|
||||
NewRunnableMethod<uint32_t>(this,
|
||||
&MediaDrmCDMProxy::OnCDMCreated,
|
||||
aPromiseId));
|
||||
NS_DispatchToMainThread(task);
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::md_CreateSession(nsAutoPtr<CreateSessionData> aData)
|
||||
{
|
||||
MOZ_ASSERT(IsOnOwnerThread());
|
||||
|
||||
if (!mCDM) {
|
||||
RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
|
||||
NS_LITERAL_CSTRING("Null CDM in md_CreateSession"));
|
||||
return;
|
||||
}
|
||||
|
||||
mCDM->CreateSession(aData->mCreateSessionToken,
|
||||
aData->mPromiseId,
|
||||
aData->mInitDataType,
|
||||
aData->mInitData,
|
||||
ToMediaDrmSessionType(aData->mSessionType));
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::md_UpdateSession(nsAutoPtr<UpdateSessionData> aData)
|
||||
{
|
||||
MOZ_ASSERT(IsOnOwnerThread());
|
||||
|
||||
if (!mCDM) {
|
||||
RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
|
||||
NS_LITERAL_CSTRING("Null CDM in md_UpdateSession"));
|
||||
return;
|
||||
}
|
||||
mCDM->UpdateSession(aData->mPromiseId,
|
||||
aData->mSessionId,
|
||||
aData->mResponse);
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::md_CloseSession(nsAutoPtr<SessionOpData> aData)
|
||||
{
|
||||
MOZ_ASSERT(IsOnOwnerThread());
|
||||
|
||||
if (!mCDM) {
|
||||
RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
|
||||
NS_LITERAL_CSTRING("Null CDM in md_CloseSession"));
|
||||
return;
|
||||
}
|
||||
mCDM->CloseSession(aData->mPromiseId, aData->mSessionId);
|
||||
}
|
||||
|
||||
void
|
||||
MediaDrmCDMProxy::md_Shutdown()
|
||||
{
|
||||
MOZ_ASSERT(IsOnOwnerThread());
|
||||
MOZ_ASSERT(mCDM);
|
||||
if (mShutdownCalled) {
|
||||
return;
|
||||
}
|
||||
mShutdownCalled = true;
|
||||
mCDM->Shutdown();
|
||||
mCDM = nullptr;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
184
dom/media/eme/mediadrm/MediaDrmCDMProxy.h
Normal file
184
dom/media/eme/mediadrm/MediaDrmCDMProxy.h
Normal file
@ -0,0 +1,184 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 MediaDrmCDMProxy_h_
|
||||
#define MediaDrmCDMProxy_h_
|
||||
|
||||
#include <jni.h>
|
||||
#include "mozilla/jni/Types.h"
|
||||
#include "GeneratedJNINatives.h"
|
||||
|
||||
#include "mozilla/CDMProxy.h"
|
||||
#include "mozilla/CDMCaps.h"
|
||||
#include "mozilla/dom/MediaKeys.h"
|
||||
#include "mozilla/MediaDrmProxySupport.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
#include "MediaCodec.h"
|
||||
#include "nsString.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
using namespace mozilla::java;
|
||||
|
||||
namespace mozilla {
|
||||
class MediaDrmCDMCallbackProxy;
|
||||
class MediaDrmCDMProxy : public CDMProxy {
|
||||
public:
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDrmCDMProxy)
|
||||
|
||||
MediaDrmCDMProxy(dom::MediaKeys* aKeys,
|
||||
const nsAString& aKeySystem,
|
||||
bool aDistinctiveIdentifierRequired,
|
||||
bool aPersistentStateRequired);
|
||||
|
||||
void Init(PromiseId aPromiseId,
|
||||
const nsAString& aOrigin,
|
||||
const nsAString& aTopLevelOrigin,
|
||||
const nsAString& aGMPName,
|
||||
bool aInPrivateBrowsing) override;
|
||||
|
||||
void CreateSession(uint32_t aCreateSessionToken,
|
||||
MediaKeySessionType aSessionType,
|
||||
PromiseId aPromiseId,
|
||||
const nsAString& aInitDataType,
|
||||
nsTArray<uint8_t>& aInitData) override;
|
||||
|
||||
void LoadSession(PromiseId aPromiseId,
|
||||
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 Shutdown() override;
|
||||
|
||||
void Terminated() override;
|
||||
|
||||
const nsCString& GetNodeId() const 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,
|
||||
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,
|
||||
nsresult aCode,
|
||||
const nsCString& aMsg) override;
|
||||
|
||||
RefPtr<DecryptPromise> Decrypt(MediaRawData* aSample) override;
|
||||
void OnDecrypted(uint32_t aId,
|
||||
DecryptStatus aResult,
|
||||
const nsTArray<uint8_t>& aDecryptedData) override;
|
||||
|
||||
void RejectPromise(PromiseId aId, nsresult aCode,
|
||||
const nsCString& aReason) override;
|
||||
|
||||
// Resolves promise with "undefined".
|
||||
// Can be called from any thread.
|
||||
void ResolvePromise(PromiseId aId) override;
|
||||
|
||||
// Threadsafe.
|
||||
const nsString& KeySystem() const override;
|
||||
|
||||
CDMCaps& Capabilites() override;
|
||||
|
||||
void OnKeyStatusesChange(const nsAString& aSessionId) override;
|
||||
|
||||
void GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId,
|
||||
nsTArray<nsCString>& aSessionIds) override;
|
||||
|
||||
#ifdef DEBUG
|
||||
bool IsOnOwnerThread() override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
virtual ~MediaDrmCDMProxy();
|
||||
|
||||
void OnCDMCreated(uint32_t aPromiseId);
|
||||
|
||||
struct CreateSessionData {
|
||||
MediaKeySessionType mSessionType;
|
||||
uint32_t mCreateSessionToken;
|
||||
PromiseId mPromiseId;
|
||||
nsCString mInitDataType;
|
||||
nsTArray<uint8_t> mInitData;
|
||||
};
|
||||
|
||||
struct UpdateSessionData {
|
||||
PromiseId mPromiseId;
|
||||
nsCString mSessionId;
|
||||
nsTArray<uint8_t> mResponse;
|
||||
};
|
||||
|
||||
struct SessionOpData {
|
||||
PromiseId mPromiseId;
|
||||
nsCString mSessionId;
|
||||
};
|
||||
|
||||
class RejectPromiseTask : public Runnable {
|
||||
public:
|
||||
RejectPromiseTask(MediaDrmCDMProxy* aProxy,
|
||||
PromiseId aId,
|
||||
nsresult aCode,
|
||||
const nsCString& aReason)
|
||||
: mProxy(aProxy)
|
||||
, mId(aId)
|
||||
, mCode(aCode)
|
||||
, mReason(aReason)
|
||||
{
|
||||
}
|
||||
NS_METHOD Run() {
|
||||
mProxy->RejectPromise(mId, mCode, mReason);
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
RefPtr<MediaDrmCDMProxy> mProxy;
|
||||
PromiseId mId;
|
||||
nsresult mCode;
|
||||
nsCString mReason;
|
||||
};
|
||||
|
||||
nsCString mNodeId;
|
||||
mozilla::UniquePtr<MediaDrmProxySupport> mCDM;
|
||||
nsAutoPtr<MediaDrmCDMCallbackProxy> mCallback;
|
||||
bool mShutdownCalled;
|
||||
|
||||
// =====================================================================
|
||||
// For MediaDrmProxySupport
|
||||
void md_Init(uint32_t aPromiseId);
|
||||
void md_CreateSession(nsAutoPtr<CreateSessionData> aData);
|
||||
void md_UpdateSession(nsAutoPtr<UpdateSessionData> aData);
|
||||
void md_CloseSession(nsAutoPtr<SessionOpData> aData);
|
||||
void md_Shutdown();
|
||||
// =====================================================================
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
#endif // MediaDrmCDMProxy_h_
|
19
dom/media/eme/mediadrm/moz.build
Normal file
19
dom/media/eme/mediadrm/moz.build
Normal file
@ -0,0 +1,19 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
EXPORTS.mozilla += [
|
||||
'MediaDrmCDMCallbackProxy.h',
|
||||
'MediaDrmCDMProxy.h',
|
||||
'MediaDrmProxySupport.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'MediaDrmCDMCallbackProxy.cpp',
|
||||
'MediaDrmCDMProxy.cpp',
|
||||
'MediaDrmProxySupport.cpp',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
@ -37,6 +37,9 @@ UNIFIED_SOURCES += [
|
||||
'MediaKeySystemAccessManager.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
|
||||
DIRS += ['mediadrm']
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
Loading…
x
Reference in New Issue
Block a user