Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / media / android / remote / remote_media_player_manager.cc
bloba5538aa225ad26cdc46c2264c5ece862a39fbc15
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.
5 #include "chrome/browser/media/android/remote/remote_media_player_manager.h"
7 #include "chrome/browser/android/tab_android.h"
8 #include "chrome/common/chrome_content_client.h"
9 #include "content/common/media/media_player_messages_android.h"
10 #include "third_party/skia/include/core/SkBitmap.h"
11 #include "ui/gfx/android/java_bitmap.h"
13 using media::MediaPlayerAndroid;
15 namespace remote_media {
17 RemoteMediaPlayerManager::RemoteMediaPlayerManager(
18 content::RenderFrameHost* render_frame_host)
19 : BrowserMediaPlayerManager(render_frame_host),
20 weak_ptr_factory_(this) {
23 RemoteMediaPlayerManager::~RemoteMediaPlayerManager() {}
25 void RemoteMediaPlayerManager::OnStart(int player_id) {
26 // TODO(aberent) This assumes this is the first time we have started this
27 // video, rather than restarting after pause. There is a lot of logic here
28 // that is unnecessary if we are restarting after pause.
29 if (MaybeStartPlayingRemotely(player_id))
30 return;
32 ReplaceRemotePlayerWithLocal();
33 BrowserMediaPlayerManager::OnStart(player_id);
36 void RemoteMediaPlayerManager::OnInitialize(
37 const MediaPlayerHostMsg_Initialize_Params& media_params) {
38 BrowserMediaPlayerManager::OnInitialize(media_params);
40 MediaPlayerAndroid* player = GetPlayer(media_params.player_id);
41 if (player) {
42 CreateRemoteMediaPlayer(player);
43 RemoteMediaPlayerBridge* remote_player = GetRemotePlayer(
44 media_params.player_id);
45 if (remote_player)
46 remote_player->OnPlayerCreated();
50 void RemoteMediaPlayerManager::OnDestroyPlayer(int player_id) {
51 RemoteMediaPlayerBridge* player = GetRemotePlayer(player_id);
52 if (player)
53 player->OnPlayerDestroyed();
54 BrowserMediaPlayerManager::OnDestroyPlayer(player_id);
57 void RemoteMediaPlayerManager::OnReleaseResources(int player_id) {
58 // We only want to release resources of local players.
59 if (player_id != RemotePlayerId())
60 BrowserMediaPlayerManager::OnReleaseResources(player_id);
63 void RemoteMediaPlayerManager::OnRequestRemotePlayback(int player_id) {
64 RemoteMediaPlayerBridge* player = GetRemotePlayer(player_id);
65 if (player)
66 player->RequestRemotePlayback();
69 void RemoteMediaPlayerManager::OnRequestRemotePlaybackControl(int player_id) {
70 RemoteMediaPlayerBridge* player = GetRemotePlayer(player_id);
71 if (player)
72 player->RequestRemotePlaybackControl();
75 int RemoteMediaPlayerManager::GetTabId() {
76 if (!web_contents())
77 return -1;
79 TabAndroid* tab = TabAndroid::FromWebContents(web_contents());
80 if (!tab)
81 return -1;
83 return tab->GetAndroidId();
86 void RemoteMediaPlayerManager::OnSetPoster(int player_id, const GURL& url) {
87 RemoteMediaPlayerBridge* player = GetRemotePlayer(player_id);
89 if (player && url.is_empty()) {
90 player->SetPosterBitmap(std::vector<SkBitmap>());
91 } else {
92 // TODO(aberent) OnSetPoster is called when the attributes of the video
93 // element are parsed, which may be before OnInitialize is called. We are
94 // here relying on the image fetch taking longer than the delay until
95 // OnInitialize is called, and hence the player is created. This is not
96 // guaranteed.
97 content::WebContents::ImageDownloadCallback callback = base::Bind(
98 &RemoteMediaPlayerManager::DidDownloadPoster,
99 weak_ptr_factory_.GetWeakPtr(), player_id);
100 web_contents()->DownloadImage(
101 url,
102 false, // is_favicon, false so that cookies will be used.
103 0, // max_bitmap_size, 0 means no limit.
104 false, // normal cache policy.
105 callback);
109 void RemoteMediaPlayerManager::DidDownloadPoster(
110 int player_id,
111 int id,
112 int http_status_code,
113 const GURL& image_url,
114 const std::vector<SkBitmap>& bitmaps,
115 const std::vector<gfx::Size>& original_bitmap_sizes) {
116 RemoteMediaPlayerBridge* player = GetRemotePlayer(player_id);
117 if (player)
118 player->SetPosterBitmap(bitmaps);
121 RemoteMediaPlayerBridge* RemoteMediaPlayerManager::CreateRemoteMediaPlayer(
122 MediaPlayerAndroid* local_player) {
123 RemoteMediaPlayerBridge* player = new RemoteMediaPlayerBridge(
124 local_player,
125 GetUserAgent(),
126 false,
127 this);
128 remote_players_.push_back(player);
129 player->Initialize();
130 return player;
133 int RemoteMediaPlayerManager::RemotePlayerId() {
134 // The remote player is created with the same id as the corresponding local
135 // player.
136 if (replaced_local_player_.get())
137 return replaced_local_player_->player_id();
138 else
139 return -1;
142 void RemoteMediaPlayerManager::ReplaceLocalPlayerWithRemote(
143 MediaPlayerAndroid* player) {
144 if (!player)
145 return;
147 int player_id = player->player_id();
148 if (player_id == RemotePlayerId()) {
149 // The player is already remote.
150 return;
153 // Before we replace the new remote player, put the old local player back
154 // in its place.
155 ReplaceRemotePlayerWithLocal();
157 // Pause the local player first before replacing it. This will allow the local
158 // player to reset its state, such as the PowerSaveBlocker.
159 // We have to pause locally as well as telling the renderer to pause, because
160 // by the time the renderer comes back to us telling us to pause we will have
161 // switched players.
162 player->Pause(true);
163 Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(), player_id));
165 // Find the remote player
166 for (auto it = remote_players_.begin(); it != remote_players_.end(); ++it) {
167 if ((*it)->player_id() == player_id) {
168 replaced_local_player_ = SwapPlayer(player_id, *it);
170 // Seek to the previous player's position.
171 (*it)->SeekTo(player->GetCurrentTime());
173 // SwapPlayers takes ownership, so we have to remove the remote player
174 // from the vector.
175 remote_players_.weak_erase(it);
176 break;
181 void RemoteMediaPlayerManager::ReplaceRemotePlayerWithLocal() {
182 int player_id = RemotePlayerId();
183 if (player_id == -1)
184 return;
186 Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(), player_id));
187 Send(new MediaPlayerMsg_DisconnectedFromRemoteDevice(RoutingID(), player_id));
189 scoped_ptr<MediaPlayerAndroid> remote_player =
190 SwapPlayer(player_id, replaced_local_player_.release());
191 if (remote_player) {
192 // Seek to the previous player's position.
193 GetPlayer(player_id)->SeekTo(remote_player->GetCurrentTime());
195 remote_player->Release();
196 // Add the remote player back into the list
197 remote_players_.push_back(
198 static_cast<RemoteMediaPlayerBridge *>(remote_player.release()));
202 bool RemoteMediaPlayerManager::MaybeStartPlayingRemotely(int player_id) {
203 MediaPlayerAndroid* player = GetPlayer(player_id);
204 if (!player)
205 return false;
207 RemoteMediaPlayerBridge* remote_player = GetRemotePlayer(player_id);
209 if (!remote_player)
210 return false;
212 if (remote_player->IsMediaPlayableRemotely() &&
213 remote_player->IsRemotePlaybackAvailable() &&
214 remote_player->IsRemotePlaybackPreferredForFrame()) {
215 ReplaceLocalPlayerWithRemote(player);
217 remote_player->SetNativePlayer();
218 remote_player->Start();
220 Send(new MediaPlayerMsg_DidMediaPlayerPlay(RoutingID(), player_id));
222 Send(new MediaPlayerMsg_ConnectedToRemoteDevice(
223 RoutingID(),
224 player_id,
225 remote_player->GetCastingMessage()));
227 return true;
230 return false;
233 void RemoteMediaPlayerManager::OnRemoteDeviceSelected(int player_id) {
235 MediaPlayerAndroid* player = GetPlayer(player_id);
236 if (!player)
237 return;
239 if (MaybeStartPlayingRemotely(player_id))
240 return;
241 OnStart(player_id);
244 void RemoteMediaPlayerManager::OnRemoteDeviceUnselected(int player_id) {
245 if (player_id == RemotePlayerId())
246 ReplaceRemotePlayerWithLocal();
249 void RemoteMediaPlayerManager::OnRemotePlaybackFinished(int player_id) {
250 if (player_id == RemotePlayerId())
251 ReplaceRemotePlayerWithLocal();
254 void RemoteMediaPlayerManager::OnRouteAvailabilityChanged(
255 int player_id, bool routes_available) {
256 Send(
257 new MediaPlayerMsg_RemoteRouteAvailabilityChanged(RoutingID(), player_id,
258 routes_available));
261 void RemoteMediaPlayerManager::ReleaseFullscreenPlayer(
262 MediaPlayerAndroid* player) {
263 // Release the original player's resources, not the current fullscreen player
264 // (which is the remote player).
265 if (replaced_local_player_.get())
266 replaced_local_player_->Release();
267 else
268 BrowserMediaPlayerManager::ReleaseFullscreenPlayer(player);
271 void RemoteMediaPlayerManager::OnPlaying(int player_id) {
272 Send(new MediaPlayerMsg_DidMediaPlayerPlay(RoutingID(),player_id));
275 void RemoteMediaPlayerManager::OnPaused(int player_id) {
276 Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(),player_id));
279 RemoteMediaPlayerBridge* RemoteMediaPlayerManager::GetRemotePlayer(
280 int player_id) {
281 if (player_id == RemotePlayerId()) {
282 return static_cast<RemoteMediaPlayerBridge*>(GetPlayer(player_id));
283 } else {
284 for (RemoteMediaPlayerBridge* player : remote_players_) {
285 if (player->player_id() == player_id) {
286 return player;
289 return nullptr;
293 void RemoteMediaPlayerManager::OnMediaMetadataChanged(int player_id,
294 base::TimeDelta duration,
295 int width,
296 int height,
297 bool success) {
298 if (player_id == RemotePlayerId() && replaced_local_player_) {
299 Send(new MediaPlayerMsg_MediaMetadataChanged(
300 RoutingID(), player_id, duration,
301 replaced_local_player_->GetVideoWidth(),
302 replaced_local_player_->GetVideoHeight(), success));
303 } else {
304 BrowserMediaPlayerManager::OnMediaMetadataChanged(player_id, duration,
305 width, height, success);
309 } // namespace remote_media