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

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: rebase only 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 // defined(ENABLE_PEPPER_CDMS)
scherkus (not reviewing) 2013/08/29 20:11:47 nit: you can leave off these // comments if you wa
ddorwin 2013/08/29 21:44:04 OOC: Really? Chrome code seems to do it all the ti
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 #endif // defined(ENABLE_PEPPER_CDMS)
55
56 #if defined(OS_ANDROID)
57 std::vector<uint8> GetUUID(const std::string& concrete_key_system);
58 #endif // defined(OS_ANDROID)
59
34 private: 60 private:
35 friend struct base::DefaultLazyInstanceTraits<KeySystems>; 61 friend struct base::DefaultLazyInstanceTraits<KeySystems>;
36 62
37 typedef base::hash_set<std::string> CodecMappings; 63 typedef base::hash_set<std::string> CodecMappings;
xhwang 2013/08/29 21:45:26 Shall we name this a Set?
ddorwin 2013/08/29 22:20:18 Separate CL. I'd like to keep as much similar in t
ddorwin 2013/08/29 23:14:30 Done in new CL.
38 typedef std::map<std::string, CodecMappings> MimeTypeMappings; 64 typedef std::map<std::string, CodecMappings> MimeTypeMappings;
39 typedef std::map<std::string, MimeTypeMappings> KeySystemMappings;
40 65
41 KeySystems(); 66 struct KeySystemProperties {
67 KeySystemProperties() : use_aes_decryptor(false) {}
68
69 bool use_aes_decryptor;
70 #if defined(ENABLE_PEPPER_CDMS)
71 std::string pepper_type;
72 #elif defined(OS_ANDROID)
73 std::vector<uint8> uuid;
74 #endif // defined(ENABLE_PEPPER_CDMS)
75 MimeTypeMappings types;
76 };
77
78 typedef std::map<std::string, KeySystemProperties> KeySystemMappings;
xhwang 2013/08/29 21:45:26 nit: rename to KeySystemPropertiesMappings?
ddorwin 2013/08/29 22:20:18 Ditto.
ddorwin 2013/08/29 23:14:30 Done in new CL.
79
80 typedef std::map<std::string, std::string> ParentKeySystemMappings;
xhwang 2013/08/29 21:45:26 nit: Can we rename all "Mappings" to "Map"?
ddorwin 2013/08/29 22:20:18 Ditto.
ddorwin 2013/08/29 23:14:30 Done in new CL.
81
82 KeySystems() {}
42 83
43 bool IsSupportedKeySystemWithContainerAndCodec( 84 bool IsSupportedKeySystemWithContainerAndCodec(
44 const std::string& mime_type, 85 const std::string& mime_type,
45 const std::string& codec, 86 const std::string& codec,
46 const std::string& key_system); 87 const std::string& key_system);
47 88
89 // Map from key system string to capabilities.
48 KeySystemMappings key_system_map_; 90 KeySystemMappings key_system_map_;
49 91
92 // Map from parent key system to the concrete key system that should be used
93 // to represent its capabilities.
94 ParentKeySystemMappings parent_key_system_map_;
95
50 DISALLOW_COPY_AND_ASSIGN(KeySystems); 96 DISALLOW_COPY_AND_ASSIGN(KeySystems);
51 }; 97 };
52 98
53 static base::LazyInstance<KeySystems> g_key_systems = LAZY_INSTANCE_INITIALIZER; 99 static base::LazyInstance<KeySystems> g_key_systems = LAZY_INSTANCE_INITIALIZER;
54 100
55 KeySystems::KeySystems() { 101 KeySystems* KeySystems::GetInstance() {
56 // Initialize the supported media type/key system combinations. 102 KeySystems* key_systems = &g_key_systems.Get();
57 for (int i = 0; i < kNumSupportedFormatKeySystemCombinations; ++i) { 103 // TODO(ddorwin): Call out to ContentClient to register key systems.
58 const MediaFormatAndKeySystem& combination = 104 static bool is_registered = false;
59 kSupportedFormatKeySystemCombinations[i]; 105 if (!is_registered) {
60 std::vector<std::string> mime_type_codecs; 106 is_registered = true; // Prevent reentrancy when Add*() is called.
61 net::ParseCodecString(combination.codecs_list, 107 RegisterKeySystems();
62 &mime_type_codecs, 108 }
63 false); 109 return key_systems;
110 }
64 111
65 CodecMappings codecs; 112 void KeySystems::AddConcreteSupportedKeySystem(
66 for (size_t j = 0; j < mime_type_codecs.size(); ++j) 113 const std::string& key_system,
67 codecs.insert(mime_type_codecs[j]); 114 bool use_aes_decryptor,
68 // Support the MIME type string alone, without codec(s) specified. 115 #if defined(ENABLE_PEPPER_CDMS)
69 codecs.insert(std::string()); 116 const std::string& pepper_type,
117 #elif defined(OS_ANDROID)
118 const uint8 uuid[16],
119 #endif // defined(ENABLE_PEPPER_CDMS)
120 const std::string& parent_key_system) {
121 KeySystemMappings::iterator key_system_iter =
122 key_system_map_.find(key_system);
123 DCHECK(key_system_iter == key_system_map_.end())
124 << "Key system already registered";
xhwang 2013/08/29 21:45:26 Use IsConcreteSupportedKeySystem()?
ddorwin 2013/08/29 22:20:18 Done.
70 125
71 // Key systems can be repeated, so there may already be an entry. 126 KeySystemProperties properties;
72 KeySystemMappings::iterator key_system_iter = 127 properties.use_aes_decryptor = use_aes_decryptor;
73 key_system_map_.find(combination.key_system); 128 #if defined(ENABLE_PEPPER_CDMS)
74 if (key_system_iter == key_system_map_.end()) { 129 DCHECK_EQ(use_aes_decryptor, pepper_type.empty());
75 MimeTypeMappings mime_types_map; 130 properties.pepper_type = pepper_type;
76 mime_types_map[combination.mime_type] = codecs; 131 #elif defined(OS_ANDROID)
77 key_system_map_[combination.key_system] = mime_types_map; 132 properties.uuid.assign(uuid, uuid + 16);
78 } else { 133 #endif // defined(ENABLE_PEPPER_CDMS)
79 MimeTypeMappings& mime_types_map = key_system_iter->second; 134 key_system_map_[key_system] = properties;
80 // mime_types_map may not be repeated for a given key system. 135
81 DCHECK(mime_types_map.find(combination.mime_type) == 136 if (!parent_key_system.empty()) {
82 mime_types_map.end()); 137 DCHECK(parent_key_system_map_.find(parent_key_system) ==
83 mime_types_map[combination.mime_type] = codecs; 138 parent_key_system_map_.end())
84 } 139 << "Parent '" << parent_key_system.c_str() << "' already registered.";
140 parent_key_system_map_[parent_key_system] = key_system;
85 } 141 }
86 } 142 }
87 143
88 bool KeySystems::IsSupportedKeySystem(const std::string& key_system) { 144 void KeySystems::AddSupportedType(const std::string& key_system,
89 bool is_supported = key_system_map_.find(key_system) != key_system_map_.end(); 145 const std::string& mime_type,
90 return is_supported && !IsOSIncompatible(key_system); 146 const std::string& codecs_list) {
147 std::vector<std::string> mime_type_codecs;
148 net::ParseCodecString(codecs_list,
149 &mime_type_codecs,
150 false);
xhwang 2013/08/29 21:45:26 fit in one line?
ddorwin 2013/08/29 22:20:18 Done.
151
152 CodecMappings codecs;
153 for (size_t j = 0; j < mime_type_codecs.size(); ++j)
154 codecs.insert(mime_type_codecs[j]);
xhwang 2013/08/29 21:45:26 Will CodecMappings codecs(mime_type_codecs.begin(
ddorwin 2013/08/29 22:20:18 Done. Thanks.
155 // Support the MIME type string alone, without codec(s) specified.
156 codecs.insert(std::string());
157
158 KeySystemMappings::iterator key_system_iter =
159 key_system_map_.find(key_system);
160 DCHECK(key_system_iter != key_system_map_.end());
xhwang 2013/08/29 21:45:26 Use IsConcreteSupportedKeySystem()?
ddorwin 2013/08/29 22:20:18 In this case, we need the iter anyway, so this see
161 MimeTypeMappings& mime_types_map = key_system_iter->second.types;
162 // mime_types_map may not be repeated for a given key system.
xhwang 2013/08/29 21:45:26 s/may/must/ ?
ddorwin 2013/08/29 22:20:18 Done.
163 DCHECK(mime_types_map.find(mime_type) == mime_types_map.end());
164 mime_types_map[mime_type] = codecs;
165 }
166
167 bool KeySystems::IsConcreteSupportedKeySystem(const std::string& key_system) {
168 return key_system_map_.find(key_system) != key_system_map_.end();
xhwang 2013/08/29 21:45:26 shall we s/key_system_map_/concrete_key_system_map
ddorwin 2013/08/29 22:20:18 Ditto. (Later)
ddorwin 2013/08/29 23:14:30 Done in new CL.
91 } 169 }
92 170
93 bool KeySystems::IsSupportedKeySystemWithContainerAndCodec( 171 bool KeySystems::IsSupportedKeySystemWithContainerAndCodec(
94 const std::string& mime_type, 172 const std::string& mime_type,
95 const std::string& codec, 173 const std::string& codec,
96 const std::string& key_system) { 174 const std::string& key_system) {
97 KeySystemMappings::const_iterator key_system_iter = 175 KeySystemMappings::const_iterator key_system_iter =
98 key_system_map_.find(key_system); 176 key_system_map_.find(key_system);
99 if (key_system_iter == key_system_map_.end()) 177 if (key_system_iter == key_system_map_.end())
100 return false; 178 return false;
101 179
102 const MimeTypeMappings& mime_types_map = key_system_iter->second; 180 const MimeTypeMappings& mime_types_map = key_system_iter->second.types;
103 MimeTypeMappings::const_iterator mime_iter = mime_types_map.find(mime_type); 181 MimeTypeMappings::const_iterator mime_iter = mime_types_map.find(mime_type);
104 if (mime_iter == mime_types_map.end()) 182 if (mime_iter == mime_types_map.end())
105 return false; 183 return false;
106 184
107 const CodecMappings& codecs = mime_iter->second; 185 const CodecMappings& codecs = mime_iter->second;
108 return (codecs.find(codec) != codecs.end()) && !IsOSIncompatible(key_system); 186 return (codecs.find(codec) != codecs.end());
109 } 187 }
110 188
111 bool KeySystems::IsSupportedKeySystemWithMediaMimeType( 189 bool KeySystems::IsSupportedKeySystemWithMediaMimeType(
112 const std::string& mime_type, 190 const std::string& mime_type,
113 const std::vector<std::string>& codecs, 191 const std::vector<std::string>& codecs,
114 const std::string& key_system) { 192 const std::string& key_system) {
193 // If |key_system| is a parent key_system, use its concrete child.
194 // Otherwise, use |key_system|.
195 std::string concrete_key_system;
196 ParentKeySystemMappings::iterator parent_key_system_iter =
197 parent_key_system_map_.find(key_system);
198 if (parent_key_system_iter != parent_key_system_map_.end())
xhwang 2013/08/29 21:45:26 Wrap this into IsParentKeySystem(key_system)?
ddorwin 2013/08/29 22:20:18 We need the iter anyway.
199 concrete_key_system = parent_key_system_iter->second;
200 else
201 concrete_key_system = key_system;
202
115 // This method is only used by the canPlaytType() path (not the EME methods), 203 // This method is only used by the canPlaytType() path (not the EME methods),
116 // so we check for suppressed key_systems here. 204 // so we check for suppressed key_systems here.
117 if(IsCanPlayTypeSuppressed(key_system)) 205 if(IsCanPlayTypeSuppressed(concrete_key_system))
118 return false; 206 return false;
119 207
120 if (codecs.empty()) 208 if (codecs.empty())
121 return IsSupportedKeySystemWithContainerAndCodec( 209 return IsSupportedKeySystemWithContainerAndCodec(
122 mime_type, std::string(), key_system); 210 mime_type, std::string(), concrete_key_system);
xhwang 2013/08/29 21:45:26 use {} since we have multiple lines in the "if" bl
ddorwin 2013/08/29 22:20:18 Done.
123 211
124 for (size_t i = 0; i < codecs.size(); ++i) { 212 for (size_t i = 0; i < codecs.size(); ++i) {
125 if (!IsSupportedKeySystemWithContainerAndCodec( 213 if (!IsSupportedKeySystemWithContainerAndCodec(
126 mime_type, codecs[i], key_system)) 214 mime_type, codecs[i], concrete_key_system))
127 return false; 215 return false;
xhwang 2013/08/29 21:45:26 use {} around the "if" block
ddorwin 2013/08/29 22:20:18 Done.
128 } 216 }
129 217
130 return true; 218 return true;
131 } 219 }
132 220
133 static inline bool IsConcreteSupportedKeySystem(const std::string& key_system) { 221 bool KeySystems::UseAesDecryptor(const std::string& concrete_key_system) {
134 bool result = g_key_systems.Get().IsSupportedKeySystem(key_system); 222 KeySystemMappings::iterator key_system_iter =
135 // Verify the two "Concrete" lists are in sync. 223 key_system_map_.find(concrete_key_system);
xhwang 2013/08/29 21:45:26 indent
ddorwin 2013/08/29 22:20:18 Done.
136 DCHECK_EQ(result, IsConcreteKeySystem(key_system)); 224 DCHECK(key_system_iter != key_system_map_.end())
137 return result; 225 << concrete_key_system << " is not a known concrete system";
226 return key_system_iter->second.use_aes_decryptor;
227 }
228
229 #if defined(ENABLE_PEPPER_CDMS)
230 std::string KeySystems::GetPepperType(const std::string& concrete_key_system) {
231 KeySystemMappings::iterator key_system_iter =
232 key_system_map_.find(concrete_key_system);
xhwang 2013/08/29 21:45:26 indent
ddorwin 2013/08/29 22:20:18 Done.
233 DCHECK(key_system_iter != key_system_map_.end())
234 << concrete_key_system << " is not a known concrete system";
235 const std::string& type = key_system_iter->second.pepper_type;
236 DCHECK(!type.empty()) << concrete_key_system << " is not Pepper-based";
237 return type;
238 }
239 #endif // defined(ENABLE_PEPPER_CDMS)
240
241 #if defined(OS_ANDROID)
242 std::vector<uint8> KeySystems::GetUUID(const std::string& concrete_key_system) {
243 KeySystemMappings::iterator key_system_iter =
244 key_system_map_.find(concrete_key_system);
xhwang 2013/08/29 21:45:26 ditto
ddorwin 2013/08/29 22:20:18 Done.
245 DCHECK(key_system_iter != key_system_map_.end())
246 << concrete_key_system << " is not a known concrete system";
247 return key_system_iter->second.uuid;
248 }
249 #endif // defined(OS_ANDROID)
250
251 //------------------------------------------------------------------------------
252
253 void AddConcreteSupportedKeySystem(
254 const std::string& key_system,
255 bool use_aes_decryptor,
256 #if defined(ENABLE_PEPPER_CDMS)
257 const std::string& pepper_type,
258 #elif defined(OS_ANDROID)
259 const uint8 uuid[16],
260 #endif
261 const std::string& parent_key_system) {
262 KeySystems::GetInstance()->AddConcreteSupportedKeySystem(key_system,
263 use_aes_decryptor,
264 #if defined(ENABLE_PEPPER_CDMS)
scherkus (not reviewing) 2013/08/29 20:11:47 de-indent this
ddorwin 2013/08/29 21:44:04 Done.
265 pepper_type,
266 #elif defined(OS_ANDROID)
267 uuid,
268 #endif
269 parent_key_system);
270 }
271
272 void AddSupportedType(const std::string& key_system,
273 const std::string& mime_type,
274 const std::string& codecs_list) {
275 KeySystems::GetInstance()->AddSupportedType(key_system,
276 mime_type, codecs_list);
138 } 277 }
139 278
140 bool IsConcreteSupportedKeySystem(const WebKit::WebString& key_system) { 279 bool IsConcreteSupportedKeySystem(const WebKit::WebString& key_system) {
141 return IsConcreteSupportedKeySystem(ToASCIIOrEmpty(key_system)); 280 return KeySystems::GetInstance()->IsConcreteSupportedKeySystem(
281 ToASCIIOrEmpty(key_system));
142 } 282 }
143 283
144 bool IsSupportedKeySystemWithMediaMimeType( 284 bool IsSupportedKeySystemWithMediaMimeType(
145 const std::string& mime_type, 285 const std::string& mime_type,
146 const std::vector<std::string>& codecs, 286 const std::vector<std::string>& codecs,
147 const std::string& key_system) { 287 const std::string& key_system) {
148 std::string concrete_key_system = EnsureConcreteKeySystem(key_system); 288 return KeySystems::GetInstance()->IsSupportedKeySystemWithMediaMimeType(
149 return g_key_systems.Get().IsSupportedKeySystemWithMediaMimeType( 289 mime_type, codecs, key_system);
150 mime_type, codecs, concrete_key_system);
151 } 290 }
152 291
153 std::string KeySystemNameForUMA(const WebKit::WebString& key_system) { 292 std::string KeySystemNameForUMA(const WebKit::WebString& key_system) {
154 return KeySystemNameForUMAInternal(key_system); 293 return KeySystemNameForUMAInternal(key_system);
155 } 294 }
156 295
157 bool CanUseAesDecryptor(const std::string& key_system) { 296 bool CanUseAesDecryptor(const std::string& concrete_key_system) {
158 return CanUseAesDecryptorInternal(key_system); 297 return KeySystems::GetInstance()->UseAesDecryptor(concrete_key_system);
159 } 298 }
160 299
161 #if defined(ENABLE_PEPPER_CDMS) 300 #if defined(ENABLE_PEPPER_CDMS)
162 std::string GetPepperType(const std::string& concrete_key_system) { 301 std::string GetPepperType(const std::string& concrete_key_system) {
163 DCHECK(IsConcreteKeySystem(concrete_key_system)) 302 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 } 303 }
172 #endif // defined(ENABLE_PEPPER_CDMS) 304 #endif // defined(ENABLE_PEPPER_CDMS)
173 305
174 #if defined(OS_ANDROID) 306 #if defined(OS_ANDROID)
175 std::vector<uint8> GetUUID(const std::string& concrete_key_system) { 307 std::vector<uint8> GetUUID(const std::string& concrete_key_system) {
176 DCHECK(IsConcreteKeySystem(concrete_key_system)) 308 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 } 309 }
185 #endif // defined(OS_ANDROID) 310 #endif // defined(OS_ANDROID)
186 311
187 } // namespace content 312 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698