blob: 4bfe48b7e76b59233e6ae24cd81380f58651df03 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 Red Hat, Inc. All rights reserved.
* The contents of this file are made available under the terms
* of the GNU Lesser General Public License (LGPL) Version 2.1 that
* accompanies this distribution (lgpl-v21.txt). The LGPL is also
* available at http://www.gnu.org/licenses/lgpl.html. If the version
* of the LGPL at http://www.gnu.org is different to the version of
* the LGPL accompanying this distribution and there is any conflict
* between the two license versions, the terms of the LGPL accompanying
* this distribution shall govern.
*
* Contributors:
* Red Hat, Inc
*******************************************************************************/
/* Manually written code */
#include <stdbool.h>
#include <gio/gio.h> // For things like GAsyncResult
#include "swt.h" // For types like jintLong etc..
#include "webkitgtk.h" // For WebKitGTK_LOAD_FUNCTION macro and custom struct definitions.
#include "webkitgtk_custom.h"
#include "webkitgtk_stats.h" // for WebKitGTK_NATIVE_ENTER.
#include "webkitgtk_structs.h" // for struct setters/getters
/**
* Flag to indicate if function pointers are cached or not.
* 0 - not cached, need caching.
* 1 - cached.
* -1 - exception occured.
*/
int fps_cached = 0;
/** Dynamic Function pointer declarations */
dyn_WebKitJavascriptResult (*fp_webkit_web_view_run_javascript_finish) (dyn_WebKitWebView, GAsyncResult*, GError**);
dyn_JSGlobalContextRef (*fp_webkit_javascript_result_get_global_context)(dyn_WebKitJavascriptResult);
void (*fp_webkit_web_view_run_javascript) (dyn_WebKitWebView, const gchar * /*script*/, GCancellable*, GAsyncReadyCallback, gpointer /*user_data*/);
dyn_JSValueRef (*fp_webkit_javascript_result_get_value)(dyn_WebKitJavascriptResult);
#define INIT_WEBKIT_FP(function) \
{ \
WebKitGTK_LOAD_FUNCTION(fp, function); \
if (fp == NULL) { \
goto fail; \
} \
fp_##function = fp; \
}
void initFPs() {
INIT_WEBKIT_FP(webkit_web_view_run_javascript_finish);
INIT_WEBKIT_FP(webkit_javascript_result_get_global_context);
INIT_WEBKIT_FP(webkit_web_view_run_javascript);
INIT_WEBKIT_FP(webkit_javascript_result_get_value);
fps_cached = 1;
return;
fail:
fps_cached = -1;
g_critical("SWT webkitgtk_custom.c: Failed to load webkit function pointer(s)");
}
/*
Calling JS script and getting return value example copied and adapted to be dynamic from:
https://webkitgtk.org/reference/webkit2gtk/stable/WebKitWebView.html#webkit-web-view-run-javascript-finish
Type conversion occurs on Java side.
*/
static void
web_view_javascript_finished_callback (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
dyn_WebKitJavascriptResult js_result;
dyn_JSGlobalContextRef context;
dyn_JSValueRef value;
GError *error = NULL;
SWTJSreturnVal * swtjsreturnvalSTRUCT = (SWTJSreturnVal*) user_data;
js_result = fp_webkit_web_view_run_javascript_finish ((jintLong) object, result, &error);
if (!js_result) {
WEBKIT_DBG_MSG ("DEBUG: webkitgtk_custom.c: webkitgtk_custom.c: Error running javascript(1): %s", error->message);
swtjsreturnvalSTRUCT->returnType = 50; //SWT.java:ERROR_FAILED_EVALUATE
gchar *err_msg;
gsize err_msg_len = strlen(error->message);
err_msg = malloc(err_msg_len + 1);
strcpy(err_msg, error->message);
swtjsreturnvalSTRUCT->errorMsg = (jintLong) err_msg;
g_error_free (error);
} else {
WEBKIT_DBG_MSG ("DEBUG: webkitgtk_custom.c: webkitgtk_custom.c: Javascript execution yielded a value");
context = fp_webkit_javascript_result_get_global_context (js_result);
value = fp_webkit_javascript_result_get_value (js_result);
swtjsreturnvalSTRUCT->context = (jintLong) context;
swtjsreturnvalSTRUCT->value = (jintLong) value;
swtjsreturnvalSTRUCT->returnType = 1; // Return is a value to be converted.
swtjsreturnvalSTRUCT->jsResultPointer = (jintLong) js_result;
// Note: js_result is free up in WebKit.java:evalute().
}
// Note about exit points: this function must unlock the spinlock prior to returning.
// As such there should not be a 'return' in this function above the unlocking code
swtjsreturnvalSTRUCT->JsCallFinished = true;
}
/**
* Convert the async function webkit_web_view_run_javascript(..) into a synchronous one
* by spinning until the callback is completed.
*/
JNIEXPORT void Java_org_eclipse_swt_internal_webkit_WebKitGTK__1swtWebkitEvaluateJavascript
(JNIEnv *env, jclass that, jintLong webkit_handle, jbyteArray javascriptStringBytes, jobject swtjsreturnvalOBJ)
{
WebKitGTK_NATIVE_ENTER(env, that, _1swtWebkitEvaluateJavascript_FUNC); // For native stats tool.
if (fps_cached == 0)
initFPs();
if (fps_cached == -1)
return;
jbyte *cString = (*env)->GetByteArrayElements(env, javascriptStringBytes, NULL);
if (cString == NULL)
return; // Out of Memory
WEBKIT_DBG_MSG("DEBUG: C: Executing Script: %s", cString);
SWTJSreturnVal swtjsreturnvalSTRUCT;
swtjsreturnvalSTRUCT.JsCallFinished = false;
swtjsreturnvalSTRUCT.returnType = 0;
swtjsreturnvalSTRUCT.errorMsg = 0;
swtjsreturnvalSTRUCT.context = 0;
swtjsreturnvalSTRUCT.value = 0;
fp_webkit_web_view_run_javascript(webkit_handle,(const gchar *) cString, NULL, web_view_javascript_finished_callback, &swtjsreturnvalSTRUCT);
while (swtjsreturnvalSTRUCT.JsCallFinished == false) {
g_main_context_iteration(0, false);
}
setSWTJSreturnValFields(env,swtjsreturnvalOBJ, &swtjsreturnvalSTRUCT);
(*env)->ReleaseByteArrayElements(env, javascriptStringBytes, cString, 0);
WebKitGTK_NATIVE_EXIT(env, that, _1swtWebkitEvaluateJavascript_FUNC);
}