Source release 18.1.0

This commit is contained in:
John "Juce" Bruce
2023-06-23 15:45:08 -07:00
parent 2baa7c6e2b
commit b2c35151ad
2074 changed files with 196004 additions and 427059 deletions

View File

@@ -222,11 +222,14 @@ class CdmTest : public WvCdmTestBase, public Cdm::IEventListener {
// IEventListener mocks:
MOCK_METHOD(void, onMessage,
(const std::string& session_id, Cdm::MessageType message_type,
const std::string& message),
const std::string& message, const std::string& server_url),
(override));
MOCK_METHOD(void, onKeyStatusesChange,
(const std::string& session_id, bool has_new_usable_key),
(override));
MOCK_METHOD(void, onExpirationChange,
(const std::string& session_id, int64_t new_expiry_time_seconds),
(override));
MOCK_METHOD(void, onRemoveComplete, (const std::string& session_id),
(override));
@@ -240,7 +243,7 @@ class CdmTest : public WvCdmTestBase, public Cdm::IEventListener {
// Reinit the library.
Cdm::Status status = Cdm::initialize(
Cdm::kNoSecureOutput, &g_host->global_storage(), g_host, g_host,
static_cast<Cdm::LogLevel>(g_cutoff), g_sandbox_id);
&g_stderr_logger, static_cast<Cdm::LogLevel>(g_cutoff), g_sandbox_id);
ASSERT_EQ(Cdm::kSuccess, status);
// Make a fresh CDM.
@@ -372,8 +375,7 @@ class CdmTest : public WvCdmTestBase, public Cdm::IEventListener {
init_data_type_name = HLS_INIT_DATA_FORMAT;
init_data = kHlsInitData;
}
} else if (session_type == Cdm::kPersistentLicense ||
session_type == Cdm::kPersistentUsageRecord) {
} else if (session_type == Cdm::kPersistentLicense) {
if (init_data_type == Cdm::kCenc) {
init_data = kCencPersistentInitData;
init_data_type_name = CENC_INIT_DATA_FORMAT;
@@ -385,7 +387,7 @@ class CdmTest : public WvCdmTestBase, public Cdm::IEventListener {
}
ASSERT_FALSE(init_data.empty());
EXPECT_CALL(*this, onMessage(*session_id, Cdm::kLicenseRequest, _))
EXPECT_CALL(*this, onMessage(*session_id, Cdm::kLicenseRequest, _, _))
.WillOnce(SaveArg<2>(message));
status = generateRequestWithRetry(*session_id, init_data_type, init_data);
ASSERT_EQ(Cdm::kSuccess, status);
@@ -416,10 +418,21 @@ class CdmTest : public WvCdmTestBase, public Cdm::IEventListener {
std::string response;
ASSERT_NO_FATAL_FAILURE(CreateSessionAndFetchLicense(
session_type, init_data_type, session_id, &response));
EXPECT_CALL(*this, onKeyStatusesChange(*session_id, true));
int64_t event_expiry_time = 0;
EXPECT_CALL(*this, onExpirationChange(*session_id, _))
.WillOnce(SaveArg<1>(&event_expiry_time));
Cdm::Status status = updateWithRetry(*session_id, response);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
ASSERT_TRUE(Mock::VerifyAndClear(this));
// The new expiry time should be consistent.
int64_t function_expiry_time = 0;
ASSERT_EQ(cdm_->getExpiration(*session_id, &function_expiry_time),
Cdm::kSuccess);
EXPECT_EQ(event_expiry_time, function_expiry_time);
}
void FetchLicenseAndUpdate(const std::string& session_id,
@@ -603,6 +616,8 @@ TEST_F(CdmTest, PrintClientInformation) {
// Collect OEMCrypto info
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_Initialize());
(void)OEMCrypto_SetMaxAPIVersion(CDM_VERSION_MAJOR);
(void)OEMCrypto_EnterTestMode();
const uint32_t oec_major = OEMCrypto_APIVersion();
const uint32_t oec_minor = OEMCrypto_MinorAPIVersion();
const char* const supports_usage_tables =
@@ -673,39 +688,46 @@ TEST_F(CdmTest, Initialize) {
// Try with an invalid output type.
Cdm::Status status = Cdm::initialize(
static_cast<Cdm::SecureOutputType>(-1), &g_host->global_storage(), g_host,
g_host, static_cast<Cdm::LogLevel>(g_cutoff), g_sandbox_id);
g_host, &g_stderr_logger, static_cast<Cdm::LogLevel>(g_cutoff),
g_sandbox_id);
EXPECT_EQ(Cdm::kTypeError, status);
// Try with various host interfaces missing.
status = Cdm::initialize(Cdm::kNoSecureOutput, nullptr, g_host, g_host,
&g_stderr_logger,
static_cast<Cdm::LogLevel>(g_cutoff), g_sandbox_id);
EXPECT_EQ(Cdm::kTypeError, status);
status = Cdm::initialize(Cdm::kNoSecureOutput, &g_host->global_storage(),
nullptr, g_host,
nullptr, g_host, &g_stderr_logger,
static_cast<Cdm::LogLevel>(g_cutoff), g_sandbox_id);
EXPECT_EQ(Cdm::kTypeError, status);
status = Cdm::initialize(Cdm::kNoSecureOutput, &g_host->global_storage(),
g_host, nullptr,
g_host, nullptr, &g_stderr_logger,
static_cast<Cdm::LogLevel>(g_cutoff), g_sandbox_id);
EXPECT_EQ(Cdm::kTypeError, status);
status = Cdm::initialize(Cdm::kNoSecureOutput, &g_host->global_storage(),
g_host, g_host, nullptr,
static_cast<Cdm::LogLevel>(g_cutoff), g_sandbox_id);
EXPECT_EQ(Cdm::kTypeError, status);
// Try all output types.
status = Cdm::initialize(Cdm::kDirectRender, &g_host->global_storage(),
g_host, g_host, static_cast<Cdm::LogLevel>(g_cutoff),
g_sandbox_id);
g_host, g_host, &g_stderr_logger,
static_cast<Cdm::LogLevel>(g_cutoff), g_sandbox_id);
EXPECT_EQ(Cdm::kSuccess, status);
status = Cdm::initialize(Cdm::kOpaqueHandle, &g_host->global_storage(),
g_host, g_host, static_cast<Cdm::LogLevel>(g_cutoff),
g_sandbox_id);
g_host, g_host, &g_stderr_logger,
static_cast<Cdm::LogLevel>(g_cutoff), g_sandbox_id);
EXPECT_EQ(Cdm::kSuccess, status);
// One last init with everything correct and working.
status = Cdm::initialize(Cdm::kNoSecureOutput, &g_host->global_storage(),
g_host, g_host, static_cast<Cdm::LogLevel>(g_cutoff),
g_sandbox_id);
g_host, g_host, &g_stderr_logger,
static_cast<Cdm::LogLevel>(g_cutoff), g_sandbox_id);
EXPECT_EQ(Cdm::kSuccess, status);
}
@@ -838,7 +860,7 @@ TEST_F(CdmTest, OpenSessionWithoutServiceCertificate) {
ASSERT_EQ(Cdm::kSuccess, cdm_->createSession(Cdm::kTemporary, &session_id));
// License request generation, however, should fail.
EXPECT_CALL(*this, onMessage(session_id, _, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, _, _, _)).Times(0);
EXPECT_EQ(Cdm::kNeedsServiceCertificate,
generateRequestWithRetry(session_id, Cdm::kCenc, kCencInitData));
Mock::VerifyAndClear(this);
@@ -852,7 +874,7 @@ TEST_F(CdmTest, OpenSessionWithoutServiceCertificate) {
cdm_->setServiceCertificate(Cdm::kLicensingService,
config_.license_service_certificate()));
EXPECT_CALL(*this, onMessage(session_id, _, _)).Times(AtLeast(1));
EXPECT_CALL(*this, onMessage(session_id, _, _, _)).Times(AtLeast(1));
EXPECT_EQ(Cdm::kSuccess,
generateRequestWithRetry(session_id, Cdm::kCenc, kCencInitData));
Mock::VerifyAndClear(this);
@@ -942,9 +964,13 @@ TEST_F(CdmTest, GenerateRequest) {
Cdm::Status status = cdm_->createSession(Cdm::kTemporary, &session_id);
ASSERT_EQ(Cdm::kSuccess, status);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _));
std::string url;
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _, _))
.WillOnce(SaveArg<3>(&url));
status = generateRequestWithRetry(session_id, Cdm::kCenc, kCencInitData);
EXPECT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
EXPECT_TRUE(url.empty());
}
TEST_F(CdmTest, GenerateRequest_ReuseSession) {
@@ -953,13 +979,14 @@ TEST_F(CdmTest, GenerateRequest_ReuseSession) {
Cdm::Status status = cdm_->createSession(Cdm::kTemporary, &session_id);
ASSERT_EQ(Cdm::kSuccess, status);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _));
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _, _));
status = generateRequestWithRetry(session_id, Cdm::kCenc, kCencInitData);
EXPECT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Can't call generateRequest more than once on a session.
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _, _))
.Times(0);
status = generateRequestWithRetry(session_id, Cdm::kCenc, kCencInitData);
EXPECT_EQ(Cdm::kInvalidState, status);
}
@@ -970,9 +997,13 @@ TEST_F(CdmTest, GenerateRequest_WebM) {
Cdm::Status status = cdm_->createSession(Cdm::kTemporary, &session_id);
ASSERT_EQ(Cdm::kSuccess, status);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _));
std::string url;
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _, _))
.WillOnce(SaveArg<3>(&url));
status = generateRequestWithRetry(session_id, Cdm::kWebM, kWebMInitData);
EXPECT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
EXPECT_TRUE(url.empty());
}
TEST_F(CdmTest, GenerateRequest_KeyIds) {
@@ -981,7 +1012,8 @@ TEST_F(CdmTest, GenerateRequest_KeyIds) {
Cdm::Status status = cdm_->createSession(Cdm::kTemporary, &session_id);
ASSERT_EQ(Cdm::kSuccess, status);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _, _))
.Times(0);
status = generateRequestWithRetry(session_id, Cdm::kKeyIds, kKeyIdsInitData);
EXPECT_EQ(Cdm::kNotSupported, status);
}
@@ -992,9 +1024,13 @@ TEST_F(CdmTest, GenerateRequest_HLS) {
Cdm::Status status = cdm_->createSession(Cdm::kTemporary, &session_id);
ASSERT_EQ(Cdm::kSuccess, status);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _));
std::string url;
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _, _))
.WillOnce(SaveArg<3>(&url));
status = generateRequestWithRetry(session_id, Cdm::kHls, kHlsInitData);
EXPECT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
EXPECT_TRUE(url.empty());
}
TEST_F(CdmTest, GenerateRequest_BogusType) {
@@ -1003,14 +1039,15 @@ TEST_F(CdmTest, GenerateRequest_BogusType) {
Cdm::Status status = cdm_->createSession(Cdm::kTemporary, &session_id);
ASSERT_EQ(Cdm::kSuccess, status);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _, _))
.Times(0);
status = generateRequestWithRetry(session_id, kBogusInitDataType, "asdf");
EXPECT_EQ(Cdm::kTypeError, status);
Mock::VerifyAndClear(this);
// This same session should still be usable with a supported init data type
// after failing with an unsupported or bogus type.
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _));
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _, _));
status = generateRequestWithRetry(session_id, Cdm::kCenc, kCencInitData);
EXPECT_EQ(Cdm::kSuccess, status);
}
@@ -1021,7 +1058,8 @@ TEST_F(CdmTest, GenerateRequest_Empty) {
Cdm::Status status = cdm_->createSession(Cdm::kTemporary, &session_id);
ASSERT_EQ(Cdm::kSuccess, status);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _, _))
.Times(0);
status = generateRequestWithRetry(session_id, Cdm::kCenc, "");
EXPECT_EQ(Cdm::kTypeError, status);
}
@@ -1032,7 +1070,8 @@ TEST_F(CdmTest, GenerateRequest_InvalidCenc) {
Cdm::Status status = cdm_->createSession(Cdm::kTemporary, &session_id);
ASSERT_EQ(Cdm::kSuccess, status);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _, _))
.Times(0);
status =
generateRequestWithRetry(session_id, Cdm::kCenc, kInvalidCencInitData);
EXPECT_EQ(Cdm::kNotSupported, status);
@@ -1044,7 +1083,8 @@ TEST_F(CdmTest, GenerateRequest_NonWidevineCenc) {
Cdm::Status status = cdm_->createSession(Cdm::kTemporary, &session_id);
ASSERT_EQ(Cdm::kSuccess, status);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _, _))
.Times(0);
status = generateRequestWithRetry(session_id, Cdm::kCenc,
kNonWidevineCencInitData);
EXPECT_EQ(Cdm::kNotSupported, status);
@@ -1056,7 +1096,7 @@ TEST_F(CdmTest, GenerateRequest_BogusSessionId) {
Cdm::Status status = cdm_->createSession(Cdm::kTemporary, &session_id);
ASSERT_EQ(Cdm::kSuccess, status);
EXPECT_CALL(*this, onMessage(_, _, _)).Times(0);
EXPECT_CALL(*this, onMessage(_, _, _, _)).Times(0);
status = generateRequestWithRetry(kBogusSessionId, Cdm::kCenc, kCencInitData);
EXPECT_EQ(Cdm::kSessionNotFound, status);
}
@@ -1178,7 +1218,8 @@ TEST_F(CdmTest, Close) {
ASSERT_EQ(Cdm::kSuccess, status);
// Can't generate a license request after close.
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _, _))
.Times(0);
status = generateRequestWithRetry(session_id, Cdm::kCenc, kCencInitData);
EXPECT_EQ(Cdm::kSessionNotFound, status);
Mock::VerifyAndClear(this);
@@ -1270,10 +1311,12 @@ TEST_F(CdmTest, LoadWillFireExpiration) {
// Let the key expire, make sure we get a key status update.
EXPECT_CALL(*this, onKeyStatusesChange(session_id, false));
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRenewal, _))
.Times(AtLeast(1));
std::string url;
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRenewal, _, _))
.WillOnce(SaveArg<3>(&url));
g_host->ElapseTime(kOfflineLicenseDurationMs);
Mock::VerifyAndClear(this);
EXPECT_FALSE(url.empty());
}
TEST_F(CdmTest, PerOriginLoadPersistent) {
@@ -1339,162 +1382,6 @@ TEST_F(CdmTest, PerOriginLoadPersistent) {
}
}
TEST_F(CdmTest, LoadUsageRecord) {
EnsureProvisioned();
std::string session_id;
std::string response;
ASSERT_NO_FATAL_FAILURE(CreateSessionAndFetchLicense(
Cdm::kPersistentUsageRecord, Cdm::kCenc, &session_id, &response));
// Update the session.
EXPECT_CALL(*this, onKeyStatusesChange(session_id, true));
Cdm::Status status = updateWithRetry(session_id, response);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Should be able to load the session again after closing it.
status = cdm_->close(session_id);
ASSERT_EQ(Cdm::kSuccess, status);
// There should be no usable keys after loading this session.
EXPECT_CALL(*this, onKeyStatusesChange(session_id, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _)).Times(0);
status = cdm_->load(session_id);
EXPECT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Should be able to load the session again after recreating the CDM.
ASSERT_NO_FATAL_FAILURE(RecreateCdm(true /* privacy_mode */));
EXPECT_CALL(*this, onKeyStatusesChange(session_id, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _)).Times(0);
status = cdm_->load(session_id);
EXPECT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Should not be able to load the session again clearing storage.
status = cdm_->close(session_id);
ASSERT_EQ(Cdm::kSuccess, status);
g_host->Reset();
EnsureProvisioned();
EXPECT_CALL(*this, onKeyStatusesChange(session_id, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _)).Times(0);
status = cdm_->load(session_id);
EXPECT_EQ(Cdm::kSessionNotFound, status);
Mock::VerifyAndClear(this);
}
TEST_F(CdmTest, DestroyUsageRecord) {
EnsureProvisioned();
std::string session_id;
std::string response;
ASSERT_NO_FATAL_FAILURE(CreateSessionAndFetchLicense(
Cdm::kPersistentUsageRecord, Cdm::kCenc, &session_id, &response));
// Update the session.
EXPECT_CALL(*this, onKeyStatusesChange(session_id, true));
Cdm::Status status = updateWithRetry(session_id, response);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Should be able to load the session again after closing it.
status = cdm_->close(session_id);
ASSERT_EQ(Cdm::kSuccess, status);
// There should be no usable keys after loading this session.
EXPECT_CALL(*this, onKeyStatusesChange(session_id, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _)).Times(0);
status = cdm_->load(session_id);
EXPECT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Should be able to load the session again after recreating the CDM.
ASSERT_NO_FATAL_FAILURE(RecreateCdm(true /* privacy_mode */));
EXPECT_CALL(*this, onKeyStatusesChange(session_id, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _)).Times(0);
status = cdm_->deleteUsageRecord(session_id);
EXPECT_EQ(Cdm::kSuccess, status);
status = cdm_->load(session_id);
EXPECT_EQ(Cdm::kSessionNotFound, status);
Mock::VerifyAndClear(this);
}
TEST_F(CdmTest, DestroyAllUsageRecords) {
EnsureProvisioned();
std::string session_id;
std::string response;
ASSERT_NO_FATAL_FAILURE(CreateSessionAndFetchLicense(
Cdm::kPersistentUsageRecord, Cdm::kCenc, &session_id, &response));
// Update the session.
EXPECT_CALL(*this, onKeyStatusesChange(session_id, true));
Cdm::Status status = updateWithRetry(session_id, response);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Should be able to load the session again after closing it.
status = cdm_->close(session_id);
ASSERT_EQ(Cdm::kSuccess, status);
// There should be no usable keys after loading this session.
EXPECT_CALL(*this, onKeyStatusesChange(session_id, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _)).Times(0);
status = cdm_->load(session_id);
EXPECT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Should be able to load the session again after recreating the CDM.
ASSERT_NO_FATAL_FAILURE(RecreateCdm(true /* privacy_mode */));
EXPECT_CALL(*this, onKeyStatusesChange(session_id, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _)).Times(0);
status = cdm_->deleteAllUsageRecords();
EXPECT_EQ(Cdm::kSuccess, status);
status = cdm_->load(session_id);
EXPECT_EQ(Cdm::kSessionNotFound, status);
Mock::VerifyAndClear(this);
}
TEST_F(CdmTest, ListUsageRecords) {
EnsureProvisioned();
std::string session_id;
std::string response;
ASSERT_NO_FATAL_FAILURE(CreateSessionAndFetchLicense(
Cdm::kPersistentUsageRecord, Cdm::kCenc, &session_id, &response));
// Update the session.
EXPECT_CALL(*this, onKeyStatusesChange(session_id, true));
Cdm::Status status = updateWithRetry(session_id, response);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Should be able to load the session again after closing it.
status = cdm_->close(session_id);
ASSERT_EQ(Cdm::kSuccess, status);
// There should be no usable keys after loading this session.
EXPECT_CALL(*this, onKeyStatusesChange(session_id, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _)).Times(0);
status = cdm_->load(session_id);
EXPECT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Should be able to load the session again after recreating the CDM.
ASSERT_NO_FATAL_FAILURE(RecreateCdm(true /* privacy_mode */));
EXPECT_CALL(*this, onKeyStatusesChange(session_id, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _)).Times(0);
std::vector<std::string> ksids;
status = cdm_->listUsageRecords(&ksids);
EXPECT_EQ(Cdm::kSuccess, status);
EXPECT_EQ(ksids.size(), 1UL);
if (ksids.size() > 0UL) {
EXPECT_TRUE(ksids[0] == session_id);
}
status = cdm_->load(session_id);
EXPECT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
}
TEST_F(CdmTest, LoadBogus) {
EnsureProvisioned();
EXPECT_CALL(*this, onKeyStatusesChange(_, _)).Times(0);
@@ -1521,7 +1408,7 @@ TEST_F(CdmTest, GetKeyStatuses) {
// Let the key expire.
EXPECT_CALL(*this, onKeyStatusesChange(session_id, false));
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRenewal, _))
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRenewal, _, _))
.Times(AtLeast(1));
g_host->ElapseTime(kExpirationTestDelayMs);
Mock::VerifyAndClear(this);
@@ -1553,7 +1440,7 @@ TEST_F(CdmTest, GetExpiration) {
// Let the key expire.
EXPECT_CALL(*this, onKeyStatusesChange(session_id, false));
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRenewal, _))
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRenewal, _, _))
.Times(AtLeast(1));
g_host->ElapseTime(kExpirationTestDelayMs);
Mock::VerifyAndClear(this);
@@ -1582,12 +1469,14 @@ TEST_P(CdmTestWithRemoveParam, Remove) {
// Remove the session. This causes a release message to be generated.
std::string message;
std::string url;
EXPECT_CALL(*this, onKeyStatusesChange(session_id, false));
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _))
.WillOnce(SaveArg<2>(&message));
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _, _))
.WillOnce(DoAll(SaveArg<2>(&message), SaveArg<3>(&url)));
Cdm::Status status = cdm_->remove(session_id);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
EXPECT_FALSE(url.empty());
// The keys should already be unusable.
Cdm::KeyStatusMap map;
@@ -1653,7 +1542,8 @@ TEST_F(CdmTest, ForceRemove) {
// Forcibly remove the session. This should immediately trigger a removal
// callback and should *not* cause a release message to be generated.
EXPECT_CALL(*this, onRemoveComplete(session_id)).Times(1);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _, _))
.Times(0);
Cdm::Status status = cdm_->forceRemove(session_id);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
@@ -1681,162 +1571,6 @@ TEST_F(CdmTest, ForceRemove) {
EXPECT_EQ(Cdm::kRangeError, status);
}
TEST_F(CdmTest, RemoveUsageRecord) {
EnsureProvisioned();
std::string session_id;
ASSERT_NO_FATAL_FAILURE(CreateSessionAndUpdate(Cdm::kPersistentUsageRecord,
Cdm::kCenc, &session_id));
// Remove the session. This causes a release message to be generated.
std::string message;
EXPECT_CALL(*this, onKeyStatusesChange(session_id, false));
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _))
.WillOnce(SaveArg<2>(&message));
Cdm::Status status = cdm_->remove(session_id);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// The keys should already be unusable.
Cdm::KeyStatusMap map;
status = cdm_->getKeyStatuses(session_id, &map);
ASSERT_EQ(Cdm::kSuccess, status);
EXPECT_EQ(Cdm::kReleased, map.begin()->second);
// Post the release message to the license server.
std::string response;
ASSERT_NO_FATAL_FAILURE(
FetchLicense(config_.license_server(), message, &response));
// Update the session.
EXPECT_CALL(*this, onRemoveComplete(session_id));
status = updateWithRetry(session_id, response);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// The session is now completely gone.
status = cdm_->close(session_id);
ASSERT_EQ(Cdm::kSessionNotFound, status);
}
TEST_F(CdmTest, RemoveThreeUsageRecords) {
EnsureProvisioned();
std::string session_id1, session_id2, session_id3;
ASSERT_NO_FATAL_FAILURE(CreateSessionAndUpdate(Cdm::kPersistentUsageRecord,
Cdm::kCenc, &session_id1));
ASSERT_NO_FATAL_FAILURE(CreateSessionAndUpdate(Cdm::kPersistentUsageRecord,
Cdm::kCenc, &session_id2));
ASSERT_NO_FATAL_FAILURE(CreateSessionAndUpdate(Cdm::kPersistentUsageRecord,
Cdm::kCenc, &session_id3));
// Close, reload and remove the middle session first
EXPECT_EQ(Cdm::kSuccess, cdm_->close(session_id2));
EXPECT_CALL(*this, onKeyStatusesChange(session_id2, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id2, Cdm::kLicenseRelease, _)).Times(0);
Cdm::Status status = cdm_->load(session_id2);
EXPECT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Remove the session. This causes a release message to be generated.
std::string message;
EXPECT_CALL(*this, onMessage(session_id2, Cdm::kLicenseRelease, _))
.WillOnce(SaveArg<2>(&message));
status = cdm_->remove(session_id2);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// The keys should already be unusable.
Cdm::KeyStatusMap map;
status = cdm_->getKeyStatuses(session_id2, &map);
ASSERT_EQ(Cdm::kSuccess, status);
EXPECT_TRUE(map.empty());
// Post the release message to the license server.
std::string response;
ASSERT_NO_FATAL_FAILURE(
FetchLicense(config_.license_server(), message, &response));
// Update the session.
EXPECT_CALL(*this, onRemoveComplete(session_id2));
status = updateWithRetry(session_id2, response);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// The session is now completely gone.
status = cdm_->close(session_id2);
ASSERT_EQ(Cdm::kSessionNotFound, status);
// Close, reload and remove the last session next
EXPECT_EQ(Cdm::kSuccess, cdm_->close(session_id3));
EXPECT_CALL(*this, onKeyStatusesChange(session_id3, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id3, Cdm::kLicenseRelease, _)).Times(0);
status = cdm_->load(session_id3);
EXPECT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Remove the session. This causes a release message to be generated.
EXPECT_CALL(*this, onMessage(session_id3, Cdm::kLicenseRelease, _))
.WillOnce(SaveArg<2>(&message));
status = cdm_->remove(session_id3);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// The keys should already be unusable.
status = cdm_->getKeyStatuses(session_id3, &map);
ASSERT_EQ(Cdm::kSuccess, status);
EXPECT_TRUE(map.empty());
// Post the release message to the license server.
ASSERT_NO_FATAL_FAILURE(
FetchLicense(config_.license_server(), message, &response));
// Update the session.
EXPECT_CALL(*this, onRemoveComplete(session_id3));
status = updateWithRetry(session_id3, response);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// The session is now completely gone.
status = cdm_->close(session_id3);
ASSERT_EQ(Cdm::kSessionNotFound, status);
// Close, reload and remove the first session next
EXPECT_EQ(Cdm::kSuccess, cdm_->close(session_id1));
EXPECT_CALL(*this, onKeyStatusesChange(session_id1, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id1, Cdm::kLicenseRelease, _)).Times(0);
status = cdm_->load(session_id1);
EXPECT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Remove the session. This causes a release message to be generated.
EXPECT_CALL(*this, onMessage(session_id1, Cdm::kLicenseRelease, _))
.WillOnce(SaveArg<2>(&message));
status = cdm_->remove(session_id1);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// The keys should already be unusable.
status = cdm_->getKeyStatuses(session_id1, &map);
ASSERT_EQ(Cdm::kSuccess, status);
EXPECT_TRUE(map.empty());
// Post the release message to the license server.
ASSERT_NO_FATAL_FAILURE(
FetchLicense(config_.license_server(), message, &response));
// Update the session.
EXPECT_CALL(*this, onRemoveComplete(session_id1));
status = updateWithRetry(session_id1, response);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// The session is now completely gone.
status = cdm_->close(session_id1);
ASSERT_EQ(Cdm::kSessionNotFound, status);
}
// Reload an offline license that does not have a usage entry.
TEST_F(CdmTest, LoadPersistentNoNonce) {
EnsureProvisioned();
@@ -1852,7 +1586,7 @@ TEST_F(CdmTest, LoadPersistentNoNonce) {
const std::string init_data = MakePSSH(pssh);
std::string license_request;
{
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _))
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _, _))
.WillOnce(SaveArg<2>(&license_request));
ASSERT_EQ(Cdm::kSuccess,
generateRequestWithRetry(session_id, Cdm::kCenc, init_data));
@@ -1905,7 +1639,7 @@ TEST_F(CdmTest, RemoveIncomplete) {
// Remove the session. This causes a release message to be generated.
std::string message;
EXPECT_CALL(*this, onKeyStatusesChange(session_id, false));
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _))
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _, _))
.WillOnce(SaveArg<2>(&message));
Cdm::Status status = cdm_->remove(session_id);
ASSERT_EQ(Cdm::kSuccess, status);
@@ -1923,7 +1657,8 @@ TEST_F(CdmTest, RemoveIncomplete) {
// Load the partially removed session.
EXPECT_CALL(*this, onKeyStatusesChange(session_id, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _, _))
.Times(0);
status = cdm_->load(session_id);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
@@ -1936,7 +1671,7 @@ TEST_F(CdmTest, RemoveIncomplete) {
// Remove the session again to fire the release message.
message.clear();
EXPECT_CALL(*this, onKeyStatusesChange(session_id, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _))
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _, _))
.WillOnce(SaveArg<2>(&message));
status = cdm_->remove(session_id);
ASSERT_EQ(Cdm::kSuccess, status);
@@ -1960,70 +1695,6 @@ TEST_F(CdmTest, RemoveIncomplete) {
ASSERT_EQ(Cdm::kSessionNotFound, status);
}
TEST_F(CdmTest, RemoveUsageRecordIncomplete) {
EnsureProvisioned();
std::string session_id;
ASSERT_NO_FATAL_FAILURE(CreateSessionAndUpdate(Cdm::kPersistentUsageRecord,
Cdm::kCenc, &session_id));
// Remove the session. This causes a release message to be generated.
std::string message;
EXPECT_CALL(*this, onKeyStatusesChange(session_id, false));
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _))
.WillOnce(SaveArg<2>(&message));
Cdm::Status status = cdm_->remove(session_id);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// The keys should already be unusable, but they should still exist.
Cdm::KeyStatusMap map;
status = cdm_->getKeyStatuses(session_id, &map);
ASSERT_EQ(Cdm::kSuccess, status);
ASSERT_FALSE(map.empty());
EXPECT_EQ(Cdm::kReleased, map.begin()->second);
// Recreate the CDM.
ASSERT_NO_FATAL_FAILURE(RecreateCdm(true /* privacy_mode */));
// Load the partially removed session.
EXPECT_CALL(*this, onKeyStatusesChange(session_id, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _)).Times(0);
status = cdm_->load(session_id);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Remove the session again to fire a release message.
message.clear();
EXPECT_CALL(*this, onKeyStatusesChange(session_id, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRelease, _))
.WillOnce(SaveArg<2>(&message));
status = cdm_->remove(session_id);
ASSERT_EQ(Cdm::kSuccess, status);
ASSERT_FALSE(message.empty());
Mock::VerifyAndClear(this);
// This session has no keys.
status = cdm_->getKeyStatuses(session_id, &map);
ASSERT_EQ(Cdm::kSuccess, status);
EXPECT_TRUE(map.empty());
// Post the release message to the license server.
std::string response;
ASSERT_NO_FATAL_FAILURE(
FetchLicense(config_.license_server(), message, &response));
// Update the session.
EXPECT_CALL(*this, onKeyStatusesChange(session_id, _)).Times(0);
EXPECT_CALL(*this, onRemoveComplete(session_id));
status = updateWithRetry(session_id, response);
ASSERT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// The session is now completely gone.
status = cdm_->load(session_id);
ASSERT_EQ(Cdm::kSessionNotFound, status);
}
TEST_F(CdmTest, RemoveNotLoaded) {
EnsureProvisioned();
// Create a persistent session and then close it.
@@ -2049,7 +1720,7 @@ TEST_F(CdmTest, RequestPersistentLicenseWithWrongInitData) {
ASSERT_EQ(Cdm::kSuccess, status);
std::string message;
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _))
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _, _))
.WillOnce(SaveArg<2>(&message));
status = generateRequestWithRetry(session_id, Cdm::kCenc, kCencInitData);
ASSERT_EQ(Cdm::kSuccess, status);
@@ -2068,7 +1739,7 @@ TEST_F(CdmTest, DISABLED_RequestTemporaryLicenseWithWrongInitData) {
ASSERT_EQ(Cdm::kSuccess, status);
std::string message;
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _))
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _, _))
.WillOnce(SaveArg<2>(&message));
status =
generateRequestWithRetry(session_id, Cdm::kCenc, kCencPersistentInitData);
@@ -2098,11 +1769,13 @@ TEST_F(CdmTest, Renewal) {
// When we elapse time, we should get a renewal message.
std::string message;
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRenewal, _))
.WillOnce(SaveArg<2>(&message));
std::string url;
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRenewal, _, _))
.WillOnce(DoAll(SaveArg<2>(&message), SaveArg<3>(&url)));
g_host->ElapseTime(kRenewalTestDelayMs);
Mock::VerifyAndClear(this);
ASSERT_FALSE(message.empty()); // Stop the test if no message came through.
EXPECT_FALSE(url.empty());
// When should still have a timer.
EXPECT_NE(0u, g_host->NumTimers());
@@ -2114,7 +1787,8 @@ TEST_F(CdmTest, Renewal) {
Cdm::Status status = cdm_->close(session_id);
ASSERT_EQ(Cdm::kSuccess, status);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRenewal, _)).Times(0);
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRenewal, _, _))
.Times(0);
g_host->ElapseTime(kRenewalTestDelayMs * 10);
Mock::VerifyAndClear(this);
}
@@ -2176,7 +1850,7 @@ TEST_F(CdmTest, SetAppParameters) {
// Send a generate request to ensure the parameter is in the message.
std::string message;
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _))
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _, _))
.WillOnce(SaveArg<2>(&message));
status = generateRequestWithRetry(session_id, Cdm::kCenc, kCencInitData);
EXPECT_EQ(Cdm::kSuccess, status);
@@ -2278,7 +1952,7 @@ TEST_F(CdmTest, HandlesKeyRotationWithOnlyOneLicenseRequest) {
// Generate a license request for the 1st entitlement init data.
std::string license_request;
{
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _))
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _, _))
.WillOnce(SaveArg<2>(&license_request));
ASSERT_EQ(Cdm::kSuccess,
generateRequestWithRetry(session_id, Cdm::kCenc,
@@ -2794,7 +2468,15 @@ TEST_F(CdmIndividualizationTest, CastReceiverProvisionAndSign) {
EXPECT_EQ(decrypted_digest, kFakeCastMessage);
}
class CdmProv40IndividualizationTest : public CdmTest {};
class CdmProv40IndividualizationTest : public CdmTest {
void SetUp() override {
CdmTest::SetUp();
if (wvoec::global_features.provisioning_method !=
OEMCrypto_BootCertificateChain) {
GTEST_SKIP() << "Test for Prov 4.0 devices only.";
}
}
};
TEST_F(CdmProv40IndividualizationTest, NeedsOemCertProvisioning) {
// No OEM cert, no DRM cert.