diff --git a/eds-Internal_Google_OAuth2_authentication.patch b/eds-Internal_Google_OAuth2_authentication.patch new file mode 100644 index 0000000..ae85c86 --- /dev/null +++ b/eds-Internal_Google_OAuth2_authentication.patch @@ -0,0 +1,237 @@ +From eaf719213b7f0e052b1e535e87b00eea8b6c5719 Mon Sep 17 00:00:00 2001 +From: Milan Crha +Date: Tue, 20 Sep 2016 12:29:48 +0200 +Subject: Bug 771547 - Internal Google OAuth2 authentication fails with expired + token + +--- + calendar/backends/caldav/e-cal-backend-caldav.c | 2 +- + libedataserver/e-data-server-util.c | 16 +++++++++---- + .../e-source-credentials-provider-impl-google.c | 2 +- + .../e-credentials-prompter-impl-google.c | 27 ++++++++++++++++++++-- + libedataserverui/e-credentials-prompter.c | 16 ++++++++++--- + 5 files changed, 52 insertions(+), 11 deletions(-) + +diff --git a/calendar/backends/caldav/e-cal-backend-caldav.c b/calendar/backends/caldav/e-cal-backend-caldav.c +index 53f7d0e..bebd87e 100644 +--- a/calendar/backends/caldav/e-cal-backend-caldav.c ++++ b/calendar/backends/caldav/e-cal-backend-caldav.c +@@ -697,7 +697,7 @@ status_code_to_result (SoupMessage *message, + gchar *body = g_strndup (message->response_body->data, message->response_body->length); + + /* Do not localize this string, it is returned by the server. */ +- if (body && (e_util_strstrcase (body, "Daily Limit Exceeded") || ++ if (body && (e_util_strstrcase (body, "Daily Limit") || + e_util_strstrcase (body, "https://console.developers.google.com/"))) { + /* Special-case this condition and provide this error up to the UI. */ + g_propagate_error (perror, +diff --git a/libedataserver/e-data-server-util.c b/libedataserver/e-data-server-util.c +index 60bb63d..63dc300 100644 +--- a/libedataserver/e-data-server-util.c ++++ b/libedataserver/e-data-server-util.c +@@ -2915,10 +2915,18 @@ e_util_get_source_oauth2_access_token_sync (ESource *source, + source, cancellable, out_access_token, + out_expires_in_seconds, error); + } else if (g_strcmp0 (auth_method, "Google") == 0) { +- success = TRUE; +- +- e_source_credentials_google_util_extract_from_credentials ( +- credentials, out_access_token, out_expires_in_seconds); ++ gint expires_in_seconds = -1; ++ ++ success = e_source_credentials_google_util_extract_from_credentials ( ++ credentials, out_access_token, &expires_in_seconds); ++ if (!success || expires_in_seconds <= 0) { ++ /* Ask to refresh the token, if it's expired */ ++ e_source_invoke_credentials_required_sync (source, ++ expires_in_seconds < 0 ? E_SOURCE_AUTHENTICATION_REQUIRED : E_SOURCE_AUTHENTICATION_REJECTED, ++ NULL, 0, NULL, cancellable, error); ++ } else if (out_expires_in_seconds) { ++ *out_expires_in_seconds = expires_in_seconds; ++ } + } + + g_free (auth_method); +diff --git a/libedataserver/e-source-credentials-provider-impl-google.c b/libedataserver/e-source-credentials-provider-impl-google.c +index 5761a17..7aecf47 100644 +--- a/libedataserver/e-source-credentials-provider-impl-google.c ++++ b/libedataserver/e-source-credentials-provider-impl-google.c +@@ -465,7 +465,7 @@ e_source_credentials_google_util_extract_from_credentials (const ENamedParameter + + if (out_expires_in_seconds) { + now = g_get_real_time () / G_USEC_PER_SEC; +- if (now < expires_after_tm) ++ if (now > expires_after_tm) + now = expires_after_tm; + + *out_expires_in_seconds = (gint) (expires_after_tm - now); +diff --git a/libedataserverui/e-credentials-prompter-impl-google.c b/libedataserverui/e-credentials-prompter-impl-google.c +index 2acfeb2..f968d7a 100644 +--- a/libedataserverui/e-credentials-prompter-impl-google.c ++++ b/libedataserverui/e-credentials-prompter-impl-google.c +@@ -291,9 +291,9 @@ cpi_google_update_prompter_credentials (GWeakRef *prompter_google_wr, + success = TRUE; + } + +- g_object_unref (prompter_google); + g_free (secret); + } ++ g_clear_object (&prompter_google); + + g_free (expires_after); + +@@ -332,8 +332,10 @@ e_credentials_prompter_impl_google_finish_dialog_idle_cb (gpointer user_data) + + g_return_val_if_fail (E_IS_CREDENTIALS_PROMPTER_IMPL_GOOGLE (prompter_google), FALSE); + ++ g_mutex_lock (&prompter_google->priv->property_lock); + if (g_source_get_id (g_main_current_source ()) == prompter_google->priv->show_dialog_idle_id) { + prompter_google->priv->show_dialog_idle_id = 0; ++ g_mutex_unlock (&prompter_google->priv->property_lock); + + g_warn_if_fail (prompter_google->priv->dialog != NULL); + +@@ -343,6 +345,8 @@ e_credentials_prompter_impl_google_finish_dialog_idle_cb (gpointer user_data) + e_credentials_prompter_impl_google_show_html (prompter_google->priv->web_view, + "Finished with error", prompter_google->priv->error_text); + } ++ } else { ++ g_mutex_unlock (&prompter_google->priv->property_lock); + } + + return FALSE; +@@ -442,9 +446,11 @@ cpi_google_get_access_token_thread (gpointer user_data) + GOOGLE_TOKEN_URI, soup_status, soup_status_get_phrase (soup_status)); + } + ++ g_mutex_lock (&prompter_google->priv->property_lock); + prompter_google->priv->show_dialog_idle_id = g_idle_add ( + e_credentials_prompter_impl_google_finish_dialog_idle_cb, + prompter_google); ++ g_mutex_unlock (&prompter_google->priv->property_lock); + } + + g_clear_object (&prompter_google); +@@ -843,10 +849,12 @@ e_credentials_prompter_impl_google_manage_dialog_idle_cb (gpointer user_data) + + g_return_val_if_fail (E_IS_CREDENTIALS_PROMPTER_IMPL_GOOGLE (prompter_google), FALSE); + ++ g_mutex_lock (&prompter_google->priv->property_lock); + if (g_source_get_id (g_main_current_source ()) == prompter_google->priv->show_dialog_idle_id) { + gboolean success; + + prompter_google->priv->show_dialog_idle_id = 0; ++ g_mutex_unlock (&prompter_google->priv->property_lock); + + g_warn_if_fail (prompter_google->priv->dialog == NULL); + +@@ -861,6 +869,8 @@ e_credentials_prompter_impl_google_manage_dialog_idle_cb (gpointer user_data) + success ? prompter_google->priv->credentials : NULL); + + e_credentials_prompter_impl_google_free_prompt_data (prompter_google); ++ } else { ++ g_mutex_unlock (&prompter_google->priv->property_lock); + } + + return FALSE; +@@ -942,9 +952,11 @@ cpi_google_check_existing_token_thread (gpointer user_data) + exit: + prompter_google = g_weak_ref_get (td->prompter_google); + if (prompter_google && !g_cancellable_is_cancelled (cancellable)) { ++ g_mutex_lock (&prompter_google->priv->property_lock); + prompter_google->priv->show_dialog_idle_id = g_idle_add ( + e_credentials_prompter_impl_google_manage_dialog_idle_cb, + prompter_google); ++ g_mutex_unlock (&prompter_google->priv->property_lock); + } + + g_clear_object (&prompter_google); +@@ -970,7 +982,14 @@ e_credentials_prompter_impl_google_process_prompt (ECredentialsPrompterImpl *pro + + prompter_google = E_CREDENTIALS_PROMPTER_IMPL_GOOGLE (prompter_impl); + g_return_if_fail (prompter_google->priv->prompt_id == NULL); +- g_return_if_fail (prompter_google->priv->show_dialog_idle_id == 0); ++ ++ g_mutex_lock (&prompter_google->priv->property_lock); ++ if (prompter_google->priv->show_dialog_idle_id != 0) { ++ g_mutex_unlock (&prompter_google->priv->property_lock); ++ g_warning ("%s: Already processing other prompt", G_STRFUNC); ++ return; ++ } ++ g_mutex_unlock (&prompter_google->priv->property_lock); + + prompter_google->priv->prompt_id = prompt_id; + prompter_google->priv->auth_source = g_object_ref (auth_source); +@@ -1021,9 +1040,11 @@ e_credentials_prompter_impl_google_process_prompt (ECredentialsPrompterImpl *pro + g_thread_unref (thread); + } else { + #endif /* ENABLE_GOOGLE_AUTH */ ++ g_mutex_lock (&prompter_google->priv->property_lock); + prompter_google->priv->show_dialog_idle_id = g_idle_add ( + e_credentials_prompter_impl_google_manage_dialog_idle_cb, + prompter_google); ++ g_mutex_unlock (&prompter_google->priv->property_lock); + #ifdef ENABLE_GOOGLE_AUTH + } + #endif /* ENABLE_GOOGLE_AUTH */ +@@ -1053,10 +1074,12 @@ e_credentials_prompter_impl_google_dispose (GObject *object) + { + ECredentialsPrompterImplGoogle *prompter_google = E_CREDENTIALS_PROMPTER_IMPL_GOOGLE (object); + ++ g_mutex_lock (&prompter_google->priv->property_lock); + if (prompter_google->priv->show_dialog_idle_id) { + g_source_remove (prompter_google->priv->show_dialog_idle_id); + prompter_google->priv->show_dialog_idle_id = 0; + } ++ g_mutex_unlock (&prompter_google->priv->property_lock); + + if (prompter_google->priv->cancellable) { + g_cancellable_cancel (prompter_google->priv->cancellable); +diff --git a/libedataserverui/e-credentials-prompter.c b/libedataserverui/e-credentials-prompter.c +index 40c39a7..1e0458e 100644 +--- a/libedataserverui/e-credentials-prompter.c ++++ b/libedataserverui/e-credentials-prompter.c +@@ -152,7 +152,7 @@ credentials_prompter_lookup_source_details_thread (GTask *task, + provider = e_credentials_prompter_get_provider (prompter); + cred_source = e_source_credentials_provider_ref_credentials_source (provider, source); + +- e_source_credentials_provider_lookup_sync (prompter->priv->provider, cred_source ? cred_source : source, cancellable, &credentials, &local_error); ++ e_source_credentials_provider_lookup_sync (provider, cred_source ? cred_source : source, cancellable, &credentials, &local_error); + + /* Interested only in the cancelled error, which means the prompter is freed. */ + if (local_error != NULL && g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { +@@ -760,19 +760,29 @@ credentials_prompter_credentials_required_cb (ESourceRegistry *registry, + const GError *op_error, + ECredentialsPrompter *prompter) + { ++ ESource *cred_source; ++ + g_return_if_fail (E_IS_SOURCE_REGISTRY (registry)); + g_return_if_fail (E_IS_SOURCE (source)); + g_return_if_fail (E_IS_CREDENTIALS_PROMPTER (prompter)); + + /* Only these two reasons are meant to be used to prompt the user for credentials. */ + if (reason != E_SOURCE_CREDENTIALS_REASON_REQUIRED && +- reason != E_SOURCE_CREDENTIALS_REASON_REJECTED) ++ reason != E_SOURCE_CREDENTIALS_REASON_REJECTED) { + return; ++ } ++ ++ cred_source = e_source_credentials_provider_ref_credentials_source (e_credentials_prompter_get_provider (prompter), source); + + /* Global auto-prompt or the source's auto-prompt is disabled. */ + if (!e_credentials_prompter_get_auto_prompt (prompter) || +- e_credentials_prompter_get_auto_prompt_disabled_for (prompter, source)) ++ (e_credentials_prompter_get_auto_prompt_disabled_for (prompter, source) && ++ (!cred_source || e_credentials_prompter_get_auto_prompt_disabled_for (prompter, cred_source)))) { ++ g_clear_object (&cred_source); + return; ++ } ++ ++ g_clear_object (&cred_source); + + /* This is a re-prompt, but the source cannot be prompted for credentials. */ + if (reason == E_SOURCE_CREDENTIALS_REASON_REJECTED && +-- +cgit v0.12 + diff --git a/evolution-data-server.changes b/evolution-data-server.changes index 3c73842..891ad7e 100644 --- a/evolution-data-server.changes +++ b/evolution-data-server.changes @@ -1,3 +1,13 @@ +------------------------------------------------------------------- +Sat Sep 24 23:21:51 UTC 2016 - zaitor@opensuse.org + +- Add eds-Internal_Google_OAuth2_authentication.patch: Internal + Google OAuth2 authentication fails with expired token + (bgo#771547). +- Conditionally apply translations-update-upstream BuildRequires + and macro for non-openSUSE only. +- Stop passing V=1 to make, we do debugging locally. + ------------------------------------------------------------------- Mon Sep 19 08:42:50 UTC 2016 - zaitor@opensuse.org diff --git a/evolution-data-server.spec b/evolution-data-server.spec index 193770e..6195fcc 100644 --- a/evolution-data-server.spec +++ b/evolution-data-server.spec @@ -41,6 +41,8 @@ Group: Development/Libraries/GNOME Url: http://www.gnome.org Source0: http://download.gnome.org/sources/evolution-data-server/3.22/%{name}-%{version}.tar.xz Source99: baselibs.conf +# PATCH-FIX-UPSTREAM eds-Internal_Google_OAuth2_authentication.patch bgo#771547 zaitor@opensuse.org -- Internal Google OAuth2 authentication fails with expired token +Patch0: eds-Internal_Google_OAuth2_authentication.patch BuildRequires: db-devel %if %USE_EVOLDAP BuildRequires: evoldap2-devel @@ -63,7 +65,9 @@ BuildRequires: mozilla-nss-devel BuildRequires: nss-shared-helper-devel BuildRequires: python-devel BuildRequires: sqlite3-devel >= 3.7.17 +%if !0%{?is_opensuse} BuildRequires: translation-update-upstream +%endif BuildRequires: vala >= 0.22.0 BuildRequires: pkgconfig(gcr-base-3) >= 3.4 BuildRequires: pkgconfig(goa-1.0) >= 3.8 @@ -268,7 +272,10 @@ This package contains developer documentation. %lang_package %prep %setup -q +%patch0 -p1 +%if !0%{?is_opensuse} translation-update-upstream +%endif %build %{configure} \ @@ -291,7 +298,7 @@ translation-update-upstream --disable-vala-bindings \ --disable-introspection %endif -make %{?_smp_mflags} V=1 +make %{?_smp_mflags} %install %{makeinstall}