Load keys before sending OnKeyStatusChange notifications
[ merge of http://go/wvgerrit/17454 ] When processing a license or renewal, calls to Set/UpdateLicense update the policy information. A side effect was introduced whereby updating the policy may cause (expiration, session key state) notifications to be sent to the listener. Due to the ordering, the notifications would be sent before the keys were loaded/refreshed, which caused issues when the notifications were immediately acted upon. This has now been corrected. b/27842970 Change-Id: Id81a71ff48edfa9ca0baafc43267995d5a3e80a6
This commit is contained in:
@@ -549,8 +549,6 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
||||
server_url_ = license.policy().renewal_server_url();
|
||||
}
|
||||
|
||||
policy_engine_->SetLicense(license);
|
||||
|
||||
if (license.policy().has_renew_with_client_id()) {
|
||||
renew_with_client_id_ = license.policy().renew_with_client_id();
|
||||
}
|
||||
@@ -565,6 +563,7 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
||||
it != key_array.end(); ++it) {
|
||||
loaded_keys_.insert(it->key_id());
|
||||
}
|
||||
policy_engine_->SetLicense(license);
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
@@ -626,8 +625,6 @@ CdmResponseType CdmLicense::HandleKeyUpdateResponse(
|
||||
return LICENSE_ID_NOT_FOUND;
|
||||
}
|
||||
|
||||
policy_engine_->UpdateLicense(license);
|
||||
|
||||
if (license.policy().has_renew_with_client_id()) {
|
||||
renew_with_client_id_ = license.policy().renew_with_client_id();
|
||||
}
|
||||
@@ -651,6 +648,8 @@ CdmResponseType CdmLicense::HandleKeyUpdateResponse(
|
||||
|
||||
if (session_->RefreshKeys(signed_response.msg(), signed_response.signature(),
|
||||
key_array.size(), &key_array[0])) {
|
||||
policy_engine_->UpdateLicense(license);
|
||||
|
||||
return KEY_ADDED;
|
||||
} else {
|
||||
return REFRESH_KEYS_ERROR;
|
||||
|
||||
@@ -30,6 +30,7 @@ using ::testing::AllOf;
|
||||
using ::testing::AtLeast;
|
||||
using ::testing::Contains;
|
||||
using ::testing::Each;
|
||||
using ::testing::Invoke;
|
||||
using ::testing::IsEmpty;
|
||||
using ::testing::Not;
|
||||
using ::testing::Pair;
|
||||
@@ -811,7 +812,6 @@ class TestWvCdmClientPropertySet : public CdmClientPropertySet {
|
||||
class TestWvCdmEventListener : public WvCdmEventListener {
|
||||
public:
|
||||
TestWvCdmEventListener() : WvCdmEventListener() {}
|
||||
|
||||
MOCK_METHOD1(OnSessionRenewalNeeded, void(const CdmSessionId& session_id));
|
||||
MOCK_METHOD3(OnSessionKeysChange, void(const CdmSessionId& session_id,
|
||||
const CdmKeyStatusMap& keys_status,
|
||||
@@ -820,6 +820,36 @@ class TestWvCdmEventListener : public WvCdmEventListener {
|
||||
int64_t new_expiry_time_seconds));
|
||||
};
|
||||
|
||||
class DecryptCallbackTester {
|
||||
public:
|
||||
DecryptCallbackTester(wvcdm::WvContentDecryptionModule* decryptor,
|
||||
SubSampleInfo* sub_sample_info)
|
||||
: decryptor_(decryptor),
|
||||
sub_sample_info_(sub_sample_info) {}
|
||||
|
||||
void Decrypt(const CdmSessionId& session_id,
|
||||
const CdmKeyStatusMap& /* keys_status */,
|
||||
bool /* has_new_usable_key */) {
|
||||
EXPECT_TRUE(decryptor_ != NULL);
|
||||
EXPECT_TRUE(sub_sample_info_ != NULL);
|
||||
|
||||
std::vector<uint8_t> decrypt_buffer(sub_sample_info_->encrypt_data.size());
|
||||
CdmDecryptionParameters decryption_parameters(
|
||||
&sub_sample_info_->key_id, &sub_sample_info_->encrypt_data.front(),
|
||||
sub_sample_info_->encrypt_data.size(), &sub_sample_info_->iv,
|
||||
sub_sample_info_->block_offset, &decrypt_buffer[0]);
|
||||
decryption_parameters.is_encrypted = sub_sample_info_->is_encrypted;
|
||||
decryption_parameters.is_secure = sub_sample_info_->is_secure;
|
||||
EXPECT_EQ(NO_ERROR, decryptor_->Decrypt(session_id,
|
||||
sub_sample_info_->validate_key_id,
|
||||
decryption_parameters));
|
||||
|
||||
}
|
||||
private:
|
||||
wvcdm::WvContentDecryptionModule* decryptor_;
|
||||
SubSampleInfo* sub_sample_info_;
|
||||
};
|
||||
|
||||
class TestWvCdmHlsEventListener : public WvCdmEventListener {
|
||||
public:
|
||||
TestWvCdmHlsEventListener() : WvCdmEventListener() {}
|
||||
@@ -2644,6 +2674,7 @@ TEST_F(WvCdmRequestLicenseTest, QueryStatusL3) {
|
||||
EXPECT_TRUE(ss.eof());
|
||||
EXPECT_LE(10u, api_version);
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, QueryKeyControlInfo) {
|
||||
Unprovision();
|
||||
Provision(kLevelDefault);
|
||||
@@ -3106,6 +3137,33 @@ TEST_F(WvCdmRequestLicenseTest, DecryptionKeyExpiredTest) {
|
||||
decryptor_.CloseSession(session_id_);
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, SessionKeyChangeNotificationTest) {
|
||||
StrictMock<TestWvCdmEventListener> listener;
|
||||
DecryptCallbackTester decrypt_callback(
|
||||
&decryptor_,
|
||||
&single_encrypted_sub_sample_short_expiry);
|
||||
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, &listener,
|
||||
&session_id_);
|
||||
EXPECT_CALL(
|
||||
listener,
|
||||
OnSessionKeysChange(
|
||||
session_id_,
|
||||
AllOf(Each(Pair(_, kKeyStatusUsable)), Not(IsEmpty())), true))
|
||||
.WillOnce(Invoke(&decrypt_callback, &DecryptCallbackTester::Decrypt));
|
||||
;
|
||||
EXPECT_CALL(listener, OnExpirationUpdate(session_id_, _));
|
||||
|
||||
const std::string kCpKeyId = a2bs_hex(
|
||||
"000000347073736800000000" // blob size and pssh
|
||||
"EDEF8BA979D64ACEA3C827DCD51D21ED00000014" // Widevine system id
|
||||
"0801121030313233343536373839616263646566"); // pssh data
|
||||
|
||||
GenerateKeyRequest(kCpKeyId, kLicenseTypeStreaming);
|
||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
|
||||
|
||||
decryptor_.CloseSession(session_id_);
|
||||
}
|
||||
|
||||
class WvCdmDecryptionTest
|
||||
: public WvCdmRequestLicenseTest,
|
||||
public ::testing::WithParamInterface<SubSampleInfo*> {};
|
||||
|
||||
Reference in New Issue
Block a user