Upstream version 11.39.250.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/android/scoped_java_ref.h"
8 #include "base/command_line.h"
9 #include "content/browser/android/content_view_core_impl.h"
10 #include "content/browser/media/android/browser_demuxer_android.h"
11 #include "content/browser/media/android/media_resource_getter_impl.h"
12 #include "content/browser/renderer_host/render_view_host_impl.h"
13 #include "content/browser/web_contents/web_contents_view_android.h"
14 #include "content/common/media/media_player_messages_android.h"
15 #include "content/public/browser/android/content_view_core.h"
16 #include "content/public/browser/android/external_video_surface_container.h"
17 #include "content/public/browser/browser_context.h"
18 #include "content/public/browser/content_browser_client.h"
19 #include "content/public/browser/render_frame_host.h"
20 #include "content/public/browser/render_process_host.h"
21 #include "content/public/browser/render_view_host.h"
22 #include "content/public/browser/storage_partition.h"
23 #include "content/public/browser/web_contents.h"
24 #include "content/public/browser/web_contents_delegate.h"
25 #include "content/public/common/content_client.h"
26 #include "content/public/common/content_switches.h"
27 #include "media/base/android/media_player_bridge.h"
28 #include "media/base/android/media_source_player.h"
29 #include "media/base/android/media_url_interceptor.h"
30 #include "media/base/media_switches.h"
31
32 using media::MediaPlayerAndroid;
33 using media::MediaPlayerBridge;
34 using media::MediaPlayerManager;
35 using media::MediaSourcePlayer;
36
37 namespace content {
38
39 // Threshold on the number of media players per renderer before we start
40 // attempting to release inactive media players.
41 const int kMediaPlayerThreshold = 1;
42
43 static BrowserMediaPlayerManager::Factory g_factory = NULL;
44 static media::MediaUrlInterceptor* media_url_interceptor_ = NULL;
45
46 // static
47 void BrowserMediaPlayerManager::RegisterFactory(Factory factory) {
48   g_factory = factory;
49 }
50
51 // static
52 void BrowserMediaPlayerManager::RegisterMediaUrlInterceptor(
53     media::MediaUrlInterceptor* media_url_interceptor) {
54   media_url_interceptor_ = media_url_interceptor;
55 }
56
57 // static
58 BrowserMediaPlayerManager* BrowserMediaPlayerManager::Create(
59     RenderFrameHost* rfh) {
60   if (g_factory)
61     return g_factory(rfh);
62   return new BrowserMediaPlayerManager(rfh);
63 }
64
65 ContentViewCoreImpl* BrowserMediaPlayerManager::GetContentViewCore() const {
66   return ContentViewCoreImpl::FromWebContents(web_contents());
67 }
68
69 MediaPlayerAndroid* BrowserMediaPlayerManager::CreateMediaPlayer(
70     const MediaPlayerHostMsg_Initialize_Params& media_player_params,
71     bool hide_url_log,
72     MediaPlayerManager* manager,
73     BrowserDemuxerAndroid* demuxer) {
74   switch (media_player_params.type) {
75     case MEDIA_PLAYER_TYPE_URL: {
76       const std::string user_agent = GetContentClient()->GetUserAgent();
77       MediaPlayerBridge* media_player_bridge = new MediaPlayerBridge(
78           media_player_params.player_id,
79           media_player_params.url,
80           media_player_params.first_party_for_cookies,
81           user_agent,
82           hide_url_log,
83           manager,
84           base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesRequested,
85                      weak_ptr_factory_.GetWeakPtr()),
86           media_player_params.frame_url,
87           media_player_params.allow_credentials);
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             media_player_params.player_id, base::TimeDelta(), 0, 0, false);
100       } else if (!content_view_core_impl->ShouldBlockMediaRequest(
101             media_player_params.url)) {
102         media_player_bridge->Initialize();
103       }
104       return media_player_bridge;
105     }
106
107     case MEDIA_PLAYER_TYPE_MEDIA_SOURCE: {
108       return new MediaSourcePlayer(
109           media_player_params.player_id,
110           manager,
111           base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesRequested,
112                      weak_ptr_factory_.GetWeakPtr()),
113           demuxer->CreateDemuxer(media_player_params.demuxer_client_id),
114           media_player_params.frame_url);
115     }
116   }
117
118   NOTREACHED();
119   return NULL;
120 }
121
122 BrowserMediaPlayerManager::BrowserMediaPlayerManager(
123     RenderFrameHost* render_frame_host)
124     : render_frame_host_(render_frame_host),
125       fullscreen_player_id_(-1),
126       fullscreen_player_is_released_(false),
127       web_contents_(WebContents::FromRenderFrameHost(render_frame_host)),
128       weak_ptr_factory_(this) {
129 }
130
131 BrowserMediaPlayerManager::~BrowserMediaPlayerManager() {
132   // During the tear down process, OnDestroyPlayer() may or may not be called
133   // (e.g. the WebContents may be destroyed before the render process). So
134   // we cannot DCHECK(players_.empty()) here. Instead, all media players in
135   // |players_| will be destroyed here because |player_| is a ScopedVector.
136 }
137
138 void BrowserMediaPlayerManager::FullscreenPlayerPlay() {
139   MediaPlayerAndroid* player = GetFullscreenPlayer();
140   if (player) {
141     if (fullscreen_player_is_released_) {
142       video_view_->OpenVideo();
143       fullscreen_player_is_released_ = false;
144     }
145     player->Start();
146     Send(new MediaPlayerMsg_DidMediaPlayerPlay(RoutingID(),
147                                                fullscreen_player_id_));
148   }
149 }
150
151 void BrowserMediaPlayerManager::FullscreenPlayerPause() {
152   MediaPlayerAndroid* player = GetFullscreenPlayer();
153   if (player) {
154     player->Pause(true);
155     Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(),
156                                                 fullscreen_player_id_));
157   }
158 }
159
160 void BrowserMediaPlayerManager::FullscreenPlayerSeek(int msec) {
161   MediaPlayerAndroid* player = GetFullscreenPlayer();
162   if (player) {
163     // TODO(kbalazs): if |fullscreen_player_is_released_| is true
164     // at this point, player->GetCurrentTime() will be wrong until
165     // FullscreenPlayerPlay (http://crbug.com/322798).
166     OnSeekRequest(fullscreen_player_id_,
167                   base::TimeDelta::FromMilliseconds(msec));
168   }
169 }
170
171 void BrowserMediaPlayerManager::ExitFullscreen(bool release_media_player) {
172   if (WebContentsDelegate* delegate = web_contents_->GetDelegate())
173     delegate->ToggleFullscreenModeForTab(web_contents_, false);
174   if (RenderWidgetHostViewAndroid* view_android =
175       static_cast<RenderWidgetHostViewAndroid*>(
176           web_contents_->GetRenderWidgetHostView())) {
177     view_android->SetOverlayVideoMode(false);
178   }
179
180   Send(
181       new MediaPlayerMsg_DidExitFullscreen(RoutingID(), fullscreen_player_id_));
182   video_view_.reset();
183   MediaPlayerAndroid* player = GetFullscreenPlayer();
184   fullscreen_player_id_ = -1;
185   if (!player)
186     return;
187   if (release_media_player)
188     ReleaseFullscreenPlayer(player);
189   else
190     player->SetVideoSurface(gfx::ScopedJavaSurface());
191 }
192
193 void BrowserMediaPlayerManager::OnTimeUpdate(
194     int player_id,
195     base::TimeDelta current_timestamp,
196     base::TimeTicks current_time_ticks) {
197   Send(new MediaPlayerMsg_MediaTimeUpdate(
198       RoutingID(), player_id, current_timestamp, current_time_ticks));
199 }
200
201 void BrowserMediaPlayerManager::SetVideoSurface(
202     gfx::ScopedJavaSurface surface) {
203   MediaPlayerAndroid* player = GetFullscreenPlayer();
204   if (!player)
205     return;
206
207   bool empty_surface = surface.IsEmpty();
208   player->SetVideoSurface(surface.Pass());
209   if (empty_surface)
210     return;
211
212   Send(new MediaPlayerMsg_DidEnterFullscreen(RoutingID(), player->player_id()));
213   if (RenderWidgetHostViewAndroid* view_android =
214       static_cast<RenderWidgetHostViewAndroid*>(
215           web_contents_->GetRenderWidgetHostView())) {
216     view_android->SetOverlayVideoMode(true);
217   }
218 }
219
220 void BrowserMediaPlayerManager::OnMediaMetadataChanged(
221     int player_id, base::TimeDelta duration, int width, int height,
222     bool success) {
223   Send(new MediaPlayerMsg_MediaMetadataChanged(
224       RoutingID(), player_id, duration, width, height, success));
225   if (fullscreen_player_id_ == player_id)
226     video_view_->UpdateMediaMetadata();
227 }
228
229 void BrowserMediaPlayerManager::OnPlaybackComplete(int player_id) {
230   Send(new MediaPlayerMsg_MediaPlaybackCompleted(RoutingID(), player_id));
231   if (fullscreen_player_id_ == player_id)
232     video_view_->OnPlaybackComplete();
233 }
234
235 void BrowserMediaPlayerManager::OnMediaInterrupted(int player_id) {
236   // Tell WebKit that the audio should be paused, then release all resources
237   Send(new MediaPlayerMsg_MediaPlayerReleased(RoutingID(), player_id));
238   OnReleaseResources(player_id);
239 }
240
241 void BrowserMediaPlayerManager::OnBufferingUpdate(
242     int player_id, int percentage) {
243   Send(new MediaPlayerMsg_MediaBufferingUpdate(
244       RoutingID(), player_id, percentage));
245   if (fullscreen_player_id_ == player_id)
246     video_view_->OnBufferingUpdate(percentage);
247 }
248
249 void BrowserMediaPlayerManager::OnSeekRequest(
250     int player_id,
251     const base::TimeDelta& time_to_seek) {
252   Send(new MediaPlayerMsg_SeekRequest(RoutingID(), player_id, time_to_seek));
253 }
254
255 void BrowserMediaPlayerManager::ReleaseAllMediaPlayers() {
256   for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
257       it != players_.end(); ++it) {
258     if ((*it)->player_id() == fullscreen_player_id_)
259       fullscreen_player_is_released_ = true;
260     (*it)->Release();
261   }
262 }
263
264 void BrowserMediaPlayerManager::OnSeekComplete(
265     int player_id,
266     const base::TimeDelta& current_time) {
267   Send(new MediaPlayerMsg_SeekCompleted(RoutingID(), player_id, current_time));
268 }
269
270 void BrowserMediaPlayerManager::OnError(int player_id, int error) {
271   Send(new MediaPlayerMsg_MediaError(RoutingID(), player_id, error));
272   if (fullscreen_player_id_ == player_id)
273     video_view_->OnMediaPlayerError(error);
274 }
275
276 void BrowserMediaPlayerManager::OnVideoSizeChanged(
277     int player_id, int width, int height) {
278   Send(new MediaPlayerMsg_MediaVideoSizeChanged(RoutingID(), player_id,
279       width, height));
280   if (fullscreen_player_id_ == player_id)
281     video_view_->OnVideoSizeChanged(width, height);
282 }
283
284 media::MediaResourceGetter*
285 BrowserMediaPlayerManager::GetMediaResourceGetter() {
286   if (!media_resource_getter_.get()) {
287     RenderProcessHost* host = web_contents()->GetRenderProcessHost();
288     BrowserContext* context = host->GetBrowserContext();
289     StoragePartition* partition = host->GetStoragePartition();
290     storage::FileSystemContext* file_system_context =
291         partition ? partition->GetFileSystemContext() : NULL;
292     // Eventually this needs to be fixed to pass the correct frame rather
293     // than just using the main frame.
294     media_resource_getter_.reset(new MediaResourceGetterImpl(
295         context,
296         file_system_context,
297         host->GetID(),
298         web_contents()->GetMainFrame()->GetRoutingID()));
299   }
300   return media_resource_getter_.get();
301 }
302
303 media::MediaUrlInterceptor*
304 BrowserMediaPlayerManager::GetMediaUrlInterceptor() {
305   return media_url_interceptor_;
306 }
307
308 MediaPlayerAndroid* BrowserMediaPlayerManager::GetFullscreenPlayer() {
309   return GetPlayer(fullscreen_player_id_);
310 }
311
312 MediaPlayerAndroid* BrowserMediaPlayerManager::GetPlayer(int player_id) {
313   for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
314       it != players_.end(); ++it) {
315     if ((*it)->player_id() == player_id)
316       return *it;
317   }
318   return NULL;
319 }
320
321 void BrowserMediaPlayerManager::RequestFullScreen(int player_id) {
322   if (fullscreen_player_id_ == player_id)
323     return;
324
325   if (fullscreen_player_id_ != -1) {
326     // TODO(qinmin): Determine the correct error code we should report to WMPA.
327     OnError(player_id, MediaPlayerAndroid::MEDIA_ERROR_DECODE);
328     return;
329   }
330
331   Send(new MediaPlayerMsg_RequestFullscreen(RoutingID(), player_id));
332 }
333
334 #if defined(VIDEO_HOLE)
335 bool
336 BrowserMediaPlayerManager::ShouldUseVideoOverlayForEmbeddedEncryptedVideo() {
337   RendererPreferences* prefs = web_contents_->GetMutableRendererPrefs();
338   return prefs->use_video_overlay_for_embedded_encrypted_video;
339 }
340
341 void BrowserMediaPlayerManager::AttachExternalVideoSurface(int player_id,
342                                                            jobject surface) {
343   MediaPlayerAndroid* player = GetPlayer(player_id);
344   if (player) {
345     player->SetVideoSurface(
346         gfx::ScopedJavaSurface::AcquireExternalSurface(surface));
347   }
348 }
349
350 void BrowserMediaPlayerManager::DetachExternalVideoSurface(int player_id) {
351   MediaPlayerAndroid* player = GetPlayer(player_id);
352   if (player)
353     player->SetVideoSurface(gfx::ScopedJavaSurface());
354 }
355
356 void BrowserMediaPlayerManager::OnFrameInfoUpdated() {
357   if (external_video_surface_container_)
358     external_video_surface_container_->OnFrameInfoUpdated();
359 }
360
361 void BrowserMediaPlayerManager::OnNotifyExternalSurface(
362     int player_id, bool is_request, const gfx::RectF& rect) {
363   if (!web_contents_)
364     return;
365
366   if (is_request) {
367     OnRequestExternalSurface(player_id, rect);
368   }
369   if (external_video_surface_container_) {
370     external_video_surface_container_->OnExternalVideoSurfacePositionChanged(
371         player_id, rect);
372   }
373 }
374
375 void BrowserMediaPlayerManager::OnRequestExternalSurface(
376     int player_id, const gfx::RectF& rect) {
377   if (!external_video_surface_container_) {
378     ContentBrowserClient* client = GetContentClient()->browser();
379     external_video_surface_container_.reset(
380         client->OverrideCreateExternalVideoSurfaceContainer(web_contents_));
381   }
382   // It's safe to use base::Unretained(this), because the callbacks will not
383   // be called after running ReleaseExternalVideoSurface().
384   if (external_video_surface_container_) {
385     external_video_surface_container_->RequestExternalVideoSurface(
386         player_id,
387         base::Bind(&BrowserMediaPlayerManager::AttachExternalVideoSurface,
388                    base::Unretained(this)),
389         base::Bind(&BrowserMediaPlayerManager::DetachExternalVideoSurface,
390                    base::Unretained(this)));
391   }
392 }
393 #endif  // defined(VIDEO_HOLE)
394
395 void BrowserMediaPlayerManager::OnEnterFullscreen(int player_id) {
396   DCHECK_EQ(fullscreen_player_id_, -1);
397 #if defined(VIDEO_HOLE)
398   if (external_video_surface_container_)
399     external_video_surface_container_->ReleaseExternalVideoSurface(player_id);
400 #endif  // defined(VIDEO_HOLE)
401   if (video_view_.get()) {
402     fullscreen_player_id_ = player_id;
403     video_view_->OpenVideo();
404     return;
405   } else if (!ContentVideoView::GetInstance()) {
406     // In Android WebView, two ContentViewCores could both try to enter
407     // fullscreen video, we just ignore the second one.
408     video_view_.reset(new ContentVideoView(this));
409     base::android::ScopedJavaLocalRef<jobject> j_content_video_view =
410         video_view_->GetJavaObject(base::android::AttachCurrentThread());
411     if (!j_content_video_view.is_null()) {
412       fullscreen_player_id_ = player_id;
413       return;
414     }
415   }
416
417   // Force the second video to exit fullscreen.
418   // TODO(qinmin): There is no need to send DidEnterFullscreen message.
419   // However, if we don't send the message, page layers will not be
420   // correctly restored. http:crbug.com/367346.
421   Send(new MediaPlayerMsg_DidEnterFullscreen(RoutingID(), player_id));
422   Send(new MediaPlayerMsg_DidExitFullscreen(RoutingID(), player_id));
423   video_view_.reset();
424 }
425
426 void BrowserMediaPlayerManager::OnExitFullscreen(int player_id) {
427   if (fullscreen_player_id_ == player_id) {
428     MediaPlayerAndroid* player = GetPlayer(player_id);
429     if (player)
430       player->SetVideoSurface(gfx::ScopedJavaSurface());
431     video_view_->OnExitFullscreen();
432   }
433 }
434
435 void BrowserMediaPlayerManager::OnInitialize(
436     const MediaPlayerHostMsg_Initialize_Params& media_player_params) {
437   DCHECK(media_player_params.type != MEDIA_PLAYER_TYPE_MEDIA_SOURCE ||
438       media_player_params.demuxer_client_id > 0)
439       << "Media source players must have positive demuxer client IDs: "
440       << media_player_params.demuxer_client_id;
441
442   RemovePlayer(media_player_params.player_id);
443
444   RenderProcessHostImpl* host = static_cast<RenderProcessHostImpl*>(
445       web_contents()->GetRenderProcessHost());
446   MediaPlayerAndroid* player = CreateMediaPlayer(
447       media_player_params,
448
449       host->GetBrowserContext()->IsOffTheRecord(), this,
450       host->browser_demuxer_android());
451
452   if (!player)
453     return;
454
455   AddPlayer(player);
456 }
457
458 void BrowserMediaPlayerManager::OnStart(int player_id) {
459   MediaPlayerAndroid* player = GetPlayer(player_id);
460   if (!player)
461     return;
462   player->Start();
463   if (fullscreen_player_id_ == player_id && fullscreen_player_is_released_) {
464     video_view_->OpenVideo();
465     fullscreen_player_is_released_ = false;
466   }
467 }
468
469 void BrowserMediaPlayerManager::OnSeek(
470     int player_id,
471     const base::TimeDelta& time) {
472   MediaPlayerAndroid* player = GetPlayer(player_id);
473   if (player)
474     player->SeekTo(time);
475 }
476
477 void BrowserMediaPlayerManager::OnPause(
478     int player_id,
479     bool is_media_related_action) {
480   MediaPlayerAndroid* player = GetPlayer(player_id);
481   if (player)
482     player->Pause(is_media_related_action);
483 }
484
485 void BrowserMediaPlayerManager::OnSetVolume(int player_id, double volume) {
486   MediaPlayerAndroid* player = GetPlayer(player_id);
487   if (player)
488     player->SetVolume(volume);
489 }
490
491 void BrowserMediaPlayerManager::OnSetPoster(int player_id, const GURL& url) {
492   // To be overridden by subclasses.
493 }
494
495 void BrowserMediaPlayerManager::OnReleaseResources(int player_id) {
496   MediaPlayerAndroid* player = GetPlayer(player_id);
497   if (player)
498     ReleasePlayer(player);
499   if (player_id == fullscreen_player_id_)
500     fullscreen_player_is_released_ = true;
501 }
502
503 void BrowserMediaPlayerManager::OnDestroyPlayer(int player_id) {
504   RemovePlayer(player_id);
505   if (fullscreen_player_id_ == player_id)
506     fullscreen_player_id_ = -1;
507 }
508
509 void BrowserMediaPlayerManager::OnRequestRemotePlayback(int /* player_id */) {
510   // Does nothing if we don't have a remote player
511 }
512
513 void BrowserMediaPlayerManager::OnRequestRemotePlaybackControl(
514     int /* player_id */) {
515   // Does nothing if we don't have a remote player
516 }
517
518 void BrowserMediaPlayerManager::AddPlayer(MediaPlayerAndroid* player) {
519   DCHECK(!GetPlayer(player->player_id()));
520   players_.push_back(player);
521 }
522
523 void BrowserMediaPlayerManager::RemovePlayer(int player_id) {
524   for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
525       it != players_.end(); ++it) {
526     if ((*it)->player_id() == player_id) {
527       ReleaseMediaResources(player_id);
528       players_.erase(it);
529       break;
530     }
531   }
532 }
533
534 scoped_ptr<media::MediaPlayerAndroid> BrowserMediaPlayerManager::SwapPlayer(
535       int player_id, media::MediaPlayerAndroid* player) {
536   media::MediaPlayerAndroid* previous_player = NULL;
537   for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
538       it != players_.end(); ++it) {
539     if ((*it)->player_id() == player_id) {
540       previous_player = *it;
541       ReleaseMediaResources(player_id);
542       players_.weak_erase(it);
543       players_.push_back(player);
544       break;
545     }
546   }
547   return scoped_ptr<media::MediaPlayerAndroid>(previous_player);
548 }
549
550 int BrowserMediaPlayerManager::RoutingID() {
551   return render_frame_host_->GetRoutingID();
552 }
553
554 bool BrowserMediaPlayerManager::Send(IPC::Message* msg) {
555   return render_frame_host_->Send(msg);
556 }
557
558 void BrowserMediaPlayerManager::ReleaseFullscreenPlayer(
559     MediaPlayerAndroid* player) {
560   ReleasePlayer(player);
561 }
562
563 void BrowserMediaPlayerManager::OnMediaResourcesRequested(int player_id) {
564   int num_active_player = 0;
565   ScopedVector<MediaPlayerAndroid>::iterator it;
566   for (it = players_.begin(); it != players_.end(); ++it) {
567     if (!(*it)->IsPlayerReady())
568       continue;
569
570     // The player is already active, ignore it.
571     if ((*it)->player_id() == player_id)
572       return;
573     else
574       num_active_player++;
575   }
576
577   // Number of active players are less than the threshold, do nothing.
578   if (num_active_player < kMediaPlayerThreshold)
579     return;
580
581   for (it = players_.begin(); it != players_.end(); ++it) {
582     if ((*it)->IsPlayerReady() && !(*it)->IsPlaying() &&
583         fullscreen_player_id_ != (*it)->player_id()) {
584       ReleasePlayer(*it);
585       Send(new MediaPlayerMsg_MediaPlayerReleased(RoutingID(),
586                                                   (*it)->player_id()));
587     }
588   }
589 }
590
591 void BrowserMediaPlayerManager::ReleaseMediaResources(int player_id) {
592 #if defined(VIDEO_HOLE)
593   if (external_video_surface_container_)
594     external_video_surface_container_->ReleaseExternalVideoSurface(player_id);
595 #endif  // defined(VIDEO_HOLE)
596 }
597
598 void BrowserMediaPlayerManager::ReleasePlayer(MediaPlayerAndroid* player) {
599   player->Release();
600   ReleaseMediaResources(player->player_id());
601 }
602
603 }  // namespace content