Source release v3.0.1 + third_party

This commit is contained in:
Joey Parrish
2015-09-11 16:15:34 -07:00
parent 0546ee6732
commit b5d6be97cb
32 changed files with 1344 additions and 129 deletions

View File

@@ -32,6 +32,7 @@
# Make sure that a valid config.h for your target is in the source tree.
'protobuf_config%': 'source',
'protobuf_source%': '../third_party/protobuf',
'protoc_host_target%': 'dummy',
}, # variables
'conditions': [
['protobuf_config=="source"', {
@@ -187,5 +188,9 @@
],
},
},
{
'target_name': 'dummy',
'type': 'none',
},
],
}

View File

@@ -19,6 +19,9 @@
'test/test_host.cpp',
'test/test_host.h',
],
'variables': {
'cdm_dir': '..',
},
'includes': [
'oemcrypto_unittests.gypi',
'core_unittests.gypi',

View File

@@ -27,6 +27,10 @@
'CORE_TESTS',
],
'dependencies': [
'cdm.gyp:license_protocol',
# This gypi may be included from outside this folder, and dependencies in
# a gypi are relative to the gyp file doing the including.
# cdm_dir is a variable the including file must set to help us find the
# correct path.
'<(cdm_dir)/cdm/cdm.gyp:license_protocol',
],
}

View File

