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(); |