Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(208)

Side by Side Diff: content/browser/media/android/media_web_contents_observer_android.cc

Issue 1580493004: Plumb audio focus support for spitzer clients. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@delegate_hookup
Patch Set: Fix crash, plumb. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698