Bug 1310936- Provide a map to get pending MediaKeySession by promise Id correctly. r=cpearce

MozReview-Commit-ID: 34BL4GYoC1A

--HG--
extra : rebase_source : 4dffdf8da32412a6812716de9edbf685235ce442
This commit is contained in:
Kilik Kuo 2016-10-20 15:28:09 +08:00
Родитель 0ba3e39262
Коммит ede59e2ecf
3 изменённых файлов: 56 добавлений и 25 удалений

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

@ -69,7 +69,7 @@ MediaKeySession::MediaKeySession(JSContext* aCx,
, mKeyStatusMap(new MediaKeyStatusMap(aParent))
, mExpiration(JS::GenericNaN())
{
EME_LOG("MediaKeySession[%p,''] session Id set", this);
EME_LOG("MediaKeySession[%p,''] ctor", this);
MOZ_ASSERT(aParent);
if (aRv.Failed()) {
@ -325,6 +325,7 @@ MediaKeySession::GenerateRequest(const nsAString& aInitDataType,
// to copy it here.
nsAutoCString base64InitData(ToBase64(data));
PromiseId pid = mKeys->StorePromise(promise);
mKeys->ConnectPendingPromiseIdWithToken(pid, Token());
mKeys->GetCDMProxy()->CreateSession(Token(),
mSessionType,
pid,
@ -390,6 +391,7 @@ MediaKeySession::Load(const nsAString& aSessionId, ErrorResult& aRv)
SetSessionId(aSessionId);
PromiseId pid = mKeys->StorePromise(promise);
mKeys->ConnectPendingPromiseIdWithToken(pid, Token());
mKeys->GetCDMProxy()->LoadSession(pid, aSessionId);
EME_LOG("MediaKeySession[%p,'%s'] Load() sent to CDM, promiseId=%d",

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

@ -196,6 +196,16 @@ MediaKeys::StorePromise(DetailedPromise* aPromise)
return id;
}
void
MediaKeys::ConnectPendingPromiseIdWithToken(PromiseId aId, uint32_t aToken)
{
// Should only be called from MediaKeySession::GenerateRequest and
// MediaKeySession::Load.
mPromiseIdToken.Put(aId, aToken);
EME_LOG("MediaKeys[%p]::ConnectPendingPromiseIdWithToken() id=%u => token(%u)",
this, aId, aToken);
}
already_AddRefed<DetailedPromise>
MediaKeys::RetrievePromise(PromiseId aId)
{
@ -219,12 +229,16 @@ MediaKeys::RejectPromise(PromiseId aId, nsresult aExceptionCode,
if (!promise) {
return;
}
if (mPendingSessions.Contains(aId)) {
// This promise could be a createSession or loadSession promise,
// so we might have a pending session waiting to be resolved into
// the promise on success. We've been directed to reject to promise,
// so we can throw away the corresponding session object.
mPendingSessions.Remove(aId);
// This promise could be a createSession or loadSession promise,
// so we might have a pending session waiting to be resolved into
// the promise on success. We've been directed to reject to promise,
// so we can throw away the corresponding session object.
uint32_t token = 0;
if (mPromiseIdToken.Get(aId, &token)) {
MOZ_ASSERT(mPendingSessions.Contains(token));
mPendingSessions.Remove(token);
mPromiseIdToken.Remove(aId);
}
MOZ_ASSERT(NS_FAILED(aExceptionCode));
@ -264,29 +278,36 @@ MediaKeys::ResolvePromise(PromiseId aId)
EME_LOG("MediaKeys[%p]::ResolvePromise(%d)", this, aId);
RefPtr<DetailedPromise> promise(RetrievePromise(aId));
MOZ_ASSERT(!mPromises.Contains(aId));
if (!promise) {
return;
}
if (mPendingSessions.Contains(aId)) {
// We should only resolve LoadSession calls via this path,
// not CreateSession() promises.
RefPtr<MediaKeySession> session;
if (!mPendingSessions.Get(aId, getter_AddRefs(session)) ||
!session ||
session->GetSessionId().IsEmpty()) {
NS_WARNING("Received activation for non-existent session!");
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR,
NS_LITERAL_CSTRING("CDM LoadSession() returned a different session ID than requested"));
mPendingSessions.Remove(aId);
return;
}
mPendingSessions.Remove(aId);
mKeySessions.Put(session->GetSessionId(), session);
promise->MaybeResolve(session);
} else {
uint32_t token = 0;
if (!mPromiseIdToken.Get(aId, &token)) {
promise->MaybeResolveWithUndefined();
return;
} else if (!mPendingSessions.Contains(token)) {
// Pending session for CreateSession() should be removed when sessionId
// is ready.
promise->MaybeResolveWithUndefined();
mPromiseIdToken.Remove(aId);
return;
}
MOZ_ASSERT(!mPromises.Contains(aId));
mPromiseIdToken.Remove(aId);
// We should only resolve LoadSession calls via this path,
// not CreateSession() promises.
RefPtr<MediaKeySession> session;
mPendingSessions.Remove(token, getter_AddRefs(session));
if (!session || session->GetSessionId().IsEmpty()) {
NS_WARNING("Received activation for non-existent session!");
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR,
NS_LITERAL_CSTRING("CDM LoadSession() returned a different session ID than requested"));
return;
}
mKeySessions.Put(session->GetSessionId(), session);
promise->MaybeResolve(session);
}
class MediaKeysGMPCrashHelper : public GMPCrashHelper

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

@ -33,6 +33,7 @@ class HTMLMediaElement;
typedef nsRefPtrHashtable<nsStringHashKey, MediaKeySession> KeySessionHashMap;
typedef nsRefPtrHashtable<nsUint32HashKey, dom::DetailedPromise> PromiseHashMap;
typedef nsRefPtrHashtable<nsUint32HashKey, MediaKeySession> PendingKeySessionsHashMap;
typedef nsDataHashtable<nsUint32HashKey, uint32_t> PendingPromiseIdTokenHashMap;
typedef uint32_t PromiseId;
// This class is used on the main thread only.
@ -107,6 +108,11 @@ public:
// promises to be resolved.
PromiseId StorePromise(DetailedPromise* aPromise);
// Stores a map for promise id and session token, and it will be used to
// remove the pending sessions by promise id while creating/loading various
// sessions in the same time.
void ConnectPendingPromiseIdWithToken(PromiseId aId, uint32_t aToken);
// Reject promise with DOMException corresponding to aExceptionCode.
void RejectPromise(PromiseId aId, nsresult aExceptionCode,
const nsCString& aReason);
@ -151,6 +157,8 @@ private:
const bool mDistinctiveIdentifierRequired;
const bool mPersistentStateRequired;
PendingPromiseIdTokenHashMap mPromiseIdToken;
};
} // namespace dom