[evolution-kolab/ek-wip-porting] EBookBackendKolab: implemented online/offline state switching



commit 552a51664d6b554a93210c85a9f9e2202be851a1
Author: Christian Hilberg <hilberg kernelconcepts de>
Date:   Fri Mar 16 20:09:43 2012 +0100

    EBookBackendKolab: implemented online/offline state switching
    
    * implemented state switching (offline, online)
    * state is set initially according to the
      E-D-S status
    * state can subsequently be toggled by the
      online state button in Evolution

 src/addressbook/e-book-backend-kolab.c |  245 +++++++++++++++++++++++++++++---
 1 files changed, 226 insertions(+), 19 deletions(-)
---
diff --git a/src/addressbook/e-book-backend-kolab.c b/src/addressbook/e-book-backend-kolab.c
index 743085b..29ac5c4 100644
--- a/src/addressbook/e-book-backend-kolab.c
+++ b/src/addressbook/e-book-backend-kolab.c
@@ -58,11 +58,12 @@ typedef struct _EBookBackendKolabPrivate EBookBackendKolabPrivate;
 struct _EBookBackendKolabPrivate
 {
 	/* GNOME_Evolution_Addressbook_BookMode	book_mode; */
-	EBookBackendCache			*book_cache;
-	KolabMailAccess				*book_koma;
-	gchar					*book_uri;
-	GHashTable				*koma_table;
-	gboolean				auth_received;
+	EBookBackendCache *book_cache;
+	KolabMailAccess *book_koma;
+	gchar *book_uri;
+	GHashTable *koma_table;
+	gboolean auth_received;
+	GError *mode_switch_err;
 };
 
 #define E_BOOK_BACKEND_KOLAB_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), E_TYPE_BOOK_BACKEND_KOLAB, EBookBackendKolabPrivate))
