Index: chrome/android/java/src/org/chromium/chrome/browser/services/gcm/ChromeGcmListenerService.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/services/gcm/ChromeGcmListenerService.java b/chrome/android/java/src/org/chromium/chrome/browser/services/gcm/ChromeGcmListenerService.java |
index d1a1660be5a4a59c13edd1a4acf117f01a0f9ee0..54f0ded7882c866b8a3d54bc1a3ae9519f5c9417 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/services/gcm/ChromeGcmListenerService.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/services/gcm/ChromeGcmListenerService.java |
@@ -4,6 +4,8 @@ |
package org.chromium.chrome.browser.services.gcm; |
+import android.content.Context; |
+import android.os.Build; |
import android.os.Bundle; |
import android.text.TextUtils; |
@@ -16,7 +18,11 @@ import org.chromium.base.annotations.SuppressFBWarnings; |
import org.chromium.base.library_loader.ProcessInitException; |
import org.chromium.chrome.browser.init.ChromeBrowserInitializer; |
import org.chromium.chrome.browser.init.ProcessInitializationHandler; |
+import org.chromium.components.background_task_scheduler.BackgroundTaskSchedulerFactory; |
+import org.chromium.components.background_task_scheduler.TaskIds; |
+import org.chromium.components.background_task_scheduler.TaskInfo; |
import org.chromium.components.gcm_driver.GCMDriver; |
+import org.chromium.components.gcm_driver.GCMMessage; |
/** |
* Receives Downstream messages and status of upstream messages from GCM. |
@@ -31,7 +37,7 @@ public class ChromeGcmListenerService extends GcmListenerService { |
} |
@Override |
- public void onMessageReceived(String from, Bundle data) { |
+ public void onMessageReceived(final String from, final Bundle data) { |
boolean hasCollapseKey = !TextUtils.isEmpty(data.getString("collapse_key")); |
GcmUma.recordDataMessageReceived(getApplicationContext(), hasCollapseKey); |
@@ -40,7 +46,24 @@ public class ChromeGcmListenerService extends GcmListenerService { |
AndroidGcmController.get(this).onMessageReceived(data); |
return; |
} |
- pushMessageReceived(from, data); |
+ |
+ final Context applicationContext = getApplicationContext(); |
+ |
+ // Dispatch the message to the GCM Driver for native features. |
+ ThreadUtils.runOnUiThread(new Runnable() { |
+ @Override |
+ public void run() { |
+ GCMMessage message = null; |
+ try { |
+ message = new GCMMessage(from, data); |
+ } catch (IllegalArgumentException e) { |
+ Log.e(TAG, "Received an invalid GCM Message", e); |
+ return; |
+ } |
+ |
+ scheduleOrDispatchMessageToDriver(applicationContext, message); |
+ } |
+ }); |
} |
@Override |
@@ -63,28 +86,50 @@ public class ChromeGcmListenerService extends GcmListenerService { |
GcmUma.recordDeletedMessages(getApplicationContext()); |
} |
- private void pushMessageReceived(final String from, final Bundle data) { |
- final String bundleSubtype = "subtype"; |
- if (!data.containsKey(bundleSubtype)) { |
- Log.w(TAG, "Received push message with no subtype"); |
- return; |
+ /** |
+ * Either schedules |message| to be dispatched through the Job Scheduler, which we use on |
+ * Android N and beyond, or immediately dispatches the message on other versions of Android. |
+ * Must be called on the UI thread both for the BackgroundTaskScheduler and for dispatching |
+ * the |message| to the GCMDriver. |
+ */ |
+ static void scheduleOrDispatchMessageToDriver(Context context, GCMMessage message) { |
+ ThreadUtils.assertOnUiThread(); |
+ |
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { |
+ Bundle extras = message.toBundle(); |
+ |
+ // TODO(peter): Add UMA for measuring latency introduced by the BackgroundTaskScheduler. |
+ TaskInfo backgroundTask = TaskInfo.createOneOffTask(TaskIds.GCM_BACKGROUND_TASK_JOB_ID, |
+ GCMBackgroundTask.class, 0 /* immediately */) |
+ .setExtras(extras) |
+ .build(); |
+ |
+ BackgroundTaskSchedulerFactory.getScheduler().schedule(context, backgroundTask); |
+ |
+ } else { |
+ dispatchMessageToDriver(context, message); |
+ } |
+ } |
+ |
+ /** |
+ * To be called when a GCM message is ready to be dispatched. Will initialise the native code |
+ * of the browser process, and forward the message to the GCM Driver. Must be called on the UI |
+ * thread. |
+ */ |
+ @SuppressFBWarnings("DM_EXIT") |
+ static void dispatchMessageToDriver(Context applicationContext, GCMMessage message) { |
+ ThreadUtils.assertOnUiThread(); |
+ |
+ try { |
+ ChromeBrowserInitializer.getInstance(applicationContext).handleSynchronousStartup(); |
+ GCMDriver.dispatchMessage(message); |
+ |
+ } catch (ProcessInitException e) { |
+ Log.e(TAG, "ProcessInitException while starting the browser process"); |
+ |
+ // Since the library failed to initialize nothing in the application can work, so kill |
+ // the whole application as opposed to just this service. |
+ System.exit(-1); |
} |
- final String appId = data.getString(bundleSubtype); |
- ThreadUtils.runOnUiThread(new Runnable() { |
- @Override |
- @SuppressFBWarnings("DM_EXIT") |
- public void run() { |
- try { |
- ChromeBrowserInitializer.getInstance(getApplicationContext()) |
- .handleSynchronousStartup(); |
- GCMDriver.onMessageReceived(appId, from, data); |
- } catch (ProcessInitException e) { |
- Log.e(TAG, "ProcessInitException while starting the browser process"); |
- // Since the library failed to initialize nothing in the application |
- // can work, so kill the whole application not just the activity. |
- System.exit(-1); |
- } |
- } |
- }); |
} |
} |