summaryrefslogtreecommitdiffstats
path: root/components/gcm_driver
diff options
context:
space:
mode:
authorjohnme@chromium.org <johnme@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-12 20:51:17 +0000
committerjohnme@chromium.org <johnme@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-12 20:51:17 +0000
commitdd60bcc85a623db6ca0c6a7bef0fb3efca2c6e45 (patch)
treecb930729fa81a5fa18ee5181ead432905cd04565 /components/gcm_driver
parentafd97b8a4eea0aaccad1aa490815201a2223f026 (diff)
downloadchromium_src-dd60bcc85a623db6ca0c6a7bef0fb3efca2c6e45.zip
chromium_src-dd60bcc85a623db6ca0c6a7bef0fb3efca2c6e45.tar.gz
chromium_src-dd60bcc85a623db6ca0c6a7bef0fb3efca2c6e45.tar.bz2
Implement GCMDriver.java using MultiplexingGcmListener
Known caveat: - Since GCM on Android only supports a single registration per native app, only a single web app can register at once, and even then only if they pass --disable-sync-gcm-in-order-to-try-push-api on the command line which disables Chrome Sync etc from receiving GCM messages. Depends on https://codereview.chromium.org/316963003/ BUG=350384 Review URL: https://codereview.chromium.org/314293006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@276795 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components/gcm_driver')
-rw-r--r--components/gcm_driver/android/java/src/org/chromium/components/gcm_driver/GCMDriver.java99
-rw-r--r--components/gcm_driver/android/java/src/org/chromium/components/gcm_driver/GCMListener.java75
2 files changed, 159 insertions, 15 deletions
diff --git a/components/gcm_driver/android/java/src/org/chromium/components/gcm_driver/GCMDriver.java b/components/gcm_driver/android/java/src/org/chromium/components/gcm_driver/GCMDriver.java
index f8d70ce..b7a5024 100644
--- a/components/gcm_driver/android/java/src/org/chromium/components/gcm_driver/GCMDriver.java
+++ b/components/gcm_driver/android/java/src/org/chromium/components/gcm_driver/GCMDriver.java
@@ -5,7 +5,11 @@
package org.chromium.components.gcm_driver;
import android.content.Context;
+import android.os.AsyncTask;
import android.os.Bundle;
+import android.util.Log;
+
+import com.google.android.gcm.GCMRegistrar;
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
@@ -15,11 +19,16 @@ import java.util.ArrayList;
import java.util.List;
/**
- * An implementation of GCMDriver using Android's Java GCM APIs.
+ * This class is the Java counterpart to the C++ GCMDriverAndroid class.
+ * It uses Android's Java GCM APIs to implements GCM registration etc, and
+ * sends back GCM messages over JNI.
+ *
* Threading model: all calls to/from C++ happen on the UI thread.
*/
@JNINamespace("gcm")
-public final class GCMDriver {
+public class GCMDriver {
+ private static final String TAG = "GCMDriver";
+
// The instance of GCMDriver currently owned by a C++ GCMDriverAndroid, if any.
private static GCMDriver sInstance = null;
@@ -41,8 +50,9 @@ public final class GCMDriver {
@CalledByNative
private static GCMDriver create(long nativeGCMDriverAndroid,
Context context) {
- if (sInstance != null)
+ if (sInstance != null) {
throw new IllegalStateException("Already instantiated");
+ }
sInstance = new GCMDriver(nativeGCMDriverAndroid, context);
return sInstance;
}
@@ -59,32 +69,91 @@ public final class GCMDriver {
}
@CalledByNative
- private void register(String appId, String[] senderIds) {
- // TODO(johnme): Actually try to register.
- nativeOnRegisterFinished(mNativeGCMDriverAndroid, appId, "", false);
+ private void register(final String appId, final String[] senderIds) {
+ new AsyncTask<Void, Void, String>() {
+ @Override
+ protected String doInBackground(Void... voids) {
+ try {
+ GCMRegistrar.checkDevice(mContext);
+ } catch (UnsupportedOperationException ex) {
+ return ""; // Indicates failure.
+ }
+ // TODO(johnme): Move checkManifest call to a test instead.
+ GCMRegistrar.checkManifest(mContext);
+ String existingRegistrationId = GCMRegistrar.getRegistrationId(mContext);
+ if (existingRegistrationId.equals("")) {
+ // TODO(johnme): Migrate from GCMRegistrar to GoogleCloudMessaging API, both
+ // here and elsewhere in Chromium.
+ // TODO(johnme): Pass appId to GCM.
+ GCMRegistrar.register(mContext, senderIds);
+ return null; // Indicates pending result.
+ } else {
+ Log.i(TAG, "Re-using existing registration ID");
+ return existingRegistrationId;
+ }
+ }
+ @Override
+ protected void onPostExecute(String registrationId) {
+ if (registrationId == null) {
+ return; // Wait for {@link #onRegisterFinished} to be called.
+ }
+ nativeOnRegisterFinished(mNativeGCMDriverAndroid, appId, registrationId,
+ !registrationId.isEmpty());
+ }
+ }.execute();
}
+
+ private enum UnregisterResult { SUCCESS, FAILED, PENDING }
+
@CalledByNative
- private void unregister(String appId) {
- // TODO(johnme): Actually try to unregister.
- nativeOnUnregisterFinished(mNativeGCMDriverAndroid, appId, false);
+ private void unregister(final String appId) {
+ new AsyncTask<Void, Void, UnregisterResult>() {
+ @Override
+ protected UnregisterResult doInBackground(Void... voids) {
+ try {
+ GCMRegistrar.checkDevice(mContext);
+ } catch (UnsupportedOperationException ex) {
+ return UnregisterResult.FAILED;
+ }
+ if (!GCMRegistrar.isRegistered(mContext)) {
+ return UnregisterResult.SUCCESS;
+ }
+ // TODO(johnme): Pass appId to GCM.
+ GCMRegistrar.unregister(mContext);
+ return UnregisterResult.PENDING;
+ }
+
+ @Override
+ protected void onPostExecute(UnregisterResult result) {
+ if (result == UnregisterResult.PENDING) {
+ return; // Wait for {@link #onUnregisterFinished} to be called.
+ }
+ nativeOnUnregisterFinished(mNativeGCMDriverAndroid, appId,
+ result == UnregisterResult.SUCCESS);
+ }
+ }.execute();
}
- public static void onRegistered(String appId, String registrationId) {
+ static void onRegisterFinished(String appId, String registrationId) {
ThreadUtils.assertOnUiThread();
+ // TODO(johnme): If this gets called, did it definitely succeed?
// TODO(johnme): Update registrations cache?
- if (sInstance != null)
+ if (sInstance != null) {
sInstance.nativeOnRegisterFinished(sInstance.mNativeGCMDriverAndroid, appId,
registrationId, true);
+ }
}
- public static void onUnregistered(String appId) {
+ static void onUnregisterFinished(String appId) {
ThreadUtils.assertOnUiThread();
+ // TODO(johnme): If this gets called, did it definitely succeed?
// TODO(johnme): Update registrations cache?
- if (sInstance != null)
+ if (sInstance != null) {
sInstance.nativeOnUnregisterFinished(sInstance.mNativeGCMDriverAndroid, appId, true);
+ }
}
- public static void onMessageReceived(final String appId, final Bundle extras) {
+ static void onMessageReceived(final String appId, final Bundle extras) {
// TODO(johnme): Store message and redeliver later if Chrome is killed before delivery.
ThreadUtils.assertOnUiThread();
launchNativeThen(new Runnable() {
@@ -113,7 +182,7 @@ public final class GCMDriver {
});
}
- public static void onMessagesDeleted(final String appId) {
+ static void onMessagesDeleted(final String appId) {
// TODO(johnme): Store event and redeliver later if Chrome is killed before delivery.
ThreadUtils.assertOnUiThread();
launchNativeThen(new Runnable() {
diff --git a/components/gcm_driver/android/java/src/org/chromium/components/gcm_driver/GCMListener.java b/components/gcm_driver/android/java/src/org/chromium/components/gcm_driver/GCMListener.java
new file mode 100644
index 0000000..d3cb556
--- /dev/null
+++ b/components/gcm_driver/android/java/src/org/chromium/components/gcm_driver/GCMListener.java
@@ -0,0 +1,75 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.gcm_driver;
+
+import android.content.Intent;
+
+import com.google.ipc.invalidation.external.client.contrib.MultiplexingGcmListener;
+
+import org.chromium.base.ThreadUtils;
+
+/**
+ * Receives GCM registration events and messages rebroadcast by MultiplexingGcmListener.
+ */
+public class GCMListener extends MultiplexingGcmListener.AbstractListener {
+ /**
+ * Receiver for broadcasts by the multiplexed GCM service. It forwards them to
+ * GCMListener.
+ *
+ * This class is public so that it can be instantiated by the Android runtime.
+ */
+ public static class Receiver extends MultiplexingGcmListener.AbstractListener.Receiver {
+ @Override
+ protected Class<?> getServiceClass() {
+ return GCMListener.class;
+ }
+ }
+
+ private static final String TAG = "GCMListener";
+
+ public GCMListener() {
+ super(TAG);
+ }
+
+ @Override
+ protected void onRegistered(final String registrationId) {
+ ThreadUtils.runOnUiThread(new Runnable() {
+ @Override public void run() {
+ // TODO(johnme): Get app ID.
+ GCMDriver.onRegisterFinished("unknown-app-id", registrationId);
+ }
+ });
+ }
+
+ @Override
+ protected void onUnregistered(String registrationId) {
+ ThreadUtils.runOnUiThread(new Runnable() {
+ @Override public void run() {
+ // TODO(johnme): Get app ID.
+ GCMDriver.onUnregisterFinished("unknown-app-id");
+ }
+ });
+ }
+
+ @Override
+ protected void onMessage(final Intent intent) {
+ ThreadUtils.runOnUiThread(new Runnable() {
+ @Override public void run() {
+ // TODO(johnme): Get app ID.
+ GCMDriver.onMessageReceived("unknown-app-id", intent.getExtras());
+ }
+ });
+ }
+
+ @Override
+ protected void onDeletedMessages(int total) {
+ ThreadUtils.runOnUiThread(new Runnable() {
+ @Override public void run() {
+ // TODO(johnme): Get app ID.
+ GCMDriver.onMessagesDeleted("unknown-app-id");
+ }
+ });
+ }
+}