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 GenerateKeyRequest(PP_Instance instance
,
116 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
123 new PpapiMsg_PPPContentDecryptor_GenerateKeyRequest(
124 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
126 SerializedVarSendInput(dispatcher
, key_system
),
127 SerializedVarSendInput(dispatcher
, type
),
128 SerializedVarSendInput(dispatcher
, init_data
)));
131 void AddKey(PP_Instance instance
,
135 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
142 new PpapiMsg_PPPContentDecryptor_AddKey(
143 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
145 SerializedVarSendInput(dispatcher
, session_id
),
146 SerializedVarSendInput(dispatcher
, key
),
147 SerializedVarSendInput(dispatcher
, init_data
)));
150 void CancelKeyRequest(PP_Instance instance
, PP_Var session_id
) {
151 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
158 new PpapiMsg_PPPContentDecryptor_CancelKeyRequest(
159 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
161 SerializedVarSendInput(dispatcher
, session_id
)));
164 void Decrypt(PP_Instance instance
,
165 PP_Resource encrypted_block
,
166 const PP_EncryptedBlockInfo
* encrypted_block_info
) {
167 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
173 PPPDecryptor_Buffer buffer
;
174 if (!InitializePppDecryptorBuffer(instance
,
182 std::string serialized_block_info
;
183 if (!SerializeBlockInfo(*encrypted_block_info
, &serialized_block_info
)) {
188 // PluginResourceTracker in the plugin process assumes that resources that it
189 // tracks have been addrefed on behalf of the plugin at the renderer side. So
190 // we explicitly do it for |encryped_block| here.
191 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_block
);
194 new PpapiMsg_PPPContentDecryptor_Decrypt(
195 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
198 serialized_block_info
));
201 void InitializeAudioDecoder(
202 PP_Instance instance
,
203 const PP_AudioDecoderConfig
* decoder_config
,
204 PP_Resource extra_data_buffer
) {
205 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
211 std::string serialized_decoder_config
;
212 if (!SerializeBlockInfo(*decoder_config
, &serialized_decoder_config
)) {
217 PPPDecryptor_Buffer buffer
;
218 if (!InitializePppDecryptorBuffer(instance
,
226 // PluginResourceTracker in the plugin process assumes that resources that it
227 // tracks have been addrefed on behalf of the plugin at the renderer side. So
228 // we explicitly do it for |extra_data_buffer| here.
229 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer
);
232 new PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder(
233 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
235 serialized_decoder_config
,
239 void InitializeVideoDecoder(
240 PP_Instance instance
,
241 const PP_VideoDecoderConfig
* decoder_config
,
242 PP_Resource extra_data_buffer
) {
243 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
249 std::string serialized_decoder_config
;
250 if (!SerializeBlockInfo(*decoder_config
, &serialized_decoder_config
)) {
255 PPPDecryptor_Buffer buffer
;
256 if (!InitializePppDecryptorBuffer(instance
,
264 // PluginResourceTracker in the plugin process assumes that resources that it
265 // tracks have been addrefed on behalf of the plugin at the renderer side. So
266 // we explicitly do it for |extra_data_buffer| here.
267 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer
);
270 new PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder(
271 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
273 serialized_decoder_config
,
278 void DeinitializeDecoder(PP_Instance instance
,
279 PP_DecryptorStreamType decoder_type
,
280 uint32_t request_id
) {
281 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
288 new PpapiMsg_PPPContentDecryptor_DeinitializeDecoder(
289 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
295 void ResetDecoder(PP_Instance instance
,
296 PP_DecryptorStreamType decoder_type
,
297 uint32_t request_id
) {
298 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
305 new PpapiMsg_PPPContentDecryptor_ResetDecoder(
306 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
312 void DecryptAndDecode(PP_Instance instance
,
313 PP_DecryptorStreamType decoder_type
,
314 PP_Resource encrypted_buffer
,
315 const PP_EncryptedBlockInfo
* encrypted_block_info
) {
316 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
322 PPPDecryptor_Buffer buffer
;
323 if (!InitializePppDecryptorBuffer(instance
,
331 std::string serialized_block_info
;
332 if (!SerializeBlockInfo(*encrypted_block_info
, &serialized_block_info
)) {
337 // PluginResourceTracker in the plugin process assumes that resources that it
338 // tracks have been addrefed on behalf of the plugin at the renderer side. So
339 // we explicitly do it for |encrypted_buffer| here.
340 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_buffer
);
343 new PpapiMsg_PPPContentDecryptor_DecryptAndDecode(
344 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
348 serialized_block_info
));
351 static const PPP_ContentDecryptor_Private content_decryptor_interface
= {
356 &InitializeAudioDecoder
,
357 &InitializeVideoDecoder
,
358 &DeinitializeDecoder
,
365 PPP_ContentDecryptor_Private_Proxy::PPP_ContentDecryptor_Private_Proxy(
366 Dispatcher
* dispatcher
)
367 : InterfaceProxy(dispatcher
),
368 ppp_decryptor_impl_(NULL
) {
369 if (dispatcher
->IsPlugin()) {
370 ppp_decryptor_impl_
= static_cast<const PPP_ContentDecryptor_Private
*>(
371 dispatcher
->local_get_interface()(
372 PPP_CONTENTDECRYPTOR_PRIVATE_INTERFACE
));
376 PPP_ContentDecryptor_Private_Proxy::~PPP_ContentDecryptor_Private_Proxy() {
380 const PPP_ContentDecryptor_Private
*
381 PPP_ContentDecryptor_Private_Proxy::GetProxyInterface() {
382 return &content_decryptor_interface
;
385 bool PPP_ContentDecryptor_Private_Proxy::OnMessageReceived(
386 const IPC::Message
& msg
) {
387 if (!dispatcher()->IsPlugin())
388 return false; // These are only valid from host->plugin.
389 // Don't allow the plugin to send these to the host.
392 IPC_BEGIN_MESSAGE_MAP(PPP_ContentDecryptor_Private_Proxy
, msg
)
393 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_GenerateKeyRequest
,
394 OnMsgGenerateKeyRequest
)
395 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_AddKey
,
397 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_CancelKeyRequest
,
398 OnMsgCancelKeyRequest
)
399 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_Decrypt
,
401 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder
,
402 OnMsgInitializeAudioDecoder
)
403 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder
,
404 OnMsgInitializeVideoDecoder
)
405 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DeinitializeDecoder
,
406 OnMsgDeinitializeDecoder
)
407 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_ResetDecoder
,
409 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DecryptAndDecode
,
410 OnMsgDecryptAndDecode
)
411 IPC_MESSAGE_UNHANDLED(handled
= false)
412 IPC_END_MESSAGE_MAP()
417 void PPP_ContentDecryptor_Private_Proxy::OnMsgGenerateKeyRequest(
418 PP_Instance instance
,
419 SerializedVarReceiveInput key_system
,
420 SerializedVarReceiveInput type
,
421 SerializedVarReceiveInput init_data
) {
422 if (ppp_decryptor_impl_
) {
423 CallWhileUnlocked(ppp_decryptor_impl_
->GenerateKeyRequest
,
425 ExtractReceivedVarAndAddRef(dispatcher(), &key_system
),
426 ExtractReceivedVarAndAddRef(dispatcher(), &type
),
427 ExtractReceivedVarAndAddRef(dispatcher(), &init_data
));
431 void PPP_ContentDecryptor_Private_Proxy::OnMsgAddKey(
432 PP_Instance instance
,
433 SerializedVarReceiveInput session_id
,
434 SerializedVarReceiveInput key
,
435 SerializedVarReceiveInput init_data
) {
436 if (ppp_decryptor_impl_
) {
437 CallWhileUnlocked(ppp_decryptor_impl_
->AddKey
,
439 ExtractReceivedVarAndAddRef(dispatcher(), &session_id
),
440 ExtractReceivedVarAndAddRef(dispatcher(), &key
),
441 ExtractReceivedVarAndAddRef(dispatcher(), &init_data
));
445 void PPP_ContentDecryptor_Private_Proxy::OnMsgCancelKeyRequest(
446 PP_Instance instance
,
447 SerializedVarReceiveInput session_id
) {
448 if (ppp_decryptor_impl_
) {
449 CallWhileUnlocked(ppp_decryptor_impl_
->CancelKeyRequest
,
451 ExtractReceivedVarAndAddRef(dispatcher(), &session_id
));
455 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecrypt(
456 PP_Instance instance
,
457 const PPPDecryptor_Buffer
& encrypted_buffer
,
458 const std::string
& serialized_block_info
) {
459 ScopedPPResource
plugin_resource(
460 ScopedPPResource::PassRef(),
461 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer
.resource
,
462 encrypted_buffer
.handle
,
463 encrypted_buffer
.size
));
464 if (ppp_decryptor_impl_
) {
465 PP_EncryptedBlockInfo block_info
;
466 if (!DeserializeBlockInfo(serialized_block_info
, &block_info
))
468 CallWhileUnlocked(ppp_decryptor_impl_
->Decrypt
,
470 plugin_resource
.get(),
471 const_cast<const PP_EncryptedBlockInfo
*>(&block_info
));
475 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeAudioDecoder(
476 PP_Instance instance
,
477 const std::string
& serialized_decoder_config
,
478 const PPPDecryptor_Buffer
& extra_data_buffer
) {
479 ScopedPPResource plugin_resource
;
480 if (extra_data_buffer
.size
> 0) {
481 plugin_resource
= ScopedPPResource(
482 ScopedPPResource::PassRef(),
483 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer
.resource
,
484 extra_data_buffer
.handle
,
485 extra_data_buffer
.size
));
488 PP_AudioDecoderConfig decoder_config
;
489 if (!DeserializeBlockInfo(serialized_decoder_config
, &decoder_config
))
492 if (ppp_decryptor_impl_
) {
494 ppp_decryptor_impl_
->InitializeAudioDecoder
,
496 const_cast<const PP_AudioDecoderConfig
*>(&decoder_config
),
497 plugin_resource
.get());
501 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeVideoDecoder(
502 PP_Instance instance
,
503 const std::string
& serialized_decoder_config
,
504 const PPPDecryptor_Buffer
& extra_data_buffer
) {
505 ScopedPPResource plugin_resource
;
506 if (extra_data_buffer
.resource
.host_resource() != 0) {
507 plugin_resource
= ScopedPPResource(
508 ScopedPPResource::PassRef(),
509 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer
.resource
,
510 extra_data_buffer
.handle
,
511 extra_data_buffer
.size
));
514 PP_VideoDecoderConfig decoder_config
;
515 if (!DeserializeBlockInfo(serialized_decoder_config
, &decoder_config
))
518 if (ppp_decryptor_impl_
) {
520 ppp_decryptor_impl_
->InitializeVideoDecoder
,
522 const_cast<const PP_VideoDecoderConfig
*>(&decoder_config
),
523 plugin_resource
.get());
527 void PPP_ContentDecryptor_Private_Proxy::OnMsgDeinitializeDecoder(
528 PP_Instance instance
,
529 PP_DecryptorStreamType decoder_type
,
530 uint32_t request_id
) {
531 if (ppp_decryptor_impl_
) {
533 ppp_decryptor_impl_
->DeinitializeDecoder
,
540 void PPP_ContentDecryptor_Private_Proxy::OnMsgResetDecoder(
541 PP_Instance instance
,
542 PP_DecryptorStreamType decoder_type
,
543 uint32_t request_id
) {
544 if (ppp_decryptor_impl_
) {
546 ppp_decryptor_impl_
->ResetDecoder
,
553 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecryptAndDecode(
554 PP_Instance instance
,
555 PP_DecryptorStreamType decoder_type
,
556 const PPPDecryptor_Buffer
& encrypted_buffer
,
557 const std::string
& serialized_block_info
) {
558 ScopedPPResource plugin_resource
;
559 if (encrypted_buffer
.resource
.host_resource() != 0) {
560 plugin_resource
= ScopedPPResource(
561 ScopedPPResource::PassRef(),
562 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer
.resource
,
563 encrypted_buffer
.handle
,
564 encrypted_buffer
.size
));
567 if (ppp_decryptor_impl_
) {
568 PP_EncryptedBlockInfo block_info
;
569 if (!DeserializeBlockInfo(serialized_block_info
, &block_info
))
572 ppp_decryptor_impl_
->DecryptAndDecode
,
575 plugin_resource
.get(),
576 const_cast<const PP_EncryptedBlockInfo
*>(&block_info
));