/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package com.android.server.uri;

import static com.android.server.uri.UriGrantsMockContext.FLAG_PERSISTABLE;
import static com.android.server.uri.UriGrantsMockContext.FLAG_PREFIX;
import static com.android.server.uri.UriGrantsMockContext.FLAG_READ;
import static com.android.server.uri.UriGrantsMockContext.PKG_CAMERA;
import static com.android.server.uri.UriGrantsMockContext.PKG_COMPLEX;
import static com.android.server.uri.UriGrantsMockContext.PKG_FORCE;
import static com.android.server.uri.UriGrantsMockContext.PKG_SOCIAL;
import static com.android.server.uri.UriGrantsMockContext.UID_PRIMARY_CAMERA;
import static com.android.server.uri.UriGrantsMockContext.UID_PRIMARY_COMPLEX;
import static com.android.server.uri.UriGrantsMockContext.UID_PRIMARY_FORCE;
import static com.android.server.uri.UriGrantsMockContext.UID_PRIMARY_PRIVATE;
import static com.android.server.uri.UriGrantsMockContext.UID_PRIMARY_PUBLIC;
import static com.android.server.uri.UriGrantsMockContext.UID_PRIMARY_SOCIAL;
import static com.android.server.uri.UriGrantsMockContext.UID_SECONDARY_CAMERA;
import static com.android.server.uri.UriGrantsMockContext.UID_SECONDARY_SOCIAL;
import static com.android.server.uri.UriGrantsMockContext.URI_FORCE;
import static com.android.server.uri.UriGrantsMockContext.URI_PHOTO_1;
import static com.android.server.uri.UriGrantsMockContext.URI_PRIVATE;
import static com.android.server.uri.UriGrantsMockContext.URI_PUBLIC;
import static com.android.server.uri.UriGrantsMockContext.USER_PRIMARY;
import static com.android.server.uri.UriGrantsMockContext.USER_SECONDARY;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

import android.content.ClipData;
import android.content.Intent;
import android.content.pm.ProviderInfo;
import android.net.Uri;
import android.os.UserHandle;
import android.util.ArraySet;

import androidx.test.InstrumentationRegistry;

import org.junit.Before;
import org.junit.Test;

import java.util.Arrays;
import java.util.Set;

public class UriGrantsManagerServiceTest {
    private UriGrantsMockContext mContext;
    private UriGrantsManagerInternal mService;

    // we expect the following only during grant if a grant is expected
    private void verifyNoVisibilityGrant() {
        verify(mContext.mPmInternal, never())
                .grantImplicitAccess(anyInt(), any(), anyInt(), anyInt(), anyBoolean());
    }

    @Before
    public void setUp() throws Exception {
        mContext = new UriGrantsMockContext(InstrumentationRegistry.getContext());
        mService = UriGrantsManagerService
            .createForTest(mContext, mContext.getFilesDir())
            .getLocalService();
    }

    /**
     * Verify that a camera sharing a normally-private photo with a social media
     * app in the same user issues a grant.
     */
    @Test
    public void testNeeded_normal_sameUser() {
        final Intent intent = new Intent(Intent.ACTION_VIEW, URI_PHOTO_1).addFlags(FLAG_READ);
        final GrantUri expectedGrant = new GrantUri(USER_PRIMARY, URI_PHOTO_1, FLAG_READ);

        final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent(
                intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_PRIMARY);
        assertEquals(PKG_SOCIAL, needed.targetPkg);
        assertEquals(UID_PRIMARY_SOCIAL, needed.targetUid);
        assertEquals(FLAG_READ, needed.flags);
        assertEquals(asSet(expectedGrant), needed.uris);
        verifyNoVisibilityGrant();
    }

