From 3a24d6364c906dd175d1121fa76ebe119c1662f5 Mon Sep 17 00:00:00 2001 From: Jim Chen Date: Mon, 6 Mar 2017 15:32:36 -0500 Subject: [PATCH] Bug 1343027 - 2. Add jni::Ref::Lock function; r=snorp Add a Lock function to jni::Ref to lock the referenced object akin to the synchronized keyword in Java. It returns an AutoLock RAII object that automatically unlocks the object when going out of scope. --- widget/android/jni/Refs.h | 44 +++++++++++++++++++++++++++++++++++++ widget/android/nsWindow.cpp | 9 +++----- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/widget/android/jni/Refs.h b/widget/android/jni/Refs.h index 79f4b01e4876..73de3796654a 100644 --- a/widget/android/jni/Refs.h +++ b/widget/android/jni/Refs.h @@ -79,6 +79,45 @@ protected: public: using JNIType = Type; + class AutoLock + { + friend class Ref; + + JNIEnv* const mEnv; + Type mInstance; + + AutoLock(Type aInstance) + : mEnv(FindEnv()) + , mInstance(mEnv->NewLocalRef(aInstance)) + { + mEnv->MonitorEnter(mInstance); + MOZ_CATCH_JNI_EXCEPTION(mEnv); + } + + public: + AutoLock(AutoLock&& aOther) + : mEnv(aOther.mEnv) + , mInstance(aOther.mInstance) + { + aOther.mInstance = nullptr; + } + + ~AutoLock() + { + Unlock(); + } + + void Unlock() + { + if (mInstance) { + mEnv->MonitorExit(mInstance); + mEnv->DeleteLocalRef(mInstance); + MOZ_CATCH_JNI_EXCEPTION(mEnv); + mInstance = nullptr; + } + } + }; + // Construct a Ref form a raw JNI reference. static Ref From(JNIType obj) { @@ -117,6 +156,11 @@ public: return T::Ref::From(*this); } + AutoLock Lock() const + { + return AutoLock(mInstance); + } + bool operator==(const Ref& other) const { // Treat two references of the same object as being the same. diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index 91318f2fe0e5..7dda9f1d93b7 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -784,12 +784,9 @@ nsWindow::AndroidView::GetSettings(JSContext* aCx, JS::MutableHandleValue aOut) return NS_OK; } - JNIEnv* const env = jni::GetGeckoThreadEnv(); - env->MonitorEnter(mSettings.Get()); - nsresult rv = widget::EventDispatcher::UnboxBundle(aCx, mSettings, aOut); - env->MonitorExit(mSettings.Get()); - - return rv; + // Lock to prevent races with UI thread. + auto lock = mSettings.Lock(); + return widget::EventDispatcher::UnboxBundle(aCx, mSettings, aOut); } /**