Refactored ProvisioningHolder to separate operations.
[ Merge of http://go/wvgerrit/219451 ] An upcoming provisioning test requires the ability to perform generate, fetch and load operations separately (similar to the current behavior of LicenseHolder). This CL separates the 3 operations into different methods and documents the pre/post conditions of each. The original API is maintained for backwards compatibility. VIC-specific: Excludes Golden-data refactoring and merges main change (216510) and typo fix (216570). Bug: 391469176 Test: run_x86_64_tests Change-Id: Iec83dfce9d235eedf04ed32d98f7700de4bade12
This commit is contained in:
@@ -20,88 +20,111 @@ namespace wvcdm {
|
|||||||
|
|
||||||
void ProvisioningHolder::Provision(CdmCertificateType cert_type,
|
void ProvisioningHolder::Provision(CdmCertificateType cert_type,
|
||||||
bool binary_provisioning) {
|
bool binary_provisioning) {
|
||||||
CdmProvisioningRequest request;
|
ASSERT_NO_FATAL_FAILURE(GenerateRequest(cert_type, binary_provisioning))
|
||||||
std::string provisioning_server_url;
|
<< "Failed to generate request";
|
||||||
|
ASSERT_NO_FATAL_FAILURE(FetchResponse()) << "Failed to fetch response";
|
||||||
|
ASSERT_NO_FATAL_FAILURE(LoadResponse(binary_provisioning))
|
||||||
|
<< "Failed to load response";
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProvisioningHolder::GenerateRequest(CdmCertificateType cert_type,
|
||||||
|
bool binary_provisioning) {
|
||||||
|
// Preconditions.
|
||||||
|
ASSERT_NE(cdm_engine_, nullptr) << "CdmEngine instance not set";
|
||||||
|
|
||||||
|
// Set cert authority if using X.509.
|
||||||
std::string cert_authority;
|
std::string cert_authority;
|
||||||
|
|
||||||
CdmSessionId session_id;
|
|
||||||
|
|
||||||
if (cert_type == kCertificateX509) {
|
if (cert_type == kCertificateX509) {
|
||||||
cert_authority = "cast.google.com";
|
cert_authority = "cast.google.com";
|
||||||
}
|
}
|
||||||
LOGV("Provision with type %s.", CdmCertificateTypeToString(cert_type));
|
LOGV("Provision with type %s.", CdmCertificateTypeToString(cert_type));
|
||||||
CdmResponseType result(CERT_PROVISIONING_NONCE_GENERATION_ERROR);
|
LOGV("cert_authority = %s", cert_authority.c_str());
|
||||||
|
|
||||||
|
CdmResponseType status(CERT_PROVISIONING_NONCE_GENERATION_ERROR);
|
||||||
|
CdmProvisioningRequest cdm_prov_request;
|
||||||
|
std::string provisioning_server_url_unused;
|
||||||
// Get a provisioning request. We might need one retry if there is a nonce
|
// Get a provisioning request. We might need one retry if there is a nonce
|
||||||
// flood failure.
|
// flood failure.
|
||||||
for (int i = 0; i < 2 && result == CERT_PROVISIONING_NONCE_GENERATION_ERROR;
|
for (int i = 0; i < 2 && status == CERT_PROVISIONING_NONCE_GENERATION_ERROR;
|
||||||
i++) {
|
i++) {
|
||||||
result = cdm_engine_->GetProvisioningRequest(
|
status = cdm_engine_->GetProvisioningRequest(
|
||||||
cert_type, cert_authority, provisioning_service_certificate_,
|
cert_type, cert_authority, provisioning_service_certificate_,
|
||||||
kLevelDefault, &request, &provisioning_server_url);
|
kLevelDefault, &cdm_prov_request, &provisioning_server_url_unused);
|
||||||
if (result == CERT_PROVISIONING_NONCE_GENERATION_ERROR) {
|
if (status == CERT_PROVISIONING_NONCE_GENERATION_ERROR) {
|
||||||
wvutil::TestSleep::Sleep(2);
|
wvutil::TestSleep::Sleep(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ASSERT_EQ(NO_ERROR, result);
|
ASSERT_EQ(status, NO_ERROR) << "Failed to generate provisioning request";
|
||||||
LOGV("cert_authority = %s", cert_authority.c_str());
|
|
||||||
|
|
||||||
|
// |binary_provisioning| implies the CdmEngine is using binary
|
||||||
|
// provisioning messages; however, ProvisioningHolder can only
|
||||||
|
// operate using Base64 requests.
|
||||||
if (binary_provisioning) {
|
if (binary_provisioning) {
|
||||||
request = wvutil::Base64SafeEncodeNoPad(request);
|
request_ = wvutil::Base64SafeEncodeNoPad(cdm_prov_request);
|
||||||
|
} else {
|
||||||
|
request_ = std::move(cdm_prov_request);
|
||||||
}
|
}
|
||||||
|
cert_type_ = cert_type;
|
||||||
|
|
||||||
if (config_.dump_golden_data()) {
|
if (config_.dump_golden_data()) {
|
||||||
std::vector<uint8_t> binary_request = wvutil::Base64SafeDecode(request);
|
const std::vector<uint8_t> binary_request =
|
||||||
CdmProvisioningRequest binary_request_string(binary_request.begin(),
|
wvutil::Base64SafeDecode(request_);
|
||||||
binary_request.end());
|
const CdmProvisioningRequest binary_request_string(binary_request.begin(),
|
||||||
|
binary_request.end());
|
||||||
MessageDumper::DumpProvisioningRequest(binary_request_string);
|
MessageDumper::DumpProvisioningRequest(binary_request_string);
|
||||||
}
|
}
|
||||||
LOGV("Provisioning request: req = %s", request.c_str());
|
}
|
||||||
|
|
||||||
// Ignore URL provided by CdmEngine. Use ours, as configured
|
void ProvisioningHolder::FetchResponse() {
|
||||||
// for test vs. production server.
|
// Preconditions.
|
||||||
provisioning_server_url.assign(provisioning_server_url_);
|
ASSERT_NE(cdm_engine_, nullptr) << "CdmEngine instance not set";
|
||||||
|
ASSERT_FALSE(request_.empty()) << "No request was set";
|
||||||
|
ASSERT_FALSE(provisioning_server_url_.empty())
|
||||||
|
<< "Test config is missing provisioning URL";
|
||||||
|
|
||||||
// Make request.
|
UrlRequest url_request(provisioning_server_url_);
|
||||||
UrlRequest url_request(provisioning_server_url);
|
ASSERT_TRUE(url_request.is_connected())
|
||||||
if (!url_request.is_connected()) {
|
<< "Failed to connect to provisoining server: "
|
||||||
LOGE("Failed to connect to provisioning server: url = %s",
|
<< provisioning_server_url_;
|
||||||
provisioning_server_url.c_str());
|
ASSERT_TRUE(url_request.PostCertRequestInQueryString(request_));
|
||||||
}
|
std::string response;
|
||||||
url_request.PostCertRequestInQueryString(request);
|
ASSERT_NO_FATAL_FAILURE(url_request.AssertOkResponseWithRetry(&response))
|
||||||
|
|
||||||
// Receive and parse response.
|
|
||||||
ASSERT_NO_FATAL_FAILURE(url_request.AssertOkResponseWithRetry(&response_))
|
|
||||||
<< "Failed to fetch provisioning response. "
|
<< "Failed to fetch provisioning response. "
|
||||||
<< DumpProvAttempt(request, response_, cert_type);
|
<< DumpProvAttempt(request_, response, cert_type_);
|
||||||
|
ASSERT_FALSE(response.empty()) << "Missing response";
|
||||||
|
response_ = std::move(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProvisioningHolder::LoadResponse(bool binary_provisioning) {
|
||||||
|
// Preconditions.
|
||||||
|
ASSERT_FALSE(response_.empty()) << "No response was fetched";
|
||||||
|
|
||||||
|
std::string cdm_prov_response;
|
||||||
if (binary_provisioning) {
|
if (binary_provisioning) {
|
||||||
// extract provisioning response from received message
|
// CDM is expecting the response to be in binary form, response
|
||||||
// Extracts signed response from JSON string, result is serialized
|
// must be extracted and decoded.
|
||||||
// protobuf.
|
std::string base_64_response;
|
||||||
std::string protobuf_response;
|
ASSERT_TRUE(ExtractSignedMessage(response_, &base_64_response))
|
||||||
const bool extract_ok = ExtractSignedMessage(response_, &protobuf_response);
|
<< "Failed to extract signed serialized response from JSON response";
|
||||||
ASSERT_TRUE(extract_ok) << "Failed to extract signed serialized "
|
ASSERT_FALSE(base_64_response.empty())
|
||||||
"response from JSON response";
|
<< "Base64 encoded provisioning response is unexpectedly empty";
|
||||||
LOGV("Extracted response message: \n%s\n", protobuf_response.c_str());
|
LOGV("Extracted response message: \n%s\n", base_64_response.c_str());
|
||||||
|
|
||||||
ASSERT_FALSE(protobuf_response.empty())
|
const std::vector<uint8_t> response_vec =
|
||||||
<< "Protobuf response is unexpectedly empty";
|
wvutil::Base64SafeDecode(base_64_response);
|
||||||
|
|
||||||
// base64 decode response to yield binary protobuf
|
|
||||||
const std::vector<uint8_t> response_vec(
|
|
||||||
wvutil::Base64SafeDecode(protobuf_response));
|
|
||||||
ASSERT_FALSE(response_vec.empty())
|
ASSERT_FALSE(response_vec.empty())
|
||||||
<< "Failed to decode base64 of response: response = "
|
<< "Failed to decode base64 response: " << base_64_response;
|
||||||
<< protobuf_response;
|
cdm_prov_response.assign(response_vec.begin(), response_vec.end());
|
||||||
|
} else {
|
||||||
response_.assign(response_vec.begin(), response_vec.end());
|
cdm_prov_response = response_;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_EQ(NO_ERROR,
|
const CdmResponseType status = cdm_engine_->HandleProvisioningResponse(
|
||||||
cdm_engine_->HandleProvisioningResponse(
|
cdm_prov_response, kLevelDefault, &certificate_, &wrapped_key_);
|
||||||
response_, kLevelDefault, &certificate_, &wrapped_key_))
|
ASSERT_EQ(status, NO_ERROR)
|
||||||
<< (binary_provisioning ? "Binary provisioning failed. "
|
<< (binary_provisioning ? "Binary provisioning failed. "
|
||||||
: "Non-binary provisioning failed. ")
|
: "Non-binary provisioning failed. ")
|
||||||
<< DumpProvAttempt(request, response_, cert_type);
|
<< DumpProvAttempt(request_, response_, cert_type_);
|
||||||
if (config_.dump_golden_data()) {
|
if (config_.dump_golden_data()) {
|
||||||
MessageDumper::DumpProvisioning(response_);
|
MessageDumper::DumpProvisioning(response_);
|
||||||
}
|
}
|
||||||
@@ -137,9 +160,9 @@ bool ProvisioningHolder::ExtractSignedMessage(const std::string& response,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ProvisioningHolder::DumpProvAttempt(const std::string& request,
|
std::string ProvisioningHolder::DumpProvAttempt(
|
||||||
const std::string& response,
|
const std::string& request, const std::string& response,
|
||||||
CdmCertificateType cert_type) {
|
CdmCertificateType cert_type) const {
|
||||||
std::stringstream info;
|
std::stringstream info;
|
||||||
info << "Cert Type: ";
|
info << "Cert Type: ";
|
||||||
PrintTo(cert_type, &info);
|
PrintTo(cert_type, &info);
|
||||||
|
|||||||
@@ -19,20 +19,58 @@ class ProvisioningHolder {
|
|||||||
provisioning_server_url_(config.provisioning_server()),
|
provisioning_server_url_(config.provisioning_server()),
|
||||||
provisioning_service_certificate_(
|
provisioning_service_certificate_(
|
||||||
config.provisioning_service_certificate()) {}
|
config.provisioning_service_certificate()) {}
|
||||||
|
|
||||||
|
// Generates requests, fetches response, and loads response.
|
||||||
void Provision(CdmCertificateType cert_type, bool binary_provisioning);
|
void Provision(CdmCertificateType cert_type, bool binary_provisioning);
|
||||||
void Provision(bool binary_provisioning) {
|
void Provision(bool binary_provisioning) {
|
||||||
Provision(kCertificateWidevine, binary_provisioning);
|
Provision(kCertificateWidevine, binary_provisioning);
|
||||||
}
|
}
|
||||||
std::string response() const { return response_; }
|
|
||||||
std::string certificate() const { return certificate_; }
|
// Generates a provisioning request from the |cdm_engine_|.
|
||||||
std::string wrapped_key() const { return wrapped_key_; }
|
// If successful, the request the stored in |request_|.
|
||||||
|
// The result of |request_| should always be the URL-Safe-Base64
|
||||||
|
// encoded value of the request.
|
||||||
|
void GenerateRequest(CdmCertificateType cert_type, bool binary_provisioning);
|
||||||
|
void GenerateRequest(bool binary_provisioning) {
|
||||||
|
GenerateRequest(kCertificateWidevine, binary_provisioning);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch the provisioning response from the server.
|
||||||
|
// Uses |request_| as the source of the request, and stores
|
||||||
|
// JSON message of the response to |response_|.
|
||||||
|
void FetchResponse();
|
||||||
|
|
||||||
|
void LoadResponse(bool binary_provisioning);
|
||||||
|
|
||||||
|
const std::string& request() const { return request_; }
|
||||||
|
// Sets the request to be used on next call to FetchResponse().
|
||||||
|
// The provided |request| must be a URL-Safe-Base64 encoding
|
||||||
|
// of the provisioning request.
|
||||||
|
void set_request(const std::string& request) { request_ = request; }
|
||||||
|
const std::string& response() const { return response_; }
|
||||||
|
const std::string& certificate() const { return certificate_; }
|
||||||
|
const std::string& wrapped_key() const { return wrapped_key_; }
|
||||||
|
|
||||||
|
void ClearProvisioningData() {
|
||||||
|
cert_type_ = kCertificateWidevine;
|
||||||
|
request_.clear();
|
||||||
|
response_.clear();
|
||||||
|
certificate_.clear();
|
||||||
|
wrapped_key_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TestCdmEngine* cdm_engine_;
|
TestCdmEngine* cdm_engine_;
|
||||||
|
// Config variables.
|
||||||
const ConfigTestEnv& config_;
|
const ConfigTestEnv& config_;
|
||||||
std::string provisioning_server_url_;
|
std::string provisioning_server_url_;
|
||||||
std::string provisioning_service_certificate_;
|
std::string provisioning_service_certificate_;
|
||||||
std::string response_;
|
// Request variables.
|
||||||
|
CdmCertificateType cert_type_;
|
||||||
|
std::string request_; // URL-Safe-Base64 encoding of request.
|
||||||
|
// Response variables.
|
||||||
|
std::string response_; // JSON message containing response.
|
||||||
|
// Post-provisioning variables.
|
||||||
std::string certificate_;
|
std::string certificate_;
|
||||||
std::string wrapped_key_;
|
std::string wrapped_key_;
|
||||||
|
|
||||||
@@ -42,11 +80,12 @@ class ProvisioningHolder {
|
|||||||
// entire string represents a serialized protobuf mesaage and return true with
|
// entire string represents a serialized protobuf mesaage and return true with
|
||||||
// the entire string. If the end_substring match fails, return false with an
|
// the entire string. If the end_substring match fails, return false with an
|
||||||
// empty *result.
|
// empty *result.
|
||||||
bool ExtractSignedMessage(const std::string& response, std::string* result);
|
static bool ExtractSignedMessage(const std::string& response,
|
||||||
|
std::string* result);
|
||||||
// Dump request and response information for use in a debug or failure log.
|
// Dump request and response information for use in a debug or failure log.
|
||||||
std::string DumpProvAttempt(const std::string& request,
|
std::string DumpProvAttempt(const std::string& request,
|
||||||
const std::string& response,
|
const std::string& response,
|
||||||
CdmCertificateType cert_type);
|
CdmCertificateType cert_type) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|||||||
Reference in New Issue
Block a user