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
,
52 ProxyMediaKeys
* media_keys
,
53 const std::string
& key_system
,
54 const GURL
& security_origin
) {
55 DCHECK(GetMediaKeys(cdm_id
)) << "|cdm_id| not registered.";
56 Send(new CdmHostMsg_InitializeCdm(
57 routing_id(), cdm_id
, key_system
, security_origin
));
60 void RendererCdmManager::SetServerCertificate(
63 const std::vector
<uint8_t>& certificate
) {
64 DCHECK(GetMediaKeys(cdm_id
)) << "|cdm_id| not registered.";
65 Send(new CdmHostMsg_SetServerCertificate(routing_id(), cdm_id
, promise_id
,
69 void RendererCdmManager::CreateSessionAndGenerateRequest(
72 CdmHostMsg_CreateSession_InitDataType init_data_type
,
73 const std::vector
<uint8_t>& init_data
) {
74 DCHECK(GetMediaKeys(cdm_id
)) << "|cdm_id| not registered.";
75 Send(new CdmHostMsg_CreateSessionAndGenerateRequest(
76 routing_id(), cdm_id
, promise_id
, init_data_type
, init_data
));
79 void RendererCdmManager::UpdateSession(int cdm_id
,
81 const std::string
& session_id
,
82 const std::vector
<uint8_t>& response
) {
83 DCHECK(GetMediaKeys(cdm_id
)) << "|cdm_id| not registered.";
84 Send(new CdmHostMsg_UpdateSession(routing_id(), cdm_id
, promise_id
,
85 session_id
, response
));
88 void RendererCdmManager::CloseSession(int cdm_id
,
90 const std::string
& session_id
) {
91 DCHECK(GetMediaKeys(cdm_id
)) << "|cdm_id| not registered.";
92 Send(new CdmHostMsg_CloseSession(routing_id(), cdm_id
, promise_id
,
96 void RendererCdmManager::DestroyCdm(int cdm_id
) {
97 DCHECK(GetMediaKeys(cdm_id
)) << "|cdm_id| not registered.";
98 Send(new CdmHostMsg_DestroyCdm(routing_id(), cdm_id
));
101 void RendererCdmManager::OnSessionMessage(
103 const std::string
& session_id
,
104 media::MediaKeys::MessageType message_type
,
105 const std::vector
<uint8
>& message
,
106 const GURL
& legacy_destination_url
) {
107 if (message
.size() > kMaxSessionMessageLength
) {
109 LOG(ERROR
) << "Message is too long and dropped.";
113 ProxyMediaKeys
* media_keys
= GetMediaKeys(cdm_id
);
115 media_keys
->OnSessionMessage(session_id
, message_type
, message
,
116 legacy_destination_url
);
119 void RendererCdmManager::OnSessionClosed(int cdm_id
,
120 const std::string
& session_id
) {
121 ProxyMediaKeys
* media_keys
= GetMediaKeys(cdm_id
);
123 media_keys
->OnSessionClosed(session_id
);
126 void RendererCdmManager::OnLegacySessionError(
128 const std::string
& session_id
,
129 MediaKeys::Exception exception
,
131 const std::string
& error_message
) {
132 ProxyMediaKeys
* media_keys
= GetMediaKeys(cdm_id
);
134 media_keys
->OnLegacySessionError(session_id
, exception
, system_code
,
138 void RendererCdmManager::OnSessionKeysChange(
140 const std::string
& session_id
,
141 bool has_additional_usable_key
,
142 const std::vector
<media::CdmKeyInformation
>& key_info_vector
) {
143 ProxyMediaKeys
* media_keys
= GetMediaKeys(cdm_id
);
147 media::CdmKeysInfo keys_info
;
148 keys_info
.reserve(key_info_vector
.size());
149 for (const auto& key_info
: key_info_vector
)
150 keys_info
.push_back(new media::CdmKeyInformation(key_info
));
152 media_keys
->OnSessionKeysChange(session_id
, has_additional_usable_key
,
156 void RendererCdmManager::OnSessionExpirationUpdate(
158 const std::string
& session_id
,
159 const base::Time
& new_expiry_time
) {
160 ProxyMediaKeys
* media_keys
= GetMediaKeys(cdm_id
);
162 media_keys
->OnSessionExpirationUpdate(session_id
, new_expiry_time
);
165 void RendererCdmManager::OnPromiseResolved(int cdm_id
, uint32_t promise_id
) {
166 ProxyMediaKeys
* media_keys
= GetMediaKeys(cdm_id
);
168 media_keys
->OnPromiseResolved(promise_id
);
171 void RendererCdmManager::OnPromiseResolvedWithSession(
174 const std::string
& session_id
) {
175 if (session_id
.length() > media::limits::kMaxSessionIdLength
) {
177 OnPromiseRejected(cdm_id
, promise_id
, MediaKeys::INVALID_ACCESS_ERROR
, 0,
178 "Session ID is too long");
182 ProxyMediaKeys
* media_keys
= GetMediaKeys(cdm_id
);
184 media_keys
->OnPromiseResolvedWithSession(promise_id
, session_id
);
187 void RendererCdmManager::OnPromiseRejected(int cdm_id
,
189 MediaKeys::Exception exception
,
190 uint32_t system_code
,
191 const std::string
& error_message
) {
192 ProxyMediaKeys
* media_keys
= GetMediaKeys(cdm_id
);
194 media_keys
->OnPromiseRejected(promise_id
, exception
, system_code
,
198 int RendererCdmManager::RegisterMediaKeys(ProxyMediaKeys
* media_keys
) {
199 int cdm_id
= next_cdm_id_
++;
200 DCHECK_NE(cdm_id
, media::CdmContext::kInvalidCdmId
);
201 DCHECK(!ContainsKey(proxy_media_keys_map_
, cdm_id
));
202 proxy_media_keys_map_
[cdm_id
] = media_keys
;
206 void RendererCdmManager::UnregisterMediaKeys(int cdm_id
) {
207 DCHECK(ContainsKey(proxy_media_keys_map_
, cdm_id
));
208 proxy_media_keys_map_
.erase(cdm_id
);
211 ProxyMediaKeys
* RendererCdmManager::GetMediaKeys(int cdm_id
) {
212 std::map
<int, ProxyMediaKeys
*>::iterator iter
=
213 proxy_media_keys_map_
.find(cdm_id
);
214 return (iter
!= proxy_media_keys_map_
.end()) ? iter
->second
: NULL
;
217 } // namespace content