diff --git a/include/wx/webview_chromium.h b/include/wx/webview_chromium.h index 57e407d2c9..7ef6f4de39 100644 --- a/include/wx/webview_chromium.h +++ b/include/wx/webview_chromium.h @@ -178,6 +178,50 @@ private: wxDECLARE_DYNAMIC_CLASS(wxWebViewChromium); }; +class CefFrame; +class CefProcessMessage; + +// Chrome-specific event sent when a message from renderer process is received. +// +// It provides the message received from another process and a frame that can +// be used to send the reply back. +class WXDLLIMPEXP_WEBVIEW wxWebViewChromiumEvent : public wxCommandEvent +{ +public: + wxWebViewChromiumEvent() = default; + + wxWebViewChromiumEvent( + wxWebViewChromium& webview, + CefFrame& frame, + CefProcessMessage& message + ); + + CefFrame& GetFrame() const { return *m_frame; } + CefProcessMessage& GetMessage() const { return *m_message; } + + wxString GetMessageName() const; + +private: + CefFrame* const m_frame = nullptr; + CefProcessMessage* const m_message = nullptr; + + wxDECLARE_DYNAMIC_CLASS_NO_ASSIGN_DEF_COPY(wxWebViewChromiumEvent); +}; + +wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_WEBVIEW, + wxEVT_WEBVIEW_CHROMIUM_MESSAGE_RECEIVED, + wxWebViewChromiumEvent ); + +typedef void (wxEvtHandler::*wxWebViewChromiumEventFunction) + (wxWebViewChromiumEvent&); + +#define wxWebViewChromiumEventHandler(func) \ + wxEVENT_HANDLER_CAST(wxWebViewChromiumEventFunction, func) + +#define EVT_WEBVIEW_CHROMIUM_MESSAGE_RECEIVED(id, fn) \ + wx__DECLARE_EVT1(wxEVT_WEBVIEW_CHROMIUM_MESSAGE_RECEIVED, id, \ + wxWebViewChromiumEventHandler(fn)) + #endif // wxUSE_WEBVIEW && wxUSE_WEBVIEW_CHROMIUM #endif // _WX_WEBVIEWCHROMIUM_H_ diff --git a/interface/wx/webview_chromium.h b/interface/wx/webview_chromium.h index ca8783e14e..da46fc7beb 100644 --- a/interface/wx/webview_chromium.h +++ b/interface/wx/webview_chromium.h @@ -254,6 +254,17 @@ - SetRoot() allows to use the given directory for all application files. + + @section events Events + + wxWebViewChromiumEvent is a specific event generated when a message from + the renderer process (in which any user-defined JavaScript functions are + executing) is received in the browser process (containing UI). Such + messages are sent using `CefFrame::SendProcessMessage(PID_BROWSER)` from + the renderer process, but describing Chromium IPC in details is out of + scope of this document, please see Chromium documentation for more + information. + @since 3.3.0 @library{wxwebview} @category{webview} @@ -292,3 +303,63 @@ public: */ void SetRoot(const wxFileName& rootDir); }; + + +/** + Event class for events generated exclusively by wxWebViewChromium. + + See wxWebViewEvent for other events also generated by wxWebViewEvent. + + Currently there is a single event type corresponding to this event: + `wxEVT_WEBVIEW_CHROMIUM_MESSAGE_RECEIVED`. To use it (this example assumes + that the required CEF headers are included): + + @code + webview->Bind( + wxEVT_WEBVIEW_CHROMIUM_MESSAGE_RECEIVED, + [this](wxWebViewChromiumEvent& event) { + if ( event.GetMessageName() == "MyCustomRequest" ) { + CefRefPtr arguments = event.GetMessage().GetArgumentList(); + CefRefPtr response = CefProcessMessage::Create("MyCustomResponse"); + + // ... do whatever is needed to construct the response ... + + event.GetFrame().SendProcessMessage(PID_RENDERER, response); + } else { + // Not our message. + event.Skip(); + } + } + ); + @endcode + + @since 3.3.0 + @library{wxwebview} + @category{webview} +**/ +class wxWebViewChromiumEvent : public wxCommandEvent +{ +public: + /** + Get the associated browser frame. + + This object can be used to call `SendProcessMessage(PID_RENDERER)` on + it to send the reply back to the renderer process. + */ + CefFrame& GetFrame() const; + + /** + Get the actual message. + + Message arguments can be used in the event handler to get information + associated with this message. + */ + CefProcessMessage& GetMessage() const; + + /** + Get the message name. + + This is just a convenient wrapper for `GetMessage().GetName()`. + */ + wxString GetMessageName() const; +}; diff --git a/src/common/webview_chromium.cpp b/src/common/webview_chromium.cpp index 45679f9fe0..7a8a0211f9 100644 --- a/src/common/webview_chromium.cpp +++ b/src/common/webview_chromium.cpp @@ -289,6 +289,11 @@ public: virtual CefRefPtr GetLoadHandler() override { return this; } virtual CefRefPtr GetRequestHandler() override { return this; } + virtual bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, + CefProcessId source_process, + CefRefPtr message) override; + // CefDisplayHandler methods virtual void OnLoadingStateChange(CefRefPtr browser, bool isLoading, bool canGoBack, @@ -1369,6 +1374,24 @@ void wxWebViewChromium::SetRoot(const wxFileName& rootDir) ); } +bool +ClientHandler::OnProcessMessageReceived(CefRefPtr WXUNUSED(browser), + CefRefPtr frame, + CefProcessId WXUNUSED(source_process), + CefRefPtr message) +{ + // This is not supposed to happen, but test for it nevertheless. + if ( !frame || !message ) + { + wxLogTrace(TRACE_CEF, "Ignoring null OnProcessMessageReceived() args"); + return false; + } + + wxWebViewChromiumEvent event(m_webview, *frame, *message); + + return m_webview.HandleWindowEvent(event); +} + // CefDisplayHandler methods void ClientHandler::OnLoadingStateChange(CefRefPtr WXUNUSED(browser), bool WXUNUSED(isLoading), @@ -1847,4 +1870,30 @@ private: wxIMPLEMENT_DYNAMIC_CLASS(wxWebViewChromiumModule, wxModule); +// ---------------------------------------------------------------------------- +// wxWebViewChromiumEvent +// ---------------------------------------------------------------------------- + +wxIMPLEMENT_DYNAMIC_CLASS(wxWebViewChromiumEvent, wxCommandEvent); + +wxDEFINE_EVENT( wxEVT_WEBVIEW_CHROMIUM_MESSAGE_RECEIVED, wxWebViewChromiumEvent ); + +wxWebViewChromiumEvent::wxWebViewChromiumEvent( + wxWebViewChromium& webview, + CefFrame& frame, + CefProcessMessage& message +) : wxCommandEvent(wxEVT_WEBVIEW_CHROMIUM_MESSAGE_RECEIVED, webview.GetId()), + m_frame(&frame), + m_message(&message) +{ + SetEventObject(&webview); +} + +wxString wxWebViewChromiumEvent::GetMessageName() const +{ + wxCHECK_MSG( m_message, {}, "No message" ); + + return m_message->GetName().ToWString(); +} + #endif // wxUSE_WEBVIEW && wxUSE_WEBVIEW_CHROMIUM