SecurityException: Permission Denial (#21290)

Fix `java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider`

Fixes flutter/flutter#66108

Co-authored-by: Dan Field <dfield@gmail.com>
This commit is contained in:
Hamdi Kahloun 2020-10-08 22:36:51 +01:00 committed by GitHub
parent 9ab40c2809
commit b2ace0cccb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 6 deletions

View File

@ -17,7 +17,9 @@ import android.view.Window;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import io.flutter.Log;
import io.flutter.embedding.engine.systemchannels.PlatformChannel;
import java.io.FileNotFoundException;
import java.util.List;
/** Android implementation of the platform plugin. */
@ -29,6 +31,7 @@ public class PlatformPlugin {
private final PlatformChannel platformChannel;
private PlatformChannel.SystemChromeStyle currentTheme;
private int mEnabledOverlays;
private static final String TAG = "PlatformPlugin";
@VisibleForTesting
final PlatformChannel.PlatformMessageHandler mPlatformMessageHandler =
@ -283,11 +286,25 @@ public class PlatformPlugin {
if (!clipboard.hasPrimaryClip()) return null;
ClipData clip = clipboard.getPrimaryClip();
if (clip == null) return null;
if (format == null || format == PlatformChannel.ClipboardContentFormat.PLAIN_TEXT) {
return clip.getItemAt(0).coerceToText(activity);
try {
ClipData clip = clipboard.getPrimaryClip();
if (clip == null) return null;
if (format == null || format == PlatformChannel.ClipboardContentFormat.PLAIN_TEXT) {
ClipData.Item item = clip.getItemAt(0);
if (item.getUri() != null)
activity.getContentResolver().openTypedAssetFileDescriptor(item.getUri(), "text/*", null);
return item.coerceToText(activity);
}
} catch (SecurityException e) {
Log.w(
TAG,
"Attempted to get clipboard data that requires additional permission(s).\n"
+ "See the exception details for which permission(s) are required, and consider adding them to your Android Manifest as described in:\n"
+ "https://developer.android.com/guide/topics/permissions/overview",
e);
return null;
} catch (FileNotFoundException e) {
return null;
}
return null;

View File

@ -1,5 +1,6 @@
package io.flutter.plugin.platform;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@ -10,11 +11,17 @@ import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.ContentResolver;
import android.content.Context;
import android.media.RingtoneManager;
import android.net.Uri;
import android.view.View;
import android.view.Window;
import io.flutter.embedding.engine.systemchannels.PlatformChannel;
import io.flutter.embedding.engine.systemchannels.PlatformChannel.ClipboardContentFormat;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
@ -42,8 +49,9 @@ public class PlatformPluginTest {
platformPlugin.vibrateHapticFeedback(PlatformChannel.HapticFeedbackType.SELECTION_CLICK);
}
@Config(sdk = 29)
@Test
public void platformPlugin_getClipboardData() {
public void platformPlugin_getClipboardData() throws IOException {
ClipboardManager clipboardManager =
RuntimeEnvironment.application.getSystemService(ClipboardManager.class);
@ -61,6 +69,23 @@ public class PlatformPluginTest {
ClipData clip = ClipData.newPlainText("label", "Text");
clipboardManager.setPrimaryClip(clip);
assertNotNull(platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat));
ContentResolver contentResolver = RuntimeEnvironment.application.getContentResolver();
Uri uri = Uri.parse("content://media/external_primary/images/media/");
clip = ClipData.newUri(contentResolver, "URI", uri);
clipboardManager.setPrimaryClip(clip);
assertNull(platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat));
uri =
RingtoneManager.getActualDefaultRingtoneUri(
RuntimeEnvironment.application.getApplicationContext(), RingtoneManager.TYPE_RINGTONE);
clip = ClipData.newUri(contentResolver, "URI", uri);
clipboardManager.setPrimaryClip(clip);
String uriData =
platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat).toString();
InputStream uriInputStream = contentResolver.openInputStream(uri);
InputStream dataInputStream = new ByteArrayInputStream(uriData.getBytes());
assertEquals(dataInputStream.read(), uriInputStream.read());
}
@Test