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 |