diff --git a/widget/android/AndroidBridge.cpp b/widget/android/AndroidBridge.cpp index 26101286a12d..eb4799a8784c 100644 --- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -179,47 +179,52 @@ AndroidBridge::Init(JNIEnv *jEnv) mHasNativeWindowAccess = false; mHasNativeWindowFallback = false; - initInit(); - #ifdef MOZ_WEBSMS_BACKEND - mAndroidSmsMessageClass = getClassGlobalRef("android/telephony/SmsMessage"); - jCalculateLength = getStaticMethod("calculateLength", "(Ljava/lang/CharSequence;Z)[I"); + AutoJNIClass smsMessage(jEnv, "android/telephony/SmsMessage"); + mAndroidSmsMessageClass = smsMessage.getGlobalRef(); + jCalculateLength = smsMessage.getStaticMethod("calculateLength", "(Ljava/lang/CharSequence;Z)[I"); #endif - jStringClass = getClassGlobalRef("java/lang/String"); + AutoJNIClass string(jEnv, "java/lang/String"); + jStringClass = string.getGlobalRef(); if (!GetStaticIntField("android/os/Build$VERSION", "SDK_INT", &mAPIVersion, jEnv)) { ALOG_BRIDGE("Failed to find API version"); } - jSurfaceClass = getClassGlobalRef("android/view/Surface"); + AutoJNIClass surface(jEnv, "android/view/Surface"); + jSurfaceClass = surface.getGlobalRef(); if (mAPIVersion <= 8 /* Froyo */) { - jSurfacePointerField = getField("mSurface", "I"); + jSurfacePointerField = surface.getField("mSurface", "I"); } else if (mAPIVersion > 8 && mAPIVersion < 19 /* KitKat */) { - jSurfacePointerField = getField("mNativeSurface", "I"); + jSurfacePointerField = surface.getField("mNativeSurface", "I"); } else { // We don't know how to get this, just set it to 0 jSurfacePointerField = 0; } - jclass eglClass = getClassGlobalRef("com/google/android/gles_jni/EGLSurfaceImpl"); + AutoJNIClass egl(jEnv, "com/google/android/gles_jni/EGLSurfaceImpl"); + jclass eglClass = egl.getGlobalRef(); if (eglClass) { // The pointer type moved to a 'long' in Android L, API version 20 const char* jniType = mAPIVersion >= 20 ? "J" : "I"; - jEGLSurfacePointerField = getField("mEGLSurface", jniType); + jEGLSurfacePointerField = egl.getField("mEGLSurface", jniType); } else { jEGLSurfacePointerField = 0; } - jChannels = getClassGlobalRef("java/nio/channels/Channels"); - jChannelCreate = jEnv->GetStaticMethodID(jChannels, "newChannel", "(Ljava/io/InputStream;)Ljava/nio/channels/ReadableByteChannel;"); + AutoJNIClass channels(jEnv, "java/nio/channels/Channels"); + jChannels = channels.getGlobalRef(); + jChannelCreate = channels.getStaticMethod("newChannel", "(Ljava/io/InputStream;)Ljava/nio/channels/ReadableByteChannel;"); - jReadableByteChannel = getClassGlobalRef("java/nio/channels/ReadableByteChannel"); - jByteBufferRead = jEnv->GetMethodID(jReadableByteChannel, "read", "(Ljava/nio/ByteBuffer;)I"); + AutoJNIClass readableByteChannel(jEnv, "java/nio/channels/ReadableByteChannel"); + jReadableByteChannel = readableByteChannel.getGlobalRef(); + jByteBufferRead = readableByteChannel.getMethod("read", "(Ljava/nio/ByteBuffer;)I"); - jInputStream = getClassGlobalRef("java/io/InputStream"); - jClose = jEnv->GetMethodID(jInputStream, "close", "()V"); - jAvailable = jEnv->GetMethodID(jInputStream, "available", "()I"); + AutoJNIClass inputStream(jEnv, "java/io/InputStream"); + jInputStream = inputStream.getGlobalRef(); + jClose = inputStream.getMethod("close", "()V"); + jAvailable = inputStream.getMethod("available", "()I"); InitAndroidJavaWrappers(jEnv); @@ -767,18 +772,14 @@ AndroidBridge::GetStaticIntField(const char *className, const char *fieldName, i jEnv = GetJNIEnv(); } - initInit(); - getClassGlobalRef(className); - jfieldID field = getStaticField(fieldName, "I"); + AutoJNIClass cls(jEnv, className); + jfieldID field = cls.getStaticField(fieldName, "I"); if (!field) { - jEnv->DeleteGlobalRef(jClass); return false; } - *aInt = static_cast(jEnv->GetStaticIntField(jClass, field)); - - jEnv->DeleteGlobalRef(jClass); + *aInt = static_cast(jEnv->GetStaticIntField(cls.getRawRef(), field)); return true; } @@ -795,17 +796,14 @@ AndroidBridge::GetStaticStringField(const char *className, const char *fieldName } AutoLocalJNIFrame jniFrame(jEnv, 1); - initInit(); - getClassGlobalRef(className); - jfieldID field = getStaticField(fieldName, "Ljava/lang/String;"); + AutoJNIClass cls(jEnv, className); + jfieldID field = cls.getStaticField(fieldName, "Ljava/lang/String;"); if (!field) { - jEnv->DeleteGlobalRef(jClass); return false; } - jstring jstr = (jstring) jEnv->GetStaticObjectField(jClass, field); - jEnv->DeleteGlobalRef(jClass); + jstring jstr = (jstring) jEnv->GetStaticObjectField(cls.getRawRef(), field); if (!jstr) return false; diff --git a/widget/android/AndroidBridge.h b/widget/android/AndroidBridge.h index 37da66443582..e14720d54abf 100644 --- a/widget/android/AndroidBridge.h +++ b/widget/android/AndroidBridge.h @@ -451,6 +451,46 @@ public: int64_t RunDelayedUiThreadTasks(); }; +class AutoJNIClass { +private: + JNIEnv* const mEnv; + const jclass mClass; + +public: + AutoJNIClass(JNIEnv* jEnv, const char* name) + : mEnv(jEnv) + , mClass(AndroidBridge::GetClassGlobalRef(jEnv, name)) + {} + + ~AutoJNIClass() { + mEnv->DeleteGlobalRef(mClass); + } + + jclass getRawRef() const { + return mClass; + } + + jclass getGlobalRef() const { + return static_cast(mEnv->NewGlobalRef(mClass)); + } + + jfieldID getField(const char* name, const char* type) const { + return AndroidBridge::GetFieldID(mEnv, mClass, name, type); + } + + jfieldID getStaticField(const char* name, const char* type) const { + return AndroidBridge::GetStaticFieldID(mEnv, mClass, name, type); + } + + jmethodID getMethod(const char* name, const char* type) const { + return AndroidBridge::GetMethodID(mEnv, mClass, name, type); + } + + jmethodID getStaticMethod(const char* name, const char* type) const { + return AndroidBridge::GetStaticMethodID(mEnv, mClass, name, type); + } +}; + class AutoJObject { public: AutoJObject(JNIEnv* aJNIEnv = nullptr) : mObject(nullptr) diff --git a/widget/android/AndroidBridgeUtilities.h b/widget/android/AndroidBridgeUtilities.h index 88ddc40ff1c4..ca8326281bae 100644 --- a/widget/android/AndroidBridgeUtilities.h +++ b/widget/android/AndroidBridgeUtilities.h @@ -1,23 +1,3 @@ -// A collection of macros to simplify getting class and method references from Java. - -#define initInit() jclass jClass - -// note that this also sets jClass -#define getClassGlobalRef(cname) \ - (jClass = AndroidBridge::GetClassGlobalRef(jEnv, cname)) - -#define getField(fname, ftype) \ - AndroidBridge::GetFieldID(jEnv, jClass, fname, ftype) - -#define getMethod(fname, ftype) \ - AndroidBridge::GetMethodID(jEnv, jClass, fname, ftype) - -#define getStaticField(fname, ftype) \ - AndroidBridge::GetStaticFieldID(jEnv, jClass, fname, ftype) - -#define getStaticMethod(fname, ftype) \ - AndroidBridge::GetStaticMethodID(jEnv, jClass, fname, ftype) - #ifndef ALOG #if defined(DEBUG) || defined(FORCE_ALOG) #define ALOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gecko" , ## args) diff --git a/widget/android/AndroidJavaWrappers.cpp b/widget/android/AndroidJavaWrappers.cpp index b22e9f07a4ca..dc583826557f 100644 --- a/widget/android/AndroidJavaWrappers.cpp +++ b/widget/android/AndroidJavaWrappers.cpp @@ -128,82 +128,81 @@ mozilla::InitAndroidJavaWrappers(JNIEnv *jEnv) void AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv) { - initInit(); + AutoJNIClass geckoEvent(jEnv, "org/mozilla/gecko/GeckoEvent"); + jGeckoEventClass = geckoEvent.getGlobalRef(); - jGeckoEventClass = getClassGlobalRef("org/mozilla/gecko/GeckoEvent"); + jActionField = geckoEvent.getField("mAction", "I"); + jTypeField = geckoEvent.getField("mType", "I"); + jAckNeededField = geckoEvent.getField("mAckNeeded", "Z"); + jTimeField = geckoEvent.getField("mTime", "J"); + jPoints = geckoEvent.getField("mPoints", "[Landroid/graphics/Point;"); + jPointIndicies = geckoEvent.getField("mPointIndicies", "[I"); + jOrientations = geckoEvent.getField("mOrientations", "[F"); + jPressures = geckoEvent.getField("mPressures", "[F"); + jToolTypes = geckoEvent.getField("mToolTypes", "[I"); + jPointRadii = geckoEvent.getField("mPointRadii", "[Landroid/graphics/Point;"); + jXField = geckoEvent.getField("mX", "D"); + jYField = geckoEvent.getField("mY", "D"); + jZField = geckoEvent.getField("mZ", "D"); + jRectField = geckoEvent.getField("mRect", "Landroid/graphics/Rect;"); - jActionField = getField("mAction", "I"); - jTypeField = getField("mType", "I"); - jAckNeededField = getField("mAckNeeded", "Z"); - jTimeField = getField("mTime", "J"); - jPoints = getField("mPoints", "[Landroid/graphics/Point;"); - jPointIndicies = getField("mPointIndicies", "[I"); - jOrientations = getField("mOrientations", "[F"); - jPressures = getField("mPressures", "[F"); - jToolTypes = getField("mToolTypes", "[I"); - jPointRadii = getField("mPointRadii", "[Landroid/graphics/Point;"); - jXField = getField("mX", "D"); - jYField = getField("mY", "D"); - jZField = getField("mZ", "D"); - jRectField = getField("mRect", "Landroid/graphics/Rect;"); - - jCharactersField = getField("mCharacters", "Ljava/lang/String;"); - jCharactersExtraField = getField("mCharactersExtra", "Ljava/lang/String;"); - jDataField = getField("mData", "Ljava/lang/String;"); - jKeyCodeField = getField("mKeyCode", "I"); - jScanCodeField = getField("mScanCode", "I"); - jMetaStateField = getField("mMetaState", "I"); - jDomKeyLocationField = getField("mDomKeyLocation", "Lorg/mozilla/gecko/GeckoEvent$DomKeyLocation;"); - jFlagsField = getField("mFlags", "I"); - jUnicodeCharField = getField("mUnicodeChar", "I"); - jBaseUnicodeCharField = getField("mBaseUnicodeChar", "I"); - jDOMPrintableKeyValueField = getField("mDOMPrintableKeyValue", "I"); - jRepeatCountField = getField("mRepeatCount", "I"); - jCountField = getField("mCount", "I"); - jStartField = getField("mStart", "I"); - jEndField = getField("mEnd", "I"); - jPointerIndexField = getField("mPointerIndex", "I"); - jRangeTypeField = getField("mRangeType", "I"); - jRangeStylesField = getField("mRangeStyles", "I"); - jRangeLineStyleField = getField("mRangeLineStyle", "I"); - jRangeBoldLineField = getField("mRangeBoldLine", "Z"); - jRangeForeColorField = getField("mRangeForeColor", "I"); - jRangeBackColorField = getField("mRangeBackColor", "I"); - jRangeLineColorField = getField("mRangeLineColor", "I"); - jLocationField = getField("mLocation", "Landroid/location/Location;"); - jConnectionTypeField = getField("mConnectionType", "I"); - jIsWifiField = getField("mIsWifi", "Z"); - jDHCPGatewayField = getField("mDHCPGateway", "I"); - jScreenOrientationField = getField("mScreenOrientation", "S"); - jByteBufferField = getField("mBuffer", "Ljava/nio/ByteBuffer;"); - jWidthField = getField("mWidth", "I"); - jHeightField = getField("mHeight", "I"); - jIDField = getField("mID", "I"); - jGamepadButtonField = getField("mGamepadButton", "I"); - jGamepadButtonPressedField = getField("mGamepadButtonPressed", "Z"); - jGamepadButtonValueField = getField("mGamepadButtonValue", "F"); - jGamepadValuesField = getField("mGamepadValues", "[F"); - jPrefNamesField = getField("mPrefNames", "[Ljava/lang/String;"); - jObjectField = getField("mObject", "Ljava/lang/Object;"); + jCharactersField = geckoEvent.getField("mCharacters", "Ljava/lang/String;"); + jCharactersExtraField = geckoEvent.getField("mCharactersExtra", "Ljava/lang/String;"); + jDataField = geckoEvent.getField("mData", "Ljava/lang/String;"); + jKeyCodeField = geckoEvent.getField("mKeyCode", "I"); + jScanCodeField = geckoEvent.getField("mScanCode", "I"); + jMetaStateField = geckoEvent.getField("mMetaState", "I"); + jDomKeyLocationField = geckoEvent.getField("mDomKeyLocation", "Lorg/mozilla/gecko/GeckoEvent$DomKeyLocation;"); + jFlagsField = geckoEvent.getField("mFlags", "I"); + jUnicodeCharField = geckoEvent.getField("mUnicodeChar", "I"); + jBaseUnicodeCharField = geckoEvent.getField("mBaseUnicodeChar", "I"); + jDOMPrintableKeyValueField = geckoEvent.getField("mDOMPrintableKeyValue", "I"); + jRepeatCountField = geckoEvent.getField("mRepeatCount", "I"); + jCountField = geckoEvent.getField("mCount", "I"); + jStartField = geckoEvent.getField("mStart", "I"); + jEndField = geckoEvent.getField("mEnd", "I"); + jPointerIndexField = geckoEvent.getField("mPointerIndex", "I"); + jRangeTypeField = geckoEvent.getField("mRangeType", "I"); + jRangeStylesField = geckoEvent.getField("mRangeStyles", "I"); + jRangeLineStyleField = geckoEvent.getField("mRangeLineStyle", "I"); + jRangeBoldLineField = geckoEvent.getField("mRangeBoldLine", "Z"); + jRangeForeColorField = geckoEvent.getField("mRangeForeColor", "I"); + jRangeBackColorField = geckoEvent.getField("mRangeBackColor", "I"); + jRangeLineColorField = geckoEvent.getField("mRangeLineColor", "I"); + jLocationField = geckoEvent.getField("mLocation", "Landroid/location/Location;"); + jConnectionTypeField = geckoEvent.getField("mConnectionType", "I"); + jIsWifiField = geckoEvent.getField("mIsWifi", "Z"); + jDHCPGatewayField = geckoEvent.getField("mDHCPGateway", "I"); + jScreenOrientationField = geckoEvent.getField("mScreenOrientation", "S"); + jByteBufferField = geckoEvent.getField("mBuffer", "Ljava/nio/ByteBuffer;"); + jWidthField = geckoEvent.getField("mWidth", "I"); + jHeightField = geckoEvent.getField("mHeight", "I"); + jIDField = geckoEvent.getField("mID", "I"); + jGamepadButtonField = geckoEvent.getField("mGamepadButton", "I"); + jGamepadButtonPressedField = geckoEvent.getField("mGamepadButtonPressed", "Z"); + jGamepadButtonValueField = geckoEvent.getField("mGamepadButtonValue", "F"); + jGamepadValuesField = geckoEvent.getField("mGamepadValues", "[F"); + jPrefNamesField = geckoEvent.getField("mPrefNames", "[Ljava/lang/String;"); + jObjectField = geckoEvent.getField("mObject", "Ljava/lang/Object;"); // Init GeckoEvent.DomKeyLocation enum - jDomKeyLocationClass = getClassGlobalRef("org/mozilla/gecko/GeckoEvent$DomKeyLocation"); - jDomKeyLocationValueField = getField("value", "I"); + AutoJNIClass domKeyLocation(jEnv, "org/mozilla/gecko/GeckoEvent$DomKeyLocation"); + jDomKeyLocationClass = domKeyLocation.getGlobalRef(); + jDomKeyLocationValueField = domKeyLocation.getField("value", "I"); } void AndroidLocation::InitLocationClass(JNIEnv *jEnv) { - initInit(); - - jLocationClass = getClassGlobalRef("android/location/Location"); - jGetLatitudeMethod = getMethod("getLatitude", "()D"); - jGetLongitudeMethod = getMethod("getLongitude", "()D"); - jGetAltitudeMethod = getMethod("getAltitude", "()D"); - jGetAccuracyMethod = getMethod("getAccuracy", "()F"); - jGetBearingMethod = getMethod("getBearing", "()F"); - jGetSpeedMethod = getMethod("getSpeed", "()F"); - jGetTimeMethod = getMethod("getTime", "()J"); + AutoJNIClass location(jEnv, "android/location/Location"); + jLocationClass = location.getGlobalRef(); + jGetLatitudeMethod = location.getMethod("getLatitude", "()D"); + jGetLongitudeMethod = location.getMethod("getLongitude", "()D"); + jGetAltitudeMethod = location.getMethod("getAltitude", "()D"); + jGetAccuracyMethod = location.getMethod("getAccuracy", "()F"); + jGetBearingMethod = location.getMethod("getBearing", "()F"); + jGetSpeedMethod = location.getMethod("getSpeed", "()F"); + jGetTimeMethod = location.getMethod("getTime", "()J"); } nsGeoPosition* @@ -235,58 +234,49 @@ AndroidLocation::CreateGeoPosition(JNIEnv *jenv, jobject jobj) void AndroidPoint::InitPointClass(JNIEnv *jEnv) { - initInit(); + AutoJNIClass point(jEnv, "android/graphics/Point"); + jPointClass = point.getGlobalRef(); - jPointClass = getClassGlobalRef("android/graphics/Point"); - - jXField = getField("x", "I"); - jYField = getField("y", "I"); + jXField = point.getField("x", "I"); + jYField = point.getField("y", "I"); } void AndroidRect::InitRectClass(JNIEnv *jEnv) { - initInit(); + AutoJNIClass rect(jEnv, "android/graphics/Rect"); + jRectClass = rect.getGlobalRef(); - jRectClass = getClassGlobalRef("android/graphics/Rect"); - - jBottomField = getField("bottom", "I"); - jLeftField = getField("left", "I"); - jTopField = getField("top", "I"); - jRightField = getField("right", "I"); + jBottomField = rect.getField("bottom", "I"); + jLeftField = rect.getField("left", "I"); + jTopField = rect.getField("top", "I"); + jRightField = rect.getField("right", "I"); } void AndroidRectF::InitRectFClass(JNIEnv *jEnv) { - initInit(); + AutoJNIClass rect(jEnv, "android/graphics/RectF"); + jRectClass = rect.getGlobalRef(); - jRectClass = getClassGlobalRef("android/graphics/RectF"); - - jBottomField = getField("bottom", "F"); - jLeftField = getField("left", "F"); - jTopField = getField("top", "F"); - jRightField = getField("right", "F"); + jBottomField = rect.getField("bottom", "F"); + jLeftField = rect.getField("left", "F"); + jTopField = rect.getField("top", "F"); + jRightField = rect.getField("right", "F"); } void AndroidLayerRendererFrame::InitLayerRendererFrameClass(JNIEnv *jEnv) { - initInit(); + AutoJNIClass layerRendererFrame(jEnv, "org/mozilla/gecko/gfx/LayerRenderer$Frame"); + jLayerRendererFrameClass = layerRendererFrame.getGlobalRef(); - jLayerRendererFrameClass = getClassGlobalRef("org/mozilla/gecko/gfx/LayerRenderer$Frame"); - - jBeginDrawingMethod = getMethod("beginDrawing", "()V"); - jDrawBackgroundMethod = getMethod("drawBackground", "()V"); - jDrawForegroundMethod = getMethod("drawForeground", "()V"); - jEndDrawingMethod = getMethod("endDrawing", "()V"); + jBeginDrawingMethod = layerRendererFrame.getMethod("beginDrawing", "()V"); + jDrawBackgroundMethod = layerRendererFrame.getMethod("drawBackground", "()V"); + jDrawForegroundMethod = layerRendererFrame.getMethod("drawForeground", "()V"); + jEndDrawingMethod = layerRendererFrame.getMethod("endDrawing", "()V"); } -#undef initInit -#undef initClassGlobalRef -#undef getField -#undef getMethod - void AndroidGeckoEvent::ReadPointArray(nsTArray &points, JNIEnv *jenv,