From 6f130c121f2c6116c6265e6433452d2e69c0d9f0 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 20 Dec 2023 01:39:02 +0100 Subject: [PATCH] Add wxWebViewChromium::SetRoot() This allows to define a prefix for all the files used by the application in the browser. --- include/wx/webview_chromium.h | 5 ++ interface/wx/webview_chromium.h | 12 ++++ src/common/webview_chromium.cpp | 106 +++++++++++++++++++++++++++++++- 3 files changed, 121 insertions(+), 2 deletions(-) diff --git a/include/wx/webview_chromium.h b/include/wx/webview_chromium.h index 0424762fbf..8afb22480d 100644 --- a/include/wx/webview_chromium.h +++ b/include/wx/webview_chromium.h @@ -14,6 +14,8 @@ #include "wx/webview.h" #include "wx/timer.h" +class WXDLLIMPEXP_FWD_BASE wxFileName; + extern WXDLLIMPEXP_DATA_WEBVIEW(const char) wxWebViewBackendChromium[]; // Private namespace containing classes used only in the implementation. @@ -123,6 +125,9 @@ public: //Virtual Filesystem Support virtual void RegisterHandler(wxSharedPtr handler) override; + // Chromium-specific functions. + void SetRoot(const wxFileName& rootDir); + #ifdef __WXGTK__ virtual void GTKHandleRealized() override; #endif diff --git a/interface/wx/webview_chromium.h b/interface/wx/webview_chromium.h index 4c2cf68ca7..ca8783e14e 100644 --- a/interface/wx/webview_chromium.h +++ b/interface/wx/webview_chromium.h @@ -250,6 +250,10 @@ - RunScript: Retrieving the result of JavaScript execution is not supported and if the @a output parameter is non-null, the function will always return false. + wxWebView also provides some functions not available in the base class: + + - SetRoot() allows to use the given directory for all application files. + @since 3.3.0 @library{wxwebview} @category{webview} @@ -279,4 +283,12 @@ public: const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxWebViewNameStr); + + /** + Use the specified directory as root for the file:// URLs. + + After calling this function, all file paths will be resolved relatively + to the given @a rootDir rather than to the actual file system root. + */ + void SetRoot(const wxFileName& rootDir); }; diff --git a/src/common/webview_chromium.cpp b/src/common/webview_chromium.cpp index 067de30b37..5c670cba90 100644 --- a/src/common/webview_chromium.cpp +++ b/src/common/webview_chromium.cpp @@ -57,6 +57,7 @@ wxGCC_WARNING_SUPPRESS(unused-parameter) #include "include/cef_string_visitor.h" #include "include/cef_version.h" #include "include/base/cef_lock.h" +#include "include/wrapper/cef_resource_manager.h" wxGCC_WARNING_RESTORE(unused-parameter) @@ -251,17 +252,21 @@ class ClientHandler : public CefClient, public CefContextMenuHandler, public CefDisplayHandler, public CefLifeSpanHandler, - public CefLoadHandler + public CefLoadHandler, + public CefRequestHandler, + public CefResourceRequestHandler { public: // Ctor must be given a backpointer to wxWebView which must remain valid // for the entire lifetime of this object. explicit ClientHandler(wxWebViewChromium& webview) : m_webview{webview} {} + // Overridden CefClient methods virtual CefRefPtr GetContextMenuHandler() override { return this; } + virtual CefRefPtr GetDisplayHandler() override { return this; } virtual CefRefPtr GetLifeSpanHandler() override { return this; } virtual CefRefPtr GetLoadHandler() override { return this; } - virtual CefRefPtr GetDisplayHandler() override { return this; } + virtual CefRefPtr GetRequestHandler() override { return this; } // CefDisplayHandler methods virtual void OnLoadingStateChange(CefRefPtr browser, @@ -321,6 +326,43 @@ public: const CefString& errorText, const CefString& failedUrl) override; + // CefRequestHandler methods + virtual CefRefPtr GetResourceRequestHandler( + CefRefPtr WXUNUSED(browser), + CefRefPtr WXUNUSED(frame), + CefRefPtr WXUNUSED(request), + bool WXUNUSED(is_navigation), + bool WXUNUSED(is_download), + const CefString& WXUNUSED(request_initiator), + bool& WXUNUSED(disable_default_handling)) override + { + return this; + } + + // CefResourceRequestHandler methods + virtual cef_return_value_t OnBeforeResourceLoad( + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + CefRefPtr callback) override; + virtual CefRefPtr GetResourceHandler( + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request) override; + + + // Our own functions. + + // Initialize the resource manager, creating it if necessary (so don't call + // this if you don't want it to be created). + CefRefPtr GetResourceManager() + { + if ( !m_resourceManager ) + m_resourceManager = new CefResourceManager{}; + + return m_resourceManager; + } + CefRefPtr GetBrowser() const { return m_browser; } // Return the main frame. May be null. @@ -361,6 +403,9 @@ private: // Record the load error code: enum wxWebViewNavigationError // -1 means no error. int m_loadErrorCode = -1; + + CefRefPtr m_resourceManager; + IMPLEMENT_REFCOUNTING(ClientHandler); }; @@ -1272,6 +1317,39 @@ void wxWebViewChromium::RegisterHandler(wxSharedPtr handler) new SchemeHandlerFactory(handler) ); } +namespace +{ + +// Called only by wxWebViewChromium::SetRoot() which ensures that it's called +// on the appropriate thread. +void +SetResourceRoot( + const CefRefPtr& resourceManager, + const wxFileName& rootDir +) +{ + resourceManager->AddDirectoryProvider( + "file:///", + rootDir.GetFullPath().utf8_string(), + 0, + "wxRootProvider" + ); +} + +} // anonymous namespace + +void wxWebViewChromium::SetRoot(const wxFileName& rootDir) +{ + CefPostTask( + TID_IO, + base::BindOnce( + &SetResourceRoot, + m_clientHandler->GetResourceManager(), + rootDir + ) + ); +} + // CefDisplayHandler methods void ClientHandler::OnLoadingStateChange(CefRefPtr WXUNUSED(browser), bool WXUNUSED(isLoading), @@ -1528,6 +1606,30 @@ void ClientHandler::OnLoadError(CefRefPtr WXUNUSED(browser), } } +// CefResourceRequestHandler methods +cef_return_value_t ClientHandler::OnBeforeResourceLoad( + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + CefRefPtr callback) +{ + if ( !m_resourceManager ) + return RV_CONTINUE; + + return m_resourceManager->OnBeforeResourceLoad(browser, frame, request, callback); +} + +CefRefPtr ClientHandler::GetResourceHandler( + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request) +{ + if ( !m_resourceManager ) + return {}; + + return m_resourceManager->GetResourceHandler(browser, frame, request); +} + bool SchemeHandler::ProcessRequest(CefRefPtr request, CefRefPtr callback) {