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 PP_Bool can_challenge_platform
) {
115 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
122 new PpapiMsg_PPPContentDecryptor_Initialize(
123 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
125 SerializedVarSendInput(dispatcher
, key_system
),
126 PP_ToBool(can_challenge_platform
)));
129 void GenerateKeyRequest(PP_Instance instance
,
132 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
139 new PpapiMsg_PPPContentDecryptor_GenerateKeyRequest(
140 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
142 SerializedVarSendInput(dispatcher
, type
),
143 SerializedVarSendInput(dispatcher
, init_data
)));
146 void AddKey(PP_Instance instance
,
150 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
157 new PpapiMsg_PPPContentDecryptor_AddKey(
158 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
160 SerializedVarSendInput(dispatcher
, session_id
),
161 SerializedVarSendInput(dispatcher
, key
),
162 SerializedVarSendInput(dispatcher
, init_data
)));
165 void CancelKeyRequest(PP_Instance instance
, PP_Var session_id
) {
166 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
173 new PpapiMsg_PPPContentDecryptor_CancelKeyRequest(
174 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
176 SerializedVarSendInput(dispatcher
, session_id
)));
179 void Decrypt(PP_Instance instance
,
180 PP_Resource encrypted_block
,
181 const PP_EncryptedBlockInfo
* encrypted_block_info
) {
182 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
188 PPPDecryptor_Buffer buffer
;
189 if (!InitializePppDecryptorBuffer(instance
,
197 std::string serialized_block_info
;
198 if (!SerializeBlockInfo(*encrypted_block_info
, &serialized_block_info
)) {
203 // PluginResourceTracker in the plugin process assumes that resources that it
204 // tracks have been addrefed on behalf of the plugin at the renderer side. So
205 // we explicitly do it for |encryped_block| here.
206 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_block
);
209 new PpapiMsg_PPPContentDecryptor_Decrypt(
210 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
213 serialized_block_info
));
216 void InitializeAudioDecoder(
217 PP_Instance instance
,
218 const PP_AudioDecoderConfig
* decoder_config
,
219 PP_Resource extra_data_buffer
) {
220 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
226 std::string serialized_decoder_config
;
227 if (!SerializeBlockInfo(*decoder_config
, &serialized_decoder_config
)) {
232 PPPDecryptor_Buffer buffer
;
233 if (!InitializePppDecryptorBuffer(instance
,
241 // PluginResourceTracker in the plugin process assumes that resources that it
242 // tracks have been addrefed on behalf of the plugin at the renderer side. So
243 // we explicitly do it for |extra_data_buffer| here.
244 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer
);
247 new PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder(
248 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
250 serialized_decoder_config
,
254 void InitializeVideoDecoder(
255 PP_Instance instance
,
256 const PP_VideoDecoderConfig
* decoder_config
,
257 PP_Resource extra_data_buffer
) {
258 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
264 std::string serialized_decoder_config
;
265 if (!SerializeBlockInfo(*decoder_config
, &serialized_decoder_config
)) {
270 PPPDecryptor_Buffer buffer
;
271 if (!InitializePppDecryptorBuffer(instance
,
279 // PluginResourceTracker in the plugin process assumes that resources that it
280 // tracks have been addrefed on behalf of the plugin at the renderer side. So
281 // we explicitly do it for |extra_data_buffer| here.
282 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer
);
285 new PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder(
286 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
288 serialized_decoder_config
,
293 void DeinitializeDecoder(PP_Instance instance
,
294 PP_DecryptorStreamType decoder_type
,
295 uint32_t request_id
) {
296 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
303 new PpapiMsg_PPPContentDecryptor_DeinitializeDecoder(
304 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
310 void ResetDecoder(PP_Instance instance
,
311 PP_DecryptorStreamType decoder_type
,
312 uint32_t request_id
) {
313 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
320 new PpapiMsg_PPPContentDecryptor_ResetDecoder(
321 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
327 void DecryptAndDecode(PP_Instance instance
,
328 PP_DecryptorStreamType decoder_type
,
329 PP_Resource encrypted_buffer
,
330 const PP_EncryptedBlockInfo
* encrypted_block_info
) {
331 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
337 PPPDecryptor_Buffer buffer
;
338 if (!InitializePppDecryptorBuffer(instance
,
346 std::string serialized_block_info
;
347 if (!SerializeBlockInfo(*encrypted_block_info
, &serialized_block_info
)) {
352 // PluginResourceTracker in the plugin process assumes that resources that it
353 // tracks have been addrefed on behalf of the plugin at the renderer side. So
354 // we explicitly do it for |encrypted_buffer| here.
355 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_buffer
);
358 new PpapiMsg_PPPContentDecryptor_DecryptAndDecode(
359 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
363 serialized_block_info
));
366 static const PPP_ContentDecryptor_Private content_decryptor_interface
= {
372 &InitializeAudioDecoder
,
373 &InitializeVideoDecoder
,
374 &DeinitializeDecoder
,
381 PPP_ContentDecryptor_Private_Proxy::PPP_ContentDecryptor_Private_Proxy(
382 Dispatcher
* dispatcher
)
383 : InterfaceProxy(dispatcher
),
384 ppp_decryptor_impl_(NULL
) {
385 if (dispatcher
->IsPlugin()) {
386 ppp_decryptor_impl_
= static_cast<const PPP_ContentDecryptor_Private
*>(
387 dispatcher
->local_get_interface()(
388 PPP_CONTENTDECRYPTOR_PRIVATE_INTERFACE
));
392 PPP_ContentDecryptor_Private_Proxy::~PPP_ContentDecryptor_Private_Proxy() {
396 const PPP_ContentDecryptor_Private
*
397 PPP_ContentDecryptor_Private_Proxy::GetProxyInterface() {
398 return &content_decryptor_interface
;
401 bool PPP_ContentDecryptor_Private_Proxy::OnMessageReceived(
402 const IPC::Message
& msg
) {
403 if (!dispatcher()->IsPlugin())
404 return false; // These are only valid from host->plugin.
405 // Don't allow the plugin to send these to the host.
408 IPC_BEGIN_MESSAGE_MAP(PPP_ContentDecryptor_Private_Proxy
, msg
)
409 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_Initialize
,
411 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_GenerateKeyRequest
,
412 OnMsgGenerateKeyRequest
)
413 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_AddKey
,
415 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_CancelKeyRequest
,
416 OnMsgCancelKeyRequest
)
417 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_Decrypt
,
419 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder
,
420 OnMsgInitializeAudioDecoder
)
421 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder
,
422 OnMsgInitializeVideoDecoder
)
423 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DeinitializeDecoder
,
424 OnMsgDeinitializeDecoder
)
425 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_ResetDecoder
,
427 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DecryptAndDecode
,
428 OnMsgDecryptAndDecode
)
429 IPC_MESSAGE_UNHANDLED(handled
= false)
430 IPC_END_MESSAGE_MAP()
435 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitialize(
436 PP_Instance instance
,
437 SerializedVarReceiveInput key_system
,
438 bool can_challenge_platform
) {
439 if (ppp_decryptor_impl_
) {
441 ppp_decryptor_impl_
->Initialize
,
443 ExtractReceivedVarAndAddRef(dispatcher(), &key_system
),
444 PP_FromBool(can_challenge_platform
));
448 void PPP_ContentDecryptor_Private_Proxy::OnMsgGenerateKeyRequest(
449 PP_Instance instance
,
450 SerializedVarReceiveInput type
,
451 SerializedVarReceiveInput init_data
) {
452 if (ppp_decryptor_impl_
) {
453 CallWhileUnlocked(ppp_decryptor_impl_
->GenerateKeyRequest
,
455 ExtractReceivedVarAndAddRef(dispatcher(), &type
),
456 ExtractReceivedVarAndAddRef(dispatcher(), &init_data
));
460 void PPP_ContentDecryptor_Private_Proxy::OnMsgAddKey(
461 PP_Instance instance
,
462 SerializedVarReceiveInput session_id
,
463 SerializedVarReceiveInput key
,
464 SerializedVarReceiveInput init_data
) {
465 if (ppp_decryptor_impl_
) {
466 CallWhileUnlocked(ppp_decryptor_impl_
->AddKey
,
468 ExtractReceivedVarAndAddRef(dispatcher(), &session_id
),
469 ExtractReceivedVarAndAddRef(dispatcher(), &key
),
470 ExtractReceivedVarAndAddRef(dispatcher(), &init_data
));
474 void PPP_ContentDecryptor_Private_Proxy::OnMsgCancelKeyRequest(
475 PP_Instance instance
,
476 SerializedVarReceiveInput session_id
) {
477 if (ppp_decryptor_impl_
) {
478 CallWhileUnlocked(ppp_decryptor_impl_
->CancelKeyRequest
,
480 ExtractReceivedVarAndAddRef(dispatcher(), &session_id
));
484 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecrypt(
485 PP_Instance instance
,
486 const PPPDecryptor_Buffer
& encrypted_buffer
,
487 const std::string
& serialized_block_info
) {
488 ScopedPPResource
plugin_resource(
489 ScopedPPResource::PassRef(),
490 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer
.resource
,
491 encrypted_buffer
.handle
,
492 encrypted_buffer
.size
));
493 if (ppp_decryptor_impl_
) {
494 PP_EncryptedBlockInfo block_info
;
495 if (!DeserializeBlockInfo(serialized_block_info
, &block_info
))
497 CallWhileUnlocked(ppp_decryptor_impl_
->Decrypt
,
499 plugin_resource
.get(),
500 const_cast<const PP_EncryptedBlockInfo
*>(&block_info
));
504 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeAudioDecoder(
505 PP_Instance instance
,
506 const std::string
& serialized_decoder_config
,
507 const PPPDecryptor_Buffer
& extra_data_buffer
) {
508 ScopedPPResource plugin_resource
;
509 if (extra_data_buffer
.size
> 0) {
510 plugin_resource
= ScopedPPResource(
511 ScopedPPResource::PassRef(),
512 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer
.resource
,
513 extra_data_buffer
.handle
,
514 extra_data_buffer
.size
));
517 PP_AudioDecoderConfig decoder_config
;
518 if (!DeserializeBlockInfo(serialized_decoder_config
, &decoder_config
))
521 if (ppp_decryptor_impl_
) {
523 ppp_decryptor_impl_
->InitializeAudioDecoder
,
525 const_cast<const PP_AudioDecoderConfig
*>(&decoder_config
),
526 plugin_resource
.get());
530 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeVideoDecoder(
531 PP_Instance instance
,
532 const std::string
& serialized_decoder_config
,
533 const PPPDecryptor_Buffer
& extra_data_buffer
) {
534 ScopedPPResource plugin_resource
;
535 if (extra_data_buffer
.resource
.host_resource() != 0) {
536 plugin_resource
= ScopedPPResource(
537 ScopedPPResource::PassRef(),
538 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer
.resource
,
539 extra_data_buffer
.handle
,
540 extra_data_buffer
.size
));
543 PP_VideoDecoderConfig decoder_config
;
544 if (!DeserializeBlockInfo(serialized_decoder_config
, &decoder_config
))
547 if (ppp_decryptor_impl_
) {
549 ppp_decryptor_impl_
->InitializeVideoDecoder
,
551 const_cast<const PP_VideoDecoderConfig
*>(&decoder_config
),
552 plugin_resource
.get());
556 void PPP_ContentDecryptor_Private_Proxy::OnMsgDeinitializeDecoder(
557 PP_Instance instance
,
558 PP_DecryptorStreamType decoder_type
,
559 uint32_t request_id
) {
560 if (ppp_decryptor_impl_
) {
562 ppp_decryptor_impl_
->DeinitializeDecoder
,
569 void PPP_ContentDecryptor_Private_Proxy::OnMsgResetDecoder(
570 PP_Instance instance
,
571 PP_DecryptorStreamType decoder_type
,
572 uint32_t request_id
) {
573 if (ppp_decryptor_impl_
) {
575 ppp_decryptor_impl_
->ResetDecoder
,
582 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecryptAndDecode(
583 PP_Instance instance
,
584 PP_DecryptorStreamType decoder_type
,
585 const PPPDecryptor_Buffer
& encrypted_buffer
,
586 const std::string
& serialized_block_info
) {
587 ScopedPPResource plugin_resource
;
588 if (encrypted_buffer
.resource
.host_resource() != 0) {
589 plugin_resource
= ScopedPPResource(
590 ScopedPPResource::PassRef(),
591 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer
.resource
,
592 encrypted_buffer
.handle
,
593 encrypted_buffer
.size
));
596 if (ppp_decryptor_impl_
) {
597 PP_EncryptedBlockInfo block_info
;
598 if (!DeserializeBlockInfo(serialized_block_info
, &block_info
))
601 ppp_decryptor_impl_
->DecryptAndDecode
,
604 plugin_resource
.get(),
605 const_cast<const PP_EncryptedBlockInfo
*>(&block_info
));