[seed] Introduce facilities for client DBus using GDbus: methods generation, signals and properties binding



commit 9f4589a7f8eb24f755fd2931499a1d2a3346911c
Author: Alexandre Mazari <amazari igalia com>
Date:   Tue Aug 30 14:46:21 2011 +0200

    Introduce facilities for client DBus using GDbus: methods generation, signals and properties binding.
    /!\ This is not compatible with the existing native dbus module.
    See documentation.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=657702

 extensions/Gio.js |  181 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 178 insertions(+), 3 deletions(-)
---
diff --git a/extensions/Gio.js b/extensions/Gio.js
index cc3db2a..78e75c1 100644
--- a/extensions/Gio.js
+++ b/extensions/Gio.js
@@ -1,4 +1,6 @@
+GLib = imports.gi.GLib;
 Gio = imports.gi.Gio;
+Lang = imports.lang;
 
 (function()
 {
@@ -8,15 +10,15 @@ Gio = imports.gi.Gio;
     {
 	    var stream = new Gio.DataInputStream.c_new(this);
 	    var line = stream.read_until("", 0);
-	    return line;	
+	return line;
     }
-    
+
     Gio.simple_write = function(file, name)
     {
 	    var file = Gio.file_new_for_path(file);
 	    var fstream = file.replace();
 	    var dstream = new Gio.DataOutputStream.c_new(fstream);
-		    
+
 	    dstream.put_string(name);
 	    fstream.close();
     }
@@ -32,4 +34,177 @@ Gio = imports.gi.Gio;
 	    fstream.close();
 	    return line;
     }
+
+    Gio.DBusProxy.prototype._call = _call;
+    Gio.DBusProxy.prototype._callAsync = _callAsync;
+    Gio.DBusProxy.new = _simple_proxy_factory;
 }).apply();
+
+/* Handler for GDBusProxy::g_properties_change
+ * Invoke the javascript handler, if any, for each changed property
+ * Property change handler should be declared as on($propertyName)Changed
+ * field of the proxy instance.
+ */
+function _dispatchPropertiesChanged (proxy,
+				     changedPropsVariant,
+				     invalidatedProps,
+				     userData)
+{
+    var jsonRes = changedPropsVariant.toJSON();
+    for (var changedProperty in jsonRes)
+    {
+	handlerName = 'on'+changedProperty+'Changed';
+	if (proxy[handlerName])
+	    proxy[handlerName] (jsonRes[changedProperty]);
+    }
+}
+
+/* Handler for GDBusProxy::g_signal
+ * Invoke the javascript handler, if any, registered for the incoming
+ * signal.
+ * Signal handler should be declared as on($signalName) field of the proxy
+ * instance.
+ */
+function _dispatchSignal (proxy, senderName, signalName, parameters)
+{
+    handlerName = 'on'+signalName;
+    if (!this[handlerName])
+	return;
+
+    var jsonRes = parameters.toJSON ();
+    proxy[handlerName] (jsonRes);
+}
+
+/* Synchronous call of a remote DBus method
+ */
+function _call (method, inSignature, outSignature, args)
+{
+    var variantRes =
+	this.call_sync (method,
+			args ? GLib.Variant.new(inSignature, arg) : null,
+			Gio.DBusCallFlags.NONE, -1);
+
+    return  variantRes.toJSON ();
+}
+
+/* Asynchronous call of a remote DBus method
+ * The callback function must take arguments with the same signature
+ * as the return value of the invoked method.
+ */
+function _callAsync (method, inSignature, outSignature, callback, args)
+{
+    var variantRes = this.call (method,
+				args || args != '' ? GLib.Variant.new(inSignature, args) : null,
+				Gio.DBusCallFlags.NONE,
+				-1,
+				null,
+				function (p, res) {
+				    var variantRes = p.call_finish (res);
+				    var jsonRes = variantRes.toJSON ();
+				    if (callback)
+					callback (jsonRes);
+				},
+				"");
+}
+
+/* Create a DBus proxy for the given service
+ * Two Javascript methods are created for each introspected
+ * DBus method name $methodName:
+ * - proxy.$methodName: sync version
+ * - proxy.$methodNameAsync: asyn version
+ */
+function _simple_proxy_factory (bus, name, object, iface) {
+    var res = new Gio.DBusProxy.for_bus_sync (bus,
+					      Gio.DBusProxyFlags.NONE,
+					      null,
+					      name,
+					      object,
+					      iface,
+					      null);
+
+    var introspectionProxy =
+	new Gio.DBusProxy.for_bus_sync (bus,
+					Gio.DBusProxyFlags.NONE,
+					null,
+					name,
+					object,
+					"org.freedesktop.DBus.Introspectable",
+					null);
+
+    var objectDescription = introspectionProxy._call ('Introspect',
+						      null, 's', null);
+    var parser = imports.libxml;
+    var xmlDoc = parser.parseString (objectDescription);
+    var objectDescription = xmlDoc.root.toJSON();
+    var interfacesArray = objectDescription['interface'];
+
+    var interfaces = {};
+    for (var i = 0; i < interfacesArray.length; i++)
+	interfaces[interfacesArray[i].name] = interfacesArray[i];
+
+    var requestedInterface = interfaces[iface];
+
+    for (var i = 0;i < requestedInterface.method.length; i++)
+    {
+	var methodDescription = requestedInterface.method[i];
+	var name = methodDescription.name;
+	var inSignature = _dbusInSignatureFromJSON (methodDescription);
+	var outSignature = _dbusOutSignatureFromJSON (methodDescription);
+
+	// capture name, inSignature, outSignature
+	res[name] = function(name, inSignature, outSignature) {
+	    return function () {
+		var args = Array.prototype.slice.call (arguments, 0);
+		return res._call (name, inSignature, outSignature, args)
+	    }
+	} (name, inSignature, outSignature);
+
+	res[name+'Async'] = function (name, inSignature, outSignature) {
+	    return function () {
+		var callback;
+		var args;
+		if (typeof (arguments[0]) == 'function')
+		{
+		    callback = arguments[0];
+		    args = Array.prototype.slice.call (arguments, 1);
+		}
+		else
+		{
+		    callback = this['on'+name+'Returned'];
+		    args = Array.prototype.slice.call (arguments, 0);
+		}
+
+		res._callAsync(name,
+			       inSignature, outSignature, callback, args);
+	    }
+	} (name, inSignature, outSignature);
+    }
+
+    res.signal.connect ("g_properties_changed",
+			Lang.bind(res, _dispatchPropertiesChanged));
+
+    res.signal.connect ("g_signal",  Lang.bind(res, _dispatchSignal));
+
+    return res;
+}
+
+/// Utils ///
+
+/* Generate the DBus/Variant signature from a json description of the method
+ */
+function _dbusSignatureFromJSON (jsonMethodDescription, dir)
+{
+    if (!jsonMethodDescription.arg)
+	return;
+
+    args = jsonMethodDescription.arg;
+    var res = '';
+    for (var i = 0; i < args.length; i++)
+	if (args[i].direction == dir)
+	    res += args[i].type;
+    return '('+res+')';
+}
+function _dbusOutSignatureFromJSON (json)
+{ return _dbusSignatureFromJSON(json, 'out'); }
+function _dbusInSignatureFromJSON (json)
+{ return _dbusSignatureFromJSON(json, 'in'); }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]