chromium/chrome/android/javatests/src/org/chromium/chrome/browser/incognito/IncognitoCookieLeakageTest.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.incognito;

import static org.junit.Assert.assertEquals;

import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.LargeTest;

import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.chromium.base.ThreadUtils;
import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameter;
import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate;
import org.chromium.base.test.params.ParameterProvider;
import org.chromium.base.test.params.ParameterSet;
import org.chromium.base.test.params.ParameterizedRunner;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.Criteria;
import org.chromium.base.test.util.CriteriaHelper;
import org.chromium.chrome.browser.customtabs.IncognitoCustomTabActivityTestRule;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.incognito.IncognitoDataTestUtils.ActivityType;
import org.chromium.chrome.browser.incognito.IncognitoDataTestUtils.TestParams;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.content_public.browser.test.util.JavaScriptUtils;
import org.chromium.net.test.EmbeddedTestServer;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeoutException;

/**
 * This test class checks cookie leakage between all different pairs of Activity types with a
 * constraint that one of the interacting activity must be either Incognito Tab or Incognito CCT.
 */
@RunWith(ParameterizedRunner.class)
@UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, ChromeSwitches.DISABLE_ALL_IPH})
public class IncognitoCookieLeakageTest {
    private static final String COOKIES_SETTING_PATH = "/chrome/test/data/android/cookie.html";
    private String mCookiesTestPage;
    private EmbeddedTestServer mTestServer;

    @Rule
    public ChromeTabbedActivityTestRule mChromeActivityTestRule =
            new ChromeTabbedActivityTestRule();

    @Rule
    public IncognitoCustomTabActivityTestRule mCustomTabActivityTestRule =
            new IncognitoCustomTabActivityTestRule();

    @Before
    public void setUp() throws TimeoutException {
        mTestServer =
                EmbeddedTestServer.createAndStartServer(
                        ApplicationProvider.getApplicationContext());
        mCookiesTestPage = mTestServer.getURL(COOKIES_SETTING_PATH);
    }

    @After
    public void tearDown() {
        ThreadUtils.runOnUiThreadBlocking(
                () -> IncognitoDataTestUtils.closeTabs(mChromeActivityTestRule));
    }

    private void setCookies(Tab tab) throws TimeoutException {
        CriteriaHelper.pollUiThread(
                () -> Criteria.checkThat(tab.getWebContents(), Matchers.notNullValue()));
        JavaScriptUtils.executeJavaScriptAndWaitForResult(tab.getWebContents(), "setCookie()");
        assertCookies(tab, "\"Foo=Bar\"");
    }

    private void assertCookies(Tab tab, String expected) throws TimeoutException {
        CriteriaHelper.pollUiThread(
                () -> Criteria.checkThat(tab.getWebContents(), Matchers.notNullValue()));
        String actual =
                JavaScriptUtils.executeJavaScriptAndWaitForResult(
                        tab.getWebContents(), "getCookie()");
        if (actual.equalsIgnoreCase("null")) actual = "\"\"";
        assertEquals(expected, actual);
    }

    /**
     * A class to provide the list of test parameters encapsulating Activity pairs, spliced on
     * regular and Incognito mode, where cookie shouldn't leak.
     */
    public static class IsolatedFlowsParams implements ParameterProvider {
        @Override
        public List<ParameterSet> getParameters() {
            List<ParameterSet> result = new ArrayList<>();
            result.addAll(new TestParams.RegularToIncognito().getParameters());
            result.addAll(new TestParams.IncognitoToRegular().getParameters());
            return result;
        }
    }

    // TODO(crbug.com/40107157) : Currently, incognito CCTs are not isolated and hence they share
    // the session with other incognito sessions. Once, they are properly isolated we should change
    // the test to expect that cookies are not leaked from/to an incognito CCT session.
    @Test
    @LargeTest
    @UseMethodParameter(TestParams.IncognitoToIncognito.class)
    public void testCookiesDoNotLeakFromIncognitoToIncognito(
            String incognitoActivityType1, String incognitoActivityType2) throws TimeoutException {
        ActivityType incognitoActivity1 = ActivityType.valueOf(incognitoActivityType1);
        ActivityType incognitoActivity2 = ActivityType.valueOf(incognitoActivityType2);

        Tab setter_tab =
                incognitoActivity1.launchUrl(
                        mChromeActivityTestRule, mCustomTabActivityTestRule, mCookiesTestPage);
        setCookies(setter_tab);

        Tab getter_tab =
                incognitoActivity2.launchUrl(
                        mChromeActivityTestRule, mCustomTabActivityTestRule, mCookiesTestPage);

        String expected = "\"\"";

        assertCookies(getter_tab, expected);
    }

    // This test cookie does not leak from regular to incognito and from incognito to regular
    // session across different activity types.
    @Test
    @LargeTest
    @UseMethodParameter(IsolatedFlowsParams.class)
    public void testCookiesDoNotLeakBetweenRegularAndIncognito(
            String setterActivityType, String getterActivityType) throws TimeoutException {
        ActivityType setterActivity = ActivityType.valueOf(setterActivityType);
        ActivityType getterActivity = ActivityType.valueOf(getterActivityType);

        Tab setter_tab =
                setterActivity.launchUrl(
                        mChromeActivityTestRule, mCustomTabActivityTestRule, mCookiesTestPage);
        setCookies(setter_tab);

        Tab getter_tab =
                getterActivity.launchUrl(
                        mChromeActivityTestRule, mCustomTabActivityTestRule, mCookiesTestPage);

        assertCookies(getter_tab, "\"\"");
    }
}