gecko-dev/dom/media/eme/CDMCaps.h
Chris Pearce 0e273ade3c 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
2016-04-22 08:31:18 +12:00

133 lines
3.7 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "nsAutoPtr.h"
#include "mozilla/Monitor.h"
#include "nsIThread.h"
#include "nsTArray.h"
#include "mozilla/Attributes.h"
#include "SamplesWaitingForKey.h"
#include "gmp-decryption.h"
namespace mozilla {
// CDM capabilities; what keys a CDMProxy can use, and whether it can decrypt, or
// decrypt-and-decode on a per stream basis. Must be locked to access state.
class CDMCaps {
public:
CDMCaps();
~CDMCaps();
struct KeyStatus {
KeyStatus(const CencKeyId& aId,
const nsString& aSessionId,
GMPMediaKeyStatus 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;
};
// 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();
// Returns true if the capabilities of the CDM are known, i.e. they have
// been reported by the CDM to Gecko.
bool AreCapsKnown();
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);
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.
// 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);
bool CanRenderAudio();
bool CanRenderVideo();
bool CanDecryptAndDecodeAudio();
bool CanDecryptAndDecodeVideo();
bool CanDecryptAudio();
bool CanDecryptVideo();
void CallOnMainThreadWhenCapsAvailable(nsIRunnable* aContinuation);
// Notifies the SamplesWaitingForKey when key become usable.
void NotifyWhenKeyIdUsable(const CencKeyId& aKey,
SamplesWaitingForKey* aSamplesWaiting);
private:
// Not taking a strong ref, since this should be allocated on the stack.
CDMCaps& mData;
};
private:
void Lock();
void Unlock();
bool HasCap(uint64_t);
struct WaitForKeys {
WaitForKeys(const CencKeyId& aKeyId,
SamplesWaitingForKey* aListener)
: mKeyId(aKeyId)
, mListener(aListener)
{}
CencKeyId mKeyId;
RefPtr<SamplesWaitingForKey> mListener;
};
Monitor mMonitor;
nsTArray<KeyStatus> mKeyStatuses;
nsTArray<WaitForKeys> mWaitForKeys;
nsTArray<nsCOMPtr<nsIRunnable>> mWaitForCaps;
uint64_t mCaps;
// It is not safe to copy this object.
CDMCaps(const CDMCaps&) = delete;
CDMCaps& operator=(const CDMCaps&) = delete;
};
} // namespace mozilla
#endif