mirror of
https://github.com/element-hq/element-android
synced 2024-11-28 05:31:21 +03:00
Stop sending media in an infinite loop in case of error (part of #587)
Not sure how this commit fix it, but the issue is not observed anymore with it
This commit is contained in:
parent
f3039601bf
commit
f077cc8467
4 changed files with 77 additions and 83 deletions
|
@ -17,7 +17,6 @@
|
|||
package im.vector.matrix.android.internal.crypto.attachments
|
||||
|
||||
import android.util.Base64
|
||||
import arrow.core.Try
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.EncryptedFileInfo
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.EncryptedFileKey
|
||||
import timber.log.Timber
|
||||
|
@ -50,7 +49,7 @@ object MXEncryptedAttachments {
|
|||
* @param mimetype the mime type
|
||||
* @return the encryption file info
|
||||
*/
|
||||
fun encryptAttachment(attachmentStream: InputStream, mimetype: String): Try<EncryptionResult> {
|
||||
fun encryptAttachment(attachmentStream: InputStream, mimetype: String): EncryptionResult {
|
||||
val t0 = System.currentTimeMillis()
|
||||
val secureRandom = SecureRandom()
|
||||
|
||||
|
@ -70,7 +69,7 @@ object MXEncryptedAttachments {
|
|||
|
||||
val outStream = ByteArrayOutputStream()
|
||||
|
||||
try {
|
||||
outStream.use {
|
||||
val encryptCipher = Cipher.getInstance(CIPHER_ALGORITHM)
|
||||
val secretKeySpec = SecretKeySpec(key, SECRET_KEY_SPEC_ALGORITHM)
|
||||
val ivParameterSpec = IvParameterSpec(initVectorBytes)
|
||||
|
@ -114,19 +113,7 @@ object MXEncryptedAttachments {
|
|||
)
|
||||
|
||||
Timber.v("Encrypt in ${System.currentTimeMillis() - t0} ms")
|
||||
return Try.just(result)
|
||||
} catch (oom: OutOfMemoryError) {
|
||||
Timber.e(oom, "## encryptAttachment failed")
|
||||
return Try.Failure(oom)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "## encryptAttachment failed")
|
||||
return Try.Failure(e)
|
||||
} finally {
|
||||
try {
|
||||
outStream.close()
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "## encryptAttachment() : fail to close outStream")
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ import retrofit2.Call
|
|||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
import timber.log.Timber
|
||||
import java.io.IOException
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.resumeWithException
|
||||
|
||||
|
@ -50,6 +51,24 @@ internal suspend fun <T> Call<T>.awaitResponse(): Response<T> {
|
|||
}
|
||||
}
|
||||
|
||||
internal suspend fun okhttp3.Call.awaitResponse(): okhttp3.Response {
|
||||
return suspendCancellableCoroutine { continuation ->
|
||||
continuation.invokeOnCancellation {
|
||||
cancel()
|
||||
}
|
||||
|
||||
enqueue(object : okhttp3.Callback {
|
||||
override fun onResponse(call: okhttp3.Call, response: okhttp3.Response) {
|
||||
continuation.resume(response)
|
||||
}
|
||||
|
||||
override fun onFailure(call: okhttp3.Call, e: IOException) {
|
||||
continuation.resumeWithException(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a retrofit Response to a Failure, and eventually parse errorBody to convert it to a MatrixError
|
||||
*/
|
||||
|
|
|
@ -16,12 +16,11 @@
|
|||
|
||||
package im.vector.matrix.android.internal.session.content
|
||||
|
||||
import arrow.core.Try
|
||||
import arrow.core.Try.Companion.raise
|
||||
import com.squareup.moshi.Moshi
|
||||
import im.vector.matrix.android.api.auth.data.SessionParams
|
||||
import im.vector.matrix.android.internal.di.Authenticated
|
||||
import im.vector.matrix.android.internal.network.ProgressRequestBody
|
||||
import im.vector.matrix.android.internal.network.awaitResponse
|
||||
import im.vector.matrix.android.internal.network.toFailure
|
||||
import okhttp3.*
|
||||
import java.io.File
|
||||
|
@ -38,28 +37,26 @@ internal class FileUploader @Inject constructor(@Authenticated
|
|||
private val responseAdapter = moshi.adapter(ContentUploadResponse::class.java)
|
||||
|
||||
|
||||
fun uploadFile(file: File,
|
||||
filename: String?,
|
||||
mimeType: String,
|
||||
progressListener: ProgressRequestBody.Listener? = null): Try<ContentUploadResponse> {
|
||||
|
||||
suspend fun uploadFile(file: File,
|
||||
filename: String?,
|
||||
mimeType: String,
|
||||
progressListener: ProgressRequestBody.Listener? = null): ContentUploadResponse {
|
||||
val uploadBody = RequestBody.create(MediaType.parse(mimeType), file)
|
||||
return upload(uploadBody, filename, progressListener)
|
||||
|
||||
}
|
||||
|
||||
fun uploadByteArray(byteArray: ByteArray,
|
||||
filename: String?,
|
||||
mimeType: String,
|
||||
progressListener: ProgressRequestBody.Listener? = null): Try<ContentUploadResponse> {
|
||||
|
||||
suspend fun uploadByteArray(byteArray: ByteArray,
|
||||
filename: String?,
|
||||
mimeType: String,
|
||||
progressListener: ProgressRequestBody.Listener? = null): ContentUploadResponse {
|
||||
val uploadBody = RequestBody.create(MediaType.parse(mimeType), byteArray)
|
||||
return upload(uploadBody, filename, progressListener)
|
||||
}
|
||||
|
||||
|
||||
private fun upload(uploadBody: RequestBody, filename: String?, progressListener: ProgressRequestBody.Listener?): Try<ContentUploadResponse> {
|
||||
val urlBuilder = HttpUrl.parse(uploadUrl)?.newBuilder() ?: return raise(RuntimeException())
|
||||
private suspend fun upload(uploadBody: RequestBody, filename: String?, progressListener: ProgressRequestBody.Listener?): ContentUploadResponse {
|
||||
val urlBuilder = HttpUrl.parse(uploadUrl)?.newBuilder() ?: throw RuntimeException()
|
||||
|
||||
val httpUrl = urlBuilder
|
||||
.addQueryParameter("filename", filename)
|
||||
|
@ -72,19 +69,15 @@ internal class FileUploader @Inject constructor(@Authenticated
|
|||
.post(requestBody)
|
||||
.build()
|
||||
|
||||
return Try {
|
||||
okHttpClient.newCall(request).execute().use { response ->
|
||||
if (!response.isSuccessful) {
|
||||
throw response.toFailure()
|
||||
} else {
|
||||
response.body()?.source()?.let {
|
||||
responseAdapter.fromJson(it)
|
||||
}
|
||||
?: throw IOException()
|
||||
return okHttpClient.newCall(request).awaitResponse().use { response ->
|
||||
if (!response.isSuccessful) {
|
||||
throw response.toFailure()
|
||||
} else {
|
||||
response.body()?.source()?.let {
|
||||
responseAdapter.fromJson(it)
|
||||
}
|
||||
?: throw IOException()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -93,32 +93,28 @@ internal class UploadContentWorker(context: Context, params: WorkerParameters) :
|
|||
}
|
||||
}
|
||||
|
||||
val contentUploadResponse = if (params.isRoomEncrypted) {
|
||||
Timber.v("Encrypt thumbnail")
|
||||
contentUploadStateTracker.setEncryptingThumbnail(eventId)
|
||||
MXEncryptedAttachments.encryptAttachment(ByteArrayInputStream(thumbnailData.bytes), thumbnailData.mimeType)
|
||||
.flatMap { encryptionResult ->
|
||||
uploadedThumbnailEncryptedFileInfo = encryptionResult.encryptedFileInfo
|
||||
try {
|
||||
val contentUploadResponse = if (params.isRoomEncrypted) {
|
||||
Timber.v("Encrypt thumbnail")
|
||||
contentUploadStateTracker.setEncryptingThumbnail(eventId)
|
||||
val encryptionResult = MXEncryptedAttachments.encryptAttachment(ByteArrayInputStream(thumbnailData.bytes), thumbnailData.mimeType)
|
||||
uploadedThumbnailEncryptedFileInfo = encryptionResult.encryptedFileInfo
|
||||
fileUploader.uploadByteArray(encryptionResult.encryptedByteArray,
|
||||
"thumb_${attachment.name}",
|
||||
"application/octet-stream",
|
||||
thumbnailProgressListener)
|
||||
} else {
|
||||
fileUploader.uploadByteArray(thumbnailData.bytes,
|
||||
"thumb_${attachment.name}",
|
||||
thumbnailData.mimeType,
|
||||
thumbnailProgressListener)
|
||||
}
|
||||
|
||||
fileUploader
|
||||
.uploadByteArray(encryptionResult.encryptedByteArray,
|
||||
"thumb_${attachment.name}",
|
||||
"application/octet-stream",
|
||||
thumbnailProgressListener)
|
||||
}
|
||||
} else {
|
||||
fileUploader
|
||||
.uploadByteArray(thumbnailData.bytes,
|
||||
"thumb_${attachment.name}",
|
||||
thumbnailData.mimeType,
|
||||
thumbnailProgressListener)
|
||||
uploadedThumbnailUrl = contentUploadResponse.contentUri
|
||||
} catch (t: Throwable) {
|
||||
Timber.e(t)
|
||||
return handleFailure(params, t)
|
||||
}
|
||||
|
||||
contentUploadResponse
|
||||
.fold(
|
||||
{ Timber.e(it) },
|
||||
{ uploadedThumbnailUrl = it.contentUri }
|
||||
)
|
||||
}
|
||||
|
||||
val progressListener = object : ProgressRequestBody.Listener {
|
||||
|
@ -133,27 +129,26 @@ internal class UploadContentWorker(context: Context, params: WorkerParameters) :
|
|||
|
||||
var uploadedFileEncryptedFileInfo: EncryptedFileInfo? = null
|
||||
|
||||
val contentUploadResponse = if (params.isRoomEncrypted) {
|
||||
Timber.v("Encrypt file")
|
||||
contentUploadStateTracker.setEncrypting(eventId)
|
||||
return try {
|
||||
val contentUploadResponse = if (params.isRoomEncrypted) {
|
||||
Timber.v("Encrypt file")
|
||||
contentUploadStateTracker.setEncrypting(eventId)
|
||||
|
||||
MXEncryptedAttachments.encryptAttachment(FileInputStream(attachmentFile), attachment.mimeType)
|
||||
.flatMap { encryptionResult ->
|
||||
uploadedFileEncryptedFileInfo = encryptionResult.encryptedFileInfo
|
||||
val encryptionResult = MXEncryptedAttachments.encryptAttachment(FileInputStream(attachmentFile), attachment.mimeType)
|
||||
uploadedFileEncryptedFileInfo = encryptionResult.encryptedFileInfo
|
||||
|
||||
fileUploader
|
||||
.uploadByteArray(encryptionResult.encryptedByteArray, attachment.name, "application/octet-stream", progressListener)
|
||||
}
|
||||
} else {
|
||||
fileUploader
|
||||
.uploadFile(attachmentFile, attachment.name, attachment.mimeType, progressListener)
|
||||
fileUploader
|
||||
.uploadByteArray(encryptionResult.encryptedByteArray, attachment.name, "application/octet-stream", progressListener)
|
||||
} else {
|
||||
fileUploader
|
||||
.uploadFile(attachmentFile, attachment.name, attachment.mimeType, progressListener)
|
||||
}
|
||||
|
||||
handleSuccess(params, contentUploadResponse.contentUri, uploadedFileEncryptedFileInfo, uploadedThumbnailUrl, uploadedThumbnailEncryptedFileInfo)
|
||||
} catch (t: Throwable) {
|
||||
Timber.e(t)
|
||||
handleFailure(params, t)
|
||||
}
|
||||
|
||||
return contentUploadResponse
|
||||
.fold(
|
||||
{ handleFailure(params, it) },
|
||||
{ handleSuccess(params, it.contentUri, uploadedFileEncryptedFileInfo, uploadedThumbnailUrl, uploadedThumbnailEncryptedFileInfo) }
|
||||
)
|
||||
}
|
||||
|
||||
private fun handleFailure(params: Params, failure: Throwable): Result {
|
||||
|
|
Loading…
Reference in a new issue