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
3 // found in the LICENSE file.
5 #include "content/browser/media/android/browser_media_player_manager.h"
7 #include "base/command_line.h"
8 #include "content/browser/android/content_view_core_impl.h"
9 #include "content/browser/media/android/browser_demuxer_android.h"
10 #include "content/browser/media/android/media_resource_getter_impl.h"
11 #include "content/browser/renderer_host/render_view_host_impl.h"
12 #include "content/browser/web_contents/web_contents_view_android.h"
13 #include "content/common/media/media_player_messages_android.h"
14 #include "content/public/browser/android/content_view_core.h"
15 #include "content/public/browser/browser_context.h"
16 #include "content/public/browser/render_process_host.h"
17 #include "content/public/browser/render_view_host.h"
18 #include "content/public/browser/storage_partition.h"
19 #include "content/public/browser/web_contents.h"
20 #include "content/public/browser/web_contents_delegate.h"
21 #include "content/public/common/content_client.h"
22 #include "content/public/common/content_switches.h"
23 #include "media/base/android/media_drm_bridge.h"
24 #include "media/base/android/media_player_bridge.h"
25 #include "media/base/android/media_source_player.h"
26 #include "media/base/media_switches.h"
28 using media::MediaDrmBridge
;
29 using media::MediaPlayerAndroid
;
30 using media::MediaPlayerBridge
;
31 using media::MediaPlayerManager
;
32 using media::MediaSourcePlayer
;
34 // Threshold on the number of media players per renderer before we start
35 // attempting to release inactive media players.
36 static const int kMediaPlayerThreshold
= 1;
38 // Maximum sizes for various EME message parameters. These are checks to
39 // prevent unnecessarily large messages from being passed around, and the sizes
40 // are somewhat arbitrary as the EME specification doesn't specify any limits.
41 static const size_t kEmeUuidSize
= 16;
42 static const size_t kEmeTypeMaximum
= 50; // Type is a MIME type.
43 static const size_t kEmeInitDataMaximum
= 10240; // 10 KB
44 static const size_t kEmeResponseMaximum
= 10240; // 10 KB
48 static BrowserMediaPlayerManager::Factory g_factory
= NULL
;
51 void BrowserMediaPlayerManager::RegisterFactory(Factory factory
) {
56 BrowserMediaPlayerManager
* BrowserMediaPlayerManager::Create(
57 RenderViewHost
* rvh
) {
59 return g_factory(rvh
);
60 return new BrowserMediaPlayerManager(rvh
);
63 ContentViewCoreImpl
* BrowserMediaPlayerManager::GetContentViewCore() const {
64 return ContentViewCoreImpl::FromWebContents(web_contents());
67 #if !defined(GOOGLE_TV)
69 MediaPlayerAndroid
* BrowserMediaPlayerManager::CreateMediaPlayer(
70 MediaPlayerHostMsg_Initialize_Type type
,
73 const GURL
& first_party_for_cookies
,
74 int demuxer_client_id
,
76 MediaPlayerManager
* manager
,
77 BrowserDemuxerAndroid
* demuxer
) {
79 case MEDIA_PLAYER_TYPE_URL
: {
80 const std::string user_agent
= GetUserAgent(url
);
81 MediaPlayerBridge
* media_player_bridge
= new MediaPlayerBridge(
84 first_party_for_cookies
,
88 BrowserMediaPlayerManager
* browser_media_player_manager
=
89 static_cast<BrowserMediaPlayerManager
*>(manager
);
90 ContentViewCoreImpl
* content_view_core_impl
=
91 static_cast<ContentViewCoreImpl
*>(ContentViewCore::FromWebContents(
92 browser_media_player_manager
->web_contents_
));
93 if (!content_view_core_impl
) {
94 // May reach here due to prerendering. Don't extract the metadata
95 // since it is expensive.
96 // TODO(qinmin): extract the metadata once the user decided to load
98 browser_media_player_manager
->OnMediaMetadataChanged(
99 player_id
, base::TimeDelta(), 0, 0, false);
100 } else if (!content_view_core_impl
->ShouldBlockMediaRequest(url
)) {
101 media_player_bridge
->Initialize();
103 return media_player_bridge
;
106 case MEDIA_PLAYER_TYPE_MEDIA_SOURCE
: {
107 return new MediaSourcePlayer(
108 player_id
, manager
, demuxer
->CreateDemuxer(demuxer_client_id
));
117 BrowserMediaPlayerManager::BrowserMediaPlayerManager(
118 RenderViewHost
* render_view_host
)
119 : WebContentsObserver(WebContents::FromRenderViewHost(render_view_host
)),
120 fullscreen_player_id_(-1),
121 pending_fullscreen_player_id_(-1),
122 web_contents_(WebContents::FromRenderViewHost(render_view_host
)),
123 weak_ptr_factory_(this) {
126 BrowserMediaPlayerManager::~BrowserMediaPlayerManager() {}
128 bool BrowserMediaPlayerManager::OnMessageReceived(const IPC::Message
& msg
) {
130 IPC_BEGIN_MESSAGE_MAP(BrowserMediaPlayerManager
, msg
)
131 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_EnterFullscreen
, OnEnterFullscreen
)
132 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_ExitFullscreen
, OnExitFullscreen
)
133 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Initialize
, OnInitialize
)
134 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Start
, OnStart
)
135 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Seek
, OnSeek
)
136 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Pause
, OnPause
)
137 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_SetVolume
, OnSetVolume
)
138 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Release
, OnReleaseResources
)
139 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyMediaPlayer
, OnDestroyPlayer
)
140 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyAllMediaPlayers
,
141 DestroyAllMediaPlayers
)
142 IPC_MESSAGE_HANDLER(MediaKeysHostMsg_InitializeCDM
,
144 IPC_MESSAGE_HANDLER(MediaKeysHostMsg_CreateSession
, OnCreateSession
)
145 IPC_MESSAGE_HANDLER(MediaKeysHostMsg_UpdateSession
, OnUpdateSession
)
146 IPC_MESSAGE_HANDLER(MediaKeysHostMsg_ReleaseSession
, OnReleaseSession
)
147 IPC_MESSAGE_HANDLER(MediaKeysHostMsg_CancelAllPendingSessionCreations
,
148 OnCancelAllPendingSessionCreations
)
149 #if defined(VIDEO_HOLE)
150 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_NotifyExternalSurface
,
151 OnNotifyExternalSurface
)
152 #endif // defined(VIDEO_HOLE)
153 IPC_MESSAGE_UNHANDLED(handled
= false)
154 IPC_END_MESSAGE_MAP()
158 void BrowserMediaPlayerManager::FullscreenPlayerPlay() {
159 MediaPlayerAndroid
* player
= GetFullscreenPlayer();
162 Send(new MediaPlayerMsg_DidMediaPlayerPlay(
163 routing_id(), fullscreen_player_id_
));
167 void BrowserMediaPlayerManager::FullscreenPlayerPause() {
168 MediaPlayerAndroid
* player
= GetFullscreenPlayer();
171 Send(new MediaPlayerMsg_DidMediaPlayerPause(
172 routing_id(), fullscreen_player_id_
));
176 void BrowserMediaPlayerManager::FullscreenPlayerSeek(int msec
) {
177 MediaPlayerAndroid
* player
= GetFullscreenPlayer();
179 // TODO(kbalazs): if |fullscreen_player_is_released_| is true
180 // at this point, player->GetCurrentTime() will be wrong until
181 // FullscreenPlayerPlay (http://crbug.com/322798).
182 OnSeekRequest(fullscreen_player_id_
,
183 base::TimeDelta::FromMilliseconds(msec
));
187 void BrowserMediaPlayerManager::ExitFullscreen(bool release_media_player
) {
188 if (WebContentsDelegate
* delegate
= web_contents_
->GetDelegate())
189 delegate
->ToggleFullscreenModeForTab(web_contents_
, false);
190 if (RenderWidgetHostViewAndroid
* view_android
=
191 static_cast<RenderWidgetHostViewAndroid
*>(
192 web_contents_
->GetRenderWidgetHostView())) {
193 view_android
->SetOverlayVideoMode(false);
196 Send(new MediaPlayerMsg_DidExitFullscreen(
197 routing_id(), fullscreen_player_id_
));
199 MediaPlayerAndroid
* player
= GetFullscreenPlayer();
200 fullscreen_player_id_
= -1;
203 if (release_media_player
)
206 player
->SetVideoSurface(gfx::ScopedJavaSurface());
209 void BrowserMediaPlayerManager::SuspendFullscreen() {
210 MediaPlayerAndroid
* player
= GetFullscreenPlayer();
212 player
->SetVideoSurface(gfx::ScopedJavaSurface());
215 void BrowserMediaPlayerManager::ResumeFullscreen(
216 gfx::ScopedJavaSurface surface
) {
217 MediaPlayerAndroid
* player
= GetFullscreenPlayer();
219 player
->SetVideoSurface(surface
.Pass());
222 void BrowserMediaPlayerManager::OnTimeUpdate(int player_id
,
223 base::TimeDelta current_time
) {
224 Send(new MediaPlayerMsg_MediaTimeUpdate(
225 routing_id(), player_id
, current_time
));
228 void BrowserMediaPlayerManager::SetVideoSurface(
229 gfx::ScopedJavaSurface surface
) {
230 MediaPlayerAndroid
* player
= GetFullscreenPlayer();
233 if (!surface
.IsEmpty()) {
234 Send(new MediaPlayerMsg_DidEnterFullscreen(routing_id(),
235 player
->player_id()));
237 player
->SetVideoSurface(surface
.Pass());
239 if (RenderWidgetHostViewAndroid
* view_android
=
240 static_cast<RenderWidgetHostViewAndroid
*>(
241 web_contents_
->GetRenderWidgetHostView())) {
242 view_android
->SetOverlayVideoMode(true);
244 if (WebContentsDelegate
* delegate
= web_contents_
->GetDelegate())
245 delegate
->ToggleFullscreenModeForTab(web_contents_
, true);
248 void BrowserMediaPlayerManager::OnMediaMetadataChanged(
249 int player_id
, base::TimeDelta duration
, int width
, int height
,
251 Send(new MediaPlayerMsg_MediaMetadataChanged(
252 routing_id(), player_id
, duration
, width
, height
, success
));
253 if (fullscreen_player_id_
== player_id
)
254 video_view_
->UpdateMediaMetadata();
257 void BrowserMediaPlayerManager::OnPlaybackComplete(int player_id
) {
258 Send(new MediaPlayerMsg_MediaPlaybackCompleted(routing_id(), player_id
));
259 if (fullscreen_player_id_
== player_id
)
260 video_view_
->OnPlaybackComplete();
263 void BrowserMediaPlayerManager::OnMediaInterrupted(int player_id
) {
264 // Tell WebKit that the audio should be paused, then release all resources
265 Send(new MediaPlayerMsg_DidMediaPlayerPause(routing_id(), player_id
));
266 OnReleaseResources(player_id
);
269 void BrowserMediaPlayerManager::OnBufferingUpdate(
270 int player_id
, int percentage
) {
271 Send(new MediaPlayerMsg_MediaBufferingUpdate(
272 routing_id(), player_id
, percentage
));
273 if (fullscreen_player_id_
== player_id
)
274 video_view_
->OnBufferingUpdate(percentage
);
277 void BrowserMediaPlayerManager::OnSeekRequest(
279 const base::TimeDelta
& time_to_seek
) {
280 Send(new MediaPlayerMsg_SeekRequest(routing_id(), player_id
, time_to_seek
));
283 void BrowserMediaPlayerManager::OnSeekComplete(
285 const base::TimeDelta
& current_time
) {
286 Send(new MediaPlayerMsg_SeekCompleted(routing_id(), player_id
, current_time
));
289 void BrowserMediaPlayerManager::OnError(int player_id
, int error
) {
290 Send(new MediaPlayerMsg_MediaError(routing_id(), player_id
, error
));
291 if (fullscreen_player_id_
== player_id
)
292 video_view_
->OnMediaPlayerError(error
);
295 void BrowserMediaPlayerManager::OnVideoSizeChanged(
296 int player_id
, int width
, int height
) {
297 Send(new MediaPlayerMsg_MediaVideoSizeChanged(routing_id(), player_id
,
299 if (fullscreen_player_id_
== player_id
)
300 video_view_
->OnVideoSizeChanged(width
, height
);
303 void BrowserMediaPlayerManager::RequestMediaResources(int player_id
) {
304 int num_active_player
= 0;
305 ScopedVector
<MediaPlayerAndroid
>::iterator it
;
306 for (it
= players_
.begin(); it
!= players_
.end(); ++it
) {
307 if (!(*it
)->IsPlayerReady())
310 // The player is already active, ignore it.
311 if ((*it
)->player_id() == player_id
)
317 // Number of active players are less than the threshold, do nothing.
318 if (num_active_player
< kMediaPlayerThreshold
)
321 for (it
= players_
.begin(); it
!= players_
.end(); ++it
) {
322 if ((*it
)->IsPlayerReady() && !(*it
)->IsPlaying() &&
323 fullscreen_player_id_
!= (*it
)->player_id()) {
325 Send(new MediaPlayerMsg_MediaPlayerReleased(
326 routing_id(), (*it
)->player_id()));
331 void BrowserMediaPlayerManager::ReleaseMediaResources(int player_id
) {
332 // Nothing needs to be done.
335 media::MediaResourceGetter
*
336 BrowserMediaPlayerManager::GetMediaResourceGetter() {
337 if (!media_resource_getter_
.get()) {
338 RenderProcessHost
* host
= web_contents()->GetRenderProcessHost();
339 BrowserContext
* context
= host
->GetBrowserContext();
340 StoragePartition
* partition
= host
->GetStoragePartition();
341 fileapi::FileSystemContext
* file_system_context
=
342 partition
? partition
->GetFileSystemContext() : NULL
;
343 media_resource_getter_
.reset(new MediaResourceGetterImpl(
344 context
, file_system_context
, host
->GetID(), routing_id()));
346 return media_resource_getter_
.get();
349 MediaPlayerAndroid
* BrowserMediaPlayerManager::GetFullscreenPlayer() {
350 return GetPlayer(fullscreen_player_id_
);
353 MediaPlayerAndroid
* BrowserMediaPlayerManager::GetPlayer(int player_id
) {
354 for (ScopedVector
<MediaPlayerAndroid
>::iterator it
= players_
.begin();
355 it
!= players_
.end(); ++it
) {
356 if ((*it
)->player_id() == player_id
)
362 MediaDrmBridge
* BrowserMediaPlayerManager::GetDrmBridge(int media_keys_id
) {
363 for (ScopedVector
<MediaDrmBridge
>::iterator it
= drm_bridges_
.begin();
364 it
!= drm_bridges_
.end(); ++it
) {
365 if ((*it
)->media_keys_id() == media_keys_id
)
371 void BrowserMediaPlayerManager::DestroyAllMediaPlayers() {
373 drm_bridges_
.clear();
374 if (fullscreen_player_id_
!= -1) {
376 fullscreen_player_id_
= -1;
380 void BrowserMediaPlayerManager::OnProtectedSurfaceRequested(int player_id
) {
381 if (fullscreen_player_id_
== player_id
)
384 if (fullscreen_player_id_
!= -1) {
385 // TODO(qinmin): Determine the correct error code we should report to WMPA.
386 OnError(player_id
, MediaPlayerAndroid::MEDIA_ERROR_DECODE
);
390 // If the player is pending approval, wait for the approval to happen.
391 if (media_keys_ids_pending_approval_
.end() !=
392 media_keys_ids_pending_approval_
.find(player_id
)) {
393 pending_fullscreen_player_id_
= player_id
;
397 // Send an IPC to the render process to request the video element to enter
398 // fullscreen. OnEnterFullscreen() will be called later on success.
399 // This guarantees the fullscreen video will be rendered correctly.
400 // During the process, DisableFullscreenEncryptedMediaPlayback() may get
401 // called before or after OnEnterFullscreen(). If it is called before
402 // OnEnterFullscreen(), the player will not enter fullscreen. And it will
403 // retry the process once CreateSession() is allowed to proceed.
404 // TODO(qinmin): make this flag default on android.
405 if (CommandLine::ForCurrentProcess()->HasSwitch(
406 switches::kDisableGestureRequirementForMediaFullscreen
)) {
407 Send(new MediaPlayerMsg_RequestFullscreen(routing_id(), player_id
));
411 // The following 5 functions are EME MediaKeySession events.
413 void BrowserMediaPlayerManager::OnSessionCreated(
416 const std::string
& web_session_id
) {
417 Send(new MediaKeysMsg_SessionCreated(
418 routing_id(), media_keys_id
, session_id
, web_session_id
));
421 void BrowserMediaPlayerManager::OnSessionMessage(
424 const std::vector
<uint8
>& message
,
425 const std::string
& destination_url
) {
426 Send(new MediaKeysMsg_SessionMessage(
427 routing_id(), media_keys_id
, session_id
, message
, destination_url
));
430 void BrowserMediaPlayerManager::OnSessionReady(int media_keys_id
,
432 Send(new MediaKeysMsg_SessionReady(routing_id(), media_keys_id
, session_id
));
435 void BrowserMediaPlayerManager::OnSessionClosed(int media_keys_id
,
437 Send(new MediaKeysMsg_SessionClosed(routing_id(), media_keys_id
, session_id
));
440 void BrowserMediaPlayerManager::OnSessionError(
443 media::MediaKeys::KeyError error_code
,
445 Send(new MediaKeysMsg_SessionError(
446 routing_id(), media_keys_id
, session_id
, error_code
, system_code
));
449 #if defined(VIDEO_HOLE)
450 void BrowserMediaPlayerManager::AttachExternalVideoSurface(int player_id
,
452 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
454 player
->SetVideoSurface(
455 gfx::ScopedJavaSurface::AcquireExternalSurface(surface
));
459 void BrowserMediaPlayerManager::DetachExternalVideoSurface(int player_id
) {
460 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
462 player
->SetVideoSurface(gfx::ScopedJavaSurface());
465 void BrowserMediaPlayerManager::OnNotifyExternalSurface(
466 int player_id
, bool is_request
, const gfx::RectF
& rect
) {
470 WebContentsViewAndroid
* view
=
471 static_cast<WebContentsViewAndroid
*>(web_contents_
->GetView());
473 view
->NotifyExternalSurface(player_id
, is_request
, rect
);
475 #endif // defined(VIDEO_HOLE)
477 void BrowserMediaPlayerManager::DisableFullscreenEncryptedMediaPlayback() {
478 if (fullscreen_player_id_
== -1)
481 // If the fullscreen player is not playing back encrypted video, do nothing.
482 MediaDrmBridge
* drm_bridge
= GetDrmBridge(fullscreen_player_id_
);
487 pending_fullscreen_player_id_
= fullscreen_player_id_
;
488 OnExitFullscreen(fullscreen_player_id_
);
491 void BrowserMediaPlayerManager::OnEnterFullscreen(int player_id
) {
492 DCHECK_EQ(fullscreen_player_id_
, -1);
493 if (media_keys_ids_pending_approval_
.find(player_id
) !=
494 media_keys_ids_pending_approval_
.end()) {
498 if (video_view_
.get()) {
499 fullscreen_player_id_
= player_id
;
500 video_view_
->OpenVideo();
501 } else if (!ContentVideoView::GetInstance()) {
502 // In Android WebView, two ContentViewCores could both try to enter
503 // fullscreen video, we just ignore the second one.
504 fullscreen_player_id_
= player_id
;
505 video_view_
.reset(new ContentVideoView(this));
509 void BrowserMediaPlayerManager::OnExitFullscreen(int player_id
) {
510 if (fullscreen_player_id_
== player_id
) {
511 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
513 player
->SetVideoSurface(gfx::ScopedJavaSurface());
514 video_view_
->OnExitFullscreen();
518 void BrowserMediaPlayerManager::OnInitialize(
519 MediaPlayerHostMsg_Initialize_Type type
,
522 const GURL
& first_party_for_cookies
,
523 int demuxer_client_id
) {
524 DCHECK(type
!= MEDIA_PLAYER_TYPE_MEDIA_SOURCE
|| demuxer_client_id
> 0)
525 << "Media source players must have positive demuxer client IDs: "
526 << demuxer_client_id
;
528 RemovePlayer(player_id
);
530 RenderProcessHostImpl
* host
= static_cast<RenderProcessHostImpl
*>(
531 web_contents()->GetRenderProcessHost());
532 AddPlayer(CreateMediaPlayer(
533 type
, player_id
, url
, first_party_for_cookies
, demuxer_client_id
,
534 host
->GetBrowserContext()->IsOffTheRecord(), this,
535 host
->browser_demuxer_android()));
538 void BrowserMediaPlayerManager::OnStart(int player_id
) {
539 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
544 void BrowserMediaPlayerManager::OnSeek(
546 const base::TimeDelta
& time
) {
547 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
549 player
->SeekTo(time
);
552 void BrowserMediaPlayerManager::OnPause(
554 bool is_media_related_action
) {
555 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
557 player
->Pause(is_media_related_action
);
560 void BrowserMediaPlayerManager::OnSetVolume(int player_id
, double volume
) {
561 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
563 player
->SetVolume(volume
);
566 void BrowserMediaPlayerManager::OnReleaseResources(int player_id
) {
567 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
571 #if defined(VIDEO_HOLE)
572 WebContentsViewAndroid
* view
=
573 static_cast<WebContentsViewAndroid
*>(web_contents_
->GetView());
575 view
->NotifyExternalSurface(player_id
, false, gfx::RectF());
576 #endif // defined(VIDEO_HOLE)
579 void BrowserMediaPlayerManager::OnDestroyPlayer(int player_id
) {
580 RemovePlayer(player_id
);
581 if (fullscreen_player_id_
== player_id
)
582 fullscreen_player_id_
= -1;
585 void BrowserMediaPlayerManager::OnInitializeCDM(
587 const std::vector
<uint8
>& uuid
,
588 const GURL
& frame_url
) {
589 if (uuid
.size() != kEmeUuidSize
) {
590 // This failure will be discovered and reported by OnCreateSession()
591 // as GetDrmBridge() will return null.
592 NOTREACHED() << "Invalid UUID for ID: " << media_keys_id
;
596 AddDrmBridge(media_keys_id
, uuid
, frame_url
);
597 // In EME v0.1b MediaKeys lives in the media element. So the |media_keys_id|
598 // is the same as the |player_id|.
599 OnSetMediaKeys(media_keys_id
, media_keys_id
);
602 void BrowserMediaPlayerManager::OnCreateSession(
605 const std::string
& type
,
606 const std::vector
<uint8
>& init_data
) {
607 if (type
.length() > kEmeTypeMaximum
) {
609 media_keys_id
, session_id
, media::MediaKeys::kUnknownError
, 0);
612 if (init_data
.size() > kEmeInitDataMaximum
) {
614 media_keys_id
, session_id
, media::MediaKeys::kUnknownError
, 0);
618 if (CommandLine::ForCurrentProcess()
619 ->HasSwitch(switches::kDisableInfobarForProtectedMediaIdentifier
)) {
620 CreateSessionIfPermitted(media_keys_id
, session_id
, type
, init_data
, true);
624 MediaDrmBridge
* drm_bridge
= GetDrmBridge(media_keys_id
);
626 DLOG(WARNING
) << "No MediaDrmBridge for ID: " << media_keys_id
<< " found";
628 media_keys_id
, session_id
, media::MediaKeys::kUnknownError
, 0);
632 if (media_keys_ids_approved_
.find(media_keys_id
) ==
633 media_keys_ids_approved_
.end()) {
634 media_keys_ids_pending_approval_
.insert(media_keys_id
);
637 BrowserContext
* context
=
638 web_contents()->GetRenderProcessHost()->GetBrowserContext();
640 context
->RequestProtectedMediaIdentifierPermission(
641 web_contents()->GetRenderProcessHost()->GetID(),
642 web_contents()->GetRenderViewHost()->GetRoutingID(),
643 static_cast<int>(session_id
),
645 drm_bridge
->frame_url(),
646 base::Bind(&BrowserMediaPlayerManager::CreateSessionIfPermitted
,
647 weak_ptr_factory_
.GetWeakPtr(),
654 void BrowserMediaPlayerManager::OnUpdateSession(
657 const std::vector
<uint8
>& response
) {
658 MediaDrmBridge
* drm_bridge
= GetDrmBridge(media_keys_id
);
660 DLOG(WARNING
) << "No MediaDrmBridge for ID: " << media_keys_id
<< " found";
662 media_keys_id
, session_id
, media::MediaKeys::kUnknownError
, 0);
666 if (response
.size() > kEmeResponseMaximum
) {
667 DLOG(WARNING
) << "Response for ID: " << media_keys_id
668 << " too long: " << response
.size();
670 media_keys_id
, session_id
, media::MediaKeys::kUnknownError
, 0);
674 drm_bridge
->UpdateSession(session_id
, &response
[0], response
.size());
675 // In EME v0.1b MediaKeys lives in the media element. So the |media_keys_id|
676 // is the same as the |player_id|.
677 // TODO(xhwang): Separate |media_keys_id| and |player_id|.
678 MediaPlayerAndroid
* player
= GetPlayer(media_keys_id
);
680 player
->OnKeyAdded();
683 void BrowserMediaPlayerManager::OnReleaseSession(int media_keys_id
,
685 MediaDrmBridge
* drm_bridge
= GetDrmBridge(media_keys_id
);
687 DLOG(WARNING
) << "No MediaDrmBridge for ID: " << media_keys_id
<< " found";
689 media_keys_id
, session_id
, media::MediaKeys::kUnknownError
, 0);
693 drm_bridge
->ReleaseSession(session_id
);
696 void BrowserMediaPlayerManager::OnCancelAllPendingSessionCreations(
698 MediaDrmBridge
* drm_bridge
= GetDrmBridge(media_keys_id
);
699 if (!drm_bridge
) return;
701 BrowserContext
* context
=
702 web_contents()->GetRenderProcessHost()->GetBrowserContext();
703 context
->CancelProtectedMediaIdentifierPermissionRequests(media_keys_id
);
706 void BrowserMediaPlayerManager::AddPlayer(MediaPlayerAndroid
* player
) {
707 DCHECK(!GetPlayer(player
->player_id()));
708 players_
.push_back(player
);
709 if (player
->IsRemote()) {
710 Send(new MediaPlayerMsg_ConnectedToRemoteDevice(routing_id(),
711 player
->player_id()));
715 void BrowserMediaPlayerManager::RemovePlayer(int player_id
) {
716 for (ScopedVector
<MediaPlayerAndroid
>::iterator it
= players_
.begin();
717 it
!= players_
.end(); ++it
) {
718 MediaPlayerAndroid
* player
= *it
;
719 if (player
->player_id() == player_id
) {
720 if (player
->IsRemote()) {
721 Send(new MediaPlayerMsg_DisconnectedFromRemoteDevice(
722 routing_id(), player
->player_id()));
730 scoped_ptr
<media::MediaPlayerAndroid
> BrowserMediaPlayerManager::SwapPlayer(
731 int player_id
, media::MediaPlayerAndroid
* player
) {
732 media::MediaPlayerAndroid
* previous_player
= NULL
;
733 for (ScopedVector
<MediaPlayerAndroid
>::iterator it
= players_
.begin();
734 it
!= players_
.end(); ++it
) {
735 if ((*it
)->player_id() == player_id
) {
736 previous_player
= *it
;
737 players_
.weak_erase(it
);
738 players_
.push_back(player
);
739 if (!previous_player
->IsRemote() && player
->IsRemote()) {
740 Send(new MediaPlayerMsg_ConnectedToRemoteDevice(
741 routing_id(), player
->player_id()));
742 } else if (previous_player
->IsRemote() && !player
->IsRemote()) {
743 Send(new MediaPlayerMsg_DisconnectedFromRemoteDevice(
744 routing_id(), player
->player_id()));
749 return scoped_ptr
<media::MediaPlayerAndroid
>(previous_player
);
752 void BrowserMediaPlayerManager::AddDrmBridge(int media_keys_id
,
753 const std::vector
<uint8
>& uuid
,
754 const GURL
& frame_url
) {
755 DCHECK(!GetDrmBridge(media_keys_id
));
757 scoped_ptr
<MediaDrmBridge
> drm_bridge(MediaDrmBridge::Create(
758 media_keys_id
, uuid
, frame_url
, this));
760 // This failure will be discovered and reported by OnCreateSession()
761 // as GetDrmBridge() will return null.
762 DVLOG(1) << "failed to create drm bridge.";
766 // TODO(xhwang/ddorwin): Pass the security level from key system.
767 MediaDrmBridge::SecurityLevel security_level
=
768 MediaDrmBridge::SECURITY_LEVEL_3
;
769 if (CommandLine::ForCurrentProcess()
770 ->HasSwitch(switches::kMediaDrmEnableNonCompositing
)) {
771 security_level
= MediaDrmBridge::SECURITY_LEVEL_1
;
773 if (!drm_bridge
->SetSecurityLevel(security_level
)) {
774 DVLOG(1) << "failed to set security level " << security_level
;
778 drm_bridges_
.push_back(drm_bridge
.release());
781 void BrowserMediaPlayerManager::RemoveDrmBridge(int media_keys_id
) {
782 for (ScopedVector
<MediaDrmBridge
>::iterator it
= drm_bridges_
.begin();
783 it
!= drm_bridges_
.end(); ++it
) {
784 if ((*it
)->media_keys_id() == media_keys_id
) {
785 drm_bridges_
.erase(it
);
791 void BrowserMediaPlayerManager::OnSetMediaKeys(int player_id
,
793 MediaPlayerAndroid
* player
= GetPlayer(player_id
);
794 MediaDrmBridge
* drm_bridge
= GetDrmBridge(media_keys_id
);
795 if (!player
|| !drm_bridge
) {
796 DVLOG(1) << "OnSetMediaKeys(): Player and MediaKeys must be present.";
799 // TODO(qinmin): add the logic to decide whether we should create the
800 // fullscreen surface for EME lv1.
801 player
->SetDrmBridge(drm_bridge
);
804 void BrowserMediaPlayerManager::CreateSessionIfPermitted(
807 const std::string
& type
,
808 const std::vector
<uint8
>& init_data
,
812 media_keys_id
, session_id
, media::MediaKeys::kUnknownError
, 0);
816 MediaDrmBridge
* drm_bridge
= GetDrmBridge(media_keys_id
);
818 DLOG(WARNING
) << "No MediaDrmBridge for ID: " << media_keys_id
<< " found";
820 media_keys_id
, session_id
, media::MediaKeys::kUnknownError
, 0);
823 media_keys_ids_pending_approval_
.erase(media_keys_id
);
824 media_keys_ids_approved_
.insert(media_keys_id
);
825 drm_bridge
->CreateSession(session_id
, type
, &init_data
[0], init_data
.size());
827 // TODO(qinmin): currently |media_keys_id| and player ID are identical.
828 // This might not be true in the future.
829 if (pending_fullscreen_player_id_
!= media_keys_id
)
832 pending_fullscreen_player_id_
= -1;
833 MediaPlayerAndroid
* player
= GetPlayer(media_keys_id
);
834 if (player
->IsPlaying())
835 OnProtectedSurfaceRequested(media_keys_id
);
838 } // namespace content