Remove unneeded ENABLE_BEGIN_FRAME_SCHEDULING command line flag
[chromium-blink-merge.git] / media / base / key_systems.cc
blob17c4210da220be672128198333c711550a26f0da
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
3 // found in the LICENSE file.
5 #include "media/base/key_systems.h"
7 #include <string>
9 #include "base/containers/hash_tables.h"
10 #include "base/lazy_instance.h"
11 #include "base/logging.h"
12 #include "base/strings/string_util.h"
13 #include "base/threading/thread_checker.h"
14 #include "base/time/time.h"
15 #include "media/base/eme_constants.h"
16 #include "media/base/key_system_info.h"
17 #include "media/base/key_systems_support_uma.h"
18 #include "media/base/media_client.h"
19 #include "media/cdm/key_system_names.h"
20 #include "third_party/widevine/cdm/widevine_cdm_common.h"
22 namespace media {
24 const char kClearKeyKeySystem[] = "org.w3.clearkey";
25 const char kPrefixedClearKeyKeySystem[] = "webkit-org.w3.clearkey";
26 const char kUnsupportedClearKeyKeySystem[] = "unsupported-org.w3.clearkey";
28 // These names are used by UMA. Do not change them!
29 const char kClearKeyKeySystemNameForUMA[] = "ClearKey";
30 const char kUnknownKeySystemNameForUMA[] = "Unknown";
32 struct NamedCodec {
33 const char* name;
34 EmeCodec type;
37 // Mapping between containers and their codecs.
38 // Only audio codec can belong to a "audio/*" container. Both audio and video
39 // codecs can belong to a "video/*" container.
40 // TODO(sandersd): This definition only makes sense for prefixed EME. Change it
41 // when prefixed EME is removed. http://crbug.com/249976
42 static NamedCodec kContainerToCodecMasks[] = {
43 {"audio/webm", EME_CODEC_WEBM_AUDIO_ALL},
44 {"video/webm", EME_CODEC_WEBM_ALL},
45 #if defined(USE_PROPRIETARY_CODECS)
46 {"audio/mp4", EME_CODEC_MP4_AUDIO_ALL},
47 {"video/mp4", EME_CODEC_MP4_ALL}
48 #endif // defined(USE_PROPRIETARY_CODECS)
51 // Mapping between codec names and enum values.
52 static NamedCodec kCodecStrings[] = {
53 {"opus", EME_CODEC_WEBM_OPUS},
54 {"vorbis", EME_CODEC_WEBM_VORBIS},
55 {"vp8", EME_CODEC_WEBM_VP8},
56 {"vp8.0", EME_CODEC_WEBM_VP8},
57 {"vp9", EME_CODEC_WEBM_VP9},
58 {"vp9.0", EME_CODEC_WEBM_VP9},
59 #if defined(USE_PROPRIETARY_CODECS)
60 {"mp4a", EME_CODEC_MP4_AAC},
61 {"avc1", EME_CODEC_MP4_AVC1},
62 {"avc3", EME_CODEC_MP4_AVC1}
63 #endif // defined(USE_PROPRIETARY_CODECS)
66 static EmeRobustness ConvertRobustness(const std::string& robustness) {
67 if (robustness.empty())
68 return EmeRobustness::EMPTY;
69 if (robustness == "SW_SECURE_CRYPTO")
70 return EmeRobustness::SW_SECURE_CRYPTO;
71 if (robustness == "SW_SECURE_DECODE")
72 return EmeRobustness::SW_SECURE_DECODE;
73 if (robustness == "HW_SECURE_CRYPTO")
74 return EmeRobustness::HW_SECURE_CRYPTO;
75 if (robustness == "HW_SECURE_DECODE")
76 return EmeRobustness::HW_SECURE_DECODE;
77 if (robustness == "HW_SECURE_ALL")
78 return EmeRobustness::HW_SECURE_ALL;
79 return EmeRobustness::INVALID;
82 static void AddClearKey(std::vector<KeySystemInfo>* concrete_key_systems) {
83 KeySystemInfo info;
84 info.key_system = kClearKeyKeySystem;
86 // On Android, Vorbis, VP8, AAC and AVC1 are supported in MediaCodec:
87 // http://developer.android.com/guide/appendix/media-formats.html
88 // VP9 support is device dependent.
90 info.supported_init_data_types =
91 kInitDataTypeMaskWebM | kInitDataTypeMaskKeyIds;
92 info.supported_codecs = EME_CODEC_WEBM_ALL;
94 #if defined(OS_ANDROID)
95 // Temporarily disable VP9 support for Android.
96 // TODO(xhwang): Use mime_util.h to query VP9 support on Android.
97 info.supported_codecs &= ~EME_CODEC_WEBM_VP9;
99 // Opus is not supported on Android yet. http://crbug.com/318436.
100 // TODO(sandersd): Check for platform support to set this bit.
101 info.supported_codecs &= ~EME_CODEC_WEBM_OPUS;
102 #endif // defined(OS_ANDROID)
104 #if defined(USE_PROPRIETARY_CODECS)
105 info.supported_init_data_types |= kInitDataTypeMaskCenc;
106 info.supported_codecs |= EME_CODEC_MP4_ALL;
107 #endif // defined(USE_PROPRIETARY_CODECS)
109 info.max_audio_robustness = EmeRobustness::EMPTY;
110 info.max_video_robustness = EmeRobustness::EMPTY;
111 info.persistent_license_support = EmeSessionTypeSupport::NOT_SUPPORTED;
112 info.persistent_release_message_support =
113 EmeSessionTypeSupport::NOT_SUPPORTED;
114 info.persistent_state_support = EmeFeatureSupport::NOT_SUPPORTED;
115 info.distinctive_identifier_support = EmeFeatureSupport::NOT_SUPPORTED;
117 info.use_aes_decryptor = true;
119 concrete_key_systems->push_back(info);
122 // Returns whether the |key_system| is known to Chromium and is thus likely to
123 // be implemented in an interoperable way.
124 // True is always returned for a |key_system| that begins with "x-".
126 // As with other web platform features, advertising support for a key system
127 // implies that it adheres to a defined and interoperable specification.
129 // To ensure interoperability, implementations of a specific |key_system| string
130 // must conform to a specification for that identifier that defines
131 // key system-specific behaviors not fully defined by the EME specification.
132 // That specification should be provided by the owner of the domain that is the
133 // reverse of the |key_system| string.
134 // This involves more than calling a library, SDK, or platform API.
135 // KeySystemsImpl must be populated appropriately, and there will likely be glue
136 // code to adapt to the API of the library, SDK, or platform API.
138 // Chromium mainline contains this data and glue code for specific key systems,
139 // which should help ensure interoperability with other implementations using
140 // these key systems.
142 // If you need to add support for other key systems, ensure that you have
143 // obtained the specification for how to integrate it with EME, implemented the
144 // appropriate glue/adapter code, and added all the appropriate data to
145 // KeySystemsImpl. Only then should you change this function.
146 static bool IsPotentiallySupportedKeySystem(const std::string& key_system) {
147 // Known and supported key systems.
148 if (key_system == kWidevineKeySystem)
149 return true;
150 if (key_system == kClearKey)
151 return true;
153 // External Clear Key is known and supports suffixes for testing.
154 if (IsExternalClearKey(key_system))
155 return true;
157 // Chromecast defines behaviors for Cast clients within its reverse domain.
158 const char kChromecastRoot[] = "com.chromecast";
159 if (IsParentKeySystemOf(kChromecastRoot, key_system))
160 return true;
162 // Implementations that do not have a specification or appropriate glue code
163 // can use the "x-" prefix to avoid conflicting with and advertising support
164 // for real key system names. Use is discouraged.
165 const char kExcludedPrefix[] = "x-";
166 if (key_system.find(kExcludedPrefix, 0, arraysize(kExcludedPrefix) - 1) == 0)
167 return true;
169 return false;
172 class KeySystemsImpl : public KeySystems {
173 public:
174 static KeySystemsImpl* GetInstance();
176 void UpdateIfNeeded();
178 bool IsConcreteSupportedKeySystem(const std::string& key_system) const;
180 bool PrefixedIsSupportedKeySystemWithMediaMimeType(
181 const std::string& mime_type,
182 const std::vector<std::string>& codecs,
183 const std::string& key_system);
185 std::string GetKeySystemNameForUMA(const std::string& key_system) const;
187 bool UseAesDecryptor(const std::string& concrete_key_system) const;
189 #if defined(ENABLE_PEPPER_CDMS)
190 std::string GetPepperType(const std::string& concrete_key_system) const;
191 #endif
193 void AddContainerMask(const std::string& container, uint32 mask);
194 void AddCodecMask(
195 EmeMediaType media_type,
196 const std::string& codec,
197 uint32 mask);
199 // Implementation of KeySystems interface.
200 bool IsSupportedKeySystem(const std::string& key_system) const override;
202 bool IsSupportedInitDataType(const std::string& key_system,
203 EmeInitDataType init_data_type) const override;
205 EmeConfigRule GetContentTypeConfigRule(
206 const std::string& key_system,
207 EmeMediaType media_type,
208 const std::string& container_mime_type,
209 const std::vector<std::string>& codecs) const override;
211 EmeConfigRule GetRobustnessConfigRule(
212 const std::string& key_system,
213 EmeMediaType media_type,
214 const std::string& requested_robustness) const override;
216 EmeSessionTypeSupport GetPersistentLicenseSessionSupport(
217 const std::string& key_system) const override;
219 EmeSessionTypeSupport GetPersistentReleaseMessageSessionSupport(
220 const std::string& key_system) const override;
222 EmeFeatureSupport GetPersistentStateSupport(
223 const std::string& key_system) const override;
225 EmeFeatureSupport GetDistinctiveIdentifierSupport(
226 const std::string& key_system) const override;
228 private:
229 KeySystemsImpl();
230 ~KeySystemsImpl() override;
232 void InitializeUMAInfo();
234 void UpdateSupportedKeySystems();
236 void AddConcreteSupportedKeySystems(
237 const std::vector<KeySystemInfo>& concrete_key_systems);
239 friend struct base::DefaultLazyInstanceTraits<KeySystemsImpl>;
241 typedef base::hash_map<std::string, KeySystemInfo> KeySystemInfoMap;
242 typedef base::hash_map<std::string, std::string> ParentKeySystemMap;
243 typedef base::hash_map<std::string, SupportedCodecs> ContainerCodecsMap;
244 typedef base::hash_map<std::string, EmeCodec> CodecsMap;
245 typedef base::hash_map<std::string, EmeInitDataType> InitDataTypesMap;
246 typedef base::hash_map<std::string, std::string> KeySystemNameForUMAMap;
248 // TODO(sandersd): Separate container enum from codec mask value.
249 // http://crbug.com/417440
250 SupportedCodecs GetCodecMaskForContainer(
251 const std::string& container) const;
252 EmeCodec GetCodecForString(const std::string& codec) const;
254 const std::string& PrefixedGetConcreteKeySystemNameFor(
255 const std::string& key_system) const;
257 // Returns whether a |container| type is supported by checking
258 // |key_system_supported_codecs|.
259 // TODO(xhwang): Update this to actually check initDataType support.
260 bool IsSupportedContainer(const std::string& container,
261 SupportedCodecs key_system_supported_codecs) const;
263 // Returns true if all |codecs| are supported in |container| by checking
264 // |key_system_supported_codecs|.
265 bool IsSupportedContainerAndCodecs(
266 const std::string& container,
267 const std::vector<std::string>& codecs,
268 SupportedCodecs key_system_supported_codecs) const;
270 // Map from key system string to capabilities.
271 KeySystemInfoMap concrete_key_system_map_;
273 // Map from parent key system to the concrete key system that should be used
274 // to represent its capabilities.
275 ParentKeySystemMap parent_key_system_map_;
277 KeySystemsSupportUMA key_systems_support_uma_;
279 ContainerCodecsMap container_to_codec_mask_map_;
280 CodecsMap codec_string_map_;
281 KeySystemNameForUMAMap key_system_name_for_uma_map_;
283 SupportedCodecs audio_codec_mask_;
284 SupportedCodecs video_codec_mask_;
286 // Makes sure all methods are called from the same thread.
287 base::ThreadChecker thread_checker_;
289 DISALLOW_COPY_AND_ASSIGN(KeySystemsImpl);
292 static base::LazyInstance<KeySystemsImpl>::Leaky g_key_systems =
293 LAZY_INSTANCE_INITIALIZER;
295 KeySystemsImpl* KeySystemsImpl::GetInstance() {
296 KeySystemsImpl* key_systems = g_key_systems.Pointer();
297 key_systems->UpdateIfNeeded();
298 return key_systems;
301 // Because we use a LazyInstance, the key systems info must be populated when
302 // the instance is lazily initiated.
303 KeySystemsImpl::KeySystemsImpl() :
304 audio_codec_mask_(EME_CODEC_AUDIO_ALL),
305 video_codec_mask_(EME_CODEC_VIDEO_ALL) {
306 for (size_t i = 0; i < arraysize(kContainerToCodecMasks); ++i) {
307 const std::string& name = kContainerToCodecMasks[i].name;
308 DCHECK(!container_to_codec_mask_map_.count(name));
309 container_to_codec_mask_map_[name] = kContainerToCodecMasks[i].type;
311 for (size_t i = 0; i < arraysize(kCodecStrings); ++i) {
312 const std::string& name = kCodecStrings[i].name;
313 DCHECK(!codec_string_map_.count(name));
314 codec_string_map_[name] = kCodecStrings[i].type;
317 InitializeUMAInfo();
319 // Always update supported key systems during construction.
320 UpdateSupportedKeySystems();
323 KeySystemsImpl::~KeySystemsImpl() {
326 SupportedCodecs KeySystemsImpl::GetCodecMaskForContainer(
327 const std::string& container) const {
328 ContainerCodecsMap::const_iterator iter =
329 container_to_codec_mask_map_.find(container);
330 if (iter != container_to_codec_mask_map_.end())
331 return iter->second;
332 return EME_CODEC_NONE;
335 EmeCodec KeySystemsImpl::GetCodecForString(const std::string& codec) const {
336 CodecsMap::const_iterator iter = codec_string_map_.find(codec);
337 if (iter != codec_string_map_.end())
338 return iter->second;
339 return EME_CODEC_NONE;
342 const std::string& KeySystemsImpl::PrefixedGetConcreteKeySystemNameFor(
343 const std::string& key_system) const {
344 ParentKeySystemMap::const_iterator iter =
345 parent_key_system_map_.find(key_system);
346 if (iter != parent_key_system_map_.end())
347 return iter->second;
348 return key_system;
351 void KeySystemsImpl::InitializeUMAInfo() {
352 DCHECK(thread_checker_.CalledOnValidThread());
353 DCHECK(key_system_name_for_uma_map_.empty());
355 std::vector<KeySystemInfoForUMA> key_systems_info_for_uma;
356 if (GetMediaClient())
357 GetMediaClient()->AddKeySystemsInfoForUMA(&key_systems_info_for_uma);
359 for (const KeySystemInfoForUMA& info : key_systems_info_for_uma) {
360 key_system_name_for_uma_map_[info.key_system] =
361 info.key_system_name_for_uma;
362 if (info.reports_key_system_support_to_uma)
363 key_systems_support_uma_.AddKeySystemToReport(info.key_system);
366 // Clear Key is always supported.
367 key_system_name_for_uma_map_[kClearKeyKeySystem] =
368 kClearKeyKeySystemNameForUMA;
371 void KeySystemsImpl::UpdateIfNeeded() {
372 if (GetMediaClient() && GetMediaClient()->IsKeySystemsUpdateNeeded())
373 UpdateSupportedKeySystems();
376 void KeySystemsImpl::UpdateSupportedKeySystems() {
377 DCHECK(thread_checker_.CalledOnValidThread());
378 concrete_key_system_map_.clear();
379 parent_key_system_map_.clear();
381 // Build KeySystemInfo.
382 std::vector<KeySystemInfo> key_systems_info;
384 // Add key systems supported by the MediaClient implementation.
385 if (GetMediaClient())
386 GetMediaClient()->AddSupportedKeySystems(&key_systems_info);
388 // Clear Key is always supported.
389 AddClearKey(&key_systems_info);
391 AddConcreteSupportedKeySystems(key_systems_info);
394 void KeySystemsImpl::AddConcreteSupportedKeySystems(
395 const std::vector<KeySystemInfo>& concrete_key_systems) {
396 DCHECK(thread_checker_.CalledOnValidThread());
397 DCHECK(concrete_key_system_map_.empty());
398 DCHECK(parent_key_system_map_.empty());
400 for (const KeySystemInfo& info : concrete_key_systems) {
401 DCHECK(!info.key_system.empty());
402 DCHECK(info.max_audio_robustness != EmeRobustness::INVALID);
403 DCHECK(info.max_video_robustness != EmeRobustness::INVALID);
404 DCHECK(info.persistent_license_support != EmeSessionTypeSupport::INVALID);
405 DCHECK(info.persistent_release_message_support !=
406 EmeSessionTypeSupport::INVALID);
407 DCHECK(info.persistent_state_support != EmeFeatureSupport::INVALID);
408 DCHECK(info.distinctive_identifier_support != EmeFeatureSupport::INVALID);
410 // Supporting persistent state is a prerequsite for supporting persistent
411 // sessions.
412 if (info.persistent_state_support == EmeFeatureSupport::NOT_SUPPORTED) {
413 DCHECK(info.persistent_license_support ==
414 EmeSessionTypeSupport::NOT_SUPPORTED);
415 DCHECK(info.persistent_release_message_support ==
416 EmeSessionTypeSupport::NOT_SUPPORTED);
419 // persistent-release-message sessions are not currently supported.
420 // http://crbug.com/448888
421 DCHECK(info.persistent_release_message_support ==
422 EmeSessionTypeSupport::NOT_SUPPORTED);
424 // If distinctive identifiers are not supported, then no other features can
425 // require them.
426 if (info.distinctive_identifier_support ==
427 EmeFeatureSupport::NOT_SUPPORTED) {
428 DCHECK(info.persistent_license_support !=
429 EmeSessionTypeSupport::SUPPORTED_WITH_IDENTIFIER);
430 DCHECK(info.persistent_release_message_support !=
431 EmeSessionTypeSupport::SUPPORTED_WITH_IDENTIFIER);
434 // Distinctive identifiers and persistent state can only be reliably blocked
435 // (and therefore be safely configurable) for Pepper-hosted key systems. For
436 // other platforms, (except for the AES decryptor) assume that the CDM can
437 // and will do anything.
438 bool can_block = info.use_aes_decryptor;
439 #if defined(ENABLE_PEPPER_CDMS)
440 DCHECK_EQ(info.use_aes_decryptor, info.pepper_type.empty());
441 if (!info.pepper_type.empty())
442 can_block = true;
443 #endif
444 if (!can_block) {
445 DCHECK(info.distinctive_identifier_support ==
446 EmeFeatureSupport::ALWAYS_ENABLED);
447 DCHECK(info.persistent_state_support ==
448 EmeFeatureSupport::ALWAYS_ENABLED);
451 DCHECK(!IsSupportedKeySystem(info.key_system))
452 << "Key system '" << info.key_system << "' already registered";
453 DCHECK(!parent_key_system_map_.count(info.key_system))
454 << "'" << info.key_system << "' is already registered as a parent";
455 concrete_key_system_map_[info.key_system] = info;
456 if (!info.parent_key_system.empty()) {
457 DCHECK(!IsConcreteSupportedKeySystem(info.parent_key_system))
458 << "Parent '" << info.parent_key_system << "' "
459 << "already registered concrete";
460 DCHECK(!parent_key_system_map_.count(info.parent_key_system))
461 << "Parent '" << info.parent_key_system << "' already registered";
462 parent_key_system_map_[info.parent_key_system] = info.key_system;
467 bool KeySystemsImpl::IsConcreteSupportedKeySystem(
468 const std::string& key_system) const {
469 DCHECK(thread_checker_.CalledOnValidThread());
470 return concrete_key_system_map_.count(key_system) != 0;
473 bool KeySystemsImpl::IsSupportedContainer(
474 const std::string& container,
475 SupportedCodecs key_system_supported_codecs) const {
476 DCHECK(thread_checker_.CalledOnValidThread());
477 DCHECK(!container.empty());
479 // When checking container support for EME, "audio/foo" should be treated the
480 // same as "video/foo". Convert the |container| to achieve this.
481 // TODO(xhwang): Replace this with real checks against supported initDataTypes
482 // combined with supported demuxers.
483 std::string canonical_container = container;
484 if (container.find("audio/") == 0)
485 canonical_container.replace(0, 6, "video/");
487 // A container is supported iif at least one codec in that container is
488 // supported.
489 SupportedCodecs supported_codecs =
490 GetCodecMaskForContainer(canonical_container);
491 return (supported_codecs & key_system_supported_codecs) != 0;
494 bool KeySystemsImpl::IsSupportedContainerAndCodecs(
495 const std::string& container,
496 const std::vector<std::string>& codecs,
497 SupportedCodecs key_system_supported_codecs) const {
498 DCHECK(thread_checker_.CalledOnValidThread());
499 DCHECK(!container.empty());
500 DCHECK(!codecs.empty());
501 DCHECK(IsSupportedContainer(container, key_system_supported_codecs));
503 SupportedCodecs container_supported_codecs =
504 GetCodecMaskForContainer(container);
506 for (size_t i = 0; i < codecs.size(); ++i) {
507 if (codecs[i].empty())
508 continue;
510 EmeCodec codec = GetCodecForString(codecs[i]);
512 // Unsupported codec.
513 if (!(codec & key_system_supported_codecs))
514 return false;
516 // Unsupported codec/container combination, e.g. "video/webm" and "avc1".
517 if (!(codec & container_supported_codecs))
518 return false;
521 return true;
524 bool KeySystemsImpl::IsSupportedInitDataType(
525 const std::string& key_system,
526 EmeInitDataType init_data_type) const {
527 DCHECK(thread_checker_.CalledOnValidThread());
529 // Locate |key_system|. Only concrete key systems are supported in unprefixed.
530 KeySystemInfoMap::const_iterator key_system_iter =
531 concrete_key_system_map_.find(key_system);
532 if (key_system_iter == concrete_key_system_map_.end()) {
533 NOTREACHED();
534 return false;
537 // Check |init_data_type|.
538 InitDataTypeMask available_init_data_types =
539 key_system_iter->second.supported_init_data_types;
540 switch (init_data_type) {
541 case EmeInitDataType::UNKNOWN:
542 return false;
543 case EmeInitDataType::WEBM:
544 return (available_init_data_types & kInitDataTypeMaskWebM) != 0;
545 case EmeInitDataType::CENC:
546 return (available_init_data_types & kInitDataTypeMaskCenc) != 0;
547 case EmeInitDataType::KEYIDS:
548 return (available_init_data_types & kInitDataTypeMaskKeyIds) != 0;
550 NOTREACHED();
551 return false;
554 bool KeySystemsImpl::PrefixedIsSupportedKeySystemWithMediaMimeType(
555 const std::string& mime_type,
556 const std::vector<std::string>& codecs,
557 const std::string& key_system) {
558 DCHECK(thread_checker_.CalledOnValidThread());
560 const std::string& concrete_key_system =
561 PrefixedGetConcreteKeySystemNameFor(key_system);
563 bool has_type = !mime_type.empty();
565 key_systems_support_uma_.ReportKeySystemQuery(key_system, has_type);
567 // Check key system support.
568 KeySystemInfoMap::const_iterator key_system_iter =
569 concrete_key_system_map_.find(concrete_key_system);
570 if (key_system_iter == concrete_key_system_map_.end())
571 return false;
573 key_systems_support_uma_.ReportKeySystemSupport(key_system, false);
575 if (!has_type) {
576 DCHECK(codecs.empty());
577 return true;
580 SupportedCodecs key_system_supported_codecs =
581 key_system_iter->second.supported_codecs;
583 if (!IsSupportedContainer(mime_type, key_system_supported_codecs))
584 return false;
586 if (!codecs.empty() &&
587 !IsSupportedContainerAndCodecs(
588 mime_type, codecs, key_system_supported_codecs)) {
589 return false;
592 key_systems_support_uma_.ReportKeySystemSupport(key_system, true);
594 return true;
597 std::string KeySystemsImpl::GetKeySystemNameForUMA(
598 const std::string& key_system) const {
599 DCHECK(thread_checker_.CalledOnValidThread());
601 KeySystemNameForUMAMap::const_iterator iter =
602 key_system_name_for_uma_map_.find(key_system);
603 if (iter == key_system_name_for_uma_map_.end())
604 return kUnknownKeySystemNameForUMA;
606 return iter->second;
609 bool KeySystemsImpl::UseAesDecryptor(
610 const std::string& concrete_key_system) const {
611 DCHECK(thread_checker_.CalledOnValidThread());
613 KeySystemInfoMap::const_iterator key_system_iter =
614 concrete_key_system_map_.find(concrete_key_system);
615 if (key_system_iter == concrete_key_system_map_.end()) {
616 DLOG(FATAL) << concrete_key_system << " is not a known concrete system";
617 return false;
620 return key_system_iter->second.use_aes_decryptor;
623 #if defined(ENABLE_PEPPER_CDMS)
624 std::string KeySystemsImpl::GetPepperType(
625 const std::string& concrete_key_system) const {
626 DCHECK(thread_checker_.CalledOnValidThread());
628 KeySystemInfoMap::const_iterator key_system_iter =
629 concrete_key_system_map_.find(concrete_key_system);
630 if (key_system_iter == concrete_key_system_map_.end()) {
631 DLOG(FATAL) << concrete_key_system << " is not a known concrete system";
632 return std::string();
635 const std::string& type = key_system_iter->second.pepper_type;
636 DLOG_IF(FATAL, type.empty()) << concrete_key_system << " is not Pepper-based";
637 return type;
639 #endif
641 void KeySystemsImpl::AddContainerMask(
642 const std::string& container,
643 uint32 mask) {
644 DCHECK(thread_checker_.CalledOnValidThread());
645 DCHECK(!container_to_codec_mask_map_.count(container));
646 container_to_codec_mask_map_[container] = static_cast<EmeCodec>(mask);
649 void KeySystemsImpl::AddCodecMask(
650 EmeMediaType media_type,
651 const std::string& codec,
652 uint32 mask) {
653 DCHECK(thread_checker_.CalledOnValidThread());
654 DCHECK(!codec_string_map_.count(codec));
655 codec_string_map_[codec] = static_cast<EmeCodec>(mask);
656 if (media_type == EmeMediaType::AUDIO) {
657 audio_codec_mask_ |= mask;
658 } else {
659 video_codec_mask_ |= mask;
663 bool KeySystemsImpl::IsSupportedKeySystem(const std::string& key_system) const {
664 DCHECK(thread_checker_.CalledOnValidThread());
665 return concrete_key_system_map_.count(key_system) != 0;
668 EmeConfigRule KeySystemsImpl::GetContentTypeConfigRule(
669 const std::string& key_system,
670 EmeMediaType media_type,
671 const std::string& container_mime_type,
672 const std::vector<std::string>& codecs) const {
673 DCHECK(thread_checker_.CalledOnValidThread());
675 // Make sure the container matches |media_type|.
676 SupportedCodecs media_type_codec_mask = EME_CODEC_NONE;
677 switch (media_type) {
678 case EmeMediaType::AUDIO:
679 if (!StartsWithASCII(container_mime_type, "audio/", true))
680 return EmeConfigRule::NOT_SUPPORTED;
681 media_type_codec_mask = audio_codec_mask_;
682 break;
683 case EmeMediaType::VIDEO:
684 if (!StartsWithASCII(container_mime_type, "video/", true))
685 return EmeConfigRule::NOT_SUPPORTED;
686 media_type_codec_mask = video_codec_mask_;
687 break;
690 // Look up the key system's supported codecs.
691 KeySystemInfoMap::const_iterator key_system_iter =
692 concrete_key_system_map_.find(key_system);
693 if (key_system_iter == concrete_key_system_map_.end()) {
694 NOTREACHED();
695 return EmeConfigRule::NOT_SUPPORTED;
697 SupportedCodecs key_system_codec_mask =
698 key_system_iter->second.supported_codecs;
699 #if defined(OS_ANDROID)
700 SupportedCodecs key_system_secure_codec_mask =
701 key_system_iter->second.supported_secure_codecs;
702 #endif // defined(OS_ANDROID)
705 // Check that the container is supported by the key system. (This check is
706 // necessary because |codecs| may be empty.)
707 SupportedCodecs container_codec_mask =
708 GetCodecMaskForContainer(container_mime_type) & media_type_codec_mask;
709 if ((key_system_codec_mask & container_codec_mask) == 0)
710 return EmeConfigRule::NOT_SUPPORTED;
712 // Check that the codecs are supported by the key system and container.
713 EmeConfigRule support = EmeConfigRule::SUPPORTED;
714 for (size_t i = 0; i < codecs.size(); i++) {
715 SupportedCodecs codec = GetCodecForString(codecs[i]);
716 if ((codec & key_system_codec_mask & container_codec_mask) == 0)
717 return EmeConfigRule::NOT_SUPPORTED;
718 #if defined(OS_ANDROID)
719 // Check whether the codec supports a hardware-secure mode; if not, indicate
720 // that hardware-secure codecs are not available for all listed codecs.
721 // Because the check for regular codec support is early-exit, we don't have
722 // to consider codecs that are only supported in hardware-secure mode. We
723 // could do so, and make use of SECURE_CODECS_REQUIRED, if it turns out that
724 // hardware-secure-only codecs actually exist and are useful.
725 if ((codec & key_system_secure_codec_mask) == 0)
726 support = EmeConfigRule::SECURE_CODECS_NOT_ALLOWED;
727 #endif // defined(OS_ANDROID)
731 return support;
734 EmeConfigRule KeySystemsImpl::GetRobustnessConfigRule(
735 const std::string& key_system,
736 EmeMediaType media_type,
737 const std::string& requested_robustness) const {
738 DCHECK(thread_checker_.CalledOnValidThread());
740 EmeRobustness robustness = ConvertRobustness(requested_robustness);
741 if (robustness == EmeRobustness::INVALID)
742 return EmeConfigRule::NOT_SUPPORTED;
743 if (robustness == EmeRobustness::EMPTY)
744 return EmeConfigRule::SUPPORTED;
746 KeySystemInfoMap::const_iterator key_system_iter =
747 concrete_key_system_map_.find(key_system);
748 if (key_system_iter == concrete_key_system_map_.end()) {
749 NOTREACHED();
750 return EmeConfigRule::NOT_SUPPORTED;
753 EmeRobustness max_robustness = EmeRobustness::INVALID;
754 switch (media_type) {
755 case EmeMediaType::AUDIO:
756 max_robustness = key_system_iter->second.max_audio_robustness;
757 break;
758 case EmeMediaType::VIDEO:
759 max_robustness = key_system_iter->second.max_video_robustness;
760 break;
763 // We can compare robustness levels whenever they are not HW_SECURE_CRYPTO
764 // and SW_SECURE_DECODE in some order. If they are exactly those two then the
765 // robustness requirement is not supported.
766 if ((max_robustness == EmeRobustness::HW_SECURE_CRYPTO &&
767 robustness == EmeRobustness::SW_SECURE_DECODE) ||
768 (max_robustness == EmeRobustness::SW_SECURE_DECODE &&
769 robustness == EmeRobustness::HW_SECURE_CRYPTO) ||
770 robustness > max_robustness) {
771 return EmeConfigRule::NOT_SUPPORTED;
774 if (key_system == kWidevineKeySystem) {
775 #if defined(OS_CHROMEOS)
776 // Hardware security requires remote attestation.
777 if (robustness >= EmeRobustness::HW_SECURE_CRYPTO)
778 return EmeConfigRule::IDENTIFIER_REQUIRED;
780 // For video, recommend remote attestation if HW_SECURE_ALL is available,
781 // because it enables hardware accelerated decoding.
782 // TODO(sandersd): Only do this when hardware accelerated decoding is
783 // available for the requested codecs.
784 if (media_type == EmeMediaType::VIDEO &&
785 max_robustness == EmeRobustness::HW_SECURE_ALL) {
786 return EmeConfigRule::IDENTIFIER_RECOMMENDED;
788 #elif defined(OS_ANDROID)
789 if (robustness > EmeRobustness::SW_SECURE_CRYPTO)
790 return EmeConfigRule::SECURE_CODECS_REQUIRED;
791 #endif // defined(OS_CHROMEOS)
794 return EmeConfigRule::SUPPORTED;
797 EmeSessionTypeSupport KeySystemsImpl::GetPersistentLicenseSessionSupport(
798 const std::string& key_system) const {
799 DCHECK(thread_checker_.CalledOnValidThread());
801 KeySystemInfoMap::const_iterator key_system_iter =
802 concrete_key_system_map_.find(key_system);
803 if (key_system_iter == concrete_key_system_map_.end()) {
804 NOTREACHED();
805 return EmeSessionTypeSupport::INVALID;
807 return key_system_iter->second.persistent_license_support;
810 EmeSessionTypeSupport KeySystemsImpl::GetPersistentReleaseMessageSessionSupport(
811 const std::string& key_system) const {
812 DCHECK(thread_checker_.CalledOnValidThread());
814 KeySystemInfoMap::const_iterator key_system_iter =
815 concrete_key_system_map_.find(key_system);
816 if (key_system_iter == concrete_key_system_map_.end()) {
817 NOTREACHED();
818 return EmeSessionTypeSupport::INVALID;
820 return key_system_iter->second.persistent_release_message_support;
823 EmeFeatureSupport KeySystemsImpl::GetPersistentStateSupport(
824 const std::string& key_system) const {
825 DCHECK(thread_checker_.CalledOnValidThread());
827 KeySystemInfoMap::const_iterator key_system_iter =
828 concrete_key_system_map_.find(key_system);
829 if (key_system_iter == concrete_key_system_map_.end()) {
830 NOTREACHED();
831 return EmeFeatureSupport::INVALID;
833 return key_system_iter->second.persistent_state_support;
836 EmeFeatureSupport KeySystemsImpl::GetDistinctiveIdentifierSupport(
837 const std::string& key_system) const {
838 DCHECK(thread_checker_.CalledOnValidThread());
840 KeySystemInfoMap::const_iterator key_system_iter =
841 concrete_key_system_map_.find(key_system);
842 if (key_system_iter == concrete_key_system_map_.end()) {
843 NOTREACHED();
844 return EmeFeatureSupport::INVALID;
846 return key_system_iter->second.distinctive_identifier_support;
849 KeySystems* KeySystems::GetInstance() {
850 return KeySystemsImpl::GetInstance();
853 //------------------------------------------------------------------------------
855 std::string GetUnprefixedKeySystemName(const std::string& key_system) {
856 if (key_system == kClearKeyKeySystem)
857 return kUnsupportedClearKeyKeySystem;
859 if (key_system == kPrefixedClearKeyKeySystem)
860 return kClearKeyKeySystem;
862 return key_system;
865 std::string GetPrefixedKeySystemName(const std::string& key_system) {
866 DCHECK_NE(key_system, kPrefixedClearKeyKeySystem);
868 if (key_system == kClearKeyKeySystem)
869 return kPrefixedClearKeyKeySystem;
871 return key_system;
874 bool PrefixedIsSupportedConcreteKeySystem(const std::string& key_system) {
875 return KeySystemsImpl::GetInstance()->IsConcreteSupportedKeySystem(
876 key_system);
879 bool IsSupportedKeySystem(const std::string& key_system) {
880 if (!KeySystemsImpl::GetInstance()->IsSupportedKeySystem(key_system))
881 return false;
883 // TODO(ddorwin): Move this to where we add key systems when prefixed EME is
884 // removed (crbug.com/249976).
885 if (!IsPotentiallySupportedKeySystem(key_system)) {
886 // If you encounter this path, see the comments for the above function.
887 NOTREACHED() << "Unrecognized key system " << key_system
888 << ". See code comments.";
889 return false;
892 return true;
895 bool IsSupportedKeySystemWithInitDataType(const std::string& key_system,
896 EmeInitDataType init_data_type) {
897 return KeySystemsImpl::GetInstance()->IsSupportedInitDataType(key_system,
898 init_data_type);
901 bool PrefixedIsSupportedKeySystemWithMediaMimeType(
902 const std::string& mime_type,
903 const std::vector<std::string>& codecs,
904 const std::string& key_system) {
905 return KeySystemsImpl::GetInstance()
906 ->PrefixedIsSupportedKeySystemWithMediaMimeType(mime_type, codecs,
907 key_system);
910 std::string GetKeySystemNameForUMA(const std::string& key_system) {
911 return KeySystemsImpl::GetInstance()->GetKeySystemNameForUMA(key_system);
914 bool CanUseAesDecryptor(const std::string& concrete_key_system) {
915 return KeySystemsImpl::GetInstance()->UseAesDecryptor(concrete_key_system);
918 #if defined(ENABLE_PEPPER_CDMS)
919 std::string GetPepperType(const std::string& concrete_key_system) {
920 return KeySystemsImpl::GetInstance()->GetPepperType(concrete_key_system);
922 #endif
924 // These two functions are for testing purpose only. The declaration in the
925 // header file is guarded by "#if defined(UNIT_TEST)" so that they can be used
926 // by tests but not non-test code. However, this .cc file is compiled as part of
927 // "media" where "UNIT_TEST" is not defined. So we need to specify
928 // "MEDIA_EXPORT" here again so that they are visible to tests.
930 MEDIA_EXPORT void AddContainerMask(const std::string& container, uint32 mask) {
931 KeySystemsImpl::GetInstance()->AddContainerMask(container, mask);
934 MEDIA_EXPORT void AddCodecMask(
935 EmeMediaType media_type,
936 const std::string& codec,
937 uint32 mask) {
938 KeySystemsImpl::GetInstance()->AddCodecMask(media_type, codec, mask);
941 } // namespace media