chromium/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPermissionsTest.java

// Copyright 2019 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.browserservices.permissiondelegation;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import static org.chromium.base.ThreadUtils.runOnUiThreadBlocking;
import static org.chromium.base.test.util.Batch.PER_CLASS;

import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.MediumTest;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;

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.library_loader.LibraryLoader;
import org.chromium.base.test.util.Batch;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.DisableIf;
import org.chromium.chrome.browser.ChromeApplicationImpl;
import org.chromium.chrome.browser.ShortcutHelper;
import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
import org.chromium.chrome.browser.customtabs.CustomTabsIntentTestUtils;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.webapps.WebappRegistry;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.components.content_settings.ContentSettingValues;
import org.chromium.components.content_settings.ContentSettingsType;
import org.chromium.components.embedder_support.util.Origin;
import org.chromium.net.test.EmbeddedTestServer;
import org.chromium.net.test.ServerCertificate;
import org.chromium.ui.test.util.UiDisableIf;

import java.util.concurrent.TimeoutException;

/**
 * Tests that cached permissions for Trusted Web Activities have an effect on the actual permission
 * state.
 */
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
// See: https://crbug.com/1120707
@DisableIf.Device(type = {UiDisableIf.TABLET})
@Batch(PER_CLASS)
public class TrustedWebActivityPermissionsTest {
    @Rule
    public CustomTabActivityTestRule mCustomTabActivityTestRule = new CustomTabActivityTestRule();

    private static final String TEST_PAGE = "/chrome/test/data/android/google.html";
    private static final int NOTIFICATIONS = ContentSettingsType.NOTIFICATIONS;
    private static final int GEOLOCATION = ContentSettingsType.GEOLOCATION;

    private EmbeddedTestServer mTestServer;
    private String mTestPage;
    private Origin mOrigin;
    private String mPackage;
    private InstalledWebappPermissionManager mPermissionManager;

    @Before
    public void setUp() throws TimeoutException {
        mCustomTabActivityTestRule.setFinishActivity(true);
        // Native needs to be initialized to start the test server.
        LibraryLoader.getInstance().ensureInitialized();

        // TWAs only work with HTTPS.
        mTestServer =
                EmbeddedTestServer.createAndStartHTTPSServer(
                        InstrumentationRegistry.getInstrumentation().getContext(),
                        ServerCertificate.CERT_OK);
        mTestPage = mTestServer.getURL(TEST_PAGE);
        mOrigin = Origin.create(mTestPage);
        mPackage = ApplicationProvider.getApplicationContext().getPackageName();

        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(
                CustomTabsIntentTestUtils.createMinimalCustomTabIntent(
                        ApplicationProvider.getApplicationContext(), mTestPage));

        mPermissionManager = ChromeApplicationImpl.getComponent().resolvePermissionManager();
        mPermissionManager.clearForTesting();
        assertEquals("\"default\"", getNotificationPermission());
    }

    @After
    public void tearDown() {
        mPermissionManager.clearForTesting();
    }

    @Test
    @MediumTest
    public void allowNotifications() throws TimeoutException {
        runOnUiThreadBlocking(
                () ->
                        mPermissionManager.updatePermission(
                                mOrigin, mPackage, NOTIFICATIONS, ContentSettingValues.ALLOW));
        assertEquals("\"granted\"", getNotificationPermission());
    }

    @Test
    @MediumTest
    public void blockNotifications() throws TimeoutException {
        runOnUiThreadBlocking(
                () ->
                        mPermissionManager.updatePermission(
                                mOrigin, mPackage, NOTIFICATIONS, ContentSettingValues.BLOCK));
        assertEquals("\"denied\"", getNotificationPermission());
    }

    @Test
    @MediumTest
    public void unregisterTwa() throws TimeoutException {
        runOnUiThreadBlocking(
                () ->
                        mPermissionManager.updatePermission(
                                mOrigin, mPackage, NOTIFICATIONS, ContentSettingValues.ALLOW));
        assertEquals("\"granted\"", getNotificationPermission());

        runOnUiThreadBlocking(() -> mPermissionManager.unregister(mOrigin));
        assertEquals("\"default\"", getNotificationPermission());
    }

    @Test
    @SmallTest
    public void detectTwa() {
        runOnUiThreadBlocking(
                () ->
                        mPermissionManager.updatePermission(
                                mOrigin, mPackage, NOTIFICATIONS, ContentSettingValues.ALLOW));
        assertTrue(ShortcutHelper.doesOriginContainAnyInstalledTwa(mOrigin.toString()));

        runOnUiThreadBlocking(() -> mPermissionManager.unregister(mOrigin));
        assertFalse(ShortcutHelper.doesOriginContainAnyInstalledTwa(mOrigin.toString()));
    }

    @Test
    @SmallTest
    public void allowGeolocation() {
        runOnUiThreadBlocking(
                () ->
                        mPermissionManager.updatePermission(
                                mOrigin, mPackage, GEOLOCATION, ContentSettingValues.ALLOW));
        assertEquals(
                Integer.valueOf(ContentSettingValues.ALLOW),
                WebappRegistry.getInstance()
                        .getPermissionStore()
                        .getPermission(GEOLOCATION, mOrigin));
    }

    @Test
    @SmallTest
    public void blockGeolocation() {
        runOnUiThreadBlocking(
                () ->
                        mPermissionManager.updatePermission(
                                mOrigin, mPackage, GEOLOCATION, ContentSettingValues.BLOCK));
        assertEquals(
                Integer.valueOf(ContentSettingValues.BLOCK),
                WebappRegistry.getInstance()
                        .getPermissionStore()
                        .getPermission(GEOLOCATION, mOrigin));
    }

    private String getNotificationPermission() throws TimeoutException {
        return mCustomTabActivityTestRule.runJavaScriptCodeInCurrentTab("Notification.permission");
    }
}