Widevine encryptor source unittest
Change-Id: I1b56d0a019480472eb462d8a39f81c4eb3c81a0e
This commit is contained in:
parent
f73f4bb773
commit
d90ca489f9
|
@ -4,7 +4,7 @@
|
|||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#include "media/base/httpfetcher.h"
|
||||
#include "media/base/http_fetcher.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
|
@ -16,7 +16,7 @@
|
|||
|
||||
namespace {
|
||||
|
||||
struct HTTPResult {
|
||||
struct HttpResult {
|
||||
int status_code;
|
||||
std::string status_message;
|
||||
std::string response;
|
||||
|
@ -74,7 +74,7 @@ void OnBegin(const happyhttp::Response* response, void* userdata) {
|
|||
DLOG(INFO) << "BEGIN (" << response->getstatus() << ", "
|
||||
<< response->getreason() << ").";
|
||||
|
||||
HTTPResult* result = static_cast<HTTPResult*>(userdata);
|
||||
HttpResult* result = static_cast<HttpResult*>(userdata);
|
||||
result->status_code = response->getstatus();
|
||||
result->status_message = response->getreason();
|
||||
result->response.clear();
|
||||
|
@ -85,13 +85,13 @@ void OnData(const happyhttp::Response* response,
|
|||
const unsigned char* data,
|
||||
int num_bytes) {
|
||||
DCHECK(response && userdata && data);
|
||||
HTTPResult* result = static_cast<HTTPResult*>(userdata);
|
||||
HttpResult* result = static_cast<HttpResult*>(userdata);
|
||||
result->response.append(reinterpret_cast<const char*>(data), num_bytes);
|
||||
}
|
||||
|
||||
void OnComplete(const happyhttp::Response* response, void* userdata) {
|
||||
DCHECK(response && userdata);
|
||||
HTTPResult* result = static_cast<HTTPResult*>(userdata);
|
||||
HttpResult* result = static_cast<HttpResult*>(userdata);
|
||||
DLOG(INFO) << "COMPLETE (" << result->response.size() << " bytes).";
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,10 @@ const int kHttpOK = 200;
|
|||
|
||||
namespace media {
|
||||
|
||||
HTTPFetcher::HTTPFetcher() {
|
||||
HttpFetcher::HttpFetcher() {}
|
||||
HttpFetcher::~HttpFetcher() {}
|
||||
|
||||
SimpleHttpFetcher::SimpleHttpFetcher() {
|
||||
#ifdef WIN32
|
||||
WSAData wsa_data;
|
||||
int code = WSAStartup(MAKEWORD(1, 1), &wsa_data);
|
||||
|
@ -111,26 +114,27 @@ HTTPFetcher::HTTPFetcher() {
|
|||
#endif // WIN32
|
||||
}
|
||||
|
||||
HTTPFetcher::~HTTPFetcher() {
|
||||
SimpleHttpFetcher::~SimpleHttpFetcher() {
|
||||
#ifdef WIN32
|
||||
if (wsa_startup_succeeded_)
|
||||
WSACleanup();
|
||||
#endif // WIN32
|
||||
}
|
||||
|
||||
Status HTTPFetcher::Get(const std::string& path, std::string* response) {
|
||||
Status SimpleHttpFetcher::Get(const std::string& path, std::string* response) {
|
||||
return FetchInternal("GET", path, "", response);
|
||||
}
|
||||
|
||||
Status HTTPFetcher::Post(const std::string& path, const std::string& data,
|
||||
std::string* response) {
|
||||
Status SimpleHttpFetcher::Post(const std::string& path,
|
||||
const std::string& data,
|
||||
std::string* response) {
|
||||
return FetchInternal("POST", path, data, response);
|
||||
}
|
||||
|
||||
Status HTTPFetcher::FetchInternal(const std::string& method,
|
||||
const std::string& url,
|
||||
const std::string& data,
|
||||
std::string* response) {
|
||||
Status SimpleHttpFetcher::FetchInternal(const std::string& method,
|
||||
const std::string& url,
|
||||
const std::string& data,
|
||||
std::string* response) {
|
||||
DCHECK(response);
|
||||
|
||||
int status_code = 0;
|
||||
|
@ -145,7 +149,7 @@ Status HTTPFetcher::FetchInternal(const std::string& method,
|
|||
}
|
||||
|
||||
try {
|
||||
HTTPResult result;
|
||||
HttpResult result;
|
||||
happyhttp::Connection connection(host.data(), port);
|
||||
connection.setcallbacks(OnBegin, OnData, OnComplete, &result);
|
||||
|
|
@ -4,32 +4,49 @@
|
|||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#ifndef MEDIA_BASE_HTTPFETCHER_H_
|
||||
#define MEDIA_BASE_HTTPFETCHER_H_
|
||||
#ifndef MEDIA_BASE_HTTP_FETCHER_H_
|
||||
#define MEDIA_BASE_HTTP_FETCHER_H_
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "media/base/status.h"
|
||||
|
||||
namespace media {
|
||||
|
||||
// A simple HTTP fetcher implementation using happyhttp.
|
||||
class HTTPFetcher {
|
||||
class HttpFetcher {
|
||||
public:
|
||||
// TODO(kqyang): Add timeout support.
|
||||
HTTPFetcher();
|
||||
~HTTPFetcher();
|
||||
HttpFetcher();
|
||||
virtual ~HttpFetcher();
|
||||
|
||||
// Fetch |response| from |url| using HTTP GET.
|
||||
// |response| should not be NULL, will contain the body of the http response
|
||||
// on success.
|
||||
// Return OK on success.
|
||||
Status Get(const std::string& url, std::string* response);
|
||||
virtual Status Get(const std::string& url, std::string* response) = 0;
|
||||
|
||||
// Fetch |response| from |url| using HTTP POST.
|
||||
// |response| should not be NULL, will contain the body of the http response
|
||||
// on success.
|
||||
// Return OK on success.
|
||||
Status Post(const std::string& url, const std::string& data,
|
||||
std::string* response);
|
||||
virtual Status Post(const std::string& url,
|
||||
const std::string& data,
|
||||
std::string* response) = 0;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(HttpFetcher);
|
||||
};
|
||||
|
||||
// A simple HttpFetcher implementation using happyhttp.
|
||||
class SimpleHttpFetcher : public HttpFetcher {
|
||||
public:
|
||||
// TODO(kqyang): Add timeout support.
|
||||
SimpleHttpFetcher();
|
||||
virtual ~SimpleHttpFetcher();
|
||||
|
||||
// HttpFetcher implementation overrides.
|
||||
virtual Status Get(const std::string& url, std::string* response) OVERRIDE;
|
||||
virtual Status Post(const std::string& url,
|
||||
const std::string& data,
|
||||
std::string* response) OVERRIDE;
|
||||
|
||||
private:
|
||||
// Internal implementation of HTTP functions, e.g. Get and Post.
|
||||
|
@ -41,10 +58,10 @@ class HTTPFetcher {
|
|||
bool wsa_startup_succeeded_;
|
||||
#endif
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(HTTPFetcher);
|
||||
DISALLOW_COPY_AND_ASSIGN(SimpleHttpFetcher);
|
||||
};
|
||||
|
||||
} // namespace media
|
||||
|
||||
#endif // MEDIA_BASE_HTTPFETCHER_H_
|
||||
#endif // MEDIA_BASE_HTTP_FETCHER_H_
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#include "media/base/httpfetcher.h"
|
||||
#include "media/base/http_fetcher.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
|
@ -30,7 +30,7 @@ namespace media {
|
|||
|
||||
static void CheckHttpGet(const std::string& url,
|
||||
const std::string& expected_response) {
|
||||
HTTPFetcher fetcher;
|
||||
SimpleHttpFetcher fetcher;
|
||||
std::string response;
|
||||
ASSERT_OK(fetcher.Get(url, &response));
|
||||
base::RemoveChars(response, "\r\n\t ", &response);
|
||||
|
@ -39,7 +39,7 @@ static void CheckHttpGet(const std::string& url,
|
|||
|
||||
static void CheckHttpPost(const std::string& url, const std::string& data,
|
||||
const std::string& expected_response) {
|
||||
HTTPFetcher fetcher;
|
||||
SimpleHttpFetcher fetcher;
|
||||
std::string response;
|
||||
ASSERT_OK(fetcher.Post(url, data, &response));
|
||||
base::RemoveChars(response, "\r\n\t ", &response);
|
||||
|
@ -47,16 +47,16 @@ static void CheckHttpPost(const std::string& url, const std::string& data,
|
|||
}
|
||||
|
||||
|
||||
TEST(HTTPFetcherTest, HttpGet) {
|
||||
TEST(HttpFetcherTest, HttpGet) {
|
||||
CheckHttpGet(kTestUrl, kExpectedGetResponse);
|
||||
}
|
||||
|
||||
TEST(HTTPFetcherTest, HttpPost) {
|
||||
TEST(HttpFetcherTest, HttpPost) {
|
||||
CheckHttpPost(kTestUrl, kPostData, kExpectedPostResponse);
|
||||
}
|
||||
|
||||
TEST(HTTPFetcherTest, InvalidUrl) {
|
||||
HTTPFetcher fetcher;
|
||||
TEST(HttpFetcherTest, InvalidUrl) {
|
||||
SimpleHttpFetcher fetcher;
|
||||
std::string response;
|
||||
const std::string invalid_url(kTestUrl, sizeof(kTestUrl) - 2);
|
||||
Status status = fetcher.Get(invalid_url, &response);
|
||||
|
@ -65,7 +65,7 @@ TEST(HTTPFetcherTest, InvalidUrl) {
|
|||
EndsWith(status.error_message(), base::IntToString(kHttpNotFound), true));
|
||||
}
|
||||
|
||||
TEST(HTTPFetcherTest, UrlWithPort) {
|
||||
TEST(HttpFetcherTest, UrlWithPort) {
|
||||
CheckHttpGet(kTestUrlWithPort, kExpectedGetResponse);
|
||||
}
|
||||
|
|
@ -23,11 +23,11 @@
|
|||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'httpfetcher',
|
||||
'target_name': 'http_fetcher',
|
||||
'type': '<(component)',
|
||||
'sources': [
|
||||
'httpfetcher.cc',
|
||||
'httpfetcher.h',
|
||||
'http_fetcher.cc',
|
||||
'http_fetcher.h',
|
||||
],
|
||||
'cflags!': [ '-fno-exceptions' ],
|
||||
'cflags_cc!': [ '-fno-exceptions' ],
|
||||
|
@ -45,16 +45,16 @@
|
|||
},
|
||||
{
|
||||
# Note that this test performs real http requests to a http server.
|
||||
'target_name': 'httpfetcher_unittest',
|
||||
'target_name': 'http_fetcher_unittest',
|
||||
'type': '<(gtest_target_type)',
|
||||
'sources': [
|
||||
'httpfetcher_unittest.cc',
|
||||
'http_fetcher_unittest.cc',
|
||||
],
|
||||
'dependencies': [
|
||||
'../../base/base.gyp:base',
|
||||
'../../testing/gtest.gyp:gtest',
|
||||
'../../testing/gtest.gyp:gtest_main',
|
||||
'httpfetcher',
|
||||
'http_fetcher',
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -110,7 +110,7 @@
|
|||
'dependencies': [
|
||||
'../../base/base.gyp:base',
|
||||
'../../third_party/openssl/openssl.gyp:openssl',
|
||||
'httpfetcher',
|
||||
'http_fetcher',
|
||||
'status',
|
||||
],
|
||||
},
|
||||
|
@ -130,6 +130,7 @@
|
|||
'status_test_util.h',
|
||||
'status_test_util_unittest.cc',
|
||||
'status_unittest.cc',
|
||||
'widevine_encryptor_source_unittest.cc',
|
||||
],
|
||||
'dependencies': [
|
||||
'../../testing/gtest.gyp:gtest',
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include "base/time/time.h"
|
||||
#include "base/threading/platform_thread.h"
|
||||
#include "base/values.h"
|
||||
#include "media/base/httpfetcher.h"
|
||||
#include "media/base/http_fetcher.h"
|
||||
#include "media/base/request_signer.h"
|
||||
|
||||
// TODO(kqyang): Move media/mp4/rcheck.h to media/base/.
|
||||
|
@ -102,7 +102,8 @@ WidevineEncryptorSource::WidevineEncryptorSource(
|
|||
const std::string& content_id,
|
||||
TrackType track_type,
|
||||
scoped_ptr<RequestSigner> signer)
|
||||
: server_url_(server_url),
|
||||
: http_fetcher_(new SimpleHttpFetcher()),
|
||||
server_url_(server_url),
|
||||
content_id_(content_id),
|
||||
track_type_(track_type),
|
||||
signer_(signer.Pass()) {
|
||||
|
@ -120,14 +121,13 @@ Status WidevineEncryptorSource::Initialize() {
|
|||
return status;
|
||||
VLOG(1) << "Message: " << message;
|
||||
|
||||
HTTPFetcher fetcher;
|
||||
std::string raw_response;
|
||||
int64 sleep_duration = kFirstRetryDelayMilliseconds;
|
||||
|
||||
// Perform client side retries if seeing server transient error to workaround
|
||||
// server limitation.
|
||||
for (int i = 0; i < kNumTransientErrorRetries; ++i) {
|
||||
status = fetcher.Post(server_url_, message, &raw_response);
|
||||
status = http_fetcher_->Post(server_url_, message, &raw_response);
|
||||
if (!status.ok())
|
||||
return status;
|
||||
VLOG(1) << "Retry [" << i << "] Response:" << raw_response;
|
||||
|
@ -172,6 +172,11 @@ WidevineEncryptorSource::GetTrackTypeFromString(
|
|||
return TRACK_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
void WidevineEncryptorSource::set_http_fetcher(
|
||||
scoped_ptr<HttpFetcher> http_fetcher) {
|
||||
http_fetcher_ = http_fetcher.Pass();
|
||||
}
|
||||
|
||||
void WidevineEncryptorSource::FillRequest(const std::string& content_id,
|
||||
std::string* request) {
|
||||
DCHECK(request);
|
||||
|
@ -256,9 +261,8 @@ bool WidevineEncryptorSource::IsExpectedTrackType(
|
|||
return track_type_ == GetTrackTypeFromString(track_type_string);
|
||||
}
|
||||
|
||||
bool WidevineEncryptorSource::ExtractEncryptionKey(
|
||||
const std::string& response,
|
||||
bool* transient_error) {
|
||||
bool WidevineEncryptorSource::ExtractEncryptionKey(const std::string& response,
|
||||
bool* transient_error) {
|
||||
DCHECK(transient_error);
|
||||
*transient_error = false;
|
||||
|
||||
|
|
|
@ -8,10 +8,12 @@
|
|||
#define MEDIA_BASE_WIDEVINE_ENCRYPTOR_SOURCE_H_
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "media/base/encryptor_source.h"
|
||||
|
||||
namespace media {
|
||||
|
||||
class HttpFetcher;
|
||||
class RequestSigner;
|
||||
|
||||
// Defines an encryptor source which talks to Widevine encryption server.
|
||||
|
@ -37,6 +39,8 @@ class WidevineEncryptorSource : public EncryptorSource {
|
|||
static WidevineEncryptorSource::TrackType GetTrackTypeFromString(
|
||||
const std::string& track_type_string);
|
||||
|
||||
void set_http_fetcher(scoped_ptr<HttpFetcher> http_fetcher);
|
||||
|
||||
private:
|
||||
// Fill |request| with necessary fields for Widevine encryption request.
|
||||
// |request| should not be NULL.
|
||||
|
@ -55,6 +59,10 @@ class WidevineEncryptorSource : public EncryptorSource {
|
|||
bool ExtractEncryptionKey(const std::string& response,
|
||||
bool* transient_error);
|
||||
|
||||
// The fetcher object used to fetch HTTP response from server.
|
||||
// It is initialized to a default fetcher on class initialization.
|
||||
// Can be overridden using set_http_fetcher for testing or other purposes.
|
||||
scoped_ptr<HttpFetcher> http_fetcher_;
|
||||
std::string server_url_;
|
||||
std::string content_id_;
|
||||
TrackType track_type_;
|
||||
|
|
|
@ -0,0 +1,232 @@
|
|||
// Copyright 2014 Google Inc. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#include "media/base/widevine_encryptor_source.h"
|
||||
|
||||
#include "base/base64.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "media/base/http_fetcher.h"
|
||||
#include "media/base/request_signer.h"
|
||||
#include "media/base/status_test_util.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
const char kServerUrl[] = "http://www.foo.com/getcontentkey";
|
||||
const char kContentId[] = "ContentFoo";
|
||||
const char kTrackType[] = "SD";
|
||||
const char kSignerName[] = "SignerFoo";
|
||||
|
||||
const char kMockSignature[] = "MockSignature";
|
||||
|
||||
const char kMockKeyId[] = "MockKeyId";
|
||||
const char kMockKey[] = "MockKey";
|
||||
const char kMockPsshData[] = "MockPsshData";
|
||||
|
||||
// The lisence service may return an error indicating a transient error has
|
||||
// just happened in the server, or other types of errors.
|
||||
// WidevineEncryptorSource will perform a number of retries on transient errors;
|
||||
// WidevineEncryptorSource does not know about other errors and retries are not
|
||||
// performed.
|
||||
const char kLicenseStatusTransientError[] = "INTERNAL_ERROR";
|
||||
const char kLicenseStatusUnknownError[] = "UNKNOWN_ERROR";
|
||||
|
||||
const char kExpectedRequestMessageFormat[] =
|
||||
"{\"content_id\":\"%s\",\"drm_types\":[\"WIDEVINE\"],\"policy\":\"\","
|
||||
"\"tracks\":[{\"type\":\"SD\"},{\"type\":\"HD\"},{\"type\":\"AUDIO\"}]}";
|
||||
const char kExpectedSignedMessageFormat[] =
|
||||
"{\"request\":\"%s\",\"signature\":\"%s\",\"signer\":\"%s\"}";
|
||||
const char kLicenseOkResponseFormat[] =
|
||||
"{\"status\":\"OK\",\"tracks\":[{\"type\":\"%s\",\"key_id\":\"%s\",\"key\":"
|
||||
"\"%s\",\"pssh\":[{\"drm_type\":\"WIDEVINE\",\"data\":\"%s\"}]}]}";
|
||||
const char kLicenseErrorResponseFormat[] =
|
||||
"{\"status\":\"%s\",\"drm\":[],\"tracks\":[]}";
|
||||
const char kHttpResponseFormat[] = "{\"response\":\"%s\"}";
|
||||
|
||||
std::string Base64Encode(const std::string& input) {
|
||||
std::string output;
|
||||
base::Base64Encode(input, &output);
|
||||
return output;
|
||||
}
|
||||
|
||||
std::string ToString(const std::vector<uint8> v) {
|
||||
return std::string(v.begin(), v.end());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::DoAll;
|
||||
using ::testing::Return;
|
||||
using ::testing::SetArgPointee;
|
||||
|
||||
namespace media {
|
||||
|
||||
class MockRequestSigner : public RequestSigner {
|
||||
public:
|
||||
explicit MockRequestSigner(const std::string& signer_name)
|
||||
: RequestSigner(signer_name) {}
|
||||
virtual ~MockRequestSigner() {}
|
||||
|
||||
MOCK_METHOD2(GenerateSignature,
|
||||
bool(const std::string& message, std::string* signature));
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(MockRequestSigner);
|
||||
};
|
||||
|
||||
class MockHttpFetcher : public HttpFetcher {
|
||||
public:
|
||||
MockHttpFetcher() : HttpFetcher() {}
|
||||
virtual ~MockHttpFetcher() {}
|
||||
|
||||
MOCK_METHOD2(Get, Status(const std::string& url, std::string* response));
|
||||
MOCK_METHOD3(Post,
|
||||
Status(const std::string& url,
|
||||
const std::string& data,
|
||||
std::string* response));
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(MockHttpFetcher);
|
||||
};
|
||||
|
||||
class WidevineEncryptorSourceTest : public ::testing::Test {
|
||||
public:
|
||||
WidevineEncryptorSourceTest()
|
||||
: mock_request_signer_(new MockRequestSigner(kSignerName)),
|
||||
mock_http_fetcher_(new MockHttpFetcher()) {}
|
||||
|
||||
protected:
|
||||
void CreateWidevineEncryptorSource() {
|
||||
widevine_encryptor_source_.reset(new WidevineEncryptorSource(
|
||||
kServerUrl,
|
||||
kContentId,
|
||||
WidevineEncryptorSource::GetTrackTypeFromString(kTrackType),
|
||||
mock_request_signer_.PassAs<RequestSigner>()));
|
||||
widevine_encryptor_source_->set_http_fetcher(
|
||||
mock_http_fetcher_.PassAs<HttpFetcher>());
|
||||
}
|
||||
|
||||
scoped_ptr<MockRequestSigner> mock_request_signer_;
|
||||
scoped_ptr<MockHttpFetcher> mock_http_fetcher_;
|
||||
scoped_ptr<WidevineEncryptorSource> widevine_encryptor_source_;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(WidevineEncryptorSourceTest);
|
||||
};
|
||||
|
||||
TEST_F(WidevineEncryptorSourceTest, GetTrackTypeFromString) {
|
||||
EXPECT_EQ(WidevineEncryptorSource::TRACK_TYPE_SD,
|
||||
WidevineEncryptorSource::GetTrackTypeFromString("SD"));
|
||||
EXPECT_EQ(WidevineEncryptorSource::TRACK_TYPE_HD,
|
||||
WidevineEncryptorSource::GetTrackTypeFromString("HD"));
|
||||
EXPECT_EQ(WidevineEncryptorSource::TRACK_TYPE_AUDIO,
|
||||
WidevineEncryptorSource::GetTrackTypeFromString("AUDIO"));
|
||||
EXPECT_EQ(WidevineEncryptorSource::TRACK_TYPE_UNKNOWN,
|
||||
WidevineEncryptorSource::GetTrackTypeFromString("FOO"));
|
||||
}
|
||||
|
||||
TEST_F(WidevineEncryptorSourceTest, GeneratureSignatureFailure) {
|
||||
EXPECT_CALL(*mock_request_signer_, GenerateSignature(_, _))
|
||||
.WillOnce(Return(false));
|
||||
|
||||
CreateWidevineEncryptorSource();
|
||||
ASSERT_EQ(Status(error::INTERNAL_ERROR, "Signature generation failed."),
|
||||
widevine_encryptor_source_->Initialize());
|
||||
}
|
||||
|
||||
// Check whether expected request message and post data was generated and
|
||||
// verify the correct behavior on http failure.
|
||||
TEST_F(WidevineEncryptorSourceTest, HttpPostFailure) {
|
||||
std::string expected_message = base::StringPrintf(
|
||||
kExpectedRequestMessageFormat, Base64Encode(kContentId).c_str());
|
||||
EXPECT_CALL(*mock_request_signer_, GenerateSignature(expected_message, _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(kMockSignature), Return(true)));
|
||||
|
||||
std::string expected_post_data =
|
||||
base::StringPrintf(kExpectedSignedMessageFormat,
|
||||
Base64Encode(expected_message).c_str(),
|
||||
Base64Encode(kMockSignature).c_str(),
|
||||
kSignerName);
|
||||
const Status kMockStatus = Status::UNKNOWN;
|
||||
EXPECT_CALL(*mock_http_fetcher_, Post(kServerUrl, expected_post_data, _))
|
||||
.WillOnce(Return(kMockStatus));
|
||||
|
||||
CreateWidevineEncryptorSource();
|
||||
ASSERT_EQ(kMockStatus, widevine_encryptor_source_->Initialize());
|
||||
}
|
||||
|
||||
TEST_F(WidevineEncryptorSourceTest, LicenseStatusOK) {
|
||||
EXPECT_CALL(*mock_request_signer_, GenerateSignature(_, _))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
std::string mock_license_status =
|
||||
base::StringPrintf(kLicenseOkResponseFormat,
|
||||
kTrackType,
|
||||
Base64Encode(kMockKeyId).c_str(),
|
||||
Base64Encode(kMockKey).c_str(),
|
||||
Base64Encode(kMockPsshData).c_str());
|
||||
std::string expected_response = base::StringPrintf(
|
||||
kHttpResponseFormat, Base64Encode(mock_license_status).c_str());
|
||||
|
||||
EXPECT_CALL(*mock_http_fetcher_, Post(_, _, _))
|
||||
.WillOnce(DoAll(SetArgPointee<2>(expected_response), Return(Status::OK)));
|
||||
|
||||
CreateWidevineEncryptorSource();
|
||||
ASSERT_OK(widevine_encryptor_source_->Initialize());
|
||||
EXPECT_EQ(kMockKeyId, ToString(widevine_encryptor_source_->key_id()));
|
||||
EXPECT_EQ(kMockKey, ToString(widevine_encryptor_source_->key()));
|
||||
EXPECT_EQ(kMockPsshData, ToString(widevine_encryptor_source_->pssh()));
|
||||
}
|
||||
|
||||
TEST_F(WidevineEncryptorSourceTest, RetryOnTransientError) {
|
||||
EXPECT_CALL(*mock_request_signer_, GenerateSignature(_, _))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
std::string mock_license_status = base::StringPrintf(
|
||||
kLicenseErrorResponseFormat, kLicenseStatusTransientError);
|
||||
std::string expected_response = base::StringPrintf(
|
||||
kHttpResponseFormat, Base64Encode(mock_license_status).c_str());
|
||||
|
||||
std::string mock_retried_license_status =
|
||||
base::StringPrintf(kLicenseOkResponseFormat,
|
||||
kTrackType,
|
||||
Base64Encode(kMockKeyId).c_str(),
|
||||
Base64Encode(kMockKey).c_str(),
|
||||
Base64Encode(kMockPsshData).c_str());
|
||||
std::string expected_retried_response = base::StringPrintf(
|
||||
kHttpResponseFormat, Base64Encode(mock_retried_license_status).c_str());
|
||||
|
||||
// Retry is expected on transient error.
|
||||
EXPECT_CALL(*mock_http_fetcher_, Post(_, _, _))
|
||||
.WillOnce(DoAll(SetArgPointee<2>(expected_response), Return(Status::OK)))
|
||||
.WillOnce(DoAll(SetArgPointee<2>(expected_retried_response),
|
||||
Return(Status::OK)));
|
||||
|
||||
CreateWidevineEncryptorSource();
|
||||
ASSERT_OK(widevine_encryptor_source_->Initialize());
|
||||
EXPECT_EQ(kMockKeyId, ToString(widevine_encryptor_source_->key_id()));
|
||||
EXPECT_EQ(kMockKey, ToString(widevine_encryptor_source_->key()));
|
||||
EXPECT_EQ(kMockPsshData, ToString(widevine_encryptor_source_->pssh()));
|
||||
}
|
||||
|
||||
TEST_F(WidevineEncryptorSourceTest, NoRetryOnUnknownError) {
|
||||
EXPECT_CALL(*mock_request_signer_, GenerateSignature(_, _))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
std::string mock_license_status = base::StringPrintf(
|
||||
kLicenseErrorResponseFormat, kLicenseStatusUnknownError);
|
||||
std::string mock_response = base::StringPrintf(
|
||||
kHttpResponseFormat, Base64Encode(mock_license_status).c_str());
|
||||
|
||||
EXPECT_CALL(*mock_http_fetcher_, Post(_, _, _))
|
||||
.WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK)));
|
||||
|
||||
CreateWidevineEncryptorSource();
|
||||
ASSERT_EQ(error::SERVER_ERROR,
|
||||
widevine_encryptor_source_->Initialize().error_code());
|
||||
}
|
||||
|
||||
} // namespace media
|
Loading…
Reference in New Issue