Bug 1315850 - Implement CDM persistent sessions. r=gerald

This is required for the browser clearing persistence tests to pass.

MozReview-Commit-ID: Ai9qc6Ds1IG

--HG--
extra : rebase_source : 80c2133e26742410fda983e3c18c35736fc013d0
This commit is contained in:
Chris Pearce 2017-03-09 19:09:43 +13:00
parent cfe7c116ce
commit caac622c6d
13 changed files with 131 additions and 6 deletions

View File

@ -115,6 +115,7 @@ public:
// 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.

View File

@ -396,7 +396,7 @@ MediaKeySession::Load(const nsAString& aSessionId, ErrorResult& aRv)
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);

View File

@ -101,6 +101,7 @@ MediaDrmCDMProxy::CreateSession(uint32_t aCreateSessionToken,
void
MediaDrmCDMProxy::LoadSession(PromiseId aPromiseId,
dom::MediaKeySessionType aSessionType,
const nsAString& aSessionId)
{
// TODO: Implement LoadSession.

View File

@ -13,6 +13,7 @@
#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"
@ -47,6 +48,7 @@ public:
nsTArray<uint8_t>& aInitData) override;
void LoadSession(PromiseId aPromiseId,
dom::MediaKeySessionType aSessionType,
const nsAString& aSessionId) override;
void SetServerCertificate(PromiseId aPromiseId,

View File

@ -79,6 +79,23 @@ ChromiumCDMChild::OnResolveNewSessionPromise(uint32_t aPromiseId,
", 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));
}
@ -294,6 +311,25 @@ ChromiumCDMChild::RecvCreateSessionAndGenerateRequest(
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,

View File

@ -88,6 +88,9 @@ protected:
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;
@ -114,6 +117,7 @@ protected:
typedef SimpleMap<uint64_t> DurationMap;
DurationMap mFrameDurations;
nsTArray<uint32_t> mLoadSessionPromiseIds;
bool mDecoderInitialized = false;
bool mPersistentStateAllowed = false;

View File

@ -66,6 +66,32 @@ ChromiumCDMParent::CreateSession(uint32_t aCreateSessionToken,
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)
@ -236,6 +262,26 @@ ChromiumCDMParent::RecvOnResolveNewSessionPromise(const uint32_t& 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)
{

View File

@ -46,6 +46,10 @@ public:
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);
@ -84,6 +88,9 @@ protected:
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,

View File

@ -224,13 +224,26 @@ ChromiumCDMProxy::CreateSession(uint32_t aCreateSessionToken,
}
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
@ -417,6 +430,11 @@ void
ChromiumCDMProxy::OnResolveLoadSessionPromise(uint32_t aPromiseId,
bool aSuccess)
{
MOZ_ASSERT(NS_IsMainThread());
if (mKeys.IsNull()) {
return;
}
mKeys->OnSessionLoaded(aPromiseId, aSuccess);
}
void

View File

@ -39,7 +39,9 @@ public:
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;

View File

@ -328,6 +328,7 @@ GMPCDMProxy::gmp_CreateSession(UniquePtr<CreateSessionData>&& aData)
void
GMPCDMProxy::LoadSession(PromiseId aPromiseId,
dom::MediaKeySessionType aSessionType,
const nsAString& aSessionId)
{
MOZ_ASSERT(NS_IsMainThread());

View File

@ -43,6 +43,7 @@ public:
nsTArray<uint8_t>& aInitData) override;
void LoadSession(PromiseId aPromiseId,
dom::MediaKeySessionType aSessionType,
const nsAString& aSessionId) override;
void SetServerCertificate(PromiseId aPromiseId,

View File

@ -26,6 +26,10 @@ child:
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);
@ -80,6 +84,8 @@ parent:
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);