2019-07-08 12:27:47 +03:00
|
|
|
/* -*- 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/. */
|
|
|
|
|
2017-01-11 23:52:05 +03:00
|
|
|
#include "ClearKeyCDM.h"
|
|
|
|
|
|
|
|
#include "ClearKeyUtils.h"
|
|
|
|
|
|
|
|
using namespace cdm;
|
|
|
|
|
2019-01-14 19:40:04 +03:00
|
|
|
ClearKeyCDM::ClearKeyCDM(Host_10* aHost) {
|
2017-01-11 23:52:05 +03:00
|
|
|
mHost = aHost;
|
|
|
|
mSessionManager = new ClearKeySessionManager(mHost);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClearKeyCDM::Initialize(bool aAllowDistinctiveIdentifier,
|
2019-01-14 19:40:04 +03:00
|
|
|
bool aAllowPersistentState,
|
|
|
|
bool aUseHardwareSecureCodecs) {
|
2017-01-11 23:52:05 +03:00
|
|
|
mSessionManager->Init(aAllowDistinctiveIdentifier, aAllowPersistentState);
|
2019-01-14 19:40:04 +03:00
|
|
|
// We call mHost->OnInitialized() in the session manager once it has
|
|
|
|
// initialized.
|
2017-01-11 23:52:05 +03:00
|
|
|
}
|
|
|
|
|
2017-11-23 11:47:13 +03:00
|
|
|
void ClearKeyCDM::GetStatusForPolicy(uint32_t aPromiseId,
|
|
|
|
const Policy& aPolicy) {
|
|
|
|
// MediaKeys::GetStatusForPolicy checks the keysystem and
|
|
|
|
// reject the promise with NS_ERROR_DOM_NOT_SUPPORTED_ERR without calling CDM.
|
|
|
|
// This function should never be called and is not supported.
|
|
|
|
assert(false);
|
|
|
|
}
|
2017-01-11 23:52:05 +03:00
|
|
|
void ClearKeyCDM::SetServerCertificate(uint32_t aPromiseId,
|
|
|
|
const uint8_t* aServerCertificateData,
|
|
|
|
uint32_t aServerCertificateDataSize) {
|
|
|
|
mSessionManager->SetServerCertificate(aPromiseId, aServerCertificateData,
|
|
|
|
aServerCertificateDataSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClearKeyCDM::CreateSessionAndGenerateRequest(uint32_t aPromiseId,
|
|
|
|
SessionType aSessionType,
|
|
|
|
InitDataType aInitDataType,
|
|
|
|
const uint8_t* aInitData,
|
|
|
|
uint32_t aInitDataSize) {
|
|
|
|
mSessionManager->CreateSession(aPromiseId, aInitDataType, aInitData,
|
|
|
|
aInitDataSize, aSessionType);
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2017-01-11 23:52:05 +03:00
|
|
|
void ClearKeyCDM::LoadSession(uint32_t aPromiseId, SessionType aSessionType,
|
|
|
|
const char* aSessionId, uint32_t aSessionIdSize) {
|
|
|
|
mSessionManager->LoadSession(aPromiseId, aSessionId, aSessionIdSize);
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2017-01-11 23:52:05 +03:00
|
|
|
void ClearKeyCDM::UpdateSession(uint32_t aPromiseId, const char* aSessionId,
|
|
|
|
uint32_t aSessionIdSize,
|
|
|
|
const uint8_t* aResponse,
|
|
|
|
uint32_t aResponseSize) {
|
|
|
|
mSessionManager->UpdateSession(aPromiseId, aSessionId, aSessionIdSize,
|
|
|
|
aResponse, aResponseSize);
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2017-01-11 23:52:05 +03:00
|
|
|
void ClearKeyCDM::CloseSession(uint32_t aPromiseId, const char* aSessionId,
|
|
|
|
uint32_t aSessionIdSize) {
|
|
|
|
mSessionManager->CloseSession(aPromiseId, aSessionId, aSessionIdSize);
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2017-01-11 23:52:05 +03:00
|
|
|
void ClearKeyCDM::RemoveSession(uint32_t aPromiseId, const char* aSessionId,
|
|
|
|
uint32_t aSessionIdSize) {
|
|
|
|
mSessionManager->RemoveSession(aPromiseId, aSessionId, aSessionIdSize);
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2017-01-11 23:52:05 +03:00
|
|
|
void ClearKeyCDM::TimerExpired(void* aContext) {
|
|
|
|
// Clearkey is not interested in timers, so this method has not been
|
|
|
|
// implemented.
|
|
|
|
assert(false);
|
|
|
|
}
|
|
|
|
|
2019-01-14 19:40:04 +03:00
|
|
|
Status ClearKeyCDM::Decrypt(const InputBuffer_2& aEncryptedBuffer,
|
2017-01-11 23:52:05 +03:00
|
|
|
DecryptedBlock* aDecryptedBuffer) {
|
2021-08-19 20:14:09 +03:00
|
|
|
if (mIsProtectionQueryEnabled) {
|
|
|
|
// Piggyback this check onto Decrypt calls. If Clearkey implements a timer
|
|
|
|
// based approach for firing events, we could instead trigger the check
|
|
|
|
// using that mechanism.
|
|
|
|
mSessionManager->QueryOutputProtectionStatusIfNeeded();
|
|
|
|
}
|
2017-01-11 23:52:05 +03:00
|
|
|
return mSessionManager->Decrypt(aEncryptedBuffer, aDecryptedBuffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
Status ClearKeyCDM::InitializeAudioDecoder(
|
2019-01-14 19:40:04 +03:00
|
|
|
const AudioDecoderConfig_2& aAudioDecoderConfig) {
|
2017-01-11 23:52:05 +03:00
|
|
|
// Audio decoding is not supported by Clearkey because Widevine doesn't
|
|
|
|
// support it and Clearkey's raison d'etre is to provide test coverage
|
|
|
|
// for paths that Widevine will exercise in the wild.
|
|
|
|
return Status::kDecodeError;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status ClearKeyCDM::InitializeVideoDecoder(
|
2019-01-14 19:40:04 +03:00
|
|
|
const VideoDecoderConfig_2& aVideoDecoderConfig) {
|
2017-01-11 23:52:05 +03:00
|
|
|
#ifdef ENABLE_WMF
|
2017-01-18 04:49:04 +03:00
|
|
|
mVideoDecoder = new VideoDecoder(mHost);
|
2017-01-11 23:52:05 +03:00
|
|
|
return mVideoDecoder->InitDecode(aVideoDecoderConfig);
|
|
|
|
#else
|
|
|
|
return Status::kDecodeError;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClearKeyCDM::DeinitializeDecoder(StreamType aDecoderType) {
|
|
|
|
#ifdef ENABLE_WMF
|
|
|
|
if (aDecoderType == StreamType::kStreamTypeVideo) {
|
2017-01-18 04:49:04 +03:00
|
|
|
mVideoDecoder->DecodingComplete();
|
|
|
|
mVideoDecoder = nullptr;
|
2017-01-11 23:52:05 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClearKeyCDM::ResetDecoder(StreamType aDecoderType) {
|
|
|
|
#ifdef ENABLE_WMF
|
|
|
|
if (aDecoderType == StreamType::kStreamTypeVideo) {
|
|
|
|
mVideoDecoder->Reset();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-01-14 19:40:04 +03:00
|
|
|
Status ClearKeyCDM::DecryptAndDecodeFrame(const InputBuffer_2& aEncryptedBuffer,
|
2017-01-11 23:52:05 +03:00
|
|
|
VideoFrame* aVideoFrame) {
|
|
|
|
#ifdef ENABLE_WMF
|
2021-08-19 20:14:09 +03:00
|
|
|
if (mIsProtectionQueryEnabled) {
|
|
|
|
// Piggyback this check onto Decrypt + Decode. If Clearkey implements a
|
|
|
|
// timer based approach for firing events, we could instead trigger the
|
|
|
|
// check using that mechanism.
|
|
|
|
mSessionManager->QueryOutputProtectionStatusIfNeeded();
|
|
|
|
}
|
2017-01-11 23:52:05 +03:00
|
|
|
return mVideoDecoder->Decode(aEncryptedBuffer, aVideoFrame);
|
|
|
|
#else
|
|
|
|
return Status::kDecodeError;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-09-13 17:49:10 +03:00
|
|
|
Status ClearKeyCDM::DecryptAndDecodeSamples(
|
2019-01-14 19:40:04 +03:00
|
|
|
const InputBuffer_2& aEncryptedBuffer, AudioFrames* aAudioFrame) {
|
2017-01-11 23:52:05 +03:00
|
|
|
// Audio decoding is not supported by Clearkey because Widevine doesn't
|
|
|
|
// support it and Clearkey's raison d'etre is to provide test coverage
|
|
|
|
// for paths that Widevine will exercise in the wild.
|
|
|
|
return Status::kDecodeError;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClearKeyCDM::OnPlatformChallengeResponse(
|
|
|
|
const PlatformChallengeResponse& aResponse) {
|
|
|
|
// This function should never be called and is not supported.
|
|
|
|
assert(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClearKeyCDM::OnQueryOutputProtectionStatus(
|
|
|
|
QueryResult aResult, uint32_t aLinkMask, uint32_t aOutputProtectionMask) {
|
2021-08-19 20:14:09 +03:00
|
|
|
// The higher level GMP machinery should not forward us query information
|
|
|
|
// unless we've requested it (even if mutiple CDMs exist at once and some
|
|
|
|
// others are reqeusting this info). If this assert fires we're violating
|
|
|
|
// that.
|
|
|
|
MOZ_ASSERT(mIsProtectionQueryEnabled,
|
|
|
|
"Should only receive a protection status "
|
|
|
|
"mIsProtectionQueryEnabled is true");
|
|
|
|
// The session manager handles the guts of this for ClearKey.
|
|
|
|
mSessionManager->OnQueryOutputProtectionStatus(aResult, aLinkMask,
|
|
|
|
aOutputProtectionMask);
|
2017-01-11 23:52:05 +03:00
|
|
|
}
|
|
|
|
|
2017-11-23 11:47:13 +03:00
|
|
|
void ClearKeyCDM::OnStorageId(uint32_t aVersion, const uint8_t* aStorageId,
|
|
|
|
uint32_t aStorageIdSize) {
|
|
|
|
// This function should never be called and is not supported.
|
|
|
|
assert(false);
|
|
|
|
}
|
|
|
|
|
2017-01-11 23:52:05 +03:00
|
|
|
void ClearKeyCDM::Destroy() {
|
|
|
|
mSessionManager->DecryptingComplete();
|
|
|
|
#ifdef ENABLE_WMF
|
2017-01-18 04:49:04 +03:00
|
|
|
// If we have called 'DeinitializeDecoder' mVideoDecoder will be null.
|
|
|
|
if (mVideoDecoder) {
|
|
|
|
mVideoDecoder->DecodingComplete();
|
|
|
|
}
|
2017-01-11 23:52:05 +03:00
|
|
|
#endif
|
2017-09-08 12:34:48 +03:00
|
|
|
delete this;
|
2017-11-23 11:47:13 +03:00
|
|
|
}
|
2021-08-19 20:14:08 +03:00
|
|
|
|
|
|
|
void ClearKeyCDM::EnableProtectionQuery() {
|
|
|
|
MOZ_ASSERT(!mIsProtectionQueryEnabled,
|
|
|
|
"Should not be called more than once per CDM");
|
|
|
|
mIsProtectionQueryEnabled = true;
|
|
|
|
}
|