Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(102)

Side by Side Diff: content/renderer/media/crypto/key_systems.cc

Issue 23464005: Explicitly register each key system. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: review feedback Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/media/crypto/key_systems.h" 5 #include "content/renderer/media/crypto/key_systems.h"
6 6
7 #include <map> 7 #include <map>
8 8
9 #include "base/lazy_instance.h" 9 #include "base/lazy_instance.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/strings/string_util.h" 11 #include "base/strings/string_util.h"
12 #include "content/renderer/media/crypto/key_systems_info.h" 12 #include "content/renderer/media/crypto/key_systems_info.h"
13 #include "net/base/mime_util.h" 13 #include "net/base/mime_util.h"
14 #include "third_party/WebKit/public/platform/WebCString.h" 14 #include "third_party/WebKit/public/platform/WebCString.h"
15 #include "third_party/WebKit/public/platform/WebString.h" 15 #include "third_party/WebKit/public/platform/WebString.h"
16 16
17 namespace content { 17 namespace content {
18 18
19 // Convert a WebString to ASCII, falling back on an empty string in the case 19 // Convert a WebString to ASCII, falling back on an empty string in the case
20 // of a non-ASCII string. 20 // of a non-ASCII string.
21 static std::string ToASCIIOrEmpty(const WebKit::WebString& string) { 21 static std::string ToASCIIOrEmpty(const WebKit::WebString& string) {
22 return IsStringASCII(string) ? UTF16ToASCII(string) : std::string(); 22 return IsStringASCII(string) ? UTF16ToASCII(string) : std::string();
23 } 23 }
24 24
25 class KeySystems { 25 class KeySystems {
26 public: 26 public:
27 bool IsSupportedKeySystem(const std::string& key_system); 27 static KeySystems* GetInstance();
28
29 void AddConcreteSupportedKeySystem(
30 const std::string& key_system,
31 bool use_aes_decryptor,
32 #if defined(ENABLE_PEPPER_CDMS)
33 const std::string& pepper_type,
34 #elif defined(OS_ANDROID)
35 const uint8 uuid[16],
36 #endif
37 const std::string& parent_key_system);
38
39 void AddSupportedType(const std::string& key_system,
40 const std::string& mime_type,
41 const std::string& codecs_list);
42
43 bool IsConcreteSupportedKeySystem(const std::string& key_system);
28 44
29 bool IsSupportedKeySystemWithMediaMimeType( 45 bool IsSupportedKeySystemWithMediaMimeType(
30 const std::string& mime_type, 46 const std::string& mime_type,
31 const std::vector<std::string>& codecs, 47 const std::vector<std::string>& codecs,
32 const std::string& key_system); 48 const std::string& key_system);
33 49
50 bool UseAesDecryptor(const std::string& concrete_key_system);
51
52 #if defined(ENABLE_PEPPER_CDMS)
53 std::string GetPepperType(const std::string& concrete_key_system);
54 #elif defined(OS_ANDROID)
55 std::vector<uint8> GetUUID(const std::string& concrete_key_system);
56 #endif
57
34 private: 58 private:
35 friend struct base::DefaultLazyInstanceTraits<KeySystems>; 59 friend struct base::DefaultLazyInstanceTraits<KeySystems>;
36 60
37 typedef base::hash_set<std::string> CodecMappings; 61 typedef base::hash_set<std::string> CodecMappings;
38 typedef std::map<std::string, CodecMappings> MimeTypeMappings; 62 typedef std::map<std::string, CodecMappings> MimeTypeMappings;
39 typedef std::map<std::string, MimeTypeMappings> KeySystemMappings;
40 63
41 KeySystems(); 64 struct KeySystemProperties {
65 KeySystemProperties() : use_aes_decryptor(false) {}
66
67 bool use_aes_decryptor;
68 #if defined(ENABLE_PEPPER_CDMS)
69 std::string pepper_type;
70 #elif defined(OS_ANDROID)
71 std::vector<uint8> uuid;
72 #endif
73 MimeTypeMappings types;
74 };
75
76 typedef std::map<std::string, KeySystemProperties> KeySystemMappings;
77
78 typedef std::map<std::string, std::string> ParentKeySystemMappings;
79
80 KeySystems() {}
42 81
43 bool IsSupportedKeySystemWithContainerAndCodec( 82 bool IsSupportedKeySystemWithContainerAndCodec(
44 const std::string& mime_type, 83 const std::string& mime_type,
45 const std::string& codec, 84 const std::string& codec,
46 const std::string& key_system); 85 const std::string& key_system);
47 86
87 // Map from key system string to capabilities.
48 KeySystemMappings key_system_map_; 88 KeySystemMappings key_system_map_;
49 89
90 // Map from parent key system to the concrete key system that should be used
91 // to represent its capabilities.
92 ParentKeySystemMappings parent_key_system_map_;
93
50 DISALLOW_COPY_AND_ASSIGN(KeySystems); 94 DISALLOW_COPY_AND_ASSIGN(KeySystems);
51 }; 95 };
52 96
53 static base::LazyInstance<KeySystems> g_key_systems = LAZY_INSTANCE_INITIALIZER; 97 static base::LazyInstance<KeySystems> g_key_systems = LAZY_INSTANCE_INITIALIZER;
54 98
55 KeySystems::KeySystems() { 99 KeySystems* KeySystems::GetInstance() {
56 // Initialize the supported media type/key system combinations. 100 KeySystems* key_systems = &g_key_systems.Get();
57 for (int i = 0; i < kNumSupportedFormatKeySystemCombinations; ++i) { 101 // TODO(ddorwin): Call out to ContentClient to register key systems.
58 const MediaFormatAndKeySystem& combination = 102 static bool is_registered = false;
59 kSupportedFormatKeySystemCombinations[i]; 103 if (!is_registered) {
60 std::vector<std::string> mime_type_codecs; 104 is_registered = true; // Prevent reentrancy when Add*() is called.
61 net::ParseCodecString(combination.codecs_list, 105 RegisterKeySystems();
62 &mime_type_codecs, 106 }
63 false); 107 return key_systems;
108 }
64 109
65 CodecMappings codecs; 110 void KeySystems::AddConcreteSupportedKeySystem(
66 for (size_t j = 0; j < mime_type_codecs.size(); ++j) 111 const std::string& key_system,
67 codecs.insert(mime_type_codecs[j]); 112 bool use_aes_decryptor,
68 // Support the MIME type string alone, without codec(s) specified. 113 #if defined(ENABLE_PEPPER_CDMS)
69 codecs.insert(std::string()); 114 const std::string& pepper_type,
115 #elif defined(OS_ANDROID)
116 const uint8 uuid[16],
117 #endif
118 const std::string& parent_key_system) {
119 KeySystemMappings::iterator key_system_iter =
120 key_system_map_.find(key_system);
121 DCHECK(key_system_iter == key_system_map_.end())
122 << "Key system already registered";
70 123
71 // Key systems can be repeated, so there may already be an entry. 124 KeySystemProperties properties;
72 KeySystemMappings::iterator key_system_iter = 125 properties.use_aes_decryptor = use_aes_decryptor;
73 key_system_map_.find(combination.key_system); 126 #if defined(ENABLE_PEPPER_CDMS)
74 if (key_system_iter == key_system_map_.end()) { 127 DCHECK_EQ(use_aes_decryptor, pepper_type.empty());
75 MimeTypeMappings mime_types_map; 128 properties.pepper_type = pepper_type;
76 mime_types_map[combination.mime_type] = codecs; 129 #elif defined(OS_ANDROID)
77 key_system_map_[combination.key_system] = mime_types_map; 130 properties.uuid.assign(uuid, uuid + 16);
78 } else { 131 #endif
79 MimeTypeMappings& mime_types_map = key_system_iter->second; 132 key_system_map_[key_system] = properties;
80 // mime_types_map may not be repeated for a given key system. 133
81 DCHECK(mime_types_map.find(combination.mime_type) == 134 if (!parent_key_system.empty()) {
82 mime_types_map.end()); 135 DCHECK(parent_key_system_map_.find(parent_key_system) ==
83 mime_types_map[combination.mime_type] = codecs; 136 parent_key_system_map_.end())
84 } 137 << "Parent '" << parent_key_system.c_str() << "' already registered.";
138 parent_key_system_map_[parent_key_system] = key_system;
85 } 139 }
86 } 140 }
87 141
88 bool KeySystems::IsSupportedKeySystem(const std::string& key_system) { 142 void KeySystems::AddSupportedType(const std::string& key_system,
89 bool is_supported = key_system_map_.find(key_system) != key_system_map_.end(); 143 const std::string& mime_type,
90 return is_supported && !IsOSIncompatible(key_system); 144 const std::string& codecs_list) {
145 std::vector<std::string> mime_type_codecs;
146 net::ParseCodecString(codecs_list,
147 &mime_type_codecs,
148 false);
149
150 CodecMappings codecs;
151 for (size_t j = 0; j < mime_type_codecs.size(); ++j)
152 codecs.insert(mime_type_codecs[j]);
153 // Support the MIME type string alone, without codec(s) specified.
154 codecs.insert(std::string());
155
156 KeySystemMappings::iterator key_system_iter =
157 key_system_map_.find(key_system);
158 DCHECK(key_system_iter != key_system_map_.end());
159 MimeTypeMappings& mime_types_map = key_system_iter->second.types;
160 // mime_types_map may not be repeated for a given key system.
161 DCHECK(mime_types_map.find(mime_type) == mime_types_map.end());
162 mime_types_map[mime_type] = codecs;
163 }
164
165 bool KeySystems::IsConcreteSupportedKeySystem(const std::string& key_system) {
166 return key_system_map_.find(key_system) != key_system_map_.end();
91 } 167 }
92 168
93 bool KeySystems::IsSupportedKeySystemWithContainerAndCodec( 169 bool KeySystems::IsSupportedKeySystemWithContainerAndCodec(
94 const std::string& mime_type, 170 const std::string& mime_type,
95 const std::string& codec, 171 const std::string& codec,
96 const std::string& key_system) { 172 const std::string& key_system) {
97 KeySystemMappings::const_iterator key_system_iter = 173 KeySystemMappings::const_iterator key_system_iter =
98 key_system_map_.find(key_system); 174 key_system_map_.find(key_system);
99 if (key_system_iter == key_system_map_.end()) 175 if (key_system_iter == key_system_map_.end())
100 return false; 176 return false;
101 177
102 const MimeTypeMappings& mime_types_map = key_system_iter->second; 178 const MimeTypeMappings& mime_types_map = key_system_iter->second.types;
103 MimeTypeMappings::const_iterator mime_iter = mime_types_map.find(mime_type); 179 MimeTypeMappings::const_iterator mime_iter = mime_types_map.find(mime_type);
104 if (mime_iter == mime_types_map.end()) 180 if (mime_iter == mime_types_map.end())
105 return false; 181 return false;
106 182
107 const CodecMappings& codecs = mime_iter->second; 183 const CodecMappings& codecs = mime_iter->second;
108 return (codecs.find(codec) != codecs.end()) && !IsOSIncompatible(key_system); 184 return (codecs.find(codec) != codecs.end());
109 } 185 }
110 186
111 bool KeySystems::IsSupportedKeySystemWithMediaMimeType( 187 bool KeySystems::IsSupportedKeySystemWithMediaMimeType(
112 const std::string& mime_type, 188 const std::string& mime_type,
113 const std::vector<std::string>& codecs, 189 const std::vector<std::string>& codecs,
114 const std::string& key_system) { 190 const std::string& key_system) {
191 // If |key_system| is a parent key_system, use its concrete child.
192 // Otherwise, use |key_system|.
193 std::string concrete_key_system;
194 ParentKeySystemMappings::iterator parent_key_system_iter =
195 parent_key_system_map_.find(key_system);
196 if (parent_key_system_iter != parent_key_system_map_.end())
197 concrete_key_system = parent_key_system_iter->second;
198 else
199 concrete_key_system = key_system;
200
115 // This method is only used by the canPlaytType() path (not the EME methods), 201 // This method is only used by the canPlaytType() path (not the EME methods),
116 // so we check for suppressed key_systems here. 202 // so we check for suppressed key_systems here.
117 if(IsCanPlayTypeSuppressed(key_system)) 203 if(IsCanPlayTypeSuppressed(concrete_key_system))
118 return false; 204 return false;
119 205
120 if (codecs.empty()) 206 if (codecs.empty())
121 return IsSupportedKeySystemWithContainerAndCodec( 207 return IsSupportedKeySystemWithContainerAndCodec(
122 mime_type, std::string(), key_system); 208 mime_type, std::string(), concrete_key_system);
123 209
124 for (size_t i = 0; i < codecs.size(); ++i) { 210 for (size_t i = 0; i < codecs.size(); ++i) {
125 if (!IsSupportedKeySystemWithContainerAndCodec( 211 if (!IsSupportedKeySystemWithContainerAndCodec(
126 mime_type, codecs[i], key_system)) 212 mime_type, codecs[i], concrete_key_system))
127 return false; 213 return false;
128 } 214 }
129 215
130 return true; 216 return true;
131 } 217 }
132 218
133 static inline bool IsConcreteSupportedKeySystem(const std::string& key_system) { 219 bool KeySystems::UseAesDecryptor(const std::string& concrete_key_system) {
134 bool result = g_key_systems.Get().IsSupportedKeySystem(key_system); 220 KeySystemMappings::iterator key_system_iter =
135 // Verify the two "Concrete" lists are in sync. 221 key_system_map_.find(concrete_key_system);
136 DCHECK_EQ(result, IsConcreteKeySystem(key_system)); 222 DCHECK(key_system_iter != key_system_map_.end())
137 return result; 223 << concrete_key_system << " is not a known concrete system";
224 return key_system_iter->second.use_aes_decryptor;
225 }
226
227 #if defined(ENABLE_PEPPER_CDMS)
228 std::string KeySystems::GetPepperType(const std::string& concrete_key_system) {
229 KeySystemMappings::iterator key_system_iter =
230 key_system_map_.find(concrete_key_system);
231 DCHECK(key_system_iter != key_system_map_.end())
232 << concrete_key_system << " is not a known concrete system";
233 const std::string& type = key_system_iter->second.pepper_type;
234 DCHECK(!type.empty()) << concrete_key_system << " is not Pepper-based";
235 return type;
236 }
237 #elif defined(OS_ANDROID)
238 std::vector<uint8> KeySystems::GetUUID(const std::string& concrete_key_system) {
239 KeySystemMappings::iterator key_system_iter =
240 key_system_map_.find(concrete_key_system);
241 DCHECK(key_system_iter != key_system_map_.end())
242 << concrete_key_system << " is not a known concrete system";
243 return key_system_iter->second.uuid;
244 }
245 #endif
246
247 //------------------------------------------------------------------------------
248
249 void AddConcreteSupportedKeySystem(
250 const std::string& key_system,
251 bool use_aes_decryptor,
252 #if defined(ENABLE_PEPPER_CDMS)
253 const std::string& pepper_type,
254 #elif defined(OS_ANDROID)
255 const uint8 uuid[16],
256 #endif
257 const std::string& parent_key_system) {
258 KeySystems::GetInstance()->AddConcreteSupportedKeySystem(key_system,
259 use_aes_decryptor,
260 #if defined(ENABLE_PEPPER_CDMS)
261 pepper_type,
262 #elif defined(OS_ANDROID)
263 uuid,
264 #endif
265 parent_key_system);
266 }
267
268 void AddSupportedType(const std::string& key_system,
269 const std::string& mime_type,
270 const std::string& codecs_list) {
271 KeySystems::GetInstance()->AddSupportedType(key_system,
272 mime_type, codecs_list);
138 } 273 }
139 274
140 bool IsConcreteSupportedKeySystem(const WebKit::WebString& key_system) { 275 bool IsConcreteSupportedKeySystem(const WebKit::WebString& key_system) {
141 return IsConcreteSupportedKeySystem(ToASCIIOrEmpty(key_system)); 276 return KeySystems::GetInstance()->IsConcreteSupportedKeySystem(
277 ToASCIIOrEmpty(key_system));
142 } 278 }
143 279
144 bool IsSupportedKeySystemWithMediaMimeType( 280 bool IsSupportedKeySystemWithMediaMimeType(
145 const std::string& mime_type, 281 const std::string& mime_type,
146 const std::vector<std::string>& codecs, 282 const std::vector<std::string>& codecs,
147 const std::string& key_system) { 283 const std::string& key_system) {
148 std::string concrete_key_system = EnsureConcreteKeySystem(key_system); 284 return KeySystems::GetInstance()->IsSupportedKeySystemWithMediaMimeType(
149 return g_key_systems.Get().IsSupportedKeySystemWithMediaMimeType( 285 mime_type, codecs, key_system);
150 mime_type, codecs, concrete_key_system);
151 } 286 }
152 287
153 std::string KeySystemNameForUMA(const WebKit::WebString& key_system) { 288 std::string KeySystemNameForUMA(const WebKit::WebString& key_system) {
154 return KeySystemNameForUMAInternal(key_system); 289 return KeySystemNameForUMAInternal(key_system);
155 } 290 }
156 291
157 bool CanUseAesDecryptor(const std::string& key_system) { 292 bool CanUseAesDecryptor(const std::string& concrete_key_system) {
158 return CanUseAesDecryptorInternal(key_system); 293 return KeySystems::GetInstance()->UseAesDecryptor(concrete_key_system);
159 } 294 }
160 295
161 #if defined(ENABLE_PEPPER_CDMS) 296 #if defined(ENABLE_PEPPER_CDMS)
162 std::string GetPepperType(const std::string& concrete_key_system) { 297 std::string GetPepperType(const std::string& concrete_key_system) {
163 DCHECK(IsConcreteKeySystem(concrete_key_system)) 298 return KeySystems::GetInstance()->GetPepperType(concrete_key_system);
164 << concrete_key_system << " is not a concrete system";
165 for (int i = 0; i < kNumKeySystemToPepperTypeMapping; ++i) {
166 if (kKeySystemToPepperTypeMapping[i].key_system == concrete_key_system)
167 return kKeySystemToPepperTypeMapping[i].type;
168 }
169
170 return std::string();
171 } 299 }
172 #endif // defined(ENABLE_PEPPER_CDMS) 300 #elif defined(OS_ANDROID)
173
174 #if defined(OS_ANDROID)
175 std::vector<uint8> GetUUID(const std::string& concrete_key_system) { 301 std::vector<uint8> GetUUID(const std::string& concrete_key_system) {
176 DCHECK(IsConcreteKeySystem(concrete_key_system)) 302 return KeySystems::GetInstance()->GetUUID(concrete_key_system);
177 << concrete_key_system << " is not a concrete system";
178 for (int i = 0; i < kNumKeySystemToUUIDMapping; ++i) {
179 if (kKeySystemToUUIDMapping[i].key_system == concrete_key_system)
180 return std::vector<uint8>(kKeySystemToUUIDMapping[i].uuid,
181 kKeySystemToUUIDMapping[i].uuid + 16);
182 }
183 return std::vector<uint8>();
184 } 303 }
185 #endif // defined(OS_ANDROID) 304 #endif
186 305
187 } // namespace content 306 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698