| 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/cdm_adapter.h" | 5 #include "media/cdm/ppapi/cdm_adapter.h" |
| 6 | 6 |
| 7 #include "media/base/limits.h" | 7 #include "media/base/limits.h" |
| 8 #include "media/cdm/ppapi/cdm_file_io_impl.h" | 8 #include "media/cdm/ppapi/cdm_file_io_impl.h" |
| 9 #include "media/cdm/ppapi/cdm_helpers.h" | 9 #include "media/cdm/ppapi/cdm_helpers.h" |
| 10 #include "media/cdm/ppapi/cdm_logging.h" | 10 #include "media/cdm/ppapi/cdm_logging.h" |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 deferred_audio_decoder_config_id_(0), | 333 deferred_audio_decoder_config_id_(0), |
| 334 deferred_initialize_video_decoder_(false), | 334 deferred_initialize_video_decoder_(false), |
| 335 deferred_video_decoder_config_id_(0), | 335 deferred_video_decoder_config_id_(0), |
| 336 last_read_file_size_kb_(0), | 336 last_read_file_size_kb_(0), |
| 337 file_size_uma_reported_(false) { | 337 file_size_uma_reported_(false) { |
| 338 callback_factory_.Initialize(this); | 338 callback_factory_.Initialize(this); |
| 339 } | 339 } |
| 340 | 340 |
| 341 CdmAdapter::~CdmAdapter() {} | 341 CdmAdapter::~CdmAdapter() {} |
| 342 | 342 |
| 343 bool CdmAdapter::CreateCdmInstance(const std::string& key_system) { | 343 CdmWrapper* CdmAdapter::CreateCdmInstance(const std::string& key_system) { |
| 344 PP_DCHECK(!cdm_); | 344 CdmWrapper* cdm = CdmWrapper::Create(key_system.data(), key_system.size(), |
| 345 cdm_ = make_linked_ptr(CdmWrapper::Create( | 345 GetCdmHost, this); |
| 346 key_system.data(), key_system.size(), GetCdmHost, this)); | |
| 347 bool success = cdm_ != NULL; | |
| 348 | 346 |
| 349 const std::string message = "CDM instance for " + key_system + | 347 const std::string message = "CDM instance for " + key_system + |
| 350 (success ? "" : " could not be") + " created."; | 348 (cdm ? "" : " could not be") + " created."; |
| 351 DLOG_TO_CONSOLE(message); | 349 DLOG_TO_CONSOLE(message); |
| 352 CDM_DLOG() << message; | 350 CDM_DLOG() << message; |
| 353 | 351 |
| 354 return success; | 352 return cdm; |
| 355 } | 353 } |
| 356 | 354 |
| 357 // No errors should be reported in this function because the spec says: | 355 void CdmAdapter::Initialize(uint32_t promise_id, |
| 358 // "Store this new error object internally with the MediaKeys instance being | 356 const std::string& key_system, |
| 359 // created. This will be used to fire an error against any session created for | |
| 360 // this instance." These errors will be reported during session creation | |
| 361 // (CreateSession()) or session loading (LoadSession()). | |
| 362 // TODO(xhwang): If necessary, we need to store the error here if we want to | |
| 363 // support more specific error reporting (other than "Unknown"). | |
| 364 void CdmAdapter::Initialize(const std::string& key_system, | |
| 365 bool allow_distinctive_identifier, | 357 bool allow_distinctive_identifier, |
| 366 bool allow_persistent_state) { | 358 bool allow_persistent_state) { |
| 367 PP_DCHECK(!key_system.empty()); | 359 PP_DCHECK(!key_system.empty()); |
| 368 // TODO(jrummell): Remove this check when CDM creation is asynchronous. | 360 PP_DCHECK(!cdm_); |
| 369 // http://crbug.com/469003 | |
| 370 PP_DCHECK(key_system_.empty() || (key_system_ == key_system && cdm_)); | |
| 371 | 361 |
| 372 #if defined(CHECK_DOCUMENT_URL) | 362 #if defined(CHECK_DOCUMENT_URL) |
| 373 PP_URLComponents_Dev url_components = {}; | 363 PP_URLComponents_Dev url_components = {}; |
| 374 const pp::URLUtil_Dev* url_util = pp::URLUtil_Dev::Get(); | 364 const pp::URLUtil_Dev* url_util = pp::URLUtil_Dev::Get(); |
| 375 if (!url_util) | 365 if (!url_util) { |
| 366 RejectPromise(promise_id, cdm::kUnknownError, 0, |
| 367 "Unable to determine origin."); |
| 376 return; | 368 return; |
| 369 } |
| 370 |
| 377 pp::Var href = url_util->GetDocumentURL(pp::InstanceHandle(pp_instance()), | 371 pp::Var href = url_util->GetDocumentURL(pp::InstanceHandle(pp_instance()), |
| 378 &url_components); | 372 &url_components); |
| 379 PP_DCHECK(href.is_string()); | 373 PP_DCHECK(href.is_string()); |
| 380 std::string url = href.AsString(); | 374 std::string url = href.AsString(); |
| 381 PP_DCHECK(!url.empty()); | 375 PP_DCHECK(!url.empty()); |
| 382 std::string url_scheme = | 376 std::string url_scheme = |
| 383 url.substr(url_components.scheme.begin, url_components.scheme.len); | 377 url.substr(url_components.scheme.begin, url_components.scheme.len); |
| 384 if (url_scheme != "file") { | 378 if (url_scheme != "file") { |
| 385 // Skip this check for file:// URLs as they don't have a host component. | 379 // Skip this check for file:// URLs as they don't have a host component. |
| 386 PP_DCHECK(url_components.host.begin); | 380 PP_DCHECK(url_components.host.begin); |
| 387 PP_DCHECK(0 < url_components.host.len); | 381 PP_DCHECK(0 < url_components.host.len); |
| 388 } | 382 } |
| 389 #endif // defined(CHECK_DOCUMENT_URL) | 383 #endif // defined(CHECK_DOCUMENT_URL) |
| 390 | 384 |
| 391 if (!cdm_ && !CreateCdmInstance(key_system)) | 385 cdm_ = make_linked_ptr(CreateCdmInstance(key_system)); |
| 386 if (!cdm_) { |
| 387 RejectPromise(promise_id, cdm::kInvalidAccessError, 0, |
| 388 "Unable to create CDM."); |
| 392 return; | 389 return; |
| 390 } |
| 393 | 391 |
| 394 PP_DCHECK(cdm_); | |
| 395 key_system_ = key_system; | 392 key_system_ = key_system; |
| 396 allow_distinctive_identifier_ = allow_distinctive_identifier; | 393 allow_distinctive_identifier_ = allow_distinctive_identifier; |
| 397 allow_persistent_state_ = allow_persistent_state; | 394 allow_persistent_state_ = allow_persistent_state; |
| 398 cdm_->Initialize(allow_distinctive_identifier, allow_persistent_state); | 395 cdm_->Initialize(allow_distinctive_identifier, allow_persistent_state); |
| 396 OnResolvePromise(promise_id); |
| 399 } | 397 } |
| 400 | 398 |
| 401 void CdmAdapter::SetServerCertificate(uint32_t promise_id, | 399 void CdmAdapter::SetServerCertificate(uint32_t promise_id, |
| 402 pp::VarArrayBuffer server_certificate) { | 400 pp::VarArrayBuffer server_certificate) { |
| 403 const uint8_t* server_certificate_ptr = | 401 const uint8_t* server_certificate_ptr = |
| 404 static_cast<const uint8_t*>(server_certificate.Map()); | 402 static_cast<const uint8_t*>(server_certificate.Map()); |
| 405 const uint32_t server_certificate_size = server_certificate.ByteLength(); | 403 const uint32_t server_certificate_size = server_certificate.ByteLength(); |
| 406 | 404 |
| 407 if (!server_certificate_ptr || | 405 if (!server_certificate_ptr || |
| 408 server_certificate_size < media::limits::kMinCertificateLength || | 406 server_certificate_size < media::limits::kMinCertificateLength || |
| 409 server_certificate_size > media::limits::kMaxCertificateLength) { | 407 server_certificate_size > media::limits::kMaxCertificateLength) { |
| 410 RejectPromise( | 408 RejectPromise( |
| 411 promise_id, cdm::kInvalidAccessError, 0, "Incorrect certificate."); | 409 promise_id, cdm::kInvalidAccessError, 0, "Incorrect certificate."); |
| 412 return; | 410 return; |
| 413 } | 411 } |
| 414 | 412 |
| 415 // Initialize() doesn't report an error, so SetServerCertificate() can be | |
| 416 // called even if Initialize() failed. | |
| 417 // TODO(jrummell): Remove this code when prefixed EME gets removed. | |
| 418 if (!cdm_) { | |
| 419 RejectPromise(promise_id, | |
| 420 cdm::kInvalidStateError, | |
| 421 0, | |
| 422 "CDM has not been initialized."); | |
| 423 return; | |
| 424 } | |
| 425 | |
| 426 cdm_->SetServerCertificate( | 413 cdm_->SetServerCertificate( |
| 427 promise_id, server_certificate_ptr, server_certificate_size); | 414 promise_id, server_certificate_ptr, server_certificate_size); |
| 428 } | 415 } |
| 429 | 416 |
| 430 void CdmAdapter::CreateSessionAndGenerateRequest(uint32_t promise_id, | 417 void CdmAdapter::CreateSessionAndGenerateRequest(uint32_t promise_id, |
| 431 PP_SessionType session_type, | 418 PP_SessionType session_type, |
| 432 PP_InitDataType init_data_type, | 419 PP_InitDataType init_data_type, |
| 433 pp::VarArrayBuffer init_data) { | 420 pp::VarArrayBuffer init_data) { |
| 434 // Initialize() doesn't report an error, so CreateSession() can be called | |
| 435 // even if Initialize() failed. | |
| 436 // TODO(jrummell): Remove this code when prefixed EME gets removed. | |
| 437 // TODO(jrummell): Verify that Initialize() failing does not resolve the | |
| 438 // MediaKeys.create() promise. | |
| 439 if (!cdm_) { | |
| 440 RejectPromise(promise_id, | |
| 441 cdm::kInvalidStateError, | |
| 442 0, | |
| 443 "CDM has not been initialized."); | |
| 444 return; | |
| 445 } | |
| 446 | |
| 447 cdm_->CreateSessionAndGenerateRequest( | 421 cdm_->CreateSessionAndGenerateRequest( |
| 448 promise_id, PpSessionTypeToCdmSessionType(session_type), | 422 promise_id, PpSessionTypeToCdmSessionType(session_type), |
| 449 PpInitDataTypeToCdmInitDataType(init_data_type), | 423 PpInitDataTypeToCdmInitDataType(init_data_type), |
| 450 static_cast<const uint8_t*>(init_data.Map()), init_data.ByteLength()); | 424 static_cast<const uint8_t*>(init_data.Map()), init_data.ByteLength()); |
| 451 } | 425 } |
| 452 | 426 |
| 453 void CdmAdapter::LoadSession(uint32_t promise_id, | 427 void CdmAdapter::LoadSession(uint32_t promise_id, |
| 454 PP_SessionType session_type, | 428 PP_SessionType session_type, |
| 455 const std::string& session_id) { | 429 const std::string& session_id) { |
| 456 // Initialize() doesn't report an error, so LoadSession() can be called | |
| 457 // even if Initialize() failed. | |
| 458 // TODO(jrummell): Remove this code when prefixed EME gets removed. | |
| 459 // TODO(jrummell): Verify that Initialize() failing does not resolve the | |
| 460 // MediaKeys.create() promise. | |
| 461 if (!cdm_) { | |
| 462 RejectPromise(promise_id, | |
| 463 cdm::kInvalidStateError, | |
| 464 0, | |
| 465 "CDM has not been initialized."); | |
| 466 return; | |
| 467 } | |
| 468 | |
| 469 cdm_->LoadSession(promise_id, PpSessionTypeToCdmSessionType(session_type), | 430 cdm_->LoadSession(promise_id, PpSessionTypeToCdmSessionType(session_type), |
| 470 session_id.data(), session_id.size()); | 431 session_id.data(), session_id.size()); |
| 471 } | 432 } |
| 472 | 433 |
| 473 void CdmAdapter::UpdateSession(uint32_t promise_id, | 434 void CdmAdapter::UpdateSession(uint32_t promise_id, |
| 474 const std::string& session_id, | 435 const std::string& session_id, |
| 475 pp::VarArrayBuffer response) { | 436 pp::VarArrayBuffer response) { |
| 476 const uint8_t* response_ptr = static_cast<const uint8_t*>(response.Map()); | 437 const uint8_t* response_ptr = static_cast<const uint8_t*>(response.Map()); |
| 477 const uint32_t response_size = response.ByteLength(); | 438 const uint32_t response_size = response.ByteLength(); |
| 478 | 439 |
| (...skipping 899 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1378 } // namespace media | 1339 } // namespace media |
| 1379 | 1340 |
| 1380 namespace pp { | 1341 namespace pp { |
| 1381 | 1342 |
| 1382 // Factory function for your specialization of the Module object. | 1343 // Factory function for your specialization of the Module object. |
| 1383 Module* CreateModule() { | 1344 Module* CreateModule() { |
| 1384 return new media::CdmAdapterModule(); | 1345 return new media::CdmAdapterModule(); |
| 1385 } | 1346 } |
| 1386 | 1347 |
| 1387 } // namespace pp | 1348 } // namespace pp |
| OLD | NEW |