Fix: Developer logs feature on older phones.
This also happens to address the security finding in issue #121 by putting logs directly into a file rather than scraping them from the device logs.
This commit is contained in:
parent
a0316ede08
commit
0039db8602
|
@ -10,6 +10,7 @@ import cash.z.ecc.android.lockbox.LockBox
|
|||
import cash.z.ecc.android.sdk.ext.SilentTwig
|
||||
import cash.z.ecc.android.sdk.ext.TroubleshootingTwig
|
||||
import cash.z.ecc.android.sdk.ext.Twig
|
||||
import cash.z.ecc.android.ui.util.DebugFileTwig
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.multibindings.IntoSet
|
||||
|
@ -53,7 +54,7 @@ class AppModule {
|
|||
): FeedbackCoordinator {
|
||||
return prefs.getBoolean(Const.Pref.FEEDBACK_ENABLED).let { isEnabled ->
|
||||
// observe nothing unless feedback is enabled
|
||||
Twig.plant(if (isEnabled) TroubleshootingTwig() else SilentTwig())
|
||||
Twig.plant(if (isEnabled) DebugFileTwig() else SilentTwig())
|
||||
FeedbackCoordinator(feedback, if (isEnabled) defaultObservers else setOf())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@ package cash.z.ecc.android.ext
|
|||
import android.content.Context
|
||||
import android.os.Build
|
||||
import androidx.fragment.app.Fragment
|
||||
import cash.z.ecc.android.sdk.ext.Bush
|
||||
import cash.z.ecc.android.sdk.ext.CompositeTwig
|
||||
import cash.z.ecc.android.sdk.ext.Twig
|
||||
import cash.z.ecc.android.sdk.ext.twig
|
||||
import java.util.*
|
||||
|
||||
|
@ -26,4 +29,10 @@ inline fun Context.locale(): Locale {
|
|||
//noinspection deprecation
|
||||
resources.configuration.locale
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add this to the SDK and if the trunk is a CompositeTwig, search through there before returning null
|
||||
inline fun <reified T> Twig.find(): T? {
|
||||
return if (Bush.trunk::class.java.isAssignableFrom(T::class.java)) Bush.trunk as T
|
||||
else null
|
||||
}
|
|
@ -11,6 +11,7 @@ import cash.z.ecc.android.R
|
|||
import cash.z.ecc.android.ZcashWalletApp
|
||||
import cash.z.ecc.android.databinding.FragmentProfileBinding
|
||||
import cash.z.ecc.android.di.viewmodel.viewModel
|
||||
import cash.z.ecc.android.ext.find
|
||||
import cash.z.ecc.android.ext.onClick
|
||||
import cash.z.ecc.android.ext.onClickNavBack
|
||||
import cash.z.ecc.android.ext.onClickNavTo
|
||||
|
@ -18,14 +19,12 @@ import cash.z.ecc.android.feedback.FeedbackFile
|
|||
import cash.z.ecc.android.feedback.Report
|
||||
import cash.z.ecc.android.feedback.Report.Funnel.UserFeedback
|
||||
import cash.z.ecc.android.feedback.Report.Tap.*
|
||||
import cash.z.ecc.android.ui.base.BaseFragment
|
||||
import cash.z.ecc.android.sdk.ext.Bush
|
||||
import cash.z.ecc.android.sdk.ext.toAbbreviatedAddress
|
||||
import cash.z.ecc.android.sdk.ext.twig
|
||||
import cash.z.ecc.android.ui.base.BaseFragment
|
||||
import cash.z.ecc.android.ui.util.DebugFileTwig
|
||||
import kotlinx.coroutines.launch
|
||||
import okio.Okio
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.lang.IllegalArgumentException
|
||||
|
||||
|
||||
class ProfileFragment : BaseFragment<FragmentProfileBinding>() {
|
||||
|
@ -70,7 +69,13 @@ class ProfileFragment : BaseFragment<FragmentProfileBinding>() {
|
|||
}
|
||||
|
||||
private fun onViewDevLogs() {
|
||||
shareFile(writeLogcat())
|
||||
developerLogFile().let {
|
||||
if (it == null) {
|
||||
mainActivity?.showSnackbar("Error: No developer log found!")
|
||||
} else {
|
||||
shareFile(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun shareFiles(vararg files: File?) {
|
||||
|
@ -102,29 +107,7 @@ class ProfileFragment : BaseFragment<FragmentProfileBinding>() {
|
|||
return mainActivity?.feedbackCoordinator?.findObserver<FeedbackFile>()?.file
|
||||
}
|
||||
|
||||
private fun loadLogFileAsText(): String? {
|
||||
val feedbackFile: File = userLogFile() ?: return null
|
||||
Okio.buffer(Okio.source(feedbackFile)).use {
|
||||
return it.readUtf8()
|
||||
}
|
||||
}
|
||||
|
||||
private fun writeLogcat(): File? {
|
||||
try {
|
||||
// Note: the /logs directory has been configured as a file provider under @xml/file_paths which allows the temporary sharing of this file
|
||||
val outputFile = File("${ZcashWalletApp.instance.filesDir}/logs", "developer_log.txt").also { it.parentFile.mkdirs() }
|
||||
if (!outputFile.parentFile.isDirectory) {
|
||||
// addresses security finding in issue #121
|
||||
throw IllegalArgumentException("Invalid path: ${outputFile.parentFile}. Verify" +
|
||||
" that the default files directory is not being manipulated.")
|
||||
}
|
||||
val cmd = arrayOf("/bin/sh", "-c", "logcat -v time -d | grep '@TWIG' > '${outputFile.absolutePath}'")
|
||||
Runtime.getRuntime().exec(cmd)
|
||||
return outputFile
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
twig("Failed to create log")
|
||||
}
|
||||
return null
|
||||
private fun developerLogFile(): File? {
|
||||
return Bush.trunk.find<DebugFileTwig>()?.file
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package cash.z.ecc.android.ui.util
|
||||
|
||||
import cash.z.ecc.android.ZcashWalletApp
|
||||
import cash.z.ecc.android.sdk.ext.TroubleshootingTwig
|
||||
import okio.Okio
|
||||
import java.io.File
|
||||
|
||||
class DebugFileTwig(fileName: String = "developer_log.txt") : TroubleshootingTwig() {
|
||||
val file = File("${ZcashWalletApp.instance.filesDir}/logs", fileName)
|
||||
|
||||
override fun twig(logMessage: String) {
|
||||
super.twig(logMessage)
|
||||
appendToFile(formatter(logMessage))
|
||||
}
|
||||
|
||||
private fun appendToFile(message: String) {
|
||||
Okio.buffer(Okio.appendingSink(file)).use {
|
||||
it.writeUtf8("$message\n")
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue