Fix iOS build for XCode 4.6.
[chromium-blink-merge.git] / ppapi / proxy / ppp_content_decryptor_private_proxy.cc
blob5d98e0dd39853765c69eb3069befa58c95907947
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_buffer_trusted_api.h"
22 #include "ppapi/thunk/ppb_instance_api.h"
23 #include "ppapi/thunk/thunk.h"
25 using ppapi::thunk::EnterResourceNoLock;
26 using ppapi::thunk::PPB_Buffer_API;
27 using ppapi::thunk::PPB_BufferTrusted_API;
28 using ppapi::thunk::PPB_Instance_API;
30 namespace ppapi {
31 namespace proxy {
33 namespace {
35 PP_Bool DescribeHostBufferResource(PP_Resource resource, uint32_t* size) {
36 EnterResourceNoLock<PPB_Buffer_API> enter(resource, true);
37 if (enter.failed())
38 return PP_FALSE;
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,
45 PP_Resource resource,
46 base::SharedMemoryHandle* shared_mem_handle) {
47 if (!dispatcher || resource == 0 || !shared_mem_handle)
48 return PP_FALSE;
49 EnterResourceNoLock<PPB_BufferTrusted_API> enter(resource, true);
50 if (enter.failed())
51 return PP_FALSE;
52 int handle;
53 int32_t result = enter.object()->GetSharedMemory(&handle);
54 if (result != PP_OK)
55 return PP_FALSE;
56 base::PlatformFile platform_file =
57 #if defined(OS_WIN)
58 reinterpret_cast<HANDLE>(static_cast<intptr_t>(handle));
59 #elif defined(OS_POSIX)
60 handle;
61 #else
62 #error Not implemented.
63 #endif
65 *shared_mem_handle = dispatcher->ShareHandleWithRemote(platform_file, false);
66 return PP_TRUE;
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);
76 return var;
79 bool InitializePppDecryptorBuffer(PP_Instance instance,
80 HostDispatcher* dispatcher,
81 PP_Resource resource,
82 PPPDecryptor_Buffer* buffer) {
83 if (!buffer) {
84 NOTREACHED();
85 return false;
88 if (resource == 0) {
89 buffer->resource = HostResource();
90 buffer->handle = base::SharedMemoryHandle();
91 buffer->size = 0;
92 return true;
95 HostResource host_resource;
96 host_resource.SetHostResource(instance, resource);
98 uint32_t size = 0;
99 if (DescribeHostBufferResource(resource, &size) == PP_FALSE)
100 return false;
102 base::SharedMemoryHandle handle;
103 if (ShareHostBufferResourceToPlugin(dispatcher,
104 resource,
105 &handle) == PP_FALSE)
106 return false;
108 buffer->resource = host_resource;
109 buffer->handle = handle;
110 buffer->size = size;
111 return true;
114 void GenerateKeyRequest(PP_Instance instance,
115 PP_Var key_system,
116 PP_Var type,
117 PP_Var init_data) {
118 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
119 if (!dispatcher) {
120 NOTREACHED();
121 return;
124 dispatcher->Send(
125 new PpapiMsg_PPPContentDecryptor_GenerateKeyRequest(
126 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
127 instance,
128 SerializedVarSendInput(dispatcher, key_system),
129 SerializedVarSendInput(dispatcher, type),
130 SerializedVarSendInput(dispatcher, init_data)));
133 void AddKey(PP_Instance instance,
134 PP_Var session_id,
135 PP_Var key,
136 PP_Var init_data) {
137 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
138 if (!dispatcher) {
139 NOTREACHED();
140 return;
143 dispatcher->Send(
144 new PpapiMsg_PPPContentDecryptor_AddKey(
145 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
146 instance,
147 SerializedVarSendInput(dispatcher, session_id),
148 SerializedVarSendInput(dispatcher, key),
149 SerializedVarSendInput(dispatcher, init_data)));
152 void CancelKeyRequest(PP_Instance instance, PP_Var session_id) {
153 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
154 if (!dispatcher) {
155 NOTREACHED();
156 return;
159 dispatcher->Send(
160 new PpapiMsg_PPPContentDecryptor_CancelKeyRequest(
161 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
162 instance,
163 SerializedVarSendInput(dispatcher, session_id)));
166 void Decrypt(PP_Instance instance,
167 PP_Resource encrypted_block,
168 const PP_EncryptedBlockInfo* encrypted_block_info) {
169 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
170 if (!dispatcher) {
171 NOTREACHED();
172 return;
175 PPPDecryptor_Buffer buffer;
176 if (!InitializePppDecryptorBuffer(instance,
177 dispatcher,
178 encrypted_block,
179 &buffer)) {
180 NOTREACHED();
181 return;
184 std::string serialized_block_info;
185 if (!SerializeBlockInfo(*encrypted_block_info, &serialized_block_info)) {
186 NOTREACHED();
187 return;
190 // PluginResourceTracker in the plugin process assumes that resources that it
191 // tracks have been addrefed on behalf of the plugin at the renderer side. So
192 // we explicitly do it for |encryped_block| here.
193 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_block);
195 dispatcher->Send(
196 new PpapiMsg_PPPContentDecryptor_Decrypt(
197 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
198 instance,
199 buffer,
200 serialized_block_info));
203 void InitializeAudioDecoder(
204 PP_Instance instance,
205 const PP_AudioDecoderConfig* decoder_config,
206 PP_Resource extra_data_buffer) {
207 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
208 if (!dispatcher) {
209 NOTREACHED();
210 return;
213 std::string serialized_decoder_config;
214 if (!SerializeBlockInfo(*decoder_config, &serialized_decoder_config)) {
215 NOTREACHED();
216 return;
219 PPPDecryptor_Buffer buffer;
220 if (!InitializePppDecryptorBuffer(instance,
221 dispatcher,
222 extra_data_buffer,
223 &buffer)) {
224 NOTREACHED();
225 return;
228 // PluginResourceTracker in the plugin process assumes that resources that it
229 // tracks have been addrefed on behalf of the plugin at the renderer side. So
230 // we explicitly do it for |extra_data_buffer| here.
231 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer);
233 dispatcher->Send(
234 new PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder(
235 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
236 instance,
237 serialized_decoder_config,
238 buffer));
241 void InitializeVideoDecoder(
242 PP_Instance instance,
243 const PP_VideoDecoderConfig* decoder_config,
244 PP_Resource extra_data_buffer) {
245 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
246 if (!dispatcher) {
247 NOTREACHED();
248 return;
251 std::string serialized_decoder_config;
252 if (!SerializeBlockInfo(*decoder_config, &serialized_decoder_config)) {
253 NOTREACHED();
254 return;
257 PPPDecryptor_Buffer buffer;
258 if (!InitializePppDecryptorBuffer(instance,
259 dispatcher,
260 extra_data_buffer,
261 &buffer)) {
262 NOTREACHED();
263 return;
266 // PluginResourceTracker in the plugin process assumes that resources that it
267 // tracks have been addrefed on behalf of the plugin at the renderer side. So
268 // we explicitly do it for |extra_data_buffer| here.
269 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer);
271 dispatcher->Send(
272 new PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder(
273 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
274 instance,
275 serialized_decoder_config,
276 buffer));
280 void DeinitializeDecoder(PP_Instance instance,
281 PP_DecryptorStreamType decoder_type,
282 uint32_t request_id) {
283 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
284 if (!dispatcher) {
285 NOTREACHED();
286 return;
289 dispatcher->Send(
290 new PpapiMsg_PPPContentDecryptor_DeinitializeDecoder(
291 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
292 instance,
293 decoder_type,
294 request_id));
297 void ResetDecoder(PP_Instance instance,
298 PP_DecryptorStreamType decoder_type,
299 uint32_t request_id) {
300 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
301 if (!dispatcher) {
302 NOTREACHED();
303 return;
306 dispatcher->Send(
307 new PpapiMsg_PPPContentDecryptor_ResetDecoder(
308 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
309 instance,
310 decoder_type,
311 request_id));
314 void DecryptAndDecode(PP_Instance instance,
315 PP_DecryptorStreamType decoder_type,
316 PP_Resource encrypted_buffer,
317 const PP_EncryptedBlockInfo* encrypted_block_info) {
318 HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
319 if (!dispatcher) {
320 NOTREACHED();
321 return;
324 PPPDecryptor_Buffer buffer;
325 if (!InitializePppDecryptorBuffer(instance,
326 dispatcher,
327 encrypted_buffer,
328 &buffer)) {
329 NOTREACHED();
330 return;
333 std::string serialized_block_info;
334 if (!SerializeBlockInfo(*encrypted_block_info, &serialized_block_info)) {
335 NOTREACHED();
336 return;
339 // PluginResourceTracker in the plugin process assumes that resources that it
340 // tracks have been addrefed on behalf of the plugin at the renderer side. So
341 // we explicitly do it for |encrypted_buffer| here.
342 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_buffer);
344 dispatcher->Send(
345 new PpapiMsg_PPPContentDecryptor_DecryptAndDecode(
346 API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
347 instance,
348 decoder_type,
349 buffer,
350 serialized_block_info));
353 static const PPP_ContentDecryptor_Private content_decryptor_interface = {
354 &GenerateKeyRequest,
355 &AddKey,
356 &CancelKeyRequest,
357 &Decrypt,
358 &InitializeAudioDecoder,
359 &InitializeVideoDecoder,
360 &DeinitializeDecoder,
361 &ResetDecoder,
362 &DecryptAndDecode
365 } // namespace
367 PPP_ContentDecryptor_Private_Proxy::PPP_ContentDecryptor_Private_Proxy(
368 Dispatcher* dispatcher)
369 : InterfaceProxy(dispatcher),
370 ppp_decryptor_impl_(NULL) {
371 if (dispatcher->IsPlugin()) {
372 ppp_decryptor_impl_ = static_cast<const PPP_ContentDecryptor_Private*>(
373 dispatcher->local_get_interface()(
374 PPP_CONTENTDECRYPTOR_PRIVATE_INTERFACE));
378 PPP_ContentDecryptor_Private_Proxy::~PPP_ContentDecryptor_Private_Proxy() {
381 // static
382 const PPP_ContentDecryptor_Private*
383 PPP_ContentDecryptor_Private_Proxy::GetProxyInterface() {
384 return &content_decryptor_interface;
387 bool PPP_ContentDecryptor_Private_Proxy::OnMessageReceived(
388 const IPC::Message& msg) {
389 bool handled = true;
390 IPC_BEGIN_MESSAGE_MAP(PPP_ContentDecryptor_Private_Proxy, msg)
391 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_GenerateKeyRequest,
392 OnMsgGenerateKeyRequest)
393 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_AddKey,
394 OnMsgAddKey)
395 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_CancelKeyRequest,
396 OnMsgCancelKeyRequest)
397 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_Decrypt,
398 OnMsgDecrypt)
399 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder,
400 OnMsgInitializeAudioDecoder)
401 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder,
402 OnMsgInitializeVideoDecoder)
403 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DeinitializeDecoder,
404 OnMsgDeinitializeDecoder)
405 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_ResetDecoder,
406 OnMsgResetDecoder)
407 IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DecryptAndDecode,
408 OnMsgDecryptAndDecode)
409 IPC_MESSAGE_UNHANDLED(handled = false)
410 IPC_END_MESSAGE_MAP()
411 DCHECK(handled);
412 return handled;
415 void PPP_ContentDecryptor_Private_Proxy::OnMsgGenerateKeyRequest(
416 PP_Instance instance,
417 SerializedVarReceiveInput key_system,
418 SerializedVarReceiveInput type,
419 SerializedVarReceiveInput init_data) {
420 if (ppp_decryptor_impl_) {
421 CallWhileUnlocked(ppp_decryptor_impl_->GenerateKeyRequest,
422 instance,
423 ExtractReceivedVarAndAddRef(dispatcher(), &key_system),
424 ExtractReceivedVarAndAddRef(dispatcher(), &type),
425 ExtractReceivedVarAndAddRef(dispatcher(), &init_data));
429 void PPP_ContentDecryptor_Private_Proxy::OnMsgAddKey(
430 PP_Instance instance,
431 SerializedVarReceiveInput session_id,
432 SerializedVarReceiveInput key,
433 SerializedVarReceiveInput init_data) {
434 if (ppp_decryptor_impl_) {
435 CallWhileUnlocked(ppp_decryptor_impl_->AddKey,
436 instance,
437 ExtractReceivedVarAndAddRef(dispatcher(), &session_id),
438 ExtractReceivedVarAndAddRef(dispatcher(), &key),
439 ExtractReceivedVarAndAddRef(dispatcher(), &init_data));
443 void PPP_ContentDecryptor_Private_Proxy::OnMsgCancelKeyRequest(
444 PP_Instance instance,
445 SerializedVarReceiveInput session_id) {
446 if (ppp_decryptor_impl_) {
447 CallWhileUnlocked(ppp_decryptor_impl_->CancelKeyRequest,
448 instance,
449 ExtractReceivedVarAndAddRef(dispatcher(), &session_id));
453 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecrypt(
454 PP_Instance instance,
455 const PPPDecryptor_Buffer& encrypted_buffer,
456 const std::string& serialized_block_info) {
457 ScopedPPResource plugin_resource(
458 ScopedPPResource::PassRef(),
459 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer.resource,
460 encrypted_buffer.handle,
461 encrypted_buffer.size));
462 if (ppp_decryptor_impl_) {
463 PP_EncryptedBlockInfo block_info;
464 if (!DeserializeBlockInfo(serialized_block_info, &block_info))
465 return;
466 CallWhileUnlocked(ppp_decryptor_impl_->Decrypt,
467 instance,
468 plugin_resource.get(),
469 const_cast<const PP_EncryptedBlockInfo*>(&block_info));
473 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeAudioDecoder(
474 PP_Instance instance,
475 const std::string& serialized_decoder_config,
476 const PPPDecryptor_Buffer& extra_data_buffer) {
477 ScopedPPResource plugin_resource;
478 if (extra_data_buffer.size > 0) {
479 plugin_resource = ScopedPPResource(
480 ScopedPPResource::PassRef(),
481 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer.resource,
482 extra_data_buffer.handle,
483 extra_data_buffer.size));
486 PP_AudioDecoderConfig decoder_config;
487 if (!DeserializeBlockInfo(serialized_decoder_config, &decoder_config))
488 return;
490 if (ppp_decryptor_impl_) {
491 CallWhileUnlocked(
492 ppp_decryptor_impl_->InitializeAudioDecoder,
493 instance,
494 const_cast<const PP_AudioDecoderConfig*>(&decoder_config),
495 plugin_resource.get());
499 void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeVideoDecoder(
500 PP_Instance instance,
501 const std::string& serialized_decoder_config,
502 const PPPDecryptor_Buffer& extra_data_buffer) {
503 ScopedPPResource plugin_resource;
504 if (extra_data_buffer.resource.host_resource() != 0) {
505 plugin_resource = ScopedPPResource(
506 ScopedPPResource::PassRef(),
507 PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer.resource,
508 extra_data_buffer.handle,
509 extra_data_buffer.size));
512 PP_VideoDecoderConfig decoder_config;
513 if (!DeserializeBlockInfo(serialized_decoder_config, &decoder_config))
514 return;
516 if (ppp_decryptor_impl_) {
517 CallWhileUnlocked(
518 ppp_decryptor_impl_->InitializeVideoDecoder,
519 instance,
520 const_cast<const PP_VideoDecoderConfig*>(&decoder_config),
521 plugin_resource.get());
525 void PPP_ContentDecryptor_Private_Proxy::OnMsgDeinitializeDecoder(
526 PP_Instance instance,
527 PP_DecryptorStreamType decoder_type,
528 uint32_t request_id) {
529 if (ppp_decryptor_impl_) {
530 CallWhileUnlocked(
531 ppp_decryptor_impl_->DeinitializeDecoder,
532 instance,
533 decoder_type,
534 request_id);
538 void PPP_ContentDecryptor_Private_Proxy::OnMsgResetDecoder(
539 PP_Instance instance,
540 PP_DecryptorStreamType decoder_type,
541 uint32_t request_id) {
542 if (ppp_decryptor_impl_) {
543 CallWhileUnlocked(
544 ppp_decryptor_impl_->ResetDecoder,
545 instance,
546 decoder_type,
547 request_id);
551 void PPP_ContentDecryptor_Private_Proxy::OnMsgDecryptAndDecode(
552 PP_Instance instance,
553 PP_DecryptorStreamType decoder_type,
554 const PPPDecryptor_Buffer& encrypted_buffer,
555 const std::string& serialized_block_info) {
556 ScopedPPResource plugin_resource;
557 if (encrypted_buffer.resource.host_resource() != 0) {
558 plugin_resource = ScopedPPResource(
559 ScopedPPResource::PassRef(),
560 PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer.resource,
561 encrypted_buffer.handle,
562 encrypted_buffer.size));
565 if (ppp_decryptor_impl_) {
566 PP_EncryptedBlockInfo block_info;
567 if (!DeserializeBlockInfo(serialized_block_info, &block_info))
568 return;
569 CallWhileUnlocked(
570 ppp_decryptor_impl_->DecryptAndDecode,
571 instance,
572 decoder_type,
573 plugin_resource.get(),
574 const_cast<const PP_EncryptedBlockInfo*>(&block_info));
578 } // namespace proxy
579 } // namespace ppapi