| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "webencryptedmediaclient_impl.h" | 5 #include "webencryptedmediaclient_impl.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/metrics/histogram.h" |
| 8 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
| 9 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
| 10 #include "media/base/key_systems.h" | 11 #include "media/base/key_systems.h" |
| 11 #include "media/base/media_permission.h" | 12 #include "media/base/media_permission.h" |
| 12 #include "net/base/mime_util.h" | 13 #include "net/base/mime_util.h" |
| 13 #include "third_party/WebKit/public/platform/WebEncryptedMediaRequest.h" | 14 #include "third_party/WebKit/public/platform/WebEncryptedMediaRequest.h" |
| 14 #include "third_party/WebKit/public/platform/WebMediaKeySystemConfiguration.h" | 15 #include "third_party/WebKit/public/platform/WebMediaKeySystemConfiguration.h" |
| 15 #include "third_party/WebKit/public/platform/WebString.h" | 16 #include "third_party/WebKit/public/platform/WebString.h" |
| 16 #include "third_party/WebKit/public/platform/WebVector.h" | 17 #include "third_party/WebKit/public/platform/WebVector.h" |
| 17 #include "webcontentdecryptionmoduleaccess_impl.h" | 18 #include "webcontentdecryptionmoduleaccess_impl.h" |
| 18 | 19 |
| 19 namespace media { | 20 namespace media { |
| 20 | 21 |
| 22 // These names are used by UMA. |
| 23 const char kKeySystemSupportUMAPrefix[] = |
| 24 "Media.EME.RequestMediaKeySystemAccess."; |
| 25 |
| 21 static bool IsSupportedContentType( | 26 static bool IsSupportedContentType( |
| 22 const std::string& key_system, | 27 const std::string& key_system, |
| 23 const std::string& mime_type, | 28 const std::string& mime_type, |
| 24 const std::string& codecs) { | 29 const std::string& codecs) { |
| 25 // Per RFC 6838, "Both top-level type and subtype names are case-insensitive." | 30 // Per RFC 6838, "Both top-level type and subtype names are case-insensitive." |
| 26 // TODO(sandersd): Check that |container| matches the capability: | 31 // TODO(sandersd): Check that |container| matches the capability: |
| 27 // - audioCapabilitys: audio/mp4 or audio/webm. | 32 // - audioCapabilitys: audio/mp4 or audio/webm. |
| 28 // - videoCapabilitys: video/mp4 or video/webm. | 33 // - videoCapabilitys: video/mp4 or video/webm. |
| 29 // http://crbug.com/429781. | 34 // http://crbug.com/429781. |
| 30 std::string container = base::StringToLowerASCII(mime_type); | 35 std::string container = base::StringToLowerASCII(mime_type); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 accumulated_configuration->videoCapabilities = video_capabilities; | 129 accumulated_configuration->videoCapabilities = video_capabilities; |
| 125 } | 130 } |
| 126 | 131 |
| 127 // TODO(sandersd): Prompt for distinctive identifiers and/or persistent state | 132 // TODO(sandersd): Prompt for distinctive identifiers and/or persistent state |
| 128 // if required. Make sure that future checks are silent. | 133 // if required. Make sure that future checks are silent. |
| 129 // http://crbug.com/446263. | 134 // http://crbug.com/446263. |
| 130 | 135 |
| 131 return true; | 136 return true; |
| 132 } | 137 } |
| 133 | 138 |
| 139 // Report usage of key system to UMA. There are 2 different counts logged: |
| 140 // 1. The key system is requested. |
| 141 // 2. The requested key system and options are supported. |
| 142 // Each stat is only reported once per renderer frame per key system. |
| 143 // Note that WebEncryptedMediaClientImpl is only created once by each |
| 144 // renderer frame. |
| 145 class WebEncryptedMediaClientImpl::Reporter { |
| 146 public: |
| 147 enum KeySystemSupportStatus { |
| 148 KEY_SYSTEM_REQUESTED = 0, |
| 149 KEY_SYSTEM_SUPPORTED = 1, |
| 150 KEY_SYSTEM_SUPPORT_STATUS_COUNT |
| 151 }; |
| 152 |
| 153 explicit Reporter(const std::string& key_system_for_uma) |
| 154 : uma_name_(kKeySystemSupportUMAPrefix + key_system_for_uma), |
| 155 is_request_reported_(false), |
| 156 is_support_reported_(false) {} |
| 157 ~Reporter() {} |
| 158 |
| 159 void ReportRequested() { |
| 160 if (is_request_reported_) |
| 161 return; |
| 162 Report(KEY_SYSTEM_REQUESTED); |
| 163 is_request_reported_ = true; |
| 164 } |
| 165 |
| 166 void ReportSupported() { |
| 167 DCHECK(is_request_reported_); |
| 168 if (is_support_reported_) |
| 169 return; |
| 170 Report(KEY_SYSTEM_SUPPORTED); |
| 171 is_support_reported_ = true; |
| 172 } |
| 173 |
| 174 private: |
| 175 void Report(KeySystemSupportStatus status) { |
| 176 // Not using UMA_HISTOGRAM_ENUMERATION directly because UMA_* macros |
| 177 // require the names to be constant throughout the process' lifetime. |
| 178 base::LinearHistogram::FactoryGet( |
| 179 uma_name_, 1, KEY_SYSTEM_SUPPORT_STATUS_COUNT, |
| 180 KEY_SYSTEM_SUPPORT_STATUS_COUNT + 1, |
| 181 base::Histogram::kUmaTargetedHistogramFlag)->Add(status); |
| 182 } |
| 183 |
| 184 const std::string uma_name_; |
| 185 bool is_request_reported_; |
| 186 bool is_support_reported_; |
| 187 }; |
| 188 |
| 134 WebEncryptedMediaClientImpl::WebEncryptedMediaClientImpl( | 189 WebEncryptedMediaClientImpl::WebEncryptedMediaClientImpl( |
| 135 scoped_ptr<CdmFactory> cdm_factory, | 190 scoped_ptr<CdmFactory> cdm_factory, |
| 136 MediaPermission* /* media_permission */) | 191 MediaPermission* /* media_permission */) |
| 137 : cdm_factory_(cdm_factory.Pass()) { | 192 : cdm_factory_(cdm_factory.Pass()) { |
| 138 // TODO(sandersd): Use |media_permission| to check for media permissions in | 193 // TODO(sandersd): Use |media_permission| to check for media permissions in |
| 139 // this class. | 194 // this class. |
| 140 } | 195 } |
| 141 | 196 |
| 142 WebEncryptedMediaClientImpl::~WebEncryptedMediaClientImpl() { | 197 WebEncryptedMediaClientImpl::~WebEncryptedMediaClientImpl() { |
| 143 } | 198 } |
| 144 | 199 |
| 145 void WebEncryptedMediaClientImpl::requestMediaKeySystemAccess( | 200 void WebEncryptedMediaClientImpl::requestMediaKeySystemAccess( |
| 146 blink::WebEncryptedMediaRequest request) { | 201 blink::WebEncryptedMediaRequest request) { |
| 147 // TODO(jrummell): This should be asynchronous. | 202 // TODO(jrummell): This should be asynchronous. |
| 148 | 203 |
| 149 // Continued from requestMediaKeySystemAccess(), step 7, from | 204 // Continued from requestMediaKeySystemAccess(), step 7, from |
| 150 // https://w3c.github.io/encrypted-media/#requestmediakeysystemaccess | 205 // https://w3c.github.io/encrypted-media/#requestmediakeysystemaccess |
| 151 // | 206 // |
| 152 // 7.1 If keySystem is not one of the Key Systems supported by the user | 207 // 7.1 If keySystem is not one of the Key Systems supported by the user |
| 153 // agent, reject promise with with a new DOMException whose name is | 208 // agent, reject promise with with a new DOMException whose name is |
| 154 // NotSupportedError. String comparison is case-sensitive. | 209 // NotSupportedError. String comparison is case-sensitive. |
| 155 if (!base::IsStringASCII(request.keySystem())) { | 210 if (!base::IsStringASCII(request.keySystem())) { |
| 156 request.requestNotSupported("Only ASCII keySystems are supported"); | 211 request.requestNotSupported("Only ASCII keySystems are supported"); |
| 157 return; | 212 return; |
| 158 } | 213 } |
| 159 | 214 |
| 160 std::string key_system = base::UTF16ToASCII(request.keySystem()); | 215 std::string key_system = base::UTF16ToASCII(request.keySystem()); |
| 216 |
| 217 // Report this request to the appropriate Reporter. |
| 218 Reporter* reporter = GetReporter(key_system); |
| 219 reporter->ReportRequested(); |
| 220 |
| 161 if (!IsConcreteSupportedKeySystem(key_system)) { | 221 if (!IsConcreteSupportedKeySystem(key_system)) { |
| 162 request.requestNotSupported("Unsupported keySystem"); | 222 request.requestNotSupported("Unsupported keySystem"); |
| 163 return; | 223 return; |
| 164 } | 224 } |
| 165 | 225 |
| 166 // 7.2 Let implementation be the implementation of keySystem. | 226 // 7.2 Let implementation be the implementation of keySystem. |
| 167 // 7.3 For each value in supportedConfigurations, run the GetSupported | 227 // 7.3 For each value in supportedConfigurations, run the GetSupported |
| 168 // Configuration algorithm and if successful, resolve promise with access | 228 // Configuration algorithm and if successful, resolve promise with access |
| 169 // and abort these steps. | 229 // and abort these steps. |
| 170 const blink::WebVector<blink::WebMediaKeySystemConfiguration>& | 230 const blink::WebVector<blink::WebMediaKeySystemConfiguration>& |
| 171 configurations = request.supportedConfigurations(); | 231 configurations = request.supportedConfigurations(); |
| 172 | 232 |
| 173 // TODO(sandersd): Remove once Blink requires the configurations parameter for | 233 // TODO(sandersd): Remove once Blink requires the configurations parameter for |
| 174 // requestMediaKeySystemAccess(). | 234 // requestMediaKeySystemAccess(). |
| 175 if (configurations.isEmpty()) { | 235 if (configurations.isEmpty()) { |
| 236 reporter->ReportSupported(); |
| 176 request.requestSucceeded(WebContentDecryptionModuleAccessImpl::Create( | 237 request.requestSucceeded(WebContentDecryptionModuleAccessImpl::Create( |
| 177 request.keySystem(), blink::WebMediaKeySystemConfiguration(), | 238 request.keySystem(), blink::WebMediaKeySystemConfiguration(), |
| 178 request.securityOrigin(), cdm_factory_.get())); | 239 request.securityOrigin(), cdm_factory_.get())); |
| 179 return; | 240 return; |
| 180 } | 241 } |
| 181 | 242 |
| 182 for (size_t i = 0; i < configurations.size(); i++) { | 243 for (size_t i = 0; i < configurations.size(); i++) { |
| 183 const blink::WebMediaKeySystemConfiguration& candidate = configurations[i]; | 244 const blink::WebMediaKeySystemConfiguration& candidate = configurations[i]; |
| 184 blink::WebMediaKeySystemConfiguration accumulated_configuration; | 245 blink::WebMediaKeySystemConfiguration accumulated_configuration; |
| 185 if (GetSupportedConfiguration(key_system, candidate, | 246 if (GetSupportedConfiguration(key_system, candidate, |
| 186 request.securityOrigin(), | 247 request.securityOrigin(), |
| 187 &accumulated_configuration)) { | 248 &accumulated_configuration)) { |
| 249 reporter->ReportSupported(); |
| 188 request.requestSucceeded(WebContentDecryptionModuleAccessImpl::Create( | 250 request.requestSucceeded(WebContentDecryptionModuleAccessImpl::Create( |
| 189 request.keySystem(), accumulated_configuration, | 251 request.keySystem(), accumulated_configuration, |
| 190 request.securityOrigin(), cdm_factory_.get())); | 252 request.securityOrigin(), cdm_factory_.get())); |
| 191 return; | 253 return; |
| 192 } | 254 } |
| 193 } | 255 } |
| 194 | 256 |
| 195 // 7.4 Reject promise with a new DOMException whose name is NotSupportedError. | 257 // 7.4 Reject promise with a new DOMException whose name is NotSupportedError. |
| 196 request.requestNotSupported( | 258 request.requestNotSupported( |
| 197 "None of the requested configurations were supported."); | 259 "None of the requested configurations were supported."); |
| 198 } | 260 } |
| 199 | 261 |
| 262 // Lazily create Reporters. |
| 263 WebEncryptedMediaClientImpl::Reporter* WebEncryptedMediaClientImpl::GetReporter( |
| 264 const std::string& key_system) { |
| 265 std::string uma_name = GetKeySystemNameForUMA(key_system); |
| 266 Reporter* reporter = reporters_.get(uma_name); |
| 267 if (reporter != nullptr) |
| 268 return reporter; |
| 269 |
| 270 // Reporter not found, so create one. |
| 271 auto result = |
| 272 reporters_.add(uma_name, make_scoped_ptr(new Reporter(uma_name))); |
| 273 DCHECK(result.second); |
| 274 return result.first->second; |
| 275 } |
| 276 |
| 200 } // namespace media | 277 } // namespace media |
| OLD | NEW |