// 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 "net/base/net_errors.h" #include "net/socket/tcp_server_socket.h" #include "net/test/python_utils.h" const uint16 kMinPort = 17000; const uint16 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( 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)) { VLOG(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)) { VLOG(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))) { VLOG(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) scoped_ptr 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. net::IPAddressNumber address; net::ParseIPLiteralToNumber("127.0.0.1", &address); uint16 start_seed = base::RandInt(0, kPortRangeSize); uint16 try_port = 0; for (uint16 i = 0; i < kPortRangeSize; ++i) { try_port = kMinPort + (start_seed + i) % kPortRangeSize; net::NetLog::Source source; net::TCPServerSocket sock(NULL, source); if (sock.Listen(net::IPEndPoint(address, try_port), 1) == net::OK) { port_ = try_port; return true; } } VLOG(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")); }