1 // Copyright (c) 2012 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 "ppapi/proxy/ppp_content_decryptor_private_proxy.h"
7 #include "base/platform_file.h"
8 #include "ppapi/c/pp_bool.h"
9 #include "ppapi/c/ppb_core.h"
10 #include "ppapi/proxy/content_decryptor_private_serializer.h"
11 #include "ppapi/proxy/host_dispatcher.h"
12 #include "ppapi/proxy/plugin_globals.h"
13 #include "ppapi/proxy/plugin_resource_tracker.h"
14 #include "ppapi/proxy/ppapi_messages.h"
15 #include "ppapi/proxy/ppb_buffer_proxy.h"
16 #include "ppapi/proxy/serialized_var.h"
17 #include "ppapi/shared_impl/scoped_pp_resource.h"
18 #include "ppapi/shared_impl/var_tracker.h"
19 #include "ppapi/thunk/enter.h"
20 #include "ppapi/thunk/ppb_buffer_api.h"
21 #include "ppapi/thunk/ppb_instance_api.h"
22 #include "ppapi/thunk/thunk.h"
24 using ppapi::thunk::EnterResourceNoLock
;
25 using ppapi::thunk::PPB_Buffer_API
;
26 using ppapi::thunk::PPB_Instance_API
;
33 PP_Bool
DescribeHostBufferResource(PP_Resource resource
, uint32_t* size
) {
34 EnterResourceNoLock
<PPB_Buffer_API
> enter(resource
, true);
37 return enter
.object()->Describe(size
);
40 // TODO(dmichael): Refactor so this handle sharing code is in one place.
41 PP_Bool
ShareHostBufferResourceToPlugin(
42 HostDispatcher
* dispatcher
,
44 base::SharedMemoryHandle
* shared_mem_handle
) {
45 if (!dispatcher
|| resource
== 0 || !shared_mem_handle
)
47 EnterResourceNoLock
<PPB_Buffer_API
> enter(resource
, true);
51 int32_t result
= enter
.object()->GetSharedMemory(&handle
);
54 base::PlatformFile platform_file
=
56 reinterpret_cast<HANDLE
>(static_cast<intptr_t>(handle
));
57 #elif defined(OS_POSIX)
60 #error Not implemented.
63 *shared_mem_handle
= dispatcher
->ShareHandleWithRemote(platform_file
, false);
67 // SerializedVarReceiveInput will decrement the reference count, but we want
68 // to give the recipient a reference. This utility function takes care of that
69 // work for the message handlers defined below.
70 PP_Var
ExtractReceivedVarAndAddRef(Dispatcher
* dispatcher
,
71 SerializedVarReceiveInput
* serialized_var
) {
72 PP_Var var
= serialized_var
->Get(dispatcher
);
73 PpapiGlobals::Get()->GetVarTracker()->AddRefVar(var
);
77 bool InitializePppDecryptorBuffer(PP_Instance instance
,
78 HostDispatcher
* dispatcher
,
80 PPPDecryptor_Buffer
* buffer
) {
87 buffer
->resource
= HostResource();
88 buffer
->handle
= base::SharedMemoryHandle();
93 HostResource host_resource
;
94 host_resource
.SetHostResource(instance
, resource
);
97 if (DescribeHostBufferResource(resource
, &size
) == PP_FALSE
)
100 base::SharedMemoryHandle handle
;
101 if (ShareHostBufferResourceToPlugin(dispatcher
,
103 &handle
) == PP_FALSE
)
106 buffer
->resource
= host_resource
;
107 buffer
->handle
= handle
;
112 void Initialize(PP_Instance instance
,
114 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
121 new PpapiMsg_PPPContentDecryptor_Initialize(
122 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
124 SerializedVarSendInput(dispatcher
, key_system
)));
127 void CreateSession(PP_Instance instance
,
131 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
137 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_CreateSession(
138 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
141 SerializedVarSendInput(dispatcher
, type
),
142 SerializedVarSendInput(dispatcher
, init_data
)));
145 void LoadSession(PP_Instance instance
,
147 PP_Var web_session_id
) {
148 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
154 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_LoadSession(
155 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
158 SerializedVarSendInput(dispatcher
, web_session_id
)));
161 void UpdateSession(PP_Instance instance
, uint32_t session_id
, PP_Var response
) {
162 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
168 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_UpdateSession(
169 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
172 SerializedVarSendInput(dispatcher
, response
)));
175 void ReleaseSession(PP_Instance instance
, uint32_t session_id
) {
176 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
182 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_ReleaseSession(
183 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
, instance
, session_id
));
186 void Decrypt(PP_Instance instance
,
187 PP_Resource encrypted_block
,
188 const PP_EncryptedBlockInfo
* encrypted_block_info
) {
189 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
195 PPPDecryptor_Buffer buffer
;
196 if (!InitializePppDecryptorBuffer(instance
,
204 std::string serialized_block_info
;
205 if (!SerializeBlockInfo(*encrypted_block_info
, &serialized_block_info
)) {
210 // PluginResourceTracker in the plugin process assumes that resources that it
211 // tracks have been addrefed on behalf of the plugin at the renderer side. So
212 // we explicitly do it for |encryped_block| here.
213 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_block
);
216 new PpapiMsg_PPPContentDecryptor_Decrypt(
217 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
220 serialized_block_info
));
223 void InitializeAudioDecoder(
224 PP_Instance instance
,
225 const PP_AudioDecoderConfig
* decoder_config
,
226 PP_Resource extra_data_buffer
) {
227 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
233 std::string serialized_decoder_config
;
234 if (!SerializeBlockInfo(*decoder_config
, &serialized_decoder_config
)) {
239 PPPDecryptor_Buffer buffer
;
240 if (!InitializePppDecryptorBuffer(instance
,
248 // PluginResourceTracker in the plugin process assumes that resources that it
249 // tracks have been addrefed on behalf of the plugin at the renderer side. So
250 // we explicitly do it for |extra_data_buffer| here.
251 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer
);
254 new PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder(
255 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
257 serialized_decoder_config
,
261 void InitializeVideoDecoder(
262 PP_Instance instance
,
263 const PP_VideoDecoderConfig
* decoder_config
,
264 PP_Resource extra_data_buffer
) {
265 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
271 std::string serialized_decoder_config
;
272 if (!SerializeBlockInfo(*decoder_config
, &serialized_decoder_config
)) {
277 PPPDecryptor_Buffer buffer
;
278 if (!InitializePppDecryptorBuffer(instance
,
286 // PluginResourceTracker in the plugin process assumes that resources that it
287 // tracks have been addrefed on behalf of the plugin at the renderer side. So
288 // we explicitly do it for |extra_data_buffer| here.
289 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer
);
292 new PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder(
293 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
295 serialized_decoder_config
,
300 void DeinitializeDecoder(PP_Instance instance
,
301 PP_DecryptorStreamType decoder_type
,
302 uint32_t request_id
) {
303 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
310 new PpapiMsg_PPPContentDecryptor_DeinitializeDecoder(
311 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
317 void ResetDecoder(PP_Instance instance
,
318 PP_DecryptorStreamType decoder_type
,
319 uint32_t request_id
) {
320 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
327 new PpapiMsg_PPPContentDecryptor_ResetDecoder(
328 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
334 void DecryptAndDecode(PP_Instance instance
,
335 PP_DecryptorStreamType decoder_type
,
336 PP_Resource encrypted_buffer
,
337 const PP_EncryptedBlockInfo
* encrypted_block_info
) {
338 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
344 PPPDecryptor_Buffer buffer
;
345 if (!InitializePppDecryptorBuffer(instance
,
353 std::string serialized_block_info
;
354 if (!SerializeBlockInfo(*encrypted_block_info
, &serialized_block_info
)) {
359 // PluginResourceTracker in the plugin process assumes that resources that it
360 // tracks have been addrefed on behalf of the plugin at the renderer side. So
361 // we explicitly do it for |encrypted_buffer| here.
362 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_buffer
);
365 new PpapiMsg_PPPContentDecryptor_DecryptAndDecode(
366 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
370 serialized_block_info
));
373 static const PPP_ContentDecryptor_Private content_decryptor_interface
= {
380 &InitializeAudioDecoder
,
381 &InitializeVideoDecoder
,
382 &DeinitializeDecoder
,
389 PPP_ContentDecryptor_Private_Proxy::PPP_ContentDecryptor_Private_Proxy(
390 Dispatcher
* dispatcher
)
391 : InterfaceProxy(dispatcher
),
392 ppp_decryptor_impl_(NULL
) {
393 if (dispatcher
->IsPlugin()) {
394 ppp_decryptor_impl_
= static_cast<const PPP_ContentDecryptor_Private
*>(
395 dispatcher
->local_get_interface()(
396 PPP_CONTENTDECRYPTOR_PRIVATE_INTERFACE
));
400 PPP_ContentDecryptor_Private_Proxy::~PPP_ContentDecryptor_Private_Proxy() {
404 const PPP_ContentDecryptor_Private
*
405 PPP_ContentDecryptor_Private_Proxy::GetProxyInterface() {
406 return &content_decryptor_interface
;
409 bool PPP_ContentDecryptor_Private_Proxy::OnMessageReceived(
410 const IPC::Message
& msg
) {
411 if (!dispatcher()->IsPlugin())
412 return false; // These are only valid from host->plugin.
413 // Don't allow the plugin to send these to the host.
416 IPC_BEGIN_MESSAGE_MAP(PPP_ContentDecryptor_Private_Proxy
, msg
)
417 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_Initialize
,
419 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_CreateSession
,
421 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_LoadSession
,
423 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_UpdateSession
,
425 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_ReleaseSession
,
427 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_Decrypt
,
429 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder
,
430 OnMsgInitializeAudioDecoder
)
431 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder
,
432 OnMsgInitializeVideoDecoder
)
433 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DeinitializeDecoder
,
434 OnMsgDeinitializeDecoder
)
435 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_ResetDecoder
,
437 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DecryptAndDecode
,
438 OnMsgDecryptAndDecode
)
439 IPC_MESSAGE_UNHANDLED(handled
= false)
440 IPC_END_MESSAGE_MAP()
445 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitialize(
446 PP_Instance instance
,
447 SerializedVarReceiveInput key_system
) {
448 if (ppp_decryptor_impl_
) {
450 ppp_decryptor_impl_
->Initialize
,
452 ExtractReceivedVarAndAddRef(dispatcher(), &key_system
));
456 void PPP_ContentDecryptor_Private_Proxy::OnMsgCreateSession(
457 PP_Instance instance
,
459 SerializedVarReceiveInput type
,
460 SerializedVarReceiveInput init_data
) {
461 if (ppp_decryptor_impl_
) {
462 CallWhileUnlocked(ppp_decryptor_impl_
->CreateSession
,
465 ExtractReceivedVarAndAddRef(dispatcher(), &type
),
466 ExtractReceivedVarAndAddRef(dispatcher(), &init_data
));
470 void PPP_ContentDecryptor_Private_Proxy::OnMsgLoadSession(
471 PP_Instance instance
,
473 SerializedVarReceiveInput web_session_id
) {
474 if (ppp_decryptor_impl_
) {
476 ppp_decryptor_impl_
->LoadSession
,
479 ExtractReceivedVarAndAddRef(dispatcher(), &web_session_id
));
483 void PPP_ContentDecryptor_Private_Proxy::OnMsgUpdateSession(
484 PP_Instance instance
,
486 SerializedVarReceiveInput response
) {
487 if (ppp_decryptor_impl_
) {
488 CallWhileUnlocked(ppp_decryptor_impl_
->UpdateSession
,
491 ExtractReceivedVarAndAddRef(dispatcher(), &response
));
495 void PPP_ContentDecryptor_Private_Proxy::OnMsgReleaseSession(
496 PP_Instance instance
,
497 uint32_t session_id
) {
498 if (ppp_decryptor_impl_
) {
499 CallWhileUnlocked(ppp_decryptor_impl_
->ReleaseSession
,
505 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecrypt(
506 PP_Instance instance
,
507 const PPPDecryptor_Buffer
& encrypted_buffer
,
508 const std::string
& serialized_block_info
) {
509 ScopedPPResource
plugin_resource(
510 ScopedPPResource::PassRef(),
511 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer
.resource
,
512 encrypted_buffer
.handle
,
513 encrypted_buffer
.size
));
514 if (ppp_decryptor_impl_
) {
515 PP_EncryptedBlockInfo block_info
;
516 if (!DeserializeBlockInfo(serialized_block_info
, &block_info
))
518 CallWhileUnlocked(ppp_decryptor_impl_
->Decrypt
,
520 plugin_resource
.get(),
521 const_cast<const PP_EncryptedBlockInfo
*>(&block_info
));
525 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeAudioDecoder(
526 PP_Instance instance
,
527 const std::string
& serialized_decoder_config
,
528 const PPPDecryptor_Buffer
& extra_data_buffer
) {
529 ScopedPPResource plugin_resource
;
530 if (extra_data_buffer
.size
> 0) {
531 plugin_resource
= ScopedPPResource(
532 ScopedPPResource::PassRef(),
533 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer
.resource
,
534 extra_data_buffer
.handle
,
535 extra_data_buffer
.size
));
538 PP_AudioDecoderConfig decoder_config
;
539 if (!DeserializeBlockInfo(serialized_decoder_config
, &decoder_config
))
542 if (ppp_decryptor_impl_
) {
544 ppp_decryptor_impl_
->InitializeAudioDecoder
,
546 const_cast<const PP_AudioDecoderConfig
*>(&decoder_config
),
547 plugin_resource
.get());
551 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeVideoDecoder(
552 PP_Instance instance
,
553 const std::string
& serialized_decoder_config
,
554 const PPPDecryptor_Buffer
& extra_data_buffer
) {
555 ScopedPPResource plugin_resource
;
556 if (extra_data_buffer
.resource
.host_resource() != 0) {
557 plugin_resource
= ScopedPPResource(
558 ScopedPPResource::PassRef(),
559 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer
.resource
,
560 extra_data_buffer
.handle
,
561 extra_data_buffer
.size
));
564 PP_VideoDecoderConfig decoder_config
;
565 if (!DeserializeBlockInfo(serialized_decoder_config
, &decoder_config
))
568 if (ppp_decryptor_impl_
) {
570 ppp_decryptor_impl_
->InitializeVideoDecoder
,
572 const_cast<const PP_VideoDecoderConfig
*>(&decoder_config
),
573 plugin_resource
.get());
577 void PPP_ContentDecryptor_Private_Proxy::OnMsgDeinitializeDecoder(
578 PP_Instance instance
,
579 PP_DecryptorStreamType decoder_type
,
580 uint32_t request_id
) {
581 if (ppp_decryptor_impl_
) {
583 ppp_decryptor_impl_
->DeinitializeDecoder
,
590 void PPP_ContentDecryptor_Private_Proxy::OnMsgResetDecoder(
591 PP_Instance instance
,
592 PP_DecryptorStreamType decoder_type
,
593 uint32_t request_id
) {
594 if (ppp_decryptor_impl_
) {
596 ppp_decryptor_impl_
->ResetDecoder
,
603 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecryptAndDecode(
604 PP_Instance instance
,
605 PP_DecryptorStreamType decoder_type
,
606 const PPPDecryptor_Buffer
& encrypted_buffer
,
607 const std::string
& serialized_block_info
) {
608 ScopedPPResource plugin_resource
;
609 if (encrypted_buffer
.resource
.host_resource() != 0) {
610 plugin_resource
= ScopedPPResource(
611 ScopedPPResource::PassRef(),
612 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer
.resource
,
613 encrypted_buffer
.handle
,
614 encrypted_buffer
.size
));
617 if (ppp_decryptor_impl_
) {
618 PP_EncryptedBlockInfo block_info
;
619 if (!DeserializeBlockInfo(serialized_block_info
, &block_info
))
622 ppp_decryptor_impl_
->DecryptAndDecode
,
625 plugin_resource
.get(),
626 const_cast<const PP_EncryptedBlockInfo
*>(&block_info
));