blob: 6d65988a20dd79946ad963f6cc172e44ac2ab85d [file] [log] [blame]
// Copyright 2014 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 "chrome/browser/media/wv_test_license_server_config.h"
#include "base/command_line.h"
#include "base/environment.h"
#include "base/files/file_util.h"
#include "base/path_service.h"
#include "base/rand_util.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
#include "net/log/net_log_source.h"
#include "net/socket/tcp_server_socket.h"
#include "net/test/python_utils.h"
const uint16_t kMinPort = 17000;
const uint16_t kPortRangeSize = 1000;
// Widevine license server configuration files.
const base::FilePath::CharType kKeysFileName[] =
FILE_PATH_LITERAL("keys.dat");
const base::FilePath::CharType kPoliciesFileName[] =
FILE_PATH_LITERAL("policies.dat");
const base::FilePath::CharType kProfilesFileName[] =
FILE_PATH_LITERAL("profiles.dat");
// License server configuration files directory name relative to root.
const base::FilePath::CharType kLicenseServerConfigDirName[] =
FILE_PATH_LITERAL("config");
WVTestLicenseServerConfig::WVTestLicenseServerConfig() {
}
WVTestLicenseServerConfig::~WVTestLicenseServerConfig() {
}
bool WVTestLicenseServerConfig::GetServerCommandLine(
base::CommandLine* command_line) {
if (!GetPythonCommand(command_line)) {
LOG(ERROR) << "Could not get Python runtime command.";
return false;
}
// Add the Python protocol buffers files directory to Python path.
base::FilePath pyproto_dir;
if (!GetPyProtoPath(&pyproto_dir)) {
DVLOG(0) << "Cannot find pyproto directory required by license server.";
return false;
}
AppendToPythonPath(pyproto_dir);
base::FilePath license_server_path;
GetLicenseServerPath(&license_server_path);
if (!base::PathExists(license_server_path)) {
DVLOG(0) << "Missing license server file at "
<< license_server_path.value();
return false;
}
base::FilePath server_root;
GetLicenseServerRootPath(&server_root);
base::FilePath config_path = server_root.Append(kLicenseServerConfigDirName);
if (!base::PathExists(config_path.Append(kKeysFileName)) ||
!base::PathExists(config_path.Append(kPoliciesFileName)) ||
!base::PathExists(config_path.Append(kProfilesFileName))) {
DVLOG(0) << "Missing license server configuration files.";
return false;
}
if (!SelectServerPort())
return false;
// Needed to dynamically load .so libraries used by license server.
// TODO(shadi): Remove need to set env variable once b/12932983 is fixed.
#if defined(OS_LINUX)
std::unique_ptr<base::Environment> env(base::Environment::Create());
const char kLibraryPathEnvVarName[] = "LD_LIBRARY_PATH";
std::string library_paths(license_server_path.DirName().value());
std::string old_path;
if (env->GetVar(kLibraryPathEnvVarName, &old_path))
library_paths.append(":").append(old_path);
env->SetVar(kLibraryPathEnvVarName, library_paths);
#endif // defined(OS_LINUX)
// Since it is a Python command line, we need to AppendArg instead of
// AppendSwitch so that the arguments are passed to the Python server instead
// of Python engine.
command_line->AppendArgPath(license_server_path);
command_line->AppendArg("-k");
command_line->AppendArgPath(config_path.Append(kKeysFileName));
command_line->AppendArg("-o");
command_line->AppendArgPath(config_path.Append(kPoliciesFileName));
command_line->AppendArg("-r");
command_line->AppendArgPath(config_path.Append(kProfilesFileName));
command_line->AppendArg(base::StringPrintf("--port=%u", port_));
return true;
}
bool WVTestLicenseServerConfig::SelectServerPort() {
// Try all ports within the range of kMinPort to (kMinPort + kPortRangeSize)
// Instead of starting from kMinPort, use a random port within that range.
uint16_t start_seed = base::RandInt(0, kPortRangeSize);
uint16_t try_port = 0;
for (uint16_t i = 0; i < kPortRangeSize; ++i) {
try_port = kMinPort + (start_seed + i) % kPortRangeSize;
net::NetLogSource source;
net::TCPServerSocket sock(NULL, source);
if (sock.Listen(net::IPEndPoint(net::IPAddress::IPv4Localhost(), try_port),
1) == net::OK) {
port_ = try_port;
return true;
}
}
DVLOG(0) << "Could not find an open port in the range of " << kMinPort <<
" to " << kMinPort + kPortRangeSize;
return false;
}
bool WVTestLicenseServerConfig::IsPlatformSupported() {
#if defined(OS_LINUX) && defined(ARCH_CPU_X86_64)
return true;
#else
return false;
#endif // defined(OS_LINUX)
}
std::string WVTestLicenseServerConfig::GetServerURL() {
return base::StringPrintf("http://localhost:%u/license_server", port_);
}
void WVTestLicenseServerConfig::GetLicenseServerPath(base::FilePath *path) {
base::FilePath server_root;
GetLicenseServerRootPath(&server_root);
// Platform-specific license server binary path relative to root.
*path =
#if defined(OS_LINUX)
server_root.Append(FILE_PATH_LITERAL("linux"))
.Append(FILE_PATH_LITERAL("license_server.py"));
#else
server_root.Append(FILE_PATH_LITERAL("unsupported_platform"));
#endif // defined(OS_LINUX)
}
void WVTestLicenseServerConfig::GetLicenseServerRootPath(
base::FilePath* path) {
base::FilePath source_root;
PathService::Get(base::DIR_SOURCE_ROOT, &source_root);
*path = source_root.Append(FILE_PATH_LITERAL("third_party"))
.Append(FILE_PATH_LITERAL("widevine"))
.Append(FILE_PATH_LITERAL("test"))
.Append(FILE_PATH_LITERAL("license_server"));
}