[evolution-data-server/wip/offline-cache] [ECalMetaBackend] Change prototype of connect_sync() and implement EBackendClass::authenticate_sync(
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/wip/offline-cache] [ECalMetaBackend] Change prototype of connect_sync() and implement EBackendClass::authenticate_sync(
- Date: Mon, 6 Mar 2017 14:44:23 +0000 (UTC)
commit 6579671ddf7b1a62457736890a7ba0c6093cfb79
Author: Milan Crha <mcrha redhat com>
Date: Mon Mar 6 15:42:20 2017 +0100
[ECalMetaBackend] Change prototype of connect_sync() and implement EBackendClass::authenticate_sync()
src/calendar/libedata-cal/e-cal-meta-backend.c | 160 ++++++++++++++++++++++--
src/calendar/libedata-cal/e-cal-meta-backend.h | 8 ++
src/libebackend/e-backend.c | 1 +
src/libedataserver/e-source-enums.h | 3 +
4 files changed, 164 insertions(+), 8 deletions(-)
---
diff --git a/src/calendar/libedata-cal/e-cal-meta-backend.c b/src/calendar/libedata-cal/e-cal-meta-backend.c
index 067628e..37a0472 100644
--- a/src/calendar/libedata-cal/e-cal-meta-backend.c
+++ b/src/calendar/libedata-cal/e-cal-meta-backend.c
@@ -51,6 +51,7 @@
struct _ECalMetaBackendPrivate {
GMutex property_lock;
ECalCache *cache;
+ ENamedParameters *last_credentials;
GHashTable *view_cancellables;
GCancellable *refresh_cancellable; /* Set when refreshing the content */
GCancellable *source_changed_cancellable; /* Set when processing source changed signal */
@@ -204,6 +205,73 @@ ecmb_steal_view_cancellable (ECalMetaBackend *meta_backend,
}
static gboolean
+ecmb_connect_wrapper_sync (ECalMetaBackend *meta_backend,
+ GCancellable *cancellable,
+ GError **error)
+{
+ ENamedParameters *credentials;
+ ESourceAuthenticationResult auth_result = E_SOURCE_AUTHENTICATION_UNKNOWN;
+ ESourceCredentialsReason creds_reason = E_SOURCE_CREDENTIALS_REASON_ERROR;
+ gchar *certificate_pem = NULL;
+ GTlsCertificateFlags certificate_errors = 0;
+ GError *local_error = NULL;
+
+ g_return_val_if_fail (E_IS_CAL_META_BACKEND (meta_backend), FALSE);
+
+ if (!e_backend_get_online (E_BACKEND (meta_backend))) {
+ g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_REPOSITORY_OFFLINE,
+ e_client_error_to_string (E_CLIENT_ERROR_REPOSITORY_OFFLINE));
+
+ return FALSE;
+ }
+
+ g_mutex_lock (&meta_backend->priv->property_lock);
+ credentials = e_named_parameters_new_clone (meta_backend->priv->last_credentials);
+ g_mutex_unlock (&meta_backend->priv->property_lock);
+
+ if (e_cal_meta_backend_connect_sync (meta_backend, credentials, &auth_result, &certificate_pem,
&certificate_errors,
+ cancellable, &local_error)) {
+ e_named_parameters_free (credentials);
+ return TRUE;
+ }
+
+ e_named_parameters_free (credentials);
+
+ g_warn_if_fail (auth_result != E_SOURCE_AUTHENTICATION_ACCEPTED);
+
+ switch (auth_result) {
+ case E_SOURCE_AUTHENTICATION_UNKNOWN:
+ if (local_error)
+ g_propagate_error (error, local_error);
+ g_free (certificate_pem);
+ return FALSE;
+ case E_SOURCE_AUTHENTICATION_ERROR:
+ creds_reason = E_SOURCE_CREDENTIALS_REASON_ERROR;
+ break;
+ case E_SOURCE_AUTHENTICATION_ERROR_SSL_FAILED:
+ creds_reason = E_SOURCE_CREDENTIALS_REASON_SSL_FAILED;
+ break;
+ case E_SOURCE_AUTHENTICATION_ACCEPTED:
+ g_warn_if_reached ();
+ break;
+ case E_SOURCE_AUTHENTICATION_REJECTED:
+ creds_reason = E_SOURCE_CREDENTIALS_REASON_REJECTED;
+ break;
+ case E_SOURCE_AUTHENTICATION_REQUIRED:
+ creds_reason = E_SOURCE_CREDENTIALS_REASON_REQUIRED;
+ break;
+ }
+
+ e_backend_schedule_credentials_required (E_BACKEND (meta_backend), creds_reason, certificate_pem,
certificate_errors,
+ local_error, cancellable, G_STRFUNC);
+
+ g_clear_error (&local_error);
+ g_free (certificate_pem);
+
+ return FALSE;
+}
+
+static gboolean
ecmb_gather_locally_cached_objects_cb (ECalCache *cal_cache,
const gchar *uid,
const gchar *rid,
@@ -262,7 +330,7 @@ ecmb_get_changes_sync (ECalMetaBackend *meta_backend,
return FALSE;
}
- if (!e_cal_meta_backend_connect_sync (meta_backend, cancellable, error) ||
+ if (!ecmb_connect_wrapper_sync (meta_backend, cancellable, error) ||
!e_cal_meta_backend_list_existing_sync (meta_backend, out_new_sync_tag, &existing_objects,
cancellable, error)) {
g_object_unref (cal_cache);
return FALSE;
@@ -464,7 +532,7 @@ ecmb_refresh_thread_func (ECalBackend *cal_backend,
meta_backend = E_CAL_META_BACKEND (cal_backend);
if (!e_backend_get_online (E_BACKEND (meta_backend)) ||
- !e_cal_meta_backend_connect_sync (meta_backend, cancellable, NULL)) {
+ !ecmb_connect_wrapper_sync (meta_backend, cancellable, NULL)) {
/* Ignore connection errors here */
return;
}
@@ -993,7 +1061,7 @@ ecmb_refresh_sync (ECalBackendSync *sync_backend,
if (!e_backend_get_online (E_BACKEND (sync_backend)))
return;
- if (e_cal_meta_backend_connect_sync (meta_backend, cancellable, error))
+ if (ecmb_connect_wrapper_sync (meta_backend, cancellable, error))
ecmb_schedule_refresh (meta_backend);
}
@@ -1030,7 +1098,7 @@ ecmb_get_object_sync (ECalBackendSync *sync_backend,
/* Ignore errors here, just try whether it's on the remote side, but not in the local cache */
if (e_backend_get_online (E_BACKEND (meta_backend)) &&
- e_cal_meta_backend_connect_sync (meta_backend, cancellable, NULL) &&
+ ecmb_connect_wrapper_sync (meta_backend, cancellable, NULL) &&
ecmb_load_component_wrapper_sync (meta_backend, cal_cache, uid, cancellable, NULL)) {
found = e_cal_cache_get_component_as_string (cal_cache, uid, rid, calobj,
cancellable, NULL);
}
@@ -1284,7 +1352,7 @@ ecmb_create_object_sync (ECalMetaBackend *meta_backend,
if (*offline_flag == E_CACHE_OFFLINE_UNKNOWN) {
if (e_backend_get_online (E_BACKEND (meta_backend)) &&
- e_cal_meta_backend_connect_sync (meta_backend, cancellable, NULL)) {
+ ecmb_connect_wrapper_sync (meta_backend, cancellable, NULL)) {
*offline_flag = E_CACHE_IS_ONLINE;
} else {
*offline_flag = E_CACHE_IS_OFFLINE;
@@ -1567,7 +1635,7 @@ ecmb_modify_object_sync (ECalMetaBackend *meta_backend,
if (success && *offline_flag == E_CACHE_OFFLINE_UNKNOWN) {
if (e_backend_get_online (E_BACKEND (meta_backend)) &&
- e_cal_meta_backend_connect_sync (meta_backend, cancellable, NULL)) {
+ ecmb_connect_wrapper_sync (meta_backend, cancellable, NULL)) {
*offline_flag = E_CACHE_IS_ONLINE;
} else {
*offline_flag = E_CACHE_IS_OFFLINE;
@@ -1724,7 +1792,7 @@ ecmb_remove_object_sync (ECalMetaBackend *meta_backend,
if (*offline_flag == E_CACHE_OFFLINE_UNKNOWN) {
if (e_backend_get_online (E_BACKEND (meta_backend)) &&
- e_cal_meta_backend_connect_sync (meta_backend, cancellable, NULL)) {
+ ecmb_connect_wrapper_sync (meta_backend, cancellable, NULL)) {
*offline_flag = E_CACHE_IS_ONLINE;
} else {
*offline_flag = E_CACHE_IS_OFFLINE;
@@ -2420,6 +2488,52 @@ ecmb_stop_view (ECalBackend *cal_backend,
}
}
+static ESourceAuthenticationResult
+ecmb_authenticate_sync (EBackend *backend,
+ const ENamedParameters *credentials,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors,
+ GCancellable *cancellable,
+ GError **error)
+{
+ ECalMetaBackend *meta_backend;
+ ESourceAuthenticationResult auth_result = E_SOURCE_AUTHENTICATION_UNKNOWN;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_CAL_META_BACKEND (backend), E_SOURCE_AUTHENTICATION_ERROR);
+
+ meta_backend = E_CAL_META_BACKEND (backend);
+
+ if (!e_backend_get_online (E_BACKEND (meta_backend))) {
+ g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_REPOSITORY_OFFLINE,
+ e_client_error_to_string (E_CLIENT_ERROR_REPOSITORY_OFFLINE));
+
+ return E_SOURCE_AUTHENTICATION_ERROR;
+ }
+
+ success = e_cal_meta_backend_connect_sync (meta_backend, credentials, &auth_result,
+ out_certificate_pem, out_certificate_errors, cancellable, error);
+
+ if (success) {
+ auth_result = E_SOURCE_AUTHENTICATION_ACCEPTED;
+ } else {
+ if (auth_result == E_SOURCE_AUTHENTICATION_UNKNOWN)
+ auth_result = E_SOURCE_AUTHENTICATION_ERROR;
+ }
+
+ g_mutex_lock (&meta_backend->priv->property_lock);
+
+ e_named_parameters_free (meta_backend->priv->last_credentials);
+ if (success)
+ meta_backend->priv->last_credentials = e_named_parameters_new_clone (credentials);
+ else
+ meta_backend->priv->last_credentials = NULL;
+
+ g_mutex_unlock (&meta_backend->priv->property_lock);
+
+ return auth_result;
+}
+
static void
ecmb_schedule_refresh (ECalMetaBackend *meta_backend)
{
@@ -2635,6 +2749,9 @@ e_cal_meta_backend_dispose (GObject *object)
g_clear_object (&meta_backend->priv->go_offline_cancellable);
}
+ e_named_parameters_free (meta_backend->priv->last_credentials);
+ meta_backend->priv->last_credentials = NULL;
+
g_mutex_unlock (&meta_backend->priv->property_lock);
/* Chain up to parent's method. */
@@ -2662,6 +2779,7 @@ static void
e_cal_meta_backend_class_init (ECalMetaBackendClass *klass)
{
GObjectClass *object_class;
+ EBackendClass *backend_class;
ECalBackendClass *cal_backend_class;
ECalBackendSyncClass *cal_backend_sync_class;
@@ -2689,6 +2807,9 @@ e_cal_meta_backend_class_init (ECalMetaBackendClass *klass)
cal_backend_class->start_view = ecmb_start_view;
cal_backend_class->stop_view = ecmb_stop_view;
+ backend_class = E_BACKEND_CLASS (klass);
+ backend_class->authenticate_sync = ecmb_authenticate_sync;
+
object_class = G_OBJECT_CLASS (klass);
object_class->set_property = e_cal_meta_backend_set_property;
object_class->get_property = e_cal_meta_backend_get_property;
@@ -3148,6 +3269,10 @@ e_cal_meta_backend_store_inline_attachments_sync (ECalMetaBackend *meta_backend,
/**
* e_cal_meta_backend_connect_sync:
* @meta_backend: an #ECalMetaBackend
+ * @credentials: (nullable): an #ENamedParameters with previously used credentials, or %NULL
+ * @out_auth_result: (out): an #ESourceAuthenticationResult with an authentication result
+ * @out_certificate_pem: (out) (transfer full): a PEM encoded certificate on failure, or %NULL
+ * @out_certificate_errors: (out): a #GTlsCertificateFlags on failure, or 0
* @cancellable: optional #GCancellable object, or %NULL
* @error: return location for a #GError, or %NULL
*
@@ -3158,6 +3283,21 @@ e_cal_meta_backend_store_inline_attachments_sync (ECalMetaBackend *meta_backend,
* errors are propagated to the caller/client side.
* This method is not called when the backend is not online.
*
+ * The @credentials parameter consists of the previously used credentials.
+ * It's always %NULL with the first connection attempt. To get the credentials,
+ * just set the @out_auth_result to %E_SOURCE_AUTHENTICATION_REQUIRED for
+ * the first time and the function will be called again once the credentials
+ * are available. See the documentation of #ESourceAuthenticationResult for
+ * other available reasons.
+ *
+ * The out parameters are passed to e_backend_schedule_credentials_required()
+ * and are ignored when the descendant returns %TRUE, aka they are used
+ * only if the connection fails. The @out_certificate_pem and @out_certificate_errors
+ * should be used together and they can be left untouched if the failure reason was
+ * not related to certificate. Use @out_auth_result %E_SOURCE_AUTHENTICATION_UNKNOWN
+ * to indicate other error than @credentials error, otherwise the @error is used
+ * according to @out_auth_result value.
+ *
* It is mandatory to implement this virtual method by the descendant.
*
* Returns: Whether succeeded.
@@ -3166,6 +3306,10 @@ e_cal_meta_backend_store_inline_attachments_sync (ECalMetaBackend *meta_backend,
**/
gboolean
e_cal_meta_backend_connect_sync (ECalMetaBackend *meta_backend,
+ const ENamedParameters *credentials,
+ ESourceAuthenticationResult *out_auth_result,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors,
GCancellable *cancellable,
GError **error)
{
@@ -3177,7 +3321,7 @@ e_cal_meta_backend_connect_sync (ECalMetaBackend *meta_backend,
g_return_val_if_fail (klass != NULL, FALSE);
g_return_val_if_fail (klass->connect_sync != NULL, FALSE);
- return klass->connect_sync (meta_backend, cancellable, error);
+ return klass->connect_sync (meta_backend, credentials, out_auth_result, out_certificate_pem,
out_certificate_errors, cancellable, error);
}
/**
diff --git a/src/calendar/libedata-cal/e-cal-meta-backend.h b/src/calendar/libedata-cal/e-cal-meta-backend.h
index 4873069..b12d5f0 100644
--- a/src/calendar/libedata-cal/e-cal-meta-backend.h
+++ b/src/calendar/libedata-cal/e-cal-meta-backend.h
@@ -97,6 +97,10 @@ struct _ECalMetaBackendClass {
/* Virtual methods */
gboolean (* connect_sync) (ECalMetaBackend *meta_backend,
+ const ENamedParameters *credentials,
+ ESourceAuthenticationResult *out_auth_result,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors,
GCancellable *cancellable,
GError **error);
gboolean (* disconnect_sync) (ECalMetaBackend *meta_backend,
@@ -166,6 +170,10 @@ gboolean e_cal_meta_backend_store_inline_attachments_sync
GCancellable *cancellable,
GError **error);
gboolean e_cal_meta_backend_connect_sync (ECalMetaBackend *meta_backend,
+ const ENamedParameters *credentials,
+ ESourceAuthenticationResult *out_auth_result,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors,
GCancellable *cancellable,
GError **error);
gboolean e_cal_meta_backend_disconnect_sync
diff --git a/src/libebackend/e-backend.c b/src/libebackend/e-backend.c
index 389b9b4..0e17755 100644
--- a/src/libebackend/e-backend.c
+++ b/src/libebackend/e-backend.c
@@ -314,6 +314,7 @@ backend_source_authenticate_thread (gpointer user_data)
ESourceCredentialsReason reason = E_SOURCE_CREDENTIALS_REASON_ERROR;
switch (auth_result) {
+ case E_SOURCE_AUTHENTICATION_UNKNOWN:
case E_SOURCE_AUTHENTICATION_ERROR:
reason = E_SOURCE_CREDENTIALS_REASON_ERROR;
break;
diff --git a/src/libedataserver/e-source-enums.h b/src/libedataserver/e-source-enums.h
index f241c9f..2c37f52 100644
--- a/src/libedataserver/e-source-enums.h
+++ b/src/libedataserver/e-source-enums.h
@@ -67,6 +67,8 @@ typedef enum {
/**
* ESourceAuthenticationResult:
+ * @E_SOURCE_AUTHENTICATION_UNKNOWN:
+ * Unknown error occurred while authenticating. Since: 3.26
* @E_SOURCE_AUTHENTICATION_ERROR:
* An error occurred while authenticating.
* @E_SOURCE_AUTHENTICATION_ERROR_SSL_FAILED:
@@ -83,6 +85,7 @@ typedef enum {
* Since: 3.6
**/
typedef enum {
+ E_SOURCE_AUTHENTICATION_UNKNOWN = -1,
E_SOURCE_AUTHENTICATION_ERROR,
E_SOURCE_AUTHENTICATION_ERROR_SSL_FAILED,
E_SOURCE_AUTHENTICATION_ACCEPTED,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]