From 0e273ade3c006acafccb76c65ed174d6629f8896 Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Fri, 22 Apr 2016 08:31:18 +1200 Subject: [PATCH] Bug 1265587 - Force keystatuses to be cleared when Widevine keysessions are closed. r=gerald The Widevine CDM, and I believe the Adobe CDM too probably, do not mark a session's keys as unusable when a key session is closed. This means that the CDMCaps' copy of the keys that are usable is wrong, and so if the media with the same keys is reloaded with the same MediaKeys, Firefox will assume that the keys are usable before the license for the keys has been re-negotiated, and so decryption will fail. MozReview-Commit-ID: 1kTDzwSD8PE --HG-- extra : rebase_source : 89c480f36bfaec11ceb5ca1e8d798b0ae795eaea --- dom/html/HTMLMediaElement.cpp | 3 +++ dom/media/eme/CDMCallbackProxy.cpp | 13 +++++++++++++ dom/media/eme/CDMCaps.cpp | 12 ++++++++++++ dom/media/eme/CDMCaps.h | 4 ++++ 4 files changed, 32 insertions(+) diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index fddd0c20fe15..d19651177faf 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -5147,6 +5147,9 @@ already_AddRefed HTMLMediaElement::SetMediaKeys(mozilla::dom::MediaKeys* aMediaKeys, ErrorResult& aRv) { + LOG(LogLevel::Debug, ("%p SetMediaKeys(%p) mMediaKeys=%p mDecoder=%p", + this, aMediaKeys, mMediaKeys.get(), mDecoder.get())); + if (MozAudioCaptured()) { aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); return nullptr; diff --git a/dom/media/eme/CDMCallbackProxy.cpp b/dom/media/eme/CDMCallbackProxy.cpp index a7f92cdbca7c..3be34b55b1c9 100644 --- a/dom/media/eme/CDMCallbackProxy.cpp +++ b/dom/media/eme/CDMCallbackProxy.cpp @@ -215,6 +215,19 @@ CDMCallbackProxy::SessionClosed(const nsCString& aSessionId) { MOZ_ASSERT(mProxy->IsOnGMPThread()); + bool keyStatusesChange = false; + { + CDMCaps::AutoLock caps(mProxy->Capabilites()); + keyStatusesChange = caps.RemoveKeysForSession(NS_ConvertUTF8toUTF16(aSessionId)); + } + if (keyStatusesChange) { + nsCOMPtr task; + task = NS_NewRunnableMethodWithArg(mProxy, + &CDMProxy::OnKeyStatusesChange, + NS_ConvertUTF8toUTF16(aSessionId)); + NS_DispatchToMainThread(task); + } + nsCOMPtr task; task = NS_NewRunnableMethodWithArg(mProxy, &CDMProxy::OnSessionClosed, diff --git a/dom/media/eme/CDMCaps.cpp b/dom/media/eme/CDMCaps.cpp index c8042375f7bf..e7db94d9dbd2 100644 --- a/dom/media/eme/CDMCaps.cpp +++ b/dom/media/eme/CDMCaps.cpp @@ -243,4 +243,16 @@ CDMCaps::AutoLock::GetSessionIdsForKeyId(const CencKeyId& aKeyId, } } +bool +CDMCaps::AutoLock::RemoveKeysForSession(const nsString& aSessionId) +{ + bool changed = false; + nsTArray statuses; + GetKeyStatusesForSession(aSessionId, statuses); + for (const KeyStatus& status : statuses) { + changed |= SetKeyStatus(status.mId, aSessionId, kGMPUnknown); + } + return changed; +} + } // namespace mozilla diff --git a/dom/media/eme/CDMCaps.h b/dom/media/eme/CDMCaps.h index 2d94de6198e8..3cc5a7076117 100644 --- a/dom/media/eme/CDMCaps.h +++ b/dom/media/eme/CDMCaps.h @@ -71,6 +71,10 @@ public: void GetSessionIdsForKeyId(const CencKeyId& aKeyId, nsTArray& aOutSessionIds); + // Ensures all keys for a session are marked as 'unknown', i.e. removed. + // Returns true if a key status was changed. + bool RemoveKeysForSession(const nsString& aSessionId); + // Sets the capabilities of the CDM. aCaps is the logical OR of the // GMP_EME_CAP_* flags from gmp-decryption.h. void SetCaps(uint64_t aCaps);