Index: android_webview/java/src/org/chromium/android_webview/AwContents.java |
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java |
index 0a0e8530776bffcb7df689bea0ff2b19e862f171..972360b86b6aeb3b246e46e78ee7e81f7d1eb518 100644 |
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java |
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java |
@@ -77,6 +77,7 @@ import java.net.URL; |
import java.util.HashMap; |
import java.util.Locale; |
import java.util.Map; |
+import java.util.WeakHashMap; |
import java.util.concurrent.Callable; |
/** |
@@ -207,7 +208,7 @@ public class AwContents implements SmartClipProvider, |
private final Context mContext; |
private final int mAppTargetSdkVersion; |
private ContentViewCore mContentViewCore; |
- private WindowAndroid mWindowAndroid; |
+ private WindowAndroidWrapper mWindowAndroid; |
private WebContents mWebContents; |
private NavigationController mNavigationController; |
private final AwContentsClient mContentsClient; |
@@ -287,16 +288,13 @@ public class AwContents implements SmartClipProvider, |
private static final class DestroyRunnable implements Runnable { |
private final long mNativeAwContents; |
- private final WindowAndroid mWindowAndroid; |
- private DestroyRunnable(long nativeAwContents, WindowAndroid windowAndroid) { |
+ private DestroyRunnable(long nativeAwContents) { |
mNativeAwContents = nativeAwContents; |
- mWindowAndroid = windowAndroid; |
} |
@Override |
public void run() { |
nativeDestroy(mNativeAwContents); |
- mWindowAndroid.destroy(); |
} |
} |
@@ -848,6 +846,60 @@ public class AwContents implements SmartClipProvider, |
mContainerView.requestLayout(); |
} |
+ // This class destroys the WindowAndroid when after it is gc-ed. |
+ private static class WindowAndroidWrapper { |
+ private final WindowAndroid mWindowAndroid; |
+ private final CleanupReference mCleanupReference; |
+ |
+ private static final class DestroyRunnable implements Runnable { |
+ private final WindowAndroid mWindowAndroid; |
+ private DestroyRunnable(WindowAndroid windowAndroid) { |
+ mWindowAndroid = windowAndroid; |
+ } |
+ @Override |
+ public void run() { |
+ mWindowAndroid.destroy(); |
+ } |
+ } |
+ |
+ public WindowAndroidWrapper(WindowAndroid windowAndroid) { |
+ mWindowAndroid = windowAndroid; |
+ mCleanupReference = |
+ new CleanupReference(this, new DestroyRunnable(windowAndroid)); |
+ } |
+ |
+ public WindowAndroid getWindowAndroid() { |
+ return mWindowAndroid; |
+ } |
+ } |
+ private static WindowAndroidWrapper sCachedWindowAndroid; |
+ private static WeakHashMap<Activity, WindowAndroidWrapper> sActivityWindowMap; |
Torne
2015/05/15 12:48:13
The hash map won't release the WindowAndroidWrappe
boliu
2015/05/15 13:34:01
Yeah I think that's fine. If another webview is cr
|
+ |
+ // getWindowAndroid is only called on UI thread, so there are no threading issues with lazy |
+ // initialization. |
+ @SuppressFBWarnings("LI_LAZY_INIT_STATIC") |
+ private static WindowAndroidWrapper getWindowAndroid(Context context) { |
+ // TODO(boliu): WebView does not currently initialize ApplicationStatus, crbug.com/470582. |
+ Activity activity = ContentViewCore.activityFromContext(context); |
+ if (activity == null) { |
+ if (sCachedWindowAndroid == null) { |
+ sCachedWindowAndroid = new WindowAndroidWrapper( |
+ new WindowAndroid(context.getApplicationContext())); |
+ } |
+ return sCachedWindowAndroid; |
+ } |
+ |
+ if (sActivityWindowMap == null) sActivityWindowMap = new WeakHashMap<>(); |
+ WindowAndroidWrapper activityWindowAndroid = sActivityWindowMap.get(activity); |
+ if (activityWindowAndroid == null) { |
+ final boolean listenToActivityState = false; |
+ activityWindowAndroid = new WindowAndroidWrapper( |
+ new ActivityWindowAndroid(activity, listenToActivityState)); |
+ sActivityWindowMap.put(activity, activityWindowAndroid); |
+ } |
+ return activityWindowAndroid; |
+ } |
+ |
/* Common initialization routine for adopting a native AwContents instance into this |
* java instance. |
* |
@@ -871,15 +923,10 @@ public class AwContents implements SmartClipProvider, |
WebContents webContents = nativeGetWebContents(mNativeAwContents); |
- // WebView does not currently initialize ApplicationStatus, crbug.com/470582. |
- final boolean listenToActivityState = false; |
- Activity activity = ContentViewCore.activityFromContext(mContext); |
- mWindowAndroid = activity != null |
- ? new ActivityWindowAndroid(activity, listenToActivityState) |
- : new WindowAndroid(mContext.getApplicationContext()); |
- mContentViewCore = createAndInitializeContentViewCore( |
- mContainerView, mContext, mInternalAccessAdapter, webContents, |
- new AwGestureStateListener(), mContentViewClient, mZoomControls, mWindowAndroid); |
+ mWindowAndroid = getWindowAndroid(mContext); |
+ mContentViewCore = createAndInitializeContentViewCore(mContainerView, mContext, |
+ mInternalAccessAdapter, webContents, new AwGestureStateListener(), |
+ mContentViewClient, mZoomControls, mWindowAndroid.getWindowAndroid()); |
nativeSetJavaPeers(mNativeAwContents, this, mWebContentsDelegate, mContentsClientBridge, |
mIoThreadClient, mInterceptNavigationDelegate); |
mWebContents = mContentViewCore.getWebContents(); |
@@ -892,7 +939,7 @@ public class AwContents implements SmartClipProvider, |
// The native side object has been bound to this java instance, so now is the time to |
// bind all the native->java relationships. |
mCleanupReference = |
- new CleanupReference(this, new DestroyRunnable(mNativeAwContents, mWindowAndroid)); |
+ new CleanupReference(this, new DestroyRunnable(mNativeAwContents)); |
} |
private void installWebContentsObserver() { |
@@ -2452,7 +2499,7 @@ public class AwContents implements SmartClipProvider, |
@CalledByNative |
private void postInvalidateOnAnimation() { |
- if (!mWindowAndroid.isInsideVSync()) { |
+ if (!mWindowAndroid.getWindowAndroid().isInsideVSync()) { |
mContainerView.postInvalidateOnAnimation(); |
} else { |
mContainerView.invalidate(); |