Bug 748531 - Guard against exceptions in JNI. r=blassey

This commit is contained in:
Kartikaya Gupta 2012-05-04 11:08:47 -04:00
parent 60a1f57e8b
commit 06aee064be
6 changed files with 407 additions and 209 deletions

View File

@ -143,7 +143,7 @@ AudioRunnable::Run()
if (!jenv)
return NS_ERROR_FAILURE;
mozilla::AndroidBridge::AutoLocalJNIFrame autoFrame(jenv);
mozilla::AutoLocalJNIFrame autoFrame(jenv);
jbyteArray bytearray = jenv->NewByteArray(mTrack->bufferSize);
if (!bytearray) {

View File

@ -104,7 +104,7 @@ AndroidBridge::Init(JNIEnv *jEnv,
ALOG_BRIDGE("AndroidBridge::Init");
jEnv->GetJavaVM(&mJavaVM);
AutoLocalJNIFrame frame(jEnv);
AutoLocalJNIFrame jniFrame(jEnv);
mJNIEnv = nsnull;
mThread = nsnull;
@ -264,6 +264,7 @@ AndroidBridge::NotifyIME(int aType, int aState)
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(sBridge->mGeckoAppShellClass,
sBridge->jNotifyIME, aType, aState);
}
@ -280,11 +281,11 @@ AndroidBridge::NotifyIMEEnabled(int aState, const nsAString& aTypeHint,
if (!env)
return;
AutoLocalJNIFrame jniFrame(env);
nsPromiseFlatString typeHint(aTypeHint);
nsPromiseFlatString actionHint(aActionHint);
jvalue args[4];
AutoLocalJNIFrame jniFrame(env, 1);
args[0].i = aState;
args[1].l = env->NewString(typeHint.get(), typeHint.Length());
args[2].l = env->NewString(actionHint.get(), actionHint.Length());
@ -318,16 +319,15 @@ AndroidBridge::NotifyIMEChange(const PRUnichar *aText, PRUint32 aTextLen,
int aStart, int aEnd, int aNewEnd)
{
ALOG_BRIDGE("AndroidBridge::NotifyIMEChange");
if (!sBridge) {
if (!sBridge)
return;
}
JNIEnv *env = GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame jniFrame(env);
jvalue args[4];
AutoLocalJNIFrame jniFrame(env, 1);
args[0].l = env->NewString(aText, aTextLen);
args[1].i = aStart;
args[2].i = aEnd;
@ -345,6 +345,7 @@ AndroidBridge::AcknowledgeEventSync()
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jAcknowledgeEventSync);
}
@ -357,7 +358,7 @@ AndroidBridge::EnableLocation(bool aEnable)
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 1);
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jEnableLocation, aEnable);
}
@ -369,28 +370,30 @@ AndroidBridge::EnableLocationHighAccuracy(bool aEnable)
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 1);
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jEnableLocationHighAccuracy, aEnable);
}
void
AndroidBridge::EnableSensor(int aSensorType) {
AndroidBridge::EnableSensor(int aSensorType)
{
ALOG_BRIDGE("AndroidBridge::EnableSensor");
JNIEnv *env = GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 1);
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jEnableSensor, aSensorType);
}
void
AndroidBridge::DisableSensor(int aSensorType) {
AndroidBridge::DisableSensor(int aSensorType)
{
ALOG_BRIDGE("AndroidBridge::DisableSensor");
JNIEnv *env = GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 1);
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jDisableSensor, aSensorType);
}
@ -404,8 +407,8 @@ AndroidBridge::ReturnIMEQueryResult(const PRUnichar *aResult, PRUint32 aLen,
if (!env)
return;
AutoLocalJNIFrame jniFrame(env);
jvalue args[3];
AutoLocalJNIFrame jniFrame(env, 1);
args[0].l = env->NewString(aResult, aLen);
args[1].i = aSelStart;
args[2].i = aSelLen;
@ -422,6 +425,7 @@ AndroidBridge::ScheduleRestart()
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jScheduleRestart);
}
@ -434,6 +438,7 @@ AndroidBridge::NotifyXreExit()
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jNotifyXreExit);
}
@ -487,6 +492,9 @@ AndroidBridge::GetHandlersForMimeType(const char *aMimeType,
jobject obj = env->CallStaticObjectMethod(mGeckoAppShellClass,
jGetHandlersForMimeType,
jstrMimeType, jstrAction);
if (jniFrame.CheckForException())
return false;
jobjectArray arr = static_cast<jobjectArray>(obj);
if (!arr)
return false;
@ -523,6 +531,9 @@ AndroidBridge::GetHandlersForURL(const char *aURL,
jobject obj = env->CallStaticObjectMethod(mGeckoAppShellClass,
jGetHandlersForURL,
jstrScheme, jstrAction);
if (jniFrame.CheckForException())
return false;
jobjectArray arr = static_cast<jobjectArray>(obj);
if (!arr)
return false;
@ -564,10 +575,14 @@ AndroidBridge::OpenUriExternal(const nsACString& aUriSpec, const nsACString& aMi
jstring jstrTitle = env->NewString(nsPromiseFlatString(aTitle).get(),
aTitle.Length());
return env->CallStaticBooleanMethod(mGeckoAppShellClass,
bool ret = env->CallStaticBooleanMethod(mGeckoAppShellClass,
jOpenUriExternal,
jstrUri, jstrType, jstrPackage,
jstrClass, jstrAction, jstrTitle);
if (jniFrame.CheckForException())
return false;
return ret;
}
void
@ -586,6 +601,9 @@ AndroidBridge::GetMimeTypeFromExtensions(const nsACString& aFileExt, nsCString&
env->CallStaticObjectMethod(mGeckoAppShellClass,
jGetMimeTypeFromExtensions,
jstrExt));
if (jniFrame.CheckForException())
return;
nsJNIString jniStr(jstrType, env);
aMimeType.Assign(NS_ConvertUTF16toUTF8(jniStr.get()));
}
@ -606,6 +624,9 @@ AndroidBridge::GetExtensionFromMimeType(const nsACString& aMimeType, nsACString&
env->CallStaticObjectMethod(mGeckoAppShellClass,
jGetExtensionFromMimeType,
jstrType));
if (jniFrame.CheckForException())
return;
nsJNIString jniStr(jstrExt, env);
aFileExt.Assign(NS_ConvertUTF16toUTF8(jniStr.get()));
}
@ -619,6 +640,7 @@ AndroidBridge::MoveTaskToBack()
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jMoveTaskToBack);
}
@ -631,12 +653,13 @@ AndroidBridge::GetClipboardText(nsAString& aText)
if (!env)
return false;
jstring jstrType =
static_cast<jstring>(env->
CallStaticObjectMethod(mGeckoAppShellClass,
jGetClipboardText));
if (!jstrType)
AutoLocalJNIFrame jniFrame(env);
jstring jstrType = static_cast<jstring>(
env->CallStaticObjectMethod(mGeckoAppShellClass,
jGetClipboardText));
if (jniFrame.CheckForException() || !jstrType)
return false;
nsJNIString jniStr(jstrType, env);
aText.Assign(jniStr);
return true;
@ -666,12 +689,13 @@ AndroidBridge::ClipboardHasText()
if (!env)
return false;
jstring jstrType =
static_cast<jstring>(env->
CallStaticObjectMethod(mGeckoAppShellClass,
jGetClipboardText));
if (!jstrType)
AutoLocalJNIFrame jniFrame(env);
jstring jstrType = static_cast<jstring>(
env->CallStaticObjectMethod(mGeckoAppShellClass,
jGetClipboardText));
if (jniFrame.CheckForException() || !jstrType)
return false;
return true;
}
@ -684,6 +708,7 @@ AndroidBridge::EmptyClipboard()
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jSetClipboardText, nsnull);
}
@ -754,12 +779,17 @@ int
AndroidBridge::GetDPI()
{
ALOG_BRIDGE("AndroidBridge::GetDPI");
const int DEFAULT_DPI = 72; // what is a better value?
JNIEnv *env = GetJNIEnv();
if (!env)
return 72; // what is a better value. If we don't have a env here, we are hosed.
return DEFAULT_DPI;
AutoLocalJNIFrame jniFrame(env);
return (int) env->CallStaticIntMethod(mGeckoAppShellClass, jGetDpi);
int dpi = (int)env->CallStaticIntMethod(mGeckoAppShellClass, jGetDpi);
if (jniFrame.CheckForException())
return DEFAULT_DPI;
return dpi;
}
void
@ -774,9 +804,12 @@ AndroidBridge::ShowFilePickerForExtensions(nsAString& aFilePath, const nsAString
AutoLocalJNIFrame jniFrame(env);
jstring jstrFilers = env->NewString(nsPromiseFlatString(aExtensions).get(),
aExtensions.Length());
jstring jstr = static_cast<jstring>(env->CallStaticObjectMethod(
mGeckoAppShellClass,
jShowFilePickerForExtensions, jstrFilers));
jstring jstr = static_cast<jstring>(env->CallStaticObjectMethod(
mGeckoAppShellClass,
jShowFilePickerForExtensions, jstrFilers));
if (jniFrame.CheckForException())
return;
aFilePath.Assign(nsJNIString(jstr, env));
}
@ -792,9 +825,12 @@ AndroidBridge::ShowFilePickerForMimeType(nsAString& aFilePath, const nsAString&
AutoLocalJNIFrame jniFrame(env);
jstring jstrFilers = env->NewString(nsPromiseFlatString(aMimeType).get(),
aMimeType.Length());
jstring jstr = static_cast<jstring>(env->CallStaticObjectMethod(
mGeckoAppShellClass,
jShowFilePickerForMimeType, jstrFilers));
jstring jstr = static_cast<jstring>(env->CallStaticObjectMethod(
mGeckoAppShellClass,
jShowFilePickerForMimeType, jstrFilers));
if (jniFrame.CheckForException())
return;
aFilePath.Assign(nsJNIString(jstr, env));
}
@ -821,6 +857,7 @@ AndroidBridge::SetFullScreen(bool aFullScreen)
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jSetFullScreen, aFullScreen);
}
@ -828,16 +865,19 @@ void
AndroidBridge::HideProgressDialogOnce()
{
static bool once = false;
if (once)
return;
JNIEnv *env = GetJNIEnv();
if (!env)
return;
if (!once) {
ALOG_BRIDGE("AndroidBridge::HideProgressDialogOnce");
env->CallStaticVoidMethod(mGeckoAppShellClass, jHideProgressDialog);
once = true;
}
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jHideProgressDialog);
if (jniFrame.CheckForException())
return;
once = true;
}
void
@ -849,6 +889,7 @@ AndroidBridge::PerformHapticFeedback(bool aIsLongPress)
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass,
jPerformHapticFeedback, aIsLongPress);
}
@ -856,14 +897,12 @@ AndroidBridge::PerformHapticFeedback(bool aIsLongPress)
void
AndroidBridge::Vibrate(const nsTArray<PRUint32>& aPattern)
{
ALOG_BRIDGE("AndroidBridge::Vibrate");
JNIEnv *env = GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame jniFrame(env);
ALOG_BRIDGE("AndroidBridge::Vibrate");
PRUint32 len = aPattern.Length();
if (!len) {
ALOG_BRIDGE(" invalid 0-length array");
@ -916,6 +955,7 @@ AndroidBridge::CancelVibrate()
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jCancelVibrate);
}
@ -928,7 +968,12 @@ AndroidBridge::IsNetworkLinkUp()
if (!env)
return false;
return !!env->CallStaticBooleanMethod(mGeckoAppShellClass, jIsNetworkLinkUp);
AutoLocalJNIFrame jniFrame(env, 0);
bool ret = !!env->CallStaticBooleanMethod(mGeckoAppShellClass, jIsNetworkLinkUp);
if (jniFrame.CheckForException())
return false;
return ret;
}
bool
@ -940,7 +985,12 @@ AndroidBridge::IsNetworkLinkKnown()
if (!env)
return false;
return !!env->CallStaticBooleanMethod(mGeckoAppShellClass, jIsNetworkLinkKnown);
AutoLocalJNIFrame jniFrame(env, 0);
bool ret = !!env->CallStaticBooleanMethod(mGeckoAppShellClass, jIsNetworkLinkKnown);
if (jniFrame.CheckForException())
return false;
return ret;
}
void
@ -973,6 +1023,9 @@ AndroidBridge::GetSystemColors(AndroidSystemColors *aColors)
AutoLocalJNIFrame jniFrame(env);
jobject obj = env->CallStaticObjectMethod(mGeckoAppShellClass, jGetSystemColors);
if (jniFrame.CheckForException())
return;
jintArray arr = static_cast<jintArray>(obj);
if (!arr)
return;
@ -1016,6 +1069,9 @@ AndroidBridge::GetIconForExtension(const nsACString& aFileExt, PRUint32 aIconSiz
jstring jstrFileExt = env->NewString(nsPromiseFlatString(fileExt).get(), fileExt.Length());
jobject obj = env->CallStaticObjectMethod(mGeckoAppShellClass, jGetIconForExtension, jstrFileExt, aIconSize);
if (jniFrame.CheckForException())
return;
jbyteArray arr = static_cast<jbyteArray>(obj);
NS_ASSERTION(arr != nsnull, "AndroidBridge::GetIconForExtension: Returned pixels array is null!");
if (!arr)
@ -1041,7 +1097,12 @@ AndroidBridge::GetShowPasswordSetting()
if (!env)
return false;
return env->CallStaticBooleanMethod(mGeckoAppShellClass, jGetShowPasswordSetting);
AutoLocalJNIFrame jniFrame(env, 0);
bool ret = env->CallStaticBooleanMethod(mGeckoAppShellClass, jGetShowPasswordSetting);
if (jniFrame.CheckForException())
return false;
return ret;
}
void
@ -1067,6 +1128,7 @@ AndroidBridge::ShowInputMethodPicker()
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jShowInputMethodPicker);
}
@ -1075,11 +1137,12 @@ AndroidBridge::CallEglCreateWindowSurface(void *dpy, void *config, AndroidGeckoS
{
ALOG_BRIDGE("AndroidBridge::CallEglCreateWindowSurface");
// Called off the main thread by the compositor
JNIEnv *env = GetJNIForThread();
JNIEnv *env = GetJNIForThread(); // called on the compositor thread
if (!env)
return NULL;
AutoLocalJNIFrame jniFrame(env);
/*
* This is basically:
*
@ -1091,7 +1154,7 @@ AndroidBridge::CallEglCreateWindowSurface(void *dpy, void *config, AndroidGeckoS
* We can't do it from java, because the EGLConfigImpl constructor is private.
*/
jobject surfaceHolder = sview.GetSurfaceHolder();
jobject surfaceHolder = sview.GetSurfaceHolder(env, &jniFrame);
if (!surfaceHolder)
return nsnull;
@ -1103,13 +1166,15 @@ AndroidBridge::CallEglCreateWindowSurface(void *dpy, void *config, AndroidGeckoS
jmethodID createWindowSurface = env->GetMethodID(jEGL10Class, "eglCreateWindowSurface", "(Ljavax/microedition/khronos/egl/EGLDisplay;Ljavax/microedition/khronos/egl/EGLConfig;Ljava/lang/Object;[I)Ljavax/microedition/khronos/egl/EGLSurface;");
jobject egl = env->CallStaticObjectMethod(jEGLContextClass, getEgl);
if (jniFrame.CheckForException())
return nsnull;
jobject jdpy = env->NewObject(jEGLDisplayImplClass, constructDisplay, (int) dpy);
jobject jconf = env->NewObject(jEGLConfigImplClass, constructConfig, (int) config);
// make the call
jobject surf = env->CallObjectMethod(egl, createWindowSurface, jdpy, jconf, surfaceHolder, NULL);
if (!surf)
if (jniFrame.CheckForException() || !surf)
return nsnull;
jfieldID sfield = env->GetFieldID(jEGLSurfaceImplClass, "mEGLSurface", "I");
@ -1129,11 +1194,13 @@ AndroidBridge::RegisterCompositor()
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 3);
AutoLocalJNIFrame jniFrame(env);
jmethodID registerCompositor = env->GetStaticMethodID(jLayerView, "registerCxxCompositor", "()Lorg/mozilla/gecko/gfx/GLController;");
jobject glController = env->CallStaticObjectMethod(jLayerView, registerCompositor);
if (jniFrame.CheckForException())
return;
sController.Acquire(env, glController);
sController.SetGLVersion(2);
@ -1157,7 +1224,7 @@ AndroidBridge::GetStaticIntField(const char *className, const char *fieldName, P
return false;
}
AutoLocalJNIFrame jniFrame(env, 3);
AutoLocalJNIFrame jniFrame(env);
jclass cls = env->FindClass(className);
if (!cls)
return false;
@ -1174,7 +1241,7 @@ AndroidBridge::GetStaticIntField(const char *className, const char *fieldName, P
bool
AndroidBridge::GetStaticStringField(const char *className, const char *fieldName, nsAString &result, JNIEnv* env /* = nsnull */)
{
ALOG_BRIDGE("AndroidBridge::GetStaticIntField %s", fieldName);
ALOG_BRIDGE("AndroidBridge::GetStaticStringField %s", fieldName);
if (!env) {
env = GetJNIEnv();
@ -1182,7 +1249,7 @@ AndroidBridge::GetStaticStringField(const char *className, const char *fieldName
return false;
}
AutoLocalJNIFrame jniFrame(env, 3);
AutoLocalJNIFrame jniFrame(env);
jclass cls = env->FindClass(className);
if (!cls)
return false;
@ -1208,6 +1275,7 @@ AndroidBridge::SetKeepScreenOn(bool on)
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(sBridge->mGeckoAppShellClass,
sBridge->jSetKeepScreenOn, on);
}
@ -1265,7 +1333,7 @@ AndroidBridge::PostToJavaThread(JNIEnv *env, nsIRunnable* aRunnable, bool aMainT
{
mRunnableQueue.AppendObject(aRunnable);
AutoLocalJNIFrame jniFrame(env);
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jPostToJavaThread, (jboolean)aMainThread);
}
@ -1350,6 +1418,7 @@ AndroidBridge::FireAndWaitForTracerEvent() {
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass,
jFireAndWaitForTracerEvent);
}
@ -1483,7 +1552,11 @@ AndroidBridge::InitCamera(const nsCString& contentType, PRUint32 camera, PRUint3
NS_ConvertASCIItoUTF16 s(contentType);
jstring jstrContentType = env->NewString(s.get(), NS_strlen(s.get()));
jobject obj = env->CallStaticObjectMethod(mGeckoAppShellClass, jInitCamera, jstrContentType, camera, *width, *height);
if (jniFrame.CheckForException())
return false;
jintArray arr = static_cast<jintArray>(obj);
if (!arr)
return false;
@ -1502,13 +1575,13 @@ AndroidBridge::InitCamera(const nsCString& contentType, PRUint32 camera, PRUint3
}
void
AndroidBridge::CloseCamera() {
AndroidBridge::CloseCamera()
{
JNIEnv *env = GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame jniFrame(env);
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jCloseCamera);
}
@ -1522,6 +1595,7 @@ AndroidBridge::EnableBatteryNotifications()
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jEnableBatteryNotifications);
}
@ -1534,6 +1608,7 @@ AndroidBridge::DisableBatteryNotifications()
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jDisableBatteryNotifications);
}
@ -1551,6 +1626,9 @@ AndroidBridge::GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInf
// To prevent calling too many methods through JNI, the Java method returns
// an array of double even if we actually want a double and a boolean.
jobject obj = env->CallStaticObjectMethod(mGeckoAppShellClass, jGetCurrentBatteryInformation);
if (jniFrame.CheckForException())
return;
jdoubleArray arr = static_cast<jdoubleArray>(obj);
if (!arr || env->GetArrayLength(arr) != 3) {
return;
@ -1574,15 +1652,12 @@ AndroidBridge::HandleGeckoMessage(const nsAString &aMessage, nsAString &aRet)
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 1);
AutoLocalJNIFrame jniFrame(env);
jstring jMessage = env->NewString(nsPromiseFlatString(aMessage).get(), aMessage.Length());
jstring returnMessage = static_cast<jstring>(env->CallStaticObjectMethod(mGeckoAppShellClass, jHandleGeckoMessage, jMessage));
if (jniFrame.CheckForException())
return;
jthrowable ex = env->ExceptionOccurred();
if (ex) {
env->ExceptionDescribe();
env->ExceptionClear();
}
nsJNIString jniStr(returnMessage, env);
aRet.Assign(jniStr);
ALOG_BRIDGE("leaving %s", __PRETTY_FUNCTION__);
@ -1602,8 +1677,8 @@ AndroidBridge::CheckURIVisited(const nsAString& aURI)
JNIEnv *env = GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 1);
AutoLocalJNIFrame jniFrame(env);
jstring jstrURI = env->NewString(nsPromiseFlatString(aURI).get(), aURI.Length());
env->CallStaticVoidMethod(mGeckoAppShellClass, jCheckUriVisited, jstrURI);
}
@ -1615,7 +1690,7 @@ AndroidBridge::MarkURIVisited(const nsAString& aURI)
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 1);
AutoLocalJNIFrame jniFrame(env);
jstring jstrURI = env->NewString(nsPromiseFlatString(aURI).get(), aURI.Length());
env->CallStaticVoidMethod(mGeckoAppShellClass, jMarkUriVisited, jstrURI);
}
@ -1631,7 +1706,11 @@ AndroidBridge::GetNumberOfMessagesForText(const nsAString& aText)
AutoLocalJNIFrame jniFrame(env);
jstring jText = env->NewString(PromiseFlatString(aText).get(), aText.Length());
return env->CallStaticIntMethod(mGeckoAppShellClass, jNumberOfMessages, jText);
PRUint16 ret = env->CallStaticIntMethod(mGeckoAppShellClass, jNumberOfMessages, jText);
if (jniFrame.CheckForException())
return 0;
return ret;
}
void
@ -1660,10 +1739,14 @@ AndroidBridge::SaveSentMessage(const nsAString& aRecipient,
if (!env)
return 0;
AutoLocalJNIFrame jniFrame(env, 1);
AutoLocalJNIFrame jniFrame(env);
jstring jRecipient = env->NewString(PromiseFlatString(aRecipient).get(), aRecipient.Length());
jstring jBody = env->NewString(PromiseFlatString(aBody).get(), aBody.Length());
return env->CallStaticIntMethod(mGeckoAppShellClass, jSaveSentMessage, jRecipient, jBody, aDate);
PRInt32 ret = env->CallStaticIntMethod(mGeckoAppShellClass, jSaveSentMessage, jRecipient, jBody, aDate);
if (jniFrame.CheckForException())
return 0;
return ret;
}
void
@ -1675,6 +1758,7 @@ AndroidBridge::GetMessage(PRInt32 aMessageId, PRInt32 aRequestId, PRUint64 aProc
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jGetMessage, aMessageId, aRequestId, aProcessId);
}
@ -1687,6 +1771,7 @@ AndroidBridge::DeleteMessage(PRInt32 aMessageId, PRInt32 aRequestId, PRUint64 aP
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jDeleteMessage, aMessageId, aRequestId, aProcessId);
}
@ -1728,6 +1813,7 @@ AndroidBridge::GetNextMessageInList(PRInt32 aListId, PRInt32 aRequestId, PRUint6
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jGetNextMessageinList, aListId, aRequestId, aProcessId);
}
@ -1740,6 +1826,7 @@ AndroidBridge::ClearMessageList(PRInt32 aListId)
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jClearMessageList, aListId);
}
@ -1757,6 +1844,9 @@ AndroidBridge::GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInf
// To prevent calling too many methods through JNI, the Java method returns
// an array of double even if we actually want a double and a boolean.
jobject obj = env->CallStaticObjectMethod(mGeckoAppShellClass, jGetCurrentNetworkInformation);
if (jniFrame.CheckForException())
return;
jdoubleArray arr = static_cast<jdoubleArray>(obj);
if (!arr || env->GetArrayLength(arr) != 2) {
return;
@ -1778,6 +1868,7 @@ AndroidBridge::EnableNetworkNotifications()
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jEnableNetworkNotifications);
}
@ -1789,19 +1880,22 @@ AndroidBridge::DisableNetworkNotifications()
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jDisableNetworkNotifications);
}
void *
AndroidBridge::LockBitmap(jobject bitmap)
{
int err;
void *buf;
JNIEnv *env = GetJNIEnv();
if (!env)
return nsnull;
AutoLocalJNIFrame jniFrame(env);
int err;
void *buf;
if ((err = AndroidBitmap_lockPixels(env, bitmap, &buf)) != 0) {
ALOG_BRIDGE("AndroidBitmap_lockPixels failed! (error %d)", err);
buf = nsnull;
@ -1813,12 +1907,14 @@ AndroidBridge::LockBitmap(jobject bitmap)
void
AndroidBridge::UnlockBitmap(jobject bitmap)
{
int err;
JNIEnv *env = GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame jniFrame(env);
int err;
if ((err = AndroidBitmap_unlockPixels(env, bitmap)) != 0)
ALOG_BRIDGE("AndroidBitmap_unlockPixels failed! (error %d)", err);
}
@ -1966,7 +2062,13 @@ AndroidBridge::IsTablet()
if (!env)
return false;
return env->CallStaticBooleanMethod(mGeckoAppShellClass, jIsTablet);
AutoLocalJNIFrame jniFrame(env, 0);
bool ret = env->CallStaticBooleanMethod(mGeckoAppShellClass, jIsTablet);
if (jniFrame.CheckForException())
return false;
return ret;
}
void
@ -2036,11 +2138,13 @@ NS_IMETHODIMP nsAndroidBridge::SetDrawMetadataProvider(nsIAndroidDrawMetadataPro
}
void
AndroidBridge::NotifyDefaultPrevented(bool aDefaultPrevented) {
AndroidBridge::NotifyDefaultPrevented(bool aDefaultPrevented)
{
JNIEnv *env = GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jNotifyDefaultPrevented, (jboolean)aDefaultPrevented);
}
@ -2097,9 +2201,12 @@ AndroidBridge::CreateSurface()
if (!env)
return nsnull;
AutoLocalJNIFrame frame(env);
AutoLocalJNIFrame jniFrame(env);
jobject surface = env->CallStaticObjectMethod(mGeckoAppShellClass, jCreateSurface);
if (jniFrame.CheckForException())
return nsnull;
if (surface)
surface = env->NewGlobalRef(surface);
@ -2115,7 +2222,7 @@ AndroidBridge::DestroySurface(jobject surface)
if (!env)
return;
AutoLocalJNIFrame frame(env);
AutoLocalJNIFrame jniFrame(env);
env->CallStaticVoidMethod(mGeckoAppShellClass, jDestroySurface, surface);
env->DeleteGlobalRef(surface);
@ -2130,7 +2237,7 @@ AndroidBridge::ShowSurface(jobject surface, const gfxRect& aRect, bool aInverted
if (!env)
return;
AutoLocalJNIFrame frame(env);
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jShowSurface, surface,
(int)aRect.x, (int)aRect.y,
@ -2147,7 +2254,7 @@ AndroidBridge::HideSurface(jobject surface)
if (!env)
return;
AutoLocalJNIFrame frame(env);
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jHideSurface, surface);
#endif
@ -2157,35 +2264,65 @@ void
AndroidBridge::GetScreenOrientation(dom::ScreenOrientationWrapper& aOrientation)
{
ALOG_BRIDGE("AndroidBridge::GetScreenOrientation");
aOrientation.orientation = static_cast<dom::ScreenOrientation>(mJNIEnv->CallStaticShortMethod(mGeckoAppShellClass, jGetScreenOrientation));
JNIEnv* env = GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
jshort orientation = env->CallStaticShortMethod(mGeckoAppShellClass, jGetScreenOrientation);
if (jniFrame.CheckForException())
return;
aOrientation.orientation = static_cast<dom::ScreenOrientation>(orientation);
}
void
AndroidBridge::EnableScreenOrientationNotifications()
{
ALOG_BRIDGE("AndroidBridge::EnableScreenOrientationNotifications");
mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jEnableScreenOrientationNotifications);
JNIEnv* env = GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jEnableScreenOrientationNotifications);
}
void
AndroidBridge::DisableScreenOrientationNotifications()
{
ALOG_BRIDGE("AndroidBridge::DisableScreenOrientationNotifications");
mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jDisableScreenOrientationNotifications);
JNIEnv* env = GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jDisableScreenOrientationNotifications);
}
void
AndroidBridge::LockScreenOrientation(const dom::ScreenOrientationWrapper& aOrientation)
{
ALOG_BRIDGE("AndroidBridge::LockScreenOrientation");
mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jLockScreenOrientation, aOrientation.orientation);
JNIEnv* env = GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jLockScreenOrientation, aOrientation.orientation);
}
void
AndroidBridge::UnlockScreenOrientation()
{
ALOG_BRIDGE("AndroidBridge::UnlockScreenOrientation");
mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jUnlockScreenOrientation);
JNIEnv* env = GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jUnlockScreenOrientation);
}
void
@ -2196,7 +2333,7 @@ AndroidBridge::PumpMessageLoop()
if (!env)
return;
AutoLocalJNIFrame frame(env);
AutoLocalJNIFrame jniFrame(env, 0);
if ((void*)pthread_self() != mThread)
return;
@ -2212,6 +2349,7 @@ NS_IMETHODIMP nsAndroidBridge::GetBrowserApp(nsIAndroidBrowserApp * *aBrowserApp
nsAppShell::gAppShell->GetBrowserApp(aBrowserApp);
return NS_OK;
}
NS_IMETHODIMP nsAndroidBridge::SetBrowserApp(nsIAndroidBrowserApp *aBrowserApp)
{
if (nsAppShell::gAppShell)
@ -2225,7 +2363,7 @@ AndroidBridge::AddPluginView(jobject view, const gfxRect& rect) {
if (!env)
return;
AutoLocalJNIFrame frame(env);
AutoLocalJNIFrame jniFrame(env);
#if MOZ_JAVA_COMPOSITOR
env->CallStaticVoidMethod(sBridge->mGeckoAppShellClass,
@ -2239,23 +2377,30 @@ AndroidBridge::AddPluginView(jobject view, const gfxRect& rect) {
}
void
AndroidBridge::RemovePluginView(jobject view) {
AndroidBridge::RemovePluginView(jobject view)
{
JNIEnv *env = GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame frame(env);
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jRemovePluginView, view);
}
extern "C"
__attribute__ ((visibility("default")))
jobject JNICALL
Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer(JNIEnv *jenv, jclass, jlong size);
Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer(JNIEnv *env, jclass, jlong size);
nsresult AndroidBridge::TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt32 srcY, PRInt32 srcW, PRInt32 srcH, PRInt32 dstW, PRInt32 dstH, PRInt32 tabId, float scale, PRInt32 token)
{
JNIEnv* env = GetJNIEnv();
if (!env)
return NS_OK;
AutoLocalJNIFrame jniFrame(env);
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(window);
if (!win)
return NS_ERROR_FAILURE;
@ -2275,34 +2420,31 @@ nsresult AndroidBridge::TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt
nsPresContext::CSSPixelsToAppUnits(srcW / scale),
nsPresContext::CSSPixelsToAppUnits(srcH / scale));
JNIEnv* jenv = GetJNIEnv();
if (!jenv)
return NS_OK;
PRUint32 stride = dstW * 2;
PRUint32 bufferSize = dstH * stride;
jobject buffer = Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer(jenv, NULL, bufferSize);
jobject buffer = Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer(env, NULL, bufferSize);
if (!buffer)
return NS_OK;
void* data = jenv->GetDirectBufferAddress(buffer);
void* data = env->GetDirectBufferAddress(buffer);
memset(data, 0, bufferSize);
nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(static_cast<unsigned char*>(data), nsIntSize(dstW, dstH), stride, gfxASurface::ImageFormatRGB16_565);
nsRefPtr<gfxContext> context = new gfxContext(surf);
context->Scale(scale * dstW / srcW, scale * dstH / srcH);
nsresult rv = presShell->RenderDocument(r, renderDocFlags, bgColor, context);
NS_ENSURE_SUCCESS(rv, rv);
AutoLocalJNIFrame jniFrame(jenv, 1);
jenv->CallStaticVoidMethod(AndroidBridge::Bridge()->mGeckoAppShellClass, AndroidBridge::Bridge()->jNotifyScreenShot, buffer, tabId, srcX * dstW / srcW , srcY * dstH / srcH, dstW, dstH, token);
env->CallStaticVoidMethod(AndroidBridge::Bridge()->mGeckoAppShellClass, AndroidBridge::Bridge()->jNotifyScreenShot, buffer, tabId, srcX * dstW / srcW , srcY * dstH / srcH, dstW, dstH, token);
return NS_OK;
}
void
AndroidBridge::NotifyPaintedRect(float top, float left, float bottom, float right)
{
JNIEnv* jenv = GetJNIEnv();
if (!jenv)
JNIEnv* env = GetJNIEnv();
if (!env)
return;
jenv->CallStaticVoidMethod(AndroidBridge::Bridge()->mGeckoAppShellClass, AndroidBridge::Bridge()->jNotifyPaintedRect, top, left, bottom, right);
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(AndroidBridge::Bridge()->mGeckoAppShellClass, AndroidBridge::Bridge()->jNotifyPaintedRect, top, left, bottom, right);
}

View File

@ -289,68 +289,6 @@ public:
void FireAndWaitForTracerEvent();
class AutoLocalJNIFrame {
public:
AutoLocalJNIFrame(int nEntries = 128)
: mEntries(nEntries)
{
mJNIEnv = AndroidBridge::GetJNIEnv();
Push();
}
AutoLocalJNIFrame(JNIEnv* aJNIEnv, int nEntries = 128)
: mEntries(nEntries)
{
mJNIEnv = aJNIEnv ? aJNIEnv : AndroidBridge::GetJNIEnv();
Push();
}
// Note! Calling Purge makes all previous local refs created in
// the AutoLocalJNIFrame's scope INVALID; be sure that you locked down
// any local refs that you need to keep around in global refs!
void Purge() {
if (mJNIEnv) {
mJNIEnv->PopLocalFrame(NULL);
Push();
}
}
bool CheckForException() {
jthrowable exception = mJNIEnv->ExceptionOccurred();
if (exception) {
mJNIEnv->ExceptionDescribe();
mJNIEnv->ExceptionClear();
return true;
}
return false;
}
~AutoLocalJNIFrame() {
if (!mJNIEnv)
return;
CheckForException();
mJNIEnv->PopLocalFrame(NULL);
}
private:
void Push() {
if (!mJNIEnv)
return;
// Make sure there is enough space to store a local ref to the
// exception. I am not completely sure this is needed, but does
// not hurt.
mJNIEnv->PushLocalFrame(mEntries + 1);
}
int mEntries;
JNIEnv* mJNIEnv;
};
/* See GLHelpers.java as to why this is needed */
void *CallEglCreateWindowSurface(void *dpy, void *config, AndroidGeckoSurfaceView& surfaceView);
@ -609,6 +547,71 @@ protected:
void (* Region_set)(void* region, void* rect);
};
class AutoLocalJNIFrame {
public:
AutoLocalJNIFrame(int nEntries = 128)
: mEntries(nEntries)
{
mJNIEnv = AndroidBridge::GetJNIEnv();
Push();
}
AutoLocalJNIFrame(JNIEnv* aJNIEnv, int nEntries = 128)
: mEntries(nEntries)
{
mJNIEnv = aJNIEnv ? aJNIEnv : AndroidBridge::GetJNIEnv();
Push();
}
// Note! Calling Purge makes all previous local refs created in
// the AutoLocalJNIFrame's scope INVALID; be sure that you locked down
// any local refs that you need to keep around in global refs!
void Purge() {
if (mJNIEnv) {
mJNIEnv->PopLocalFrame(NULL);
Push();
}
}
bool CheckForException() {
if (mJNIEnv->ExceptionCheck()) {
mJNIEnv->ExceptionDescribe();
mJNIEnv->ExceptionClear();
return true;
}
return false;
}
~AutoLocalJNIFrame() {
if (!mJNIEnv)
return;
CheckForException();
mJNIEnv->PopLocalFrame(NULL);
}
private:
void Push() {
if (!mJNIEnv)
return;
// Make sure there is enough space to store a local ref to the
// exception. I am not completely sure this is needed, but does
// not hurt.
jint ret = mJNIEnv->PushLocalFrame(mEntries + 1);
NS_ABORT_IF_FALSE(ret == 0, "Failed to push local JNI frame");
if (ret < 0) {
CheckForException();
}
}
int mEntries;
JNIEnv* mJNIEnv;
};
}
#define NS_ANDROIDBRIDGE_CID \

