* added better support for passwords
[modest] / src / modest-tny-account-store.c
1 /* modest-tny-account-store.c */
2
3 /* insert (c)/licensing information) */
4
5 #include <string.h>
6
7 #include <tny-account-iface.h>
8 #include <tny-account-store-iface.h>
9 #include <tny-store-account-iface.h>
10 #include <tny-transport-account-iface.h>
11 #include <tny-device-iface.h>
12 #include <tny-device.h>
13 #include <tny-account-store.h>
14
15 #include <tny-store-account.h>
16 #include <tny-transport-account.h>
17
18 #include "modest-account-mgr.h"
19 #include "modest-tny-account-store.h"
20
21 /* 'private'/'protected' functions */
22 static void modest_tny_account_store_class_init   (ModestTnyAccountStoreClass *klass);
23 static void modest_tny_account_store_init         (ModestTnyAccountStore *obj);
24 static void modest_tny_account_store_finalize     (GObject *obj);
25
26 /* implementations for tny-account-store-iface */
27 static void    modest_tny_account_store_iface_init              (gpointer g_iface, gpointer iface_data);
28
29 static void    modest_tny_account_store_add_store_account       (TnyAccountStoreIface *self,
30                                                                TnyStoreAccountIface *account);
31 static void    modest_tny_account_store_add_transport_account   (TnyAccountStoreIface *self,
32                                                                        TnyTransportAccountIface *account);
33 static const GList*  modest_tny_account_store_get_store_accounts      (TnyAccountStoreIface *iface);
34 static const GList*  modest_tny_account_store_get_transport_accounts  (TnyAccountStoreIface *iface);
35
36 /* list my signals */
37 enum {
38         PASSWORD_REQUESTED_SIGNAL,
39         LAST_SIGNAL
40 };
41
42 /* Password Status */
43 enum {
44         PW_NOT_INVALID,
45         PW_INVALID,
46 };
47
48 static const gchar *transport_protocols[] = { "smtp", NULL };
49
50 typedef struct _ModestTnyAccountStorePrivate ModestTnyAccountStorePrivate;
51 struct _ModestTnyAccountStorePrivate {
52
53         GMutex *store_lock;
54         GMutex *transport_lock;
55         GList *store_accounts;
56         GList *transport_accounts;
57         gchar *cache_dir;
58
59         TnySessionCamel *tny_session_camel;
60         TnyDeviceIface  *device;
61
62         ModestAccountMgr *modest_acc_mgr;
63         gint pw_invalid;
64 };
65 #define MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
66                                                       MODEST_TYPE_TNY_ACCOUNT_STORE, \
67                                                       ModestTnyAccountStorePrivate))
68 /* globals */
69 static GObjectClass *parent_class = NULL;
70
71 static guint signals[LAST_SIGNAL] = {0};
72
73 GType
74 modest_tny_account_store_get_type (void)
75 {
76         static GType my_type = 0;
77         if (!my_type) {
78                 static const GTypeInfo my_info = {
79                         sizeof(ModestTnyAccountStoreClass),
80                         NULL,           /* base init */
81                         NULL,           /* base finalize */
82                         (GClassInitFunc) modest_tny_account_store_class_init,
83                         NULL,           /* class finalize */
84                         NULL,           /* class data */
85                         sizeof(ModestTnyAccountStore),
86                         1,              /* n_preallocs */
87                         (GInstanceInitFunc) modest_tny_account_store_init,
88                 };
89
90                 static const GInterfaceInfo iface_info = {
91                         (GInterfaceInitFunc) modest_tny_account_store_iface_init,
92                         NULL,         /* interface_finalize */
93                         NULL          /* interface_data */
94                 };
95                 /* hack hack */
96                 my_type = g_type_register_static (TNY_TYPE_ACCOUNT_STORE,
97                                                   "ModestTnyAccountStore", &my_info, 0);
98
99                 g_type_add_interface_static (my_type, TNY_TYPE_ACCOUNT_STORE_IFACE,
100                                              &iface_info);
101         }
102         return my_type;
103 }
104
105 static void
106 modest_tny_account_store_class_init (ModestTnyAccountStoreClass *klass)
107 {
108         GObjectClass *gobject_class;
109         gobject_class = (GObjectClass*) klass;
110
111         parent_class            = g_type_class_peek_parent (klass);
112         gobject_class->finalize = modest_tny_account_store_finalize;
113
114         g_type_class_add_private (gobject_class,
115                                   sizeof(ModestTnyAccountStorePrivate));
116
117         signals[PASSWORD_REQUESTED_SIGNAL] =
118                 g_signal_new ("password_requested",
119                               G_TYPE_FROM_CLASS (gobject_class),
120                               G_SIGNAL_RUN_FIRST,
121                               G_STRUCT_OFFSET(ModestTnyAccountStoreClass, password_requested),
122                               NULL, NULL,
123                               g_cclosure_marshal_VOID__POINTER,
124                               G_TYPE_NONE, 1, G_TYPE_POINTER);
125 }
126
127 static void
128 modest_tny_account_store_init (ModestTnyAccountStore *obj)
129 {
130         ModestTnyAccountStorePrivate *priv =
131                 MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(obj);
132
133         priv->modest_acc_mgr         = NULL;
134         priv->device                 = NULL;
135
136         priv->store_lock             = NULL;
137         priv->transport_lock         = NULL;
138         priv->store_accounts         = NULL;
139         priv->transport_accounts     = NULL;
140         priv->cache_dir              = NULL;
141
142         priv->tny_session_camel      = NULL;
143         /* Meaning: if not indicated otherwise, we have valid password data */
144         priv->pw_invalid             = PW_NOT_INVALID;
145 }
146
147
148 static void
149 free_gobject (GObject *obj, gpointer user_data)
150 {
151         if (obj)
152                 g_object_unref (obj);
153 }
154
155
156 static GList*
157 free_gobject_list (GList *list)
158 {
159         if (list) {
160                 g_list_foreach (list, (GFunc)free_gobject, NULL);
161                 g_list_free (list);
162         }
163         return NULL;
164 }
165
166 static gchar*
167 get_password (TnyAccountIface *account,
168               const gchar *prompt,
169               gboolean *cancel) {
170
171         const gchar *key;
172         const TnyAccountStoreIface *account_store;
173         ModestTnyAccountStore *self;
174         ModestTnyAccountStorePrivate *priv;
175         gchar *retval;
176
177         g_return_val_if_fail (account, NULL);
178
179         key = tny_account_iface_get_id (account);
180         account_store = tny_account_iface_get_account_store(account);
181
182         self = MODEST_TNY_ACCOUNT_STORE (account_store);
183         priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
184
185         if (priv->pw_invalid==PW_NOT_INVALID) {
186                 retval = modest_account_mgr_get_server_account_string (priv->modest_acc_mgr,
187                                                                        key,
188                                                                        MODEST_ACCOUNT_PASSWORD,
189                                                                        NULL);
190         } else {
191                 g_signal_emit(G_OBJECT(self), signals[PASSWORD_REQUESTED_SIGNAL], 0, key);
192                 priv->pw_invalid=PW_NOT_INVALID;
193                 retval=NULL;
194         }
195         return retval;
196 }
197
198
199 static void
200 forget_password (TnyAccountIface *account) {
201
202         ModestTnyAccountStore *self;
203         ModestTnyAccountStorePrivate *priv;
204         const TnyAccountStoreIface *account_store;
205
206         account_store = tny_account_iface_get_account_store(account);
207         self = MODEST_TNY_ACCOUNT_STORE (account_store);
208         priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
209
210         priv->pw_invalid=PW_INVALID;
211 }
212
213
214 static TnyAccountIface*
215 tny_account_from_key (ModestTnyAccountStore *self, const gchar *key,
216                       gboolean is_store)
217 {
218         TnyAccountIface *tny_account;
219         ModestTnyAccountStorePrivate *priv;
220         gchar *val;
221
222         g_return_val_if_fail (self, NULL);
223         g_return_val_if_fail (key, NULL);
224
225         priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
226
227         /* is it a store or a transport? */
228         if (is_store)
229                 tny_account = TNY_ACCOUNT_IFACE(tny_store_account_new ());
230         else
231                 tny_account = TNY_ACCOUNT_IFACE(tny_transport_account_new ());
232
233         if (!tny_account) {
234                 g_warning ("failed to create new tny %s account",
235                            is_store ? "store" : "transport");
236                 return NULL;
237         }
238
239         tny_account_iface_set_account_store (TNY_ACCOUNT_IFACE(tny_account),
240                                              TNY_ACCOUNT_STORE_IFACE(self));
241         /* id */
242         tny_account_iface_set_id (tny_account, key);
243         tny_account_iface_set_name (tny_account, key);
244
245         /* proto */
246         val = modest_account_mgr_get_server_account_string (priv->modest_acc_mgr, key,
247                                                             MODEST_ACCOUNT_PROTO, NULL);
248         if (val) {
249                 tny_account_iface_set_proto (tny_account, val);
250                 g_free (val);
251         } else {
252                 g_warning ("protocol not defined for %s", key);
253                 g_object_unref (G_OBJECT(tny_account));
254                 return NULL;
255         }
256
257         /* hostname */
258         val = modest_account_mgr_get_server_account_string (priv->modest_acc_mgr, key,
259                                                             MODEST_ACCOUNT_HOSTNAME,
260                                                             NULL);
261         if (val) {
262                 tny_account_iface_set_hostname (tny_account, val);
263                 g_free (val);
264         }
265
266
267         /* username */
268         val = modest_account_mgr_get_server_account_string (priv->modest_acc_mgr, key,
269                                                             MODEST_ACCOUNT_USERNAME,
270                                                             NULL);
271         if (val) {
272                 tny_account_iface_set_user (tny_account, val);
273                 g_free (val);
274         }
275
276         tny_account_iface_set_pass_func (tny_account, get_password);
277         tny_account_iface_set_forget_pass_func (tny_account, forget_password);
278
279         return tny_account;
280 }
281
282
283 static GList*
284 tny_accounts_from_server_accounts (ModestTnyAccountStore *self, GSList *accounts,
285                                    gboolean is_store)
286 {
287         GSList *cursor = accounts;
288         GList *tny_accounts = NULL;
289
290         g_return_val_if_fail (self, NULL);
291
292         while (cursor) {
293                 TnyAccountIface *tny_account;
294                 tny_account = tny_account_from_key (self, (gchar*)cursor->data,
295                                                     is_store);
296                 if (!tny_account) {
297                         g_warning ("could not create tnyaccount for %s",
298                                    (gchar*)cursor->data);
299                 } else {
300                         tny_accounts =
301                                 g_list_append (tny_accounts, tny_account);
302                 }
303                 cursor = cursor->next;
304         }
305
306         return tny_accounts;
307 }
308
309
310 static void
311 manager_new_account (ModestAccountMgr *modest_acc_mgr, gchar *name, gpointer data)
312 {
313         ModestTnyAccountStore *self = data;
314         ModestTnyAccountStorePrivate *priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
315         TnyAccountIface *new_account;
316         gchar *proto;
317         gint i = 0;
318         gboolean is_store = TRUE;
319
320         g_print ("new account signal %s\n", name);
321
322         proto = modest_account_mgr_get_server_account_string (priv->modest_acc_mgr, name,
323                                                             MODEST_ACCOUNT_PROTO, NULL);
324         if (!proto) {
325                 g_printerr ("Cannot add account: unknown type.");
326                 return;
327         }
328
329         while (transport_protocols [i]) {
330                 if (!strcmp (transport_protocols [i], proto)) {
331                         is_store = FALSE;
332                         break;
333                 }
334                 i++;
335         }
336
337         /* fill account lists */
338         if (!priv->store_accounts)
339                 modest_tny_account_store_get_store_accounts (TNY_ACCOUNT_STORE_IFACE(self));
340         if (!priv->transport_accounts)
341                 modest_tny_account_store_get_transport_accounts (TNY_ACCOUNT_STORE_IFACE(self));
342
343
344         if (is_store) {
345                         new_account = tny_account_from_key (self, name, is_store);
346                         g_mutex_lock (priv->store_lock);
347                         priv->store_accounts = g_list_append (priv->store_accounts, new_account);
348                         g_mutex_unlock (priv->store_lock);
349         } else {
350                         new_account = tny_account_from_key (self, name, is_store);
351                         g_mutex_lock (priv->transport_lock);
352                         priv->transport_accounts = g_list_append (priv->transport_accounts, new_account);
353                         g_mutex_unlock (priv->transport_lock);
354         }
355         g_signal_emit (self,
356                 tny_account_store_iface_signals [TNY_ACCOUNT_STORE_IFACE_ACCOUNT_INSERTED], 0, new_account);
357 }
358
359
360 static void
361 manager_remove_account (ModestAccountMgr *modest_acc_mgr, gchar *name, gpointer data)
362 {
363         g_print ("remove account signal %s\n", name);
364 }
365
366
367 static void
368 manager_change_account (ModestAccountMgr *modest_acc_mgr, gchar *accountname,
369         gchar *key, gchar* value, gpointer data)
370 {
371         ModestTnyAccountStore *self = data;
372         ModestTnyAccountStorePrivate *priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
373         GList *iter;
374         TnyAccountIface *account = NULL;
375
376         g_print ("account change signal: account: %s key: %s value: %s\n", accountname, key, value);
377
378         /* fill account lists */
379         if (!priv->store_accounts)
380                 modest_tny_account_store_get_store_accounts (TNY_ACCOUNT_STORE_IFACE(self));
381         if (!priv->transport_accounts)
382                 modest_tny_account_store_get_transport_accounts (TNY_ACCOUNT_STORE_IFACE(self));
383
384         for (iter = priv->store_accounts; iter; iter = iter->next) {
385                 TnyAccountIface *acc = iter->data;
386                 if (!strcmp (tny_account_iface_get_name (acc), accountname)) {
387                         account = acc;
388                         break;
389                 }
390         }
391
392         if (!account)
393                 for (iter = priv->transport_accounts; iter; iter = iter->next) {
394                         TnyAccountIface *acc = iter->data;
395                         if (!strcmp (tny_account_iface_get_name (acc), accountname)) {
396                                 account = acc;
397                                 break;
398                         }
399                 }
400
401         if (!account) {
402                 g_printerr ("Couldn't find account - returning without applying changes.");
403                 return;
404         }
405
406         g_mutex_lock (priv->store_lock);
407         g_mutex_lock (priv->transport_lock);
408
409         if (!strcmp (key, MODEST_ACCOUNT_HOSTNAME))
410                 tny_account_iface_set_hostname (account, value);
411         if (!strcmp (key, MODEST_ACCOUNT_USERNAME))
412                 tny_account_iface_set_user (account, value);
413
414         g_mutex_unlock (priv->transport_lock);
415         g_mutex_unlock (priv->store_lock);
416
417         /* TODO: handle protocol and password changes */
418         g_signal_emit (self,
419                 tny_account_store_iface_signals [TNY_ACCOUNT_STORE_IFACE_ACCOUNTS_RELOADED], 0);
420 }
421
422
423 static void
424 modest_tny_account_store_finalize (GObject *obj)
425 {
426         ModestTnyAccountStore *self = MODEST_TNY_ACCOUNT_STORE(obj);
427         ModestTnyAccountStorePrivate *priv =
428                 MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
429
430         g_signal_handlers_disconnect_by_func (G_OBJECT (priv->modest_acc_mgr),
431                 G_CALLBACK(manager_new_account), NULL);
432         g_signal_handlers_disconnect_by_func (G_OBJECT (priv->modest_acc_mgr),
433                 G_CALLBACK(manager_remove_account), NULL);
434         g_signal_handlers_disconnect_by_func (G_OBJECT (priv->modest_acc_mgr),
435                 G_CALLBACK(manager_change_account), NULL);
436
437         if (priv->modest_acc_mgr) {
438                 g_object_unref (G_OBJECT(priv->modest_acc_mgr));
439                 priv->modest_acc_mgr = NULL;
440         }
441
442         if (priv->tny_session_camel) {
443                 g_object_unref (G_OBJECT(priv->tny_session_camel));
444                 priv->tny_session_camel = NULL;
445         }
446
447         if (priv->device) {
448                 g_object_unref (G_OBJECT(priv->device));
449                 priv->device = NULL;
450         }
451
452         g_mutex_lock (priv->store_lock);
453         priv->store_accounts     = free_gobject_list (priv->store_accounts);
454         g_mutex_unlock (priv->store_lock);
455
456         g_mutex_lock (priv->transport_lock);
457         priv->transport_accounts = free_gobject_list (priv->store_accounts);
458         g_mutex_unlock (priv->transport_lock);
459
460
461         g_mutex_free (priv->store_lock);
462         g_mutex_free (priv->transport_lock);
463
464         g_free (priv->cache_dir);
465         priv->cache_dir = NULL;
466
467 }
468
469
470 GObject*
471 modest_tny_account_store_new (ModestAccountMgr *modest_acc_mgr) {
472
473         GObject *obj;
474         ModestTnyAccountStorePrivate *priv;
475
476         g_return_val_if_fail (modest_acc_mgr, NULL);
477
478         obj  = G_OBJECT(g_object_new(MODEST_TYPE_TNY_ACCOUNT_STORE, NULL));
479
480         priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(obj);
481
482         g_object_ref(G_OBJECT(modest_acc_mgr));
483         priv->modest_acc_mgr = modest_acc_mgr;
484
485         priv->store_lock = g_mutex_new ();
486         priv->transport_lock = g_mutex_new ();
487
488         priv->device = (TnyDeviceIface*)tny_device_new();
489         if (!priv->device) {
490                 g_warning ("Cannot create Device instance");
491                 g_object_unref (obj);
492                 return NULL;
493         }
494         priv->tny_session_camel = tny_session_camel_new
495                 (TNY_ACCOUNT_STORE_IFACE(obj));
496         if (!priv->tny_session_camel) {
497                 g_warning ("Cannot create TnySessionCamel instance");
498                 g_object_unref (obj);
499                 return NULL;
500         }
501
502         g_signal_connect (G_OBJECT (modest_acc_mgr), "account-add",
503                 G_CALLBACK(manager_new_account), obj);
504         g_signal_connect (G_OBJECT (modest_acc_mgr), "account-remove",
505                 G_CALLBACK(manager_remove_account), obj);
506         g_signal_connect (G_OBJECT (modest_acc_mgr), "account-change",
507                 G_CALLBACK(manager_change_account), obj);
508
509         return obj;
510 }
511
512
513 static gboolean
514 add_account  (TnyAccountStoreIface *self, TnyAccountIface *account) {
515
516         TnyAccountIface       *account_iface;
517         ModestTnyAccountStore *account_store;
518         ModestTnyAccountStorePrivate *priv;
519
520         const gchar *account_name;
521         const gchar *hostname, *username, *proto;
522
523         g_return_val_if_fail (self, FALSE);
524         g_return_val_if_fail (account, FALSE);
525
526         account_iface  = TNY_ACCOUNT_IFACE(account);
527         account_store  = MODEST_TNY_ACCOUNT_STORE(self);
528         priv           = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
529
530         account_name   = tny_account_iface_get_id(account_iface);
531         if (!account_name) {
532                 g_warning ("failed to retrieve account name");
533                 return FALSE;
534         }
535
536         hostname =  tny_account_iface_get_hostname(account_iface);
537         username =  tny_account_iface_get_user(account_iface);
538         proto    =  tny_account_iface_get_proto(account_iface);
539
540         return modest_account_mgr_add_server_account (priv->modest_acc_mgr,
541                                                       account_name,
542                                                       hostname, username, NULL,
543                                                       proto);
544 }
545
546
547 static void
548 modest_tny_account_store_add_store_account  (TnyAccountStoreIface *self,
549                                              TnyStoreAccountIface *account)
550 {
551         if (!add_account (self, TNY_ACCOUNT_IFACE(account)))
552                 g_warning ("failed to add store account");
553 }
554
555
556 static void
557 modest_tny_account_store_add_transport_account  (TnyAccountStoreIface *self,
558                                                  TnyTransportAccountIface *account)
559 {
560         if (!add_account (self, TNY_ACCOUNT_IFACE(account)))
561                 g_warning ("failed to add transport account");
562 }
563
564
565 static const GList*
566 modest_tny_account_store_get_store_accounts  (TnyAccountStoreIface *iface)
567 {
568         ModestTnyAccountStore        *self;
569         ModestTnyAccountStorePrivate *priv;
570         GSList                       *accounts;
571
572         g_return_val_if_fail (iface, NULL);
573
574         self = MODEST_TNY_ACCOUNT_STORE(iface);
575         priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
576
577         if (!priv->store_accounts) {
578                 accounts =
579                         modest_account_mgr_server_account_names (priv->modest_acc_mgr,
580                                                                  NULL,
581                                                                  MODEST_PROTO_TYPE_STORE,
582                                                                  NULL, FALSE);
583
584                 g_mutex_lock (priv->store_lock);
585                 priv->store_accounts = tny_accounts_from_server_accounts (self, accounts, TRUE);
586                 g_mutex_unlock (priv->store_lock);
587                 g_slist_free (accounts);
588         }
589
590         return priv->store_accounts;
591 }
592
593
594 static const GList*
595 modest_tny_account_store_get_transport_accounts (TnyAccountStoreIface *iface)
596 {
597         ModestTnyAccountStore        *self;
598         ModestTnyAccountStorePrivate *priv;
599         GSList                       *accounts;
600
601         g_return_val_if_fail (iface, NULL);
602
603         self = MODEST_TNY_ACCOUNT_STORE(iface);
604         priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
605
606
607         if (!priv->transport_accounts) {
608                 accounts =
609                         modest_account_mgr_server_account_names (priv->modest_acc_mgr,
610                                                                  NULL,
611                                                                  MODEST_PROTO_TYPE_TRANSPORT,
612                                                                  NULL, FALSE);
613                 g_mutex_lock (priv->transport_lock);
614                 priv->transport_accounts = tny_accounts_from_server_accounts (self, accounts, FALSE);
615                 g_mutex_unlock (priv->transport_lock);
616                 g_slist_free (accounts);
617         }
618
619
620         return priv->transport_accounts;
621 }
622
623
624 ModestAccountMgr
625 *modest_tny_account_store_get_accout_mgr(ModestTnyAccountStore *self)
626 {
627         ModestTnyAccountStorePrivate *priv;
628         g_return_val_if_fail (self, NULL);
629
630         priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
631
632         return priv->modest_acc_mgr;
633 }
634
635
636 TnySessionCamel*
637 tny_account_store_get_session (TnyAccountStore *self)
638 {
639         ModestTnyAccountStorePrivate *priv;
640         g_return_val_if_fail (self, NULL);
641
642         priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
643
644         return priv->tny_session_camel;
645 }
646
647
648 /**
649  * modest_tny_account_store_get_cache_dir:
650  * @self: self a TnyAccountStoreIface instance
651  *
652  * returns the pathname of the cache directory
653  *
654  * Returns: a string with the value of the pathname
655  * to the cache directory or NULL if the environment variable $HOME is
656  * not set. string should _not_ be freed by caller
657  */
658 static const gchar*
659 modest_tny_account_store_get_cache_dir (TnyAccountStoreIface *self)
660 {
661         ModestTnyAccountStorePrivate *priv;
662         priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
663
664         if (!priv->cache_dir) {
665                 if (g_getenv("HOME") != NULL)
666                         priv->cache_dir = g_strconcat(g_getenv("HOME"),
667                                                       "/.modest/cache/", NULL);
668         }
669         return priv->cache_dir;
670 }
671
672
673 static const TnyDeviceIface*
674 modest_tny_account_store_get_device (TnyAccountStoreIface *self)
675 {
676         ModestTnyAccountStorePrivate *priv;
677
678         priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE (self);
679
680         return priv->device;
681 }
682
683
684 static void
685 modest_tny_account_store_iface_init (gpointer g_iface, gpointer iface_data)
686 {
687         TnyAccountStoreIfaceClass *klass;
688
689         g_return_if_fail (g_iface);
690
691         klass = (TnyAccountStoreIfaceClass *)g_iface;
692
693         klass->add_store_account_func      =
694                 modest_tny_account_store_add_store_account;
695         klass->get_store_accounts_func     =
696                 modest_tny_account_store_get_store_accounts;
697         klass->add_transport_account_func  =
698                 modest_tny_account_store_add_transport_account;
699         klass->get_transport_accounts_func =
700                 modest_tny_account_store_get_transport_accounts;
701         klass->get_cache_dir_func =
702                 modest_tny_account_store_get_cache_dir;
703         klass->get_device_func =
704                 modest_tny_account_store_get_device;
705 }