Updated question
I am loading a remote page that I control into a WKWebview
in my app and customizing it by loading local CSS and font files. At page load, in webView:didFinishNavigation:
, I am running some JS to inject some style
tags and a link
element whose src
points to a local file via a custom URL scheme myfile
implemented via WKURLSchemeHandler
. The local file is being blocked from loading by what appears to be Content Security Policy.
I am not able to add headers because the page I'm loading is in an S3 bucket, but I have added a meta
tag to the head
on the server (not injected with JS):
<meta http-equiv="Content-Security-Policy" content="default-src 'self' otfile:; style-src 'self' 'unsafe-inline' 'unsafe-eval' http: https: data: otfile:"/>
Even with this addition, the web view does not attempt to load the local CSS - looking at the Safari web inspector, the link
element is in the head
but the CSS file doesn't show up on the network tab. Evaluating await fetch('otfile://myfile.css')
in the console produces a warning like this:
[blocked] The page at https://my-bucket.s3.amazonaws.com/file.xhtml was not allowed to display insecure content from otfile://file.css.
An example project demonstrating the issue can be found here.
My question has now become: How do I specify to WKWebView / WebKit that it's permitted to load arbitrary content via my custom URL scheme here?
See below for original
I'm loading a remote page in a WKWebView, and I need to customize the styling of it by injecting a reference to a local CSS file at page load using Javascript. I'm using an implementation of WKURLSchemeHandler
to do this. When I set up my web view:
WKFileLoadHandler *fileHandler = [[MyFileLoadHandler alloc]init];
[config setURLSchemeHandler:fileHandler forURLScheme:@"myfile"];
self.webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:config];
self.webView.navigationDelegate = self;
self.webView.allowsLinkPreview = NO;
self.webView.opaque = NO;
[self.view addSubview:self.webView];
[self.webView autoPinEdgesToSuperviewEdges];
//self.url is a remote url
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:self.url];
request.cachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData;
[self.webView loadRequest:request];
Then, when the page has loaded, in webView:didFinishNavigation
:
NSMutableString *strJs = [NSMutableString string];
[strJs appendString:@"var cssTag = document.createElement('link');\n"];
[strJs appendString:@"cssTag.setAttribute('type', 'text/css');\n"];
[strJs appendString:@"cssTag.setAttribute('href', 'myfile://bundle/css/engine.css');\n"];
[strJs appendString:@"cssTag.setAttribute('rel', 'stylesheet');\n"];
[strJs appendString:@"document.head.appendChild(cssTag);\n"];
[self.webView evaluateJavascript:strJs completionHandler:nil];
In my code I have a completion handler that I've omitted here for brevity, and there is no error reported when running the JS.
What I'm seeing is that the web view does not attempt to load the CSS file. It never even makes a call to the scheme handler, and it doesn't show up in the Web Inspector as a request that was attempted.
I have tried setting the href
of the link
element to a remote URL instead, and the web view attempts to load that. I also tried creating an img
element with its src
set to a myfile://
URL and appending it to the document body, and the web view attempts to load that.
Is there a property or security policy or something that prevents WKWebView
from loading CSS documents using custom scheme handlers when the document it has open is via https
?
Update: this appears to be the same issue as this question.