IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / browser / media / android / browser_media_player_manager.cc
blobda48675e683dc0d5796fae9e21d520da9ef407e5
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
46 namespace content {
48 static BrowserMediaPlayerManager::Factory g_factory = NULL;
50 // static
51 void BrowserMediaPlayerManager::RegisterFactory(Factory factory) {
52 g_factory = factory;
55 // static
56 BrowserMediaPlayerManager* BrowserMediaPlayerManager::Create(
57 RenderViewHost* rvh) {
58 if (g_factory)
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)
68 // static
69 MediaPlayerAndroid* BrowserMediaPlayerManager::CreateMediaPlayer(
70 MediaPlayerHostMsg_Initialize_Type type,
71 int player_id,
72 const GURL& url,
73 const GURL& first_party_for_cookies,
74 int demuxer_client_id,
75 bool hide_url_log,
76 MediaPlayerManager* manager,
77 BrowserDemuxerAndroid* demuxer) {
78 switch (type) {
79 case MEDIA_PLAYER_TYPE_URL: {
80 const std::string user_agent = GetUserAgent(url);
81 MediaPlayerBridge* media_player_bridge = new MediaPlayerBridge(
82 player_id,
83 url,
84 first_party_for_cookies,
85 user_agent,
86 hide_url_log,
87 manager);
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
97 // the page.
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));
112 NOTREACHED();
113 return NULL;
115 #endif
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) {
129 bool handled = true;
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,
143 OnInitializeCDM)
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()
155 return handled;
158 void BrowserMediaPlayerManager::FullscreenPlayerPlay() {
159 MediaPlayerAndroid* player = GetFullscreenPlayer();
160 if (player) {
161 player->Start();
162 Send(new MediaPlayerMsg_DidMediaPlayerPlay(
163 routing_id(), fullscreen_player_id_));
167 void BrowserMediaPlayerManager::FullscreenPlayerPause() {
168 MediaPlayerAndroid* player = GetFullscreenPlayer();
169 if (player) {
170 player->Pause(true);
171 Send(new MediaPlayerMsg_DidMediaPlayerPause(
172 routing_id(), fullscreen_player_id_));
176 void BrowserMediaPlayerManager::FullscreenPlayerSeek(int msec) {
177 MediaPlayerAndroid* player = GetFullscreenPlayer();
178 if (player) {
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_));
198 video_view_.reset();
199 MediaPlayerAndroid* player = GetFullscreenPlayer();
200 fullscreen_player_id_ = -1;
201 if (!player)
202 return;
203 if (release_media_player)
204 player->Release();
205 else
206 player->SetVideoSurface(gfx::ScopedJavaSurface());
209 void BrowserMediaPlayerManager::SuspendFullscreen() {
210 MediaPlayerAndroid* player = GetFullscreenPlayer();
211 if (player)
212 player->SetVideoSurface(gfx::ScopedJavaSurface());
215 void BrowserMediaPlayerManager::ResumeFullscreen(
216 gfx::ScopedJavaSurface surface) {
217 MediaPlayerAndroid* player = GetFullscreenPlayer();
218 if (player)
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();
231 if (!player)
232 return;
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,
250 bool success) {
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(
278 int player_id,
279 const base::TimeDelta& time_to_seek) {
280 Send(new MediaPlayerMsg_SeekRequest(routing_id(), player_id, time_to_seek));
283 void BrowserMediaPlayerManager::OnSeekComplete(
284 int player_id,
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,
298 width, height));
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())
308 continue;
310 // The player is already active, ignore it.
311 if ((*it)->player_id() == player_id)
312 return;
313 else
314 num_active_player++;
317 // Number of active players are less than the threshold, do nothing.
318 if (num_active_player < kMediaPlayerThreshold)
319 return;
321 for (it = players_.begin(); it != players_.end(); ++it) {
322 if ((*it)->IsPlayerReady() && !(*it)->IsPlaying() &&
323 fullscreen_player_id_ != (*it)->player_id()) {
324 (*it)->Release();
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)
357 return *it;
359 return NULL;
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)
366 return *it;
368 return NULL;
371 void BrowserMediaPlayerManager::DestroyAllMediaPlayers() {
372 players_.clear();
373 drm_bridges_.clear();
374 if (fullscreen_player_id_ != -1) {
375 video_view_.reset();
376 fullscreen_player_id_ = -1;
380 void BrowserMediaPlayerManager::OnProtectedSurfaceRequested(int player_id) {
381 if (fullscreen_player_id_ == player_id)
382 return;
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);
387 return;
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;
394 return;
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(
414 int media_keys_id,
415 uint32 session_id,
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(
422 int media_keys_id,
423 uint32 session_id,
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,
431 uint32 session_id) {
432 Send(new MediaKeysMsg_SessionReady(routing_id(), media_keys_id, session_id));
435 void BrowserMediaPlayerManager::OnSessionClosed(int media_keys_id,
436 uint32 session_id) {
437 Send(new MediaKeysMsg_SessionClosed(routing_id(), media_keys_id, session_id));
440 void BrowserMediaPlayerManager::OnSessionError(
441 int media_keys_id,
442 uint32 session_id,
443 media::MediaKeys::KeyError error_code,
444 int system_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,
451 jobject surface) {
452 MediaPlayerAndroid* player = GetPlayer(player_id);
453 if (player) {
454 player->SetVideoSurface(
455 gfx::ScopedJavaSurface::AcquireExternalSurface(surface));
459 void BrowserMediaPlayerManager::DetachExternalVideoSurface(int player_id) {
460 MediaPlayerAndroid* player = GetPlayer(player_id);
461 if (player)
462 player->SetVideoSurface(gfx::ScopedJavaSurface());
465 void BrowserMediaPlayerManager::OnNotifyExternalSurface(
466 int player_id, bool is_request, const gfx::RectF& rect) {
467 if (!web_contents_)
468 return;
470 WebContentsViewAndroid* view =
471 static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
472 if (view)
473 view->NotifyExternalSurface(player_id, is_request, rect);
475 #endif // defined(VIDEO_HOLE)
477 void BrowserMediaPlayerManager::DisableFullscreenEncryptedMediaPlayback() {
478 if (fullscreen_player_id_ == -1)
479 return;
481 // If the fullscreen player is not playing back encrypted video, do nothing.
482 MediaDrmBridge* drm_bridge = GetDrmBridge(fullscreen_player_id_);
483 if (!drm_bridge)
484 return;
486 // Exit fullscreen.
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()) {
495 return;
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);
512 if (player)
513 player->SetVideoSurface(gfx::ScopedJavaSurface());
514 video_view_->OnExitFullscreen();
518 void BrowserMediaPlayerManager::OnInitialize(
519 MediaPlayerHostMsg_Initialize_Type type,
520 int player_id,
521 const GURL& url,
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);
540 if (player)
541 player->Start();
544 void BrowserMediaPlayerManager::OnSeek(
545 int player_id,
546 const base::TimeDelta& time) {
547 MediaPlayerAndroid* player = GetPlayer(player_id);
548 if (player)
549 player->SeekTo(time);
552 void BrowserMediaPlayerManager::OnPause(
553 int player_id,
554 bool is_media_related_action) {
555 MediaPlayerAndroid* player = GetPlayer(player_id);
556 if (player)
557 player->Pause(is_media_related_action);
560 void BrowserMediaPlayerManager::OnSetVolume(int player_id, double volume) {
561 MediaPlayerAndroid* player = GetPlayer(player_id);
562 if (player)
563 player->SetVolume(volume);
566 void BrowserMediaPlayerManager::OnReleaseResources(int player_id) {
567 MediaPlayerAndroid* player = GetPlayer(player_id);
568 if (player)
569 player->Release();
571 #if defined(VIDEO_HOLE)
572 WebContentsViewAndroid* view =
573 static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
574 if (view)
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(
586 int media_keys_id,
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;
593 return;
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(
603 int media_keys_id,
604 uint32 session_id,
605 const std::string& type,
606 const std::vector<uint8>& init_data) {
607 if (type.length() > kEmeTypeMaximum) {
608 OnSessionError(
609 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
610 return;
612 if (init_data.size() > kEmeInitDataMaximum) {
613 OnSessionError(
614 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
615 return;
618 if (CommandLine::ForCurrentProcess()
619 ->HasSwitch(switches::kDisableInfobarForProtectedMediaIdentifier)) {
620 CreateSessionIfPermitted(media_keys_id, session_id, type, init_data, true);
621 return;
624 MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
625 if (!drm_bridge) {
626 DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found";
627 OnSessionError(
628 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
629 return;
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),
644 media_keys_id,
645 drm_bridge->frame_url(),
646 base::Bind(&BrowserMediaPlayerManager::CreateSessionIfPermitted,
647 weak_ptr_factory_.GetWeakPtr(),
648 media_keys_id,
649 session_id,
650 type,
651 init_data));
654 void BrowserMediaPlayerManager::OnUpdateSession(
655 int media_keys_id,
656 uint32 session_id,
657 const std::vector<uint8>& response) {
658 MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
659 if (!drm_bridge) {
660 DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found";
661 OnSessionError(
662 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
663 return;
666 if (response.size() > kEmeResponseMaximum) {
667 DLOG(WARNING) << "Response for ID: " << media_keys_id
668 << " too long: " << response.size();
669 OnSessionError(
670 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
671 return;
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);
679 if (player)
680 player->OnKeyAdded();
683 void BrowserMediaPlayerManager::OnReleaseSession(int media_keys_id,
684 uint32 session_id) {
685 MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
686 if (!drm_bridge) {
687 DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found";
688 OnSessionError(
689 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
690 return;
693 drm_bridge->ReleaseSession(session_id);
696 void BrowserMediaPlayerManager::OnCancelAllPendingSessionCreations(
697 int media_keys_id) {
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()));
724 players_.erase(it);
725 break;
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()));
746 break;
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));
759 if (!drm_bridge) {
760 // This failure will be discovered and reported by OnCreateSession()
761 // as GetDrmBridge() will return null.
762 DVLOG(1) << "failed to create drm bridge.";
763 return;
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;
775 return;
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);
786 break;
791 void BrowserMediaPlayerManager::OnSetMediaKeys(int player_id,
792 int media_keys_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.";
797 return;
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(
805 int media_keys_id,
806 uint32 session_id,
807 const std::string& type,
808 const std::vector<uint8>& init_data,
809 bool permitted) {
810 if (!permitted) {
811 OnSessionError(
812 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
813 return;
816 MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
817 if (!drm_bridge) {
818 DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found";
819 OnSessionError(
820 media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
821 return;
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)
830 return;
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