From 424d8e0f45ee0f72f5cb4ebbe2d3c1e79e15c6e1 Mon Sep 17 00:00:00 2001 From: Kyle Hickinson Date: Mon, 13 Jan 2025 15:24:44 -0500 Subject: [PATCH] [iOS] Don't read pasteboard for text when evaluating search suggestions This change alters how we determine if some text was inserted by pasting contents from the pasteboard for users using keyboards that assemble words/characters using multiple key inputs. --- .../BVC+ToolbarDelegate.swift | 5 ++++- .../Toolbars/UrlBar/TopToolbarView.swift | 4 ++++ .../Widgets/AutocompleteTextField.swift | 10 +++++++++ .../Sources/Brave/Helpers/URLBarHelper.swift | 22 +++---------------- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+ToolbarDelegate.swift b/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+ToolbarDelegate.swift index 90e1152a0a6f..7da420fdd992 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+ToolbarDelegate.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+ToolbarDelegate.swift @@ -221,11 +221,14 @@ extension BrowserViewController: TopToolbarDelegate { } else { showSearchController() + let locationLastReplacement = topToolbar.locationLastReplacement + let isPasting = topToolbar.isPastingInURLBar Task { await searchController?.setSearchQuery( query: text, showSearchSuggestions: URLBarHelper.shared.shouldShowSearchSuggestions( - using: topToolbar.locationLastReplacement + using: locationLastReplacement, + isPasting: isPasting ) ) } diff --git a/ios/brave-ios/Sources/Brave/Frontend/Browser/Toolbars/UrlBar/TopToolbarView.swift b/ios/brave-ios/Sources/Brave/Frontend/Browser/Toolbars/UrlBar/TopToolbarView.swift index 27cef7af3b29..fdbecdd4a131 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Browser/Toolbars/UrlBar/TopToolbarView.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Browser/Toolbars/UrlBar/TopToolbarView.swift @@ -119,6 +119,10 @@ class TopToolbarView: UIView, ToolbarProtocol { locationTextField?.lastReplacement ?? "" } + var isPastingInURLBar: Bool { + locationTextField?.isPasting ?? false + } + // MARK: Views private var locationTextField: AutocompleteTextField? diff --git a/ios/brave-ios/Sources/Brave/Frontend/Widgets/AutocompleteTextField.swift b/ios/brave-ios/Sources/Brave/Frontend/Widgets/AutocompleteTextField.swift index 9e7d6aae0a43..f7d7d860fbcb 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Widgets/AutocompleteTextField.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Widgets/AutocompleteTextField.swift @@ -92,6 +92,9 @@ public class AutocompleteTextField: UITextField, UITextFieldDelegate { self, didEnterText: self.text?.preferredSearchSuggestionText ?? "" ) + if self.isPasting { + self.isPasting = false + } } } ) @@ -217,6 +220,13 @@ public class AutocompleteTextField: UITextField, UITextFieldDelegate { return hasActiveCompletion } + private(set) var isPasting: Bool = false + + public override func paste(_ sender: Any?) { + isPasting = true + super.paste(sender) + } + // `shouldChangeCharactersInRange` is called before the text changes, and textDidChange is called after. // Since the text has changed, remove the completion here, and textDidChange will fire the callback to // get the new autocompletion. diff --git a/ios/brave-ios/Sources/Brave/Helpers/URLBarHelper.swift b/ios/brave-ios/Sources/Brave/Helpers/URLBarHelper.swift index 3ad37cbda348..85d8104993a2 100644 --- a/ios/brave-ios/Sources/Brave/Helpers/URLBarHelper.swift +++ b/ios/brave-ios/Sources/Brave/Helpers/URLBarHelper.swift @@ -10,27 +10,11 @@ class URLBarHelper { static let shared = URLBarHelper() - func shouldShowSearchSuggestions(using lastReplacement: String) async -> Bool { - // Check if last entry to url textfield needs to be checked as suspicious. - // The reason of checking count is bigger than 1 is the single character - // entries will always be safe and only way to achieve multi character entry is - // using paste board. - // This check also allow us to handle paste permission case - guard lastReplacement.count > 1 else { - return true - } - - // Check if paste board has any text to guarantee the case - guard UIPasteboard.general.hasStrings || UIPasteboard.general.hasURLs else { - return true - } - - // Perform check on pasted text - if let pasteboardContents = UIPasteboard.general.string { - let isSuspicious = await isSuspiciousQuery(pasteboardContents) + func shouldShowSearchSuggestions(using lastReplacement: String, isPasting: Bool) async -> Bool { + if isPasting { + let isSuspicious = await isSuspiciousQuery(lastReplacement) return !isSuspicious } - return true }