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. 4 5 #include "content/renderer/media/crypto/key_systems.h" 6 7 #include <map> 8 9 #include "base/lazy_instance.h" 10 #include "base/logging.h" 11 #include "base/strings/string_util.h" 12 #include "content/renderer/media/crypto/key_systems_info.h" 13 #include "net/base/mime_util.h" 14 #include "third_party/WebKit/public/platform/WebCString.h" 15 #include "third_party/WebKit/public/platform/WebString.h" 16 17 namespace content { 18 19 // Convert a WebString to ASCII, falling back on an empty string in the case 20 // of a non-ASCII string. 21 static std::string ToASCIIOrEmpty(const WebKit::WebString& string) { 22 return IsStringASCII(string) ? UTF16ToASCII(string) : std::string(); 23 } 24 25 class KeySystems { 26 public: 27 bool IsSupportedKeySystem(const std::string& key_system); 28 29 bool IsSupportedKeySystemWithMediaMimeType( 30 const std::string& mime_type, 31 const std::vector<std::string>& codecs, 32 const std::string& key_system); 33 34 private: 35 friend struct base::DefaultLazyInstanceTraits<KeySystems>; 36 37 typedef base::hash_set<std::string> CodecMappings; 38 typedef std::map<std::string, CodecMappings> MimeTypeMappings; 39 typedef std::map<std::string, MimeTypeMappings> KeySystemMappings; 40 41 KeySystems(); 42 43 bool IsSupportedKeySystemWithContainerAndCodec( 44 const std::string& mime_type, 45 const std::string& codec, 46 const std::string& key_system); 47 48 KeySystemMappings key_system_map_; 49 50 DISALLOW_COPY_AND_ASSIGN(KeySystems); 51 }; 52 53 static base::LazyInstance<KeySystems> g_key_systems = LAZY_INSTANCE_INITIALIZER; 54 55 KeySystems::KeySystems() { 56 // Initialize the supported media type/key system combinations. 57 for (int i = 0; i < kNumSupportedFormatKeySystemCombinations; ++i) { 58 const MediaFormatAndKeySystem& combination = 59 kSupportedFormatKeySystemCombinations[i]; 60 std::vector<std::string> mime_type_codecs; 61 net::ParseCodecString(combination.codecs_list, 62 &mime_type_codecs, 63 false); 64 65 CodecMappings codecs; 66 for (size_t j = 0; j < mime_type_codecs.size(); ++j) 67 codecs.insert(mime_type_codecs[j]); 68 // Support the MIME type string alone, without codec(s) specified. 69 codecs.insert(std::string()); 70 71 // Key systems can be repeated, so there may already be an entry. 72 KeySystemMappings::iterator key_system_iter = 73 key_system_map_.find(combination.key_system); 74 if (key_system_iter == key_system_map_.end()) { 75 MimeTypeMappings mime_types_map; 76 mime_types_map[combination.mime_type] = codecs; 77 key_system_map_[combination.key_system] = mime_types_map; 78 } else { 79 MimeTypeMappings& mime_types_map = key_system_iter->second; 80 // mime_types_map may not be repeated for a given key system. 81 DCHECK(mime_types_map.find(combination.mime_type) == 82 mime_types_map.end()); 83 mime_types_map[combination.mime_type] = codecs; 84 } 85 } 86 } 87 88 bool KeySystems::IsSupportedKeySystem(const std::string& key_system) { 89 bool is_supported = key_system_map_.find(key_system) != key_system_map_.end(); 90 return is_supported && IsSystemCompatible(key_system); 91 } 92 93 bool KeySystems::IsSupportedKeySystemWithContainerAndCodec( 94 const std::string& mime_type, 95 const std::string& codec, 96 const std::string& key_system) { 97 KeySystemMappings::const_iterator key_system_iter = 98 key_system_map_.find(key_system); 99 if (key_system_iter == key_system_map_.end()) 100 return false; 101 102 const MimeTypeMappings& mime_types_map = key_system_iter->second; 103 MimeTypeMappings::const_iterator mime_iter = mime_types_map.find(mime_type); 104 if (mime_iter == mime_types_map.end()) 105 return false; 106 107 const CodecMappings& codecs = mime_iter->second; 108 return (codecs.find(codec) != codecs.end()) && IsSystemCompatible(key_system); 109 } 110 111 bool KeySystems::IsSupportedKeySystemWithMediaMimeType( 112 const std::string& mime_type, 113 const std::vector<std::string>& codecs, 114 const std::string& key_system) { 115 // This method is only used by the canPlaytType() path (not the EME methods), 116 // so we check for suppressed key_systems here. 117 if(IsCanPlayTypeSuppressed(key_system)) 118 return false; 119 120 if (codecs.empty()) 121 return IsSupportedKeySystemWithContainerAndCodec( 122 mime_type, std::string(), key_system); 123 124 for (size_t i = 0; i < codecs.size(); ++i) { 125 if (!IsSupportedKeySystemWithContainerAndCodec( 126 mime_type, codecs[i], key_system)) 127 return false; 128 } 129 130 return true; 131 } 132 133 bool IsSupportedKeySystem(const WebKit::WebString& key_system) { 134 return g_key_systems.Get().IsSupportedKeySystem(ToASCIIOrEmpty(key_system)); 135 } 136 137 bool IsSupportedKeySystemWithMediaMimeType( 138 const std::string& mime_type, 139 const std::vector<std::string>& codecs, 140 const std::string& key_system) { 141 return g_key_systems.Get().IsSupportedKeySystemWithMediaMimeType( 142 mime_type, codecs, key_system); 143 } 144 145 std::string KeySystemNameForUMA(const WebKit::WebString& key_system) { 146 return KeySystemNameForUMAInternal(key_system); 147 } 148 149 bool CanUseAesDecryptor(const std::string& key_system) { 150 return CanUseBuiltInAesDecryptor(key_system); 151 } 152 153 #if defined(ENABLE_PEPPER_CDMS) 154 std::string GetPepperType(const std::string& key_system) { 155 for (int i = 0; i < kNumKeySystemToPepperTypeMapping; ++i) { 156 if (kKeySystemToPepperTypeMapping[i].key_system == key_system) 157 return kKeySystemToPepperTypeMapping[i].type; 158 } 159 160 return std::string(); 161 } 162 #endif // defined(ENABLE_PEPPER_CDMS) 163 164 #if defined(OS_ANDROID) 165 std::vector<uint8> GetUUID(const std::string& key_system) { 166 for (int i = 0; i < kNumKeySystemToUUIDMapping; ++i) { 167 if (kKeySystemToUUIDMapping[i].key_system == key_system) 168 return std::vector<uint8>(kKeySystemToUUIDMapping[i].uuid, 169 kKeySystemToUUIDMapping[i].uuid + 16); 170 } 171 return std::vector<uint8>(); 172 } 173 #endif // defined(OS_ANDROID) 174 175 } // namespace content 176