    /**
     * Verify that a camera sharing a normally-private photo with a social media
     * app in a different user issues a grant.
     */
    @Test
    public void testNeeded_normal_differentUser() {
        final Intent intent = new Intent(Intent.ACTION_VIEW, URI_PHOTO_1).addFlags(FLAG_READ);
        final GrantUri expectedGrant = new GrantUri(USER_PRIMARY, URI_PHOTO_1, FLAG_READ);

        final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent(
                intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_SECONDARY);
        assertEquals(PKG_SOCIAL, needed.targetPkg);
        assertEquals(UID_SECONDARY_SOCIAL, needed.targetUid);
        assertEquals(FLAG_READ, needed.flags);
        assertEquals(asSet(expectedGrant), needed.uris);
        verifyNoVisibilityGrant();
    }

    /**
     * No need to issue grants for public authorities.
     */
    @Test
    public void testNeeded_public() {
        final Intent intent = new Intent(Intent.ACTION_VIEW, URI_PUBLIC).addFlags(FLAG_READ);
        final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent(
                intent, UID_PRIMARY_PUBLIC, PKG_SOCIAL, USER_PRIMARY);
        assertNull(needed);
        verify(mContext.mPmInternal).grantImplicitAccess(eq(USER_PRIMARY), isNull(), eq(
                UserHandle.getAppId(UID_PRIMARY_SOCIAL)), eq(UID_PRIMARY_PUBLIC), eq(false));
    }

    /**
     * But we're willing to issue grants to public authorities when crossing
     * user boundaries.
     */
    @Test
    public void testNeeded_public_differentUser() {
        final Intent intent = new Intent(Intent.ACTION_VIEW, URI_PUBLIC).addFlags(FLAG_READ);
        final GrantUri expectedGrant = new GrantUri(USER_PRIMARY, URI_PUBLIC, FLAG_READ);

        final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent(
                intent, UID_PRIMARY_PUBLIC, PKG_SOCIAL, USER_SECONDARY);
        assertEquals(PKG_SOCIAL, needed.targetPkg);
        assertEquals(UID_SECONDARY_SOCIAL, needed.targetUid);
        assertEquals(FLAG_READ, needed.flags);
        assertEquals(asSet(expectedGrant), needed.uris);
        verifyNoVisibilityGrant();
    }

    /**
     * Refuse to issue grants for private authorities.
     */
    @Test
    public void testNeeded_private() {
        final Intent intent = new Intent(Intent.ACTION_VIEW, URI_PRIVATE).addFlags(FLAG_READ);
        try {
            mService.checkGrantUriPermissionFromIntent(
                    intent, UID_PRIMARY_PRIVATE, PKG_SOCIAL, USER_PRIMARY);
            fail();
        } catch (SecurityException expected) {
        }
    }

    /**
     * Verify that {@link ProviderInfo#forceUriPermissions} forces permission
     * grants, even when receiver already holds permission.
     */
    @Test
    public void testNeeded_force() {
        final Intent intent = new Intent(Intent.ACTION_VIEW, URI_FORCE)
                .addFlags(FLAG_READ);
        final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent(
                intent, UID_PRIMARY_FORCE, PKG_FORCE, USER_PRIMARY);
        assertEquals(asSet(new GrantUri(USER_PRIMARY, URI_FORCE, 0)), needed.uris);
    }

    /**
     * Verify that we can't grant permissions to top level of a provider with
     * complex permission model.
     */
    @Test
    public void testNeeded_complex_top() {
        final Uri uri = Uri.parse("content://" + PKG_COMPLEX + "/");
        {
            final Intent intent = new Intent(Intent.ACTION_VIEW, uri)
                    .addFlags(FLAG_READ | Intent.FLAG_ACTIVITY_CLEAR_TASK);
            assertNull(mService.checkGrantUriPermissionFromIntent(
                    intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_PRIMARY));
        }
        {
            final Intent intent = new Intent(Intent.ACTION_VIEW, uri)
                    .addFlags(FLAG_READ | FLAG_PREFIX);
            try {
                mService.checkGrantUriPermissionFromIntent(
                        intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_PRIMARY);
                fail();
            } catch (SecurityException expected) {
            }
        }
        {
            final Intent intent = new Intent(Intent.ACTION_VIEW, uri)
                    .addFlags(FLAG_READ | FLAG_PERSISTABLE);
            try {
                mService.checkGrantUriPermissionFromIntent(
                        intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_PRIMARY);
                fail();
            } catch (SecurityException expected) {
            }
        }
    }

