Source release 16.3.0

This commit is contained in:
John W. Bruce
2020-07-24 14:30:03 -07:00
parent b830b1d1fb
commit 160df9f57a
74 changed files with 4632 additions and 2561 deletions

View File

@@ -26,6 +26,7 @@
#include "test_base.h"
#include "test_host.h"
#include "test_printers.h"
#include "test_sleep.h"
#include "url_request.h"
using namespace testing;
@@ -58,7 +59,7 @@ const std::string kCencInitData = a2bs_hex(
"edef8ba979d64acea3c827dcd51d21ed" // Widevine system id
"00000022" // pssh data size
// pssh data:
"08011a0d7769646576696e655f746573"
"08011a0d7769646576696e655f746573" // "streaming_clip9"
"74220f73747265616d696e675f636c69"
"7039");
const std::string kCencPersistentInitData = a2bs_hex(
@@ -68,7 +69,7 @@ const std::string kCencPersistentInitData = a2bs_hex(
"edef8ba979d64acea3c827dcd51d21ed" // Widevine system id
"00000020" // pssh data size
// pssh data:
"08011a0d7769646576696e655f746573"
"08011a0d7769646576696e655f746573" // "offline_clip6"
"74220d6f66666c696e655f636c697036");
const std::string kInvalidCencInitData = a2bs_hex(
"0000000c" // blob size
@@ -83,7 +84,7 @@ const std::string kNonWidevineCencInitData = a2bs_hex(
const std::string kWebMInitData = a2bs_hex("deadbeefdeadbeefdeadbeefdeadbeef");
const std::string kKeyIdsInitData =
"{\"kids\":[\"67ef0gd8pvfd0\",\"77ef0gd8pvfd0\"]}";
const std::string kHlsInitData =
const std::string kHlsInitData = // content_id = "bigbuckbunny"
"#EXT-X-KEY:METHOD=SAMPLE-AES,KEYFORMAT=\"com.widevine\",KEYFORMATVERSIONS="
"\"1\",URI=\"data:text/plain;base64,ew0KICAgInByb3ZpZGVyIjogIndpZGV2aW5lX3R"
"lc3QiLA0KICAgImNvbnRlbnRfaWQiOiAiWW1sblluVmphMkoxYm01NSIsDQogICAia2V5X2lkc"
@@ -331,19 +332,27 @@ class CdmTest : public WvCdmTestBase, public Cdm::IEventListener {
Cdm::Status status = cdm_->createSession(session_type, session_id);
ASSERT_EQ(Cdm::kSuccess, status);
std::string init_data_type_name;
std::string init_data;
if (session_type == Cdm::kTemporary) {
if (init_data_type == Cdm::kCenc) {
init_data_type_name = CENC_INIT_DATA_FORMAT;
init_data = kCencInitData;
} else if (init_data_type == Cdm::kHls) {
init_data_type_name = HLS_INIT_DATA_FORMAT;
init_data = kHlsInitData;
}
} else if (session_type == Cdm::kPersistentLicense ||
session_type == Cdm::kPersistentUsageRecord) {
if (init_data_type == Cdm::kCenc) {
init_data = kCencPersistentInitData;
init_data_type_name = CENC_INIT_DATA_FORMAT;
}
}
if (g_cutoff >= LOG_DEBUG) {
InitializationData parsed_init_data(init_data_type_name, init_data);
parsed_init_data.DumpToLogs();
}
ASSERT_FALSE(init_data.empty());
EXPECT_CALL(*this, onMessage(*session_id, Cdm::kLicenseRequest, _))
@@ -397,26 +406,19 @@ class CdmTest : public WvCdmTestBase, public Cdm::IEventListener {
Mock::VerifyAndClear(this);
}
std::string GetProvisioningResponse(const std::string& message,
size_t max_attempts = 10) {
std::string GetProvisioningResponse(const std::string& message) {
std::string uri = config_.provisioning_server();
LOGV("GetProvisioningResponse: URI: %s", uri.c_str());
LOGV("GetProvisioningResponse: message:\n%s\n", b2a_hex(message).c_str());
std::string reply;
uri += "&signedRequest=" + message;
// TODO(b/139361531): Remove loop once provisioning service is stable.
for (size_t attempt = 1; attempt <= max_attempts; attempt++) {
FetchCertificate(uri, &reply);
if (HasFatalFailure()) {
LOGE("Failed to get provisioning response: attempt = %zu", attempt);
reply.clear();
continue;
} else {
LOGV("GetProvisioningResponse: response:\n%s\n", reply.c_str());
break;
}
std::string reply;
FetchCertificate(uri, &reply);
if (HasFatalFailure()) {
LOGE("Failed to get provisioning response");
reply.clear();
} else {
LOGV("GetProvisioningResponse: response:\n%s\n", reply.c_str());
}
return reply;
}
@@ -443,6 +445,10 @@ class CdmTest : public WvCdmTestBase, public Cdm::IEventListener {
Cdm::InitDataType init_data_type,
const std::string& init_data) {
const int num_retries = 5;
if (init_data_type == Cdm::kCenc && g_cutoff >= LOG_DEBUG) {
InitializationData parsed_init_data(CENC_INIT_DATA_FORMAT, init_data);
parsed_init_data.DumpToLogs();
}
for (int i = 0; i < num_retries; i++) {
LOGD("attempt %d", i);
Cdm::Status status =
@@ -512,18 +518,19 @@ class MockTimerClient : public Cdm::ITimer::IClient {
MOCK_METHOD1(onTimerExpired, void(void*));
};
} // namespace
TEST_F(CdmTest, TestHostTimer) {
// Validate that the TestHost timers are processed in the correct order.
// Validate that the TestHost timers are processed in the correct order and
// on the correct timeouts.
const int64_t kTimerDelayMs = 1000;
void* kCtx1 = reinterpret_cast<void*>(0x1);
void* kCtx2 = reinterpret_cast<void*>(0x2);
void* kCtx4 = reinterpret_cast<void*>(0x4);
MockTimerClient client;
g_host->setTimeout(kTimerDelayMs * 1, &client, kCtx1);
g_host->setTimeout(kTimerDelayMs * 2, &client, kCtx2);
g_host->setTimeout(kTimerDelayMs * 4, &client, kCtx4);
EXPECT_CALL(client, onTimerExpired(kCtx1));
g_host->ElapseTime(kTimerDelayMs);
@@ -536,6 +543,14 @@ TEST_F(CdmTest, TestHostTimer) {
EXPECT_CALL(client, onTimerExpired(_)).Times(0);
g_host->ElapseTime(kTimerDelayMs);
Mock::VerifyAndClear(&client);
EXPECT_CALL(client, onTimerExpired(kCtx4));
g_host->ElapseTime(kTimerDelayMs);
Mock::VerifyAndClear(&client);
EXPECT_CALL(client, onTimerExpired(_)).Times(0);
g_host->ElapseTime(kTimerDelayMs);
Mock::VerifyAndClear(&client);
}
TEST_F(CdmTest, Initialize) {
@@ -1649,6 +1664,65 @@ TEST_F(CdmTest, RemoveThreeUsageRecords) {
ASSERT_EQ(Cdm::kSessionNotFound, status);
}
// Reload an offline license that does not have a usage entry.
TEST_F(CdmTest, LoadPersistentNoNonce) {
EnsureProvisioned();
std::string session_id;
ASSERT_EQ(Cdm::kSuccess,
cdm_->createSession(Cdm::kPersistentLicense, &session_id));
video_widevine::WidevinePsshData pssh;
// offline_clip1 does not have a provider session token, so it will not
// generate a usage table entry.
pssh.set_content_id("offline_clip1");
const std::string init_data = MakePSSH(pssh);
std::string license_request;
{
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _))
.WillOnce(SaveArg<2>(&license_request));
ASSERT_EQ(Cdm::kSuccess,
generateRequestWithRetry(session_id, Cdm::kCenc, init_data));
Mock::VerifyAndClear(this);
}
// Send the request to the license server and receive the license response.
std::string license_response;
FetchLicense(config_.license_server(), license_request, &license_response);
// Update the session with the new keys.
{
EXPECT_CALL(*this, onKeyStatusesChange(session_id, true));
ASSERT_EQ(Cdm::kSuccess, updateWithRetry(session_id, license_response));
Mock::VerifyAndClear(this);
}
// Should be able to load the session again after closing it.
Cdm::Status status = cdm_->close(session_id);
ASSERT_EQ(Cdm::kSuccess, status);
EXPECT_CALL(*this, onKeyStatusesChange(session_id, true));
status = cdm_->load(session_id);
EXPECT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Should be able to load the session again after recreating the CDM.
ASSERT_NO_FATAL_FAILURE(RecreateCdm(true /* privacy_mode */));
EXPECT_CALL(*this, onKeyStatusesChange(session_id, true));
status = cdm_->load(session_id);
EXPECT_EQ(Cdm::kSuccess, status);
Mock::VerifyAndClear(this);
// Should not be able to load the session again after clearing storage.
status = cdm_->close(session_id);
ASSERT_EQ(Cdm::kSuccess, status);
g_host->Reset();
EnsureProvisioned();
EXPECT_CALL(*this, onKeyStatusesChange(session_id, _)).Times(0);
status = cdm_->load(session_id);
EXPECT_EQ(Cdm::kSessionNotFound, status);
Mock::VerifyAndClear(this);
}
TEST_F(CdmTest, RemoveIncomplete) {
EnsureProvisioned();
std::string session_id;
@@ -2414,4 +2488,6 @@ TEST_F(CdmIndividualizationTest, NoLoadWithoutProvisioning) {
EXPECT_EQ(Cdm::kNeedsDeviceCertificate, cdm_->load(kBogusSessionId));
}
} // namespace
} // namespace widevine