Source release 19.3.0
This commit is contained in:
@@ -115,7 +115,7 @@ class MockCdmEngineImpl : public CdmEngine {
|
||||
class WvCdmEngineMetricsImplTest : public ::testing::Test {
|
||||
public:
|
||||
void SetUp() override {
|
||||
file_system_.reset(CreateTestFileSystem());
|
||||
file_system_ = CreateTestFileSystem();
|
||||
std::shared_ptr<EngineMetrics> engine_metrics(new EngineMetrics);
|
||||
test_cdm_metrics_engine_.reset(
|
||||
new CdmEngineMetricsImpl<StrictMock<MockCdmEngineImpl>>(
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#ifndef CDM_TEST_CONFIG_TEST_ENV_H_
|
||||
#define CDM_TEST_CONFIG_TEST_ENV_H_
|
||||
|
||||
#include <string>
|
||||
#include "disallow_copy_and_assign.h"
|
||||
|
||||
#include "wv_cdm_types.h"
|
||||
#include "wv_class_utils.h"
|
||||
|
||||
// Declare class ConfigTestEnv - holds the configuration settings needed
|
||||
// to talk to the various provisioning and license servers.
|
||||
@@ -45,7 +45,6 @@ enum ContentId {
|
||||
// Configures default test environment.
|
||||
class ConfigTestEnv {
|
||||
public:
|
||||
|
||||
typedef struct {
|
||||
ServerConfigurationId id;
|
||||
std::string license_server_url;
|
||||
@@ -63,12 +62,9 @@ class ConfigTestEnv {
|
||||
bool release);
|
||||
// Allow copy, assign, and move. Performance is not an issue in test
|
||||
// initialization.
|
||||
ConfigTestEnv(const ConfigTestEnv&) = default;
|
||||
ConfigTestEnv(ConfigTestEnv&&) = default;
|
||||
ConfigTestEnv& operator=(const ConfigTestEnv&) = default;
|
||||
ConfigTestEnv& operator=(ConfigTestEnv&&) = default;
|
||||
WVCDM_DEFAULT_COPY_AND_MOVE(ConfigTestEnv);
|
||||
|
||||
~ConfigTestEnv() {};
|
||||
~ConfigTestEnv() {}
|
||||
|
||||
ServerConfigurationId server_id() { return server_id_; }
|
||||
const std::string& client_auth() const { return client_auth_; }
|
||||
@@ -157,11 +153,8 @@ class ConfigTestEnv {
|
||||
// It dump_golden_data_ is true, message data is dumped to a file for help
|
||||
// in generating golden test data.
|
||||
bool dump_golden_data_ = false;
|
||||
};
|
||||
|
||||
}; // class ConfigTestEnv
|
||||
// The default provisioning server URL for a default provisioning request.
|
||||
extern const std::string kDefaultProvisioningServerUrl;
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
#endif // CDM_TEST_CONFIG_TEST_ENV_H_
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "certificate_provisioning.h"
|
||||
#include "license_holder.h"
|
||||
#include "log.h"
|
||||
#include "oec_device_features.h"
|
||||
#include "provisioning_holder.h"
|
||||
#include "test_base.h"
|
||||
#include "wv_cdm_types.h"
|
||||
@@ -135,6 +136,9 @@ class CoreIntegrationTest : public WvCdmTestBaseWithEngine {
|
||||
* different apps. Test using two different apps and origins.
|
||||
*/
|
||||
TEST_F(CoreIntegrationTest, ProvisioningStableSpoidTest) {
|
||||
if (wvoec::global_features.provisioning_method == OEMCrypto_DrmCertificate) {
|
||||
GTEST_SKIP() << "Device does not provision.";
|
||||
}
|
||||
std::string level;
|
||||
ASSERT_EQ(
|
||||
NO_ERROR,
|
||||
|
||||
@@ -5,11 +5,13 @@
|
||||
#ifndef CDM_TEST_CREATE_TEST_FILE_SYSTEM_H_
|
||||
#define CDM_TEST_CREATE_TEST_FILE_SYSTEM_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "file_store.h"
|
||||
|
||||
// Create a new FileSystem object that is suitable for using to create a new
|
||||
// CdmEngine object. How this is implemented is platform-specific. The caller
|
||||
// owns the returned pointer and is responsible for deleting it.
|
||||
wvutil::FileSystem* CreateTestFileSystem();
|
||||
std::unique_ptr<wvutil::FileSystem> CreateTestFileSystem();
|
||||
|
||||
#endif // CDM_TEST_CREATE_TEST_FILE_SYSTEM_H_
|
||||
|
||||
@@ -1,20 +1,9 @@
|
||||
// Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#include "fake_provisioning_server.h"
|
||||
|
||||
#include "core_message_deserialize.h"
|
||||
#include "core_message_serialize.h"
|
||||
#include "core_message_serialize_proto.h"
|
||||
#include "crypto_session.h"
|
||||
#include "license_protocol.pb.h"
|
||||
#include "log.h"
|
||||
#include "oec_key_deriver.h"
|
||||
#include "oec_test_data.h"
|
||||
#include "privacy_crypto.h"
|
||||
#include "service_certificate.h"
|
||||
#include "string_conversions.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
// TODO: refactor oec_session so that these are not needed.
|
||||
#include <gtest/gtest.h>
|
||||
@@ -27,7 +16,18 @@
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509_vfy.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "core_message_deserialize.h"
|
||||
#include "core_message_serialize.h"
|
||||
#include "core_message_serialize_proto.h"
|
||||
#include "crypto_session.h"
|
||||
#include "license_protocol.pb.h"
|
||||
#include "log.h"
|
||||
#include "oec_key_deriver.h"
|
||||
#include "oec_test_data.h"
|
||||
#include "privacy_crypto.h"
|
||||
#include "service_certificate.h"
|
||||
#include "string_conversions.h"
|
||||
|
||||
namespace wvcdm {
|
||||
namespace {
|
||||
@@ -357,5 +357,4 @@ bool FakeProvisioningServer::MakeResponse(
|
||||
json_response->append(kJsonEnd);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#ifndef CDM_TEST_HTTP_SOCKET_H_
|
||||
#define CDM_TEST_HTTP_SOCKET_H_
|
||||
|
||||
@@ -13,13 +12,14 @@
|
||||
#include <gtest/gtest_prod.h>
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#include "disallow_copy_and_assign.h"
|
||||
#include "wv_class_utils.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
// Provides basic Linux based TCP socket interface.
|
||||
class HttpSocket {
|
||||
public:
|
||||
HttpSocket() = delete;
|
||||
WVCDM_DISALLOW_COPY_AND_MOVE(HttpSocket);
|
||||
// A scheme (http:// or https://) is required for the URL.
|
||||
explicit HttpSocket(const std::string& url);
|
||||
~HttpSocket();
|
||||
@@ -70,10 +70,6 @@ class HttpSocket {
|
||||
// When the socket was created. Logged on error to help debug flaky
|
||||
// tests. e.g. b/186031735
|
||||
std::time_t create_time_;
|
||||
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(HttpSocket);
|
||||
};
|
||||
|
||||
}; // class HttpSocket
|
||||
} // namespace wvcdm
|
||||
|
||||
#endif // CDM_TEST_HTTP_SOCKET_H_
|
||||
|
||||
@@ -102,7 +102,7 @@ void LicenseHolder::GenerateAndPostRenewalRequest(
|
||||
void LicenseHolder::FetchRenewal() {
|
||||
ASSERT_NE(request_in_flight_, nullptr) << "Failed for " << content_id();
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
request_in_flight_->AssertOkResponse(&request_response_))
|
||||
request_in_flight_->AssertOkResponseWithRetry(&request_response_))
|
||||
<< "Renewal failed for " << content_id();
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ void LicenseHolder::GenerateAndPostReleaseRequest(
|
||||
void LicenseHolder::FetchRelease() {
|
||||
ASSERT_NE(request_in_flight_, nullptr) << "Failed for " << content_id();
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
request_in_flight_->AssertOkResponse(&request_response_))
|
||||
request_in_flight_->AssertOkResponseWithRetry(&request_response_))
|
||||
<< "Renewal failed for " << content_id();
|
||||
}
|
||||
|
||||
@@ -293,7 +293,7 @@ void LicenseHolder::GetKeyResponse(const CdmKeyRequest& key_request) {
|
||||
|
||||
std::string http_response;
|
||||
url_request.PostRequest(key_request.message);
|
||||
ASSERT_NO_FATAL_FAILURE(url_request.AssertOkResponse(&http_response))
|
||||
ASSERT_NO_FATAL_FAILURE(url_request.AssertOkResponseWithRetry(&http_response))
|
||||
<< "Failed for " << content_id();
|
||||
LicenseRequest license_request;
|
||||
license_request.GetDrmMessage(http_response, key_response_);
|
||||
|
||||
@@ -1,31 +1,27 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#ifndef CDM_TEST_LICENSE_REQUEST_H_
|
||||
#define CDM_TEST_LICENSE_REQUEST_H_
|
||||
|
||||
#include <string>
|
||||
#include "disallow_copy_and_assign.h"
|
||||
|
||||
#include "wv_class_utils.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
// Parses response from a license request.
|
||||
// This class assumes a particular response format defined by
|
||||
// Google license servers.
|
||||
class LicenseRequest {
|
||||
public:
|
||||
LicenseRequest() {}
|
||||
LicenseRequest() = default;
|
||||
WVCDM_DISALLOW_COPY_AND_MOVE(LicenseRequest);
|
||||
~LicenseRequest() {}
|
||||
|
||||
void GetDrmMessage(const std::string& response, std::string& drm_msg);
|
||||
|
||||
private:
|
||||
size_t FindHeaderEndPosition(const std::string& response) const;
|
||||
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(LicenseRequest);
|
||||
};
|
||||
|
||||
}; // class LicenseRequest
|
||||
} // namespace wvcdm
|
||||
|
||||
#endif // CDM_TEST_LICENSE_REQUEST_H_
|
||||
|
||||
@@ -22,10 +22,32 @@
|
||||
#include "wv_cdm_constants.h"
|
||||
|
||||
namespace wvcdm {
|
||||
// Protobuf generated classes
|
||||
using ClientCapabilities =
|
||||
video_widevine::ClientIdentification::ClientCapabilities;
|
||||
using video_widevine::ClientIdentification;
|
||||
using video_widevine::License;
|
||||
using KeyContainer = video_widevine::License::KeyContainer;
|
||||
using video_widevine::LicenseRequest;
|
||||
using ContentIdentification = LicenseRequest::ContentIdentification;
|
||||
using video_widevine::SignedMessage;
|
||||
using PsshEntitledKey = video_widevine::WidevinePsshData::EntitledKey;
|
||||
|
||||
// gmock methods
|
||||
using ::testing::_;
|
||||
using ::testing::DoAll;
|
||||
using ::testing::NotNull;
|
||||
using ::testing::PrintToStringParamName;
|
||||
using ::testing::Return;
|
||||
using ::testing::ReturnRef;
|
||||
using ::testing::SetArgPointee;
|
||||
using ::testing::SetArgReferee;
|
||||
using ::testing::UnorderedElementsAre;
|
||||
using ::testing::Values;
|
||||
|
||||
namespace {
|
||||
using wvutil::a2bs_hex;
|
||||
|
||||
namespace {
|
||||
const std::string kEmptyString;
|
||||
const std::string kAesKey = a2bs_hex("000102030405060708090a0b0c0d0e0f");
|
||||
const std::string kAesIv = a2bs_hex("000102030405060708090a0b0c0d0e0f");
|
||||
@@ -156,7 +178,7 @@ class MockCryptoSession : public TestCryptoSession {
|
||||
OEMCrypto_SignatureHashAlgorithm&),
|
||||
(override));
|
||||
MOCK_METHOD(CdmResponseType, LoadEntitledContentKeys,
|
||||
(const std::vector<CryptoKey>& key_array), (override));
|
||||
(const std::vector<CryptoKey>&), (override));
|
||||
MOCK_METHOD(bool, GetResourceRatingTier, (uint32_t*), (override));
|
||||
MOCK_METHOD(bool, GetWatermarkingSupport, (CdmWatermarkingSupport*),
|
||||
(override));
|
||||
@@ -169,37 +191,11 @@ class MockPolicyEngine : public PolicyEngine {
|
||||
public:
|
||||
MockPolicyEngine(CryptoSession* crypto)
|
||||
: PolicyEngine("mock_session_id", nullptr, crypto) {}
|
||||
MOCK_METHOD(
|
||||
void, SetEntitledLicenseKeys,
|
||||
(const std::vector<video_widevine::WidevinePsshData_EntitledKey>&),
|
||||
(override));
|
||||
MOCK_METHOD(void, SetEntitledLicenseKeys,
|
||||
(const std::vector<PsshEntitledKey>&), (override));
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// Protobuf generated classes
|
||||
using ClientCapabilities =
|
||||
video_widevine::ClientIdentification::ClientCapabilities;
|
||||
using video_widevine::ClientIdentification;
|
||||
using video_widevine::License;
|
||||
using video_widevine::License_KeyContainer;
|
||||
using video_widevine::LicenseRequest;
|
||||
using video_widevine::LicenseRequest_ContentIdentification;
|
||||
using video_widevine::SignedMessage;
|
||||
using video_widevine::WidevinePsshData_EntitledKey;
|
||||
|
||||
// gmock methods
|
||||
using ::testing::_;
|
||||
using ::testing::DoAll;
|
||||
using ::testing::NotNull;
|
||||
using ::testing::PrintToStringParamName;
|
||||
using ::testing::Return;
|
||||
using ::testing::ReturnRef;
|
||||
using ::testing::SetArgPointee;
|
||||
using ::testing::SetArgReferee;
|
||||
using ::testing::UnorderedElementsAre;
|
||||
using ::testing::Values;
|
||||
|
||||
class CdmLicenseTestPeer : public CdmLicense {
|
||||
public:
|
||||
CdmLicenseTestPeer(const CdmSessionId& session_id, wvutil::Clock* clock)
|
||||
@@ -208,7 +204,10 @@ class CdmLicenseTestPeer : public CdmLicense {
|
||||
using CdmLicense::HandleNewEntitledKeys;
|
||||
|
||||
void set_entitlement_keys(const License& license) {
|
||||
entitlement_keys_.CopyFrom(license.key());
|
||||
for (const auto& key_container : license.key()) {
|
||||
if (key_container.type() != KeyContainer::ENTITLEMENT) continue;
|
||||
entitlement_key_ids_.insert(key_container.id());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -368,15 +367,13 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) {
|
||||
|
||||
// Verify Client Identification
|
||||
const ClientIdentification& client_id = license_request.client_id();
|
||||
EXPECT_EQ(
|
||||
video_widevine::ClientIdentification_TokenType_DRM_DEVICE_CERTIFICATE,
|
||||
client_id.type());
|
||||
EXPECT_EQ(ClientIdentification::DRM_DEVICE_CERTIFICATE, client_id.type());
|
||||
EXPECT_TRUE(std::equal(client_id.token().begin(), client_id.token().end(),
|
||||
kToken.begin()));
|
||||
|
||||
EXPECT_LT(0, client_id.client_info_size());
|
||||
for (int i = 0; i < client_id.client_info_size(); ++i) {
|
||||
const ::video_widevine::ClientIdentification_NameValue& name_value =
|
||||
const ClientIdentification::NameValue& name_value =
|
||||
client_id.client_info(i);
|
||||
EXPECT_TRUE(!name_value.name().empty());
|
||||
EXPECT_TRUE(!name_value.value().empty());
|
||||
@@ -406,14 +403,13 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) {
|
||||
ClientCapabilities::WATERMARKING_CONFIGURABLE);
|
||||
|
||||
// Verify Content Identification
|
||||
const LicenseRequest_ContentIdentification& content_id =
|
||||
license_request.content_id();
|
||||
const ContentIdentification& content_id = license_request.content_id();
|
||||
ASSERT_TRUE(content_id.has_widevine_pssh_data());
|
||||
EXPECT_FALSE(content_id.has_webm_key_id());
|
||||
EXPECT_FALSE(content_id.has_existing_license());
|
||||
|
||||
const ::video_widevine::LicenseRequest_ContentIdentification_WidevinePsshData&
|
||||
widevine_pssh_data = content_id.widevine_pssh_data();
|
||||
const ContentIdentification::WidevinePsshData& widevine_pssh_data =
|
||||
content_id.widevine_pssh_data();
|
||||
EXPECT_TRUE(std::equal(widevine_pssh_data.pssh_data(0).begin(),
|
||||
widevine_pssh_data.pssh_data(0).end(),
|
||||
kCencPssh.begin()));
|
||||
@@ -423,8 +419,7 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) {
|
||||
kCryptoRequestId.begin()));
|
||||
|
||||
// Verify other license request fields
|
||||
EXPECT_EQ(::video_widevine::LicenseRequest_RequestType_NEW,
|
||||
license_request.type());
|
||||
EXPECT_EQ(LicenseRequest::NEW, license_request.type());
|
||||
EXPECT_EQ(kLicenseStartTime, license_request.request_time());
|
||||
EXPECT_EQ(video_widevine::VERSION_2_1, license_request.protocol_version());
|
||||
EXPECT_EQ(kNonce, license_request.key_control_nonce());
|
||||
@@ -502,15 +497,13 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidationV15) {
|
||||
|
||||
// Verify Client Identification
|
||||
const ClientIdentification& client_id = license_request.client_id();
|
||||
EXPECT_EQ(
|
||||
video_widevine::ClientIdentification_TokenType_DRM_DEVICE_CERTIFICATE,
|
||||
client_id.type());
|
||||
EXPECT_EQ(ClientIdentification::DRM_DEVICE_CERTIFICATE, client_id.type());
|
||||
EXPECT_TRUE(std::equal(client_id.token().begin(), client_id.token().end(),
|
||||
kToken.begin()));
|
||||
|
||||
EXPECT_LT(0, client_id.client_info_size());
|
||||
for (int i = 0; i < client_id.client_info_size(); ++i) {
|
||||
const ::video_widevine::ClientIdentification_NameValue& name_value =
|
||||
const ClientIdentification::NameValue& name_value =
|
||||
client_id.client_info(i);
|
||||
EXPECT_TRUE(!name_value.name().empty());
|
||||
EXPECT_TRUE(!name_value.value().empty());
|
||||
@@ -540,14 +533,13 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidationV15) {
|
||||
ClientCapabilities::WATERMARKING_NOT_SUPPORTED);
|
||||
|
||||
// Verify Content Identification
|
||||
const LicenseRequest_ContentIdentification& content_id =
|
||||
license_request.content_id();
|
||||
const ContentIdentification& content_id = license_request.content_id();
|
||||
ASSERT_TRUE(content_id.has_widevine_pssh_data());
|
||||
EXPECT_FALSE(content_id.has_webm_key_id());
|
||||
EXPECT_FALSE(content_id.has_existing_license());
|
||||
|
||||
const ::video_widevine::LicenseRequest_ContentIdentification_WidevinePsshData&
|
||||
widevine_pssh_data = content_id.widevine_pssh_data();
|
||||
const ContentIdentification::WidevinePsshData& widevine_pssh_data =
|
||||
content_id.widevine_pssh_data();
|
||||
EXPECT_TRUE(std::equal(widevine_pssh_data.pssh_data(0).begin(),
|
||||
widevine_pssh_data.pssh_data(0).end(),
|
||||
kCencPssh.begin()));
|
||||
@@ -557,8 +549,7 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidationV15) {
|
||||
kCryptoRequestId.begin()));
|
||||
|
||||
// Verify other license request fields
|
||||
EXPECT_EQ(::video_widevine::LicenseRequest_RequestType_NEW,
|
||||
license_request.type());
|
||||
EXPECT_EQ(LicenseRequest::NEW, license_request.type());
|
||||
EXPECT_EQ(kLicenseStartTime, license_request.request_time());
|
||||
EXPECT_EQ(video_widevine::VERSION_2_1, license_request.protocol_version());
|
||||
EXPECT_EQ(kNonce, license_request.key_control_nonce());
|
||||
@@ -590,14 +581,13 @@ TEST_P(CdmLicenseEntitledKeyTest, LoadsEntitledKeys) {
|
||||
|
||||
// Set up a known, fake entitlement key
|
||||
License entitlement_license;
|
||||
License_KeyContainer* entitlement_key = entitlement_license.add_key();
|
||||
entitlement_key->set_type(
|
||||
video_widevine::License_KeyContainer_KeyType_ENTITLEMENT);
|
||||
KeyContainer* entitlement_key = entitlement_license.add_key();
|
||||
entitlement_key->set_type(KeyContainer::ENTITLEMENT);
|
||||
entitlement_key->set_id(kFakeEntitlementKeyId);
|
||||
|
||||
// Set up a fake entitled key that matches the entitlement key
|
||||
std::vector<WidevinePsshData_EntitledKey> entitled_keys(1);
|
||||
WidevinePsshData_EntitledKey& padded_key = entitled_keys[0];
|
||||
std::vector<PsshEntitledKey> entitled_keys(1);
|
||||
PsshEntitledKey& padded_key = entitled_keys[0];
|
||||
padded_key.set_entitlement_key_id(kFakeEntitlementKeyId);
|
||||
padded_key.set_key_id(kFakeEntitledKeyId);
|
||||
padded_key.set_key(variant.key);
|
||||
|
||||
@@ -235,24 +235,30 @@ void MessageDumper::DumpProvisioningRequest(
|
||||
const CdmProvisioningRequest& request) {
|
||||
if (wvoec::global_features.derive_key_method ==
|
||||
wvoec::DeviceFeatures::TEST_PROVISION_40) {
|
||||
LOGD("Provisioning 4.0 does not have a v17 or v18 core message.");
|
||||
// The ODKGoldenProvision40V19 test will have its own class for now since
|
||||
// we are only testing the request.
|
||||
DumpHeader(&provision_file, "Provision40");
|
||||
} else {
|
||||
DumpHeader(&provision_file, "Provision");
|
||||
SignedProvisioningMessage signed_message;
|
||||
EXPECT_TRUE(signed_message.ParseFromString(request))
|
||||
<< "Request = " << wvutil::b2a_hex(request);
|
||||
if (wvoec::global_features.api_version >= wvoec::kCoreMessagesAPI) {
|
||||
EXPECT_TRUE(signed_message.has_oemcrypto_core_message());
|
||||
DumpHex(&provision_file, "core_request",
|
||||
signed_message.oemcrypto_core_message());
|
||||
}
|
||||
}
|
||||
SignedProvisioningMessage signed_message;
|
||||
EXPECT_TRUE(signed_message.ParseFromString(request))
|
||||
<< "Request = " << wvutil::b2a_hex(request);
|
||||
if (wvoec::global_features.api_version >= wvoec::kCoreMessagesAPI) {
|
||||
EXPECT_TRUE(signed_message.has_oemcrypto_core_message());
|
||||
DumpHex(&provision_file, "core_request",
|
||||
signed_message.oemcrypto_core_message());
|
||||
}
|
||||
}
|
||||
|
||||
void MessageDumper::DumpProvisioning(const CdmProvisioningResponse& response) {
|
||||
if (wvoec::global_features.derive_key_method ==
|
||||
wvoec::DeviceFeatures::TEST_PROVISION_40) {
|
||||
LOGD("Provisioning 4.0 does not have a core message.");
|
||||
LOGD(
|
||||
"Provisioning 4.0 does not have a v17, v18 or v19 core message in the "
|
||||
"response.");
|
||||
provision_file << " RunTest();\n";
|
||||
provision_file << "}\n\n";
|
||||
} else {
|
||||
SignedProvisioningMessage signed_response;
|
||||
if (!signed_response.ParseFromString(response)) {
|
||||
|
||||
@@ -69,7 +69,7 @@ void ProvisioningHolder::Provision(CdmCertificateType cert_type,
|
||||
url_request.PostCertRequestInQueryString(request);
|
||||
|
||||
// Receive and parse response.
|
||||
ASSERT_NO_FATAL_FAILURE(url_request.AssertOkResponse(&response_))
|
||||
ASSERT_NO_FATAL_FAILURE(url_request.AssertOkResponseWithRetry(&response_))
|
||||
<< "Failed to fetch provisioning response. "
|
||||
<< DumpProvAttempt(request, response_, cert_type);
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ using wvutil::TestSleep;
|
||||
|
||||
namespace wvcdm {
|
||||
FileSystem* RebootTest::file_system_;
|
||||
std::unique_ptr<FileSystem> RebootTest::default_file_system_;
|
||||
|
||||
namespace {
|
||||
// How much fudge or round off error do we allow in license durations for reboot
|
||||
@@ -31,7 +32,10 @@ constexpr int64_t kFudge = 10;
|
||||
|
||||
void RebootTest::SetUp() {
|
||||
WvCdmTestBase::SetUp();
|
||||
if (!file_system_) file_system_ = CreateTestFileSystem();
|
||||
if (!file_system_) {
|
||||
if (!default_file_system_) default_file_system_ = CreateTestFileSystem();
|
||||
file_system_ = default_file_system_.get();
|
||||
}
|
||||
|
||||
const ::testing::TestInfo* const test_info =
|
||||
::testing::UnitTest::GetInstance()->current_test_info();
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#define WVCDM_CORE_REBOOT_TEST_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -37,6 +38,7 @@ class RebootTest : public WvCdmTestBaseWithEngine {
|
||||
|
||||
// This is used to store each test's persistent data.
|
||||
static wvutil::FileSystem* file_system_;
|
||||
static std::unique_ptr<wvutil::FileSystem> default_file_system_;
|
||||
|
||||
// The persistent data for the current test.
|
||||
std::map<std::string, std::string> persistent_data_;
|
||||
|
||||
@@ -373,9 +373,12 @@ void WvCdmTestBase::InstallTestRootOfTrust() {
|
||||
sizeof(test_keybox)));
|
||||
break;
|
||||
case wvoec::DeviceFeatures::LOAD_TEST_RSA_KEY:
|
||||
// Rare case: used by devices with baked in DRM cert.
|
||||
// Rare case: used by devices with baked in production DRM cert.
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestRSAKey());
|
||||
break;
|
||||
case wvoec::DeviceFeatures::PRELOADED_RSA_KEY:
|
||||
// Rare case: used by devices with baked in test DRM cert.
|
||||
break;
|
||||
case wvoec::DeviceFeatures::TEST_PROVISION_30:
|
||||
// Can use oem certificate to install test rsa key.
|
||||
break;
|
||||
@@ -404,6 +407,10 @@ void WvCdmTestBase::Provision() {
|
||||
}
|
||||
|
||||
void WvCdmTestBase::EnsureProvisioned() {
|
||||
if (wvoec::global_features.provisioning_method == OEMCrypto_DrmCertificate) {
|
||||
LOGD("Device is preprovisioned.");
|
||||
return;
|
||||
}
|
||||
CdmSessionId session_id;
|
||||
std::unique_ptr<wvutil::FileSystem> file_system(CreateTestFileSystem());
|
||||
// OpenSession will check if a DRM certificate exists, while
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
#include "url_request.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
@@ -24,11 +26,15 @@ const int kConnectTimeoutMs = 15000;
|
||||
const int kWriteTimeoutMs = 12000;
|
||||
const int kReadTimeoutMs = 12000;
|
||||
constexpr int kHttpOk = 200;
|
||||
const std::vector<int> kRetryCodes = {502, 504};
|
||||
|
||||
const std::string kGoogleHeaderUpper("X-Google");
|
||||
const std::string kGoogleHeaderLower("x-google");
|
||||
const std::string kCrLf("\r\n");
|
||||
|
||||
constexpr unsigned kRetryCount = 3;
|
||||
constexpr unsigned kRetryIntervalSeconds = 1;
|
||||
|
||||
// Concatenate all chunks into one blob and returns the response with
|
||||
// header information.
|
||||
void ConcatenateChunkedResponse(const std::string http_response,
|
||||
@@ -127,13 +133,34 @@ bool UrlRequest::GetResponse(std::string* message) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void UrlRequest::AssertOkResponse(std::string* message) {
|
||||
void UrlRequest::AssertOkResponseWithRetry(std::string* message) {
|
||||
ASSERT_TRUE(message);
|
||||
ASSERT_TRUE(GetResponse(message));
|
||||
const int status_code = GetStatusCode(*message);
|
||||
ASSERT_EQ(kHttpOk, status_code) << "HTTP response from " << socket_.url()
|
||||
<< ": (" << message->size() << ") :\n"
|
||||
<< *message;
|
||||
int status_code = 0;
|
||||
for (unsigned i = 0; i < kRetryCount; i++) {
|
||||
*message = "";
|
||||
ASSERT_TRUE(GetResponse(message)) << "For attempt " << (i + 1);
|
||||
status_code = GetStatusCode(*message);
|
||||
// If we didn't get a retry status, then we're done.
|
||||
if (std::find(kRetryCodes.begin(), kRetryCodes.end(), status_code) ==
|
||||
kRetryCodes.end()) {
|
||||
ASSERT_EQ(kHttpOk, status_code) << "HTTP response from " << socket_.url()
|
||||
<< ": (" << message->size() << ") :\n"
|
||||
<< *message;
|
||||
return;
|
||||
}
|
||||
std::cerr << "Temporary failure HTTP response from " << socket_.url()
|
||||
<< ": (" << message->size() << ") :\n"
|
||||
<< *message << "\n"
|
||||
<< "Attempt " << (i + 1) << "\n";
|
||||
socket_.CloseSocket();
|
||||
is_connected_ = false;
|
||||
sleep(kRetryIntervalSeconds << i);
|
||||
Reconnect();
|
||||
SendRequestOnce();
|
||||
}
|
||||
GTEST_FAIL() << "HTTP response from " << socket_.url() << ": ("
|
||||
<< message->size() << ") :\n"
|
||||
<< *message;
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -190,36 +217,35 @@ bool UrlRequest::GetDebugHeaderFields(
|
||||
|
||||
bool UrlRequest::PostRequestWithPath(const std::string& path,
|
||||
const std::string& data) {
|
||||
std::string request;
|
||||
request_.clear();
|
||||
|
||||
request.append("POST ");
|
||||
request.append(path);
|
||||
request.append(" HTTP/1.1\r\n");
|
||||
request_.append("POST ");
|
||||
request_.append(path);
|
||||
request_.append(" HTTP/1.1\r\n");
|
||||
|
||||
request.append("Host: ");
|
||||
request.append(socket_.domain_name());
|
||||
request.append("\r\n");
|
||||
request_.append("Host: ");
|
||||
request_.append(socket_.domain_name());
|
||||
request_.append("\r\n");
|
||||
|
||||
request.append("Connection: close\r\n");
|
||||
request.append("User-Agent: Widevine CDM v1.0\r\n");
|
||||
request.append("X-Return-Encrypted-Headers: request_and_response\r\n");
|
||||
request_.append("Connection: close\r\n");
|
||||
request_.append("User-Agent: Widevine CDM v1.0\r\n");
|
||||
request_.append("X-Return-Encrypted-Headers: request_and_response\r\n");
|
||||
|
||||
// buffer to store length of data as a string
|
||||
char data_size_buffer[32] = {0};
|
||||
snprintf(data_size_buffer, sizeof(data_size_buffer), "%zu", data.size());
|
||||
request_.append("Content-Length: ");
|
||||
request_.append(std::to_string(data.size()));
|
||||
request_.append("\r\n");
|
||||
|
||||
request.append("Content-Length: ");
|
||||
request.append(data_size_buffer); // appends size of data
|
||||
request.append("\r\n");
|
||||
request_.append("\r\n"); // empty line to terminate headers
|
||||
|
||||
request.append("\r\n"); // empty line to terminate headers
|
||||
|
||||
request.append(data);
|
||||
request_.append(data);
|
||||
return SendRequestOnce();
|
||||
}
|
||||
|
||||
bool UrlRequest::SendRequestOnce() {
|
||||
const int ret = socket_.WriteAndLogErrors(
|
||||
request.c_str(), static_cast<int>(request.size()), kWriteTimeoutMs);
|
||||
LOGV("HTTP request: (%zu): %s", request.size(), request.c_str());
|
||||
LOGV("HTTP request hex: %s", wvutil::b2a_hex(request).c_str());
|
||||
request_.c_str(), static_cast<int>(request_.size()), kWriteTimeoutMs);
|
||||
LOGV("HTTP request: (%zu): %s", request_.size(), request_.c_str());
|
||||
LOGV("HTTP request hex: %s", wvutil::b2a_hex(request_).c_str());
|
||||
return ret != -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#ifndef CDM_TEST_URL_REQUEST_H_
|
||||
#define CDM_TEST_URL_REQUEST_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "disallow_copy_and_assign.h"
|
||||
#include "http_socket.h"
|
||||
#include "wv_class_utils.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
// Provides simple HTTP request and response service.
|
||||
// Only POST request method is implemented.
|
||||
class UrlRequest {
|
||||
public:
|
||||
UrlRequest() = delete;
|
||||
WVCDM_DISALLOW_COPY_AND_MOVE(UrlRequest);
|
||||
|
||||
explicit UrlRequest(const std::string& url);
|
||||
~UrlRequest();
|
||||
|
||||
@@ -29,7 +30,8 @@ class UrlRequest {
|
||||
bool GetResponse(std::string* message);
|
||||
static int GetStatusCode(const std::string& response);
|
||||
// Get the response, and expect the status is OK.
|
||||
void AssertOkResponse(std::string* message);
|
||||
// It will retry if the response code is in the 500 range.
|
||||
void AssertOkResponseWithRetry(std::string* message);
|
||||
|
||||
static bool GetDebugHeaderFields(
|
||||
const std::string& response,
|
||||
@@ -37,13 +39,11 @@ class UrlRequest {
|
||||
|
||||
private:
|
||||
bool PostRequestWithPath(const std::string& path, const std::string& data);
|
||||
bool SendRequestOnce();
|
||||
|
||||
bool is_connected_;
|
||||
HttpSocket socket_;
|
||||
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(UrlRequest);
|
||||
};
|
||||
|
||||
std::string request_;
|
||||
}; // class UrlRequest
|
||||
} // namespace wvcdm
|
||||
|
||||
#endif // CDM_TEST_URL_REQUEST_H_
|
||||
|
||||
Reference in New Issue
Block a user