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_NE(media::MediaKeys::SessionType::TEMPORARY_SESSION, session_type); |
| 639 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 640 |
| 641 if (!permission_was_allowed) { |
| 642 promise->reject(MediaKeys::NOT_SUPPORTED_ERROR, 0, "Permission denied."); |
| 643 return; |
| 644 } |
| 645 |
| 646 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); |
| 647 if (!cdm) { |
| 648 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); |
| 649 return; |
| 650 } |
| 651 |
| 652 cdm->LoadSession(session_type, session_id, promise.Pass()); |
587 } | 653 } |
588 | 654 |
589 } // namespace content | 655 } // namespace content |
OLD | NEW |