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/cpp/private/content_decryptor_private.h"
6
7#include <cstring>  // memcpy
8
9#include "ppapi/c/ppb_var.h"
10#include "ppapi/c/private/ppb_content_decryptor_private.h"
11#include "ppapi/c/private/ppp_content_decryptor_private.h"
12#include "ppapi/cpp/instance.h"
13#include "ppapi/cpp/instance_handle.h"
14#include "ppapi/cpp/logging.h"
15#include "ppapi/cpp/module.h"
16#include "ppapi/cpp/module_impl.h"
17#include "ppapi/cpp/var.h"
18#include "ppapi/cpp/var_array.h"
19
20namespace pp {
21
22namespace {
23
24static const char kPPPContentDecryptorInterface[] =
25    PPP_CONTENTDECRYPTOR_PRIVATE_INTERFACE;
26
27void Initialize(PP_Instance instance,
28                PP_Var key_system_arg) {
29  void* object =
30      Instance::GetPerInstanceObject(instance, kPPPContentDecryptorInterface);
31  if (!object)
32    return;
33
34  pp::Var key_system_var(pp::PASS_REF, key_system_arg);
35  if (!key_system_var.is_string())
36    return;
37
38  static_cast<ContentDecryptor_Private*>(object)->Initialize(
39      key_system_var.AsString());
40}
41
42void SetServerCertificate(PP_Instance instance,
43                          uint32_t promise_id,
44                          PP_Var server_certificate_arg) {
45  void* object =
46      Instance::GetPerInstanceObject(instance, kPPPContentDecryptorInterface);
47  if (!object)
48    return;
49
50  pp::Var server_certificate_var(server_certificate_arg);
51  if (!server_certificate_var.is_array_buffer())
52    return;
53  pp::VarArrayBuffer server_certificate(server_certificate_var);
54
55  static_cast<ContentDecryptor_Private*>(object)
56      ->SetServerCertificate(promise_id, server_certificate);
57}
58
59void CreateSession(PP_Instance instance,
60                   uint32_t promise_id,
61                   PP_Var init_data_type_arg,
62                   PP_Var init_data_arg,
63                   PP_SessionType session_type) {
64  void* object =
65      Instance::GetPerInstanceObject(instance, kPPPContentDecryptorInterface);
66  if (!object)
67    return;
68
69  pp::Var init_data_type_var(pp::PASS_REF, init_data_type_arg);
70  if (!init_data_type_var.is_string())
71    return;
72
73  pp::Var init_data_var(pp::PASS_REF, init_data_arg);
74  if (!init_data_var.is_array_buffer())
75    return;
76  pp::VarArrayBuffer init_data_array_buffer(init_data_var);
77
78  static_cast<ContentDecryptor_Private*>(object)
79      ->CreateSession(promise_id,
80                      init_data_type_var.AsString(),
81                      init_data_array_buffer,
82                      session_type);
83}
84
85void LoadSession(PP_Instance instance,
86                 uint32_t promise_id,
87                 PP_Var web_session_id_arg) {
88  void* object =
89      Instance::GetPerInstanceObject(instance, kPPPContentDecryptorInterface);
90  if (!object)
91    return;
92
93  pp::Var web_session_id_var(web_session_id_arg);
94  if (!web_session_id_var.is_string())
95    return;
96
97  static_cast<ContentDecryptor_Private*>(object)
98      ->LoadSession(promise_id, web_session_id_var.AsString());
99}
100
101void UpdateSession(PP_Instance instance,
102                   uint32_t promise_id,
103                   PP_Var web_session_id_arg,
104                   PP_Var response_arg) {
105  void* object =
106      Instance::GetPerInstanceObject(instance, kPPPContentDecryptorInterface);
107  if (!object)
108    return;
109
110  pp::Var web_session_id_var(web_session_id_arg);
111  if (!web_session_id_var.is_string())
112    return;
113
114  pp::Var response_var(response_arg);
115  if (!response_var.is_array_buffer())
116    return;
117  pp::VarArrayBuffer response(response_var);
118
119  static_cast<ContentDecryptor_Private*>(object)
120      ->UpdateSession(promise_id, web_session_id_var.AsString(), response);
121}
122
123void CloseSession(PP_Instance instance,
124                  uint32_t promise_id,
125                  PP_Var web_session_id_arg) {
126  void* object =
127      Instance::GetPerInstanceObject(instance, kPPPContentDecryptorInterface);
128  if (!object)
129    return;
130
131  pp::Var web_session_id_var(web_session_id_arg);
132  if (!web_session_id_var.is_string())
133    return;
134
135  static_cast<ContentDecryptor_Private*>(object)
136      ->CloseSession(promise_id, web_session_id_var.AsString());
137}
138
139void RemoveSession(PP_Instance instance,
140                   uint32_t promise_id,
141                   PP_Var web_session_id_arg) {
142  void* object =
143      Instance::GetPerInstanceObject(instance, kPPPContentDecryptorInterface);
144  if (!object)
145    return;
146
147  pp::Var web_session_id_var(web_session_id_arg);
148  if (!web_session_id_var.is_string())
149    return;
150
151  static_cast<ContentDecryptor_Private*>(object)
152      ->RemoveSession(promise_id, web_session_id_var.AsString());
153}
154
155void GetUsableKeyIds(PP_Instance instance,
156                     uint32_t promise_id,
157                     PP_Var web_session_id_arg) {
158  void* object =
159      Instance::GetPerInstanceObject(instance, kPPPContentDecryptorInterface);
160  if (!object)
161    return;
162
163  pp::Var web_session_id_var(web_session_id_arg);
164  if (!web_session_id_var.is_string())
165    return;
166
167  static_cast<ContentDecryptor_Private*>(object)
168      ->GetUsableKeyIds(promise_id, web_session_id_var.AsString());
169}
170
171void Decrypt(PP_Instance instance,
172             PP_Resource encrypted_resource,
173             const PP_EncryptedBlockInfo* encrypted_block_info) {
174  pp::Buffer_Dev encrypted_block(encrypted_resource);
175
176  void* object =
177      Instance::GetPerInstanceObject(instance, kPPPContentDecryptorInterface);
178  if (!object)
179    return;
180
181  static_cast<ContentDecryptor_Private*>(object)->Decrypt(
182      encrypted_block,
183      *encrypted_block_info);
184}
185
186void InitializeAudioDecoder(
187    PP_Instance instance,
188    const PP_AudioDecoderConfig* decoder_config,
189    PP_Resource extra_data_resource) {
190  pp::Buffer_Dev extra_data_buffer(extra_data_resource);
191
192  void* object =
193      Instance::GetPerInstanceObject(instance, kPPPContentDecryptorInterface);
194  if (!object)
195    return;
196
197  static_cast<ContentDecryptor_Private*>(object)->InitializeAudioDecoder(
198      *decoder_config,
199      extra_data_buffer);
200}
201
202void InitializeVideoDecoder(
203    PP_Instance instance,
204    const PP_VideoDecoderConfig* decoder_config,
205    PP_Resource extra_data_resource) {
206  pp::Buffer_Dev extra_data_buffer(extra_data_resource);
207
208  void* object =
209      Instance::GetPerInstanceObject(instance, kPPPContentDecryptorInterface);
210  if (!object)
211    return;
212
213  static_cast<ContentDecryptor_Private*>(object)->InitializeVideoDecoder(
214      *decoder_config,
215      extra_data_buffer);
216}
217
218void DeinitializeDecoder(PP_Instance instance,
219                         PP_DecryptorStreamType decoder_type,
220                         uint32_t request_id) {
221  void* object =
222      Instance::GetPerInstanceObject(instance, kPPPContentDecryptorInterface);
223  if (!object)
224    return;
225  static_cast<ContentDecryptor_Private*>(object)->DeinitializeDecoder(
226      decoder_type,
227      request_id);
228}
229
230void ResetDecoder(PP_Instance instance,
231                  PP_DecryptorStreamType decoder_type,
232                  uint32_t request_id) {
233  void* object =
234      Instance::GetPerInstanceObject(instance, kPPPContentDecryptorInterface);
235  if (!object)
236    return;
237  static_cast<ContentDecryptor_Private*>(object)->ResetDecoder(decoder_type,
238                                                               request_id);
239}
240
241void DecryptAndDecode(PP_Instance instance,
242                      PP_DecryptorStreamType decoder_type,
243                      PP_Resource encrypted_resource,
244                      const PP_EncryptedBlockInfo* encrypted_block_info) {
245  pp::Buffer_Dev encrypted_buffer(encrypted_resource);
246
247  void* object =
248      Instance::GetPerInstanceObject(instance, kPPPContentDecryptorInterface);
249  if (!object)
250    return;
251
252  static_cast<ContentDecryptor_Private*>(object)->DecryptAndDecode(
253      decoder_type,
254      encrypted_buffer,
255      *encrypted_block_info);
256}
257
258const PPP_ContentDecryptor_Private ppp_content_decryptor = {
259    &Initialize,
260    &SetServerCertificate,
261    &CreateSession,
262    &LoadSession,
263    &UpdateSession,
264    &CloseSession,
265    &RemoveSession,
266    &GetUsableKeyIds,
267    &Decrypt,
268    &InitializeAudioDecoder,
269    &InitializeVideoDecoder,
270    &DeinitializeDecoder,
271    &ResetDecoder,
272    &DecryptAndDecode};
273
274template <> const char* interface_name<PPB_ContentDecryptor_Private>() {
275  return PPB_CONTENTDECRYPTOR_PRIVATE_INTERFACE;
276}
277
278}  // namespace
279
280ContentDecryptor_Private::ContentDecryptor_Private(Instance* instance)
281    : associated_instance_(instance) {
282  Module::Get()->AddPluginInterface(kPPPContentDecryptorInterface,
283                                    &ppp_content_decryptor);
284  instance->AddPerInstanceObject(kPPPContentDecryptorInterface, this);
285}
286
287ContentDecryptor_Private::~ContentDecryptor_Private() {
288  Instance::RemovePerInstanceObject(associated_instance_,
289                                    kPPPContentDecryptorInterface,
290                                    this);
291}
292
293void ContentDecryptor_Private::PromiseResolved(uint32_t promise_id) {
294  if (has_interface<PPB_ContentDecryptor_Private>()) {
295    get_interface<PPB_ContentDecryptor_Private>()->PromiseResolved(
296        associated_instance_.pp_instance(), promise_id);
297  }
298}
299
300void ContentDecryptor_Private::PromiseResolvedWithSession(
301    uint32_t promise_id,
302    const std::string& web_session_id) {
303  if (has_interface<PPB_ContentDecryptor_Private>()) {
304    pp::Var web_session_id_var(web_session_id);
305    get_interface<PPB_ContentDecryptor_Private>()->PromiseResolvedWithSession(
306        associated_instance_.pp_instance(),
307        promise_id,
308        web_session_id_var.pp_var());
309  }
310}
311
312void ContentDecryptor_Private::PromiseResolvedWithKeyIds(
313    uint32_t promise_id,
314    const std::vector<std::vector<uint8_t> >& key_ids) {
315  if (has_interface<PPB_ContentDecryptor_Private>()) {
316    pp::VarArray key_ids_array = pp::VarArray();
317    key_ids_array.SetLength(key_ids.size());
318    for (size_t i = 0; i < key_ids.size(); ++i) {
319      const std::vector<uint8_t>& entry = key_ids[i];
320      pp::VarArrayBuffer array_buffer(entry.size());
321      memcpy(array_buffer.Map(), &entry[0], entry.size());
322      key_ids_array.Set(i, array_buffer);
323    }
324    get_interface<PPB_ContentDecryptor_Private>()->PromiseResolvedWithKeyIds(
325        associated_instance_.pp_instance(), promise_id, key_ids_array.pp_var());
326  }
327}
328
329void ContentDecryptor_Private::PromiseRejected(
330    uint32_t promise_id,
331    PP_CdmExceptionCode exception_code,
332    uint32_t system_code,
333    const std::string& error_description) {
334  if (has_interface<PPB_ContentDecryptor_Private>()) {
335    pp::Var error_description_var(error_description);
336    get_interface<PPB_ContentDecryptor_Private>()->PromiseRejected(
337        associated_instance_.pp_instance(),
338        promise_id,
339        exception_code,
340        system_code,
341        error_description_var.pp_var());
342  }
343}
344
345void ContentDecryptor_Private::SessionMessage(
346    const std::string& web_session_id,
347    pp::VarArrayBuffer message,
348    const std::string& destination_url) {
349  if (has_interface<PPB_ContentDecryptor_Private>()) {
350    pp::Var web_session_id_var(web_session_id);
351    pp::Var destination_url_var(destination_url);
352    get_interface<PPB_ContentDecryptor_Private>()->SessionMessage(
353        associated_instance_.pp_instance(),
354        web_session_id_var.pp_var(),
355        message.pp_var(),
356        destination_url_var.pp_var());
357  }
358}
359
360void ContentDecryptor_Private::SessionKeysChange(
361    const std::string& web_session_id,
362    bool has_additional_usable_key) {
363  if (has_interface<PPB_ContentDecryptor_Private>()) {
364    pp::Var web_session_id_var(web_session_id);
365    get_interface<PPB_ContentDecryptor_Private>()->SessionKeysChange(
366        associated_instance_.pp_instance(),
367        web_session_id_var.pp_var(),
368        PP_FromBool(has_additional_usable_key));
369  }
370}
371
372void ContentDecryptor_Private::SessionExpirationChange(
373    const std::string& web_session_id,
374    PP_Time new_expiry_time) {
375  if (has_interface<PPB_ContentDecryptor_Private>()) {
376    pp::Var web_session_id_var(web_session_id);
377    get_interface<PPB_ContentDecryptor_Private>()->SessionExpirationChange(
378        associated_instance_.pp_instance(),
379        web_session_id_var.pp_var(),
380        new_expiry_time);
381  }
382}
383
384void ContentDecryptor_Private::SessionReady(const std::string& web_session_id) {
385  if (has_interface<PPB_ContentDecryptor_Private>()) {
386    pp::Var web_session_id_var(web_session_id);
387    get_interface<PPB_ContentDecryptor_Private>()->SessionReady(
388        associated_instance_.pp_instance(), web_session_id_var.pp_var());
389  }
390}
391
392void ContentDecryptor_Private::SessionClosed(
393    const std::string& web_session_id) {
394  if (has_interface<PPB_ContentDecryptor_Private>()) {
395    pp::Var web_session_id_var(web_session_id);
396    get_interface<PPB_ContentDecryptor_Private>()->SessionClosed(
397        associated_instance_.pp_instance(), web_session_id_var.pp_var());
398  }
399}
400
401void ContentDecryptor_Private::SessionError(
402    const std::string& web_session_id,
403    PP_CdmExceptionCode exception_code,
404    uint32_t system_code,
405    const std::string& error_description) {
406  if (has_interface<PPB_ContentDecryptor_Private>()) {
407    pp::Var web_session_id_var(web_session_id);
408    pp::Var error_description_var(error_description);
409    get_interface<PPB_ContentDecryptor_Private>()->SessionError(
410        associated_instance_.pp_instance(),
411        web_session_id_var.pp_var(),
412        exception_code,
413        system_code,
414        error_description_var.pp_var());
415  }
416}
417
418void ContentDecryptor_Private::DeliverBlock(
419    pp::Buffer_Dev decrypted_block,
420    const PP_DecryptedBlockInfo& decrypted_block_info) {
421  if (has_interface<PPB_ContentDecryptor_Private>()) {
422    get_interface<PPB_ContentDecryptor_Private>()->DeliverBlock(
423        associated_instance_.pp_instance(),
424        decrypted_block.pp_resource(),
425        &decrypted_block_info);
426  }
427}
428
429void ContentDecryptor_Private::DecoderInitializeDone(
430    PP_DecryptorStreamType decoder_type,
431    uint32_t request_id,
432    bool success) {
433  if (has_interface<PPB_ContentDecryptor_Private>()) {
434    get_interface<PPB_ContentDecryptor_Private>()->DecoderInitializeDone(
435        associated_instance_.pp_instance(),
436        decoder_type,
437        request_id,
438        PP_FromBool(success));
439  }
440}
441
442void ContentDecryptor_Private::DecoderDeinitializeDone(
443    PP_DecryptorStreamType decoder_type,
444    uint32_t request_id) {
445  if (has_interface<PPB_ContentDecryptor_Private>()) {
446    get_interface<PPB_ContentDecryptor_Private>()->DecoderDeinitializeDone(
447        associated_instance_.pp_instance(),
448        decoder_type,
449        request_id);
450  }
451}
452
453void ContentDecryptor_Private::DecoderResetDone(
454    PP_DecryptorStreamType decoder_type,
455    uint32_t request_id) {
456  if (has_interface<PPB_ContentDecryptor_Private>()) {
457    get_interface<PPB_ContentDecryptor_Private>()->DecoderResetDone(
458        associated_instance_.pp_instance(),
459        decoder_type,
460        request_id);
461  }
462}
463
464void ContentDecryptor_Private::DeliverFrame(
465    pp::Buffer_Dev decrypted_frame,
466    const PP_DecryptedFrameInfo& decrypted_frame_info) {
467  if (has_interface<PPB_ContentDecryptor_Private>()) {
468    get_interface<PPB_ContentDecryptor_Private>()->DeliverFrame(
469        associated_instance_.pp_instance(),
470        decrypted_frame.pp_resource(),
471        &decrypted_frame_info);
472  }
473}
474
475void ContentDecryptor_Private::DeliverSamples(
476    pp::Buffer_Dev audio_frames,
477    const PP_DecryptedSampleInfo& decrypted_sample_info) {
478  if (has_interface<PPB_ContentDecryptor_Private>()) {
479    get_interface<PPB_ContentDecryptor_Private>()->DeliverSamples(
480        associated_instance_.pp_instance(),
481        audio_frames.pp_resource(),
482        &decrypted_sample_info);
483  }
484}
485
486}  // namespace pp
487