JUCE uses the native macOS WebView in the WebBrowserComponent so theoretically this should be quite possible. I have added (what I believe to be) the appropriate methods in the JUCEWebClickDetector class which now looks like this:
DownloadClickDetectorClass() : ObjCClass<NSObject> ("JUCEWebClickDetector_")
{
addIvar<WebBrowserComponent*> ("owner");
addMethod (@selector (webView:decidePolicyForNavigationAction:request:frame:decisionListener:),
decidePolicyForNavigationAction, "v@:@@@@@");
addMethod (@selector (webView:decidePolicyForNewWindowAction:request:newFrameName:decisionListener:),
decidePolicyForNewWindowAction, "v@:@@@@@");
addMethod (@selector (webView:didFinishLoadForFrame:), didFinishLoadForFrame, "v@:@@");
addMethod (@selector (webView:didFailLoadWithError:forFrame:), didFailLoadWithError, "v@:@@@");
addMethod (@selector (webView:didFailProvisionalLoadWithError:forFrame:), didFailLoadWithError, "v@:@@@");
addMethod (@selector (webView:willCloseFrame:), willCloseFrame, "v@:@@");
addMethod (@selector (webView:runOpenPanelForFileButtonWithResultListener:allowMultipleFiles:), runOpenPanel, "v@:@@", @encode (BOOL));
addMethod (@selector (isSelectorExcludedFromWebScript:), webview_is_selector_excluded_from_web_script, "c@::", @encode (BOOL));
addMethod (@selector (webScriptNameForSelector:), webview_webscript_name_for_selector, "c@::" );
addMethod (@selector (webView:didClearWindowObject:forFrame:), webview_did_clear_window_object, "v@:@@@" );
addMethod (@selector (invoke:), webview_external_invoke, "v@:@" );
registerClass();
}
static void setOwner (id self, WebBrowserComponent* owner) { object_setInstanceVariable (self, "owner", owner); }
static WebBrowserComponent* getOwner (id self) { return getIvar<WebBrowserComponent*> (self, "owner"); }
static BOOL webview_is_selector_excluded_from_web_script(id self, SEL cmd,
SEL selector) {
return selector != @selector(invoke:);
}
static NSString *webview_webscript_name_for_selector(id self, SEL cmd,
SEL selector) {
return selector == @selector(invoke:) ? @"invoke" : nil;
}
static void webview_did_clear_window_object(id self, SEL cmd, id webview,
id script, id frame) {
[script setValue:self forKey:@"external"];
}
static void webview_external_invoke(id self, SEL cmd, id arg) {
std::cout << "JS Click" << std::endl;
}
...
When I run the app with some breakpoints it will break on the webview_did_clear_window_object function but nothing happens when I click the HTML button on my page. From what I can tell, no other functions are being called (not breaking at breakpoints).
This is my first time modding any of the juce modules directly so it is entirely possible that I am missing something simple here but I just can’t seem to figure out what the issue is here.
For reference, here is the HTML file I am loading:
<!DOCTYPE html>
<html>
<body>
<button type="button" onclick="myFunction()">Click Me!</button>
<script>
function myFunction() {
window.external.invoke();
}
</script>
</body>
</html>
