| Index: blimp/client/android/java/src/org/chromium/blimp/BlimpLibraryLoader.java
|
| diff --git a/blimp/client/android/java/src/org/chromium/blimp/BlimpLibraryLoader.java b/blimp/client/android/java/src/org/chromium/blimp/BlimpLibraryLoader.java
|
| index ff2fa8df0207ef18efef068245835a8c647715d3..7166e2b9e6ef920a3c62622e1d3376c8f2a945a3 100644
|
| --- a/blimp/client/android/java/src/org/chromium/blimp/BlimpLibraryLoader.java
|
| +++ b/blimp/client/android/java/src/org/chromium/blimp/BlimpLibraryLoader.java
|
| @@ -7,7 +7,9 @@ package org.chromium.blimp;
|
| import android.content.Context;
|
| import android.os.Handler;
|
|
|
| +import org.chromium.base.ObserverList;
|
| import org.chromium.base.ResourceExtractor;
|
| +import org.chromium.base.ThreadUtils;
|
| import org.chromium.base.annotations.JNINamespace;
|
| import org.chromium.base.library_loader.LibraryLoader;
|
| import org.chromium.base.library_loader.LibraryProcessType;
|
| @@ -31,12 +33,31 @@ public final class BlimpLibraryLoader {
|
| }
|
|
|
| /**
|
| + * Whether or not a call to {@link #startAsync(Context, Callback)} is/has actually attempted to
|
| + * load the native library.
|
| + */
|
| + private static boolean sLoadAttempted = false;
|
| +
|
| + /** If not {@code null} the result of a load attempt. */
|
| + private static Boolean sLibraryLoadResult;
|
| +
|
| + /**
|
| + * A list of {@link Callback} instances that still need to be notified of the result of the
|
| + * initial call to {@link #startAsync(Context, Callback)}.
|
| + */
|
| + private static ObserverList<Callback> sOutstandingCallbacks = new ObserverList<Callback>();
|
| +
|
| + /**
|
| * Disallow instantiation of this class.
|
| */
|
| private BlimpLibraryLoader() {}
|
|
|
| /**
|
| - * Starts asynchronously loading and registering the native libraries.
|
| + * Starts asynchronously loading and registering the native libraries. If this is called more
|
| + * than once, only the first caller will actually load the library. The subsequent calls will
|
| + * wait for the first call to finish and notify their {@link BlimpLibraryLoader.Callback}
|
| + * instances accordingly. Any calls to this after the library has finished loading will just
|
| + * have the initial load result posted back to {@code callback}.
|
| * @param context A {@link Context} object.
|
| * @param callback A {@link BlimpLibraryLoader.Callback} to be notified upon
|
| * completion.
|
| @@ -44,9 +65,26 @@ public final class BlimpLibraryLoader {
|
| */
|
| public static void startAsync(final Context context, final Callback callback)
|
| throws ProcessInitException {
|
| + ThreadUtils.assertOnUiThread();
|
| +
|
| + // Save the callback to be notified once loading and initializiation is one.
|
| + sOutstandingCallbacks.addObserver(callback);
|
| +
|
| + if (sLibraryLoadResult != null) {
|
| + // The library is already loaded, notify {@code callback} and skip the rest of the
|
| + // loading steps.
|
| + notifyCallbacksAndClear();
|
| + return;
|
| + }
|
| +
|
| + // If we're already in the process of loading, skip this call. Otherwise mark that we are
|
| + // loading and do the actual load. Subsequent calls won't run the load steps, but will wait
|
| + // for this load to finish.
|
| + if (sLoadAttempted) return;
|
| + sLoadAttempted = true;
|
| +
|
| ResourceExtractor extractor = ResourceExtractor.get(context);
|
| extractor.startExtractingResources();
|
| -
|
| LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER).ensureInitialized(context);
|
|
|
| extractor.addCompletionCallback(new Runnable() {
|
| @@ -58,13 +96,35 @@ public final class BlimpLibraryLoader {
|
| public void run() {
|
| // Only run nativeStartBlimp if we properly initialized native.
|
| boolean startResult = initResult && nativeStartBlimp();
|
| - if (callback != null) callback.onStartupComplete(startResult);
|
| + sLibraryLoadResult = new Boolean(startResult);
|
| +
|
| + // Notify any oustanding callers to #startAsync().
|
| + notifyCallbacksAndClear();
|
| }
|
| });
|
| }
|
| });
|
| }
|
|
|
| + private static void notifyCallbacksAndClear() {
|
| + for (Callback callback : sOutstandingCallbacks) {
|
| + notifyCallback(callback);
|
| + }
|
| +
|
| + // Clear the callback list so we don't hold onto references to callers.
|
| + sOutstandingCallbacks.clear();
|
| + }
|
| +
|
| + private static void notifyCallback(final Callback callback) {
|
| + new Handler().post(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + ThreadUtils.assertOnUiThread();
|
| + callback.onStartupComplete(sLibraryLoadResult);
|
| + }
|
| + });
|
| + }
|
| +
|
| // Native methods.
|
| private static native boolean nativeInitializeBlimp(Context context);
|
| private static native boolean nativeStartBlimp();
|
|
|