libebackend: Add EOAuth2Support interface.
authorMatthew Barnes <mbarnes@redhat.com>
Fri, 28 Dec 2012 23:21:30 +0000 (18:21 -0500)
committerMatthew Barnes <mbarnes@redhat.com>
Mon, 31 Dec 2012 14:06:20 +0000 (09:06 -0500)
Standard server-side interface to be implemented by E-D-S modules
providing OAuth 2.0 support for ESources.

docs/reference/libebackend/libebackend-docs.xml
docs/reference/libebackend/libebackend-sections.txt
docs/reference/libebackend/libebackend.types
libebackend/Makefile.am
libebackend/e-oauth2-support.c [new file with mode: 0644]
libebackend/e-oauth2-support.h [new file with mode: 0644]
libebackend/libebackend.h

index f63f1ba..972ea6b 100644 (file)
@@ -25,6 +25,7 @@
     <xi:include href="xml/e-authentication-session.xml"/>
     <xi:include href="xml/e-collection-backend.xml"/>
     <xi:include href="xml/e-collection-backend-factory.xml"/>
+    <xi:include href="xml/e-oauth2-support.xml"/>
     <xi:include href="xml/e-server-side-source.xml"/>
     <xi:include href="xml/e-source-registry-server.xml"/>
   </chapter>
index 55caacd..e85990f 100644 (file)
@@ -311,6 +311,22 @@ EModulePrivate
 </SECTION>
 
 <SECTION>
+<FILE>e-oauth2-support</FILE>
+<TITLE>EOAuth2Support</TITLE>
+EOAuth2Support
+EOAuth2SupportInterface
+e_oauth2_support_get_access_token_sync
+e_oauth2_support_get_access_token
+e_oauth2_support_get_access_token_finish
+<SUBSECTION Standard>
+E_OAUTH2_SUPPORT
+E_IS_OAUTH2_SUPPORT
+E_TYPE_OAUTH2_SUPPORT
+E_OAUTH2_SUPPORT_GET_INTERFACE
+e_oauth2_support_get_type
+</SECTION>
+
+<SECTION>
 <FILE>e-offline-listener</FILE>
 <TITLE>EOfflineListener</TITLE>
 EOfflineListenerState
index 43414ef..aeb38dc 100644 (file)
@@ -12,6 +12,7 @@ e_extensible_get_type
 e_extension_get_type
 e_file_cache_get_type
 e_module_get_type
+e_oauth2_support_get_type
 e_offline_listener_get_type
 e_server_side_source_get_type
 e_source_registry_server_get_type
index a8ac830..b6a2685 100644 (file)
@@ -45,6 +45,7 @@ libebackend_1_2_la_SOURCES =          \
        e-dbus-server.c                 \
        e-extensible.c                  \
        e-extension.c                   \
+       e-oauth2-support.c              \
        e-offline-listener.c            \
        e-dbhash.c                      \
        e-db3-utils.c                   \
@@ -88,6 +89,7 @@ libebackendinclude_HEADERS =          \
        e-dbus-server.h                 \
        e-extensible.h                  \
        e-extension.h                   \
+       e-oauth2-support.h              \
        e-offline-listener.h            \
        e-db3-utils.h                   \
        e-dbhash.h                      \
