Chromium Code Reviews| Index: components/gcm_driver/instance_id/android/java/src/org/chromium/components/gcm_driver/instance_id/InstanceIDBridge.java |
| diff --git a/components/gcm_driver/instance_id/android/java/src/org/chromium/components/gcm_driver/instance_id/InstanceIDBridge.java b/components/gcm_driver/instance_id/android/java/src/org/chromium/components/gcm_driver/instance_id/InstanceIDBridge.java |
| index 1f61bd564a7f0cf52a92ea63e8227cd33b2bf8f9..b0c6ec0e5d32bec7f596f06eade20ffccbc24479 100644 |
| --- a/components/gcm_driver/instance_id/android/java/src/org/chromium/components/gcm_driver/instance_id/InstanceIDBridge.java |
| +++ b/components/gcm_driver/instance_id/android/java/src/org/chromium/components/gcm_driver/instance_id/InstanceIDBridge.java |
| @@ -14,6 +14,7 @@ import org.chromium.base.annotations.CalledByNative; |
| import org.chromium.base.annotations.JNINamespace; |
| import java.io.IOException; |
| +import java.util.concurrent.ExecutionException; |
| /** |
| * Wraps InstanceID and InstanceIDWithSubtype so they can be used over JNI. |
| @@ -23,7 +24,9 @@ import java.io.IOException; |
| public class InstanceIDBridge { |
| /** Underlying InstanceID. May be shared by multiple InstanceIDBridges. */ |
| private final InstanceID mInstanceID; |
| - private final long mNativeInstanceIDAndroid; |
| + private long mNativeInstanceIDAndroid; |
| + |
| + private static boolean sBlockOnAsyncTasksForTesting = false; |
| private InstanceIDBridge( |
| long nativeInstanceIDAndroid, Context context, String subtype) { |
| @@ -51,6 +54,16 @@ public class InstanceIDBridge { |
| mNativeInstanceIDAndroid = 0; |
| } |
| + /** |
| + * Enable this in tests such as unit tests where C++ never returns to the Java looper and the |
| + * NestedSystemMessageHandler is disabled. In such tests, the onPostExecute of AsyncTasks will |
| + * never get executed, so instead we'll synchronously block until each task completes. |
|
Peter Beverloo
2016/04/15 00:00:17
Please avoid use of "we" in comments. (Also goes f
johnme
2016/04/15 16:00:42
Done.
|
| + */ |
| + @CalledByNative |
| + private static void setBlockOnAsyncTasksForTesting(boolean block) { |
| + sBlockOnAsyncTasksForTesting = block; |
| + } |
| + |
| /** Wrapper for {@link InstanceID#getId}. */ |
| @CalledByNative |
| public String getId() { |
| @@ -74,9 +87,9 @@ public class InstanceIDBridge { |
| for (int i = 0; i < extrasStrings.length; i += 2) { |
| extras.putString(extrasStrings[i], extrasStrings[i + 1]); |
| } |
| - new AsyncTask<Void, Void, String>() { |
| + new BridgeAsyncTask<String>() { |
| @Override |
| - protected String doInBackground(Void... params) { |
| + protected String doBackgroundWork() { |
| try { |
| return mInstanceID.getToken(authorizedEntity, scope, extras); |
| } catch (IOException ex) { |
| @@ -84,10 +97,8 @@ public class InstanceIDBridge { |
| } |
| } |
| @Override |
| - protected void onPostExecute(String token) { |
| - if (mNativeInstanceIDAndroid != 0) { |
| - nativeDidGetToken(mNativeInstanceIDAndroid, requestId, token); |
| - } |
| + protected void sendResultToNative(String token) { |
| + nativeDidGetToken(mNativeInstanceIDAndroid, requestId, token); |
| } |
| }.execute(); |
| } |
| @@ -96,9 +107,9 @@ public class InstanceIDBridge { |
| @CalledByNative |
| private void deleteToken( |
| final int requestId, final String authorizedEntity, final String scope) { |
| - new AsyncTask<Void, Void, Boolean>() { |
| + new BridgeAsyncTask<Boolean>() { |
| @Override |
| - protected Boolean doInBackground(Void... params) { |
| + protected Boolean doBackgroundWork() { |
| try { |
| mInstanceID.deleteToken(authorizedEntity, scope); |
| return true; |
| @@ -107,10 +118,8 @@ public class InstanceIDBridge { |
| } |
| } |
| @Override |
| - protected void onPostExecute(Boolean success) { |
| - if (mNativeInstanceIDAndroid != 0) { |
| - nativeDidDeleteToken(mNativeInstanceIDAndroid, requestId, success); |
| - } |
| + protected void sendResultToNative(Boolean success) { |
| + nativeDidDeleteToken(mNativeInstanceIDAndroid, requestId, success); |
| } |
| }.execute(); |
| } |
| @@ -118,9 +127,9 @@ public class InstanceIDBridge { |
| /** Async wrapper for {@link InstanceID#deleteInstanceID}. */ |
| @CalledByNative |
| private void deleteInstanceID(final int requestId) { |
| - new AsyncTask<Void, Void, Boolean>() { |
| + new BridgeAsyncTask<Boolean>() { |
| @Override |
| - protected Boolean doInBackground(Void... params) { |
| + protected Boolean doBackgroundWork() { |
| try { |
| mInstanceID.deleteInstanceID(); |
| return true; |
| @@ -129,10 +138,8 @@ public class InstanceIDBridge { |
| } |
| } |
| @Override |
| - protected void onPostExecute(Boolean success) { |
| - if (mNativeInstanceIDAndroid != 0) { |
| - nativeDidDeleteID(mNativeInstanceIDAndroid, requestId, success); |
| - } |
| + protected void sendResultToNative(Boolean success) { |
| + nativeDidDeleteID(mNativeInstanceIDAndroid, requestId, success); |
| } |
| }.execute(); |
| } |
| @@ -143,4 +150,40 @@ public class InstanceIDBridge { |
| long nativeInstanceIDAndroid, int requestId, boolean success); |
| private native void nativeDidDeleteID( |
| long nativeInstanceIDAndroid, int requestId, boolean success); |
| + |
| + /** Custom AsyncTask wrapper to workaround onPostExecute not working in tests. */ |
|
Peter Beverloo
2016/04/15 00:00:17
Thank you for generalizing this!
Please give this
johnme
2016/04/15 16:00:42
Done.
|
| + private abstract class BridgeAsyncTask<Result> { |
| + protected abstract Result doBackgroundWork(); |
| + |
| + protected abstract void sendResultToNative(Result result); |
| + |
| + public void execute() { |
| + AsyncTask<Void, Void, Result> task = new AsyncTask<Void, Void, Result>() { |
| + @Override |
| + protected Result doInBackground(Void... params) { |
| + return doBackgroundWork(); |
| + } |
| + @Override |
| + protected void onPostExecute(Result result) { |
| + if (!sBlockOnAsyncTasksForTesting && mNativeInstanceIDAndroid != 0) { |
| + sendResultToNative(result); |
| + } |
| + } |
| + }; |
| + task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
|
Peter Beverloo
2016/04/15 00:00:17
What's wrong with .execute()? The documentation sa
johnme
2016/04/15 16:00:42
The default SERIAL_EXECUTOR is global to the app's
|
| + // Normally onPostExecute will be run once doInBackground completes. But during tests |
| + // (other than content_browsertests and layout tests) onPostExecute never runs because |
| + // C++ is blocking the UI thread (and the Java message loop isn't nested). In such tests |
| + // we use AsyncTask.get() to synchronously block until doInBackground completes. |
| + if (sBlockOnAsyncTasksForTesting) { |
| + Result result; |
| + try { |
| + result = task.get(); |
| + } catch (InterruptedException | ExecutionException e) { |
| + throw new IllegalStateException(e); // Shouldn't happen in tests :-p |
|
Peter Beverloo
2016/04/15 00:00:17
No smileys in comments please :-)
johnme
2016/04/15 16:00:42
Spoil sport :-p
|
| + } |
| + sendResultToNative(result); |
| + } |
| + } |
| + } |
| } |