Report key status change

Also modified PolicyEngine::CanDecrypt to use the new Keys_status_.

Bug: 19771431

Merged from Widevine CDM repo:
https://widevine-internal-review.googlesource.com/#/c/13904/

Change-Id: If7fb7fa45ecf9ff4e65278cda00ad7230b57f50b
This commit is contained in:
Kongqun Yang
2015-03-30 19:10:56 -07:00
parent bdb82e04f8
commit 4621028434
10 changed files with 315 additions and 26 deletions

View File

@@ -38,6 +38,8 @@ const int64_t kHighDuration =
const char* kRenewalServerUrl =
"https://test.google.com/license/GetCencLicense";
const wvcdm::KeyId kKeyId = "357adc89f1673433c36c621f1b5c41ee";
const wvcdm::KeyId kAnotherKeyId = "another_key_id";
const wvcdm::KeyId kSomeRandomKeyId = "some_random_key_id";
const wvcdm::CdmSessionId kSessionId = "mock_session_id";
int64_t GetLicenseRenewalDelay(int64_t license_duration) {
@@ -58,20 +60,34 @@ using video_widevine_server::sdk::OFFLINE;
// gmock methods
using ::testing::_;
using ::testing::AllOf;
using ::testing::AtLeast;
using ::testing::Field;
using ::testing::InSequence;
using ::testing::MockFunction;
using ::testing::Return;
using ::testing::StrictMock;
using ::testing::UnorderedElementsAre;
class MockCdmEventListener : public WvCdmEventListener {
public:
MOCK_METHOD1(OnSessionRenewalNeeded, void(const CdmSessionId& session_id));
MOCK_METHOD1(OnSessionExpiration, void(const CdmSessionId& session_id));
MOCK_METHOD3(OnSessionKeysChange,
void(const CdmSessionId& session_id,
const std::vector<CdmKeyInformation>& cdm_keys_info,
bool has_new_usable_key));
MOCK_METHOD2(OnExpirationUpdate,
void(const CdmSessionId& session_id, int64_t new_expiry_time));
};
class MockMaxResEngine : public MaxResEngine {
public:
MockMaxResEngine() : MaxResEngine(NULL) {}
MOCK_METHOD1(CanDecrypt, bool(const KeyId& key_id));
};
class PolicyEngineTest : public ::testing::Test {
protected:
virtual void SetUp() {
@@ -85,6 +101,10 @@ class PolicyEngineTest : public ::testing::Test {
id->set_version(1);
id->set_type(STREAMING);
License::KeyContainer* key = license_.add_key();
key->set_type(License::KeyContainer::CONTENT);
key->set_id(kKeyId);
License_Policy* policy = license_.mutable_policy();
policy = license_.mutable_policy();
policy->set_can_play(true);
@@ -120,8 +140,42 @@ class PolicyEngineTest : public ::testing::Test {
policy_engine_->set_clock(mock_clock_);
}
void InjectMockMaxResEngine() {
mock_max_res_engine_ = new MockMaxResEngine();
policy_engine_->set_max_res_engine(mock_max_res_engine_);
}
void ExpectSessionKeysChange(CdmKeyStatus expected_key_status,
bool expected_has_new_usable_key) {
EXPECT_CALL(mock_event_listener_,
OnSessionKeysChange(
kSessionId,
UnorderedElementsAre(
AllOf(Field(&CdmKeyInformation::key_id, kKeyId),
Field(&CdmKeyInformation::key_status,
expected_key_status))),
expected_has_new_usable_key));
}
void ExpectSessionKeysChange(CdmKeyStatus expected_key1_status,
CdmKeyStatus expected_key2_status,
bool expected_has_new_usable_key) {
EXPECT_CALL(mock_event_listener_,
OnSessionKeysChange(
kSessionId,
UnorderedElementsAre(
AllOf(Field(&CdmKeyInformation::key_id, kKeyId),
Field(&CdmKeyInformation::key_status,
expected_key1_status)),
AllOf(Field(&CdmKeyInformation::key_id, kAnotherKeyId),
Field(&CdmKeyInformation::key_status,
expected_key2_status))),
expected_has_new_usable_key));
}
StrictMock<MockCdmEventListener> mock_event_listener_;
MockClock* mock_clock_;
MockMaxResEngine* mock_max_res_engine_;
scoped_ptr<PolicyEngine> policy_engine_;
License license_;
MockFunction<void(int i)> check_;
@@ -137,6 +191,7 @@ TEST_F(PolicyEngineTest, PlaybackSuccess) {
.WillOnce(Return(kLicenseStartTime + 5))
.WillOnce(Return(kLicenseStartTime + 10));
ExpectSessionKeysChange(kKeyStatusUsable, true);
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, kLicenseStartTime + kLowDuration));
@@ -146,6 +201,7 @@ TEST_F(PolicyEngineTest, PlaybackSuccess) {
policy_engine_->BeginDecryption();
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId));
EXPECT_FALSE(policy_engine_->CanDecrypt(kSomeRandomKeyId));
}
TEST_F(PolicyEngineTest, PlaybackFailed_CanPlayFalse) {
@@ -156,6 +212,8 @@ TEST_F(PolicyEngineTest, PlaybackFailed_CanPlayFalse) {
.WillOnce(Return(kLicenseStartTime + 1))
.WillOnce(Return(kLicenseStartTime + 5));
ExpectSessionKeysChange(kKeyStatusExpired, false);
policy_engine_->SetLicense(license_);
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId));
@@ -179,9 +237,11 @@ TEST_F(PolicyEngineTest, PlaybackFails_RentalDurationExpired) {
.WillOnce(Return(kLicenseStartTime + min_duration));
InSequence s;
ExpectSessionKeysChange(kKeyStatusUsable, true);
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, kLicenseStartTime + kLowDuration));
EXPECT_CALL(check_, Call(1));
ExpectSessionKeysChange(kKeyStatusExpired, false);
EXPECT_CALL(mock_event_listener_, OnSessionExpiration(kSessionId));
EXPECT_CALL(check_, Call(2));
@@ -211,11 +271,13 @@ TEST_F(PolicyEngineTest, PlaybackFails_PlaybackDurationExpired) {
.WillOnce(Return(playback_start_time + kPlaybackDuration + 2));
InSequence s;
ExpectSessionKeysChange(kKeyStatusUsable, true);
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, kLicenseStartTime + kHighDuration));
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, playback_start_time + kPlaybackDuration));
EXPECT_CALL(check_, Call(1));
ExpectSessionKeysChange(kKeyStatusExpired, false);
EXPECT_CALL(mock_event_listener_, OnSessionExpiration(_));
EXPECT_CALL(check_, Call(2));
@@ -244,9 +306,11 @@ TEST_F(PolicyEngineTest, PlaybackFails_LicenseDurationExpired) {
.WillOnce(Return(kLicenseStartTime + min_duration));
InSequence s;
ExpectSessionKeysChange(kKeyStatusUsable, true);
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, kLicenseStartTime + kLowDuration));
EXPECT_CALL(check_, Call(1));
ExpectSessionKeysChange(kKeyStatusExpired, false);
EXPECT_CALL(mock_event_listener_, OnSessionExpiration(_));
EXPECT_CALL(check_, Call(2));
@@ -275,9 +339,11 @@ TEST_F(PolicyEngineTest, PlaybackFails_ExpiryBeforeRenewalDelay) {
.WillOnce(Return(kLicenseStartTime + min_duration));
InSequence s;
ExpectSessionKeysChange(kKeyStatusUsable, true);
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, kLicenseStartTime + kLowDuration));
EXPECT_CALL(check_, Call(1));
ExpectSessionKeysChange(kKeyStatusExpired, false);
EXPECT_CALL(mock_event_listener_, OnSessionExpiration(_));
EXPECT_CALL(check_, Call(2));
@@ -309,6 +375,7 @@ TEST_F(PolicyEngineTest, PlaybackOk_RentalDuration0) {
.WillOnce(Return(kLicenseStartTime + kStreamingLicenseDuration));
InSequence s;
ExpectSessionKeysChange(kKeyStatusUsable, true);
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, kLicenseStartTime + kLowDuration));
EXPECT_CALL(check_, Call(1));
@@ -316,6 +383,7 @@ TEST_F(PolicyEngineTest, PlaybackOk_RentalDuration0) {
EXPECT_CALL(check_, Call(2));
EXPECT_CALL(mock_event_listener_, OnSessionRenewalNeeded(_));
EXPECT_CALL(check_, Call(3));
ExpectSessionKeysChange(kKeyStatusExpired, false);
EXPECT_CALL(mock_event_listener_, OnSessionExpiration(_));
EXPECT_CALL(check_, Call(4));
@@ -348,6 +416,7 @@ TEST_F(PolicyEngineTest, PlaybackOk_PlaybackDuration0) {
.WillOnce(Return(kLicenseStartTime + kHighDuration + 2));
InSequence s;
ExpectSessionKeysChange(kKeyStatusUsable, true);
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, kLicenseStartTime + kHighDuration));
EXPECT_CALL(check_, Call(1));
@@ -355,6 +424,7 @@ TEST_F(PolicyEngineTest, PlaybackOk_PlaybackDuration0) {
EXPECT_CALL(check_, Call(2));
EXPECT_CALL(mock_event_listener_, OnSessionRenewalNeeded(_));
EXPECT_CALL(check_, Call(3));
ExpectSessionKeysChange(kKeyStatusExpired, false);
EXPECT_CALL(mock_event_listener_, OnSessionExpiration(_));
EXPECT_CALL(check_, Call(4));
@@ -385,9 +455,11 @@ TEST_F(PolicyEngineTest, PlaybackOk_LicenseDuration0) {
.WillOnce(Return(kLicenseStartTime + min_duration));
InSequence s;
ExpectSessionKeysChange(kKeyStatusUsable, true);
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, kLicenseStartTime + kLowDuration));
EXPECT_CALL(check_, Call(1));
ExpectSessionKeysChange(kKeyStatusExpired, false);
EXPECT_CALL(mock_event_listener_, OnSessionExpiration(_));
EXPECT_CALL(check_, Call(2));
@@ -417,6 +489,7 @@ TEST_F(PolicyEngineTest, PlaybackOk_Durations0) {
.WillOnce(Return(kLicenseStartTime + kHighDuration - 1))
.WillOnce(Return(kLicenseStartTime + kHighDuration));
ExpectSessionKeysChange(kKeyStatusUsable, true);
EXPECT_CALL(mock_event_listener_, OnExpirationUpdate(_, kNoExpiration));
policy_engine_->SetLicense(license_);
@@ -437,8 +510,11 @@ TEST_F(PolicyEngineTest, PlaybackOk_LicenseWithFutureStartTime) {
.WillOnce(Return(kLicenseStartTime))
.WillOnce(Return(kLicenseStartTime + 10));
InSequence s;
ExpectSessionKeysChange(kKeyStatusPending, false);
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, kLicenseStartTime + kLowDuration));
ExpectSessionKeysChange(kKeyStatusUsable, true);
policy_engine_->SetLicense(license_);
@@ -466,10 +542,12 @@ TEST_F(PolicyEngineTest, PlaybackFailed_CanRenewFalse) {
.WillOnce(Return(kLicenseStartTime + kStreamingLicenseDuration + 10));
InSequence s;
ExpectSessionKeysChange(kKeyStatusUsable, true);
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, kLicenseStartTime + kLowDuration));
EXPECT_CALL(check_, Call(1));
EXPECT_CALL(check_, Call(2));
ExpectSessionKeysChange(kKeyStatusExpired, false);
EXPECT_CALL(mock_event_listener_, OnSessionExpiration(_));
EXPECT_CALL(check_, Call(3));
@@ -502,6 +580,7 @@ TEST_F(PolicyEngineTest, PlaybackOk_RenewSuccess) {
kLicenseRenewalRetryInterval + 10));
InSequence s;
ExpectSessionKeysChange(kKeyStatusUsable, true);
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, kLicenseStartTime + kLowDuration));
EXPECT_CALL(check_, Call(1));
@@ -550,14 +629,17 @@ TEST_F(PolicyEngineTest, PlaybackOk_RenewSuccess_WithFutureStartTime) {
.WillOnce(Return(kLicenseStartTime + license_renewal_delay + 60));
InSequence s;
ExpectSessionKeysChange(kKeyStatusUsable, true);
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, kLicenseStartTime + kLowDuration));
EXPECT_CALL(check_, Call(1));
EXPECT_CALL(mock_event_listener_, OnSessionRenewalNeeded(_));
EXPECT_CALL(check_, Call(2));
ExpectSessionKeysChange(kKeyStatusPending, false);
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, new_license_start_time + kLowDuration));
EXPECT_CALL(check_, Call(3));
ExpectSessionKeysChange(kKeyStatusUsable, true);
EXPECT_CALL(check_, Call(4));
policy_engine_->SetLicense(license_);
@@ -598,6 +680,7 @@ TEST_F(PolicyEngineTest, PlaybackFailed_RenewFailedVersionNotUpdated) {
.WillOnce(Return(kLicenseStartTime + kStreamingLicenseDuration + 10));
InSequence s;
ExpectSessionKeysChange(kKeyStatusUsable, true);
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, kLicenseStartTime + kLowDuration));
EXPECT_CALL(check_, Call(1));
@@ -605,6 +688,7 @@ TEST_F(PolicyEngineTest, PlaybackFailed_RenewFailedVersionNotUpdated) {
EXPECT_CALL(check_, Call(2));
EXPECT_CALL(mock_event_listener_, OnSessionRenewalNeeded(_));
EXPECT_CALL(check_, Call(3));
ExpectSessionKeysChange(kKeyStatusExpired, false);
EXPECT_CALL(mock_event_listener_, OnSessionExpiration(_));
EXPECT_CALL(check_, Call(4));
@@ -652,6 +736,7 @@ TEST_F(PolicyEngineTest, PlaybackFailed_RepeatedRenewFailures) {
.WillOnce(Return(kLicenseStartTime + kStreamingLicenseDuration + 15));
InSequence s;
ExpectSessionKeysChange(kKeyStatusUsable, true);
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, kLicenseStartTime + kLowDuration));
EXPECT_CALL(check_, Call(1));
@@ -664,6 +749,7 @@ TEST_F(PolicyEngineTest, PlaybackFailed_RepeatedRenewFailures) {
EXPECT_CALL(mock_event_listener_, OnSessionRenewalNeeded(_));
EXPECT_CALL(check_, Call(6));
EXPECT_CALL(check_, Call(7));
ExpectSessionKeysChange(kKeyStatusExpired, false);
EXPECT_CALL(mock_event_listener_, OnSessionExpiration(_));
EXPECT_CALL(check_, Call(8));
@@ -702,6 +788,7 @@ TEST_F(PolicyEngineTest, PlaybackOk_RenewSuccessAfterExpiry) {
.WillOnce(Return(kLicenseStartTime + kStreamingLicenseDuration + 40));
InSequence s;
ExpectSessionKeysChange(kKeyStatusUsable, true);
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, kLicenseStartTime + kLowDuration));
EXPECT_CALL(check_, Call(1));
@@ -714,8 +801,10 @@ TEST_F(PolicyEngineTest, PlaybackOk_RenewSuccessAfterExpiry) {
EXPECT_CALL(mock_event_listener_, OnSessionRenewalNeeded(_));
EXPECT_CALL(check_, Call(6));
EXPECT_CALL(check_, Call(7));
ExpectSessionKeysChange(kKeyStatusExpired, false);
EXPECT_CALL(mock_event_listener_, OnSessionExpiration(_));
EXPECT_CALL(check_, Call(8));
ExpectSessionKeysChange(kKeyStatusUsable, true);
EXPECT_CALL(
mock_event_listener_,
OnExpirationUpdate(_, new_license_start_time + new_license_duration));
@@ -767,6 +856,7 @@ TEST_F(PolicyEngineTest, PlaybackOk_RenewSuccessAfterFailures) {
.WillOnce(Return(kLicenseStartTime + license_renewal_delay + 200));
InSequence s;
ExpectSessionKeysChange(kKeyStatusUsable, true);
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, kLicenseStartTime + kLowDuration));
EXPECT_CALL(check_, Call(1));
@@ -818,6 +908,7 @@ TEST_F(PolicyEngineTest, PlaybackOk_RenewedWithUsage) {
.WillOnce(Return(kLicenseStartTime + 50));
InSequence s;
ExpectSessionKeysChange(kKeyStatusUsable, true);
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, kLicenseStartTime + kLowDuration));
EXPECT_CALL(check_, Call(1));
@@ -850,6 +941,87 @@ TEST_F(PolicyEngineTest, PlaybackOk_RenewedWithUsage) {
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId));
}
TEST_F(PolicyEngineTest, MultipleKeysInLicense) {
const char kSigningKeyId[] = "signing_key";
license_.clear_key();
License::KeyContainer* content_key = license_.add_key();
content_key->set_type(License::KeyContainer::CONTENT);
content_key->set_id(kKeyId);
License::KeyContainer* non_content_key = license_.add_key();
non_content_key->set_type(License::KeyContainer::SIGNING);
non_content_key->set_id(kSigningKeyId);
License::KeyContainer* content_key_without_id = license_.add_key();
content_key_without_id->set_type(License::KeyContainer::CONTENT);
License::KeyContainer* another_content_key = license_.add_key();
another_content_key->set_type(License::KeyContainer::CONTENT);
another_content_key->set_id(kAnotherKeyId);
EXPECT_CALL(*mock_clock_, GetCurrentTime())
.WillOnce(Return(kLicenseStartTime + 1));
ExpectSessionKeysChange(kKeyStatusUsable, kKeyStatusUsable, true);
EXPECT_CALL(mock_event_listener_, OnExpirationUpdate(_, _));
policy_engine_->SetLicense(license_);
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId));
EXPECT_TRUE(policy_engine_->CanDecrypt(kAnotherKeyId));
EXPECT_FALSE(policy_engine_->CanDecrypt(kSigningKeyId));
EXPECT_FALSE(policy_engine_->CanDecrypt(kSomeRandomKeyId));
}
TEST_F(PolicyEngineTest, KeysOutputNotAllowedByMaxResEngine) {
license_.clear_key();
License::KeyContainer* content_key = license_.add_key();
content_key->set_type(License::KeyContainer::CONTENT);
content_key->set_id(kKeyId);
License::KeyContainer* another_content_key = license_.add_key();
another_content_key->set_type(License::KeyContainer::CONTENT);
another_content_key->set_id(kAnotherKeyId);
EXPECT_CALL(*mock_clock_, GetCurrentTime())
.WillOnce(Return(kLicenseStartTime + 1))
.WillOnce(Return(kLicenseStartTime + 5))
.WillOnce(Return(kLicenseStartTime + 8))
.WillOnce(Return(kLicenseStartTime + 10));
InjectMockMaxResEngine();
EXPECT_CALL(*mock_max_res_engine_, CanDecrypt(kKeyId))
.WillOnce(Return(false))
.WillOnce(Return(true))
.WillOnce(Return(false))
.WillOnce(Return(true));
EXPECT_CALL(*mock_max_res_engine_, CanDecrypt(kAnotherKeyId))
.WillOnce(Return(false))
.WillOnce(Return(false))
.WillOnce(Return(true))
.WillOnce(Return(true));
InSequence s;
ExpectSessionKeysChange(kKeyStatusOutputNotAllowed,
kKeyStatusOutputNotAllowed, false);
EXPECT_CALL(mock_event_listener_, OnExpirationUpdate(_, _));
ExpectSessionKeysChange(kKeyStatusUsable, kKeyStatusOutputNotAllowed, true);
ExpectSessionKeysChange(kKeyStatusOutputNotAllowed, kKeyStatusUsable, true);
ExpectSessionKeysChange(kKeyStatusUsable, kKeyStatusUsable, true);
policy_engine_->SetLicense(license_);
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId));
EXPECT_FALSE(policy_engine_->CanDecrypt(kAnotherKeyId));
policy_engine_->OnTimerEvent();
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId));
EXPECT_FALSE(policy_engine_->CanDecrypt(kAnotherKeyId));
policy_engine_->OnTimerEvent();
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId));
EXPECT_TRUE(policy_engine_->CanDecrypt(kAnotherKeyId));
policy_engine_->OnTimerEvent();
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId));
EXPECT_TRUE(policy_engine_->CanDecrypt(kAnotherKeyId));
}
class PolicyEngineQueryTest : public PolicyEngineTest {
protected:
virtual void SetUp() {