summaryrefslogtreecommitdiffstats
path: root/media/cdm/ppapi/cdm_adapter.h
blob: ef7bc20b9acf98e74e3da205d70db4f4e424242a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MEDIA_CDM_PPAPI_CDM_ADAPTER_H_
#define MEDIA_CDM_PPAPI_CDM_ADAPTER_H_

#include <string>
#include <vector>

#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "build/build_config.h"
#include "media/cdm/ppapi/api/content_decryption_module.h"
#include "media/cdm/ppapi/cdm_helpers.h"
#include "media/cdm/ppapi/cdm_wrapper.h"
#include "media/cdm/ppapi/linked_ptr.h"
#include "ppapi/c/pp_stdint.h"
#include "ppapi/c/private/pp_content_decryptor.h"
#include "ppapi/cpp/completion_callback.h"
#include "ppapi/cpp/private/content_decryptor_private.h"
#include "ppapi/cpp/var.h"
#include "ppapi/cpp/var_array_buffer.h"
#include "ppapi/utility/completion_callback_factory.h"

#if defined(OS_CHROMEOS)
#include "ppapi/cpp/private/output_protection_private.h"
#include "ppapi/cpp/private/platform_verification.h"
#endif

namespace media {

// GetCdmHostFunc implementation.
void* GetCdmHost(int host_interface_version, void* user_data);

// An adapter class for abstracting away PPAPI interaction and threading for a
// Content Decryption Module (CDM).
class CdmAdapter : public pp::Instance,
                   public pp::ContentDecryptor_Private,
                   public cdm::Host_6,
                   public cdm::Host_7 {
 public:
  CdmAdapter(PP_Instance instance, pp::Module* module);
  virtual ~CdmAdapter();

  // pp::Instance implementation.
  virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
    return true;
  }

  // PPP_ContentDecryptor_Private implementation.
  // Note: Results of calls to these methods must be reported through the
  // PPB_ContentDecryptor_Private interface.
  void Initialize(const std::string& key_system) override;
  void SetServerCertificate(uint32_t promise_id,
                            pp::VarArrayBuffer server_certificate) override;
  void CreateSessionAndGenerateRequest(uint32_t promise_id,
                                       PP_SessionType session_type,
                                       const std::string& init_data_type,
                                       pp::VarArrayBuffer init_data) override;
  void LoadSession(uint32_t promise_id,
                   PP_SessionType session_type,
                   const std::string& session_id) override;
  void UpdateSession(uint32_t promise_id,
                     const std::string& session_id,
                     pp::VarArrayBuffer response) override;
  void CloseSession(uint32_t promise_id, const std::string& session_id);
  void RemoveSession(uint32_t promise_id,
                     const std::string& session_id) override;
  void Decrypt(pp::Buffer_Dev encrypted_buffer,
               const PP_EncryptedBlockInfo& encrypted_block_info) override;
  void InitializeAudioDecoder(const PP_AudioDecoderConfig& decoder_config,
                              pp::Buffer_Dev extra_data_buffer) override;
  void InitializeVideoDecoder(const PP_VideoDecoderConfig& decoder_config,
                              pp::Buffer_Dev extra_data_buffer) override;
  void DeinitializeDecoder(PP_DecryptorStreamType decoder_type,
                           uint32_t request_id) override;
  void ResetDecoder(PP_DecryptorStreamType decoder_type,
                    uint32_t request_id) override;
  void DecryptAndDecode(
      PP_DecryptorStreamType decoder_type,
      pp::Buffer_Dev encrypted_buffer,
      const PP_EncryptedBlockInfo& encrypted_block_info) override;

