[ServiceWorker] Implement WebServiceWorkerContextClient::openWindow().
[chromium-blink-merge.git] / content / renderer / media / crypto / ppapi_decryptor.cc
blobed13dc0d04a18aa2a16969ecbed7c33f92f100dd
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.
5 #include "content/renderer/media/crypto/ppapi_decryptor.h"
7 #include <string>
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/message_loop/message_loop_proxy.h"
13 #include "content/renderer/pepper/content_decryptor_delegate.h"
14 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
15 #include "media/base/audio_decoder_config.h"
16 #include "media/base/cdm_key_information.h"
17 #include "media/base/data_buffer.h"
18 #include "media/base/decoder_buffer.h"
19 #include "media/base/key_systems.h"
20 #include "media/base/video_decoder_config.h"
21 #include "media/base/video_frame.h"
23 namespace content {
25 scoped_ptr<PpapiDecryptor> PpapiDecryptor::Create(
26 const std::string& key_system,
27 const GURL& security_origin,
28 const CreatePepperCdmCB& create_pepper_cdm_cb,
29 const media::SessionMessageCB& session_message_cb,
30 const media::SessionClosedCB& session_closed_cb,
31 const media::SessionErrorCB& session_error_cb,
32 const media::SessionKeysChangeCB& session_keys_change_cb,
33 const media::SessionExpirationUpdateCB& session_expiration_update_cb) {
34 std::string plugin_type = media::GetPepperType(key_system);
35 DCHECK(!plugin_type.empty());
36 scoped_ptr<PepperCdmWrapper> pepper_cdm_wrapper =
37 create_pepper_cdm_cb.Run(plugin_type, security_origin);
38 if (!pepper_cdm_wrapper) {
39 DLOG(ERROR) << "Plugin instance creation failed.";
40 return scoped_ptr<PpapiDecryptor>();
43 return scoped_ptr<PpapiDecryptor>(
44 new PpapiDecryptor(key_system,
45 pepper_cdm_wrapper.Pass(),
46 session_message_cb,
47 session_closed_cb,
48 session_error_cb,
49 session_keys_change_cb,
50 session_expiration_update_cb));
53 PpapiDecryptor::PpapiDecryptor(
54 const std::string& key_system,
55 scoped_ptr<PepperCdmWrapper> pepper_cdm_wrapper,
56 const media::SessionMessageCB& session_message_cb,
57 const media::SessionClosedCB& session_closed_cb,
58 const media::SessionErrorCB& session_error_cb,
59 const media::SessionKeysChangeCB& session_keys_change_cb,
60 const media::SessionExpirationUpdateCB& session_expiration_update_cb)
61 : pepper_cdm_wrapper_(pepper_cdm_wrapper.Pass()),
62 session_message_cb_(session_message_cb),
63 session_closed_cb_(session_closed_cb),
64 session_error_cb_(session_error_cb),
65 session_keys_change_cb_(session_keys_change_cb),
66 session_expiration_update_cb_(session_expiration_update_cb),
67 render_loop_proxy_(base::MessageLoopProxy::current()),
68 weak_ptr_factory_(this) {
69 DCHECK(pepper_cdm_wrapper_.get());
70 DCHECK(!session_message_cb_.is_null());
71 DCHECK(!session_closed_cb_.is_null());
72 DCHECK(!session_error_cb_.is_null());
73 DCHECK(!session_keys_change_cb.is_null());
74 DCHECK(!session_expiration_update_cb.is_null());
76 base::WeakPtr<PpapiDecryptor> weak_this = weak_ptr_factory_.GetWeakPtr();
77 CdmDelegate()->Initialize(
78 key_system,
79 base::Bind(&PpapiDecryptor::OnSessionMessage, weak_this),
80 base::Bind(&PpapiDecryptor::OnSessionClosed, weak_this),
81 base::Bind(&PpapiDecryptor::OnSessionError, weak_this),
82 base::Bind(&PpapiDecryptor::OnSessionKeysChange, weak_this),
83 base::Bind(&PpapiDecryptor::OnSessionExpirationUpdate, weak_this),
84 base::Bind(&PpapiDecryptor::OnFatalPluginError, weak_this));
87 PpapiDecryptor::~PpapiDecryptor() {
88 pepper_cdm_wrapper_.reset();
91 void PpapiDecryptor::SetServerCertificate(
92 const uint8* certificate_data,
93 int certificate_data_length,
94 scoped_ptr<media::SimpleCdmPromise> promise) {
95 DVLOG(2) << __FUNCTION__;
96 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
98 if (!CdmDelegate()) {
99 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist.");
100 return;
103 CdmDelegate()->SetServerCertificate(
104 certificate_data, certificate_data_length, promise.Pass());
107 void PpapiDecryptor::CreateSessionAndGenerateRequest(
108 SessionType session_type,
109 const std::string& init_data_type,
110 const uint8* init_data,
111 int init_data_length,
112 scoped_ptr<media::NewSessionCdmPromise> promise) {
113 DVLOG(2) << __FUNCTION__;
114 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
116 if (!CdmDelegate()) {
117 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist.");
118 return;
121 CdmDelegate()->CreateSessionAndGenerateRequest(session_type, init_data_type,
122 init_data, init_data_length,
123 promise.Pass());
126 void PpapiDecryptor::LoadSession(
127 SessionType session_type,
128 const std::string& session_id,
129 scoped_ptr<media::NewSessionCdmPromise> promise) {
130 DVLOG(2) << __FUNCTION__;
131 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
133 if (!CdmDelegate()) {
134 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist.");
135 return;
137 CdmDelegate()->LoadSession(session_type, session_id, promise.Pass());
140 void PpapiDecryptor::UpdateSession(
141 const std::string& session_id,
142 const uint8* response,
143 int response_length,
144 scoped_ptr<media::SimpleCdmPromise> promise) {
145 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
147 if (!CdmDelegate()) {
148 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist.");
149 return;
151 CdmDelegate()->UpdateSession(session_id, response, response_length,
152 promise.Pass());
155 void PpapiDecryptor::CloseSession(const std::string& session_id,
156 scoped_ptr<media::SimpleCdmPromise> promise) {
157 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
159 if (!CdmDelegate()) {
160 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist.");
161 return;
164 CdmDelegate()->CloseSession(session_id, promise.Pass());
167 void PpapiDecryptor::RemoveSession(
168 const std::string& session_id,
169 scoped_ptr<media::SimpleCdmPromise> promise) {
170 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
172 if (!CdmDelegate()) {
173 promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist.");
174 return;
177 CdmDelegate()->RemoveSession(session_id, promise.Pass());
180 media::CdmContext* PpapiDecryptor::GetCdmContext() {
181 return this;
184 media::Decryptor* PpapiDecryptor::GetDecryptor() {
185 return this;
188 void PpapiDecryptor::RegisterNewKeyCB(StreamType stream_type,
189 const NewKeyCB& new_key_cb) {
190 if (!render_loop_proxy_->BelongsToCurrentThread()) {
191 render_loop_proxy_->PostTask(FROM_HERE,
192 base::Bind(&PpapiDecryptor::RegisterNewKeyCB,
193 weak_ptr_factory_.GetWeakPtr(),
194 stream_type,
195 new_key_cb));
196 return;
199 DVLOG(3) << __FUNCTION__ << " - stream_type: " << stream_type;
200 switch (stream_type) {
201 case kAudio:
202 new_audio_key_cb_ = new_key_cb;
203 break;
204 case kVideo:
205 new_video_key_cb_ = new_key_cb;
206 break;
207 default:
208 NOTREACHED();
212 void PpapiDecryptor::Decrypt(
213 StreamType stream_type,
214 const scoped_refptr<media::DecoderBuffer>& encrypted,
215 const DecryptCB& decrypt_cb) {
216 if (!render_loop_proxy_->BelongsToCurrentThread()) {
217 render_loop_proxy_->PostTask(FROM_HERE,
218 base::Bind(&PpapiDecryptor::Decrypt,
219 weak_ptr_factory_.GetWeakPtr(),
220 stream_type,
221 encrypted,
222 decrypt_cb));
223 return;
226 DVLOG(3) << __FUNCTION__ << " - stream_type: " << stream_type;
227 if (!CdmDelegate() ||
228 !CdmDelegate()->Decrypt(stream_type, encrypted, decrypt_cb)) {
229 decrypt_cb.Run(kError, NULL);
233 void PpapiDecryptor::CancelDecrypt(StreamType stream_type) {
234 if (!render_loop_proxy_->BelongsToCurrentThread()) {
235 render_loop_proxy_->PostTask(FROM_HERE,
236 base::Bind(&PpapiDecryptor::CancelDecrypt,
237 weak_ptr_factory_.GetWeakPtr(),
238 stream_type));
239 return;
242 DVLOG(1) << __FUNCTION__ << " - stream_type: " << stream_type;
243 if (CdmDelegate())
244 CdmDelegate()->CancelDecrypt(stream_type);
247 void PpapiDecryptor::InitializeAudioDecoder(
248 const media::AudioDecoderConfig& config,
249 const DecoderInitCB& init_cb) {
250 if (!render_loop_proxy_->BelongsToCurrentThread()) {
251 render_loop_proxy_->PostTask(
252 FROM_HERE,
253 base::Bind(&PpapiDecryptor::InitializeAudioDecoder,
254 weak_ptr_factory_.GetWeakPtr(),
255 config,
256 init_cb));
257 return;
260 DVLOG(2) << __FUNCTION__;
261 DCHECK(config.is_encrypted());
262 DCHECK(config.IsValidConfig());
264 audio_decoder_init_cb_ = init_cb;
265 if (!CdmDelegate() || !CdmDelegate()->InitializeAudioDecoder(
266 config,
267 base::Bind(&PpapiDecryptor::OnDecoderInitialized,
268 weak_ptr_factory_.GetWeakPtr(),
269 kAudio))) {
270 base::ResetAndReturn(&audio_decoder_init_cb_).Run(false);
271 return;
275 void PpapiDecryptor::InitializeVideoDecoder(
276 const media::VideoDecoderConfig& config,
277 const DecoderInitCB& init_cb) {
278 if (!render_loop_proxy_->BelongsToCurrentThread()) {
279 render_loop_proxy_->PostTask(
280 FROM_HERE,
281 base::Bind(&PpapiDecryptor::InitializeVideoDecoder,
282 weak_ptr_factory_.GetWeakPtr(),
283 config,
284 init_cb));
285 return;
288 DVLOG(2) << __FUNCTION__;
289 DCHECK(config.is_encrypted());
290 DCHECK(config.IsValidConfig());
292 video_decoder_init_cb_ = init_cb;
293 if (!CdmDelegate() || !CdmDelegate()->InitializeVideoDecoder(
294 config,
295 base::Bind(&PpapiDecryptor::OnDecoderInitialized,
296 weak_ptr_factory_.GetWeakPtr(),
297 kVideo))) {
298 base::ResetAndReturn(&video_decoder_init_cb_).Run(false);
299 return;
303 void PpapiDecryptor::DecryptAndDecodeAudio(
304 const scoped_refptr<media::DecoderBuffer>& encrypted,
305 const AudioDecodeCB& audio_decode_cb) {
306 if (!render_loop_proxy_->BelongsToCurrentThread()) {
307 render_loop_proxy_->PostTask(
308 FROM_HERE,
309 base::Bind(&PpapiDecryptor::DecryptAndDecodeAudio,
310 weak_ptr_factory_.GetWeakPtr(),
311 encrypted,
312 audio_decode_cb));
313 return;
316 DVLOG(3) << __FUNCTION__;
317 if (!CdmDelegate() ||
318 !CdmDelegate()->DecryptAndDecodeAudio(encrypted, audio_decode_cb)) {
319 audio_decode_cb.Run(kError, AudioFrames());
323 void PpapiDecryptor::DecryptAndDecodeVideo(
324 const scoped_refptr<media::DecoderBuffer>& encrypted,
325 const VideoDecodeCB& video_decode_cb) {
326 if (!render_loop_proxy_->BelongsToCurrentThread()) {
327 render_loop_proxy_->PostTask(
328 FROM_HERE,
329 base::Bind(&PpapiDecryptor::DecryptAndDecodeVideo,
330 weak_ptr_factory_.GetWeakPtr(),
331 encrypted,
332 video_decode_cb));
333 return;
336 DVLOG(3) << __FUNCTION__;
337 if (!CdmDelegate() ||
338 !CdmDelegate()->DecryptAndDecodeVideo(encrypted, video_decode_cb)) {
339 video_decode_cb.Run(kError, NULL);
343 void PpapiDecryptor::ResetDecoder(StreamType stream_type) {
344 if (!render_loop_proxy_->BelongsToCurrentThread()) {
345 render_loop_proxy_->PostTask(FROM_HERE,
346 base::Bind(&PpapiDecryptor::ResetDecoder,
347 weak_ptr_factory_.GetWeakPtr(),
348 stream_type));
349 return;
352 DVLOG(2) << __FUNCTION__ << " - stream_type: " << stream_type;
353 if (CdmDelegate())
354 CdmDelegate()->ResetDecoder(stream_type);
357 void PpapiDecryptor::DeinitializeDecoder(StreamType stream_type) {
358 if (!render_loop_proxy_->BelongsToCurrentThread()) {
359 render_loop_proxy_->PostTask(
360 FROM_HERE,
361 base::Bind(&PpapiDecryptor::DeinitializeDecoder,
362 weak_ptr_factory_.GetWeakPtr(),
363 stream_type));
364 return;
367 DVLOG(2) << __FUNCTION__ << " - stream_type: " << stream_type;
368 if (CdmDelegate())
369 CdmDelegate()->DeinitializeDecoder(stream_type);
372 void PpapiDecryptor::OnDecoderInitialized(StreamType stream_type,
373 bool success) {
374 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
375 switch (stream_type) {
376 case kAudio:
377 DCHECK(!audio_decoder_init_cb_.is_null());
378 base::ResetAndReturn(&audio_decoder_init_cb_).Run(success);
379 break;
380 case kVideo:
381 DCHECK(!video_decoder_init_cb_.is_null());
382 base::ResetAndReturn(&video_decoder_init_cb_).Run(success);
383 break;
384 default:
385 NOTREACHED();
389 void PpapiDecryptor::OnSessionMessage(const std::string& session_id,
390 MessageType message_type,
391 const std::vector<uint8>& message,
392 const GURL& legacy_destination_url) {
393 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
394 session_message_cb_.Run(session_id, message_type, message,
395 legacy_destination_url);
398 void PpapiDecryptor::OnSessionKeysChange(const std::string& session_id,
399 bool has_additional_usable_key,
400 media::CdmKeysInfo keys_info) {
401 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
403 // TODO(jrummell): Handling resume playback should be done in the media
404 // player, not in the Decryptors. http://crbug.com/413413.
405 if (has_additional_usable_key)
406 AttemptToResumePlayback();
408 session_keys_change_cb_.Run(session_id, has_additional_usable_key,
409 keys_info.Pass());
412 void PpapiDecryptor::OnSessionExpirationUpdate(
413 const std::string& session_id,
414 const base::Time& new_expiry_time) {
415 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
416 session_expiration_update_cb_.Run(session_id, new_expiry_time);
419 void PpapiDecryptor::OnSessionClosed(const std::string& session_id) {
420 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
421 session_closed_cb_.Run(session_id);
424 void PpapiDecryptor::OnSessionError(const std::string& session_id,
425 MediaKeys::Exception exception_code,
426 uint32 system_code,
427 const std::string& error_description) {
428 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
429 session_error_cb_.Run(session_id, exception_code, system_code,
430 error_description);
433 void PpapiDecryptor::AttemptToResumePlayback() {
434 if (!new_audio_key_cb_.is_null())
435 new_audio_key_cb_.Run();
437 if (!new_video_key_cb_.is_null())
438 new_video_key_cb_.Run();
441 void PpapiDecryptor::OnFatalPluginError() {
442 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
443 pepper_cdm_wrapper_.reset();
446 ContentDecryptorDelegate* PpapiDecryptor::CdmDelegate() {
447 DCHECK(render_loop_proxy_->BelongsToCurrentThread());
448 return (pepper_cdm_wrapper_) ? pepper_cdm_wrapper_->GetCdmDelegate() : NULL;
451 } // namespace content