Skip to content
This repository has been archived by the owner on Jan 4, 2019. It is now read-only.

Commit

Permalink
Verify CDM host files
Browse files Browse the repository at this point in the history
  • Loading branch information
darkdh authored and bridiver committed Oct 4, 2017
1 parent 897bd52 commit d1b68ef
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 6 deletions.
126 changes: 126 additions & 0 deletions atom/app/atom_content_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,26 @@
#include "atom/common/atom_version.h"
#include "atom/common/options_switches.h"
#include "atom/common/pepper_flash_util.h"
#include "base/base_paths.h"
#include "base/command_line.h"
#include "base/debug/crash_logging.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/mac/bundle_locations.h"
#include "base/memory/ptr_util.h"
#include "base/path_service.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_version.h"
#include "chrome/common/crash_keys.h"
#include "chrome/common/extensions/extension_process_policy.h"
#include "chrome/common/secure_origin_whitelist.h"
#include "content/public/common/cdm_info.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/pepper_plugin_info.h"
#include "content/public/common/user_agent.h"
Expand All @@ -41,6 +47,52 @@
#include "extensions/common/features/feature_util.h"
#endif

#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS) && \
!defined(WIDEVINE_CDM_IS_COMPONENT)
#define WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT
#include "chrome/common/widevine_cdm_constants.h"
#endif

#if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
#include "chrome/common/media/cdm_host_file_path.h"
#endif

#if defined(WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT)
bool IsWidevineAvailable(base::FilePath* adapter_path,
base::FilePath* cdm_path,
std::vector<std::string>* codecs_supported) {
static enum {
NOT_CHECKED,
FOUND,
NOT_FOUND,
} widevine_cdm_file_check = NOT_CHECKED;
// TODO(jrummell): We should add a new path for DIR_WIDEVINE_CDM and use that
// to locate the CDM and the CDM adapter.
if (PathService::Get(chrome::FILE_WIDEVINE_CDM_ADAPTER, adapter_path)) {
*cdm_path = adapter_path->DirName().AppendASCII(
base::GetNativeLibraryName(kWidevineCdmLibraryName));
if (widevine_cdm_file_check == NOT_CHECKED) {
widevine_cdm_file_check =
(base::PathExists(*adapter_path) && base::PathExists(*cdm_path))
? FOUND
: NOT_FOUND;
}
if (widevine_cdm_file_check == FOUND) {
// Add the supported codecs as if they came from the component manifest.
// This list must match the CDM that is being bundled with Chrome.
codecs_supported->push_back(kCdmSupportedCodecVp8);
codecs_supported->push_back(kCdmSupportedCodecVp9);
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
codecs_supported->push_back(kCdmSupportedCodecAvc1);
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
return true;
}
}

return false;
}
#endif // defined(WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT)