    /**
     * Verify that we allow special cross-user grants to top level of a provider
     * that normally wouldn't allow it. Only basic permission modes are allowed;
     * advanced modes throw.
     */
    @Test
    public void testNeeded_complex_top_differentUser() {
        final Uri uri = Uri.parse("content://" + PKG_COMPLEX + "/");
        {
            final Intent intent = new Intent(Intent.ACTION_VIEW, uri)
                    .addFlags(FLAG_READ);
            final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent(
                    intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_SECONDARY);
            assertEquals(FLAG_READ, needed.flags);
        }
        {
            final Intent intent = new Intent(Intent.ACTION_VIEW, uri)
                    .addFlags(FLAG_READ | FLAG_PREFIX);
            try {
                mService.checkGrantUriPermissionFromIntent(
                        intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_SECONDARY);
                fail();
            } catch (SecurityException expected) {
            }
        }
        {
            final Intent intent = new Intent(Intent.ACTION_VIEW, uri)
                    .addFlags(FLAG_READ | FLAG_PERSISTABLE);
            try {
                mService.checkGrantUriPermissionFromIntent(
                        intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_SECONDARY);
                fail();
            } catch (SecurityException expected) {
            }
        }
    }

    /**
     * Verify that we can grant permissions to middle level of a provider with
     * complex permission model.
     */
    @Test
    public void testNeeded_complex_middle() {
        final Uri uri = Uri.parse("content://" + PKG_COMPLEX + "/secure/12");
        {
            final Intent intent = new Intent(Intent.ACTION_VIEW, uri)
                    .addFlags(FLAG_READ);
            final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent(
                    intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_PRIMARY);
            assertEquals(asSet(new GrantUri(USER_PRIMARY, uri, 0)), needed.uris);
        }
        {
            final Intent intent = new Intent(Intent.ACTION_VIEW, uri)
                    .addFlags(FLAG_READ | FLAG_PREFIX);
            final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent(
                    intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_PRIMARY);
            assertEquals(asSet(new GrantUri(USER_PRIMARY, uri, FLAG_PREFIX)), needed.uris);
        }
        {
            final Intent intent = new Intent(Intent.ACTION_VIEW, uri)
                    .addFlags(FLAG_READ | FLAG_PERSISTABLE);
            final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent(
                    intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_PRIMARY);
            assertEquals(asSet(new GrantUri(USER_PRIMARY, uri, 0)), needed.uris);
        }
    }

    /**
     * Verify that when we try sending a list of mixed items that the actual
     * grants are verified based on the capabilities of the caller.
     */
    @Test
    public void testNeeded_mixedPersistable() {
        final ClipData clip = ClipData.newRawUri("test", URI_PHOTO_1);
        clip.addItem(new ClipData.Item(URI_PUBLIC));

        final Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.addFlags(FLAG_READ | FLAG_PERSISTABLE);
        intent.setClipData(clip);

        {
            // When granting towards primary, persistable can't be honored so
            // the entire grant fails
            try {
                mService.checkGrantUriPermissionFromIntent(
                        intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_PRIMARY);
                fail();
            } catch (SecurityException expected) {
            }
        }
        {
            // When granting towards secondary, persistable can't be honored so
            // the entire grant fails
            try {
                mService.checkGrantUriPermissionFromIntent(
                        intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_SECONDARY);
                fail();
            } catch (SecurityException expected) {
            }
        }
    }

