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 18 const uint16 kMinPort = 17000; 19 const uint16 kPortRangeSize = 1000; 20 21 // Widevine license server configuration files. 22 const base::FilePath::CharType kKeysFileName[] = 23 FILE_PATH_LITERAL("keys.dat"); 24 const base::FilePath::CharType kPoliciesFileName[] = 25 FILE_PATH_LITERAL("policies.dat"); 26 const base::FilePath::CharType kProfilesFileName[] = 27 FILE_PATH_LITERAL("profiles.dat"); 28 29 // License server configuration files directory name relative to root. 30 const base::FilePath::CharType kLicenseServerConfigDirName[] = 31 FILE_PATH_LITERAL("config"); 32 33 WVTestLicenseServerConfig::WVTestLicenseServerConfig() { 34 } 35 36 WVTestLicenseServerConfig::~WVTestLicenseServerConfig() { 37 } 38 39 bool 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 101 bool 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 122 bool 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 130 std::string WVTestLicenseServerConfig::GetServerURL() { 131 return base::StringPrintf("http://localhost:%u/license_server", port_); 132 } 133 134 void 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 147 void 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