[evolution-data-server/libgdata-port] Cleaned up error handling and fixed some attribute bugs in the Google Contacts backend



commit d2872bbe103b43e87d8469513df4f4ec55ea71ef
Author: Philip Withnall <philip tecnocode co uk>
Date:   Sun Jul 19 16:48:31 2009 +0100

    Cleaned up error handling and fixed some attribute bugs in the Google Contacts backend

 .../backends/google/e-book-backend-google.c        |   68 +++++++--
 addressbook/backends/google/google-book.c          |  175 ++++++--------------
 addressbook/backends/google/google-book.h          |   15 --
 addressbook/backends/google/util.c                 |    8 +-
 4 files changed, 111 insertions(+), 155 deletions(-)
---
diff --git a/addressbook/backends/google/e-book-backend-google.c b/addressbook/backends/google/e-book-backend-google.c
index fc0ff61..3a2b962 100644
--- a/addressbook/backends/google/e-book-backend-google.c
+++ b/addressbook/backends/google/e-book-backend-google.c
@@ -1,6 +1,7 @@
 /* e-book-backend-google.c - Google contact backendy.
  *
  * Copyright (C) 2008 Joergen Scheibengruber
+ * Copyright (C) 2009 Philip Withnall
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published by the
@@ -27,6 +28,7 @@
 #include <libedata-book/e-data-book.h>
 #include <libedata-book/e-data-book-view.h>
 #include <libedata-book/e-book-backend-sexp.h>
+#include <gdata/gdata-service.h>
 
 #include "e-book-backend-google.h"
 #include "google-book.h"
@@ -48,7 +50,7 @@ struct _EBookBackendGooglePrivate
 
 gboolean __e_book_backend_google_debug__;
 
-static EBookBackendSyncStatus e_book_backend_status_from_google_book_error (GoogleBookError error_code);
+static EBookBackendSyncStatus e_book_backend_status_from_google_book_error (GError *error);
 
 static EBookBackendSyncStatus
 e_book_backend_google_create_contact (EBookBackendSync 	*backend,
@@ -76,7 +78,7 @@ e_book_backend_google_create_contact (EBookBackendSync 	*backend,
     google_book_add_contact (priv->book, contact, out_contact, &error);
     g_object_unref (contact);
     if (error) {
-	status = e_book_backend_status_from_google_book_error (error->code);
+	status = e_book_backend_status_from_google_book_error (error);
 	__debug__ ("Creating contact failed: %s", error->message);
 	g_clear_error (&error);
 	*out_contact = NULL;
@@ -114,7 +116,7 @@ e_book_backend_google_remove_contacts (EBookBackendSync *backend,
 	google_book_remove_contact (priv->book, uid, &error);
 	if (error) {
 	    /* Only last error will be reported */
