Commit 59422884 authored by John Rummell's avatar John Rummell Committed by Commit Bot

Update CdmInfo to include encryption schemes supported

CdmInfo will now keep track of the encryption schemes supported by each
registered CDM. For component-updated Widevine, this will be determined
from the manifest. For built-in CDMs, this list is compiled in.

The set of encryption schemes supported is also passed to KeySystemSupport.

BUG=657957,658026
TEST=new content_unittests pass

Change-Id: I444091035e7ae1bc18720aff5bfea86afeca5ba7
Reviewed-on: https://chromium-review.googlesource.com/1019884Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarNasko Oskov <nasko@chromium.org>
Reviewed-by: default avatarLei Zhang <thestig@chromium.org>
Reviewed-by: default avatarJoshua Pawlicki <waffles@chromium.org>
Reviewed-by: default avatarXiaohan Wang <xhwang@chromium.org>
Commit-Queue: John Rummell <jrummell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#555150}
parent d8de8d34
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "base/base_paths.h" #include "base/base_paths.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/containers/flat_set.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/logging.h" #include "base/logging.h"
...@@ -35,6 +36,9 @@ ...@@ -35,6 +36,9 @@
#include "content/public/browser/cdm_registry.h" #include "content/public/browser/cdm_registry.h"
#include "content/public/common/cdm_info.h" #include "content/public/common/cdm_info.h"
#include "crypto/sha2.h" #include "crypto/sha2.h"
// TODO(crbug.com/825041): Move EncryptionMode out of decrypt_config and
// rename it to EncryptionScheme.
#include "media/base/decrypt_config.h"
#include "media/base/video_codecs.h" #include "media/base/video_codecs.h"
#include "media/cdm/supported_cdm_versions.h" #include "media/cdm/supported_cdm_versions.h"
#include "third_party/widevine/cdm/widevine_cdm_common.h" #include "third_party/widevine/cdm/widevine_cdm_common.h"
...@@ -100,6 +104,8 @@ const char kCdmCodecsListName[] = "x-cdm-codecs"; ...@@ -100,6 +104,8 @@ const char kCdmCodecsListName[] = "x-cdm-codecs";
// Whether persistent license is supported by the CDM: "true" or "false". // Whether persistent license is supported by the CDM: "true" or "false".
const char kCdmPersistentLicenseSupportName[] = const char kCdmPersistentLicenseSupportName[] =
"x-cdm-persistent-license-support"; "x-cdm-persistent-license-support";
const char kCdmSupportedEncryptionSchemesName[] =
"x-cdm-supported-encryption-schemes";
// The following strings are used to specify supported codecs in the // The following strings are used to specify supported codecs in the
// parameter |kCdmCodecsListName|. // parameter |kCdmCodecsListName|.
...@@ -109,6 +115,11 @@ const char kCdmSupportedCodecVp9[] = "vp9.0"; ...@@ -109,6 +115,11 @@ const char kCdmSupportedCodecVp9[] = "vp9.0";
const char kCdmSupportedCodecAvc1[] = "avc1"; const char kCdmSupportedCodecAvc1[] = "avc1";
#endif #endif
// The following strings are used to specify supported encryption schemes in
// the parameter |kCdmSupportedEncryptionSchemesName|.
const char kCdmSupportedEncryptionSchemeCenc[] = "cenc";
const char kCdmSupportedEncryptionSchemeCbcs[] = "cbcs";
// Widevine CDM is packaged as a multi-CRX. Widevine CDM binaries are located in // Widevine CDM is packaged as a multi-CRX. Widevine CDM binaries are located in
// _platform_specific/<platform_arch> folder in the package. This function // _platform_specific/<platform_arch> folder in the package. This function
// returns the platform-specific subdirectory that is part of that multi-CRX. // returns the platform-specific subdirectory that is part of that multi-CRX.
...@@ -198,6 +209,49 @@ bool GetPersistentLicenseSupport(const base::DictionaryValue& manifest) { ...@@ -198,6 +209,49 @@ bool GetPersistentLicenseSupport(const base::DictionaryValue& manifest) {
return value && value->is_bool() && value->GetBool(); return value && value->is_bool() && value->GetBool();
} }
// Determine the set of encryption schemes supported from |manifest|. It is
// assumed that all CDMs support 'cenc', so if the manifest entry
// |kCdmSupportedEncryptionSchemesName| is missing, the result will indicate
// support for 'cenc' only. Incorrect types in the manifest entry will log
// the error and return the empty set. Unrecognized values will be reported
// but otherwise ignored.
base::flat_set<media::EncryptionMode> GetSupportedEncryptionSchemes(
const base::DictionaryValue& manifest) {
const base::Value* value =
manifest.FindKey(kCdmSupportedEncryptionSchemesName);
if (!value)
return {media::EncryptionMode::kCenc};
if (!value->is_list()) {
DLOG(ERROR) << "Manifest entry " << kCdmSupportedEncryptionSchemesName
<< " is not a list.";
return {};
}
const base::Value::ListStorage& list = value->GetList();
base::flat_set<media::EncryptionMode> result;
for (const auto& item : list) {
if (!item.is_string()) {
DLOG(ERROR) << "Unrecognized item type in manifest entry "
<< kCdmSupportedEncryptionSchemesName;
return {};
}
const std::string& scheme = item.GetString();
if (scheme == kCdmSupportedEncryptionSchemeCenc) {
result.insert(media::EncryptionMode::kCenc);
} else if (scheme == kCdmSupportedEncryptionSchemeCbcs) {
result.insert(media::EncryptionMode::kCbcs);
} else {
DLOG(WARNING) << "Unrecognized encryption scheme " << scheme
<< " in manifest entry "
<< kCdmSupportedEncryptionSchemesName;
}
}
return result;
}
void RegisterWidevineCdmWithChrome( void RegisterWidevineCdmWithChrome(
const base::Version& cdm_version, const base::Version& cdm_version,
const base::FilePath& cdm_install_dir, const base::FilePath& cdm_install_dir,
...@@ -205,6 +259,13 @@ void RegisterWidevineCdmWithChrome( ...@@ -205,6 +259,13 @@ void RegisterWidevineCdmWithChrome(
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
const std::string codecs = GetCodecs(*manifest); const std::string codecs = GetCodecs(*manifest);
bool supports_persistent_license = GetPersistentLicenseSupport(*manifest); bool supports_persistent_license = GetPersistentLicenseSupport(*manifest);
auto supported_encryption_schemes = GetSupportedEncryptionSchemes(*manifest);
// TODO(crbug.com/837840): Validate results for other manifest entries.
if (supported_encryption_schemes.empty()) {
VLOG(1) << "Not registering Widevine CDM due to malformed manifest.";
return;
}
VLOG(1) << "Register Widevine CDM with Chrome"; VLOG(1) << "Register Widevine CDM with Chrome";
...@@ -217,7 +278,8 @@ void RegisterWidevineCdmWithChrome( ...@@ -217,7 +278,8 @@ void RegisterWidevineCdmWithChrome(
CdmRegistry::GetInstance()->RegisterCdm(content::CdmInfo( CdmRegistry::GetInstance()->RegisterCdm(content::CdmInfo(
kWidevineCdmDisplayName, kWidevineCdmGuid, cdm_version, cdm_path, kWidevineCdmDisplayName, kWidevineCdmGuid, cdm_version, cdm_path,
kWidevineCdmFileSystemId, supported_video_codecs, kWidevineCdmFileSystemId, supported_video_codecs,
supports_persistent_license, kWidevineKeySystem, false)); supports_persistent_license, supported_encryption_schemes,
kWidevineKeySystem, false));
} }
} // namespace } // namespace
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <utility> #include <utility>
#include "base/command_line.h" #include "base/command_line.h"
#include "base/containers/flat_set.h"
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/json/json_reader.h" #include "base/json/json_reader.h"
#include "base/lazy_instance.h" #include "base/lazy_instance.h"
...@@ -49,6 +50,7 @@ ...@@ -49,6 +50,7 @@
#include "extensions/common/constants.h" #include "extensions/common/constants.h"
#include "gpu/config/gpu_info.h" #include "gpu/config/gpu_info.h"
#include "gpu/config/gpu_util.h" #include "gpu/config/gpu_util.h"
#include "media/base/decrypt_config.h"
#include "media/base/media_switches.h" #include "media/base/media_switches.h"
#include "media/base/video_codecs.h" #include "media/base/video_codecs.h"
#include "media/media_buildflags.h" #include "media/media_buildflags.h"
...@@ -128,9 +130,11 @@ content::PepperPluginInfo::PPP_ShutdownModuleFunc g_nacl_shutdown_module; ...@@ -128,9 +130,11 @@ content::PepperPluginInfo::PPP_ShutdownModuleFunc g_nacl_shutdown_module;
#endif #endif
#if defined(WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT) #if defined(WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT)
bool IsWidevineAvailable(base::FilePath* cdm_path, bool IsWidevineAvailable(
std::vector<media::VideoCodec>* codecs_supported, base::FilePath* cdm_path,
bool* supports_persistent_license) { std::vector<media::VideoCodec>* codecs_supported,
bool* supports_persistent_license,
base::flat_set<media::EncryptionMode>* modes_supported) {
static enum { static enum {
NOT_CHECKED, NOT_CHECKED,
FOUND, FOUND,
...@@ -158,6 +162,10 @@ bool IsWidevineAvailable(base::FilePath* cdm_path, ...@@ -158,6 +162,10 @@ bool IsWidevineAvailable(base::FilePath* cdm_path,
*supports_persistent_license = false; *supports_persistent_license = false;
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
// TODO(crbug.com/835009): Update once Widevine on Linux supports more
// encryption schemes.
modes_supported->insert(media::EncryptionMode::kCenc);
return true; return true;
} }
} }
...@@ -524,15 +532,18 @@ void ChromeContentClient::AddContentDecryptionModules( ...@@ -524,15 +532,18 @@ void ChromeContentClient::AddContentDecryptionModules(
base::FilePath cdm_path; base::FilePath cdm_path;
std::vector<media::VideoCodec> video_codecs_supported; std::vector<media::VideoCodec> video_codecs_supported;
bool supports_persistent_license = false; bool supports_persistent_license = false;
base::flat_set<media::EncryptionMode> encryption_modes_supported;
if (IsWidevineAvailable(&cdm_path, &video_codecs_supported, if (IsWidevineAvailable(&cdm_path, &video_codecs_supported,
&supports_persistent_license)) { &supports_persistent_license,
&encryption_modes_supported)) {
const base::Version version(WIDEVINE_CDM_VERSION_STRING); const base::Version version(WIDEVINE_CDM_VERSION_STRING);
DCHECK(version.IsValid()); DCHECK(version.IsValid());
cdms->push_back(content::CdmInfo( cdms->push_back(content::CdmInfo(
kWidevineCdmDisplayName, kWidevineCdmGuid, version, cdm_path, kWidevineCdmDisplayName, kWidevineCdmGuid, version, cdm_path,
kWidevineCdmFileSystemId, video_codecs_supported, kWidevineCdmFileSystemId, video_codecs_supported,
supports_persistent_license, kWidevineKeySystem, false)); supports_persistent_license, encryption_modes_supported,
kWidevineKeySystem, false));
} }
#endif // defined(WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT) #endif // defined(WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT)
...@@ -556,10 +567,13 @@ void ChromeContentClient::AddContentDecryptionModules( ...@@ -556,10 +567,13 @@ void ChromeContentClient::AddContentDecryptionModules(
// Otherwise, it'll be treated as a sub-key-system of normal // Otherwise, it'll be treated as a sub-key-system of normal
// kExternalClearKeyKeySystem. See MultipleCdmTypes test in // kExternalClearKeyKeySystem. See MultipleCdmTypes test in
// ECKEncryptedMediaTest. // ECKEncryptedMediaTest.
// TODO(crbug.com/835009): Update when ECK supports more encryption
// schemes.
cdms->push_back(content::CdmInfo( cdms->push_back(content::CdmInfo(
media::kClearKeyCdmDisplayName, media::kClearKeyCdmDifferentGuid, media::kClearKeyCdmDisplayName, media::kClearKeyCdmDifferentGuid,
base::Version("0.1.0.0"), clear_key_cdm_path, base::Version("0.1.0.0"), clear_key_cdm_path,
media::kClearKeyCdmFileSystemId, {}, supports_persistent_license, media::kClearKeyCdmFileSystemId, {}, supports_persistent_license,
{media::EncryptionMode::kCenc},
kExternalClearKeyDifferentGuidTestKeySystem, false)); kExternalClearKeyDifferentGuidTestKeySystem, false));
// Supported codecs are hard-coded in ExternalClearKeyProperties. // Supported codecs are hard-coded in ExternalClearKeyProperties.
...@@ -567,7 +581,7 @@ void ChromeContentClient::AddContentDecryptionModules( ...@@ -567,7 +581,7 @@ void ChromeContentClient::AddContentDecryptionModules(
media::kClearKeyCdmDisplayName, media::kClearKeyCdmGuid, media::kClearKeyCdmDisplayName, media::kClearKeyCdmGuid,
base::Version("0.1.0.0"), clear_key_cdm_path, base::Version("0.1.0.0"), clear_key_cdm_path,
media::kClearKeyCdmFileSystemId, {}, supports_persistent_license, media::kClearKeyCdmFileSystemId, {}, supports_persistent_license,
kExternalClearKeyKeySystem, true)); {media::EncryptionMode::kCenc}, kExternalClearKeyKeySystem, true));
} }
#endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS)
} }
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "components/cdm/renderer/external_clear_key_key_system_properties.h" #include "components/cdm/renderer/external_clear_key_key_system_properties.h"
#include "components/cdm/renderer/widevine_key_system_properties.h" #include "components/cdm/renderer/widevine_key_system_properties.h"
#include "content/public/renderer/render_thread.h" #include "content/public/renderer/render_thread.h"
#include "media/base/decrypt_config.h"
#include "media/base/eme_constants.h" #include "media/base/eme_constants.h"
#include "media/base/key_system_properties.h" #include "media/base/key_system_properties.h"
#include "media/media_buildflags.h" #include "media/media_buildflags.h"
...@@ -81,9 +82,10 @@ static void AddExternalClearKey( ...@@ -81,9 +82,10 @@ static void AddExternalClearKey(
std::vector<media::VideoCodec> supported_video_codecs; std::vector<media::VideoCodec> supported_video_codecs;
bool supports_persistent_license; bool supports_persistent_license;
if (!content::IsKeySystemSupported(kExternalClearKeyKeySystem, std::vector<media::EncryptionMode> supported_encryption_schemes;
&supported_video_codecs, if (!content::IsKeySystemSupported(
&supports_persistent_license)) { kExternalClearKeyKeySystem, &supported_video_codecs,
&supports_persistent_license, &supported_encryption_schemes)) {
return; return;
} }
...@@ -194,9 +196,10 @@ static void AddWidevine( ...@@ -194,9 +196,10 @@ static void AddWidevine(
std::vector<media::VideoCodec> supported_video_codecs; std::vector<media::VideoCodec> supported_video_codecs;
bool supports_persistent_license = false; bool supports_persistent_license = false;
if (!content::IsKeySystemSupported(kWidevineKeySystem, std::vector<media::EncryptionMode> supported_encryption_schemes;
&supported_video_codecs, if (!content::IsKeySystemSupported(
&supports_persistent_license)) { kWidevineKeySystem, &supported_video_codecs,
&supports_persistent_license, &supported_encryption_schemes)) {
DVLOG(1) << "Widevine CDM is not currently available."; DVLOG(1) << "Widevine CDM is not currently available.";
return; return;
} }
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <vector> #include <vector>
#include "base/base_paths.h" #include "base/base_paths.h"
#include "base/containers/flat_set.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/strings/string_split.h" #include "base/strings/string_split.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
...@@ -21,6 +22,7 @@ ...@@ -21,6 +22,7 @@
namespace content { namespace content {
const char kTestCdmName[] = "Test CDM"; const char kTestCdmName[] = "Test CDM";
const char kAlternateCdmName[] = "Alternate CDM";
const char kTestCdmGuid[] = "62FE9C4B-384E-48FD-B28A-9F6F248BC8CC"; const char kTestCdmGuid[] = "62FE9C4B-384E-48FD-B28A-9F6F248BC8CC";
const char kTestPath[] = "/aa/bb"; const char kTestPath[] = "/aa/bb";
const char kVersion1[] = "1.1.1.1"; const char kVersion1[] = "1.1.1.1";
...@@ -41,13 +43,14 @@ class CdmRegistryImplTest : public testing::Test { ...@@ -41,13 +43,14 @@ class CdmRegistryImplTest : public testing::Test {
const std::string& path, const std::string& path,
const std::vector<media::VideoCodec>& supported_video_codecs, const std::vector<media::VideoCodec>& supported_video_codecs,
bool supports_persistent_license, bool supports_persistent_license,
const base::flat_set<media::EncryptionMode>& supported_modes,
std::string supported_key_system, std::string supported_key_system,
bool supports_sub_key_systems = false) { bool supports_sub_key_systems = false) {
cdm_registry_.RegisterCdm( cdm_registry_.RegisterCdm(CdmInfo(
CdmInfo(name, kTestCdmGuid, base::Version(version), name, kTestCdmGuid, base::Version(version),
base::FilePath::FromUTF8Unsafe(path), kTestFileSystemId, base::FilePath::FromUTF8Unsafe(path), kTestFileSystemId,
supported_video_codecs, supports_persistent_license, supported_video_codecs, supports_persistent_license, supported_modes,
supported_key_system, supports_sub_key_systems)); supported_key_system, supports_sub_key_systems));
} }
bool IsRegistered(const std::string& name, const std::string& version) { bool IsRegistered(const std::string& name, const std::string& version) {
...@@ -73,7 +76,8 @@ class CdmRegistryImplTest : public testing::Test { ...@@ -73,7 +76,8 @@ class CdmRegistryImplTest : public testing::Test {
TEST_F(CdmRegistryImplTest, Register) { TEST_F(CdmRegistryImplTest, Register) {
Register(kTestCdmName, kVersion1, kTestPath, Register(kTestCdmName, kVersion1, kTestPath,
{media::kCodecVP8, media::kCodecVP9}, true, kTestKeySystem, true); {media::kCodecVP8, media::kCodecVP9}, true,
{media::EncryptionMode::kCenc}, kTestKeySystem, true);
std::vector<CdmInfo> cdms = cdm_registry_.GetAllRegisteredCdms(); std::vector<CdmInfo> cdms = cdm_registry_.GetAllRegisteredCdms();
ASSERT_EQ(1u, cdms.size()); ASSERT_EQ(1u, cdms.size());
CdmInfo cdm = cdms[0]; CdmInfo cdm = cdms[0];
...@@ -85,29 +89,38 @@ TEST_F(CdmRegistryImplTest, Register) { ...@@ -85,29 +89,38 @@ TEST_F(CdmRegistryImplTest, Register) {
EXPECT_EQ(media::kCodecVP8, cdm.supported_video_codecs[0]); EXPECT_EQ(media::kCodecVP8, cdm.supported_video_codecs[0]);
EXPECT_EQ(media::kCodecVP9, cdm.supported_video_codecs[1]); EXPECT_EQ(media::kCodecVP9, cdm.supported_video_codecs[1]);
EXPECT_TRUE(cdm.supports_persistent_license); EXPECT_TRUE(cdm.supports_persistent_license);
EXPECT_EQ(1u, cdm.supported_encryption_schemes.size());
EXPECT_EQ(
1u, cdm.supported_encryption_schemes.count(media::EncryptionMode::kCenc));
EXPECT_EQ(kTestKeySystem, cdm.supported_key_system); EXPECT_EQ(kTestKeySystem, cdm.supported_key_system);
EXPECT_TRUE(cdm.supports_sub_key_systems); EXPECT_TRUE(cdm.supports_sub_key_systems);
} }
TEST_F(CdmRegistryImplTest, ReRegister) { TEST_F(CdmRegistryImplTest, ReRegister) {
Register(kTestCdmName, kVersion1, "/bb/cc", {}, false, kTestKeySystem); Register(kTestCdmName, kVersion1, "/bb/cc", {}, false,
{media::EncryptionMode::kCenc}, kTestKeySystem);
EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1)); EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
// Now register same key system with different values. // Now register same key system with different values.
Register(kTestCdmName, kVersion1, kTestPath, {}, false, kTestKeySystem); Register(kTestCdmName, kVersion1, kTestPath, {}, false,
{media::EncryptionMode::kCenc}, kTestKeySystem);
EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1)); EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
} }
TEST_F(CdmRegistryImplTest, MultipleVersions) { TEST_F(CdmRegistryImplTest, MultipleVersions) {
Register(kTestCdmName, kVersion1, kTestPath, {}, false, kTestKeySystem); Register(kTestCdmName, kVersion1, kTestPath, {}, false,
Register(kTestCdmName, kVersion2, "/bb/cc", {}, false, kTestKeySystem); {media::EncryptionMode::kCenc}, kTestKeySystem);
Register(kTestCdmName, kVersion2, "/bb/cc", {}, false,
{media::EncryptionMode::kCenc}, kTestKeySystem);
EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1)); EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion2)); EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion2));
} }
TEST_F(CdmRegistryImplTest, NewVersionInsertedLast) { TEST_F(CdmRegistryImplTest, NewVersionInsertedLast) {
Register(kTestCdmName, kVersion1, kTestPath, {}, false, kTestKeySystem); Register(kTestCdmName, kVersion1, kTestPath, {}, false,
Register(kTestCdmName, kVersion2, "/bb/cc", {}, false, kTestKeySystem); {media::EncryptionMode::kCenc}, kTestKeySystem);
Register(kTestCdmName, kVersion2, "/bb/cc", {}, false,
{media::EncryptionMode::kCenc}, kTestKeySystem);
const std::vector<std::string> versions = GetVersions(kTestCdmGuid); const std::vector<std::string> versions = GetVersions(kTestCdmGuid);
EXPECT_EQ(2u, versions.size()); EXPECT_EQ(2u, versions.size());
...@@ -115,4 +128,28 @@ TEST_F(CdmRegistryImplTest, NewVersionInsertedLast) { ...@@ -115,4 +128,28 @@ TEST_F(CdmRegistryImplTest, NewVersionInsertedLast) {
EXPECT_EQ(kVersion2, versions[1]); EXPECT_EQ(kVersion2, versions[1]);
} }
TEST_F(CdmRegistryImplTest, DifferentNames) {
Register(kTestCdmName, kVersion1, kTestPath, {}, false,
{media::EncryptionMode::kCenc}, kTestKeySystem);
Register(kAlternateCdmName, kVersion1, kTestPath, {}, false,
{media::EncryptionMode::kCbcs}, kTestKeySystem);
EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
EXPECT_TRUE(IsRegistered(kAlternateCdmName, kVersion1));
}
TEST_F(CdmRegistryImplTest, SupportedEncryptionSchemes) {
Register(kTestCdmName, kVersion1, kTestPath, {}, false,
{media::EncryptionMode::kCenc, media::EncryptionMode::kCbcs},
kTestKeySystem);
std::vector<CdmInfo> cdms = cdm_registry_.GetAllRegisteredCdms();
ASSERT_EQ(1u, cdms.size());
const CdmInfo& cdm = cdms[0];
EXPECT_EQ(2u, cdm.supported_encryption_schemes.size());
EXPECT_EQ(
1u, cdm.supported_encryption_schemes.count(media::EncryptionMode::kCenc));
EXPECT_EQ(
1u, cdm.supported_encryption_schemes.count(media::EncryptionMode::kCbcs));
}
} // namespace content } // namespace content
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <vector> #include <vector>
#include "base/containers/flat_set.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_functions.h"
#include "content/public/browser/cdm_registry.h" #include "content/public/browser/cdm_registry.h"
...@@ -62,13 +63,16 @@ void KeySystemSupportImpl::IsKeySystemSupported( ...@@ -62,13 +63,16 @@ void KeySystemSupportImpl::IsKeySystemSupported(
std::unique_ptr<CdmInfo> cdm = GetCdmInfoForKeySystem(key_system); std::unique_ptr<CdmInfo> cdm = GetCdmInfoForKeySystem(key_system);
if (!cdm) { if (!cdm) {
SendCdmAvailableUMA(key_system, false); SendCdmAvailableUMA(key_system, false);
std::move(callback).Run(false, {}, false); std::move(callback).Run(false, {}, false, {});
return; return;
} }
const base::flat_set<media::EncryptionMode>& schemes =
cdm->supported_encryption_schemes;
SendCdmAvailableUMA(key_system, true); SendCdmAvailableUMA(key_system, true);
std::move(callback).Run(true, cdm->supported_video_codecs, std::move(callback).Run(
cdm->supports_persistent_license); true, cdm->supported_video_codecs, cdm->supports_persistent_license,
std::vector<media::EncryptionMode>(schemes.begin(), schemes.end()));
} }
} // namespace content } // namespace content
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "content/public/common/cdm_info.h" #include "content/public/common/cdm_info.h"
#include "content/public/common/webplugininfo.h" #include "content/public/common/webplugininfo.h"
#include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/test_browser_thread_bundle.h"
#include "media/base/decrypt_config.h"
#include "media/base/video_codecs.h" #include "media/base/video_codecs.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -39,24 +40,16 @@ class KeySystemSupportTest : public testing::Test { ...@@ -39,24 +40,16 @@ class KeySystemSupportTest : public testing::Test {
// |supports_persistent_license|. All other values for CdmInfo have some // |supports_persistent_license|. All other values for CdmInfo have some
// default value as they're not returned by IsKeySystemSupported(). // default value as they're not returned by IsKeySystemSupported().
void Register(const std::string& key_system, void Register(const std::string& key_system,
const std::vector<media::VideoCodec> supported_video_codecs, const std::vector<media::VideoCodec>& supported_video_codecs,
bool supports_persistent_license) { bool supports_persistent_license,
const base::flat_set<media::EncryptionMode>& supported_modes) {
DVLOG(1) << __func__; DVLOG(1) << __func__;
CdmRegistry::GetInstance()->RegisterCdm( CdmRegistry::GetInstance()->RegisterCdm(
CdmInfo(key_system, kTestCdmGuid, base::Version(kVersion), CdmInfo(key_system, kTestCdmGuid, base::Version(kVersion),
base::FilePath::FromUTF8Unsafe(kTestPath), kTestFileSystemId, base::FilePath::FromUTF8Unsafe(kTestPath), kTestFileSystemId,
supported_video_codecs, supports_persistent_license, key_system, supported_video_codecs, supports_persistent_license,
false)); supported_modes, key_system, false));
// As IsKeySystemSupported() checks for the matching pepper plugin,
// register a dummy one.
// TODO(crbug.com/772160) Remove this when pepper CDM support removed.
PluginService::GetInstance()->RegisterInternalPlugin(
WebPluginInfo(base::ASCIIToUTF16(key_system),
base::FilePath::FromUTF8Unsafe(kTestPath),
base::ASCIIToUTF16(kVersion), base::string16()),
true);
} }
// Determines if |key_system| is registered. If it is, updates |codecs_| // Determines if |key_system| is registered. If it is, updates |codecs_|
...@@ -65,7 +58,8 @@ class KeySystemSupportTest : public testing::Test { ...@@ -65,7 +58,8 @@ class KeySystemSupportTest : public testing::Test {
DVLOG(1) << __func__; DVLOG(1) << __func__;
bool is_available = false; bool is_available = false;
key_system_support_->IsKeySystemSupported(key_system, &is_available, key_system_support_->IsKeySystemSupported(key_system, &is_available,
&codecs_, &persistent_); &codecs_, &persistent_,
&encryption_schemes_);
return is_available; return is_available;
} }
...@@ -75,6 +69,7 @@ class KeySystemSupportTest : public testing::Test { ...@@ -75,6 +69,7 @@ class KeySystemSupportTest : public testing::Test {
// Updated by IsSupported(). // Updated by IsSupported().
std::vector<media::VideoCodec> codecs_; std::vector<media::VideoCodec> codecs_;
bool persistent_; bool persistent_;
std::vector<media::EncryptionMode> encryption_schemes_;
}; };
// Note that as CdmRegistry::GetInstance() is a static, it is shared between // Note that as CdmRegistry::GetInstance() is a static, it is shared between
...@@ -86,30 +81,41 @@ TEST_F(KeySystemSupportTest, NoKeySystems) { ...@@ -86,30 +81,41 @@ TEST_F(KeySystemSupportTest, NoKeySystems) {
} }
TEST_F(KeySystemSupportTest, OneKeySystem) { TEST_F(KeySystemSupportTest, OneKeySystem) {
Register("KeySystem2", {media::VideoCodec::kCodecVP8}, true); Register("KeySystem2", {media::VideoCodec::kCodecVP8}, true,
{media::EncryptionMode::kCenc, media::EncryptionMode::kCbcs});
EXPECT_TRUE(IsSupported("KeySystem2")); EXPECT_TRUE(IsSupported("KeySystem2"));
EXPECT_EQ(1u, codecs_.size()); EXPECT_EQ(1u, codecs_.size());
EXPECT_EQ(media::VideoCodec::kCodecVP8, codecs_[0]); EXPECT_EQ(media::VideoCodec::kCodecVP8, codecs_[0]);
EXPECT_TRUE(persistent_); EXPECT_TRUE(persistent_);
EXPECT_EQ(2u, encryption_schemes_.size());
EXPECT_EQ(media::EncryptionMode::kCenc, encryption_schemes_[0]);
EXPECT_EQ(media::EncryptionMode::kCbcs, encryption_schemes_[1]);
} }
TEST_F(KeySystemSupportTest, MultipleKeySystems) { TEST_F(KeySystemSupportTest, MultipleKeySystems) {
Register("KeySystem3", Register("KeySystem3",
{media::VideoCodec::kCodecVP8, media::VideoCodec::kCodecVP9}, true); {media::VideoCodec::kCodecVP8, media::VideoCodec::kCodecVP9}, true,
Register("KeySystem4", {media::VideoCodec::kCodecVP9}, false); {media::EncryptionMode::kCenc});
Register("KeySystem4", {media::VideoCodec::kCodecVP9}, false,
{media::EncryptionMode::kCbcs});
EXPECT_TRUE(IsSupported("KeySystem3")); EXPECT_TRUE(IsSupported("KeySystem3"));
EXPECT_EQ(2u, codecs_.size()); EXPECT_EQ(2u, codecs_.size());
EXPECT_EQ(media::VideoCodec::kCodecVP8, codecs_[0]); EXPECT_EQ(media::VideoCodec::kCodecVP8, codecs_[0]);
EXPECT_EQ(media::VideoCodec::kCodecVP9, codecs_[1]); EXPECT_EQ(media::VideoCodec::kCodecVP9, codecs_[1]);
EXPECT_TRUE(persistent_); EXPECT_TRUE(persistent_);
EXPECT_EQ(1u, encryption_schemes_.size());
EXPECT_EQ(media::EncryptionMode::kCenc, encryption_schemes_[0]);
EXPECT_TRUE(IsSupported("KeySystem4")); EXPECT_TRUE(IsSupported("KeySystem4"));
EXPECT_EQ(1u, codecs_.size()); EXPECT_EQ(1u, codecs_.size());
EXPECT_EQ(media::VideoCodec::kCodecVP9, codecs_[0]); EXPECT_EQ(media::VideoCodec::kCodecVP9, codecs_[0]);
EXPECT_FALSE(persistent_); EXPECT_FALSE(persistent_);
EXPECT_EQ(1u, encryption_schemes_.size());
EXPECT_EQ(media::EncryptionMode::kCbcs, encryption_schemes_[0]);
} }
TEST_F(KeySystemSupportTest, MissingKeySystem) { TEST_F(KeySystemSupportTest, MissingKeySystem) {
Register("KeySystem5", {media::VideoCodec::kCodecVP8}, true); Register("KeySystem5", {media::VideoCodec::kCodecVP8}, true,
{media::EncryptionMode::kCenc});
EXPECT_FALSE(IsSupported("KeySystem6")); EXPECT_FALSE(IsSupported("KeySystem6"));
} }
......
...@@ -9,15 +9,17 @@ ...@@ -9,15 +9,17 @@
namespace content { namespace content {
CdmInfo::CdmInfo(const std::string& name, CdmInfo::CdmInfo(
const std::string& guid, const std::string& name,
const base::Version& version, const std::string& guid,
const base::FilePath& path, const base::Version& version,
const std::string& file_system_id, const base::FilePath& path,
const std::vector<media::VideoCodec>& supported_video_codecs, const std::string& file_system_id,
bool supports_persistent_license, const std::vector<media::VideoCodec>& supported_video_codecs,
const std::string& supported_key_system, bool supports_persistent_license,
bool supports_sub_key_systems) const base::flat_set<media::EncryptionMode>& supported_encryption_schemes,
const std::string& supported_key_system,
bool supports_sub_key_systems)
: name(name), : name(name),
guid(guid), guid(guid),
version(version), version(version),
...@@ -25,13 +27,15 @@ CdmInfo::CdmInfo(const std::string& name, ...@@ -25,13 +27,15 @@ CdmInfo::CdmInfo(const std::string& name,
file_system_id(file_system_id), file_system_id(file_system_id),
supported_video_codecs(supported_video_codecs), supported_video_codecs(supported_video_codecs),
supports_persistent_license(supports_persistent_license), supports_persistent_license(supports_persistent_license),
supported_encryption_schemes(supported_encryption_schemes),
supported_key_system(supported_key_system), supported_key_system(supported_key_system),
supports_sub_key_systems(supports_sub_key_systems) { supports_sub_key_systems(supports_sub_key_systems) {
DCHECK(base::IsValidGUID(guid)); DCHECK(base::IsValidGUID(guid));
DCHECK(!supported_encryption_schemes.empty());
} }
CdmInfo::CdmInfo(const CdmInfo& other) = default; CdmInfo::CdmInfo(const CdmInfo& other) = default;
CdmInfo::~CdmInfo() {} CdmInfo::~CdmInfo() = default;
} // namespace content } // namespace content
...@@ -8,24 +8,30 @@ ...@@ -8,24 +8,30 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "base/containers/flat_set.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/version.h" #include "base/version.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
// TODO(crbug.com/825041): Move EncryptionMode out of decrypt_config and
// rename it to EncryptionScheme.
#include "media/base/decrypt_config.h"
#include "media/base/video_codecs.h" #include "media/base/video_codecs.h"
namespace content { namespace content {
// Represents a Content Decryption Module implementation and its capabilities. // Represents a Content Decryption Module implementation and its capabilities.
struct CONTENT_EXPORT CdmInfo { struct CONTENT_EXPORT CdmInfo {
CdmInfo(const std::string& name, CdmInfo(
const std::string& guid, const std::string& name,
const base::Version& version, const std::string& guid,
const base::FilePath& path, const base::Version& version,
const std::string& file_system_id, const base::FilePath& path,
const std::vector<media::VideoCodec>& supported_video_codecs, const std::string& file_system_id,
bool supports_persistent_license, const std::vector<media::VideoCodec>& supported_video_codecs,
const std::string& supported_key_system, bool supports_persistent_license,
bool supports_sub_key_systems); const base::flat_set<media::EncryptionMode>& supported_encryption_schemes,
const std::string& supported_key_system,
bool supports_sub_key_systems);
CdmInfo(const CdmInfo& other); CdmInfo(const CdmInfo& other);
~CdmInfo(); ~CdmInfo();
...@@ -57,6 +63,10 @@ struct CONTENT_EXPORT CdmInfo { ...@@ -57,6 +63,10 @@ struct CONTENT_EXPORT CdmInfo {
// Whether this CDM supports persistent licenses. // Whether this CDM supports persistent licenses.
bool supports_persistent_license; bool supports_persistent_license;
// List of encryption schemes supported by the CDM (e.g. cenc). This is the
// set of encryption schemes that the CDM supports.
base::flat_set<media::EncryptionMode> supported_encryption_schemes;
// The key system supported by this CDM. // The key system supported by this CDM.
std::string supported_key_system; std::string supported_key_system;
...@@ -64,7 +74,7 @@ struct CONTENT_EXPORT CdmInfo { ...@@ -64,7 +74,7 @@ struct CONTENT_EXPORT CdmInfo {
// A sub key system to a key system is like a sub domain to a domain. // A sub key system to a key system is like a sub domain to a domain.
// For example, com.example.somekeysystem.a and com.example.somekeysystem.b // For example, com.example.somekeysystem.a and com.example.somekeysystem.b
// are both sub key systems of com.example.somekeysystem. // are both sub key systems of com.example.somekeysystem.
bool supports_sub_key_systems = false; bool supports_sub_key_systems;
}; };
} // namespace content } // namespace content
......
...@@ -15,7 +15,8 @@ namespace content { ...@@ -15,7 +15,8 @@ namespace content {
bool IsKeySystemSupported( bool IsKeySystemSupported(
const std::string& key_system, const std::string& key_system,
std::vector<media::VideoCodec>* supported_video_codecs, std::vector<media::VideoCodec>* supported_video_codecs,
bool* supports_persistent_license) { bool* supports_persistent_license,
std::vector<media::EncryptionMode>* supported_encryption_schemes) {
DVLOG(3) << __func__ << " key_system: " << key_system; DVLOG(3) << __func__ << " key_system: " << key_system;
bool is_supported = false; bool is_supported = false;
...@@ -23,9 +24,9 @@ bool IsKeySystemSupported( ...@@ -23,9 +24,9 @@ bool IsKeySystemSupported(
content::RenderThread::Get()->GetConnector()->BindInterface( content::RenderThread::Get()->GetConnector()->BindInterface(
mojom::kBrowserServiceName, mojo::MakeRequest(&key_system_support)); mojom::kBrowserServiceName, mojo::MakeRequest(&key_system_support));
key_system_support->IsKeySystemSupported(key_system, &is_supported, key_system_support->IsKeySystemSupported(
supported_video_codecs, key_system, &is_supported, supported_video_codecs,
supports_persistent_license); supports_persistent_license, supported_encryption_schemes);
return is_supported; return is_supported;
} }
......
...@@ -9,18 +9,20 @@ ...@@ -9,18 +9,20 @@
#include <vector> #include <vector>
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "media/base/decrypt_config.h"
#include "media/base/video_codecs.h" #include "media/base/video_codecs.h"
namespace content { namespace content {
// Determines if |key_system| is supported by calling into the browser. // Determines if |key_system| is supported by calling into the browser.
// If it is supported, return true and |supported_video_codecs| and // If it is supported, return true and |supported_video_codecs|,
// |supports_persistent_license| are updated to match what |key_system| // |supports_persistent_license| and |supported_encryption_schemes| are updated
// supports. If not supported, false is returned. // to match what |key_system| supports. If not supported, false is returned.
CONTENT_EXPORT bool IsKeySystemSupported( CONTENT_EXPORT bool IsKeySystemSupported(
const std::string& key_system, const std::string& key_system,
std::vector<media::VideoCodec>* supported_video_codecs, std::vector<media::VideoCodec>* supported_video_codecs,
bool* supports_persistent_license); bool* supports_persistent_license,
std::vector<media::EncryptionMode>* supported_encryption_schemes);
} // namespace content } // namespace content
......
...@@ -9,14 +9,16 @@ import "media/mojo/interfaces/media_types.mojom"; ...@@ -9,14 +9,16 @@ import "media/mojo/interfaces/media_types.mojom";
interface KeySystemSupport { interface KeySystemSupport {
// Query to determine if the browser supports the key system |key_system|. // Query to determine if the browser supports the key system |key_system|.
// If supported, |is_supported| = true and the remaining properties indicate // If supported, |is_supported| = true and the remaining properties indicate
// the codecs supported and if the key system supports persistent licenses. // the codecs supported, if the key system supports persistent licenses, and
// KeySystemSupport implementation is in the browser process, as it maintains // the set of encryption schemes supported. KeySystemSupport implementation
// the list of installed key systems. Clients run in the renderer process. // is in the browser process, as it maintains the list of installed key
// systems. Clients run in the renderer process.
// TODO(crbug.com/796725) Find a way to include profiles and levels for // TODO(crbug.com/796725) Find a way to include profiles and levels for
// |supported_video_codecs|. // |supported_video_codecs|.
[Sync] [Sync]
IsKeySystemSupported(string key_system) IsKeySystemSupported(string key_system)
=> (bool is_supported, => (bool is_supported,
array<VideoCodec> supported_video_codecs, array<VideoCodec> supported_video_codecs,
bool supports_persistent_license); bool supports_persistent_license,
array<EncryptionMode> supported_encryption_schemes);
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment