Index: content/browser/renderer_host/java/java_bound_object.cc |
diff --git a/content/browser/renderer_host/java/java_bound_object.cc b/content/browser/renderer_host/java/java_bound_object.cc |
index a9f7920d1c036e2f2547724de8337f9e50a378ec..b5f7c70b978bc7b47847726ee1af19a3abd0e6b9 100644 |
--- a/content/browser/renderer_host/java/java_bound_object.cc |
+++ b/content/browser/renderer_host/java/java_bound_object.cc |
@@ -397,7 +397,10 @@ jobject CreateJavaArray(const JavaType& type, jsize length) { |
return NULL; |
} |
-// Note that this only handles primitive types and strings. |
+// Sets the specified element of the supplied array to the value of the |
+// supplied jvalue. Requires that the type of the array matches that of the |
+// jvalue. Handles only primitive types and strings. Note that in the case of a |
+// string, the array takes a new reference to the string object. |
void SetArrayElement(jobject array, |
const JavaType& type, |
jsize index, |
@@ -454,6 +457,7 @@ jvalue CoerceJavaScriptValueToJavaValue(const NPVariant& variant, |
const JavaType& target_type, |
bool coerce_to_string); |
+// Returns a new local reference to a Java array. |
jobject CoerceJavaScriptObjectToArray(const NPVariant& variant, |
const JavaType& target_type) { |
DCHECK_EQ(JavaType::TypeArray, target_type.type); |
@@ -498,8 +502,7 @@ jobject CoerceJavaScriptObjectToArray(const NPVariant& variant, |
return NULL; |
} |
- // Create the Java array. Note that we don't explicitly release the local |
- // ref to the result or any of its elements. |
+ // Create the Java array. |
// TODO(steveblock): Handle failure to create the array. |
jobject result = CreateJavaArray(target_inner_type, length); |
NPVariant value_variant; |
@@ -512,10 +515,19 @@ jobject CoerceJavaScriptObjectToArray(const NPVariant& variant, |
// value as JavaScript undefined. |
WebBindings::getProperty(0, object, WebBindings::getIntIdentifier(i), |
&value_variant); |
- SetArrayElement(result, target_inner_type, i, |
- CoerceJavaScriptValueToJavaValue(value_variant, |
- target_inner_type, |
- false)); |
+ jvalue element = CoerceJavaScriptValueToJavaValue(value_variant, |
+ target_inner_type, |
+ false); |
+ SetArrayElement(result, target_inner_type, i, element); |
+ // CoerceJavaScriptValueToJavaValue() creates new local references to |
+ // strings, objects and arrays. Of these, only strings can occur here. |
+ // SetArrayElement() causes the array to take its own reference to the |
+ // string, so we can now release the local reference. |
+ DCHECK_NE(JavaType::TypeObject, target_inner_type.type); |
+ DCHECK_NE(JavaType::TypeArray, target_inner_type.type); |
+ if (target_inner_type.type == JavaType::TypeString) { |
+ AttachCurrentThread()->DeleteLocalRef(element.l); |
joth
2012/03/22 12:42:12
nit: Grab the JNIEnv* outside the loop.
Steve Block
2012/03/22 13:03:23
Done.
|
+ } |
WebBindings::releaseVariantValue(&value_variant); |
} |
@@ -644,15 +656,16 @@ jvalue CoerceJavaScriptNullOrUndefinedToJavaValue(const NPVariant& variant, |
// strings when required, rather than simply converting to NULL. This is used |
// to maintain current behaviour, which differs slightly depending upon whether |
// or not the coercion in question is for an array element. |
+// |
+// Note that the jvalue returned by this method may contain a new local |
+// reference to an object (string, object or array). This must be released by |
+// the caller. |
jvalue CoerceJavaScriptValueToJavaValue(const NPVariant& variant, |
const JavaType& target_type, |
bool coerce_to_string) { |
// Note that in all these conversions, the relevant field of the jvalue must |
// always be explicitly set, as jvalue does not initialize its fields. |
- // Some of these methods create new Java Strings. Note that we don't |
- // explicitly release the local ref to these new objects, as there's no simple |
- // way to do so. |
switch (variant.type) { |
case NPVariantType_Int32: |
case NPVariantType_Double: |
@@ -745,6 +758,17 @@ bool JavaBoundObject::Invoke(const std::string& name, const NPVariant* args, |
// Call |
*result = CallJNIMethod(java_object_.obj(), method->return_type(), |
method->id(), ¶meters[0]); |
+ |
+ // Now that we're done with the jvalue, release any local references created |
+ // by CoerceJavaScriptValueToJavaValue(). |
+ for (size_t i = 0; i < arg_count; ++i) { |
+ if (method->parameter_type(i).type == JavaType::TypeString || |
+ method->parameter_type(i).type == JavaType::TypeObject || |
+ method->parameter_type(i).type == JavaType::TypeArray) { |
+ AttachCurrentThread()->DeleteLocalRef(parameters[i].l); |
+ } |
joth
2012/03/22 12:42:12
to make it a bit more self documenting, how about
Steve Block
2012/03/22 13:03:23
Done.
|
+ } |
+ |
return true; |
} |