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 #include <utility> | 10 #include <utility> |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
51 static bool InitializeFFmpegLibraries() { | 51 static bool InitializeFFmpegLibraries() { |
52 media::InitializeMediaLibrary(); | 52 media::InitializeMediaLibrary(); |
53 return true; | 53 return true; |
54 } | 54 } |
55 static bool g_ffmpeg_lib_initialized = InitializeFFmpegLibraries(); | 55 static bool g_ffmpeg_lib_initialized = InitializeFFmpegLibraries(); |
56 | 56 |
57 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER | 57 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER |
58 | 58 |
59 const char kClearKeyCdmVersion[] = "0.1.0.1"; | 59 const char kClearKeyCdmVersion[] = "0.1.0.1"; |
60 const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey"; | 60 const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey"; |
61 | |
62 // Variants of external clear key key system to test different scenarios. | |
61 const char kExternalClearKeyDecryptOnlyKeySystem[] = | 63 const char kExternalClearKeyDecryptOnlyKeySystem[] = |
62 "org.chromium.externalclearkey.decryptonly"; | 64 "org.chromium.externalclearkey.decryptonly"; |
63 const char kExternalClearKeyFileIOTestKeySystem[] = | 65 const char kExternalClearKeyFileIOTestKeySystem[] = |
64 "org.chromium.externalclearkey.fileiotest"; | 66 "org.chromium.externalclearkey.fileiotest"; |
67 const char kExternalClearKeyOutputProtectionTestKeySystem[] = | |
68 "org.chromium.externalclearkey.outputprotectiontest"; | |
65 const char kExternalClearKeyCrashKeySystem[] = | 69 const char kExternalClearKeyCrashKeySystem[] = |
66 "org.chromium.externalclearkey.crash"; | 70 "org.chromium.externalclearkey.crash"; |
67 | 71 |
68 // Constants for the enumalted session that can be loaded by LoadSession(). | 72 // Constants for the enumalted session that can be loaded by LoadSession(). |
69 // These constants need to be in sync with | 73 // These constants need to be in sync with |
70 // chrome/test/data/media/encrypted_media_utils.js | 74 // chrome/test/data/media/encrypted_media_utils.js |
71 const char kLoadableSessionId[] = "LoadableSession"; | 75 const char kLoadableSessionId[] = "LoadableSession"; |
72 const uint8_t kLoadableSessionKeyId[] = "0123456789012345"; | 76 const uint8_t kLoadableSessionKeyId[] = "0123456789012345"; |
73 const uint8_t kLoadableSessionKey[] = {0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, | 77 const uint8_t kLoadableSessionKey[] = {0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, |
74 0xd2, 0x7b, 0x68, 0xef, 0x12, 0x2a, | 78 0xd2, 0x7b, 0x68, 0xef, 0x12, 0x2a, |
75 0xfc, 0xe4, 0xae, 0x3c}; | 79 0xfc, 0xe4, 0xae, 0x3c}; |
76 | 80 |
77 const int64_t kSecondsPerMinute = 60; | 81 const int64_t kSecondsPerMinute = 60; |
78 const int64_t kMsPerSecond = 1000; | 82 const int64_t kMsPerSecond = 1000; |
79 const int64_t kInitialTimerDelayMs = 200; | 83 const int64_t kInitialTimerDelayMs = 200; |
80 const int64_t kMaxTimerDelayMs = 1 * kSecondsPerMinute * kMsPerSecond; | 84 const int64_t kMaxTimerDelayMs = 1 * kSecondsPerMinute * kMsPerSecond; |
81 // Renewal message header. For prefixed EME, if a key message starts with | 85 // Renewal message header. For prefixed EME, if a key message starts with |
82 // |kRenewalHeader|, it's a renewal message. Otherwise, it's a key request. | 86 // |kRenewalHeader|, it's a renewal message. Otherwise, it's a key request. |
83 // FIXME(jrummell): Remove this once prefixed EME goes away. | 87 // FIXME(jrummell): Remove this once prefixed EME goes away. |
84 const char kRenewalHeader[] = "RENEWAL"; | 88 const char kRenewalHeader[] = "RENEWAL"; |
85 // CDM file IO test result header. | 89 |
86 const char kFileIOTestResultHeader[] = "FILEIOTESTRESULT"; | 90 // CDM unit test result header. Must be in sync with UNIT_TEST_RESULT_HEADER in |
91 // media/test/data/eme_player_js/globals.js. | |
92 const char kUnitTestResultHeader[] = "UNIT_TEST_RESULT"; | |
87 | 93 |
88 // Copies |input_buffer| into a media::DecoderBuffer. If the |input_buffer| is | 94 // Copies |input_buffer| into a media::DecoderBuffer. If the |input_buffer| is |
89 // empty, an empty (end-of-stream) media::DecoderBuffer is returned. | 95 // empty, an empty (end-of-stream) media::DecoderBuffer is returned. |
90 static scoped_refptr<media::DecoderBuffer> CopyDecoderBufferFrom( | 96 static scoped_refptr<media::DecoderBuffer> CopyDecoderBufferFrom( |
91 const cdm::InputBuffer& input_buffer) { | 97 const cdm::InputBuffer& input_buffer) { |
92 if (!input_buffer.data) { | 98 if (!input_buffer.data) { |
93 DCHECK(!input_buffer.data_size); | 99 DCHECK(!input_buffer.data_size); |
94 return media::DecoderBuffer::CreateEOSBuffer(); | 100 return media::DecoderBuffer::CreateEOSBuffer(); |
95 } | 101 } |
96 | 102 |
(...skipping 15 matching lines...) Expand all Loading... | |
112 input_buffer.iv_size), | 118 input_buffer.iv_size), |
113 subsamples)); | 119 subsamples)); |
114 | 120 |
115 output_buffer->set_decrypt_config(std::move(decrypt_config)); | 121 output_buffer->set_decrypt_config(std::move(decrypt_config)); |
116 output_buffer->set_timestamp( | 122 output_buffer->set_timestamp( |
117 base::TimeDelta::FromMicroseconds(input_buffer.timestamp)); | 123 base::TimeDelta::FromMicroseconds(input_buffer.timestamp)); |
118 | 124 |
119 return output_buffer; | 125 return output_buffer; |
120 } | 126 } |
121 | 127 |
122 static std::string GetFileIOTestResultMessage(bool success) { | 128 static std::string GetUnitTestResultMessage(bool success) { |
123 std::string message(kFileIOTestResultHeader); | 129 std::string message(kUnitTestResultHeader); |
124 message += success ? '1' : '0'; | 130 message += success ? '1' : '0'; |
125 return message; | 131 return message; |
126 } | 132 } |
127 | 133 |
128 static cdm::Error ConvertException(media::MediaKeys::Exception exception_code) { | 134 static cdm::Error ConvertException(media::MediaKeys::Exception exception_code) { |
129 switch (exception_code) { | 135 switch (exception_code) { |
130 case media::MediaKeys::NOT_SUPPORTED_ERROR: | 136 case media::MediaKeys::NOT_SUPPORTED_ERROR: |
131 return cdm::kNotSupportedError; | 137 return cdm::kNotSupportedError; |
132 case media::MediaKeys::INVALID_STATE_ERROR: | 138 case media::MediaKeys::INVALID_STATE_ERROR: |
133 return cdm::kInvalidStateError; | 139 return cdm::kInvalidStateError; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
225 void* CreateCdmInstance(int cdm_interface_version, | 231 void* CreateCdmInstance(int cdm_interface_version, |
226 const char* key_system, uint32_t key_system_size, | 232 const char* key_system, uint32_t key_system_size, |
227 GetCdmHostFunc get_cdm_host_func, | 233 GetCdmHostFunc get_cdm_host_func, |
228 void* user_data) { | 234 void* user_data) { |
229 DVLOG(1) << "CreateCdmInstance()"; | 235 DVLOG(1) << "CreateCdmInstance()"; |
230 | 236 |
231 std::string key_system_string(key_system, key_system_size); | 237 std::string key_system_string(key_system, key_system_size); |
232 if (key_system_string != kExternalClearKeyKeySystem && | 238 if (key_system_string != kExternalClearKeyKeySystem && |
233 key_system_string != kExternalClearKeyDecryptOnlyKeySystem && | 239 key_system_string != kExternalClearKeyDecryptOnlyKeySystem && |
234 key_system_string != kExternalClearKeyFileIOTestKeySystem && | 240 key_system_string != kExternalClearKeyFileIOTestKeySystem && |
241 key_system_string != kExternalClearKeyOutputProtectionTestKeySystem && | |
235 key_system_string != kExternalClearKeyCrashKeySystem) { | 242 key_system_string != kExternalClearKeyCrashKeySystem) { |
236 DVLOG(1) << "Unsupported key system:" << key_system_string; | 243 DVLOG(1) << "Unsupported key system:" << key_system_string; |
237 return NULL; | 244 return NULL; |
238 } | 245 } |
239 | 246 |
240 if (cdm_interface_version != media::ClearKeyCdmInterface::kVersion) | 247 if (cdm_interface_version != media::ClearKeyCdmInterface::kVersion) |
241 return NULL; | 248 return NULL; |
242 | 249 |
243 media::ClearKeyCdmHost* host = static_cast<media::ClearKeyCdmHost*>( | 250 media::ClearKeyCdmHost* host = static_cast<media::ClearKeyCdmHost*>( |
244 get_cdm_host_func(media::ClearKeyCdmHost::kVersion, user_data)); | 251 get_cdm_host_func(media::ClearKeyCdmHost::kVersion, user_data)); |
(...skipping 17 matching lines...) Expand all Loading... | |
262 : decryptor_(new AesDecryptor( | 269 : decryptor_(new AesDecryptor( |
263 origin, | 270 origin, |
264 base::Bind(&ClearKeyCdm::OnSessionMessage, base::Unretained(this)), | 271 base::Bind(&ClearKeyCdm::OnSessionMessage, base::Unretained(this)), |
265 base::Bind(&ClearKeyCdm::OnSessionClosed, base::Unretained(this)), | 272 base::Bind(&ClearKeyCdm::OnSessionClosed, base::Unretained(this)), |
266 base::Bind(&ClearKeyCdm::OnSessionKeysChange, | 273 base::Bind(&ClearKeyCdm::OnSessionKeysChange, |
267 base::Unretained(this)))), | 274 base::Unretained(this)))), |
268 host_(host), | 275 host_(host), |
269 key_system_(key_system), | 276 key_system_(key_system), |
270 has_received_keys_change_event_for_emulated_loadsession_(false), | 277 has_received_keys_change_event_for_emulated_loadsession_(false), |
271 timer_delay_ms_(kInitialTimerDelayMs), | 278 timer_delay_ms_(kInitialTimerDelayMs), |
272 renewal_timer_set_(false) { | 279 renewal_timer_set_(false), |
280 is_running_output_protection_test_(false) { | |
273 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) | 281 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) |
274 channel_count_ = 0; | 282 channel_count_ = 0; |
275 bits_per_channel_ = 0; | 283 bits_per_channel_ = 0; |
276 samples_per_second_ = 0; | 284 samples_per_second_ = 0; |
277 output_timestamp_base_in_microseconds_ = kNoTimestamp; | 285 output_timestamp_base_in_microseconds_ = kNoTimestamp; |
278 total_samples_generated_ = 0; | 286 total_samples_generated_ = 0; |
279 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER | 287 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER |
280 } | 288 } |
281 | 289 |
282 ClearKeyCdm::~ClearKeyCdm() {} | 290 ClearKeyCdm::~ClearKeyCdm() {} |
(...skipping 16 matching lines...) Expand all Loading... | |
299 new media::CdmCallbackPromise<std::string>( | 307 new media::CdmCallbackPromise<std::string>( |
300 base::Bind(&ClearKeyCdm::OnSessionCreated, base::Unretained(this), | 308 base::Bind(&ClearKeyCdm::OnSessionCreated, base::Unretained(this), |
301 promise_id), | 309 promise_id), |
302 base::Bind(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this), | 310 base::Bind(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this), |
303 promise_id))); | 311 promise_id))); |
304 decryptor_->CreateSessionAndGenerateRequest( | 312 decryptor_->CreateSessionAndGenerateRequest( |
305 ConvertSessionType(session_type), ConvertInitDataType(init_data_type), | 313 ConvertSessionType(session_type), ConvertInitDataType(init_data_type), |
306 std::vector<uint8_t>(init_data, init_data + init_data_size), | 314 std::vector<uint8_t>(init_data, init_data + init_data_size), |
307 std::move(promise)); | 315 std::move(promise)); |
308 | 316 |
309 if (key_system_ == kExternalClearKeyFileIOTestKeySystem) | 317 if (key_system_ == kExternalClearKeyFileIOTestKeySystem) { |
310 StartFileIOTest(); | 318 StartFileIOTest(); |
319 } else if (key_system_ == kExternalClearKeyOutputProtectionTestKeySystem) { | |
320 StartOutputProtectionTest(); | |
321 } | |
311 } | 322 } |
312 | 323 |
313 // Loads a emulated stored session. Currently only |kLoadableSessionId| | 324 // Loads a emulated stored session. Currently only |kLoadableSessionId| |
314 // (containing a |kLoadableSessionKey| for |kLoadableSessionKeyId|) is | 325 // (containing a |kLoadableSessionKey| for |kLoadableSessionKeyId|) is |
315 // supported. | 326 // supported. |
316 void ClearKeyCdm::LoadSession(uint32_t promise_id, | 327 void ClearKeyCdm::LoadSession(uint32_t promise_id, |
317 cdm::SessionType session_type, | 328 cdm::SessionType session_type, |
318 const char* session_id, | 329 const char* session_id, |
319 uint32_t session_id_length) { | 330 uint32_t session_id_length) { |
320 DVLOG(1) << __FUNCTION__; | 331 DVLOG(1) << __FUNCTION__; |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
687 | 698 |
688 void ClearKeyCdm::OnPlatformChallengeResponse( | 699 void ClearKeyCdm::OnPlatformChallengeResponse( |
689 const cdm::PlatformChallengeResponse& response) { | 700 const cdm::PlatformChallengeResponse& response) { |
690 NOTIMPLEMENTED(); | 701 NOTIMPLEMENTED(); |
691 } | 702 } |
692 | 703 |
693 void ClearKeyCdm::OnQueryOutputProtectionStatus( | 704 void ClearKeyCdm::OnQueryOutputProtectionStatus( |
694 cdm::QueryResult result, | 705 cdm::QueryResult result, |
695 uint32_t link_mask, | 706 uint32_t link_mask, |
696 uint32_t output_protection_mask) { | 707 uint32_t output_protection_mask) { |
697 NOTIMPLEMENTED(); | 708 if (!is_running_output_protection_test_) { |
709 NOTREACHED() << "OnQueryOutputProtectionStatus() called unexpectedly."; | |
710 return; | |
711 } | |
712 | |
713 is_running_output_protection_test_ = false; | |
714 | |
715 // On ChromeOS, status query will fail on Linux ChromeOS build. So we ignore | |
716 // the query result. On all other platforms, status query should succeed. | |
717 // TODO(xhwang): Check how to make status query work on ChromeOS in tests. | |
xhwang
2016/06/21 20:07:18
+kcwu: Any idea how to get this working in a test
kcwu
2016/06/23 09:07:40
Sorry for late reply.
How about using base::SysIn
| |
718 #if !defined(OS_CHROMEOS) | |
719 if (result != cdm::kQuerySucceeded) { | |
720 OnUnitTestComplete(false); | |
721 return; | |
722 } | |
723 #endif | |
724 OnUnitTestComplete(true); | |
698 }; | 725 }; |
699 | 726 |
700 void ClearKeyCdm::LoadLoadableSession() { | 727 void ClearKeyCdm::LoadLoadableSession() { |
701 std::string jwk_set = GenerateJWKSet(kLoadableSessionKey, | 728 std::string jwk_set = GenerateJWKSet(kLoadableSessionKey, |
702 sizeof(kLoadableSessionKey), | 729 sizeof(kLoadableSessionKey), |
703 kLoadableSessionKeyId, | 730 kLoadableSessionKeyId, |
704 sizeof(kLoadableSessionKeyId) - 1); | 731 sizeof(kLoadableSessionKeyId) - 1); |
705 std::unique_ptr<media::SimpleCdmPromise> promise( | 732 std::unique_ptr<media::SimpleCdmPromise> promise( |
706 new media::CdmCallbackPromise<>( | 733 new media::CdmCallbackPromise<>( |
707 base::Bind(&ClearKeyCdm::OnLoadSessionUpdated, | 734 base::Bind(&ClearKeyCdm::OnLoadSessionUpdated, |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
896 | 923 |
897 int samples_generated = GenerateFakeAudioFramesFromDuration( | 924 int samples_generated = GenerateFakeAudioFramesFromDuration( |
898 timestamp_in_microseconds - CurrentTimeStampInMicroseconds(), | 925 timestamp_in_microseconds - CurrentTimeStampInMicroseconds(), |
899 audio_frames); | 926 audio_frames); |
900 total_samples_generated_ += samples_generated; | 927 total_samples_generated_ += samples_generated; |
901 | 928 |
902 return samples_generated == 0 ? cdm::kNeedMoreData : cdm::kSuccess; | 929 return samples_generated == 0 ? cdm::kNeedMoreData : cdm::kSuccess; |
903 } | 930 } |
904 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER | 931 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER |
905 | 932 |
933 void ClearKeyCdm::OnUnitTestComplete(bool success) { | |
934 std::string message = GetUnitTestResultMessage(success); | |
935 host_->OnSessionMessage(last_session_id_.data(), last_session_id_.length(), | |
936 cdm::kLicenseRequest, message.data(), | |
937 message.length(), NULL, 0); | |
938 } | |
939 | |
906 void ClearKeyCdm::StartFileIOTest() { | 940 void ClearKeyCdm::StartFileIOTest() { |
907 file_io_test_runner_.reset(new FileIOTestRunner( | 941 file_io_test_runner_.reset(new FileIOTestRunner( |
908 base::Bind(&ClearKeyCdmHost::CreateFileIO, base::Unretained(host_)))); | 942 base::Bind(&ClearKeyCdmHost::CreateFileIO, base::Unretained(host_)))); |
909 file_io_test_runner_->RunAllTests( | 943 file_io_test_runner_->RunAllTests( |
910 base::Bind(&ClearKeyCdm::OnFileIOTestComplete, base::Unretained(this))); | 944 base::Bind(&ClearKeyCdm::OnFileIOTestComplete, base::Unretained(this))); |
911 } | 945 } |
912 | 946 |
913 void ClearKeyCdm::OnFileIOTestComplete(bool success) { | 947 void ClearKeyCdm::OnFileIOTestComplete(bool success) { |
914 DVLOG(1) << __FUNCTION__ << ": " << success; | 948 DVLOG(1) << __FUNCTION__ << ": " << success; |
915 std::string message = GetFileIOTestResultMessage(success); | 949 OnUnitTestComplete(success); |
916 host_->OnSessionMessage(last_session_id_.data(), last_session_id_.length(), | |
917 cdm::kLicenseRequest, message.data(), | |
918 message.length(), NULL, 0); | |
919 file_io_test_runner_.reset(); | 950 file_io_test_runner_.reset(); |
920 } | 951 } |
921 | 952 |
953 void ClearKeyCdm::StartOutputProtectionTest() { | |
954 is_running_output_protection_test_ = true; | |
955 host_->QueryOutputProtectionStatus(); | |
956 } | |
957 | |
922 } // namespace media | 958 } // namespace media |
OLD | NEW |