Bug 984458 - f. Add NativeJSObject opt getters; r=blassey
authorJim Chen <nchen@mozilla.com>
Tue, 01 Apr 2014 15:16:56 -0400
changeset 176554 99a8ea57ec6580caf24130c883546e9810e58e26
parent 176553 1c7f49db0b096e8a558496d8e2c7e7a5a621b765
child 176555 d86d8ac76b25041018a6002eb0f10c55d970e325
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersblassey
bugs984458
milestone31.0a1
Bug 984458 - f. Add NativeJSObject opt getters; r=blassey
mobile/android/base/util/NativeJSObject.java
mozglue/android/jni-stubs.inc
widget/android/NativeJSContainer.cpp
--- a/mobile/android/base/util/NativeJSObject.java
+++ b/mobile/android/base/util/NativeJSObject.java
@@ -39,80 +39,170 @@ public class NativeJSObject
      * @throws IllegalThreadStateException
      *         If not called on the thread this object is attached to
      * @throws UnsupportedOperationException
      *         If an internal JSAPI call failed
      */
     public native boolean getBoolean(String name);
 
     /**
+     * Returns the value of a boolean property.
+     *
+     * @param name
+     *        Property name
+     * @param fallback
+     *        Value to return if property does not exist
+     * @throws IllegalArgumentException
+     *         If the property exists and its type does not match the return type
+     * @throws NullPointerException
+     *         If name is null or if this JS object has been disposed
+     * @throws IllegalThreadStateException
+     *         If not called on the thread this object is attached to
+     * @throws UnsupportedOperationException
+     *         If an internal JSAPI call failed
+     */
+    public native boolean optBoolean(String name, boolean fallback);
+
+    /**
      * Returns the value of a double property.
      *
      * @param name
      *        Property name
      * @throws IllegalArgumentException
      *         If the property does not exist or if its type does not match the return type
      * @throws NullPointerException
      *         If name is null or if this JS object has been disposed
      * @throws IllegalThreadStateException
      *         If not called on the thread this object is attached to
      * @throws UnsupportedOperationException
      *         If an internal JSAPI call failed
      */
     public native double getDouble(String name);
 
     /**
+     * Returns the value of a double property.
+     *
+     * @param name
+     *        Property name
+     * @param fallback
+     *        Value to return if property does not exist
+     * @throws IllegalArgumentException
+     *         If the property exists and its type does not match the return type
+     * @throws NullPointerException
+     *         If name is null or if this JS object has been disposed
+     * @throws IllegalThreadStateException
+     *         If not called on the thread this object is attached to
+     * @throws UnsupportedOperationException
+     *         If an internal JSAPI call failed
+     */
+    public native double optDouble(String name, double fallback);
+
+    /**
      * Returns the value of an int property.
      *
      * @param name
      *        Property name
      * @throws IllegalArgumentException
      *         If the property does not exist or if its type does not match the return type
      * @throws NullPointerException
      *         If name is null or if this JS object has been disposed
      * @throws IllegalThreadStateException
      *         If not called on the thread this object is attached to
      * @throws UnsupportedOperationException
      *         If an internal JSAPI call failed
      */
     public native int getInt(String name);
 
     /**
+     * Returns the value of an int property.
+     *
+     * @param name
+     *        Property name
+     * @param fallback
+     *        Value to return if property does not exist
+     * @throws IllegalArgumentException
+     *         If the property exists and its type does not match the return type
+     * @throws NullPointerException
+     *         If name is null or if this JS object has been disposed
+     * @throws IllegalThreadStateException
+     *         If not called on the thread this object is attached to
+     * @throws UnsupportedOperationException
+     *         If an internal JSAPI call failed
+     */
+    public native int optInt(String name, int fallback);
+
+    /**
      * Returns the value of an object property.
      *
      * @param name
      *        Property name
      * @throws IllegalArgumentException
      *         If the property does not exist or if its type does not match the return type
      * @throws NullPointerException
      *         If name is null or if this JS object has been disposed
      * @throws IllegalThreadStateException
      *         If not called on the thread this object is attached to
      * @throws UnsupportedOperationException
      *         If an internal JSAPI call failed
      */
     public native NativeJSObject getObject(String name);
 
     /**
+     * Returns the value of an object property.
+     *
+     * @param name
+     *        Property name
+     * @param fallback
+     *        Value to return if property does not exist
+     * @throws IllegalArgumentException
+     *         If the property exists and its type does not match the return type
+     * @throws NullPointerException
+     *         If name is null or if this JS object has been disposed
+     * @throws IllegalThreadStateException
+     *         If not called on the thread this object is attached to
+     * @throws UnsupportedOperationException
+     *         If an internal JSAPI call failed
+     */
+    public native NativeJSObject optObject(String name, NativeJSObject fallback);
+
+    /**
      * Returns the value of a string property.
      *
      * @param name
      *        Property name
      * @throws IllegalArgumentException
      *         If the property does not exist or if its type does not match the return type
      * @throws NullPointerException
      *         If name is null or if this JS object has been disposed
      * @throws IllegalThreadStateException
      *         If not called on the thread this object is attached to
      * @throws UnsupportedOperationException
      *         If an internal JSAPI call failed
      */
     public native String getString(String name);
 
     /**
+     * Returns the value of a string property.
+     *
+     * @param name
+     *        Property name
+     * @param fallback
+     *        Value to return if property does not exist
+     * @throws IllegalArgumentException
+     *         If the property exists and its type does not match the return type
+     * @throws NullPointerException
+     *         If name is null or if this JS object has been disposed
+     * @throws IllegalThreadStateException
+     *         If not called on the thread this object is attached to
+     * @throws UnsupportedOperationException
+     *         If an internal JSAPI call failed
+     */
+    public native String optString(String name, String fallback);
+
+    /**
      * Returns whether a property exists in this object
      *
      * @param name
      *        Property name
      * @throws NullPointerException
      *         If name is null or if this JS object has been disposed
      * @throws IllegalThreadStateException
      *         If not called on the thread this object is attached to
--- a/mozglue/android/jni-stubs.inc
+++ b/mozglue/android/jni-stubs.inc
@@ -623,16 +623,35 @@ Java_org_mozilla_gecko_util_NativeJSObje
 #endif
 
 #ifdef JNI_BINDINGS
   xul_dlsym("Java_org_mozilla_gecko_util_NativeJSObject_getBoolean", &f_Java_org_mozilla_gecko_util_NativeJSObject_getBoolean);
 #endif
 
 #ifdef JNI_STUBS
 
+typedef jboolean (*Java_org_mozilla_gecko_util_NativeJSObject_optBoolean_t)(JNIEnv *, jobject, jstring, jboolean);
+static Java_org_mozilla_gecko_util_NativeJSObject_optBoolean_t f_Java_org_mozilla_gecko_util_NativeJSObject_optBoolean;
+extern "C" NS_EXPORT jboolean JNICALL
+Java_org_mozilla_gecko_util_NativeJSObject_optBoolean(JNIEnv * arg0, jobject arg1, jstring arg2, jboolean arg3) {
+    if (!f_Java_org_mozilla_gecko_util_NativeJSObject_optBoolean) {
+        arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
+                       "JNI Function called before it was loaded");
+        return false;
+    }
+    return f_Java_org_mozilla_gecko_util_NativeJSObject_optBoolean(arg0, arg1, arg2, arg3);
+}
+#endif
+
+#ifdef JNI_BINDINGS
+  xul_dlsym("Java_org_mozilla_gecko_util_NativeJSObject_optBoolean", &f_Java_org_mozilla_gecko_util_NativeJSObject_optBoolean);
+#endif
+
+#ifdef JNI_STUBS
+
 typedef jdouble (*Java_org_mozilla_gecko_util_NativeJSObject_getDouble_t)(JNIEnv *, jobject, jstring);
 static Java_org_mozilla_gecko_util_NativeJSObject_getDouble_t f_Java_org_mozilla_gecko_util_NativeJSObject_getDouble;
 extern "C" NS_EXPORT jdouble JNICALL
 Java_org_mozilla_gecko_util_NativeJSObject_getDouble(JNIEnv * arg0, jobject arg1, jstring arg2) {
     if (!f_Java_org_mozilla_gecko_util_NativeJSObject_getDouble) {
         arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
                        "JNI Function called before it was loaded");
         return 0;
@@ -642,16 +661,35 @@ Java_org_mozilla_gecko_util_NativeJSObje
 #endif
 
 #ifdef JNI_BINDINGS
   xul_dlsym("Java_org_mozilla_gecko_util_NativeJSObject_getDouble", &f_Java_org_mozilla_gecko_util_NativeJSObject_getDouble);
 #endif
 
 #ifdef JNI_STUBS
 
+typedef jdouble (*Java_org_mozilla_gecko_util_NativeJSObject_optDouble_t)(JNIEnv *, jobject, jstring, jdouble);
+static Java_org_mozilla_gecko_util_NativeJSObject_optDouble_t f_Java_org_mozilla_gecko_util_NativeJSObject_optDouble;
+extern "C" NS_EXPORT jdouble JNICALL
+Java_org_mozilla_gecko_util_NativeJSObject_optDouble(JNIEnv * arg0, jobject arg1, jstring arg2, jdouble arg3) {
+    if (!f_Java_org_mozilla_gecko_util_NativeJSObject_optDouble) {
+        arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
+                       "JNI Function called before it was loaded");
+        return 0;
+    }
+    return f_Java_org_mozilla_gecko_util_NativeJSObject_optDouble(arg0, arg1, arg2, arg3);
+}
+#endif
+
+#ifdef JNI_BINDINGS
+  xul_dlsym("Java_org_mozilla_gecko_util_NativeJSObject_optDouble", &f_Java_org_mozilla_gecko_util_NativeJSObject_optDouble);
+#endif
+
+#ifdef JNI_STUBS
+
 typedef jint (*Java_org_mozilla_gecko_util_NativeJSObject_getInt_t)(JNIEnv *, jobject, jstring);
 static Java_org_mozilla_gecko_util_NativeJSObject_getInt_t f_Java_org_mozilla_gecko_util_NativeJSObject_getInt;
 extern "C" NS_EXPORT jint JNICALL
 Java_org_mozilla_gecko_util_NativeJSObject_getInt(JNIEnv * arg0, jobject arg1, jstring arg2) {
     if (!f_Java_org_mozilla_gecko_util_NativeJSObject_getInt) {
         arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
                        "JNI Function called before it was loaded");
         return 0;
@@ -661,16 +699,35 @@ Java_org_mozilla_gecko_util_NativeJSObje
 #endif
 
 #ifdef JNI_BINDINGS
   xul_dlsym("Java_org_mozilla_gecko_util_NativeJSObject_getInt", &f_Java_org_mozilla_gecko_util_NativeJSObject_getInt);
 #endif
 
 #ifdef JNI_STUBS
 
+typedef jint (*Java_org_mozilla_gecko_util_NativeJSObject_optInt_t)(JNIEnv *, jobject, jstring, jint);
+static Java_org_mozilla_gecko_util_NativeJSObject_optInt_t f_Java_org_mozilla_gecko_util_NativeJSObject_optInt;
+extern "C" NS_EXPORT jint JNICALL
+Java_org_mozilla_gecko_util_NativeJSObject_optInt(JNIEnv * arg0, jobject arg1, jstring arg2, jint arg3) {
+    if (!f_Java_org_mozilla_gecko_util_NativeJSObject_optInt) {
+        arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
+                       "JNI Function called before it was loaded");
+        return 0;
+    }
+    return f_Java_org_mozilla_gecko_util_NativeJSObject_optInt(arg0, arg1, arg2, arg3);
+}
+#endif
+
+#ifdef JNI_BINDINGS
+  xul_dlsym("Java_org_mozilla_gecko_util_NativeJSObject_optInt", &f_Java_org_mozilla_gecko_util_NativeJSObject_optInt);
+#endif
+
+#ifdef JNI_STUBS
+
 typedef jobject (*Java_org_mozilla_gecko_util_NativeJSObject_getObject_t)(JNIEnv *, jobject, jstring);
 static Java_org_mozilla_gecko_util_NativeJSObject_getObject_t f_Java_org_mozilla_gecko_util_NativeJSObject_getObject;
 extern "C" NS_EXPORT jobject JNICALL
 Java_org_mozilla_gecko_util_NativeJSObject_getObject(JNIEnv * arg0, jobject arg1, jstring arg2) {
     if (!f_Java_org_mozilla_gecko_util_NativeJSObject_getObject) {
         arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
                        "JNI Function called before it was loaded");
         return nullptr;
@@ -680,16 +737,35 @@ Java_org_mozilla_gecko_util_NativeJSObje
 #endif
 
 #ifdef JNI_BINDINGS
   xul_dlsym("Java_org_mozilla_gecko_util_NativeJSObject_getObject", &f_Java_org_mozilla_gecko_util_NativeJSObject_getObject);
 #endif
 
 #ifdef JNI_STUBS
 
+typedef jobject (*Java_org_mozilla_gecko_util_NativeJSObject_optObject_t)(JNIEnv *, jobject, jstring, jobject);
+static Java_org_mozilla_gecko_util_NativeJSObject_optObject_t f_Java_org_mozilla_gecko_util_NativeJSObject_optObject;
+extern "C" NS_EXPORT jobject JNICALL
+Java_org_mozilla_gecko_util_NativeJSObject_optObject(JNIEnv * arg0, jobject arg1, jstring arg2, jobject arg3) {
+    if (!f_Java_org_mozilla_gecko_util_NativeJSObject_optObject) {
+        arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
+                       "JNI Function called before it was loaded");
+        return nullptr;
+    }
+    return f_Java_org_mozilla_gecko_util_NativeJSObject_optObject(arg0, arg1, arg2, arg3);
+}
+#endif
+
+#ifdef JNI_BINDINGS
+  xul_dlsym("Java_org_mozilla_gecko_util_NativeJSObject_optObject", &f_Java_org_mozilla_gecko_util_NativeJSObject_optObject);
+#endif
+
+#ifdef JNI_STUBS
+
 typedef jstring (*Java_org_mozilla_gecko_util_NativeJSObject_getString_t)(JNIEnv *, jobject, jstring);
 static Java_org_mozilla_gecko_util_NativeJSObject_getString_t f_Java_org_mozilla_gecko_util_NativeJSObject_getString;
 extern "C" NS_EXPORT jstring JNICALL
 Java_org_mozilla_gecko_util_NativeJSObject_getString(JNIEnv * arg0, jobject arg1, jstring arg2) {
     if (!f_Java_org_mozilla_gecko_util_NativeJSObject_getString) {
         arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
                        "JNI Function called before it was loaded");
         return nullptr;
@@ -699,16 +775,35 @@ Java_org_mozilla_gecko_util_NativeJSObje
 #endif
 
 #ifdef JNI_BINDINGS
   xul_dlsym("Java_org_mozilla_gecko_util_NativeJSObject_getString", &f_Java_org_mozilla_gecko_util_NativeJSObject_getString);
 #endif
 
 #ifdef JNI_STUBS
 
+typedef jstring (*Java_org_mozilla_gecko_util_NativeJSObject_optString_t)(JNIEnv *, jobject, jstring, jstring);
+static Java_org_mozilla_gecko_util_NativeJSObject_optString_t f_Java_org_mozilla_gecko_util_NativeJSObject_optString;
+extern "C" NS_EXPORT jstring JNICALL
+Java_org_mozilla_gecko_util_NativeJSObject_optString(JNIEnv * arg0, jobject arg1, jstring arg2, jstring arg3) {
+    if (!f_Java_org_mozilla_gecko_util_NativeJSObject_optString) {
+        arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
+                       "JNI Function called before it was loaded");
+        return nullptr;
+    }
+    return f_Java_org_mozilla_gecko_util_NativeJSObject_optString(arg0, arg1, arg2, arg3);
+}
+#endif
+
+#ifdef JNI_BINDINGS
+  xul_dlsym("Java_org_mozilla_gecko_util_NativeJSObject_optString", &f_Java_org_mozilla_gecko_util_NativeJSObject_optString);
+#endif
+
+#ifdef JNI_STUBS
+
 typedef jboolean (*Java_org_mozilla_gecko_util_NativeJSObject_has_t)(JNIEnv *, jobject, jstring);
 static Java_org_mozilla_gecko_util_NativeJSObject_has_t f_Java_org_mozilla_gecko_util_NativeJSObject_has;
 extern "C" NS_EXPORT jboolean JNICALL
 Java_org_mozilla_gecko_util_NativeJSObject_has(JNIEnv * arg0, jobject arg1, jstring arg2) {
     if (!f_Java_org_mozilla_gecko_util_NativeJSObject_has) {
         arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
                        "JNI Function called before it was loaded");
         return false;
--- a/widget/android/NativeJSContainer.cpp
+++ b/widget/android/NativeJSContainer.cpp
@@ -401,44 +401,59 @@ struct HasProperty
     typedef jboolean Type;
 
     static bool InValue(JS::HandleValue val) {
         return true;
     }
 
     static Type FromValue(JNIEnv* env, jobject instance,
                           JSContext* cx, JS::HandleValue val) {
-        return JSVAL_IS_VOID(val) ? JNI_TRUE : JNI_FALSE;
+        return JNI_TRUE;
     }
 };
 
+MOZ_BEGIN_ENUM_CLASS(FallbackOption)
+    THROW,
+    RETURN,
+MOZ_END_ENUM_CLASS(FallbackOption)
+
 template <class Property>
 typename Property::Type
-GetProperty(JNIEnv* env, jobject instance, jstring name) {
+GetProperty(JNIEnv* env, jobject instance, jstring name,
+            FallbackOption option = FallbackOption::THROW,
+            typename Property::Type fallback = typename Property::Type()) {
     MOZ_ASSERT(env);
     MOZ_ASSERT(instance);
 
     JSContext* const cx =
         NativeJSContainer::GetContextFromObject(env, instance);
     const JS::RootedObject object(cx,
         NativeJSContainer::GetObjectFromObject(env, instance));
     const JSJNIString strName(env, name);
     JS::RootedValue val(cx);
 
     if (!object ||
         !CheckJNIArgument(env, name) ||
         !CheckJSCall(env,
             JS_GetUCProperty(cx, object, strName, strName.Length(), &val))) {
         return typename Property::Type();
     }
+    if (val.isUndefined()) {
+        if (option == FallbackOption::THROW) {
+            AndroidBridge::ThrowException(env,
+                "java/lang/IllegalArgumentException",
+                "Property does not exist");
+        }
+        return fallback;
+    }
     if (!Property::InValue(val)) {
         AndroidBridge::ThrowException(env,
             "java/lang/IllegalArgumentException",
-            "Property does not exist or type mismatch");
-        return typename Property::Type();
+            "Property type mismatch");
+        return fallback;
     }
     return Property::FromValue(env, instance, cx, val);
 }
 
 } // namespace
 
 extern "C" {
 
@@ -457,44 +472,79 @@ Java_org_mozilla_gecko_util_NativeJSCont
 }
 
 NS_EXPORT jboolean JNICALL
 Java_org_mozilla_gecko_util_NativeJSObject_getBoolean(JNIEnv* env, jobject instance, jstring name)
 {
     return GetProperty<BooleanProperty>(env, instance, name);
 }
 
+NS_EXPORT jboolean JNICALL
+Java_org_mozilla_gecko_util_NativeJSObject_optBoolean(JNIEnv* env, jobject instance,
+                                                      jstring name, jboolean fallback)
+{
+    return GetProperty<BooleanProperty>(env, instance, name, FallbackOption::RETURN, fallback);
+}
+
 NS_EXPORT jdouble JNICALL
 Java_org_mozilla_gecko_util_NativeJSObject_getDouble(JNIEnv* env, jobject instance, jstring name)
 {
     return GetProperty<DoubleProperty>(env, instance, name);
 }
 
+NS_EXPORT jdouble JNICALL
+Java_org_mozilla_gecko_util_NativeJSObject_optDouble(JNIEnv* env, jobject instance,
+                                                     jstring name, jdouble fallback)
+{
+    return GetProperty<DoubleProperty>(env, instance, name, FallbackOption::RETURN, fallback);
+}
+
 NS_EXPORT jint JNICALL
 Java_org_mozilla_gecko_util_NativeJSObject_getInt(JNIEnv* env, jobject instance, jstring name)
 {
     return GetProperty<IntProperty>(env, instance, name);
 }
 
+NS_EXPORT jint JNICALL
+Java_org_mozilla_gecko_util_NativeJSObject_optInt(JNIEnv* env, jobject instance,
+                                                  jstring name, jint fallback)
+{
+    return GetProperty<IntProperty>(env, instance, name, FallbackOption::RETURN, fallback);
+}
+
 NS_EXPORT jobject JNICALL
 Java_org_mozilla_gecko_util_NativeJSObject_getObject(JNIEnv* env, jobject instance, jstring name)
 {
     return GetProperty<ObjectProperty>(env, instance, name);
 }
 
+NS_EXPORT jobject JNICALL
+Java_org_mozilla_gecko_util_NativeJSObject_optObject(JNIEnv* env, jobject instance,
+                                                     jstring name, jobject fallback)
+{
+    return GetProperty<ObjectProperty>(env, instance, name, FallbackOption::RETURN, fallback);
+}
+
 NS_EXPORT jstring JNICALL
 Java_org_mozilla_gecko_util_NativeJSObject_getString(JNIEnv* env, jobject instance, jstring name)
 {
     return GetProperty<StringProperty>(env, instance, name);
 }
 
+NS_EXPORT jstring JNICALL
+Java_org_mozilla_gecko_util_NativeJSObject_optString(JNIEnv* env, jobject instance,
+                                                     jstring name, jstring fallback)
+{
+    return GetProperty<StringProperty>(env, instance, name, FallbackOption::RETURN, fallback);
+}
+
 NS_EXPORT jboolean JNICALL
 Java_org_mozilla_gecko_util_NativeJSObject_has(JNIEnv* env, jobject instance, jstring name)
 {
-    return GetProperty<HasProperty>(env, instance, name);
+    return GetProperty<HasProperty>(env, instance, name, FallbackOption::RETURN, JNI_FALSE);
 }
 
 NS_EXPORT jstring JNICALL
 Java_org_mozilla_gecko_util_NativeJSObject_toString(JNIEnv* env, jobject instance)
 {
     MOZ_ASSERT(env);
     MOZ_ASSERT(instance);