#import typedef char *(*SettingsCallback)(const char *, const char *, const char *, bool); typedef void (*SettingsFree)(char *); @interface KanbanSettingsHandler : NSObject @property(nonatomic, weak) WKWebView *webview; @property(nonatomic, copy) NSString *label; @property(nonatomic) SettingsCallback callback; @property(nonatomic) SettingsFree releaseReply; @end @implementation KanbanSettingsHandler - (void)userContentController:(WKUserContentController *)controller didReceiveScriptMessage:(WKScriptMessage *)message replyHandler:(void (^)(id, NSString *))replyHandler { if (message.webView != self.webview || !message.frameInfo.isMainFrame || ![message.body isKindOfClass:NSString.class]) { replyHandler(nil, @"untrustedFrame"); return; } char *reply = self.callback(self.label.UTF8String, message.frameInfo.request.URL.absoluteString.UTF8String, [(NSString *)message.body UTF8String], message.frameInfo.isMainFrame); if (!reply) { replyHandler(nil, @"bridgeUnavailable"); return; } NSString *value = [NSString stringWithUTF8String:reply]; self.releaseReply(reply); replyHandler(value, nil); } @end void install_workspace_settings(void *pointer, const char *label, const char *script, SettingsCallback callback, SettingsFree releaseReply) { WKWebView *webview = (__bridge WKWebView *)pointer; KanbanSettingsHandler *handler = [KanbanSettingsHandler new]; handler.webview = webview; handler.label = [NSString stringWithUTF8String:label]; handler.callback = callback; handler.releaseReply = releaseReply; [webview.configuration.userContentController addScriptMessageHandlerWithReply:handler contentWorld:WKContentWorld.pageWorld name:@"kanbanSettings"]; [webview.configuration.userContentController addUserScript:[[WKUserScript alloc] initWithSource:[NSString stringWithUTF8String:script] injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]]; // The initial document may already have started loading before the handler is attached. [webview evaluateJavaScript:[NSString stringWithUTF8String:script] completionHandler:nil]; }