View File

@ -225,13 +225,22 @@ AndroidLocation::InitLocationClass(JNIEnv *jEnv)
nsGeoPosition*
AndroidLocation::CreateGeoPosition(JNIEnv *jenv, jobject jobj)
{
AutoLocalJNIFrame jniFrame(jenv);
double latitude = jenv->CallDoubleMethod(jobj, jGetLatitudeMethod);
if (jniFrame.CheckForException()) return NULL;
double longitude = jenv->CallDoubleMethod(jobj, jGetLongitudeMethod);
if (jniFrame.CheckForException()) return NULL;
double altitude = jenv->CallDoubleMethod(jobj, jGetAltitudeMethod);
if (jniFrame.CheckForException()) return NULL;
float accuracy = jenv->CallFloatMethod (jobj, jGetAccuracyMethod);
if (jniFrame.CheckForException()) return NULL;
float bearing = jenv->CallFloatMethod (jobj, jGetBearingMethod);
if (jniFrame.CheckForException()) return NULL;
float speed = jenv->CallFloatMethod (jobj, jGetSpeedMethod);
if (jniFrame.CheckForException()) return NULL;
long long time = jenv->CallLongMethod (jobj, jGetTimeMethod);
if (jniFrame.CheckForException()) return NULL;
return new nsGeoPosition(latitude, longitude,
altitude, accuracy,
@ -631,7 +640,13 @@ AndroidGeckoSurfaceView::BeginDrawing()
if (!env)
return 0;
return env->CallIntMethod(wrapped_obj, jBeginDrawingMethod);
AutoLocalJNIFrame jniFrame(env, 0);
int ret = env->CallIntMethod(wrapped_obj, jBeginDrawingMethod);
if (jniFrame.CheckForException())
return 0;
return ret;
}
void
@ -641,6 +656,7 @@ AndroidGeckoSurfaceView::EndDrawing()
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallVoidMethod(wrapped_obj, jEndDrawingMethod);
}
@ -651,6 +667,7 @@ AndroidGeckoSurfaceView::Draw2D(jobject bitmap, int width, int height)
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallVoidMethod(wrapped_obj, jDraw2DBitmapMethod, bitmap, width, height);
}
@ -661,6 +678,7 @@ AndroidGeckoSurfaceView::Draw2D(jobject buffer, int stride)
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallVoidMethod(wrapped_obj, jDraw2DBufferMethod, buffer, stride);
}
@ -673,7 +691,7 @@ AndroidGeckoLayerClient::SetFirstPaintViewport(float aOffsetX, float aOffsetY, f
if (!env)
return;
AndroidBridge::AutoLocalJNIFrame jniFrame(env);
AutoLocalJNIFrame jniFrame(env, 0);
return env->CallVoidMethod(wrapped_obj, jSetFirstPaintViewport, aOffsetX, aOffsetY, aZoom, aPageWidth, aPageHeight,
aCssPageWidth, aCssPageHeight);
}
@ -686,7 +704,7 @@ AndroidGeckoLayerClient::SetPageSize(float aZoom, float aPageWidth, float aPageH
if (!env)
return;
AndroidBridge::AutoLocalJNIFrame jniFrame(env);
AutoLocalJNIFrame jniFrame(env, 0);
return env->CallVoidMethod(wrapped_obj, jSetPageSize, aZoom, aPageWidth, aPageHeight, aCssPageWidth, aCssPageHeight);
}
@ -699,14 +717,18 @@ AndroidGeckoLayerClient::SyncViewportInfo(const nsIntRect& aDisplayPort, float a
if (!env)
return;
AndroidViewTransform viewTransform;
AndroidBridge::AutoLocalJNIFrame jniFrame(env);
AutoLocalJNIFrame jniFrame(env);
jobject viewTransformJObj = env->CallObjectMethod(wrapped_obj, jSyncViewportInfoMethod,
aDisplayPort.x, aDisplayPort.y,
aDisplayPort.width, aDisplayPort.height,
aDisplayResolution, aLayersUpdated);
if (jniFrame.CheckForException())
return;
NS_ABORT_IF_FALSE(viewTransformJObj, "No view transform object!");
AndroidViewTransform viewTransform;
viewTransform.Init(viewTransformJObj);
aScrollOffset = nsIntPoint(viewTransform.GetX(env), viewTransform.GetY(env));
@ -714,51 +736,69 @@ AndroidGeckoLayerClient::SyncViewportInfo(const nsIntRect& aDisplayPort, float a
}
jobject
AndroidGeckoSurfaceView::GetSoftwareDrawBitmap()
AndroidGeckoSurfaceView::GetSoftwareDrawBitmap(JNIEnv *env, AutoLocalJNIFrame *jniFrame)
{
JNIEnv *env = AndroidBridge::GetJNIEnv();
if (!env)
if (!env || !jniFrame)
return nsnull;
return env->CallObjectMethod(wrapped_obj, jGetSoftwareDrawBitmapMethod);
jobject ret = env->CallObjectMethod(wrapped_obj, jGetSoftwareDrawBitmapMethod);
if (jniFrame->CheckForException())
return nsnull;
return ret;
}
jobject
AndroidGeckoSurfaceView::GetSoftwareDrawBuffer()
AndroidGeckoSurfaceView::GetSoftwareDrawBuffer(JNIEnv *env, AutoLocalJNIFrame *jniFrame)
{
JNIEnv *env = AndroidBridge::GetJNIEnv();
if (!env)
if (!env || !jniFrame)
return nsnull;
return env->CallObjectMethod(wrapped_obj, jGetSoftwareDrawBufferMethod);
jobject ret = env->CallObjectMethod(wrapped_obj, jGetSoftwareDrawBufferMethod);
if (jniFrame->CheckForException())
return nsnull;
return ret;
}
jobject
AndroidGeckoSurfaceView::GetSurface()
AndroidGeckoSurfaceView::GetSurface(JNIEnv *env, AutoLocalJNIFrame *jniFrame)
{
JNIEnv *env = AndroidBridge::GetJNIEnv();
if (!env)
if (!env || !jniFrame)
return nsnull;
return env->CallObjectMethod(wrapped_obj, jGetSurfaceMethod);
jobject ret = env->CallObjectMethod(wrapped_obj, jGetSurfaceMethod);
if (jniFrame->CheckForException())
return nsnull;
return ret;
}
jobject
AndroidGeckoSurfaceView::GetSurfaceHolder()
AndroidGeckoSurfaceView::GetSurfaceHolder(JNIEnv *env, AutoLocalJNIFrame *jniFrame)
{
JNIEnv *env = GetJNIForThread();
if (!env)
if (!env || !jniFrame)
return nsnull;
return env->CallObjectMethod(wrapped_obj, jGetHolderMethod);
jobject ret = env->CallObjectMethod(wrapped_obj, jGetHolderMethod);
if (jniFrame->CheckForException())
return nsnull;
return ret;
}
void
bool
AndroidGeckoLayerClient::CreateFrame(JNIEnv *env, AndroidLayerRendererFrame& aFrame)
{
AutoLocalJNIFrame jniFrame(env, 1);
jobject frameJObj = env->CallObjectMethod(wrapped_obj, jCreateFrameMethod);
if (jniFrame.CheckForException())
return false;
NS_ABORT_IF_FALSE(frameJObj, "No frame object!");
aFrame.Init(env, frameJObj);
return true;
}
void

View File

@ -59,6 +59,7 @@
namespace mozilla {
class AndroidGeckoLayerClient;
class AutoLocalJNIFrame;
void InitAndroidJavaWrappers(JNIEnv *jEnv);
@ -207,7 +208,7 @@ public:
void SetPageSize(float aZoom, float aPageWidth, float aPageHeight, float aCssPageWidth, float aCssPageHeight);
void SyncViewportInfo(const nsIntRect& aDisplayPort, float aDisplayResolution, bool aLayersUpdated,
nsIntPoint& aScrollOffset, float& aScaleX, float& aScaleY);
void CreateFrame(JNIEnv *env, AndroidLayerRendererFrame& aFrame);
bool CreateFrame(JNIEnv *env, AndroidLayerRendererFrame& aFrame);
void ActivateProgram(JNIEnv *env);
void DeactivateProgram(JNIEnv *env);
@ -241,17 +242,14 @@ public:
};
int BeginDrawing();
jobject GetSoftwareDrawBitmap();
jobject GetSoftwareDrawBuffer();
jobject GetSoftwareDrawBitmap(JNIEnv *env, AutoLocalJNIFrame *jniFrame);
jobject GetSoftwareDrawBuffer(JNIEnv *env, AutoLocalJNIFrame *jniFrame);
void EndDrawing();
void Draw2D(jobject bitmap, int width, int height);
void Draw2D(jobject buffer, int stride);
jobject GetSurface();
// must have a JNI local frame when calling this,
// and you'd better know what you're doing
jobject GetSurfaceHolder();
jobject GetSurface(JNIEnv *env, AutoLocalJNIFrame *jniFrame);
jobject GetSurfaceHolder(JNIEnv *env, AutoLocalJNIFrame *jniFrame);
protected:
static jclass jGeckoSurfaceViewClass;

View File

@ -914,11 +914,15 @@ nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae)
if (AndroidBridge::Bridge()->HasNativeWindowAccess()) {
AndroidGeckoSurfaceView& sview(AndroidBridge::Bridge()->SurfaceView());
jobject surface = sview.GetSurface();
if (surface) {
sNativeWindow = AndroidBridge::Bridge()->AcquireNativeWindow(AndroidBridge::GetJNIEnv(), surface);
if (sNativeWindow) {
AndroidBridge::Bridge()->SetNativeWindowFormat(sNativeWindow, 0, 0, AndroidBridge::WINDOW_FORMAT_RGB_565);
JNIEnv *env = AndroidBridge::GetJNIEnv();
if (env) {
AutoLocalJNIFrame jniFrame(env);
jobject surface = sview.GetSurface(env, &jniFrame);
if (surface) {
sNativeWindow = AndroidBridge::Bridge()->AcquireNativeWindow(env, surface);
if (sNativeWindow) {
AndroidBridge::Bridge()->SetNativeWindowFormat(sNativeWindow, 0, 0, AndroidBridge::WINDOW_FORMAT_RGB_565);
}
}
}
}
@ -1109,7 +1113,11 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
nsRefPtr<nsWindow> kungFuDeathGrip(this);
AndroidBridge::AutoLocalJNIFrame jniFrame;
JNIEnv *env = AndroidBridge::GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame jniFrame;
#ifdef MOZ_JAVA_COMPOSITOR
// We're paused, or we haven't been given a window-size yet, so do nothing
if (sCompositorPaused || gAndroidBounds.width <= 0 || gAndroidBounds.height <= 0) {
@ -1173,7 +1181,7 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
AndroidBridge::Bridge()->UnlockWindow(sNativeWindow);
} else if (AndroidBridge::Bridge()->HasNativeBitmapAccess()) {
jobject bitmap = sview.GetSoftwareDrawBitmap();
jobject bitmap = sview.GetSoftwareDrawBitmap(env, &jniFrame);
if (!bitmap) {
ALOG("no bitmap to draw into - skipping draw");
return;
@ -1202,16 +1210,12 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
AndroidBridge::Bridge()->UnlockBitmap(bitmap);
sview.Draw2D(bitmap, mBounds.width, mBounds.height);
} else {
jobject bytebuf = sview.GetSoftwareDrawBuffer();
jobject bytebuf = sview.GetSoftwareDrawBuffer(env, &jniFrame);
if (!bytebuf) {
ALOG("no buffer to draw into - skipping draw");
return;
}
JNIEnv *env = AndroidBridge::GetJNIEnv();
if (!env)
return;
void *buf = env->GetDirectBufferAddress(bytebuf);
int cap = env->GetDirectBufferCapacity(bytebuf);
if (!buf || cap != (mBounds.width * mBounds.height * 2)) {
@ -2219,39 +2223,50 @@ nsWindow::GetIMEUpdatePreference()
#ifdef MOZ_JAVA_COMPOSITOR
void
nsWindow::DrawWindowUnderlay(LayerManager* aManager, nsIntRect aRect) {
nsWindow::DrawWindowUnderlay(LayerManager* aManager, nsIntRect aRect)
{
JNIEnv *env = GetJNIForThread();
NS_ABORT_IF_FALSE(env, "No JNI environment at DrawWindowUnderlay()!");
if (!env)
return;
AndroidBridge::AutoLocalJNIFrame jniFrame(env);
AutoLocalJNIFrame jniFrame(env);
AndroidGeckoLayerClient& client = AndroidBridge::Bridge()->GetLayerClient();
client.CreateFrame(env, mLayerRendererFrame);
if (!client.CreateFrame(env, mLayerRendererFrame))
return;
client.ActivateProgram(env);
if (jniFrame.CheckForException()) return;
mLayerRendererFrame.BeginDrawing(env);
if (jniFrame.CheckForException()) return;
mLayerRendererFrame.DrawBackground(env);
if (jniFrame.CheckForException()) return;
client.DeactivateProgram(env);
}
void
nsWindow::DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect) {
nsWindow::DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect)
{
JNIEnv *env = GetJNIForThread();
NS_ABORT_IF_FALSE(env, "No JNI environment at DrawWindowOverlay()!");
if (!env)
return;
AndroidBridge::AutoLocalJNIFrame jniFrame(env);
AutoLocalJNIFrame jniFrame(env);
NS_ABORT_IF_FALSE(!mLayerRendererFrame.isNull(),
"Frame should have been created in DrawWindowUnderlay()!");
AndroidGeckoLayerClient& client = AndroidBridge::Bridge()->GetLayerClient();
client.ActivateProgram(env);
if (jniFrame.CheckForException()) return;
mLayerRendererFrame.DrawForeground(env);
if (jniFrame.CheckForException()) return;
mLayerRendererFrame.EndDrawing(env);
if (jniFrame.CheckForException()) return;
client.DeactivateProgram(env);
if (jniFrame.CheckForException()) return;
mLayerRendererFrame.Dispose(env);
}