Changes from Widevine CDM repo

Squashed commit of these CLs from the widevine cdm repo:

Update YT CP server URI to point to the UAT server
https://widevine-internal-review.googlesource.com/#/c/9327/

OEMCrypto Version 9 API
https://widevine-internal-review.googlesource.com/#/c/9142/

Correct Device ID length in OEMCrypto reference version
https://widevine-internal-review.googlesource.com/#/c/8723/

Modify tests to prevent intermittent failures
https://widevine-internal-review.googlesource.com/#/c/8982/

Generate a unique license request ID
https://widevine-internal-review.googlesource.com/#/c/8721/

Re-enable android timer mechanisms
https://widevine-internal-review.googlesource.com/#/c/8833/

Do not close CDM session on removeKeys
https://widevine-internal-review.googlesource.com/#/c/8703/

And numerous changes required by Eureka, Steel, and CTE versions of
Widevine CDM, as highlighted here:
https://widevine-internal-review.googlesource.com/#/c/8596/
https://widevine-internal-review.googlesource.com/#/c/8955/
https://widevine-internal-review.googlesource.com/#/c/8922/
https://widevine-internal-review.googlesource.com/#/c/8890/
https://widevine-internal-review.googlesource.com/#/c/8871/
https://widevine-internal-review.googlesource.com/#/c/8706/
https://widevine-internal-review.googlesource.com/#/c/8425/

Change-Id: Iafd33905227e74eb2132c240b929d2282ab68042
This commit is contained in:
Fred Gylys-Colwell
2014-03-14 15:00:22 -07:00
parent 7e8bea7d8d
commit dd75655102
45 changed files with 856 additions and 711 deletions

View File

