Merge "Support Per-Origin Provisioning"

This commit is contained in:
John "Juce" Bruce
2015-04-10 18:20:54 +00:00
committed by Android (Google) Code Review
19 changed files with 627 additions and 313 deletions

View File

@@ -32,13 +32,14 @@ class CdmEngine {
// Session related methods
virtual CdmResponseType OpenSession(const CdmKeySystem& key_system,
const CdmClientPropertySet* property_set,
const std::string& origin,
WvCdmEventListener* event_listener,
CdmSessionId* session_id);
virtual CdmResponseType CloseSession(const CdmSessionId& session_id);
virtual CdmResponseType OpenKeySetSession(
const CdmKeySetId& key_set_id, const CdmClientPropertySet* property_set,
WvCdmEventListener* event_listener);
const std::string& origin, WvCdmEventListener* event_listener);
virtual CdmResponseType CloseKeySetSession(const CdmKeySetId& key_set_id);
// License related methods
@@ -113,13 +114,18 @@ class CdmEngine {
// Provisioning related methods
virtual CdmResponseType GetProvisioningRequest(
CdmCertificateType cert_type, const std::string& cert_authority,
CdmProvisioningRequest* request, std::string* default_url);
const std::string& origin, CdmProvisioningRequest* request,
std::string* default_url);
virtual CdmResponseType HandleProvisioningResponse(
CdmProvisioningResponse& response, std::string* cert,
std::string* wrapped_key);
const std::string& origin, CdmProvisioningResponse& response,
std::string* cert, std::string* wrapped_key);
virtual CdmResponseType Unprovision(CdmSecurityLevel security_level);
virtual bool IsProvisioned(CdmSecurityLevel security_level,
const std::string& origin);
virtual CdmResponseType Unprovision(CdmSecurityLevel security_level,
const std::string& origin);
// Usage related methods for streaming licenses
// Retrieve a random usage info from the list of all usage infos for this app

View File

