| // 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 <memory> |
| #include <vector> |
| |
| #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<CdmHostFilePath>& 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<InitVerificationFunc>( |
| 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::HostFile> 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<CdmHostFilePath>& 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::HostFile>* 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 |