Bug 1427079 - Don't let disposed window be read from parcels; r=snorp
It's possible for parcels derived from the session to outlast the
session lifecycle. This patch makes us return null when trying to
retrieve window objects using stale parcels.
MozReview-Commit-ID: 3Vp6T3uCEBt
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoSession.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoSession.java
@@ -291,32 +291,46 @@ public class GeckoSession extends LayerS
private NativeQueue mNativeQueue;
private Binder mBinder;
public Window(final NativeQueue nativeQueue) {
mNativeQueue = nativeQueue;
}
@Override // IInterface
- public IBinder asBinder() {
+ public Binder asBinder() {
if (mBinder == null) {
mBinder = new Binder();
mBinder.attachInterface(this, Window.class.getName());
}
return mBinder;
}
@WrapForJNI(dispatchTo = "proxy")
public static native void open(Window instance, Compositor compositor,
EventDispatcher dispatcher,
GeckoBundle settings, String chromeUri,
int screenId, boolean privateMode);
- @WrapForJNI(dispatchTo = "proxy")
- @Override protected native void disposeNative();
+ @Override // JNIObject
+ protected void disposeNative() {
+ // Detach ourselves from the binder as well, to prevent this window from being
+ // read from any parcels.
+ asBinder().attachInterface(null, Window.class.getName());
+
+ if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
+ nativeDisposeNative();
+ } else {
+ GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY,
+ this, "nativeDisposeNative");
+ }
+ }
+
+ @WrapForJNI(dispatchTo = "proxy", stubName = "DisposeNative")
+ private native void nativeDisposeNative();
@WrapForJNI(dispatchTo = "proxy")
public native void close();
@WrapForJNI(dispatchTo = "proxy")
public native void transfer(Compositor compositor, EventDispatcher dispatcher,
GeckoBundle settings);
@@ -523,24 +537,22 @@ public class GeckoSession extends LayerS
ThreadUtils.assertOnUiThread();
if (!isOpen()) {
throw new IllegalStateException("Session is not open");
}
if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
mWindow.close();
- mWindow.disposeNative();
} else {
GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY,
mWindow, "close");
- GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY,
- mWindow, "disposeNative");
}
+ mWindow.disposeNative();
mWindow = null;
onWindowChanged();
}
private void onWindowChanged() {
if (mWindow != null) {
mTextInput.onWindowChanged(mWindow);
}
--- a/widget/android/GeneratedJNIWrappers.h
+++ b/widget/android/GeneratedJNIWrappers.h
@@ -2287,17 +2287,17 @@ public:
mozilla::jni::DispatchTarget::PROXY;
};
struct DisposeNative_t {
typedef Window Owner;
typedef void ReturnType;
typedef void SetterType;
typedef mozilla::jni::Args<> Args;
- static constexpr char name[] = "disposeNative";
+ static constexpr char name[] = "nativeDisposeNative";
static constexpr char signature[] =
"()V";
static const bool isStatic = false;
static const mozilla::jni::ExceptionMode exceptionMode =
mozilla::jni::ExceptionMode::ABORT;
static const mozilla::jni::CallingThread callingThread =
mozilla::jni::CallingThread::ANY;
static const mozilla::jni::DispatchTarget dispatchTarget =