  // cdm::Host_6 and cdm::Host_7 implementation.
  cdm::Buffer* Allocate(uint32_t capacity) override;
  void SetTimer(int64_t delay_ms, void* context) override;
  cdm::Time GetCurrentWallTime() override;
  void OnResolveNewSessionPromise(uint32_t promise_id,
                                  const char* session_id,
                                  uint32_t session_id_size) override;
  void OnResolvePromise(uint32_t promise_id) override;
  void OnRejectPromise(uint32_t promise_id,
                       cdm::Error error,
                       uint32_t system_code,
                       const char* error_message,
                       uint32_t error_message_size) override;
  void OnExpirationChange(const char* session_id,
                          uint32_t session_id_size,
                          cdm::Time new_expiry_time) override;
  void OnSessionClosed(const char* session_id,
                       uint32_t session_id_size) override;
  void SendPlatformChallenge(const char* service_id,
                             uint32_t service_id_size,
                             const char* challenge,
                             uint32_t challenge_size) override;
  void EnableOutputProtection(uint32_t desired_protection_mask) override;
  void QueryOutputProtectionStatus() override;
  void OnDeferredInitializationDone(cdm::StreamType stream_type,
                                    cdm::Status decoder_status) override;
  cdm::FileIO* CreateFileIO(cdm::FileIOClient* client) override;

  // cdm::Host_7 implementation.
  void OnSessionMessage(const char* session_id,
                        uint32_t session_id_size,
                        cdm::MessageType message_type,
                        const char* message,
                        uint32_t message_size) override;
  void OnSessionKeysChange(const char* session_id,
                           uint32_t session_id_size,
                           bool has_additional_usable_key,
                           const cdm::KeyInformation* keys_info,
                           uint32_t keys_info_count) override;
  void OnLegacySessionError(const char* session_id,
                            uint32_t session_id_size,
                            cdm::Error error,
                            uint32_t system_code,
                            const char* error_message,
                            uint32_t error_message_size) override;

  // cdm::Host_6 implementation.
  void OnResolveKeyIdsPromise(uint32_t promise_id,
                              const cdm::BinaryData* usable_key_ids,
                              uint32_t usable_key_ids_size) override;
  void OnSessionMessage(const char* session_id,
                        uint32_t session_id_size,
                        const char* message,
                        uint32_t message_size,
                        const char* destination_url,
                        uint32_t destination_url_size) override;
  void OnSessionUsableKeysChange(const char* session_id,
                                 uint32_t session_id_size,
                                 bool has_additional_usable_key) override;
  void OnSessionError(const char* session_id,
                      uint32_t session_id_size,
                      cdm::Error error,
                      uint32_t system_code,
                      const char* error_message,
                      uint32_t error_message_size) override;

 private:
  // These are reported to UMA server. Do not change the existing values!
  enum OutputProtectionStatus {
    OUTPUT_PROTECTION_QUERIED = 0,
    OUTPUT_PROTECTION_NO_EXTERNAL_LINK = 1,
    OUTPUT_PROTECTION_ALL_EXTERNAL_LINKS_PROTECTED = 2,
    OUTPUT_PROTECTION_MAX = 3
  };

  typedef linked_ptr<DecryptedBlockImpl> LinkedDecryptedBlock;
  typedef linked_ptr<VideoFrameImpl> LinkedVideoFrame;
  typedef linked_ptr<AudioFramesImpl> LinkedAudioFrames;

  struct SessionError {
    SessionError(cdm::Error error,
                 uint32_t system_code,
                 std::string error_description);
    cdm::Error error;
    uint32_t system_code;
    std::string error_description;
  };

  bool CreateCdmInstance(const std::string& key_system);

  // <code>PPB_ContentDecryptor_Private</code> dispatchers. These are passed to
  // <code>callback_factory_</code> to ensure that calls into
  // <code>PPP_ContentDecryptor_Private</code> are asynchronous.
  void SendPromiseResolvedInternal(int32_t result, uint32_t promise_id);
  void SendPromiseResolvedWithSessionInternal(int32_t result,
                                              uint32_t promise_id,
                                              const std::string& session_id);
  void SendPromiseRejectedInternal(int32_t result,
                                   uint32_t promise_id,
                                   const SessionError& error);
  void SendSessionMessageInternal(int32_t result,
                                  const std::string& session_id,
                                  cdm::MessageType message_type,
                                  const std::vector<uint8_t>& message);
  void SendSessionClosedInternal(int32_t result, const std::string& session_id);
  void SendSessionErrorInternal(int32_t result,
                                const std::string& session_id,
                                const SessionError& error);
  void SendSessionKeysChangeInternal(
      int32_t result,
      const std::string& session_id,
      bool has_additional_usable_key,
      const std::vector<PP_KeyInformation>& key_info);
  void SendExpirationChangeInternal(int32_t result,
                                    const std::string& session_id,
                                    cdm::Time new_expiry_time);
  void RejectPromise(uint32_t promise_id,
                     cdm::Error error,
                     uint32_t system_code,
                     const std::string& error_message);

