I#27 - [IMAPx] Ignore DavMail's CR/LF in BODYSTRUCTURE response
[evolution-data-server.git] / src / libedataserver / e-source-registry.c
blob9c166dbaf4c5019cb033328b17b39c3e4648381d
1 /*
2 * e-source-registry.c
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 Lesser General Public License
11 * for more details.
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/>.
18 /**
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
32 * #ESource instances.
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.
39 * Note: The #ESourceRegistry uses thread default main context from the time
40 * of its creation to deliver D-Bus signals, finish operations and so on,
41 * thus it requires a running main loop for its proper functionality.
42 **/
44 #include "evolution-data-server-config.h"
46 #include <glib/gstdio.h>
47 #include <glib/gi18n-lib.h>
49 /* XXX Yeah, yeah... */
50 #define GCR_API_SUBJECT_TO_CHANGE
52 #include <gcr/gcr-base.h>
54 /* Private D-Bus classes. */
55 #include "e-dbus-source.h"
56 #include "e-dbus-source-manager.h"
58 #include "e-data-server-util.h"
59 #include "e-source-collection.h"
60 #include "e-source-enumtypes.h"
62 /* Needed for the defaults API. */
63 #include "e-source-address-book.h"
64 #include "e-source-calendar.h"
65 #include "e-source-mail-account.h"
66 #include "e-source-mail-identity.h"
67 #include "e-source-memo-list.h"
68 #include "e-source-task-list.h"
70 #include "e-source-registry.h"
72 #define E_SOURCE_REGISTRY_GET_PRIVATE(obj) \
73 (G_TYPE_INSTANCE_GET_PRIVATE \
74 ((obj), E_TYPE_SOURCE_REGISTRY, ESourceRegistryPrivate))
76 #define DBUS_OBJECT_PATH "/org/gnome/evolution/dataserver/SourceManager"
77 #define GSETTINGS_SCHEMA "org.gnome.Evolution.DefaultSources"
79 /* Built-in data source UIDs. */
80 #define E_SOURCE_BUILTIN_ADDRESS_BOOK_UID "system-address-book"
81 #define E_SOURCE_BUILTIN_CALENDAR_UID "system-calendar"
82 #define E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID "local"
83 #define E_SOURCE_BUILTIN_MEMO_LIST_UID "system-memo-list"
84 #define E_SOURCE_BUILTIN_PROXY_UID "system-proxy"
85 #define E_SOURCE_BUILTIN_TASK_LIST_UID "system-task-list"
87 /* GSettings keys for default data sources. */
88 #define E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY "default-address-book"
89 #define E_SETTINGS_DEFAULT_CALENDAR_KEY "default-calendar"
90 #define E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY "default-mail-account"
91 #define E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY "default-mail-identity"
92 #define E_SETTINGS_DEFAULT_MEMO_LIST_KEY "default-memo-list"
93 #define E_SETTINGS_DEFAULT_TASK_LIST_KEY "default-task-list"
95 typedef struct _AsyncContext AsyncContext;
96 typedef struct _CreateContext CreateContext;
97 typedef struct _SourceClosure SourceClosure;
98 typedef struct _ThreadClosure ThreadClosure;
99 typedef struct _CredentialsRequiredClosure CredentialsRequiredClosure;
101 struct _ESourceRegistryPrivate {
102 GMainContext *main_context;
104 GThread *manager_thread;
105 ThreadClosure *thread_closure;
107 GDBusObjectManager *dbus_object_manager;
108 EDBusSourceManager *dbus_source_manager;
110 GHashTable *object_path_table;
111 GMutex object_path_table_lock;
113 GHashTable *service_restart_table;
114 GMutex service_restart_table_lock;
116 GHashTable *sources;
117 GMutex sources_lock;
119 GSettings *settings;
121 gboolean initialized;
122 GError *init_error;
123 GMutex init_lock;
125 EOAuth2Services *oauth2_services;
128 struct _AsyncContext {
129 ESource *source;
130 GList *list_of_sources;
133 /* Used in e_source_registry_create_sources_sync() */
134 struct _CreateContext {
135 GHashTable *pending_uids;
136 GMainContext *main_context;
137 GMainLoop *main_loop;
140 struct _SourceClosure {
141 GWeakRef registry;
142 ESource *source;
145 struct _ThreadClosure {
146 ESourceRegistry *registry;
147 GMainContext *main_context;
148 GMainLoop *main_loop;
149 GCond main_loop_cond;
150 GMutex main_loop_mutex;
151 GError *error;
154 struct _CredentialsRequiredClosure {
155 GWeakRef registry;
156 ESource *source;
157 ESourceCredentialsReason reason;
158 gchar *certificate_pem;
159 GTlsCertificateFlags certificate_errors;
160 GError *op_error;
163 enum {
164 PROP_0,
165 PROP_DEFAULT_ADDRESS_BOOK,
166 PROP_DEFAULT_CALENDAR,
167 PROP_DEFAULT_MAIL_ACCOUNT,
168 PROP_DEFAULT_MAIL_IDENTITY,
169 PROP_DEFAULT_MEMO_LIST,
170 PROP_DEFAULT_TASK_LIST
173 enum {
174 SOURCE_ADDED,
175 SOURCE_CHANGED,
176 SOURCE_REMOVED,
177 SOURCE_ENABLED,
178 SOURCE_DISABLED,
179 CREDENTIALS_REQUIRED,
180 LAST_SIGNAL
183 /* Forward Declarations */
184 static void source_registry_add_source (ESourceRegistry *registry,
185 ESource *source);
186 static void e_source_registry_initable_init (GInitableIface *iface);
188 /* Private ESource function, for our use only. */
189 void __e_source_private_replace_dbus_object
190 (ESource *source,
191 GDBusObject *dbus_object);
193 static guint signals[LAST_SIGNAL];
195 /* By default, the GAsyncInitable interface calls GInitable.init()
196 * from a separate thread, so we only have to override GInitable. */
197 G_DEFINE_TYPE_WITH_CODE (
198 ESourceRegistry,
199 e_source_registry,
200 G_TYPE_OBJECT,
201 G_IMPLEMENT_INTERFACE (
202 G_TYPE_INITABLE, e_source_registry_initable_init)
203 G_IMPLEMENT_INTERFACE (
204 G_TYPE_ASYNC_INITABLE, NULL))
206 static void
207 async_context_free (AsyncContext *async_context)
209 if (async_context->source != NULL)
210 g_object_unref (async_context->source);
212 g_list_free_full (
213 async_context->list_of_sources,
214 (GDestroyNotify) g_object_unref);
216 g_slice_free (AsyncContext, async_context);
219 static CreateContext *
220 create_context_new (void)
222 CreateContext *create_context;
224 create_context = g_slice_new0 (CreateContext);
226 create_context->pending_uids = g_hash_table_new_full (
227 (GHashFunc) g_str_hash,
228 (GEqualFunc) g_str_equal,
229 (GDestroyNotify) g_free,
230 (GDestroyNotify) NULL);
232 create_context->main_context = g_main_context_new ();
234 create_context->main_loop = g_main_loop_new (
235 create_context->main_context, FALSE);
237 return create_context;
240 static void
241 create_context_free (CreateContext *create_context)
243 g_main_loop_unref (create_context->main_loop);
244 g_main_context_unref (create_context->main_context);
245 g_hash_table_unref (create_context->pending_uids);
247 g_slice_free (CreateContext, create_context);
250 static void
251 source_closure_free (SourceClosure *closure)
253 g_weak_ref_clear (&closure->registry);
254 g_object_unref (closure->source);
256 g_slice_free (SourceClosure, closure);
259 static void
260 thread_closure_free (ThreadClosure *closure)
262 /* The registry member is not referenced. */
264 g_warn_if_fail (!g_main_context_pending (closure->main_context));
266 g_main_context_unref (closure->main_context);
267 g_main_loop_unref (closure->main_loop);
268 g_cond_clear (&closure->main_loop_cond);
269 g_mutex_clear (&closure->main_loop_mutex);
271 /* The GError should be NULL at this point,
272 * regardless of whether an error occurred. */
273 g_warn_if_fail (closure->error == NULL);
275 g_slice_free (ThreadClosure, closure);
278 static void
279 credentials_required_closure_free (gpointer ptr)
281 CredentialsRequiredClosure *closure = ptr;
283 if (closure) {
284 g_weak_ref_clear (&closure->registry);
285 g_object_unref (closure->source);
286 g_free (closure->certificate_pem);
287 g_clear_error (&closure->op_error);
289 g_slice_free (CredentialsRequiredClosure, closure);
293 G_LOCK_DEFINE_STATIC (singleton_lock);
294 static GWeakRef singleton;
296 static ESourceRegistry *
297 source_registry_dup_uninitialized_singleton (void)
299 ESourceRegistry *registry;
301 G_LOCK (singleton_lock);
303 registry = g_weak_ref_get (&singleton);
304 if (registry == NULL) {
305 registry = g_object_new (E_TYPE_SOURCE_REGISTRY, NULL);
306 g_weak_ref_set (&singleton, registry);
309 G_UNLOCK (singleton_lock);
311 return registry;
314 static gchar *
315 source_registry_dbus_object_dup_uid (GDBusObject *dbus_object)
317 EDBusObject *e_dbus_object;
318 EDBusSource *e_dbus_source;
320 /* EDBusSource interface should always be present. */
321 e_dbus_object = E_DBUS_OBJECT (dbus_object);
322 e_dbus_source = e_dbus_object_peek_source (e_dbus_object);
324 return e_dbus_source_dup_uid (e_dbus_source);
327 static void
328 source_registry_object_path_table_insert (ESourceRegistry *registry,
329 const gchar *object_path,
330 ESource *source)
332 GHashTable *object_path_table;
334 g_return_if_fail (object_path != NULL);
335 g_return_if_fail (E_IS_SOURCE (source));
337 object_path_table = registry->priv->object_path_table;
339 g_mutex_lock (&registry->priv->object_path_table_lock);
341 g_hash_table_insert (
342 object_path_table,
343 g_strdup (object_path),
344 g_object_ref (source));
346 g_mutex_unlock (&registry->priv->object_path_table_lock);
349 static ESource *
350 source_registry_object_path_table_lookup (ESourceRegistry *registry,
351 const gchar *object_path)
353 GHashTable *object_path_table;
354 ESource *source;
356 g_return_val_if_fail (object_path != NULL, NULL);
358 object_path_table = registry->priv->object_path_table;
360 g_mutex_lock (&registry->priv->object_path_table_lock);
362 source = g_hash_table_lookup (object_path_table, object_path);
363 if (source != NULL)
364 g_object_ref (source);
366 g_mutex_unlock (&registry->priv->object_path_table_lock);
368 return source;
371 static gboolean
372 source_registry_object_path_table_remove (ESourceRegistry *registry,
373 const gchar *object_path)
375 GHashTable *object_path_table;
376 gboolean removed;
378 g_return_val_if_fail (object_path != NULL, FALSE);
380 object_path_table = registry->priv->object_path_table;
382 g_mutex_lock (&registry->priv->object_path_table_lock);
384 removed = g_hash_table_remove (object_path_table, object_path);
386 g_mutex_unlock (&registry->priv->object_path_table_lock);
388 return removed;
391 static void
392 source_registry_service_restart_table_add (ESourceRegistry *registry,
393 const gchar *uid)
395 GHashTable *service_restart_table;
397 g_return_if_fail (uid != NULL);
399 service_restart_table = registry->priv->service_restart_table;
401 g_mutex_lock (&registry->priv->service_restart_table_lock);
403 g_hash_table_add (service_restart_table, g_strdup (uid));
405 g_mutex_unlock (&registry->priv->service_restart_table_lock);
408 static gboolean
409 source_registry_service_restart_table_remove (ESourceRegistry *registry,
410 const gchar *uid)
412 GHashTable *service_restart_table;
413 gboolean removed;
415 g_return_val_if_fail (uid != NULL, FALSE);
417 service_restart_table = registry->priv->service_restart_table;
419 g_mutex_lock (&registry->priv->service_restart_table_lock);
421 removed = g_hash_table_remove (service_restart_table, uid);
423 g_mutex_unlock (&registry->priv->service_restart_table_lock);
425 return removed;
428 static GList *
429 source_registry_service_restart_table_steal_all (ESourceRegistry *registry)
431 GHashTable *service_restart_table;
432 GList *list;
434 service_restart_table = registry->priv->service_restart_table;
436 g_mutex_lock (&registry->priv->service_restart_table_lock);
438 list = g_hash_table_get_keys (service_restart_table);
439 g_hash_table_steal_all (service_restart_table);
441 g_mutex_unlock (&registry->priv->service_restart_table_lock);
443 return list;
446 static gboolean
447 source_registry_sources_remove (ESourceRegistry *registry,
448 ESource *source)
450 const gchar *uid;
451 gboolean removed;
453 uid = e_source_get_uid (source);
454 g_return_val_if_fail (uid != NULL, FALSE);
456 g_mutex_lock (&registry->priv->sources_lock);
458 removed = g_hash_table_remove (registry->priv->sources, uid);
460 g_mutex_unlock (&registry->priv->sources_lock);
462 return removed;
465 static ESource *
466 source_registry_sources_lookup (ESourceRegistry *registry,
467 const gchar *uid)
469 ESource *source;
471 g_return_val_if_fail (uid != NULL, NULL);
473 g_mutex_lock (&registry->priv->sources_lock);
475 source = g_hash_table_lookup (registry->priv->sources, uid);
477 if (source != NULL)
478 g_object_ref (source);
480 g_mutex_unlock (&registry->priv->sources_lock);
482 return source;
485 static GList *
486 source_registry_sources_get_values (ESourceRegistry *registry)
488 GList *values;
490 g_mutex_lock (&registry->priv->sources_lock);
492 values = g_hash_table_get_values (registry->priv->sources);
494 g_list_foreach (values, (GFunc) g_object_ref, NULL);
496 g_mutex_unlock (&registry->priv->sources_lock);
498 return values;
501 static GNode *
502 source_registry_sources_build_tree (ESourceRegistry *registry)
504 GNode *root;
505 GHashTable *index;
506 GHashTableIter iter;
507 gpointer key, value;
509 g_mutex_lock (&registry->priv->sources_lock);
511 root = g_node_new (NULL);
512 index = g_hash_table_new (g_str_hash, g_str_equal);
514 /* Add a GNode for each ESource to the index. */
515 g_hash_table_iter_init (&iter, registry->priv->sources);
516 while (g_hash_table_iter_next (&iter, &key, &value)) {
517 ESource *source = g_object_ref (value);
518 g_hash_table_insert (index, key, g_node_new (source));
521 /* Traverse the index and link the nodes together. */
522 g_hash_table_iter_init (&iter, index);
523 while (g_hash_table_iter_next (&iter, NULL, &value)) {
524 ESource *source;
525 GNode *source_node;
526 GNode *parent_node;
527 const gchar *parent_uid;
529 source_node = (GNode *) value;
530 source = E_SOURCE (source_node->data);
531 parent_uid = e_source_get_parent (source);
533 if (parent_uid == NULL || *parent_uid == '\0') {
534 parent_node = root;
535 } else {
536 parent_node = g_hash_table_lookup (index, parent_uid);
537 g_warn_if_fail (parent_node != NULL);
540 /* Should never be NULL, but just to be safe. */
541 if (parent_node != NULL)
542 g_node_append (parent_node, source_node);
545 g_hash_table_destroy (index);
547 g_mutex_unlock (&registry->priv->sources_lock);
549 return root;
552 static void
553 source_registry_settings_changed_cb (GSettings *settings,
554 const gchar *key,
555 ESourceRegistry *registry)
557 /* We define a property name that matches every key in
558 * the "org.gnome.Evolution.DefaultSources" schema. */
559 g_object_notify (G_OBJECT (registry), key);
562 static gboolean
563 source_registry_source_changed_idle_cb (gpointer user_data)
565 SourceClosure *closure = user_data;
566 ESourceRegistry *registry;
568 registry = g_weak_ref_get (&closure->registry);
570 if (registry != NULL) {
571 g_signal_emit (
572 registry,
573 signals[SOURCE_CHANGED], 0,
574 closure->source);
575 g_object_unref (registry);
578 return FALSE;
581 static gboolean
582 source_registry_source_notify_enabled_idle_cb (gpointer user_data)
584 SourceClosure *closure = user_data;
585 ESourceRegistry *registry;
587 registry = g_weak_ref_get (&closure->registry);
589 if (registry != NULL) {
590 if (e_source_get_enabled (closure->source)) {
591 g_signal_emit (
592 registry,
593 signals[SOURCE_ENABLED], 0,
594 closure->source);
595 } else {
596 g_signal_emit (
597 registry,
598 signals[SOURCE_DISABLED], 0,
599 closure->source);
601 g_object_unref (registry);
604 return FALSE;
607 static void
608 source_registry_source_changed_cb (ESource *source,
609 ESourceRegistry *registry)
611 GSource *idle_source;
612 SourceClosure *closure;
614 closure = g_slice_new0 (SourceClosure);
615 g_weak_ref_init (&closure->registry, registry);
616 closure->source = g_object_ref (source);
618 idle_source = g_idle_source_new ();
619 g_source_set_callback (
620 idle_source,
621 source_registry_source_changed_idle_cb,
622 closure, (GDestroyNotify) source_closure_free);
623 g_source_attach (idle_source, registry->priv->main_context);
624 g_source_unref (idle_source);
627 static void
628 source_registry_source_notify_enabled_cb (ESource *source,
629 GParamSpec *pspec,
630 ESourceRegistry *registry)
632 GSource *idle_source;
633 SourceClosure *closure;
635 closure = g_slice_new0 (SourceClosure);
636 g_weak_ref_init (&closure->registry, registry);
637 closure->source = g_object_ref (source);
639 idle_source = g_idle_source_new ();
640 g_source_set_callback (
641 idle_source,
642 source_registry_source_notify_enabled_idle_cb,
643 closure, (GDestroyNotify) source_closure_free);
644 g_source_attach (idle_source, registry->priv->main_context);
645 g_source_unref (idle_source);
648 static gboolean
649 source_registry_source_credentials_required_idle_cb (gpointer user_data)
651 CredentialsRequiredClosure *closure = user_data;
652 ESourceRegistry *registry;
654 registry = g_weak_ref_get (&closure->registry);
656 if (registry != NULL) {
657 g_signal_emit (
658 registry,
659 signals[CREDENTIALS_REQUIRED], 0,
660 closure->source, closure->reason, closure->certificate_pem,
661 closure->certificate_errors, closure->op_error);
663 g_object_unref (registry);
666 return FALSE;
669 static void
670 source_registry_source_credentials_required_cb (ESource *source,
671 ESourceCredentialsReason reason,
672 const gchar *certificate_pem,
673 GTlsCertificateFlags certificate_errors,
674 const GError *op_error,
675 ESourceRegistry *registry)
677 GSource *idle_source;
678 CredentialsRequiredClosure *closure;
680 closure = g_slice_new0 (CredentialsRequiredClosure);
681 g_weak_ref_init (&closure->registry, registry);
682 closure->source = g_object_ref (source);
683 closure->reason = reason;
684 closure->certificate_pem = g_strdup (certificate_pem);
685 closure->certificate_errors = certificate_errors;
686 closure->op_error = op_error ? g_error_copy (op_error) : NULL;
688 idle_source = g_idle_source_new ();
689 g_source_set_callback (
690 idle_source,
691 source_registry_source_credentials_required_idle_cb,
692 closure, credentials_required_closure_free);
693 g_source_attach (idle_source, registry->priv->main_context);
694 g_source_unref (idle_source);
697 static ESource *
698 source_registry_new_source (ESourceRegistry *registry,
699 GDBusObject *dbus_object)
701 GMainContext *main_context;
702 ESource *source;
703 const gchar *object_path;
704 GError *local_error = NULL;
706 /* We don't want the ESource emitting "changed" signals from
707 * the manager thread, so we pass it the same main context the
708 * registry uses for scheduling signal emissions. */
709 main_context = registry->priv->main_context;
710 source = e_source_new (dbus_object, main_context, &local_error);
711 object_path = g_dbus_object_get_object_path (dbus_object);
713 /* The likelihood of an error here is slim, so it's
714 * sufficient to just print a warning if one occurs. */
715 if (local_error != NULL) {
716 g_warn_if_fail (source == NULL);
717 g_critical (
718 "ESourceRegistry: Failed to create a "
719 "data source object for path '%s': %s",
720 object_path, local_error->message);
721 g_error_free (local_error);
722 return NULL;
725 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
727 /* Add the ESource to the object path table immediately. */
728 source_registry_object_path_table_insert (
729 registry, object_path, source);
731 return source;
734 static void
735 source_registry_unref_source (ESource *source)
737 g_signal_handlers_disconnect_matched (
738 source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
739 source_registry_source_changed_cb, NULL);
741 g_signal_handlers_disconnect_matched (
742 source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
743 source_registry_source_notify_enabled_cb, NULL);
745 g_signal_handlers_disconnect_matched (
746 source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
747 source_registry_source_credentials_required_cb, NULL);
749 g_object_unref (source);
752 static void
753 source_registry_add_source (ESourceRegistry *registry,
754 ESource *source)
756 const gchar *uid;
758 /* This is called in the manager thread during initialization
759 * and in response to "object-added" signals from the manager. */
761 uid = e_source_get_uid (source);
762 g_return_if_fail (uid != NULL);
764 g_mutex_lock (&registry->priv->sources_lock);
766 /* Check if we already have this source in the registry. */
767 if (g_hash_table_lookup (registry->priv->sources, uid) != NULL) {
768 g_mutex_unlock (&registry->priv->sources_lock);
769 return;
772 g_signal_connect (
773 source, "changed",
774 G_CALLBACK (source_registry_source_changed_cb),
775 registry);
777 g_signal_connect (
778 source, "notify::enabled",
779 G_CALLBACK (source_registry_source_notify_enabled_cb),
780 registry);
782 g_signal_connect (
783 source, "credentials-required",
784 G_CALLBACK (source_registry_source_credentials_required_cb),
785 registry);
787 g_hash_table_insert (
788 registry->priv->sources,
789 g_strdup (uid), g_object_ref (source));
791 g_mutex_unlock (&registry->priv->sources_lock);
794 static gboolean
795 source_registry_object_added_idle_cb (gpointer user_data)
797 SourceClosure *closure = user_data;
798 ESourceRegistry *registry;
800 registry = g_weak_ref_get (&closure->registry);
802 if (registry != NULL) {
803 g_signal_emit (
804 registry,
805 signals[SOURCE_ADDED], 0,
806 closure->source);
807 g_object_unref (registry);
810 return FALSE;
813 static void
814 source_registry_object_added_by_owner (ESourceRegistry *registry,
815 GDBusObject *dbus_object)
817 SourceClosure *closure;
818 GSource *idle_source;
819 ESource *source;
821 g_return_if_fail (E_DBUS_IS_OBJECT (dbus_object));
823 source = source_registry_new_source (registry, dbus_object);
824 g_return_if_fail (source != NULL);
826 /* Add the new ESource to our internal hash table so it can be
827 * obtained through e_source_registry_ref_source() immediately. */
828 source_registry_add_source (registry, source);
830 /* Schedule a callback on the ESourceRegistry's GMainContext. */
832 closure = g_slice_new0 (SourceClosure);
833 g_weak_ref_init (&closure->registry, registry);
834 closure->source = g_object_ref (source);
836 idle_source = g_idle_source_new ();
837 g_source_set_callback (
838 idle_source,
839 source_registry_object_added_idle_cb,
840 closure, (GDestroyNotify) source_closure_free);
841 g_source_attach (idle_source, registry->priv->main_context);
842 g_source_unref (idle_source);
844 g_object_unref (source);
847 static void
848 source_registry_object_added_no_owner (ESourceRegistry *registry,
849 GDBusObject *dbus_object)
851 ESource *source = NULL;
852 gchar *uid;
854 uid = source_registry_dbus_object_dup_uid (dbus_object);
856 if (source_registry_service_restart_table_remove (registry, uid))
857 source = e_source_registry_ref_source (registry, uid);
859 if (source != NULL) {
860 const gchar *object_path;
862 object_path = g_dbus_object_get_object_path (dbus_object);
864 source_registry_object_path_table_insert (
865 registry, object_path, source);
867 __e_source_private_replace_dbus_object (source, dbus_object);
869 g_object_unref (source);
871 } else {
872 source_registry_object_added_by_owner (registry, dbus_object);
875 g_free (uid);
878 static void
879 source_registry_object_added_cb (GDBusObjectManager *object_manager,
880 GDBusObject *dbus_object,
881 ESourceRegistry *registry)
883 gchar *name_owner;
885 name_owner = g_dbus_object_manager_client_get_name_owner (
886 G_DBUS_OBJECT_MANAGER_CLIENT (object_manager));
888 if (name_owner != NULL)
889 source_registry_object_added_by_owner (registry, dbus_object);
890 else
891 source_registry_object_added_no_owner (registry, dbus_object);
893 g_free (name_owner);
896 static gboolean
897 source_registry_object_removed_idle_cb (gpointer user_data)
899 SourceClosure *closure = user_data;
900 ESourceRegistry *registry;
902 registry = g_weak_ref_get (&closure->registry);
904 if (registry != NULL) {
905 g_signal_emit (
906 registry,
907 signals[SOURCE_REMOVED], 0,
908 closure->source);
909 g_object_unref (registry);
912 return FALSE;
915 static void
916 source_registry_object_removed_by_owner (ESourceRegistry *registry,
917 GDBusObject *dbus_object)
919 SourceClosure *closure;
920 GSource *idle_source;
921 ESource *source;
922 const gchar *object_path;
924 /* Find the corresponding ESource in the object path table.
925 * Note that the lookup returns a new ESource reference. */
926 object_path = g_dbus_object_get_object_path (dbus_object);
927 source = source_registry_object_path_table_lookup (
928 registry, object_path);
929 g_return_if_fail (E_IS_SOURCE (source));
931 /* Remove the ESource from the object path table immediately. */
932 source_registry_object_path_table_remove (registry, object_path);
934 /* Also remove the ESource from the sources table immediately. */
935 if (!source_registry_sources_remove (registry, source)) {
936 g_object_unref (source);
937 g_return_if_reached ();
940 /* Strip the ESource of its GDBusObject. */
941 __e_source_private_replace_dbus_object (source, NULL);
943 /* Schedule a callback on the ESourceRegistry's GMainContext. */
945 closure = g_slice_new0 (SourceClosure);
946 g_weak_ref_init (&closure->registry, registry);
947 closure->source = g_object_ref (source);
949 idle_source = g_idle_source_new ();
950 g_source_set_callback (
951 idle_source,
952 source_registry_object_removed_idle_cb,
953 closure, (GDestroyNotify) source_closure_free);
954 g_source_attach (idle_source, registry->priv->main_context);
955 g_source_unref (idle_source);
957 g_object_unref (source);
960 static void
961 source_registry_object_removed_no_owner (ESourceRegistry *registry,
962 GDBusObject *dbus_object)
964 const gchar *object_path;
966 object_path = g_dbus_object_get_object_path (dbus_object);
968 if (source_registry_object_path_table_remove (registry, object_path)) {
969 gchar *uid;
971 uid = source_registry_dbus_object_dup_uid (dbus_object);
972 source_registry_service_restart_table_add (registry, uid);
973 g_free (uid);
977 static void
978 source_registry_object_removed_cb (GDBusObjectManager *object_manager,
979 GDBusObject *dbus_object,
980 ESourceRegistry *registry)
982 gchar *name_owner;
984 name_owner = g_dbus_object_manager_client_get_name_owner (
985 G_DBUS_OBJECT_MANAGER_CLIENT (object_manager));
987 if (name_owner != NULL)
988 source_registry_object_removed_by_owner (registry, dbus_object);
989 else
990 source_registry_object_removed_no_owner (registry, dbus_object);
992 g_free (name_owner);
995 static void
996 source_registry_name_appeared (ESourceRegistry *registry)
998 GList *list, *link;
1000 /* The D-Bus service restarted, and the GDBusObjectManager has
1001 * just set its "name-owner" property having finished emitting
1002 * an "object-added" signal for each GDBusObject. */
1004 list = source_registry_service_restart_table_steal_all (registry);
1006 for (link = list; link != NULL; link = g_list_next (link)) {
1007 SourceClosure *closure;
1008 GSource *idle_source;
1009 ESource *source;
1010 const gchar *uid = link->data;
1012 source = e_source_registry_ref_source (registry, uid);
1013 if (source == NULL)
1014 continue;
1016 closure = g_slice_new0 (SourceClosure);
1017 g_weak_ref_init (&closure->registry, registry);
1018 closure->source = g_object_ref (source);
1020 idle_source = g_idle_source_new ();
1021 g_source_set_callback (
1022 idle_source,
1023 source_registry_object_removed_idle_cb,
1024 closure, (GDestroyNotify) source_closure_free);
1025 g_source_attach (idle_source, registry->priv->main_context);
1026 g_source_unref (idle_source);
1028 g_object_unref (source);
1031 g_list_free_full (list, (GDestroyNotify) g_free);
1034 static void
1035 source_registry_name_vanished (ESourceRegistry *registry)
1037 /* This function is just a convenience breakpoint. The D-Bus
1038 * service aborted, so the GDBusObjectManager has cleared its
1039 * "name-owner" property and will now emit a "object-removed"
1040 * signal for each GDBusObject. */
1043 static void
1044 source_registry_notify_name_owner_cb (GDBusObjectManager *object_manager,
1045 GParamSpec *pspec,
1046 ESourceRegistry *registry)
1048 gchar *name_owner;
1050 name_owner = g_dbus_object_manager_client_get_name_owner (
1051 G_DBUS_OBJECT_MANAGER_CLIENT (object_manager));
1053 if (name_owner != NULL)
1054 source_registry_name_appeared (registry);
1055 else
1056 source_registry_name_vanished (registry);
1058 g_free (name_owner);
1061 static gboolean
1062 source_registry_object_manager_running (gpointer data)
1064 ThreadClosure *closure = data;
1066 g_mutex_lock (&closure->main_loop_mutex);
1067 g_cond_broadcast (&closure->main_loop_cond);
1068 g_mutex_unlock (&closure->main_loop_mutex);
1070 return FALSE;
1073 static gpointer
1074 source_registry_object_manager_thread (gpointer data)
1076 GDBusObjectManager *object_manager;
1077 ThreadClosure *closure = data;
1078 GSource *idle_source;
1079 GList *list, *link;
1080 gulong object_added_handler_id = 0;
1081 gulong object_removed_handler_id = 0;
1082 gulong notify_name_owner_handler_id = 0;
1084 /* GDBusObjectManagerClient grabs the thread-default GMainContext
1085 * at creation time and only emits signals from that GMainContext.
1086 * Running it in a separate thread prevents its signal emissions
1087 * from being inhibited by someone overriding the thread-default
1088 * GMainContext. */
1090 /* This becomes the GMainContext that GDBusObjectManagerClient
1091 * will emit signals from. Make it the thread-default context
1092 * for this thread before creating the client. */
1093 g_main_context_push_thread_default (closure->main_context);
1095 object_manager = e_dbus_object_manager_client_new_for_bus_sync (
1096 G_BUS_TYPE_SESSION,
1097 G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
1098 SOURCES_DBUS_SERVICE_NAME,
1099 DBUS_OBJECT_PATH,
1100 NULL, &closure->error);
1102 /* Sanity check. */
1103 g_warn_if_fail (
1104 ((object_manager != NULL) && (closure->error == NULL)) ||
1105 ((object_manager == NULL) && (closure->error != NULL)));
1107 /* If we failed to create the GDBusObjectManagerClient, skip
1108 * straight to the main loop. The GError will be propagated
1109 * back to the caller, the main loop will terminate, and the
1110 * partially-initialized ESourceRegistry will be destroyed. */
1111 if (object_manager == NULL)
1112 goto notify;
1114 /* Give the registry a handle to the object manager. */
1115 closure->registry->priv->dbus_object_manager =
1116 g_object_ref (object_manager);
1118 /* Now populate the registry with an initial set of ESources. */
1120 list = g_dbus_object_manager_get_objects (object_manager);
1122 for (link = list; link != NULL; link = g_list_next (link)) {
1123 GDBusObject *dbus_object;
1124 ESource *source;
1126 dbus_object = G_DBUS_OBJECT (link->data);
1128 source = source_registry_new_source (
1129 closure->registry, dbus_object);
1131 if (source != NULL) {
1132 source_registry_add_source (
1133 closure->registry, source);
1134 g_object_unref (source);
1138 g_list_free_full (list, (GDestroyNotify) g_object_unref);
1140 /* Listen for D-Bus object additions and removals. */
1142 object_added_handler_id = g_signal_connect (
1143 object_manager, "object-added",
1144 G_CALLBACK (source_registry_object_added_cb),
1145 closure->registry);
1147 object_removed_handler_id = g_signal_connect (
1148 object_manager, "object-removed",
1149 G_CALLBACK (source_registry_object_removed_cb),
1150 closure->registry);
1152 notify_name_owner_handler_id = g_signal_connect (
1153 object_manager, "notify::name-owner",
1154 G_CALLBACK (source_registry_notify_name_owner_cb),
1155 closure->registry);
1157 notify:
1158 /* Schedule a one-time idle callback to broadcast through a
1159 * condition variable that our main loop is up and running. */
1161 idle_source = g_idle_source_new ();
1162 g_source_set_callback (
1163 idle_source,
1164 source_registry_object_manager_running,
1165 closure, (GDestroyNotify) NULL);
1166 g_source_attach (idle_source, closure->main_context);
1167 g_source_unref (idle_source);
1169 /* Now we mostly idle here for the rest of the session. */
1171 g_main_loop_run (closure->main_loop);
1173 /* Clean up and exit. */
1175 if (object_manager != NULL) {
1176 g_signal_handler_disconnect (
1177 object_manager, object_added_handler_id);
1178 g_signal_handler_disconnect (
1179 object_manager, object_removed_handler_id);
1180 g_signal_handler_disconnect (
1181 object_manager, notify_name_owner_handler_id);
1182 g_object_unref (object_manager);
1185 /* Make sure the queue is flushed, because items in it can reference
1186 the main_context, effectively causing it to leak, together with
1187 its GWakeup ([eventfd]) file descriptor. */
1188 while (g_main_context_pending (closure->main_context)) {
1189 g_main_context_iteration (closure->main_context, FALSE);
1192 g_main_context_pop_thread_default (closure->main_context);
1194 return NULL;
1197 static void
1198 source_registry_set_property (GObject *object,
1199 guint property_id,
1200 const GValue *value,
1201 GParamSpec *pspec)
1203 switch (property_id) {
1204 case PROP_DEFAULT_ADDRESS_BOOK:
1205 e_source_registry_set_default_address_book (
1206 E_SOURCE_REGISTRY (object),
1207 g_value_get_object (value));
1208 return;
1210 case PROP_DEFAULT_CALENDAR:
1211 e_source_registry_set_default_calendar (
1212 E_SOURCE_REGISTRY (object),
1213 g_value_get_object (value));
1214 return;
1216 case PROP_DEFAULT_MAIL_ACCOUNT:
1217 e_source_registry_set_default_mail_account (
1218 E_SOURCE_REGISTRY (object),
1219 g_value_get_object (value));
1220 return;
1222 case PROP_DEFAULT_MAIL_IDENTITY:
1223 e_source_registry_set_default_mail_identity (
1224 E_SOURCE_REGISTRY (object),
1225 g_value_get_object (value));
1226 return;
1228 case PROP_DEFAULT_MEMO_LIST:
1229 e_source_registry_set_default_memo_list (
1230 E_SOURCE_REGISTRY (object),
1231 g_value_get_object (value));
1232 return;
1234 case PROP_DEFAULT_TASK_LIST:
1235 e_source_registry_set_default_task_list (
1236 E_SOURCE_REGISTRY (object),
1237 g_value_get_object (value));
1238 return;
1241 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1244 static void
1245 source_registry_get_property (GObject *object,
1246 guint property_id,
1247 GValue *value,
1248 GParamSpec *pspec)
1250 switch (property_id) {
1251 case PROP_DEFAULT_ADDRESS_BOOK:
1252 g_value_take_object (
1253 value,
1254 e_source_registry_ref_default_address_book (
1255 E_SOURCE_REGISTRY (object)));
1256 return;
1258 case PROP_DEFAULT_CALENDAR:
1259 g_value_take_object (
1260 value,
1261 e_source_registry_ref_default_calendar (
1262 E_SOURCE_REGISTRY (object)));
1263 return;
1265 case PROP_DEFAULT_MAIL_ACCOUNT:
1266 g_value_take_object (
1267 value,
1268 e_source_registry_ref_default_mail_account (
1269 E_SOURCE_REGISTRY (object)));
1270 return;
1272 case PROP_DEFAULT_MAIL_IDENTITY:
1273 g_value_take_object (
1274 value,
1275 e_source_registry_ref_default_mail_identity (
1276 E_SOURCE_REGISTRY (object)));
1277 return;
1279 case PROP_DEFAULT_MEMO_LIST:
1280 g_value_take_object (
1281 value,
1282 e_source_registry_ref_default_memo_list (
1283 E_SOURCE_REGISTRY (object)));
1284 return;
1286 case PROP_DEFAULT_TASK_LIST:
1287 g_value_take_object (
1288 value,
1289 e_source_registry_ref_default_task_list (
1290 E_SOURCE_REGISTRY (object)));
1291 return;
1294 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1297 static void
1298 source_registry_dispose (GObject *object)
1300 ESourceRegistryPrivate *priv;
1302 priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
1304 if (priv->dbus_object_manager != NULL) {
1305 g_object_unref (priv->dbus_object_manager);
1306 priv->dbus_object_manager = NULL;
1309 if (priv->dbus_source_manager != NULL) {
1310 g_object_unref (priv->dbus_source_manager);
1311 priv->dbus_source_manager = NULL;
1314 /* Terminate the manager thread after GDBus objects,
1315 because they can schedule GSource-s in the main context there. */
1316 if (priv->manager_thread != NULL) {
1317 g_main_loop_quit (priv->thread_closure->main_loop);
1318 g_thread_join (priv->manager_thread);
1319 priv->manager_thread = NULL;
1322 if (priv->thread_closure) {
1323 thread_closure_free (priv->thread_closure);
1324 priv->thread_closure = NULL;
1327 g_hash_table_remove_all (priv->object_path_table);
1329 g_hash_table_remove_all (priv->sources);
1331 if (priv->main_context != NULL) {
1332 while (g_main_context_pending (priv->main_context)) {
1333 g_main_context_iteration (priv->main_context, FALSE);
1335 g_main_context_unref (priv->main_context);
1336 priv->main_context = NULL;
1339 if (priv->settings != NULL) {
1340 g_signal_handlers_disconnect_by_data (priv->settings, object);
1341 g_object_unref (priv->settings);
1342 priv->settings = NULL;
1345 /* Chain up to parent's finalize() method. */
1346 G_OBJECT_CLASS (e_source_registry_parent_class)->dispose (object);
1349 static void
1350 source_registry_finalize (GObject *object)
1352 ESourceRegistryPrivate *priv;
1354 priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
1356 g_hash_table_destroy (priv->object_path_table);
1357 g_mutex_clear (&priv->object_path_table_lock);
1359 g_hash_table_destroy (priv->service_restart_table);
1360 g_mutex_clear (&priv->service_restart_table_lock);
1362 g_hash_table_destroy (priv->sources);
1363 g_mutex_clear (&priv->sources_lock);
1365 g_clear_error (&priv->init_error);
1366 g_mutex_clear (&priv->init_lock);
1368 g_clear_object (&priv->oauth2_services);
1370 /* Chain up to parent's finalize() method. */
1371 G_OBJECT_CLASS (e_source_registry_parent_class)->finalize (object);
1374 static gboolean
1375 source_registry_initable_init (GInitable *initable,
1376 GCancellable *cancellable,
1377 GError **error)
1379 ESourceRegistry *registry;
1380 ThreadClosure *closure;
1381 GError *local_error = NULL;
1383 registry = E_SOURCE_REGISTRY (initable);
1385 g_mutex_lock (&registry->priv->init_lock);
1387 if (registry->priv->initialized)
1388 goto exit;
1390 closure = g_slice_new0 (ThreadClosure);
1391 closure->registry = registry; /* do not reference */
1392 closure->main_context = g_main_context_new ();
1393 /* It's important to pass 'is_running=FALSE' here because
1394 * we wait for the main loop to start running as a way of
1395 * synchronizing with the manager thread. */
1396 closure->main_loop = g_main_loop_new (closure->main_context, FALSE);
1397 g_cond_init (&closure->main_loop_cond);
1398 g_mutex_init (&closure->main_loop_mutex);
1400 registry->priv->thread_closure = closure;
1402 registry->priv->manager_thread = g_thread_new (
1403 NULL,
1404 source_registry_object_manager_thread,
1405 closure);
1407 /* Wait for notification that the manager
1408 * thread's main loop has been started. */
1409 g_mutex_lock (&closure->main_loop_mutex);
1410 while (!g_main_loop_is_running (closure->main_loop))
1411 g_cond_wait (
1412 &closure->main_loop_cond,
1413 &closure->main_loop_mutex);
1414 g_mutex_unlock (&closure->main_loop_mutex);
1416 /* Check for error in the manager thread. */
1417 if (closure->error != NULL) {
1418 g_dbus_error_strip_remote_error (closure->error);
1419 g_propagate_error (&registry->priv->init_error, closure->error);
1420 closure->error = NULL;
1421 goto exit;
1424 /* The registry should now be populated with sources.
1426 * XXX Actually, not necessarily if the registry service was
1427 * just now activated. There may yet be a small window
1428 * while the registry service starts up before it exports
1429 * any sources, even built-in sources. This COULD create
1430 * problems if any logic that depends on those built-in
1431 * sources executes during this time window, but so far
1432 * we haven't seen any cases of that.
1434 * Attempts in the past to stop and wait for sources to
1435 * show up have proven problematic. See for example:
1436 * https://bugzilla.gnome.org/678378
1438 * Leave the runtime check disabled for the moment.
1439 * I have a feeling I'll be revisiting this again.
1441 /*g_warn_if_fail (g_hash_table_size (registry->priv->sources) > 0);*/
1443 /* The EDBusSourceManagerProxy is just another D-Bus interface
1444 * that resides at the same object path. It's unrelated to the
1445 * GDBusObjectManagerClient and doesn't need its own thread. */
1446 registry->priv->dbus_source_manager =
1447 e_dbus_source_manager_proxy_new_for_bus_sync (
1448 G_BUS_TYPE_SESSION,
1449 G_DBUS_PROXY_FLAGS_NONE,
1450 SOURCES_DBUS_SERVICE_NAME,
1451 DBUS_OBJECT_PATH,
1452 cancellable, &local_error);
1454 if (local_error != NULL) {
1455 g_dbus_error_strip_remote_error (local_error);
1456 g_propagate_error (&registry->priv->init_error, local_error);
1457 goto exit;
1460 exit:
1461 registry->priv->initialized = TRUE;
1462 g_mutex_unlock (&registry->priv->init_lock);
1464 if (registry->priv->init_error != NULL) {
1465 GError *init_error_copy;
1467 /* Return a copy of the same error to
1468 * all pending initialization requests. */
1469 init_error_copy = g_error_copy (registry->priv->init_error);
1470 g_propagate_error (error, init_error_copy);
1472 return FALSE;
1475 return TRUE;
1478 static void
1479 e_source_registry_class_init (ESourceRegistryClass *class)
1481 GObjectClass *object_class;
1483 g_type_class_add_private (class, sizeof (ESourceRegistryPrivate));
1485 object_class = G_OBJECT_CLASS (class);
1486 object_class->set_property = source_registry_set_property;
1487 object_class->get_property = source_registry_get_property;
1488 object_class->dispose = source_registry_dispose;
1489 object_class->finalize = source_registry_finalize;
1491 /* The property names correspond to the key names in the
1492 * "org.gnome.Evolution.DefaultSources" GSettings schema. */
1495 * ESourceRegistry:default-address-book:
1497 * The default address book #ESource.
1499 g_object_class_install_property (
1500 object_class,
1501 PROP_DEFAULT_ADDRESS_BOOK,
1502 g_param_spec_object (
1503 "default-address-book",
1504 "Default Address Book",
1505 "The default address book ESource",
1506 E_TYPE_SOURCE,
1507 G_PARAM_READWRITE |
1508 G_PARAM_STATIC_STRINGS));
1511 * ESourceRegistry:default-calendar:
1513 * The default calendar #ESource.
1515 g_object_class_install_property (
1516 object_class,
1517 PROP_DEFAULT_CALENDAR,
1518 g_param_spec_object (
1519 "default-calendar",
1520 "Default Calendar",
1521 "The default calendar ESource",
1522 E_TYPE_SOURCE,
1523 G_PARAM_READWRITE |
1524 G_PARAM_STATIC_STRINGS));
1527 * ESourceRegistry:default-mail-account:
1529 * The default mail account #ESource.
1531 g_object_class_install_property (
1532 object_class,
1533 PROP_DEFAULT_MAIL_ACCOUNT,
1534 g_param_spec_object (
1535 "default-mail-account",
1536 "Default Mail Account",
1537 "The default mail account ESource",
1538 E_TYPE_SOURCE,
1539 G_PARAM_READWRITE |
1540 G_PARAM_STATIC_STRINGS));
1543 * ESourceRegistry:default-mail-identity:
1545 * The default mail identity #ESource.
1547 g_object_class_install_property (
1548 object_class,
1549 PROP_DEFAULT_MAIL_IDENTITY,
1550 g_param_spec_object (
1551 "default-mail-identity",
1552 "Default Mail Identity",
1553 "The default mail identity ESource",
1554 E_TYPE_SOURCE,
1555 G_PARAM_READWRITE |
1556 G_PARAM_STATIC_STRINGS));
1559 * ESourceRegistry:default-memo-list:
1561 * The default memo list #ESource.
1563 g_object_class_install_property (
1564 object_class,
1565 PROP_DEFAULT_MEMO_LIST,
1566 g_param_spec_object (
1567 "default-memo-list",
1568 "Default Memo List",
1569 "The default memo list ESource",
1570 E_TYPE_SOURCE,
1571 G_PARAM_READWRITE |
1572 G_PARAM_STATIC_STRINGS));
1575 * ESourceRegistry:default-task-list:
1577 * The default task list #ESource.
1579 g_object_class_install_property (
1580 object_class,
1581 PROP_DEFAULT_TASK_LIST,
1582 g_param_spec_object (
1583 "default-task-list",
1584 "Default Task List",
1585 "The default task list ESource",
1586 E_TYPE_SOURCE,
1587 G_PARAM_READWRITE |
1588 G_PARAM_STATIC_STRINGS));
1591 * ESourceRegistry::source-added:
1592 * @registry: the #ESourceRegistry which emitted the signal
1593 * @source: the newly-added #ESource
1595 * Emitted when an #ESource is added to @registry.
1597 signals[SOURCE_ADDED] = g_signal_new (
1598 "source-added",
1599 G_OBJECT_CLASS_TYPE (object_class),
1600 G_SIGNAL_RUN_LAST,
1601 G_STRUCT_OFFSET (ESourceRegistryClass, source_added),
1602 NULL, NULL, NULL,
1603 G_TYPE_NONE, 1,
1604 E_TYPE_SOURCE);
1607 * ESourceRegistry::source-changed:
1608 * @registry: the #ESourceRegistry which emitted the signal
1609 * @source: the #ESource that changed
1611 * Emitted when an #ESource registered with @registry emits
1612 * its #ESource::changed signal.
1614 signals[SOURCE_CHANGED] = g_signal_new (
1615 "source-changed",
1616 G_OBJECT_CLASS_TYPE (object_class),
1617 G_SIGNAL_RUN_LAST,
1618 G_STRUCT_OFFSET (ESourceRegistryClass, source_changed),
1619 NULL, NULL, NULL,
1620 G_TYPE_NONE, 1,
1621 E_TYPE_SOURCE);
1624 * ESourceRegistry::source-removed:
1625 * @registry: the #ESourceRegistry which emitted the signal
1626 * @source: the #ESource that got removed
1628 * Emitted when an #ESource is removed from @registry.
1630 signals[SOURCE_REMOVED] = g_signal_new (
1631 "source-removed",
1632 G_OBJECT_CLASS_TYPE (object_class),
1633 G_SIGNAL_RUN_LAST,
1634 G_STRUCT_OFFSET (ESourceRegistryClass, source_removed),
1635 NULL, NULL, NULL,
1636 G_TYPE_NONE, 1,
1637 E_TYPE_SOURCE);
1640 * ESourceRegistry::source-enabled:
1641 * @registry: the #ESourceRegistry which emitted the signal
1642 * @source: the #ESource that got enabled
1644 * Emitted when an #ESource #ESource:enabled property becomes %TRUE.
1646 signals[SOURCE_ENABLED] = g_signal_new (
1647 "source-enabled",
1648 G_OBJECT_CLASS_TYPE (object_class),
1649 G_SIGNAL_RUN_LAST,
1650 G_STRUCT_OFFSET (ESourceRegistryClass, source_enabled),
1651 NULL, NULL, NULL,
1652 G_TYPE_NONE, 1,
1653 E_TYPE_SOURCE);
1656 * ESourceRegistry::source-disabled:
1657 * @registry: the #ESourceRegistry which emitted the signal
1658 * @source: the #ESource that got disabled
1660 * Emitted when an #ESource #ESource:enabled property becomes %FALSE.
1662 signals[SOURCE_DISABLED] = g_signal_new (
1663 "source-disabled",
1664 G_OBJECT_CLASS_TYPE (object_class),
1665 G_SIGNAL_RUN_LAST,
1666 G_STRUCT_OFFSET (ESourceRegistryClass, source_disabled),
1667 NULL, NULL, NULL,
1668 G_TYPE_NONE, 1,
1669 E_TYPE_SOURCE);
1672 * ESourceRegistry::credentials-required:
1673 * @registry: the #ESourceRegistry which emitted the signal
1674 * @source: the #ESource that requires credentials
1675 * @reason: an #ESourceCredentialsReason indicating why the credentials are requested
1676 * @certificate_pem: PEM-encoded secure connection certificate for failed SSL checks
1677 * @certificate_errors: what failed with the SSL certificate
1678 * @op_error: a #GError with a description of the error, or %NULL
1680 * The ::credentials-required signal is emitted when the @source
1681 * requires credentials to connect to (possibly remote)
1682 * data store. The credentials can be passed to the source using
1683 * e_source_authenticate() function. The signal is emitted in
1684 * the thread-default main context from the time the @registry was created.
1686 * Note: This is just a proxy signal for the ESource::credentials-required signal.
1688 signals[CREDENTIALS_REQUIRED] = g_signal_new (
1689 "credentials-required",
1690 G_TYPE_FROM_CLASS (class),
1691 G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
1692 G_STRUCT_OFFSET (ESourceRegistryClass, credentials_required),
1693 NULL, NULL, NULL,
1694 G_TYPE_NONE, 5,
1695 E_TYPE_SOURCE,
1696 E_TYPE_SOURCE_CREDENTIALS_REASON,
1697 G_TYPE_STRING,
1698 G_TYPE_TLS_CERTIFICATE_FLAGS,
1699 G_TYPE_ERROR);
1702 static void
1703 e_source_registry_initable_init (GInitableIface *iface)
1705 iface->init = source_registry_initable_init;
1708 static void
1709 e_source_registry_init (ESourceRegistry *registry)
1711 registry->priv = E_SOURCE_REGISTRY_GET_PRIVATE (registry);
1713 /* This is so the object manager thread can schedule signal
1714 * emissions on the thread-default context for this thread. */
1715 registry->priv->main_context = g_main_context_ref_thread_default ();
1717 /* D-Bus object path -> ESource */
1718 registry->priv->object_path_table =
1719 g_hash_table_new_full (
1720 (GHashFunc) g_str_hash,
1721 (GEqualFunc) g_str_equal,
1722 (GDestroyNotify) g_free,
1723 (GDestroyNotify) g_object_unref);
1725 g_mutex_init (&registry->priv->object_path_table_lock);
1727 /* Set of UID strings */
1728 registry->priv->service_restart_table =
1729 g_hash_table_new_full (
1730 (GHashFunc) g_str_hash,
1731 (GEqualFunc) g_str_equal,
1732 (GDestroyNotify) g_free,
1733 (GDestroyNotify) NULL);
1735 g_mutex_init (&registry->priv->service_restart_table_lock);
1737 /* UID string -> ESource */
1738 registry->priv->sources = g_hash_table_new_full (
1739 (GHashFunc) g_str_hash,
1740 (GEqualFunc) g_str_equal,
1741 (GDestroyNotify) g_free,
1742 (GDestroyNotify) source_registry_unref_source);
1744 g_mutex_init (&registry->priv->sources_lock);
1746 registry->priv->settings = g_settings_new (GSETTINGS_SCHEMA);
1748 g_signal_connect (
1749 registry->priv->settings, "changed",
1750 G_CALLBACK (source_registry_settings_changed_cb), registry);
1752 g_mutex_init (&registry->priv->init_lock);
1754 registry->priv->oauth2_services = e_oauth2_services_new ();
1758 * e_source_registry_new_sync:
1759 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1760 * @error: return location for a #GError, or %NULL
1762 * Creates a new #ESourceRegistry front-end for the registry D-Bus service.
1763 * If an error occurs in connecting to the D-Bus service, the function sets
1764 * @error and returns %NULL.
1766 * Since 3.12 a singleton will be returned. No strong reference is kept
1767 * internally, so it is the caller's responsibility to keep one.
1769 * Returns: a new #ESourceRegistry, or %NULL
1771 * Since: 3.6
1773 ESourceRegistry *
1774 e_source_registry_new_sync (GCancellable *cancellable,
1775 GError **error)
1777 ESourceRegistry *registry;
1779 /* XXX Work around http://bugzilla.gnome.org/show_bug.cgi?id=683519
1780 * until GObject's type initialization deadlock issue is fixed.
1781 * Apparently only the synchronous instantiation is affected. */
1782 g_type_ensure (G_TYPE_DBUS_CONNECTION);
1783 g_type_ensure (G_TYPE_DBUS_PROXY);
1784 g_type_ensure (G_BUS_TYPE_SESSION);
1786 registry = source_registry_dup_uninitialized_singleton ();
1788 if (!g_initable_init (G_INITABLE (registry), cancellable, error))
1789 g_clear_object (&registry);
1791 return registry;
1794 /* Helper for e_source_registry_new() */
1795 static void
1796 source_registry_init_cb (GObject *source_object,
1797 GAsyncResult *result,
1798 gpointer user_data)
1800 GTask *task = user_data;
1801 GError *local_error = NULL;
1803 g_async_initable_init_finish (
1804 G_ASYNC_INITABLE (source_object), result, &local_error);
1806 if (local_error == NULL) {
1807 g_task_return_pointer (
1808 task, g_object_ref (source_object),
1809 (GDestroyNotify) g_object_unref);
1810 } else {
1811 g_task_return_error (task, local_error);
1814 g_object_unref (task);
1818 * e_source_registry_new:
1819 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1820 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1821 * is satisfied
1822 * @user_data: (closure): data to pass to the callback function
1824 * Asynchronously creates a new #ESourceRegistry front-end for the registry
1825 * D-Bus service.
1827 * When the operation is finished, @callback will be called. You can then
1828 * call e_source_registry_new_finish() to get the result of the operation.
1830 * Since 3.12 a singleton will be returned. No strong reference is kept
1831 * internally, so it is the caller's responsibility to keep one.
1833 * Since: 3.6
1835 void
1836 e_source_registry_new (GCancellable *cancellable,
1837 GAsyncReadyCallback callback,
1838 gpointer user_data)
1840 ESourceRegistry *registry;
1841 GTask *task;
1843 task = g_task_new (NULL, cancellable, callback, user_data);
1845 registry = source_registry_dup_uninitialized_singleton ();
1847 g_async_initable_init_async (
1848 G_ASYNC_INITABLE (registry),
1849 G_PRIORITY_DEFAULT, cancellable,
1850 source_registry_init_cb, task);
1852 g_object_unref (registry);
1856 * e_source_registry_new_finish:
1857 * @result: a #GAsyncResult
1858 * @error: return location for a #GError, or %NULL
1860 * Finishes the operation started with e_source_registry_new_finish().
1861 * If an error occurs in connecting to the D-Bus service, the function
1862 * sets @error and returns %NULL.
1864 * Returns: a new #ESourceRegistry, or %NULL
1866 * Since: 3.6
1868 ESourceRegistry *
1869 e_source_registry_new_finish (GAsyncResult *result,
1870 GError **error)
1872 g_return_val_if_fail (g_task_is_valid (result, NULL), NULL);
1874 return g_task_propagate_pointer (G_TASK (result), error);
1878 * e_source_registry_get_oauth2_services:
1879 * @registry: an #ESourceRegistry
1881 * Returns: (transfer none): an instance of #EOAuth2Services, owned by @registry
1883 * Since: 3.28
1885 EOAuth2Services *
1886 e_source_registry_get_oauth2_services (ESourceRegistry *registry)
1888 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
1890 return registry->priv->oauth2_services;
1893 /* Helper for e_source_registry_commit_source() */
1894 static void
1895 source_registry_commit_source_thread (GSimpleAsyncResult *simple,
1896 GObject *object,
1897 GCancellable *cancellable)
1899 AsyncContext *async_context;
1900 GError *local_error = NULL;
1902 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1904 e_source_registry_commit_source_sync (
1905 E_SOURCE_REGISTRY (object),
1906 async_context->source,
1907 cancellable, &local_error);
1909 if (local_error != NULL)
1910 g_simple_async_result_take_error (simple, local_error);
1914 * e_source_registry_commit_source_sync:
1915 * @registry: an #ESourceRegistry
1916 * @source: an #ESource with changes to commit
1917 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1918 * @error: return location for #GError, or %NULL
1920 * This is a convenience function intended for use with graphical
1921 * #ESource editors. Call this function when the user is finished
1922 * making changes to @source.
1924 * If @source has a #GDBusObject, its contents are submitted to the D-Bus
1925 * service through e_source_write_sync().
1927 * If @source does NOT have a #GDBusObject (implying it's a scratch
1928 * #ESource), its contents are submitted to the D-Bus service through
1929 * either e_source_remote_create_sync() if @source is to be a collection
1930 * member, or e_source_registry_create_sources_sync() if @source to be an
1931 * independent data source.
1933 * If an error occurs, the function will set @error and return %FALSE.
1935 * Returns: %TRUE on success, %FALSE on failure
1937 * Since: 3.6
1939 gboolean
1940 e_source_registry_commit_source_sync (ESourceRegistry *registry,
1941 ESource *source,
1942 GCancellable *cancellable,
1943 GError **error)
1945 GDBusObject *dbus_object;
1946 ESource *collection_source;
1947 gboolean collection_member;
1948 gboolean success;
1950 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
1951 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
1953 dbus_object = e_source_ref_dbus_object (source);
1955 collection_source = e_source_registry_find_extension (
1956 registry, source, E_SOURCE_EXTENSION_COLLECTION);
1958 collection_member =
1959 (collection_source != NULL) &&
1960 (collection_source != source);
1962 if (dbus_object != NULL) {
1963 success = e_source_write_sync (source, cancellable, error);
1964 g_object_unref (dbus_object);
1966 } else if (collection_member) {
1967 success = e_source_remote_create_sync (
1968 collection_source, source, cancellable, error);
1970 } else {
1971 GList *list = g_list_prepend (NULL, source);
1972 success = e_source_registry_create_sources_sync (
1973 registry, list, cancellable, error);
1974 g_list_free (list);
1977 if (collection_source != NULL)
1978 g_object_unref (collection_source);
1980 return success;
1984 * e_source_registry_commit_source:
1985 * @registry: an #ESourceRegistry
1986 * @source: an #ESource with changes to commit
1987 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
1988 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
1989 * is satisfied
1990 * @user_data: (closure): data to pass to the callback function
1992 * See e_source_registry_commit_source_sync() for details.
1994 * When the operation is finished, @callback will be called. You can then
1995 * call e_source_registry_commit_source_finish() to get the result of the
1996 * operation.
1998 * Since: 3.6
2000 void
2001 e_source_registry_commit_source (ESourceRegistry *registry,
2002 ESource *source,
2003 GCancellable *cancellable,
2004 GAsyncReadyCallback callback,
2005 gpointer user_data)
2007 GSimpleAsyncResult *simple;
2008 AsyncContext *async_context;
2010 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2011 g_return_if_fail (E_IS_SOURCE (source));
2013 async_context = g_slice_new0 (AsyncContext);
2014 async_context->source = g_object_ref (source);
2016 simple = g_simple_async_result_new (
2017 G_OBJECT (registry), callback, user_data,
2018 e_source_registry_commit_source);
2020 g_simple_async_result_set_check_cancellable (simple, cancellable);
2022 g_simple_async_result_set_op_res_gpointer (
2023 simple, async_context, (GDestroyNotify) async_context_free);
2025 g_simple_async_result_run_in_thread (
2026 simple, source_registry_commit_source_thread,
2027 G_PRIORITY_DEFAULT, cancellable);
2029 g_object_unref (simple);
2033 * e_source_registry_commit_source_finish:
2034 * @registry: an #ESourceRegistry
2035 * @result: a #GAsyncResult
2036 * @error: return location for a #GError, or %NULL
2038 * Finishes the operation started with e_source_registry_commit_source().
2040 * If an error occurred, the function will set @error and return %FALSE.
2042 * Returns: %TRUE on success, %FALSE on failure
2044 * Since: 3.6
2046 gboolean
2047 e_source_registry_commit_source_finish (ESourceRegistry *registry,
2048 GAsyncResult *result,
2049 GError **error)
2051 GSimpleAsyncResult *simple;
2053 g_return_val_if_fail (
2054 g_simple_async_result_is_valid (
2055 result, G_OBJECT (registry),
2056 e_source_registry_commit_source), FALSE);
2058 simple = G_SIMPLE_ASYNC_RESULT (result);
2060 /* Assume success unless a GError is set. */
2061 return !g_simple_async_result_propagate_error (simple, error);
2064 /* Helper for e_source_registry_create_sources() */
2065 static void
2066 source_registry_create_sources_thread (GSimpleAsyncResult *simple,
2067 GObject *object,
2068 GCancellable *cancellable)
2070 AsyncContext *async_context;
2071 GError *local_error = NULL;
2073 async_context = g_simple_async_result_get_op_res_gpointer (simple);
2075 e_source_registry_create_sources_sync (
2076 E_SOURCE_REGISTRY (object),
2077 async_context->list_of_sources,
2078 cancellable, &local_error);
2080 if (local_error != NULL)
2081 g_simple_async_result_take_error (simple, local_error);
2084 /* Helper for e_source_registry_create_sources_sync() */
2085 static gboolean
2086 source_registry_create_sources_main_loop_quit_cb (gpointer user_data)
2088 GMainLoop *main_loop = user_data;
2090 g_main_loop_quit (main_loop);
2092 return FALSE;
2095 /* Helper for e_source_registry_create_sources_sync() */
2096 static void
2097 source_registry_create_sources_object_added_cb (GDBusObjectManager *object_manager,
2098 GDBusObject *dbus_object,
2099 CreateContext *create_context)
2101 gchar *uid;
2103 uid = source_registry_dbus_object_dup_uid (dbus_object);
2105 if (uid != NULL) {
2106 g_hash_table_remove (create_context->pending_uids, uid);
2107 g_free (uid);
2110 /* The hash table will be empty when all of the expected
2111 * GDBusObjects have been added to the GDBusObjectManager. */
2112 if (g_hash_table_size (create_context->pending_uids) == 0) {
2113 GSource *idle_source;
2115 idle_source = g_idle_source_new ();
2116 g_source_set_callback (
2117 idle_source,
2118 source_registry_create_sources_main_loop_quit_cb,
2119 g_main_loop_ref (create_context->main_loop),
2120 (GDestroyNotify) g_main_loop_unref);
2121 g_source_attach (idle_source, create_context->main_context);
2122 g_source_unref (idle_source);
2127 * e_source_registry_create_sources_sync:
2128 * @registry: an #ESourceRegistry
2129 * @list_of_sources: (element-type ESource): a list of #ESource instances with
2130 * no #GDBusObject
2131 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2132 * @error: return location for a #GError, or %NULL
2134 * Requests the D-Bus service create new key files for each #ESource in
2135 * @list_of_sources. Each list element must be a scratch #ESource with
2136 * no #GDBusObject.
2138 * If an error occurs, the function will set @error and return %FALSE.
2140 * Returns: %TRUE on success, %FALSE on failure
2142 * Since: 3.6
2144 gboolean
2145 e_source_registry_create_sources_sync (ESourceRegistry *registry,
2146 GList *list_of_sources,
2147 GCancellable *cancellable,
2148 GError **error)
2150 CreateContext *create_context;
2151 GVariantBuilder builder;
2152 GVariant *variant;
2153 GList *link;
2154 gulong object_added_id;
2155 GError *local_error = NULL;
2157 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
2159 /* Verify the list elements are all ESources. */
2160 for (link = list_of_sources; link != NULL; link = g_list_next (link))
2161 g_return_val_if_fail (E_IS_SOURCE (link->data), FALSE);
2163 create_context = create_context_new ();
2164 g_main_context_push_thread_default (create_context->main_context);
2166 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
2168 for (link = list_of_sources; link != NULL; link = g_list_next (link)) {
2169 ESource *source;
2170 gchar *source_data;
2171 gchar *uid;
2173 source = E_SOURCE (link->data);
2174 uid = e_source_dup_uid (source);
2176 /* Takes ownership of the UID string. */
2177 g_hash_table_add (create_context->pending_uids, uid);
2179 source_data = e_source_to_string (source, NULL);
2180 g_variant_builder_add (&builder, "{ss}", uid, source_data);
2181 g_free (source_data);
2184 variant = g_variant_builder_end (&builder);
2186 /* Use G_CONNECT_AFTER so source_registry_object_added_cb()
2187 * runs first and actually adds the ESource to the internal
2188 * hash table before we go quitting our main loop. */
2189 object_added_id = g_signal_connect_after (
2190 registry->priv->dbus_object_manager, "object-added",
2191 G_CALLBACK (source_registry_create_sources_object_added_cb),
2192 create_context);
2194 /* This function sinks the floating GVariant reference. */
2195 e_dbus_source_manager_call_create_sources_sync (
2196 registry->priv->dbus_source_manager,
2197 variant, cancellable, &local_error);
2199 g_variant_builder_clear (&builder);
2201 /* Wait for an "object-added" signal for each created ESource.
2202 * But also set a short timeout to avoid getting stuck here in
2203 * case the registry service adds sources to its orphan table,
2204 * which prevents them from being exported over D-Bus. */
2205 if (local_error == NULL) {
2206 GSource *timeout_source;
2208 timeout_source = g_timeout_source_new_seconds (2);
2209 g_source_set_callback (
2210 timeout_source,
2211 source_registry_create_sources_main_loop_quit_cb,
2212 g_main_loop_ref (create_context->main_loop),
2213 (GDestroyNotify) g_main_loop_unref);
2214 g_source_attach (timeout_source, create_context->main_context);
2215 g_source_unref (timeout_source);
2217 g_main_loop_run (create_context->main_loop);
2220 g_signal_handler_disconnect (
2221 registry->priv->dbus_object_manager, object_added_id);
2223 g_main_context_pop_thread_default (create_context->main_context);
2224 create_context_free (create_context);
2226 if (local_error != NULL) {
2227 g_dbus_error_strip_remote_error (local_error);
2228 g_propagate_error (error, local_error);
2229 return FALSE;
2232 return TRUE;
2236 * e_source_registry_create_sources:
2237 * @registry: an #ESourceRegistry
2238 * @list_of_sources: (element-type ESource): a list of #ESource instances with
2239 * no #GDBusObject
2240 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2241 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2242 * is satisfied
2243 * @user_data: (closure): data to pass to the callback function
2245 * Asynchronously requests the D-Bus service create new key files for each
2246 * #ESource in @list_of_sources. Each list element must be a scratch
2247 * #ESource with no #GDBusObject.
2249 * When the operation is finished, @callback will be called. You can then
2250 * call e_source_registry_create_sources_finish() to get the result of the
2251 * operation.
2253 * Since: 3.6
2255 void
2256 e_source_registry_create_sources (ESourceRegistry *registry,
2257 GList *list_of_sources,
2258 GCancellable *cancellable,
2259 GAsyncReadyCallback callback,
2260 gpointer user_data)
2262 GSimpleAsyncResult *simple;
2263 AsyncContext *async_context;
2264 GList *link;
2266 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2268 /* Verify the list elements are all ESources. */
2269 for (link = list_of_sources; link != NULL; link = g_list_next (link))
2270 g_return_if_fail (E_IS_SOURCE (link->data));
2272 async_context = g_slice_new0 (AsyncContext);
2273 async_context->list_of_sources = g_list_copy (list_of_sources);
2275 g_list_foreach (
2276 async_context->list_of_sources,
2277 (GFunc) g_object_ref, NULL);
2279 simple = g_simple_async_result_new (
2280 G_OBJECT (registry), callback, user_data,
2281 e_source_registry_create_sources);
2283 g_simple_async_result_set_check_cancellable (simple, cancellable);
2285 g_simple_async_result_set_op_res_gpointer (
2286 simple, async_context, (GDestroyNotify) async_context_free);
2288 g_simple_async_result_run_in_thread (
2289 simple, source_registry_create_sources_thread,
2290 G_PRIORITY_DEFAULT, cancellable);
2292 g_object_unref (simple);
2296 * e_source_registry_create_sources_finish:
2297 * @registry: an #ESourceRegistry
2298 * @result: a #GAsyncResult
2299 * @error: return location for a #GError, or %NULL
2301 * Finishes the operation started with e_source_registry_create_sources().
2303 * If an error occurred, the function will set @error and return %FALSE.
2305 * Returns: %TRUE on success, %FALSE on failure
2307 * Since: 3.6
2309 gboolean
2310 e_source_registry_create_sources_finish (ESourceRegistry *registry,
2311 GAsyncResult *result,
2312 GError **error)
2314 GSimpleAsyncResult *simple;
2316 g_return_val_if_fail (
2317 g_simple_async_result_is_valid (
2318 result, G_OBJECT (registry),
2319 e_source_registry_create_sources), FALSE);
2321 simple = G_SIMPLE_ASYNC_RESULT (result);
2323 /* Assume success unless a GError is set. */
2324 return !g_simple_async_result_propagate_error (simple, error);
2328 * e_source_registry_refresh_backend_sync:
2329 * @registry: an #ESourceRegistry
2330 * @source_uid: UID of a collection #ESource whose backend to refresh
2331 * @cancellable: optional #GCancellable object, or %NULL
2332 * @error: return location for a #GError, or %NULL
2334 * Requests the D-Bus service to refresh collection backend for an #ESource
2335 * with UID @source_uid. The result means that the refresh had been scheduled
2336 * not whether the refresh itself succeeded. The refresh is not initiated
2337 * when the collection backend is offline.
2339 * If an error occurs, the function will set @error and return %FALSE.
2341 * Returns: Whether succeeded
2343 * Since: 3.30
2345 gboolean
2346 e_source_registry_refresh_backend_sync (ESourceRegistry *registry,
2347 const gchar *source_uid,
2348 GCancellable *cancellable,
2349 GError **error)
2351 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
2352 g_return_val_if_fail (source_uid != NULL, FALSE);
2354 return e_dbus_source_manager_call_refresh_backend_sync (
2355 registry->priv->dbus_source_manager,
2356 source_uid, cancellable, error);
2359 static void
2360 e_source_registry_refresh_backend_thread (GTask *task,
2361 gpointer source_object,
2362 gpointer task_data,
2363 GCancellable *cancellable)
2365 gboolean success;
2366 GError *local_error = NULL;
2368 success = e_source_registry_refresh_backend_sync (source_object, task_data, cancellable, &local_error);
2370 if (local_error)
2371 g_task_return_error (task, local_error);
2372 else
2373 g_task_return_boolean (task, success);
2377 * e_source_registry_refresh_backend:
2378 * @registry: an #ESourceRegistry
2379 * @source_uid: UID of a collection #ESource whose backend to refresh
2380 * @cancellable: optional #GCancellable object, or %NULL
2381 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2382 * is satisfied
2383 * @user_data: (closure): data to pass to the callback function
2385 * Asynchronously requests the D-Bus service to refresh collection backend
2386 * for an #ESource with UID @source_uid. The result means that the refresh
2387 * had been scheduled not whether the refresh itself succeeded. The refresh
2388 * is not initiated when the collection backend is offline.
2390 * When the operation is finished, @callback will be called. You can then
2391 * call e_source_registry_refresh_backend_finish() to get the result of
2392 * the operation.
2394 * Since: 3.30
2396 void
2397 e_source_registry_refresh_backend (ESourceRegistry *registry,
2398 const gchar *source_uid,
2399 GCancellable *cancellable,
2400 GAsyncReadyCallback callback,
2401 gpointer user_data)
2403 GTask *task;
2405 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
2406 g_return_if_fail (source_uid != NULL);
2408 task = g_task_new (registry, cancellable, callback, user_data);
2409 g_task_set_source_tag (task, e_source_registry_refresh_backend);
2410 g_task_set_task_data (task, g_strdup (source_uid), g_free);
2412 g_task_run_in_thread (task, e_source_registry_refresh_backend_thread);
2414 g_object_unref (task);
2418 * e_source_registry_refresh_backend_finish:
2419 * @registry: an #ESourceRegistry
2420 * @result: a #GAsyncResult
2421 * @error: return location for a #GError, or %NULL
2423 * Finishes the operation started with e_source_registry_refresh_backend().
2425 * If an error occurred, the function will set @error and return %FALSE.
2427 * Returns: Whether succeeded
2429 * Since: 3.30
2431 gboolean
2432 e_source_registry_refresh_backend_finish (ESourceRegistry *registry,
2433 GAsyncResult *result,
2434 GError **error)
2436 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
2437 g_return_val_if_fail (g_task_is_valid (result, registry), FALSE);
2438 g_return_val_if_fail (g_async_result_is_tagged (result, e_source_registry_refresh_backend), FALSE);
2440 return g_task_propagate_boolean (G_TASK (result), error);
2444 * e_source_registry_ref_source:
2445 * @registry: an #ESourceRegistry
2446 * @uid: a unique identifier string
2448 * Looks up an #ESource in @registry by its unique identifier string.
2450 * The returned #ESource is referenced for thread-safety and must be
2451 * unreferenced with g_object_unref() when finished with it.
2453 * Returns: (transfer full): an #ESource, or %NULL if no match was found
2455 * Since: 3.6
2457 ESource *
2458 e_source_registry_ref_source (ESourceRegistry *registry,
2459 const gchar *uid)
2461 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2462 g_return_val_if_fail (uid != NULL, NULL);
2464 return source_registry_sources_lookup (registry, uid);
2468 * e_source_registry_list_sources:
2469 * @registry: an #ESourceRegistry
2470 * @extension_name: (allow-none): an extension name, or %NULL
2472 * Returns a list of registered sources, sorted by display name. If
2473 * @extension_name is given, restrict the list to sources having that
2474 * extension name.
2476 * The sources returned in the list are referenced for thread-safety.
2477 * They must each be unreferenced with g_object_unref() when finished
2478 * with them. Free the returned list itself with g_list_free().
2480 * An easy way to free the list properly in one step is as follows:
2482 * |[
2483 * g_list_free_full (list, g_object_unref);
2484 * ]|
2486 * Returns: (element-type ESource) (transfer full): a sorted list of sources
2488 * Since: 3.6
2490 GList *
2491 e_source_registry_list_sources (ESourceRegistry *registry,
2492 const gchar *extension_name)
2494 GList *list, *link;
2495 GQueue trash = G_QUEUE_INIT;
2497 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2499 list = g_list_sort (
2500 source_registry_sources_get_values (registry),
2501 (GCompareFunc) e_source_compare_by_display_name);
2503 if (extension_name == NULL)
2504 return list;
2506 for (link = list; link != NULL; link = g_list_next (link)) {
2507 ESource *source = E_SOURCE (link->data);
2509 if (!e_source_has_extension (source, extension_name)) {
2510 g_queue_push_tail (&trash, link);
2511 g_object_unref (source);
2515 /* We do want pop_head() here, not pop_head_link(). */
2516 while ((link = g_queue_pop_head (&trash)) != NULL)
2517 list = g_list_delete_link (list, link);
2519 return list;
2523 * e_source_registry_list_enabled:
2524 * @registry: an #ESourceRegistry
2525 * @extension_name: (allow-none): an extension name, or %NULL
2527 * Similar to e_source_registry_list_sources(), but returns only enabled
2528 * sources according to e_source_registry_check_enabled().
2530 * The sources returned in the list are referenced for thread-safety.
2531 * They must each be unreferenced with g_object_unref() when finished
2532 * with them. Free the returned list itself with g_list_free().
2534 * An easy way to free the list properly in one step is as follows:
2536 * |[
2537 * g_list_free_full (list, g_object_unref);
2538 * ]|
2540 * Returns: (element-type ESource) (transfer full): a sorted list of sources
2542 * Since: 3.10
2544 GList *
2545 e_source_registry_list_enabled (ESourceRegistry *registry,
2546 const gchar *extension_name)
2548 GList *list, *link;
2549 GQueue trash = G_QUEUE_INIT;
2551 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2553 list = e_source_registry_list_sources (registry, extension_name);
2555 for (link = list; link != NULL; link = g_list_next (link)) {
2556 ESource *source = E_SOURCE (link->data);
2558 if (!e_source_registry_check_enabled (registry, source)) {
2559 g_queue_push_tail (&trash, link);
2560 g_object_unref (source);
2564 /* We do want pop_head() here, not pop_head_link(). */
2565 while ((link = g_queue_pop_head (&trash)) != NULL)
2566 list = g_list_delete_link (list, link);
2568 return list;
2572 * e_source_registry_find_extension:
2573 * @registry: an #ESourceRegistry
2574 * @source: an #ESource
2575 * @extension_name: the extension name to find
2577 * Examines @source and its ancestors and returns the "deepest" #ESource
2578 * having an #ESourceExtension with the given @extension_name. If neither
2579 * @source nor any of its ancestors have such an extension, the function
2580 * returns %NULL.
2582 * This function is useful in cases when an #ESourceExtension is meant to
2583 * apply to both the #ESource it belongs to and the #ESource's descendants.
2585 * A common example is the #ESourceCollection extension, where descendants
2586 * of an #ESource having an #ESourceCollection extension are implied to be
2587 * members of that collection. In that example, this function can be used
2588 * to test whether @source is a member of a collection.
2590 * The returned #ESource is referenced for thread-safety and must be
2591 * unreferenced with g_object_unref() when finished with it.
2593 * Note the function returns the #ESource containing the #ESourceExtension
2594 * instead of the #ESourceExtension itself because extension instances are
2595 * not to be referenced directly (see e_source_get_extension()).
2597 * Returns: (transfer full): an #ESource, or %NULL if no match was found
2599 * Since: 3.6
2601 ESource *
2602 e_source_registry_find_extension (ESourceRegistry *registry,
2603 ESource *source,
2604 const gchar *extension_name)
2606 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2607 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2608 g_return_val_if_fail (extension_name != NULL, NULL);
2610 g_object_ref (source);
2612 while (!e_source_has_extension (source, extension_name)) {
2613 gchar *uid;
2615 uid = e_source_dup_parent (source);
2617 g_object_unref (source);
2618 source = NULL;
2620 if (uid != NULL) {
2621 source = e_source_registry_ref_source (registry, uid);
2622 g_free (uid);
2625 if (source == NULL)
2626 break;
2629 return source;
2633 * e_source_registry_check_enabled:
2634 * @registry: an #ESourceRegistry
2635 * @source: an #ESource
2637 * Determines whether @source is "effectively" enabled by examining its
2638 * own #ESource:enabled property as well as those of its ancestors in the
2639 * #ESource hierarchy. If all examined #ESource:enabled properties are
2640 * %TRUE, then the function returns %TRUE. If any are %FALSE, then the
2641 * function returns %FALSE.
2643 * Use this function instead of e_source_get_enabled() to determine
2644 * things like whether to display an #ESource in a user interface or
2645 * whether to act on the data set described by the #ESource.
2647 * Returns: whether @source is "effectively" enabled
2649 * Since: 3.8
2651 gboolean
2652 e_source_registry_check_enabled (ESourceRegistry *registry,
2653 ESource *source)
2655 gboolean enabled;
2656 gchar *parent_uid;
2658 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
2659 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
2661 enabled = e_source_get_enabled (source);
2662 parent_uid = e_source_dup_parent (source);
2664 while (enabled && parent_uid != NULL) {
2665 ESource *parent;
2667 parent = e_source_registry_ref_source (registry, parent_uid);
2669 g_free (parent_uid);
2670 parent_uid = NULL;
2672 if (parent != NULL) {
2673 enabled = e_source_get_enabled (parent);
2674 parent_uid = e_source_dup_parent (parent);
2675 g_object_unref (parent);
2679 g_free (parent_uid);
2681 return enabled;
2684 /* Helper for e_source_registry_build_display_tree() */
2685 static gint
2686 source_registry_compare_nodes (GNode *node_a,
2687 GNode *node_b)
2689 ESource *source_a = E_SOURCE (node_a->data);
2690 ESource *source_b = E_SOURCE (node_b->data);
2691 const gchar *uid_a, *uid_b;
2693 uid_a = e_source_get_uid (source_a);
2694 uid_b = e_source_get_uid (source_b);
2696 /* Sanity check, with runtime warnings. */
2697 if (uid_a == NULL) {
2698 g_warn_if_reached ();
2699 uid_a = "";
2701 if (uid_b == NULL) {
2702 g_warn_if_reached ();
2703 uid_b = "";
2706 /* The built-in "local-stub" source comes first at depth 1. */
2708 if (g_strcmp0 (uid_a, "local-stub") == 0)
2709 return -1;
2711 if (g_strcmp0 (uid_b, "local-stub") == 0)
2712 return 1;
2714 /* The built-in "system-*" sources come first at depth 2. */
2716 if (g_str_has_prefix (uid_a, "system-"))
2717 return -1;
2719 if (g_str_has_prefix (uid_b, "system-"))
2720 return 1;
2722 return e_source_compare_by_display_name (source_a, source_b);
2725 /* Helper for e_source_registry_build_display_tree() */
2726 static gboolean
2727 source_registry_prune_nodes (GNode *node,
2728 const gchar *extension_name)
2730 GQueue queue = G_QUEUE_INIT;
2731 GNode *child_node;
2733 /* Unlink all the child nodes and place them in a queue. */
2734 while ((child_node = g_node_first_child (node)) != NULL) {
2735 g_node_unlink (child_node);
2736 g_queue_push_tail (&queue, child_node);
2739 /* Sort the queue by source name. */
2740 g_queue_sort (
2741 &queue, (GCompareDataFunc)
2742 source_registry_compare_nodes, NULL);
2744 /* Pop nodes off the head of the queue until the queue is empty.
2745 * If the node has either its own children or the given extension
2746 * name, put it back under the parent node (preserving the sorted
2747 * order). Otherwise delete the node and its descendants. */
2748 while ((child_node = g_queue_pop_head (&queue)) != NULL) {
2749 ESource *child = E_SOURCE (child_node->data);
2750 gboolean append_child_node = FALSE;
2752 if (extension_name == NULL)
2753 append_child_node = e_source_get_enabled (child);
2755 else if (e_source_has_extension (child, extension_name))
2756 append_child_node = e_source_get_enabled (child);
2758 else if (g_node_first_child (child_node) != NULL)
2759 append_child_node = e_source_get_enabled (child);
2761 if (append_child_node)
2762 g_node_append (node, child_node);
2763 else
2764 e_source_registry_free_display_tree (child_node);
2767 return FALSE;
2771 * e_source_registry_build_display_tree: (skip)
2772 * @registry: an #ESourceRegistry
2773 * @extension_name: (allow-none): an extension name, or %NULL
2775 * Returns a single #GNode tree of registered sources that can be used to
2776 * populate a #GtkTreeModel. (The root #GNode is just an empty placeholder.)
2778 * Similar to e_source_registry_list_sources(), an @extension_name can be
2779 * given to restrict the tree to sources having that extension name. Parents
2780 * of matched sources are included in the tree regardless of whether they have
2781 * an extension named @extension_name.
2783 * Disabled leaf nodes are automatically excluded from the #GNode tree.
2785 * The sources returned in the tree are referenced for thread-safety.
2786 * They must each be unreferenced with g_object_unref() when finished
2787 * with them. Free the returned tree itself with g_node_destroy().
2788 * For convenience, e_source_registry_free_display_tree() does all
2789 * that in one step.
2791 * Returns: (element-type ESource) (transfer full): a tree of sources,
2792 * arranged for display
2794 * Since: 3.6
2796 GNode *
2797 e_source_registry_build_display_tree (ESourceRegistry *registry,
2798 const gchar *extension_name)
2800 GNode *root;
2802 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2804 /* Assemble all data sources into a tree. */
2805 root = source_registry_sources_build_tree (registry);
2807 /* Prune unwanted nodes from the copied source trees.
2808 * This must be done in "post" order (children first)
2809 * since it reorders and deletes child nodes. */
2810 g_node_traverse (
2811 root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
2812 (GNodeTraverseFunc) source_registry_prune_nodes,
2813 (gpointer) extension_name);
2815 return root;
2818 /* Helper for e_source_registry_free_display_tree() */
2819 static void
2820 source_registry_unref_nodes (GNode *node)
2822 while (node != NULL) {
2823 if (node->children != NULL)
2824 source_registry_unref_nodes (node->children);
2825 if (node->data != NULL)
2826 g_object_unref (node->data);
2827 node = node->next;
2832 * e_source_registry_free_display_tree:
2833 * @display_tree: a tree of sources, arranged for display
2835 * Convenience function to free a #GNode tree of registered
2836 * sources created by e_source_registry_build_display_tree().
2838 * Since: 3.6
2840 void
2841 e_source_registry_free_display_tree (GNode *display_tree)
2843 g_return_if_fail (display_tree != NULL);
2845 /* XXX This would be easier if GLib had something like
2846 * g_node_destroy_full() which took a GDestroyNotify.
2847 * Then the tree would not have to be traversed twice. */
2849 source_registry_unref_nodes (display_tree);
2850 g_node_destroy (display_tree);
2854 * e_source_registry_dup_unique_display_name:
2855 * @registry: an #ESourceRegistry
2856 * @source: an #ESource
2857 * @extension_name: (allow-none): an extension name, or %NULL
2859 * Compares @source's #ESource:display-name against other sources having
2860 * an #ESourceExtension named @extension_name, if given, or else against
2861 * all other sources in the @registry.
2863 * If @sources's #ESource:display-name is unique among these other sources,
2864 * the function will return the #ESource:display-name verbatim. Otherwise
2865 * the function will construct a string that includes the @sources's own
2866 * #ESource:display-name as well as those of its ancestors.
2868 * The function's return value is intended to be used in messages shown to
2869 * the user to help clarify which source is being referred to. It assumes
2870 * @source's #ESource:display-name is at least unique among its siblings.
2872 * Free the returned string with g_free() when finished with it.
2874 * Returns: a unique display name for @source
2876 * Since: 3.8
2878 gchar *
2879 e_source_registry_dup_unique_display_name (ESourceRegistry *registry,
2880 ESource *source,
2881 const gchar *extension_name)
2883 GString *buffer;
2884 GList *list, *link;
2885 gchar *display_name;
2886 gboolean need_clarification = FALSE;
2888 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2889 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2891 list = e_source_registry_list_sources (registry, extension_name);
2893 /* Remove the input source from the list, if present. */
2894 link = g_list_find (list, source);
2895 if (link != NULL) {
2896 g_object_unref (link->data);
2897 list = g_list_delete_link (list, link);
2900 /* Now find another source with a matching display name. */
2901 link = g_list_find_custom (
2902 list, source, (GCompareFunc)
2903 e_source_compare_by_display_name);
2905 need_clarification = (link != NULL);
2907 g_list_free_full (list, (GDestroyNotify) g_object_unref);
2908 list = NULL;
2910 display_name = e_source_dup_display_name (source);
2911 buffer = g_string_new (display_name);
2912 g_free (display_name);
2914 if (need_clarification) {
2915 /* Build a list of ancestor sources. */
2917 g_object_ref (source);
2919 while (source != NULL) {
2920 gchar *parent_uid;
2922 parent_uid = e_source_dup_parent (source);
2924 g_object_unref (source);
2925 source = NULL;
2927 if (parent_uid != NULL) {
2928 source = e_source_registry_ref_source (
2929 registry, parent_uid);
2930 g_free (parent_uid);
2933 if (source != NULL) {
2934 g_object_ref (source);
2935 list = g_list_prepend (list, source);
2939 /* Display the ancestor names from the most distant
2940 * ancestor to the input source's immediate parent. */
2942 if (list != NULL)
2943 g_string_append (buffer, " (");
2945 for (link = list; link != NULL; link = g_list_next (link)) {
2946 if (link != list)
2947 g_string_append (buffer, " / ");
2949 source = E_SOURCE (link->data);
2950 display_name = e_source_dup_display_name (source);
2951 g_string_append (buffer, display_name);
2952 g_free (display_name);
2955 if (list != NULL)
2956 g_string_append (buffer, ")");
2958 g_list_free_full (list, (GDestroyNotify) g_object_unref);
2961 return g_string_free (buffer, FALSE);
2964 /* Helper for e_source_registry_debug_dump() */
2965 static gboolean
2966 source_registry_debug_dump_cb (GNode *node)
2968 guint ii, depth;
2970 /* Root node is an empty placeholder. */
2971 if (G_NODE_IS_ROOT (node))
2972 return FALSE;
2974 depth = g_node_depth (node);
2975 for (ii = 2; ii < depth; ii++)
2976 g_print (" ");
2978 if (E_IS_SOURCE (node->data)) {
2979 ESource *source = E_SOURCE (node->data);
2980 g_print ("\"%s\" ", e_source_get_display_name (source));
2981 g_print ("(%s)", e_source_get_uid (source));
2984 g_print ("\n");
2986 return FALSE;
2990 * e_source_registry_debug_dump:
2991 * @registry: an #ESourceRegistry
2992 * @extension_name: (allow-none): an extension name, or %NULL
2994 * Handy debugging function that uses e_source_registry_build_display_tree()
2995 * to print a tree of registered sources to standard output.
2997 * Since: 3.6
2999 void
3000 e_source_registry_debug_dump (ESourceRegistry *registry,
3001 const gchar *extension_name)
3003 GNode *root;
3005 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3007 root = e_source_registry_build_display_tree (registry, extension_name);
3009 g_node_traverse (
3010 root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
3011 (GNodeTraverseFunc) source_registry_debug_dump_cb, NULL);
3013 e_source_registry_free_display_tree (root);
3017 * e_source_registry_ref_builtin_address_book:
3018 * @registry: an #ESourceRegistry
3020 * Returns the built-in address book #ESource.
3022 * This #ESource is always present and makes for a safe fallback.
3024 * The returned #ESource is referenced for thread-safety and must be
3025 * unreferenced with g_object_unref() when finished with it.
3027 * Returns: (transfer full): the built-in address book #ESource
3029 * Since: 3.6
3031 ESource *
3032 e_source_registry_ref_builtin_address_book (ESourceRegistry *registry)
3034 ESource *source;
3035 const gchar *uid;
3037 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3039 uid = E_SOURCE_BUILTIN_ADDRESS_BOOK_UID;
3040 source = e_source_registry_ref_source (registry, uid);
3041 g_return_val_if_fail (source != NULL, NULL);
3043 return source;
3047 * e_source_registry_ref_builtin_calendar:
3048 * @registry: an #ESourceRegistry
3050 * Returns the built-in calendar #ESource.
3052 * This #ESource is always present and makes for a safe fallback.
3054 * The returned #ESource is referenced for thread-safety and must be
3055 * unreferenced with g_object_unref() when finished with it.
3057 * Returns: (transfer full): the built-in calendar #ESource
3059 * Since: 3.6
3061 ESource *
3062 e_source_registry_ref_builtin_calendar (ESourceRegistry *registry)
3064 ESource *source;
3065 const gchar *uid;
3067 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3069 uid = E_SOURCE_BUILTIN_CALENDAR_UID;
3070 source = e_source_registry_ref_source (registry, uid);
3071 g_return_val_if_fail (source != NULL, NULL);
3073 return source;
3077 * e_source_registry_ref_builtin_mail_account:
3078 * @registry: an #ESourceRegistry
3080 * Returns the built-in mail account #ESource.
3082 * This #ESource is always present and makes for a safe fallback.
3084 * The returned #ESource is referenced for thread-safety and must be
3085 * unreferenced with g_object_unref() when finished with it.
3087 * Returns: (transfer full): the built-in mail account #ESource
3089 * Since: 3.6
3091 ESource *
3092 e_source_registry_ref_builtin_mail_account (ESourceRegistry *registry)
3094 ESource *source;
3095 const gchar *uid;
3097 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3099 uid = E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID;
3100 source = e_source_registry_ref_source (registry, uid);
3101 g_return_val_if_fail (source != NULL, NULL);
3103 return source;
3107 * e_source_registry_ref_builtin_memo_list:
3108 * @registry: an #ESourceRegistry
3110 * Returns the built-in memo list #ESource.
3112 * This #ESource is always present and makes for a safe fallback.
3114 * The returned #ESource is referenced for thread-safety and must be
3115 * unreferenced with g_object_unref() when finished with it.
3117 * Returns: (transfer full): the built-in memo list #ESource
3119 * Since: 3.6
3121 ESource *
3122 e_source_registry_ref_builtin_memo_list (ESourceRegistry *registry)
3124 ESource *source;
3125 const gchar *uid;
3127 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3129 uid = E_SOURCE_BUILTIN_MEMO_LIST_UID;
3130 source = e_source_registry_ref_source (registry, uid);
3131 g_return_val_if_fail (source != NULL, NULL);
3133 return source;
3137 * e_source_registry_ref_builtin_proxy:
3138 * @registry: an #ESourceRegistry
3140 * Returns the built-in proxy profile #ESource.
3142 * This #ESource is always present and makes for a safe fallback.
3144 * The returned #ESource is referenced for thread-safety and must be
3145 * unreferenced with g_object_unref() when finished with it.
3147 * Returns: (transfer full): the built-in proxy profile #ESource
3149 * Since: 3.12
3151 ESource *
3152 e_source_registry_ref_builtin_proxy (ESourceRegistry *registry)
3154 ESource *source;
3155 const gchar *uid;
3157 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3159 uid = E_SOURCE_BUILTIN_PROXY_UID;
3160 source = e_source_registry_ref_source (registry, uid);
3161 g_return_val_if_fail (source != NULL, NULL);
3163 return source;
3167 * e_source_registry_ref_builtin_task_list:
3168 * @registry: an #ESourceRegistry
3170 * Returns the built-in task list #ESource.
3172 * This #ESource is always present and makes for a safe fallback.
3174 * The returned #ESource is referenced for thread-safety and must be
3175 * unreferenced with g_object_unref() when finished with it.
3177 * Returns: (transfer full): the built-in task list #ESource
3179 * Since: 3.6
3181 ESource *
3182 e_source_registry_ref_builtin_task_list (ESourceRegistry *registry)
3184 ESource *source;
3185 const gchar *uid;
3187 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3189 uid = E_SOURCE_BUILTIN_TASK_LIST_UID;
3190 source = e_source_registry_ref_source (registry, uid);
3191 g_return_val_if_fail (source != NULL, NULL);
3193 return source;
3197 * e_source_registry_ref_default_address_book:
3198 * @registry: an #ESourceRegistry
3200 * Returns the #ESource most recently passed to
3201 * e_source_registry_set_default_address_book() either in this session
3202 * or a previous session, or else falls back to the built-in address book.
3204 * The returned #ESource is referenced for thread-safety and must be
3205 * unreferenced with g_object_unref() when finished with it.
3207 * Returns: (transfer full): the default address book #ESource
3209 * Since: 3.6
3211 ESource *
3212 e_source_registry_ref_default_address_book (ESourceRegistry *registry)
3214 const gchar *key;
3215 ESource *source;
3216 gchar *uid;
3218 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3220 key = E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY;
3221 uid = g_settings_get_string (registry->priv->settings, key);
3222 source = e_source_registry_ref_source (registry, uid);
3223 g_free (uid);
3225 /* The built-in source is always present. */
3226 if (source == NULL)
3227 source = e_source_registry_ref_builtin_address_book (registry);
3229 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3231 return source;
3235 * e_source_registry_set_default_address_book:
3236 * @registry: an #ESourceRegistry
3237 * @default_source: (allow-none): an address book #ESource, or %NULL
3239 * Sets @default_source as the default address book. If @default_source
3240 * is %NULL, the default address book is reset to the built-in address book.
3241 * This setting will persist across sessions until changed.
3243 * Since: 3.6
3245 void
3246 e_source_registry_set_default_address_book (ESourceRegistry *registry,
3247 ESource *default_source)
3249 const gchar *key;
3250 const gchar *uid;
3252 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3254 if (default_source != NULL) {
3255 g_return_if_fail (E_IS_SOURCE (default_source));
3256 uid = e_source_get_uid (default_source);
3257 } else {
3258 uid = E_SOURCE_BUILTIN_ADDRESS_BOOK_UID;
3261 key = E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY;
3262 g_settings_set_string (registry->priv->settings, key, uid);
3264 /* The GSettings::changed signal will trigger a "notify" signal
3265 * from the registry, so no need to call g_object_notify() here. */
3269 * e_source_registry_ref_default_calendar:
3270 * @registry: an #ESourceRegistry
3272 * Returns the #ESource most recently passed to
3273 * e_source_registry_set_default_calendar() either in this session
3274 * or a previous session, or else falls back to the built-in calendar.
3276 * The returned #ESource is referenced for thread-safety and must be
3277 * unreferenced with g_object_unref() when finished with it.
3279 * Returns: (transfer full): the default calendar #ESource
3281 * Since: 3.6
3283 ESource *
3284 e_source_registry_ref_default_calendar (ESourceRegistry *registry)
3286 const gchar *key;
3287 ESource *source;
3288 gchar *uid;
3290 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3292 key = E_SETTINGS_DEFAULT_CALENDAR_KEY;
3293 uid = g_settings_get_string (registry->priv->settings, key);
3294 source = e_source_registry_ref_source (registry, uid);
3295 g_free (uid);
3297 /* The built-in source is always present. */
3298 if (source == NULL)
3299 source = e_source_registry_ref_builtin_calendar (registry);
3301 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3303 return source;
3307 * e_source_registry_set_default_calendar:
3308 * @registry: an #ESourceRegistry
3309 * @default_source: (allow-none): a calendar #ESource, or %NULL
3311 * Sets @default_source as the default calendar. If @default_source
3312 * is %NULL, the default calendar is reset to the built-in calendar.
3313 * This setting will persist across sessions until changed.
3315 * Since: 3.6
3317 void
3318 e_source_registry_set_default_calendar (ESourceRegistry *registry,
3319 ESource *default_source)
3321 const gchar *key;
3322 const gchar *uid;
3324 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3326 if (default_source != NULL) {
3327 g_return_if_fail (E_IS_SOURCE (default_source));
3328 uid = e_source_get_uid (default_source);
3329 } else {
3330 uid = E_SOURCE_BUILTIN_CALENDAR_UID;
3333 key = E_SETTINGS_DEFAULT_CALENDAR_KEY;
3334 g_settings_set_string (registry->priv->settings, key, uid);
3336 /* The GSettings::changed signal will trigger a "notify" signal
3337 * from the registry, so no need to call g_object_notify() here. */
3341 * e_source_registry_ref_default_mail_account:
3342 * @registry: an #ESourceRegistry
3344 * Returns the #ESource most recently passed to
3345 * e_source_registry_set_default_mail_account() either in this session
3346 * or a previous session, or else falls back to the built-in mail account.
3348 * The returned #ESource is referenced for thread-safety and must be
3349 * unreferenced with g_object_unref() when finished with it.
3351 * Returns: (transfer full): the default mail account #ESource
3353 * Since: 3.6
3355 ESource *
3356 e_source_registry_ref_default_mail_account (ESourceRegistry *registry)
3358 const gchar *key;
3359 ESource *source;
3360 gchar *uid;
3362 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3364 key = E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY;
3365 uid = g_settings_get_string (registry->priv->settings, key);
3366 source = e_source_registry_ref_source (registry, uid);
3367 g_free (uid);
3369 /* The built-in source is always present. */
3370 if (source == NULL)
3371 source = e_source_registry_ref_builtin_mail_account (registry);
3373 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3375 return source;
3379 * e_source_registry_set_default_mail_account:
3380 * @registry: an #ESourceRegistry
3381 * @default_source: (allow-none): a mail account #ESource, or %NULL
3383 * Sets @default_source as the default mail account. If @default_source
3384 * is %NULL, the default mail account is reset to the built-in mail account.
3385 * This setting will persist across sessions until changed.
3387 * Since: 3.6
3389 void
3390 e_source_registry_set_default_mail_account (ESourceRegistry *registry,
3391 ESource *default_source)
3393 const gchar *key;
3394 const gchar *uid;
3396 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3398 if (default_source != NULL) {
3399 g_return_if_fail (E_IS_SOURCE (default_source));
3400 uid = e_source_get_uid (default_source);
3401 } else {
3402 uid = E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID;
3405 key = E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY;
3406 g_settings_set_string (registry->priv->settings, key, uid);
3408 /* The GSettings::changed signal will trigger a "notify" signal
3409 * from the registry, so no need to call g_object_notify() here. */
3412 /* Helper for e_source_registry_ref_default_mail_identity() */
3413 static ESource *
3414 source_registry_ref_any_mail_identity (ESourceRegistry *registry)
3416 ESource *source;
3417 GList *list, *link;
3418 const gchar *extension_name;
3419 gchar *uid = NULL;
3421 /* First fallback: Return the mail identity named
3422 * by the default mail account. */
3424 source = e_source_registry_ref_default_mail_account (registry);
3426 /* This should never be NULL, but just to be safe. */
3427 if (source != NULL) {
3428 ESourceMailAccount *extension;
3430 extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
3431 extension = e_source_get_extension (source, extension_name);
3432 uid = e_source_mail_account_dup_identity_uid (extension);
3434 g_object_unref (source);
3435 source = NULL;
3438 if (uid != NULL) {
3439 source = e_source_registry_ref_source (registry, uid);
3440 g_free (uid);
3443 if (source != NULL)
3444 return source;
3446 /* Second fallback: Pick any available mail identity,
3447 * preferring enabled identities. */
3449 extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
3450 list = e_source_registry_list_sources (registry, extension_name);
3452 for (link = list; link != NULL; link = g_list_next (link)) {
3453 ESource *candidate = E_SOURCE (link->data);
3455 if (e_source_registry_check_enabled (registry, candidate)) {
3456 source = g_object_ref (candidate);
3457 break;
3461 if (source == NULL && list != NULL)
3462 source = g_object_ref (list->data);
3464 g_list_free_full (list, (GDestroyNotify) g_object_unref);
3466 return source;
3470 * e_source_registry_ref_default_mail_identity:
3471 * @registry: an #ESourceRegistry
3473 * Returns the #ESource most recently passed to
3474 * e_source_registry_set_default_mail_identity() either in this session
3475 * or a previous session, or else falls back to the mail identity named
3476 * by the default mail account. If even that fails it returns any mail
3477 * identity from @registry, or %NULL if there are none.
3479 * The returned #ESource is referenced for thread-safety and must be
3480 * unreferenced with g_object_unref() when finished with it.
3482 * Returns: (transfer full): the default mail identity #ESource, or %NULL
3484 * Since: 3.6
3486 ESource *
3487 e_source_registry_ref_default_mail_identity (ESourceRegistry *registry)
3489 const gchar *key;
3490 ESource *source;
3491 gchar *uid;
3493 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3495 key = E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY;
3496 uid = g_settings_get_string (registry->priv->settings, key);
3497 source = e_source_registry_ref_source (registry, uid);
3498 g_free (uid);
3500 if (source == NULL)
3501 source = source_registry_ref_any_mail_identity (registry);
3503 return source;
3507 * e_source_registry_set_default_mail_identity:
3508 * @registry: an #ESourceRegistry
3509 * @default_source: (allow-none): a mail identity #ESource, or %NULL
3511 * Sets @default_source as the default mail identity. If @default_source
3512 * is %NULL, the next request for the default mail identity will use the
3513 * fallbacks described in e_source_registry_ref_default_mail_identity().
3515 * Since: 3.6
3517 void
3518 e_source_registry_set_default_mail_identity (ESourceRegistry *registry,
3519 ESource *default_source)
3521 const gchar *key;
3522 const gchar *uid;
3524 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3526 if (default_source != NULL) {
3527 g_return_if_fail (E_IS_SOURCE (default_source));
3528 uid = e_source_get_uid (default_source);
3529 } else {
3530 uid = ""; /* no built-in mail identity */
3533 key = E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY;
3534 g_settings_set_string (registry->priv->settings, key, uid);
3536 /* The GSettings::changed signal will trigger a "notify" signal
3537 * from the registry, so no need to call g_object_notify() here. */
3541 * e_source_registry_ref_default_memo_list:
3542 * @registry: an #ESourceRegistry
3544 * Returns the #ESource most recently passed to
3545 * e_source_registry_set_default_memo_list() either in this session
3546 * or a previous session, or else falls back to the built-in memo list.
3548 * The returned #ESource is referenced for thread-safety and must be
3549 * unreferenced with g_object_unref() when finished with it.
3551 * Returns: (transfer full): the default memo list #ESource
3553 * Since: 3.6
3555 ESource *
3556 e_source_registry_ref_default_memo_list (ESourceRegistry *registry)
3558 const gchar *key;
3559 ESource *source;
3560 gchar *uid;
3562 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3564 key = E_SETTINGS_DEFAULT_MEMO_LIST_KEY;
3565 uid = g_settings_get_string (registry->priv->settings, key);
3566 source = e_source_registry_ref_source (registry, uid);
3567 g_free (uid);
3569 /* The built-in source is always present. */
3570 if (source == NULL)
3571 source = e_source_registry_ref_builtin_memo_list (registry);
3573 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3575 return source;
3579 * e_source_registry_set_default_memo_list:
3580 * @registry: an #ESourceRegistry
3581 * @default_source: (allow-none): a memo list #ESource, or %NULL
3583 * Sets @default_source as the default memo list. If @default_source
3584 * is %NULL, the default memo list is reset to the built-in memo list.
3585 * This setting will persist across sessions until changed.
3587 * Since: 3.6
3589 void
3590 e_source_registry_set_default_memo_list (ESourceRegistry *registry,
3591 ESource *default_source)
3593 const gchar *key;
3594 const gchar *uid;
3596 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3598 if (default_source != NULL) {
3599 g_return_if_fail (E_IS_SOURCE (default_source));
3600 uid = e_source_get_uid (default_source);
3601 } else {
3602 uid = E_SOURCE_BUILTIN_MEMO_LIST_UID;
3605 key = E_SETTINGS_DEFAULT_MEMO_LIST_KEY;
3606 g_settings_set_string (registry->priv->settings, key, uid);
3608 /* The GSettings::changed signal will trigger a "notify" signal
3609 * from the registry, so no need to call g_object_notify() here. */
3613 * e_source_registry_ref_default_task_list:
3614 * @registry: an #ESourceRegistry
3616 * Returns the #ESource most recently passed to
3617 * e_source_registry_set_default_task_list() either in this session
3618 * or a previous session, or else falls back to the built-in task list.
3620 * The returned #ESource is referenced for thread-safety and must be
3621 * unreferenced with g_object_unref() when finished with it.
3623 * Returns: (transfer full): the default task list #ESource
3625 * Since: 3.6
3627 ESource *
3628 e_source_registry_ref_default_task_list (ESourceRegistry *registry)
3630 const gchar *key;
3631 ESource *source;
3632 gchar *uid;
3634 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3636 key = E_SETTINGS_DEFAULT_TASK_LIST_KEY;
3637 uid = g_settings_get_string (registry->priv->settings, key);
3638 source = e_source_registry_ref_source (registry, uid);
3639 g_free (uid);
3641 /* The built-in source is always present. */
3642 if (source == NULL)
3643 source = e_source_registry_ref_builtin_task_list (registry);
3645 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
3647 return source;
3651 * e_source_registry_set_default_task_list:
3652 * @registry: an #ESourceRegistry
3653 * @default_source: (allow-none): a task list #ESource, or %NULL
3655 * Sets @default_source as the default task list. If @default_source
3656 * is %NULL, the default task list is reset to the built-in task list.
3657 * This setting will persist across sessions until changed.
3659 * Since: 3.6
3661 void
3662 e_source_registry_set_default_task_list (ESourceRegistry *registry,
3663 ESource *default_source)
3665 const gchar *key;
3666 const gchar *uid;
3668 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3670 if (default_source != NULL) {
3671 g_return_if_fail (E_IS_SOURCE (default_source));
3672 uid = e_source_get_uid (default_source);
3673 } else {
3674 uid = E_SOURCE_BUILTIN_TASK_LIST_UID;
3677 key = E_SETTINGS_DEFAULT_TASK_LIST_KEY;
3678 g_settings_set_string (registry->priv->settings, key, uid);
3680 /* The GSettings::changed signal will trigger a "notify" signal
3681 * from the registry, so no need to call g_object_notify() here. */
3685 * e_source_registry_ref_default_for_extension_name:
3686 * @registry: an #ESourceRegistry
3687 * @extension_name: an extension_name
3689 * This is a convenience function to return a default #ESource based on
3690 * @extension_name. This only works with a subset of extension names.
3692 * If @extension_name is #E_SOURCE_EXTENSION_ADDRESS_BOOK, the function
3693 * returns the current default address book, or else falls back to the
3694 * built-in address book.
3696 * If @extension_name is #E_SOURCE_EXTENSION_CALENDAR, the function returns
3697 * the current default calendar, or else falls back to the built-in calendar.
3699 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_ACCOUNT, the function
3700 * returns the current default mail account, or else falls back to the
3701 * built-in mail account.
3703 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_IDENTITY, the function
3704 * returns the current default mail identity, or else falls back to the
3705 * mail identity named by the current default mail account.
3707 * If @extension_name is #E_SOURCE_EXTENSION_MEMO_LIST, the function returns
3708 * the current default memo list, or else falls back to the built-in memo list.
3710 * If @extension_name is #E_SOURCE_EXTENSION_TASK_LIST, the function returns
3711 * the current default task list, or else falls back to the built-in task list.
3713 * For all other values of @extension_name, the function returns %NULL.
3715 * The returned #ESource is referenced for thread-safety and must be
3716 * unreferenced with g_object_unref() when finished with it.
3718 * Returns: (transfer full): the default #ESource based on @extension_name
3720 * Since: 3.6
3722 ESource *
3723 e_source_registry_ref_default_for_extension_name (ESourceRegistry *registry,
3724 const gchar *extension_name)
3726 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
3727 g_return_val_if_fail (extension_name != NULL, NULL);
3729 if (strcmp (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK) == 0)
3730 return e_source_registry_ref_default_address_book (registry);
3732 if (strcmp (extension_name, E_SOURCE_EXTENSION_CALENDAR) == 0)
3733 return e_source_registry_ref_default_calendar (registry);
3735 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_ACCOUNT) == 0)
3736 return e_source_registry_ref_default_mail_account (registry);
3738 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_IDENTITY) == 0)
3739 return e_source_registry_ref_default_mail_identity (registry);
3741 if (strcmp (extension_name, E_SOURCE_EXTENSION_MEMO_LIST) == 0)
3742 return e_source_registry_ref_default_memo_list (registry);
3744 if (strcmp (extension_name, E_SOURCE_EXTENSION_TASK_LIST) == 0)
3745 return e_source_registry_ref_default_task_list (registry);
3747 return NULL;
3751 * e_source_registry_set_default_for_extension_name:
3752 * @registry: an #ESourceRegistry
3753 * @extension_name: an extension name
3754 * @default_source: (allow-none): an #ESource, or %NULL
3756 * This is a convenience function to set a default #ESource based on
3757 * @extension_name. This only works with a subset of extension names.
3759 * If @extension_name is #E_SOURCE_EXTENSION_ADDRESS_BOOK, the function
3760 * sets @default_source as the default address book. If @default_source
3761 * is %NULL, the default address book is reset to the built-in address book.
3763 * If @extension_name is #E_SOURCE_EXTENSION_CALENDAR, the function sets
3764 * @default_source as the default calendar. If @default_source is %NULL,
3765 * the default calendar is reset to the built-in calendar.
3767 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_ACCOUNT, the function
3768 * sets @default_source as the default mail account. If @default_source
3769 * is %NULL, the default mail account is reset to the built-in mail account.
3771 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_IDENTITY, the function
3772 * sets @default_source as the default mail identity. If @default_source
3773 * is %NULL, the next request for the default mail identity will return
3774 * the mail identity named by the default mail account.
3776 * If @extension_name is #E_SOURCE_EXTENSION_MEMO_LIST, the function sets
3777 * @default_source as the default memo list. If @default_source is %NULL,
3778 * the default memo list is reset to the built-in memo list.
3780 * If @extension_name is #E_SOURCE_EXTENSION_TASK_LIST, the function sets
3781 * @default_source as the default task list. If @default_source is %NULL,
3782 * the default task list is reset to the built-in task list.
3784 * For all other values of @extension_name, the function does nothing.
3786 * Since: 3.6
3788 void
3789 e_source_registry_set_default_for_extension_name (ESourceRegistry *registry,
3790 const gchar *extension_name,
3791 ESource *default_source)
3793 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
3794 g_return_if_fail (extension_name != NULL);
3796 if (strcmp (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK) == 0)
3797 e_source_registry_set_default_address_book (
3798 registry, default_source);
3800 if (strcmp (extension_name, E_SOURCE_EXTENSION_CALENDAR) == 0)
3801 e_source_registry_set_default_calendar (
3802 registry, default_source);
3804 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_ACCOUNT) == 0)
3805 e_source_registry_set_default_mail_account (
3806 registry, default_source);
3808 if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_IDENTITY) == 0)
3809 e_source_registry_set_default_mail_identity (
3810 registry, default_source);
3812 if (strcmp (extension_name, E_SOURCE_EXTENSION_MEMO_LIST) == 0)
3813 e_source_registry_set_default_memo_list (
3814 registry, default_source);
3816 if (strcmp (extension_name, E_SOURCE_EXTENSION_TASK_LIST) == 0)
3817 e_source_registry_set_default_task_list (
3818 registry, default_source);