Bug 1252650 - Add intent to create XPCOM services in GeckoService; r=snorp
authorJim Chen <nchen@mozilla.com>
Wed, 20 Apr 2016 15:06:13 -0400
changeset 294084 3f76b4e1d805b0771b097bbd8746271e046ada61
parent 294083 d29c9c527c7a080d3cec0d5e37dc3caa9520ddba
child 294085 ca46a5d6f50d85924e59a63a189b17ee49510975
push id75428
push usernchen@mozilla.com
push dateWed, 20 Apr 2016 19:07:08 +0000
treeherdermozilla-inbound@f69911bd0bc2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs1252650
milestone48.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 1252650 - Add intent to create XPCOM services in GeckoService; r=snorp Add support for Intents that launch GeckoService and create services based on a category registered with the category manager.
mobile/android/base/java/org/mozilla/gecko/GeckoService.java
mobile/android/base/java/org/mozilla/gecko/GeckoThread.java
widget/android/nsAppShell.cpp
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoService.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoService.java
@@ -22,47 +22,45 @@ import org.mozilla.gecko.util.EventCallb
 public class GeckoService extends Service {
 
     private static final String LOGTAG = "GeckoService";
     private static final boolean DEBUG = false;
 
     private static final String INTENT_PROFILE_NAME = "org.mozilla.gecko.intent.PROFILE_NAME";
     private static final String INTENT_PROFILE_DIR = "org.mozilla.gecko.intent.PROFILE_DIR";
 
-    private static class EventListener implements NativeEventListener {
+    private static final String INTENT_ACTION_UPDATE_ADDONS = "update-addons";
+    private static final String INTENT_ACTION_CREATE_SERVICES = "create-services";
 
-        private PendingIntent getIntentForAction(final Context context, final String action) {
-            final Intent intent = new Intent(action, /* uri */ null, context, GeckoService.class);
-            final GeckoProfile profile = GeckoThread.getActiveProfile();
-            if (profile != null) {
-                intent.putExtra(INTENT_PROFILE_NAME, profile.getName());
-                intent.putExtra(INTENT_PROFILE_DIR, profile.getDir().getAbsolutePath());
-            }
-            return PendingIntent.getService(context, /* requestCode */ 0, intent,
-                                            PendingIntent.FLAG_CANCEL_CURRENT);
-        }
+    private static final String INTENT_SERVICE_CATEGORY = "category";
 
+    private static class EventListener implements NativeEventListener {
         @Override // NativeEventListener
         public void handleMessage(final String event,
                                   final NativeJSObject message,
                                   final EventCallback callback) {
             final Context context = GeckoAppShell.getApplicationContext();
             switch (event) {
             case "Gecko:ScheduleRun":
                 if (DEBUG) {
                     Log.d(LOGTAG, "Scheduling " + message.getString("action") +
                                   " @ " + message.getInt("interval") + "ms");
                 }
+
+                final Intent intent = getIntentForAction(context, message.getString("action"));
+                final PendingIntent pendingIntent = PendingIntent.getService(
+                        context, /* requestCode */ 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+
                 final AlarmManager am = (AlarmManager)
                     context.getSystemService(Context.ALARM_SERVICE);
                 // Cancel any previous alarm and schedule a new one.
                 am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME,
                                        message.getInt("trigger"),
                                        message.getInt("interval"),
-                                       getIntentForAction(context, message.getString("action")));
+                                       pendingIntent);
                 break;
 
             default:
                 throw new UnsupportedOperationException(event);
             }
         }
     }
 
@@ -108,16 +106,37 @@ public class GeckoService extends Servic
         }
 
         if (DEBUG) {
             Log.d(LOGTAG, "Destroyed");
         }
         super.onDestroy();
     }
 
+    private static Intent getIntentForAction(final Context context, final String action) {
+        final Intent intent = new Intent(action, /* uri */ null, context, GeckoService.class);
+        final GeckoProfile profile = GeckoThread.getActiveProfile();
+        if (profile != null) {
+            setIntentProfile(intent, profile.getName(), profile.getDir().getAbsolutePath());
+        }
+        return intent;
+    }
+
+    public static Intent getIntentToCreateServices(final Context context, final String category) {
+        final Intent intent = getIntentForAction(context, INTENT_ACTION_CREATE_SERVICES);
+        intent.putExtra(INTENT_SERVICE_CATEGORY, category);
+        return intent;
+    }
+
+    public static void setIntentProfile(final Intent intent, final String profileName,
+                                        final String profileDir) {
+        intent.putExtra(INTENT_PROFILE_NAME, profileName);
+        intent.putExtra(INTENT_PROFILE_DIR, profileDir);
+    }
+
     private int handleIntent(final Intent intent, final int startId) {
         if (DEBUG) {
             Log.d(LOGTAG, "Handling " + intent.getAction());
         }
 
         final String profileName = intent.getStringExtra(INTENT_PROFILE_NAME);
         final String profileDir = intent.getStringExtra(INTENT_PROFILE_DIR);
 
@@ -137,21 +156,30 @@ public class GeckoService extends Servic
             }
             stopSelf(startId);
             return Service.START_NOT_STICKY;
         }
 
         GeckoThread.launch();
 
         switch (intent.getAction()) {
-        case "update-addons":
+        case INTENT_ACTION_UPDATE_ADDONS:
             // Run the add-on update service. Because the service is automatically invoked
             // when loading Gecko, we don't have to do anything else here.
             break;
 
+        case INTENT_ACTION_CREATE_SERVICES:
+            final String category = intent.getStringExtra(INTENT_SERVICE_CATEGORY);
+
+            if (category == null) {
+                break;
+            }
+            GeckoThread.createServices(category);
+            break;
+
         default:
             Log.w(LOGTAG, "Unknown request: " + intent);
         }
 
         stopSelf(startId);
         return Service.START_NOT_STICKY;
     }
 
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoThread.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoThread.java
@@ -634,9 +634,21 @@ public class GeckoThread extends Thread 
     public static void onResume() {
         if (isStateAtLeast(State.PROFILE_READY)) {
             nativeOnResume();
         } else {
             queueNativeCallUntil(State.PROFILE_READY, GeckoThread.class,
                                  "nativeOnResume");
         }
     }
+
+    @WrapForJNI(stubName = "CreateServices")
+    private static native void nativeCreateServices(String category);
+
+    public static void createServices(final String category) {
+        if (isStateAtLeast(State.PROFILE_READY)) {
+            nativeCreateServices(category);
+        } else {
+            queueNativeCallUntil(State.PROFILE_READY, GeckoThread.class, "nativeCreateServices",
+                                 String.class, category);
+        }
+    }
 }
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -260,16 +260,24 @@ public:
         }
 
         // We didn't return from one of our own activities, so restore
         // to foreground status
         nsCOMPtr<nsIObserverService> obsServ =
             mozilla::services::GetObserverService();
         obsServ->NotifyObservers(nullptr, "application-foreground", nullptr);
     }
+
+    static void CreateServices(jni::String::Param aCategory)
+    {
+        nsCString category(aCategory->ToCString());
+
+        NS_CreateServicesFromCategory(
+                category.get(), /* aOrigin */ nullptr, category.get());
+    }
 };
 
 uint32_t GeckoThreadSupport::sPauseCount;
 
 
 class GeckoAppShellSupport final
     : public widget::GeckoAppShell::Natives<GeckoAppShellSupport>
     , public UsesGeckoThreadProxy