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 kEmeInitDataMaximum = 64 * 1024; // 64 KB
43 static const size_t kEmeResponseMaximum = 64 * 1024; // 64 KB
47 static BrowserMediaPlayerManager::Factory g_factory = NULL;
50 void BrowserMediaPlayerManager::RegisterFactory(Factory factory) {
55 BrowserMediaPlayerManager* BrowserMediaPlayerManager::Create(
56 RenderViewHost* rvh) {
58 return g_factory(rvh);
59 return new BrowserMediaPlayerManager(rvh);
62 ContentViewCoreImpl* BrowserMediaPlayerManager::GetContentViewCore() const {
63 return ContentViewCoreImpl::FromWebContents(web_contents());
67 MediaPlayerAndroid* BrowserMediaPlayerManager::CreateMediaPlayer(
68 MediaPlayerHostMsg_Initialize_Type type,
71 const GURL& first_party_for_cookies,
72 int demuxer_client_id,
74 MediaPlayerManager* manager,
75 BrowserDemuxerAndroid* demuxer) {
77 case MEDIA_PLAYER_TYPE_URL: {
78 const std::string user_agent = GetUserAgent(url);
79 MediaPlayerBridge* media_player_bridge = new MediaPlayerBridge(
82 first_party_for_cookies,
86 BrowserMediaPlayerManager* browser_media_player_manager =
87 static_cast<BrowserMediaPlayerManager*>(manager);
88 ContentViewCoreImpl* content_view_core_impl =
89 static_cast<ContentViewCoreImpl*>(ContentViewCore::FromWebContents(
90 browser_media_player_manager->web_contents_));
91 if (!content_view_core_impl) {
92 // May reach here due to prerendering. Don't extract the metadata
93 // since it is expensive.
94 // TODO(qinmin): extract the metadata once the user decided to load
96 browser_media_player_manager->OnMediaMetadataChanged(
97 player_id, base::TimeDelta(), 0, 0, false);
98 } else if (!content_view_core_impl->ShouldBlockMediaRequest(url)) {
99 media_player_bridge->Initialize();
101 return media_player_bridge;
104 case MEDIA_PLAYER_TYPE_MEDIA_SOURCE: {
105 return new MediaSourcePlayer(
106 player_id, manager, demuxer->CreateDemuxer(demuxer_client_id));
114 BrowserMediaPlayerManager::BrowserMediaPlayerManager(
115 RenderViewHost* render_view_host)
116 : WebContentsObserver(WebContents::FromRenderViewHost(render_view_host)),
117 fullscreen_player_id_(-1),
118 pending_fullscreen_player_id_(-1),
119 fullscreen_player_is_released_(false),
120 web_contents_(WebContents::FromRenderViewHost(render_view_host)),
121 weak_ptr_factory_(this) {
124 BrowserMediaPlayerManager::~BrowserMediaPlayerManager() {}
126 bool BrowserMediaPlayerManager::OnMessageReceived(const IPC::Message& msg) {
128 IPC_BEGIN_MESSAGE_MAP(BrowserMediaPlayerManager, msg)
129 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_EnterFullscreen, OnEnterFullscreen)
130 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_ExitFullscreen, OnExitFullscreen)
131 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Initialize, OnInitialize)
132 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Start, OnStart)
133 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Seek, OnSeek)
134 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Pause, OnPause)
135 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_SetVolume, OnSetVolume)
136 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_SetPoster, OnSetPoster)
137 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Release, OnReleaseResources)
138 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyMediaPlayer, OnDestroyPlayer)
139 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyAllMediaPlayers,
140 DestroyAllMediaPlayers)
141 IPC_MESSAGE_HANDLER(MediaKeysHostMsg_InitializeCDM,
143 IPC_MESSAGE_HANDLER(MediaKeysHostMsg_CreateSession, OnCreateSession)
144 IPC_MESSAGE_HANDLER(MediaKeysHostMsg_UpdateSession, OnUpdateSession)
145 IPC_MESSAGE_HANDLER(MediaKeysHostMsg_ReleaseSession, OnReleaseSession)
146 IPC_MESSAGE_HANDLER(MediaKeysHostMsg_DestroyCdm, OnDestroyCdm)
147 #if defined(VIDEO_HOLE)
148 IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_NotifyExternalSurface,
149 OnNotifyExternalSurface)
150 #endif // defined(VIDEO_HOLE)
151 IPC_MESSAGE_UNHANDLED(handled = false)
152 IPC_END_MESSAGE_MAP()
156 void BrowserMediaPlayerManager::FullscreenPlayerPlay() {
157 MediaPlayerAndroid* player = GetFullscreenPlayer();
159 if (fullscreen_player_is_released_) {
160 video_view_->OpenVideo();
161 fullscreen_player_is_released_ = false;
164 Send(new MediaPlayerMsg_DidMediaPlayerPlay(
165 routing_id(), fullscreen_player_id_));
169 void BrowserMediaPlayerManager::FullscreenPlayerPause() {
170 MediaPlayerAndroid* player = GetFullscreenPlayer();
173 Send(new MediaPlayerMsg_DidMediaPlayerPause(
174 routing_id(), fullscreen_player_id_));
178 void BrowserMediaPlayerManager::FullscreenPlayerSeek(int msec) {
179 MediaPlayerAndroid* player = GetFullscreenPlayer();
181 // TODO(kbalazs): if |fullscreen_player_is_released_| is true
182 // at this point, player->GetCurrentTime() will be wrong until
183 // FullscreenPlayerPlay (http://crbug.com/322798).
184 OnSeekRequest(fullscreen_player_id_,
185 base::TimeDelta::FromMilliseconds(msec));
189 void BrowserMediaPlayerManager::ExitFullscreen(bool release_media_player) {
190 if (CommandLine::ForCurrentProcess()->HasSwitch(
191 switches::kEnableOverlayFullscreenVideoSubtitle)) {
192 if (WebContentsDelegate* delegate = web_contents_->GetDelegate())
193 delegate->ToggleFullscreenModeForTab(web_contents_, false);
194 if (RenderWidgetHostViewAndroid* view_android =
195 static_cast<RenderWidgetHostViewAndroid*>(
196 web_contents_->GetRenderWidgetHostView())) {
197 view_android->SetOverlayVideoMode(false);
201 Send(new MediaPlayerMsg_DidExitFullscreen(
202 routing_id(), fullscreen_player_id_));
204 MediaPlayerAndroid* player = GetFullscreenPlayer();
205 fullscreen_player_id_ = -1;
208 if (release_media_player)
209 ReleaseFullscreenPlayer(player);
211 player->SetVideoSurface(gfx::ScopedJavaSurface());
214 void BrowserMediaPlayerManager::OnTimeUpdate(int player_id,
215 base::TimeDelta current_time) {
216 Send(new MediaPlayerMsg_MediaTimeUpdate(
217 routing_id(), player_id, current_time));
220 void BrowserMediaPlayerManager::SetVideoSurface(
221 gfx::ScopedJavaSurface surface) {
222 MediaPlayerAndroid* player = GetFullscreenPlayer();
225 if (!surface.IsEmpty()) {
226 Send(new MediaPlayerMsg_DidEnterFullscreen(routing_id(),
227 player->player_id()));
229 player->SetVideoSurface(surface.Pass());
231 if (!CommandLine::ForCurrentProcess()->HasSwitch(
232 switches::kEnableOverlayFullscreenVideoSubtitle)) {
235 if (RenderWidgetHostViewAndroid* view_android =
236 static_cast<RenderWidgetHostViewAndroid*>(
237 web_contents_->GetRenderWidgetHostView())) {
238 view_android->SetOverlayVideoMode(true);
240 if (WebContentsDelegate* delegate = web_contents_->GetDelegate())
241 delegate->ToggleFullscreenModeForTab(web_contents_, true);
244 void BrowserMediaPlayerManager::OnMediaMetadataChanged(
245 int player_id, base::TimeDelta duration, int width, int height,
247 Send(new MediaPlayerMsg_MediaMetadataChanged(
248 routing_id(), player_id, duration, width, height, success));
249 if (fullscreen_player_id_ == player_id)
250 video_view_->UpdateMediaMetadata();
253 void BrowserMediaPlayerManager::OnPlaybackComplete(int player_id) {
254 Send(new MediaPlayerMsg_MediaPlaybackCompleted(routing_id(), player_id));
255 if (fullscreen_player_id_ == player_id)
256 video_view_->OnPlaybackComplete();
259 void BrowserMediaPlayerManager::OnMediaInterrupted(int player_id) {
260 // Tell WebKit that the audio should be paused, then release all resources
261 Send(new MediaPlayerMsg_MediaPlayerReleased(routing_id(), player_id));
262 OnReleaseResources(player_id);
265 void BrowserMediaPlayerManager::OnBufferingUpdate(
266 int player_id, int percentage) {
267 Send(new MediaPlayerMsg_MediaBufferingUpdate(
268 routing_id(), player_id, percentage));
269 if (fullscreen_player_id_ == player_id)
270 video_view_->OnBufferingUpdate(percentage);
273 void BrowserMediaPlayerManager::OnSeekRequest(
275 const base::TimeDelta& time_to_seek) {
276 Send(new MediaPlayerMsg_SeekRequest(routing_id(), player_id, time_to_seek));
279 void BrowserMediaPlayerManager::OnSeekComplete(
281 const base::TimeDelta& current_time) {
282 Send(new MediaPlayerMsg_SeekCompleted(routing_id(), player_id, current_time));
285 void BrowserMediaPlayerManager::OnError(int player_id, int error) {
286 Send(new MediaPlayerMsg_MediaError(routing_id(), player_id, error));
287 if (fullscreen_player_id_ == player_id)
288 video_view_->OnMediaPlayerError(error);
291 void BrowserMediaPlayerManager::OnVideoSizeChanged(
292 int player_id, int width, int height) {
293 Send(new MediaPlayerMsg_MediaVideoSizeChanged(routing_id(), player_id,
295 if (fullscreen_player_id_ == player_id)
296 video_view_->OnVideoSizeChanged(width, height);
299 void BrowserMediaPlayerManager::RequestMediaResources(int player_id) {
300 int num_active_player = 0;
301 ScopedVector<MediaPlayerAndroid>::iterator it;
302 for (it = players_.begin(); it != players_.end(); ++it) {
303 if (!(*it)->IsPlayerReady())
306 // The player is already active, ignore it.
307 if ((*it)->player_id() == player_id)
313 // Number of active players are less than the threshold, do nothing.
314 if (num_active_player < kMediaPlayerThreshold)
317 for (it = players_.begin(); it != players_.end(); ++it) {
318 if ((*it)->IsPlayerReady() && !(*it)->IsPlaying() &&
319 fullscreen_player_id_ != (*it)->player_id()) {
321 Send(new MediaPlayerMsg_MediaPlayerReleased(
322 routing_id(), (*it)->player_id()));
327 void BrowserMediaPlayerManager::ReleaseMediaResources(int player_id) {
328 // Nothing needs to be done.
331 media::MediaResourceGetter*
332 BrowserMediaPlayerManager::GetMediaResourceGetter() {
333 if (!media_resource_getter_.get()) {
334 RenderProcessHost* host = web_contents()->GetRenderProcessHost();
335 BrowserContext* context = host->GetBrowserContext();
336 StoragePartition* partition = host->GetStoragePartition();
337 fileapi::FileSystemContext* file_system_context =
338 partition ? partition->GetFileSystemContext() : NULL;
339 media_resource_getter_.reset(new MediaResourceGetterImpl(
340 context, file_system_context, host->GetID(), routing_id()));
342 return media_resource_getter_.get();
345 MediaPlayerAndroid* BrowserMediaPlayerManager::GetFullscreenPlayer() {
346 return GetPlayer(fullscreen_player_id_);
349 MediaPlayerAndroid* BrowserMediaPlayerManager::GetPlayer(int player_id) {
350 for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
351 it != players_.end(); ++it) {
352 if ((*it)->player_id() == player_id)
358 MediaDrmBridge* BrowserMediaPlayerManager::GetDrmBridge(int media_keys_id) {
359 for (ScopedVector<MediaDrmBridge>::iterator it = drm_bridges_.begin();
360 it != drm_bridges_.end(); ++it) {
361 if ((*it)->media_keys_id() == media_keys_id)
367 void BrowserMediaPlayerManager::DestroyAllMediaPlayers() {
369 drm_bridges_.clear();
370 if (fullscreen_player_id_ != -1) {
372 fullscreen_player_id_ = -1;
376 void BrowserMediaPlayerManager::OnProtectedSurfaceRequested(int player_id) {
377 if (fullscreen_player_id_ == player_id)
380 if (fullscreen_player_id_ != -1) {
381 // TODO(qinmin): Determine the correct error code we should report to WMPA.
382 OnError(player_id, MediaPlayerAndroid::MEDIA_ERROR_DECODE);
386 // If the player is pending approval, wait for the approval to happen.
387 if (media_keys_ids_pending_approval_.end() !=
388 media_keys_ids_pending_approval_.find(player_id)) {
389 pending_fullscreen_player_id_ = player_id;
393 // Send an IPC to the render process to request the video element to enter
394 // fullscreen. OnEnterFullscreen() will be called later on success.
395 // This guarantees the fullscreen video will be rendered correctly.
396 // During the process, DisableFullscreenEncryptedMediaPlayback() may get
397 // called before or after OnEnterFullscreen(). If it is called before
398 // OnEnterFullscreen(), the player will not enter fullscreen. And it will
399 // retry the process once CreateSession() is allowed to proceed.
400 // TODO(qinmin): make this flag default on android.
401 if (CommandLine::ForCurrentProcess()->HasSwitch(
402 switches::kDisableGestureRequirementForMediaFullscreen)) {
403 Send(new MediaPlayerMsg_RequestFullscreen(routing_id(), player_id));
407 // The following 5 functions are EME MediaKeySession events.
409 void BrowserMediaPlayerManager::OnSessionCreated(
412 const std::string& web_session_id) {
413 Send(new MediaKeysMsg_SessionCreated(
414 routing_id(), media_keys_id, session_id, web_session_id));
417 void BrowserMediaPlayerManager::OnSessionMessage(
420 const std::vector<uint8>& message,
421 const GURL& destination_url) {
422 Send(new MediaKeysMsg_SessionMessage(
423 routing_id(), media_keys_id, session_id, message, destination_url));
426 void BrowserMediaPlayerManager::OnSessionReady(int media_keys_id,
428 Send(new MediaKeysMsg_SessionReady(routing_id(), media_keys_id, session_id));
431 void BrowserMediaPlayerManager::OnSessionClosed(int media_keys_id,
433 Send(new MediaKeysMsg_SessionClosed(routing_id(), media_keys_id, session_id));
436 void BrowserMediaPlayerManager::OnSessionError(
439 media::MediaKeys::KeyError error_code,
441 Send(new MediaKeysMsg_SessionError(
442 routing_id(), media_keys_id, session_id, error_code, system_code));
445 #if defined(VIDEO_HOLE)
446 void BrowserMediaPlayerManager::AttachExternalVideoSurface(int player_id,
448 MediaPlayerAndroid* player = GetPlayer(player_id);
450 player->SetVideoSurface(
451 gfx::ScopedJavaSurface::AcquireExternalSurface(surface));
455 void BrowserMediaPlayerManager::DetachExternalVideoSurface(int player_id) {
456 MediaPlayerAndroid* player = GetPlayer(player_id);
458 player->SetVideoSurface(gfx::ScopedJavaSurface());
461 void BrowserMediaPlayerManager::OnNotifyExternalSurface(
462 int player_id, bool is_request, const gfx::RectF& rect) {
466 WebContentsViewAndroid* view =
467 static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
469 view->NotifyExternalSurface(player_id, is_request, rect);
471 #endif // defined(VIDEO_HOLE)
473 void BrowserMediaPlayerManager::DisableFullscreenEncryptedMediaPlayback() {
474 if (fullscreen_player_id_ == -1)
477 // If the fullscreen player is not playing back encrypted video, do nothing.
478 MediaDrmBridge* drm_bridge = GetDrmBridge(fullscreen_player_id_);
483 pending_fullscreen_player_id_ = fullscreen_player_id_;
484 OnExitFullscreen(fullscreen_player_id_);
487 void BrowserMediaPlayerManager::OnEnterFullscreen(int player_id) {
488 DCHECK_EQ(fullscreen_player_id_, -1);
489 if (media_keys_ids_pending_approval_.find(player_id) !=
490 media_keys_ids_pending_approval_.end()) {
494 if (video_view_.get()) {
495 fullscreen_player_id_ = player_id;
496 video_view_->OpenVideo();
497 } else if (!ContentVideoView::GetInstance()) {
498 // In Android WebView, two ContentViewCores could both try to enter
499 // fullscreen video, we just ignore the second one.
500 fullscreen_player_id_ = player_id;
501 video_view_.reset(new ContentVideoView(this));
505 void BrowserMediaPlayerManager::OnExitFullscreen(int player_id) {
506 if (fullscreen_player_id_ == player_id) {
507 MediaPlayerAndroid* player = GetPlayer(player_id);
509 player->SetVideoSurface(gfx::ScopedJavaSurface());
510 video_view_->OnExitFullscreen();
514 void BrowserMediaPlayerManager::OnInitialize(
515 MediaPlayerHostMsg_Initialize_Type type,
518 const GURL& first_party_for_cookies,
519 int demuxer_client_id) {
520 DCHECK(type != MEDIA_PLAYER_TYPE_MEDIA_SOURCE || demuxer_client_id > 0)
521 << "Media source players must have positive demuxer client IDs: "
522 << demuxer_client_id;
524 RemovePlayer(player_id);
526 RenderProcessHostImpl* host = static_cast<RenderProcessHostImpl*>(
527 web_contents()->GetRenderProcessHost());
528 AddPlayer(CreateMediaPlayer(
529 type, player_id, url, first_party_for_cookies, demuxer_client_id,
530 host->GetBrowserContext()->IsOffTheRecord(), this,
531 host->browser_demuxer_android()));
534 void BrowserMediaPlayerManager::OnStart(int player_id) {
535 MediaPlayerAndroid* player = GetPlayer(player_id);
540 void BrowserMediaPlayerManager::OnSeek(
542 const base::TimeDelta& time) {
543 MediaPlayerAndroid* player = GetPlayer(player_id);
545 player->SeekTo(time);
548 void BrowserMediaPlayerManager::OnPause(
550 bool is_media_related_action) {
551 MediaPlayerAndroid* player = GetPlayer(player_id);
553 player->Pause(is_media_related_action);
556 void BrowserMediaPlayerManager::OnSetVolume(int player_id, double volume) {
557 MediaPlayerAndroid* player = GetPlayer(player_id);
559 player->SetVolume(volume);
562 void BrowserMediaPlayerManager::OnSetPoster(int player_id, const GURL& url) {
563 // To be overridden by subclasses.
566 void BrowserMediaPlayerManager::OnReleaseResources(int player_id) {
567 MediaPlayerAndroid* player = GetPlayer(player_id);
570 if (player_id == fullscreen_player_id_)
571 fullscreen_player_is_released_ = true;
573 #if defined(VIDEO_HOLE)
574 WebContentsViewAndroid* view =
575 static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
577 view->NotifyExternalSurface(player_id, false, gfx::RectF());
578 #endif // defined(VIDEO_HOLE)
581 void BrowserMediaPlayerManager::OnDestroyPlayer(int player_id) {
582 RemovePlayer(player_id);
583 if (fullscreen_player_id_ == player_id)
584 fullscreen_player_id_ = -1;
587 void BrowserMediaPlayerManager::OnInitializeCDM(
589 const std::vector<uint8>& uuid,
590 const GURL& frame_url) {
591 if (uuid.size() != kEmeUuidSize) {
592 // This failure will be discovered and reported by OnCreateSession()
593 // as GetDrmBridge() will return null.
594 NOTREACHED() << "Invalid UUID for ID: " << media_keys_id;
598 AddDrmBridge(media_keys_id, uuid, frame_url);
599 // In EME v0.1b MediaKeys lives in the media element. So the |media_keys_id|
600 // is the same as the |player_id|.
601 OnSetMediaKeys(media_keys_id, media_keys_id);
604 void BrowserMediaPlayerManager::OnCreateSession(
607 MediaKeysHostMsg_CreateSession_Type content_type,
608 const std::vector<uint8>& init_data) {
609 if (init_data.size() > kEmeInitDataMaximum) {
610 LOG(WARNING) << "InitData for ID: " << media_keys_id
611 << " too long: " << init_data.size();
613 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
617 // Convert the session content type into a MIME type. "audio" and "video"
618 // don't matter, so using "video" for the MIME type.
620 // https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-createsession
621 std::string mime_type;
622 switch (content_type) {
623 case CREATE_SESSION_TYPE_WEBM:
624 mime_type = "video/webm";
626 case CREATE_SESSION_TYPE_MP4:
627 mime_type = "video/mp4";
634 if (CommandLine::ForCurrentProcess()
635 ->HasSwitch(switches::kDisableInfobarForProtectedMediaIdentifier)) {
636 CreateSessionIfPermitted(
637 media_keys_id, session_id, mime_type, init_data, true);
641 MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
643 DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found";
645 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
649 if (media_keys_ids_approved_.find(media_keys_id) ==
650 media_keys_ids_approved_.end()) {
651 media_keys_ids_pending_approval_.insert(media_keys_id);
654 BrowserContext* context =
655 web_contents()->GetRenderProcessHost()->GetBrowserContext();
657 context->RequestProtectedMediaIdentifierPermission(
658 web_contents()->GetRenderProcessHost()->GetID(),
659 web_contents()->GetRenderViewHost()->GetRoutingID(),
660 static_cast<int>(session_id),
662 drm_bridge->frame_url(),
663 base::Bind(&BrowserMediaPlayerManager::CreateSessionIfPermitted,
664 weak_ptr_factory_.GetWeakPtr(),
671 void BrowserMediaPlayerManager::OnUpdateSession(
674 const std::vector<uint8>& response) {
675 MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
677 DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found";
679 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
683 if (response.size() > kEmeResponseMaximum) {
684 LOG(WARNING) << "Response for ID: " << media_keys_id
685 << " too long: " << response.size();
687 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
691 drm_bridge->UpdateSession(session_id, &response[0], response.size());
692 // In EME v0.1b MediaKeys lives in the media element. So the |media_keys_id|
693 // is the same as the |player_id|.
694 // TODO(xhwang): Separate |media_keys_id| and |player_id|.
695 MediaPlayerAndroid* player = GetPlayer(media_keys_id);
697 player->OnKeyAdded();
700 void BrowserMediaPlayerManager::OnReleaseSession(int media_keys_id,
702 MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
704 DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found";
706 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
710 drm_bridge->ReleaseSession(session_id);
713 void BrowserMediaPlayerManager::OnDestroyCdm(int media_keys_id) {
714 MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
715 if (!drm_bridge) return;
717 CancelAllPendingSessionCreations(media_keys_id);
718 RemoveDrmBridge(media_keys_id);
721 void BrowserMediaPlayerManager::CancelAllPendingSessionCreations(
723 BrowserContext* context =
724 web_contents()->GetRenderProcessHost()->GetBrowserContext();
725 context->CancelProtectedMediaIdentifierPermissionRequests(media_keys_id);
728 void BrowserMediaPlayerManager::AddPlayer(MediaPlayerAndroid* player) {
729 DCHECK(!GetPlayer(player->player_id()));
730 players_.push_back(player);
731 if (player->IsRemote()) {
732 Send(new MediaPlayerMsg_ConnectedToRemoteDevice(routing_id(),
733 player->player_id()));
737 void BrowserMediaPlayerManager::RemovePlayer(int player_id) {
738 for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
739 it != players_.end(); ++it) {
740 MediaPlayerAndroid* player = *it;
741 if (player->player_id() == player_id) {
742 if (player->IsRemote()) {
743 Send(new MediaPlayerMsg_DisconnectedFromRemoteDevice(
744 routing_id(), player->player_id()));
752 scoped_ptr<media::MediaPlayerAndroid> BrowserMediaPlayerManager::SwapPlayer(
753 int player_id, media::MediaPlayerAndroid* player) {
754 media::MediaPlayerAndroid* previous_player = NULL;
755 for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
756 it != players_.end(); ++it) {
757 if ((*it)->player_id() == player_id) {
758 previous_player = *it;
759 players_.weak_erase(it);
760 players_.push_back(player);
761 if (!previous_player->IsRemote() && player->IsRemote()) {
762 Send(new MediaPlayerMsg_ConnectedToRemoteDevice(
763 routing_id(), player->player_id()));
764 } else if (previous_player->IsRemote() && !player->IsRemote()) {
765 Send(new MediaPlayerMsg_DisconnectedFromRemoteDevice(
766 routing_id(), player->player_id()));
771 return scoped_ptr<media::MediaPlayerAndroid>(previous_player);
774 void BrowserMediaPlayerManager::AddDrmBridge(int media_keys_id,
775 const std::vector<uint8>& uuid,
776 const GURL& frame_url) {
777 DCHECK(!GetDrmBridge(media_keys_id));
779 scoped_ptr<MediaDrmBridge> drm_bridge(MediaDrmBridge::Create(
780 media_keys_id, uuid, frame_url, this));
782 // This failure will be discovered and reported by OnCreateSession()
783 // as GetDrmBridge() will return null.
784 DVLOG(1) << "failed to create drm bridge.";
788 // TODO(xhwang/ddorwin): Pass the security level from key system.
789 MediaDrmBridge::SecurityLevel security_level =
790 MediaDrmBridge::SECURITY_LEVEL_3;
791 if (CommandLine::ForCurrentProcess()
792 ->HasSwitch(switches::kMediaDrmEnableNonCompositing)) {
793 security_level = MediaDrmBridge::SECURITY_LEVEL_1;
795 if (!drm_bridge->SetSecurityLevel(security_level)) {
796 DVLOG(1) << "failed to set security level " << security_level;
800 drm_bridges_.push_back(drm_bridge.release());
803 void BrowserMediaPlayerManager::RemoveDrmBridge(int media_keys_id) {
804 for (ScopedVector<MediaDrmBridge>::iterator it = drm_bridges_.begin();
805 it != drm_bridges_.end(); ++it) {
806 if ((*it)->media_keys_id() == media_keys_id) {
807 drm_bridges_.erase(it);
813 void BrowserMediaPlayerManager::OnSetMediaKeys(int player_id,
815 MediaPlayerAndroid* player = GetPlayer(player_id);
816 MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
817 if (!player || !drm_bridge) {
818 DVLOG(1) << "OnSetMediaKeys(): Player and MediaKeys must be present.";
821 // TODO(qinmin): add the logic to decide whether we should create the
822 // fullscreen surface for EME lv1.
823 player->SetDrmBridge(drm_bridge);
826 void BrowserMediaPlayerManager::CreateSessionIfPermitted(
829 const std::string& content_type,
830 const std::vector<uint8>& init_data,
834 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
838 MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
840 DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found";
842 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
845 media_keys_ids_pending_approval_.erase(media_keys_id);
846 media_keys_ids_approved_.insert(media_keys_id);
848 if (!drm_bridge->CreateSession(
849 session_id, content_type, &init_data[0], init_data.size())) {
853 // TODO(xhwang): Move the following code to OnSessionReady.
855 // TODO(qinmin): currently |media_keys_id| and player ID are identical.
856 // This might not be true in the future.
857 if (pending_fullscreen_player_id_ != media_keys_id)
860 pending_fullscreen_player_id_ = -1;
861 MediaPlayerAndroid* player = GetPlayer(media_keys_id);
862 if (player->IsPlaying())
863 OnProtectedSurfaceRequested(media_keys_id);
866 void BrowserMediaPlayerManager::ReleaseFullscreenPlayer(
867 MediaPlayerAndroid* player) {
871 } // namespace content