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 "chrome/renderer/media/chrome_key_systems.h"
10 #include "base/logging.h"
11 #include "base/strings/string16.h"
12 #include "base/strings/string_split.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "chrome/common/render_messages.h"
15 #include "components/cdm/renderer/widevine_key_systems.h"
16 #include "content/public/renderer/render_thread.h"
17 #include "media/base/eme_constants.h"
19 #if defined(OS_ANDROID)
20 #include "components/cdm/renderer/android_key_systems.h"
23 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
25 // The following must be after widevine_cdm_version.h.
27 #if defined(WIDEVINE_CDM_AVAILABLE) && defined(WIDEVINE_CDM_MIN_GLIBC_VERSION)
28 #include <gnu/libc-version.h>
29 #include "base/version.h"
32 using media::KeySystemInfo
;
33 using media::SupportedCodecs
;
35 #if defined(ENABLE_PEPPER_CDMS)
36 static bool IsPepperCdmAvailable(
37 const std::string
& pepper_type
,
38 std::vector
<base::string16
>* additional_param_names
,
39 std::vector
<base::string16
>* additional_param_values
) {
40 bool is_available
= false;
41 content::RenderThread::Get()->Send(
42 new ChromeViewHostMsg_IsInternalPluginAvailableForMimeType(
45 additional_param_names
,
46 additional_param_values
));
51 // External Clear Key (used for testing).
52 static void AddExternalClearKey(
53 std::vector
<KeySystemInfo
>* concrete_key_systems
) {
54 static const char kExternalClearKeyKeySystem
[] =
55 "org.chromium.externalclearkey";
56 static const char kExternalClearKeyDecryptOnlyKeySystem
[] =
57 "org.chromium.externalclearkey.decryptonly";
58 static const char kExternalClearKeyFileIOTestKeySystem
[] =
59 "org.chromium.externalclearkey.fileiotest";
60 static const char kExternalClearKeyInitializeFailKeySystem
[] =
61 "org.chromium.externalclearkey.initializefail";
62 static const char kExternalClearKeyCrashKeySystem
[] =
63 "org.chromium.externalclearkey.crash";
64 static const char kExternalClearKeyPepperType
[] =
65 "application/x-ppapi-clearkey-cdm";
67 std::vector
<base::string16
> additional_param_names
;
68 std::vector
<base::string16
> additional_param_values
;
69 if (!IsPepperCdmAvailable(kExternalClearKeyPepperType
,
70 &additional_param_names
,
71 &additional_param_values
)) {
75 KeySystemInfo
info(kExternalClearKeyKeySystem
);
77 info
.supported_codecs
= media::EME_CODEC_WEBM_ALL
;
78 info
.supported_init_data_types
= media::EME_INIT_DATA_TYPE_WEBM
;
79 #if defined(USE_PROPRIETARY_CODECS)
80 info
.supported_codecs
|= media::EME_CODEC_MP4_ALL
;
81 info
.supported_init_data_types
|= media::EME_INIT_DATA_TYPE_CENC
;
82 #endif // defined(USE_PROPRIETARY_CODECS)
84 info
.pepper_type
= kExternalClearKeyPepperType
;
86 concrete_key_systems
->push_back(info
);
88 // Add support of decrypt-only mode in ClearKeyCdm.
89 info
.key_system
= kExternalClearKeyDecryptOnlyKeySystem
;
90 concrete_key_systems
->push_back(info
);
92 // A key system that triggers FileIO test in ClearKeyCdm.
93 info
.key_system
= kExternalClearKeyFileIOTestKeySystem
;
94 concrete_key_systems
->push_back(info
);
96 // A key system that Chrome thinks is supported by ClearKeyCdm, but actually
97 // will be refused by ClearKeyCdm. This is to test the CDM initialization
99 info
.key_system
= kExternalClearKeyInitializeFailKeySystem
;
100 concrete_key_systems
->push_back(info
);
102 // A key system that triggers a crash in ClearKeyCdm.
103 info
.key_system
= kExternalClearKeyCrashKeySystem
;
104 concrete_key_systems
->push_back(info
);
107 #if defined(WIDEVINE_CDM_AVAILABLE)
108 // This function finds "codecs" and parses the value into the vector |codecs|.
109 // Converts the codec strings to UTF-8 since we only expect ASCII strings and
110 // this simplifies the rest of the code in this file.
111 void GetSupportedCodecsForPepperCdm(
112 const std::vector
<base::string16
>& additional_param_names
,
113 const std::vector
<base::string16
>& additional_param_values
,
114 std::vector
<std::string
>* codecs
) {
115 DCHECK(codecs
->empty());
116 DCHECK_EQ(additional_param_names
.size(), additional_param_values
.size());
117 for (size_t i
= 0; i
< additional_param_names
.size(); ++i
) {
118 if (additional_param_names
[i
] ==
119 base::ASCIIToUTF16(kCdmSupportedCodecsParamName
)) {
120 const base::string16
& codecs_string16
= additional_param_values
[i
];
121 std::string codecs_string
;
122 if (!base::UTF16ToUTF8(codecs_string16
.c_str(),
123 codecs_string16
.length(),
125 DLOG(WARNING
) << "Non-UTF-8 codecs string.";
126 // Continue using the best effort conversion.
128 base::SplitString(codecs_string
,
129 kCdmSupportedCodecsValueDelimiter
,
136 static void AddPepperBasedWidevine(
137 std::vector
<KeySystemInfo
>* concrete_key_systems
) {
138 #if defined(WIDEVINE_CDM_MIN_GLIBC_VERSION)
139 Version
glibc_version(gnu_get_libc_version());
140 DCHECK(glibc_version
.IsValid());
141 if (glibc_version
.IsOlderThan(WIDEVINE_CDM_MIN_GLIBC_VERSION
))
143 #endif // defined(WIDEVINE_CDM_MIN_GLIBC_VERSION)
145 std::vector
<base::string16
> additional_param_names
;
146 std::vector
<base::string16
> additional_param_values
;
147 if (!IsPepperCdmAvailable(kWidevineCdmPluginMimeType
,
148 &additional_param_names
,
149 &additional_param_values
)) {
150 DVLOG(1) << "Widevine CDM is not currently available.";
154 std::vector
<std::string
> codecs
;
155 GetSupportedCodecsForPepperCdm(additional_param_names
,
156 additional_param_values
,
159 SupportedCodecs supported_codecs
= media::EME_CODEC_NONE
;
161 // Audio codecs are always supported.
162 // TODO(sandersd): Distinguish these from those that are directly supported,
163 // as those may offer a higher level of protection.
164 supported_codecs
|= media::EME_CODEC_WEBM_OPUS
;
165 supported_codecs
|= media::EME_CODEC_WEBM_VORBIS
;
166 #if defined(USE_PROPRIETARY_CODECS)
167 supported_codecs
|= media::EME_CODEC_MP4_AAC
;
168 #endif // defined(USE_PROPRIETARY_CODECS)
170 for (size_t i
= 0; i
< codecs
.size(); ++i
) {
171 if (codecs
[i
] == kCdmSupportedCodecVp8
)
172 supported_codecs
|= media::EME_CODEC_WEBM_VP8
;
173 if (codecs
[i
] == kCdmSupportedCodecVp9
)
174 supported_codecs
|= media::EME_CODEC_WEBM_VP9
;
175 #if defined(USE_PROPRIETARY_CODECS)
176 if (codecs
[i
] == kCdmSupportedCodecAvc1
)
177 supported_codecs
|= media::EME_CODEC_MP4_AVC1
;
178 #endif // defined(USE_PROPRIETARY_CODECS)
181 cdm::AddWidevineWithCodecs(cdm::WIDEVINE
,
183 concrete_key_systems
);
185 #endif // defined(WIDEVINE_CDM_AVAILABLE)
186 #endif // defined(ENABLE_PEPPER_CDMS)
188 void AddChromeKeySystems(std::vector
<KeySystemInfo
>* key_systems_info
) {
189 #if defined(ENABLE_PEPPER_CDMS)
190 AddExternalClearKey(key_systems_info
);
192 #if defined(WIDEVINE_CDM_AVAILABLE)
193 AddPepperBasedWidevine(key_systems_info
);
194 #endif // defined(WIDEVINE_CDM_AVAILABLE)
195 #endif // defined(ENABLE_PEPPER_CDMS)
197 #if defined(OS_ANDROID)
198 cdm::AddAndroidWidevine(key_systems_info
);
199 #endif // defined(OS_ANDROID)