To avoid using file URLs, I'm using the WKURLSchemeHandler to create a custom url to load my assets into a webview.
This works great, except that certain ways of loading assets from the custom URL results in the error:
Failed to load resource: Origin null is not allowed by Access-Control-Allow-Origin. Loading an asset in an image tag, css background property, or using a javascript import works. But using css mask, or javascript fetch does not.
You can see the problem by right-clicking in the window, and clicking show developer tools.
Css masks are used widely throughout the content in my webview, and I'm also using fetch. So I need both of these to work.
What is causing this error? Why does it only happen when using certain methods of loading resources?
import SwiftUI
import WebKit
struct ContentView: View {
var body: some View {
HTMLView().frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
struct HTMLView: NSViewRepresentable {
func makeNSView(context: Context) -> WKWebView {
/* Create the custom url handler and webview */
let config = WKWebViewConfiguration()
config.setURLSchemeHandler(CustomURLHandler(), forURLScheme: "asset")
let webview = WKWebView(frame: .zero, configuration: config)
/* Enable developer tools so we can right click and show the inspector */
webview.configuration.preferences.setValue(true, forKey: "developerExtrasEnabled")
/* Example html that does and doesn't work: */
let html = """
<style>
#box {
width: 100px;
height: 100px;
border: 1px solid green;
/* This works: */
background: url(asset://test.svg);
}
#box2 {
width: 100px;
height: 100px;
border: 1px solid red;
background: blue;
/* This does not work: */
-webkit-mask-image: url(asset://test.svg);
}
</style>
<p>This box loads the asset using the background property:</p>
<div id="box"></div>
<p>This box results in the error, and doesn't show the image with the css mask:</p>
<div id="box2"></div>
<script>
// Using javascript fetch also doesn't work:
fetch('asset://test.svg')
.then(data => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
</script>
"""
webview.loadHTMLString(html, baseURL: nil)
return webview
}
func updateNSView(_ nsView: WKWebView, context: Context) {}
}
class CustomURLHandler: NSObject, WKURLSchemeHandler {
func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
guard let url = urlSchemeTask.request.url else {
return
}
/* Handle the custom url assets here. In this example I'm just returning a test svg: */
let testImage = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"><svg width=\"100%\" height=\"100%\" viewBox=\"0 0 19 18\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xml:space=\"preserve\" xmlns:serif=\"http://www.serif.com/\" style=\"fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;\"><g transform=\"matrix(1,0,0,1,-540,-709.618)\"><g transform=\"matrix(0.5,0,0,0.666667,467,536)\"><g transform=\"matrix(2,0,0,1.5,-934,-804)\"><path d=\"M549,712.6C550.895,709 554.684,709 556.579,710.8C558.474,712.6 558.474,716.2 556.579,719.8C555.253,722.5 551.842,725.2 549,727C546.158,725.2 542.747,722.5 541.421,719.8C539.526,716.2 539.526,712.6 541.421,710.8C543.316,709 547.105,709 549,712.6Z\" style=\"fill:rgb(255,0,0);\"/></g></g></g></svg>"
guard let data = testImage.data(using: .utf8) else { return }
let urlResponse = URLResponse(url: url, mimeType: "image/svg+xml", expectedContentLength: data.count, textEncodingName: nil)
urlSchemeTask.didReceive(urlResponse)
urlSchemeTask.didReceive(data)
urlSchemeTask.didFinish()
}
func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {}
}