source_registry_ref_any_mail_identity(): Fix a typo.
[platform/upstream/evolution-data-server.git] / libedataserver / e-source-registry.c
1 /*
2  * e-source-registry.c
3  *
4  * This program 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 of the License, or (at your option) version 3.
8  *
9  * This program 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 the program; if not, see <http://www.gnu.org/licenses/>
16  *
17  */
18
19 /**
20  * SECTION: e-source-registry
21  * @include: libedataserver/libedataserver.h
22  * @short_description: A central repository for data sources
23  *
24  * The #ESourceRegistry is a global singleton store for all #ESource
25  * instances.  It uses file monitors to react to key file creation and
26  * deletion events, either constructing an #ESource instance from the
27  * newly created key file, or removing from the logical #ESource
28  * hierarchy the instance corresponding to the deleted key file.
29  *
30  * The #ESourceRegistry can be queried for individual #ESource instances
31  * by their unique identifier string or key file path, for collections of
32  * #ESource instances having a particular extension, or for all available
33  * #ESource instances.
34  *
35  * The #ESourceRegistry API also provides a front-end for the
36  * "org.gnome.Evolution.DefaultSources" #GSettings schema which tracks
37  * which #ESource instances are designated to be the user's default address
38  * book, calendar, memo list and task list for desktop integration.
39  **/
40
41 #include "e-source-registry.h"
42
43 #include <config.h>
44 #include <glib/gstdio.h>
45 #include <glib/gi18n-lib.h>
46
47 /* XXX Yeah, yeah... */
48 #define GCR_API_SUBJECT_TO_CHANGE
49
50 #include <gcr/gcr-base.h>
51
52 /* Private D-Bus classes. */
53 #include <e-dbus-source.h>
54 #include <e-dbus-source-manager.h>
55
56 #include <libedataserver/e-marshal.h>
57 #include <libedataserver/e-data-server-util.h>
58 #include <libedataserver/e-source-collection.h>
59
60 /* Needed for the defaults API. */
61 #include <libedataserver/e-source-address-book.h>
62 #include <libedataserver/e-source-calendar.h>
63 #include <libedataserver/e-source-mail-account.h>
64 #include <libedataserver/e-source-mail-identity.h>
65
66 #include "e-dbus-authenticator.h"
67
68 #define E_SOURCE_REGISTRY_GET_PRIVATE(obj) \
69         (G_TYPE_INSTANCE_GET_PRIVATE \
70         ((obj), E_TYPE_SOURCE_REGISTRY, ESourceRegistryPrivate))
71
72 #define DBUS_OBJECT_PATH "/org/gnome/evolution/dataserver/SourceManager"
73 #define GSETTINGS_SCHEMA "org.gnome.Evolution.DefaultSources"
74
75 /* Built-in data source UIDs. */
76 #define E_SOURCE_BUILTIN_ADDRESS_BOOK_UID       "system-address-book"
77 #define E_SOURCE_BUILTIN_CALENDAR_UID           "system-calendar"
78 #define E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID       "local"
79 #define E_SOURCE_BUILTIN_MEMO_LIST_UID          "system-memo-list"
80 #define E_SOURCE_BUILTIN_TASK_LIST_UID          "system-task-list"
81
82 /* GSettings keys for default data sources. */
83 #define E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY     "default-address-book"
84 #define E_SETTINGS_DEFAULT_CALENDAR_KEY         "default-calendar"
85 #define E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY     "default-mail-account"
86 #define E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY    "default-mail-identity"
87 #define E_SETTINGS_DEFAULT_MEMO_LIST_KEY        "default-memo-list"
88 #define E_SETTINGS_DEFAULT_TASK_LIST_KEY        "default-task-list"
89
90 typedef struct _AsyncContext AsyncContext;
91 typedef struct _AuthContext AuthContext;
92 typedef struct _SourceClosure SourceClosure;
93 typedef struct _ThreadClosure ThreadClosure;
94
95 struct _ESourceRegistryPrivate {
96         GMainContext *main_context;
97
98         GThread *manager_thread;
99         ThreadClosure *thread_closure;
100
101         GDBusObjectManager *dbus_object_manager;
102         EDBusSourceManager *dbus_source_manager;
103
104         GHashTable *object_path_table;
105         GMutex *object_path_table_lock;
106
107         GHashTable *sources;
108         GMutex *sources_lock;
109
110         GSettings *settings;
111 };
112
113 struct _AsyncContext {
114         ESource *source;
115         GList *list_of_sources;
116         ESourceAuthenticator *auth;
117 };
118
119 /* Used in e_source_registry_authenticate_sync() */
120 struct _AuthContext {
121         ESourceAuthenticator *auth;
122         EDBusAuthenticator *dbus_auth;
123         GCancellable *cancellable;
124         GMainLoop *main_loop;
125         ESourceAuthenticationResult auth_result;
126         GcrSecretExchange *secret_exchange;
127         gboolean authenticating;
128         gboolean success;
129         GError **error;
130 };
131
132 struct _SourceClosure {
133         ESourceRegistry *registry;
134         ESource *source;
135 };
136
137 struct _ThreadClosure {
138         ESourceRegistry *registry;
139         GMainContext *main_context;
140         GMainLoop *main_loop;
141         GCond *main_loop_cond;
142         GMutex *main_loop_mutex;
143 };
144
145 enum {
146         PROP_0,
147         PROP_DEFAULT_ADDRESS_BOOK,
148         PROP_DEFAULT_CALENDAR,
149         PROP_DEFAULT_MAIL_ACCOUNT,
150         PROP_DEFAULT_MAIL_IDENTITY,
151         PROP_DEFAULT_MEMO_LIST,
152         PROP_DEFAULT_TASK_LIST
153 };
154
155 enum {
156         SOURCE_ADDED,
157         SOURCE_CHANGED,
158         SOURCE_REMOVED,
159         SOURCE_ENABLED,
160         SOURCE_DISABLED,
161         LAST_SIGNAL
162 };
163
164 /* Forward Declarations */
165 static void     source_registry_add_source      (ESourceRegistry *registry,
166                                                  ESource *source);
167 static void     e_source_registry_initable_init (GInitableIface *interface);
168
169 static guint signals[LAST_SIGNAL];
170
171 /* By default, the GAsyncInitable interface calls GInitable.init()
172  * from a separate thread, so we only have to override GInitable. */
173 G_DEFINE_TYPE_WITH_CODE (
174         ESourceRegistry,
175         e_source_registry,
176         G_TYPE_OBJECT,
177         G_IMPLEMENT_INTERFACE (
178                 G_TYPE_INITABLE, e_source_registry_initable_init)
179         G_IMPLEMENT_INTERFACE (
180                 G_TYPE_ASYNC_INITABLE, NULL))
181
182 static void
183 async_context_free (AsyncContext *async_context)
184 {
185         if (async_context->source != NULL)
186                 g_object_unref (async_context->source);
187
188         g_list_free_full (
189                 async_context->list_of_sources,
190                 (GDestroyNotify) g_object_unref);
191
192         if (async_context->auth != NULL)
193                 g_object_unref (async_context->auth);
194
195         g_slice_free (AsyncContext, async_context);
196 }
197
198 static void
199 auth_context_free (AuthContext *auth_context)
200 {
201         if (auth_context->auth != NULL)
202                 g_object_unref (auth_context->auth);
203
204         if (auth_context->dbus_auth != NULL)
205                 g_object_unref (auth_context->dbus_auth);
206
207         if (auth_context->cancellable != NULL)
208                 g_object_unref (auth_context->cancellable);
209
210         if (auth_context->main_loop != NULL)
211                 g_main_loop_unref (auth_context->main_loop);
212
213         if (auth_context->secret_exchange != NULL)
214                 g_object_unref (auth_context->secret_exchange);
215
216         g_slice_free (AuthContext, auth_context);
217 }
218
219 static void
220 source_closure_free (SourceClosure *closure)
221 {
222         g_object_unref (closure->registry);
223         g_object_unref (closure->source);
224
225         g_slice_free (SourceClosure, closure);
226 }
227
228 static void
229 thread_closure_free (ThreadClosure *closure)
230 {
231         /* The registry member is not referenced. */
232
233         g_main_context_unref (closure->main_context);
234         g_main_loop_unref (closure->main_loop);
235         g_cond_free (closure->main_loop_cond);
236         g_mutex_free (closure->main_loop_mutex);
237
238         g_slice_free (ThreadClosure, closure);
239 }
240
241 static void
242 source_registry_object_path_table_insert (ESourceRegistry *registry,
243                                           const gchar *object_path,
244                                           ESource *source)
245 {
246         g_return_if_fail (object_path != NULL);
247         g_return_if_fail (E_IS_SOURCE (source));
248
249         g_mutex_lock (registry->priv->object_path_table_lock);
250
251         g_hash_table_insert (
252                 registry->priv->object_path_table,
253                 g_strdup (object_path),
254                 g_object_ref (source));
255
256         g_mutex_unlock (registry->priv->object_path_table_lock);
257 }
258
259 static ESource *
260 source_registry_object_path_table_lookup (ESourceRegistry *registry,
261                                           const gchar *object_path)
262 {
263         ESource *source;
264
265         g_return_val_if_fail (object_path != NULL, NULL);
266
267         g_mutex_lock (registry->priv->object_path_table_lock);
268
269         source = g_hash_table_lookup (
270                 registry->priv->object_path_table, object_path);
271         if (source != NULL)
272                 g_object_ref (source);
273
274         g_mutex_unlock (registry->priv->object_path_table_lock);
275
276         return source;
277 }
278
279 static gboolean
280 source_registry_object_path_table_remove (ESourceRegistry *registry,
281                                           const gchar *object_path)
282 {
283         gboolean removed;
284
285         g_return_val_if_fail (object_path != NULL, FALSE);
286
287         g_mutex_lock (registry->priv->object_path_table_lock);
288
289         removed = g_hash_table_remove (
290                 registry->priv->object_path_table, object_path);
291
292         g_mutex_unlock (registry->priv->object_path_table_lock);
293
294         return removed;
295 }
296
297 static void
298 source_registry_sources_insert (ESourceRegistry *registry,
299                                 ESource *source)
300 {
301         const gchar *uid;
302
303         uid = e_source_get_uid (source);
304         g_return_if_fail (uid != NULL);
305
306         g_mutex_lock (registry->priv->sources_lock);
307
308         g_hash_table_insert (
309                 registry->priv->sources,
310                 g_strdup (uid), g_object_ref (source));
311
312         g_mutex_unlock (registry->priv->sources_lock);
313 }
314
315 static gboolean
316 source_registry_sources_remove (ESourceRegistry *registry,
317                                 ESource *source)
318 {
319         const gchar *uid;
320         gboolean removed;
321
322         uid = e_source_get_uid (source);
323         g_return_val_if_fail (uid != NULL, FALSE);
324
325         g_mutex_lock (registry->priv->sources_lock);
326
327         removed = g_hash_table_remove (registry->priv->sources, uid);
328
329         g_mutex_unlock (registry->priv->sources_lock);
330
331         return removed;
332 }
333
334 static ESource *
335 source_registry_sources_lookup (ESourceRegistry *registry,
336                                 const gchar *uid)
337 {
338         ESource *source;
339
340         g_return_val_if_fail (uid != NULL, NULL);
341
342         g_mutex_lock (registry->priv->sources_lock);
343
344         source = g_hash_table_lookup (registry->priv->sources, uid);
345
346         if (source != NULL)
347                 g_object_ref (source);
348
349         g_mutex_unlock (registry->priv->sources_lock);
350
351         return source;
352 }
353
354 static GList *
355 source_registry_sources_get_values (ESourceRegistry *registry)
356 {
357         GList *values;
358
359         g_mutex_lock (registry->priv->sources_lock);
360
361         values = g_hash_table_get_values (registry->priv->sources);
362
363         g_list_foreach (values, (GFunc) g_object_ref, NULL);
364
365         g_mutex_unlock (registry->priv->sources_lock);
366
367         return values;
368 }
369
370 static GNode *
371 source_registry_sources_build_tree (ESourceRegistry *registry)
372 {
373         GNode *root;
374         GHashTable *index;
375         GHashTableIter iter;
376         gpointer key, value;
377
378         g_mutex_lock (registry->priv->sources_lock);
379
380         root = g_node_new (NULL);
381         index = g_hash_table_new (g_str_hash, g_str_equal);
382
383         /* Add a GNode for each ESource to the index. */
384         g_hash_table_iter_init (&iter, registry->priv->sources);
385         while (g_hash_table_iter_next (&iter, &key, &value)) {
386                 ESource *source = g_object_ref (value);
387                 g_hash_table_insert (index, key, g_node_new (source));
388         }
389
390         /* Traverse the index and link the nodes together. */
391         g_hash_table_iter_init (&iter, index);
392         while (g_hash_table_iter_next (&iter, NULL, &value)) {
393                 ESource *source;
394                 GNode *source_node;
395                 GNode *parent_node;
396                 const gchar *parent_uid;
397
398                 source_node = (GNode *) value;
399                 source = E_SOURCE (source_node->data);
400                 parent_uid = e_source_get_parent (source);
401
402                 if (parent_uid == NULL || *parent_uid == '\0') {
403                         parent_node = root;
404                 } else {
405                         parent_node = g_hash_table_lookup (index, parent_uid);
406                         g_warn_if_fail (parent_node != NULL);
407                 }
408
409                 /* Should never be NULL, but just to be safe. */
410                 if (parent_node != NULL)
411                         g_node_append (parent_node, source_node);
412         }
413
414         g_hash_table_destroy (index);
415
416         g_mutex_unlock (registry->priv->sources_lock);
417
418         return root;
419 }
420
421 static void
422 source_registry_settings_changed_cb (GSettings *settings,
423                                      const gchar *key,
424                                      ESourceRegistry *registry)
425 {
426         /* We define a property name that matches every key in
427          * the "org.gnome.Evolution.DefaultSources" schema. */
428         g_object_notify (G_OBJECT (registry), key);
429 }
430
431 static gboolean
432 source_registry_source_changed_idle_cb (gpointer user_data)
433 {
434         SourceClosure *closure = user_data;
435
436         g_signal_emit (
437                 closure->registry,
438                 signals[SOURCE_CHANGED], 0,
439                 closure->source);
440
441         return FALSE;
442 }
443
444 static gboolean
445 source_registry_source_notify_enabled_idle_cb (gpointer user_data)
446 {
447         SourceClosure *closure = user_data;
448
449         if (e_source_get_enabled (closure->source))
450                 g_signal_emit (
451                         closure->registry,
452                         signals[SOURCE_ENABLED], 0,
453                         closure->source);
454         else
455                 g_signal_emit (
456                         closure->registry,
457                         signals[SOURCE_DISABLED], 0,
458                         closure->source);
459
460         return FALSE;
461 }
462
463 static void
464 source_registry_source_changed_cb (ESource *source,
465                                    ESourceRegistry *registry)
466 {
467         GSource *idle_source;
468         SourceClosure *closure;
469
470         closure = g_slice_new0 (SourceClosure);
471         closure->registry = g_object_ref (registry);
472         closure->source = g_object_ref (source);
473
474         idle_source = g_idle_source_new ();
475         g_source_set_callback (
476                 idle_source,
477                 source_registry_source_changed_idle_cb,
478                 closure, (GDestroyNotify) source_closure_free);
479         g_source_attach (idle_source, registry->priv->main_context);
480         g_source_unref (idle_source);
481 }
482
483 static void
484 source_registry_source_notify_enabled_cb (ESource *source,
485                                           GParamSpec *pspec,
486                                           ESourceRegistry *registry)
487 {
488         GSource *idle_source;
489         SourceClosure *closure;
490
491         closure = g_slice_new0 (SourceClosure);
492         closure->registry = g_object_ref (registry);
493         closure->source = g_object_ref (source);
494
495         idle_source = g_idle_source_new ();
496         g_source_set_callback (
497                 idle_source,
498                 source_registry_source_notify_enabled_idle_cb,
499                 closure, (GDestroyNotify) source_closure_free);
500         g_source_attach (idle_source, registry->priv->main_context);
501         g_source_unref (idle_source);
502 }
503
504 static ESource *
505 source_registry_new_source (ESourceRegistry *registry,
506                             GDBusObject *dbus_object)
507 {
508         GMainContext *main_context;
509         ESource *source;
510         const gchar *object_path;
511         GError *error = NULL;
512
513         /* We don't want the ESource emitting "changed" signals from
514          * the manager thread, so we pass it the same main context the
515          * registry uses for scheduling signal emissions. */
516         main_context = registry->priv->main_context;
517         source = e_source_new (dbus_object, main_context, &error);
518         object_path = g_dbus_object_get_object_path (dbus_object);
519
520         /* The likelihood of an error here is slim, so it's
521          * sufficient to just print a warning if one occurs. */
522         if (error != NULL) {
523                 g_warn_if_fail (source == NULL);
524                 g_critical (
525                         "ESourceRegistry: Failed to create a "
526                         "data source object for path '%s': %s",
527                         object_path, error->message);
528                 g_error_free (error);
529                 return NULL;
530         }
531
532         g_return_val_if_fail (E_IS_SOURCE (source), NULL);
533
534         /* Add the ESource to the object path table immediately. */
535         source_registry_object_path_table_insert (
536                 registry, object_path, source);
537
538         return source;
539 }
540
541 static void
542 source_registry_unref_source (ESource *source)
543 {
544         g_signal_handlers_disconnect_matched (
545                 source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
546                 source_registry_source_changed_cb, NULL);
547
548         g_signal_handlers_disconnect_matched (
549                 source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
550                 source_registry_source_notify_enabled_cb, NULL);
551
552         g_object_unref (source);
553 }
554
555 static void
556 source_registry_add_source (ESourceRegistry *registry,
557                             ESource *source)
558 {
559         const gchar *uid;
560
561         uid = e_source_get_uid (source);
562         g_return_if_fail (uid != NULL);
563
564         g_mutex_lock (registry->priv->sources_lock);
565
566         /* Check if we already have this source in the registry. */
567         if (g_hash_table_lookup (registry->priv->sources, uid) != NULL) {
568                 g_mutex_unlock (registry->priv->sources_lock);
569                 return;
570         }
571
572         g_signal_connect (
573                 source, "changed",
574                 G_CALLBACK (source_registry_source_changed_cb),
575                 registry);
576
577         g_signal_connect (
578                 source, "notify::enabled",
579                 G_CALLBACK (source_registry_source_notify_enabled_cb),
580                 registry);
581
582         g_mutex_unlock (registry->priv->sources_lock);
583
584         source_registry_sources_insert (registry, source);
585
586         g_signal_emit (registry, signals[SOURCE_ADDED], 0, source);
587 }
588
589 static void
590 source_registry_remove_source (ESourceRegistry *registry,
591                                ESource *source)
592 {
593         g_object_ref (source);
594
595         if (source_registry_sources_remove (registry, source))
596                 g_signal_emit (registry, signals[SOURCE_REMOVED], 0, source);
597
598         g_object_unref (source);
599 }
600
601 static gboolean
602 source_registry_object_added_idle_cb (gpointer user_data)
603 {
604         SourceClosure *closure = user_data;
605
606         source_registry_add_source (closure->registry, closure->source);
607
608         return FALSE;
609 }
610
611 static void
612 source_registry_object_added_cb (GDBusObjectManager *object_manager,
613                                  GDBusObject *dbus_object,
614                                  ESourceRegistry *registry)
615 {
616         SourceClosure *closure;
617         GSource *idle_source;
618         ESource *source;
619
620         g_return_if_fail (E_DBUS_IS_OBJECT (dbus_object));
621
622         source = source_registry_new_source (registry, dbus_object);
623         g_return_if_fail (source != NULL);
624
625         /* Schedule a callback on the ESourceRegistry's GMainContext. */
626
627         closure = g_slice_new0 (SourceClosure);
628         closure->registry = g_object_ref (registry);
629         closure->source = g_object_ref (source);
630
631         idle_source = g_idle_source_new ();
632         g_source_set_callback (
633                 idle_source,
634                 source_registry_object_added_idle_cb,
635                 closure, (GDestroyNotify) source_closure_free);
636         g_source_attach (idle_source, registry->priv->main_context);
637         g_source_unref (idle_source);
638
639         g_object_unref (source);
640 }
641
642 static gboolean
643 source_registry_object_removed_idle_cb (gpointer user_data)
644 {
645         SourceClosure *closure = user_data;
646
647         source_registry_remove_source (closure->registry, closure->source);
648
649         return FALSE;
650 }
651
652 static void
653 source_registry_object_removed_cb (GDBusObjectManager *manager,
654                                    GDBusObject *dbus_object,
655                                    ESourceRegistry *registry)
656 {
657         SourceClosure *closure;
658         GSource *idle_source;
659         ESource *source;
660         const gchar *object_path;
661
662         /* Find the corresponding ESource in the object path table.
663          * Note that the lookup returns a new ESource reference. */
664         object_path = g_dbus_object_get_object_path (dbus_object);
665         source = source_registry_object_path_table_lookup (
666                 registry, object_path);
667         g_return_if_fail (E_IS_SOURCE (source));
668
669         /* Remove the ESource from the object path table immediately. */
670         source_registry_object_path_table_remove (registry, object_path);
671
672         /* Schedule a callback on the ESourceRegistry's GMainContext. */
673
674         closure = g_slice_new0 (SourceClosure);
675         closure->registry = g_object_ref (registry);
676         closure->source = g_object_ref (source);
677
678         idle_source = g_idle_source_new ();
679         g_source_set_callback (
680                 idle_source,
681                 source_registry_object_removed_idle_cb,
682                 closure, (GDestroyNotify) source_closure_free);
683         g_source_attach (idle_source, registry->priv->main_context);
684         g_source_unref (idle_source);
685
686         g_object_unref (source);
687 }
688
689 static gboolean
690 source_registry_object_manager_running (gpointer data)
691 {
692         ThreadClosure *closure = data;
693
694         g_mutex_lock (closure->main_loop_mutex);
695         g_cond_broadcast (closure->main_loop_cond);
696         g_mutex_unlock (closure->main_loop_mutex);
697
698         return FALSE;
699 }
700
701 static gpointer
702 source_registry_object_manager_thread (gpointer data)
703 {
704         GDBusObjectManager *object_manager;
705         ThreadClosure *closure = data;
706         GSource *idle_source;
707         GList *list, *link;
708         gulong object_added_id;
709         gulong object_removed_id;
710         GError *error = NULL;
711
712         /* GDBusObjectManagerClient grabs the thread-default GMainContext
713          * at creation time and only emits signals from that GMainContext.
714          * Running it in a separate thread prevents its signal emissions
715          * from being inhibited by someone overriding the thread-default
716          * GMainContext. */
717
718         /* This becomes the GMainContext that GDBusObjectManagerClient
719          * will emit signals from.  Make it the thread-default context
720          * for this thread before creating the client. */
721         g_main_context_push_thread_default (closure->main_context);
722
723         object_manager = e_dbus_object_manager_client_new_for_bus_sync (
724                 G_BUS_TYPE_SESSION,
725                 G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
726                 SOURCES_DBUS_SERVICE_NAME,
727                 DBUS_OBJECT_PATH,
728                 NULL, &error);
729
730         /* If this fails there's really no point in continuing
731          * since we rely on the object manager to populate the
732          * registry.  Abort the process with a fatal error. */
733         if (error != NULL) {
734                 g_error ("%s", error->message);
735                 g_assert_not_reached ();
736         }
737
738         /* Give the registry a handle to the object manager. */
739         closure->registry->priv->dbus_object_manager =
740                 g_object_ref (object_manager);
741
742         /* Now populate the registry with an initial set of ESources. */
743
744         list = g_dbus_object_manager_get_objects (object_manager);
745
746         for (link = list; link != NULL; link = g_list_next (link)) {
747                 GDBusObject *dbus_object;
748                 ESource *source;
749
750                 dbus_object = G_DBUS_OBJECT (link->data);
751
752                 source = source_registry_new_source (
753                         closure->registry, dbus_object);
754
755                 if (source != NULL) {
756                         source_registry_add_source (
757                                 closure->registry, source);
758                         g_object_unref (source);
759                 }
760         }
761
762         g_list_free_full (list, (GDestroyNotify) g_object_unref);
763
764         /* Schedule a one-time idle callback to broadcast through a
765          * condition variable that our main loop is up and running. */
766
767         idle_source = g_idle_source_new ();
768         g_source_set_callback (
769                 idle_source,
770                 source_registry_object_manager_running,
771                 closure, (GDestroyNotify) NULL);
772         g_source_attach (idle_source, closure->main_context);
773         g_source_unref (idle_source);
774
775         /* Listen for D-Bus object additions and removals. */
776
777         object_added_id = g_signal_connect (
778                 object_manager, "object-added",
779                 G_CALLBACK (source_registry_object_added_cb),
780                 closure->registry);
781
782         object_removed_id = g_signal_connect (
783                 object_manager, "object-removed",
784                 G_CALLBACK (source_registry_object_removed_cb),
785                 closure->registry);
786
787         /* Now we mostly idle here for the rest of the session. */
788
789         g_main_loop_run (closure->main_loop);
790
791         /* Clean up and exit. */
792
793         g_signal_handler_disconnect (object_manager, object_added_id);
794         g_signal_handler_disconnect (object_manager, object_removed_id);
795
796         g_object_unref (object_manager);
797
798         g_main_context_pop_thread_default (closure->main_context);
799
800         return NULL;
801 }
802
803 static void
804 source_registry_set_property (GObject *object,
805                               guint property_id,
806                               const GValue *value,
807                               GParamSpec *pspec)
808 {
809         switch (property_id) {
810                 case PROP_DEFAULT_ADDRESS_BOOK:
811                         e_source_registry_set_default_address_book (
812                                 E_SOURCE_REGISTRY (object),
813                                 g_value_get_object (value));
814                         return;
815
816                 case PROP_DEFAULT_CALENDAR:
817                         e_source_registry_set_default_calendar (
818                                 E_SOURCE_REGISTRY (object),
819                                 g_value_get_object (value));
820                         return;
821
822                 case PROP_DEFAULT_MAIL_ACCOUNT:
823                         e_source_registry_set_default_mail_account (
824                                 E_SOURCE_REGISTRY (object),
825                                 g_value_get_object (value));
826                         return;
827
828                 case PROP_DEFAULT_MAIL_IDENTITY:
829                         e_source_registry_set_default_mail_identity (
830                                 E_SOURCE_REGISTRY (object),
831                                 g_value_get_object (value));
832                         return;
833
834                 case PROP_DEFAULT_MEMO_LIST:
835                         e_source_registry_set_default_memo_list (
836                                 E_SOURCE_REGISTRY (object),
837                                 g_value_get_object (value));
838                         return;
839
840                 case PROP_DEFAULT_TASK_LIST:
841                         e_source_registry_set_default_task_list (
842                                 E_SOURCE_REGISTRY (object),
843                                 g_value_get_object (value));
844                         return;
845         }
846
847         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
848 }
849
850 static void
851 source_registry_get_property (GObject *object,
852                               guint property_id,
853                               GValue *value,
854                               GParamSpec *pspec)
855 {
856         switch (property_id) {
857                 case PROP_DEFAULT_ADDRESS_BOOK:
858                         g_value_take_object (
859                                 value,
860                                 e_source_registry_ref_default_address_book (
861                                 E_SOURCE_REGISTRY (object)));
862                         return;
863
864                 case PROP_DEFAULT_CALENDAR:
865                         g_value_take_object (
866                                 value,
867                                 e_source_registry_ref_default_calendar (
868                                 E_SOURCE_REGISTRY (object)));
869                         return;
870
871                 case PROP_DEFAULT_MAIL_ACCOUNT:
872                         g_value_take_object (
873                                 value,
874                                 e_source_registry_ref_default_mail_account (
875                                 E_SOURCE_REGISTRY (object)));
876                         return;
877
878                 case PROP_DEFAULT_MAIL_IDENTITY:
879                         g_value_take_object (
880                                 value,
881                                 e_source_registry_ref_default_mail_identity (
882                                 E_SOURCE_REGISTRY (object)));
883                         return;
884
885                 case PROP_DEFAULT_MEMO_LIST:
886                         g_value_take_object (
887                                 value,
888                                 e_source_registry_ref_default_memo_list (
889                                 E_SOURCE_REGISTRY (object)));
890                         return;
891
892                 case PROP_DEFAULT_TASK_LIST:
893                         g_value_take_object (
894                                 value,
895                                 e_source_registry_ref_default_task_list (
896                                 E_SOURCE_REGISTRY (object)));
897                         return;
898         }
899
900         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
901 }
902
903 static void
904 source_registry_dispose (GObject *object)
905 {
906         ESourceRegistryPrivate *priv;
907
908         priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
909
910         /* Terminate the manager thread first. */
911         if (priv->manager_thread != NULL) {
912                 g_main_loop_quit (priv->thread_closure->main_loop);
913                 g_thread_join (priv->manager_thread);
914                 thread_closure_free (priv->thread_closure);
915                 priv->manager_thread = NULL;
916                 priv->thread_closure = NULL;
917         }
918
919         if (priv->main_context != NULL) {
920                 g_main_context_unref (priv->main_context);
921                 priv->main_context = NULL;
922         }
923
924         if (priv->dbus_object_manager != NULL) {
925                 g_object_unref (priv->dbus_object_manager);
926                 priv->dbus_object_manager = NULL;
927         }
928
929         if (priv->dbus_source_manager != NULL) {
930                 g_object_unref (priv->dbus_source_manager);
931                 priv->dbus_source_manager = NULL;
932         }
933
934         g_hash_table_remove_all (priv->object_path_table);
935
936         g_hash_table_remove_all (priv->sources);
937
938         if (priv->settings != NULL) {
939                 g_object_unref (priv->settings);
940                 priv->settings = NULL;
941         }
942
943         /* Chain up to parent's finalize() method. */
944         G_OBJECT_CLASS (e_source_registry_parent_class)->dispose (object);
945 }
946
947 static void
948 source_registry_finalize (GObject *object)
949 {
950         ESourceRegistryPrivate *priv;
951
952         priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
953
954         g_hash_table_destroy (priv->object_path_table);
955         g_mutex_free (priv->object_path_table_lock);
956
957         g_hash_table_destroy (priv->sources);
958         g_mutex_free (priv->sources_lock);
959
960         /* Chain up to parent's finalize() method. */
961         G_OBJECT_CLASS (e_source_registry_parent_class)->finalize (object);
962 }
963
964 static gboolean
965 source_registry_initable_init (GInitable *initable,
966                                GCancellable *cancellable,
967                                GError **error)
968 {
969         ESourceRegistry *registry;
970         ThreadClosure *closure;
971
972         registry = E_SOURCE_REGISTRY (initable);
973
974         closure = g_slice_new0 (ThreadClosure);
975         closure->registry = registry;  /* do not reference */
976         closure->main_context = g_main_context_new ();
977         /* It's important to pass 'is_running=FALSE' here because
978          * we wait for the main loop to start running as a way of
979          * synchronizing with the manager thread. */
980         closure->main_loop = g_main_loop_new (closure->main_context, FALSE);
981         closure->main_loop_cond = g_cond_new ();
982         closure->main_loop_mutex = g_mutex_new ();
983
984         registry->priv->thread_closure = closure;
985
986         registry->priv->manager_thread = g_thread_create (
987                 source_registry_object_manager_thread,
988                 closure, TRUE /* joinable */, error);
989
990         if (registry->priv->manager_thread == NULL)
991                 return FALSE;
992
993         /* Wait for notification that the manager
994          * thread's main loop has been started. */
995         g_mutex_lock (closure->main_loop_mutex);
996         while (!g_main_loop_is_running (closure->main_loop))
997                 g_cond_wait (
998                         closure->main_loop_cond,
999                         closure->main_loop_mutex);
1000         g_mutex_unlock (closure->main_loop_mutex);
1001
1002         /* We should now have a GDBusObjectManagerClient available. */
1003         g_return_val_if_fail (
1004                 G_IS_DBUS_OBJECT_MANAGER_CLIENT (
1005                 registry->priv->dbus_object_manager), FALSE);
1006
1007         /* The registry should now be populated with sources. */
1008         g_warn_if_fail (g_hash_table_size (registry->priv->sources) > 0);
1009
1010         /* The EDBusSourceManagerProxy is just another D-Bus interface
1011          * that resides at the same object path.  It's unrelated to the
1012          * GDBusObjectManagerClient and doesn't need its own thread. */
1013         registry->priv->dbus_source_manager =
1014                 e_dbus_source_manager_proxy_new_for_bus_sync (
1015                         G_BUS_TYPE_SESSION,
1016                         G_DBUS_PROXY_FLAGS_NONE,
1017                         SOURCES_DBUS_SERVICE_NAME,
1018                         DBUS_OBJECT_PATH,
1019                         cancellable, error);
1020
1021         if (registry->priv->dbus_source_manager == NULL)
1022                 return FALSE;
1023
1024         return TRUE;
1025 }
1026
1027 static void
1028 e_source_registry_class_init (ESourceRegistryClass *class)
1029 {
1030         GObjectClass *object_class;
1031
1032         g_type_class_add_private (class, sizeof (ESourceRegistryPrivate));
1033
1034         object_class = G_OBJECT_CLASS (class);
1035         object_class->set_property = source_registry_set_property;
1036         object_class->get_property = source_registry_get_property;
1037         object_class->dispose = source_registry_dispose;
1038         object_class->finalize = source_registry_finalize;
1039
1040         /* The property names correspond to the key names in the
1041          * "org.gnome.Evolution.DefaultSources" GSettings schema. */
1042
1043         /**
1044          * ESourceRegistry:default-address-book:
1045          *
1046          * The default address book #ESource.
1047          **/
1048         g_object_class_install_property (
1049                 object_class,
1050                 PROP_DEFAULT_ADDRESS_BOOK,
1051                 g_param_spec_object (
1052                         "default-address-book",
1053                         "Default Address Book",
1054                         "The default address book ESource",
1055                         E_TYPE_SOURCE,
1056                         G_PARAM_READWRITE |
1057                         G_PARAM_STATIC_STRINGS));
1058
1059         /**
1060          * ESourceRegistry:default-calendar:
1061          *
1062          * The default calendar #ESource.
1063          **/
1064         g_object_class_install_property (
1065                 object_class,
1066                 PROP_DEFAULT_CALENDAR,
1067                 g_param_spec_object (
1068                         "default-calendar",
1069                         "Default Calendar",
1070                         "The default calendar ESource",
1071                         E_TYPE_SOURCE,
1072                         G_PARAM_READWRITE |
1073                         G_PARAM_STATIC_STRINGS));
1074
1075         /**
1076          * ESourceRegistry:default-mail-account:
1077          *
1078          * The default mail account #ESource.
1079          **/
1080         g_object_class_install_property (
1081                 object_class,
1082                 PROP_DEFAULT_MAIL_ACCOUNT,
1083                 g_param_spec_object (
1084                         "default-mail-account",
1085                         "Default Mail Account",
1086                         "The default mail account ESource",
1087                         E_TYPE_SOURCE,
1088                         G_PARAM_READWRITE |
1089                         G_PARAM_STATIC_STRINGS));
1090
1091         /**
1092          * ESourceRegistry:default-mail-identity:
1093          *
1094          * The default mail identity #ESource.
1095          **/
1096         g_object_class_install_property (
1097                 object_class,
1098                 PROP_DEFAULT_MAIL_IDENTITY,
1099                 g_param_spec_object (
1100                         "default-mail-identity",
1101                         "Default Mail Identity",
1102                         "The default mail identity ESource",
1103                         E_TYPE_SOURCE,
1104                         G_PARAM_READWRITE |
1105                         G_PARAM_STATIC_STRINGS));
1106
1107         /**
1108          * ESourceRegistry:default-memo-list:
1109          *
1110          * The default memo list #ESource.
1111          **/
1112         g_object_class_install_property (
1113                 object_class,
1114                 PROP_DEFAULT_MEMO_LIST,
1115                 g_param_spec_object (
1116                         "default-memo-list",
1117                         "Default Memo List",
1118                         "The default memo list ESource",
1119                         E_TYPE_SOURCE,
1120                         G_PARAM_READWRITE |
1121                         G_PARAM_STATIC_STRINGS));
1122
1123         /**
1124          * ESourceRegistry:default-task-list:
1125          *
1126          * The default task list #ESource.
1127          **/
1128         g_object_class_install_property (
1129                 object_class,
1130                 PROP_DEFAULT_TASK_LIST,
1131                 g_param_spec_object (
1132                         "default-task-list",
1133                         "Default Task List",
1134                         "The default task list ESource",
1135                         E_TYPE_SOURCE,
1136                         G_PARAM_READWRITE |
1137                         G_PARAM_STATIC_STRINGS));
1138
1139         /**
1140          * ESourceRegistry::source-added:
1141          * @registry: the #ESourceRegistry which emitted the signal
1142          * @source: the newly-added #ESource
1143          *
1144          * Emitted when an #ESource is added to @registry.
1145          **/
1146         signals[SOURCE_ADDED] = g_signal_new (
1147                 "source-added",
1148                 G_OBJECT_CLASS_TYPE (object_class),
1149                 G_SIGNAL_RUN_LAST,
1150                 G_STRUCT_OFFSET (ESourceRegistryClass, source_added),
1151                 NULL, NULL,
1152                 g_cclosure_marshal_VOID__OBJECT,
1153                 G_TYPE_NONE, 1,
1154                 E_TYPE_SOURCE);
1155
1156         /**
1157          * ESourceRegistry::source-changed:
1158          * @registry: the #ESourceRegistry which emitted the signal
1159          * @source: the #ESource that changed
1160          *
1161          * Emitted when an #ESource registered with @registry emits
1162          * its #ESource::changed signal.
1163          **/
1164         signals[SOURCE_CHANGED] = g_signal_new (
1165                 "source-changed",
1166                 G_OBJECT_CLASS_TYPE (object_class),
1167                 G_SIGNAL_RUN_LAST,
1168                 G_STRUCT_OFFSET (ESourceRegistryClass, source_changed),
1169                 NULL, NULL,
1170                 g_cclosure_marshal_VOID__OBJECT,
1171                 G_TYPE_NONE, 1,
1172                 E_TYPE_SOURCE);
1173
1174         /**
1175          * ESourceRegistry::source-removed:
1176          * @registry: the #ESourceRegistry which emitted the signal
1177          * @source: the #ESource that got removed
1178          *
1179          * Emitted when an #ESource is removed from @registry.
1180          **/
1181         signals[SOURCE_REMOVED] = g_signal_new (
1182                 "source-removed",
1183                 G_OBJECT_CLASS_TYPE (object_class),
1184                 G_SIGNAL_RUN_LAST,
1185                 G_STRUCT_OFFSET (ESourceRegistryClass, source_removed),
1186                 NULL, NULL,
1187                 g_cclosure_marshal_VOID__OBJECT,
1188                 G_TYPE_NONE, 1,
1189                 E_TYPE_SOURCE);
1190
1191         /**
1192          * ESourceRegistry::source-enabled:
1193          * @registry: the #ESourceRegistry which emitted the signal
1194          * @source: the #ESource that got enabled
1195          *
1196          * Emitted when an #ESource #ESource:enabled property becomes %TRUE.
1197          **/
1198         signals[SOURCE_ENABLED] = g_signal_new (
1199                 "source-enabled",
1200                 G_OBJECT_CLASS_TYPE (object_class),
1201                 G_SIGNAL_RUN_LAST,
1202                 G_STRUCT_OFFSET (ESourceRegistryClass, source_enabled),
1203                 NULL, NULL,
1204                 g_cclosure_marshal_VOID__OBJECT,
1205                 G_TYPE_NONE, 1,
1206                 E_TYPE_SOURCE);
1207
1208         /**
1209          * ESourceRegistry::source-disabled:
1210          * @registry: the #ESourceRegistry which emitted the signal
1211          * @source: the #ESource that got disabled
1212          *
1213          * Emitted when an #ESource #ESource:enabled property becomes %FALSE.
1214          **/
1215         signals[SOURCE_DISABLED] = g_signal_new (
1216                 "source-disabled",
1217                 G_OBJECT_CLASS_TYPE (object_class),
1218                 G_SIGNAL_RUN_LAST,
1219                 G_STRUCT_OFFSET (ESourceRegistryClass, source_disabled),
1220                 NULL, NULL,
1221                 g_cclosure_marshal_VOID__OBJECT,
1222                 G_TYPE_NONE, 1,
1223                 E_TYPE_SOURCE);
1224 }
1225
1226 static void
1227 e_source_registry_initable_init (GInitableIface *interface)
1228 {
1229         interface->init = source_registry_initable_init;
1230 }
1231
1232 static void
1233 e_source_registry_init (ESourceRegistry *registry)
1234 {
1235         registry->priv = E_SOURCE_REGISTRY_GET_PRIVATE (registry);
1236
1237         /* This is so the object manager thread can schedule signal
1238          * emissions on the thread-default context for this thread. */
1239         registry->priv->main_context = g_main_context_ref_thread_default ();
1240
1241         /* D-Bus object path -> ESource */
1242         registry->priv->object_path_table =
1243                 g_hash_table_new_full (
1244                         (GHashFunc) g_str_hash,
1245                         (GEqualFunc) g_str_equal,
1246                         (GDestroyNotify) g_free,
1247                         (GDestroyNotify) g_object_unref);
1248
1249         registry->priv->object_path_table_lock = g_mutex_new ();
1250
1251         /* UID string -> ESource */
1252         registry->priv->sources = g_hash_table_new_full (
1253                 (GHashFunc) g_str_hash,
1254                 (GEqualFunc) g_str_equal,
1255                 (GDestroyNotify) g_free,
1256                 (GDestroyNotify) source_registry_unref_source);
1257
1258         registry->priv->sources_lock = g_mutex_new ();
1259
1260         registry->priv->settings = g_settings_new (GSETTINGS_SCHEMA);
1261
1262         g_signal_connect (
1263                 registry->priv->settings, "changed",
1264                 G_CALLBACK (source_registry_settings_changed_cb), registry);
1265 }
1266
1267 /**
1268  * e_source_registry_new_sync:
1269  * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1270  * @error: return location for a #GError, or %NULL
1271  *
1272  * Creates a new #ESourceRegistry front-end for the registry D-Bus service.
1273  * If an error occurs in connecting to the D-Bus service, the function sets
1274  * @error and returns %NULL.
1275  *
1276  * Returns: a new #ESourceRegistry, or %NULL
1277  *
1278  * Since: 3.6
1279  **/
1280 ESourceRegistry *
1281 e_source_registry_new_sync (GCancellable *cancellable,
1282                             GError **error)
1283 {
1284         return g_initable_new (
1285                 E_TYPE_SOURCE_REGISTRY,
1286                 cancellable, error, NULL);
1287 }
1288
1289 /**
1290  * e_source_registry_new:
1291  * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1292  * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1293  *            is satisfied
1294  * @user_data: (closure): data to pass to the callback function
1295  *
1296  * Asynchronously creates a new #ESourceRegistry front-end for the registry
1297  * D-Bus service.
1298  *
1299  * When the operation is finished, @callback will be called.  You can then
1300  * call e_source_registry_new_finish() to get the result of the operation.
1301  *
1302  * Since: 3.6
1303  **/
1304 void
1305 e_source_registry_new (GCancellable *cancellable,
1306                        GAsyncReadyCallback callback,
1307                        gpointer user_data)
1308 {
1309         g_async_initable_new_async (
1310                 E_TYPE_SOURCE_REGISTRY,
1311                 G_PRIORITY_DEFAULT, cancellable,
1312                 callback, user_data, NULL);
1313 }
1314
1315 /**
1316  * e_source_registry_new_finish:
1317  * @result: a #GAsyncResult
1318  * @error: return location for a #GError, or %NULL
1319  *
1320  * Finishes the operation started with e_source_registry_new_finish().
1321  * If an error occurs in connecting to the D-Bus service, the function
1322  * sets @error and returns %NULL.
1323  *
1324  * Returns: a new #ESourceRegistry, or %NULL
1325  *
1326  * Since: 3.6
1327  **/
1328 ESourceRegistry *
1329 e_source_registry_new_finish (GAsyncResult *result,
1330                               GError **error)
1331 {
1332         GObject *source_object;
1333         GObject *object;
1334
1335         g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
1336
1337         source_object = g_async_result_get_source_object (result);
1338         g_return_val_if_fail (source_object != NULL, NULL);
1339
1340         object = g_async_initable_new_finish (
1341                 G_ASYNC_INITABLE (source_object), result, error);
1342
1343         g_object_unref (source_object);
1344
1345         return (object != NULL) ? E_SOURCE_REGISTRY (object) : NULL;
1346 }
1347
1348 /* Helper for e_source_registry_authenticate() */
1349 static void
1350 source_registry_authenticate_thread (GSimpleAsyncResult *simple,
1351                                      GObject *object,
1352                                      GCancellable *cancellable)
1353 {
1354         AsyncContext *async_context;
1355         GError *error = NULL;
1356
1357         async_context = g_simple_async_result_get_op_res_gpointer (simple);
1358
1359         e_source_registry_authenticate_sync (
1360                 E_SOURCE_REGISTRY (object),
1361                 async_context->source,
1362                 async_context->auth,
1363                 cancellable, &error);
1364
1365         if (error != NULL)
1366                 g_simple_async_result_take_error (simple, error);
1367 }
1368
1369 /* Helper for e_source_registry_authenticate_sync() */
1370 static gboolean
1371 source_registry_authenticate_respond_cb (AuthContext *auth_context)
1372 {
1373         ESourceAuthenticationResult auth_result;
1374         GError *non_fatal_error = NULL;
1375
1376         g_return_val_if_fail (auth_context->authenticating, FALSE);
1377
1378         auth_result = auth_context->auth_result;
1379
1380         /* Allow the next authentication attempt to proceed. */
1381         auth_context->authenticating = FALSE;
1382
1383         /* Send the server a status update based on the authentication
1384          * result.  Note, we don't really care if the D-Bus message gets
1385          * through to the server at this point.  If it doesn't, the auth
1386          * session will either time out on its own or the authentication
1387          * dialog will eventually be dismissed by the user. */
1388
1389         /* If we were cancelled from our side, we have a bit of a dilemma.
1390          * We need to tell the server to cancel the authentication session,
1391          * but that involves making a synchronous D-Bus call, which we are
1392          * not supposed to do if we know we've been cancelled.  But if we
1393          * don't tell the server, the authentication session will be left
1394          * to timeout on its own (which may take minutes), and meanwhile
1395          * all other authentication requests are blocked.  So choose the
1396          * lesser evil and make the synchronous call but without passing
1397          * the already-cancelled GCancellable. */
1398         if (g_cancellable_is_cancelled (auth_context->cancellable)) {
1399                 e_dbus_authenticator_call_cancel_sync (
1400                         auth_context->dbus_auth,
1401                         NULL, &non_fatal_error);
1402                 g_main_loop_quit (auth_context->main_loop);
1403                 auth_context->success = FALSE;
1404
1405         /* If an error occurred while attempting to authenticate,
1406          * tell the server to cancel the authentication session. */
1407         } else if (auth_result == E_SOURCE_AUTHENTICATION_ERROR) {
1408                 e_dbus_authenticator_call_cancel_sync (
1409                         auth_context->dbus_auth,
1410                         auth_context->cancellable,
1411                         &non_fatal_error);
1412                 g_main_loop_quit (auth_context->main_loop);
1413                 auth_context->success = FALSE;
1414
1415         /* If the password was accepted, let the server know so it
1416          * can close any authentication dialogs and save the user
1417          * provided password to the keyring. */
1418         } else if (auth_result == E_SOURCE_AUTHENTICATION_ACCEPTED) {
1419                 e_dbus_authenticator_call_accepted_sync (
1420                         auth_context->dbus_auth,
1421                         auth_context->cancellable,
1422                         &non_fatal_error);
1423                 g_main_loop_quit (auth_context->main_loop);
1424                 auth_context->success = TRUE;
1425
1426         /* If the password was rejected, let the server know so it can
1427          * indicate failure and request a different password, and then
1428          * wait for the next "response" signal. */
1429         } else {
1430                 e_dbus_authenticator_call_rejected_sync (
1431                         auth_context->dbus_auth,
1432                         auth_context->cancellable,
1433                         &non_fatal_error);
1434         }
1435
1436         /* Leave breadcrumbs if something went wrong,
1437          * but don't fail the whole operation over it. */
1438         if (non_fatal_error != NULL) {
1439                 g_warning ("%s: %s", G_STRFUNC, non_fatal_error->message);
1440                 g_error_free (non_fatal_error);
1441         }
1442
1443         return FALSE;
1444 }
1445
1446 /* Helper for e_source_registry_authenticate_sync() */
1447 static void
1448 source_registry_authenticate_authenticate_cb (EDBusAuthenticator *dbus_auth,
1449                                               const gchar *encrypted_secret,
1450                                               AuthContext *auth_context)
1451 {
1452         GSource *idle_source;
1453         GMainContext *main_context;
1454         GString *password;
1455         gboolean valid_secret;
1456
1457         /* We should only get one secret at a time. */
1458         g_return_if_fail (!auth_context->authenticating);
1459
1460         valid_secret = gcr_secret_exchange_receive (
1461                 auth_context->secret_exchange, encrypted_secret);
1462         g_return_if_fail (valid_secret);
1463
1464         auth_context->authenticating = TRUE;
1465
1466         /* This avoids revealing the password in a stack trace. */
1467         password = g_string_new (
1468                 gcr_secret_exchange_get_secret (
1469                 auth_context->secret_exchange, NULL));
1470
1471         /* Try authenticating with the given password.  We have to
1472          * call this synchronously because some authenticators use
1473          * mutexes to serialize I/O operations and are not prepared
1474          * to make authentication attempts from a different thread.
1475          *
1476          * Unfortunately this means we won't notice server-side
1477          * dismissals while the main loop is blocked.  We respond
1478          * to the server from a low-priority idle callback so that
1479          * any pending "dismissed" signals get handled first. */
1480
1481         auth_context->auth_result =
1482                 e_source_authenticator_try_password_sync (
1483                         auth_context->auth, password,
1484                         auth_context->cancellable,
1485                         auth_context->error);
1486
1487         idle_source = g_idle_source_new ();
1488         main_context = g_main_context_get_thread_default ();
1489         g_source_set_callback (
1490                 idle_source, (GSourceFunc)
1491                 source_registry_authenticate_respond_cb,
1492                 auth_context, NULL);
1493         g_source_attach (idle_source, main_context);
1494         g_source_unref (idle_source);
1495
1496         g_string_free (password, TRUE);
1497 }
1498
1499 /* Helper for e_source_registry_authenticate_sync() */
1500 static void
1501 source_registry_authenticate_dismissed_cb (EDBusAuthenticator *dbus_auth,
1502                                            AuthContext *auth_context)
1503 {
1504         /* Be careful not to overwrite an existing error in case this
1505          * is called after e_source_authenticator_try_password_sync()
1506          * but prior to the idle callback. */
1507         if (auth_context->auth_result != E_SOURCE_AUTHENTICATION_ERROR) {
1508                 /* XXX Use a separate error code for dismissals? */
1509                 g_set_error_literal (
1510                         auth_context->error,
1511                         G_IO_ERROR, G_IO_ERROR_CANCELLED,
1512                         _("The user declined to authenticate"));
1513                 auth_context->auth_result = E_SOURCE_AUTHENTICATION_ERROR;
1514         }
1515
1516         g_main_loop_quit (auth_context->main_loop);
1517         auth_context->success = FALSE;
1518 }
1519
1520 /* Helper for e_source_registry_authenticate_sync() */
1521 static gboolean
1522 source_registry_call_authenticate_for_source (ESourceRegistry *registry,
1523                                               ESourceAuthenticator *auth,
1524                                               ESource *source,
1525                                               gchar **out_object_path,
1526                                               GCancellable *cancellable,
1527                                               GError **error)
1528 {
1529         ESource *collection;
1530         const gchar *uid;
1531         gchar *prompt_title = NULL;
1532         gchar *prompt_message = NULL;
1533         gchar *prompt_description = NULL;
1534         gboolean success;
1535
1536         /* If the source is a member of a collection, we want to store
1537          * the password under the UID of the "collection" source so it
1538          * will apply to the entire collection.
1539          *
1540          * XXX This assumes all sources in a collection share a single
1541          *     password.  If that turns out not to be true in all cases
1542          *     we could maybe add a "SharedPassword: true/false" key to
1543          *     [Collection] and apply it here.
1544          */
1545         collection = e_source_registry_find_extension (
1546                 registry, source, E_SOURCE_EXTENSION_COLLECTION);
1547         if (collection != NULL)
1548                 source = collection;
1549         else
1550                 g_object_ref (source);
1551
1552         uid = e_source_get_uid (source);
1553
1554         e_source_authenticator_get_prompt_strings (
1555                 auth, source,
1556                 &prompt_title,
1557                 &prompt_message,
1558                 &prompt_description);
1559
1560         success = e_dbus_source_manager_call_authenticate_sync (
1561                 registry->priv->dbus_source_manager, uid,
1562                 prompt_title, prompt_message, prompt_description,
1563                 out_object_path, cancellable, error);
1564
1565         g_free (prompt_title);
1566         g_free (prompt_message);
1567         g_free (prompt_description);
1568
1569         g_object_unref (source);
1570
1571         return success;
1572 }
1573
1574 /**
1575  * e_source_registry_authenticate_sync:
1576  * @registry: an #ESourceRegistry
1577  * @source: an #ESource
1578  * @auth: an #ESourceAuthenticator
1579  * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1580  * @error: return location for a #GError, or %NULL
1581  *
1582  * Authenticates @source, using @auth to handle the authentication
1583  * attempts.  The operation loops until authentication is successful or
1584  * the user aborts further authentication attempts.  If an error occurs,
1585  * the function will set @error and return %FALSE.
1586  *
1587  * Note that @source need not have a #GDBusObject, which means this
1588  * function can test authentication on a scratch #ESource.
1589  *
1590  * Only backend implementations and data source editors should call this
1591  * function.  The intent is for basic client applications to not have to
1592  * deal with authentication at all.
1593  *
1594  * Returns: %TRUE on success, %FALSE on failure
1595  *
1596  * Since: 3.6
1597  **/
1598 gboolean
1599 e_source_registry_authenticate_sync (ESourceRegistry *registry,
1600                                      ESource *source,
1601                                      ESourceAuthenticator *auth,
1602                                      GCancellable *cancellable,
1603                                      GError **error)
1604 {
1605         AuthContext *auth_context;
1606         GMainContext *main_context;
1607         EDBusAuthenticator *dbus_auth;
1608         gchar *encryption_key;
1609         gchar *object_path = NULL;
1610         gboolean success;
1611
1612         g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
1613         g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1614         g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATOR (auth), FALSE);
1615
1616         /* This extracts authentication prompt details for the ESource
1617          * before initiating an authentication session with the server,
1618          * so split it out of the main algorithm for clarity's sake. */
1619         success = source_registry_call_authenticate_for_source (
1620                 registry, auth, source, &object_path, cancellable, error);
1621
1622         if (!success) {
1623                 g_warn_if_fail (object_path == NULL);
1624                 return FALSE;
1625         }
1626
1627         g_return_val_if_fail (object_path != NULL, FALSE);
1628
1629         main_context = g_main_context_new ();
1630         g_main_context_push_thread_default (main_context);
1631
1632         dbus_auth = e_dbus_authenticator_proxy_new_for_bus_sync (
1633                 G_BUS_TYPE_SESSION,
1634                 G_DBUS_PROXY_FLAGS_NONE,
1635                 SOURCES_DBUS_SERVICE_NAME,
1636                 object_path, cancellable, error);
1637
1638         g_free (object_path);
1639
1640         if (dbus_auth == NULL) {
1641                 success = FALSE;
1642                 goto exit;
1643         }
1644
1645         auth_context = g_slice_new0 (AuthContext);
1646         auth_context->auth = g_object_ref (auth);
1647         auth_context->dbus_auth = dbus_auth;  /* takes ownership */
1648         auth_context->main_loop = g_main_loop_new (main_context, FALSE);
1649         auth_context->error = error;
1650
1651         /* This just needs to be something other than
1652          * E_SOURCE_AUTHENTICATION_ERROR so we don't trip
1653          * up source_registry_authenticate_dismissed_cb(). */
1654         auth_context->auth_result = E_SOURCE_AUTHENTICATION_REJECTED;
1655
1656         if (G_IS_CANCELLABLE (cancellable))
1657                 auth_context->cancellable = g_object_ref (cancellable);
1658
1659         auth_context->secret_exchange =
1660                 gcr_secret_exchange_new (GCR_SECRET_EXCHANGE_PROTOCOL_1);
1661
1662         g_signal_connect (
1663                 dbus_auth, "authenticate",
1664                 G_CALLBACK (source_registry_authenticate_authenticate_cb),
1665                 auth_context);
1666
1667         g_signal_connect (
1668                 dbus_auth, "dismissed",
1669                 G_CALLBACK (source_registry_authenticate_dismissed_cb),
1670                 auth_context);
1671
1672         encryption_key = gcr_secret_exchange_begin (
1673                 auth_context->secret_exchange);
1674
1675         /* Signal the D-Bus server that we're ready to begin the
1676          * authentication session.  This must happen AFTER we've
1677          * connected to the response signal since the server may
1678          * already have a response ready and waiting for us. */
1679         success = e_dbus_authenticator_call_ready_sync (
1680                 dbus_auth, encryption_key, cancellable, error);
1681
1682         g_free (encryption_key);
1683
1684         if (success) {
1685                 g_main_loop_run (auth_context->main_loop);
1686                 success = auth_context->success;
1687         }
1688
1689         auth_context_free (auth_context);
1690
1691 exit:
1692         g_main_context_pop_thread_default (main_context);
1693         g_main_context_unref (main_context);
1694
1695         return success;
1696 }
1697
1698 /**
1699  * e_source_registry_authenticate:
1700  * @registry: an #ESourceRegistry
1701  * @source: an #ESource
1702  * @auth: an #ESourceAuthenticator
1703  * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1704  * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1705  *            is satisfied
1706  * @user_data: (closure): data to pass to the callback function
1707  *
1708  * Asynchronously authenticates @source, using @auth to handle the
1709  * authentication attempts.  The operation loops until authentication
1710  * is successful or the user aborts further authentication attempts.
1711  *
1712  * Note that @source need not have a #GDBusObject, which means this
1713  * function can test authentication on a scratch #ESource.
1714  *
1715  * When the operation is finished, @callback will be called.  You can then
1716  * call e_source_registry_authenticate_finish() to get the result of the
1717  * operation.
1718  *
1719  * Only backend implementations and data source editors should call this
1720  * function.  The intent is for basic client applications to not have to
1721  * deal with authentication at all.
1722  *
1723  * Since: 3.6
1724  **/
1725 void
1726 e_source_registry_authenticate (ESourceRegistry *registry,
1727                                 ESource *source,
1728                                 ESourceAuthenticator *auth,
1729                                 GCancellable *cancellable,
1730                                 GAsyncReadyCallback callback,
1731                                 gpointer user_data)
1732 {
1733         GSimpleAsyncResult *simple;
1734         AsyncContext *async_context;
1735
1736         g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
1737         g_return_if_fail (E_IS_SOURCE (source));
1738         g_return_if_fail (E_IS_SOURCE_AUTHENTICATOR (auth));
1739
1740         async_context = g_slice_new0 (AsyncContext);
1741         async_context->source = g_object_ref (source);
1742         async_context->auth = g_object_ref (auth);
1743
1744         simple = g_simple_async_result_new (
1745                 G_OBJECT (registry), callback, user_data,
1746                 e_source_registry_authenticate);
1747
1748         g_simple_async_result_set_check_cancellable (simple, cancellable);
1749
1750         g_simple_async_result_set_op_res_gpointer (
1751                 simple, async_context, (GDestroyNotify) async_context_free);
1752
1753         g_simple_async_result_run_in_thread (
1754                 simple, source_registry_authenticate_thread,
1755                 G_PRIORITY_DEFAULT, cancellable);
1756
1757         g_object_unref (simple);
1758 }
1759
1760 /**
1761  * e_source_registry_authenticate_finish:
1762  * @registry: an #ESourceRegistry
1763  * @result: a #GAsyncResult
1764  * @error: return location for a #GError, or %NULL
1765  *
1766  * Finishes the operation started with e_source_registry_authenticate().
1767  * If an error occurred, the function will set @error and return %FALSE.
1768  *
1769  * Returns: %TRUE on success, %FALSE on failure
1770  *
1771  * Since: 3.6
1772  **/
1773 gboolean
1774 e_source_registry_authenticate_finish (ESourceRegistry *registry,
1775                                        GAsyncResult *result,
1776                                        GError **error)
1777 {
1778         GSimpleAsyncResult *simple;
1779
1780         g_return_val_if_fail (
1781                 g_simple_async_result_is_valid (
1782                 result, G_OBJECT (registry),
1783                 e_source_registry_authenticate), FALSE);
1784
1785         simple = G_SIMPLE_ASYNC_RESULT (result);
1786
1787         /* Assume success unless a GError is set. */
1788         return !g_simple_async_result_propagate_error (simple, error);
1789 }
1790
1791 /* Helper for e_source_registry_commit_source() */
1792 static void
1793 source_registry_commit_source_thread (GSimpleAsyncResult *simple,
1794                                       GObject *object,
1795                                       GCancellable *cancellable)
1796 {
1797         AsyncContext *async_context;
1798         GError *error = NULL;
1799
1800         async_context = g_simple_async_result_get_op_res_gpointer (simple);
1801
1802         e_source_registry_commit_source_sync (
1803                 E_SOURCE_REGISTRY (object),
1804                 async_context->source,
1805                 cancellable, &error);
1806
1807         if (error != NULL)
1808                 g_simple_async_result_take_error (simple, error);
1809 }
1810
1811 /**
1812  * e_source_registry_commit_source_sync:
1813  * @registry: an #ESourceRegistry
1814  * @source: an #ESource with changes to commit
1815  * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1816  * @error: return location for #GError, or %NULL
1817  *
1818  * This is a convenience function intended for use with graphical
1819  * #ESource editors.  Call this function when the user is finished
1820  * making changes to @source.
1821  *
1822  * If @source has a #GDBusObject, its contents are submitted to the D-Bus
1823  * service through e_source_write_sync().
1824  *
1825  * If @source does NOT have a #GDBusObject (implying it's a scratch
1826  * #ESource), its contents are submitted to the D-Bus service through
1827  * e_source_registry_create_sources_sync().
1828  *
1829  * If an error occurs, the function will set @error and return %FALSE.
1830  *
1831  * Returns: %TRUE on success, %FALSE on failure
1832  *
1833  * Since: 3.6
1834  **/
1835 gboolean
1836 e_source_registry_commit_source_sync (ESourceRegistry *registry,
1837                                       ESource *source,
1838                                       GCancellable *cancellable,
1839                                       GError **error)
1840 {
1841         GDBusObject *dbus_object;
1842         gboolean success;
1843
1844         g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
1845         g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1846
1847         dbus_object = e_source_ref_dbus_object (source);
1848
1849         if (dbus_object != NULL) {
1850                 success = e_source_write_sync (source, cancellable, error);
1851                 g_object_unref (dbus_object);
1852         } else {
1853                 GList *list = g_list_prepend (NULL, source);
1854                 success = e_source_registry_create_sources_sync (
1855                         registry, list, cancellable, error);
1856                 g_list_free (list);
1857         }
1858
1859         return success;
1860 }
1861
1862 /**
1863  * e_source_registry_commit_source:
1864  * @registry: an #ESourceRegistry
1865  * @source: an #ESource with changes to commit
1866  * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1867  * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1868  *            is satisfied
1869  * @user_data: (closure): data to pass to the callback function
1870  *
1871  * See e_source_registry_commit_source_sync() for details.
1872  *
1873  * When the operation is finished, @callback will be called.  You can then
1874  * call e_source_registry_commit_source_finish() to get the result of the
1875  * operation.
1876  *
1877  * Since: 3.6
1878  **/
1879 void
1880 e_source_registry_commit_source (ESourceRegistry *registry,
1881                                  ESource *source,
1882                                  GCancellable *cancellable,
1883                                  GAsyncReadyCallback callback,
1884                                  gpointer user_data)
1885 {
1886         GSimpleAsyncResult *simple;
1887         AsyncContext *async_context;
1888
1889         g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
1890         g_return_if_fail (E_IS_SOURCE (source));
1891
1892         async_context = g_slice_new0 (AsyncContext);
1893         async_context->source = g_object_ref (source);
1894
1895         simple = g_simple_async_result_new (
1896                 G_OBJECT (registry), callback, user_data,
1897                 e_source_registry_commit_source);
1898
1899         g_simple_async_result_set_check_cancellable (simple, cancellable);
1900
1901         g_simple_async_result_set_op_res_gpointer (
1902                 simple, async_context, (GDestroyNotify) async_context_free);
1903
1904         g_simple_async_result_run_in_thread (
1905                 simple, source_registry_commit_source_thread,
1906                 G_PRIORITY_DEFAULT, cancellable);
1907
1908         g_object_unref (simple);
1909 }
1910
1911 /**
1912  * e_source_registry_commit_source_finish:
1913  * @registry: an #ESourceRegistry
1914  * @result: a #GAsyncResult
1915  * @error: return location for a #GError, or %NULL
1916  *
1917  * Finishes the operation started with e_source_registry_commit_source().
1918  *
1919  * If an error occurred, the function will set @error and return %FALSE.
1920  *
1921  * Returns: %TRUE on success, %FALSE on failure
1922  *
1923  * Since: 3.6
1924  **/
1925 gboolean
1926 e_source_registry_commit_source_finish (ESourceRegistry *registry,
1927                                         GAsyncResult *result,
1928                                         GError **error)
1929 {
1930         GSimpleAsyncResult *simple;
1931
1932         g_return_val_if_fail (
1933                 g_simple_async_result_is_valid (
1934                 result, G_OBJECT (registry),
1935                 e_source_registry_commit_source), FALSE);
1936
1937         simple = G_SIMPLE_ASYNC_RESULT (result);
1938
1939         /* Assume success unless a GError is set. */
1940         return !g_simple_async_result_propagate_error (simple, error);
1941 }
1942
1943 /* Helper for e_source_registry_create_sources() */
1944 static void
1945 source_registry_create_sources_thread (GSimpleAsyncResult *simple,
1946                                        GObject *object,
1947                                        GCancellable *cancellable)
1948 {
1949         AsyncContext *async_context;
1950         GError *error = NULL;
1951
1952         async_context = g_simple_async_result_get_op_res_gpointer (simple);
1953
1954         e_source_registry_create_sources_sync (
1955                 E_SOURCE_REGISTRY (object),
1956                 async_context->list_of_sources,
1957                 cancellable, &error);
1958
1959         if (error != NULL)
1960                 g_simple_async_result_take_error (simple, error);
1961 }
1962
1963 /**
1964  * e_source_registry_create_sources_sync:
1965  * @registry: an #ESourceRegistry
1966  * @list_of_sources: (element-type ESource): a list of #ESource instances with
1967  * no #GDBusObject
1968  * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1969  * @error: return location for a #GError, or %NULL
1970  *
1971  * Requests the D-Bus service create new key files for each #ESource in
1972  * @list_of_sources.  Each list element must be a scratch #ESource with
1973  * no #GDBusObject.
1974  *
1975  * If an error occurs, the function will set @error and return %FALSE.
1976  *
1977  * Returns: %TRUE on success, %FALSE on failure
1978  *
1979  * Since: 3.6
1980  **/
1981 gboolean
1982 e_source_registry_create_sources_sync (ESourceRegistry *registry,
1983                                        GList *list_of_sources,
1984                                        GCancellable *cancellable,
1985                                        GError **error)
1986 {
1987         GVariantBuilder builder;
1988         GVariant *variant;
1989         GList *link;
1990         gboolean success;
1991
1992         g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
1993
1994         /* Verify the list elements are all ESources. */
1995         for (link = list_of_sources; link != NULL; link = g_list_next (link))
1996                 g_return_val_if_fail (E_IS_SOURCE (link->data), FALSE);
1997
1998         g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
1999
2000         for (link = list_of_sources; link != NULL; link = g_list_next (link)) {
2001                 ESource *source;
2002                 const gchar *uid;
2003                 gchar *source_data;
2004
2005                 source = E_SOURCE (link->data);
2006                 uid = e_source_get_uid (source);
2007
2008                 source_data = e_source_to_string (source, NULL);
2009                 g_variant_builder_add (&builder, "{ss}", uid, source_data);
2010                 g_free (source_data);
2011         }
2012
2013         variant = g_variant_builder_end (&builder);
2014
2015         /* This function sinks the floating GVariant reference. */
2016         success = e_dbus_source_manager_call_create_sources_sync (
2017                 registry->priv->dbus_source_manager,
2018                 variant, cancellable, error);
2019
2020         g_variant_builder_clear (&builder);
2021
2022         return success;
2023 }
2024
2025 /**
2026  * e_source_registry_create_sources:
2027  * @registry: an #ESourceRegistry
2028  * @list_of_sources: (element-type ESource): a list of #ESource instances with
2029  * no #GDBusObject
2030  * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2031  * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2032  *            is satisfied
2033  * @user_data: (closure): data to pass to the callback function
2034  *
2035  * Asynchronously requests the D-Bus service create new key files for each
2036  * #ESource in @list_of_sources.  Each list element must be a scratch
2037  * #ESource with no #GDBusObject.
2038  *
2039  * When the operation is finished, @callback will be called.  You can then
2040  * call e_source_registry_create_sources_finish() to get the result of the
2041  * operation.
2042  *
2043  * Since: 3.6
2044  **/
2045 void
2046 e_source_registry_create_sources (ESourceRegistry *registry,
2047                                   GList *list_of_sources,
2048                                   GCancellable *cancellable,
2049                                   GAsyncReadyCallback callback,
2050                                   gpointer user_data)
2051 {
2052         GSimpleAsyncResult *simple;
2053         AsyncContext *async_context;
2054         GList *link;
2055
2056         g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2057
2058         /* Verify the list elements are all ESources. */
2059         for (link = list_of_sources; link != NULL; link = g_list_next (link))
2060                 g_return_if_fail (E_IS_SOURCE (link->data));
2061
2062         async_context = g_slice_new0 (AsyncContext);
2063         async_context->list_of_sources = g_list_copy (list_of_sources);
2064
2065         g_list_foreach (
2066                 async_context->list_of_sources,
2067                 (GFunc) g_object_ref, NULL);
2068
2069         simple = g_simple_async_result_new (
2070                 G_OBJECT (registry), callback, user_data,
2071                 e_source_registry_create_sources);
2072
2073         g_simple_async_result_set_check_cancellable (simple, cancellable);
2074
2075         g_simple_async_result_set_op_res_gpointer (
2076                 simple, async_context, (GDestroyNotify) async_context_free);
2077
2078         g_simple_async_result_run_in_thread (
2079                 simple, source_registry_create_sources_thread,
2080                 G_PRIORITY_DEFAULT, cancellable);
2081
2082         g_object_unref (simple);
2083 }
2084
2085 /**
2086  * e_source_registry_create_sources_finish:
2087  * @registry: an #ESourceRegistry
2088  * @result: a #GAsyncResult
2089  * @error: return location for a #GError, or %NULL
2090  *
2091  * Finishes the operation started with e_source_registry_create_sources().
2092  *
2093  * If an error occurred, the function will set @error and return %FALSE.
2094  *
2095  * Returns: %TRUE on success, %FALSE on failure
2096  *
2097  * Since: 3.6
2098  **/
2099 gboolean
2100 e_source_registry_create_sources_finish (ESourceRegistry *registry,
2101                                          GAsyncResult *result,
2102                                          GError **error)
2103 {
2104         GSimpleAsyncResult *simple;
2105
2106         g_return_val_if_fail (
2107                 g_simple_async_result_is_valid (
2108                 result, G_OBJECT (registry),
2109                 e_source_registry_create_sources), FALSE);
2110
2111         simple = G_SIMPLE_ASYNC_RESULT (result);
2112
2113         /* Assume success unless a GError is set. */
2114         return !g_simple_async_result_propagate_error (simple, error);
2115 }
2116
2117 /**
2118  * e_source_registry_ref_source:
2119  * @registry: an #ESourceRegistry
2120  * @uid: a unique identifier string
2121  *
2122  * Looks up an #ESource in @registry by its unique identifier string.
2123  *
2124  * The returned #ESource is referenced for thread-safety and must be
2125  * unreferenced with g_object_unref() when finished with it.
2126  *
2127  * Returns: (transfer full): an #ESource, or %NULL if no match was found
2128  *
2129  * Since: 3.6
2130  **/
2131 ESource *
2132 e_source_registry_ref_source (ESourceRegistry *registry,
2133                               const gchar *uid)
2134 {
2135         g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2136         g_return_val_if_fail (uid != NULL, NULL);
2137
2138         return source_registry_sources_lookup (registry, uid);
2139 }
2140
2141 /**
2142  * e_source_registry_list_sources:
2143  * @registry: an #ESourceRegistry
2144  * @extension_name: (allow-none): an extension name, or %NULL
2145  *
2146  * Returns a list of registered sources, sorted by display name.  If
2147  * @extension_name is given, restrict the list to sources having that
2148  * extension name.
2149  *
2150  * The sources returned in the list are referenced for thread-safety.
2151  * They must each be unreferenced with g_object_unref() when finished
2152  * when them.  Free the returned list itself with g_list_free().
2153  *
2154  * An easy way to free the list properly in one step is as follows:
2155  *
2156  * |[
2157  *   g_list_free_full (list, g_object_unref);
2158  * ]|
2159  *
2160  * Returns: (element-type ESource) (transfer full): a sorted list of sources
2161  *
2162  * Since: 3.6
2163  **/
2164 GList *
2165 e_source_registry_list_sources (ESourceRegistry *registry,
2166                                 const gchar *extension_name)
2167 {
2168         GList *list, *link;
2169         GQueue trash = G_QUEUE_INIT;
2170
2171         g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2172
2173         list = g_list_sort (
2174                 source_registry_sources_get_values (registry),
2175                 (GCompareFunc) e_source_compare_by_display_name);
2176
2177         if (extension_name == NULL)
2178                 return list;
2179
2180         for (link = list; link != NULL; link = g_list_next (link)) {
2181                 ESource *source = E_SOURCE (link->data);
2182
2183                 if (!e_source_has_extension (source, extension_name)) {
2184                         g_queue_push_tail (&trash, link);
2185                         g_object_unref (source);
2186                 }
2187         }
2188
2189         /* We do want pop_head() here, not pop_head_link(). */
2190         while ((link = g_queue_pop_head (&trash)) != NULL)
2191                 list = g_list_delete_link (list, link);
2192
2193         return list;
2194 }
2195
2196 /**
2197  * e_source_registry_find_extension:
2198  * @registry: an #ESourceRegistry
2199  * @source: an #ESource
2200  * @extension_name: the extension name to find
2201  *
2202  * Examines @source and its ancestors and returns the "deepest" #ESource
2203  * having an #ESourceExtension with the given @extension_name.  If neither
2204  * @source nor any of its ancestors have such an extension, the function
2205  * returns %NULL.
2206  *
2207  * This function is useful in cases when an #ESourceExtension is meant to
2208  * apply to both the #ESource it belongs to and the #ESource's descendants.
2209  *
2210  * A common example is the #ESourceCollection extension, where descendants
2211  * of an #ESource having an #ESourceCollection extension are implied to be
2212  * members of that collection.  In that example, this function can be used
2213  * to test whether @source is a member of a collection.
2214  *
2215  * The returned #ESource is referenced for thread-safety and must be
2216  * unreferenced with g_object_unref() when finished with it.
2217  *
2218  * Note the function returns the #ESource containing the #ESourceExtension
2219  * instead of the #ESourceExtension itself because extension instances are
2220  * not to be referenced directly (see e_source_get_extension()).
2221  *
2222  * Returns: (transfer full): an #ESource, or %NULL if no match was found
2223  *
2224  * Since: 3.6
2225  **/
2226 ESource *
2227 e_source_registry_find_extension (ESourceRegistry *registry,
2228                                   ESource *source,
2229                                   const gchar *extension_name)
2230 {
2231         g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2232         g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2233         g_return_val_if_fail (extension_name != NULL, NULL);
2234
2235         g_object_ref (source);
2236
2237         while (!e_source_has_extension (source, extension_name)) {
2238                 gchar *uid;
2239
2240                 uid = e_source_dup_parent (source);
2241
2242                 g_object_unref (source);
2243                 source = NULL;
2244
2245                 if (uid != NULL) {
2246                         source = e_source_registry_ref_source (registry, uid);
2247                         g_free (uid);
2248                 }
2249
2250                 if (source == NULL)
2251                         break;
2252         }
2253
2254         return source;
2255 }
2256
2257 /* Helper for e_source_registry_build_display_tree() */
2258 static gint
2259 source_registry_compare_nodes (GNode *node_a,
2260                                GNode *node_b)
2261 {
2262         ESource *source_a = E_SOURCE (node_a->data);
2263         ESource *source_b = E_SOURCE (node_b->data);
2264         const gchar *uid_a, *uid_b;
2265
2266         uid_a = e_source_get_uid (source_a);
2267         uid_b = e_source_get_uid (source_b);
2268
2269         /* Sanity check, with runtime warnings. */
2270         if (uid_a == NULL) {
2271                 g_warn_if_reached ();
2272                 uid_a = "";
2273         }
2274         if (uid_b == NULL) {
2275                 g_warn_if_reached ();
2276                 uid_b = "";
2277         }
2278
2279         /* The built-in "local-stub" source comes first at depth 1. */
2280
2281         if (g_strcmp0 (uid_a, "local-stub") == 0)
2282                 return -1;
2283
2284         if (g_strcmp0 (uid_b, "local-stub") == 0)
2285                 return 1;
2286
2287         /* The built-in "system-*" sources come first at depth 2. */
2288
2289         if (g_str_has_prefix (uid_a, "system-"))
2290                 return -1;
2291
2292         if (g_str_has_prefix (uid_b, "system-"))
2293                 return 1;
2294
2295         return e_source_compare_by_display_name (source_a, source_b);
2296 }
2297
2298 /* Helper for e_source_registry_build_display_tree() */
2299 static gboolean
2300 source_registry_prune_nodes (GNode *node,
2301                              const gchar *extension_name)
2302 {
2303         GQueue queue = G_QUEUE_INIT;
2304         GNode *child_node;
2305
2306         /* Unlink all the child nodes and place them in a queue. */
2307         while ((child_node = g_node_first_child (node)) != NULL) {
2308                 g_node_unlink (child_node);
2309                 g_queue_push_tail (&queue, child_node);
2310         }
2311
2312         /* Sort the queue by source name. */
2313         g_queue_sort (
2314                 &queue, (GCompareDataFunc)
2315                 source_registry_compare_nodes, NULL);
2316
2317         /* Pop nodes off the head of the queue until the queue is empty.
2318          * If the node has either its own children or the given extension
2319          * name, put it back under the parent node (preserving the sorted
2320          * order).  Otherwise delete the node and its descendants. */
2321         while ((child_node = g_queue_pop_head (&queue)) != NULL) {
2322                 ESource *child = E_SOURCE (child_node->data);
2323                 gboolean append_child_node = FALSE;
2324
2325                 if (extension_name == NULL)
2326                         append_child_node = e_source_get_enabled (child);
2327
2328                 else if (e_source_has_extension (child, extension_name))
2329                         append_child_node = e_source_get_enabled (child);
2330
2331                 else if (g_node_first_child (child_node) != NULL)
2332                         append_child_node = e_source_get_enabled (child);
2333
2334                 if (append_child_node)
2335                         g_node_append (node, child_node);
2336                 else
2337                         e_source_registry_free_display_tree (child_node);
2338         }
2339
2340         return FALSE;
2341 }
2342
2343 /**
2344  * e_source_registry_build_display_tree:
2345  * @registry: an #ESourceRegistry
2346  * @extension_name: (allow-none): an extension name, or %NULL
2347  *
2348  * Returns a single #GNode tree of registered sources that can be used to
2349  * populate a #GtkTreeModel.  (The root #GNode is just an empty placeholder.)
2350  *
2351  * Similar to e_source_registry_list_sources(), an @extension_name can be
2352  * given to restrict the tree to sources having that extension name.  Parents
2353  * of matched sources are included in the tree regardless of whether they have
2354  * an extension named @extension_name.
2355  *
2356  * Disabled leaf nodes are automatically excluded from the #GNode tree.
2357  *
2358  * The sources returned in the tree are referenced for thread-safety.
2359  * They must each be unreferenced with g_object_unref() when finished
2360  * with them.  Free the returned tree itself with g_node_destroy().
2361  * For convenience, e_source_registry_free_display_tree() does all
2362  * that in one step.
2363  *
2364  * Returns: (element-type ESource) (transfer full): a tree of sources,
2365  *          arranged for display
2366  *
2367  * Since: 3.6
2368  **/
2369 GNode *
2370 e_source_registry_build_display_tree (ESourceRegistry *registry,
2371                                       const gchar *extension_name)
2372 {
2373         GNode *root;
2374
2375         g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2376
2377         /* Assemble all data sources into a tree. */
2378         root = source_registry_sources_build_tree (registry);
2379
2380         /* Prune unwanted nodes from the copied source trees.
2381          * This must be done in "post" order (children first)
2382          * since it reorders and deletes child nodes. */
2383         g_node_traverse (
2384                 root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
2385                 (GNodeTraverseFunc) source_registry_prune_nodes,
2386                 (gpointer) extension_name);
2387
2388         return root;
2389 }
2390
2391 /* Helper for e_source_registry_free_display_tree() */
2392 static void
2393 source_registry_unref_nodes (GNode *node)
2394 {
2395         while (node != NULL) {
2396                 if (node->children != NULL)
2397                         source_registry_unref_nodes (node->children);
2398                 if (node->data != NULL)
2399                         g_object_unref (node->data);
2400                 node = node->next;
2401         }
2402 }
2403
2404 /**
2405  * e_source_registry_free_display_tree:
2406  * @display_tree: a tree of sources, arranged for display
2407  *
2408  * Convenience function to free a #GNode tree of registered
2409  * sources created by e_source_registry_build_display_tree().
2410  *
2411  * Since: 3.6
2412  **/
2413 void
2414 e_source_registry_free_display_tree (GNode *display_tree)
2415 {
2416         g_return_if_fail (display_tree != NULL);
2417
2418         /* XXX This would be easier if GLib had something like
2419          *     g_node_destroy_full() which took a GDestroyNotify.
2420          *     Then the tree would not have to be traversed twice. */
2421
2422         source_registry_unref_nodes (display_tree);
2423         g_node_destroy (display_tree);
2424 }
2425
2426 /* Helper for e_source_registry_debug_dump() */
2427 static gboolean
2428 source_registry_debug_dump_cb (GNode *node)
2429 {
2430         guint ii, depth;
2431
2432         /* Root node is an empty placeholder. */
2433         if (G_NODE_IS_ROOT (node))
2434                 return FALSE;
2435
2436         depth = g_node_depth (node);
2437         for (ii = 2; ii < depth; ii++)
2438                 g_print ("    ");
2439
2440         if (E_IS_SOURCE (node->data)) {
2441                 ESource *source = E_SOURCE (node->data);
2442                 g_print ("\"%s\" ", e_source_get_display_name (source));
2443                 g_print ("(%s)", e_source_get_uid (source));
2444         }
2445
2446         g_print ("\n");
2447
2448         return FALSE;
2449 }
2450
2451 /**
2452  * e_source_registry_debug_dump:
2453  * @registry: an #ESourceRegistry
2454  * @extension_name: (allow-none): an extension name, or %NULL
2455  *
2456  * Handy debugging function that uses e_source_registry_build_display_tree()
2457  * to print a tree of registered sources to standard output.
2458  *
2459  * Since: 3.6
2460  **/
2461 void
2462 e_source_registry_debug_dump (ESourceRegistry *registry,
2463                               const gchar *extension_name)
2464 {
2465         GNode *root;
2466
2467         g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2468
2469         root = e_source_registry_build_display_tree (registry, extension_name);
2470
2471         g_node_traverse (
2472                 root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
2473                 (GNodeTraverseFunc) source_registry_debug_dump_cb, NULL);
2474
2475         e_source_registry_free_display_tree (root);
2476 }
2477
2478 /**
2479  * e_source_registry_ref_builtin_address_book:
2480  * @registry: an #ESourceRegistry
2481  *
2482  * Returns the built-in address book #ESource.
2483  *
2484  * This #ESource is always present and makes for a safe fallback.
2485  *
2486  * The returned #ESource is referenced for thread-safety and must be
2487  * unreferenced with g_object_unref() when finished with it.
2488  *
2489  * Returns: (transfer full): the built-in address book #ESource
2490  *
2491  * Since: 3.6
2492  **/
2493 ESource *
2494 e_source_registry_ref_builtin_address_book (ESourceRegistry *registry)
2495 {
2496         ESource *source;
2497         const gchar *uid;
2498
2499         g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2500
2501         uid = E_SOURCE_BUILTIN_ADDRESS_BOOK_UID;
2502         source = e_source_registry_ref_source (registry, uid);
2503         g_return_val_if_fail (source != NULL, NULL);
2504
2505         return source;
2506 }
2507
2508 /**
2509  * e_source_registry_ref_default_address_book:
2510  * @registry: an #ESourceRegistry
2511  *
2512  * Returns the #ESource most recently passed to
2513  * e_source_registry_set_default_address_book() either in this session
2514  * or a previous session, or else falls back to the built-in address book.
2515  *
2516  * The returned #ESource is referenced for thread-safety and must be
2517  * unreferenced with g_object_unref() when finished with it.
2518  *
2519  * Returns: (transfer full): the default address book #ESource
2520  *
2521  * Since: 3.6
2522  **/
2523 ESource *
2524 e_source_registry_ref_default_address_book (ESourceRegistry *registry)
2525 {
2526         const gchar *key;
2527         ESource *source;
2528         gchar *uid;
2529
2530         g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2531
2532         key = E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY;
2533         uid = g_settings_get_string (registry->priv->settings, key);
2534         source = e_source_registry_ref_source (registry, uid);
2535         g_free (uid);
2536
2537         /* The built-in source is always present. */
2538         if (source == NULL)
2539                 source = e_source_registry_ref_builtin_address_book (registry);
2540
2541         g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2542
2543         return source;
2544 }
2545
2546 /**
2547  * e_source_registry_set_default_address_book:
2548  * @registry: an #ESourceRegistry
2549  * @default_source: (allow-none): an address book #ESource, or %NULL
2550  *
2551  * Sets @default_source as the default address book.  If @default_source
2552  * is %NULL, the default address book is reset to the built-in address book.
2553  * This setting will persist across sessions until changed.
2554  *
2555  * Since: 3.6
2556  **/
2557 void
2558 e_source_registry_set_default_address_book (ESourceRegistry *registry,
2559                                             ESource *default_source)
2560 {
2561         const gchar *key;
2562         const gchar *uid;
2563
2564         g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2565
2566         if (default_source != NULL) {
2567                 g_return_if_fail (E_IS_SOURCE (default_source));
2568                 uid = e_source_get_uid (default_source);
2569         } else {
2570                 uid = E_SOURCE_BUILTIN_ADDRESS_BOOK_UID;
2571         }
2572
2573         key = E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY;
2574         g_settings_set_string (registry->priv->settings, key, uid);
2575
2576         /* The GSettings::changed signal will trigger a "notify" signal
2577          * from the registry, so no need to call g_object_notify() here. */
2578 }
2579
2580 /**
2581  * e_source_registry_ref_builtin_calendar:
2582  * @registry: an #ESourceRegistry
2583  *
2584  * Returns the built-in calendar #ESource.
2585  *
2586  * This #ESource is always present and makes for a safe fallback.
2587  *
2588  * The returned #ESource is referenced for thread-safety and must be
2589  * unreferenced with g_object_unref() when finished with it.
2590  *
2591  * Returns: (transfer full): the built-in calendar #ESource
2592  *
2593  * Since: 3.6
2594  **/
2595 ESource *
2596 e_source_registry_ref_builtin_calendar (ESourceRegistry *registry)
2597 {
2598         ESource *source;
2599         const gchar *uid;
2600
2601         g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2602
2603         uid = E_SOURCE_BUILTIN_CALENDAR_UID;
2604         source = e_source_registry_ref_source (registry, uid);
2605         g_return_val_if_fail (source != NULL, NULL);
2606
2607         return source;
2608 }
2609
2610 /**
2611  * e_source_registry_ref_default_calendar:
2612  * @registry: an #ESourceRegistry
2613  *
2614  * Returns the #ESource most recently passed to
2615  * e_source_registry_set_default_calendar() either in this session
2616  * or a previous session, or else falls back to the built-in calendar.
2617  *
2618  * The returned #ESource is referenced for thread-safety and must be
2619  * unreferenced with g_object_unref() when finished with it.
2620  *
2621  * Returns: (transfer full): the default calendar #ESource
2622  *
2623  * Since: 3.6
2624  **/
2625 ESource *
2626 e_source_registry_ref_default_calendar (ESourceRegistry *registry)
2627 {
2628         const gchar *key;
2629         ESource *source;
2630         gchar *uid;
2631
2632         g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2633
2634         key = E_SETTINGS_DEFAULT_CALENDAR_KEY;
2635         uid = g_settings_get_string (registry->priv->settings, key);
2636         source = e_source_registry_ref_source (registry, uid);
2637         g_free (uid);
2638
2639         /* The built-in source is always present. */
2640         if (source == NULL)
2641                 source = e_source_registry_ref_builtin_calendar (registry);
2642
2643         g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2644
2645         return source;
2646 }
2647
2648 /**
2649  * e_source_registry_set_default_calendar:
2650  * @registry: an #ESourceRegistry
2651  * @default_source: (allow-none): a calendar #ESource, or %NULL
2652  *
2653  * Sets @default_source as the default calendar.  If @default_source
2654  * is %NULL, the default calendar is reset to the built-in calendar.
2655  * This setting will persist across sessions until changed.
2656  *
2657  * Since: 3.6
2658  **/
2659 void
2660 e_source_registry_set_default_calendar (ESourceRegistry *registry,
2661                                         ESource *default_source)
2662 {
2663         const gchar *key;
2664         const gchar *uid;
2665
2666         g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2667
2668         if (default_source != NULL) {
2669                 g_return_if_fail (E_IS_SOURCE (default_source));
2670                 uid = e_source_get_uid (default_source);
2671         } else {
2672                 uid = E_SOURCE_BUILTIN_CALENDAR_UID;
2673         }
2674
2675         key = E_SETTINGS_DEFAULT_CALENDAR_KEY;
2676         g_settings_set_string (registry->priv->settings, key, uid);
2677
2678         /* The GSettings::changed signal will trigger a "notify" signal
2679          * from the registry, so no need to call g_object_notify() here. */
2680 }
2681
2682 /**
2683  * e_source_registry_ref_builtin_mail_account:
2684  * @registry: an #ESourceRegistry
2685  *
2686  * Returns the built-in mail account #ESource.
2687  *
2688  * This #ESource is always present and makes for a safe fallback.
2689  *
2690  * The returned #ESource is referenced for thread-safety and must be
2691  * unreferenced with g_object_unref() when finished with it.
2692  *
2693  * Returns: (transfer full): the built-in mail account #ESource
2694  *
2695  * Since: 3.6
2696  **/
2697 ESource *
2698 e_source_registry_ref_builtin_mail_account (ESourceRegistry *registry)
2699 {
2700         ESource *source;
2701         const gchar *uid;
2702
2703         g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2704
2705         uid = E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID;
2706         source = e_source_registry_ref_source (registry, uid);
2707         g_return_val_if_fail (source != NULL, NULL);
2708
2709         return source;
2710 }
2711
2712 /**
2713  * e_source_registry_ref_default_mail_account:
2714  * @registry: an #ESourceRegistry
2715  *
2716  * Returns the #ESource most recently passed to
2717  * e_source_registry_set_default_mail_account() either in this session
2718  * or a previous session, or else falls back to the built-in mail account.
2719  *
2720  * The returned #ESource is referenced for thread-safety and must be
2721  * unreferenced with g_object_unref() when finished with it.
2722  *
2723  * Returns: (transfer full): the default mail account #ESource
2724  *
2725  * Since: 3.6
2726  **/
2727 ESource *
2728 e_source_registry_ref_default_mail_account (ESourceRegistry *registry)
2729 {
2730         const gchar *key;
2731         ESource *source;
2732         gchar *uid;
2733
2734         g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2735
2736         key = E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY;
2737         uid = g_settings_get_string (registry->priv->settings, key);
2738         source = e_source_registry_ref_source (registry, uid);
2739         g_free (uid);
2740
2741         /* The built-in source is always present. */
2742         if (source == NULL)
2743                 source = e_source_registry_ref_builtin_mail_account (registry);
2744
2745         g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2746
2747         return source;
2748 }
2749
2750 /**
2751  * e_source_registry_set_default_mail_account:
2752  * @registry: an #ESourceRegistry
2753  * @default_source: (allow-none): a mail account #ESource, or %NULL
2754  *
2755  * Sets @default_source as the default mail account.  If @default_source
2756  * is %NULL, the default mail account is reset to the built-in mail account.
2757  * This setting will persist across sessions until changed.
2758  *
2759  * Since: 3.6
2760  **/
2761 void
2762 e_source_registry_set_default_mail_account (ESourceRegistry *registry,
2763                                             ESource *default_source)
2764 {
2765         const gchar *key;
2766         const gchar *uid;
2767
2768         g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2769
2770         if (default_source != NULL) {
2771                 g_return_if_fail (E_IS_SOURCE (default_source));
2772                 uid = e_source_get_uid (default_source);
2773         } else {
2774                 uid = E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID;
2775         }
2776
2777         key = E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY;
2778         g_settings_set_string (registry->priv->settings, key, uid);
2779
2780         /* The GSettings::changed signal will trigger a "notify" signal
2781          * from the registry, so no need to call g_object_notify() here. */
2782 }
2783
2784 /* Helper for e_source_registry_ref_default_mail_identity() */
2785 static ESource *
2786 source_registry_ref_any_mail_identity (ESourceRegistry *registry)
2787 {
2788         ESource *source;
2789         GList *list, *link;
2790         const gchar *extension_name;
2791         gchar *uid = NULL;
2792
2793         /* First fallback: Return the mail identity named
2794          *                 by the default mail account. */
2795
2796         source = e_source_registry_ref_default_mail_account (registry);
2797
2798         /* This should never be NULL, but just to be safe. */
2799         if (source != NULL) {
2800                 ESourceMailAccount *extension;
2801
2802                 extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
2803                 extension = e_source_get_extension (source, extension_name);
2804                 uid = e_source_mail_account_dup_identity_uid (extension);
2805
2806                 g_object_unref (source);
2807                 source = NULL;
2808         }
2809
2810         if (uid != NULL) {
2811                 source = e_source_registry_ref_source (registry, uid);
2812                 g_free (uid);
2813         }
2814
2815         if (source != NULL)
2816                 return source;
2817
2818         /* Second fallback: Pick any available mail identity,
2819          *                  preferring enabled identities. */
2820
2821         extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
2822         list = e_source_registry_list_sources (registry, extension_name);
2823
2824         for (link = list; link != NULL; link = g_list_next (link)) {
2825                 ESource *candidate = E_SOURCE (link->data);
2826
2827                 if (e_source_get_enabled (candidate)) {
2828                         source = g_object_ref (candidate);
2829                         break;
2830                 }
2831         }
2832
2833         if (source == NULL && list != NULL)
2834                 source = g_object_ref (list->data);
2835
2836         g_list_free_full (list, (GDestroyNotify) g_object_unref);
2837
2838         return source;
2839 }
2840
2841 /**
2842  * e_source_registry_ref_default_mail_identity:
2843  * @registry: an #ESourceRegistry
2844  *
2845  * Returns the #ESource most recently passed to
2846  * e_source_registry_set_default_mail_identity() either in this session
2847  * or a previous session, or else falls back to the mail identity named
2848  * by the default mail account.  If even that fails it returns any mail
2849  * identity from @registry, or %NULL if there are none.
2850  *
2851  * The returned #ESource is referenced for thread-safety and must be
2852  * unreferenced with g_object_unref() when finished with it.
2853  *
2854  * Returns: (transfer full): the default mail identity #ESource, or %NULL
2855  *
2856  * Since: 3.6
2857  **/
2858 ESource *
2859 e_source_registry_ref_default_mail_identity (ESourceRegistry *registry)
2860 {
2861         const gchar *key;
2862         ESource *source;
2863         gchar *uid;
2864
2865         g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2866
2867         key = E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY;
2868         uid = g_settings_get_string (registry->priv->settings, key);
2869         source = e_source_registry_ref_source (registry, uid);
2870         g_free (uid);
2871
2872         if (source == NULL)
2873                 source = source_registry_ref_any_mail_identity (registry);
2874
2875         return source;
2876 }
2877
2878 /**
2879  * e_source_registry_set_default_mail_identity:
2880  * @registry: an #ESourceRegistry
2881  * @default_source: (allow-none): a mail identity #ESource, or %NULL
2882  *
2883  * Sets @default_source as the default mail identity.  If @default_source
2884  * is %NULL, the next request for the default mail identity will use the
2885  * fallbacks described in e_source_registry_get_default_mail_identity().
2886  *
2887  * Since: 3.6
2888  **/
2889 void
2890 e_source_registry_set_default_mail_identity (ESourceRegistry *registry,
2891                                              ESource *default_source)
2892 {
2893         const gchar *key;
2894         const gchar *uid;
2895
2896         g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2897
2898         if (default_source != NULL) {
2899                 g_return_if_fail (E_IS_SOURCE (default_source));
2900                 uid = e_source_get_uid (default_source);
2901         } else {
2902                 uid = "";  /* no built-in mail identity */
2903         }
2904
2905         key = E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY;
2906         g_settings_set_string (registry->priv->settings, key, uid);
2907
2908         /* The GSettings::changed signal will trigger a "notify" signal
2909          * from the registry, so no need to call g_object_notify() here. */
2910 }
2911
2912 /**
2913  * e_source_registry_ref_builtin_memo_list:
2914  * @registry: an #ESourceRegistry
2915  *
2916  * Returns the built-in memo list #ESource.
2917  *
2918  * This #ESource is always present and makes for a safe fallback.
2919  *
2920  * The returned #ESource is referenced for thread-safety and must be
2921  * unreferenced with g_object_unref() when finished with it.
2922  *
2923  * Returns: (transfer full): the built-in memo list #ESource
2924  *
2925  * Since: 3.6
2926  **/
2927 ESource *
2928 e_source_registry_ref_builtin_memo_list (ESourceRegistry *registry)
2929 {
2930         ESource *source;
2931         const gchar *uid;
2932
2933         g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2934
2935         uid = E_SOURCE_BUILTIN_MEMO_LIST_UID;
2936         source = e_source_registry_ref_source (registry, uid);
2937         g_return_val_if_fail (source != NULL, NULL);
2938
2939         return source;
2940 }
2941
2942 /**
2943  * e_source_registry_ref_default_memo_list:
2944  * @registry: an #ESourceRegistry
2945  *
2946  * Returns the #ESource most recently passed to
2947  * e_source_registry_set_default_memo_list() either in this session
2948  * or a previous session, or else falls back to the built-in memo list.
2949  *
2950  * The returned #ESource is referenced for thread-safety and must be
2951  * unreferenced with g_object_unref() when finished with it.
2952  *
2953  * Returns: (transfer full): the default memo list #ESource
2954  *
2955  * Since: 3.6
2956  **/
2957 ESource *
2958 e_source_registry_ref_default_memo_list (ESourceRegistry *registry)
2959 {
2960         const gchar *key;
2961         ESource *source;
2962         gchar *uid;
2963
2964         g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2965
2966         key = E_SETTINGS_DEFAULT_MEMO_LIST_KEY;
2967         uid = g_settings_get_string (registry->priv->settings, key);
2968         source = e_source_registry_ref_source (registry, uid);
2969         g_free (uid);
2970
2971         /* The built-in source is always present. */
2972         if (source == NULL)
2973                 source = e_source_registry_ref_builtin_memo_list (registry);
2974
2975         g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2976
2977         return source;
2978 }
2979
2980 /**
2981  * e_source_registry_set_default_memo_list:
2982  * @registry: an #ESourceRegistry
2983  * @default_source: (allow-none): a memo list #ESource, or %NULL
2984  *
2985  * Sets @default_source as the default memo list.  If @default_source
2986  * is %NULL, the default memo list is reset to the built-in memo list.
2987  * This setting will persist across sessions until changed.
2988  *
2989  * Since: 3.6
2990  **/
2991 void
2992 e_source_registry_set_default_memo_list (ESourceRegistry *registry,
2993                                          ESource *default_source)
2994 {
2995         const gchar *key;
2996         const gchar *uid;
2997
2998         g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2999
3000         if (default_source != NULL) {
3001                 g_return_if_fail (E_IS_SOURCE (default_source));
3002                 uid = e_source_get_uid (default_source);
3003         } else {
3004                 uid = E_SOURCE_BUILTIN_MEMO_LIST_UID;
3005         }
3006
3007         key = E_SETTINGS_DEFAULT_MEMO_LIST_KEY;
3008         g_settings_set_string (registry->priv->settings, key, uid);
3009
3010         /* The GSettings::changed signal will trigger a "notify" signal
3011          * from the registry, so no need to call g_object_notify() here. */
3012 }
3013
3014 /**
3015  * e_source_registry_ref_builtin_task_list:
3016  * @registry: an #ESourceRegistry
3017  *
3018  * Returns the built-in task list #ESource.
3019  *
3020  * This #ESource is always present and makes for a safe fallback.
3021  *
3022  * The returned #ESource is referenced for thread-safety and must be
3023  * unreferenced with g_object_unref() when finished with it.
3024  *
3025  * Returns: (transfer full): the built-in task list #ESource
3026  *
3027  * Since: 3.6
3028  **/
3029 ESource *
3030 e_source_registry_ref_builtin_task_list (ESourceRegistry *registry)
3031 {
3032         ESource *source;
3033         const gchar *uid;
3034
3035         g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3036
3037         uid = E_SOURCE_BUILTIN_TASK_LIST_UID;
3038         source = e_source_registry_ref_source (registry, uid);
3039         g_return_val_if_fail (source != NULL, NULL);
3040
3041         return source;
3042 }
3043
3044 /**
3045  * e_source_registry_ref_default_task_list:
3046  * @registry: an #ESourceRegistry
3047  *
3048  * Returns the #ESource most recently passed to
3049  * e_source_registry_set_default_task_list() either in this session
3050  * or a previous session, or else falls back to the built-in task list.
3051  *
3052  * The returned #ESource is referenced for thread-safety and must be
3053  * unreferenced with g_object_unref() when finished with it.
3054  *
3055  * Returns: (transfer full): the default task list #ESource
3056  *
3057  * Since: 3.6
3058  **/
3059 ESource *
3060 e_source_registry_ref_default_task_list (ESourceRegistry *registry)
3061 {
3062         const gchar *key;
3063         ESource *source;
3064         gchar *uid;
3065
3066         g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3067
3068         key = E_SETTINGS_DEFAULT_TASK_LIST_KEY;
3069         uid = g_settings_get_string (registry->priv->settings, key);
3070         source = e_source_registry_ref_source (registry, uid);
3071         g_free (uid);
3072
3073         /* The built-in source is always present. */
3074         if (source == NULL)
3075                 source = e_source_registry_ref_builtin_task_list (registry);
3076
3077         g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3078
3079         return source;
3080 }
3081
3082 /**
3083  * e_source_registry_set_default_task_list:
3084  * @registry: an #ESourceRegistry
3085  * @default_source: (allow-none): a task list #ESource, or %NULL
3086  *
3087  * Sets @default_source as the default task list.  If @default_source
3088  * is %NULL, the default task list is reset to the built-in task list.
3089  * This setting will persist across sessions until changed.
3090  *
3091  * Since: 3.6
3092  **/
3093 void
3094 e_source_registry_set_default_task_list (ESourceRegistry *registry,
3095                                          ESource *default_source)
3096 {
3097         const gchar *key;
3098         const gchar *uid;
3099
3100         g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3101
3102         if (default_source != NULL) {
3103                 g_return_if_fail (E_IS_SOURCE (default_source));
3104                 uid = e_source_get_uid (default_source);
3105         } else {
3106                 uid = E_SOURCE_BUILTIN_TASK_LIST_UID;
3107         }
3108
3109         key = E_SETTINGS_DEFAULT_TASK_LIST_KEY;
3110         g_settings_set_string (registry->priv->settings, key, uid);
3111
3112         /* The GSettings::changed signal will trigger a "notify" signal
3113          * from the registry, so no need to call g_object_notify() here. */
3114 }
3115
3116 /**
3117  * e_source_registry_ref_default_for_extension_name:
3118  * @registry: an #ESourceRegistry
3119  * @extension_name: an extension_name
3120  *
3121  * This is a convenience function to return a default #ESource based on
3122  * @extension_name.  This only works with a subset of extension names.
3123  *
3124  * If @extension_name is #E_SOURCE_EXTENSION_ADDRESS_BOOK, the function
3125  * returns the current default address book, or else falls back to the
3126  * built-in address book.
3127  *
3128  * If @extension_name is #E_SOURCE_EXTENSION_CALENDAR, the function returns
3129  * the current default calendar, or else falls back to the built-in calendar.
3130  *
3131  * If @extension_name is #E_SOURCE_EXTENSION_MAIL_ACCOUNT, the function
3132  * returns the current default mail account, or else falls back to the
3133  * built-in mail account.
3134  *
3135  * If @extension_name is #E_SOURCE_EXTENSION_MAIL_IDENTITY, the function
3136  * returns the current default mail identity, or else falls back to the
3137  * mail identity named by the current default mail account.
3138  *
3139  * If @extension_name is #E_SOURCE_EXTENSION_MEMO_LIST, the function returns
3140  * the current default memo list, or else falls back to the built-in memo list.
3141  *
3142  * If @extension_name is #E_SOURCE_EXTENSION_TASK_LIST, the function returns
3143  * the current default task list, or else falls back to the built-in task list.
3144  *
3145  * For all other values of @extension_name, the function returns %NULL.
3146  *
3147  * The returned #ESource is referenced for thread-safety and must be
3148  * unreferenced with g_object_unref() when finished with it.
3149  *
3150  * Returns: (transfer full): the default #ESource based on @extension_name
3151  *
3152  * Since: 3.6
3153  **/
3154 ESource *
3155 e_source_registry_ref_default_for_extension_name (ESourceRegistry *registry,
3156                                                   const gchar *extension_name)
3157 {
3158         g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3159         g_return_val_if_fail (extension_name != NULL, NULL);
3160
3161         if (strcmp (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK) == 0)
3162                 return e_source_registry_ref_default_address_book (registry);
3163
3164         if (strcmp (extension_name, E_SOURCE_EXTENSION_CALENDAR) == 0)
3165                 return e_source_registry_ref_default_calendar (registry);
3166
3167         if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_ACCOUNT) == 0)
3168                 return e_source_registry_ref_default_mail_account (registry);
3169
3170         if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_IDENTITY) == 0)
3171                 return e_source_registry_ref_default_mail_identity (registry);
3172
3173         if (strcmp (extension_name, E_SOURCE_EXTENSION_MEMO_LIST) == 0)
3174                 return e_source_registry_ref_default_memo_list (registry);
3175
3176         if (strcmp (extension_name, E_SOURCE_EXTENSION_TASK_LIST) == 0)
3177                 return e_source_registry_ref_default_task_list (registry);
3178
3179         return NULL;
3180 }
3181
3182 /**
3183  * e_source_registry_set_default_for_extension_name:
3184  * @registry: an #ESourceRegistry
3185  * @extension_name: an extension name
3186  * @default_source: (allow-none): an #ESource, or %NULL
3187  *
3188  * This is a convenience function to set a default #ESource based on
3189  * @extension_name.  This only works with a subset of extension names.
3190  *
3191  * If @extension_name is #E_SOURCE_EXTENSION_ADDRESS_BOOK, the function
3192  * sets @default_source as the default address book.  If @default_source
3193  * is %NULL, the default address book is reset to the built-in address book.
3194  *
3195  * If @extension_name is #E_SOURCE_EXTENSION_CALENDAR, the function sets
3196  * @default_source as the default calendar.  If @default_source is %NULL,
3197  * the default calendar is reset to the built-in calendar.
3198  *
3199  * If @extension_name is #E_SOURCE_EXTENSION_MAIL_ACCOUNT, the function
3200  * sets @default_source as the default mail account.  If @default_source
3201  * is %NULL, the default mail account is reset to the built-in mail account.
3202  *
3203  * If @extension_name is #E_SOURCE_EXTENSION_MAIL_IDENTITY, the function
3204  * sets @default_source as the default mail identity.  If @default_source
3205  * is %NULL, the next request for the default mail identity will return
3206  * the mail identity named by the default mail account.
3207  *
3208  * If @extension_name is #E_SOURCE_EXTENSION_MEMO_LIST, the function sets
3209  * @default_source as the default memo list.  If @default_source is %NULL,
3210  * the default memo list is reset to the built-in memo list.
3211  *
3212  * If @extension_name is #E_SOURCE_EXTENSION_TASK_LIST, the function sets
3213  * @default_source as the default task list.  If @default_source is %NULL,
3214  * the default task list is reset to the built-in task list.
3215  *
3216  * For all other values of @extension_name, the function does nothing.
3217  *
3218  * Since: 3.6
3219  **/
3220 void
3221 e_source_registry_set_default_for_extension_name (ESourceRegistry *registry,
3222                                                   const gchar *extension_name,
3223                                                   ESource *default_source)
3224 {
3225         g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3226         g_return_if_fail (extension_name != NULL);
3227
3228         if (strcmp (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK) == 0)
3229                 e_source_registry_set_default_address_book (
3230                         registry, default_source);
3231
3232         if (strcmp (extension_name, E_SOURCE_EXTENSION_CALENDAR) == 0)
3233                 e_source_registry_set_default_calendar (
3234                         registry, default_source);
3235
3236         if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_ACCOUNT) == 0)
3237                 e_source_registry_set_default_mail_account (
3238                         registry, default_source);
3239
3240         if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_IDENTITY) == 0)
3241                 e_source_registry_set_default_mail_identity (
3242                         registry, default_source);
3243
3244         if (strcmp (extension_name, E_SOURCE_EXTENSION_MEMO_LIST) == 0)
3245                 e_source_registry_set_default_memo_list (
3246                         registry, default_source);
3247
3248         if (strcmp (extension_name, E_SOURCE_EXTENSION_TASK_LIST) == 0)
3249                 e_source_registry_set_default_task_list (
3250                         registry, default_source);
3251 }
3252