Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / content / browser / media / android / browser_media_player_manager.cc
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.
4
5 #include "content/browser/media/android/browser_media_player_manager.h"
6
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"
27
28 using media::MediaDrmBridge;
29 using media::MediaPlayerAndroid;
30 using media::MediaPlayerBridge;
31 using media::MediaPlayerManager;
32 using media::MediaSourcePlayer;
33
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;
37
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
44
45 namespace content {
46
47 static BrowserMediaPlayerManager::Factory g_factory = NULL;
48
49 // static
50 void BrowserMediaPlayerManager::RegisterFactory(Factory factory) {
51   g_factory = factory;
52 }
53
54 // static
55 BrowserMediaPlayerManager* BrowserMediaPlayerManager::Create(
56     RenderViewHost* rvh) {
57   if (g_factory)
58     return g_factory(rvh);
59   return new BrowserMediaPlayerManager(rvh);
60 }
61
62 ContentViewCoreImpl* BrowserMediaPlayerManager::GetContentViewCore() const {
63   return ContentViewCoreImpl::FromWebContents(web_contents());
64 }
65
66 // static
67 MediaPlayerAndroid* BrowserMediaPlayerManager::CreateMediaPlayer(
68     MediaPlayerHostMsg_Initialize_Type type,
69     int player_id,
70     const GURL& url,
71     const GURL& first_party_for_cookies,
72     int demuxer_client_id,
73     bool hide_url_log,
74     MediaPlayerManager* manager,
75     BrowserDemuxerAndroid* demuxer) {
76   switch (type) {
77     case MEDIA_PLAYER_TYPE_URL: {
78       const std::string user_agent = GetUserAgent(url);
79       MediaPlayerBridge* media_player_bridge = new MediaPlayerBridge(
80           player_id,
81           url,
82           first_party_for_cookies,
83           user_agent,
84           hide_url_log,
85           manager);
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
95         // the page.
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();
100       }
101       return media_player_bridge;
102     }
103
104     case MEDIA_PLAYER_TYPE_MEDIA_SOURCE: {
105       return new MediaSourcePlayer(
106           player_id, manager, demuxer->CreateDemuxer(demuxer_client_id));
107     }
108   }
109
110   NOTREACHED();
111   return NULL;
112 }
113
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) {
122 }
123
124 BrowserMediaPlayerManager::~BrowserMediaPlayerManager() {}
125
126 bool BrowserMediaPlayerManager::OnMessageReceived(const IPC::Message& msg) {
127   bool handled = true;
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,
142                         OnInitializeCDM)
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()
153   return handled;
154 }
155
156 void BrowserMediaPlayerManager::FullscreenPlayerPlay() {
157   MediaPlayerAndroid* player = GetFullscreenPlayer();
158   if (player) {
159     if (fullscreen_player_is_released_) {
160       video_view_->OpenVideo();
161       fullscreen_player_is_released_ = false;
162     }
163     player->Start();
164     Send(new MediaPlayerMsg_DidMediaPlayerPlay(
165         routing_id(), fullscreen_player_id_));
166   }
167 }
168
169 void BrowserMediaPlayerManager::FullscreenPlayerPause() {
170   MediaPlayerAndroid* player = GetFullscreenPlayer();
171   if (player) {
172     player->Pause(true);
173     Send(new MediaPlayerMsg_DidMediaPlayerPause(
174         routing_id(), fullscreen_player_id_));
175   }
176 }
177
178 void BrowserMediaPlayerManager::FullscreenPlayerSeek(int msec) {
179   MediaPlayerAndroid* player = GetFullscreenPlayer();
180   if (player) {
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));
186   }
187 }
188
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);
198     }
199   }
200
201   Send(new MediaPlayerMsg_DidExitFullscreen(
202       routing_id(), fullscreen_player_id_));
203   video_view_.reset();
204   MediaPlayerAndroid* player = GetFullscreenPlayer();
205   fullscreen_player_id_ = -1;
206   if (!player)
207     return;
208   if (release_media_player)
209     ReleaseFullscreenPlayer(player);
210   else
211     player->SetVideoSurface(gfx::ScopedJavaSurface());
212 }
213
214 void BrowserMediaPlayerManager::OnTimeUpdate(int player_id,
215                                              base::TimeDelta current_time) {
216   Send(new MediaPlayerMsg_MediaTimeUpdate(
217       routing_id(), player_id, current_time));
218 }
219
220 void BrowserMediaPlayerManager::SetVideoSurface(
221     gfx::ScopedJavaSurface surface) {
222   MediaPlayerAndroid* player = GetFullscreenPlayer();
223   if (!player)
224     return;
225   if (!surface.IsEmpty()) {
226     Send(new MediaPlayerMsg_DidEnterFullscreen(routing_id(),
227                                                player->player_id()));
228   }
229   player->SetVideoSurface(surface.Pass());
230
231   if (!CommandLine::ForCurrentProcess()->HasSwitch(
232       switches::kEnableOverlayFullscreenVideoSubtitle)) {
233     return;
234   }
235   if (RenderWidgetHostViewAndroid* view_android =
236       static_cast<RenderWidgetHostViewAndroid*>(
237           web_contents_->GetRenderWidgetHostView())) {
238     view_android->SetOverlayVideoMode(true);
239   }
240   if (WebContentsDelegate* delegate = web_contents_->GetDelegate())
241     delegate->ToggleFullscreenModeForTab(web_contents_, true);
242 }
243
244 void BrowserMediaPlayerManager::OnMediaMetadataChanged(
245     int player_id, base::TimeDelta duration, int width, int height,
246     bool success) {
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();
251 }
252
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();
257 }
258
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);
263 }
264
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);
271 }
272
273 void BrowserMediaPlayerManager::OnSeekRequest(
274     int player_id,
275     const base::TimeDelta& time_to_seek) {
276   Send(new MediaPlayerMsg_SeekRequest(routing_id(), player_id, time_to_seek));
277 }
278
279 void BrowserMediaPlayerManager::OnSeekComplete(
280     int player_id,
281     const base::TimeDelta& current_time) {
282   Send(new MediaPlayerMsg_SeekCompleted(routing_id(), player_id, current_time));
283 }
284
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);
289 }
290
291 void BrowserMediaPlayerManager::OnVideoSizeChanged(
292     int player_id, int width, int height) {
293   Send(new MediaPlayerMsg_MediaVideoSizeChanged(routing_id(), player_id,
294       width, height));
295   if (fullscreen_player_id_ == player_id)
296     video_view_->OnVideoSizeChanged(width, height);
297 }
298
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())
304       continue;
305
306     // The player is already active, ignore it.
307     if ((*it)->player_id() == player_id)
308       return;
309     else
310       num_active_player++;
311   }
312
313   // Number of active players are less than the threshold, do nothing.
314   if (num_active_player < kMediaPlayerThreshold)
315     return;
316
317   for (it = players_.begin(); it != players_.end(); ++it) {
318     if ((*it)->IsPlayerReady() && !(*it)->IsPlaying() &&
319         fullscreen_player_id_ != (*it)->player_id()) {
320       (*it)->Release();
321       Send(new MediaPlayerMsg_MediaPlayerReleased(
322           routing_id(), (*it)->player_id()));
323     }
324   }
325 }
326
327 void BrowserMediaPlayerManager::ReleaseMediaResources(int player_id) {
328   // Nothing needs to be done.
329 }
330
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()));
341   }
342   return media_resource_getter_.get();
343 }
344
345 MediaPlayerAndroid* BrowserMediaPlayerManager::GetFullscreenPlayer() {
346   return GetPlayer(fullscreen_player_id_);
347 }
348
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)
353       return *it;
354   }
355   return NULL;
356 }
357
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)
362       return *it;
363   }
364   return NULL;
365 }
366
367 void BrowserMediaPlayerManager::DestroyAllMediaPlayers() {
368   players_.clear();
369   drm_bridges_.clear();
370   if (fullscreen_player_id_ != -1) {
371     video_view_.reset();
372     fullscreen_player_id_ = -1;
373   }
374 }
375
376 void BrowserMediaPlayerManager::OnProtectedSurfaceRequested(int player_id) {
377   if (fullscreen_player_id_ == player_id)
378     return;
379
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);
383     return;
384   }
385
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;
390     return;
391   }
392
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));
404   }
405 }
406
407 // The following 5 functions are EME MediaKeySession events.
408
409 void BrowserMediaPlayerManager::OnSessionCreated(
410     int media_keys_id,
411     uint32 session_id,
412     const std::string& web_session_id) {
413   Send(new MediaKeysMsg_SessionCreated(
414       routing_id(), media_keys_id, session_id, web_session_id));
415 }
416
417 void BrowserMediaPlayerManager::OnSessionMessage(
418     int media_keys_id,
419     uint32 session_id,
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));
424 }
425
426 void BrowserMediaPlayerManager::OnSessionReady(int media_keys_id,
427                                                uint32 session_id) {
428   Send(new MediaKeysMsg_SessionReady(routing_id(), media_keys_id, session_id));
429 }
430
431 void BrowserMediaPlayerManager::OnSessionClosed(int media_keys_id,
432                                                 uint32 session_id) {
433   Send(new MediaKeysMsg_SessionClosed(routing_id(), media_keys_id, session_id));
434 }
435
436 void BrowserMediaPlayerManager::OnSessionError(
437     int media_keys_id,
438     uint32 session_id,
439     media::MediaKeys::KeyError error_code,
440     int system_code) {
441   Send(new MediaKeysMsg_SessionError(
442       routing_id(), media_keys_id, session_id, error_code, system_code));
443 }
444
445 #if defined(VIDEO_HOLE)
446 void BrowserMediaPlayerManager::AttachExternalVideoSurface(int player_id,
447                                                            jobject surface) {
448   MediaPlayerAndroid* player = GetPlayer(player_id);
449   if (player) {
450     player->SetVideoSurface(
451         gfx::ScopedJavaSurface::AcquireExternalSurface(surface));
452   }
453 }
454
455 void BrowserMediaPlayerManager::DetachExternalVideoSurface(int player_id) {
456   MediaPlayerAndroid* player = GetPlayer(player_id);
457   if (player)
458     player->SetVideoSurface(gfx::ScopedJavaSurface());
459 }
460
461 void BrowserMediaPlayerManager::OnNotifyExternalSurface(
462     int player_id, bool is_request, const gfx::RectF& rect) {
463   if (!web_contents_)
464     return;
465
466   WebContentsViewAndroid* view =
467       static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
468   if (view)
469     view->NotifyExternalSurface(player_id, is_request, rect);
470 }
471 #endif  // defined(VIDEO_HOLE)
472
473 void BrowserMediaPlayerManager::DisableFullscreenEncryptedMediaPlayback() {
474   if (fullscreen_player_id_ == -1)
475     return;
476
477   // If the fullscreen player is not playing back encrypted video, do nothing.
478   MediaDrmBridge* drm_bridge = GetDrmBridge(fullscreen_player_id_);
479   if (!drm_bridge)
480     return;
481
482   // Exit fullscreen.
483   pending_fullscreen_player_id_ = fullscreen_player_id_;
484   OnExitFullscreen(fullscreen_player_id_);
485 }
486
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()) {
491     return;
492   }
493
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));
502   }
503 }
504
505 void BrowserMediaPlayerManager::OnExitFullscreen(int player_id) {
506   if (fullscreen_player_id_ == player_id) {
507     MediaPlayerAndroid* player = GetPlayer(player_id);
508     if (player)
509       player->SetVideoSurface(gfx::ScopedJavaSurface());
510     video_view_->OnExitFullscreen();
511   }
512 }
513
514 void BrowserMediaPlayerManager::OnInitialize(
515     MediaPlayerHostMsg_Initialize_Type type,
516     int player_id,
517     const GURL& url,
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;
523
524   RemovePlayer(player_id);
525
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()));
532 }
533
534 void BrowserMediaPlayerManager::OnStart(int player_id) {
535   MediaPlayerAndroid* player = GetPlayer(player_id);
536   if (player)
537     player->Start();
538 }
539
540 void BrowserMediaPlayerManager::OnSeek(
541     int player_id,
542     const base::TimeDelta& time) {
543   MediaPlayerAndroid* player = GetPlayer(player_id);
544   if (player)
545     player->SeekTo(time);
546 }
547
548 void BrowserMediaPlayerManager::OnPause(
549     int player_id,
550     bool is_media_related_action) {
551   MediaPlayerAndroid* player = GetPlayer(player_id);
552   if (player)
553     player->Pause(is_media_related_action);
554 }
555
556 void BrowserMediaPlayerManager::OnSetVolume(int player_id, double volume) {
557   MediaPlayerAndroid* player = GetPlayer(player_id);
558   if (player)
559     player->SetVolume(volume);
560 }
561
562 void BrowserMediaPlayerManager::OnSetPoster(int player_id, const GURL& url) {
563   // To be overridden by subclasses.
564 }
565
566 void BrowserMediaPlayerManager::OnReleaseResources(int player_id) {
567   MediaPlayerAndroid* player = GetPlayer(player_id);
568   if (player)
569     player->Release();
570   if (player_id == fullscreen_player_id_)
571     fullscreen_player_is_released_ = true;
572
573 #if defined(VIDEO_HOLE)
574   WebContentsViewAndroid* view =
575       static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
576   if (view)
577     view->NotifyExternalSurface(player_id, false, gfx::RectF());
578 #endif  // defined(VIDEO_HOLE)
579 }
580
581 void BrowserMediaPlayerManager::OnDestroyPlayer(int player_id) {
582   RemovePlayer(player_id);
583   if (fullscreen_player_id_ == player_id)
584     fullscreen_player_id_ = -1;
585 }
586
587 void BrowserMediaPlayerManager::OnInitializeCDM(
588     int media_keys_id,
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;
595     return;
596   }
597
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);
602 }
603
604 void BrowserMediaPlayerManager::OnCreateSession(
605     int media_keys_id,
606     uint32 session_id,
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();
612     OnSessionError(
613         media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
614     return;
615   }
616
617   // Convert the session content type into a MIME type. "audio" and "video"
618   // don't matter, so using "video" for the MIME type.
619   // Ref:
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";
625       break;
626     case CREATE_SESSION_TYPE_MP4:
627       mime_type = "video/mp4";
628       break;
629     default:
630       NOTREACHED();
631       return;
632   }
633
634   if (CommandLine::ForCurrentProcess()
635       ->HasSwitch(switches::kDisableInfobarForProtectedMediaIdentifier)) {
636     CreateSessionIfPermitted(
637         media_keys_id, session_id, mime_type, init_data, true);
638     return;
639   }
640
641   MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
642   if (!drm_bridge) {
643     DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found";
644     OnSessionError(
645         media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
646     return;
647   }
648
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);
652   }
653
654   BrowserContext* context =
655       web_contents()->GetRenderProcessHost()->GetBrowserContext();
656
657   context->RequestProtectedMediaIdentifierPermission(
658       web_contents()->GetRenderProcessHost()->GetID(),
659       web_contents()->GetRenderViewHost()->GetRoutingID(),
660       static_cast<int>(session_id),
661       media_keys_id,
662       drm_bridge->frame_url(),
663       base::Bind(&BrowserMediaPlayerManager::CreateSessionIfPermitted,
664                  weak_ptr_factory_.GetWeakPtr(),
665                  media_keys_id,
666                  session_id,
667                  mime_type,
668                  init_data));
669 }
670
671 void BrowserMediaPlayerManager::OnUpdateSession(
672     int media_keys_id,
673     uint32 session_id,
674     const std::vector<uint8>& response) {
675   MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
676   if (!drm_bridge) {
677     DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found";
678     OnSessionError(
679         media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
680     return;
681   }
682
683   if (response.size() > kEmeResponseMaximum) {
684     LOG(WARNING) << "Response for ID: " << media_keys_id
685                  << " too long: " << response.size();
686     OnSessionError(
687         media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
688     return;
689   }
690
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);
696   if (player)
697     player->OnKeyAdded();
698 }
699
700 void BrowserMediaPlayerManager::OnReleaseSession(int media_keys_id,
701                                                  uint32 session_id) {
702   MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
703   if (!drm_bridge) {
704     DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found";
705     OnSessionError(
706         media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
707     return;
708   }
709
710   drm_bridge->ReleaseSession(session_id);
711 }
712
713 void BrowserMediaPlayerManager::OnDestroyCdm(int media_keys_id) {
714   MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
715   if (!drm_bridge) return;
716
717   CancelAllPendingSessionCreations(media_keys_id);
718   RemoveDrmBridge(media_keys_id);
719 }
720
721 void BrowserMediaPlayerManager::CancelAllPendingSessionCreations(
722     int media_keys_id) {
723   BrowserContext* context =
724       web_contents()->GetRenderProcessHost()->GetBrowserContext();
725   context->CancelProtectedMediaIdentifierPermissionRequests(media_keys_id);
726 }
727
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()));
734   }
735 }
736
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()));
745       }
746       players_.erase(it);
747       break;
748     }
749   }
750 }
751
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()));
767       }
768       break;
769     }
770   }
771   return scoped_ptr<media::MediaPlayerAndroid>(previous_player);
772 }
773
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));
778
779   scoped_ptr<MediaDrmBridge> drm_bridge(MediaDrmBridge::Create(
780       media_keys_id, uuid, frame_url, this));
781   if (!drm_bridge) {
782     // This failure will be discovered and reported by OnCreateSession()
783     // as GetDrmBridge() will return null.
784     DVLOG(1) << "failed to create drm bridge.";
785     return;
786   }
787
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;
794   }
795   if (!drm_bridge->SetSecurityLevel(security_level)) {
796     DVLOG(1) << "failed to set security level " << security_level;
797     return;
798   }
799
800   drm_bridges_.push_back(drm_bridge.release());
801 }
802
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);
808       break;
809     }
810   }
811 }
812
813 void BrowserMediaPlayerManager::OnSetMediaKeys(int player_id,
814                                                int media_keys_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.";
819     return;
820   }
821   // TODO(qinmin): add the logic to decide whether we should create the
822   // fullscreen surface for EME lv1.
823   player->SetDrmBridge(drm_bridge);
824 }
825
826 void BrowserMediaPlayerManager::CreateSessionIfPermitted(
827     int media_keys_id,
828     uint32 session_id,
829     const std::string& content_type,
830     const std::vector<uint8>& init_data,
831     bool permitted) {
832   if (!permitted) {
833     OnSessionError(
834         media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
835     return;
836   }
837
838   MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
839   if (!drm_bridge) {
840     DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found";
841     OnSessionError(
842         media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
843     return;
844   }
845   media_keys_ids_pending_approval_.erase(media_keys_id);
846   media_keys_ids_approved_.insert(media_keys_id);
847
848   if (!drm_bridge->CreateSession(
849            session_id, content_type, &init_data[0], init_data.size())) {
850     return;
851   }
852
853   // TODO(xhwang): Move the following code to OnSessionReady.
854
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)
858     return;
859
860   pending_fullscreen_player_id_ = -1;
861   MediaPlayerAndroid* player = GetPlayer(media_keys_id);
862   if (player->IsPlaying())
863     OnProtectedSurfaceRequested(media_keys_id);
864 }
865
866 void BrowserMediaPlayerManager::ReleaseFullscreenPlayer(
867     MediaPlayerAndroid* player) {
868     player->Release();
869 }
870
871 }  // namespace content