Add version to CdmCapability
As several CDMs only compute the supported capabilities on first use, add `version` to CdmCapability so that the version can be determined when the other capabilities are determined. Leaving `version` on CdmInfo as some CDMs that are component updated get their version when updated. However, if the version is specified on both CdmInfo and CdmCapability, then the one specified with CdmCapability is used. Bug: 368659592 Test: Updated tests pass Change-Id: I1aed694ad383956be59c8f065f264658e1d06595 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6230125 Reviewed-by: Xiaohan Wang <xhwang@chromium.org> Commit-Queue: John Rummell <jrummell@chromium.org> Reviewed-by: Yuchen Liu <yucliu@chromium.org> Reviewed-by: Nasko Oskov <nasko@chromium.org> Reviewed-by: Joshua Pawlicki <waffles@chromium.org> Cr-Commit-Position: refs/heads/main@{#1417602}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
3b7ee977a9
commit
2f059abe51
chrome
browser
component_updater
common
chromecast/common
components/cdm/common
content
browser
media
common
media
public
common
media
@ -96,7 +96,7 @@ void RegisterWidevineCdmWithChrome(const base::Version& cdm_version,
|
||||
content::CdmInfo cdm_info(
|
||||
kWidevineKeySystem, content::CdmInfo::Robustness::kSoftwareSecure,
|
||||
std::move(capability), /*supports_sub_key_systems=*/false,
|
||||
kWidevineCdmDisplayName, kWidevineCdmType, cdm_version, cdm_path);
|
||||
kWidevineCdmDisplayName, kWidevineCdmType, cdm_path);
|
||||
content::CdmRegistry::GetInstance()->RegisterCdm(cdm_info);
|
||||
}
|
||||
#endif // !BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS)
|
||||
@ -117,10 +117,9 @@ bool UpdateHintFile(const base::FilePath& cdm_base_path) {
|
||||
|
||||
auto manifest_path =
|
||||
bundled_cdm_file_path.Append(FILE_PATH_LITERAL("manifest.json"));
|
||||
base::Version version;
|
||||
media::CdmCapability capability;
|
||||
if (ParseCdmManifestFromPath(manifest_path, &version, &capability)) {
|
||||
bundled_version = version;
|
||||
if (ParseCdmManifestFromPath(manifest_path, &capability)) {
|
||||
bundled_version = capability.version;
|
||||
}
|
||||
#endif // BUILDFLAG(BUNDLE_WIDEVINE_CDM)
|
||||
|
||||
@ -182,9 +181,8 @@ void VerifyManifestAndUpdateHintFile(const std::string& image_dir) {
|
||||
// Image loaded, so check that the manifest is valid.
|
||||
base::FilePath mount_point(image_dir);
|
||||
auto manifest_path = mount_point.Append(FILE_PATH_LITERAL("manifest.json"));
|
||||
base::Version version;
|
||||
media::CdmCapability capability;
|
||||
if (!ParseCdmManifestFromPath(manifest_path, &version, &capability)) {
|
||||
if (!ParseCdmManifestFromPath(manifest_path, &capability)) {
|
||||
VLOG(1) << "Widevine image does not contain expected manifest.";
|
||||
return;
|
||||
}
|
||||
|
@ -56,13 +56,12 @@ using Robustness = content::CdmInfo::Robustness;
|
||||
// Create a CdmInfo for a Widevine CDM, using |version|, |cdm_library_path|, and
|
||||
// |capability|.
|
||||
std::unique_ptr<content::CdmInfo> CreateWidevineCdmInfo(
|
||||
const base::Version& version,
|
||||
const base::FilePath& cdm_library_path,
|
||||
media::CdmCapability capability) {
|
||||
return std::make_unique<content::CdmInfo>(
|
||||
kWidevineKeySystem, Robustness::kSoftwareSecure, std::move(capability),
|
||||
/*supports_sub_key_systems=*/false, kWidevineCdmDisplayName,
|
||||
kWidevineCdmType, version, cdm_library_path);
|
||||
kWidevineCdmType, cdm_library_path);
|
||||
}
|
||||
|
||||
// On desktop Linux and ChromeOS, given |cdm_base_path| that points to a folder
|
||||
@ -82,15 +81,13 @@ std::unique_ptr<content::CdmInfo> CreateCdmInfoFromWidevineDirectory(
|
||||
|
||||
// Manifest should be at the top level.
|
||||
auto manifest_path = cdm_base_path.Append(FILE_PATH_LITERAL("manifest.json"));
|
||||
base::Version version;
|
||||
media::CdmCapability capability;
|
||||
if (!ParseCdmManifestFromPath(manifest_path, &version, &capability)) {
|
||||
if (!ParseCdmManifestFromPath(manifest_path, &capability)) {
|
||||
DLOG(ERROR) << __func__ << " no manifest: " << manifest_path;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return CreateWidevineCdmInfo(version, cdm_library_path,
|
||||
std::move(capability));
|
||||
return CreateWidevineCdmInfo(cdm_library_path, std::move(capability));
|
||||
}
|
||||
#endif // (BUILDFLAG(BUNDLE_WIDEVINE_CDM) ||
|
||||
// BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT)) && (BUILDFLAG(IS_LINUX) ||
|
||||
@ -161,7 +158,7 @@ void AddSoftwareSecureWidevine(std::vector<content::CdmInfo>* cdms) {
|
||||
cdms->emplace_back(
|
||||
kWidevineKeySystem, Robustness::kSoftwareSecure, std::nullopt,
|
||||
/*supports_sub_key_systems=*/false, kWidevineCdmDisplayName,
|
||||
kWidevineCdmType, base::Version(), base::FilePath());
|
||||
kWidevineCdmType, base::FilePath());
|
||||
|
||||
#elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
|
||||
// The Widevine CDM on Linux/ChromeOS needs to be registered (and loaded)
|
||||
@ -204,18 +201,20 @@ void AddSoftwareSecureWidevine(std::vector<content::CdmInfo>* cdms) {
|
||||
|
||||
if (bundled_widevine && !hinted_widevine) {
|
||||
// Only a bundled version is available, so use it.
|
||||
VLOG(1) << "Registering bundled Widevine " << bundled_widevine->version;
|
||||
VLOG(1) << "Registering bundled Widevine "
|
||||
<< bundled_widevine->capability->version;
|
||||
cdms->push_back(*bundled_widevine);
|
||||
} else if (!bundled_widevine && hinted_widevine) {
|
||||
// Only a component updated version is available, so use it.
|
||||
VLOG(1) << "Registering hinted Widevine " << hinted_widevine->version;
|
||||
VLOG(1) << "Registering hinted Widevine "
|
||||
<< hinted_widevine->capability->version;
|
||||
cdms->push_back(*hinted_widevine);
|
||||
} else if (!bundled_widevine && !hinted_widevine) {
|
||||
VLOG(1) << "Widevine enabled but no library found";
|
||||
} else {
|
||||
// Both a bundled CDM and a hinted CDM found, so choose between them.
|
||||
base::Version bundled_version = bundled_widevine->version;
|
||||
base::Version hinted_version = hinted_widevine->version;
|
||||
base::Version bundled_version = bundled_widevine->capability->version;
|
||||
base::Version hinted_version = hinted_widevine->capability->version;
|
||||
DVLOG(1) << __func__ << " bundled: " << bundled_version;
|
||||
DVLOG(1) << __func__ << " hinted: " << hinted_version;
|
||||
|
||||
@ -249,7 +248,7 @@ void AddHardwareSecureWidevine(std::vector<content::CdmInfo>* cdms) {
|
||||
cdms->emplace_back(
|
||||
kWidevineKeySystem, Robustness::kHardwareSecure, std::nullopt,
|
||||
/*supports_sub_key_systems=*/false, kWidevineCdmDisplayName,
|
||||
kWidevineCdmType, base::Version(), base::FilePath());
|
||||
kWidevineCdmType, base::FilePath());
|
||||
|
||||
#elif BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA)
|
||||
media::CdmCapability capability;
|
||||
@ -312,7 +311,8 @@ void AddExternalClearKey(std::vector<content::CdmInfo>* cdms) {
|
||||
media::CdmCapability capability(
|
||||
{}, {}, {media::EncryptionScheme::kCenc, media::EncryptionScheme::kCbcs},
|
||||
{media::CdmSessionType::kTemporary,
|
||||
media::CdmSessionType::kPersistentLicense});
|
||||
media::CdmSessionType::kPersistentLicense},
|
||||
base::Version("0.1.0.0"));
|
||||
|
||||
// Register media::kExternalClearKeyDifferentCdmTypeTestKeySystem first
|
||||
// separately. Otherwise, it'll be treated as a sub-key-system of normal
|
||||
@ -322,14 +322,13 @@ void AddExternalClearKey(std::vector<content::CdmInfo>* cdms) {
|
||||
media::kExternalClearKeyDifferentCdmTypeTestKeySystem,
|
||||
Robustness::kSoftwareSecure, capability,
|
||||
/*supports_sub_key_systems=*/false, media::kClearKeyCdmDisplayName,
|
||||
media::kClearKeyCdmDifferentCdmType, base::Version("0.1.0.0"),
|
||||
clear_key_cdm_path));
|
||||
media::kClearKeyCdmDifferentCdmType, clear_key_cdm_path));
|
||||
|
||||
cdms->push_back(content::CdmInfo(
|
||||
media::kExternalClearKeyKeySystem, Robustness::kSoftwareSecure,
|
||||
capability,
|
||||
/*supports_sub_key_systems=*/true, media::kClearKeyCdmDisplayName,
|
||||
media::kClearKeyCdmType, base::Version("0.1.0.0"), clear_key_cdm_path));
|
||||
media::kClearKeyCdmType, clear_key_cdm_path));
|
||||
}
|
||||
#endif // BUILDFLAG(ENABLE_LIBRARY_CDMS)
|
||||
|
||||
@ -349,15 +348,14 @@ void AddMediaFoundationClearKey(std::vector<content::CdmInfo>* cdms) {
|
||||
// Supported codecs are hard-coded in ExternalClearKeyKeySystemInfo.
|
||||
media::CdmCapability capability(
|
||||
{}, {}, {media::EncryptionScheme::kCenc, media::EncryptionScheme::kCbcs},
|
||||
{media::CdmSessionType::kTemporary});
|
||||
{media::CdmSessionType::kTemporary}, base::Version("0.1.0.0"));
|
||||
|
||||
cdms->push_back(
|
||||
content::CdmInfo(media::kMediaFoundationClearKeyKeySystem,
|
||||
Robustness::kHardwareSecure, capability,
|
||||
/*supports_sub_key_systems=*/false,
|
||||
media::kMediaFoundationClearKeyCdmDisplayName,
|
||||
media::kMediaFoundationClearKeyCdmType,
|
||||
base::Version("0.1.0.0"), clear_key_cdm_path));
|
||||
cdms->push_back(content::CdmInfo(
|
||||
media::kMediaFoundationClearKeyKeySystem, Robustness::kHardwareSecure,
|
||||
capability,
|
||||
/*supports_sub_key_systems=*/false,
|
||||
media::kMediaFoundationClearKeyCdmDisplayName,
|
||||
media::kMediaFoundationClearKeyCdmType, clear_key_cdm_path));
|
||||
}
|
||||
#endif // BUILDFLAG(IS_WIN)
|
||||
|
||||
|
@ -51,10 +51,9 @@ base::Version GetBundledWidevineVersion() {
|
||||
|
||||
auto manifest_path = cdm_base_path.Append(FILE_PATH_LITERAL("manifest.json"));
|
||||
if (base::PathExists(manifest_path)) {
|
||||
base::Version version;
|
||||
media::CdmCapability capability;
|
||||
if (ParseCdmManifestFromPath(manifest_path, &version, &capability)) {
|
||||
return version;
|
||||
if (ParseCdmManifestFromPath(manifest_path, &capability)) {
|
||||
return capability.version;
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,10 +99,8 @@ void CreateFakeComponentUpdatedWidevine(
|
||||
EXPECT_TRUE(serializer.Serialize(manifest));
|
||||
|
||||
// Verify that the manifest is actually usable.
|
||||
base::Version manifest_version;
|
||||
media::CdmCapability capability;
|
||||
EXPECT_TRUE(ParseCdmManifestFromPath(manifest_path, &manifest_version,
|
||||
&capability));
|
||||
EXPECT_TRUE(ParseCdmManifestFromPath(manifest_path, &capability));
|
||||
|
||||
// Now create a dummy executable. It is in a nested directory, so create the
|
||||
// directory first. Contents don't matter as only its existence is checked.
|
||||
@ -133,7 +130,7 @@ TEST(CdmRegistrationTest, ChooseBundledCdm) {
|
||||
auto cdms = GetSoftwareSecureWidevine();
|
||||
#if BUILDFLAG(BUNDLE_WIDEVINE_CDM)
|
||||
EXPECT_EQ(cdms.size(), 1u);
|
||||
EXPECT_EQ(cdms[0].version, bundled_version);
|
||||
EXPECT_EQ(cdms[0].capability->version, bundled_version);
|
||||
#else
|
||||
EXPECT_EQ(cdms.size(), 0u);
|
||||
#endif // BUILDFLAG(BUNDLE_WIDEVINE_CDM)
|
||||
@ -156,11 +153,11 @@ TEST(CdmRegistrationTest, ChooseComponentUpdatedCdm) {
|
||||
#if BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT)
|
||||
// Component Updated CDM has the higher version so it should be chosen.
|
||||
EXPECT_EQ(cdms.size(), 1u);
|
||||
EXPECT_EQ(cdms[0].version, component_updated_version);
|
||||
EXPECT_EQ(cdms[0].capability->version, component_updated_version);
|
||||
#elif BUILDFLAG(BUNDLE_WIDEVINE_CDM)
|
||||
// No Component Update support but a bundled CDM, so it should be chosen.
|
||||
EXPECT_EQ(cdms.size(), 1u);
|
||||
EXPECT_EQ(cdms[0].version, bundled_version);
|
||||
EXPECT_EQ(cdms[0].capability->version, bundled_version);
|
||||
#else
|
||||
// No CDM available.
|
||||
EXPECT_EQ(cdms.size(), 0u);
|
||||
@ -190,11 +187,11 @@ TEST(CdmRegistrationTest, ChooseDowngradedCdm) {
|
||||
// Even though the Component Updated CDM has the lower version, it should be
|
||||
// chosen. Doesn't matter if there is a bundled CDM or not.
|
||||
EXPECT_EQ(cdms.size(), 1u);
|
||||
EXPECT_EQ(cdms[0].version, component_updated_version);
|
||||
EXPECT_EQ(cdms[0].capability->version, component_updated_version);
|
||||
#elif BUILDFLAG(BUNDLE_WIDEVINE_CDM)
|
||||
// No Component Update support but a bundled CDM, so it should be chosen.
|
||||
EXPECT_EQ(cdms.size(), 1u);
|
||||
EXPECT_EQ(cdms[0].version, bundled_version);
|
||||
EXPECT_EQ(cdms[0].capability->version, bundled_version);
|
||||
#else
|
||||
// No CDM available.
|
||||
EXPECT_EQ(cdms.size(), 0u);
|
||||
@ -237,15 +234,15 @@ TEST(CdmRegistrationTest, ChooseCorrectCdm) {
|
||||
auto cdms = GetSoftwareSecureWidevine();
|
||||
#if BUILDFLAG(BUNDLE_WIDEVINE_CDM) && BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT)
|
||||
EXPECT_EQ(cdms.size(), 1u);
|
||||
EXPECT_EQ(cdms[0].version, versions[c.selected]);
|
||||
EXPECT_EQ(cdms[0].capability->version, versions[c.selected]);
|
||||
#elif BUILDFLAG(BUNDLE_WIDEVINE_CDM)
|
||||
// Only support for bundled CDM, so it will always be returned.
|
||||
EXPECT_EQ(cdms.size(), 1u);
|
||||
EXPECT_EQ(cdms[0].version, versions[c.bundled]);
|
||||
EXPECT_EQ(cdms[0].capability->version, versions[c.bundled]);
|
||||
#elif BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT)
|
||||
// Only support for component updated CDM, so it will always be returned.
|
||||
EXPECT_EQ(cdms.size(), 1u);
|
||||
EXPECT_EQ(cdms[0].version, versions[c.hinted]);
|
||||
EXPECT_EQ(cdms[0].capability->version, versions[c.hinted]);
|
||||
#else
|
||||
EXPECT_EQ(cdms.size(), 0u);
|
||||
#endif
|
||||
|
@ -63,13 +63,12 @@ namespace {
|
||||
#if BUILDFLAG(BUNDLE_WIDEVINE_CDM) && BUILDFLAG(IS_LINUX)
|
||||
// Copied from chrome_content_client.cc
|
||||
std::unique_ptr<content::CdmInfo> CreateWidevineCdmInfo(
|
||||
const base::Version& version,
|
||||
const base::FilePath& cdm_library_path,
|
||||
media::CdmCapability capability) {
|
||||
return std::make_unique<content::CdmInfo>(
|
||||
kWidevineKeySystem, content::CdmInfo::Robustness::kSoftwareSecure,
|
||||
std::move(capability), /*supports_sub_key_systems=*/false,
|
||||
kWidevineCdmDisplayName, kWidevineCdmType, version, cdm_library_path);
|
||||
kWidevineCdmDisplayName, kWidevineCdmType, cdm_library_path);
|
||||
}
|
||||
|
||||
// On desktop Linux, given |cdm_base_path| that points to a folder containing
|
||||
@ -91,13 +90,12 @@ std::unique_ptr<content::CdmInfo> CreateCdmInfoFromWidevineDirectory(
|
||||
|
||||
// Manifest should be at the top level.
|
||||
auto manifest_path = cdm_base_path.Append(FILE_PATH_LITERAL("manifest.json"));
|
||||
base::Version version;
|
||||
media::CdmCapability capability;
|
||||
if (!ParseCdmManifestFromPath(manifest_path, &version, &capability))
|
||||
if (!ParseCdmManifestFromPath(manifest_path, &capability)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return CreateWidevineCdmInfo(version, cdm_library_path,
|
||||
std::move(capability));
|
||||
return CreateWidevineCdmInfo(cdm_library_path, std::move(capability));
|
||||
}
|
||||
|
||||
// This code checks to see if the Widevine CDM was bundled with Chrome. If one
|
||||
|
@ -299,11 +299,11 @@ bool ParseCdmManifest(const base::Value::Dict& manifest,
|
||||
return GetAudioCodecs(manifest, &capability->audio_codecs) &&
|
||||
GetVideoCodecs(manifest, &capability->video_codecs) &&
|
||||
GetEncryptionSchemes(manifest, &capability->encryption_schemes) &&
|
||||
GetSessionTypes(manifest, &capability->session_types);
|
||||
GetSessionTypes(manifest, &capability->session_types) &&
|
||||
GetVersion(manifest, &capability->version);
|
||||
}
|
||||
|
||||
bool ParseCdmManifestFromPath(const base::FilePath& manifest_path,
|
||||
base::Version* version,
|
||||
media::CdmCapability* capability) {
|
||||
JSONFileValueDeserializer deserializer(manifest_path);
|
||||
int error_code;
|
||||
@ -318,6 +318,5 @@ bool ParseCdmManifestFromPath(const base::FilePath& manifest_path,
|
||||
base::Value::Dict& manifest_dict = manifest->GetDict();
|
||||
|
||||
return IsCdmManifestCompatibleWithChrome(manifest_dict) &&
|
||||
GetVersion(manifest_dict, version) &&
|
||||
ParseCdmManifest(manifest_dict, capability);
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
namespace base {
|
||||
class FilePath;
|
||||
class Version;
|
||||
} // namespace base
|
||||
|
||||
namespace media {
|
||||
@ -23,21 +22,21 @@ struct CdmCapability;
|
||||
// updated recently or the user downgrades Chrome.
|
||||
bool IsCdmManifestCompatibleWithChrome(const base::Value::Dict& manifest);
|
||||
|
||||
// Extracts the necessary information from |manifest| and updates |capability|.
|
||||
// Extracts the necessary information from `manifest` and updates `capability`.
|
||||
// Returns true on success, false if there are errors in the manifest.
|
||||
// If this method returns false, |capability| may or may not be updated.
|
||||
// If this method returns false, `capability` may or may not be updated.
|
||||
bool ParseCdmManifest(const base::Value::Dict& manifest,
|
||||
media::CdmCapability* capability);
|
||||
|
||||
// Reads the file |manifest_path| which is assumed to be a CDM manifest and
|
||||
// extracts the necessary information from it to update |version| and
|
||||
// |capability|. This also verifies that the read CDM manifest is compatible
|
||||
// with Chrome (by calling IsCdmManifestCompatibleWithChrome()). Returns true on
|
||||
// Reads the file `manifest_path` which is assumed to be a CDM manifest and
|
||||
// extracts the necessary information from it to update `capability`. All the
|
||||
// fields in `capability` are optional except `version`, which must be
|
||||
// specified. This also verifies that the read CDM manifest is compatible with
|
||||
// Chrome (by calling IsCdmManifestCompatibleWithChrome()). Returns true on
|
||||
// success, false if there are errors in the file or the manifest is not
|
||||
// compatible with this version of Chrome. If this method returns false,
|
||||
// |version| and |capability| may or may not be updated.
|
||||
// `capability` may or may not be updated.
|
||||
bool ParseCdmManifestFromPath(const base::FilePath& manifest_path,
|
||||
base::Version* version,
|
||||
media::CdmCapability* capability);
|
||||
|
||||
#endif // COMPONENTS_CDM_COMMON_CDM_MANIFEST_H_
|
||||
|
@ -51,6 +51,7 @@ constexpr int kSupportedCdmInterfaceVersion =
|
||||
static_assert(media::kSupportedCdmInterfaceVersions[0].enabled,
|
||||
"kSupportedCdmInterfaceVersion is not enabled by default.");
|
||||
constexpr int kSupportedCdmHostVersion = media::kMinSupportedCdmHostVersion;
|
||||
const char kVersion[] = "1.2.3.4";
|
||||
|
||||
// Make a string of the values from 0 up to and including |item|.
|
||||
std::string MakeStringList(int item) {
|
||||
@ -93,6 +94,7 @@ base::Value::Dict DefaultManifest() {
|
||||
base::NumberToString(kSupportedCdmInterfaceVersion));
|
||||
dict.Set(kCdmHostVersionsName,
|
||||
base::NumberToString(kSupportedCdmHostVersion));
|
||||
dict.Set(kCdmVersion, kVersion);
|
||||
return dict;
|
||||
}
|
||||
|
||||
@ -215,7 +217,12 @@ TEST(CdmManifestTest, ValidManifest) {
|
||||
TEST(CdmManifestTest, EmptyManifest) {
|
||||
base::Value::Dict manifest;
|
||||
CdmCapability capability;
|
||||
EXPECT_FALSE(ParseCdmManifest(manifest, &capability));
|
||||
|
||||
// Manifests require a version.
|
||||
manifest.Set(kCdmVersion, kVersion);
|
||||
EXPECT_TRUE(ParseCdmManifest(manifest, &capability));
|
||||
|
||||
CheckVideoCodecs(capability.video_codecs, {});
|
||||
CheckAudioCodecs(capability.audio_codecs, {
|
||||
media::AudioCodec::kOpus,
|
||||
@ -411,22 +418,18 @@ TEST(CdmManifestTest, ManifestSessionTypes) {
|
||||
}
|
||||
|
||||
TEST(CdmManifestTest, FileManifest) {
|
||||
const char kVersion[] = "1.2.3.4";
|
||||
|
||||
base::ScopedTempDir temp_dir;
|
||||
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
|
||||
auto manifest_path = temp_dir.GetPath().AppendASCII("manifest.json");
|
||||
|
||||
// Manifests read from a file also need a version.
|
||||
auto manifest = DefaultManifest();
|
||||
manifest.Set(kCdmVersion, kVersion);
|
||||
WriteManifestToFile(manifest, manifest_path);
|
||||
|
||||
base::Version version;
|
||||
CdmCapability capability;
|
||||
EXPECT_TRUE(ParseCdmManifestFromPath(manifest_path, &version, &capability));
|
||||
EXPECT_TRUE(version.IsValid());
|
||||
EXPECT_EQ(version.GetString(), kVersion);
|
||||
EXPECT_TRUE(ParseCdmManifestFromPath(manifest_path, &capability));
|
||||
EXPECT_TRUE(capability.version.IsValid());
|
||||
EXPECT_EQ(capability.version.GetString(), kVersion);
|
||||
CheckVideoCodecs(capability.video_codecs,
|
||||
{media::VideoCodec::kVP8, media::VideoCodec::kVP9,
|
||||
media::VideoCodec::kAV1});
|
||||
@ -444,11 +447,11 @@ TEST(CdmManifestTest, FileManifestNoVersion) {
|
||||
auto manifest_path = temp_dir.GetPath().AppendASCII("manifest.json");
|
||||
|
||||
auto manifest = DefaultManifest();
|
||||
manifest.Remove(kCdmVersion);
|
||||
WriteManifestToFile(manifest, manifest_path);
|
||||
|
||||
base::Version version;
|
||||
CdmCapability capability;
|
||||
EXPECT_FALSE(ParseCdmManifestFromPath(manifest_path, &version, &capability));
|
||||
EXPECT_FALSE(ParseCdmManifestFromPath(manifest_path, &capability));
|
||||
}
|
||||
|
||||
TEST(CdmManifestTest, FileManifestBadVersion) {
|
||||
@ -460,9 +463,8 @@ TEST(CdmManifestTest, FileManifestBadVersion) {
|
||||
manifest.Set(kCdmVersion, "bad version");
|
||||
WriteManifestToFile(manifest, manifest_path);
|
||||
|
||||
base::Version version;
|
||||
CdmCapability capability;
|
||||
EXPECT_FALSE(ParseCdmManifestFromPath(manifest_path, &version, &capability));
|
||||
EXPECT_FALSE(ParseCdmManifestFromPath(manifest_path, &capability));
|
||||
}
|
||||
|
||||
TEST(CdmManifestTest, FileManifestDoesNotExist) {
|
||||
@ -470,9 +472,8 @@ TEST(CdmManifestTest, FileManifestDoesNotExist) {
|
||||
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
|
||||
auto manifest_path = temp_dir.GetPath().AppendASCII("manifest.json");
|
||||
|
||||
base::Version version;
|
||||
CdmCapability capability;
|
||||
EXPECT_FALSE(ParseCdmManifestFromPath(manifest_path, &version, &capability));
|
||||
EXPECT_FALSE(ParseCdmManifestFromPath(manifest_path, &capability));
|
||||
}
|
||||
|
||||
TEST(CdmManifestTest, FileManifestEmpty) {
|
||||
@ -483,9 +484,8 @@ TEST(CdmManifestTest, FileManifestEmpty) {
|
||||
base::Value::Dict manifest;
|
||||
WriteManifestToFile(manifest, manifest_path);
|
||||
|
||||
base::Version version;
|
||||
CdmCapability capability;
|
||||
EXPECT_FALSE(ParseCdmManifestFromPath(manifest_path, &version, &capability));
|
||||
EXPECT_FALSE(ParseCdmManifestFromPath(manifest_path, &capability));
|
||||
}
|
||||
|
||||
TEST(CdmManifestTest, FileManifestLite) {
|
||||
@ -505,9 +505,8 @@ TEST(CdmManifestTest, FileManifestLite) {
|
||||
base::NumberToString(kSupportedCdmHostVersion));
|
||||
WriteManifestToFile(manifest, manifest_path);
|
||||
|
||||
base::Version version;
|
||||
CdmCapability capability;
|
||||
EXPECT_TRUE(ParseCdmManifestFromPath(manifest_path, &version, &capability));
|
||||
EXPECT_TRUE(ParseCdmManifestFromPath(manifest_path, &capability));
|
||||
CheckVideoCodecs(capability.video_codecs, {});
|
||||
CheckEncryptionSchemes(capability.encryption_schemes,
|
||||
{media::EncryptionScheme::kCenc});
|
||||
@ -523,7 +522,6 @@ TEST(CdmManifestTest, FileManifestNotDictionary) {
|
||||
base::Value manifest("not a dictionary");
|
||||
WriteManifestToFile(manifest, manifest_path);
|
||||
|
||||
base::Version version;
|
||||
CdmCapability capability;
|
||||
EXPECT_FALSE(ParseCdmManifestFromPath(manifest_path, &version, &capability));
|
||||
EXPECT_FALSE(ParseCdmManifestFromPath(manifest_path, &capability));
|
||||
}
|
||||
|
@ -213,7 +213,8 @@ GetHardwareSecureCapabilityOverriddenFromCommandLine() {
|
||||
// on 'cbcs' not being supported.
|
||||
return media::CdmCapability(std::move(audio_codecs), std::move(video_codecs),
|
||||
{media::EncryptionScheme::kCenc},
|
||||
{media::CdmSessionType::kTemporary});
|
||||
{media::CdmSessionType::kTemporary},
|
||||
base::Version("0.1.0.0"));
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
|
@ -147,21 +147,22 @@ class CdmRegistryImplTest : public testing::Test {
|
||||
{media::AudioCodec::kVorbis},
|
||||
{{media::VideoCodec::kVP8, {}}, {media::VideoCodec::kVP9, {}}},
|
||||
{EncryptionScheme::kCenc},
|
||||
{CdmSessionType::kTemporary, CdmSessionType::kPersistentLicense});
|
||||
{CdmSessionType::kTemporary, CdmSessionType::kPersistentLicense},
|
||||
base::Version(kVersion1));
|
||||
}
|
||||
|
||||
media::CdmCapability GetOtherCdmCapability() {
|
||||
return media::CdmCapability(
|
||||
{media::AudioCodec::kVorbis}, {{media::VideoCodec::kVP9, {}}},
|
||||
{EncryptionScheme::kCbcs}, {CdmSessionType::kTemporary});
|
||||
{EncryptionScheme::kCbcs}, {CdmSessionType::kTemporary},
|
||||
base::Version(kVersion1));
|
||||
}
|
||||
|
||||
CdmInfo GetTestCdmInfo() {
|
||||
return CdmInfo(kTestKeySystem, CdmInfo::Robustness::kSoftwareSecure,
|
||||
GetTestCdmCapability(),
|
||||
/*supports_sub_key_systems=*/true, kTestCdmName,
|
||||
kTestCdmType, base::Version(kVersion1),
|
||||
base::FilePath::FromUTF8Unsafe(kTestPath));
|
||||
kTestCdmType, base::FilePath::FromUTF8Unsafe(kTestPath));
|
||||
}
|
||||
|
||||
void Register(CdmInfo cdm_info) {
|
||||
@ -173,8 +174,7 @@ class CdmRegistryImplTest : public testing::Test {
|
||||
Robustness robustness = Robustness::kSoftwareSecure) {
|
||||
Register(CdmInfo(key_system, robustness, std::move(capability),
|
||||
/*supports_sub_key_systems=*/true, kTestCdmName,
|
||||
kTestCdmType, base::Version(kVersion1),
|
||||
base::FilePath::FromUTF8Unsafe(kTestPath)));
|
||||
kTestCdmType, base::FilePath::FromUTF8Unsafe(kTestPath)));
|
||||
}
|
||||
|
||||
void RegisterForLazySoftwareSecureInitialization() {
|
||||
@ -199,7 +199,7 @@ class CdmRegistryImplTest : public testing::Test {
|
||||
|
||||
bool IsRegistered(const std::string& name, const std::string& version) {
|
||||
for (const auto& cdm : cdm_registry_.GetRegisteredCdms()) {
|
||||
if (cdm.name == name && cdm.version.GetString() == version) {
|
||||
if (cdm.name == name && cdm.capability->version.GetString() == version) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -210,7 +210,7 @@ class CdmRegistryImplTest : public testing::Test {
|
||||
std::vector<std::string> versions;
|
||||
for (const auto& cdm : cdm_registry_.GetRegisteredCdms()) {
|
||||
if (cdm.type == cdm_type) {
|
||||
versions.push_back(cdm.version.GetString());
|
||||
versions.push_back(cdm.capability->version.GetString());
|
||||
}
|
||||
}
|
||||
return versions;
|
||||
@ -280,7 +280,7 @@ TEST_F(CdmRegistryImplTest, Register) {
|
||||
ASSERT_EQ(1u, cdms.size());
|
||||
CdmInfo cdm = cdms[0];
|
||||
EXPECT_EQ(kTestCdmName, cdm.name);
|
||||
EXPECT_EQ(kVersion1, cdm.version.GetString());
|
||||
EXPECT_EQ(kVersion1, cdm.capability->version.GetString());
|
||||
EXPECT_EQ(kTestPath, cdm.path.MaybeAsASCII());
|
||||
EXPECT_EQ(kTestCdmType, cdm.type);
|
||||
EXPECT_AUDIO_CODECS(AudioCodec::kVorbis);
|
||||
@ -308,7 +308,7 @@ TEST_F(CdmRegistryImplTest, ReRegister) {
|
||||
TEST_F(CdmRegistryImplTest, MultipleVersions) {
|
||||
auto cdm_info = GetTestCdmInfo();
|
||||
Register(cdm_info);
|
||||
cdm_info.version = base::Version(kVersion2);
|
||||
cdm_info.capability->version = base::Version(kVersion2);
|
||||
Register(cdm_info);
|
||||
|
||||
EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
|
||||
@ -317,13 +317,13 @@ TEST_F(CdmRegistryImplTest, MultipleVersions) {
|
||||
// The first inserted CdmInfo takes effect.
|
||||
auto result = cdm_registry_.GetCdmInfo(kTestKeySystem,
|
||||
CdmInfo::Robustness::kSoftwareSecure);
|
||||
ASSERT_EQ(result->version, base::Version(kVersion1));
|
||||
ASSERT_EQ(result->capability->version, base::Version(kVersion1));
|
||||
}
|
||||
|
||||
TEST_F(CdmRegistryImplTest, NewVersionInsertedLast) {
|
||||
auto cdm_info = GetTestCdmInfo();
|
||||
Register(cdm_info);
|
||||
cdm_info.version = base::Version(kVersion2);
|
||||
cdm_info.capability->version = base::Version(kVersion2);
|
||||
Register(cdm_info);
|
||||
|
||||
const std::vector<std::string> versions = GetVersions(kTestCdmType);
|
||||
@ -349,7 +349,8 @@ TEST_F(CdmRegistryImplTest, Profiles) {
|
||||
{{VideoCodec::kVP9,
|
||||
media::VideoCodecInfo({media::VP9PROFILE_PROFILE0,
|
||||
media::VP9PROFILE_PROFILE2})}},
|
||||
{EncryptionScheme::kCenc}, {CdmSessionType::kTemporary}));
|
||||
{EncryptionScheme::kCenc}, {CdmSessionType::kTemporary},
|
||||
base::Version(kVersion1)));
|
||||
auto cdm_info = cdm_registry_.GetCdmInfo(
|
||||
kTestKeySystem, CdmInfo::Robustness::kSoftwareSecure);
|
||||
CdmInfo& cdm = *cdm_info;
|
||||
@ -385,7 +386,7 @@ TEST_F(CdmRegistryImplTest, GetCdmInfo_Success) {
|
||||
const CdmInfo& cdm = *cdm_info;
|
||||
|
||||
EXPECT_EQ(kTestCdmName, cdm.name);
|
||||
EXPECT_EQ(kVersion1, cdm.version.GetString());
|
||||
EXPECT_EQ(kVersion1, cdm.capability->version.GetString());
|
||||
EXPECT_EQ(kTestPath, cdm.path.MaybeAsASCII());
|
||||
EXPECT_EQ(kTestCdmType, cdm.type);
|
||||
EXPECT_VIDEO_CODECS(VideoCodec::kVP8, VideoCodec::kVP9);
|
||||
|
@ -78,7 +78,8 @@ CdmCapability TestCdmCapability() {
|
||||
return CdmCapability(
|
||||
{AudioCodec::kVorbis}, {{VideoCodec::kVP8, {}}, {VideoCodec::kVP9, {}}},
|
||||
{EncryptionScheme::kCenc, EncryptionScheme::kCbcs},
|
||||
{CdmSessionType::kTemporary, CdmSessionType::kPersistentLicense});
|
||||
{CdmSessionType::kTemporary, CdmSessionType::kPersistentLicense},
|
||||
base::Version("1.2.3.4"));
|
||||
}
|
||||
|
||||
KeySystemCapabilities TestKeySystemCapabilities(
|
||||
|
@ -115,7 +115,13 @@ base::Value::Dict CdmInfoToDict(const CdmInfo& cdm_info) {
|
||||
dict.Set("status", GetCdmInfoCapabilityStatusName(cdm_info.status));
|
||||
|
||||
if (cdm_info.capability) {
|
||||
dict.Set("capability", CdmCapabilityToDict(cdm_info.capability.value()));
|
||||
auto capability = cdm_info.capability.value();
|
||||
dict.Set("capability", CdmCapabilityToDict(capability));
|
||||
if (capability.version.IsValid()) {
|
||||
// If version is specified, it overrides what may have been set in
|
||||
// `cdm_info.version`.
|
||||
dict.Set("version", capability.version.GetString());
|
||||
}
|
||||
} else {
|
||||
// This could happen if hardware secure capabilities are overridden or
|
||||
// hardware video decode is disabled from command line.
|
||||
|
@ -31,6 +31,22 @@ CdmInfo::CdmInfo(const std::string& key_system,
|
||||
this->status = Status::kUninitialized;
|
||||
}
|
||||
|
||||
CdmInfo::CdmInfo(const std::string& key_system,
|
||||
Robustness robustness,
|
||||
std::optional<media::CdmCapability> capability,
|
||||
bool supports_sub_key_systems,
|
||||
const std::string& name,
|
||||
const media::CdmType& type,
|
||||
const base::FilePath& path)
|
||||
: CdmInfo(key_system,
|
||||
robustness,
|
||||
std::move(capability),
|
||||
supports_sub_key_systems,
|
||||
name,
|
||||
type,
|
||||
base::Version(),
|
||||
path) {}
|
||||
|
||||
CdmInfo::CdmInfo(const std::string& key_system,
|
||||
Robustness robustness,
|
||||
std::optional<media::CdmCapability> capability,
|
||||
|
@ -53,6 +53,8 @@ struct CONTENT_EXPORT CdmInfo {
|
||||
};
|
||||
|
||||
// If `capability` is nullopt, the `capability` will be lazy initialized.
|
||||
// Note that `version` will be overridden by the version in `capability` to
|
||||
// allow for version determination during lazy initialization.
|
||||
CdmInfo(const std::string& key_system,
|
||||
Robustness robustness,
|
||||
std::optional<media::CdmCapability> capability,
|
||||
@ -61,6 +63,13 @@ struct CONTENT_EXPORT CdmInfo {
|
||||
const media::CdmType& type,
|
||||
const base::Version& version,
|
||||
const base::FilePath& path);
|
||||
CdmInfo(const std::string& key_system,
|
||||
Robustness robustness,
|
||||
std::optional<media::CdmCapability> capability,
|
||||
bool supports_sub_key_systems,
|
||||
const std::string& name,
|
||||
const media::CdmType& type,
|
||||
const base::FilePath& path);
|
||||
CdmInfo(const std::string& key_system,
|
||||
Robustness robustness,
|
||||
std::optional<media::CdmCapability> capability,
|
||||
|
@ -35,11 +35,13 @@ CdmCapability::CdmCapability(
|
||||
base::flat_set<AudioCodec> audio_codecs,
|
||||
VideoCodecMap video_codecs,
|
||||
base::flat_set<EncryptionScheme> encryption_schemes,
|
||||
base::flat_set<CdmSessionType> session_types)
|
||||
base::flat_set<CdmSessionType> session_types,
|
||||
base::Version version)
|
||||
: audio_codecs(std::move(audio_codecs)),
|
||||
video_codecs(std::move(video_codecs)),
|
||||
encryption_schemes(std::move(encryption_schemes)),
|
||||
session_types(std::move(session_types)) {}
|
||||
session_types(std::move(session_types)),
|
||||
version(std::move(version)) {}
|
||||
|
||||
CdmCapability::CdmCapability(const CdmCapability& other) = default;
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "base/containers/flat_set.h"
|
||||
#include "base/functional/callback.h"
|
||||
#include "base/types/expected.h"
|
||||
#include "base/version.h"
|
||||
#include "media/base/audio_codecs.h"
|
||||
#include "media/base/content_decryption_module.h"
|
||||
#include "media/base/encryption_scheme.h"
|
||||
@ -54,7 +55,8 @@ struct MEDIA_EXPORT CdmCapability {
|
||||
CdmCapability(base::flat_set<AudioCodec> audio_codecs,
|
||||
VideoCodecMap video_codecs,
|
||||
base::flat_set<EncryptionScheme> encryption_schemes,
|
||||
base::flat_set<CdmSessionType> session_types);
|
||||
base::flat_set<CdmSessionType> session_types,
|
||||
base::Version version);
|
||||
CdmCapability(const CdmCapability& other);
|
||||
~CdmCapability();
|
||||
|
||||
@ -73,6 +75,9 @@ struct MEDIA_EXPORT CdmCapability {
|
||||
|
||||
// List of session types supported by the CDM.
|
||||
base::flat_set<CdmSessionType> session_types;
|
||||
|
||||
// Version of the CDM. May be empty if the version is not known.
|
||||
base::Version version;
|
||||
};
|
||||
|
||||
bool MEDIA_EXPORT operator==(const CdmCapability& lhs,
|
||||
|
@ -55,11 +55,17 @@ bool StructTraits<media::mojom::CdmCapabilityDataView, media::CdmCapability>::
|
||||
if (!input.ReadSessionTypes(&session_types))
|
||||
return false;
|
||||
|
||||
base::Version version;
|
||||
if (!input.ReadVersion(&version)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// |encryption_schemes|, |session_types| and |audio_codecs| are converted
|
||||
// to a base::flat_map implicitly.
|
||||
*output = media::CdmCapability(
|
||||
std::move(audio_codecs), std::move(video_codecs),
|
||||
std::move(encryption_schemes), std::move(session_types));
|
||||
*output =
|
||||
media::CdmCapability(std::move(audio_codecs), std::move(video_codecs),
|
||||
std::move(encryption_schemes),
|
||||
std::move(session_types), std::move(version));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define MEDIA_MOJO_MOJOM_CDM_CAPABILITY_MOJOM_TRAITS_H_
|
||||
|
||||
#include "base/containers/flat_set.h"
|
||||
#include "base/version.h"
|
||||
#include "media/base/audio_codecs.h"
|
||||
#include "media/base/cdm_capability.h"
|
||||
#include "media/base/content_decryption_module.h"
|
||||
@ -55,6 +56,11 @@ struct StructTraits<media::mojom::CdmCapabilityDataView, media::CdmCapability> {
|
||||
return input.session_types;
|
||||
}
|
||||
|
||||
// CDM version.
|
||||
static const base::Version version(const media::CdmCapability& input) {
|
||||
return input.version;
|
||||
}
|
||||
|
||||
static bool Read(media::mojom::CdmCapabilityDataView input,
|
||||
media::CdmCapability* output);
|
||||
};
|
||||
|
@ -6,6 +6,7 @@ module media.mojom;
|
||||
|
||||
import "media/mojo/mojom/content_decryption_module.mojom";
|
||||
import "media/mojo/mojom/media_types.mojom";
|
||||
import "mojo/public/mojom/base/version.mojom";
|
||||
|
||||
struct VideoCodecInfo {
|
||||
// Array of VideoCodecProfiles supported. If no profiles for a
|
||||
@ -32,6 +33,7 @@ struct CdmCapability {
|
||||
|
||||
array<EncryptionScheme> encryption_schemes;
|
||||
array<CdmSessionType> session_types;
|
||||
mojo_base.mojom.Version version;
|
||||
};
|
||||
|
||||
// See media::CdmCapabilityQueryStatus
|
||||
|
Reference in New Issue
Block a user