--- a/dom/media/eme/CDMCaps.cpp
+++ b/dom/media/eme/CDMCaps.cpp
@@ -38,24 +38,25 @@ CDMCaps::AutoLock::AutoLock(CDMCaps& aIn
mData.Lock();
}
CDMCaps::AutoLock::~AutoLock()
{
mData.Unlock();
}
-// Keys with kGMPUsable, kGMPOutputDownscaled, or kGMPOutputRestricted status
-// can be used by the CDM to decrypt or decrypt-and-decode samples.
+// Keys with MediaKeyStatus::Usable, MediaKeyStatus::Output_downscaled,
+// or MediaKeyStatus::Output_restricted status can be used by the CDM
+// to decrypt or decrypt-and-decode samples.
static bool
-IsUsableStatus(GMPMediaKeyStatus aStatus)
+IsUsableStatus(dom::MediaKeyStatus aStatus)
{
- return aStatus == kGMPUsable ||
- aStatus == kGMPOutputRestricted ||
- aStatus == kGMPOutputDownscaled;
+ return aStatus == dom::MediaKeyStatus::Usable ||
+ aStatus == dom::MediaKeyStatus::Output_restricted ||
+ aStatus == dom::MediaKeyStatus::Output_downscaled;
}
bool
CDMCaps::AutoLock::IsKeyUsable(const CencKeyId& aKeyId)
{
mData.mMonitor.AssertCurrentThreadOwns();
for (const KeyStatus& keyStatus : mData.mKeyStatuses) {
if (keyStatus.mId == aKeyId) {
@@ -63,48 +64,51 @@ CDMCaps::AutoLock::IsKeyUsable(const Cen
}
}
return false;
}
bool
CDMCaps::AutoLock::SetKeyStatus(const CencKeyId& aKeyId,
const nsString& aSessionId,
- GMPMediaKeyStatus aStatus)
+ const dom::Optional<dom::MediaKeyStatus>& aStatus)
{
mData.mMonitor.AssertCurrentThreadOwns();
- KeyStatus key(aKeyId, aSessionId, aStatus);
- if (aStatus == kGMPUnknown) {
+ if (!aStatus.WasPassed()) {
+ // Called from ForgetKeyStatus.
// Return true if the element is found to notify key changes.
- return mData.mKeyStatuses.RemoveElement(key);
+ return mData.mKeyStatuses.RemoveElement(KeyStatus(aKeyId,
+ aSessionId,
+ dom::MediaKeyStatus::Internal_error));
}
+ KeyStatus key(aKeyId, aSessionId, aStatus.Value());
auto index = mData.mKeyStatuses.IndexOf(key);
if (index != mData.mKeyStatuses.NoIndex) {
- if (mData.mKeyStatuses[index].mStatus == aStatus) {
+ if (mData.mKeyStatuses[index].mStatus == aStatus.Value()) {
// No change.
return false;
}
auto oldStatus = mData.mKeyStatuses[index].mStatus;
- mData.mKeyStatuses[index].mStatus = aStatus;
+ mData.mKeyStatuses[index].mStatus = aStatus.Value();
// The old key status was one for which we can decrypt media. We don't
// need to do the "notify usable" step below, as it should be impossible
// for us to have anything waiting on this key to become usable, since it
// was already usable.
if (IsUsableStatus(oldStatus)) {
return true;
}
} else {
mData.mKeyStatuses.AppendElement(key);
}
// Only call NotifyUsable() for a key when we are going from non-usable
// to usable state.
- if (!IsUsableStatus(aStatus)) {
+ if (!IsUsableStatus(aStatus.Value())) {
return true;
}
auto& waiters = mData.mWaitForKeys;
size_t i = 0;
while (i < waiters.Length()) {
auto& w = waiters[i];
if (w.mKeyId == aKeyId) {
@@ -150,15 +154,17 @@ CDMCaps::AutoLock::GetSessionIdsForKeyId
}
bool
CDMCaps::AutoLock::RemoveKeysForSession(const nsString& aSessionId)
{
bool changed = false;
nsTArray<KeyStatus> statuses;
GetKeyStatusesForSession(aSessionId, statuses);
- for (const KeyStatus& keyStatus : statuses) {
- changed |= SetKeyStatus(keyStatus.mId, aSessionId, kGMPUnknown);
+ for (const KeyStatus& status : statuses) {
+ changed |= SetKeyStatus(status.mId,
+ aSessionId,
+ dom::Optional<dom::MediaKeyStatus>());
}
return changed;
}
} // namespace mozilla
--- a/dom/media/eme/CDMCaps.h
+++ b/dom/media/eme/CDMCaps.h
@@ -2,68 +2,73 @@
/* 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 CDMCaps_h_
#define CDMCaps_h_
-#include "nsString.h"
-#include "mozilla/Monitor.h"
+#include "gmp-decryption.h"
#include "nsIThread.h"
#include "nsTArray.h"
-#include "mozilla/Attributes.h"
+#include "nsString.h"
#include "SamplesWaitingForKey.h"
-#include "gmp-decryption.h"
+
+#include "mozilla/Monitor.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/dom/MediaKeyStatusMapBinding.h" // For MediaKeyStatus
+#include "mozilla/dom/BindingDeclarations.h" // For Optional
namespace mozilla {
// CDM capabilities; what keys a CDMProxy can use.
// Must be locked to access state.
class CDMCaps {
public:
CDMCaps();
~CDMCaps();
struct KeyStatus {
KeyStatus(const CencKeyId& aId,
const nsString& aSessionId,
- GMPMediaKeyStatus aStatus)
+ dom::MediaKeyStatus aStatus)
: mId(aId)
, mSessionId(aSessionId)
, mStatus(aStatus)
{}
KeyStatus(const KeyStatus& aOther)
: mId(aOther.mId)
, mSessionId(aOther.mSessionId)
, mStatus(aOther.mStatus)
{}
bool operator==(const KeyStatus& aOther) const {
return mId == aOther.mId &&
mSessionId == aOther.mSessionId;
};
CencKeyId mId;
nsString mSessionId;
- GMPMediaKeyStatus mStatus;
+ dom::MediaKeyStatus mStatus;
};
// Locks the CDMCaps. It must be locked to access its shared state.
// Threadsafe when locked.
class MOZ_STACK_CLASS AutoLock {
public:
explicit AutoLock(CDMCaps& aKeyCaps);
~AutoLock();
bool IsKeyUsable(const CencKeyId& aKeyId);
// Returns true if key status changed,
// i.e. the key status changed from usable to expired.
- bool SetKeyStatus(const CencKeyId& aKeyId, const nsString& aSessionId, GMPMediaKeyStatus aStatus);
+ bool SetKeyStatus(const CencKeyId& aKeyId,
+ const nsString& aSessionId,
+ const dom::Optional<dom::MediaKeyStatus>& aStatus);
void GetKeyStatusesForSession(const nsAString& aSessionId,
nsTArray<KeyStatus>& aOutKeyStatuses);
void GetSessionIdsForKeyId(const CencKeyId& aKeyId,
nsTArray<nsCString>& aOutSessionIds);
// Ensures all keys for a session are marked as 'unknown', i.e. removed.
--- a/dom/media/eme/CDMProxy.h
+++ b/dom/media/eme/CDMProxy.h
@@ -29,16 +29,18 @@ struct DecryptResult {
DecryptResult(DecryptStatus aStatus, MediaRawData* aSample)
: mStatus(aStatus)
, mSample(aSample)
{}
DecryptStatus mStatus;
RefPtr<MediaRawData> mSample;
};
+typedef int64_t UnixTime;
+
// Proxies calls CDM, and proxies calls back.
// Note: Promises are passed in via a PromiseId, so that the ID can be
// passed via IPC to the CDM, which can then signal when to reject or
// resolve the promise using its PromiseId.
class CDMProxy {
protected:
typedef dom::PromiseId PromiseId;
typedef dom::MediaKeySessionType MediaKeySessionType;
@@ -137,17 +139,17 @@ public:
// Main thread only.
virtual void OnSessionMessage(const nsAString& aSessionId,
dom::MediaKeyMessageType aMessageType,
nsTArray<uint8_t>& aMessage) = 0;
// Main thread only.
virtual void OnExpirationChange(const nsAString& aSessionId,
- int64_t aExpiryTime) = 0;
+ UnixTime aExpiryTime) = 0;
// Main thread only.
virtual void OnSessionClosed(const nsAString& aSessionId) = 0;
// Main thread only.
virtual void OnSessionError(const nsAString& aSessionId,
nsresult aException,
uint32_t aSystemCode,
--- a/dom/media/eme/DecryptorProxyCallback.h
+++ b/dom/media/eme/DecryptorProxyCallback.h
@@ -1,48 +1,56 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 DecryptorProxyCallback_h_
#define DecryptorProxyCallback_h_
+#include "mozilla/dom/MediaKeyStatusMapBinding.h" // For MediaKeyStatus
+#include "mozilla/dom/MediaKeyMessageEventBinding.h" // For MediaKeyMessageType
+#include "mozilla/CDMProxy.h"
+
class DecryptorProxyCallback {
public:
+
virtual ~DecryptorProxyCallback() {}
virtual void SetSessionId(uint32_t aCreateSessionId,
const nsCString& aSessionId) = 0;
virtual void ResolveLoadSessionPromise(uint32_t aPromiseId,
bool aSuccess) = 0;
virtual void ResolvePromise(uint32_t aPromiseId) = 0;
virtual void RejectPromise(uint32_t aPromiseId,
nsresult aException,
const nsCString& aSessionId) = 0;
virtual void SessionMessage(const nsCString& aSessionId,
- GMPSessionMessageType aMessageType,
+ mozilla::dom::MediaKeyMessageType aMessageType,
const nsTArray<uint8_t>& aMessage) = 0;
virtual void ExpirationChange(const nsCString& aSessionId,
- GMPTimestamp aExpiryTime) = 0;
+ mozilla::UnixTime aExpiryTime) = 0;
virtual void SessionClosed(const nsCString& aSessionId) = 0;
virtual void SessionError(const nsCString& aSessionId,
nsresult aException,
uint32_t aSystemCode,
const nsCString& aMessage) = 0;
virtual void KeyStatusChanged(const nsCString& aSessionId,
const nsTArray<uint8_t>& aKeyId,
- GMPMediaKeyStatus aStatus) = 0;
+ mozilla::dom::MediaKeyStatus aStatus) = 0;
+
+ virtual void ForgetKeyStatus(const nsCString& aSessionId,
+ const nsTArray<uint8_t>& aKeyId) = 0;
virtual void Decrypted(uint32_t aId,
- GMPErr aResult,
+ mozilla::DecryptStatus aResult,
const nsTArray<uint8_t>& aDecryptedData) = 0;
};
#endif
\ No newline at end of file
--- a/dom/media/eme/MediaKeySession.cpp
+++ b/dom/media/eme/MediaKeySession.cpp
@@ -139,19 +139,20 @@ MediaKeySession::UpdateKeyStatusMap()
}
mKeyStatusMap->Update(keyStatuses);
if (EME_LOG_ENABLED()) {
nsAutoCString message(
nsPrintfCString("MediaKeySession[%p,'%s'] key statuses change {",
this, NS_ConvertUTF16toUTF8(mSessionId).get()));
+ using IntegerType = typename std::underlying_type<MediaKeyStatus>::type;
for (const CDMCaps::KeyStatus& status : keyStatuses) {
message.Append(nsPrintfCString(" (%s,%s)", ToBase64(status.mId).get(),
- MediaKeyStatusValues::strings[status.mStatus].value));
+ MediaKeyStatusValues::strings[static_cast<IntegerType>(status.mStatus)].value));
}
message.Append(" }");
EME_LOG(message.get());
}
}
MediaKeyStatusMap*
MediaKeySession::KeyStatuses() const
--- a/dom/media/eme/MediaKeyStatusMap.cpp
+++ b/dom/media/eme/MediaKeyStatusMap.cpp
@@ -103,33 +103,19 @@ MediaKeyStatusMap::GetValueAtIndex(uint3
}
uint32_t
MediaKeyStatusMap::Size() const
{
return mStatuses.Length();
}
-static MediaKeyStatus
-ToMediaKeyStatus(GMPMediaKeyStatus aStatus) {
- switch (aStatus) {
- case kGMPUsable: return MediaKeyStatus::Usable;
- case kGMPExpired: return MediaKeyStatus::Expired;
- case kGMPOutputDownscaled: return MediaKeyStatus::Output_downscaled;
- case kGMPOutputRestricted: return MediaKeyStatus::Output_restricted;
- case kGMPInternalError: return MediaKeyStatus::Internal_error;
- case kGMPReleased: return MediaKeyStatus::Released;
- case kGMPStatusPending: return MediaKeyStatus::Status_pending;
- default: return MediaKeyStatus::Internal_error;
- }
-}
-
void
MediaKeyStatusMap::Update(const nsTArray<CDMCaps::KeyStatus>& aKeys)
{
mStatuses.Clear();
for (const auto& key : aKeys) {
- mStatuses.InsertElementSorted(KeyStatus(key.mId, ToMediaKeyStatus(key.mStatus)));
+ mStatuses.InsertElementSorted(KeyStatus(key.mId, key.mStatus));
}
}
} // namespace dom
} // namespace mozilla
--- a/dom/media/gmp/GMPCDMCallbackProxy.cpp
+++ b/dom/media/gmp/GMPCDMCallbackProxy.cpp
@@ -133,55 +133,44 @@ GMPCDMCallbackProxy::RejectPromise(uint3
nsCOMPtr<nsIRunnable> task;
task = new RejectPromiseTask(mProxy,
aPromiseId,
aException,
aMessage);
NS_DispatchToMainThread(task);
}
-static dom::MediaKeyMessageType
-ToMediaKeyMessageType(GMPSessionMessageType aMessageType) {
- switch (aMessageType) {
- case kGMPLicenseRequest: return dom::MediaKeyMessageType::License_request;
- case kGMPLicenseRenewal: return dom::MediaKeyMessageType::License_renewal;
- case kGMPLicenseRelease: return dom::MediaKeyMessageType::License_release;
- case kGMPIndividualizationRequest: return dom::MediaKeyMessageType::Individualization_request;
- default: return dom::MediaKeyMessageType::License_request;
- };
-};
-
class SessionMessageTask : public Runnable {
public:
SessionMessageTask(CDMProxy* aProxy,
const nsCString& aSessionId,
- GMPSessionMessageType aMessageType,
+ dom::MediaKeyMessageType aMessageType,
const nsTArray<uint8_t>& aMessage)
: mProxy(aProxy)
, mSid(NS_ConvertUTF8toUTF16(aSessionId))
, mMsgType(aMessageType)
{
mMsg.AppendElements(aMessage);
}
NS_IMETHOD Run() override {
- mProxy->OnSessionMessage(mSid, ToMediaKeyMessageType(mMsgType), mMsg);
+ mProxy->OnSessionMessage(mSid, mMsgType, mMsg);
return NS_OK;
}
RefPtr<CDMProxy> mProxy;
dom::PromiseId mPid;
nsString mSid;
- GMPSessionMessageType mMsgType;
+ dom::MediaKeyMessageType mMsgType;
nsTArray<uint8_t> mMsg;
};
void
GMPCDMCallbackProxy::SessionMessage(const nsCString& aSessionId,
- GMPSessionMessageType aMessageType,
+ dom::MediaKeyMessageType aMessageType,
const nsTArray<uint8_t>& aMessage)
{
MOZ_ASSERT(mProxy->IsOnOwnerThread());
nsCOMPtr<nsIRunnable> task;
task = new SessionMessageTask(mProxy,
aSessionId,
aMessageType,
@@ -289,55 +278,65 @@ GMPCDMCallbackProxy::SessionError(const
aSystemCode,
aMessage);
NS_DispatchToMainThread(task);
}
void
GMPCDMCallbackProxy::KeyStatusChanged(const nsCString& aSessionId,
const nsTArray<uint8_t>& aKeyId,
- GMPMediaKeyStatus aStatus)
+ dom::MediaKeyStatus aStatus)
{
MOZ_ASSERT(mProxy->IsOnOwnerThread());
+ KeyStatusChangedInternal(aSessionId,
+ aKeyId,
+ dom::Optional<dom::MediaKeyStatus>(aStatus));
+}
+
+void
+GMPCDMCallbackProxy::ForgetKeyStatus(const nsCString& aSessionId,
+ const nsTArray<uint8_t>& aKeyId)
+{
+ MOZ_ASSERT(mProxy->IsOnOwnerThread());
+
+ KeyStatusChangedInternal(aSessionId,
+ aKeyId,
+ dom::Optional<dom::MediaKeyStatus>());
+}
+
+void
+GMPCDMCallbackProxy::KeyStatusChangedInternal(const nsCString& aSessionId,
+ const nsTArray<uint8_t>& aKeyId,
+ const dom::Optional<dom::MediaKeyStatus>& aStatus)
+{
bool keyStatusesChange = false;
{
CDMCaps::AutoLock caps(mProxy->Capabilites());
keyStatusesChange = caps.SetKeyStatus(aKeyId,
NS_ConvertUTF8toUTF16(aSessionId),
aStatus);
}
if (keyStatusesChange) {
nsCOMPtr<nsIRunnable> task;
task = NewRunnableMethod<nsString>(mProxy,
&CDMProxy::OnKeyStatusesChange,
NS_ConvertUTF8toUTF16(aSessionId));
NS_DispatchToMainThread(task);
}
}
-DecryptStatus
-ToDecryptStatus(GMPErr aError)
-{
- switch (aError) {
- case GMPNoErr: return Ok;
- case GMPNoKeyErr: return NoKeyErr;
- case GMPAbortedErr: return AbortedErr;
- default: return GenericErr;
- }
-}
-
void
GMPCDMCallbackProxy::Decrypted(uint32_t aId,
- GMPErr aResult,
+ DecryptStatus aResult,
const nsTArray<uint8_t>& aDecryptedData)
{
MOZ_ASSERT(mProxy->IsOnOwnerThread());
- mProxy->OnDecrypted(aId, ToDecryptStatus(aResult), aDecryptedData);
+ mProxy->OnDecrypted(aId, aResult, aDecryptedData);
}
void
GMPCDMCallbackProxy::Terminated()
{
MOZ_ASSERT(mProxy->IsOnOwnerThread());
nsCOMPtr<nsIRunnable> task = NewRunnableMethod(mProxy, &CDMProxy::Terminated);
NS_DispatchToMainThread(task);
--- a/dom/media/gmp/GMPCDMCallbackProxy.h
+++ b/dom/media/gmp/GMPCDMCallbackProxy.h
@@ -25,44 +25,50 @@ public:
void ResolvePromise(uint32_t aPromiseId) override;
void RejectPromise(uint32_t aPromiseId,
nsresult aException,
const nsCString& aSessionId) override;
void SessionMessage(const nsCString& aSessionId,
- GMPSessionMessageType aMessageType,
+ dom::MediaKeyMessageType aMessageType,
const nsTArray<uint8_t>& aMessage) override;
void ExpirationChange(const nsCString& aSessionId,
- GMPTimestamp aExpiryTime) override;
+ UnixTime aExpiryTime) override;
void SessionClosed(const nsCString& aSessionId) override;
void SessionError(const nsCString& aSessionId,
nsresult aException,
uint32_t aSystemCode,
const nsCString& aMessage) override;
void KeyStatusChanged(const nsCString& aSessionId,
const nsTArray<uint8_t>& aKeyId,
- GMPMediaKeyStatus aStatus) override;
+ dom::MediaKeyStatus aStatus) override;
+
+ void ForgetKeyStatus(const nsCString& aSessionId,
+ const nsTArray<uint8_t>& aKeyId) override;
void Decrypted(uint32_t aId,
- GMPErr aResult,
+ DecryptStatus aResult,
const nsTArray<uint8_t>& aDecryptedData) override;
void Terminated() override;
~GMPCDMCallbackProxy() {}
private:
friend class GMPCDMProxy;
explicit GMPCDMCallbackProxy(CDMProxy* aProxy);
+ void KeyStatusChangedInternal(const nsCString& aSessionId,
+ const nsTArray<uint8_t>& aKeyId,
+ const dom::Optional<dom::MediaKeyStatus>& aStatus);
// Warning: Weak ref.
CDMProxy* mProxy;
};
} // namespace mozilla
#endif // GMPCDMCallbackProxy_h_
--- a/dom/media/gmp/GMPDecryptorChild.cpp
+++ b/dom/media/gmp/GMPDecryptorChild.cpp
@@ -156,19 +156,26 @@ void
GMPDecryptorChild::KeyStatusChanged(const char* aSessionId,
uint32_t aSessionIdLength,
const uint8_t* aKeyId,
uint32_t aKeyIdLength,
GMPMediaKeyStatus aStatus)
{
AutoTArray<uint8_t, 16> kid;
kid.AppendElements(aKeyId, aKeyIdLength);
- CALL_ON_GMP_THREAD(SendKeyStatusChanged,
- nsCString(aSessionId, aSessionIdLength), kid,
- aStatus);
+ if (aStatus == kGMPUnknown) {
+ CALL_ON_GMP_THREAD(SendForgetKeyStatus,
+ nsCString(aSessionId, aSessionIdLength),
+ kid);
+ } else {
+ CALL_ON_GMP_THREAD(SendKeyStatusChanged,
+ nsCString(aSessionId, aSessionIdLength),
+ kid,
+ aStatus);
+ }
}
void
GMPDecryptorChild::Decrypted(GMPBuffer* aBuffer, GMPErr aResult)
{
if (!ON_GMP_THREAD()) {
// We should run this whole method on the GMP thread since the buffer needs
// to be deleted after the SendDecrypted call.
--- a/dom/media/gmp/GMPDecryptorParent.cpp
+++ b/dom/media/gmp/GMPDecryptorParent.cpp
@@ -260,29 +260,41 @@ GMPDecryptorParent::RecvRejectPromise(co
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return false;
}
mCallback->RejectPromise(aPromiseId, GMPExToNsresult(aException), aMessage);
return true;
}
+
+static dom::MediaKeyMessageType
+ToMediaKeyMessageType(GMPSessionMessageType aMessageType) {
+ switch (aMessageType) {
+ case kGMPLicenseRequest: return dom::MediaKeyMessageType::License_request;
+ case kGMPLicenseRenewal: return dom::MediaKeyMessageType::License_renewal;
+ case kGMPLicenseRelease: return dom::MediaKeyMessageType::License_release;
+ case kGMPIndividualizationRequest: return dom::MediaKeyMessageType::Individualization_request;
+ default: return dom::MediaKeyMessageType::License_request;
+ };
+};
+
bool
GMPDecryptorParent::RecvSessionMessage(const nsCString& aSessionId,
const GMPSessionMessageType& aMessageType,
nsTArray<uint8_t>&& aMessage)
{
LOGD(("GMPDecryptorParent[%p]::RecvSessionMessage(sessionId='%s', type=%d, msg='%s')",
this, aSessionId.get(), aMessageType, ToBase64(aMessage).get()));
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return false;
}
- mCallback->SessionMessage(aSessionId, aMessageType, aMessage);
+ mCallback->SessionMessage(aSessionId, ToMediaKeyMessageType(aMessageType), aMessage);
return true;
}
bool
GMPDecryptorParent::RecvExpirationChange(const nsCString& aSessionId,
const double& aExpiryTime)
{
LOGD(("GMPDecryptorParent[%p]::RecvExpirationChange(sessionId='%s', expiry=%lf)",
@@ -326,43 +338,81 @@ GMPDecryptorParent::RecvSessionError(con
}
mCallback->SessionError(aSessionId,
GMPExToNsresult(aException),
aSystemCode,
aMessage);
return true;
}
+static dom::MediaKeyStatus
+ToMediaKeyStatus(GMPMediaKeyStatus aStatus) {
+ switch (aStatus) {
+ case kGMPUsable: return dom::MediaKeyStatus::Usable;
+ case kGMPExpired: return dom::MediaKeyStatus::Expired;
+ case kGMPOutputDownscaled: return dom::MediaKeyStatus::Output_downscaled;
+ case kGMPOutputRestricted: return dom::MediaKeyStatus::Output_restricted;
+ case kGMPInternalError: return dom::MediaKeyStatus::Internal_error;
+ case kGMPReleased: return dom::MediaKeyStatus::Released;
+ case kGMPStatusPending: return dom::MediaKeyStatus::Status_pending;
+ default: return dom::MediaKeyStatus::Internal_error;
+ }
+}
+
bool
GMPDecryptorParent::RecvKeyStatusChanged(const nsCString& aSessionId,
InfallibleTArray<uint8_t>&& aKeyId,
const GMPMediaKeyStatus& aStatus)
{
LOGD(("GMPDecryptorParent[%p]::RecvKeyStatusChanged(sessionId='%s', keyId=%s, status=%d)",
this, aSessionId.get(), ToBase64(aKeyId).get(), aStatus));
if (mIsOpen) {
- mCallback->KeyStatusChanged(aSessionId, aKeyId, aStatus);
+ mCallback->KeyStatusChanged(aSessionId, aKeyId, ToMediaKeyStatus(aStatus));
}
return true;
}
bool
+GMPDecryptorParent::RecvForgetKeyStatus(const nsCString& aSessionId,
+ InfallibleTArray<uint8_t>&& aKeyId)
+{
+ LOGD(("GMPDecryptorParent[%p]::RecvForgetKeyStatus(sessionId='%s', keyId=%s)",
+ this, aSessionId.get(), ToBase64(aKeyId).get()));
+
+ if (mIsOpen) {
+ mCallback->ForgetKeyStatus(aSessionId, aKeyId);
+ }
+ return true;
+}
+
+DecryptStatus
+ToDecryptStatus(GMPErr aError)
+{
+ switch (aError) {
+ case GMPNoErr: return Ok;
+ case GMPNoKeyErr: return NoKeyErr;
+ case GMPAbortedErr: return AbortedErr;
+ default: return GenericErr;
+ }
+}
+
+bool
GMPDecryptorParent::RecvDecrypted(const uint32_t& aId,
const GMPErr& aErr,
InfallibleTArray<uint8_t>&& aBuffer)
{
LOGV(("GMPDecryptorParent[%p]::RecvDecrypted(id=%d, err=%d)",
this, aId, aErr));
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return false;
}
- mCallback->Decrypted(aId, aErr, aBuffer);
+ mCallback->Decrypted(aId, ToDecryptStatus(aErr), aBuffer);
return true;
}
bool
GMPDecryptorParent::RecvShutdown()
{
LOGD(("GMPDecryptorParent[%p]::RecvShutdown()", this));
--- a/dom/media/gmp/GMPDecryptorParent.h
+++ b/dom/media/gmp/GMPDecryptorParent.h
@@ -97,16 +97,19 @@ private:
const GMPDOMException& aException,
const uint32_t& aSystemCode,
const nsCString& aMessage) override;
bool RecvKeyStatusChanged(const nsCString& aSessionId,
InfallibleTArray<uint8_t>&& aKeyId,
const GMPMediaKeyStatus& aStatus) override;
+ bool RecvForgetKeyStatus(const nsCString& aSessionId,
+ InfallibleTArray<uint8_t>&& aKeyId) override;
+
bool RecvDecrypted(const uint32_t& aId,
const GMPErr& aErr,
InfallibleTArray<uint8_t>&& aBuffer) override;
bool RecvShutdown() override;
void ActorDestroy(ActorDestroyReason aWhy) override;
bool Recv__delete__() override;
--- a/dom/media/gmp/PGMPDecryptor.ipdl
+++ b/dom/media/gmp/PGMPDecryptor.ipdl
@@ -77,15 +77,17 @@ parent:
async SessionError(nsCString aSessionId,
GMPDOMException aDOMExceptionCode,
uint32_t aSystemCode,
nsCString aMessage);
async KeyStatusChanged(nsCString aSessionId, uint8_t[] aKey,
GMPMediaKeyStatus aStatus);
+ async ForgetKeyStatus(nsCString aSessionId, uint8_t[] aKey);
+
async Decrypted(uint32_t aId, GMPErr aResult, uint8_t[] aBuffer);
async Shutdown();
};
} // namespace gmp
} // namespace mozilla
--- a/dom/media/gtest/TestGMPCrossOrigin.cpp
+++ b/dom/media/gtest/TestGMPCrossOrigin.cpp
@@ -17,16 +17,18 @@
#include "MediaPrefs.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsIFile.h"
#include "nsISimpleEnumerator.h"
#include "mozilla/Atomics.h"
#include "nsNSSComponent.h"
#include "mozilla/DebugOnly.h"
#include "GMPDeviceBinding.h"
+#include "mozilla/dom/MediaKeyStatusMapBinding.h" // For MediaKeyStatus
+#include "mozilla/dom/MediaKeyMessageEventBinding.h" // For MediaKeyMessageType
#if defined(XP_WIN)
#include "mozilla/WindowsVersion.h"
#endif
using namespace std;
using namespace mozilla;
@@ -1339,17 +1341,17 @@ class GMPStorageTest : public GMPDecrypt
void SetFinished() {
mFinished = true;
Shutdown();
NS_DispatchToMainThread(NewRunnableMethod(this, &GMPStorageTest::Dummy));
}
void SessionMessage(const nsCString& aSessionId,
- GMPSessionMessageType aMessageType,
+ mozilla::dom::MediaKeyMessageType aMessageType,
const nsTArray<uint8_t>& aMessage) override
{
MonitorAutoLock mon(mMonitor);
nsCString msg((const char*)aMessage.Elements(), aMessage.Length());
EXPECT_TRUE(mExpected.Length() > 0);
bool matches = mExpected[0].mMessage.Equals(msg);
EXPECT_STREQ(mExpected[0].mMessage.get(), msg.get());
@@ -1366,27 +1368,31 @@ class GMPStorageTest : public GMPDecrypt
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 ExpirationChange(const nsCString& aSessionId,
- GMPTimestamp aExpiryTime) override {}
+ UnixTime aExpiryTime) override {}
void SessionClosed(const nsCString& aSessionId) override {}
void SessionError(const nsCString& aSessionId,
nsresult aException,
uint32_t aSystemCode,
const nsCString& aMessage) override {}
void KeyStatusChanged(const nsCString& aSessionId,
const nsTArray<uint8_t>& aKeyId,
- GMPMediaKeyStatus aStatus) override { }
+ mozilla::dom::MediaKeyStatus aStatus) override { }
+
+ void ForgetKeyStatus(const nsCString& aSessionId,
+ const nsTArray<uint8_t>& aKeyId) override { }
+
void Decrypted(uint32_t aId,
- GMPErr aResult,
+ mozilla::DecryptStatus aResult,
const nsTArray<uint8_t>& aDecryptedData) override { }
void Terminated() override {
if (mDecryptor) {
mDecryptor->Close();
mDecryptor = nullptr;
}
}