Merge pull request #896 from kiwix/895-wkurlschemehandler-crash

WebKitHandler concurrency fix
This commit is contained in:
Kelson 2024-08-02 11:55:31 +02:00 committed by GitHub
commit 9f441b7c38
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 21 additions and 24 deletions

View File

@ -25,50 +25,45 @@ import WebKit
/// until WebKit behavior is changed. /// until WebKit behavior is changed.
final class KiwixURLSchemeHandler: NSObject, WKURLSchemeHandler { final class KiwixURLSchemeHandler: NSObject, WKURLSchemeHandler {
static let KiwixScheme = "kiwix" static let KiwixScheme = "kiwix"
private let inSync = InSync(label: "org.kiwix.url.scheme.sync") @MainActor private var startedTasks: [Int: Bool] = [:]
private var startedTasks: [Int: Bool] = [:]
// MARK: Life cycle // MARK: Life cycle
private func startFor(_ hashValue: Int) async { @MainActor
await withCheckedContinuation { continuation in private func startFor(_ hashValue: Int) {
inSync.execute { startedTasks[hashValue] = true
self.startedTasks[hashValue] = true
continuation.resume()
}
}
} }
@MainActor
private func isStartedFor(_ hashValue: Int) -> Bool { private func isStartedFor(_ hashValue: Int) -> Bool {
return inSync.read { startedTasks[hashValue] != nil
self.startedTasks[hashValue] != nil
}
} }
@MainActor
private func stopFor(_ hashValue: Int) { private func stopFor(_ hashValue: Int) {
inSync.execute { startedTasks.removeValue(forKey: hashValue)
self.startedTasks.removeValue(forKey: hashValue)
}
} }
@MainActor
private func stopAll() { private func stopAll() {
inSync.execute { startedTasks.removeAll()
self.startedTasks.removeAll()
}
} }
@MainActor
func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) { func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {
stopFor(urlSchemeTask.hash) stopFor(urlSchemeTask.hash)
} }
@MainActor
func didFailProvisionalNavigation() { func didFailProvisionalNavigation() {
stopAll() stopAll()
} }
@MainActor
func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) { func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
guard isStartedFor(urlSchemeTask.hash) == false else { return } guard isStartedFor(urlSchemeTask.hash) == false else { return }
Task { startFor(urlSchemeTask.hash)
await startFor(urlSchemeTask.hash) Task { @MainActor in
await handle(task: urlSchemeTask) await handle(task: urlSchemeTask)
} }
} }

View File

@ -397,10 +397,12 @@ final class BrowserViewModel: NSObject, ObservableObject,
withError error: Error withError error: Error
) { ) {
let error = error as NSError let error = error as NSError
webView.stopLoading() Task { @MainActor in
(webView.configuration webView.stopLoading()
.urlSchemeHandler(forURLScheme: KiwixURLSchemeHandler.KiwixScheme) as? KiwixURLSchemeHandler)? (webView.configuration
.didFailProvisionalNavigation() .urlSchemeHandler(forURLScheme: KiwixURLSchemeHandler.KiwixScheme) as? KiwixURLSchemeHandler)?
.didFailProvisionalNavigation()
}
guard error.code != NSURLErrorCancelled else { return } guard error.code != NSURLErrorCancelled else { return }
guard canShowMimeType else { guard canShowMimeType else {
guard let kiwixURL = error.userInfo[NSURLErrorFailingURLErrorKey] as? URL else { guard let kiwixURL = error.userInfo[NSURLErrorFailingURLErrorKey] as? URL else {