Source release v2.1.4-0-804 + third_party libs
Change-Id: I1db8582efba613fa8a2b91a9c2697c5dfb2a8abf
This commit is contained in:
@@ -3,15 +3,16 @@
|
||||
#ifndef WVCDM_CORE_CDM_ENGINE_H_
|
||||
#define WVCDM_CORE_CDM_ENGINE_H_
|
||||
|
||||
#include "cdm_session.h"
|
||||
#include "certificate_provisioning.h"
|
||||
#include "initialization_data.h"
|
||||
#include "oemcrypto_adapter.h"
|
||||
#include "scoped_ptr.h"
|
||||
#include "wv_cdm_types.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
class CdmClientPropertySet;
|
||||
class CdmSession;
|
||||
class CryptoEngine;
|
||||
class WvCdmEventListener;
|
||||
|
||||
@@ -121,8 +122,11 @@ class CdmEngine {
|
||||
CdmReleaseKeySetMap release_key_sets_;
|
||||
CertificateProvisioning cert_provisioning_;
|
||||
SecurityLevel cert_provisioning_requested_security_level_;
|
||||
CdmSession* usage_session_;
|
||||
|
||||
static bool seeded_;
|
||||
|
||||
// usage related variables
|
||||
scoped_ptr<CdmSession> usage_session_;
|
||||
int64_t last_usage_information_update_time;
|
||||
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(CdmEngine);
|
||||
|
||||
@@ -31,11 +31,6 @@ class CdmSession {
|
||||
virtual CdmResponseType RestoreUsageSession(
|
||||
const CdmKeyMessage& key_request, const CdmKeyResponse& key_response);
|
||||
|
||||
virtual void set_key_system(const CdmKeySystem& ksystem) {
|
||||
key_system_ = ksystem;
|
||||
}
|
||||
virtual const CdmKeySystem& key_system() { return key_system_; }
|
||||
|
||||
virtual const CdmSessionId& session_id() { return session_id_; }
|
||||
|
||||
virtual CdmResponseType GenerateKeyRequest(
|
||||
@@ -99,6 +94,11 @@ class CdmSession {
|
||||
}
|
||||
|
||||
private:
|
||||
// Internal constructor
|
||||
void Create(CdmLicense* license_parser, CryptoSession* crypto_session,
|
||||
PolicyEngine* policy_engine, DeviceFiles* file_handle,
|
||||
const CdmClientPropertySet* cdm_client_property_set);
|
||||
|
||||
// Generate unique ID for each new session.
|
||||
CdmSessionId GenerateSessionId();
|
||||
bool GenerateKeySetId(CdmKeySetId* key_set_id);
|
||||
@@ -108,17 +108,18 @@ class CdmSession {
|
||||
bool DeleteLicense();
|
||||
|
||||
// instance variables
|
||||
const CdmSessionId session_id_;
|
||||
CdmKeySystem key_system_;
|
||||
CdmLicense license_parser_;
|
||||
bool initialized_;
|
||||
CdmSessionId session_id_;
|
||||
scoped_ptr<CdmLicense> license_parser_;
|
||||
scoped_ptr<CryptoSession> crypto_session_;
|
||||
PolicyEngine policy_engine_;
|
||||
scoped_ptr<PolicyEngine> policy_engine_;
|
||||
scoped_ptr<DeviceFiles> file_handle_;
|
||||
bool license_received_;
|
||||
bool reinitialize_session_;
|
||||
bool is_offline_;
|
||||
bool is_release_;
|
||||
bool is_usage_update_needed_;
|
||||
bool is_initial_decryption_;
|
||||
CdmSecurityLevel security_level_;
|
||||
|
||||
// information useful for offline and usage scenarios
|
||||
CdmKeyMessage key_request_;
|
||||
@@ -133,12 +134,18 @@ class CdmSession {
|
||||
// license type release and offline related information
|
||||
CdmKeySetId key_set_id_;
|
||||
|
||||
// Used for certificate based licensing
|
||||
std::string wrapped_key_;
|
||||
bool is_certificate_loaded_;
|
||||
|
||||
std::set<WvCdmEventListener*> listeners_;
|
||||
|
||||
// For testing only
|
||||
// Takes ownership of license_parser, crypto_session, policy_engine
|
||||
// and device_files
|
||||
CdmSession(CdmLicense* license_parser, CryptoSession* crypto_session,
|
||||
PolicyEngine* policy_engine, DeviceFiles* file_handle,
|
||||
const CdmClientPropertySet* cdm_client_property_set);
|
||||
#if defined(UNIT_TEST)
|
||||
friend class CdmSessionTest;
|
||||
#endif
|
||||
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(CdmSession);
|
||||
};
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ class CryptoSession {
|
||||
virtual bool GetToken(std::string* token);
|
||||
virtual CdmSecurityLevel GetSecurityLevel();
|
||||
virtual bool GetDeviceUniqueId(std::string* device_id);
|
||||
virtual bool GetApiVersion(uint32_t* version);
|
||||
virtual bool GetSystemId(uint32_t* system_id);
|
||||
virtual bool GetProvisioningId(std::string* provisioning_id);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#ifndef WVCDM_CORE_DEVICE_FILES_H_
|
||||
#define WVCDM_CORE_DEVICE_FILES_H_
|
||||
|
||||
#include "scoped_ptr.h"
|
||||
#include "wv_cdm_types.h"
|
||||
|
||||
#if defined(UNIT_TEST)
|
||||
@@ -21,11 +22,13 @@ class DeviceFiles {
|
||||
kLicenseStateUnknown,
|
||||
} LicenseState;
|
||||
|
||||
DeviceFiles(): file_(NULL), security_level_(kSecurityLevelUninitialized),
|
||||
initialized_(false), test_file_(false) {}
|
||||
DeviceFiles();
|
||||
virtual ~DeviceFiles();
|
||||
|
||||
virtual bool Init(CdmSecurityLevel security_level);
|
||||
virtual bool Reset(CdmSecurityLevel security_level) {
|
||||
return Init(security_level);
|
||||
}
|
||||
|
||||
virtual bool StoreCertificate(const std::string& certificate,
|
||||
const std::string& wrapped_private_key);
|
||||
@@ -93,7 +96,7 @@ class DeviceFiles {
|
||||
FRIEND_TEST(WvCdmUsageInfoTest, DISABLED_UsageInfo);
|
||||
#endif
|
||||
|
||||
File* file_;
|
||||
scoped_ptr<File> file_;
|
||||
CdmSecurityLevel security_level_;
|
||||
bool initialized_;
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ class PolicyEngine {
|
||||
private:
|
||||
typedef enum {
|
||||
kLicenseStateInitial,
|
||||
kLicenseStatePending, // if license is issued for sometime in the future
|
||||
kLicenseStateCanPlay,
|
||||
kLicenseStateNeedRenewal,
|
||||
kLicenseStateWaitingLicenseUpdate,
|
||||
@@ -91,18 +92,14 @@ class PolicyEngine {
|
||||
// from the license server we will get an updated id field.
|
||||
video_widevine_server::sdk::LicenseIdentification license_id_;
|
||||
|
||||
// This is the license start time that gets sent from the server in each
|
||||
// license request or renewal.
|
||||
// The server returns the license start time in the license/license renewal
|
||||
// response based off the request time sent by the client in the
|
||||
// license request/renewal
|
||||
int64_t license_start_time_;
|
||||
|
||||
// This is the time at which the license was received and playback was
|
||||
// started. These times are based off the local clock in case there is a
|
||||
// discrepency between local and server time.
|
||||
int64_t license_received_time_;
|
||||
int64_t playback_start_time_;
|
||||
|
||||
// This is used as a reference point for policy management. This value
|
||||
// represents an offset from license_received_time_. This is used to
|
||||
// represents an offset from license_start_time_. This is used to
|
||||
// calculate the time where renewal retries should occur.
|
||||
int64_t next_renewal_time_;
|
||||
int64_t policy_max_duration_seconds_;
|
||||
|
||||
@@ -87,6 +87,14 @@ class Properties {
|
||||
security_level_path_backward_compatibility_support_ = flag;
|
||||
}
|
||||
|
||||
#if defined(UNIT_TEST)
|
||||
FRIEND_TEST(CdmSessionTest, InitWithCertificate);
|
||||
FRIEND_TEST(CdmSessionTest, InitWithKeybox);
|
||||
FRIEND_TEST(CdmSessionTest, ReInitFail);
|
||||
FRIEND_TEST(CdmSessionTest, InitFailCryptoError);
|
||||
FRIEND_TEST(CdmSessionTest, InitNeedsProvisioning);
|
||||
#endif
|
||||
|
||||
private:
|
||||
static bool oem_crypto_use_secure_buffers_;
|
||||
static bool oem_crypto_use_fifo_;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "cdm_engine.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
@@ -18,22 +20,26 @@
|
||||
|
||||
namespace {
|
||||
const uint32_t kUpdateUsageInformationPeriod = 60; // seconds
|
||||
const size_t kMinNoncesPerSession = 4;
|
||||
const size_t kUsageReportsPerRequest = 1;
|
||||
} // unnamed namespace
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
bool CdmEngine::seeded_ = false;
|
||||
|
||||
CdmEngine::CdmEngine()
|
||||
: cert_provisioning_requested_security_level_(kLevelDefault),
|
||||
usage_session_(NULL),
|
||||
last_usage_information_update_time(0) {
|
||||
Properties::Init();
|
||||
if (!seeded_) {
|
||||
Clock clock;
|
||||
srand(clock.GetCurrentTime());
|
||||
seeded_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
CdmEngine::~CdmEngine() {
|
||||
if (NULL != usage_session_)
|
||||
delete usage_session_;
|
||||
|
||||
CdmSessionMap::iterator i(sessions_.begin());
|
||||
for (; i != sessions_.end(); ++i) {
|
||||
delete i->second;
|
||||
@@ -505,9 +511,7 @@ CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level) {
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::GetUsageInfo(CdmUsageInfo* usage_info) {
|
||||
if (NULL == usage_session_) {
|
||||
usage_session_ = new CdmSession(NULL);
|
||||
}
|
||||
usage_session_.reset(new CdmSession(NULL));
|
||||
|
||||
CdmResponseType status = usage_session_->Init();
|
||||
if (NO_ERROR != status) {
|
||||
@@ -533,35 +537,32 @@ CdmResponseType CdmEngine::GetUsageInfo(CdmUsageInfo* usage_info) {
|
||||
}
|
||||
|
||||
std::string server_url;
|
||||
// rate limit secure stop messages based on minimum nonce
|
||||
// table size per session
|
||||
usage_info->resize(license_info.size() >= kMinNoncesPerSession - 1
|
||||
? kMinNoncesPerSession - 1
|
||||
: license_info.size());
|
||||
for (size_t i = 0; i < usage_info->size(); ++i) {
|
||||
status = usage_session_->RestoreUsageSession(license_info[i].first,
|
||||
license_info[i].second);
|
||||
if (KEY_ADDED != status) {
|
||||
LOGE("CdmEngine::GetUsageInfo: restore usage session error: %ld",
|
||||
status);
|
||||
usage_info->clear();
|
||||
return status;
|
||||
}
|
||||
status = usage_session_->GenerateReleaseRequest(&(*usage_info)[i],
|
||||
&server_url);
|
||||
if (KEY_MESSAGE != status) {
|
||||
LOGE("CdmEngine::GetUsageInfo: generate release request error: %ld",
|
||||
status);
|
||||
usage_info->clear();
|
||||
return status;
|
||||
}
|
||||
usage_info->resize(kUsageReportsPerRequest);
|
||||
|
||||
uint32_t index = rand() % license_info.size();
|
||||
status = usage_session_->RestoreUsageSession(license_info[index].first,
|
||||
license_info[index].second);
|
||||
if (KEY_ADDED != status) {
|
||||
LOGE("CdmEngine::GetUsageInfo: restore usage session (%d) error %ld",
|
||||
index, status);
|
||||
usage_info->clear();
|
||||
return status;
|
||||
}
|
||||
|
||||
status = usage_session_->GenerateReleaseRequest(&(*usage_info)[0], &server_url);
|
||||
|
||||
if (KEY_MESSAGE != status) {
|
||||
LOGE("CdmEngine::GetUsageInfo: generate release request error: %ld",
|
||||
status);
|
||||
usage_info->clear();
|
||||
return status;
|
||||
}
|
||||
return KEY_MESSAGE;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::ReleaseUsageInfo(
|
||||
const CdmUsageInfoReleaseMessage& message) {
|
||||
if (NULL == usage_session_) {
|
||||
if (NULL == usage_session_.get()) {
|
||||
LOGE("CdmEngine::ReleaseUsageInfo: cdm session not initialized");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
@@ -569,9 +570,8 @@ CdmResponseType CdmEngine::ReleaseUsageInfo(
|
||||
CdmResponseType status = usage_session_->ReleaseKey(message);
|
||||
if (NO_ERROR != status) {
|
||||
LOGE("CdmEngine::ReleaseUsageInfo: release key error: %ld", status);
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
return NO_ERROR;
|
||||
return status;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::Decrypt(
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "cdm_engine.h"
|
||||
#include "clock.h"
|
||||
#include "crypto_session.h"
|
||||
#include "device_files.h"
|
||||
#include "file_store.h"
|
||||
@@ -25,16 +24,56 @@ namespace wvcdm {
|
||||
|
||||
typedef std::set<WvCdmEventListener*>::iterator CdmEventListenerIter;
|
||||
|
||||
CdmSession::CdmSession(const CdmClientPropertySet* cdm_client_property_set)
|
||||
: session_id_(GenerateSessionId()),
|
||||
crypto_session_(NULL),
|
||||
license_received_(false),
|
||||
reinitialize_session_(false),
|
||||
is_offline_(false),
|
||||
is_release_(false),
|
||||
is_usage_update_needed_(false),
|
||||
is_initial_decryption_(true),
|
||||
is_certificate_loaded_(false) {
|
||||
CdmSession::CdmSession(const CdmClientPropertySet* cdm_client_property_set) {
|
||||
Create(new CdmLicense(), new CryptoSession(), new PolicyEngine(),
|
||||
new DeviceFiles(), cdm_client_property_set);
|
||||
}
|
||||
|
||||
CdmSession::CdmSession(
|
||||
CdmLicense* license_parser,
|
||||
CryptoSession* crypto_session,
|
||||
PolicyEngine* policy_engine,
|
||||
DeviceFiles* file_handle,
|
||||
const CdmClientPropertySet* cdm_client_property_set) {
|
||||
Create(license_parser, crypto_session, policy_engine, file_handle,
|
||||
cdm_client_property_set);
|
||||
}
|
||||
|
||||
void CdmSession::Create(
|
||||
CdmLicense* license_parser,
|
||||
CryptoSession* crypto_session,
|
||||
PolicyEngine* policy_engine,
|
||||
DeviceFiles* file_handle,
|
||||
const CdmClientPropertySet* cdm_client_property_set) {
|
||||
// Just return on failures. Failures will be signaled in Init.
|
||||
if (NULL == license_parser) {
|
||||
LOGE("CdmSession::Create: License parser not provided");
|
||||
return;
|
||||
}
|
||||
if (NULL == crypto_session) {
|
||||
LOGE("CdmSession::Create: Crypto session not provided");
|
||||
return;
|
||||
}
|
||||
if (NULL == policy_engine) {
|
||||
LOGE("CdmSession::Create: Policy engine not provided");
|
||||
return;
|
||||
}
|
||||
if (NULL == file_handle) {
|
||||
LOGE("CdmSession::Create: Device files not provided");
|
||||
return;
|
||||
}
|
||||
initialized_ = false;
|
||||
session_id_ = GenerateSessionId();
|
||||
license_parser_.reset(license_parser);
|
||||
crypto_session_.reset(crypto_session);
|
||||
file_handle_.reset(file_handle);
|
||||
policy_engine_.reset(policy_engine);
|
||||
license_received_ = false;
|
||||
is_offline_ = false;
|
||||
is_release_ = false;
|
||||
is_usage_update_needed_ = false;
|
||||
is_initial_decryption_ = true;
|
||||
security_level_ = crypto_session_.get()->GetSecurityLevel();
|
||||
if (cdm_client_property_set) {
|
||||
Properties::AddSessionPropertySet(session_id_, cdm_client_property_set);
|
||||
}
|
||||
@@ -43,29 +82,36 @@ CdmSession::CdmSession(const CdmClientPropertySet* cdm_client_property_set)
|
||||
CdmSession::~CdmSession() { Properties::RemoveSessionPropertySet(session_id_); }
|
||||
|
||||
CdmResponseType CdmSession::Init() {
|
||||
scoped_ptr<CryptoSession> session(new CryptoSession());
|
||||
|
||||
CdmResponseType sts = session->Open(GetRequestedSecurityLevel());
|
||||
if (session_id_.empty()) {
|
||||
LOGE("CdmSession::Init: Failed, session not properly constructed");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
if (initialized_) {
|
||||
LOGE("CdmSession::Init: Failed due to previous initialization");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
CdmResponseType sts = crypto_session_->Open(GetRequestedSecurityLevel());
|
||||
if (NO_ERROR != sts) return sts;
|
||||
|
||||
std::string token;
|
||||
if (Properties::use_certificates_as_identification()) {
|
||||
DeviceFiles handle;
|
||||
if (!handle.Init(session.get()->GetSecurityLevel()) ||
|
||||
!handle.RetrieveCertificate(&token, &wrapped_key_)) {
|
||||
std::string wrapped_key;
|
||||
if (!file_handle_->Init(security_level_) ||
|
||||
!file_handle_->RetrieveCertificate(&token, &wrapped_key) ||
|
||||
!crypto_session_->LoadCertificatePrivateKey(wrapped_key)) {
|
||||
return NEED_PROVISIONING;
|
||||
}
|
||||
} else {
|
||||
if (!session->GetToken(&token)) return UNKNOWN_ERROR;
|
||||
if (!crypto_session_->GetToken(&token)) return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
if (!license_parser_.Init(token, session.get(), &policy_engine_))
|
||||
if (!license_parser_->Init(token, crypto_session_.get(),
|
||||
policy_engine_.get()))
|
||||
return UNKNOWN_ERROR;
|
||||
|
||||
crypto_session_.reset(session.release());
|
||||
license_received_ = false;
|
||||
reinitialize_session_ = false;
|
||||
is_initial_decryption_ = true;
|
||||
initialized_ = true;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -74,17 +120,17 @@ CdmResponseType CdmSession::RestoreOfflineSession(
|
||||
key_set_id_ = key_set_id;
|
||||
|
||||
// Retrieve license information from persistent store
|
||||
DeviceFiles handle;
|
||||
if (!handle.Init(crypto_session_->GetSecurityLevel()))
|
||||
if (!file_handle_->Reset(security_level_))
|
||||
return UNKNOWN_ERROR;
|
||||
|
||||
DeviceFiles::LicenseState license_state;
|
||||
|
||||
if (!handle.RetrieveLicense(key_set_id, &license_state, &offline_init_data_,
|
||||
&key_request_, &key_response_,
|
||||
&offline_key_renewal_request_,
|
||||
&offline_key_renewal_response_,
|
||||
&offline_release_server_url_)) {
|
||||
if (!file_handle_->RetrieveLicense(key_set_id, &license_state,
|
||||
&offline_init_data_,
|
||||
&key_request_, &key_response_,
|
||||
&offline_key_renewal_request_,
|
||||
&offline_key_renewal_response_,
|
||||
&offline_release_server_url_)) {
|
||||
LOGE("CdmSession::Init failed to retrieve license. key set id = %s",
|
||||
key_set_id.c_str());
|
||||
return UNKNOWN_ERROR;
|
||||
@@ -95,17 +141,8 @@ CdmResponseType CdmSession::RestoreOfflineSession(
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
if (Properties::use_certificates_as_identification()) {
|
||||
if (is_certificate_loaded_ ||
|
||||
crypto_session_->LoadCertificatePrivateKey(wrapped_key_)) {
|
||||
is_certificate_loaded_ = true;
|
||||
} else {
|
||||
return NEED_PROVISIONING;
|
||||
}
|
||||
}
|
||||
|
||||
if (!license_parser_.RestoreOfflineLicense(key_request_, key_response_,
|
||||
offline_key_renewal_response_)) {
|
||||
if (!license_parser_->RestoreOfflineLicense(key_request_, key_response_,
|
||||
offline_key_renewal_response_)) {
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
@@ -121,16 +158,8 @@ CdmResponseType CdmSession::RestoreUsageSession(
|
||||
|
||||
key_request_ = key_request;
|
||||
key_response_ = key_response;
|
||||
if (Properties::use_certificates_as_identification()) {
|
||||
if (is_certificate_loaded_ ||
|
||||
crypto_session_->LoadCertificatePrivateKey(wrapped_key_)) {
|
||||
is_certificate_loaded_ = true;
|
||||
} else {
|
||||
return NEED_PROVISIONING;
|
||||
}
|
||||
}
|
||||
|
||||
if (!license_parser_.RestoreUsageLicense(key_request_, key_response_)) {
|
||||
if (!license_parser_->RestoreUsageLicense(key_request_, key_response_)) {
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
@@ -144,14 +173,6 @@ CdmResponseType CdmSession::GenerateKeyRequest(
|
||||
const InitializationData& init_data, const CdmLicenseType license_type,
|
||||
const CdmAppParameterMap& app_parameters, CdmKeyMessage* key_request,
|
||||
std::string* server_url) {
|
||||
if (reinitialize_session_) {
|
||||
CdmResponseType sts = Init();
|
||||
if (sts != NO_ERROR) {
|
||||
LOGW("CdmSession::GenerateKeyRequest: Reinitialization failed");
|
||||
return sts;
|
||||
}
|
||||
}
|
||||
|
||||
if (crypto_session_.get() == NULL) {
|
||||
LOGW("CdmSession::GenerateKeyRequest: Invalid crypto session");
|
||||
return UNKNOWN_ERROR;
|
||||
@@ -182,24 +203,14 @@ CdmResponseType CdmSession::GenerateKeyRequest(
|
||||
init_data.type().c_str());
|
||||
return KEY_ERROR;
|
||||
}
|
||||
if (init_data.IsEmpty() && !license_parser_.HasInitData()) {
|
||||
if (init_data.IsEmpty() && !license_parser_->HasInitData()) {
|
||||
LOGW("CdmSession::GenerateKeyRequest: init data absent");
|
||||
return KEY_ERROR;
|
||||
}
|
||||
|
||||
if (Properties::use_certificates_as_identification()) {
|
||||
if (is_certificate_loaded_ ||
|
||||
crypto_session_->LoadCertificatePrivateKey(wrapped_key_)) {
|
||||
is_certificate_loaded_ = true;
|
||||
} else {
|
||||
reinitialize_session_ = true;
|
||||
return NEED_PROVISIONING;
|
||||
}
|
||||
}
|
||||
|
||||
if (!license_parser_.PrepareKeyRequest(init_data, license_type,
|
||||
app_parameters, session_id_,
|
||||
key_request, server_url)) {
|
||||
if (!license_parser_->PrepareKeyRequest(init_data, license_type,
|
||||
app_parameters, session_id_,
|
||||
key_request, server_url)) {
|
||||
return KEY_ERROR;
|
||||
}
|
||||
|
||||
@@ -227,18 +238,19 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response,
|
||||
}
|
||||
|
||||
if (is_release_) {
|
||||
return ReleaseKey(key_response);
|
||||
CdmResponseType sts = ReleaseKey(key_response);
|
||||
return (NO_ERROR == sts) ? KEY_ADDED : sts;
|
||||
} else if (license_received_) { // renewal
|
||||
return RenewKey(key_response);
|
||||
} else {
|
||||
CdmResponseType sts = license_parser_.HandleKeyResponse(key_response);
|
||||
CdmResponseType sts = license_parser_->HandleKeyResponse(key_response);
|
||||
|
||||
if (sts != KEY_ADDED) return sts;
|
||||
|
||||
license_received_ = true;
|
||||
key_response_ = key_response;
|
||||
|
||||
if (is_offline_ || !license_parser_.provider_session_token().empty()) {
|
||||
if (is_offline_ || !license_parser_->provider_session_token().empty()) {
|
||||
sts = StoreLicense();
|
||||
if (sts != NO_ERROR) return sts;
|
||||
}
|
||||
@@ -281,7 +293,7 @@ CdmResponseType CdmSession::QueryStatus(CdmQueryMap* key_info) {
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::QueryKeyStatus(CdmQueryMap* key_info) {
|
||||
return policy_engine_.Query(key_info);
|
||||
return policy_engine_->Query(key_info);
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::QueryKeyControlInfo(CdmQueryMap* key_info) {
|
||||
@@ -316,12 +328,12 @@ CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) {
|
||||
|
||||
if (NO_ERROR == status) {
|
||||
if (is_initial_decryption_) {
|
||||
policy_engine_.BeginDecryption();
|
||||
policy_engine_->BeginDecryption();
|
||||
is_initial_decryption_ = false;
|
||||
}
|
||||
if (!is_usage_update_needed_) {
|
||||
is_usage_update_needed_ =
|
||||
!license_parser_.provider_session_token().empty();
|
||||
!license_parser_->provider_session_token().empty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,7 +345,8 @@ 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;
|
||||
}
|
||||
@@ -347,7 +360,7 @@ CdmResponseType CdmSession::GenerateRenewalRequest(CdmKeyMessage* key_request,
|
||||
// RenewKey() - Accept renewal response and update key info.
|
||||
CdmResponseType CdmSession::RenewKey(const CdmKeyResponse& key_response) {
|
||||
CdmResponseType sts =
|
||||
license_parser_.HandleKeyUpdateResponse(true, key_response);
|
||||
license_parser_->HandleKeyUpdateResponse(true, key_response);
|
||||
if (sts != KEY_ADDED) return sts;
|
||||
|
||||
if (is_offline_) {
|
||||
@@ -360,7 +373,7 @@ CdmResponseType CdmSession::RenewKey(const CdmKeyResponse& key_response) {
|
||||
CdmResponseType CdmSession::GenerateReleaseRequest(CdmKeyMessage* key_request,
|
||||
std::string* server_url) {
|
||||
is_release_ = true;
|
||||
if (!license_parser_.PrepareKeyUpdateRequest(false, key_request, server_url))
|
||||
if (!license_parser_->PrepareKeyUpdateRequest(false, key_request, server_url))
|
||||
return UNKNOWN_ERROR;
|
||||
|
||||
if (is_offline_) { // Mark license as being released
|
||||
@@ -372,19 +385,19 @@ CdmResponseType CdmSession::GenerateReleaseRequest(CdmKeyMessage* key_request,
|
||||
|
||||
// ReleaseKey() - Accept release response and release license.
|
||||
CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) {
|
||||
CdmResponseType sts = license_parser_.HandleKeyUpdateResponse(false,
|
||||
CdmResponseType sts = license_parser_->HandleKeyUpdateResponse(false,
|
||||
key_response);
|
||||
if (NO_ERROR != sts)
|
||||
if (KEY_ADDED != sts)
|
||||
return sts;
|
||||
|
||||
if (is_offline_ || !license_parser_.provider_session_token().empty()) {
|
||||
if (is_offline_ || !license_parser_->provider_session_token().empty()) {
|
||||
DeleteLicense();
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
bool CdmSession::IsKeyLoaded(const KeyId& key_id) {
|
||||
return license_parser_.IsKeyLoaded(key_id);
|
||||
return license_parser_->IsKeyLoaded(key_id);
|
||||
}
|
||||
|
||||
CdmSessionId CdmSession::GenerateSessionId() {
|
||||
@@ -401,8 +414,7 @@ bool CdmSession::GenerateKeySetId(CdmKeySetId* key_set_id) {
|
||||
std::vector<uint8_t> random_data(
|
||||
(kKeySetIdLength - sizeof(KEY_SET_ID_PREFIX)) / 2, 0);
|
||||
|
||||
DeviceFiles handle;
|
||||
if (!handle.Init(crypto_session_->GetSecurityLevel()))
|
||||
if (!file_handle_->Reset(security_level_))
|
||||
return false;
|
||||
|
||||
while (key_set_id->empty()) {
|
||||
@@ -412,7 +424,7 @@ bool CdmSession::GenerateKeySetId(CdmKeySetId* key_set_id) {
|
||||
*key_set_id = KEY_SET_ID_PREFIX + b2a_hex(random_data);
|
||||
|
||||
// key set collision
|
||||
if (handle.LicenseExists(*key_set_id)) {
|
||||
if (file_handle_->LicenseExists(*key_set_id)) {
|
||||
key_set_id->clear();
|
||||
}
|
||||
}
|
||||
@@ -440,20 +452,20 @@ CdmResponseType CdmSession::StoreLicense() {
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
std::string provider_session_token = license_parser_.provider_session_token();
|
||||
std::string provider_session_token =
|
||||
license_parser_->provider_session_token();
|
||||
if (provider_session_token.empty()) {
|
||||
LOGE("CdmSession::StoreLicense: No provider session token and not offline");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
DeviceFiles handle;
|
||||
if (!handle.Init(crypto_session_->GetSecurityLevel())) {
|
||||
if (!file_handle_->Reset(security_level_)) {
|
||||
LOGE("CdmSession::StoreLicense: Unable to initialize device files");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
if (!handle.StoreUsageInfo(provider_session_token, key_request_,
|
||||
key_response_)) {
|
||||
if (!file_handle_->StoreUsageInfo(provider_session_token, key_request_,
|
||||
key_response_)) {
|
||||
LOGE("CdmSession::StoreLicense: Unable to store usage info");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
@@ -461,31 +473,29 @@ CdmResponseType CdmSession::StoreLicense() {
|
||||
}
|
||||
|
||||
bool CdmSession::StoreLicense(DeviceFiles::LicenseState state) {
|
||||
DeviceFiles handle;
|
||||
if (!handle.Init(crypto_session_->GetSecurityLevel()))
|
||||
if (!file_handle_->Reset(security_level_))
|
||||
return false;
|
||||
|
||||
return handle.StoreLicense(
|
||||
return file_handle_->StoreLicense(
|
||||
key_set_id_, state, offline_init_data_, key_request_,
|
||||
key_response_, offline_key_renewal_request_,
|
||||
offline_key_renewal_response_, offline_release_server_url_);
|
||||
}
|
||||
|
||||
bool CdmSession::DeleteLicense() {
|
||||
if (!is_offline_ && license_parser_.provider_session_token().empty())
|
||||
if (!is_offline_ && license_parser_->provider_session_token().empty())
|
||||
return false;
|
||||
|
||||
DeviceFiles handle;
|
||||
if (!handle.Init(crypto_session_->GetSecurityLevel())) {
|
||||
if (!file_handle_->Reset(security_level_)) {
|
||||
LOGE("CdmSession::DeleteLicense: Unable to initialize device files");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_offline_)
|
||||
return handle.DeleteLicense(key_set_id_);
|
||||
return file_handle_->DeleteLicense(key_set_id_);
|
||||
else
|
||||
return handle.DeleteUsageInfo(
|
||||
license_parser_.provider_session_token());
|
||||
return file_handle_->DeleteUsageInfo(
|
||||
license_parser_->provider_session_token());
|
||||
}
|
||||
|
||||
bool CdmSession::AttachEventListener(WvCdmEventListener* listener) {
|
||||
@@ -501,7 +511,7 @@ 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();
|
||||
|
||||
@@ -159,6 +159,25 @@ bool CryptoSession::GetDeviceUniqueId(std::string* device_id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CryptoSession::GetApiVersion(uint32_t* version) {
|
||||
if (!version) {
|
||||
LOGE("CryptoSession::GetApiVersion: No buffer passed to method.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!initialized_) {
|
||||
return false;
|
||||
}
|
||||
CdmSecurityLevel level = GetSecurityLevel();
|
||||
SecurityLevel security_level = kLevelDefault;
|
||||
if (kSecurityLevelL3 == level) security_level = kLevel3;
|
||||
|
||||
LOGV("CryptoSession::GetApiVersion: Lock");
|
||||
AutoLock auto_lock(crypto_lock_);
|
||||
*version = OEMCrypto_APIVersion(security_level);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CryptoSession::GetSystemId(uint32_t* system_id) {
|
||||
if (!system_id) {
|
||||
LOGE("CryptoSession::GetSystemId : No buffer passed to method.");
|
||||
|
||||
@@ -55,8 +55,13 @@ bool Hash(const std::string& data, std::string* hash) {
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
DeviceFiles::DeviceFiles()
|
||||
: file_(NULL), security_level_(kSecurityLevelUninitialized),
|
||||
initialized_(false), test_file_(false) {
|
||||
}
|
||||
|
||||
DeviceFiles::~DeviceFiles() {
|
||||
if (!file_ && !test_file_) delete file_;
|
||||
if (test_file_) file_.release();
|
||||
}
|
||||
|
||||
bool DeviceFiles::Init(CdmSecurityLevel security_level) {
|
||||
@@ -69,7 +74,7 @@ bool DeviceFiles::Init(CdmSecurityLevel security_level) {
|
||||
LOGW("DeviceFiles::Init: Unsupported security level %d", security_level);
|
||||
return false;
|
||||
}
|
||||
file_ = new File();
|
||||
if (!test_file_) file_.reset(new File());
|
||||
security_level_ = security_level;
|
||||
initialized_ = true;
|
||||
return true;
|
||||
@@ -363,18 +368,13 @@ bool DeviceFiles::DeleteUsageInfo(const std::string& provider_session_token) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UsageInfo* updated_info = file.mutable_usage_info();
|
||||
UsageInfo info(*(const_cast<const UsageInfo*>(updated_info)));
|
||||
updated_info->clear_sessions();
|
||||
UsageInfo* usage_info = file.mutable_usage_info();
|
||||
int index = 0;
|
||||
bool found = false;
|
||||
for (int i = 0; i < info.sessions_size(); ++i) {
|
||||
if (info.sessions(i).token().compare(provider_session_token) == 0) {
|
||||
for (; index < usage_info->sessions_size(); ++index) {
|
||||
if (usage_info->sessions(index).token().compare(provider_session_token) == 0) {
|
||||
found = true;
|
||||
} else {
|
||||
updated_info->add_sessions()->set_token(info.sessions(i).token());
|
||||
updated_info->add_sessions()->set_license_request(
|
||||
info.sessions(i).license_request());
|
||||
updated_info->add_sessions()->set_license(info.sessions(i).license());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,6 +384,13 @@ bool DeviceFiles::DeleteUsageInfo(const std::string& provider_session_token) {
|
||||
return false;
|
||||
}
|
||||
|
||||
google::protobuf::RepeatedPtrField<UsageInfo_ProviderSession>* sessions =
|
||||
usage_info->mutable_sessions();
|
||||
if (index < usage_info->sessions_size() - 1) {
|
||||
sessions->SwapElements(index, usage_info->sessions_size() - 1);
|
||||
}
|
||||
sessions->RemoveLast();
|
||||
|
||||
file.SerializeToString(&serialized_file);
|
||||
return StoreFile(kUsageInfoFileName, serialized_file);
|
||||
}
|
||||
@@ -452,7 +459,7 @@ bool DeviceFiles::RetrieveUsageInfo(std::vector<
|
||||
|
||||
bool DeviceFiles::StoreFile(const char* name,
|
||||
const std::string& serialized_file) {
|
||||
if (!file_) {
|
||||
if (!file_.get()) {
|
||||
LOGW("DeviceFiles::StoreFile: Invalid file handle");
|
||||
return false;
|
||||
}
|
||||
@@ -512,7 +519,7 @@ bool DeviceFiles::StoreFile(const char* name,
|
||||
}
|
||||
|
||||
bool DeviceFiles::RetrieveFile(const char* name, std::string* serialized_file) {
|
||||
if (!file_) {
|
||||
if (!file_.get()) {
|
||||
LOGW("DeviceFiles::RetrieveFile: Invalid file handle");
|
||||
return false;
|
||||
}
|
||||
@@ -661,8 +668,7 @@ std::string DeviceFiles::GetUsageInfoFileName() {
|
||||
}
|
||||
|
||||
void DeviceFiles::SetTestFile(File* file) {
|
||||
if (file_) delete file_;
|
||||
file_ = file;
|
||||
file_.reset(file);
|
||||
test_file_ = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "clock.h"
|
||||
#include "crypto_key.h"
|
||||
#include "crypto_session.h"
|
||||
#include "device_files.h"
|
||||
@@ -22,6 +23,7 @@ std::string kDeviceNameKey = "device_name";
|
||||
std::string kProductNameKey = "product_name";
|
||||
std::string kBuildInfoKey = "build_info";
|
||||
std::string kDeviceIdKey = "device_id";
|
||||
std::string kOemCryptoApiVersion = "oemcrypto_api_version";
|
||||
const unsigned char kServiceCertificateCAPublicKey[] = {
|
||||
0x30, 0x82, 0x01, 0x8a, 0x02, 0x82, 0x01, 0x81,
|
||||
0x00, 0xb4, 0xfe, 0x39, 0xc3, 0x65, 0x90, 0x03,
|
||||
@@ -254,12 +256,17 @@ bool CdmLicense::PrepareKeyRequest(const InitializationData& init_data,
|
||||
client_info->set_name(kBuildInfoKey);
|
||||
client_info->set_value(value);
|
||||
}
|
||||
|
||||
if (session_->GetDeviceUniqueId(&value)) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kDeviceIdKey);
|
||||
client_info->set_value(value);
|
||||
}
|
||||
uint32_t version = 0;
|
||||
if (session_->GetApiVersion(&version)) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kOemCryptoApiVersion);
|
||||
client_info->set_value(UintToString(version));
|
||||
}
|
||||
|
||||
if (privacy_mode_enabled) {
|
||||
EncryptedClientIdentification* encrypted_client_id =
|
||||
@@ -353,12 +360,11 @@ bool CdmLicense::PrepareKeyRequest(const InitializationData& init_data,
|
||||
return false;
|
||||
}
|
||||
|
||||
// The time field will be updated once the cdm wrapper
|
||||
// has been updated to pass us in the time.
|
||||
license_request.set_request_time(0);
|
||||
|
||||
license_request.set_type(LicenseRequest::NEW);
|
||||
|
||||
Clock clock;
|
||||
license_request.set_request_time(clock.GetCurrentTime());
|
||||
|
||||
// Get/set the nonce. This value will be reflected in the Key Control Block
|
||||
// of the license response.
|
||||
uint32_t nonce;
|
||||
@@ -424,6 +430,9 @@ bool CdmLicense::PrepareKeyUpdateRequest(bool is_renewal,
|
||||
else
|
||||
license_request.set_type(LicenseRequest::RELEASE);
|
||||
|
||||
Clock clock;
|
||||
license_request.set_request_time(clock.GetCurrentTime());
|
||||
|
||||
LicenseRequest_ContentIdentification_ExistingLicense* current_license =
|
||||
license_request.mutable_content_id()->mutable_license();
|
||||
LicenseIdentification license_id = policy_engine_->license_id();
|
||||
@@ -432,8 +441,9 @@ bool CdmLicense::PrepareKeyUpdateRequest(bool is_renewal,
|
||||
if (!is_renewal) {
|
||||
if (license_id.has_provider_session_token()) {
|
||||
std::string usage_report;
|
||||
if (!session_->GenerateUsageReport(license_id.provider_session_token(),
|
||||
&usage_report)) {
|
||||
if (NO_ERROR !=
|
||||
session_->GenerateUsageReport(license_id.provider_session_token(),
|
||||
&usage_report)) {
|
||||
return false;
|
||||
}
|
||||
current_license->set_session_usage_table_entry(usage_report);
|
||||
@@ -560,7 +570,6 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
||||
return KEY_ERROR;
|
||||
}
|
||||
|
||||
std::string provider_session_token;
|
||||
if (license.id().has_provider_session_token())
|
||||
provider_session_token_ = license.id().provider_session_token();
|
||||
|
||||
@@ -575,7 +584,7 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
||||
mac_key_iv,
|
||||
mac_key,
|
||||
key_array,
|
||||
provider_session_token);
|
||||
provider_session_token_);
|
||||
|
||||
if (KEY_ADDED == resp) {
|
||||
loaded_keys_.clear();
|
||||
@@ -627,24 +636,23 @@ CdmResponseType CdmLicense::HandleKeyUpdateResponse(
|
||||
return KEY_ERROR;
|
||||
}
|
||||
|
||||
if (is_renewal) {
|
||||
if (license.policy().has_renewal_server_url() &&
|
||||
license.policy().renewal_server_url().size() > 0) {
|
||||
server_url_ = license.policy().renewal_server_url();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (license.id().has_provider_session_token()) {
|
||||
provider_session_token_ = license.id().provider_session_token();
|
||||
session_->ReleaseUsageInformation(signed_response.msg(),
|
||||
signed_response.signature(),
|
||||
provider_session_token_);
|
||||
}
|
||||
}
|
||||
|
||||
policy_engine_->UpdateLicense(license);
|
||||
|
||||
if (!is_renewal) return KEY_ADDED;
|
||||
if (!is_renewal) {
|
||||
if (!license.id().has_provider_session_token()) return KEY_ADDED;
|
||||
|
||||
provider_session_token_ = license.id().provider_session_token();
|
||||
CdmResponseType status =
|
||||
session_->ReleaseUsageInformation(signed_response.msg(),
|
||||
signed_response.signature(),
|
||||
provider_session_token_);
|
||||
return (NO_ERROR == status) ? KEY_ADDED : status;
|
||||
}
|
||||
|
||||
if (license.policy().has_renewal_server_url() &&
|
||||
license.policy().renewal_server_url().size() > 0) {
|
||||
server_url_ = license.policy().renewal_server_url();
|
||||
}
|
||||
|
||||
std::vector<CryptoKey> key_array = ExtractContentKeys(license);
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@ void PolicyEngine::Init(Clock* clock) {
|
||||
license_state_ = kLicenseStateInitial;
|
||||
can_decrypt_ = false;
|
||||
license_start_time_ = 0;
|
||||
license_received_time_ = 0;
|
||||
playback_start_time_ = 0;
|
||||
next_renewal_time_ = 0;
|
||||
policy_max_duration_seconds_ = 0;
|
||||
@@ -76,6 +75,14 @@ void PolicyEngine::OnTimerEvent(bool* event_occurred, CdmEventType* event) {
|
||||
break;
|
||||
}
|
||||
|
||||
case kLicenseStatePending: {
|
||||
if (current_time >= license_start_time_) {
|
||||
license_state_ = kLicenseStateCanPlay;
|
||||
can_decrypt_ = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kLicenseStateInitial:
|
||||
case kLicenseStateExpired: {
|
||||
break;
|
||||
@@ -115,13 +122,11 @@ void PolicyEngine::UpdateLicense(
|
||||
policy_.MergeFrom(license.policy());
|
||||
|
||||
// some basic license validation
|
||||
if (license_state_ == kLicenseStateInitial) {
|
||||
// license start time needs to be present in the initial response
|
||||
if (!license.has_license_start_time())
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// if renewal, discard license if version has not been updated
|
||||
// license start time needs to be specified in the initial response
|
||||
if (!license.has_license_start_time()) return;
|
||||
|
||||
// if renewal, discard license if version has not been updated
|
||||
if (license_state_ != kLicenseStateInitial) {
|
||||
if (license.id().version() > license_id_.version())
|
||||
license_id_.CopyFrom(license.id());
|
||||
else
|
||||
@@ -129,12 +134,8 @@ void PolicyEngine::UpdateLicense(
|
||||
}
|
||||
|
||||
// Update time information
|
||||
int64_t current_time = clock_->GetCurrentTime();
|
||||
if (license.has_license_start_time())
|
||||
license_start_time_ = license.license_start_time();
|
||||
license_received_time_ = current_time;
|
||||
next_renewal_time_ = current_time +
|
||||
policy_.renewal_delay_seconds();
|
||||
license_start_time_ = license.license_start_time();
|
||||
next_renewal_time_ = license_start_time_ + policy_.renewal_delay_seconds();
|
||||
|
||||
// Calculate policy_max_duration_seconds_. policy_max_duration_seconds_
|
||||
// will be set to the minimum of the following policies :
|
||||
@@ -157,12 +158,18 @@ void PolicyEngine::UpdateLicense(
|
||||
return;
|
||||
}
|
||||
|
||||
int64_t current_time = clock_->GetCurrentTime();
|
||||
if (IsLicenseDurationExpired(current_time)) return;
|
||||
if (IsPlaybackDurationExpired(current_time)) return;
|
||||
|
||||
// Update state
|
||||
license_state_ = kLicenseStateCanPlay;
|
||||
can_decrypt_ = true;
|
||||
if (current_time >= license_start_time_) {
|
||||
license_state_ = kLicenseStateCanPlay;
|
||||
can_decrypt_ = true;
|
||||
} else {
|
||||
license_state_ = kLicenseStatePending;
|
||||
can_decrypt_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void PolicyEngine::BeginDecryption() {
|
||||
@@ -178,6 +185,7 @@ void PolicyEngine::BeginDecryption() {
|
||||
}
|
||||
break;
|
||||
case kLicenseStateInitial:
|
||||
case kLicenseStatePending:
|
||||
case kLicenseStateExpired:
|
||||
default:
|
||||
break;
|
||||
@@ -221,7 +229,7 @@ void PolicyEngine::UpdateRenewalRequest(int64_t current_time) {
|
||||
// will always return false if the value is 0.
|
||||
bool PolicyEngine::IsLicenseDurationExpired(int64_t current_time) {
|
||||
return policy_max_duration_seconds_ &&
|
||||
license_received_time_ + policy_max_duration_seconds_ <=
|
||||
license_start_time_ + policy_max_duration_seconds_ <=
|
||||
current_time;
|
||||
}
|
||||
|
||||
@@ -229,9 +237,12 @@ int64_t PolicyEngine::GetLicenseDurationRemaining(int64_t current_time) {
|
||||
if (0 == policy_max_duration_seconds_) return LLONG_MAX;
|
||||
|
||||
int64_t remaining_time = policy_max_duration_seconds_
|
||||
+ license_received_time_ - current_time;
|
||||
+ license_start_time_ - current_time;
|
||||
|
||||
if (remaining_time < 0) remaining_time = 0;
|
||||
if (remaining_time < 0)
|
||||
remaining_time = 0;
|
||||
else if (remaining_time > policy_max_duration_seconds_)
|
||||
remaining_time = policy_max_duration_seconds_;
|
||||
return remaining_time;
|
||||
}
|
||||
|
||||
@@ -256,7 +267,7 @@ int64_t PolicyEngine::GetPlaybackDurationRemaining(int64_t current_time) {
|
||||
bool PolicyEngine::IsRenewalDelayExpired(int64_t current_time) {
|
||||
return policy_.can_renew() &&
|
||||
(policy_.renewal_delay_seconds() > 0) &&
|
||||
license_received_time_ + policy_.renewal_delay_seconds() <=
|
||||
license_start_time_ + policy_.renewal_delay_seconds() <=
|
||||
current_time;
|
||||
}
|
||||
|
||||
@@ -264,7 +275,7 @@ bool PolicyEngine::IsRenewalRecoveryDurationExpired(
|
||||
int64_t current_time) {
|
||||
// NOTE: Renewal Recovery Duration is currently not used.
|
||||
return (policy_.renewal_recovery_duration_seconds() > 0) &&
|
||||
license_received_time_ + policy_.renewal_recovery_duration_seconds() <=
|
||||
license_start_time_ + policy_.renewal_recovery_duration_seconds() <=
|
||||
current_time;
|
||||
}
|
||||
|
||||
|
||||
239
core/test/cdm_session_unittest.cpp
Normal file
239
core/test/cdm_session_unittest.cpp
Normal file
@@ -0,0 +1,239 @@
|
||||
// Copyright 2014 Google Inc. All Rights Reserved.
|
||||
|
||||
#include "cdm_session.h"
|
||||
#include "crypto_key.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "properties.h"
|
||||
#include "string_conversions.h"
|
||||
|
||||
namespace {
|
||||
const std::string kToken = wvcdm::a2bs_hex(
|
||||
"0AAE02080212107E0A892DEEB021E7AF696B938BB1D5B1188B85AD9D05228E023082010A02"
|
||||
"82010100DBEDF2BFB0EC98213766E65049B9AB176FA4B1FBFBB2A0C96C87D9F2B895E0ED77"
|
||||
"93BDA057E6BC3E0CA2348BC6831E03609445CA4D418CB98EAC98FFC87AB2364CE76BA26BEE"
|
||||
"CDB0C45BD2A6FE9FD38CC5A1C26303AEEB7E9C3CAFAB0D10E46C07E50BEDAB42BF21F40BD2"
|
||||
"E055DB0B455191D6B4CEEB11B3F1AFA42B5C0CE4C96B75A5283C0E3AE049AA7CF86D1C4EF6"
|
||||
"6A9088B53BCF320ABC9B98A22C219DC109014EFEA72DA5FF2ED5D655DE7AE06EAC6C6B4191"
|
||||
"523B2CD2DC1EBFF5F08B11CFE056F2826C1323F12704EC7EBBC1AF935129E5543804492AF9"
|
||||
"23B848F4AF47B4BFB131C39DDDC99DBAEEE0F30AD2ADBBC63E60793D0876E37391008BB4DB"
|
||||
"F7020301000128DD22128002A9E571776EA9D22A1BD14248DA88E12FD859989F613360B8D2"
|
||||
"DA40AF31CC071C7A138466F0EB745E3FD664C0E1A5E4F01098B8D56C34A0158DF9916D192F"
|
||||
"841ADCA17FD630E1C0CBE652CAC6A52B6A1581BE4029CE6FAE0E04D2D2C7861187AF8299D8"
|
||||
"3E008DB9A2789672CA1DED903773D7E82B234CE2C799EB73CF80600C08F17EEDDDF369D2B8"
|
||||
"4A08292F22D1F18FE89521905E713BA674F2217881DBD7711B8C48D5FDCE6FAB51F935E293"
|
||||
"CB29191AB012B115FD2F5F23164B063D0A929C3E254BF0F4FA60051EB6B3498ED99FF77C19"
|
||||
"68E8CD83A35CEB054D05433FD0EA6AAE43C87DDA377591D1DCC1831EE130BFFF6D139A5ADA"
|
||||
"738B0F257CCE2649E71AB4050AAE020801121017DCBC27D11341D497135442A188DAA6188F"
|
||||
"89809105228E023082010A0282010100D21ADD7549D2748B3494526A9C3FB86C79376BBE8C"
|
||||
"8856F601B8D10461F77ACC7331B10DEBF365120056CDB5662D25907B74F12382F0F4A0CA47"
|
||||
"5EEA9562815C6228F6F698ADA27879D8890F2A2D96A746DDEF5316301C003519C2A2250354"
|
||||
"674169FDDA41CE14D3C52BEA7A20384515012D5952B38AA19E15E8563CC7AAA81C2122880A"
|
||||
"A370A64FEA23C53FB83AC3DB5753214730A349E07F64BF32BE7EAD30D02612AF110BB44FB0"
|
||||
"8E1D308173B327EF64D40C41639542B2D1A73C98A6607EC6C683B513A58470514106EF87AE"
|
||||
"1E7B9C695B93A104DF7437BFC4167789748A43ED208F2C1FA710793C688885EAE732A8BFDF"
|
||||
"5B423B23D75B88FC0ADC8FBDB5020301000128DD2212800372D2FB88098BA3B85B6B4354E0"
|
||||
"3767DBE2D7724663FB0A62ABF7704EA910E01F221349EE16D0152C769384050CE78520668C"
|
||||
"06CCFD3D789AF3EB69FF163615CD609169FDBE2E15A029D34AD2605625BC81844C9D1E2CE0"
|
||||
"519039F3799ADAEF86641E20B033DC16DF2E5B9A1A2A417B8BB3B7A4D9AD1A99367448587D"
|
||||
"A13DDE05A3ED9D62FA42078973B4AA40263D7BFA23F1072E94CDF323FA45F78408823E55C4"
|
||||
"F4C5C723819CF44CE6D98E50C04EC24D93B1AAB8877B9108B9CA391308E1A3645EBB0E7CAC"
|
||||
"BB40B5451560ED799421873BFB5ABB917FA60DB9C77CB8606AF7E3142626F5EA40E5CB8AA0"
|
||||
"89D8E7D6A9361935C426A4450EA8BC2E57290D3BF0A0962991D2A91B752FC80C3E7E4E5503"
|
||||
"3D71C94B325307A68815F026448F56A2741CEBEFC18E8C142F5F62BFAA67A291517DDE982D"
|
||||
"8CD5A9DF6E3D3A99B806F6D60991358C5BE77117D4F3168F3348E9A048539F892F4D783152"
|
||||
"C7A8095224AA56B78C5CF7BD1AB1B179C0C0D11E3C3BAC84C141A00191321E3ACC17242E68"
|
||||
"3C");
|
||||
const std::string kWrappedKey = wvcdm::a2bs_hex(
|
||||
"3B84252DD84F1A710365014A114507FFFA3DD404625D61D1EEC7C3A39D72CB8D9318ADE9DA"
|
||||
"05D69F9776DAFDA49A97BC30E84CA275925DFD98CA04F7DB23465103A224852192DE232902"
|
||||
"99FF82024F5CCA7716ACA9BE0B56348BA16B9E3136D73789C842CB2ECA4820DDAAF59CCB9B"
|
||||
"FCF2B4B0E2E5199FDCEC8DEBFFE50BB03041D8E767EA3FE6834C2E79E261ABF17B68EA66E1"
|
||||
"45AD0A6B056F39C06531A9038C996BADD524E57AE7D5339F13C574E7A398C03D65FD730BAC"
|
||||
"36F25347350DD2AD69EFA4DC040DC2D9DD4F53A729839FA3496CF580F2CBD51C3522DD67BC"
|
||||
"BA4A91E89E2BD70449F28E026638920A6DF7B9A0B2C977ACC65AE845E76EF81CADAA746DAF"
|
||||
"51D4D6FCBC083BE50DA1874D6EB1A30579B23C30881D94A8E5181FE20BF8F8C5F2522B1E7D"
|
||||
"092B1E20BDE5373F40286DE15267247F88C564BD4EBF4F69B889A03C9892584DC340D87EE1"
|
||||
"DFF2942D1B7E7EBD846349575F2DE6FDEF71BB005CFBEA845D87937BEBCAFEAC785A092C0A"
|
||||
"76CE7F7A4FE2F8E43045DED5202A2A55F547BA5DE67AF9E6B2B7DC89EFAD34AC0B40BF4B8F"
|
||||
"F82F8706B9A88FB9C7A0972E4A4B6CA970BF4F086573D595E5DB8ED0FDA4F9446ACD4B119C"
|
||||
"1E949C194B042A5CFFC13043FF79F049068A67CC1EB671A10EF7DA927753C4D149E9D0000D"
|
||||
"4307008BA0AED576ACCADF0CE6758F683087F26C2E38297B8C7D78DC3F1E8F24D7B3A0BED9"
|
||||
"C066F8348FD19CDB54A92C4E944EE11E11B3B44344E0DB0E1B4BD6CF9295AB66C05454776A"
|
||||
"8FE33AF659F67718AB43ACB52E83F8C29129DCE9654E8F1EBF9DAB9E933955E24389A37DBE"
|
||||
"17BA89AC8C750B025CB2F65D5C8BF32FED87EF368F15751AA2114159B6C9C6C814D0720DA4"
|
||||
"6E885BBB764ADC250D05F70306C3190991C31439BF273A33B6D1773E4FD089F32E753FA3C7"
|
||||
"7B5ED7DB28407D87396F1F8C83B58176EDFE1F923BDB7DA0ADE58CA2BCD6E76F9463BE7A5A"
|
||||
"909BE2731241BF1436F3E6A639FC7C717445D89AA5812E4532405B0FB368FE736E22D10FFD"
|
||||
"15FACCF69FAC468B5552C7887763B96578038CCF154F333E2095BBFF71D5C1235E032174FB"
|
||||
"44EAB4A753E7A917666A400EBE4F3D2C90100155C27F4B30C8ACFEDA6EFC763EF3556874E5"
|
||||
"8A5AB0AEBBF39990F79EF4D65EC4697D7BBEEF4F32AE8C4A8A94814A9BE532B5AC902BC0C5"
|
||||
"FB0A3E661AFF5961B6E79C82CC32FA7B7B48297347503FD58B110B93208167CC1FB96AD822"
|
||||
"42F60B9D2BF9CCEE8E778A3D3A3302303FB4E33F607D46AACE49D3546A993EDC6FBEE6E19D"
|
||||
"36831D85877013C57FE335F38D5CD9C3E09C1CEE28BC92C53A364663A7C031DF43B89BAAB4"
|
||||
"AA8176900FD483AD70E3844BD15EE4F01D8BE72186BBF9E019FCEE5961166696854D1A901F"
|
||||
"9D71B69B05F75FF233DB3C37F18DCADA640F68C4386F2E528CD77B93521A4574EF399375CD"
|
||||
"2BE7B9FDC0AE62249717B7E0022BF55C0D023669DD09355EAA90E9DF9BEA309DF7561423BF"
|
||||
"1DAD177F07A442E1591553924C0F67C2E86774009825490322A6B74319B4C77AA6195CA393"
|
||||
"03A311F762FB0FD445278D9ACF26A9049C5031BE91F2C4A6BE994CA5A3CEBC2ACCF93AB1EB"
|
||||
"993A6AA6DEB152DE8C9BB0E6B37B478393B50D1AAE99C086A0ED6D93BA7DD2DEEAB58EE34B"
|
||||
"C5EE06BE238E8DE6CB44211097C5C90D5C04857918856F86B7036986C20A43153892ED9093"
|
||||
"33EF70621A98184DDAB5E14BC971CF98CF6C91A37FFA83B00AD3BCABBAAB2DEF1C52F43003"
|
||||
"E74C92B44F9205D22262FB47948654229DE1920F8EDF96A19A88A1CA1552F8856FB4CBF83B"
|
||||
"AA3348419159D207F65FCE9C1A500C6818");
|
||||
} // namespace
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
// gmock methods
|
||||
using ::testing::_;
|
||||
using ::testing::Eq;
|
||||
using ::testing::NotNull;
|
||||
using ::testing::Return;
|
||||
using ::testing::SetArgPointee;
|
||||
using ::testing::StrEq;
|
||||
|
||||
class MockDeviceFiles : public DeviceFiles {
|
||||
public:
|
||||
MOCK_METHOD1(Init, bool(CdmSecurityLevel));
|
||||
MOCK_METHOD2(RetrieveCertificate, bool(std::string*, std::string*));
|
||||
};
|
||||
|
||||
class MockCryptoSession : public CryptoSession {
|
||||
public:
|
||||
MOCK_METHOD1(GetToken, bool(std::string*));
|
||||
MOCK_METHOD0(GetSecurityLevel, CdmSecurityLevel());
|
||||
MOCK_METHOD0(Open, CdmResponseType());
|
||||
MOCK_METHOD1(Open, CdmResponseType(SecurityLevel));
|
||||
MOCK_METHOD1(LoadCertificatePrivateKey, bool(std::string&));
|
||||
};
|
||||
|
||||
class MockPolicyEngine : public PolicyEngine {
|
||||
public:
|
||||
// Leaving a place holder for when PolicyEngine methods need to be mocked
|
||||
};
|
||||
|
||||
class MockCdmLicense : public CdmLicense {
|
||||
public:
|
||||
MOCK_METHOD3(Init, bool(const std::string&, CryptoSession*, PolicyEngine*));
|
||||
};
|
||||
|
||||
class CdmSessionTest : public ::testing::Test {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
license_parser_ = new MockCdmLicense();
|
||||
crypto_session_ = new MockCryptoSession();
|
||||
policy_engine_ = new MockPolicyEngine();
|
||||
file_handle_ = new MockDeviceFiles();
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
if (cdm_session_) delete cdm_session_;
|
||||
}
|
||||
|
||||
void CreateSession() {
|
||||
cdm_session_ = new CdmSession(license_parser_, crypto_session_,
|
||||
policy_engine_, file_handle_, NULL);
|
||||
}
|
||||
|
||||
void CreateSession(const CdmClientPropertySet* cdm_client_property_set) {
|
||||
cdm_session_ =
|
||||
new CdmSession(license_parser_, crypto_session_, policy_engine_,
|
||||
file_handle_, cdm_client_property_set);
|
||||
}
|
||||
|
||||
CdmSession* cdm_session_;
|
||||
MockCdmLicense* license_parser_;
|
||||
MockCryptoSession* crypto_session_;
|
||||
MockPolicyEngine* policy_engine_;
|
||||
MockDeviceFiles* file_handle_;
|
||||
};
|
||||
|
||||
TEST_F(CdmSessionTest, InitWithCertificate) {
|
||||
CdmSecurityLevel level = kSecurityLevelL1;
|
||||
EXPECT_CALL(*crypto_session_, GetSecurityLevel()).WillOnce(Return(level));
|
||||
EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault)))
|
||||
.WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
|
||||
EXPECT_CALL(*file_handle_, RetrieveCertificate(NotNull(), NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kToken), SetArgPointee<1>(kWrappedKey),
|
||||
Return(true)));
|
||||
EXPECT_CALL(*crypto_session_, LoadCertificatePrivateKey(StrEq(kWrappedKey)))
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(*license_parser_,
|
||||
Init(Eq(kToken), Eq(crypto_session_), Eq(policy_engine_)))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
Properties::set_use_certificates_as_identification(true);
|
||||
|
||||
CreateSession();
|
||||
ASSERT_EQ(NO_ERROR, cdm_session_->Init());
|
||||
}
|
||||
|
||||
TEST_F(CdmSessionTest, InitWithKeybox) {
|
||||
CdmSecurityLevel level = kSecurityLevelL1;
|
||||
EXPECT_CALL(*crypto_session_, GetSecurityLevel()).WillOnce(Return(level));
|
||||
EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault)))
|
||||
.WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(*crypto_session_, GetToken(NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kToken), Return(true)));
|
||||
EXPECT_CALL(*license_parser_,
|
||||
Init(Eq(kToken), Eq(crypto_session_), Eq(policy_engine_)))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
Properties::set_use_certificates_as_identification(false);
|
||||
|
||||
CreateSession();
|
||||
ASSERT_EQ(NO_ERROR, cdm_session_->Init());
|
||||
}
|
||||
|
||||
TEST_F(CdmSessionTest, ReInitFail) {
|
||||
CdmSecurityLevel level = kSecurityLevelL1;
|
||||
EXPECT_CALL(*crypto_session_, GetSecurityLevel()).WillOnce(Return(level));
|
||||
EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault)))
|
||||
.WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
|
||||
EXPECT_CALL(*file_handle_, RetrieveCertificate(NotNull(), NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kToken), SetArgPointee<1>(kWrappedKey),
|
||||
Return(true)));
|
||||
EXPECT_CALL(*crypto_session_, LoadCertificatePrivateKey(StrEq(kWrappedKey)))
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(*license_parser_,
|
||||
Init(Eq(kToken), Eq(crypto_session_), Eq(policy_engine_)))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
Properties::set_use_certificates_as_identification(true);
|
||||
|
||||
CreateSession();
|
||||
ASSERT_EQ(NO_ERROR, cdm_session_->Init());
|
||||
ASSERT_EQ(UNKNOWN_ERROR, cdm_session_->Init());
|
||||
}
|
||||
|
||||
TEST_F(CdmSessionTest, InitFailCryptoError) {
|
||||
CdmSecurityLevel level = kSecurityLevelL1;
|
||||
EXPECT_CALL(*crypto_session_, GetSecurityLevel()).WillOnce(Return(level));
|
||||
EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault)))
|
||||
.WillOnce(Return(UNKNOWN_ERROR));
|
||||
|
||||
Properties::set_use_certificates_as_identification(true);
|
||||
|
||||
CreateSession();
|
||||
ASSERT_EQ(UNKNOWN_ERROR, cdm_session_->Init());
|
||||
}
|
||||
|
||||
TEST_F(CdmSessionTest, InitNeedsProvisioning) {
|
||||
CdmSecurityLevel level = kSecurityLevelL1;
|
||||
EXPECT_CALL(*crypto_session_, GetSecurityLevel()).WillOnce(Return(level));
|
||||
EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault)))
|
||||
.WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
|
||||
EXPECT_CALL(*file_handle_, RetrieveCertificate(NotNull(), NotNull()))
|
||||
.WillOnce(Return(false));
|
||||
|
||||
Properties::set_use_certificates_as_identification(true);
|
||||
|
||||
CreateSession();
|
||||
ASSERT_EQ(NEED_PROVISIONING, cdm_session_->Init());
|
||||
}
|
||||
|
||||
} // wvcdm
|
||||
@@ -138,8 +138,7 @@ TEST_F(PolicyEngineTest, PlaybackFailed_CanPlayFalse) {
|
||||
policy->set_can_play(false);
|
||||
|
||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||
.WillOnce(Return(kLicenseStartTime + 1))
|
||||
.WillOnce(Return(kLicenseStartTime + 5));
|
||||
.WillOnce(Return(kLicenseStartTime + 1));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
EXPECT_FALSE(policy_engine_->can_decrypt());
|
||||
@@ -163,8 +162,8 @@ TEST_F(PolicyEngineTest, PlaybackFails_RentalDurationExpired) {
|
||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||
.WillOnce(Return(kLicenseStartTime + 1))
|
||||
.WillOnce(Return(kLicenseStartTime + 5))
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration))
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration + 1));
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration - 1))
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
|
||||
@@ -220,8 +219,8 @@ TEST_F(PolicyEngineTest, PlaybackFails_LicenseDurationExpired) {
|
||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||
.WillOnce(Return(kLicenseStartTime + 1))
|
||||
.WillOnce(Return(kLicenseStartTime + 5))
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration))
|
||||
.WillOnce(Return(kLicenseStartTime + 1 + min_duration));
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration - 1))
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
|
||||
@@ -248,8 +247,8 @@ TEST_F(PolicyEngineTest, PlaybackFails_ExpiryBeforeRenewalDelay) {
|
||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||
.WillOnce(Return(kLicenseStartTime + 1))
|
||||
.WillOnce(Return(kLicenseStartTime + 5))
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration))
|
||||
.WillOnce(Return(kLicenseStartTime + 1 + min_duration));
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration - 1))
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
|
||||
@@ -277,10 +276,10 @@ TEST_F(PolicyEngineTest, PlaybackOk_RentalDuration0) {
|
||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||
.WillOnce(Return(kLicenseStartTime + 1))
|
||||
.WillOnce(Return(kLicenseStartTime + 5))
|
||||
.WillOnce(Return(kLicenseStartTime + license_renewal_delay - 1))
|
||||
.WillOnce(Return(kLicenseStartTime + license_renewal_delay))
|
||||
.WillOnce(Return(kLicenseStartTime + 1 + license_renewal_delay))
|
||||
.WillOnce(Return(kLicenseStartTime + kStreamingLicenseDuration))
|
||||
.WillOnce(Return(kLicenseStartTime + 1 + kStreamingLicenseDuration));
|
||||
.WillOnce(Return(kLicenseStartTime + kStreamingLicenseDuration - 1))
|
||||
.WillOnce(Return(kLicenseStartTime + kStreamingLicenseDuration));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
|
||||
@@ -357,8 +356,8 @@ TEST_F(PolicyEngineTest, PlaybackOk_LicenseDuration0) {
|
||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||
.WillOnce(Return(kLicenseStartTime + 1))
|
||||
.WillOnce(Return(kLicenseStartTime + 5))
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration))
|
||||
.WillOnce(Return(kLicenseStartTime + 1 + min_duration));
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration - 1))
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
|
||||
@@ -387,8 +386,8 @@ TEST_F(PolicyEngineTest, PlaybackOk_Durations0) {
|
||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||
.WillOnce(Return(kLicenseStartTime + 1))
|
||||
.WillOnce(Return(kLicenseStartTime + 5))
|
||||
.WillOnce(Return(kLicenseStartTime + kHighDuration))
|
||||
.WillOnce(Return(kLicenseStartTime + kHighDuration + 10));
|
||||
.WillOnce(Return(kLicenseStartTime + kHighDuration - 1))
|
||||
.WillOnce(Return(kLicenseStartTime + kHighDuration));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
|
||||
@@ -406,6 +405,29 @@ TEST_F(PolicyEngineTest, PlaybackOk_Durations0) {
|
||||
EXPECT_TRUE(policy_engine_->can_decrypt());
|
||||
}
|
||||
|
||||
TEST_F(PolicyEngineTest, PlaybackOk_LicenseWithFutureStartTime) {
|
||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||
.WillOnce(Return(kLicenseStartTime - 100))
|
||||
.WillOnce(Return(kLicenseStartTime - 50))
|
||||
.WillOnce(Return(kLicenseStartTime))
|
||||
.WillOnce(Return(kLicenseStartTime + 10));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
|
||||
bool event_occurred;
|
||||
CdmEventType event;
|
||||
policy_engine_->OnTimerEvent(&event_occurred, &event);
|
||||
EXPECT_FALSE(event_occurred);
|
||||
EXPECT_FALSE(policy_engine_->can_decrypt());
|
||||
|
||||
policy_engine_->OnTimerEvent(&event_occurred, &event);
|
||||
EXPECT_FALSE(event_occurred);
|
||||
EXPECT_TRUE(policy_engine_->can_decrypt());
|
||||
|
||||
policy_engine_->BeginDecryption();
|
||||
EXPECT_TRUE(policy_engine_->can_decrypt());
|
||||
}
|
||||
|
||||
TEST_F(PolicyEngineTest, PlaybackFailed_CanRenewFalse) {
|
||||
License_Policy* policy = license_.mutable_policy();
|
||||
policy->set_can_renew(false);
|
||||
@@ -480,6 +502,49 @@ TEST_F(PolicyEngineTest, PlaybackOk_RenewSuccess) {
|
||||
EXPECT_TRUE(policy_engine_->can_decrypt());
|
||||
}
|
||||
|
||||
TEST_F(PolicyEngineTest, PlaybackOk_RenewSuccess_WithFutureStartTime) {
|
||||
int64_t license_renewal_delay =
|
||||
GetLicenseRenewalDelay(kStreamingLicenseDuration);
|
||||
|
||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||
.WillOnce(Return(kLicenseStartTime + 1))
|
||||
.WillOnce(Return(kLicenseStartTime + 5))
|
||||
.WillOnce(Return(kLicenseStartTime + license_renewal_delay - 15))
|
||||
.WillOnce(Return(kLicenseStartTime + license_renewal_delay + 10))
|
||||
.WillOnce(Return(kLicenseStartTime + license_renewal_delay + 20))
|
||||
.WillOnce(Return(kLicenseStartTime + license_renewal_delay + 30))
|
||||
.WillOnce(Return(kLicenseStartTime + license_renewal_delay + 60));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
|
||||
policy_engine_->BeginDecryption();
|
||||
EXPECT_TRUE(policy_engine_->can_decrypt());
|
||||
|
||||
bool event_occurred;
|
||||
CdmEventType event;
|
||||
policy_engine_->OnTimerEvent(&event_occurred, &event);
|
||||
EXPECT_FALSE(event_occurred);
|
||||
|
||||
policy_engine_->OnTimerEvent(&event_occurred, &event);
|
||||
EXPECT_TRUE(event_occurred);
|
||||
EXPECT_EQ(LICENSE_RENEWAL_NEEDED_EVENT, event);
|
||||
EXPECT_TRUE(policy_engine_->can_decrypt());
|
||||
|
||||
license_.set_license_start_time(kLicenseStartTime + license_renewal_delay +
|
||||
50);
|
||||
LicenseIdentification* id = license_.mutable_id();
|
||||
id->set_version(2);
|
||||
policy_engine_->UpdateLicense(license_);
|
||||
|
||||
policy_engine_->OnTimerEvent(&event_occurred, &event);
|
||||
EXPECT_FALSE(event_occurred);
|
||||
EXPECT_FALSE(policy_engine_->can_decrypt());
|
||||
|
||||
policy_engine_->OnTimerEvent(&event_occurred, &event);
|
||||
EXPECT_FALSE(event_occurred);
|
||||
EXPECT_TRUE(policy_engine_->can_decrypt());
|
||||
}
|
||||
|
||||
TEST_F(PolicyEngineTest, PlaybackFailed_RenewFailedVersionNotUpdated) {
|
||||
int64_t license_renewal_delay =
|
||||
GetLicenseRenewalDelay(kStreamingLicenseDuration);
|
||||
@@ -790,7 +855,7 @@ TEST_F(PolicyEngineTest, QuerySuccess) {
|
||||
ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
ss.clear();
|
||||
EXPECT_EQ(kStreamingLicenseDuration - 99, remaining_time);
|
||||
EXPECT_EQ(kStreamingLicenseDuration - 100, remaining_time);
|
||||
ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
EXPECT_EQ(kPlaybackDuration, remaining_time);
|
||||
@@ -816,7 +881,7 @@ TEST_F(PolicyEngineTest, QuerySuccess_PlaybackNotBegun) {
|
||||
std::istringstream ss;
|
||||
ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
EXPECT_EQ(kStreamingLicenseDuration - 99, remaining_time);
|
||||
EXPECT_EQ(kStreamingLicenseDuration - 100, remaining_time);
|
||||
ss.clear();
|
||||
ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
@@ -832,7 +897,7 @@ TEST_F(PolicyEngineTest, QuerySuccess_PlaybackNotBegun) {
|
||||
ss.clear();
|
||||
ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
EXPECT_EQ(kStreamingLicenseDuration - 199, remaining_time);
|
||||
EXPECT_EQ(kStreamingLicenseDuration - 200, remaining_time);
|
||||
ss.clear();
|
||||
ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
@@ -861,7 +926,7 @@ TEST_F(PolicyEngineTest, QuerySuccess_PlaybackBegun) {
|
||||
std::istringstream ss;
|
||||
ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
EXPECT_EQ(kStreamingLicenseDuration - 49, remaining_time);
|
||||
EXPECT_EQ(kStreamingLicenseDuration - 50, remaining_time);
|
||||
ss.clear();
|
||||
ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
@@ -885,7 +950,7 @@ TEST_F(PolicyEngineTest, QuerySuccess_PlaybackBegun) {
|
||||
ss.clear();
|
||||
ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
EXPECT_EQ(kStreamingLicenseDuration - 199, remaining_time);
|
||||
EXPECT_EQ(kStreamingLicenseDuration - 200, remaining_time);
|
||||
ss.clear();
|
||||
ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
@@ -931,7 +996,7 @@ TEST_F(PolicyEngineTest, QuerySuccess_Offline) {
|
||||
std::istringstream ss;
|
||||
ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
EXPECT_EQ(kOfflineLicenseDuration - 299, remaining_time);
|
||||
EXPECT_EQ(kOfflineLicenseDuration - 300, remaining_time);
|
||||
ss.clear();
|
||||
ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
@@ -952,8 +1017,7 @@ TEST_F(PolicyEngineTest, QuerySuccess_CanPlayFalse) {
|
||||
|
||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||
.WillOnce(Return(kLicenseStartTime + 1))
|
||||
.WillOnce(Return(kLicenseStartTime + 100))
|
||||
.WillOnce(Return(kLicenseStartTime + 200));
|
||||
.WillOnce(Return(kLicenseStartTime + 100));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
EXPECT_FALSE(policy_engine_->can_decrypt());
|
||||
@@ -977,7 +1041,7 @@ TEST_F(PolicyEngineTest, QuerySuccess_CanPlayFalse) {
|
||||
std::istringstream ss;
|
||||
ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
EXPECT_EQ(kOfflineLicenseDuration - 199, remaining_time);
|
||||
EXPECT_EQ(kOfflineLicenseDuration - 100, remaining_time);
|
||||
ss.clear();
|
||||
ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
@@ -995,8 +1059,8 @@ TEST_F(PolicyEngineTest, QuerySuccess_RentalDurationExpired) {
|
||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||
.WillOnce(Return(kLicenseStartTime + 1))
|
||||
.WillOnce(Return(kLicenseStartTime + 5))
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration - 1))
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration))
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration + 1))
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration + 5));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
@@ -1076,7 +1140,7 @@ TEST_F(PolicyEngineTest, QuerySuccess_PlaybackDurationExpired) {
|
||||
std::istringstream ss;
|
||||
ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
EXPECT_EQ(kHighDuration - 10004 - min_duration, remaining_time);
|
||||
EXPECT_EQ(kHighDuration - 10005 - min_duration, remaining_time);
|
||||
ss.clear();
|
||||
ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
@@ -1092,9 +1156,9 @@ TEST_F(PolicyEngineTest, QuerySuccess_LicenseDurationExpired) {
|
||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||
.WillOnce(Return(kLicenseStartTime + 1))
|
||||
.WillOnce(Return(kLicenseStartTime + 5))
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration - 1))
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration))
|
||||
.WillOnce(Return(kLicenseStartTime + 1 + min_duration))
|
||||
.WillOnce(Return(kLicenseStartTime + 5 + min_duration));
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration + 5));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
|
||||
@@ -1140,11 +1204,11 @@ TEST_F(PolicyEngineTest, QuerySuccess_RentalDuration0) {
|
||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||
.WillOnce(Return(kLicenseStartTime + 1))
|
||||
.WillOnce(Return(kLicenseStartTime + 5))
|
||||
.WillOnce(Return(kLicenseStartTime + license_renewal_delay - 1))
|
||||
.WillOnce(Return(kLicenseStartTime + license_renewal_delay))
|
||||
.WillOnce(Return(kLicenseStartTime + 1 + license_renewal_delay))
|
||||
.WillOnce(Return(kLicenseStartTime + kStreamingLicenseDuration - 1))
|
||||
.WillOnce(Return(kLicenseStartTime + kStreamingLicenseDuration))
|
||||
.WillOnce(Return(kLicenseStartTime + 1 + kStreamingLicenseDuration))
|
||||
.WillOnce(Return(kLicenseStartTime + 5 + kStreamingLicenseDuration));
|
||||
.WillOnce(Return(kLicenseStartTime + kStreamingLicenseDuration + 5));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
|
||||
@@ -1275,9 +1339,9 @@ TEST_F(PolicyEngineTest, QuerySuccess_LicenseDuration0) {
|
||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||
.WillOnce(Return(kLicenseStartTime + 1))
|
||||
.WillOnce(Return(kLicenseStartTime + 5))
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration - 1))
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration))
|
||||
.WillOnce(Return(kLicenseStartTime + 1 + min_duration))
|
||||
.WillOnce(Return(kLicenseStartTime + 5 + min_duration));
|
||||
.WillOnce(Return(kLicenseStartTime + min_duration + 5));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
|
||||
@@ -1325,7 +1389,7 @@ TEST_F(PolicyEngineTest, QuerySuccess_Durations0) {
|
||||
.WillOnce(Return(kLicenseStartTime + 1))
|
||||
.WillOnce(Return(kLicenseStartTime + 5))
|
||||
.WillOnce(Return(kLicenseStartTime + kHighDuration))
|
||||
.WillOnce(Return(kLicenseStartTime + kHighDuration + 10))
|
||||
.WillOnce(Return(kLicenseStartTime + kHighDuration + 9))
|
||||
.WillOnce(Return(kLicenseStartTime + kHighDuration + 15));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
@@ -1361,4 +1425,213 @@ TEST_F(PolicyEngineTest, QuerySuccess_Durations0) {
|
||||
EXPECT_EQ(LLONG_MAX, remaining_time);
|
||||
EXPECT_EQ(kRenewalServerUrl, query_info[QUERY_KEY_RENEWAL_SERVER_URL]);
|
||||
}
|
||||
|
||||
TEST_F(PolicyEngineTest, QuerySuccess_LicenseWithFutureStartTime) {
|
||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||
.WillOnce(Return(kLicenseStartTime - 100))
|
||||
.WillOnce(Return(kLicenseStartTime - 50))
|
||||
.WillOnce(Return(kLicenseStartTime - 10))
|
||||
.WillOnce(Return(kLicenseStartTime))
|
||||
.WillOnce(Return(kLicenseStartTime + 10))
|
||||
.WillOnce(Return(kLicenseStartTime + 25));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
|
||||
bool event_occurred;
|
||||
CdmEventType event;
|
||||
policy_engine_->OnTimerEvent(&event_occurred, &event);
|
||||
EXPECT_FALSE(event_occurred);
|
||||
EXPECT_FALSE(policy_engine_->can_decrypt());
|
||||
|
||||
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(kStreamingLicenseDuration, 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]);
|
||||
|
||||
EXPECT_FALSE(policy_engine_->can_decrypt());
|
||||
|
||||
policy_engine_->OnTimerEvent(&event_occurred, &event);
|
||||
EXPECT_FALSE(event_occurred);
|
||||
EXPECT_TRUE(policy_engine_->can_decrypt());
|
||||
policy_engine_->BeginDecryption();
|
||||
|
||||
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]);
|
||||
|
||||
ss.clear();
|
||||
ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
EXPECT_EQ(kStreamingLicenseDuration - 25, remaining_time);
|
||||
ss.clear();
|
||||
ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
EXPECT_EQ(kPlaybackDuration - 15, remaining_time);
|
||||
EXPECT_EQ(kRenewalServerUrl, query_info[QUERY_KEY_RENEWAL_SERVER_URL]);
|
||||
}
|
||||
|
||||
TEST_F(PolicyEngineTest, QuerySuccess_Renew) {
|
||||
int64_t license_renewal_delay =
|
||||
GetLicenseRenewalDelay(kStreamingLicenseDuration);
|
||||
|
||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||
.WillOnce(Return(kLicenseStartTime + 1))
|
||||
.WillOnce(Return(kLicenseStartTime + 5))
|
||||
.WillOnce(Return(kLicenseStartTime + license_renewal_delay - 25))
|
||||
.WillOnce(Return(kLicenseStartTime + license_renewal_delay + 10))
|
||||
.WillOnce(Return(kLicenseStartTime + license_renewal_delay + 20))
|
||||
.WillOnce(Return(kLicenseStartTime + license_renewal_delay +
|
||||
kLicenseRenewalRetryInterval + 10))
|
||||
.WillOnce(Return(kLicenseStartTime + license_renewal_delay +
|
||||
kLicenseRenewalRetryInterval + 15));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
|
||||
policy_engine_->BeginDecryption();
|
||||
EXPECT_TRUE(policy_engine_->can_decrypt());
|
||||
|
||||
bool event_occurred;
|
||||
CdmEventType event;
|
||||
policy_engine_->OnTimerEvent(&event_occurred, &event);
|
||||
EXPECT_FALSE(event_occurred);
|
||||
|
||||
policy_engine_->OnTimerEvent(&event_occurred, &event);
|
||||
EXPECT_TRUE(event_occurred);
|
||||
EXPECT_EQ(LICENSE_RENEWAL_NEEDED_EVENT, event);
|
||||
EXPECT_TRUE(policy_engine_->can_decrypt());
|
||||
|
||||
license_.set_license_start_time(kLicenseStartTime + license_renewal_delay +
|
||||
15);
|
||||
LicenseIdentification* id = license_.mutable_id();
|
||||
id->set_version(2);
|
||||
policy_engine_->UpdateLicense(license_);
|
||||
|
||||
policy_engine_->OnTimerEvent(&event_occurred, &event);
|
||||
EXPECT_FALSE(event_occurred);
|
||||
EXPECT_TRUE(policy_engine_->can_decrypt());
|
||||
|
||||
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(kStreamingLicenseDuration - kLicenseRenewalRetryInterval,
|
||||
remaining_time);
|
||||
ss.clear();
|
||||
ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
EXPECT_EQ(kPlaybackDuration + 5 - license_renewal_delay -
|
||||
kLicenseRenewalRetryInterval - 15,
|
||||
remaining_time);
|
||||
EXPECT_EQ(kRenewalServerUrl, query_info[QUERY_KEY_RENEWAL_SERVER_URL]);
|
||||
}
|
||||
|
||||
TEST_F(PolicyEngineTest, QuerySuccess_RenewWithFutureStartTime) {
|
||||
int64_t license_renewal_delay =
|
||||
GetLicenseRenewalDelay(kStreamingLicenseDuration);
|
||||
|
||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||
.WillOnce(Return(kLicenseStartTime + 1))
|
||||
.WillOnce(Return(kLicenseStartTime + 5))
|
||||
.WillOnce(Return(kLicenseStartTime + license_renewal_delay - 25))
|
||||
.WillOnce(Return(kLicenseStartTime + license_renewal_delay + 10))
|
||||
.WillOnce(Return(kLicenseStartTime + license_renewal_delay + 20))
|
||||
.WillOnce(Return(kLicenseStartTime + license_renewal_delay +
|
||||
kLicenseRenewalRetryInterval + 10))
|
||||
.WillOnce(Return(kLicenseStartTime + license_renewal_delay +
|
||||
kLicenseRenewalRetryInterval + 20))
|
||||
.WillOnce(Return(kLicenseStartTime + license_renewal_delay +
|
||||
kLicenseRenewalRetryInterval + 30))
|
||||
.WillOnce(Return(kLicenseStartTime + license_renewal_delay +
|
||||
kLicenseRenewalRetryInterval + 40));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
|
||||
policy_engine_->BeginDecryption();
|
||||
EXPECT_TRUE(policy_engine_->can_decrypt());
|
||||
|
||||
bool event_occurred;
|
||||
CdmEventType event;
|
||||
policy_engine_->OnTimerEvent(&event_occurred, &event);
|
||||
EXPECT_FALSE(event_occurred);
|
||||
|
||||
policy_engine_->OnTimerEvent(&event_occurred, &event);
|
||||
EXPECT_TRUE(event_occurred);
|
||||
EXPECT_EQ(LICENSE_RENEWAL_NEEDED_EVENT, event);
|
||||
EXPECT_TRUE(policy_engine_->can_decrypt());
|
||||
|
||||
license_.set_license_start_time(kLicenseStartTime + license_renewal_delay +
|
||||
kLicenseRenewalRetryInterval + 20);
|
||||
LicenseIdentification* id = license_.mutable_id();
|
||||
id->set_version(2);
|
||||
policy_engine_->UpdateLicense(license_);
|
||||
|
||||
policy_engine_->OnTimerEvent(&event_occurred, &event);
|
||||
EXPECT_FALSE(event_occurred);
|
||||
EXPECT_FALSE(policy_engine_->can_decrypt());
|
||||
|
||||
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(kStreamingLicenseDuration, remaining_time);
|
||||
ss.clear();
|
||||
ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
EXPECT_EQ(kPlaybackDuration + 5 - license_renewal_delay -
|
||||
kLicenseRenewalRetryInterval - 20,
|
||||
remaining_time);
|
||||
EXPECT_EQ(kRenewalServerUrl, query_info[QUERY_KEY_RENEWAL_SERVER_URL]);
|
||||
|
||||
policy_engine_->OnTimerEvent(&event_occurred, &event);
|
||||
EXPECT_FALSE(event_occurred);
|
||||
EXPECT_TRUE(policy_engine_->can_decrypt());
|
||||
|
||||
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]);
|
||||
|
||||
ss.clear();
|
||||
ss.str(query_info[QUERY_KEY_LICENSE_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
EXPECT_EQ(kStreamingLicenseDuration - 20, remaining_time);
|
||||
ss.clear();
|
||||
ss.str(query_info[QUERY_KEY_PLAYBACK_DURATION_REMAINING]);
|
||||
ss >> remaining_time;
|
||||
EXPECT_EQ(kPlaybackDuration + 5 - license_renewal_delay -
|
||||
kLicenseRenewalRetryInterval - 40,
|
||||
remaining_time);
|
||||
EXPECT_EQ(kRenewalServerUrl, query_info[QUERY_KEY_RENEWAL_SERVER_URL]);
|
||||
}
|
||||
|
||||
} // wvcdm
|
||||
|
||||
Reference in New Issue
Block a user