1// Copyright 2013 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#ifndef MEDIA_CDM_PPAPI_CDM_ADAPTER_H_
6#define MEDIA_CDM_PPAPI_CDM_ADAPTER_H_
7
8#include <string>
9#include <vector>
10
11#include "base/basictypes.h"
12#include "base/compiler_specific.h"
13#include "build/build_config.h"
14#include "media/cdm/ppapi/api/content_decryption_module.h"
15#include "media/cdm/ppapi/cdm_helpers.h"
16#include "media/cdm/ppapi/cdm_wrapper.h"
17#include "media/cdm/ppapi/linked_ptr.h"
18#include "ppapi/c/pp_stdint.h"
19#include "ppapi/c/private/pp_content_decryptor.h"
20#include "ppapi/cpp/completion_callback.h"
21#include "ppapi/cpp/private/content_decryptor_private.h"
22#include "ppapi/cpp/var.h"
23#include "ppapi/cpp/var_array_buffer.h"
24#include "ppapi/utility/completion_callback_factory.h"
25
26#if defined(OS_CHROMEOS)
27#include "ppapi/cpp/private/output_protection_private.h"
28#include "ppapi/cpp/private/platform_verification.h"
29#endif
30
31namespace media {
32
33// GetCdmHostFunc implementation.
34void* GetCdmHost(int host_interface_version, void* user_data);
35
36// An adapter class for abstracting away PPAPI interaction and threading for a
37// Content Decryption Module (CDM).
38class CdmAdapter : public pp::Instance,
39                   public pp::ContentDecryptor_Private,
40                   public cdm::Host_4,
41                   public cdm::Host_6 {
42 public:
43  CdmAdapter(PP_Instance instance, pp::Module* module);
44  virtual ~CdmAdapter();
45
46  // pp::Instance implementation.
47  virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
48    return true;
49  }
50
51  // PPP_ContentDecryptor_Private implementation.
52  // Note: Results of calls to these methods must be reported through the
53  // PPB_ContentDecryptor_Private interface.
54  virtual void Initialize(const std::string& key_system) OVERRIDE;
55  virtual void SetServerCertificate(
56      uint32_t promise_id,
57      pp::VarArrayBuffer server_certificate) OVERRIDE;
58  virtual void CreateSession(uint32_t promise_id,
59                             const std::string& init_data_type,
60                             pp::VarArrayBuffer init_data,
61                             PP_SessionType session_type) OVERRIDE;
62  virtual void LoadSession(uint32_t promise_id,
63                           const std::string& web_session_id) OVERRIDE;
64  virtual void UpdateSession(uint32_t promise_id,
65                             const std::string& web_session_id,
66                             pp::VarArrayBuffer response) OVERRIDE;
67  virtual void CloseSession(uint32_t promise_id,
68                            const std::string& web_session_id);
69  virtual void RemoveSession(uint32_t promise_id,
70                             const std::string& web_session_id) OVERRIDE;
71  virtual void GetUsableKeyIds(uint32_t promise_id,
72                               const std::string& web_session_id) OVERRIDE;
73  virtual void Decrypt(
74      pp::Buffer_Dev encrypted_buffer,
75      const PP_EncryptedBlockInfo& encrypted_block_info) OVERRIDE;
76  virtual void InitializeAudioDecoder(
77      const PP_AudioDecoderConfig& decoder_config,
78      pp::Buffer_Dev extra_data_buffer) OVERRIDE;
79  virtual void InitializeVideoDecoder(
80      const PP_VideoDecoderConfig& decoder_config,
81      pp::Buffer_Dev extra_data_buffer) OVERRIDE;
82  virtual void DeinitializeDecoder(PP_DecryptorStreamType decoder_type,
83                                   uint32_t request_id) OVERRIDE;
84  virtual void ResetDecoder(PP_DecryptorStreamType decoder_type,
85                            uint32_t request_id) OVERRIDE;
86  virtual void DecryptAndDecode(
87      PP_DecryptorStreamType decoder_type,
88      pp::Buffer_Dev encrypted_buffer,
89      const PP_EncryptedBlockInfo& encrypted_block_info) OVERRIDE;
90
91  // cdm::Host_4 and cdm::Host_6 implementation.
92  virtual cdm::Buffer* Allocate(uint32_t capacity) OVERRIDE;
93  virtual void SetTimer(int64_t delay_ms, void* context) OVERRIDE;
94
95  // cdm::Host_4 implementation.
96  virtual double GetCurrentWallTimeInSeconds() OVERRIDE;
97  virtual void OnSessionCreated(uint32_t session_id,
98                                const char* web_session_id,
99                                uint32_t web_session_id_length) OVERRIDE;
100  virtual void OnSessionMessage(uint32_t session_id,
101                                const char* message,
102                                uint32_t message_length,
103                                const char* destination_url,
104                                uint32_t destination_url_length) OVERRIDE;
105  virtual void OnSessionReady(uint32_t session_id) OVERRIDE;
106  virtual void OnSessionClosed(uint32_t session_id) OVERRIDE;
107  virtual void OnSessionError(uint32_t session_id,
108                              cdm::MediaKeyError error_code,
109                              uint32_t system_code) OVERRIDE;
110
111  // cdm::Host_6 implementation.
112  virtual cdm::Time GetCurrentWallTime() OVERRIDE;
113  virtual void OnResolveNewSessionPromise(
114      uint32_t promise_id,
115      const char* web_session_id,
116      uint32_t web_session_id_length) OVERRIDE;
117  virtual void OnResolvePromise(uint32_t promise_id) OVERRIDE;
118  virtual void OnResolveKeyIdsPromise(uint32_t promise_id,
119                                      const cdm::BinaryData* usable_key_ids,
120                                      uint32_t usable_key_ids_length) OVERRIDE;
121  virtual void OnRejectPromise(uint32_t promise_id,
122                               cdm::Error error,
123                               uint32_t system_code,
124                               const char* error_message,
125                               uint32_t error_message_length) OVERRIDE;
126  virtual void OnSessionMessage(const char* web_session_id,
127                                uint32_t web_session_id_length,
128                                const char* message,
129                                uint32_t message_length,
130                                const char* destination_url,
131                                uint32_t destination_url_length) OVERRIDE;
132  virtual void OnSessionUsableKeysChange(
133      const char* web_session_id,
134      uint32_t web_session_id_length,
135      bool has_additional_usable_key) OVERRIDE;
136  virtual void OnExpirationChange(const char* web_session_id,
137                                  uint32_t web_session_id_length,
138                                  cdm::Time new_expiry_time) OVERRIDE;
139  virtual void OnSessionClosed(const char* web_session_id,
140                               uint32_t web_session_id_length) OVERRIDE;
141  virtual void OnSessionError(const char* web_session_id,
142                              uint32_t web_session_id_length,
143                              cdm::Error error,
144                              uint32_t system_code,
145                              const char* error_message,
146                              uint32_t error_message_length) OVERRIDE;
147
148  // cdm::Host_4 and cdm::Host_6 implementation.
149  virtual void SendPlatformChallenge(const char* service_id,
150                                     uint32_t service_id_length,
151                                     const char* challenge,
152                                     uint32_t challenge_length) OVERRIDE;
153  virtual void EnableOutputProtection(
154      uint32_t desired_protection_mask) OVERRIDE;
155  virtual void QueryOutputProtectionStatus() OVERRIDE;
156  virtual void OnDeferredInitializationDone(
157      cdm::StreamType stream_type,
158      cdm::Status decoder_status) OVERRIDE;
159  virtual cdm::FileIO* CreateFileIO(cdm::FileIOClient* client) OVERRIDE;
160
161 private:
162  // These are reported to UMA server. Do not change the existing values!
163  enum OutputProtectionStatus {
164    OUTPUT_PROTECTION_QUERIED = 0,
165    OUTPUT_PROTECTION_NO_EXTERNAL_LINK = 1,
166    OUTPUT_PROTECTION_ALL_EXTERNAL_LINKS_PROTECTED = 2,
167    OUTPUT_PROTECTION_MAX = 3
168  };
169
170  typedef linked_ptr<DecryptedBlockImpl> LinkedDecryptedBlock;
171  typedef linked_ptr<VideoFrameImpl> LinkedVideoFrame;
172  typedef linked_ptr<AudioFramesImpl> LinkedAudioFrames;
173
174  struct SessionError {
175    SessionError(cdm::Error error,
176                 uint32_t system_code,
177                 std::string error_description);
178    cdm::Error error;
179    uint32_t system_code;
180    std::string error_description;
181  };
182
183  bool CreateCdmInstance(const std::string& key_system);
184
185  // <code>PPB_ContentDecryptor_Private</code> dispatchers. These are passed to
186  // <code>callback_factory_</code> to ensure that calls into
187  // <code>PPP_ContentDecryptor_Private</code> are asynchronous.
188  void SendPromiseResolvedInternal(int32_t result, uint32_t promise_id);
189  void SendPromiseResolvedWithSessionInternal(
190      int32_t result,
191      uint32_t promise_id,
192      const std::string& web_session_id);
193  void SendPromiseResolvedWithUsableKeyIdsInternal(
194      int32_t result,
195      uint32_t promise_id,
196      std::vector<std::vector<uint8> > key_ids);
197  void SendPromiseRejectedInternal(int32_t result,
198                                   uint32_t promise_id,
199                                   const SessionError& error);
200  void SendSessionMessageInternal(int32_t result,
201                                  const std::string& web_session_id,
202                                  const std::vector<uint8>& message,
203                                  const std::string& destination_url);
204  void SendSessionReadyInternal(int32_t result,
205                                const std::string& web_session_id);
206  void SendSessionClosedInternal(int32_t result,
207                                 const std::string& web_session_id);
208  void SendSessionErrorInternal(int32_t result,
209                                const std::string& web_session_id,
210                                const SessionError& error);
211  void SendSessionUsableKeysChangeInternal(int32_t result,
212                                           const std::string& web_session_id,
213                                           bool has_additional_usable_key);
214  void SendExpirationChangeInternal(int32_t result,
215                                    const std::string& web_session_id,
216                                    cdm::Time new_expiry_time);
217  void RejectPromise(uint32_t promise_id,
218                     cdm::Error error,
219                     uint32_t system_code,
220                     const std::string& error_message);
221
222  void DeliverBlock(int32_t result,
223                    const cdm::Status& status,
224                    const LinkedDecryptedBlock& decrypted_block,
225                    const PP_DecryptTrackingInfo& tracking_info);
226  void DecoderInitializeDone(int32_t result,
227                             PP_DecryptorStreamType decoder_type,
228                             uint32_t request_id,
229                             bool success);
230  void DecoderDeinitializeDone(int32_t result,
231                               PP_DecryptorStreamType decoder_type,
232                               uint32_t request_id);
233  void DecoderResetDone(int32_t result,
234                        PP_DecryptorStreamType decoder_type,
235                        uint32_t request_id);
236  void DeliverFrame(int32_t result,
237                    const cdm::Status& status,
238                    const LinkedVideoFrame& video_frame,
239                    const PP_DecryptTrackingInfo& tracking_info);
240  void DeliverSamples(int32_t result,
241                      const cdm::Status& status,
242                      const LinkedAudioFrames& audio_frames,
243                      const PP_DecryptTrackingInfo& tracking_info);
244
245  // Helper for SetTimer().
246  void TimerExpired(int32_t result, void* context);
247
248  bool IsValidVideoFrame(const LinkedVideoFrame& video_frame);
249
250  // Callback to report |file_size_bytes| of the first file read by FileIO.
251  void OnFirstFileRead(int32_t file_size_bytes);
252
253#if !defined(NDEBUG)
254  // Logs the given message to the JavaScript console associated with the
255  // CDM adapter instance. The name of the CDM adapter issuing the log message
256  // will be automatically prepended to the message.
257  void LogToConsole(const pp::Var& value);
258#endif  // !defined(NDEBUG)
259
260#if defined(OS_CHROMEOS)
261  void ReportOutputProtectionUMA(OutputProtectionStatus status);
262  void ReportOutputProtectionQuery();
263  void ReportOutputProtectionQueryResult();
264
265  struct PepperPlatformChallengeResponse {
266    pp::Var signed_data;
267    pp::Var signed_data_signature;
268    pp::Var platform_key_certificate;
269  };
270
271  void SendPlatformChallengeDone(
272      int32_t result,
273      const linked_ptr<PepperPlatformChallengeResponse>& response);
274  void EnableProtectionDone(int32_t result);
275  void QueryOutputProtectionStatusDone(int32_t result);
276
277  pp::OutputProtection_Private output_protection_;
278  pp::PlatformVerification platform_verification_;
279
280  // Same as above, these are only read by QueryOutputProtectionStatusDone().
281  uint32_t output_link_mask_;
282  uint32_t output_protection_mask_;
283  bool query_output_protection_in_progress_;
284
285  // Tracks whether an output protection query and a positive query result (no
286  // unprotected external link) have been reported to UMA.
287  bool uma_for_output_protection_query_reported_;
288  bool uma_for_output_protection_positive_result_reported_;
289#endif
290
291  PpbBufferAllocator allocator_;
292  pp::CompletionCallbackFactory<CdmAdapter> callback_factory_;
293  linked_ptr<CdmWrapper> cdm_;
294  std::string key_system_;
295
296  // If the CDM returned kDeferredInitialization during InitializeAudioDecoder()
297  // or InitializeVideoDecoder(), the (Audio|Video)DecoderConfig.request_id is
298  // saved for the future call to OnDeferredInitializationDone().
299  bool deferred_initialize_audio_decoder_;
300  uint32_t deferred_audio_decoder_config_id_;
301  bool deferred_initialize_video_decoder_;
302  uint32_t deferred_video_decoder_config_id_;
303
304  uint32_t last_read_file_size_kb_;
305  bool file_size_uma_reported_;
306
307  DISALLOW_COPY_AND_ASSIGN(CdmAdapter);
308};
309
310}  // namespace media
311
312#endif  // MEDIA_CDM_PPAPI_CDM_ADAPTER_H_
313