summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2018-11-01 18:34:05 +0100
committerMilan Crha <mcrha@redhat.com>2018-11-01 18:37:22 +0100
commit32d89b16591465a09028994ed4b93a4de4493255 (patch)
tree27d57aa89a6c08667201eedfb0b32af7f8076d3e
parent9e3af6c07ac7775eaae792b843e363e578c09f43 (diff)
downloadevolution-data-server-32d89b16591465a09028994ed4b93a4de4493255.tar.gz
I#51 - [Gmail] Change from OAuth2 to other authentication doesn't stick
Closes https://gitlab.gnome.org/GNOME/evolution-data-server/issues/51
-rw-r--r--src/libebackend/e-collection-backend.c65
-rw-r--r--src/libebackend/e-collection-backend.h3
-rw-r--r--src/modules/google-backend/module-google-backend.c76
3 files changed, 127 insertions, 17 deletions
diff --git a/src/libebackend/e-collection-backend.c b/src/libebackend/e-collection-backend.c
index d9ed7d43f..335fc773e 100644
--- a/src/libebackend/e-collection-backend.c
+++ b/src/libebackend/e-collection-backend.c
@@ -71,6 +71,7 @@ struct _ECollectionBackendPrivate {
/* Resource ID -> ESource */
GHashTable *unclaimed_resources;
GMutex unclaimed_resources_lock;
+ GHashTable *new_sources; /* ESource::uid ~> NULL, uses the unclaimed_resources_lock */
gulong source_added_handler_id;
gulong source_removed_handler_id;
@@ -342,6 +343,13 @@ collection_backend_claim_resource (ECollectionBackend *backend,
GFile *file = collection_backend_new_user_file (backend);
source = collection_backend_new_source (backend, file, error);
g_object_unref (file);
+
+ if (source) {
+ if (!backend->priv->new_sources)
+ backend->priv->new_sources = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ g_hash_table_insert (backend->priv->new_sources, e_source_dup_uid (source), NULL);
+ }
}
g_mutex_unlock (&backend->priv->unclaimed_resources_lock);
@@ -547,6 +555,21 @@ collection_backend_source_enabled_cb (ESource *source,
g_object_notify (collection, "mail-enabled");
}
+static void
+collection_backend_forget_new_sources (ECollectionBackend *backend)
+{
+ g_return_if_fail (E_IS_COLLECTION_BACKEND (backend));
+
+ g_mutex_lock (&backend->priv->unclaimed_resources_lock);
+
+ if (backend->priv->new_sources) {
+ g_hash_table_destroy (backend->priv->new_sources);
+ backend->priv->new_sources = NULL;
+ }
+
+ g_mutex_unlock (&backend->priv->unclaimed_resources_lock);
+}
+
static gboolean
collection_backend_populate_idle_cb (gpointer user_data)
{
@@ -561,6 +584,10 @@ collection_backend_populate_idle_cb (gpointer user_data)
g_return_val_if_fail (class != NULL, FALSE);
g_return_val_if_fail (class->populate != NULL, FALSE);
+ /* Any new sources found during the last populate() are not
+ considered new anymore. */
+ collection_backend_forget_new_sources (backend);
+
class->populate (backend);
return FALSE;
@@ -773,6 +800,8 @@ collection_backend_dispose (GObject *object)
g_mutex_lock (&priv->unclaimed_resources_lock);
g_hash_table_remove_all (priv->unclaimed_resources);
+ if (priv->new_sources)
+ g_hash_table_remove_all (priv->new_sources);
g_mutex_unlock (&priv->unclaimed_resources_lock);
/* Chain up to parent's dispose() method. */
@@ -792,6 +821,8 @@ collection_backend_finalize (GObject *object)
g_mutex_clear (&priv->property_lock);
g_hash_table_destroy (priv->unclaimed_resources);
+ if (priv->new_sources)
+ g_hash_table_destroy (priv->new_sources);
g_mutex_clear (&priv->unclaimed_resources_lock);
g_weak_ref_clear (&priv->server);
@@ -1201,6 +1232,7 @@ e_collection_backend_init (ECollectionBackend *backend)
g_mutex_init (&backend->priv->children_lock);
g_mutex_init (&backend->priv->property_lock);
backend->priv->unclaimed_resources = unclaimed_resources;
+ backend->priv->new_sources = NULL;
g_mutex_init (&backend->priv->unclaimed_resources_lock);
g_weak_ref_init (&backend->priv->server, NULL);
}
@@ -1257,6 +1289,39 @@ e_collection_backend_new_child (ECollectionBackend *backend,
}
/**
+ * e_collection_backend_is_new_source:
+ * @backend: an #ECollectionBackend
+ * @source: a child #ESource
+ *
+ * Returns whether the @source is a newly created child or not. New sources
+ * are remembered between two populate calls only.
+ *
+ * Returns: %TRUE, when the @source is a new child; %FALSE when
+ * it had been known before.
+ *
+ * Since: 3.32
+ **/
+gboolean
+e_collection_backend_is_new_source (ECollectionBackend *backend,
+ ESource *source)
+{
+ gboolean is_new;
+
+ g_return_val_if_fail (E_IS_COLLECTION_BACKEND (backend), FALSE);
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+ g_return_val_if_fail (e_source_get_uid (source) != NULL, FALSE);
+
+ g_mutex_lock (&backend->priv->unclaimed_resources_lock);
+
+ is_new = backend->priv->new_sources &&
+ g_hash_table_contains (backend->priv->new_sources, e_source_get_uid (source));
+
+ g_mutex_unlock (&backend->priv->unclaimed_resources_lock);
+
+ return is_new;
+}
+
+/**
* e_collection_backend_ref_proxy_resolver:
* @backend: an #ECollectionBackend
*
diff --git a/src/libebackend/e-collection-backend.h b/src/libebackend/e-collection-backend.h
index 014232e42..695358d51 100644
--- a/src/libebackend/e-collection-backend.h
+++ b/src/libebackend/e-collection-backend.h
@@ -115,6 +115,9 @@ struct _ECollectionBackendClass {
GType e_collection_backend_get_type (void) G_GNUC_CONST;
ESource * e_collection_backend_new_child (ECollectionBackend *backend,
const gchar *resource_id);
+gboolean e_collection_backend_is_new_source
+ (ECollectionBackend *backend,
+ ESource *source);
GProxyResolver *
e_collection_backend_ref_proxy_resolver
(ECollectionBackend *backend);
diff --git a/src/modules/google-backend/module-google-backend.c b/src/modules/google-backend/module-google-backend.c
index c5527e3af..29586337f 100644
--- a/src/modules/google-backend/module-google-backend.c
+++ b/src/modules/google-backend/module-google-backend.c
@@ -151,28 +151,65 @@ host_ends_with (const gchar *host,
}
static gboolean
-google_backend_is_google_host (ESourceAuthentication *auth_extension)
+google_backend_is_google_host (ESourceAuthentication *auth_extension,
+ gboolean *out_requires_oauth2)
{
gboolean is_google;
+ gboolean requires_oauth2;
gchar *host;
g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (auth_extension), FALSE);
host = e_source_authentication_dup_host (auth_extension);
- is_google = host && (
+ requires_oauth2 = host && host_ends_with (host, "googleusercontent.com");
+
+ is_google = requires_oauth2 || (host && (
host_ends_with (host, "gmail.com") ||
host_ends_with (host, "googlemail.com") ||
- host_ends_with (host, "google.com") ||
- host_ends_with (host, "googleusercontent.com"));
+ host_ends_with (host, "google.com")));
g_free (host);
+ if (out_requires_oauth2)
+ *out_requires_oauth2 = requires_oauth2;
+
return is_google;
}
+static gboolean
+google_backend_is_oauth2 (const gchar *method)
+{
+ return g_strcmp0 (method, GOOGLE_OAUTH2_METHOD) == 0 ||
+ g_strcmp0 (method, "OAuth2") == 0 ||
+ g_strcmp0 (method, "XOAUTH2") == 0;
+}
+
+static gboolean
+google_backend_can_change_auth_method (ESourceAuthentication *auth_extension,
+ const gchar *new_method)
+{
+ gchar *cur_method;
+ gboolean can_change;
+
+ g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (auth_extension), FALSE);
+
+ if (!new_method)
+ return FALSE;
+
+ cur_method = e_source_authentication_dup_method (auth_extension);
+
+ /* Only when turning off OAuth2 */
+ can_change = google_backend_is_oauth2 (cur_method) && !google_backend_is_oauth2 (new_method);
+
+ g_free (cur_method);
+
+ return can_change;
+}
+
static void
-google_backend_mail_update_auth_method (ESource *child_source,
+google_backend_mail_update_auth_method (ECollectionBackend *collection_backend,
+ ESource *child_source,
ESource *master_source)
{
ESourceAuthentication *auth_extension;
@@ -182,7 +219,7 @@ google_backend_mail_update_auth_method (ESource *child_source,
auth_extension = e_source_get_extension (child_source, E_SOURCE_EXTENSION_AUTHENTICATION);
- if (!google_backend_is_google_host (auth_extension))
+ if (!google_backend_is_google_host (auth_extension, NULL))
return;
oauth2_support = e_server_side_source_ref_oauth2_support (E_SERVER_SIDE_SOURCE (child_source));
@@ -201,7 +238,8 @@ google_backend_mail_update_auth_method (ESource *child_source,
method = NULL;
}
- if (method)
+ if (method && (e_collection_backend_is_new_source (collection_backend, child_source) ||
+ google_backend_can_change_auth_method (auth_extension, method)))
e_source_authentication_set_method (auth_extension, method);
g_clear_object (&oauth2_support);
@@ -212,21 +250,22 @@ google_backend_mail_update_auth_method_cb (ESource *child_source,
GParamSpec *param,
EBackend *backend)
{
- google_backend_mail_update_auth_method (child_source, e_backend_get_source (backend));
+ google_backend_mail_update_auth_method (E_COLLECTION_BACKEND (backend), child_source, e_backend_get_source (backend));
}
static void
-google_backend_calendar_update_auth_method (ESource *child_source,
+google_backend_calendar_update_auth_method (ECollectionBackend *collection_backend,
+ ESource *child_source,
ESource *master_source)
{
EOAuth2Support *oauth2_support;
ESourceAuthentication *auth_extension;
const gchar *method;
- gboolean can_use_google_auth;
+ gboolean can_use_google_auth, requires_oauth2 = FALSE;
auth_extension = e_source_get_extension (child_source, E_SOURCE_EXTENSION_AUTHENTICATION);
- if (!google_backend_is_google_host (auth_extension))
+ if (!google_backend_is_google_host (auth_extension, &requires_oauth2))
return;
oauth2_support = e_server_side_source_ref_oauth2_support (E_SERVER_SIDE_SOURCE (child_source));
@@ -245,7 +284,10 @@ google_backend_calendar_update_auth_method (ESource *child_source,
method = "plain/password";
}
- e_source_authentication_set_method (auth_extension, method);
+ if (requires_oauth2 ||
+ e_collection_backend_is_new_source (collection_backend, child_source) ||
+ google_backend_can_change_auth_method (auth_extension, method))
+ e_source_authentication_set_method (auth_extension, method);
g_clear_object (&oauth2_support);
}
@@ -255,7 +297,7 @@ google_backend_calendar_update_auth_method_cb (ESource *child_source,
GParamSpec *param,
EBackend *backend)
{
- google_backend_calendar_update_auth_method (child_source, e_backend_get_source (backend));
+ google_backend_calendar_update_auth_method (E_COLLECTION_BACKEND (backend), child_source, e_backend_get_source (backend));
}
static void
@@ -269,7 +311,7 @@ google_backend_contacts_update_auth_method (ESource *child_source,
extension = e_source_get_extension (child_source, E_SOURCE_EXTENSION_AUTHENTICATION);
- if (!google_backend_is_google_host (extension))
+ if (!google_backend_is_google_host (extension, NULL))
return;
oauth2_support = e_server_side_source_ref_oauth2_support (E_SERVER_SIDE_SOURCE (child_source));
@@ -476,7 +518,7 @@ google_backend_authenticate_sync (EBackend *backend,
/* When the WebDAV extension is created, the auth method can be reset, thus ensure
it's there before setting correct authentication method on the master source. */
(void) e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
- google_backend_calendar_update_auth_method (source, NULL);
+ google_backend_calendar_update_auth_method (collection, source, NULL);
if (goa_extension) {
calendar_url = e_source_goa_get_calendar_url (goa_extension);
@@ -751,7 +793,7 @@ google_backend_child_added (ECollectionBackend *backend,
if (e_source_has_extension (child_source, E_SOURCE_EXTENSION_MAIL_ACCOUNT) ||
e_source_has_extension (child_source, E_SOURCE_EXTENSION_MAIL_TRANSPORT)) {
- google_backend_mail_update_auth_method (child_source, collection_source);
+ google_backend_mail_update_auth_method (backend, child_source, collection_source);
g_signal_connect (
child_source, "notify::oauth2-support",
G_CALLBACK (google_backend_mail_update_auth_method_cb),
@@ -780,7 +822,7 @@ google_backend_child_added (ECollectionBackend *backend,
g_free (today);
}
- google_backend_calendar_update_auth_method (child_source, collection_source);
+ google_backend_calendar_update_auth_method (backend, child_source, collection_source);
g_signal_connect (
child_source, "notify::oauth2-support",
G_CALLBACK (google_backend_calendar_update_auth_method_cb),