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 "content/browser/media/android/browser_media_player_manager.h" | 5 #include "content/browser/media/android/browser_media_player_manager.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "content/browser/android/content_view_core_impl.h" | 8 #include "content/browser/android/content_view_core_impl.h" |
9 #include "content/browser/media/android/browser_demuxer_android.h" | 9 #include "content/browser/media/android/browser_demuxer_android.h" |
10 #include "content/browser/media/android/media_resource_getter_impl.h" | 10 #include "content/browser/media/android/media_resource_getter_impl.h" |
(...skipping 16 matching lines...) Expand all Loading... |
27 using media::MediaDrmBridge; | 27 using media::MediaDrmBridge; |
28 using media::MediaPlayerAndroid; | 28 using media::MediaPlayerAndroid; |
29 using media::MediaPlayerBridge; | 29 using media::MediaPlayerBridge; |
30 using media::MediaPlayerManager; | 30 using media::MediaPlayerManager; |
31 using media::MediaSourcePlayer; | 31 using media::MediaSourcePlayer; |
32 | 32 |
33 // Threshold on the number of media players per renderer before we start | 33 // Threshold on the number of media players per renderer before we start |
34 // attempting to release inactive media players. | 34 // attempting to release inactive media players. |
35 static const int kMediaPlayerThreshold = 1; | 35 static const int kMediaPlayerThreshold = 1; |
36 | 36 |
| 37 // Maximum sizes for various EME message parameters. These are checks to |
| 38 // prevent unnecessarily large messages from being passed around, and the sizes |
| 39 // are somewhat arbitrary as the EME specification doesn't specify any limits. |
| 40 static const size_t kEmeUuidSize = 16; |
| 41 static const size_t kEmeTypeMaximum = 50; // Type is a MIME type. |
| 42 static const size_t kEmeInitDataMaximum = 10240; // 10 KB |
| 43 static const size_t kEmeResponseMaximum = 10240; // 10 KB |
| 44 |
37 namespace content { | 45 namespace content { |
38 | 46 |
39 static BrowserMediaPlayerManager::Factory g_factory = NULL; | 47 static BrowserMediaPlayerManager::Factory g_factory = NULL; |
40 | 48 |
41 // static | 49 // static |
42 void BrowserMediaPlayerManager::RegisterFactory(Factory factory) { | 50 void BrowserMediaPlayerManager::RegisterFactory(Factory factory) { |
43 g_factory = factory; | 51 g_factory = factory; |
44 } | 52 } |
45 | 53 |
46 // static | 54 // static |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Start, OnStart) | 124 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Start, OnStart) |
117 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Seek, OnSeek) | 125 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Seek, OnSeek) |
118 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Pause, OnPause) | 126 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Pause, OnPause) |
119 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_SetVolume, OnSetVolume) | 127 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_SetVolume, OnSetVolume) |
120 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Release, OnReleaseResources) | 128 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Release, OnReleaseResources) |
121 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyMediaPlayer, OnDestroyPlayer) | 129 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyMediaPlayer, OnDestroyPlayer) |
122 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyAllMediaPlayers, | 130 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyAllMediaPlayers, |
123 DestroyAllMediaPlayers) | 131 DestroyAllMediaPlayers) |
124 IPC_MESSAGE_HANDLER(MediaKeysHostMsg_InitializeCDM, | 132 IPC_MESSAGE_HANDLER(MediaKeysHostMsg_InitializeCDM, |
125 OnInitializeCDM) | 133 OnInitializeCDM) |
126 IPC_MESSAGE_HANDLER(MediaKeysHostMsg_GenerateKeyRequest, | 134 IPC_MESSAGE_HANDLER(MediaKeysHostMsg_CreateSession, OnCreateSession) |
127 OnGenerateKeyRequest) | 135 IPC_MESSAGE_HANDLER(MediaKeysHostMsg_UpdateSession, OnUpdateSession) |
128 IPC_MESSAGE_HANDLER(MediaKeysHostMsg_AddKey, OnAddKey) | 136 IPC_MESSAGE_HANDLER(MediaKeysHostMsg_ReleaseSession, OnReleaseSession) |
129 IPC_MESSAGE_HANDLER(MediaKeysHostMsg_CancelKeyRequest, | |
130 OnCancelKeyRequest) | |
131 #if defined(GOOGLE_TV) | 137 #if defined(GOOGLE_TV) |
132 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_NotifyExternalSurface, | 138 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_NotifyExternalSurface, |
133 OnNotifyExternalSurface) | 139 OnNotifyExternalSurface) |
134 #endif | 140 #endif |
135 IPC_MESSAGE_UNHANDLED(handled = false) | 141 IPC_MESSAGE_UNHANDLED(handled = false) |
136 IPC_END_MESSAGE_MAP() | 142 IPC_END_MESSAGE_MAP() |
137 return handled; | 143 return handled; |
138 } | 144 } |
139 | 145 |
140 void BrowserMediaPlayerManager::FullscreenPlayerPlay() { | 146 void BrowserMediaPlayerManager::FullscreenPlayerPlay() { |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 pending_fullscreen_player_id_ = player_id; | 354 pending_fullscreen_player_id_ = player_id; |
349 return; | 355 return; |
350 } | 356 } |
351 | 357 |
352 // Send an IPC to the render process to request the video element to enter | 358 // Send an IPC to the render process to request the video element to enter |
353 // fullscreen. OnEnterFullscreen() will be called later on success. | 359 // fullscreen. OnEnterFullscreen() will be called later on success. |
354 // This guarantees the fullscreen video will be rendered correctly. | 360 // This guarantees the fullscreen video will be rendered correctly. |
355 // During the process, DisableFullscreenEncryptedMediaPlayback() may get | 361 // During the process, DisableFullscreenEncryptedMediaPlayback() may get |
356 // called before or after OnEnterFullscreen(). If it is called before | 362 // called before or after OnEnterFullscreen(). If it is called before |
357 // OnEnterFullscreen(), the player will not enter fullscreen. And it will | 363 // OnEnterFullscreen(), the player will not enter fullscreen. And it will |
358 // retry the process once the GenerateKeyRequest is allowed to proceed | 364 // retry the process once CreateSession() is allowed to proceed. |
359 // TODO(qinmin): make this flag default on android. | 365 // TODO(qinmin): make this flag default on android. |
360 if (CommandLine::ForCurrentProcess()->HasSwitch( | 366 if (CommandLine::ForCurrentProcess()->HasSwitch( |
361 switches::kDisableGestureRequirementForMediaFullscreen)) { | 367 switches::kDisableGestureRequirementForMediaFullscreen)) { |
362 Send(new MediaPlayerMsg_RequestFullscreen(routing_id(), player_id)); | 368 Send(new MediaPlayerMsg_RequestFullscreen(routing_id(), player_id)); |
363 } | 369 } |
364 } | 370 } |
365 | 371 |
366 // The following 5 functions are EME MediaKeySession events. | 372 // The following 5 functions are EME MediaKeySession events. |
367 | 373 |
368 void BrowserMediaPlayerManager::OnSessionCreated( | 374 void BrowserMediaPlayerManager::OnSessionCreated( |
369 int media_keys_id, | 375 int media_keys_id, |
370 uint32 session_id, | 376 uint32 session_id, |
371 const std::string& web_session_id) { | 377 const std::string& web_session_id) { |
372 Send(new MediaKeysMsg_SetSessionId( | 378 Send(new MediaKeysMsg_SessionCreated( |
373 routing_id(), media_keys_id, session_id, web_session_id)); | 379 routing_id(), media_keys_id, session_id, web_session_id)); |
374 } | 380 } |
375 | 381 |
376 void BrowserMediaPlayerManager::OnSessionMessage( | 382 void BrowserMediaPlayerManager::OnSessionMessage( |
377 int media_keys_id, | 383 int media_keys_id, |
378 uint32 session_id, | 384 uint32 session_id, |
379 const std::vector<uint8>& message, | 385 const std::vector<uint8>& message, |
380 const std::string& destination_url) { | 386 const std::string& destination_url) { |
381 Send(new MediaKeysMsg_KeyMessage( | 387 Send(new MediaKeysMsg_SessionMessage( |
382 routing_id(), media_keys_id, session_id, message, destination_url)); | 388 routing_id(), media_keys_id, session_id, message, destination_url)); |
383 } | 389 } |
384 | 390 |
385 void BrowserMediaPlayerManager::OnSessionReady(int media_keys_id, | 391 void BrowserMediaPlayerManager::OnSessionReady(int media_keys_id, |
386 uint32 session_id) { | 392 uint32 session_id) { |
387 Send(new MediaKeysMsg_KeyAdded(routing_id(), media_keys_id, session_id)); | 393 Send(new MediaKeysMsg_SessionReady(routing_id(), media_keys_id, session_id)); |
388 } | 394 } |
389 | 395 |
390 void BrowserMediaPlayerManager::OnSessionClosed(int media_keys_id, | 396 void BrowserMediaPlayerManager::OnSessionClosed(int media_keys_id, |
391 uint32 session_id) { | 397 uint32 session_id) { |
392 // TODO(jrummell): Update Android calls and IPC names. | 398 Send(new MediaKeysMsg_SessionClosed(routing_id(), media_keys_id, session_id)); |
393 } | 399 } |
394 | 400 |
395 void BrowserMediaPlayerManager::OnSessionError( | 401 void BrowserMediaPlayerManager::OnSessionError( |
396 int media_keys_id, | 402 int media_keys_id, |
397 uint32 session_id, | 403 uint32 session_id, |
398 media::MediaKeys::KeyError error_code, | 404 media::MediaKeys::KeyError error_code, |
399 int system_code) { | 405 int system_code) { |
400 Send(new MediaKeysMsg_KeyError( | 406 Send(new MediaKeysMsg_SessionError( |
401 routing_id(), media_keys_id, session_id, error_code, system_code)); | 407 routing_id(), media_keys_id, session_id, error_code, system_code)); |
402 } | 408 } |
403 | 409 |
404 #if defined(GOOGLE_TV) | 410 #if defined(GOOGLE_TV) |
405 void BrowserMediaPlayerManager::AttachExternalVideoSurface(int player_id, | 411 void BrowserMediaPlayerManager::AttachExternalVideoSurface(int player_id, |
406 jobject surface) { | 412 jobject surface) { |
407 MediaPlayerAndroid* player = GetPlayer(player_id); | 413 MediaPlayerAndroid* player = GetPlayer(player_id); |
408 if (player) { | 414 if (player) { |
409 player->SetVideoSurface( | 415 player->SetVideoSurface( |
410 gfx::ScopedJavaSurface::AcquireExternalSurface(surface)); | 416 gfx::ScopedJavaSurface::AcquireExternalSurface(surface)); |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
539 void BrowserMediaPlayerManager::OnDestroyPlayer(int player_id) { | 545 void BrowserMediaPlayerManager::OnDestroyPlayer(int player_id) { |
540 RemovePlayer(player_id); | 546 RemovePlayer(player_id); |
541 if (fullscreen_player_id_ == player_id) | 547 if (fullscreen_player_id_ == player_id) |
542 fullscreen_player_id_ = -1; | 548 fullscreen_player_id_ = -1; |
543 } | 549 } |
544 | 550 |
545 void BrowserMediaPlayerManager::OnInitializeCDM( | 551 void BrowserMediaPlayerManager::OnInitializeCDM( |
546 int media_keys_id, | 552 int media_keys_id, |
547 const std::vector<uint8>& uuid, | 553 const std::vector<uint8>& uuid, |
548 const GURL& frame_url) { | 554 const GURL& frame_url) { |
| 555 if (uuid.size() != kEmeUuidSize) { |
| 556 // This failure will be discovered and reported by OnCreateSession() |
| 557 // as GetDrmBridge() will return null. |
| 558 NOTREACHED() << "Invalid UUID for ID: " << media_keys_id; |
| 559 return; |
| 560 } |
| 561 |
549 AddDrmBridge(media_keys_id, uuid, frame_url); | 562 AddDrmBridge(media_keys_id, uuid, frame_url); |
550 // In EME v0.1b MediaKeys lives in the media element. So the |media_keys_id| | 563 // In EME v0.1b MediaKeys lives in the media element. So the |media_keys_id| |
551 // is the same as the |player_id|. | 564 // is the same as the |player_id|. |
552 OnSetMediaKeys(media_keys_id, media_keys_id); | 565 OnSetMediaKeys(media_keys_id, media_keys_id); |
553 } | 566 } |
554 | 567 |
555 void BrowserMediaPlayerManager::OnGenerateKeyRequest( | 568 void BrowserMediaPlayerManager::OnCreateSession( |
556 int media_keys_id, | 569 int media_keys_id, |
557 uint32 session_id, | 570 uint32 session_id, |
558 const std::string& type, | 571 const std::string& type, |
559 const std::vector<uint8>& init_data) { | 572 const std::vector<uint8>& init_data) { |
| 573 if (type.length() > kEmeTypeMaximum) { |
| 574 OnSessionError( |
| 575 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0); |
| 576 return; |
| 577 } |
| 578 if (init_data.size() > kEmeInitDataMaximum) { |
| 579 OnSessionError( |
| 580 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0); |
| 581 return; |
| 582 } |
| 583 |
560 if (CommandLine::ForCurrentProcess() | 584 if (CommandLine::ForCurrentProcess() |
561 ->HasSwitch(switches::kDisableInfobarForProtectedMediaIdentifier)) { | 585 ->HasSwitch(switches::kDisableInfobarForProtectedMediaIdentifier)) { |
562 GenerateKeyIfAllowed(media_keys_id, session_id, type, init_data, true); | 586 GenerateKeyIfAllowed(media_keys_id, session_id, type, init_data, true); |
563 return; | 587 return; |
564 } | 588 } |
565 | 589 |
566 MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id); | 590 MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id); |
567 if (!drm_bridge) { | 591 if (!drm_bridge) { |
568 DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found"; | 592 DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found"; |
569 OnSessionError( | 593 OnSessionError( |
570 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0); | 594 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0); |
571 return; | 595 return; |
572 } | 596 } |
573 | 597 |
574 if (media_keys_ids_approved_.find(media_keys_id) == | 598 if (media_keys_ids_approved_.find(media_keys_id) == |
575 media_keys_ids_approved_.end()) { | 599 media_keys_ids_approved_.end()) { |
576 media_keys_ids_pending_approval_.insert(media_keys_id); | 600 media_keys_ids_pending_approval_.insert(media_keys_id); |
577 } | 601 } |
578 web_contents()->GetDelegate()->RequestProtectedMediaIdentifierPermission( | 602 web_contents()->GetDelegate()->RequestProtectedMediaIdentifierPermission( |
579 web_contents(), | 603 web_contents(), |
580 drm_bridge->frame_url(), | 604 drm_bridge->frame_url(), |
581 base::Bind(&BrowserMediaPlayerManager::GenerateKeyIfAllowed, | 605 base::Bind(&BrowserMediaPlayerManager::GenerateKeyIfAllowed, |
582 weak_ptr_factory_.GetWeakPtr(), | 606 weak_ptr_factory_.GetWeakPtr(), |
583 media_keys_id, | 607 media_keys_id, |
584 session_id, | 608 session_id, |
585 type, | 609 type, |
586 init_data)); | 610 init_data)); |
587 } | 611 } |
588 | 612 |
589 void BrowserMediaPlayerManager::OnAddKey(int media_keys_id, | 613 void BrowserMediaPlayerManager::OnUpdateSession( |
590 uint32 session_id, | 614 int media_keys_id, |
591 const std::vector<uint8>& key, | 615 uint32 session_id, |
592 const std::vector<uint8>& init_data) { | 616 const std::vector<uint8>& response) { |
593 MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id); | 617 MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id); |
594 if (!drm_bridge) { | 618 if (!drm_bridge) { |
595 DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found"; | 619 DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found"; |
596 OnSessionError( | 620 OnSessionError( |
597 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0); | 621 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0); |
598 return; | 622 return; |
599 } | 623 } |
600 | 624 |
601 DCHECK(init_data.empty()); | 625 if (response.size() > kEmeResponseMaximum) { |
602 drm_bridge->UpdateSession(session_id, &key[0], key.size()); | 626 DLOG(WARNING) << "Response for ID: " << media_keys_id |
| 627 << " too long: " << response.size(); |
| 628 OnSessionError( |
| 629 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0); |
| 630 return; |
| 631 } |
| 632 |
| 633 drm_bridge->UpdateSession(session_id, &response[0], response.size()); |
603 // In EME v0.1b MediaKeys lives in the media element. So the |media_keys_id| | 634 // In EME v0.1b MediaKeys lives in the media element. So the |media_keys_id| |
604 // is the same as the |player_id|. | 635 // is the same as the |player_id|. |
605 // TODO(xhwang): Separate |media_keys_id| and |player_id|. | 636 // TODO(xhwang): Separate |media_keys_id| and |player_id|. |
606 MediaPlayerAndroid* player = GetPlayer(media_keys_id); | 637 MediaPlayerAndroid* player = GetPlayer(media_keys_id); |
607 if (player) | 638 if (player) |
608 player->OnKeyAdded(); | 639 player->OnKeyAdded(); |
609 } | 640 } |
610 | 641 |
611 void BrowserMediaPlayerManager::OnCancelKeyRequest(int media_keys_id, | 642 void BrowserMediaPlayerManager::OnReleaseSession(int media_keys_id, |
612 uint32 session_id) { | 643 uint32 session_id) { |
613 MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id); | 644 MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id); |
614 if (!drm_bridge) { | 645 if (!drm_bridge) { |
615 DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found"; | 646 DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found"; |
616 OnSessionError( | 647 OnSessionError( |
617 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0); | 648 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0); |
618 return; | 649 return; |
619 } | 650 } |
620 | 651 |
621 drm_bridge->ReleaseSession(session_id); | 652 drm_bridge->ReleaseSession(session_id); |
622 } | 653 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
674 // TODO(xhwang/ddorwin): Pass the security level from key system. | 705 // TODO(xhwang/ddorwin): Pass the security level from key system. |
675 std::string security_level = "L3"; | 706 std::string security_level = "L3"; |
676 if (CommandLine::ForCurrentProcess() | 707 if (CommandLine::ForCurrentProcess() |
677 ->HasSwitch(switches::kMediaDrmEnableNonCompositing)) { | 708 ->HasSwitch(switches::kMediaDrmEnableNonCompositing)) { |
678 security_level = "L1"; | 709 security_level = "L1"; |
679 } | 710 } |
680 | 711 |
681 scoped_ptr<MediaDrmBridge> drm_bridge(MediaDrmBridge::Create( | 712 scoped_ptr<MediaDrmBridge> drm_bridge(MediaDrmBridge::Create( |
682 media_keys_id, uuid, frame_url, security_level, this)); | 713 media_keys_id, uuid, frame_url, security_level, this)); |
683 if (!drm_bridge) { | 714 if (!drm_bridge) { |
684 // This failure will be discovered and reported by OnGenerateKeyRequest() | 715 // This failure will be discovered and reported by OnCreateSession() |
685 // as GetDrmBridge() will return null. | 716 // as GetDrmBridge() will return null. |
686 DVLOG(1) << "failed to create drm bridge."; | 717 DVLOG(1) << "failed to create drm bridge."; |
687 return; | 718 return; |
688 } | 719 } |
689 | 720 |
690 drm_bridges_.push_back(drm_bridge.release()); | 721 drm_bridges_.push_back(drm_bridge.release()); |
691 } | 722 } |
692 | 723 |
693 void BrowserMediaPlayerManager::RemoveDrmBridge(int media_keys_id) { | 724 void BrowserMediaPlayerManager::RemoveDrmBridge(int media_keys_id) { |
694 for (ScopedVector<MediaDrmBridge>::iterator it = drm_bridges_.begin(); | 725 for (ScopedVector<MediaDrmBridge>::iterator it = drm_bridges_.begin(); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
738 if (pending_fullscreen_player_id_ != media_keys_id) | 769 if (pending_fullscreen_player_id_ != media_keys_id) |
739 return; | 770 return; |
740 | 771 |
741 pending_fullscreen_player_id_ = -1; | 772 pending_fullscreen_player_id_ = -1; |
742 MediaPlayerAndroid* player = GetPlayer(media_keys_id); | 773 MediaPlayerAndroid* player = GetPlayer(media_keys_id); |
743 if (player->IsPlaying()) | 774 if (player->IsPlaying()) |
744 OnProtectedSurfaceRequested(media_keys_id); | 775 OnProtectedSurfaceRequested(media_keys_id); |
745 } | 776 } |
746 | 777 |
747 } // namespace content | 778 } // namespace content |
OLD | NEW |