[evolution/wip/webkit2] Move authentication of backends back to the client
- From: Tomas Popela <tpopela src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/wip/webkit2] Move authentication of backends back to the client
- Date: Wed, 22 Apr 2015 12:51:27 +0000 (UTC)
commit 77c3ed213e7d32c23231175b30aa7597685df189
Author: Milan Crha <mcrha redhat com>
Date: Mon Feb 2 14:50:27 2015 +0100
Move authentication of backends back to the client
Since this change the client is responsible to provide credentials
to use to authenticate backends (through ESource-s, to be more precise),
unless the credentials are already saved.
.../gui/contact-editor/e-contact-quick-add.c | 4 +-
addressbook/gui/widgets/e-addressbook-selector.c | 2 +-
addressbook/gui/widgets/eab-contact-compare.c | 2 +-
addressbook/gui/widgets/eab-gui-util.c | 2 +-
addressbook/importers/evolution-csv-importer.c | 2 +-
addressbook/importers/evolution-ldif-importer.c | 2 +-
addressbook/importers/evolution-vcard-importer.c | 2 +-
.../evolution-addressbook-export-list-cards.c | 2 +-
.../evolution-addressbook-export-list-folders.c | 2 +-
calendar/alarm-notify/alarm-notify.c | 4 +-
calendar/gui/dialogs/copy-source-dialog.c | 4 +-
calendar/gui/e-cal-model.c | 2 +-
calendar/gui/e-cal-ops.c | 10 +-
calendar/gui/e-calendar-view.c | 2 +-
calendar/importers/icalendar-importer.c | 4 +-
configure.ac | 6 +-
e-util/e-client-cache.c | 93 +++-
e-util/e-client-cache.h | 10 +-
e-util/e-client-combo-box.c | 2 +-
e-util/e-client-selector.c | 121 ++---
e-util/e-client-selector.h | 2 +
e-util/e-misc-utils.c | 70 +---
e-util/e-misc-utils.h | 15 +-
e-util/e-name-selector-entry.c | 2 +-
e-util/e-name-selector.c | 2 +-
e-util/test-source-selector.c | 4 +-
evolution-shell.pc.in | 2 +-
libemail-engine/Makefile.am | 2 -
libemail-engine/e-mail-authenticator.c | 266 ----------
libemail-engine/e-mail-authenticator.h | 79 ---
libemail-engine/e-mail-session-utils.c | 8 +-
libemail-engine/e-mail-session.c | 228 ++-------
libemail-engine/e-mail-session.h | 5 +
libemail-engine/libemail-engine.h | 1 -
libemail-engine/mail-ops.c | 7 +-
mail/e-mail-account-store.c | 23 +-
mail/e-mail-backend.c | 15 +
mail/e-mail-ui-session.c | 260 +++++++++-
mail/importers/pine-importer.c | 2 +-
modules/addressbook/e-book-shell-backend.c | 4 +-
modules/addressbook/e-book-shell-view-actions.c | 112 +---
modules/addressbook/e-book-shell-view-private.c | 2 +-
.../cal-config-caldav/e-caldav-chooser-dialog.c | 134 ++++-
modules/cal-config-caldav/e-caldav-chooser.c | 295 +++++++++---
modules/cal-config-caldav/e-caldav-chooser.h | 30 ++
.../evolution-cal-config-caldav.c | 16 +
modules/calendar/e-cal-attachment-handler.c | 2 +-
modules/calendar/e-cal-base-shell-backend.c | 2 +-
modules/calendar/e-cal-base-shell-sidebar.c | 6 +-
modules/calendar/e-cal-base-shell-view.c | 16 +-
modules/contact-photos/e-contact-photo-source.c | 2 +-
modules/itip-formatter/itip-view.c | 17 +-
modules/mail/e-mail-shell-view-actions.c | 62 +--
modules/vcard-inline/e-mail-part-vcard.c | 2 +-
plugins/bbdb/bbdb.c | 4 +-
plugins/mail-to-task/mail-to-task.c | 2 +-
plugins/publish-calendar/publish-format-fb.c | 2 +-
plugins/publish-calendar/publish-format-ical.c | 2 +-
plugins/save-calendar/csv-format.c | 2 +-
plugins/save-calendar/ical-format.c | 2 +-
plugins/save-calendar/rdf-format.c | 2 +-
po/POTFILES.in | 1 -
shell/e-shell-window.c | 2 +-
shell/e-shell.c | 546 +++++++++++++++++++-
shell/e-shell.h | 5 +
shell/shell.error.xml | 32 ++
66 files changed, 1522 insertions(+), 1053 deletions(-)
---
diff --git a/addressbook/gui/contact-editor/e-contact-quick-add.c
b/addressbook/gui/contact-editor/e-contact-quick-add.c
index dbcdd56..2830508 100644
--- a/addressbook/gui/contact-editor/e-contact-quick-add.c
+++ b/addressbook/gui/contact-editor/e-contact-quick-add.c
@@ -190,7 +190,7 @@ quick_add_merge_contact (QuickAdd *qa)
e_client_cache_get_client (
qa->client_cache, qa->source,
- E_SOURCE_EXTENSION_ADDRESS_BOOK,
+ E_SOURCE_EXTENSION_ADDRESS_BOOK, 30,
qa->cancellable, merge_cb, qa);
}
@@ -337,7 +337,7 @@ edit_contact (QuickAdd *qa)
e_client_cache_get_client (
qa->client_cache, qa->source,
- E_SOURCE_EXTENSION_ADDRESS_BOOK,
+ E_SOURCE_EXTENSION_ADDRESS_BOOK, 30,
qa->cancellable, ce_have_book, qa);
}
diff --git a/addressbook/gui/widgets/e-addressbook-selector.c
b/addressbook/gui/widgets/e-addressbook-selector.c
index 60a4b0e..5d4eb93 100644
--- a/addressbook/gui/widgets/e-addressbook-selector.c
+++ b/addressbook/gui/widgets/e-addressbook-selector.c
@@ -326,7 +326,7 @@ addressbook_selector_data_dropped (ESourceSelector *selector,
merge_context->pending_adds = TRUE;
e_client_selector_get_client (
- E_CLIENT_SELECTOR (selector), destination, FALSE, NULL,
+ E_CLIENT_SELECTOR (selector), destination, FALSE, 30, NULL,
target_client_connect_cb, merge_context);
return TRUE;
diff --git a/addressbook/gui/widgets/eab-contact-compare.c b/addressbook/gui/widgets/eab-contact-compare.c
index 776e26d..21648af 100644
--- a/addressbook/gui/widgets/eab-contact-compare.c
+++ b/addressbook/gui/widgets/eab-contact-compare.c
@@ -831,7 +831,7 @@ eab_contact_locate_match_full (ESourceRegistry *registry,
source = e_source_registry_ref_default_address_book (registry);
- e_book_client_connect (source, NULL, book_client_connect_cb, info);
+ e_book_client_connect (source, 30, NULL, book_client_connect_cb, info);
g_object_unref (source);
}
diff --git a/addressbook/gui/widgets/eab-gui-util.c b/addressbook/gui/widgets/eab-gui-util.c
index 8718cda..7fa58d4 100644
--- a/addressbook/gui/widgets/eab-gui-util.c
+++ b/addressbook/gui/widgets/eab-gui-util.c
@@ -618,7 +618,7 @@ eab_transfer_contacts (ESourceRegistry *registry,
process->delete_from_source = delete_from_source;
e_book_client_connect (
- destination, NULL, book_client_connect_cb, process);
+ destination, 30, NULL, book_client_connect_cb, process);
}
/*
diff --git a/addressbook/importers/evolution-csv-importer.c b/addressbook/importers/evolution-csv-importer.c
index 5e1eb33..89d1583 100644
--- a/addressbook/importers/evolution-csv-importer.c
+++ b/addressbook/importers/evolution-csv-importer.c
@@ -929,7 +929,7 @@ csv_import (EImport *ei,
source = g_datalist_get_data (&target->data, "csv-source");
- e_book_client_connect (source, NULL, book_client_connect_cb, gci);
+ e_book_client_connect (source, 30, NULL, book_client_connect_cb, gci);
}
static void
diff --git a/addressbook/importers/evolution-ldif-importer.c b/addressbook/importers/evolution-ldif-importer.c
index 7268a1a..ac616cc 100644
--- a/addressbook/importers/evolution-ldif-importer.c
+++ b/addressbook/importers/evolution-ldif-importer.c
@@ -723,7 +723,7 @@ ldif_import (EImport *ei,
source = g_datalist_get_data (&target->data, "ldif-source");
- e_book_client_connect (source, NULL, book_client_connect_cb, gci);
+ e_book_client_connect (source, 30, NULL, book_client_connect_cb, gci);
}
static void
diff --git a/addressbook/importers/evolution-vcard-importer.c
b/addressbook/importers/evolution-vcard-importer.c
index 636210f..b6a3abc 100644
--- a/addressbook/importers/evolution-vcard-importer.c
+++ b/addressbook/importers/evolution-vcard-importer.c
@@ -548,7 +548,7 @@ vcard_import (EImport *ei,
source = g_datalist_get_data (&target->data, "vcard-source");
- e_book_client_connect (source, NULL, book_client_connect_cb, gci);
+ e_book_client_connect (source, 30, NULL, book_client_connect_cb, gci);
}
static void
diff --git a/addressbook/tools/evolution-addressbook-export-list-cards.c
b/addressbook/tools/evolution-addressbook-export-list-cards.c
index c6261f6..c89c54b 100644
--- a/addressbook/tools/evolution-addressbook-export-list-cards.c
+++ b/addressbook/tools/evolution-addressbook-export-list-cards.c
@@ -719,7 +719,7 @@ action_list_cards_init (ActionContext *p_actctx)
else
source = e_source_registry_ref_default_address_book (registry);
- client = e_book_client_connect_sync (source, NULL, &error);
+ client = e_book_client_connect_sync (source, 30, NULL, &error);
g_object_unref (source);
diff --git a/addressbook/tools/evolution-addressbook-export-list-folders.c
b/addressbook/tools/evolution-addressbook-export-list-folders.c
index 41b232c..8e137b8 100644
--- a/addressbook/tools/evolution-addressbook-export-list-folders.c
+++ b/addressbook/tools/evolution-addressbook-export-list-folders.c
@@ -63,7 +63,7 @@ action_list_folders_init (ActionContext *p_actctx)
source = E_SOURCE (iter->data);
- client = e_book_client_connect_sync (source, NULL, &error);
+ client = e_book_client_connect_sync (source, 30, NULL, &error);
/* Sanity check. */
g_warn_if_fail (
diff --git a/calendar/alarm-notify/alarm-notify.c b/calendar/alarm-notify/alarm-notify.c
index fc71d69..50621f1 100644
--- a/calendar/alarm-notify/alarm-notify.c
+++ b/calendar/alarm-notify/alarm-notify.c
@@ -312,9 +312,7 @@ alarm_notify_add_calendar (AlarmNotify *an,
debug (("Opening '%s' (%s)", e_source_get_display_name (source), e_source_get_uid (source)));
- e_cal_client_connect (
- source, source_type, NULL,
- client_connect_cb, an);
+ e_cal_client_connect (source, source_type, 30, NULL, client_connect_cb, an);
g_mutex_unlock (&an->priv->mutex);
}
diff --git a/calendar/gui/dialogs/copy-source-dialog.c b/calendar/gui/dialogs/copy-source-dialog.c
index 6210587..0c0fd10 100644
--- a/calendar/gui/dialogs/copy-source-dialog.c
+++ b/calendar/gui/dialogs/copy-source-dialog.c
@@ -111,14 +111,14 @@ copy_source_thread (EAlertSinkThreadJobData *job_data,
if (!csd)
goto out;
- client = e_util_open_client_sync (job_data, e_cal_model_get_client_cache (csd->model),
csd->extension_name, csd->from_source, cancellable, error);
+ client = e_util_open_client_sync (job_data, e_cal_model_get_client_cache (csd->model),
csd->extension_name, csd->from_source, 30, cancellable, error);
if (client)
from_client = E_CAL_CLIENT (client);
if (!from_client)
goto out;
- client = e_util_open_client_sync (job_data, e_cal_model_get_client_cache (csd->model),
csd->extension_name, csd->to_source, cancellable, error);
+ client = e_util_open_client_sync (job_data, e_cal_model_get_client_cache (csd->model),
csd->extension_name, csd->to_source, 30, cancellable, error);
if (client)
to_client = E_CAL_CLIENT (client);
diff --git a/calendar/gui/e-cal-model.c b/calendar/gui/e-cal-model.c
index 44253bb..b4f399e 100644
--- a/calendar/gui/e-cal-model.c
+++ b/calendar/gui/e-cal-model.c
@@ -1188,7 +1188,7 @@ cal_model_create_component_from_values_thread (EAlertSinkThreadJobData *job_data
e_alert_sink_thread_job_set_alert_arg_0 (job_data, e_source_get_display_name (source));
client = e_client_cache_get_client_sync (client_cache, source,
- cal_model_kind_to_extension_name (ccd->model), cancellable, &local_error);
+ cal_model_kind_to_extension_name (ccd->model), (guint32) -1, cancellable, &local_error);
g_clear_object (&source);
if (!client) {
diff --git a/calendar/gui/e-cal-ops.c b/calendar/gui/e-cal-ops.c
index cd8224e..3d5fc1a 100644
--- a/calendar/gui/e-cal-ops.c
+++ b/calendar/gui/e-cal-ops.c
@@ -590,7 +590,7 @@ cal_ops_update_components_thread (EAlertSinkThreadJobData *job_data,
e_alert_sink_thread_job_set_alert_arg_0 (job_data, e_source_get_display_name (source));
- client = e_client_cache_get_client_sync (client_cache, source, pcd->extension_name, cancellable,
&local_error);
+ client = e_client_cache_get_client_sync (client_cache, source, pcd->extension_name, 30, cancellable,
&local_error);
g_clear_object (&source);
if (!client) {
@@ -1209,7 +1209,7 @@ cal_ops_open_client_sync (EAlertSinkThreadJobData *job_data,
_("Source with UID '%s' not found"), client_uid);
e_alert_sink_thread_job_set_alert_arg_0 (job_data, client_uid);
} else {
- client = e_client_cache_get_client_sync (client_cache, source, extension_name, cancellable,
error);
+ client = e_client_cache_get_client_sync (client_cache, source, extension_name, 30,
cancellable, error);
if (client)
cal_client = E_CAL_CLIENT (client);
}
@@ -1560,7 +1560,7 @@ cal_ops_new_component_editor_thread (EAlertSinkThreadJobData *job_data,
client_cache = e_shell_get_client_cache (ncd->shell);
- client = e_client_cache_get_client_sync (client_cache, ncd->default_source,
ncd->extension_name, cancellable, &local_error);
+ client = e_client_cache_get_client_sync (client_cache, ncd->default_source,
ncd->extension_name, 30, cancellable, &local_error);
if (client)
ncd->client = E_CAL_CLIENT (client);
}
@@ -1930,7 +1930,7 @@ transfer_components_thread (EAlertSinkThreadJobData *job_data,
client_cache = e_shell_get_client_cache (tcd->shell);
- to_client = e_util_open_client_sync (job_data, client_cache, extension_name, tcd->destination,
cancellable, error);
+ to_client = e_util_open_client_sync (job_data, client_cache, extension_name, tcd->destination, 30,
cancellable, error);
if (!to_client)
goto out;
@@ -1948,7 +1948,7 @@ transfer_components_thread (EAlertSinkThreadJobData *job_data,
ESource *source = key;
GSList *icalcomps = value;
- from_client = e_util_open_client_sync (job_data, client_cache, extension_name, source,
cancellable, error);
+ from_client = e_util_open_client_sync (job_data, client_cache, extension_name, source, 30,
cancellable, error);
if (!from_client) {
success = FALSE;
goto out;
diff --git a/calendar/gui/e-calendar-view.c b/calendar/gui/e-calendar-view.c
index 22b278f..799054e 100644
--- a/calendar/gui/e-calendar-view.c
+++ b/calendar/gui/e-calendar-view.c
@@ -853,7 +853,7 @@ cal_view_paste_clipboard_thread (EAlertSinkThreadJobData *job_data,
e_alert_sink_thread_job_set_alert_arg_0 (job_data, e_source_get_display_name (source));
client_cache = e_cal_model_get_client_cache (model);
- e_client = e_client_cache_get_client_sync (client_cache, source, extension_name, cancellable,
&local_error);
+ e_client = e_client_cache_get_client_sync (client_cache, source, extension_name, 30, cancellable,
&local_error);
if (!e_client) {
e_util_propagate_open_source_job_error (job_data, extension_name, local_error, error);
goto out;
diff --git a/calendar/importers/icalendar-importer.c b/calendar/importers/icalendar-importer.c
index fd4c9ad..f59aacf 100644
--- a/calendar/importers/icalendar-importer.c
+++ b/calendar/importers/icalendar-importer.c
@@ -463,7 +463,7 @@ ivcal_import (EImport *ei,
e_cal_client_connect (
g_datalist_get_data (&target->data, "primary-source"),
- type, ici->cancellable, ivcal_connect_cb, ici);
+ type, 30, ici->cancellable, ivcal_connect_cb, ici);
}
static void
@@ -901,7 +901,7 @@ open_default_source (ICalIntelligentImporter *ici,
e_import_status (ici->ei, ici->target, _("Opening calendar"), 0);
e_cal_client_connect (
- source, source_type, ici->cancellable,
+ source, source_type, 30, ici->cancellable,
default_client_connect_cb, odsd);
g_object_unref (source);
diff --git a/configure.ac b/configure.ac
index 49e4547..55ca4a5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -303,6 +303,7 @@ PKG_CHECK_MODULES([EVOLUTION_DATA_SERVER],
libebook-1.2 >= eds_minimum_version
libecal-1.2 >= eds_minimum_version
libedataserver-1.2 >= eds_minimum_version
+ libedataserverui-1.2 >= eds_minimum_version
libebackend-1.2 >= eds_minimum_version])
AC_SUBST(EVOLUTION_DATA_SERVER_CFLAGS)
AC_SUBST(EVOLUTION_DATA_SERVER_LIBS)
@@ -1127,9 +1128,8 @@ dnl CERT_UI Flags
dnl ******************************
dnl
dnl Here we want the Mozilla flags to go *before* the other ones,
-dnl especially the mozilla-nss -I flags to go before the gnutls ones
-dnl (which are dragged in through libedataserverui), as both
-dnl gnutls and mozilla-nss have a header called "pkcs12.h" which is
+dnl especially the mozilla-nss -I flags to go before the gnutls ones,
+dnl as both gnutls and mozilla-nss have a header called "pkcs12.h" which is
dnl included in smime/lib/e-pkcs12.c. It wants the Mozilla NSS one.
dnl
CERT_UI_CFLAGS="$MANUAL_NSS_CFLAGS $MOZILLA_NSS_CFLAGS"
diff --git a/e-util/e-client-cache.c b/e-util/e-client-cache.c
index 39d670f..8a962ad 100644
--- a/e-util/e-client-cache.c
+++ b/e-util/e-client-cache.c
@@ -95,6 +95,7 @@ enum {
CLIENT_CONNECTED,
CLIENT_CREATED,
CLIENT_NOTIFY,
+ ALLOW_AUTH_PROMPT,
LAST_SIGNAL
};
@@ -656,21 +657,6 @@ client_cache_cal_connect_cb (GObject *source_object,
}
static void
-client_cache_source_allow_auth_prompt_done_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- GError *local_error = NULL;
-
- e_source_allow_auth_prompt_finish (E_SOURCE (source_object), result, &local_error);
-
- if (local_error) {
- g_debug ("%s: Failed with: %s", G_STRFUNC, local_error->message);
- g_clear_error (&local_error);
- }
-}
-
-static void
client_cache_source_removed_cb (ESourceRegistry *registry,
ESource *source,
GWeakRef *weak_ref)
@@ -695,10 +681,7 @@ client_cache_source_disabled_cb (ESourceRegistry *registry,
client_cache = g_weak_ref_get (weak_ref);
if (client_cache != NULL) {
- /* There is not much interest in the result, it just
- makes sure a password prompt will be shown the next
- time it is needed. */
- e_source_allow_auth_prompt (source, NULL, client_cache_source_allow_auth_prompt_done_cb,
NULL);
+ e_client_cache_emit_allow_auth_prompt (client_cache, source);
client_ht_remove (client_cache, source);
g_object_unref (client_cache);
@@ -924,7 +907,7 @@ e_client_cache_class_init (EClientCacheClass *class)
"client-connected",
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_FIRST,
- 0 /* G_STRUCT_OFFSET (EClientCacheClass, client_connected) */,
+ G_STRUCT_OFFSET (EClientCacheClass, client_connected),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
E_TYPE_CLIENT);
@@ -980,6 +963,25 @@ e_client_cache_class_init (EClientCacheClass *class)
G_TYPE_NONE, 2,
E_TYPE_CLIENT,
G_TYPE_PARAM);
+
+ /**
+ * EClientCache::allow-auth-prompt:
+ * @client_cache: an #EClientCache, which sent the signal
+ * @source: an #ESource
+ *
+ * This signal is emitted with e_client_cache_emit_allow_auth_prompt() to let
+ * any listeners know to enable credentials prompt for the given @source.
+ *
+ * Since: 3.14
+ **/
+ signals[ALLOW_AUTH_PROMPT] = g_signal_new (
+ "allow-auth-prompt",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (EClientCacheClass, allow_auth_prompt),
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 1,
+ E_TYPE_SOURCE);
}
static void
@@ -1094,6 +1096,7 @@ client_cache_get_client_sync_cb (GObject *source_object,
* @client_cache: an #EClientCache
* @source: an #ESource
* @extension_name: an extension name
+ * @wait_for_connected_seconds: timeout, in seconds, to wait for the backend to be fully connected
* @cancellable: optional #GCancellable object, or %NULL
* @error: return location for a #GError, or %NULL
*
@@ -1118,6 +1121,15 @@ client_cache_get_client_sync_cb (GObject *source_object,
* for this function to work. All other @extension_name values will
* result in an error.
*
+ * The @wait_for_connected_seconds argument had been added since 3.14,
+ * to let the caller decide how long to wait for the backend to fully
+ * connect to its (possibly remote) data store. This is required due
+ * to a change in the authentication process, which is fully asynchronous
+ * and done on the client side, while not every client is supposed to
+ * response to authentication requests. In case the backend will not connect
+ * within the set interval, then it is opened in an offline mode. A special
+ * value -1 can be used to not wait for the connected state at all.
+ *
* If a request for the same @source and @extension_name is already in
* progress when this function is called, this request will "piggyback"
* on the in-progress request such that they will both succeed or fail
@@ -1133,6 +1145,7 @@ EClient *
e_client_cache_get_client_sync (EClientCache *client_cache,
ESource *source,
const gchar *extension_name,
+ guint32 wait_for_connected_seconds,
GCancellable *cancellable,
GError **error)
{
@@ -1148,7 +1161,7 @@ e_client_cache_get_client_sync (EClientCache *client_cache,
g_mutex_lock (&data.mutex);
e_client_cache_get_client (
- client_cache, source, extension_name,cancellable,
+ client_cache, source, extension_name, wait_for_connected_seconds, cancellable,
client_cache_get_client_sync_cb, &data);
/* This is needed, because e_async_closure_new() pushes its own thread default main context,
@@ -1176,6 +1189,7 @@ e_client_cache_get_client_sync (EClientCache *client_cache,
* @client_cache: an #EClientCache
* @source: an #ESource
* @extension_name: an extension name
+ * @wait_for_connected_seconds: timeout, in seconds, to wait for the backend to be fully connected
* @cancellable: optional #GCancellable object, or %NULL
* @callback: a #GAsyncReadyCallback to call when the request is satisfied
* @user_data: data to pass to the callback function
@@ -1201,6 +1215,15 @@ e_client_cache_get_client_sync (EClientCache *client_cache,
* for this function to work. All other @extension_name values will
* result in an error.
*
+ * The @wait_for_connected_seconds argument had been added since 3.14,
+ * to let the caller decide how long to wait for the backend to fully
+ * connect to its (possibly remote) data store. This is required due
+ * to a change in the authentication process, which is fully asynchronous
+ * and done on the client side, while not every client is supposed to
+ * response to authentication requests. In case the backend will not connect
+ * within the set interval, then it is opened in an offline mode. A special
+ * value -1 can be used to not wait for the connected state at all.
+ *
* If a request for the same @source and @extension_name is already in
* progress when this function is called, this request will "piggyback"
* on the in-progress request such that they will both succeed or fail
@@ -1214,6 +1237,7 @@ void
e_client_cache_get_client (EClientCache *client_cache,
ESource *source,
const gchar *extension_name,
+ guint32 wait_for_connected_seconds,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
@@ -1276,7 +1300,7 @@ e_client_cache_get_client (EClientCache *client_cache,
if (g_str_equal (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK)) {
e_book_client_connect (
- source, cancellable,
+ source, wait_for_connected_seconds, cancellable,
client_cache_book_connect_cb,
client_data_ref (client_data));
goto exit;
@@ -1284,7 +1308,7 @@ e_client_cache_get_client (EClientCache *client_cache,
if (g_str_equal (extension_name, E_SOURCE_EXTENSION_CALENDAR)) {
e_cal_client_connect (
- source, E_CAL_CLIENT_SOURCE_TYPE_EVENTS,
+ source, E_CAL_CLIENT_SOURCE_TYPE_EVENTS, wait_for_connected_seconds,
cancellable, client_cache_cal_connect_cb,
client_data_ref (client_data));
goto exit;
@@ -1292,7 +1316,7 @@ e_client_cache_get_client (EClientCache *client_cache,
if (g_str_equal (extension_name, E_SOURCE_EXTENSION_MEMO_LIST)) {
e_cal_client_connect (
- source, E_CAL_CLIENT_SOURCE_TYPE_MEMOS,
+ source, E_CAL_CLIENT_SOURCE_TYPE_MEMOS, wait_for_connected_seconds,
cancellable, client_cache_cal_connect_cb,
client_data_ref (client_data));
goto exit;
@@ -1300,7 +1324,7 @@ e_client_cache_get_client (EClientCache *client_cache,
if (g_str_equal (extension_name, E_SOURCE_EXTENSION_TASK_LIST)) {
e_cal_client_connect (
- source, E_CAL_CLIENT_SOURCE_TYPE_TASKS,
+ source, E_CAL_CLIENT_SOURCE_TYPE_TASKS, wait_for_connected_seconds,
cancellable, client_cache_cal_connect_cb,
client_data_ref (client_data));
goto exit;
@@ -1429,3 +1453,22 @@ e_client_cache_is_backend_dead (EClientCache *client_cache,
return dead_backend;
}
+/**
+ * e_client_cache_emit_allow_auth_prompt:
+ * @client_cache: an #EClientCache
+ * @source: an #ESource
+ *
+ * Emits 'allow-auth-prompt' on @client_cache for @source. This lets
+ * any listeners know to enable credentials prompt for this @source.
+ *
+ * Since: 3.14
+ **/
+void
+e_client_cache_emit_allow_auth_prompt (EClientCache *client_cache,
+ ESource *source)
+{
+ g_return_if_fail (E_IS_CLIENT_CACHE (client_cache));
+ g_return_if_fail (E_IS_SOURCE (source));
+
+ g_signal_emit (client_cache, signals[ALLOW_AUTH_PROMPT], 0, source);
+}
diff --git a/e-util/e-client-cache.h b/e-util/e-client-cache.h
index c3c45ed..71d0fd0 100644
--- a/e-util/e-client-cache.h
+++ b/e-util/e-client-cache.h
@@ -76,9 +76,10 @@ struct _EClientCacheClass {
GParamSpec *pspec);
void (*client_created) (EClientCache *client_cache,
EClient *client);
- /* Do not break ABI right now
void (*client_connected) (EClientCache *client_cache,
- EClient *client); */
+ EClient *client);
+ void (*allow_auth_prompt) (EClientCache *client_cache,
+ ESource *source);
};
GType e_client_cache_get_type (void) G_GNUC_CONST;
@@ -88,11 +89,13 @@ ESourceRegistry *
EClient * e_client_cache_get_client_sync (EClientCache *client_cache,
ESource *source,
const gchar *extension_name,
+ guint32 wait_for_connected_seconds,
GCancellable *cancellable,
GError **error);
void e_client_cache_get_client (EClientCache *client_cache,
ESource *source,
const gchar *extension_name,
+ guint32 wait_for_connected_seconds,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
@@ -107,6 +110,9 @@ EClient * e_client_cache_ref_cached_client
gboolean e_client_cache_is_backend_dead (EClientCache *client_cache,
ESource *source,
const gchar *extension_name);
+void e_client_cache_emit_allow_auth_prompt
+ (EClientCache *client_cache,
+ ESource *source);
G_END_DECLS
diff --git a/e-util/e-client-combo-box.c b/e-util/e-client-combo-box.c
index 0845fd0..3b98f1b 100644
--- a/e-util/e-client-combo-box.c
+++ b/e-util/e-client-combo-box.c
@@ -372,7 +372,7 @@ e_client_combo_box_get_client (EClientComboBox *combo_box,
e_client_cache_get_client (
client_cache, source,
- extension_name, cancellable,
+ extension_name, 30, cancellable,
client_combo_box_get_client_done_cb,
g_object_ref (simple));
diff --git a/e-util/e-client-selector.c b/e-util/e-client-selector.c
index 6b65735..6972b2f 100644
--- a/e-util/e-client-selector.c
+++ b/e-util/e-client-selector.c
@@ -516,6 +516,7 @@ e_client_selector_ref_client_cache (EClientSelector *selector)
* @selector: an #ESourceSelector
* @source: an #ESource
* @call_allow_auth_prompt: whether call allow-auth-prompt on the source first
+ * @wait_for_connected_seconds: timeout, in seconds, to wait for the backend to be fully connected
* @cancellable: optional #GCancellable object, or %NULL
* @error: return location for a #GError, or %NULL
*
@@ -531,6 +532,15 @@ e_client_selector_ref_client_cache (EClientSelector *selector)
* "piggyback" on the in-progress request such that they will both succeed
* or fail simultaneously.
*
+ * The @wait_for_connected_seconds argument had been added since 3.14,
+ * to let the caller decide how long to wait for the backend to fully
+ * connect to its (possibly remote) data store. This is required due
+ * to a change in the authentication process, which is fully asynchronous
+ * and done on the client side, while not every client is supposed to
+ * response to authentication requests. In case the backend will not connect
+ * within the set interval, then it is opened in an offline mode. A special
+ * value -1 can be used to not wait for the connected state at all.
+ *
* Unreference the returned #EClient with g_object_unref() when finished
* with it. If an error occurs, the function will set @error and return
* %NULL.
@@ -541,6 +551,7 @@ EClient *
e_client_selector_get_client_sync (EClientSelector *selector,
ESource *source,
gboolean call_allow_auth_prompt,
+ guint32 wait_for_connected_seconds,
GCancellable *cancellable,
GError **error)
{
@@ -551,18 +562,16 @@ e_client_selector_get_client_sync (EClientSelector *selector,
g_return_val_if_fail (E_IS_CLIENT_SELECTOR (selector), NULL);
g_return_val_if_fail (E_IS_SOURCE (source), NULL);
- if (call_allow_auth_prompt) {
- if (!e_source_allow_auth_prompt_sync (source, cancellable, error))
- return NULL;
- }
-
extension_name = e_source_selector_get_extension_name (E_SOURCE_SELECTOR (selector));
client_cache = e_client_selector_ref_client_cache (selector);
+ if (call_allow_auth_prompt)
+ e_client_cache_emit_allow_auth_prompt (client_cache, source);
+
client = e_client_cache_get_client_sync (
client_cache, source,
- extension_name, cancellable, error);
+ extension_name, wait_for_connected_seconds, cancellable, error);
g_object_unref (client_cache);
@@ -604,63 +613,12 @@ client_selector_get_client_done_cb (GObject *source_object,
g_object_unref (simple);
}
-typedef struct _AllowAuthPromptData
-{
- EClientSelector *selector;
- GSimpleAsyncResult *simple;
- GCancellable *cancellable;
-} AllowAuthPromptData;
-
-static void
-client_selector_allow_auth_prompt_done_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- AllowAuthPromptData *data;
- ESource *source;
- GError *local_error = NULL;
-
- g_return_if_fail (E_IS_SOURCE (source_object));
- g_return_if_fail (user_data != NULL);
-
- data = user_data;
- source = E_SOURCE (source_object);
-
- e_source_allow_auth_prompt_finish (source, result, &local_error);
-
- if (local_error) {
- g_simple_async_result_take_error (data->simple, local_error);
- g_simple_async_result_complete (data->simple);
- local_error = NULL;
- } else {
- EClientCache *client_cache;
- const gchar *extension_name;
-
- extension_name = e_source_selector_get_extension_name (
- E_SOURCE_SELECTOR (data->selector));
-
- client_cache = e_client_selector_ref_client_cache (data->selector);
-
- e_client_cache_get_client (
- client_cache, source,
- extension_name, data->cancellable,
- client_selector_get_client_done_cb,
- g_object_ref (data->simple));
-
- g_object_unref (client_cache);
- }
-
- g_clear_object (&data->selector);
- g_clear_object (&data->simple);
- g_clear_object (&data->cancellable);
- g_free (data);
-}
-
/**
* e_client_selector_get_client:
* @selector: an #ESourceSelector
* @source: an #ESource
* @call_allow_auth_prompt: whether call allow-auth-prompt on the source first
+ * @wait_for_connected_seconds: timeout, in seconds, to wait for the backend to be fully connected
* @cancellable: optional #GCancellable object, or %NULL
* @callback: a #GAsyncReadyCallback to call when the request is satisfied
* @user_data: data to pass to the callback function
@@ -677,6 +635,15 @@ client_selector_allow_auth_prompt_done_cb (GObject *source_object,
* "piggyback" on the in-progress request such that they will both succeed
* or fail simultaneously.
*
+ * The @wait_for_connected_seconds argument had been added since 3.14,
+ * to let the caller decide how long to wait for the backend to fully
+ * connect to its (possibly remote) data store. This is required due
+ * to a change in the authentication process, which is fully asynchronous
+ * and done on the client side, while not every client is supposed to
+ * response to authentication requests. In case the backend will not connect
+ * within the set interval, then it is opened in an offline mode. A special
+ * value -1 can be used to not wait for the connected state at all.
+ *
* When the operation is finished, @callback will be called. You can
* then call e_client_selector_get_client_finish() to get the result of
* the operation.
@@ -685,11 +652,14 @@ void
e_client_selector_get_client (EClientSelector *selector,
ESource *source,
gboolean call_allow_auth_prompt,
+ guint32 wait_for_connected_seconds,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GSimpleAsyncResult *simple;
+ EClientCache *client_cache;
+ const gchar *extension_name;
g_return_if_fail (E_IS_CLIENT_SELECTOR (selector));
g_return_if_fail (E_IS_SOURCE (source));
@@ -700,34 +670,21 @@ e_client_selector_get_client (EClientSelector *selector,
g_simple_async_result_set_check_cancellable (simple, cancellable);
- if (call_allow_auth_prompt) {
- AllowAuthPromptData *data;
-
- data = g_new0 (AllowAuthPromptData, 1);
- data->selector = g_object_ref (selector);
- data->simple = g_object_ref (simple);
- data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
-
- e_source_allow_auth_prompt (source, cancellable,
- client_selector_allow_auth_prompt_done_cb, data);
- } else {
- EClientCache *client_cache;
- const gchar *extension_name;
-
- extension_name = e_source_selector_get_extension_name (
- E_SOURCE_SELECTOR (selector));
+ extension_name = e_source_selector_get_extension_name (
+ E_SOURCE_SELECTOR (selector));
- client_cache = e_client_selector_ref_client_cache (selector);
+ client_cache = e_client_selector_ref_client_cache (selector);
- e_client_cache_get_client (
- client_cache, source,
- extension_name, cancellable,
- client_selector_get_client_done_cb,
- g_object_ref (simple));
+ if (call_allow_auth_prompt)
+ e_client_cache_emit_allow_auth_prompt (client_cache, source);
- g_object_unref (client_cache);
- }
+ e_client_cache_get_client (
+ client_cache, source,
+ extension_name, wait_for_connected_seconds, cancellable,
+ client_selector_get_client_done_cb,
+ g_object_ref (simple));
+ g_object_unref (client_cache);
g_object_unref (simple);
}
diff --git a/e-util/e-client-selector.h b/e-util/e-client-selector.h
index c8d3e71..66556c3 100644
--- a/e-util/e-client-selector.h
+++ b/e-util/e-client-selector.h
@@ -68,11 +68,13 @@ EClient * e_client_selector_get_client_sync
(EClientSelector *selector,
ESource *source,
gboolean call_allow_auth_prompt,
+ guint32 wait_for_connected_seconds,
GCancellable *cancellable,
GError **error);
void e_client_selector_get_client (EClientSelector *selector,
ESource *source,
gboolean call_allow_auth_prompt,
+ guint32 wait_for_connected_seconds,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
diff --git a/e-util/e-misc-utils.c b/e-util/e-misc-utils.c
index 8ebcb21..72a610b 100644
--- a/e-util/e-misc-utils.c
+++ b/e-util/e-misc-utils.c
@@ -2308,73 +2308,6 @@ e_util_dup_searchable_categories (void)
return g_list_reverse (res);
}
-
-gboolean
-e_util_allow_auth_prompt_and_refresh_client_sync (EClient *client,
- GCancellable *cancellable,
- GError **error)
-{
- g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
-
- if (!e_source_allow_auth_prompt_sync (e_client_get_source (client), cancellable, error))
- return FALSE;
-
- return e_client_refresh_sync (client, cancellable, error);
-}
-
-static void
-util_allow_auth_prompt_and_refresh_client_thread (GTask *task,
- gpointer source_object,
- gpointer task_data,
- GCancellable *cancellable)
-{
- gboolean success;
- GError *local_error = NULL;
-
- success = e_util_allow_auth_prompt_and_refresh_client_sync (
- E_CLIENT (source_object),
- cancellable, &local_error);
-
- if (local_error != NULL) {
- g_task_return_error (task, local_error);
- } else {
- g_task_return_boolean (task, success);
- }
-}
-
-void
-e_util_allow_auth_prompt_and_refresh_client (EClient *client,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GTask *task;
-
- g_return_if_fail (E_IS_CLIENT (client));
-
- task = g_task_new (client, cancellable, callback, user_data);
- g_task_set_source_tag (task, e_util_allow_auth_prompt_and_refresh_client);
-
- g_task_run_in_thread (task, util_allow_auth_prompt_and_refresh_client_thread);
-
- g_object_unref (task);
-}
-
-gboolean
-e_util_allow_auth_prompt_and_refresh_client_finish (EClient *client,
- GAsyncResult *result,
- GError **error)
-{
- g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
- g_return_val_if_fail (g_task_is_valid (result, client), FALSE);
-
- g_return_val_if_fail (
- g_async_result_is_tagged (
- result, e_util_allow_auth_prompt_and_refresh_client), FALSE);
-
- return g_task_propagate_boolean (G_TASK (result), error);
-}
-
/**
* e_util_get_open_source_job_info:
* @extension_name: an extension name of the source
@@ -2485,6 +2418,7 @@ e_util_open_client_sync (EAlertSinkThreadJobData *job_data,
EClientCache *client_cache,
const gchar *extension_name,
ESource *source,
+ guint32 wait_for_connected_seconds,
GCancellable *cancellable,
GError **error)
{
@@ -2497,7 +2431,7 @@ e_util_open_client_sync (EAlertSinkThreadJobData *job_data,
camel_operation_push_message (cancellable, "%s", description);
- client = e_client_cache_get_client_sync (client_cache, source, extension_name, cancellable,
&local_error);
+ client = e_client_cache_get_client_sync (client_cache, source, extension_name,
wait_for_connected_seconds, cancellable, &local_error);
camel_operation_pop_message (cancellable);
diff --git a/e-util/e-misc-utils.h b/e-util/e-misc-utils.h
index e4c5c1a..3fce1d0 100644
--- a/e-util/e-misc-utils.h
+++ b/e-util/e-misc-utils.h
@@ -194,20 +194,6 @@ GSList * e_util_get_category_filter_options
(void);
GList * e_util_dup_searchable_categories (void);
-gboolean e_util_allow_auth_prompt_and_refresh_client_sync
- (EClient *client,
- GCancellable *cancellable,
- GError **error);
-void e_util_allow_auth_prompt_and_refresh_client
- (EClient *client,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean e_util_allow_auth_prompt_and_refresh_client_finish
- (EClient *client,
- GAsyncResult *result,
- GError **error);
-
gboolean e_util_get_open_source_job_info (const gchar *extension_name,
const gchar *source_display_name,
gchar **description,
@@ -224,6 +210,7 @@ EClient * e_util_open_client_sync (struct _EAlertSinkThreadJobData *job_data,
struct _EClientCache *client_cache,
const gchar *extension_name,
ESource *source,
+ guint32 wait_for_connected_seconds,
GCancellable *cancellable,
GError **error);
diff --git a/e-util/e-name-selector-entry.c b/e-util/e-name-selector-entry.c
index d1e5f7a..0b53b35 100644
--- a/e-util/e-name-selector-entry.c
+++ b/e-util/e-name-selector-entry.c
@@ -2459,7 +2459,7 @@ setup_default_contact_store (ENameSelectorEntry *name_selector_entry)
e_client_cache_get_client (
client_cache, source,
- E_SOURCE_EXTENSION_ADDRESS_BOOK,
+ E_SOURCE_EXTENSION_ADDRESS_BOOK, (guint32) -1,
cancellable,
name_selector_entry_get_client_cb,
g_object_ref (contact_store));
diff --git a/e-util/e-name-selector.c b/e-util/e-name-selector.c
index cd0eb01..53f9b36 100644
--- a/e-util/e-name-selector.c
+++ b/e-util/e-name-selector.c
@@ -199,7 +199,7 @@ e_name_selector_load_books (ENameSelector *name_selector)
* concurrent operations like this. */
e_client_cache_get_client (
client_cache, source,
- E_SOURCE_EXTENSION_ADDRESS_BOOK,
+ E_SOURCE_EXTENSION_ADDRESS_BOOK, (guint32) -1,
name_selector->priv->cancellable,
name_selector_get_client_cb,
g_object_ref (name_selector));
diff --git a/e-util/test-source-selector.c b/e-util/test-source-selector.c
index 8b09142..8c08163 100644
--- a/e-util/test-source-selector.c
+++ b/e-util/test-source-selector.c
@@ -137,10 +137,10 @@ open_selected_clicked_cb (GtkWidget *button,
if (source_type == E_CAL_CLIENT_SOURCE_TYPE_LAST)
client = e_book_client_connect_sync (
- source, NULL, &local_error);
+ source, (guint32) -1, NULL, &local_error);
else
client = e_cal_client_connect_sync (
- source, source_type, NULL, &local_error);
+ source, source_type, (guint32) -1, NULL, &local_error);
if (client != NULL) {
g_hash_table_insert (
diff --git a/evolution-shell.pc.in b/evolution-shell.pc.in
index 9954edc..0127017 100644
--- a/evolution-shell.pc.in
+++ b/evolution-shell.pc.in
@@ -18,7 +18,7 @@ execversion= BASE_VERSION@
Name: evolution-shell
Description: libraries needed for Evolution shell components
Version: @VERSION@
-Requires: gtk+-3.0 libebackend-1.2 webkitgtk-3.0
+Requires: gtk+-3.0 libebackend-1.2 libedataserver-1.2 libedataserverui-1.2 webkitgtk-3.0
Requires.private: @GNOME_DESKTOP_DEPENDENCY@
Libs: -L${privlibdir} -levolution-shell -levolution-util -Wl,-R${privlibdir}
Cflags: -I${privincludedir}
diff --git a/libemail-engine/Makefile.am b/libemail-engine/Makefile.am
index 4dd1bd4..c8ecb91 100644
--- a/libemail-engine/Makefile.am
+++ b/libemail-engine/Makefile.am
@@ -33,7 +33,6 @@ libmailengineinclude_HEADERS = \
libemail-engine.h \
camel-null-store.h \
camel-sasl-xoauth2.h \
- e-mail-authenticator.h \
e-mail-engine-enums.h \
e-mail-engine-enumtypes.h \
e-mail-folder-utils.h \
@@ -57,7 +56,6 @@ libemail_engine_la_SOURCES = \
$(libmailengineinclude_HEADERS) \
camel-null-store.c \
camel-sasl-xoauth2.c \
- e-mail-authenticator.c \
e-mail-engine-enumtypes.c \
e-mail-folder-utils.c \
e-mail-junk-filter.c \
diff --git a/libemail-engine/e-mail-session-utils.c b/libemail-engine/e-mail-session-utils.c
index 8f4630d..8a8e96c 100644
--- a/libemail-engine/e-mail-session-utils.c
+++ b/libemail-engine/e-mail-session-utils.c
@@ -559,14 +559,8 @@ mail_session_send_to_thread (GSimpleAsyncResult *simple,
g_object_unref (session);
if (source) {
- e_source_allow_auth_prompt_sync (source, cancellable, &error);
+ e_mail_session_emit_allow_auth_prompt (session, source);
g_object_unref (source);
-
- if (error) {
- g_simple_async_result_take_error (simple, error);
- e_mail_session_unmark_service_used (session, context->transport);
- return;
- }
}
did_connect = TRUE;
diff --git a/libemail-engine/e-mail-session.c b/libemail-engine/e-mail-session.c
index fb97e4e..6fb442b 100644
--- a/libemail-engine/e-mail-session.c
+++ b/libemail-engine/e-mail-session.c
@@ -51,7 +51,6 @@
/* This too, though it's less of a hack. */
#include "camel-sasl-xoauth2.h"
-#include "e-mail-authenticator.h"
#include "e-mail-session.h"
#include "e-mail-folder-utils.h"
#include "e-mail-utils.h"
@@ -135,6 +134,7 @@ enum {
REFRESH_SERVICE,
STORE_ADDED,
STORE_REMOVED,
+ ALLOW_AUTH_PROMPT,
LAST_SIGNAL
};
@@ -1280,190 +1280,6 @@ mail_session_forget_password (CamelSession *session,
return TRUE;
}
-static CamelCertTrust
-mail_session_trust_prompt (CamelSession *session,
- CamelService *service,
- GTlsCertificate *certificate,
- GTlsCertificateFlags errors)
-{
- EUserPrompter *prompter;
- ENamedParameters *parameters;
- CamelSettings *settings;
- CamelCertTrust response;
- GByteArray *der = NULL;
- gchar *base64;
- gchar *errhex;
- gchar *host;
- gint button_index;
-
- prompter = e_user_prompter_new ();
- parameters = e_named_parameters_new ();
-
- settings = camel_service_ref_settings (service);
- g_return_val_if_fail (CAMEL_IS_NETWORK_SETTINGS (settings), 0);
- host = camel_network_settings_dup_host (
- CAMEL_NETWORK_SETTINGS (settings));
- g_object_unref (settings);
-
- /* XXX No accessor function for this property. */
- g_object_get (certificate, "certificate", &der, NULL);
- g_return_val_if_fail (der != NULL, 0);
- base64 = g_base64_encode (der->data, der->len);
- g_byte_array_unref (der);
-
- errhex = g_strdup_printf ("%x", (gint) errors);
-
- e_named_parameters_set (parameters, "host", host);
- e_named_parameters_set (parameters, "certificate", base64);
- e_named_parameters_set (parameters, "certificate-errors", errhex);
-
- g_free (host);
- g_free (base64);
- g_free (errhex);
-
- button_index = e_user_prompter_extension_prompt_sync (
- prompter, "ETrustPrompt::trust-prompt",
- parameters, NULL, NULL, NULL);
-
- switch (button_index) {
- case 0:
- response = CAMEL_CERT_TRUST_NEVER;
- break;
- case 1:
- response = CAMEL_CERT_TRUST_FULLY;
- break;
- case 2:
- response = CAMEL_CERT_TRUST_TEMPORARY;
- break;
- default:
- response = CAMEL_CERT_TRUST_UNKNOWN;
- break;
- }
-
- e_named_parameters_free (parameters);
- g_object_unref (prompter);
-
- return response;
-}
-
-static gboolean
-mail_session_authenticate_sync (CamelSession *session,
- CamelService *service,
- const gchar *mechanism,
- GCancellable *cancellable,
- GError **error)
-{
- ESource *source;
- ESourceRegistry *registry;
- ESourceAuthenticator *auth;
- CamelServiceAuthType *authtype = NULL;
- CamelAuthenticationResult result;
- const gchar *uid;
- gboolean authenticated;
- gboolean try_empty_password = FALSE;
- GError *local_error = NULL;
-
- /* Do not chain up. Camel's default method is only an example for
- * subclasses to follow. Instead we mimic most of its logic here. */
-
- registry = e_mail_session_get_registry (E_MAIL_SESSION (session));
-
- /* Treat a mechanism name of "none" as NULL. */
- if (g_strcmp0 (mechanism, "none") == 0)
- mechanism = NULL;
-
- /* APOP is one case where a non-SASL mechanism name is passed, so
- * don't bail if the CamelServiceAuthType struct comes back NULL. */
- if (mechanism != NULL)
- authtype = camel_sasl_authtype (mechanism);
-
- /* If the SASL mechanism does not involve a user
- * password, then it gets one shot to authenticate. */
- if (authtype != NULL && !authtype->need_password) {
- result = camel_service_authenticate_sync (
- service, mechanism, cancellable, error);
- if (result == CAMEL_AUTHENTICATION_REJECTED)
- g_set_error (
- error, CAMEL_SERVICE_ERROR,
- CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
- _("%s authentication failed"), mechanism);
- return (result == CAMEL_AUTHENTICATION_ACCEPTED);
- }
-
- /* Some SASL mechanisms can attempt to authenticate without a
- * user password being provided (e.g. single-sign-on credentials),
- * but can fall back to a user password. Handle that case next. */
- if (mechanism != NULL) {
- CamelProvider *provider;
- CamelSasl *sasl;
- const gchar *service_name;
-
- provider = camel_service_get_provider (service);
- service_name = provider->protocol;
-
- /* XXX Would be nice if camel_sasl_try_empty_password_sync()
- * returned the result in an "out" parameter so it's
- * easier to distinguish errors from a "no" answer.
- * YYY There are precisely two states. Either we appear to
- * have credentials (although we don't yet know if the
- * server would *accept* them, of course). Or we don't
- * have any credentials, and we can't even try. There
- * is no middle ground.
- * N.B. For 'have credentials', read 'the ntlm_auth
- * helper exists and at first glance seems to
- * be responding sanely'. */
- sasl = camel_sasl_new (service_name, mechanism, service);
- if (sasl != NULL) {
- try_empty_password =
- camel_sasl_try_empty_password_sync (
- sasl, cancellable, &local_error);
- g_object_unref (sasl);
- }
- }
-
- /* Abort authentication if we got cancelled.
- * Otherwise clear any errors and press on. */
- if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
- return FALSE;
-
- g_clear_error (&local_error);
-
- /* Find a matching ESource for this CamelService. */
- uid = camel_service_get_uid (service);
- source = e_source_registry_ref_source (registry, uid);
-
- if (source == NULL) {
- g_set_error (
- error, CAMEL_SERVICE_ERROR,
- CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
- _("No data source found for UID '%s'"), uid);
- return FALSE;
- }
-
- auth = e_mail_authenticator_new (service, mechanism);
-
- result = CAMEL_AUTHENTICATION_REJECTED;
-
- if (try_empty_password) {
- result = camel_service_authenticate_sync (
- service, mechanism, cancellable, error);
- }
-
- if (result == CAMEL_AUTHENTICATION_REJECTED) {
- /* We need a password, preferrably one cached in
- * the keyring or else by interactive user prompt. */
- authenticated = e_source_registry_authenticate_sync (
- registry, source, auth, cancellable, error);
- } else {
- authenticated = (result == CAMEL_AUTHENTICATION_ACCEPTED);
- }
- g_object_unref (auth);
-
- g_object_unref (source);
-
- return authenticated;
-}
-
static gboolean
mail_session_forward_to_sync (CamelSession *session,
CamelFolder *folder,
@@ -1660,8 +1476,6 @@ e_mail_session_class_init (EMailSessionClass *class)
session_class->add_service = mail_session_add_service;
session_class->get_password = mail_session_get_password;
session_class->forget_password = mail_session_forget_password;
- session_class->trust_prompt = mail_session_trust_prompt;
- session_class->authenticate_sync = mail_session_authenticate_sync;
session_class->forward_to_sync = mail_session_forward_to_sync;
class->create_vfolder_context = mail_session_create_vfolder_context;
@@ -1777,6 +1591,26 @@ e_mail_session_class_init (EMailSessionClass *class)
G_TYPE_NONE, 1,
CAMEL_TYPE_STORE);
+ /**
+ * EMailSession::store-removed
+ * @session: the #EMailSession that emitted the signal
+ * @source: an #ESource
+ *
+ * This signal is emitted with e_mail_session_emit_allow_auth_prompt() to let
+ * any listeners know to enable credentials prompt for the given @source.
+ *
+ * Since: 3.14
+ **/
+ signals[ALLOW_AUTH_PROMPT] = g_signal_new (
+ "allow-auth-prompt",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (EMailSessionClass, allow_auth_prompt),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ E_TYPE_SOURCE);
+
camel_null_store_register_provider ();
/* Make sure ESourceCamel picks up the "none" provider. */
@@ -2552,3 +2386,23 @@ e_mail_session_unmark_service_used (EMailSession *session,
g_mutex_unlock (&session->priv->used_services_lock);
}
+
+/**
+ * e_mail_session_emit_allow_auth_prompt:
+ * @session: an #EMailSession
+ * @source: an #ESource
+ *
+ * Emits 'allow-auth-prompt' on @session for @source. This lets
+ * any listeners know to enable credentials prompt for this @source.
+ *
+ * Since: 3.14
+ **/
+void
+e_mail_session_emit_allow_auth_prompt (EMailSession *session,
+ ESource *source)
+{
+ g_return_if_fail (E_IS_MAIL_SESSION (session));
+ g_return_if_fail (E_IS_SOURCE (source));
+
+ g_signal_emit (session, signals[ALLOW_AUTH_PROMPT], 0, source);
+}
diff --git a/libemail-engine/e-mail-session.h b/libemail-engine/e-mail-session.h
index 0d8f5e6..44374cd 100644
--- a/libemail-engine/e-mail-session.h
+++ b/libemail-engine/e-mail-session.h
@@ -82,6 +82,8 @@ struct _EMailSessionClass {
CamelStore *store);
void (*store_removed) (EMailSession *session,
CamelStore *store);
+ void (*allow_auth_prompt) (EMailSession *session,
+ ESource *source);
};
GType e_mail_session_get_type (void);
@@ -164,6 +166,9 @@ gboolean e_mail_session_mark_service_used_sync
void e_mail_session_unmark_service_used
(EMailSession *session,
CamelService *service);
+void e_mail_session_emit_allow_auth_prompt
+ (EMailSession *session,
+ ESource *source);
/* Useful GBinding transform functions */
gboolean e_binding_transform_service_to_source
diff --git a/libemail-engine/libemail-engine.h b/libemail-engine/libemail-engine.h
index c8eaea0..6e0b2be 100644
--- a/libemail-engine/libemail-engine.h
+++ b/libemail-engine/libemail-engine.h
@@ -22,7 +22,6 @@
#include <libemail-engine/camel-null-store.h>
#include <libemail-engine/camel-sasl-xoauth2.h>
-#include <libemail-engine/e-mail-authenticator.h>
#include <libemail-engine/e-mail-engine-enums.h>
#include <libemail-engine/e-mail-engine-enumtypes.h>
#include <libemail-engine/e-mail-folder-utils.h>
diff --git a/libemail-engine/mail-ops.c b/libemail-engine/mail-ops.c
index 7679d45..8e6484d 100644
--- a/libemail-engine/mail-ops.c
+++ b/libemail-engine/mail-ops.c
@@ -680,13 +680,8 @@ mail_send_message (struct _send_queue_msg *m,
g_object_unref (session);
if (source) {
- gboolean success;
-
- success = e_source_allow_auth_prompt_sync (source, cancellable, error);
+ e_mail_session_emit_allow_auth_prompt (m->session, source);
g_object_unref (source);
-
- if (!success)
- goto exit;
}
if (!camel_service_connect_sync (service, cancellable, error))
diff --git a/mail/e-mail-account-store.c b/mail/e-mail-account-store.c
index 70c7cf3..4a68584 100644
--- a/mail/e-mail-account-store.c
+++ b/mail/e-mail-account-store.c
@@ -504,32 +504,17 @@ mail_account_store_constructed (GObject *object)
}
static void
-mail_account_store_allow_auth_prompt_done_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- GError *local_error = NULL;
-
- e_source_allow_auth_prompt_finish (E_SOURCE (source_object), result, &local_error);
-
- if (local_error) {
- g_debug ("%s: Failed with: %s", G_STRFUNC, local_error->message);
- g_clear_error (&local_error);
- }
-}
-
-static void
call_allow_auth_prompt (ESource *source)
{
+ EShell *shell;
+
if (!source)
return;
g_return_if_fail (E_IS_SOURCE (source));
- /* There is not much interest in the result, it just
- makes sure a password prompt will be shown the next
- time it is needed. */
- e_source_allow_auth_prompt (source, NULL, mail_account_store_allow_auth_prompt_done_cb, NULL);
+ shell = e_shell_get_default ();
+ e_shell_allow_auth_prompt_for (shell, source);
}
static void
diff --git a/mail/e-mail-backend.c b/mail/e-mail-backend.c
index d3113ba..91d9262 100644
--- a/mail/e-mail-backend.c
+++ b/mail/e-mail-backend.c
@@ -931,6 +931,17 @@ mail_backend_job_finished_cb (CamelSession *session,
}
static void
+mail_backend_allow_auth_prompt_cb (EMailSession *session,
+ ESource *source,
+ EShell *shell)
+{
+ g_return_if_fail (E_IS_SOURCE (source));
+ g_return_if_fail (E_IS_SHELL (shell));
+
+ e_shell_allow_auth_prompt_for (shell, source);
+}
+
+static void
mail_backend_get_property (GObject *object,
guint property_id,
GValue *value,
@@ -1158,6 +1169,10 @@ mail_backend_constructed (GObject *object)
priv->session = e_mail_ui_session_new (registry);
g_signal_connect (
+ priv->session, "allow-auth-prompt",
+ G_CALLBACK (mail_backend_allow_auth_prompt_cb), shell);
+
+ g_signal_connect (
priv->session, "flush-outbox",
G_CALLBACK (mail_send), priv->session);
diff --git a/mail/e-mail-ui-session.c b/mail/e-mail-ui-session.c
index 959b2fb..accecfc 100644
--- a/mail/e-mail-ui-session.c
+++ b/mail/e-mail-ui-session.c
@@ -631,6 +631,262 @@ mail_ui_session_user_alert (CamelSession *session,
g_free (display_name);
}
+static gpointer
+mail_ui_session_call_trust_prompt_in_main_thread_cb (const gchar *source_extension,
+ const gchar *source_display_name,
+ const gchar *host,
+ const gchar *certificate_pem,
+ gconstpointer pcertificate_errors)
+{
+ EShell *shell;
+ ETrustPromptResponse prompt_response;
+
+ shell = e_shell_get_default ();
+
+ prompt_response = e_trust_prompt_run_modal (gtk_application_get_active_window (GTK_APPLICATION
(shell)),
+ source_extension, source_display_name, host, certificate_pem, GPOINTER_TO_UINT
(pcertificate_errors), NULL);
+
+ return GINT_TO_POINTER (prompt_response);
+}
+
+static CamelCertTrust
+mail_ui_session_trust_prompt (CamelSession *session,
+ CamelService *service,
+ GTlsCertificate *certificate,
+ GTlsCertificateFlags errors)
+{
+ CamelSettings *settings;
+ CamelCertTrust response;
+ gchar *host, *certificate_pem = NULL;
+ ETrustPromptResponse prompt_response;
+ const gchar *source_extension;
+
+ settings = camel_service_ref_settings (service);
+ g_return_val_if_fail (CAMEL_IS_NETWORK_SETTINGS (settings), 0);
+ host = camel_network_settings_dup_host (
+ CAMEL_NETWORK_SETTINGS (settings));
+ g_object_unref (settings);
+
+ /* XXX No accessor function for this property. */
+ g_object_get (certificate, "certificate-pem", &certificate_pem, NULL);
+ g_return_val_if_fail (certificate_pem != NULL, 0);
+
+ if (CAMEL_IS_TRANSPORT (service))
+ source_extension = E_SOURCE_EXTENSION_MAIL_TRANSPORT;
+ else
+ source_extension = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+
+ prompt_response = GPOINTER_TO_INT (mail_call_main (MAIL_CALL_p_ppppp,
+ (MailMainFunc) mail_ui_session_call_trust_prompt_in_main_thread_cb,
+ source_extension, camel_service_get_display_name (service), host, certificate_pem,
GUINT_TO_POINTER (errors)));
+
+ g_free (certificate_pem);
+ g_free (host);
+
+ switch (prompt_response) {
+ case E_TRUST_PROMPT_RESPONSE_REJECT:
+ response = CAMEL_CERT_TRUST_NEVER;
+ break;
+ case E_TRUST_PROMPT_RESPONSE_ACCEPT:
+ response = CAMEL_CERT_TRUST_FULLY;
+ break;
+ case E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY:
+ response = CAMEL_CERT_TRUST_TEMPORARY;
+ break;
+ default:
+ response = CAMEL_CERT_TRUST_UNKNOWN;
+ break;
+ }
+
+ return response;
+}
+
+typedef struct _TryCredentialsData {
+ CamelService *service;
+ const gchar *mechanism;
+} TryCredentialsData;
+
+static gboolean
+mail_ui_session_try_credentials_sync (ECredentialsPrompter *prompter,
+ ESource *source,
+ const ENamedParameters *credentials,
+ gboolean *out_authenticated,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **error)
+{
+ TryCredentialsData *data = user_data;
+ gchar *credential_name = NULL;
+ CamelAuthenticationResult result;
+
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+ g_return_val_if_fail (credentials != NULL, FALSE);
+ g_return_val_if_fail (out_authenticated != NULL, FALSE);
+ g_return_val_if_fail (data != NULL, FALSE);
+ g_return_val_if_fail (CAMEL_IS_SERVICE (data->service), FALSE);
+
+ if (e_source_has_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION)) {
+ ESourceAuthentication *auth_extension;
+
+ auth_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);
+ credential_name = e_source_authentication_dup_credential_name (auth_extension);
+
+ if (!credential_name || !*credential_name) {
+ g_free (credential_name);
+ credential_name = NULL;
+ }
+ }
+
+ camel_service_set_password (data->service, e_named_parameters_get (credentials,
+ credential_name ? credential_name : E_SOURCE_CREDENTIAL_PASSWORD));
+
+ g_free (credential_name);
+
+ result = camel_service_authenticate_sync (data->service, data->mechanism, cancellable, error);
+
+ *out_authenticated = result == CAMEL_AUTHENTICATION_ACCEPTED;
+
+ if (*out_authenticated) {
+ ESourceCredentialsProvider *credentials_provider;
+ ESource *cred_source;
+
+ credentials_provider = e_credentials_prompter_get_provider (prompter);
+ cred_source = e_source_credentials_provider_ref_credentials_source (credentials_provider,
source);
+
+ if (cred_source)
+ e_source_invoke_authenticate_sync (cred_source, credentials, cancellable, NULL);
+
+ g_clear_object (&cred_source);
+ }
+
+ return result == CAMEL_AUTHENTICATION_REJECTED;
+}
+
+static gboolean
+mail_ui_session_authenticate_sync (CamelSession *session,
+ CamelService *service,
+ const gchar *mechanism,
+ GCancellable *cancellable,
+ GError **error)
+{
+ ESource *source;
+ ESourceRegistry *registry;
+ CamelServiceAuthType *authtype = NULL;
+ CamelAuthenticationResult result;
+ const gchar *uid;
+ gboolean authenticated;
+ gboolean try_empty_password = FALSE;
+ GError *local_error = NULL;
+
+ /* Do not chain up. Camel's default method is only an example for
+ * subclasses to follow. Instead we mimic most of its logic here. */
+
+ registry = e_mail_session_get_registry (E_MAIL_SESSION (session));
+
+ /* Treat a mechanism name of "none" as NULL. */
+ if (g_strcmp0 (mechanism, "none") == 0)
+ mechanism = NULL;
+
+ /* APOP is one case where a non-SASL mechanism name is passed, so
+ * don't bail if the CamelServiceAuthType struct comes back NULL. */
+ if (mechanism != NULL)
+ authtype = camel_sasl_authtype (mechanism);
+
+ /* If the SASL mechanism does not involve a user
+ * password, then it gets one shot to authenticate. */
+ if (authtype != NULL && !authtype->need_password) {
+ result = camel_service_authenticate_sync (
+ service, mechanism, cancellable, error);
+ if (result == CAMEL_AUTHENTICATION_REJECTED)
+ g_set_error (
+ error, CAMEL_SERVICE_ERROR,
+ CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+ _("%s authentication failed"), mechanism);
+ return (result == CAMEL_AUTHENTICATION_ACCEPTED);
+ }
+
+ /* Some SASL mechanisms can attempt to authenticate without a
+ * user password being provided (e.g. single-sign-on credentials),
+ * but can fall back to a user password. Handle that case next. */
+ if (mechanism != NULL) {
+ CamelProvider *provider;
+ CamelSasl *sasl;
+ const gchar *service_name;
+
+ provider = camel_service_get_provider (service);
+ service_name = provider->protocol;
+
+ /* XXX Would be nice if camel_sasl_try_empty_password_sync()
+ * returned the result in an "out" parameter so it's
+ * easier to distinguish errors from a "no" answer.
+ * YYY There are precisely two states. Either we appear to
+ * have credentials (although we don't yet know if the
+ * server would *accept* them, of course). Or we don't
+ * have any credentials, and we can't even try. There
+ * is no middle ground.
+ * N.B. For 'have credentials', read 'the ntlm_auth
+ * helper exists and at first glance seems to
+ * be responding sanely'. */
+ sasl = camel_sasl_new (service_name, mechanism, service);
+ if (sasl != NULL) {
+ try_empty_password =
+ camel_sasl_try_empty_password_sync (
+ sasl, cancellable, &local_error);
+ g_object_unref (sasl);
+ }
+ }
+
+ /* Abort authentication if we got cancelled.
+ * Otherwise clear any errors and press on. */
+ if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return FALSE;
+
+ g_clear_error (&local_error);
+
+ /* Find a matching ESource for this CamelService. */
+ uid = camel_service_get_uid (service);
+ source = e_source_registry_ref_source (registry, uid);
+
+ if (source == NULL) {
+ g_set_error (
+ error, CAMEL_SERVICE_ERROR,
+ CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+ _("No data source found for UID '%s'"), uid);
+ return FALSE;
+ }
+
+ result = CAMEL_AUTHENTICATION_REJECTED;
+
+ if (try_empty_password) {
+ result = camel_service_authenticate_sync (
+ service, mechanism, cancellable, error);
+ }
+
+ if (result == CAMEL_AUTHENTICATION_REJECTED) {
+ /* We need a password, preferrably one cached in
+ * the keyring or else by interactive user prompt. */
+ EShell *shell;
+ ECredentialsPrompter *credentials_prompter;
+ TryCredentialsData data;
+
+ shell = e_shell_get_default ();
+ credentials_prompter = e_shell_get_credentials_prompter (shell);
+
+ data.service = service;
+ data.mechanism = mechanism;
+
+ authenticated = e_credentials_prompter_loop_prompt_sync (credentials_prompter,
+ source, E_CREDENTIALS_PROMPTER_PROMPT_FLAG_ALLOW_SOURCE_SAVE,
+ mail_ui_session_try_credentials_sync, &data, cancellable, error);
+ } else {
+ authenticated = (result == CAMEL_AUTHENTICATION_ACCEPTED);
+ }
+
+ g_object_unref (source);
+
+ return authenticated;
+}
+
extern gint camel_application_is_exiting;
static void
@@ -671,6 +927,8 @@ e_mail_ui_session_class_init (EMailUISessionClass *class)
session_class->get_filter_driver = mail_ui_session_get_filter_driver;
session_class->lookup_addressbook = mail_ui_session_lookup_addressbook;
session_class->user_alert = mail_ui_session_user_alert;
+ session_class->trust_prompt = mail_ui_session_trust_prompt;
+ session_class->authenticate_sync = mail_ui_session_authenticate_sync;
mail_session_class = E_MAIL_SESSION_CLASS (class);
mail_session_class->create_vfolder_context = mail_ui_session_create_vfolder_context;
@@ -942,7 +1200,7 @@ e_mail_ui_session_check_known_address_sync (EMailUISession *session,
client = e_client_cache_get_client_sync (
client_cache, source,
- E_SOURCE_EXTENSION_ADDRESS_BOOK,
+ E_SOURCE_EXTENSION_ADDRESS_BOOK, (guint32) -1,
cancellable, &local_error);
if (client == NULL) {
diff --git a/mail/importers/pine-importer.c b/mail/importers/pine-importer.c
index dc366ca..391ea07 100644
--- a/mail/importers/pine-importer.c
+++ b/mail/importers/pine-importer.c
@@ -196,7 +196,7 @@ import_contacts (void)
ESource *source;
source = E_SOURCE (list->data);
- client = e_book_client_connect_sync (source, NULL, &error);
+ client = e_book_client_connect_sync (source, 30, NULL, &error);
} else {
/* No address books exist. */
g_warning ("%s: No address books exist.", G_STRFUNC);
diff --git a/modules/addressbook/e-book-shell-backend.c b/modules/addressbook/e-book-shell-backend.c
index fd14a26..666120f 100644
--- a/modules/addressbook/e-book-shell-backend.c
+++ b/modules/addressbook/e-book-shell-backend.c
@@ -217,14 +217,14 @@ action_contact_new_cb (GtkAction *action,
if (strcmp (action_name, "contact-new") == 0)
e_client_cache_get_client (
client_cache, source,
- E_SOURCE_EXTENSION_ADDRESS_BOOK,
+ E_SOURCE_EXTENSION_ADDRESS_BOOK, 30,
NULL,
book_shell_backend_new_contact_cb,
g_object_ref (shell));
if (strcmp (action_name, "contact-new-list") == 0)
e_client_cache_get_client (
client_cache, source,
- E_SOURCE_EXTENSION_ADDRESS_BOOK,
+ E_SOURCE_EXTENSION_ADDRESS_BOOK, 30,
NULL,
book_shell_backend_new_contact_list_cb,
g_object_ref (shell));
diff --git a/modules/addressbook/e-book-shell-view-actions.c b/modules/addressbook/e-book-shell-view-actions.c
index b5c0e28..8fe5f63 100644
--- a/modules/addressbook/e-book-shell-view-actions.c
+++ b/modules/addressbook/e-book-shell-view-actions.c
@@ -200,31 +200,6 @@ action_address_book_properties_cb (GtkAction *action,
}
static void
-address_book_handle_refresh_done (ESource *source,
- EActivity *activity,
- const GError *error)
-{
- EAlertSink *alert_sink;
- const gchar *display_name;
-
- alert_sink = e_activity_get_alert_sink (activity);
- display_name = e_source_get_display_name (source);
-
- if (e_activity_handle_cancellation (activity, error)) {
- /* nothing to do */
-
- } else if (error != NULL) {
- e_alert_submit (
- alert_sink,
- "addressbook:refresh-error",
- display_name, error->message, NULL);
-
- } else {
- e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
- }
-}
-
-static void
address_book_refresh_done_cb (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
@@ -232,6 +207,8 @@ address_book_refresh_done_cb (GObject *source_object,
EClient *client;
ESource *source;
EActivity *activity;
+ EAlertSink *alert_sink;
+ const gchar *display_name;
GError *local_error = NULL;
g_return_if_fail (E_IS_CLIENT (source_object));
@@ -240,55 +217,25 @@ address_book_refresh_done_cb (GObject *source_object,
source = e_client_get_source (client);
activity = user_data;
- e_util_allow_auth_prompt_and_refresh_client_finish (client, result, &local_error);
-
- address_book_handle_refresh_done (source, activity, local_error);
-
- g_clear_object (&activity);
- g_clear_error (&local_error);
-}
-
-typedef struct _AllowAuthPromptData {
- EActivity *activity;
- ESourceSelector *selector;
-} AllowAuthPromptData;
-
-static void
-address_book_allow_auth_prompt_done_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- ESource *source;
- ESourceSelector *selector;
- EActivity *activity;
- AllowAuthPromptData *data = user_data;
- GError *local_error = NULL;
-
- g_return_if_fail (E_IS_SOURCE (source_object));
- g_return_if_fail (user_data != NULL);
-
- source = E_SOURCE (source_object);
- activity = data->activity;
- selector = data->selector;
+ e_client_refresh_finish (client, result, &local_error);
- g_free (data);
-
- e_source_allow_auth_prompt_finish (source, result, &local_error);
-
- address_book_handle_refresh_done (source, activity, local_error);
+ alert_sink = e_activity_get_alert_sink (activity);
+ display_name = e_source_get_display_name (source);
- if (!local_error) {
- ESource *primary;
+ if (e_activity_handle_cancellation (activity, local_error)) {
+ /* nothing to do */
- primary = e_source_selector_ref_primary_selection (selector);
- if (primary == source)
- e_source_selector_set_primary_selection (selector, source);
+ } else if (local_error != NULL) {
+ e_alert_submit (
+ alert_sink,
+ "addressbook:refresh-error",
+ display_name, local_error->message, NULL);
- g_clear_object (&primary);
+ } else {
+ e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
}
g_clear_object (&activity);
- g_clear_object (&selector);
g_clear_error (&local_error);
}
@@ -305,6 +252,7 @@ action_address_book_refresh_cb (GtkAction *action,
EShellBackend *shell_backend;
EShellContent *shell_content;
EShellView *shell_view;
+ EShell *shell;
GCancellable *cancellable;
book_shell_sidebar = book_shell_view->priv->book_shell_sidebar;
@@ -313,6 +261,7 @@ action_address_book_refresh_cb (GtkAction *action,
shell_view = E_SHELL_VIEW (book_shell_view);
shell_backend = e_shell_view_get_shell_backend (shell_view);
shell_content = e_shell_view_get_shell_content (shell_view);
+ shell = e_shell_backend_get_shell (shell_backend);
source = e_source_selector_ref_primary_selection (selector);
@@ -320,24 +269,15 @@ action_address_book_refresh_cb (GtkAction *action,
client = e_client_selector_ref_cached_client (
E_CLIENT_SELECTOR (selector), source);
if (!client) {
- AllowAuthPromptData *data;
-
- alert_sink = E_ALERT_SINK (shell_content);
- activity = e_activity_new ();
- cancellable = g_cancellable_new ();
+ ESource *primary;
- e_activity_set_alert_sink (activity, alert_sink);
- e_activity_set_cancellable (activity, cancellable);
+ e_shell_allow_auth_prompt_for (shell, source);
- data = g_new0 (AllowAuthPromptData, 1);
- data->activity = activity;
- data->selector = g_object_ref (selector);
+ primary = e_source_selector_ref_primary_selection (selector);
+ if (primary == source)
+ e_source_selector_set_primary_selection (selector, source);
- e_source_allow_auth_prompt (source, cancellable,
address_book_allow_auth_prompt_done_cb, data);
-
- e_shell_backend_add_activity (shell_backend, activity);
-
- g_object_unref (cancellable);
+ g_clear_object (&primary);
}
g_object_unref (source);
@@ -355,7 +295,9 @@ action_address_book_refresh_cb (GtkAction *action,
e_activity_set_alert_sink (activity, alert_sink);
e_activity_set_cancellable (activity, cancellable);
- e_util_allow_auth_prompt_and_refresh_client (client, cancellable, address_book_refresh_done_cb,
activity);
+ e_shell_allow_auth_prompt_for (shell, source);
+
+ e_client_refresh (client, cancellable, address_book_refresh_done_cb, activity);
e_shell_backend_add_activity (shell_backend, activity);
@@ -418,7 +360,7 @@ map_window_show_contact_editor_cb (EContactMapWindow *window,
/* FIXME This blocks. Needs to be asynchronous. */
client = e_client_cache_get_client_sync (
client_cache, source,
- E_SOURCE_EXTENSION_ADDRESS_BOOK,
+ E_SOURCE_EXTENSION_ADDRESS_BOOK, (guint32) -1,
NULL, &error);
g_object_unref (source);
@@ -485,7 +427,7 @@ action_address_book_map_cb (GtkAction *action,
/* FIXME This blocks. Needs to be asynchronous. */
client = e_client_cache_get_client_sync (
client_cache, source,
- E_SOURCE_EXTENSION_ADDRESS_BOOK,
+ E_SOURCE_EXTENSION_ADDRESS_BOOK, (guint32) -1,
NULL, &error);
g_object_unref (source);
diff --git a/modules/addressbook/e-book-shell-view-private.c b/modules/addressbook/e-book-shell-view-private.c
index b4080a9..59d3584 100644
--- a/modules/addressbook/e-book-shell-view-private.c
+++ b/modules/addressbook/e-book-shell-view-private.c
@@ -339,7 +339,7 @@ book_shell_view_activate_selected_source (EBookShellView *book_shell_view,
/* XXX No way to cancel this? */
e_client_selector_get_client (
E_CLIENT_SELECTOR (selector),
- source, TRUE, NULL,
+ source, TRUE, (guint32) -1, NULL,
book_shell_view_client_connect_cb,
g_object_ref (view));
diff --git a/modules/cal-config-caldav/e-caldav-chooser-dialog.c
b/modules/cal-config-caldav/e-caldav-chooser-dialog.c
index 66c3381..fce3f71 100644
--- a/modules/cal-config-caldav/e-caldav-chooser-dialog.c
+++ b/modules/cal-config-caldav/e-caldav-chooser-dialog.c
@@ -42,6 +42,10 @@ static void caldav_chooser_dialog_populated_cb
(GObject *source_object,
GAsyncResult *result,
gpointer user_data);
+static void caldav_chooser_dialog_credentials_prompt_cb
+ (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data);
G_DEFINE_DYNAMIC_TYPE (
ECaldavChooserDialog,
@@ -67,40 +71,124 @@ caldav_chooser_dialog_done (ECaldavChooserDialog *dialog,
}
}
+/* It's a little weird to have the callback called on the #ESource,
+ but it's simpler than writing a proxy around the e-trust-prompt
+ async call, which would be unnecessary anyway. */
static void
-caldav_chooser_dialog_authenticate_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
+caldav_chooser_dialog_trust_prompt_done_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
{
- ESourceRegistry *registry;
ECaldavChooserDialog *dialog;
ECaldavChooser *chooser;
+ ETrustPromptResponse response = E_TRUST_PROMPT_RESPONSE_UNKNOWN;
GError *error = NULL;
- registry = E_SOURCE_REGISTRY (source_object);
- dialog = E_CALDAV_CHOOSER_DIALOG (user_data);
+ g_return_if_fail (E_IS_SOURCE (source_object));
+ g_return_if_fail (E_IS_CALDAV_CHOOSER_DIALOG (user_data));
+ dialog = E_CALDAV_CHOOSER_DIALOG (user_data);
chooser = e_caldav_chooser_dialog_get_chooser (dialog);
- e_source_registry_authenticate_finish (registry, result, &error);
+ if (!e_trust_prompt_run_for_source_finish (E_SOURCE (source_object), result, &response, &error)) {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ /* close also the dialog */
+ gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
+ } else {
+ caldav_chooser_dialog_done (dialog, error);
+ }
+ } else if (response == E_TRUST_PROMPT_RESPONSE_ACCEPT ||
+ response == E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY) {
+ e_caldav_chooser_populate (
+ chooser, dialog->priv->cancellable,
+ caldav_chooser_dialog_populated_cb,
+ g_object_ref (dialog));
+ } else {
+ g_warn_if_fail (error == NULL);
- /* Ignore cancellations, and leave the mouse cursor alone
- * since the GdkWindow may have already been destroyed. */
- if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
- /* do nothing */
+ error = e_caldav_chooser_new_ssl_trust_error (chooser);
+
+ caldav_chooser_dialog_done (dialog, error);
+ }
+
+ g_clear_error (&error);
+ g_object_unref (dialog);
+}
+
+static void
+caldav_chooser_dialog_authenticate_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ECaldavChooserDialog *dialog = user_data;
+ ECaldavChooser *chooser;
+ GError *error = NULL;
+
+ g_return_if_fail (E_IS_CALDAV_CHOOSER (source_object));
+
+ chooser = E_CALDAV_CHOOSER (source_object);
+
+ if (!e_caldav_chooser_authenticate_finish (chooser, result, &error)) {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ /* close also the dialog */
+ gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
+ } else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED)) {
+ e_caldav_chooser_run_credentials_prompt (
+ chooser,
+ caldav_chooser_dialog_credentials_prompt_cb,
+ g_object_ref (dialog));
+
+ } else if (g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED)) {
+ e_caldav_chooser_run_trust_prompt (chooser, GTK_WINDOW (dialog),
+ dialog->priv->cancellable,
+ caldav_chooser_dialog_trust_prompt_done_cb,
+ g_object_ref (dialog));
+
+ /* We were either successful or got an unexpected error. */
+ } else {
+ caldav_chooser_dialog_done (dialog, error);
+ }
+ } else {
+ g_warn_if_fail (error == NULL);
- /* Successful authentication, so try populating again. */
- } else if (error == NULL) {
e_caldav_chooser_populate (
chooser, dialog->priv->cancellable,
caldav_chooser_dialog_populated_cb,
g_object_ref (dialog));
+ }
+
+ g_clear_error (&error);
+ g_object_unref (dialog);
+}
+
+static void
+caldav_chooser_dialog_credentials_prompt_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ECaldavChooser *chooser;
+ ECaldavChooserDialog *dialog = user_data;
+ ENamedParameters *credentials = NULL;
+ GError *error = NULL;
+
+ g_return_if_fail (E_IS_CREDENTIALS_PROMPTER (source_object));
- /* Still not working? Give up and display an error message. */
+ chooser = e_caldav_chooser_dialog_get_chooser (dialog);
+ g_return_if_fail (chooser != NULL);
+
+ if (!e_caldav_chooser_run_credentials_prompt_finish (chooser, result, &credentials, &error)) {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ /* close also the dialog */
+ gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
+ } else {
+ caldav_chooser_dialog_done (dialog, error);
+ }
} else {
- caldav_chooser_dialog_done (dialog, error);
+ e_caldav_chooser_authenticate (chooser, credentials, dialog->priv->cancellable,
+ caldav_chooser_dialog_authenticate_cb, g_object_ref (dialog));
}
+ e_named_parameters_free (credentials);
g_clear_error (&error);
g_object_unref (dialog);
}
@@ -129,17 +217,15 @@ caldav_chooser_dialog_populated_cb (GObject *source_object,
* round-trip to the server, but we don't want to risk prompting
* for authentication unnecessarily. */
} else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED)) {
- ESourceRegistry *registry;
- ESource *source;
-
- registry = e_caldav_chooser_get_registry (chooser);
- source = e_caldav_chooser_get_source (chooser);
+ e_caldav_chooser_run_credentials_prompt (
+ chooser,
+ caldav_chooser_dialog_credentials_prompt_cb,
+ g_object_ref (dialog));
- e_source_registry_authenticate (
- registry, source,
- E_SOURCE_AUTHENTICATOR (chooser),
+ } else if (g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED)) {
+ e_caldav_chooser_run_trust_prompt (chooser, GTK_WINDOW (dialog),
dialog->priv->cancellable,
- caldav_chooser_dialog_authenticate_cb,
+ caldav_chooser_dialog_trust_prompt_done_cb,
g_object_ref (dialog));
/* We were either successful or got an unexpected error. */
diff --git a/modules/cal-config-caldav/e-caldav-chooser.c b/modules/cal-config-caldav/e-caldav-chooser.c
index 77035c1..c167834 100644
--- a/modules/cal-config-caldav/e-caldav-chooser.c
+++ b/modules/cal-config-caldav/e-caldav-chooser.c
@@ -27,6 +27,7 @@
#include <libxml/xpathInternals.h>
#include <e-util/e-util.h>
+#include <libedataserverui/libedataserverui.h>
#define E_CALDAV_CHOOSER_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE \
@@ -46,11 +47,17 @@ typedef struct _Context Context;
struct _ECaldavChooserPrivate {
ESourceRegistry *registry;
+ ECredentialsPrompter *prompter;
ESource *source;
ECalClientSourceType source_type;
SoupSession *session;
GList *user_address_set;
+ gchar *username;
gchar *password;
+ gchar *certificate_pem;
+ GTlsCertificateFlags certificate_errors;
+ gchar *error_text;
+ gboolean first_auth_request;
};
struct _Context {
@@ -94,8 +101,6 @@ enum {
};
/* Forward Declarations */
-static void e_caldav_chooser_authenticator_init
- (ESourceAuthenticatorInterface *iface);
static void caldav_chooser_get_collection_details
(SoupSession *session,
SoupMessage *message,
@@ -103,14 +108,7 @@ static void caldav_chooser_get_collection_details
GSimpleAsyncResult *simple,
Context *context);
-G_DEFINE_DYNAMIC_TYPE_EXTENDED (
- ECaldavChooser,
- e_caldav_chooser,
- GTK_TYPE_TREE_VIEW,
- 0,
- G_IMPLEMENT_INTERFACE_DYNAMIC (
- E_TYPE_SOURCE_AUTHENTICATOR,
- e_caldav_chooser_authenticator_init))
+G_DEFINE_DYNAMIC_TYPE (ECaldavChooser, e_caldav_chooser, GTK_TYPE_TREE_VIEW)
static gconstpointer
compat_libxml_output_buffer_get_content (xmlOutputBufferPtr buf,
@@ -316,30 +314,26 @@ caldav_chooser_authenticate_cb (SoupSession *session,
{
ESource *source;
ESourceAuthentication *extension;
- const gchar *extension_name;
- const gchar *username;
- const gchar *password;
source = e_caldav_chooser_get_source (chooser);
- extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
- extension = e_source_get_extension (source, extension_name);
-
- username = e_source_authentication_get_user (extension);
- password = chooser->priv->password;
+ extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);
/* If our password was rejected, let the operation fail. */
if (retrying)
return;
+ if (!chooser->priv->username)
+ chooser->priv->username = e_source_authentication_dup_user (extension);
+
/* If we don't have a username, let the operation fail. */
- if (username == NULL || *username == '\0')
+ if (chooser->priv->username == NULL || *chooser->priv->username == '\0')
return;
/* If we don't have a password, let the operation fail. */
- if (password == NULL || *password == '\0')
+ if (chooser->priv->password == NULL || *chooser->priv->password == '\0')
return;
- soup_auth_authenticate (auth, username, password);
+ soup_auth_authenticate (auth, chooser->priv->username, chooser->priv->password);
}
static void
@@ -369,10 +363,14 @@ caldav_chooser_configure_session (ECaldavChooser *chooser,
}
static gboolean
-caldav_chooser_check_successful (SoupMessage *message,
+caldav_chooser_check_successful (ECaldavChooser *chooser,
+ SoupMessage *message,
GError **error)
{
GIOErrorEnum error_code;
+ GTlsCertificate *certificate = NULL;
+
+ g_return_val_if_fail (E_IS_CALDAV_CHOOSER (chooser), FALSE);
/* Loosely copied from the GVFS DAV backend. */
@@ -403,6 +401,26 @@ caldav_chooser_check_successful (SoupMessage *message,
case SOUP_STATUS_INSUFFICIENT_STORAGE:
error_code = G_IO_ERROR_NO_SPACE;
break;
+ case SOUP_STATUS_SSL_FAILED:
+ g_free (chooser->priv->certificate_pem);
+ chooser->priv->certificate_pem = NULL;
+
+ g_object_get (G_OBJECT (message),
+ "tls-certificate", &certificate,
+ "tls-errors", &chooser->priv->certificate_errors,
+ NULL);
+ if (certificate) {
+ g_object_get (certificate, "certificate-pem",
&chooser->priv->certificate_pem, NULL);
+ g_object_unref (certificate);
+ }
+
+ g_free (chooser->priv->error_text);
+ chooser->priv->error_text = g_strdup (message->reason_phrase);
+
+ g_set_error (
+ error, SOUP_HTTP_ERROR, message->status_code,
+ _("HTTP Error: %s"), message->reason_phrase);
+ return FALSE;
default:
error_code = G_IO_ERROR_FAILED;
break;
@@ -416,14 +434,15 @@ caldav_chooser_check_successful (SoupMessage *message,
}
static xmlDocPtr
-caldav_chooser_parse_xml (SoupMessage *message,
+caldav_chooser_parse_xml (ECaldavChooser *chooser,
+ SoupMessage *message,
const gchar *expected_name,
GError **error)
{
xmlDocPtr doc;
xmlNodePtr root;
- if (!caldav_chooser_check_successful (message, error))
+ if (!caldav_chooser_check_successful (chooser, message, error))
return NULL;
doc = xmlReadMemory (
@@ -828,9 +847,14 @@ caldav_chooser_collection_details_cb (SoupSession *session,
xmlDocPtr doc;
xmlXPathContextPtr xp_ctx;
xmlXPathObjectPtr xp_obj;
+ GObject *chooser_obj;
GError *error = NULL;
- doc = caldav_chooser_parse_xml (message, "multistatus", &error);
+ chooser_obj = g_async_result_get_source_object (G_ASYNC_RESULT (simple));
+
+ doc = caldav_chooser_parse_xml (E_CALDAV_CHOOSER (chooser_obj), message, "multistatus", &error);
+
+ g_clear_object (&chooser_obj);
if (error != NULL) {
g_warn_if_fail (doc == NULL);
@@ -910,7 +934,7 @@ caldav_chooser_get_collection_details (SoupSession *session,
NS_ICAL, XC ("calendar-color"),
NULL);
- e_soup_ssl_trust_connect (message, context->source, context->registry, context->cancellable);
+ e_soup_ssl_trust_connect (message, context->source);
/* This takes ownership of the message. */
soup_session_queue_message (
@@ -931,11 +955,15 @@ caldav_chooser_calendar_home_set_cb (SoupSession *session,
xmlXPathContextPtr xp_ctx;
xmlXPathObjectPtr xp_obj;
gchar *calendar_home_set;
+ GObject *chooser_obj;
GError *error = NULL;
context = g_simple_async_result_get_op_res_gpointer (simple);
+ chooser_obj = g_async_result_get_source_object (G_ASYNC_RESULT (simple));
+
+ doc = caldav_chooser_parse_xml (E_CALDAV_CHOOSER (chooser_obj), message, "multistatus", &error);
- doc = caldav_chooser_parse_xml (message, "multistatus", &error);
+ g_clear_object (&chooser_obj);
/* If we were cancelled then we're in a GCancellable::cancelled
* signal handler right now and GCancellable has its mutex locked,
@@ -1096,7 +1124,7 @@ retry_propfind:
NS_CALDAV, XC ("calendar-user-address-set"),
NULL);
- e_soup_ssl_trust_connect (message, context->source, context->registry, context->cancellable);
+ e_soup_ssl_trust_connect (message, context->source);
/* This takes ownership of the message. */
soup_session_queue_message (
@@ -1200,20 +1228,10 @@ caldav_chooser_dispose (GObject *object)
priv = E_CALDAV_CHOOSER_GET_PRIVATE (object);
- if (priv->registry != NULL) {
- g_object_unref (priv->registry);
- priv->registry = NULL;
- }
-
- if (priv->source != NULL) {
- g_object_unref (priv->source);
- priv->source = NULL;
- }
-
- if (priv->session != NULL) {
- g_object_unref (priv->session);
- priv->session = NULL;
- }
+ g_clear_object (&priv->registry);
+ g_clear_object (&priv->prompter);
+ g_clear_object (&priv->source);
+ g_clear_object (&priv->session);
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (e_caldav_chooser_parent_class)->dispose (object);
@@ -1230,7 +1248,10 @@ caldav_chooser_finalize (GObject *object)
priv->user_address_set,
(GDestroyNotify) g_free);
+ g_free (priv->username);
g_free (priv->password);
+ g_free (priv->certificate_pem);
+ g_free (priv->error_text);
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (e_caldav_chooser_parent_class)->finalize (object);
@@ -1254,6 +1275,9 @@ caldav_chooser_constructed (GObject *object)
caldav_chooser_configure_session (chooser, session);
chooser->priv->session = session;
+ chooser->priv->prompter = e_credentials_prompter_new (chooser->priv->registry);
+ e_credentials_prompter_set_auto_prompt (chooser->priv->prompter, FALSE);
+
tree_view = GTK_TREE_VIEW (object);
list_store = gtk_list_store_new (
@@ -1308,12 +1332,11 @@ caldav_chooser_try_password_cancelled_cb (GCancellable *cancellable,
}
static ESourceAuthenticationResult
-caldav_chooser_try_password_sync (ESourceAuthenticator *auth,
- const GString *password,
+caldav_chooser_try_password_sync (ECaldavChooser *chooser,
+ const ENamedParameters *credentials,
GCancellable *cancellable,
GError **error)
{
- ECaldavChooser *chooser;
ESourceAuthenticationResult result;
SoupMessage *message;
SoupSession *session;
@@ -1324,22 +1347,35 @@ caldav_chooser_try_password_sync (ESourceAuthenticator *auth,
gulong cancel_id = 0;
GError *local_error = NULL;
- chooser = E_CALDAV_CHOOSER (auth);
+ g_return_val_if_fail (E_IS_CALDAV_CHOOSER (chooser), E_SOURCE_AUTHENTICATION_ERROR);
+ g_return_val_if_fail (credentials != NULL, E_SOURCE_AUTHENTICATION_ERROR);
+
+ source = e_caldav_chooser_get_source (chooser);
+ extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
+ extension = e_source_get_extension (source, extension_name);
/* Cache the password for later use in our
* SoupSession::authenticate signal handler. */
+ g_free (chooser->priv->username);
+ chooser->priv->username = g_strdup (e_named_parameters_get (credentials,
E_SOURCE_CREDENTIAL_USERNAME));
+
g_free (chooser->priv->password);
- chooser->priv->password = g_strdup (password->str);
+ chooser->priv->password = g_strdup (e_named_parameters_get (credentials,
E_SOURCE_CREDENTIAL_PASSWORD));
+
+ if (e_named_parameters_get (credentials, E_SOURCE_CREDENTIAL_SSL_TRUST))
+ e_source_webdav_set_ssl_trust (extension, e_named_parameters_get (credentials,
E_SOURCE_CREDENTIAL_SSL_TRUST));
+
+ g_free (chooser->priv->certificate_pem);
+ chooser->priv->certificate_pem = NULL;
+ chooser->priv->certificate_errors = 0;
+ g_free (chooser->priv->error_text);
+ chooser->priv->error_text = NULL;
/* Create our own SoupSession so we
* can try the password synchronously. */
session = soup_session_new ();
caldav_chooser_configure_session (chooser, session);
- source = e_caldav_chooser_get_source (chooser);
- extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
- extension = e_source_get_extension (source, extension_name);
-
soup_uri = e_source_webdav_dup_soup_uri (extension);
g_return_val_if_fail (soup_uri != NULL, E_SOURCE_AUTHENTICATION_ERROR);
@@ -1357,19 +1393,22 @@ caldav_chooser_try_password_sync (ESourceAuthenticator *auth,
g_object_ref (session),
(GDestroyNotify) g_object_unref);
- e_soup_ssl_trust_connect (message, source, chooser->priv->registry, cancellable);
+ e_soup_ssl_trust_connect (message, source);
soup_session_send_message (session, message);
if (cancel_id > 0)
g_cancellable_disconnect (cancellable, cancel_id);
- if (caldav_chooser_check_successful (message, &local_error)) {
+ if (caldav_chooser_check_successful (chooser, message, &local_error)) {
result = E_SOURCE_AUTHENTICATION_ACCEPTED;
} else if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED)) {
result = E_SOURCE_AUTHENTICATION_REJECTED;
- g_clear_error (&local_error);
+ /* Return also the error here. */
+
+ } else if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED)) {
+ result = E_SOURCE_AUTHENTICATION_ERROR_SSL_FAILED;
} else {
result = E_SOURCE_AUTHENTICATION_ERROR;
@@ -1441,15 +1480,10 @@ e_caldav_chooser_class_finalize (ECaldavChooserClass *class)
}
static void
-e_caldav_chooser_authenticator_init (ESourceAuthenticatorInterface *iface)
-{
- iface->try_password_sync = caldav_chooser_try_password_sync;
-}
-
-static void
e_caldav_chooser_init (ECaldavChooser *chooser)
{
chooser->priv = E_CALDAV_CHOOSER_GET_PRIVATE (chooser);
+ chooser->priv->first_auth_request = TRUE;
}
void
@@ -1471,7 +1505,8 @@ e_caldav_chooser_new (ESourceRegistry *registry,
return g_object_new (
E_TYPE_CALDAV_CHOOSER,
- "registry", registry, "source", source,
+ "registry", registry,
+ "source", source,
"source-type", source_type, NULL);
}
@@ -1483,6 +1518,14 @@ e_caldav_chooser_get_registry (ECaldavChooser *chooser)
return chooser->priv->registry;
}
+ECredentialsPrompter *
+e_caldav_chooser_get_prompter (ECaldavChooser *chooser)
+{
+ g_return_val_if_fail (E_IS_CALDAV_CHOOSER (chooser), NULL);
+
+ return chooser->priv->prompter;
+}
+
ESource *
e_caldav_chooser_get_source (ECaldavChooser *chooser)
{
@@ -1545,7 +1588,7 @@ e_caldav_chooser_populate (ECaldavChooser *chooser,
NS_WEBDAV, XC ("principal-URL"),
NULL);
- e_soup_ssl_trust_connect (message, source, context->registry, context->cancellable);
+ e_soup_ssl_trust_connect (message, source);
/* This takes ownership of the message. */
soup_session_queue_message (
@@ -1675,3 +1718,131 @@ e_caldav_chooser_apply_selected (ECaldavChooser *chooser)
return TRUE;
}
+void
+e_caldav_chooser_run_trust_prompt (ECaldavChooser *chooser,
+ GtkWindow *parent,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (E_IS_CALDAV_CHOOSER (chooser));
+
+ e_trust_prompt_run_for_source (parent,
+ chooser->priv->source,
+ chooser->priv->certificate_pem,
+ chooser->priv->certificate_errors,
+ chooser->priv->error_text,
+ FALSE,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/* Free returned pointer with g_error_free() or g_clear_error() */
+GError *
+e_caldav_chooser_new_ssl_trust_error (ECaldavChooser *chooser)
+{
+ g_return_val_if_fail (E_IS_CALDAV_CHOOSER (chooser), NULL);
+ g_return_val_if_fail (chooser->priv->error_text != NULL, NULL);
+
+ return g_error_new_literal (SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED, chooser->priv->error_text);
+}
+
+/* The callback has an ECredentialsPrompter as the source_object. */
+void
+e_caldav_chooser_run_credentials_prompt (ECaldavChooser *chooser,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (E_IS_CALDAV_CHOOSER (chooser));
+ g_return_if_fail (callback != NULL);
+
+ e_credentials_prompter_prompt (chooser->priv->prompter, chooser->priv->source,
chooser->priv->error_text,
+ chooser->priv->first_auth_request ?
E_CREDENTIALS_PROMPTER_PROMPT_FLAG_ALLOW_STORED_CREDENTIALS : 0,
+ callback, user_data);
+
+ chooser->priv->first_auth_request = FALSE;
+}
+
+gboolean
+e_caldav_chooser_run_credentials_prompt_finish (ECaldavChooser *chooser,
+ GAsyncResult *result,
+ ENamedParameters **out_credentials,
+ GError **error)
+{
+ ESource *source = NULL;
+
+ g_return_val_if_fail (E_IS_CALDAV_CHOOSER (chooser), FALSE);
+ g_return_val_if_fail (out_credentials != NULL, FALSE);
+
+ if (!e_credentials_prompter_prompt_finish (chooser->priv->prompter, result,
+ &source, out_credentials, error))
+ return FALSE;
+
+ g_return_val_if_fail (source == chooser->priv->source, FALSE);
+
+ return TRUE;
+}
+
+static void
+e_caldav_chooser_authenticate_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ ECaldavChooser *chooser = source_object;
+ const ENamedParameters *credentials = task_data;
+ gboolean success;
+ GError *local_error = NULL;
+
+ if (caldav_chooser_try_password_sync (chooser, credentials, cancellable, &local_error)
+ != E_SOURCE_AUTHENTICATION_ACCEPTED && !local_error) {
+ local_error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED, _("Unknown error"));
+ }
+
+ if (local_error != NULL) {
+ g_task_return_error (task, local_error);
+ } else {
+ g_task_return_boolean (task, success);
+ }
+}
+
+void
+e_caldav_chooser_authenticate (ECaldavChooser *chooser,
+ const ENamedParameters *credentials,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ ENamedParameters *credentials_copy;
+ GTask *task;
+
+ g_return_if_fail (E_IS_CALDAV_CHOOSER (chooser));
+ g_return_if_fail (credentials != NULL);
+ g_return_if_fail (callback != NULL);
+
+ credentials_copy = e_named_parameters_new_clone (credentials);
+
+ task = g_task_new (chooser, cancellable, callback, user_data);
+ g_task_set_source_tag (task, e_caldav_chooser_authenticate);
+ g_task_set_task_data (task, credentials_copy, (GDestroyNotify) e_named_parameters_free);
+
+ g_task_run_in_thread (task, e_caldav_chooser_authenticate_thread);
+
+ g_object_unref (task);
+}
+
+gboolean
+e_caldav_chooser_authenticate_finish (ECaldavChooser *chooser,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (E_IS_CALDAV_CHOOSER (chooser), FALSE);
+ g_return_val_if_fail (g_task_is_valid (result, chooser), FALSE);
+
+ g_return_val_if_fail (
+ g_async_result_is_tagged (
+ result, e_caldav_chooser_authenticate), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
diff --git a/modules/cal-config-caldav/e-caldav-chooser.h b/modules/cal-config-caldav/e-caldav-chooser.h
index 15d2d95..246b25a 100644
--- a/modules/cal-config-caldav/e-caldav-chooser.h
+++ b/modules/cal-config-caldav/e-caldav-chooser.h
@@ -20,6 +20,7 @@
#include <gtk/gtk.h>
#include <libecal/libecal.h>
+#include <libedataserverui/libedataserverui.h>
/* Standard GObject macros */
#define E_TYPE_CALDAV_CHOOSER \
@@ -62,6 +63,8 @@ GtkWidget * e_caldav_chooser_new (ESourceRegistry *registry,
ECalClientSourceType source_type);
ESourceRegistry *
e_caldav_chooser_get_registry (ECaldavChooser *chooser);
+ECredentialsPrompter *
+ e_caldav_chooser_get_prompter (ECaldavChooser *chooser);
ESource * e_caldav_chooser_get_source (ECaldavChooser *chooser);
ECalClientSourceType
e_caldav_chooser_get_source_type
@@ -76,4 +79,31 @@ gboolean e_caldav_chooser_populate_finish
GError **error);
gboolean e_caldav_chooser_apply_selected (ECaldavChooser *chooser);
+void e_caldav_chooser_run_trust_prompt
+ (ECaldavChooser *chooser,
+ GtkWindow *parent,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GError * e_caldav_chooser_new_ssl_trust_error
+ (ECaldavChooser *chooser);
+void e_caldav_chooser_run_credentials_prompt
+ (ECaldavChooser *chooser,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_caldav_chooser_run_credentials_prompt_finish
+ (ECaldavChooser *chooser,
+ GAsyncResult *result,
+ ENamedParameters **out_credentials,
+ GError **error);
+void e_caldav_chooser_authenticate (ECaldavChooser *chooser,
+ const ENamedParameters *credentials,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_caldav_chooser_authenticate_finish
+ (ECaldavChooser *chooser,
+ GAsyncResult *result,
+ GError **error);
+
#endif /* E_CALDAV_CHOOSER_H */
diff --git a/modules/cal-config-caldav/evolution-cal-config-caldav.c
b/modules/cal-config-caldav/evolution-cal-config-caldav.c
index 5cd165e..9de01a0 100644
--- a/modules/cal-config-caldav/evolution-cal-config-caldav.c
+++ b/modules/cal-config-caldav/evolution-cal-config-caldav.c
@@ -79,6 +79,13 @@ cal_config_caldav_context_free (Context *context)
g_slice_free (Context, context);
}
+static GtkWindow *
+caldav_config_get_dialog_parent_cb (ECredentialsPrompter *prompter,
+ GtkWindow *dialog)
+{
+ return dialog;
+}
+
static void
cal_config_caldav_run_dialog (GtkButton *button,
Context *context)
@@ -86,9 +93,11 @@ cal_config_caldav_run_dialog (GtkButton *button,
ESourceConfig *config;
ESourceRegistry *registry;
ECalClientSourceType source_type;
+ ECredentialsPrompter *prompter;
GtkWidget *dialog;
GtkWidget *widget;
gpointer parent;
+ gulong handler_id;
config = e_source_config_backend_get_config (context->backend);
registry = e_source_config_get_registry (config);
@@ -111,8 +120,15 @@ cal_config_caldav_run_dialog (GtkButton *button,
dialog, "icon-name",
G_BINDING_SYNC_CREATE);
+ prompter = e_caldav_chooser_get_prompter (E_CALDAV_CHOOSER (widget));
+
+ handler_id = g_signal_connect (prompter, "get-dialog-parent",
+ G_CALLBACK (caldav_config_get_dialog_parent_cb), dialog);
+
gtk_dialog_run (GTK_DIALOG (dialog));
+ g_signal_handler_disconnect (prompter, handler_id);
+
gtk_widget_destroy (dialog);
}
diff --git a/modules/calendar/e-cal-attachment-handler.c b/modules/calendar/e-cal-attachment-handler.c
index 81e396b..ef28ddd 100644
--- a/modules/calendar/e-cal-attachment-handler.c
+++ b/modules/calendar/e-cal-attachment-handler.c
@@ -155,7 +155,7 @@ import_component_thread (EAlertSinkThreadJobData *job_data,
g_return_if_fail (icd != NULL);
- e_client = e_util_open_client_sync (job_data, e_shell_get_client_cache (icd->shell),
icd->extension_name, icd->source, cancellable, error);
+ e_client = e_util_open_client_sync (job_data, e_shell_get_client_cache (icd->shell),
icd->extension_name, icd->source, 30, cancellable, error);
if (e_client)
client = E_CAL_CLIENT (e_client);
diff --git a/modules/calendar/e-cal-base-shell-backend.c b/modules/calendar/e-cal-base-shell-backend.c
index 15a9f35..a67eb87 100644
--- a/modules/calendar/e-cal-base-shell-backend.c
+++ b/modules/calendar/e-cal-base-shell-backend.c
@@ -365,7 +365,7 @@ cal_base_shell_backend_handle_uri_thread (EAlertSinkThreadJobData *job_data,
client_cache = e_shell_get_client_cache (shell);
- client = e_client_cache_get_client_sync (client_cache, source, extension_name, cancellable,
&local_error);
+ client = e_client_cache_get_client_sync (client_cache, source, extension_name, 30,
cancellable, &local_error);
if (client) {
hud->cal_client = E_CAL_CLIENT (client);
diff --git a/modules/calendar/e-cal-base-shell-sidebar.c b/modules/calendar/e-cal-base-shell-sidebar.c
index f51cab0..83fe540 100644
--- a/modules/calendar/e-cal-base-shell-sidebar.c
+++ b/modules/calendar/e-cal-base-shell-sidebar.c
@@ -324,7 +324,7 @@ e_cal_base_shell_sidebar_open_client_thread (EAlertSinkThreadJobData *job_data,
selector = E_CLIENT_SELECTOR (e_cal_base_shell_sidebar_get_selector (data->sidebar));
data->client = e_client_selector_get_client_sync (
- selector, data->source, TRUE, cancellable, &local_error);
+ selector, data->source, TRUE, (guint32) -1, cancellable, &local_error);
e_util_propagate_open_source_job_error (job_data, data->extension_name, local_error, error);
}
@@ -469,12 +469,12 @@ cal_base_shell_sidebar_transfer_thread (EAlertSinkThreadJobData *job_data,
g_return_if_fail (titd->icalcomp != NULL);
source_client = e_client_selector_get_client_sync (
- titd->selector, titd->source, FALSE, cancellable, error);
+ titd->selector, titd->source, FALSE, 30, cancellable, error);
if (!source_client)
return;
destination_client = e_client_selector_get_client_sync (
- titd->selector, titd->destination, FALSE, cancellable, error);
+ titd->selector, titd->destination, FALSE, 30, cancellable, error);
if (!destination_client) {
g_object_unref (source_client);
return;
diff --git a/modules/calendar/e-cal-base-shell-view.c b/modules/calendar/e-cal-base-shell-view.c
index dd6957d..a0eb9ca 100644
--- a/modules/calendar/e-cal-base-shell-view.c
+++ b/modules/calendar/e-cal-base-shell-view.c
@@ -133,9 +133,9 @@ e_cal_base_shell_view_get_source_type (EShellView *shell_view)
}
static void
-cal_base_shell_view_allow_auth_prompt_and_refresh_done_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
+cal_base_shell_view_refresh_done_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
{
EClient *client;
EActivity *activity;
@@ -152,7 +152,7 @@ cal_base_shell_view_allow_auth_prompt_and_refresh_done_cb (GObject *source_objec
alert_sink = e_activity_get_alert_sink (activity);
display_name = e_source_get_display_name (source);
- e_util_allow_auth_prompt_and_refresh_client_finish (client, result, &local_error);
+ e_client_refresh_finish (client, result, &local_error);
if (e_activity_handle_cancellation (activity, local_error)) {
g_error_free (local_error);
@@ -191,6 +191,7 @@ e_cal_base_shell_view_allow_auth_prompt_and_refresh (EShellView *shell_view,
{
EShellBackend *shell_backend;
EShellContent *shell_content;
+ EShell *shell;
EActivity *activity;
EAlertSink *alert_sink;
GCancellable *cancellable;
@@ -200,6 +201,7 @@ e_cal_base_shell_view_allow_auth_prompt_and_refresh (EShellView *shell_view,
shell_backend = e_shell_view_get_shell_backend (shell_view);
shell_content = e_shell_view_get_shell_content (shell_view);
+ shell = e_shell_backend_get_shell (shell_backend);
alert_sink = E_ALERT_SINK (shell_content);
activity = e_activity_new ();
@@ -208,8 +210,10 @@ e_cal_base_shell_view_allow_auth_prompt_and_refresh (EShellView *shell_view,
e_activity_set_alert_sink (activity, alert_sink);
e_activity_set_cancellable (activity, cancellable);
- e_util_allow_auth_prompt_and_refresh_client (client, cancellable,
- cal_base_shell_view_allow_auth_prompt_and_refresh_done_cb, activity);
+ e_shell_allow_auth_prompt_for (shell, e_client_get_source (client));
+
+ e_client_refresh (client, cancellable,
+ cal_base_shell_view_refresh_done_cb, activity);
e_shell_backend_add_activity (shell_backend, activity);
diff --git a/modules/contact-photos/e-contact-photo-source.c b/modules/contact-photos/e-contact-photo-source.c
index 910bc12..95c0911 100644
--- a/modules/contact-photos/e-contact-photo-source.c
+++ b/modules/contact-photos/e-contact-photo-source.c
@@ -326,7 +326,7 @@ contact_photo_source_get_photo (EPhotoSource *photo_source,
* a main loop so signal emissions can work. */
e_client_cache_get_client (
client_cache, source,
- E_SOURCE_EXTENSION_ADDRESS_BOOK,
+ E_SOURCE_EXTENSION_ADDRESS_BOOK, (guint32) -1,
cancellable,
contact_photo_source_get_client_cb,
g_object_ref (simple));
diff --git a/modules/itip-formatter/itip-view.c b/modules/itip-formatter/itip-view.c
index 8d96a4c..f2136a1 100644
--- a/modules/itip-formatter/itip-view.c
+++ b/modules/itip-formatter/itip-view.c
@@ -3515,7 +3515,7 @@ start_calendar_server (EMailPartItip *pitip,
client_cache = itip_view_get_client_cache (view);
e_client_cache_get_client (
- client_cache, source, extension_name,
+ client_cache, source, extension_name, 30,
pitip->cancellable, func, data);
}
@@ -3950,13 +3950,6 @@ find_cal_opened_cb (GObject *source_object,
return;
}
- /* Do not process read-only calendars */
- if (e_client_is_readonly (client)) {
- g_object_unref (client);
- decrease_find_data (fd);
- return;
- }
-
cal_client = E_CAL_CLIENT (client);
source = e_client_get_source (client);
@@ -3971,6 +3964,13 @@ find_cal_opened_cb (GObject *source_object,
e_source_conflict_search_get_include_me (extension);
}
+ /* Do not process read-only calendars */
+ if (e_client_is_readonly (E_CLIENT (cal_client))) {
+ g_object_unref (cal_client);
+ decrease_find_data (fd);
+ return;
+ }
+
/* Check for conflicts */
/* If the query fails, we'll just ignore it */
/* FIXME What happens for recurring conflicts? */
@@ -3991,6 +3991,7 @@ find_cal_opened_cb (GObject *source_object,
}
decrease_find_data (fd);
+ g_clear_object (&cal_client);
}
static void
diff --git a/modules/mail/e-mail-shell-view-actions.c b/modules/mail/e-mail-shell-view-actions.c
index b1be490..40c3664 100644
--- a/modules/mail/e-mail-shell-view-actions.c
+++ b/modules/mail/e-mail-shell-view-actions.c
@@ -156,54 +156,6 @@ account_refresh_folder_info_received_cb (GObject *source,
g_clear_object (&activity);
}
-typedef struct _RefreshData
-{
- EActivity *activity;
- CamelStore *store;
-} RefreshData;
-
-static void
-account_refresh_allow_auth_prompt_done_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- RefreshData *data = user_data;
- EActivity *activity;
- CamelStore *store;
- GError *local_error = NULL;
-
- g_return_if_fail (data != NULL);
-
- activity = data->activity;
- store = data->store;
-
- g_free (data);
-
- e_source_allow_auth_prompt_finish (E_SOURCE (source_object), result, &local_error);
-
- if (e_activity_handle_cancellation (activity, local_error)) {
- g_error_free (local_error);
- g_clear_object (&activity);
- } else {
- GCancellable *cancellable;
-
- if (local_error) {
- g_debug ("%s: Failed with: %s", G_STRFUNC, local_error->message);
- g_clear_error (&local_error);
- }
-
- cancellable = e_activity_get_cancellable (activity);
-
- camel_store_get_folder_info (
- store, NULL,
- CAMEL_STORE_FOLDER_INFO_RECURSIVE,
- G_PRIORITY_DEFAULT, cancellable,
- account_refresh_folder_info_received_cb, activity);
- }
-
- g_object_unref (store);
-}
-
static void
action_mail_account_refresh_cb (GtkAction *action,
EMailShellView *mail_shell_view)
@@ -218,7 +170,6 @@ action_mail_account_refresh_cb (GtkAction *action,
EShell *shell;
CamelStore *store;
GCancellable *cancellable;
- RefreshData *data;
mail_shell_content = mail_shell_view->priv->mail_shell_content;
mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar;
@@ -231,18 +182,21 @@ action_mail_account_refresh_cb (GtkAction *action,
activity = e_mail_reader_new_activity (E_MAIL_READER (mail_view));
cancellable = e_activity_get_cancellable (activity);
- data = g_new0 (RefreshData, 1);
- data->activity = activity;
- data->store = store;
-
shell = e_shell_backend_get_shell (e_shell_view_get_shell_backend (E_SHELL_VIEW (mail_shell_view)));
registry = e_shell_get_registry (shell);
source = e_source_registry_ref_source (registry, camel_service_get_uid (CAMEL_SERVICE (store)));
g_return_if_fail (source != NULL);
- e_source_allow_auth_prompt (source, cancellable, account_refresh_allow_auth_prompt_done_cb, data);
+ e_shell_allow_auth_prompt_for (shell, source);
+
+ camel_store_get_folder_info (
+ store, NULL,
+ CAMEL_STORE_FOLDER_INFO_RECURSIVE,
+ G_PRIORITY_DEFAULT, cancellable,
+ account_refresh_folder_info_received_cb, activity);
g_clear_object (&source);
+ g_clear_object (&store);
}
static void
diff --git a/modules/vcard-inline/e-mail-part-vcard.c b/modules/vcard-inline/e-mail-part-vcard.c
index 4768295..f5729a6 100644
--- a/modules/vcard-inline/e-mail-part-vcard.c
+++ b/modules/vcard-inline/e-mail-part-vcard.c
@@ -147,7 +147,7 @@ save_vcard_cb (GDBusConnection *connection,
(GCopyFunc) g_object_ref, NULL);
e_book_client_connect (
- source, NULL, client_connect_cb, contact_list);
+ source, 30, NULL, client_connect_cb, contact_list);
}
static void
diff --git a/plugins/bbdb/bbdb.c b/plugins/bbdb/bbdb.c
index d5b896c..6e7582c 100644
--- a/plugins/bbdb/bbdb.c
+++ b/plugins/bbdb/bbdb.c
@@ -363,7 +363,7 @@ bbdb_do_it (EBookClient *client,
client_addressbook = (EBookClient *) e_client_cache_get_client_sync (
client_cache, (ESource *) aux_addressbooks->data,
- E_SOURCE_EXTENSION_ADDRESS_BOOK,
+ E_SOURCE_EXTENSION_ADDRESS_BOOK, 30,
NULL, &error);
if (error != NULL) {
@@ -505,7 +505,7 @@ bbdb_create_book_client (gint type,
client = e_client_cache_get_client_sync (
client_cache, source,
- E_SOURCE_EXTENSION_ADDRESS_BOOK,
+ E_SOURCE_EXTENSION_ADDRESS_BOOK, 30,
cancellable, error);
g_object_unref (source);
diff --git a/plugins/mail-to-task/mail-to-task.c b/plugins/mail-to-task/mail-to-task.c
index ceaa01f..a8c9f62 100644
--- a/plugins/mail-to-task/mail-to-task.c
+++ b/plugins/mail-to-task/mail-to-task.c
@@ -843,7 +843,7 @@ do_mail_to_event (AsyncData *data)
GError *error = NULL;
client = e_client_cache_get_client_sync (data->client_cache,
- data->source, data->extension_name, NULL, &error);
+ data->source, data->extension_name, 30, NULL, &error);
/* Sanity check. */
g_return_val_if_fail (
diff --git a/plugins/publish-calendar/publish-format-fb.c b/plugins/publish-calendar/publish-format-fb.c
index 0a064a9..a0cabdd 100644
--- a/plugins/publish-calendar/publish-format-fb.c
+++ b/plugins/publish-calendar/publish-format-fb.c
@@ -91,7 +91,7 @@ write_calendar (const gchar *uid,
EClientCache *client_cache;
client_cache = e_shell_get_client_cache (shell);
- client = e_client_cache_get_client_sync (client_cache, source, E_SOURCE_EXTENSION_CALENDAR,
NULL, error);
+ client = e_client_cache_get_client_sync (client_cache, source, E_SOURCE_EXTENSION_CALENDAR,
30, NULL, error);
g_object_unref (source);
} else {
diff --git a/plugins/publish-calendar/publish-format-ical.c b/plugins/publish-calendar/publish-format-ical.c
index 06215a6..3f06cdb 100644
--- a/plugins/publish-calendar/publish-format-ical.c
+++ b/plugins/publish-calendar/publish-format-ical.c
@@ -94,7 +94,7 @@ write_calendar (const gchar *uid,
EClientCache *client_cache;
client_cache = e_shell_get_client_cache (shell);
- client = e_client_cache_get_client_sync (client_cache, source, E_SOURCE_EXTENSION_CALENDAR,
NULL, error);
+ client = e_client_cache_get_client_sync (client_cache, source, E_SOURCE_EXTENSION_CALENDAR,
30, NULL, error);
g_object_unref (source);
} else {
diff --git a/plugins/save-calendar/csv-format.c b/plugins/save-calendar/csv-format.c
index 498f5e5..1a1b163 100644
--- a/plugins/save-calendar/csv-format.c
+++ b/plugins/save-calendar/csv-format.c
@@ -332,7 +332,7 @@ do_save_calendar_csv (FormatHandler *handler,
/* open source client */
primary_source = e_source_selector_ref_primary_selection (selector);
source_client = e_client_cache_get_client_sync (client_cache,
- primary_source, e_source_selector_get_extension_name (selector), NULL, &error);
+ primary_source, e_source_selector_get_extension_name (selector), 30, NULL, &error);
g_object_unref (primary_source);
/* Sanity check. */
diff --git a/plugins/save-calendar/ical-format.c b/plugins/save-calendar/ical-format.c
index fb79479..8e3d64d 100644
--- a/plugins/save-calendar/ical-format.c
+++ b/plugins/save-calendar/ical-format.c
@@ -104,7 +104,7 @@ do_save_calendar_ical (FormatHandler *handler,
/* open source client */
primary_source = e_source_selector_ref_primary_selection (selector);
source_client = e_client_cache_get_client_sync (client_cache,
- primary_source, e_source_selector_get_extension_name (selector), NULL, &error);
+ primary_source, e_source_selector_get_extension_name (selector), 30, NULL, &error);
g_object_unref (primary_source);
/* Sanity check. */
diff --git a/plugins/save-calendar/rdf-format.c b/plugins/save-calendar/rdf-format.c
index 947c4ff..3365b48 100644
--- a/plugins/save-calendar/rdf-format.c
+++ b/plugins/save-calendar/rdf-format.c
@@ -199,7 +199,7 @@ do_save_calendar_rdf (FormatHandler *handler,
/* open source client */
primary_source = e_source_selector_ref_primary_selection (selector);
source_client = e_client_cache_get_client_sync (client_cache,
- primary_source, e_source_selector_get_extension_name (selector), NULL, &error);
+ primary_source, e_source_selector_get_extension_name (selector), 30, NULL, &error);
g_object_unref (primary_source);
/* Sanity check. */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index cd37de0..4c22ce3 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -314,7 +314,6 @@ e-util/widgets.error.xml
evolution.appdata.xml.in
libemail-engine/camel-null-store.c
libemail-engine/camel-sasl-xoauth2.c
-libemail-engine/e-mail-authenticator.c
libemail-engine/e-mail-folder-utils.c
libemail-engine/e-mail-session.c
libemail-engine/e-mail-session-utils.c
diff --git a/shell/e-shell-window.c b/shell/e-shell-window.c
index 1b445d3..4b6b6af 100644
--- a/shell/e-shell-window.c
+++ b/shell/e-shell-window.c
@@ -1659,7 +1659,7 @@ shell_window_connect_client_thread (EAlertSinkThreadJobData *job_data,
client_cache = e_shell_get_client_cache (shell);
cc_data->client = e_client_cache_get_client_sync (client_cache,
- cc_data->source, cc_data->extension_name, cancellable, &local_error);
+ cc_data->source, cc_data->extension_name, 30, cancellable, &local_error);
e_util_propagate_open_source_job_error (job_data, cc_data->extension_name, local_error, error);
}
diff --git a/shell/e-shell.c b/shell/e-shell.c
index ee99474..ed90be6 100644
--- a/shell/e-shell.c
+++ b/shell/e-shell.c
@@ -51,8 +51,10 @@
struct _EShellPrivate {
GQueue alerts;
ESourceRegistry *registry;
+ ECredentialsPrompter *credentials_prompter;
EClientCache *client_cache;
GtkWidget *preferences_window;
+ GCancellable *cancellable;
/* Shell Backends */
GList *loaded_backends; /* not referenced */
@@ -70,6 +72,9 @@ struct _EShellPrivate {
guint prepare_quit_timeout_id;
gulong backend_died_handler_id;
+ gulong allow_auth_prompt_handler_id;
+ gulong get_dialog_parent_handler_id;
+ gulong credentials_required_handler_id;
guint auto_reconnect : 1;
guint express_mode : 1;
@@ -90,7 +95,8 @@ enum {
PROP_MODULE_DIRECTORY,
PROP_NETWORK_AVAILABLE,
PROP_ONLINE,
- PROP_REGISTRY
+ PROP_REGISTRY,
+ PROP_CREDENTIALS_PROMPTER
};
enum {
@@ -598,6 +604,422 @@ shell_backend_died_cb (EClientCache *client_cache,
}
static void
+shell_allow_auth_prompt_cb (EClientCache *client_cache,
+ ESource *source,
+ EShell *shell)
+{
+ g_return_if_fail (E_IS_SOURCE (source));
+ g_return_if_fail (E_IS_SHELL (shell));
+
+ e_shell_allow_auth_prompt_for (shell, source);
+}
+
+static void
+shell_source_connection_status_notify_cb (ESource *source,
+ GParamSpec *param,
+ EAlert *alert)
+{
+ g_return_if_fail (E_IS_ALERT (alert));
+
+ if (e_source_get_connection_status (source) == E_SOURCE_CONNECTION_STATUS_DISCONNECTED ||
+ e_source_get_connection_status (source) == E_SOURCE_CONNECTION_STATUS_CONNECTING ||
+ e_source_get_connection_status (source) == E_SOURCE_CONNECTION_STATUS_CONNECTED)
+ e_alert_response (alert, GTK_RESPONSE_CLOSE);
+}
+
+static void
+shell_submit_source_connection_alert (EShell *shell,
+ ESource *source,
+ EAlert *alert)
+{
+ g_return_if_fail (E_IS_SHELL (shell));
+ g_return_if_fail (E_IS_SOURCE (source));
+ g_return_if_fail (E_IS_ALERT (alert));
+
+ e_signal_connect_notify_object (source, "notify::connection-status",
+ G_CALLBACK (shell_source_connection_status_notify_cb), alert, 0);
+
+ e_shell_submit_alert (shell, alert);
+}
+
+static void
+shell_source_invoke_authenticate_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ESource *source;
+ EShell *shell = user_data;
+ GError *error = NULL;
+
+ g_return_if_fail (E_IS_SOURCE (source_object));
+
+ source = E_SOURCE (source_object);
+
+ if (!e_source_invoke_authenticate_finish (source, result, &error)) {
+ /* Can be cancelled only if the shell is disposing/disposed */
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ EAlert *alert;
+
+ g_return_if_fail (E_IS_SHELL (shell));
+
+ alert = e_alert_new ("shell:source-invoke-authenticate-failed",
+ e_source_get_display_name (source),
+ error->message,
+ NULL);
+ e_shell_submit_alert (shell, alert);
+ g_object_unref (alert);
+ }
+
+ g_clear_error (&error);
+ }
+}
+
+#define SOURCE_ALERT_KEY_SOURCE "source-alert-key-source"
+#define SOURCE_ALERT_KEY_CERTIFICATE_PEM "source-alert-key-certificate-pem"
+#define SOURCE_ALERT_KEY_CERTIFICATE_ERRORS "source-alert-key-certificate-errors"
+#define SOURCE_ALERT_KEY_ERROR_TEXT "source-alert-key-error-text"
+
+static void
+shell_trust_prompt_done_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ESource *source;
+ EShell *shell = user_data;
+ ETrustPromptResponse response = E_TRUST_PROMPT_RESPONSE_UNKNOWN;
+ ENamedParameters *credentials;
+ GError *error = NULL;
+
+ g_return_if_fail (E_IS_SOURCE (source_object));
+
+ source = E_SOURCE (source_object);
+
+ if (!e_trust_prompt_run_for_source_finish (source, result, &response, &error)) {
+ /* Can be cancelled only if the shell is disposing/disposed */
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ EAlert *alert;
+
+ g_return_if_fail (E_IS_SHELL (shell));
+
+ alert = e_alert_new ("shell:source-trust-prompt-failed",
+ e_source_get_display_name (source),
+ error->message,
+ NULL);
+ e_shell_submit_alert (shell, alert);
+ g_object_unref (alert);
+ }
+
+ g_clear_error (&error);
+ return;
+ }
+
+ g_return_if_fail (E_IS_SHELL (shell));
+
+ if (response == E_TRUST_PROMPT_RESPONSE_UNKNOWN) {
+ e_credentials_prompter_set_auto_prompt_disabled_for (shell->priv->credentials_prompter,
source, TRUE);
+ return;
+ }
+
+ /* If a credentials prompt is required, then it'll be shown immediately. */
+ e_credentials_prompter_set_auto_prompt_disabled_for (shell->priv->credentials_prompter, source,
FALSE);
+
+ credentials = e_named_parameters_new ();
+
+ e_source_invoke_authenticate (source, credentials, shell->priv->cancellable,
+ shell_source_invoke_authenticate_cb, shell);
+
+ e_named_parameters_free (credentials);
+}
+
+static void
+shell_credentials_prompt_done_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ EShell *shell = user_data;
+ ESource *source = NULL;
+ ENamedParameters *credentials = NULL;
+ GError *error = NULL;
+
+ g_return_if_fail (E_IS_SHELL (shell));
+
+ if (e_credentials_prompter_prompt_finish (E_CREDENTIALS_PROMPTER (source_object), result, &source,
&credentials, &error)) {
+ e_source_invoke_authenticate (source, credentials, shell->priv->cancellable,
+ shell_source_invoke_authenticate_cb, shell);
+ } else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ EAlert *alert;
+
+ g_return_if_fail (E_IS_SHELL (shell));
+
+ alert = e_alert_new ("shell:source-credentials-prompt-failed",
+ e_source_get_display_name (source),
+ error->message,
+ NULL);
+ e_shell_submit_alert (shell, alert);
+ g_object_unref (alert);
+ }
+
+ e_named_parameters_free (credentials);
+ g_clear_object (&source);
+ g_clear_object (&shell);
+ g_clear_error (&error);
+}
+
+static void
+shell_connection_error_alert_response_cb (EAlert *alert,
+ gint response_id,
+ EShell *shell)
+{
+ ESource *source;
+
+ g_return_if_fail (E_IS_SHELL (shell));
+
+ if (response_id != GTK_RESPONSE_APPLY)
+ return;
+
+ source = g_object_get_data (G_OBJECT (alert), SOURCE_ALERT_KEY_SOURCE);
+ g_return_if_fail (E_IS_SOURCE (source));
+
+ e_credentials_prompter_set_auto_prompt_disabled_for (shell->priv->credentials_prompter, source,
FALSE);
+
+ e_credentials_prompter_prompt (shell->priv->credentials_prompter, source, NULL,
+ E_CREDENTIALS_PROMPTER_PROMPT_FLAG_ALLOW_STORED_CREDENTIALS,
+ shell_credentials_prompt_done_cb, g_object_ref (shell));
+}
+
+static void
+shell_connect_trust_error_alert_response_cb (EAlert *alert,
+ gint response_id,
+ EShell *shell)
+{
+ ESource *source;
+ const gchar *certificate_pem;
+ GTlsCertificateFlags certificate_errors;
+ const gchar *error_text;
+
+ g_return_if_fail (E_IS_SHELL (shell));
+
+ if (response_id != GTK_RESPONSE_APPLY)
+ return;
+
+ source = g_object_get_data (G_OBJECT (alert), SOURCE_ALERT_KEY_SOURCE);
+ certificate_pem = g_object_get_data (G_OBJECT (alert), SOURCE_ALERT_KEY_CERTIFICATE_PEM);
+ certificate_errors = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (alert),
SOURCE_ALERT_KEY_CERTIFICATE_ERRORS));
+ error_text = g_object_get_data (G_OBJECT (alert), SOURCE_ALERT_KEY_ERROR_TEXT);
+
+ g_return_if_fail (E_IS_SOURCE (source));
+
+ g_object_set_data_full (G_OBJECT (source), SOURCE_ALERT_KEY_CERTIFICATE_PEM, g_strdup
(certificate_pem), g_free);
+
+ e_trust_prompt_run_for_source (gtk_application_get_active_window (GTK_APPLICATION (shell)),
+ source, certificate_pem, certificate_errors, error_text, TRUE,
+ shell->priv->cancellable, shell_trust_prompt_done_cb, shell);
+}
+
+static void
+shell_process_credentials_required_errors (EShell *shell,
+ ESource *source,
+ ESourceCredentialsReason reason,
+ const gchar *certificate_pem,
+ GTlsCertificateFlags certificate_errors,
+ const GError *op_error)
+{
+ g_return_if_fail (E_IS_SHELL (shell));
+ g_return_if_fail (E_IS_SOURCE (source));
+
+ /* Skip disabled sources */
+ if (!e_source_registry_check_enabled (shell->priv->registry, source))
+ return;
+
+ switch (reason) {
+ case E_SOURCE_CREDENTIALS_REASON_UNKNOWN:
+ /* This should not be here */
+ g_warn_if_reached ();
+ return;
+ case E_SOURCE_CREDENTIALS_REASON_REQUIRED:
+ case E_SOURCE_CREDENTIALS_REASON_REJECTED:
+ /* These are handled by the credentials prompter, if not disabled */
+ if (e_credentials_prompter_get_auto_prompt_disabled_for (shell->priv->credentials_prompter,
source))
+ break;
+
+ return;
+ case E_SOURCE_CREDENTIALS_REASON_SSL_FAILED:
+ case E_SOURCE_CREDENTIALS_REASON_ERROR:
+ break;
+ }
+
+ if (reason == E_SOURCE_CREDENTIALS_REASON_ERROR) {
+ EAlert *alert;
+
+ alert = e_alert_new ("shell:source-connection-error",
+ e_source_get_display_name (source),
+ op_error && *(op_error->message) ? op_error->message : _("Unknown error"),
+ NULL);
+
+ g_signal_connect (alert, "response", G_CALLBACK (shell_connection_error_alert_response_cb),
shell);
+ g_object_set_data_full (G_OBJECT (alert), SOURCE_ALERT_KEY_SOURCE, g_object_ref (source),
g_object_unref);
+
+ shell_submit_source_connection_alert (shell, source, alert);
+ g_object_unref (alert);
+ } else if (reason == E_SOURCE_CREDENTIALS_REASON_SSL_FAILED) {
+ g_return_if_fail (e_source_has_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION));
+
+ if (e_credentials_prompter_get_auto_prompt_disabled_for (shell->priv->credentials_prompter,
source)) {
+ /* Only show an alert */
+ EAlert *alert;
+ gchar *cert_errors_str;
+
+ cert_errors_str = e_trust_prompt_describe_certificate_errors (certificate_errors);
+
+ alert = e_alert_new ("shell:source-connection-trust-error",
+ e_source_get_display_name (source),
+ (cert_errors_str && *cert_errors_str) ? cert_errors_str :
+ op_error && *(op_error->message) ? op_error->message : _("Unknown
error"),
+ NULL);
+
+ g_signal_connect (alert, "response", G_CALLBACK
(shell_connect_trust_error_alert_response_cb), shell);
+
+ g_object_set_data_full (G_OBJECT (alert), SOURCE_ALERT_KEY_SOURCE, g_object_ref
(source), g_object_unref);
+ g_object_set_data_full (G_OBJECT (alert), SOURCE_ALERT_KEY_CERTIFICATE_PEM, g_strdup
(certificate_pem), g_free);
+ g_object_set_data (G_OBJECT (alert), SOURCE_ALERT_KEY_CERTIFICATE_ERRORS,
GUINT_TO_POINTER (certificate_errors));
+ g_object_set_data_full (G_OBJECT (alert), SOURCE_ALERT_KEY_ERROR_TEXT, op_error ?
g_strdup (op_error->message) : NULL, g_free);
+
+ shell_submit_source_connection_alert (shell, source, alert);
+
+ g_free (cert_errors_str);
+ g_object_unref (alert);
+ } else {
+ g_object_set_data_full (G_OBJECT (source), SOURCE_ALERT_KEY_CERTIFICATE_PEM, g_strdup
(certificate_pem), g_free);
+
+ e_trust_prompt_run_for_source (gtk_application_get_active_window (GTK_APPLICATION
(shell)),
+ source, certificate_pem, certificate_errors, op_error ? op_error->message :
NULL, TRUE,
+ shell->priv->cancellable, shell_trust_prompt_done_cb, shell);
+ }
+ } else if (reason == E_SOURCE_CREDENTIALS_REASON_REQUIRED ||
+ reason == E_SOURCE_CREDENTIALS_REASON_REJECTED) {
+ EAlert *alert;
+
+ alert = e_alert_new ("shell:source-connection-error",
+ e_source_get_display_name (source),
+ op_error && *(op_error->message) ? op_error->message : _("Credentials are
required to connect to the destination host."),
+ NULL);
+
+ g_signal_connect (alert, "response", G_CALLBACK (shell_connection_error_alert_response_cb),
shell);
+ g_object_set_data_full (G_OBJECT (alert), SOURCE_ALERT_KEY_SOURCE, g_object_ref (source),
g_object_unref);
+
+ shell_submit_source_connection_alert (shell, source, alert);
+ g_object_unref (alert);
+ } else {
+ g_warn_if_reached ();
+ }
+}
+
+static void
+shell_get_last_credentials_required_arguments_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ EShell *shell = user_data;
+ ESource *source;
+ ESourceCredentialsReason reason = E_SOURCE_CREDENTIALS_REASON_UNKNOWN;
+ gchar *certificate_pem = NULL;
+ GTlsCertificateFlags certificate_errors = 0;
+ GError *op_error = NULL;
+ GError *error = NULL;
+
+ g_return_if_fail (E_IS_SOURCE (source_object));
+
+ source = E_SOURCE (source_object);
+
+ if (!e_source_get_last_credentials_required_arguments_finish (source, result, &reason,
+ &certificate_pem, &certificate_errors, &op_error, &error)) {
+ /* Can be cancelled only if the shell is disposing/disposed */
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ EAlert *alert;
+
+ g_return_if_fail (E_IS_SHELL (shell));
+
+ alert = e_alert_new ("shell:source-get-values-failed",
+ e_source_get_display_name (source),
+ error->message,
+ NULL);
+ e_shell_submit_alert (shell, alert);
+ g_object_unref (alert);
+ }
+
+ g_clear_error (&error);
+ return;
+ }
+
+ g_return_if_fail (E_IS_SHELL (shell));
+
+ if (reason != E_SOURCE_CREDENTIALS_REASON_UNKNOWN)
+ shell_process_credentials_required_errors (shell, source, reason, certificate_pem,
certificate_errors, op_error);
+
+ g_free (certificate_pem);
+ g_clear_error (&op_error);
+}
+
+static void
+shell_process_failed_authentications (EShell *shell)
+{
+ GList *sources, *link;
+
+ g_return_if_fail (E_IS_SHELL (shell));
+
+ sources = e_source_registry_list_enabled (shell->priv->registry, NULL);
+
+ for (link = sources; link; link = g_list_next (link)) {
+ ESource *source = link->data;
+
+ if (source && (
+ e_source_get_connection_status (source) == E_SOURCE_CONNECTION_STATUS_DISCONNECTED ||
+ e_source_get_connection_status (source) == E_SOURCE_CONNECTION_STATUS_SSL_FAILED)) {
+ /* Only show alerts, do not open windows */
+ e_credentials_prompter_set_auto_prompt_disabled_for
(shell->priv->credentials_prompter, source, TRUE);
+
+ e_source_get_last_credentials_required_arguments (source, shell->priv->cancellable,
+ shell_get_last_credentials_required_arguments_cb, shell);
+ }
+ }
+
+ g_list_free_full (sources, g_object_unref);
+}
+
+static void
+shell_credentials_required_cb (ESourceRegistry *registry,
+ ESource *source,
+ ESourceCredentialsReason reason,
+ const gchar *certificate_pem,
+ GTlsCertificateFlags certificate_errors,
+ const GError *op_error,
+ EShell *shell)
+{
+ g_return_if_fail (E_IS_SHELL (shell));
+
+ shell_process_credentials_required_errors (shell, source, reason, certificate_pem,
certificate_errors, op_error);
+}
+
+static GtkWindow *
+shell_get_dialog_parent_cb (ECredentialsPrompter *prompter,
+ EShell *shell)
+{
+ GList *windows, *link;
+
+ g_return_val_if_fail (E_IS_SHELL (shell), NULL);
+
+ windows = gtk_application_get_windows (GTK_APPLICATION (shell));
+ for (link = windows; link; link = g_list_next (link)) {
+ GtkWindow *window = link->data;
+
+ if (E_IS_SHELL_WINDOW (window))
+ return window;
+ }
+
+ return NULL;
+}
+
+static void
shell_sm_quit_cb (EShell *shell,
gpointer user_data)
{
@@ -712,6 +1134,12 @@ shell_get_property (GObject *object,
value, e_shell_get_registry (
E_SHELL (object)));
return;
+
+ case PROP_CREDENTIALS_PROMPTER:
+ g_value_set_object (
+ value, e_shell_get_credentials_prompter (
+ E_SHELL (object)));
+ return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -735,6 +1163,11 @@ shell_dispose (GObject *object)
priv->prepare_quit_timeout_id = 0;
}
+ if (priv->cancellable) {
+ g_cancellable_cancel (priv->cancellable);
+ g_clear_object (&priv->cancellable);
+ }
+
while ((alert = g_queue_pop_head (&priv->alerts)) != NULL) {
g_signal_handlers_disconnect_by_func (
alert, shell_alert_response_cb, object);
@@ -754,7 +1187,29 @@ shell_dispose (GObject *object)
priv->backend_died_handler_id = 0;
}
+ if (priv->allow_auth_prompt_handler_id > 0) {
+ g_signal_handler_disconnect (
+ priv->client_cache,
+ priv->allow_auth_prompt_handler_id);
+ priv->allow_auth_prompt_handler_id = 0;
+ }
+
+ if (priv->credentials_required_handler_id > 0) {
+ g_signal_handler_disconnect (
+ priv->registry,
+ priv->credentials_required_handler_id);
+ priv->credentials_required_handler_id = 0;
+ }
+
+ if (priv->get_dialog_parent_handler_id > 0) {
+ g_signal_handler_disconnect (
+ priv->credentials_prompter,
+ priv->get_dialog_parent_handler_id);
+ priv->get_dialog_parent_handler_id = 0;
+ }
+
g_clear_object (&priv->registry);
+ g_clear_object (&priv->credentials_prompter);
g_clear_object (&priv->client_cache);
g_clear_object (&priv->preferences_window);
@@ -905,13 +1360,27 @@ shell_initable_init (GInitable *initable,
return FALSE;
shell->priv->registry = g_object_ref (registry);
+ shell->priv->credentials_prompter = e_credentials_prompter_new (registry);
shell->priv->client_cache = e_client_cache_new (registry);
+ shell->priv->credentials_required_handler_id = g_signal_connect (
+ shell->priv->registry, "credentials-required",
+ G_CALLBACK (shell_credentials_required_cb), shell);
+
+ shell->priv->get_dialog_parent_handler_id = g_signal_connect (
+ shell->priv->credentials_prompter, "get-dialog-parent",
+ G_CALLBACK (shell_get_dialog_parent_cb), shell);
+
handler_id = g_signal_connect (
shell->priv->client_cache, "backend-died",
G_CALLBACK (shell_backend_died_cb), shell);
shell->priv->backend_died_handler_id = handler_id;
+ handler_id = g_signal_connect (
+ shell->priv->client_cache, "allow-auth-prompt",
+ G_CALLBACK (shell_allow_auth_prompt_cb), shell);
+ shell->priv->allow_auth_prompt_handler_id = handler_id;
+
/* Configure WebKit's default SoupSession. */
proxy_source = e_source_registry_ref_builtin_proxy (registry);
@@ -1070,6 +1539,24 @@ e_shell_class_init (EShellClass *class)
G_PARAM_STATIC_STRINGS));
/**
+ * EShell:credentials-prompter
+ *
+ * The #ECredentialsPrompter managing #ESource credential requests.
+ *
+ * Since: 3.14
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_CREDENTIALS_PROMPTER,
+ g_param_spec_object (
+ "credentials-prompter",
+ "Credentials Prompter",
+ "Credentials Prompter",
+ E_TYPE_CREDENTIALS_PROMPTER,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
* EShell::event
* @shell: the #EShell which emitted the signal
* @event_data: data associated with the event
@@ -1232,6 +1719,7 @@ e_shell_init (EShell *shell)
g_queue_init (&shell->priv->alerts);
+ shell->priv->cancellable = g_cancellable_new ();
shell->priv->preferences_window = e_preferences_window_new (shell);
shell->priv->backends_by_name = backends_by_name;
shell->priv->backends_by_scheme = backends_by_scheme;
@@ -1443,6 +1931,54 @@ e_shell_get_registry (EShell *shell)
}
/**
+ * e_shell_get_credentials_prompter:
+ * @shell: an #EShell
+ *
+ * Returns the shell's #ECredentialsPrompter which responds
+ * to #ESource instances credential requests.
+ *
+ * Returns: the #ECredentialsPrompter
+ *
+ * Since: 3.14
+ **/
+ECredentialsPrompter *
+e_shell_get_credentials_prompter (EShell *shell)
+{
+ g_return_val_if_fail (E_IS_SHELL (shell), NULL);
+
+ return shell->priv->credentials_prompter;
+}
+
+/**
+ * e_shell_allow_auth_prompt_for:
+ * @shell: an #EShell
+ * @source: an #ESource
+ *
+ * Allows direct credentials prompt for @source. That means,
+ * when the @source will emit 'credentials-required' signal,
+ * then a user will be asked accordingly. When the auth prompt
+ * is disabled, aonly an #EAlert is shown.
+ *
+ * Since: 3.14
+ **/
+void
+e_shell_allow_auth_prompt_for (EShell *shell,
+ ESource *source)
+{
+ g_return_if_fail (E_IS_SHELL (shell));
+ g_return_if_fail (E_IS_SOURCE (source));
+
+ e_credentials_prompter_set_auto_prompt_disabled_for (shell->priv->credentials_prompter, source,
FALSE);
+
+ if (e_source_get_connection_status (source) == E_SOURCE_CONNECTION_STATUS_AWAITING_CREDENTIALS) {
+ e_credentials_prompter_process_source (shell->priv->credentials_prompter, source);
+ } else if (e_source_get_connection_status (source) == E_SOURCE_CONNECTION_STATUS_SSL_FAILED) {
+ e_source_get_last_credentials_required_arguments (source, shell->priv->cancellable,
+ shell_get_last_credentials_required_arguments_cb, shell);
+ }
+}
+
+/**
* e_shell_create_shell_window:
* @shell: an #EShell
* @view_name: name of the initial shell view, or %NULL
@@ -1499,6 +2035,14 @@ e_shell_create_shell_window (EShell *shell,
gtk_widget_show (shell_window);
+ if (g_list_length (gtk_application_get_windows (GTK_APPLICATION (shell))) == 1) {
+ /* It's the first window, process outstanding credential requests now */
+ e_credentials_prompter_process_awaiting_credentials (shell->priv->credentials_prompter);
+
+ /* Also check alerts for failed authentications */
+ shell_process_failed_authentications (shell);
+ }
+
return shell_window;
remote: /* Send a message to the other Evolution process. */
diff --git a/shell/e-shell.h b/shell/e-shell.h
index 4ae9c31..1d336e2 100644
--- a/shell/e-shell.h
+++ b/shell/e-shell.h
@@ -22,6 +22,7 @@
#define E_SHELL_H
#include <libedataserver/libedataserver.h>
+#include <libedataserverui/libedataserverui.h>
#include <e-util/e-util.h>
@@ -117,6 +118,10 @@ EShellBackend * e_shell_get_backend_by_scheme (EShell *shell,
EClientCache * e_shell_get_client_cache (EShell *shell);
ESourceRegistry *
e_shell_get_registry (EShell *shell);
+ECredentialsPrompter *
+ e_shell_get_credentials_prompter(EShell *shell);
+void e_shell_allow_auth_prompt_for (EShell *shell,
+ ESource *source);
GtkWidget * e_shell_create_shell_window (EShell *shell,
const gchar *view_name);
guint e_shell_handle_uris (EShell *shell,
diff --git a/shell/shell.error.xml b/shell/shell.error.xml
index a0c59cf..8ce679e 100644
--- a/shell/shell.error.xml
+++ b/shell/shell.error.xml
@@ -35,4 +35,36 @@ If you choose to continue, you may not have access to some of your old data.
<button _label="Keep _Waiting" response="GTK_RESPONSE_CANCEL"/>
</error>
+ <error id="source-get-values-failed" type="warning">
+ <_primary>Failed to get values from '{0}'</_primary>
+ <secondary>{1}</secondary>
+ </error>
+
+ <error id="source-invoke-authenticate-failed" type="warning">
+ <_primary>Failed to invoke authenticate for '{0}'</_primary>
+ <secondary>{1}</secondary>
+ </error>
+
+ <error id="source-connection-error" type="error">
+ <_primary>Failed to connect to '{0}'</_primary>
+ <secondary>{1}</secondary>
+ <button _label="_Reconnect" response="GTK_RESPONSE_APPLY"/>
+ </error>
+
+ <error id="source-credentials-prompt-failed" type="warning">
+ <_primary>Failed to prompt for credentials for '{0}'</_primary>
+ <secondary>{1}</secondary>
+ </error>
+
+ <error id="source-trust-prompt-failed" type="warning">
+ <_primary>Failed to finish trust prompt for '{0}'</_primary>
+ <secondary>{1}</secondary>
+ </error>
+
+ <error id="source-connection-trust-error" type="error">
+ <_primary>SSL certificate for '{0}' is not trusted.</_primary>
+ <_secondary>Reason: {1}</_secondary>
+ <button _label="_View Certificate" response="GTK_RESPONSE_APPLY"/>
+ </error>
+
</error-list>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]