chromium/chrome/browser/paint_preview/android/javatests/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabServiceTest.java

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.paint_preview.services;

import android.app.Activity;

import androidx.test.filters.MediumTest;
import androidx.test.platform.app.InstrumentationRegistry;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;

import org.chromium.base.ThreadUtils;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.CriteriaHelper;
import org.chromium.base.test.util.Feature;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.TabClosureParams;
import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.net.test.EmbeddedTestServer;

import java.util.concurrent.TimeUnit;

/** Tests for the Paint Preview Tab Manager. */
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
public class PaintPreviewTabServiceTest {
    private static final long TIMEOUT_MS = 5000;
    private static final long POLLING_INTERVAL_MS = 500;

    @Rule
    public final ChromeTabbedActivityTestRule mActivityTestRule =
            new ChromeTabbedActivityTestRule();

    @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();

    private TabModelSelector mTabModelSelector;
    private TabModel mTabModel;
    private Tab mTab;
    private PaintPreviewTabService mPaintPreviewTabService;

    @Before
    public void setUp() throws Exception {
        mActivityTestRule.startMainActivityOnBlankPage();
        mTab = mActivityTestRule.getActivity().getActivityTab();
        mTabModelSelector = mActivityTestRule.getActivity().getTabModelSelector();
        mTabModel = mTabModelSelector.getModel(/* incognito= */ false);
    }

    /** Verifies that a Tab's contents are captured when the activity is stopped. */
    @Test
    @MediumTest
    @Feature({"PaintPreview"})
    public void testCapturedAndDelete() throws Exception {
        EmbeddedTestServer testServer = mActivityTestRule.getTestServer();
        final String url = testServer.getURL("/chrome/test/data/android/about.html");

        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    mPaintPreviewTabService = PaintPreviewTabServiceFactory.getServiceInstance();
                    mTab.loadUrl(new LoadUrlParams(url));
                });
        // Give the tab time to complete layout before hiding.
        TimeUnit.SECONDS.sleep(1);
        int tabId = mTab.getId();

        // Simulate closing the app.
        Activity activity = mActivityTestRule.getActivity();
        activity.getWindow().setLocalFocus(false, false);
        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    InstrumentationRegistry.getInstrumentation().callActivityOnPause(activity);
                });
        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    InstrumentationRegistry.getInstrumentation().callActivityOnStop(activity);
                });

        // Allow time to capture.
        CriteriaHelper.pollUiThread(
                () -> {
                    mPaintPreviewTabService = PaintPreviewTabServiceFactory.getServiceInstance();
                    return mPaintPreviewTabService.hasCaptureForTab(tabId);
                },
                "Paint Preview didn't get captured.",
                TIMEOUT_MS,
                POLLING_INTERVAL_MS);

        // Simulate unpausing the app (for cleanup).
        activity.getWindow().setLocalFocus(true, true);
        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    InstrumentationRegistry.getInstrumentation().callActivityOnRestart(activity);
                    InstrumentationRegistry.getInstrumentation().callActivityOnStart(activity);
                    InstrumentationRegistry.getInstrumentation().callActivityOnResume(activity);
                });

        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    mTabModelSelector = mActivityTestRule.getActivity().getTabModelSelector();
                    mTab = mTabModelSelector.getTabById(tabId);
                    mTabModel = mTabModelSelector.getModel(/* incognito= */ false);
                });

        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    mTabModel.closeTabs(TabClosureParams.closeTab(mTab).allowUndo(false).build());
                });

        CriteriaHelper.pollUiThread(
                () -> {
                    return !mPaintPreviewTabService.hasCaptureForTab(tabId);
                },
                "Paint Preview didn't get deleted.",
                TIMEOUT_MS,
                POLLING_INTERVAL_MS);
    }

    /** Tests that capturing and deleting via an audit works as expected. */
    @Test
    @MediumTest
    @Feature({"PaintPreview"})
    public void testCapturedAndDeleteViaAudit() throws Exception {
        EmbeddedTestServer testServer = mActivityTestRule.getTestServer();
        final String url = testServer.getURL("/chrome/test/data/android/about.html");

        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    mPaintPreviewTabService = PaintPreviewTabServiceFactory.getServiceInstance();
                    mTab.loadUrl(new LoadUrlParams(url));
                });
        // Give the tab time to complete layout before hiding.
        TimeUnit.SECONDS.sleep(1);
        int tabId = mTab.getId();

        // Simulate closing the app.
        Activity activity = mActivityTestRule.getActivity();
        activity.getWindow().setLocalFocus(false, false);
        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    InstrumentationRegistry.getInstrumentation().callActivityOnPause(activity);
                });
        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    InstrumentationRegistry.getInstrumentation().callActivityOnStop(activity);
                });

        // Allow time to capture.
        CriteriaHelper.pollUiThread(
                () -> {
                    mPaintPreviewTabService = PaintPreviewTabServiceFactory.getServiceInstance();
                    return mPaintPreviewTabService.hasCaptureForTab(tabId);
                },
                "Paint Preview didn't get captured.",
                TIMEOUT_MS,
                POLLING_INTERVAL_MS);

        // Simulate unpausing the app (for cleanup).
        activity.getWindow().setLocalFocus(true, true);
        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    InstrumentationRegistry.getInstrumentation().callActivityOnRestart(activity);
                    InstrumentationRegistry.getInstrumentation().callActivityOnStart(activity);
                    InstrumentationRegistry.getInstrumentation().callActivityOnResume(activity);
                });

        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    mPaintPreviewTabService.auditArtifacts(new int[0]);
                });

        CriteriaHelper.pollUiThread(
                () -> {
                    return !mPaintPreviewTabService.hasCaptureForTab(tabId);
                },
                "Paint Preview didn't get deleted.",
                TIMEOUT_MS,
                POLLING_INTERVAL_MS);
    }

    /** Verifies the pre-native preview exists check works. */
    @Test
    @MediumTest
    @Feature({"PaintPreview"})
    public void testPreNativePreviewExists() throws Exception {
        mTemporaryFolder.newFile("2.zip");
        mTemporaryFolder.newFile("3.zip");
        mTemporaryFolder.newFile("6");
        mTemporaryFolder.newFolder("10");

        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    mPaintPreviewTabService = PaintPreviewTabServiceFactory.getServiceInstance();
                    Assert.assertTrue(
                            mPaintPreviewTabService.previewExistsPreNative(
                                    mTemporaryFolder.getRoot().getPath(), 2));
                    Assert.assertTrue(
                            mPaintPreviewTabService.previewExistsPreNative(
                                    mTemporaryFolder.getRoot().getPath(), 3));
                    Assert.assertFalse(
                            mPaintPreviewTabService.previewExistsPreNative(
                                    mTemporaryFolder.getRoot().getPath(), 6));
                    Assert.assertFalse(
                            mPaintPreviewTabService.previewExistsPreNative(
                                    mTemporaryFolder.getRoot().getPath(), 10));
                });
    }
}