1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org.chromium.content.browser;
7 import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
9 import android.graphics.Bitmap;
10 import android.graphics.Color;
11 import android.graphics.Rect;
12 import android.os.SystemClock;
13 import android.test.suitebuilder.annotation.SmallTest;
15 import junit.framework.AssertionFailedError;
17 import org.chromium.base.ThreadUtils;
18 import org.chromium.base.test.util.Feature;
19 import org.chromium.base.test.util.UrlUtils;
20 import org.chromium.content.browser.ContentReadbackHandler.GetBitmapCallback;
21 import org.chromium.content.browser.test.util.Criteria;
22 import org.chromium.content.browser.test.util.CriteriaHelper;
23 import org.chromium.content_shell_apk.ContentShellTestBase;
25 import java.util.concurrent.atomic.AtomicBoolean;
26 import java.util.concurrent.atomic.AtomicInteger;
29 * Tests that we can readback the contents of a ContentView.
31 public class ContentViewReadbackTest extends ContentShellTestBase {
33 private static final int COLOR_THRESHOLD = 8;
34 private static final long WAIT_FOR_READBACK_TIMEOUT = scaleTimeout(10000);
37 protected void setUp() throws Exception {
39 launchContentShellWithUrl(UrlUtils.encodeHtmlDataUri(
40 "<html style=\"background: #00f;\"><head><style>body { height: 5000px; }</style>" +
42 assertTrue("Page failed to load", waitForActiveShellToBeDoneLoading());
45 private static void assertEqualColor(int actual, int expected, int threshold) {
46 int deltaR = Math.abs(Color.red(actual) - Color.red(expected));
47 int deltaG = Math.abs(Color.green(actual) - Color.green(expected));
48 int deltaB = Math.abs(Color.blue(actual) - Color.blue(expected));
49 if (deltaR > threshold || deltaG > threshold || deltaB > threshold) {
50 throw new AssertionFailedError(
51 "Color does not match; expected " + expected + ", got " + actual);
55 private void assertWaitForYScroll(final int previousYScroll) throws InterruptedException {
56 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
58 public boolean isSatisfied() {
59 return getContentViewCore().getNativeScrollYForTest() > previousYScroll;
64 private void assertWaitForReadback(final AtomicBoolean readbackDone)
65 throws InterruptedException {
66 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
68 public boolean isSatisfied() {
69 return readbackDone.get();
71 }, WAIT_FOR_READBACK_TIMEOUT, CriteriaHelper.DEFAULT_POLLING_INTERVAL));
75 * Test to make sure the screenshots captured of the ContentView are not blank.
77 * @throws InterruptedException
81 public void testScreenshotIsNotBlank() throws Throwable {
82 final AtomicBoolean readbackDone = new AtomicBoolean(false);
83 final AtomicInteger color = new AtomicInteger();
85 // We wait on the fling to make sure that the compositor side has a layer available by the
86 // time we reach readback.
87 int previousYScroll = getContentViewCore().getNativeScrollYForTest();
88 ThreadUtils.runOnUiThreadBlocking(new Runnable() {
91 getContentViewCore().flingForTest(SystemClock.uptimeMillis(), 0, 0, 0, -100);
94 assertWaitForYScroll(previousYScroll);
96 runTestOnUiThread(new Runnable() {
99 ContentReadbackHandler contentReadbackHandler = new ContentReadbackHandler() {
101 protected boolean readyForReadback() {
106 GetBitmapCallback callback = new GetBitmapCallback() {
108 public void onFinishGetBitmap(Bitmap bitmap) {
109 assertNotNull("Readback did not return valid bitmap", bitmap);
110 // Verify a pixel in the center of the screenshot.
111 color.set(bitmap.getPixel(bitmap.getWidth() / 2, bitmap.getHeight() / 2));
112 readbackDone.set(true);
116 contentReadbackHandler.initNativeContentReadbackHandler();
117 contentReadbackHandler.getContentBitmapAsync(1.0f, new Rect(), getContentViewCore(),
121 assertWaitForReadback(readbackDone);
123 assertEqualColor(color.get(), Color.BLUE, COLOR_THRESHOLD);