-	    status = e_book_backend_status_from_google_book_error (error->code);
+	    status = e_book_backend_status_from_google_book_error (error);
 	    __debug__ ("Deleting contact %s failed: %s", uid, error->message);
 	    g_clear_error (&error);
 	} else {
@@ -154,7 +156,7 @@ e_book_backend_google_modify_contact (EBookBackendSync 	*backend,
     google_book_update_contact (priv->book, contact, out_contact, &error);
     g_object_unref (contact);
     if (error) {
-	status = e_book_backend_status_from_google_book_error (error->code);
+	status = e_book_backend_status_from_google_book_error (error);
 	__debug__ ("Modifying contact failed: %s", error->message);
 	g_clear_error (&error);
 	*out_contact = NULL;
@@ -181,7 +183,7 @@ e_book_backend_google_get_contact (EBookBackendSync 	*backend,
 
     contact = google_book_get_contact (priv->book, uid, &error);
     if (error) {
-	status = e_book_backend_status_from_google_book_error (error->code);
+	status = e_book_backend_status_from_google_book_error (error);
 	__debug__ ("Getting contact with uid %s failed: %s", uid, error->message);
 	g_clear_error (&error);
 	return status;
@@ -212,7 +214,7 @@ e_book_backend_google_get_contact_list (EBookBackendSync *backend,
 
     all_contacts = google_book_get_all_contacts (priv->book, &error);
     if (error) {
-	status = e_book_backend_status_from_google_book_error (error->code);
+	status = e_book_backend_status_from_google_book_error (error);
 	__debug__ ("Getting all contacts failed: %s", error->message);
 	g_clear_error (&error);
 	return status;
@@ -283,9 +285,8 @@ on_google_book_sequence_complete (GoogleBook *book, GError *error, gpointer user
 
     priv = GET_PRIVATE (user_data);
     if (error) {
-	status = e_book_backend_status_from_google_book_error (error->code);
+	status = e_book_backend_status_from_google_book_error (error);
 	__debug__ ("Book-view query failed: %s", error->message);
-	status = e_book_backend_status_from_google_book_error (error->code);
 	g_clear_error (&error);
     }
     for (iter = priv->bookviews; iter; iter = iter->next) {
@@ -378,9 +379,8 @@ e_book_backend_google_authenticate_user (EBookBackendSync *backend,
 
     google_book_connect_to_google (priv->book, password, &error);
     if (error) {
-	status = e_book_backend_status_from_google_book_error (error->code);
+	status = e_book_backend_status_from_google_book_error (error);
 	__debug__ ("Authentication failed: %s", error->message);
-	status = e_book_backend_status_from_google_book_error (error->code);
 	g_clear_error (&error);
     } else {
 	e_book_backend_notify_writable (E_BOOK_BACKEND (backend), TRUE);
@@ -686,8 +686,54 @@ e_book_backend_google_new (void)
 }
 
 static EBookBackendSyncStatus
-e_book_backend_status_from_google_book_error (GoogleBookError error_code)
+e_book_backend_status_from_google_book_error (GError *error)
 {
+    if (!error)
+        return GNOME_Evolution_Addressbook_Success;
+
+    if (error->domain == GDATA_AUTHENTICATION_ERROR) {
+        /* Authentication errors */
+        switch (error->code) {
+        case GDATA_AUTHENTICATION_ERROR_BAD_AUTHENTICATION:
+            return GNOME_Evolution_Addressbook_AuthenticationFailed;
+        case GDATA_AUTHENTICATION_ERROR_NOT_VERIFIED:
+        case GDATA_AUTHENTICATION_ERROR_TERMS_NOT_AGREED:
+        case GDATA_AUTHENTICATION_ERROR_CAPTCHA_REQUIRED:
+        case GDATA_AUTHENTICATION_ERROR_ACCOUNT_DELETED:
+        case GDATA_AUTHENTICATION_ERROR_ACCOUNT_DISABLED:
+            return GNOME_Evolution_Addressbook_PermissionDenied;
+        case GDATA_AUTHENTICATION_ERROR_SERVICE_DISABLED:
+            return GNOME_Evolution_Addressbook_RepositoryOffline;
+        default:
+            return GNOME_Evolution_Addressbook_OtherError;
+        }
+    } else if (error->domain == GDATA_SERVICE_ERROR) {
+        /* General service errors */
+        switch (error->code) {
+        case GDATA_SERVICE_ERROR_UNAVAILABLE:
+            return GNOME_Evolution_Addressbook_RepositoryOffline;
+        case GDATA_SERVICE_ERROR_PROTOCOL_ERROR:
+            return GNOME_Evolution_Addressbook_InvalidQuery;
+        case GDATA_SERVICE_ERROR_ENTRY_ALREADY_INSERTED:
+            return GNOME_Evolution_Addressbook_ContactIdAlreadyExists;
+        case GDATA_SERVICE_ERROR_AUTHENTICATION_REQUIRED:
+            return GNOME_Evolution_Addressbook_AuthenticationRequired;
+        case GDATA_SERVICE_ERROR_NOT_FOUND:
+            return GNOME_Evolution_Addressbook_ContactNotFound;
+        case GDATA_SERVICE_ERROR_CONFLICT:
+            return GNOME_Evolution_Addressbook_ContactIdAlreadyExists;
+        case GDATA_SERVICE_ERROR_FORBIDDEN:
+            return GNOME_Evolution_Addressbook_QueryRefused;
+        case GDATA_SERVICE_ERROR_WITH_QUERY:
+        case GDATA_SERVICE_ERROR_WITH_INSERTION:
+        case GDATA_SERVICE_ERROR_WITH_UPDATE:
+        case GDATA_SERVICE_ERROR_WITH_DELETION:
+            return GNOME_Evolution_Addressbook_InvalidQuery;
+        default:
+            return GNOME_Evolution_Addressbook_OtherError;
+        }
+    }
+
     return GNOME_Evolution_Addressbook_OtherError;
 }
 
diff --git a/addressbook/backends/google/google-book.c b/addressbook/backends/google/google-book.c
index 1dd5160..b23f038 100644
--- a/addressbook/backends/google/google-book.c
+++ b/addressbook/backends/google/google-book.c
@@ -26,6 +26,7 @@
 #include <libedataserver/e-proxy.h>
 #include <gdata/gdata-service.h>
 #include <gdata/services/contacts/gdata-contacts-service.h>
+#include <gdata/services/contacts/gdata-contacts-query.h>
 #include <gdata/services/contacts/gdata-contacts-contact.h>
 
 #include "util.h"
@@ -101,11 +102,6 @@ google_book_get_new_contacts_in_chunks (GoogleBook *book,
                                         GError    **error);
 
 static void
-google_book_error_from_soup_error      (GError *soup_error,
-                                        GError **error,
-                                        const char *message);
-
-static void
 google_book_cache_init (GoogleBook *book, gboolean on_disk)
 {
     GoogleBookPrivate *priv = GET_PRIVATE (book);
@@ -284,9 +280,8 @@ google_book_cache_get_last_update (GoogleBook *book)
     case ON_DISK_CACHE:
         return e_book_backend_cache_get_time (priv->cache.on_disk);
     case IN_MEMORY_CACHE:
-        if (priv->cache.in_memory.contacts) {
+        if (priv->cache.in_memory.contacts)
             return g_time_val_to_iso8601 (&priv->cache.in_memory.last_updated);
-        }
         break;
     case NO_CACHE:
     default:
@@ -762,7 +757,6 @@ google_book_connect_to_google (GoogleBook *book, const char *password, GError **
 {
     GoogleBookPrivate *priv;
     GDataService *service;
-    GError *soup_error = NULL;
 
     __debug__ (G_STRFUNC);
     g_return_val_if_fail (IS_GOOGLE_BOOK (book), FALSE);
@@ -782,11 +776,7 @@ google_book_connect_to_google (GoogleBook *book, const char *password, GError **
     proxy_settings_changed (priv->proxy, priv);
     priv->service = NULL;
 
-    gdata_service_authenticate (service, priv->username, password, NULL, &soup_error);
-
-    if (soup_error) {
-        google_book_error_from_soup_error (soup_error, error,
-                                           "Connecting to Google failed");
+    if (!gdata_service_authenticate (service, priv->username, password, NULL, error)) {
         priv->service = NULL;
         g_object_unref (service);
         g_object_unref (priv->proxy);
@@ -839,7 +829,6 @@ google_book_add_contact (GoogleBook *book,
     GoogleBookPrivate *priv;
     GDataEntry *entry, *new_entry;
     gchar *xml;
-    GError *soup_error = NULL;
 
     *out_contact = NULL;
 
@@ -856,16 +845,12 @@ google_book_add_contact (GoogleBook *book,
     g_free (xml);
 
     new_entry = GDATA_ENTRY (gdata_contacts_service_insert_contact (GDATA_CONTACTS_SERVICE (priv->service), GDATA_CONTACTS_CONTACT (entry),
-    								    NULL, &soup_error));
+                                                                    NULL, error));
     g_object_unref (entry);
-    if (soup_error) {
-        google_book_error_from_soup_error (soup_error, error,
-                                           "Adding entry failed");
+    if (!new_entry)
         return FALSE;
-    }
 
     *out_contact = google_book_cache_add_contact (book, new_entry);
-
     g_object_unref (new_entry);
 
     return TRUE;
@@ -879,7 +864,6 @@ google_book_update_contact (GoogleBook *book,
 {
     GoogleBookPrivate *priv;
     GDataEntry *entry, *new_entry;
-    GError *soup_error = NULL;
     EContact *cached_contact;
     gchar *xml;
     const char *uid;
@@ -899,9 +883,9 @@ google_book_update_contact (GoogleBook *book,
     cached_contact = google_book_cache_get_contact (book, uid, &entry);
     if (NULL == cached_contact) {
         g_set_error (error,
-                    GOOGLE_BOOK_ERROR,
-                    GOOGLE_BOOK_ERROR_CONTACT_NOT_FOUND,
-                    "Contact with uid %s not found in cache.", uid);
+                     GDATA_SERVICE_ERROR,
+                     GDATA_SERVICE_ERROR_NOT_FOUND,
+                     "Contact with uid %s not found in cache.", uid);
         return FALSE;
     }
     g_object_unref (cached_contact);
@@ -912,14 +896,11 @@ google_book_update_contact (GoogleBook *book,
     g_free (xml);
 
     new_entry = GDATA_ENTRY (gdata_contacts_service_update_contact (GDATA_CONTACTS_SERVICE (priv->service), GDATA_CONTACTS_CONTACT (entry),
-    								    NULL, &soup_error));
+                                                                    NULL, error));
     g_object_unref (entry);
 
-    if (soup_error) {
-        google_book_error_from_soup_error (soup_error, error,
-                                           "Updating entry failed");
+    if (!new_entry)
         return FALSE;
-    }
 
     xml = NULL;
     if (new_entry)
@@ -928,7 +909,6 @@ google_book_update_contact (GoogleBook *book,
     g_free (xml);
 
     *out_contact = google_book_cache_add_contact (book, new_entry);
-
     g_object_unref (new_entry);
 
     return TRUE;
@@ -939,8 +919,8 @@ google_book_remove_contact (GoogleBook *book, const char *uid, GError **error)
 {
     GoogleBookPrivate *priv;
     GDataEntry *entry = NULL;
-    GError *soup_error = NULL;
     EContact *cached_contact;
+    gboolean success;
 
     __debug__ (G_STRFUNC);
     g_return_val_if_fail (IS_GOOGLE_BOOK (book), FALSE);
@@ -951,25 +931,16 @@ google_book_remove_contact (GoogleBook *book, const char *uid, GError **error)
 
     cached_contact = google_book_cache_get_contact (book, uid, &entry);
     if (NULL == cached_contact) {
-        g_set_error (error,
-                    GOOGLE_BOOK_ERROR,
-                    GOOGLE_BOOK_ERROR_CONTACT_NOT_FOUND,
-                    "Contact with uid %s not found in cache.", uid);
+        g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_NOT_FOUND, "Contact with uid %s not found in cache.", uid);
         return FALSE;
     }
 
     google_book_cache_remove_contact (book, uid);
-    gdata_service_delete_entry (GDATA_SERVICE (priv->service), entry, NULL, &soup_error);
+    success = gdata_service_delete_entry (GDATA_SERVICE (priv->service), entry, NULL, error);
     g_object_unref (entry);
     g_object_unref (cached_contact);
 
-    if (soup_error) {
-        google_book_error_from_soup_error (soup_error, error,
-                                           "Removing entry failed");
-        return FALSE;
-    }
-
-    return TRUE;
+    return success;
 }
 
 static void
@@ -1038,10 +1009,13 @@ google_book_get_new_contacts_in_chunks (GoogleBook *book,
                                         GError    **error)
 {
     GoogleBookPrivate *priv;
-    int start_index = 1;
+    GDataFeed *feed;
+    GDataQuery *query;
     char *last_updated;
     GError *our_error = NULL;
     gboolean rv = TRUE;
+    GTimeVal current_time;
+    int results;
 
     priv = GET_PRIVATE (book);
 
@@ -1052,29 +1026,24 @@ google_book_get_new_contacts_in_chunks (GoogleBook *book,
 
     google_book_cache_freeze (book);
 
-    while (start_index > 0) {
-        GDataFeed *feed;
+    /* Build our query */
+    query = GDATA_QUERY (gdata_contacts_query_new_with_limits (NULL, 1, chunk_size));
+    if (last_updated) {
+        GTimeVal updated;
+
+        g_assert (g_time_val_from_iso8601 (last_updated, &updated) == TRUE);
+        gdata_query_set_updated_min (query, &updated);
+        gdata_contacts_query_set_show_deleted (GDATA_CONTACTS_QUERY (query), TRUE);
+    }
+
+    /* Get the paginated results */
+    do {
         GList *entries;
-        GString *uri;
-        int results;
-        GError *soup_error = NULL;
-
-        /* TODO: Convert to GDataQuery */
-        uri = g_string_new (priv->base_uri);
-        g_string_append_printf (uri, "?max-results=%d&start-index=%d",
-                                chunk_size, start_index);
-        if (last_updated) {
-            g_string_append_printf (uri, "&updated-min=%s&showdeleted=true",
-                                    last_updated);
-        }
 
-        __debug__ ("URI is '%s'", uri->str);
-        feed = gdata_service_query (priv->service, uri->str, NULL, GDATA_TYPE_CONTACTS_CONTACT, NULL, NULL, NULL, &soup_error);
-        g_string_free (uri, TRUE);
+        /* Run the query */
+        feed = gdata_contacts_service_query_contacts (GDATA_CONTACTS_SERVICE (priv->service), query, NULL, NULL, NULL, &our_error);
 
-        if (soup_error) {
-            google_book_error_from_soup_error (soup_error, &our_error,
-                                               "Downloading feed failed");
+        if (our_error) {
             google_book_emit_sequence_complete (book, our_error);
             g_propagate_error (error, our_error);
 
@@ -1086,24 +1055,22 @@ google_book_get_new_contacts_in_chunks (GoogleBook *book,
         results = entries ? g_list_length (entries) : 0;
         __debug__ ("Feed has %d entries", results);
 
-        if (last_updated) {
+        /* Process the entries from this page */
+        if (last_updated)
             g_list_foreach (entries, process_subsequent_entry, book);
-        } else {
+        else
             g_list_foreach (entries, process_initial_entry, book);
-        }
+        g_object_unref (feed);
 
-        if (results == chunk_size) {
-            start_index += results;
-        } else {
-            GTimeVal current_time;
+        /* Move to the next page */
+        gdata_query_next_page (query);
+    } while (results == chunk_size);
+
+    /* Finish updating the cache */
+    g_get_current_time (&current_time);
+    google_book_cache_set_last_update (book, &current_time);
+    google_book_emit_sequence_complete (book, NULL);
 
-            start_index = -1;
-            g_get_current_time (&current_time);
-            google_book_cache_set_last_update (book, &current_time);
-            google_book_emit_sequence_complete (book, NULL);
-        }
-        g_object_unref (feed);
-    }
 out:
     g_free (last_updated);
     google_book_cache_thaw (book);
@@ -1136,12 +1103,8 @@ google_book_get_contact (GoogleBook *book,
         }
         return contact;
     } else {
-        if (NULL == *error) {
-            g_set_error (error,
-                        GOOGLE_BOOK_ERROR,
-                        GOOGLE_BOOK_ERROR_CONTACT_NOT_FOUND,
-                        "Contact with uid %s not found in cache.", uid);
-        }
+        if (NULL == *error)
+            g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_NOT_FOUND, "Contact with uid %s not found in cache.", uid);
     }
     return NULL;
 }
@@ -1235,47 +1198,3 @@ google_book_set_live_mode (GoogleBook *book, gboolean live_mode)
         google_book_cache_refresh_if_needed (book, NULL);
     }
 }
-
-static void
-google_book_error_from_soup_error (GError     *soup_error,
-                                   GError    **error,
-                                   const char *message)
-{
-    GoogleBookError code;
-
-    g_assert (soup_error);
-
-    /* TODO: Convert this to deal with libgdata codes */
-    if (soup_error->code < 100) {
-        code = GOOGLE_BOOK_ERROR_NETWORK_ERROR;
-    } else
-    if (soup_error->code == 200) {
-        code = GOOGLE_BOOK_ERROR_NONE;
-    } else
-    if (soup_error->code == 400) {
-        code = GOOGLE_BOOK_ERROR_INVALID_CONTACT;
-    } else
-    if (soup_error->code == 401) {
-        code = GOOGLE_BOOK_ERROR_AUTH_REQUIRED;
-    } else
-    if (soup_error->code == 403) {
-        code = GOOGLE_BOOK_ERROR_AUTH_FAILED;
-    } else
-    if (soup_error->code == 404) {
-        code = GOOGLE_BOOK_ERROR_CONTACT_NOT_FOUND;
-    } else
-    if (soup_error->code == 409) {
-        code = GOOGLE_BOOK_ERROR_CONFLICT;
-    } else {
-        code = GOOGLE_BOOK_ERROR_HTTP_ERROR;
-    }
-    g_set_error (error,
-                GOOGLE_BOOK_ERROR,
-                GOOGLE_BOOK_ERROR_HTTP_ERROR,
-                "%s due to '%s' (HTTP code %d)",
-                message ? message : "Action failed",
-                soup_error->message,
-                soup_error->code);
-    g_clear_error (&soup_error);
-}
-
diff --git a/addressbook/backends/google/google-book.h b/addressbook/backends/google/google-book.h
index 0d390ae..6accbb4 100644
--- a/addressbook/backends/google/google-book.h
+++ b/addressbook/backends/google/google-book.h
@@ -45,7 +45,6 @@ G_BEGIN_DECLS
 
 typedef struct _GoogleBook      GoogleBook;
 typedef struct _GoogleBookClass GoogleBookClass;
-typedef enum   _GoogleBookError GoogleBookError;
 
 struct _GoogleBook
 {
@@ -64,20 +63,6 @@ struct _GoogleBookClass
     void (*auth_required) (void);
 };
 
-enum _GoogleBookError
-{
-    GOOGLE_BOOK_ERROR_NONE,
-    GOOGLE_BOOK_ERROR_CONTACT_NOT_FOUND,
-    GOOGLE_BOOK_ERROR_INVALID_CONTACT,
-    GOOGLE_BOOK_ERROR_CONFLICT,
-    GOOGLE_BOOK_ERROR_AUTH_FAILED,
-    GOOGLE_BOOK_ERROR_AUTH_REQUIRED,
-    GOOGLE_BOOK_ERROR_NETWORK_ERROR,
-    GOOGLE_BOOK_ERROR_HTTP_ERROR
-};
-
-#define GOOGLE_BOOK_ERROR (g_quark_from_string ("GoogleBookError"))
-
 typedef void (*GoogleBookContactRetrievedCallback) (EContact *contact, gpointer user_data);
 
 GType google_book_get_type (void);
diff --git a/addressbook/backends/google/util.c b/addressbook/backends/google/util.c
index bddd440..7696f99 100644
--- a/addressbook/backends/google/util.c
+++ b/addressbook/backends/google/util.c
@@ -101,6 +101,12 @@ _gdata_entry_update_from_e_contact (GDataEntry *entry,
         e_contact_name_free (name);
     }
 
+    /* Clear out all the old attributes */
+    gdata_contacts_contact_remove_all_email_addresses (GDATA_CONTACTS_CONTACT (entry));
+    gdata_contacts_contact_remove_all_phone_numbers (GDATA_CONTACTS_CONTACT (entry));
+    gdata_contacts_contact_remove_all_postal_addresses (GDATA_CONTACTS_CONTACT (entry));
+    gdata_contacts_contact_remove_all_im_addresses (GDATA_CONTACTS_CONTACT (entry));
+
     /* We walk them in reverse order, so we can find
      * the correct primaries */
     iter = g_list_last (attributes);
@@ -158,7 +164,7 @@ _gdata_entry_update_from_e_contact (GDataEntry *entry,
                         (attr, &have_im_primary);
             if (im)
                 gdata_contacts_contact_add_im_address (GDATA_CONTACTS_CONTACT (entry), im);
-        } else if (e_vcard_attribute_is_single_valued (attr)) {
+        } else if (e_vcard_attribute_is_single_valued (attr) && g_ascii_strcasecmp (name, "X-MOZILLA-HTML") != 0) {
             gchar *value;
 
             /* Add the attribute as an extended property */



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