Add wxWebView::RunScriptAsync()

This commit is contained in:
Tobias Taschner
2021-04-07 22:21:04 +02:00
committed by Tobias Taschner
parent cf6a947dab
commit e9dc74cb6d
4 changed files with 74 additions and 36 deletions

View File

@@ -88,7 +88,7 @@ public:
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;
virtual bool AddUserScript(const wxString& javascript,

View File

@@ -191,7 +191,8 @@ public:
virtual wxString GetUserAgent() const;
// Script
virtual bool RunScript(const wxString& javascript, wxString* output = NULL) const = 0;
virtual bool RunScript(const wxString& javascript, wxString* output = NULL) const;
virtual void RunScriptAsync(const wxString& javascript, void* clientData = NULL) const;
virtual bool AddScriptMessageHandler(const wxString& name)
{ wxUnusedVar(name); return false; }
virtual bool RemoveScriptMessageHandler(const wxString& name)
@@ -267,6 +268,9 @@ protected:
bool QueryCommandEnabled(const wxString& command) const;
void ExecCommand(const wxString& command);
void SendScriptResult(void* clientData, bool success,
const wxString& output) const;
// Count the number of calls to RunScript() in order to prevent
// the_same variable from being used twice in more than one call.
mutable int m_runScriptCount;
@@ -276,6 +280,8 @@ private:
static wxStringWebViewFactoryMap::iterator FindFactory(const wxString &backend);
bool m_showMenu;
mutable int m_syncScriptResult;
mutable wxString m_syncScriptOutput;
wxString m_findText;
static wxStringWebViewFactoryMap m_factoryMap;
@@ -319,6 +325,7 @@ wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_WEBVIEW, wxEVT_WEBVIEW_NEWWINDOW, wxWebVie
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);
wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_WEBVIEW, wxEVT_WEBVIEW_SCRIPT_RESULT, wxWebViewEvent);
typedef void (wxEvtHandler::*wxWebViewEventFunction)
(wxWebViewEvent&);

View File

@@ -50,6 +50,7 @@ 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);
wxDEFINE_EVENT( wxEVT_WEBVIEW_SCRIPT_RESULT, wxWebViewEvent);
wxStringWebViewFactoryMap wxWebView::m_factoryMap;
@@ -224,6 +225,51 @@ wxString wxWebView::GetUserAgent() const
return userAgent;
}
bool wxWebView::RunScript(const wxString& javascript, wxString* output) const
{
m_syncScriptResult = -1;
m_syncScriptOutput.Clear();
RunScriptAsync(javascript, (void*)this);
// Wait for script exection
while (m_syncScriptResult == -1)
wxYield();
if (m_syncScriptResult && output)
*output = m_syncScriptOutput;
return m_syncScriptResult == 1;
}
void wxWebView::RunScriptAsync(const wxString& WXUNUSED(javascript),
void* WXUNUSED(clientData)) const
{
wxLogError(_("RunScriptAsync not supported"));
}
void wxWebView::SendScriptResult(void* clientData, bool success,
const wxString& output) const
{
// If currently running sync RunScript() don't send an event, but use
// the scripts result directly
if (m_syncScriptResult == -1)
{
if (!success)
wxLogWarning(_("Error running JavaScript: %s"), output);
m_syncScriptOutput = output;
m_syncScriptResult = success;
}
else
{
wxWebViewEvent evt(wxEVT_WEBVIEW_SCRIPT_RESULT, GetId(), "", "",
wxWEBVIEW_NAV_ACTION_NONE);
evt.SetEventObject(const_cast<wxWebView*>(this));
evt.SetClientData(clientData);
evt.SetInt(success);
evt.SetString(output);
HandleWindowEvent(evt);
}
}
// static
wxWebView* wxWebView::New(const wxString& backend)
{

View File

@@ -831,61 +831,46 @@ void wxWebViewEdge::MSWSetBrowserExecutableDir(const wxString & path)
wxWebViewEdgeImpl::ms_browserExecutableDir = path;
}
bool wxWebViewEdge::RunScript(const wxString& javascript, wxString* output) const
void wxWebViewEdge::RunScriptAsync(const wxString& javascript, void* clientData) const
{
if (!m_impl->m_webView)
return false;
{
SendScriptResult(clientData, false, "");
return; // TODO: postpone execution
}
wxJSScriptWrapper wrapJS(javascript, wxJSScriptWrapper::JS_OUTPUT_STRING);
int scriptResult = -1;
wxString scriptOutput;
// Start script execution
HRESULT executionResult = m_impl->m_webView->ExecuteScript(wrapJS.GetWrappedCode().wc_str(), Callback<ICoreWebView2ExecuteScriptCompletedHandler>(
[&scriptResult, &executionResult, &scriptOutput](HRESULT error, PCWSTR result) -> HRESULT
[this, clientData](HRESULT error, PCWSTR result) -> HRESULT
{
// Handle script execution callback
if (error == S_OK)
{
scriptOutput.assign(result);
scriptResult = 1;
wxString scriptDecodedResult;
// Try to decode JSON string or return original
// result if it's not a valid JSON string
if (!wxJSON::DecodeString(result, &scriptDecodedResult))
scriptDecodedResult = result;
wxString scriptExtractedOutput;
bool success = wxJSScriptWrapper::ExtractOutput(scriptDecodedResult, &scriptExtractedOutput);
SendScriptResult(clientData, success, scriptExtractedOutput);
}
else
{
executionResult = error;
scriptResult = 0;
SendScriptResult(clientData, false, wxString::Format("%s (0x%08lx)",
wxSysErrorMsgStr(error), error));
}
return S_OK;
}).Get());
// Wait for script exection
while (scriptResult == -1)
wxYield();
if (FAILED(executionResult))
{
if (output)
output->Printf("%s (0x%08lx)", wxSysErrorMsgStr(executionResult), executionResult);
return false;
SendScriptResult(clientData, false, wxString::Format("%s (0x%08lx)",
wxSysErrorMsgStr(executionResult), executionResult));
}
wxString scriptDecodedResult;
// Try to decode JSON string or return original
// result if it's not a valid JSON string
if (!wxJSON::DecodeString(scriptOutput, &scriptDecodedResult))
scriptDecodedResult = scriptOutput;
wxString scriptExtractedOutput;
bool success = wxJSScriptWrapper::ExtractOutput(scriptDecodedResult, &scriptExtractedOutput);
if (!success)
wxLogWarning(_("Error running JavaScript: %s"), scriptExtractedOutput);
if (output)
*output = scriptDecodedResult;
return success;
}
bool wxWebViewEdge::AddScriptMessageHandler(const wxString& name)