Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/browser/media/cdm/browser_cdm_manager.h" | 5 #include "content/browser/media/cdm/browser_cdm_manager.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 170 } | 170 } |
| 171 | 171 |
| 172 bool BrowserCdmManager::OnMessageReceived(const IPC::Message& msg) { | 172 bool BrowserCdmManager::OnMessageReceived(const IPC::Message& msg) { |
| 173 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 173 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 174 bool handled = true; | 174 bool handled = true; |
| 175 IPC_BEGIN_MESSAGE_MAP(BrowserCdmManager, msg) | 175 IPC_BEGIN_MESSAGE_MAP(BrowserCdmManager, msg) |
| 176 IPC_MESSAGE_HANDLER(CdmHostMsg_InitializeCdm, OnInitializeCdm) | 176 IPC_MESSAGE_HANDLER(CdmHostMsg_InitializeCdm, OnInitializeCdm) |
| 177 IPC_MESSAGE_HANDLER(CdmHostMsg_SetServerCertificate, OnSetServerCertificate) | 177 IPC_MESSAGE_HANDLER(CdmHostMsg_SetServerCertificate, OnSetServerCertificate) |
| 178 IPC_MESSAGE_HANDLER(CdmHostMsg_CreateSessionAndGenerateRequest, | 178 IPC_MESSAGE_HANDLER(CdmHostMsg_CreateSessionAndGenerateRequest, |
| 179 OnCreateSessionAndGenerateRequest) | 179 OnCreateSessionAndGenerateRequest) |
| 180 IPC_MESSAGE_HANDLER(CdmHostMsg_LoadSession, OnLoadSession) | |
| 180 IPC_MESSAGE_HANDLER(CdmHostMsg_UpdateSession, OnUpdateSession) | 181 IPC_MESSAGE_HANDLER(CdmHostMsg_UpdateSession, OnUpdateSession) |
| 181 IPC_MESSAGE_HANDLER(CdmHostMsg_CloseSession, OnCloseSession) | 182 IPC_MESSAGE_HANDLER(CdmHostMsg_CloseSession, OnCloseSession) |
| 183 IPC_MESSAGE_HANDLER(CdmHostMsg_RemoveSession, OnRemoveSession) | |
| 182 IPC_MESSAGE_HANDLER(CdmHostMsg_DestroyCdm, OnDestroyCdm) | 184 IPC_MESSAGE_HANDLER(CdmHostMsg_DestroyCdm, OnDestroyCdm) |
| 183 IPC_MESSAGE_UNHANDLED(handled = false) | 185 IPC_MESSAGE_UNHANDLED(handled = false) |
| 184 IPC_END_MESSAGE_MAP() | 186 IPC_END_MESSAGE_MAP() |
| 185 return handled; | 187 return handled; |
| 186 } | 188 } |
| 187 | 189 |
| 188 media::BrowserCdm* BrowserCdmManager::GetCdm(int render_frame_id, | 190 media::BrowserCdm* BrowserCdmManager::GetCdm(int render_frame_id, |
| 189 int cdm_id) const { | 191 int cdm_id) const { |
| 190 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 192 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 191 return cdm_map_.get(GetId(render_frame_id, cdm_id)); | 193 return cdm_map_.get(GetId(render_frame_id, cdm_id)); |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 327 | 329 |
| 328 if (certificate.empty()) { | 330 if (certificate.empty()) { |
| 329 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Empty certificate."); | 331 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Empty certificate."); |
| 330 return; | 332 return; |
| 331 } | 333 } |
| 332 | 334 |
| 333 cdm->SetServerCertificate(certificate, promise.Pass()); | 335 cdm->SetServerCertificate(certificate, promise.Pass()); |
| 334 } | 336 } |
| 335 | 337 |
| 336 void BrowserCdmManager::OnCreateSessionAndGenerateRequest( | 338 void BrowserCdmManager::OnCreateSessionAndGenerateRequest( |
| 337 int render_frame_id, | 339 const CdmHostMsg_CreateSessionAndGenerateRequest_Params& params) { |
| 338 int cdm_id, | |
| 339 uint32_t promise_id, | |
| 340 CdmHostMsg_CreateSession_InitDataType init_data_type, | |
| 341 const std::vector<uint8>& init_data) { | |
| 342 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 340 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 343 | 341 |
| 342 int render_frame_id = params.render_frame_id; | |
| 343 int cdm_id = params.cdm_id; | |
| 344 const std::vector<uint8>& init_data = params.init_data; | |
| 344 scoped_ptr<NewSessionPromise> promise( | 345 scoped_ptr<NewSessionPromise> promise( |
| 345 new NewSessionPromise(this, render_frame_id, cdm_id, promise_id)); | 346 new NewSessionPromise(this, render_frame_id, cdm_id, params.promise_id)); |
| 346 | 347 |
| 347 if (init_data.size() > media::limits::kMaxInitDataLength) { | 348 if (init_data.size() > media::limits::kMaxInitDataLength) { |
| 348 LOG(WARNING) << "InitData for ID: " << cdm_id | 349 LOG(WARNING) << "InitData for ID: " << cdm_id |
| 349 << " too long: " << init_data.size(); | 350 << " too long: " << init_data.size(); |
| 350 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Init data too long."); | 351 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Init data too long."); |
| 351 return; | 352 return; |
| 352 } | 353 } |
| 353 #if defined(OS_ANDROID) | 354 #if defined(OS_ANDROID) |
| 354 // 'webm' initData is a single key ID. On Android the length is restricted. | 355 // 'webm' initData is a single key ID. On Android the length is restricted. |
| 355 if (init_data_type == INIT_DATA_TYPE_WEBM && | 356 if (params.init_data_type == INIT_DATA_TYPE_WEBM && |
| 356 init_data.size() != kAndroidKeyIdBytes) { | 357 init_data.size() != kAndroidKeyIdBytes) { |
| 357 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, | 358 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, |
| 358 "'webm' initData is not the correct length."); | 359 "'webm' initData is not the correct length."); |
| 359 return; | 360 return; |
| 360 } | 361 } |
| 361 #endif | 362 #endif |
| 362 | 363 |
| 363 media::EmeInitDataType eme_init_data_type; | 364 media::EmeInitDataType eme_init_data_type; |
| 364 switch (init_data_type) { | 365 switch (params.init_data_type) { |
| 365 case INIT_DATA_TYPE_WEBM: | 366 case INIT_DATA_TYPE_WEBM: |
| 366 eme_init_data_type = media::EmeInitDataType::WEBM; | 367 eme_init_data_type = media::EmeInitDataType::WEBM; |
| 367 break; | 368 break; |
| 368 #if defined(USE_PROPRIETARY_CODECS) | 369 #if defined(USE_PROPRIETARY_CODECS) |
| 369 case INIT_DATA_TYPE_CENC: | 370 case INIT_DATA_TYPE_CENC: |
| 370 eme_init_data_type = media::EmeInitDataType::CENC; | 371 eme_init_data_type = media::EmeInitDataType::CENC; |
| 371 break; | 372 break; |
| 372 #endif | 373 #endif |
| 373 default: | 374 default: |
| 374 NOTREACHED(); | 375 NOTREACHED(); |
| 375 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, | 376 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, |
| 376 "Invalid init data type."); | 377 "Invalid init data type."); |
| 377 return; | 378 return; |
| 378 } | 379 } |
| 379 | 380 |
| 380 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); | 381 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); |
| 381 if (!cdm) { | 382 if (!cdm) { |
| 382 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id; | 383 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id; |
| 383 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); | 384 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); |
| 384 return; | 385 return; |
| 385 } | 386 } |
| 386 | 387 |
| 387 CheckPermissionStatus( | 388 CheckPermissionStatus( |
| 388 render_frame_id, cdm_id, | 389 render_frame_id, cdm_id, |
| 389 base::Bind(&BrowserCdmManager::CreateSessionAndGenerateRequestIfPermitted, | 390 base::Bind(&BrowserCdmManager::CreateSessionAndGenerateRequestIfPermitted, |
| 390 this, render_frame_id, cdm_id, eme_init_data_type, init_data, | 391 this, render_frame_id, cdm_id, params.session_type, |
| 391 base::Passed(&promise))); | 392 eme_init_data_type, init_data, base::Passed(&promise))); |
| 393 } | |
| 394 | |
| 395 void BrowserCdmManager::OnLoadSession( | |
| 396 int render_frame_id, | |
| 397 int cdm_id, | |
| 398 uint32_t promise_id, | |
| 399 media::MediaKeys::SessionType session_type, | |
| 400 const std::string& session_id) { | |
| 401 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | |
| 402 | |
| 403 scoped_ptr<NewSessionPromise> promise( | |
| 404 new NewSessionPromise(this, render_frame_id, cdm_id, promise_id)); | |
| 405 | |
| 406 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); | |
| 407 if (!cdm) { | |
| 408 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id; | |
| 409 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); | |
| 410 return; | |
| 411 } | |
| 412 | |
| 413 CheckPermissionStatus( | |
| 414 render_frame_id, cdm_id, | |
| 415 base::Bind(&BrowserCdmManager::LoadSessionIfPermitted, | |
| 416 this, render_frame_id, cdm_id, session_type, | |
| 417 session_id, base::Passed(&promise))); | |
| 392 } | 418 } |
| 393 | 419 |
| 394 void BrowserCdmManager::OnUpdateSession(int render_frame_id, | 420 void BrowserCdmManager::OnUpdateSession(int render_frame_id, |
| 395 int cdm_id, | 421 int cdm_id, |
| 396 uint32_t promise_id, | 422 uint32_t promise_id, |
| 397 const std::string& session_id, | 423 const std::string& session_id, |
| 398 const std::vector<uint8>& response) { | 424 const std::vector<uint8>& response) { |
| 399 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 425 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 400 | 426 |
| 401 scoped_ptr<SimplePromise> promise( | 427 scoped_ptr<SimplePromise> promise( |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 433 | 459 |
| 434 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); | 460 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); |
| 435 if (!cdm) { | 461 if (!cdm) { |
| 436 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); | 462 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); |
| 437 return; | 463 return; |
| 438 } | 464 } |
| 439 | 465 |
| 440 cdm->CloseSession(session_id, promise.Pass()); | 466 cdm->CloseSession(session_id, promise.Pass()); |
| 441 } | 467 } |
| 442 | 468 |
| 469 void BrowserCdmManager::OnRemoveSession(int render_frame_id, | |
| 470 int cdm_id, | |
| 471 uint32_t promise_id, | |
| 472 const std::string& session_id) { | |
| 473 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | |
| 474 | |
| 475 scoped_ptr<SimplePromise> promise( | |
| 476 new SimplePromise(this, render_frame_id, cdm_id, promise_id)); | |
| 477 | |
| 478 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); | |
| 479 if (!cdm) { | |
| 480 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); | |
| 481 return; | |
| 482 } | |
| 483 | |
| 484 cdm->RemoveSession(session_id, promise.Pass()); | |
| 485 } | |
| 486 | |
| 443 void BrowserCdmManager::OnDestroyCdm(int render_frame_id, int cdm_id) { | 487 void BrowserCdmManager::OnDestroyCdm(int render_frame_id, int cdm_id) { |
| 444 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 488 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 445 RemoveCdm(GetId(render_frame_id, cdm_id)); | 489 RemoveCdm(GetId(render_frame_id, cdm_id)); |
| 446 } | 490 } |
| 447 | 491 |
| 448 // Use a weak pointer here instead of |this| to avoid circular references. | 492 // Use a weak pointer here instead of |this| to avoid circular references. |
| 449 #define BROWSER_CDM_MANAGER_CB(func) \ | 493 #define BROWSER_CDM_MANAGER_CB(func) \ |
| 450 base::Bind(&BrowserCdmManager::func, weak_ptr_factory_.GetWeakPtr(), \ | 494 base::Bind(&BrowserCdmManager::func, weak_ptr_factory_.GetWeakPtr(), \ |
| 451 render_frame_id, cdm_id) | 495 render_frame_id, cdm_id) |
| 452 | 496 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 555 task_runner_->PostTask(FROM_HERE, | 599 task_runner_->PostTask(FROM_HERE, |
| 556 base::Bind(permission_status_cb, allowed)); | 600 base::Bind(permission_status_cb, allowed)); |
| 557 } else { | 601 } else { |
| 558 permission_status_cb.Run(allowed); | 602 permission_status_cb.Run(allowed); |
| 559 } | 603 } |
| 560 } | 604 } |
| 561 | 605 |
| 562 void BrowserCdmManager::CreateSessionAndGenerateRequestIfPermitted( | 606 void BrowserCdmManager::CreateSessionAndGenerateRequestIfPermitted( |
| 563 int render_frame_id, | 607 int render_frame_id, |
| 564 int cdm_id, | 608 int cdm_id, |
| 609 media::MediaKeys::SessionType session_type, | |
| 565 media::EmeInitDataType init_data_type, | 610 media::EmeInitDataType init_data_type, |
| 566 const std::vector<uint8>& init_data, | 611 const std::vector<uint8>& init_data, |
| 567 scoped_ptr<media::NewSessionCdmPromise> promise, | 612 scoped_ptr<media::NewSessionCdmPromise> promise, |
| 568 bool permission_was_allowed) { | 613 bool permission_was_allowed) { |
| 569 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 614 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 570 | 615 |
| 571 if (!permission_was_allowed) { | 616 if (!permission_was_allowed) { |
| 572 promise->reject(MediaKeys::NOT_SUPPORTED_ERROR, 0, "Permission denied."); | 617 promise->reject(MediaKeys::NOT_SUPPORTED_ERROR, 0, "Permission denied."); |
| 573 return; | 618 return; |
| 574 } | 619 } |
| 575 | 620 |
| 576 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); | 621 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); |
| 577 if (!cdm) { | 622 if (!cdm) { |
| 578 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); | 623 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); |
| 579 return; | 624 return; |
| 580 } | 625 } |
| 581 | 626 |
| 582 // Only the temporary session type is supported in browser CDM path. | 627 cdm->CreateSessionAndGenerateRequest(session_type, init_data_type, |
| 583 // TODO(xhwang): Add SessionType support if needed. | 628 init_data, promise.Pass()); |
| 584 cdm->CreateSessionAndGenerateRequest(media::MediaKeys::TEMPORARY_SESSION, | 629 } |
| 585 init_data_type, init_data, | 630 |
| 586 promise.Pass()); | 631 void BrowserCdmManager::LoadSessionIfPermitted( |
| 632 int render_frame_id, | |
| 633 int cdm_id, | |
| 634 media::MediaKeys::SessionType session_type, | |
| 635 const std::string& session_id, | |
| 636 scoped_ptr<media::NewSessionCdmPromise> promise, | |
| 637 bool permission_was_allowed) { | |
| 638 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | |
| 639 | |
|
ddorwin
2015/05/28 23:51:50
Should we DCHECK session_type != temporary?
Or, DC
gunsch
2015/05/28 23:59:12
Done.
| |
| 640 if (!permission_was_allowed) { | |
| 641 promise->reject(MediaKeys::NOT_SUPPORTED_ERROR, 0, "Permission denied."); | |
| 642 return; | |
| 643 } | |
| 644 | |
| 645 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); | |
| 646 if (!cdm) { | |
| 647 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); | |
| 648 return; | |
| 649 } | |
| 650 | |
| 651 cdm->LoadSession(session_type, session_id, promise.Pass()); | |
|
ddorwin
2015/05/28 23:51:50
Blink checks the session type, right?
MediaDrmBri
gunsch
2015/05/28 23:59:12
Sure, promises were already rejected but NOTREACHE
| |
| 587 } | 652 } |
| 588 | 653 |
| 589 } // namespace content | 654 } // namespace content |
| OLD | NEW |