diff options
4 files changed, 107 insertions, 90 deletions
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/database/SQLiteCursor.java b/chrome/android/java/src/org/chromium/chrome/browser/database/SQLiteCursor.java index 2297d90..8099e7e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/database/SQLiteCursor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/database/SQLiteCursor.java @@ -9,6 +9,8 @@ import android.database.AbstractCursor; import android.database.CursorWindow; import android.util.Log; +import org.chromium.base.CalledByNative; + import java.sql.Types; /** @@ -31,10 +33,15 @@ public class SQLiteCursor extends AbstractCursor { private final Object mMoveLock = new Object(); private final Object mGetBlobLock = new Object(); - SQLiteCursor(int nativeSQLiteCursor) { + private SQLiteCursor(int nativeSQLiteCursor) { mNativeSQLiteCursor = nativeSQLiteCursor; } + @CalledByNative + private static SQLiteCursor create(int nativeSQLiteCursor) { + return new SQLiteCursor(nativeSQLiteCursor); + } + @Override public int getCount() { synchronized (mMoveLock) { diff --git a/chrome/browser/history/android/sqlite_cursor.cc b/chrome/browser/history/android/sqlite_cursor.cc index 691ed95..f6c254b 100644 --- a/chrome/browser/history/android/sqlite_cursor.cc +++ b/chrome/browser/history/android/sqlite_cursor.cc @@ -5,6 +5,7 @@ #include "chrome/browser/history/android/sqlite_cursor.h" #include "base/android/jni_android.h" +#include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/bind.h" #include "base/logging.h" @@ -14,9 +15,6 @@ #include "sql/statement.h" using base::android::ConvertUTF8ToJavaString; -using base::android::GetClass; -using base::android::HasClass; -using base::android::MethodID; using base::android::ScopedJavaLocalRef; using content::BrowserThread; @@ -55,24 +53,9 @@ ScopedJavaLocalRef<jobject> SQLiteCursor::NewJavaSqliteCursor( history::AndroidStatement* statement, AndroidHistoryProviderService* service, FaviconService* favicon_service) { - if (!HasClass(env, kSQLiteCursorClassPath)) { - LOG(ERROR) << "Can not find " << kSQLiteCursorClassPath; - return ScopedJavaLocalRef<jobject>(); - } - - ScopedJavaLocalRef<jclass> sclass = GetClass(env, kSQLiteCursorClassPath); - jmethodID method_id = MethodID::Get<MethodID::TYPE_INSTANCE>( - env, sclass.obj(), "<init>", "(I)V"); - SQLiteCursor* cursor = new SQLiteCursor(column_names, statement, service, favicon_service); - ScopedJavaLocalRef<jobject> obj(env, - env->NewObject(sclass.obj(), method_id, reinterpret_cast<jint>(cursor))); - if (obj.is_null()) { - delete cursor; - return ScopedJavaLocalRef<jobject>(); - } - return obj; + return Java_SQLiteCursor_create(env, reinterpret_cast<jint>(cursor)); } bool SQLiteCursor::RegisterSqliteCursor(JNIEnv* env) { @@ -91,16 +74,7 @@ jint SQLiteCursor::GetCount(JNIEnv* env, jobject obj) { ScopedJavaLocalRef<jobjectArray> SQLiteCursor::GetColumnNames(JNIEnv* env, jobject obj) { - size_t count = column_names_.size(); - ScopedJavaLocalRef<jclass> sclass = GetClass(env, "java/lang/String"); - ScopedJavaLocalRef<jobjectArray> arr(env, - env->NewObjectArray(count, sclass.obj(), NULL)); - for (size_t i = 0; i < count; i++) { - ScopedJavaLocalRef<jstring> str = - ConvertUTF8ToJavaString(env, column_names_[i].c_str()); - env->SetObjectArrayElement(arr.obj(), i, str.obj()); - } - return arr; + return base::android::ToJavaArrayOfStrings(env, column_names_); } ScopedJavaLocalRef<jstring> SQLiteCursor::GetString(JNIEnv* env, @@ -135,13 +109,7 @@ ScopedJavaLocalRef<jbyteArray> SQLiteCursor::GetBlob(JNIEnv* env, } else { statement_->statement()->ColumnBlobAsVector(column, &blob); } - ScopedJavaLocalRef<jbyteArray> jb(env, env->NewByteArray(blob.size())); - int count = 0; - for (std::vector<unsigned char>::const_iterator i = blob.begin(); - i != blob.end(); ++i) { - env->SetByteArrayRegion(jb.obj(), count++, 1, (jbyte *)i); - } - return jb; + return base::android::ToJavaByteArray(env, &blob[0], blob.size()); } jboolean SQLiteCursor::IsNull(JNIEnv* env, jobject obj, jint column) { diff --git a/media/base/android/java/src/org/chromium/media/MediaPlayerBridge.java b/media/base/android/java/src/org/chromium/media/MediaPlayerBridge.java index 1bf80058..7274418 100644 --- a/media/base/android/java/src/org/chromium/media/MediaPlayerBridge.java +++ b/media/base/android/java/src/org/chromium/media/MediaPlayerBridge.java @@ -8,14 +8,43 @@ import android.content.Context; import android.media.MediaPlayer; import android.net.Uri; import android.text.TextUtils; +import android.util.Log; import org.chromium.base.CalledByNative; import org.chromium.base.JNINamespace; +import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.HashMap; @JNINamespace("media") class MediaPlayerBridge { + + private static final String TAG = "MediaPlayerBridge"; + + private static class AllowedOperations { + private final boolean mCanPause; + private final boolean mCanSeekForward; + private final boolean mCanSeekBackward; + + private AllowedOperations(boolean canPause, boolean canSeekForward, + boolean canSeekBackward) { + mCanPause = canPause; + mCanSeekForward = canSeekForward; + mCanSeekBackward = canSeekBackward; + } + + @CalledByNative("AllowedOperations") + private boolean canPause() { return mCanPause; } + + @CalledByNative("AllowedOperations") + private boolean canSeekForward() { return mCanSeekForward; } + + @CalledByNative("AllowedOperations") + private boolean canSeekBackward() { return mCanSeekBackward; } + } + @CalledByNative private static boolean setDataSource(MediaPlayer player, Context context, String url, String cookies, boolean hideUrlLog) { @@ -32,4 +61,49 @@ class MediaPlayerBridge { return false; } } + + /** + * Returns an AllowedOperations object to show all the operations that are + * allowed on the media player. + */ + @CalledByNative + private static AllowedOperations getAllowedOperations(MediaPlayer player) { + boolean canPause = true; + boolean canSeekForward = true; + boolean canSeekBackward = true; + try { + Method getMetadata = player.getClass().getDeclaredMethod( + "getMetadata", boolean.class, boolean.class); + getMetadata.setAccessible(true); + Object data = getMetadata.invoke(player, false, false); + if (data != null) { + Class<?> metadataClass = data.getClass(); + Method hasMethod = metadataClass.getDeclaredMethod("has", int.class); + Method getBooleanMethod = metadataClass.getDeclaredMethod("getBoolean", int.class); + + int pause = (Integer) metadataClass.getField("PAUSE_AVAILABLE").get(null); + int seekForward = + (Integer) metadataClass.getField("SEEK_FORWARD_AVAILABLE").get(null); + int seekBackward = + (Integer) metadataClass.getField("SEEK_BACKWARD_AVAILABLE").get(null); + hasMethod.setAccessible(true); + getBooleanMethod.setAccessible(true); + canPause = !((Boolean) hasMethod.invoke(data, pause)) + || ((Boolean) getBooleanMethod.invoke(data, pause)); + canSeekForward = !((Boolean) hasMethod.invoke(data, seekForward)) + || ((Boolean) getBooleanMethod.invoke(data, seekForward)); + canSeekBackward = !((Boolean) hasMethod.invoke(data, seekBackward)) + || ((Boolean) getBooleanMethod.invoke(data, seekBackward)); + } + } catch (NoSuchMethodException e) { + Log.e(TAG, "Cannot find getMetadata() method: " + e); + } catch (InvocationTargetException e) { + Log.e(TAG, "Cannot invoke MediaPlayer.getMetadata() method: " + e); + } catch (IllegalAccessException e) { + Log.e(TAG, "Cannot access metadata: " + e); + } catch (NoSuchFieldException e) { + Log.e(TAG, "Cannot find matching fields in Metadata class: " + e); + } + return new AllowedOperations(canPause, canSeekForward, canSeekBackward); + } } diff --git a/media/base/android/media_player_bridge.cc b/media/base/android/media_player_bridge.cc index 4ebde7d..7550fd6 100644 --- a/media/base/android/media_player_bridge.cc +++ b/media/base/android/media_player_bridge.cc @@ -15,20 +15,9 @@ #include "media/base/android/cookie_getter.h" #include "media/base/android/media_player_bridge_manager.h" -using base::android::AttachCurrentThread; -using base::android::CheckException; using base::android::ConvertUTF8ToJavaString; -using base::android::GetClass; -using base::android::JavaRef; -using base::android::MethodID; using base::android::ScopedJavaLocalRef; -// These constants are from the android source tree and need to be kept in -// sync with android/media/MediaMetadata.java. -static const jint kPauseAvailable = 1; -static const jint kSeekBackwardAvailable = 2; -static const jint kSeekForwardAvailable = 3; - // Time update happens every 250ms. static const int kTimeUpdateInterval = 250; @@ -90,7 +79,7 @@ MediaPlayerBridge::~MediaPlayerBridge() { } void MediaPlayerBridge::InitializePlayer() { - JNIEnv* env = AttachCurrentThread(); + JNIEnv* env = base::android::AttachCurrentThread(); CHECK(env); j_media_player_.Reset(JNI_MediaPlayer::Java_MediaPlayer_Constructor(env)); @@ -105,7 +94,7 @@ void MediaPlayerBridge::SetVideoSurface(jobject surface) { if (j_media_player_.is_null() && surface != NULL) Prepare(); - JNIEnv* env = AttachCurrentThread(); + JNIEnv* env = base::android::AttachCurrentThread(); CHECK(env); JNI_MediaPlayer::Java_MediaPlayer_setSurface( @@ -130,7 +119,7 @@ void MediaPlayerBridge::GetCookiesCallback(const std::string& cookies) { if (j_media_player_.is_null()) return; - JNIEnv* env = AttachCurrentThread(); + JNIEnv* env = base::android::AttachCurrentThread(); CHECK(env); // Create a Java String for the URL. @@ -180,7 +169,7 @@ bool MediaPlayerBridge::IsPlaying() { if (!prepared_) return pending_play_; - JNIEnv* env = AttachCurrentThread(); + JNIEnv* env = base::android::AttachCurrentThread(); CHECK(env); jboolean result = JNI_MediaPlayer::Java_MediaPlayer_isPlaying( env, j_media_player_.obj()); @@ -190,7 +179,7 @@ bool MediaPlayerBridge::IsPlaying() { int MediaPlayerBridge::GetVideoWidth() { if (!prepared_) return width_; - JNIEnv* env = AttachCurrentThread(); + JNIEnv* env = base::android::AttachCurrentThread(); return JNI_MediaPlayer::Java_MediaPlayer_getVideoWidth( env, j_media_player_.obj()); } @@ -198,7 +187,7 @@ int MediaPlayerBridge::GetVideoWidth() { int MediaPlayerBridge::GetVideoHeight() { if (!prepared_) return height_; - JNIEnv* env = AttachCurrentThread(); + JNIEnv* env = base::android::AttachCurrentThread(); return JNI_MediaPlayer::Java_MediaPlayer_getVideoHeight( env, j_media_player_.obj()); } @@ -216,7 +205,7 @@ void MediaPlayerBridge::SeekTo(base::TimeDelta time) { base::TimeDelta MediaPlayerBridge::GetCurrentTime() { if (!prepared_) return pending_seek_; - JNIEnv* env = AttachCurrentThread(); + JNIEnv* env = base::android::AttachCurrentThread(); return base::TimeDelta::FromMilliseconds( JNI_MediaPlayer::Java_MediaPlayer_getCurrentPosition( env, j_media_player_.obj())); @@ -225,7 +214,7 @@ base::TimeDelta MediaPlayerBridge::GetCurrentTime() { base::TimeDelta MediaPlayerBridge::GetDuration() { if (!prepared_) return duration_; - JNIEnv* env = AttachCurrentThread(); + JNIEnv* env = base::android::AttachCurrentThread(); return base::TimeDelta::FromMilliseconds( JNI_MediaPlayer::Java_MediaPlayer_getDuration( env, j_media_player_.obj())); @@ -244,7 +233,7 @@ void MediaPlayerBridge::Release() { pending_play_ = false; SetVideoSurface(NULL); - JNIEnv* env = AttachCurrentThread(); + JNIEnv* env = base::android::AttachCurrentThread(); JNI_MediaPlayer::Java_MediaPlayer_release(env, j_media_player_.obj()); j_media_player_.Reset(); @@ -255,7 +244,7 @@ void MediaPlayerBridge::SetVolume(float left_volume, float right_volume) { if (j_media_player_.is_null()) return; - JNIEnv* env = AttachCurrentThread(); + JNIEnv* env = base::android::AttachCurrentThread(); CHECK(env); JNI_MediaPlayer::Java_MediaPlayer_setVolume( env, j_media_player_.obj(), left_volume, right_volume); @@ -325,41 +314,20 @@ void MediaPlayerBridge::OnMediaPrepared() { } void MediaPlayerBridge::GetMetadata() { - JNIEnv* env = AttachCurrentThread(); + JNIEnv* env = base::android::AttachCurrentThread(); CHECK(env); - ScopedJavaLocalRef<jclass> media_player_class( - GetClass(env, "android/media/MediaPlayer")); - jmethodID method = MethodID::Get<MethodID::TYPE_INSTANCE>( - env, media_player_class.obj(), "getMetadata", - "(ZZ)Landroid/media/Metadata;"); - ScopedJavaLocalRef<jobject> j_metadata( - env, env->CallObjectMethod( - j_media_player_.obj(), method, JNI_FALSE, JNI_FALSE)); - CheckException(env); - if (j_metadata.is_null()) - return; - - ScopedJavaLocalRef<jclass> metadata_class( - GetClass(env, "android/media/Metadata")); - jmethodID get_boolean = MethodID::Get<MethodID::TYPE_INSTANCE>( - env, metadata_class.obj(), "getBoolean", "(I)Z"); - can_pause_ = env->CallBooleanMethod(j_metadata.obj(), - get_boolean, - kPauseAvailable); - CheckException(env); - can_seek_forward_ = env->CallBooleanMethod(j_metadata.obj(), - get_boolean, - kSeekBackwardAvailable); - CheckException(env); - can_seek_backward_ = env->CallBooleanMethod(j_metadata.obj(), - get_boolean, - kSeekForwardAvailable); - CheckException(env); + ScopedJavaLocalRef<jobject> allowedOperations = + Java_MediaPlayerBridge_getAllowedOperations(env, j_media_player_.obj()); + can_pause_ = Java_AllowedOperations_canPause(env, allowedOperations.obj()); + can_seek_forward_ = Java_AllowedOperations_canSeekForward( + env, allowedOperations.obj()); + can_seek_backward_ = Java_AllowedOperations_canSeekBackward( + env, allowedOperations.obj()); } void MediaPlayerBridge::StartInternal() { - JNIEnv* env = AttachCurrentThread(); + JNIEnv* env = base::android::AttachCurrentThread(); JNI_MediaPlayer::Java_MediaPlayer_start(env, j_media_player_.obj()); if (!time_update_timer_.IsRunning()) { time_update_timer_.Start( @@ -370,13 +338,13 @@ void MediaPlayerBridge::StartInternal() { } void MediaPlayerBridge::PauseInternal() { - JNIEnv* env = AttachCurrentThread(); + JNIEnv* env = base::android::AttachCurrentThread(); JNI_MediaPlayer::Java_MediaPlayer_pause(env, j_media_player_.obj()); time_update_timer_.Stop(); } void MediaPlayerBridge::SeekInternal(base::TimeDelta time) { - JNIEnv* env = AttachCurrentThread(); + JNIEnv* env = base::android::AttachCurrentThread(); CHECK(env); int time_msec = static_cast<int>(time.InMilliseconds()); |