Chromium Code Reviews| 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 4d80be73e6d07d234a2cfeef69823b3e5675638d..9b59dbe22adbc917aa72b6b6cd43b180d5897832 100644 |
| --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java |
| +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java |
| @@ -94,6 +94,8 @@ public class AwContents implements SmartClipProvider { |
| // produce little visible difference. |
| private static final float ZOOM_CONTROLS_EPSILON = 0.007f; |
| + private static final String BLANK_URL = "about:blank"; |
| + |
| /** |
| * WebKit hit test related data strcutre. These are used to implement |
| * getHitTestResult, requestFocusNodeHref, requestImageRef methods in WebView. |
| @@ -182,6 +184,15 @@ public class AwContents implements SmartClipProvider { |
| } |
| } |
| + /** |
| + * Callback used when flushing the visual state, see {@link #flushVisualState}. |
| + */ |
| + @VisibleForTesting |
| + public abstract static class VisualStateFlushCallback { |
| + public abstract void onComplete(); |
| + public abstract void onFailure(int reason); |
| + } |
| + |
| private long mNativeAwContents; |
| private final AwBrowserContext mBrowserContext; |
| private ViewGroup mContainerView; |
| @@ -256,6 +267,9 @@ public class AwContents implements SmartClipProvider { |
| // when in this state. |
| private boolean mTemporarilyDetached; |
| + // This flag indicates that we're currently loading BLANK_URL from loadBlankNow. |
| + private boolean mIsLoadingBlankNow = false; |
| + |
| // True when this AwContents has been destroyed. |
| // Do not use directly, call isDestroyed() instead. |
| private boolean mIsDestroyed = false; |
| @@ -552,6 +566,34 @@ public class AwContents implements SmartClipProvider { |
| } |
| /** |
| + * Extension of {@link AwWebContentsObserver} that adds functionality that {@link AwContents} |
| + * encapsulates. |
| + */ |
| + private class AwContentsAwWebContentsObserver extends AwWebContentsObserver { |
| + public AwContentsAwWebContentsObserver( |
| + WebContents webContents, AwContentsClient awContentsClient) { |
| + super(webContents, awContentsClient); |
| + } |
| + |
| + @Override |
| + public void didNavigateMainFrame(String url, String baseUrl, |
| + boolean isNavigationToDifferentPage, boolean isFragmentNavigation) { |
| + super.didNavigateMainFrame( |
| + url, baseUrl, isNavigationToDifferentPage, isFragmentNavigation); |
| + // Waiting for didNavigateMainFrame before flashing ensures that the flush callback will |
|
mkosiba (inactive)
2015/01/19 11:15:58
nit: before flushing?
Ignacio Solla
2015/01/19 18:26:41
Done.
|
| + // not be received before BLANK_URL has made it into the screen. |
| + flushVisualStateIfLoadingBlankNow(url); |
| + } |
| + |
| + @Override |
| + public void didFailLoad(boolean isProvisionalLoad, boolean isMainFrame, int errorCode, |
| + String description, String failingUrl) { |
| + super.didFailLoad(isProvisionalLoad, isMainFrame, errorCode, description, failingUrl); |
| + flushVisualStateIfLoadingBlankNow(failingUrl); |
| + } |
| + } |
| + |
| + /** |
| * @param browserContext the browsing context to associate this view contents with. |
| * @param containerView the view-hierarchy item this object will be bound to. |
| * @param context the context to use, usually containerView.getContext(). |
| @@ -835,7 +877,7 @@ public class AwContents implements SmartClipProvider { |
| if (mWebContentsObserver != null) { |
| mWebContentsObserver.detachFromWebContents(); |
| } |
| - mWebContentsObserver = new AwWebContentsObserver(mWebContents, mContentsClient); |
| + mWebContentsObserver = new AwContentsAwWebContentsObserver(mWebContents, mContentsClient); |
| } |
| /** |
| @@ -978,6 +1020,11 @@ public class AwContents implements SmartClipProvider { |
| return mNavigationController; |
| } |
| + @VisibleForTesting |
| + public Context getContext() { |
|
mkosiba (inactive)
2015/01/19 11:15:58
I don't think you need this, the base test class h
Ignacio Solla
2015/01/19 18:26:41
Done.
|
| + return mContext; |
| + } |
| + |
| // Can be called from any thread. |
| public AwSettings getSettings() { |
| return mSettings; |
| @@ -1144,6 +1191,38 @@ public class AwContents implements SmartClipProvider { |
| } |
| /** |
| + * Loads "about:blank" and draws the background color specified by |
| + * {@link AwContents#setBackgroundColor(int)} immediately without having to wait for the |
| + * asynchronous load to complete ({@link AwContentsClient#onPageFinished(String)}). |
| + * |
| + * <p>This API is useful when recycling container views and want to clear the contents from the |
| + * old page immediately. |
| + */ |
| + public void loadBlankNow() { |
| + if (mIsLoadingBlankNow) { |
| + return; |
| + } |
| + loadUrl(new LoadUrlParams(BLANK_URL)); |
| + mIsLoadingBlankNow = true; |
| + } |
| + |
| + private void flushVisualStateIfLoadingBlankNow(String url) { |
| + if (mIsLoadingBlankNow && BLANK_URL.equals(url)) { |
| + flushVisualState(new VisualStateFlushCallback() { |
| + @Override |
| + public void onFailure(int reason) { |
| + mIsLoadingBlankNow = false; |
|
mkosiba (inactive)
2015/01/19 11:15:58
I think Bo mentioned you need to postInvalidateOnA
Ignacio Solla
2015/01/19 18:26:41
I propagate this bit to BVR. I'll ask Bo if we sti
Ignacio Solla
2015/01/19 18:31:57
Bo confirmed offline that EnsureContinuousInvalida
|
| + } |
| + |
| + @Override |
| + public void onComplete() { |
| + mIsLoadingBlankNow = false; |
| + } |
| + }); |
| + } |
| + } |
| + |
| + /** |
| * Load url without fixing up the url string. Consumers of ContentView are responsible for |
| * ensuring the URL passed in is properly formatted (i.e. the scheme has been added if left |
| * off during user input). |
| @@ -1243,7 +1322,9 @@ public class AwContents implements SmartClipProvider { |
| // Do not ask the ContentViewCore for the background color, as it will always |
| // report white prior to initial navigation or post destruction, whereas we want |
| // to use the client supplied base value in those cases. |
| - if (isDestroyed() || !mContentsClient.isCachedRendererBackgroundColorValid()) { |
| + // When loading BLANK_URL we want to draw the client supplied base color immediately. |
| + if (isDestroyed() || !mContentsClient.isCachedRendererBackgroundColorValid() |
| + || mIsLoadingBlankNow) { |
| return mBaseBackgroundColor; |
| } |
| return mContentsClient.getCachedRendererBackgroundColor(); |
| @@ -2020,6 +2101,22 @@ public class AwContents implements SmartClipProvider { |
| if (!isDestroyed()) nativeSetJsOnlineProperty(mNativeAwContents, networkUp); |
| } |
| + /** |
| + * Flush the visual state. |
| + * |
| + * Flushing the visual state means queuing a callback in Blink that will be invoked when the |
| + * contents of the DOM tree at the moment that the callback was enqueued (or later) are drawn |
| + * into the screen. In other words, the following events need to happen before the callback is |
| + * invoked: |
| + * 1. The DOM tree is committed becoming the pending tree - see ThreadProxy::BeginMainFrame |
| + * 2. The pending tree is activated becoming the active tree |
| + * 3. A frame swap happens that draws the active tree into the screen |
| + */ |
| + @VisibleForTesting |
| + public void flushVisualState(VisualStateFlushCallback callback) { |
| + nativeFlushVisualState(mNativeAwContents, callback); |
| + } |
| + |
| //-------------------------------------------------------------------------------------------- |
| // Methods called from native via JNI |
| //-------------------------------------------------------------------------------------------- |
| @@ -2123,6 +2220,15 @@ public class AwContents implements SmartClipProvider { |
| mContentsClient.getCallbackHelper().postOnNewPicture(mPictureListenerContentProvider); |
| } |
| + @CalledByNative |
| + public static void flushVisualStateCallback(VisualStateFlushCallback callback, int value) { |
| + if (value == 0) { |
| + callback.onComplete(); |
| + } else { |
| + callback.onFailure(value); |
| + } |
| + } |
| + |
| // Called as a result of nativeUpdateLastHitTestData. |
| @CalledByNative |
| private void updateHitTestData( |
| @@ -2337,8 +2443,9 @@ public class AwContents implements SmartClipProvider { |
| @Override |
| public void onDraw(Canvas canvas) { |
| - if (isDestroyed()) { |
| - TraceEvent.instant("EarlyOut_destroyed"); |
| + if (isDestroyed() || mIsLoadingBlankNow) { |
| + String trace = isDestroyed() ? "EarlyOut_destroyed" : "EarlyOut_loadingBlank"; |
| + TraceEvent.instant(trace); |
| canvas.drawColor(getEffectiveBackgroundColor()); |
| return; |
| } |
| @@ -2688,6 +2795,8 @@ public class AwContents implements SmartClipProvider { |
| private native long nativeGetAwDrawGLViewContext(long nativeAwContents); |
| private native long nativeCapturePicture(long nativeAwContents, int width, int height); |
| private native void nativeEnableOnNewPicture(long nativeAwContents, boolean enabled); |
| + private native void nativeFlushVisualState( |
| + long nativeAwContents, VisualStateFlushCallback callback); |
| private native void nativeClearView(long nativeAwContents); |
| private native void nativeSetExtraHeadersForUrl(long nativeAwContents, |
| String url, String extraHeaders); |