spiegel-keyman/ios/engine/KMEI/KeymanEngine/Classes/Keyboard/WebViewSchemeHandler.swift
Joshua Horton fa435cbeae
docs(ios): change file header date format
Co-authored-by: Marc Durdin <marc@durdin.net>
2026-06-29 22:21:58 +07:00

95 lines
2.7 KiB
Swift

/*
* Keyman is copyright (C) SIL Global. MIT License.
*
* Created by Joshua Horton on 2026-06-24.
*
* WebViewKeyboardLoader implements a URLSchemeHandler that allows
* the hosted Keyman Engine for Web to access all files, consistently,
* via a http-like protocol, preventing CORS access issues for files
* loaded dynamically.
*/
import WebKit
import UniformTypeIdentifiers
import os.log
func getMimeType(forExtension ext: String) -> String {
// Find the UTType associated with the file extension
if let utType = UTType(filenameExtension: ext) {
// Return the preferred MIME type if it exists
return utType.preferredMIMEType ?? "application/octet-stream"
}
return "application/octet-stream"
}
class WebViewSchemeHandler: NSObject, WKURLSchemeHandler {
let storage: Storage
let scheme = "keyman-engine"
init(storage: Storage) {
self.storage = storage
}
func webView(_ webView: WKWebView, start urlSchemeTask: any WKURLSchemeTask) {
guard let url = urlSchemeTask.request.url else {
return
}
var components = URLComponents(url: url, resolvingAgainstBaseURL: false)!
components.scheme = "file"
let fileUrl = components.url
let doError = { () -> Void in
let message = "Could not load url via WKURLSchemeHandler: \(url)"
let errorInfo = [
NSLocalizedDescriptionKey: message
]
let error = NSError(domain: "WebViewKeyboardLoader", code: 500, userInfo: errorInfo)
os_log("%{public}s", log:KeymanEngineLogger.settings, type: .error, message)
SentryManager.capture(error, message: message)
urlSchemeTask.didFailWithError(error)
}
guard fileUrl != nil else {
doError()
return
}
do {
let fileContents = try Data(contentsOf: fileUrl!)
let fileExtension = fileUrl!.pathExtension
let mimeType: String = getMimeType(forExtension: fileExtension)
let charset: String = mimeType.hasPrefix("text/") ? "; charset=utf-8" : ""
let response = HTTPURLResponse(
url: url,
statusCode: 200,
httpVersion: "HTTP/1.1",
headerFields: [
"Content-Type": "\(mimeType)\(charset)",
]
)!
urlSchemeTask.didReceive(response)
urlSchemeTask.didReceive(fileContents)
urlSchemeTask.didFinish()
} catch {
doError()
return
}
}
func webView(_ webView: WKWebView, stop urlSchemeTask: any WKURLSchemeTask) {
}
func buildUrlForFile(fileURL: URL) -> URL {
var loadingURLBuilder = URLComponents()
loadingURLBuilder.scheme = scheme
loadingURLBuilder.path = fileURL.path
return loadingURLBuilder.url!
}
}