| Index: chrome/android/java/src/org/chromium/chrome/browser/GcmPlatformImpl.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/GcmPlatformImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/GcmPlatformImpl.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..06e4367985f2f5a16cb985fa2c9800ff50c2f060
|
| --- /dev/null
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/GcmPlatformImpl.java
|
| @@ -0,0 +1,200 @@
|
| +// Copyright 2013 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.chrome.browser;
|
| +
|
| +import android.content.Context;
|
| +import android.content.Intent;
|
| +import android.os.AsyncTask;
|
| +import android.util.Log;
|
| +
|
| +import com.google.android.gcm.GCMRegistrar;
|
| +import com.google.ipc.invalidation.external.client.contrib.MultiplexingGcmListener;
|
| +
|
| +import org.chromium.base.CalledByNative;
|
| +import org.chromium.base.ThreadUtils;
|
| +
|
| +import java.io.IOException;
|
| +
|
| +/**
|
| + * This class is the Java counterpart to the C++ GcmPlatformImplAndroid class.
|
| + * It implements GCM registration, and sends back GCM messages over JNI.
|
| + *
|
| + * Threading model note: all calls from C++ must happen on the UI thread.
|
| + * Callbacks from Android may happen on a different thread, so we always
|
| + * use ThreadUtils.runOnUiThread when calling back to C++.
|
| + */
|
| +class GcmPlatformImpl {
|
| + private static final String TAG = "Chrome-GcmPlatformImpl";
|
| +
|
| + private static GcmPlatformImpl sInstance = null;
|
| +
|
| + private long mNativeGcmPlatformImplAndroid;
|
| + private Context mContext;
|
| +
|
| + private GcmPlatformImpl(long nativeGcmPlatformImplAndroid, Context context) {
|
| + mNativeGcmPlatformImplAndroid = nativeGcmPlatformImplAndroid;
|
| + mContext = context;
|
| + sInstance = this;
|
| + }
|
| +
|
| + /**
|
| + * Create a GcmPlatformImpl object, which is owned by GcmPlatformImplAndroid
|
| + * on the C++ side.
|
| + *
|
| + * @param nativeGcmPlatformImplAndroid The C++ object that owns us.
|
| + * @param context The app context.
|
| + */
|
| + @CalledByNative
|
| + private static GcmPlatformImpl create(int nativeGcmPlatformImplAndroid,
|
| + Context context) {
|
| + if (sInstance != null) {
|
| + throw new IllegalStateException("Already instantiated");
|
| + }
|
| + return new GcmPlatformImpl(nativeGcmPlatformImplAndroid, context);
|
| + }
|
| +
|
| + /**
|
| + * Called when our C++ counterpart is deleted. Clear the handle to our
|
| + * native C++ object, ensuring it's never called.
|
| + */
|
| + @CalledByNative
|
| + private void destroy() {
|
| + mNativeGcmPlatformImplAndroid = 0;
|
| + }
|
| +
|
| + /**
|
| + * Registers the app with GCM servers asynchronously. Calls
|
| + * nativeOnRegistrationFinished once this is done.
|
| + *
|
| + * @param appUniqueIdCurrentlyIgnored A unique string identifying the app.
|
| + * Currently ignored.
|
| + * @param senderIds List of project numbers or Google accounts identifying
|
| + * who is allowed to send messages to this application.
|
| + */
|
| + @CalledByNative
|
| + private void registerApp(String appUniqueIdCurrentlyIgnored, String[] senderIds) {
|
| + new AsyncTask<String, Void, String>() {
|
| + @Override
|
| + protected String doInBackground(String[] senderIds) {
|
| + try {
|
| + GCMRegistrar.checkDevice(mContext);
|
| + }
|
| + catch (UnsupportedOperationException ex) {
|
| + return ""; // Indicates failure
|
| + }
|
| + GCMRegistrar.checkManifest(mContext); // TODO: Do I want this?
|
| + String registrationId = GCMRegistrar.getRegistrationId(mContext);
|
| + if (registrationId.equals("")) {
|
| + GCMRegistrar.register(mContext, senderIds);
|
| + return null; // Indicates pending result
|
| + } else {
|
| + return registrationId;
|
| + }
|
| + }
|
| +
|
| + @Override
|
| + protected void onPostExecute(String registrationId) {
|
| + if (registrationId != null)
|
| + nativeOnRegistrationFinished(mNativeGcmPlatformImplAndroid,
|
| + registrationId);
|
| + }
|
| + }.execute(senderIds);
|
| + }
|
| +
|
| + // registrationId will be an empty string in case of failure.
|
| + private native void nativeOnRegistrationFinished(long nativeGcmPlatformImplAndroid,
|
| + String registrationId);
|
| + private native void nativeOnMessageReceived(long nativeGcmPlatformImplAndroid, String data);
|
| + private native void nativeOnMessagesDeletedByServer(long nativeGcmPlatformImplAndroid);
|
| +
|
| + /**
|
| + * Receives GCM registration events and messages rebroadcast by MultiplexingGcmListener.
|
| + */
|
| + public static class GcmListener extends MultiplexingGcmListener.AbstractListener {
|
| + /**
|
| + * Receiver for broadcasts by the multiplexed GCM service. It forwards them to
|
| + * GcmListener.
|
| + */
|
| + public static class Receiver extends MultiplexingGcmListener.AbstractListener.Receiver {
|
| + /**
|
| + * This class is public so that it can be instantiated by the Android runtime.
|
| + */
|
| + @Override
|
| + protected Class<?> getServiceClass() {
|
| + return GcmListener.class;
|
| + }
|
| + }
|
| +
|
| + private static final String TAG = "GcmListener";
|
| +
|
| + public GcmListener() {
|
| + super(TAG);
|
| + }
|
| +
|
| + @Override
|
| + protected void onMessage(Intent intent) {
|
| + final GcmPlatformImpl impl = GcmPlatformImpl.sInstance;
|
| + // HACK FOR DEMO: Don't start Chrome if it's not already running.
|
| + if (impl == null)
|
| + return;
|
| +
|
| + final String DATA_KEY = "data";
|
| + if (!intent.hasExtra(DATA_KEY)) {
|
| + // Not a GCM message for us (likely for sync or cloud print).
|
| + return;
|
| + }
|
| + final String data = intent.getExtras().getString(DATA_KEY);
|
| +
|
| + ThreadUtils.runOnUiThread(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + impl.nativeOnMessageReceived(impl.mNativeGcmPlatformImplAndroid, data);
|
| + }
|
| + });
|
| + }
|
| +
|
| + @Override
|
| + public void onRegistered(final String registrationId) {
|
| + final GcmPlatformImpl impl = GcmPlatformImpl.sInstance;
|
| + // Drop this event if it arrives after Chrome gets killed.
|
| + if (impl == null)
|
| + return;
|
| +
|
| + // TODO: Check that this onRegistered event actually corresponds
|
| + // to the current observer of GcmPlatformImplAndroid. Requires
|
| + // changes to Android GCM API.
|
| +
|
| + ThreadUtils.runOnUiThread(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + impl.nativeOnRegistrationFinished(impl.mNativeGcmPlatformImplAndroid,
|
| + registrationId);
|
| + }
|
| + });
|
| + }
|
| +
|
| + @Override
|
| + public void onUnregistered(String registrationId) {
|
| + Log.e(TAG, "onUnregistered not implemented");
|
| + }
|
| +
|
| + @Override
|
| + protected void onDeletedMessages(int total) {
|
| + final GcmPlatformImpl impl = GcmPlatformImpl.sInstance;
|
| + // HACK FOR DEMO: Don't start Chrome if it's not already running.
|
| + if (impl == null)
|
| + return;
|
| +
|
| + // FIXME: How do we know whether this message is for us, sync or cloud print?
|
| +
|
| + ThreadUtils.runOnUiThread(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + impl.nativeOnMessagesDeletedByServer(impl.mNativeGcmPlatformImplAndroid);
|
| + }
|
| + });
|
| + }
|
| + }
|
| +}
|
|
|