    /**
     * Verify that two overlapping owners require separate grants and that they
     * don't interfere with each other.
     */
    @Test
    public void testGrant_overlap() {
        final Intent intent = new Intent(Intent.ACTION_VIEW, URI_PHOTO_1).addFlags(FLAG_READ);

        final UriPermissionOwner activity = new UriPermissionOwner(mService, "activity");
        final UriPermissionOwner service = new UriPermissionOwner(mService, "service");

        final GrantUri expectedGrant = new GrantUri(USER_PRIMARY, URI_PHOTO_1, FLAG_READ);

        // Grant read via activity and write via service
        mService.grantUriPermissionUncheckedFromIntent(mService.checkGrantUriPermissionFromIntent(
                intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_PRIMARY), activity);
        mService.grantUriPermissionUncheckedFromIntent(mService.checkGrantUriPermissionFromIntent(
                intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_PRIMARY), service);

        // Verify that everything is good with the world
        assertTrue(mService.checkUriPermission(expectedGrant, UID_PRIMARY_SOCIAL, FLAG_READ));

        // Finish activity; service should hold permission
        activity.removeUriPermissions();
        assertTrue(mService.checkUriPermission(expectedGrant, UID_PRIMARY_SOCIAL, FLAG_READ));

        // And finishing service should wrap things up
        service.removeUriPermissions();
        assertFalse(mService.checkUriPermission(expectedGrant, UID_PRIMARY_SOCIAL, FLAG_READ));
    }

    @Test
    public void testCheckAuthorityGrants() {
        final Intent intent = new Intent(Intent.ACTION_VIEW, URI_PHOTO_1).addFlags(FLAG_READ);
        final UriPermissionOwner owner = new UriPermissionOwner(mService, "primary");

        final ProviderInfo cameraInfo = mContext.mPmInternal.resolveContentProvider(
                PKG_CAMERA, 0, USER_PRIMARY);

        // By default no social can see any camera
        assertFalse(mService.checkAuthorityGrants(UID_PRIMARY_SOCIAL,
                cameraInfo, USER_PRIMARY, true));
        assertFalse(mService.checkAuthorityGrants(UID_PRIMARY_SOCIAL,
                cameraInfo, USER_SECONDARY, true));
        assertFalse(mService.checkAuthorityGrants(UID_SECONDARY_SOCIAL,
                cameraInfo, USER_PRIMARY, true));
        assertFalse(mService.checkAuthorityGrants(UID_SECONDARY_SOCIAL,
                cameraInfo, USER_SECONDARY, true));

        // Granting primary camera to primary social
        mService.grantUriPermissionUncheckedFromIntent(mService.checkGrantUriPermissionFromIntent(
                intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_PRIMARY), owner);
        assertTrue(mService.checkAuthorityGrants(UID_PRIMARY_SOCIAL,
                cameraInfo, USER_PRIMARY, true));
        assertFalse(mService.checkAuthorityGrants(UID_PRIMARY_SOCIAL,
                cameraInfo, USER_SECONDARY, true));
        assertFalse(mService.checkAuthorityGrants(UID_SECONDARY_SOCIAL,
                cameraInfo, USER_PRIMARY, true));
        assertFalse(mService.checkAuthorityGrants(UID_SECONDARY_SOCIAL,
                cameraInfo, USER_SECONDARY, true));

        // Granting secondary camera to primary social
        mService.grantUriPermissionUncheckedFromIntent(mService.checkGrantUriPermissionFromIntent(
                intent, UID_SECONDARY_CAMERA, PKG_SOCIAL, USER_PRIMARY), owner);
        assertTrue(mService.checkAuthorityGrants(UID_PRIMARY_SOCIAL,
                cameraInfo, USER_PRIMARY, true));
        assertTrue(mService.checkAuthorityGrants(UID_PRIMARY_SOCIAL,
                cameraInfo, USER_SECONDARY, true));
        assertFalse(mService.checkAuthorityGrants(UID_SECONDARY_SOCIAL,
                cameraInfo, USER_PRIMARY, true));
        assertFalse(mService.checkAuthorityGrants(UID_SECONDARY_SOCIAL,
                cameraInfo, USER_SECONDARY, true));

        // And releasing the grant means we lose access
        owner.removeUriPermissions();
        assertFalse(mService.checkAuthorityGrants(UID_PRIMARY_SOCIAL,
                cameraInfo, USER_PRIMARY, true));
        assertFalse(mService.checkAuthorityGrants(UID_PRIMARY_SOCIAL,
                cameraInfo, USER_SECONDARY, true));
    }

    private static <T> Set<T> asSet(T... values) {
        return new ArraySet<T>(Arrays.asList(values));
    }
}
