OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/cdm/ppapi/external_clear_key/clear_key_cdm.h" | 5 #include "media/cdm/ppapi/external_clear_key/clear_key_cdm.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cstring> | 8 #include <cstring> |
9 #include <sstream> | 9 #include <sstream> |
10 | 10 |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 | 260 |
261 const char* GetCdmVersion() { | 261 const char* GetCdmVersion() { |
262 return kClearKeyCdmVersion; | 262 return kClearKeyCdmVersion; |
263 } | 263 } |
264 | 264 |
265 namespace media { | 265 namespace media { |
266 | 266 |
267 ClearKeyCdm::ClearKeyCdm(ClearKeyCdmHost* host, | 267 ClearKeyCdm::ClearKeyCdm(ClearKeyCdmHost* host, |
268 const std::string& key_system, | 268 const std::string& key_system, |
269 const GURL& origin) | 269 const GURL& origin) |
270 : decryptor_( | 270 : decryptor_(new AesDecryptor( |
271 origin, | 271 origin, |
272 base::Bind(&ClearKeyCdm::OnSessionMessage, base::Unretained(this)), | 272 base::Bind(&ClearKeyCdm::OnSessionMessage, base::Unretained(this)), |
273 base::Bind(&ClearKeyCdm::OnSessionClosed, base::Unretained(this)), | 273 base::Bind(&ClearKeyCdm::OnSessionClosed, base::Unretained(this)), |
274 base::Bind(&ClearKeyCdm::OnSessionKeysChange, | 274 base::Bind(&ClearKeyCdm::OnSessionKeysChange, |
275 base::Unretained(this))), | 275 base::Unretained(this)))), |
276 host_(host), | 276 host_(host), |
277 key_system_(key_system), | 277 key_system_(key_system), |
278 has_received_keys_change_event_for_emulated_loadsession_(false), | 278 has_received_keys_change_event_for_emulated_loadsession_(false), |
279 timer_delay_ms_(kInitialTimerDelayMs), | 279 timer_delay_ms_(kInitialTimerDelayMs), |
280 renewal_timer_set_(false) { | 280 renewal_timer_set_(false) { |
281 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) | 281 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) |
282 channel_count_ = 0; | 282 channel_count_ = 0; |
283 bits_per_channel_ = 0; | 283 bits_per_channel_ = 0; |
284 samples_per_second_ = 0; | 284 samples_per_second_ = 0; |
285 output_timestamp_base_in_microseconds_ = kNoTimestamp; | 285 output_timestamp_base_in_microseconds_ = kNoTimestamp; |
(...skipping 18 matching lines...) Expand all Loading... |
304 DVLOG(1) << __FUNCTION__; | 304 DVLOG(1) << __FUNCTION__; |
305 | 305 |
306 scoped_ptr<media::NewSessionCdmPromise> promise( | 306 scoped_ptr<media::NewSessionCdmPromise> promise( |
307 new media::CdmCallbackPromise<std::string>( | 307 new media::CdmCallbackPromise<std::string>( |
308 base::Bind(&ClearKeyCdm::OnSessionCreated, | 308 base::Bind(&ClearKeyCdm::OnSessionCreated, |
309 base::Unretained(this), | 309 base::Unretained(this), |
310 promise_id), | 310 promise_id), |
311 base::Bind(&ClearKeyCdm::OnPromiseFailed, | 311 base::Bind(&ClearKeyCdm::OnPromiseFailed, |
312 base::Unretained(this), | 312 base::Unretained(this), |
313 promise_id))); | 313 promise_id))); |
314 decryptor_.CreateSessionAndGenerateRequest( | 314 decryptor_->CreateSessionAndGenerateRequest( |
315 ConvertSessionType(session_type), ConvertInitDataType(init_data_type), | 315 ConvertSessionType(session_type), ConvertInitDataType(init_data_type), |
316 std::vector<uint8_t>(init_data, init_data + init_data_size), | 316 std::vector<uint8_t>(init_data, init_data + init_data_size), |
317 promise.Pass()); | 317 promise.Pass()); |
318 | 318 |
319 if (key_system_ == kExternalClearKeyFileIOTestKeySystem) | 319 if (key_system_ == kExternalClearKeyFileIOTestKeySystem) |
320 StartFileIOTest(); | 320 StartFileIOTest(); |
321 } | 321 } |
322 | 322 |
323 // Loads a emulated stored session. Currently only |kLoadableSessionId| | 323 // Loads a emulated stored session. Currently only |kLoadableSessionId| |
324 // (containing a |kLoadableSessionKey| for |kLoadableSessionKeyId|) is | 324 // (containing a |kLoadableSessionKey| for |kLoadableSessionKeyId|) is |
(...skipping 15 matching lines...) Expand all Loading... |
340 DCHECK(session_id_for_emulated_loadsession_.empty()); | 340 DCHECK(session_id_for_emulated_loadsession_.empty()); |
341 | 341 |
342 scoped_ptr<media::NewSessionCdmPromise> promise( | 342 scoped_ptr<media::NewSessionCdmPromise> promise( |
343 new media::CdmCallbackPromise<std::string>( | 343 new media::CdmCallbackPromise<std::string>( |
344 base::Bind(&ClearKeyCdm::OnSessionLoaded, | 344 base::Bind(&ClearKeyCdm::OnSessionLoaded, |
345 base::Unretained(this), | 345 base::Unretained(this), |
346 promise_id), | 346 promise_id), |
347 base::Bind(&ClearKeyCdm::OnPromiseFailed, | 347 base::Bind(&ClearKeyCdm::OnPromiseFailed, |
348 base::Unretained(this), | 348 base::Unretained(this), |
349 promise_id))); | 349 promise_id))); |
350 decryptor_.CreateSessionAndGenerateRequest( | 350 decryptor_->CreateSessionAndGenerateRequest( |
351 MediaKeys::TEMPORARY_SESSION, EmeInitDataType::WEBM, | 351 MediaKeys::TEMPORARY_SESSION, EmeInitDataType::WEBM, |
352 std::vector<uint8_t>(), promise.Pass()); | 352 std::vector<uint8_t>(), promise.Pass()); |
353 } | 353 } |
354 | 354 |
355 void ClearKeyCdm::UpdateSession(uint32 promise_id, | 355 void ClearKeyCdm::UpdateSession(uint32 promise_id, |
356 const char* session_id, | 356 const char* session_id, |
357 uint32_t session_id_length, | 357 uint32_t session_id_length, |
358 const uint8* response, | 358 const uint8* response, |
359 uint32 response_size) { | 359 uint32 response_size) { |
360 DVLOG(1) << __FUNCTION__; | 360 DVLOG(1) << __FUNCTION__; |
361 std::string web_session_str(session_id, session_id_length); | 361 std::string web_session_str(session_id, session_id_length); |
362 | 362 |
363 // If updating the loadable session, use the actual session id generated. | 363 // If updating the loadable session, use the actual session id generated. |
364 if (web_session_str == std::string(kLoadableSessionId)) | 364 if (web_session_str == std::string(kLoadableSessionId)) |
365 web_session_str = session_id_for_emulated_loadsession_; | 365 web_session_str = session_id_for_emulated_loadsession_; |
366 | 366 |
367 scoped_ptr<media::SimpleCdmPromise> promise(new media::CdmCallbackPromise<>( | 367 scoped_ptr<media::SimpleCdmPromise> promise(new media::CdmCallbackPromise<>( |
368 base::Bind(&ClearKeyCdm::OnPromiseResolved, base::Unretained(this), | 368 base::Bind(&ClearKeyCdm::OnPromiseResolved, base::Unretained(this), |
369 promise_id), | 369 promise_id), |
370 base::Bind(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this), | 370 base::Bind(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this), |
371 promise_id))); | 371 promise_id))); |
372 decryptor_.UpdateSession( | 372 decryptor_->UpdateSession( |
373 web_session_str, std::vector<uint8_t>(response, response + response_size), | 373 web_session_str, std::vector<uint8_t>(response, response + response_size), |
374 promise.Pass()); | 374 promise.Pass()); |
375 | 375 |
376 if (!renewal_timer_set_) { | 376 if (!renewal_timer_set_) { |
377 ScheduleNextRenewal(); | 377 ScheduleNextRenewal(); |
378 renewal_timer_set_ = true; | 378 renewal_timer_set_ = true; |
379 } | 379 } |
380 } | 380 } |
381 | 381 |
382 void ClearKeyCdm::CloseSession(uint32 promise_id, | 382 void ClearKeyCdm::CloseSession(uint32 promise_id, |
383 const char* session_id, | 383 const char* session_id, |
384 uint32_t session_id_length) { | 384 uint32_t session_id_length) { |
385 DVLOG(1) << __FUNCTION__; | 385 DVLOG(1) << __FUNCTION__; |
386 std::string web_session_str(session_id, session_id_length); | 386 std::string web_session_str(session_id, session_id_length); |
387 | 387 |
388 // If closing the loadable session, use the actual session id generated. | 388 // If closing the loadable session, use the actual session id generated. |
389 if (web_session_str == std::string(kLoadableSessionId)) | 389 if (web_session_str == std::string(kLoadableSessionId)) |
390 web_session_str = session_id_for_emulated_loadsession_; | 390 web_session_str = session_id_for_emulated_loadsession_; |
391 | 391 |
392 scoped_ptr<media::SimpleCdmPromise> promise(new media::CdmCallbackPromise<>( | 392 scoped_ptr<media::SimpleCdmPromise> promise(new media::CdmCallbackPromise<>( |
393 base::Bind( | 393 base::Bind( |
394 &ClearKeyCdm::OnPromiseResolved, base::Unretained(this), promise_id), | 394 &ClearKeyCdm::OnPromiseResolved, base::Unretained(this), promise_id), |
395 base::Bind( | 395 base::Bind( |
396 &ClearKeyCdm::OnPromiseFailed, base::Unretained(this), promise_id))); | 396 &ClearKeyCdm::OnPromiseFailed, base::Unretained(this), promise_id))); |
397 decryptor_.CloseSession(web_session_str, promise.Pass()); | 397 decryptor_->CloseSession(web_session_str, promise.Pass()); |
398 } | 398 } |
399 | 399 |
400 void ClearKeyCdm::RemoveSession(uint32 promise_id, | 400 void ClearKeyCdm::RemoveSession(uint32 promise_id, |
401 const char* session_id, | 401 const char* session_id, |
402 uint32_t session_id_length) { | 402 uint32_t session_id_length) { |
403 DVLOG(1) << __FUNCTION__; | 403 DVLOG(1) << __FUNCTION__; |
404 std::string web_session_str(session_id, session_id_length); | 404 std::string web_session_str(session_id, session_id_length); |
405 | 405 |
406 // RemoveSession only allowed for the loadable session. | 406 // RemoveSession only allowed for the loadable session. |
407 if (web_session_str == std::string(kLoadableSessionId)) { | 407 if (web_session_str == std::string(kLoadableSessionId)) { |
408 web_session_str = session_id_for_emulated_loadsession_; | 408 web_session_str = session_id_for_emulated_loadsession_; |
409 } else { | 409 } else { |
410 // TODO(jrummell): This should be a DCHECK once blink does the proper | 410 // TODO(jrummell): This should be a DCHECK once blink does the proper |
411 // checks. | 411 // checks. |
412 std::string message("Not supported for non-persistent sessions."); | 412 std::string message("Not supported for non-persistent sessions."); |
413 host_->OnRejectPromise(promise_id, | 413 host_->OnRejectPromise(promise_id, |
414 cdm::kInvalidAccessError, | 414 cdm::kInvalidAccessError, |
415 0, | 415 0, |
416 message.data(), | 416 message.data(), |
417 message.length()); | 417 message.length()); |
418 return; | 418 return; |
419 } | 419 } |
420 | 420 |
421 scoped_ptr<media::SimpleCdmPromise> promise(new media::CdmCallbackPromise<>( | 421 scoped_ptr<media::SimpleCdmPromise> promise(new media::CdmCallbackPromise<>( |
422 base::Bind(&ClearKeyCdm::OnPromiseResolved, base::Unretained(this), | 422 base::Bind(&ClearKeyCdm::OnPromiseResolved, base::Unretained(this), |
423 promise_id), | 423 promise_id), |
424 base::Bind(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this), | 424 base::Bind(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this), |
425 promise_id))); | 425 promise_id))); |
426 decryptor_.RemoveSession(web_session_str, promise.Pass()); | 426 decryptor_->RemoveSession(web_session_str, promise.Pass()); |
427 } | 427 } |
428 | 428 |
429 void ClearKeyCdm::SetServerCertificate(uint32 promise_id, | 429 void ClearKeyCdm::SetServerCertificate(uint32 promise_id, |
430 const uint8_t* server_certificate_data, | 430 const uint8_t* server_certificate_data, |
431 uint32_t server_certificate_data_size) { | 431 uint32_t server_certificate_data_size) { |
432 // ClearKey doesn't use a server certificate. | 432 // ClearKey doesn't use a server certificate. |
433 host_->OnResolvePromise(promise_id); | 433 host_->OnResolvePromise(promise_id); |
434 } | 434 } |
435 | 435 |
436 void ClearKeyCdm::TimerExpired(void* context) { | 436 void ClearKeyCdm::TimerExpired(void* context) { |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
664 | 664 |
665 if (buffer->end_of_stream()) { | 665 if (buffer->end_of_stream()) { |
666 *decrypted_buffer = buffer; | 666 *decrypted_buffer = buffer; |
667 return cdm::kSuccess; | 667 return cdm::kSuccess; |
668 } | 668 } |
669 | 669 |
670 // Callback is called synchronously, so we can use variables on the stack. | 670 // Callback is called synchronously, so we can use variables on the stack. |
671 media::Decryptor::Status status = media::Decryptor::kError; | 671 media::Decryptor::Status status = media::Decryptor::kError; |
672 // The AesDecryptor does not care what the stream type is. Pass kVideo | 672 // The AesDecryptor does not care what the stream type is. Pass kVideo |
673 // for both audio and video decryption. | 673 // for both audio and video decryption. |
674 decryptor_.Decrypt( | 674 decryptor_->Decrypt( |
675 media::Decryptor::kVideo, | 675 media::Decryptor::kVideo, buffer, |
676 buffer, | |
677 base::Bind(&CopyDecryptResults, &status, decrypted_buffer)); | 676 base::Bind(&CopyDecryptResults, &status, decrypted_buffer)); |
678 | 677 |
679 if (status == media::Decryptor::kError) | 678 if (status == media::Decryptor::kError) |
680 return cdm::kDecryptError; | 679 return cdm::kDecryptError; |
681 | 680 |
682 if (status == media::Decryptor::kNoKey) | 681 if (status == media::Decryptor::kNoKey) |
683 return cdm::kNoKey; | 682 return cdm::kNoKey; |
684 | 683 |
685 DCHECK_EQ(status, media::Decryptor::kSuccess); | 684 DCHECK_EQ(status, media::Decryptor::kSuccess); |
686 return cdm::kSuccess; | 685 return cdm::kSuccess; |
(...skipping 13 matching lines...) Expand all Loading... |
700 | 699 |
701 void ClearKeyCdm::LoadLoadableSession() { | 700 void ClearKeyCdm::LoadLoadableSession() { |
702 std::string jwk_set = GenerateJWKSet(kLoadableSessionKey, | 701 std::string jwk_set = GenerateJWKSet(kLoadableSessionKey, |
703 sizeof(kLoadableSessionKey), | 702 sizeof(kLoadableSessionKey), |
704 kLoadableSessionKeyId, | 703 kLoadableSessionKeyId, |
705 sizeof(kLoadableSessionKeyId) - 1); | 704 sizeof(kLoadableSessionKeyId) - 1); |
706 scoped_ptr<media::SimpleCdmPromise> promise(new media::CdmCallbackPromise<>( | 705 scoped_ptr<media::SimpleCdmPromise> promise(new media::CdmCallbackPromise<>( |
707 base::Bind(&ClearKeyCdm::OnLoadSessionUpdated, base::Unretained(this)), | 706 base::Bind(&ClearKeyCdm::OnLoadSessionUpdated, base::Unretained(this)), |
708 base::Bind(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this), | 707 base::Bind(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this), |
709 promise_id_for_emulated_loadsession_))); | 708 promise_id_for_emulated_loadsession_))); |
710 decryptor_.UpdateSession(session_id_for_emulated_loadsession_, | 709 decryptor_->UpdateSession( |
711 std::vector<uint8_t>(jwk_set.begin(), jwk_set.end()), | 710 session_id_for_emulated_loadsession_, |
712 promise.Pass()); | 711 std::vector<uint8_t>(jwk_set.begin(), jwk_set.end()), promise.Pass()); |
713 } | 712 } |
714 | 713 |
715 void ClearKeyCdm::OnSessionMessage(const std::string& session_id, | 714 void ClearKeyCdm::OnSessionMessage(const std::string& session_id, |
716 MediaKeys::MessageType message_type, | 715 MediaKeys::MessageType message_type, |
717 const std::vector<uint8>& message, | 716 const std::vector<uint8>& message, |
718 const GURL& legacy_destination_url) { | 717 const GURL& legacy_destination_url) { |
719 DVLOG(1) << "OnSessionMessage: " << message.size(); | 718 DVLOG(1) << "OnSessionMessage: " << message.size(); |
720 | 719 |
721 // Ignore the message when we are waiting to update the loadable session. | 720 // Ignore the message when we are waiting to update the loadable session. |
722 if (session_id == session_id_for_emulated_loadsession_) | 721 if (session_id == session_id_for_emulated_loadsession_) |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
910 void ClearKeyCdm::OnFileIOTestComplete(bool success) { | 909 void ClearKeyCdm::OnFileIOTestComplete(bool success) { |
911 DVLOG(1) << __FUNCTION__ << ": " << success; | 910 DVLOG(1) << __FUNCTION__ << ": " << success; |
912 std::string message = GetFileIOTestResultMessage(success); | 911 std::string message = GetFileIOTestResultMessage(success); |
913 host_->OnSessionMessage(last_session_id_.data(), last_session_id_.length(), | 912 host_->OnSessionMessage(last_session_id_.data(), last_session_id_.length(), |
914 cdm::kLicenseRequest, message.data(), | 913 cdm::kLicenseRequest, message.data(), |
915 message.length(), NULL, 0); | 914 message.length(), NULL, 0); |
916 file_io_test_runner_.reset(); | 915 file_io_test_runner_.reset(); |
917 } | 916 } |
918 | 917 |
919 } // namespace media | 918 } // namespace media |
OLD | NEW |