Builds libwvmdrmengine.so, which is loaded by the new MediaDrm APIs to support playback of Widevine/CENC protected content. Change-Id: I6f57dd37083dfd96c402cb9dd137c7d74edc8f1c
202 lines
6.9 KiB
C++
202 lines
6.9 KiB
C++
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include <string>
|
|
|
|
#include "base/at_exit.h"
|
|
#include "net/url_request/url_request.h"
|
|
#include "net/url_request/url_request_test_util.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
#include "string_conversions.h"
|
|
#include "wv_content_decryption_module.h"
|
|
|
|
namespace {
|
|
|
|
// Default license server to play server, can be configured using --server command line option
|
|
std::string gGpLicenseServer =
|
|
"https://jmt17.google.com/video-dev/license/GetCencLicense";
|
|
std::string gYtLicenseServer =
|
|
"https://www.youtube.com/api/drm/widevine?video_id=03681262dc412c06&source=YOUTUBE";
|
|
|
|
std::string gLicenseServer(gYtLicenseServer);
|
|
|
|
// Default key id (pssh), can be configured using --keyid command line option
|
|
std::string gKeyID = "000000347073736800000000" // blob size and pssh
|
|
"EDEF8BA979D64ACEA3C827DCD51D21ED00000014" // Widevine system id
|
|
"08011210e02562e04cd55351b14b3d748d36ed8e"; // pssh data
|
|
|
|
// An invalid key id, expected to fail
|
|
std::string kWrongKeyID = "000000347073736800000000" // blob size and psshb
|
|
"EDEF8BA979D64ACEA3C827DCD51D21ED00000014" // Widevine system id
|
|
"0901121094889920E8D6520098577DF8F2DD5546"; // pssh data
|
|
|
|
static const char kWidevineKeySystem[] = "com.widevine.alpha";
|
|
|
|
} // namespace
|
|
|
|
namespace wvcdm_test {
|
|
|
|
class WvCdmDecryptorTest : public testing::Test {
|
|
public:
|
|
WvCdmDecryptorTest() {}
|
|
~WvCdmDecryptorTest() {}
|
|
|
|
protected:
|
|
void GenerateKeyRequest(const std::string& key_system,
|
|
const std::string& init_data) {
|
|
EXPECT_EQ(decryptor_.GenerateKeyRequest(key_system,
|
|
init_data,
|
|
&key_msg_,
|
|
&session_id_), wvcdm::KEY_MESSAGE);
|
|
}
|
|
|
|
void GenerateRenewalRequest(const std::string& key_system,
|
|
const std::string& init_data) {
|
|
EXPECT_EQ(decryptor_.GenerateRenewalRequest(key_system,
|
|
init_data,
|
|
session_id_, &key_msg_),
|
|
wvcdm::KEY_MESSAGE);
|
|
}
|
|
|
|
std::string GetKeyRequestResponse(const std::string& server_url,
|
|
int expected_response) {
|
|
net::TestDelegate d;
|
|
net::TestNetworkDelegate network_delegate;
|
|
net::TestURLRequestContext context(true);
|
|
context.set_network_delegate(&network_delegate);
|
|
scoped_ptr<net::HostResolver> resolver(
|
|
net::HostResolver::CreateDefaultResolver(NULL));
|
|
context.set_host_resolver(resolver.get());
|
|
context.Init();
|
|
net::URLRequest r(GURL(server_url), &d, &context);
|
|
r.EnableChunkedUpload();
|
|
r.set_method("POST");
|
|
r.AppendChunkToUpload(key_msg_.data(), key_msg_.size(), true);
|
|
r.Start();
|
|
EXPECT_TRUE(r.is_pending());
|
|
|
|
MessageLoop::current()->Run();
|
|
|
|
std::string data = d.data_received();
|
|
// Youtube server returns 400 for invalid message while play server returns
|
|
// 500, so just test inequity here for invalid message
|
|
if (expected_response == 200) {
|
|
EXPECT_EQ(200, r.GetResponseCode()) << data;
|
|
} else {
|
|
EXPECT_NE(200, r.GetResponseCode()) << data;
|
|
}
|
|
EXPECT_EQ(net::URLRequestStatus::SUCCESS, r.status().status());
|
|
EXPECT_TRUE(d.bytes_received() > 0);
|
|
// Extract DRM message:
|
|
// https://docs.google.com/a/google.com/document/d/1Xue3bgwv2qIAnuFIZ-HCcix43dvH2UxsOEA_8FCBO3I/edit#
|
|
if (r.status().status() == net::URLRequestStatus::SUCCESS) {
|
|
size_t pos = data.find("\r\n");
|
|
if (pos != data.npos) data = data.substr(pos+2);
|
|
}
|
|
return data;
|
|
}
|
|
|
|
void VerifyKeyRequestResponse(const std::string& server_url,
|
|
std::string& init_data,
|
|
bool is_renewal) {
|
|
std::string resp = GetKeyRequestResponse(server_url, 200);
|
|
|
|
std::cout << "Message: " << wvcdm::b2a_hex(key_msg_) << std::endl;
|
|
std::cout << "Response: " << wvcdm::b2a_hex(resp) << std::endl;
|
|
|
|
if (is_renewal) {
|
|
EXPECT_EQ(decryptor_.RenewKey(kWidevineKeySystem,
|
|
init_data, resp,
|
|
session_id_), wvcdm::KEY_ADDED);
|
|
}
|
|
else {
|
|
EXPECT_EQ(decryptor_.AddKey(kWidevineKeySystem,
|
|
init_data, resp,
|
|
session_id_), wvcdm::KEY_ADDED);
|
|
}
|
|
|
|
std::cout << "back from AddKey" << std::endl;
|
|
|
|
}
|
|
|
|
wvcdm::WvContentDecryptionModule decryptor_;
|
|
|
|
std::string key_msg_;
|
|
std::string session_id_;
|
|
};
|
|
|
|
TEST_F(WvCdmDecryptorTest, BaseMessageTest)
|
|
{
|
|
GenerateKeyRequest(kWidevineKeySystem, gKeyID);
|
|
|
|
GetKeyRequestResponse(gLicenseServer, 200);
|
|
}
|
|
|
|
TEST_F(WvCdmDecryptorTest, WrongMessageTest)
|
|
{
|
|
std::string wrong_message = wvcdm::a2b_hex(kWrongKeyID);
|
|
|
|
GenerateKeyRequest(kWidevineKeySystem, wrong_message);
|
|
|
|
GetKeyRequestResponse(gLicenseServer, 500);
|
|
}
|
|
|
|
TEST_F(WvCdmDecryptorTest, NormalWebMDecryption) {
|
|
GenerateKeyRequest(kWidevineKeySystem, gKeyID);
|
|
|
|
VerifyKeyRequestResponse(gLicenseServer, gKeyID, false);
|
|
}
|
|
|
|
TEST_F(WvCdmDecryptorTest, LicenseRenewal) {
|
|
GenerateKeyRequest(kWidevineKeySystem, gKeyID);
|
|
|
|
VerifyKeyRequestResponse(gLicenseServer, gKeyID, false);
|
|
|
|
GenerateRenewalRequest(kWidevineKeySystem, gKeyID);
|
|
|
|
VerifyKeyRequestResponse(gLicenseServer, gKeyID, true);
|
|
}
|
|
|
|
} // namespace wvcdm_test
|
|
|
|
int main(int argc, char **argv) {
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
|
|
std::string temp;
|
|
std::string license_server(gLicenseServer);
|
|
std::string key_id(gKeyID);
|
|
for (int i=1; i<argc; i++) {
|
|
temp.assign(argv[i]);
|
|
if (temp.find("--server=") == 0) {
|
|
gLicenseServer.assign(temp.substr(strlen("--server=")));
|
|
}
|
|
else if (temp.find("--keyid=") == 0) {
|
|
gKeyID.assign(temp.substr(strlen("--keyid=")));
|
|
}
|
|
else {
|
|
std::cout << "error: unknown option '" << argv[i] << "'" << std::endl;
|
|
std::cout << "usage: wvcdm_test [options]" << std::endl << std::endl;
|
|
std::cout << std::setw(30) << std::left << " --server=<server_url>";
|
|
std::cout << "configure the license server url, please include http[s] in the url" << std::endl;
|
|
std::cout << std::setw(30) << std::left << " ";
|
|
std::cout << "default: " << license_server << std::endl;
|
|
std::cout << std::setw(30) << std::left << " --keyid=<key_id>";
|
|
std::cout << "configure the key id or pssh, in hex format" << std::endl;
|
|
std::cout << std::setw(30) << std::left << " ";
|
|
std::cout << "default: " << key_id << std::endl << std::endl;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
std::cout << std::endl;
|
|
std::cout << "Server: " << gLicenseServer << std::endl;
|
|
std::cout << "KeyID: " << gKeyID << std::endl << std::endl;
|
|
|
|
gKeyID = wvcdm::a2b_hex(gKeyID);
|
|
|
|
base::AtExitManager exit;
|
|
MessageLoop ttr(MessageLoop::TYPE_IO);
|
|
return RUN_ALL_TESTS();
|
|
}
|