Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ppapi / proxy / ppp_content_decryptor_private_proxy.cc
blobeee3871b5098d01643d8c19999aeb6d6db9ee52f
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 "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;
28 namespace ppapi {
29 namespace proxy {
31 namespace {
33 PP_Bool DescribeHostBufferResource(PP_Resource resource, uint32_t* size) {
34 EnterResourceNoLock<PPB_Buffer_API> enter(resource, true);
35 if (enter.failed())
36 return PP_FALSE;
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,
43 PP_Resource resource,
44 base::SharedMemoryHandle* shared_mem_handle) {
45 if (!dispatcher || resource == 0 || !shared_mem_handle)
46 return PP_FALSE;
47 EnterResourceNoLock<PPB_Buffer_API> enter(resource, true);
48 if (enter.failed())
49 return PP_FALSE;
50 int handle;
51 int32_t result = enter.object()->GetSharedMemory(&handle);
52 if (result != PP_OK)
53 return PP_FALSE;
54 base::PlatformFile platform_file =
55 #if defined(OS_WIN)
56 reinterpret_cast<HANDLE>(static_cast<intptr_t>(handle));
57 #elif defined(OS_POSIX)
58 handle;
59 #else
60 #error Not implemented.
61 #endif
63 *shared_mem_handle = dispatcher->ShareHandleWithRemote(platform_file, false);
64 return PP_TRUE;
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);
74 return var;
77 bool InitializePppDecryptorBuffer(PP_Instance instance,
78 HostDispatcher* dispatcher,
79 PP_Resource resource,
80 PPPDecryptor_Buffer* buffer) {
81 if (!buffer) {
82 NOTREACHED();
83 return false;
86 if (resource == 0) {
87 buffer->resource = HostResource();
88 buffer->handle = base::SharedMemoryHandle();
89 buffer->size = 0;
90 return true;
93 HostResource host_resource;
94 host_resource.SetHostResource(instance, resource);
96 uint32_t size = 0;
97 if (DescribeHostBufferResource(resource, &size) == PP_FALSE)
98 return false;
100 base::SharedMemoryHandle handle;
101 if (ShareHostBufferResourceToPlugin(dispatcher,
102 resource,
103 &handle) == PP_FALSE)
104 return false;
106 buffer->resource = host_resource;
107 buffer->handle = handle;
108 buffer->size = size;
109 return true;
112 void Initialize(PP_Instance instance,
113 PP_Var key_system) {
114 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
115 if (!dispatcher) {
116 NOTREACHED();
117 return;
120 dispatcher->Send(
121 new PpapiMsg_PPPContentDecryptor_Initialize(
122 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
123 instance,
124 SerializedVarSendInput(dispatcher, key_system)));
127 void CreateSession(PP_Instance instance,
128 uint32_t promise_id,
129 PP_Var init_data_type,
130 PP_Var init_data,
131 PP_SessionType session_type) {
132 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
133 if (!dispatcher) {
134 NOTREACHED();
135 return;
138 dispatcher->Send(new PpapiMsg_PPPContentDecryptor_CreateSession(
139 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
140 instance,
141 promise_id,
142 SerializedVarSendInput(dispatcher, init_data_type),
143 SerializedVarSendInput(dispatcher, init_data),
144 session_type));
147 void LoadSession(PP_Instance instance,
148 uint32_t promise_id,
149 PP_Var web_session_id) {
150 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
151 if (!dispatcher) {
152 NOTREACHED();
153 return;
156 dispatcher->Send(new PpapiMsg_PPPContentDecryptor_LoadSession(
157 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
158 instance,
159 promise_id,
160 SerializedVarSendInput(dispatcher, web_session_id)));
163 void UpdateSession(PP_Instance instance,
164 uint32_t promise_id,
165 PP_Var web_session_id,
166 PP_Var response) {
167 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
168 if (!dispatcher) {
169 NOTREACHED();
170 return;
173 dispatcher->Send(new PpapiMsg_PPPContentDecryptor_UpdateSession(
174 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
175 instance,
176 promise_id,
177 SerializedVarSendInput(dispatcher, web_session_id),
178 SerializedVarSendInput(dispatcher, response)));
181 void ReleaseSession(PP_Instance instance,
182 uint32_t promise_id,
183 PP_Var web_session_id) {
184 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
185 if (!dispatcher) {
186 NOTREACHED();
187 return;
190 dispatcher->Send(new PpapiMsg_PPPContentDecryptor_ReleaseSession(
191 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
192 instance,
193 promise_id,
194 SerializedVarSendInput(dispatcher, web_session_id)));
197 void Decrypt(PP_Instance instance,
198 PP_Resource encrypted_block,
199 const PP_EncryptedBlockInfo* encrypted_block_info) {
200 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
201 if (!dispatcher) {
202 NOTREACHED();
203 return;
206 PPPDecryptor_Buffer buffer;
207 if (!InitializePppDecryptorBuffer(instance,
208 dispatcher,
209 encrypted_block,
210 &buffer)) {
211 NOTREACHED();
212 return;
215 std::string serialized_block_info;
216 if (!SerializeBlockInfo(*encrypted_block_info, &serialized_block_info)) {
217 NOTREACHED();
218 return;
221 // PluginResourceTracker in the plugin process assumes that resources that it
222 // tracks have been addrefed on behalf of the plugin at the renderer side. So
223 // we explicitly do it for |encryped_block| here.
224 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_block);
226 dispatcher->Send(
227 new PpapiMsg_PPPContentDecryptor_Decrypt(
228 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
229 instance,
230 buffer,
231 serialized_block_info));
234 void InitializeAudioDecoder(
235 PP_Instance instance,
236 const PP_AudioDecoderConfig* decoder_config,
237 PP_Resource extra_data_buffer) {
238 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
239 if (!dispatcher) {
240 NOTREACHED();
241 return;
244 std::string serialized_decoder_config;
245 if (!SerializeBlockInfo(*decoder_config, &serialized_decoder_config)) {
246 NOTREACHED();
247 return;
250 PPPDecryptor_Buffer buffer;
251 if (!InitializePppDecryptorBuffer(instance,
252 dispatcher,
253 extra_data_buffer,
254 &buffer)) {
255 NOTREACHED();
256 return;
259 // PluginResourceTracker in the plugin process assumes that resources that it
260 // tracks have been addrefed on behalf of the plugin at the renderer side. So
261 // we explicitly do it for |extra_data_buffer| here.
262 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer);
264 dispatcher->Send(
265 new PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder(
266 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
267 instance,
268 serialized_decoder_config,
269 buffer));
272 void InitializeVideoDecoder(
273 PP_Instance instance,
274 const PP_VideoDecoderConfig* decoder_config,
275 PP_Resource extra_data_buffer) {
276 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
277 if (!dispatcher) {
278 NOTREACHED();
279 return;
282 std::string serialized_decoder_config;
283 if (!SerializeBlockInfo(*decoder_config, &serialized_decoder_config)) {
284 NOTREACHED();
285 return;
288 PPPDecryptor_Buffer buffer;
289 if (!InitializePppDecryptorBuffer(instance,
290 dispatcher,
291 extra_data_buffer,
292 &buffer)) {
293 NOTREACHED();
294 return;
297 // PluginResourceTracker in the plugin process assumes that resources that it
298 // tracks have been addrefed on behalf of the plugin at the renderer side. So
299 // we explicitly do it for |extra_data_buffer| here.
300 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer);
302 dispatcher->Send(
303 new PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder(
304 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
305 instance,
306 serialized_decoder_config,
307 buffer));
311 void DeinitializeDecoder(PP_Instance instance,
312 PP_DecryptorStreamType decoder_type,
313 uint32_t request_id) {
314 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
315 if (!dispatcher) {
316 NOTREACHED();
317 return;
320 dispatcher->Send(
321 new PpapiMsg_PPPContentDecryptor_DeinitializeDecoder(
322 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
323 instance,
324 decoder_type,
325 request_id));
328 void ResetDecoder(PP_Instance instance,
329 PP_DecryptorStreamType decoder_type,
330 uint32_t request_id) {
331 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
332 if (!dispatcher) {
333 NOTREACHED();
334 return;
337 dispatcher->Send(
338 new PpapiMsg_PPPContentDecryptor_ResetDecoder(
339 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
340 instance,
341 decoder_type,
342 request_id));
345 void DecryptAndDecode(PP_Instance instance,
346 PP_DecryptorStreamType decoder_type,
347 PP_Resource encrypted_buffer,
348 const PP_EncryptedBlockInfo* encrypted_block_info) {
349 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
350 if (!dispatcher) {
351 NOTREACHED();
352 return;
355 PPPDecryptor_Buffer buffer;
356 if (!InitializePppDecryptorBuffer(instance,
357 dispatcher,
358 encrypted_buffer,
359 &buffer)) {
360 NOTREACHED();
361 return;
364 std::string serialized_block_info;
365 if (!SerializeBlockInfo(*encrypted_block_info, &serialized_block_info)) {
366 NOTREACHED();
367 return;
370 // PluginResourceTracker in the plugin process assumes that resources that it
371 // tracks have been addrefed on behalf of the plugin at the renderer side. So
372 // we explicitly do it for |encrypted_buffer| here.
373 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_buffer);
375 dispatcher->Send(
376 new PpapiMsg_PPPContentDecryptor_DecryptAndDecode(
377 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
378 instance,
379 decoder_type,
380 buffer,
381 serialized_block_info));
384 static const PPP_ContentDecryptor_Private content_decryptor_interface = {
385 &Initialize,
386 &CreateSession,
387 &LoadSession,
388 &UpdateSession,
389 &ReleaseSession,
390 &Decrypt,
391 &InitializeAudioDecoder,
392 &InitializeVideoDecoder,
393 &DeinitializeDecoder,
394 &ResetDecoder,
395 &DecryptAndDecode
398 } // namespace
400 PPP_ContentDecryptor_Private_Proxy::PPP_ContentDecryptor_Private_Proxy(
401 Dispatcher* dispatcher)
402 : InterfaceProxy(dispatcher),
403 ppp_decryptor_impl_(NULL) {
404 if (dispatcher->IsPlugin()) {
405 ppp_decryptor_impl_ = static_cast<const PPP_ContentDecryptor_Private*>(
406 dispatcher->local_get_interface()(
407 PPP_CONTENTDECRYPTOR_PRIVATE_INTERFACE));
411 PPP_ContentDecryptor_Private_Proxy::~PPP_ContentDecryptor_Private_Proxy() {
414 // static
415 const PPP_ContentDecryptor_Private*
416 PPP_ContentDecryptor_Private_Proxy::GetProxyInterface() {
417 return &content_decryptor_interface;
420 bool PPP_ContentDecryptor_Private_Proxy::OnMessageReceived(
421 const IPC::Message& msg) {
422 if (!dispatcher()->IsPlugin())
423 return false; // These are only valid from host->plugin.
424 // Don't allow the plugin to send these to the host.
426 bool handled = true;
427 IPC_BEGIN_MESSAGE_MAP(PPP_ContentDecryptor_Private_Proxy, msg)
428 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_Initialize,
429 OnMsgInitialize)
430 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_CreateSession,
431 OnMsgCreateSession)
432 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_LoadSession,
433 OnMsgLoadSession)
434 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_UpdateSession,
435 OnMsgUpdateSession)
436 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_ReleaseSession,
437 OnMsgReleaseSession)
438 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_Decrypt,
439 OnMsgDecrypt)
440 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder,
441 OnMsgInitializeAudioDecoder)
442 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder,
443 OnMsgInitializeVideoDecoder)
444 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DeinitializeDecoder,
445 OnMsgDeinitializeDecoder)
446 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_ResetDecoder,
447 OnMsgResetDecoder)
448 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DecryptAndDecode,
449 OnMsgDecryptAndDecode)
450 IPC_MESSAGE_UNHANDLED(handled = false)
451 IPC_END_MESSAGE_MAP()
452 DCHECK(handled);
453 return handled;
456 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitialize(
457 PP_Instance instance,
458 SerializedVarReceiveInput key_system) {
459 if (ppp_decryptor_impl_) {
460 CallWhileUnlocked(
461 ppp_decryptor_impl_->Initialize,
462 instance,
463 ExtractReceivedVarAndAddRef(dispatcher(), &key_system));
467 void PPP_ContentDecryptor_Private_Proxy::OnMsgCreateSession(
468 PP_Instance instance,
469 uint32_t promise_id,
470 SerializedVarReceiveInput init_data_type,
471 SerializedVarReceiveInput init_data,
472 PP_SessionType session_type) {
473 if (ppp_decryptor_impl_) {
474 CallWhileUnlocked(
475 ppp_decryptor_impl_->CreateSession,
476 instance,
477 promise_id,
478 ExtractReceivedVarAndAddRef(dispatcher(), &init_data_type),
479 ExtractReceivedVarAndAddRef(dispatcher(), &init_data),
480 session_type);
484 void PPP_ContentDecryptor_Private_Proxy::OnMsgLoadSession(
485 PP_Instance instance,
486 uint32_t promise_id,
487 SerializedVarReceiveInput web_session_id) {
488 if (ppp_decryptor_impl_) {
489 CallWhileUnlocked(
490 ppp_decryptor_impl_->LoadSession,
491 instance,
492 promise_id,
493 ExtractReceivedVarAndAddRef(dispatcher(), &web_session_id));
497 void PPP_ContentDecryptor_Private_Proxy::OnMsgUpdateSession(
498 PP_Instance instance,
499 uint32_t promise_id,
500 SerializedVarReceiveInput web_session_id,
501 SerializedVarReceiveInput response) {
502 if (ppp_decryptor_impl_) {
503 CallWhileUnlocked(
504 ppp_decryptor_impl_->UpdateSession,
505 instance,
506 promise_id,
507 ExtractReceivedVarAndAddRef(dispatcher(), &web_session_id),
508 ExtractReceivedVarAndAddRef(dispatcher(), &response));
512 void PPP_ContentDecryptor_Private_Proxy::OnMsgReleaseSession(
513 PP_Instance instance,
514 uint32_t promise_id,
515 SerializedVarReceiveInput web_session_id) {
516 if (ppp_decryptor_impl_) {
517 CallWhileUnlocked(
518 ppp_decryptor_impl_->ReleaseSession,
519 instance,
520 promise_id,
521 ExtractReceivedVarAndAddRef(dispatcher(), &web_session_id));
525 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecrypt(
526 PP_Instance instance,
527 const PPPDecryptor_Buffer& encrypted_buffer,
528 const std::string& serialized_block_info) {
529 ScopedPPResource plugin_resource(
530 ScopedPPResource::PassRef(),
531 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer.resource,
532 encrypted_buffer.handle,
533 encrypted_buffer.size));
534 if (ppp_decryptor_impl_) {
535 PP_EncryptedBlockInfo block_info;
536 if (!DeserializeBlockInfo(serialized_block_info, &block_info))
537 return;
538 CallWhileUnlocked(ppp_decryptor_impl_->Decrypt,
539 instance,
540 plugin_resource.get(),
541 const_cast<const PP_EncryptedBlockInfo*>(&block_info));
545 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeAudioDecoder(
546 PP_Instance instance,
547 const std::string& serialized_decoder_config,
548 const PPPDecryptor_Buffer& extra_data_buffer) {
549 ScopedPPResource plugin_resource;
550 if (extra_data_buffer.size > 0) {
551 plugin_resource = ScopedPPResource(
552 ScopedPPResource::PassRef(),
553 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer.resource,
554 extra_data_buffer.handle,
555 extra_data_buffer.size));
558 PP_AudioDecoderConfig decoder_config;
559 if (!DeserializeBlockInfo(serialized_decoder_config, &decoder_config))
560 return;
562 if (ppp_decryptor_impl_) {
563 CallWhileUnlocked(
564 ppp_decryptor_impl_->InitializeAudioDecoder,
565 instance,
566 const_cast<const PP_AudioDecoderConfig*>(&decoder_config),
567 plugin_resource.get());
571 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeVideoDecoder(
572 PP_Instance instance,
573 const std::string& serialized_decoder_config,
574 const PPPDecryptor_Buffer& extra_data_buffer) {
575 ScopedPPResource plugin_resource;
576 if (extra_data_buffer.resource.host_resource() != 0) {
577 plugin_resource = ScopedPPResource(
578 ScopedPPResource::PassRef(),
579 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer.resource,
580 extra_data_buffer.handle,
581 extra_data_buffer.size));
584 PP_VideoDecoderConfig decoder_config;
585 if (!DeserializeBlockInfo(serialized_decoder_config, &decoder_config))
586 return;
588 if (ppp_decryptor_impl_) {
589 CallWhileUnlocked(
590 ppp_decryptor_impl_->InitializeVideoDecoder,
591 instance,
592 const_cast<const PP_VideoDecoderConfig*>(&decoder_config),
593 plugin_resource.get());
597 void PPP_ContentDecryptor_Private_Proxy::OnMsgDeinitializeDecoder(
598 PP_Instance instance,
599 PP_DecryptorStreamType decoder_type,
600 uint32_t request_id) {
601 if (ppp_decryptor_impl_) {
602 CallWhileUnlocked(
603 ppp_decryptor_impl_->DeinitializeDecoder,
604 instance,
605 decoder_type,
606 request_id);
610 void PPP_ContentDecryptor_Private_Proxy::OnMsgResetDecoder(
611 PP_Instance instance,
612 PP_DecryptorStreamType decoder_type,
613 uint32_t request_id) {
614 if (ppp_decryptor_impl_) {
615 CallWhileUnlocked(
616 ppp_decryptor_impl_->ResetDecoder,
617 instance,
618 decoder_type,
619 request_id);
623 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecryptAndDecode(
624 PP_Instance instance,
625 PP_DecryptorStreamType decoder_type,
626 const PPPDecryptor_Buffer& encrypted_buffer,
627 const std::string& serialized_block_info) {
628 ScopedPPResource plugin_resource;
629 if (encrypted_buffer.resource.host_resource() != 0) {
630 plugin_resource = ScopedPPResource(
631 ScopedPPResource::PassRef(),
632 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer.resource,
633 encrypted_buffer.handle,
634 encrypted_buffer.size));
637 if (ppp_decryptor_impl_) {
638 PP_EncryptedBlockInfo block_info;
639 if (!DeserializeBlockInfo(serialized_block_info, &block_info))
640 return;
641 CallWhileUnlocked(
642 ppp_decryptor_impl_->DecryptAndDecode,
643 instance,
644 decoder_type,
645 plugin_resource.get(),
646 const_cast<const PP_EncryptedBlockInfo*>(&block_info));
650 } // namespace proxy
651 } // namespace ppapi