1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/media/wv_test_license_server_config.h" 6 7#include "base/command_line.h" 8#include "base/environment.h" 9#include "base/files/file_util.h" 10#include "base/path_service.h" 11#include "base/rand_util.h" 12#include "base/strings/stringprintf.h" 13#include "net/base/net_errors.h" 14#include "net/socket/tcp_server_socket.h" 15#include "net/test/python_utils.h" 16 17 18const uint16 kMinPort = 17000; 19const uint16 kPortRangeSize = 1000; 20 21// Widevine license server configuration files. 22const base::FilePath::CharType kKeysFileName[] = 23 FILE_PATH_LITERAL("keys.dat"); 24const base::FilePath::CharType kPoliciesFileName[] = 25 FILE_PATH_LITERAL("policies.dat"); 26const base::FilePath::CharType kProfilesFileName[] = 27 FILE_PATH_LITERAL("profiles.dat"); 28 29// License server configuration files directory name relative to root. 30const base::FilePath::CharType kLicenseServerConfigDirName[] = 31 FILE_PATH_LITERAL("config"); 32 33WVTestLicenseServerConfig::WVTestLicenseServerConfig() { 34} 35 36WVTestLicenseServerConfig::~WVTestLicenseServerConfig() { 37} 38 39bool WVTestLicenseServerConfig::GetServerCommandLine( 40 CommandLine* command_line) { 41 if (!GetPythonCommand(command_line)) { 42 LOG(ERROR) << "Could not get Python runtime command."; 43 return false; 44 } 45 46 // Add the Python protocol buffers files directory to Python path. 47 base::FilePath pyproto_dir; 48 if (!GetPyProtoPath(&pyproto_dir)) { 49 VLOG(0) << "Cannot find pyproto directory required by license server."; 50 return false; 51 } 52 AppendToPythonPath(pyproto_dir); 53 54 base::FilePath license_server_path; 55 GetLicenseServerPath(&license_server_path); 56 if (!base::PathExists(license_server_path)) { 57 VLOG(0) << "Missing license server file at " << license_server_path.value(); 58 return false; 59 } 60 61 base::FilePath server_root; 62 GetLicenseServerRootPath(&server_root); 63 base::FilePath config_path = server_root.Append(kLicenseServerConfigDirName); 64 65 if (!base::PathExists(config_path.Append(kKeysFileName)) || 66 !base::PathExists(config_path.Append(kPoliciesFileName)) || 67 !base::PathExists(config_path.Append(kProfilesFileName))) { 68 VLOG(0) << "Missing license server configuration files."; 69 return false; 70 } 71 72 if (!SelectServerPort()) 73 return false; 74 75 // Needed to dynamically load .so libraries used by license server. 76 // TODO(shadi): Remove need to set env variable once b/12932983 is fixed. 77#if defined(OS_LINUX) 78 scoped_ptr<base::Environment> env(base::Environment::Create()); 79 const char kLibraryPathEnvVarName[] = "LD_LIBRARY_PATH"; 80 std::string library_paths(license_server_path.DirName().value()); 81 std::string old_path; 82 if (env->GetVar(kLibraryPathEnvVarName, &old_path)) 83 library_paths.append(":").append(old_path); 84 env->SetVar(kLibraryPathEnvVarName, library_paths); 85#endif // defined(OS_LINUX) 86 87 // Since it is a Python command line, we need to AppendArg instead of 88 // AppendSwitch so that the arguments are passed to the Python server instead 89 // of Python engine. 90 command_line->AppendArgPath(license_server_path); 91 command_line->AppendArg("-k"); 92 command_line->AppendArgPath(config_path.Append(kKeysFileName)); 93 command_line->AppendArg("-o"); 94 command_line->AppendArgPath(config_path.Append(kPoliciesFileName)); 95 command_line->AppendArg("-r"); 96 command_line->AppendArgPath(config_path.Append(kProfilesFileName)); 97 command_line->AppendArg(base::StringPrintf("--port=%u", port_)); 98 return true; 99} 100 101bool WVTestLicenseServerConfig::SelectServerPort() { 102 // Try all ports within the range of kMinPort to (kMinPort + kPortRangeSize) 103 // Instead of starting from kMinPort, use a random port within that range. 104 net::IPAddressNumber address; 105 net::ParseIPLiteralToNumber("127.0.0.1", &address); 106 uint16 start_seed = base::RandInt(0, kPortRangeSize); 107 uint16 try_port = 0; 108 for (uint16 i = 0; i < kPortRangeSize; ++i) { 109 try_port = kMinPort + (start_seed + i) % kPortRangeSize; 110 net::NetLog::Source source; 111 net::TCPServerSocket sock(NULL, source); 112 if (sock.Listen(net::IPEndPoint(address, try_port), 1) == net::OK) { 113 port_ = try_port; 114 return true; 115 } 116 } 117 VLOG(0) << "Could not find an open port in the range of " << kMinPort << 118 " to " << kMinPort + kPortRangeSize; 119 return false; 120} 121 122bool WVTestLicenseServerConfig::IsPlatformSupported() { 123#if defined(OS_LINUX) && defined(ARCH_CPU_X86_64) 124 return true; 125#else 126 return false; 127#endif // defined(OS_LINUX) 128} 129 130std::string WVTestLicenseServerConfig::GetServerURL() { 131 return base::StringPrintf("http://localhost:%u/license_server", port_); 132} 133 134void WVTestLicenseServerConfig::GetLicenseServerPath(base::FilePath *path) { 135 base::FilePath server_root; 136 GetLicenseServerRootPath(&server_root); 137 // Platform-specific license server binary path relative to root. 138 *path = 139#if defined(OS_LINUX) 140 server_root.Append(FILE_PATH_LITERAL("linux")) 141 .Append(FILE_PATH_LITERAL("license_server.py")); 142#else 143 server_root.Append(FILE_PATH_LITERAL("unsupported_platform")); 144#endif // defined(OS_LINUX) 145} 146 147void WVTestLicenseServerConfig::GetLicenseServerRootPath( 148 base::FilePath* path) { 149 base::FilePath source_root; 150 PathService::Get(base::DIR_SOURCE_ROOT, &source_root); 151 *path = source_root.Append(FILE_PATH_LITERAL("third_party")) 152 .Append(FILE_PATH_LITERAL("widevine")) 153 .Append(FILE_PATH_LITERAL("test")) 154 .Append(FILE_PATH_LITERAL("license_server")); 155} 156