Decrypt video file

This commit is contained in:
Benoit Marty
2019-07-08 17:07:21 +02:00
parent 1b82ed5abb
commit 12bd85e0a9
11 changed files with 280 additions and 49 deletions

View File

@ -23,6 +23,7 @@ import arrow.core.Try
import okio.Okio
import timber.log.Timber
import java.io.File
import java.io.InputStream
/**
* Save a string to a file with Okio

View File

@ -29,14 +29,7 @@ import im.vector.matrix.android.api.permalinks.MatrixPermalinkSpan
import im.vector.matrix.android.api.session.events.model.RelationType
import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.api.session.room.model.EditAggregatedSummary
import im.vector.matrix.android.api.session.room.model.message.MessageAudioContent
import im.vector.matrix.android.api.session.room.model.message.MessageContent
import im.vector.matrix.android.api.session.room.model.message.MessageEmoteContent
import im.vector.matrix.android.api.session.room.model.message.MessageFileContent
import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
import im.vector.matrix.android.api.session.room.model.message.MessageNoticeContent
import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
import im.vector.matrix.android.api.session.room.model.message.*
import im.vector.matrix.android.api.session.room.send.SendState
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.matrix.android.internal.crypto.attachments.toElementToDecrypt
@ -87,9 +80,9 @@ class MessageItemFactory @Inject constructor(
val messageContent: MessageContent =
event.annotations?.editSummary?.aggregatedContent?.toModel()
?: event.root.getClearContent().toModel()
?: //Malformed content, we should echo something on screen
return DefaultItem_().text(stringProvider.getString(R.string.malformed_message))
?: event.root.getClearContent().toModel()
?: //Malformed content, we should echo something on screen
return DefaultItem_().text(stringProvider.getString(R.string.malformed_message))
if (messageContent.relatesTo?.type == RelationType.REPLACE) {
// ignore replace event, the targeted id is already edited
@ -99,16 +92,16 @@ class MessageItemFactory @Inject constructor(
// val ev = all.toModel<Event>()
return when (messageContent) {
is MessageEmoteContent -> buildEmoteMessageItem(messageContent,
informationData,
event.annotations?.editSummary,
highlight,
callback)
informationData,
event.annotations?.editSummary,
highlight,
callback)
is MessageTextContent -> buildTextMessageItem(event.sendState,
messageContent,
informationData,
event.annotations?.editSummary,
highlight,
callback
messageContent,
informationData,
event.annotations?.editSummary,
highlight,
callback
)
is MessageImageContent -> buildImageMessageItem(messageContent, informationData, highlight, callback)
is MessageNoticeContent -> buildNoticeMessageItem(messageContent, informationData, highlight, callback)
@ -142,7 +135,7 @@ class MessageItemFactory @Inject constructor(
}))
.longClickListener { view ->
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
?: false
?: false
}
}
@ -165,7 +158,7 @@ class MessageItemFactory @Inject constructor(
}))
.longClickListener { view ->
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
?: false
?: false
}
.clickListener(
DebouncedClickListener(View.OnClickListener { _ ->
@ -218,7 +211,7 @@ class MessageItemFactory @Inject constructor(
}))
.longClickListener { view ->
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
?: false
?: false
}
}
@ -239,8 +232,10 @@ class MessageItemFactory @Inject constructor(
)
val videoData = VideoContentRenderer.Data(
eventId = informationData.eventId,
filename = messageContent.body,
videoUrl = messageContent.url,
url = messageContent.encryptedFileInfo?.url ?: messageContent.url,
elementToDecrypt = messageContent.encryptedFileInfo?.toElementToDecrypt(),
thumbnailMediaData = thumbnailData
)
@ -262,7 +257,7 @@ class MessageItemFactory @Inject constructor(
.clickListener { view -> callback?.onVideoMessageClicked(messageContent, videoData, view) }
.longClickListener { view ->
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
?: false
?: false
}
}
@ -302,7 +297,7 @@ class MessageItemFactory @Inject constructor(
}))
.longClickListener { view ->
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
?: false
?: false
}
}
@ -334,9 +329,9 @@ class MessageItemFactory @Inject constructor(
//nop
}
},
editStart,
editEnd,
Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
editStart,
editEnd,
Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
return spannable
}
@ -372,7 +367,7 @@ class MessageItemFactory @Inject constructor(
}))
.longClickListener { view ->
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
?: false
?: false
}
}
@ -408,7 +403,7 @@ class MessageItemFactory @Inject constructor(
}))
.longClickListener { view ->
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
?: false
?: false
}
}

View File

@ -100,7 +100,6 @@ class ImageContentRenderer @Inject constructor(private val activeSessionHolder:
return
}
// TODO DECRYPT_FILE Decrypt file
imageView.showImage(
Uri.parse(thumbnail),
Uri.parse(fullSize)

View File

@ -18,26 +18,87 @@ package im.vector.riotx.features.media
import android.os.Parcelable
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.TextView
import android.widget.VideoView
import androidx.core.view.isVisible
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt
import im.vector.riotx.R
import im.vector.riotx.core.di.ActiveSessionHolder
import im.vector.riotx.core.error.ErrorFormatter
import kotlinx.android.parcel.Parcelize
import timber.log.Timber
import java.io.File
import javax.inject.Inject
class VideoContentRenderer @Inject constructor(private val activeSessionHolder: ActiveSessionHolder){
class VideoContentRenderer @Inject constructor(private val activeSessionHolder: ActiveSessionHolder,
private val errorFormatter: ErrorFormatter) {
// TODO DECRYPT_FILE Encrypted data
@Parcelize
data class Data(
val eventId: String,
val filename: String,
val videoUrl: String?,
val url: String?,
val elementToDecrypt: ElementToDecrypt?,
val thumbnailMediaData: ImageContentRenderer.Data
) : Parcelable
fun render(data: Data, thumbnailView: ImageView, videoView: VideoView) {
fun render(data: Data,
thumbnailView: ImageView,
loadingView: ProgressBar,
videoView: VideoView,
errorView: TextView) {
val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver()
val resolvedUrl = contentUrlResolver.resolveFullSize(data.videoUrl)
videoView.setVideoPath(resolvedUrl)
videoView.start()
if (data.elementToDecrypt != null) {
Timber.v("Decrypt video")
videoView.isVisible = false
if (data.url == null) {
loadingView.isVisible = false
errorView.isVisible = true
errorView.setText(R.string.unknown_error)
} else {
thumbnailView.isVisible = true
loadingView.isVisible = true
activeSessionHolder.getActiveSession()
.decryptFile(data.eventId,
data.filename,
data.url,
data.elementToDecrypt,
object : MatrixCallback<File> {
override fun onSuccess(data: File) {
thumbnailView.isVisible = false
loadingView.isVisible = false
videoView.isVisible = true
videoView.setVideoPath(data.path)
videoView.start()
}
override fun onFailure(failure: Throwable) {
loadingView.isVisible = false
errorView.isVisible = true
errorView.text = errorFormatter.toHumanReadable(failure)
}
})
}
} else {
thumbnailView.isVisible = false
loadingView.isVisible = false
val resolvedUrl = contentUrlResolver.resolveFullSize(data.url)
if (resolvedUrl == null) {
errorView.isVisible = true
errorView.setText(R.string.unknown_error)
} else {
videoView.setVideoPath(resolvedUrl)
videoView.start()
}
}
}
}

View File

@ -28,6 +28,7 @@ import javax.inject.Inject
class VideoMediaViewerActivity : VectorBaseActivity() {
@Inject lateinit var imageContentRenderer: ImageContentRenderer
@Inject lateinit var videoContentRenderer: VideoContentRenderer
override fun injectWith(injector: ScreenComponent) {
@ -38,12 +39,10 @@ class VideoMediaViewerActivity : VectorBaseActivity() {
super.onCreate(savedInstanceState)
setContentView(im.vector.riotx.R.layout.activity_video_media_viewer)
val mediaData = intent.getParcelableExtra<VideoContentRenderer.Data>(EXTRA_MEDIA_DATA)
if (mediaData.videoUrl.isNullOrEmpty()) {
finish()
} else {
configureToolbar(videoMediaViewerToolbar, mediaData)
videoContentRenderer.render(mediaData, videoMediaViewerThumbnailView, videoMediaViewerVideoView)
}
configureToolbar(videoMediaViewerToolbar, mediaData)
imageContentRenderer.render(mediaData.thumbnailMediaData, ImageContentRenderer.Mode.FULL_SIZE, videoMediaViewerThumbnailView)
videoContentRenderer.render(mediaData, videoMediaViewerThumbnailView, videoMediaViewerLoading, videoMediaViewerVideoView, videoMediaViewerErrorView)
}
private fun configureToolbar(toolbar: Toolbar, mediaData: VideoContentRenderer.Data) {

View File

@ -15,6 +15,7 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
@ -32,12 +33,35 @@
<ImageView
android:id="@+id/videoMediaViewerThumbnailView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="match_parent"
android:visibility="gone"
tools:visibility="visible" />
<ProgressBar
android:id="@+id/videoMediaViewerLoading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone"
tools:visibility="visible" />
<VideoView
android:id="@+id/videoMediaViewerVideoView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="match_parent"
android:visibility="gone" />
<TextView
android:id="@+id/videoMediaViewerErrorView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="16dp"
android:textColor="@color/riotx_notice"
android:textSize="16sp"
android:visibility="gone"
tools:text="Error"
tools:visibility="visible" />
</FrameLayout>