Merge branch 'fix/2848_allow-downloading-pgp/mime-message-attachments' into 'develop'
Fixes downloading of the pgp/mime message attachments See merge request android/mail/proton-mail-android!1055
This commit is contained in:
commit
de39dad5ff
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Proton Technologies AG
|
||||
*
|
||||
* This file is part of ProtonMail.
|
||||
*
|
||||
* ProtonMail is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonMail is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package ch.protonmail.android.attachments
|
||||
|
||||
import ch.protonmail.android.crypto.AddressCrypto
|
||||
import ch.protonmail.android.data.local.model.Attachment
|
||||
import javax.inject.Inject
|
||||
|
||||
class ExtractAttachmentByteArray @Inject constructor(
|
||||
private val attachmentsRepository: AttachmentsRepository
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(attachment: Attachment, addressCrypto: AddressCrypto): ByteArray? {
|
||||
return attachment.mimeData ?: attachmentsRepository.getAttachmentDataOrNull(
|
||||
addressCrypto,
|
||||
requireNotNull(attachment.attachmentId),
|
||||
requireNotNull(attachment.keyPackets)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -57,7 +57,7 @@ class HandleSingleAttachment @Inject constructor(
|
|||
private val databaseProvider: DatabaseProvider,
|
||||
private val attachmentsHelper: AttachmentsHelper,
|
||||
private val clearingServiceHelper: AttachmentClearingServiceHelper,
|
||||
private val attachmentsRepository: AttachmentsRepository
|
||||
private val extractAttachmentByteArray: ExtractAttachmentByteArray
|
||||
) {
|
||||
|
||||
private val attachmentMetadataDao: AttachmentMetadataDao
|
||||
|
@ -153,17 +153,13 @@ class HandleSingleAttachment @Inject constructor(
|
|||
crypto: AddressCrypto,
|
||||
mimeType: String?
|
||||
): Uri? {
|
||||
val decryptedByteArray = attachmentsRepository.getAttachmentDataOrNull(
|
||||
crypto,
|
||||
requireNotNull(attachment.attachmentId),
|
||||
requireNotNull(attachment.keyPackets)
|
||||
)
|
||||
|
||||
return decryptedByteArray?.inputStream()?.let {
|
||||
attachmentsHelper.saveAttachmentInMediaStore(
|
||||
context.contentResolver, filename, mimeType, it
|
||||
)
|
||||
}
|
||||
return extractAttachmentByteArray(attachment, crypto)
|
||||
?.inputStream()
|
||||
?.let {
|
||||
attachmentsHelper.saveAttachmentInMediaStore(
|
||||
context.contentResolver, filename, mimeType, it
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun downloadAttachmentBeforeQ(
|
||||
|
@ -172,24 +168,18 @@ class HandleSingleAttachment @Inject constructor(
|
|||
crypto: AddressCrypto,
|
||||
mimeType: String?
|
||||
): Uri? {
|
||||
|
||||
val decryptedByteArray = attachmentsRepository.getAttachmentDataOrNull(
|
||||
crypto,
|
||||
requireNotNull(attachment.attachmentId),
|
||||
requireNotNull(attachment.keyPackets)
|
||||
)
|
||||
|
||||
return decryptedByteArray?.let { bytes ->
|
||||
val file = saveBytesToFile(filename, bytes)
|
||||
val result = awaitUriFromMediaScanned(
|
||||
context,
|
||||
file,
|
||||
mimeType
|
||||
)
|
||||
val uri = result.second
|
||||
Timber.v("Stored file: $filename path: ${result.first} uri: $uri")
|
||||
uri
|
||||
}
|
||||
return extractAttachmentByteArray(attachment, crypto)
|
||||
?.let { bytes ->
|
||||
val file = saveBytesToFile(filename, bytes)
|
||||
val result = awaitUriFromMediaScanned(
|
||||
context,
|
||||
file,
|
||||
mimeType
|
||||
)
|
||||
val uri = result.second
|
||||
Timber.v("Stored file: $filename path: ${result.first} uri: $uri")
|
||||
uri
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveBytesToFile(filename: String, bytes: ByteArray): File {
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Proton Technologies AG
|
||||
*
|
||||
* This file is part of ProtonMail.
|
||||
*
|
||||
* ProtonMail is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonMail is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package ch.protonmail.android.attachments
|
||||
|
||||
import ch.protonmail.android.crypto.AddressCrypto
|
||||
import ch.protonmail.android.testdata.AttachmentTestData
|
||||
import io.mockk.called
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import kotlinx.coroutines.test.runBlockingTest
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertSame
|
||||
|
||||
internal class ExtractAttachmentByteArrayTest {
|
||||
|
||||
private val addressCryptoMock = mockk<AddressCrypto>()
|
||||
private val attachmentsRepositoryMock = mockk<AttachmentsRepository>()
|
||||
private val extractAttachmentByteArray = ExtractAttachmentByteArray(
|
||||
attachmentsRepositoryMock
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `should return the in memory mime data when it is present`() = runBlockingTest {
|
||||
// given
|
||||
val expectedAttachmentBytes = AttachmentTestData.WITH_MIME_DATA.mimeData
|
||||
|
||||
// when
|
||||
val actualAttachmentBytes = extractAttachmentByteArray(
|
||||
AttachmentTestData.WITH_MIME_DATA,
|
||||
addressCryptoMock
|
||||
)
|
||||
|
||||
// then
|
||||
assertSame(expectedAttachmentBytes, actualAttachmentBytes)
|
||||
verify { addressCryptoMock wasNot called }
|
||||
verify { attachmentsRepositoryMock wasNot called }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should get attachment byte array through repository when in memory mime data not present`() = runBlockingTest {
|
||||
// given
|
||||
val expectedAttachmentBytes = ByteArray(42)
|
||||
coEvery {
|
||||
attachmentsRepositoryMock.getAttachmentDataOrNull(
|
||||
addressCryptoMock,
|
||||
AttachmentTestData.ID,
|
||||
AttachmentTestData.KEY_PACKETS
|
||||
)
|
||||
} returns expectedAttachmentBytes
|
||||
|
||||
// when
|
||||
val actualAttachmentBytes = extractAttachmentByteArray(
|
||||
AttachmentTestData.WITHOUT_MIME_DATA,
|
||||
addressCryptoMock
|
||||
)
|
||||
|
||||
// then
|
||||
assertSame(expectedAttachmentBytes, actualAttachmentBytes)
|
||||
}
|
||||
}
|
|
@ -48,10 +48,10 @@ class HandleSingleAttachmentTest : ArchTest {
|
|||
private val context: Context = mockk()
|
||||
private val userManager: UserManager = mockk()
|
||||
private val databaseProvider: DatabaseProvider = mockk()
|
||||
private val attachmentsRepository: AttachmentsRepository = mockk()
|
||||
private val clearingServiceHelper: AttachmentClearingServiceHelper = mockk()
|
||||
private val attachmentsHelper: AttachmentsHelper = mockk()
|
||||
private val testMimeType = "image/jpeg"
|
||||
private val extractAttachmentByteArray: ExtractAttachmentByteArray = mockk()
|
||||
|
||||
val useCase = HandleSingleAttachment(
|
||||
context,
|
||||
|
@ -59,7 +59,7 @@ class HandleSingleAttachmentTest : ArchTest {
|
|||
databaseProvider,
|
||||
attachmentsHelper,
|
||||
clearingServiceHelper,
|
||||
attachmentsRepository
|
||||
extractAttachmentByteArray
|
||||
)
|
||||
|
||||
@BeforeTest
|
||||
|
@ -101,9 +101,7 @@ class HandleSingleAttachmentTest : ArchTest {
|
|||
every { keyPackets } returns testKeyPackets
|
||||
}
|
||||
coEvery {
|
||||
attachmentsRepository.getAttachmentDataOrNull(
|
||||
crypto, testAttachmentId, testKeyPackets
|
||||
)
|
||||
extractAttachmentByteArray(attachment, crypto)
|
||||
} returns testBytePackets
|
||||
val expected = ListenableWorker.Result.failure()
|
||||
|
||||
|
@ -112,9 +110,7 @@ class HandleSingleAttachmentTest : ArchTest {
|
|||
|
||||
// then
|
||||
coVerify(exactly = 3) {
|
||||
attachmentsRepository.getAttachmentDataOrNull(
|
||||
crypto, testAttachmentId, testKeyPackets
|
||||
)
|
||||
extractAttachmentByteArray(attachment, crypto)
|
||||
}
|
||||
assertEquals(expected, result)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Proton Technologies AG
|
||||
*
|
||||
* This file is part of ProtonMail.
|
||||
*
|
||||
* ProtonMail is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonMail is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package ch.protonmail.android.testdata
|
||||
|
||||
import ch.protonmail.android.data.local.model.Attachment
|
||||
|
||||
object AttachmentTestData {
|
||||
const val ID = "attachmentId"
|
||||
const val KEY_PACKETS = "keyPackets"
|
||||
val WITH_MIME_DATA = Attachment(attachmentId = ID, mimeData = ByteArray(10), keyPackets = KEY_PACKETS)
|
||||
val WITHOUT_MIME_DATA = Attachment(attachmentId = ID, mimeData = null, keyPackets = KEY_PACKETS)
|
||||
}
|
Loading…
Reference in New Issue