Bug 1059043 - Move MediaKeys.createSession into MediaKeySession as per spec - r=cpearce,smaug

This commit is contained in:
Edwin Flores 2014-09-24 10:04:49 +12:00
Родитель 0afabd88d4
Коммит e18043e3ad
18 изменённых файлов: 217 добавлений и 76 удалений

Просмотреть файл

@ -56,6 +56,38 @@ CDMCallbackProxy::ResolveNewSessionPromise(uint32_t aPromiseId,
NS_DispatchToMainThread(task);
}
class LoadSessionTask : public nsRunnable {
public:
LoadSessionTask(CDMProxy* aProxy,
uint32_t aPromiseId,
bool aSuccess)
: mProxy(aProxy)
, mPid(aPromiseId)
, mSuccess(aSuccess)
{
}
NS_IMETHOD Run() {
mProxy->OnResolveLoadSessionPromise(mPid, mSuccess);
return NS_OK;
}
nsRefPtr<CDMProxy> mProxy;
dom::PromiseId mPid;
bool mSuccess;
};
void
CDMCallbackProxy::ResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess)
{
MOZ_ASSERT(mProxy->IsOnGMPThread());
nsRefPtr<nsIRunnable> task(new LoadSessionTask(mProxy,
aPromiseId,
aSuccess));
NS_DispatchToMainThread(task);
}
void
CDMCallbackProxy::ResolvePromise(uint32_t aPromiseId)
{

Просмотреть файл

@ -20,6 +20,9 @@ public:
virtual void ResolveNewSessionPromise(uint32_t aPromiseId,
const nsCString& aSessionId) MOZ_OVERRIDE;
virtual void ResolveLoadSessionPromise(uint32_t aPromiseId,
bool aSuccess) MOZ_OVERRIDE;
virtual void ResolvePromise(uint32_t aPromiseId) MOZ_OVERRIDE;
virtual void RejectPromise(uint32_t aPromiseId,
@ -66,4 +69,4 @@ private:
} // namespace mozilla
#endif // CDMCallbackProxy_h_
#endif // CDMCallbackProxy_h_

Просмотреть файл

@ -373,6 +373,16 @@ CDMProxy::OnResolveNewSessionPromise(uint32_t aPromiseId,
mKeys->OnSessionCreated(aPromiseId, aSessionId);
}
void
CDMProxy::OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess)
{
MOZ_ASSERT(NS_IsMainThread());
if (mKeys.IsNull()) {
return;
}
mKeys->OnSessionLoaded(aPromiseId, aSuccess);
}
void
CDMProxy::OnSessionMessage(const nsAString& aSessionId,
nsTArray<uint8_t>& aMessage,

Просмотреть файл

@ -108,6 +108,9 @@ public:
void OnResolveNewSessionPromise(uint32_t aPromiseId,
const nsAString& aSessionId);
// Main thread only.
void OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess);
// Main thread only.
void OnSessionMessage(const nsAString& aSessionId,
nsTArray<uint8_t>& aMessage,

Просмотреть файл

@ -39,6 +39,7 @@ MediaKeySession::MediaKeySession(nsPIDOMWindow* aParent,
, mKeySystem(aKeySystem)
, mSessionType(aSessionType)
, mIsClosed(false)
, mUninitialized(true)
{
MOZ_ASSERT(aParent);
mClosed = mKeys->MakePromise(aRv);
@ -95,6 +96,70 @@ MediaKeySession::Closed() const
return mClosed;
}
already_AddRefed<Promise>
MediaKeySession::GenerateRequest(const nsAString& aInitDataType,
const ArrayBufferViewOrArrayBuffer& aInitData,
ErrorResult& aRv)
{
nsRefPtr<Promise> promise(mKeys->MakePromise(aRv));
if (aRv.Failed()) {
return nullptr;
}
if (!mUninitialized) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return promise.forget();
}
mUninitialized = false;
nsTArray<uint8_t> data;
if (aInitDataType.IsEmpty() ||
!CopyArrayBufferViewOrArrayBufferData(aInitData, data)) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return promise.forget();
}
PromiseId pid = mKeys->StorePromise(promise);
mKeys->OnSessionPending(pid, this);
mKeys->GetCDMProxy()->CreateSession(mSessionType,
pid,
aInitDataType, data);
return promise.forget();
}
already_AddRefed<Promise>
MediaKeySession::Load(const nsAString& aSessionId, ErrorResult& aRv)
{
nsRefPtr<Promise> promise(mKeys->MakePromise(aRv));
if (aRv.Failed()) {
return nullptr;
}
if (aSessionId.IsEmpty()) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
// "The sessionId parameter is empty."
return promise.forget();
}
if (!mUninitialized) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return promise.forget();
}
mUninitialized = false;
Init(aSessionId);
auto pid = mKeys->StorePromise(promise);
mKeys->OnSessionPending(pid, this);
mKeys->GetCDMProxy()->LoadSession(pid, aSessionId);
return promise.forget();
}
already_AddRefed<Promise>
MediaKeySession::Update(const ArrayBufferViewOrArrayBuffer& aResponse, ErrorResult& aRv)
{

Просмотреть файл

@ -63,6 +63,13 @@ public:
Promise* Closed() const;
already_AddRefed<Promise> GenerateRequest(const nsAString& aInitDataType,
const ArrayBufferViewOrArrayBuffer& aInitData,
ErrorResult& aRv);
already_AddRefed<Promise> Load(const nsAString& aSessionId,
ErrorResult& aRv);
already_AddRefed<Promise> Update(const ArrayBufferViewOrArrayBuffer& response,
ErrorResult& aRv);
@ -92,6 +99,7 @@ private:
nsString mSessionId;
const SessionType mSessionType;
bool mIsClosed;
bool mUninitialized;
};
} // namespace dom

