[#477] Hiding sensitive clipboard information

* [#477] Hiding sensitive clipboard information

Closes #477

* [#477] Hiding sensitive clipboard information from api <33

Closes #477

* [#477] Code cleanup

Closes #477

* Changelog update

---------

Co-authored-by: Honza <rychnovsky.honza@gmail.com>
This commit is contained in:
Milan 2024-07-19 15:34:42 +02:00 committed by GitHub
parent a503091ab2
commit f862a4be97
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 33 additions and 24 deletions

View File

@ -10,6 +10,9 @@ and this application adheres to [Semantic Versioning](https://semver.org/spec/v2
- A new What's New screen has been added, accessible from the About screen. It contains the release notes parsed - A new What's New screen has been added, accessible from the About screen. It contains the release notes parsed
from the new [docs/whatsNew/WHATS_NEW_EN.md] file from the new [docs/whatsNew/WHATS_NEW_EN.md] file
- These release notes and release priority are both propagated to every new Google Play release using CI logic - These release notes and release priority are both propagated to every new Google Play release using CI logic
- Copying sensitive information like addresses, transaction IDs, or wallet secrets into the device clipboard is now
masked out from the system visual confirmation, but it's still copied as expected. `ClipDescription.EXTRA_IS_SENSITIVE`
flag is used on Android SDK level 33 and higher, masking out the `Toast` text on levels below it.
### Changed ### Changed
- The About screen has been redesigned to align with the new design guidelines - The About screen has been redesigned to align with the new design guidelines

View File

@ -11,6 +11,8 @@ directly impact users rather than highlighting other key architectural updates.*
### Added ### Added
- A new What's New screen has been added, accessible from the About screen - A new What's New screen has been added, accessible from the About screen
- Copying sensitive information like addresses, transaction IDs, or wallet secrets into the device clipboard is now
masked out from the system visual confirmation, but it's still copied as expected.
### Changed ### Changed
- The About screen has been redesigned to align with the new design guidelines - The About screen has been redesigned to align with the new design guidelines

View File

@ -1,13 +0,0 @@
@file:Suppress("ktlint:standard:filename")
package co.electriccoin.zcash.spackle
import android.content.ClipData
import android.content.ClipboardManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
suspend fun ClipboardManager.setPrimaryClipSuspend(data: ClipData) =
withContext(Dispatchers.IO) {
setPrimaryClip(data)
}

View File

@ -1,35 +1,46 @@
package co.electriccoin.zcash.spackle package co.electriccoin.zcash.spackle
import android.content.ClipData import android.content.ClipData
import android.content.ClipDescription
import android.content.ClipboardManager import android.content.ClipboardManager
import android.content.Context import android.content.Context
import android.os.PersistableBundle
import android.widget.Toast import android.widget.Toast
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
object ClipboardManagerUtil { object ClipboardManagerUtil {
private val extraIsSensitive: String
get() =
if (AndroidApiVersion.isAtLeastT) {
ClipDescription.EXTRA_IS_SENSITIVE
} else {
"android.content.extra.IS_SENSITIVE"
}
fun copyToClipboard( fun copyToClipboard(
context: Context, context: Context,
label: String, label: String,
value: String value: String
) { ) {
Twig.info { "Copied to clipboard: label: $label, value: $value" } Twig.info { "Copied to clipboard: label: $label, value: $value" }
val clipboardManager = context.getSystemService(ClipboardManager::class.java) val clipboardManager = context.getSystemService<ClipboardManager>()
val data = val data =
ClipData.newPlainText( ClipData.newPlainText(label, value).apply {
label, description.extras =
value PersistableBundle().apply {
) putBoolean(extraIsSensitive, true)
}
}
if (AndroidApiVersion.isAtLeastT) { if (AndroidApiVersion.isAtLeastT) {
// API 33 and later implement their system Toast UI. // API 33 and later implement their system Toast UI.
clipboardManager.setPrimaryClip(data) clipboardManager.setPrimaryClip(data)
} else { } else {
// Blocking call is fine here, as we just moved to the IO thread to satisfy theStrictMode on an older API // Blocking call is fine here, as we just moved to the IO thread to satisfy theStrictMode on an older API
runBlocking { clipboardManager.setPrimaryClipSuspend(data) } runBlocking(Dispatchers.IO) {
Toast.makeText( clipboardManager.setPrimaryClip(data)
context, }
value, Toast.makeText(context, context.getString(R.string.hide_clipboard_placeholder), Toast.LENGTH_SHORT).show()
Toast.LENGTH_SHORT
).show()
} }
} }
} }

View File

@ -20,3 +20,5 @@ suspend fun Context.getInternalCacheDirSuspend(subDirectory: String?): File =
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
(subDirectory?.let { File(cacheDir, subDirectory) } ?: cacheDir).apply { mkdirsSuspend() } (subDirectory?.let { File(cacheDir, subDirectory) } ?: cacheDir).apply { mkdirsSuspend() }
} }
inline fun <reified T> Context.getSystemService(): T = getSystemService(T::class.java)

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hide_clipboard_placeholder" translatable="false">******</string>
</resources>