Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/src/main/kotlin/ee/ria/DigiDoc/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,10 @@ class MainActivity :

val componentClassName = this.javaClass.name

val externalFileUris = if (savedInstanceState == null) getExternalFileUris(intent) else emptyList()
val locale = dataStore.getLocale() ?: getLocale("en")
val webEidUri = intent.data?.takeIf { WebEidUriUtil.isWebEidUri(it) }
val browserPackage = if (webEidUri != null) resolveBrowserPackage(intent) else null
val externalFileUris = getExternalFileUris(intent)

localeUtil.updateLocale(applicationContext, locale)

Expand Down
28 changes: 16 additions & 12 deletions utils-lib/src/main/kotlin/ee/ria/DigiDoc/utilsLib/file/FileUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -507,18 +507,22 @@ object FileUtil {
}

fun getExternalFileUris(intent: Intent): List<Uri> {
val externalFileUris = mutableListOf<Uri>()
intent.data?.takeIf { it.scheme in ALLOWED_FILE_SCHEMES }?.let { externalFileUris.add(it) }
intent.clipData?.let { clipData ->
for (i in 0 until clipData.itemCount) {
clipData
.getItemAt(
i,
)?.uri
?.takeIf { it.scheme in ALLOWED_FILE_SCHEMES }
?.let { externalFileUris.add(it) }
val clipData = intent.clipData
val data = intent.data
val uris =
when {
// The same file can be in both clipData and data, so read clipData only to avoid duplicates.
clipData != null && clipData.itemCount > 0 ->
(0 until clipData.itemCount).mapNotNull { clipData.getItemAt(it)?.uri }
// If there is no clipData, take the file from data, or from a share (EXTRA_STREAM).
data != null -> listOf(data)
intent.action == Intent.ACTION_SEND ->
listOfNotNull(intent.getParcelableExtra(Intent.EXTRA_STREAM, Uri::class.java))
intent.action == Intent.ACTION_SEND_MULTIPLE ->
intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM, Uri::class.java).orEmpty()
else -> emptyList()
}
}
return externalFileUris
// Only file-backed schemes are openable. Drop web (https) and deep-link (e.g. web-eid-mobile) URIs.
return uris.filter { it.scheme in ALLOWED_FILE_SCHEMES }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -175,30 +175,60 @@ class FileUtilTest {
}

@Test
fun fileUtil_getExternalFileUris_clipDataFiltersOutNonAllowedSchemes() =
fun fileUtil_getExternalFileUris_returnsSingleUriWhenFileInBothDataAndClipData() =
runBlocking {
val mockIntent = mock(Intent::class.java)
val mockClipData = mock(ClipData::class.java)
val mockClipDataItem1 = mock(ClipData.Item::class.java)
val mockClipDataItem2 = mock(ClipData.Item::class.java)
val mockUri1 = mock(Uri::class.java)
val mockUri2 = mock(Uri::class.java)
val mockClipDataItem = mock(ClipData.Item::class.java)
val mockUri = mock(Uri::class.java)

`when`(mockUri1.scheme).thenReturn("content")
`when`(mockUri2.scheme).thenReturn("https")
`when`(mockClipDataItem1.uri).thenReturn(mockUri1)
`when`(mockClipDataItem2.uri).thenReturn(mockUri2)
`when`(mockUri.scheme).thenReturn("content")
`when`(mockIntent.data).thenReturn(mockUri)
`when`(mockClipDataItem.uri).thenReturn(mockUri)
`when`(mockClipData.getItemAt(0)).thenReturn(mockClipDataItem)
`when`(mockClipData.itemCount).thenReturn(1)
`when`(mockIntent.clipData).thenReturn(mockClipData)

`when`(mockClipData.getItemAt(0)).thenReturn(mockClipDataItem1)
`when`(mockClipData.getItemAt(1)).thenReturn(mockClipDataItem2)
`when`(mockClipData.itemCount).thenReturn(2)
val externalFileUris = FileUtil.getExternalFileUris(mockIntent)

`when`(mockIntent.clipData).thenReturn(mockClipData)
assertEquals(1, externalFileUris.size)
assertEquals(mockUri, externalFileUris.first())
}

@Test
fun fileUtil_getExternalFileUris_fallsBackToExtraStreamForActionSend() =
runBlocking {
val mockIntent = mock(Intent::class.java)
val mockUri = mock(Uri::class.java)

`when`(mockUri.scheme).thenReturn("content")
`when`(mockIntent.action).thenReturn(Intent.ACTION_SEND)
`when`(mockIntent.getParcelableExtra(Intent.EXTRA_STREAM, Uri::class.java)).thenReturn(mockUri)

val externalFileUris = FileUtil.getExternalFileUris(mockIntent)

assertEquals(1, externalFileUris.size)
assertEquals(mockUri, externalFileUris.first())
}

@Test
fun fileUtil_getExternalFileUris_fallsBackToExtraStreamForActionSendMultiple() =
runBlocking {
val mockIntent = mock(Intent::class.java)
val mockUri1 = mock(Uri::class.java)
val mockUri2 = mock(Uri::class.java)

`when`(mockUri1.scheme).thenReturn("content")
`when`(mockUri2.scheme).thenReturn("content")
`when`(mockIntent.action).thenReturn(Intent.ACTION_SEND_MULTIPLE)
`when`(mockIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM, Uri::class.java))
.thenReturn(arrayListOf(mockUri1, mockUri2))

val externalFileUris = FileUtil.getExternalFileUris(mockIntent)

assertEquals(2, externalFileUris.size)
assertEquals(mockUri1, externalFileUris.first())
assertEquals(mockUri2, externalFileUris.last())
}

@Test
Expand Down
Loading