soc.2010.detachablepurple: 9ebfa0ef: Added the client part of the GetAllAccou...

gillux at soc.pidgin.im gillux at soc.pidgin.im
Thu Jul 15 17:35:50 EDT 2010


----------------------------------------------------------------------
Revision: 9ebfa0ef511ed05726607a126e0356e73b885c0e
Parent:   729a8d40bc3b49c16ae374cb02294364e7b71aa4
Author:   gillux at soc.pidgin.im
Date:     07/15/10 15:42:25
Branch:   im.pidgin.soc.2010.detachablepurple
URL: http://d.pidgin.im/viewmtn/revision/info/9ebfa0ef511ed05726607a126e0356e73b885c0e

Changelog: 

Added the client part of the GetAllAccounts method, with a little helper
that calls it and locally recreate the identical accounts (kinda
"remote loading" of the accounts).
And updated the account loader to do so!

Changes against parent 729a8d40bc3b49c16ae374cb02294364e7b71aa4

  patched  libpurple/accountlist.c
  patched  libpurple/dbus-constructor.c
  patched  libpurple/dbus-constructor.h

-------------- next part --------------
============================================================
--- libpurple/accountlist.c	14ee885a53cce0d7d9bff7c97091565f4f2d9379
+++ libpurple/accountlist.c	fd799035a5329260f5d02439505f49c5e4cf221f
@@ -24,6 +24,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
 #include "internal.h"
+#include "dbus-constructor.h"
 #include "purple.h"
 #include "gsignal.h"
 #include "marshallers.h"
@@ -560,6 +561,12 @@ purple_accounts_load()
 
 	global.accounts_loaded = TRUE;
 
+	/* In remote mode, don't read the accounts locally,
+	 * load them from the daemon instead.
+	 */
+	if (purple_core_get_remote_mode())
+		return purple_accounts_get_all_RPC();
+
 	node = purple_util_read_xml_from_file("accounts.xml", _("accounts"));
 
 	if (node == NULL)
============================================================
--- libpurple/dbus-constructor.c	cb39a2c74a5c78982ef679844a67a1bc0a66e35e
+++ libpurple/dbus-constructor.c	b6713abc76a55400584075313dce2cf521e8ced4
@@ -25,10 +25,11 @@
 #include "account.h"
 #include "accountlist.h"
 #include "dbus-constructor.h"
+#include "dbus-constructor-client.h"
 #include "dbus-constructor-server.h"
 #include "dbus-maybe.h"
+#include "debug.h"
 
