| 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 |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 | 127 |
| 127 return output_buffer; | 128 return output_buffer; |
| 128 } | 129 } |
| 129 | 130 |
| 130 static std::string GetFileIOTestResultMessage(bool success) { | 131 static std::string GetFileIOTestResultMessage(bool success) { |
| 131 std::string message(kFileIOTestResultHeader); | 132 std::string message(kFileIOTestResultHeader); |
| 132 message += success ? '1' : '0'; | 133 message += success ? '1' : '0'; |
| 133 return message; | 134 return message; |
| 134 } | 135 } |
| 135 | 136 |
| 137 static cdm::Error ConvertException(media::MediaKeys::Exception exception_code) { |
| 138 switch (exception_code) { |
| 139 case media::MediaKeys::EXCEPTION_NO_MODIFICATION_ALLOWED_ERROR: |
| 140 return cdm::kNoModificationAllowedError; |
| 141 case media::MediaKeys::EXCEPTION_NOT_FOUND_ERROR: |
| 142 return cdm::kNotFoundError; |
| 143 case media::MediaKeys::EXCEPTION_NOT_SUPPORTED_ERROR: |
| 144 return cdm::kNotSupportedError; |
| 145 case media::MediaKeys::EXCEPTION_INVALID_STATE_ERROR: |
| 146 return cdm::kInvalidStateError; |
| 147 case media::MediaKeys::EXCEPTION_INVALID_MODIFICATION_ERROR: |
| 148 return cdm::kInvalidModificationError; |
| 149 case media::MediaKeys::EXCEPTION_INVALID_ACCESS_ERROR: |
| 150 return cdm::kInvalidAccessError; |
| 151 case media::MediaKeys::EXCEPTION_SECURITY_ERROR: |
| 152 return cdm::kSecurityError; |
| 153 case media::MediaKeys::EXCEPTION_ABORT_ERROR: |
| 154 return cdm::kAbortError; |
| 155 case media::MediaKeys::EXCEPTION_QUOTA_EXCEEDED_ERROR: |
| 156 return cdm::kQuotaExceededError; |
| 157 case media::MediaKeys::EXCEPTION_TIMEOUT_ERROR: |
| 158 return cdm::kTimeoutError; |
| 159 case media::MediaKeys::EXCEPTION_NOT_READABLE_ERROR: |
| 160 return cdm::kNotReadableError; |
| 161 case media::MediaKeys::EXCEPTION_DATA_ERROR: |
| 162 return cdm::kDataError; |
| 163 case media::MediaKeys::EXCEPTION_OPERATION_ERROR: |
| 164 return cdm::kOperationError; |
| 165 case media::MediaKeys::EXCEPTION_VERSION_ERROR: |
| 166 return cdm::kVersionError; |
| 167 case media::MediaKeys::EXCEPTION_UNKNOWN_ERROR: |
| 168 return cdm::kUnknownError; |
| 169 case media::MediaKeys::EXCEPTION_CLIENT_ERROR: |
| 170 return cdm::kClientError; |
| 171 case media::MediaKeys::EXCEPTION_OUTPUT_ERROR: |
| 172 return cdm::kOutputError; |
| 173 } |
| 174 } |
| 175 |
| 176 static media::MediaKeys::SessionType ConvertSessionType( |
| 177 cdm::SessionType session_type) { |
| 178 switch (session_type) { |
| 179 case cdm::kPersistent: |
| 180 return media::MediaKeys::SESSION_TYPE_PERSISTENT; |
| 181 case cdm::kTemporary: |
| 182 return media::MediaKeys::SESSION_TYPE_TEMPORARY; |
| 183 } |
| 184 } |
| 185 |
| 136 template<typename Type> | 186 template<typename Type> |
| 137 class ScopedResetter { | 187 class ScopedResetter { |
| 138 public: | 188 public: |
| 139 explicit ScopedResetter(Type* object) : object_(object) {} | 189 explicit ScopedResetter(Type* object) : object_(object) {} |
| 140 ~ScopedResetter() { object_->Reset(); } | 190 ~ScopedResetter() { object_->Reset(); } |
| 141 | 191 |
| 142 private: | 192 private: |
| 143 Type* const object_; | 193 Type* const object_; |
| 144 }; | 194 }; |
| 145 | 195 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 180 } | 230 } |
| 181 | 231 |
| 182 const char* GetCdmVersion() { | 232 const char* GetCdmVersion() { |
| 183 return kClearKeyCdmVersion; | 233 return kClearKeyCdmVersion; |
| 184 } | 234 } |
| 185 | 235 |
| 186 namespace media { | 236 namespace media { |
| 187 | 237 |
| 188 ClearKeyCdm::ClearKeyCdm(ClearKeyCdmHost* host, const std::string& key_system) | 238 ClearKeyCdm::ClearKeyCdm(ClearKeyCdmHost* host, const std::string& key_system) |
| 189 : decryptor_( | 239 : decryptor_( |
| 190 base::Bind(&ClearKeyCdm::OnSessionCreated, base::Unretained(this)), | 240 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), | 241 host_(host), |
| 196 key_system_(key_system), | 242 key_system_(key_system), |
| 197 last_session_id_(MediaKeys::kInvalidSessionId), | |
| 198 session_id_for_emulated_loadsession_(MediaKeys::kInvalidSessionId), | |
| 199 timer_delay_ms_(kInitialTimerDelayMs), | 243 timer_delay_ms_(kInitialTimerDelayMs), |
| 200 heartbeat_timer_set_(false) { | 244 heartbeat_timer_set_(false) { |
| 201 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) | 245 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) |
| 202 channel_count_ = 0; | 246 channel_count_ = 0; |
| 203 bits_per_channel_ = 0; | 247 bits_per_channel_ = 0; |
| 204 samples_per_second_ = 0; | 248 samples_per_second_ = 0; |
| 205 output_timestamp_base_in_microseconds_ = kNoTimestamp; | 249 output_timestamp_base_in_microseconds_ = kNoTimestamp; |
| 206 total_samples_generated_ = 0; | 250 total_samples_generated_ = 0; |
| 207 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER | 251 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER |
| 208 } | 252 } |
| 209 | 253 |
| 210 ClearKeyCdm::~ClearKeyCdm() {} | 254 ClearKeyCdm::~ClearKeyCdm() {} |
| 211 | 255 |
| 212 void ClearKeyCdm::CreateSession(uint32 session_id, | 256 void ClearKeyCdm::CreateSession(uint32 promise_id, |
| 213 const char* type, | 257 const char* init_data_type, |
| 214 uint32 type_size, | 258 uint32 init_data_type_size, |
| 215 const uint8* init_data, | 259 const uint8* init_data, |
| 216 uint32 init_data_size) { | 260 uint32 init_data_size, |
| 261 cdm::SessionType session_type) { |
| 217 DVLOG(1) << __FUNCTION__; | 262 DVLOG(1) << __FUNCTION__; |
| 218 decryptor_.CreateSession( | |
| 219 session_id, std::string(type, type_size), init_data, init_data_size); | |
| 220 | 263 |
| 221 // Save the latest session ID for heartbeat and file IO test messages. | 264 scoped_ptr<media::NewSessionCdmPromise> promise( |
| 222 last_session_id_ = session_id; | 265 new media::NewSessionCdmPromise( |
| 266 base::Bind(&ClearKeyCdm::OnSessionCreated, |
| 267 base::Unretained(this), |
| 268 promise_id), |
| 269 base::Bind(&ClearKeyCdm::OnSessionCreateFailed, |
| 270 base::Unretained(this), |
| 271 promise_id))); |
| 272 decryptor_.CreateSession(std::string(init_data_type, init_data_type_size), |
| 273 init_data, |
| 274 init_data_size, |
| 275 ConvertSessionType(session_type), |
| 276 promise.Pass()); |
| 223 | 277 |
| 224 if (key_system_ == kExternalClearKeyFileIOTestKeySystem) | 278 if (key_system_ == kExternalClearKeyFileIOTestKeySystem) |
| 225 StartFileIOTest(); | 279 StartFileIOTest(); |
| 226 } | 280 } |
| 227 | 281 |
| 228 // Loads a emulated stored session. Currently only |kLoadableWebSessionId| | 282 // Loads a emulated stored session. Currently only |kLoadableWebSessionId| |
| 229 // (containing a |kLoadableSessionKey| for |kLoadableSessionKeyId|) is | 283 // (containing a |kLoadableSessionKey| for |kLoadableSessionKeyId|) is |
| 230 // supported. | 284 // supported. |
| 231 void ClearKeyCdm::LoadSession(uint32_t session_id, | 285 void ClearKeyCdm::LoadSession(uint32 promise_id, |
| 232 const char* web_session_id, | 286 const char* web_session_id, |
| 233 uint32_t web_session_id_length) { | 287 uint32_t web_session_id_length) { |
| 234 DVLOG(1) << __FUNCTION__; | 288 DVLOG(1) << __FUNCTION__; |
| 235 | 289 |
| 236 if (std::string(kLoadableWebSessionId) != | 290 if (std::string(kLoadableWebSessionId) != |
| 237 std::string(web_session_id, web_session_id_length)) { | 291 std::string(web_session_id, web_session_id_length)) { |
| 238 // TODO(xhwang): Report "NotFoundError" when we support DOMError style. | 292 std::string message("Incorrect session id specified for LoadSession()."); |
| 239 OnSessionError(session_id, MediaKeys::kUnknownError, 0); | 293 host_->OnRejectPromise( |
| 294 promise_id, cdm::kNotFoundError, 0, message.data(), message.length()); |
| 240 return; | 295 return; |
| 241 } | 296 } |
| 242 | 297 |
| 243 session_id_for_emulated_loadsession_ = session_id; | 298 scoped_ptr<media::NewSessionCdmPromise> promise( |
| 244 | 299 new media::NewSessionCdmPromise( |
| 245 decryptor_.CreateSession(session_id, kLoadableSessionContentType, NULL, 0); | 300 base::Bind(&ClearKeyCdm::OnSessionLoaded, |
| 301 base::Unretained(this), |
| 302 promise_id), |
| 303 base::Bind(&ClearKeyCdm::OnSessionLoadFailed, |
| 304 base::Unretained(this), |
| 305 promise_id))); |
| 306 decryptor_.CreateSession(std::string(kLoadableSessionContentType), |
| 307 NULL, |
| 308 0, |
| 309 MediaKeys::SESSION_TYPE_TEMPORARY, |
| 310 promise.Pass()); |
| 246 } | 311 } |
| 247 | 312 |
| 248 void ClearKeyCdm::UpdateSession(uint32 session_id, | 313 void ClearKeyCdm::UpdateSession(uint32 promise_id, |
| 314 const char* web_session_id, |
| 315 uint32_t web_session_id_size, |
| 249 const uint8* response, | 316 const uint8* response, |
| 250 uint32 response_size) { | 317 uint32 response_size) { |
| 251 DVLOG(1) << __FUNCTION__; | 318 DVLOG(1) << __FUNCTION__; |
| 252 decryptor_.UpdateSession(session_id, response, response_size); | 319 std::string web_session_str(web_session_id, web_session_id_size); |
| 320 |
| 321 scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise( |
| 322 base::Bind(&ClearKeyCdm::OnSessionUpdated, |
| 323 base::Unretained(this), |
| 324 promise_id, |
| 325 web_session_str), |
| 326 base::Bind(&ClearKeyCdm::OnSessionUpdateFailed, |
| 327 base::Unretained(this), |
| 328 promise_id))); |
| 329 decryptor_.UpdateSession( |
| 330 web_session_str, response, response_size, promise.Pass()); |
| 253 | 331 |
| 254 if (!heartbeat_timer_set_) { | 332 if (!heartbeat_timer_set_) { |
| 255 ScheduleNextHeartBeat(); | 333 ScheduleNextHeartBeat(); |
| 256 heartbeat_timer_set_ = true; | 334 heartbeat_timer_set_ = true; |
| 257 } | 335 } |
| 258 } | 336 } |
| 259 | 337 |
| 260 void ClearKeyCdm::ReleaseSession(uint32 session_id) { | 338 void ClearKeyCdm::ReleaseSession(uint32 promise_id, |
| 339 const char* web_session_id, |
| 340 uint32_t web_session_id_size) { |
| 261 DVLOG(1) << __FUNCTION__; | 341 DVLOG(1) << __FUNCTION__; |
| 262 decryptor_.ReleaseSession(session_id); | 342 std::string web_session_str(web_session_id, web_session_id_size); |
| 343 |
| 344 scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise( |
| 345 base::Bind(&ClearKeyCdm::OnSessionReleased, |
| 346 base::Unretained(this), |
| 347 promise_id, |
| 348 web_session_str), |
| 349 base::Bind(&ClearKeyCdm::OnSessionReleaseFailed, |
| 350 base::Unretained(this), |
| 351 promise_id))); |
| 352 decryptor_.ReleaseSession(web_session_str, promise.Pass()); |
| 353 } |
| 354 |
| 355 void ClearKeyCdm::SetServerCertificate(uint32 promise_id, |
| 356 const uint8_t* server_certificate_data, |
| 357 uint32_t server_certificate_data_size) { |
| 358 // ClearKey doesn't use a server certificate. |
| 359 host_->OnResolvePromise(promise_id); |
| 263 } | 360 } |
| 264 | 361 |
| 265 void ClearKeyCdm::TimerExpired(void* context) { | 362 void ClearKeyCdm::TimerExpired(void* context) { |
| 266 if (context == &session_id_for_emulated_loadsession_) { | 363 if (context == &session_id_for_emulated_loadsession_) { |
| 267 LoadLoadableSession(); | 364 LoadLoadableSession(); |
| 268 return; | 365 return; |
| 269 } | 366 } |
| 270 | 367 |
| 271 DCHECK(heartbeat_timer_set_); | 368 DCHECK(heartbeat_timer_set_); |
| 272 std::string heartbeat_message; | 369 std::string heartbeat_message; |
| 273 if (!next_heartbeat_message_.empty() && | 370 if (!next_heartbeat_message_.empty() && |
| 274 context == &next_heartbeat_message_[0]) { | 371 context == &next_heartbeat_message_[0]) { |
| 275 heartbeat_message = next_heartbeat_message_; | 372 heartbeat_message = next_heartbeat_message_; |
| 276 } else { | 373 } else { |
| 277 heartbeat_message = "ERROR: Invalid timer context found!"; | 374 heartbeat_message = "ERROR: Invalid timer context found!"; |
| 278 } | 375 } |
| 279 | 376 |
| 280 // This URL is only used for testing the code path for defaultURL. | 377 // 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. | 378 // There is no service at this URL, so applications should ignore it. |
| 282 const char url[] = "http://test.externalclearkey.chromium.org"; | 379 const char url[] = "http://test.externalclearkey.chromium.org"; |
| 283 | 380 |
| 284 host_->OnSessionMessage(last_session_id_, | 381 host_->OnSessionMessage(last_session_id_.data(), |
| 382 last_session_id_.length(), |
| 285 heartbeat_message.data(), | 383 heartbeat_message.data(), |
| 286 heartbeat_message.size(), | 384 heartbeat_message.length(), |
| 287 url, | 385 url, |
| 288 arraysize(url) - 1); | 386 arraysize(url) - 1); |
| 289 | 387 |
| 290 ScheduleNextHeartBeat(); | 388 ScheduleNextHeartBeat(); |
| 291 } | 389 } |
| 292 | 390 |
| 293 static void CopyDecryptResults( | 391 static void CopyDecryptResults( |
| 294 media::Decryptor::Status* status_copy, | 392 media::Decryptor::Status* status_copy, |
| 295 scoped_refptr<media::DecoderBuffer>* buffer_copy, | 393 scoped_refptr<media::DecoderBuffer>* buffer_copy, |
| 296 media::Decryptor::Status status, | 394 media::Decryptor::Status status, |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 | 567 |
| 470 void ClearKeyCdm::Destroy() { | 568 void ClearKeyCdm::Destroy() { |
| 471 DVLOG(1) << "Destroy()"; | 569 DVLOG(1) << "Destroy()"; |
| 472 delete this; | 570 delete this; |
| 473 } | 571 } |
| 474 | 572 |
| 475 void ClearKeyCdm::ScheduleNextHeartBeat() { | 573 void ClearKeyCdm::ScheduleNextHeartBeat() { |
| 476 // Prepare the next heartbeat message and set timer. | 574 // Prepare the next heartbeat message and set timer. |
| 477 std::ostringstream msg_stream; | 575 std::ostringstream msg_stream; |
| 478 msg_stream << kHeartBeatHeader << " from ClearKey CDM set at time " | 576 msg_stream << kHeartBeatHeader << " from ClearKey CDM set at time " |
| 479 << host_->GetCurrentWallTimeInSeconds() << "."; | 577 << host_->GetCurrentTime() << "."; |
| 480 next_heartbeat_message_ = msg_stream.str(); | 578 next_heartbeat_message_ = msg_stream.str(); |
| 481 | 579 |
| 482 host_->SetTimer(timer_delay_ms_, &next_heartbeat_message_[0]); | 580 host_->SetTimer(timer_delay_ms_, &next_heartbeat_message_[0]); |
| 483 | 581 |
| 484 // Use a smaller timer delay at start-up to facilitate testing. Increase the | 582 // Use a smaller timer delay at start-up to facilitate testing. Increase the |
| 485 // timer delay up to a limit to avoid message spam. | 583 // timer delay up to a limit to avoid message spam. |
| 486 if (timer_delay_ms_ < kMaxTimerDelayMs) | 584 if (timer_delay_ms_ < kMaxTimerDelayMs) |
| 487 timer_delay_ms_ = std::min(2 * timer_delay_ms_, kMaxTimerDelayMs); | 585 timer_delay_ms_ = std::min(2 * timer_delay_ms_, kMaxTimerDelayMs); |
| 488 } | 586 } |
| 489 | 587 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 528 NOTIMPLEMENTED(); | 626 NOTIMPLEMENTED(); |
| 529 }; | 627 }; |
| 530 | 628 |
| 531 void ClearKeyCdm::LoadLoadableSession() { | 629 void ClearKeyCdm::LoadLoadableSession() { |
| 532 std::string jwk_set = GenerateJWKSet(kLoadableSessionKey, | 630 std::string jwk_set = GenerateJWKSet(kLoadableSessionKey, |
| 533 sizeof(kLoadableSessionKey), | 631 sizeof(kLoadableSessionKey), |
| 534 kLoadableSessionKeyId, | 632 kLoadableSessionKeyId, |
| 535 sizeof(kLoadableSessionKeyId) - 1); | 633 sizeof(kLoadableSessionKeyId) - 1); |
| 536 // TODO(xhwang): This triggers OnSessionUpdated(). For prefixed EME support, | 634 // TODO(xhwang): This triggers OnSessionUpdated(). For prefixed EME support, |
| 537 // this is okay. Check WD EME support. | 635 // this is okay. Check WD EME support. |
| 636 scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise( |
| 637 base::Bind(&ClearKeyCdm::OnSessionUpdated, |
| 638 base::Unretained(this), |
| 639 promise_id_for_emulated_loadsession_, |
| 640 session_id_for_emulated_loadsession_), |
| 641 base::Bind(&ClearKeyCdm::OnSessionUpdateFailed, |
| 642 base::Unretained(this), |
| 643 promise_id_for_emulated_loadsession_))); |
| 538 decryptor_.UpdateSession(session_id_for_emulated_loadsession_, | 644 decryptor_.UpdateSession(session_id_for_emulated_loadsession_, |
| 539 reinterpret_cast<const uint8*>(jwk_set.data()), | 645 reinterpret_cast<const uint8*>(jwk_set.data()), |
| 540 jwk_set.size()); | 646 jwk_set.size(), |
| 647 promise.Pass()); |
| 541 } | 648 } |
| 542 | 649 |
| 543 void ClearKeyCdm::OnSessionCreated(uint32 session_id, | 650 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, | 651 const std::vector<uint8>& message, |
| 565 const std::string& destination_url) { | 652 const std::string& destination_url) { |
| 566 DVLOG(1) << "OnSessionMessage: " << message.size(); | 653 DVLOG(1) << "OnSessionMessage: " << message.size(); |
| 567 | 654 |
| 568 // Ignore the message when we are waiting to update the loadable session. | 655 // Ignore the message when we are waiting to update the loadable session. |
| 569 if (session_id == session_id_for_emulated_loadsession_) | 656 if (web_session_id == session_id_for_emulated_loadsession_) |
| 570 return; | 657 return; |
| 571 | 658 |
| 572 host_->OnSessionMessage(session_id, | 659 // OnSessionMessage() only called during CreateSession(), so no promise |
| 660 // involved (OnSessionCreated() called to resolve the CreateSession() |
| 661 // promise). |
| 662 host_->OnSessionMessage(web_session_id.data(), |
| 663 web_session_id.length(), |
| 573 reinterpret_cast<const char*>(message.data()), | 664 reinterpret_cast<const char*>(message.data()), |
| 574 message.size(), | 665 message.size(), |
| 575 destination_url.data(), | 666 destination_url.data(), |
| 576 destination_url.size()); | 667 destination_url.length()); |
| 577 } | 668 } |
| 578 | 669 |
| 579 void ClearKeyCdm::OnSessionReady(uint32 session_id) { | 670 void ClearKeyCdm::OnSessionCreated(uint32 promise_id, |
| 580 if (session_id == session_id_for_emulated_loadsession_) { | 671 const std::string& web_session_id) { |
| 581 session_id_for_emulated_loadsession_ = MediaKeys::kInvalidSessionId; | 672 // Save the latest session ID for heartbeat and file IO test messages. |
| 582 host_->OnSessionCreated( | 673 last_session_id_ = web_session_id; |
| 583 session_id, kLoadableWebSessionId, strlen(kLoadableWebSessionId)); | 674 |
| 675 host_->OnResolveNewSessionPromise( |
| 676 promise_id, web_session_id.data(), web_session_id.length()); |
| 677 } |
| 678 |
| 679 void ClearKeyCdm::OnSessionCreateFailed(uint32 promise_id, |
| 680 MediaKeys::Exception exception_code, |
| 681 uint32 system_code, |
| 682 const std::string& error_message) { |
| 683 RejectPromise(promise_id, exception_code, system_code, error_message); |
| 684 } |
| 685 |
| 686 void ClearKeyCdm::OnSessionLoaded(uint32 promise_id, |
| 687 const std::string& web_session_id) { |
| 688 // Save the latest session ID for heartbeat and file IO test messages. |
| 689 last_session_id_ = web_session_id; |
| 690 |
| 691 // |decryptor_| created some session as |web_session_id|, but going forward |
| 692 // we need to map that to |kLoadableWebSessionId|, as that is what callers |
| 693 // expect. |
| 694 session_id_for_emulated_loadsession_ = web_session_id; |
| 695 |
| 696 // Delay LoadLoadableSession() to test the case where Decrypt*() calls are |
| 697 // made before the session is fully loaded. |
| 698 const int64 kDelayToLoadSessionMs = 500; |
| 699 |
| 700 // Defer resolving the promise until the session is loaded. |
| 701 promise_id_for_emulated_loadsession_ = promise_id; |
| 702 |
| 703 // Use the address of |session_id_for_emulated_loadsession_| as the timer |
| 704 // context so that we can call LoadLoadableSession() when the timer expires. |
| 705 host_->SetTimer(kDelayToLoadSessionMs, &session_id_for_emulated_loadsession_); |
| 706 } |
| 707 |
| 708 void ClearKeyCdm::OnSessionLoadFailed(uint32 promise_id, |
| 709 MediaKeys::Exception exception_code, |
| 710 uint32 system_code, |
| 711 const std::string& error_message) { |
| 712 RejectPromise(promise_id, exception_code, system_code, error_message); |
| 713 } |
| 714 |
| 715 void ClearKeyCdm::OnSessionUpdated(uint32 promise_id, |
| 716 const std::string& web_session_id) { |
| 717 // OnSessionReady() only called as success for UpdateSession(). However, |
| 718 // UpdateSession() also called to finish loading sessions, so handle |
| 719 // appropriately. |
| 720 if (web_session_id == session_id_for_emulated_loadsession_) { |
| 721 session_id_for_emulated_loadsession_ = std::string(); |
| 722 // |promise_id| is the LoadSession() promise, so resolve appropriately. |
| 723 host_->OnResolveNewSessionPromise( |
| 724 promise_id, kLoadableWebSessionId, strlen(kLoadableWebSessionId)); |
| 725 host_->OnSessionReady(kLoadableWebSessionId, strlen(kLoadableWebSessionId)); |
| 726 return; |
| 584 } | 727 } |
| 585 | 728 |
| 586 host_->OnSessionReady(session_id); | 729 host_->OnResolvePromise(promise_id); |
| 587 } | 730 } |
| 588 | 731 |
| 589 void ClearKeyCdm::OnSessionClosed(uint32 session_id) { | 732 void ClearKeyCdm::OnSessionUpdateFailed(uint32 promise_id, |
| 590 host_->OnSessionClosed(session_id); | 733 MediaKeys::Exception exception_code, |
| 734 uint32 system_code, |
| 735 const std::string& error_message) { |
| 736 RejectPromise(promise_id, exception_code, system_code, error_message); |
| 591 } | 737 } |
| 592 | 738 |
| 593 void ClearKeyCdm::OnSessionError(uint32 session_id, | 739 void ClearKeyCdm::OnSessionReleased(uint32 promise_id, |
| 594 media::MediaKeys::KeyError error_code, | 740 const std::string& web_session_id) { |
| 595 uint32 system_code) { | 741 host_->OnResolvePromise(promise_id); |
| 596 host_->OnSessionError( | 742 } |
| 597 session_id, static_cast<cdm::MediaKeyError>(error_code), system_code); | 743 |
| 744 void ClearKeyCdm::OnSessionReleaseFailed(uint32 promise_id, |
| 745 MediaKeys::Exception exception_code, |
| 746 uint32 system_code, |
| 747 const std::string& error_message) { |
| 748 RejectPromise(promise_id, exception_code, system_code, error_message); |
| 749 } |
| 750 |
| 751 void ClearKeyCdm::RejectPromise(uint32 promise_id, |
| 752 MediaKeys::Exception exception_code, |
| 753 uint32 system_code, |
| 754 const std::string& error_message) { |
| 755 host_->OnRejectPromise(promise_id, |
| 756 ConvertException(exception_code), |
| 757 system_code, |
| 758 error_message.data(), |
| 759 error_message.length()); |
| 598 } | 760 } |
| 599 | 761 |
| 600 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) | 762 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) |
| 601 int64 ClearKeyCdm::CurrentTimeStampInMicroseconds() const { | 763 int64 ClearKeyCdm::CurrentTimeStampInMicroseconds() const { |
| 602 return output_timestamp_base_in_microseconds_ + | 764 return output_timestamp_base_in_microseconds_ + |
| 603 base::Time::kMicrosecondsPerSecond * | 765 base::Time::kMicrosecondsPerSecond * |
| 604 total_samples_generated_ / samples_per_second_; | 766 total_samples_generated_ / samples_per_second_; |
| 605 } | 767 } |
| 606 | 768 |
| 607 int ClearKeyCdm::GenerateFakeAudioFramesFromDuration( | 769 int ClearKeyCdm::GenerateFakeAudioFramesFromDuration( |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 void ClearKeyCdm::StartFileIOTest() { | 821 void ClearKeyCdm::StartFileIOTest() { |
| 660 file_io_test_runner_.reset(new FileIOTestRunner( | 822 file_io_test_runner_.reset(new FileIOTestRunner( |
| 661 base::Bind(&ClearKeyCdmHost::CreateFileIO, base::Unretained(host_)))); | 823 base::Bind(&ClearKeyCdmHost::CreateFileIO, base::Unretained(host_)))); |
| 662 file_io_test_runner_->RunAllTests( | 824 file_io_test_runner_->RunAllTests( |
| 663 base::Bind(&ClearKeyCdm::OnFileIOTestComplete, base::Unretained(this))); | 825 base::Bind(&ClearKeyCdm::OnFileIOTestComplete, base::Unretained(this))); |
| 664 } | 826 } |
| 665 | 827 |
| 666 void ClearKeyCdm::OnFileIOTestComplete(bool success) { | 828 void ClearKeyCdm::OnFileIOTestComplete(bool success) { |
| 667 DVLOG(1) << __FUNCTION__ << ": " << success; | 829 DVLOG(1) << __FUNCTION__ << ": " << success; |
| 668 std::string message = GetFileIOTestResultMessage(success); | 830 std::string message = GetFileIOTestResultMessage(success); |
| 669 host_->OnSessionMessage( | 831 host_->OnSessionMessage(last_session_id_.data(), |
| 670 last_session_id_, message.data(), message.size(), NULL, 0); | 832 last_session_id_.length(), |
| 833 message.data(), |
| 834 message.length(), |
| 835 NULL, |
| 836 0); |
| 671 file_io_test_runner_.reset(); | 837 file_io_test_runner_.reset(); |
| 672 } | 838 } |
| 673 | 839 |
| 674 } // namespace media | 840 } // namespace media |
| OLD | NEW |