diff -up evolution-data-server-3.8.5/calendar/backends/caldav/e-cal-backend-caldav.c.google-caldav-v2 evolution-data-server-3.8.5/calendar/backends/caldav/e-cal-backend-caldav.c
--- evolution-data-server-3.8.5/calendar/backends/caldav/e-cal-backend-caldav.c.google-caldav-v2 2013-07-23 07:58:13.000000000 -0400
+++ evolution-data-server-3.8.5/calendar/backends/caldav/e-cal-backend-caldav.c 2013-08-16 06:46:04.137343301 -0400
@@ -958,6 +958,32 @@ parse_propfind_response (SoupMessage *me
/* Authentication helpers for libsoup */
static void
+soup_authenticate_bearer (SoupSession *session,
+ SoupMessage *message,
+ SoupAuth *auth,
+ ESource *source)
+{
+ gchar *access_token = NULL;
+ gint expires_in_seconds = -1;
+ GError *local_error = NULL;
+
+ e_source_get_oauth2_access_token_sync (
+ source, NULL, &access_token,
+ &expires_in_seconds, &local_error);
+
+ e_soup_auth_bearer_set_access_token (
+ E_SOUP_AUTH_BEARER (auth),
+ access_token, expires_in_seconds);
+
+ if (local_error != NULL) {
+ g_warning ("%s: %s", G_STRFUNC, local_error->message);
+ g_error_free (local_error);
+ }
+
+ g_free (access_token);
+}
+
+static void
soup_authenticate (SoupSession *session,
SoupMessage *msg,
SoupAuth *auth,
@@ -975,8 +1001,14 @@ soup_authenticate (SoupSession *session,
extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
auth_extension = e_source_get_extension (source, extension_name);
+ if (retrying)
+ return;
+
+ if (E_IS_SOUP_AUTH_BEARER (auth)) {
+ soup_authenticate_bearer (session, msg, auth, source);
+
/* do not send same password twice, but keep it for later use */
- if (!retrying && cbdav->priv->password != NULL) {
+ } else if (cbdav->priv->password != NULL) {
gchar *user;
user = e_source_authentication_dup_user (auth_extension);
@@ -5210,6 +5242,8 @@ cal_backend_caldav_constructed (GObject
static void
e_cal_backend_caldav_init (ECalBackendCalDAV *cbdav)
{
+ SoupSessionFeature *feature;
+
cbdav->priv = E_CAL_BACKEND_CALDAV_GET_PRIVATE (cbdav);
cbdav->priv->session = soup_session_sync_new ();
g_object_set (
@@ -5219,6 +5253,16 @@ e_cal_backend_caldav_init (ECalBackendCa
SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, TRUE,
NULL);
+ /* XXX SoupAuthManager is public API as of libsoup 2.42, but
+ * this isn't worth bumping our libsoup requirement over.
+ * So get the SoupAuthManager GType by its type name. */
+ feature = soup_session_get_feature (
+ cbdav->priv->session,
+ g_type_from_name ("SoupAuthManager"));
+
+ /* Add the "Bearer" auth type to support OAuth 2.0. */
+ soup_session_feature_add_feature (feature, E_TYPE_SOUP_AUTH_BEARER);
+
cbdav->priv->proxy = e_proxy_new ();
e_proxy_setup_proxy (cbdav->priv->proxy);
g_signal_connect (cbdav->priv->proxy, "changed", G_CALLBACK (proxy_settings_changed), cbdav->priv);
diff -up evolution-data-server-3.8.5/docs/reference/libebackend/libebackend-docs.xml.google-caldav-v2 evolution-data-server-3.8.5/docs/reference/libebackend/libebackend-docs.xml
--- evolution-data-server-3.8.5/docs/reference/libebackend/libebackend-docs.xml.google-caldav-v2 2013-03-17 08:46:02.000000000 -0400
+++ evolution-data-server-3.8.5/docs/reference/libebackend/libebackend-docs.xml 2013-08-16 06:46:04.131343499 -0400
@@ -34,6 +34,7 @@
Miscellaneous Utilities
+
diff -up evolution-data-server-3.8.5/docs/reference/libebackend/libebackend-sections.txt.google-caldav-v2 evolution-data-server-3.8.5/docs/reference/libebackend/libebackend-sections.txt
--- evolution-data-server-3.8.5/docs/reference/libebackend/libebackend-sections.txt.google-caldav-v2 2013-08-11 07:26:26.000000000 -0400
+++ evolution-data-server-3.8.5/docs/reference/libebackend/libebackend-sections.txt 2013-08-16 06:46:04.132343461 -0400
@@ -397,6 +397,24 @@ EServerSideSourcePrivate
+e-soup-auth-bearer
+ESoupAuthBearer
+ESoupAuthBearer
+e_soup_auth_bearer_set_access_token
+
+E_SOUP_AUTH_BEARER
+E_IS_SOUP_AUTH_BEARER
+E_TYPE_SOUP_AUTH_BEARER
+E_SOUP_AUTH_BEARER_CLASS
+E_IS_SOUP_AUTH_BEARER_CLASS
+E_SOUP_AUTH_BEARER_GET_CLASS
+ESoupAuthBearerClass
+e_soup_auth_bearer_get_type
+
+ESoupAuthBearerPrivate
+
+
+
e-source-registry-server
ESourceRegistryServer
E_SOURCE_REGISTRY_SERVER_OBJECT_PATH
diff -up evolution-data-server-3.8.5/docs/reference/libebackend/libebackend.types.google-caldav-v2 evolution-data-server-3.8.5/docs/reference/libebackend/libebackend.types
--- evolution-data-server-3.8.5/docs/reference/libebackend/libebackend.types.google-caldav-v2 2013-08-11 07:26:26.000000000 -0400
+++ evolution-data-server-3.8.5/docs/reference/libebackend/libebackend.types 2013-08-16 06:46:04.134343391 -0400
@@ -15,6 +15,7 @@ e_module_get_type
e_oauth2_support_get_type
e_offline_listener_get_type
e_server_side_source_get_type
+e_soup_auth_bearer_get_type
e_source_registry_server_get_type
e_user_prompter_get_type
e_user_prompter_server_get_type
diff -up evolution-data-server-3.8.5/libebackend/e-soup-auth-bearer.c.google-caldav-v2 evolution-data-server-3.8.5/libebackend/e-soup-auth-bearer.c
--- evolution-data-server-3.8.5/libebackend/e-soup-auth-bearer.c.google-caldav-v2 2013-08-16 06:46:04.135343359 -0400
+++ evolution-data-server-3.8.5/libebackend/e-soup-auth-bearer.c 2013-08-16 06:46:04.135343359 -0400
@@ -0,0 +1,196 @@
+/*
+ * e-soup-auth-bearer.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
+ *
+ */
+
+/**
+ * SECTION: e-soup-auth-bearer
+ * @include: libebackend/libebackend.h
+ * @short_description: OAuth 2.0 support for libsoup
+ *
+ * #ESoupAuthBearer adds libsoup support for the use of bearer tokens in
+ * HTTP requests to access OAuth 2.0 protected resources, as defined in
+ * RFC 6750.
+ *
+ * An #EBackend should integrate #ESoupAuthBearer first by adding it as a
+ * feature to a #SoupSession's #SoupAuthManager, then from a #SoupSession
+ * #SoupSession::authenticate handler call e_source_get_oauth2_access_token()
+ * and pass the results to e_soup_auth_bearer_set_access_token().
+ **/
+
+#include "e-soup-auth-bearer.h"
+
+#include
+
+#define E_SOUP_AUTH_BEARER_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_SOUP_AUTH_BEARER, ESoupAuthBearerPrivate))
+
+#define AUTH_STRENGTH 1
+
+#define EXPIRY_INVALID ((time_t) -1)
+
+struct _ESoupAuthBearerPrivate {
+ gchar *access_token;
+ time_t expiry;
+};
+
+G_DEFINE_TYPE (
+ ESoupAuthBearer,
+ e_soup_auth_bearer,
+ SOUP_TYPE_AUTH)
+
+static gboolean
+e_soup_auth_bearer_is_expired (ESoupAuthBearer *bearer)
+{
+ gboolean expired = FALSE;
+
+ if (bearer->priv->expiry != EXPIRY_INVALID)
+ expired = (bearer->priv->expiry < time (NULL));
+
+ return expired;
+}
+
+static void
+e_soup_auth_bearer_finalize (GObject *object)
+{
+ ESoupAuthBearerPrivate *priv;
+
+ priv = E_SOUP_AUTH_BEARER_GET_PRIVATE (object);
+
+ g_free (priv->access_token);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (e_soup_auth_bearer_parent_class)->finalize (object);
+}
+
+static gboolean
+e_soup_auth_bearer_update (SoupAuth *auth,
+ SoupMessage *message,
+ GHashTable *auth_header)
+{
+ /* XXX Not sure what to do here. Discard the access token? */
+
+ return TRUE;
+}
+
+static GSList *
+e_soup_auth_bearer_get_protection_space (SoupAuth *auth,
+ SoupURI *source_uri)
+{
+ /* XXX Not sure what to do here. Need to return something. */
+
+ return g_slist_prepend (NULL, g_strdup (""));
+}
+
+static gboolean
+e_soup_auth_bearer_is_authenticated (SoupAuth *auth)
+{
+ ESoupAuthBearer *bearer;
+ gboolean authenticated = FALSE;
+
+ bearer = E_SOUP_AUTH_BEARER (auth);
+
+ if (!e_soup_auth_bearer_is_expired (bearer))
+ authenticated = (bearer->priv->access_token != NULL);
+
+ return authenticated;
+}
+
+static gchar *
+e_soup_auth_bearer_get_authorization (SoupAuth *auth,
+ SoupMessage *message)
+{
+ ESoupAuthBearer *bearer;
+
+ bearer = E_SOUP_AUTH_BEARER (auth);
+
+ return g_strdup_printf ("Bearer %s", bearer->priv->access_token);
+}
+
+static void
+e_soup_auth_bearer_class_init (ESoupAuthBearerClass *class)
+{
+ GObjectClass *object_class;
+ SoupAuthClass *auth_class;
+
+ g_type_class_add_private (class, sizeof (ESoupAuthBearerPrivate));
+
+ /* Keep the "e" prefix on private methods
+ * so we don't step on libsoup's namespace. */
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = e_soup_auth_bearer_finalize;
+
+ auth_class = SOUP_AUTH_CLASS (class);
+ auth_class->scheme_name = "Bearer";
+ auth_class->strength = AUTH_STRENGTH;
+ auth_class->update = e_soup_auth_bearer_update;
+ auth_class->get_protection_space = e_soup_auth_bearer_get_protection_space;
+ auth_class->is_authenticated = e_soup_auth_bearer_is_authenticated;
+ auth_class->get_authorization = e_soup_auth_bearer_get_authorization;
+}
+
+static void
+e_soup_auth_bearer_init (ESoupAuthBearer *bearer)
+{
+ bearer->priv = E_SOUP_AUTH_BEARER_GET_PRIVATE (bearer);
+ bearer->priv->expiry = EXPIRY_INVALID;
+}
+
+/**
+ * e_soup_auth_bearer_set_access_token:
+ * @bearer: an #ESoupAuthBearer
+ * @access_token: an OAuth 2.0 access token
+ * @expires_in_seconds: expiry for @access_token, or 0 if unknown
+ *
+ * This function is analogous to soup_auth_authenticate() for "Basic" HTTP
+ * authentication, except it takes an OAuth 2.0 access token instead of a
+ * username and password.
+ *
+ * If @expires_in_seconds is greater than zero, soup_auth_is_authenticated()
+ * will return %FALSE after the given number of seconds have elapsed.
+ *
+ * Since: 3.10
+ **/
+void
+e_soup_auth_bearer_set_access_token (ESoupAuthBearer *bearer,
+ const gchar *access_token,
+ gint expires_in_seconds)
+{
+ gboolean was_authenticated;
+ gboolean now_authenticated;
+
+ g_return_if_fail (E_IS_SOUP_AUTH_BEARER (bearer));
+
+ was_authenticated = soup_auth_is_authenticated (SOUP_AUTH (bearer));
+
+ g_free (bearer->priv->access_token);
+ bearer->priv->access_token = g_strdup (access_token);
+
+ if (expires_in_seconds > 0)
+ bearer->priv->expiry = time (NULL) + expires_in_seconds;
+ else
+ bearer->priv->expiry = EXPIRY_INVALID;
+
+ now_authenticated = soup_auth_is_authenticated (SOUP_AUTH (bearer));
+
+ if (was_authenticated != now_authenticated)
+ g_object_notify (
+ G_OBJECT (bearer),
+ SOUP_AUTH_IS_AUTHENTICATED);
+}
+
diff -up evolution-data-server-3.8.5/libebackend/e-soup-auth-bearer.h.google-caldav-v2 evolution-data-server-3.8.5/libebackend/e-soup-auth-bearer.h
--- evolution-data-server-3.8.5/libebackend/e-soup-auth-bearer.h.google-caldav-v2 2013-08-16 06:46:04.135343359 -0400
+++ evolution-data-server-3.8.5/libebackend/e-soup-auth-bearer.h 2013-08-16 06:46:04.135343359 -0400
@@ -0,0 +1,79 @@
+/*
+ * e-soup-auth-bearer.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
+ *
+ */
+
+#if !defined (__LIBEBACKEND_H_INSIDE__) && !defined (LIBEBACKEND_COMPILATION)
+#error "Only should be included directly."
+#endif
+
+#ifndef E_SOUP_AUTH_BEARER_H
+#define E_SOUP_AUTH_BEARER_H
+
+#include
+
+/* Standard GObject macros */
+#define E_TYPE_SOUP_AUTH_BEARER \
+ (e_soup_auth_bearer_get_type ())
+#define E_SOUP_AUTH_BEARER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SOUP_AUTH_BEARER, ESoupAuthBearer))
+#define E_SOUP_AUTH_BEARER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SOUP_AUTH_BEARER, ESoupAuthBearerClass))
+#define E_IS_SOUP_AUTH_BEARER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SOUP_AUTH_BEARER))
+#define E_IS_SOUP_AUTH_BEARER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SOUP_AUTH_BEARER))
+#define E_SOUP_AUTH_BEARER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SOUP_AUTH_BEARER, ESoupAuthBearerClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ESoupAuthBearer ESoupAuthBearer;
+typedef struct _ESoupAuthBearerClass ESoupAuthBearerClass;
+typedef struct _ESoupAuthBearerPrivate ESoupAuthBearerPrivate;
+
+/**
+ * ESoupAuthBearer:
+ *
+ * Contains only private data that should be read and manipulated using the
+ * functions below.
+ *
+ * Since: 3.10
+ **/
+struct _ESoupAuthBearer {
+ SoupAuth parent;
+ ESoupAuthBearerPrivate *priv;
+};
+
+struct _ESoupAuthBearerClass {
+ SoupAuthClass parent_class;
+};
+
+GType e_soup_auth_bearer_get_type (void) G_GNUC_CONST;
+void e_soup_auth_bearer_set_access_token
+ (ESoupAuthBearer *bearer,
+ const gchar *access_token,
+ gint expires_in_seconds);
+
+G_END_DECLS
+
+#endif /* E_SOUP_AUTH_BEARER_H */
+
diff -up evolution-data-server-3.8.5/libebackend/libebackend.h.google-caldav-v2 evolution-data-server-3.8.5/libebackend/libebackend.h
--- evolution-data-server-3.8.5/libebackend/libebackend.h.google-caldav-v2 2013-07-23 07:57:40.000000000 -0400
+++ evolution-data-server-3.8.5/libebackend/libebackend.h 2013-08-16 06:46:04.135343359 -0400
@@ -42,6 +42,7 @@
#include
#include
#include
+#include
#include
#include
#include
diff -up evolution-data-server-3.8.5/libebackend/Makefile.am.google-caldav-v2 evolution-data-server-3.8.5/libebackend/Makefile.am
--- evolution-data-server-3.8.5/libebackend/Makefile.am.google-caldav-v2 2013-04-18 11:33:59.000000000 -0400
+++ evolution-data-server-3.8.5/libebackend/Makefile.am 2013-08-16 06:46:04.134343391 -0400
@@ -35,6 +35,7 @@ libebackend_1_2_la_CPPFLAGS = \
$(E_BACKEND_CFLAGS) \
$(GCR_BASE_CFLAGS) \
$(GIO_UNIX_CFLAGS) \
+ $(SOUP_CFLAGS) \
$(CODE_COVERAGE_CFLAGS) \
$(NULL)
@@ -56,6 +57,7 @@ libebackend_1_2_la_SOURCES = \
e-db3-utils.c \
e-module.c \
e-server-side-source.c \
+ e-soup-auth-bearer.c \
e-source-registry-server.c \
e-sqlite3-vfs.c \
e-user-prompter.c \
@@ -71,6 +73,7 @@ libebackend_1_2_la_LIBADD = \
$(SQLITE3_LIBS) \
$(GCR_BASE_LIBS) \
$(GIO_UNIX_LIBS) \
+ $(SOUP_LIBS) \
$(DB_LIBS)
libebackend_1_2_la_LDFLAGS = \
@@ -100,6 +103,7 @@ libebackendinclude_HEADERS = \
e-dbhash.h \
e-module.h \
e-server-side-source.h \
+ e-soup-auth-bearer.h \
e-source-registry-server.h \
e-sqlite3-vfs.h \
e-user-prompter.h \
diff -up evolution-data-server-3.8.5/libedataserver/e-source-webdav.c.google-caldav-v2 evolution-data-server-3.8.5/libedataserver/e-source-webdav.c
--- evolution-data-server-3.8.5/libedataserver/e-source-webdav.c.google-caldav-v2 2013-07-23 07:57:32.000000000 -0400
+++ evolution-data-server-3.8.5/libedataserver/e-source-webdav.c 2013-08-16 06:46:04.130343539 -0400
@@ -108,15 +108,39 @@ source_webdav_user_to_method (GBinding *
GValue *target_value,
gpointer user_data)
{
+ GObject *target_object;
+ ESourceAuthentication *extension;
const gchar *user;
+ gchar *method;
+ gboolean success = TRUE;
+
+ target_object = g_binding_get_target (binding);
+ extension = E_SOURCE_AUTHENTICATION (target_object);
+ method = e_source_authentication_dup_method (extension);
+ g_return_val_if_fail (method != NULL, FALSE);
+
+ /* Be careful not to stomp on a custom method name.
+ * Only change it under the following conditions:
+ *
+ * 1) If "user" is empty, set "method" to "none".
+ * 2) If "user" is not empty and "method" is "none",
+ * set "method" to "plain/password" (corresponds
+ * to HTTP Basic authentication).
+ * 3) Otherwise preserve the current "method" value.
+ */
user = g_value_get_string (source_value);
- if (user == NULL || *user == '\0')
+ if (user == NULL || *user == '\0') {
g_value_set_string (target_value, "none");
- else
+ } else if (g_str_equal (method, "none")) {
g_value_set_string (target_value, "plain/password");
+ } else {
+ success = FALSE;
+ }
+
+ g_free (method);
- return TRUE;
+ return success;
}
static void
diff -up evolution-data-server-3.8.5/modules/google-backend/module-google-backend.c.google-caldav-v2 evolution-data-server-3.8.5/modules/google-backend/module-google-backend.c
--- evolution-data-server-3.8.5/modules/google-backend/module-google-backend.c.google-caldav-v2 2013-07-23 07:57:38.000000000 -0400
+++ evolution-data-server-3.8.5/modules/google-backend/module-google-backend.c 2013-08-16 06:46:04.371341485 -0400
@@ -45,10 +45,16 @@
/* Calendar Configuration Details */
#define GOOGLE_CALENDAR_BACKEND_NAME "caldav"
-#define GOOGLE_CALENDAR_HOST "www.google.com"
-#define GOOGLE_CALENDAR_CALDAV_PATH "/calendar/dav/%s/events"
#define GOOGLE_CALENDAR_RESOURCE_ID "Calendar"
+/* CalDAV v1 Configuration Details */
+#define GOOGLE_CALDAV_V1_HOST "www.google.com"
+#define GOOGLE_CALDAV_V1_PATH "/calendar/dav/%s/events"
+
+/* CalDAV v2 Configuration Details */
+#define GOOGLE_CALDAV_V2_HOST "apidata.googleusercontent.com"
+#define GOOGLE_CALDAV_V2_PATH "/caldav/v2/%s/events"
+
/* Contacts Configuration Details */
#define GOOGLE_CONTACTS_BACKEND_NAME "google"
#define GOOGLE_CONTACTS_HOST "www.google.com"
@@ -95,24 +101,68 @@ G_DEFINE_DYNAMIC_TYPE (
E_TYPE_COLLECTION_BACKEND_FACTORY)
static void
-google_backend_contacts_update_auth_method (ESource *source)
+google_backend_calendar_update_auth_method (ESource *source)
{
EOAuth2Support *oauth2_support;
- ESourceAuthentication *extension;
+ ESourceAuthentication *auth_extension;
+ ESourceWebdav *webdav_extension;
const gchar *extension_name;
-
- extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
- extension = e_source_get_extension (source, extension_name);
+ const gchar *host;
+ const gchar *method;
+ const gchar *path_format;
+ gchar *path;
+ gchar *user;
oauth2_support = e_server_side_source_ref_oauth2_support (
E_SERVER_SIDE_SOURCE (source));
+
+ /* The host name and WebDAV resource path depend on the
+ * authentication method used, so update those here too. */
+
if (oauth2_support != NULL) {
- e_source_authentication_set_method (extension, "OAuth2");
- g_object_unref (oauth2_support);
- return;
+ method = "OAuth2";
+ host = GOOGLE_CALDAV_V2_HOST;
+ path_format = GOOGLE_CALDAV_V2_PATH;
+ } else {
+ method = "plain/password";
+ host = GOOGLE_CALDAV_V1_HOST;
+ path_format = GOOGLE_CALDAV_V1_PATH;
}
- e_source_authentication_set_method (extension, "ClientLogin");
+ extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+ auth_extension = e_source_get_extension (source, extension_name);
+ e_source_authentication_set_host (auth_extension, host);
+ e_source_authentication_set_method (auth_extension, method);
+
+ extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
+ webdav_extension = e_source_get_extension (source, extension_name);
+
+ user = e_source_authentication_dup_user (auth_extension);
+ path = g_strdup_printf (path_format, (user != NULL) ? user : "");
+ e_source_webdav_set_resource_path (webdav_extension, path);
+ g_free (path);
+ g_free (user);
+
+ g_clear_object (&oauth2_support);
+}
+
+static void
+google_backend_contacts_update_auth_method (ESource *source)
+{
+ EOAuth2Support *oauth2_support;
+ ESourceAuthentication *extension;
+ const gchar *extension_name;
+ const gchar *method;
+
+ oauth2_support = e_server_side_source_ref_oauth2_support (
+ E_SERVER_SIDE_SOURCE (source));
+
+ extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+ extension = e_source_get_extension (source, extension_name);
+ method = (oauth2_support != NULL) ? "OAuth2" : "ClientLogin";
+ e_source_authentication_set_method (extension, method);
+
+ g_clear_object (&oauth2_support);
}
static void
@@ -125,14 +175,16 @@ google_backend_add_calendar (ECollection
ESourceCollection *collection_extension;
const gchar *backend_name;
const gchar *extension_name;
- const gchar *identity;
const gchar *resource_id;
- gchar *path;
/* FIXME As a future enhancement, we should query Google
* for a list of user calendars and add them to the
* collection with matching display names and colors. */
+ /* NOTE: Host name and WebDAV resource path are set in
+ * google_backend_calendar_update_auth_method(),
+ * since they depend on the auth method used. */
+
collection_source = e_backend_get_source (E_BACKEND (backend));
resource_id = GOOGLE_CALENDAR_RESOURCE_ID;
@@ -155,15 +207,15 @@ google_backend_add_calendar (ECollection
extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
extension = e_source_get_extension (source, extension_name);
- e_source_authentication_set_host (
- E_SOURCE_AUTHENTICATION (extension),
- GOOGLE_CALENDAR_HOST);
-
g_object_bind_property (
collection_extension, "identity",
extension, "user",
G_BINDING_SYNC_CREATE);
+ /* Make sure the WebDAV resource path is up-to-date, since
+ * it's built from the "user" property that we just set. */
+ google_backend_calendar_update_auth_method (source);
+
extension_name = E_SOURCE_EXTENSION_SECURITY;
extension = e_source_get_extension (source, extension_name);
@@ -178,19 +230,11 @@ google_backend_add_calendar (ECollection
g_get_current_time (&today_tv);
today = g_time_val_to_iso8601 (&today_tv);
- e_source_alarms_set_last_notified (E_SOURCE_ALARMS (extension), today);
+ e_source_alarms_set_last_notified (
+ E_SOURCE_ALARMS (extension), today);
g_free (today);
}
- extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
- extension = e_source_get_extension (source, extension_name);
-
- identity = e_source_collection_get_identity (collection_extension);
- path = g_strdup_printf (GOOGLE_CALENDAR_CALDAV_PATH, identity);
- e_source_webdav_set_resource_path (
- E_SOURCE_WEBDAV (extension), path);
- g_free (path);
-
server = e_collection_backend_ref_server (backend);
e_source_registry_server_add_source (server, source);
g_object_unref (server);
@@ -337,6 +381,20 @@ google_backend_child_added (ECollectionB
collection_identity);
}
+ /* Keep the calendar authentication method up-to-date.
+ *
+ * XXX Not using a property binding here in case I end up adding
+ * other "support" interfaces which influence authentication.
+ * Many-to-one property bindinds tend not to work so well. */
+ extension_name = E_SOURCE_EXTENSION_CALENDAR;
+ if (e_source_has_extension (child_source, extension_name)) {
+ google_backend_calendar_update_auth_method (child_source);
+ g_signal_connect (
+ child_source, "notify::oauth2-support",
+ G_CALLBACK (google_backend_calendar_update_auth_method),
+ NULL);
+ }
+
/* Keep the contacts authentication method up-to-date.
*
* XXX Not using a property binding here in case I end up adding