Bug 1432160 - Initialize PushService for custom tabs / PWA; r?snorp draft
authorJim Chen <nchen@mozilla.com>
Thu, 08 Feb 2018 18:33:19 -0500
changeset 752789 cc9372a27199b2b8a772f4d32b300be3fce43859
parent 752655 22a2b0f1b1ab6054de76a92ed4a85d4d09e1514f
push id98387
push userbmo:nchen@mozilla.com
push dateThu, 08 Feb 2018 23:33:38 +0000
reviewerssnorp
bugs1432160
milestone60.0a1
Bug 1432160 - Initialize PushService for custom tabs / PWA; r?snorp We currently initialize PushService on delayed startup, which only happens when Fennec is launched. This patch makes us also initialize PushService if needed by web content from custom tabs / PWA, by listening for the push initialization event in GeckoApplication. MozReview-Commit-ID: 9CTOEZmOqls
mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
mobile/android/base/java/org/mozilla/gecko/push/PushService.java
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
@@ -302,16 +302,17 @@ public class GeckoApplication extends Ap
                 null);
         EventDispatcher.getInstance().registerUiThreadListener(mListener,
                 "Gecko:Exited",
                 "RuntimePermissions:Check",
                 "Snackbar:Show",
                 "Share:Text",
                 null);
         EventDispatcher.getInstance().registerBackgroundThreadListener(mListener,
+                "PushServiceAndroidGCM:Configure",
                 "Bookmark:Insert",
                 "Image:SetAs",
                 "Profile:Create",
                 null);
 
         super.onCreate();
     }
 
@@ -325,41 +326,46 @@ public class GeckoApplication extends Ap
                 null);
         EventDispatcher.getInstance().unregisterUiThreadListener(mListener,
                 "Gecko:Exited",
                 "RuntimePermissions:Check",
                 "Snackbar:Show",
                 "Share:Text",
                 null);
         EventDispatcher.getInstance().unregisterBackgroundThreadListener(mListener,
+                "PushServiceAndroidGCM:Configure",
                 "Bookmark:Insert",
                 "Image:SetAs",
                 "Profile:Create",
                 null);
 
         GeckoService.unregister();
     }
 
+    /* package */ boolean initPushService() {
+        // It's fine to throw GCM initialization onto a background thread; the registration process requires
+        // network access, so is naturally asynchronous.  This, of course, races against Gecko page load of
+        // content requiring GCM-backed services, like Web Push.  There's nothing to be done here.
+        try {
+            final Class<?> clazz = Class.forName("org.mozilla.gecko.push.PushService");
+            final Method onCreate = clazz.getMethod("onCreate", Context.class);
+            return (Boolean) onCreate.invoke(null, getApplicationContext()); // Method is static.
+        } catch (Exception e) {
+            Log.e(LOG_TAG, "Got exception during startup; ignoring.", e);
+            return false;
+        }
+    }
+
     public void onDelayedStartup() {
         if (AppConstants.MOZ_ANDROID_GCM) {
             // TODO: only run in main process.
             ThreadUtils.postToBackgroundThread(new Runnable() {
                 @Override
                 public void run() {
-                    // It's fine to throw GCM initialization onto a background thread; the registration process requires
-                    // network access, so is naturally asynchronous.  This, of course, races against Gecko page load of
-                    // content requiring GCM-backed services, like Web Push.  There's nothing to be done here.
-                    try {
-                        final Class<?> clazz = Class.forName("org.mozilla.gecko.push.PushService");
-                        final Method onCreate = clazz.getMethod("onCreate", Context.class);
-                        onCreate.invoke(null, getApplicationContext()); // Method is static.
-                    } catch (Exception e) {
-                        Log.e(LOG_TAG, "Got exception during startup; ignoring.", e);
-                        return;
-                    }
+                    initPushService();
                 }
             });
         }
 
         GeckoAccessibility.setAccessibilityManagerListeners(this);
 
         AudioFocusAgent.getInstance().attachToContext(this);
     }
@@ -530,16 +536,22 @@ public class GeckoApplication extends Ap
                                 .message(resId)
                                 .duration(Snackbar.LENGTH_LONG)
                                 .buildAndShow();
                     }
                 });
 
             } else if ("Image:SetAs".equals(event)) {
                 setImageAs(message.getString("url"));
+
+            } else if ("PushServiceAndroidGCM:Configure".equals(event)) {
+                // Init push service and redirect the event to it.
+                if (initPushService()) {
+                    EventDispatcher.getInstance().dispatch(event, message, callback);
+                }
             }
         }
     }
 
     public boolean isApplicationInBackground() {
         return mInBackground;
     }
 
--- a/mobile/android/base/java/org/mozilla/gecko/push/PushService.java
+++ b/mobile/android/base/java/org/mozilla/gecko/push/PushService.java
@@ -92,24 +92,25 @@ public class PushService implements Bund
     public static synchronized PushService getInstance(Context context) {
         if (sInstance == null) {
             onCreate(context);
         }
         return sInstance;
     }
 
     @ReflectionTarget
-    public static synchronized void onCreate(Context context) {
+    public static synchronized boolean onCreate(Context context) {
         if (sInstance != null) {
-            return;
+            return false;
         }
         sInstance = new PushService(context);
 
         sInstance.registerGeckoEventListener();
         sInstance.onStartup();
+        return true;
     }
 
     protected final PushManager pushManager;
 
     // NB: These are not thread-safe, we're depending on these being access from the same background thread.
     private boolean isReadyPushServiceAndroidGCM = false;
     private boolean isReadyFxAccountsPush = false;
     private final List<JSONObject> pendingPushMessages;