Skip to content

Commit

Permalink
Queue wxWebViewEdge events to avoid difficult to debug bugs
Browse files Browse the repository at this point in the history
Using HandleWindowEvent() from the WebView2 event callbacks
is a common error source when user code does something blocking
like RunScript() or ShowModal().
Queue the events to prevent this where possible, in
wxEVT_WEBVIEW_NAVIGATING at least warn the developer instead
of hanging silently.

Closes wxWidgets#22834, wxWidgets#22744, wxWidgets#19075

(cherry picked from commit 0ace989)
  • Loading branch information
TcT2k committed Dec 8, 2022
1 parent af3db51 commit 9130216
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 8 deletions.
1 change: 1 addition & 0 deletions include/wx/msw/private/webview_edge.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class wxWebViewEdgeImpl

bool m_initialized;
bool m_isBusy;
bool m_inEventCallback;
wxString m_pendingURL;
wxString m_pendingPage;
int m_pendingContextMenuEnabled;
Expand Down
1 change: 1 addition & 0 deletions include/wx/msw/webview_edge.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class WXDLLIMPEXP_WEBVIEW wxWebViewEdge : public wxWebView

virtual bool SetUserAgent(const wxString& userAgent) wxOVERRIDE;

virtual bool RunScript(const wxString& javascript, wxString* output = NULL) const wxOVERRIDE;
virtual void RunScriptAsync(const wxString& javascript, void* clientData = NULL) const wxOVERRIDE;
virtual bool AddScriptMessageHandler(const wxString& name) wxOVERRIDE;
virtual bool RemoveScriptMessageHandler(const wxString& name) wxOVERRIDE;
Expand Down
30 changes: 22 additions & 8 deletions src/msw/webview_edge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "wx/filename.h"
#include "wx/module.h"
#include "wx/log.h"
#include "wx/scopeguard.h"
#include "wx/stdpaths.h"
#include "wx/thread.h"
#include "wx/tokenzr.h"
Expand Down Expand Up @@ -64,6 +65,10 @@ GetAvailableCoreWebView2BrowserVersionString_t wxGetAvailableCoreWebView2Browser
wxDynamicLibrary wxWebViewEdgeImpl::ms_loaderDll;
#endif // wxUSE_WEBVIEW_EDGE_STATIC

#define wxWEBVIEW_EDGE_EVENT_HANDLER_METHOD \
m_inEventCallback = true; \
wxON_BLOCK_EXIT_SET(m_inEventCallback, false);

wxString wxWebViewEdgeImpl::ms_browserExecutableDir;

