Allow specifying a custom CefClient to use with wxWebViewChromium
This opens many customization possibilities beyond those provided by wxWebView API and also allows to process CEF IPC messages much more efficiently than what is possible using wxEvents. Closes #24336.
This commit is contained in:
parent
a766ed9f21
commit
5ca49dc56c
11 changed files with 249 additions and 3 deletions
|
|
@ -4062,7 +4062,8 @@ COND_USE_GUI_1_ALL_GUI_HEADERS = \
|
|||
wx/webview.h \
|
||||
wx/webviewarchivehandler.h \
|
||||
wx/webviewfshandler.h \
|
||||
wx/webview_chromium.h
|
||||
wx/webview_chromium.h \
|
||||
wx/webview_chromium_impl.h
|
||||
@COND_USE_GUI_1@ALL_GUI_HEADERS = $(COND_USE_GUI_1_ALL_GUI_HEADERS)
|
||||
COND_MONOLITHIC_1_SHARED_1___monodll___depname = \
|
||||
$(LIBDIRNAME)/$(DLLPREFIX)$(WXDLLNAMEPREFIXGUI)u$(WXDEBUGFLAG)$(WX_LIB_FLAVOUR)$(WXCOMPILER)$(VENDORTAG)$(WXDLLVERSIONTAG)$(dll___targetsuf3)
|
||||
|
|
|
|||
|
|
@ -2708,6 +2708,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
|
|||
wx/webviewarchivehandler.h
|
||||
wx/webviewfshandler.h
|
||||
wx/webview_chromium.h
|
||||
wx/webview_chromium_impl.h
|
||||
</set>
|
||||
<set var="WEBVIEW_HDR" hints="files">
|
||||
$(WEBVIEW_HDR_PLATFORM)
|
||||
|
|
|
|||
|
|
@ -2533,6 +2533,7 @@ set(WEBVIEW_CMN_HDR
|
|||
wx/webviewarchivehandler.h
|
||||
wx/webviewfshandler.h
|
||||
wx/webview_chromium.h
|
||||
wx/webview_chromium_impl.h
|
||||
)
|
||||
|
||||
set(WEBVIEW_OSX_SHARED_HDR
|
||||
|
|
|
|||
|
|
@ -2486,6 +2486,7 @@ WEBVIEW_CMN_HDR =
|
|||
wx/webviewarchivehandler.h
|
||||
wx/webviewfshandler.h
|
||||
wx/webview_chromium.h
|
||||
wx/webview_chromium_impl.h
|
||||
|
||||
WEBVIEW_OSX_SHARED_HDR =
|
||||
wx/osx/webviewhistoryitem_webkit.h
|
||||
|
|
|
|||
|
|
@ -507,6 +507,7 @@
|
|||
<ClInclude Include="..\..\include\wx\webviewfshandler.h" />
|
||||
<ClInclude Include="..\..\include\wx\webview_chromium.h" />
|
||||
<ClInclude Include="..\..\include\wx\msw\webview_edge.h" />
|
||||
<ClInclude Include="..\..\include\wx\webview_chromium_impl.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
|
|
|||
|
|
@ -61,6 +61,9 @@
|
|||
<ClInclude Include="..\..\include\wx\webview_chromium.h">
|
||||
<Filter>Common Headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\wx\webview_chromium_impl.h">
|
||||
<Filter>Common Headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\wx\webviewarchivehandler.h">
|
||||
<Filter>Common Headers</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ class WXDLLIMPEXP_FWD_BASE wxFileName;
|
|||
|
||||
extern WXDLLIMPEXP_DATA_WEBVIEW(const char) wxWebViewBackendChromium[];
|
||||
|
||||
class CefClient;
|
||||
|
||||
// Private namespace containing classes used only in the implementation.
|
||||
namespace wxCEF
|
||||
{
|
||||
|
|
@ -170,6 +172,10 @@ private:
|
|||
friend class wxCEF::ClientHandler;
|
||||
wxCEF::ClientHandler* m_clientHandler = nullptr;
|
||||
|
||||
// Actual client used by CEF: this can be either m_clientHandler itself or
|
||||
// a custom client provided by the application.
|
||||
CefClient* m_actualClient = nullptr;
|
||||
|
||||
friend class wxWebViewChromiumModule;
|
||||
static bool ms_cefInitialized;
|
||||
|
||||
|
|
@ -198,6 +204,19 @@ public:
|
|||
|
||||
// Logging level must be one of cef_log_severity_t values (0 means default).
|
||||
int m_logLevel = 0;
|
||||
|
||||
// Function to create the custom CefClient to use if non-null.
|
||||
//
|
||||
// The CefClient subclass must delegate all not otherwise implemented
|
||||
// functions to the provided client (and should always delegate the
|
||||
// lifetime-related callbacks).
|
||||
//
|
||||
// It is recommended, although not required, to derive the custom client
|
||||
// from wxDelegatingCefClient defined in wx/webview_chromium_impl.h.
|
||||
CefClient* (*m_clientCreate)(CefClient* client, void* data) = nullptr;
|
||||
|
||||
// Data to pass to m_clientCreate if it is used.
|
||||
void* m_clientCreateData = nullptr;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
97
include/wx/webview_chromium_impl.h
Normal file
97
include/wx/webview_chromium_impl.h
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: wx/webview_chromium_impl.h
|
||||
// Purpose: Helpers for implementing custom CefClient for wxWebViewChromium
|
||||
// Author: Vadim Zeitlin
|
||||
// Created: 2024-02-17
|
||||
// Copyright: (c) 2024 Vadim Zeitlin <vadim@wxwidgets.org>
|
||||
// Licence: wxWindows licence
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _WX_WEBVIEW_CHROMIUM_IMPL_H_
|
||||
#define _WX_WEBVIEW_CHROMIUM_IMPL_H_
|
||||
|
||||
// Note that this header includes CEF headers and so the appropriate include
|
||||
// path should be set up when using it.
|
||||
|
||||
#ifdef __VISUALC__
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4100)
|
||||
#endif
|
||||
|
||||
wxGCC_WARNING_SUPPRESS(unused-parameter)
|
||||
|
||||
#include "include/cef_client.h"
|
||||
|
||||
wxGCC_WARNING_RESTORE(unused-parameter)
|
||||
|
||||
#ifdef __VISUALC__
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Convenient base class for custom CefClient implementations.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class wxDelegatingCefClient : public CefClient
|
||||
{
|
||||
public:
|
||||
// Forward all CefClient methods to the original client.
|
||||
virtual CefRefPtr<CefAudioHandler> GetAudioHandler() override
|
||||
{ return m_clientOrig->GetAudioHandler(); }
|
||||
virtual CefRefPtr<CefCommandHandler> GetCommandHandler() override
|
||||
{ return m_clientOrig->GetCommandHandler(); }
|
||||
virtual CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() override
|
||||
{ return m_clientOrig->GetContextMenuHandler(); }
|
||||
virtual CefRefPtr<CefDialogHandler> GetDialogHandler() override
|
||||
{ return m_clientOrig->GetDialogHandler(); }
|
||||
virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() override
|
||||
{ return m_clientOrig->GetDisplayHandler(); }
|
||||
virtual CefRefPtr<CefDownloadHandler> GetDownloadHandler() override
|
||||
{ return m_clientOrig->GetDownloadHandler(); }
|
||||
virtual CefRefPtr<CefDragHandler> GetDragHandler() override
|
||||
{ return m_clientOrig->GetDragHandler(); }
|
||||
virtual CefRefPtr<CefFindHandler> GetFindHandler() override
|
||||
{ return m_clientOrig->GetFindHandler(); }
|
||||
virtual CefRefPtr<CefFocusHandler> GetFocusHandler() override
|
||||
{ return m_clientOrig->GetFocusHandler(); }
|
||||
virtual CefRefPtr<CefFrameHandler> GetFrameHandler() override
|
||||
{ return m_clientOrig->GetFrameHandler(); }
|
||||
virtual CefRefPtr<CefPermissionHandler> GetPermissionHandler() override
|
||||
{ return m_clientOrig->GetPermissionHandler(); }
|
||||
virtual CefRefPtr<CefJSDialogHandler> GetJSDialogHandler() override
|
||||
{ return m_clientOrig->GetJSDialogHandler(); }
|
||||
virtual CefRefPtr<CefKeyboardHandler> GetKeyboardHandler() override
|
||||
{ return m_clientOrig->GetKeyboardHandler(); }
|
||||
virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override
|
||||
{ return m_clientOrig->GetLifeSpanHandler(); }
|
||||
virtual CefRefPtr<CefLoadHandler> GetLoadHandler() override
|
||||
{ return m_clientOrig->GetLoadHandler(); }
|
||||
virtual CefRefPtr<CefPrintHandler> GetPrintHandler() override
|
||||
{ return m_clientOrig->GetPrintHandler(); }
|
||||
virtual CefRefPtr<CefRenderHandler> GetRenderHandler() override
|
||||
{ return m_clientOrig->GetRenderHandler(); }
|
||||
virtual CefRefPtr<CefRequestHandler> GetRequestHandler() override
|
||||
{ return m_clientOrig->GetRequestHandler(); }
|
||||
virtual bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefProcessId source_process,
|
||||
CefRefPtr<CefProcessMessage> message) override
|
||||
{
|
||||
return m_clientOrig->OnProcessMessageReceived(browser, frame,
|
||||
source_process, message);
|
||||
}
|
||||
|
||||
protected:
|
||||
// Objects of this class shouldn't be created, only derived classes should
|
||||
// be used, hence the constructor is protected.
|
||||
explicit wxDelegatingCefClient(CefClient* clientOrig)
|
||||
: m_clientOrig{clientOrig}
|
||||
{
|
||||
}
|
||||
|
||||
CefRefPtr<CefClient> const m_clientOrig;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(wxDelegatingCefClient);
|
||||
};
|
||||
|
||||
#endif // _WX_WEBVIEW_CHROMIUM_IMPL_H_
|
||||
|
|
@ -386,6 +386,36 @@ public:
|
|||
Default value 0 means to use default "INFO" log level.
|
||||
*/
|
||||
int m_logLevel = 0;
|
||||
|
||||
/**
|
||||
Function to create the custom CefClient to use if non-null.
|
||||
|
||||
CEF uses an object of CefClient class to customize handling of many
|
||||
operations, by allowing to return custom objects from its callbacks,
|
||||
and for processing IPC messages received from the other processes used
|
||||
by CEF. By defining this function pointer, the application can use its
|
||||
own CefClient subclass to customize many aspects of CEF behaviour
|
||||
beyond what is possible using the standard wxWebView API.
|
||||
|
||||
Please note that the returned object must delegate all not otherwise
|
||||
implemented functions to the provided @a client (and should always
|
||||
delegate the lifetime-related callbacks). You can ensure that this is
|
||||
the case by deriving your custom CefClient subclass from
|
||||
wxDelegatingCefClient, but you still need to do it manually if not
|
||||
using this class.
|
||||
*/
|
||||
CefClient* (*m_clientCreate)(CefClient* client, void* data) = nullptr;
|
||||
|
||||
/**
|
||||
Data to pass to m_clientCreate if it is used.
|
||||
|
||||
This is just an arbitrary pointer, which is passed as argument to
|
||||
m_clientCreate function if it is non-null.
|
||||
|
||||
This pointer itself may be null if it is not necessary to pass any
|
||||
extra data to the client creation function.
|
||||
*/
|
||||
void* m_clientCreateData = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -416,6 +446,13 @@ public:
|
|||
);
|
||||
@endcode
|
||||
|
||||
@note Using wxEvent dispatching adds a significant overhead to handling of
|
||||
CEF IPC messages, so if performance is important (i.e. many such messages
|
||||
are expected), it is recommended to configure wxWebViewChromium to use a
|
||||
custom `CefClient` as described in wxWebViewConfigurationChromium
|
||||
documentation and handle the messages directly in the overridden
|
||||
`OnProcessMessageReceived()` of the custom client class.
|
||||
|
||||
@since 3.3.0
|
||||
@library{wxwebview}
|
||||
@category{webview}
|
||||
|
|
|
|||
64
interface/wx/webview_chromium_impl.h
Normal file
64
interface/wx/webview_chromium_impl.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: webview_chromium_impl.h
|
||||
// Purpose: Documentation for wxWebViewChromium implementation helpers
|
||||
// Author: Vadim Zeitlin
|
||||
// Created: 2024-02-17
|
||||
// Copyright: (c) 2024 Vadim Zeitlin <vadim@wxwidgets.org>
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
Helper class to simplify creating custom CefClient subclasses.
|
||||
|
||||
Please note that the application including this header must set up the
|
||||
compiler options to include the CEF directory as one of the include paths,
|
||||
as this header -- unlike wx/webview_chromium.h -- includes CEF headers.
|
||||
|
||||
Here is a simple example of using this class to customize processing the
|
||||
messages received from the other CEF processes:
|
||||
|
||||
@code
|
||||
#include <wx/webview_chromium_impl.h>
|
||||
|
||||
struct CustomClient : wxDelegatingCefClient
|
||||
{
|
||||
using wxDelegatingCefClient::wxDelegatingCefClient;
|
||||
|
||||
static CefClient* Create(CefClient* client, void* WXUNUSED(data)
|
||||
{
|
||||
return new CustomClient(client);
|
||||
}
|
||||
|
||||
bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefProcessId source_process,
|
||||
CefRefPtr<CefProcessMessage> message) override
|
||||
{
|
||||
// Handle the message here.
|
||||
|
||||
return true; // or false if not handled
|
||||
}
|
||||
};
|
||||
|
||||
void MyFunction()
|
||||
{
|
||||
wxWebViewConfiguration config = wxWebView::NewConfiguration(wxWebViewBackendChromium);
|
||||
|
||||
auto configChrome =
|
||||
static_cast<wxWebViewConfigurationChromium*>(config.GetNativeConfiguration());
|
||||
configChrome->m_clientCreate = &CustomClient::Create;
|
||||
|
||||
auto webview = new wxWebViewChromium(config);
|
||||
if ( !webview->Create(this, wxID_ANY, url) )
|
||||
{
|
||||
// Handle error.
|
||||
}
|
||||
}
|
||||
@endcode
|
||||
|
||||
@since 3.3.0
|
||||
@category{webview}
|
||||
*/
|
||||
class wxDelegatingCefClient : CefClient
|
||||
{
|
||||
};
|
||||
|
|
@ -829,9 +829,22 @@ bool wxWebViewChromium::DoCreateBrowser(const wxString& url)
|
|||
}
|
||||
}
|
||||
|
||||
// Check if we need to create a custom client handler.
|
||||
const auto configChrome =
|
||||
static_cast<wxWebViewConfigurationChromium*>(m_implData->m_config.GetNativeConfiguration());
|
||||
if ( auto create = configChrome->m_clientCreate )
|
||||
{
|
||||
m_actualClient = create(m_clientHandler, configChrome->m_clientCreateData);
|
||||
if ( m_actualClient )
|
||||
m_actualClient->AddRef();
|
||||
}
|
||||
|
||||
if ( !m_actualClient )
|
||||
m_actualClient = m_clientHandler;
|
||||
|
||||
if ( !CefBrowserHost::CreateBrowser(
|
||||
info,
|
||||
CefRefPtr<CefClient>{m_clientHandler},
|
||||
CefRefPtr<CefClient>{m_actualClient},
|
||||
url.ToStdString(),
|
||||
browsersettings,
|
||||
nullptr, // No extra info
|
||||
|
|
@ -856,7 +869,10 @@ wxWebViewChromium::~wxWebViewChromium()
|
|||
|
||||
constexpr bool forceClose = true;
|
||||
m_clientHandler->GetHost()->CloseBrowser(forceClose);
|
||||
m_clientHandler->Release();
|
||||
|
||||
// We need to destroy the client handler used by the browser to allow
|
||||
// it to close.
|
||||
m_actualClient->Release();
|
||||
|
||||
// We need to wait until the browser is really closed, which happens
|
||||
// asynchronously, as otherwise we could exit the program and call
|
||||
|
|
@ -905,6 +921,11 @@ wxWebViewChromium::~wxWebViewChromium()
|
|||
// really destroying the object before CefShutdown() is called.
|
||||
wxUnusedVar(handle);
|
||||
#endif
|
||||
|
||||
// If we hadn't release our own client handler above, we need to do it
|
||||
// now (notice that it's safe to do it, as it can't be used any more).
|
||||
if ( m_clientHandler != m_actualClient )
|
||||
m_clientHandler->Release();
|
||||
}
|
||||
|
||||
delete m_implData;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue