Source release v3.0.4
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "cdm_engine.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <iostream>
|
||||
@@ -10,6 +11,7 @@
|
||||
#include "cdm_session.h"
|
||||
#include "clock.h"
|
||||
#include "device_files.h"
|
||||
#include "file_store.h"
|
||||
#include "license_protocol.pb.h"
|
||||
#include "log.h"
|
||||
#include "properties.h"
|
||||
@@ -227,7 +229,8 @@ CdmResponseType CdmEngine::GenerateKeyRequest(
|
||||
|
||||
key_request->clear();
|
||||
|
||||
if (license_type == kLicenseTypeRelease) {
|
||||
if (license_type == kLicenseTypeRelease &&
|
||||
!iter->second->license_received()) {
|
||||
sts = iter->second->RestoreOfflineSession(key_set_id, kLicenseTypeRelease);
|
||||
if (sts != KEY_ADDED) {
|
||||
LOGE("CdmEngine::GenerateKeyRequest: key release restoration failed,"
|
||||
@@ -338,7 +341,7 @@ CdmResponseType CdmEngine::RestoreKey(const CdmSessionId& session_id,
|
||||
if (sts != KEY_ADDED && sts != GET_RELEASED_LICENSE_ERROR) {
|
||||
LOGE("CdmEngine::RestoreKey: restore offline session failed = %d", sts);
|
||||
}
|
||||
return sts; // TODO ewew
|
||||
return sts;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::RemoveKeys(const CdmSessionId& session_id) {
|
||||
@@ -602,6 +605,9 @@ CdmResponseType CdmEngine::GetProvisioningRequest(
|
||||
LOGE("CdmEngine::GetProvisioningRequest: invalid output parameters");
|
||||
return INVALID_PROVISIONING_REQUEST_PARAM_2;
|
||||
}
|
||||
|
||||
DeleteAllUsageReportsUponFactoryReset();
|
||||
|
||||
if (NULL == cert_provisioning_.get()) {
|
||||
cert_provisioning_.reset(new CertificateProvisioning());
|
||||
}
|
||||
@@ -663,6 +669,7 @@ CdmResponseType CdmEngine::HandleProvisioningResponse(
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType ret = cert_provisioning_->HandleProvisioningResponse(
|
||||
origin, response, cert, wrapped_key);
|
||||
// Release resources only on success. It is possible that a provisioning
|
||||
@@ -928,6 +935,66 @@ CdmResponseType CdmEngine::ReleaseUsageInfo(
|
||||
return status;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::LoadUsageSession(const CdmKeySetId& key_set_id,
|
||||
CdmKeyMessage* release_message) {
|
||||
LOGI("CdmEngine::LoadUsageSession");
|
||||
// This method is currently only used by the CE CDM, in which all session IDs
|
||||
// are key set IDs.
|
||||
assert(Properties::AlwaysUseKeySetIds());
|
||||
|
||||
if (key_set_id.empty()) {
|
||||
LOGE("CdmEngine::LoadUsageSession: invalid key set id");
|
||||
return EMPTY_KEYSET_ID_ENG_5;
|
||||
}
|
||||
|
||||
CdmSessionMap::iterator iter = sessions_.find(key_set_id);
|
||||
if (iter == sessions_.end()) {
|
||||
LOGE("CdmEngine::LoadUsageSession: session_id not found = %s ",
|
||||
key_set_id.c_str());
|
||||
return SESSION_NOT_FOUND_11;
|
||||
}
|
||||
|
||||
DeviceFiles handle;
|
||||
if (!handle.Init(iter->second->GetSecurityLevel())) {
|
||||
LOGE("CdmEngine::LoadUsageSession: unable to initialize device files");
|
||||
return LOAD_USAGE_INFO_FILE_ERROR;
|
||||
}
|
||||
|
||||
std::string app_id;
|
||||
iter->second->GetApplicationId(&app_id);
|
||||
|
||||
CdmKeyMessage key_message;
|
||||
CdmKeyResponse key_response;
|
||||
if (!handle.RetrieveUsageInfoByKeySetId(app_id, key_set_id, &key_message,
|
||||
&key_response)) {
|
||||
LOGE("CdmEngine::LoadUsageSession: unable to find usage information");
|
||||
return LOAD_USAGE_INFO_MISSING;
|
||||
}
|
||||
|
||||
CdmResponseType status =
|
||||
iter->second->RestoreUsageSession(key_message, key_response);
|
||||
if (KEY_ADDED != status) {
|
||||
LOGE("CdmEngine::LoadUsageSession: usage session error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
std::string server_url;
|
||||
status = iter->second->GenerateReleaseRequest(release_message, &server_url);
|
||||
|
||||
switch (status) {
|
||||
case KEY_MESSAGE:
|
||||
break;
|
||||
case KEY_CANCELED: // usage information not present in
|
||||
iter->second->DeleteLicense(); // OEMCrypto, delete and try again
|
||||
break;
|
||||
default:
|
||||
LOGE("CdmEngine::LoadUsageSession: generate release request error: %d",
|
||||
status);
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::Decrypt(const CdmSessionId& session_id,
|
||||
const CdmDecryptionParameters& parameters) {
|
||||
if (parameters.key_id == NULL) {
|
||||
@@ -1097,4 +1164,34 @@ std::string CdmEngine::MapHdcpVersion(
|
||||
return "";
|
||||
}
|
||||
|
||||
void CdmEngine::DeleteAllUsageReportsUponFactoryReset() {
|
||||
std::string device_base_path_level1 = "";
|
||||
std::string device_base_path_level3 = "";
|
||||
Properties::GetDeviceFilesBasePath(kSecurityLevelL1,
|
||||
&device_base_path_level1);
|
||||
Properties::GetDeviceFilesBasePath(kSecurityLevelL3,
|
||||
&device_base_path_level3);
|
||||
|
||||
File file;
|
||||
if (!file.Exists(device_base_path_level1) &&
|
||||
!file.Exists(device_base_path_level3)) {
|
||||
scoped_ptr<CryptoSession> crypto_session(new CryptoSession());
|
||||
CdmResponseType status = crypto_session->Open(
|
||||
cert_provisioning_requested_security_level_);
|
||||
if (NO_ERROR == status) {
|
||||
status = crypto_session->DeleteAllUsageReports();
|
||||
if (NO_ERROR != status) {
|
||||
LOGW(
|
||||
"CdmEngine::GetProvisioningRequest: "
|
||||
"Fails to delete usage reports: %d", status);
|
||||
}
|
||||
} else {
|
||||
LOGW(
|
||||
"CdmEngine::GetProvisioningRequest: "
|
||||
"Fails to open crypto session: error=%d.\n"
|
||||
"Usage reports are not removed after factory reset.", status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
@@ -37,6 +37,7 @@ CdmSession::CdmSession(CdmClientPropertySet* cdm_client_property_set,
|
||||
license_received_(false),
|
||||
is_offline_(false),
|
||||
is_release_(false),
|
||||
is_temporary_(false),
|
||||
security_level_(kSecurityLevelUninitialized),
|
||||
requested_security_level_(kLevelDefault),
|
||||
is_initial_decryption_(true),
|
||||
@@ -66,7 +67,13 @@ CdmSession::CdmSession(CdmClientPropertySet* cdm_client_property_set,
|
||||
}
|
||||
}
|
||||
|
||||
CdmSession::~CdmSession() { Properties::RemoveSessionPropertySet(session_id_); }
|
||||
CdmSession::~CdmSession() {
|
||||
if (!key_set_id_.empty()) {
|
||||
// Unreserve the license ID.
|
||||
file_handle_->UnreserveLicenseId(key_set_id_);
|
||||
}
|
||||
Properties::RemoveSessionPropertySet(session_id_);
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::Init() {
|
||||
if (session_id_.empty()) {
|
||||
@@ -184,6 +191,9 @@ CdmResponseType CdmSession::GenerateKeyRequest(
|
||||
}
|
||||
|
||||
switch (license_type) {
|
||||
case kLicenseTypeTemporary:
|
||||
is_temporary_ = true;
|
||||
break;
|
||||
case kLicenseTypeStreaming:
|
||||
is_offline_ = false;
|
||||
break;
|
||||
@@ -207,6 +217,8 @@ CdmResponseType CdmSession::GenerateKeyRequest(
|
||||
license_type = kLicenseTypeRelease;
|
||||
} else if (is_offline_) {
|
||||
license_type = kLicenseTypeOffline;
|
||||
} else if (is_temporary_) {
|
||||
license_type = kLicenseTypeTemporary;
|
||||
} else {
|
||||
license_type = kLicenseTypeStreaming;
|
||||
}
|
||||
@@ -484,12 +496,22 @@ bool CdmSession::GenerateKeySetId(CdmKeySetId* key_set_id) {
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::StoreLicense() {
|
||||
if (is_temporary_) {
|
||||
LOGE("CdmSession::StoreLicense: Session type prohibits storage.");
|
||||
return STORAGE_PROHIBITED;
|
||||
}
|
||||
|
||||
if (is_offline_) {
|
||||
if (key_set_id_.empty()) {
|
||||
LOGE("CdmSession::StoreLicense: No key set ID");
|
||||
return EMPTY_KEYSET_ID;
|
||||
}
|
||||
|
||||
if (!license_parser_->is_offline()) {
|
||||
LOGE("CdmSession::StoreLicense: License policy prohibits storage.");
|
||||
return OFFLINE_LICENSE_PROHIBITED;
|
||||
}
|
||||
|
||||
if (!StoreLicense(DeviceFiles::kLicenseStateActive)) {
|
||||
LOGE("CdmSession::StoreLicense: Unable to store license");
|
||||
CdmResponseType sts = Init();
|
||||
@@ -502,7 +524,7 @@ CdmResponseType CdmSession::StoreLicense() {
|
||||
return STORE_LICENSE_ERROR_1;
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
} // if (is_offline_)
|
||||
|
||||
std::string provider_session_token =
|
||||
license_parser_->provider_session_token();
|
||||
@@ -519,7 +541,7 @@ CdmResponseType CdmSession::StoreLicense() {
|
||||
std::string app_id;
|
||||
GetApplicationId(&app_id);
|
||||
if (!file_handle_->StoreUsageInfo(provider_session_token, key_request_,
|
||||
key_response_, app_id)) {
|
||||
key_response_, app_id, key_set_id_)) {
|
||||
LOGE("CdmSession::StoreLicense: Unable to store usage info");
|
||||
return STORE_USAGE_INFO_ERROR;
|
||||
}
|
||||
|
||||
@@ -343,10 +343,20 @@ bool DeviceFiles::ReserveLicenseId(const std::string& key_set_id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeviceFiles::UnreserveLicenseId(const std::string& key_set_id) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::UnreserveLicenseId: not initialized");
|
||||
return false;
|
||||
}
|
||||
reserved_license_ids_.erase(key_set_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeviceFiles::StoreUsageInfo(const std::string& provider_session_token,
|
||||
const CdmKeyMessage& key_request,
|
||||
const CdmKeyResponse& key_response,
|
||||
const std::string& app_id) {
|
||||
const std::string& app_id,
|
||||
const std::string& key_set_id) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::StoreUsageInfo: not initialized");
|
||||
return false;
|
||||
@@ -372,6 +382,7 @@ bool DeviceFiles::StoreUsageInfo(const std::string& provider_session_token,
|
||||
provider_session_token.size());
|
||||
provider_session->set_license_request(key_request.data(), key_request.size());
|
||||
provider_session->set_license(key_response.data(), key_response.size());
|
||||
provider_session->set_key_set_id(key_set_id.data(), key_set_id.size());
|
||||
|
||||
file.SerializeToString(&serialized_file);
|
||||
return StoreFileWithHash(file_name, serialized_file);
|
||||
@@ -513,22 +524,48 @@ bool DeviceFiles::RetrieveUsageInfo(const std::string& app_id,
|
||||
LOGW("DeviceFiles::RetrieveUsageInfo: Unable to parse file");
|
||||
return false;
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
bool found = false;
|
||||
for (; index < file.usage_info().sessions_size(); ++index) {
|
||||
if (file.usage_info().sessions(index).token() == provider_session_token) {
|
||||
found = true;
|
||||
break;
|
||||
*license_request = file.usage_info().sessions(index).license_request();
|
||||
*license_response = file.usage_info().sessions(index).license();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DeviceFiles::RetrieveUsageInfoByKeySetId(
|
||||
const std::string& app_id,
|
||||
const std::string& key_set_id,
|
||||
CdmKeyMessage* license_request,
|
||||
CdmKeyResponse* license_response) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::RetrieveUsageInfoByKeySetId: not initialized");
|
||||
return false;
|
||||
}
|
||||
std::string serialized_file;
|
||||
std::string file_name = GetUsageInfoFileName(app_id);
|
||||
if (!RetrieveHashedFile(file_name, &serialized_file)) return false;
|
||||
|
||||
video_widevine_client::sdk::File file;
|
||||
if (!file.ParseFromString(serialized_file)) {
|
||||
LOGW("DeviceFiles::RetrieveUsageInfoByKeySetId: Unable to parse file");
|
||||
return false;
|
||||
}
|
||||
|
||||
*license_request = file.usage_info().sessions(index).license_request();
|
||||
*license_response = file.usage_info().sessions(index).license();
|
||||
return true;
|
||||
int index = 0;
|
||||
for (; index < file.usage_info().sessions_size(); ++index) {
|
||||
if (file.usage_info().sessions(index).key_set_id() == key_set_id) {
|
||||
*license_request = file.usage_info().sessions(index).license_request();
|
||||
*license_response = file.usage_info().sessions(index).license();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DeviceFiles::StoreFileWithHash(const std::string& name,
|
||||
|
||||
@@ -46,6 +46,7 @@ message UsageInfo {
|
||||
optional bytes token = 1;
|
||||
optional bytes license_request = 2;
|
||||
optional bytes license = 3;
|
||||
optional bytes key_set_id = 4;
|
||||
}
|
||||
|
||||
repeated ProviderSession sessions = 1;
|
||||
|
||||
@@ -132,6 +132,7 @@ CdmLicense::CdmLicense(const CdmSessionId& session_id)
|
||||
session_id_(session_id),
|
||||
initialized_(false),
|
||||
renew_with_client_id_(false),
|
||||
is_offline_(false),
|
||||
clock_(new Clock()) {}
|
||||
|
||||
CdmLicense::CdmLicense(const CdmSessionId& session_id, Clock* clock)
|
||||
@@ -139,7 +140,8 @@ CdmLicense::CdmLicense(const CdmSessionId& session_id, Clock* clock)
|
||||
policy_engine_(NULL),
|
||||
session_id_(session_id),
|
||||
initialized_(false),
|
||||
renew_with_client_id_(false) {
|
||||
renew_with_client_id_(false),
|
||||
is_offline_(false) {
|
||||
clock_.reset(clock);
|
||||
}
|
||||
|
||||
@@ -522,6 +524,10 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
||||
return NO_CONTENT_KEY;
|
||||
}
|
||||
|
||||
if (license.id().type() == video_widevine_server::sdk::OFFLINE &&
|
||||
license.policy().can_persist())
|
||||
is_offline_ = true;
|
||||
|
||||
if (license.id().has_provider_session_token())
|
||||
provider_session_token_ = license.id().provider_session_token();
|
||||
|
||||
@@ -1102,6 +1108,7 @@ bool CdmLicense::PrepareContentId(const CdmLicenseType license_type,
|
||||
content_id->set_license_type(video_widevine_server::sdk::OFFLINE);
|
||||
break;
|
||||
case kLicenseTypeStreaming:
|
||||
case kLicenseTypeTemporary:
|
||||
content_id->set_license_type(video_widevine_server::sdk::STREAMING);
|
||||
break;
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user