[evolution-data-server] google: Add EGDataOAuth2Authorizer.
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] google: Add EGDataOAuth2Authorizer.
- Date: Mon, 31 Dec 2012 15:53:05 +0000 (UTC)
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]