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
,
116 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
123 new PpapiMsg_PPPContentDecryptor_Initialize(
124 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
126 SerializedVarSendInput(dispatcher
, key_system
)));
129 void SetServerCertificate(PP_Instance instance
,
131 PP_Var server_certificate
) {
132 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
138 ArrayBufferVar
* server_certificate_buffer
=
139 ArrayBufferVar::FromPPVar(server_certificate
);
140 if (!server_certificate_buffer
||
141 server_certificate_buffer
->ByteLength() <
142 media::limits::kMinCertificateLength
||
143 server_certificate_buffer
->ByteLength() >
144 media::limits::kMaxCertificateLength
) {
149 const uint8_t* server_certificate_ptr
=
150 static_cast<const uint8_t*>(server_certificate_buffer
->Map());
151 const uint32_t server_certificate_size
=
152 server_certificate_buffer
->ByteLength();
153 std::vector
<uint8_t> server_certificate_vector(
154 server_certificate_ptr
, server_certificate_ptr
+ server_certificate_size
);
156 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_SetServerCertificate(
157 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
160 server_certificate_vector
));
163 void CreateSession(PP_Instance instance
,
165 PP_Var init_data_type
,
167 PP_SessionType session_type
) {
168 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
174 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_CreateSession(
175 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
178 SerializedVarSendInput(dispatcher
, init_data_type
),
179 SerializedVarSendInput(dispatcher
, init_data
),
183 void LoadSession(PP_Instance instance
,
185 PP_Var web_session_id
) {
186 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
192 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_LoadSession(
193 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
196 SerializedVarSendInput(dispatcher
, web_session_id
)));
199 void UpdateSession(PP_Instance instance
,
201 PP_Var web_session_id
,
203 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
209 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_UpdateSession(
210 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
213 SerializedVarSendInput(dispatcher
, web_session_id
),
214 SerializedVarSendInput(dispatcher
, response
)));
217 void CloseSession(PP_Instance instance
,
219 PP_Var web_session_id
) {
220 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
226 StringVar
* session_id
= StringVar::FromPPVar(web_session_id
);
228 session_id
->value().length() > media::limits::kMaxWebSessionIdLength
) {
233 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_CloseSession(
234 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
237 session_id
->value()));
240 void RemoveSession(PP_Instance instance
,
242 PP_Var web_session_id
) {
243 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
249 StringVar
* session_id
= StringVar::FromPPVar(web_session_id
);
251 session_id
->value().length() > media::limits::kMaxWebSessionIdLength
) {
256 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_RemoveSession(
257 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
260 session_id
->value()));
263 void GetUsableKeyIds(PP_Instance instance
,
265 PP_Var web_session_id
) {
266 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
272 StringVar
* session_id
= StringVar::FromPPVar(web_session_id
);
274 session_id
->value().length() > media::limits::kMaxWebSessionIdLength
) {
279 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_GetUsableKeyIds(
280 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
283 session_id
->value()));
286 void Decrypt(PP_Instance instance
,
287 PP_Resource encrypted_block
,
288 const PP_EncryptedBlockInfo
* encrypted_block_info
) {
289 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
295 PPPDecryptor_Buffer buffer
;
296 if (!InitializePppDecryptorBuffer(instance
,
304 std::string serialized_block_info
;
305 if (!SerializeBlockInfo(*encrypted_block_info
, &serialized_block_info
)) {
310 // PluginResourceTracker in the plugin process assumes that resources that it
311 // tracks have been addrefed on behalf of the plugin at the renderer side. So
312 // we explicitly do it for |encryped_block| here.
313 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_block
);
316 new PpapiMsg_PPPContentDecryptor_Decrypt(
317 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
320 serialized_block_info
));
323 void InitializeAudioDecoder(
324 PP_Instance instance
,
325 const PP_AudioDecoderConfig
* decoder_config
,
326 PP_Resource extra_data_buffer
) {
327 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
333 std::string serialized_decoder_config
;
334 if (!SerializeBlockInfo(*decoder_config
, &serialized_decoder_config
)) {
339 PPPDecryptor_Buffer buffer
;
340 if (!InitializePppDecryptorBuffer(instance
,
348 // PluginResourceTracker in the plugin process assumes that resources that it
349 // tracks have been addrefed on behalf of the plugin at the renderer side. So
350 // we explicitly do it for |extra_data_buffer| here.
351 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer
);
354 new PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder(
355 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
357 serialized_decoder_config
,
361 void InitializeVideoDecoder(
362 PP_Instance instance
,
363 const PP_VideoDecoderConfig
* decoder_config
,
364 PP_Resource extra_data_buffer
) {
365 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
371 std::string serialized_decoder_config
;
372 if (!SerializeBlockInfo(*decoder_config
, &serialized_decoder_config
)) {
377 PPPDecryptor_Buffer buffer
;
378 if (!InitializePppDecryptorBuffer(instance
,
386 // PluginResourceTracker in the plugin process assumes that resources that it
387 // tracks have been addrefed on behalf of the plugin at the renderer side. So
388 // we explicitly do it for |extra_data_buffer| here.
389 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer
);
392 new PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder(
393 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
395 serialized_decoder_config
,
400 void DeinitializeDecoder(PP_Instance instance
,
401 PP_DecryptorStreamType decoder_type
,
402 uint32_t request_id
) {
403 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
410 new PpapiMsg_PPPContentDecryptor_DeinitializeDecoder(
411 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
417 void ResetDecoder(PP_Instance instance
,
418 PP_DecryptorStreamType decoder_type
,
419 uint32_t request_id
) {
420 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
427 new PpapiMsg_PPPContentDecryptor_ResetDecoder(
428 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
434 void DecryptAndDecode(PP_Instance instance
,
435 PP_DecryptorStreamType decoder_type
,
436 PP_Resource encrypted_buffer
,
437 const PP_EncryptedBlockInfo
* encrypted_block_info
) {
438 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
444 PPPDecryptor_Buffer buffer
;
445 if (!InitializePppDecryptorBuffer(instance
,
453 std::string serialized_block_info
;
454 if (!SerializeBlockInfo(*encrypted_block_info
, &serialized_block_info
)) {
459 // PluginResourceTracker in the plugin process assumes that resources that it
460 // tracks have been addrefed on behalf of the plugin at the renderer side. So
461 // we explicitly do it for |encrypted_buffer| here.
462 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_buffer
);
465 new PpapiMsg_PPPContentDecryptor_DecryptAndDecode(
466 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
470 serialized_block_info
));
473 static const PPP_ContentDecryptor_Private content_decryptor_interface
= {
475 &SetServerCertificate
,
483 &InitializeAudioDecoder
,
484 &InitializeVideoDecoder
,
485 &DeinitializeDecoder
,
491 PPP_ContentDecryptor_Private_Proxy::PPP_ContentDecryptor_Private_Proxy(
492 Dispatcher
* dispatcher
)
493 : InterfaceProxy(dispatcher
),
494 ppp_decryptor_impl_(NULL
) {
495 if (dispatcher
->IsPlugin()) {
496 ppp_decryptor_impl_
= static_cast<const PPP_ContentDecryptor_Private
*>(
497 dispatcher
->local_get_interface()(
498 PPP_CONTENTDECRYPTOR_PRIVATE_INTERFACE
));
502 PPP_ContentDecryptor_Private_Proxy::~PPP_ContentDecryptor_Private_Proxy() {
506 const PPP_ContentDecryptor_Private
*
507 PPP_ContentDecryptor_Private_Proxy::GetProxyInterface() {
508 return &content_decryptor_interface
;
511 bool PPP_ContentDecryptor_Private_Proxy::OnMessageReceived(
512 const IPC::Message
& msg
) {
513 if (!dispatcher()->IsPlugin())
514 return false; // These are only valid from host->plugin.
515 // Don't allow the plugin to send these to the host.
518 IPC_BEGIN_MESSAGE_MAP(PPP_ContentDecryptor_Private_Proxy
, msg
)
519 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_Initialize
,
521 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_SetServerCertificate
,
522 OnMsgSetServerCertificate
)
523 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_CreateSession
,
525 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_LoadSession
,
527 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_UpdateSession
,
529 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_CloseSession
,
531 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_RemoveSession
,
533 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_GetUsableKeyIds
,
534 OnMsgGetUsableKeyIds
)
535 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_Decrypt
,
537 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder
,
538 OnMsgInitializeAudioDecoder
)
539 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder
,
540 OnMsgInitializeVideoDecoder
)
541 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DeinitializeDecoder
,
542 OnMsgDeinitializeDecoder
)
543 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_ResetDecoder
,
545 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DecryptAndDecode
,
546 OnMsgDecryptAndDecode
)
547 IPC_MESSAGE_UNHANDLED(handled
= false)
548 IPC_END_MESSAGE_MAP()
553 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitialize(
554 PP_Instance instance
,
555 SerializedVarReceiveInput key_system
) {
556 if (ppp_decryptor_impl_
) {
558 ppp_decryptor_impl_
->Initialize
,
560 ExtractReceivedVarAndAddRef(dispatcher(), &key_system
));
564 void PPP_ContentDecryptor_Private_Proxy::OnMsgSetServerCertificate(
565 PP_Instance instance
,
567 std::vector
<uint8_t> server_certificate
) {
568 if (server_certificate
.size() < media::limits::kMinCertificateLength
||
569 server_certificate
.size() > media::limits::kMaxCertificateLength
) {
574 if (ppp_decryptor_impl_
) {
575 ScopedPPVar
server_certificate_var(
576 ScopedPPVar::PassRef(),
579 ->MakeArrayBufferPPVar(server_certificate
.size(),
580 &server_certificate
[0]));
581 CallWhileUnlocked(ppp_decryptor_impl_
->SetServerCertificate
,
584 server_certificate_var
.get());
588 void PPP_ContentDecryptor_Private_Proxy::OnMsgCreateSession(
589 PP_Instance instance
,
591 SerializedVarReceiveInput init_data_type
,
592 SerializedVarReceiveInput init_data
,
593 PP_SessionType session_type
) {
594 if (ppp_decryptor_impl_
) {
596 ppp_decryptor_impl_
->CreateSession
,
599 ExtractReceivedVarAndAddRef(dispatcher(), &init_data_type
),
600 ExtractReceivedVarAndAddRef(dispatcher(), &init_data
),
605 void PPP_ContentDecryptor_Private_Proxy::OnMsgLoadSession(
606 PP_Instance instance
,
608 SerializedVarReceiveInput web_session_id
) {
609 if (ppp_decryptor_impl_
) {
611 ppp_decryptor_impl_
->LoadSession
,
614 ExtractReceivedVarAndAddRef(dispatcher(), &web_session_id
));
618 void PPP_ContentDecryptor_Private_Proxy::OnMsgUpdateSession(
619 PP_Instance instance
,
621 SerializedVarReceiveInput web_session_id
,
622 SerializedVarReceiveInput response
) {
623 if (ppp_decryptor_impl_
) {
625 ppp_decryptor_impl_
->UpdateSession
,
628 ExtractReceivedVarAndAddRef(dispatcher(), &web_session_id
),
629 ExtractReceivedVarAndAddRef(dispatcher(), &response
));
633 void PPP_ContentDecryptor_Private_Proxy::OnMsgCloseSession(
634 PP_Instance instance
,
636 const std::string
& web_session_id
) {
637 if (ppp_decryptor_impl_
) {
638 ScopedPPVar
web_session_id_var(ScopedPPVar::PassRef(),
639 StringVar::StringToPPVar(web_session_id
));
640 CallWhileUnlocked(ppp_decryptor_impl_
->CloseSession
,
643 web_session_id_var
.get());
647 void PPP_ContentDecryptor_Private_Proxy::OnMsgRemoveSession(
648 PP_Instance instance
,
650 const std::string
& web_session_id
) {
651 if (ppp_decryptor_impl_
) {
652 ScopedPPVar
web_session_id_var(ScopedPPVar::PassRef(),
653 StringVar::StringToPPVar(web_session_id
));
654 CallWhileUnlocked(ppp_decryptor_impl_
->RemoveSession
,
657 web_session_id_var
.get());
661 void PPP_ContentDecryptor_Private_Proxy::OnMsgGetUsableKeyIds(
662 PP_Instance instance
,
664 const std::string
& web_session_id
) {
665 if (ppp_decryptor_impl_
) {
666 ScopedPPVar
web_session_id_var(ScopedPPVar::PassRef(),
667 StringVar::StringToPPVar(web_session_id
));
668 CallWhileUnlocked(ppp_decryptor_impl_
->GetUsableKeyIds
,
671 web_session_id_var
.get());
675 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecrypt(
676 PP_Instance instance
,
677 const PPPDecryptor_Buffer
& encrypted_buffer
,
678 const std::string
& serialized_block_info
) {
679 ScopedPPResource
plugin_resource(
680 ScopedPPResource::PassRef(),
681 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer
.resource
,
682 encrypted_buffer
.handle
,
683 encrypted_buffer
.size
));
684 if (ppp_decryptor_impl_
) {
685 PP_EncryptedBlockInfo block_info
;
686 if (!DeserializeBlockInfo(serialized_block_info
, &block_info
))
688 CallWhileUnlocked(ppp_decryptor_impl_
->Decrypt
,
690 plugin_resource
.get(),
695 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeAudioDecoder(
696 PP_Instance instance
,
697 const std::string
& serialized_decoder_config
,
698 const PPPDecryptor_Buffer
& extra_data_buffer
) {
699 ScopedPPResource plugin_resource
;
700 if (extra_data_buffer
.size
> 0) {
701 plugin_resource
= ScopedPPResource(
702 ScopedPPResource::PassRef(),
703 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer
.resource
,
704 extra_data_buffer
.handle
,
705 extra_data_buffer
.size
));
708 PP_AudioDecoderConfig decoder_config
;
709 if (!DeserializeBlockInfo(serialized_decoder_config
, &decoder_config
))
712 if (ppp_decryptor_impl_
) {
714 ppp_decryptor_impl_
->InitializeAudioDecoder
,
717 plugin_resource
.get());
721 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeVideoDecoder(
722 PP_Instance instance
,
723 const std::string
& serialized_decoder_config
,
724 const PPPDecryptor_Buffer
& extra_data_buffer
) {
725 ScopedPPResource plugin_resource
;
726 if (extra_data_buffer
.resource
.host_resource() != 0) {
727 plugin_resource
= ScopedPPResource(
728 ScopedPPResource::PassRef(),
729 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer
.resource
,
730 extra_data_buffer
.handle
,
731 extra_data_buffer
.size
));
734 PP_VideoDecoderConfig decoder_config
;
735 if (!DeserializeBlockInfo(serialized_decoder_config
, &decoder_config
))
738 if (ppp_decryptor_impl_
) {
740 ppp_decryptor_impl_
->InitializeVideoDecoder
,
743 plugin_resource
.get());
747 void PPP_ContentDecryptor_Private_Proxy::OnMsgDeinitializeDecoder(
748 PP_Instance instance
,
749 PP_DecryptorStreamType decoder_type
,
750 uint32_t request_id
) {
751 if (ppp_decryptor_impl_
) {
753 ppp_decryptor_impl_
->DeinitializeDecoder
,
760 void PPP_ContentDecryptor_Private_Proxy::OnMsgResetDecoder(
761 PP_Instance instance
,
762 PP_DecryptorStreamType decoder_type
,
763 uint32_t request_id
) {
764 if (ppp_decryptor_impl_
) {
766 ppp_decryptor_impl_
->ResetDecoder
,
773 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecryptAndDecode(
774 PP_Instance instance
,
775 PP_DecryptorStreamType decoder_type
,
776 const PPPDecryptor_Buffer
& encrypted_buffer
,
777 const std::string
& serialized_block_info
) {
778 ScopedPPResource plugin_resource
;
779 if (encrypted_buffer
.resource
.host_resource() != 0) {
780 plugin_resource
= ScopedPPResource(
781 ScopedPPResource::PassRef(),
782 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer
.resource
,
783 encrypted_buffer
.handle
,
784 encrypted_buffer
.size
));
787 if (ppp_decryptor_impl_
) {
788 PP_EncryptedBlockInfo block_info
;
789 if (!DeserializeBlockInfo(serialized_block_info
, &block_info
))
792 ppp_decryptor_impl_
->DecryptAndDecode
,
795 plugin_resource
.get(),