Source release v3.4.1
This commit is contained in:
@@ -53,6 +53,9 @@ const std::pair<const std::string *, const std::string *> kBase64TestVectors[] =
|
||||
make_pair(&kTwoBytesOverData, &kTwoBytesOverB64Data),
|
||||
make_pair(&kTestData, &kB64TestData)};
|
||||
|
||||
const std::string kBase64ErrorVectors[] = {"Foo$sa", "Foo\x99\x23\xfa\02",
|
||||
"Foo==Foo", "FooBa"};
|
||||
|
||||
std::string ConvertToBase64WebSafe(const std::string &std_base64_string) {
|
||||
std::string str(std_base64_string);
|
||||
for (size_t i = 0; i < str.size(); ++i) {
|
||||
@@ -89,9 +92,19 @@ TEST_P(Base64EncodeDecodeTest, WebSafeEncodeDecodeTest) {
|
||||
EXPECT_STREQ(encoded_string.data(), b64_string.data());
|
||||
}
|
||||
|
||||
class Base64ErrorDecodeTest : public ::testing::TestWithParam<std::string> {};
|
||||
|
||||
TEST_P(Base64ErrorDecodeTest, EncoderErrors) {
|
||||
std::vector<uint8_t> result = Base64Decode(GetParam());
|
||||
EXPECT_EQ(0u, result.size());
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(ExecutesBase64Test, Base64EncodeDecodeTest,
|
||||
::testing::ValuesIn(kBase64TestVectors));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(ExecutesBase64Test, Base64ErrorDecodeTest,
|
||||
::testing::ValuesIn(kBase64ErrorVectors));
|
||||
|
||||
class HtoNLL64Test : public ::testing::Test {};
|
||||
|
||||
TEST_F(HtoNLL64Test, PositiveNumber) {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
namespace wvcdm {
|
||||
|
||||
// Protobuf generated classes.
|
||||
using video_widevine::WidevineCencHeader;
|
||||
using video_widevine::WidevinePsshData;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -164,6 +164,19 @@ const std::string kZeroSizedPsshBox = a2bs_hex(
|
||||
// data:
|
||||
"08011a0d7769646576696e655f74657374220f73747265616d696e675f636c697031");
|
||||
|
||||
const std::string kSubLicensePsshBox = a2bs_hex(
|
||||
// Widevine PSSH box
|
||||
"0000009f" // atom size (whole buffer)
|
||||
"70737368" // atom type="pssh"
|
||||
"00000000" // v0, flags=0
|
||||
"edef8ba979d64acea3c827dcd51d21ed" // system id (Widevine)
|
||||
"0000007f" // data size
|
||||
// data:
|
||||
"0801120d746573745f6b65795f69645f30120d746573745f6b65795f69645f31220f"
|
||||
"746573745f636f6e74656e745f69645a250a147375625f73657373696f6e5f6b6579"
|
||||
"5f69645f30120d7375625f6c6963656e73655f305a250a147375625f73657373696f"
|
||||
"6e5f6b65795f69645f31120d7375625f6c6963656e73655f31");
|
||||
|
||||
// HLS test attribute key and values
|
||||
const std::string kHlsIvHexValue = "6DF49213A781E338628D0E9C812D328E";
|
||||
const std::string kHlsIvValue = "0x" + kHlsIvHexValue;
|
||||
@@ -353,7 +366,9 @@ struct HlsInitDataVariant {
|
||||
HlsInitDataVariant(CdmHlsMethod method, const std::string& provider,
|
||||
const std::string& content_id, const std::string& key_id,
|
||||
bool success)
|
||||
: method_(method), provider_(provider), content_id_(content_id),
|
||||
: method_(method),
|
||||
provider_(provider),
|
||||
content_id_(content_id),
|
||||
success_(success) {
|
||||
if (key_id.size() > 0) key_ids_.push_back(key_id);
|
||||
}
|
||||
@@ -410,13 +425,31 @@ TEST_P(InitializationDataTest, Parse) {
|
||||
EXPECT_FALSE(init_data.IsEmpty());
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(ParsePssh, InitializationDataTest,
|
||||
::testing::Values(kWidevinePssh, kWidevinePsshFirst,
|
||||
kWidevinePsshAfterV0Pssh,
|
||||
kWidevinePsshAfterNonZeroFlags,
|
||||
kWidevinePsshAfterV1Pssh,
|
||||
kWidevineV1Pssh, kOtherBoxFirst,
|
||||
kZeroSizedPsshBox));
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
ParsePssh, InitializationDataTest,
|
||||
::testing::Values(kWidevinePssh, kWidevinePsshFirst,
|
||||
kWidevinePsshAfterV0Pssh, kWidevinePsshAfterNonZeroFlags,
|
||||
kWidevinePsshAfterV1Pssh, kWidevineV1Pssh, kOtherBoxFirst,
|
||||
kZeroSizedPsshBox, kSubLicensePsshBox));
|
||||
TEST_F(InitializationDataTest, ExtractSubLicense) {
|
||||
InitializationData init_data(ISO_BMFF_VIDEO_MIME_TYPE, kSubLicensePsshBox);
|
||||
EXPECT_FALSE(init_data.IsEmpty());
|
||||
std::vector<video_widevine::SubLicense> keys =
|
||||
init_data.ExtractEmbeddedKeys();
|
||||
ASSERT_EQ(keys.size(), 2UL);
|
||||
ASSERT_EQ(keys[0].sub_session_key_id(), "sub_session_key_id_0");
|
||||
ASSERT_EQ(keys[1].sub_session_key_id(), "sub_session_key_id_1");
|
||||
ASSERT_EQ(keys[0].key_msg(), "sub_license_0");
|
||||
ASSERT_EQ(keys[1].key_msg(), "sub_license_1");
|
||||
}
|
||||
|
||||
TEST_F(InitializationDataTest, ExtractEmptySubLicense) {
|
||||
InitializationData init_data(ISO_BMFF_VIDEO_MIME_TYPE, kWidevinePssh);
|
||||
EXPECT_FALSE(init_data.IsEmpty());
|
||||
std::vector<video_widevine::SubLicense> keys =
|
||||
init_data.ExtractEmbeddedKeys();
|
||||
ASSERT_TRUE(keys.empty());
|
||||
}
|
||||
|
||||
TEST_P(HlsKeyFormatVersionsExtractionTest, ExtractKeyFormatVersions) {
|
||||
std::vector<std::string> versions = GetParam();
|
||||
@@ -598,9 +631,9 @@ TEST_P(HlsConstructionTest, InitData) {
|
||||
EXPECT_EQ(param.success_, InitializationData::ConstructWidevineInitData(
|
||||
param.method_, uri, &value));
|
||||
if (param.success_) {
|
||||
WidevineCencHeader cenc_header;
|
||||
WidevinePsshData cenc_header;
|
||||
EXPECT_TRUE(cenc_header.ParseFromString(value));
|
||||
EXPECT_EQ(video_widevine::WidevineCencHeader_Algorithm_AESCTR,
|
||||
EXPECT_EQ(video_widevine::WidevinePsshData_Algorithm_AESCTR,
|
||||
cenc_header.algorithm());
|
||||
for (size_t i = 0; i < param.key_ids_.size(); ++i) {
|
||||
bool key_id_found = false;
|
||||
@@ -620,9 +653,14 @@ TEST_P(HlsConstructionTest, InitData) {
|
||||
cenc_header.content_id());
|
||||
uint32_t protection_scheme = 0;
|
||||
switch (param.method_) {
|
||||
case kHlsMethodAes128: protection_scheme = kFourCcCbc1; break;
|
||||
case kHlsMethodSampleAes: protection_scheme = kFourCcCbcs; break;
|
||||
default: break;
|
||||
case kHlsMethodAes128:
|
||||
protection_scheme = kFourCcCbc1;
|
||||
break;
|
||||
case kHlsMethodSampleAes:
|
||||
protection_scheme = kFourCcCbcs;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
EXPECT_EQ(protection_scheme, cenc_header.protection_scheme());
|
||||
}
|
||||
@@ -633,8 +671,8 @@ INSTANTIATE_TEST_CASE_P(
|
||||
::testing::Values(
|
||||
HlsInitDataVariant(kHlsMethodAes128, "", kHlsTestContentId,
|
||||
kHlsTestKeyId1, false),
|
||||
HlsInitDataVariant(kHlsMethodAes128, kHlsTestProvider,
|
||||
"", kHlsTestKeyId1, false),
|
||||
HlsInitDataVariant(kHlsMethodAes128, kHlsTestProvider, "",
|
||||
kHlsTestKeyId1, false),
|
||||
HlsInitDataVariant(kHlsMethodAes128, kHlsTestProvider,
|
||||
kHlsTestContentId, "", false),
|
||||
HlsInitDataVariant(kHlsMethodAes128, kHlsTestProvider,
|
||||
@@ -699,9 +737,9 @@ TEST_P(HlsParseTest, Parse) {
|
||||
EXPECT_EQ(kHlsMethodSampleAes, init_data.hls_method());
|
||||
}
|
||||
|
||||
WidevineCencHeader cenc_header;
|
||||
WidevinePsshData cenc_header;
|
||||
EXPECT_TRUE(cenc_header.ParseFromString(init_data.data()));
|
||||
EXPECT_EQ(video_widevine::WidevineCencHeader_Algorithm_AESCTR,
|
||||
EXPECT_EQ(video_widevine::WidevinePsshData_Algorithm_AESCTR,
|
||||
cenc_header.algorithm());
|
||||
if (param.key_.compare(kJsonProvider) == 0) {
|
||||
EXPECT_EQ(param.value_, cenc_header.provider());
|
||||
|
||||
@@ -79,6 +79,32 @@ const std::string kLicenseRequestSignature = a2bs_hex(
|
||||
"9AE18B91516E0CDD0B581590DDDEA2A2527E2C9ABA273629B586A9D22D451A827E332CFC3E"
|
||||
"9BEDB6CF3D8713F9E11675DF1F5DB9038DBBECAB9D1683F8722CAF6E18EC8C04AEE5");
|
||||
|
||||
const std::string kSubLicensePssh = a2bs_hex(
|
||||
"000002317073736800000000edef8ba979d64acea3c827dcd51d21ed000002010801120d54"
|
||||
"6573744b6579415544494f30120a546573744b6579534430120a546573744b65794844301a"
|
||||
"0048e3dc959b0650025a9b010a101f10e4700b1a5b731c545fe2405cea1b12860112620a0d"
|
||||
"546573744b6579415544494f3012102f4b661d1064b5ea82efcd3ef850f45b1a10a02c5cea"
|
||||
"5182383c064c06abbc79bfa8200242240a1023acc9a0ef2bca66af2a1307cc9edeb21210e1"
|
||||
"f1d352b4c6b1aad1fd78423db256946205415544494f1a20aaf4537f09332c502a88f43a18"
|
||||
"a3e21ec28bbde675c5d87054fbca06f98e98015a95010a10c034cf6ae181b8d07f2e79142d"
|
||||
"792bb3128001125c0a0a546573744b657953443012106d37a0a201afdef8a494f89a4b0772"
|
||||
"4a1a10457db86b73bf87177a5cc61c0d04b690200242240a1001fe432d2a8afb7054ae76a3"
|
||||
"9c2727e612108761b7e0ba354ee4132117a9de12abd3620253441a20e3f37529cb795b35a0"
|
||||
"d186e4ce7187f08dda5f1df136ddb92eb0a65a899635005a95010a1021cdec9b2105c6b643"
|
||||
"e71f68e5302c85128001125c0a0a546573744b6579484430121012a3e3afe1e23be2c3fc55"
|
||||
"fddad877451a108f31ff0865f4d4fb41d96414297f7728200242240a1061e3cbca755b36c8"
|
||||
"e7d6dda03af20e4f1210a2fa2fc5d10c9c84ddc5511446ce77e9620248441a20a945699aef"
|
||||
"49355b0214b636edb7670bbe350c58b69cd52f207953b380a52df2");
|
||||
|
||||
const std::string kSubSessionKeyID1 =
|
||||
a2bs_hex("1f10e4700b1a5b731c545fe2405cea1b");
|
||||
|
||||
const std::string kSubSessionKeyID2 =
|
||||
a2bs_hex("c034cf6ae181b8d07f2e79142d792bb3");
|
||||
|
||||
const std::string kSubSessionKeyID3 =
|
||||
a2bs_hex("21cdec9b2105c6b643e71f68e5302c85");
|
||||
|
||||
class MockCryptoSession : public CryptoSession {
|
||||
public:
|
||||
MOCK_METHOD0(IsOpen, bool());
|
||||
@@ -88,6 +114,9 @@ class MockCryptoSession : public CryptoSession {
|
||||
MOCK_METHOD1(GetApiVersion, bool(uint32_t*));
|
||||
MOCK_METHOD1(GenerateNonce, bool(uint32_t*));
|
||||
MOCK_METHOD3(PrepareRequest, bool(const std::string&, bool, std::string*));
|
||||
MOCK_METHOD3(GenerateSubSessionNonce,
|
||||
bool(const std::string& sub_session_key_id, bool* exists,
|
||||
uint32_t* nonce));
|
||||
};
|
||||
|
||||
class MockPolicyEngine : public PolicyEngine {
|
||||
@@ -126,11 +155,12 @@ using ::testing::SetArgPointee;
|
||||
|
||||
class CdmLicenseTest : public ::testing::Test {
|
||||
protected:
|
||||
CdmLicenseTest(const std::string& pssh = (kCencInitDataHdr + kCencPssh))
|
||||
: pssh_(pssh) {}
|
||||
virtual void SetUp() {
|
||||
clock_ = new MockClock();
|
||||
crypto_session_ = new MockCryptoSession();
|
||||
init_data_ = new MockInitializationData(CENC_INIT_DATA_FORMAT,
|
||||
kCencInitDataHdr + kCencPssh);
|
||||
crypto_session_ = new testing::StrictMock<MockCryptoSession>();
|
||||
init_data_ = new MockInitializationData(CENC_INIT_DATA_FORMAT, pssh_);
|
||||
policy_engine_ = new MockPolicyEngine(crypto_session_);
|
||||
}
|
||||
|
||||
@@ -142,7 +172,7 @@ class CdmLicenseTest : public ::testing::Test {
|
||||
if (clock_) delete clock_;
|
||||
}
|
||||
|
||||
void CreateCdmLicense() {
|
||||
virtual void CreateCdmLicense() {
|
||||
cdm_license_ = new CdmLicense(kCdmSessionId, clock_);
|
||||
clock_ = NULL;
|
||||
}
|
||||
@@ -153,6 +183,12 @@ class CdmLicenseTest : public ::testing::Test {
|
||||
MockInitializationData* init_data_;
|
||||
MockPolicyEngine* policy_engine_;
|
||||
ServiceCertificate service_cert_;
|
||||
std::string pssh_;
|
||||
};
|
||||
|
||||
class SubLicenseTest : public CdmLicenseTest {
|
||||
protected:
|
||||
SubLicenseTest() : CdmLicenseTest(kSubLicensePssh) {}
|
||||
};
|
||||
|
||||
TEST_F(CdmLicenseTest, InitSuccess) {
|
||||
@@ -303,4 +339,88 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) {
|
||||
EXPECT_EQ(kNonce, license_request.key_control_nonce());
|
||||
}
|
||||
|
||||
TEST_F(SubLicenseTest, VerifySubSessionData) {
|
||||
bool usage_information_support = true;
|
||||
CryptoSession::HdcpCapability current_hdcp_version = HDCP_NO_DIGITAL_OUTPUT;
|
||||
CryptoSession::HdcpCapability max_hdcp_version = HDCP_V2_1;
|
||||
uint32_t crypto_session_api_version = 9;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
|
||||
EXPECT_CALL(*crypto_session_, GenerateRequestId(NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kCryptoRequestId), Return(true)));
|
||||
EXPECT_CALL(*crypto_session_, UsageInformationSupport(NotNull()))
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<0>(usage_information_support), Return(true)));
|
||||
EXPECT_CALL(*crypto_session_, GetHdcpCapabilities(NotNull(), NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(current_hdcp_version),
|
||||
SetArgPointee<1>(max_hdcp_version), Return(true)));
|
||||
EXPECT_CALL(*crypto_session_, GetApiVersion(NotNull()))
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<0>(crypto_session_api_version), Return(true)));
|
||||
EXPECT_CALL(*clock_, GetCurrentTime()).WillOnce(Return(kLicenseStartTime));
|
||||
EXPECT_CALL(*crypto_session_, GenerateNonce(NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kNonce), Return(true)));
|
||||
EXPECT_CALL(*crypto_session_, PrepareRequest(_, Eq(false), NotNull()))
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<2>(kLicenseRequestSignature), Return(true)));
|
||||
|
||||
// SubLicense session data calls.
|
||||
// TODO(jfore): These calls are being invoked twice each. This should not
|
||||
// present a functional problem, but we should investigate why.
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
GenerateSubSessionNonce(kSubSessionKeyID1, NotNull(), NotNull()))
|
||||
.WillRepeatedly(
|
||||
DoAll(SetArgPointee<1>(true), SetArgPointee<2>(0), Return(true)));
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
GenerateSubSessionNonce(kSubSessionKeyID2, NotNull(), NotNull()))
|
||||
.WillRepeatedly(
|
||||
DoAll(SetArgPointee<1>(true), SetArgPointee<2>(1), Return(true)));
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
GenerateSubSessionNonce(kSubSessionKeyID3, NotNull(), NotNull()))
|
||||
.WillRepeatedly(
|
||||
DoAll(SetArgPointee<1>(true), SetArgPointee<2>(2), Return(true)));
|
||||
|
||||
CreateCdmLicense();
|
||||
// TODO(gmorgan) fix below - no default service certificate
|
||||
//service_cert_.Init(kDefaultServiceCertificate);
|
||||
EXPECT_TRUE(cdm_license_->Init(
|
||||
&service_cert_, kToken, kClientTokenDrmCert, kEmptyString,
|
||||
crypto_session_, policy_engine_));
|
||||
CdmAppParameterMap app_parameters;
|
||||
CdmKeyMessage signed_request;
|
||||
Properties::set_use_certificates_as_identification(true);
|
||||
std::string server_url;
|
||||
EXPECT_EQ(cdm_license_->PrepareKeyRequest(*init_data_, kLicenseTypeStreaming,
|
||||
app_parameters, &signed_request,
|
||||
&server_url),
|
||||
KEY_MESSAGE);
|
||||
EXPECT_TRUE(!signed_request.empty());
|
||||
|
||||
SignedMessage signed_message;
|
||||
EXPECT_TRUE(signed_message.ParseFromString(signed_request));
|
||||
LicenseRequest license_request;
|
||||
EXPECT_TRUE(license_request.ParseFromString(signed_message.msg()));
|
||||
EXPECT_EQ(3, license_request.sub_session_data().size());
|
||||
|
||||
for (int i = 0; i < license_request.sub_session_data().size(); ++i) {
|
||||
const video_widevine::LicenseRequest_SubSessionData& sl =
|
||||
license_request.sub_session_data(i);
|
||||
EXPECT_EQ(static_cast<uint32_t>(i), sl.nonce());
|
||||
switch (i) {
|
||||
case 0:
|
||||
EXPECT_EQ(kSubSessionKeyID1, sl.sub_session_key_id());
|
||||
EXPECT_EQ("AUDIO", sl.track_label());
|
||||
break;
|
||||
case 1:
|
||||
EXPECT_EQ(kSubSessionKeyID2, sl.sub_session_key_id());
|
||||
EXPECT_EQ("SD", sl.track_label());
|
||||
break;
|
||||
case 3:
|
||||
EXPECT_EQ(kSubSessionKeyID3, sl.sub_session_key_id());
|
||||
EXPECT_EQ("HD", sl.track_label());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
@@ -487,6 +487,27 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
|
||||
break;
|
||||
case PARSE_RESPONSE_ERROR_4: *os << "PARSE_RESPONSE_ERROR_4";
|
||||
break;
|
||||
case LICENSE_REQUEST_INVALID_SUBLICENSE:
|
||||
*os << "LICENSE_REQUEST_INVALID_SUBLICENSE";
|
||||
break;
|
||||
case INVALID_SESSION_1:
|
||||
*os << "INVALID_SESSION_1";
|
||||
break;
|
||||
case NO_DEVICE_KEY_1:
|
||||
*os << "NO_DEVICE_KEY_1";
|
||||
break;
|
||||
case NO_CONTENT_KEY_2:
|
||||
*os << "NO_CONTENT_KEY_2";
|
||||
break;
|
||||
case INSUFFICIENT_CRYPTO_RESOURCES_2:
|
||||
*os << "INSUFFICIENT_CRYPTO_RESOURCES_2";
|
||||
break;
|
||||
case UNKNOWN_SELECT_KEY_ERROR_1:
|
||||
*os << "UNKNOWN_SELECT_KEY_ERROR_1";
|
||||
break;
|
||||
case UNKNOWN_SELECT_KEY_ERROR_2:
|
||||
*os << "UNKNOWN_SELECT_KEY_ERROR_2";
|
||||
break;
|
||||
default:
|
||||
*os << "Unknown CdmResponseType";
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user