1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/media/cdm_registry_impl.h"
6
7 #include <algorithm>
8 #include <string>
9 #include <vector>
10
11 #include "base/base_paths.h"
12 #include "base/containers/flat_set.h"
13 #include "base/files/file_path.h"
14 #include "base/strings/string_split.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/token.h"
18 #include "base/version.h"
19 #include "content/public/common/cdm_info.h"
20 #include "media/base/video_codecs.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22
23 namespace content {
24
25 namespace {
26
27 using VideoCodec = media::VideoCodec;
28 using EncryptionScheme = media::EncryptionScheme;
29 using CdmSessionType = media::CdmSessionType;
30
31 const char kTestCdmName[] = "Test CDM";
32 const char kAlternateCdmName[] = "Alternate CDM";
33 const base::Token kTestCdmGuid{1234, 5678};
34 const char kTestPath[] = "/aa/bb";
35 const char kVersion1[] = "1.1.1.1";
36 const char kVersion2[] = "1.1.1.2";
37 const char kTestKeySystem[] = "com.example.somesystem";
38 const char kTestFileSystemId[] = "file_system_id";
39
40 // Helper function to compare a STL container to an initializer_list.
41 template <typename Container, typename T>
StlEquals(const Container a,std::initializer_list<T> b)42 bool StlEquals(const Container a, std::initializer_list<T> b) {
43 return a == Container(b);
44 }
45
46 #define EXPECT_STL_EQ(a, ...) \
47 do { \
48 EXPECT_TRUE(StlEquals(a, {__VA_ARGS__})); \
49 } while (false)
50
51 #define EXPECT_VIDEO_CODECS(...) \
52 EXPECT_STL_EQ(cdm.capability.video_codecs, __VA_ARGS__)
53
54 #define EXPECT_ENCRYPTION_SCHEMES(...) \
55 EXPECT_STL_EQ(cdm.capability.encryption_schemes, __VA_ARGS__)
56
57 #define EXPECT_SESSION_TYPES(...) \
58 EXPECT_STL_EQ(cdm.capability.session_types, __VA_ARGS__)
59
60 } // namespace
61
62 // For simplicity and to make failures easier to diagnose, this test uses
63 // std::string instead of base::FilePath and std::vector<std::string>.
64 class CdmRegistryImplTest : public testing::Test {
65 public:
CdmRegistryImplTest()66 CdmRegistryImplTest() {}
~CdmRegistryImplTest()67 ~CdmRegistryImplTest() override {}
68
69 protected:
GetTestCdmInfo()70 CdmInfo GetTestCdmInfo() {
71 return CdmInfo(
72 kTestCdmName, kTestCdmGuid, base::Version(kVersion1),
73 base::FilePath::FromUTF8Unsafe(kTestPath), kTestFileSystemId,
74 CdmCapability(
75 {media::kCodecVP8, media::kCodecVP9}, {EncryptionScheme::kCenc},
76 {CdmSessionType::kTemporary, CdmSessionType::kPersistentLicense}),
77 kTestKeySystem, /*supports_sub_key_systems=*/true);
78 }
79
Register(CdmInfo cdm_info)80 void Register(CdmInfo cdm_info) {
81 cdm_registry_.RegisterCdm(std::move(cdm_info));
82 }
83
IsRegistered(const std::string & name,const std::string & version)84 bool IsRegistered(const std::string& name, const std::string& version) {
85 for (const auto& cdm : cdm_registry_.GetAllRegisteredCdms()) {
86 if (cdm.name == name && cdm.version.GetString() == version)
87 return true;
88 }
89 return false;
90 }
91
GetVersions(const base::Token & guid)92 std::vector<std::string> GetVersions(const base::Token& guid) {
93 std::vector<std::string> versions;
94 for (const auto& cdm : cdm_registry_.GetAllRegisteredCdms()) {
95 if (cdm.guid == guid)
96 versions.push_back(cdm.version.GetString());
97 }
98 return versions;
99 }
100
101 protected:
102 CdmRegistryImpl cdm_registry_;
103 };
104
TEST_F(CdmRegistryImplTest,Register)105 TEST_F(CdmRegistryImplTest, Register) {
106 Register(GetTestCdmInfo());
107
108 auto cdms = cdm_registry_.GetAllRegisteredCdms();
109 ASSERT_EQ(1u, cdms.size());
110 CdmInfo cdm = cdms[0];
111 EXPECT_EQ(kTestCdmName, cdm.name);
112 EXPECT_EQ(kVersion1, cdm.version.GetString());
113 EXPECT_EQ(kTestPath, cdm.path.MaybeAsASCII());
114 EXPECT_EQ(kTestFileSystemId, cdm.file_system_id);
115 EXPECT_VIDEO_CODECS(VideoCodec::kCodecVP8, VideoCodec::kCodecVP9);
116 EXPECT_ENCRYPTION_SCHEMES(EncryptionScheme::kCenc);
117 EXPECT_SESSION_TYPES(CdmSessionType::kTemporary,
118 CdmSessionType::kPersistentLicense);
119 EXPECT_EQ(kTestKeySystem, cdm.supported_key_system);
120 EXPECT_TRUE(cdm.supports_sub_key_systems);
121 }
122
TEST_F(CdmRegistryImplTest,ReRegister)123 TEST_F(CdmRegistryImplTest, ReRegister) {
124 auto cdm_info = GetTestCdmInfo();
125 Register(cdm_info);
126 EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
127
128 // Now register same key system with different values.
129 cdm_info.supports_sub_key_systems = false;
130 Register(cdm_info);
131
132 EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
133 }
134
TEST_F(CdmRegistryImplTest,MultipleVersions)135 TEST_F(CdmRegistryImplTest, MultipleVersions) {
136 auto cdm_info = GetTestCdmInfo();
137 Register(cdm_info);
138 cdm_info.version = base::Version(kVersion2);
139 Register(cdm_info);
140
141 EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
142 EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion2));
143 }
144
TEST_F(CdmRegistryImplTest,NewVersionInsertedLast)145 TEST_F(CdmRegistryImplTest, NewVersionInsertedLast) {
146 auto cdm_info = GetTestCdmInfo();
147 Register(cdm_info);
148 cdm_info.version = base::Version(kVersion2);
149 Register(cdm_info);
150
151 const std::vector<std::string> versions = GetVersions(kTestCdmGuid);
152 EXPECT_EQ(2u, versions.size());
153 EXPECT_EQ(kVersion1, versions[0]);
154 EXPECT_EQ(kVersion2, versions[1]);
155 }
156
TEST_F(CdmRegistryImplTest,DifferentNames)157 TEST_F(CdmRegistryImplTest, DifferentNames) {
158 auto cdm_info = GetTestCdmInfo();
159 Register(cdm_info);
160 cdm_info.name = kAlternateCdmName;
161 Register(cdm_info);
162
163 EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
164 EXPECT_TRUE(IsRegistered(kAlternateCdmName, kVersion1));
165 }
166
TEST_F(CdmRegistryImplTest,SupportedEncryptionSchemes)167 TEST_F(CdmRegistryImplTest, SupportedEncryptionSchemes) {
168 auto cdm_info = GetTestCdmInfo();
169 cdm_info.capability.encryption_schemes = {EncryptionScheme::kCenc,
170 EncryptionScheme::kCbcs};
171 Register(cdm_info);
172
173 std::vector<CdmInfo> cdms = cdm_registry_.GetAllRegisteredCdms();
174 ASSERT_EQ(1u, cdms.size());
175 const CdmInfo& cdm = cdms[0];
176 EXPECT_ENCRYPTION_SCHEMES(EncryptionScheme::kCenc, EncryptionScheme::kCbcs);
177 }
178
179 } // namespace content
180