Blame SOURCES/evolution-data-server-3.8.5-google-caldav-v2.patch

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