[evolution-data-server] ESourceRegistry's thread main_context can leak



commit 98f13365247bc4e2c9bd4e94fc78a26d4303a460
Author: Milan Crha <mcrha redhat com>
Date:   Wed Jul 18 15:54:14 2018 +0200

    ESourceRegistry's thread main_context can leak
    
    The problem was that EWebDAVDiscover (used to find out CalDAV calendars/memo
    lists/task lists and CardDAV books) wanted to receive a proxy ESource, for
    which it requires either ESourceRegistry or ESourceRegistryServer. As
    the EWebDAVDiscover API didn't have any such argument it always created its
    own ESourceRegistry instance, which had been dropped shortly afterwards. This
    drop also meant that the internal GDBus object scheduled its own events on
    the ESourceRegistry's thread main_context (to unsubscribe D-Bus signals), but
    this main_context didn't have enough time to flush the queue, which resulted
    in a leak of the main_context, because the events in it referenced it (similar
    to circular reference). The fix was to flush the queue before closing
    the thread and to reorganize the ESourceRegistry's dispose() function, thus
    the flush is done on filled main_context.
    
    While I've been in it, some structures unnecessarily long held a GCancellable
    object, which also means a file descriptor, thus I fixed that as well.
    
    As the last, but not least, I added a new API for the EWebDAVDiscover to
    be able to provide also a function to reference an ESource, thus there is
    no need to create the ESourceRegistry instance, thus it is quicker and more
    effective now.
    
    Reported downstream at:
    https://bugzilla.redhat.com/show_bug.cgi?id=1600489

 src/libebackend/e-backend.c                     |  43 +++++++--
 src/libebackend/e-webdav-collection-backend.c   |  34 +++----
 src/libedataserver/e-source-registry.c          |  31 ++++--
 src/libedataserver/e-webdav-discover.c          | 123 +++++++++++++++++++++---
 src/libedataserver/e-webdav-discover.h          |  37 +++++++
 src/libedataserverui/e-webdav-discover-widget.c |  21 ++--
 6 files changed, 238 insertions(+), 51 deletions(-)
---
diff --git a/src/libebackend/e-backend.c b/src/libebackend/e-backend.c
index ed40cc099..bd7203592 100644
--- a/src/libebackend/e-backend.c
+++ b/src/libebackend/e-backend.c
@@ -84,15 +84,22 @@ enum {
 
 G_DEFINE_ABSTRACT_TYPE (EBackend, e_backend, G_TYPE_OBJECT)
 
+typedef struct _CanReachData {
+       EBackend *backend;
+       GCancellable *cancellable;
+} CanReachData;
+
 static void
 backend_network_monitor_can_reach_cb (GObject *source_object,
                                       GAsyncResult *result,
                                       gpointer user_data)
 {
-       EBackend *backend = E_BACKEND (user_data);
+       CanReachData *crd = user_data;
        gboolean host_is_reachable;
        GError *error = NULL;
 
+       g_return_if_fail (crd != NULL);
+
        host_is_reachable = g_network_monitor_can_reach_finish (
                G_NETWORK_MONITOR (source_object), result, &error);
 
@@ -101,25 +108,32 @@ backend_network_monitor_can_reach_cb (GObject *source_object,
                (host_is_reachable && (error == NULL)) ||
                (!host_is_reachable && (error != NULL)));
 
+       g_mutex_lock (&crd->backend->priv->network_monitor_cancellable_lock);
+       if (crd->backend->priv->network_monitor_cancellable == crd->cancellable)
+               g_clear_object (&crd->backend->priv->network_monitor_cancellable);
+       g_mutex_unlock (&crd->backend->priv->network_monitor_cancellable_lock);
+
        if (G_IS_IO_ERROR (error, G_IO_ERROR_CANCELLED) ||
-           host_is_reachable == e_backend_get_online (backend)) {
+           host_is_reachable == e_backend_get_online (crd->backend)) {
                g_clear_error (&error);
-               g_object_unref (backend);
+               g_object_unref (crd->backend);
+               g_free (crd);
                return;
        }
 
        g_clear_error (&error);
 
-       e_backend_set_online (backend, host_is_reachable);
+       e_backend_set_online (crd->backend, host_is_reachable);
 
        if (!host_is_reachable) {
                ESource *source;
 
-               source = e_backend_get_source (backend);
+               source = e_backend_get_source (crd->backend);
                e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_DISCONNECTED);
        }
 
-       g_object_unref (backend);
+       g_object_unref (crd->backend);
+       g_free (crd);
 }
 
 static GSocketConnectable *
