ContentViewReadbackTest.java revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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.
4
5package org.chromium.content.browser;
6
7import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
8
9import android.graphics.Bitmap;
10import android.graphics.Color;
11import android.graphics.Rect;
12import android.os.SystemClock;
13import android.test.suitebuilder.annotation.SmallTest;
14
15import junit.framework.AssertionFailedError;
16
17import org.chromium.base.ThreadUtils;
18import org.chromium.base.test.util.Feature;
19import org.chromium.base.test.util.UrlUtils;
20import org.chromium.content.browser.ContentReadbackHandler.GetBitmapCallback;
21import org.chromium.content.browser.test.util.Criteria;
22import org.chromium.content.browser.test.util.CriteriaHelper;
23import org.chromium.content_shell_apk.ContentShellTestBase;
24
25import java.util.concurrent.atomic.AtomicBoolean;
26import java.util.concurrent.atomic.AtomicInteger;
27
28/**
29 * Tests that we can readback the contents of a ContentView.
30 */
31public class ContentViewReadbackTest extends ContentShellTestBase {
32
33    private static final int COLOR_THRESHOLD = 8;
34    private static final long WAIT_FOR_READBACK_TIMEOUT =  scaleTimeout(10000);
35
36    @Override
37    protected void setUp() throws Exception {
38        super.setUp();
39        launchContentShellWithUrl(UrlUtils.encodeHtmlDataUri(
40                "<html style=\"background: #00f;\"><head><style>body { height: 5000px; }</style>" +
41                "</head></html>"));
42        assertTrue("Page failed to load", waitForActiveShellToBeDoneLoading());
43    }
44
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);
52        }
53    }
54
55    private void assertWaitForYScroll(final int previousYScroll) throws InterruptedException {
56        assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
57            @Override
58            public boolean isSatisfied() {
59                return getContentViewCore().getNativeScrollYForTest() > previousYScroll;
60            }
61        }));
62    }
63
64    private void assertWaitForReadback(final AtomicBoolean readbackDone)
65            throws InterruptedException {
66        assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
67            @Override
68            public boolean isSatisfied() {
69                return readbackDone.get();
70            }
71        }, WAIT_FOR_READBACK_TIMEOUT, CriteriaHelper.DEFAULT_POLLING_INTERVAL));
72    }
73
74    /**
75     * Test to make sure the screenshots captured of the ContentView are not blank.
76     *
77     * @throws InterruptedException
78     */
79    @SmallTest
80    @Feature({"Main"})
81    public void testScreenshotIsNotBlank() throws Throwable {
82        final AtomicBoolean readbackDone = new AtomicBoolean(false);
83        final AtomicInteger color = new AtomicInteger();
84
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() {
89            @Override
90            public void run() {
91                getContentViewCore().flingForTest(SystemClock.uptimeMillis(), 0, 0, 0, -100);
92            }
93        });
94        assertWaitForYScroll(previousYScroll);
95
96        runTestOnUiThread(new Runnable() {
97            @Override
98            public void run() {
99                ContentReadbackHandler contentReadbackHandler = new ContentReadbackHandler() {
100                    @Override
101                    protected boolean readyForReadback() {
102                        return true;
103                    }
104                };
105
106                GetBitmapCallback callback = new GetBitmapCallback() {
107                    @Override
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);
113                    }
114                };
115
116                contentReadbackHandler.initNativeContentReadbackHandler();
117                contentReadbackHandler.getContentBitmapAsync(1.0f, new Rect(), getContentViewCore(),
118                        callback);
119            }
120        });
121        assertWaitForReadback(readbackDone);
122
123        assertEqualColor(color.get(), Color.BLUE, COLOR_THRESHOLD);
124    }
125}
126