Update V8 to version 4.7.56.
[chromium-blink-merge.git] / media / base / key_systems.cc
blob78029e1dffe8a24dc181eb564a36eeedd330a33c
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"
8 #include "base/containers/hash_tables.h"
9 #include "base/lazy_instance.h"
10 #include "base/logging.h"
11 #include "base/strings/string_util.h"
12 #include "base/threading/thread_checker.h"
13 #include "base/time/time.h"
14 #include "media/base/key_system_info.h"
15 #include "media/base/key_systems_support_uma.h"
16 #include "media/base/media_client.h"
17 #include "media/cdm/key_system_names.h"
18 #include "third_party/widevine/cdm/widevine_cdm_common.h"
20 namespace media {
22 const char kClearKeyKeySystem[] = "org.w3.clearkey";
23 const char kPrefixedClearKeyKeySystem[] = "webkit-org.w3.clearkey";
24 const char kUnsupportedClearKeyKeySystem[] = "unsupported-org.w3.clearkey";
26 // These names are used by UMA. Do not change them!
27 const char kClearKeyKeySystemNameForUMA[] = "ClearKey";
28 const char kUnknownKeySystemNameForUMA[] = "Unknown";
30 struct NamedCodec {
31 const char* name;
32 EmeCodec type;
35 // Mapping between containers and their codecs.
36 // Only audio codec can belong to a "audio/*" container. Both audio and video
37 // codecs can belong to a "video/*" container.
38 // TODO(sandersd): This definition only makes sense for prefixed EME. Change it
39 // when prefixed EME is removed. http://crbug.com/249976
40 static NamedCodec kContainerToCodecMasks[] = {
41 {"audio/webm", EME_CODEC_WEBM_AUDIO_ALL},
42 {"video/webm", EME_CODEC_WEBM_ALL},
43 #if defined(USE_PROPRIETARY_CODECS)
44 {"audio/mp4", EME_CODEC_MP4_AUDIO_ALL},
45 {"video/mp4", EME_CODEC_MP4_ALL}
46 #endif // defined(USE_PROPRIETARY_CODECS)
49 // Mapping between codec names and enum values.
50 static NamedCodec kCodecStrings[] = {
51 {"opus", EME_CODEC_WEBM_OPUS},
52 {"vorbis", EME_CODEC_WEBM_VORBIS},
53 {"vp8", EME_CODEC_WEBM_VP8},
54 {"vp8.0", EME_CODEC_WEBM_VP8},
55 {"vp9", EME_CODEC_WEBM_VP9},
56 {"vp9.0", EME_CODEC_WEBM_VP9},
57 #if defined(USE_PROPRIETARY_CODECS)
58 {"mp4a", EME_CODEC_MP4_AAC},
59 {"avc1", EME_CODEC_MP4_AVC1},
60 {"avc3", EME_CODEC_MP4_AVC1}
61 #endif // defined(USE_PROPRIETARY_CODECS)
64 static EmeRobustness ConvertRobustness(const std::string& robustness) {
65 if (robustness.empty())
66 return EmeRobustness::EMPTY;
67 if (robustness == "SW_SECURE_CRYPTO")
68 return EmeRobustness::SW_SECURE_CRYPTO;
69 if (robustness == "SW_SECURE_DECODE")
70 return EmeRobustness::SW_SECURE_DECODE;
71 if (robustness == "HW_SECURE_CRYPTO")
72 return EmeRobustness::HW_SECURE_CRYPTO;
73 if (robustness == "HW_SECURE_DECODE")
74 return EmeRobustness::HW_SECURE_DECODE;
75 if (robustness == "HW_SECURE_ALL")
76 return EmeRobustness::HW_SECURE_ALL;
77 return EmeRobustness::INVALID;
80 static void AddClearKey(std::vector<KeySystemInfo>* concrete_key_systems) {
81 KeySystemInfo info;
82 info.key_system = kClearKeyKeySystem;
84 // On Android, Vorbis, VP8, AAC and AVC1 are supported in MediaCodec:
85 // http://developer.android.com/guide/appendix/media-formats.html
86 // VP9 support is device dependent.
88 info.supported_init_data_types =
89 kInitDataTypeMaskWebM | kInitDataTypeMaskKeyIds;
90 info.supported_codecs = EME_CODEC_WEBM_ALL;
92 #if defined(OS_ANDROID)
93 // Temporarily disable VP9 support for Android.
94 // TODO(xhwang): Use mime_util.h to query VP9 support on Android.
95 info.supported_codecs &= ~EME_CODEC_WEBM_VP9;
97 // Opus is not supported on Android yet. http://crbug.com/318436.
98 // TODO(sandersd): Check for platform support to set this bit.
99 info.supported_codecs &= ~EME_CODEC_WEBM_OPUS;
100 #endif // defined(OS_ANDROID)
102 #if defined(USE_PROPRIETARY_CODECS)
103 info.supported_init_data_types |= kInitDataTypeMaskCenc;
104 info.supported_codecs |= EME_CODEC_MP4_ALL;
105 #endif // defined(USE_PROPRIETARY_CODECS)
107 info.max_audio_robustness = EmeRobustness::EMPTY;
108 info.max_video_robustness = EmeRobustness::EMPTY;
109 info.persistent_license_support = EmeSessionTypeSupport::NOT_SUPPORTED;
110 info.persistent_release_message_support =
111 EmeSessionTypeSupport::NOT_SUPPORTED;
112 info.persistent_state_support = EmeFeatureSupport::NOT_SUPPORTED;
113 info.distinctive_identifier_support = EmeFeatureSupport::NOT_SUPPORTED;
115 info.use_aes_decryptor = true;
117 concrete_key_systems->push_back(info);
120 // Returns whether the |key_system| is known to Chromium and is thus likely to
121 // be implemented in an interoperable way.
122 // True is always returned for a |key_system| that begins with "x-".
124 // As with other web platform features, advertising support for a key system
125 // implies that it adheres to a defined and interoperable specification.
127 // To ensure interoperability, implementations of a specific |key_system| string
128 // must conform to a specification for that identifier that defines
129 // key system-specific behaviors not fully defined by the EME specification.
130 // That specification should be provided by the owner of the domain that is the
131 // reverse of the |key_system| string.
132 // This involves more than calling a library, SDK, or platform API.
133 // KeySystemsImpl must be populated appropriately, and there will likely be glue
134 // code to adapt to the API of the library, SDK, or platform API.
136 // Chromium mainline contains this data and glue code for specific key systems,
137 // which should help ensure interoperability with other implementations using
138 // these key systems.
140 // If you need to add support for other key systems, ensure that you have
141 // obtained the specification for how to integrate it with EME, implemented the
142 // appropriate glue/adapter code, and added all the appropriate data to
143 // KeySystemsImpl. Only then should you change this function.
144 static bool IsPotentiallySupportedKeySystem(const std::string& key_system) {
145 // Known and supported key systems.
146 if (key_system == kWidevineKeySystem)
147 return true;
148 if (key_system == kClearKey)
149 return true;
151 // External Clear Key is known and supports suffixes for testing.
152 if (IsExternalClearKey(key_system))
153 return true;
155 // Chromecast defines behaviors for Cast clients within its reverse domain.
156 const char kChromecastRoot[] = "com.chromecast";
157 if (IsParentKeySystemOf(kChromecastRoot, key_system))
158 return true;
160 // Implementations that do not have a specification or appropriate glue code
161 // can use the "x-" prefix to avoid conflicting with and advertising support
162 // for real key system names. Use is discouraged.
163 const char kExcludedPrefix[] = "x-";
164 if (key_system.find(kExcludedPrefix, 0, arraysize(kExcludedPrefix) - 1) == 0)
165 return true;
167 return false;
170 class KeySystemsImpl : public KeySystems {
171 public:
172 static KeySystemsImpl* GetInstance();
174 void UpdateIfNeeded();
176 bool IsConcreteSupportedKeySystem(const std::string& key_system) const;
178 bool PrefixedIsSupportedKeySystemWithMediaMimeType(
179 const std::string& mime_type,
180 const std::vector<std::string>& codecs,
181 const std::string& key_system);
183 std::string GetKeySystemNameForUMA(const std::string& key_system) const;
185 bool UseAesDecryptor(const std::string& concrete_key_system) const;
187 #if defined(ENABLE_PEPPER_CDMS)
188 std::string GetPepperType(const std::string& concrete_key_system) const;
189 #endif
191 void AddContainerMask(const std::string& container, uint32 mask);
192 void AddCodecMask(
193 EmeMediaType media_type,
194 const std::string& codec,
195 uint32 mask);
197 // Implementation of KeySystems interface.
198 bool IsSupportedKeySystem(const std::string& key_system) const override;
200 bool IsSupportedInitDataType(const std::string& key_system,
201 EmeInitDataType init_data_type) const override;
203 EmeConfigRule GetContentTypeConfigRule(
204 const std::string& key_system,
205 EmeMediaType media_type,
206 const std::string& container_mime_type,
207 const std::vector<std::string>& codecs) const override;
209 EmeConfigRule GetRobustnessConfigRule(
210 const std::string& key_system,
211 EmeMediaType media_type,
212 const std::string& requested_robustness) const override;
214 EmeSessionTypeSupport GetPersistentLicenseSessionSupport(
215 const std::string& key_system) const override;
217 EmeSessionTypeSupport GetPersistentReleaseMessageSessionSupport(
218 const std::string& key_system) const override;
220 EmeFeatureSupport GetPersistentStateSupport(
221 const std::string& key_system) const override;
223 EmeFeatureSupport GetDistinctiveIdentifierSupport(
224 const std::string& key_system) const override;
226 private:
227 KeySystemsImpl();
228 ~KeySystemsImpl() override;
230 void InitializeUMAInfo();
232 void UpdateSupportedKeySystems();
234 void AddConcreteSupportedKeySystems(
235 const std::vector<KeySystemInfo>& concrete_key_systems);
237 friend struct base::DefaultLazyInstanceTraits<KeySystemsImpl>;
239 typedef base::hash_map<std::string, KeySystemInfo> KeySystemInfoMap;
240 typedef base::hash_map<std::string, std::string> ParentKeySystemMap;
241 typedef base::hash_map<std::string, SupportedCodecs> ContainerCodecsMap;
242 typedef base::hash_map<std::string, EmeCodec> CodecsMap;
243 typedef base::hash_map<std::string, EmeInitDataType> InitDataTypesMap;
244 typedef base::hash_map<std::string, std::string> KeySystemNameForUMAMap;
246 // TODO(sandersd): Separate container enum from codec mask value.
247 // http://crbug.com/417440
248 SupportedCodecs GetCodecMaskForContainer(
249 const std::string& container) const;
250 EmeCodec GetCodecForString(const std::string& codec) const;
252 const std::string& PrefixedGetConcreteKeySystemNameFor(
253 const std::string& key_system) const;
255 // Returns whether a |container| type is supported by checking
256 // |key_system_supported_codecs|.
257 // TODO(xhwang): Update this to actually check initDataType support.
258 bool IsSupportedContainer(const std::string& container,
259 SupportedCodecs key_system_supported_codecs) const;
261 // Returns true if all |codecs| are supported in |container| by checking
262 // |key_system_supported_codecs|.
263 bool IsSupportedContainerAndCodecs(
264 const std::string& container,
265 const std::vector<std::string>& codecs,
266 SupportedCodecs key_system_supported_codecs) const;
268 // Map from key system string to capabilities.
269 KeySystemInfoMap concrete_key_system_map_;
271 // Map from parent key system to the concrete key system that should be used
272 // to represent its capabilities.
273 ParentKeySystemMap parent_key_system_map_;
275 KeySystemsSupportUMA key_systems_support_uma_;
277 ContainerCodecsMap container_to_codec_mask_map_;
278 CodecsMap codec_string_map_;
279 KeySystemNameForUMAMap key_system_name_for_uma_map_;
281 SupportedCodecs audio_codec_mask_;
282 SupportedCodecs video_codec_mask_;
284 // Makes sure all methods are called from the same thread.
285 base::ThreadChecker thread_checker_;
287 DISALLOW_COPY_AND_ASSIGN(KeySystemsImpl);
290 static base::LazyInstance<KeySystemsImpl>::Leaky g_key_systems =
291 LAZY_INSTANCE_INITIALIZER;
293 KeySystemsImpl* KeySystemsImpl::GetInstance() {
294 KeySystemsImpl* key_systems = g_key_systems.Pointer();
295 key_systems->UpdateIfNeeded();
296 return key_systems;
299 // Because we use a LazyInstance, the key systems info must be populated when
300 // the instance is lazily initiated.
301 KeySystemsImpl::KeySystemsImpl() :
302 audio_codec_mask_(EME_CODEC_AUDIO_ALL),
303 video_codec_mask_(EME_CODEC_VIDEO_ALL) {
304 for (size_t i = 0; i < arraysize(kContainerToCodecMasks); ++i) {
305 const std::string& name = kContainerToCodecMasks[i].name;
306 DCHECK(!container_to_codec_mask_map_.count(name));
307 container_to_codec_mask_map_[name] = kContainerToCodecMasks[i].type;
309 for (size_t i = 0; i < arraysize(kCodecStrings); ++i) {
310 const std::string& name = kCodecStrings[i].name;
311 DCHECK(!codec_string_map_.count(name));
312 codec_string_map_[name] = kCodecStrings[i].type;
315 InitializeUMAInfo();
317 // Always update supported key systems during construction.
318 UpdateSupportedKeySystems();
321 KeySystemsImpl::~KeySystemsImpl() {
324 SupportedCodecs KeySystemsImpl::GetCodecMaskForContainer(
325 const std::string& container) const {
326 ContainerCodecsMap::const_iterator iter =
327 container_to_codec_mask_map_.find(container);
328 if (iter != container_to_codec_mask_map_.end())
329 return iter->second;
330 return EME_CODEC_NONE;
333 EmeCodec KeySystemsImpl::GetCodecForString(const std::string& codec) const {
334 CodecsMap::const_iterator iter = codec_string_map_.find(codec);
335 if (iter != codec_string_map_.end())
336 return iter->second;
337 return EME_CODEC_NONE;
340 const std::string& KeySystemsImpl::PrefixedGetConcreteKeySystemNameFor(
341 const std::string& key_system) const {
342 ParentKeySystemMap::const_iterator iter =
343 parent_key_system_map_.find(key_system);
344 if (iter != parent_key_system_map_.end())
345 return iter->second;
346 return key_system;
349 void KeySystemsImpl::InitializeUMAInfo() {
350 DCHECK(thread_checker_.CalledOnValidThread());
351 DCHECK(key_system_name_for_uma_map_.empty());
353 std::vector<KeySystemInfoForUMA> key_systems_info_for_uma;
354 if (GetMediaClient())
355 GetMediaClient()->AddKeySystemsInfoForUMA(&key_systems_info_for_uma);
357 for (const KeySystemInfoForUMA& info : key_systems_info_for_uma) {
358 key_system_name_for_uma_map_[info.key_system] =
359 info.key_system_name_for_uma;
360 if (info.reports_key_system_support_to_uma)
361 key_systems_support_uma_.AddKeySystemToReport(info.key_system);
364 // Clear Key is always supported.
365 key_system_name_for_uma_map_[kClearKeyKeySystem] =
366 kClearKeyKeySystemNameForUMA;
369 void KeySystemsImpl::UpdateIfNeeded() {
370 if (GetMediaClient() && GetMediaClient()->IsKeySystemsUpdateNeeded())
371 UpdateSupportedKeySystems();
374 void KeySystemsImpl::UpdateSupportedKeySystems() {
375 DCHECK(thread_checker_.CalledOnValidThread());
376 concrete_key_system_map_.clear();
377 parent_key_system_map_.clear();
379 // Build KeySystemInfo.
380 std::vector<KeySystemInfo> key_systems_info;
382 // Add key systems supported by the MediaClient implementation.
383 if (GetMediaClient())
384 GetMediaClient()->AddSupportedKeySystems(&key_systems_info);
386 // Clear Key is always supported.
387 AddClearKey(&key_systems_info);
389 AddConcreteSupportedKeySystems(key_systems_info);
392 void KeySystemsImpl::AddConcreteSupportedKeySystems(
393 const std::vector<KeySystemInfo>& concrete_key_systems) {
394 DCHECK(thread_checker_.CalledOnValidThread());
395 DCHECK(concrete_key_system_map_.empty());
396 DCHECK(parent_key_system_map_.empty());
398 for (const KeySystemInfo& info : concrete_key_systems) {
399 DCHECK(!info.key_system.empty());
400 DCHECK(info.max_audio_robustness != EmeRobustness::INVALID);
401 DCHECK(info.max_video_robustness != EmeRobustness::INVALID);
402 DCHECK(info.persistent_license_support != EmeSessionTypeSupport::INVALID);
403 DCHECK(info.persistent_release_message_support !=
404 EmeSessionTypeSupport::INVALID);
405 DCHECK(info.persistent_state_support != EmeFeatureSupport::INVALID);
406 DCHECK(info.distinctive_identifier_support != EmeFeatureSupport::INVALID);
408 // Supporting persistent state is a prerequsite for supporting persistent
409 // sessions.
410 if (info.persistent_state_support == EmeFeatureSupport::NOT_SUPPORTED) {
411 DCHECK(info.persistent_license_support ==
412 EmeSessionTypeSupport::NOT_SUPPORTED);
413 DCHECK(info.persistent_release_message_support ==
414 EmeSessionTypeSupport::NOT_SUPPORTED);
417 // persistent-release-message sessions are not currently supported.
418 // http://crbug.com/448888
419 DCHECK(info.persistent_release_message_support ==
420 EmeSessionTypeSupport::NOT_SUPPORTED);
422 // If distinctive identifiers are not supported, then no other features can
423 // require them.
424 if (info.distinctive_identifier_support ==
425 EmeFeatureSupport::NOT_SUPPORTED) {
426 DCHECK(info.persistent_license_support !=
427 EmeSessionTypeSupport::SUPPORTED_WITH_IDENTIFIER);
428 DCHECK(info.persistent_release_message_support !=
429 EmeSessionTypeSupport::SUPPORTED_WITH_IDENTIFIER);
432 // Distinctive identifiers and persistent state can only be reliably blocked
433 // (and therefore be safely configurable) for Pepper-hosted key systems. For
434 // other platforms, (except for the AES decryptor) assume that the CDM can
435 // and will do anything.
436 bool can_block = info.use_aes_decryptor;
437 #if defined(ENABLE_PEPPER_CDMS)
438 DCHECK_EQ(info.use_aes_decryptor, info.pepper_type.empty());
439 if (!info.pepper_type.empty())
440 can_block = true;
441 #endif
442 if (!can_block) {
443 DCHECK(info.distinctive_identifier_support ==
444 EmeFeatureSupport::ALWAYS_ENABLED);
445 DCHECK(info.persistent_state_support ==
446 EmeFeatureSupport::ALWAYS_ENABLED);
449 DCHECK(!IsSupportedKeySystem(info.key_system))
450 << "Key system '" << info.key_system << "' already registered";
451 DCHECK(!parent_key_system_map_.count(info.key_system))
452 << "'" << info.key_system << "' is already registered as a parent";
453 concrete_key_system_map_[info.key_system] = info;
454 if (!info.parent_key_system.empty()) {
455 DCHECK(!IsConcreteSupportedKeySystem(info.parent_key_system))
456 << "Parent '" << info.parent_key_system << "' "
457 << "already registered concrete";
458 DCHECK(!parent_key_system_map_.count(info.parent_key_system))
459 << "Parent '" << info.parent_key_system << "' already registered";
460 parent_key_system_map_[info.parent_key_system] = info.key_system;
465 bool KeySystemsImpl::IsConcreteSupportedKeySystem(
466 const std::string& key_system) const {
467 DCHECK(thread_checker_.CalledOnValidThread());
468 return concrete_key_system_map_.count(key_system) != 0;
471 bool KeySystemsImpl::IsSupportedContainer(
472 const std::string& container,
473 SupportedCodecs key_system_supported_codecs) const {
474 DCHECK(thread_checker_.CalledOnValidThread());
475 DCHECK(!container.empty());
477 // When checking container support for EME, "audio/foo" should be treated the
478 // same as "video/foo". Convert the |container| to achieve this.
479 // TODO(xhwang): Replace this with real checks against supported initDataTypes
480 // combined with supported demuxers.
481 std::string canonical_container = container;
482 if (container.find("audio/") == 0)
483 canonical_container.replace(0, 6, "video/");
485 // A container is supported iif at least one codec in that container is
486 // supported.
487 SupportedCodecs supported_codecs =
488 GetCodecMaskForContainer(canonical_container);
489 return (supported_codecs & key_system_supported_codecs) != 0;
492 bool KeySystemsImpl::IsSupportedContainerAndCodecs(
493 const std::string& container,
494 const std::vector<std::string>& codecs,
495 SupportedCodecs key_system_supported_codecs) const {
496 DCHECK(thread_checker_.CalledOnValidThread());
497 DCHECK(!container.empty());
498 DCHECK(!codecs.empty());
499 DCHECK(IsSupportedContainer(container, key_system_supported_codecs));
501 SupportedCodecs container_supported_codecs =
502 GetCodecMaskForContainer(container);
504 for (size_t i = 0; i < codecs.size(); ++i) {
505 if (codecs[i].empty())
506 continue;
508 EmeCodec codec = GetCodecForString(codecs[i]);
510 // Unsupported codec.
511 if (!(codec & key_system_supported_codecs))
512 return false;
514 // Unsupported codec/container combination, e.g. "video/webm" and "avc1".
515 if (!(codec & container_supported_codecs))
516 return false;
519 return true;
522 bool KeySystemsImpl::IsSupportedInitDataType(
523 const std::string& key_system,
524 EmeInitDataType init_data_type) const {
525 DCHECK(thread_checker_.CalledOnValidThread());
527 // Locate |key_system|. Only concrete key systems are supported in unprefixed.
528 KeySystemInfoMap::const_iterator key_system_iter =
529 concrete_key_system_map_.find(key_system);
530 if (key_system_iter == concrete_key_system_map_.end()) {
531 NOTREACHED();
532 return false;
535 // Check |init_data_type|.
536 InitDataTypeMask available_init_data_types =
537 key_system_iter->second.supported_init_data_types;
538 switch (init_data_type) {
539 case EmeInitDataType::UNKNOWN:
540 return false;
541 case EmeInitDataType::WEBM:
542 return (available_init_data_types & kInitDataTypeMaskWebM) != 0;
543 case EmeInitDataType::CENC:
544 return (available_init_data_types & kInitDataTypeMaskCenc) != 0;
545 case EmeInitDataType::KEYIDS:
546 return (available_init_data_types & kInitDataTypeMaskKeyIds) != 0;
548 NOTREACHED();
549 return false;
552 bool KeySystemsImpl::PrefixedIsSupportedKeySystemWithMediaMimeType(
553 const std::string& mime_type,
554 const std::vector<std::string>& codecs,
555 const std::string& key_system) {
556 DCHECK(thread_checker_.CalledOnValidThread());
558 const std::string& concrete_key_system =
559 PrefixedGetConcreteKeySystemNameFor(key_system);
561 bool has_type = !mime_type.empty();
563 key_systems_support_uma_.ReportKeySystemQuery(key_system, has_type);
565 // Check key system support.
566 KeySystemInfoMap::const_iterator key_system_iter =
567 concrete_key_system_map_.find(concrete_key_system);
568 if (key_system_iter == concrete_key_system_map_.end())
569 return false;
571 key_systems_support_uma_.ReportKeySystemSupport(key_system, false);
573 if (!has_type) {
574 DCHECK(codecs.empty());
575 return true;
578 SupportedCodecs key_system_supported_codecs =
579 key_system_iter->second.supported_codecs;
581 if (!IsSupportedContainer(mime_type, key_system_supported_codecs))
582 return false;
584 if (!codecs.empty() &&
585 !IsSupportedContainerAndCodecs(
586 mime_type, codecs, key_system_supported_codecs)) {
587 return false;
590 key_systems_support_uma_.ReportKeySystemSupport(key_system, true);
592 return true;
595 std::string KeySystemsImpl::GetKeySystemNameForUMA(
596 const std::string& key_system) const {
597 DCHECK(thread_checker_.CalledOnValidThread());
599 KeySystemNameForUMAMap::const_iterator iter =
600 key_system_name_for_uma_map_.find(key_system);
601 if (iter == key_system_name_for_uma_map_.end())
602 return kUnknownKeySystemNameForUMA;
604 return iter->second;
607 bool KeySystemsImpl::UseAesDecryptor(
608 const std::string& concrete_key_system) const {
609 DCHECK(thread_checker_.CalledOnValidThread());
611 KeySystemInfoMap::const_iterator key_system_iter =
612 concrete_key_system_map_.find(concrete_key_system);
613 if (key_system_iter == concrete_key_system_map_.end()) {
614 DLOG(ERROR) << concrete_key_system << " is not a known concrete system";
615 return false;
618 return key_system_iter->second.use_aes_decryptor;
621 #if defined(ENABLE_PEPPER_CDMS)
622 std::string KeySystemsImpl::GetPepperType(
623 const std::string& concrete_key_system) const {
624 DCHECK(thread_checker_.CalledOnValidThread());
626 KeySystemInfoMap::const_iterator key_system_iter =
627 concrete_key_system_map_.find(concrete_key_system);
628 if (key_system_iter == concrete_key_system_map_.end()) {
629 DLOG(FATAL) << concrete_key_system << " is not a known concrete system";
630 return std::string();
633 const std::string& type = key_system_iter->second.pepper_type;
634 DLOG_IF(FATAL, type.empty()) << concrete_key_system << " is not Pepper-based";
635 return type;
637 #endif
639 void KeySystemsImpl::AddContainerMask(
640 const std::string& container,
641 uint32 mask) {
642 DCHECK(thread_checker_.CalledOnValidThread());
643 DCHECK(!container_to_codec_mask_map_.count(container));
644 container_to_codec_mask_map_[container] = static_cast<EmeCodec>(mask);
647 void KeySystemsImpl::AddCodecMask(
648 EmeMediaType media_type,
649 const std::string& codec,
650 uint32 mask) {
651 DCHECK(thread_checker_.CalledOnValidThread());
652 DCHECK(!codec_string_map_.count(codec));
653 codec_string_map_[codec] = static_cast<EmeCodec>(mask);
654 if (media_type == EmeMediaType::AUDIO) {
655 audio_codec_mask_ |= mask;
656 } else {
657 video_codec_mask_ |= mask;
661 bool KeySystemsImpl::IsSupportedKeySystem(const std::string& key_system) const {
662 DCHECK(thread_checker_.CalledOnValidThread());
663 return concrete_key_system_map_.count(key_system) != 0;
666 EmeConfigRule KeySystemsImpl::GetContentTypeConfigRule(
667 const std::string& key_system,
668 EmeMediaType media_type,
669 const std::string& container_mime_type,
670 const std::vector<std::string>& codecs) const {
671 DCHECK(thread_checker_.CalledOnValidThread());
673 // Make sure the container matches |media_type|.
674 SupportedCodecs media_type_codec_mask = EME_CODEC_NONE;
675 switch (media_type) {
676 case EmeMediaType::AUDIO:
677 if (!base::StartsWith(container_mime_type, "audio/",
678 base::CompareCase::SENSITIVE))
679 return EmeConfigRule::NOT_SUPPORTED;
680 media_type_codec_mask = audio_codec_mask_;
681 break;
682 case EmeMediaType::VIDEO:
683 if (!base::StartsWith(container_mime_type, "video/",
684 base::CompareCase::SENSITIVE))
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. The goal is to
720 // prevent mixing of non-hardware-secure codecs with hardware-secure codecs,
721 // since the mode is fixed at CDM creation.
723 // Because the check for regular codec support is early-exit, we don't have
724 // to consider codecs that are only supported in hardware-secure mode. We
725 // could do so, and make use of HW_SECURE_CODECS_REQUIRED, if it turns out
726 // that hardware-secure-only codecs actually exist and are useful.
727 if ((codec & key_system_secure_codec_mask) == 0)
728 support = EmeConfigRule::HW_SECURE_CODECS_NOT_ALLOWED;
729 #endif // defined(OS_ANDROID)
732 return support;
735 EmeConfigRule KeySystemsImpl::GetRobustnessConfigRule(
736 const std::string& key_system,
737 EmeMediaType media_type,
738 const std::string& requested_robustness) const {
739 DCHECK(thread_checker_.CalledOnValidThread());
741 EmeRobustness robustness = ConvertRobustness(requested_robustness);
742 if (robustness == EmeRobustness::INVALID)
743 return EmeConfigRule::NOT_SUPPORTED;
744 if (robustness == EmeRobustness::EMPTY)
745 return EmeConfigRule::SUPPORTED;
747 KeySystemInfoMap::const_iterator key_system_iter =
748 concrete_key_system_map_.find(key_system);
749 if (key_system_iter == concrete_key_system_map_.end()) {
750 NOTREACHED();
751 return EmeConfigRule::NOT_SUPPORTED;
754 EmeRobustness max_robustness = EmeRobustness::INVALID;
755 switch (media_type) {
756 case EmeMediaType::AUDIO:
757 max_robustness = key_system_iter->second.max_audio_robustness;
758 break;
759 case EmeMediaType::VIDEO:
760 max_robustness = key_system_iter->second.max_video_robustness;
761 break;
764 // We can compare robustness levels whenever they are not HW_SECURE_CRYPTO
765 // and SW_SECURE_DECODE in some order. If they are exactly those two then the
766 // robustness requirement is not supported.
767 if ((max_robustness == EmeRobustness::HW_SECURE_CRYPTO &&
768 robustness == EmeRobustness::SW_SECURE_DECODE) ||
769 (max_robustness == EmeRobustness::SW_SECURE_DECODE &&
770 robustness == EmeRobustness::HW_SECURE_CRYPTO) ||
771 robustness > max_robustness) {
772 return EmeConfigRule::NOT_SUPPORTED;
775 if (key_system == kWidevineKeySystem) {
776 #if defined(OS_CHROMEOS)
777 // Hardware security requires remote attestation.
778 if (robustness >= EmeRobustness::HW_SECURE_CRYPTO)
779 return EmeConfigRule::IDENTIFIER_REQUIRED;
781 // For video, recommend remote attestation if HW_SECURE_ALL is available,
782 // because it enables hardware accelerated decoding.
783 // TODO(sandersd): Only do this when hardware accelerated decoding is
784 // available for the requested codecs.
785 if (media_type == EmeMediaType::VIDEO &&
786 max_robustness == EmeRobustness::HW_SECURE_ALL) {
787 return EmeConfigRule::IDENTIFIER_RECOMMENDED;
789 #elif defined(OS_ANDROID)
790 if (robustness > EmeRobustness::SW_SECURE_CRYPTO)
791 return EmeConfigRule::HW_SECURE_CODECS_REQUIRED;
792 #endif // defined(OS_CHROMEOS)
795 return EmeConfigRule::SUPPORTED;
798 EmeSessionTypeSupport KeySystemsImpl::GetPersistentLicenseSessionSupport(
799 const std::string& key_system) const {
800 DCHECK(thread_checker_.CalledOnValidThread());
802 KeySystemInfoMap::const_iterator key_system_iter =
803 concrete_key_system_map_.find(key_system);
804 if (key_system_iter == concrete_key_system_map_.end()) {
805 NOTREACHED();
806 return EmeSessionTypeSupport::INVALID;
808 return key_system_iter->second.persistent_license_support;
811 EmeSessionTypeSupport KeySystemsImpl::GetPersistentReleaseMessageSessionSupport(
812 const std::string& key_system) const {
813 DCHECK(thread_checker_.CalledOnValidThread());
815 KeySystemInfoMap::const_iterator key_system_iter =
816 concrete_key_system_map_.find(key_system);
817 if (key_system_iter == concrete_key_system_map_.end()) {
818 NOTREACHED();
819 return EmeSessionTypeSupport::INVALID;
821 return key_system_iter->second.persistent_release_message_support;
824 EmeFeatureSupport KeySystemsImpl::GetPersistentStateSupport(
825 const std::string& key_system) const {
826 DCHECK(thread_checker_.CalledOnValidThread());
828 KeySystemInfoMap::const_iterator key_system_iter =
829 concrete_key_system_map_.find(key_system);
830 if (key_system_iter == concrete_key_system_map_.end()) {
831 NOTREACHED();
832 return EmeFeatureSupport::INVALID;
834 return key_system_iter->second.persistent_state_support;
837 EmeFeatureSupport KeySystemsImpl::GetDistinctiveIdentifierSupport(
838 const std::string& key_system) const {
839 DCHECK(thread_checker_.CalledOnValidThread());
841 KeySystemInfoMap::const_iterator key_system_iter =
842 concrete_key_system_map_.find(key_system);
843 if (key_system_iter == concrete_key_system_map_.end()) {
844 NOTREACHED();
845 return EmeFeatureSupport::INVALID;
847 return key_system_iter->second.distinctive_identifier_support;
850 KeySystems* KeySystems::GetInstance() {
851 return KeySystemsImpl::GetInstance();
854 //------------------------------------------------------------------------------
856 std::string GetUnprefixedKeySystemName(const std::string& key_system) {
857 if (key_system == kClearKeyKeySystem)
858 return kUnsupportedClearKeyKeySystem;
860 if (key_system == kPrefixedClearKeyKeySystem)
861 return kClearKeyKeySystem;
863 return key_system;
866 std::string GetPrefixedKeySystemName(const std::string& key_system) {
867 DCHECK_NE(key_system, kPrefixedClearKeyKeySystem);
869 if (key_system == kClearKeyKeySystem)
870 return kPrefixedClearKeyKeySystem;
872 return key_system;
875 bool PrefixedIsSupportedConcreteKeySystem(const std::string& key_system) {
876 return KeySystemsImpl::GetInstance()->IsConcreteSupportedKeySystem(
877 key_system);
880 bool IsSupportedKeySystem(const std::string& key_system) {
881 if (!KeySystemsImpl::GetInstance()->IsSupportedKeySystem(key_system))
882 return false;
884 // TODO(ddorwin): Move this to where we add key systems when prefixed EME is
885 // removed (crbug.com/249976).
886 if (!IsPotentiallySupportedKeySystem(key_system)) {
887 // If you encounter this path, see the comments for the above function.
888 NOTREACHED() << "Unrecognized key system " << key_system
889 << ". See code comments.";
890 return false;
893 return true;
896 bool IsSupportedKeySystemWithInitDataType(const std::string& key_system,
897 EmeInitDataType init_data_type) {
898 return KeySystemsImpl::GetInstance()->IsSupportedInitDataType(key_system,
899 init_data_type);
902 bool PrefixedIsSupportedKeySystemWithMediaMimeType(
903 const std::string& mime_type,
904 const std::vector<std::string>& codecs,
905 const std::string& key_system) {
906 return KeySystemsImpl::GetInstance()
907 ->PrefixedIsSupportedKeySystemWithMediaMimeType(mime_type, codecs,
908 key_system);
911 std::string GetKeySystemNameForUMA(const std::string& key_system) {
912 return KeySystemsImpl::GetInstance()->GetKeySystemNameForUMA(key_system);
915 bool CanUseAesDecryptor(const std::string& concrete_key_system) {
916 return KeySystemsImpl::GetInstance()->UseAesDecryptor(concrete_key_system);
919 #if defined(ENABLE_PEPPER_CDMS)
920 std::string GetPepperType(const std::string& concrete_key_system) {
921 return KeySystemsImpl::GetInstance()->GetPepperType(concrete_key_system);
923 #endif
925 // These two functions are for testing purpose only. The declaration in the
926 // header file is guarded by "#if defined(UNIT_TEST)" so that they can be used
927 // by tests but not non-test code. However, this .cc file is compiled as part of
928 // "media" where "UNIT_TEST" is not defined. So we need to specify
929 // "MEDIA_EXPORT" here again so that they are visible to tests.
931 MEDIA_EXPORT void AddContainerMask(const std::string& container, uint32 mask) {
932 KeySystemsImpl::GetInstance()->AddContainerMask(container, mask);
935 MEDIA_EXPORT void AddCodecMask(
936 EmeMediaType media_type,
937 const std::string& codec,
938 uint32 mask) {
939 KeySystemsImpl::GetInstance()->AddCodecMask(media_type, codec, mask);
942 } // namespace media