namespace atom {

namespace {
Expand Down Expand Up @@ -142,4 +194,78 @@ void AtomContentClient::AddPepperPlugins(
AddPepperFlashFromCommandLine(plugins);
}

// 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.
base::FilePath GetSigFilePath(const base::FilePath& file_path) {
return file_path.AddExtension(kSignatureFileExtension);
}

void AtomContentClient::AddContentDecryptionModules(
std::vector<content::CdmInfo>* cdms,
std::vector<content::CdmHostFilePath>* cdm_host_file_paths) {
if (cdms) {
// TODO(jrummell): Need to have a better flag to indicate systems Widevine
// is available on. For now we continue to use ENABLE_PEPPER_CDMS so that
// we can experiment between pepper and mojo.
#if defined(WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT)
base::FilePath adapter_path;
base::FilePath cdm_path;
std::vector<std::string> codecs_supported;
if (IsWidevineAvailable(&adapter_path, &cdm_path, &codecs_supported)) {
// CdmInfo needs |path| to be the actual Widevine library,
// not the adapter, so adjust as necessary. It will be in the
// same directory as the installed adapter.
const base::Version version(WIDEVINE_CDM_VERSION_STRING);
DCHECK(version.IsValid());
cdms->push_back(content::CdmInfo(kWidevineCdmType, version, cdm_path,
codecs_supported));
}
#endif // defined(WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT)

// TODO(jrummell): Add External Clear Key CDM for testing, if it's
// available.
}

#if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
if (cdm_host_file_paths) {
#if defined(OS_WIN)
static const base::FilePath::CharType* const kUnversionedFiles[] = {
FILE_PATH_LITERAL("brave.exe")};
base::FilePath brave_exe_dir;
if (!PathService::Get(base::DIR_EXE, &brave_exe_dir))
NOTREACHED();
cdm_host_file_paths->reserve(arraysize(kUnversionedFiles));

// Signature files are always in the version directory.
for (size_t i = 0; i < arraysize(kUnversionedFiles); ++i) {
base::FilePath file_path = brave_exe_dir.Append(kUnversionedFiles[i]);
base::FilePath sig_path =
GetSigFilePath(brave_exe_dir.Append(kUnversionedFiles[i]));
VLOG(1) << __func__ << ": unversioned file " << i << " at "
<< file_path.value() << ", signature file " << sig_path.value();
cdm_host_file_paths->push_back(
content::CdmHostFilePath(file_path, sig_path));
}
#elif defined(OS_MACOSX)
base::FilePath brave_framework_path =
base::mac::FrameworkBundlePath().Append(chrome::kFrameworkExecutableName);

base::FilePath brave_framework_sig_path = GetSigFilePath(
brave_framework_path.Append(chrome::kFrameworkExecutableName));

VLOG(1) << __func__
<< ": brave_framework_path=" << brave_framework_path.value()
<< ", signature_path=" << brave_framework_sig_path.value();
cdm_host_file_paths->push_back(
content::CdmHostFilePath(brave_framework_path, brave_framework_sig_path));
#endif
}
#endif
}

} // namespace atom
4 changes: 4 additions & 0 deletions atom/app/atom_content_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ class AtomContentClient : public brightray::ContentClient {
bool AllowScriptExtensionForServiceWorker(const GURL& script_url) override;
content::OriginTrialPolicy* GetOriginTrialPolicy() override;

void AddContentDecryptionModules(
std::vector<content::CdmInfo>* cdms,
std::vector<content::CdmHostFilePath>* cdm_host_file_paths) override;

private:
std::unique_ptr<ChromeOriginTrialPolicy> origin_trial_policy_;
DISALLOW_COPY_AND_ASSIGN(AtomContentClient);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ const char kCdmHostVersionsName[] = "x-cdm-host-versions";
// The list is passed to other parts of Chrome.
const char kCdmCodecsListName[] = "x-cdm-codecs";

// TODO(xhwang): Move this to a common place if needed.
const base::FilePath::CharType kSignatureFileExtension[] =
FILE_PATH_LITERAL(".sig");


// Widevine CDM is packaged as a multi-CRX. Widevine CDM binaries are located in
// _platform_specific/<platform_arch> folder in the package. This function
// returns the platform-specific subdirectory that is part of that multi-CRX.
Expand Down Expand Up @@ -355,22 +360,31 @@ void WidevineCdmComponentInstallerTraits::UpdateCdmAdapter(
DCHECK(!chromium_version.empty());

// If we are not using bundled CDM and we don't have a valid adapter, create
// the version file and copy the CDM adapter from |adapter_source_path| to
// |adapter_install_path|.
// the version file, copy the CDM adapter signature file, and copy the CDM
// adapter.
if (adapter_install_path != adapter_source_path &&
!HasValidAdapter(adapter_version_path, adapter_install_path,
chromium_version)) {
if (!base::CopyFile(adapter_source_path, adapter_install_path)) {
PLOG(WARNING) << "Failed to copy Widevine CDM adapter.";
return;
}

// Generate the version file.
int bytes_written = base::WriteFile(
adapter_version_path, chromium_version.data(), chromium_version.size());
if (bytes_written < 0 ||
static_cast<size_t>(bytes_written) != chromium_version.size()) {
PLOG(WARNING) << "Failed to write Widevine CDM adapter version file.";
// Ignore version file writing failure and try to copy the CDM adapter.
// Ignore version file writing failure.
}

if (!base::CopyFile(adapter_source_path, adapter_install_path)) {
PLOG(WARNING) << "Failed to copy Widevine CDM adapter.";
return;
// Copy Widevine CDM adapter signature file.
if (!base::CopyFile(
adapter_source_path.AddExtension(kSignatureFileExtension),
adapter_install_path.AddExtension(kSignatureFileExtension))) {
PLOG(WARNING) << "Failed to copy Widevine CDM adapter signature file.";
// The sig file may be missing or the copy failed. Ignore the failure.
}
}

Expand Down

0 comments on commit d1b68ef

Please sign in to comment.