| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package org.chromium.android_webview.test; |
| |
| import android.graphics.Bitmap; |
| import android.graphics.Color; |
| import android.support.test.InstrumentationRegistry; |
| import android.view.View; |
| |
| import androidx.test.filters.SmallTest; |
| |
| import org.junit.Assert; |
| import org.junit.Before; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| |
| import org.chromium.android_webview.AwContents; |
| import org.chromium.android_webview.AwContents.VisualStateCallback; |
| import org.chromium.android_webview.test.util.GraphicsTestUtils; |
| import org.chromium.base.test.util.CriteriaHelper; |
| import org.chromium.base.test.util.Feature; |
| import org.chromium.base.test.util.UrlUtils; |
| import org.chromium.content_public.browser.test.util.TestThreadUtils; |
| import org.chromium.content_public.common.ContentUrlConstants; |
| |
| import java.util.concurrent.CountDownLatch; |
| import java.util.concurrent.TimeUnit; |
| |
| /** |
| * AwContents rendering / pixel tests. |
| */ |
| @RunWith(AwJUnit4ClassRunner.class) |
| public class AwContentsRenderTest { |
| @Rule |
| public AwActivityTestRule mActivityTestRule = new AwActivityTestRule(); |
| |
| private TestAwContentsClient mContentsClient; |
| private AwContents mAwContents; |
| private AwTestContainerView mContainerView; |
| |
| @Before |
| public void setUp() { |
| mContentsClient = new TestAwContentsClient(); |
| mContainerView = mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); |
| mAwContents = mContainerView.getAwContents(); |
| } |
| |
| void setBackgroundColorOnUiThread(final int c) { |
| TestThreadUtils.runOnUiThreadBlocking(() -> mAwContents.setBackgroundColor(c)); |
| } |
| |
| @Test |
| @SmallTest |
| @Feature({"AndroidWebView"}) |
| public void testSetGetBackgroundColor() throws Throwable { |
| setBackgroundColorOnUiThread(Color.MAGENTA); |
| GraphicsTestUtils.pollForBackgroundColor(mAwContents, Color.MAGENTA); |
| |
| setBackgroundColorOnUiThread(Color.CYAN); |
| GraphicsTestUtils.pollForBackgroundColor(mAwContents, Color.CYAN); |
| |
| mActivityTestRule.loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), |
| ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); |
| GraphicsTestUtils.pollForBackgroundColor(mAwContents, Color.CYAN); |
| |
| setBackgroundColorOnUiThread(Color.YELLOW); |
| GraphicsTestUtils.pollForBackgroundColor(mAwContents, Color.YELLOW); |
| |
| final String html_meta = "<html><head><meta name=color-scheme content=dark></head></html>"; |
| mActivityTestRule.loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), |
| "data:text/html," + html_meta); |
| final int dark_scheme_color = 0xFF121212; |
| GraphicsTestUtils.pollForBackgroundColor(mAwContents, dark_scheme_color); |
| |
| final String html = "<html><head><style>body {background-color:#227788}</style></head>" |
| + "<body></body></html>"; |
| // Loading the html via a data URI requires us to encode '#' symbols as '%23'. |
| mActivityTestRule.loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), |
| "data:text/html," + html.replace("#", "%23")); |
| final int teal = 0xFF227788; |
| GraphicsTestUtils.pollForBackgroundColor(mAwContents, teal); |
| |
| // Changing the base background should not override CSS background. |
| setBackgroundColorOnUiThread(Color.MAGENTA); |
| Assert.assertEquals(teal, GraphicsTestUtils.sampleBackgroundColorOnUiThread(mAwContents)); |
| // ...setting the background is asynchronous, so pause a bit and retest just to be sure. |
| Thread.sleep(500); |
| Assert.assertEquals(teal, GraphicsTestUtils.sampleBackgroundColorOnUiThread(mAwContents)); |
| } |
| |
| @Test |
| @SmallTest |
| @Feature({"AndroidWebView"}) |
| public void testPictureListener() throws Throwable { |
| TestThreadUtils.runOnUiThreadBlocking(() -> mAwContents.enableOnNewPicture(true, true)); |
| |
| int pictureCount = mContentsClient.getPictureListenerHelper().getCallCount(); |
| mActivityTestRule.loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), |
| ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); |
| mContentsClient.getPictureListenerHelper().waitForCallback(pictureCount, 1); |
| // Invalidation only, so picture should be null. |
| Assert.assertNull(mContentsClient.getPictureListenerHelper().getPicture()); |
| } |
| |
| @Test |
| @SmallTest |
| @Feature({"AndroidWebView"}) |
| public void testForceDrawWhenInvisible() throws Throwable { |
| final String html = "<html><head><style>body {background-color:#227788}</style></head>" |
| + "<body>Hello world!</body></html>"; |
| // Loading the html via a data URI requires us to encode '#' symbols as '%23'. |
| mActivityTestRule.loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), |
| "data:text/html," + html.replace("#", "%23")); |
| |
| Bitmap visibleBitmap = null; |
| Bitmap invisibleBitmap = null; |
| final CountDownLatch latch = new CountDownLatch(1); |
| InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { |
| final long requestId1 = 1; |
| mAwContents.insertVisualStateCallback(requestId1, new VisualStateCallback() { |
| @Override |
| public void onComplete(long id) { |
| Assert.assertEquals(requestId1, id); |
| latch.countDown(); |
| } |
| }); |
| }); |
| Assert.assertTrue( |
| latch.await(AwActivityTestRule.SCALED_WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS)); |
| |
| final int width = |
| TestThreadUtils.runOnUiThreadBlockingNoException(() -> mContainerView.getWidth()); |
| final int height = |
| TestThreadUtils.runOnUiThreadBlockingNoException(() -> mContainerView.getHeight()); |
| visibleBitmap = GraphicsTestUtils.drawAwContentsOnUiThread(mAwContents, width, height); |
| |
| // Things that affect DOM page visibility: |
| // 1. isPaused |
| // 2. window's visibility, if the webview is attached to a window. |
| // Note android.view.View's visibility does not affect DOM page visibility. |
| InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { |
| mContainerView.setVisibility(View.INVISIBLE); |
| Assert.assertTrue(mAwContents.isPageVisible()); |
| |
| mAwContents.onPause(); |
| Assert.assertFalse(mAwContents.isPageVisible()); |
| |
| mAwContents.onResume(); |
| Assert.assertTrue(mAwContents.isPageVisible()); |
| |
| // Simulate a window visiblity change. WebView test app can't |
| // manipulate the window visibility directly. |
| mAwContents.onWindowVisibilityChanged(View.INVISIBLE); |
| Assert.assertFalse(mAwContents.isPageVisible()); |
| }); |
| |
| // VisualStateCallback#onComplete won't be called when WebView is |
| // invisible. So there is no reliable way to tell if View#setVisibility |
| // has taken effect. Just sleep the test thread for 500ms. |
| Thread.sleep(500); |
| invisibleBitmap = GraphicsTestUtils.drawAwContentsOnUiThread(mAwContents, width, height); |
| Assert.assertNotNull(invisibleBitmap); |
| Assert.assertTrue(invisibleBitmap.sameAs(visibleBitmap)); |
| } |
| |
| @Test |
| @SmallTest |
| @Feature({"AndroidWebView"}) |
| public void testSoftwareCanvas() throws Throwable { |
| TestThreadUtils.runOnUiThreadBlocking( |
| () -> mAwContents.setLayerType(View.LAYER_TYPE_SOFTWARE, null)); |
| |
| String testFile = "android_webview/test/data/green_canvas.html"; |
| String url = UrlUtils.getIsolatedTestFileUrl(testFile); |
| AwActivityTestRule.enableJavaScriptOnUiThread(mAwContents); |
| mActivityTestRule.loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), url); |
| mActivityTestRule.waitForVisualStateCallback(mAwContents); |
| |
| CriteriaHelper.pollInstrumentationThread(() -> { |
| Bitmap bitmap = GraphicsTestUtils.drawAwContentsOnUiThread(mAwContents, 500, 500); |
| return Color.GREEN == bitmap.getPixel(250, 250); |
| }); |
| } |
| } |