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.
4
5#include "ppapi/proxy/ppp_content_decryptor_private_proxy.h"
6
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"
25
26using ppapi::thunk::EnterResourceNoLock;
27using ppapi::thunk::PPB_Buffer_API;
28using ppapi::thunk::PPB_Instance_API;
29
30namespace ppapi {
31namespace proxy {
32
33namespace {
34
35PP_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);
40}
41
42// TODO(dmichael): Refactor so this handle sharing code is in one place.
43PP_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_Buffer_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
64
65  *shared_mem_handle = dispatcher->ShareHandleWithRemote(platform_file, false);
66  return PP_TRUE;
67}
68
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.
72PP_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;
77}
78
79bool InitializePppDecryptorBuffer(PP_Instance instance,
80                                  HostDispatcher* dispatcher,
81                                  PP_Resource resource,
82                                  PPPDecryptor_Buffer* buffer) {
83  if (!buffer) {
84    NOTREACHED();
85    return false;
86  }
87
88  if (resource == 0) {
89    buffer->resource = HostResource();
90    buffer->handle = base::SharedMemoryHandle();
91    buffer->size = 0;
92    return true;
93  }
94
95  HostResource host_resource;
96  host_resource.SetHostResource(instance, resource);
97
98  uint32_t size = 0;
99  if (DescribeHostBufferResource(resource, &size) == PP_FALSE)
100    return false;
101
102  base::SharedMemoryHandle handle;
103  if (ShareHostBufferResourceToPlugin(dispatcher,
104                                      resource,
105                                      &handle) == PP_FALSE)
106    return false;
107
108  buffer->resource = host_resource;
109  buffer->handle = handle;
110  buffer->size = size;
111  return true;
112}
113
114void Initialize(PP_Instance instance,
115                PP_Var key_system) {
116  HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
117  if (!dispatcher) {
118    NOTREACHED();
119    return;
120  }
121
122  dispatcher->Send(
123      new PpapiMsg_PPPContentDecryptor_Initialize(
124          API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
125          instance,
126          SerializedVarSendInput(dispatcher, key_system)));
127}
128
129void SetServerCertificate(PP_Instance instance,
130                          uint32_t promise_id,
131                          PP_Var server_certificate) {
132  HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
133  if (!dispatcher) {
134    NOTREACHED();
135    return;
136  }
137
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) {
145    NOTREACHED();
146    return;
147  }
148
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);
155
156  dispatcher->Send(new PpapiMsg_PPPContentDecryptor_SetServerCertificate(
157      API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
158      instance,
159      promise_id,
160      server_certificate_vector));
161}
162
163void CreateSession(PP_Instance instance,
164                   uint32_t promise_id,
165                   PP_Var init_data_type,
166                   PP_Var init_data,
167                   PP_SessionType session_type) {
168  HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
169  if (!dispatcher) {
170    NOTREACHED();
171    return;
172  }
173
174  dispatcher->Send(new PpapiMsg_PPPContentDecryptor_CreateSession(
175      API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
176      instance,
177      promise_id,
178      SerializedVarSendInput(dispatcher, init_data_type),
179      SerializedVarSendInput(dispatcher, init_data),
180      session_type));
181}
182
183void LoadSession(PP_Instance instance,
184                 uint32_t promise_id,
185                 PP_Var web_session_id) {
186  HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
187  if (!dispatcher) {
188    NOTREACHED();
189    return;
190  }
191
192  dispatcher->Send(new PpapiMsg_PPPContentDecryptor_LoadSession(
193      API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
194      instance,
195      promise_id,
196      SerializedVarSendInput(dispatcher, web_session_id)));
197}
198
199void UpdateSession(PP_Instance instance,
200                   uint32_t promise_id,
201                   PP_Var web_session_id,
202                   PP_Var response) {
203  HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
204  if (!dispatcher) {
205    NOTREACHED();
206    return;
207  }
208
209  dispatcher->Send(new PpapiMsg_PPPContentDecryptor_UpdateSession(
210      API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
211      instance,
212      promise_id,
213      SerializedVarSendInput(dispatcher, web_session_id),
214      SerializedVarSendInput(dispatcher, response)));
215}
216
217void CloseSession(PP_Instance instance,
218                  uint32_t promise_id,
219                  PP_Var web_session_id) {
220  HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
221  if (!dispatcher) {
222    NOTREACHED();
223    return;
224  }
225
226  StringVar* session_id = StringVar::FromPPVar(web_session_id);
227  if (!session_id ||
228      session_id->value().length() > media::limits::kMaxWebSessionIdLength) {
229    NOTREACHED();
230    return;
231  }
232
233  dispatcher->Send(new PpapiMsg_PPPContentDecryptor_CloseSession(
234      API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
235      instance,
236      promise_id,
237      session_id->value()));
238}
239
240void RemoveSession(PP_Instance instance,
241                   uint32_t promise_id,
242                   PP_Var web_session_id) {
243  HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
244  if (!dispatcher) {
245    NOTREACHED();
246    return;
247  }
248
249  StringVar* session_id = StringVar::FromPPVar(web_session_id);
250  if (!session_id ||
251      session_id->value().length() > media::limits::kMaxWebSessionIdLength) {
252    NOTREACHED();
253    return;
254  }
255
256  dispatcher->Send(new PpapiMsg_PPPContentDecryptor_RemoveSession(
257      API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
258      instance,
259      promise_id,
260      session_id->value()));
261}
262
263void GetUsableKeyIds(PP_Instance instance,
264                     uint32_t promise_id,
265                     PP_Var web_session_id) {
266  HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
267  if (!dispatcher) {
268    NOTREACHED();
269    return;
270  }
271
272  StringVar* session_id = StringVar::FromPPVar(web_session_id);
273  if (!session_id ||
274      session_id->value().length() > media::limits::kMaxWebSessionIdLength) {
275    NOTREACHED();
276    return;
277  }
278
279  dispatcher->Send(new PpapiMsg_PPPContentDecryptor_GetUsableKeyIds(
280      API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
281      instance,
282      promise_id,
283      session_id->value()));
284}
285
286void Decrypt(PP_Instance instance,
287             PP_Resource encrypted_block,
288             const PP_EncryptedBlockInfo* encrypted_block_info) {
289  HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
290  if (!dispatcher) {
291    NOTREACHED();
292    return;
293  }
294
295  PPPDecryptor_Buffer buffer;
296  if (!InitializePppDecryptorBuffer(instance,
297                                    dispatcher,
298                                    encrypted_block,
299                                    &buffer)) {
300    NOTREACHED();
301    return;
302  }
303
304  std::string serialized_block_info;
305  if (!SerializeBlockInfo(*encrypted_block_info, &serialized_block_info)) {
306    NOTREACHED();
307    return;
308  }
309
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);
314
315  dispatcher->Send(
316      new PpapiMsg_PPPContentDecryptor_Decrypt(
317          API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
318          instance,
319          buffer,
320          serialized_block_info));
321}
322
323void InitializeAudioDecoder(
324    PP_Instance instance,
325    const PP_AudioDecoderConfig* decoder_config,
326    PP_Resource extra_data_buffer) {
327  HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
328  if (!dispatcher) {
329    NOTREACHED();
330    return;
331  }
332
333  std::string serialized_decoder_config;
334  if (!SerializeBlockInfo(*decoder_config, &serialized_decoder_config)) {
335    NOTREACHED();
336    return;
337  }
338
339  PPPDecryptor_Buffer buffer;
340  if (!InitializePppDecryptorBuffer(instance,
341                                    dispatcher,
342                                    extra_data_buffer,
343                                    &buffer)) {
344    NOTREACHED();
345    return;
346  }
347
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);
352
353  dispatcher->Send(
354      new PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder(
355          API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
356          instance,
357          serialized_decoder_config,
358          buffer));
359}
360
361void InitializeVideoDecoder(
362    PP_Instance instance,
363    const PP_VideoDecoderConfig* decoder_config,
364    PP_Resource extra_data_buffer) {
365  HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
366  if (!dispatcher) {
367    NOTREACHED();
368    return;
369  }
370
371  std::string serialized_decoder_config;
372  if (!SerializeBlockInfo(*decoder_config, &serialized_decoder_config)) {
373    NOTREACHED();
374    return;
375  }
376
377  PPPDecryptor_Buffer buffer;
378  if (!InitializePppDecryptorBuffer(instance,
379                                    dispatcher,
380                                    extra_data_buffer,
381                                    &buffer)) {
382    NOTREACHED();
383    return;
384  }
385
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);
390
391  dispatcher->Send(
392      new PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder(
393          API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
394          instance,
395          serialized_decoder_config,
396          buffer));
397}
398
399
400void DeinitializeDecoder(PP_Instance instance,
401                         PP_DecryptorStreamType decoder_type,
402                         uint32_t request_id) {
403  HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
404  if (!dispatcher) {
405    NOTREACHED();
406    return;
407  }
408
409  dispatcher->Send(
410      new PpapiMsg_PPPContentDecryptor_DeinitializeDecoder(
411          API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
412          instance,
413          decoder_type,
414          request_id));
415}
416
417void ResetDecoder(PP_Instance instance,
418                  PP_DecryptorStreamType decoder_type,
419                  uint32_t request_id) {
420  HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
421  if (!dispatcher) {
422    NOTREACHED();
423    return;
424  }
425
426  dispatcher->Send(
427      new PpapiMsg_PPPContentDecryptor_ResetDecoder(
428          API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
429          instance,
430          decoder_type,
431          request_id));
432}
433
434void 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);
439  if (!dispatcher) {
440    NOTREACHED();
441    return;
442  }
443
444  PPPDecryptor_Buffer buffer;
445  if (!InitializePppDecryptorBuffer(instance,
446                                    dispatcher,
447                                    encrypted_buffer,
448                                    &buffer)) {
449    NOTREACHED();
450    return;
451  }
452
453  std::string serialized_block_info;
454  if (!SerializeBlockInfo(*encrypted_block_info, &serialized_block_info)) {
455    NOTREACHED();
456    return;
457  }
458
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);
463
464  dispatcher->Send(
465      new PpapiMsg_PPPContentDecryptor_DecryptAndDecode(
466          API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
467          instance,
468          decoder_type,
469          buffer,
470          serialized_block_info));
471}
472
473static const PPP_ContentDecryptor_Private content_decryptor_interface = {
474    &Initialize,
475    &SetServerCertificate,
476    &CreateSession,
477    &LoadSession,
478    &UpdateSession,
479    &CloseSession,
480    &RemoveSession,
481    &GetUsableKeyIds,
482    &Decrypt,
483    &InitializeAudioDecoder,
484    &InitializeVideoDecoder,
485    &DeinitializeDecoder,
486    &ResetDecoder,
487    &DecryptAndDecode};
488
489}  // namespace
490
491PPP_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));
499  }
500}
501
502PPP_ContentDecryptor_Private_Proxy::~PPP_ContentDecryptor_Private_Proxy() {
503}
504
505// static
506const PPP_ContentDecryptor_Private*
507    PPP_ContentDecryptor_Private_Proxy::GetProxyInterface() {
508  return &content_decryptor_interface;
509}
510
511bool 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.
516
517  bool handled = true;
518  IPC_BEGIN_MESSAGE_MAP(PPP_ContentDecryptor_Private_Proxy, msg)
519    IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_Initialize,
520                        OnMsgInitialize)
521    IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_SetServerCertificate,
522                        OnMsgSetServerCertificate)
523    IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_CreateSession,
524                        OnMsgCreateSession)
525    IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_LoadSession,
526                        OnMsgLoadSession)
527    IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_UpdateSession,
528                        OnMsgUpdateSession)
529    IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_CloseSession,
530                        OnMsgCloseSession)
531    IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_RemoveSession,
532                        OnMsgRemoveSession)
533    IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_GetUsableKeyIds,
534                        OnMsgGetUsableKeyIds)
535    IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_Decrypt,
536                        OnMsgDecrypt)
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,
544                        OnMsgResetDecoder)
545    IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DecryptAndDecode,
546                        OnMsgDecryptAndDecode)
547    IPC_MESSAGE_UNHANDLED(handled = false)
548  IPC_END_MESSAGE_MAP()
549  DCHECK(handled);
550  return handled;
551}
552
553void PPP_ContentDecryptor_Private_Proxy::OnMsgInitialize(
554    PP_Instance instance,
555    SerializedVarReceiveInput key_system) {
556  if (ppp_decryptor_impl_) {
557    CallWhileUnlocked(
558        ppp_decryptor_impl_->Initialize,
559        instance,
560        ExtractReceivedVarAndAddRef(dispatcher(), &key_system));
561  }
562}
563
564void PPP_ContentDecryptor_Private_Proxy::OnMsgSetServerCertificate(
565    PP_Instance instance,
566    uint32_t promise_id,
567    std::vector<uint8_t> server_certificate) {
568  if (server_certificate.size() < media::limits::kMinCertificateLength ||
569      server_certificate.size() > media::limits::kMaxCertificateLength) {
570    NOTREACHED();
571    return;
572  }
573
574  if (ppp_decryptor_impl_) {
575    ScopedPPVar server_certificate_var(
576        ScopedPPVar::PassRef(),
577        PpapiGlobals::Get()
578            ->GetVarTracker()
579            ->MakeArrayBufferPPVar(server_certificate.size(),
580                                   &server_certificate[0]));
581    CallWhileUnlocked(ppp_decryptor_impl_->SetServerCertificate,
582                      instance,
583                      promise_id,
584                      server_certificate_var.get());
585  }
586}
587
588void PPP_ContentDecryptor_Private_Proxy::OnMsgCreateSession(
589    PP_Instance instance,
590    uint32_t promise_id,
591    SerializedVarReceiveInput init_data_type,
592    SerializedVarReceiveInput init_data,
593    PP_SessionType session_type) {
594  if (ppp_decryptor_impl_) {
595    CallWhileUnlocked(
596        ppp_decryptor_impl_->CreateSession,
597        instance,
598        promise_id,
599        ExtractReceivedVarAndAddRef(dispatcher(), &init_data_type),
600        ExtractReceivedVarAndAddRef(dispatcher(), &init_data),
601        session_type);
602  }
603}
604
605void PPP_ContentDecryptor_Private_Proxy::OnMsgLoadSession(
606    PP_Instance instance,
607    uint32_t promise_id,
608    SerializedVarReceiveInput web_session_id) {
609  if (ppp_decryptor_impl_) {
610    CallWhileUnlocked(
611        ppp_decryptor_impl_->LoadSession,
612        instance,
613        promise_id,
614        ExtractReceivedVarAndAddRef(dispatcher(), &web_session_id));
615  }
616}
617
618void PPP_ContentDecryptor_Private_Proxy::OnMsgUpdateSession(
619    PP_Instance instance,
620    uint32_t promise_id,
621    SerializedVarReceiveInput web_session_id,
622    SerializedVarReceiveInput response) {
623  if (ppp_decryptor_impl_) {
624    CallWhileUnlocked(
625        ppp_decryptor_impl_->UpdateSession,
626        instance,
627        promise_id,
628        ExtractReceivedVarAndAddRef(dispatcher(), &web_session_id),
629        ExtractReceivedVarAndAddRef(dispatcher(), &response));
630  }
631}
632
633void PPP_ContentDecryptor_Private_Proxy::OnMsgCloseSession(
634    PP_Instance instance,
635    uint32_t promise_id,
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,
641                      instance,
642                      promise_id,
643                      web_session_id_var.get());
644  }
645}
646
647void PPP_ContentDecryptor_Private_Proxy::OnMsgRemoveSession(
648    PP_Instance instance,
649    uint32_t promise_id,
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,
655                      instance,
656                      promise_id,
657                      web_session_id_var.get());
658  }
659}
660
661void PPP_ContentDecryptor_Private_Proxy::OnMsgGetUsableKeyIds(
662    PP_Instance instance,
663    uint32_t promise_id,
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,
669                      instance,
670                      promise_id,
671                      web_session_id_var.get());
672  }
673}
674
675void 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))
687      return;
688    CallWhileUnlocked(ppp_decryptor_impl_->Decrypt,
689                      instance,
690                      plugin_resource.get(),
691                      &block_info);
692  }
693}
694
695void 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));
706  }
707
708  PP_AudioDecoderConfig decoder_config;
709  if (!DeserializeBlockInfo(serialized_decoder_config, &decoder_config))
710      return;
711
712  if (ppp_decryptor_impl_) {
713    CallWhileUnlocked(
714        ppp_decryptor_impl_->InitializeAudioDecoder,
715        instance,
716        &decoder_config,
717        plugin_resource.get());
718  }
719}
720
721void 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));
732  }
733
734  PP_VideoDecoderConfig decoder_config;
735  if (!DeserializeBlockInfo(serialized_decoder_config, &decoder_config))
736      return;
737
738  if (ppp_decryptor_impl_) {
739    CallWhileUnlocked(
740        ppp_decryptor_impl_->InitializeVideoDecoder,
741        instance,
742        &decoder_config,
743        plugin_resource.get());
744  }
745}
746
747void PPP_ContentDecryptor_Private_Proxy::OnMsgDeinitializeDecoder(
748    PP_Instance instance,
749    PP_DecryptorStreamType decoder_type,
750    uint32_t request_id) {
751  if (ppp_decryptor_impl_) {
752    CallWhileUnlocked(
753        ppp_decryptor_impl_->DeinitializeDecoder,
754        instance,
755        decoder_type,
756        request_id);
757  }
758}
759
760void PPP_ContentDecryptor_Private_Proxy::OnMsgResetDecoder(
761    PP_Instance instance,
762    PP_DecryptorStreamType decoder_type,
763    uint32_t request_id) {
764  if (ppp_decryptor_impl_) {
765    CallWhileUnlocked(
766        ppp_decryptor_impl_->ResetDecoder,
767        instance,
768        decoder_type,
769        request_id);
770  }
771}
772
773void 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));
785  }
786
787  if (ppp_decryptor_impl_) {
788    PP_EncryptedBlockInfo block_info;
789    if (!DeserializeBlockInfo(serialized_block_info, &block_info))
790      return;
791    CallWhileUnlocked(
792        ppp_decryptor_impl_->DecryptAndDecode,
793        instance,
794        decoder_type,
795        plugin_resource.get(),
796        &block_info);
797  }
798}
799
800}  // namespace proxy
801}  // namespace ppapi
802