From 694aa3ff89c47f0e8198e104efcff2dc370473e4 Mon Sep 17 00:00:00 2001 From: Brandon Date: Fri, 23 Feb 2024 17:01:20 -0500 Subject: [PATCH 1/2] Fix bugs with secureContentState being set in didFailProvisionalNavigation as URL is only ever updated in didCommit so there's a mismatch. This should NEVER be done. Fix external URLs not working due to inactive tab logic. Fix security certificate display showing when there's no cert at all. Remove serverPinningTrust because it can mismatch in didFailProvisionalNavigation when an AppStore URL is loaded on top of a already secure page URL, then the appstore URL assumes the cert of the page which is wrong. Apple gives us no cert on purpose so we should not store the one from chain evaluation --- .../BVC+ShareActivity.swift | 8 +- .../BVC+WKNavigationDelegate.swift | 171 ++++++------------ .../BrowserViewController.swift | 14 +- .../Browser/Helpers/ErrorPageHelper.swift | 9 +- .../CertificateErrorPageHandler.swift | 4 +- .../Sources/Brave/Frontend/Browser/Tab.swift | 1 - .../BraveCertificateUtils.swift | 7 +- 7 files changed, 77 insertions(+), 137 deletions(-) diff --git a/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+ShareActivity.swift b/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+ShareActivity.swift index 8c06ac59396f..9e66e92401cd 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+ShareActivity.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+ShareActivity.swift @@ -301,10 +301,10 @@ extension BrowserViewController { } // Display Certificate Activity - if let selectedTab = tabManager.selectedTab, - selectedTab.secureContentState != .missingSSL && selectedTab.secureContentState != .unknown - { - logSecureContentState(tab: selectedTab, details: "Display Certificate Activity Settings") + if let tabURL = tabManager.selectedTab?.webView?.url, tabManager.selectedTab?.webView?.serverTrust != nil || ErrorPageHelper.hasCertificates(for: tabURL) { + if let selectedTab = tabManager.selectedTab { + logSecureContentState(tab: selectedTab, details: "Display Certificate Activity Settings") + } activities.append( BasicMenuActivity( diff --git a/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+WKNavigationDelegate.swift b/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+WKNavigationDelegate.swift index d27fb59fa7a3..16a19d3cac55 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+WKNavigationDelegate.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+WKNavigationDelegate.swift @@ -67,24 +67,8 @@ extension BrowserViewController: WKNavigationDelegate { // check if web view is loading a different origin than the one currently loaded if let selectedTab = tabManager.selectedTab, - selectedTab.url?.origin != webView.url?.origin - { - if let url = webView.url { - if !InternalURL.isValid(url: url) { - // reset secure content state to unknown until page can be evaluated - selectedTab.sslPinningError = nil - selectedTab.sslPinningTrust = nil - selectedTab.secureContentState = .unknown - logSecureContentState( - tab: selectedTab, - details: - "DidStartProvisionalNavigation - Reset secure content state to unknown until page can be evaluated" - ) - - updateToolbarSecureContentState(.unknown) - } - } - + selectedTab.url?.origin != webView.url?.origin { + // new site has a different origin, hide wallet icon. tabManager.selectedTab?.isWalletIconVisible = false // new site, reset connected addresses @@ -746,21 +730,23 @@ extension BrowserViewController: WKNavigationDelegate { download.delegate = self } - nonisolated public func webView( - _ webView: WKWebView, - respondTo challenge: URLAuthenticationChallenge - ) async -> (URLSession.AuthChallengeDisposition, URLCredential?) { + @MainActor + public func webView(_ webView: WKWebView, respondTo challenge: URLAuthenticationChallenge) async -> (URLSession.AuthChallengeDisposition, URLCredential?) { // If this is a certificate challenge, see if the certificate has previously been // accepted by the user. let host = challenge.protectionSpace.host let origin = "\(host):\(challenge.protectionSpace.port)" if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust, - let trust = challenge.protectionSpace.serverTrust, - let cert = (SecTrustCopyCertificateChain(trust) as? [SecCertificate])?.first, - profile.certStore.containsCertificate(cert, forOrigin: origin) - { - return (.useCredential, URLCredential(trust: trust)) + let trust = challenge.protectionSpace.serverTrust { + + let cert = await Task.detached { + return (SecTrustCopyCertificateChain(trust) as? [SecCertificate])?.first + }.value + + if let cert = cert, profile.certStore.containsCertificate(cert, forOrigin: origin) { + return (.useCredential, URLCredential(trust: trust)) + } } // Certificate Pinning @@ -782,13 +768,8 @@ extension BrowserViewController: WKNavigationDelegate { if result == Int32.min { // Cert is POTENTIALLY invalid and cannot be pinned - await MainActor.run { - // Handle the potential error later in `didFailProvisionalNavigation` - self.tab(for: webView)?.sslPinningTrust = serverTrust - } - // Let WebKit handle the request and validate the cert - // This is the same as calling `BraveCertificateUtils.evaluateTrust` + // This is the same as calling `BraveCertificateUtils.evaluateTrust` but with more error info provided by WebKit return (.performDefaultHandling, nil) } @@ -796,27 +777,19 @@ extension BrowserViewController: WKNavigationDelegate { Logger.module.error("CERTIFICATE_INVALID") let errorCode = CFNetworkErrors.braveCertificatePinningFailed.rawValue - let underlyingError = NSError( - domain: kCFErrorDomainCFNetwork as String, - code: Int(errorCode), - userInfo: ["_kCFStreamErrorCodeKey": Int(errorCode)] - ) - - let error = await NSError( - domain: kCFErrorDomainCFNetwork as String, - code: Int(errorCode), - userInfo: [ - NSURLErrorFailingURLErrorKey: webView.url as Any, - "NSErrorPeerCertificateChainKey": certificateChain, - NSUnderlyingErrorKey: underlyingError, - ] - ) - - await MainActor.run { - // Handle the error later in `didFailProvisionalNavigation` - self.tab(for: webView)?.sslPinningError = error - } - + let underlyingError = NSError(domain: kCFErrorDomainCFNetwork as String, + code: Int(errorCode), + userInfo: ["_kCFStreamErrorCodeKey": Int(errorCode)]) + + let error = NSError(domain: kCFErrorDomainCFNetwork as String, + code: Int(errorCode), + userInfo: [NSURLErrorFailingURLErrorKey: webView.url as Any, + "NSErrorPeerCertificateChainKey": certificateChain, + NSUnderlyingErrorKey: underlyingError]) + + // Handle the error later in `didFailProvisionalNavigation` + self.tab(for: webView)?.sslPinningError = error + return (.cancelAuthenticationChallenge, nil) } } @@ -825,39 +798,34 @@ extension BrowserViewController: WKNavigationDelegate { let protectionSpace = challenge.protectionSpace let credential = challenge.proposedCredential let previousFailureCount = challenge.previousFailureCount - return await Task { @MainActor in - guard - protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic - || protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPDigest - || protectionSpace.authenticationMethod == NSURLAuthenticationMethodNTLM, - let tab = tab(for: webView) - else { - return (.performDefaultHandling, nil) - } - // The challenge may come from a background tab, so ensure it's the one visible. - tabManager.selectTab(tab) - - do { - let credentials = try await Authenticator.handleAuthRequest( - self, - credential: credential, - protectionSpace: protectionSpace, - previousFailureCount: previousFailureCount - ) - - if BasicAuthCredentialsManager.validDomains.contains(host) { - BasicAuthCredentialsManager.setCredential( - origin: origin, - credential: credentials.credentials - ) - } - - return (.useCredential, credentials.credentials) - } catch { - return (.rejectProtectionSpace, nil) + guard protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic || + protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPDigest || + protectionSpace.authenticationMethod == NSURLAuthenticationMethodNTLM, + let tab = tab(for: webView) + else { + return (.performDefaultHandling, nil) + } + + // The challenge may come from a background tab, so ensure it's the one visible. + tabManager.selectTab(tab) + + do { + let credentials = try await Authenticator.handleAuthRequest( + self, + credential: credential, + protectionSpace: protectionSpace, + previousFailureCount: previousFailureCount + ) + + if BasicAuthCredentialsManager.validDomains.contains(host) { + BasicAuthCredentialsManager.setCredential(origin: origin, credential: credentials.credentials) } - }.value + + return (.useCredential, credentials.credentials) + } catch { + return (.rejectProtectionSpace, nil) + } } public func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) { @@ -991,20 +959,6 @@ extension BrowserViewController: WKNavigationDelegate { ) { guard let tab = tab(for: webView) else { return } - // WebKit does not update certs on cancellation of a frame load - // So manually trigger the notification with the current cert - // Also, when Chromium cert validation passes, BUT Apple cert validation fails, the request is cancelled automatically by WebKit - // In such a case, the webView.serverTrust is `nil`. The only time we have a valid trust is when we received the challenge - // so we need to update the URL-Bar to show that serverTrust when WebKit's is nil. - logSecureContentState(tab: tab, details: "ObserveValue trigger in didFailProvisionalNavigation") - - observeValue( - forKeyPath: KVOConstants.serverTrust.keyPath, - of: webView, - change: [.newKey: webView.serverTrust ?? tab.sslPinningTrust as Any, .kindKey: 1], - context: nil - ) - // Ignore the "Frame load interrupted" error that is triggered when we cancel a request // to open an external application and hand it over to UIApplication.openURL(). The result // will be that we switch to the external app, for example the app store, while keeping the @@ -1036,23 +990,10 @@ extension BrowserViewController: WKNavigationDelegate { if let url = error.userInfo[NSURLErrorFailingURLErrorKey] as? URL { - // The certificate came from the WebKit SSL Handshake validation and the cert is untrusted - if webView.serverTrust == nil, let serverTrust = tab.sslPinningTrust, - error.userInfo["NSErrorPeerCertificateChainKey"] == nil - { - // Build a cert chain error to display in the cert viewer in such cases, as we aren't given one by WebKit - var userInfo = error.userInfo - userInfo["NSErrorPeerCertificateChainKey"] = - SecTrustCopyCertificateChain(serverTrust) as? [SecCertificate] ?? [] - userInfo["NSErrorPeerUntrustedByApple"] = true - error = NSError(domain: error.domain, code: error.code, userInfo: userInfo) + if tab == self.tabManager.selectedTab { + self.topToolbar.hideProgressBar() } - - ErrorPageHelper(certStore: profile.certStore).loadPage(error, forUrl: url, inWebView: webView) - // Submitting same errornous URL using toolbar will cause progress bar get stuck - // Reseting the progress bar in case there is an error is necessary - topToolbar.hideProgressBar() - + // If the local web server isn't working for some reason (Brave cellular data is // disabled in settings, for example), we'll fail to load the session restore URL. // We rely on loading that page to get the restore callback to reset the restoring diff --git a/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BrowserViewController.swift b/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BrowserViewController.swift index eaf3710a94a5..e4397e5719d9 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BrowserViewController.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BrowserViewController.swift @@ -2071,8 +2071,9 @@ public class BrowserViewController: UIViewController { tab.secureContentState = .unknown logSecureContentState(tab: tab, path: path) - guard let serverTrust = tab.webView?.serverTrust else { - if let url = tab.webView?.url ?? tab.url { + guard let url = webView.url, + let serverTrust = webView.serverTrust else { + if let url = webView.url { if InternalURL.isValid(url: url), let internalUrl = InternalURL(url), internalUrl.isAboutURL || internalUrl.isAboutHomeURL @@ -2165,10 +2166,9 @@ public class BrowserViewController: UIViewController { } break } - - guard let scheme = tab.webView?.url?.scheme, - let host = tab.webView?.url?.host - else { + + guard let scheme = url.scheme, + let host = url.host else { tab.secureContentState = .unknown logSecureContentState(tab: tab, path: path, details: "No webview URL host scheme)") @@ -2177,7 +2177,7 @@ public class BrowserViewController: UIViewController { } let port: Int - if let urlPort = tab.webView?.url?.port { + if let urlPort = url.port { port = urlPort } else if scheme == "https" { port = 443 diff --git a/ios/brave-ios/Sources/Brave/Frontend/Browser/Helpers/ErrorPageHelper.swift b/ios/brave-ios/Sources/Brave/Frontend/Browser/Helpers/ErrorPageHelper.swift index 977c58f775f8..a2d7c0413b6a 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Browser/Helpers/ErrorPageHelper.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Browser/Helpers/ErrorPageHelper.swift @@ -104,11 +104,6 @@ class ErrorPageHelper { URLQueryItem(name: "timestamp", value: "\(Int(Date().timeIntervalSince1970 * 1000))"), ] - // The error came from WebKit's internal validation and the cert is untrusted - if error.userInfo["NSErrorPeerUntrustedByApple"] as? Bool == true { - queryItems.append(URLQueryItem(name: "peeruntrusted", value: "true")) - } - // If this is an invalid certificate, show a certificate error allowing the // user to go back or continue. The certificate itself is encoded and added as // a query parameter to the error page URL; we then read the certificate from @@ -186,6 +181,10 @@ extension ErrorPageHelper { return 0 } + static func hasCertificates(for url: URL) -> Bool { + return (url as NSURL).valueForQueryParameter(key: "badcerts") != nil + } + static func serverTrust(from errorURL: URL) throws -> SecTrust? { guard let internalUrl = InternalURL(errorURL), internalUrl.isErrorPage, diff --git a/ios/brave-ios/Sources/Brave/Frontend/Browser/Interstitial Pages/CertificateErrorPageHandler.swift b/ios/brave-ios/Sources/Brave/Frontend/Browser/Interstitial Pages/CertificateErrorPageHandler.swift index 9a9c9833c2cf..187e479c824c 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Browser/Interstitial Pages/CertificateErrorPageHandler.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Browser/Interstitial Pages/CertificateErrorPageHandler.swift @@ -17,9 +17,7 @@ class CertificateErrorPageHandler: InterstitialPageHandler { } func response(for model: ErrorPageModel) -> (URLResponse, Data)? { - let hasCertificate = - model.components.valueForQuery("certerror") != nil - && model.components.valueForQuery("peeruntrusted") == nil + let hasCertificate = model.components.valueForQuery("certerror") != nil guard let asset = Bundle.module.path(forResource: "CertificateError", ofType: "html") else { assert(false) diff --git a/ios/brave-ios/Sources/Brave/Frontend/Browser/Tab.swift b/ios/brave-ios/Sources/Brave/Frontend/Browser/Tab.swift index 36bc7ae19819..c092fa50ffe0 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Browser/Tab.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Browser/Tab.swift @@ -103,7 +103,6 @@ class Tab: NSObject { var secureContentState: TabSecureContentState = .unknown var sslPinningError: Error? - var sslPinningTrust: SecTrust? private let _syncTab: BraveSyncTab? private let _faviconDriver: FaviconDriver? diff --git a/ios/brave-ios/Sources/CertificateUtilities/BraveCertificateUtils.swift b/ios/brave-ios/Sources/CertificateUtilities/BraveCertificateUtils.swift index 1c48cf7e7e3d..5938e48b7c55 100644 --- a/ios/brave-ios/Sources/CertificateUtilities/BraveCertificateUtils.swift +++ b/ios/brave-ios/Sources/CertificateUtilities/BraveCertificateUtils.swift @@ -220,7 +220,8 @@ extension BraveCertificateUtils { return serverTrust! } - public static func evaluateTrust(_ trust: SecTrust, for host: String?) async throws { + /// Verifies ServerTrust using Apple's APIs which validates also the X509 Certificate against the System Trusts + static func evaluateTrust(_ trust: SecTrust, for host: String?) async throws { try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) in BraveCertificateUtils.evaluationQueue.async { SecTrustEvaluateAsyncWithError(trust, BraveCertificateUtils.evaluationQueue) { @@ -241,7 +242,9 @@ extension BraveCertificateUtils { } } - public static func verifyTrust(_ trust: SecTrust, host: String, port: Int) async -> Int { + /// Verifies ServerTrust using Brave-Core which verifies only SSL Pinning Status + static func verifyTrust(_ trust: SecTrust, host: String, port: Int) async -> Int { + return Int(BraveCertificateUtility.verifyTrust(trust, host: host, port: port)) } } From 71ab49af5571c49485e2518c2b66c751b7b8ddf6 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Mon, 26 Feb 2024 10:31:51 -0500 Subject: [PATCH 2/2] Adding non animated dismiss to handle TabTray blocking external alert presantation --- .../BVC+ShareActivity.swift | 7 +- .../BVC+WKNavigationDelegate.swift | 79 ++++++++++--------- .../BrowserViewController.swift | 23 +++--- .../Browser/Helpers/ErrorPageHelper.swift | 2 +- .../Frontend/Browser/NavigationRouter.swift | 8 +- .../BraveCertificateUtils.swift | 5 +- 6 files changed, 61 insertions(+), 63 deletions(-) diff --git a/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+ShareActivity.swift b/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+ShareActivity.swift index 9e66e92401cd..645af6d3f253 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+ShareActivity.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+ShareActivity.swift @@ -301,7 +301,10 @@ extension BrowserViewController { } // Display Certificate Activity - if let tabURL = tabManager.selectedTab?.webView?.url, tabManager.selectedTab?.webView?.serverTrust != nil || ErrorPageHelper.hasCertificates(for: tabURL) { + if let tabURL = tabManager.selectedTab?.webView?.url, + tabManager.selectedTab?.webView?.serverTrust != nil + || ErrorPageHelper.hasCertificates(for: tabURL) + { if let selectedTab = tabManager.selectedTab { logSecureContentState(tab: selectedTab, details: "Display Certificate Activity Settings") } @@ -316,7 +319,7 @@ extension BrowserViewController { ) } - // Report Web-compat Issue Actibity + // Report Web-compat Issue Activity activities.append( BasicMenuActivity( title: Strings.Shields.reportABrokenSite, diff --git a/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+WKNavigationDelegate.swift b/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+WKNavigationDelegate.swift index 16a19d3cac55..615e43a5f0c2 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+WKNavigationDelegate.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+WKNavigationDelegate.swift @@ -67,8 +67,9 @@ extension BrowserViewController: WKNavigationDelegate { // check if web view is loading a different origin than the one currently loaded if let selectedTab = tabManager.selectedTab, - selectedTab.url?.origin != webView.url?.origin { - + selectedTab.url?.origin != webView.url?.origin + { + // new site has a different origin, hide wallet icon. tabManager.selectedTab?.isWalletIconVisible = false // new site, reset connected addresses @@ -730,20 +731,25 @@ extension BrowserViewController: WKNavigationDelegate { download.delegate = self } - @MainActor - public func webView(_ webView: WKWebView, respondTo challenge: URLAuthenticationChallenge) async -> (URLSession.AuthChallengeDisposition, URLCredential?) { + + public func webView( + _ webView: WKWebView, + respondTo challenge: URLAuthenticationChallenge + ) async -> (URLSession.AuthChallengeDisposition, URLCredential?) { + // If this is a certificate challenge, see if the certificate has previously been // accepted by the user. let host = challenge.protectionSpace.host let origin = "\(host):\(challenge.protectionSpace.port)" if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust, - let trust = challenge.protectionSpace.serverTrust { - + let trust = challenge.protectionSpace.serverTrust + { + let cert = await Task.detached { return (SecTrustCopyCertificateChain(trust) as? [SecCertificate])?.first }.value - + if let cert = cert, profile.certStore.containsCertificate(cert, forOrigin: origin) { return (.useCredential, URLCredential(trust: trust)) } @@ -777,19 +783,25 @@ extension BrowserViewController: WKNavigationDelegate { Logger.module.error("CERTIFICATE_INVALID") let errorCode = CFNetworkErrors.braveCertificatePinningFailed.rawValue - let underlyingError = NSError(domain: kCFErrorDomainCFNetwork as String, - code: Int(errorCode), - userInfo: ["_kCFStreamErrorCodeKey": Int(errorCode)]) - - let error = NSError(domain: kCFErrorDomainCFNetwork as String, - code: Int(errorCode), - userInfo: [NSURLErrorFailingURLErrorKey: webView.url as Any, - "NSErrorPeerCertificateChainKey": certificateChain, - NSUnderlyingErrorKey: underlyingError]) + let underlyingError = NSError( + domain: kCFErrorDomainCFNetwork as String, + code: Int(errorCode), + userInfo: ["_kCFStreamErrorCodeKey": Int(errorCode)] + ) + + let error = NSError( + domain: kCFErrorDomainCFNetwork as String, + code: Int(errorCode), + userInfo: [ + NSURLErrorFailingURLErrorKey: webView.url as Any, + "NSErrorPeerCertificateChainKey": certificateChain, + NSUnderlyingErrorKey: underlyingError, + ] + ) // Handle the error later in `didFailProvisionalNavigation` self.tab(for: webView)?.sslPinningError = error - + return (.cancelAuthenticationChallenge, nil) } } @@ -799,14 +811,15 @@ extension BrowserViewController: WKNavigationDelegate { let credential = challenge.proposedCredential let previousFailureCount = challenge.previousFailureCount - guard protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic || - protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPDigest || - protectionSpace.authenticationMethod == NSURLAuthenticationMethodNTLM, - let tab = tab(for: webView) + guard + protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic + || protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPDigest + || protectionSpace.authenticationMethod == NSURLAuthenticationMethodNTLM, + let tab = tab(for: webView) else { return (.performDefaultHandling, nil) } - + // The challenge may come from a background tab, so ensure it's the one visible. tabManager.selectTab(tab) @@ -817,11 +830,14 @@ extension BrowserViewController: WKNavigationDelegate { protectionSpace: protectionSpace, previousFailureCount: previousFailureCount ) - + if BasicAuthCredentialsManager.validDomains.contains(host) { - BasicAuthCredentialsManager.setCredential(origin: origin, credential: credentials.credentials) + BasicAuthCredentialsManager.setCredential( + origin: origin, + credential: credentials.credentials + ) } - + return (.useCredential, credentials.credentials) } catch { return (.rejectProtectionSpace, nil) @@ -993,7 +1009,7 @@ extension BrowserViewController: WKNavigationDelegate { if tab == self.tabManager.selectedTab { self.topToolbar.hideProgressBar() } - + // If the local web server isn't working for some reason (Brave cellular data is // disabled in settings, for example), we'll fail to load the session restore URL. // We rely on loading that page to get the restore callback to reset the restoring @@ -1059,16 +1075,7 @@ extension BrowserViewController { // External dialog should not be shown for non-active tabs #6687 - #7835 let isVisibleTab = tab?.isTabVisible() == true - // Check user trying to open on NTP like external link browsing - var isAboutHome = false - if let url = tab?.url { - isAboutHome = InternalURL(url)?.isAboutHomeURL == true - } - - // Finally check non-active tab - let isNonActiveTab = isAboutHome ? false : tab?.url?.host != topToolbar.currentURL?.host - - if !isVisibleTab || isNonActiveTab { + if !isVisibleTab { return false } diff --git a/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BrowserViewController.swift b/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BrowserViewController.swift index e4397e5719d9..2696edffa5e9 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BrowserViewController.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Browser/BrowserViewController/BrowserViewController.swift @@ -2072,7 +2072,8 @@ public class BrowserViewController: UIViewController { logSecureContentState(tab: tab, path: path) guard let url = webView.url, - let serverTrust = webView.serverTrust else { + let serverTrust = webView.serverTrust + else { if let url = webView.url { if InternalURL.isValid(url: url), let internalUrl = InternalURL(url), @@ -2166,9 +2167,10 @@ public class BrowserViewController: UIViewController { } break } - + guard let scheme = url.scheme, - let host = url.host else { + let host = url.host + else { tab.secureContentState = .unknown logSecureContentState(tab: tab, path: path, details: "No webview URL host scheme)") @@ -2315,15 +2317,8 @@ public class BrowserViewController: UIViewController { browser.tabManager.addTabsForURLs([url], zombie: false, isPrivate: isPrivate) } - public func switchToTabForURLOrOpen( - _ url: URL, - isPrivate: Bool = false, - isPrivileged: Bool, - isExternal: Bool = false - ) { - if !isExternal { - popToBVC() - } + public func switchToTabForURLOrOpen(_ url: URL, isPrivate: Bool = false, isPrivileged: Bool) { + popToBVC(isAnimated: false) if let tab = tabManager.getTabForURL(url, isPrivate: isPrivate) { tabManager.selectTab(tab) @@ -2461,11 +2456,11 @@ public class BrowserViewController: UIViewController { present(settingsNavigationController, animated: true) } - func popToBVC(completion: (() -> Void)? = nil) { + func popToBVC(isAnimated: Bool = true, completion: (() -> Void)? = nil) { guard let currentViewController = navigationController?.topViewController else { return } - currentViewController.dismiss(animated: true, completion: completion) + currentViewController.dismiss(animated: isAnimated, completion: completion) if currentViewController != self { _ = self.navigationController?.popViewController(animated: true) diff --git a/ios/brave-ios/Sources/Brave/Frontend/Browser/Helpers/ErrorPageHelper.swift b/ios/brave-ios/Sources/Brave/Frontend/Browser/Helpers/ErrorPageHelper.swift index a2d7c0413b6a..06ed30516702 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Browser/Helpers/ErrorPageHelper.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Browser/Helpers/ErrorPageHelper.swift @@ -184,7 +184,7 @@ extension ErrorPageHelper { static func hasCertificates(for url: URL) -> Bool { return (url as NSURL).valueForQueryParameter(key: "badcerts") != nil } - + static func serverTrust(from errorURL: URL) throws -> SecTrust? { guard let internalUrl = InternalURL(errorURL), internalUrl.isErrorPage, diff --git a/ios/brave-ios/Sources/Brave/Frontend/Browser/NavigationRouter.swift b/ios/brave-ios/Sources/Brave/Frontend/Browser/NavigationRouter.swift index 12c6e8fc9e61..dd665a777be9 100644 --- a/ios/brave-ios/Sources/Brave/Frontend/Browser/NavigationRouter.swift +++ b/ios/brave-ios/Sources/Brave/Frontend/Browser/NavigationRouter.swift @@ -91,13 +91,7 @@ public enum NavigationPath: Equatable { private static func handleURL(url: URL?, isPrivate: Bool, with bvc: BrowserViewController) { if let newURL = url { - bvc.switchToTabForURLOrOpen( - newURL, - isPrivate: isPrivate, - isPrivileged: false, - isExternal: true - ) - bvc.popToBVC() + bvc.switchToTabForURLOrOpen(newURL, isPrivate: isPrivate, isPrivileged: false) } else { bvc.openBlankNewTab(attemptLocationFieldFocus: false, isPrivate: isPrivate) } diff --git a/ios/brave-ios/Sources/CertificateUtilities/BraveCertificateUtils.swift b/ios/brave-ios/Sources/CertificateUtilities/BraveCertificateUtils.swift index 5938e48b7c55..f43677603295 100644 --- a/ios/brave-ios/Sources/CertificateUtilities/BraveCertificateUtils.swift +++ b/ios/brave-ios/Sources/CertificateUtilities/BraveCertificateUtils.swift @@ -221,7 +221,7 @@ extension BraveCertificateUtils { } /// Verifies ServerTrust using Apple's APIs which validates also the X509 Certificate against the System Trusts - static func evaluateTrust(_ trust: SecTrust, for host: String?) async throws { + public static func evaluateTrust(_ trust: SecTrust, for host: String?) async throws { try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) in BraveCertificateUtils.evaluationQueue.async { SecTrustEvaluateAsyncWithError(trust, BraveCertificateUtils.evaluationQueue) { @@ -243,8 +243,7 @@ extension BraveCertificateUtils { } /// Verifies ServerTrust using Brave-Core which verifies only SSL Pinning Status - static func verifyTrust(_ trust: SecTrust, host: String, port: Int) async -> Int { - + public static func verifyTrust(_ trust: SecTrust, host: String, port: Int) async -> Int { return Int(BraveCertificateUtility.verifyTrust(trust, host: host, port: port)) } }