Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9a3b6f41 authored by Jason Chang's avatar Jason Chang
Browse files

Fix DocumentsUI causes Gmail to crash when performing drag-n-drop

of a directory

Add defensive check to prevent extra invalid mime type to be
included in a union way of Set.addAll() API call.

Bug: 131121225
Test: manual
Test: atest DocumentsUIGoogleTests
Change-Id: Idceb7eaac5b5f102bd8932ccb2b187a07b794baf
parent 3b30dc16
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.documentsui.base;

import static com.android.documentsui.base.SharedMinimal.DEBUG;

import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.database.Cursor;
@@ -26,6 +28,7 @@ import android.os.Parcelable;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsProvider;
import android.util.Log;

import androidx.annotation.VisibleForTesting;

@@ -48,6 +51,7 @@ import javax.annotation.Nullable;
 * Representation of a {@link Document}.
 */
public class DocumentInfo implements Durable, Parcelable {
    private static final String TAG = "DocumentInfo";
    private static final int VERSION_INIT = 1;
    private static final int VERSION_SPLIT_URI = 2;

@@ -373,7 +377,14 @@ public class DocumentInfo implements Durable, Parcelable {
    public static void addMimeTypes(ContentResolver resolver, Uri uri, Set<String> mimeTypes) {
        assert(uri != null);
        if ("content".equals(uri.getScheme())) {
            mimeTypes.add(resolver.getType(uri));
            final String type = resolver.getType(uri);
            if (type != null) {
                mimeTypes.add(type);
            } else {
                if (DEBUG) {
                    Log.d(TAG, "resolver.getType(uri) return null, url:" + uri.toSafeString());
                }
            }
            final String[] streamTypes = resolver.getStreamTypes(uri, "*/*");
            if (streamTypes != null) {
                mimeTypes.addAll(Arrays.asList(streamTypes));
+83 −8
Original line number Diff line number Diff line
@@ -16,49 +16,124 @@

package com.android.documentsui.base;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import android.provider.DocumentsContract;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;

import com.android.documentsui.base.DocumentInfo;
import androidx.test.rule.provider.ProviderTestRule;

import com.android.documentsui.InspectorProvider;

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

import java.util.HashSet;
import java.util.Set;

@SmallTest
public class DocumentInfoTest extends AndroidTestCase {

    private static final DocumentInfo TEST_DOC
            = createDocInfo("authority.a", "doc.1", "text/plain");
    private static final String FOLDER_NAME = "Top";
    private static final String FILE_NAME = InspectorProvider.OPEN_IN_PROVIDER_TEST;

    private Context mContext;
    private ContentResolver mResolver;

    @Rule
    private ProviderTestRule mProviderTestRule = new ProviderTestRule.Builder(
            InspectorProvider.class, InspectorProvider.AUTHORITY).build();

    @Before
    public void setUp() throws Exception {
        super.setUp();

        mContext = prepareContentResolverSource();
        mResolver = mContext.getContentResolver();
    }

    private static DocumentInfo createDocInfo(String authority, String docId, String mimeType) {
        DocumentInfo doc = new DocumentInfo();
        doc.authority = authority;
        doc.documentId = docId;
        doc.mimeType = mimeType;
        doc.deriveFields();
        return doc;
    }

    protected Context prepareContentResolverSource() {
        ContentResolver contentResolver = mProviderTestRule.getResolver();
        Context context = mock(Context.class);
        // inject ContentResolver
        when(context.getContentResolver()).thenReturn(contentResolver);
        return context;
    }

    @Test
    public void testEquals() throws Exception {
        assertEquals(TEST_DOC, TEST_DOC);
        assertEquals(TEST_DOC, createDocInfo("authority.a", "doc.1", "text/plain"));
    }

    @Test
    public void testEquals_HandlesNulls() throws Exception {
        assertFalse(TEST_DOC.equals(null));
    }

    @Test
    public void testEquals_HandlesNullFields() throws Exception {
        assertFalse(TEST_DOC.equals(new DocumentInfo()));
        assertFalse(new DocumentInfo().equals(TEST_DOC));
    }

    @Test
    public void testNotEquals_differentAuthority() throws Exception {
        assertFalse(TEST_DOC.equals(createDocInfo("authority.b", "doc.1", "text/plain")));
    }

    @Test
    public void testNotEquals_differentDocId() throws Exception {
        assertFalse(TEST_DOC.equals(createDocInfo("authority.a", "doc.2", "text/plain")));
    }

    @Test
    public void testNotEquals_differentMimetype() throws Exception {
        assertFalse(TEST_DOC.equals(createDocInfo("authority.a", "doc.1", "image/png")));
    }

    private static DocumentInfo createDocInfo(String authority, String docId, String mimeType) {
        DocumentInfo doc = new DocumentInfo();
        doc.authority = authority;
        doc.documentId = docId;
        doc.mimeType = mimeType;
        doc.deriveFields();
        return doc;
    @Test
    public void testFolderMimeTypeFromUri() throws Exception {
        final Uri validUri = DocumentsContract.buildDocumentUri(
                InspectorProvider.AUTHORITY, FOLDER_NAME);

        final Set<String> mimeTypes = new HashSet<>();
        DocumentInfo.addMimeTypes(mResolver, validUri, mimeTypes);

        assertThat(mimeTypes.size()).isEqualTo(1);

        assertThat(mimeTypes.contains(DocumentsContract.Document.MIME_TYPE_DIR)).isTrue();
    }

    @Test
    public void testFileMimeTypeFromUri() throws Exception {
        final Uri validUri = DocumentsContract.buildDocumentUri(
                InspectorProvider.AUTHORITY, FILE_NAME);

        final Set<String> mimeTypes = new HashSet<>();
        DocumentInfo.addMimeTypes(mResolver, validUri, mimeTypes);

        assertThat(mimeTypes.size()).isEqualTo(1);

        assertThat(mimeTypes.contains("text/plain")).isTrue();
    }
}