Bug 1427079 - Don't let disposed window be read from parcels; r=snorp draft
authorJim Chen <nchen@mozilla.com>
Thu, 11 Jan 2018 13:45:54 -0500
changeset 719279 fceda356bf812d80d81f4e35cbc3f74ad6151d77
parent 715271 ac93fdadf1022211eec62258ad22b42cb37a6d14
child 745738 862e3a3e864b18bc33a079c48c6528817c65ad61
push id95193
push userbmo:nchen@mozilla.com
push dateThu, 11 Jan 2018 18:46:16 +0000
reviewerssnorp
bugs1427079
milestone59.0a1
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
mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoSession.java
widget/android/GeneratedJNIWrappers.h
--- 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 =