4 * This library is free software you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, see <http://www.gnu.org/licenses/>.
19 * SECTION: e-source-registry
20 * @include: libedataserver/libedataserver.h
21 * @short_description: A central repository for data sources
23 * The #ESourceRegistry is a global singleton store for all #ESource
24 * instances. It uses file monitors to react to key file creation and
25 * deletion events, either constructing an #ESource instance from the
26 * newly created key file, or removing from the logical #ESource
27 * hierarchy the instance corresponding to the deleted key file.
29 * The #ESourceRegistry can be queried for individual #ESource instances
30 * by their unique identifier string or key file path, for collections of
31 * #ESource instances having a particular extension, or for all available
34 * The #ESourceRegistry API also provides a front-end for the
35 * "org.gnome.Evolution.DefaultSources" #GSettings schema which tracks
36 * which #ESource instances are designated to be the user's default address
37 * book, calendar, memo list and task list for desktop integration.
40 #include "e-source-registry.h"
43 #include <glib/gstdio.h>
44 #include <glib/gi18n-lib.h>
46 /* XXX Yeah, yeah... */
47 #define GCR_API_SUBJECT_TO_CHANGE
49 #include <gcr/gcr-base.h>
51 /* Private D-Bus classes. */
52 #include <e-dbus-source.h>
53 #include <e-dbus-source-manager.h>
55 #include <libedataserver/e-data-server-util.h>
56 #include <libedataserver/e-source-collection.h>
58 /* Needed for the defaults API. */
59 #include <libedataserver/e-source-address-book.h>
60 #include <libedataserver/e-source-calendar.h>
61 #include <libedataserver/e-source-mail-account.h>
62 #include <libedataserver/e-source-mail-identity.h>
64 #include "e-dbus-authenticator.h"
66 #define E_SOURCE_REGISTRY_GET_PRIVATE(obj) \
67 (G_TYPE_INSTANCE_GET_PRIVATE \
68 ((obj), E_TYPE_SOURCE_REGISTRY, ESourceRegistryPrivate))
70 #define DBUS_OBJECT_PATH "/org/gnome/evolution/dataserver/SourceManager"
71 #define GSETTINGS_SCHEMA "org.gnome.Evolution.DefaultSources"
73 /* Built-in data source UIDs. */
74 #define E_SOURCE_BUILTIN_ADDRESS_BOOK_UID "system-address-book"
75 #define E_SOURCE_BUILTIN_CALENDAR_UID "system-calendar"
76 #define E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID "local"
77 #define E_SOURCE_BUILTIN_MEMO_LIST_UID "system-memo-list"
78 #define E_SOURCE_BUILTIN_PROXY_UID "system-proxy"
79 #define E_SOURCE_BUILTIN_TASK_LIST_UID "system-task-list"
81 /* GSettings keys for default data sources. */
82 #define E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY "default-address-book"
83 #define E_SETTINGS_DEFAULT_CALENDAR_KEY "default-calendar"
84 #define E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY "default-mail-account"
85 #define E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY "default-mail-identity"
86 #define E_SETTINGS_DEFAULT_MEMO_LIST_KEY "default-memo-list"
87 #define E_SETTINGS_DEFAULT_TASK_LIST_KEY "default-task-list"
89 typedef struct _AsyncContext AsyncContext;
90 typedef struct _AuthContext AuthContext;
91 typedef struct _CreateContext CreateContext;
92 typedef struct _SourceClosure SourceClosure;
93 typedef struct _ThreadClosure ThreadClosure;
95 struct _ESourceRegistryPrivate {
96 GMainContext *main_context;
98 GThread *manager_thread;
99 ThreadClosure *thread_closure;
101 GDBusObjectManager *dbus_object_manager;
102 EDBusSourceManager *dbus_source_manager;
104 GHashTable *object_path_table;
105 GMutex object_path_table_lock;
107 GHashTable *service_restart_table;
108 GMutex service_restart_table_lock;
115 gboolean initialized;
120 struct _AsyncContext {
122 GList *list_of_sources;
123 ESourceAuthenticator *auth;
126 /* Used in e_source_registry_authenticate_sync() */
127 struct _AuthContext {
128 ESourceAuthenticator *auth;
129 EDBusAuthenticator *dbus_auth;
130 GCancellable *cancellable;
131 GMainLoop *main_loop;
132 ESourceAuthenticationResult auth_result;
133 GcrSecretExchange *secret_exchange;
134 gboolean authenticating;
138 /* Used in e_source_registry_create_sources_sync() */
139 struct _CreateContext {
140 GHashTable *pending_uids;
141 GMainContext *main_context;
142 GMainLoop *main_loop;
145 struct _SourceClosure {
150 struct _ThreadClosure {
151 ESourceRegistry *registry;
152 GMainContext *main_context;
153 GMainLoop *main_loop;
154 GCond main_loop_cond;
155 GMutex main_loop_mutex;
161 PROP_DEFAULT_ADDRESS_BOOK,
162 PROP_DEFAULT_CALENDAR,
163 PROP_DEFAULT_MAIL_ACCOUNT,
164 PROP_DEFAULT_MAIL_IDENTITY,
165 PROP_DEFAULT_MEMO_LIST,
166 PROP_DEFAULT_TASK_LIST
178 /* Forward Declarations */
179 static void source_registry_add_source (ESourceRegistry *registry,
181 static void e_source_registry_initable_init (GInitableIface *iface);
183 /* Private ESource function, for our use only. */
184 void __e_source_private_replace_dbus_object
186 GDBusObject *dbus_object);
188 static guint signals[LAST_SIGNAL];
190 /* By default, the GAsyncInitable interface calls GInitable.init()
191 * from a separate thread, so we only have to override GInitable. */
192 G_DEFINE_TYPE_WITH_CODE (
196 G_IMPLEMENT_INTERFACE (
197 G_TYPE_INITABLE, e_source_registry_initable_init)
198 G_IMPLEMENT_INTERFACE (
199 G_TYPE_ASYNC_INITABLE, NULL))
202 async_context_free (AsyncContext *async_context)
204 if (async_context->source != NULL)
205 g_object_unref (async_context->source);
208 async_context->list_of_sources,
209 (GDestroyNotify) g_object_unref);
211 if (async_context->auth != NULL)
212 g_object_unref (async_context->auth);
214 g_slice_free (AsyncContext, async_context);
218 auth_context_free (AuthContext *auth_context)
220 if (auth_context->auth != NULL)
221 g_object_unref (auth_context->auth);
223 if (auth_context->dbus_auth != NULL)
224 g_object_unref (auth_context->dbus_auth);
226 if (auth_context->cancellable != NULL)
227 g_object_unref (auth_context->cancellable);
229 if (auth_context->main_loop != NULL)
230 g_main_loop_unref (auth_context->main_loop);
232 if (auth_context->secret_exchange != NULL)
233 g_object_unref (auth_context->secret_exchange);
235 g_slice_free (AuthContext, auth_context);
238 static CreateContext *
239 create_context_new (void)
241 CreateContext *create_context;
243 create_context = g_slice_new0 (CreateContext);
245 create_context->pending_uids = g_hash_table_new_full (
246 (GHashFunc) g_str_hash,
247 (GEqualFunc) g_str_equal,
248 (GDestroyNotify) g_free,
249 (GDestroyNotify) NULL);
251 create_context->main_context = g_main_context_new ();
253 create_context->main_loop = g_main_loop_new (
254 create_context->main_context, FALSE);
256 return create_context;
260 create_context_free (CreateContext *create_context)
262 g_main_loop_unref (create_context->main_loop);
263 g_main_context_unref (create_context->main_context);
264 g_hash_table_unref (create_context->pending_uids);
266 g_slice_free (CreateContext, create_context);
270 source_closure_free (SourceClosure *closure)
272 g_weak_ref_set (&closure->registry, NULL);
273 g_object_unref (closure->source);
275 g_slice_free (SourceClosure, closure);
279 thread_closure_free (ThreadClosure *closure)
281 /* The registry member is not referenced. */
283 g_main_context_unref (closure->main_context);
284 g_main_loop_unref (closure->main_loop);
285 g_cond_clear (&closure->main_loop_cond);
286 g_mutex_clear (&closure->main_loop_mutex);
288 /* The GError should be NULL at this point,
289 * regardless of whether an error occurred. */
290 g_warn_if_fail (closure->error == NULL);
292 g_slice_free (ThreadClosure, closure);
295 G_LOCK_DEFINE_STATIC (singleton_lock);
296 static GWeakRef singleton;
298 static ESourceRegistry *
299 source_registry_dup_uninitialized_singleton (void)
301 ESourceRegistry *registry;
303 G_LOCK (singleton_lock);
305 registry = g_weak_ref_get (&singleton);
306 if (registry == NULL) {
307 registry = g_object_new (E_TYPE_SOURCE_REGISTRY, NULL);
308 g_weak_ref_set (&singleton, registry);
311 G_UNLOCK (singleton_lock);
317 source_registry_dbus_object_dup_uid (GDBusObject *dbus_object)
319 EDBusObject *e_dbus_object;
320 EDBusSource *e_dbus_source;
322 /* EDBusSource interface should always be present. */
323 e_dbus_object = E_DBUS_OBJECT (dbus_object);
324 e_dbus_source = e_dbus_object_peek_source (e_dbus_object);
326 return e_dbus_source_dup_uid (e_dbus_source);
330 source_registry_object_path_table_insert (ESourceRegistry *registry,
331 const gchar *object_path,
334 GHashTable *object_path_table;
336 g_return_if_fail (object_path != NULL);
337 g_return_if_fail (E_IS_SOURCE (source));
339 object_path_table = registry->priv->object_path_table;
341 g_mutex_lock (®istry->priv->object_path_table_lock);
343 g_hash_table_insert (
345 g_strdup (object_path),
346 g_object_ref (source));
348 g_mutex_unlock (®istry->priv->object_path_table_lock);
352 source_registry_object_path_table_lookup (ESourceRegistry *registry,
353 const gchar *object_path)
355 GHashTable *object_path_table;
358 g_return_val_if_fail (object_path != NULL, NULL);
360 object_path_table = registry->priv->object_path_table;
362 g_mutex_lock (®istry->priv->object_path_table_lock);
364 source = g_hash_table_lookup (object_path_table, object_path);
366 g_object_ref (source);
368 g_mutex_unlock (®istry->priv->object_path_table_lock);
374 source_registry_object_path_table_remove (ESourceRegistry *registry,
375 const gchar *object_path)
377 GHashTable *object_path_table;
380 g_return_val_if_fail (object_path != NULL, FALSE);
382 object_path_table = registry->priv->object_path_table;
384 g_mutex_lock (®istry->priv->object_path_table_lock);
386 removed = g_hash_table_remove (object_path_table, object_path);
388 g_mutex_unlock (®istry->priv->object_path_table_lock);
394 source_registry_service_restart_table_add (ESourceRegistry *registry,
397 GHashTable *service_restart_table;
399 g_return_if_fail (uid != NULL);
401 service_restart_table = registry->priv->service_restart_table;
403 g_mutex_lock (®istry->priv->service_restart_table_lock);
405 g_hash_table_add (service_restart_table, g_strdup (uid));
407 g_mutex_unlock (®istry->priv->service_restart_table_lock);
411 source_registry_service_restart_table_remove (ESourceRegistry *registry,
414 GHashTable *service_restart_table;
417 g_return_val_if_fail (uid != NULL, FALSE);
419 service_restart_table = registry->priv->service_restart_table;
421 g_mutex_lock (®istry->priv->service_restart_table_lock);
423 removed = g_hash_table_remove (service_restart_table, uid);
425 g_mutex_unlock (®istry->priv->service_restart_table_lock);
431 source_registry_service_restart_table_steal_all (ESourceRegistry *registry)
433 GHashTable *service_restart_table;
436 service_restart_table = registry->priv->service_restart_table;
438 g_mutex_lock (®istry->priv->service_restart_table_lock);
440 list = g_hash_table_get_keys (service_restart_table);
441 g_hash_table_steal_all (service_restart_table);
443 g_mutex_unlock (®istry->priv->service_restart_table_lock);
449 source_registry_sources_insert (ESourceRegistry *registry,
454 uid = e_source_get_uid (source);
455 g_return_if_fail (uid != NULL);
457 g_mutex_lock (®istry->priv->sources_lock);
459 g_hash_table_insert (
460 registry->priv->sources,
461 g_strdup (uid), g_object_ref (source));
463 g_mutex_unlock (®istry->priv->sources_lock);
467 source_registry_sources_remove (ESourceRegistry *registry,
473 uid = e_source_get_uid (source);
474 g_return_val_if_fail (uid != NULL, FALSE);
476 g_mutex_lock (®istry->priv->sources_lock);
478 removed = g_hash_table_remove (registry->priv->sources, uid);
480 g_mutex_unlock (®istry->priv->sources_lock);
486 source_registry_sources_lookup (ESourceRegistry *registry,
491 g_return_val_if_fail (uid != NULL, NULL);
493 g_mutex_lock (®istry->priv->sources_lock);
495 source = g_hash_table_lookup (registry->priv->sources, uid);
498 g_object_ref (source);
500 g_mutex_unlock (®istry->priv->sources_lock);
506 source_registry_sources_get_values (ESourceRegistry *registry)
510 g_mutex_lock (®istry->priv->sources_lock);
512 values = g_hash_table_get_values (registry->priv->sources);
514 g_list_foreach (values, (GFunc) g_object_ref, NULL);
516 g_mutex_unlock (®istry->priv->sources_lock);
522 source_registry_sources_build_tree (ESourceRegistry *registry)
529 g_mutex_lock (®istry->priv->sources_lock);
531 root = g_node_new (NULL);
532 index = g_hash_table_new (g_str_hash, g_str_equal);
534 /* Add a GNode for each ESource to the index. */
535 g_hash_table_iter_init (&iter, registry->priv->sources);
536 while (g_hash_table_iter_next (&iter, &key, &value)) {
537 ESource *source = g_object_ref (value);
538 g_hash_table_insert (index, key, g_node_new (source));
541 /* Traverse the index and link the nodes together. */
542 g_hash_table_iter_init (&iter, index);
543 while (g_hash_table_iter_next (&iter, NULL, &value)) {
547 const gchar *parent_uid;
549 source_node = (GNode *) value;
550 source = E_SOURCE (source_node->data);
551 parent_uid = e_source_get_parent (source);
553 if (parent_uid == NULL || *parent_uid == '\0') {
556 parent_node = g_hash_table_lookup (index, parent_uid);
557 g_warn_if_fail (parent_node != NULL);
560 /* Should never be NULL, but just to be safe. */
561 if (parent_node != NULL)
562 g_node_append (parent_node, source_node);
565 g_hash_table_destroy (index);
567 g_mutex_unlock (®istry->priv->sources_lock);
573 source_registry_settings_changed_cb (GSettings *settings,
575 ESourceRegistry *registry)
577 /* We define a property name that matches every key in
578 * the "org.gnome.Evolution.DefaultSources" schema. */
579 g_object_notify (G_OBJECT (registry), key);
583 source_registry_source_changed_idle_cb (gpointer user_data)
585 SourceClosure *closure = user_data;
586 ESourceRegistry *registry;
588 registry = g_weak_ref_get (&closure->registry);
590 if (registry != NULL) {
593 signals[SOURCE_CHANGED], 0,
595 g_object_unref (registry);
602 source_registry_source_notify_enabled_idle_cb (gpointer user_data)
604 SourceClosure *closure = user_data;
605 ESourceRegistry *registry;
607 registry = g_weak_ref_get (&closure->registry);
609 if (registry != NULL) {
610 if (e_source_get_enabled (closure->source)) {
613 signals[SOURCE_ENABLED], 0,
618 signals[SOURCE_DISABLED], 0,
621 g_object_unref (registry);
628 source_registry_source_changed_cb (ESource *source,
629 ESourceRegistry *registry)
631 GSource *idle_source;
632 SourceClosure *closure;
634 closure = g_slice_new0 (SourceClosure);
635 g_weak_ref_set (&closure->registry, registry);
636 closure->source = g_object_ref (source);
638 idle_source = g_idle_source_new ();
639 g_source_set_callback (
641 source_registry_source_changed_idle_cb,
642 closure, (GDestroyNotify) source_closure_free);
643 g_source_attach (idle_source, registry->priv->main_context);
644 g_source_unref (idle_source);
648 source_registry_source_notify_enabled_cb (ESource *source,
650 ESourceRegistry *registry)
652 GSource *idle_source;
653 SourceClosure *closure;
655 closure = g_slice_new0 (SourceClosure);
656 g_weak_ref_set (&closure->registry, registry);
657 closure->source = g_object_ref (source);
659 idle_source = g_idle_source_new ();
660 g_source_set_callback (
662 source_registry_source_notify_enabled_idle_cb,
663 closure, (GDestroyNotify) source_closure_free);
664 g_source_attach (idle_source, registry->priv->main_context);
665 g_source_unref (idle_source);
669 source_registry_new_source (ESourceRegistry *registry,
670 GDBusObject *dbus_object)
672 GMainContext *main_context;
674 const gchar *object_path;
675 GError *local_error = NULL;
677 /* We don't want the ESource emitting "changed" signals from
678 * the manager thread, so we pass it the same main context the
679 * registry uses for scheduling signal emissions. */
680 main_context = registry->priv->main_context;
681 source = e_source_new (dbus_object, main_context, &local_error);
682 object_path = g_dbus_object_get_object_path (dbus_object);
684 /* The likelihood of an error here is slim, so it's
685 * sufficient to just print a warning if one occurs. */
686 if (local_error != NULL) {
687 g_warn_if_fail (source == NULL);
689 "ESourceRegistry: Failed to create a "
690 "data source object for path '%s': %s",
691 object_path, local_error->message);
692 g_error_free (local_error);
696 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
698 /* Add the ESource to the object path table immediately. */
699 source_registry_object_path_table_insert (
700 registry, object_path, source);
706 source_registry_unref_source (ESource *source)
708 g_signal_handlers_disconnect_matched (
709 source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
710 source_registry_source_changed_cb, NULL);
712 g_signal_handlers_disconnect_matched (
713 source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
714 source_registry_source_notify_enabled_cb, NULL);
716 g_object_unref (source);
720 source_registry_add_source (ESourceRegistry *registry,
725 /* This is called in the manager thread during initialization
726 * and in response to "object-added" signals from the manager. */
728 uid = e_source_get_uid (source);
729 g_return_if_fail (uid != NULL);
731 g_mutex_lock (®istry->priv->sources_lock);
733 /* Check if we already have this source in the registry. */
734 if (g_hash_table_lookup (registry->priv->sources, uid) != NULL) {
735 g_mutex_unlock (®istry->priv->sources_lock);
741 G_CALLBACK (source_registry_source_changed_cb),
745 source, "notify::enabled",
746 G_CALLBACK (source_registry_source_notify_enabled_cb),
749 g_mutex_unlock (®istry->priv->sources_lock);
751 source_registry_sources_insert (registry, source);
755 source_registry_object_added_idle_cb (gpointer user_data)
757 SourceClosure *closure = user_data;
758 ESourceRegistry *registry;
760 registry = g_weak_ref_get (&closure->registry);
762 if (registry != NULL) {
765 signals[SOURCE_ADDED], 0,
767 g_object_unref (registry);
774 source_registry_object_added_by_owner (ESourceRegistry *registry,
775 GDBusObject *dbus_object)
777 SourceClosure *closure;
778 GSource *idle_source;
781 g_return_if_fail (E_DBUS_IS_OBJECT (dbus_object));
783 source = source_registry_new_source (registry, dbus_object);
784 g_return_if_fail (source != NULL);
786 /* Add the new ESource to our internal hash table so it can be
787 * obtained through e_source_registry_ref_source() immediately. */
788 source_registry_add_source (registry, source);
790 /* Schedule a callback on the ESourceRegistry's GMainContext. */
792 closure = g_slice_new0 (SourceClosure);
793 g_weak_ref_set (&closure->registry, registry);
794 closure->source = g_object_ref (source);
796 idle_source = g_idle_source_new ();
797 g_source_set_callback (
799 source_registry_object_added_idle_cb,
800 closure, (GDestroyNotify) source_closure_free);
801 g_source_attach (idle_source, registry->priv->main_context);
802 g_source_unref (idle_source);
804 g_object_unref (source);
808 source_registry_object_added_no_owner (ESourceRegistry *registry,
809 GDBusObject *dbus_object)
811 ESource *source = NULL;
814 uid = source_registry_dbus_object_dup_uid (dbus_object);
816 if (source_registry_service_restart_table_remove (registry, uid))
817 source = e_source_registry_ref_source (registry, uid);
819 if (source != NULL) {
820 const gchar *object_path;
822 object_path = g_dbus_object_get_object_path (dbus_object);
824 source_registry_object_path_table_insert (
825 registry, object_path, source);
827 __e_source_private_replace_dbus_object (source, dbus_object);
829 g_object_unref (source);
832 source_registry_object_added_by_owner (registry, dbus_object);
839 source_registry_object_added_cb (GDBusObjectManager *object_manager,
840 GDBusObject *dbus_object,
841 ESourceRegistry *registry)
845 name_owner = g_dbus_object_manager_client_get_name_owner (
846 G_DBUS_OBJECT_MANAGER_CLIENT (object_manager));
848 if (name_owner != NULL)
849 source_registry_object_added_by_owner (registry, dbus_object);
851 source_registry_object_added_no_owner (registry, dbus_object);
857 source_registry_object_removed_idle_cb (gpointer user_data)
859 SourceClosure *closure = user_data;
860 ESourceRegistry *registry;
862 registry = g_weak_ref_get (&closure->registry);
864 if (registry != NULL) {
867 signals[SOURCE_REMOVED], 0,
869 g_object_unref (registry);
876 source_registry_object_removed_by_owner (ESourceRegistry *registry,
877 GDBusObject *dbus_object)
879 SourceClosure *closure;
880 GSource *idle_source;
882 const gchar *object_path;
884 /* Find the corresponding ESource in the object path table.
885 * Note that the lookup returns a new ESource reference. */
886 object_path = g_dbus_object_get_object_path (dbus_object);
887 source = source_registry_object_path_table_lookup (
888 registry, object_path);
889 g_return_if_fail (E_IS_SOURCE (source));
891 /* Remove the ESource from the object path table immediately. */
892 source_registry_object_path_table_remove (registry, object_path);
894 /* Also remove the ESource from the sources table immediately. */
895 if (!source_registry_sources_remove (registry, source)) {
896 g_object_unref (source);
897 g_return_if_reached ();
900 /* Strip the ESource of its GDBusObject. */
901 __e_source_private_replace_dbus_object (source, NULL);
903 /* Schedule a callback on the ESourceRegistry's GMainContext. */
905 closure = g_slice_new0 (SourceClosure);
906 g_weak_ref_set (&closure->registry, registry);
907 closure->source = g_object_ref (source);
909 idle_source = g_idle_source_new ();
910 g_source_set_callback (
912 source_registry_object_removed_idle_cb,
913 closure, (GDestroyNotify) source_closure_free);
914 g_source_attach (idle_source, registry->priv->main_context);
915 g_source_unref (idle_source);
917 g_object_unref (source);
921 source_registry_object_removed_no_owner (ESourceRegistry *registry,
922 GDBusObject *dbus_object)
924 const gchar *object_path;
926 object_path = g_dbus_object_get_object_path (dbus_object);
928 if (source_registry_object_path_table_remove (registry, object_path)) {
931 uid = source_registry_dbus_object_dup_uid (dbus_object);
932 source_registry_service_restart_table_add (registry, uid);
938 source_registry_object_removed_cb (GDBusObjectManager *object_manager,
939 GDBusObject *dbus_object,
940 ESourceRegistry *registry)
944 name_owner = g_dbus_object_manager_client_get_name_owner (
945 G_DBUS_OBJECT_MANAGER_CLIENT (object_manager));
947 if (name_owner != NULL)
948 source_registry_object_removed_by_owner (registry, dbus_object);
950 source_registry_object_removed_no_owner (registry, dbus_object);
956 source_registry_name_appeared (ESourceRegistry *registry)
960 /* The D-Bus service restarted, and the GDBusObjectManager has
961 * just set its "name-owner" property having finished emitting
962 * an "object-added" signal for each GDBusObject. */
964 list = source_registry_service_restart_table_steal_all (registry);
966 for (link = list; link != NULL; link = g_list_next (link)) {
967 SourceClosure *closure;
968 GSource *idle_source;
970 const gchar *uid = link->data;
972 source = e_source_registry_ref_source (registry, uid);
976 closure = g_slice_new0 (SourceClosure);
977 g_weak_ref_set (&closure->registry, registry);
978 closure->source = g_object_ref (source);
980 idle_source = g_idle_source_new ();
981 g_source_set_callback (
983 source_registry_object_removed_idle_cb,
984 closure, (GDestroyNotify) source_closure_free);
985 g_source_attach (idle_source, registry->priv->main_context);
986 g_source_unref (idle_source);
988 g_object_unref (source);
991 g_list_free_full (list, (GDestroyNotify) g_free);
995 source_registry_name_vanished (ESourceRegistry *registry)
997 /* This function is just a convenience breakpoint. The D-Bus
998 * service aborted, so the GDBusObjectManager has cleared its
999 * "name-owner" property and will now emit a "object-removed"
1000 * signal for each GDBusObject. */
1004 source_registry_notify_name_owner_cb (GDBusObjectManager *object_manager,
1006 ESourceRegistry *registry)
1010 name_owner = g_dbus_object_manager_client_get_name_owner (
1011 G_DBUS_OBJECT_MANAGER_CLIENT (object_manager));
1013 if (name_owner != NULL)
1014 source_registry_name_appeared (registry);
1016 source_registry_name_vanished (registry);
1018 g_free (name_owner);
1022 source_registry_object_manager_running (gpointer data)
1024 ThreadClosure *closure = data;
1026 g_mutex_lock (&closure->main_loop_mutex);
1027 g_cond_broadcast (&closure->main_loop_cond);
1028 g_mutex_unlock (&closure->main_loop_mutex);
1034 source_registry_object_manager_thread (gpointer data)
1036 GDBusObjectManager *object_manager;
1037 ThreadClosure *closure = data;
1038 GSource *idle_source;
1040 gulong object_added_handler_id = 0;
1041 gulong object_removed_handler_id = 0;
1042 gulong notify_name_owner_handler_id = 0;
1044 /* GDBusObjectManagerClient grabs the thread-default GMainContext
1045 * at creation time and only emits signals from that GMainContext.
1046 * Running it in a separate thread prevents its signal emissions
1047 * from being inhibited by someone overriding the thread-default
1050 /* This becomes the GMainContext that GDBusObjectManagerClient
1051 * will emit signals from. Make it the thread-default context
1052 * for this thread before creating the client. */
1053 g_main_context_push_thread_default (closure->main_context);
1055 object_manager = e_dbus_object_manager_client_new_for_bus_sync (
1057 G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
1058 SOURCES_DBUS_SERVICE_NAME,
1060 NULL, &closure->error);
1064 ((object_manager != NULL) && (closure->error == NULL)) ||
1065 ((object_manager == NULL) && (closure->error != NULL)));
1067 /* If we failed to create the GDBusObjectManagerClient, skip
1068 * straight to the main loop. The GError will be propagated
1069 * back to the caller, the main loop will terminate, and the
1070 * partially-initialized ESourceRegistry will be destroyed. */
1071 if (object_manager == NULL)
1074 /* Give the registry a handle to the object manager. */
1075 closure->registry->priv->dbus_object_manager =
1076 g_object_ref (object_manager);
1078 /* Now populate the registry with an initial set of ESources. */
1080 list = g_dbus_object_manager_get_objects (object_manager);
1082 for (link = list; link != NULL; link = g_list_next (link)) {
1083 GDBusObject *dbus_object;
1086 dbus_object = G_DBUS_OBJECT (link->data);
1088 source = source_registry_new_source (
1089 closure->registry, dbus_object);
1091 if (source != NULL) {
1092 source_registry_add_source (
1093 closure->registry, source);
1094 g_object_unref (source);
1098 g_list_free_full (list, (GDestroyNotify) g_object_unref);
1100 /* Listen for D-Bus object additions and removals. */
1102 object_added_handler_id = g_signal_connect (
1103 object_manager, "object-added",
1104 G_CALLBACK (source_registry_object_added_cb),
1107 object_removed_handler_id = g_signal_connect (
1108 object_manager, "object-removed",
1109 G_CALLBACK (source_registry_object_removed_cb),
1112 notify_name_owner_handler_id = g_signal_connect (
1113 object_manager, "notify::name-owner",
1114 G_CALLBACK (source_registry_notify_name_owner_cb),
1118 /* Schedule a one-time idle callback to broadcast through a
1119 * condition variable that our main loop is up and running. */
1121 idle_source = g_idle_source_new ();
1122 g_source_set_callback (
1124 source_registry_object_manager_running,
1125 closure, (GDestroyNotify) NULL);
1126 g_source_attach (idle_source, closure->main_context);
1127 g_source_unref (idle_source);
1129 /* Now we mostly idle here for the rest of the session. */
1131 g_main_loop_run (closure->main_loop);
1133 /* Clean up and exit. */
1135 if (object_manager != NULL) {
1136 g_signal_handler_disconnect (
1137 object_manager, object_added_handler_id);
1138 g_signal_handler_disconnect (
1139 object_manager, object_removed_handler_id);
1140 g_signal_handler_disconnect (
1141 object_manager, notify_name_owner_handler_id);
1142 g_object_unref (object_manager);
1145 g_main_context_pop_thread_default (closure->main_context);
1151 source_registry_set_property (GObject *object,
1153 const GValue *value,
1156 switch (property_id) {
1157 case PROP_DEFAULT_ADDRESS_BOOK:
1158 e_source_registry_set_default_address_book (
1159 E_SOURCE_REGISTRY (object),
1160 g_value_get_object (value));
1163 case PROP_DEFAULT_CALENDAR:
1164 e_source_registry_set_default_calendar (
1165 E_SOURCE_REGISTRY (object),
1166 g_value_get_object (value));
1169 case PROP_DEFAULT_MAIL_ACCOUNT:
1170 e_source_registry_set_default_mail_account (
1171 E_SOURCE_REGISTRY (object),
1172 g_value_get_object (value));
1175 case PROP_DEFAULT_MAIL_IDENTITY:
1176 e_source_registry_set_default_mail_identity (
1177 E_SOURCE_REGISTRY (object),
1178 g_value_get_object (value));
1181 case PROP_DEFAULT_MEMO_LIST:
1182 e_source_registry_set_default_memo_list (
1183 E_SOURCE_REGISTRY (object),
1184 g_value_get_object (value));
1187 case PROP_DEFAULT_TASK_LIST:
1188 e_source_registry_set_default_task_list (
1189 E_SOURCE_REGISTRY (object),
1190 g_value_get_object (value));
1194 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1198 source_registry_get_property (GObject *object,
1203 switch (property_id) {
1204 case PROP_DEFAULT_ADDRESS_BOOK:
1205 g_value_take_object (
1207 e_source_registry_ref_default_address_book (
1208 E_SOURCE_REGISTRY (object)));
1211 case PROP_DEFAULT_CALENDAR:
1212 g_value_take_object (
1214 e_source_registry_ref_default_calendar (
1215 E_SOURCE_REGISTRY (object)));
1218 case PROP_DEFAULT_MAIL_ACCOUNT:
1219 g_value_take_object (
1221 e_source_registry_ref_default_mail_account (
1222 E_SOURCE_REGISTRY (object)));
1225 case PROP_DEFAULT_MAIL_IDENTITY:
1226 g_value_take_object (
1228 e_source_registry_ref_default_mail_identity (
1229 E_SOURCE_REGISTRY (object)));
1232 case PROP_DEFAULT_MEMO_LIST:
1233 g_value_take_object (
1235 e_source_registry_ref_default_memo_list (
1236 E_SOURCE_REGISTRY (object)));
1239 case PROP_DEFAULT_TASK_LIST:
1240 g_value_take_object (
1242 e_source_registry_ref_default_task_list (
1243 E_SOURCE_REGISTRY (object)));
1247 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1251 source_registry_dispose (GObject *object)
1253 ESourceRegistryPrivate *priv;
1255 priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
1257 /* Terminate the manager thread first. */
1258 if (priv->manager_thread != NULL) {
1259 g_main_loop_quit (priv->thread_closure->main_loop);
1260 g_thread_join (priv->manager_thread);
1261 thread_closure_free (priv->thread_closure);
1262 priv->manager_thread = NULL;
1263 priv->thread_closure = NULL;
1266 if (priv->main_context != NULL) {
1267 g_main_context_unref (priv->main_context);
1268 priv->main_context = NULL;
1271 if (priv->dbus_object_manager != NULL) {
1272 g_object_unref (priv->dbus_object_manager);
1273 priv->dbus_object_manager = NULL;
1276 if (priv->dbus_source_manager != NULL) {
1277 g_object_unref (priv->dbus_source_manager);
1278 priv->dbus_source_manager = NULL;
1281 g_hash_table_remove_all (priv->object_path_table);
1283 g_hash_table_remove_all (priv->sources);
1285 if (priv->settings != NULL) {
1286 g_signal_handlers_disconnect_by_data (priv->settings, object);
1287 g_object_unref (priv->settings);
1288 priv->settings = NULL;
1291 /* Chain up to parent's finalize() method. */
1292 G_OBJECT_CLASS (e_source_registry_parent_class)->dispose (object);
1296 source_registry_finalize (GObject *object)
1298 ESourceRegistryPrivate *priv;
1300 priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
1302 g_hash_table_destroy (priv->object_path_table);
1303 g_mutex_clear (&priv->object_path_table_lock);
1305 g_hash_table_destroy (priv->service_restart_table);
1306 g_mutex_clear (&priv->service_restart_table_lock);
1308 g_hash_table_destroy (priv->sources);
1309 g_mutex_clear (&priv->sources_lock);
1311 g_clear_error (&priv->init_error);
1312 g_mutex_clear (&priv->init_lock);
1314 /* Chain up to parent's finalize() method. */
1315 G_OBJECT_CLASS (e_source_registry_parent_class)->finalize (object);
1319 source_registry_initable_init (GInitable *initable,
1320 GCancellable *cancellable,
1323 ESourceRegistry *registry;
1324 ThreadClosure *closure;
1325 GError *local_error = NULL;
1327 registry = E_SOURCE_REGISTRY (initable);
1329 g_mutex_lock (®istry->priv->init_lock);
1331 if (registry->priv->initialized)
1334 closure = g_slice_new0 (ThreadClosure);
1335 closure->registry = registry; /* do not reference */
1336 closure->main_context = g_main_context_new ();
1337 /* It's important to pass 'is_running=FALSE' here because
1338 * we wait for the main loop to start running as a way of
1339 * synchronizing with the manager thread. */
1340 closure->main_loop = g_main_loop_new (closure->main_context, FALSE);
1341 g_cond_init (&closure->main_loop_cond);
1342 g_mutex_init (&closure->main_loop_mutex);
1344 registry->priv->thread_closure = closure;
1346 registry->priv->manager_thread = g_thread_new (
1348 source_registry_object_manager_thread,
1351 /* Wait for notification that the manager
1352 * thread's main loop has been started. */
1353 g_mutex_lock (&closure->main_loop_mutex);
1354 while (!g_main_loop_is_running (closure->main_loop))
1356 &closure->main_loop_cond,
1357 &closure->main_loop_mutex);
1358 g_mutex_unlock (&closure->main_loop_mutex);
1360 /* Check for error in the manager thread. */
1361 if (closure->error != NULL) {
1362 g_dbus_error_strip_remote_error (closure->error);
1363 g_propagate_error (®istry->priv->init_error, closure->error);
1364 closure->error = NULL;
1368 /* The registry should now be populated with sources.
1370 * XXX Actually, not necessarily if the registry service was
1371 * just now activated. There may yet be a small window
1372 * while the registry service starts up before it exports
1373 * any sources, even built-in sources. This COULD create
1374 * problems if any logic that depends on those built-in
1375 * sources executes during this time window, but so far
1376 * we haven't seen any cases of that.
1378 * Attempts in the past to stop and wait for sources to
1379 * show up have proven problematic. See for example:
1380 * https://bugzilla.gnome.org/678378
1382 * Leave the runtime check disabled for the moment.
1383 * I have a feeling I'll be revisiting this again.
1385 /*g_warn_if_fail (g_hash_table_size (registry->priv->sources) > 0);*/
1387 /* The EDBusSourceManagerProxy is just another D-Bus interface
1388 * that resides at the same object path. It's unrelated to the
1389 * GDBusObjectManagerClient and doesn't need its own thread. */
1390 registry->priv->dbus_source_manager =
1391 e_dbus_source_manager_proxy_new_for_bus_sync (
1393 G_DBUS_PROXY_FLAGS_NONE,
1394 SOURCES_DBUS_SERVICE_NAME,
1396 cancellable, &local_error);
1398 if (local_error != NULL) {
1399 g_dbus_error_strip_remote_error (local_error);
1400 g_propagate_error (®istry->priv->init_error, local_error);
1404 /* Allow authentication prompts for all exported data sources
1405 * when a new EDBusSourceManagerProxy is created. The thought
1406 * being, if you cancel an authentication prompt you will not
1407 * be bothered again until you start (or restart) a new E-D-S
1408 * client app. Failure here is non-fatal, ignore errors. */
1409 e_dbus_source_manager_call_allow_auth_prompt_all_sync (
1410 registry->priv->dbus_source_manager, cancellable, NULL);
1413 registry->priv->initialized = TRUE;
1414 g_mutex_unlock (®istry->priv->init_lock);
1416 if (registry->priv->init_error != NULL) {
1417 GError *init_error_copy;
1419 /* Return a copy of the same error to
1420 * all pending initialization requests. */
1421 init_error_copy = g_error_copy (registry->priv->init_error);
1422 g_propagate_error (error, init_error_copy);
1431 e_source_registry_class_init (ESourceRegistryClass *class)
1433 GObjectClass *object_class;
1435 g_type_class_add_private (class, sizeof (ESourceRegistryPrivate));
1437 object_class = G_OBJECT_CLASS (class);
1438 object_class->set_property = source_registry_set_property;
1439 object_class->get_property = source_registry_get_property;
1440 object_class->dispose = source_registry_dispose;
1441 object_class->finalize = source_registry_finalize;
1443 /* The property names correspond to the key names in the
1444 * "org.gnome.Evolution.DefaultSources" GSettings schema. */
1447 * ESourceRegistry:default-address-book:
1449 * The default address book #ESource.
1451 g_object_class_install_property (
1453 PROP_DEFAULT_ADDRESS_BOOK,
1454 g_param_spec_object (
1455 "default-address-book",
1456 "Default Address Book",
1457 "The default address book ESource",
1460 G_PARAM_STATIC_STRINGS));
1463 * ESourceRegistry:default-calendar:
1465 * The default calendar #ESource.
1467 g_object_class_install_property (
1469 PROP_DEFAULT_CALENDAR,
1470 g_param_spec_object (
1473 "The default calendar ESource",
1476 G_PARAM_STATIC_STRINGS));
1479 * ESourceRegistry:default-mail-account:
1481 * The default mail account #ESource.
1483 g_object_class_install_property (
1485 PROP_DEFAULT_MAIL_ACCOUNT,
1486 g_param_spec_object (
1487 "default-mail-account",
1488 "Default Mail Account",
1489 "The default mail account ESource",
1492 G_PARAM_STATIC_STRINGS));
1495 * ESourceRegistry:default-mail-identity:
1497 * The default mail identity #ESource.
1499 g_object_class_install_property (
1501 PROP_DEFAULT_MAIL_IDENTITY,
1502 g_param_spec_object (
1503 "default-mail-identity",
1504 "Default Mail Identity",
1505 "The default mail identity ESource",
1508 G_PARAM_STATIC_STRINGS));
1511 * ESourceRegistry:default-memo-list:
1513 * The default memo list #ESource.
1515 g_object_class_install_property (
1517 PROP_DEFAULT_MEMO_LIST,
1518 g_param_spec_object (
1519 "default-memo-list",
1520 "Default Memo List",
1521 "The default memo list ESource",
1524 G_PARAM_STATIC_STRINGS));
1527 * ESourceRegistry:default-task-list:
1529 * The default task list #ESource.
1531 g_object_class_install_property (
1533 PROP_DEFAULT_TASK_LIST,
1534 g_param_spec_object (
1535 "default-task-list",
1536 "Default Task List",
1537 "The default task list ESource",
1540 G_PARAM_STATIC_STRINGS));
1543 * ESourceRegistry::source-added:
1544 * @registry: the #ESourceRegistry which emitted the signal
1545 * @source: the newly-added #ESource
1547 * Emitted when an #ESource is added to @registry.
1549 signals[SOURCE_ADDED] = g_signal_new (
1551 G_OBJECT_CLASS_TYPE (object_class),
1553 G_STRUCT_OFFSET (ESourceRegistryClass, source_added),
1559 * ESourceRegistry::source-changed:
1560 * @registry: the #ESourceRegistry which emitted the signal
1561 * @source: the #ESource that changed
1563 * Emitted when an #ESource registered with @registry emits
1564 * its #ESource::changed signal.
1566 signals[SOURCE_CHANGED] = g_signal_new (
1568 G_OBJECT_CLASS_TYPE (object_class),
1570 G_STRUCT_OFFSET (ESourceRegistryClass, source_changed),
1576 * ESourceRegistry::source-removed:
1577 * @registry: the #ESourceRegistry which emitted the signal
1578 * @source: the #ESource that got removed
1580 * Emitted when an #ESource is removed from @registry.
1582 signals[SOURCE_REMOVED] = g_signal_new (
1584 G_OBJECT_CLASS_TYPE (object_class),
1586 G_STRUCT_OFFSET (ESourceRegistryClass, source_removed),
1592 * ESourceRegistry::source-enabled:
1593 * @registry: the #ESourceRegistry which emitted the signal
1594 * @source: the #ESource that got enabled
1596 * Emitted when an #ESource #ESource:enabled property becomes %TRUE.
1598 signals[SOURCE_ENABLED] = g_signal_new (
1600 G_OBJECT_CLASS_TYPE (object_class),
1602 G_STRUCT_OFFSET (ESourceRegistryClass, source_enabled),
1608 * ESourceRegistry::source-disabled:
1609 * @registry: the #ESourceRegistry which emitted the signal
1610 * @source: the #ESource that got disabled
1612 * Emitted when an #ESource #ESource:enabled property becomes %FALSE.
1614 signals[SOURCE_DISABLED] = g_signal_new (
1616 G_OBJECT_CLASS_TYPE (object_class),
1618 G_STRUCT_OFFSET (ESourceRegistryClass, source_disabled),
1625 e_source_registry_initable_init (GInitableIface *iface)
1627 iface->init = source_registry_initable_init;
1631 e_source_registry_init (ESourceRegistry *registry)
1633 registry->priv = E_SOURCE_REGISTRY_GET_PRIVATE (registry);
1635 /* This is so the object manager thread can schedule signal
1636 * emissions on the thread-default context for this thread. */
1637 registry->priv->main_context = g_main_context_ref_thread_default ();
1639 /* D-Bus object path -> ESource */
1640 registry->priv->object_path_table =
1641 g_hash_table_new_full (
1642 (GHashFunc) g_str_hash,
1643 (GEqualFunc) g_str_equal,
1644 (GDestroyNotify) g_free,
1645 (GDestroyNotify) g_object_unref);
1647 g_mutex_init (®istry->priv->object_path_table_lock);
1649 /* Set of UID strings */
1650 registry->priv->service_restart_table =
1651 g_hash_table_new_full (
1652 (GHashFunc) g_str_hash,
1653 (GEqualFunc) g_str_equal,
1654 (GDestroyNotify) g_free,
1655 (GDestroyNotify) NULL);
1657 g_mutex_init (®istry->priv->service_restart_table_lock);
1659 /* UID string -> ESource */
1660 registry->priv->sources = g_hash_table_new_full (
1661 (GHashFunc) g_str_hash,
1662 (GEqualFunc) g_str_equal,
1663 (GDestroyNotify) g_free,
1664 (GDestroyNotify) source_registry_unref_source);
1666 g_mutex_init (®istry->priv->sources_lock);
1668 registry->priv->settings = g_settings_new (GSETTINGS_SCHEMA);
1671 registry->priv->settings, "changed",
1672 G_CALLBACK (source_registry_settings_changed_cb), registry);
1674 g_mutex_init (®istry->priv->init_lock);
1678 * e_source_registry_new_sync:
1679 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1680 * @error: return location for a #GError, or %NULL
1682 * Creates a new #ESourceRegistry front-end for the registry D-Bus service.
1683 * If an error occurs in connecting to the D-Bus service, the function sets
1684 * @error and returns %NULL.
1686 * Since 3.12 a singleton will be returned. No strong reference is kept
1687 * internally, so it is the caller's responsibility to keep one.
1689 * Returns: a new #ESourceRegistry, or %NULL
1694 e_source_registry_new_sync (GCancellable *cancellable,
1697 ESourceRegistry *registry;
1699 /* XXX Work around http://bugzilla.gnome.org/show_bug.cgi?id=683519
1700 * until GObject's type initialization deadlock issue is fixed.
1701 * Apparently only the synchronous instantiation is affected. */
1702 g_type_ensure (G_TYPE_DBUS_CONNECTION);
1704 registry = source_registry_dup_uninitialized_singleton ();
1706 if (!g_initable_init (G_INITABLE (registry), cancellable, error))
1707 g_clear_object (®istry);
1712 /* Helper for e_source_registry_new() */
1714 source_registry_init_cb (GObject *source_object,
1715 GAsyncResult *result,
1718 GTask *task = user_data;
1719 GError *local_error = NULL;
1721 g_async_initable_init_finish (
1722 G_ASYNC_INITABLE (source_object), result, &local_error);
1724 if (local_error == NULL) {
1725 g_task_return_pointer (
1726 task, g_object_ref (source_object),
1727 (GDestroyNotify) g_object_unref);
1729 g_task_return_error (task, local_error);
1732 g_object_unref (task);
1736 * e_source_registry_new:
1737 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1738 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1740 * @user_data: (closure): data to pass to the callback function
1742 * Asynchronously creates a new #ESourceRegistry front-end for the registry
1745 * When the operation is finished, @callback will be called. You can then
1746 * call e_source_registry_new_finish() to get the result of the operation.
1748 * Since 3.12 a singleton will be returned. No strong reference is kept
1749 * internally, so it is the caller's responsibility to keep one.
1754 e_source_registry_new (GCancellable *cancellable,
1755 GAsyncReadyCallback callback,
1758 ESourceRegistry *registry;
1761 task = g_task_new (NULL, cancellable, callback, user_data);
1763 registry = source_registry_dup_uninitialized_singleton ();
1765 g_async_initable_init_async (
1766 G_ASYNC_INITABLE (registry),
1767 G_PRIORITY_DEFAULT, cancellable,
1768 source_registry_init_cb, task);
1770 g_object_unref (registry);
1774 * e_source_registry_new_finish:
1775 * @result: a #GAsyncResult
1776 * @error: return location for a #GError, or %NULL
1778 * Finishes the operation started with e_source_registry_new_finish().
1779 * If an error occurs in connecting to the D-Bus service, the function
1780 * sets @error and returns %NULL.
1782 * Returns: a new #ESourceRegistry, or %NULL
1787 e_source_registry_new_finish (GAsyncResult *result,
1790 g_return_val_if_fail (g_task_is_valid (result, NULL), NULL);
1792 return g_task_propagate_pointer (G_TASK (result), error);
1795 /* Helper for e_source_registry_authenticate() */
1797 source_registry_authenticate_thread (GSimpleAsyncResult *simple,
1799 GCancellable *cancellable)
1801 AsyncContext *async_context;
1802 GError *local_error = NULL;
1804 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1806 e_source_registry_authenticate_sync (
1807 E_SOURCE_REGISTRY (object),
1808 async_context->source,
1809 async_context->auth,
1810 cancellable, &local_error);
1812 if (local_error != NULL)
1813 g_simple_async_result_take_error (simple, local_error);
1816 /* Helper for e_source_registry_authenticate_sync() */
1818 source_registry_authenticate_respond_cb (AuthContext *auth_context)
1820 ESourceAuthenticationResult auth_result;
1821 GError *non_fatal_error = NULL;
1823 g_return_val_if_fail (auth_context->authenticating, FALSE);
1825 auth_result = auth_context->auth_result;
1827 /* Allow the next authentication attempt to proceed. */
1828 auth_context->authenticating = FALSE;
1830 /* Send the server a status update based on the authentication
1831 * result. Note, we don't really care if the D-Bus message gets
1832 * through to the server at this point. If it doesn't, the auth
1833 * session will either time out on its own or the authentication
1834 * dialog will eventually be dismissed by the user. */
1836 /* If we were cancelled from our side, we have a bit of a dilemma.
1837 * We need to tell the server to cancel the authentication session,
1838 * but that involves making a synchronous D-Bus call, which we are
1839 * not supposed to do if we know we've been cancelled. But if we
1840 * don't tell the server, the authentication session will be left
1841 * to timeout on its own (which may take minutes), and meanwhile
1842 * all other authentication requests are blocked. So choose the
1843 * lesser evil and make the synchronous call but without passing
1844 * the already-cancelled GCancellable. */
1845 if (g_cancellable_is_cancelled (auth_context->cancellable)) {
1846 e_dbus_authenticator_call_cancel_sync (
1847 auth_context->dbus_auth,
1848 NULL, &non_fatal_error);
1849 g_main_loop_quit (auth_context->main_loop);
1851 /* If an error occurred while attempting to authenticate,
1852 * tell the server to cancel the authentication session. */
1853 } else if (auth_result == E_SOURCE_AUTHENTICATION_ERROR) {
1854 e_dbus_authenticator_call_cancel_sync (
1855 auth_context->dbus_auth,
1856 auth_context->cancellable,
1858 g_main_loop_quit (auth_context->main_loop);
1860 /* If the password was accepted, let the server know so it
1861 * can close any authentication dialogs and save the user
1862 * provided password to the keyring. */
1863 } else if (auth_result == E_SOURCE_AUTHENTICATION_ACCEPTED) {
1864 e_dbus_authenticator_call_accepted_sync (
1865 auth_context->dbus_auth,
1866 auth_context->cancellable,
1868 g_main_loop_quit (auth_context->main_loop);
1870 /* If the password was rejected, let the server know so it can
1871 * indicate failure and request a different password, and then
1872 * wait for the next "response" signal. */
1874 e_dbus_authenticator_call_rejected_sync (
1875 auth_context->dbus_auth,
1876 auth_context->cancellable,
1880 /* Leave breadcrumbs if something went wrong,
1881 * but don't fail the whole operation over it. */
1882 if (non_fatal_error != NULL) {
1883 g_dbus_error_strip_remote_error (non_fatal_error);
1884 g_warning ("%s: %s", G_STRFUNC, non_fatal_error->message);
1885 g_error_free (non_fatal_error);
1891 /* Helper for e_source_registry_authenticate_sync() */
1893 source_registry_authenticate_authenticate_cb (EDBusAuthenticator *dbus_auth,
1894 const gchar *encrypted_secret,
1895 AuthContext *auth_context)
1897 GSource *idle_source;
1898 GMainContext *main_context;
1900 gboolean valid_secret;
1902 /* We should only get one secret at a time. */
1903 g_return_if_fail (!auth_context->authenticating);
1905 valid_secret = gcr_secret_exchange_receive (
1906 auth_context->secret_exchange, encrypted_secret);
1907 g_return_if_fail (valid_secret);
1909 auth_context->authenticating = TRUE;
1911 /* This avoids revealing the password in a stack trace. */
1912 password = g_string_new (
1913 gcr_secret_exchange_get_secret (
1914 auth_context->secret_exchange, NULL));
1916 /* Try authenticating with the given password. We have to
1917 * call this synchronously because some authenticators use
1918 * mutexes to serialize I/O operations and are not prepared
1919 * to make authentication attempts from a different thread.
1921 * Unfortunately this means we won't notice server-side
1922 * dismissals while the main loop is blocked. We respond
1923 * to the server from a low-priority idle callback so that
1924 * any pending "dismissed" signals get handled first. */
1926 auth_context->auth_result =
1927 e_source_authenticator_try_password_sync (
1928 auth_context->auth, password,
1929 auth_context->cancellable,
1930 auth_context->error);
1932 idle_source = g_idle_source_new ();
1933 main_context = g_main_context_get_thread_default ();
1934 g_source_set_callback (
1935 idle_source, (GSourceFunc)
1936 source_registry_authenticate_respond_cb,
1937 auth_context, NULL);
1938 g_source_attach (idle_source, main_context);
1939 g_source_unref (idle_source);
1941 g_string_free (password, TRUE);
1944 /* Helper for e_source_registry_authenticate_sync() */
1946 source_registry_authenticate_dismissed_cb (EDBusAuthenticator *dbus_auth,
1947 AuthContext *auth_context)
1949 /* Be careful not to overwrite an existing error in case this
1950 * is called after e_source_authenticator_try_password_sync()
1951 * but prior to the idle callback. */
1952 if (auth_context->auth_result != E_SOURCE_AUTHENTICATION_ERROR) {
1953 /* XXX Use a separate error code for dismissals? */
1954 g_set_error_literal (
1955 auth_context->error,
1956 G_IO_ERROR, G_IO_ERROR_CANCELLED,
1957 _("The user declined to authenticate"));
1958 auth_context->auth_result = E_SOURCE_AUTHENTICATION_ERROR;
1961 g_main_loop_quit (auth_context->main_loop);
1964 /* Helper for e_source_registry_authenticate_sync() */
1966 source_registry_authenticate_server_error_cb (EDBusAuthenticator *dbus_auth,
1968 const gchar *message,
1969 AuthContext *auth_context)
1971 /* Be careful not to overwrite an existing error */
1972 if (auth_context->auth_result != E_SOURCE_AUTHENTICATION_ERROR) {
1975 error = g_dbus_error_new_for_dbus_error (name, message);
1976 g_propagate_error (auth_context->error, error);
1978 auth_context->auth_result = E_SOURCE_AUTHENTICATION_ERROR;
1981 g_main_loop_quit (auth_context->main_loop);
1984 /* Helper for e_source_registry_authenticate_sync() */
1986 source_registry_call_authenticate_for_source (ESourceRegistry *registry,
1987 ESourceAuthenticator *auth,
1989 gchar **out_object_path,
1990 GCancellable *cancellable,
1993 ESource *collection;
1995 gchar *prompt_title = NULL;
1996 gchar *prompt_message = NULL;
1997 gchar *prompt_description = NULL;
1998 GError *local_error = NULL;
2000 g_object_ref (source);
2002 /* If the source is a member of a collection, we want to store
2003 * the password under the UID of the "collection" source so it
2004 * will apply to the entire collection.
2006 * XXX This assumes all sources in a collection share a single
2007 * password. If that turns out not to be true in all cases
2008 * we could maybe add a "SharedPassword: true/false" key to
2009 * [Collection] and apply it here.
2011 * Addendum: Assumption proven wrong. GOA's generic IMAP/SMTP
2012 * provider uses a plain ECollectionBackend (backend
2013 * name "none") with separately stored passwords for
2014 * IMAP vs SMTP. Just handle this case directly for
2015 * now, but don't rule out the "SharedPassword" idea.
2017 collection = e_source_registry_find_extension (
2018 registry, source, E_SOURCE_EXTENSION_COLLECTION);
2019 if (collection != NULL) {
2020 ESourceBackend *extension;
2021 gchar *backend_name;
2023 extension = e_source_get_extension (
2024 collection, E_SOURCE_EXTENSION_COLLECTION);
2025 backend_name = e_source_backend_dup_backend_name (extension);
2027 if (g_strcmp0 (backend_name, "none") != 0) {
2028 g_object_unref (source);
2029 source = g_object_ref (collection);
2032 g_free (backend_name);
2034 g_object_unref (collection);
2037 uid = e_source_get_uid (source);
2039 e_source_authenticator_get_prompt_strings (
2043 &prompt_description);
2045 e_dbus_source_manager_call_authenticate_sync (
2046 registry->priv->dbus_source_manager, uid,
2047 prompt_title, prompt_message, prompt_description,
2048 out_object_path, cancellable, &local_error);
2050 g_free (prompt_title);
2051 g_free (prompt_message);
2052 g_free (prompt_description);
2054 g_object_unref (source);
2056 if (local_error != NULL) {
2057 g_dbus_error_strip_remote_error (local_error);
2058 g_propagate_error (error, local_error);
2066 * e_source_registry_authenticate_sync:
2067 * @registry: an #ESourceRegistry
2068 * @source: an #ESource
2069 * @auth: an #ESourceAuthenticator
2070 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2071 * @error: return location for a #GError, or %NULL
2073 * Authenticates @source, using @auth to handle the authentication
2074 * attempts. The operation loops until authentication is successful or
2075 * the user aborts further authentication attempts. If an error occurs,
2076 * the function will set @error and return %FALSE.
2078 * Note that @source need not have a #GDBusObject, which means this
2079 * function can test authentication on a scratch #ESource.
2081 * Only backend implementations and data source editors should call this
2082 * function. The intent is for basic client applications to not have to
2083 * deal with authentication at all.
2085 * Returns: %TRUE on success, %FALSE on failure
2090 e_source_registry_authenticate_sync (ESourceRegistry *registry,
2092 ESourceAuthenticator *auth,
2093 GCancellable *cancellable,
2096 AuthContext *auth_context;
2097 GMainContext *main_context;
2098 EDBusAuthenticator *dbus_auth;
2099 gboolean without_password;
2100 gchar *encryption_key;
2101 gchar *object_path = NULL;
2102 GError *local_error = NULL;
2104 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
2105 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2106 g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATOR (auth), FALSE);
2108 /* This extracts authentication prompt details for the ESource
2109 * before initiating an authentication session with the server,
2110 * so split it out of the main algorithm for clarity's sake. */
2111 source_registry_call_authenticate_for_source (
2112 registry, auth, source, &object_path,
2113 cancellable, &local_error);
2115 if (local_error != NULL) {
2116 g_warn_if_fail (object_path == NULL);
2117 g_propagate_error (error, local_error);
2121 g_return_val_if_fail (object_path != NULL, FALSE);
2123 main_context = g_main_context_new ();
2124 g_main_context_push_thread_default (main_context);
2126 dbus_auth = e_dbus_authenticator_proxy_new_for_bus_sync (
2128 G_DBUS_PROXY_FLAGS_NONE,
2129 SOURCES_DBUS_SERVICE_NAME,
2130 object_path, cancellable, &local_error);
2132 g_free (object_path);
2135 g_return_val_if_fail (
2136 ((dbus_auth != NULL) && (local_error == NULL)) ||
2137 ((dbus_auth == NULL) && (local_error != NULL)), FALSE);
2139 if (local_error != NULL)
2142 without_password = e_source_authenticator_get_without_password (auth);
2143 e_dbus_authenticator_set_without_password (dbus_auth, without_password);
2145 auth_context = g_slice_new0 (AuthContext);
2146 auth_context->auth = g_object_ref (auth);
2147 auth_context->dbus_auth = dbus_auth; /* takes ownership */
2148 auth_context->main_loop = g_main_loop_new (main_context, FALSE);
2149 auth_context->error = &local_error;
2151 /* This just needs to be something other than
2152 * E_SOURCE_AUTHENTICATION_ERROR so we don't trip
2153 * up source_registry_authenticate_dismissed_cb(). */
2154 auth_context->auth_result = E_SOURCE_AUTHENTICATION_REJECTED;
2156 if (G_IS_CANCELLABLE (cancellable))
2157 auth_context->cancellable = g_object_ref (cancellable);
2159 auth_context->secret_exchange =
2160 gcr_secret_exchange_new (GCR_SECRET_EXCHANGE_PROTOCOL_1);
2163 dbus_auth, "authenticate",
2164 G_CALLBACK (source_registry_authenticate_authenticate_cb),
2168 dbus_auth, "dismissed",
2169 G_CALLBACK (source_registry_authenticate_dismissed_cb),
2173 dbus_auth, "server-error",
2174 G_CALLBACK (source_registry_authenticate_server_error_cb),
2177 encryption_key = gcr_secret_exchange_begin (
2178 auth_context->secret_exchange);
2180 /* Signal the D-Bus server that we're ready to begin the
2181 * authentication session. This must happen AFTER we've
2182 * connected to the response signal since the server may
2183 * already have a response ready and waiting for us. */
2184 e_dbus_authenticator_call_ready_sync (
2185 dbus_auth, encryption_key, cancellable, &local_error);
2187 g_free (encryption_key);
2189 if (local_error == NULL)
2190 g_main_loop_run (auth_context->main_loop);
2192 auth_context_free (auth_context);
2195 g_main_context_pop_thread_default (main_context);
2197 /* Make sure the main_context doesn't have pending operations;
2198 * workarounds https://bugzilla.gnome.org/show_bug.cgi?id=690126 */
2199 while (g_main_context_pending (main_context))
2200 g_main_context_iteration (main_context, FALSE);
2202 g_main_context_unref (main_context);
2204 if (local_error != NULL) {
2205 g_dbus_error_strip_remote_error (local_error);
2206 g_propagate_error (error, local_error);
2214 * e_source_registry_authenticate:
2215 * @registry: an #ESourceRegistry
2216 * @source: an #ESource
2217 * @auth: an #ESourceAuthenticator
2218 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2219 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2221 * @user_data: (closure): data to pass to the callback function
2223 * Asynchronously authenticates @source, using @auth to handle the
2224 * authentication attempts. The operation loops until authentication
2225 * is successful or the user aborts further authentication attempts.
2227 * Note that @source need not have a #GDBusObject, which means this
2228 * function can test authentication on a scratch #ESource.
2230 * When the operation is finished, @callback will be called. You can then
2231 * call e_source_registry_authenticate_finish() to get the result of the
2234 * Only backend implementations and data source editors should call this
2235 * function. The intent is for basic client applications to not have to
2236 * deal with authentication at all.
2241 e_source_registry_authenticate (ESourceRegistry *registry,
2243 ESourceAuthenticator *auth,
2244 GCancellable *cancellable,
2245 GAsyncReadyCallback callback,
2248 GSimpleAsyncResult *simple;
2249 AsyncContext *async_context;
2251 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2252 g_return_if_fail (E_IS_SOURCE (source));
2253 g_return_if_fail (E_IS_SOURCE_AUTHENTICATOR (auth));
2255 async_context = g_slice_new0 (AsyncContext);
2256 async_context->source = g_object_ref (source);
2257 async_context->auth = g_object_ref (auth);
2259 simple = g_simple_async_result_new (
2260 G_OBJECT (registry), callback, user_data,
2261 e_source_registry_authenticate);
2263 g_simple_async_result_set_check_cancellable (simple, cancellable);
2265 g_simple_async_result_set_op_res_gpointer (
2266 simple, async_context, (GDestroyNotify) async_context_free);
2268 g_simple_async_result_run_in_thread (
2269 simple, source_registry_authenticate_thread,
2270 G_PRIORITY_DEFAULT, cancellable);
2272 g_object_unref (simple);
2276 * e_source_registry_authenticate_finish:
2277 * @registry: an #ESourceRegistry
2278 * @result: a #GAsyncResult
2279 * @error: return location for a #GError, or %NULL
2281 * Finishes the operation started with e_source_registry_authenticate().
2282 * If an error occurred, the function will set @error and return %FALSE.
2284 * Returns: %TRUE on success, %FALSE on failure
2289 e_source_registry_authenticate_finish (ESourceRegistry *registry,
2290 GAsyncResult *result,
2293 GSimpleAsyncResult *simple;
2295 g_return_val_if_fail (
2296 g_simple_async_result_is_valid (
2297 result, G_OBJECT (registry),
2298 e_source_registry_authenticate), FALSE);
2300 simple = G_SIMPLE_ASYNC_RESULT (result);
2302 /* Assume success unless a GError is set. */
2303 return !g_simple_async_result_propagate_error (simple, error);
2306 /* Helper for e_source_registry_commit_source() */
2308 source_registry_commit_source_thread (GSimpleAsyncResult *simple,
2310 GCancellable *cancellable)
2312 AsyncContext *async_context;
2313 GError *local_error = NULL;
2315 async_context = g_simple_async_result_get_op_res_gpointer (simple);
2317 e_source_registry_commit_source_sync (
2318 E_SOURCE_REGISTRY (object),
2319 async_context->source,
2320 cancellable, &local_error);
2322 if (local_error != NULL)
2323 g_simple_async_result_take_error (simple, local_error);
2327 * e_source_registry_commit_source_sync:
2328 * @registry: an #ESourceRegistry
2329 * @source: an #ESource with changes to commit
2330 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2331 * @error: return location for #GError, or %NULL
2333 * This is a convenience function intended for use with graphical
2334 * #ESource editors. Call this function when the user is finished
2335 * making changes to @source.
2337 * If @source has a #GDBusObject, its contents are submitted to the D-Bus
2338 * service through e_source_write_sync().
2340 * If @source does NOT have a #GDBusObject (implying it's a scratch
2341 * #ESource), its contents are submitted to the D-Bus service through
2342 * either e_source_remote_create_sync() if @source is to be a collection
2343 * member, or e_source_registry_create_sources_sync() if @source to be an
2344 * independent data source.
2346 * If an error occurs, the function will set @error and return %FALSE.
2348 * Returns: %TRUE on success, %FALSE on failure
2353 e_source_registry_commit_source_sync (ESourceRegistry *registry,
2355 GCancellable *cancellable,
2358 GDBusObject *dbus_object;
2359 ESource *collection_source;
2360 gboolean collection_member;
2363 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
2364 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2366 dbus_object = e_source_ref_dbus_object (source);
2368 collection_source = e_source_registry_find_extension (
2369 registry, source, E_SOURCE_EXTENSION_COLLECTION);
2372 (collection_source != NULL) &&
2373 (collection_source != source);
2375 if (dbus_object != NULL) {
2376 success = e_source_write_sync (source, cancellable, error);
2377 g_object_unref (dbus_object);
2379 } else if (collection_member) {
2380 success = e_source_remote_create_sync (
2381 collection_source, source, cancellable, error);
2384 GList *list = g_list_prepend (NULL, source);
2385 success = e_source_registry_create_sources_sync (
2386 registry, list, cancellable, error);
2390 if (collection_source != NULL)
2391 g_object_unref (collection_source);
2397 * e_source_registry_commit_source:
2398 * @registry: an #ESourceRegistry
2399 * @source: an #ESource with changes to commit
2400 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2401 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2403 * @user_data: (closure): data to pass to the callback function
2405 * See e_source_registry_commit_source_sync() for details.
2407 * When the operation is finished, @callback will be called. You can then
2408 * call e_source_registry_commit_source_finish() to get the result of the
2414 e_source_registry_commit_source (ESourceRegistry *registry,
2416 GCancellable *cancellable,
2417 GAsyncReadyCallback callback,
2420 GSimpleAsyncResult *simple;
2421 AsyncContext *async_context;
2423 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2424 g_return_if_fail (E_IS_SOURCE (source));
2426 async_context = g_slice_new0 (AsyncContext);
2427 async_context->source = g_object_ref (source);
2429 simple = g_simple_async_result_new (
2430 G_OBJECT (registry), callback, user_data,
2431 e_source_registry_commit_source);
2433 g_simple_async_result_set_check_cancellable (simple, cancellable);
2435 g_simple_async_result_set_op_res_gpointer (
2436 simple, async_context, (GDestroyNotify) async_context_free);
2438 g_simple_async_result_run_in_thread (
2439 simple, source_registry_commit_source_thread,
2440 G_PRIORITY_DEFAULT, cancellable);
2442 g_object_unref (simple);
2446 * e_source_registry_commit_source_finish:
2447 * @registry: an #ESourceRegistry
2448 * @result: a #GAsyncResult
2449 * @error: return location for a #GError, or %NULL
2451 * Finishes the operation started with e_source_registry_commit_source().
2453 * If an error occurred, the function will set @error and return %FALSE.
2455 * Returns: %TRUE on success, %FALSE on failure
2460 e_source_registry_commit_source_finish (ESourceRegistry *registry,
2461 GAsyncResult *result,
2464 GSimpleAsyncResult *simple;
2466 g_return_val_if_fail (
2467 g_simple_async_result_is_valid (
2468 result, G_OBJECT (registry),
2469 e_source_registry_commit_source), FALSE);
2471 simple = G_SIMPLE_ASYNC_RESULT (result);
2473 /* Assume success unless a GError is set. */
2474 return !g_simple_async_result_propagate_error (simple, error);
2477 /* Helper for e_source_registry_create_sources() */
2479 source_registry_create_sources_thread (GSimpleAsyncResult *simple,
2481 GCancellable *cancellable)
2483 AsyncContext *async_context;
2484 GError *local_error = NULL;
2486 async_context = g_simple_async_result_get_op_res_gpointer (simple);
2488 e_source_registry_create_sources_sync (
2489 E_SOURCE_REGISTRY (object),
2490 async_context->list_of_sources,
2491 cancellable, &local_error);
2493 if (local_error != NULL)
2494 g_simple_async_result_take_error (simple, local_error);
2497 /* Helper for e_source_registry_create_sources_sync() */
2499 source_registry_create_sources_main_loop_quit_cb (gpointer user_data)
2501 GMainLoop *main_loop = user_data;
2503 g_main_loop_quit (main_loop);
2508 /* Helper for e_source_registry_create_sources_sync() */
2510 source_registry_create_sources_object_added_cb (GDBusObjectManager *object_manager,
2511 GDBusObject *dbus_object,
2512 CreateContext *create_context)
2516 uid = source_registry_dbus_object_dup_uid (dbus_object);
2519 g_hash_table_remove (create_context->pending_uids, uid);
2523 /* The hash table will be empty when all of the expected
2524 * GDBusObjects have been added to the GDBusObjectManager. */
2525 if (g_hash_table_size (create_context->pending_uids) == 0) {
2526 GSource *idle_source;
2528 idle_source = g_idle_source_new ();
2529 g_source_set_callback (
2531 source_registry_create_sources_main_loop_quit_cb,
2532 g_main_loop_ref (create_context->main_loop),
2533 (GDestroyNotify) g_main_loop_unref);
2534 g_source_attach (idle_source, create_context->main_context);
2535 g_source_unref (idle_source);
2540 * e_source_registry_create_sources_sync:
2541 * @registry: an #ESourceRegistry
2542 * @list_of_sources: (element-type ESource): a list of #ESource instances with
2544 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2545 * @error: return location for a #GError, or %NULL
2547 * Requests the D-Bus service create new key files for each #ESource in
2548 * @list_of_sources. Each list element must be a scratch #ESource with
2551 * If an error occurs, the function will set @error and return %FALSE.
2553 * Returns: %TRUE on success, %FALSE on failure
2558 e_source_registry_create_sources_sync (ESourceRegistry *registry,
2559 GList *list_of_sources,
2560 GCancellable *cancellable,
2563 CreateContext *create_context;
2564 GVariantBuilder builder;
2567 gulong object_added_id;
2568 GError *local_error = NULL;
2570 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
2572 /* Verify the list elements are all ESources. */
2573 for (link = list_of_sources; link != NULL; link = g_list_next (link))
2574 g_return_val_if_fail (E_IS_SOURCE (link->data), FALSE);
2576 create_context = create_context_new ();
2577 g_main_context_push_thread_default (create_context->main_context);
2579 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
2581 for (link = list_of_sources; link != NULL; link = g_list_next (link)) {
2586 source = E_SOURCE (link->data);
2587 uid = e_source_dup_uid (source);
2589 /* Takes ownership of the UID string. */
2590 g_hash_table_add (create_context->pending_uids, uid);
2592 source_data = e_source_to_string (source, NULL);
2593 g_variant_builder_add (&builder, "{ss}", uid, source_data);
2594 g_free (source_data);
2597 variant = g_variant_builder_end (&builder);
2599 /* Use G_CONNECT_AFTER so source_registry_object_added_cb()
2600 * runs first and actually adds the ESource to the internal
2601 * hash table before we go quitting our main loop. */
2602 object_added_id = g_signal_connect_after (
2603 registry->priv->dbus_object_manager, "object-added",
2604 G_CALLBACK (source_registry_create_sources_object_added_cb),
2607 /* This function sinks the floating GVariant reference. */
2608 e_dbus_source_manager_call_create_sources_sync (
2609 registry->priv->dbus_source_manager,
2610 variant, cancellable, &local_error);
2612 g_variant_builder_clear (&builder);
2614 /* Wait for an "object-added" signal for each created ESource.
2615 * But also set a short timeout to avoid getting stuck here in
2616 * case the registry service adds sources to its orphan table,
2617 * which prevents them from being exported over D-Bus. */
2618 if (local_error == NULL) {
2619 GSource *timeout_source;
2621 timeout_source = g_timeout_source_new_seconds (2);
2622 g_source_set_callback (
2624 source_registry_create_sources_main_loop_quit_cb,
2625 g_main_loop_ref (create_context->main_loop),
2626 (GDestroyNotify) g_main_loop_unref);
2627 g_source_attach (timeout_source, create_context->main_context);
2628 g_source_unref (timeout_source);
2630 g_main_loop_run (create_context->main_loop);
2633 g_signal_handler_disconnect (
2634 registry->priv->dbus_object_manager, object_added_id);
2636 g_main_context_pop_thread_default (create_context->main_context);
2637 create_context_free (create_context);
2639 if (local_error != NULL) {
2640 g_dbus_error_strip_remote_error (local_error);
2641 g_propagate_error (error, local_error);
2649 * e_source_registry_create_sources:
2650 * @registry: an #ESourceRegistry
2651 * @list_of_sources: (element-type ESource): a list of #ESource instances with
2653 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2654 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2656 * @user_data: (closure): data to pass to the callback function
2658 * Asynchronously requests the D-Bus service create new key files for each
2659 * #ESource in @list_of_sources. Each list element must be a scratch
2660 * #ESource with no #GDBusObject.
2662 * When the operation is finished, @callback will be called. You can then
2663 * call e_source_registry_create_sources_finish() to get the result of the
2669 e_source_registry_create_sources (ESourceRegistry *registry,
2670 GList *list_of_sources,
2671 GCancellable *cancellable,
2672 GAsyncReadyCallback callback,
2675 GSimpleAsyncResult *simple;
2676 AsyncContext *async_context;
2679 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2681 /* Verify the list elements are all ESources. */
2682 for (link = list_of_sources; link != NULL; link = g_list_next (link))
2683 g_return_if_fail (E_IS_SOURCE (link->data));
2685 async_context = g_slice_new0 (AsyncContext);
2686 async_context->list_of_sources = g_list_copy (list_of_sources);
2689 async_context->list_of_sources,
2690 (GFunc) g_object_ref, NULL);
2692 simple = g_simple_async_result_new (
2693 G_OBJECT (registry), callback, user_data,
2694 e_source_registry_create_sources);
2696 g_simple_async_result_set_check_cancellable (simple, cancellable);
2698 g_simple_async_result_set_op_res_gpointer (
2699 simple, async_context, (GDestroyNotify) async_context_free);
2701 g_simple_async_result_run_in_thread (
2702 simple, source_registry_create_sources_thread,
2703 G_PRIORITY_DEFAULT, cancellable);
2705 g_object_unref (simple);
2709 * e_source_registry_create_sources_finish:
2710 * @registry: an #ESourceRegistry
2711 * @result: a #GAsyncResult
2712 * @error: return location for a #GError, or %NULL
2714 * Finishes the operation started with e_source_registry_create_sources().
2716 * If an error occurred, the function will set @error and return %FALSE.
2718 * Returns: %TRUE on success, %FALSE on failure
2723 e_source_registry_create_sources_finish (ESourceRegistry *registry,
2724 GAsyncResult *result,
2727 GSimpleAsyncResult *simple;
2729 g_return_val_if_fail (
2730 g_simple_async_result_is_valid (
2731 result, G_OBJECT (registry),
2732 e_source_registry_create_sources), FALSE);
2734 simple = G_SIMPLE_ASYNC_RESULT (result);
2736 /* Assume success unless a GError is set. */
2737 return !g_simple_async_result_propagate_error (simple, error);
2741 * e_source_registry_ref_source:
2742 * @registry: an #ESourceRegistry
2743 * @uid: a unique identifier string
2745 * Looks up an #ESource in @registry by its unique identifier string.
2747 * The returned #ESource is referenced for thread-safety and must be
2748 * unreferenced with g_object_unref() when finished with it.
2750 * Returns: (transfer full): an #ESource, or %NULL if no match was found
2755 e_source_registry_ref_source (ESourceRegistry *registry,
2758 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2759 g_return_val_if_fail (uid != NULL, NULL);
2761 return source_registry_sources_lookup (registry, uid);
2765 * e_source_registry_list_sources:
2766 * @registry: an #ESourceRegistry
2767 * @extension_name: (allow-none): an extension name, or %NULL
2769 * Returns a list of registered sources, sorted by display name. If
2770 * @extension_name is given, restrict the list to sources having that
2773 * The sources returned in the list are referenced for thread-safety.
2774 * They must each be unreferenced with g_object_unref() when finished
2775 * with them. Free the returned list itself with g_list_free().
2777 * An easy way to free the list properly in one step is as follows:
2780 * g_list_free_full (list, g_object_unref);
2783 * Returns: (element-type ESource) (transfer full): a sorted list of sources
2788 e_source_registry_list_sources (ESourceRegistry *registry,
2789 const gchar *extension_name)
2792 GQueue trash = G_QUEUE_INIT;
2794 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2796 list = g_list_sort (
2797 source_registry_sources_get_values (registry),
2798 (GCompareFunc) e_source_compare_by_display_name);
2800 if (extension_name == NULL)
2803 for (link = list; link != NULL; link = g_list_next (link)) {
2804 ESource *source = E_SOURCE (link->data);
2806 if (!e_source_has_extension (source, extension_name)) {
2807 g_queue_push_tail (&trash, link);
2808 g_object_unref (source);
2812 /* We do want pop_head() here, not pop_head_link(). */
2813 while ((link = g_queue_pop_head (&trash)) != NULL)
2814 list = g_list_delete_link (list, link);
2820 * e_source_registry_list_enabled:
2821 * @registry: an #ESourceRegistry
2822 * @extension_name: (allow-none): an extension name, or %NULL
2824 * Similar to e_source_registry_list_sources(), but returns only enabled
2825 * sources according to e_source_registry_check_enabled().
2827 * The sources returned in the list are referenced for thread-safety.
2828 * They must each be unreferenced with g_object_unref() when finished
2829 * with them. Free the returned list itself with g_list_free().
2831 * An easy way to free the list properly in one step is as follows:
2834 * g_list_free_full (list, g_object_unref);
2837 * Returns: (element-type ESource) (transfer full): a sorted list of sources
2842 e_source_registry_list_enabled (ESourceRegistry *registry,
2843 const gchar *extension_name)
2846 GQueue trash = G_QUEUE_INIT;
2848 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2850 list = e_source_registry_list_sources (registry, extension_name);
2852 for (link = list; link != NULL; link = g_list_next (link)) {
2853 ESource *source = E_SOURCE (link->data);
2855 if (!e_source_registry_check_enabled (registry, source)) {
2856 g_queue_push_tail (&trash, link);
2857 g_object_unref (source);
2861 /* We do want pop_head() here, not pop_head_link(). */
2862 while ((link = g_queue_pop_head (&trash)) != NULL)
2863 list = g_list_delete_link (list, link);
2869 * e_source_registry_find_extension:
2870 * @registry: an #ESourceRegistry
2871 * @source: an #ESource
2872 * @extension_name: the extension name to find
2874 * Examines @source and its ancestors and returns the "deepest" #ESource
2875 * having an #ESourceExtension with the given @extension_name. If neither
2876 * @source nor any of its ancestors have such an extension, the function
2879 * This function is useful in cases when an #ESourceExtension is meant to
2880 * apply to both the #ESource it belongs to and the #ESource's descendants.
2882 * A common example is the #ESourceCollection extension, where descendants
2883 * of an #ESource having an #ESourceCollection extension are implied to be
2884 * members of that collection. In that example, this function can be used
2885 * to test whether @source is a member of a collection.
2887 * The returned #ESource is referenced for thread-safety and must be
2888 * unreferenced with g_object_unref() when finished with it.
2890 * Note the function returns the #ESource containing the #ESourceExtension
2891 * instead of the #ESourceExtension itself because extension instances are
2892 * not to be referenced directly (see e_source_get_extension()).
2894 * Returns: (transfer full): an #ESource, or %NULL if no match was found
2899 e_source_registry_find_extension (ESourceRegistry *registry,
2901 const gchar *extension_name)
2903 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2904 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2905 g_return_val_if_fail (extension_name != NULL, NULL);
2907 g_object_ref (source);
2909 while (!e_source_has_extension (source, extension_name)) {
2912 uid = e_source_dup_parent (source);
2914 g_object_unref (source);
2918 source = e_source_registry_ref_source (registry, uid);
2930 * e_source_registry_check_enabled:
2931 * @registry: an #ESourceRegistry
2932 * @source: an #ESource
2934 * Determines whether @source is "effectively" enabled by examining its
2935 * own #ESource:enabled property as well as those of its ancestors in the
2936 * #ESource hierarchy. If all examined #ESource:enabled properties are
2937 * %TRUE, then the function returns %TRUE. If any are %FALSE, then the
2938 * function returns %FALSE.
2940 * Use this function instead of e_source_get_enabled() to determine
2941 * things like whether to display an #ESource in a user interface or
2942 * whether to act on the data set described by the #ESource.
2944 * Returns: whether @source is "effectively" enabled
2949 e_source_registry_check_enabled (ESourceRegistry *registry,
2955 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
2956 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2958 enabled = e_source_get_enabled (source);
2959 parent_uid = e_source_dup_parent (source);
2961 while (enabled && parent_uid != NULL) {
2964 parent = e_source_registry_ref_source (registry, parent_uid);
2966 g_free (parent_uid);
2969 if (parent != NULL) {
2970 enabled = e_source_get_enabled (parent);
2971 parent_uid = e_source_dup_parent (parent);
2972 g_object_unref (parent);
2976 g_free (parent_uid);
2981 /* Helper for e_source_registry_build_display_tree() */
2983 source_registry_compare_nodes (GNode *node_a,
2986 ESource *source_a = E_SOURCE (node_a->data);
2987 ESource *source_b = E_SOURCE (node_b->data);
2988 const gchar *uid_a, *uid_b;
2990 uid_a = e_source_get_uid (source_a);
2991 uid_b = e_source_get_uid (source_b);
2993 /* Sanity check, with runtime warnings. */
2994 if (uid_a == NULL) {
2995 g_warn_if_reached ();
2998 if (uid_b == NULL) {
2999 g_warn_if_reached ();
3003 /* The built-in "local-stub" source comes first at depth 1. */
3005 if (g_strcmp0 (uid_a, "local-stub") == 0)
3008 if (g_strcmp0 (uid_b, "local-stub") == 0)
3011 /* The built-in "system-*" sources come first at depth 2. */
3013 if (g_str_has_prefix (uid_a, "system-"))
3016 if (g_str_has_prefix (uid_b, "system-"))
3019 return e_source_compare_by_display_name (source_a, source_b);
3022 /* Helper for e_source_registry_build_display_tree() */
3024 source_registry_prune_nodes (GNode *node,
3025 const gchar *extension_name)
3027 GQueue queue = G_QUEUE_INIT;
3030 /* Unlink all the child nodes and place them in a queue. */
3031 while ((child_node = g_node_first_child (node)) != NULL) {
3032 g_node_unlink (child_node);
3033 g_queue_push_tail (&queue, child_node);
3036 /* Sort the queue by source name. */
3038 &queue, (GCompareDataFunc)
3039 source_registry_compare_nodes, NULL);
3041 /* Pop nodes off the head of the queue until the queue is empty.
3042 * If the node has either its own children or the given extension
3043 * name, put it back under the parent node (preserving the sorted
3044 * order). Otherwise delete the node and its descendants. */
3045 while ((child_node = g_queue_pop_head (&queue)) != NULL) {
3046 ESource *child = E_SOURCE (child_node->data);
3047 gboolean append_child_node = FALSE;
3049 if (extension_name == NULL)
3050 append_child_node = e_source_get_enabled (child);
3052 else if (e_source_has_extension (child, extension_name))
3053 append_child_node = e_source_get_enabled (child);
3055 else if (g_node_first_child (child_node) != NULL)
3056 append_child_node = e_source_get_enabled (child);
3058 if (append_child_node)
3059 g_node_append (node, child_node);
3061 e_source_registry_free_display_tree (child_node);
3068 * e_source_registry_build_display_tree:
3069 * @registry: an #ESourceRegistry
3070 * @extension_name: (allow-none): an extension name, or %NULL
3072 * Returns a single #GNode tree of registered sources that can be used to
3073 * populate a #GtkTreeModel. (The root #GNode is just an empty placeholder.)
3075 * Similar to e_source_registry_list_sources(), an @extension_name can be
3076 * given to restrict the tree to sources having that extension name. Parents
3077 * of matched sources are included in the tree regardless of whether they have
3078 * an extension named @extension_name.
3080 * Disabled leaf nodes are automatically excluded from the #GNode tree.
3082 * The sources returned in the tree are referenced for thread-safety.
3083 * They must each be unreferenced with g_object_unref() when finished
3084 * with them. Free the returned tree itself with g_node_destroy().
3085 * For convenience, e_source_registry_free_display_tree() does all
3088 * Returns: (element-type ESource) (transfer full): a tree of sources,
3089 * arranged for display
3094 e_source_registry_build_display_tree (ESourceRegistry *registry,
3095 const gchar *extension_name)
3099 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3101 /* Assemble all data sources into a tree. */
3102 root = source_registry_sources_build_tree (registry);
3104 /* Prune unwanted nodes from the copied source trees.
3105 * This must be done in "post" order (children first)
3106 * since it reorders and deletes child nodes. */
3108 root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
3109 (GNodeTraverseFunc) source_registry_prune_nodes,
3110 (gpointer) extension_name);
3115 /* Helper for e_source_registry_free_display_tree() */
3117 source_registry_unref_nodes (GNode *node)
3119 while (node != NULL) {
3120 if (node->children != NULL)
3121 source_registry_unref_nodes (node->children);
3122 if (node->data != NULL)
3123 g_object_unref (node->data);
3129 * e_source_registry_free_display_tree:
3130 * @display_tree: a tree of sources, arranged for display
3132 * Convenience function to free a #GNode tree of registered
3133 * sources created by e_source_registry_build_display_tree().
3138 e_source_registry_free_display_tree (GNode *display_tree)
3140 g_return_if_fail (display_tree != NULL);
3142 /* XXX This would be easier if GLib had something like
3143 * g_node_destroy_full() which took a GDestroyNotify.
3144 * Then the tree would not have to be traversed twice. */
3146 source_registry_unref_nodes (display_tree);
3147 g_node_destroy (display_tree);
3151 * e_source_registry_dup_unique_display_name:
3152 * @registry: an #ESourceRegistry
3153 * @source: an #ESource
3154 * @extension_name: (allow-none): an extension name, or %NULL
3156 * Compares @source's #ESource:display-name against other sources having
3157 * an #ESourceExtension named @extension_name, if given, or else against
3158 * all other sources in the @registry.
3160 * If @sources's #ESource:display-name is unique among these other sources,
3161 * the function will return the #ESource:display-name verbatim. Otherwise
3162 * the function will construct a string that includes the @sources's own
3163 * #ESource:display-name as well as those of its ancestors.
3165 * The function's return value is intended to be used in messages shown to
3166 * the user to help clarify which source is being referred to. It assumes
3167 * @source's #ESource:display-name is at least unique among its siblings.
3169 * Free the returned string with g_free() when finished with it.
3171 * Returns: a unique display name for @source
3176 e_source_registry_dup_unique_display_name (ESourceRegistry *registry,
3178 const gchar *extension_name)
3182 gchar *display_name;
3183 gboolean need_clarification = FALSE;
3185 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3186 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3188 list = e_source_registry_list_sources (registry, extension_name);
3190 /* Remove the input source from the list, if present. */
3191 link = g_list_find (list, source);
3193 g_object_unref (link->data);
3194 list = g_list_delete_link (list, link);
3197 /* Now find another source with a matching display name. */
3198 link = g_list_find_custom (
3199 list, source, (GCompareFunc)
3200 e_source_compare_by_display_name);
3202 need_clarification = (link != NULL);
3204 g_list_free_full (list, (GDestroyNotify) g_object_unref);
3207 display_name = e_source_dup_display_name (source);
3208 buffer = g_string_new (display_name);
3209 g_free (display_name);
3211 if (need_clarification) {
3212 /* Build a list of ancestor sources. */
3214 g_object_ref (source);
3216 while (source != NULL) {
3219 parent_uid = e_source_dup_parent (source);
3221 g_object_unref (source);
3224 if (parent_uid != NULL) {
3225 source = e_source_registry_ref_source (
3226 registry, parent_uid);
3227 g_free (parent_uid);
3230 if (source != NULL) {
3231 g_object_ref (source);
3232 list = g_list_prepend (list, source);
3236 /* Display the ancestor names from the most distant
3237 * ancestor to the input source's immediate parent. */
3240 g_string_append (buffer, " (");
3242 for (link = list; link != NULL; link = g_list_next (link)) {
3244 g_string_append (buffer, " / ");
3246 source = E_SOURCE (link->data);
3247 display_name = e_source_dup_display_name (source);
3248 g_string_append (buffer, display_name);
3249 g_free (display_name);
3253 g_string_append (buffer, ")");
3255 g_list_free_full (list, (GDestroyNotify) g_object_unref);
3258 return g_string_free (buffer, FALSE);
3261 /* Helper for e_source_registry_debug_dump() */
3263 source_registry_debug_dump_cb (GNode *node)
3267 /* Root node is an empty placeholder. */
3268 if (G_NODE_IS_ROOT (node))
3271 depth = g_node_depth (node);
3272 for (ii = 2; ii < depth; ii++)
3275 if (E_IS_SOURCE (node->data)) {
3276 ESource *source = E_SOURCE (node->data);
3277 g_print ("\"%s\" ", e_source_get_display_name (source));
3278 g_print ("(%s)", e_source_get_uid (source));
3287 * e_source_registry_debug_dump:
3288 * @registry: an #ESourceRegistry
3289 * @extension_name: (allow-none): an extension name, or %NULL
3291 * Handy debugging function that uses e_source_registry_build_display_tree()
3292 * to print a tree of registered sources to standard output.
3297 e_source_registry_debug_dump (ESourceRegistry *registry,
3298 const gchar *extension_name)
3302 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3304 root = e_source_registry_build_display_tree (registry, extension_name);
3307 root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
3308 (GNodeTraverseFunc) source_registry_debug_dump_cb, NULL);
3310 e_source_registry_free_display_tree (root);
3314 * e_source_registry_ref_builtin_address_book:
3315 * @registry: an #ESourceRegistry
3317 * Returns the built-in address book #ESource.
3319 * This #ESource is always present and makes for a safe fallback.
3321 * The returned #ESource is referenced for thread-safety and must be
3322 * unreferenced with g_object_unref() when finished with it.
3324 * Returns: (transfer full): the built-in address book #ESource
3329 e_source_registry_ref_builtin_address_book (ESourceRegistry *registry)
3334 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3336 uid = E_SOURCE_BUILTIN_ADDRESS_BOOK_UID;
3337 source = e_source_registry_ref_source (registry, uid);
3338 g_return_val_if_fail (source != NULL, NULL);
3344 * e_source_registry_ref_builtin_calendar:
3345 * @registry: an #ESourceRegistry
3347 * Returns the built-in calendar #ESource.
3349 * This #ESource is always present and makes for a safe fallback.
3351 * The returned #ESource is referenced for thread-safety and must be
3352 * unreferenced with g_object_unref() when finished with it.
3354 * Returns: (transfer full): the built-in calendar #ESource
3359 e_source_registry_ref_builtin_calendar (ESourceRegistry *registry)
3364 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3366 uid = E_SOURCE_BUILTIN_CALENDAR_UID;
3367 source = e_source_registry_ref_source (registry, uid);
3368 g_return_val_if_fail (source != NULL, NULL);
3374 * e_source_registry_ref_builtin_mail_account:
3375 * @registry: an #ESourceRegistry
3377 * Returns the built-in mail account #ESource.
3379 * This #ESource is always present and makes for a safe fallback.
3381 * The returned #ESource is referenced for thread-safety and must be
3382 * unreferenced with g_object_unref() when finished with it.
3384 * Returns: (transfer full): the built-in mail account #ESource
3389 e_source_registry_ref_builtin_mail_account (ESourceRegistry *registry)
3394 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3396 uid = E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID;
3397 source = e_source_registry_ref_source (registry, uid);
3398 g_return_val_if_fail (source != NULL, NULL);
3404 * e_source_registry_ref_builtin_memo_list:
3405 * @registry: an #ESourceRegistry
3407 * Returns the built-in memo list #ESource.
3409 * This #ESource is always present and makes for a safe fallback.
3411 * The returned #ESource is referenced for thread-safety and must be
3412 * unreferenced with g_object_unref() when finished with it.
3414 * Returns: (transfer full): the built-in memo list #ESource
3419 e_source_registry_ref_builtin_memo_list (ESourceRegistry *registry)
3424 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3426 uid = E_SOURCE_BUILTIN_MEMO_LIST_UID;
3427 source = e_source_registry_ref_source (registry, uid);
3428 g_return_val_if_fail (source != NULL, NULL);
3434 * e_source_registry_ref_builtin_proxy:
3435 * @registry: an #ESourceRegistry
3437 * Returns the built-in proxy profile #ESource.
3439 * This #ESource is always present and makes for a safe fallback.
3441 * The returned #ESource is referenced for thread-safety and must be
3442 * unreferenced with g_object_unref() when finished with it.
3444 * Returns: (transfer full): the built-in proxy profile #ESource
3449 e_source_registry_ref_builtin_proxy (ESourceRegistry *registry)
3454 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3456 uid = E_SOURCE_BUILTIN_PROXY_UID;
3457 source = e_source_registry_ref_source (registry, uid);
3458 g_return_val_if_fail (source != NULL, NULL);
3464 * e_source_registry_ref_builtin_task_list:
3465 * @registry: an #ESourceRegistry
3467 * Returns the built-in task list #ESource.
3469 * This #ESource is always present and makes for a safe fallback.
3471 * The returned #ESource is referenced for thread-safety and must be
3472 * unreferenced with g_object_unref() when finished with it.
3474 * Returns: (transfer full): the built-in task list #ESource
3479 e_source_registry_ref_builtin_task_list (ESourceRegistry *registry)
3484 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3486 uid = E_SOURCE_BUILTIN_TASK_LIST_UID;
3487 source = e_source_registry_ref_source (registry, uid);
3488 g_return_val_if_fail (source != NULL, NULL);
3494 * e_source_registry_ref_default_address_book:
3495 * @registry: an #ESourceRegistry
3497 * Returns the #ESource most recently passed to
3498 * e_source_registry_set_default_address_book() either in this session
3499 * or a previous session, or else falls back to the built-in address book.
3501 * The returned #ESource is referenced for thread-safety and must be
3502 * unreferenced with g_object_unref() when finished with it.
3504 * Returns: (transfer full): the default address book #ESource
3509 e_source_registry_ref_default_address_book (ESourceRegistry *registry)
3515 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3517 key = E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY;
3518 uid = g_settings_get_string (registry->priv->settings, key);
3519 source = e_source_registry_ref_source (registry, uid);
3522 /* The built-in source is always present. */
3524 source = e_source_registry_ref_builtin_address_book (registry);
3526 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3532 * e_source_registry_set_default_address_book:
3533 * @registry: an #ESourceRegistry
3534 * @default_source: (allow-none): an address book #ESource, or %NULL
3536 * Sets @default_source as the default address book. If @default_source
3537 * is %NULL, the default address book is reset to the built-in address book.
3538 * This setting will persist across sessions until changed.
3543 e_source_registry_set_default_address_book (ESourceRegistry *registry,
3544 ESource *default_source)
3549 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3551 if (default_source != NULL) {
3552 g_return_if_fail (E_IS_SOURCE (default_source));
3553 uid = e_source_get_uid (default_source);
3555 uid = E_SOURCE_BUILTIN_ADDRESS_BOOK_UID;
3558 key = E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY;
3559 g_settings_set_string (registry->priv->settings, key, uid);
3561 /* The GSettings::changed signal will trigger a "notify" signal
3562 * from the registry, so no need to call g_object_notify() here. */
3566 * e_source_registry_ref_default_calendar:
3567 * @registry: an #ESourceRegistry
3569 * Returns the #ESource most recently passed to
3570 * e_source_registry_set_default_calendar() either in this session
3571 * or a previous session, or else falls back to the built-in calendar.
3573 * The returned #ESource is referenced for thread-safety and must be
3574 * unreferenced with g_object_unref() when finished with it.
3576 * Returns: (transfer full): the default calendar #ESource
3581 e_source_registry_ref_default_calendar (ESourceRegistry *registry)
3587 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3589 key = E_SETTINGS_DEFAULT_CALENDAR_KEY;
3590 uid = g_settings_get_string (registry->priv->settings, key);
3591 source = e_source_registry_ref_source (registry, uid);
3594 /* The built-in source is always present. */
3596 source = e_source_registry_ref_builtin_calendar (registry);
3598 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3604 * e_source_registry_set_default_calendar:
3605 * @registry: an #ESourceRegistry
3606 * @default_source: (allow-none): a calendar #ESource, or %NULL
3608 * Sets @default_source as the default calendar. If @default_source
3609 * is %NULL, the default calendar is reset to the built-in calendar.
3610 * This setting will persist across sessions until changed.
3615 e_source_registry_set_default_calendar (ESourceRegistry *registry,
3616 ESource *default_source)
3621 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3623 if (default_source != NULL) {
3624 g_return_if_fail (E_IS_SOURCE (default_source));
3625 uid = e_source_get_uid (default_source);
3627 uid = E_SOURCE_BUILTIN_CALENDAR_UID;
3630 key = E_SETTINGS_DEFAULT_CALENDAR_KEY;
3631 g_settings_set_string (registry->priv->settings, key, uid);
3633 /* The GSettings::changed signal will trigger a "notify" signal
3634 * from the registry, so no need to call g_object_notify() here. */
3638 * e_source_registry_ref_default_mail_account:
3639 * @registry: an #ESourceRegistry
3641 * Returns the #ESource most recently passed to
3642 * e_source_registry_set_default_mail_account() either in this session
3643 * or a previous session, or else falls back to the built-in mail account.
3645 * The returned #ESource is referenced for thread-safety and must be
3646 * unreferenced with g_object_unref() when finished with it.
3648 * Returns: (transfer full): the default mail account #ESource
3653 e_source_registry_ref_default_mail_account (ESourceRegistry *registry)
3659 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3661 key = E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY;
3662 uid = g_settings_get_string (registry->priv->settings, key);
3663 source = e_source_registry_ref_source (registry, uid);
3666 /* The built-in source is always present. */
3668 source = e_source_registry_ref_builtin_mail_account (registry);
3670 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3676 * e_source_registry_set_default_mail_account:
3677 * @registry: an #ESourceRegistry
3678 * @default_source: (allow-none): a mail account #ESource, or %NULL
3680 * Sets @default_source as the default mail account. If @default_source
3681 * is %NULL, the default mail account is reset to the built-in mail account.
3682 * This setting will persist across sessions until changed.
3687 e_source_registry_set_default_mail_account (ESourceRegistry *registry,
3688 ESource *default_source)
3693 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3695 if (default_source != NULL) {
3696 g_return_if_fail (E_IS_SOURCE (default_source));
3697 uid = e_source_get_uid (default_source);
3699 uid = E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID;
3702 key = E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY;
3703 g_settings_set_string (registry->priv->settings, key, uid);
3705 /* The GSettings::changed signal will trigger a "notify" signal
3706 * from the registry, so no need to call g_object_notify() here. */
3709 /* Helper for e_source_registry_ref_default_mail_identity() */
3711 source_registry_ref_any_mail_identity (ESourceRegistry *registry)
3715 const gchar *extension_name;
3718 /* First fallback: Return the mail identity named
3719 * by the default mail account. */
3721 source = e_source_registry_ref_default_mail_account (registry);
3723 /* This should never be NULL, but just to be safe. */
3724 if (source != NULL) {
3725 ESourceMailAccount *extension;
3727 extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
3728 extension = e_source_get_extension (source, extension_name);
3729 uid = e_source_mail_account_dup_identity_uid (extension);
3731 g_object_unref (source);
3736 source = e_source_registry_ref_source (registry, uid);
3743 /* Second fallback: Pick any available mail identity,
3744 * preferring enabled identities. */
3746 extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
3747 list = e_source_registry_list_sources (registry, extension_name);
3749 for (link = list; link != NULL; link = g_list_next (link)) {
3750 ESource *candidate = E_SOURCE (link->data);
3752 if (e_source_registry_check_enabled (registry, candidate)) {
3753 source = g_object_ref (candidate);
3758 if (source == NULL && list != NULL)
3759 source = g_object_ref (list->data);
3761 g_list_free_full (list, (GDestroyNotify) g_object_unref);
3767 * e_source_registry_ref_default_mail_identity:
3768 * @registry: an #ESourceRegistry
3770 * Returns the #ESource most recently passed to
3771 * e_source_registry_set_default_mail_identity() either in this session
3772 * or a previous session, or else falls back to the mail identity named
3773 * by the default mail account. If even that fails it returns any mail
3774 * identity from @registry, or %NULL if there are none.
3776 * The returned #ESource is referenced for thread-safety and must be
3777 * unreferenced with g_object_unref() when finished with it.
3779 * Returns: (transfer full): the default mail identity #ESource, or %NULL
3784 e_source_registry_ref_default_mail_identity (ESourceRegistry *registry)
3790 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3792 key = E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY;
3793 uid = g_settings_get_string (registry->priv->settings, key);
3794 source = e_source_registry_ref_source (registry, uid);
3798 source = source_registry_ref_any_mail_identity (registry);
3804 * e_source_registry_set_default_mail_identity:
3805 * @registry: an #ESourceRegistry
3806 * @default_source: (allow-none): a mail identity #ESource, or %NULL
3808 * Sets @default_source as the default mail identity. If @default_source
3809 * is %NULL, the next request for the default mail identity will use the
3810 * fallbacks described in e_source_registry_ref_default_mail_identity().
3815 e_source_registry_set_default_mail_identity (ESourceRegistry *registry,
3816 ESource *default_source)
3821 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3823 if (default_source != NULL) {
3824 g_return_if_fail (E_IS_SOURCE (default_source));
3825 uid = e_source_get_uid (default_source);
3827 uid = ""; /* no built-in mail identity */
3830 key = E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY;
3831 g_settings_set_string (registry->priv->settings, key, uid);
3833 /* The GSettings::changed signal will trigger a "notify" signal
3834 * from the registry, so no need to call g_object_notify() here. */
3838 * e_source_registry_ref_default_memo_list:
3839 * @registry: an #ESourceRegistry
3841 * Returns the #ESource most recently passed to
3842 * e_source_registry_set_default_memo_list() either in this session
3843 * or a previous session, or else falls back to the built-in memo list.
3845 * The returned #ESource is referenced for thread-safety and must be
3846 * unreferenced with g_object_unref() when finished with it.
3848 * Returns: (transfer full): the default memo list #ESource
3853 e_source_registry_ref_default_memo_list (ESourceRegistry *registry)
3859 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3861 key = E_SETTINGS_DEFAULT_MEMO_LIST_KEY;
3862 uid = g_settings_get_string (registry->priv->settings, key);
3863 source = e_source_registry_ref_source (registry, uid);
3866 /* The built-in source is always present. */
3868 source = e_source_registry_ref_builtin_memo_list (registry);
3870 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3876 * e_source_registry_set_default_memo_list:
3877 * @registry: an #ESourceRegistry
3878 * @default_source: (allow-none): a memo list #ESource, or %NULL
3880 * Sets @default_source as the default memo list. If @default_source
3881 * is %NULL, the default memo list is reset to the built-in memo list.
3882 * This setting will persist across sessions until changed.
3887 e_source_registry_set_default_memo_list (ESourceRegistry *registry,
3888 ESource *default_source)
3893 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3895 if (default_source != NULL) {
3896 g_return_if_fail (E_IS_SOURCE (default_source));
3897 uid = e_source_get_uid (default_source);
3899 uid = E_SOURCE_BUILTIN_MEMO_LIST_UID;
3902 key = E_SETTINGS_DEFAULT_MEMO_LIST_KEY;
3903 g_settings_set_string (registry->priv->settings, key, uid);
3905 /* The GSettings::changed signal will trigger a "notify" signal
3906 * from the registry, so no need to call g_object_notify() here. */
3910 * e_source_registry_ref_default_task_list:
3911 * @registry: an #ESourceRegistry
3913 * Returns the #ESource most recently passed to
3914 * e_source_registry_set_default_task_list() either in this session
3915 * or a previous session, or else falls back to the built-in task list.
3917 * The returned #ESource is referenced for thread-safety and must be
3918 * unreferenced with g_object_unref() when finished with it.
3920 * Returns: (transfer full): the default task list #ESource
3925 e_source_registry_ref_default_task_list (ESourceRegistry *registry)
3931 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3933 key = E_SETTINGS_DEFAULT_TASK_LIST_KEY;
3934 uid = g_settings_get_string (registry->priv->settings, key);
3935 source = e_source_registry_ref_source (registry, uid);
3938 /* The built-in source is always present. */
3940 source = e_source_registry_ref_builtin_task_list (registry);
3942 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3948 * e_source_registry_set_default_task_list:
3949 * @registry: an #ESourceRegistry
3950 * @default_source: (allow-none): a task list #ESource, or %NULL
3952 * Sets @default_source as the default task list. If @default_source
3953 * is %NULL, the default task list is reset to the built-in task list.
3954 * This setting will persist across sessions until changed.
3959 e_source_registry_set_default_task_list (ESourceRegistry *registry,
3960 ESource *default_source)
3965 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3967 if (default_source != NULL) {
3968 g_return_if_fail (E_IS_SOURCE (default_source));
3969 uid = e_source_get_uid (default_source);
3971 uid = E_SOURCE_BUILTIN_TASK_LIST_UID;
3974 key = E_SETTINGS_DEFAULT_TASK_LIST_KEY;
3975 g_settings_set_string (registry->priv->settings, key, uid);
3977 /* The GSettings::changed signal will trigger a "notify" signal
3978 * from the registry, so no need to call g_object_notify() here. */
3982 * e_source_registry_ref_default_for_extension_name:
3983 * @registry: an #ESourceRegistry
3984 * @extension_name: an extension_name
3986 * This is a convenience function to return a default #ESource based on
3987 * @extension_name. This only works with a subset of extension names.
3989 * If @extension_name is #E_SOURCE_EXTENSION_ADDRESS_BOOK, the function
3990 * returns the current default address book, or else falls back to the
3991 * built-in address book.
3993 * If @extension_name is #E_SOURCE_EXTENSION_CALENDAR, the function returns
3994 * the current default calendar, or else falls back to the built-in calendar.
3996 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_ACCOUNT, the function
3997 * returns the current default mail account, or else falls back to the
3998 * built-in mail account.
4000 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_IDENTITY, the function
4001 * returns the current default mail identity, or else falls back to the
4002 * mail identity named by the current default mail account.
4004 * If @extension_name is #E_SOURCE_EXTENSION_MEMO_LIST, the function returns
4005 * the current default memo list, or else falls back to the built-in memo list.
4007 * If @extension_name is #E_SOURCE_EXTENSION_TASK_LIST, the function returns
4008 * the current default task list, or else falls back to the built-in task list.
4010 * For all other values of @extension_name, the function returns %NULL.
4012 * The returned #ESource is referenced for thread-safety and must be
4013 * unreferenced with g_object_unref() when finished with it.
4015 * Returns: (transfer full): the default #ESource based on @extension_name
4020 e_source_registry_ref_default_for_extension_name (ESourceRegistry *registry,
4021 const gchar *extension_name)
4023 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
4024 g_return_val_if_fail (extension_name != NULL, NULL);
4026 if (strcmp (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK) == 0)
4027 return e_source_registry_ref_default_address_book (registry);
4029 if (strcmp (extension_name, E_SOURCE_EXTENSION_CALENDAR) == 0)
4030 return e_source_registry_ref_default_calendar (registry);
4032 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_ACCOUNT) == 0)
4033 return e_source_registry_ref_default_mail_account (registry);
4035 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_IDENTITY) == 0)
4036 return e_source_registry_ref_default_mail_identity (registry);
4038 if (strcmp (extension_name, E_SOURCE_EXTENSION_MEMO_LIST) == 0)
4039 return e_source_registry_ref_default_memo_list (registry);
4041 if (strcmp (extension_name, E_SOURCE_EXTENSION_TASK_LIST) == 0)
4042 return e_source_registry_ref_default_task_list (registry);
4048 * e_source_registry_set_default_for_extension_name:
4049 * @registry: an #ESourceRegistry
4050 * @extension_name: an extension name
4051 * @default_source: (allow-none): an #ESource, or %NULL
4053 * This is a convenience function to set a default #ESource based on
4054 * @extension_name. This only works with a subset of extension names.
4056 * If @extension_name is #E_SOURCE_EXTENSION_ADDRESS_BOOK, the function
4057 * sets @default_source as the default address book. If @default_source
4058 * is %NULL, the default address book is reset to the built-in address book.
4060 * If @extension_name is #E_SOURCE_EXTENSION_CALENDAR, the function sets
4061 * @default_source as the default calendar. If @default_source is %NULL,
4062 * the default calendar is reset to the built-in calendar.
4064 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_ACCOUNT, the function
4065 * sets @default_source as the default mail account. If @default_source
4066 * is %NULL, the default mail account is reset to the built-in mail account.
4068 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_IDENTITY, the function
4069 * sets @default_source as the default mail identity. If @default_source
4070 * is %NULL, the next request for the default mail identity will return
4071 * the mail identity named by the default mail account.
4073 * If @extension_name is #E_SOURCE_EXTENSION_MEMO_LIST, the function sets
4074 * @default_source as the default memo list. If @default_source is %NULL,
4075 * the default memo list is reset to the built-in memo list.
4077 * If @extension_name is #E_SOURCE_EXTENSION_TASK_LIST, the function sets
4078 * @default_source as the default task list. If @default_source is %NULL,
4079 * the default task list is reset to the built-in task list.
4081 * For all other values of @extension_name, the function does nothing.
4086 e_source_registry_set_default_for_extension_name (ESourceRegistry *registry,
4087 const gchar *extension_name,
4088 ESource *default_source)
4090 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
4091 g_return_if_fail (extension_name != NULL);
4093 if (strcmp (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK) == 0)
4094 e_source_registry_set_default_address_book (
4095 registry, default_source);
4097 if (strcmp (extension_name, E_SOURCE_EXTENSION_CALENDAR) == 0)
4098 e_source_registry_set_default_calendar (
4099 registry, default_source);
4101 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_ACCOUNT) == 0)
4102 e_source_registry_set_default_mail_account (
4103 registry, default_source);
4105 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_IDENTITY) == 0)
4106 e_source_registry_set_default_mail_identity (
4107 registry, default_source);
4109 if (strcmp (extension_name, E_SOURCE_EXTENSION_MEMO_LIST) == 0)
4110 e_source_registry_set_default_memo_list (
4111 registry, default_source);
4113 if (strcmp (extension_name, E_SOURCE_EXTENSION_TASK_LIST) == 0)
4114 e_source_registry_set_default_task_list (
4115 registry, default_source);