picker: prevent security exception

This commit is contained in:
Thibault Deckers 2024-10-13 22:04:01 +02:00
parent 2932e0b80f
commit 1058aba262

View file

@ -432,8 +432,13 @@ open class MainActivity : FlutterFragmentActivity() {
open fun submitPickedItems(call: MethodCall, result: MethodChannel.Result) { open fun submitPickedItems(call: MethodCall, result: MethodChannel.Result) {
val pickedUris = call.argument<List<String>>("uris") val pickedUris = call.argument<List<String>>("uris")
try { if (pickedUris.isNullOrEmpty()) {
if (!pickedUris.isNullOrEmpty()) { setResult(RESULT_CANCELED)
// move code triggering `Binder` call off the main thread
defaultScope.launch { finish() }
return
}
val toUri = { uriString: String -> AppAdapterHandler.getShareableUri(this@MainActivity, Uri.parse(uriString)) } val toUri = { uriString: String -> AppAdapterHandler.getShareableUri(this@MainActivity, Uri.parse(uriString)) }
val intent = Intent().apply { val intent = Intent().apply {
val firstUri = toUri(pickedUris.first()) val firstUri = toUri(pickedUris.first())
@ -446,19 +451,30 @@ open class MainActivity : FlutterFragmentActivity() {
} }
} }
} }
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
}
setResult(RESULT_OK, intent)
} else {
setResult(RESULT_CANCELED)
} }
// move code triggering `Binder` call off the main thread // move code triggering `Binder` call off the main thread
defaultScope.launch { finish() } defaultScope.launch {
submitPickedItemsIntent(intent, result)
}
}
private fun submitPickedItemsIntent(intent: Intent, result: MethodChannel.Result) {
try {
setResult(RESULT_OK, intent)
finish()
} catch (e: Exception) { } catch (e: Exception) {
if (e is TransactionTooLargeException || e.cause is TransactionTooLargeException) { if (e is SecurityException && intent.flags and Intent.FLAG_GRANT_WRITE_URI_PERMISSION != 0) {
result.error("submitPickedItems-large", "transaction too large with ${pickedUris?.size} URIs", e) // in some environments, providing the write flag yields a `SecurityException`:
// "UID XXXX does not have permission to content://XXXX"
// so we retry without it
Log.i(LOG_TAG, "retry submitting picked items without FLAG_GRANT_WRITE_URI_PERMISSION")
intent.flags = intent.flags and Intent.FLAG_GRANT_WRITE_URI_PERMISSION.inv()
submitPickedItemsIntent(intent, result)
} else if (e is TransactionTooLargeException || e.cause is TransactionTooLargeException) {
result.error("submitPickedItems-large", "transaction too large with ${intent.clipData?.itemCount} URIs", e)
} else { } else {
result.error("submitPickedItems-exception", "failed to pick ${pickedUris?.size} URIs", e) result.error("submitPickedItems-exception", "failed to pick ${intent.clipData?.itemCount} URIs", e)
} }
} }
} }