diff options
author | Lev Ufimtsev | 2016-08-04 19:13:18 +0000 |
---|---|---|
committer | Alexander Kurtakov | 2016-09-09 07:13:36 +0000 |
commit | 7003ce9e76832ab4cf8e13c1633c97edca922ae7 (patch) | |
tree | d4c2cc7a465b49142606ccfafe3d7e9630bbe3da /bundles/org.eclipse.swt/Eclipse SWT WebKit | |
parent | 03e505a39be2165463f88264099ee8921b2bb263 (diff) | |
download | eclipse.platform.swt-7003ce9e76832ab4cf8e13c1633c97edca922ae7.tar.gz eclipse.platform.swt-7003ce9e76832ab4cf8e13c1633c97edca922ae7.tar.xz eclipse.platform.swt-7003ce9e76832ab4cf8e13c1633c97edca922ae7.zip |
Bug 430538: [GTK3][webkit] Support Custom JavaScript execution in
WebKit2 mode of SWT Browser
Stage 1 - RADY FOR REVIEW.
Patch Set 1: 2016-08Aug-04Thu (pushed2Gerrit)
Implement return mechanism for webkit_*_run_javascript()
- Adding a webkitgtk_custom.c file for custom function
- modified linux_makefil for additional file
- cleanup of linux_makefile for webkit, (confusing target naming).
Patch Set 2: 2016-08Aug-08Mon (pushed2Gerrit)
- Implemented call to webkit
- Implemented spinlock and while loop to wait for callback
to finish. Spinlock is passed as pointer to callback.
Patch Set 3: (pushed2Gerrit)
- 2016-08Aug-08Mon - minor tweaks.
- 2016-08Aug-09Tue - renamed custom method/function name.
- 2016-08Aug-10Wed - fixed potential memory leak.
- 2016-08Aug-15Mon - Implemented conditional compilation for
build servers without webkit2gtk4
Patch Set 4:
2016-08Aug-30Tue
- Rewrite to call webkit functions dynamically instead of hard-linking
- removed pkg-config dependencies to webkitgtk
- Changed pkg-config webkit flags to use gio instead of glib.
Note, glib is a subset of gio, and gio is a subset of Gtk2/Gtk3,
thus this should not break anything.
Patchset 14:
- Adjusted comment in webkitgtk_custom.c
> Warning to future developers as it's not obvious. I did not know
until you pointed it out.
- Removed 'ifndef' from function swt_webkit_web_view_run_javascript
call. In hindsight, it doesn't look like it's necessary.
Things I've tested:
- Child Eclipse with webkit2 browser
- Browser tests: (fixes tests 3,4, 8).
- Various browser snippets.
To test yourself:
- To enable webkit2, set:
SWT_WEBKIT2=1
- Manual inspection via SWT-SNIPPET:
https://github.com/ericwill/SWT-snippets/blob/master/src/browser/Bug430538_JS_Set_Background.java
If you click the 'execute' button, now background is set.
(Note, other button 'evalute' not working yet).
- Browser8.java now passes and correctly executes JS
(enable verbose on line 30 to see before/after, now background
changes).
- Browser3.java now passes
Change-Id: I5a7b8ecb599de5ac30c2483f99d30f3a47995a64
Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=430538
Signed-off-by: Lev Ufimtsev <lufimtse@redhat.com>
Diffstat (limited to 'bundles/org.eclipse.swt/Eclipse SWT WebKit')
8 files changed, 195 insertions, 5 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk.c b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk.c index 87ead7f286..3947b5bfe3 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk.c +++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk.c @@ -1041,6 +1041,22 @@ JNIEXPORT jintLong JNICALL WebKitGTK_NATIVE(_1soup_1uri_1to_1string) } #endif +#ifndef NO__1swt_1webkit_1web_1view_1run_1javascript +JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(_1swt_1webkit_1web_1view_1run_1javascript) + (JNIEnv *env, jclass that, jintLong arg0, jbyteArray arg1) +{ + jbyte *lparg1=NULL; + jlong rc = 0; + WebKitGTK_NATIVE_ENTER(env, that, _1swt_1webkit_1web_1view_1run_1javascript_FUNC); + if (arg1) if ((lparg1 = (*env)->GetByteArrayElements(env, arg1, NULL)) == NULL) goto fail; + rc = (jlong)swt_webkit_web_view_run_javascript(arg0, lparg1); +fail: + if (arg1 && lparg1) (*env)->ReleaseByteArrayElements(env, arg1, lparg1, 0); + WebKitGTK_NATIVE_EXIT(env, that, _1swt_1webkit_1web_1view_1run_1javascript_FUNC); + return rc; +} +#endif + #ifndef NO__1webkit_1authentication_1request_1authenticate JNIEXPORT void JNICALL WebKitGTK_NATIVE(_1webkit_1authentication_1request_1authenticate) (JNIEnv *env, jclass that, jintLong arg0, jintLong arg1) diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk.h b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk.h index 8621fef9c3..00219cf811 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk.h +++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk.h @@ -12,7 +12,9 @@ * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ - + +/* Manually written code */ + #ifndef INC_webkitgtk_H #define INC_webkitgtk_H @@ -21,6 +23,9 @@ #include <stdlib.h> #include <glib-object.h> +// For JNI bindings in webkitgtk.c to properly link to custom functions: +#include "webkitgtk_custom.h" + #define WebKitGTK_LOAD_FUNCTION(var, name) \ static int initialized = 0; \ static void *var = NULL; \ diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_custom.c b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_custom.c new file mode 100644 index 0000000000..3b2f887377 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_custom.c @@ -0,0 +1,133 @@ +/******************************************************************************* +* 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 "webkitgtk_custom.h" +#include "webkitgtk.h" // For WebKitGTK_LOAD_FUNCTION macro +#include "swt.h" // For types like jintLong etc.. + +#include <gio/gio.h> // For things like GAsyncResult + + +// Note about webkit includes: +// Do not include things like '<webkit2/webkit2.h>' '<JavaScriptCore/JavaScript.h>' directly. +// All webkit functions must be loaded dynamically. +// If you compile on a newer Linux that contains Webkit2, trying to run the compiled binary on older +// OS's without webkit2 will lead to a crash even when they are running in 'Webkit1' mode. +// See Bug 430538. + + +/* + Calling JS script and getting return value example copied and adapted from: + https://webkitgtk.org/reference/webkit2gtk/stable/WebKitWebView.html#webkit-web-view-run-javascript-finish +*/ +static void +web_view_javascript_finished_callback (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + + //// TODO handling of return value to be implemented in Stage 2. + //// All webkit functions will need to be called dynamically. +// WebKitJavascriptResult *js_result; +// JSValueRef value; +// JSGlobalContextRef context; +// GError *error = NULL; +// +// +// js_result = webkit_web_view_run_javascript_finish (WEBKIT_WEB_VIEW (object), result, &error); +// if (!js_result) { +// // Recoverable runtime error: +// g_warning ("webkitgtk_custom.c: Error running javascript(1): %s", error->message); +// g_error_free (error); +// } else { +// context = webkit_javascript_result_get_global_context (js_result); +// value = webkit_javascript_result_get_value (js_result); +// +// +//// // TODO WEBKIT2 - handle various return value(s). Starter code below. +// // Idea: create struct with pointer to return value and lock; +// // then pass it along via user_data. NOTE *malloc it* +// +// // Supress compiler warnings till return types implemented. +// (void) value; +// (void) context; +// +//// if (JSValueIsString (context, value)) { +//// JSStringRef js_str_value; +//// gchar *str_value; +//// gsize str_length; +//// +//// js_str_value = JSValueToStringCopy (context, value, NULL); +//// str_length = JSStringGetMaximumUTF8CStringSize (js_str_value); +//// str_value = (gchar *)g_malloc (str_length); +//// JSStringGetUTF8CString (js_str_value, str_value, str_length); +//// JSStringRelease (js_str_value); +//// g_print ("Script result: %s\n", str_value); +//// g_free (str_value); +//// +//// // else if JSValueIsBoolean +//// // else if JSValueIsNumber +//// // else if JSValueIsObject +//// // else if JSValueIsNull +//// // else if JSValueIsArray +//// // else if JSValueIsUndefined (?) +//// // else if JSValueIsDate (?) +//// } else { +//// g_warning ("webkitgtk_custom.c: Error running javascript(2): unexpected return value"); +//// } +// +// webkit_javascript_result_unref (js_result); +// } +// +// // 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 + gboolean *JsCallFinished = (gboolean* ) user_data; + *JsCallFinished = TRUE; +} + + + +/* + * Type notes: + * [Java] -> [native] + * byte [] -> signed char *str + * long /int/ -> long +*/ +/** + * Convert the async function webkit_web_view_run_javascript(..) into a synchronous one + * by spinning until the callback is completed. + */ +long swt_webkit_web_view_run_javascript (long webkit_handle, signed char *script) { + + // TODO - WEBKIT2 port this will eventually be a struct that will hold the return value. + gboolean * JsCallFinished = g_new(gboolean, 1); //allocate 1 unit of gboolean (not assigning '1' to it). + *JsCallFinished = FALSE; + + // Macro usage copied and adjusted from webkitgtk.c's 'NO__1webkit_1web_1view_1run_1javascript' wrapper. + WebKitGTK_LOAD_FUNCTION(fp, webkit_web_view_run_javascript) + if (fp) { + ((void (CALLING_CONVENTION*)(jintLong, jbyte *, jintLong, jintLong, jintLong))fp)((jintLong) webkit_handle, script, (jintLong) 0, (jintLong) web_view_javascript_finished_callback, (jintLong) JsCallFinished); + } + + // Spin till callback completes. Note this spin is needed for 'callback' event to be called, otherwise we have a hang. + while (*JsCallFinished == FALSE) { + g_main_context_iteration(0, FALSE); + } + g_free(JsCallFinished); + + return 1; +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_custom.h b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_custom.h new file mode 100644 index 0000000000..c220705b07 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_custom.h @@ -0,0 +1,24 @@ +/******************************************************************************* +* 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 +*******************************************************************************/ + +#ifndef INC_webkitgtk_custom_H +#define INC_webkitgtk_custom_H + +/* Manually written code */ + +long swt_webkit_web_view_run_javascript (long webkit_handle, signed char *script); + +#endif /*INC_webkit_custom_H*/ + diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.c b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.c index 6d0961a560..0a8a44ae42 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.c +++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.c @@ -73,6 +73,7 @@ char * WebKitGTK_nativeFunctionNames[] = { "_1soup_1uri_1free", "_1soup_1uri_1new", "_1soup_1uri_1to_1string", + "_1swt_1webkit_1web_1view_1run_1javascript", "_1webkit_1authentication_1request_1authenticate", "_1webkit_1authentication_1request_1cancel", "_1webkit_1authentication_1request_1is_1retry", diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.h b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.h index a882b17f55..20502b0ba8 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.h +++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.h @@ -83,6 +83,7 @@ typedef enum { _1soup_1uri_1free_FUNC, _1soup_1uri_1new_FUNC, _1soup_1uri_1to_1string_FUNC, + _1swt_1webkit_1web_1view_1run_1javascript_FUNC, _1webkit_1authentication_1request_1authenticate_FUNC, _1webkit_1authentication_1request_1cancel_FUNC, _1webkit_1authentication_1request_1is_1retry_FUNC, diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebKit.java b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebKit.java index a4abe6e53f..a850e8da21 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebKit.java +++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebKit.java @@ -905,12 +905,11 @@ boolean close (boolean showPrompters) { public boolean execute (String script) { byte[] scriptBytes = (script + '\0').getBytes (StandardCharsets.UTF_8); //$NON-NLS-1$ - long /*int*/ result = 0; if (WEBKIT2){ - WebKitGTK.webkit_web_view_run_javascript (webView, scriptBytes, 0, 0, 0); - // TODO - this call is asynchronous, so no return vaulue. As result this call executes but - // returns false. Handling of return value to be implemented... + // Currently always returns 1 upon completion. + // TODO WEBKIT2 - modify webkitgtk_custom to return 0 if there is an error. + result = (int) WebKitGTK.swt_webkit_web_view_run_javascript(webView, scriptBytes); } else { long /*int*/ jsScriptString = WebKitGTK.JSStringCreateWithUTF8CString (scriptBytes); diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/internal/webkit/WebKitGTK.java b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/internal/webkit/WebKitGTK.java index 98fe4e30d0..4e52d2db86 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/internal/webkit/WebKitGTK.java +++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/internal/webkit/WebKitGTK.java @@ -1675,4 +1675,15 @@ public static final long /*int*/ SoupMessage_request_headers (long /*int*/ messa } } +/* This custom function must only be called on Webkit2, use if (WEBKIT2) boolean. */ +public static final native long _swt_webkit_web_view_run_javascript (long /*int*/ webkit_handle, byte[] script); +public static final long swt_webkit_web_view_run_javascript (long /*int*/ webkit_handle, byte[] script) { + lock.lock(); + try { + return _swt_webkit_web_view_run_javascript (webkit_handle, script); + } finally { + lock.unlock(); + } +} + } |