Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c169
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h1
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c11
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h11
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java192
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk.c20
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_extension.c241
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_extension.h59
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.c1
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.h1
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebKit.java97
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebkitGDBus.java261
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/internal/webkit/WebKitGTK.java11
-rw-r--r--tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug536141_BrowserFunctionLostReload.java158
14 files changed, 1174 insertions, 59 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c
index 08e24009d6..596c69a177 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c
@@ -16235,6 +16235,91 @@ fail:
}
#endif
+#ifndef NO__1g_1dbus_1proxy_1call
+JNIEXPORT void JNICALL OS_NATIVE(_1g_1dbus_1proxy_1call)
+ (JNIEnv *env, jclass that, jintLong arg0, jbyteArray arg1, jintLong arg2, jint arg3, jint arg4, jintLong arg5, jintLong arg6, jintLongArray arg7)
+{
+ jbyte *lparg1=NULL;
+ jintLong *lparg7=NULL;
+ OS_NATIVE_ENTER(env, that, _1g_1dbus_1proxy_1call_FUNC);
+ if (arg1) if ((lparg1 = (*env)->GetByteArrayElements(env, arg1, NULL)) == NULL) goto fail;
+ if (arg7) if ((lparg7 = (*env)->GetIntLongArrayElements(env, arg7, NULL)) == NULL) goto fail;
+/*
+ g_dbus_proxy_call((GDBusProxy *)arg0, (const gchar *)lparg1, (GVariant *)arg2, arg3, arg4, (GCancellable *)arg5, arg6, (GError **)lparg7);
+*/
+ {
+ OS_LOAD_FUNCTION(fp, g_dbus_proxy_call)
+ if (fp) {
+ ((void (CALLING_CONVENTION*)(GDBusProxy *, const gchar *, GVariant *, jint, jint, GCancellable *, jintLong, GError **))fp)((GDBusProxy *)arg0, (const gchar *)lparg1, (GVariant *)arg2, arg3, arg4, (GCancellable *)arg5, arg6, (GError **)lparg7);
+ }
+ }
+fail:
+ if (arg7 && lparg7) (*env)->ReleaseIntLongArrayElements(env, arg7, lparg7, 0);
+ if (arg1 && lparg1) (*env)->ReleaseByteArrayElements(env, arg1, lparg1, 0);
+ OS_NATIVE_EXIT(env, that, _1g_1dbus_1proxy_1call_FUNC);
+}
+#endif
+
+#ifndef NO__1g_1dbus_1proxy_1call_1finish
+JNIEXPORT jintLong JNICALL OS_NATIVE(_1g_1dbus_1proxy_1call_1finish)
+ (JNIEnv *env, jclass that, jintLong arg0, jintLong arg1, jintLongArray arg2)
+{
+ jintLong *lparg2=NULL;
+ jintLong rc = 0;
+ OS_NATIVE_ENTER(env, that, _1g_1dbus_1proxy_1call_1finish_FUNC);
+ if (arg2) if ((lparg2 = (*env)->GetIntLongArrayElements(env, arg2, NULL)) == NULL) goto fail;
+ rc = (jintLong)g_dbus_proxy_call_finish((GDBusProxy *)arg0, (GAsyncResult *)arg1, (GError **)lparg2);
+fail:
+ if (arg2 && lparg2) (*env)->ReleaseIntLongArrayElements(env, arg2, lparg2, 0);
+ OS_NATIVE_EXIT(env, that, _1g_1dbus_1proxy_1call_1finish_FUNC);
+ return rc;
+}
+#endif
+
+#ifndef NO__1g_1dbus_1proxy_1call_1sync
+JNIEXPORT jintLong JNICALL OS_NATIVE(_1g_1dbus_1proxy_1call_1sync)
+ (JNIEnv *env, jclass that, jintLong arg0, jbyteArray arg1, jintLong arg2, jint arg3, jint arg4, jintLong arg5, jintLongArray arg6)
+{
+ jbyte *lparg1=NULL;
+ jintLong *lparg6=NULL;
+ jintLong rc = 0;
+ OS_NATIVE_ENTER(env, that, _1g_1dbus_1proxy_1call_1sync_FUNC);
+ if (arg1) if ((lparg1 = (*env)->GetByteArrayElements(env, arg1, NULL)) == NULL) goto fail;
+ if (arg6) if ((lparg6 = (*env)->GetIntLongArrayElements(env, arg6, NULL)) == NULL) goto fail;
+ rc = (jintLong)g_dbus_proxy_call_sync((GDBusProxy *)arg0, (const gchar *)lparg1, (GVariant *)arg2, arg3, arg4, (GCancellable *)arg5, (GError **)lparg6);
+fail:
+ if (arg6 && lparg6) (*env)->ReleaseIntLongArrayElements(env, arg6, lparg6, 0);
+ if (arg1 && lparg1) (*env)->ReleaseByteArrayElements(env, arg1, lparg1, 0);
+ OS_NATIVE_EXIT(env, that, _1g_1dbus_1proxy_1call_1sync_FUNC);
+ return rc;
+}
+#endif
+
+#ifndef NO__1g_1dbus_1proxy_1new_1for_1bus_1sync
+JNIEXPORT jintLong JNICALL OS_NATIVE(_1g_1dbus_1proxy_1new_1for_1bus_1sync)
+ (JNIEnv *env, jclass that, jint arg0, jint arg1, jintLong arg2, jbyteArray arg3, jbyteArray arg4, jbyteArray arg5, jintLong arg6, jintLongArray arg7)
+{
+ jbyte *lparg3=NULL;
+ jbyte *lparg4=NULL;
+ jbyte *lparg5=NULL;
+ jintLong *lparg7=NULL;
+ jintLong rc = 0;
+ OS_NATIVE_ENTER(env, that, _1g_1dbus_1proxy_1new_1for_1bus_1sync_FUNC);
+ if (arg3) if ((lparg3 = (*env)->GetByteArrayElements(env, arg3, NULL)) == NULL) goto fail;
+ if (arg4) if ((lparg4 = (*env)->GetByteArrayElements(env, arg4, NULL)) == NULL) goto fail;
+ if (arg5) if ((lparg5 = (*env)->GetByteArrayElements(env, arg5, NULL)) == NULL) goto fail;
+ if (arg7) if ((lparg7 = (*env)->GetIntLongArrayElements(env, arg7, NULL)) == NULL) goto fail;
+ rc = (jintLong)g_dbus_proxy_new_for_bus_sync(arg0, arg1, (GDBusInterfaceInfo *)arg2, (const gchar *)lparg3, (const gchar *)lparg4, (const gchar *)lparg5, (GCancellable *)arg6, (GError **)lparg7);
+fail:
+ if (arg7 && lparg7) (*env)->ReleaseIntLongArrayElements(env, arg7, lparg7, 0);
+ if (arg5 && lparg5) (*env)->ReleaseByteArrayElements(env, arg5, lparg5, 0);
+ if (arg4 && lparg4) (*env)->ReleaseByteArrayElements(env, arg4, lparg4, 0);
+ if (arg3 && lparg3) (*env)->ReleaseByteArrayElements(env, arg3, lparg3, 0);
+ OS_NATIVE_EXIT(env, that, _1g_1dbus_1proxy_1new_1for_1bus_1sync_FUNC);
+ return rc;
+}
+#endif
+
#ifndef NO__1g_1error_1free
JNIEXPORT void JNICALL OS_NATIVE(_1g_1error_1free)
(JNIEnv *env, jclass that, jintLong arg0)
@@ -17970,6 +18055,50 @@ JNIEXPORT jintLong JNICALL OS_NATIVE(_1g_1value_1peek_1pointer)
}
#endif
+#ifndef NO__1g_1variant_1builder_1add_1value
+JNIEXPORT void JNICALL OS_NATIVE(_1g_1variant_1builder_1add_1value)
+ (JNIEnv *env, jclass that, jintLong arg0, jintLong arg1)
+{
+ OS_NATIVE_ENTER(env, that, _1g_1variant_1builder_1add_1value_FUNC);
+ g_variant_builder_add_value((GVariantBuilder *)arg0, (GVariant *)arg1);
+ OS_NATIVE_EXIT(env, that, _1g_1variant_1builder_1add_1value_FUNC);
+}
+#endif
+
+#ifndef NO__1g_1variant_1builder_1end
+JNIEXPORT jintLong JNICALL OS_NATIVE(_1g_1variant_1builder_1end)
+ (JNIEnv *env, jclass that, jintLong arg0)
+{
+ jintLong rc = 0;
+ OS_NATIVE_ENTER(env, that, _1g_1variant_1builder_1end_FUNC);
+ rc = (jintLong)g_variant_builder_end((GVariantBuilder *)arg0);
+ OS_NATIVE_EXIT(env, that, _1g_1variant_1builder_1end_FUNC);
+ return rc;
+}
+#endif
+
+#ifndef NO__1g_1variant_1builder_1new
+JNIEXPORT jintLong JNICALL OS_NATIVE(_1g_1variant_1builder_1new)
+ (JNIEnv *env, jclass that, jintLong arg0)
+{
+ jintLong rc = 0;
+ OS_NATIVE_ENTER(env, that, _1g_1variant_1builder_1new_FUNC);
+ rc = (jintLong)g_variant_builder_new((const GVariantType *)arg0);
+ OS_NATIVE_EXIT(env, that, _1g_1variant_1builder_1new_FUNC);
+ return rc;
+}
+#endif
+
+#ifndef NO__1g_1variant_1builder_1unref
+JNIEXPORT void JNICALL OS_NATIVE(_1g_1variant_1builder_1unref)
+ (JNIEnv *env, jclass that, jintLong arg0)
+{
+ OS_NATIVE_ENTER(env, that, _1g_1variant_1builder_1unref_FUNC);
+ g_variant_builder_unref((GVariantBuilder *)arg0);
+ OS_NATIVE_EXIT(env, that, _1g_1variant_1builder_1unref_FUNC);
+}
+#endif
+
#ifndef NO__1g_1variant_1get_1boolean
JNIEXPORT jboolean JNICALL OS_NATIVE(_1g_1variant_1get_1boolean)
(JNIEnv *env, jclass that, jintLong arg0)
@@ -18070,6 +18199,18 @@ JNIEXPORT jintLong JNICALL OS_NATIVE(_1g_1variant_1get_1type_1string)
}
#endif
+#ifndef NO__1g_1variant_1get_1uint64
+JNIEXPORT jlong JNICALL OS_NATIVE(_1g_1variant_1get_1uint64)
+ (JNIEnv *env, jclass that, jintLong arg0)
+{
+ jlong rc = 0;
+ OS_NATIVE_ENTER(env, that, _1g_1variant_1get_1uint64_FUNC);
+ rc = (jlong)g_variant_get_uint64((GVariant *)arg0);
+ OS_NATIVE_EXIT(env, that, _1g_1variant_1get_1uint64_FUNC);
+ return rc;
+}
+#endif
+
#ifndef NO__1g_1variant_1is_1of_1type
JNIEXPORT jboolean JNICALL OS_NATIVE(_1g_1variant_1is_1of_1type)
(JNIEnv *env, jclass that, jintLong arg0, jbyteArray arg1)
@@ -18178,6 +18319,34 @@ fail:
}
#endif
+#ifndef NO__1g_1variant_1new_1uint64
+JNIEXPORT jintLong JNICALL OS_NATIVE(_1g_1variant_1new_1uint64)
+ (JNIEnv *env, jclass that, jlong arg0)
+{
+ jintLong rc = 0;
+ OS_NATIVE_ENTER(env, that, _1g_1variant_1new_1uint64_FUNC);
+ rc = (jintLong)g_variant_new_uint64(arg0);
+ OS_NATIVE_EXIT(env, that, _1g_1variant_1new_1uint64_FUNC);
+ return rc;
+}
+#endif
+
+#ifndef NO__1g_1variant_1type_1new
+JNIEXPORT jintLong JNICALL OS_NATIVE(_1g_1variant_1type_1new)
+ (JNIEnv *env, jclass that, jbyteArray arg0)
+{
+ jbyte *lparg0=NULL;
+ jintLong rc = 0;
+ OS_NATIVE_ENTER(env, that, _1g_1variant_1type_1new_FUNC);
+ if (arg0) if ((lparg0 = (*env)->GetByteArrayElements(env, arg0, NULL)) == NULL) goto fail;
+ rc = (jintLong)g_variant_type_new((const gchar *)lparg0);
+fail:
+ if (arg0 && lparg0) (*env)->ReleaseByteArrayElements(env, arg0, lparg0, 0);
+ OS_NATIVE_EXIT(env, that, _1g_1variant_1type_1new_FUNC);
+ return rc;
+}
+#endif
+
#ifndef NO__1getpid
JNIEXPORT jint JNICALL OS_NATIVE(_1getpid)
(JNIEnv *env, jclass that)
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h
index bcce6b32a0..9ccc85811c 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h
@@ -67,6 +67,7 @@
#define g_thread_init_LIB LIB_GTHREAD
#define ubuntu_menu_proxy_get_LIB LIB_GTK
#define FcConfigAppFontAddFile_LIB LIB_FONTCONFIG
+#define g_dbus_proxy_call_LIB LIB_GLIB
// GTK3 only
#define g_bytes_new_LIB LIB_GLIB
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c
index d5e53977d1..6491dd15eb 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c
@@ -1333,6 +1333,10 @@ char * OS_nativeFunctionNames[] = {
"_1g_1dbus_1method_1invocation_1return_1value",
"_1g_1dbus_1node_1info_1lookup_1interface",
"_1g_1dbus_1node_1info_1new_1for_1xml",
+ "_1g_1dbus_1proxy_1call",
+ "_1g_1dbus_1proxy_1call_1finish",
+ "_1g_1dbus_1proxy_1call_1sync",
+ "_1g_1dbus_1proxy_1new_1for_1bus_1sync",
"_1g_1error_1free",
"_1g_1error_1get_1message",
"_1g_1file_1get_1uri",
@@ -1513,6 +1517,10 @@ char * OS_nativeFunctionNames[] = {
"_1g_1utf8_1to_1utf16___3BJ_3J_3J_3J",
#endif
"_1g_1value_1peek_1pointer",
+ "_1g_1variant_1builder_1add_1value",
+ "_1g_1variant_1builder_1end",
+ "_1g_1variant_1builder_1new",
+ "_1g_1variant_1builder_1unref",
"_1g_1variant_1get_1boolean",
"_1g_1variant_1get_1byte",
"_1g_1variant_1get_1child_1value",
@@ -1521,6 +1529,7 @@ char * OS_nativeFunctionNames[] = {
"_1g_1variant_1get_1string",
"_1g_1variant_1get_1type",
"_1g_1variant_1get_1type_1string",
+ "_1g_1variant_1get_1uint64",
"_1g_1variant_1is_1of_1type",
"_1g_1variant_1n_1children",
"_1g_1variant_1new_1boolean",
@@ -1529,6 +1538,8 @@ char * OS_nativeFunctionNames[] = {
"_1g_1variant_1new_1int32",
"_1g_1variant_1new_1string",
"_1g_1variant_1new_1tuple",
+ "_1g_1variant_1new_1uint64",
+ "_1g_1variant_1type_1new",
"_1gdk_1keymap_1translate_1keyboard_1state",
"_1getpid",
"_1glib_1major_1version",
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h
index fd55aea6d2..70894d8d40 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h
@@ -1319,6 +1319,10 @@ typedef enum {
_1g_1dbus_1method_1invocation_1return_1value_FUNC,
_1g_1dbus_1node_1info_1lookup_1interface_FUNC,
_1g_1dbus_1node_1info_1new_1for_1xml_FUNC,
+ _1g_1dbus_1proxy_1call_FUNC,
+ _1g_1dbus_1proxy_1call_1finish_FUNC,
+ _1g_1dbus_1proxy_1call_1sync_FUNC,
+ _1g_1dbus_1proxy_1new_1for_1bus_1sync_FUNC,
_1g_1error_1free_FUNC,
_1g_1error_1get_1message_FUNC,
_1g_1file_1get_1uri_FUNC,
@@ -1499,6 +1503,10 @@ typedef enum {
_1g_1utf8_1to_1utf16___3BJ_3J_3J_3J_FUNC,
#endif
_1g_1value_1peek_1pointer_FUNC,
+ _1g_1variant_1builder_1add_1value_FUNC,
+ _1g_1variant_1builder_1end_FUNC,
+ _1g_1variant_1builder_1new_FUNC,
+ _1g_1variant_1builder_1unref_FUNC,
_1g_1variant_1get_1boolean_FUNC,
_1g_1variant_1get_1byte_FUNC,
_1g_1variant_1get_1child_1value_FUNC,
@@ -1507,6 +1515,7 @@ typedef enum {
_1g_1variant_1get_1string_FUNC,
_1g_1variant_1get_1type_FUNC,
_1g_1variant_1get_1type_1string_FUNC,
+ _1g_1variant_1get_1uint64_FUNC,
_1g_1variant_1is_1of_1type_FUNC,
_1g_1variant_1n_1children_FUNC,
_1g_1variant_1new_1boolean_FUNC,
@@ -1515,6 +1524,8 @@ typedef enum {
_1g_1variant_1new_1int32_FUNC,
_1g_1variant_1new_1string_FUNC,
_1g_1variant_1new_1tuple_FUNC,
+ _1g_1variant_1new_1uint64_FUNC,
+ _1g_1variant_1type_1new_FUNC,
_1gdk_1keymap_1translate_1keyboard_1state_FUNC,
_1getpid_FUNC,
_1glib_1major_1version_FUNC,
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
index a894399983..221e1a6c1f 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
@@ -204,6 +204,16 @@ public class OS extends C {
* @category gdbus */
public static final int G_BUS_NAME_OWNER_FLAGS_REPLACE = (1<<1);
+ // Proxy flags found here: https://developer.gnome.org/gio/stable/GDBusProxy.html#GDBusProxyFlags
+ public static final int G_DBUS_PROXY_FLAGS_NONE = 0;
+ public static final int G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES = 1;
+ public static final int G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS = 2;
+ public static final int G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START = 3;
+ public static final int G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES = 4;
+ public static final int G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START_AT_CONSTRUCTION = 5;
+
+ public static final int G_DBUS_CALL_FLAGS_NONE = 0;
+ public static final int G_DBUS_CALL_FLAGS_NO_AUTO_START = (1<<0);
/**
* DBus Data types as defined by:
@@ -220,8 +230,12 @@ public class OS extends C {
/** @category gdbus */
public static final String DBUS_TYPE_STRING_ARRAY = "as";
/** @category gdbus */
+ public static final String DBUS_TYPE_STRUCT_ARRAY_BROWSER_FUNCS = "a(tss)";
+ /** @category gdbus */
public static final String DBUS_TYPE_INT32 = "i";
/** @category gdbus */
+ public static final String DBUS_TYPE_UINT64 = "t";
+ /** @category gdbus */
public static final String DBUS_TYPE_DOUBLE = "d";
/** @category gdbus */
public static final String DBUS_TYPE_STRUCT = "r"; // Not used by Dbus, but implemented by GDBus.
@@ -245,9 +259,13 @@ public class OS extends C {
/** @category gdbus */
public static final byte[] G_VARIANT_TYPE_IN32 = ascii(DBUS_TYPE_INT32);
/** @category gdbus */
+ public static final byte[] G_VARIANT_TYPE_UINT64 = ascii(DBUS_TYPE_UINT64);
+ /** @category gdbus */
public static final byte[] G_VARIANT_TYPE_DOUBLE = ascii(DBUS_TYPE_DOUBLE);
/** @category gdbus */
public static final byte[] G_VARIANT_TYPE_TUPLE = ascii(DBUS_TYPE_STRUCT);
+ /** @category gdbus */
+ public static final byte[] G_VARIANT_TYPE_ARRAY_BROWSER_FUNCS = ascii(DBUS_TYPE_STRUCT_ARRAY_BROWSER_FUNCS);
/** Signals */
@@ -4261,6 +4279,79 @@ public static final void setDarkThemePreferred(boolean preferred){
GTK.gtk_application_prefer_dark_theme);
}
+/**
+ * @param info cast=(GDBusInterfaceInfo *)
+ * @param name cast=(const gchar *)
+ * @param object_path cast=(const gchar *)
+ * @param interface_name cast=(const gchar *)
+ * @param cancellable cast=(GCancellable *)
+ * @param error cast=(GError **)
+ * @category gdbus
+ */
+public static final native long /*int*/ _g_dbus_proxy_new_for_bus_sync (int bus_type, int flags, long /*int*/ info, byte [] name, byte [] object_path, byte [] interface_name,
+ long /*int*/ cancellable, long /*int*/[] error);
+public static final long /*int*/ g_dbus_proxy_new_for_bus_sync (int bus_type, int flags, long /*int*/ info, byte [] name, byte [] object_path, byte [] interface_name,
+ long /*int*/ cancellable, long /*int*/[] error) {
+ lock.lock();
+ try {
+ return _g_dbus_proxy_new_for_bus_sync (bus_type, flags, info, name, object_path, interface_name, cancellable, error);
+ } finally {
+ lock.unlock();
+ }
+}
+
+/**
+ * @param proxy cast=(GDBusProxy *)
+ * @param method_name cast=(const gchar *)
+ * @param parameters cast=(GVariant *)
+ * @param cancellable cast=(GCancellable *)
+ * @param error cast=(GError **)
+ * @category gdbus
+ */
+public static final native long /*int*/ _g_dbus_proxy_call_sync (long /*int*/ proxy, byte[] method_name, long /*int*/ parameters, int flags, int timeout_msec, long /*int*/ cancellable, long /*int*/[] error);
+public static final long /*int*/ g_dbus_proxy_call_sync (long /*int*/ proxy, byte[] method_name, long /*int*/ parameters, int flags, int timeout_msec, long /*int*/ cancellable, long /*int*/[] error) {
+ lock.lock();
+ try {
+ return _g_dbus_proxy_call_sync (proxy, method_name, parameters, flags, timeout_msec, cancellable, error);
+ } finally {
+ lock.unlock();
+ }
+}
+
+/**
+ * @method flags=dynamic
+ * @param proxy cast=(GDBusProxy *)
+ * @param method_name cast=(const gchar *)
+ * @param parameters cast=(GVariant *)
+ * @param cancellable cast=(GCancellable *)
+ * @param error cast=(GError **)
+ * @category gdbus
+ */
+public static final native void _g_dbus_proxy_call (long /*int*/ proxy, byte[] method_name, long /*int*/ parameters, int flags, int timeout_msec, long /*int*/ cancellable, long /*int*/ callback, long /*int*/[] error);
+public static final void g_dbus_proxy_call (long /*int*/ proxy, byte[] method_name, long /*int*/ parameters, int flags, int timeout_msec, long /*int*/ cancellable, long /*int*/ callback, long /*int*/[] error) {
+ lock.lock();
+ try {
+ _g_dbus_proxy_call (proxy, method_name, parameters, flags, timeout_msec, cancellable, callback, error);
+ } finally {
+ lock.unlock();
+ }
+}
+
+/**
+ * @param proxy cast=(GDBusProxy *)
+ * @param res cast=(GAsyncResult *)
+ * @param error cast=(GError **)
+ * @category gdbus
+ */
+public static final native long /*int*/ _g_dbus_proxy_call_finish (long /*int*/ proxy, long /*int*/ res, long /*int*/[] error);
+public static final long /*int*/ g_dbus_proxy_call_finish (long /*int*/ proxy, long /*int*/ res, long /*int*/[] error) {
+ lock.lock();
+ try {
+ return _g_dbus_proxy_call_finish (proxy, res, error);
+ } finally {
+ lock.unlock();
+ }
+}
/**
* @param xml_data cast=(const gchar *)
@@ -4354,6 +4445,82 @@ public static final void g_dbus_method_invocation_return_value (long /*int*/ inv
}
/**
+ * @param type cast=(const GVariantType *)
+ * @category gdbus
+ */
+public static final native long /*int*/ _g_variant_builder_new (long /*int*/ type);
+/** @category gdbus */
+public static final long /*int*/ g_variant_builder_new (long /*int*/ type) {
+ lock.lock();
+ try {
+ return _g_variant_builder_new(type);
+ } finally {
+ lock.unlock();
+ }
+}
+
+/**
+ * @param builder cast=(GVariantBuilder *)
+ * @param value cast=(GVariant *)
+ * @category gdbus
+ */
+public static final native void /*int*/ _g_variant_builder_add_value (long /*int*/ builder, long /*int*/ value);
+/** @category gdbus */
+public static final void /*int*/ g_variant_builder_add_value (long /*int*/ builder, long /*int*/ value) {
+ lock.lock();
+ try {
+ _g_variant_builder_add_value(builder, value);
+ } finally {
+ lock.unlock();
+ }
+}
+
+/**
+ * @param type cast=(const gchar *)
+ * @category gdbus
+ */
+public static final native long /*int*/ _g_variant_type_new (byte [] type);
+/** @category gdbus */
+public static final long /*int*/ g_variant_type_new (byte [] type) {
+ lock.lock();
+ try {
+ return _g_variant_type_new(type);
+ } finally {
+ lock.unlock();
+ }
+}
+
+/**
+ * @param builder cast=(GVariantBuilder *)
+ * @category gdbus
+ */
+public static final native long /*int*/ _g_variant_builder_end (long /*int*/ builder);
+/** @category gdbus */
+public static final long /*int*/ g_variant_builder_end (long /*int*/ builder) {
+ lock.lock();
+ try {
+ return _g_variant_builder_end(builder);
+ } finally {
+ lock.unlock();
+ }
+}
+
+/**
+ * @param builder cast=(GVariantBuilder *)
+ * @category gdbus
+ */
+public static final native void /*int*/ _g_variant_builder_unref (long /*int*/ builder);
+/** @category gdbus */
+public static final void /*int*/ g_variant_builder_unref (long /*int*/ builder) {
+ lock.lock();
+ try {
+ _g_variant_builder_unref(builder);
+ } finally {
+ lock.unlock();
+ }
+}
+
+/**
* @param intval cast=(gint32)
* @category gdbus
*/
@@ -4447,6 +4614,31 @@ public static final double g_variant_get_double (long /*int*/ gvariant) {
}
}
+public static final native long /*int*/ _g_variant_new_uint64 (long value);
+public static final long /*int*/ g_variant_new_uint64 (long value) {
+ lock.lock();
+ try {
+ return _g_variant_new_uint64 (value);
+ } finally {
+ lock.unlock();
+ }
+}
+
+/**
+ * @param gvariant cast=(GVariant *)
+ * @category gdbus
+ */
+public static final native long _g_variant_get_uint64 (long /*int*/ gvariant);
+/** @category gdbus */
+public static final long g_variant_get_uint64 (long /*int*/ gvariant) {
+ lock.lock();
+ try {
+ return _g_variant_get_uint64 (gvariant);
+ } finally {
+ lock.unlock();
+ }
+}
+
/**
* @param gvariant cast=(GVariant *)
* @param length cast=(gsize *)
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 de6febe682..686437b6e5 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
@@ -2921,6 +2921,26 @@ JNIEXPORT jintLong JNICALL WebKitGTK_NATIVE(_1webkit_1web_1view_1get_1main_1reso
}
#endif
+#ifndef NO__1webkit_1web_1view_1get_1page_1id
+JNIEXPORT jintLong JNICALL WebKitGTK_NATIVE(_1webkit_1web_1view_1get_1page_1id)
+ (JNIEnv *env, jclass that, jintLong arg0)
+{
+ jintLong rc = 0;
+ WebKitGTK_NATIVE_ENTER(env, that, _1webkit_1web_1view_1get_1page_1id_FUNC);
+/*
+ rc = (jintLong)webkit_web_view_get_page_id(arg0);
+*/
+ {
+ WebKitGTK_LOAD_FUNCTION(fp, webkit_web_view_get_page_id)
+ if (fp) {
+ rc = (jintLong)((jintLong (CALLING_CONVENTION*)(jintLong))fp)(arg0);
+ }
+ }
+ WebKitGTK_NATIVE_EXIT(env, that, _1webkit_1web_1view_1get_1page_1id_FUNC);
+ return rc;
+}
+#endif
+
#ifndef NO__1webkit_1web_1view_1get_1progress
JNIEXPORT jdouble JNICALL WebKitGTK_NATIVE(_1webkit_1web_1view_1get_1progress)
(JNIEnv *env, jclass that, jintLong arg0)
diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_extension.c b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_extension.c
index 2dbc28c16c..fd958309a8 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_extension.c
+++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_extension.c
@@ -13,7 +13,6 @@ gint32 parentUniqueId = 0;
guchar SWT_DBUS_MAGIC_NUMBER_EMPTY_ARRAY = 101;
guchar SWT_DBUS_MAGIC_NUMBER_NULL = 48;
-
// +-------------+----------------------------------------------------------------
// | Misc Helpers|
// +-------------+
@@ -35,6 +34,13 @@ static const gchar base_service_name[] = "org.eclipse.swt"; // Base name. Full n
static const gchar object_name[] = "/org/eclipse/swt/gdbus";
static const gchar interface[] = "org.eclipse.swt.gdbusInterface";
+typedef struct {
+ guint64 page_id;
+ const gchar *function;
+ const gchar *url;
+} BrowserFunction;
+
+GSList *function_list = NULL;
GDBusProxy *proxy = NULL; // The proxy that we work with
void proxy_init () {
@@ -72,10 +78,12 @@ GVariant * callMainProc(char * methodName, GVariant * params) {
// Error checking.
if (result == NULL) {
- if (error != NULL)
- g_error("SWT Webextension: Call failed because '%s.' Probably didn't handle type properly, could be an SWT bug. Signature: %s\n", error->message, g_variant_get_type_string(params));
- else
- g_error("SWT Webextension: Call failed for an unknown reason.\n");
+ if (error != NULL) {
+ g_error("SWT web extension: Call failed because '%s.'\n", error->message);
+ }
+ else {
+ g_error("SWT web extension: Call failed for an unknown reason.\n");
+ }
return NULL;
}
@@ -289,17 +297,124 @@ static JSValueRef webkit2callJava (JSContextRef context,
return retVal;
}
+static void web_page_created_callback(WebKitWebExtension *extension, WebKitWebPage *web_page, gpointer user_data) {
+ // Observation. This seems to be called only once.
+}
+
+/**
+ * Returns the main frame of the WebPage with the given ID
+ */
+static WebKitFrame *webkitgtk_extension_get_main_frame (const guint64 id) {
+ WebKitWebPage *web_page = webkit_web_extension_get_page (this_extension, id);
+ return webkit_web_page_get_main_frame (web_page);
+}
+
+/*
+ * Execute the Javascript for the given page and URL.
+ */
+static gboolean webkitgtk_extension_execute_script (const guint64 page_id, const gchar* script, const gchar* url) {
+ WebKitFrame *main_frame = webkitgtk_extension_get_main_frame (page_id);
+
+ JSStringRef url_string = JSStringCreateWithUTF8CString (url);
+ JSStringRef script_string = JSStringCreateWithUTF8CString (script);
+
+ JSGlobalContextRef context = webkit_frame_get_javascript_global_context (main_frame);
+
+ JSValueRef exception;
+ JSValueRef result = JSEvaluateScript(context, script_string, NULL, url_string, 0, &exception);
+ if (!result) {
+ JSStringRef exceptionIString = JSValueToStringCopy(context, exception, NULL);
+ size_t exceptionUTF8Size = JSStringGetMaximumUTF8CStringSize(exceptionIString);
+ char* exceptionUTF8 = (char*)malloc(exceptionUTF8Size);
+ JSStringGetUTF8CString(exceptionIString, exceptionUTF8, exceptionUTF8Size);
+ g_error("SWT web extension: failed to execute script exception: %s\n", exceptionUTF8);
+ free(exceptionUTF8);
+ JSStringRelease(exceptionIString);
+ }
+
+ JSStringRelease (url_string);
+ JSStringRelease (script_string);
+
+ return result != NULL;
+}
+
+void execute_browser_functions(gconstpointer item, gpointer page) {
+ BrowserFunction *function = (BrowserFunction *) item;
+ if (function != NULL && function->page_id == GPOINTER_TO_UINT(page)) {
+ webkitgtk_extension_execute_script(function->page_id, function->function, function->url);
+ }
+ return;
+}
+
+gint find_browser_function (gconstpointer item, gconstpointer target) {
+ BrowserFunction *element = (BrowserFunction *) item;
+ BrowserFunction *remove = (BrowserFunction *) target;
+ if (element->page_id == remove->page_id && g_strcmp0(element->function, remove->function) == 0 &&
+ g_strcmp0(element->url, remove->url) == 0) {
+ return 0;
+ }
+ return 1;
+}
+
+void add_browser_function(guint64 page_id, const gchar *function, const gchar *url) {
+ BrowserFunction *func = g_slice_new0(BrowserFunction);
+ func->page_id = page_id;
+ func->function = function;
+ func->url = url;
+ function_list = g_slist_append(function_list, func);
+}
+
+void remove_browser_function(guint64 page_id, const gchar *function, const gchar *url) {
+ BrowserFunction *func = g_slice_new0(BrowserFunction);
+ func->page_id = page_id;
+ func->function = function;
+ func->url = url;
+ GSList *to_remove = g_slist_find_custom(function_list, func, find_browser_function);
+ if (to_remove != NULL) {
+ function_list = g_slist_delete_link(function_list, to_remove);
+ }
+ g_slice_free(BrowserFunction, func);
+}
+
+void unpack_browser_function_array(GVariant *array) {
+ GVariantIter iter;
+ GVariant *child;
+
+ g_variant_iter_init (&iter, array);
+ while ((child = g_variant_iter_next_value (&iter))) {
+ gsize length = (int)g_variant_n_children (child);
+ if (length > 3) {
+ // If the length is longer than three, something went wrong and this tuple should be skipped
+ g_warning("SWT web extension: there was an error unpacking the GVariant tuple for a BrowserFunction in the web extension.\n");
+ continue;
+ }
+ guint64 page = g_variant_get_uint64(g_variant_get_child_value(child, 0));
+ if (page == -1) {
+ // Empty or malformed BrowserFunction, skip this one
+ continue;
+ } else {
+ const gchar *function = g_variant_get_string(g_variant_get_child_value(child, 1), NULL);
+ const gchar *url = g_variant_get_string(g_variant_get_child_value(child, 2), NULL);
+ if (function != NULL && url != NULL) {
+ add_browser_function(page, function, url);
+ } else {
+ g_warning("SWT web extension: there was an error unpacking the function string or URL.\n");
+ }
+ }
+ g_variant_unref (child);
+ }
+}
/*
- * Everytime a webpage is loaded, we should re-register the 'webkit2callJava' function.
+ * Every time a webpage is loaded, we should re-register the 'webkit2callJava' function.
+ * Additionally, we re-register all BrowserFunctions that are stored in the function_list
+ * GSList.
*/
-static void window_object_cleared_callback (WebKitScriptWorld *world,
- WebKitWebPage *web_page,
+static void window_object_cleared_callback (WebKitScriptWorld *world, WebKitWebPage *web_page,
WebKitFrame *frame,
- gpointer user_data)
-{
- // Observation: This is called everytime a webpage is loaded.
- JSGlobalContextRef jsContext;
+ gpointer user_data) {
+ // Observation: This is called every time a webpage is loaded.
+ JSGlobalContextRef jsContext;
JSObjectRef globalObject;
JSValueRef exception = 0;
@@ -314,23 +429,113 @@ static void window_object_cleared_callback (WebKitScriptWorld *world,
if (exception) {
g_print("OJSObjectSetProperty exception occurred");
}
+
+ /*
+ * Iterate over the list of BrowserFunctions and execute each one of them for the current page.
+ * This ensures that BrowserFunctions are not lost on page reloads. See bug 536141.
+ */
+ if (function_list != NULL) {
+ guint64 page_id = webkit_web_page_get_id (web_page);
+ if (page_id != -1) {
+ g_slist_foreach(function_list, (GFunc)execute_browser_functions, GUINT_TO_POINTER(page_id));
+ } else {
+ g_warning("SWT web extension: there was an error fetching the page ID in the object_cleared callback.\n");
+ }
+ }
}
-static void web_page_created_callback(WebKitWebExtension *extension, WebKitWebPage *web_page, gpointer user_data) {
- // Observation. This seems to be called only once.
+static void
+webkitgtk_extension_handle_method_call (GDBusConnection *connection, const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data) {
+ gboolean result = FALSE;
+ const gchar *script;
+ const gchar *url;
+ guint64 page_id;
+ // Check method names
+ if (g_strcmp0(method_name, "webkitgtk_extension_register_function") == 0) {
+ g_variant_get(parameters, "(t&s&s)", &page_id, &script, &url);
+ if (page_id != -1) {
+ result = TRUE;
+ // Return before processing the linked list, to prevent DBus from hanging
+ g_dbus_method_invocation_return_value(invocation, g_variant_new("(b)", result));
+ add_browser_function(page_id, script, url);
+ return;
+ }
+ g_dbus_method_invocation_return_value(invocation, g_variant_new("(b)", result));
+ return;
+ }
+ if (g_strcmp0(method_name, "webkitgtk_extension_deregister_function") == 0) {
+ g_variant_get(parameters, "(t&s&s)", &page_id, &script, &url);
+ if (page_id != -1) {
+ result = TRUE;
+ // Return before processing the linked list, to prevent DBus from hanging
+ g_dbus_method_invocation_return_value(invocation, g_variant_new("(b)", result));
+ remove_browser_function(page_id, script, url);
+ return;
+ }
+ g_dbus_method_invocation_return_value(invocation, g_variant_new("(b)", result));
+ return;
+ }
+ g_error ("UNKNOWN method %s\n", method_name);
}
-G_MODULE_EXPORT void
-webkit_web_extension_initialize_with_user_data(WebKitWebExtension *extension, GVariant *user_data)
-{
+static const GDBusInterfaceVTable interface_vtable = {webkitgtk_extension_handle_method_call, NULL, NULL};
+
+static void on_bus_acquired (GDBusConnection *connection, const gchar *name, gpointer user_data) {
+ dbus_interface = g_dbus_node_info_lookup_interface(dbus_node, WEBKITGTK_EXTENSION_DBUS_INTERFACE);
+ guint registration_id = g_dbus_connection_register_object(connection,
+ webkitgtk_extension_dbus_path,
+ dbus_interface,
+ &interface_vtable, NULL, /* user_data */
+ NULL, /* user_data_free_func */
+ NULL); /* GError** */
+ g_assert(registration_id > 0);
+
+ GVariant *g_var_result = callMainProc("webkitWebExtensionIdentifer", g_variant_new ("(ss)",
+ webkitgtk_extension_dbus_name, webkitgtk_extension_dbus_path));
+ if (g_variant_is_of_type(g_var_result, G_VARIANT_TYPE_TUPLE)) {
+ unpack_browser_function_array(g_variant_get_child_value(g_var_result, 0));
+ } else {
+ g_warning("SWT web extension: on_bus_acquired return value from SWT was an unexpected type (not a tuple).\n");
+ }
+ return;
+}
+
+G_MODULE_EXPORT void webkit_web_extension_initialize_with_user_data(WebKitWebExtension *extension, GVariant *user_data) {
// To debug this extension:
// - ensure this is build with debug flags (look for '-g*' in make_linux, or 'SWT_LIB_DEBUG' macro.
// - connect to WebKitWebProcess with pid of this extension. Use below to print it:
- // g_print("Webext pid: %d (To debug, attach to WebKitWebProcess with this pid)\n", getpid());
+ // g_print("Webext pid: %d (To debug, attach to WebKitWebProcess with this pid)\n", getpid());
+ this_extension = extension;
parentUniqueId = g_variant_get_int32(user_data);
g_signal_connect(extension, "page-created", G_CALLBACK(web_page_created_callback), NULL);
// To hook into javascript execution:
g_signal_connect (webkit_script_world_get_default (), "window-object-cleared", G_CALLBACK (window_object_cleared_callback), NULL);
+
+ // Create DBus server for this web extension
+ webkitgtk_extension_dbus_name = combineStrInt((char *) WEBKITGTK_EXTENSION_DBUS_NAME_PREFIX, (gint32) getpid());
+ webkitgtk_extension_dbus_path = combineStrInt((char *) WEBKITGTK_EXTENSION_DBUS_PATH_PREFIX, (gint32) getpid());
+
+ dbus_introspection_xml = g_new (gchar, strlen(dbus_introspection_xml_template) + strlen(WEBKITGTK_EXTENSION_DBUS_INTERFACE) + 1);
+ g_sprintf (dbus_introspection_xml, dbus_introspection_xml_template, WEBKITGTK_EXTENSION_DBUS_INTERFACE);
+ dbus_node = g_dbus_node_info_new_for_xml (dbus_introspection_xml, NULL);
+ g_assert (dbus_node != NULL);
+
+ guint owner_id;
+ owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
+ webkitgtk_extension_dbus_name,
+ G_BUS_NAME_OWNER_FLAGS_REPLACE | G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT,
+ on_bus_acquired,
+ NULL, /* on_name_acquired */
+ NULL, /* on_name_lost */
+ NULL,
+ NULL);
+ g_assert (owner_id != 0);
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_extension.h b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_extension.h
index 72a507ba81..4d2713cd76 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_extension.h
+++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_extension.h
@@ -1,4 +1,4 @@
-/*******************************************************************************
+ /*******************************************************************************
* Copyright (c) 2017 Red Hat and others. 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
@@ -12,12 +12,9 @@
* Contributors:
* Red Hat - initial API and implementation
*******************************************************************************/
-
-
#ifndef INC_webkit_extension_H
#define INC_webkit_extension_H
-
#include <string.h>
#include <glib.h>
@@ -29,12 +26,10 @@
#include <unistd.h>
#include <stdio.h>
-
// These 2 are only for getpid();
#include <sys/types.h>
#include <unistd.h>
-
#include <webkit2/webkit-web-extension.h>
#include <JavaScriptCore/JavaScript.h>
@@ -42,22 +37,40 @@
#include <JavaScriptCore/JSObjectRef.h>
#include <JavaScriptCore/JSStringRef.h>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+#define WEBKITGTK_EXTENSION_DBUS_NAME_PREFIX "org.eclipse.swt.webkitgtk_extension"
+#define WEBKITGTK_EXTENSION_DBUS_PATH_PREFIX "/org/eclipse/swt/webkitgtk_extension/gdbus/"
+#define WEBKITGTK_EXTENSION_DBUS_INTERFACE "org.eclipse.swt.webkitgtk_extension.gdbusInterface"
+
+#define WEBKIT_MAIN_PROCESS_DBUS_NAME_PREFIX "org.eclipse.swt"
+#define WEBKIT_MAIN_PROCESS_DBUS_PATH_PREFIX "/org/eclipse/swt/gdbus/"
+
+static gchar* webkitgtk_extension_dbus_name;
+static gchar* webkitgtk_extension_dbus_path;
+
+static WebKitWebExtension *this_extension;
+
+static GDBusNodeInfo *dbus_node;
+static GDBusInterfaceInfo *dbus_interface;
+static gchar* dbus_introspection_xml;
+static gchar* dbus_introspection_xml_template =
+"<node>"
+ "<interface name='%s'>"
+
+ "<method name='webkitgtk_extension_register_function'>"
+ "<arg type='t' name='page_id' direction='in'/>"
+ "<arg type='s' name='script' direction='in'/>"
+ "<arg type='s' name='url' direction='in'/>"
+ "<arg type='b' name='result' direction='out'/>"
+ "</method>"
+
+ "<method name='webkitgtk_extension_deregister_function'>"
+ "<arg type='t' name='page_id' direction='in'/>"
+ "<arg type='s' name='script' direction='in'/>"
+ "<arg type='s' name='url' direction='in'/>"
+ "<arg type='b' name='result' direction='out'/>"
+ "</method>"
+
+ "</interface>"
+"</node>";
#endif /*INC_webkit_extension_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 32ad50e13e..84ee7e587d 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
@@ -167,6 +167,7 @@ char * WebKitGTK_nativeFunctionNames[] = {
"_1webkit_1web_1view_1get_1load_1status",
"_1webkit_1web_1view_1get_1main_1frame",
"_1webkit_1web_1view_1get_1main_1resource",
+ "_1webkit_1web_1view_1get_1page_1id",
"_1webkit_1web_1view_1get_1progress",
"_1webkit_1web_1view_1get_1settings",
"_1webkit_1web_1view_1get_1title",
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 dab44c08fe..22196ffafa 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
@@ -177,6 +177,7 @@ typedef enum {
_1webkit_1web_1view_1get_1load_1status_FUNC,
_1webkit_1web_1view_1get_1main_1frame_FUNC,
_1webkit_1web_1view_1get_1main_1resource_FUNC,
+ _1webkit_1web_1view_1get_1page_1id_FUNC,
_1webkit_1web_1view_1get_1progress_FUNC,
_1webkit_1web_1view_1get_1settings_FUNC,
_1webkit_1web_1view_1get_1title_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 81b218af3c..470ae9959f 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
@@ -127,6 +127,7 @@ class WebKit extends WebBrowser {
*/
long /*int*/ webView;
long /*int*/ scrolledWindow;
+ long pageId;
/** Webkit1 only. Used by the externalObject for javascript callback to java. */
long /*int*/ webViewData;
@@ -419,12 +420,52 @@ class WebKit extends WebBrowser {
@Override
public void createFunction(BrowserFunction function) {
if (WEBKIT2) {
- if (!Webkit2Extension.gdbus_init()) {
- System.err.println("SWT Webkit Warning: Webkit extension failed to initialize. BrowserFunction will not work.: " + function.name);
+ if (!WebkitGDBus.initialized) {
+ System.err.println("SWT webkit: WebkitGDBus and/or Webkit2Extension not loaded, BrowserFunction will not work." +
+ "Tried to create "+ function.name);
return;
}
}
super.createFunction(function);
+ if (WEBKIT2) {
+ String url = this.getUrl().isEmpty() ? "nullURL" : this.getUrl();
+ /*
+ * If the proxy to the extension has not yet been loaded, store the BrowserFunction page ID,
+ * function string, and URL in a HashMap. Once the proxy to the extension is loaded, these
+ * functions will be sent to and registered in the extension.
+ */
+ if (!WebkitGDBus.proxyToExtension) {
+ WebkitGDBus.functionsPending = true;
+ ArrayList<ArrayList<String>> list = new ArrayList<>();
+ ArrayList<String> functionAndUrl = new ArrayList<>();
+ functionAndUrl.add(0, function.functionString);
+ functionAndUrl.add(1, url);
+ list.add(functionAndUrl);
+ ArrayList<ArrayList<String>> existing = WebkitGDBus.pendingBrowserFunctions.putIfAbsent(this.pageId, list);
+ if (existing != null) {
+ existing.add(functionAndUrl);
+ }
+ } else {
+ // If the proxy to the extension is already loaded, register the function in the extension via DBus
+ boolean successful = webkit_extension_modify_function(this.pageId, function.functionString, url, "register");
+ if (!successful) {
+ System.err.println("SWT webkit: failure registering BrowserFunction " + function.name);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void destroyFunction (BrowserFunction function) {
+ // Only deregister functions if the proxy to the extension has been loaded
+ if (WebkitGDBus.proxyToExtension && WEBKIT2) {
+ String url = this.getUrl().isEmpty() ? "nullURL" : this.getUrl();
+ boolean successful = webkit_extension_modify_function(this.pageId, function.functionString, url, "deregister");
+ if (!successful) {
+ System.err.println("SWT webkit: failure deregistering BrowserFunction from extension " + function.name);
+ }
+ }
+ super.destroyFunction(function);
}
private static String getInternalErrorMsg () {
@@ -458,6 +499,7 @@ class WebKit extends WebBrowser {
static class Webkit2Extension {
/** Note, if updating this, you need to change it also in webkitgtk_extension.c */
private static final String javaScriptFunctionName = "webkit2callJava"; // $NON-NLS-1$
+ private static final String webkitWebExtensionIdentifier = "webkitWebExtensionIdentifer"; // $NON-NLS-1$
private static Callback initializeWebExtensions_callback;
private static int uniqueID = OS.getpid();
@@ -470,6 +512,9 @@ class WebKit extends WebBrowser {
static String getJavaScriptFunctionName() {
return javaScriptFunctionName;
}
+ static String getWebExtensionIdentifer() {
+ return webkitWebExtensionIdentifier;
+ }
static String getJavaScriptFunctionDeclaration(long /*int*/ webView) {
return "if (!window.callJava) {\n"
+ " window.callJava = function callJava(index, token, args) {\n"
@@ -479,6 +524,12 @@ class WebKit extends WebBrowser {
}
static void init() {
+ /*
+ * Initialize GDBus before the extension, as the extension initialization callback at the C level
+ * sends data back to SWT via GDBus. Failure to load GDBus here will result in crashes.
+ * See bug 536141.
+ */
+ gdbus_init();
initializeWebExtensions_callback = new Callback(Webkit2Extension.class, "initializeWebExtensions_callback", void.class, new Type [] {long.class, long.class});
if (initializeWebExtensions_callback.getAddress() == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
if (WebKitGTK.webkit_get_minor_version() >= 4) { // Callback exists only since 2.04
@@ -1199,6 +1250,7 @@ public void create (Composite parent, int style) {
OS.g_signal_connect (webView, OS.focus_out_event, JSDOMEventProc.getAddress (), WIDGET_EVENT);
// if connecting any other special gtk event to webkit, add SWT.* to w2_passThroughSwtEvents above.
}
+ this.pageId = WebKitGTK.webkit_web_view_get_page_id (webView);
if (WEBKIT1) {
OS.g_signal_connect (webView, OS.button_press_event, JSDOMEventProc.getAddress (), 0);
OS.g_signal_connect (webView, OS.button_release_event, JSDOMEventProc.getAddress (), 0);
@@ -1522,6 +1574,46 @@ void nonBlockingExecute(String script) {
}
}
+/**
+ * Modifies a BrowserFunction in the web extension. This method can be used to register/deregister BrowserFunctions
+ * in the web extension, so that those BrowserFunctions are executed upon triggering of the object_cleared callback (in
+ * the extension, not in Java).
+ *
+ * This function will return true if: the operation succeeds synchronously, or if the synchronous call timed out and an
+ * asynchronous call was performed instead. All other cases will return false.
+ *
+ * Supported actions: "register" and "deregister"
+ *
+ * @param pageId the page ID of the WebKit instance/web page
+ * @param function the function string
+ * @param url the URL
+ * @param action the action being performed on the function, which will be used to form the DBus method name.
+ * @return true if the action succeeded (or was performed asynchronously), false if it failed
+ */
+private boolean webkit_extension_modify_function (long pageId, String function, String url, String action){
+ long /*int*/ args[] = { OS.g_variant_new_uint64(pageId),
+ OS.g_variant_new_string (Converter.javaStringToCString(function)),
+ OS.g_variant_new_string (Converter.javaStringToCString(url))};
+ final long /*int*/ argsTuple = OS.g_variant_new_tuple(args, args.length);
+ if (argsTuple == 0) return false;
+ String dbusMethodName = "webkitgtk_extension_" + action + "_function";
+ Object returnVal = WebkitGDBus.callExtensionSync(argsTuple, dbusMethodName);
+ if (returnVal instanceof Boolean) {
+ return (Boolean) returnVal;
+ } else if (returnVal instanceof String) {
+ String returnString = (String) returnVal;
+ /*
+ * Call the extension asynchronously if a synchronous call times out.
+ * Note: this is a pretty rare case, and usually only happens when running test cases.
+ * See bug 536141.
+ */
+ if ("timeout".equals(returnString)) {
+ return WebkitGDBus.callExtensionAsync(argsTuple, dbusMethodName);
+ }
+ }
+ return false;
+}
+
@Override
public boolean execute (String script) {
if (WEBKIT2){
@@ -3284,7 +3376,6 @@ long /*int*/ webkit_load_changed (long /*int*/ web_view, int status, long user_d
return handleLoadCommitted (uri, true);
}
case WebKitGTK.WEBKIT2_LOAD_FINISHED: {
- registerBrowserFunctions(); // Bug 508217
addEventHandlers (web_view, true);
long /*int*/ title = WebKitGTK.webkit_web_view_get_title (webView);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebkitGDBus.java b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebkitGDBus.java
index de2dc641ea..d7ec16e391 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebkitGDBus.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebkitGDBus.java
@@ -15,6 +15,8 @@
package org.eclipse.swt.browser;
+import java.util.*;
+
import org.eclipse.swt.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.gtk.*;
@@ -33,11 +35,29 @@ import org.eclipse.swt.internal.gtk.*;
*/
class WebkitGDBus {
private static String DBUS_SERVICE_NAME;
- private static final String DBUS_OBJECT_NAME = "/org/eclipse/swt/gdbus";
+ private static final String DBUS_OBJECT_PATH = "/org/eclipse/swt/gdbus";
private static final String INTERFACE_NAME = "org.eclipse.swt.gdbusInterface";
+ private static final String EXTENSION_INTERFACE_NAME = "org.eclipse.swt.webkitgtk_extension.gdbusInterface";
+ private static String EXTENSION_DBUS_NAME;
+ private static String EXTENSION_DBUS_PATH;
/** Accepted methods over gdbus */
private static final String webkit2callJava = WebKit.Webkit2Extension.getJavaScriptFunctionName();
+ private static final String webkitWebExtensionIdentifier = WebKit.Webkit2Extension.getWebExtensionIdentifer();
+
+ /** Proxy connection to the web extension.*/
+ static long /*int*/ proxy;
+ /** A field that is set to true if the proxy connection has been established, false otherwise */
+ static boolean proxyToExtension;
+ /** Set to true if there are <code>BrowserFunction</code> objects waiting to be registered with the web extension.*/
+ static boolean functionsPending;
+ /**
+ * HashMap that stores any BrowserFunctions which have been created but not yet registered with the web extension.
+ * These functions will be registered with the web extension as soon as the proxy to the extension is set up.
+ *
+ * The format of the HashMap is (page ID, list of function string and URL).
+ */
+ static HashMap<Long, ArrayList<ArrayList<String>>> pendingBrowserFunctions = new HashMap<>();
/**
@@ -77,6 +97,11 @@ class WebkitGDBus {
+ " <arg type='" + OS.DBUS_TYPE_SINGLE_COMPLETE + "' name='arguments' direction='in'/>"
+ " <arg type='" + OS.DBUS_TYPE_SINGLE_COMPLETE + "' name='result' direction='out'/>"
+ " </method>"
+ + " <method name='" + webkitWebExtensionIdentifier + "'>"
+ + " <arg type='"+ OS.DBUS_TYPE_STRING + "' name='webExtensionDbusName' direction='in'/>"
+ + " <arg type='"+ OS.DBUS_TYPE_STRING + "' name='webExtensionDbusPath' direction='in'/>"
+ + " <arg type='"+ OS.DBUS_TYPE_STRUCT_ARRAY_BROWSER_FUNCS + "' name='result' direction='out'/>"
+ + " </method>"
+ " </interface>"
+ "</node>";
@@ -96,6 +121,9 @@ class WebkitGDBus {
private static Callback onNameLostCallback;
private static Callback handleMethodCallback;
+ /** Callback for asynchronous proxy calls to the extension */
+ private static Callback callExtensionAsyncCallback;
+
static {
onBusAcquiredCallback = new Callback (WebkitGDBus.class, "onBusAcquiredCallback", 3); //$NON-NLS-1$
if (onBusAcquiredCallback.getAddress () == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
@@ -108,9 +136,12 @@ class WebkitGDBus {
handleMethodCallback = new Callback (WebkitGDBus.class, "handleMethodCallback", 8); //$NON-NLS-1$
if (handleMethodCallback.getAddress () == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
+
+ callExtensionAsyncCallback = new Callback (WebkitGDBus.class, "callExtensionAsyncCallback", 3); //$NON-NLS-1$
+ if (callExtensionAsyncCallback.getAddress () == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
}
- static private boolean initialized;
+ static boolean initialized;
/** This method is not intended to be referenced by clients. Internal class. */
static void init(String uniqueId) {
@@ -169,7 +200,7 @@ class WebkitGDBus {
// Other times it validates it fine. We ignore for now as 32bit will be dropped anyway.
OS.g_dbus_connection_register_object(
connection,
- Converter.javaStringToCString(DBUS_OBJECT_NAME),
+ Converter.javaStringToCString(DBUS_OBJECT_PATH),
interface_info,
vtable,
0, // user_data
@@ -177,7 +208,7 @@ class WebkitGDBus {
error);
if (error[0] != 0) {
- System.err.println("SWT WebkitGDBus: Failed to register object: " + DBUS_OBJECT_NAME);
+ System.err.println("SWT WebkitGDBus: Failed to register object: " + DBUS_OBJECT_PATH);
return 0;
}
}
@@ -236,19 +267,123 @@ class WebkitGDBus {
String java_method_name = Converter.cCharPtrToJavaString(method_name, false);
Object result = null;
- if (java_method_name != null && java_method_name.equals(webkit2callJava)) {
- try {
- Object [] java_parameters = (Object []) convertGVariantToJava(gvar_parameters);
- result = WebKit.Webkit2Extension.webkit2callJavaCallback(java_parameters);
- } catch (Exception e) {
- // gdbus should always return to prevent extension from hanging.
- result = (String) WebBrowser.CreateErrorString (e.getLocalizedMessage ());
- System.err.println("SWT Webkit: Exception occured in Webkit2 callback logic. Bug?");
+ if (java_method_name != null) {
+ if (java_method_name.equals(webkit2callJava)) {
+ try {
+ Object [] java_parameters = (Object []) convertGVariantToJava(gvar_parameters);
+ result = WebKit.Webkit2Extension.webkit2callJavaCallback(java_parameters);
+ } catch (Exception e) {
+ // gdbus should always return to prevent extension from hanging.
+ result = (String) WebBrowser.CreateErrorString (e.getLocalizedMessage ());
+ System.err.println("SWT Webkit: Exception occured in Webkit2 callback logic. Bug?");
+ }
+ } else if (java_method_name.equals(webkitWebExtensionIdentifier)) {
+ Object [] nameArray = (Object []) convertGVariantToJava(gvar_parameters);
+ if (nameArray [0] != null && nameArray[0] instanceof String) EXTENSION_DBUS_NAME = (String) nameArray[0];
+ if (nameArray [1] != null && nameArray[1] instanceof String) EXTENSION_DBUS_PATH = (String) nameArray[1];
+ proxyToExtension = proxyToExtensionInit();
+ if (proxyToExtension) {
+ invokeReturnValueExtensionIdentifier(pendingBrowserFunctions, invocation);
+ } else {
+ invokeReturnValueExtensionIdentifier(null, invocation);
+ System.err.println("SWT webkit: proxy to web extension failed to load, BrowserFunction may not work.");
+ }
+ return 0;
+ }
+ } else {
+ result = (String) "SWT webkit: GDBus called an unknown method?";
+ System.err.println("SWT webkit: Received a call from an unknown method: " + java_method_name);
+ }
+ invokeReturnValue(result, invocation);
+ return 0;
+ }
+
+ @SuppressWarnings("unused")
+ private static long /*int*/ callExtensionAsyncCallback (long /*int*/ source_object, long /*int*/ res, long /*int*/ user_data) {
+ long /*int*/[] gerror = new long /*int*/[1];
+ long /*int*/ result = OS.g_dbus_proxy_call_finish (proxy, res, gerror);
+ if (gerror[0] != 0){
+ long /*int*/ errMsg = OS.g_error_get_message(gerror[0]);
+ String msg = Converter.cCharPtrToJavaString(errMsg, false);
+ System.err.println("SWT webkit: There was an error executing something asynchronously with the extension (Java callback).");
+ System.err.println("SWT webkit: the error message provided is " + msg);
+ OS.g_error_free(gerror[0]);
+ }
+ return 0;
+ }
+
+ /**
+ * Returns a GVariant to the DBus invocation of the extension identifier method. When the extension
+ * is initialized it sends a DBus message to the SWT webkit instance. As a return value, the SWT webkit
+ * instance sends any BrowserFunctions that have been registered. If no functions have been registered,
+ * an "empty" function with a page ID of -1 is sent.
+ *
+ * @param map the HashMap of BrowserFunctions waiting to be registered in the extension, or null
+ * if you'd like to explicitly send an empty function signature
+ * @param invocation the GDBus invocation to return the value on
+ */
+ private static void invokeReturnValueExtensionIdentifier (HashMap<Long, ArrayList<ArrayList<String>>> map,
+ long /*int*/ invocation) {
+ long /*int*/ resultGVariant;
+ long /*int*/ builder;
+ long /*int*/ type = OS.g_variant_type_new(OS.G_VARIANT_TYPE_ARRAY_BROWSER_FUNCS);
+ builder = OS.g_variant_builder_new(type);
+ if (builder == 0) return;
+ Object [] tupleArray = new Object[3];
+ boolean sendEmptyFunction;
+ if (map == null) {
+ sendEmptyFunction = true;
+ } else {
+ sendEmptyFunction = map.isEmpty() && !functionsPending;
+ }
+ /*
+ * No functions to register, send a page ID of -1 and empty strings.
+ */
+ if (sendEmptyFunction) {
+ tupleArray[0] = (long)-1;
+ tupleArray[1] = "";
+ tupleArray[2] = "";
+ long /*int*/ tupleGVariant = convertJavaToGVariant(tupleArray);
+ if (tupleGVariant != 0) {
+ OS.g_variant_builder_add_value(builder, tupleGVariant);
+ } else {
+ System.err.println("SWT webkit: error creating empty BrowserFunction GVariant tuple, skipping.");
}
} else {
- result = (String) "SWT Webkit: Gdbus called an unknown method?";
- System.err.println("SWT WebkitGDBus: Received a call from an unknown method: " + java_method_name);
+ for (long id : map.keySet()) {
+ ArrayList<ArrayList<String>> list = map.get(id);
+ if (list != null) {
+ for (ArrayList<String> stringList : list) {
+ Object [] stringArray = stringList.toArray();
+ if (stringArray.length > 2) {
+ System.err.println("SWT webkit: String array with BrowserFunction and URL should never have"
+ + "more than 2 Strings");
+ }
+ tupleArray[0] = id;
+ System.arraycopy(stringArray, 0, tupleArray, 1, 2);
+ long /*int*/ tupleGVariant = convertJavaToGVariant(tupleArray);
+ if (tupleGVariant != 0) {
+ OS.g_variant_builder_add_value(builder, tupleGVariant);
+ } else {
+ System.err.println("SWT webkit: error creating BrowserFunction GVariant tuple, skipping.");
+ }
+ }
+ }
+ }
+ }
+ resultGVariant = OS.g_variant_builder_end(builder);
+ String typeString = Converter.cCharPtrToJavaString(OS.g_variant_get_type_string(resultGVariant), false);
+ if (!OS.DBUS_TYPE_STRUCT_ARRAY_BROWSER_FUNCS.equals(typeString)) {
+ System.err.println("An error packaging the GVariant occurred: type mismatch.");
}
+ long /*int*/ [] variants = {resultGVariant};
+ long /*int*/ finalGVariant = OS.g_variant_new_tuple(variants, 1);
+ OS.g_dbus_method_invocation_return_value(invocation, finalGVariant);
+ OS.g_variant_builder_unref(builder);
+ return;
+ }
+
+ private static void invokeReturnValue (Object result, long /*int*/ invocation) {
long /*int*/ resultGVariant = 0;
try {
resultGVariant = convertJavaToGVariant(new Object [] {result}); // Result has to be a tuple.
@@ -258,10 +393,98 @@ class WebkitGDBus {
resultGVariant = convertJavaToGVariant(new Object [] {errMsg});
}
OS.g_dbus_method_invocation_return_value(invocation, resultGVariant);
- return 0; // void return value.
+ return; // void return value.
}
+ /**
+ * Initializes the proxy connection to the web extension.
+ *
+ * @return true if establishing the proxy connections succeeded,
+ * false otherwise
+ */
+ private static boolean proxyToExtensionInit() {
+ if (proxy != 0) {
+ return true;
+ } else {
+ if (EXTENSION_DBUS_NAME != null && EXTENSION_DBUS_PATH != null) {
+ long /*int*/ [] error = new long /*int*/ [1];
+ byte [] name = Converter.javaStringToCString(EXTENSION_DBUS_NAME);
+ byte [] path = Converter.javaStringToCString(EXTENSION_DBUS_PATH);
+ byte [] interfaceName = Converter.javaStringToCString(EXTENSION_INTERFACE_NAME);
+ proxy = OS.g_dbus_proxy_new_for_bus_sync(OS.G_BUS_TYPE_SESSION, OS.G_DBUS_PROXY_FLAGS_NONE, 0, name, path, interfaceName, 0, error);
+ if (error[0] != 0) {
+ long /*int*/ errMsg = OS.g_error_get_message(error[0]);
+ String msg = Converter.cCharPtrToJavaString(errMsg, false);
+ OS.g_error_free(error[0]);
+ System.err.println("SWT webkit: there was an error establishing the proxy connection to the extension. " +
+ " The error is " + msg);
+ return false;
+ } else {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Calls the web extension synchronously. Returns true if the operation succeeded, and false
+ * otherwise (or if the operation times out).
+ *
+ * @param params a pointer to the GVariant containing the parameters
+ * @param methodName a String representing the DBus method name in the extension
+ * @return an Object representing the return value from DBus in boolean form
+ */
+ static Object callExtensionSync (long /*int*/ params, String methodName) {
+ long /*int*/[] gerror = new long /*int*/ [1]; // GError **
+ long /*int*/ gVariant = OS.g_dbus_proxy_call_sync(proxy, Converter.javaStringToCString(methodName),
+ params, OS.G_DBUS_CALL_FLAGS_NO_AUTO_START, 1000, 0, gerror);
+ if (gerror[0] != 0) {
+ long /*int*/ errMsg = OS.g_error_get_message(gerror[0]);
+ String msg = Converter.cCharPtrToJavaString(errMsg, false);
+ /*
+ * Don't print console warnings for timeout errors, as we can handle these ourselves.
+ * Note, most timeout errors happen only when running test cases, not during "normal" use.
+ */
+ if (msg != null && (!msg.contains("Timeout") && !msg.contains("timeout"))) {
+ System.err.println("SWT webkit: There was an error executing something synchronously with the extension.");
+ System.err.println("SWT webkit: The error message is: " + msg);
+ return (Object) false;
+ }
+ OS.g_error_free(gerror[0]);
+ return (Object) "timeout";
+ }
+ Object resultObject = gVariant != 0 ? convertGVariantToJava(gVariant) : (Object) false;
+ // Sometimes we get back tuples from GDBus, which get converted into Object arrays. In this case
+ // we only care about the first value, since the extension never returns anything more than that.
+ if (resultObject instanceof Object[]) {
+ return ((Object []) resultObject)[0];
+ }
+ return resultObject;
+ }
+ /**
+ * Calls the web extension asynchronously. Note, this method returning true does not
+ * guarantee the operation's success, it only means no errors occurred.
+ *
+ * @param params a pointer to the GVariant containing the parameters
+ * @param methodName a String representing the DBus method name in the extension
+ * @return true if the extension was called without errors, false otherwise
+ */
+ static boolean callExtensionAsync (long /*int*/ params, String methodName) {
+ long /*int*/[] gerror = new long /*int*/ [1]; // GError **
+ OS.g_dbus_proxy_call(proxy, Converter.javaStringToCString(methodName),
+ params, OS.G_DBUS_CALL_FLAGS_NO_AUTO_START, 1000, 0, callExtensionAsyncCallback.getAddress(), gerror);
+ if (gerror[0] != 0) {
+ long /*int*/ errMsg = OS.g_error_get_message(gerror[0]);
+ String msg = Converter.cCharPtrToJavaString(errMsg, false);
+ System.err.println("SWT webkit: There was an error executing something asynchronously with the extension.");
+ System.err.println("SWT webkit: The error message is: " + msg);
+ OS.g_error_free(gerror[0]);
+ return false;
+ }
+ return true;
+ }
/* TYPE NOTES
*
@@ -314,6 +537,10 @@ class WebkitGDBus {
return new Double(OS.g_variant_get_double(gVariant));
}
+ if (OS.g_variant_is_of_type(gVariant, OS.G_VARIANT_TYPE_UINT64)){
+ return new Long(OS.g_variant_get_uint64(gVariant));
+ }
+
if (OS.g_variant_is_of_type(gVariant, OS.G_VARIANT_TYPE_STRING)){
return Converter.cCharPtrToJavaString(OS.g_variant_get_string(gVariant, null), false);
}
@@ -346,6 +573,10 @@ class WebkitGDBus {
return OS.g_variant_new_byte(WebkitGDBus.SWT_DBUS_MAGIC_NUMBER_NULL); // see: WebKitGTK.java 'TYPE NOTES'
}
+ if (javaObject instanceof Long) {
+ return OS.g_variant_new_uint64((Long) javaObject);
+ }
+
if (javaObject instanceof String) {
return OS.g_variant_new_string (Converter.javaStringToCString((String) javaObject));
}
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 11ccd2261f..c1df6956a2 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
@@ -1722,6 +1722,17 @@ public static final long /*int*/ webkit_web_view_get_main_frame (long /*int*/ we
}
/** @method flags=dynamic */
+public static final native long /*int*/ _webkit_web_view_get_page_id (long /*int*/ web_view);
+public static final long /*int*/ webkit_web_view_get_page_id (long /*int*/ web_view) {
+ lock.lock();
+ try {
+ return _webkit_web_view_get_page_id (web_view);
+ } finally {
+ lock.unlock();
+ }
+}
+
+/** @method flags=dynamic */
public static final native double _webkit_web_view_get_progress (long /*int*/ web_view);
public static final double webkit_web_view_get_progress (long /*int*/ web_view) {
assert WEBKIT1 : Webkit1AssertMsg;
diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug536141_BrowserFunctionLostReload.java b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug536141_BrowserFunctionLostReload.java
new file mode 100644
index 0000000000..09dec0b2aa
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug536141_BrowserFunctionLostReload.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Red Hat and others. 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 - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.tests.gtk.snippets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.browser.Browser;
+import org.eclipse.swt.browser.BrowserFunction;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/*
+ * Title: Bug 536141: [Webkit2][Gtk] BrowserFunction lost after page reload on Linux/GTK
+ * How to run: Read the instructions printed in the console
+ * Bug description: N/A
+ * Expected results: BrowserFunctions should be added/removed as expected, see instructions for details
+ * GTK Version(s):
+ */
+public class Bug536141_BrowserFunctionLostReload {
+
+ static int count = 0;
+
+ public static void main(String[] args) {
+ Display display = new Display();
+ Shell shell = new Shell(display);
+ shell.setSize(500, 600);
+
+ GridLayout gridLayout = new GridLayout();
+ shell.setLayout(gridLayout);
+
+ final Text jsConsole = new Text(shell, SWT.BORDER);
+// jsConsole.setText("document.body.innerHTML = theJavaFunction(123, 'hello', null, true)");
+ jsConsole.setText("document.body.innerHTML = theJavaFunction()"); // Case where there are no paramaters.
+ jsConsole.setSelection(jsConsole.getText().length());
+ GridData data = new GridData(SWT.FILL, SWT.BEGINNING, true, false);
+ jsConsole.setLayoutData(data);
+
+ final Browser browser = new Browser(shell, SWT.NONE);
+ browser.setText("hello <b>world!</b>");
+ data = new GridData(SWT.FILL, SWT.FILL, true, true);
+ browser.setLayoutData(data);
+
+ jsConsole.addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if (e.keyCode == 13) { // 13 = Enter
+ browser.execute(jsConsole.getText());
+ }
+ }
+ });
+
+ Button loadNewPage = new Button(shell, SWT.PUSH);
+ loadNewPage.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+ loadNewPage.setText("Load new page");
+ loadNewPage.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ browser.setText("New page!" + count++);
+ }
+ });
+
+
+ // BrowserFunction Code
+ @SuppressWarnings("unused")
+ final BrowserFunction function = new CustomFunction (browser, "theJavaFunction");
+
+ Button create = new Button (shell, SWT.PUSH);
+ create.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+ create.setText("Create function");
+ create.addSelectionListener(new SelectionListener () {
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {}
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ System.out.println("creating function");
+ @SuppressWarnings("unused")
+ final BrowserFunction function2 = new CustomFunction (browser, "theJavaFunction2");
+ }
+ });
+
+ Button destroy = new Button (shell, SWT.PUSH);
+ destroy.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+ destroy.setText("Destroy function");
+ destroy.addSelectionListener(new SelectionListener () {
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {}
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ System.out.println("destroying function");
+ function.dispose();
+ }
+ });
+ shell.open();
+ System.out.println("INSTRUCTIONS: pressing the \"Create function\" button will create a function called theJavaFunction2.");
+ System.out.println("Pressing the \"Destroy function\" button will destory the function called theJavaFunction.");
+ System.out.println("To test that theJavaFunction2 was created, add the \"2\""
+ + " at the end of theJavaFunction in the console and press enter.");
+ System.out.println("To test that theJavaFunction was deleted, remove the \"2\""
+ + " at the end of theJavaFunction in the console and press enter.");
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch())
+ display.sleep();
+ }
+ display.dispose();
+ }
+
+ static class CustomFunction extends BrowserFunction { // copied from snippet 307
+ CustomFunction (Browser browser, String name) {
+ super (browser, name);
+ }
+ @Override
+ public Object function (Object[] arguments) {
+ System.out.println ("theJavaFunction() called from javascript with args:");
+ for (int i = 0; i < arguments.length; i++) {
+ Object arg = arguments[i];
+ if (arg == null) {
+ System.out.println ("\t-->null");
+ } else {
+ System.out.println ("\t-->" + arg.getClass ().getName () + ": " + arg.toString ());
+ }
+ }
+ return arguments;
+// return new Point(1, 2);
+
+// Object returnValue = new Object[] {
+// new Short ((short)3),
+// new Boolean (true),
+// null,
+// new Object[] {"a string", new Boolean (false)},
+// "hi",
+// new Float (2.0f / 3.0f),
+// };
+// return returnValue;
+
+// return new Double(42.0);
+ }
+ }
+}

Back to the top