--- a/dom/media/eme/CDMProxy.h
+++ b/dom/media/eme/CDMProxy.h
@@ -110,16 +110,17 @@ public:
PromiseId aPromiseId,
const nsAString& aInitDataType,
nsTArray<uint8_t>& aInitData) = 0;
// Main thread only.
// Uses the CDM to load a presistent session stored on disk.
// Calls MediaKeys::OnSessionActivated() when session is loaded.
virtual void LoadSession(PromiseId aPromiseId,
+ dom::MediaKeySessionType aSessionType,
const nsAString& aSessionId) = 0;
// Main thread only.
// Sends a new certificate to the CDM.
// Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
// processed the request.
// Assumes ownership of (Move()s) aCert's contents.
virtual void SetServerCertificate(PromiseId aPromiseId,
--- a/dom/media/eme/MediaKeySession.cpp
+++ b/dom/media/eme/MediaKeySession.cpp
@@ -391,17 +391,17 @@ MediaKeySession::Load(const nsAString& a
// session from its owning MediaKey's set of sessions awaiting a sessionId.
RefPtr<MediaKeySession> session(mKeys->GetPendingSession(Token()));
MOZ_ASSERT(session == this, "Session should be awaiting id on its own token");
// Associate with the known sessionId.
SetSessionId(aSessionId);
PromiseId pid = mKeys->StorePromise(promise);
- mKeys->GetCDMProxy()->LoadSession(pid, aSessionId);
+ mKeys->GetCDMProxy()->LoadSession(pid, mSessionType, aSessionId);
EME_LOG("MediaKeySession[%p,'%s'] Load() sent to CDM, promiseId=%d",
this, NS_ConvertUTF16toUTF8(mSessionId).get(), pid);
return promise.forget();
}
already_AddRefed<Promise>
--- a/dom/media/eme/mediadrm/MediaDrmCDMProxy.cpp
+++ b/dom/media/eme/mediadrm/MediaDrmCDMProxy.cpp
@@ -96,16 +96,17 @@ MediaDrmCDMProxy::CreateSession(uint32_t
NewRunnableMethod<UniquePtr<CreateSessionData>&&>(this,
&MediaDrmCDMProxy::md_CreateSession,
Move(data)));
mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
}
void
MediaDrmCDMProxy::LoadSession(PromiseId aPromiseId,
+ dom::MediaKeySessionType aSessionType,
const nsAString& aSessionId)
{
// TODO: Implement LoadSession.
RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("Currently Fennec did not support LoadSession"));
}
void
--- a/dom/media/eme/mediadrm/MediaDrmCDMProxy.h
+++ b/dom/media/eme/mediadrm/MediaDrmCDMProxy.h
@@ -8,16 +8,17 @@
#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/dom/MediaKeySession.h"
#include "mozilla/MediaDrmProxySupport.h"
#include "mozilla/UniquePtr.h"
#include "MediaCodec.h"
#include "nsString.h"
using namespace mozilla::java;
@@ -42,16 +43,17 @@ public:
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;
--- a/dom/media/gmp/ChromiumCDMChild.cpp
+++ b/dom/media/gmp/ChromiumCDMChild.cpp
@@ -74,16 +74,33 @@ ChromiumCDMChild::OnResolveNewSessionPro
const char* aSessionId,
uint32_t aSessionIdSize)
{
MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::OnResolveNewSessionPromise(pid=%" PRIu32
", sid=%s)",
aPromiseId,
aSessionId);
+
+ if (mLoadSessionPromiseIds.Contains(aPromiseId)) {
+ // As laid out in the Chromium CDM API, if the CDM fails to load
+ // a session it calls OnResolveNewSessionPromise with nullptr as the sessionId.
+ // We can safely assume this means that we have failed to load a session
+ // as the other methods specify calling 'OnRejectPromise' when they fail.
+ bool loadSuccessful = aSessionId != nullptr;
+ GMP_LOG("ChromiumCDMChild::OnResolveNewSessionPromise(pid=%u, sid=%s) "
+ "resolving %s load session ",
+ aPromiseId,
+ aSessionId,
+ (loadSuccessful ? "successful" : "failed"));
+ Unused << SendResolveLoadSessionPromise(aPromiseId, loadSuccessful);
+ mLoadSessionPromiseIds.RemoveElement(aPromiseId);
+ return;
+ }
+
Unused << SendOnResolveNewSessionPromise(aPromiseId,
nsCString(aSessionId, aSessionIdSize));
}
void ChromiumCDMChild::OnResolvePromise(uint32_t aPromiseId)
{
MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::OnResolvePromise(pid=%" PRIu32 ")", aPromiseId);
@@ -290,16 +307,35 @@ ChromiumCDMChild::RecvCreateSessionAndGe
static_cast<cdm::InitDataType>(aInitDataType),
aInitData.Elements(),
aInitData.Length());
}
return IPC_OK();
}
mozilla::ipc::IPCResult
+ChromiumCDMChild::RecvLoadSession(const uint32_t& aPromiseId,
+ const uint32_t& aSessionType,
+ const nsCString& aSessionId)
+{
+ GMP_LOG("ChromiumCDMChild::RecvLoadSession(pid=%u, type=%u, sessionId=%s)",
+ aPromiseId,
+ aSessionType,
+ aSessionId.get());
+ if (mCDM) {
+ mLoadSessionPromiseIds.AppendElement(aPromiseId);
+ mCDM->LoadSession(aPromiseId,
+ static_cast<cdm::SessionType>(aSessionType),
+ aSessionId.get(),
+ aSessionId.Length());
+ }
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
ChromiumCDMChild::RecvUpdateSession(const uint32_t& aPromiseId,
const nsCString& aSessionId,
nsTArray<uint8_t>&& aResponse)
{
MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::RecvUpdateSession(pid=%" PRIu32
", sid=%s) responseLen=%zu",
aPromiseId,
--- a/dom/media/gmp/ChromiumCDMChild.h
+++ b/dom/media/gmp/ChromiumCDMChild.h
@@ -83,16 +83,19 @@ protected:
ipc::IPCResult RecvSetServerCertificate(
const uint32_t& aPromiseId,
nsTArray<uint8_t>&& aServerCert) override;
ipc::IPCResult RecvCreateSessionAndGenerateRequest(
const uint32_t& aPromiseId,
const uint32_t& aSessionType,
const uint32_t& aInitDataType,
nsTArray<uint8_t>&& aInitData) override;
+ ipc::IPCResult RecvLoadSession(const uint32_t& aPromiseId,
+ const uint32_t& aSessionType,
+ const nsCString& aSessionId) override;
ipc::IPCResult RecvUpdateSession(const uint32_t& aPromiseId,
const nsCString& aSessionId,
nsTArray<uint8_t>&& aResponse) override;
ipc::IPCResult RecvCloseSession(const uint32_t& aPromiseId,
const nsCString& aSessionId) override;
ipc::IPCResult RecvRemoveSession(const uint32_t& aPromiseId,
const nsCString& aSessionId) override;
ipc::IPCResult RecvDecrypt(const uint32_t& aId,
@@ -109,16 +112,17 @@ protected:
void DecryptFailed(uint32_t aId, cdm::Status aStatus);
void ReturnOutput(WidevineVideoFrame& aFrame);
GMPContentChild* mPlugin = nullptr;
cdm::ContentDecryptionModule_8* mCDM = nullptr;
typedef SimpleMap<uint64_t> DurationMap;
DurationMap mFrameDurations;
+ nsTArray<uint32_t> mLoadSessionPromiseIds;
bool mDecoderInitialized = false;
bool mPersistentStateAllowed = false;
};
} // namespace gmp
} // namespace mozilla
--- a/dom/media/gmp/ChromiumCDMParent.cpp
+++ b/dom/media/gmp/ChromiumCDMParent.cpp
@@ -62,16 +62,42 @@ ChromiumCDMParent::CreateSession(uint32_
NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("Failed to send generateRequest to CDM process."));
return;
}
mPromiseToCreateSessionToken.Put(aPromiseId, aCreateSessionToken);
}
void
+ChromiumCDMParent::LoadSession(uint32_t aPromiseId,
+ uint32_t aSessionType,
+ nsString aSessionId)
+{
+ GMP_LOG("ChromiumCDMParent::LoadSession(this=%p, pid=%u, type=%u, sid=%s)",
+ this,
+ aPromiseId,
+ aSessionType,
+ NS_ConvertUTF16toUTF8(aSessionId).get());
+ if (mIsShutdown) {
+ RejectPromise(aPromiseId,
+ NS_ERROR_DOM_INVALID_STATE_ERR,
+ NS_LITERAL_CSTRING("CDM is shutdown."));
+ return;
+ }
+ if (!SendLoadSession(
+ aPromiseId, aSessionType, NS_ConvertUTF16toUTF8(aSessionId))) {
+ RejectPromise(
+ aPromiseId,
+ NS_ERROR_DOM_INVALID_STATE_ERR,
+ NS_LITERAL_CSTRING("Failed to send loadSession to CDM process."));
+ return;
+ }
+}
+
+void
ChromiumCDMParent::SetServerCertificate(uint32_t aPromiseId,
const nsTArray<uint8_t>& aCert)
{
GMP_LOG("ChromiumCDMParent::SetServerCertificate(this=%p)", this);
if (mIsShutdown) {
RejectPromise(aPromiseId,
NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("CDM is shutdown."));
@@ -231,16 +257,36 @@ ChromiumCDMParent::RecvOnResolveNewSessi
NS_ConvertUTF8toUTF16(aSessionId));
NS_DispatchToMainThread(task);
ResolvePromise(aPromiseId);
return IPC_OK();
}
+ipc::IPCResult
+ChromiumCDMParent::RecvResolveLoadSessionPromise(const uint32_t& aPromiseId,
+ const bool& aSuccessful)
+{
+ GMP_LOG("ChromiumCDMParent::RecvResolveLoadSessionPromise(this=%p, pid=%u, "
+ "successful=%d)",
+ this,
+ aPromiseId,
+ aSuccessful);
+ if (!mProxy || mIsShutdown) {
+ return IPC_OK();
+ }
+
+ NS_DispatchToMainThread(NewRunnableMethod<uint32_t, bool>(
+ mProxy,
+ &ChromiumCDMProxy::OnResolveLoadSessionPromise,
+ aPromiseId,
+ aSuccessful));
+ return IPC_OK();
+}
void
ChromiumCDMParent::ResolvePromise(uint32_t aPromiseId)
{
GMP_LOG(
"ChromiumCDMParent::ResolvePromise(this=%p, pid=%u)", this, aPromiseId);
// Note: The MediaKeys rejects all pending DOM promises when it
// initiates shutdown.
--- a/dom/media/gmp/ChromiumCDMParent.h
+++ b/dom/media/gmp/ChromiumCDMParent.h
@@ -41,16 +41,20 @@ public:
bool aAllowPersistentState);
void CreateSession(uint32_t aCreateSessionToken,
uint32_t aSessionType,
uint32_t aInitDataType,
uint32_t aPromiseId,
const nsTArray<uint8_t>& aInitData);
+ void LoadSession(uint32_t aPromiseId,
+ uint32_t aSessionType,
+ nsString aSessionId);
+
void SetServerCertificate(uint32_t aPromiseId,
const nsTArray<uint8_t>& aCert);
void UpdateSession(const nsCString& aSessionId,
uint32_t aPromiseId,
const nsTArray<uint8_t>& aResponse);
void CloseSession(const nsCString& aSessionId, uint32_t aPromiseId);
@@ -79,16 +83,19 @@ public:
protected:
~ChromiumCDMParent() {}
ipc::IPCResult Recv__delete__() override;
ipc::IPCResult RecvOnResolveNewSessionPromise(
const uint32_t& aPromiseId,
const nsCString& aSessionId) override;
+ ipc::IPCResult RecvResolveLoadSessionPromise(
+ const uint32_t& aPromiseId,
+ const bool& aSuccessful) override;
ipc::IPCResult RecvOnResolvePromise(const uint32_t& aPromiseId) override;
ipc::IPCResult RecvOnRejectPromise(const uint32_t& aPromiseId,
const uint32_t& aError,
const uint32_t& aSystemCode,
const nsCString& aErrorMessage) override;
ipc::IPCResult RecvOnSessionMessage(const nsCString& aSessionId,
const uint32_t& aMessageType,
nsTArray<uint8_t>&& aMessage) override;
--- a/dom/media/gmp/ChromiumCDMProxy.cpp
+++ b/dom/media/gmp/ChromiumCDMProxy.cpp
@@ -219,23 +219,36 @@ ChromiumCDMProxy::CreateSession(uint32_t
aCreateSessionToken,
sessionType,
initDataType,
aPromiseId,
Move(aInitData)));
}
void
-ChromiumCDMProxy::LoadSession(PromiseId aPromiseId, const nsAString& aSessionId)
+ChromiumCDMProxy::LoadSession(PromiseId aPromiseId,
+ dom::MediaKeySessionType aSessionType,
+ const nsAString& aSessionId)
{
MOZ_ASSERT(NS_IsMainThread());
- RejectPromise(aPromiseId,
- NS_ERROR_DOM_NOT_SUPPORTED_ERR,
- NS_LITERAL_CSTRING("loadSession is not supported"));
+ RefPtr<gmp::ChromiumCDMParent> cdm = GetCDMParent();
+ if (!cdm) {
+ RejectPromise(aPromiseId,
+ NS_ERROR_DOM_INVALID_STATE_ERR,
+ NS_LITERAL_CSTRING("Null CDM in LoadSession"));
+ return;
+ }
+
+ mGMPThread->Dispatch(NewRunnableMethod<uint32_t, uint32_t, nsString>(
+ cdm,
+ &gmp::ChromiumCDMParent::LoadSession,
+ aPromiseId,
+ ToCDMSessionType(aSessionType),
+ aSessionId));
}
void
ChromiumCDMProxy::SetServerCertificate(PromiseId aPromiseId,
nsTArray<uint8_t>& aCert)
{
MOZ_ASSERT(NS_IsMainThread());
EME_LOG("ChromiumCDMProxy::SetServerCertificate(pid=%u) certLen=%zu",
@@ -412,16 +425,21 @@ ChromiumCDMProxy::OnSetSessionId(uint32_
session->SetSessionId(aSessionId);
}
}
void
ChromiumCDMProxy::OnResolveLoadSessionPromise(uint32_t aPromiseId,
bool aSuccess)
{
+ MOZ_ASSERT(NS_IsMainThread());
+ if (mKeys.IsNull()) {
+ return;
+ }
+ mKeys->OnSessionLoaded(aPromiseId, aSuccess);
}
void
ChromiumCDMProxy::OnSessionMessage(const nsAString& aSessionId,
dom::MediaKeyMessageType aMessageType,
nsTArray<uint8_t>& aMessage)
{
MOZ_ASSERT(NS_IsMainThread());
--- a/dom/media/gmp/ChromiumCDMProxy.h
+++ b/dom/media/gmp/ChromiumCDMProxy.h
@@ -34,17 +34,19 @@ public:
const nsAString& aGMPName) override;
void CreateSession(uint32_t aCreateSessionToken,
dom::MediaKeySessionType aSessionType,
PromiseId aPromiseId,
const nsAString& aInitDataType,
nsTArray<uint8_t>& aInitData) override;
- void LoadSession(PromiseId aPromiseId, const nsAString& aSessionId) 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;
--- a/dom/media/gmp/GMPCDMProxy.cpp
+++ b/dom/media/gmp/GMPCDMProxy.cpp
@@ -323,16 +323,17 @@ GMPCDMProxy::gmp_CreateSession(UniquePtr
aData->mPromiseId,
aData->mInitDataType,
aData->mInitData,
ToGMPSessionType(aData->mSessionType));
}
void
GMPCDMProxy::LoadSession(PromiseId aPromiseId,
+ dom::MediaKeySessionType aSessionType,
const nsAString& aSessionId)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mOwnerThread);
UniquePtr<SessionOpData> data(new SessionOpData());
data->mPromiseId = aPromiseId;
data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
--- a/dom/media/gmp/GMPCDMProxy.h
+++ b/dom/media/gmp/GMPCDMProxy.h
@@ -38,16 +38,17 @@ public:
void CreateSession(uint32_t aCreateSessionToken,
dom::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;
--- a/dom/media/gmp/PChromiumCDM.ipdl
+++ b/dom/media/gmp/PChromiumCDM.ipdl
@@ -21,16 +21,20 @@ child:
async SetServerCertificate(uint32_t aPromiseId,
uint8_t[] aServerCert);
async CreateSessionAndGenerateRequest(uint32_t aPromiseId,
uint32_t aSessionType,
uint32_t aInitDataType,
uint8_t[] aInitData);
+ async LoadSession(uint32_t aPromiseId,
+ uint32_t aSessionType,
+ nsCString aSessionId);
+
async UpdateSession(uint32_t aPromiseId,
nsCString aSessionId,
uint8_t[] aResponse);
async CloseSession(uint32_t aPromiseId,
nsCString aSessionId);
async RemoveSession(uint32_t aPromiseId,
@@ -75,16 +79,18 @@ parent:
async OnSessionClosed(nsCString aSessionId);
async OnLegacySessionError(nsCString aSessionId,
uint32_t aError,
uint32_t aSystemCode,
nsCString aMessage);
+ async ResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccessful);
+
// Return values of cdm::ContentDecryptionModule8::Decrypt
async Decrypted(uint32_t aId, uint32_t aStatus, uint8_t[] aData);
async OnDecoderInitDone(uint32_t aStatus);
// Return values of cdm::ContentDecryptionModule8::DecryptAndDecodeFrame
async Decoded(CDMVideoFrame aFrame);
async DecodeFailed(uint32_t aStatus);