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/files/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
,
129 PP_Var init_data_type
,
131 PP_SessionType session_type
) {
132 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
138 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_CreateSession(
139 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
142 SerializedVarSendInput(dispatcher
, init_data_type
),
143 SerializedVarSendInput(dispatcher
, init_data
),
147 void LoadSession(PP_Instance instance
,
149 PP_Var web_session_id
) {
150 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
156 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_LoadSession(
157 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
160 SerializedVarSendInput(dispatcher
, web_session_id
)));
163 void UpdateSession(PP_Instance instance
,
165 PP_Var web_session_id
,
167 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
173 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_UpdateSession(
174 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
177 SerializedVarSendInput(dispatcher
, web_session_id
),
178 SerializedVarSendInput(dispatcher
, response
)));
181 void ReleaseSession(PP_Instance instance
,
183 PP_Var web_session_id
) {
184 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
190 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_ReleaseSession(
191 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
194 SerializedVarSendInput(dispatcher
, web_session_id
)));
197 void Decrypt(PP_Instance instance
,
198 PP_Resource encrypted_block
,
199 const PP_EncryptedBlockInfo
* encrypted_block_info
) {
200 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
206 PPPDecryptor_Buffer buffer
;
207 if (!InitializePppDecryptorBuffer(instance
,
215 std::string serialized_block_info
;
216 if (!SerializeBlockInfo(*encrypted_block_info
, &serialized_block_info
)) {
221 // PluginResourceTracker in the plugin process assumes that resources that it
222 // tracks have been addrefed on behalf of the plugin at the renderer side. So
223 // we explicitly do it for |encryped_block| here.
224 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_block
);
227 new PpapiMsg_PPPContentDecryptor_Decrypt(
228 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
231 serialized_block_info
));
234 void InitializeAudioDecoder(
235 PP_Instance instance
,
236 const PP_AudioDecoderConfig
* decoder_config
,
237 PP_Resource extra_data_buffer
) {
238 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
244 std::string serialized_decoder_config
;
245 if (!SerializeBlockInfo(*decoder_config
, &serialized_decoder_config
)) {
250 PPPDecryptor_Buffer buffer
;
251 if (!InitializePppDecryptorBuffer(instance
,
259 // PluginResourceTracker in the plugin process assumes that resources that it
260 // tracks have been addrefed on behalf of the plugin at the renderer side. So
261 // we explicitly do it for |extra_data_buffer| here.
262 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer
);
265 new PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder(
266 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
268 serialized_decoder_config
,
272 void InitializeVideoDecoder(
273 PP_Instance instance
,
274 const PP_VideoDecoderConfig
* decoder_config
,
275 PP_Resource extra_data_buffer
) {
276 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
282 std::string serialized_decoder_config
;
283 if (!SerializeBlockInfo(*decoder_config
, &serialized_decoder_config
)) {
288 PPPDecryptor_Buffer buffer
;
289 if (!InitializePppDecryptorBuffer(instance
,
297 // PluginResourceTracker in the plugin process assumes that resources that it
298 // tracks have been addrefed on behalf of the plugin at the renderer side. So
299 // we explicitly do it for |extra_data_buffer| here.
300 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer
);
303 new PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder(
304 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
306 serialized_decoder_config
,
311 void DeinitializeDecoder(PP_Instance instance
,
312 PP_DecryptorStreamType decoder_type
,
313 uint32_t request_id
) {
314 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
321 new PpapiMsg_PPPContentDecryptor_DeinitializeDecoder(
322 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
328 void ResetDecoder(PP_Instance instance
,
329 PP_DecryptorStreamType decoder_type
,
330 uint32_t request_id
) {
331 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
338 new PpapiMsg_PPPContentDecryptor_ResetDecoder(
339 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
345 void DecryptAndDecode(PP_Instance instance
,
346 PP_DecryptorStreamType decoder_type
,
347 PP_Resource encrypted_buffer
,
348 const PP_EncryptedBlockInfo
* encrypted_block_info
) {
349 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
355 PPPDecryptor_Buffer buffer
;
356 if (!InitializePppDecryptorBuffer(instance
,
364 std::string serialized_block_info
;
365 if (!SerializeBlockInfo(*encrypted_block_info
, &serialized_block_info
)) {
370 // PluginResourceTracker in the plugin process assumes that resources that it
371 // tracks have been addrefed on behalf of the plugin at the renderer side. So
372 // we explicitly do it for |encrypted_buffer| here.
373 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_buffer
);
376 new PpapiMsg_PPPContentDecryptor_DecryptAndDecode(
377 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
381 serialized_block_info
));
384 static const PPP_ContentDecryptor_Private content_decryptor_interface
= {
391 &InitializeAudioDecoder
,
392 &InitializeVideoDecoder
,
393 &DeinitializeDecoder
,
400 PPP_ContentDecryptor_Private_Proxy::PPP_ContentDecryptor_Private_Proxy(
401 Dispatcher
* dispatcher
)
402 : InterfaceProxy(dispatcher
),
403 ppp_decryptor_impl_(NULL
) {
404 if (dispatcher
->IsPlugin()) {
405 ppp_decryptor_impl_
= static_cast<const PPP_ContentDecryptor_Private
*>(
406 dispatcher
->local_get_interface()(
407 PPP_CONTENTDECRYPTOR_PRIVATE_INTERFACE
));
411 PPP_ContentDecryptor_Private_Proxy::~PPP_ContentDecryptor_Private_Proxy() {
415 const PPP_ContentDecryptor_Private
*
416 PPP_ContentDecryptor_Private_Proxy::GetProxyInterface() {
417 return &content_decryptor_interface
;
420 bool PPP_ContentDecryptor_Private_Proxy::OnMessageReceived(
421 const IPC::Message
& msg
) {
422 if (!dispatcher()->IsPlugin())
423 return false; // These are only valid from host->plugin.
424 // Don't allow the plugin to send these to the host.
427 IPC_BEGIN_MESSAGE_MAP(PPP_ContentDecryptor_Private_Proxy
, msg
)
428 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_Initialize
,
430 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_CreateSession
,
432 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_LoadSession
,
434 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_UpdateSession
,
436 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_ReleaseSession
,
438 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_Decrypt
,
440 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder
,
441 OnMsgInitializeAudioDecoder
)
442 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder
,
443 OnMsgInitializeVideoDecoder
)
444 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DeinitializeDecoder
,
445 OnMsgDeinitializeDecoder
)
446 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_ResetDecoder
,
448 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DecryptAndDecode
,
449 OnMsgDecryptAndDecode
)
450 IPC_MESSAGE_UNHANDLED(handled
= false)
451 IPC_END_MESSAGE_MAP()
456 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitialize(
457 PP_Instance instance
,
458 SerializedVarReceiveInput key_system
) {
459 if (ppp_decryptor_impl_
) {
461 ppp_decryptor_impl_
->Initialize
,
463 ExtractReceivedVarAndAddRef(dispatcher(), &key_system
));
467 void PPP_ContentDecryptor_Private_Proxy::OnMsgCreateSession(
468 PP_Instance instance
,
470 SerializedVarReceiveInput init_data_type
,
471 SerializedVarReceiveInput init_data
,
472 PP_SessionType session_type
) {
473 if (ppp_decryptor_impl_
) {
475 ppp_decryptor_impl_
->CreateSession
,
478 ExtractReceivedVarAndAddRef(dispatcher(), &init_data_type
),
479 ExtractReceivedVarAndAddRef(dispatcher(), &init_data
),
484 void PPP_ContentDecryptor_Private_Proxy::OnMsgLoadSession(
485 PP_Instance instance
,
487 SerializedVarReceiveInput web_session_id
) {
488 if (ppp_decryptor_impl_
) {
490 ppp_decryptor_impl_
->LoadSession
,
493 ExtractReceivedVarAndAddRef(dispatcher(), &web_session_id
));
497 void PPP_ContentDecryptor_Private_Proxy::OnMsgUpdateSession(
498 PP_Instance instance
,
500 SerializedVarReceiveInput web_session_id
,
501 SerializedVarReceiveInput response
) {
502 if (ppp_decryptor_impl_
) {
504 ppp_decryptor_impl_
->UpdateSession
,
507 ExtractReceivedVarAndAddRef(dispatcher(), &web_session_id
),
508 ExtractReceivedVarAndAddRef(dispatcher(), &response
));
512 void PPP_ContentDecryptor_Private_Proxy::OnMsgReleaseSession(
513 PP_Instance instance
,
515 SerializedVarReceiveInput web_session_id
) {
516 if (ppp_decryptor_impl_
) {
518 ppp_decryptor_impl_
->ReleaseSession
,
521 ExtractReceivedVarAndAddRef(dispatcher(), &web_session_id
));
525 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecrypt(
526 PP_Instance instance
,
527 const PPPDecryptor_Buffer
& encrypted_buffer
,
528 const std::string
& serialized_block_info
) {
529 ScopedPPResource
plugin_resource(
530 ScopedPPResource::PassRef(),
531 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer
.resource
,
532 encrypted_buffer
.handle
,
533 encrypted_buffer
.size
));
534 if (ppp_decryptor_impl_
) {
535 PP_EncryptedBlockInfo block_info
;
536 if (!DeserializeBlockInfo(serialized_block_info
, &block_info
))
538 CallWhileUnlocked(ppp_decryptor_impl_
->Decrypt
,
540 plugin_resource
.get(),
541 const_cast<const PP_EncryptedBlockInfo
*>(&block_info
));
545 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeAudioDecoder(
546 PP_Instance instance
,
547 const std::string
& serialized_decoder_config
,
548 const PPPDecryptor_Buffer
& extra_data_buffer
) {
549 ScopedPPResource plugin_resource
;
550 if (extra_data_buffer
.size
> 0) {
551 plugin_resource
= ScopedPPResource(
552 ScopedPPResource::PassRef(),
553 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer
.resource
,
554 extra_data_buffer
.handle
,
555 extra_data_buffer
.size
));
558 PP_AudioDecoderConfig decoder_config
;
559 if (!DeserializeBlockInfo(serialized_decoder_config
, &decoder_config
))
562 if (ppp_decryptor_impl_
) {
564 ppp_decryptor_impl_
->InitializeAudioDecoder
,
566 const_cast<const PP_AudioDecoderConfig
*>(&decoder_config
),
567 plugin_resource
.get());
571 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeVideoDecoder(
572 PP_Instance instance
,
573 const std::string
& serialized_decoder_config
,
574 const PPPDecryptor_Buffer
& extra_data_buffer
) {
575 ScopedPPResource plugin_resource
;
576 if (extra_data_buffer
.resource
.host_resource() != 0) {
577 plugin_resource
= ScopedPPResource(
578 ScopedPPResource::PassRef(),
579 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer
.resource
,
580 extra_data_buffer
.handle
,
581 extra_data_buffer
.size
));
584 PP_VideoDecoderConfig decoder_config
;
585 if (!DeserializeBlockInfo(serialized_decoder_config
, &decoder_config
))
588 if (ppp_decryptor_impl_
) {
590 ppp_decryptor_impl_
->InitializeVideoDecoder
,
592 const_cast<const PP_VideoDecoderConfig
*>(&decoder_config
),
593 plugin_resource
.get());
597 void PPP_ContentDecryptor_Private_Proxy::OnMsgDeinitializeDecoder(
598 PP_Instance instance
,
599 PP_DecryptorStreamType decoder_type
,
600 uint32_t request_id
) {
601 if (ppp_decryptor_impl_
) {
603 ppp_decryptor_impl_
->DeinitializeDecoder
,
610 void PPP_ContentDecryptor_Private_Proxy::OnMsgResetDecoder(
611 PP_Instance instance
,
612 PP_DecryptorStreamType decoder_type
,
613 uint32_t request_id
) {
614 if (ppp_decryptor_impl_
) {
616 ppp_decryptor_impl_
->ResetDecoder
,
623 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecryptAndDecode(
624 PP_Instance instance
,
625 PP_DecryptorStreamType decoder_type
,
626 const PPPDecryptor_Buffer
& encrypted_buffer
,
627 const std::string
& serialized_block_info
) {
628 ScopedPPResource plugin_resource
;
629 if (encrypted_buffer
.resource
.host_resource() != 0) {
630 plugin_resource
= ScopedPPResource(
631 ScopedPPResource::PassRef(),
632 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer
.resource
,
633 encrypted_buffer
.handle
,
634 encrypted_buffer
.size
));
637 if (ppp_decryptor_impl_
) {
638 PP_EncryptedBlockInfo block_info
;
639 if (!DeserializeBlockInfo(serialized_block_info
, &block_info
))
642 ppp_decryptor_impl_
->DecryptAndDecode
,
645 plugin_resource
.get(),
646 const_cast<const PP_EncryptedBlockInfo
*>(&block_info
));