diff options
author | Milan Crha <mcrha@redhat.com> | 2018-11-01 18:34:05 +0100 |
---|---|---|
committer | Milan Crha <mcrha@redhat.com> | 2018-11-01 18:37:22 +0100 |
commit | 32d89b16591465a09028994ed4b93a4de4493255 (patch) | |
tree | 27d57aa89a6c08667201eedfb0b32af7f8076d3e | |
parent | 9e3af6c07ac7775eaae792b843e363e578c09f43 (diff) | |
download | evolution-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.c | 65 | ||||
-rw-r--r-- | src/libebackend/e-collection-backend.h | 3 | ||||
-rw-r--r-- | src/modules/google-backend/module-google-backend.c | 76 |
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), |