• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "chrome/renderer/media/chrome_key_systems.h"
6 
7 #include <string>
8 #include <vector>
9 
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 
18 #if defined(OS_ANDROID)
19 #include "components/cdm/renderer/android_key_systems.h"
20 #endif
21 
22 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
23 
24 // The following must be after widevine_cdm_version.h.
25 
26 #if defined(WIDEVINE_CDM_AVAILABLE) && defined(WIDEVINE_CDM_MIN_GLIBC_VERSION)
27 #include <gnu/libc-version.h>
28 #include "base/version.h"
29 #endif
30 
31 using content::KeySystemInfo;
32 using content::SupportedCodecs;
33 
34 #if defined(ENABLE_PEPPER_CDMS)
IsPepperCdmAvailable(const std::string & pepper_type,std::vector<base::string16> * additional_param_names,std::vector<base::string16> * additional_param_values)35 static bool IsPepperCdmAvailable(
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_available = false;
40   content::RenderThread::Get()->Send(
41       new ChromeViewHostMsg_IsInternalPluginAvailableForMimeType(
42           pepper_type,
43           &is_available,
44           additional_param_names,
45           additional_param_values));
46 
47   return is_available;
48 }
49 
50 // External Clear Key (used for testing).
AddExternalClearKey(std::vector<KeySystemInfo> * concrete_key_systems)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";
65 
66   std::vector<base::string16> additional_param_names;
67   std::vector<base::string16> additional_param_values;
68   if (!IsPepperCdmAvailable(kExternalClearKeyPepperType,
69                             &additional_param_names,
70                             &additional_param_values)) {
71     return;
72   }
73 
74   KeySystemInfo info(kExternalClearKeyKeySystem);
75 
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)
80 
81   info.pepper_type = kExternalClearKeyPepperType;
82 
83   concrete_key_systems->push_back(info);
84 
85   // Add support of decrypt-only mode in ClearKeyCdm.
86   info.key_system = kExternalClearKeyDecryptOnlyKeySystem;
87   concrete_key_systems->push_back(info);
88 
89   // A key system that triggers FileIO test in ClearKeyCdm.
90   info.key_system = kExternalClearKeyFileIOTestKeySystem;
91   concrete_key_systems->push_back(info);
92 
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
95   // failure case.
96   info.key_system = kExternalClearKeyInitializeFailKeySystem;
97   concrete_key_systems->push_back(info);
98 
99   // A key system that triggers a crash in ClearKeyCdm.
100   info.key_system = kExternalClearKeyCrashKeySystem;
101   concrete_key_systems->push_back(info);
102 }
103 
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.
GetSupportedCodecsForPepperCdm(const std::vector<base::string16> & additional_param_names,const std::vector<base::string16> & additional_param_values,std::vector<std::string> * codecs)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(),
121                              &codecs_string)) {
122         DLOG(WARNING) << "Non-UTF-8 codecs string.";
123         // Continue using the best effort conversion.
124       }
125       base::SplitString(codecs_string,
126                         kCdmSupportedCodecsValueDelimiter,
127                         codecs);
128       break;
129     }
130   }
131 }
132 
AddPepperBasedWidevine(std::vector<KeySystemInfo> * concrete_key_systems)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))
139     return;
140 #endif  // defined(WIDEVINE_CDM_MIN_GLIBC_VERSION)
141 
142   std::vector<base::string16> additional_param_names;
143   std::vector<base::string16> additional_param_values;
144   if (!IsPepperCdmAvailable(kWidevineCdmPluginMimeType,
145                             &additional_param_names,
146                             &additional_param_values)) {
147     DVLOG(1) << "Widevine CDM is not currently available.";
148     return;
149   }
150 
151   std::vector<std::string> codecs;
152   GetSupportedCodecsForPepperCdm(additional_param_names,
153                                  additional_param_values,
154                                  &codecs);
155 
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)
170   }
171 
172   cdm::AddWidevineWithCodecs(cdm::WIDEVINE,
173                              supported_codecs,
174                              concrete_key_systems);
175 }
176 #endif  // defined(WIDEVINE_CDM_AVAILABLE)
177 #endif  // defined(ENABLE_PEPPER_CDMS)
178 
AddChromeKeySystems(std::vector<KeySystemInfo> * key_systems_info)179 void AddChromeKeySystems(std::vector<KeySystemInfo>* key_systems_info) {
180 #if defined(ENABLE_PEPPER_CDMS)
181   AddExternalClearKey(key_systems_info);
182 
183 #if defined(WIDEVINE_CDM_AVAILABLE)
184   AddPepperBasedWidevine(key_systems_info);
185 #endif  // defined(WIDEVINE_CDM_AVAILABLE)
186 #endif  // defined(ENABLE_PEPPER_CDMS)
187 
188 #if defined(OS_ANDROID)
189   cdm::AddAndroidWidevine(key_systems_info);
190 #endif  // defined(OS_ANDROID)
191 }
192