Skip to content

Commit

Permalink
Queue wxWebViewEdge events
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#22744, wxWidgets#19075
  • Loading branch information
TcT2k committed Sep 30, 2022
1 parent 6a10e04 commit b25e7e2
Show file tree
Hide file tree
Showing 3 changed files with 38 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 @@ -60,6 +60,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
44 changes: 36 additions & 8 deletions src/msw/webview_edge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,23 @@ class wxWebViewEdgeHandlerResponse : public wxWebViewHandlerResponse
wxCOMPtr<ICoreWebView2WebResourceRequestedEventArgs> m_args;
};

class wxWebViewImplCallbackActivator
{
public:
wxWebViewImplCallbackActivator(wxWebViewEdgeImpl* impl) :
m_impl(impl)
{
m_impl->m_inEventCallback = true;
}

~wxWebViewImplCallbackActivator()
{
m_impl->m_inEventCallback = false;
}

wxWebViewEdgeImpl* m_impl;
};

wxString wxWebViewEdgeImpl::ms_browserExecutableDir;

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

Expand Down Expand Up @@ -365,6 +383,7 @@ void wxWebViewEdgeImpl::UpdateBounds()

HRESULT wxWebViewEdgeImpl::OnNavigationStarting(ICoreWebView2* WXUNUSED(sender), ICoreWebView2NavigationStartingEventArgs* args)
{
wxWebViewImplCallbackActivator cbActivator(this);
m_isBusy = true;
wxString evtURL;
wxCoTaskMemPtr<wchar_t> uri;
Expand All @@ -389,7 +408,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 @@ -441,7 +460,7 @@ HRESULT wxWebViewEdgeImpl::OnNavigationCompleted(ICoreWebView2* WXUNUSED(sender)
}
}
if (!ignoreStatus)
m_ctrl->HandleWindowEvent(event);
m_ctrl->GetEventHandler()->AddPendingEvent(event);
}
else
{
Expand All @@ -464,7 +483,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 @@ -482,7 +501,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 @@ -493,7 +512,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 @@ -502,7 +521,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 @@ -517,7 +536,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 @@ -548,7 +567,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 @@ -1080,6 +1099,15 @@ void wxWebViewEdge::MSWSetBrowserExecutableDir(const wxString & path)
wxWebViewEdgeImpl::ms_browserExecutableDir = path;
}

bool wxWebViewEdge::RunScript(const wxString& javascript, wxString* output) const
{
if (m_impl->m_inEventCallback)
{
wxFAIL_MSG("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 b25e7e2

Please sign in to comment.