| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "content/renderer/pepper/content_decryptor_delegate.h" | 5 #include "content/renderer/pepper/content_decryptor_delegate.h" |
| 6 | 6 |
| 7 #include "base/callback_helpers.h" | 7 #include "base/callback_helpers.h" |
| 8 #include "base/debug/trace_event.h" | 8 #include "base/debug/trace_event.h" |
| 9 #include "base/message_loop/message_loop_proxy.h" | 9 #include "base/message_loop/message_loop_proxy.h" |
| 10 #include "base/metrics/sparse_histogram.h" | 10 #include "base/metrics/sparse_histogram.h" |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 case PP_DECRYPTEDSAMPLEFORMAT_PLANAR_F32: | 250 case PP_DECRYPTEDSAMPLEFORMAT_PLANAR_F32: |
| 251 return media::kSampleFormatPlanarF32; | 251 return media::kSampleFormatPlanarF32; |
| 252 default: | 252 default: |
| 253 NOTREACHED(); | 253 NOTREACHED(); |
| 254 return media::kUnknownSampleFormat; | 254 return media::kUnknownSampleFormat; |
| 255 } | 255 } |
| 256 } | 256 } |
| 257 | 257 |
| 258 PP_SessionType MediaSessionTypeToPpSessionType( | 258 PP_SessionType MediaSessionTypeToPpSessionType( |
| 259 MediaKeys::SessionType session_type) { | 259 MediaKeys::SessionType session_type) { |
| 260 // TODO(jrummell): Add support for PP_SESSIONTYPE_RELEASE_LICENSE. |
| 260 switch (session_type) { | 261 switch (session_type) { |
| 261 case MediaKeys::TEMPORARY_SESSION: | 262 case MediaKeys::TEMPORARY_SESSION: |
| 262 return PP_SESSIONTYPE_TEMPORARY; | 263 return PP_SESSIONTYPE_TEMPORARY; |
| 263 case MediaKeys::PERSISTENT_SESSION: | 264 case MediaKeys::PERSISTENT_SESSION: |
| 264 return PP_SESSIONTYPE_PERSISTENT; | 265 return PP_SESSIONTYPE_PERSISTENT_LICENSE; |
| 265 default: | 266 default: |
| 266 NOTREACHED(); | 267 NOTREACHED(); |
| 267 return PP_SESSIONTYPE_TEMPORARY; | 268 return PP_SESSIONTYPE_TEMPORARY; |
| 268 } | 269 } |
| 269 } | 270 } |
| 270 | 271 |
| 271 MediaKeys::Exception PpExceptionTypeToMediaException( | 272 MediaKeys::Exception PpExceptionTypeToMediaException( |
| 272 PP_CdmExceptionCode exception_code) { | 273 PP_CdmExceptionCode exception_code) { |
| 273 switch (exception_code) { | 274 switch (exception_code) { |
| 274 case PP_CDMEXCEPTIONCODE_NOTSUPPORTEDERROR: | 275 case PP_CDMEXCEPTIONCODE_NOTSUPPORTEDERROR: |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 audio_channel_layout_(media::CHANNEL_LAYOUT_NONE), | 315 audio_channel_layout_(media::CHANNEL_LAYOUT_NONE), |
| 315 next_promise_id_(1), | 316 next_promise_id_(1), |
| 316 weak_ptr_factory_(this) { | 317 weak_ptr_factory_(this) { |
| 317 weak_this_ = weak_ptr_factory_.GetWeakPtr(); | 318 weak_this_ = weak_ptr_factory_.GetWeakPtr(); |
| 318 } | 319 } |
| 319 | 320 |
| 320 ContentDecryptorDelegate::~ContentDecryptorDelegate() { | 321 ContentDecryptorDelegate::~ContentDecryptorDelegate() { |
| 321 SatisfyAllPendingCallbacksOnError(); | 322 SatisfyAllPendingCallbacksOnError(); |
| 322 } | 323 } |
| 323 | 324 |
| 325 // TODO(jrummell): Remove |session_ready_cb| and |session_keys_change_cb|. |
| 324 void ContentDecryptorDelegate::Initialize( | 326 void ContentDecryptorDelegate::Initialize( |
| 325 const std::string& key_system, | 327 const std::string& key_system, |
| 326 const media::SessionMessageCB& session_message_cb, | 328 const media::SessionMessageCB& session_message_cb, |
| 327 const media::SessionReadyCB& session_ready_cb, | 329 const media::SessionReadyCB& session_ready_cb, |
| 328 const media::SessionClosedCB& session_closed_cb, | 330 const media::SessionClosedCB& session_closed_cb, |
| 329 const media::SessionErrorCB& session_error_cb, | 331 const media::SessionErrorCB& session_error_cb, |
| 330 const media::SessionKeysChangeCB& session_keys_change_cb, | 332 const media::SessionKeysChangeCB& session_keys_change_cb, |
| 331 const media::SessionExpirationUpdateCB& session_expiration_update_cb, | 333 const media::SessionExpirationUpdateCB& session_expiration_update_cb, |
| 332 const base::Closure& fatal_plugin_error_cb) { | 334 const base::Closure& fatal_plugin_error_cb) { |
| 333 DCHECK(!key_system.empty()); | 335 DCHECK(!key_system.empty()); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 364 } | 366 } |
| 365 | 367 |
| 366 uint32_t promise_id = SavePromise(promise.Pass()); | 368 uint32_t promise_id = SavePromise(promise.Pass()); |
| 367 PP_Var certificate_array = | 369 PP_Var certificate_array = |
| 368 PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( | 370 PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( |
| 369 certificate_length, certificate); | 371 certificate_length, certificate); |
| 370 plugin_decryption_interface_->SetServerCertificate( | 372 plugin_decryption_interface_->SetServerCertificate( |
| 371 pp_instance_, promise_id, certificate_array); | 373 pp_instance_, promise_id, certificate_array); |
| 372 } | 374 } |
| 373 | 375 |
| 376 // TODO(jrummell): Rename method to CreateSessionAndGenerateRequest() |
| 377 // and reorder parameter list. |
| 374 void ContentDecryptorDelegate::CreateSession( | 378 void ContentDecryptorDelegate::CreateSession( |
| 375 const std::string& init_data_type, | 379 const std::string& init_data_type, |
| 376 const uint8* init_data, | 380 const uint8* init_data, |
| 377 int init_data_length, | 381 int init_data_length, |
| 378 MediaKeys::SessionType session_type, | 382 MediaKeys::SessionType session_type, |
| 379 scoped_ptr<NewSessionCdmPromise> promise) { | 383 scoped_ptr<NewSessionCdmPromise> promise) { |
| 380 uint32_t promise_id = SavePromise(promise.Pass()); | 384 uint32_t promise_id = SavePromise(promise.Pass()); |
| 381 PP_Var init_data_array = | 385 PP_Var init_data_array = |
| 382 PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( | 386 PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( |
| 383 init_data_length, init_data); | 387 init_data_length, init_data); |
| 384 plugin_decryption_interface_->CreateSession( | 388 plugin_decryption_interface_->CreateSessionAndGenerateRequest( |
| 385 pp_instance_, | 389 pp_instance_, promise_id, MediaSessionTypeToPpSessionType(session_type), |
| 386 promise_id, | 390 StringVar::StringToPPVar(init_data_type), init_data_array); |
| 387 StringVar::StringToPPVar(init_data_type), | |
| 388 init_data_array, | |
| 389 MediaSessionTypeToPpSessionType(session_type)); | |
| 390 } | 391 } |
| 391 | 392 |
| 393 // TODO(jrummell): Pass |session_type| to this method. |
| 392 void ContentDecryptorDelegate::LoadSession( | 394 void ContentDecryptorDelegate::LoadSession( |
| 393 const std::string& web_session_id, | 395 const std::string& web_session_id, |
| 394 scoped_ptr<NewSessionCdmPromise> promise) { | 396 scoped_ptr<NewSessionCdmPromise> promise) { |
| 395 uint32_t promise_id = SavePromise(promise.Pass()); | 397 uint32_t promise_id = SavePromise(promise.Pass()); |
| 396 plugin_decryption_interface_->LoadSession( | 398 plugin_decryption_interface_->LoadSession( |
| 397 pp_instance_, promise_id, StringVar::StringToPPVar(web_session_id)); | 399 pp_instance_, promise_id, PP_SESSIONTYPE_PERSISTENT_LICENSE, |
| 400 StringVar::StringToPPVar(web_session_id)); |
| 398 } | 401 } |
| 399 | 402 |
| 400 void ContentDecryptorDelegate::UpdateSession( | 403 void ContentDecryptorDelegate::UpdateSession( |
| 401 const std::string& web_session_id, | 404 const std::string& web_session_id, |
| 402 const uint8* response, | 405 const uint8* response, |
| 403 int response_length, | 406 int response_length, |
| 404 scoped_ptr<SimpleCdmPromise> promise) { | 407 scoped_ptr<SimpleCdmPromise> promise) { |
| 405 uint32_t promise_id = SavePromise(promise.Pass()); | 408 uint32_t promise_id = SavePromise(promise.Pass()); |
| 406 PP_Var response_array = | 409 PP_Var response_array = |
| 407 PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( | 410 PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( |
| (...skipping 26 matching lines...) Expand all Loading... |
| 434 promise->reject( | 437 promise->reject( |
| 435 media::MediaKeys::INVALID_ACCESS_ERROR, 0, "Incorrect session."); | 438 media::MediaKeys::INVALID_ACCESS_ERROR, 0, "Incorrect session."); |
| 436 return; | 439 return; |
| 437 } | 440 } |
| 438 | 441 |
| 439 uint32_t promise_id = SavePromise(promise.Pass()); | 442 uint32_t promise_id = SavePromise(promise.Pass()); |
| 440 plugin_decryption_interface_->RemoveSession( | 443 plugin_decryption_interface_->RemoveSession( |
| 441 pp_instance_, promise_id, StringVar::StringToPPVar(web_session_id)); | 444 pp_instance_, promise_id, StringVar::StringToPPVar(web_session_id)); |
| 442 } | 445 } |
| 443 | 446 |
| 447 // TODO(jrummell): Remove this method. |
| 444 void ContentDecryptorDelegate::GetUsableKeyIds( | 448 void ContentDecryptorDelegate::GetUsableKeyIds( |
| 445 const std::string& web_session_id, | 449 const std::string& web_session_id, |
| 446 scoped_ptr<media::KeyIdsPromise> promise) { | 450 scoped_ptr<media::KeyIdsPromise> promise) { |
| 447 if (web_session_id.length() > media::limits::kMaxWebSessionIdLength) { | 451 NOTREACHED(); |
| 448 promise->reject( | |
| 449 media::MediaKeys::INVALID_ACCESS_ERROR, 0, "Incorrect session."); | |
| 450 return; | |
| 451 } | |
| 452 | |
| 453 uint32_t promise_id = SavePromise(promise.Pass()); | |
| 454 plugin_decryption_interface_->GetUsableKeyIds( | |
| 455 pp_instance_, promise_id, StringVar::StringToPPVar(web_session_id)); | |
| 456 } | 452 } |
| 457 | 453 |
| 458 // TODO(xhwang): Remove duplication of code in Decrypt(), | 454 // TODO(xhwang): Remove duplication of code in Decrypt(), |
| 459 // DecryptAndDecodeAudio() and DecryptAndDecodeVideo(). | 455 // DecryptAndDecodeAudio() and DecryptAndDecodeVideo(). |
| 460 bool ContentDecryptorDelegate::Decrypt( | 456 bool ContentDecryptorDelegate::Decrypt( |
| 461 Decryptor::StreamType stream_type, | 457 Decryptor::StreamType stream_type, |
| 462 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, | 458 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, |
| 463 const Decryptor::DecryptCB& decrypt_cb) { | 459 const Decryptor::DecryptCB& decrypt_cb) { |
| 464 DVLOG(3) << "Decrypt() - stream_type: " << stream_type; | 460 DVLOG(3) << "Decrypt() - stream_type: " << stream_type; |
| 465 | 461 |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 722 } | 718 } |
| 723 | 719 |
| 724 StringVar* web_session_id_string = StringVar::FromPPVar(web_session_id); | 720 StringVar* web_session_id_string = StringVar::FromPPVar(web_session_id); |
| 725 DCHECK(web_session_id_string); | 721 DCHECK(web_session_id_string); |
| 726 | 722 |
| 727 NewSessionCdmPromise* session_promise = | 723 NewSessionCdmPromise* session_promise = |
| 728 static_cast<NewSessionCdmPromise*>(promise.get()); | 724 static_cast<NewSessionCdmPromise*>(promise.get()); |
| 729 session_promise->resolve(web_session_id_string->value()); | 725 session_promise->resolve(web_session_id_string->value()); |
| 730 } | 726 } |
| 731 | 727 |
| 732 void ContentDecryptorDelegate::OnPromiseResolvedWithKeyIds( | |
| 733 uint32 promise_id, | |
| 734 PP_Var key_ids_array) { | |
| 735 scoped_ptr<CdmPromise> promise = TakePromise(promise_id); | |
| 736 | |
| 737 ArrayVar* key_ids = ArrayVar::FromPPVar(key_ids_array); | |
| 738 DCHECK(key_ids && key_ids->GetLength() <= media::limits::kMaxKeyIds); | |
| 739 media::KeyIdsVector key_ids_vector; | |
| 740 if (key_ids && key_ids->GetLength() <= media::limits::kMaxKeyIds) { | |
| 741 for (size_t i = 0; i < key_ids->GetLength(); ++i) { | |
| 742 ArrayBufferVar* array_buffer = ArrayBufferVar::FromPPVar(key_ids->Get(i)); | |
| 743 | |
| 744 if (!array_buffer || | |
| 745 array_buffer->ByteLength() < media::limits::kMinKeyIdLength || | |
| 746 array_buffer->ByteLength() > media::limits::kMaxKeyIdLength) { | |
| 747 NOTREACHED(); | |
| 748 continue; | |
| 749 } | |
| 750 | |
| 751 std::vector<uint8> key_id; | |
| 752 const uint8* data = static_cast<const uint8*>(array_buffer->Map()); | |
| 753 key_id.assign(data, data + array_buffer->ByteLength()); | |
| 754 key_ids_vector.push_back(key_id); | |
| 755 } | |
| 756 } | |
| 757 | |
| 758 if (!promise || | |
| 759 promise->GetResolveParameterType() != | |
| 760 media::CdmPromise::KEY_IDS_VECTOR_TYPE) { | |
| 761 NOTREACHED(); | |
| 762 return; | |
| 763 } | |
| 764 | |
| 765 KeyIdsPromise* key_ids_promise(static_cast<KeyIdsPromise*>(promise.get())); | |
| 766 key_ids_promise->resolve(key_ids_vector); | |
| 767 } | |
| 768 | |
| 769 void ContentDecryptorDelegate::OnPromiseRejected( | 728 void ContentDecryptorDelegate::OnPromiseRejected( |
| 770 uint32 promise_id, | 729 uint32 promise_id, |
| 771 PP_CdmExceptionCode exception_code, | 730 PP_CdmExceptionCode exception_code, |
| 772 uint32 system_code, | 731 uint32 system_code, |
| 773 PP_Var error_description) { | 732 PP_Var error_description) { |
| 774 ReportSystemCodeUMA(key_system_, system_code); | 733 ReportSystemCodeUMA(key_system_, system_code); |
| 775 | 734 |
| 776 StringVar* error_description_string = StringVar::FromPPVar(error_description); | 735 StringVar* error_description_string = StringVar::FromPPVar(error_description); |
| 777 DCHECK(error_description_string); | 736 DCHECK(error_description_string); |
| 778 | 737 |
| 779 scoped_ptr<CdmPromise> promise = TakePromise(promise_id); | 738 scoped_ptr<CdmPromise> promise = TakePromise(promise_id); |
| 780 DCHECK(promise); | 739 DCHECK(promise); |
| 781 if (promise) { | 740 if (promise) { |
| 782 promise->reject(PpExceptionTypeToMediaException(exception_code), | 741 promise->reject(PpExceptionTypeToMediaException(exception_code), |
| 783 system_code, | 742 system_code, |
| 784 error_description_string->value()); | 743 error_description_string->value()); |
| 785 } | 744 } |
| 786 } | 745 } |
| 787 | 746 |
| 747 // TODO(jrummell): Pass |message_type| to the callback. |
| 788 void ContentDecryptorDelegate::OnSessionMessage(PP_Var web_session_id, | 748 void ContentDecryptorDelegate::OnSessionMessage(PP_Var web_session_id, |
| 789 PP_Var message, | 749 PP_MessageType message_type, |
| 790 PP_Var destination_url) { | 750 PP_Var message) { |
| 791 if (session_message_cb_.is_null()) | 751 if (session_message_cb_.is_null()) |
| 792 return; | 752 return; |
| 793 | 753 |
| 794 StringVar* web_session_id_string = StringVar::FromPPVar(web_session_id); | 754 StringVar* web_session_id_string = StringVar::FromPPVar(web_session_id); |
| 795 DCHECK(web_session_id_string); | 755 DCHECK(web_session_id_string); |
| 796 | 756 |
| 797 ArrayBufferVar* message_array_buffer = ArrayBufferVar::FromPPVar(message); | 757 ArrayBufferVar* message_array_buffer = ArrayBufferVar::FromPPVar(message); |
| 798 std::vector<uint8> message_vector; | 758 std::vector<uint8> message_vector; |
| 799 if (message_array_buffer) { | 759 if (message_array_buffer) { |
| 800 const uint8* data = static_cast<const uint8*>(message_array_buffer->Map()); | 760 const uint8* data = static_cast<const uint8*>(message_array_buffer->Map()); |
| 801 message_vector.assign(data, data + message_array_buffer->ByteLength()); | 761 message_vector.assign(data, data + message_array_buffer->ByteLength()); |
| 802 } | 762 } |
| 803 | 763 |
| 804 StringVar* destination_url_string = StringVar::FromPPVar(destination_url); | 764 session_message_cb_.Run(web_session_id_string->value(), message_vector, |
| 805 DCHECK(destination_url_string); | 765 GURL::EmptyGURL()); |
| 806 | |
| 807 GURL verified_gurl = GURL(destination_url_string->value()); | |
| 808 if (!verified_gurl.is_valid() && !verified_gurl.is_empty()) { | |
| 809 DLOG(WARNING) << "SessionMessage default_url is invalid : " | |
| 810 << verified_gurl.possibly_invalid_spec(); | |
| 811 verified_gurl = GURL::EmptyGURL(); // Replace invalid destination_url. | |
| 812 } | |
| 813 | |
| 814 session_message_cb_.Run( | |
| 815 web_session_id_string->value(), message_vector, verified_gurl); | |
| 816 } | 766 } |
| 817 | 767 |
| 768 // TODO(jrummell): Decode |key_information| and pass it to the callback. |
| 818 void ContentDecryptorDelegate::OnSessionKeysChange( | 769 void ContentDecryptorDelegate::OnSessionKeysChange( |
| 819 PP_Var web_session_id, | 770 PP_Var web_session_id, |
| 820 PP_Bool has_additional_usable_key) { | 771 PP_Bool has_additional_usable_key, |
| 772 PP_Var key_information) { |
| 821 if (session_keys_change_cb_.is_null()) | 773 if (session_keys_change_cb_.is_null()) |
| 822 return; | 774 return; |
| 823 | 775 |
| 824 StringVar* web_session_id_string = StringVar::FromPPVar(web_session_id); | 776 StringVar* web_session_id_string = StringVar::FromPPVar(web_session_id); |
| 825 DCHECK(web_session_id_string); | 777 DCHECK(web_session_id_string); |
| 826 | 778 |
| 827 session_keys_change_cb_.Run(web_session_id_string->value(), | 779 session_keys_change_cb_.Run(web_session_id_string->value(), |
| 828 PP_ToBool(has_additional_usable_key)); | 780 PP_ToBool(has_additional_usable_key)); |
| 829 } | 781 } |
| 830 | 782 |
| 831 void ContentDecryptorDelegate::OnSessionExpirationChange( | 783 void ContentDecryptorDelegate::OnSessionExpirationChange( |
| 832 PP_Var web_session_id, | 784 PP_Var web_session_id, |
| 833 PP_Time new_expiry_time) { | 785 PP_Time new_expiry_time) { |
| 834 if (session_expiration_update_cb_.is_null()) | 786 if (session_expiration_update_cb_.is_null()) |
| 835 return; | 787 return; |
| 836 | 788 |
| 837 StringVar* web_session_id_string = StringVar::FromPPVar(web_session_id); | 789 StringVar* web_session_id_string = StringVar::FromPPVar(web_session_id); |
| 838 DCHECK(web_session_id_string); | 790 DCHECK(web_session_id_string); |
| 839 | 791 |
| 840 session_expiration_update_cb_.Run(web_session_id_string->value(), | 792 session_expiration_update_cb_.Run(web_session_id_string->value(), |
| 841 ppapi::PPTimeToTime(new_expiry_time)); | 793 ppapi::PPTimeToTime(new_expiry_time)); |
| 842 } | 794 } |
| 843 | 795 |
| 844 void ContentDecryptorDelegate::OnSessionReady(PP_Var web_session_id) { | |
| 845 if (session_ready_cb_.is_null()) | |
| 846 return; | |
| 847 | |
| 848 StringVar* web_session_id_string = StringVar::FromPPVar(web_session_id); | |
| 849 DCHECK(web_session_id_string); | |
| 850 | |
| 851 session_ready_cb_.Run(web_session_id_string->value()); | |
| 852 } | |
| 853 | |
| 854 void ContentDecryptorDelegate::OnSessionClosed(PP_Var web_session_id) { | 796 void ContentDecryptorDelegate::OnSessionClosed(PP_Var web_session_id) { |
| 855 if (session_closed_cb_.is_null()) | 797 if (session_closed_cb_.is_null()) |
| 856 return; | 798 return; |
| 857 | 799 |
| 858 StringVar* web_session_id_string = StringVar::FromPPVar(web_session_id); | 800 StringVar* web_session_id_string = StringVar::FromPPVar(web_session_id); |
| 859 DCHECK(web_session_id_string); | 801 DCHECK(web_session_id_string); |
| 860 | 802 |
| 861 session_closed_cb_.Run(web_session_id_string->value()); | 803 session_closed_cb_.Run(web_session_id_string->value()); |
| 862 } | 804 } |
| 863 | 805 |
| (...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1324 | 1266 |
| 1325 scoped_ptr<CdmPromise> ContentDecryptorDelegate::TakePromise( | 1267 scoped_ptr<CdmPromise> ContentDecryptorDelegate::TakePromise( |
| 1326 uint32_t promise_id) { | 1268 uint32_t promise_id) { |
| 1327 PromiseMap::iterator it = promises_.find(promise_id); | 1269 PromiseMap::iterator it = promises_.find(promise_id); |
| 1328 if (it == promises_.end()) | 1270 if (it == promises_.end()) |
| 1329 return scoped_ptr<CdmPromise>(); | 1271 return scoped_ptr<CdmPromise>(); |
| 1330 return promises_.take_and_erase(it); | 1272 return promises_.take_and_erase(it); |
| 1331 } | 1273 } |
| 1332 | 1274 |
| 1333 } // namespace content | 1275 } // namespace content |
| OLD | NEW |