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 "media/base/limits.h"
9 #include "ppapi/c/pp_bool.h"
10 #include "ppapi/c/ppb_core.h"
11 #include "ppapi/proxy/content_decryptor_private_serializer.h"
12 #include "ppapi/proxy/host_dispatcher.h"
13 #include "ppapi/proxy/plugin_globals.h"
14 #include "ppapi/proxy/plugin_resource_tracker.h"
15 #include "ppapi/proxy/ppapi_messages.h"
16 #include "ppapi/proxy/ppb_buffer_proxy.h"
17 #include "ppapi/proxy/serialized_var.h"
18 #include "ppapi/shared_impl/scoped_pp_resource.h"
19 #include "ppapi/shared_impl/scoped_pp_var.h"
20 #include "ppapi/shared_impl/var_tracker.h"
21 #include "ppapi/thunk/enter.h"
22 #include "ppapi/thunk/ppb_buffer_api.h"
23 #include "ppapi/thunk/ppb_instance_api.h"
24 #include "ppapi/thunk/thunk.h"
26 using ppapi::thunk::EnterResourceNoLock
;
27 using ppapi::thunk::PPB_Buffer_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_Buffer_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 Initialize(PP_Instance instance
,
117 PP_Bool allow_distinctive_identifier
,
118 PP_Bool allow_persistent_state
) {
119 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
125 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_Initialize(
126 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
, instance
, promise_id
,
127 SerializedVarSendInput(dispatcher
, key_system
),
128 allow_distinctive_identifier
, allow_persistent_state
));
131 void SetServerCertificate(PP_Instance instance
,
133 PP_Var server_certificate
) {
134 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
140 ArrayBufferVar
* server_certificate_buffer
=
141 ArrayBufferVar::FromPPVar(server_certificate
);
142 if (!server_certificate_buffer
||
143 server_certificate_buffer
->ByteLength() <
144 media::limits::kMinCertificateLength
||
145 server_certificate_buffer
->ByteLength() >
146 media::limits::kMaxCertificateLength
) {
151 const uint8_t* server_certificate_ptr
=
152 static_cast<const uint8_t*>(server_certificate_buffer
->Map());
153 const uint32_t server_certificate_size
=
154 server_certificate_buffer
->ByteLength();
155 std::vector
<uint8_t> server_certificate_vector(
156 server_certificate_ptr
, server_certificate_ptr
+ server_certificate_size
);
158 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_SetServerCertificate(
159 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
162 server_certificate_vector
));
165 void CreateSessionAndGenerateRequest(PP_Instance instance
,
167 PP_SessionType session_type
,
168 PP_InitDataType init_data_type
,
170 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
177 new PpapiMsg_PPPContentDecryptor_CreateSessionAndGenerateRequest(
178 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
, instance
, promise_id
,
179 session_type
, init_data_type
,
180 SerializedVarSendInput(dispatcher
, init_data
)));
183 void LoadSession(PP_Instance instance
,
185 PP_SessionType session_type
,
187 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
193 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_LoadSession(
194 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
, instance
, promise_id
, session_type
,
195 SerializedVarSendInput(dispatcher
, session_id
)));
198 void UpdateSession(PP_Instance instance
,
202 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
208 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_UpdateSession(
209 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
, instance
, promise_id
,
210 SerializedVarSendInput(dispatcher
, session_id
),
211 SerializedVarSendInput(dispatcher
, response
)));
214 void CloseSession(PP_Instance instance
,
217 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
223 StringVar
* session_id_string
= StringVar::FromPPVar(session_id
);
224 if (!session_id_string
||
225 session_id_string
->value().length() >
226 media::limits::kMaxSessionIdLength
) {
231 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_CloseSession(
232 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
, instance
, promise_id
,
233 session_id_string
->value()));
236 void RemoveSession(PP_Instance instance
,
239 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
245 StringVar
* session_id_string
= StringVar::FromPPVar(session_id
);
246 if (!session_id_string
||
247 session_id_string
->value().length() >
248 media::limits::kMaxSessionIdLength
) {
253 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_RemoveSession(
254 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
, instance
, promise_id
,
255 session_id_string
->value()));
258 void Decrypt(PP_Instance instance
,
259 PP_Resource encrypted_block
,
260 const PP_EncryptedBlockInfo
* encrypted_block_info
) {
261 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
267 PPPDecryptor_Buffer buffer
;
268 if (!InitializePppDecryptorBuffer(instance
,
276 std::string serialized_block_info
;
277 if (!SerializeBlockInfo(*encrypted_block_info
, &serialized_block_info
)) {
282 // PluginResourceTracker in the plugin process assumes that resources that it
283 // tracks have been addrefed on behalf of the plugin at the renderer side. So
284 // we explicitly do it for |encryped_block| here.
285 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_block
);
288 new PpapiMsg_PPPContentDecryptor_Decrypt(
289 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
292 serialized_block_info
));
295 void InitializeAudioDecoder(
296 PP_Instance instance
,
297 const PP_AudioDecoderConfig
* decoder_config
,
298 PP_Resource extra_data_buffer
) {
299 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
305 std::string serialized_decoder_config
;
306 if (!SerializeBlockInfo(*decoder_config
, &serialized_decoder_config
)) {
311 PPPDecryptor_Buffer buffer
;
312 if (!InitializePppDecryptorBuffer(instance
,
320 // PluginResourceTracker in the plugin process assumes that resources that it
321 // tracks have been addrefed on behalf of the plugin at the renderer side. So
322 // we explicitly do it for |extra_data_buffer| here.
323 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer
);
326 new PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder(
327 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
329 serialized_decoder_config
,
333 void InitializeVideoDecoder(
334 PP_Instance instance
,
335 const PP_VideoDecoderConfig
* decoder_config
,
336 PP_Resource extra_data_buffer
) {
337 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
343 std::string serialized_decoder_config
;
344 if (!SerializeBlockInfo(*decoder_config
, &serialized_decoder_config
)) {
349 PPPDecryptor_Buffer buffer
;
350 if (!InitializePppDecryptorBuffer(instance
,
358 // PluginResourceTracker in the plugin process assumes that resources that it
359 // tracks have been addrefed on behalf of the plugin at the renderer side. So
360 // we explicitly do it for |extra_data_buffer| here.
361 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer
);
364 new PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder(
365 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
367 serialized_decoder_config
,
372 void DeinitializeDecoder(PP_Instance instance
,
373 PP_DecryptorStreamType decoder_type
,
374 uint32_t request_id
) {
375 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
382 new PpapiMsg_PPPContentDecryptor_DeinitializeDecoder(
383 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
389 void ResetDecoder(PP_Instance instance
,
390 PP_DecryptorStreamType decoder_type
,
391 uint32_t request_id
) {
392 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
399 new PpapiMsg_PPPContentDecryptor_ResetDecoder(
400 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
406 void DecryptAndDecode(PP_Instance instance
,
407 PP_DecryptorStreamType decoder_type
,
408 PP_Resource encrypted_buffer
,
409 const PP_EncryptedBlockInfo
* encrypted_block_info
) {
410 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
416 PPPDecryptor_Buffer buffer
;
417 if (!InitializePppDecryptorBuffer(instance
,
425 std::string serialized_block_info
;
426 if (!SerializeBlockInfo(*encrypted_block_info
, &serialized_block_info
)) {
431 // PluginResourceTracker in the plugin process assumes that resources that it
432 // tracks have been addrefed on behalf of the plugin at the renderer side. So
433 // we explicitly do it for |encrypted_buffer| here.
434 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_buffer
);
437 new PpapiMsg_PPPContentDecryptor_DecryptAndDecode(
438 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
442 serialized_block_info
));
445 static const PPP_ContentDecryptor_Private content_decryptor_interface
= {
447 &SetServerCertificate
,
448 &CreateSessionAndGenerateRequest
,
454 &InitializeAudioDecoder
,
455 &InitializeVideoDecoder
,
456 &DeinitializeDecoder
,
462 PPP_ContentDecryptor_Private_Proxy::PPP_ContentDecryptor_Private_Proxy(
463 Dispatcher
* dispatcher
)
464 : InterfaceProxy(dispatcher
),
465 ppp_decryptor_impl_(NULL
) {
466 if (dispatcher
->IsPlugin()) {
467 ppp_decryptor_impl_
= static_cast<const PPP_ContentDecryptor_Private
*>(
468 dispatcher
->local_get_interface()(
469 PPP_CONTENTDECRYPTOR_PRIVATE_INTERFACE
));
473 PPP_ContentDecryptor_Private_Proxy::~PPP_ContentDecryptor_Private_Proxy() {
477 const PPP_ContentDecryptor_Private
*
478 PPP_ContentDecryptor_Private_Proxy::GetProxyInterface() {
479 return &content_decryptor_interface
;
482 bool PPP_ContentDecryptor_Private_Proxy::OnMessageReceived(
483 const IPC::Message
& msg
) {
484 if (!dispatcher()->IsPlugin())
485 return false; // These are only valid from host->plugin.
486 // Don't allow the plugin to send these to the host.
489 IPC_BEGIN_MESSAGE_MAP(PPP_ContentDecryptor_Private_Proxy
, msg
)
490 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_Initialize
,
492 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_SetServerCertificate
,
493 OnMsgSetServerCertificate
)
495 PpapiMsg_PPPContentDecryptor_CreateSessionAndGenerateRequest
,
496 OnMsgCreateSessionAndGenerateRequest
)
497 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_LoadSession
,
499 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_UpdateSession
,
501 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_CloseSession
,
503 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_RemoveSession
,
505 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_Decrypt
,
507 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder
,
508 OnMsgInitializeAudioDecoder
)
509 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder
,
510 OnMsgInitializeVideoDecoder
)
511 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DeinitializeDecoder
,
512 OnMsgDeinitializeDecoder
)
513 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_ResetDecoder
,
515 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DecryptAndDecode
,
516 OnMsgDecryptAndDecode
)
517 IPC_MESSAGE_UNHANDLED(handled
= false)
518 IPC_END_MESSAGE_MAP()
523 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitialize(
524 PP_Instance instance
,
526 SerializedVarReceiveInput key_system
,
527 PP_Bool allow_distinctive_identifier
,
528 PP_Bool allow_persistent_state
) {
529 if (ppp_decryptor_impl_
) {
530 CallWhileUnlocked(ppp_decryptor_impl_
->Initialize
, instance
, promise_id
,
531 ExtractReceivedVarAndAddRef(dispatcher(), &key_system
),
532 allow_distinctive_identifier
, allow_persistent_state
);
536 void PPP_ContentDecryptor_Private_Proxy::OnMsgSetServerCertificate(
537 PP_Instance instance
,
539 std::vector
<uint8_t> server_certificate
) {
540 if (server_certificate
.size() < media::limits::kMinCertificateLength
||
541 server_certificate
.size() > media::limits::kMaxCertificateLength
) {
546 if (ppp_decryptor_impl_
) {
547 ScopedPPVar
server_certificate_var(
548 ScopedPPVar::PassRef(),
551 ->MakeArrayBufferPPVar(
552 static_cast<uint32_t>(server_certificate
.size()),
553 &server_certificate
[0]));
554 CallWhileUnlocked(ppp_decryptor_impl_
->SetServerCertificate
,
557 server_certificate_var
.get());
561 void PPP_ContentDecryptor_Private_Proxy::OnMsgCreateSessionAndGenerateRequest(
562 PP_Instance instance
,
564 PP_SessionType session_type
,
565 PP_InitDataType init_data_type
,
566 SerializedVarReceiveInput init_data
) {
567 if (ppp_decryptor_impl_
) {
568 CallWhileUnlocked(ppp_decryptor_impl_
->CreateSessionAndGenerateRequest
,
569 instance
, promise_id
, session_type
, init_data_type
,
570 ExtractReceivedVarAndAddRef(dispatcher(), &init_data
));
574 void PPP_ContentDecryptor_Private_Proxy::OnMsgLoadSession(
575 PP_Instance instance
,
577 PP_SessionType session_type
,
578 SerializedVarReceiveInput session_id
) {
579 if (ppp_decryptor_impl_
) {
580 CallWhileUnlocked(ppp_decryptor_impl_
->LoadSession
, instance
, promise_id
,
582 ExtractReceivedVarAndAddRef(dispatcher(), &session_id
));
586 void PPP_ContentDecryptor_Private_Proxy::OnMsgUpdateSession(
587 PP_Instance instance
,
589 SerializedVarReceiveInput session_id
,
590 SerializedVarReceiveInput response
) {
591 if (ppp_decryptor_impl_
) {
592 CallWhileUnlocked(ppp_decryptor_impl_
->UpdateSession
, instance
, promise_id
,
593 ExtractReceivedVarAndAddRef(dispatcher(), &session_id
),
594 ExtractReceivedVarAndAddRef(dispatcher(), &response
));
598 void PPP_ContentDecryptor_Private_Proxy::OnMsgCloseSession(
599 PP_Instance instance
,
601 const std::string
& session_id
) {
602 if (ppp_decryptor_impl_
) {
603 ScopedPPVar
session_id_var(ScopedPPVar::PassRef(),
604 StringVar::StringToPPVar(session_id
));
605 CallWhileUnlocked(ppp_decryptor_impl_
->CloseSession
, instance
, promise_id
,
606 session_id_var
.get());
610 void PPP_ContentDecryptor_Private_Proxy::OnMsgRemoveSession(
611 PP_Instance instance
,
613 const std::string
& session_id
) {
614 if (ppp_decryptor_impl_
) {
615 ScopedPPVar
session_id_var(ScopedPPVar::PassRef(),
616 StringVar::StringToPPVar(session_id
));
617 CallWhileUnlocked(ppp_decryptor_impl_
->RemoveSession
, instance
, promise_id
,
618 session_id_var
.get());
622 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecrypt(
623 PP_Instance instance
,
624 const PPPDecryptor_Buffer
& encrypted_buffer
,
625 const std::string
& serialized_block_info
) {
626 ScopedPPResource
plugin_resource(
627 ScopedPPResource::PassRef(),
628 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer
.resource
,
629 encrypted_buffer
.handle
,
630 encrypted_buffer
.size
));
631 if (ppp_decryptor_impl_
) {
632 PP_EncryptedBlockInfo block_info
;
633 if (!DeserializeBlockInfo(serialized_block_info
, &block_info
))
635 CallWhileUnlocked(ppp_decryptor_impl_
->Decrypt
,
637 plugin_resource
.get(),
642 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeAudioDecoder(
643 PP_Instance instance
,
644 const std::string
& serialized_decoder_config
,
645 const PPPDecryptor_Buffer
& extra_data_buffer
) {
646 ScopedPPResource plugin_resource
;
647 if (extra_data_buffer
.size
> 0) {
648 plugin_resource
= ScopedPPResource(
649 ScopedPPResource::PassRef(),
650 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer
.resource
,
651 extra_data_buffer
.handle
,
652 extra_data_buffer
.size
));
655 PP_AudioDecoderConfig decoder_config
;
656 if (!DeserializeBlockInfo(serialized_decoder_config
, &decoder_config
))
659 if (ppp_decryptor_impl_
) {
661 ppp_decryptor_impl_
->InitializeAudioDecoder
,
664 plugin_resource
.get());
668 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeVideoDecoder(
669 PP_Instance instance
,
670 const std::string
& serialized_decoder_config
,
671 const PPPDecryptor_Buffer
& extra_data_buffer
) {
672 ScopedPPResource plugin_resource
;
673 if (extra_data_buffer
.resource
.host_resource() != 0) {
674 plugin_resource
= ScopedPPResource(
675 ScopedPPResource::PassRef(),
676 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer
.resource
,
677 extra_data_buffer
.handle
,
678 extra_data_buffer
.size
));
681 PP_VideoDecoderConfig decoder_config
;
682 if (!DeserializeBlockInfo(serialized_decoder_config
, &decoder_config
))
685 if (ppp_decryptor_impl_
) {
687 ppp_decryptor_impl_
->InitializeVideoDecoder
,
690 plugin_resource
.get());
694 void PPP_ContentDecryptor_Private_Proxy::OnMsgDeinitializeDecoder(
695 PP_Instance instance
,
696 PP_DecryptorStreamType decoder_type
,
697 uint32_t request_id
) {
698 if (ppp_decryptor_impl_
) {
700 ppp_decryptor_impl_
->DeinitializeDecoder
,
707 void PPP_ContentDecryptor_Private_Proxy::OnMsgResetDecoder(
708 PP_Instance instance
,
709 PP_DecryptorStreamType decoder_type
,
710 uint32_t request_id
) {
711 if (ppp_decryptor_impl_
) {
713 ppp_decryptor_impl_
->ResetDecoder
,
720 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecryptAndDecode(
721 PP_Instance instance
,
722 PP_DecryptorStreamType decoder_type
,
723 const PPPDecryptor_Buffer
& encrypted_buffer
,
724 const std::string
& serialized_block_info
) {
725 ScopedPPResource plugin_resource
;
726 if (encrypted_buffer
.resource
.host_resource() != 0) {
727 plugin_resource
= ScopedPPResource(
728 ScopedPPResource::PassRef(),
729 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer
.resource
,
730 encrypted_buffer
.handle
,
731 encrypted_buffer
.size
));
734 if (ppp_decryptor_impl_
) {
735 PP_EncryptedBlockInfo block_info
;
736 if (!DeserializeBlockInfo(serialized_block_info
, &block_info
))
739 ppp_decryptor_impl_
->DecryptAndDecode
,
742 plugin_resource
.get(),