]> git.0d.be Git - empathy.git/blob - libempathy/empathy-account-manager.c
Make it possible to set element properties from a config file
[empathy.git] / libempathy / empathy-account-manager.c
1 /*
2  * Copyright (C) 2008 Collabora Ltd.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  * Authors: Cosimo Cecchi <cosimo.cecchi@collabora.co.uk>
19  *          Sjoerd Simons <sjoerd.simons@collabora.co.uk>
20  */
21
22 #include "config.h"
23
24 #include <libmissioncontrol/mc-account-monitor.h>
25
26 #include "empathy-account-manager.h"
27 #include "empathy-account-priv.h"
28 #include "empathy-marshal.h"
29 #include "empathy-utils.h"
30
31 #define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT
32 #include <libempathy/empathy-debug.h>
33
34 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountManager)
35
36 typedef struct {
37   McAccountMonitor *monitor;
38   MissionControl   *mc;
39
40   /* (owned) unique name -> (reffed) EmpathyAccount */
41   GHashTable       *accounts;
42   int               connected;
43   int               connecting;
44   gboolean          dispose_run;
45 } EmpathyAccountManagerPriv;
46
47 enum {
48   ACCOUNT_CREATED,
49   ACCOUNT_DELETED,
50   ACCOUNT_ENABLED,
51   ACCOUNT_DISABLED,
52   ACCOUNT_CHANGED,
53   ACCOUNT_CONNECTION_CHANGED,
54   ACCOUNT_PRESENCE_CHANGED,
55   NEW_CONNECTION,
56   LAST_SIGNAL
57 };
58
59 static guint signals[LAST_SIGNAL];
60 static EmpathyAccountManager *manager_singleton = NULL;
61
62 G_DEFINE_TYPE (EmpathyAccountManager, empathy_account_manager, G_TYPE_OBJECT);
63
64 static TpConnectionPresenceType
65 mc_presence_to_tp_presence (McPresence presence)
66 {
67   switch (presence)
68     {
69       case MC_PRESENCE_OFFLINE:
70         return TP_CONNECTION_PRESENCE_TYPE_OFFLINE;
71       case MC_PRESENCE_AVAILABLE:
72         return TP_CONNECTION_PRESENCE_TYPE_AVAILABLE;
73       case MC_PRESENCE_AWAY:
74         return TP_CONNECTION_PRESENCE_TYPE_AWAY;
75       case MC_PRESENCE_EXTENDED_AWAY:
76         return TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY;
77       case MC_PRESENCE_HIDDEN:
78         return TP_CONNECTION_PRESENCE_TYPE_HIDDEN;
79       case MC_PRESENCE_DO_NOT_DISTURB:
80         return TP_CONNECTION_PRESENCE_TYPE_BUSY;
81       default:
82         return TP_CONNECTION_PRESENCE_TYPE_UNSET;
83     }
84 }
85
86 static void
87 emp_account_connection_cb (EmpathyAccount *account,
88   GParamSpec *spec,
89   gpointer manager)
90 {
91   TpConnection *connection = empathy_account_get_connection (account);
92
93   DEBUG ("Signalling connection %p of account %s",
94       connection, empathy_account_get_unique_name (account));
95
96   if (connection != NULL)
97     g_signal_emit (manager, signals[NEW_CONNECTION], 0, connection);
98 }
99
100 static void
101 emp_account_status_changed_cb (EmpathyAccount *account,
102   TpConnectionStatus old,
103   TpConnectionStatus new,
104   TpConnectionStatusReason reason,
105   gpointer user_data)
106 {
107   EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (user_data);
108   EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
109
110   switch (old)
111     {
112       case TP_CONNECTION_STATUS_CONNECTING:
113         priv->connecting--;
114         break;
115       case TP_CONNECTION_STATUS_CONNECTED:
116         priv->connected--;
117         break;
118       default:
119         break;
120     }
121
122   switch (new)
123     {
124       case TP_CONNECTION_STATUS_CONNECTING:
125         priv->connecting++;
126         break;
127       case TP_CONNECTION_STATUS_CONNECTED:
128         priv->connected++;
129         break;
130       default:
131         break;
132     }
133
134   g_signal_emit (manager, signals[ACCOUNT_CONNECTION_CHANGED], 0,
135     account, reason, new, old);
136 }
137
138 static void
139 emp_account_presence_changed_cb (EmpathyAccount *account,
140   TpConnectionPresenceType old,
141   TpConnectionPresenceType new,
142   gpointer user_data)
143 {
144   EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (user_data);
145   g_signal_emit (manager, signals[ACCOUNT_PRESENCE_CHANGED], 0,
146     account, new, old);
147 }
148
149 static EmpathyAccount *
150 create_account (EmpathyAccountManager *manager,
151   const gchar *account_name,
152   McAccount *mc_account)
153 {
154   EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
155   EmpathyAccount *account;
156   TpConnectionStatus status;
157   TpConnectionPresenceType presence;
158   McPresence mc_presence;
159   TpConnection *connection;
160   GError *error = NULL;
161
162   if ((account = g_hash_table_lookup (priv->accounts, account_name)) != NULL)
163     return account;
164
165   account = _empathy_account_new (mc_account);
166   g_hash_table_insert (priv->accounts, g_strdup (account_name),
167     account);
168
169   _empathy_account_set_enabled (account,
170       mc_account_is_enabled (mc_account));
171
172   g_signal_emit (manager, signals[ACCOUNT_CREATED], 0, account);
173
174   g_signal_connect (account, "notify::connection",
175     G_CALLBACK (emp_account_connection_cb), manager);
176
177   connection = mission_control_get_tpconnection (priv->mc,
178     mc_account, NULL);
179   _empathy_account_set_connection (account, connection);
180
181   status = mission_control_get_connection_status (priv->mc,
182      mc_account, &error);
183
184   if (error != NULL)
185     {
186       status = TP_CONNECTION_STATUS_DISCONNECTED;
187       g_clear_error (&error);
188     }
189
190   mc_presence = mission_control_get_presence_actual (priv->mc, &error);
191   if (error != NULL)
192     {
193       presence = TP_CONNECTION_PRESENCE_TYPE_UNSET;
194       g_clear_error (&error);
195     }
196   else
197     {
198       presence = mc_presence_to_tp_presence (mc_presence);
199     }
200
201   g_signal_connect (account, "status-changed",
202     G_CALLBACK (emp_account_status_changed_cb), manager);
203
204   g_signal_connect (account, "presence-changed",
205     G_CALLBACK (emp_account_presence_changed_cb), manager);
206
207   _empathy_account_set_status (account, status,
208     TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED,
209     presence);
210
211   return account;
212 }
213
214 static void
215 account_created_cb (McAccountMonitor *mon,
216                     gchar *account_name,
217                     EmpathyAccountManager *manager)
218 {
219   McAccount *mc_account = mc_account_lookup (account_name);
220
221   if (mc_account != NULL)
222     create_account (manager, account_name, mc_account);
223 }
224
225 static void
226 account_deleted_cb (McAccountMonitor *mon,
227                     gchar *account_name,
228                     EmpathyAccountManager *manager)
229 {
230   EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
231   EmpathyAccount *account;
232
233   account = g_hash_table_lookup (priv->accounts, account_name);
234
235   if (account)
236     {
237       g_signal_emit (manager, signals[ACCOUNT_DELETED], 0, account);
238       g_hash_table_remove (priv->accounts, account_name);
239     }
240 }
241
242 static void
243 account_changed_cb (McAccountMonitor *mon,
244                     gchar *account_name,
245                     EmpathyAccountManager *manager)
246 {
247   EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
248   EmpathyAccount *account;
249
250   account = g_hash_table_lookup (priv->accounts, account_name);
251
252   if (account != NULL)
253     g_signal_emit (manager, signals[ACCOUNT_CHANGED], 0, account);
254 }
255
256 static void
257 account_disabled_cb (McAccountMonitor *mon,
258                      gchar *account_name,
259                      EmpathyAccountManager *manager)
260 {
261   EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
262   EmpathyAccount *account;
263
264   account = g_hash_table_lookup (priv->accounts, account_name);
265
266   if (account)
267     {
268       _empathy_account_set_enabled (account, FALSE);
269       g_signal_emit (manager, signals[ACCOUNT_DISABLED], 0, account);
270     }
271 }
272
273 static void
274 account_enabled_cb (McAccountMonitor *mon,
275                     gchar *account_name,
276                     EmpathyAccountManager *manager)
277 {
278   EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
279   EmpathyAccount *account;
280
281   account = g_hash_table_lookup (priv->accounts, account_name);
282
283   if (account)
284     {
285       _empathy_account_set_enabled (account, TRUE);
286       g_signal_emit (manager, signals[ACCOUNT_ENABLED], 0, account);
287     }
288 }
289
290 typedef struct {
291   TpConnectionStatus status;
292   TpConnectionPresenceType presence;
293   TpConnectionStatusReason reason;
294   gchar *unique_name;
295   EmpathyAccountManager *manager;
296   McAccount *mc_account;
297 } ChangedSignalData;
298
299 static gboolean
300 account_status_changed_idle_cb (ChangedSignalData *signal_data)
301 {
302   EmpathyAccount *account;
303   EmpathyAccountManager *manager = signal_data->manager;
304   EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
305
306   account = g_hash_table_lookup (priv->accounts,
307     signal_data->unique_name);
308
309   if (account)
310     {
311       if (empathy_account_get_connection (account) == NULL)
312         {
313           TpConnection *connection;
314
315           connection = mission_control_get_tpconnection (priv->mc,
316              signal_data->mc_account, NULL);
317
318           if (connection != NULL)
319             {
320               _empathy_account_set_connection (account, connection);
321               g_object_unref (connection);
322             }
323         }
324
325       _empathy_account_set_status (account, signal_data->status,
326         signal_data->reason,
327         signal_data->presence);
328     }
329
330   g_object_unref (signal_data->manager);
331   g_object_unref (signal_data->mc_account);
332   g_free (signal_data->unique_name);
333   g_slice_free (ChangedSignalData, signal_data);
334
335   return FALSE;
336 }
337
338 static void
339 account_status_changed_cb (MissionControl *mc,
340                            TpConnectionStatus status,
341                            McPresence presence,
342                            TpConnectionStatusReason reason,
343                            const gchar *unique_name,
344                            EmpathyAccountManager *manager)
345 {
346   ChangedSignalData *data;
347
348   DEBUG ("Status of account %s became "
349     "status: %d presence: %d reason: %d", unique_name, status,
350     presence, reason);
351
352   data = g_slice_new0 (ChangedSignalData);
353   data->status = status;
354   data->presence = mc_presence_to_tp_presence (presence);
355   data->reason = reason;
356   data->unique_name = g_strdup (unique_name);
357   data->manager = g_object_ref (manager);
358   data->mc_account = mc_account_lookup (unique_name);
359
360   g_idle_add ((GSourceFunc) account_status_changed_idle_cb, data);
361 }
362
363 static void
364 empathy_account_manager_init (EmpathyAccountManager *manager)
365 {
366   EmpathyAccountManagerPriv *priv;
367   GList *mc_accounts, *l;
368
369   priv = G_TYPE_INSTANCE_GET_PRIVATE (manager,
370       EMPATHY_TYPE_ACCOUNT_MANAGER, EmpathyAccountManagerPriv);
371
372   manager->priv = priv;
373   priv->monitor = mc_account_monitor_new ();
374   priv->mc = empathy_mission_control_dup_singleton ();
375   priv->connected = priv->connecting = 0;
376   priv->dispose_run = FALSE;
377
378   priv->accounts = g_hash_table_new_full (g_str_hash, g_str_equal,
379       g_free, (GDestroyNotify) g_object_unref);
380
381   mc_accounts = mc_accounts_list ();
382
383   for (l = mc_accounts; l; l = l->next)
384     account_created_cb (priv->monitor,
385       (char *) mc_account_get_unique_name (l->data), manager);
386
387   g_signal_connect (priv->monitor, "account-created",
388       G_CALLBACK (account_created_cb), manager);
389   g_signal_connect (priv->monitor, "account-deleted",
390       G_CALLBACK (account_deleted_cb), manager);
391   g_signal_connect (priv->monitor, "account-disabled",
392       G_CALLBACK (account_disabled_cb), manager);
393   g_signal_connect (priv->monitor, "account-enabled",
394       G_CALLBACK (account_enabled_cb), manager);
395   g_signal_connect (priv->monitor, "account-changed",
396       G_CALLBACK (account_changed_cb), manager);
397
398   dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc), "AccountStatusChanged",
399                                G_CALLBACK (account_status_changed_cb),
400                                manager, NULL);
401
402   mc_accounts_list_free (mc_accounts);
403 }
404
405 static void
406 do_finalize (GObject *obj)
407 {
408   EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (obj);
409   EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
410
411   g_hash_table_destroy (priv->accounts);
412
413   G_OBJECT_CLASS (empathy_account_manager_parent_class)->finalize (obj);
414 }
415
416 static void
417 do_dispose (GObject *obj)
418 {
419   EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (obj);
420   EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
421
422   if (priv->dispose_run)
423     return;
424
425   priv->dispose_run = TRUE;
426
427   dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->mc),
428                                   "AccountStatusChanged",
429                                   G_CALLBACK (account_status_changed_cb),
430                                   obj);
431
432   if (priv->monitor)
433     {
434       g_signal_handlers_disconnect_by_func (priv->monitor,
435                                             account_created_cb, obj);
436       g_signal_handlers_disconnect_by_func (priv->monitor,
437                                             account_deleted_cb, obj);
438       g_signal_handlers_disconnect_by_func (priv->monitor,
439                                             account_disabled_cb, obj);
440       g_signal_handlers_disconnect_by_func (priv->monitor,
441                                             account_enabled_cb, obj);
442       g_signal_handlers_disconnect_by_func (priv->monitor,
443                                             account_changed_cb, obj);
444       g_object_unref (priv->monitor);
445       priv->monitor = NULL;
446     }
447
448   if (priv->mc)
449     g_object_unref (priv->mc);
450
451   g_hash_table_remove_all (priv->accounts);
452
453   G_OBJECT_CLASS (empathy_account_manager_parent_class)->dispose (obj);
454 }
455
456 static GObject *
457 do_constructor (GType type,
458                 guint n_construct_params,
459                 GObjectConstructParam *construct_params)
460 {
461   GObject *retval;
462
463   if (!manager_singleton)
464     {
465       retval = G_OBJECT_CLASS (empathy_account_manager_parent_class)->constructor (type,
466                                                                                    n_construct_params,
467                                                                                    construct_params);
468       manager_singleton = EMPATHY_ACCOUNT_MANAGER (retval);
469       g_object_add_weak_pointer (retval, (gpointer) &manager_singleton);
470     }
471   else
472     {
473       retval = g_object_ref (manager_singleton);
474     }
475
476   return retval;
477 }
478
479 static void
480 empathy_account_manager_class_init (EmpathyAccountManagerClass *klass)
481 {
482   GObjectClass *oclass = G_OBJECT_CLASS (klass);
483
484   oclass->finalize = do_finalize;
485   oclass->dispose = do_dispose;
486   oclass->constructor = do_constructor;
487
488   signals[ACCOUNT_CREATED] =
489     g_signal_new ("account-created",
490                   G_TYPE_FROM_CLASS (klass),
491                   G_SIGNAL_RUN_LAST,
492                   0,
493                   NULL, NULL,
494                   g_cclosure_marshal_VOID__OBJECT,
495                   G_TYPE_NONE,
496                   1, EMPATHY_TYPE_ACCOUNT);
497
498   signals[ACCOUNT_DELETED] =
499     g_signal_new ("account-deleted",
500                   G_TYPE_FROM_CLASS (klass),
501                   G_SIGNAL_RUN_LAST,
502                   0,
503                   NULL, NULL,
504                   g_cclosure_marshal_VOID__OBJECT,
505                   G_TYPE_NONE,
506                   1, EMPATHY_TYPE_ACCOUNT);
507
508   signals[ACCOUNT_ENABLED] =
509     g_signal_new ("account-enabled",
510                   G_TYPE_FROM_CLASS (klass),
511                   G_SIGNAL_RUN_LAST,
512                   0,
513                   NULL, NULL,
514                   g_cclosure_marshal_VOID__OBJECT,
515                   G_TYPE_NONE,
516                   1, EMPATHY_TYPE_ACCOUNT);
517
518   signals[ACCOUNT_DISABLED] =
519     g_signal_new ("account-disabled",
520                   G_TYPE_FROM_CLASS (klass),
521                   G_SIGNAL_RUN_LAST,
522                   0,
523                   NULL, NULL,
524                   g_cclosure_marshal_VOID__OBJECT,
525                   G_TYPE_NONE,
526                   1, EMPATHY_TYPE_ACCOUNT);
527
528   signals[ACCOUNT_CHANGED] =
529     g_signal_new ("account-changed",
530                   G_TYPE_FROM_CLASS (klass),
531                   G_SIGNAL_RUN_LAST,
532                   0,
533                   NULL, NULL,
534                   g_cclosure_marshal_VOID__OBJECT,
535                   G_TYPE_NONE,
536                   1, EMPATHY_TYPE_ACCOUNT);
537
538   signals[ACCOUNT_CONNECTION_CHANGED] =
539     g_signal_new ("account-connection-changed",
540                   G_TYPE_FROM_CLASS (klass),
541                   G_SIGNAL_RUN_LAST,
542                   0,
543                   NULL, NULL,
544                   _empathy_marshal_VOID__OBJECT_INT_UINT_UINT,
545                   G_TYPE_NONE,
546                   4, EMPATHY_TYPE_ACCOUNT,
547                   G_TYPE_INT,   /* reason */
548                   G_TYPE_UINT,  /* actual connection */
549                   G_TYPE_UINT); /* previous connection */
550
551   signals[ACCOUNT_PRESENCE_CHANGED] =
552     g_signal_new ("account-presence-changed",
553                   G_TYPE_FROM_CLASS (klass),
554                   G_SIGNAL_RUN_LAST,
555                   0,
556                   NULL, NULL,
557                   _empathy_marshal_VOID__OBJECT_INT_INT,
558                   G_TYPE_NONE,
559                   3, EMPATHY_TYPE_ACCOUNT,
560                   G_TYPE_INT,  /* actual presence */
561                   G_TYPE_INT); /* previous presence */
562
563   signals[NEW_CONNECTION] =
564     g_signal_new ("new-connection",
565                   G_TYPE_FROM_CLASS (klass),
566                   G_SIGNAL_RUN_LAST,
567                   0,
568                   NULL, NULL,
569                   g_cclosure_marshal_VOID__OBJECT,
570                   G_TYPE_NONE,
571                   1, TP_TYPE_CONNECTION);
572
573   g_type_class_add_private (oclass, sizeof (EmpathyAccountManagerPriv));
574 }
575
576 /* public methods */
577
578 EmpathyAccountManager *
579 empathy_account_manager_dup_singleton (void)
580 {
581   return g_object_new (EMPATHY_TYPE_ACCOUNT_MANAGER, NULL);
582 }
583
584 EmpathyAccount *
585 empathy_account_manager_create (EmpathyAccountManager *manager,
586   McProfile *profile)
587 {
588   McAccount *mc_account = mc_account_create (profile);
589   return g_object_ref (create_account (manager,
590       mc_account_get_unique_name (mc_account),
591       mc_account));
592 }
593
594 int
595 empathy_account_manager_get_connected_accounts (EmpathyAccountManager *manager)
596 {
597   EmpathyAccountManagerPriv *priv;
598
599   g_return_val_if_fail (EMPATHY_IS_ACCOUNT_MANAGER (manager), 0);
600
601   priv = GET_PRIV (manager);
602
603   return priv->connected;
604 }
605
606 int
607 empathy_account_manager_get_connecting_accounts (EmpathyAccountManager *manager)
608 {
609   EmpathyAccountManagerPriv *priv;
610
611   g_return_val_if_fail (EMPATHY_IS_ACCOUNT_MANAGER (manager), 0);
612
613   priv = GET_PRIV (manager);
614
615   return priv->connecting;
616 }
617
618 /**
619  * empathy_account_manager_get_count:
620  * @manager: a #EmpathyAccountManager
621  *
622  * Get the number of accounts.
623  *
624  * Returns: the number of accounts.
625  **/
626 int
627 empathy_account_manager_get_count (EmpathyAccountManager *manager)
628 {
629   EmpathyAccountManagerPriv *priv;
630
631   g_return_val_if_fail (EMPATHY_IS_ACCOUNT_MANAGER (manager), 0);
632
633   priv = GET_PRIV (manager);
634
635   return g_hash_table_size (priv->accounts);
636 }
637
638 EmpathyAccount *
639 empathy_account_manager_get_account (EmpathyAccountManager *manager,
640                                      TpConnection          *connection)
641 {
642   EmpathyAccountManagerPriv *priv;
643   GHashTableIter iter;
644   gpointer value;
645
646   g_return_val_if_fail (EMPATHY_IS_ACCOUNT_MANAGER (manager), 0);
647
648   priv = GET_PRIV (manager);
649
650   g_hash_table_iter_init (&iter, priv->accounts);
651   while (g_hash_table_iter_next (&iter, NULL, &value))
652     {
653       EmpathyAccount *account = EMPATHY_ACCOUNT (value);
654
655       if (connection == empathy_account_get_connection (account))
656           return account;
657     }
658
659   return NULL;
660 }
661
662 EmpathyAccount *
663 empathy_account_manager_lookup (EmpathyAccountManager *manager,
664     const gchar *unique_name)
665 {
666   EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
667   EmpathyAccount *account;
668
669   account = g_hash_table_lookup (priv->accounts, unique_name);
670
671   if (account != NULL)
672     g_object_ref (account);
673
674   return account;
675 }
676
677 GList *
678 empathy_account_manager_dup_accounts (EmpathyAccountManager *manager)
679 {
680   EmpathyAccountManagerPriv *priv;
681   GList *ret;
682
683   g_return_val_if_fail (EMPATHY_IS_ACCOUNT_MANAGER (manager), NULL);
684
685   priv = GET_PRIV (manager);
686
687   ret = g_hash_table_get_values (priv->accounts);
688   g_list_foreach (ret, (GFunc) g_object_ref, NULL);
689
690   return ret;
691 }
692
693 /**
694  * empathy_account_manager_dup_connections:
695  * @manager: a #EmpathyAccountManager
696  *
697  * Get a #GList of all ready #TpConnection. The list must be freed with
698  * g_list_free, and its elements must be unreffed.
699  *
700  * Returns: the list of connections
701  **/
702 GList *
703 empathy_account_manager_dup_connections (EmpathyAccountManager *manager)
704 {
705   EmpathyAccountManagerPriv *priv;
706   GHashTableIter iter;
707   gpointer value;
708   GList *ret = NULL;
709
710   g_return_val_if_fail (EMPATHY_IS_ACCOUNT_MANAGER (manager), NULL);
711
712   priv = GET_PRIV (manager);
713
714   g_hash_table_iter_init (&iter, priv->accounts);
715   while (g_hash_table_iter_next (&iter, NULL, &value))
716     {
717       EmpathyAccount *account = EMPATHY_ACCOUNT (value);
718       TpConnection *connection;
719
720       connection = empathy_account_get_connection (account);
721       if (connection != NULL)
722         ret = g_list_prepend (ret, g_object_ref (connection));
723     }
724
725   return ret;
726 }
727
728 void
729 empathy_account_manager_remove (EmpathyAccountManager *manager,
730     EmpathyAccount *account)
731 {
732   mc_account_delete (_empathy_account_get_mc_account (account));
733 }