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 "media/blink/cdm_session_adapter.h"
8 #include "base/logging.h"
9 #include "base/memory/weak_ptr.h"
10 #include "base/stl_util.h"
11 #include "media/base/cdm_factory.h"
12 #include "media/base/cdm_promise.h"
13 #include "media/base/key_systems.h"
14 #include "media/base/media_keys.h"
15 #include "media/blink/webcontentdecryptionmodulesession_impl.h"
20 const char kMediaEME
[] = "Media.EME.";
21 const char kDot
[] = ".";
23 CdmSessionAdapter::CdmSessionAdapter() : weak_ptr_factory_(this) {
26 CdmSessionAdapter::~CdmSessionAdapter() {}
28 bool CdmSessionAdapter::Initialize(CdmFactory
* cdm_factory
,
29 const std::string
& key_system
,
30 const GURL
& security_origin
) {
31 key_system_uma_prefix_
=
32 kMediaEME
+ GetKeySystemNameForUMA(key_system
) + kDot
;
34 base::WeakPtr
<CdmSessionAdapter
> weak_this
= weak_ptr_factory_
.GetWeakPtr();
35 media_keys_
= cdm_factory
->Create(
38 base::Bind(&CdmSessionAdapter::OnSessionMessage
, weak_this
),
39 base::Bind(&CdmSessionAdapter::OnSessionReady
, weak_this
),
40 base::Bind(&CdmSessionAdapter::OnSessionClosed
, weak_this
),
41 base::Bind(&CdmSessionAdapter::OnSessionError
, weak_this
),
42 base::Bind(&CdmSessionAdapter::OnSessionKeysChange
, weak_this
),
43 base::Bind(&CdmSessionAdapter::OnSessionExpirationUpdate
, weak_this
));
45 // Success if |media_keys_| created.
49 void CdmSessionAdapter::SetServerCertificate(
50 const uint8
* server_certificate
,
51 int server_certificate_length
,
52 scoped_ptr
<SimpleCdmPromise
> promise
) {
53 media_keys_
->SetServerCertificate(
54 server_certificate
, server_certificate_length
, promise
.Pass());
57 WebContentDecryptionModuleSessionImpl
* CdmSessionAdapter::CreateSession() {
58 return new WebContentDecryptionModuleSessionImpl(this);
61 bool CdmSessionAdapter::RegisterSession(
62 const std::string
& web_session_id
,
63 base::WeakPtr
<WebContentDecryptionModuleSessionImpl
> session
) {
64 // If this session ID is already registered, don't register it again.
65 if (ContainsKey(sessions_
, web_session_id
))
68 sessions_
[web_session_id
] = session
;
72 void CdmSessionAdapter::UnregisterSession(const std::string
& web_session_id
) {
73 DCHECK(ContainsKey(sessions_
, web_session_id
));
74 sessions_
.erase(web_session_id
);
77 void CdmSessionAdapter::InitializeNewSession(
78 const std::string
& init_data_type
,
79 const uint8
* init_data
,
81 MediaKeys::SessionType session_type
,
82 scoped_ptr
<NewSessionCdmPromise
> promise
) {
83 media_keys_
->CreateSession(init_data_type
,
90 void CdmSessionAdapter::LoadSession(
91 const std::string
& web_session_id
,
92 scoped_ptr
<NewSessionCdmPromise
> promise
) {
93 media_keys_
->LoadSession(web_session_id
, promise
.Pass());
96 void CdmSessionAdapter::UpdateSession(
97 const std::string
& web_session_id
,
98 const uint8
* response
,
100 scoped_ptr
<SimpleCdmPromise
> promise
) {
101 media_keys_
->UpdateSession(
102 web_session_id
, response
, response_length
, promise
.Pass());
105 void CdmSessionAdapter::CloseSession(
106 const std::string
& web_session_id
,
107 scoped_ptr
<SimpleCdmPromise
> promise
) {
108 media_keys_
->CloseSession(web_session_id
, promise
.Pass());
111 void CdmSessionAdapter::RemoveSession(
112 const std::string
& web_session_id
,
113 scoped_ptr
<SimpleCdmPromise
> promise
) {
114 media_keys_
->RemoveSession(web_session_id
, promise
.Pass());
117 void CdmSessionAdapter::GetUsableKeyIds(
118 const std::string
& web_session_id
,
119 scoped_ptr
<KeyIdsPromise
> promise
) {
120 media_keys_
->GetUsableKeyIds(web_session_id
, promise
.Pass());
123 Decryptor
* CdmSessionAdapter::GetDecryptor() {
124 return media_keys_
->GetDecryptor();
127 const std::string
& CdmSessionAdapter::GetKeySystemUMAPrefix() const {
128 return key_system_uma_prefix_
;
131 #if defined(ENABLE_BROWSER_CDMS)
132 int CdmSessionAdapter::GetCdmId() const {
133 return media_keys_
->GetCdmId();
135 #endif // defined(ENABLE_BROWSER_CDMS)
137 void CdmSessionAdapter::OnSessionMessage(const std::string
& web_session_id
,
138 const std::vector
<uint8
>& message
,
139 const GURL
& destination_url
) {
140 WebContentDecryptionModuleSessionImpl
* session
= GetSession(web_session_id
);
141 DLOG_IF(WARNING
, !session
) << __FUNCTION__
<< " for unknown session "
144 session
->OnSessionMessage(message
, destination_url
);
147 void CdmSessionAdapter::OnSessionKeysChange(const std::string
& web_session_id
,
148 bool has_additional_usable_key
) {
149 WebContentDecryptionModuleSessionImpl
* session
= GetSession(web_session_id
);
150 DLOG_IF(WARNING
, !session
) << __FUNCTION__
<< " for unknown session "
153 session
->OnSessionKeysChange(has_additional_usable_key
);
156 void CdmSessionAdapter::OnSessionExpirationUpdate(
157 const std::string
& web_session_id
,
158 const base::Time
& new_expiry_time
) {
159 WebContentDecryptionModuleSessionImpl
* session
= GetSession(web_session_id
);
160 DLOG_IF(WARNING
, !session
) << __FUNCTION__
<< " for unknown session "
163 session
->OnSessionExpirationUpdate(new_expiry_time
);
166 void CdmSessionAdapter::OnSessionReady(const std::string
& web_session_id
) {
167 // Ready events not used by unprefixed EME.
168 // TODO(jrummell): Remove when prefixed EME removed.
171 void CdmSessionAdapter::OnSessionClosed(const std::string
& web_session_id
) {
172 WebContentDecryptionModuleSessionImpl
* session
= GetSession(web_session_id
);
173 DLOG_IF(WARNING
, !session
) << __FUNCTION__
<< " for unknown session "
176 session
->OnSessionClosed();
179 void CdmSessionAdapter::OnSessionError(
180 const std::string
& web_session_id
,
181 MediaKeys::Exception exception_code
,
183 const std::string
& error_message
) {
184 // Error events not used by unprefixed EME.
185 // TODO(jrummell): Remove when prefixed EME removed.
188 WebContentDecryptionModuleSessionImpl
* CdmSessionAdapter::GetSession(
189 const std::string
& web_session_id
) {
190 // Since session objects may get garbage collected, it is possible that there
191 // are events coming back from the CDM and the session has been unregistered.
192 // We can not tell if the CDM is firing events at sessions that never existed.
193 SessionMap::iterator session
= sessions_
.find(web_session_id
);
194 return (session
!= sessions_
.end()) ? session
->second
.get() : NULL
;