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);
52 base::SharedMemory
* shm
;
53 int32_t result
= enter
.object()->GetSharedMemory(&shm
);
58 dispatcher
->ShareSharedMemoryHandleWithRemote(shm
->handle());
62 // SerializedVarReceiveInput will decrement the reference count, but we want
63 // to give the recipient a reference. This utility function takes care of that
64 // work for the message handlers defined below.
65 PP_Var
ExtractReceivedVarAndAddRef(Dispatcher
* dispatcher
,
66 SerializedVarReceiveInput
* serialized_var
) {
67 PP_Var var
= serialized_var
->Get(dispatcher
);
68 PpapiGlobals::Get()->GetVarTracker()->AddRefVar(var
);
72 bool InitializePppDecryptorBuffer(PP_Instance instance
,
73 HostDispatcher
* dispatcher
,
75 PPPDecryptor_Buffer
* buffer
) {
82 buffer
->resource
= HostResource();
83 buffer
->handle
= base::SharedMemoryHandle();
88 HostResource host_resource
;
89 host_resource
.SetHostResource(instance
, resource
);
92 if (DescribeHostBufferResource(resource
, &size
) == PP_FALSE
)
95 base::SharedMemoryHandle handle
;
96 if (ShareHostBufferResourceToPlugin(dispatcher
,
101 buffer
->resource
= host_resource
;
102 buffer
->handle
= handle
;
107 void Initialize(PP_Instance instance
,
110 PP_Bool allow_distinctive_identifier
,
111 PP_Bool allow_persistent_state
) {
112 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
118 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_Initialize(
119 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
, instance
, promise_id
,
120 SerializedVarSendInput(dispatcher
, key_system
),
121 allow_distinctive_identifier
, allow_persistent_state
));
124 void SetServerCertificate(PP_Instance instance
,
126 PP_Var server_certificate
) {
127 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
133 ArrayBufferVar
* server_certificate_buffer
=
134 ArrayBufferVar::FromPPVar(server_certificate
);
135 if (!server_certificate_buffer
||
136 server_certificate_buffer
->ByteLength() <
137 media::limits::kMinCertificateLength
||
138 server_certificate_buffer
->ByteLength() >
139 media::limits::kMaxCertificateLength
) {
144 const uint8_t* server_certificate_ptr
=
145 static_cast<const uint8_t*>(server_certificate_buffer
->Map());
146 const uint32_t server_certificate_size
=
147 server_certificate_buffer
->ByteLength();
148 std::vector
<uint8_t> server_certificate_vector(
149 server_certificate_ptr
, server_certificate_ptr
+ server_certificate_size
);
151 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_SetServerCertificate(
152 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
155 server_certificate_vector
));
158 void CreateSessionAndGenerateRequest(PP_Instance instance
,
160 PP_SessionType session_type
,
161 PP_InitDataType init_data_type
,
163 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
170 new PpapiMsg_PPPContentDecryptor_CreateSessionAndGenerateRequest(
171 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
, instance
, promise_id
,
172 session_type
, init_data_type
,
173 SerializedVarSendInput(dispatcher
, init_data
)));
176 void LoadSession(PP_Instance instance
,
178 PP_SessionType session_type
,
180 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
186 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_LoadSession(
187 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
, instance
, promise_id
, session_type
,
188 SerializedVarSendInput(dispatcher
, session_id
)));
191 void UpdateSession(PP_Instance instance
,
195 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
201 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_UpdateSession(
202 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
, instance
, promise_id
,
203 SerializedVarSendInput(dispatcher
, session_id
),
204 SerializedVarSendInput(dispatcher
, response
)));
207 void CloseSession(PP_Instance instance
,
210 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
216 StringVar
* session_id_string
= StringVar::FromPPVar(session_id
);
217 if (!session_id_string
||
218 session_id_string
->value().length() >
219 media::limits::kMaxSessionIdLength
) {
224 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_CloseSession(
225 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
, instance
, promise_id
,
226 session_id_string
->value()));
229 void RemoveSession(PP_Instance instance
,
232 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
238 StringVar
* session_id_string
= StringVar::FromPPVar(session_id
);
239 if (!session_id_string
||
240 session_id_string
->value().length() >
241 media::limits::kMaxSessionIdLength
) {
246 dispatcher
->Send(new PpapiMsg_PPPContentDecryptor_RemoveSession(
247 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
, instance
, promise_id
,
248 session_id_string
->value()));
251 void Decrypt(PP_Instance instance
,
252 PP_Resource encrypted_block
,
253 const PP_EncryptedBlockInfo
* encrypted_block_info
) {
254 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
260 PPPDecryptor_Buffer buffer
;
261 if (!InitializePppDecryptorBuffer(instance
,
269 std::string serialized_block_info
;
270 if (!SerializeBlockInfo(*encrypted_block_info
, &serialized_block_info
)) {
275 // PluginResourceTracker in the plugin process assumes that resources that it
276 // tracks have been addrefed on behalf of the plugin at the renderer side. So
277 // we explicitly do it for |encryped_block| here.
278 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_block
);
281 new PpapiMsg_PPPContentDecryptor_Decrypt(
282 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
285 serialized_block_info
));
288 void InitializeAudioDecoder(
289 PP_Instance instance
,
290 const PP_AudioDecoderConfig
* decoder_config
,
291 PP_Resource extra_data_buffer
) {
292 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
298 std::string serialized_decoder_config
;
299 if (!SerializeBlockInfo(*decoder_config
, &serialized_decoder_config
)) {
304 PPPDecryptor_Buffer buffer
;
305 if (!InitializePppDecryptorBuffer(instance
,
313 // PluginResourceTracker in the plugin process assumes that resources that it
314 // tracks have been addrefed on behalf of the plugin at the renderer side. So
315 // we explicitly do it for |extra_data_buffer| here.
316 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer
);
319 new PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder(
320 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
322 serialized_decoder_config
,
326 void InitializeVideoDecoder(
327 PP_Instance instance
,
328 const PP_VideoDecoderConfig
* decoder_config
,
329 PP_Resource extra_data_buffer
) {
330 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
336 std::string serialized_decoder_config
;
337 if (!SerializeBlockInfo(*decoder_config
, &serialized_decoder_config
)) {
342 PPPDecryptor_Buffer buffer
;
343 if (!InitializePppDecryptorBuffer(instance
,
351 // PluginResourceTracker in the plugin process assumes that resources that it
352 // tracks have been addrefed on behalf of the plugin at the renderer side. So
353 // we explicitly do it for |extra_data_buffer| here.
354 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer
);
357 new PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder(
358 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
360 serialized_decoder_config
,
365 void DeinitializeDecoder(PP_Instance instance
,
366 PP_DecryptorStreamType decoder_type
,
367 uint32_t request_id
) {
368 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
375 new PpapiMsg_PPPContentDecryptor_DeinitializeDecoder(
376 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
382 void ResetDecoder(PP_Instance instance
,
383 PP_DecryptorStreamType decoder_type
,
384 uint32_t request_id
) {
385 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
392 new PpapiMsg_PPPContentDecryptor_ResetDecoder(
393 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
399 void DecryptAndDecode(PP_Instance instance
,
400 PP_DecryptorStreamType decoder_type
,
401 PP_Resource encrypted_buffer
,
402 const PP_EncryptedBlockInfo
* encrypted_block_info
) {
403 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
409 PPPDecryptor_Buffer buffer
;
410 if (!InitializePppDecryptorBuffer(instance
,
418 std::string serialized_block_info
;
419 if (!SerializeBlockInfo(*encrypted_block_info
, &serialized_block_info
)) {
424 // PluginResourceTracker in the plugin process assumes that resources that it
425 // tracks have been addrefed on behalf of the plugin at the renderer side. So
426 // we explicitly do it for |encrypted_buffer| here.
427 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_buffer
);
430 new PpapiMsg_PPPContentDecryptor_DecryptAndDecode(
431 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE
,
435 serialized_block_info
));
438 static const PPP_ContentDecryptor_Private content_decryptor_interface
= {
440 &SetServerCertificate
,
441 &CreateSessionAndGenerateRequest
,
447 &InitializeAudioDecoder
,
448 &InitializeVideoDecoder
,
449 &DeinitializeDecoder
,
455 PPP_ContentDecryptor_Private_Proxy::PPP_ContentDecryptor_Private_Proxy(
456 Dispatcher
* dispatcher
)
457 : InterfaceProxy(dispatcher
),
458 ppp_decryptor_impl_(NULL
) {
459 if (dispatcher
->IsPlugin()) {
460 ppp_decryptor_impl_
= static_cast<const PPP_ContentDecryptor_Private
*>(
461 dispatcher
->local_get_interface()(
462 PPP_CONTENTDECRYPTOR_PRIVATE_INTERFACE
));
466 PPP_ContentDecryptor_Private_Proxy::~PPP_ContentDecryptor_Private_Proxy() {
470 const PPP_ContentDecryptor_Private
*
471 PPP_ContentDecryptor_Private_Proxy::GetProxyInterface() {
472 return &content_decryptor_interface
;
475 bool PPP_ContentDecryptor_Private_Proxy::OnMessageReceived(
476 const IPC::Message
& msg
) {
477 if (!dispatcher()->IsPlugin())
478 return false; // These are only valid from host->plugin.
479 // Don't allow the plugin to send these to the host.
482 IPC_BEGIN_MESSAGE_MAP(PPP_ContentDecryptor_Private_Proxy
, msg
)
483 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_Initialize
,
485 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_SetServerCertificate
,
486 OnMsgSetServerCertificate
)
488 PpapiMsg_PPPContentDecryptor_CreateSessionAndGenerateRequest
,
489 OnMsgCreateSessionAndGenerateRequest
)
490 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_LoadSession
,
492 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_UpdateSession
,
494 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_CloseSession
,
496 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_RemoveSession
,
498 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_Decrypt
,
500 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder
,
501 OnMsgInitializeAudioDecoder
)
502 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder
,
503 OnMsgInitializeVideoDecoder
)
504 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DeinitializeDecoder
,
505 OnMsgDeinitializeDecoder
)
506 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_ResetDecoder
,
508 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DecryptAndDecode
,
509 OnMsgDecryptAndDecode
)
510 IPC_MESSAGE_UNHANDLED(handled
= false)
511 IPC_END_MESSAGE_MAP()
516 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitialize(
517 PP_Instance instance
,
519 SerializedVarReceiveInput key_system
,
520 PP_Bool allow_distinctive_identifier
,
521 PP_Bool allow_persistent_state
) {
522 if (ppp_decryptor_impl_
) {
523 CallWhileUnlocked(ppp_decryptor_impl_
->Initialize
, instance
, promise_id
,
524 ExtractReceivedVarAndAddRef(dispatcher(), &key_system
),
525 allow_distinctive_identifier
, allow_persistent_state
);
529 void PPP_ContentDecryptor_Private_Proxy::OnMsgSetServerCertificate(
530 PP_Instance instance
,
532 std::vector
<uint8_t> server_certificate
) {
533 if (server_certificate
.size() < media::limits::kMinCertificateLength
||
534 server_certificate
.size() > media::limits::kMaxCertificateLength
) {
539 if (ppp_decryptor_impl_
) {
540 ScopedPPVar
server_certificate_var(
541 ScopedPPVar::PassRef(),
544 ->MakeArrayBufferPPVar(
545 static_cast<uint32_t>(server_certificate
.size()),
546 &server_certificate
[0]));
547 CallWhileUnlocked(ppp_decryptor_impl_
->SetServerCertificate
,
550 server_certificate_var
.get());
554 void PPP_ContentDecryptor_Private_Proxy::OnMsgCreateSessionAndGenerateRequest(
555 PP_Instance instance
,
557 PP_SessionType session_type
,
558 PP_InitDataType init_data_type
,
559 SerializedVarReceiveInput init_data
) {
560 if (ppp_decryptor_impl_
) {
561 CallWhileUnlocked(ppp_decryptor_impl_
->CreateSessionAndGenerateRequest
,
562 instance
, promise_id
, session_type
, init_data_type
,
563 ExtractReceivedVarAndAddRef(dispatcher(), &init_data
));
567 void PPP_ContentDecryptor_Private_Proxy::OnMsgLoadSession(
568 PP_Instance instance
,
570 PP_SessionType session_type
,
571 SerializedVarReceiveInput session_id
) {
572 if (ppp_decryptor_impl_
) {
573 CallWhileUnlocked(ppp_decryptor_impl_
->LoadSession
, instance
, promise_id
,
575 ExtractReceivedVarAndAddRef(dispatcher(), &session_id
));
579 void PPP_ContentDecryptor_Private_Proxy::OnMsgUpdateSession(
580 PP_Instance instance
,
582 SerializedVarReceiveInput session_id
,
583 SerializedVarReceiveInput response
) {
584 if (ppp_decryptor_impl_
) {
585 CallWhileUnlocked(ppp_decryptor_impl_
->UpdateSession
, instance
, promise_id
,
586 ExtractReceivedVarAndAddRef(dispatcher(), &session_id
),
587 ExtractReceivedVarAndAddRef(dispatcher(), &response
));
591 void PPP_ContentDecryptor_Private_Proxy::OnMsgCloseSession(
592 PP_Instance instance
,
594 const std::string
& session_id
) {
595 if (ppp_decryptor_impl_
) {
596 ScopedPPVar
session_id_var(ScopedPPVar::PassRef(),
597 StringVar::StringToPPVar(session_id
));
598 CallWhileUnlocked(ppp_decryptor_impl_
->CloseSession
, instance
, promise_id
,
599 session_id_var
.get());
603 void PPP_ContentDecryptor_Private_Proxy::OnMsgRemoveSession(
604 PP_Instance instance
,
606 const std::string
& session_id
) {
607 if (ppp_decryptor_impl_
) {
608 ScopedPPVar
session_id_var(ScopedPPVar::PassRef(),
609 StringVar::StringToPPVar(session_id
));
610 CallWhileUnlocked(ppp_decryptor_impl_
->RemoveSession
, instance
, promise_id
,
611 session_id_var
.get());
615 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecrypt(
616 PP_Instance instance
,
617 const PPPDecryptor_Buffer
& encrypted_buffer
,
618 const std::string
& serialized_block_info
) {
619 ScopedPPResource
plugin_resource(
620 ScopedPPResource::PassRef(),
621 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer
.resource
,
622 encrypted_buffer
.handle
,
623 encrypted_buffer
.size
));
624 if (ppp_decryptor_impl_
) {
625 PP_EncryptedBlockInfo block_info
;
626 if (!DeserializeBlockInfo(serialized_block_info
, &block_info
))
628 CallWhileUnlocked(ppp_decryptor_impl_
->Decrypt
,
630 plugin_resource
.get(),
635 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeAudioDecoder(
636 PP_Instance instance
,
637 const std::string
& serialized_decoder_config
,
638 const PPPDecryptor_Buffer
& extra_data_buffer
) {
639 ScopedPPResource plugin_resource
;
640 if (extra_data_buffer
.size
> 0) {
641 plugin_resource
= ScopedPPResource(
642 ScopedPPResource::PassRef(),
643 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer
.resource
,
644 extra_data_buffer
.handle
,
645 extra_data_buffer
.size
));
648 PP_AudioDecoderConfig decoder_config
;
649 if (!DeserializeBlockInfo(serialized_decoder_config
, &decoder_config
))
652 if (ppp_decryptor_impl_
) {
654 ppp_decryptor_impl_
->InitializeAudioDecoder
,
657 plugin_resource
.get());
661 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeVideoDecoder(
662 PP_Instance instance
,
663 const std::string
& serialized_decoder_config
,
664 const PPPDecryptor_Buffer
& extra_data_buffer
) {
665 ScopedPPResource plugin_resource
;
666 if (extra_data_buffer
.resource
.host_resource() != 0) {
667 plugin_resource
= ScopedPPResource(
668 ScopedPPResource::PassRef(),
669 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer
.resource
,
670 extra_data_buffer
.handle
,
671 extra_data_buffer
.size
));
674 PP_VideoDecoderConfig decoder_config
;
675 if (!DeserializeBlockInfo(serialized_decoder_config
, &decoder_config
))
678 if (ppp_decryptor_impl_
) {
680 ppp_decryptor_impl_
->InitializeVideoDecoder
,
683 plugin_resource
.get());
687 void PPP_ContentDecryptor_Private_Proxy::OnMsgDeinitializeDecoder(
688 PP_Instance instance
,
689 PP_DecryptorStreamType decoder_type
,
690 uint32_t request_id
) {
691 if (ppp_decryptor_impl_
) {
693 ppp_decryptor_impl_
->DeinitializeDecoder
,
700 void PPP_ContentDecryptor_Private_Proxy::OnMsgResetDecoder(
701 PP_Instance instance
,
702 PP_DecryptorStreamType decoder_type
,
703 uint32_t request_id
) {
704 if (ppp_decryptor_impl_
) {
706 ppp_decryptor_impl_
->ResetDecoder
,
713 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecryptAndDecode(
714 PP_Instance instance
,
715 PP_DecryptorStreamType decoder_type
,
716 const PPPDecryptor_Buffer
& encrypted_buffer
,
717 const std::string
& serialized_block_info
) {
718 ScopedPPResource plugin_resource
;
719 if (encrypted_buffer
.resource
.host_resource() != 0) {
720 plugin_resource
= ScopedPPResource(
721 ScopedPPResource::PassRef(),
722 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer
.resource
,
723 encrypted_buffer
.handle
,
724 encrypted_buffer
.size
));
727 if (ppp_decryptor_impl_
) {
728 PP_EncryptedBlockInfo block_info
;
729 if (!DeserializeBlockInfo(serialized_block_info
, &block_info
))
732 ppp_decryptor_impl_
->DecryptAndDecode
,
735 plugin_resource
.get(),