Make RequestSigner optional for WidevineKeySource
Change-Id: I4298d5c5ba1d8539c5cd28130266b1a988308f0b
This commit is contained in:
parent
7e9515c349
commit
e72d12c54f
|
@ -136,13 +136,11 @@ class WidevineKeySource::RefCountedEncryptionKeyMap
|
|||
DISALLOW_COPY_AND_ASSIGN(RefCountedEncryptionKeyMap);
|
||||
};
|
||||
|
||||
WidevineKeySource::WidevineKeySource(
|
||||
const std::string& server_url,
|
||||
scoped_ptr<RequestSigner> signer)
|
||||
: key_production_thread_(
|
||||
"KeyProductionThread",
|
||||
base::Bind(&WidevineKeySource::FetchKeysTask,
|
||||
base::Unretained(this))),
|
||||
WidevineKeySource::WidevineKeySource(const std::string& server_url,
|
||||
scoped_ptr<RequestSigner> signer)
|
||||
: key_production_thread_("KeyProductionThread",
|
||||
base::Bind(&WidevineKeySource::FetchKeysTask,
|
||||
base::Unretained(this))),
|
||||
key_fetcher_(new HttpKeyFetcher(kKeyFetchTimeoutInSeconds)),
|
||||
server_url_(server_url),
|
||||
signer_(signer.Pass()),
|
||||
|
@ -150,7 +148,6 @@ WidevineKeySource::WidevineKeySource(
|
|||
key_production_started_(false),
|
||||
start_key_production_(false, false),
|
||||
first_crypto_period_index_(0) {
|
||||
DCHECK(signer_);
|
||||
}
|
||||
|
||||
WidevineKeySource::~WidevineKeySource() {
|
||||
|
@ -313,7 +310,7 @@ Status WidevineKeySource::FetchKeysInternal(bool enable_key_rotation,
|
|||
&request);
|
||||
|
||||
std::string message;
|
||||
Status status = SignRequest(request, &message);
|
||||
Status status = GenerateKeyMessage(request, &message);
|
||||
if (!status.ok())
|
||||
return status;
|
||||
VLOG(1) << "Message: " << message;
|
||||
|
@ -397,28 +394,30 @@ void WidevineKeySource::FillRequest(bool enable_key_rotation,
|
|||
base::JSONWriter::Write(&request_dict_, request);
|
||||
}
|
||||
|
||||
Status WidevineKeySource::SignRequest(const std::string& request,
|
||||
std::string* signed_request) {
|
||||
DCHECK(signed_request);
|
||||
Status WidevineKeySource::GenerateKeyMessage(const std::string& request,
|
||||
std::string* message) {
|
||||
DCHECK(message);
|
||||
|
||||
// Sign the request.
|
||||
std::string signature;
|
||||
if (!signer_->GenerateSignature(request, &signature))
|
||||
return Status(error::INTERNAL_ERROR, "Signature generation failed.");
|
||||
|
||||
// Encode request and signature using Base64 encoding.
|
||||
std::string request_base64_string;
|
||||
base::Base64Encode(request, &request_base64_string);
|
||||
|
||||
std::string signature_base64_string;
|
||||
base::Base64Encode(signature, &signature_base64_string);
|
||||
base::DictionaryValue request_dict;
|
||||
request_dict.SetString("request", request_base64_string);
|
||||
|
||||
base::DictionaryValue signed_request_dict;
|
||||
signed_request_dict.SetString("request", request_base64_string);
|
||||
signed_request_dict.SetString("signature", signature_base64_string);
|
||||
signed_request_dict.SetString("signer", signer_->signer_name());
|
||||
// Sign the request.
|
||||
if (signer_) {
|
||||
std::string signature;
|
||||
if (!signer_->GenerateSignature(request, &signature))
|
||||
return Status(error::INTERNAL_ERROR, "Signature generation failed.");
|
||||
|
||||
base::JSONWriter::Write(&signed_request_dict, signed_request);
|
||||
std::string signature_base64_string;
|
||||
base::Base64Encode(signature, &signature_base64_string);
|
||||
|
||||
request_dict.SetString("signature", signature_base64_string);
|
||||
request_dict.SetString("signer", signer_->signer_name());
|
||||
}
|
||||
|
||||
base::JSONWriter::Write(&request_dict, message);
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ template <class T> class ProducerConsumerQueue;
|
|||
class WidevineKeySource : public KeySource {
|
||||
public:
|
||||
/// @param server_url is the Widevine common encryption server url.
|
||||
/// @param signer signs the request message. It should not be NULL.
|
||||
/// @param signer signs the request message. Can be NULL.
|
||||
WidevineKeySource(const std::string& server_url,
|
||||
scoped_ptr<RequestSigner> signer);
|
||||
|
||||
|
@ -81,9 +81,9 @@ class WidevineKeySource : public KeySource {
|
|||
void FillRequest(bool enable_key_rotation,
|
||||
uint32_t first_crypto_period_index,
|
||||
std::string* request);
|
||||
// Sign and properly format |request|.
|
||||
// |signed_request| should not be NULL. Return OK on success.
|
||||
Status SignRequest(const std::string& request, std::string* signed_request);
|
||||
// Base64 escape and format the request. Optionally sign the request if a
|
||||
// signer is provided. |message| should not be NULL. Return OK on success.
|
||||
Status GenerateKeyMessage(const std::string& request, std::string* message);
|
||||
// Decode |response| from JSON formatted |raw_response|.
|
||||
// |response| should not be NULL.
|
||||
bool DecodeResponse(const std::string& raw_response, std::string* response);
|
||||
|
|
|
@ -156,10 +156,9 @@ class WidevineKeySourceTest : public ::testing::Test {
|
|||
}
|
||||
|
||||
protected:
|
||||
void CreateWidevineKeySource() {
|
||||
widevine_key_source_.reset(new WidevineKeySource(
|
||||
kServerUrl,
|
||||
mock_request_signer_.PassAs<RequestSigner>()));
|
||||
void CreateWidevineKeySource(scoped_ptr<RequestSigner> request_signer) {
|
||||
widevine_key_source_.reset(
|
||||
new WidevineKeySource(kServerUrl, request_signer.Pass()));
|
||||
widevine_key_source_->set_key_fetcher(
|
||||
mock_key_fetcher_.PassAs<KeyFetcher>());
|
||||
}
|
||||
|
@ -204,7 +203,7 @@ TEST_F(WidevineKeySourceTest, GenerateSignatureFailure) {
|
|||
EXPECT_CALL(*mock_request_signer_, GenerateSignature(_, _))
|
||||
.WillOnce(Return(false));
|
||||
|
||||
CreateWidevineKeySource();
|
||||
CreateWidevineKeySource(mock_request_signer_.PassAs<RequestSigner>());
|
||||
ASSERT_EQ(Status(error::INTERNAL_ERROR, "Signature generation failed."),
|
||||
widevine_key_source_->FetchKeys(content_id_, kPolicy));
|
||||
}
|
||||
|
@ -227,30 +226,24 @@ TEST_F(WidevineKeySourceTest, HttpFetchFailure) {
|
|||
FetchKeys(StrEq(kServerUrl), expected_post_data, _))
|
||||
.WillOnce(Return(kMockStatus));
|
||||
|
||||
CreateWidevineKeySource();
|
||||
CreateWidevineKeySource(mock_request_signer_.PassAs<RequestSigner>());
|
||||
ASSERT_EQ(kMockStatus,
|
||||
widevine_key_source_->FetchKeys(content_id_, kPolicy));
|
||||
}
|
||||
|
||||
TEST_F(WidevineKeySourceTest, LicenseStatusCencOK) {
|
||||
EXPECT_CALL(*mock_request_signer_, GenerateSignature(_, _))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
std::string mock_response = base::StringPrintf(
|
||||
kHttpResponseFormat, Base64Encode(GenerateMockLicenseResponse()).c_str());
|
||||
|
||||
EXPECT_CALL(*mock_key_fetcher_, FetchKeys(_, _, _))
|
||||
.WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK)));
|
||||
|
||||
CreateWidevineKeySource();
|
||||
CreateWidevineKeySource(scoped_ptr<RequestSigner>());
|
||||
ASSERT_OK(widevine_key_source_->FetchKeys(content_id_, kPolicy));
|
||||
VerifyKeys(false);
|
||||
}
|
||||
|
||||
TEST_F(WidevineKeySourceTest, LicenseStatusCencNotOK) {
|
||||
EXPECT_CALL(*mock_request_signer_, GenerateSignature(_, _))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
std::string mock_response = base::StringPrintf(
|
||||
kHttpResponseFormat, Base64Encode(
|
||||
GenerateMockClassicLicenseResponse()).c_str());
|
||||
|
@ -258,23 +251,20 @@ TEST_F(WidevineKeySourceTest, LicenseStatusCencNotOK) {
|
|||
EXPECT_CALL(*mock_key_fetcher_, FetchKeys(_, _, _))
|
||||
.WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK)));
|
||||
|
||||
CreateWidevineKeySource();
|
||||
CreateWidevineKeySource(scoped_ptr<RequestSigner>());
|
||||
ASSERT_EQ(error::SERVER_ERROR,
|
||||
widevine_key_source_->FetchKeys(content_id_, kPolicy)
|
||||
.error_code());
|
||||
}
|
||||
|
||||
TEST_F(WidevineKeySourceTest, LicenseStatusCencWithPsshDataOK) {
|
||||
EXPECT_CALL(*mock_request_signer_, GenerateSignature(_, _))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
std::string mock_response = base::StringPrintf(
|
||||
kHttpResponseFormat, Base64Encode(GenerateMockLicenseResponse()).c_str());
|
||||
|
||||
EXPECT_CALL(*mock_key_fetcher_, FetchKeys(_, _, _))
|
||||
.WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK)));
|
||||
|
||||
CreateWidevineKeySource();
|
||||
CreateWidevineKeySource(scoped_ptr<RequestSigner>());
|
||||
std::vector<uint8_t> pssh_data(
|
||||
reinterpret_cast<const uint8_t*>(kRequestPsshData),
|
||||
reinterpret_cast<const uint8_t*>(kRequestPsshData) + strlen(kContentId));
|
||||
|
@ -283,9 +273,6 @@ TEST_F(WidevineKeySourceTest, LicenseStatusCencWithPsshDataOK) {
|
|||
}
|
||||
|
||||
TEST_F(WidevineKeySourceTest, LicenseStatusClassicOK) {
|
||||
EXPECT_CALL(*mock_request_signer_, GenerateSignature(_, _))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
std::string mock_response = base::StringPrintf(
|
||||
kHttpResponseFormat, Base64Encode(
|
||||
GenerateMockClassicLicenseResponse()).c_str());
|
||||
|
@ -293,15 +280,12 @@ TEST_F(WidevineKeySourceTest, LicenseStatusClassicOK) {
|
|||
EXPECT_CALL(*mock_key_fetcher_, FetchKeys(_, _, _))
|
||||
.WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK)));
|
||||
|
||||
CreateWidevineKeySource();
|
||||
CreateWidevineKeySource(scoped_ptr<RequestSigner>());
|
||||
ASSERT_OK(widevine_key_source_->FetchKeys(kClassicAssetId));
|
||||
VerifyKeys(true);
|
||||
}
|
||||
|
||||
TEST_F(WidevineKeySourceTest, RetryOnHttpTimeout) {
|
||||
EXPECT_CALL(*mock_request_signer_, GenerateSignature(_, _))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
std::string mock_response = base::StringPrintf(
|
||||
kHttpResponseFormat, Base64Encode(GenerateMockLicenseResponse()).c_str());
|
||||
|
||||
|
@ -310,15 +294,12 @@ TEST_F(WidevineKeySourceTest, RetryOnHttpTimeout) {
|
|||
.WillOnce(Return(Status(error::TIME_OUT, "")))
|
||||
.WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK)));
|
||||
|
||||
CreateWidevineKeySource();
|
||||
CreateWidevineKeySource(scoped_ptr<RequestSigner>());
|
||||
ASSERT_OK(widevine_key_source_->FetchKeys(content_id_, kPolicy));
|
||||
VerifyKeys(false);
|
||||
}
|
||||
|
||||
TEST_F(WidevineKeySourceTest, RetryOnTransientError) {
|
||||
EXPECT_CALL(*mock_request_signer_, GenerateSignature(_, _))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
std::string mock_license_status = base::StringPrintf(
|
||||
kLicenseResponseFormat, kLicenseStatusTransientError, "");
|
||||
std::string mock_response = base::StringPrintf(
|
||||
|
@ -333,15 +314,12 @@ TEST_F(WidevineKeySourceTest, RetryOnTransientError) {
|
|||
.WillOnce(DoAll(SetArgPointee<2>(expected_retried_response),
|
||||
Return(Status::OK)));
|
||||
|
||||
CreateWidevineKeySource();
|
||||
CreateWidevineKeySource(scoped_ptr<RequestSigner>());
|
||||
ASSERT_OK(widevine_key_source_->FetchKeys(content_id_, kPolicy));
|
||||
VerifyKeys(false);
|
||||
}
|
||||
|
||||
TEST_F(WidevineKeySourceTest, NoRetryOnUnknownError) {
|
||||
EXPECT_CALL(*mock_request_signer_, GenerateSignature(_, _))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
std::string mock_license_status = base::StringPrintf(
|
||||
kLicenseResponseFormat, kLicenseStatusUnknownError, "");
|
||||
std::string mock_response = base::StringPrintf(
|
||||
|
@ -350,7 +328,7 @@ TEST_F(WidevineKeySourceTest, NoRetryOnUnknownError) {
|
|||
EXPECT_CALL(*mock_key_fetcher_, FetchKeys(_, _, _))
|
||||
.WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK)));
|
||||
|
||||
CreateWidevineKeySource();
|
||||
CreateWidevineKeySource(scoped_ptr<RequestSigner>());
|
||||
ASSERT_EQ(error::SERVER_ERROR,
|
||||
widevine_key_source_->FetchKeys(content_id_, kPolicy).error_code());
|
||||
}
|
||||
|
@ -435,7 +413,7 @@ TEST_F(WidevineKeySourceTest, KeyRotationTest) {
|
|||
.WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK)));
|
||||
}
|
||||
|
||||
CreateWidevineKeySource();
|
||||
CreateWidevineKeySource(mock_request_signer_.PassAs<RequestSigner>());
|
||||
ASSERT_OK(widevine_key_source_->FetchKeys(content_id_, kPolicy));
|
||||
|
||||
EncryptionKey encryption_key;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "packager/media/base/stream_info.h"
|
||||
#include "packager/media/base/timestamp.h"
|
||||
#include "packager/media/base/video_stream_info.h"
|
||||
#include "packager/media/base/widevine_key_source.h"
|
||||
#include "packager/media/base/key_source.h"
|
||||
#include "packager/media/formats/wvm/wvm_media_parser.h"
|
||||
#include "packager/media/test/test_data_util.h"
|
||||
|
||||
|
@ -28,47 +28,21 @@ const char kWvmFile[] = "hb2_4stream_encrypted.wvm";
|
|||
const uint32_t kExpectedStreams = 4;
|
||||
const int kExpectedVideoFrameCount = 6665;
|
||||
const int kExpectedAudioFrameCount = 11964;
|
||||
const char kServerUrl[] = "fake_server_url";
|
||||
const char kSigner[] = "fake_signer";
|
||||
const uint8 kExpectedAssetKey[16] = {'\006', static_cast<uint8>('\201'), '\177',
|
||||
'H', 'k', static_cast<uint8>('\362'), '\177', '>', static_cast<uint8>('\307'),
|
||||
'9', static_cast<uint8>('\250'), '?', '\022', '\n',
|
||||
static_cast<uint8>('\322'), static_cast<uint8>('\374')};
|
||||
} // namespace
|
||||
const uint8_t kExpectedAssetKey[] =
|
||||
"\x06\x81\x7f\x48\x6b\xf2\x7f\x3e\xc7\x39\xa8\x3f\x12\x0a\xd2\xfc";
|
||||
} // namespace
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::DoAll;
|
||||
using ::testing::InSequence;
|
||||
using ::testing::Return;
|
||||
using ::testing::SetArgPointee;
|
||||
|
||||
namespace edash_packager {
|
||||
namespace media {
|
||||
|
||||
class FakeRequestSigner : public RequestSigner {
|
||||
class MockKeySource : public KeySource {
|
||||
public:
|
||||
FakeRequestSigner() : RequestSigner(kSigner) {}
|
||||
virtual ~FakeRequestSigner() {}
|
||||
|
||||
virtual bool GenerateSignature(const std::string& message,
|
||||
std::string* signature) OVERRIDE {
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(FakeRequestSigner);
|
||||
};
|
||||
|
||||
scoped_ptr<FakeRequestSigner> kFakeRequestSigner(new FakeRequestSigner());
|
||||
|
||||
class MockKeySource : public WidevineKeySource {
|
||||
public:
|
||||
MockKeySource() : WidevineKeySource(
|
||||
kServerUrl, kFakeRequestSigner.PassAs<RequestSigner>()) {
|
||||
// KeyProduction thread started in test because FetchKeys()
|
||||
// is mocked. ~ClosureThread expects to terminate this thread.
|
||||
key_production_thread_.Start();
|
||||
}
|
||||
MockKeySource() {}
|
||||
virtual ~MockKeySource() {}
|
||||
|
||||
MOCK_METHOD1(FetchKeys, Status(uint32_t asset_id));
|
||||
|
@ -169,7 +143,7 @@ class WvmMediaParserTest : public testing::Test {
|
|||
|
||||
TEST_F(WvmMediaParserTest, ParseWvm) {
|
||||
EXPECT_CALL(*key_source_, FetchKeys(_)).WillOnce(Return(Status::OK));
|
||||
EXPECT_CALL(*key_source_, GetKey(_,_))
|
||||
EXPECT_CALL(*key_source_, GetKey(_, _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(encryption_key_), Return(Status::OK)));
|
||||
Parse(kWvmFile);
|
||||
EXPECT_EQ(kExpectedStreams, stream_map_.size());
|
||||
|
|
Loading…
Reference in New Issue