Просмотреть файл

@ -274,73 +274,25 @@ MediaKeys::OnCDMCreated(PromiseId aId)
}
}
already_AddRefed<Promise>
MediaKeys::LoadSession(const nsAString& aSessionId, ErrorResult& aRv)
{
nsRefPtr<Promise> promise(MakePromise(aRv));
if (aRv.Failed()) {
return nullptr;
}
if (aSessionId.IsEmpty()) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
// "The sessionId parameter is empty."
return promise.forget();
}
// TODO: The spec doesn't specify what to do in this case...
if (mKeySessions.Contains(aSessionId)) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return promise.forget();
}
// Create session.
nsRefPtr<MediaKeySession> session(
new MediaKeySession(GetParentObject(), this, mKeySystem, SessionType::Persistent, aRv));
if (aRv.Failed()) {
return nullptr;
}
session->Init(aSessionId);
auto pid = StorePromise(promise);
mPendingSessions.Put(pid, session);
mProxy->LoadSession(pid, aSessionId);
return promise.forget();
}
already_AddRefed<Promise>
MediaKeys::CreateSession(const nsAString& initDataType,
const ArrayBufferViewOrArrayBuffer& aInitData,
SessionType aSessionType,
already_AddRefed<MediaKeySession>
MediaKeys::CreateSession(SessionType aSessionType,
ErrorResult& aRv)
{
nsRefPtr<Promise> promise(MakePromise(aRv));
if (aRv.Failed()) {
return nullptr;
}
nsTArray<uint8_t> data;
if (initDataType.IsEmpty() ||
!CopyArrayBufferViewOrArrayBufferData(aInitData, data)) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return promise.forget();
}
nsRefPtr<MediaKeySession> session = new MediaKeySession(GetParentObject(),
this,
mKeySystem,
aSessionType,
aRv);
auto pid = StorePromise(promise);
// Hang onto session until the CDM has finished setting it up.
mPendingSessions.Put(pid, session);
mProxy->CreateSession(aSessionType,
pid,
initDataType,
data);
return promise.forget();
return session.forget();
}
void
MediaKeys::OnSessionPending(PromiseId aId, MediaKeySession* aSession)
{
MOZ_ASSERT(mPromises.Contains(aId));
MOZ_ASSERT(!mPendingSessions.Contains(aId));
mPendingSessions.Put(aId, aSession);
}
void
@ -370,6 +322,35 @@ MediaKeys::OnSessionCreated(PromiseId aId, const nsAString& aSessionId)
promise->MaybeResolve(session);
}
void
MediaKeys::OnSessionLoaded(PromiseId aId, bool aSuccess)
{
nsRefPtr<Promise> promise(RetrievePromise(aId));
if (!promise) {
NS_WARNING("MediaKeys tried to resolve a non-existent promise");
return;
}
MOZ_ASSERT(mPendingSessions.Contains(aId));
nsRefPtr<MediaKeySession> session;
bool gotSession = mPendingSessions.Get(aId, getter_AddRefs(session));
// Session has completed creation/loading, remove it from mPendingSessions,
// and resolve the promise with it. We store it in mKeySessions, so we can
// find it again if we need to send messages to it etc.
mPendingSessions.Remove(aId);
if (!gotSession || !session) {
NS_WARNING("Received activation for non-existent session!");
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return;
}
MOZ_ASSERT(!session->GetSessionId().IsEmpty() &&
!mKeySessions.Contains(session->GetSessionId()));
mKeySessions.Put(session->GetSessionId(), session);
promise->MaybeResolve(aSuccess);
}
void
MediaKeys::OnSessionClosed(MediaKeySession* aSession)
{

Просмотреть файл

@ -59,14 +59,8 @@ public:
void GetKeySystem(nsString& retval) const;
// JavaScript: MediaKeys.createSession()
already_AddRefed<Promise> CreateSession(const nsAString& aInitDataType,
const ArrayBufferViewOrArrayBuffer& aInitData,
SessionType aSessionType,
ErrorResult& aRv);
// JavaScript: MediaKeys.loadSession()
already_AddRefed<Promise> LoadSession(const nsAString& aSessionId,
ErrorResult& aRv);
already_AddRefed<MediaKeySession> CreateSession(SessionType aSessionType,
ErrorResult& aRv);
// JavaScript: MediaKeys.SetServerCertificate()
already_AddRefed<Promise> SetServerCertificate(const ArrayBufferViewOrArrayBuffer& aServerCertificate,
@ -89,8 +83,13 @@ public:
// Called once a Create() operation succeeds.
void OnCDMCreated(PromiseId aId);
// Called once a CreateSession or LoadSession succeeds.
// Called when GenerateRequest or Load have been called on a MediaKeySession
// and we are waiting for its initialisation to finish.
void OnSessionPending(PromiseId aId, MediaKeySession* aSession);
// Called once a CreateSession succeeds.
void OnSessionCreated(PromiseId aId, const nsAString& aSessionId);
// Called once a LoadSession succeeds.
void OnSessionLoaded(PromiseId aId, bool aSuccess);
// Called once a session has closed.
void OnSessionClosed(MediaKeySession* aSession);

Просмотреть файл

@ -53,6 +53,13 @@ GMPDecryptorChild::ResolveNewSessionPromise(uint32_t aPromiseId,
aPromiseId, nsAutoCString(aSessionId, aSessionIdLength));
}
void
GMPDecryptorChild::ResolveLoadSessionPromise(uint32_t aPromiseId,
bool aSuccess)
{
CALL_ON_GMP_THREAD(SendResolveLoadSessionPromise, aPromiseId, aSuccess);
}
void
GMPDecryptorChild::ResolvePromise(uint32_t aPromiseId)
{

Просмотреть файл

@ -31,6 +31,8 @@ public:
virtual void ResolveNewSessionPromise(uint32_t aPromiseId,
const char* aSessionId,
uint32_t aSessionIdLength) MOZ_OVERRIDE;
virtual void ResolveLoadSessionPromise(uint32_t aPromiseId,
bool aSuccess) MOZ_OVERRIDE;
virtual void ResolvePromise(uint32_t aPromiseId) MOZ_OVERRIDE;
virtual void RejectPromise(uint32_t aPromiseId,

Просмотреть файл

@ -152,6 +152,18 @@ GMPDecryptorParent::RecvResolveNewSessionPromise(const uint32_t& aPromiseId,
return true;
}
bool
GMPDecryptorParent::RecvResolveLoadSessionPromise(const uint32_t& aPromiseId,
const bool& aSuccess)
{
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return false;
}
mCallback->ResolveLoadSessionPromise(aPromiseId, aSuccess);
return true;
}
bool
GMPDecryptorParent::RecvResolvePromise(const uint32_t& aPromiseId)
{

Просмотреть файл

@ -67,6 +67,9 @@ private:
virtual bool RecvResolveNewSessionPromise(const uint32_t& aPromiseId,
const nsCString& aSessionId) MOZ_OVERRIDE;
virtual bool RecvResolveLoadSessionPromise(const uint32_t& aPromiseId,
const bool& aSuccess) MOZ_OVERRIDE;
virtual bool RecvResolvePromise(const uint32_t& aPromiseId) MOZ_OVERRIDE;
virtual bool RecvRejectPromise(const uint32_t& aPromiseId,

Просмотреть файл

@ -20,6 +20,9 @@ public:
virtual void ResolveNewSessionPromise(uint32_t aPromiseId,
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,

Просмотреть файл

@ -53,6 +53,9 @@ parent:
ResolveNewSessionPromise(uint32_t aPromiseId,
nsCString aSessionId);
ResolveLoadSessionPromise(uint32_t aPromiseId,
bool aSuccess);
ResolvePromise(uint32_t aPromiseId);
RejectPromise(uint32_t aPromiseId,

Просмотреть файл

@ -94,7 +94,7 @@ typedef int64_t GMPTimestamp;
// Callbacks to be called from the CDM. Threadsafe.
class GMPDecryptorCallback {
public:
// Resolves a promise for a session created or loaded.
// Resolves a promise for a session created.
// Passes the session id to be exposed to JavaScript.
// Must be called before SessionMessage().
// aSessionId must be null terminated.
@ -102,6 +102,13 @@ public:
const char* aSessionId,
uint32_t aSessionIdLength) = 0;
// Resolves a promise for a session loaded.
// Resolves to false if we don't have any session data stored for the given
// session ID.
// Must be called before SessionMessage().
virtual void ResolveLoadSessionPromise(uint32_t aPromiseId,
bool aSuccess) = 0;
// Called to resolve a specified promise with "undefined".
virtual void ResolvePromise(uint32_t aPromiseId) = 0;

Просмотреть файл

@ -24,6 +24,12 @@ interface MediaKeySession : EventTarget {
// void, not any: https://www.w3.org/Bugs/Public/show_bug.cgi?id=26457
readonly attribute Promise<void> closed;
[NewObject, Throws]
Promise<void> generateRequest(DOMString initDataType, (ArrayBufferView or ArrayBuffer) initData);
[NewObject, Throws]
Promise<boolean> load(DOMString sessionId);
// session operations
// void, not any: https://www.w3.org/Bugs/Public/show_bug.cgi?id=26457
[NewObject, Throws]

Просмотреть файл

@ -18,10 +18,7 @@ interface MediaKeys {
readonly attribute DOMString keySystem;
[NewObject, Throws]
Promise<MediaKeySession> createSession(DOMString initDataType, (ArrayBufferView or ArrayBuffer) initData, optional SessionType sessionType = "temporary");
[NewObject, Throws]
Promise<MediaKeySession> loadSession(DOMString sessionId);
MediaKeySession createSession(optional SessionType sessionType = "temporary");
// void, not any: https://www.w3.org/Bugs/Public/show_bug.cgi?id=26457
[NewObject, Throws]

Просмотреть файл

@ -169,8 +169,8 @@ ClearKeyDecryptionManager::LoadSession(uint32_t aPromiseId,
uint32_t aSessionIdLength)
{
// TODO implement "persistent" sessions.
mCallback->RejectPromise(aPromiseId, kGMPNotSupportedError,
nullptr /* message */, 0 /* messageLen */);
mCallback->ResolveLoadSessionPromise(aPromiseId, false);
CK_LOGD("ClearKeyDecryptionManager::LoadSession");
}