Roll leveldb from r73 to r75.
[chromium-blink-merge.git] / ppapi / proxy / ppp_content_decryptor_private_proxy.cc
blobf986e7f8d7214dbbb3efbaa9a3751bef30be2ad0
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_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 GenerateKeyRequest(PP_Instance instance,
113 PP_Var key_system,
114 PP_Var type,
115 PP_Var init_data) {
116 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
117 if (!dispatcher) {
118 NOTREACHED();
119 return;
122 dispatcher->Send(
123 new PpapiMsg_PPPContentDecryptor_GenerateKeyRequest(
124 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
125 instance,
126 SerializedVarSendInput(dispatcher, key_system),
127 SerializedVarSendInput(dispatcher, type),
128 SerializedVarSendInput(dispatcher, init_data)));
131 void AddKey(PP_Instance instance,
132 PP_Var session_id,
133 PP_Var key,
134 PP_Var init_data) {
135 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
136 if (!dispatcher) {
137 NOTREACHED();
138 return;
141 dispatcher->Send(
142 new PpapiMsg_PPPContentDecryptor_AddKey(
143 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
144 instance,
145 SerializedVarSendInput(dispatcher, session_id),
146 SerializedVarSendInput(dispatcher, key),
147 SerializedVarSendInput(dispatcher, init_data)));
150 void CancelKeyRequest(PP_Instance instance, PP_Var session_id) {
151 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
152 if (!dispatcher) {
153 NOTREACHED();
154 return;
157 dispatcher->Send(
158 new PpapiMsg_PPPContentDecryptor_CancelKeyRequest(
159 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
160 instance,
161 SerializedVarSendInput(dispatcher, session_id)));
164 void Decrypt(PP_Instance instance,
165 PP_Resource encrypted_block,
166 const PP_EncryptedBlockInfo* encrypted_block_info) {
167 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
168 if (!dispatcher) {
169 NOTREACHED();
170 return;
173 PPPDecryptor_Buffer buffer;
174 if (!InitializePppDecryptorBuffer(instance,
175 dispatcher,
176 encrypted_block,
177 &buffer)) {
178 NOTREACHED();
179 return;
182 std::string serialized_block_info;
183 if (!SerializeBlockInfo(*encrypted_block_info, &serialized_block_info)) {
184 NOTREACHED();
185 return;
188 // PluginResourceTracker in the plugin process assumes that resources that it
189 // tracks have been addrefed on behalf of the plugin at the renderer side. So
190 // we explicitly do it for |encryped_block| here.
191 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_block);
193 dispatcher->Send(
194 new PpapiMsg_PPPContentDecryptor_Decrypt(
195 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
196 instance,
197 buffer,
198 serialized_block_info));
201 void InitializeAudioDecoder(
202 PP_Instance instance,
203 const PP_AudioDecoderConfig* decoder_config,
204 PP_Resource extra_data_buffer) {
205 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
206 if (!dispatcher) {
207 NOTREACHED();
208 return;
211 std::string serialized_decoder_config;
212 if (!SerializeBlockInfo(*decoder_config, &serialized_decoder_config)) {
213 NOTREACHED();
214 return;
217 PPPDecryptor_Buffer buffer;
218 if (!InitializePppDecryptorBuffer(instance,
219 dispatcher,
220 extra_data_buffer,
221 &buffer)) {
222 NOTREACHED();
223 return;
226 // PluginResourceTracker in the plugin process assumes that resources that it
227 // tracks have been addrefed on behalf of the plugin at the renderer side. So
228 // we explicitly do it for |extra_data_buffer| here.
229 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer);
231 dispatcher->Send(
232 new PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder(
233 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
234 instance,
235 serialized_decoder_config,
236 buffer));
239 void InitializeVideoDecoder(
240 PP_Instance instance,
241 const PP_VideoDecoderConfig* decoder_config,
242 PP_Resource extra_data_buffer) {
243 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
244 if (!dispatcher) {
245 NOTREACHED();
246 return;
249 std::string serialized_decoder_config;
250 if (!SerializeBlockInfo(*decoder_config, &serialized_decoder_config)) {
251 NOTREACHED();
252 return;
255 PPPDecryptor_Buffer buffer;
256 if (!InitializePppDecryptorBuffer(instance,
257 dispatcher,
258 extra_data_buffer,
259 &buffer)) {
260 NOTREACHED();
261 return;
264 // PluginResourceTracker in the plugin process assumes that resources that it
265 // tracks have been addrefed on behalf of the plugin at the renderer side. So
266 // we explicitly do it for |extra_data_buffer| here.
267 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer);
269 dispatcher->Send(
270 new PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder(
271 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
272 instance,
273 serialized_decoder_config,
274 buffer));
278 void DeinitializeDecoder(PP_Instance instance,
279 PP_DecryptorStreamType decoder_type,
280 uint32_t request_id) {
281 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
282 if (!dispatcher) {
283 NOTREACHED();
284 return;
287 dispatcher->Send(
288 new PpapiMsg_PPPContentDecryptor_DeinitializeDecoder(
289 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
290 instance,
291 decoder_type,
292 request_id));
295 void ResetDecoder(PP_Instance instance,
296 PP_DecryptorStreamType decoder_type,
297 uint32_t request_id) {
298 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
299 if (!dispatcher) {
300 NOTREACHED();
301 return;
304 dispatcher->Send(
305 new PpapiMsg_PPPContentDecryptor_ResetDecoder(
306 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
307 instance,
308 decoder_type,
309 request_id));
312 void DecryptAndDecode(PP_Instance instance,
313 PP_DecryptorStreamType decoder_type,
314 PP_Resource encrypted_buffer,
315 const PP_EncryptedBlockInfo* encrypted_block_info) {
316 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
317 if (!dispatcher) {
318 NOTREACHED();
319 return;
322 PPPDecryptor_Buffer buffer;
323 if (!InitializePppDecryptorBuffer(instance,
324 dispatcher,
325 encrypted_buffer,
326 &buffer)) {
327 NOTREACHED();
328 return;
331 std::string serialized_block_info;
332 if (!SerializeBlockInfo(*encrypted_block_info, &serialized_block_info)) {
333 NOTREACHED();
334 return;
337 // PluginResourceTracker in the plugin process assumes that resources that it
338 // tracks have been addrefed on behalf of the plugin at the renderer side. So
339 // we explicitly do it for |encrypted_buffer| here.
340 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_buffer);
342 dispatcher->Send(
343 new PpapiMsg_PPPContentDecryptor_DecryptAndDecode(
344 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
345 instance,
346 decoder_type,
347 buffer,
348 serialized_block_info));
351 static const PPP_ContentDecryptor_Private content_decryptor_interface = {
352 &GenerateKeyRequest,
353 &AddKey,
354 &CancelKeyRequest,
355 &Decrypt,
356 &InitializeAudioDecoder,
357 &InitializeVideoDecoder,
358 &DeinitializeDecoder,
359 &ResetDecoder,
360 &DecryptAndDecode
363 } // namespace
365 PPP_ContentDecryptor_Private_Proxy::PPP_ContentDecryptor_Private_Proxy(
366 Dispatcher* dispatcher)
367 : InterfaceProxy(dispatcher),
368 ppp_decryptor_impl_(NULL) {
369 if (dispatcher->IsPlugin()) {
370 ppp_decryptor_impl_ = static_cast<const PPP_ContentDecryptor_Private*>(
371 dispatcher->local_get_interface()(
372 PPP_CONTENTDECRYPTOR_PRIVATE_INTERFACE));
376 PPP_ContentDecryptor_Private_Proxy::~PPP_ContentDecryptor_Private_Proxy() {
379 // static
380 const PPP_ContentDecryptor_Private*
381 PPP_ContentDecryptor_Private_Proxy::GetProxyInterface() {
382 return &content_decryptor_interface;
385 bool PPP_ContentDecryptor_Private_Proxy::OnMessageReceived(
386 const IPC::Message& msg) {
387 if (!dispatcher()->IsPlugin())
388 return false; // These are only valid from host->plugin.
389 // Don't allow the plugin to send these to the host.
391 bool handled = true;
392 IPC_BEGIN_MESSAGE_MAP(PPP_ContentDecryptor_Private_Proxy, msg)
393 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_GenerateKeyRequest,
394 OnMsgGenerateKeyRequest)
395 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_AddKey,
396 OnMsgAddKey)
397 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_CancelKeyRequest,
398 OnMsgCancelKeyRequest)
399 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_Decrypt,
400 OnMsgDecrypt)
401 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder,
402 OnMsgInitializeAudioDecoder)
403 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder,
404 OnMsgInitializeVideoDecoder)
405 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DeinitializeDecoder,
406 OnMsgDeinitializeDecoder)
407 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_ResetDecoder,
408 OnMsgResetDecoder)
409 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DecryptAndDecode,
410 OnMsgDecryptAndDecode)
411 IPC_MESSAGE_UNHANDLED(handled = false)
412 IPC_END_MESSAGE_MAP()
413 DCHECK(handled);
414 return handled;
417 void PPP_ContentDecryptor_Private_Proxy::OnMsgGenerateKeyRequest(
418 PP_Instance instance,
419 SerializedVarReceiveInput key_system,
420 SerializedVarReceiveInput type,
421 SerializedVarReceiveInput init_data) {
422 if (ppp_decryptor_impl_) {
423 CallWhileUnlocked(ppp_decryptor_impl_->GenerateKeyRequest,
424 instance,
425 ExtractReceivedVarAndAddRef(dispatcher(), &key_system),
426 ExtractReceivedVarAndAddRef(dispatcher(), &type),
427 ExtractReceivedVarAndAddRef(dispatcher(), &init_data));
431 void PPP_ContentDecryptor_Private_Proxy::OnMsgAddKey(
432 PP_Instance instance,
433 SerializedVarReceiveInput session_id,
434 SerializedVarReceiveInput key,
435 SerializedVarReceiveInput init_data) {
436 if (ppp_decryptor_impl_) {
437 CallWhileUnlocked(ppp_decryptor_impl_->AddKey,
438 instance,
439 ExtractReceivedVarAndAddRef(dispatcher(), &session_id),
440 ExtractReceivedVarAndAddRef(dispatcher(), &key),
441 ExtractReceivedVarAndAddRef(dispatcher(), &init_data));
445 void PPP_ContentDecryptor_Private_Proxy::OnMsgCancelKeyRequest(
446 PP_Instance instance,
447 SerializedVarReceiveInput session_id) {
448 if (ppp_decryptor_impl_) {
449 CallWhileUnlocked(ppp_decryptor_impl_->CancelKeyRequest,
450 instance,
451 ExtractReceivedVarAndAddRef(dispatcher(), &session_id));
455 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecrypt(
456 PP_Instance instance,
457 const PPPDecryptor_Buffer& encrypted_buffer,
458 const std::string& serialized_block_info) {
459 ScopedPPResource plugin_resource(
460 ScopedPPResource::PassRef(),
461 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer.resource,
462 encrypted_buffer.handle,
463 encrypted_buffer.size));
464 if (ppp_decryptor_impl_) {
465 PP_EncryptedBlockInfo block_info;
466 if (!DeserializeBlockInfo(serialized_block_info, &block_info))
467 return;
468 CallWhileUnlocked(ppp_decryptor_impl_->Decrypt,
469 instance,
470 plugin_resource.get(),
471 const_cast<const PP_EncryptedBlockInfo*>(&block_info));
475 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeAudioDecoder(
476 PP_Instance instance,
477 const std::string& serialized_decoder_config,
478 const PPPDecryptor_Buffer& extra_data_buffer) {
479 ScopedPPResource plugin_resource;
480 if (extra_data_buffer.size > 0) {
481 plugin_resource = ScopedPPResource(
482 ScopedPPResource::PassRef(),
483 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer.resource,
484 extra_data_buffer.handle,
485 extra_data_buffer.size));
488 PP_AudioDecoderConfig decoder_config;
489 if (!DeserializeBlockInfo(serialized_decoder_config, &decoder_config))
490 return;
492 if (ppp_decryptor_impl_) {
493 CallWhileUnlocked(
494 ppp_decryptor_impl_->InitializeAudioDecoder,
495 instance,
496 const_cast<const PP_AudioDecoderConfig*>(&decoder_config),
497 plugin_resource.get());
501 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeVideoDecoder(
502 PP_Instance instance,
503 const std::string& serialized_decoder_config,
504 const PPPDecryptor_Buffer& extra_data_buffer) {
505 ScopedPPResource plugin_resource;
506 if (extra_data_buffer.resource.host_resource() != 0) {
507 plugin_resource = ScopedPPResource(
508 ScopedPPResource::PassRef(),
509 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer.resource,
510 extra_data_buffer.handle,
511 extra_data_buffer.size));
514 PP_VideoDecoderConfig decoder_config;
515 if (!DeserializeBlockInfo(serialized_decoder_config, &decoder_config))
516 return;
518 if (ppp_decryptor_impl_) {
519 CallWhileUnlocked(
520 ppp_decryptor_impl_->InitializeVideoDecoder,
521 instance,
522 const_cast<const PP_VideoDecoderConfig*>(&decoder_config),
523 plugin_resource.get());
527 void PPP_ContentDecryptor_Private_Proxy::OnMsgDeinitializeDecoder(
528 PP_Instance instance,
529 PP_DecryptorStreamType decoder_type,
530 uint32_t request_id) {
531 if (ppp_decryptor_impl_) {
532 CallWhileUnlocked(
533 ppp_decryptor_impl_->DeinitializeDecoder,
534 instance,
535 decoder_type,
536 request_id);
540 void PPP_ContentDecryptor_Private_Proxy::OnMsgResetDecoder(
541 PP_Instance instance,
542 PP_DecryptorStreamType decoder_type,
543 uint32_t request_id) {
544 if (ppp_decryptor_impl_) {
545 CallWhileUnlocked(
546 ppp_decryptor_impl_->ResetDecoder,
547 instance,
548 decoder_type,
549 request_id);
553 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecryptAndDecode(
554 PP_Instance instance,
555 PP_DecryptorStreamType decoder_type,
556 const PPPDecryptor_Buffer& encrypted_buffer,
557 const std::string& serialized_block_info) {
558 ScopedPPResource plugin_resource;
559 if (encrypted_buffer.resource.host_resource() != 0) {
560 plugin_resource = ScopedPPResource(
561 ScopedPPResource::PassRef(),
562 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer.resource,
563 encrypted_buffer.handle,
564 encrypted_buffer.size));
567 if (ppp_decryptor_impl_) {
568 PP_EncryptedBlockInfo block_info;
569 if (!DeserializeBlockInfo(serialized_block_info, &block_info))
570 return;
571 CallWhileUnlocked(
572 ppp_decryptor_impl_->DecryptAndDecode,
573 instance,
574 decoder_type,
575 plugin_resource.get(),
576 const_cast<const PP_EncryptedBlockInfo*>(&block_info));
580 } // namespace proxy
581 } // namespace ppapi