Commit c196c218 authored by boliu's avatar boliu Committed by Commit bot

[WebView] Add test for visual state API when view dettached.

Calling the visual state API when the container view is dettached
must draw the contents correctly when the callback is received.
We add a test for that.

We also fix a possible crash if the container view is dettached
after insertVisualStateCallback has been called but before
the callback has been received.

Original author igsolla@chromium.org
BUG=461369, 457184

Review URL: https://codereview.chromium.org/972013003

Cr-Commit-Position: refs/heads/master@{#319112}
parent e9e5cc28
...@@ -271,6 +271,8 @@ public class AwContents implements SmartClipProvider, ...@@ -271,6 +271,8 @@ public class AwContents implements SmartClipProvider,
// when in this state. // when in this state.
private boolean mTemporarilyDetached; private boolean mTemporarilyDetached;
private Handler mHandler;
// True when this AwContents has been destroyed. // True when this AwContents has been destroyed.
// Do not use directly, call isDestroyed() instead. // Do not use directly, call isDestroyed() instead.
private boolean mIsDestroyed = false; private boolean mIsDestroyed = false;
...@@ -603,6 +605,7 @@ public class AwContents implements SmartClipProvider, ...@@ -603,6 +605,7 @@ public class AwContents implements SmartClipProvider,
mContainerView = containerView; mContainerView = containerView;
mContainerView.setWillNotDraw(false); mContainerView.setWillNotDraw(false);
mHandler = new Handler();
mContext = context; mContext = context;
mInternalAccessAdapter = internalAccessAdapter; mInternalAccessAdapter = internalAccessAdapter;
mNativeGLDelegate = nativeGLDelegate; mNativeGLDelegate = nativeGLDelegate;
...@@ -941,7 +944,7 @@ public class AwContents implements SmartClipProvider, ...@@ -941,7 +944,7 @@ public class AwContents implements SmartClipProvider,
nativeOnDetachedFromWindow(mNativeAwContents); nativeOnDetachedFromWindow(mNativeAwContents);
} }
mIsDestroyed = true; mIsDestroyed = true;
new Handler().post(new Runnable() { mHandler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
destroyNatives(); destroyNatives();
...@@ -2220,7 +2223,7 @@ public class AwContents implements SmartClipProvider, ...@@ -2220,7 +2223,7 @@ public class AwContents implements SmartClipProvider,
final VisualStateCallback callback, final long requestId) { final VisualStateCallback callback, final long requestId) {
// Posting avoids invoking the callback inside invoking_composite_ // Posting avoids invoking the callback inside invoking_composite_
// (see synchronous_compositor_impl.cc and crbug/452530). // (see synchronous_compositor_impl.cc and crbug/452530).
mContainerView.getHandler().post(new Runnable() { mHandler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
callback.onComplete(requestId); callback.onComplete(requestId);
......
...@@ -6,6 +6,8 @@ package org.chromium.android_webview.test; ...@@ -6,6 +6,8 @@ package org.chromium.android_webview.test;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Rect;
import android.os.Build;
import android.test.suitebuilder.annotation.SmallTest; import android.test.suitebuilder.annotation.SmallTest;
import android.view.View; import android.view.View;
import android.webkit.WebChromeClient; import android.webkit.WebChromeClient;
...@@ -16,6 +18,7 @@ import org.chromium.android_webview.test.util.CommonResources; ...@@ -16,6 +18,7 @@ import org.chromium.android_webview.test.util.CommonResources;
import org.chromium.android_webview.test.util.GraphicsTestUtils; import org.chromium.android_webview.test.util.GraphicsTestUtils;
import org.chromium.android_webview.test.util.JavascriptEventObserver; import org.chromium.android_webview.test.util.JavascriptEventObserver;
import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Feature;
import org.chromium.base.test.util.MinAndroidSdkLevel;
import org.chromium.content.browser.ContentViewCore; import org.chromium.content.browser.ContentViewCore;
import org.chromium.content.browser.test.util.CallbackHelper; import org.chromium.content.browser.test.util.CallbackHelper;
import org.chromium.content.browser.test.util.DOMUtils; import org.chromium.content.browser.test.util.DOMUtils;
...@@ -28,6 +31,7 @@ import java.util.concurrent.atomic.AtomicReference; ...@@ -28,6 +31,7 @@ import java.util.concurrent.atomic.AtomicReference;
/** /**
* Visual state related tests. * Visual state related tests.
*/ */
@MinAndroidSdkLevel(Build.VERSION_CODES.KITKAT)
public class VisualStateTest extends AwTestBase { public class VisualStateTest extends AwTestBase {
private static final String WAIT_FOR_JS_TEST_URL = private static final String WAIT_FOR_JS_TEST_URL =
...@@ -321,6 +325,83 @@ public class VisualStateTest extends AwTestBase { ...@@ -321,6 +325,83 @@ public class VisualStateTest extends AwTestBase {
assertTrue(testFinishedSignal.await(AwTestBase.WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS)); assertTrue(testFinishedSignal.await(AwTestBase.WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS));
} }
@Feature({"AndroidWebView"})
@SmallTest
public void testVisualStateCallbackWhenContainerViewDetached()
throws Throwable {
final CountDownLatch readyToEnterFullscreenSignal = new CountDownLatch(1);
final CountDownLatch hasCustomViewSignal = new CountDownLatch(1);
final CountDownLatch testFinishedSignal = new CountDownLatch(1);
final AtomicReference<AwContents> awContentsRef = new AtomicReference<>();
final AtomicReference<View> customViewRef = new AtomicReference<>();
final TestAwContentsClient awContentsClient = new TestAwContentsClient() {
@Override
public void onPageFinished(String url) {
super.onPageFinished(url);
readyToEnterFullscreenSignal.countDown();
}
@Override
public void onShowCustomView(
final View customView, WebChromeClient.CustomViewCallback callback) {
// Please note that we don't attach the custom view to the window here
// (awContentsClient is an instance of TestAwContentsClient, not
// FullScreenVideoTestAwContentsClient).
customView.setClipBounds(new Rect(0, 0, 100, 100));
customView.measure(100, 100);
customView.layout(0, 0, 100, 100);
customViewRef.set(customView);
hasCustomViewSignal.countDown();
}
};
final AwTestContainerView testView = createAwTestContainerViewOnMainSync(awContentsClient);
final AwContents awContents = testView.getAwContents();
awContentsRef.set(awContents);
final ContentViewCore contentViewCore = testView.getContentViewCore();
enableJavaScriptOnUiThread(awContents);
awContents.getSettings().setFullscreenSupported(true);
// JS will notify this observer once it has entered fullscreen.
final JavascriptEventObserver jsObserver = new JavascriptEventObserver();
runTestOnUiThread(new Runnable() {
@Override
public void run() {
jsObserver.register(contentViewCore, "jsObserver");
}
});
loadUrlSync(awContents, awContentsClient.getOnPageFinishedHelper(), FULLSCREEN_TEST_URL);
assertTrue(readyToEnterFullscreenSignal.await(
AwTestBase.WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS));
DOMUtils.clickNode(VisualStateTest.this, contentViewCore, ENTER_FULLSCREEN_CONTROL_ID);
assertTrue(hasCustomViewSignal.await(AwTestBase.WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS));
assertTrue(jsObserver.waitForEvent(WAIT_TIMEOUT_MS));
runTestOnUiThread(new Runnable() {
@Override
public void run() {
awContents.insertVisualStateCallback(20, new VisualStateCallback() {
@Override
public void onComplete(long id) {
assertFalse(customViewRef.get().isAttachedToWindow());
// NOTE: We cannot use drawAwContents here because the web contents
// are rendered into the custom view while in fullscreen.
Bitmap redScreenshot = GraphicsTestUtils.drawView(
customViewRef.get(), 100, 100);
assertEquals(Color.RED, redScreenshot.getPixel(50, 50));
testFinishedSignal.countDown();
}
});
}
});
assertTrue(testFinishedSignal.await(AwTestBase.WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS));
}
private static final LoadUrlParams createTestPageUrl(String backgroundColor) { private static final LoadUrlParams createTestPageUrl(String backgroundColor) {
return LoadUrlParams.createLoadDataParams( return LoadUrlParams.createLoadDataParams(
"<html><body bgcolor=" + backgroundColor + "></body></html>", "text/html", false); "<html><body bgcolor=" + backgroundColor + "></body></html>", "text/html", false);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment