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"
18 #if defined(OS_ANDROID)
19 #include "components/cdm/renderer/android_key_systems.h"
22 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
24 // The following must be after widevine_cdm_version.h.
26 #if defined(WIDEVINE_CDM_AVAILABLE) && defined(WIDEVINE_CDM_MIN_GLIBC_VERSION)
27 #include <gnu/libc-version.h>
28 #include "base/version.h"
31 using content::KeySystemInfo
;
32 using content::SupportedCodecs
;
34 #if defined(ENABLE_PEPPER_CDMS)
35 static bool IsPepperCdmRegistered(
36 const std::string
& pepper_type
,
37 std::vector
<base::string16
>* additional_param_names
,
38 std::vector
<base::string16
>* additional_param_values
) {
39 bool is_registered
= false;
40 content::RenderThread::Get()->Send(
41 new ChromeViewHostMsg_IsInternalPluginRegisteredForMimeType(
44 additional_param_names
,
45 additional_param_values
));
50 // External Clear Key (used for testing).
51 static void AddExternalClearKey(
52 std::vector
<KeySystemInfo
>* concrete_key_systems
) {
53 static const char kExternalClearKeyKeySystem
[] =
54 "org.chromium.externalclearkey";
55 static const char kExternalClearKeyDecryptOnlyKeySystem
[] =
56 "org.chromium.externalclearkey.decryptonly";
57 static const char kExternalClearKeyFileIOTestKeySystem
[] =
58 "org.chromium.externalclearkey.fileiotest";
59 static const char kExternalClearKeyInitializeFailKeySystem
[] =
60 "org.chromium.externalclearkey.initializefail";
61 static const char kExternalClearKeyCrashKeySystem
[] =
62 "org.chromium.externalclearkey.crash";
63 static const char kExternalClearKeyPepperType
[] =
64 "application/x-ppapi-clearkey-cdm";
66 std::vector
<base::string16
> additional_param_names
;
67 std::vector
<base::string16
> additional_param_values
;
68 if (!IsPepperCdmRegistered(kExternalClearKeyPepperType
,
69 &additional_param_names
,
70 &additional_param_values
)) {
74 KeySystemInfo
info(kExternalClearKeyKeySystem
);
76 info
.supported_codecs
= content::EME_CODEC_WEBM_ALL
;
77 #if defined(USE_PROPRIETARY_CODECS)
78 info
.supported_codecs
|= content::EME_CODEC_MP4_ALL
;
79 #endif // defined(USE_PROPRIETARY_CODECS)
81 info
.pepper_type
= kExternalClearKeyPepperType
;
83 concrete_key_systems
->push_back(info
);
85 // Add support of decrypt-only mode in ClearKeyCdm.
86 info
.key_system
= kExternalClearKeyDecryptOnlyKeySystem
;
87 concrete_key_systems
->push_back(info
);
89 // A key system that triggers FileIO test in ClearKeyCdm.
90 info
.key_system
= kExternalClearKeyFileIOTestKeySystem
;
91 concrete_key_systems
->push_back(info
);
93 // A key system that Chrome thinks is supported by ClearKeyCdm, but actually
94 // will be refused by ClearKeyCdm. This is to test the CDM initialization
96 info
.key_system
= kExternalClearKeyInitializeFailKeySystem
;
97 concrete_key_systems
->push_back(info
);
99 // A key system that triggers a crash in ClearKeyCdm.
100 info
.key_system
= kExternalClearKeyCrashKeySystem
;
101 concrete_key_systems
->push_back(info
);
104 #if defined(WIDEVINE_CDM_AVAILABLE)
105 // This function finds "codecs" and parses the value into the vector |codecs|.
106 // Converts the codec strings to UTF-8 since we only expect ASCII strings and
107 // this simplifies the rest of the code in this file.
108 void GetSupportedCodecsForPepperCdm(
109 const std::vector
<base::string16
>& additional_param_names
,
110 const std::vector
<base::string16
>& additional_param_values
,
111 std::vector
<std::string
>* codecs
) {
112 DCHECK(codecs
->empty());
113 DCHECK_EQ(additional_param_names
.size(), additional_param_values
.size());
114 for (size_t i
= 0; i
< additional_param_names
.size(); ++i
) {
115 if (additional_param_names
[i
] ==
116 base::ASCIIToUTF16(kCdmSupportedCodecsParamName
)) {
117 const base::string16
& codecs_string16
= additional_param_values
[i
];
118 std::string codecs_string
;
119 if (!base::UTF16ToUTF8(codecs_string16
.c_str(),
120 codecs_string16
.length(),
122 DLOG(WARNING
) << "Non-UTF-8 codecs string.";
123 // Continue using the best effort conversion.
125 base::SplitString(codecs_string
,
126 kCdmSupportedCodecsValueDelimiter
,
133 static void AddPepperBasedWidevine(
134 std::vector
<KeySystemInfo
>* concrete_key_systems
) {
135 #if defined(WIDEVINE_CDM_MIN_GLIBC_VERSION)
136 Version
glibc_version(gnu_get_libc_version());
137 DCHECK(glibc_version
.IsValid());
138 if (glibc_version
.IsOlderThan(WIDEVINE_CDM_MIN_GLIBC_VERSION
))
140 #endif // defined(WIDEVINE_CDM_MIN_GLIBC_VERSION)
142 std::vector
<base::string16
> additional_param_names
;
143 std::vector
<base::string16
> additional_param_values
;
144 if (!IsPepperCdmRegistered(kWidevineCdmPluginMimeType
,
145 &additional_param_names
,
146 &additional_param_values
)) {
147 DVLOG(1) << "Widevine CDM is not currently available.";
151 std::vector
<std::string
> codecs
;
152 GetSupportedCodecsForPepperCdm(additional_param_names
,
153 additional_param_values
,
156 SupportedCodecs supported_codecs
= content::EME_CODEC_NONE
;
157 for (size_t i
= 0; i
< codecs
.size(); ++i
) {
158 if (codecs
[i
] == kCdmSupportedCodecVorbis
)
159 supported_codecs
|= content::EME_CODEC_WEBM_VORBIS
;
160 if (codecs
[i
] == kCdmSupportedCodecVp8
)
161 supported_codecs
|= content::EME_CODEC_WEBM_VP8
;
162 if (codecs
[i
] == kCdmSupportedCodecVp9
)
163 supported_codecs
|= content::EME_CODEC_WEBM_VP9
;
164 #if defined(USE_PROPRIETARY_CODECS)
165 if (codecs
[i
] == kCdmSupportedCodecAac
)
166 supported_codecs
|= content::EME_CODEC_MP4_AAC
;
167 if (codecs
[i
] == kCdmSupportedCodecAvc1
)
168 supported_codecs
|= content::EME_CODEC_MP4_AVC1
;
169 #endif // defined(USE_PROPRIETARY_CODECS)
172 cdm::AddWidevineWithCodecs(cdm::WIDEVINE
,
174 concrete_key_systems
);
176 #endif // defined(WIDEVINE_CDM_AVAILABLE)
177 #endif // defined(ENABLE_PEPPER_CDMS)
179 void AddChromeKeySystems(std::vector
<KeySystemInfo
>* key_systems_info
) {
180 #if defined(ENABLE_PEPPER_CDMS)
181 AddExternalClearKey(key_systems_info
);
183 #if defined(WIDEVINE_CDM_AVAILABLE)
184 AddPepperBasedWidevine(key_systems_info
);
185 #endif // defined(WIDEVINE_CDM_AVAILABLE)
186 #endif // defined(ENABLE_PEPPER_CDMS)
188 #if defined(OS_ANDROID)
189 cdm::AddAndroidWidevine(key_systems_info
);
190 #endif // defined(OS_ANDROID)