From db1382e0a3c46a5caae106c50a0a2f0a09fcd494 Mon Sep 17 00:00:00 2001 From: Rahul Frias Date: Fri, 9 Jan 2015 00:28:56 -0800 Subject: [PATCH] Corrections to license policy handling and reporting If a key query occurred before a license was received an UNKNOWN_ERROR was returned. This now succeeds but returns no information (an empty container). Also licenses that were already expired when received were not marked as such. This did not cause violations in playback rules but caused an exception when they were queried. [ Merge of https://widevine-internal-review.googlesource.com/#/c/12300 from wv git repo ] b/18843625 Change-Id: I6990765c15e519ddf203a2fd8f0a130306f090a6 --- libwvdrmengine/cdm/core/src/policy_engine.cpp | 15 ++-- .../cdm/core/test/policy_engine_unittest.cpp | 82 ++++++++++++++++++- 2 files changed, 87 insertions(+), 10 deletions(-) diff --git a/libwvdrmengine/cdm/core/src/policy_engine.cpp b/libwvdrmengine/cdm/core/src/policy_engine.cpp index 2e29782a..719d1304 100644 --- a/libwvdrmengine/cdm/core/src/policy_engine.cpp +++ b/libwvdrmengine/cdm/core/src/policy_engine.cpp @@ -163,15 +163,14 @@ void PolicyEngine::UpdateLicense( policy_max_duration_seconds_ = policy_.license_duration_seconds(); } - if (!policy_.can_play()) { + int64_t current_time = clock_->GetCurrentTime(); + if (!policy_.can_play() || + IsLicenseDurationExpired(current_time) || + IsPlaybackDurationExpired(current_time)) { license_state_ = kLicenseStateExpired; return; } - int64_t current_time = clock_->GetCurrentTime(); - if (IsLicenseDurationExpired(current_time)) return; - if (IsPlaybackDurationExpired(current_time)) return; - // Update state if (current_time >= license_start_time_) { license_state_ = kLicenseStateCanPlay; @@ -216,8 +215,10 @@ CdmResponseType PolicyEngine::Query(CdmQueryMap* key_info) { std::stringstream ss; int64_t current_time = clock_->GetCurrentTime(); - if (license_state_ == kLicenseStateInitial) - return UNKNOWN_ERROR; + if (license_state_ == kLicenseStateInitial) { + key_info->clear(); + return NO_ERROR; + } (*key_info)[QUERY_KEY_LICENSE_TYPE] = license_id_.type() == video_widevine_server::sdk::STREAMING ? diff --git a/libwvdrmengine/cdm/core/test/policy_engine_unittest.cpp b/libwvdrmengine/cdm/core/test/policy_engine_unittest.cpp index b8c63790..23feff51 100644 --- a/libwvdrmengine/cdm/core/test/policy_engine_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/policy_engine_unittest.cpp @@ -135,7 +135,8 @@ TEST_F(PolicyEngineTest, PlaybackFailed_CanPlayFalse) { policy->set_can_play(false); EXPECT_CALL(*mock_clock_, GetCurrentTime()) - .WillOnce(Return(kLicenseStartTime + 1)); + .WillOnce(Return(kLicenseStartTime + 1)) + .WillOnce(Return(kLicenseStartTime + 5)); policy_engine_->SetLicense(license_); EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId)); @@ -825,12 +826,26 @@ TEST_F(PolicyEngineTest, PlaybackOk_RenewedWithUsage) { EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId)); } -TEST_F(PolicyEngineTest, QueryFailed_LicenseNotReceived) { +TEST_F(PolicyEngineTest, QuerySuccess_LicenseNotReceived) { EXPECT_CALL(*mock_clock_, GetCurrentTime()) .WillOnce(Return(kLicenseStartTime)); CdmQueryMap query_info; - EXPECT_EQ(UNKNOWN_ERROR, policy_engine_->Query(&query_info)); + EXPECT_EQ(NO_ERROR, policy_engine_->Query(&query_info)); + EXPECT_EQ(0, query_info.size()); +} + +TEST_F(PolicyEngineTest, QuerySuccess_LicenseStartTimeNotSet) { + license_.clear_license_start_time(); + + EXPECT_CALL(*mock_clock_, GetCurrentTime()) + .WillOnce(Return(kLicenseStartTime + 1)); + + policy_engine_->SetLicense(license_); + + CdmQueryMap query_info; + EXPECT_EQ(NO_ERROR, policy_engine_->Query(&query_info)); + EXPECT_EQ(0, query_info.size()); } TEST_F(PolicyEngineTest, QuerySuccess) { @@ -1001,6 +1016,66 @@ TEST_F(PolicyEngineTest, QuerySuccess_Offline) { EXPECT_EQ(kRenewalServerUrl, query_info[QUERY_KEY_RENEWAL_SERVER_URL]); } +TEST_F(PolicyEngineTest, QuerySuccess_InitialRentalDurationExpired) { + License_Policy* policy = license_.mutable_policy(); + policy->set_rental_duration_seconds(kLowDuration); + policy->set_license_duration_seconds(kHighDuration); + + EXPECT_CALL(*mock_clock_, GetCurrentTime()) + .WillOnce(Return(kLicenseStartTime + kLowDuration + 1)) + .WillOnce(Return(kLicenseStartTime + kLowDuration + 5)); + + policy_engine_->SetLicense(license_); + + EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId)); + + CdmQueryMap query_info; + EXPECT_EQ(NO_ERROR, policy_engine_->Query(&query_info)); + EXPECT_EQ(QUERY_VALUE_STREAMING, query_info[QUERY_KEY_LICENSE_TYPE]); + EXPECT_EQ(QUERY_VALUE_TRUE, query_info[QUERY_KEY_PLAY_ALLOWED]); + EXPECT_EQ(QUERY_VALUE_FALSE, query_info[QUERY_KEY_PERSIST_ALLOWED]); + EXPECT_EQ(QUERY_VALUE_TRUE, query_info[QUERY_KEY_RENEW_ALLOWED]); + + int64_t remaining_time; + std::istringstream ss; + ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]); + ss >> remaining_time; + EXPECT_EQ(0, remaining_time); + ss.clear(); + ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]); + ss >> remaining_time; + EXPECT_EQ(kPlaybackDuration, remaining_time); + EXPECT_EQ(kRenewalServerUrl, query_info[QUERY_KEY_RENEWAL_SERVER_URL]); +} + +TEST_F(PolicyEngineTest, QuerySuccess_InitialLicenseDurationExpired) { + EXPECT_CALL(*mock_clock_, GetCurrentTime()) + .WillOnce(Return(kLicenseStartTime + kStreamingLicenseDuration + 1)) + .WillOnce(Return(kLicenseStartTime + kStreamingLicenseDuration + 5)); + + policy_engine_->SetLicense(license_); + + EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId)); + + CdmQueryMap query_info; + EXPECT_EQ(NO_ERROR, policy_engine_->Query(&query_info)); + EXPECT_EQ(QUERY_VALUE_STREAMING, query_info[QUERY_KEY_LICENSE_TYPE]); + EXPECT_EQ(QUERY_VALUE_TRUE, query_info[QUERY_KEY_PLAY_ALLOWED]); + EXPECT_EQ(QUERY_VALUE_FALSE, query_info[QUERY_KEY_PERSIST_ALLOWED]); + EXPECT_EQ(QUERY_VALUE_TRUE, query_info[QUERY_KEY_RENEW_ALLOWED]); + + int64_t remaining_time; + std::istringstream ss; + ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]); + ss >> remaining_time; + EXPECT_EQ(0, remaining_time); + ss.clear(); + ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]); + ss >> remaining_time; + EXPECT_EQ(kPlaybackDuration, remaining_time); + EXPECT_EQ(kRenewalServerUrl, query_info[QUERY_KEY_RENEWAL_SERVER_URL]); +} + TEST_F(PolicyEngineTest, QuerySuccess_CanPlayFalse) { LicenseIdentification* id = license_.mutable_id(); id->set_type(OFFLINE); @@ -1014,6 +1089,7 @@ TEST_F(PolicyEngineTest, QuerySuccess_CanPlayFalse) { EXPECT_CALL(*mock_clock_, GetCurrentTime()) .WillOnce(Return(kLicenseStartTime + 1)) + .WillOnce(Return(kLicenseStartTime + 5)) .WillOnce(Return(kLicenseStartTime + 100)); policy_engine_->SetLicense(license_);