  void DeliverBlock(int32_t result,
                    const cdm::Status& status,
                    const LinkedDecryptedBlock& decrypted_block,
                    const PP_DecryptTrackingInfo& tracking_info);
  void DecoderInitializeDone(int32_t result,
                             PP_DecryptorStreamType decoder_type,
                             uint32_t request_id,
                             bool success);
  void DecoderDeinitializeDone(int32_t result,
                               PP_DecryptorStreamType decoder_type,
                               uint32_t request_id);
  void DecoderResetDone(int32_t result,
                        PP_DecryptorStreamType decoder_type,
                        uint32_t request_id);
  void DeliverFrame(int32_t result,
                    const cdm::Status& status,
                    const LinkedVideoFrame& video_frame,
                    const PP_DecryptTrackingInfo& tracking_info);
  void DeliverSamples(int32_t result,
                      const cdm::Status& status,
                      const LinkedAudioFrames& audio_frames,
                      const PP_DecryptTrackingInfo& tracking_info);

  // Helper for SetTimer().
  void TimerExpired(int32_t result, void* context);

  bool IsValidVideoFrame(const LinkedVideoFrame& video_frame);

  // Callback to report |file_size_bytes| of the first file read by FileIO.
  void OnFirstFileRead(int32_t file_size_bytes);

#if !defined(NDEBUG)
  // Logs the given message to the JavaScript console associated with the
  // CDM adapter instance. The name of the CDM adapter issuing the log message
  // will be automatically prepended to the message.
  void LogToConsole(const pp::Var& value);
#endif  // !defined(NDEBUG)

#if defined(OS_CHROMEOS)
  void ReportOutputProtectionUMA(OutputProtectionStatus status);
  void ReportOutputProtectionQuery();
  void ReportOutputProtectionQueryResult();

  struct PepperPlatformChallengeResponse {
    pp::Var signed_data;
    pp::Var signed_data_signature;
    pp::Var platform_key_certificate;
  };

  void SendPlatformChallengeDone(
      int32_t result,
      const linked_ptr<PepperPlatformChallengeResponse>& response);
  void EnableProtectionDone(int32_t result);
  void QueryOutputProtectionStatusDone(int32_t result);

  pp::OutputProtection_Private output_protection_;
  pp::PlatformVerification platform_verification_;

  // Same as above, these are only read by QueryOutputProtectionStatusDone().
  uint32_t output_link_mask_;
  uint32_t output_protection_mask_;
  bool query_output_protection_in_progress_;

  // Tracks whether an output protection query and a positive query result (no
  // unprotected external link) have been reported to UMA.
  bool uma_for_output_protection_query_reported_;
  bool uma_for_output_protection_positive_result_reported_;
#endif

  PpbBufferAllocator allocator_;
  pp::CompletionCallbackFactory<CdmAdapter> callback_factory_;
  linked_ptr<CdmWrapper> cdm_;
  std::string key_system_;

  // If the CDM returned kDeferredInitialization during InitializeAudioDecoder()
  // or InitializeVideoDecoder(), the (Audio|Video)DecoderConfig.request_id is
  // saved for the future call to OnDeferredInitializationDone().
  bool deferred_initialize_audio_decoder_;
  uint32_t deferred_audio_decoder_config_id_;
  bool deferred_initialize_video_decoder_;
  uint32_t deferred_video_decoder_config_id_;

  uint32_t last_read_file_size_kb_;
  bool file_size_uma_reported_;

  DISALLOW_COPY_AND_ASSIGN(CdmAdapter);
};

}  // namespace media

#endif  // MEDIA_CDM_PPAPI_CDM_ADAPTER_H_