import android.preference.PreferenceManager;
import android.util.Log;
-import com.google.android.gcm.GCMRegistrar;
-
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import org.chromium.base.ThreadUtils;
import org.chromium.base.library_loader.ProcessInitException;
+import org.chromium.content.app.ContentApplication;
import org.chromium.content.browser.BrowserStartupController;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
new AsyncTask<Void, Void, String>() {
@Override
protected String doInBackground(Void... voids) {
+ // TODO(johnme): Should check if GMS is installed on the device first. Ditto below.
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;
+ String subtype = appId;
+ GoogleCloudMessagingV2 gcm = new GoogleCloudMessagingV2(mContext);
+ String registrationId = gcm.register(subtype, senderIds);
+ return registrationId;
+ } catch (IOException ex) {
+ Log.w(TAG, "GCMv2 registration failed for " + appId, ex);
+ return "";
}
}
@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(final String appId) {
- new AsyncTask<Void, Void, UnregisterResult>() {
+ new AsyncTask<Void, Void, Boolean>() {
@Override
- protected UnregisterResult doInBackground(Void... voids) {
+ protected Boolean doInBackground(Void... voids) {
try {
- GCMRegistrar.checkDevice(mContext);
- } catch (UnsupportedOperationException ex) {
- return UnregisterResult.FAILED;
- }
- if (!GCMRegistrar.isRegistered(mContext)) {
- return UnregisterResult.SUCCESS;
+ String subtype = appId;
+ GoogleCloudMessagingV2 gcm = new GoogleCloudMessagingV2(mContext);
+ gcm.unregister(subtype);
+ return true;
+ } catch (IOException ex) {
+ Log.w(TAG, "GCMv2 unregistration failed for " + appId, ex);
+ return false;
}
- // 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);
+ protected void onPostExecute(Boolean success) {
+ nativeOnUnregisterFinished(mNativeGCMDriverAndroid, appId, success);
}
}.execute();
}
- 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) {
- sInstance.nativeOnRegisterFinished(sInstance.mNativeGCMDriverAndroid, getLastAppId(),
- registrationId, true);
- }
- }
-
- 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) {
- sInstance.nativeOnUnregisterFinished(sInstance.mNativeGCMDriverAndroid, getLastAppId(),
- true);
- }
- }
-
static void onMessageReceived(Context context, final String appId, final Bundle extras) {
- final String pushApiDataKey = "data";
- if (!extras.containsKey(pushApiDataKey)) {
- // For now on Android only the Push API uses GCMDriver. To avoid double-handling of
- // messages already handled in Java by other implementations of MultiplexingGcmListener,
- // and unnecessarily waking up the browser processes for all existing GCM messages that
- // are received by Chrome on Android, we currently discard messages unless they are
- // destined for the Push API.
- // TODO(johnme): Find a better way of distinguishing messages that should be delivered
- // to native from messages that have already been delivered to Java, for example by
- // refactoring other implementations of MultiplexingGcmListener to instead register with
- // this class, and distinguish them based on appId (which also requires GCM to start
- // sending us the app IDs).
- return;
- }
-
// TODO(johnme): Store message and redeliver later if Chrome is killed before delivery.
ThreadUtils.assertOnUiThread();
launchNativeThen(context, new Runnable() {
@Override public void run() {
+ final String bundleSubtype = "subtype";
final String bundleSenderId = "from";
final String bundleCollapseKey = "collapse_key";
final String bundleGcmplex = "com.google.ipc.invalidation.gcmmplex.";
List<String> dataKeysAndValues = new ArrayList<String>();
for (String key : extras.keySet()) {
// TODO(johnme): Check there aren't other keys that we need to exclude.
- if (key == bundleSenderId || key == bundleCollapseKey ||
- key.startsWith(bundleGcmplex))
+ if (key.equals(bundleSubtype) || key.equals(bundleSenderId) ||
+ key.equals(bundleCollapseKey) || key.startsWith(bundleGcmplex))
continue;
dataKeysAndValues.add(key);
dataKeysAndValues.add(extras.getString(key));
}
+ String guessedAppId = GCMListener.UNKNOWN_APP_ID.equals(appId) ? getLastAppId()
+ : appId;
sInstance.nativeOnMessageReceived(sInstance.mNativeGCMDriverAndroid,
- getLastAppId(), senderId, collapseKey,
+ guessedAppId, senderId, collapseKey,
dataKeysAndValues.toArray(new String[dataKeysAndValues.size()]));
}
});
ThreadUtils.assertOnUiThread();
launchNativeThen(context, new Runnable() {
@Override public void run() {
- sInstance.nativeOnMessagesDeleted(sInstance.mNativeGCMDriverAndroid,
- getLastAppId());
+ String guessedAppId = GCMListener.UNKNOWN_APP_ID.equals(appId) ? getLastAppId()
+ : appId;
+ sInstance.nativeOnMessagesDeleted(sInstance.mNativeGCMDriverAndroid, guessedAppId);
}
});
}
return;
}
- // TODO(johnme): Call ChromeMobileApplication.initCommandLine(context) or
- // ChromeShellApplication.initCommandLine() as appropriate.
+ ContentApplication.initCommandLine(context);
try {
BrowserStartupController.get(context).startBrowserProcessesSync(false);