// Copyright 2016 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 "media/cdm/cdm_host_files.h" #include #include #include "base/command_line.h" #include "base/files/file.h" #include "base/files/file_path.h" #include "base/lazy_instance.h" #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/native_library.h" #include "base/path_service.h" #include "base/scoped_native_library.h" #include "build/build_config.h" #include "media/cdm/api/content_decryption_module_ext.h" #include "media/cdm/cdm_paths.h" namespace media { namespace { // TODO(xhwang): Move this to a common place if needed. const base::FilePath::CharType kSignatureFileExtension[] = FILE_PATH_LITERAL(".sig"); // Returns the signature file path given the |file_path|. This function should // only be used when the signature file and the file are located in the same // directory, which is the case for the CDM. base::FilePath GetSigFilePath(const base::FilePath& file_path) { return file_path.AddExtension(kSignatureFileExtension); } } // namespace CdmHostFiles::CdmHostFiles() { DVLOG(1) << __func__; } CdmHostFiles::~CdmHostFiles() { DVLOG(1) << __func__; } void CdmHostFiles::Initialize( const base::FilePath& cdm_path, const std::vector& cdm_host_file_paths) { OpenCdmFile(cdm_path); OpenCommonFiles(cdm_host_file_paths); } CdmHostFiles::Status CdmHostFiles::InitVerification( base::NativeLibrary cdm_library) { DVLOG(1) << __func__; DCHECK(cdm_library); // Get function pointer exported by the CDM. // See media/cdm/api/content_decryption_module_ext.h. using InitVerificationFunc = bool (*)(const cdm::HostFile* cdm_host_files, uint32_t num_files); static const char kInitVerificationFuncName[] = "VerifyCdmHost_0"; InitVerificationFunc init_verification_func = reinterpret_cast( base::GetFunctionPointerFromNativeLibrary(cdm_library, kInitVerificationFuncName)); if (!init_verification_func) { LOG(ERROR) << "Function " << kInitVerificationFuncName << " not found."; CloseAllFiles(); return Status::kGetFunctionFailed; } // Fills |cdm_host_files| with common and CDM specific files. std::vector cdm_host_files; TakePlatformFiles(&cdm_host_files); // std::vector::data() is not guaranteed to be nullptr when empty(). const cdm::HostFile* cdm_host_files_ptr = cdm_host_files.empty() ? nullptr : cdm_host_files.data(); // Call |init_verification_func| on the CDM with |cdm_host_files|. Note that // the ownership of these files are transferred to the CDM, which will close // the files immediately after use. DVLOG(1) << __func__ << ": Calling " << kInitVerificationFuncName << "() with " << cdm_host_files.size() << " files."; for (const auto& host_file : cdm_host_files) { DVLOG(1) << " - File Path: " << host_file.file_path; DVLOG(1) << " - File: " << host_file.file; DVLOG(1) << " - Sig File: " << host_file.sig_file; } if (!init_verification_func(cdm_host_files_ptr, cdm_host_files.size())) { DVLOG(1) << "Failed to verify CDM host."; CloseAllFiles(); return Status::kInitVerificationFailed; } // Close all files not passed to the CDM. CloseAllFiles(); return Status::kSuccess; } void CdmHostFiles::CloseAllFiles() { common_files_.clear(); cdm_specific_files_.clear(); } void CdmHostFiles::OpenCommonFiles( const std::vector& cdm_host_file_paths) { DCHECK(common_files_.empty()); for (const auto& value : cdm_host_file_paths) { common_files_.push_back( CdmHostFile::Create(value.file_path, value.sig_file_path)); } } void CdmHostFiles::OpenCdmFile(const base::FilePath& cdm_path) { DCHECK(!cdm_path.empty()); cdm_specific_files_.push_back( CdmHostFile::Create(cdm_path, GetSigFilePath(cdm_path))); } void CdmHostFiles::TakePlatformFiles( std::vector* cdm_host_files) { DCHECK(cdm_host_files->empty()); // Populate an array of cdm::HostFile. for (const auto& file : common_files_) cdm_host_files->push_back(file->TakePlatformFile()); for (const auto& file : cdm_specific_files_) cdm_host_files->push_back(file->TakePlatformFile()); } } // namespace media