-
 /**
  * PurpleConstructor, a dummy class to remotely create and load gobjects over DBus.
  *
@@ -70,10 +71,17 @@ PurpleConstructor* purple_constructor_ge
 }
 
 PurpleConstructor* purple_constructor_get_instance(void) {
+	DBusGProxy* proxy;
 	static PurpleConstructor* self = NULL;
 
 	if (self == NULL) {
 		self = g_object_new(PURPLE_TYPE_CONSTRUCTOR, NULL);
+		proxy = dbus_g_proxy_new_for_name(purple_dbus_get_g_connection(),
+						DBUS_PURPLE_SERVICE,
+						DBUS_CONSTRUCTOR_PATH,
+						DBUS_CONSTRUCTOR_INTERFACE);
+		purple_object_set_dbus_obj_proxy(PURPLE_OBJECT(self), proxy);
+		PURPLE_DBUS_REGISTER_OBJECT(DBUS_CONSTRUCTOR_PATH, self);
 	}
 	return self;
 }
@@ -223,3 +231,125 @@ DBUS_purple_constructor_get_all_accounts
 	return TRUE;
 }
 
+/**
+ * A callback used in load_accounts_cb().
+ * Unpacks the { prop_name, prop_gvalue } dbus structure and set
+ * the prop_name property in the given account.
+ */
+static void
+load_account_prop_cb(GValueArray* box, PurpleAccount* account)
+{
+	GParamSpec *prop_spec;
+	char* prop_name;
+	GValue value_box = {0, };
+	GValue *prop_val;
+
+	/* Each property consists of a DBUS_STRUCT_PROPERTY */
+	g_value_init(&value_box, DBUS_STRUCT_PROPERTY);
+	g_value_set_boxed(&value_box, box);
+
+	dbus_g_type_struct_get(&value_box, 0, &prop_name, 1, &prop_val,
+			G_MAXUINT);
+
+	g_object_set_property(G_OBJECT(account), prop_name, prop_val);
+
+	g_free(prop_name);
+	g_value_unset(&value_box);
+	g_value_unset(prop_val);
+}
+
+/**
+ * A helper function used in DBUS_purple_constructor_get_all_accounts().
+ * Finds a property named prop_name in prop_array array of structs.
+ */
+static GValue*
+get_prop_by_name(GPtrArray *prop_array, char *prop_name)
+{
+	int i;
+	GValue val = {0, };
+	GValue value_box = {0, };
+
+	g_value_init(&value_box, DBUS_STRUCT_PROPERTY);
+	g_value_init(&val, G_TYPE_STRING);
+
+	for (i = 0; i < prop_array->len; i++) {
+		g_value_set_boxed(&value_box, prop_array->pdata[i]);
+		dbus_g_type_struct_get_member(&value_box, 0, &val);
+		if (purple_strequal(g_value_get_string(&val), prop_name)) {
+			g_value_unset(&val);
+			g_value_init(&val, G_TYPE_VALUE);
+			dbus_g_type_struct_get_member(&value_box, 1, &val);
+			g_value_unset(&value_box);
+			return g_value_get_boxed(&val);
+		}
+	}
+	g_value_unset(&value_box);
+	return NULL;
+}
+
+/**
+ * A callback used in purple_accounts_get_all_RPC().
+ * Unpacks the { protocol_id, account_struct } dbus structure and construct
+ * a new account based on these informations.
+ */
+static void
+load_accounts_cb(GValueArray* box)
+{
+	GValue val = {0, };
+	PurpleAccount *acc;
+	char *protocol_id;
+	GPtrArray *prop_array;
+	GValue *username;
+
+	/* Each account consists of a DBUS_STRUCT_ACCOUNT */
+	g_value_init(&val, DBUS_STRUCT_ACCOUNT);
+	g_value_set_boxed(&val, box);
+	dbus_g_type_struct_get(&val,
+		0, &protocol_id, 1, &prop_array, G_MAXUINT);
+
+	/* First get the username, it is needed to construct the account */
+	username = get_prop_by_name(prop_array, "username");
+	if (!username) {
+		purple_debug_warning("dbus",
+			"Couldn't load the account: username not found\n");
+		return;
+	}
+	/* Temporarly go in normal mode, and it will create a local account */
+	purple_core_set_remote_mode(FALSE);
+	acc = purple_account_new(g_value_get_string(username), protocol_id);
+
+	/* Then load the others properties. Keep the normal mode here,
+	 * otherwise it will try to remotely set the properties.
+	 */
+	g_ptr_array_foreach(prop_array, (GFunc)load_account_prop_cb, acc);
+	purple_core_set_remote_mode(TRUE);
+
+	g_free(protocol_id);
+	g_value_unset(username);
+	g_ptr_array_free(prop_array, TRUE);
+	g_value_unset(&val);
+	g_value_array_free(box);
+}
+
+void
+purple_accounts_get_all_RPC(void)
+{
+	PurpleConstructor* con = purple_constructor_get_instance();
+	DBusGProxy *proxy = purple_object_get_dbus_obj_proxy(PURPLE_OBJECT(con));
+	GError *error = NULL;
+	GPtrArray* accounts;
+
+	/* In remote mode accounts are already loaded by the daemon.
+	 * We need to get those here.
+	 */
+	if(!im_pidgin_purple_constructor_get_all_accounts(proxy, &accounts, &error)) {
+		PURPLE_RPC_FAILED(purple_constructor_get_all_accounts, error);
+		return;
+	}
+
+	g_ptr_array_foreach(accounts, (GFunc)load_accounts_cb, NULL);
+	purple_debug_info("dbus",
+			"Loaded %i remote account(s).\n", accounts->len);
+
+	g_ptr_array_free(accounts, TRUE);
+}
============================================================
--- libpurple/dbus-constructor.h	bd334697ba1cec9544763dc50d06b422d203a47a
+++ libpurple/dbus-constructor.h	d4131551274011a835d8e9f7281bd13531d3e97b
@@ -72,8 +72,17 @@ gboolean DBUS_purple_constructor_get_all
  */
 gboolean DBUS_purple_constructor_get_all_accounts(PurpleConstructor* con, GPtrArray** accounts, GError** error);
 
+/**
+ * A helper function to remotely call purple_accounts_get_all()
+ */
+void purple_accounts_get_all_RPC(void);
+
 G_END_DECLS
 
+#else /* !HAVE_DBUS */
+
+#define purple_accounts_get_all_RPC() ((void)0)
+
 #endif /* HAVE_DBUS */
 
 #endif /* _DBUS_CONSTRUCTOR_H_ */


More information about the Commits mailing list