[evolution-data-server] google: Add EGDataOAuth2Authorizer.



commit 79f3c3ff3206511ed0a6e9245a6fabd2b5310945
Author: Matthew Barnes <mbarnes redhat com>
Date:   Sun Dec 30 22:12:19 2012 -0500

    google: Add EGDataOAuth2Authorizer.
    
    This will eventually replace EGDataGoaAuthorizer once we require
    GNOME Online Accounts 3.8.  It obtains an OAuth 2.0 access token
    using e_source_get_oauth2_access_token_sync() and avoid a direct
    dependency on GNOME Online Accounts (or similar frameworks).
    
    E-D-S 3.8 will still support older versions of GNOME Online Accounts,
    which use OAuth 1.0a for Google authentication.  So the earliest that
    EGDataGoaAuthorizer will die is E-D-S 3.9.1.

 addressbook/backends/google/Makefile.am            |    2 +
 .../backends/google/e-book-backend-google.c        |   32 ++-
 .../backends/google/e-gdata-goa-authorizer.c       |  109 +------
 .../backends/google/e-gdata-oauth2-authorizer.c    |  325 ++++++++++++++++++++
 .../backends/google/e-gdata-oauth2-authorizer.h    |   70 +++++
 5 files changed, 442 insertions(+), 96 deletions(-)
---
diff --git a/addressbook/backends/google/Makefile.am b/addressbook/backends/google/Makefile.am
index 03dc659..5da07b1 100644
--- a/addressbook/backends/google/Makefile.am
+++ b/addressbook/backends/google/Makefile.am
@@ -29,6 +29,8 @@ libebookbackendgoogle_la_SOURCES = \
 	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 \
 	$(GOA_SOURCES)
 
 libebookbackendgoogle_la_LIBADD = \
diff --git a/addressbook/backends/google/e-book-backend-google.c b/addressbook/backends/google/e-book-backend-google.c
index e8610d3..7de0702 100644
--- a/addressbook/backends/google/e-book-backend-google.c
+++ b/addressbook/backends/google/e-book-backend-google.c
@@ -30,6 +30,7 @@
 
 #include "e-book-backend-google.h"
 #include "e-book-google-utils.h"
+#include "e-gdata-oauth2-authorizer.h"
 
 #ifdef HAVE_GOA
 #include "e-gdata-goa-authorizer.h"
