Refactor WebsiteSettings to operate on a SecurityInfo
[chromium-blink-merge.git] / chrome / browser / media / android / remote / remote_media_player_bridge.cc
blob3f9781e07f487d66c3e75975030d8b63c7544a00
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_bridge.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h"
9 #include "chrome/browser/media/android/remote/record_cast_action.h"
10 #include "chrome/browser/media/android/remote/remote_media_player_manager.h"
11 #include "content/public/browser/android/content_view_core.h"
12 #include "content/public/browser/web_contents.h"
13 #include "jni/RemoteMediaPlayerBridge_jni.h"
14 #include "media/base/android/media_common_android.h"
15 #include "media/base/android/media_resource_getter.h"
16 #include "media/base/timestamp_constants.h"
17 #include "third_party/skia/include/core/SkBitmap.h"
18 #include "ui/gfx/android/java_bitmap.h"
20 using base::android::ConvertUTF8ToJavaString;
21 using base::android::ScopedJavaLocalRef;
22 using base::android::AttachCurrentThread;
24 namespace {
26 * Dummy function for RequestMediaResources callback. The callback is never
27 * actually called by MediaPlayerAndroid or RemoteMediaPlayer but is needed
28 * to compile the constructor call.
30 void DoNothing(int /*i*/) {}
33 namespace remote_media {
35 RemoteMediaPlayerBridge::RemoteMediaPlayerBridge(
36 MediaPlayerAndroid* local_player, const std::string& user_agent,
37 bool hide_url_log, RemoteMediaPlayerManager* manager)
38 : MediaPlayerAndroid(local_player->player_id(), manager,
39 base::Bind(&DoNothing),
40 local_player->frame_url()),
41 start_position_millis_(0),
42 local_player_(local_player),
43 in_use_(false),
44 prepared_(false),
45 pending_play_(false),
46 width_(0),
47 height_(0),
48 should_seek_on_prepare_(false),
49 hide_url_log_(hide_url_log),
50 volume_(-1.0),
51 url_(local_player->GetUrl()),
52 first_party_for_cookies_(local_player->GetFirstPartyForCookies()),
53 user_agent_(user_agent),
54 weak_factory_(this) {
55 if (local_player->GetCurrentTime().InMilliseconds() > 0)
56 start_position_millis_ = local_player->GetCurrentTime().InMilliseconds();
57 JNIEnv* env = base::android::AttachCurrentThread();
58 CHECK(env);
59 ScopedJavaLocalRef<jstring> j_url_string;
60 if (url_.is_valid()) {
61 // Create a Java String for the URL.
62 j_url_string = ConvertUTF8ToJavaString(env, url_.spec());
64 ScopedJavaLocalRef<jstring> j_frame_url_string;
65 if (local_player->frame_url().is_valid()) {
66 // Create a Java String for the URL.
67 j_frame_url_string = ConvertUTF8ToJavaString(
68 env, local_player->frame_url().spec());
70 java_bridge_.Reset(
71 Java_RemoteMediaPlayerBridge_create(env, reinterpret_cast<intptr_t>(this),
72 start_position_millis_,
73 j_url_string.obj(),
74 j_frame_url_string.obj()));
77 RemoteMediaPlayerBridge::~RemoteMediaPlayerBridge() {
78 JNIEnv* env = base::android::AttachCurrentThread();
79 CHECK(env);
80 Java_RemoteMediaPlayerBridge_destroy(env, java_bridge_.obj());
81 Release();
84 int RemoteMediaPlayerBridge::GetVideoWidth() {
85 return local_player_->GetVideoWidth();
88 int RemoteMediaPlayerBridge::GetVideoHeight() {
89 return local_player_->GetVideoHeight();
92 void RemoteMediaPlayerBridge::OnVideoSizeChanged(int width, int height) {
93 width_ = width;
94 height_ = height;
95 MediaPlayerAndroid::OnVideoSizeChanged(width, height);
98 void RemoteMediaPlayerBridge::OnPlaybackComplete() {
99 time_update_timer_.Stop();
100 MediaPlayerAndroid::OnPlaybackComplete();
103 void RemoteMediaPlayerBridge::OnMediaInterrupted() {}
105 void RemoteMediaPlayerBridge::OnMediaPrepared() {
106 if (!in_use_)
107 return;
109 prepared_ = true;
110 duration_ = GetDuration();
112 // If media player was recovered from a saved state, consume all the pending
113 // events.
114 if (should_seek_on_prepare_) {
115 PendingSeekInternal(pending_seek_);
116 pending_seek_ = base::TimeDelta::FromMilliseconds(0);
117 should_seek_on_prepare_ = false;
120 if (pending_play_) {
121 StartInternal();
122 pending_play_ = false;
125 manager()->OnMediaMetadataChanged(
126 player_id(), duration_, width_, height_, true);
129 void RemoteMediaPlayerBridge::StartInternal() {
130 JNIEnv* env = AttachCurrentThread();
131 Java_RemoteMediaPlayerBridge_start(env, java_bridge_.obj());
132 if (!time_update_timer_.IsRunning()) {
133 time_update_timer_.Start(
134 FROM_HERE,
135 base::TimeDelta::FromMilliseconds(media::kTimeUpdateInterval),
136 this, &RemoteMediaPlayerBridge::OnTimeUpdateTimerFired);
140 void RemoteMediaPlayerBridge::PauseInternal() {
141 JNIEnv* env = AttachCurrentThread();
142 Java_RemoteMediaPlayerBridge_pause(env, java_bridge_.obj());
143 time_update_timer_.Stop();
146 void RemoteMediaPlayerBridge::SeekInternal(base::TimeDelta time) {
147 if (time > duration_)
148 time = duration_;
150 // Seeking to an invalid position may cause media player to stuck in an
151 // error state.
152 if (time < base::TimeDelta()) {
153 DCHECK_EQ(-1.0, time.InMillisecondsF());
154 return;
157 JNIEnv* env = AttachCurrentThread();
158 CHECK(env);
159 int time_msec = static_cast<int>(time.InMilliseconds());
160 Java_RemoteMediaPlayerBridge_seekTo(
161 env, java_bridge_.obj(), time_msec);
164 void RemoteMediaPlayerBridge::OnTimeUpdateTimerFired() {
165 manager()->OnTimeUpdate(
166 player_id(), GetCurrentTime(), base::TimeTicks::Now());
169 void RemoteMediaPlayerBridge::PendingSeekInternal(const base::TimeDelta& time) {
170 SeekInternal(time);
173 void RemoteMediaPlayerBridge::Prepare() {
174 DCHECK(!in_use_);
175 DCHECK(IsMediaPlayableRemotely());
176 in_use_ = true;
177 AttachListener(java_bridge_.obj());
178 JNIEnv* env = AttachCurrentThread();
179 CHECK(env);
181 if (url_.is_valid()) {
182 // Create a Java String for the URL.
183 ScopedJavaLocalRef<jstring> j_url_string =
184 ConvertUTF8ToJavaString(env, url_.spec());
186 jobject j_context = base::android::GetApplicationContext();
187 DCHECK(j_context);
189 ScopedJavaLocalRef<jstring> j_cookies = ConvertUTF8ToJavaString(
190 env, cookies_);
191 ScopedJavaLocalRef<jstring> j_user_agent = ConvertUTF8ToJavaString(
192 env, user_agent_);
194 if (!Java_RemoteMediaPlayerBridge_setDataSource(
195 env, java_bridge_.obj(), j_context, j_url_string.obj(),
196 j_cookies.obj(), j_user_agent.obj(), hide_url_log_)) {
197 OnMediaError(MEDIA_ERROR_FORMAT);
198 return;
202 if (!Java_RemoteMediaPlayerBridge_prepareAsync(env, java_bridge_.obj()))
203 OnMediaError(MEDIA_ERROR_FORMAT);
206 void RemoteMediaPlayerBridge::Pause(bool is_media_related_action) {
207 // Ignore the pause if it's not from an event that is explicitly telling
208 // the video to pause. It's possible for Pause() to be called for other
209 // reasons, such as freeing resources, etc. and during those times, the
210 // remote video playback should not be paused.
211 if (is_media_related_action) {
212 if (!in_use_) {
213 pending_play_ = false;
214 } else {
215 if (prepared_ && IsPlaying())
216 PauseInternal();
217 else
218 pending_play_ = false;
223 void RemoteMediaPlayerBridge::SetVideoSurface(gfx::ScopedJavaSurface surface) {
224 // The surface is reset whenever the fullscreen view is destroyed or created.
225 // Since the remote player doesn't use it, we forward it to the local player
226 // for the time when user disconnects and resumes local playback
227 // (see crbug.com/420690).
228 local_player_->SetVideoSurface(surface.Pass());
231 base::android::ScopedJavaLocalRef<jstring> RemoteMediaPlayerBridge::GetFrameUrl(
232 JNIEnv* env, jobject obj) {
233 return ConvertUTF8ToJavaString(env, frame_url().spec());
236 void RemoteMediaPlayerBridge::OnPlaying(JNIEnv* env, jobject obj) {
237 static_cast<RemoteMediaPlayerManager *>(manager())->OnPlaying(player_id());
240 void RemoteMediaPlayerBridge::OnPaused(JNIEnv* env, jobject obj) {
241 static_cast<RemoteMediaPlayerManager *>(manager())->OnPaused(player_id());
244 void RemoteMediaPlayerBridge::OnRouteSelected(JNIEnv* env, jobject obj,
245 jstring castingMessage) {
246 casting_message_.reset(
247 new std::string(
248 base::android::ConvertJavaStringToUTF8(env, castingMessage)));
249 static_cast<RemoteMediaPlayerManager *>(manager())->OnRemoteDeviceSelected(
250 player_id());
253 void RemoteMediaPlayerBridge::OnRouteUnselected(JNIEnv* env, jobject obj) {
254 casting_message_.reset();
255 static_cast<RemoteMediaPlayerManager *>(manager())->OnRemoteDeviceUnselected(
256 player_id());
259 void RemoteMediaPlayerBridge::OnPlaybackFinished(JNIEnv* env, jobject obj) {
260 static_cast<RemoteMediaPlayerManager *>(manager())->OnRemotePlaybackFinished(
261 player_id());
264 void RemoteMediaPlayerBridge::OnRouteAvailabilityChanged(JNIEnv* env,
265 jobject obj,
266 jboolean available) {
267 static_cast<RemoteMediaPlayerManager *>(manager())->
268 OnRouteAvailabilityChanged(player_id(), available);
271 // static
272 bool RemoteMediaPlayerBridge::RegisterRemoteMediaPlayerBridge(JNIEnv* env) {
273 bool ret = RegisterNativesImpl(env);
274 DCHECK(g_RemoteMediaPlayerBridge_clazz);
275 return ret;
278 void RemoteMediaPlayerBridge::RequestRemotePlayback() {
279 JNIEnv* env = AttachCurrentThread();
280 CHECK(env);
282 Java_RemoteMediaPlayerBridge_requestRemotePlayback(
283 env, java_bridge_.obj());
286 void RemoteMediaPlayerBridge::RequestRemotePlaybackControl() {
287 JNIEnv* env = AttachCurrentThread();
288 CHECK(env);
290 Java_RemoteMediaPlayerBridge_requestRemotePlaybackControl(
291 env, java_bridge_.obj());
294 void RemoteMediaPlayerBridge::SetNativePlayer() {
295 JNIEnv* env = AttachCurrentThread();
296 CHECK(env);
298 Java_RemoteMediaPlayerBridge_setNativePlayer(
299 env, java_bridge_.obj());
302 void RemoteMediaPlayerBridge::OnPlayerCreated() {
303 JNIEnv* env = AttachCurrentThread();
304 CHECK(env);
306 Java_RemoteMediaPlayerBridge_onPlayerCreated(
307 env, java_bridge_.obj());
310 void RemoteMediaPlayerBridge::OnPlayerDestroyed() {
311 JNIEnv* env = AttachCurrentThread();
312 CHECK(env);
314 Java_RemoteMediaPlayerBridge_onPlayerDestroyed(
315 env, java_bridge_.obj());
318 bool RemoteMediaPlayerBridge::IsRemotePlaybackAvailable() const {
319 JNIEnv* env = AttachCurrentThread();
320 CHECK(env);
322 jboolean result = Java_RemoteMediaPlayerBridge_isRemotePlaybackAvailable(
323 env, java_bridge_.obj());
325 return result;
328 bool RemoteMediaPlayerBridge::IsRemotePlaybackPreferredForFrame() const {
329 if (in_use_) {
330 // We have already decided to use remote playback
331 return true;
333 JNIEnv* env = AttachCurrentThread();
334 CHECK(env);
336 jboolean result =
337 Java_RemoteMediaPlayerBridge_isRemotePlaybackPreferredForFrame(
338 env, java_bridge_.obj());
339 return result;
342 std::string RemoteMediaPlayerBridge::GetCastingMessage() {
343 return casting_message_ ?
344 *casting_message_ : std::string();
347 void RemoteMediaPlayerBridge::SetPosterBitmap(
348 const std::vector<SkBitmap>& bitmaps) {
349 JNIEnv* env = AttachCurrentThread();
350 CHECK(env);
352 if (bitmaps.empty()) {
353 Java_RemoteMediaPlayerBridge_setPosterBitmap(env, java_bridge_.obj(), NULL);
354 } else {
355 ScopedJavaLocalRef<jobject> j_poster_bitmap;
356 j_poster_bitmap = gfx::ConvertToJavaBitmap(&(bitmaps[0]));
358 Java_RemoteMediaPlayerBridge_setPosterBitmap(env, java_bridge_.obj(),
359 j_poster_bitmap.obj());
363 void RemoteMediaPlayerBridge::Start() {
364 if (!in_use_) {
365 pending_play_ = true;
366 Prepare();
367 } else {
368 if (prepared_)
369 StartInternal();
370 else
371 pending_play_ = true;
375 void RemoteMediaPlayerBridge::SeekTo(base::TimeDelta timestamp) {
376 // Record the time to seek when OnMediaPrepared() is called.
377 pending_seek_ = timestamp;
378 should_seek_on_prepare_ = true;
380 if (!in_use_)
381 Prepare();
382 else if (prepared_)
383 SeekInternal(timestamp);
386 void RemoteMediaPlayerBridge::Release() {
387 if (!in_use_)
388 return;
389 time_update_timer_.Stop();
390 if (prepared_) {
391 pending_seek_ = GetCurrentTime();
392 should_seek_on_prepare_ = true;
395 prepared_ = false;
396 pending_play_ = false;
397 JNIEnv* env = AttachCurrentThread();
398 Java_RemoteMediaPlayerBridge_release(env, java_bridge_.obj());
399 DetachListener();
400 in_use_ = false;
403 void RemoteMediaPlayerBridge::SetVolume(double volume) {
404 if (!in_use_) {
405 volume_ = volume;
406 return;
409 JNIEnv* env = AttachCurrentThread();
410 CHECK(env);
411 Java_RemoteMediaPlayerBridge_setVolume(
412 env, java_bridge_.obj(), volume);
415 base::TimeDelta RemoteMediaPlayerBridge::GetCurrentTime() {
416 if (!prepared_)
417 return pending_seek_;
418 JNIEnv* env = AttachCurrentThread();
419 return base::TimeDelta::FromMilliseconds(
420 Java_RemoteMediaPlayerBridge_getCurrentPosition(
421 env, java_bridge_.obj()));
424 base::TimeDelta RemoteMediaPlayerBridge::GetDuration() {
425 if (!prepared_)
426 return duration_;
427 JNIEnv* env = AttachCurrentThread();
428 const int duration_ms =
429 Java_RemoteMediaPlayerBridge_getDuration(env, java_bridge_.obj());
430 // Sometimes we can't get the duration remotely, but the local media player
431 // knows it.
432 // TODO (aberent) This is for YouTube. Remove it when the YouTube receiver is
433 // fixed.
434 if (duration_ms == 0) {
435 return local_player_->GetDuration();
437 return duration_ms < 0 ? media::kInfiniteDuration()
438 : base::TimeDelta::FromMilliseconds(duration_ms);
441 bool RemoteMediaPlayerBridge::IsPlaying() {
442 if (!prepared_)
443 return pending_play_;
445 JNIEnv* env = AttachCurrentThread();
446 CHECK(env);
447 jboolean result = Java_RemoteMediaPlayerBridge_isPlaying(
448 env, java_bridge_.obj());
449 return result;
452 bool RemoteMediaPlayerBridge::CanPause() {
453 return true;
456 bool RemoteMediaPlayerBridge::CanSeekForward() {
457 return true;
460 bool RemoteMediaPlayerBridge::CanSeekBackward() {
461 return true;
464 bool RemoteMediaPlayerBridge::IsPlayerReady() {
465 return prepared_;
468 GURL RemoteMediaPlayerBridge::GetUrl() {
469 return url_;
472 GURL RemoteMediaPlayerBridge::GetFirstPartyForCookies() {
473 return first_party_for_cookies_;
476 void RemoteMediaPlayerBridge::Initialize() {
477 cookies_.clear();
478 media::MediaResourceGetter* resource_getter =
479 manager()->GetMediaResourceGetter();
480 resource_getter->GetCookies(
481 url_, first_party_for_cookies_,
482 base::Bind(&RemoteMediaPlayerBridge::OnCookiesRetrieved,
483 weak_factory_.GetWeakPtr()));
486 bool RemoteMediaPlayerBridge::IsMediaPlayableRemotely() const {
487 JNIEnv* env = AttachCurrentThread();
488 CHECK(env);
490 return Java_RemoteMediaPlayerBridge_isMediaPlayableRemotely(
491 env, java_bridge_.obj());
494 base::android::ScopedJavaLocalRef<jstring> RemoteMediaPlayerBridge::GetTitle(
495 JNIEnv* env, jobject obj) {
496 base::string16 title;
497 content::ContentViewCore* core =
498 static_cast<RemoteMediaPlayerManager*>(manager())->GetContentViewCore();
499 if (core) {
500 content::WebContents* contents = core->GetWebContents();
501 if (contents) {
502 title = contents->GetTitle();
505 return base::android::ConvertUTF16ToJavaString(env, title);
508 void RemoteMediaPlayerBridge::OnCookiesRetrieved(const std::string& cookies) {
509 // TODO(aberent) Do we need to retrieve auth credentials for basic
510 // authentication? MediaPlayerBridge does.
511 cookies_ = cookies;
514 } // namespace remote_media