@@ -4,6 +4,7 @@
#define WVCDM_CORE_CDM_SESSION_H_
#include <set>
#include <string>
#include "crypto_session.h"
#include "device_files.h"
@@ -22,7 +23,7 @@ class WvCdmEventListener;
class CdmSession {
public:
CdmSession(const CdmClientPropertySet* cdm_client_property_set,
WvCdmEventListener* event_listener);
const std::string& origin, WvCdmEventListener* event_listener);
virtual ~CdmSession();
virtual CdmResponseType Init();
@@ -128,6 +129,7 @@ class CdmSession {
// instance variables
bool initialized_;
CdmSessionId session_id_;
const std::string origin_;
scoped_ptr<CdmLicense> license_parser_;
scoped_ptr<CryptoSession> crypto_session_;
scoped_ptr<PolicyEngine> policy_engine_;

View File

@@ -3,6 +3,8 @@
#ifndef WVCDM_CORE_CERTIFICATE_PROVISIONING_H_
#define WVCDM_CORE_CERTIFICATE_PROVISIONING_H_
#include <string>
#include "crypto_session.h"
#include "oemcrypto_adapter.h"
#include "wv_cdm_types.h"
@@ -20,9 +22,11 @@ class CertificateProvisioning {
CdmResponseType GetProvisioningRequest(SecurityLevel requested_security_level,
CdmCertificateType cert_type,
const std::string& cert_authority,
const std::string& origin,
CdmProvisioningRequest* request,
std::string* default_url);
CdmResponseType HandleProvisioningResponse(CdmProvisioningResponse& response,
CdmResponseType HandleProvisioningResponse(const std::string& origin,
CdmProvisioningResponse& response,
std::string* cert,
std::string* wrapped_key);

View File

@@ -4,6 +4,7 @@
#define WVCDM_CORE_DEVICE_FILES_H_
#include <unistd.h>
#include <string>
#include "scoped_ptr.h"
#include "wv_cdm_types.h"
@@ -32,10 +33,14 @@ class DeviceFiles {
return Init(security_level);
}
virtual bool StoreCertificate(const std::string& certificate,
virtual bool StoreCertificate(const std::string& origin,
const std::string& certificate,
const std::string& wrapped_private_key);
virtual bool RetrieveCertificate(std::string* certificate,
virtual bool RetrieveCertificate(const std::string& origin,
std::string* certificate,
std::string* wrapped_private_key);
virtual bool HasCertificate(const std::string& origin);
virtual bool RemoveCertificate(const std::string& origin);
virtual bool StoreLicense(const std::string& key_set_id,
const LicenseState state,
@@ -100,18 +105,21 @@ class DeviceFiles {
// stored in a common directory and need to be copied over.
virtual void SecurityLevelPathBackwardCompatibility();
// For testing only:
static std::string GetCertificateFileName();
static std::string GetCertificateFileName(const std::string& origin);
static std::string GetLicenseFileNameExtension();
static std::string GetUsageInfoFileName(const std::string& app_id);
static std::string GetBlankFileData();
static std::string GetFileNameSafeHash(const std::string& input);
// For testing only:
void SetTestFile(File* file);
#if defined(UNIT_TEST)
FRIEND_TEST(DeviceFilesSecurityLevelTest, SecurityLevel);
FRIEND_TEST(DeviceFilesStoreTest, StoreCertificate);
FRIEND_TEST(DeviceCertificateStoreTest, StoreCertificate);
FRIEND_TEST(DeviceCertificateTest, ReadCertificate);
FRIEND_TEST(DeviceCertificateTest, HasCertificate);
FRIEND_TEST(DeviceFilesStoreTest, StoreLicense);
FRIEND_TEST(DeviceFilesTest, DeleteLicense);
FRIEND_TEST(DeviceFilesTest, ReadCertificate);
FRIEND_TEST(DeviceFilesTest, ReserveLicenseIds);
FRIEND_TEST(DeviceFilesTest, RetrieveLicenses);
FRIEND_TEST(DeviceFilesTest, SecurityLevelPathBackwardCompatibility);

View File

@@ -75,6 +75,8 @@ static const std::string WEBM_VIDEO_MIME_TYPE = "video/webm";
static const std::string WEBM_AUDIO_MIME_TYPE = "audio/webm";
static const std::string CENC_INIT_DATA_FORMAT = "cenc";
static const std::string WEBM_INIT_DATA_FORMAT = "webm";
static const char EMPTY_ORIGIN[] = "";
} // namespace wvcdm
#endif // WVCDM_CORE_WV_CDM_CONSTANTS_H_

View File

@@ -76,6 +76,7 @@ CdmEngine::~CdmEngine() {
CdmResponseType CdmEngine::OpenSession(const CdmKeySystem& key_system,
const CdmClientPropertySet* property_set,
const std::string& origin,
WvCdmEventListener* event_listener,
CdmSessionId* session_id) {
LOGI("CdmEngine::OpenSession");
@@ -91,7 +92,7 @@ CdmResponseType CdmEngine::OpenSession(const CdmKeySystem& key_system,
}
scoped_ptr<CdmSession> new_session(
new CdmSession(property_set, event_listener));
new CdmSession(property_set, origin, event_listener));
if (new_session->session_id().empty()) {
LOGE("CdmEngine::OpenSession: failure to generate session ID");
return UNKNOWN_ERROR;
@@ -115,7 +116,7 @@ CdmResponseType CdmEngine::OpenSession(const CdmKeySystem& key_system,
CdmResponseType CdmEngine::OpenKeySetSession(
const CdmKeySetId& key_set_id, const CdmClientPropertySet* property_set,
WvCdmEventListener* event_listener) {
const std::string& origin, WvCdmEventListener* event_listener) {
LOGI("CdmEngine::OpenKeySetSession");
if (key_set_id.empty()) {
@@ -125,7 +126,8 @@ CdmResponseType CdmEngine::OpenKeySetSession(
CdmSessionId session_id;
CdmResponseType sts =
OpenSession(KEY_SYSTEM, property_set, event_listener, &session_id);
OpenSession(KEY_SYSTEM, property_set, origin, event_listener,
&session_id);
if (sts != NO_ERROR) return sts;
@@ -503,9 +505,10 @@ CdmResponseType CdmEngine::QueryKeyControlInfo(const CdmSessionId& session_id,
*/
CdmResponseType CdmEngine::GetProvisioningRequest(
CdmCertificateType cert_type, const std::string& cert_authority,
CdmProvisioningRequest* request, std::string* default_url) {
const std::string& origin, CdmProvisioningRequest* request,
std::string* default_url) {
if (!request || !default_url) {
LOGE("CdmEngine::GetProvisioningRequest: invalid input parameters");
LOGE("CdmEngine::GetProvisioningRequest: invalid output parameters");
return UNKNOWN_ERROR;
}
if (NULL == cert_provisioning_.get()) {
@@ -513,7 +516,7 @@ CdmResponseType CdmEngine::GetProvisioningRequest(
}
CdmResponseType ret = cert_provisioning_->GetProvisioningRequest(
cert_provisioning_requested_security_level_, cert_type, cert_authority,
request, default_url);
origin, request, default_url);
if (ret != NO_ERROR) {
cert_provisioning_.reset(NULL); // Release resources.
}
@@ -528,8 +531,8 @@ CdmResponseType CdmEngine::GetProvisioningRequest(
* Returns NO_ERROR for success and UNKNOWN_ERROR if fails.
*/
CdmResponseType CdmEngine::HandleProvisioningResponse(
CdmProvisioningResponse& response, std::string* cert,
std::string* wrapped_key) {
const std::string& origin, CdmProvisioningResponse& response,
std::string* cert, std::string* wrapped_key) {
if (response.empty()) {
LOGE("CdmEngine::HandleProvisioningResponse: Empty provisioning response.");
cert_provisioning_.reset(NULL);
@@ -553,35 +556,55 @@ CdmResponseType CdmEngine::HandleProvisioningResponse(
return UNKNOWN_ERROR;
}
CdmResponseType ret = cert_provisioning_->HandleProvisioningResponse(
response, cert, wrapped_key);
origin, response, cert, wrapped_key);
cert_provisioning_.reset(NULL); // Release resources.
return ret;
}
CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level) {
bool CdmEngine::IsProvisioned(CdmSecurityLevel security_level,
const std::string& origin) {
DeviceFiles handle;
if (!handle.Init(security_level)) {
LOGE("CdmEngine::IsProvisioned: unable to initialize device files");
return false;
}
return handle.HasCertificate(origin);
}
CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level,
const std::string& origin) {
DeviceFiles handle;
if (!handle.Init(security_level)) {
LOGE("CdmEngine::Unprovision: unable to initialize device files");
return UNKNOWN_ERROR;
}
if (!handle.DeleteAllFiles()) {
LOGE("CdmEngine::Unprovision: unable to delete files");
return UNKNOWN_ERROR;
}
if (origin != EMPTY_ORIGIN) {
if (!handle.RemoveCertificate(origin)) {
LOGE("CdmEngine::Unprovision: unable to delete certificate for origin %s",
origin.c_str());
return UNKNOWN_ERROR;
}
return NO_ERROR;
} else {
if (!handle.DeleteAllFiles()) {
LOGE("CdmEngine::Unprovision: unable to delete files");
return UNKNOWN_ERROR;
}
scoped_ptr<CryptoSession> crypto_session(new CryptoSession());
CdmResponseType status = crypto_session->Open(
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault);
if (NO_ERROR != status) {
LOGE("CdmEngine::Unprovision: error opening crypto session: %d", status);
return UNKNOWN_ERROR;
scoped_ptr<CryptoSession> crypto_session(new CryptoSession());
CdmResponseType status = crypto_session->Open(
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault);
if (NO_ERROR != status) {
LOGE("CdmEngine::Unprovision: error opening crypto session: %d", status);
return UNKNOWN_ERROR;
}
status = crypto_session->DeleteAllUsageReports();
if (status != NO_ERROR) {
LOGE("CdmEngine::Unprovision: error deleteing usage reports: %d", status);
}
return status;
}
status = crypto_session->DeleteAllUsageReports();
if (status != NO_ERROR) {
LOGE("CdmEngine::Unprovision: error deleteing usage reports: %d", status);
}
return status;
}
CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
@@ -592,7 +615,8 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
}
usage_property_set_->set_security_level(kLevelDefault);
usage_property_set_->set_app_id(app_id);
usage_session_.reset(new CdmSession(usage_property_set_.get(), NULL));
usage_session_.reset(
new CdmSession(usage_property_set_.get(), EMPTY_ORIGIN, NULL));
CdmResponseType status = usage_session_->Init();
if (NO_ERROR != status) {
LOGE("CdmEngine::GetUsageInfo: session init error");
@@ -610,7 +634,8 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
&license_response)) {
usage_property_set_->set_security_level(kLevel3);
usage_property_set_->set_app_id(app_id);
usage_session_.reset(new CdmSession(usage_property_set_.get(), NULL));
usage_session_.reset(
new CdmSession(usage_property_set_.get(), EMPTY_ORIGIN, NULL));
status = usage_session_->Init();
if (NO_ERROR != status) {
LOGE("CdmEngine::GetUsageInfo: session init error");
@@ -678,7 +703,8 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
usage_property_set_->set_security_level(requested_security_level);
usage_property_set_->set_app_id(app_id);
usage_session_.reset(new CdmSession(usage_property_set_.get(), NULL));
usage_session_.reset(
new CdmSession(usage_property_set_.get(), EMPTY_ORIGIN, NULL));
CdmResponseType status = usage_session_->Init();
if (NO_ERROR != status) {

View File

@@ -24,9 +24,11 @@ const size_t kKeySetIdLength = 14;
namespace wvcdm {
CdmSession::CdmSession(const CdmClientPropertySet* cdm_client_property_set,
const std::string& origin,
WvCdmEventListener* event_listener)
: initialized_(false),
session_id_(GenerateSessionId()),
origin_(origin),
license_parser_(new CdmLicense),
crypto_session_(new CryptoSession),
policy_engine_(
@@ -70,7 +72,7 @@ CdmResponseType CdmSession::Init() {
if (Properties::use_certificates_as_identification()) {
std::string wrapped_key;
if (!file_handle_->Init(security_level_) ||
!file_handle_->RetrieveCertificate(&token, &wrapped_key) ||
!file_handle_->RetrieveCertificate(origin_, &token, &wrapped_key) ||
!crypto_session_->LoadCertificatePrivateKey(wrapped_key)) {
return NEED_PROVISIONING;
}

View File

@@ -57,8 +57,8 @@ void CertificateProvisioning::ComposeJsonRequestAsQueryString(
*/
CdmResponseType CertificateProvisioning::GetProvisioningRequest(
SecurityLevel requested_security_level, CdmCertificateType cert_type,
const std::string& cert_authority, CdmProvisioningRequest* request,
std::string* default_url) {
const std::string& cert_authority, const std::string& origin,
CdmProvisioningRequest* request, std::string* default_url) {
if (!default_url) {
LOGE("GetProvisioningRequest: pointer for returning URL is NULL");
return UNKNOWN_ERROR;
@@ -113,6 +113,15 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequest(
cert_type_ = cert_type;
options->set_certificate_authority(cert_authority);
if (origin != EMPTY_ORIGIN) {
std::string device_unique_id;
if (!crypto_session_.GetDeviceUniqueId(&device_unique_id)) {
LOGE("GetProvisioningRequest: fails to get device unique ID");
return UNKNOWN_ERROR;
}
provisioning_request.set_stable_id(device_unique_id + origin);
}
std::string serialized_message;
provisioning_request.SerializeToString(&serialized_message);
@@ -180,8 +189,8 @@ bool CertificateProvisioning::ParseJsonResponse(
* Returns NO_ERROR for success and UNKNOWN_ERROR if fails.
*/
CdmResponseType CertificateProvisioning::HandleProvisioningResponse(
CdmProvisioningResponse& response, std::string* cert,
std::string* wrapped_key) {
const std::string& origin, CdmProvisioningResponse& response,
std::string* cert, std::string* wrapped_key) {
// Extracts signed response from JSON string, decodes base64 signed response
const std::string kMessageStart = "\"signedResponse\": \"";
const std::string kMessageEnd = "\"";
@@ -255,7 +264,7 @@ CdmResponseType CertificateProvisioning::HandleProvisioningResponse(
LOGE("HandleProvisioningResponse: failed to init DeviceFiles");
return UNKNOWN_ERROR;
}
if (!handle.StoreCertificate(device_certificate, wrapped_rsa_key)) {
if (!handle.StoreCertificate(origin, device_certificate, wrapped_rsa_key)) {
LOGE("HandleProvisioningResponse: failed to save provisioning certificate");
return UNKNOWN_ERROR;
}

View File

@@ -10,6 +10,7 @@
#include "log.h"
#include "properties.h"
#include "string_conversions.h"
#include "wv_cdm_constants.h"
#if defined(__APPLE__)
#include <CommonCrypto/CommonDigest.h>
@@ -31,7 +32,8 @@ using video_widevine_client::sdk::UsageInfo_ProviderSession;
namespace {
const char kCertificateFileName[] = "cert.bin";
const char kCertificateFileNamePrefix[] = "cert";
const char kCertificateFileNameExt[] = ".bin";
const char kUsageInfoFileNamePrefix[] = "usage";
const char kUsageInfoFileNameExt[] = ".bin";
const char kLicenseFileNameExt[] = ".lic";
@@ -86,7 +88,8 @@ bool DeviceFiles::Init(CdmSecurityLevel security_level) {
return true;
}
bool DeviceFiles::StoreCertificate(const std::string& certificate,
bool DeviceFiles::StoreCertificate(const std::string& origin,
const std::string& certificate,
const std::string& wrapped_private_key) {
if (!initialized_) {
LOGW("DeviceFiles::StoreCertificate: not initialized");
@@ -106,10 +109,11 @@ bool DeviceFiles::StoreCertificate(const std::string& certificate,
std::string serialized_file;
file.SerializeToString(&serialized_file);
return StoreFileWithHash(kCertificateFileName, serialized_file);
return StoreFileWithHash(GetCertificateFileName(origin), serialized_file);
}
bool DeviceFiles::RetrieveCertificate(std::string* certificate,
bool DeviceFiles::RetrieveCertificate(const std::string& origin,
std::string* certificate,
std::string* wrapped_private_key) {
if (!initialized_) {
LOGW("DeviceFiles::RetrieveCertificate: not initialized");
@@ -121,7 +125,9 @@ bool DeviceFiles::RetrieveCertificate(std::string* certificate,
}
std::string serialized_file;
if (!RetrieveHashedFile(kCertificateFileName, &serialized_file)) return false;
if (!RetrieveHashedFile(GetCertificateFileName(origin), &serialized_file)) {
return false;
}
video_widevine_client::sdk::File file;
if (!file.ParseFromString(serialized_file)) {
@@ -151,6 +157,24 @@ bool DeviceFiles::RetrieveCertificate(std::string* certificate,
return true;
}
bool DeviceFiles::HasCertificate(const std::string& origin) {
if (!initialized_) {
LOGW("DeviceFiles::HasCertificate: not initialized");
return false;
}
return FileExists(GetCertificateFileName(origin));
}
bool DeviceFiles::RemoveCertificate(const std::string& origin) {
if (!initialized_) {
LOGW("DeviceFiles::RemoveCertificate: not initialized");
return false;
}
return RemoveFile(GetCertificateFileName(origin));
}
bool DeviceFiles::StoreLicense(const std::string& key_set_id,
const LicenseState state,
const CdmInitData& pssh_data,
@@ -749,8 +773,12 @@ void DeviceFiles::SecurityLevelPathBackwardCompatibility() {
}
}
std::string DeviceFiles::GetCertificateFileName() {
return kCertificateFileName;
std::string DeviceFiles::GetCertificateFileName(const std::string& origin) {
std::string hash;
if (origin != EMPTY_ORIGIN) {
hash = GetFileNameSafeHash(origin);
}
return kCertificateFileNamePrefix + hash + kCertificateFileNameExt;
}
std::string DeviceFiles::GetLicenseFileNameExtension() {
@@ -758,20 +786,23 @@ std::string DeviceFiles::GetLicenseFileNameExtension() {
}
std::string DeviceFiles::GetUsageInfoFileName(const std::string& app_id) {
if (app_id == "") {
return std::string(kUsageInfoFileNamePrefix) +
std::string(kUsageInfoFileNameExt);
std::string hash;
if (app_id != "") {
hash = GetFileNameSafeHash(app_id);
}
std::vector<uint8_t> hash(MD5_DIGEST_LENGTH);
const unsigned char* input =
reinterpret_cast<const unsigned char*>(app_id.data());
MD5(input, app_id.size(), &hash[0]);
return std::string(kUsageInfoFileNamePrefix) + wvcdm::Base64SafeEncode(hash) +
std::string(kUsageInfoFileNameExt);
return kUsageInfoFileNamePrefix + hash + kUsageInfoFileNameExt;
}
std::string DeviceFiles::GetBlankFileData() { return kBlankFileData; }
std::string DeviceFiles::GetFileNameSafeHash(const std::string& input) {
std::vector<uint8_t> hash(MD5_DIGEST_LENGTH);
const unsigned char* input_ptr =
reinterpret_cast<const unsigned char*>(input.data());
MD5(input_ptr, input.size(), &hash[0]);
return wvcdm::Base64SafeEncode(hash);
}
void DeviceFiles::SetTestFile(File* file) {
file_.reset(file);
test_file_ = true;

View File

@@ -48,10 +48,12 @@ class WvCdmEngineTest : public testing::Test {
public:
virtual void SetUp() {
CdmResponseType status =
cdm_engine_.OpenSession(g_key_system, NULL, NULL, &session_id_);
cdm_engine_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL,
&session_id_);
if (status == NEED_PROVISIONING) {
Provision();
status = cdm_engine_.OpenSession(g_key_system, NULL, NULL, &session_id_);
status = cdm_engine_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL,
&session_id_);
}
ASSERT_EQ(NO_ERROR, status);
ASSERT_NE("", session_id_) << "Could not open CDM session.";
@@ -67,14 +69,15 @@ class WvCdmEngineTest : public testing::Test {
std::string cert_authority;
std::string cert, wrapped_key;
ASSERT_EQ(NO_ERROR, cdm_engine_.GetProvisioningRequest(
cert_type, cert_authority, &prov_request,
&provisioning_server_url));
cert_type, cert_authority, EMPTY_ORIGIN,
&prov_request, &provisioning_server_url));
UrlRequest url_request(provisioning_server_url);
url_request.PostCertRequestInQueryString(prov_request);
std::string message;
bool ok = url_request.GetResponse(&message);
EXPECT_TRUE(ok);
ASSERT_EQ(NO_ERROR, cdm_engine_.HandleProvisioningResponse(message, &cert,
ASSERT_EQ(NO_ERROR, cdm_engine_.HandleProvisioningResponse(EMPTY_ORIGIN,
message, &cert,
&wrapped_key));
}

View File

@@ -8,6 +8,7 @@
#include "scoped_ptr.h"
#include "string_conversions.h"
#include "test_printers.h"
#include "wv_cdm_constants.h"
namespace {
const std::string kToken = wvcdm::a2bs_hex(
@@ -83,6 +84,9 @@ const std::string kWrappedKey = wvcdm::a2bs_hex(
"33EF70621A98184DDAB5E14BC971CF98CF6C91A37FFA83B00AD3BCABBAAB2DEF1C52F43003"
"E74C92B44F9205D22262FB47948654229DE1920F8EDF96A19A88A1CA1552F8856FB4CBF83B"
"AA3348419159D207F65FCE9C1A500C6818");
const std::string kTestOrigin = "com.google";
} // namespace
namespace wvcdm {
@@ -99,7 +103,8 @@ using ::testing::StrEq;
class MockDeviceFiles : public DeviceFiles {
public:
MOCK_METHOD1(Init, bool(CdmSecurityLevel));
MOCK_METHOD2(RetrieveCertificate, bool(std::string*, std::string*));
MOCK_METHOD3(RetrieveCertificate, bool(const std::string&, std::string*,
std::string*));
};
class MockCryptoSession : public CryptoSession {
@@ -127,7 +132,7 @@ class MockCdmLicense : public CdmLicense {
class CdmSessionTest : public ::testing::Test {
protected:
virtual void SetUp() {
cdm_session_.reset(new CdmSession(NULL, NULL));
cdm_session_.reset(new CdmSession(NULL, kTestOrigin, NULL));
// Inject testing mocks.
license_parser_ = new MockCdmLicense();
cdm_session_->set_license_parser(license_parser_);
@@ -156,8 +161,9 @@ TEST_F(CdmSessionTest, InitWithCertificate) {
.InSequence(crypto_session_seq)
.WillOnce(Return(level));
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),
EXPECT_CALL(*file_handle_, RetrieveCertificate(StrEq(kTestOrigin), NotNull(),
NotNull()))
.WillOnce(DoAll(SetArgPointee<1>(kToken), SetArgPointee<2>(kWrappedKey),
Return(true)));
EXPECT_CALL(*crypto_session_, LoadCertificatePrivateKey(StrEq(kWrappedKey)))
.InSequence(crypto_session_seq)
@@ -202,8 +208,9 @@ TEST_F(CdmSessionTest, ReInitFail) {
.InSequence(crypto_session_seq)
.WillOnce(Return(level));
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),
EXPECT_CALL(*file_handle_, RetrieveCertificate(StrEq(kTestOrigin), NotNull(),
NotNull()))
.WillOnce(DoAll(SetArgPointee<1>(kToken), SetArgPointee<2>(kWrappedKey),
Return(true)));
EXPECT_CALL(*crypto_session_, LoadCertificatePrivateKey(StrEq(kWrappedKey)))
.InSequence(crypto_session_seq)
@@ -238,7 +245,8 @@ TEST_F(CdmSessionTest, InitNeedsProvisioning) {
.InSequence(crypto_session_seq)
.WillOnce(Return(level));
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
EXPECT_CALL(*file_handle_, RetrieveCertificate(NotNull(), NotNull()))
EXPECT_CALL(*file_handle_, RetrieveCertificate(StrEq(kTestOrigin), NotNull(),
NotNull()))
.WillOnce(Return(false));
Properties::set_use_certificates_as_identification(true);

View File

@@ -1,11 +1,13 @@
// Copyright 2013 Google Inc. All Rights Reserved.
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "device_files.h"
#include "file_store.h"
#include "properties.h"
#include "string_conversions.h"
#include "wv_cdm_constants.h"
#include "wv_cdm_types.h"
namespace wvcdm {
@@ -1230,6 +1232,8 @@ UsageInfo kUsageInfoTestData[] = {
"0E12202FF1FBA9926A24A1F79970EC427DDF87B4421488F7952499BC33CEB282D9E48"
"A")}};
const std::string kTestOrigin = "com.google";
} // namespace
class MockFile : public File {
@@ -1278,6 +1282,23 @@ class DeviceFilesTest : public ::testing::Test {
class DeviceFilesStoreTest : public DeviceFilesTest,
public ::testing::WithParamInterface<bool> {};
struct CertStorageVariant {
CertStorageVariant(bool dir_exists_value, const std::string& origin_value)
: dir_exists(dir_exists_value),
origin(origin_value) {}
const bool dir_exists;
const std::string origin;
};
class DeviceCertificateStoreTest
: public DeviceFilesTest,
public ::testing::WithParamInterface<CertStorageVariant> {};
class DeviceCertificateTest
: public DeviceFilesTest,
public ::testing::WithParamInterface<std::string> {};
class DeviceFilesSecurityLevelTest
: public DeviceFilesTest,
public ::testing::WithParamInterface<CdmSecurityLevel> {};
@@ -1323,17 +1344,17 @@ MATCHER_P6(Contains, str1, str2, str3, str4, str5, str6, "") {
data.find(str6) != std::string::npos);
}
TEST_P(DeviceFilesStoreTest, StoreCertificate) {
TEST_P(DeviceCertificateStoreTest, StoreCertificate) {
MockFile file;
CertStorageVariant params = GetParam();
std::string certificate(GenerateRandomData(kCertificateLen));
std::string wrapped_private_key(GenerateRandomData(kWrappedKeyLen));
std::string device_certificate_path =
device_base_path_ + DeviceFiles::GetCertificateFileName();
device_base_path_ + DeviceFiles::GetCertificateFileName(params.origin);
bool dir_exists = GetParam();
EXPECT_CALL(file, IsDirectory(StrEq(device_base_path_)))
.WillOnce(Return(dir_exists));
if (dir_exists) {
.WillOnce(Return(params.dir_exists));
if (params.dir_exists) {
EXPECT_CALL(file, CreateDirectory(_)).Times(0);
} else {
EXPECT_CALL(file, CreateDirectory(StrEq(device_base_path_)))
@@ -1352,16 +1373,22 @@ TEST_P(DeviceFilesStoreTest, StoreCertificate) {
DeviceFiles device_files;
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
device_files.SetTestFile(&file);
EXPECT_TRUE(device_files.StoreCertificate(certificate, wrapped_private_key));
EXPECT_TRUE(device_files.StoreCertificate(params.origin, certificate,
wrapped_private_key));
}
INSTANTIATE_TEST_CASE_P(StoreCertificate, DeviceFilesStoreTest,
::testing::Bool());
INSTANTIATE_TEST_CASE_P(
StoreCertificate, DeviceCertificateStoreTest,
::testing::Values(CertStorageVariant(true, EMPTY_ORIGIN),
CertStorageVariant(true, kTestOrigin),
CertStorageVariant(false, EMPTY_ORIGIN),
CertStorageVariant(false, kTestOrigin)));
TEST_F(DeviceFilesTest, ReadCertificate) {
TEST_P(DeviceCertificateTest, ReadCertificate) {
MockFile file;
std::string origin = GetParam();
std::string device_certificate_path =
device_base_path_ + DeviceFiles::GetCertificateFileName();
device_base_path_ + DeviceFiles::GetCertificateFileName(origin);
std::string data = a2bs_hex(kTestCertificateFileData);
EXPECT_CALL(file, Exists(StrEq(device_certificate_path)))
@@ -1382,11 +1409,36 @@ TEST_F(DeviceFilesTest, ReadCertificate) {
std::string certificate, wrapped_private_key;
ASSERT_TRUE(
device_files.RetrieveCertificate(&certificate, &wrapped_private_key));
device_files.RetrieveCertificate(origin, &certificate,
&wrapped_private_key));
EXPECT_EQ(kTestCertificate, b2a_hex(certificate));
EXPECT_EQ(kTestWrappedPrivateKey, b2a_hex(wrapped_private_key));
}
TEST_P(DeviceCertificateTest, HasCertificate) {
MockFile file;
std::string origin = GetParam();
std::string device_certificate_path =
device_base_path_ + DeviceFiles::GetCertificateFileName(origin);
EXPECT_CALL(file, Exists(StrEq(device_certificate_path)))
.WillOnce(Return(false))
.WillOnce(Return(true));
EXPECT_CALL(file, Open(_, _)).Times(0);
DeviceFiles device_files;
ASSERT_TRUE(device_files.Init(kSecurityLevelL1));
device_files.SetTestFile(&file);
// MockFile returns false.
EXPECT_FALSE(device_files.HasCertificate(origin));
// MockFile returns true.
EXPECT_TRUE(device_files.HasCertificate(origin));
}
INSTANTIATE_TEST_CASE_P(CertificateUseTests, DeviceCertificateTest,
::testing::Values(EMPTY_ORIGIN, kTestOrigin));
TEST_P(DeviceFilesSecurityLevelTest, SecurityLevel) {
MockFile file;
std::string certificate(GenerateRandomData(kCertificateLen));
@@ -1397,7 +1449,7 @@ TEST_P(DeviceFilesSecurityLevelTest, SecurityLevel) {
ASSERT_TRUE(
Properties::GetDeviceFilesBasePath(security_level, &device_base_path));
std::string device_certificate_path =
device_base_path + DeviceFiles::GetCertificateFileName();
device_base_path + DeviceFiles::GetCertificateFileName(EMPTY_ORIGIN);
EXPECT_CALL(file, IsDirectory(StrEq(device_base_path)))
.WillOnce(Return(false));
@@ -1416,7 +1468,8 @@ TEST_P(DeviceFilesSecurityLevelTest, SecurityLevel) {
DeviceFiles device_files;
EXPECT_TRUE(device_files.Init(security_level));
device_files.SetTestFile(&file);
EXPECT_TRUE(device_files.StoreCertificate(certificate, wrapped_private_key));
EXPECT_TRUE(device_files.StoreCertificate(EMPTY_ORIGIN, certificate,
wrapped_private_key));
}
INSTANTIATE_TEST_CASE_P(SecurityLevel, DeviceFilesSecurityLevelTest,
@@ -1595,13 +1648,15 @@ TEST_F(DeviceFilesTest, SecurityLevelPathBackwardCompatibility) {
EXPECT_CALL(file, CreateDirectory(StrEq(new_path))).WillOnce(Return(true));
}
std::string old_path = base_path + DeviceFiles::GetCertificateFileName();
old_files.push_back(DeviceFiles::GetCertificateFileName());
std::string old_path =
base_path + DeviceFiles::GetCertificateFileName(EMPTY_ORIGIN);
old_files.push_back(DeviceFiles::GetCertificateFileName(EMPTY_ORIGIN));
EXPECT_CALL(file, IsRegularFile(StrEq(old_path))).WillOnce(Return(true));
EXPECT_CALL(file, Remove(StrEq(old_path))).WillOnce(Return(true));
for (size_t i = 0; i < security_dirs.size(); ++i) {
new_path =
base_path + security_dirs[i] + DeviceFiles::GetCertificateFileName();
base_path + security_dirs[i] +
DeviceFiles::GetCertificateFileName(EMPTY_ORIGIN);
EXPECT_CALL(file, Copy(StrEq(old_path), StrEq(new_path)))
.WillOnce(Return(true));
}
@@ -1625,7 +1680,8 @@ TEST_F(DeviceFilesTest, SecurityLevelPathBackwardCompatibility) {
std::string data = a2bs_hex(kTestCertificateFileData);
new_path = device_base_path_ + DeviceFiles::GetCertificateFileName();
new_path =
device_base_path_ + DeviceFiles::GetCertificateFileName(EMPTY_ORIGIN);
EXPECT_CALL(file, Exists(StrEq(new_path))).WillOnce(Return(true));
EXPECT_CALL(file, FileSize(_)).WillOnce(Return(data.size()));
EXPECT_CALL(file, Open(_, _)).WillOnce(Return(true));
@@ -1642,7 +1698,8 @@ TEST_F(DeviceFilesTest, SecurityLevelPathBackwardCompatibility) {
Properties::Init();
std::string certificate, wrapped_private_key;
ASSERT_TRUE(
device_files.RetrieveCertificate(&certificate, &wrapped_private_key));
device_files.RetrieveCertificate(EMPTY_ORIGIN, &certificate,
&wrapped_private_key));
}
TEST_F(DeviceFilesTest, UpdateLicenseState) {

View File

@@ -28,6 +28,7 @@ class WvContentDecryptionModule : public TimerHandler {
// Session related methods
virtual CdmResponseType OpenSession(const CdmKeySystem& key_system,
CdmClientPropertySet* property_set,
const std::string& origin,
WvCdmEventListener* event_listener,
CdmSessionId* session_id);
virtual CdmResponseType CloseSession(const CdmSessionId& session_id);
@@ -40,6 +41,7 @@ class WvContentDecryptionModule : public TimerHandler {
const CdmLicenseType license_type,
CdmAppParameterMap& app_parameters,
CdmClientPropertySet* property_set,
const std::string& origin,
CdmKeyMessage* key_request,
CdmKeyRequestType* key_request_type,
std::string* server_url);
@@ -75,15 +77,18 @@ class WvContentDecryptionModule : public TimerHandler {
virtual CdmResponseType GetProvisioningRequest(
CdmCertificateType cert_type,
const std::string& cert_authority,
const std::string& origin,
CdmProvisioningRequest* request,
std::string* default_url);
virtual CdmResponseType HandleProvisioningResponse(
const std::string& origin,
CdmProvisioningResponse& response,
std::string* cert,
std::string* wrapped_key);
virtual CdmResponseType Unprovision(CdmSecurityLevel level);
virtual CdmResponseType Unprovision(CdmSecurityLevel level,
const std::string& origin);
// Secure stop related methods
virtual CdmResponseType GetUsageInfo(const std::string& app_id,

View File

@@ -39,15 +39,16 @@ bool WvContentDecryptionModule::IsWebm(const std::string& init_data_type) {
CdmResponseType WvContentDecryptionModule::OpenSession(
const CdmKeySystem& key_system, CdmClientPropertySet* property_set,
WvCdmEventListener* event_listener, CdmSessionId* session_id) {
const std::string& origin, WvCdmEventListener* event_listener,
CdmSessionId* session_id) {
if (property_set && property_set->is_session_sharing_enabled()) {
AutoLock auto_lock(session_sharing_id_generation_lock_);
if (property_set->session_sharing_id() == 0)
property_set->set_session_sharing_id(GenerateSessionSharingId());
}
return cdm_engine_->OpenSession(key_system, property_set, event_listener,
session_id);
return cdm_engine_->OpenSession(key_system, property_set, origin,
event_listener, session_id);
}
CdmResponseType WvContentDecryptionModule::CloseSession(
@@ -61,11 +62,13 @@ CdmResponseType WvContentDecryptionModule::GenerateKeyRequest(
const CdmSessionId& session_id, const CdmKeySetId& key_set_id,
const std::string& init_data_type, const CdmInitData& init_data,
const CdmLicenseType license_type, CdmAppParameterMap& app_parameters,
CdmClientPropertySet* property_set, CdmKeyMessage* key_request,
CdmKeyRequestType* key_request_type, std::string* server_url) {
CdmClientPropertySet* property_set, const std::string& origin,
CdmKeyMessage* key_request, CdmKeyRequestType* key_request_type,
std::string* server_url) {
CdmResponseType sts;
if (license_type == kLicenseTypeRelease) {
sts = cdm_engine_->OpenKeySetSession(key_set_id, property_set, NULL);
sts = cdm_engine_->OpenKeySetSession(key_set_id, property_set, origin,
NULL);
if (sts != NO_ERROR) return sts;
}
InitializationData initialization_data(init_data_type, init_data);
@@ -132,22 +135,26 @@ CdmResponseType WvContentDecryptionModule::QueryKeyControlInfo(
CdmResponseType WvContentDecryptionModule::GetProvisioningRequest(
CdmCertificateType cert_type,
const std::string& cert_authority,
const std::string& origin,
CdmProvisioningRequest* request,
std::string* default_url) {
return cdm_engine_->GetProvisioningRequest(cert_type, cert_authority,
return cdm_engine_->GetProvisioningRequest(cert_type, cert_authority, origin,
request, default_url);
}
CdmResponseType WvContentDecryptionModule::HandleProvisioningResponse(
const std::string& origin,
CdmProvisioningResponse& response,
std::string* cert,
std::string* wrapped_key) {
return cdm_engine_->HandleProvisioningResponse(response, cert, wrapped_key);
return cdm_engine_->HandleProvisioningResponse(origin, response, cert,
wrapped_key);
}
CdmResponseType WvContentDecryptionModule::Unprovision(
CdmSecurityLevel level) {
return cdm_engine_->Unprovision(level);
CdmSecurityLevel level,
const std::string& origin) {
return cdm_engine_->Unprovision(level, origin);
}
CdmResponseType WvContentDecryptionModule::GetUsageInfo(

View File

@@ -268,8 +268,8 @@ class WvCdmExtendedDurationTest : public WvCdmTestBase {
CdmKeyRequestType key_request_type;
EXPECT_EQ(KEY_MESSAGE, decryptor_.GenerateKeyRequest(
session_id_, key_set_id_, "video/mp4", init_data,
license_type, app_parameters, NULL, &key_msg_,
&key_request_type, &server_url));
license_type, app_parameters, NULL, EMPTY_ORIGIN,
&key_msg_, &key_request_type, &server_url));
EXPECT_EQ(kKeyRequestTypeInitial, key_request_type);
EXPECT_EQ(0u, server_url.size());
}
@@ -283,8 +283,8 @@ class WvCdmExtendedDurationTest : public WvCdmTestBase {
CdmKeyRequestType key_request_type;
EXPECT_EQ(KEY_MESSAGE, decryptor_.GenerateKeyRequest(
session_id_, key_set_id_, "video/mp4", init_data,
license_type, app_parameters, NULL, &key_msg_,
&key_request_type, server_url));
license_type, app_parameters, NULL, EMPTY_ORIGIN,
&key_msg_, &key_request_type, server_url));
EXPECT_EQ(kKeyRequestTypeRenewal, key_request_type);
// TODO(edwinwong, rfrias): Add tests cases for when license server url
// is empty on renewal. Need appropriate key id at the server.
@@ -300,7 +300,8 @@ class WvCdmExtendedDurationTest : public WvCdmTestBase {
EXPECT_EQ(KEY_MESSAGE, decryptor_.GenerateKeyRequest(
session_id, key_set_id, "video/mp4", init_data,
kLicenseTypeRelease, app_parameters, NULL,
&key_msg_, &key_request_type, &server_url));
EMPTY_ORIGIN, &key_msg_, &key_request_type,
&server_url));
EXPECT_EQ(kKeyRequestTypeRelease, key_request_type);
}
@@ -398,13 +399,14 @@ class WvCdmExtendedDurationTest : public WvCdmTestBase {
}
void Unprovision() {
EXPECT_EQ(NO_ERROR, decryptor_.Unprovision(kSecurityLevelL1));
EXPECT_EQ(NO_ERROR, decryptor_.Unprovision(kSecurityLevelL3));
EXPECT_EQ(NO_ERROR, decryptor_.Unprovision(kSecurityLevelL1, EMPTY_ORIGIN));
EXPECT_EQ(NO_ERROR, decryptor_.Unprovision(kSecurityLevelL3, EMPTY_ORIGIN));
}
void Provision() {
CdmResponseType status =
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL,
&session_id_);
switch (status) {
case NO_ERROR:
decryptor_.CloseSession(session_id_);
@@ -421,7 +423,8 @@ class WvCdmExtendedDurationTest : public WvCdmTestBase {
std::string cert_authority, cert, wrapped_key;
status = decryptor_.GetProvisioningRequest(
cert_type, cert_authority, &key_msg_, &provisioning_server_url);
cert_type, cert_authority, EMPTY_ORIGIN, &key_msg_,
&provisioning_server_url);
EXPECT_EQ(NO_ERROR, status);
if (NO_ERROR != status) return;
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
@@ -429,8 +432,9 @@ class WvCdmExtendedDurationTest : public WvCdmTestBase {
std::string response =
GetCertRequestResponse(g_config->provisioning_server_url());
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(NO_ERROR, decryptor_.HandleProvisioningResponse(response, &cert,
&wrapped_key));
EXPECT_EQ(NO_ERROR,
decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert,
&wrapped_key));
EXPECT_EQ(0, static_cast<int>(cert.size()));
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
decryptor_.CloseSession(session_id_);
@@ -614,7 +618,8 @@ class WvCdmExtendedDurationTest : public WvCdmTestBase {
}
std::string GetSecurityLevel(TestWvCdmClientPropertySet* property_set) {
decryptor_.OpenSession(g_key_system, property_set, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, property_set, EMPTY_ORIGIN, NULL,
&session_id_);
CdmQueryMap query_info;
EXPECT_EQ(NO_ERROR,
decryptor_.QuerySessionStatus(session_id_, &query_info));
@@ -647,7 +652,7 @@ class WvCdmExtendedDurationTest : public WvCdmTestBase {
TEST_F(WvCdmExtendedDurationTest, VerifyLicenseRequestTest) {
Provision();
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
GenerateKeyRequest(g_key_id, kLicenseTypeStreaming);
EXPECT_TRUE(!key_msg_.empty());
@@ -715,7 +720,7 @@ TEST_F(WvCdmExtendedDurationTest, VerifyLicenseRequestTest) {
TEST_F(WvCdmExtendedDurationTest, VerifyLicenseRenewalTest) {
Provision();
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
GenerateKeyRequest(g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
@@ -803,7 +808,8 @@ TEST_F(WvCdmExtendedDurationTest, UsageOverflowTest) {
EXPECT_TRUE(handle.DeleteAllUsageInfoForApp("", &provider_session_tokens));
for (size_t i = 0; i < kMaxUsageTableSize + 100; ++i) {
decryptor_.OpenSession(g_key_system, property_set, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, property_set, EMPTY_ORIGIN, NULL,
&session_id_);
std::string key_id = a2bs_hex(
"000000427073736800000000" // blob size and pssh
"EDEF8BA979D64ACEA3C827DCD51D21ED00000022" // Widevine system id
@@ -843,7 +849,7 @@ TEST_P(WvCdmStreamingNoPstTest, UsageTest) {
Unprovision();
Provision();
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
GenerateKeyRequest(g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
@@ -917,7 +923,7 @@ TEST_P(WvCdmStreamingPstTest, UsageTest) {
Unprovision();
Provision();
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
GenerateKeyRequest(kStreamingClip1PstInitData, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
@@ -982,7 +988,7 @@ TEST_P(WvCdmStreamingUsageReportTest, UsageTest) {
Unprovision();
Provision();
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
GenerateKeyRequest(kStreamingClip1PstInitData, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
@@ -1078,7 +1084,7 @@ TEST_P(WvCdmOfflineUsageReportTest, UsageTest) {
Unprovision();
Provision();
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
GenerateKeyRequest(kOfflineClip2PstInitData, kLicenseTypeOffline);
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
@@ -1101,7 +1107,7 @@ TEST_P(WvCdmOfflineUsageReportTest, UsageTest) {
for (size_t i = 0; i < GetParam(); ++i) {
session_id_.clear();
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
EXPECT_EQ(KEY_ADDED, decryptor_.RestoreKey(session_id_, key_set_id));
// Query and validate usage information
@@ -1144,7 +1150,7 @@ TEST_P(WvCdmOfflineUsageReportTest, UsageTest) {
}
session_id_.clear();
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
EXPECT_EQ(KEY_ADDED, decryptor_.RestoreKey(session_id_, key_set_id));
// Query and validate usage information

View File

@@ -493,7 +493,8 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
EXPECT_EQ(wvcdm::KEY_MESSAGE,
decryptor_.GenerateKeyRequest(
session_id_, key_set_id, "video/mp4", init_data, license_type,
app_parameters, property_set, &key_msg_, NULL, &server_url));
app_parameters, property_set, EMPTY_ORIGIN, &key_msg_, NULL,
&server_url));
EXPECT_EQ(0u, server_url.size());
}
@@ -513,8 +514,8 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
EXPECT_EQ(wvcdm::KEY_MESSAGE,
decryptor_.GenerateKeyRequest(
session_id_, key_set_id_, "video/mp4", init_data,
license_type, app_parameters, property_set, &key_msg_,
&key_request_type, server_url));
license_type, app_parameters, property_set, EMPTY_ORIGIN,
&key_msg_, &key_request_type, server_url));
EXPECT_EQ(kKeyRequestTypeRenewal, key_request_type);
// TODO(edwinwong, rfrias): Add tests cases for when license server url
// is empty on renewal. Need appropriate key id at the server.
@@ -535,8 +536,8 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
EXPECT_EQ(wvcdm::KEY_MESSAGE,
decryptor_.GenerateKeyRequest(
session_id, key_set_id, "video/mp4", init_data,
kLicenseTypeRelease, app_parameters, property_set, &key_msg_,
&key_request_type, &server_url));
kLicenseTypeRelease, app_parameters, property_set,
EMPTY_ORIGIN, &key_msg_, &key_request_type, &server_url));
EXPECT_EQ(kKeyRequestTypeRelease, key_request_type);
}
@@ -635,8 +636,8 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
}
void Unprovision() {
EXPECT_EQ(NO_ERROR, decryptor_.Unprovision(kSecurityLevelL1));
EXPECT_EQ(NO_ERROR, decryptor_.Unprovision(kSecurityLevelL3));
EXPECT_EQ(NO_ERROR, decryptor_.Unprovision(kSecurityLevelL1, EMPTY_ORIGIN));
EXPECT_EQ(NO_ERROR, decryptor_.Unprovision(kSecurityLevelL3, EMPTY_ORIGIN));
}
void Provision(SecurityLevel level) {
@@ -649,7 +650,8 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
}
CdmResponseType status =
decryptor_.OpenSession(g_key_system, property_set, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, property_set, EMPTY_ORIGIN, NULL,
&session_id_);
switch (status) {
case NO_ERROR:
decryptor_.CloseSession(session_id_);
@@ -666,7 +668,8 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
std::string cert_authority, cert, wrapped_key;
status = decryptor_.GetProvisioningRequest(
cert_type, cert_authority, &key_msg_, &provisioning_server_url);
cert_type, cert_authority, EMPTY_ORIGIN, &key_msg_,
&provisioning_server_url);
EXPECT_EQ(wvcdm::NO_ERROR, status);
if (NO_ERROR != status) return;
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
@@ -674,8 +677,9 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
std::string response =
GetCertRequestResponse(g_config->provisioning_server_url());
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse(
response, &cert, &wrapped_key));
EXPECT_EQ(wvcdm::NO_ERROR,
decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert,
&wrapped_key));
EXPECT_EQ(0, static_cast<int>(cert.size()));
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
decryptor_.CloseSession(session_id_);
@@ -683,7 +687,8 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
}
std::string GetSecurityLevel(TestWvCdmClientPropertySet* property_set) {
EXPECT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, property_set, NULL,
EXPECT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, property_set,
EMPTY_ORIGIN, NULL,
&session_id_));
CdmQueryMap query_info;
EXPECT_EQ(wvcdm::NO_ERROR,
@@ -720,21 +725,22 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
};
TEST_F(WvCdmRequestLicenseTest, ProvisioningTest) {
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
std::string provisioning_server_url;
CdmCertificateType cert_type = kCertificateWidevine;
std::string cert_authority, cert, wrapped_key;
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(
cert_type, cert_authority, &key_msg_,
&provisioning_server_url));
cert_type, cert_authority, EMPTY_ORIGIN,
&key_msg_, &provisioning_server_url));
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
std::string response =
GetCertRequestResponse(g_config->provisioning_server_url());
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse(
response, &cert, &wrapped_key));
EXPECT_EQ(wvcdm::NO_ERROR,
decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert,
&wrapped_key));
EXPECT_EQ(0, static_cast<int>(cert.size()));
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
decryptor_.CloseSession(session_id_);
@@ -748,48 +754,52 @@ TEST_F(WvCdmRequestLicenseTest, UnprovisionTest) {
handle.SetTestFile(&file);
std::string certificate;
std::string wrapped_private_key;
EXPECT_TRUE(handle.RetrieveCertificate(&certificate, &wrapped_private_key));
EXPECT_TRUE(handle.RetrieveCertificate(EMPTY_ORIGIN, &certificate,
&wrapped_private_key));
EXPECT_EQ(NO_ERROR, decryptor_.Unprovision(security_level));
EXPECT_FALSE(handle.RetrieveCertificate(&certificate, &wrapped_private_key));
EXPECT_EQ(NO_ERROR, decryptor_.Unprovision(security_level, EMPTY_ORIGIN));
EXPECT_FALSE(handle.RetrieveCertificate(EMPTY_ORIGIN, &certificate,
&wrapped_private_key));
}
TEST_F(WvCdmRequestLicenseTest, ProvisioningRetryTest) {
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
std::string provisioning_server_url;
CdmCertificateType cert_type = kCertificateWidevine;
std::string cert_authority, cert, wrapped_key;
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(
cert_type, cert_authority, &key_msg_,
&provisioning_server_url));
cert_type, cert_authority, EMPTY_ORIGIN,
&key_msg_, &provisioning_server_url));
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(
cert_type, cert_authority, &key_msg_,
&provisioning_server_url));
cert_type, cert_authority, EMPTY_ORIGIN,
&key_msg_, &provisioning_server_url));
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
std::string response =
GetCertRequestResponse(g_config->provisioning_server_url());
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse(
response, &cert, &wrapped_key));
EXPECT_EQ(wvcdm::NO_ERROR,
decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert,
&wrapped_key));
EXPECT_EQ(0, static_cast<int>(cert.size()));
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
response =
GetCertRequestResponse(g_config->provisioning_server_url());
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(wvcdm::UNKNOWN_ERROR, decryptor_.HandleProvisioningResponse(
response, &cert, &wrapped_key));
EXPECT_EQ(wvcdm::UNKNOWN_ERROR,
decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert,
&wrapped_key));
EXPECT_EQ(0, static_cast<int>(cert.size()));
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, DISABLED_X509ProvisioningTest) {
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
std::string provisioning_server_url;
CdmCertificateType cert_type = kCertificateX509;
// TODO(rfrias): insert appropriate CA here
@@ -797,15 +807,16 @@ TEST_F(WvCdmRequestLicenseTest, DISABLED_X509ProvisioningTest) {
std::string cert, wrapped_key;
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(
cert_type, cert_authority, &key_msg_,
&provisioning_server_url));
cert_type, cert_authority, EMPTY_ORIGIN,
&key_msg_, &provisioning_server_url));
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
std::string response =
GetCertRequestResponse(g_config->provisioning_server_url());
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse(
response, &cert, &wrapped_key));
EXPECT_EQ(wvcdm::NO_ERROR,
decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert,
&wrapped_key));
EXPECT_NE(0, static_cast<int>(cert.size()));
EXPECT_NE(0, static_cast<int>(wrapped_key.size()));
decryptor_.CloseSession(session_id_);
@@ -821,34 +832,39 @@ TEST_F(WvCdmRequestLicenseTest, PropertySetTest) {
property_set_L1.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L1);
property_set_L1.set_use_privacy_mode(true);
decryptor_.OpenSession(g_key_system, &property_set_L1, NULL, &session_id_L1);
decryptor_.OpenSession(g_key_system, &property_set_L1, EMPTY_ORIGIN, NULL,
&session_id_L1);
property_set_L3.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3);
property_set_L3.set_use_privacy_mode(false);
CdmResponseType sts = decryptor_.OpenSession(g_key_system, &property_set_L3,
NULL, &session_id_L3);
EMPTY_ORIGIN, NULL,
&session_id_L3);
if (NEED_PROVISIONING == sts) {
std::string provisioning_server_url;
CdmCertificateType cert_type = kCertificateWidevine;
std::string cert_authority, cert, wrapped_key;
EXPECT_EQ(NO_ERROR, decryptor_.GetProvisioningRequest(
cert_type, cert_authority, &key_msg_,
&provisioning_server_url));
cert_type, cert_authority, EMPTY_ORIGIN,
&key_msg_, &provisioning_server_url));
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
std::string response =
GetCertRequestResponse(g_config->provisioning_server_url());
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(NO_ERROR, decryptor_.HandleProvisioningResponse(response, &cert,
&wrapped_key));
EXPECT_EQ(NO_ERROR,
decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert,
&wrapped_key));
EXPECT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, &property_set_L3,
NULL, &session_id_L3));
EMPTY_ORIGIN, NULL,
&session_id_L3));
} else {
EXPECT_EQ(NO_ERROR, sts);
}
property_set_Ln.set_security_level("");
decryptor_.OpenSession(g_key_system, &property_set_Ln, NULL, &session_id_Ln);
decryptor_.OpenSession(g_key_system, &property_set_Ln, EMPTY_ORIGIN, NULL,
&session_id_Ln);
std::string security_level;
EXPECT_TRUE(Properties::GetSecurityLevel(session_id_L1, &security_level));
@@ -889,22 +905,24 @@ TEST_F(WvCdmRequestLicenseTest, ForceL3Test) {
EXPECT_EQ(
NEED_PROVISIONING,
decryptor_.OpenSession(g_key_system, &property_set, NULL, &session_id_));
decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL,
&session_id_));
std::string provisioning_server_url;
CdmCertificateType cert_type = kCertificateWidevine;
std::string cert_authority, cert, wrapped_key;
EXPECT_EQ(NO_ERROR, decryptor_.GetProvisioningRequest(
cert_type, cert_authority, &key_msg_,
cert_type, cert_authority, EMPTY_ORIGIN, &key_msg_,
&provisioning_server_url));
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
std::string response =
GetCertRequestResponse(g_config->provisioning_server_url());
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(NO_ERROR, decryptor_.HandleProvisioningResponse(response, &cert,
&wrapped_key));
EXPECT_EQ(NO_ERROR,
decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert,
&wrapped_key));
EXPECT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, &property_set, NULL,
&session_id_));
EXPECT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, &property_set,
EMPTY_ORIGIN, NULL, &session_id_));
GenerateKeyRequest(g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
decryptor_.CloseSession(session_id_);
@@ -914,7 +932,8 @@ TEST_F(WvCdmRequestLicenseTest, PrivacyModeTest) {
TestWvCdmClientPropertySet property_set;
property_set.set_use_privacy_mode(true);
decryptor_.OpenSession(g_key_system, &property_set, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL,
&session_id_);
GenerateKeyRequest(g_key_id, kLicenseTypeStreaming);
std::string resp = GetKeyRequestResponse(g_license_server, g_client_auth);
@@ -930,21 +949,22 @@ TEST_F(WvCdmRequestLicenseTest, PrivacyModeWithServiceCertificateTest) {
property_set.set_use_privacy_mode(true);
property_set.set_service_certificate(a2bs_hex(kServiceCertificate));
decryptor_.OpenSession(g_key_system, &property_set, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL,
&session_id_);
GenerateKeyRequest(g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, BaseMessageTest) {
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
GenerateKeyRequest(g_key_id, kLicenseTypeStreaming);
GetKeyRequestResponse(g_license_server, g_client_auth);
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, WrongMessageTest) {
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
std::string wrong_message = wvcdm::a2bs_hex(g_wrong_key_id);
GenerateKeyRequest(wrong_message, kLicenseTypeStreaming);
@@ -972,7 +992,7 @@ TEST_F(WvCdmRequestLicenseTest, WrongMessageTest) {
}
TEST_F(WvCdmRequestLicenseTest, AddStreamingKeyTest) {
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
GenerateKeyRequest(g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
decryptor_.CloseSession(session_id_);
@@ -987,7 +1007,7 @@ TEST_F(WvCdmRequestLicenseTest, AddKeyOfflineTest) {
std::string client_auth;
GetOfflineConfiguration(&key_id, &client_auth);
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
GenerateKeyRequest(key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(g_license_server, client_auth, false);
decryptor_.CloseSession(session_id_);
@@ -1002,7 +1022,7 @@ TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeyTest) {
std::string client_auth;
GetOfflineConfiguration(&key_id, &client_auth);
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
GenerateKeyRequest(key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(g_license_server, client_auth, false);
@@ -1011,7 +1031,7 @@ TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeyTest) {
decryptor_.CloseSession(session_id_);
session_id_.clear();
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_.RestoreKey(session_id_, key_set_id));
decryptor_.CloseSession(session_id_);
}
@@ -1025,7 +1045,7 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseOfflineKeyTest) {
std::string client_auth;
GetOfflineConfiguration(&key_id, &client_auth);
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
GenerateKeyRequest(key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(g_license_server, client_auth, false);
@@ -1035,7 +1055,7 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseOfflineKeyTest) {
session_id_.clear();
key_set_id_.clear();
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_.RestoreKey(session_id_, key_set_id));
decryptor_.CloseSession(session_id_);
@@ -1055,7 +1075,7 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseRetryOfflineKeyTest) {
std::string client_auth;
GetOfflineConfiguration(&key_id, &client_auth);
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
GenerateKeyRequest(key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(g_license_server, client_auth, false);
@@ -1065,7 +1085,7 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseRetryOfflineKeyTest) {
session_id_.clear();
key_set_id_.clear();
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_.RestoreKey(session_id_, key_set_id));
decryptor_.CloseSession(session_id_);
@@ -1074,7 +1094,7 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseRetryOfflineKeyTest) {
GenerateKeyRelease(key_set_id);
session_id_.clear();
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
EXPECT_EQ(wvcdm::UNKNOWN_ERROR, decryptor_.RestoreKey(session_id_, key_set_id));
decryptor_.CloseSession(session_id_);
@@ -1097,28 +1117,32 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseRetryL3OfflineKeyTest) {
GetOfflineConfiguration(&key_id, &client_auth);
CdmResponseType sts =
decryptor_.OpenSession(g_key_system, &property_set, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL,
&session_id_);
if (NEED_PROVISIONING == sts) {
std::string provisioning_server_url;
CdmCertificateType cert_type = kCertificateWidevine;
std::string cert_authority, cert, wrapped_key;
EXPECT_EQ(NO_ERROR, decryptor_.GetProvisioningRequest(
cert_type, cert_authority, &key_msg_,
cert_type, cert_authority, EMPTY_ORIGIN, &key_msg_,
&provisioning_server_url));
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
std::string response =
GetCertRequestResponse(g_config->provisioning_server_url());
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(NO_ERROR, decryptor_.HandleProvisioningResponse(response, &cert,
&wrapped_key));
EXPECT_EQ(NO_ERROR,
decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert,
&wrapped_key));
EXPECT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, &property_set,
NULL, &session_id_));
EMPTY_ORIGIN, NULL,
&session_id_));
} else {
EXPECT_EQ(NO_ERROR, sts);
}
decryptor_.OpenSession(g_key_system, &property_set, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL,
&session_id_);
GenerateKeyRequest(key_id, kLicenseTypeOffline, &property_set);
VerifyKeyRequestResponse(g_license_server, client_auth, false);
@@ -1128,7 +1152,8 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseRetryL3OfflineKeyTest) {
session_id_.clear();
key_set_id_.clear();
decryptor_.OpenSession(g_key_system, &property_set, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL,
&session_id_);
EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_.RestoreKey(session_id_, key_set_id));
decryptor_.CloseSession(session_id_);
@@ -1137,7 +1162,8 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseRetryL3OfflineKeyTest) {
GenerateKeyRelease(key_set_id, &property_set);
session_id_.clear();
decryptor_.OpenSession(g_key_system, &property_set, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL,
&session_id_);
EXPECT_EQ(
wvcdm::UNKNOWN_ERROR, decryptor_.RestoreKey(session_id_, key_set_id));
decryptor_.CloseSession(session_id_);
@@ -1158,7 +1184,7 @@ TEST_F(WvCdmRequestLicenseTest, ExpiryOnReleaseOfflineKeyTest) {
std::string client_auth;
GetOfflineConfiguration(&key_id, &client_auth);
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
GenerateKeyRequest(key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(g_license_server, client_auth, false);
@@ -1169,7 +1195,8 @@ TEST_F(WvCdmRequestLicenseTest, ExpiryOnReleaseOfflineKeyTest) {
session_id_.clear();
key_set_id_.clear();
StrictMock<TestWvCdmEventListener> listener;
decryptor_.OpenSession(g_key_system, NULL, &listener, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, &listener,
&session_id_);
CdmSessionId restore_session_id = session_id_;
EXPECT_CALL(listener,
OnSessionKeysChange(restore_session_id,
@@ -1197,7 +1224,7 @@ TEST_F(WvCdmRequestLicenseTest, ExpiryOnReleaseOfflineKeyTest) {
}
TEST_F(WvCdmRequestLicenseTest, StreamingLicenseRenewal) {
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
GenerateKeyRequest(g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
@@ -1214,7 +1241,7 @@ TEST_F(WvCdmRequestLicenseTest, OfflineLicenseRenewal) {
std::string client_auth;
GetOfflineConfiguration(&key_id, &client_auth);
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
GenerateKeyRequest(key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(g_license_server, client_auth, false);
@@ -1227,7 +1254,8 @@ TEST_F(WvCdmRequestLicenseTest, OfflineLicenseRenewal) {
TEST_F(WvCdmRequestLicenseTest, RemoveKeys) {
ASSERT_EQ(NO_ERROR,
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_));
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL,
&session_id_));
GenerateKeyRequest(g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
ASSERT_EQ(NO_ERROR, decryptor_.RemoveKeys(session_id_));
@@ -1248,7 +1276,7 @@ TEST_F(WvCdmRequestLicenseTest, UsageInfoRetryTest) {
EXPECT_TRUE(handle.DeleteAllUsageInfoForApp(app_id, &psts));
SubSampleInfo* data = &usage_info_sub_samples_icp[0];
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
std::string key_id = a2bs_hex(
"000000427073736800000000" // blob size and pssh
"EDEF8BA979D64ACEA3C827DCD51D21ED00000022" // Widevine system id
@@ -1326,7 +1354,8 @@ TEST_P(WvCdmUsageInfoTest, UsageInfo) {
for (size_t i = 0; i < usage_info_data->usage_info; ++i) {
SubSampleInfo* data = usage_info_data->sub_sample + i;
decryptor_.OpenSession(g_key_system, property_set, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, property_set, EMPTY_ORIGIN, NULL,
&session_id_);
std::string key_id = a2bs_hex(
"000000427073736800000000" // blob size and pssh
"EDEF8BA979D64ACEA3C827DCD51D21ED00000022" // Widevine system id
@@ -1405,7 +1434,7 @@ TEST_F(WvCdmRequestLicenseTest, QueryKeyStatus) {
Unprovision();
Provision(kLevelDefault);
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
GenerateKeyRequest(g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
@@ -1478,7 +1507,7 @@ TEST_F(WvCdmRequestLicenseTest, QueryKeyControlInfo) {
Unprovision();
Provision(kLevelDefault);
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
GenerateKeyRequest(g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
@@ -1540,26 +1569,27 @@ TEST_F(WvCdmRequestLicenseTest, SecurityLevelPathBackwardCompatibility) {
file.Remove(path);
}
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
std::string provisioning_server_url;
CdmCertificateType cert_type = kCertificateWidevine;
std::string cert_authority, cert, wrapped_key;
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(
cert_type, cert_authority, &key_msg_,
&provisioning_server_url));
cert_type, cert_authority, EMPTY_ORIGIN,
&key_msg_, &provisioning_server_url));
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
std::string response =
GetCertRequestResponse(g_config->provisioning_server_url());
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse(
response, &cert, &wrapped_key));
EXPECT_EQ(wvcdm::NO_ERROR,
decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert,
&wrapped_key));
decryptor_.CloseSession(session_id_);
std::vector<std::string> files;
EXPECT_TRUE(file.List(base_path, &files));
size_t number_of_files = files.size();
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
GenerateKeyRequest(key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(g_license_server, client_auth, false);
CdmKeySetId key_set_id = key_set_id_;
@@ -1585,11 +1615,11 @@ TEST_F(WvCdmRequestLicenseTest, SecurityLevelPathBackwardCompatibility) {
// Setup complete to earlier version (non-security level based) path.
// Restore persistent license, retrieve L1, L3 streaming licenses to verify
session_id_.clear();
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_.RestoreKey(session_id_, key_set_id));
decryptor_.CloseSession(session_id_);
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
GenerateKeyRequest(g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, client_auth, false);
decryptor_.CloseSession(session_id_);
@@ -1601,26 +1631,28 @@ TEST_F(WvCdmRequestLicenseTest, SecurityLevelPathBackwardCompatibility) {
EXPECT_EQ(
wvcdm::NEED_PROVISIONING,
decryptor_.OpenSession(g_key_system, &property_set, NULL, &session_id_));
decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL,
&session_id_));
EXPECT_EQ(NO_ERROR, decryptor_.GetProvisioningRequest(
cert_type, cert_authority, &key_msg_,
cert_type, cert_authority, EMPTY_ORIGIN, &key_msg_,
&provisioning_server_url));
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
response =
GetCertRequestResponse(g_config->provisioning_server_url());
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(NO_ERROR, decryptor_.HandleProvisioningResponse(response, &cert,
&wrapped_key));
EXPECT_EQ(NO_ERROR,
decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert,
&wrapped_key));
EXPECT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, &property_set, NULL,
&session_id_));
EXPECT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, &property_set,
EMPTY_ORIGIN, NULL, &session_id_));
GenerateKeyRequest(g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, client_auth, false);
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, DISABLED_OfflineLicenseDecryptionTest) {
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
GenerateKeyRequest(g_key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
@@ -1673,7 +1705,7 @@ TEST_F(WvCdmRequestLicenseTest, DISABLED_OfflineLicenseDecryptionTest) {
}
TEST_F(WvCdmRequestLicenseTest, DISABLED_RestoreOfflineLicenseDecryptionTest) {
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
GenerateKeyRequest(g_key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
CdmKeySetId key_set_id = key_set_id_;
@@ -1681,7 +1713,7 @@ TEST_F(WvCdmRequestLicenseTest, DISABLED_RestoreOfflineLicenseDecryptionTest) {
decryptor_.CloseSession(session_id_);
session_id_.clear();
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_.RestoreKey(session_id_, key_set_id));
/*
// key 1, encrypted, 256b
@@ -1798,7 +1830,8 @@ TEST_P(WvCdmSessionSharingTest, SessionSharingTest) {
property_set.set_session_sharing_mode(
session_sharing_info->session_sharing_enabled);
decryptor_.OpenSession(g_key_system, &property_set, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL,
&session_id_);
CdmSessionId gp_session_id_1 = session_id_;
GenerateKeyRequest(g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
@@ -1811,7 +1844,8 @@ TEST_P(WvCdmSessionSharingTest, SessionSharingTest) {
"edef8ba979d64acea3c827dcd51d21ed00000014" // Widevine system id
"08011210bdf1cb4fffc6506b8b7945b0bd2917fb"); // pssh data
decryptor_.OpenSession(g_key_system, &property_set, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL,
&session_id_);
CdmSessionId gp_session_id_2 = session_id_;
GenerateKeyRequest(gp_key_id2, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, gp_client_auth2, false);
@@ -1846,7 +1880,7 @@ TEST_F(WvCdmRequestLicenseTest, DecryptionKeyExpiredTest) {
"EDEF8BA979D64ACEA3C827DCD51D21ED00000014" // Widevine system id
"0801121030313233343536373839616263646566"); // pssh data
SubSampleInfo* data = &single_encrypted_sub_sample_short_expiry;
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
if (data->retrieve_key) {
GenerateKeyRequest(kCpKeyId, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
@@ -1876,7 +1910,7 @@ class WvCdmDecryptionTest
TEST_P(WvCdmDecryptionTest, DecryptionTest) {
SubSampleInfo* data = GetParam();
decryptor_.OpenSession(g_key_system, NULL, NULL, &session_id_);
decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, &session_id_);
if (data->retrieve_key) {
GenerateKeyRequest(g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);

View File

@@ -252,6 +252,8 @@ class WVDrmPlugin : public android::DrmPlugin,
WvContentDecryptionModule* mCDM;
WVGenericCryptoInterface* mCrypto;
std::string mOrigin;
Mutex mCryptoSessionsMutex;
map<CdmSessionId, CryptoSession> mCryptoSessions;
@@ -273,6 +275,8 @@ class WVDrmPlugin : public android::DrmPlugin,
status_t mapOEMCryptoResult(OEMCryptoResult res);
bool InitDataResemblesPSSH(const Vector<uint8_t>& initData);
const char* determineOrigin() const;
};
} // namespace wvdrm

View File

@@ -74,7 +74,8 @@ DrmPlugin::KeyStatusType ConvertFromCdmKeyStatus(CdmKeyStatus keyStatus) {
WVDrmPlugin::WVDrmPlugin(WvContentDecryptionModule* cdm,
WVGenericCryptoInterface* crypto)
: mCDM(cdm), mCrypto(crypto), mCryptoSessionsMutex(), mCryptoSessions() {}
: mCDM(cdm), mCrypto(crypto), mOrigin(), mCryptoSessionsMutex(),
mCryptoSessions() {}
WVDrmPlugin::~WVDrmPlugin() {
typedef map<CdmSessionId, CryptoSession>::iterator mapIterator;
@@ -93,7 +94,8 @@ WVDrmPlugin::~WVDrmPlugin() {
status_t WVDrmPlugin::openSession(Vector<uint8_t>& sessionId) {
CdmSessionId cdmSessionId;
CdmResponseType res =
mCDM->OpenSession("com.widevine", &mPropertySet, this, &cdmSessionId);
mCDM->OpenSession("com.widevine", &mPropertySet, determineOrigin(), this,
&cdmSessionId);
if (!isCdmResponseTypeSuccess(res)) {
return mapAndNotifyOfCdmResponseType(sessionId, res);
@@ -234,8 +236,8 @@ status_t WVDrmPlugin::getKeyRequest(
string cdmDefaultUrl;
CdmResponseType res = mCDM->GenerateKeyRequest(
cdmSessionId, cdmKeySetId, cdmInitDataType, processedInitData,
cdmLicenseType, cdmParameters, &mPropertySet, &keyRequest,
&cdmKeyRequestType, &cdmDefaultUrl);
cdmLicenseType, cdmParameters, &mPropertySet, determineOrigin(),
&keyRequest, &cdmKeyRequestType, &cdmDefaultUrl);
*keyRequestType = ConvertFromCdmKeyRequestType(cdmKeyRequestType);
if (isCdmResponseTypeSuccess(res)) {
@@ -361,6 +363,7 @@ status_t WVDrmPlugin::getProvisionRequest(const String8& cert_type,
CdmResponseType res = mCDM->GetProvisioningRequest(cdmCertType,
cdmCertAuthority,
determineOrigin(),
&cdmProvisionRequest,
&cdmDefaultUrl);
@@ -384,7 +387,8 @@ status_t WVDrmPlugin::provideProvisionResponse(
CdmProvisioningResponse cdmResponse(response.begin(), response.end());
string cdmCertificate;
string cdmWrappedKey;
CdmResponseType res = mCDM->HandleProvisioningResponse(cdmResponse,
CdmResponseType res = mCDM->HandleProvisioningResponse(determineOrigin(),
cdmResponse,
&cdmCertificate,
&cdmWrappedKey);
if (isCdmResponseTypeSuccess(res)) {
@@ -403,8 +407,8 @@ status_t WVDrmPlugin::provideProvisionResponse(
}
status_t WVDrmPlugin::unprovisionDevice() {
CdmResponseType res1 = mCDM->Unprovision(kSecurityLevelL1);
CdmResponseType res3 = mCDM->Unprovision(kSecurityLevelL3);
CdmResponseType res1 = mCDM->Unprovision(kSecurityLevelL1, determineOrigin());
CdmResponseType res3 = mCDM->Unprovision(kSecurityLevelL3, determineOrigin());
if (!isCdmResponseTypeSuccess(res1))
{
return mapCdmResponseType(res1);
@@ -511,6 +515,8 @@ status_t WVDrmPlugin::getPropertyString(const String8& name,
return queryProperty(QUERY_KEY_MAX_NUMBER_OF_SESSIONS, value);
} else if (name == "appId") {
value = mPropertySet.app_id().c_str();
} else if (name == "origin") {
value = mOrigin.c_str();
} else {
ALOGE("App requested unknown string property %s", name.string());
return android::ERROR_DRM_CANNOT_HANDLE;
@@ -609,6 +615,18 @@ status_t WVDrmPlugin::setPropertyString(const String8& name,
ALOGE("App tried to set the application id while sessions are opened.");
return kErrorSessionIsOpen;
}
} else if (name == "origin") {
size_t sessionCount = 0;
{
Mutex::Autolock lock(mCryptoSessionsMutex);
sessionCount = mCryptoSessions.size();
}
if (sessionCount == 0) {
mOrigin = value.string();
} else {
ALOGE("App tried to set the origin while sessions are opened.");
return kErrorSessionIsOpen;
}
} else {
ALOGE("App set unknown string property %s", name.string());
return android::ERROR_DRM_CANNOT_HANDLE;
@@ -1009,4 +1027,8 @@ bool WVDrmPlugin::InitDataResemblesPSSH(const Vector<uint8_t>& initData) {
return id == kPsshTag;
}
const char* WVDrmPlugin::determineOrigin() const {
return mOrigin.empty() ? EMPTY_ORIGIN : mOrigin.c_str();
}
} // namespace wvdrm

View File

@@ -4,6 +4,7 @@
#include <stdio.h>
#include <string.h>
#include <ostream>
#include <string>
#include "cdm_client_property_set.h"
@@ -24,21 +25,28 @@ using namespace testing;
using namespace wvcdm;
using namespace wvdrm;
namespace {
const String8 kEmptyString;
const String8 kOrigin("widevine.com");
const String8 kAppId("com.unittest.mock.app.id");
}
class MockCDM : public WvContentDecryptionModule {
public:
MOCK_METHOD4(OpenSession, CdmResponseType(const CdmKeySystem&,
MOCK_METHOD5(OpenSession, CdmResponseType(const CdmKeySystem&,
CdmClientPropertySet*,
const std::string&,
WvCdmEventListener*,
CdmSessionId*));
MOCK_METHOD1(CloseSession, CdmResponseType(const CdmSessionId&));
MOCK_METHOD10(GenerateKeyRequest,
MOCK_METHOD11(GenerateKeyRequest,
CdmResponseType(const CdmSessionId&, const CdmKeySetId&,
const std::string&, const CdmInitData&,
const CdmLicenseType, CdmAppParameterMap&,
CdmClientPropertySet*, CdmKeyMessage*,
CdmKeyRequestType*, string*));
CdmClientPropertySet*, const std::string&,
CdmKeyMessage*, CdmKeyRequestType*, string*));
MOCK_METHOD3(AddKey, CdmResponseType(const CdmSessionId&,
const CdmKeyResponse&,
@@ -57,13 +65,18 @@ class MockCDM : public WvContentDecryptionModule {
MOCK_METHOD2(QueryKeyControlInfo, CdmResponseType(const CdmSessionId&,
CdmQueryMap*));
MOCK_METHOD4(GetProvisioningRequest, CdmResponseType(CdmCertificateType,
MOCK_METHOD5(GetProvisioningRequest, CdmResponseType(CdmCertificateType,
const std::string&,
const std::string&,
CdmProvisioningRequest*,
std::string*));
MOCK_METHOD3(HandleProvisioningResponse,
CdmResponseType(CdmProvisioningResponse&, std::string*, std::string*));
MOCK_METHOD4(HandleProvisioningResponse,
CdmResponseType(const std::string&, CdmProvisioningResponse&,
std::string*, std::string*));
MOCK_METHOD2(Unprovision, CdmResponseType(CdmSecurityLevel,
const std::string&));
MOCK_METHOD2(GetUsageInfo, CdmResponseType(const std::string&,
CdmUsageInfo*));
@@ -72,8 +85,6 @@ class MockCDM : public WvContentDecryptionModule {
const CdmSecureStopId&,
CdmUsageInfo*));
MOCK_METHOD1(Unprovision, CdmResponseType(CdmSecurityLevel));
MOCK_METHOD1(ReleaseAllUsageInfo, CdmResponseType(const std::string&));
MOCK_METHOD1(ReleaseUsageInfo,
@@ -149,14 +160,35 @@ class WVDrmPluginTest : public Test {
}
};
struct OriginTestVariant {
// For a test that does not expect any follow-up queries
OriginTestVariant(const std::string& nameValue, const String8& originValue,
const std::string& expectedOriginValue)
: name(nameValue), origin(originValue),
expectedOrigin(expectedOriginValue) {}
const std::string name;
const String8 origin;
const std::string expectedOrigin;
};
void PrintTo(const OriginTestVariant& param, ::std::ostream* os) {
*os << param.name << " Variant";
}
class WVDrmPluginOriginTest : public WVDrmPluginTest,
public WithParamInterface<OriginTestVariant> {};
TEST_F(WVDrmPluginTest, OpensSessions) {
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _, _, _))
.WillOnce(DoAll(SetArgPointee<3>(cdmSessionId),
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm,
OpenSession(StrEq("com.widevine"), _, StrEq(EMPTY_ORIGIN), _, _))
.WillOnce(DoAll(SetArgPointee<4>(cdmSessionId),
Return(wvcdm::NO_ERROR)));
// Provide expected behavior when plugin requests session control info
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
@@ -270,26 +302,27 @@ TEST_F(WVDrmPluginTest, GeneratesKeyRequests) {
EXPECT_CALL(cdm, GenerateKeyRequest(cdmSessionId, "", mimeType, initData,
kLicenseTypeOffline, cdmParameters, _,
_, _, _))
.WillOnce(DoAll(SetArgPointee<7>(cdmRequest),
SetArgPointee<8>(kKeyRequestTypeInitial),
SetArgPointee<9>(kDefaultUrl),
_, _, _, _))
.WillOnce(DoAll(SetArgPointee<8>(cdmRequest),
SetArgPointee<9>(kKeyRequestTypeInitial),
SetArgPointee<10>(kDefaultUrl),
Return(wvcdm::KEY_MESSAGE)));
EXPECT_CALL(cdm, GenerateKeyRequest(cdmSessionId, "", mimeType, initData,
kLicenseTypeStreaming, cdmParameters,
_, _, _, _))
.WillOnce(DoAll(SetArgPointee<7>(cdmRequest),
SetArgPointee<8>(kKeyRequestTypeRenewal),
SetArgPointee<9>(kDefaultUrl),
_, _, _, _, _))
.WillOnce(DoAll(SetArgPointee<8>(cdmRequest),
SetArgPointee<9>(kKeyRequestTypeRenewal),
SetArgPointee<10>(kDefaultUrl),
Return(wvcdm::KEY_MESSAGE)));
EXPECT_CALL(cdm, GenerateKeyRequest("", cdmKeySetId, mimeType, initData,
kLicenseTypeRelease, cdmParameters,
NotNull(), _, _, _))
.WillOnce(DoAll(SetArgPointee<7>(cdmRequest),
SetArgPointee<8>(kKeyRequestTypeRelease),
SetArgPointee<9>(kDefaultUrl),
NotNull(), StrEq(EMPTY_ORIGIN), _, _,
_))
.WillOnce(DoAll(SetArgPointee<8>(cdmRequest),
SetArgPointee<9>(kKeyRequestTypeRelease),
SetArgPointee<10>(kDefaultUrl),
Return(wvcdm::KEY_MESSAGE)));
}
}
@@ -384,10 +417,10 @@ TEST_F(WVDrmPluginTest, HandlesPrivacyCertCaseOfAddKey) {
// Provide expected behavior in response to OpenSession and store the
// property set
EXPECT_CALL(cdm, OpenSession(_, _, _, _))
.WillRepeatedly(DoAll(SetArgPointee<3>(cdmSessionId),
SaveArg<1>(&propertySet),
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, OpenSession(_, _, _, _, _))
.WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId),
SaveArg<1>(&propertySet),
Return(wvcdm::NO_ERROR)));
// Provide expected behavior when plugin requests session control info
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
@@ -512,9 +545,9 @@ TEST_F(WVDrmPluginTest, GetsProvisioningRequests) {
static const char* kDefaultUrl = "http://google.com/";
EXPECT_CALL(cdm, GetProvisioningRequest(kCertificateWidevine, IsEmpty(),
_, _))
.WillOnce(DoAll(SetArgPointee<2>(cdmRequest),
SetArgPointee<3>(kDefaultUrl),
EMPTY_ORIGIN, _, _))
.WillOnce(DoAll(SetArgPointee<3>(cdmRequest),
SetArgPointee<4>(kDefaultUrl),
Return(wvcdm::NO_ERROR)));
Vector<uint8_t> request;
@@ -542,7 +575,8 @@ TEST_F(WVDrmPluginTest, HandlesProvisioningResponses) {
Vector<uint8_t> response;
response.appendArray(responseRaw, kResponseSize);
EXPECT_CALL(cdm, HandleProvisioningResponse(ElementsAreArray(responseRaw,
EXPECT_CALL(cdm, HandleProvisioningResponse(EMPTY_ORIGIN,
ElementsAreArray(responseRaw,
kResponseSize),
_, _))
.Times(1);
@@ -560,9 +594,9 @@ TEST_F(WVDrmPluginTest, UnprovisionsDevice) {
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
EXPECT_CALL(cdm, Unprovision(kSecurityLevelL1))
EXPECT_CALL(cdm, Unprovision(kSecurityLevelL1, EMPTY_ORIGIN))
.Times(1);
EXPECT_CALL(cdm, Unprovision(kSecurityLevelL3))
EXPECT_CALL(cdm, Unprovision(kSecurityLevelL3, EMPTY_ORIGIN))
.Times(1);
status_t res = plugin.unprovisionDevice();
@@ -576,11 +610,11 @@ TEST_F(WVDrmPluginTest, MuxesUnprovisioningErrors) {
// Tests that both Unprovisions are called even if one fails. Also tests that
// no matter which fails, the function always propagates the error.
EXPECT_CALL(cdm, Unprovision(kSecurityLevelL1))
EXPECT_CALL(cdm, Unprovision(kSecurityLevelL1, EMPTY_ORIGIN))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR))
.WillOnce(Return(wvcdm::NO_ERROR))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
EXPECT_CALL(cdm, Unprovision(kSecurityLevelL3))
EXPECT_CALL(cdm, Unprovision(kSecurityLevelL3, EMPTY_ORIGIN))
.WillOnce(Return(wvcdm::NO_ERROR))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR))
.WillOnce(Return(wvcdm::UNKNOWN_ERROR));
@@ -824,9 +858,9 @@ TEST_F(WVDrmPluginTest, FailsGenericMethodsWithoutAnAlgorithmSet) {
bool match;
// Provide expected behavior to support session creation
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _, _, _))
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _, _, _, _))
.Times(AtLeast(1))
.WillRepeatedly(DoAll(SetArgPointee<3>(cdmSessionId),
.WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId),
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
@@ -903,9 +937,9 @@ TEST_F(WVDrmPluginTest, CallsGenericEncrypt) {
}
// Provide expected behavior to support session creation
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _, _, _))
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _, _, _, _))
.Times(AtLeast(1))
.WillRepeatedly(DoAll(SetArgPointee<3>(cdmSessionId),
.WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId),
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
@@ -963,9 +997,9 @@ TEST_F(WVDrmPluginTest, CallsGenericDecrypt) {
}
// Provide expected behavior to support session creation
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _, _, _))
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _, _, _, _))
.Times(AtLeast(1))
.WillRepeatedly(DoAll(SetArgPointee<3>(cdmSessionId),
.WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId),
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
@@ -1025,9 +1059,9 @@ TEST_F(WVDrmPluginTest, CallsGenericSign) {
}
// Provide expected behavior to support session creation
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _, _, _))
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _, _, _, _))
.Times(AtLeast(1))
.WillRepeatedly(DoAll(SetArgPointee<3>(cdmSessionId),
.WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId),
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
@@ -1097,9 +1131,9 @@ TEST_F(WVDrmPluginTest, CallsGenericVerify) {
}
// Provide expected behavior to support session creation
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _, _, _))
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _, _, _, _))
.Times(AtLeast(1))
.WillRepeatedly(DoAll(SetArgPointee<3>(cdmSessionId),
.WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId),
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
@@ -1130,9 +1164,9 @@ TEST_F(WVDrmPluginTest, RegistersForEvents) {
WVDrmPlugin plugin(&cdm, &crypto);
// Provide expected behavior to support session creation
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _, &plugin, _))
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _, _, &plugin, _))
.Times(AtLeast(1))
.WillRepeatedly(DoAll(SetArgPointee<3>(cdmSessionId),
.WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId),
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
@@ -1163,10 +1197,10 @@ TEST_F(WVDrmPluginTest, UnregistersForAllEventsOnDestruction) {
CdmSessionId cdmSessionId1(sessionIdRaw1, sessionIdRaw1 + kSessionIdSize);
CdmSessionId cdmSessionId2(sessionIdRaw2, sessionIdRaw2 + kSessionIdSize);
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _, _, _))
.WillOnce(DoAll(SetArgPointee<3>(cdmSessionId1),
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _, _, _, _))
.WillOnce(DoAll(SetArgPointee<4>(cdmSessionId1),
Return(wvcdm::NO_ERROR)))
.WillOnce(DoAll(SetArgPointee<3>(cdmSessionId2),
.WillOnce(DoAll(SetArgPointee<4>(cdmSessionId2),
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId1, _))
@@ -1281,9 +1315,9 @@ TEST_F(WVDrmPluginTest, GeneratesProvisioningNeededEvent) {
NULL))
.Times(1);
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _, _, _))
EXPECT_CALL(cdm, OpenSession(StrEq("com.widevine"), _, _, _, _))
.Times(AtLeast(1))
.WillRepeatedly(DoAll(SetArgPointee<3>(cdmSessionId),
.WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId),
Return(wvcdm::NEED_PROVISIONING)));
EXPECT_CALL(cdm, CloseSession(_))
@@ -1307,10 +1341,10 @@ TEST_F(WVDrmPluginTest, ProvidesExpectedDefaultPropertiesToCdm) {
{
// Provide expected behavior in response to OpenSession and store the
// property set
EXPECT_CALL(cdm, OpenSession(_, _, _, _))
.WillRepeatedly(DoAll(SetArgPointee<3>(cdmSessionId),
SaveArg<1>(&propertySet),
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, OpenSession(_, _, _, _, _))
.WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId),
SaveArg<1>(&propertySet),
Return(wvcdm::NO_ERROR)));
// Provide expected behavior when plugin requests session control info
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
@@ -1330,6 +1364,7 @@ TEST_F(WVDrmPluginTest, ProvidesExpectedDefaultPropertiesToCdm) {
EXPECT_EQ(0u, propertySet->session_sharing_id());
EXPECT_STREQ("", propertySet->app_id().c_str());
}
TEST_F(WVDrmPluginTest, CanSetAppId) {
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
@@ -1337,14 +1372,22 @@ TEST_F(WVDrmPluginTest, CanSetAppId) {
const CdmClientPropertySet* propertySet = NULL;
CdmQueryMap l3Map;
l3Map[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L3;
// Provide expected mock behavior
{
// Provide expected behavior in response to OpenSession and store the
// property set
EXPECT_CALL(cdm, OpenSession(_, _, _, _))
.WillRepeatedly(DoAll(SetArgPointee<3>(cdmSessionId),
SaveArg<1>(&propertySet),
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, OpenSession(_, _, _, _, _))
.WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId),
SaveArg<1>(&propertySet),
Return(wvcdm::NO_ERROR)));
// Provide expected behavior when plugin queries for the security level
EXPECT_CALL(cdm, QueryStatus(_))
.WillRepeatedly(DoAll(SetArgPointee<0>(l3Map),
Return(wvcdm::NO_ERROR)));
// Provide expected behavior when plugin requests session control info
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
@@ -1361,7 +1404,6 @@ TEST_F(WVDrmPluginTest, CanSetAppId) {
ASSERT_EQ(OK, res);
// Test setting an application id before a session is opened.
const String8 kAppId("com.unittest.mock.app.id");
res = plugin.setPropertyString(String8("appId"), kAppId);
ASSERT_EQ(OK, res);
@@ -1376,6 +1418,42 @@ TEST_F(WVDrmPluginTest, CanSetAppId) {
ASSERT_EQ(kErrorSessionIsOpen, res);
}
TEST_P(WVDrmPluginOriginTest, CanSetOrigin) {
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
WVDrmPlugin plugin(&cdm, &crypto);
OriginTestVariant params = GetParam();
// Provide expected mock behavior
{
// Provide expected behavior when plugin requests session control info
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
.WillRepeatedly(Invoke(setSessionIdOnMap<4>));
// Provide expected behavior when plugin closes a session
EXPECT_CALL(cdm, CloseSession(_))
.Times(AtLeast(0));
}
// Note which mock calls we expect
EXPECT_CALL(cdm, OpenSession(_, _, StrEq(params.expectedOrigin), _, _))
.WillOnce(DoAll(SetArgPointee<4>(cdmSessionId),
Return(wvcdm::NO_ERROR)));
// Set the properties & run the test
if (!params.origin.isEmpty()) {
ASSERT_EQ(OK, plugin.setPropertyString(String8("origin"), params.origin));
}
EXPECT_EQ(OK, plugin.openSession(sessionId));
// Test setting an origin while sessions are opened. This should fail.
EXPECT_NE(OK, plugin.setPropertyString(String8("origin"), kOrigin));
EXPECT_EQ(OK, plugin.closeSession(sessionId));
}
INSTANTIATE_TEST_CASE_P(OriginTests, WVDrmPluginOriginTest, Values(
OriginTestVariant("No Origin", kEmptyString, EMPTY_ORIGIN),
OriginTestVariant("With an Origin", kOrigin, kOrigin.string())));
TEST_F(WVDrmPluginTest, CanSetSecurityLevel) {
StrictMock<MockCDM> cdm;
StrictMock<MockCrypto> crypto;
@@ -1399,10 +1477,10 @@ TEST_F(WVDrmPluginTest, CanSetSecurityLevel) {
{
// Provide expected behavior in response to OpenSession and store the
// property set
EXPECT_CALL(cdm, OpenSession(_, _, _, _))
.WillRepeatedly(DoAll(SetArgPointee<3>(cdmSessionId),
SaveArg<1>(&propertySet),
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, OpenSession(_, _, _, _, _))
.WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId),
SaveArg<1>(&propertySet),
Return(wvcdm::NO_ERROR)));
// Provide expected behavior when plugin requests session control info
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
@@ -1484,10 +1562,10 @@ TEST_F(WVDrmPluginTest, CanSetPrivacyMode) {
{
// Provide expected behavior in response to OpenSession and store the
// property set
EXPECT_CALL(cdm, OpenSession(_, _, _, _))
.WillRepeatedly(DoAll(SetArgPointee<3>(cdmSessionId),
SaveArg<1>(&propertySet),
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, OpenSession(_, _, _, _, _))
.WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId),
SaveArg<1>(&propertySet),
Return(wvcdm::NO_ERROR)));
// Provide expected behavior when plugin requests session control info
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
@@ -1539,10 +1617,10 @@ TEST_F(WVDrmPluginTest, CanSetServiceCertificate) {
{
// Provide expected behavior in response to OpenSession and store the
// property set
EXPECT_CALL(cdm, OpenSession(_, _, _, _))
.WillRepeatedly(DoAll(SetArgPointee<3>(cdmSessionId),
SaveArg<1>(&propertySet),
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, OpenSession(_, _, _, _, _))
.WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId),
SaveArg<1>(&propertySet),
Return(wvcdm::NO_ERROR)));
// Provide expected behavior when plugin requests session control info
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
@@ -1580,10 +1658,10 @@ TEST_F(WVDrmPluginTest, CanSetSessionSharing) {
{
// Provide expected behavior in response to OpenSession and store the
// property set
EXPECT_CALL(cdm, OpenSession(_, _, _, _))
.WillRepeatedly(DoAll(SetArgPointee<3>(cdmSessionId),
SaveArg<1>(&propertySet),
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, OpenSession(_, _, _, _, _))
.WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId),
SaveArg<1>(&propertySet),
Return(wvcdm::NO_ERROR)));
// Provide expected behavior when plugin requests session control info
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))
@@ -1639,10 +1717,10 @@ TEST_F(WVDrmPluginTest, AllowsStoringOfSessionSharingId) {
{
// Provide expected behavior in response to OpenSession and store the
// property set
EXPECT_CALL(cdm, OpenSession(_, _, _, _))
.WillRepeatedly(DoAll(SetArgPointee<3>(cdmSessionId),
SaveArg<1>(&propertySet),
Return(wvcdm::NO_ERROR)));
EXPECT_CALL(cdm, OpenSession(_, _, _, _, _))
.WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId),
SaveArg<1>(&propertySet),
Return(wvcdm::NO_ERROR)));
// Provide expected behavior when plugin requests session control info
EXPECT_CALL(cdm, QueryKeyControlInfo(cdmSessionId, _))