@@ -960,9 +961,34 @@ request_authorization (EBookBackend *backend,
 	/* Make sure we have the GDataService configured
 	 * before requesting authorization. */
 
+	if (priv->authorizer == NULL) {
+		ESource *source;
+		ESourceAuthentication *extension;
+		EGDataOAuth2Authorizer *authorizer;
+		const gchar *extension_name;
+		gchar *method;
+
+		extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+		source = e_backend_get_source (E_BACKEND (backend));
+		extension = e_source_get_extension (source, extension_name);
+		method = e_source_authentication_dup_method (extension);
+
+		if (g_strcmp0 (method, "OAuth2") == 0) {
+			authorizer = e_gdata_oauth2_authorizer_new (source);
+			priv->authorizer = GDATA_AUTHORIZER (authorizer);
+		}
+
+		g_free (method);
+	}
+
 #ifdef HAVE_GOA
 	/* If this is associated with a GNOME Online Account,
-	 * use OAuth authentication instead of ClientLogin. */
+	 * use OAuth 1.0a authentication instead of ClientLogin.
+	 *
+	 * XXX GNOME Online Accounts 3.8 switched its Google provider
+	 *     from OAuth 1.0a to OAuth 2.0.  Once we require GOA 3.8
+	 *     we can drop this and keep direct GOA usage confined to
+	 *     the "gnome-online-accounts" module. */
 	if (priv->authorizer == NULL) {
 		EGDataGoaAuthorizer *authorizer;
 		GoaObject *goa_object;
@@ -993,13 +1019,11 @@ request_authorization (EBookBackend *backend,
 		proxy_settings_changed (priv->proxy, backend);
 	}
 
-#ifdef HAVE_GOA
 	/* If we're using OAuth tokens, then as far as the backend
 	 * is concerned it's always authorized.  The GDataAuthorizer
 	 * will take care of everything in the background. */
-	if (E_IS_GDATA_GOA_AUTHORIZER (priv->authorizer))
+	if (!GDATA_IS_CLIENT_LOGIN_AUTHORIZER (priv->authorizer))
 		return TRUE;
-#endif
 
 	/* Otherwise it's up to us to obtain a login secret. */
 	return e_backend_authenticate_sync (
diff --git a/addressbook/backends/google/e-gdata-goa-authorizer.c b/addressbook/backends/google/e-gdata-goa-authorizer.c
index 74a6059..31e2a42 100644
--- a/addressbook/backends/google/e-gdata-goa-authorizer.c
+++ b/addressbook/backends/google/e-gdata-goa-authorizer.c
@@ -58,11 +58,11 @@ G_DEFINE_TYPE_WITH_CODE (
 		e_gdata_goa_authorizer_interface_init))
 
 static GHashTable *
-gdata_goa_authorizer_get_oauth1_parameters (SoupMessage *message,
-                                            const gchar *consumer_key,
-                                            const gchar *consumer_secret,
-                                            const gchar *access_token,
-                                            const gchar *access_token_secret)
+gdata_goa_authorizer_get_oauth_parameters (SoupMessage *message,
+                                           const gchar *consumer_key,
+                                           const gchar *consumer_secret,
+                                           const gchar *access_token,
+                                           const gchar *access_token_secret)
 {
 	GString *query;
 	GString *base_string;
@@ -202,8 +202,8 @@ gdata_goa_authorizer_get_oauth1_parameters (SoupMessage *message,
 }
 
 static void
-gdata_goa_authorizer_add_oauth1_authorization (GDataAuthorizer *authorizer,
-                                               SoupMessage *message)
+gdata_goa_authorizer_add_authorization (GDataAuthorizer *authorizer,
+                                        SoupMessage *message)
 {
 	EGDataGoaAuthorizerPrivate *priv;
 	GoaOAuthBased *goa_oauth_based;
@@ -235,11 +235,12 @@ gdata_goa_authorizer_add_oauth1_authorization (GDataAuthorizer *authorizer,
 		return;
 
 	goa_oauth_based = goa_object_get_oauth_based (priv->goa_object);
+	g_return_if_fail (goa_oauth_based != NULL);
 
 	consumer_key = goa_oauth_based_get_consumer_key (goa_oauth_based);
 	consumer_secret = goa_oauth_based_get_consumer_secret (goa_oauth_based);
 
-	parameters = gdata_goa_authorizer_get_oauth1_parameters (
+	parameters = gdata_goa_authorizer_get_oauth_parameters (
 		message,
 		consumer_key,
 		consumer_secret,
@@ -277,56 +278,6 @@ gdata_goa_authorizer_add_oauth1_authorization (GDataAuthorizer *authorizer,
 	g_object_unref (goa_oauth_based);
 }
 
-static void
-gdata_goa_authorizer_add_oauth2_authorization (GDataAuthorizer *authorizer,
-                                               SoupMessage *message)
-{
-	EGDataGoaAuthorizerPrivate *priv;
-	GString *authorization;
-
-	/* This MUST be called with the mutex already locked. */
-
-	priv = E_GDATA_GOA_AUTHORIZER_GET_PRIVATE (authorizer);
-
-	/* 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 (priv->access_token == NULL)
-		return;
-
-	authorization = g_string_new ("OAuth ");
-	g_string_append (authorization, 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->str);
-
-	g_string_free (authorization, TRUE);
-}
-
-static void
-gdata_goa_authorizer_add_authorization (GDataAuthorizer *authorizer,
-                                        SoupMessage *message)
-{
-	EGDataGoaAuthorizerPrivate *priv;
-
-	/* This MUST be called with the mutex already locked. */
-
-	priv = E_GDATA_GOA_AUTHORIZER_GET_PRIVATE (authorizer);
-
-	/* Prefer OAuth 2.0 over OAuth 1.0. */
-	if (goa_object_peek_oauth2_based (priv->goa_object) != NULL) {
-		gdata_goa_authorizer_add_oauth2_authorization (
-			authorizer, message);
-	} else if (goa_object_peek_oauth_based (priv->goa_object) != NULL) {
-		gdata_goa_authorizer_add_oauth1_authorization (
-			authorizer, message);
-	}
-}
-
 static gboolean
 gdata_goa_authorizer_is_authorized (GDataAuthorizer *authorizer,
                                     GDataAuthorizationDomain *domain)
@@ -489,12 +440,13 @@ gdata_goa_authorizer_refresh_authorization (GDataAuthorizer *authorizer,
 {
 	EGDataGoaAuthorizerPrivate *priv;
 	GoaOAuthBased *goa_oauth_based;
-	GoaOAuth2Based *goa_oauth2_based;
-	GoaAccount *goa_account;
 	gboolean success = FALSE;
 
 	priv = E_GDATA_GOA_AUTHORIZER_GET_PRIVATE (authorizer);
 
+	goa_oauth_based = goa_object_get_oauth_based (priv->goa_object);
+	g_return_val_if_fail (goa_oauth_based != NULL, FALSE);
+
 	g_mutex_lock (&mutex);
 
 	g_free (priv->access_token);
@@ -503,41 +455,14 @@ gdata_goa_authorizer_refresh_authorization (GDataAuthorizer *authorizer,
 	g_free (priv->access_token_secret);
 	priv->access_token_secret = NULL;
 
-	goa_account = goa_object_get_account (priv->goa_object);
-	goa_oauth_based = goa_object_get_oauth_based (priv->goa_object);
-	goa_oauth2_based = goa_object_get_oauth2_based (priv->goa_object);
-
-	success = goa_account_call_ensure_credentials_sync (
-		goa_account, NULL, cancellable, error);
-
-	if (!success)
-		goto exit;
-
-	/* Prefer OAuth 2.0 over OAuth 1.0. */
-	if (goa_oauth2_based != NULL) {
-		success = goa_oauth2_based_call_get_access_token_sync (
-			goa_oauth2_based, &priv->access_token,
-			NULL, cancellable, error);
-	} else if (goa_oauth_based != NULL) {
-		success = goa_oauth_based_call_get_access_token_sync (
-			goa_oauth_based, &priv->access_token,
-			&priv->access_token_secret, NULL, cancellable, error);
-	} else {
-		g_warn_if_reached ();  /* should never happen */
-	}
-
-exit:
-	if (goa_account != NULL)
-		g_object_unref (goa_account);
-
-	if (goa_oauth_based != NULL)
-		g_object_unref (goa_oauth_based);
-
-	if (goa_oauth2_based != NULL)
-		g_object_unref (goa_oauth2_based);
+	success = goa_oauth_based_call_get_access_token_sync (
+		goa_oauth_based, &priv->access_token,
+		&priv->access_token_secret, NULL, cancellable, error);
 
 	g_mutex_unlock (&mutex);
 
+	g_object_unref (goa_oauth_based);
+
 	return success;
 }
 
diff --git a/addressbook/backends/google/e-gdata-oauth2-authorizer.c b/addressbook/backends/google/e-gdata-oauth2-authorizer.c
new file mode 100644
index 0000000..a973f36
--- /dev/null
+++ b/addressbook/backends/google/e-gdata-oauth2-authorizer.c
@@ -0,0 +1,325 @@
+/*
+ * e-gdata-oauth2-authorizer.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/>
+ *
+ */
+
+#include "e-gdata-oauth2-authorizer.h"
+
+#define E_GDATA_OAUTH2_AUTHORIZER_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_GDATA_OAUTH2_AUTHORIZER, EGDataOAuth2AuthorizerPrivate))
+
+struct _EGDataOAuth2AuthorizerPrivate {
+	GWeakRef source;
+
+	/* These members are protected by the global mutex. */
+	gchar *access_token;
+	GHashTable *authorization_domains;
+};
+
+enum {
+	PROP_0,
+	PROP_SOURCE
+};
+
+/* GDataAuthorizer methods must be thread-safe. */
+static GMutex mutex;
+
+/* Forward Declarations */
+static void	e_gdata_oauth2_authorizer_interface_init
+					(GDataAuthorizerInterface *interface);
+
+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
+gdata_oauth2_authorizer_is_authorized (GDataAuthorizer *authorizer,
+                                       GDataAuthorizationDomain *domain)
+{
+	EGDataOAuth2AuthorizerPrivate *priv;
+
+	/* This MUST be called with the mutex already locked. */
+
+	if (domain == NULL)
+		return TRUE;
+
+	priv = E_GDATA_OAUTH2_AUTHORIZER_GET_PRIVATE (authorizer);
+
+	return g_hash_table_contains (priv->authorization_domains, domain);
+}
+
+static void
+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
+gdata_oauth2_authorizer_set_property (GObject *object,
+                                      guint property_id,
+                                      const GValue *value,
+                                      GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_SOURCE:
+			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
+gdata_oauth2_authorizer_get_property (GObject *object,
+                                      guint property_id,
+                                      GValue *value,
+                                      GParamSpec *pspec)
+{
+	switch (property_id) {
+		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
+gdata_oauth2_authorizer_dispose (GObject *object)
+{
+	EGDataOAuth2AuthorizerPrivate *priv;
+
+	priv = E_GDATA_OAUTH2_AUTHORIZER_GET_PRIVATE (object);
+
+	g_weak_ref_set (&priv->source, NULL);
+
+	g_hash_table_remove_all (priv->authorization_domains);
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_gdata_oauth2_authorizer_parent_class)->
+		dispose (object);
+}
+
+static void
+gdata_oauth2_authorizer_finalize (GObject *object)
+{
+	EGDataOAuth2AuthorizerPrivate *priv;
+
+	priv = E_GDATA_OAUTH2_AUTHORIZER_GET_PRIVATE (object);
+
+	g_free (priv->access_token);
+
+	g_hash_table_destroy (priv->authorization_domains);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_gdata_oauth2_authorizer_parent_class)->
+		finalize (object);
+}
+
+static void
+gdata_oauth2_authorizer_constructed (GObject *object)
+{
+	EGDataOAuth2AuthorizerPrivate *priv;
+	GType service_type;
+	GList *domains;
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_gdata_oauth2_authorizer_parent_class)->
+		constructed (object);
+
+	priv = E_GDATA_OAUTH2_AUTHORIZER_GET_PRIVATE (object);
+
+	/* XXX We would need to generalize this to make the class
+	 *     reusable for other service types, probably by adding
+	 *     a "service-type" constructor property. */
+	service_type = GDATA_TYPE_CONTACTS_SERVICE;
+	domains = gdata_service_get_authorization_domains (service_type);
+
+	while (domains != NULL) {
+		g_hash_table_add (
+			priv->authorization_domains,
+			g_object_ref (domains->data));
+		domains = g_list_delete_link (domains, domains);
+	}
+}
+
+static void
+gdata_oauth2_authorizer_process_request (GDataAuthorizer *authorizer,
+                                         GDataAuthorizationDomain *domain,
+                                         SoupMessage *message)
+{
+	EGDataOAuth2AuthorizerPrivate *priv;
+	gchar *authorization;
+
+	priv = E_GDATA_OAUTH2_AUTHORIZER_GET_PRIVATE (authorizer);
+
+	g_mutex_lock (&mutex);
+
+	if (!gdata_oauth2_authorizer_is_authorized (authorizer, domain))
+		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 (priv->access_token == NULL)
+		goto exit;
+
+	authorization = g_strdup_printf ("OAuth %s", 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
+gdata_oauth2_authorizer_is_authorized_for_domain (GDataAuthorizer *authorizer,
+                                                  GDataAuthorizationDomain *domain)
+{
+	gboolean authorized;
+
+	g_mutex_lock (&mutex);
+
+	authorized = gdata_oauth2_authorizer_is_authorized (authorizer, domain);
+
+	g_mutex_unlock (&mutex);
+
+	return authorized;
+}
+
+static gboolean
+gdata_oauth2_authorizer_refresh_authorization (GDataAuthorizer *authorizer,
+                                               GCancellable *cancellable,
+                                               GError **error)
+{
+	EGDataOAuth2Authorizer *oauth2_authorizer;
+	ESource *source;
+	gchar **ptr_access_token;
+	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);
+
+	ptr_access_token = &oauth2_authorizer->priv->access_token;
+
+	g_mutex_lock (&mutex);
+
+	g_free (*ptr_access_token);
+	*ptr_access_token = NULL;
+
+	success = e_source_get_oauth2_access_token_sync (
+		source, cancellable, ptr_access_token, NULL, error);
+
+	g_mutex_unlock (&mutex);
+
+	g_object_unref (source);
+
+	return success;
+}
+
+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 = gdata_oauth2_authorizer_set_property;
+	object_class->get_property = gdata_oauth2_authorizer_get_property;
+	object_class->dispose = gdata_oauth2_authorizer_dispose;
+	object_class->finalize = gdata_oauth2_authorizer_finalize;
+	object_class->constructed = gdata_oauth2_authorizer_constructed;
+
+	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 *interface)
+{
+	interface->process_request =
+		gdata_oauth2_authorizer_process_request;
+	interface->is_authorized_for_domain =
+		gdata_oauth2_authorizer_is_authorized_for_domain;
+	interface->refresh_authorization =
+		gdata_oauth2_authorizer_refresh_authorization;
+}
+
+static void
+e_gdata_oauth2_authorizer_init (EGDataOAuth2Authorizer *authorizer)
+{
+	GHashTable *authorization_domains;
+
+	authorization_domains = g_hash_table_new_full (
+		(GHashFunc) g_direct_hash,
+		(GEqualFunc) g_direct_equal,
+		(GDestroyNotify) g_object_unref,
+		(GDestroyNotify) NULL);
+
+	authorizer->priv = E_GDATA_OAUTH2_AUTHORIZER_GET_PRIVATE (authorizer);
+	authorizer->priv->authorization_domains = authorization_domains;
+}
+
+EGDataOAuth2Authorizer *
+e_gdata_oauth2_authorizer_new (ESource *source)
+{
+	g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+
+	return g_object_new (
+		E_TYPE_GDATA_OAUTH2_AUTHORIZER,
+		"source", source, NULL);
+}
+
+ESource *
+e_gdata_oauth2_authorizer_ref_source (EGDataOAuth2Authorizer *authorizer)
+{
+	g_return_val_if_fail (E_IS_GDATA_OAUTH2_AUTHORIZER (authorizer), NULL);
+
+	return g_weak_ref_get (&authorizer->priv->source);
+}
+
diff --git a/addressbook/backends/google/e-gdata-oauth2-authorizer.h b/addressbook/backends/google/e-gdata-oauth2-authorizer.h
new file mode 100644
index 0000000..28c9f61
--- /dev/null
+++ b/addressbook/backends/google/e-gdata-oauth2-authorizer.h
@@ -0,0 +1,70 @@
+/*
+ * e-gdata-oauth2-authorizer.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/>
+ *
+ */
+
+#ifndef E_GDATA_OAUTH2_AUTHORIZER_H
+#define E_GDATA_OAUTH2_AUTHORIZER_H
+
+#include <gdata/gdata.h>
+#include <libedataserver/libedataserver.h>
+
+/* Standard GObject macros */
+#define E_TYPE_GDATA_OAUTH2_AUTHORIZER \
+	(e_gdata_oauth2_authorizer_get_type ())
+#define E_GDATA_OAUTH2_AUTHORIZER(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_GDATA_OAUTH2_AUTHORIZER, EGDataOAuth2Authorizer))
+#define E_GDATA_OAUTH2_AUTHORIZER_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_GDATA_OAUTH2_AUTHORIZER, EGDataOAuth2AuthorizerClass))
+#define E_IS_GDATA_OAUTH2_AUTHORIZER(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_GDATA_OAUTH2_AUTHORIZER))
+#define E_IS_GDATA_OAUTH2_AUTHORIZER_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_GDATA_OAUTH2_AUTHORIZER))
+#define E_GDATA_OAUTH2_AUTHORIZER_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_GDATA_OAUTH2_AUTHORIZER, EGDataOAuth2AuthorizerClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EGDataOAuth2Authorizer EGDataOAuth2Authorizer;
+typedef struct _EGDataOAuth2AuthorizerClass EGDataOAuth2AuthorizerClass;
+typedef struct _EGDataOAuth2AuthorizerPrivate EGDataOAuth2AuthorizerPrivate;
+
+struct _EGDataOAuth2Authorizer {
+	GObject parent;
+	EGDataOAuth2AuthorizerPrivate *priv;
+};
+
+struct _EGDataOAuth2AuthorizerClass {
+	GObjectClass parent_class;
+};
+
+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);
+
+G_END_DECLS
+
+#endif /* E_GDATA_OAUTH2_AUTHORIZER_H */
+



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