Include protection_scheme in Widevine CENC request
Widevine license server added support for protection_schemes recently; If CENC request includes protection_scheme in the CENC request, server will return with a PSSH with protection_scheme filled in. Change-Id: I6dcac498b5e039503d6ac0f6e057737f7c53efaf
This commit is contained in:
parent
d9e7e2f1d0
commit
5fc6e540f3
|
@ -496,7 +496,8 @@ bool RunPackager(const StreamDescriptorList& stream_descriptors) {
|
|||
FLAGS_enable_playready_encryption) {
|
||||
if (encryption_options.protection_scheme == FOURCC_NULL)
|
||||
return false;
|
||||
encryption_key_source = CreateEncryptionKeySource();
|
||||
encryption_key_source =
|
||||
CreateEncryptionKeySource(encryption_options.protection_scheme);
|
||||
if (!encryption_key_source)
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -88,11 +88,12 @@ std::unique_ptr<RequestSigner> CreateSigner() {
|
|||
return signer;
|
||||
}
|
||||
|
||||
std::unique_ptr<KeySource> CreateEncryptionKeySource() {
|
||||
std::unique_ptr<KeySource> CreateEncryptionKeySource(FourCC protection_scheme) {
|
||||
std::unique_ptr<KeySource> encryption_key_source;
|
||||
if (FLAGS_enable_widevine_encryption) {
|
||||
std::unique_ptr<WidevineKeySource> widevine_key_source(
|
||||
new WidevineKeySource(FLAGS_key_server_url, FLAGS_include_common_pssh));
|
||||
widevine_key_source->set_protection_scheme(protection_scheme);
|
||||
if (!FLAGS_signer.empty()) {
|
||||
std::unique_ptr<RequestSigner> request_signer(CreateSigner());
|
||||
if (!request_signer)
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include <memory>
|
||||
|
||||
#include "packager/media/base/fourccs.h"
|
||||
|
||||
DECLARE_bool(dump_stream_info);
|
||||
|
||||
namespace shaka {
|
||||
|
@ -30,9 +32,11 @@ struct MuxerOptions;
|
|||
|
||||
/// Create KeySource based on provided command line options for content
|
||||
/// encryption. Also fetches keys.
|
||||
/// @param protection_scheme specifies the protection scheme to be used for
|
||||
/// encryption.
|
||||
/// @return A std::unique_ptr containing a new KeySource, or nullptr if
|
||||
/// encryption is not required.
|
||||
std::unique_ptr<KeySource> CreateEncryptionKeySource();
|
||||
std::unique_ptr<KeySource> CreateEncryptionKeySource(FourCC protection_scheme);
|
||||
|
||||
/// Create KeySource based on provided command line options for content
|
||||
/// decryption. Does not fetch keys.
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "packager/base/bind.h"
|
||||
#include "packager/base/json/json_reader.h"
|
||||
#include "packager/base/json/json_writer.h"
|
||||
#include "packager/base/strings/string_number_conversions.h"
|
||||
#include "packager/media/base/fixed_key_source.h"
|
||||
#include "packager/media/base/http_key_fetcher.h"
|
||||
#include "packager/media/base/network_util.h"
|
||||
|
@ -22,6 +23,7 @@
|
|||
#include "packager/media/base/widevine_pssh_data.pb.h"
|
||||
|
||||
namespace shaka {
|
||||
namespace media {
|
||||
namespace {
|
||||
|
||||
const bool kEnableKeyRotation = true;
|
||||
|
@ -118,9 +120,12 @@ bool GetPsshDataFromTrack(const base::DictionaryValue& track_dict,
|
|||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
bool IsProtectionSchemeValid(FourCC protection_scheme) {
|
||||
return protection_scheme == FOURCC_cenc || protection_scheme == FOURCC_cbcs ||
|
||||
protection_scheme == FOURCC_cbc1 || protection_scheme == FOURCC_cens;
|
||||
}
|
||||
|
||||
namespace media {
|
||||
} // namespace
|
||||
|
||||
WidevineKeySource::WidevineKeySource(const std::string& server_url,
|
||||
bool add_common_pssh)
|
||||
|
@ -130,6 +135,7 @@ WidevineKeySource::WidevineKeySource(const std::string& server_url,
|
|||
key_fetcher_(new HttpKeyFetcher(kKeyFetchTimeoutInSeconds)),
|
||||
server_url_(server_url),
|
||||
crypto_period_count_(kDefaultCryptoPeriodCount),
|
||||
protection_scheme_(FOURCC_cenc),
|
||||
add_common_pssh_(add_common_pssh),
|
||||
key_production_started_(false),
|
||||
start_key_production_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
|
||||
|
@ -157,6 +163,18 @@ Status WidevineKeySource::FetchKeys(const std::vector<uint8_t>& content_id,
|
|||
BytesToBase64String(content_id, &content_id_base64_string);
|
||||
request_dict_.SetString("content_id", content_id_base64_string);
|
||||
request_dict_.SetString("policy", policy);
|
||||
|
||||
FourCC protection_scheme = protection_scheme_;
|
||||
// Treat sample aes as a variant of cbcs.
|
||||
if (protection_scheme == kAppleSampleAesProtectionScheme)
|
||||
protection_scheme = FOURCC_cbcs;
|
||||
if (IsProtectionSchemeValid(protection_scheme)) {
|
||||
request_dict_.SetInteger("protection_scheme", protection_scheme);
|
||||
} else {
|
||||
LOG(WARNING) << "Ignore unrecognized protection scheme "
|
||||
<< FourCCToString(protection_scheme);
|
||||
}
|
||||
|
||||
return FetchKeysInternal(!kEnableKeyRotation, 0, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "packager/base/synchronization/waitable_event.h"
|
||||
#include "packager/base/values.h"
|
||||
#include "packager/media/base/closure_thread.h"
|
||||
#include "packager/media/base/fourccs.h"
|
||||
#include "packager/media/base/key_source.h"
|
||||
|
||||
namespace shaka {
|
||||
|
@ -53,6 +54,11 @@ class WidevineKeySource : public KeySource {
|
|||
Status FetchKeys(const std::vector<uint8_t>& content_id,
|
||||
const std::string& policy);
|
||||
|
||||
/// Set the protection scheme for the key source.
|
||||
void set_protection_scheme(FourCC protection_scheme) {
|
||||
protection_scheme_ = protection_scheme;
|
||||
}
|
||||
|
||||
/// Set signer for the key source.
|
||||
/// @param signer signs the request message.
|
||||
void set_signer(std::unique_ptr<RequestSigner> signer);
|
||||
|
@ -61,9 +67,6 @@ class WidevineKeySource : public KeySource {
|
|||
/// @param key_fetcher points to the @b KeyFetcher object to be injected.
|
||||
void set_key_fetcher(std::unique_ptr<KeyFetcher> key_fetcher);
|
||||
|
||||
protected:
|
||||
ClosureThread key_production_thread_;
|
||||
|
||||
private:
|
||||
typedef std::map<TrackType, std::unique_ptr<EncryptionKey>> EncryptionKeyMap;
|
||||
typedef ProducerConsumerQueue<std::shared_ptr<EncryptionKeyMap>>
|
||||
|
@ -104,6 +107,7 @@ class WidevineKeySource : public KeySource {
|
|||
// Push the keys to the key pool.
|
||||
bool PushToKeyPool(EncryptionKeyMap* encryption_key_map);
|
||||
|
||||
ClosureThread key_production_thread_;
|
||||
// The fetcher object used to fetch keys from the license service.
|
||||
// It is initialized to a default fetcher on class initialization.
|
||||
// Can be overridden using set_key_fetcher for testing or other purposes.
|
||||
|
@ -113,6 +117,7 @@ class WidevineKeySource : public KeySource {
|
|||
base::DictionaryValue request_dict_;
|
||||
|
||||
const uint32_t crypto_period_count_;
|
||||
FourCC protection_scheme_;
|
||||
base::Lock lock_;
|
||||
bool add_common_pssh_;
|
||||
bool key_production_started_;
|
||||
|
|
|
@ -19,13 +19,19 @@
|
|||
#include "packager/media/base/widevine_key_source.h"
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::Bool;
|
||||
using ::testing::Combine;
|
||||
using ::testing::DoAll;
|
||||
using ::testing::InSequence;
|
||||
using ::testing::Return;
|
||||
using ::testing::SetArgPointee;
|
||||
using ::testing::StrEq;
|
||||
using ::testing::Test;
|
||||
using ::testing::Values;
|
||||
using ::testing::WithParamInterface;
|
||||
|
||||
namespace shaka {
|
||||
namespace media {
|
||||
namespace {
|
||||
const char kServerUrl[] = "http://www.foo.com/getcontentkey";
|
||||
const char kContentId[] = "ContentFoo";
|
||||
|
@ -45,6 +51,7 @@ const char kLicenseStatusUnknownError[] = "UNKNOWN_ERROR";
|
|||
|
||||
const char kExpectedRequestMessageFormat[] =
|
||||
"{\"content_id\":\"%s\",\"drm_types\":[\"WIDEVINE\"],\"policy\":\"%s\","
|
||||
"\"protection_scheme\":%d,"
|
||||
"\"tracks\":[{\"type\":\"SD\"},{\"type\":\"HD\"},{\"type\":\"UHD1\"},"
|
||||
"{\"type\":\"UHD2\"},{\"type\":\"AUDIO\"}]}";
|
||||
const char kExpectedRequestMessageWithAssetIdFormat[] =
|
||||
|
@ -64,11 +71,12 @@ const char kClassicTrackFormat[] = "{\"type\":\"%s\",\"key\":\"%s\"}";
|
|||
const char kLicenseResponseFormat[] = "{\"status\":\"%s\",\"tracks\":[%s]}";
|
||||
const char kHttpResponseFormat[] = "{\"response\":\"%s\"}";
|
||||
const uint8_t kRequestPsshBox[] = {
|
||||
0, 0, 0, 41, 'p', 's', 's', 'h', 0, 0, 0,
|
||||
0, 0, 0, 44, 'p', 's', 's', 'h', 0, 0, 0,
|
||||
0, 0xed, 0xef, 0x8b, 0xa9, 0x79, 0xd6, 0x4a, 0xce, 0xa3, 0xc8,
|
||||
0x27, 0xdc, 0xd5, 0x1d, 0x21, 0xed, 0, 0, 0, 0x09, 'P',
|
||||
'S', 'S', 'H', ' ', 'd', 'a', 't', 'a'};
|
||||
const char kRequestPsshData[] = "PSSH data";
|
||||
0x27, 0xdc, 0xd5, 0x1d, 0x21, 0xed, 0, 0, 0, 12, 0x22,
|
||||
0x0a, 'C', 'o', 'n', 't', 'e', 'n', 't', 'F', 'o', 'o'};
|
||||
const char kRequestPsshData[] = {0x22, 0x0a, 'C', 'o', 'n', 't', 'e',
|
||||
'n', 't', 'F', 'o', 'o', '\0'};
|
||||
const uint8_t kRequestPsshDataFromKeyIds[] = {0x12, 0x06, 0x00, 0x01,
|
||||
0x02, 0x03, 0x04, 0x05};
|
||||
const uint8_t kRequestKeyId[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
|
||||
|
@ -98,8 +106,8 @@ std::string GetMockKey(const std::string& track_type) {
|
|||
return "MockKey" + track_type;
|
||||
}
|
||||
|
||||
std::string GetMockPsshData(const std::string& track_type) {
|
||||
return "MockPsshData" + track_type;
|
||||
std::string GetMockPsshData() {
|
||||
return kRequestPsshData;
|
||||
}
|
||||
|
||||
std::string GenerateMockLicenseResponse() {
|
||||
|
@ -108,12 +116,11 @@ std::string GenerateMockLicenseResponse() {
|
|||
for (size_t i = 0; i < 5; ++i) {
|
||||
if (!tracks.empty())
|
||||
tracks += ",";
|
||||
tracks += base::StringPrintf(
|
||||
kTrackFormat,
|
||||
kTrackTypes[i].c_str(),
|
||||
tracks +=
|
||||
base::StringPrintf(kTrackFormat, kTrackTypes[i].c_str(),
|
||||
Base64Encode(GetMockKeyId(kTrackTypes[i])).c_str(),
|
||||
Base64Encode(GetMockKey(kTrackTypes[i])).c_str(),
|
||||
Base64Encode(GetMockPsshData(kTrackTypes[i])).c_str());
|
||||
Base64Encode(GetMockPsshData()).c_str());
|
||||
}
|
||||
return base::StringPrintf(kLicenseResponseFormat, "OK", tracks.c_str());
|
||||
}
|
||||
|
@ -134,8 +141,6 @@ std::string GenerateMockClassicLicenseResponse() {
|
|||
|
||||
} // namespace
|
||||
|
||||
namespace media {
|
||||
|
||||
class MockRequestSigner : public RequestSigner {
|
||||
public:
|
||||
explicit MockRequestSigner(const std::string& signer_name)
|
||||
|
@ -163,8 +168,7 @@ class MockKeyFetcher : public KeyFetcher {
|
|||
DISALLOW_COPY_AND_ASSIGN(MockKeyFetcher);
|
||||
};
|
||||
|
||||
class WidevineKeySourceTest : public ::testing::Test,
|
||||
public ::testing::WithParamInterface<bool> {
|
||||
class WidevineKeySourceTest : public Test {
|
||||
public:
|
||||
WidevineKeySourceTest()
|
||||
: mock_request_signer_(new MockRequestSigner(kSignerName)),
|
||||
|
@ -177,8 +181,17 @@ class WidevineKeySourceTest : public ::testing::Test,
|
|||
}
|
||||
|
||||
protected:
|
||||
FourCC GetExpectedProtectionScheme() {
|
||||
// Apple SAMPLE-AES is considered as a variation of cbcs.
|
||||
if (protection_scheme_ == kAppleSampleAesProtectionScheme)
|
||||
return FOURCC_cbcs;
|
||||
return protection_scheme_;
|
||||
}
|
||||
|
||||
void CreateWidevineKeySource() {
|
||||
widevine_key_source_.reset(new WidevineKeySource(kServerUrl, GetParam()));
|
||||
widevine_key_source_.reset(
|
||||
new WidevineKeySource(kServerUrl, add_common_pssh_));
|
||||
widevine_key_source_->set_protection_scheme(protection_scheme_);
|
||||
widevine_key_source_->set_key_fetcher(std::move(mock_key_fetcher_));
|
||||
}
|
||||
|
||||
|
@ -191,13 +204,14 @@ class WidevineKeySourceTest : public ::testing::Test,
|
|||
&encryption_key));
|
||||
EXPECT_EQ(GetMockKey(kTrackTypes[i]), ToString(encryption_key.key));
|
||||
if (!classic) {
|
||||
ASSERT_EQ(GetParam() ? 2u : 1u, encryption_key.key_system_info.size());
|
||||
ASSERT_EQ(add_common_pssh_ ? 2u : 1u,
|
||||
encryption_key.key_system_info.size());
|
||||
EXPECT_EQ(GetMockKeyId(kTrackTypes[i]),
|
||||
ToString(encryption_key.key_id));
|
||||
EXPECT_EQ(GetMockPsshData(kTrackTypes[i]),
|
||||
EXPECT_EQ(GetMockPsshData(),
|
||||
ToString(encryption_key.key_system_info[0].pssh_data()));
|
||||
|
||||
if (GetParam()) {
|
||||
if (add_common_pssh_) {
|
||||
// Each of the keys contains all the key IDs.
|
||||
const std::vector<uint8_t> common_system_id(
|
||||
kCommonSystemId, kCommonSystemId + arraysize(kCommonSystemId));
|
||||
|
@ -222,12 +236,14 @@ class WidevineKeySourceTest : public ::testing::Test,
|
|||
std::unique_ptr<MockKeyFetcher> mock_key_fetcher_;
|
||||
std::unique_ptr<WidevineKeySource> widevine_key_source_;
|
||||
std::vector<uint8_t> content_id_;
|
||||
bool add_common_pssh_ = false;
|
||||
FourCC protection_scheme_ = FOURCC_cenc;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(WidevineKeySourceTest);
|
||||
};
|
||||
|
||||
TEST_P(WidevineKeySourceTest, GetTrackTypeFromString) {
|
||||
TEST_F(WidevineKeySourceTest, GetTrackTypeFromString) {
|
||||
EXPECT_EQ(KeySource::TRACK_TYPE_SD,
|
||||
KeySource::GetTrackTypeFromString("SD"));
|
||||
EXPECT_EQ(KeySource::TRACK_TYPE_HD,
|
||||
|
@ -242,7 +258,7 @@ TEST_P(WidevineKeySourceTest, GetTrackTypeFromString) {
|
|||
KeySource::GetTrackTypeFromString("FOO"));
|
||||
}
|
||||
|
||||
TEST_P(WidevineKeySourceTest, GenerateSignatureFailure) {
|
||||
TEST_F(WidevineKeySourceTest, GenerateSignatureFailure) {
|
||||
EXPECT_CALL(*mock_request_signer_, GenerateSignature(_, _))
|
||||
.WillOnce(Return(false));
|
||||
|
||||
|
@ -252,11 +268,70 @@ TEST_P(WidevineKeySourceTest, GenerateSignatureFailure) {
|
|||
widevine_key_source_->FetchKeys(content_id_, kPolicy));
|
||||
}
|
||||
|
||||
TEST_F(WidevineKeySourceTest, RetryOnHttpTimeout) {
|
||||
std::string mock_response = base::StringPrintf(
|
||||
kHttpResponseFormat, Base64Encode(GenerateMockLicenseResponse()).c_str());
|
||||
|
||||
// Retry is expected on HTTP timeout.
|
||||
EXPECT_CALL(*mock_key_fetcher_, FetchKeys(_, _, _))
|
||||
.WillOnce(Return(Status(error::TIME_OUT, "")))
|
||||
.WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK)));
|
||||
|
||||
CreateWidevineKeySource();
|
||||
ASSERT_OK(widevine_key_source_->FetchKeys(content_id_, kPolicy));
|
||||
VerifyKeys(false);
|
||||
}
|
||||
|
||||
TEST_F(WidevineKeySourceTest, RetryOnTransientError) {
|
||||
std::string mock_license_status = base::StringPrintf(
|
||||
kLicenseResponseFormat, kLicenseStatusTransientError, "");
|
||||
std::string mock_response = base::StringPrintf(
|
||||
kHttpResponseFormat, Base64Encode(mock_license_status).c_str());
|
||||
|
||||
std::string expected_retried_response = base::StringPrintf(
|
||||
kHttpResponseFormat, Base64Encode(GenerateMockLicenseResponse()).c_str());
|
||||
|
||||
// Retry is expected on transient error.
|
||||
EXPECT_CALL(*mock_key_fetcher_, FetchKeys(_, _, _))
|
||||
.WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK)))
|
||||
.WillOnce(DoAll(SetArgPointee<2>(expected_retried_response),
|
||||
Return(Status::OK)));
|
||||
|
||||
CreateWidevineKeySource();
|
||||
ASSERT_OK(widevine_key_source_->FetchKeys(content_id_, kPolicy));
|
||||
VerifyKeys(false);
|
||||
}
|
||||
|
||||
TEST_F(WidevineKeySourceTest, NoRetryOnUnknownError) {
|
||||
std::string mock_license_status = base::StringPrintf(
|
||||
kLicenseResponseFormat, kLicenseStatusUnknownError, "");
|
||||
std::string mock_response = base::StringPrintf(
|
||||
kHttpResponseFormat, Base64Encode(mock_license_status).c_str());
|
||||
|
||||
EXPECT_CALL(*mock_key_fetcher_, FetchKeys(_, _, _))
|
||||
.WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK)));
|
||||
|
||||
CreateWidevineKeySource();
|
||||
ASSERT_EQ(error::SERVER_ERROR,
|
||||
widevine_key_source_->FetchKeys(content_id_, kPolicy).error_code());
|
||||
}
|
||||
|
||||
class WidevineKeySourceParameterizedTest
|
||||
: public WidevineKeySourceTest,
|
||||
public WithParamInterface<std::tr1::tuple<bool, FourCC>> {
|
||||
public:
|
||||
WidevineKeySourceParameterizedTest() {
|
||||
add_common_pssh_ = std::tr1::get<0>(GetParam());
|
||||
protection_scheme_ = std::tr1::get<1>(GetParam());
|
||||
}
|
||||
};
|
||||
|
||||
// Check whether expected request message and post data was generated and
|
||||
// verify the correct behavior on http failure.
|
||||
TEST_P(WidevineKeySourceTest, HttpFetchFailure) {
|
||||
TEST_P(WidevineKeySourceParameterizedTest, HttpFetchFailure) {
|
||||
std::string expected_message = base::StringPrintf(
|
||||
kExpectedRequestMessageFormat, Base64Encode(kContentId).c_str(), kPolicy);
|
||||
kExpectedRequestMessageFormat, Base64Encode(kContentId).c_str(), kPolicy,
|
||||
GetExpectedProtectionScheme());
|
||||
EXPECT_CALL(*mock_request_signer_,
|
||||
GenerateSignature(StrEq(expected_message), _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(kMockSignature), Return(true)));
|
||||
|
@ -277,7 +352,7 @@ TEST_P(WidevineKeySourceTest, HttpFetchFailure) {
|
|||
widevine_key_source_->FetchKeys(content_id_, kPolicy));
|
||||
}
|
||||
|
||||
TEST_P(WidevineKeySourceTest, LicenseStatusCencOK) {
|
||||
TEST_P(WidevineKeySourceParameterizedTest, LicenseStatusCencOK) {
|
||||
std::string mock_response = base::StringPrintf(
|
||||
kHttpResponseFormat, Base64Encode(GenerateMockLicenseResponse()).c_str());
|
||||
|
||||
|
@ -289,7 +364,7 @@ TEST_P(WidevineKeySourceTest, LicenseStatusCencOK) {
|
|||
VerifyKeys(false);
|
||||
}
|
||||
|
||||
TEST_P(WidevineKeySourceTest, LicenseStatusCencNotOK) {
|
||||
TEST_P(WidevineKeySourceParameterizedTest, LicenseStatusCencNotOK) {
|
||||
std::string mock_response = base::StringPrintf(
|
||||
kHttpResponseFormat, Base64Encode(
|
||||
GenerateMockClassicLicenseResponse()).c_str());
|
||||
|
@ -303,7 +378,7 @@ TEST_P(WidevineKeySourceTest, LicenseStatusCencNotOK) {
|
|||
.error_code());
|
||||
}
|
||||
|
||||
TEST_P(WidevineKeySourceTest, LicenseStatusCencWithPsshBoxOK) {
|
||||
TEST_P(WidevineKeySourceParameterizedTest, LicenseStatusCencWithPsshBoxOK) {
|
||||
std::string expected_message =
|
||||
base::StringPrintf(kExpectedRequestMessageWithPsshFormat,
|
||||
Base64Encode(kRequestPsshData).c_str());
|
||||
|
@ -324,7 +399,7 @@ TEST_P(WidevineKeySourceTest, LicenseStatusCencWithPsshBoxOK) {
|
|||
VerifyKeys(false);
|
||||
}
|
||||
|
||||
TEST_P(WidevineKeySourceTest, LicenseStatusCencWithKeyIdOK) {
|
||||
TEST_P(WidevineKeySourceParameterizedTest, LicenseStatusCencWithKeyIdsOK) {
|
||||
std::string expected_pssh_data(
|
||||
kRequestPsshDataFromKeyIds,
|
||||
kRequestPsshDataFromKeyIds + arraysize(kRequestPsshDataFromKeyIds));
|
||||
|
@ -348,7 +423,7 @@ TEST_P(WidevineKeySourceTest, LicenseStatusCencWithKeyIdOK) {
|
|||
VerifyKeys(false);
|
||||
}
|
||||
|
||||
TEST_P(WidevineKeySourceTest, LicenseStatusClassicOK) {
|
||||
TEST_P(WidevineKeySourceParameterizedTest, LicenseStatusClassicOK) {
|
||||
std::string expected_message = base::StringPrintf(
|
||||
kExpectedRequestMessageWithAssetIdFormat, kClassicAssetId);
|
||||
EXPECT_CALL(*mock_request_signer_,
|
||||
|
@ -370,59 +445,12 @@ TEST_P(WidevineKeySourceTest, LicenseStatusClassicOK) {
|
|||
VerifyKeys(true);
|
||||
}
|
||||
|
||||
TEST_P(WidevineKeySourceTest, RetryOnHttpTimeout) {
|
||||
std::string mock_response = base::StringPrintf(
|
||||
kHttpResponseFormat, Base64Encode(GenerateMockLicenseResponse()).c_str());
|
||||
|
||||
// Retry is expected on HTTP timeout.
|
||||
EXPECT_CALL(*mock_key_fetcher_, FetchKeys(_, _, _))
|
||||
.WillOnce(Return(Status(error::TIME_OUT, "")))
|
||||
.WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK)));
|
||||
|
||||
CreateWidevineKeySource();
|
||||
ASSERT_OK(widevine_key_source_->FetchKeys(content_id_, kPolicy));
|
||||
VerifyKeys(false);
|
||||
}
|
||||
|
||||
TEST_P(WidevineKeySourceTest, RetryOnTransientError) {
|
||||
std::string mock_license_status = base::StringPrintf(
|
||||
kLicenseResponseFormat, kLicenseStatusTransientError, "");
|
||||
std::string mock_response = base::StringPrintf(
|
||||
kHttpResponseFormat, Base64Encode(mock_license_status).c_str());
|
||||
|
||||
std::string expected_retried_response = base::StringPrintf(
|
||||
kHttpResponseFormat, Base64Encode(GenerateMockLicenseResponse()).c_str());
|
||||
|
||||
// Retry is expected on transient error.
|
||||
EXPECT_CALL(*mock_key_fetcher_, FetchKeys(_, _, _))
|
||||
.WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK)))
|
||||
.WillOnce(DoAll(SetArgPointee<2>(expected_retried_response),
|
||||
Return(Status::OK)));
|
||||
|
||||
CreateWidevineKeySource();
|
||||
ASSERT_OK(widevine_key_source_->FetchKeys(content_id_, kPolicy));
|
||||
VerifyKeys(false);
|
||||
}
|
||||
|
||||
TEST_P(WidevineKeySourceTest, NoRetryOnUnknownError) {
|
||||
std::string mock_license_status = base::StringPrintf(
|
||||
kLicenseResponseFormat, kLicenseStatusUnknownError, "");
|
||||
std::string mock_response = base::StringPrintf(
|
||||
kHttpResponseFormat, Base64Encode(mock_license_status).c_str());
|
||||
|
||||
EXPECT_CALL(*mock_key_fetcher_, FetchKeys(_, _, _))
|
||||
.WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK)));
|
||||
|
||||
CreateWidevineKeySource();
|
||||
ASSERT_EQ(error::SERVER_ERROR,
|
||||
widevine_key_source_->FetchKeys(content_id_, kPolicy).error_code());
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
const char kCryptoPeriodRequestMessageFormat[] =
|
||||
"{\"content_id\":\"%s\",\"crypto_period_count\":%u,\"drm_types\":["
|
||||
"\"WIDEVINE\"],\"first_crypto_period_index\":%u,\"policy\":\"%s\","
|
||||
"\"protection_scheme\":%d,"
|
||||
"\"tracks\":[{\"type\":\"SD\"},{\"type\":\"HD\"},{\"type\":\"UHD1\"},"
|
||||
"{\"type\":\"UHD2\"},{\"type\":\"AUDIO\"}]}";
|
||||
|
||||
|
@ -459,7 +487,7 @@ std::string GenerateMockKeyRotationLicenseResponse(
|
|||
|
||||
} // namespace
|
||||
|
||||
TEST_P(WidevineKeySourceTest, KeyRotationTest) {
|
||||
TEST_P(WidevineKeySourceParameterizedTest, KeyRotationTest) {
|
||||
const uint32_t kFirstCryptoPeriodIndex = 8;
|
||||
const uint32_t kCryptoPeriodCount = 10;
|
||||
// Array of indexes to be checked.
|
||||
|
@ -482,12 +510,10 @@ TEST_P(WidevineKeySourceTest, KeyRotationTest) {
|
|||
for (uint32_t i = 0; i < kCryptoIterations; ++i) {
|
||||
uint32_t first_crypto_period_index =
|
||||
kFirstCryptoPeriodIndex - 1 + i * kCryptoPeriodCount;
|
||||
std::string expected_message =
|
||||
base::StringPrintf(kCryptoPeriodRequestMessageFormat,
|
||||
Base64Encode(kContentId).c_str(),
|
||||
kCryptoPeriodCount,
|
||||
first_crypto_period_index,
|
||||
kPolicy);
|
||||
std::string expected_message = base::StringPrintf(
|
||||
kCryptoPeriodRequestMessageFormat, Base64Encode(kContentId).c_str(),
|
||||
kCryptoPeriodCount, first_crypto_period_index, kPolicy,
|
||||
GetExpectedProtectionScheme());
|
||||
EXPECT_CALL(*mock_request_signer_, GenerateSignature(expected_message, _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(kMockSignature), Return(true)));
|
||||
|
||||
|
@ -526,8 +552,13 @@ TEST_P(WidevineKeySourceTest, KeyRotationTest) {
|
|||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(WidevineKeySourceInstance,
|
||||
WidevineKeySourceTest,
|
||||
::testing::Bool());
|
||||
WidevineKeySourceParameterizedTest,
|
||||
Combine(Bool(),
|
||||
Values(FOURCC_cenc,
|
||||
FOURCC_cbcs,
|
||||
FOURCC_cens,
|
||||
FOURCC_cbc1,
|
||||
kAppleSampleAesProtectionScheme)));
|
||||
|
||||
} // namespace media
|
||||
} // namespace shaka
|
||||
|
|
Loading…
Reference in New Issue