Bug 1330458 - Queue undipatched events before Gecko is ready; r=snorp
authorJim Chen <nchen@mozilla.com>
Fri, 13 Jan 2017 14:39:27 -0500
changeset 374409 74f4405ca51b958c0021e1cb330fef30072bd6e6
parent 374408 aa169d27ca871ed614a26c1421b728e794b95c65
child 374410 fb6a2290e35d17db060dfe3c541ca04f3a6f9230
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs1330458
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1330458 - Queue undipatched events before Gecko is ready; r=snorp To deal with the Java side trying to send events to Gecko before Gecko is ready, make a special exception to queue any undispatched events when Gecko is not ready, so that the events can be redispatched to Gecko later.
mobile/android/geckoview/src/main/java/org/mozilla/gecko/EventDispatcher.java
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/EventDispatcher.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/EventDispatcher.java
@@ -84,21 +84,20 @@ public final class EventDispatcher exten
 
     @WrapForJNI private static final int DETACHED = 0;
     @WrapForJNI private static final int ATTACHED = 1;
     @WrapForJNI private static final int REATTACHING = 2;
 
     @WrapForJNI(calledFrom = "gecko")
     private synchronized void setAttachedToGecko(final int state) {
         if (mAttachedToGecko && state == DETACHED) {
-            if (GeckoThread.isStateAtLeast(GeckoThread.State.JNI_READY)) {
+            if (GeckoThread.isRunning()) {
                 disposeNative();
             } else {
-                GeckoThread.queueNativeCallUntil(GeckoThread.State.JNI_READY,
-                        this, "disposeNative");
+                GeckoThread.queueNativeCall(this, "disposeNative");
             }
         }
         mAttachedToGecko = (state == ATTACHED);
     }
 
     private <T> void registerListener(final Class<?> listType,
                                       final Map<String, List<T>> listenersMap,
                                       final T listener,
@@ -402,17 +401,29 @@ public final class EventDispatcher exten
         }
 
         if (dispatchToThread(type, jsMessage, bundleMessage, callback,
                              mBackgroundThreadListeners, ThreadUtils.getBackgroundHandler())) {
             return true;
         }
 
         if (jsMessage == null) {
-            Log.w(LOGTAG, "No listeners for " + type + " in dispatchToThreads");
+            Log.w(LOGTAG, "No listeners for " + type);
+        }
+
+        if (!GeckoThread.isRunning() && jsMessage == null) {
+            // Usually, we discard an event if there is no listeners for it by the time of
+            // the dispatch. However, if Gecko is not ready and there is no listener for
+            // this event that's possibly headed to Gecko, we make a special exception to
+            // queue this event until Gecko is ready. This way, Gecko can first register
+            // its listeners, and accept the event when it is ready.
+            GeckoThread.queueNativeCall(this, "dispatchToGecko",
+                                        String.class, type, GeckoBundle.class, bundleMessage,
+                                        EventCallback.class, JavaCallbackDelegate.wrap(callback));
+            return true;
         }
 
         if (!AppConstants.RELEASE_OR_BETA && jsMessage == null) {
             // We're dispatching a Bundle message. Because Gecko thread listeners are not
             // supported for Bundle messages, do a sanity check to make sure we don't have
             // matching Gecko thread listeners.
             boolean hasGeckoListener = false;
             synchronized (mGeckoThreadNativeListeners) {
@@ -482,18 +493,16 @@ public final class EventDispatcher exten
         // on a separate thread.
         synchronized (listenersMap) {
             final List<BundleEventListener> listeners = listenersMap.get(type);
             if (listeners == null) {
                 return false;
             }
 
             if (listeners.isEmpty()) {
-                Log.w(LOGTAG, "No listeners for " + type + " in dispatchToThread");
-
                 // There were native listeners, and they're gone.
                 return false;
             }
 
             final GeckoBundle messageAsBundle;
             try {
                 messageAsBundle = jsMessage != null ?
                         convertBundle(jsMessage.toBundle(), jsMessage) : bundleMessage;
@@ -524,18 +533,17 @@ public final class EventDispatcher exten
         //   "event_specific": "value",
         //   ...
         try {
             final String type = message.getString("type");
 
             final List<GeckoEventListener> listeners = getGeckoListeners(type);
 
             if (listeners == null || listeners.isEmpty()) {
-                Log.w(LOGTAG, "No listeners for " + type + " in dispatchEvent");
-
+                Log.w(LOGTAG, "No listeners for " + type);
                 return false;
             }
 
             for (final GeckoEventListener listener : listeners) {
                 listener.handleMessage(type, message);
             }
         } catch (final JSONException e) {
             Log.e(LOGTAG, "handleGeckoMessage throws " + e, e);