org.eclipse.swt.browser.WebkitGDBus Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.eclipse.swt.gtk.linux.ppc64le Show documentation
Show all versions of org.eclipse.swt.gtk.linux.ppc64le Show documentation
Standard Widget Toolkit for GTK on ppc64le
/*******************************************************************************
* 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
* 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.browser;
import java.util.*;
import org.eclipse.swt.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.gtk.*;
import org.eclipse.swt.widgets.*;
/**
* Logic for Webkit to interact with it's Webkit extension via GDBus.
*
* While this class supports quite a bit of GDBus and gvariant support, it is by no means a complete
* implementation and it's tailored to support Java to Javascript conversion. (E.g all Numbers are converted to Double).
* If this is ever to be used outside of Webkit, then care must be taken to deal with
* cases that are not currently implemented/used. See: WebKitGTK.java 'TYPE NOTES'
*
* For hygiene purposes, GVariant types should not be leaving this class. Convert on the way in/out.
*
* @category gdbus
*/
class WebkitGDBus {
/*
* If any of the GDBus names/paths/interfaces need to be changed, then they also need to be changed
* in the extension (webkitgtk_extension.c).
*/
/* WEBKITGDBUS_DBUS_NAME isn't actually used but is here for informative purposes */
@SuppressWarnings("unused")
private static final String WEBKITGDBUS_DBUS_NAME = "org.eclipse.swt";
private static final byte [] WEBKITGDBUS_OBJECT_PATH = Converter.javaStringToCString("/org/eclipse/swt/gdbus");
private static final String WEBKITGDBUS_INTERFACE_NAME_JAVA = "org.eclipse.swt.gdbusInterface";
private static final byte [] WEBKITGDBUS_INTERFACE_NAME = Converter.javaStringToCString("org.eclipse.swt.gdbusInterface");
/* Extension connection details, in byte [] form */
private static final byte [] EXTENSION_DBUS_NAME = Converter.javaStringToCString("org.eclipse.swt.webkitgtk_extension");
private static final byte [] EXTENSION_OBJECT_PATH = Converter.javaStringToCString("/org/eclipse/swt/webkitgtk_extension/gdbus");
private static final byte [] EXTENSION_INTERFACE_NAME = Converter.javaStringToCString("org.eclipse.swt.webkitgtk_extension.gdbusInterface");
/** Extension GDBusServer client address */
private static String EXTENSION_DBUS_SERVER_CLIENT_ADDRESS;
/* Accepted GDBus methods */
private static final String webkit2callJava = WebKit.WebKitExtension.getJavaScriptFunctionName();
private static final String webkitWebExtensionIdentifier = WebKit.WebKitExtension.getWebExtensionIdentifier();
/* Connections */
/** GDBusConnection from the web extension */
static long connectionFromExtension;
/** GDBusConnection to the web extension */
static long connectionToExtension;
/** A field that is set to true if the proxy connection has been established, false otherwise. */
static boolean connectionToExtensionCreated;
/* Server related objects */
/** GDBusServer for the main SWT process */
private static long gDBusServer = 0;
/** GDBusAuthObserver for the server */
private static long authObserver = 0;
/** GUID of the GDBusServer */
private static long guid = 0;
/** Display this GDBus class is "attached" to */
static Display display;
// BrowserFunction logic
/** Set to true if there are BrowserFunction
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>> pendingBrowserFunctions = new HashMap<>();
/**
* Interface is read/parsed at run time. No compilation with gdbus-code-gen necessary.
*
* Note,
* - When calling a method via g_dbus_proxy_call_sync(..g_variant params..),
* the g_variant that describes parameters should only mirror incoming parameters.
* Each type is a separate argument.
* e.g:
* g_variant xml:
* "(si)", "string", 42 .. arg type='s'
* .. arg type='i'
*
* - Nested parameters need to have a 2nd bracket around them.
* e.g:
* g_variant xml:
* "((r)i)", *gvariant, 42 .. arg type='r'
* .. arg type='i'
*
* - '@' is a pointer to a gvariant. so '@r' is a pointer to nested type, i.e *gvariant
*
* To understand the mappings, it's good to understand DBus and GVariant's syntax:
* https://dbus.freedesktop.org/doc/dbus-specification.html#idm423
* https://developer.gnome.org/glib/stable/glib-GVariantType.html
*
* Be mindful about only using supported DBUS_TYPE_* , as convert* methods might fail otherwise.
* Alternatively, modify convert* methods.
*/
private static final byte [] WEBKITGDBUS_INTROSPECTION_XML = Converter.javaStringToCString(
""
+ " "
+ " "
+ " "
+ " "
+ " "
+ " "
+ " "
+ " "
+ " "
+ " "
+ " "
+ " "
+ " "
+ " ");
/**
* GDBus/DBus doesn't have a notion of Null.
* To get around this, we use magic numbers to represent special cases.
* Currently this is specific to Webkit to deal with Javascript data type conversions.
* @category gdbus */
private static final byte SWT_DBUS_MAGIC_NUMBER_EMPTY_ARRAY = 101;
/** @category gdbus */
private static final byte SWT_DBUS_MAGIC_NUMBER_NULL = 48;
/** Callback for GDBus method handling */
private static Callback handleMethodCB;
/** Callback for incoming connections to WebkitGDBus' server */
private static Callback newConnectionCB;
/** Callback for creating a new connection to the web extension */
private static Callback newConnectionToExtensionCB;
/** Callback for authenticating connections to WebkitGDBus' server */
private static Callback authenticatePeerCB;
/** Callback for asynchronous proxy calls to the extension */
private static Callback callExtensionAsyncCB;
static {
handleMethodCB = new Callback (WebkitGDBus.class, "handleMethodCB", 8); //$NON-NLS-1$
callExtensionAsyncCB = new Callback (WebkitGDBus.class, "callExtensionAsyncCB", 3); //$NON-NLS-1$
newConnectionCB = new Callback (WebkitGDBus.class, "newConnectionCB", 3); //$NON-NLS-1$
newConnectionToExtensionCB = new Callback (WebkitGDBus.class, "newConnectionToExtensionCB", 3); //$NON-NLS-1$
authenticatePeerCB = new Callback (WebkitGDBus.class, "authenticatePeerCB", 4); //$NON-NLS-1$
}
/** True iff the GDBusServer has been initialized */
static boolean initialized;
/** True iff this class has been attached to a Display */
static boolean attachedToDisplay;
/** This method is in an internal class and is not intended to be referenced by clients. */
static long init () {
if (initialized) {
return gDBusServer;
}
initialized = true;
// Generate address and GUID
long address = construct_server_address();
authObserver = OS.g_dbus_auth_observer_new();
guid = OS.g_dbus_generate_guid();
// Create server
long [] error = new long [1];
gDBusServer = OS.g_dbus_server_new_sync(address, OS.G_DBUS_SERVER_FLAGS_NONE, guid, authObserver, 0, error);
// Connect authentication and incoming connections signals to the newly created server, and start it
if (gDBusServer != 0) {
OS.g_signal_connect(gDBusServer, OS.new_connection, newConnectionCB.getAddress(), 0);
OS.g_signal_connect(authObserver, OS.authorize_authenticated_peer, authenticatePeerCB.getAddress(), 0);
OS.g_dbus_server_start(gDBusServer);
} else {
System.err.println("SWT WebKitGDBus: error creating DBus server " + Display.extractFreeGError(error[0]));
}
return gDBusServer;
}
/**
* Sets the Display for this class. This allows WebkitGDBus to attach its servers and related objects
* to the provided Display. When the Display is disposed, it will will release the GDBus related
* resources.
*
* @param displayToSet the Display to set
*/
static void setDisplay (Display displayToSet) {
if (attachedToDisplay) {
return;
} else {
display = displayToSet;
/*
* Add the GDBusServer, GDBusAuthObserver, and GUID to the Display.
* Note that we don't add the connections yet, because they likely
* don't exist. Those are added in callbacks as they come in.
*/
if (gDBusServer != 0) display.dBusServers.add(gDBusServer);
if (authObserver != 0) display.dBusAuthObservers.add(authObserver);
if (guid != 0) display.dBusGUIDS.add(guid);
attachedToDisplay = true;
}
}
/**
* Constructs an address at which the GDBus server for the SWT main process
* can be reached.
*
* @return a pointer to the address
*/
private static long construct_server_address () {
// On Linux, the address required is used for as an abstract path. If abstract path is not supported
// one must create & manage temporary directories. See Bug562443.
byte [] address = Converter.wcsToMbcs("unix:tmpdir=/tmp/SWT-GDBusServer", true);
long addressPtr = OS.g_malloc(address.length);
C.memmove(addressPtr, address, address.length);
return addressPtr;
}
/**
* This is called when a client call one of the GDBus methods.
*
* Developer note:
* This method can be reached directly from GDBus cmd utility:
* gdbus call --session --dest org.eclipse.swt --object-path /org/eclipse/swt/gdbus --method org.eclipse.swt.gdbusInterface.HelloWorld
* where as you tab complete, you append the UNIQUE_ID.
*
* @param connection GDBusConnection
* @param sender const gchar
* @param object_path const gchar
* @param interface_name const gchar
* @param method_name const gchar
* @param gvar_parameters GVariant
* @param invocation GDBusMethodInvocation
* @param user_data gpointer
* @return
*/
@SuppressWarnings("unused") // callback not directly called by SWT
private static long handleMethodCB (
long connection, long sender,
long object_path, long interface_name,
long method_name, long gvar_parameters,
long invocation, long user_data) {
String java_method_name = Converter.cCharPtrToJavaString(method_name, false);
Object result = null;
if (java_method_name != null) {
if (java_method_name.equals(webkit2callJava)) {
try {
Object [] java_parameters = (Object []) convertGVariantToJava(gvar_parameters);
result = WebKit.WebKitExtension.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 WebkitGDBus: Exception occured in Webkit2 callback logic.");
}
} else if (java_method_name.equals(webkitWebExtensionIdentifier)) {
Object [] serverAddress = (Object []) convertGVariantToJava(gvar_parameters);
if (serverAddress[0] != null && serverAddress[0] instanceof String) {
EXTENSION_DBUS_SERVER_CLIENT_ADDRESS = (String) serverAddress[0];
// Connect to the extension's server by creating a connection asynchronously
createConnectionToExtension();
/*
* Return any pending BrowserFunctions that were created before WebkitGDBus
* was initialized.
*/
invokeReturnValueExtensionIdentifier(pendingBrowserFunctions, invocation);
} else {
System.err.println("SWT WebkitGDBus: error in web extension identification process."
+ " BrowserFunction may not work.");
}
return 0;
}
} else {
result = (String) "SWT WebkitGDBus: GDBus called an unknown method?";
System.err.println("SWT WebkitGDBus: Received a call from an unknown method: " + java_method_name);
}
invokeReturnValue(result, invocation);
return 0;
}
@SuppressWarnings("unused") // callback not directly called by SWT
private static long callExtensionAsyncCB (long source_object, long result, long user_data) {
long [] error = new long [1];
long gVariantResult = OS.g_dbus_connection_call_finish (connectionToExtension, result, error);
if (error[0] != 0) {
String msg = Display.extractFreeGError(error[0]);
System.err.println("SWT WebkitGDBus: there was an error executing something asynchronously with the extension (Java callback).");
System.err.println("SWT WebkitGDBus: the error message provided is " + msg);
}
OS.g_variant_unref(gVariantResult);
return 0;
}
@SuppressWarnings("unused") // callback not directly called by SWT
private static long authenticatePeerCB (long observer, long stream, long credentials, long user_data) {
boolean authorized = false;
if (credentials != 0) {
long error [] = new long [1];
long ownCredentials = OS.g_credentials_new();
authorized = OS.g_credentials_is_same_user(credentials, ownCredentials, error);
if (error[0] != 0) {
String msg = Display.extractFreeGError(error[0]);
System.err.println("SWT WebkitGDBus: error authenticating client connection to server " + msg);
}
OS.g_object_unref(ownCredentials);
}
return authorized ? 1 : 0;
}
@SuppressWarnings("unused") // callback not directly called by SWT
private static long newConnectionCB (long server, long connection, long user_data) {
long gdBusNodeInfo;
long [] error = new long [1];
gdBusNodeInfo = OS.g_dbus_node_info_new_for_xml(WEBKITGDBUS_INTROSPECTION_XML, error);
if (gdBusNodeInfo == 0 || error[0] != 0) {
System.err.println("SWT WebkitGDBus: failed to get introspection data");
}
assert gdBusNodeInfo != 0 : "SWT WebKitGDBus: introspection data should not be 0";
long interface_info = OS.g_dbus_node_info_lookup_interface(gdBusNodeInfo, WEBKITGDBUS_INTERFACE_NAME);
long vtable [] = { handleMethodCB.getAddress(), 0, 0 };
OS.g_dbus_connection_register_object(
connection,
WEBKITGDBUS_OBJECT_PATH,
interface_info,
vtable,
0, // user_data
0, // user_data_free_func
error);
if (error[0] != 0) {
System.err.println("SWT WebKitGDBus: failed to register object: " + WEBKITGDBUS_OBJECT_PATH);
return 0;
}
// Ref the connection and add it to the Display's list of connections
connectionFromExtension = OS.g_object_ref(connection);
if (attachedToDisplay && display != null) {
if (!display.dBusConnections.contains(connection)) display.dBusConnections.add(connectionFromExtension);
}
return 1;
}
@SuppressWarnings("unused") // callback not directly called by SWT
private static long newConnectionToExtensionCB (long sourceObject, long result, long user_data) {
long [] error = new long [1];
connectionToExtension = OS.g_dbus_connection_new_for_address_finish(result, error);
if (error[0] != 0) {
System.err.println("SWT WebKitGDBus: error finishing connection: " + Display.extractFreeGError(error[0]));
return 0;
} else {
connectionToExtensionCreated = true;
}
// Add the connections to the Display's list of connections
if (attachedToDisplay && display != null) {
if (!display.dBusConnections.contains(connectionToExtension)) display.dBusConnections.add(connectionToExtension);
}
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>> map,
long invocation) {
long resultGVariant;
long builder;
long 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 tupleGVariant = convertJavaToGVariant(tupleArray);
if (tupleGVariant != 0) {
OS.g_variant_builder_add_value(builder, tupleGVariant);
} else {
System.err.println("SWT WebKitGDBus: error creating empty BrowserFunction GVariant tuple, skipping.");
}
} else {
for (long id : map.keySet()) {
ArrayList> list = map.get(id);
if (list != null) {
for (ArrayList stringList : list) {
Object [] stringArray = stringList.toArray();
if (stringArray.length > 2) {
System.err.println("SWT WebKitGDBus: String array with BrowserFunction and URL should never have"
+ "more than 2 Strings");
}
tupleArray[0] = id;
System.arraycopy(stringArray, 0, tupleArray, 1, 2);
long tupleGVariant = convertJavaToGVariant(tupleArray);
if (tupleGVariant != 0) {
OS.g_variant_builder_add_value(builder, tupleGVariant);
} else {
System.err.println("SWT WebKitGDBus: 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("SWT WebKitGDBus: an error packaging the GVariant occurred: type mismatch.");
}
long [] variants = {resultGVariant};
long finalGVariant = OS.g_variant_new_tuple(variants, 1);
OS.g_dbus_method_invocation_return_value(invocation, finalGVariant);
OS.g_variant_builder_unref(builder);
OS.g_variant_type_free(type);
return;
}
private static void invokeReturnValue (Object result, long invocation) {
long resultGVariant = 0;
try {
resultGVariant = convertJavaToGVariant(new Object [] {result}); // Result has to be a tuple.
} catch (SWTException e) {
// gdbus should always return to prevent extension from hanging.
String errMsg = (String) WebBrowser.CreateErrorString (e.getLocalizedMessage ());
resultGVariant = convertJavaToGVariant(new Object [] {errMsg});
}
OS.g_dbus_method_invocation_return_value(invocation, resultGVariant);
return; // void return value.
}
/**
* Asynchronously initializes a GDBusConnection to the web extension. Connection process
* will be confirmed when the newConnectionToExtension callback is called.
*/
private static void createConnectionToExtension() {
byte [] address = Converter.javaStringToCString(EXTENSION_DBUS_SERVER_CLIENT_ADDRESS);
long [] error = new long [1];
// Create connection asynchronously to avoid deadlock issues
OS.g_dbus_connection_new_for_address (address, OS.G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
0, 0, newConnectionToExtensionCB.getAddress(), 0);
if (error[0] != 0) {
System.err.println("SWT WebkitGDBus: error creating connection to the extension "
+ Display.extractFreeGError(error[0]));
}
}
/**
* 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 params, String methodName) {
long [] error = new long [1]; // GError **
long gVariant = OS.g_dbus_connection_call_sync(connectionToExtension, EXTENSION_DBUS_NAME, EXTENSION_OBJECT_PATH,
EXTENSION_INTERFACE_NAME, Converter.javaStringToCString(methodName), params,
0, OS.G_DBUS_CALL_FLAGS_NO_AUTO_START, 1000, 0, error);
if (error[0] != 0) {
String msg = Display.extractFreeGError(error[0]);
/*
* 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 WebKitGDBus: there was an error executing something synchronously with the extension.");
System.err.println("SWT WebKitGDBus: the error message is: " + msg);
return (Object) false;
}
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 params, String methodName) {
long [] error = new long [1]; // GError **
OS.g_dbus_connection_call(connectionToExtension, EXTENSION_DBUS_NAME, EXTENSION_OBJECT_PATH,
EXTENSION_INTERFACE_NAME, Converter.javaStringToCString(methodName), params,
0, OS.G_DBUS_CALL_FLAGS_NO_AUTO_START, 1000, 0, callExtensionAsyncCB.getAddress(), 0);
if (error[0] != 0) {
String msg = Display.extractFreeGError(error[0]);
System.err.println("SWT WebKitGDBus: there was an error executing something asynchronously "
+ "with the extension.");
System.err.println("SWT WebKitGDBus: the error message is: " + msg);
return false;
}
return true;
}
/* TYPE NOTES
*
* GDBus doesn't support all the types that we need. I used encoded 'byte' to translate some types.
*
* - 'null' is not supported. I thought to potentially use 'maybe' types, but they imply a possible NULL of a certain type, but not null itself.
* so I use 'byte=48' (meaning '0' in ASCII) to denote null.
*
* - Empty arrays/structs are not supported by gdbus.
* "Container types ... Empty structures are not allowed; there must be at least one type code between the parentheses"
* src: https://dbus.freedesktop.org/doc/dbus-specification.html
* I used byte=101 (meaning 'e' in ASCII) to denote empty array.
*
* In Javascript all Number types seem to be 'double', (int/float/double/short -> Double). So we convert everything into double accordingly.
*
* DBus Type info: https://dbus.freedesktop.org/doc/dbus-specification.html#idm423
* GDBus Type info: https://developer.gnome.org/glib/stable/glib-GVariantType.html
*/
/**
* Converts the given GVariant to a Java object.
* (Only subset of types is currently supported).
*
* We assume that the given gvariant does not contain errors. (checked by webextension first).
*
* @param gVariant a pointer to the native GVariant
*/
static Object convertGVariantToJava(long gVariant){
if (OS.g_variant_is_of_type(gVariant, OS.G_VARIANT_TYPE_BOOLEAN)){
return OS.g_variant_get_boolean(gVariant);
}
// see: WebKitGTK.java 'TYPE NOTES'
if (OS.g_variant_is_of_type(gVariant, OS.G_VARIANT_TYPE_BYTE)) {
byte byteVal = OS.g_variant_get_byte(gVariant);
switch (byteVal) {
case WebkitGDBus.SWT_DBUS_MAGIC_NUMBER_NULL:
return null;
case WebkitGDBus.SWT_DBUS_MAGIC_NUMBER_EMPTY_ARRAY:
return new Object [0];
default:
System.err.println("SWT WebKitGDBus: received an unsupported byte type via GDBus: " + byteVal);
break;
}
}
if (OS.g_variant_is_of_type(gVariant, OS.G_VARIANT_TYPE_DOUBLE)){
return OS.g_variant_get_double(gVariant);
}
if (OS.g_variant_is_of_type(gVariant, OS.G_VARIANT_TYPE_UINT64)){
return 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);
}
if (OS.g_variant_is_of_type(gVariant, OS.G_VARIANT_TYPE_TUPLE)){
int length = (int)OS.g_variant_n_children (gVariant);
Object[] result = new Object[length];
for (int i = 0; i < length; i++) {
result[i] = convertGVariantToJava (OS.g_variant_get_child_value(gVariant, i));
}
return result;
}
String typeString = Converter.cCharPtrToJavaString(OS.g_variant_get_type_string(gVariant), false);
SWT.error (SWT.ERROR_INVALID_ARGUMENT, new Throwable("Unhandled variant type " + typeString ));
return null;
}
/**
* Converts the given Java Object to a GVariant * representation.
* (Only subset of types is currently supported).
*
* We assume that input Object may contain invalid types.
*
* @return pointer GVariant *
*/
static long convertJavaToGVariant(Object javaObject) throws SWTException {
if (javaObject == null) {
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));
}
if (javaObject instanceof Boolean) {
return OS.g_variant_new_boolean((Boolean) javaObject);
}
// We treat Integer, Long, Double, Short as a 'double' because in Javascript these are all 'double'.
// Note, they all extend 'Number' java type, so they are an instance of it.
if (javaObject instanceof Number) { // see: WebKitGTK.java 'TYPE NOTES'
return OS.g_variant_new_double (((Number) javaObject).doubleValue());
}
if (javaObject instanceof Object[]) {
Object[] arrayValue = (Object[]) javaObject;
int length = arrayValue.length;
if (length == 0) {
return OS.g_variant_new_byte(WebkitGDBus.SWT_DBUS_MAGIC_NUMBER_EMPTY_ARRAY); // see: WebKitGTK.java 'TYPE NOTES'
}
long variants[] = new long [length];
for (int i = 0; i < length; i++) {
variants[i] = convertJavaToGVariant(arrayValue[i]);
}
return OS.g_variant_new_tuple(variants, length);
}
System.err.println("SWT WebKitGDBus: invalid object being returned to JavaScript: " + javaObject.toString() + "\n"
+ "Only the following are supported: null, String, Boolean, Number(Long,Integer,Double...), Object[] of basic types");
throw new SWTException(SWT.ERROR_INVALID_ARGUMENT, "Given object is not valid: " + javaObject.toString());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy