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
3 // found in the LICENSE file.
5 #include "webencryptedmediaclient_impl.h"
8 #include "base/metrics/histogram.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "media/base/key_systems.h"
12 #include "media/base/media_permission.h"
13 #include "media/blink/webcontentdecryptionmodule_impl.h"
14 #include "media/blink/webcontentdecryptionmoduleaccess_impl.h"
15 #include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h"
16 #include "third_party/WebKit/public/platform/WebEncryptedMediaRequest.h"
17 #include "third_party/WebKit/public/platform/WebMediaKeySystemConfiguration.h"
18 #include "third_party/WebKit/public/platform/WebString.h"
24 // Used to name UMAs in Reporter.
25 const char kKeySystemSupportUMAPrefix
[] =
26 "Media.EME.RequestMediaKeySystemAccess.";
30 // Report usage of key system to UMA. There are 2 different counts logged:
31 // 1. The key system is requested.
32 // 2. The requested key system and options are supported.
33 // Each stat is only reported once per renderer frame per key system.
34 // Note that WebEncryptedMediaClientImpl is only created once by each
36 class WebEncryptedMediaClientImpl::Reporter
{
38 enum KeySystemSupportStatus
{
39 KEY_SYSTEM_REQUESTED
= 0,
40 KEY_SYSTEM_SUPPORTED
= 1,
41 KEY_SYSTEM_SUPPORT_STATUS_COUNT
44 explicit Reporter(const std::string
& key_system_for_uma
)
45 : uma_name_(kKeySystemSupportUMAPrefix
+ key_system_for_uma
),
46 is_request_reported_(false),
47 is_support_reported_(false) {}
50 void ReportRequested() {
51 if (is_request_reported_
)
53 Report(KEY_SYSTEM_REQUESTED
);
54 is_request_reported_
= true;
57 void ReportSupported() {
58 DCHECK(is_request_reported_
);
59 if (is_support_reported_
)
61 Report(KEY_SYSTEM_SUPPORTED
);
62 is_support_reported_
= true;
66 void Report(KeySystemSupportStatus status
) {
67 // Not using UMA_HISTOGRAM_ENUMERATION directly because UMA_* macros
68 // require the names to be constant throughout the process' lifetime.
69 base::LinearHistogram::FactoryGet(
70 uma_name_
, 1, KEY_SYSTEM_SUPPORT_STATUS_COUNT
,
71 KEY_SYSTEM_SUPPORT_STATUS_COUNT
+ 1,
72 base::Histogram::kUmaTargetedHistogramFlag
)->Add(status
);
75 const std::string uma_name_
;
76 bool is_request_reported_
;
77 bool is_support_reported_
;
80 WebEncryptedMediaClientImpl::WebEncryptedMediaClientImpl(
81 base::Callback
<bool(void)> are_secure_codecs_supported_cb
,
82 CdmFactory
* cdm_factory
,
83 MediaPermission
* media_permission
)
84 : are_secure_codecs_supported_cb_(are_secure_codecs_supported_cb
),
85 cdm_factory_(cdm_factory
),
86 key_system_config_selector_(KeySystems::GetInstance(), media_permission
),
91 WebEncryptedMediaClientImpl::~WebEncryptedMediaClientImpl() {
94 void WebEncryptedMediaClientImpl::requestMediaKeySystemAccess(
95 blink::WebEncryptedMediaRequest request
) {
96 GetReporter(request
.keySystem())->ReportRequested();
97 key_system_config_selector_
.SelectConfig(
98 request
.keySystem(), request
.supportedConfigurations(),
99 request
.securityOrigin(), are_secure_codecs_supported_cb_
.Run(),
100 base::Bind(&WebEncryptedMediaClientImpl::OnRequestSucceeded
,
101 weak_factory_
.GetWeakPtr(), request
),
102 base::Bind(&WebEncryptedMediaClientImpl::OnRequestNotSupported
,
103 weak_factory_
.GetWeakPtr(), request
));
106 void WebEncryptedMediaClientImpl::CreateCdm(
107 const blink::WebString
& key_system
,
108 const blink::WebSecurityOrigin
& security_origin
,
109 const CdmConfig
& cdm_config
,
110 blink::WebContentDecryptionModuleResult result
) {
111 WebContentDecryptionModuleImpl::Create(
112 cdm_factory_
, key_system
, security_origin
, cdm_config
, result
);
115 void WebEncryptedMediaClientImpl::OnRequestSucceeded(
116 blink::WebEncryptedMediaRequest request
,
117 const blink::WebMediaKeySystemConfiguration
& accumulated_configuration
,
118 const CdmConfig
& cdm_config
) {
119 GetReporter(request
.keySystem())->ReportSupported();
120 // TODO(sandersd): Pass |are_secure_codecs_required| along and use it to
121 // configure the CDM security level and use of secure surfaces on Android.
122 request
.requestSucceeded(WebContentDecryptionModuleAccessImpl::Create(
123 request
.keySystem(), request
.securityOrigin(), accumulated_configuration
,
124 cdm_config
, weak_factory_
.GetWeakPtr()));
127 void WebEncryptedMediaClientImpl::OnRequestNotSupported(
128 blink::WebEncryptedMediaRequest request
,
129 const blink::WebString
& error_message
) {
130 request
.requestNotSupported(error_message
);
133 WebEncryptedMediaClientImpl::Reporter
* WebEncryptedMediaClientImpl::GetReporter(
134 const blink::WebString
& key_system
) {
135 // Assumes that empty will not be found by GetKeySystemNameForUMA().
136 // TODO(sandersd): Avoid doing ASCII conversion more than once.
137 std::string key_system_ascii
;
138 if (base::IsStringASCII(key_system
))
139 key_system_ascii
= base::UTF16ToASCII(key_system
);
141 // Return a per-frame singleton so that UMA reports will be once-per-frame.
142 std::string uma_name
= GetKeySystemNameForUMA(key_system_ascii
);
143 Reporter
* reporter
= reporters_
.get(uma_name
);
145 reporter
= new Reporter(uma_name
);
146 reporters_
.add(uma_name
, make_scoped_ptr(reporter
));