Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Williams2018-07-12 20:14:54 +0000
committerEric Williams2018-08-14 14:51:19 +0000
commitf0fe56670826e5b46e2c9a52c132ec39f531e136 (patch)
treef6d509251f92ea8e583bd09986c1e0ec1ae88e17 /bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk
parentdfb0cb3dbe3b038908c695231ad8a8f200ee1500 (diff)
downloadeclipse.platform.swt-f0fe56670826e5b46e2c9a52c132ec39f531e136.tar.gz
eclipse.platform.swt-f0fe56670826e5b46e2c9a52c132ec39f531e136.tar.xz
eclipse.platform.swt-f0fe56670826e5b46e2c9a52c132ec39f531e136.zip
Bug 536141: [Webkit2][Gtk] BrowserFunction lost after page reload on
Linux/GTK The main cause of this bug is that web pages load too quickly -- by the time the BrowserFunctions are re-registered asynchronously from Java, the extension has loaded the page. BEFORE THIS PATCH: BrowserFunctions were registered asynchronously from Java into the web extension (C). This was done either at the outset (WebBrowser.createFunction()), or after every page load (Webkit.webkit_load_changed() callback). AFTER THIS PATCH: The fix is relatively straightforward, yet GDBus adds a lot of overhead. Instead of constantly registering BrowserFunctions from Java, we load them into the web extension on creation. This hands off the responsibility of re-registering BrowserFunctions to the web extension, which reduces overhead and ensures the functions are registered/executed before the page loads. The BrowserFunctions are stored at the C level in the extension, using a linked list. Whenever the "object-cleared" callback is triggered in the extension, the linked list is iterated over and any BrowserFunctions for that page are re-registered. Chronological ordering of information flow from SWT -> web extension via GDBus. 1) SWT Webkit class is loaded. SWT GDBus server is created. 2) SWT Webkit creates the extension, passing it the information of the SWT Webkit GDBus server. 3) The extension's initialization callback is called in C. 4) In this callback the extension contacts the SWT Webkit GDBus server and provides it with information such as its PID and name. 5) SWT Webkit acknowledges this information, and sends back any BrowserFunctions that were created before the extension loaded. 6) The extension adds these BrowserFunctions to its linked list. 7) Any subsequent BrowserFunctions are added to the extension's linked list by calling the extension's GDBus server synchronously. In the event of a GDBus timeout (happens sometimes when running tests), the GDBus call is made asynchronously. This functionality can be tested with the attached snippet. AllBrowserTests pass without issue, and there are no visible Browser issues in the IDE. The plugin attached to the initial bug report is now functional. Change-Id: Iddc5f2e69f0a7fd4500bd8228f0bc46c4b3a6322 Signed-off-by: Eric Williams <ericwill@redhat.com>
Diffstat (limited to 'bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk')
-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
8 files changed, 632 insertions, 59 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 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;

Back to the top