@@ -5,7 +5,6 @@
#include "certificate_provisioning.h"
#include "oemcrypto_adapter.h"
#include "timer.h"
#include "wv_cdm_types.h"
namespace wvcdm {
@@ -18,121 +17,114 @@ class WvCdmEventListener;
typedef std::map<CdmSessionId, CdmSession*> CdmSessionMap;
typedef std::map<CdmKeySetId, CdmSessionId> CdmReleaseKeySetMap;
class CdmEngine : public TimerHandler {
class CdmEngine {
public:
CdmEngine();
virtual ~CdmEngine();
// Session related methods
virtual CdmResponseType OpenSession(
const CdmKeySystem& key_system,
const CdmClientPropertySet* property_set,
CdmSessionId* session_id);
virtual CdmResponseType CloseSession(const CdmSessionId& session_id);
CdmResponseType OpenSession(const CdmKeySystem& key_system,
const CdmClientPropertySet* property_set,
CdmSessionId* session_id);
CdmResponseType CloseSession(const CdmSessionId& session_id);
virtual CdmResponseType OpenKeySetSession(const CdmKeySetId& key_set_id);
virtual CdmResponseType CloseKeySetSession(const CdmKeySetId& key_set_id);
CdmResponseType OpenKeySetSession(const CdmKeySetId& key_set_id);
CdmResponseType CloseKeySetSession(const CdmKeySetId& key_set_id);
// License related methods
// Construct a valid license request
virtual CdmResponseType GenerateKeyRequest(const CdmSessionId& session_id,
const CdmKeySetId& key_set_id,
const CdmInitData& init_data,
const CdmLicenseType license_type,
CdmAppParameterMap& app_parameters,
CdmKeyMessage* key_request,
std::string* server_url);
CdmResponseType GenerateKeyRequest(const CdmSessionId& session_id,
const CdmKeySetId& key_set_id,
const CdmInitData& init_data,
const CdmLicenseType license_type,
CdmAppParameterMap& app_parameters,
CdmKeyMessage* key_request,
std::string* server_url);
// Accept license response and extract key info.
virtual CdmResponseType AddKey(const CdmSessionId& session_id,
const CdmKeyResponse& key_data,
CdmKeySetId* key_set_id);
CdmResponseType AddKey(const CdmSessionId& session_id,
const CdmKeyResponse& key_data,
CdmKeySetId* key_set_id);
virtual CdmResponseType RestoreKey(const CdmSessionId& session_id,
const CdmKeySetId& key_set_id);
CdmResponseType RestoreKey(const CdmSessionId& session_id,
const CdmKeySetId& key_set_id);
CdmResponseType CancelKeyRequest(const CdmSessionId& session_id);
// Construct valid renewal request for the current session keys.
virtual CdmResponseType GenerateRenewalRequest(const CdmSessionId& session_id,
CdmKeyMessage* key_request,
std::string* server_url);
CdmResponseType GenerateRenewalRequest(const CdmSessionId& session_id,
CdmKeyMessage* key_request,
std::string* server_url);
// Accept renewal response and update key info.
virtual CdmResponseType RenewKey(const CdmSessionId& session_id,
const CdmKeyResponse& key_data);
CdmResponseType RenewKey(const CdmSessionId& session_id,
const CdmKeyResponse& key_data);
// Query system information
virtual CdmResponseType QueryStatus(CdmQueryMap* info);
CdmResponseType QueryStatus(CdmQueryMap* info);
// Query session information
virtual CdmResponseType QuerySessionStatus(const CdmSessionId& session_id,
CdmQueryMap* key_info);
// Query license information
virtual CdmResponseType QueryKeyStatus(const CdmSessionId& session_id,
CdmQueryMap* key_info);
CdmResponseType QueryKeyStatus(const CdmSessionId& session_id,
CdmQueryMap* key_info);
// Query seesion control information
virtual CdmResponseType QueryKeyControlInfo(const CdmSessionId& session_id,
CdmQueryMap* key_info);
CdmResponseType QueryKeyControlInfo(const CdmSessionId& session_id,
CdmQueryMap* key_info);
// Provisioning related methods
virtual CdmResponseType GetProvisioningRequest(
CdmProvisioningRequest* request,
std::string* default_url);
CdmResponseType GetProvisioningRequest(CdmProvisioningRequest* request,
std::string* default_url);
virtual CdmResponseType HandleProvisioningResponse(
CdmProvisioningResponse& response);
CdmResponseType HandleProvisioningResponse(CdmProvisioningResponse& response);
// Secure stop related methods
virtual CdmResponseType GetSecureStops(CdmSecureStops* secure_stops);
virtual CdmResponseType ReleaseSecureStops(
CdmResponseType GetSecureStops(CdmSecureStops* secure_stops);
CdmResponseType ReleaseSecureStops(
const CdmSecureStopReleaseMessage& message);
// Decryption and key related methods
// Accept encrypted buffer and return decrypted data.
virtual CdmResponseType Decrypt(const CdmSessionId& session_id,
const CdmDecryptionParameters& parameters);
CdmResponseType Decrypt(const CdmSessionId& session_id,
const CdmDecryptionParameters& parameters);
size_t SessionSize() const { return sessions_.size(); }
// Is the key known to any session?
virtual bool IsKeyValid(const KeyId& key_id);
virtual bool FindSessionForKey(const KeyId& key_id, CdmSessionId* sessionId);
bool IsKeyLoaded(const KeyId& key_id);
bool FindSessionForKey(const KeyId& key_id, CdmSessionId* sessionId);
// Event listener related methods
virtual bool AttachEventListener(const CdmSessionId& session_id,
WvCdmEventListener* listener);
virtual bool DetachEventListener(const CdmSessionId& session_id,
WvCdmEventListener* listener);
bool AttachEventListener(const CdmSessionId& session_id,
WvCdmEventListener* listener);
bool DetachEventListener(const CdmSessionId& session_id,
WvCdmEventListener* listener);
// Parse a blob of multiple concatenated PSSH atoms to extract the first
// widevine pssh
static bool ExtractWidevinePssh(const CdmInitData& init_data,
CdmInitData* output);
// Timer expiration method
void OnTimerEvent();
private:
// private methods
// Cancel all sessions
virtual bool CancelSessions();
virtual bool ValidateKeySystem(const CdmKeySystem& key_system);
bool CancelSessions();
bool ValidateKeySystem(const CdmKeySystem& key_system);
// timer related methods to drive policy decisions
virtual void EnablePolicyTimer();
virtual void DisablePolicyTimer(bool force);
virtual void OnTimerEvent();
virtual void OnKeyReleaseEvent(const CdmKeySetId& key_set_id);
void OnKeyReleaseEvent(const CdmKeySetId& key_set_id);
// instance variables
CdmSessionMap sessions_;
CdmReleaseKeySetMap release_key_sets_;
CertificateProvisioning cert_provisioning_;
SecurityLevel cert_provisioning_requested_security_level_;
// policy timer
Timer policy_timer_;
CORE_DISALLOW_COPY_AND_ASSIGN(CdmEngine);
};

View File

@@ -79,7 +79,7 @@ class CdmSession {
// ReleaseKey() - Accept response and release key.
CdmResponseType ReleaseKey(const CdmKeyResponse& key_response);
bool IsKeyValid(const KeyId& key_id);
bool IsKeyLoaded(const KeyId& key_id);
bool AttachEventListener(WvCdmEventListener* listener);
bool DetachEventListener(WvCdmEventListener* listener);
@@ -119,8 +119,6 @@ class CdmSession {
// license type release and offline related information
CdmKeySetId key_set_id_;
KeyId key_id_;
// Used for certificate based licensing
std::string wrapped_key_;
bool is_certificate_loaded_;

View File

@@ -63,7 +63,6 @@ class CryptoSession {
std::string* wrapped_rsa_key);
// Media data path
bool SelectKey(const std::string& key_id);
CdmResponseType Decrypt(const CdmDecryptionParameters& parameters);
bool GetRandom(size_t data_length, uint8_t* random_data);
@@ -80,6 +79,8 @@ class CryptoSession {
size_t GetOffset(std::string message, std::string field);
bool SetDestinationBufferType();
bool SelectKey(const std::string& key_id);
static const size_t kSignatureSize = 32; // size for HMAC-SHA256 signature
static Lock crypto_lock_;
static bool initialized_;

View File

@@ -59,6 +59,9 @@ class DeviceFiles {
bool RetrieveFile(const char* name, std::string* data);
private:
// Certificate and offline licenses are now stored in security
// level specific directories. In an earlier version they were
// stored in a common directory and need to be copied over.
virtual void SecurityLevelPathBackwardCompatibility();
File* file_;

View File

@@ -12,6 +12,8 @@ namespace wvcdm {
// File class. The implementation is platform dependent.
class File {
public:
class Impl;
// defines as bit flag
enum OpenFlags {
kNoFlags = 0,
@@ -39,7 +41,6 @@ class File {
virtual ssize_t FileSize(const std::string& file_path);
private:
class Impl;
Impl *impl_;
CORE_DISALLOW_COPY_AND_ASSIGN(File);

View File

@@ -27,7 +27,12 @@ class PolicyEngine {
// status is not calculated to avoid overhead in the decryption path.
inline bool can_decrypt() { return can_decrypt_; }
void OnTimerEvent(bool& event_occurred, CdmEventType& event);
// OnTimerEvent is called when a timer fires. It notifies the Policy Engine
// that the timer has fired and that it should check whether any events have
// occurred since the last timer event. If so, it sets event_occurred to true
// and sets event to point to the event that occurred. If not, it sets
// event_occurred to false.
void OnTimerEvent(bool* event_occurred, CdmEventType* event);
// SetLicense is used in handling the initial license response. It stores
// an exact copy of the policy information stored in the license.

View File

@@ -14,7 +14,7 @@
namespace wvcdm {
typedef std::map<CdmSessionId, const CdmClientPropertySet*>
CdmClientPropertySetMap;
CdmClientPropertySetMap;
// This class saves information about features and properties enabled
// for a given platform. At initialization it initializes properties from
@@ -42,9 +42,7 @@ class Properties {
static inline bool use_certificates_as_identification() {
return use_certificates_as_identification_;
}
static inline bool extract_pssh_data() {
return extract_pssh_data_;
}
static inline bool extract_pssh_data() { return extract_pssh_data_; }
static inline bool decrypt_with_empty_session_support() {
return decrypt_with_empty_session_support_;
}
@@ -64,13 +62,12 @@ class Properties {
static bool GetSecurityLevelDirectories(std::vector<std::string>* dirs);
static const std::string GetSecurityLevel(const CdmSessionId& session_id);
static const std::vector<uint8_t> GetServiceCertificate(
const CdmSessionId& session_id);
const CdmSessionId& session_id);
static bool UsePrivacyMode(const CdmSessionId& session_id);
static uint32_t GetSessionSharingId(const CdmSessionId& session_id);
static bool AddSessionPropertySet(
const CdmSessionId& session_id,
const CdmClientPropertySet* property_set);
static bool AddSessionPropertySet(const CdmSessionId& session_id,
const CdmClientPropertySet* property_set);
static bool RemoveSessionPropertySet(const CdmSessionId& session_id);
private:
@@ -94,16 +91,17 @@ class Properties {
static void set_use_certificates_as_identification(bool flag) {
use_certificates_as_identification_ = flag;
}
static void set_extract_pssh_data(bool flag) {
extract_pssh_data_ = flag;
}
static void set_extract_pssh_data(bool flag) { extract_pssh_data_ = flag; }
static void set_decrypt_with_empty_session_support(bool flag) {
decrypt_with_empty_session_support_ = flag;
}
static void set_security_level_path_backward_compatibility_support(bool flag) {
static void set_security_level_path_backward_compatibility_support(
bool flag) {
security_level_path_backward_compatibility_support_ = flag;
}
private:
static bool begin_license_usage_when_received_;
static bool require_explicit_renew_request_;
static bool oem_crypto_use_secure_buffers_;

View File

@@ -11,6 +11,7 @@
namespace wvcdm {
std::vector<uint8_t> a2b_hex(const std::string& b);
std::vector<uint8_t> a2b_hex(const std::string& label, const std::string& b);
std::string a2bs_hex(const std::string& b);
std::string b2a_hex(const std::vector<uint8_t>& b);
std::string b2a_hex(const std::string& b);

View File

@@ -31,6 +31,8 @@ class TimerHandler {
class Timer {
public:
class Impl;
Timer();
~Timer();
@@ -39,7 +41,6 @@ class Timer {
bool IsRunning();
private:
class Impl;
Impl *impl_;
CORE_DISALLOW_COPY_AND_ASSIGN(Timer);

View File

@@ -54,7 +54,7 @@ static const std::string QUERY_VALUE_OFFLINE = "Offline";
static const std::string QUERY_VALUE_SECURITY_LEVEL_L1 = "L1";
static const std::string QUERY_VALUE_SECURITY_LEVEL_L2 = "L2";
static const std::string QUERY_VALUE_SECURITY_LEVEL_L3 = "L3";
static const std::string QUERY_VALUE_SECURITY_LEVEL_Unknown = "Unknown";
static const std::string QUERY_VALUE_SECURITY_LEVEL_UNKNOWN = "Unknown";
} // namespace wvcdm

View File

@@ -8,7 +8,7 @@
namespace wvcdm {
// Listener for events from the Content Decryption Module.
// The caller of the CDM API must provide an implementation for onEvent
// The caller of the CDM API must provide an implementation for OnEvent
// and signal its intent by using the Attach/DetachEventListener methods
// in the WvContentDecryptionModule class.
class WvCdmEventListener {
@@ -16,7 +16,7 @@ class WvCdmEventListener {
WvCdmEventListener() {}
virtual ~WvCdmEventListener() {}
virtual void onEvent(const CdmSessionId& session_id,
virtual void OnEvent(const CdmSessionId& session_id,
CdmEventType cdm_event) = 0;
private:

View File

@@ -28,6 +28,11 @@ typedef std::vector<uint8_t> CdmSecureStopReleaseMessage;
typedef std::string CdmProvisioningRequest;
typedef std::string CdmProvisioningResponse;
// Types for shared host/cdm interface pairs used to shared vendor data.
typedef std::pair<std::string, std::string> kStringPairs;
typedef std::vector<uint8_t> kVectorBytes;
typedef std::pair<std::string, kVectorBytes> kVectorPairs;
enum CdmResponseType {
NO_ERROR,
UNKNOWN_ERROR,

View File

@@ -15,10 +15,6 @@
#include "wv_cdm_constants.h"
#include "wv_cdm_event_listener.h"
namespace {
const int kCdmPolicyTimerDurationSeconds = 1;
}
namespace wvcdm {
CdmEngine::CdmEngine()
@@ -29,7 +25,6 @@ CdmEngine::CdmEngine()
CdmEngine::~CdmEngine() {
CancelSessions();
DisablePolicyTimer(true);
CdmSessionMap::iterator i(sessions_.begin());
for (; i != sessions_.end(); ++i)
delete i->second;
@@ -101,7 +96,6 @@ CdmResponseType CdmEngine::CloseSession(const CdmSessionId& session_id) {
CdmSession* session = iter->second;
sessions_.erase(session_id);
DisablePolicyTimer(false);
delete session;
return NO_ERROR;
}
@@ -248,10 +242,6 @@ CdmResponseType CdmEngine::AddKey(
return sts;
}
if (!license_type_release) {
EnablePolicyTimer();
}
return KEY_ADDED;
}
@@ -286,9 +276,6 @@ CdmResponseType CdmEngine::CancelKeyRequest(const CdmSessionId& session_id) {
//TODO(gmorgan): Issue: what is semantics of canceling a key request. Should
//this call cancel all keys for the session?
// TODO(jfore): We should disable the policy timer here if there are no
// active sessions. Sessions are currently not being destroyed here. We can
// add this logic once the semantics of canceling the key is worked out.
CdmSessionMap::iterator iter = sessions_.find(session_id);
if (iter == sessions_.end()) {
@@ -296,8 +283,8 @@ CdmResponseType CdmEngine::CancelKeyRequest(const CdmSessionId& session_id) {
return KEY_ERROR;
}
// TODO(edwinwong, rfrias): unload keys here
DisablePolicyTimer(false);
// Re-initialize to release crypto session/keys without closing session
iter->second->Init();
return NO_ERROR;
}
@@ -372,7 +359,8 @@ CdmResponseType CdmEngine::QueryStatus(CdmQueryMap* key_info) {
break;
case kSecurityLevelUninitialized:
case kSecurityLevelUnknown:
(*key_info)[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_Unknown;
(*key_info)[QUERY_KEY_SECURITY_LEVEL] =
QUERY_VALUE_SECURITY_LEVEL_UNKNOWN;
break;
default:
return KEY_ERROR;
@@ -504,8 +492,13 @@ CdmResponseType CdmEngine::Decrypt(
}
if (parameters.decrypt_buffer == NULL) {
LOGE("CdmEngine::Decrypt: no dest decrypt buffer");
return KEY_ERROR;
if (!parameters.is_secure &&
!Properties::Properties::oem_crypto_use_fifo()) {
LOGE("CdmEngine::Decrypt: no dest decrypt buffer");
return KEY_ERROR;
} // else we must be level 1 direct and we don't need to return a buffer.
// TODO:(eschacker) look at renaming Properties::oem_crypto_use_fifo()
// to something like Properties::oem_crypto_use_direct_rendering().
}
CdmSessionMap::iterator iter;
@@ -514,7 +507,7 @@ CdmResponseType CdmEngine::Decrypt(
// Loop through the sessions to find the session containing the key_id.
for (iter = sessions_.begin(); iter != sessions_.end(); ++iter) {
if (iter->second->IsKeyValid(*parameters.key_id)) break;
if (iter->second->IsKeyLoaded(*parameters.key_id)) break;
}
} else {
iter = sessions_.find(session_id);
@@ -527,10 +520,10 @@ CdmResponseType CdmEngine::Decrypt(
return iter->second->Decrypt(parameters);
}
bool CdmEngine::IsKeyValid(const KeyId& key_id) {
bool CdmEngine::IsKeyLoaded(const KeyId& key_id) {
for (CdmSessionMap::iterator iter = sessions_.begin();
iter != sessions_.end(); ++iter) {
if (iter->second->IsKeyValid(key_id)) {
if (iter->second->IsKeyLoaded(key_id)) {
return true;
}
}
@@ -545,14 +538,21 @@ bool CdmEngine::FindSessionForKey(
return false;
}
CdmSessionMap::iterator iter = sessions_.find(*session_id);
if (iter != sessions_.end()) {
if (iter->second->IsKeyLoaded(key_id)) {
return true;
}
}
uint32_t session_sharing_id = Properties::GetSessionSharingId(*session_id);
for (CdmSessionMap::iterator iter = sessions_.begin();
iter != sessions_.end(); ++iter) {
CdmSessionId id = iter->second->session_id();
if (Properties::GetSessionSharingId(id) == session_sharing_id) {
if (iter->second->IsKeyValid(key_id)) {
*session_id = id;
for (iter = sessions_.begin(); iter != sessions_.end(); ++iter) {
CdmSessionId local_session_id = iter->second->session_id();
if (Properties::GetSessionSharingId(local_session_id) ==
session_sharing_id) {
if (iter->second->IsKeyLoaded(key_id)) {
*session_id = local_session_id;
return true;
}
}
@@ -684,16 +684,6 @@ bool CdmEngine::ExtractWidevinePssh(
return false;
}
void CdmEngine::EnablePolicyTimer() {
if (!policy_timer_.IsRunning())
policy_timer_.Start(this, kCdmPolicyTimerDurationSeconds);
}
void CdmEngine::DisablePolicyTimer(bool force) {
if ((sessions_.size() == 0 || force) && policy_timer_.IsRunning())
policy_timer_.Stop();
}
void CdmEngine::OnTimerEvent() {
for (CdmSessionMap::iterator iter = sessions_.begin();
iter != sessions_.end(); ++iter) {

View File

@@ -95,7 +95,10 @@ CdmResponseType CdmSession::RestoreOfflineSession(
}
if (Properties::use_certificates_as_identification()) {
if (!crypto_session_->LoadCertificatePrivateKey(wrapped_key_)) {
if (is_certificate_loaded_ ||
crypto_session_->LoadCertificatePrivateKey(wrapped_key_)) {
is_certificate_loaded_ = true;
} else {
return NEED_PROVISIONING;
}
}
@@ -165,8 +168,7 @@ CdmResponseType CdmSession::GenerateKeyRequest(
if (is_certificate_loaded_ ||
crypto_session_->LoadCertificatePrivateKey(wrapped_key_)) {
is_certificate_loaded_ = true;
}
else {
} else {
reinitialize_session_ = true;
return NEED_PROVISIONING;
}
@@ -241,12 +243,12 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response,
CdmResponseType CdmSession::QueryStatus(CdmQueryMap* key_info) {
if (crypto_session_.get() == NULL) {
LOGW("CdmSession::QueryStatus: Invalid crypto session");
LOGE("CdmSession::QueryStatus: Invalid crypto session");
return UNKNOWN_ERROR;
}
if (!crypto_session_->IsOpen()) {
LOGW("CdmSession::QueryStatus: Crypto session not open");
LOGE("CdmSession::QueryStatus: Crypto session not open");
return UNKNOWN_ERROR;
}
@@ -262,7 +264,8 @@ CdmResponseType CdmSession::QueryStatus(CdmQueryMap* key_info) {
break;
case kSecurityLevelUninitialized:
case kSecurityLevelUnknown:
(*key_info)[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_Unknown;
(*key_info)[QUERY_KEY_SECURITY_LEVEL] =
QUERY_VALUE_SECURITY_LEVEL_UNKNOWN;
break;
default:
return KEY_ERROR;
@@ -321,8 +324,10 @@ CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) {
// session keys.
CdmResponseType CdmSession::GenerateRenewalRequest(CdmKeyMessage* key_request,
std::string* server_url) {
if (!license_parser_.PrepareKeyUpdateRequest(true, key_request, server_url))
if (!license_parser_.PrepareKeyUpdateRequest(true, key_request, server_url)) {
LOGE("CdmSession::GenerateRenewalRequest: ERROR on prepare");
return KEY_ERROR;
}
if (license_type_ == kLicenseTypeOffline) {
offline_key_renewal_request_ = *key_request;
@@ -364,7 +369,7 @@ CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) {
return sts;
}
bool CdmSession::IsKeyValid(const KeyId& key_id) {
bool CdmSession::IsKeyLoaded(const KeyId& key_id) {
return license_parser_.IsKeyLoaded(key_id);
}
@@ -428,12 +433,12 @@ void CdmSession::OnTimerEvent() {
bool event_occurred = false;
CdmEventType event;
policy_engine_.OnTimerEvent(event_occurred, event);
policy_engine_.OnTimerEvent(&event_occurred, &event);
if (event_occurred) {
for (CdmEventListenerIter iter = listeners_.begin();
iter != listeners_.end(); ++iter) {
(*iter)->onEvent(session_id_, event);
(*iter)->OnEvent(session_id_, event);
}
}
}
@@ -442,7 +447,7 @@ void CdmSession::OnKeyReleaseEvent(const CdmKeySetId& key_set_id) {
if (key_set_id_ == key_set_id) {
for (CdmEventListenerIter iter = listeners_.begin();
iter != listeners_.end(); ++iter) {
(*iter)->onEvent(session_id_, LICENSE_EXPIRED_EVENT);
(*iter)->OnEvent(session_id_, LICENSE_EXPIRED_EVENT);
}
}
}

View File

@@ -176,11 +176,20 @@ CdmResponseType CertificateProvisioning::HandleProvisioningResponse(
return UNKNOWN_ERROR;
}
if (!signed_response.has_signature() || !signed_response.has_message()) {
LOGE("HandleProvisioningResponse: signature or message not found");
return UNKNOWN_ERROR;
bool error = false;
if (!signed_response.has_signature()) {
LOGE("HandleProvisioningResponse: signature not found");
error = true;
}
if (!signed_response.has_message()) {
LOGE("HandleProvisioningResponse: message not found");
error = true;
}
if (error)
return UNKNOWN_ERROR;
const std::string& signed_message = signed_response.message();
ProvisioningResponse provisioning_response;

View File

@@ -155,10 +155,7 @@ bool CryptoSession::GetDeviceUniqueId(std::string* device_id) {
return false;
}
id.resize(id_length + 1);
id[id_length] = '\0';
*device_id = reinterpret_cast<const char*>(&id[0]);
device_id->assign(reinterpret_cast<char *>(&id[0]), id_length);
return true;
}
@@ -358,6 +355,8 @@ CdmResponseType CryptoSession::LoadKeys(const std::string& message,
if (mac_key.size() >= MAC_KEY_SIZE && mac_key_iv.size() >= KEY_IV_SIZE) {
enc_mac_key = msg + GetOffset(message, mac_key);
enc_mac_key_iv = msg + GetOffset(message, mac_key_iv);
} else {
LOGV("CryptoSession::LoadKeys: enc_mac_key not set");
}
std::vector<OEMCrypto_KeyObject> load_key_array(num_keys);
for (int i = 0; i < num_keys; ++i) {
@@ -394,7 +393,7 @@ CdmResponseType CryptoSession::LoadKeys(const std::string& message,
}
bool CryptoSession::LoadCertificatePrivateKey(std::string& wrapped_key) {
LOGV("CryptoSession::LoadKeys: Lock");
LOGV("CryptoSession::LoadCertificatePrivateKey: Lock");
AutoLock auto_lock(crypto_lock_);
LOGV("LoadDeviceRSAKey: id=%ld", (uint32_t)oec_session_id_);
@@ -566,7 +565,7 @@ CdmResponseType CryptoSession::Decrypt(const CdmDecryptionParameters& params) {
AutoLock auto_lock(crypto_lock_);
// Check if key needs to be selected
if (params.is_encrypted) {
if (key_id_.compare(*params.key_id) != 0) {
if (key_id_ != *params.key_id) {
if (SelectKey(*params.key_id)) {
key_id_ = *params.key_id;
} else {
@@ -604,7 +603,7 @@ CdmResponseType CryptoSession::Decrypt(const CdmDecryptionParameters& params) {
switch (sts) {
case OEMCrypto_SUCCESS:
break;
return NO_ERROR;
case OEMCrypto_ERROR_INSUFFICIENT_RESOURCES:
return INSUFFICIENT_CRYPTO_RESOURCES;
case OEMCrypto_ERROR_KEY_EXPIRED:
@@ -612,7 +611,6 @@ CdmResponseType CryptoSession::Decrypt(const CdmDecryptionParameters& params) {
default:
return UNKNOWN_ERROR;
}
return NO_ERROR;
}
bool CryptoSession::GenerateNonce(uint32_t* nonce) {

View File

@@ -22,8 +22,11 @@ namespace {
const char kCertificateFileName[] = "cert.bin";
const char kLicenseFileNameExt[] = ".lic";
const char kWildcard[] = "*";
const char kPathDelimiter[] = "/";
const char *kSecurityLevelPathCompatibilityExclusionList[] = { "ay64.dat" };
const char kDirectoryDelimiter = '/';
const char* kSecurityLevelPathCompatibilityExclusionList[] = {"ay64.dat"};
size_t kSecurityLevelPathCompatibilityExclusionListSize =
sizeof(kSecurityLevelPathCompatibilityExclusionList) /
sizeof(*kSecurityLevelPathCompatibilityExclusionList);
} // namespace
namespace wvcdm {
@@ -436,7 +439,6 @@ bool DeviceFiles::RetrieveFile(const char* name, std::string* data) {
}
if (!file_->Open(path, File::kReadOnly | File::kBinary)) {
LOGW("DeviceFiles::RetrieveFile: File open failed: %s", path.c_str());
return false;
}
@@ -457,27 +459,33 @@ bool DeviceFiles::RetrieveFile(const char* name, std::string* data) {
void DeviceFiles::SecurityLevelPathBackwardCompatibility() {
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
LOGW("DeviceFiles::SecurityLevelPathBackwardCompatibility: Unable to "
LOGW(
"DeviceFiles::SecurityLevelPathBackwardCompatibility: Unable to "
"get base path");
return;
}
std::vector<std::string> security_dirs;
if (!Properties::GetSecurityLevelDirectories(&security_dirs)) {
LOGW("DeviceFiles::SecurityLevelPathBackwardCompatibility: Unable to "
LOGW(
"DeviceFiles::SecurityLevelPathBackwardCompatibility: Unable to "
"get security directories");
return;
}
size_t pos = std::string::npos;
for (size_t i = 0; i < security_dirs.size(); ++i) {
pos = path.rfind(security_dirs[i]);
if (std::string::npos != pos)
pos = path.find(security_dirs[i]);
if (pos != std::string::npos && pos > 0 &&
pos == path.size() - security_dirs[i].size() &&
path[pos - 1] == kDirectoryDelimiter) {
break;
}
}
if (pos == std::string::npos) {
LOGV("DeviceFiles::SecurityLevelPathBackwardCompatibility: Security level "
LOGV(
"DeviceFiles::SecurityLevelPathBackwardCompatibility: Security level "
"specific path not found. Check properties?");
return;
}
@@ -485,16 +493,16 @@ void DeviceFiles::SecurityLevelPathBackwardCompatibility() {
std::string from_dir(path, 0, pos);
std::vector<std::string> files;
file_->List(from_dir, &files);
if (!file_->List(from_dir, &files)) {
return;
}
for (size_t i = 0; i < files.size(); ++i) {
std::string from = from_dir + files[i];
bool exclude = false;
for (size_t j = 0;
j < sizeof(kSecurityLevelPathCompatibilityExclusionList) /
sizeof(const char*);
j++) {
if (files[i].compare(kSecurityLevelPathCompatibilityExclusionList[j]) == 0) {
for (size_t j = 0; j < kSecurityLevelPathCompatibilityExclusionListSize;
++j) {
if (files[i] == kSecurityLevelPathCompatibilityExclusionList[j]) {
exclude = true;
break;
}
@@ -504,8 +512,7 @@ void DeviceFiles::SecurityLevelPathBackwardCompatibility() {
for (size_t j = 0; j < security_dirs.size(); ++j) {
std::string to_dir = from_dir + security_dirs[j];
if (!file_->Exists(to_dir))
file_->CreateDirectory(to_dir);
if (!file_->Exists(to_dir)) file_->CreateDirectory(to_dir);
std::string to = to_dir + files[i];
file_->Copy(from, to);
}

View File

@@ -90,7 +90,7 @@ typedef OEMCryptoResult (*L1_GenerateRSASignature_t)(OEMCrypto_SESSION session,
size_t message_length,
uint8_t* signature,
size_t* signature_length,
RSA_Padding_Scheme algorithm);
RSA_Padding_Scheme padding_scheme);
typedef OEMCryptoResult (*L1_DeriveKeysFromSessionKey_t)(
OEMCrypto_SESSION session, const uint8_t* enc_session_key,
size_t enc_session_key_length, const uint8_t* mac_key_context,
@@ -318,7 +318,7 @@ class Adapter {
}
LevelSession get(OEMCrypto_SESSION session) {
AutoLock auto_lock(lookup_lock_);
AutoLock auto_lock(session_map_lock_);
map_iterator pair = session_map_.find(session);
if (pair == session_map_.end()) {
return LevelSession();
@@ -327,7 +327,6 @@ class Adapter {
}
OEMCryptoResult OpenSession(OEMCrypto_SESSION* session, SecurityLevel level) {
AutoLock auto_lock(lookup_lock_);
LevelSession new_session;
OEMCryptoResult result;
if (level == kLevelDefault && level1_valid_) {
@@ -340,6 +339,7 @@ class Adapter {
*session = new_session.session + kLevel3Offset;
}
if (result == OEMCrypto_SUCCESS) {
AutoLock auto_lock(session_map_lock_);
// Make sure session is not already in my list of sessions.
while (session_map_.find(*session) != session_map_.end()) {
(*session)++;
@@ -350,7 +350,7 @@ class Adapter {
}
OEMCryptoResult CloseSession(OEMCrypto_SESSION session) {
AutoLock auto_lock(lookup_lock_);
AutoLock auto_lock(session_map_lock_);
map_iterator pair = session_map_.find(session);
if (pair == session_map_.end()) {
return OEMCrypto_ERROR_INVALID_SESSION;
@@ -367,7 +367,7 @@ class Adapter {
struct FunctionPointers level1_;
struct FunctionPointers level3_;
std::map<OEMCrypto_SESSION, LevelSession> session_map_;
Lock lookup_lock_;
Lock session_map_lock_;
// This is just for debugging the map between session ids.
// If we add this to the level 3 session id, then the external session
// id will match the internal session id in the last two digits.
@@ -583,12 +583,13 @@ extern "C" OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(
extern "C" OEMCryptoResult OEMCrypto_GenerateRSASignature(
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
uint8_t* signature, size_t* signature_length, RSA_Padding_Scheme algorithm) {
uint8_t* signature, size_t* signature_length, RSA_Padding_Scheme padding_scheme) {
if (!kAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
LevelSession pair = kAdapter->get(session);
if (!pair.fcn) return OEMCrypto_ERROR_INVALID_SESSION;
return pair.fcn->GenerateRSASignature(pair.session, message, message_length,
signature, signature_length, algorithm);
signature, signature_length,
padding_scheme);
}
extern "C" OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(

View File

@@ -40,8 +40,8 @@ void PolicyEngine::Init(Clock* clock) {
clock_ = clock;
}
void PolicyEngine::OnTimerEvent(bool& event_occured, CdmEventType& event) {
event_occured = false;
void PolicyEngine::OnTimerEvent(bool* event_occurred, CdmEventType* event) {
*event_occurred = false;
int64_t current_time = clock_->GetCurrentTime();
// License expiration trumps all.
@@ -50,8 +50,8 @@ void PolicyEngine::OnTimerEvent(bool& event_occured, CdmEventType& event) {
license_state_ != kLicenseStateExpired) {
license_state_ = kLicenseStateExpired;
can_decrypt_ = false;
event = LICENSE_EXPIRED_EVENT;
event_occured = true;
*event = LICENSE_EXPIRED_EVENT;
*event_occurred = true;
return;
}
@@ -91,8 +91,8 @@ void PolicyEngine::OnTimerEvent(bool& event_occured, CdmEventType& event) {
if (renewal_needed) {
UpdateRenewalRequest(current_time);
event = LICENSE_RENEWAL_NEEDED_EVENT;
event_occured = true;
*event = LICENSE_RENEWAL_NEEDED_EVENT;
*event_occurred = true;
}
}
@@ -109,6 +109,10 @@ void PolicyEngine::UpdateLicense(
if (!license.has_policy())
return;
if (kLicenseStateExpired == license_state_) {
LOGD("PolicyEngine::UpdateLicense: updating an expired license");
}
policy_.MergeFrom(license.policy());
if (!policy_.can_play()) {

View File

@@ -5,7 +5,7 @@
#include "wv_cdm_constants.h"
namespace {
const char *kSecurityLevelDirs[] = { "L1/", "L3/" };
const char* kSecurityLevelDirs[] = {"L1/", "L3/"};
} // namespace
namespace wvcdm {
@@ -30,20 +30,20 @@ void Properties::Init() {
kPropertyUseCertificatesAsIdentification;
extract_pssh_data_ = kExtractPsshData;
decrypt_with_empty_session_support_ = kDecryptWithEmptySessionSupport;
security_level_path_backward_compatibility_support_ = kSecurityLevelPathBackwardCompatibilitySupport;
security_level_path_backward_compatibility_support_ =
kSecurityLevelPathBackwardCompatibilitySupport;
session_property_set_.reset(new CdmClientPropertySetMap());
}
bool Properties::AddSessionPropertySet(
const CdmSessionId& session_id,
const CdmClientPropertySet* property_set) {
const CdmSessionId& session_id, const CdmClientPropertySet* property_set) {
if (NULL == session_property_set_.get()) {
return false;
}
std::pair<CdmClientPropertySetMap::iterator, bool> result =
session_property_set_->insert(
std::pair<const CdmSessionId,
const CdmClientPropertySet*>(session_id, property_set));
session_property_set_->insert(
std::pair<const CdmSessionId, const CdmClientPropertySet*>(
session_id, property_set));
return result.second;
}
@@ -55,7 +55,7 @@ bool Properties::RemoveSessionPropertySet(const CdmSessionId& session_id) {
}
const CdmClientPropertySet* Properties::GetCdmClientPropertySet(
const CdmSessionId& session_id) {
const CdmSessionId& session_id) {
if (NULL != session_property_set_.get()) {
CdmClientPropertySetMap::const_iterator it =
session_property_set_->find(session_id);
@@ -112,7 +112,7 @@ uint32_t Properties::GetSessionSharingId(const CdmSessionId& session_id) {
}
bool Properties::GetSecurityLevelDirectories(std::vector<std::string>* dirs) {
dirs->resize(sizeof(kSecurityLevelDirs)/sizeof(const char*));
dirs->resize(sizeof(kSecurityLevelDirs) / sizeof(const char*));
for (size_t i = 0; i < dirs->size(); ++i) {
(*dirs)[i] = kSecurityLevelDirs[i];
}

View File

@@ -50,6 +50,16 @@ std::vector<uint8_t> a2b_hex(const std::string& byte) {
return array;
}
// converts an ascii hex string(2 bytes per digit) into a decimal byte string
// dump the string with the label.
std::vector<uint8_t> a2b_hex(const std::string& label, const std::string& byte) {
std::cout << std::endl << "[[DUMP: " << label << " ]= \"" << byte << "\"]"
<< std::endl << std::endl;
return a2b_hex(byte);
}
std::string a2bs_hex(const std::string& byte) {
std::vector<uint8_t> array = a2b_hex(byte);
return std::string(array.begin(), array.end());
@@ -141,7 +151,7 @@ std::string IntToString(int value) {
memset(buffer, 0, kOutputBufSize);
snprintf(buffer, kOutputBufSize, "%d", value);
std::string out_string(buffer, sizeof(buffer));
std::string out_string(buffer);
return out_string;
}
@@ -153,7 +163,7 @@ std::string UintToString(unsigned int value) {
memset(buffer, 0, kOutputBufSize);
snprintf(buffer, kOutputBufSize, "%u", value);
std::string out_string(buffer, sizeof(buffer));
std::string out_string(buffer);
return out_string;
}

View File

@@ -5,7 +5,7 @@
#if defined(CHROMIUM_BUILD)
#include "base/at_exit.h"
#include "base/message_loop.h"
#include "base/message_loop/message_loop.h"
#endif
#include "cdm_engine.h"
#include "config_test_env.h"
@@ -19,7 +19,9 @@
#include "wv_cdm_types.h"
namespace {
// Http OK response code.
const int kHttpOk = 200;
// Default license server, can be configured using --server command line option
// Default key id (pssh), can be configured using --keyid command line option
std::string g_client_auth;
@@ -88,12 +90,11 @@ namespace wvcdm {
class WvCdmEngineTest : public testing::Test {
public:
virtual void SetUp() {
cdm_engine_.reset(new CdmEngine());
cdm_engine_->OpenSession(g_key_system, NULL, &session_id_);
cdm_engine_.OpenSession(g_key_system, NULL, &session_id_);
}
virtual void TearDown() {
cdm_engine_->CloseSession(session_id_);
cdm_engine_.CloseSession(session_id_);
}
protected:
@@ -110,21 +111,21 @@ class WvCdmEngineTest : public testing::Test {
}
EXPECT_EQ(KEY_MESSAGE,
cdm_engine_->GenerateKeyRequest(session_id_,
key_set_id,
init_data,
kLicenseTypeStreaming,
app_parameters,
&key_msg_,
&server_url));
cdm_engine_.GenerateKeyRequest(session_id_,
key_set_id,
init_data,
kLicenseTypeStreaming,
app_parameters,
&key_msg_,
&server_url));
}
void GenerateRenewalRequest(const std::string& key_system,
const std::string& init_data) {
EXPECT_EQ(KEY_MESSAGE,
cdm_engine_->GenerateRenewalRequest(session_id_,
&key_msg_,
&server_url_));
cdm_engine_.GenerateRenewalRequest(session_id_,
&key_msg_,
&server_url_));
}
// posts a request and extracts the drm message from the response
@@ -164,18 +165,18 @@ class WvCdmEngineTest : public testing::Test {
std::string resp = GetKeyRequestResponse(server_url,
client_auth);
CdmKeySetId key_set_id;
EXPECT_EQ(cdm_engine_->AddKey(session_id_, resp, &key_set_id), KEY_ADDED);
EXPECT_EQ(cdm_engine_.AddKey(session_id_, resp, &key_set_id), KEY_ADDED);
}
void VerifyRenewalKeyResponse(const std::string& server_url,
const std::string& client_auth,
std::string& init_data){
std::string& init_data) {
std::string resp = GetKeyRequestResponse(server_url,
client_auth);
EXPECT_EQ(cdm_engine_->RenewKey(session_id_, resp), wvcdm::KEY_ADDED);
EXPECT_EQ(cdm_engine_.RenewKey(session_id_, resp), wvcdm::KEY_ADDED);
}
scoped_ptr<CdmEngine> cdm_engine_;
CdmEngine cdm_engine_;
std::string key_msg_;
std::string session_id_;
std::string server_url_;
@@ -198,7 +199,10 @@ TEST_F(WvCdmEngineTest, BaseMessageTest) {
TEST_F(WvCdmEngineTest, WrongMessageTest) {
std::string wrong_message = a2bs_hex(g_wrong_key_id);
GenerateKeyRequest(g_key_system, wrong_message);
GetKeyRequestResponse(g_license_server, g_client_auth);
// We should receive a response with no license, i.e. the extracted license
// response message should be empty.
ASSERT_EQ("", GetKeyRequestResponse(g_license_server, g_client_auth));
}
TEST_F(WvCdmEngineTest, NormalDecryption) {
@@ -313,7 +317,7 @@ int main(int argc, char **argv) {
#if defined(CHROMIUM_BUILD)
base::AtExitManager exit;
MessageLoop ttr(MessageLoop::TYPE_IO);
base::MessageLoop ttr(base::MessageLoop::TYPE_IO);
#endif
return RUN_ALL_TESTS();
}

View File

@@ -5,7 +5,7 @@
namespace {
// Youtube Content Protection license server data
const std::string kYtCpLicenseServer =
"http://kir03wwwg185.widevine.net/drm";
"http://wv-ref-eme-player.appspot.com/proxy";
const std::string kYtCpClientAuth = "";
const std::string kYtCpKeyId =
"000000347073736800000000" // blob size and pssh

View File

@@ -26,6 +26,7 @@ using ::testing::StrEq;
namespace {
const uint32_t kCertificateLen = 700;
const uint32_t kWrappedKeyLen = 500;
const uint32_t kProtobufEstimatedLen = 75;
const std::string kTestCertificate =
"124B035F3D256A656F0E505A085E7A6C482B61035E0C4A540F7803137F4C3B45206B7F33"
"347F4D7A005E56400F0955011F4E07072D0D46781817460974326A516E3944385760280E"
@@ -209,7 +210,7 @@ LicenseInfo license_test_data[] = {
"0112001A16200342120A106B63746C0000000000ECDCBE0000000020DBDF"
"A68F051A20182F029E35047A3841FA176C74E5B387350E8D58DEA6878FF0"
"BEA6CABACA1C2C"),
"https://jmt17.google.com/video/license/GetCencLicense",
"https://jmt17.google.com/video-dev/license/GetCencLicense",
wvcdm::a2bs_hex(
"0AAF150802100122A8150801121408011210303132333435363738394142"
"434445461A9D0E080112950C0AD70B080112EF090AB002080212103E560E"
@@ -1038,7 +1039,7 @@ MATCHER_P(IsStrEq, str, "") {
MATCHER_P2(Contains, str1, str2, "") {
// Estimating the length of data. We can have gmock provide length
// as well as pointer to data but that will introduce a dependency on tr1
std::string data(arg, str1.size() + str2.size() + 75);
std::string data(arg, str1.size() + str2.size() + kProtobufEstimatedLen);
return (data.find(str1) != std::string::npos &&
data.find(str2) != std::string::npos);
}
@@ -1046,7 +1047,7 @@ MATCHER_P6(Contains, str1, str2, str3, str4, str5, str6, "") {
// Estimating the length of data. We can have gmock provide length
// as well as pointer to data but that will introduce a dependency on tr1
std::string data(arg, str1.size() + str2.size() + str3.size() + str4.size() +
str5.size() + str6.size() + 75);
str5.size() + str6.size() + kProtobufEstimatedLen);
return (data.find(str1) != std::string::npos &&
data.find(str2) != std::string::npos &&
data.find(str3) != std::string::npos &&

View File

@@ -7,7 +7,7 @@
#include "test_vectors.h"
namespace {
const std::string kTestDirName = "test";
const std::string kTestDirName = "test_dir";
const std::string kTestFileName = "test.txt";
const std::string kTestFileName2 = "test2.txt";
const std::string kTestFileNameExt = ".txt";
@@ -210,7 +210,7 @@ TEST_F(FileTest, CopyFile) {
EXPECT_TRUE(wr_file.Open(path, File::kCreate | File::kBinary));
EXPECT_TRUE(wr_file.Write(write_data.data(), write_data.size()));
wr_file.Close();
EXPECT_TRUE(file.Exists(path));
ASSERT_TRUE(file.Exists(path));
std::string path_copy = test_vectors::kTestDir + kTestFileName2;
EXPECT_FALSE(file.Exists(path_copy));
@@ -257,9 +257,9 @@ TEST_F(FileTest, ListFiles) {
EXPECT_EQ(3u, files.size());
for (size_t i = 0; i < files.size(); ++i) {
EXPECT_TRUE(files[i].compare(kTestDirName) == 0 ||
files[i].compare(kTestFileName) == 0 ||
files[i].compare(kTestFileName2) == 0);
EXPECT_TRUE(files[i] == kTestDirName ||
files[i] == kTestFileName ||
files[i] == kTestFileName2);
}
}

View File

@@ -57,7 +57,7 @@ class PolicyEngineTest : public ::testing::Test {
policy->set_renewal_recovery_duration_seconds(license_duration_ -
license_renewal_delay_); // 10 minutes
policy->set_renewal_server_url(
"https://jmt17.google.com/video/license/GetCencLicense");
"https://jmt17.google.com/video-dev/license/GetCencLicense");
policy->set_renewal_delay_seconds(license_renewal_delay_);
policy->set_renewal_retry_interval_seconds(
license_renewal_retry_interval_);
@@ -97,7 +97,7 @@ TEST_F(PolicyEngineTest, PlaybackSuccess) {
bool event_occurred;
CdmEventType event;
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->BeginDecryption();
@@ -115,7 +115,7 @@ TEST_F(PolicyEngineTest, PlaybackFailed_CanPlayFalse) {
bool event_occurred;
CdmEventType event;
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->BeginDecryption();
@@ -141,10 +141,10 @@ TEST_F(PolicyEngineTest, PlaybackFails_RentalDurationExpired) {
bool event_occurred;
CdmEventType event;
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_EXPIRED_EVENT, event);
@@ -171,10 +171,10 @@ TEST_F(PolicyEngineTest, PlaybackFails_PlaybackDurationExpired) {
bool event_occurred;
CdmEventType event;
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_EXPIRED_EVENT, event);
@@ -198,10 +198,10 @@ TEST_F(PolicyEngineTest, PlaybackFails_LicenseDurationExpired) {
bool event_occurred;
CdmEventType event;
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_EXPIRED_EVENT, event);
@@ -226,10 +226,10 @@ TEST_F(PolicyEngineTest, PlaybackOk_RentalDuration0) {
bool event_occurred;
CdmEventType event;
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_EXPIRED_EVENT, event);
@@ -254,10 +254,10 @@ TEST_F(PolicyEngineTest, PlaybackOk_PlaybackDuration0) {
bool event_occurred;
CdmEventType event;
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_EXPIRED_EVENT, event);
@@ -282,10 +282,10 @@ TEST_F(PolicyEngineTest, PlaybackOk_LicenseDuration0) {
bool event_occurred;
CdmEventType event;
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_EXPIRED_EVENT, event);
@@ -312,10 +312,10 @@ TEST_F(PolicyEngineTest, PlaybackOk_Durations0) {
bool event_occurred;
CdmEventType event;
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
EXPECT_TRUE(policy_engine_->can_decrypt());
@@ -343,13 +343,13 @@ TEST_F(PolicyEngineTest, PlaybackFailed_CanRenewFalse) {
bool event_occurred;
CdmEventType event;
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_EXPIRED_EVENT, event);
@@ -374,10 +374,10 @@ TEST_F(PolicyEngineTest, PlaybackOk_RenewSuccess) {
bool event_occurred;
CdmEventType event;
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_RENEWAL_NEEDED_EVENT, event);
@@ -389,7 +389,7 @@ TEST_F(PolicyEngineTest, PlaybackOk_RenewSuccess) {
id->set_version(2);
policy_engine_->UpdateLicense(license_);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
EXPECT_TRUE(policy_engine_->can_decrypt());
@@ -412,10 +412,10 @@ TEST_F(PolicyEngineTest, PlaybackFailed_RenewFailedVersionNotUpdated) {
bool event_occurred;
CdmEventType event;
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_RENEWAL_NEEDED_EVENT, event);
@@ -425,13 +425,13 @@ TEST_F(PolicyEngineTest, PlaybackFailed_RenewFailedVersionNotUpdated) {
license_renewal_delay_ + 15);
policy_engine_->UpdateLicense(license_);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_RENEWAL_NEEDED_EVENT, event);
EXPECT_TRUE(policy_engine_->can_decrypt());
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_EXPIRED_EVENT, event);
@@ -459,37 +459,37 @@ TEST_F(PolicyEngineTest, PlaybackFailed_RepeatedRenewFailures) {
bool event_occurred;
CdmEventType event;
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_RENEWAL_NEEDED_EVENT, event);
EXPECT_TRUE(policy_engine_->can_decrypt());
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_RENEWAL_NEEDED_EVENT, event);
EXPECT_TRUE(policy_engine_->can_decrypt());
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_RENEWAL_NEEDED_EVENT, event);
EXPECT_TRUE(policy_engine_->can_decrypt());
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_EXPIRED_EVENT, event);
@@ -519,37 +519,37 @@ TEST_F(PolicyEngineTest, PlaybackOk_RenewSuccessAfterExpiry) {
bool event_occurred;
CdmEventType event;
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_RENEWAL_NEEDED_EVENT, event);
EXPECT_TRUE(policy_engine_->can_decrypt());
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_RENEWAL_NEEDED_EVENT, event);
EXPECT_TRUE(policy_engine_->can_decrypt());
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_RENEWAL_NEEDED_EVENT, event);
EXPECT_TRUE(policy_engine_->can_decrypt());
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_EXPIRED_EVENT, event);
@@ -566,7 +566,7 @@ TEST_F(PolicyEngineTest, PlaybackOk_RenewSuccessAfterExpiry) {
policy_engine_->UpdateLicense(license_);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
EXPECT_TRUE(policy_engine_->can_decrypt());
@@ -593,25 +593,25 @@ TEST_F(PolicyEngineTest, PlaybackOk_RenewSuccessAfterFailures) {
bool event_occurred;
CdmEventType event;
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_RENEWAL_NEEDED_EVENT, event);
EXPECT_TRUE(policy_engine_->can_decrypt());
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_RENEWAL_NEEDED_EVENT, event);
EXPECT_TRUE(policy_engine_->can_decrypt());
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
license_.set_license_start_time(license_start_time_ +
@@ -620,12 +620,12 @@ TEST_F(PolicyEngineTest, PlaybackOk_RenewSuccessAfterFailures) {
id->set_version(2);
policy_engine_->UpdateLicense(license_);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
EXPECT_TRUE(policy_engine_->can_decrypt());
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
EXPECT_TRUE(policy_engine_->can_decrypt());
@@ -647,13 +647,13 @@ TEST_F(PolicyEngineTest, PlaybackOk_RenewedWithUsage) {
bool event_occurred;
CdmEventType event;
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->BeginDecryption();
EXPECT_FALSE(policy_engine_->can_decrypt());
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_TRUE(event_occurred);
EXPECT_EQ(LICENSE_RENEWAL_NEEDED_EVENT, event);
@@ -663,7 +663,7 @@ TEST_F(PolicyEngineTest, PlaybackOk_RenewedWithUsage) {
id->set_version(2);
policy_engine_->UpdateLicense(license_);
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
EXPECT_TRUE(policy_engine_->can_decrypt());
@@ -723,7 +723,7 @@ TEST_F(PolicyEngineTest, QuerySuccess_Offline) {
bool event_occurred;
CdmEventType event;
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->BeginDecryption();
@@ -765,7 +765,7 @@ TEST_F(PolicyEngineTest, QuerySuccess_DurationExpired) {
bool event_occurred;
CdmEventType event;
policy_engine_->OnTimerEvent(event_occurred, event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
EXPECT_FALSE(event_occurred);
policy_engine_->BeginDecryption();

View File

@@ -114,12 +114,14 @@ int UrlRequest::GetResponse(std::string* message) {
bytes = socket_.Read(buffer_, kHttpBufferSize, kTimeoutInMs);
if (bytes > 0) {
response.append(buffer_, bytes);
attempts = kSingleReadAttempt;
if (bytes < static_cast<int>(kHttpBufferSize)) {
attempts = kSingleReadAttempt;
}
} else {
if (bytes < 0) LOGE("read error = ", errno);
// bytes == 0 indicates nothing to read
}
};
}
ConcatenateChunkedResponse(response, message);
LOGD("HTTP response: (%d): %s", message->size(), b2a_hex(*message).c_str());