Commit 9cf7cd64 authored by Milan Crha's avatar Milan Crha

I#51 - [Gmail] Change from OAuth2 to other authentication doesn't stick

Closes GNOME/evolution-data-server#51
parent 37e582ad
......@@ -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);
}
......@@ -1256,6 +1288,39 @@ e_collection_backend_new_child (ECollectionBackend *backend,
return child_source;
}
/**
* 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.30.3
**/
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
......
......@@ -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);
......
......@@ -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),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment