summaryrefslogtreecommitdiffstats
path: root/content/browser/renderer_host/java/java_bound_object.cc
diff options
context:
space:
mode:
authorsteveblock@chromium.org <steveblock@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-26 23:22:23 +0000
committersteveblock@chromium.org <steveblock@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-26 23:22:23 +0000
commitd71a168fea36a3003e24da6b8223de83b0643691 (patch)
treee0a4a528f8eaa6c79f7082a256663aaabae9c7e3 /content/browser/renderer_host/java/java_bound_object.cc
parentec8ee1ff175f1b212d691cc225289d6d59b8017a (diff)
downloadchromium_src-d71a168fea36a3003e24da6b8223de83b0643691.zip
chromium_src-d71a168fea36a3003e24da6b8223de83b0643691.tar.gz
chromium_src-d71a168fea36a3003e24da6b8223de83b0643691.tar.bz2
Handle uncaught exceptions from methods called through the Java Bridge
If a method called on a Java object through the Java Bridge throws an uncaught exception, handle it native-side by clearing the exception to prevent a crash, and throwing a JavaScript exception. BUG=125194 Review URL: http://codereview.chromium.org/10239009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@134176 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/renderer_host/java/java_bound_object.cc')
-rw-r--r--content/browser/renderer_host/java/java_bound_object.cc80
1 files changed, 48 insertions, 32 deletions
diff --git a/content/browser/renderer_host/java/java_bound_object.cc b/content/browser/renderer_host/java/java_bound_object.cc
index c0d1aa5..ca2eb1a 100644
--- a/content/browser/renderer_host/java/java_bound_object.cc
+++ b/content/browser/renderer_host/java/java_bound_object.cc
@@ -114,82 +114,98 @@ bool JavaNPObject::GetProperty(NPObject* np_object,
return false;
}
-// Calls a Java method through JNI and returns the result as an NPVariant. Note
-// that this method does not do any type coercion. The Java return value is
-// simply converted to the corresponding NPAPI type.
-NPVariant CallJNIMethod(jobject object, const JavaType& return_type,
- jmethodID id, jvalue* parameters) {
+// Calls a Java method through JNI. If the Java method raises an uncaught
+// exception, it is cleared and this method returns false. Otherwise, this
+// method returns true and the Java method's return value is provided as an
+// NPVariant. Note that this method does not do any type coercion. The Java
+// return value is simply converted to the corresponding NPAPI type.
+bool CallJNIMethod(jobject object, const JavaType& return_type, jmethodID id,
+ jvalue* parameters, NPVariant* result) {
JNIEnv* env = AttachCurrentThread();
- NPVariant result;
switch (return_type.type) {
case JavaType::TypeBoolean:
BOOLEAN_TO_NPVARIANT(env->CallBooleanMethodA(object, id, parameters),
- result);
+ *result);
break;
case JavaType::TypeByte:
- INT32_TO_NPVARIANT(env->CallByteMethodA(object, id, parameters), result);
+ INT32_TO_NPVARIANT(env->CallByteMethodA(object, id, parameters), *result);
break;
case JavaType::TypeChar:
- INT32_TO_NPVARIANT(env->CallCharMethodA(object, id, parameters), result);
+ INT32_TO_NPVARIANT(env->CallCharMethodA(object, id, parameters), *result);
break;
case JavaType::TypeShort:
- INT32_TO_NPVARIANT(env->CallShortMethodA(object, id, parameters), result);
+ INT32_TO_NPVARIANT(env->CallShortMethodA(object, id, parameters),
+ *result);
break;
case JavaType::TypeInt:
- INT32_TO_NPVARIANT(env->CallIntMethodA(object, id, parameters), result);
+ INT32_TO_NPVARIANT(env->CallIntMethodA(object, id, parameters), *result);
break;
case JavaType::TypeLong:
- DOUBLE_TO_NPVARIANT(env->CallLongMethodA(object, id, parameters), result);
+ DOUBLE_TO_NPVARIANT(env->CallLongMethodA(object, id, parameters),
+ *result);
break;
case JavaType::TypeFloat:
DOUBLE_TO_NPVARIANT(env->CallFloatMethodA(object, id, parameters),
- result);
+ *result);
break;
case JavaType::TypeDouble:
DOUBLE_TO_NPVARIANT(env->CallDoubleMethodA(object, id, parameters),
- result);
+ *result);
break;
case JavaType::TypeVoid:
env->CallVoidMethodA(object, id, parameters);
- VOID_TO_NPVARIANT(result);
+ VOID_TO_NPVARIANT(*result);
break;
case JavaType::TypeArray:
// LIVECONNECT_COMPLIANCE: Existing behavior is to not call methods that
// return arrays. Spec requires calling the method and converting the
// result to a JavaScript array.
- VOID_TO_NPVARIANT(result);
+ VOID_TO_NPVARIANT(*result);
break;
case JavaType::TypeString: {
- ScopedJavaLocalRef<jstring> java_string(env, static_cast<jstring>(
- env->CallObjectMethodA(object, id, parameters)));
- if (!java_string.obj()) {
+ jstring java_string = static_cast<jstring>(
+ env->CallObjectMethodA(object, id, parameters));
+ // If an exception was raised, we must clear it before calling most JNI
+ // methods. ScopedJavaLocalRef is liable to make such calls, so we test
+ // first.
+ if (base::android::ClearException(env)) {
+ return false;
+ }
+ ScopedJavaLocalRef<jstring> scoped_java_string(env, java_string);
+ if (!scoped_java_string.obj()) {
// LIVECONNECT_COMPLIANCE: Existing behavior is to return undefined.
// Spec requires returning a null string.
- VOID_TO_NPVARIANT(result);
+ VOID_TO_NPVARIANT(*result);
break;
}
- std::string str = base::android::ConvertJavaStringToUTF8(java_string);
+ std::string str =
+ base::android::ConvertJavaStringToUTF8(scoped_java_string);
// Take a copy and pass ownership to the variant. We must allocate using
// NPN_MemAlloc, to match NPN_ReleaseVariant, which uses NPN_MemFree.
size_t length = str.length();
char* buffer = static_cast<char*>(NPN_MemAlloc(length));
str.copy(buffer, length, 0);
- STRINGN_TO_NPVARIANT(buffer, length, result);
+ STRINGN_TO_NPVARIANT(buffer, length, *result);
break;
}
case JavaType::TypeObject: {
- ScopedJavaLocalRef<jobject> java_object(
- env,
- env->CallObjectMethodA(object, id, parameters));
- if (!java_object.obj()) {
- NULL_TO_NPVARIANT(result);
+ // If an exception was raised, we must clear it before calling most JNI
+ // methods. ScopedJavaLocalRef is liable to make such calls, so we test
+ // first.
+ jobject java_object = env->CallObjectMethodA(object, id, parameters);
+ if (base::android::ClearException(env)) {
+ return false;
+ }
+ ScopedJavaLocalRef<jobject> scoped_java_object(env, java_object);
+ if (!scoped_java_object.obj()) {
+ NULL_TO_NPVARIANT(*result);
break;
}
- OBJECT_TO_NPVARIANT(JavaBoundObject::Create(java_object), result);
+ OBJECT_TO_NPVARIANT(JavaBoundObject::Create(scoped_java_object), *result);
break;
}
}
- return result;
+ return !base::android::ClearException(env);
}
jvalue CoerceJavaScriptNumberToJavaValue(const NPVariant& variant,
@@ -766,8 +782,8 @@ bool JavaBoundObject::Invoke(const std::string& name, const NPVariant* args,
}
// Call
- *result = CallJNIMethod(java_object_.obj(), method->return_type(),
- method->id(), &parameters[0]);
+ bool ok = CallJNIMethod(java_object_.obj(), method->return_type(),
+ method->id(), &parameters[0], result);
// Now that we're done with the jvalue, release any local references created
// by CoerceJavaScriptValueToJavaValue().
@@ -776,7 +792,7 @@ bool JavaBoundObject::Invoke(const std::string& name, const NPVariant* args,
ReleaseJavaValueIfRequired(env, &parameters[i], method->parameter_type(i));
}
- return true;
+ return ok;
}
void JavaBoundObject::EnsureMethodsAreSetUp() const {