2
0
mirror of https://github.com/fork-maintainers/iceraven-browser synced 2024-11-15 18:12:54 +00:00

Bug 1810044 1810045 - Delay reading clipboard and allow to paste non url

This commit is contained in:
Timshel 2023-09-28 17:44:31 +02:00 committed by mergify[bot]
parent 5a06549a3b
commit 06fb70e5db
2 changed files with 38 additions and 24 deletions

View File

@ -39,10 +39,7 @@ class ClipboardHandler(val context: Context) {
if (clipboard.isPrimaryClipEmpty()) {
return null
}
if (clipboard.isPrimaryClipPlainText() ||
clipboard.isPrimaryClipHtmlText() ||
clipboard.isPrimaryClipUrlText()
) {
if (containsText()) {
return firstSafePrimaryClipItemText
}
return null
@ -101,6 +98,16 @@ class ClipboardHandler(val context: Context) {
}
}
/**
* Returns whether or not the clipboard data contains text.
* We cannot rely on `isPrimaryClipEmpty()` since it triggers a clipboard access system notification.
*/
fun containsText(): Boolean {
return clipboard.isPrimaryClipHtmlText() ||
clipboard.isPrimaryClipPlainText() ||
clipboard.isPrimaryClipUrlText()
}
@Suppress("MagicNumber")
internal fun containsURL(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
@ -127,6 +134,13 @@ class ClipboardHandler(val context: Context) {
private fun ClipboardManager.isPrimaryClipUrlText() =
primaryClipDescription?.hasMimeType(MIME_TYPE_TEXT_URL) ?: false
/**
* Returns whether or not the clipboard has any clip data.
* Reads the clip data, be aware this is a sensitive API as from Android 12 and above,
* accessing it will trigger a notification letting the user know the app has accessed the clipboard,
* make sure when you call this API that users are completely aware that we are accessing the clipboard.
* See https://github.com/mozilla-mobile/fenix/issues/22271 for more details.
*/
private fun ClipboardManager.isPrimaryClipEmpty() = primaryClip?.itemCount == 0
/**

View File

@ -26,6 +26,10 @@ import org.mozilla.fenix.databinding.BrowserToolbarPopupWindowBinding
import org.mozilla.fenix.ext.components
import java.lang.ref.WeakReference
/**
* Since Android 12 reading the clipboard triggers an OS notification.
* As such it is important that we do not read it prematurely and only when the user trigger a paste action.
*/
object ToolbarPopupWindow {
fun show(
view: WeakReference<View>,
@ -35,12 +39,13 @@ object ToolbarPopupWindow {
copyVisible: Boolean = true,
) {
val context = view.get()?.context ?: return
val clipboard = context.components.clipboardHandler
val clipboardUrl = clipboard.getUrl()
val clipboardText = clipboard.text
if (!copyVisible && clipboardUrl == null) return
val isCustomTabSession = customTabId != null
val clipboard = context.components.clipboardHandler
val containsText = clipboard.containsText()
val containsUrl = clipboard.containsURL()
val pasteDeactivated = isCustomTabSession || (!containsText && !containsUrl)
if (!copyVisible && pasteDeactivated) return
val binding = BrowserToolbarPopupWindowBinding.inflate(LayoutInflater.from(context))
val popupWindow = PopupWindow(
@ -57,9 +62,8 @@ object ToolbarPopupWindow {
popupWindow.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
binding.copy.isVisible = copyVisible
binding.paste.isVisible = clipboardText != null && !isCustomTabSession
binding.pasteAndGo.isVisible = clipboardUrl != null && !isCustomTabSession
binding.paste.isVisible = containsText && !isCustomTabSession
binding.pasteAndGo.isVisible = containsUrl && !isCustomTabSession
if (copyVisible) {
binding.copy.setOnClickListener { copyView ->
@ -82,17 +86,21 @@ object ToolbarPopupWindow {
}
}
clipboardText?.let { text ->
if (binding.paste.isVisible) {
binding.paste.setOnClickListener {
popupWindow.dismiss()
handlePaste(text)
handlePaste(clipboard.text.orEmpty())
}
}
clipboardUrl?.let { url ->
if (binding.pasteAndGo.isVisible) {
binding.pasteAndGo.setOnClickListener {
popupWindow.dismiss()
handlePasteAndGo(url)
clipboard.extractURL()?.also {
handlePasteAndGo(it)
} ?: run {
Logger("ToolbarPopupWindow").error("Clipboard contains URL but unable to read text")
}
}
}
@ -119,12 +127,4 @@ object ToolbarPopupWindow {
selectedTab?.readerState?.activeUrl ?: selectedTab?.content?.url
}
}
private fun ClipboardHandler.getUrl(): String? {
if (containsURL()) {
text?.let { return it }
Logger("ToolbarPopupWindow").error("Clipboard contains URL but unable to read text")
}
return null
}
}