From 011035ef088d057fc1fc15049510b1e95c3126a6 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Mon, 15 Feb 2021 16:15:10 +0100 Subject: [PATCH 01/31] Add wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED event --- include/wx/webview.h | 1 + interface/wx/webview.h | 3 +++ src/common/webview.cpp | 1 + 3 files changed, 5 insertions(+) diff --git a/include/wx/webview.h b/include/wx/webview.h index 22bcfd8279..24a96045eb 100644 --- a/include/wx/webview.h +++ b/include/wx/webview.h @@ -296,6 +296,7 @@ wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_WEBVIEW, wxEVT_WEBVIEW_ERROR, wxWebViewEve wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_WEBVIEW, wxEVT_WEBVIEW_NEWWINDOW, wxWebViewEvent ); wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_WEBVIEW, wxEVT_WEBVIEW_TITLE_CHANGED, wxWebViewEvent ); wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_WEBVIEW, wxEVT_WEBVIEW_FULLSCREEN_CHANGED, wxWebViewEvent); +wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_WEBVIEW, wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, wxWebViewEvent); typedef void (wxEvtHandler::*wxWebViewEventFunction) (wxWebViewEvent&); diff --git a/interface/wx/webview.h b/interface/wx/webview.h index 18581d2c9a..dced7e269a 100644 --- a/interface/wx/webview.h +++ b/interface/wx/webview.h @@ -433,6 +433,9 @@ public: the page wants to enter or leave fullscreen. Use GetInt to get the status. Currently only implemented for the edge and WebKit2GTK+ backend and is only available in wxWidgets 3.1.5 or later. + @event{EVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED} + Process a @c wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED event + only available in wxWidgets 3.1.5 or later. @endEventTable @since 2.9.3 diff --git a/src/common/webview.cpp b/src/common/webview.cpp index 3303fc08df..cc845a2b5e 100644 --- a/src/common/webview.cpp +++ b/src/common/webview.cpp @@ -49,6 +49,7 @@ wxDEFINE_EVENT( wxEVT_WEBVIEW_ERROR, wxWebViewEvent ); wxDEFINE_EVENT( wxEVT_WEBVIEW_NEWWINDOW, wxWebViewEvent ); wxDEFINE_EVENT( wxEVT_WEBVIEW_TITLE_CHANGED, wxWebViewEvent ); wxDEFINE_EVENT( wxEVT_WEBVIEW_FULLSCREEN_CHANGED, wxWebViewEvent); +wxDEFINE_EVENT( wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, wxWebViewEvent); wxStringWebViewFactoryMap wxWebView::m_factoryMap; From edcaf5210ee5ae4c301bbae630e789784120d081 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Mon, 15 Feb 2021 16:15:29 +0100 Subject: [PATCH 02/31] Implement script message for edge backend --- include/wx/msw/private/webview_edge.h | 2 ++ src/msw/webview_edge.cpp | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/include/wx/msw/private/webview_edge.h b/include/wx/msw/private/webview_edge.h index f78d984395..bb5063807e 100644 --- a/include/wx/msw/private/webview_edge.h +++ b/include/wx/msw/private/webview_edge.h @@ -47,6 +47,7 @@ public: EventRegistrationToken m_documentTitleChangedToken = { }; EventRegistrationToken m_contentLoadingToken = { }; EventRegistrationToken m_containsFullScreenElementChangedToken = { }; + EventRegistrationToken m_webMessageReceivedToken = { }; // WebView Event handlers HRESULT OnNavigationStarting(ICoreWebView2* sender, ICoreWebView2NavigationStartingEventArgs* args); @@ -56,6 +57,7 @@ public: HRESULT OnDocumentTitleChanged(ICoreWebView2* sender, IUnknown* args); HRESULT OnContentLoading(ICoreWebView2* sender, ICoreWebView2ContentLoadingEventArgs* args); HRESULT OnContainsFullScreenElementChanged(ICoreWebView2* sender, IUnknown* args); + HRESULT OnWebMessageReceived(ICoreWebView2* sender, ICoreWebView2WebMessageReceivedEventArgs* args); HRESULT OnEnvironmentCreated(HRESULT result, ICoreWebView2Environment* environment); HRESULT OnWebViewCreated(HRESULT result, ICoreWebView2Controller* webViewController); diff --git a/src/msw/webview_edge.cpp b/src/msw/webview_edge.cpp index 355d384e31..22846b93a4 100644 --- a/src/msw/webview_edge.cpp +++ b/src/msw/webview_edge.cpp @@ -73,6 +73,7 @@ wxWebViewEdgeImpl::~wxWebViewEdgeImpl() m_webView->remove_DocumentTitleChanged(m_documentTitleChangedToken); m_webView->remove_ContentLoading(m_contentLoadingToken); m_webView->remove_ContainsFullScreenElementChanged(m_containsFullScreenElementChangedToken); + m_webView->remove_WebMessageReceived(m_webMessageReceivedToken); } } @@ -318,6 +319,20 @@ HRESULT wxWebViewEdgeImpl::OnContainsFullScreenElementChanged(ICoreWebView2* WXU return S_OK; } +HRESULT wxWebViewEdgeImpl::OnWebMessageReceived(ICoreWebView2* WXUNUSED(sender), ICoreWebView2WebMessageReceivedEventArgs* args) +{ + wxCoTaskMemPtr msgContent; + + wxWebViewEvent event(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, m_ctrl->GetId(), + m_ctrl->GetCurrentURL(), wxString()); + event.SetEventObject(m_ctrl); + if (SUCCEEDED(args->get_WebMessageAsJson(&msgContent))) + event.SetString(wxString(msgContent)); + m_ctrl->HandleWindowEvent(event); + + return S_OK; +} + HRESULT wxWebViewEdgeImpl::OnWebViewCreated(HRESULT result, ICoreWebView2Controller* webViewController) { if (FAILED(result)) @@ -367,6 +382,10 @@ HRESULT wxWebViewEdgeImpl::OnWebViewCreated(HRESULT result, ICoreWebView2Control Callback( this, &wxWebViewEdgeImpl::OnContainsFullScreenElementChanged).Get(), &m_containsFullScreenElementChangedToken); + m_webView->add_WebMessageReceived( + Callback( + this, &wxWebViewEdgeImpl::OnWebMessageReceived).Get(), + &m_webMessageReceivedToken); if (m_pendingContextMenuEnabled != -1) { From a7ff7a801253964a002ec118caf8e96877affca2 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Mon, 15 Feb 2021 18:13:57 +0100 Subject: [PATCH 03/31] Implement script message for WKWebView backend --- include/wx/osx/webview_webkit.h | 1 + include/wx/webview.h | 1 + samples/webview/webview.cpp | 1 + src/osx/webview_webkit.mm | 54 +++++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+) diff --git a/include/wx/osx/webview_webkit.h b/include/wx/osx/webview_webkit.h index 6bd6da02f3..8b31ffdd34 100644 --- a/include/wx/osx/webview_webkit.h +++ b/include/wx/osx/webview_webkit.h @@ -89,6 +89,7 @@ public: virtual bool IsEditable() const wxOVERRIDE; bool RunScript(const wxString& javascript, wxString* output = NULL) const wxOVERRIDE; + virtual void AddScriptMessageHandler(const wxString& name) wxOVERRIDE; //Virtual Filesystem Support virtual void RegisterHandler(wxSharedPtr handler) wxOVERRIDE; diff --git a/include/wx/webview.h b/include/wx/webview.h index 24a96045eb..14f7970919 100644 --- a/include/wx/webview.h +++ b/include/wx/webview.h @@ -182,6 +182,7 @@ public: virtual void RegisterHandler(wxSharedPtr handler) = 0; virtual void Reload(wxWebViewReloadFlags flags = wxWEBVIEW_RELOAD_DEFAULT) = 0; virtual bool RunScript(const wxString& javascript, wxString* output = NULL) const = 0; + virtual void AddScriptMessageHandler(const wxString& name) { } virtual void SetEditable(bool enable = true) = 0; void SetPage(const wxString& html, const wxString& baseUrl) { diff --git a/samples/webview/webview.cpp b/samples/webview/webview.cpp index ac9512ed89..653bd56a6c 100644 --- a/samples/webview/webview.cpp +++ b/samples/webview/webview.cpp @@ -398,6 +398,7 @@ WebFrame::WebFrame(const wxString& url) : m_browser->RegisterHandler(wxSharedPtr(new wxWebViewFSHandler("memory"))); #endif m_browser->Create(this, wxID_ANY, url, wxDefaultPosition, wxDefaultSize); + m_browser->AddScriptMessageHandler("wx"); topsizer->Add(m_browser, wxSizerFlags().Expand().Proportion(1)); #ifndef __WXMAC__ diff --git a/src/osx/webview_webkit.mm b/src/osx/webview_webkit.mm index a788f8c4a3..56647b98ed 100644 --- a/src/osx/webview_webkit.mm +++ b/src/osx/webview_webkit.mm @@ -87,6 +87,15 @@ wxEND_EVENT_TABLE() @end #endif // macOS 10.13+ +@interface WebViewScriptMessageHandler: NSObject +{ + wxWebViewWebKit* webKitWindow; +} + +- (id)initWithWxWindow: (wxWebViewWebKit*)inWindow; + +@end + //----------------------------------------------------------------------------- // wxWebViewFactoryWebKit //----------------------------------------------------------------------------- @@ -385,6 +394,12 @@ bool wxWebViewWebKit::RunScript(const wxString& javascript, wxString* output) co return true; } +void wxWebViewWebKit::AddScriptMessageHandler(const wxString& name) +{ + [m_webView.configuration.userContentController addScriptMessageHandler: + [[WebViewScriptMessageHandler alloc] initWithWxWindow:this] name:wxCFStringRef(name).AsNSString()]; +} + void wxWebViewWebKit::LoadURL(const wxString& url) { [m_webView loadRequest:[NSURLRequest requestWithURL: @@ -891,4 +906,43 @@ WX_API_AVAILABLE_MACOS(10, 12) @end +@implementation WebViewScriptMessageHandler + +- (id)initWithWxWindow: (wxWebViewWebKit*)inWindow +{ + if (self = [super init]) + { + webKitWindow = inWindow; // non retained + } + return self; +} + +- (void)userContentController:(nonnull WKUserContentController *)userContentController + didReceiveScriptMessage:(nonnull WKScriptMessage *)message +{ + wxWebViewEvent event(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, + webKitWindow->GetId(), + webKitWindow->GetCurrentURL(), + ""); + if ([message.body isKindOfClass:NSString.class]) + event.SetString(wxCFStringRef::AsString(message.body)); + else if ([message.body isKindOfClass:NSNumber.class]) + event.SetString(wxCFStringRef::AsString(((NSNumber*)message.body).stringValue)); + else if ([message.body isKindOfClass:NSDate.class]) + event.SetString(wxCFStringRef::AsString(((NSDate*)message.body).description)); + else if ([message.body isKindOfClass:NSNull.class]) + event.SetString("null"); + else if ([message.body isKindOfClass:NSDictionary.class] || [message.body isKindOfClass:NSArray.class]) + { + NSError* error = nil; + NSData* jsonData = [NSJSONSerialization dataWithJSONObject:message.body options:0 error:&error]; + NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + event.SetString(wxCFStringRef::AsString(jsonString)); + } + + webKitWindow->ProcessWindowEvent(event); +} + +@end + #endif //wxUSE_WEBVIEW && wxUSE_WEBVIEW_WEBKIT From 5b838ae6c1d21765e2fa48e0332d179762241e24 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Fri, 26 Feb 2021 15:54:46 +0100 Subject: [PATCH 04/31] Fix unused warning --- include/wx/webview.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/wx/webview.h b/include/wx/webview.h index 14f7970919..7771f4797b 100644 --- a/include/wx/webview.h +++ b/include/wx/webview.h @@ -182,7 +182,7 @@ public: virtual void RegisterHandler(wxSharedPtr handler) = 0; virtual void Reload(wxWebViewReloadFlags flags = wxWEBVIEW_RELOAD_DEFAULT) = 0; virtual bool RunScript(const wxString& javascript, wxString* output = NULL) const = 0; - virtual void AddScriptMessageHandler(const wxString& name) { } + virtual void AddScriptMessageHandler(const wxString& WXUNUSED(name)) { } virtual void SetEditable(bool enable = true) = 0; void SetPage(const wxString& html, const wxString& baseUrl) { From c78147b267393111a9009fb2777de85ff9b33cd8 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Fri, 26 Feb 2021 16:05:41 +0100 Subject: [PATCH 05/31] Add script command handler to sample --- samples/webview/webview.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/samples/webview/webview.cpp b/samples/webview/webview.cpp index 653bd56a6c..792430b167 100644 --- a/samples/webview/webview.cpp +++ b/samples/webview/webview.cpp @@ -121,6 +121,7 @@ public: void OnNewWindow(wxWebViewEvent& evt); void OnTitleChanged(wxWebViewEvent& evt); void OnFullScreenChanged(wxWebViewEvent& evt); + void OnScriptMessage(wxWebViewEvent& evt); void OnSetPage(wxCommandEvent& evt); void OnViewSourceRequest(wxCommandEvent& evt); void OnViewTextRequest(wxCommandEvent& evt); @@ -539,6 +540,7 @@ WebFrame::WebFrame(const wxString& url) : Bind(wxEVT_WEBVIEW_NEWWINDOW, &WebFrame::OnNewWindow, this, m_browser->GetId()); Bind(wxEVT_WEBVIEW_TITLE_CHANGED, &WebFrame::OnTitleChanged, this, m_browser->GetId()); Bind(wxEVT_WEBVIEW_FULLSCREEN_CHANGED, &WebFrame::OnFullScreenChanged, this, m_browser->GetId()); + Bind(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, &WebFrame::OnScriptMessage, this, m_browser->GetId()); // Connect the menu events Bind(wxEVT_MENU, &WebFrame::OnSetPage, this, setPage->GetId()); @@ -906,6 +908,11 @@ void WebFrame::OnFullScreenChanged(wxWebViewEvent & evt) ShowFullScreen(evt.GetInt() != 0); } +void WebFrame::OnScriptMessage(wxWebViewEvent& evt) +{ + wxLogMessage("Script message recieved; value = %s", evt.GetString()); +} + void WebFrame::OnSetPage(wxCommandEvent& WXUNUSED(evt)) { m_browser->SetPage From c3d0d7d0007f72629a8378b0e7af207c7cc4acd8 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Fri, 26 Feb 2021 16:45:50 +0100 Subject: [PATCH 06/31] Identify script handler in message event --- include/wx/webview.h | 7 +++++-- interface/wx/webview.h | 11 ++++++++++- samples/webview/webview.cpp | 2 +- src/osx/webview_webkit.mm | 4 +++- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/include/wx/webview.h b/include/wx/webview.h index 7771f4797b..987f3bdb1f 100644 --- a/include/wx/webview.h +++ b/include/wx/webview.h @@ -270,9 +270,10 @@ public: wxWebViewEvent() {} wxWebViewEvent(wxEventType type, int id, const wxString& url, const wxString target, - wxWebViewNavigationActionFlags flags = wxWEBVIEW_NAV_ACTION_NONE) + wxWebViewNavigationActionFlags flags = wxWEBVIEW_NAV_ACTION_NONE, + const wxString& messageHandler = wxString()) : wxNotifyEvent(type, id), m_url(url), m_target(target), - m_actionFlags(flags) + m_actionFlags(flags), m_messageHandler(messageHandler) {} @@ -280,12 +281,14 @@ public: const wxString& GetTarget() const { return m_target; } wxWebViewNavigationActionFlags GetNavigationAction() const { return m_actionFlags; } + const wxString& GetMessageHandler() const { return m_messageHandler; } virtual wxEvent* Clone() const wxOVERRIDE { return new wxWebViewEvent(*this); } private: wxString m_url; wxString m_target; wxWebViewNavigationActionFlags m_actionFlags; + wxString m_messageHandler; wxDECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxWebViewEvent); }; diff --git a/interface/wx/webview.h b/interface/wx/webview.h index dced7e269a..942bcf845e 100644 --- a/interface/wx/webview.h +++ b/interface/wx/webview.h @@ -1111,7 +1111,8 @@ public: wxWebViewEvent(); wxWebViewEvent(wxEventType type, int id, const wxString href, const wxString target, - wxWebViewNavigationActionFlags flags = wxWEBVIEW_NAV_ACTION_NONE); + wxWebViewNavigationActionFlags flags = wxWEBVIEW_NAV_ACTION_NONE, + const wxString& messageHandler = wxString()); /** Get the name of the target frame which the url of this event @@ -1132,6 +1133,14 @@ public: @since 3.1.2 */ wxWebViewNavigationActionFlags GetNavigationAction() const; + + /** + Get the name of the script handler. Only valid for events of type + @c wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED + + @since 3.1.5 + */ + const wxString& GetMessageHandler() const; }; diff --git a/samples/webview/webview.cpp b/samples/webview/webview.cpp index 792430b167..2084857801 100644 --- a/samples/webview/webview.cpp +++ b/samples/webview/webview.cpp @@ -910,7 +910,7 @@ void WebFrame::OnFullScreenChanged(wxWebViewEvent & evt) void WebFrame::OnScriptMessage(wxWebViewEvent& evt) { - wxLogMessage("Script message recieved; value = %s", evt.GetString()); + wxLogMessage("Script message recieved; value = %s, handler = %s", evt.GetString(), evt.GetMessageHandler()); } void WebFrame::OnSetPage(wxCommandEvent& WXUNUSED(evt)) diff --git a/src/osx/webview_webkit.mm b/src/osx/webview_webkit.mm index 56647b98ed..fe76d79883 100644 --- a/src/osx/webview_webkit.mm +++ b/src/osx/webview_webkit.mm @@ -923,7 +923,9 @@ WX_API_AVAILABLE_MACOS(10, 12) wxWebViewEvent event(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, webKitWindow->GetId(), webKitWindow->GetCurrentURL(), - ""); + "", + wxWEBVIEW_NAV_ACTION_NONE, + wxCFStringRef::AsString(message.name)); if ([message.body isKindOfClass:NSString.class]) event.SetString(wxCFStringRef::AsString(message.body)); else if ([message.body isKindOfClass:NSNumber.class]) From 04d22cc9f67955250efa3ce94e67f42a2fed95ad Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Fri, 26 Feb 2021 16:50:48 +0100 Subject: [PATCH 07/31] Add RemoveScriptMessage handler and return bool --- include/wx/osx/webview_webkit.h | 3 ++- include/wx/webview.h | 3 ++- src/osx/webview_webkit.mm | 9 ++++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/include/wx/osx/webview_webkit.h b/include/wx/osx/webview_webkit.h index 8b31ffdd34..e7900cfbb8 100644 --- a/include/wx/osx/webview_webkit.h +++ b/include/wx/osx/webview_webkit.h @@ -89,7 +89,8 @@ public: virtual bool IsEditable() const wxOVERRIDE; bool RunScript(const wxString& javascript, wxString* output = NULL) const wxOVERRIDE; - virtual void AddScriptMessageHandler(const wxString& name) wxOVERRIDE; + virtual bool AddScriptMessageHandler(const wxString& name) wxOVERRIDE; + virtual bool RemoveScriptMessageHandler(const wxString& name) wxOVERRIDE; //Virtual Filesystem Support virtual void RegisterHandler(wxSharedPtr handler) wxOVERRIDE; diff --git a/include/wx/webview.h b/include/wx/webview.h index 987f3bdb1f..aadba6bfc7 100644 --- a/include/wx/webview.h +++ b/include/wx/webview.h @@ -182,7 +182,8 @@ public: virtual void RegisterHandler(wxSharedPtr handler) = 0; virtual void Reload(wxWebViewReloadFlags flags = wxWEBVIEW_RELOAD_DEFAULT) = 0; virtual bool RunScript(const wxString& javascript, wxString* output = NULL) const = 0; - virtual void AddScriptMessageHandler(const wxString& WXUNUSED(name)) { } + virtual bool AddScriptMessageHandler(const wxString& WXUNUSED(name)) { return false; } + virtual bool RemoveScriptMessageHandler(const wxString& WXUNUSED(name)) { return false; } virtual void SetEditable(bool enable = true) = 0; void SetPage(const wxString& html, const wxString& baseUrl) { diff --git a/src/osx/webview_webkit.mm b/src/osx/webview_webkit.mm index fe76d79883..9e3abda81a 100644 --- a/src/osx/webview_webkit.mm +++ b/src/osx/webview_webkit.mm @@ -394,10 +394,17 @@ bool wxWebViewWebKit::RunScript(const wxString& javascript, wxString* output) co return true; } -void wxWebViewWebKit::AddScriptMessageHandler(const wxString& name) +bool wxWebViewWebKit::AddScriptMessageHandler(const wxString& name) { [m_webView.configuration.userContentController addScriptMessageHandler: [[WebViewScriptMessageHandler alloc] initWithWxWindow:this] name:wxCFStringRef(name).AsNSString()]; + return true; +} + +bool wxWebViewWebKit::RemoveScriptMessageHandler(const wxString& name) +{ + [m_webView.configuration.userContentController removeScriptMessageHandlerForName:wxCFStringRef(name).AsNSString()]; + return true; } void wxWebViewWebKit::LoadURL(const wxString& url) From 3f23273f46453b9360511ee66c542e185d1046da Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Fri, 26 Feb 2021 16:55:44 +0100 Subject: [PATCH 08/31] Fix typo in sample --- samples/webview/webview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/webview/webview.cpp b/samples/webview/webview.cpp index 2084857801..23ce490582 100644 --- a/samples/webview/webview.cpp +++ b/samples/webview/webview.cpp @@ -910,7 +910,7 @@ void WebFrame::OnFullScreenChanged(wxWebViewEvent & evt) void WebFrame::OnScriptMessage(wxWebViewEvent& evt) { - wxLogMessage("Script message recieved; value = %s, handler = %s", evt.GetString(), evt.GetMessageHandler()); + wxLogMessage("Script message received; value = %s, handler = %s", evt.GetString(), evt.GetMessageHandler()); } void WebFrame::OnSetPage(wxCommandEvent& WXUNUSED(evt)) From 302ae644ddd227446e9eb25943e717214f82c32c Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Fri, 26 Feb 2021 17:11:33 +0100 Subject: [PATCH 09/31] Fix mixed EOL --- src/msw/webview_edge.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/msw/webview_edge.cpp b/src/msw/webview_edge.cpp index 22846b93a4..439e177884 100644 --- a/src/msw/webview_edge.cpp +++ b/src/msw/webview_edge.cpp @@ -319,7 +319,7 @@ HRESULT wxWebViewEdgeImpl::OnContainsFullScreenElementChanged(ICoreWebView2* WXU return S_OK; } -HRESULT wxWebViewEdgeImpl::OnWebMessageReceived(ICoreWebView2* WXUNUSED(sender), ICoreWebView2WebMessageReceivedEventArgs* args) +HRESULT wxWebViewEdgeImpl::OnWebMessageReceived(ICoreWebView2* WXUNUSED(sender), ICoreWebView2WebMessageReceivedEventArgs* args) { wxCoTaskMemPtr msgContent; @@ -329,8 +329,8 @@ HRESULT wxWebViewEdgeImpl::OnWebMessageReceived(ICoreWebView2* WXUNUSED(sender), if (SUCCEEDED(args->get_WebMessageAsJson(&msgContent))) event.SetString(wxString(msgContent)); m_ctrl->HandleWindowEvent(event); - - return S_OK; + + return S_OK; } HRESULT wxWebViewEdgeImpl::OnWebViewCreated(HRESULT result, ICoreWebView2Controller* webViewController) From 3af4702b119b3d81bb915b5c03ad0c03c4271332 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Fri, 26 Feb 2021 18:49:30 +0100 Subject: [PATCH 10/31] Implement wxWebView::EnableAccessToDevTools() for GTK --- include/wx/gtk/webview_webkit.h | 2 ++ interface/wx/webview.h | 2 +- src/gtk/webview_webkit2.cpp | 12 ++++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/include/wx/gtk/webview_webkit.h b/include/wx/gtk/webview_webkit.h index ed375d3a39..4a757b2112 100644 --- a/include/wx/gtk/webview_webkit.h +++ b/include/wx/gtk/webview_webkit.h @@ -78,6 +78,8 @@ public: virtual wxString GetPageText() const wxOVERRIDE; virtual void Print() wxOVERRIDE; virtual bool IsBusy() const wxOVERRIDE; + virtual void EnableAccessToDevTools(bool enable = true) wxOVERRIDE; + virtual bool IsAccessToDevToolsEnabled() const wxOVERRIDE; void SetZoomType(wxWebViewZoomType) wxOVERRIDE; wxWebViewZoomType GetZoomType() const wxOVERRIDE; diff --git a/interface/wx/webview.h b/interface/wx/webview.h index 942bcf845e..d7be072476 100644 --- a/interface/wx/webview.h +++ b/interface/wx/webview.h @@ -776,7 +776,7 @@ public: Enable or disable access to dev tools for the user. This is currently only implemented for the Edge (Chromium) backend - where the dev tools are enabled by default. + where the dev tools are enabled by default and the WebKit2GTK+ backend. @since 3.1.4 */ diff --git a/src/gtk/webview_webkit2.cpp b/src/gtk/webview_webkit2.cpp index da4aae46df..f1207bf072 100644 --- a/src/gtk/webview_webkit2.cpp +++ b/src/gtk/webview_webkit2.cpp @@ -698,6 +698,18 @@ float wxWebViewWebKit::GetWebkitZoom() const return webkit_web_view_get_zoom_level(m_web_view); } +void wxWebViewWebKit::EnableAccessToDevTools(bool enable) +{ + WebKitSettings* settings = webkit_web_view_get_settings(m_web_view); + webkit_settings_set_enable_developer_extras(settings, enable); +} + +bool wxWebViewWebKit::IsAccessToDevToolsEnabled() const +{ + WebKitSettings* settings = webkit_web_view_get_settings(m_web_view); + return webkit_settings_get_enable_developer_extras(settings); +} + void wxWebViewWebKit::Stop() { webkit_web_view_stop_loading(m_web_view); From 71f745e64782c28edb637edafca26c456d929d2e Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Fri, 26 Feb 2021 21:27:50 +0100 Subject: [PATCH 11/31] Implement script message for GTK backend --- include/wx/gtk/webview_webkit.h | 2 + src/gtk/webview_webkit2.cpp | 91 +++++++++++++++++++++++---------- 2 files changed, 67 insertions(+), 26 deletions(-) diff --git a/include/wx/gtk/webview_webkit.h b/include/wx/gtk/webview_webkit.h index 4a757b2112..f207226a59 100644 --- a/include/wx/gtk/webview_webkit.h +++ b/include/wx/gtk/webview_webkit.h @@ -117,6 +117,8 @@ public: virtual void ClearSelection() wxOVERRIDE; virtual bool RunScript(const wxString& javascript, wxString* output = NULL) const wxOVERRIDE; + virtual bool AddScriptMessageHandler(const wxString& name) wxOVERRIDE; + virtual bool RemoveScriptMessageHandler(const wxString& name) wxOVERRIDE; //Virtual Filesystem Support virtual void RegisterHandler(wxSharedPtr handler) wxOVERRIDE; diff --git a/src/gtk/webview_webkit2.cpp b/src/gtk/webview_webkit2.cpp index f1207bf072..78fb1a56c5 100644 --- a/src/gtk/webview_webkit2.cpp +++ b/src/gtk/webview_webkit2.cpp @@ -31,6 +31,37 @@ #include #include +// Helper function to get string from Webkit JS result +bool wxGetStringFromJSResult(WebKitJavascriptResult* js_result, wxString* output) +{ + JSGlobalContextRef context = webkit_javascript_result_get_global_context(js_result); + JSValueRef value = webkit_javascript_result_get_value(js_result); + + JSValueRef exception = NULL; + wxJSStringRef js_value + ( + JSValueIsObject(context, value) + ? JSValueCreateJSONString(context, value, 0, &exception) + : JSValueToStringCopy(context, value, &exception) + ); + + if ( exception ) + { + if ( output ) + { + wxJSStringRef ex_value(JSValueToStringCopy(context, exception, NULL)); + *output = ex_value.ToWxString(); + } + + return false; + } + + if ( output != NULL ) + *output = js_value.ToWxString(); + + return true; +} + // ---------------------------------------------------------------------------- // GTK callbacks // ---------------------------------------------------------------------------- @@ -290,6 +321,21 @@ wxgtk_webview_webkit_leave_fullscreen(WebKitWebView *WXUNUSED(web_view), return FALSE; } +static void +wxgtk_webview_webkit_script_message_received(WebKitUserContentManager *WXUNUSED(content_manager), + WebKitJavascriptResult *js_result, + wxWebViewWebKit *webKitCtrl) +{ + wxWebViewEvent event(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, + webKitCtrl->GetId(), + webKitCtrl->GetCurrentURL(), + ""); + wxString msgStr; + if (wxGetStringFromJSResult(js_result, &msgStr)) + event.SetString(msgStr); + webKitCtrl->HandleWindowEvent(event); +} + static gboolean wxgtk_webview_webkit_decide_policy(WebKitWebView *web_view, WebKitPolicyDecision *decision, @@ -1221,32 +1267,7 @@ bool wxWebViewWebKit::RunScriptSync(const wxString& javascript, wxString* output return false; } - JSGlobalContextRef context = webkit_javascript_result_get_global_context(js_result); - JSValueRef value = webkit_javascript_result_get_value(js_result); - - JSValueRef exception = NULL; - wxJSStringRef js_value - ( - JSValueIsObject(context, value) - ? JSValueCreateJSONString(context, value, 0, &exception) - : JSValueToStringCopy(context, value, &exception) - ); - - if ( exception ) - { - if ( output ) - { - wxJSStringRef ex_value(JSValueToStringCopy(context, exception, NULL)); - *output = ex_value.ToWxString(); - } - - return false; - } - - if ( output != NULL ) - *output = js_value.ToWxString(); - - return true; + return wxGetStringFromJSResult(js_result, output); } bool wxWebViewWebKit::RunScript(const wxString& javascript, wxString* output) const @@ -1278,6 +1299,24 @@ bool wxWebViewWebKit::RunScript(const wxString& javascript, wxString* output) co return true; } +bool wxWebViewWebKit::AddScriptMessageHandler(const wxString& name) +{ + if (!m_web_view) + return false; + + WebKitUserContentManager *ucm = webkit_web_view_get_user_content_manager(m_web_view); + g_signal_connect(ucm, wxString::Format("script-message-received::%s", name).utf8_str(), + G_CALLBACK(wxgtk_webview_webkit_script_message_received), this); + return webkit_user_content_manager_register_script_message_handler(ucm, name.utf8_str()); +} + +bool wxWebViewWebKit::RemoveScriptMessageHandler(const wxString& name) +{ + WebKitUserContentManager *ucm = webkit_web_view_get_user_content_manager(m_web_view); + webkit_user_content_manager_unregister_script_message_handler(ucm, name.utf8_str()); + return true; +} + void wxWebViewWebKit::RegisterHandler(wxSharedPtr handler) { m_handlerList.push_back(handler); From a09713de5f3bfd5255f2241f628366d9e1c4b5f8 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Fri, 26 Feb 2021 21:37:23 +0100 Subject: [PATCH 12/31] Decode web message result like RunScript() result --- src/msw/webview_edge.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/msw/webview_edge.cpp b/src/msw/webview_edge.cpp index 439e177884..3e0414b68b 100644 --- a/src/msw/webview_edge.cpp +++ b/src/msw/webview_edge.cpp @@ -319,15 +319,31 @@ HRESULT wxWebViewEdgeImpl::OnContainsFullScreenElementChanged(ICoreWebView2* WXU return S_OK; } -HRESULT wxWebViewEdgeImpl::OnWebMessageReceived(ICoreWebView2* WXUNUSED(sender), ICoreWebView2WebMessageReceivedEventArgs* args) +HRESULT +wxWebViewEdgeImpl::OnWebMessageReceived(ICoreWebView2* WXUNUSED(sender), + ICoreWebView2WebMessageReceivedEventArgs* args) { wxCoTaskMemPtr msgContent; + HRESULT hr = args->get_WebMessageAsJson(&msgContent); + if (FAILED(hr)) + { + wxLogApiError("get_WebMessageAsJson", hr); + return hr; + } + wxWebViewEvent event(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, m_ctrl->GetId(), m_ctrl->GetCurrentURL(), wxString()); event.SetEventObject(m_ctrl); - if (SUCCEEDED(args->get_WebMessageAsJson(&msgContent))) - event.SetString(wxString(msgContent)); + + // Try to decode JSON string or return original + // result if it's not a valid JSON string + wxString msgStr; + wxString msgJson(msgContent); + if (!wxJSON::DecodeString(msgJson, &msgStr)) + msgStr = msgJson; + event.SetString(msgStr); + m_ctrl->HandleWindowEvent(event); return S_OK; From 140e9825b72bbaec3f82277cb0b1bdb1bb3cad94 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Fri, 26 Feb 2021 21:41:02 +0100 Subject: [PATCH 13/31] Log error if script handler cannot be added --- samples/webview/webview.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/samples/webview/webview.cpp b/samples/webview/webview.cpp index 23ce490582..0b39fb6186 100644 --- a/samples/webview/webview.cpp +++ b/samples/webview/webview.cpp @@ -399,7 +399,6 @@ WebFrame::WebFrame(const wxString& url) : m_browser->RegisterHandler(wxSharedPtr(new wxWebViewFSHandler("memory"))); #endif m_browser->Create(this, wxID_ANY, url, wxDefaultPosition, wxDefaultSize); - m_browser->AddScriptMessageHandler("wx"); topsizer->Add(m_browser, wxSizerFlags().Expand().Proportion(1)); #ifndef __WXMAC__ @@ -408,6 +407,8 @@ WebFrame::WebFrame(const wxString& url) : //And the memory: file system m_browser->RegisterHandler(wxSharedPtr(new wxWebViewFSHandler("memory"))); #endif + if (!m_browser->AddScriptMessageHandler("wx")) + wxLogError("Could not add script message handler"); SetSizer(topsizer); From 2d007ff3f17d4ca477680c01035e3805d22e3c76 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Fri, 26 Feb 2021 21:51:15 +0100 Subject: [PATCH 14/31] Add named script handler to edge --- include/wx/msw/private/webview_edge.h | 1 + include/wx/msw/webview_edge.h | 2 ++ src/msw/webview_edge.cpp | 29 ++++++++++++++++++++++++++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/include/wx/msw/private/webview_edge.h b/include/wx/msw/private/webview_edge.h index bb5063807e..99d91a7a9d 100644 --- a/include/wx/msw/private/webview_edge.h +++ b/include/wx/msw/private/webview_edge.h @@ -38,6 +38,7 @@ public: wxString m_pendingURL; int m_pendingContextMenuEnabled; int m_pendingAccessToDevToolsEnabled; + wxString m_scriptMsgHandlerName; // WebView Events tokens EventRegistrationToken m_navigationStartingToken = { }; diff --git a/include/wx/msw/webview_edge.h b/include/wx/msw/webview_edge.h index ffd54f2077..4df68bff9a 100644 --- a/include/wx/msw/webview_edge.h +++ b/include/wx/msw/webview_edge.h @@ -90,6 +90,8 @@ public: virtual bool IsAccessToDevToolsEnabled() const wxOVERRIDE; virtual bool RunScript(const wxString& javascript, wxString* output = NULL) const wxOVERRIDE; + virtual bool AddScriptMessageHandler(const wxString& name) wxOVERRIDE; + virtual bool RemoveScriptMessageHandler(const wxString& name) wxOVERRIDE; virtual void RegisterHandler(wxSharedPtr handler) wxOVERRIDE; diff --git a/src/msw/webview_edge.cpp b/src/msw/webview_edge.cpp index 3e0414b68b..647ecffd48 100644 --- a/src/msw/webview_edge.cpp +++ b/src/msw/webview_edge.cpp @@ -333,7 +333,8 @@ wxWebViewEdgeImpl::OnWebMessageReceived(ICoreWebView2* WXUNUSED(sender), } wxWebViewEvent event(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, m_ctrl->GetId(), - m_ctrl->GetCurrentURL(), wxString()); + m_ctrl->GetCurrentURL(), wxString(), + wxWEBVIEW_NAV_ACTION_NONE, m_scriptMsgHandlerName); event.SetEventObject(m_ctrl); // Try to decode JSON string or return original @@ -417,7 +418,10 @@ HRESULT wxWebViewEdgeImpl::OnWebViewCreated(HRESULT result, ICoreWebView2Control wxCOMPtr settings(GetSettings()); if (settings) + { settings->put_IsStatusBarEnabled(false); + settings->put_IsWebMessageEnabled(!m_scriptMsgHandlerName.empty()); + } if (!m_pendingURL.empty()) { @@ -807,6 +811,29 @@ bool wxWebViewEdge::RunScript(const wxString& javascript, wxString* output) cons return true; } +bool wxWebViewEdge::AddScriptMessageHandler(const wxString& name) +{ + // Edge only supports a single message handler + if (!m_impl->m_scriptMsgHandlerName.empty()) + return false; + + m_impl->m_scriptMsgHandlerName = name; + wxCOMPtr settings(m_impl->GetSettings()); + if (settings) + settings->put_IsWebMessageEnabled(true); + + return true; +} + +bool wxWebViewEdge::RemoveScriptMessageHandler(const wxString& WXUNUSED(name)) +{ + m_impl->m_scriptMsgHandlerName.clear(); + wxCOMPtr settings(m_impl->GetSettings()); + if (settings) + settings->put_IsWebMessageEnabled(false); + return true; +} + void wxWebViewEdge::RegisterHandler(wxSharedPtr handler) { // TODO: could maybe be implemented via IWebView2WebView5::add_WebResourceRequested From b1d558a61204104fe47714c52667a199705463f4 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Fri, 26 Feb 2021 21:55:10 +0100 Subject: [PATCH 15/31] Disabled dev tools per default for Edge This unifies the behavior among backends and is probably the more useful default for most applications. --- interface/wx/webview.h | 4 ++-- src/msw/webview_edge.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/wx/webview.h b/interface/wx/webview.h index d7be072476..e510ed0654 100644 --- a/interface/wx/webview.h +++ b/interface/wx/webview.h @@ -775,8 +775,8 @@ public: /** Enable or disable access to dev tools for the user. - This is currently only implemented for the Edge (Chromium) backend - where the dev tools are enabled by default and the WebKit2GTK+ backend. + This is currently only implemented for the Edge (Chromium) backend and + the WebKit2GTK+ backend. Dev tools are disabled by default. @since 3.1.4 */ diff --git a/src/msw/webview_edge.cpp b/src/msw/webview_edge.cpp index 647ecffd48..8e3336dfe8 100644 --- a/src/msw/webview_edge.cpp +++ b/src/msw/webview_edge.cpp @@ -82,7 +82,7 @@ bool wxWebViewEdgeImpl::Create() m_initialized = false; m_isBusy = false; m_pendingContextMenuEnabled = -1; - m_pendingAccessToDevToolsEnabled = -1; + m_pendingAccessToDevToolsEnabled = 0; m_historyLoadingFromList = false; m_historyEnabled = true; From f2bfa7d4465e1338ed5cdb024ae091b04d884186 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Fri, 26 Feb 2021 22:35:49 +0100 Subject: [PATCH 16/31] Initial AddScriptMessageHandler() documentation --- interface/wx/webview.h | 84 ++++++++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 27 deletions(-) diff --git a/interface/wx/webview.h b/interface/wx/webview.h index e510ed0654..28682e90d6 100644 --- a/interface/wx/webview.h +++ b/interface/wx/webview.h @@ -435,7 +435,8 @@ public: and is only available in wxWidgets 3.1.5 or later. @event{EVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED} Process a @c wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED event - only available in wxWidgets 3.1.5 or later. + only available in wxWidgets 3.1.5 or later for usage details see + AddScriptMessageHandler(). @endEventTable @since 2.9.3 @@ -612,6 +613,44 @@ public: */ virtual void Reload(wxWebViewReloadFlags flags = wxWEBVIEW_RELOAD_DEFAULT) = 0; + /** + Set the editable property of the web control. Enabling allows the user + to edit the page even if the @c contenteditable attribute is not set. + The exact capabilities vary with the backend being used. + + @note This is not implemented on macOS. + */ + virtual void SetEditable(bool enable = true) = 0; + + /** + Set the displayed page source to the contents of the given string. + @param html The string that contains the HTML data to display. + @param baseUrl URL assigned to the HTML data, to be used to resolve + relative paths, for instance. + @note When using @c wxWEBVIEW_BACKEND_IE you must wait for the current + page to finish loading before calling SetPage(). The baseURL + parameter is not used in this backend and the edge backend. + */ + virtual void SetPage(const wxString& html, const wxString& baseUrl) = 0; + + /** + Set the displayed page source to the contents of the given stream. + @param html The stream to read HTML data from. + @param baseUrl URL assigned to the HTML data, to be used to resolve + relative paths, for instance. + */ + virtual void SetPage(wxInputStream& html, wxString baseUrl); + + /** + Stop the current page loading process, if any. + May trigger an error event of type @c wxWEBVIEW_NAV_ERR_USER_CANCELLED. + TODO: make @c wxWEBVIEW_NAV_ERR_USER_CANCELLED errors uniform across ports. + */ + virtual void Stop() = 0; + + /** + @name Scripting + */ /** Runs the given JavaScript code. @@ -673,39 +712,30 @@ public: virtual bool RunScript(const wxString& javascript, wxString* output = NULL) const = 0; /** - Set the editable property of the web control. Enabling allows the user - to edit the page even if the @c contenteditable attribute is not set. - The exact capabilities vary with the backend being used. + Add a script message handler with the given name. - @note This is not implemented on macOS. + @return @true if the handler could be added, @false if it could not be added. + + @see RemoveScriptMessageHandler() + + @note The Edge (Chromium) backend only supports a single message handler and + the IE backend does not support script message handlers. + + @since 3.1.5 */ - virtual void SetEditable(bool enable = true) = 0; + virtual bool AddScriptMessageHandler(const wxString& name); /** - Set the displayed page source to the contents of the given string. - @param html The string that contains the HTML data to display. - @param baseUrl URL assigned to the HTML data, to be used to resolve - relative paths, for instance. - @note When using @c wxWEBVIEW_BACKEND_IE you must wait for the current - page to finish loading before calling SetPage(). The baseURL - parameter is not used in this backend and the edge backend. - */ - virtual void SetPage(const wxString& html, const wxString& baseUrl) = 0; + Remove a script message handler with the given name that was previously added via + AddScriptMessageHandler(). - /** - Set the displayed page source to the contents of the given stream. - @param html The stream to read HTML data from. - @param baseUrl URL assigned to the HTML data, to be used to resolve - relative paths, for instance. - */ - virtual void SetPage(wxInputStream& html, wxString baseUrl); + @return @true if the handler could be removed, @false if it could not be removed. - /** - Stop the current page loading process, if any. - May trigger an error event of type @c wxWEBVIEW_NAV_ERR_USER_CANCELLED. - TODO: make @c wxWEBVIEW_NAV_ERR_USER_CANCELLED errors uniform across ports. + @see AddScriptMessageHandler() + + @since 3.1.5 */ - virtual void Stop() = 0; + virtual bool RemoveScriptMessageHandler(const wxString& name); /** @name Clipboard From 6f7ac6a934887bd6efa142e4263744f6c09b6659 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Fri, 26 Feb 2021 22:52:11 +0100 Subject: [PATCH 17/31] Add wxWebView::AddUserScript() This allows to inject javascript code across multiple pages --- include/wx/webview.h | 13 ++++++++++++ interface/wx/webview.h | 40 +++++++++++++++++++++++++++++++++++++ samples/webview/webview.cpp | 21 +++++++++++++++++++ 3 files changed, 74 insertions(+) diff --git a/include/wx/webview.h b/include/wx/webview.h index aadba6bfc7..732b612455 100644 --- a/include/wx/webview.h +++ b/include/wx/webview.h @@ -86,6 +86,12 @@ enum wxWebViewNavigationActionFlags wxWEBVIEW_NAV_ACTION_OTHER }; +enum wxWebViewUserScriptInjectionTime +{ + wxWEBVIEW_INJECT_AT_DOCUMENT_START, + wxWEBVIEW_INJECT_AT_DOCUMENT_END +}; + //Base class for custom scheme handlers class WXDLLIMPEXP_WEBVIEW wxWebViewHandler { @@ -181,9 +187,16 @@ public: virtual void Print() = 0; virtual void RegisterHandler(wxSharedPtr handler) = 0; virtual void Reload(wxWebViewReloadFlags flags = wxWEBVIEW_RELOAD_DEFAULT) = 0; + + // Script virtual bool RunScript(const wxString& javascript, wxString* output = NULL) const = 0; virtual bool AddScriptMessageHandler(const wxString& WXUNUSED(name)) { return false; } virtual bool RemoveScriptMessageHandler(const wxString& WXUNUSED(name)) { return false; } + virtual bool AddUserScript(const wxString& WXUNUSED(javascript), + wxWebViewUserScriptInjectionTime WXUNUSED(injectionTime) = wxWEBVIEW_INJECT_AT_DOCUMENT_START) + { return false; } + virtual void RemoveAllUserScripts() {} + virtual void SetEditable(bool enable = true) = 0; void SetPage(const wxString& html, const wxString& baseUrl) { diff --git a/interface/wx/webview.h b/interface/wx/webview.h index 28682e90d6..d736a1173f 100644 --- a/interface/wx/webview.h +++ b/interface/wx/webview.h @@ -107,6 +107,19 @@ enum wxWebViewNavigationActionFlags wxWEBVIEW_NAV_ACTION_OTHER }; +/** + Specifies at which place of documents an user script will be inserted. + + @since 3.1.5 +*/ +enum wxWebViewUserScriptInjectionTime +{ + /** Insert the code of the user script at the beginning of loaded documents. */ + wxWEBVIEW_INJECT_AT_DOCUMENT_START, + /** Insert the code of the user script at the end of the loaded documents. */ + wxWEBVIEW_INJECT_AT_DOCUMENT_END +}; + /** Internet Explorer emulation modes for wxWebViewIE. @@ -737,6 +750,33 @@ public: */ virtual bool RemoveScriptMessageHandler(const wxString& name); + /** + Injects the specified script into the webpage’s content. + + @param javascript The java script code to add + @param injectionTime Specifies when the script could will be + executed. + @return Returns true if the script was added successfully + + @note Please not that this is unsupported by the IE backend and + the Edge (Chromium) backend does only support wxWEBVIEW_INJECT_AT_DOCUMENT_START. + + @see RemoveAllUserScripts() + + @since 3.1.5 + */ + virtual bool AddUserScript(const wxString& javascript, + wxWebViewUserScriptInjectionTime injectionTime = wxWEBVIEW_INJECT_AT_DOCUMENT_START); + + /** + Removes all user scripts from the web view. + + @see AddUserScript() + + @since 3.1.5 + */ + virtual void RemoveAllUserScripts(); + /** @name Clipboard */ diff --git a/samples/webview/webview.cpp b/samples/webview/webview.cpp index 0b39fb6186..02441633a7 100644 --- a/samples/webview/webview.cpp +++ b/samples/webview/webview.cpp @@ -159,6 +159,7 @@ public: void OnRunScriptArrayWithEmulationLevel(wxCommandEvent& evt); #endif void OnRunScriptCustom(wxCommandEvent& evt); + void OnAddUserScript(wxCommandEvent& evt); void OnClearSelection(wxCommandEvent& evt); void OnDeleteSelection(wxCommandEvent& evt); void OnSelectAll(wxCommandEvent& evt); @@ -488,6 +489,7 @@ WebFrame::WebFrame(const wxString& url) : #endif m_script_custom = script_menu->Append(wxID_ANY, "Custom script"); m_tools_menu->AppendSubMenu(script_menu, _("Run Script")); + wxMenuItem* addUserScript = m_tools_menu->Append(wxID_ANY, _("Add user script")); //Selection menu wxMenu* selection = new wxMenu(); @@ -586,6 +588,7 @@ WebFrame::WebFrame(const wxString& url) : } #endif Bind(wxEVT_MENU, &WebFrame::OnRunScriptCustom, this, m_script_custom->GetId()); + Bind(wxEVT_MENU, &WebFrame::OnAddUserScript, this, addUserScript->GetId()); Bind(wxEVT_MENU, &WebFrame::OnClearSelection, this, m_selection_clear->GetId()); Bind(wxEVT_MENU, &WebFrame::OnDeleteSelection, this, m_selection_delete->GetId()); Bind(wxEVT_MENU, &WebFrame::OnSelectAll, this, selectall->GetId()); @@ -1198,6 +1201,24 @@ void WebFrame::OnRunScriptCustom(wxCommandEvent& WXUNUSED(evt)) return; RunScript(dialog.GetValue()); +} + +void WebFrame::OnAddUserScript(wxCommandEvent & WXUNUSED(evt)) +{ + wxString userScript = "window.wx_test_var = 'wxWidgets webview sample';"; + wxTextEntryDialog dialog + ( + this, + "Enter the JavaScript code to run as the initialization script that runs before any script in the HTML document.", + wxGetTextFromUserPromptStr, + userScript, + wxOK | wxCANCEL | wxCENTRE | wxTE_MULTILINE + ); + if (dialog.ShowModal() != wxID_OK) + return; + + if (!m_browser->AddUserScript(dialog.GetValue())) + wxLogError("Could not add user script"); } void WebFrame::OnClearSelection(wxCommandEvent& WXUNUSED(evt)) From 4d78437a77e4240c00e7b027386f0c4e7bafdc55 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Fri, 26 Feb 2021 23:24:00 +0100 Subject: [PATCH 18/31] Implement AddUserScript() for edge backend --- include/wx/msw/private/webview_edge.h | 3 ++ include/wx/msw/webview_edge.h | 3 ++ src/msw/webview_edge.cpp | 48 +++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/include/wx/msw/private/webview_edge.h b/include/wx/msw/private/webview_edge.h index 99d91a7a9d..7c5efcce51 100644 --- a/include/wx/msw/private/webview_edge.h +++ b/include/wx/msw/private/webview_edge.h @@ -38,6 +38,8 @@ public: wxString m_pendingURL; int m_pendingContextMenuEnabled; int m_pendingAccessToDevToolsEnabled; + wxVector m_pendingUserScripts; + wxVector m_userScriptIds; wxString m_scriptMsgHandlerName; // WebView Events tokens @@ -59,6 +61,7 @@ public: HRESULT OnContentLoading(ICoreWebView2* sender, ICoreWebView2ContentLoadingEventArgs* args); HRESULT OnContainsFullScreenElementChanged(ICoreWebView2* sender, IUnknown* args); HRESULT OnWebMessageReceived(ICoreWebView2* sender, ICoreWebView2WebMessageReceivedEventArgs* args); + HRESULT OnAddScriptToExecuteOnDocumentedCreatedCompleted(HRESULT errorCode, LPCWSTR id); HRESULT OnEnvironmentCreated(HRESULT result, ICoreWebView2Environment* environment); HRESULT OnWebViewCreated(HRESULT result, ICoreWebView2Controller* webViewController); diff --git a/include/wx/msw/webview_edge.h b/include/wx/msw/webview_edge.h index 4df68bff9a..6f233ec598 100644 --- a/include/wx/msw/webview_edge.h +++ b/include/wx/msw/webview_edge.h @@ -92,6 +92,9 @@ public: virtual bool RunScript(const wxString& javascript, wxString* output = NULL) const wxOVERRIDE; virtual bool AddScriptMessageHandler(const wxString& name) wxOVERRIDE; virtual bool RemoveScriptMessageHandler(const wxString& name) wxOVERRIDE; + virtual bool AddUserScript(const wxString& javascript, + wxWebViewUserScriptInjectionTime injectionTime = wxWEBVIEW_INJECT_AT_DOCUMENT_START) wxOVERRIDE; + virtual void RemoveAllUserScripts() wxOVERRIDE; virtual void RegisterHandler(wxSharedPtr handler) wxOVERRIDE; diff --git a/src/msw/webview_edge.cpp b/src/msw/webview_edge.cpp index 8e3336dfe8..600375da22 100644 --- a/src/msw/webview_edge.cpp +++ b/src/msw/webview_edge.cpp @@ -423,6 +423,14 @@ HRESULT wxWebViewEdgeImpl::OnWebViewCreated(HRESULT result, ICoreWebView2Control settings->put_IsWebMessageEnabled(!m_scriptMsgHandlerName.empty()); } + if (!m_pendingUserScripts.empty()) + { + for (wxVector::iterator it = m_pendingUserScripts.begin(); + it != m_pendingUserScripts.end(); ++it) + m_ctrl->AddUserScript(*it); + m_pendingUserScripts.clear(); + } + if (!m_pendingURL.empty()) { m_ctrl->LoadURL(m_pendingURL); @@ -834,6 +842,46 @@ bool wxWebViewEdge::RemoveScriptMessageHandler(const wxString& WXUNUSED(name)) return true; } +HRESULT wxWebViewEdgeImpl::OnAddScriptToExecuteOnDocumentedCreatedCompleted(HRESULT errorCode, LPCWSTR id) +{ + if (SUCCEEDED(errorCode)) + m_userScriptIds.push_back(id); + return S_OK; +} + +bool wxWebViewEdge::AddUserScript(const wxString& javascript, + wxWebViewUserScriptInjectionTime injectionTime) +{ + // Currently only AT_DOCUMENT_START is supported + if (injectionTime != wxWEBVIEW_INJECT_AT_DOCUMENT_START) + return false; + + if (m_impl->m_webView) + { + HRESULT hr = m_impl->m_webView->AddScriptToExecuteOnDocumentCreated(javascript.wc_str(), + Callback(m_impl, + &wxWebViewEdgeImpl::OnAddScriptToExecuteOnDocumentedCreatedCompleted).Get()); + if (FAILED(hr)) + return false; + } + else + m_impl->m_pendingUserScripts.push_back(javascript); + + return true; +} + +void wxWebViewEdge::RemoveAllUserScripts() +{ + m_impl->m_pendingUserScripts.clear(); + for (wxVector::iterator it = m_impl->m_userScriptIds.begin(); + it != m_impl->m_userScriptIds.end(); ++it) + { + HRESULT hr = m_impl->m_webView->RemoveScriptToExecuteOnDocumentCreated(it->wc_str()); + if (FAILED(hr)) + wxLogApiError("RemoveScriptToExecuteOnDocumentCreated", hr); + } +} + void wxWebViewEdge::RegisterHandler(wxSharedPtr handler) { // TODO: could maybe be implemented via IWebView2WebView5::add_WebResourceRequested From c9606d7b5a002fdf7fa6aeca100e28a464bcfb3c Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Sat, 27 Feb 2021 10:59:23 +0100 Subject: [PATCH 19/31] Implement AddUserScript() for GTK --- include/wx/gtk/webview_webkit.h | 3 +++ src/gtk/webview_webkit2.cpp | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/wx/gtk/webview_webkit.h b/include/wx/gtk/webview_webkit.h index f207226a59..d9e728b331 100644 --- a/include/wx/gtk/webview_webkit.h +++ b/include/wx/gtk/webview_webkit.h @@ -119,6 +119,9 @@ public: virtual bool RunScript(const wxString& javascript, wxString* output = NULL) const wxOVERRIDE; virtual bool AddScriptMessageHandler(const wxString& name) wxOVERRIDE; virtual bool RemoveScriptMessageHandler(const wxString& name) wxOVERRIDE; + virtual bool AddUserScript(const wxString& javascript, + wxWebViewUserScriptInjectionTime injectionTime = wxWEBVIEW_INJECT_AT_DOCUMENT_START) wxOVERRIDE; + virtual void RemoveAllUserScripts() wxOVERRIDE; //Virtual Filesystem Support virtual void RegisterHandler(wxSharedPtr handler) wxOVERRIDE; diff --git a/src/gtk/webview_webkit2.cpp b/src/gtk/webview_webkit2.cpp index 78fb1a56c5..3d61057b97 100644 --- a/src/gtk/webview_webkit2.cpp +++ b/src/gtk/webview_webkit2.cpp @@ -1317,6 +1317,29 @@ bool wxWebViewWebKit::RemoveScriptMessageHandler(const wxString& name) return true; } +bool wxWebViewWebKit::AddUserScript(const wxString& javascript, + wxWebViewUserScriptInjectionTime injectionTime) +{ + WebKitUserScript* userScript = webkit_user_script_new( + javascript.utf8_str(), + WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, + (injectionTime == wxWEBVIEW_INJECT_AT_DOCUMENT_START) ? + WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_START : WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END, + NULL, NULL + ); + WebKitUserContentManager *ucm = webkit_web_view_get_user_content_manager(m_web_view); + webkit_user_content_manager_add_script(ucm, userScript); + webkit_user_script_unref(userScript); + + return true; +} + +void wxWebViewWebKit::RemoveAllUserScripts() +{ + WebKitUserContentManager *ucm = webkit_web_view_get_user_content_manager(m_web_view); + webkit_user_content_manager_remove_all_scripts(ucm); +} + void wxWebViewWebKit::RegisterHandler(wxSharedPtr handler) { m_handlerList.push_back(handler); From 29bfcdfd5e3b1ad8f34885b2a022fdd1a4b4b313 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Sat, 27 Feb 2021 11:55:50 +0100 Subject: [PATCH 20/31] Add common web message identifier --- include/wx/msw/private/webview_edge.h | 2 ++ samples/webview/webview.cpp | 9 +++++++++ src/gtk/webview_webkit2.cpp | 12 +++++++++++- src/msw/webview_edge.cpp | 28 ++++++++++++++++++++------- 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/include/wx/msw/private/webview_edge.h b/include/wx/msw/private/webview_edge.h index 7c5efcce51..58d2f25908 100644 --- a/include/wx/msw/private/webview_edge.h +++ b/include/wx/msw/private/webview_edge.h @@ -75,6 +75,8 @@ public: ICoreWebView2Settings* GetSettings(); + void UpdateWebMessageHandler(); + static wxDynamicLibrary ms_loaderDll; static wxString ms_browserExecutableDir; static wxString ms_version; diff --git a/samples/webview/webview.cpp b/samples/webview/webview.cpp index 02441633a7..d78bbfe8d2 100644 --- a/samples/webview/webview.cpp +++ b/samples/webview/webview.cpp @@ -158,6 +158,7 @@ public: void OnRunScriptDateWithEmulationLevel(wxCommandEvent& evt); void OnRunScriptArrayWithEmulationLevel(wxCommandEvent& evt); #endif + void OnRunScriptMessage(wxCommandEvent& evt); void OnRunScriptCustom(wxCommandEvent& evt); void OnAddUserScript(wxCommandEvent& evt); void OnClearSelection(wxCommandEvent& evt); @@ -229,6 +230,7 @@ private: wxMenuItem* m_script_date_el; wxMenuItem* m_script_array_el; #endif + wxMenuItem* m_script_message; wxMenuItem* m_script_custom; wxMenuItem* m_selection_clear; wxMenuItem* m_selection_delete; @@ -487,6 +489,7 @@ WebFrame::WebFrame(const wxString& url) : m_script_array_el = script_menu->Append(wxID_ANY, "Return array changing emulation level"); } #endif + m_script_message = script_menu->Append(wxID_ANY, "Send script message"); m_script_custom = script_menu->Append(wxID_ANY, "Custom script"); m_tools_menu->AppendSubMenu(script_menu, _("Run Script")); wxMenuItem* addUserScript = m_tools_menu->Append(wxID_ANY, _("Add user script")); @@ -587,6 +590,7 @@ WebFrame::WebFrame(const wxString& url) : Bind(wxEVT_MENU, &WebFrame::OnRunScriptArrayWithEmulationLevel, this, m_script_array_el->GetId()); } #endif + Bind(wxEVT_MENU, &WebFrame::OnRunScriptMessage, this, m_script_message->GetId()); Bind(wxEVT_MENU, &WebFrame::OnRunScriptCustom, this, m_script_custom->GetId()); Bind(wxEVT_MENU, &WebFrame::OnAddUserScript, this, addUserScript->GetId()); Bind(wxEVT_MENU, &WebFrame::OnClearSelection, this, m_selection_clear->GetId()); @@ -1187,6 +1191,11 @@ void WebFrame::OnRunScriptArrayWithEmulationLevel(wxCommandEvent& WXUNUSED(evt)) } #endif +void WebFrame::OnRunScriptMessage(wxCommandEvent & evt) +{ + RunScript("window.wx.postMessage('This is a web message');"); +} + void WebFrame::OnRunScriptCustom(wxCommandEvent& WXUNUSED(evt)) { wxTextEntryDialog dialog diff --git a/src/gtk/webview_webkit2.cpp b/src/gtk/webview_webkit2.cpp index 3d61057b97..4ae910e5af 100644 --- a/src/gtk/webview_webkit2.cpp +++ b/src/gtk/webview_webkit2.cpp @@ -1307,7 +1307,17 @@ bool wxWebViewWebKit::AddScriptMessageHandler(const wxString& name) WebKitUserContentManager *ucm = webkit_web_view_get_user_content_manager(m_web_view); g_signal_connect(ucm, wxString::Format("script-message-received::%s", name).utf8_str(), G_CALLBACK(wxgtk_webview_webkit_script_message_received), this); - return webkit_user_content_manager_register_script_message_handler(ucm, name.utf8_str()); + bool res = webkit_user_content_manager_register_script_message_handler(ucm, name.utf8_str()); + if (res) + { + // Make webkit message handler available under common name + wxString js = wxString::Format("window.%s = window.webkit.messageHandlers.%s;", + name, name); + AddUserScript(js); + RunScript(js); + } + + return res; } bool wxWebViewWebKit::RemoveScriptMessageHandler(const wxString& name) diff --git a/src/msw/webview_edge.cpp b/src/msw/webview_edge.cpp index 600375da22..8bc4e2590a 100644 --- a/src/msw/webview_edge.cpp +++ b/src/msw/webview_edge.cpp @@ -420,8 +420,8 @@ HRESULT wxWebViewEdgeImpl::OnWebViewCreated(HRESULT result, ICoreWebView2Control if (settings) { settings->put_IsStatusBarEnabled(false); - settings->put_IsWebMessageEnabled(!m_scriptMsgHandlerName.empty()); } + UpdateWebMessageHandler(); if (!m_pendingUserScripts.empty()) { @@ -440,6 +440,24 @@ HRESULT wxWebViewEdgeImpl::OnWebViewCreated(HRESULT result, ICoreWebView2Control return S_OK; } +void wxWebViewEdgeImpl::UpdateWebMessageHandler() +{ + wxCOMPtr settings(GetSettings()); + if (!settings) + return; + + settings->put_IsWebMessageEnabled(!m_scriptMsgHandlerName.empty()); + + if (!m_scriptMsgHandlerName.empty()) + { + // Make edge message handler available under common name + wxString js = wxString::Format("window.%s = window.chrome.webview;", + m_scriptMsgHandlerName); + m_ctrl->AddUserScript(js); + m_webView->ExecuteScript(js.wc_str(), NULL); + } +} + ICoreWebView2Settings* wxWebViewEdgeImpl::GetSettings() { if (!m_webView) @@ -826,9 +844,7 @@ bool wxWebViewEdge::AddScriptMessageHandler(const wxString& name) return false; m_impl->m_scriptMsgHandlerName = name; - wxCOMPtr settings(m_impl->GetSettings()); - if (settings) - settings->put_IsWebMessageEnabled(true); + m_impl->UpdateWebMessageHandler(); return true; } @@ -836,9 +852,7 @@ bool wxWebViewEdge::AddScriptMessageHandler(const wxString& name) bool wxWebViewEdge::RemoveScriptMessageHandler(const wxString& WXUNUSED(name)) { m_impl->m_scriptMsgHandlerName.clear(); - wxCOMPtr settings(m_impl->GetSettings()); - if (settings) - settings->put_IsWebMessageEnabled(false); + m_impl->UpdateWebMessageHandler(); return true; } From a27f73367cab93dc47bcc5a76a170d437fbe522c Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Sun, 28 Feb 2021 19:55:19 +0100 Subject: [PATCH 21/31] Implement AddUserScript() for WKWebView backend --- include/wx/osx/webview_webkit.h | 3 +++ src/osx/webview_webkit.mm | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/include/wx/osx/webview_webkit.h b/include/wx/osx/webview_webkit.h index e7900cfbb8..3d95825b73 100644 --- a/include/wx/osx/webview_webkit.h +++ b/include/wx/osx/webview_webkit.h @@ -91,6 +91,9 @@ public: bool RunScript(const wxString& javascript, wxString* output = NULL) const wxOVERRIDE; virtual bool AddScriptMessageHandler(const wxString& name) wxOVERRIDE; virtual bool RemoveScriptMessageHandler(const wxString& name) wxOVERRIDE; + virtual bool AddUserScript(const wxString& javascript, + wxWebViewUserScriptInjectionTime injectionTime = wxWEBVIEW_INJECT_AT_DOCUMENT_START) wxOVERRIDE; + virtual void RemoveAllUserScripts() wxOVERRIDE; //Virtual Filesystem Support virtual void RegisterHandler(wxSharedPtr handler) wxOVERRIDE; diff --git a/src/osx/webview_webkit.mm b/src/osx/webview_webkit.mm index 9e3abda81a..4f64352a69 100644 --- a/src/osx/webview_webkit.mm +++ b/src/osx/webview_webkit.mm @@ -407,6 +407,23 @@ bool wxWebViewWebKit::RemoveScriptMessageHandler(const wxString& name) return true; } +bool wxWebViewWebKit::AddUserScript(const wxString& javascript, + wxWebViewUserScriptInjectionTime injectionTime) +{ + WKUserScript* userScript = + [[WKUserScript alloc] initWithSource:wxCFStringRef(javascript).AsNSString() + injectionTime:(injectionTime == wxWEBVIEW_INJECT_AT_DOCUMENT_START) ? + WKUserScriptInjectionTimeAtDocumentStart : WKUserScriptInjectionTimeAtDocumentEnd + forMainFrameOnly:NO]; + [m_webView.configuration.userContentController addUserScript:userScript]; + return true; +} + +void wxWebViewWebKit::RemoveAllUserScripts() +{ + [m_webView.configuration.userContentController removeAllUserScripts]; +} + void wxWebViewWebKit::LoadURL(const wxString& url) { [m_webView loadRequest:[NSURLRequest requestWithURL: From 2c3d179923c762830d3cb0845d270980c4454e36 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Sun, 28 Feb 2021 19:57:33 +0100 Subject: [PATCH 22/31] Implement common web message identifier for macOS --- src/osx/webview_webkit.mm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/osx/webview_webkit.mm b/src/osx/webview_webkit.mm index 4f64352a69..8dae40f8b8 100644 --- a/src/osx/webview_webkit.mm +++ b/src/osx/webview_webkit.mm @@ -398,6 +398,11 @@ bool wxWebViewWebKit::AddScriptMessageHandler(const wxString& name) { [m_webView.configuration.userContentController addScriptMessageHandler: [[WebViewScriptMessageHandler alloc] initWithWxWindow:this] name:wxCFStringRef(name).AsNSString()]; + // Make webkit message handler available under common name + wxString js = wxString::Format("window.%s = window.webkit.messageHandlers.%s;", + name, name); + AddUserScript(js); + RunScript(js); return true; } From 2a16638e2a177cf6306467a9d63c112ad606be4c Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Sun, 28 Feb 2021 20:01:27 +0100 Subject: [PATCH 23/31] Fix EOL issues --- samples/webview/webview.cpp | 14 +++++++------- src/msw/webview_edge.cpp | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/samples/webview/webview.cpp b/samples/webview/webview.cpp index d78bbfe8d2..f5459fe35b 100644 --- a/samples/webview/webview.cpp +++ b/samples/webview/webview.cpp @@ -1191,11 +1191,11 @@ void WebFrame::OnRunScriptArrayWithEmulationLevel(wxCommandEvent& WXUNUSED(evt)) } #endif -void WebFrame::OnRunScriptMessage(wxCommandEvent & evt) +void WebFrame::OnRunScriptMessage(wxCommandEvent & evt) { - RunScript("window.wx.postMessage('This is a web message');"); -} - + RunScript("window.wx.postMessage('This is a web message');"); +} + void WebFrame::OnRunScriptCustom(wxCommandEvent& WXUNUSED(evt)) { wxTextEntryDialog dialog @@ -1210,9 +1210,9 @@ void WebFrame::OnRunScriptCustom(wxCommandEvent& WXUNUSED(evt)) return; RunScript(dialog.GetValue()); -} - -void WebFrame::OnAddUserScript(wxCommandEvent & WXUNUSED(evt)) +} + +void WebFrame::OnAddUserScript(wxCommandEvent & WXUNUSED(evt)) { wxString userScript = "window.wx_test_var = 'wxWidgets webview sample';"; wxTextEntryDialog dialog diff --git a/src/msw/webview_edge.cpp b/src/msw/webview_edge.cpp index 8bc4e2590a..f464e3619e 100644 --- a/src/msw/webview_edge.cpp +++ b/src/msw/webview_edge.cpp @@ -440,7 +440,7 @@ HRESULT wxWebViewEdgeImpl::OnWebViewCreated(HRESULT result, ICoreWebView2Control return S_OK; } -void wxWebViewEdgeImpl::UpdateWebMessageHandler() +void wxWebViewEdgeImpl::UpdateWebMessageHandler() { wxCOMPtr settings(GetSettings()); if (!settings) @@ -856,11 +856,11 @@ bool wxWebViewEdge::RemoveScriptMessageHandler(const wxString& WXUNUSED(name)) return true; } -HRESULT wxWebViewEdgeImpl::OnAddScriptToExecuteOnDocumentedCreatedCompleted(HRESULT errorCode, LPCWSTR id) +HRESULT wxWebViewEdgeImpl::OnAddScriptToExecuteOnDocumentedCreatedCompleted(HRESULT errorCode, LPCWSTR id) { if (SUCCEEDED(errorCode)) m_userScriptIds.push_back(id); - return S_OK; + return S_OK; } bool wxWebViewEdge::AddUserScript(const wxString& javascript, From 575ae90d85a0a7ce83caa5aecf33da7ea166d3f5 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Sun, 28 Feb 2021 20:03:10 +0100 Subject: [PATCH 24/31] Fix trailing whitespace --- interface/wx/webview.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/wx/webview.h b/interface/wx/webview.h index d736a1173f..a46a3d177d 100644 --- a/interface/wx/webview.h +++ b/interface/wx/webview.h @@ -745,7 +745,7 @@ public: @return @true if the handler could be removed, @false if it could not be removed. @see AddScriptMessageHandler() - + @since 3.1.5 */ virtual bool RemoveScriptMessageHandler(const wxString& name); @@ -762,7 +762,7 @@ public: the Edge (Chromium) backend does only support wxWEBVIEW_INJECT_AT_DOCUMENT_START. @see RemoveAllUserScripts() - + @since 3.1.5 */ virtual bool AddUserScript(const wxString& javascript, @@ -772,7 +772,7 @@ public: Removes all user scripts from the web view. @see AddUserScript() - + @since 3.1.5 */ virtual void RemoveAllUserScripts(); From 166d7e2c83e706bb452a6f18489a1c99b9410ca5 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Sun, 28 Feb 2021 20:06:59 +0100 Subject: [PATCH 25/31] Fix unused warning in sample --- samples/webview/webview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/webview/webview.cpp b/samples/webview/webview.cpp index f5459fe35b..3bd20ac462 100644 --- a/samples/webview/webview.cpp +++ b/samples/webview/webview.cpp @@ -1191,7 +1191,7 @@ void WebFrame::OnRunScriptArrayWithEmulationLevel(wxCommandEvent& WXUNUSED(evt)) } #endif -void WebFrame::OnRunScriptMessage(wxCommandEvent & evt) +void WebFrame::OnRunScriptMessage(wxCommandEvent& WXUNUSED(evt)) { RunScript("window.wx.postMessage('This is a web message');"); } From d4a9ec2448ef4729c67c3358168099391ad70ee5 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Sun, 28 Feb 2021 20:14:38 +0100 Subject: [PATCH 26/31] Define unused parameters differently to improve intellisense --- include/wx/webview.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/include/wx/webview.h b/include/wx/webview.h index 732b612455..c300f72195 100644 --- a/include/wx/webview.h +++ b/include/wx/webview.h @@ -190,11 +190,13 @@ public: // Script virtual bool RunScript(const wxString& javascript, wxString* output = NULL) const = 0; - virtual bool AddScriptMessageHandler(const wxString& WXUNUSED(name)) { return false; } - virtual bool RemoveScriptMessageHandler(const wxString& WXUNUSED(name)) { return false; } - virtual bool AddUserScript(const wxString& WXUNUSED(javascript), - wxWebViewUserScriptInjectionTime WXUNUSED(injectionTime) = wxWEBVIEW_INJECT_AT_DOCUMENT_START) - { return false; } + virtual bool AddScriptMessageHandler(const wxString& name) + { wxUnusedVar(name); return false; } + virtual bool RemoveScriptMessageHandler(const wxString& name) + { wxUnusedVar(name); return false; } + virtual bool AddUserScript(const wxString& javascript, + wxWebViewUserScriptInjectionTime injectionTime = wxWEBVIEW_INJECT_AT_DOCUMENT_START) + { wxUnusedVar(javascript); wxUnusedVar(injectionTime); return false; } virtual void RemoveAllUserScripts() {} virtual void SetEditable(bool enable = true) = 0; From ca5133fff7acd036918d64d54059a70c47a09891 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Sun, 28 Feb 2021 20:41:49 +0100 Subject: [PATCH 27/31] Add usage documentation to wxWebView::AddScriptMessageHandler() --- interface/wx/webview.h | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/interface/wx/webview.h b/interface/wx/webview.h index a46a3d177d..15fd6b8dee 100644 --- a/interface/wx/webview.h +++ b/interface/wx/webview.h @@ -446,7 +446,7 @@ public: the page wants to enter or leave fullscreen. Use GetInt to get the status. Currently only implemented for the edge and WebKit2GTK+ backend and is only available in wxWidgets 3.1.5 or later. - @event{EVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED} + @event{EVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED(id, func)} Process a @c wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED event only available in wxWidgets 3.1.5 or later for usage details see AddScriptMessageHandler(). @@ -727,7 +727,29 @@ public: /** Add a script message handler with the given name. - @return @true if the handler could be added, @false if it could not be added. + To use the script message handler from javascript use + @c window..postMessage() where corresponds the the value + of the name parameter. The will be available to the application + via a @c wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED event. + + Sample C++ code receiving a script message: + @code + // Install message handler with the name wx_msg + m_webView->AddScriptMessageHandler('wx_msg'); + // Bind handler + m_webView->Bind(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, [](wxWebViewEvent& evt) { + wxLogMessage("Script message received; value = %s, handler = %s", evt.GetString(), evt.GetMessageHandler()); + }); + @endcode + + Sample javascript sending a script message: + @code + // Send sample message body + window.wx_msg.postMessage('This is a message body'); + @endcode + + @param name Name of the message handler that can be used from javascript + @return @true if the handler could be added, @false if it could not be added @see RemoveScriptMessageHandler() @@ -1167,6 +1189,10 @@ public: @event{EVT_WEBVIEW_TITLE_CHANGED(id, func)} Process a @c wxEVT_WEBVIEW_TITLE_CHANGED event, generated when the page title changes. Use GetString to get the title. + @event{EVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED(id, func)} + Process a @c wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED event + only available in wxWidgets 3.1.5 or later for usage details see + wxWebView::AddScriptMessageHandler(). @endEventTable @since 2.9.3 From f419240335a940d22b3865bcd1b36678badd46f3 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Sun, 28 Feb 2021 20:44:38 +0100 Subject: [PATCH 28/31] Add Apple transport security to wxWebView docs --- interface/wx/webview.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/interface/wx/webview.h b/interface/wx/webview.h index 15fd6b8dee..ca6cbba09a 100644 --- a/interface/wx/webview.h +++ b/interface/wx/webview.h @@ -387,6 +387,12 @@ public: systems on macOS 10.13+. In order to use handlers two-step creation has to be used and RegisterHandler() has to be called before Create(). + Starting with macOS 10.11 and iOS 9 an application cannot create unsecure + connections (this includes HTTP and unverified HTTPS). You have to include + additional fields in your Info.plist to enable such connections. + For further details see the documentation on NSAppTransportSecurity + here + @section async Asynchronous Notifications Many of the methods in wxWebView are asynchronous, i.e. they return From e8371824bdddc8783231bdf11f66a5b37013a19c Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Sun, 28 Feb 2021 20:48:01 +0100 Subject: [PATCH 29/31] Disable new methods for webkit1 --- include/wx/gtk/webview_webkit.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/wx/gtk/webview_webkit.h b/include/wx/gtk/webview_webkit.h index d9e728b331..0b9a1939f8 100644 --- a/include/wx/gtk/webview_webkit.h +++ b/include/wx/gtk/webview_webkit.h @@ -78,8 +78,10 @@ public: virtual wxString GetPageText() const wxOVERRIDE; virtual void Print() wxOVERRIDE; virtual bool IsBusy() const wxOVERRIDE; +#if wxUSE_WEBVIEW_WEBKIT2 virtual void EnableAccessToDevTools(bool enable = true) wxOVERRIDE; virtual bool IsAccessToDevToolsEnabled() const wxOVERRIDE; +#endif void SetZoomType(wxWebViewZoomType) wxOVERRIDE; wxWebViewZoomType GetZoomType() const wxOVERRIDE; @@ -117,11 +119,13 @@ public: virtual void ClearSelection() wxOVERRIDE; virtual bool RunScript(const wxString& javascript, wxString* output = NULL) const wxOVERRIDE; +#if wxUSE_WEBVIEW_WEBKIT2 virtual bool AddScriptMessageHandler(const wxString& name) wxOVERRIDE; virtual bool RemoveScriptMessageHandler(const wxString& name) wxOVERRIDE; virtual bool AddUserScript(const wxString& javascript, wxWebViewUserScriptInjectionTime injectionTime = wxWEBVIEW_INJECT_AT_DOCUMENT_START) wxOVERRIDE; virtual void RemoveAllUserScripts() wxOVERRIDE; +#endif //Virtual Filesystem Support virtual void RegisterHandler(wxSharedPtr handler) wxOVERRIDE; From 5a30bbe38fc55e1ab63300c94c6ea2e9d1d62eaf Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Sun, 28 Feb 2021 22:33:15 +0100 Subject: [PATCH 30/31] Apply suggestions from code review Co-authored-by: PB --- interface/wx/webview.h | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/interface/wx/webview.h b/interface/wx/webview.h index ca6cbba09a..ff5d289076 100644 --- a/interface/wx/webview.h +++ b/interface/wx/webview.h @@ -454,7 +454,7 @@ public: and is only available in wxWidgets 3.1.5 or later. @event{EVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED(id, func)} Process a @c wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED event - only available in wxWidgets 3.1.5 or later for usage details see + only available in wxWidgets 3.1.5 or later. For usage details see AddScriptMessageHandler(). @endEventTable @@ -755,7 +755,7 @@ public: @endcode @param name Name of the message handler that can be used from javascript - @return @true if the handler could be added, @false if it could not be added + @return @true if the handler could be added, @false if it could not be added. @see RemoveScriptMessageHandler() @@ -781,12 +781,11 @@ public: /** Injects the specified script into the webpage’s content. - @param javascript The java script code to add - @param injectionTime Specifies when the script could will be - executed. - @return Returns true if the script was added successfully + @param javascript The javascript code to add. + @param injectionTime Specifies when the script will be executed. + @return Returns true if the script was added successfully. - @note Please not that this is unsupported by the IE backend and + @note Please note that this is unsupported by the IE backend and the Edge (Chromium) backend does only support wxWEBVIEW_INJECT_AT_DOCUMENT_START. @see RemoveAllUserScripts() @@ -1197,7 +1196,7 @@ public: the page title changes. Use GetString to get the title. @event{EVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED(id, func)} Process a @c wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED event - only available in wxWidgets 3.1.5 or later for usage details see + only available in wxWidgets 3.1.5 or later. For usage details see wxWebView::AddScriptMessageHandler(). @endEventTable From 5e35e6c63582546c77fa2cfd5384ffdf39bdf46f Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Sun, 28 Feb 2021 22:38:09 +0100 Subject: [PATCH 31/31] Clear script ids in RemoveAllUserScripts() --- src/msw/webview_edge.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/msw/webview_edge.cpp b/src/msw/webview_edge.cpp index f464e3619e..8d7baddb69 100644 --- a/src/msw/webview_edge.cpp +++ b/src/msw/webview_edge.cpp @@ -887,13 +887,13 @@ bool wxWebViewEdge::AddUserScript(const wxString& javascript, void wxWebViewEdge::RemoveAllUserScripts() { m_impl->m_pendingUserScripts.clear(); - for (wxVector::iterator it = m_impl->m_userScriptIds.begin(); - it != m_impl->m_userScriptIds.end(); ++it) + for (auto& scriptId : m_impl->m_userScriptIds) { - HRESULT hr = m_impl->m_webView->RemoveScriptToExecuteOnDocumentCreated(it->wc_str()); + HRESULT hr = m_impl->m_webView->RemoveScriptToExecuteOnDocumentCreated(scriptId.wc_str()); if (FAILED(hr)) wxLogApiError("RemoveScriptToExecuteOnDocumentCreated", hr); } + m_impl->m_userScriptIds.clear(); } void wxWebViewEdge::RegisterHandler(wxSharedPtr handler)