Skip to content

Commit

Permalink
Fix alert continuation leak when WebKit automatically cancels the req…
Browse files Browse the repository at this point in the history
…uest. Handle manual cancellation as well.
  • Loading branch information
Brandon-T committed Dec 19, 2024
1 parent 7dbdad1 commit 33b9276
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,15 @@ extension BrowserViewController: WKNavigationDelegate {
guard var requestURL = navigationAction.request.url else {
return (.cancel, preferences)
}

let tab = tab(for: webView)
if tab?.isExternalAppAlertPresented == true {
tab?.externalAppPopup?.dismissWithType(dismissType: .noAnimation)
tab?.externalAppPopupContinuation?.resume(with: .success(false))
tab?.externalAppPopupContinuation = nil
tab?.externalAppPopup = nil
}

if InternalURL.isValid(url: requestURL) {
if navigationAction.navigationType != .backForward, navigationAction.isInternalUnprivileged,
navigationAction.sourceFrame != nil || navigationAction.targetFrame?.isMainFrame == false
Expand Down Expand Up @@ -204,7 +213,6 @@ extension BrowserViewController: WKNavigationDelegate {

// First special case are some schemes that are about Calling. We prompt the user to confirm this action. This
// gives us the exact same behaviour as Safari.
let tab = tab(for: webView)

if ["sms", "tel", "facetime", "facetime-audio"].contains(requestURL.scheme) {
let shouldOpen = await handleExternalURL(
Expand Down Expand Up @@ -1264,6 +1272,8 @@ extension BrowserViewController {
titleSize: 21
)

tab?.externalAppPopup = popup

if isSuppressActive {
popup.addButton(title: Strings.suppressAlertsActionTitle, type: .destructive) {
[weak tab] () -> PopupViewDismissType in
Expand Down Expand Up @@ -1322,10 +1332,17 @@ extension BrowserViewController {

tab?.externalAppAlertCounter += 1

return await withCheckedContinuation { continuation in
showExternalSchemeAlert(isSuppressActive: tab?.externalAppAlertCounter ?? 0 > 2) {
continuation.resume(with: .success($0))
return await withTaskCancellationHandler {
return await withCheckedContinuation { [weak tab] continuation in
tab?.externalAppPopupContinuation = continuation
showExternalSchemeAlert(isSuppressActive: tab?.externalAppAlertCounter ?? 0 > 2) {
tab?.externalAppPopupContinuation = nil
continuation.resume(with: .success($0))
}
}
} onCancel: { [weak tab] in
tab?.externalAppPopupContinuation?.resume(with: .success(false))
tab?.externalAppPopupContinuation = nil
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions ios/brave-ios/Sources/Brave/Frontend/Browser/Tab.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import BraveCore
import BraveShields
import BraveUI
import BraveWallet
import CertificateUtilities
import Data
Expand Down Expand Up @@ -429,6 +430,8 @@ class Tab: NSObject {

/// Boolean tracking custom url-scheme alert presented
var isExternalAppAlertPresented = false
var externalAppPopup: AlertPopupView?
var externalAppPopupContinuation: CheckedContinuation<Bool, Never>?
var externalAppAlertCounter = 0
var isExternalAppAlertSuppressed = false
var externalAppURLDomain: String?
Expand Down

0 comments on commit 33b9276

Please sign in to comment.