@@ -74,13 +75,116 @@ G_DEFINE_TYPE (EBookBackendKolab, e_book_backend_kolab, E_TYPE_BOOK_BACKEND_SYNC
 /* internal statics */
 
 static void
+book_backend_kolab_signal_online_cb (GObject *object)
+{
+	EBackend *backend = NULL;
+	EBookBackendKolab *self = NULL;
+	EBookBackendKolabPrivate *priv = NULL;
+	gboolean online = FALSE;
+	gboolean ok = FALSE;
+
+	g_return_if_fail (E_IS_BOOK_BACKEND_KOLAB (object));
+
+	backend = E_BACKEND (object);
+	self = E_BOOK_BACKEND_KOLAB (object);
+	priv = E_BOOK_BACKEND_KOLAB_PRIVATE (self);
+
+	online = e_backend_get_online (backend);
+
+	g_debug ("%s()[%u] backend mode: %i",
+	         __func__, __LINE__, online);
+
+	/* FIXME
+	 *
+	 * This callback is for online state notifications only.
+	 * Doing I/O, which can fail, is the wrong thing to do
+	 * here since we do not have a proper way to let the user
+	 * cancel the I/O. Getting KolabMailAccess online can hang.
+	 * Thus, cancellation would be needed.
+	 *
+	 * e_backend_get_online (backend) could be called in the
+	 * "other" operations and the KolabMailAccess state changed
+	 * if needed, Problem: KolabMailAccess online/offline state
+	 * change involves synchronization with the server, which
+	 * may take long time and is not expected by the user if
+	 * they e.g. just add a contact or event.
+	 *
+	 * For now, we'll leave the cancellation issue aside
+	 * (we could not have cancelled in 2.30 either), but
+	 * at least bind a GError to our backend object, if we
+	 * have one. We can then propagate this error in the
+	 * first "other" operation the user triggers.
+	 *
+	 * It has been supposed by upstream to use a global static
+	 * GCancellable for the cancellation issue, but it will
+	 * not help us here since the Evolution online/offline
+	 * toggle button does not seem to expect heavy I/O to
+	 * be triggered. Our local GCancellabe would need transfer
+	 * to Evo and be registered there so the online/offline
+	 * switching in evo-kolab could be cancelled from the
+	 * frontend. Moreover, there is no telling how long a
+	 * synchronization run with the Kolab server may take,
+	 * so we also cannot set a sensible timeout here.
+	 *
+	 */
+
+	if (priv->mode_switch_err != NULL) {
+		g_warning ("%s()[%u]: Online mode switching error pending (%s)",
+		           __func__, __LINE__, priv->mode_switch_err->message);
+		g_error_free (priv->mode_switch_err);
+		priv->mode_switch_err = NULL;
+	}
+	ok = kolab_util_backend_deploy_mode_by_backend (priv->book_koma,
+	                                                online,
+	                                                NULL, /* GCancellable (see above )*/
+	                                                &(priv->mode_switch_err));
+	if (priv->mode_switch_err) {
+		g_warning ("%s()[%u]: Online mode switching error pending (%s)",
+		           __func__, __LINE__, priv->mode_switch_err->message);
+	}
+
+	if (ok) {
+		e_book_backend_notify_online (E_BOOK_BACKEND (self), online);
+	}
+}
+
+static gboolean
+book_backend_kolab_notify_open (EBookBackendKolab *self,
+                                GError **err)
+{
+	EBookBackend *bbackend = NULL;
+	EBookBackendKolabPrivate *priv = NULL;
+	KolabMailAccessOpmodeID tmp_mode = KOLAB_MAIL_ACCESS_OPMODE_INVAL;
+	GError *tmp_err = NULL;
+
+	g_assert (E_IS_BOOK_BACKEND_KOLAB (self));
+	g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
+
+	priv = E_BOOK_BACKEND_KOLAB_PRIVATE (self);
+	bbackend = E_BOOK_BACKEND (self);
+
+	tmp_mode = kolab_mail_access_get_opmode (priv->book_koma, &tmp_err);
+	if (tmp_err != NULL) {
+		g_propagate_error (err, tmp_err);
+		return FALSE;
+	}
+	e_book_backend_notify_online (bbackend,
+	                              tmp_mode = KOLAB_MAIL_ACCESS_OPMODE_ONLINE ? TRUE : FALSE);
+	e_book_backend_notify_opened (bbackend, NULL);
+
+	return TRUE;
+}
+
+/*----------------------------------------------------------------------------*/
+/* class functions */
+
+static void
 e_book_backend_kolab_open (EBookBackendSync *backend,
                            EDataBook *book,
                            GCancellable *cancellable,
                            gboolean only_if_exists,
                            GError **error)
 {
-	EBookBackend *bbackend = NULL;
 	EBookBackendKolab *self = NULL;
 	EBookBackendKolabPrivate *priv = NULL;
 	ESource *source = NULL;
@@ -88,15 +192,15 @@ e_book_backend_kolab_open (EBookBackendSync *backend,
         KolabSettingsHandler *ksettings = NULL;
         KolabMailAccess *tmp_koma = NULL;
         KolabSyncStrategyID sync_value = KOLAB_SYNC_STRATEGY_DEFAULT;
-        KolabMailAccessOpmodeID tmp_mode = KOLAB_MAIL_ACCESS_OPMODE_INVAL;
         gchar *sourcename = NULL;
         gchar *servername = NULL;
         gchar *username = NULL;
         gchar *user_at_server = NULL;
         gchar *tmp_key = NULL;
         const gchar *sync_prop = NULL;
-	GError *tmp_err = NULL;
+	gboolean online = FALSE;
 	gboolean ok = FALSE;
+	GError *tmp_err = NULL;
 
 	e_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_KOLAB (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
 	e_return_data_book_error_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
@@ -106,7 +210,6 @@ e_book_backend_kolab_open (EBookBackendSync *backend,
 
 	self = E_BOOK_BACKEND_KOLAB (backend);
 	priv = E_BOOK_BACKEND_KOLAB_PRIVATE (self);
-	bbackend = E_BOOK_BACKEND (backend);
 
 	kolab_util_glib_init ();
 	kolab_util_http_init ();
@@ -163,6 +266,8 @@ e_book_backend_kolab_open (EBookBackendSync *backend,
 	sync_value = kolab_util_misc_sync_value_from_property (sync_prop);
 	sourcename = kolab_util_backend_get_relative_path_from_uri (priv->book_uri);
 
+	/* Check whether we have a KolabMailAccess (KoMA) instance already */
+
 	user_at_server = g_strdup_printf ("%s %s",
 	                                  username, servername);
 
@@ -171,7 +276,9 @@ e_book_backend_kolab_open (EBookBackendSync *backend,
 	                                   (gpointer *) &tmp_key,
 	                                   (gpointer *) &tmp_koma);
 	if (ok) {
-		/* There is already a KoMA instance for $servername. Use it and return */
+		/* There already is a KoMA instance for user_at_server.
+		 * Use it and return
+		 */
 		g_object_ref (tmp_koma);
 		priv->book_koma = tmp_koma;
 		g_free (servername);
@@ -185,7 +292,29 @@ e_book_backend_kolab_open (EBookBackendSync *backend,
 		                                     NULL,
 		                                     sourcename,
 		                                     &sync_value);
-		goto notifications;
+		g_object_unref (ksettings);
+		/* We should have received authentication data (password)
+		 * at this point, since it was requested and stored when
+		 * the KolabMailAccess object was initially created.
+		 * We can just skip the AuthenticationRequested part here
+		 * and move along...
+		 */
+		online = e_backend_get_online (E_BACKEND (backend));
+		ok = kolab_util_backend_deploy_mode_by_backend (priv->book_koma,
+		                                                online,
+		                                                cancellable,
+		                                                &tmp_err);
+		if (! ok) {
+			kolab_util_contact_err_to_edb_err (error, tmp_err, __func__, __LINE__);
+			g_error_free (tmp_err);
+			return;
+		}
+		ok = book_backend_kolab_notify_open (self, &tmp_err);
+		if (! ok) {
+			kolab_util_contact_err_to_edb_err (error, tmp_err, __func__, __LINE__);
+			g_error_free (tmp_err);
+		}
+		return;
 	}
 
 	/* Nope, we need to setup a new KoMA instance and a settings handler */
@@ -255,7 +384,17 @@ e_book_backend_kolab_open (EBookBackendSync *backend,
 		return;
 	}
 
- notifications:
+	/* If we are here (just created a fresh KolabMailAccess),
+	 * we did not yet receive authentication data. Though we
+	 * do not need it if we want to stay in offline mode, once
+	 * we're asked to go online, we'll need the credentials
+	 * (password in our case) anyway, so we can just request
+	 * it once the book gets opened.
+	 */
+	e_book_backend_notify_auth_required (E_BOOK_BACKEND (self), TRUE, NULL);
+
+	/* FIXME may need to move the notifications to authenticate_user() */
+#if 0
 	/* e_book_backend_kolab_set_mode (backend, priv->book_mode); */
 	tmp_mode = kolab_mail_access_get_opmode (priv->book_koma, &tmp_err);
 	if (tmp_err != NULL) {
@@ -264,8 +403,6 @@ e_book_backend_kolab_open (EBookBackendSync *backend,
 		return;
 	}
 
-#if 0 /* FIXME */
-	e_book_backend_notify_auth_required (bbackend, TRUE, NULL);
 	e_book_backend_set_is_loaded (bbackend, TRUE);
 	e_book_backend_notify_connection_status (bbackend,
 	                                         tmp_mode = KOLAB_MAIL_ACCESS_OPMODE_ONLINE ? TRUE : FALSE);
@@ -337,6 +474,7 @@ e_book_backend_kolab_refresh (EBookBackendSync *backend,
 	g_error ("%s: FIXME implement me", __func__);
 }
 
+#if 0 /* probably not needed */
 static gboolean
 e_book_backend_kolab_get_backend_property (EBookBackendSync *backend,
                                            EDataBook *book,
@@ -362,7 +500,9 @@ e_book_backend_kolab_get_backend_property (EBookBackendSync *backend,
 
 	return TRUE;
 }
+#endif
 
+#if 0 /* probably not needed */
 static gboolean
 e_book_backend_kolab_set_backend_property (EBookBackendSync *backend,
                                            EDataBook *book,
@@ -386,6 +526,7 @@ e_book_backend_kolab_set_backend_property (EBookBackendSync *backend,
 
 	g_error ("%s: FIXME implement me", __func__);
 }
+#endif
 
 static void
 e_book_backend_kolab_create_contacts (EBookBackendSync *backend,
@@ -683,6 +824,13 @@ e_book_backend_kolab_authenticate_user (EBookBackendSync *backend,
 {
 	EBookBackendKolab *self = NULL;
 	EBookBackendKolabPrivate *priv = NULL;
+	KolabSettingsHandler *ksettings = NULL;
+	const gchar *cred_user = NULL;
+	const gchar *cred_pwd  = NULL;
+	const gchar *kset_user = NULL;
+	gboolean online = FALSE;
+	gboolean ok = FALSE;
+	GError *tmp_err = NULL;
 
 	g_return_if_fail (error == NULL || *error == NULL);
 	e_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_KOLAB (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
@@ -692,11 +840,60 @@ e_book_backend_kolab_authenticate_user (EBookBackendSync *backend,
 	self = E_BOOK_BACKEND_KOLAB (backend);
 	priv = E_BOOK_BACKEND_KOLAB_PRIVATE (self);
 
-	g_error ("%s: FIXME implement me", __func__);
+	g_debug ("%s()[%u] called.", __func__, __LINE__);
+
+	ksettings = kolab_mail_access_get_settings_handler (priv->book_koma);
+
+	/* warn about a possible inconsistency in user names */
+	kset_user = kolab_settings_handler_get_char_field (ksettings,
+	                                                  KOLAB_SETTINGS_HANDLER_CHAR_FIELD_KOLAB_USER_NAME,
+	                                                  &tmp_err);
+	if (tmp_err != NULL) {
+		g_object_unref (ksettings);
+		kolab_util_contact_err_to_edb_err (error, tmp_err, __func__, __LINE__);
+		g_error_free (tmp_err);
+		return;
+	}
+	cred_user = e_credentials_peek (credentials,
+	                                E_CREDENTIALS_KEY_USERNAME);
+	if (g_strcmp0 (kset_user, cred_user) != 0) {
+		g_warning ("%s()[%u] username from argument and username in "
+		           "KolabSettingsHandler do not match: %s vs. %s",
+		           __func__, __LINE__, cred_user, kset_user);
+	}
+
+	cred_pwd = e_credentials_peek (credentials,
+	                               E_CREDENTIALS_KEY_PASSWORD);
+
+	kolab_util_backend_prepare_settings (ksettings,
+	                                     NULL,
+	                                     NULL,
+	                                     NULL,
+	                                     cred_pwd,
+	                                     NULL,
+	                                     NULL);
+	g_object_unref (ksettings);
+
+	priv->auth_received = TRUE;
+
+	online = e_backend_get_online (E_BACKEND (backend));
+	ok = kolab_util_backend_deploy_mode_by_backend (priv->book_koma,
+	                                                online,
+	                                                cancellable,
+	                                                &tmp_err);
+	if (! ok) {
+		kolab_util_contact_err_to_edb_err (error, tmp_err, __func__, __LINE__);
+		g_error_free (tmp_err);
+		return;
+	}
+
+	ok = book_backend_kolab_notify_open (self, &tmp_err);
+	if (! ok) {
+		kolab_util_contact_err_to_edb_err (error, tmp_err, __func__, __LINE__);
+		g_error_free (tmp_err);
+	}
 
 #if 0 /* FIXME old */
-	g_debug ("%s()[%u] called.",
-	         __func__, __LINE__);
 	g_debug (" + user: %s\n + auth_method: %s",
 	         user, auth_method);
 	g_debug ("%s()[%u]    username = %s",
@@ -734,7 +931,7 @@ e_book_backend_kolab_authenticate_user (EBookBackendSync *backend,
 	                                     NULL);
 
 	priv->auth_received = TRUE;
-	ok = kolab_util_contact_deploy_mode_by_backend (priv->book_koma,
+	ok = kolab_util_backend_deploy_mode_by_backend (priv->book_koma,
 	                                                priv->book_mode);
 
 	return GNOME_Evolution_Addressbook_Success;
@@ -869,6 +1066,9 @@ e_book_backend_kolab_init (EBookBackendKolab *backend)
 	priv->book_uri = NULL;
 	priv->book_koma = NULL;
 	priv->auth_received = FALSE;
+	priv->mode_switch_err = NULL;
+
+	g_signal_connect (E_BACKEND (backend), "notify::online", G_CALLBACK (book_backend_kolab_signal_online_cb), NULL);
 } /* e_book_backend_kolab_init () */
 
 static void
@@ -913,6 +1113,11 @@ e_book_backend_kolab_finalize (GObject *object)
 
 	if (priv->book_uri != NULL)
 		g_free (priv->book_uri);
+	if (priv->mode_switch_err != NULL) {
+		g_warning ("%s()[%u]: %s",
+		           __func__, __LINE__, priv->mode_switch_err->message);
+		g_error_free (priv->mode_switch_err);
+	}
 
 	G_OBJECT_CLASS (e_book_backend_kolab_parent_class)->finalize (object);
 } /* e_book_backend_kolab_finalize () */
@@ -940,8 +1145,10 @@ e_book_backend_kolab_class_init (EBookBackendKolabClass *klass)
 	sync_class->open_sync = e_book_backend_kolab_open;
 	sync_class->remove_sync = e_book_backend_kolab_remove;
 	sync_class->refresh_sync = e_book_backend_kolab_refresh;
+#if 0 /* probably not needed */
 	sync_class->get_backend_property_sync = e_book_backend_kolab_get_backend_property;
 	sync_class->set_backend_property_sync = e_book_backend_kolab_set_backend_property;
+#endif
 	sync_class->create_contacts_sync = e_book_backend_kolab_create_contacts;
 	sync_class->remove_contacts_sync = e_book_backend_kolab_remove_contacts;
 	sync_class->modify_contacts_sync = e_book_backend_kolab_modify_contacts;
@@ -1053,7 +1260,7 @@ e_book_backend_kolab_set_mode (EBookBackend *backend,
 	}
 
 	if (priv->auth_received == TRUE)
-		tmp_mode = kolab_util_contact_deploy_mode_by_koma (priv->book_koma,
+		tmp_mode = kolab_util_backend_deploy_mode_by_koma (priv->book_koma,
 		                                                   koma_mode);
 	else
 		tmp_mode = KOLAB_MAIL_ACCESS_OPMODE_OFFLINE;



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