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 "content/renderer/media/crypto/renderer_cdm_manager.h"
7 #include "base/stl_util.h"
8 #include "content/common/media/cdm_messages.h"
9 #include "content/renderer/media/crypto/proxy_media_keys.h"
10 #include "media/base/cdm_context.h"
11 #include "media/base/limits.h"
15 using media::MediaKeys
;
17 // Maximum sizes for various EME API parameters. These are checks to prevent
18 // unnecessarily large messages from being passed around, and the sizes
19 // are somewhat arbitrary as the EME spec doesn't specify any limits.
20 const size_t kMaxSessionMessageLength
= 10240; // 10 KB
22 RendererCdmManager::RendererCdmManager(RenderFrame
* render_frame
)
23 : RenderFrameObserver(render_frame
),
24 next_cdm_id_(media::CdmContext::kInvalidCdmId
+ 1) {
27 RendererCdmManager::~RendererCdmManager() {
28 DCHECK(proxy_media_keys_map_
.empty())
29 << "RendererCdmManager is owned by RenderFrameImpl and is destroyed only "
30 "after all ProxyMediaKeys are destroyed and unregistered.";
33 bool RendererCdmManager::OnMessageReceived(const IPC::Message
& msg
) {
35 IPC_BEGIN_MESSAGE_MAP(RendererCdmManager
, msg
)
36 IPC_MESSAGE_HANDLER(CdmMsg_SessionMessage
, OnSessionMessage
)
37 IPC_MESSAGE_HANDLER(CdmMsg_SessionClosed
, OnSessionClosed
)
38 IPC_MESSAGE_HANDLER(CdmMsg_LegacySessionError
, OnLegacySessionError
)
39 IPC_MESSAGE_HANDLER(CdmMsg_SessionKeysChange
, OnSessionKeysChange
)
40 IPC_MESSAGE_HANDLER(CdmMsg_SessionExpirationUpdate
,
41 OnSessionExpirationUpdate
)
42 IPC_MESSAGE_HANDLER(CdmMsg_ResolvePromise
, OnPromiseResolved
)
43 IPC_MESSAGE_HANDLER(CdmMsg_ResolvePromiseWithSession
,
44 OnPromiseResolvedWithSession
)
45 IPC_MESSAGE_HANDLER(CdmMsg_RejectPromise
, OnPromiseRejected
)
46 IPC_MESSAGE_UNHANDLED(handled
= false)
51 void RendererCdmManager::InitializeCdm(int cdm_id
,
53 ProxyMediaKeys
* media_keys
,
54 const std::string
& key_system
,
55 const GURL
& security_origin
,
56 bool use_hw_secure_codecs
) {
57 DCHECK(GetMediaKeys(cdm_id
)) << "|cdm_id| not registered.";
58 CdmHostMsg_InitializeCdm_Params params
;
59 params
.key_system
= key_system
;
60 params
.security_origin
= security_origin
;
61 params
.use_hw_secure_codecs
= use_hw_secure_codecs
;
62 Send(new CdmHostMsg_InitializeCdm(routing_id(), cdm_id
, promise_id
, params
));
65 void RendererCdmManager::SetServerCertificate(
68 const std::vector
<uint8_t>& certificate
) {
69 DCHECK(GetMediaKeys(cdm_id
)) << "|cdm_id| not registered.";
70 Send(new CdmHostMsg_SetServerCertificate(routing_id(), cdm_id
, promise_id
,
74 void RendererCdmManager::CreateSessionAndGenerateRequest(
77 media::MediaKeys::SessionType session_type
,
78 CdmHostMsg_CreateSession_InitDataType init_data_type
,
79 const std::vector
<uint8_t>& init_data
) {
80 DCHECK(GetMediaKeys(cdm_id
)) << "|cdm_id| not registered.";
81 CdmHostMsg_CreateSessionAndGenerateRequest_Params params
;
82 params
.render_frame_id
= routing_id();
83 params
.cdm_id
= cdm_id
;
84 params
.promise_id
= promise_id
;
85 params
.session_type
= session_type
;
86 params
.init_data_type
= init_data_type
;
87 params
.init_data
= init_data
;
88 Send(new CdmHostMsg_CreateSessionAndGenerateRequest(params
));
91 void RendererCdmManager::LoadSession(
94 media::MediaKeys::SessionType session_type
,
95 const std::string
& session_id
) {
96 DCHECK(GetMediaKeys(cdm_id
)) << "|cdm_id| not registered.";
97 Send(new CdmHostMsg_LoadSession(routing_id(), cdm_id
, promise_id
,
98 session_type
, session_id
));
101 void RendererCdmManager::UpdateSession(int cdm_id
,
103 const std::string
& session_id
,
104 const std::vector
<uint8_t>& response
) {
105 DCHECK(GetMediaKeys(cdm_id
)) << "|cdm_id| not registered.";
106 Send(new CdmHostMsg_UpdateSession(routing_id(), cdm_id
, promise_id
,
107 session_id
, response
));
110 void RendererCdmManager::CloseSession(int cdm_id
,
112 const std::string
& session_id
) {
113 DCHECK(GetMediaKeys(cdm_id
)) << "|cdm_id| not registered.";
114 Send(new CdmHostMsg_CloseSession(routing_id(), cdm_id
, promise_id
,
118 void RendererCdmManager::RemoveSession(int cdm_id
,
120 const std::string
& session_id
) {
121 DCHECK(GetMediaKeys(cdm_id
)) << "|cdm_id| not registered.";
122 Send(new CdmHostMsg_RemoveSession(routing_id(), cdm_id
, promise_id
,
126 void RendererCdmManager::DestroyCdm(int cdm_id
) {
127 DCHECK(GetMediaKeys(cdm_id
)) << "|cdm_id| not registered.";
128 Send(new CdmHostMsg_DestroyCdm(routing_id(), cdm_id
));
131 void RendererCdmManager::OnSessionMessage(
133 const std::string
& session_id
,
134 media::MediaKeys::MessageType message_type
,
135 const std::vector
<uint8
>& message
,
136 const GURL
& legacy_destination_url
) {
137 if (message
.size() > kMaxSessionMessageLength
) {
139 LOG(ERROR
) << "Message is too long and dropped.";
143 ProxyMediaKeys
* media_keys
= GetMediaKeys(cdm_id
);
145 media_keys
->OnSessionMessage(session_id
, message_type
, message
,
146 legacy_destination_url
);
149 void RendererCdmManager::OnSessionClosed(int cdm_id
,
150 const std::string
& session_id
) {
151 ProxyMediaKeys
* media_keys
= GetMediaKeys(cdm_id
);
153 media_keys
->OnSessionClosed(session_id
);
156 void RendererCdmManager::OnLegacySessionError(
158 const std::string
& session_id
,
159 MediaKeys::Exception exception
,
161 const std::string
& error_message
) {
162 ProxyMediaKeys
* media_keys
= GetMediaKeys(cdm_id
);
164 media_keys
->OnLegacySessionError(session_id
, exception
, system_code
,
168 void RendererCdmManager::OnSessionKeysChange(
170 const std::string
& session_id
,
171 bool has_additional_usable_key
,
172 const std::vector
<media::CdmKeyInformation
>& key_info_vector
) {
173 ProxyMediaKeys
* media_keys
= GetMediaKeys(cdm_id
);
177 media::CdmKeysInfo keys_info
;
178 keys_info
.reserve(key_info_vector
.size());
179 for (const auto& key_info
: key_info_vector
)
180 keys_info
.push_back(new media::CdmKeyInformation(key_info
));
182 media_keys
->OnSessionKeysChange(session_id
, has_additional_usable_key
,
186 void RendererCdmManager::OnSessionExpirationUpdate(
188 const std::string
& session_id
,
189 const base::Time
& new_expiry_time
) {
190 ProxyMediaKeys
* media_keys
= GetMediaKeys(cdm_id
);
192 media_keys
->OnSessionExpirationUpdate(session_id
, new_expiry_time
);
195 void RendererCdmManager::OnPromiseResolved(int cdm_id
, uint32_t promise_id
) {
196 ProxyMediaKeys
* media_keys
= GetMediaKeys(cdm_id
);
198 media_keys
->OnPromiseResolved(promise_id
);
201 void RendererCdmManager::OnPromiseResolvedWithSession(
204 const std::string
& session_id
) {
205 if (session_id
.length() > media::limits::kMaxSessionIdLength
) {
207 OnPromiseRejected(cdm_id
, promise_id
, MediaKeys::INVALID_ACCESS_ERROR
, 0,
208 "Session ID is too long");
212 ProxyMediaKeys
* media_keys
= GetMediaKeys(cdm_id
);
214 media_keys
->OnPromiseResolvedWithSession(promise_id
, session_id
);
217 void RendererCdmManager::OnPromiseRejected(int cdm_id
,
219 MediaKeys::Exception exception
,
220 uint32_t system_code
,
221 const std::string
& error_message
) {
222 ProxyMediaKeys
* media_keys
= GetMediaKeys(cdm_id
);
224 media_keys
->OnPromiseRejected(promise_id
, exception
, system_code
,
228 int RendererCdmManager::RegisterMediaKeys(ProxyMediaKeys
* media_keys
) {
229 int cdm_id
= next_cdm_id_
++;
230 DCHECK_NE(cdm_id
, media::CdmContext::kInvalidCdmId
);
231 DCHECK(!ContainsKey(proxy_media_keys_map_
, cdm_id
));
232 proxy_media_keys_map_
[cdm_id
] = media_keys
;
236 void RendererCdmManager::UnregisterMediaKeys(int cdm_id
) {
237 DCHECK(ContainsKey(proxy_media_keys_map_
, cdm_id
));
238 proxy_media_keys_map_
.erase(cdm_id
);
241 ProxyMediaKeys
* RendererCdmManager::GetMediaKeys(int cdm_id
) {
242 std::map
<int, ProxyMediaKeys
*>::iterator iter
=
243 proxy_media_keys_map_
.find(cdm_id
);
244 return (iter
!= proxy_media_keys_map_
.end()) ? iter
->second
: NULL
;
247 } // namespace content