1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

WebBrowserComponent (macOS): Catch use after free async callback bug

This commit is contained in:
Oliver James 2024-12-30 12:51:00 +00:00 committed by reuk
parent cafe62dd88
commit f72cf8ff14
No known key found for this signature in database

View file

@ -424,60 +424,82 @@ struct WebViewDelegateClass final : public ObjCClass<NSObject>
addMethod (@selector (webView:decidePolicyForNavigationAction:decisionHandler:), addMethod (@selector (webView:decidePolicyForNavigationAction:decisionHandler:),
[] (id self, SEL, WKWebView*, WKNavigationAction* navigationAction, void (^decisionHandler) (WKNavigationActionPolicy)) [] (id self, SEL, WKWebView*, WKNavigationAction* navigationAction, void (^decisionHandler) (WKNavigationActionPolicy))
{ {
if (getConnector (self)->getBrowser().pageAboutToLoad (nsStringToJuce ([[[navigationAction request] URL] absoluteString]))) if (auto* connector = getConnector (self))
decisionHandler (WKNavigationActionPolicyAllow); {
else if (connector->getBrowser().pageAboutToLoad (nsStringToJuce ([[[navigationAction request] URL] absoluteString])))
decisionHandler (WKNavigationActionPolicyCancel); decisionHandler (WKNavigationActionPolicyAllow);
else
decisionHandler (WKNavigationActionPolicyCancel);
}
}); });
addMethod (@selector (webView:didFinishNavigation:), addMethod (@selector (webView:didFinishNavigation:),
[] (id self, SEL, WKWebView* webview, WKNavigation*) [] (id self, SEL, WKWebView* webview, WKNavigation*)
{ {
getConnector (self)->getBrowser().pageFinishedLoading (nsStringToJuce ([[webview URL] absoluteString])); if (auto* connector = getConnector (self))
connector->getBrowser().pageFinishedLoading (nsStringToJuce ([[webview URL] absoluteString]));
}); });
addMethod (@selector (webView:didFailNavigation:withError:), addMethod (@selector (webView:didFailNavigation:withError:),
[] (id self, SEL, WKWebView*, WKNavigation*, NSError* error) [] (id self, SEL, WKWebView*, WKNavigation*, NSError* error)
{ {
displayError (&getConnector (self)->getBrowser(), error); if (auto* connector = getConnector (self))
displayError (&connector->getBrowser(), error);
}); });
addMethod (@selector (webView:didFailProvisionalNavigation:withError:), addMethod (@selector (webView:didFailProvisionalNavigation:withError:),
[] (id self, SEL, WKWebView*, WKNavigation*, NSError* error) [] (id self, SEL, WKWebView*, WKNavigation*, NSError* error)
{ {
displayError (&getConnector (self)->getBrowser(), error); if (auto* connector = getConnector (self))
displayError (&connector->getBrowser(), error);
}); });
addMethod (@selector (webViewDidClose:), addMethod (@selector (webViewDidClose:),
[] (id self, SEL, WKWebView*) [] (id self, SEL, WKWebView*)
{ {
getConnector (self)->getBrowser().windowCloseRequest(); if (auto* connector = getConnector (self))
connector->getBrowser().windowCloseRequest();
}); });
addMethod (@selector (webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:), addMethod (@selector (webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:),
[] (id self, SEL, WKWebView*, WKWebViewConfiguration*, WKNavigationAction* navigationAction, WKWindowFeatures*) [] (id self, SEL, WKWebView*, WKWebViewConfiguration*, WKNavigationAction* navigationAction, WKWindowFeatures*)
{ {
getConnector (self)->getBrowser().newWindowAttemptingToLoad (nsStringToJuce ([[[navigationAction request] URL] absoluteString])); if (auto* connector = getConnector (self))
connector->getBrowser().newWindowAttemptingToLoad (nsStringToJuce ([[[navigationAction request] URL] absoluteString]));
return nil; return nil;
}); });
addMethod (@selector (userContentController:didReceiveScriptMessage:), addMethod (@selector (userContentController:didReceiveScriptMessage:),
[] (id self, SEL, id, id message) [] (id self, SEL, id, id message)
{ {
const auto object = fromObject ([message body]); if (auto* connector = getConnector (self))
if (! object.isString())
{ {
jassertfalse; const auto object = fromObject ([message body]);
return;
}
getConnector (self)->handleNativeEvent (JSON::fromString (object.toString())); if (! object.isString())
{
jassertfalse;
return;
}
connector->handleNativeEvent (JSON::fromString (object.toString()));
}
}); });
addMethod (@selector (webView:startURLSchemeTask:), addMethod (@selector (webView:startURLSchemeTask:),
[] (id self, SEL, id, id urlSchemeTask) [] (id self, SEL, id, id urlSchemeTask)
{ {
auto* connector = getConnector (self);
if (connector == nullptr)
{
[urlSchemeTask didFailWithError: [NSError errorWithDomain:NSURLErrorDomain
code:NSURLErrorCancelled
userInfo: nil]];
return;
}
const auto request = [urlSchemeTask request]; const auto request = [urlSchemeTask request];
auto* url = [&] auto* url = [&]
@ -488,8 +510,7 @@ struct WebViewDelegateClass final : public ObjCClass<NSObject>
}(); }();
const auto path = nsStringToJuce ([url path]); const auto path = nsStringToJuce ([url path]);
const auto resource = connector->handleResourceRequest (path);
const auto resource = getConnector (self)->handleResourceRequest (path);
JUCE_AUTORELEASEPOOL JUCE_AUTORELEASEPOOL
{ {
@ -513,7 +534,7 @@ struct WebViewDelegateClass final : public ObjCClass<NSObject>
@"Content-Type" : juceStringToNS (resource->mimeType), @"Content-Type" : juceStringToNS (resource->mimeType),
} mutableCopy]; } mutableCopy];
if (auto allowedOrigin = getConnector (self)->getOptions().getAllowedOrigin()) if (auto allowedOrigin = connector->getOptions().getAllowedOrigin())
{ {
[headers setObject:juceStringToNS (*allowedOrigin) [headers setObject:juceStringToNS (*allowedOrigin)
forKey:@"Access-Control-Allow-Origin"]; forKey:@"Access-Control-Allow-Origin"];
@ -543,7 +564,7 @@ struct WebViewDelegateClass final : public ObjCClass<NSObject>
if (@available (macOS 10.12, *)) if (@available (macOS 10.12, *))
{ {
addMethod (@selector (webView:runOpenPanelWithParameters:initiatedByFrame:completionHandler:), addMethod (@selector (webView:runOpenPanelWithParameters:initiatedByFrame:completionHandler:),
[] (id, SEL, WKWebView*, WKOpenPanelParameters* parameters, WKFrameInfo*, void (^completionHandler)(NSArray<NSURL*>*)) [] (id self, SEL, WKWebView*, WKOpenPanelParameters* parameters, WKFrameInfo*, void (^completionHandler)(NSArray<NSURL*>*))
{ {
using CompletionHandlerType = decltype (completionHandler); using CompletionHandlerType = decltype (completionHandler);
@ -577,6 +598,9 @@ struct WebViewDelegateClass final : public ObjCClass<NSObject>
bool handlerCalled = false; bool handlerCalled = false;
}; };
if (getConnector (self) == nullptr)
return;
auto chooser = std::make_unique<FileChooser> (TRANS ("Select the file you want to upload..."), auto chooser = std::make_unique<FileChooser> (TRANS ("Select the file you want to upload..."),
File::getSpecialLocation (File::userHomeDirectory), "*"); File::getSpecialLocation (File::userHomeDirectory), "*");
auto* wrapper = new DeletedFileChooserWrapper (std::move (chooser), completionHandler); auto* wrapper = new DeletedFileChooserWrapper (std::move (chooser), completionHandler);
@ -881,6 +905,8 @@ public:
~WKWebViewImpl() override ~WKWebViewImpl() override
{ {
WebViewDelegateClass::setConnector (webViewDelegate.get(), nullptr);
setView (nil); setView (nil);
[webView.get() setNavigationDelegate: nil]; [webView.get() setNavigationDelegate: nil];
[webView.get() setUIDelegate: nil]; [webView.get() setUIDelegate: nil];