@@ -34,7 +34,17 @@ typedef __int64 int64_t;
namespace widevine {
class CDM_EXPORT Cdm {
class CDM_EXPORT ITimerClient {
public:
// Called by ITimer when a timer expires.
virtual void onTimerExpired(void* context) = 0;
protected:
ITimerClient() {}
virtual ~ITimerClient() {}
};
class CDM_EXPORT Cdm : public ITimerClient {
public:
// Session types defined by EME.
typedef enum {
@@ -179,21 +189,17 @@ class CDM_EXPORT Cdm {
// See Cdm::initialize().
class ITimer {
public:
class IClient {
public:
// Called by ITimer when a timer expires.
virtual void onTimerExpired(void* context) = 0;
protected:
IClient() {}
virtual ~IClient() {}
};
// This typedef is for backward compatibility with v3.0.0.
typedef ITimerClient IClient;
// Call |client->onTimerExpired(context)| after a delay of |delay_ms| ms.
virtual void setTimeout(int64_t delay_ms,
IClient* client,
void* context) = 0;
// Cancel all timers associated with |client|.
virtual void cancel(IClient *client) = 0;
protected:
ITimer() {}
virtual ~ITimer() {}
@@ -425,6 +431,27 @@ class CDM_EXPORT Cdm {
virtual Status decrypt(const InputBuffer& input,
const OutputBuffer& output) = 0;
// Sets a value in the custom app settings. These are settings
// that are sent with any message to the license server. These methods
// should only be used by advanced users maintaining existing systems.
// The |key| cannot be empty.
virtual Status setAppParameter(const std::string& key,
const std::string& value) = 0;
// Gets the current value in the custom app settings. If the key is
// not present, then kInvalidAccess is returned. The |key| cannot be
// empty. |result| cannot be null. See setAppParameter().
virtual Status getAppParameter(const std::string& key,
std::string* result) = 0;
// Removes the value in the custom app settings. If the key is not
// present, then kInvalidAccess is returned. The |key| cannot be empty.
// See setAppParameter().
virtual Status removeAppParameter(const std::string& key) = 0;
// Clears all the values in the custom app settings. See setAppParameter().
virtual Status clearAppParameters() = 0;
protected:
Cdm() {}
};

View File

@@ -1,2 +1,2 @@
// Widevine CE CDM Version
#define CDM_VERSION "v3.0.0-0-g8d3792b-ce"
#define CDM_VERSION "v3.0.1-0-g41710d9-ce"

View File

@@ -105,7 +105,6 @@ class PropertySet : public CdmClientPropertySet {
};
class CdmImpl : public Cdm,
public Cdm::ITimer::IClient,
public WvCdmEventListener {
public:
CdmImpl(IEventListener* listener,
@@ -134,6 +133,16 @@ class CdmImpl : public Cdm,
virtual Status getKeyStatuses(const std::string& session_id,
KeyStatusMap* key_statuses) OVERRIDE;
virtual Status setAppParameter(const std::string& key,
const std::string& value) OVERRIDE;
virtual Status getAppParameter(const std::string& key,
std::string* result) OVERRIDE;
virtual Status removeAppParameter(const std::string& key) OVERRIDE;
virtual Status clearAppParameters() OVERRIDE;
virtual Status close(const std::string& session_id) OVERRIDE;
virtual Status remove(const std::string& session_id) OVERRIDE;
@@ -141,7 +150,7 @@ class CdmImpl : public Cdm,
virtual Status decrypt(const InputBuffer& input,
const OutputBuffer& output) OVERRIDE;
// ITimer::IClient:
// ITimerClient:
virtual void onTimerExpired(void* context) OVERRIDE;
// WvCdmEventListener:
@@ -160,6 +169,7 @@ class CdmImpl : public Cdm,
CdmEngine cdm_engine_;
PropertySet property_set_;
CdmAppParameterMap app_parameters_;
std::map<std::string, SessionType> new_session_types_;
std::map<std::string, int64_t> session_expirations_;
@@ -173,7 +183,9 @@ CdmImpl::CdmImpl(IEventListener* listener,
property_set_.set_use_privacy_mode(privacy_mode);
}
CdmImpl::~CdmImpl() {}
CdmImpl::~CdmImpl() {
host.timer->cancel(this);
}
Cdm::Status CdmImpl::setServerCertificate(const std::string& certificate) {
if (!property_set_.use_privacy_mode()) {
@@ -283,14 +295,13 @@ Cdm::Status CdmImpl::generateRequest(const std::string& session_id,
return kInvalidAccess;
}
CdmAppParameterMap empty_app_parameters;
std::string key_request;
CdmKeyRequestType key_request_type;
std::string ignored_server_url;
CdmResponseType result = cdm_engine_.GenerateKeyRequest(
session_id, session_id, init_data_obj,
license_type, empty_app_parameters, &key_request, &key_request_type,
license_type, app_parameters_, &key_request, &key_request_type,
&ignored_server_url, NULL);
if (result != KEY_MESSAGE) {
@@ -349,13 +360,12 @@ Cdm::Status CdmImpl::load(const std::string& session_id) {
// This was partially removed already.
// The EME spec states that we should send a release message right away.
InitializationData empty_initialization_data;
CdmAppParameterMap empty_app_parameters;
CdmKeyMessage key_request;
std::string ignored_server_url;
CdmResponseType result = cdm_engine_.GenerateKeyRequest(
session_id, session_id, empty_initialization_data,
kLicenseTypeRelease, empty_app_parameters, &key_request, NULL,
kLicenseTypeRelease, app_parameters_, &key_request, NULL,
&ignored_server_url, NULL);
if (result != KEY_MESSAGE) {
LOGE("Unexpected error %d", result);
@@ -412,14 +422,13 @@ Cdm::Status CdmImpl::update(const std::string& session_id,
// The underlying session in CdmEngine has stored a copy of the original
// init data, so we can use an empty one this time.
InitializationData empty_init_data;
CdmAppParameterMap empty_app_parameters;
std::string key_request;
CdmKeyRequestType key_request_type;
std::string ignored_server_url;
CdmResponseType result = cdm_engine_.GenerateKeyRequest(
session_id, session_id, empty_init_data, kLicenseTypeDeferred,
empty_app_parameters, &key_request, &key_request_type,
app_parameters_, &key_request, &key_request_type,
&ignored_server_url, NULL);
if (result != KEY_MESSAGE) {
@@ -476,6 +485,42 @@ Cdm::Status CdmImpl::getKeyStatuses(const std::string& session_id,
return kSuccess;
}
Cdm::Status CdmImpl::setAppParameter(const std::string& key,
const std::string& value) {
if (key.empty()) {
return kInvalidAccess;
}
app_parameters_[key] = value;
return kSuccess;
}
Cdm::Status CdmImpl::getAppParameter(const std::string& key,
std::string* result) {
if (NULL == result || key.empty() ||
app_parameters_.find(key) == app_parameters_.end()) {
return kInvalidAccess;
}
*result = app_parameters_[key];
return kSuccess;
}
Cdm::Status CdmImpl::removeAppParameter(const std::string& key) {
if (key.empty()) {
return kInvalidAccess;
}
CdmAppParameterMap::iterator it = app_parameters_.find(key);
if (it == app_parameters_.end()) {
return kInvalidAccess;
}
app_parameters_.erase(it);
return kSuccess;
}
Cdm::Status CdmImpl::clearAppParameters() {
app_parameters_.clear();
return kSuccess;
}
Cdm::Status CdmImpl::close(const std::string& session_id) {
if (!cdm_engine_.IsOpenSession(session_id)) {
LOGE("No such session: %s", session_id.c_str());
@@ -507,13 +552,12 @@ Cdm::Status CdmImpl::remove(const std::string& session_id) {
}
InitializationData empty_initialization_data;
CdmAppParameterMap empty_app_parameters;
CdmKeyMessage key_request;
std::string ignored_server_url;
CdmResponseType result = cdm_engine_.GenerateKeyRequest(
session_id, session_id, empty_initialization_data,
kLicenseTypeRelease, empty_app_parameters, &key_request, NULL,
kLicenseTypeRelease, app_parameters_, &key_request, NULL,
&ignored_server_url, NULL);
if (result != KEY_MESSAGE) {
LOGE("Unexpected error %d", result);

View File

@@ -10,6 +10,7 @@
#include "cdm_test_printers.h"
#include "license_request.h"
#include "log.h"
#include "OEMCryptoCENC.h"
#include "override.h"
#include "properties_ce.h"
#include "scoped_ptr.h"
@@ -103,6 +104,12 @@ const std::vector<uint8_t> kOutput1 = a2b_hex(
"4884604c8da8a53ce33db9ff8f1c5bb6bb97f37b39906bf41596555c1bcce9ed"
"08a899cd760ff0899a1170c2f224b9c52997a0785b7fe170805fd3e8b1127659");
const std::string kValue = "A Value";
const std::string kNewValue = "A New Value";
const std::string kParamName = "PARAM";
const std::string kParamName2 = "PARAM2";
class CdmTest : public Test,
public Cdm::IEventListener {
@@ -423,6 +430,20 @@ TEST_F(CdmTest, Initialize) {
}
TEST_F(CdmTest, DeviceCertificateRequest) {
uint32_t nonce = 0;
uint8_t buffer[1];
size_t size = 0;
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_Initialize());
int result = OEMCrypto_RewrapDeviceRSAKey(
0, buffer, 0, buffer, 0, &nonce, buffer, 0, buffer, buffer, &size);
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_Terminate());
if (result == OEMCrypto_ERROR_NOT_IMPLEMENTED) {
LOGW("WARNING: Skipping DeviceCertificateRequest because the device does "
"not support provisioning. If you are using a baked-in certificate, "
"this is expected. Otherwise, something is wrong.");
return;
}
// Clear any existing certificates.
g_host->remove("cert.bin");
@@ -1075,4 +1096,84 @@ TEST_F(CdmTest, ServerCertificateProvisioning) {
Mock::VerifyAndClear(this);
}
TEST_F(CdmTest, SetAppParameters) {
// Must use privacy_mode = false to ensure that the message is in plain-text.
std::string session_id;
ASSERT_NO_FATAL_FAILURE(RecreateCdm(false /* privacy_mode */));
Cdm::Status status = cdm_->createSession(Cdm::kTemporary, &session_id);
ASSERT_EQ(Cdm::kSuccess, status);
// Set a new app parameter, and check by getting.
std::string result;
status = cdm_->setAppParameter(kParamName, kValue);
ASSERT_EQ(Cdm::kSuccess, status);
status = cdm_->getAppParameter(kParamName, &result);
ASSERT_EQ(Cdm::kSuccess, status);
ASSERT_EQ(kValue, result);
// Try to get using a null result.
status = cdm_->getAppParameter(kParamName, NULL);
ASSERT_EQ(Cdm::kInvalidAccess, status);
// Try to get using an empty key.
status = cdm_->getAppParameter("", &result);
ASSERT_EQ(Cdm::kInvalidAccess, status);
// Try to set using an empty key.
status = cdm_->setAppParameter("", kValue);
ASSERT_EQ(Cdm::kInvalidAccess, status);
// Try to remove using an empty key.
status = cdm_->removeAppParameter("");
ASSERT_EQ(Cdm::kInvalidAccess, status);
// Change an existing app parameter.
status = cdm_->setAppParameter(kParamName, kNewValue);
ASSERT_EQ(Cdm::kSuccess, status);
status = cdm_->getAppParameter(kParamName, &result);
ASSERT_EQ(Cdm::kSuccess, status);
ASSERT_EQ(kNewValue, result);
// Remove an existing app parameter, check for invalid access when it's gone.
status = cdm_->removeAppParameter(kParamName);
ASSERT_EQ(Cdm::kSuccess, status);
status = cdm_->getAppParameter(kParamName, &result);
ASSERT_EQ(Cdm::kInvalidAccess, status);
// Try to remove an absent value.
status = cdm_->removeAppParameter(kParamName2);
ASSERT_EQ(Cdm::kInvalidAccess, status);
// Set some values to check for.
status = cdm_->setAppParameter(kParamName, kValue);
ASSERT_EQ(Cdm::kSuccess, status);
status = cdm_->setAppParameter(kParamName2, kNewValue);
ASSERT_EQ(Cdm::kSuccess, status);
// Send a generate request to ensure the parameter is in the message.
std::string message;
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _)).WillOnce(
SaveArg<2>(&message));
status = cdm_->generateRequest(session_id, Cdm::kCenc, kCencInitData);
EXPECT_EQ(Cdm::kSuccess, status);
EXPECT_TRUE(!message.empty() && message.find(kValue) != std::string::npos);
Mock::VerifyAndClear(this);
// Ensure that the value is still present and correct.
status = cdm_->getAppParameter(kParamName, &result);
ASSERT_EQ(Cdm::kSuccess, status);
ASSERT_EQ(kValue, result);
status = cdm_->getAppParameter(kParamName2, &result);
ASSERT_EQ(Cdm::kSuccess, status);
ASSERT_EQ(kNewValue, result);
// Clear all the parameters.
status = cdm_->clearAppParameters();
ASSERT_EQ(Cdm::kSuccess, status);
status = cdm_->getAppParameter(kParamName, &result);
ASSERT_EQ(Cdm::kInvalidAccess, status);
status = cdm_->getAppParameter(kParamName2, &result);
ASSERT_EQ(Cdm::kInvalidAccess, status);
}
} // namespace widevine

View File

@@ -91,3 +91,20 @@ void TestHost::setTimeout(int64_t delay_ms,
int64_t expiry_time = now_ + delay_ms;
timers_.push(Timer(expiry_time, client, context));
}
void TestHost::cancel(IClient* client) {
// Filter out the timers for this client and put the rest into |others|.
std::priority_queue<Timer> others;
while (timers_.size()) {
Timer t = timers_.top();
timers_.pop();
if (t.client != client) {
others.push(t);
}
}
// Now swap the queues.
timers_.swap(others);
}

View File

@@ -30,6 +30,7 @@ class TestHost : public widevine::Cdm::IStorage,
virtual void setTimeout(int64_t delay_ms,
IClient* client,
void* context) OVERRIDE;
virtual void cancel(IClient* client) OVERRIDE;
private:
struct Timer {