@@ -184,13 +198,19 @@ backend_update_online_state_timeout_cb (gpointer user_data)
 
                e_backend_set_online (backend, TRUE);
        } else {
+               CanReachData *crd;
+
                cancellable = g_cancellable_new ();
 
+               crd = g_new0 (CanReachData, 1);
+               crd->backend = g_object_ref (backend);
+               crd->cancellable = cancellable;
+
                g_network_monitor_can_reach_async (
                        backend->priv->network_monitor,
                        connectable, cancellable,
                        backend_network_monitor_can_reach_cb,
-                       g_object_ref (backend));
+                       crd);
 
                backend->priv->network_monitor_cancellable = cancellable;
                g_mutex_unlock (&backend->priv->network_monitor_cancellable_lock);
@@ -301,6 +321,15 @@ static void
 authenticate_thread_data_free (AuthenticateThreadData *data)
 {
        if (data) {
+               if (data->backend) {
+                       g_mutex_lock (&data->backend->priv->authenticate_cancellable_lock);
+                       if (data->backend->priv->authenticate_cancellable &&
+                           data->backend->priv->authenticate_cancellable == data->cancellable) {
+                               g_clear_object (&data->backend->priv->authenticate_cancellable);
+                       }
+                       g_mutex_unlock (&data->backend->priv->authenticate_cancellable_lock);
+               }
+
                g_clear_object (&data->backend);
                g_clear_object (&data->cancellable);
                e_named_parameters_free (data->credentials);
diff --git a/src/libebackend/e-webdav-collection-backend.c b/src/libebackend/e-webdav-collection-backend.c
index 03c50c21b..ce9feacfb 100644
--- a/src/libebackend/e-webdav-collection-backend.c
+++ b/src/libebackend/e-webdav-collection-backend.c
@@ -461,6 +461,7 @@ e_webdav_collection_backend_discover_sync (EWebDAVCollectionBackend *webdav_back
                                           GError **error)
 {
        ECollectionBackend *collection;
+       ESourceRegistryServer *server;
        ESourceCollection *collection_extension;
        ESource *source;
        ESourceAuthenticationResult result;
@@ -497,11 +498,13 @@ e_webdav_collection_backend_discover_sync (EWebDAVCollectionBackend *webdav_back
        g_list_foreach (sources, webdav_collection_add_uid_to_hashtable, known_sources);
        g_list_free_full (sources, g_object_unref);
 
+       server = e_collection_backend_ref_server (collection);
+
        if (e_source_collection_get_calendar_enabled (collection_extension) && calendar_url &&
-           e_webdav_discover_sources_sync (source, calendar_url,
+           e_webdav_discover_sources_full_sync (source, calendar_url,
                E_WEBDAV_DISCOVER_SUPPORTS_EVENTS | E_WEBDAV_DISCOVER_SUPPORTS_MEMOS | 
E_WEBDAV_DISCOVER_SUPPORTS_TASKS,
-               credentials, out_certificate_pem, out_certificate_errors,
-               &discovered_sources, NULL, cancellable, &local_error)) {
+               credentials, (EWebDAVDiscoverRefSourceFunc) e_source_registry_server_ref_source, server,
+               out_certificate_pem, out_certificate_errors, &discovered_sources, NULL, cancellable, 
&local_error)) {
                EWebDAVDiscoverSupports source_types[] = {
                        E_WEBDAV_DISCOVER_SUPPORTS_EVENTS,
                        E_WEBDAV_DISCOVER_SUPPORTS_MEMOS,
@@ -516,9 +519,9 @@ e_webdav_collection_backend_discover_sync (EWebDAVCollectionBackend *webdav_back
        }
 
        if (!local_error && e_source_collection_get_contacts_enabled (collection_extension) && contacts_url &&
-           e_webdav_discover_sources_sync (source, contacts_url, E_WEBDAV_DISCOVER_SUPPORTS_CONTACTS,
-               credentials, out_certificate_pem, out_certificate_errors,
-               &discovered_sources, NULL, cancellable, &local_error)) {
+           e_webdav_discover_sources_full_sync (source, contacts_url, E_WEBDAV_DISCOVER_SUPPORTS_CONTACTS,
+               credentials, (EWebDAVDiscoverRefSourceFunc) e_source_registry_server_ref_source, server,
+               out_certificate_pem, out_certificate_errors, &discovered_sources, NULL, cancellable, 
&local_error)) {
                EWebDAVDiscoverSupports source_types[] = {
                        E_WEBDAV_DISCOVER_SUPPORTS_CONTACTS
                };
@@ -530,24 +533,19 @@ e_webdav_collection_backend_discover_sync (EWebDAVCollectionBackend *webdav_back
                any_success = TRUE;
        }
 
-       if (any_success) {
-               ESourceRegistryServer *server;
-
-               server = e_collection_backend_ref_server (collection);
+       if (any_success && server) {
+               RemoveSourcesData rsd;
 
-               if (server) {
-                       RemoveSourcesData rsd;
+               rsd.server = server;
+               rsd.webdav_backend = webdav_backend;
 
-                       rsd.server = server;
-                       rsd.webdav_backend = webdav_backend;
-
-                       g_hash_table_foreach (known_sources, webdav_collection_remove_unknown_sources_cb, 
&rsd);
-                       g_object_unref (server);
-               }
+               g_hash_table_foreach (known_sources, webdav_collection_remove_unknown_sources_cb, &rsd);
 
                g_clear_error (&local_error);
        }
 
+       g_clear_object (&server);
+
        if (local_error == NULL) {
                result = E_SOURCE_AUTHENTICATION_ACCEPTED;
                e_collection_backend_authenticate_children (collection, credentials);
diff --git a/src/libedataserver/e-source-registry.c b/src/libedataserver/e-source-registry.c
index b7c975abc..9c166dbaf 100644
--- a/src/libedataserver/e-source-registry.c
+++ b/src/libedataserver/e-source-registry.c
@@ -261,6 +261,8 @@ thread_closure_free (ThreadClosure *closure)
 {
        /* The registry member is not referenced. */
 
+       g_warn_if_fail (!g_main_context_pending (closure->main_context));
+
        g_main_context_unref (closure->main_context);
        g_main_loop_unref (closure->main_loop);
        g_cond_clear (&closure->main_loop_cond);
@@ -1180,6 +1182,13 @@ notify:
                g_object_unref (object_manager);
        }
 
+       /* Make sure the queue is flushed, because items in it can reference
+          the main_context, effectively causing it to leak, together with
+          its GWakeup ([eventfd]) file descriptor. */
+       while (g_main_context_pending (closure->main_context)) {
+               g_main_context_iteration (closure->main_context, FALSE);
+       }
+
        g_main_context_pop_thread_default (closure->main_context);
 
        return NULL;
@@ -1292,15 +1301,6 @@ source_registry_dispose (GObject *object)
 
        priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
 
-       /* Terminate the manager thread first. */
-       if (priv->manager_thread != NULL) {
-               g_main_loop_quit (priv->thread_closure->main_loop);
-               g_thread_join (priv->manager_thread);
-               thread_closure_free (priv->thread_closure);
-               priv->manager_thread = NULL;
-               priv->thread_closure = NULL;
-       }
-
        if (priv->dbus_object_manager != NULL) {
                g_object_unref (priv->dbus_object_manager);
                priv->dbus_object_manager = NULL;
@@ -1311,6 +1311,19 @@ source_registry_dispose (GObject *object)
                priv->dbus_source_manager = NULL;
        }
 
+       /* Terminate the manager thread after GDBus objects,
+          because they can schedule GSource-s in the main context there. */
+       if (priv->manager_thread != NULL) {
+               g_main_loop_quit (priv->thread_closure->main_loop);
+               g_thread_join (priv->manager_thread);
+               priv->manager_thread = NULL;
+       }
+
+       if (priv->thread_closure) {
+               thread_closure_free (priv->thread_closure);
+               priv->thread_closure = NULL;
+       }
+
        g_hash_table_remove_all (priv->object_path_table);
 
        g_hash_table_remove_all (priv->sources);
diff --git a/src/libedataserver/e-webdav-discover.c b/src/libedataserver/e-webdav-discover.c
index e7c55b7f3..3e7b48522 100644
--- a/src/libedataserver/e-webdav-discover.c
+++ b/src/libedataserver/e-webdav-discover.c
@@ -307,6 +307,8 @@ typedef struct _EWebDAVDiscoverContext {
        gchar *url_use_path;
        guint32 only_supports;
        ENamedParameters *credentials;
+       EWebDAVDiscoverRefSourceFunc ref_source_func;
+       gpointer ref_source_func_user_data;
        gchar *out_certificate_pem;
        GTlsCertificateFlags out_certificate_errors;
        GSList *out_discovered_sources;
@@ -317,7 +319,9 @@ static EWebDAVDiscoverContext *
 e_webdav_discover_context_new (ESource *source,
                               const gchar *url_use_path,
                               guint32 only_supports,
-                              const ENamedParameters *credentials)
+                              const ENamedParameters *credentials,
+                              EWebDAVDiscoverRefSourceFunc ref_source_func,
+                              gpointer ref_source_func_user_data)
 {
        EWebDAVDiscoverContext *context;
 
@@ -326,6 +330,8 @@ e_webdav_discover_context_new (ESource *source,
        context->url_use_path = g_strdup (url_use_path);
        context->only_supports = only_supports;
        context->credentials = e_named_parameters_new_clone (credentials);
+       context->ref_source_func = ref_source_func;
+       context->ref_source_func_user_data = ref_source_func_user_data;
        context->out_certificate_pem = NULL;
        context->out_certificate_errors = 0;
        context->out_discovered_sources = NULL;
@@ -393,8 +399,9 @@ e_webdav_discover_sources_thread (GTask *task,
        g_return_if_fail (context != NULL);
        g_return_if_fail (E_IS_SOURCE (source_object));
 
-       success = e_webdav_discover_sources_sync (E_SOURCE (source_object),
+       success = e_webdav_discover_sources_full_sync (E_SOURCE (source_object),
                context->url_use_path, context->only_supports, context->credentials,
+               context->ref_source_func, context->ref_source_func_user_data,
                &context->out_certificate_pem, &context->out_certificate_errors,
                &context->out_discovered_sources, &context->out_calendar_user_addresses,
                cancellable, &local_error);
@@ -409,6 +416,8 @@ e_webdav_discover_sources_thread (GTask *task,
 static gboolean
 e_webdav_discover_setup_proxy_resolver (EWebDAVSession *webdav,
                                        ESource *cred_source,
+                                       EWebDAVDiscoverRefSourceFunc ref_source_func,
+                                       gpointer ref_source_func_user_data,
                                        GCancellable *cancellable,
                                        GError **error)
 {
@@ -428,14 +437,18 @@ e_webdav_discover_setup_proxy_resolver (EWebDAVSession *webdav,
        uid = e_source_authentication_dup_proxy_uid (auth_extension);
 
        if (uid != NULL) {
-               ESourceRegistry * registry;
-
-               registry = e_source_registry_new_sync (cancellable, error);
-               if (!registry) {
-                       success = FALSE;
+               if (ref_source_func) {
+                       source = ref_source_func (ref_source_func_user_data, uid);
                } else {
-                       source = e_source_registry_ref_source (registry, uid);
-                       g_object_unref (registry);
+                       ESourceRegistry *registry;
+
+                       registry = e_source_registry_new_sync (cancellable, error);
+                       if (!registry) {
+                               success = FALSE;
+                       } else {
+                               source = e_source_registry_ref_source (registry, uid);
+                               g_object_unref (registry);
+                       }
                }
 
                g_free (uid);
@@ -485,13 +498,52 @@ e_webdav_discover_sources (ESource *source,
                           GCancellable *cancellable,
                           GAsyncReadyCallback callback,
                           gpointer user_data)
+{
+       g_return_if_fail (E_IS_SOURCE (source));
+
+       e_webdav_discover_sources_full (source, url_use_path, only_supports, credentials, NULL, NULL, 
cancellable, callback, user_data);
+}
+
+/**
+ * e_webdav_discover_sources_full:
+ * @source: an #ESource from which to take connection details
+ * @url_use_path: (nullable): optional URL override, or %NULL
+ * @only_supports: bit-or of EWebDAVDiscoverSupports, to limit what type of sources to search
+ * @credentials: (nullable): credentials to use for authentication to the server
+ * @ref_source_func: (nullable): optional callback to use to get an ESource
+ * @ref_source_func_user_data: (nullable): user data for @ref_source_func
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: (scope async): a #GAsyncReadyCallback to call when the request
+ *            is satisfied
+ * @user_data: (closure): data to pass to the callback function
+ *
+ * This is the same as e_webdav_discover_sources(), it only allows to
+ * provide a callback function (with its user_data), to reference an additional
+ * #ESource. It's good to avoid creating its own #ESourceRegistry instance to
+ * get it.
+ *
+ * When the operation is finished, @callback will be called. You can then
+ * call e_webdav_discover_sources_finish() to get the result of the operation.
+ *
+ * Since: 3.30
+ **/
+void
+e_webdav_discover_sources_full (ESource *source,
+                               const gchar *url_use_path,
+                               guint32 only_supports,
+                               const ENamedParameters *credentials,
+                               EWebDAVDiscoverRefSourceFunc ref_source_func,
+                               gpointer ref_source_func_user_data,
+                               GCancellable *cancellable,
+                               GAsyncReadyCallback callback,
+                               gpointer user_data)
 {
        EWebDAVDiscoverContext *context;
        GTask *task;
 
        g_return_if_fail (E_IS_SOURCE (source));
 
-       context = e_webdav_discover_context_new (source, url_use_path, only_supports, credentials);
+       context = e_webdav_discover_context_new (source, url_use_path, only_supports, credentials, 
ref_source_func, ref_source_func_user_data);
 
        task = g_task_new (source, cancellable, callback, user_data);
        g_task_set_source_tag (task, e_webdav_discover_sources);
@@ -649,6 +701,55 @@ e_webdav_discover_sources_sync (ESource *source,
                                GSList **out_calendar_user_addresses,
                                GCancellable *cancellable,
                                GError **error)
+{
+       g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+
+       return e_webdav_discover_sources_full_sync (source, url_use_path, only_supports, credentials, NULL, 
NULL,
+               out_certificate_pem, out_certificate_errors, out_discovered_sources, 
out_calendar_user_addresses, cancellable, error);
+}
+
+/**
+ * e_webdav_discover_sources_full_sync:
+ * @source: an #ESource from which to take connection details
+ * @url_use_path: (nullable): optional URL override, or %NULL
+ * @only_supports: bit-or of EWebDAVDiscoverSupports, to limit what type of sources to search
+ * @credentials: (nullable): credentials to use for authentication to the server
+ * @ref_source_func: (nullable): optional callback to use to get an ESource
+ * @ref_source_func_user_data: (nullable): user data for @ref_source_func
+ * @out_certificate_pem: (out) (nullable): optional return location
+ *   for a server SSL certificate in PEM format, when the operation failed
+ *   with an SSL error
+ * @out_certificate_errors: (out) (nullable): optional #GTlsCertificateFlags,
+ *   with certificate error flags when the operation failed with SSL error
+ * @out_discovered_sources: (out) (element-type EWebDAVDiscoveredSource): a #GSList
+ *   of all discovered sources
+ * @out_calendar_user_addresses: (out) (nullable) (element-type utf8): a #GSList of
+ *   all discovered mail addresses for calendar sources
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * This is the same as e_webdav_discover_sources_sync(), it only allows to
+ * provide a callback function (with its user_data), to reference an additional
+ * #ESource. It's good to avoid creating its own #ESourceRegistry instance to
+ * get it.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.30
+ **/
+gboolean
+e_webdav_discover_sources_full_sync (ESource *source,
+                                    const gchar *url_use_path,
+                                    guint32 only_supports,
+                                    const ENamedParameters *credentials,
+                                    EWebDAVDiscoverRefSourceFunc ref_source_func,
+                                    gpointer ref_source_func_user_data,
+                                    gchar **out_certificate_pem,
+                                    GTlsCertificateFlags *out_certificate_errors,
+                                    GSList **out_discovered_sources,
+                                    GSList **out_calendar_user_addresses,
+                                    GCancellable *cancellable,
+                                    GError **error)
 {
        ESourceWebdav *webdav_extension;
        EWebDAVSession *webdav;
@@ -696,7 +797,7 @@ e_webdav_discover_sources_sync (ESource *source,
 
        webdav = e_webdav_session_new (source);
 
-       if (!e_webdav_discover_setup_proxy_resolver (webdav, source, cancellable, error)) {
+       if (!e_webdav_discover_setup_proxy_resolver (webdav, source, ref_source_func, 
ref_source_func_user_data, cancellable, error)) {
                soup_uri_free (soup_uri);
                g_object_unref (webdav);
 
diff --git a/src/libedataserver/e-webdav-discover.h b/src/libedataserver/e-webdav-discover.h
index 52bf4a0df..860499c75 100644
--- a/src/libedataserver/e-webdav-discover.h
+++ b/src/libedataserver/e-webdav-discover.h
@@ -74,6 +74,43 @@ gboolean     e_webdav_discover_sources_sync          (ESource *source,
                                                         GCancellable *cancellable,
                                                         GError **error);
 
+/**
+ * EWebDAVDiscoverRefSourceFunc:
+ * @user_data: user data, as passed to e_webdav_discover_sources_full() or
+ *     e_webdav_discover_sources_full_sync()
+ * @uid: an #ESource UID to return
+ *
+ * Returns: (transfer full) (nullable): an #ESource with UID @uid, or %NULL, if not found.
+ *    Dereference the returned non-NULL #ESource with g_object_unref(), when no longer needed.
+ *
+ * Since: 3.30
+ **/
+typedef ESource * (* EWebDAVDiscoverRefSourceFunc)     (gpointer user_data,
+                                                        const gchar *uid);
+
+void           e_webdav_discover_sources_full          (ESource *source,
+                                                        const gchar *url_use_path,
+                                                        guint32 only_supports,
+                                                        const ENamedParameters *credentials,
+                                                        EWebDAVDiscoverRefSourceFunc ref_source_func,
+                                                        gpointer ref_source_func_user_data,
+                                                        GCancellable *cancellable,
+                                                        GAsyncReadyCallback callback,
+                                                        gpointer user_data);
+
+gboolean       e_webdav_discover_sources_full_sync     (ESource *source,
+                                                        const gchar *url_use_path,
+                                                        guint32 only_supports,
+                                                        const ENamedParameters *credentials,
+                                                        EWebDAVDiscoverRefSourceFunc ref_source_func,
+                                                        gpointer ref_source_func_user_data,
+                                                        gchar **out_certificate_pem,
+                                                        GTlsCertificateFlags *out_certificate_errors,
+                                                        GSList **out_discovered_sources,
+                                                        GSList **out_calendar_user_addresses,
+                                                        GCancellable *cancellable,
+                                                        GError **error);
+
 G_END_DECLS
 
 #endif /* E_WEBDAV_DISCOVER_H */
diff --git a/src/libedataserverui/e-webdav-discover-widget.c b/src/libedataserverui/e-webdav-discover-widget.c
index 0933b88d7..73c2a6f49 100644
--- a/src/libedataserverui/e-webdav-discover-widget.c
+++ b/src/libedataserverui/e-webdav-discover-widget.c
@@ -580,6 +580,7 @@ typedef struct _RefreshData {
        GSimpleAsyncResult *simple;
        gchar *base_url;
        ENamedParameters *credentials;
+       ESourceRegistry *registry;
 } RefreshData;
 
 static void
@@ -608,6 +609,7 @@ refresh_data_free (gpointer ptr)
                g_clear_object (&rd->content);
                g_clear_object (&rd->cancellable);
                g_clear_object (&rd->simple);
+               g_clear_object (&rd->registry);
                g_free (rd->base_url);
                e_named_parameters_free (rd->credentials);
                g_free (rd);
@@ -640,8 +642,9 @@ e_webdav_discover_content_trust_prompt_done_cb (GObject *source_object,
                refresh_data_free (rd);
        } else if (response == E_TRUST_PROMPT_RESPONSE_ACCEPT || response == 
E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY) {
                /* Use NULL credentials to reuse those from the last time. */
-               e_webdav_discover_sources (source, rd->base_url, E_WEBDAV_DISCOVER_SUPPORTS_NONE, 
rd->credentials, rd->cancellable,
-                       e_webdav_discover_content_refresh_done_cb, rd);
+               e_webdav_discover_sources_full (source, rd->base_url, E_WEBDAV_DISCOVER_SUPPORTS_NONE, 
rd->credentials,
+                       rd->registry ? (EWebDAVDiscoverRefSourceFunc) e_source_registry_ref_source : NULL, 
rd->registry,
+                       rd->cancellable, e_webdav_discover_content_refresh_done_cb, rd);
        } else {
                g_cancellable_cancel (rd->cancellable);
                g_warn_if_fail (g_cancellable_set_error_if_cancelled (rd->cancellable, &local_error));
@@ -686,8 +689,9 @@ e_webdav_discover_content_credentials_prompt_done_cb (GObject *source_object,
                        e_source_authentication_set_user (auth_extension, e_named_parameters_get 
(rd->credentials, E_SOURCE_CREDENTIAL_USERNAME));
                }
 
-               e_webdav_discover_sources (source, rd->base_url, E_WEBDAV_DISCOVER_SUPPORTS_NONE, 
rd->credentials, rd->cancellable,
-                       e_webdav_discover_content_refresh_done_cb, rd);
+               e_webdav_discover_sources_full (source, rd->base_url, E_WEBDAV_DISCOVER_SUPPORTS_NONE, 
rd->credentials,
+                       rd->registry ? (EWebDAVDiscoverRefSourceFunc) e_source_registry_ref_source : NULL, 
rd->registry,
+                       rd->cancellable, e_webdav_discover_content_refresh_done_cb, rd);
        }
 
        e_named_parameters_free (credentials);
@@ -844,6 +848,10 @@ e_webdav_discover_content_refresh (GtkWidget *content,
        rd->simple = g_simple_async_result_new (G_OBJECT (content), callback, user_data, 
e_webdav_discover_content_refresh);
        rd->base_url = g_strdup (data->base_url);
        rd->credentials = NULL;
+       rd->registry = e_credentials_prompter_get_registry (data->credentials_prompter);
+
+       if (rd->registry)
+               g_object_ref (rd->registry);
 
        if (data->source) {
                source = g_object_ref (data->source);
@@ -888,8 +896,9 @@ e_webdav_discover_content_refresh (GtkWidget *content,
 
        gtk_grid_attach (GTK_GRID (content), GTK_WIDGET (data->info_bar), 0, 2, 1, 1);
 
-       e_webdav_discover_sources (source, rd->base_url, E_WEBDAV_DISCOVER_SUPPORTS_NONE, rd->credentials, 
rd->cancellable,
-               e_webdav_discover_content_refresh_done_cb, rd);
+       e_webdav_discover_sources_full (source, rd->base_url, E_WEBDAV_DISCOVER_SUPPORTS_NONE, 
rd->credentials,
+               rd->registry ? (EWebDAVDiscoverRefSourceFunc) e_source_registry_ref_source : NULL, 
rd->registry,
+               rd->cancellable, e_webdav_discover_content_refresh_done_cb, rd);
 
        g_object_unref (source);
        soup_uri_free (soup_uri);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]