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 <string> | 10 #include <string> |
11 #include <vector> | 11 #include <vector> |
12 | 12 |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
14 #include "base/debug/trace_event.h" | 14 #include "base/debug/trace_event.h" |
15 #include "base/logging.h" | 15 #include "base/logging.h" |
16 #include "base/time/time.h" | 16 #include "base/time/time.h" |
| 17 #include "media/base/cdm_promise.h" |
17 #include "media/base/decoder_buffer.h" | 18 #include "media/base/decoder_buffer.h" |
18 #include "media/base/decrypt_config.h" | 19 #include "media/base/decrypt_config.h" |
19 #include "media/cdm/json_web_key.h" | 20 #include "media/cdm/json_web_key.h" |
20 #include "media/cdm/ppapi/cdm_file_io_test.h" | 21 #include "media/cdm/ppapi/cdm_file_io_test.h" |
21 #include "media/cdm/ppapi/external_clear_key/cdm_video_decoder.h" | 22 #include "media/cdm/ppapi/external_clear_key/cdm_video_decoder.h" |
22 | 23 |
23 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) | 24 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) |
24 #include "base/basictypes.h" | 25 #include "base/basictypes.h" |
25 const int64 kNoTimestamp = kint64min; | 26 const int64 kNoTimestamp = kint64min; |
26 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER | 27 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER |
27 | 28 |
28 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) | 29 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) |
29 #include "base/at_exit.h" | 30 #include "base/at_exit.h" |
30 #include "base/files/file_path.h" | 31 #include "base/files/file_path.h" |
31 #include "base/path_service.h" | 32 #include "base/path_service.h" |
32 #include "media/base/media.h" | 33 #include "media/base/media.h" |
33 #include "media/cdm/ppapi/external_clear_key/ffmpeg_cdm_audio_decoder.h" | 34 #include "media/cdm/ppapi/external_clear_key/ffmpeg_cdm_audio_decoder.h" |
34 #include "media/cdm/ppapi/external_clear_key/ffmpeg_cdm_video_decoder.h" | 35 #include "media/cdm/ppapi/external_clear_key/ffmpeg_cdm_video_decoder.h" |
35 | 36 |
36 // Include FFmpeg avformat.h for av_register_all(). | 37 // Include FFmpeg avformat.h for av_register_all(). |
37 extern "C" { | 38 extern "C" { |
38 // Temporarily disable possible loss of data warning. | 39 // Temporarily disable possible loss of data warning. |
39 MSVC_PUSH_DISABLE_WARNING(4244); | 40 MSVC_PUSH_DISABLE_WARNING(4244); |
40 #include <libavformat/avformat.h> | 41 #include <libavformat/avformat.h> |
41 MSVC_POP_WARNING(); | 42 MSVC_POP_WARNING(); |
42 } // extern "C" | 43 } // extern "C" |
43 | 44 |
| 45 #define COMPILE_ASSERT_MATCHING_ENUM(cdm_name, media_name) \ |
| 46 COMPILE_ASSERT(static_cast<int>(cdm::cdm_name) == \ |
| 47 static_cast<int>(media::MediaKeys::media_name), \ |
| 48 mismatching_enums) |
| 49 // Validate cdm::SessionType and MediaKeys::SessionType |
| 50 COMPILE_ASSERT_MATCHING_ENUM(kTemporary, SESSION_TYPE_TEMPORARY); |
| 51 COMPILE_ASSERT_MATCHING_ENUM(kPersistent, SESSION_TYPE_PERSISTENT); |
| 52 |
| 53 // Validate cdm::MediaKeyException and MediaKeys::MediaKeysException |
| 54 COMPILE_ASSERT_MATCHING_ENUM(kIndexSizeError, |
| 55 MEDIA_KEYS_EXCEPTION_INDEX_SIZE_ERROR); |
| 56 COMPILE_ASSERT_MATCHING_ENUM(kHierarchyRequestError, |
| 57 MEDIA_KEYS_EXCEPTION_HIERARCHY_REQUEST_ERROR); |
| 58 COMPILE_ASSERT_MATCHING_ENUM(kWrongDocumentError, |
| 59 MEDIA_KEYS_EXCEPTION_WRONG_DOCUMENT_ERROR); |
| 60 COMPILE_ASSERT_MATCHING_ENUM(kInvalidCharacterError, |
| 61 MEDIA_KEYS_EXCEPTION_INVALID_CHARACTER_ERROR); |
| 62 COMPILE_ASSERT_MATCHING_ENUM( |
| 63 kNoModificationAllowedError, |
| 64 MEDIA_KEYS_EXCEPTION_NO_MODIFICATION_ALLOWED_ERROR); |
| 65 COMPILE_ASSERT_MATCHING_ENUM(kNotFoundError, |
| 66 MEDIA_KEYS_EXCEPTION_NOT_FOUND_ERROR); |
| 67 COMPILE_ASSERT_MATCHING_ENUM(kNotSupportedError, |
| 68 MEDIA_KEYS_EXCEPTION_NOT_SUPPORTED_ERROR); |
| 69 COMPILE_ASSERT_MATCHING_ENUM(kInvalidStateError, |
| 70 MEDIA_KEYS_EXCEPTION_INVALID_STATE_ERROR); |
| 71 COMPILE_ASSERT_MATCHING_ENUM(kSyntaxError, MEDIA_KEYS_EXCEPTION_SYNTAX_ERROR); |
| 72 COMPILE_ASSERT_MATCHING_ENUM(kInvalidModificationError, |
| 73 MEDIA_KEYS_EXCEPTION_INVALID_MODIFICATION_ERROR); |
| 74 COMPILE_ASSERT_MATCHING_ENUM(kNamespaceError, |
| 75 MEDIA_KEYS_EXCEPTION_NAMESPACE_ERROR); |
| 76 COMPILE_ASSERT_MATCHING_ENUM(kInvalidAccessError, |
| 77 MEDIA_KEYS_EXCEPTION_INVALID_ACCESS_ERROR); |
| 78 COMPILE_ASSERT_MATCHING_ENUM(kSecurityError, |
| 79 MEDIA_KEYS_EXCEPTION_SECURITY_ERROR); |
| 80 COMPILE_ASSERT_MATCHING_ENUM(kNetworkError, MEDIA_KEYS_EXCEPTION_NETWORK_ERROR); |
| 81 COMPILE_ASSERT_MATCHING_ENUM(kAbortError, MEDIA_KEYS_EXCEPTION_ABORT_ERROR); |
| 82 COMPILE_ASSERT_MATCHING_ENUM(kUrlMismatchError, |
| 83 MEDIA_KEYS_EXCEPTION_URL_MISMATCH_ERROR); |
| 84 COMPILE_ASSERT_MATCHING_ENUM(kQuotaExceededError, |
| 85 MEDIA_KEYS_EXCEPTION_QUOTA_EXCEEDED_ERROR); |
| 86 COMPILE_ASSERT_MATCHING_ENUM(kTimeoutError, MEDIA_KEYS_EXCEPTION_TIMEOUT_ERROR); |
| 87 COMPILE_ASSERT_MATCHING_ENUM(kInvalidNodeTypeError, |
| 88 MEDIA_KEYS_EXCEPTION_INVALID_NODE_TYPE_ERROR); |
| 89 COMPILE_ASSERT_MATCHING_ENUM(kDataCloneError, |
| 90 MEDIA_KEYS_EXCEPTION_DATA_CLONE_ERROR); |
| 91 COMPILE_ASSERT_MATCHING_ENUM(kEncodingError, |
| 92 MEDIA_KEYS_EXCEPTION_ENCODING_ERROR); |
| 93 COMPILE_ASSERT_MATCHING_ENUM(kNotReadableError, |
| 94 MEDIA_KEYS_EXCEPTION_NOT_READABLE_ERROR); |
| 95 COMPILE_ASSERT_MATCHING_ENUM(kDataError, MEDIA_KEYS_EXCEPTION_DATA_ERROR); |
| 96 COMPILE_ASSERT_MATCHING_ENUM(kOperationError, |
| 97 MEDIA_KEYS_EXCEPTION_OPERATION_ERROR); |
| 98 COMPILE_ASSERT_MATCHING_ENUM(kVersionError, MEDIA_KEYS_EXCEPTION_VERSION_ERROR); |
| 99 COMPILE_ASSERT_MATCHING_ENUM(kMediaKeyErrorUnknownError, |
| 100 MEDIA_KEYS_EXCEPTION_UNKNOWN_ERROR); |
| 101 COMPILE_ASSERT_MATCHING_ENUM(kMediaKeyErrorClientError, |
| 102 MEDIA_KEYS_EXCEPTION_CLIENT_ERROR); |
| 103 COMPILE_ASSERT_MATCHING_ENUM(kMediaKeyErrorOutputError, |
| 104 MEDIA_KEYS_EXCEPTION_OUTPUT_ERROR); |
| 105 #undef COMPILE_ASSERT_MATCHING_ENUM |
| 106 |
44 // TODO(tomfinegan): When COMPONENT_BUILD is not defined an AtExitManager must | 107 // TODO(tomfinegan): When COMPONENT_BUILD is not defined an AtExitManager must |
45 // exist before the call to InitializeFFmpegLibraries(). This should no longer | 108 // exist before the call to InitializeFFmpegLibraries(). This should no longer |
46 // be required after http://crbug.com/91970 because we'll be able to get rid of | 109 // be required after http://crbug.com/91970 because we'll be able to get rid of |
47 // InitializeFFmpegLibraries(). | 110 // InitializeFFmpegLibraries(). |
48 #if !defined COMPONENT_BUILD | 111 #if !defined COMPONENT_BUILD |
49 static base::AtExitManager g_at_exit_manager; | 112 static base::AtExitManager g_at_exit_manager; |
50 #endif | 113 #endif |
51 | 114 |
52 // TODO(tomfinegan): InitializeFFmpegLibraries() and |g_cdm_module_initialized| | 115 // TODO(tomfinegan): InitializeFFmpegLibraries() and |g_cdm_module_initialized| |
53 // are required for running in the sandbox, and should no longer be required | 116 // are required for running in the sandbox, and should no longer be required |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 } | 243 } |
181 | 244 |
182 const char* GetCdmVersion() { | 245 const char* GetCdmVersion() { |
183 return kClearKeyCdmVersion; | 246 return kClearKeyCdmVersion; |
184 } | 247 } |
185 | 248 |
186 namespace media { | 249 namespace media { |
187 | 250 |
188 ClearKeyCdm::ClearKeyCdm(ClearKeyCdmHost* host, const std::string& key_system) | 251 ClearKeyCdm::ClearKeyCdm(ClearKeyCdmHost* host, const std::string& key_system) |
189 : decryptor_( | 252 : decryptor_( |
190 base::Bind(&ClearKeyCdm::OnSessionCreated, base::Unretained(this)), | 253 base::Bind(&ClearKeyCdm::OnSessionMessage, base::Unretained(this))), |
191 base::Bind(&ClearKeyCdm::OnSessionMessage, base::Unretained(this)), | |
192 base::Bind(&ClearKeyCdm::OnSessionReady, base::Unretained(this)), | |
193 base::Bind(&ClearKeyCdm::OnSessionClosed, base::Unretained(this)), | |
194 base::Bind(&ClearKeyCdm::OnSessionError, base::Unretained(this))), | |
195 host_(host), | 254 host_(host), |
196 key_system_(key_system), | 255 key_system_(key_system), |
197 last_session_id_(MediaKeys::kInvalidSessionId), | |
198 session_id_for_emulated_loadsession_(MediaKeys::kInvalidSessionId), | |
199 timer_delay_ms_(kInitialTimerDelayMs), | 256 timer_delay_ms_(kInitialTimerDelayMs), |
200 heartbeat_timer_set_(false) { | 257 heartbeat_timer_set_(false) { |
201 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) | 258 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) |
202 channel_count_ = 0; | 259 channel_count_ = 0; |
203 bits_per_channel_ = 0; | 260 bits_per_channel_ = 0; |
204 samples_per_second_ = 0; | 261 samples_per_second_ = 0; |
205 output_timestamp_base_in_microseconds_ = kNoTimestamp; | 262 output_timestamp_base_in_microseconds_ = kNoTimestamp; |
206 total_samples_generated_ = 0; | 263 total_samples_generated_ = 0; |
207 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER | 264 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER |
208 } | 265 } |
209 | 266 |
210 ClearKeyCdm::~ClearKeyCdm() {} | 267 ClearKeyCdm::~ClearKeyCdm() {} |
211 | 268 |
212 void ClearKeyCdm::CreateSession(uint32 session_id, | 269 void ClearKeyCdm::CreateSession(uint32 promise_id, |
213 const char* type, | 270 const char* init_data_type, |
214 uint32 type_size, | 271 uint32 init_data_type_size, |
215 const uint8* init_data, | 272 const uint8* init_data, |
216 uint32 init_data_size) { | 273 uint32 init_data_size, |
| 274 cdm::SessionType session_type) { |
217 DVLOG(1) << __FUNCTION__; | 275 DVLOG(1) << __FUNCTION__; |
218 decryptor_.CreateSession( | |
219 session_id, std::string(type, type_size), init_data, init_data_size); | |
220 | 276 |
221 // Save the latest session ID for heartbeat and file IO test messages. | 277 scoped_ptr<media::CdmPromise<std::string> > promise( |
222 last_session_id_ = session_id; | 278 new media::CdmPromise<std::string>( |
| 279 base::Bind(&ClearKeyCdm::OnSessionCreated, |
| 280 base::Unretained(this), |
| 281 promise_id), |
| 282 base::Bind(&ClearKeyCdm::OnSessionCreateFailed, |
| 283 base::Unretained(this), |
| 284 promise_id))); |
| 285 decryptor_.CreateSession(std::string(init_data_type, init_data_type_size), |
| 286 init_data, |
| 287 init_data_size, |
| 288 static_cast<MediaKeys::SessionType>(session_type), |
| 289 promise.Pass()); |
223 | 290 |
224 if (key_system_ == kExternalClearKeyFileIOTestKeySystem) | 291 if (key_system_ == kExternalClearKeyFileIOTestKeySystem) |
225 StartFileIOTest(); | 292 StartFileIOTest(); |
226 } | 293 } |
227 | 294 |
228 // Loads a emulated stored session. Currently only |kLoadableWebSessionId| | 295 // Loads a emulated stored session. Currently only |kLoadableWebSessionId| |
229 // (containing a |kLoadableSessionKey| for |kLoadableSessionKeyId|) is | 296 // (containing a |kLoadableSessionKey| for |kLoadableSessionKeyId|) is |
230 // supported. | 297 // supported. |
231 void ClearKeyCdm::LoadSession(uint32_t session_id, | 298 void ClearKeyCdm::LoadSession(uint32 promise_id, |
232 const char* web_session_id, | 299 const char* web_session_id, |
233 uint32_t web_session_id_length) { | 300 uint32_t web_session_id_length) { |
234 DVLOG(1) << __FUNCTION__; | 301 DVLOG(1) << __FUNCTION__; |
235 | 302 |
236 if (std::string(kLoadableWebSessionId) != | 303 if (std::string(kLoadableWebSessionId) != |
237 std::string(web_session_id, web_session_id_length)) { | 304 std::string(web_session_id, web_session_id_length)) { |
238 // TODO(xhwang): Report "NotFoundError" when we support DOMError style. | 305 std::string message("Incorrect session id specified for LoadSession()."); |
239 OnSessionError(session_id, MediaKeys::kUnknownError, 0); | 306 host_->OnRejectPromise( |
| 307 promise_id, cdm::kNotFoundError, 0, message.data(), message.length()); |
240 return; | 308 return; |
241 } | 309 } |
242 | 310 |
243 session_id_for_emulated_loadsession_ = session_id; | 311 scoped_ptr<media::CdmPromise<std::string> > promise( |
244 | 312 new media::CdmPromise<std::string>( |
245 decryptor_.CreateSession(session_id, kLoadableSessionContentType, NULL, 0); | 313 base::Bind(&ClearKeyCdm::OnSessionLoaded, |
| 314 base::Unretained(this), |
| 315 promise_id), |
| 316 base::Bind(&ClearKeyCdm::OnSessionLoadFailed, |
| 317 base::Unretained(this), |
| 318 promise_id))); |
| 319 decryptor_.CreateSession(std::string(kLoadableSessionContentType), |
| 320 NULL, |
| 321 0, |
| 322 MediaKeys::SESSION_TYPE_TEMPORARY, |
| 323 promise.Pass()); |
246 } | 324 } |
247 | 325 |
248 void ClearKeyCdm::UpdateSession(uint32 session_id, | 326 void ClearKeyCdm::UpdateSession(uint32 promise_id, |
| 327 const char* web_session_id, |
| 328 uint32_t web_session_id_size, |
249 const uint8* response, | 329 const uint8* response, |
250 uint32 response_size) { | 330 uint32 response_size) { |
251 DVLOG(1) << __FUNCTION__; | 331 DVLOG(1) << __FUNCTION__; |
252 decryptor_.UpdateSession(session_id, response, response_size); | 332 std::string web_session_str(web_session_id, web_session_id_size); |
| 333 |
| 334 scoped_ptr<media::CdmPromise<void> > promise(new media::CdmPromise<void>( |
| 335 base::Bind(&ClearKeyCdm::OnSessionUpdated, |
| 336 base::Unretained(this), |
| 337 promise_id, |
| 338 web_session_str), |
| 339 base::Bind(&ClearKeyCdm::OnSessionUpdateFailed, |
| 340 base::Unretained(this), |
| 341 promise_id))); |
| 342 decryptor_.UpdateSession( |
| 343 web_session_str, response, response_size, promise.Pass()); |
253 | 344 |
254 if (!heartbeat_timer_set_) { | 345 if (!heartbeat_timer_set_) { |
255 ScheduleNextHeartBeat(); | 346 ScheduleNextHeartBeat(); |
256 heartbeat_timer_set_ = true; | 347 heartbeat_timer_set_ = true; |
257 } | 348 } |
258 } | 349 } |
259 | 350 |
260 void ClearKeyCdm::ReleaseSession(uint32 session_id) { | 351 void ClearKeyCdm::ReleaseSession(uint32 promise_id, |
| 352 const char* web_session_id, |
| 353 uint32_t web_session_id_size) { |
261 DVLOG(1) << __FUNCTION__; | 354 DVLOG(1) << __FUNCTION__; |
262 decryptor_.ReleaseSession(session_id); | 355 std::string web_session_str(web_session_id, web_session_id_size); |
| 356 |
| 357 scoped_ptr<media::CdmPromise<void> > promise(new media::CdmPromise<void>( |
| 358 base::Bind(&ClearKeyCdm::OnSessionReleased, |
| 359 base::Unretained(this), |
| 360 promise_id, |
| 361 web_session_str), |
| 362 base::Bind(&ClearKeyCdm::OnSessionReleaseFailed, |
| 363 base::Unretained(this), |
| 364 promise_id))); |
| 365 decryptor_.ReleaseSession(web_session_str, promise.Pass()); |
| 366 } |
| 367 |
| 368 void ClearKeyCdm::SetServerCertificate(uint32 promise_id, |
| 369 const uint8_t* server_certificate_data, |
| 370 uint32_t server_certificate_data_size) { |
| 371 // ClearKey doesn't use a server certificate. |
| 372 host_->OnResolvePromise(promise_id); |
263 } | 373 } |
264 | 374 |
265 void ClearKeyCdm::TimerExpired(void* context) { | 375 void ClearKeyCdm::TimerExpired(void* context) { |
266 if (context == &session_id_for_emulated_loadsession_) { | 376 if (context == &session_id_for_emulated_loadsession_) { |
267 LoadLoadableSession(); | 377 LoadLoadableSession(); |
268 return; | 378 return; |
269 } | 379 } |
270 | 380 |
271 DCHECK(heartbeat_timer_set_); | 381 DCHECK(heartbeat_timer_set_); |
272 std::string heartbeat_message; | 382 std::string heartbeat_message; |
273 if (!next_heartbeat_message_.empty() && | 383 if (!next_heartbeat_message_.empty() && |
274 context == &next_heartbeat_message_[0]) { | 384 context == &next_heartbeat_message_[0]) { |
275 heartbeat_message = next_heartbeat_message_; | 385 heartbeat_message = next_heartbeat_message_; |
276 } else { | 386 } else { |
277 heartbeat_message = "ERROR: Invalid timer context found!"; | 387 heartbeat_message = "ERROR: Invalid timer context found!"; |
278 } | 388 } |
279 | 389 |
280 // This URL is only used for testing the code path for defaultURL. | 390 // This URL is only used for testing the code path for defaultURL. |
281 // There is no service at this URL, so applications should ignore it. | 391 // There is no service at this URL, so applications should ignore it. |
282 const char url[] = "http://test.externalclearkey.chromium.org"; | 392 const char url[] = "http://test.externalclearkey.chromium.org"; |
283 | 393 |
284 host_->OnSessionMessage(last_session_id_, | 394 host_->OnSessionMessage(last_session_id_.data(), |
| 395 last_session_id_.length(), |
285 heartbeat_message.data(), | 396 heartbeat_message.data(), |
286 heartbeat_message.size(), | 397 heartbeat_message.length(), |
287 url, | 398 url, |
288 arraysize(url) - 1); | 399 arraysize(url) - 1); |
289 | 400 |
290 ScheduleNextHeartBeat(); | 401 ScheduleNextHeartBeat(); |
291 } | 402 } |
292 | 403 |
293 static void CopyDecryptResults( | 404 static void CopyDecryptResults( |
294 media::Decryptor::Status* status_copy, | 405 media::Decryptor::Status* status_copy, |
295 scoped_refptr<media::DecoderBuffer>* buffer_copy, | 406 scoped_refptr<media::DecoderBuffer>* buffer_copy, |
296 media::Decryptor::Status status, | 407 media::Decryptor::Status status, |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 NOTIMPLEMENTED(); | 639 NOTIMPLEMENTED(); |
529 }; | 640 }; |
530 | 641 |
531 void ClearKeyCdm::LoadLoadableSession() { | 642 void ClearKeyCdm::LoadLoadableSession() { |
532 std::string jwk_set = GenerateJWKSet(kLoadableSessionKey, | 643 std::string jwk_set = GenerateJWKSet(kLoadableSessionKey, |
533 sizeof(kLoadableSessionKey), | 644 sizeof(kLoadableSessionKey), |
534 kLoadableSessionKeyId, | 645 kLoadableSessionKeyId, |
535 sizeof(kLoadableSessionKeyId) - 1); | 646 sizeof(kLoadableSessionKeyId) - 1); |
536 // TODO(xhwang): This triggers OnSessionUpdated(). For prefixed EME support, | 647 // TODO(xhwang): This triggers OnSessionUpdated(). For prefixed EME support, |
537 // this is okay. Check WD EME support. | 648 // this is okay. Check WD EME support. |
| 649 scoped_ptr<media::CdmPromise<void> > promise(new media::CdmPromise<void>( |
| 650 base::Bind(&ClearKeyCdm::OnSessionUpdated, |
| 651 base::Unretained(this), |
| 652 promise_id_for_emulated_loadsession_, |
| 653 session_id_for_emulated_loadsession_), |
| 654 base::Bind(&ClearKeyCdm::OnSessionUpdateFailed, |
| 655 base::Unretained(this), |
| 656 promise_id_for_emulated_loadsession_))); |
538 decryptor_.UpdateSession(session_id_for_emulated_loadsession_, | 657 decryptor_.UpdateSession(session_id_for_emulated_loadsession_, |
539 reinterpret_cast<const uint8*>(jwk_set.data()), | 658 reinterpret_cast<const uint8*>(jwk_set.data()), |
540 jwk_set.size()); | 659 jwk_set.size(), |
| 660 promise.Pass()); |
541 } | 661 } |
542 | 662 |
543 void ClearKeyCdm::OnSessionCreated(uint32 session_id, | 663 void ClearKeyCdm::OnSessionMessage(const std::string& web_session_id, |
544 const std::string& web_session_id) { | |
545 std::string new_web_session_id = web_session_id; | |
546 | |
547 if (session_id == session_id_for_emulated_loadsession_) { | |
548 // Delay LoadLoadableSession() to test the case where Decrypt*() calls are | |
549 // made before the session is fully loaded. | |
550 const int64 kDelayToLoadSessionMs = 500; | |
551 // Use the address of |session_id_for_emulated_loadsession_| as the timer | |
552 // context so that we can call LoadLoadableSession() when the timer expires. | |
553 host_->SetTimer(kDelayToLoadSessionMs, | |
554 &session_id_for_emulated_loadsession_); | |
555 // Defer OnSessionCreated() until the session is loaded. | |
556 return; | |
557 } | |
558 | |
559 host_->OnSessionCreated( | |
560 session_id, web_session_id.data(), web_session_id.size()); | |
561 } | |
562 | |
563 void ClearKeyCdm::OnSessionMessage(uint32 session_id, | |
564 const std::vector<uint8>& message, | 664 const std::vector<uint8>& message, |
565 const std::string& destination_url) { | 665 const std::string& destination_url) { |
566 DVLOG(1) << "OnSessionMessage: " << message.size(); | 666 DVLOG(1) << "OnSessionMessage: " << message.size(); |
567 | 667 |
568 // Ignore the message when we are waiting to update the loadable session. | 668 // Ignore the message when we are waiting to update the loadable session. |
569 if (session_id == session_id_for_emulated_loadsession_) | 669 if (web_session_id == session_id_for_emulated_loadsession_) |
570 return; | 670 return; |
571 | 671 |
572 host_->OnSessionMessage(session_id, | 672 // OnSessionMessage() only called during CreateSession(), so no promise |
| 673 // involved (OnSessionCreated() called to resolve the CreateSession() |
| 674 // promise). |
| 675 host_->OnSessionMessage(web_session_id.data(), |
| 676 web_session_id.length(), |
573 reinterpret_cast<const char*>(message.data()), | 677 reinterpret_cast<const char*>(message.data()), |
574 message.size(), | 678 message.size(), |
575 destination_url.data(), | 679 destination_url.data(), |
576 destination_url.size()); | 680 destination_url.length()); |
577 } | 681 } |
578 | 682 |
579 void ClearKeyCdm::OnSessionReady(uint32 session_id) { | 683 void ClearKeyCdm::OnSessionCreated(uint32 promise_id, |
580 if (session_id == session_id_for_emulated_loadsession_) { | 684 const std::string& web_session_id) { |
581 session_id_for_emulated_loadsession_ = MediaKeys::kInvalidSessionId; | 685 // Save the latest session ID for heartbeat and file IO test messages. |
582 host_->OnSessionCreated( | 686 last_session_id_ = web_session_id; |
583 session_id, kLoadableWebSessionId, strlen(kLoadableWebSessionId)); | 687 |
| 688 host_->OnResolveNewSessionPromise( |
| 689 promise_id, web_session_id.data(), web_session_id.length()); |
| 690 } |
| 691 |
| 692 void ClearKeyCdm::OnSessionCreateFailed( |
| 693 uint32 promise_id, |
| 694 MediaKeys::MediaKeysException exception_code, |
| 695 uint32 system_code, |
| 696 const std::string& error_message) { |
| 697 RejectPromise(promise_id, exception_code, system_code, error_message); |
| 698 } |
| 699 |
| 700 void ClearKeyCdm::OnSessionLoaded(uint32 promise_id, |
| 701 const std::string& web_session_id) { |
| 702 // Save the latest session ID for heartbeat and file IO test messages. |
| 703 last_session_id_ = web_session_id; |
| 704 |
| 705 // |decryptor_| created some session as |web_session_id|, but going forward |
| 706 // we need to map that to |kLoadableWebSessionId|, as that is what callers |
| 707 // expect. |
| 708 session_id_for_emulated_loadsession_ = web_session_id; |
| 709 |
| 710 // Delay LoadLoadableSession() to test the case where Decrypt*() calls are |
| 711 // made before the session is fully loaded. |
| 712 const int64 kDelayToLoadSessionMs = 500; |
| 713 |
| 714 // Defer resolving the promise until the session is loaded. |
| 715 promise_id_for_emulated_loadsession_ = promise_id; |
| 716 |
| 717 // Use the address of |session_id_for_emulated_loadsession_| as the timer |
| 718 // context so that we can call LoadLoadableSession() when the timer expires. |
| 719 host_->SetTimer(kDelayToLoadSessionMs, &session_id_for_emulated_loadsession_); |
| 720 } |
| 721 |
| 722 void ClearKeyCdm::OnSessionLoadFailed( |
| 723 uint32 promise_id, |
| 724 MediaKeys::MediaKeysException exception_code, |
| 725 uint32 system_code, |
| 726 const std::string& error_message) { |
| 727 RejectPromise(promise_id, exception_code, system_code, error_message); |
| 728 } |
| 729 |
| 730 void ClearKeyCdm::OnSessionUpdated(uint32 promise_id, |
| 731 const std::string& web_session_id) { |
| 732 // OnSessionReady() only called as success for UpdateSession(). However, |
| 733 // UpdateSession() also called to finish loading sessions, so handle |
| 734 // appropriately. |
| 735 if (web_session_id == session_id_for_emulated_loadsession_) { |
| 736 session_id_for_emulated_loadsession_ = std::string(); |
| 737 // |promise_id| is the LoadSession() promise, so resolve appropriately. |
| 738 host_->OnResolveNewSessionPromise( |
| 739 promise_id, kLoadableWebSessionId, strlen(kLoadableWebSessionId)); |
| 740 host_->OnSessionReady(kLoadableWebSessionId, strlen(kLoadableWebSessionId)); |
| 741 return; |
584 } | 742 } |
585 | 743 |
586 host_->OnSessionReady(session_id); | 744 host_->OnResolvePromise(promise_id); |
587 } | 745 } |
588 | 746 |
589 void ClearKeyCdm::OnSessionClosed(uint32 session_id) { | 747 void ClearKeyCdm::OnSessionUpdateFailed( |
590 host_->OnSessionClosed(session_id); | 748 uint32 promise_id, |
| 749 MediaKeys::MediaKeysException exception_code, |
| 750 uint32 system_code, |
| 751 const std::string& error_message) { |
| 752 RejectPromise(promise_id, exception_code, system_code, error_message); |
591 } | 753 } |
592 | 754 |
593 void ClearKeyCdm::OnSessionError(uint32 session_id, | 755 void ClearKeyCdm::OnSessionReleased(uint32 promise_id, |
594 media::MediaKeys::KeyError error_code, | 756 const std::string& web_session_id) { |
595 uint32 system_code) { | 757 host_->OnResolvePromise(promise_id); |
596 host_->OnSessionError( | 758 } |
597 session_id, static_cast<cdm::MediaKeyError>(error_code), system_code); | 759 |
| 760 void ClearKeyCdm::OnSessionReleaseFailed( |
| 761 uint32 promise_id, |
| 762 MediaKeys::MediaKeysException exception_code, |
| 763 uint32 system_code, |
| 764 const std::string& error_message) { |
| 765 RejectPromise(promise_id, exception_code, system_code, error_message); |
| 766 } |
| 767 |
| 768 void ClearKeyCdm::RejectPromise(uint32 promise_id, |
| 769 MediaKeys::MediaKeysException exception_code, |
| 770 uint32 system_code, |
| 771 const std::string& error_message) { |
| 772 host_->OnRejectPromise(promise_id, |
| 773 static_cast<cdm::MediaKeyException>(exception_code), |
| 774 system_code, |
| 775 error_message.data(), |
| 776 error_message.length()); |
598 } | 777 } |
599 | 778 |
600 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) | 779 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) |
601 int64 ClearKeyCdm::CurrentTimeStampInMicroseconds() const { | 780 int64 ClearKeyCdm::CurrentTimeStampInMicroseconds() const { |
602 return output_timestamp_base_in_microseconds_ + | 781 return output_timestamp_base_in_microseconds_ + |
603 base::Time::kMicrosecondsPerSecond * | 782 base::Time::kMicrosecondsPerSecond * |
604 total_samples_generated_ / samples_per_second_; | 783 total_samples_generated_ / samples_per_second_; |
605 } | 784 } |
606 | 785 |
607 int ClearKeyCdm::GenerateFakeAudioFramesFromDuration( | 786 int ClearKeyCdm::GenerateFakeAudioFramesFromDuration( |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
659 void ClearKeyCdm::StartFileIOTest() { | 838 void ClearKeyCdm::StartFileIOTest() { |
660 file_io_test_runner_.reset(new FileIOTestRunner( | 839 file_io_test_runner_.reset(new FileIOTestRunner( |
661 base::Bind(&ClearKeyCdmHost::CreateFileIO, base::Unretained(host_)))); | 840 base::Bind(&ClearKeyCdmHost::CreateFileIO, base::Unretained(host_)))); |
662 file_io_test_runner_->RunAllTests( | 841 file_io_test_runner_->RunAllTests( |
663 base::Bind(&ClearKeyCdm::OnFileIOTestComplete, base::Unretained(this))); | 842 base::Bind(&ClearKeyCdm::OnFileIOTestComplete, base::Unretained(this))); |
664 } | 843 } |
665 | 844 |
666 void ClearKeyCdm::OnFileIOTestComplete(bool success) { | 845 void ClearKeyCdm::OnFileIOTestComplete(bool success) { |
667 DVLOG(1) << __FUNCTION__ << ": " << success; | 846 DVLOG(1) << __FUNCTION__ << ": " << success; |
668 std::string message = GetFileIOTestResultMessage(success); | 847 std::string message = GetFileIOTestResultMessage(success); |
669 host_->OnSessionMessage( | 848 host_->OnSessionMessage(last_session_id_.data(), |
670 last_session_id_, message.data(), message.size(), NULL, 0); | 849 last_session_id_.length(), |
| 850 message.data(), |
| 851 message.length(), |
| 852 NULL, |
| 853 0); |
671 file_io_test_runner_.reset(); | 854 file_io_test_runner_.reset(); |
672 } | 855 } |
673 | 856 |
674 } // namespace media | 857 } // namespace media |
OLD | NEW |