mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-09 04:25:38 +00:00
Bug 1081755 - Implement MediaKeySession keyschange event. r=edwin,bz
This commit is contained in:
parent
ae49c5abce
commit
67088a0aad
@ -496,6 +496,7 @@ GK_ATOM(keepcurrentinview, "keepcurrentinview")
|
||||
GK_ATOM(keepobjectsalive, "keepobjectsalive")
|
||||
GK_ATOM(key, "key")
|
||||
GK_ATOM(keycode, "keycode")
|
||||
GK_ATOM(keyschange, "keyschange")
|
||||
GK_ATOM(keydown, "keydown")
|
||||
GK_ATOM(keygen, "keygen")
|
||||
GK_ATOM(keypress, "keypress")
|
||||
|
@ -272,8 +272,18 @@ CDMCallbackProxy::KeyIdUsable(const nsCString& aSessionId,
|
||||
{
|
||||
MOZ_ASSERT(mProxy->IsOnGMPThread());
|
||||
|
||||
CDMCaps::AutoLock caps(mProxy->Capabilites());
|
||||
caps.SetKeyUsable(aKeyId, NS_ConvertUTF8toUTF16(aSessionId));
|
||||
bool keysChange = false;
|
||||
{
|
||||
CDMCaps::AutoLock caps(mProxy->Capabilites());
|
||||
keysChange = caps.SetKeyUsable(aKeyId, NS_ConvertUTF8toUTF16(aSessionId));
|
||||
}
|
||||
if (keysChange) {
|
||||
nsRefPtr<nsIRunnable> task;
|
||||
task = NS_NewRunnableMethodWithArg<nsString>(mProxy,
|
||||
&CDMProxy::OnKeysChange,
|
||||
NS_ConvertUTF8toUTF16(aSessionId));
|
||||
NS_DispatchToMainThread(task);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -282,8 +292,18 @@ CDMCallbackProxy::KeyIdNotUsable(const nsCString& aSessionId,
|
||||
{
|
||||
MOZ_ASSERT(mProxy->IsOnGMPThread());
|
||||
|
||||
CDMCaps::AutoLock caps(mProxy->Capabilites());
|
||||
caps.SetKeyUnusable(aKeyId, NS_ConvertUTF8toUTF16(aSessionId));
|
||||
bool keysChange = false;
|
||||
{
|
||||
CDMCaps::AutoLock caps(mProxy->Capabilites());
|
||||
keysChange = caps.SetKeyUnusable(aKeyId, NS_ConvertUTF8toUTF16(aSessionId));
|
||||
}
|
||||
if (keysChange) {
|
||||
nsRefPtr<nsIRunnable> task;
|
||||
task = NS_NewRunnableMethodWithArg<nsString>(mProxy,
|
||||
&CDMProxy::OnKeysChange,
|
||||
NS_ConvertUTF8toUTF16(aSessionId));
|
||||
NS_DispatchToMainThread(task);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -88,12 +88,16 @@ CDMCaps::AutoLock::IsKeyUsable(const CencKeyId& aKeyId)
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
CDMCaps::AutoLock::SetKeyUsable(const CencKeyId& aKeyId,
|
||||
const nsString& aSessionId)
|
||||
{
|
||||
mData.mMonitor.AssertCurrentThreadOwns();
|
||||
mData.mUsableKeyIds.AppendElement(UsableKey(aKeyId, aSessionId));
|
||||
UsableKey key(aKeyId, aSessionId);
|
||||
if (mData.mUsableKeyIds.Contains(key)) {
|
||||
return false;
|
||||
}
|
||||
mData.mUsableKeyIds.AppendElement(key);
|
||||
auto& waiters = mData.mWaitForKeys;
|
||||
size_t i = 0;
|
||||
while (i < waiters.Length()) {
|
||||
@ -110,13 +114,18 @@ CDMCaps::AutoLock::SetKeyUsable(const CencKeyId& aKeyId,
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
CDMCaps::AutoLock::SetKeyUnusable(const CencKeyId& aKeyId,
|
||||
const nsString& aSessionId)
|
||||
{
|
||||
mData.mMonitor.AssertCurrentThreadOwns();
|
||||
UsableKey key(aKeyId, aSessionId);
|
||||
if (!mData.mUsableKeyIds.Contains(key)) {
|
||||
return false;
|
||||
}
|
||||
auto& keys = mData.mUsableKeyIds;
|
||||
for (size_t i = 0; i < keys.Length(); i++) {
|
||||
if (keys[i].mId == aKeyId &&
|
||||
@ -125,6 +134,7 @@ CDMCaps::AutoLock::SetKeyUnusable(const CencKeyId& aKeyId,
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -38,8 +38,13 @@ public:
|
||||
|
||||
bool IsKeyUsable(const CencKeyId& aKeyId);
|
||||
|
||||
void SetKeyUsable(const CencKeyId& aKeyId, const nsString& aSessionId);
|
||||
void SetKeyUnusable(const CencKeyId& aKeyId, const nsString& aSessionId);
|
||||
// Returns true if setting this key usable results in the usable keys
|
||||
// changing for this session, i.e. the key was not previously marked usable.
|
||||
bool SetKeyUsable(const CencKeyId& aKeyId, const nsString& aSessionId);
|
||||
|
||||
// Returns true if setting this key unusable results in the usable keys
|
||||
// changing for this session, i.e. the key was previously marked usable.
|
||||
bool SetKeyUnusable(const CencKeyId& aKeyId, const nsString& aSessionId);
|
||||
|
||||
void DropKeysForSession(const nsAString& aSessionId);
|
||||
void GetUsableKeysForSession(const nsAString& aSessionId,
|
||||
@ -99,6 +104,11 @@ private:
|
||||
: mId(aOther.mId)
|
||||
, mSessionId(aOther.mSessionId)
|
||||
{}
|
||||
bool operator==(const UsableKey& aOther) const {
|
||||
return mId == aOther.mId &&
|
||||
mSessionId == aOther.mSessionId;
|
||||
};
|
||||
|
||||
CencKeyId mId;
|
||||
nsString mSessionId;
|
||||
};
|
||||
|
@ -425,6 +425,19 @@ CDMProxy::OnSessionMessage(const nsAString& aSessionId,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CDMProxy::OnKeysChange(const nsAString& aSessionId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mKeys.IsNull()) {
|
||||
return;
|
||||
}
|
||||
nsRefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
|
||||
if (session) {
|
||||
session->DispatchKeysChange();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CDMProxy::OnExpirationChange(const nsAString& aSessionId,
|
||||
GMPTimestamp aExpiryTime)
|
||||
|
@ -162,6 +162,9 @@ public:
|
||||
|
||||
CDMCaps& Capabilites();
|
||||
|
||||
// Main thread only.
|
||||
void OnKeysChange(const nsAString& aSessionId);
|
||||
|
||||
#ifdef DEBUG
|
||||
bool IsOnGMPThread();
|
||||
#endif
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "mozilla/CDMProxy.h"
|
||||
#include "mozilla/AsyncEventDispatcher.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -284,5 +285,24 @@ MediaKeySession::DispatchKeyError(uint32_t aSystemCode)
|
||||
asyncDispatcher->PostDOMEvent();
|
||||
}
|
||||
|
||||
void
|
||||
MediaKeySession::DispatchKeysChange()
|
||||
{
|
||||
if (IsClosed()) {
|
||||
return;
|
||||
}
|
||||
DebugOnly<nsresult> rv =
|
||||
nsContentUtils::DispatchTrustedEvent(mKeys->GetOwnerDoc(),
|
||||
this,
|
||||
NS_LITERAL_STRING("keyschange"),
|
||||
false,
|
||||
false);
|
||||
#ifdef DEBUG
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to dispatch keyschange event");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -84,6 +84,8 @@ public:
|
||||
|
||||
void DispatchKeyError(uint32_t system_code);
|
||||
|
||||
void DispatchKeysChange();
|
||||
|
||||
void OnClosed();
|
||||
|
||||
bool IsClosed() const;
|
||||
|
@ -591,5 +591,11 @@ CopyArrayBufferViewOrArrayBufferData(const ArrayBufferViewOrArrayBuffer& aBuffer
|
||||
return true;
|
||||
}
|
||||
|
||||
nsIDocument*
|
||||
MediaKeys::GetOwnerDoc() const
|
||||
{
|
||||
return mElement ? mElement->OwnerDoc() : nullptr;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -122,6 +122,10 @@ public:
|
||||
// was created, failure otherwise.
|
||||
nsresult CheckPrincipals();
|
||||
|
||||
// Returns a pointer to the bound media element's owner doc.
|
||||
// If we're not bound, this returns null.
|
||||
nsIDocument* GetOwnerDoc() const;
|
||||
|
||||
private:
|
||||
|
||||
static bool IsTypeSupported(const nsAString& aKeySystem,
|
||||
|
@ -153,6 +153,25 @@ function PlayTest(test, elem)
|
||||
elem.play();
|
||||
}
|
||||
|
||||
function KeysChangeFunc(session, keys) {
|
||||
session.keyIdsReceived = [];
|
||||
for (var keyid in keys) {
|
||||
info("Set " + keyid + " to false in session.keyIdsReceived");
|
||||
session.keyIdsReceived[keyid] = false;
|
||||
}
|
||||
return function(ev) {
|
||||
var session = ev.target;
|
||||
session.gotKeysChanged = true;
|
||||
session.getUsableKeyIds().then(function(keyIds) {
|
||||
for (var k = 0; k < keyIds.length; k++) {
|
||||
var kid = Base64ToHex(window.btoa(ArrayBufferToString(keyIds[k])));
|
||||
ok(kid in session.keyIdsReceived, "session.keyIdsReceived contained " + kid + " as expected.");
|
||||
session.keyIdsReceived[kid] = true;
|
||||
}
|
||||
}, bail("Failed to get keyIds"));
|
||||
}
|
||||
}
|
||||
|
||||
function startTest(test, token)
|
||||
{
|
||||
manager.started(test._token);
|
||||
@ -170,6 +189,7 @@ function startTest(test, token)
|
||||
|
||||
MediaKeys.create(KEYSYSTEM_TYPE).then(function(mediaKeys) {
|
||||
info(token + " created MediaKeys object ok");
|
||||
mediaKeys.sessions = [];
|
||||
return v.setMediaKeys(mediaKeys);
|
||||
}, bail("failed to create MediaKeys object")).then(function() {
|
||||
info(token + " set MediaKeys on <video> element ok");
|
||||
@ -178,6 +198,8 @@ function startTest(test, token)
|
||||
"MediaKeys should still support keysystem after CDM created...");
|
||||
|
||||
var session = v.mediaKeys.createSession(test.sessionType);
|
||||
v.mediaKeys.sessions.push(session);
|
||||
session.addEventListener("keyschange", KeysChangeFunc(session, test.keys), false);
|
||||
session.addEventListener("message", UpdateSessionFunc(test));
|
||||
session.generateRequest(ev.initDataType, ev.initData).then(function() {
|
||||
}, bail(token + " Failed to initialise MediaKeySession"));
|
||||
@ -198,6 +220,17 @@ function startTest(test, token)
|
||||
token + " Duration of video should be corrrect");
|
||||
ok(Math.abs(test.duration - v.currentTime) < 0.1,
|
||||
token + " Current time should be same as duration");
|
||||
// Verify all sessions had all keys went sent the to the CDM usable, and thus
|
||||
// that we received keyschange event(s).
|
||||
var sessions = v.mediaKeys.sessions;
|
||||
is(sessions.length, 1, "should have 1 session");
|
||||
for (var i = 0; i < sessions.length; i++) {
|
||||
var session = sessions[i];
|
||||
ok(session.gotKeysChanged, "Should have received at least one keychange event");
|
||||
for (var kid in session.keyIdsReceived) {
|
||||
ok(session.keyIdsReceived[kid], "key with id " + kid + " was usable as expected");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
v.addEventListener("error", bail(token + " got error event"));
|
||||
|
Loading…
x
Reference in New Issue
Block a user