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_buffer_trusted_api.h"
22 #include "ppapi/thunk/ppb_instance_api.h"
23 #include "ppapi/thunk/thunk.h"
25 using ppapi::thunk::EnterResourceNoLock
;
26 using ppapi::thunk::PPB_Buffer_API
;
27 using ppapi::thunk::PPB_BufferTrusted_API
;
28 using ppapi::thunk::PPB_Instance_API
;
35 PP_Bool
DescribeHostBufferResource(PP_Resource resource
, uint32_t* size
) {
36 EnterResourceNoLock
<PPB_Buffer_API
> enter(resource
, true);
39 return enter
.object()->Describe(size
);
42 // TODO(dmichael): Refactor so this handle sharing code is in one place.
43 PP_Bool
ShareHostBufferResourceToPlugin(
44 HostDispatcher
* dispatcher
,
46 base::SharedMemoryHandle
* shared_mem_handle
) {
47 if (!dispatcher
|| resource
== 0 || !shared_mem_handle
)
49 EnterResourceNoLock
<PPB_BufferTrusted_API
> enter(resource
, true);
53 int32_t result
= enter
.object()->GetSharedMemory(&handle
);
56 base::PlatformFile platform_file
=
58 reinterpret_cast<HANDLE
>(static_cast<intptr_t>(handle
));
59 #elif defined(OS_POSIX)
62 #error Not implemented.
65 *shared_mem_handle
= dispatcher
->ShareHandleWithRemote(platform_file
, false);
69 // SerializedVarReceiveInput will decrement the reference count, but we want
70 // to give the recipient a reference. This utility function takes care of that
71 // work for the message handlers defined below.
72 PP_Var
ExtractReceivedVarAndAddRef(Dispatcher
* dispatcher
,
73 SerializedVarReceiveInput
* serialized_var
) {
74 PP_Var var
= serialized_var
->Get(dispatcher
);
75 PpapiGlobals::Get()->GetVarTracker()->AddRefVar(var
);
79 bool InitializePppDecryptorBuffer(PP_Instance instance
,
80 HostDispatcher
* dispatcher
,
82 PPPDecryptor_Buffer
* buffer
) {
89 buffer
->resource
= HostResource();
90 buffer
->handle
= base::SharedMemoryHandle();
95 HostResource host_resource
;
96 host_resource
.SetHostResource(instance
, resource
);
99 if (DescribeHostBufferResource(resource
, &size
) == PP_FALSE
)
102 base::SharedMemoryHandle handle
;
103 if (ShareHostBufferResourceToPlugin(dispatcher
,
105 &handle
) == PP_FALSE
)
108 buffer
->resource
= host_resource
;
109 buffer
->handle
= handle
;
114 void GenerateKeyRequest(PP_Instance instance
,
118 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
125 new PpapiMsg_PPPContentDecryptor_GenerateKeyRequest(
126 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
128 SerializedVarSendInput(dispatcher
, key_system
),
129 SerializedVarSendInput(dispatcher
, type
),
130 SerializedVarSendInput(dispatcher
, init_data
)));
133 void AddKey(PP_Instance instance
,
137 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
144 new PpapiMsg_PPPContentDecryptor_AddKey(
145 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
147 SerializedVarSendInput(dispatcher
, session_id
),
148 SerializedVarSendInput(dispatcher
, key
),
149 SerializedVarSendInput(dispatcher
, init_data
)));
152 void CancelKeyRequest(PP_Instance instance
, PP_Var session_id
) {
153 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
160 new PpapiMsg_PPPContentDecryptor_CancelKeyRequest(
161 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
163 SerializedVarSendInput(dispatcher
, session_id
)));
166 void Decrypt(PP_Instance instance
,
167 PP_Resource encrypted_block
,
168 const PP_EncryptedBlockInfo
* encrypted_block_info
) {
169 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
175 PPPDecryptor_Buffer buffer
;
176 if (!InitializePppDecryptorBuffer(instance
,
184 std::string serialized_block_info
;
185 if (!SerializeBlockInfo(*encrypted_block_info
, &serialized_block_info
)) {
190 // PluginResourceTracker in the plugin process assumes that resources that it
191 // tracks have been addrefed on behalf of the plugin at the renderer side. So
192 // we explicitly do it for |encryped_block| here.
193 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_block
);
196 new PpapiMsg_PPPContentDecryptor_Decrypt(
197 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
200 serialized_block_info
));
203 void InitializeAudioDecoder(
204 PP_Instance instance
,
205 const PP_AudioDecoderConfig
* decoder_config
,
206 PP_Resource extra_data_buffer
) {
207 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
213 std::string serialized_decoder_config
;
214 if (!SerializeBlockInfo(*decoder_config
, &serialized_decoder_config
)) {
219 PPPDecryptor_Buffer buffer
;
220 if (!InitializePppDecryptorBuffer(instance
,
228 // PluginResourceTracker in the plugin process assumes that resources that it
229 // tracks have been addrefed on behalf of the plugin at the renderer side. So
230 // we explicitly do it for |extra_data_buffer| here.
231 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer
);
234 new PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder(
235 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
237 serialized_decoder_config
,
241 void InitializeVideoDecoder(
242 PP_Instance instance
,
243 const PP_VideoDecoderConfig
* decoder_config
,
244 PP_Resource extra_data_buffer
) {
245 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
251 std::string serialized_decoder_config
;
252 if (!SerializeBlockInfo(*decoder_config
, &serialized_decoder_config
)) {
257 PPPDecryptor_Buffer buffer
;
258 if (!InitializePppDecryptorBuffer(instance
,
266 // PluginResourceTracker in the plugin process assumes that resources that it
267 // tracks have been addrefed on behalf of the plugin at the renderer side. So
268 // we explicitly do it for |extra_data_buffer| here.
269 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer
);
272 new PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder(
273 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
275 serialized_decoder_config
,
280 void DeinitializeDecoder(PP_Instance instance
,
281 PP_DecryptorStreamType decoder_type
,
282 uint32_t request_id
) {
283 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
290 new PpapiMsg_PPPContentDecryptor_DeinitializeDecoder(
291 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
297 void ResetDecoder(PP_Instance instance
,
298 PP_DecryptorStreamType decoder_type
,
299 uint32_t request_id
) {
300 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
307 new PpapiMsg_PPPContentDecryptor_ResetDecoder(
308 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
314 void DecryptAndDecode(PP_Instance instance
,
315 PP_DecryptorStreamType decoder_type
,
316 PP_Resource encrypted_buffer
,
317 const PP_EncryptedBlockInfo
* encrypted_block_info
) {
318 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
324 PPPDecryptor_Buffer buffer
;
325 if (!InitializePppDecryptorBuffer(instance
,
333 std::string serialized_block_info
;
334 if (!SerializeBlockInfo(*encrypted_block_info
, &serialized_block_info
)) {
339 // PluginResourceTracker in the plugin process assumes that resources that it
340 // tracks have been addrefed on behalf of the plugin at the renderer side. So
341 // we explicitly do it for |encrypted_buffer| here.
342 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_buffer
);
345 new PpapiMsg_PPPContentDecryptor_DecryptAndDecode(
346 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
350 serialized_block_info
));
353 static const PPP_ContentDecryptor_Private content_decryptor_interface
= {
358 &InitializeAudioDecoder
,
359 &InitializeVideoDecoder
,
360 &DeinitializeDecoder
,
367 PPP_ContentDecryptor_Private_Proxy::PPP_ContentDecryptor_Private_Proxy(
368 Dispatcher
* dispatcher
)
369 : InterfaceProxy(dispatcher
),
370 ppp_decryptor_impl_(NULL
) {
371 if (dispatcher
->IsPlugin()) {
372 ppp_decryptor_impl_
= static_cast<const PPP_ContentDecryptor_Private
*>(
373 dispatcher
->local_get_interface()(
374 PPP_CONTENTDECRYPTOR_PRIVATE_INTERFACE
));
378 PPP_ContentDecryptor_Private_Proxy::~PPP_ContentDecryptor_Private_Proxy() {
382 const PPP_ContentDecryptor_Private
*
383 PPP_ContentDecryptor_Private_Proxy::GetProxyInterface() {
384 return &content_decryptor_interface
;
387 bool PPP_ContentDecryptor_Private_Proxy::OnMessageReceived(
388 const IPC::Message
& msg
) {
390 IPC_BEGIN_MESSAGE_MAP(PPP_ContentDecryptor_Private_Proxy
, msg
)
391 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_GenerateKeyRequest
,
392 OnMsgGenerateKeyRequest
)
393 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_AddKey
,
395 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_CancelKeyRequest
,
396 OnMsgCancelKeyRequest
)
397 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_Decrypt
,
399 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder
,
400 OnMsgInitializeAudioDecoder
)
401 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder
,
402 OnMsgInitializeVideoDecoder
)
403 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DeinitializeDecoder
,
404 OnMsgDeinitializeDecoder
)
405 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_ResetDecoder
,
407 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DecryptAndDecode
,
408 OnMsgDecryptAndDecode
)
409 IPC_MESSAGE_UNHANDLED(handled
= false)
410 IPC_END_MESSAGE_MAP()
415 void PPP_ContentDecryptor_Private_Proxy::OnMsgGenerateKeyRequest(
416 PP_Instance instance
,
417 SerializedVarReceiveInput key_system
,
418 SerializedVarReceiveInput type
,
419 SerializedVarReceiveInput init_data
) {
420 if (ppp_decryptor_impl_
) {
421 CallWhileUnlocked(ppp_decryptor_impl_
->GenerateKeyRequest
,
423 ExtractReceivedVarAndAddRef(dispatcher(), &key_system
),
424 ExtractReceivedVarAndAddRef(dispatcher(), &type
),
425 ExtractReceivedVarAndAddRef(dispatcher(), &init_data
));
429 void PPP_ContentDecryptor_Private_Proxy::OnMsgAddKey(
430 PP_Instance instance
,
431 SerializedVarReceiveInput session_id
,
432 SerializedVarReceiveInput key
,
433 SerializedVarReceiveInput init_data
) {
434 if (ppp_decryptor_impl_
) {
435 CallWhileUnlocked(ppp_decryptor_impl_
->AddKey
,
437 ExtractReceivedVarAndAddRef(dispatcher(), &session_id
),
438 ExtractReceivedVarAndAddRef(dispatcher(), &key
),
439 ExtractReceivedVarAndAddRef(dispatcher(), &init_data
));
443 void PPP_ContentDecryptor_Private_Proxy::OnMsgCancelKeyRequest(
444 PP_Instance instance
,
445 SerializedVarReceiveInput session_id
) {
446 if (ppp_decryptor_impl_
) {
447 CallWhileUnlocked(ppp_decryptor_impl_
->CancelKeyRequest
,
449 ExtractReceivedVarAndAddRef(dispatcher(), &session_id
));
453 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecrypt(
454 PP_Instance instance
,
455 const PPPDecryptor_Buffer
& encrypted_buffer
,
456 const std::string
& serialized_block_info
) {
457 ScopedPPResource
plugin_resource(
458 ScopedPPResource::PassRef(),
459 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer
.resource
,
460 encrypted_buffer
.handle
,
461 encrypted_buffer
.size
));
462 if (ppp_decryptor_impl_
) {
463 PP_EncryptedBlockInfo block_info
;
464 if (!DeserializeBlockInfo(serialized_block_info
, &block_info
))
466 CallWhileUnlocked(ppp_decryptor_impl_
->Decrypt
,
468 plugin_resource
.get(),
469 const_cast<const PP_EncryptedBlockInfo
*>(&block_info
));
473 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeAudioDecoder(
474 PP_Instance instance
,
475 const std::string
& serialized_decoder_config
,
476 const PPPDecryptor_Buffer
& extra_data_buffer
) {
477 ScopedPPResource plugin_resource
;
478 if (extra_data_buffer
.size
> 0) {
479 plugin_resource
= ScopedPPResource(
480 ScopedPPResource::PassRef(),
481 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer
.resource
,
482 extra_data_buffer
.handle
,
483 extra_data_buffer
.size
));
486 PP_AudioDecoderConfig decoder_config
;
487 if (!DeserializeBlockInfo(serialized_decoder_config
, &decoder_config
))
490 if (ppp_decryptor_impl_
) {
492 ppp_decryptor_impl_
->InitializeAudioDecoder
,
494 const_cast<const PP_AudioDecoderConfig
*>(&decoder_config
),
495 plugin_resource
.get());
499 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeVideoDecoder(
500 PP_Instance instance
,
501 const std::string
& serialized_decoder_config
,
502 const PPPDecryptor_Buffer
& extra_data_buffer
) {
503 ScopedPPResource plugin_resource
;
504 if (extra_data_buffer
.resource
.host_resource() != 0) {
505 plugin_resource
= ScopedPPResource(
506 ScopedPPResource::PassRef(),
507 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer
.resource
,
508 extra_data_buffer
.handle
,
509 extra_data_buffer
.size
));
512 PP_VideoDecoderConfig decoder_config
;
513 if (!DeserializeBlockInfo(serialized_decoder_config
, &decoder_config
))
516 if (ppp_decryptor_impl_
) {
518 ppp_decryptor_impl_
->InitializeVideoDecoder
,
520 const_cast<const PP_VideoDecoderConfig
*>(&decoder_config
),
521 plugin_resource
.get());
525 void PPP_ContentDecryptor_Private_Proxy::OnMsgDeinitializeDecoder(
526 PP_Instance instance
,
527 PP_DecryptorStreamType decoder_type
,
528 uint32_t request_id
) {
529 if (ppp_decryptor_impl_
) {
531 ppp_decryptor_impl_
->DeinitializeDecoder
,
538 void PPP_ContentDecryptor_Private_Proxy::OnMsgResetDecoder(
539 PP_Instance instance
,
540 PP_DecryptorStreamType decoder_type
,
541 uint32_t request_id
) {
542 if (ppp_decryptor_impl_
) {
544 ppp_decryptor_impl_
->ResetDecoder
,
551 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecryptAndDecode(
552 PP_Instance instance
,
553 PP_DecryptorStreamType decoder_type
,
554 const PPPDecryptor_Buffer
& encrypted_buffer
,
555 const std::string
& serialized_block_info
) {
556 ScopedPPResource plugin_resource
;
557 if (encrypted_buffer
.resource
.host_resource() != 0) {
558 plugin_resource
= ScopedPPResource(
559 ScopedPPResource::PassRef(),
560 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer
.resource
,
561 encrypted_buffer
.handle
,
562 encrypted_buffer
.size
));
565 if (ppp_decryptor_impl_
) {
566 PP_EncryptedBlockInfo block_info
;
567 if (!DeserializeBlockInfo(serialized_block_info
, &block_info
))
570 ppp_decryptor_impl_
->DecryptAndDecode
,
573 plugin_resource
.get(),
574 const_cast<const PP_EncryptedBlockInfo
*>(&block_info
));