Errors reported by content of WKWebView (via window.onerror) are censored to "Script error.""

Script error.

We've decided to implement certain highly-dynamic content in out iOS codebase using web technologies, here's what we're doing:

  • We download a zip file containing html, javascript, and images.
  • We unzip the archive, construct a WKWebView, and load the content using webView.loadFileURL(indexHtmlUrl, allowingReadAccessTo: parentDirectory)

This works fine, but we'd also like to be notified on any rendering errors that might be raised, so we can fix them.

let errorHandlerScriptString = """
        
            (function() {
                var oldLog = console.log;
                console.log = function(message) {
                    window.webkit.messageHandlers.consoleLog.postMessage(message);
                    oldLog.apply(console, arguments);
                }
            })();
        
            // don't even allow asking for location permissions
            navigator.geolocation.getCurrentPosition = function(success, error, options) {
                error({
                    PERMISSION_DENIED: 1,
                    code: 1
                });
            };
        
            window.onerror = (msg, url, line, column, error) => {
              const message = {
                message: msg,
                url: url,
                line: line,
                column: column,
                error: JSON.stringify(error)
              }
              if (window.webkit) {
                window.webkit.messageHandlers.error.postMessage(message);
              } else {
                console.log("Error:", message);
              }
            };
        """

let errorHandlerScript = WKUserScript(source: errorHandlerScriptString, injectionTime: .atDocumentStart, forMainFrameOnly: false)

webView.configuration.userContentController.addUserScript(templateParamsScript)

This causes the error messages to be censored to just "Script error." - See here for more reference https://stackoverflow.com/questions/50229935/wkwebview-get-javascript-errors

This seems to be a security measure to prevent scripts with a different origin from reading error messages. I've tried to move the javascript that hooks to window.onerror to a file that's loaded in the header of the html, as well as putting it directly at the beginning of the <body> tag. Same results, still censored.

There's recommendations to load the html using webView.loadHTMLString(html, baseURL: URL(string: "http://localhost/")!), but my understanding is that than there is not way to access a local resource, such as an image that was downloaded together with the html?

I'd use WKURLSchemeHandler to load the assets via a url scheme to make sure everything loads correctly.

Loading:

            if let resource = Bundle.main.url(forResource: "image", withExtension: "png"),
               let resourceData = try? Data(contentsOf: resource) {
                data = resourceData
                response = URLResponse(
                    url: url,
                    mimeType: "image/png",
                    expectedContentLength: data!.count,
                    textEncodingName: nil)
            }

WKWebView setup:

        config.setURLSchemeHandler(LocalLoaderCustomSchemeHandler(), forURLScheme: scheme)
        let webView = WKWebView(frame: view.frame, configuration: config)
        webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.addSubview(webView)
        webView.load(URLRequest(url: URL(string: scheme + ":\(LocalObjectType.html)" )!))

Example HTML:

    <link rel="stylesheet" href="apple-localloader:css">
</head>
<body>
    <h1>Your content is all here </h1>
    <br>
    <img src="apple-localloader:png"/>
    <br>
    <img src="apple-localloader:https"/>
    <br>
    <embed src="apple-localloader:pdf" type="application/pdf"/>
    <br>
    <br>
    <h2 id="date">Date</h2>
    <img id="https"/>
    <script src="apple-localloader:javascript"></script>
</body>
</html>

Rico


WWDR | DTS | Software Engineer

Would using webView.load(URLRequest(url: URL(string: scheme + ":\(LocalObjectType.html)" )!)) fix the issue of window.onerror callback in javascript sending errors censored to only "Script error."?

Errors reported by content of WKWebView (via window.onerror) are censored to "Script error.""
 
 
Q