Export the key share trail in rageshake (opt-in)
This commit is contained in:
parent
41e3ff381f
commit
077bcb3f2a
|
@ -69,6 +69,9 @@ class BugReportActivity : VectorBaseActivity() {
|
|||
bug_report_button_include_crash_logs.isChecked = false
|
||||
bug_report_button_include_crash_logs.isVisible = false
|
||||
|
||||
bug_report_button_include_key_share_history.isChecked = false
|
||||
bug_report_button_include_key_share_history.isVisible = false
|
||||
|
||||
// Keep the screenshot
|
||||
} else {
|
||||
supportActionBar?.setTitle(R.string.title_activity_bug_report)
|
||||
|
@ -121,6 +124,7 @@ class BugReportActivity : VectorBaseActivity() {
|
|||
forSuggestion,
|
||||
bug_report_button_include_logs.isChecked,
|
||||
bug_report_button_include_crash_logs.isChecked,
|
||||
bug_report_button_include_key_share_history.isChecked,
|
||||
bug_report_button_include_screenshot.isChecked,
|
||||
bug_report_edit_text.text.toString(),
|
||||
object : BugReporter.IMXBugReportListener {
|
||||
|
|
|
@ -33,6 +33,7 @@ import im.vector.app.core.extensions.getAllChildFragments
|
|||
import im.vector.app.core.extensions.toOnOff
|
||||
import im.vector.app.features.settings.VectorLocale
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import im.vector.app.features.settings.devtools.GossipingEventsSerializer
|
||||
import im.vector.app.features.settings.locale.SystemLocaleProvider
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
import im.vector.app.features.version.VersionProvider
|
||||
|
@ -74,6 +75,7 @@ class BugReporter @Inject constructor(
|
|||
private const val LOG_CAT_FILENAME = "logcat.log"
|
||||
private const val LOG_CAT_SCREENSHOT_FILENAME = "screenshot.png"
|
||||
private const val CRASH_FILENAME = "crash.log"
|
||||
private const val KEY_REQUESTS_FILENAME = "keyRequests.log"
|
||||
|
||||
private const val BUFFER_SIZE = 1024 * 1024 * 50
|
||||
}
|
||||
|
@ -143,6 +145,7 @@ class BugReporter @Inject constructor(
|
|||
* @param forSuggestion true to send a suggestion
|
||||
* @param withDevicesLogs true to include the device log
|
||||
* @param withCrashLogs true to include the crash logs
|
||||
* @param withKeyRequestHistory true to include the crash logs
|
||||
* @param withScreenshot true to include the screenshot
|
||||
* @param theBugDescription the bug description
|
||||
* @param listener the listener
|
||||
|
@ -152,6 +155,7 @@ class BugReporter @Inject constructor(
|
|||
forSuggestion: Boolean,
|
||||
withDevicesLogs: Boolean,
|
||||
withCrashLogs: Boolean,
|
||||
withKeyRequestHistory: Boolean,
|
||||
withScreenshot: Boolean,
|
||||
theBugDescription: String,
|
||||
listener: IMXBugReportListener?) {
|
||||
|
@ -207,6 +211,22 @@ class BugReporter @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
activeSessionHolder.getSafeActiveSession()
|
||||
?.takeIf { !mIsCancelled && withKeyRequestHistory }
|
||||
?.cryptoService()
|
||||
?.getGossipingEvents()
|
||||
?.let { GossipingEventsSerializer().serialize(it) }
|
||||
?.toByteArray()
|
||||
?.let { rawByteArray ->
|
||||
File(context.cacheDir.absolutePath, KEY_REQUESTS_FILENAME)
|
||||
.also {
|
||||
it.outputStream()
|
||||
.use { os -> os.write(rawByteArray) }
|
||||
}
|
||||
}
|
||||
?.let { compressFile(it) }
|
||||
?.let { gzippedFiles.add(it) }
|
||||
|
||||
var deviceId = "undefined"
|
||||
var userId = "undefined"
|
||||
var olmVersion = "undefined"
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.settings.devtools
|
||||
|
||||
import im.vector.app.core.resources.DateProvider
|
||||
import me.gujun.android.span.span
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.internal.crypto.model.event.OlmEventContent
|
||||
import org.matrix.android.sdk.internal.crypto.model.event.SecretSendEventContent
|
||||
import org.matrix.android.sdk.internal.crypto.model.rest.ForwardedRoomKeyContent
|
||||
import org.matrix.android.sdk.internal.crypto.model.rest.GossipingToDeviceObject
|
||||
import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyShareRequest
|
||||
import org.matrix.android.sdk.internal.crypto.model.rest.SecretShareRequest
|
||||
import org.threeten.bp.format.DateTimeFormatter
|
||||
|
||||
class GossipingEventsSerializer {
|
||||
private val full24DateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")
|
||||
|
||||
fun serialize(eventList: List<Event>): String {
|
||||
return buildString {
|
||||
eventList.forEach {
|
||||
val clearType = it.getClearType()
|
||||
append("[${getFormattedDate(it.ageLocalTs)}] $clearType from:${it.senderId} - ")
|
||||
when (clearType) {
|
||||
EventType.ROOM_KEY_REQUEST -> {
|
||||
val content = it.getClearContent().toModel<RoomKeyShareRequest>()
|
||||
append("reqId:${content?.requestId} action:${content?.action} ")
|
||||
if (content?.action == GossipingToDeviceObject.ACTION_SHARE_REQUEST) {
|
||||
append("sessionId: ${content.body?.sessionId} ")
|
||||
}
|
||||
append("requestedBy: ${content?.requestingDeviceId}")
|
||||
}
|
||||
EventType.FORWARDED_ROOM_KEY -> {
|
||||
val encryptedContent = it.content.toModel<OlmEventContent>()
|
||||
val content = it.getClearContent().toModel<ForwardedRoomKeyContent>()
|
||||
|
||||
append("sessionId:${content?.sessionId} From Device (sender key):${encryptedContent?.senderKey}")
|
||||
span("\nFrom Device (sender key):") {
|
||||
textStyle = "bold"
|
||||
}
|
||||
}
|
||||
EventType.ROOM_KEY -> {
|
||||
val content = it.getClearContent()
|
||||
append("sessionId:${content?.get("session_id")} roomId:${content?.get("room_id")} dest:${content?.get("_dest") ?: "me"}")
|
||||
}
|
||||
EventType.SEND_SECRET -> {
|
||||
val content = it.getClearContent().toModel<SecretSendEventContent>()
|
||||
append("requestId:${content?.requestId} From Device:${it.mxDecryptionResult?.payload?.get("sender_device")}")
|
||||
}
|
||||
EventType.REQUEST_SECRET -> {
|
||||
val content = it.getClearContent().toModel<SecretShareRequest>()
|
||||
append("reqId:${content?.requestId} action:${content?.action} ")
|
||||
if (content?.action == GossipingToDeviceObject.ACTION_SHARE_REQUEST) {
|
||||
append("secretName:${content.secretName} ")
|
||||
}
|
||||
append("requestedBy:${content?.requestingDeviceId}")
|
||||
}
|
||||
EventType.ENCRYPTED -> {
|
||||
append("Failed to Decrypt")
|
||||
}
|
||||
else -> {
|
||||
append("??")
|
||||
}
|
||||
}
|
||||
append("\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFormattedDate(ageLocalTs: Long?): String {
|
||||
return ageLocalTs
|
||||
?.let { DateProvider.toLocalDateTime(it) }
|
||||
?.let { full24DateFormatter.format(it) }
|
||||
?: "?"
|
||||
}
|
||||
}
|
|
@ -70,10 +70,6 @@ class KeyRequestViewModel @AssistedInject constructor(
|
|||
fun create(initialState: KeyRequestViewState): KeyRequestViewModel
|
||||
}
|
||||
|
||||
private val full24DateFormatter by lazy {
|
||||
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")
|
||||
}
|
||||
|
||||
companion object : MvRxViewModelFactory<KeyRequestViewModel, KeyRequestViewState> {
|
||||
|
||||
@JvmStatic
|
||||
|
@ -98,54 +94,7 @@ class KeyRequestViewModel @AssistedInject constructor(
|
|||
// this can take long
|
||||
val eventList = session.cryptoService().getGossipingEvents()
|
||||
// clean it a bit to
|
||||
val raw = buildString {
|
||||
eventList.forEach {
|
||||
val clearType = it.getClearType()
|
||||
append("[${getFormattedDate(it.ageLocalTs)}] $clearType from:${it.senderId} - ")
|
||||
when (clearType) {
|
||||
EventType.ROOM_KEY_REQUEST -> {
|
||||
val content = it.getClearContent().toModel<RoomKeyShareRequest>()
|
||||
append("reqId:${content?.requestId} action:${content?.action} ")
|
||||
if (content?.action == GossipingToDeviceObject.ACTION_SHARE_REQUEST) {
|
||||
append("sessionId: ${content.body?.sessionId} ")
|
||||
}
|
||||
append("requestedBy: ${content?.requestingDeviceId}")
|
||||
}
|
||||
EventType.FORWARDED_ROOM_KEY -> {
|
||||
val encryptedContent = it.content.toModel<OlmEventContent>()
|
||||
val content = it.getClearContent().toModel<ForwardedRoomKeyContent>()
|
||||
|
||||
append("sessionId:${content?.sessionId} From Device (sender key):${encryptedContent?.senderKey}")
|
||||
span("\nFrom Device (sender key):") {
|
||||
textStyle = "bold"
|
||||
}
|
||||
}
|
||||
EventType.ROOM_KEY -> {
|
||||
val content = it.getClearContent()
|
||||
append("sessionId:${content?.get("session_id")} roomId:${content?.get("room_id")} dest:${content?.get("_dest") ?: "me"}")
|
||||
}
|
||||
EventType.SEND_SECRET -> {
|
||||
val content = it.getClearContent().toModel<SecretSendEventContent>()
|
||||
append("requestId:${content?.requestId} From Device:${it.mxDecryptionResult?.payload?.get("sender_device")}")
|
||||
}
|
||||
EventType.REQUEST_SECRET -> {
|
||||
val content = it.getClearContent().toModel<SecretShareRequest>()
|
||||
append("reqId:${content?.requestId} action:${content?.action} ")
|
||||
if (content?.action == GossipingToDeviceObject.ACTION_SHARE_REQUEST) {
|
||||
append("secretName:${content.secretName} ")
|
||||
}
|
||||
append("requestedBy:${content?.requestingDeviceId}")
|
||||
}
|
||||
EventType.ENCRYPTED -> {
|
||||
append("Failed to Decrypt")
|
||||
}
|
||||
else -> {
|
||||
append("??")
|
||||
}
|
||||
}
|
||||
append("\n")
|
||||
}
|
||||
}
|
||||
val raw = GossipingEventsSerializer().serialize(eventList)
|
||||
setState {
|
||||
copy(exporting = Success(Unit))
|
||||
}
|
||||
|
@ -157,11 +106,4 @@ class KeyRequestViewModel @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFormattedDate(ageLocalTs: Long?): String {
|
||||
return ageLocalTs
|
||||
?.let { DateProvider.toLocalDateTime(it) }
|
||||
?.let { full24DateFormatter.format(it) }
|
||||
?: "?"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,6 +125,15 @@
|
|||
android:checked="true"
|
||||
android:text="@string/send_bug_report_include_crash_logs" />
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/bug_report_button_include_key_share_history"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:checked="false"
|
||||
android:text="@string/send_bug_report_include_key_share_history" />
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/bug_report_button_include_screenshot"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -192,6 +192,7 @@
|
|||
|
||||
<string name="send_bug_report_include_logs">Send logs</string>
|
||||
<string name="send_bug_report_include_crash_logs">Send crash logs</string>
|
||||
<string name="send_bug_report_include_key_share_history">Send key share requests history</string>
|
||||
<string name="send_bug_report_include_screenshot">Send screenshot</string>
|
||||
<string name="send_bug_report">Report bug</string>
|
||||
<string name="send_bug_report_description">Please describe the bug. What did you do? What did you expect to happen? What actually happened?</string>
|
||||
|
|
Loading…
Reference in New Issue