// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary // source code may only be used and distributed under the Widevine License // Agreement. #include #include #include #include #include #include #include #include #include #include "cdm.h" #include "log.h" #include "oec_device_features.h" #include "stderr_logger.h" #include "test_base.h" #include "test_host.h" CDM_NAMESPACE::StderrLogger g_stderr_logger; std::string g_sandbox_id; namespace CDM_NAMESPACE { namespace { constexpr char kSandboxIdParam[] = "--sandbox_id="; constexpr char kCertPathParam[] = "--cert_path="; constexpr char kCertKeyPathParam[] = "--cert_key_path="; // Following the pattern established by help text in test_base.cpp constexpr char kExtraHelpText[] = " --sandbox_id=\n" " Specifies the Sandbox ID that should be sent to OEMCrypto via\n" " OEMCrypto_SetSandbox(). On most platforms, since Sandbox IDs are not\n" " in use, this parameter should be omitted.\n" " --cert_path=\n" " Path to a preloaded DRM certificate. This may speed up some tests\n" " by skipping the provisioning step. On most platforms, this parameter\n" " parameter should be omitted.\n" " --cert_key_path=\n" " Path to a key in preloaded DRM certificate. This should only be used\n" " if the device has a baked in cert.\n"; bool ReadFile(const std::string& path, std::string* output) { output->clear(); std::ifstream fs(path, std::ios::in | std::ios::binary); if (!fs) { LOGE("Failed to open %s: %s", path.c_str(), strerror(errno)); return false; } std::stringstream buffer; buffer << fs.rdbuf(); *output = buffer.str(); return true; } // Reads a file from the command line arguments. // The file path is expected to be the first argument after the flag. // For example, if the flag is "--cert_path=" and the command line is // cdm_test_runner --cert_path=/path/to/cert // then the file at /path/to/cert will be read. // The flag will be removed from the command line arguments. bool ReadFileFromArg(const char* path_flag, std::vector& args, std::string* data) { auto path_iter = std::find_if(std::begin(args) + 1, std::end(args), [path_flag](const std::string& elem) -> bool { return elem.find(path_flag) == 0; }); if (path_iter != std::end(args)) { const std::string path = path_iter->substr(strlen(path_flag)); args.erase(path_iter); return ReadFile(path, data); } return false; } } // namespace int Main(Cdm::IStorage* storage, Cdm::IClock* clock, Cdm::ITimer* timer, Cdm::ILogger* logger, int argc, char** argv) { // Find and filter out the Sandbox ID, if any. std::vector args(argv, argv + argc); auto sandbox_id_iter = std::find_if(std::begin(args) + 1, std::end(args), [](const std::string& elem) -> bool { return elem.find(kSandboxIdParam) == 0; }); if (sandbox_id_iter != std::end(args)) { g_sandbox_id = sandbox_id_iter->substr(strlen(kSandboxIdParam)); args.erase(sandbox_id_iter); } Cdm::Status status = Cdm::initialize( Cdm::kOpaqueHandle, storage, clock, timer, logger, static_cast(wvutil::g_cutoff), g_sandbox_id); (void)status; // status is now used when assertions are turned off. assert(status == Cdm::kSuccess); std::string data; if (ReadFileFromArg(kCertPathParam, args, &data)) { g_host->set_baked_in_cert(data); } if (ReadFileFromArg(kCertKeyPathParam, args, &data)) { wvoec::global_features.set_rsa_test_key( std::vector(data.begin(), data.end())); } std::vector new_argv(args.size()); std::transform( std::begin(args), std::end(args), std::begin(new_argv), [](const std::string& arg) -> const char* { return arg.c_str(); }); // This must take place after the call to Cdm::initialize() because it makes // calls that are only valid after the library is initialized. if (!wvcdm::WvCdmTestBase::Initialize(static_cast(new_argv.size()), new_argv.data(), kExtraHelpText)) { return 1; } // Init gtest after oemcrypto and cdm host have been initialized. ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } } // namespace CDM_NAMESPACE