| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/media/android/media_web_contents_observer_android.h" | 5 #include "content/browser/media/android/media_web_contents_observer_android.h" |
| 6 | 6 |
| 7 #include "base/callback.h" |
| 7 #include "content/browser/media/android/browser_media_player_manager.h" | 8 #include "content/browser/media/android/browser_media_player_manager.h" |
| 8 #include "content/browser/media/android/browser_media_session_manager.h" | 9 #include "content/browser/media/android/browser_media_session_manager.h" |
| 9 #include "content/browser/media/android/media_session.h" | 10 #include "content/browser/media/android/media_session.h" |
| 10 #include "content/browser/media/android/media_session_observer.h" | 11 #include "content/browser/media/android/media_session_observer.h" |
| 11 #include "content/browser/media/cdm/browser_cdm_manager.h" | 12 #include "content/browser/media/cdm/browser_cdm_manager.h" |
| 12 #include "content/browser/web_contents/web_contents_impl.h" | 13 #include "content/browser/web_contents/web_contents_impl.h" |
| 14 #include "content/common/frame_messages.h" |
| 13 #include "content/common/media/media_player_messages_android.h" | 15 #include "content/common/media/media_player_messages_android.h" |
| 14 #include "content/common/media/media_session_messages_android.h" | 16 #include "content/common/media/media_session_messages_android.h" |
| 15 #include "content/public/browser/render_frame_host.h" | 17 #include "content/public/browser/render_frame_host.h" |
| 16 #include "content/public/browser/web_contents.h" | 18 #include "content/public/browser/web_contents.h" |
| 17 #include "ipc/ipc_message_macros.h" | 19 #include "ipc/ipc_message_macros.h" |
| 18 #include "media/base/android/media_player_android.h" | 20 #include "media/base/android/media_player_android.h" |
| 19 | 21 |
| 20 namespace content { | 22 namespace content { |
| 21 | 23 |
| 22 class MediaSessionController : public MediaSessionObserver { | 24 class MediaSessionController : public MediaSessionObserver { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 41 ? MediaSession::Type::Content | 43 ? MediaSession::Type::Content |
| 42 : MediaSession::Type::Transient; | 44 : MediaSession::Type::Transient; |
| 43 | 45 |
| 44 // If a session can't be created, force a pause immediately. | 46 // If a session can't be created, force a pause immediately. |
| 45 if (!MediaSession::Get(media_web_contents_observer_->web_contents()) | 47 if (!MediaSession::Get(media_web_contents_observer_->web_contents()) |
| 46 ->AddPlayer(this, player_id_, media_session_type)) { | 48 ->AddPlayer(this, player_id_, media_session_type)) { |
| 47 OnSuspend(player_id_); | 49 OnSuspend(player_id_); |
| 48 return false; | 50 return false; |
| 49 } | 51 } |
| 50 | 52 |
| 53 initialized_ = true; |
| 51 return true; | 54 return true; |
| 52 } | 55 } |
| 53 | 56 |
| 54 ~MediaSessionController() { | 57 ~MediaSessionController() { |
| 55 MediaSession::Get(media_web_contents_observer_->web_contents()) | 58 if (initialized_) { |
| 56 ->RemovePlayer(this, player_id_); | 59 MediaSession::Get(media_web_contents_observer_->web_contents()) |
| 60 ->RemovePlayer(this, player_id_); |
| 61 } |
| 57 } | 62 } |
| 58 | 63 |
| 59 void OnSuspend(int player_id) { | 64 void OnSuspend(int player_id) { |
| 60 DCHECK_EQ(player_id_, player_id); | 65 DCHECK_EQ(player_id_, player_id); |
| 61 media_web_contents_observer_->Send( | 66 media_web_contents_observer_->Send( |
| 62 new FrameMsg_MediaDelegatePause(id_.first->GetRoutingID(), id_.second)); | 67 new FrameMsg_MediaDelegatePause(id_.first->GetRoutingID(), id_.second)); |
| 63 } | 68 } |
| 64 | 69 |
| 65 void OnResume(int player_id) { | 70 void OnResume(int player_id) { |
| 66 DCHECK_EQ(player_id_, player_id); | 71 DCHECK_EQ(player_id_, player_id); |
| 67 media_web_contents_observer_->Send( | 72 media_web_contents_observer_->Send( |
| 68 new FrameMsg_MediaDelegatePlay(id_.first->GetRoutingID(), id_.second)); | 73 new FrameMsg_MediaDelegatePlay(id_.first->GetRoutingID(), id_.second)); |
| 69 } | 74 } |
| 70 | 75 |
| 71 void PausePlayback() { | 76 void PausePlayback() { |
| 72 MediaSession* session = | 77 MediaSession* session = |
| 73 MediaSession::Get(media_web_contents_observer_->web_contents()); | 78 MediaSession::Get(media_web_contents_observer_->web_contents()); |
| 74 // TODO(dalecurtis, mlamouri): This seems odd, if we don't check suspend of | 79 // TODO(dalecurtis, mlamouri): This seems odd, if we don't check suspend of |
| 75 // the entire session, notifying a pause will DCHECK in mediasession.cc:146. | 80 // the entire session, notifying a pause will DCHECK in mediasession.cc:146. |
| 76 if (!session->IsSuspended()) | 81 if (!session->IsSuspended()) |
| 77 session->OnPlayerPaused(this, player_id_); | 82 session->OnPlayerPaused(this, player_id_); |
| 78 } | 83 } |
| 79 | 84 |
| 80 private: | 85 private: |
| 81 const WebContentsObserver::MediaPlayerId id_; | 86 const WebContentsObserver::MediaPlayerId id_; |
| 82 MediaWebContentsObserver* const media_web_contents_observer_; | 87 MediaWebContentsObserver* const media_web_contents_observer_; |
| 83 int player_id_ = 0; | 88 int player_id_ = 0; |
| 84 bool initialize_failed_ = false; | 89 bool initialized_ = false; |
| 85 | 90 |
| 86 DISALLOW_COPY_AND_ASSIGN(MediaSessionController); | 91 DISALLOW_COPY_AND_ASSIGN(MediaSessionController); |
| 87 }; | 92 }; |
| 88 | 93 |
| 89 MediaWebContentsObserverAndroid::MediaWebContentsObserverAndroid( | 94 MediaWebContentsObserverAndroid::MediaWebContentsObserverAndroid( |
| 90 WebContents* web_contents) | 95 WebContents* web_contents) |
| 91 : MediaWebContentsObserver(web_contents) {} | 96 : MediaWebContentsObserver(web_contents) {} |
| 92 | 97 |
| 93 MediaWebContentsObserverAndroid::~MediaWebContentsObserverAndroid() { | 98 MediaWebContentsObserverAndroid::~MediaWebContentsObserverAndroid() {} |
| 94 // Clear active sessions before destructing the observer. | |
| 95 media_session_map_.clear(); | |
| 96 } | |
| 97 | 99 |
| 98 // static | 100 // static |
| 99 MediaWebContentsObserverAndroid* | 101 MediaWebContentsObserverAndroid* |
| 100 MediaWebContentsObserverAndroid::FromWebContents(WebContents* web_contents) { | 102 MediaWebContentsObserverAndroid::FromWebContents(WebContents* web_contents) { |
| 101 return static_cast<MediaWebContentsObserverAndroid*>( | 103 return static_cast<MediaWebContentsObserverAndroid*>( |
| 102 static_cast<WebContentsImpl*>(web_contents) | 104 static_cast<WebContentsImpl*>(web_contents) |
| 103 ->media_web_contents_observer()); | 105 ->media_web_contents_observer()); |
| 104 } | 106 } |
| 105 | 107 |
| 106 BrowserMediaPlayerManager* | 108 BrowserMediaPlayerManager* |
| (...skipping 15 matching lines...) Expand all Loading... |
| 122 auto it = media_session_managers_.find(render_frame_host); | 124 auto it = media_session_managers_.find(render_frame_host); |
| 123 if (it != media_session_managers_.end()) | 125 if (it != media_session_managers_.end()) |
| 124 return it->second; | 126 return it->second; |
| 125 | 127 |
| 126 BrowserMediaSessionManager* manager = | 128 BrowserMediaSessionManager* manager = |
| 127 new BrowserMediaSessionManager(render_frame_host); | 129 new BrowserMediaSessionManager(render_frame_host); |
| 128 media_session_managers_.set(render_frame_host, make_scoped_ptr(manager)); | 130 media_session_managers_.set(render_frame_host, make_scoped_ptr(manager)); |
| 129 return manager; | 131 return manager; |
| 130 } | 132 } |
| 131 | 133 |
| 134 // static |
| 135 void MediaWebContentsObserverAndroid::CheckFocus( |
| 136 int render_frame_id, |
| 137 const base::Closure& on_focus_cb) { |
| 138 for (const auto& kv : media_session_map_) { |
| 139 if (kv.first.first->GetRoutingID() == render_frame_id) { |
| 140 on_focus_cb.Run(); |
| 141 return; |
| 142 } |
| 143 } |
| 144 |
| 145 deferred_focus_cbs_[render_frame_id].push_back(on_focus_cb); |
| 146 } |
| 147 |
| 132 #if defined(VIDEO_HOLE) | 148 #if defined(VIDEO_HOLE) |
| 133 void MediaWebContentsObserverAndroid::OnFrameInfoUpdated() { | 149 void MediaWebContentsObserverAndroid::OnFrameInfoUpdated() { |
| 134 for (auto it = media_player_managers_.begin(); | 150 for (auto it = media_player_managers_.begin(); |
| 135 it != media_player_managers_.end(); ++it) { | 151 it != media_player_managers_.end(); ++it) { |
| 136 it->second->OnFrameInfoUpdated(); | 152 it->second->OnFrameInfoUpdated(); |
| 137 } | 153 } |
| 138 } | 154 } |
| 139 #endif // defined(VIDEO_HOLE) | 155 #endif // defined(VIDEO_HOLE) |
| 140 | 156 |
| 141 void MediaWebContentsObserverAndroid::RenderFrameDeleted( | 157 void MediaWebContentsObserverAndroid::RenderFrameDeleted( |
| 142 RenderFrameHost* render_frame_host) { | 158 RenderFrameHost* render_frame_host) { |
| 143 MediaWebContentsObserver::RenderFrameDeleted(render_frame_host); | 159 MediaWebContentsObserver::RenderFrameDeleted(render_frame_host); |
| 144 | 160 |
| 161 for (auto it = media_session_map_.begin(); it != media_session_map_.end();) { |
| 162 if (it->first.first == render_frame_host) |
| 163 it = media_session_map_.erase(it); |
| 164 else |
| 165 ++it; |
| 166 } |
| 167 |
| 145 // Always destroy the media players before CDMs because we do not support | 168 // Always destroy the media players before CDMs because we do not support |
| 146 // detaching CDMs from media players yet. See http://crbug.com/330324 | 169 // detaching CDMs from media players yet. See http://crbug.com/330324 |
| 147 media_player_managers_.erase(render_frame_host); | 170 media_player_managers_.erase(render_frame_host); |
| 148 media_session_managers_.erase(render_frame_host); | 171 media_session_managers_.erase(render_frame_host); |
| 149 | 172 |
| 150 // TODO(xhwang): Currently MediaWebContentsObserver, BrowserMediaPlayerManager | 173 // TODO(xhwang): Currently MediaWebContentsObserver, BrowserMediaPlayerManager |
| 151 // and BrowserCdmManager all run on browser UI thread. So this call is okay. | 174 // and BrowserCdmManager all run on browser UI thread. So this call is okay. |
| 152 // In the future we need to support the case where MediaWebContentsObserver | 175 // In the future we need to support the ~case where MediaWebContentsObserver |
| 153 // get notified on browser UI thread, but BrowserMediaPlayerManager and | 176 // get notified on browser UI thread, but BrowserMediaPlayerManager and |
| 154 // BrowserCdmManager run on a different thread. | 177 // BrowserCdmManager run on a different thread. |
| 155 BrowserCdmManager* browser_cdm_manager = | 178 BrowserCdmManager* browser_cdm_manager = |
| 156 BrowserCdmManager::FromProcess(render_frame_host->GetProcess()->GetID()); | 179 BrowserCdmManager::FromProcess(render_frame_host->GetProcess()->GetID()); |
| 157 if (browser_cdm_manager) | 180 if (browser_cdm_manager) |
| 158 browser_cdm_manager->RenderFrameDeleted(render_frame_host->GetRoutingID()); | 181 browser_cdm_manager->RenderFrameDeleted(render_frame_host->GetRoutingID()); |
| 159 } | 182 } |
| 160 | 183 |
| 161 bool MediaWebContentsObserverAndroid::OnMessageReceived( | 184 bool MediaWebContentsObserverAndroid::OnMessageReceived( |
| 162 const IPC::Message& msg, | 185 const IPC::Message& msg, |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 | 307 |
| 285 // TODO(xhwang): This could possibly fail. In that case we should reject the | 308 // TODO(xhwang): This could possibly fail. In that case we should reject the |
| 286 // promise. | 309 // promise. |
| 287 media_player->SetCdm(cdm); | 310 media_player->SetCdm(cdm); |
| 288 } | 311 } |
| 289 | 312 |
| 290 void MediaWebContentsObserverAndroid::OnMediaDestroyedNotification( | 313 void MediaWebContentsObserverAndroid::OnMediaDestroyedNotification( |
| 291 RenderFrameHost* render_frame_host, | 314 RenderFrameHost* render_frame_host, |
| 292 int64_t player_cookie) { | 315 int64_t player_cookie) { |
| 293 media_session_map_.erase(MediaPlayerId(render_frame_host, player_cookie)); | 316 media_session_map_.erase(MediaPlayerId(render_frame_host, player_cookie)); |
| 317 deferred_focus_cbs_.erase(render_frame_host->GetRoutingID()); |
| 294 } | 318 } |
| 295 | 319 |
| 296 void MediaWebContentsObserverAndroid::OnMediaPlayingNotification( | 320 void MediaWebContentsObserverAndroid::OnMediaPlayingNotification( |
| 297 RenderFrameHost* render_frame_host, | 321 RenderFrameHost* render_frame_host, |
| 298 int64_t player_cookie, | 322 int64_t player_cookie, |
| 299 bool has_video, | 323 bool has_video, |
| 300 bool has_audio, | 324 bool has_audio, |
| 301 bool is_remote, | 325 bool is_remote, |
| 302 base::TimeDelta duration) { | 326 base::TimeDelta duration) { |
| 303 // Don't setup a media session for remote playback instances. | 327 // Don't setup a media session for remote playback instances. |
| 304 if (is_remote) | 328 if (is_remote) |
| 305 return; | 329 return; |
| 306 | 330 |
| 307 const MediaPlayerId id(render_frame_host, player_cookie); | 331 const MediaPlayerId id(render_frame_host, player_cookie); |
| 308 scoped_ptr<MediaSessionController> controller( | 332 scoped_ptr<MediaSessionController> controller( |
| 309 new MediaSessionController(id, this)); | 333 new MediaSessionController(id, this)); |
| 310 | 334 |
| 311 // If initialize fails, the controller should be destroyed and a new one | 335 // If initialize fails, the controller should be destroyed and a new one |
| 312 // attempted later after another playback attempt occurs. | 336 // attempted later after another playback attempt occurs. |
| 313 if (!controller->Initialize(has_video, has_audio, duration)) | 337 if (!controller->Initialize(has_video, has_audio, duration)) |
| 314 return; | 338 return; |
| 315 | 339 |
| 316 media_session_map_[id] = std::move(controller); | 340 media_session_map_[id] = std::move(controller); |
| 341 |
| 342 // Notify any deferred focus callbacks. |
| 343 auto it = deferred_focus_cbs_.find(render_frame_host->GetRoutingID()); |
| 344 if (it != deferred_focus_cbs_.end()) { |
| 345 for (const auto& cb : it->second) |
| 346 cb.Run(); |
| 347 deferred_focus_cbs_.erase(it); |
| 348 } |
| 317 } | 349 } |
| 318 | 350 |
| 319 void MediaWebContentsObserverAndroid::OnMediaPausedNotification( | 351 void MediaWebContentsObserverAndroid::OnMediaPausedNotification( |
| 320 RenderFrameHost* render_frame_host, | 352 RenderFrameHost* render_frame_host, |
| 321 int64_t player_cookie, | 353 int64_t player_cookie, |
| 322 bool reached_end_of_stream) { | 354 bool reached_end_of_stream) { |
| 323 // Drop the session if playback completes normally. | 355 // Drop the session if playback completes normally. |
| 324 if (reached_end_of_stream) { | 356 if (reached_end_of_stream) { |
| 325 OnMediaDestroyedNotification(render_frame_host, player_cookie); | 357 OnMediaDestroyedNotification(render_frame_host, player_cookie); |
| 326 return; | 358 return; |
| 327 } | 359 } |
| 328 | 360 |
| 329 auto it = | 361 auto it = |
| 330 media_session_map_.find(MediaPlayerId(render_frame_host, player_cookie)); | 362 media_session_map_.find(MediaPlayerId(render_frame_host, player_cookie)); |
| 331 if (it == media_session_map_.end()) | 363 if (it == media_session_map_.end()) |
| 332 return; | 364 return; |
| 333 | 365 |
| 334 it->second->PausePlayback(); | 366 it->second->PausePlayback(); |
| 335 } | 367 } |
| 336 | 368 |
| 337 } // namespace content | 369 } // namespace content |
| OLD | NEW |