[evolution-data-server] Merge duplicated code around EGDataOAuth2Authorizer



commit 34514d58d5387030c073c6c35efcb353204553a0
Author: Milan Crha <mcrha redhat com>
Date:   Tue Nov 21 13:47:14 2017 +0100

    Merge duplicated code around EGDataOAuth2Authorizer

 .../evolution-data-server-docs.sgml.in             |    1 +
 src/addressbook/backends/google/CMakeLists.txt     |    2 -
 .../backends/google/e-book-backend-google.c        |    6 +-
 .../backends/google/e-gdata-oauth2-authorizer.c    |  394 ---------------
 src/calendar/backends/gtasks/CMakeLists.txt        |    2 -
 .../backends/gtasks/e-cal-backend-gtasks.c         |    5 +-
 .../backends/gtasks/e-gdata-oauth2-authorizer.c    |  394 ---------------
 .../backends/gtasks/e-gdata-oauth2-authorizer.h    |   75 ---
 src/libedataserver/CMakeLists.txt                  |    5 +
 src/libedataserver/e-data-server-util.c            |    2 +-
 src/libedataserver/e-gdata-oauth2-authorizer.c     |  527 ++++++++++++++++++++
 .../e-gdata-oauth2-authorizer.h                    |   29 +-
 src/libedataserver/libedataserver.h                |    1 +
 src/modules/google-backend/CMakeLists.txt          |    2 -
 .../google-backend/e-gdata-oauth2-authorizer.c     |  394 ---------------
 .../google-backend/e-gdata-oauth2-authorizer.h     |   74 ---
 src/modules/google-backend/module-google-backend.c |   23 +-
 17 files changed, 565 insertions(+), 1371 deletions(-)
---
diff --git a/docs/reference/evolution-data-server/evolution-data-server-docs.sgml.in 
b/docs/reference/evolution-data-server/evolution-data-server-docs.sgml.in
index 37517ce..9f7861a 100644
--- a/docs/reference/evolution-data-server/evolution-data-server-docs.sgml.in
+++ b/docs/reference/evolution-data-server/evolution-data-server-docs.sgml.in
@@ -227,6 +227,7 @@
       <xi:include href="xml/e-error.xml"/>
       <xi:include href="xml/e-flag.xml"/>
       <xi:include href="xml/e-free-form-exp.xml"/>
+      <xi:include href="xml/e-gdata-oauth2-authorizer.xml"/>
       <xi:include href="xml/e-gdbus-templates.xml"/>
       <xi:include href="xml/e-memory.xml"/>
       <xi:include href="xml/e-network-monitor.xml"/>
