diff --git a/modules/juce_gui_extra/misc/juce_WebBrowserComponent.h b/modules/juce_gui_extra/misc/juce_WebBrowserComponent.h index 7f5b836ff1..2d9b18b437 100644 --- a/modules/juce_gui_extra/misc/juce_WebBrowserComponent.h +++ b/modules/juce_gui_extra/misc/juce_WebBrowserComponent.h @@ -212,6 +212,29 @@ public: Colour backgroundColour; }; + /** Options specific to the WkWebView backend used on Apple systems. These options will be + ignored on non-Apple platforms. + */ + class AppleWkWebView + { + public: + /** Specifies whether the WebView is allowed to access siblings of files specified with + the file:// URL scheme. + + Allowing this is a potential security vulnerability if you don't have full control + over the file that you are opening. + */ + [[nodiscard]] AppleWkWebView withAllowAccessToEnclosingDirectory (bool x) const + { + return withMember (*this, &AppleWkWebView::allowAccessToEnclosingDirectory, x); + } + + auto getAllowAccessToEnclosingDirectory() const { return allowAccessToEnclosingDirectory; } + + private: + bool allowAccessToEnclosingDirectory = false; + }; + /** Specifies options that apply to the Windows implementation when the WebView2 feature is enabled. @@ -222,6 +245,13 @@ public: return withMember (*this, &Options::winWebView2, winWebView2Options); } + /** Specifies options that influence the WebBrowserComponent's behaviour on Apple systems. + */ + [[nodiscard]] Options withAppleWkWebViewOptions (const AppleWkWebView& appleWkWebViewOptions) const + { + return withMember (*this, &Options::appleWkWebView, appleWkWebViewOptions); + } + /** Enables native integration features for the code running inside the WebBrowserComponent. This injects data and function objects under `window.__JUCE__.backend` through which @@ -342,6 +372,7 @@ public: auto keepsPageLoadedWhenBrowserIsHidden() const noexcept { return keepPageLoadedWhenBrowserIsHidden; } auto getUserAgent() const { return userAgent; } auto getWinWebView2BackendOptions() const { return winWebView2; } + auto getAppleWkWebViewOptions() const { return appleWkWebView; } auto getNativeIntegrationsEnabled() const { return enableNativeIntegration; } const auto& getNativeFunctions() const { return nativeFunctions; } const auto& getEventListeners() const { return eventListeners; } @@ -357,6 +388,7 @@ public: bool enableNativeIntegration = false; String userAgent; WinWebView2 winWebView2; + AppleWkWebView appleWkWebView; std::map nativeFunctions; std::vector> eventListeners; StringArray userScripts; diff --git a/modules/juce_gui_extra/native/juce_WebBrowserComponent_mac.mm b/modules/juce_gui_extra/native/juce_WebBrowserComponent_mac.mm index 7c4cad144b..c91417a683 100644 --- a/modules/juce_gui_extra/native/juce_WebBrowserComponent_mac.mm +++ b/modules/juce_gui_extra/native/juce_WebBrowserComponent_mac.mm @@ -818,7 +818,9 @@ public: delegateConnector (implIn.owner, [this] (const auto& m) { owner.handleNativeEvent (m); }, [this] (const auto& r) { return owner.handleResourceRequest (r); }, - browserOptions) + browserOptions), + allowAccessToEnclosingDirectory (browserOptions.getAppleWkWebViewOptions() + .getAllowAccessToEnclosingDirectory()) { ObjCObjectHandle config { [WKWebViewConfiguration new] }; id preferences = [config.get() preferences]; @@ -987,8 +989,23 @@ public: { auto file = URL (url).getLocalFile(); - if (NSURL* nsUrl = [NSURL fileURLWithPath: juceStringToNS (file.getFullPathName())]) - [webView.get() loadFileURL: appendParametersToFileURL (url, nsUrl) allowingReadAccessToURL: nsUrl]; + NSURL* nsUrl = [NSURL fileURLWithPath: juceStringToNS (file.getFullPathName())]; + + auto* accessPath = [&] + { + if (! allowAccessToEnclosingDirectory) + return nsUrl; + + auto* parentUrl = [NSURL fileURLWithPath: juceStringToNS (file.getParentDirectory().getFullPathName())]; + + if (parentUrl == nullptr) + return nsUrl; + + return parentUrl; + }(); + + if (nsUrl != nullptr) + [webView.get() loadFileURL: appendParametersToFileURL (url, nsUrl) allowingReadAccessToURL: accessPath]; } else if (NSMutableURLRequest* request = getRequestForURL (url, headers, postData)) { @@ -1061,6 +1078,7 @@ public: private: WebBrowserComponent::Impl& owner; DelegateConnector delegateConnector; + bool allowAccessToEnclosingDirectory = false; LastFocusChange lastFocusChange; ObjCObjectHandle webView; ObjCObjectHandle webViewDelegate;