diff --git a/libebackend/e-oauth2-support.c b/libebackend/e-oauth2-support.c
new file mode 100644 (file)
index 0000000..7315404
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * e-oauth2-support.c
+ *
+ * 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 Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program 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 the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+/**
+ * SECTION: e-oauth2-support
+ * @include: libebackend/libebackend.h
+ * @short_description: An interface for OAuth 2.0 support
+ *
+ * Support for OAuth 2.0 access tokens is typically provided through
+ * dynamically loaded modules.  The module will provide an extension
+ * class which implements the #EOAuth2SupportInterface, which can be
+ * plugged into all appropriate #EServerSideSource instances through
+ * e_server_side_source_set_oauth2_support().  Incoming requests for
+ * access tokens are then forwarded to the extension providing OAuth
+ * 2.0 support through e_oauth2_support_get_access_token().
+ **/
+
+#include "e-oauth2-support.h"
+
+typedef struct _AsyncContext AsyncContext;
+
+struct _AsyncContext {
+       ESource *source;
+       gchar *access_token;
+       gint expires_in;
+};
+
+G_DEFINE_INTERFACE (
+       EOAuth2Support,
+       e_oauth2_support,
+       G_TYPE_OBJECT)
+
+static void
+async_context_free (AsyncContext *async_context)
+{
+       if (async_context->source != NULL)
+               g_object_unref (async_context->source);
+
+       g_free (async_context->access_token);
+
+       g_slice_free (AsyncContext, async_context);
+}
+
+/* Helper for oauth2_support_get_access_token() */
+static void
+oauth2_support_get_access_token_thread (GSimpleAsyncResult *simple,
+                                        GObject *object,
+                                        GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       e_oauth2_support_get_access_token_sync (
+               E_OAUTH2_SUPPORT (simple),
+               async_context->source,
+               cancellable,
+               &async_context->access_token,
+               &async_context->expires_in,
+               &error);
+
+       if (error != NULL)
+               g_simple_async_result_take_error (simple, error);
+}
+
+static void
+oauth2_support_get_access_token (EOAuth2Support *support,
+                                 ESource *source,
+                                 GCancellable *cancellable,
+                                 GAsyncReadyCallback callback,
+                                 gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->source = g_object_ref (source);
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (support), callback, user_data,
+               oauth2_support_get_access_token);
+
+       g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, oauth2_support_get_access_token_thread,
+               G_PRIORITY_DEFAULT, cancellable);
+
+       g_object_unref (simple);
+}
+
+static gboolean
+oauth2_support_get_access_token_finish (EOAuth2Support *support,
+                                        GAsyncResult *result,
+                                        gchar **out_access_token,
+                                        gint *out_expires_in,
+                                        GError **error)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (support),
+               oauth2_support_get_access_token), FALSE);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       if (g_simple_async_result_propagate_error (simple, error))
+               return FALSE;
+
+       g_return_val_if_fail (async_context->access_token != NULL, FALSE);
+
+       if (out_access_token != NULL) {
+               *out_access_token = async_context->access_token;
+               async_context->access_token = NULL;
+       }
+
+       if (out_expires_in != NULL)
+               *out_expires_in = async_context->expires_in;
+
+       return TRUE;
+}
+
+static void
+e_oauth2_support_default_init (EOAuth2SupportInterface *interface)
+{
+       interface->get_access_token = oauth2_support_get_access_token;
+       interface->get_access_token_finish = oauth2_support_get_access_token_finish;
+}
+
+/**
+ * e_oauth2_support_get_access_token_sync:
+ * @support: an #EOAuthSupport
+ * @source: an #ESource
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @out_access_token: return location for the access token, or %NULL
+ * @out_expires_in: return location for the token expiry, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Obtains the OAuth 2.0 access token for @source along with its expiry
+ * in seconds from the current time (or 0 if unknown).
+ *
+ * Free the returned access token with g_free() when finished with it.
+ * If an error occurs, the function will set @error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.8
+ **/
+gboolean
+e_oauth2_support_get_access_token_sync (EOAuth2Support *support,
+                                        ESource *source,
+                                        GCancellable *cancellable,
+                                        gchar **out_access_token,
+                                        gint *out_expires_in,
+                                        GError **error)
+{
+       EOAuth2SupportInterface *interface;
+
+       g_return_val_if_fail (E_IS_OAUTH2_SUPPORT (support), FALSE);
+       g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+
+       interface = E_OAUTH2_SUPPORT_GET_INTERFACE (support);
+       g_return_val_if_fail (interface->get_access_token_sync != NULL, FALSE);
+
+       return interface->get_access_token_sync (
+               support, source, cancellable,
+               out_access_token, out_expires_in, error);
+}
+
+/**
+ * e_oauth2_support_get_access_token:
+ * @support: an #EOAuth2Support
+ * @source: an #ESource
+ * @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
+ *
+ * Asynchronously obtains the OAuth 2.0 access token for @source along
+ * with its expiry in seconds from the current time (or 0 if unknown).
+ *
+ * When the operation is finished, @callback will be called.  You can then
+ * call e_oauth2_support_get_access_token_finish() to get the result of the
+ * operation.
+ *
+ * Since: 3.8
+ **/
+void
+e_oauth2_support_get_access_token (EOAuth2Support *support,
+                                   ESource *source,
+                                   GCancellable *cancellable,
+                                   GAsyncReadyCallback callback,
+                                   gpointer user_data)
+{
+       EOAuth2SupportInterface *interface;
+
+       g_return_if_fail (E_IS_OAUTH2_SUPPORT (support));
+       g_return_if_fail (E_IS_SOURCE (source));
+
+       interface = E_OAUTH2_SUPPORT_GET_INTERFACE (support);
+       g_return_if_fail (interface->get_access_token != NULL);
+
+       return interface->get_access_token (
+               support, source, cancellable, callback, user_data);
+}
+
+/**
+ * e_oauth2_support_get_access_token_finish:
+ * @support: an #EOAuth2Support
+ * @result: a #GAsyncResult
+ * @out_access_token: return location for the access token, or %NULL
+ * @out_expires_in: return location for the token expiry, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with e_oauth2_support_get_access_token().
+ *
+ * Free the returned access token with g_free() when finished with it.
+ * If an error occurred, the function will set @error and return %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.8
+ **/
+gboolean
+e_oauth2_support_get_access_token_finish (EOAuth2Support *support,
+                                          GAsyncResult *result,
+                                          gchar **out_access_token,
+                                          gint *out_expires_in,
+                                          GError **error)
+{
+       EOAuth2SupportInterface *interface;
+
+       g_return_val_if_fail (E_IS_OAUTH2_SUPPORT (support), FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+       interface = E_OAUTH2_SUPPORT_GET_INTERFACE (support);
+       g_return_val_if_fail (interface->get_access_token_finish != NULL, FALSE);
+
+       return interface->get_access_token_finish (
+               support, result, out_access_token, out_expires_in, error);
+}
+
diff --git a/libebackend/e-oauth2-support.h b/libebackend/e-oauth2-support.h
new file mode 100644 (file)
index 0000000..82972f0
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * e-oauth2-support.h
+ *
+ * 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 Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program 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 the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#if !defined (__LIBEBACKEND_H_INSIDE__) && !defined (LIBEBACKEND_COMPILATION)
+#error "Only <libebackend/libebackend.h> should be included directly."
+#endif
+
+#ifndef E_OAUTH2_SUPPORT_H
+#define E_OAUTH2_SUPPORT_H
+
+#include <libedataserver/libedataserver.h>
+
+/* Standard GObject macros */
+#define E_TYPE_OAUTH2_SUPPORT \
+       (e_oauth2_support_get_type ())
+#define E_OAUTH2_SUPPORT(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST \
+       ((obj), E_TYPE_OAUTH2_SUPPORT, EOAuth2Support))
+#define E_IS_OAUTH2_SUPPORT(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE \
+       ((obj), E_TYPE_OAUTH2_SUPPORT))
+#define E_OAUTH2_SUPPORT_GET_INTERFACE(obj) \
+       (G_TYPE_INSTANCE_GET_INTERFACE \
+       ((obj), E_TYPE_OAUTH2_SUPPORT, EOAuth2SupportInterface))
+
+G_BEGIN_DECLS
+
+/**
+ * EOAuth2Support:
+ *
+ * Since: 3.8
+ **/
+typedef struct _EOAuth2Support EOAuth2Support;
+typedef struct _EOAuth2SupportInterface EOAuth2SupportInterface;
+
+/**
+ * EOAuth2SupportInterface:
+ *
+ * Since: 3.8
+ **/
+struct _EOAuth2SupportInterface {
+       GTypeInterface parent_interface;
+
+       /* Synchronous I/O Methods */
+       gboolean        (*get_access_token_sync)
+                                               (EOAuth2Support *support,
+                                                ESource *source,
+                                                GCancellable *cancellable,
+                                                gchar **out_access_token,
+                                                gint *out_expires_in,
+                                                GError **error);
+
+       /* Asynchronous I/O Methods (all have defaults) */
+       void            (*get_access_token)     (EOAuth2Support *support,
+                                                ESource *source,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gboolean        (*get_access_token_finish)
+                                               (EOAuth2Support *support,
+                                                GAsyncResult *result,
+                                                gchar **out_access_token,
+                                                gint *out_expires_in,
+                                                GError **error);
+};
+
+GType          e_oauth2_support_get_type       (void) G_GNUC_CONST;
+gboolean       e_oauth2_support_get_access_token_sync
+                                               (EOAuth2Support *support,
+                                                ESource *source,
+                                                GCancellable *cancellable,
+                                                gchar **out_access_token,
+                                                gint *out_expires_in,
+                                                GError **error);
+void           e_oauth2_support_get_access_token
+                                               (EOAuth2Support *support,
+                                                ESource *source,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       e_oauth2_support_get_access_token_finish
+                                               (EOAuth2Support *support,
+                                                GAsyncResult *result,
+                                                gchar **out_access_token,
+                                                gint *out_expires_in,
+                                                GError **error);
+
+G_END_DECLS
+
+#endif /* E_OAUTH2_SUPPORT_H */
+
index b0b9d3d..f7f0157 100644 (file)
@@ -39,6 +39,7 @@
 #include <libebackend/e-extension.h>
 #include <libebackend/e-file-cache.h>
 #include <libebackend/e-module.h>
+#include <libebackend/e-oauth2-support.h>
 #include <libebackend/e-offline-listener.h>
 #include <libebackend/e-server-side-source.h>
 #include <libebackend/e-source-registry-server.h>