wxWebViewEdgeImpl::wxWebViewEdgeImpl(wxWebViewEdge* webview):
Expand Down Expand Up @@ -91,6 +96,7 @@ bool wxWebViewEdgeImpl::Create()
{
m_initialized = false;
m_isBusy = false;
m_inEventCallback = false;
m_pendingContextMenuEnabled = -1;
m_pendingAccessToDevToolsEnabled = 0;

Expand Down Expand Up @@ -188,6 +194,7 @@ void wxWebViewEdgeImpl::UpdateBounds()

HRESULT wxWebViewEdgeImpl::OnNavigationStarting(ICoreWebView2* WXUNUSED(sender), ICoreWebView2NavigationStartingEventArgs* args)
{
wxWEBVIEW_EDGE_EVENT_HANDLER_METHOD
m_isBusy = true;
wxString evtURL;
wxCoTaskMemPtr<wchar_t> uri;
Expand All @@ -212,7 +219,7 @@ HRESULT wxWebViewEdgeImpl::OnSourceChanged(ICoreWebView2 * WXUNUSED(sender), ICo
// navigation within the current document, send apropriate events
wxWebViewEvent event(wxEVT_WEBVIEW_NAVIGATING, m_ctrl->GetId(), m_ctrl->GetCurrentURL(), wxString());
event.SetEventObject(m_ctrl);
m_ctrl->HandleWindowEvent(event);
m_ctrl->GetEventHandler()->AddPendingEvent(event);
OnNavigationCompleted(NULL, NULL);
OnDOMContentLoaded(NULL, NULL);
}
Expand Down Expand Up @@ -264,7 +271,7 @@ HRESULT wxWebViewEdgeImpl::OnNavigationCompleted(ICoreWebView2* WXUNUSED(sender)
}
}
if (!ignoreStatus)
m_ctrl->HandleWindowEvent(event);
m_ctrl->GetEventHandler()->AddPendingEvent(event);
}
else
{
Expand All @@ -287,7 +294,7 @@ HRESULT wxWebViewEdgeImpl::OnNavigationCompleted(ICoreWebView2* WXUNUSED(sender)
//Reset as we are done now
m_historyLoadingFromList = false;
wxWebViewEvent evt(wxEVT_WEBVIEW_NAVIGATED, m_ctrl->GetId(), uri, wxString());
m_ctrl->HandleWindowEvent(evt);
m_ctrl->GetEventHandler()->AddPendingEvent(evt);
}
return S_OK;
}
Expand All @@ -305,7 +312,7 @@ HRESULT wxWebViewEdgeImpl::OnNewWindowRequested(ICoreWebView2* WXUNUSED(sender),
navFlags = wxWEBVIEW_NAV_ACTION_USER;

wxWebViewEvent evt(wxEVT_WEBVIEW_NEWWINDOW, m_ctrl->GetId(), evtURL, wxString(), navFlags);
m_ctrl->HandleWindowEvent(evt);
m_ctrl->GetEventHandler()->AddPendingEvent(evt);
args->put_Handled(true);
return S_OK;
}
Expand All @@ -316,7 +323,7 @@ HRESULT wxWebViewEdgeImpl::OnDocumentTitleChanged(ICoreWebView2* WXUNUSED(sender
m_ctrl->GetId(), m_ctrl->GetCurrentURL(), "");
event.SetString(m_ctrl->GetCurrentTitle());
event.SetEventObject(m_ctrl);
m_ctrl->HandleWindowEvent(event);
m_ctrl->GetEventHandler()->AddPendingEvent(event);
return S_OK;
}

Expand All @@ -325,7 +332,7 @@ HRESULT wxWebViewEdgeImpl::OnDOMContentLoaded(ICoreWebView2* WXUNUSED(sender), I
wxWebViewEvent event(wxEVT_WEBVIEW_LOADED, m_ctrl->GetId(),
m_ctrl->GetCurrentURL(), "");
event.SetEventObject(m_ctrl);
m_ctrl->HandleWindowEvent(event);
m_ctrl->GetEventHandler()->AddPendingEvent(event);
return S_OK;
}

Expand All @@ -340,7 +347,7 @@ HRESULT wxWebViewEdgeImpl::OnContainsFullScreenElementChanged(ICoreWebView2* WXU
m_ctrl->GetCurrentURL(), wxString());
event.SetEventObject(m_ctrl);
event.SetInt(containsFullscreenEvent);
m_ctrl->HandleWindowEvent(event);
m_ctrl->GetEventHandler()->AddPendingEvent(event);

return S_OK;
}
Expand Down Expand Up @@ -371,7 +378,7 @@ wxWebViewEdgeImpl::OnWebMessageReceived(ICoreWebView2* WXUNUSED(sender),
msgStr = msgJson;
event.SetString(msgStr);

m_ctrl->HandleWindowEvent(event);
m_ctrl->GetEventHandler()->AddPendingEvent(event);

return S_OK;
}
Expand Down Expand Up @@ -849,6 +856,13 @@ void wxWebViewEdge::MSWSetBrowserExecutableDir(const wxString & path)
wxWebViewEdgeImpl::ms_browserExecutableDir = path;
}

bool wxWebViewEdge::RunScript(const wxString& javascript, wxString* output) const
{
wxCHECK_MSG(!m_impl->m_inEventCallback, false,
"RunScript() cannot be used during event callbacks. Consider using RunScriptAsync()");
return wxWebView::RunScript(javascript, output);
}

void wxWebViewEdge::RunScriptAsync(const wxString& javascript, void* clientData) const
{
if (!m_impl->m_webView)
Expand Down

0 comments on commit 9130216

Please sign in to comment.