Source release v3.2.0

This commit is contained in:
Gene Morgan
2017-02-01 16:36:41 -08:00
parent 643b91b616
commit 2fde891c01
370 changed files with 40622 additions and 276133 deletions

View File

@@ -17,6 +17,7 @@
#include "license.h"
#include "log.h"
#include "properties.h"
#include "string_conversions.h"
#include "wv_cdm_constants.h"
#include "wv_cdm_event_listener.h"
@@ -114,7 +115,16 @@ class CdmImpl : public Cdm,
virtual ~CdmImpl();
// Cdm:
virtual Status setServerCertificate(const std::string& certificate) OVERRIDE;
virtual Status setServiceCertificate(const std::string& certificate) OVERRIDE;
virtual bool isProvisioned() OVERRIDE;
virtual Status removeProvisioning() OVERRIDE;
virtual Status removeUsageTable() OVERRIDE;
virtual Status listStoredLicenses(
std::vector<std::string>* key_set_ids) OVERRIDE;
virtual Status createSession(SessionType session_type,
std::string* session_id) OVERRIDE;
@@ -177,6 +187,8 @@ class CdmImpl : public Cdm,
const std::string& key_id, GenericSigningAlgorithmType algorithm,
const std::string& signature) OVERRIDE;
virtual Status setVideoResolution(const std::string& session_id,
uint32_t width, uint32_t height) OVERRIDE;
// ITimerClient:
virtual void onTimerExpired(void* context) OVERRIDE;
@@ -251,29 +263,55 @@ CdmImpl::~CdmImpl() {
host.timer->cancel(this);
}
Cdm::Status CdmImpl::setServerCertificate(const std::string& certificate) {
if (!property_set_.use_privacy_mode()) {
LOGE("Cannot set server certificate if privacy mode is disabled.");
return kNotSupported;
}
Cdm::Status CdmImpl::setServiceCertificate(const std::string& certificate) {
if (certificate.empty()) {
LOGE("An empty server certificate is invalid.");
return kTypeError;
LOGW("An empty licensing service certificate may be invalid.");
}
if (CdmLicense::VerifySignedServiceCertificate(certificate) != NO_ERROR) {
LOGE("Invalid server certificate!");
// Check for properly signed and well-formed certificate.
// Keep results. NOTE: an empty certificate should be accepted here.
CdmResponseType status = cdm_engine_.SetServiceCertificate(certificate);
if (status != NO_ERROR) {
LOGE("Invalid service certificate! Error code = %d", status);
return kTypeError;
}
return kSuccess;
}
property_set_.set_service_certificate(certificate);
bool CdmImpl::isProvisioned() {
return cdm_engine_.IsProvisioned(kSecurityLevelL1);
}
Cdm::Status CdmImpl::removeProvisioning() {
if (cdm_engine_.Unprovision(kSecurityLevelL1) != NO_ERROR) {
return kUnexpectedError;
}
return kSuccess;
}
Cdm::Status CdmImpl::removeUsageTable() {
if (cdm_engine_.DeleteUsageTable(kSecurityLevelL1) != NO_ERROR) {
return kUnexpectedError;
}
return kSuccess;
}
Cdm::Status CdmImpl::listStoredLicenses(std::vector<std::string>* key_set_ids) {
if (key_set_ids == NULL) {
LOGE("Missing vector parameter to receive key_set_ids.");
return kTypeError;
}
if (cdm_engine_.ListStoredLicenses(kSecurityLevelL1, key_set_ids) !=
NO_ERROR) {
return kUnexpectedError;
}
return kSuccess;
}
Cdm::Status CdmImpl::createSession(SessionType session_type,
std::string* session_id) {
if (NULL == session_id) {
if (session_id == NULL) {
LOGE("Missing session ID pointer.");
return kTypeError;
}
@@ -420,21 +458,8 @@ Cdm::Status CdmImpl::generateRequest(const std::string& session_id,
sessions_[session_id].callable = true;
assert(key_request.type == kKeyRequestTypeInitial);
MessageType message_type;
if (property_set_.use_privacy_mode() &&
property_set_.service_certificate().empty()) {
// We can deduce that this is a server cert request, even though CdmEgine
// cannot currently inform us of this.
// Previously, we used message type kIndividiualizationRequest for this.
// The EME editor has clarified that this was a misinterpretation of the
// spec, and that this should also be kLicenseRequest.
LOGI("A server certificate request has been generated.");
message_type = kLicenseRequest;
} else {
LOGI("A license request has been generated.");
message_type = kLicenseRequest;
}
listener_->onMessage(session_id, message_type, key_request.message);
LOGI("A license request has been generated.");
listener_->onMessage(session_id, kLicenseRequest, key_request.message);
return kSuccess;
}
@@ -449,8 +474,9 @@ Cdm::Status CdmImpl::load(const std::string& session_id) {
return kQuotaExceeded;
}
CdmResponseType result = cdm_engine_.OpenSession(
"com.widevine.alpha", &property_set_, session_id, this);
CdmResponseType result = cdm_engine_.OpenSession("com.widevine.alpha",
&property_set_, session_id,
this);
switch (result) {
case NO_ERROR:
break;
@@ -504,6 +530,13 @@ Cdm::Status CdmImpl::load(const std::string& session_id) {
return kUnexpectedError;
}
if (!policy_timer_enabled_) {
policy_timer_enabled_ = true;
host.timer->setTimeout(kPolicyTimerDurationMilliseconds,
this,
kPolicyTimerContext);
}
sessions_[session_id].type = kPersistentLicense;
sessions_[session_id].callable = true;
return kSuccess;
@@ -590,34 +623,10 @@ Cdm::Status CdmImpl::update(const std::string& session_id,
CdmResponseType result =
cdm_engine_.AddKey(session_id, response, &key_set_id);
if (result == NEED_KEY) {
// We just provisioned a server certificate.
assert(property_set_.use_privacy_mode());
// The cert is now available to all sessions in this CDM instance.
// This is consistent with the behavior of the Chrome CDM.
assert(!property_set_.service_certificate().empty());
// The underlying session in CdmEngine has stored a copy of the original
// init data, so we can use an empty one this time.
InitializationData empty_init_data;
CdmKeyRequest key_request;
CdmResponseType result = cdm_engine_.GenerateKeyRequest(
session_id, session_id, empty_init_data, kLicenseTypeDeferred,
app_parameters_, &key_request);
if (result != KEY_MESSAGE) {
LOGE("Unexpected error %d", result);
return kUnexpectedError;
}
LOGI("A deferred license request has been generated.");
assert(key_request.type == kKeyRequestTypeInitial);
MessageType message_type = kLicenseRequest;
listener_->onMessage(session_id, message_type, key_request.message);
return kSuccess;
} else if (result == OFFLINE_LICENSE_PROHIBITED) {
// result should only be NEED_KEY after server certificate provisioning, which
// should no longer happen in this version of the CDM.
assert(result != NEED_KEY);
if (result == OFFLINE_LICENSE_PROHIBITED) {
LOGE("A temporary session cannot be used for a persistent license.");
return kRangeError;
} else if (result == STORAGE_PROHIBITED) {
@@ -986,6 +995,22 @@ Cdm::Status CdmImpl::genericVerify(
return kUnexpectedError;
}
Cdm::Status CdmImpl::setVideoResolution(const std::string& session_id,
uint32_t width, uint32_t height) {
// Verify that width * height will fit into a 32-bit quantity.
// This is done to be compatible with the video resolution in the
// license policy settings.
uint64_t pixels = width;
pixels *= height;
if (pixels >= (1ULL << 32))
return kRangeError;
if (cdm_engine_.NotifyResolution(session_id, width, height)) {
return kSuccess;
} else {
return kSessionNotFound;
}
}
void CdmImpl::onTimerExpired(void* context) {
if (context == kPolicyTimerContext) {
if (policy_timer_enabled_) {
@@ -1127,16 +1152,20 @@ Cdm::Status Cdm::initialize(
IClock* clock,
ITimer* timer,
LogLevel verbosity) {
// If you want to direct-render on L3, CryptoSession will pass that request
// along to OEMCrypto. But if you want to use an opaque handle on L3,
// CryptoSession will silently ignore you and tell OEMCrypto to treat the
// address as a clear buffer. :-(
// Specify the maximum severity of message that will be output to
// the console. See core/include/log.h for the valid priority values.
g_cutoff = static_cast<LogPriority>(verbosity);
// If you want to direct-render on L3, CryptoSession will pass that
// request along to OEMCrypto. But if you want to use an opaque
// handle on L3, CryptoSession will silently ignore you and tell
// OEMCrypto to treat the address as a clear buffer.
//
// So this logic mirrors that in CryptoSession. Effectively, we are
// detecting at init time the conditions that would prevent CryptoSession (in
// its current form) from passing the desired buffer type constant to
// OEMCrypto.
// TODO: Discuss changes to CryptoSession.
// So this logic mirrors that in CryptoSession. Effectively, we
// are detecting at init time the conditions that would prevent
// CryptoSession (in its current form) from passing the desired
// buffer type constant to OEMCrypto.
switch (secure_output_type) {
case kOpaqueHandle:
// This output type requires an OEMCrypto that reports L1.
@@ -1166,9 +1195,6 @@ Cdm::Status Cdm::initialize(
return kTypeError;
}
// Our enum values match those in core/include/log.h
g_cutoff = static_cast<LogPriority>(verbosity);
PropertiesCE::SetSecureOutputType(secure_output_type);
PropertiesCE::SetClientInfo(client_info);
Properties::Init();
@@ -1267,14 +1293,14 @@ class FileSystem::Impl {
widevine::Cdm::IStorage* storage;
};
FileSystem::FileSystem() : FileSystem("", NULL) {}
FileSystem::FileSystem() : impl_(new Impl) {
impl_->storage = host.storage;
}
FileSystem::FileSystem(const std::string& origin, void* extra_data)
: impl_(new Impl), origin_(origin) {
if (extra_data)
impl_->storage = (widevine::Cdm::IStorage*)extra_data;
else
impl_->storage = host.storage;
assert(NULL != extra_data);
impl_->storage = (widevine::Cdm::IStorage*)extra_data;
}
FileSystem::~FileSystem() {
@@ -1316,4 +1342,12 @@ ssize_t FileSystem::FileSize(const std::string& file_path) {
return impl_->storage->size(file_path);
}
bool FileSystem::List(const std::string&,
std::vector<std::string>* file_names) {
if (!impl_ || !file_names)
return false;
return impl_->storage->list(file_names);
}
} // namespace wvcdm

View File

@@ -143,4 +143,9 @@ bool Properties::AlwaysUseKeySetIds() {
return true;
}
// static
bool Properties::UseProviderIdInProvisioningRequest() {
return true;
}
} // namespace wvcdm