Merge branch 'webview-js-retval'

Integrate GSoC 2017 work by Jose Lorenzo on allowing returning values
from JavaScript code via wxWebView::RunScript().
This commit is contained in:
Vadim Zeitlin
2017-11-04 14:33:42 +01:00
15 changed files with 931 additions and 49 deletions

View File

@@ -19,7 +19,13 @@
#include "wx/base64.h"
#include "wx/log.h"
#include "wx/gtk/private/webview_webkit2_extension.h"
#include "wx/gtk/private/string.h"
#include "wx/gtk/private/webkit.h"
#include "wx/gtk/private/error.h"
#include "wx/private/jsscriptwrapper.h"
#include <webkit2/webkit2.h>
#include <JavaScriptCore/JSValueRef.h>
#include <JavaScriptCore/JSStringRef.h>
// ----------------------------------------------------------------------------
// GTK callbacks
@@ -1098,13 +1104,112 @@ wxString wxWebViewWebKit::GetPageText() const
return wxString();
}
void wxWebViewWebKit::RunScript(const wxString& javascript)
extern "C"
{
static void wxgtk_run_javascript_cb(GObject *,
GAsyncResult *res,
void *user_data)
{
g_object_ref(res);
GAsyncResult** res_out = static_cast<GAsyncResult**>(user_data);
*res_out = res;
}
} // extern "C"
// Run the given script synchronously and return its result in output.
bool wxWebViewWebKit::RunScriptSync(const wxString& javascript, wxString* output)
{
GAsyncResult *result = NULL;
webkit_web_view_run_javascript(m_web_view,
javascript.mb_str(wxConvUTF8),
javascript.utf8_str(),
NULL,
NULL,
NULL);
wxgtk_run_javascript_cb,
&result);
GMainContext *main_context = g_main_context_get_thread_default();
while ( !result )
g_main_context_iteration(main_context, TRUE);
wxGtkError error;
wxWebKitJavascriptResult js_result
(
webkit_web_view_run_javascript_finish
(
m_web_view,
result,
error.Out()
)
);
// Match g_object_ref() in wxgtk_run_javascript_cb()
g_object_unref(result);
if ( !js_result )
{
if ( output )
*output = error.GetMessage();
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;
}
bool wxWebViewWebKit::RunScript(const wxString& javascript, wxString* output)
{
wxJSScriptWrapper wrapJS(javascript, &m_runScriptCount);
// This string is also used as an error indicator: it's cleared if there is
// no error or used in the warning message below if there is one.
wxString result;
if ( RunScriptSync(wrapJS.GetWrappedCode(), &result)
&& result == wxS("true") )
{
if ( RunScriptSync(wrapJS.GetOutputCode(), &result) )
{
if ( output )
*output = result;
result.clear();
}
RunScriptSync(wrapJS.GetCleanUpCode());
}
if ( !result.empty() )
{
wxLogWarning(_("Error running JavaScript: %s"), result);
return false;
}
return true;
}
void wxWebViewWebKit::RegisterHandler(wxSharedPtr<wxWebViewHandler> handler)