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
)) {
76 info
.key_system
= kExternalClearKeyKeySystem
;
78 info
.supported_init_data_types
=
79 media::kInitDataTypeMaskWebM
| media::kInitDataTypeMaskKeyIds
;
80 info
.supported_codecs
= media::EME_CODEC_WEBM_ALL
;
81 #if defined(USE_PROPRIETARY_CODECS)
82 info
.supported_init_data_types
|= media::kInitDataTypeMaskCenc
;
83 info
.supported_codecs
|= media::EME_CODEC_MP4_ALL
;
84 #endif // defined(USE_PROPRIETARY_CODECS)
86 info
.max_audio_robustness
= media::EmeRobustness::EMPTY
;
87 info
.max_video_robustness
= media::EmeRobustness::EMPTY
;
89 // Persistent sessions are faked.
90 info
.persistent_license_support
= media::EmeSessionTypeSupport::SUPPORTED
;
91 info
.persistent_release_message_support
=
92 media::EmeSessionTypeSupport::NOT_SUPPORTED
;
93 info
.persistent_state_support
= media::EmeFeatureSupport::REQUESTABLE
;
94 info
.distinctive_identifier_support
= media::EmeFeatureSupport::NOT_SUPPORTED
;
96 info
.pepper_type
= kExternalClearKeyPepperType
;
98 concrete_key_systems
->push_back(info
);
100 // Add support of decrypt-only mode in ClearKeyCdm.
101 info
.key_system
= kExternalClearKeyDecryptOnlyKeySystem
;
102 concrete_key_systems
->push_back(info
);
104 // A key system that triggers FileIO test in ClearKeyCdm.
105 info
.key_system
= kExternalClearKeyFileIOTestKeySystem
;
106 concrete_key_systems
->push_back(info
);
108 // A key system that Chrome thinks is supported by ClearKeyCdm, but actually
109 // will be refused by ClearKeyCdm. This is to test the CDM initialization
111 info
.key_system
= kExternalClearKeyInitializeFailKeySystem
;
112 concrete_key_systems
->push_back(info
);
114 // A key system that triggers a crash in ClearKeyCdm.
115 info
.key_system
= kExternalClearKeyCrashKeySystem
;
116 concrete_key_systems
->push_back(info
);
119 #if defined(WIDEVINE_CDM_AVAILABLE)
120 // This function finds "codecs" and parses the value into the vector |codecs|.
121 // Converts the codec strings to UTF-8 since we only expect ASCII strings and
122 // this simplifies the rest of the code in this file.
123 void GetSupportedCodecsForPepperCdm(
124 const std::vector
<base::string16
>& additional_param_names
,
125 const std::vector
<base::string16
>& additional_param_values
,
126 std::vector
<std::string
>* codecs
) {
127 DCHECK(codecs
->empty());
128 DCHECK_EQ(additional_param_names
.size(), additional_param_values
.size());
129 for (size_t i
= 0; i
< additional_param_names
.size(); ++i
) {
130 if (additional_param_names
[i
] ==
131 base::ASCIIToUTF16(kCdmSupportedCodecsParamName
)) {
132 const base::string16
& codecs_string16
= additional_param_values
[i
];
133 std::string codecs_string
;
134 if (!base::UTF16ToUTF8(codecs_string16
.c_str(),
135 codecs_string16
.length(),
137 DLOG(WARNING
) << "Non-UTF-8 codecs string.";
138 // Continue using the best effort conversion.
140 *codecs
= base::SplitString(
141 codecs_string
, std::string(1, kCdmSupportedCodecsValueDelimiter
),
142 base::TRIM_WHITESPACE
, base::SPLIT_WANT_ALL
);
148 static void AddPepperBasedWidevine(
149 std::vector
<KeySystemInfo
>* concrete_key_systems
) {
150 #if defined(WIDEVINE_CDM_MIN_GLIBC_VERSION)
151 Version
glibc_version(gnu_get_libc_version());
152 DCHECK(glibc_version
.IsValid());
153 if (glibc_version
.IsOlderThan(WIDEVINE_CDM_MIN_GLIBC_VERSION
))
155 #endif // defined(WIDEVINE_CDM_MIN_GLIBC_VERSION)
157 std::vector
<base::string16
> additional_param_names
;
158 std::vector
<base::string16
> additional_param_values
;
159 if (!IsPepperCdmAvailable(kWidevineCdmPluginMimeType
,
160 &additional_param_names
,
161 &additional_param_values
)) {
162 DVLOG(1) << "Widevine CDM is not currently available.";
166 std::vector
<std::string
> codecs
;
167 GetSupportedCodecsForPepperCdm(additional_param_names
,
168 additional_param_values
,
171 SupportedCodecs supported_codecs
= media::EME_CODEC_NONE
;
173 // Audio codecs are always supported.
174 // TODO(sandersd): Distinguish these from those that are directly supported,
175 // as those may offer a higher level of protection.
176 supported_codecs
|= media::EME_CODEC_WEBM_OPUS
;
177 supported_codecs
|= media::EME_CODEC_WEBM_VORBIS
;
178 #if defined(USE_PROPRIETARY_CODECS)
179 supported_codecs
|= media::EME_CODEC_MP4_AAC
;
180 #endif // defined(USE_PROPRIETARY_CODECS)
182 for (size_t i
= 0; i
< codecs
.size(); ++i
) {
183 if (codecs
[i
] == kCdmSupportedCodecVp8
)
184 supported_codecs
|= media::EME_CODEC_WEBM_VP8
;
185 if (codecs
[i
] == kCdmSupportedCodecVp9
)
186 supported_codecs
|= media::EME_CODEC_WEBM_VP9
;
187 #if defined(USE_PROPRIETARY_CODECS)
188 if (codecs
[i
] == kCdmSupportedCodecAvc1
)
189 supported_codecs
|= media::EME_CODEC_MP4_AVC1
;
190 #endif // defined(USE_PROPRIETARY_CODECS)
193 cdm::AddWidevineWithCodecs(
194 cdm::WIDEVINE
, supported_codecs
,
195 #if defined(OS_CHROMEOS)
196 media::EmeRobustness::HW_SECURE_ALL
, // Maximum audio robustness.
197 media::EmeRobustness::HW_SECURE_ALL
, // Maximim video robustness.
198 media::EmeSessionTypeSupport::
199 SUPPORTED_WITH_IDENTIFIER
, // Persistent-license.
200 media::EmeSessionTypeSupport::
201 NOT_SUPPORTED
, // Persistent-release-message.
202 media::EmeFeatureSupport::REQUESTABLE
, // Persistent state.
203 media::EmeFeatureSupport::REQUESTABLE
, // Distinctive identifier.
205 media::EmeRobustness::SW_SECURE_CRYPTO
, // Maximum audio robustness.
206 media::EmeRobustness::SW_SECURE_DECODE
, // Maximum video robustness.
207 media::EmeSessionTypeSupport::NOT_SUPPORTED
, // persistent-license.
208 media::EmeSessionTypeSupport::
209 NOT_SUPPORTED
, // persistent-release-message.
210 media::EmeFeatureSupport::REQUESTABLE
, // Persistent state.
211 media::EmeFeatureSupport::NOT_SUPPORTED
, // Distinctive identifier.
212 #endif // defined(OS_CHROMEOS)
213 concrete_key_systems
);
215 #endif // defined(WIDEVINE_CDM_AVAILABLE)
216 #endif // defined(ENABLE_PEPPER_CDMS)
218 void AddChromeKeySystems(std::vector
<KeySystemInfo
>* key_systems_info
) {
219 #if defined(ENABLE_PEPPER_CDMS)
220 AddExternalClearKey(key_systems_info
);
222 #if defined(WIDEVINE_CDM_AVAILABLE)
223 AddPepperBasedWidevine(key_systems_info
);
224 #endif // defined(WIDEVINE_CDM_AVAILABLE)
225 #endif // defined(ENABLE_PEPPER_CDMS)
227 #if defined(OS_ANDROID)
228 cdm::AddAndroidWidevine(key_systems_info
);
229 #endif // defined(OS_ANDROID)