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:
parent
5a06549a3b
commit
06fb70e5db
@ -39,10 +39,7 @@ class ClipboardHandler(val context: Context) {
|
|||||||
if (clipboard.isPrimaryClipEmpty()) {
|
if (clipboard.isPrimaryClipEmpty()) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
if (clipboard.isPrimaryClipPlainText() ||
|
if (containsText()) {
|
||||||
clipboard.isPrimaryClipHtmlText() ||
|
|
||||||
clipboard.isPrimaryClipUrlText()
|
|
||||||
) {
|
|
||||||
return firstSafePrimaryClipItemText
|
return firstSafePrimaryClipItemText
|
||||||
}
|
}
|
||||||
return null
|
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")
|
@Suppress("MagicNumber")
|
||||||
internal fun containsURL(): Boolean {
|
internal fun containsURL(): Boolean {
|
||||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
@ -127,6 +134,13 @@ class ClipboardHandler(val context: Context) {
|
|||||||
private fun ClipboardManager.isPrimaryClipUrlText() =
|
private fun ClipboardManager.isPrimaryClipUrlText() =
|
||||||
primaryClipDescription?.hasMimeType(MIME_TYPE_TEXT_URL) ?: false
|
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
|
private fun ClipboardManager.isPrimaryClipEmpty() = primaryClip?.itemCount == 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,6 +26,10 @@ import org.mozilla.fenix.databinding.BrowserToolbarPopupWindowBinding
|
|||||||
import org.mozilla.fenix.ext.components
|
import org.mozilla.fenix.ext.components
|
||||||
import java.lang.ref.WeakReference
|
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 {
|
object ToolbarPopupWindow {
|
||||||
fun show(
|
fun show(
|
||||||
view: WeakReference<View>,
|
view: WeakReference<View>,
|
||||||
@ -35,12 +39,13 @@ object ToolbarPopupWindow {
|
|||||||
copyVisible: Boolean = true,
|
copyVisible: Boolean = true,
|
||||||
) {
|
) {
|
||||||
val context = view.get()?.context ?: return
|
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 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 binding = BrowserToolbarPopupWindowBinding.inflate(LayoutInflater.from(context))
|
||||||
val popupWindow = PopupWindow(
|
val popupWindow = PopupWindow(
|
||||||
@ -57,9 +62,8 @@ object ToolbarPopupWindow {
|
|||||||
popupWindow.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
popupWindow.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||||
|
|
||||||
binding.copy.isVisible = copyVisible
|
binding.copy.isVisible = copyVisible
|
||||||
|
binding.paste.isVisible = containsText && !isCustomTabSession
|
||||||
binding.paste.isVisible = clipboardText != null && !isCustomTabSession
|
binding.pasteAndGo.isVisible = containsUrl && !isCustomTabSession
|
||||||
binding.pasteAndGo.isVisible = clipboardUrl != null && !isCustomTabSession
|
|
||||||
|
|
||||||
if (copyVisible) {
|
if (copyVisible) {
|
||||||
binding.copy.setOnClickListener { copyView ->
|
binding.copy.setOnClickListener { copyView ->
|
||||||
@ -82,17 +86,21 @@ object ToolbarPopupWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clipboardText?.let { text ->
|
if (binding.paste.isVisible) {
|
||||||
binding.paste.setOnClickListener {
|
binding.paste.setOnClickListener {
|
||||||
popupWindow.dismiss()
|
popupWindow.dismiss()
|
||||||
handlePaste(text)
|
handlePaste(clipboard.text.orEmpty())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clipboardUrl?.let { url ->
|
if (binding.pasteAndGo.isVisible) {
|
||||||
binding.pasteAndGo.setOnClickListener {
|
binding.pasteAndGo.setOnClickListener {
|
||||||
popupWindow.dismiss()
|
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
|
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user