diff --git a/src/addressbook/backends/google/CMakeLists.txt b/src/addressbook/backends/google/CMakeLists.txt
index e4d930d..09e2bee 100644
--- a/src/addressbook/backends/google/CMakeLists.txt
+++ b/src/addressbook/backends/google/CMakeLists.txt
@@ -12,8 +12,6 @@ add_library(ebookbackendgoogle MODULE
        e-book-backend-google.h
        e-book-google-utils.c
        e-book-google-utils.h
-       e-gdata-oauth2-authorizer.c
-       e-gdata-oauth2-authorizer.h
 )
 
 add_dependencies(ebookbackendgoogle
diff --git a/src/addressbook/backends/google/e-book-backend-google.c 
b/src/addressbook/backends/google/e-book-backend-google.c
index 645cbb1..2ec0d24 100644
--- a/src/addressbook/backends/google/e-book-backend-google.c
+++ b/src/addressbook/backends/google/e-book-backend-google.c
@@ -28,9 +28,10 @@
 #include <glib/gi18n-lib.h>
 #include <gdata/gdata.h>
 
+#include "libedataserver/libedataserver.h"
+
 #include "e-book-backend-google.h"
 #include "e-book-google-utils.h"
-#include "e-gdata-oauth2-authorizer.h"
 
 #define URI_GET_CONTACTS "https://www.google.com/m8/feeds/contacts/default/full";
 
@@ -168,8 +169,7 @@ ebb_google_request_authorization (EBookBackendGoogle *bbgoogle,
 
                source = e_backend_get_source (E_BACKEND (bbgoogle));
 
-               /* Only OAuth2 is supported with Google Tasks */
-               authorizer = e_gdata_oauth2_authorizer_new (source);
+               authorizer = e_gdata_oauth2_authorizer_new (source, GDATA_TYPE_CONTACTS_SERVICE);
                bbgoogle->priv->authorizer = GDATA_AUTHORIZER (authorizer);
        }
 
diff --git a/src/calendar/backends/gtasks/CMakeLists.txt b/src/calendar/backends/gtasks/CMakeLists.txt
index 38ee19a..4664980 100644
--- a/src/calendar/backends/gtasks/CMakeLists.txt
+++ b/src/calendar/backends/gtasks/CMakeLists.txt
@@ -9,8 +9,6 @@ set(SOURCES
        e-cal-backend-gtasks-factory.c
        e-cal-backend-gtasks.c
        e-cal-backend-gtasks.h
-       e-gdata-oauth2-authorizer.c
-       e-gdata-oauth2-authorizer.h
 )
 
 add_library(ecalbackendgtasks MODULE
diff --git a/src/calendar/backends/gtasks/e-cal-backend-gtasks.c 
b/src/calendar/backends/gtasks/e-cal-backend-gtasks.c
index f8c4d2c..9815242 100644
--- a/src/calendar/backends/gtasks/e-cal-backend-gtasks.c
+++ b/src/calendar/backends/gtasks/e-cal-backend-gtasks.c
@@ -21,7 +21,8 @@
 #include <glib/gi18n-lib.h>
 #include <gdata/gdata.h>
 
-#include "e-gdata-oauth2-authorizer.h"
+#include "libedataserver/libedataserver.h"
+
 #include "e-cal-backend-gtasks.h"
 
 #define d(x)
@@ -281,7 +282,7 @@ ecb_gtasks_request_authorization (ECalBackendGTasks *cbgtasks,
                source = e_backend_get_source (E_BACKEND (cbgtasks));
 
                /* Only OAuth2 is supported with Google Tasks */
-               authorizer = e_gdata_oauth2_authorizer_new (source);
+               authorizer = e_gdata_oauth2_authorizer_new (source, GDATA_TYPE_TASKS_SERVICE);
                cbgtasks->priv->authorizer = GDATA_AUTHORIZER (authorizer);
        }
 
diff --git a/src/libedataserver/CMakeLists.txt b/src/libedataserver/CMakeLists.txt
index d562e84..3a16a57 100644
--- a/src/libedataserver/CMakeLists.txt
+++ b/src/libedataserver/CMakeLists.txt
@@ -57,6 +57,7 @@ set(SOURCES
        e-extension.c
        e-flag.c
        e-free-form-exp.c
+       e-gdata-oauth2-authorizer.c
        e-gdbus-templates.c
        e-iterator.c
        e-list.c
@@ -140,6 +141,7 @@ set(HEADERS
        e-extension.h
        e-flag.h
        e-free-form-exp.h
+       e-gdata-oauth2-authorizer.h
        e-gdbus-templates.h
        e-iterator.h
        e-list.h
@@ -242,6 +244,7 @@ target_compile_options(edataserver PUBLIC
        ${GIO_UNIX_CFLAGS}
        ${ICU_CFLAGS}
        ${GOOGLE_AUTH_CFLAGS}
+       ${LIBGDATA_CFLAGS}
 )
 
 target_include_directories(edataserver PUBLIC
@@ -256,6 +259,7 @@ target_include_directories(edataserver PUBLIC
        ${GIO_UNIX_INCLUDE_DIRS}
        ${ICU_INCLUDE_DIRS}
        ${GOOGLE_AUTH_INCLUDE_DIRS}
+       ${LIBGDATA_INCLUDE_DIRS}
 )
 
 target_link_libraries(edataserver
@@ -265,6 +269,7 @@ target_link_libraries(edataserver
        ${GIO_UNIX_LDFLAGS}
        ${ICU_LDFLAGS}
        ${GOOGLE_AUTH_LDFLAGS}
+       ${LIBGDATA_LDFLAGS}
 )
 
 install(TARGETS edataserver
diff --git a/src/libedataserver/e-data-server-util.c b/src/libedataserver/e-data-server-util.c
index 505ab36..750e18f 100644
--- a/src/libedataserver/e-data-server-util.c
+++ b/src/libedataserver/e-data-server-util.c
@@ -2247,7 +2247,7 @@ e_named_parameters_new_clone (const ENamedParameters *parameters)
 
 /**
  * e_named_parameters_free:
- * @parameters: an #ENamedParameters
+ * @parameters: (nullable): an #ENamedParameters
  *
  * Frees an instance of #ENamedParameters, previously allocated
  * with e_named_parameters_new(). Function does nothing, if
diff --git a/src/libedataserver/e-gdata-oauth2-authorizer.c b/src/libedataserver/e-gdata-oauth2-authorizer.c
new file mode 100644
index 0000000..79ef743
--- /dev/null
+++ b/src/libedataserver/e-gdata-oauth2-authorizer.c
@@ -0,0 +1,527 @@
+/*
+ * e-gdata-oauth2-authorizer.c
+ *
+ * This library 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 Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "evolution-data-server-config.h"
+
+#include <time.h>
+
+#include "e-gdata-oauth2-authorizer.h"
+
+#ifdef HAVE_LIBGDATA
+
+#include <gdata/gdata.h>
+
+#define EXPIRY_INVALID ((time_t) -1)
+
+struct _EGDataOAuth2AuthorizerPrivate {
+       GWeakRef source;
+       GType service_type;
+
+       /* These members are protected by the global mutex. */
+       gchar *access_token;
+       time_t expiry;
+       GHashTable *authorization_domains;
+       ENamedParameters *credentials;
+};
+
+enum {
+       PROP_0,
+       PROP_SERVICE_TYPE,
+       PROP_SOURCE
+};
+
+/* GDataAuthorizer methods must be thread-safe. */
+static GMutex mutex;
+
+/* Forward Declarations */
+static void e_gdata_oauth2_authorizer_interface_init (GDataAuthorizerInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (EGDataOAuth2Authorizer, e_gdata_oauth2_authorizer, G_TYPE_OBJECT,
+       G_IMPLEMENT_INTERFACE (GDATA_TYPE_AUTHORIZER, e_gdata_oauth2_authorizer_interface_init))
+
+static gboolean
+e_gdata_oauth2_authorizer_is_authorized (GDataAuthorizer *authorizer,
+                                        GDataAuthorizationDomain *domain)
+{
+       EGDataOAuth2Authorizer *oauth2_authorizer;
+
+       /* This MUST be called with the mutex already locked. */
+
+       if (!domain)
+               return TRUE;
+
+       oauth2_authorizer = E_GDATA_OAUTH2_AUTHORIZER (authorizer);
+
+       return g_hash_table_contains (oauth2_authorizer->priv->authorization_domains, domain);
+}
+
+static void
+e_gdata_oauth2_authorizer_set_service_type (EGDataOAuth2Authorizer *authorizer,
+                                           GType service_type)
+{
+       g_return_if_fail (service_type != 0);
+
+       authorizer->priv->service_type = service_type;
+}
+
+static void
+e_gdata_oauth2_authorizer_set_source (EGDataOAuth2Authorizer *authorizer,
+                                     ESource *source)
+{
+       g_return_if_fail (E_IS_SOURCE (source));
+
+       g_weak_ref_set (&authorizer->priv->source, source);
+}
+
+static void
+e_gdata_oauth2_authorizer_set_property (GObject *object,
+                                       guint property_id,
+                                       const GValue *value,
+                                       GParamSpec *pspec)
+{
+       switch (property_id) {
+               case PROP_SERVICE_TYPE:
+                       e_gdata_oauth2_authorizer_set_service_type (
+                               E_GDATA_OAUTH2_AUTHORIZER (object),
+                               g_value_get_gtype (value));
+                       return;
+
+               case PROP_SOURCE:
+                       e_gdata_oauth2_authorizer_set_source (
+                               E_GDATA_OAUTH2_AUTHORIZER (object),
+                               g_value_get_object (value));
+                       return;
+       }
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+e_gdata_oauth2_authorizer_get_property (GObject *object,
+                                       guint property_id,
+                                       GValue *value,
+                                       GParamSpec *pspec)
+{
+       switch (property_id) {
+               case PROP_SERVICE_TYPE:
+                       g_value_set_gtype (
+                               value,
+                               e_gdata_oauth2_authorizer_get_service_type (
+                               E_GDATA_OAUTH2_AUTHORIZER (object)));
+                       return;
+
+               case PROP_SOURCE:
+                       g_value_take_object (
+                               value,
+                               e_gdata_oauth2_authorizer_ref_source (
+                               E_GDATA_OAUTH2_AUTHORIZER (object)));
+                       return;
+       }
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+e_gdata_oauth2_authorizer_dispose (GObject *object)
+{
+       EGDataOAuth2Authorizer *oauth2_authorizer;
+
+       oauth2_authorizer = E_GDATA_OAUTH2_AUTHORIZER (object);
+
+       g_weak_ref_set (&oauth2_authorizer->priv->source, NULL);
+
+       g_hash_table_remove_all (oauth2_authorizer->priv->authorization_domains);
+
+       /* Chain up to parent's method. */
+       G_OBJECT_CLASS (e_gdata_oauth2_authorizer_parent_class)->dispose (object);
+}
+
+static void
+e_gdata_oauth2_authorizer_finalize (GObject *object)
+{
+       EGDataOAuth2Authorizer *oauth2_authorizer;
+
+       oauth2_authorizer = E_GDATA_OAUTH2_AUTHORIZER (object);
+
+       g_free (oauth2_authorizer->priv->access_token);
+
+       g_hash_table_destroy (oauth2_authorizer->priv->authorization_domains);
+       g_weak_ref_clear (&oauth2_authorizer->priv->source);
+
+       e_named_parameters_free (oauth2_authorizer->priv->credentials);
+
+       /* Chain up to parent's method. */
+       G_OBJECT_CLASS (e_gdata_oauth2_authorizer_parent_class)->finalize (object);
+}
+
+static void
+e_gdata_oauth2_authorizer_constructed (GObject *object)
+{
+       EGDataOAuth2Authorizer *oauth2_authorizer;
+       GList *domains, *link;
+
+       /* Chain up to parent's method. */
+       G_OBJECT_CLASS (e_gdata_oauth2_authorizer_parent_class)->constructed (object);
+
+       oauth2_authorizer = E_GDATA_OAUTH2_AUTHORIZER (object);
+
+       domains = gdata_service_get_authorization_domains (oauth2_authorizer->priv->service_type);
+       for (link = domains; link; link = g_list_next (link)) {
+               g_hash_table_add (
+                       oauth2_authorizer->priv->authorization_domains,
+                       g_object_ref (domains->data));
+       }
+
+       g_list_free (domains);
+}
+
+static void
+e_gdata_oauth2_authorizer_process_request (GDataAuthorizer *authorizer,
+                                          GDataAuthorizationDomain *domain,
+                                          SoupMessage *message)
+{
+       EGDataOAuth2Authorizer *oauth2_authorizer;
+       gchar *authorization;
+
+       oauth2_authorizer = E_GDATA_OAUTH2_AUTHORIZER (authorizer);
+
+       g_mutex_lock (&mutex);
+
+       if (!e_gdata_oauth2_authorizer_is_authorized (authorizer, domain) ||
+           e_gdata_oauth2_authorizer_is_expired (oauth2_authorizer))
+               goto exit;
+
+       /* We can't add an Authorization header without an access token.
+        * Let the request fail.  GData should refresh us if it gets back
+        * a "401 Authorization required" response from Google, and then
+        * automatically retry the request. */
+       if (!oauth2_authorizer->priv->access_token)
+               goto exit;
+
+       authorization = g_strdup_printf ("OAuth %s", oauth2_authorizer->priv->access_token);
+
+       /* Use replace here, not append, to make sure
+        * there's only one "Authorization" header. */
+       soup_message_headers_replace (
+               message->request_headers,
+               "Authorization", authorization);
+
+       g_free (authorization);
+
+exit:
+       g_mutex_unlock (&mutex);
+}
+
+static gboolean
+e_gdata_oauth2_authorizer_is_authorized_for_domain (GDataAuthorizer *authorizer,
+                                                   GDataAuthorizationDomain *domain)
+{
+       gboolean authorized;
+
+       g_mutex_lock (&mutex);
+
+       authorized = e_gdata_oauth2_authorizer_is_authorized (authorizer, domain);
+
+       g_mutex_unlock (&mutex);
+
+       return authorized;
+}
+
+static gboolean
+e_gdata_oauth2_authorizer_refresh_authorization (GDataAuthorizer *authorizer,
+                                                GCancellable *cancellable,
+                                                GError **error)
+{
+       EGDataOAuth2Authorizer *oauth2_authorizer;
+       ESource *source;
+       gchar *access_token = NULL;
+       gint expires_in_seconds = -1;
+       gboolean success = FALSE;
+
+       oauth2_authorizer = E_GDATA_OAUTH2_AUTHORIZER (authorizer);
+       source = e_gdata_oauth2_authorizer_ref_source (oauth2_authorizer);
+       g_return_val_if_fail (source != NULL, FALSE);
+
+       g_mutex_lock (&mutex);
+
+       success = e_util_get_source_oauth2_access_token_sync (source, oauth2_authorizer->priv->credentials,
+               &access_token, &expires_in_seconds, cancellable, error);
+
+       /* Returned token is the same, thus no refresh happened, thus rather fail. */
+       if (access_token && g_strcmp0 (access_token, oauth2_authorizer->priv->access_token) == 0) {
+               g_free (access_token);
+               access_token = NULL;
+               success = FALSE;
+       }
+
+       g_free (oauth2_authorizer->priv->access_token);
+       oauth2_authorizer->priv->access_token = access_token;
+
+       if (success && expires_in_seconds > 0)
+               oauth2_authorizer->priv->expiry = time (NULL) + expires_in_seconds - 1;
+       else
+               oauth2_authorizer->priv->expiry = EXPIRY_INVALID;
+
+       g_mutex_unlock (&mutex);
+
+       g_object_unref (source);
+
+       return success && access_token;
+}
+
+static void
+e_gdata_oauth2_authorizer_class_init (EGDataOAuth2AuthorizerClass *class)
+{
+       GObjectClass *object_class;
+
+       g_type_class_add_private (class, sizeof (EGDataOAuth2AuthorizerPrivate));
+
+       object_class = G_OBJECT_CLASS (class);
+       object_class->set_property = e_gdata_oauth2_authorizer_set_property;
+       object_class->get_property = e_gdata_oauth2_authorizer_get_property;
+       object_class->dispose = e_gdata_oauth2_authorizer_dispose;
+       object_class->finalize = e_gdata_oauth2_authorizer_finalize;
+       object_class->constructed = e_gdata_oauth2_authorizer_constructed;
+
+       g_object_class_install_property (
+               object_class,
+               PROP_SERVICE_TYPE,
+               g_param_spec_gtype (
+                       "service-type",
+                       "Service Type",
+                       "The service type for which this authorization will be used",
+                       GDATA_TYPE_SERVICE,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT_ONLY |
+                       G_PARAM_STATIC_STRINGS));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_SOURCE,
+               g_param_spec_object (
+                       "source",
+                       "Source",
+                       "The data source to authenticate",
+                       E_TYPE_SOURCE,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT_ONLY |
+                       G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_gdata_oauth2_authorizer_interface_init (GDataAuthorizerInterface *iface)
+{
+       iface->process_request = e_gdata_oauth2_authorizer_process_request;
+       iface->is_authorized_for_domain = e_gdata_oauth2_authorizer_is_authorized_for_domain;
+       iface->refresh_authorization = e_gdata_oauth2_authorizer_refresh_authorization;
+}
+
+static void
+e_gdata_oauth2_authorizer_init (EGDataOAuth2Authorizer *oauth2_authorizer)
+{
+       oauth2_authorizer->priv = G_TYPE_INSTANCE_GET_PRIVATE (oauth2_authorizer, 
E_TYPE_GDATA_OAUTH2_AUTHORIZER, EGDataOAuth2AuthorizerPrivate);
+       oauth2_authorizer->priv->authorization_domains = g_hash_table_new_full (g_direct_hash, 
g_direct_equal, g_object_unref, NULL);
+       oauth2_authorizer->priv->expiry = EXPIRY_INVALID;
+       g_weak_ref_init (&oauth2_authorizer->priv->source, NULL);
+}
+
+#endif /* HAVE_LIBGDATA */
+
+/**
+ * e_gdata_oauth2_authorizer_supported:
+ *
+ * Returns: Whether the #EGDataOAuth2Authorizer is supported, which
+ *    means whether evolution-data-server had been compiled with libgdata.
+ *
+ * Since: 3.28
+ **/
+gboolean
+e_gdata_oauth2_authorizer_supported (void)
+{
+#ifdef HAVE_LIBGDATA
+       return TRUE;
+#else
+       return FALSE;
+#endif
+}
+
+/**
+ * e_gdata_oauth2_authorizer_new:
+ * @source: an #ESource
+ * @service_type: a #GDataService type descendant
+ *
+ * Creates a new #EGDataOAuth2Authorizer for the given @source
+ * and @service_type. The function always returns %NULL when
+ * e_gdata_oauth2_authorizer_supported() returns %FALSE.
+ *
+ * Returns: (transfer full): a new #EGDataOAuth2Authorizer, or %NULL when
+ *    the #EGDataOAuth2Authorizer is not supported.
+ *
+ * Since: 3.28
+ **/
+EGDataOAuth2Authorizer *
+e_gdata_oauth2_authorizer_new (ESource *source,
+                              GType service_type)
+{
+       g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+
+#ifdef HAVE_LIBGDATA
+       return g_object_new (E_TYPE_GDATA_OAUTH2_AUTHORIZER,
+               "service-type", service_type,
+               "source", source,
+               NULL);
+#else
+       return NULL;
+#endif
+}
+
+/**
+ * e_gdata_oauth2_authorizer_ref_source:
+ * @oauth2_authorizer: an #EGDataOAuth2Authorizer
+ *
+ * Returns: (transfer full): an #ESource, for which the @oauth2_authorizer
+ *    had been created, or %NULL. Free returned non-NULL object with g_object_unref(),
+ *    when done with it.
+ *
+ * See: e_gdata_oauth2_authorizer_supported()
+ *
+ * Since: 3.28
+ **/
+ESource *
+e_gdata_oauth2_authorizer_ref_source (EGDataOAuth2Authorizer *oauth2_authorizer)
+{
+#ifdef HAVE_LIBGDATA
+       g_return_val_if_fail (E_IS_GDATA_OAUTH2_AUTHORIZER (oauth2_authorizer), NULL);
+
+       return g_weak_ref_get (&oauth2_authorizer->priv->source);
+#else
+       return NULL;
+#endif
+}
+
+/**
+ * e_gdata_oauth2_authorizer_get_service_type:
+ * @oauth2_authorizer: an #EGDataOAuth2Authorizer
+ *
+ * Returns: a service %GType, for which the @oauth2_authorizer had been created.
+ *
+ * See: e_gdata_oauth2_authorizer_supported()
+ *
+ * Since: 3.28
+ **/
+GType
+e_gdata_oauth2_authorizer_get_service_type (EGDataOAuth2Authorizer *oauth2_authorizer)
+{
+#ifdef HAVE_LIBGDATA
+       g_return_val_if_fail (E_IS_GDATA_OAUTH2_AUTHORIZER (oauth2_authorizer), (GType) 0);
+
+       return oauth2_authorizer->priv->service_type;
+#else
+       return (GType) 0;
+#endif
+}
+
+/**
+ * e_gdata_oauth2_authorizer_set_credentials:
+ * @oauth2_authorizer: an #EGDataOAuth2Authorizer
+ * @credentials: (nullable): credentials to set, or %NULL
+ *
+ * Updates internally stored credentials, used to get access token.
+ *
+ * See: e_gdata_oauth2_authorizer_supported()
+ *
+ * Since: 3.28
+ **/
+void
+e_gdata_oauth2_authorizer_set_credentials (EGDataOAuth2Authorizer *oauth2_authorizer,
+                                          const ENamedParameters *credentials)
+{
+#ifdef HAVE_LIBGDATA
+       g_return_if_fail (E_IS_GDATA_OAUTH2_AUTHORIZER (oauth2_authorizer));
+
+       g_mutex_lock (&mutex);
+
+       e_named_parameters_free (oauth2_authorizer->priv->credentials);
+       if (credentials)
+               oauth2_authorizer->priv->credentials = e_named_parameters_new_clone (credentials);
+       else
+               oauth2_authorizer->priv->credentials = NULL;
+
+       g_free (oauth2_authorizer->priv->access_token);
+       oauth2_authorizer->priv->access_token = NULL;
+
+       oauth2_authorizer->priv->expiry = EXPIRY_INVALID;
+
+       g_mutex_unlock (&mutex);
+#endif
+}
+
+/**
+ * e_gdata_oauth2_authorizer_clone_credentials:
+ * @oauth2_authorizer: an #EGDataOAuth2Authorizer
+ *
+ * Returns: (transfer full) (nullable): A copy of currently stored credentials,
+ *    or %NULL, when none are set. Free the returned structure with
+ *    e_named_parameters_free(), when no longer needed.
+ *
+ * See: e_gdata_oauth2_authorizer_supported()
+ *
+ * Since: 3.28
+ **/
+ENamedParameters *
+e_gdata_oauth2_authorizer_clone_credentials (EGDataOAuth2Authorizer *oauth2_authorizer)
+{
+#ifdef HAVE_LIBGDATA
+       ENamedParameters *credentials = NULL;
+
+       g_return_val_if_fail (E_IS_GDATA_OAUTH2_AUTHORIZER (oauth2_authorizer), NULL);
+
+       g_mutex_lock (&mutex);
+
+       if (oauth2_authorizer->priv->credentials)
+               credentials = e_named_parameters_new_clone (oauth2_authorizer->priv->credentials);
+
+       g_mutex_unlock (&mutex);
+
+       return credentials;
+#else
+       return NULL;
+#endif
+}
+
+/**
+ * e_gdata_oauth2_authorizer_is_expired:
+ * @oauth2_authorizer: an #EGDataOAuth2Authorizer
+ *
+ * Returns: Whether the internally stored token is expired.
+ *
+ * See: e_gdata_oauth2_authorizer_supported()
+ *
+ * Since: 3.28
+ **/
+gboolean
+e_gdata_oauth2_authorizer_is_expired (EGDataOAuth2Authorizer *oauth2_authorizer)
+{
+#ifdef HAVE_LIBGDATA
+       g_return_val_if_fail (E_IS_GDATA_OAUTH2_AUTHORIZER (oauth2_authorizer), TRUE);
+
+       return oauth2_authorizer->priv->expiry == EXPIRY_INVALID ||
+              oauth2_authorizer->priv->expiry <= time (NULL);
+#else
+       return TRUE;
+#endif
+}
diff --git a/src/addressbook/backends/google/e-gdata-oauth2-authorizer.h 
b/src/libedataserver/e-gdata-oauth2-authorizer.h
similarity index 70%
rename from src/addressbook/backends/google/e-gdata-oauth2-authorizer.h
rename to src/libedataserver/e-gdata-oauth2-authorizer.h
index 0dfc582..eef8078 100644
--- a/src/addressbook/backends/google/e-gdata-oauth2-authorizer.h
+++ b/src/libedataserver/e-gdata-oauth2-authorizer.h
@@ -15,11 +15,15 @@
  *
  */
 
+#if !defined (__LIBEDATASERVER_H_INSIDE__) && !defined (LIBEDATASERVER_COMPILATION)
+#error "Only <libedataserver/libedataserver.h> should be included directly."
+#endif
+
 #ifndef E_GDATA_OAUTH2_AUTHORIZER_H
 #define E_GDATA_OAUTH2_AUTHORIZER_H
 
-#include <gdata/gdata.h>
-#include <libedataserver/libedataserver.h>
+#include <libedataserver/e-source.h>
+#include <libedataserver/e-data-server-util.h>
 
 /* Standard GObject macros */
 #define E_TYPE_GDATA_OAUTH2_AUTHORIZER \
@@ -55,21 +59,22 @@ struct _EGDataOAuth2AuthorizerClass {
        GObjectClass parent_class;
 };
 
-GType          e_gdata_oauth2_authorizer_get_type
-                                       (void) G_GNUC_CONST;
+gboolean       e_gdata_oauth2_authorizer_supported     (void);
+GType          e_gdata_oauth2_authorizer_get_type      (void) G_GNUC_CONST;
 EGDataOAuth2Authorizer *
-               e_gdata_oauth2_authorizer_new
-                                       (ESource *source);
-ESource *      e_gdata_oauth2_authorizer_ref_source
-                                       (EGDataOAuth2Authorizer *authorizer);
+               e_gdata_oauth2_authorizer_new           (ESource *source,
+                                                        GType service_type);
+ESource *      e_gdata_oauth2_authorizer_ref_source    (EGDataOAuth2Authorizer *oauth2_authorizer);
+GType          e_gdata_oauth2_authorizer_get_service_type
+                                                       (EGDataOAuth2Authorizer *oauth2_authorizer);
 void           e_gdata_oauth2_authorizer_set_credentials
-                                       (EGDataOAuth2Authorizer *authorizer,
-                                        const ENamedParameters *credentials);
+                                                       (EGDataOAuth2Authorizer *oauth2_authorizer,
+                                                        const ENamedParameters *credentials);
 ENamedParameters *
                e_gdata_oauth2_authorizer_clone_credentials
-                                       (EGDataOAuth2Authorizer *authorizer);
+                                                       (EGDataOAuth2Authorizer *oauth2_authorizer);
+gboolean       e_gdata_oauth2_authorizer_is_expired    (EGDataOAuth2Authorizer *oauth2_authorizer);
 
 G_END_DECLS
 
 #endif /* E_GDATA_OAUTH2_AUTHORIZER_H */
-
diff --git a/src/libedataserver/libedataserver.h b/src/libedataserver/libedataserver.h
index fd95ddd..f3df296 100644
--- a/src/libedataserver/libedataserver.h
+++ b/src/libedataserver/libedataserver.h
@@ -31,6 +31,7 @@
 #include <libedataserver/e-extension.h>
 #include <libedataserver/e-flag.h>
 #include <libedataserver/e-free-form-exp.h>
+#include <libedataserver/e-gdata-oauth2-authorizer.h>
 #include <libedataserver/e-gdbus-templates.h>
 #include <libedataserver/e-iterator.h>
 #include <libedataserver/e-list-iterator.h>
diff --git a/src/modules/google-backend/CMakeLists.txt b/src/modules/google-backend/CMakeLists.txt
index c6b9e7b..7f62505 100644
--- a/src/modules/google-backend/CMakeLists.txt
+++ b/src/modules/google-backend/CMakeLists.txt
@@ -1,8 +1,6 @@
 set(extra_deps)
 if(HAVE_LIBGDATA)
        set(sources
-               e-gdata-oauth2-authorizer.c
-               e-gdata-oauth2-authorizer.h
                module-google-backend.c
        )
 else(HAVE_LIBGDATA)
diff --git a/src/modules/google-backend/module-google-backend.c 
b/src/modules/google-backend/module-google-backend.c
index 2663355..4efa245 100644
--- a/src/modules/google-backend/module-google-backend.c
+++ b/src/modules/google-backend/module-google-backend.c
@@ -20,21 +20,12 @@
 #include <glib/gi18n-lib.h>
 
 #include <libebackend/libebackend.h>
+#include <libedataserver/libedataserver.h>
 
 #ifdef HAVE_LIBGDATA
 #include <gdata/gdata.h>
 #endif
 
-/* This macro was introduced in libgdata 0.11,
- * but we currently only require libgdata 0.10. */
-#ifndef GDATA_CHECK_VERSION
-#define GDATA_CHECK_VERSION(major,minor,micro) 0
-#endif
-
-#if GDATA_CHECK_VERSION(0,15,1)
-#include "e-gdata-oauth2-authorizer.h"
-#endif
-
 /* Standard GObject macros */
 #define E_TYPE_GOOGLE_BACKEND \
        (e_google_backend_get_type ())
@@ -340,7 +331,7 @@ google_remove_unknown_sources_cb (gpointer resource_id,
        }
 }
 
-#if GDATA_CHECK_VERSION(0,15,1)
+#ifdef HAVE_LIBGDATA
 static void
 google_add_task_list (ECollectionBackend *collection,
                      const gchar *resource_id,
@@ -419,7 +410,7 @@ google_add_task_list (ECollectionBackend *collection,
        g_object_unref (server);
        g_free (identity);
 }
-#endif /* GDATA_CHECK_VERSION(0,15,1) */
+#endif /* HAVE_LIBGDATA */
 
 static ESourceAuthenticationResult
 google_backend_authenticate_sync (EBackend *backend,
@@ -439,7 +430,6 @@ google_backend_authenticate_sync (EBackend *backend,
        GList *sources;
        ENamedParameters *credentials_copy = NULL;
        const gchar *calendar_url;
-       GError *local_error = NULL;
 
        g_return_val_if_fail (collection != NULL, E_SOURCE_AUTHENTICATION_ERROR);
 
@@ -494,14 +484,15 @@ google_backend_authenticate_sync (EBackend *backend,
                result = E_SOURCE_AUTHENTICATION_ACCEPTED;
        }
 
-#if GDATA_CHECK_VERSION(0,15,1)
+#ifdef HAVE_LIBGDATA
        if (result == E_SOURCE_AUTHENTICATION_ACCEPTED &&
            e_source_collection_get_calendar_enabled (collection_extension) &&
            (goa_extension || e_source_credentials_google_is_supported ())) {
                EGDataOAuth2Authorizer *authorizer;
                GDataTasksService *tasks_service;
+               GError *local_error = NULL;
 
-               authorizer = e_gdata_oauth2_authorizer_new (e_backend_get_source (backend));
+               authorizer = e_gdata_oauth2_authorizer_new (e_backend_get_source (backend), 
GDATA_TYPE_TASKS_SERVICE);
                e_gdata_oauth2_authorizer_set_credentials (authorizer, credentials);
 
                tasks_service = gdata_tasks_service_new (GDATA_AUTHORIZER (authorizer));
@@ -543,7 +534,7 @@ google_backend_authenticate_sync (EBackend *backend,
                g_clear_object (&authorizer);
                g_clear_error (&local_error);
        }
-#endif /* GDATA_CHECK_VERSION(0,15,1) */
+#endif /* HAVE_LIBGDATA */
 
        if (result == E_SOURCE_AUTHENTICATION_ACCEPTED) {
                ESourceRegistryServer *server;


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