diff options
| author | Carlos Garcia Campos <cgarcia@igalia.com> | 2020-10-26 10:20:01 +0100 |
|---|---|---|
| committer | Carlos Garcia Campos <cgarcia@igalia.com> | 2020-10-28 09:36:28 +0100 |
| commit | 8a918ee3cd75def6f9c1a6bdcb1008e99684ec6b (patch) | |
| tree | fb2e595e7ef0e253ba97e7f05fe5cf9173f824da /libsoup/auth | |
| parent | 50248a9d3127eec834e9b9450ea26d98683d0d55 (diff) | |
| download | libsoup-8a918ee3cd75def6f9c1a6bdcb1008e99684ec6b.tar.gz | |
Move authenticate signal from SoupSession to SoupMessage
In case of tunneling the authenticate signal is emitted in the original
message, since the tunneling message is an internal implementation
detail. The authenticate signal is now true handled, and SoupAuthManager
automatically pauses and unpauses the message when handled
asynchronously. soup_auth_cancel() has been added to complete an async
authentication when no credentials are provided.
Diffstat (limited to 'libsoup/auth')
| -rw-r--r-- | libsoup/auth/soup-auth-manager.c | 37 | ||||
| -rw-r--r-- | libsoup/auth/soup-auth.c | 100 | ||||
| -rw-r--r-- | libsoup/auth/soup-auth.h | 8 |
3 files changed, 142 insertions, 3 deletions
diff --git a/libsoup/auth/soup-auth-manager.c b/libsoup/auth/soup-auth-manager.c index 86f249d4..2af4a0b5 100644 --- a/libsoup/auth/soup-auth-manager.c +++ b/libsoup/auth/soup-auth-manager.c @@ -508,6 +508,21 @@ lookup_proxy_auth (SoupAuthManagerPrivate *priv, SoupMessage *msg) } static void +async_auth_finished (SoupAuth *auth, + GParamSpec *pspec, + SoupMessage *msg) +{ + SoupSession *session; + + session = g_object_steal_data (G_OBJECT (msg), "auth-msg-session"); + if (!session) + return; + + soup_session_unpause_message (session, msg); + g_object_unref (session); +} + +static void authenticate_auth (SoupAuthManager *manager, SoupAuth *auth, SoupMessage *msg, gboolean prior_auth_failed, gboolean proxy, gboolean can_interact) @@ -533,8 +548,24 @@ authenticate_auth (SoupAuthManager *manager, SoupAuth *auth, soup_uri_set_password (uri, NULL); soup_uri_set_user (uri, NULL); } else if (!soup_auth_is_authenticated (auth) && can_interact) { - g_signal_emit (manager, signals[AUTHENTICATE], 0, - msg, auth, prior_auth_failed); + SoupMessage *original_msg; + gboolean handled; + + original_msg = soup_session_get_original_message_for_authentication (priv->session, + msg); + handled = soup_message_authenticate (original_msg, auth, prior_auth_failed); + if (handled && !soup_auth_is_authenticated (auth)) { + soup_session_pause_message (priv->session, msg); + g_object_set_data_full (G_OBJECT (msg), "auth-msg-session", + g_object_ref (priv->session), + g_object_unref); + g_signal_connect_object (auth, "notify::is-authenticated", + G_CALLBACK (async_auth_finished), + msg, 0); + g_signal_connect_object (auth, "notify::is-cancelled", + G_CALLBACK (async_auth_finished), + msg, 0); + } } } @@ -578,7 +609,7 @@ record_auth_for_uri (SoupAuthManagerPrivate *priv, SoupURI *uri, * since the old one might already be authenticated.) */ old_auth = g_hash_table_lookup (host->auths, auth_info); - if (old_auth && (old_auth != auth || !prior_auth_failed)) { + if (old_auth && (old_auth != auth || !prior_auth_failed) && !soup_auth_is_cancelled (old_auth)) { g_free (auth_info); return old_auth; } else { diff --git a/libsoup/auth/soup-auth.c b/libsoup/auth/soup-auth.c index 881ed9f9..62d0a677 100644 --- a/libsoup/auth/soup-auth.c +++ b/libsoup/auth/soup-auth.c @@ -38,6 +38,7 @@ typedef struct { char *realm; char *host; gboolean proxy; + gboolean cancelled; } SoupAuthPrivate; G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (SoupAuth, soup_auth, G_TYPE_OBJECT) @@ -50,6 +51,7 @@ enum { PROP_HOST, PROP_IS_FOR_PROXY, PROP_IS_AUTHENTICATED, + PROP_IS_CANCELLED, LAST_PROP }; @@ -60,6 +62,18 @@ soup_auth_init (SoupAuth *auth) } static void +soup_auth_dispose (GObject *object) +{ + SoupAuth *auth = SOUP_AUTH (object); + SoupAuthPrivate *priv = soup_auth_get_instance_private (auth); + + if (!priv->cancelled && !soup_auth_is_authenticated (auth)) + soup_auth_cancel (auth); + + G_OBJECT_CLASS (soup_auth_parent_class)->dispose (object); +} + +static void soup_auth_finalize (GObject *object) { SoupAuth *auth = SOUP_AUTH (object); @@ -119,6 +133,8 @@ soup_auth_get_property (GObject *object, guint prop_id, case PROP_IS_AUTHENTICATED: g_value_set_boolean (value, soup_auth_is_authenticated (auth)); break; + case PROP_IS_CANCELLED: + g_value_set_boolean (value, priv->cancelled); default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -138,6 +154,7 @@ soup_auth_class_init (SoupAuthClass *auth_class) auth_class->can_authenticate = auth_can_authenticate; + object_class->dispose = soup_auth_dispose; object_class->finalize = soup_auth_finalize; object_class->set_property = soup_auth_set_property; object_class->get_property = soup_auth_get_property; @@ -208,6 +225,20 @@ soup_auth_class_init (SoupAuthClass *auth_class) FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + /** + * SoupAuth:is-cancelled: + * + * An alias for the #SoupAuth:is-cancelled property. + * (Whether or not the auth has been cancelled.) + **/ + g_object_class_install_property ( + object_class, PROP_IS_CANCELLED, + g_param_spec_boolean ("is-cancelled", + "Cancelled", + "Whether or not the auth is cancelled", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); } /** @@ -289,6 +320,9 @@ soup_auth_update (SoupAuth *auth, SoupMessage *msg, const char *auth_header) g_return_val_if_fail (SOUP_IS_MESSAGE (msg), FALSE); g_return_val_if_fail (auth_header != NULL, FALSE); + if (priv->cancelled) + return FALSE; + scheme = soup_auth_get_scheme_name (auth); if (g_ascii_strncasecmp (auth_header, scheme, strlen (scheme)) != 0) return FALSE; @@ -323,12 +357,17 @@ soup_auth_update (SoupAuth *auth, SoupMessage *msg, const char *auth_header) void soup_auth_authenticate (SoupAuth *auth, const char *username, const char *password) { + SoupAuthPrivate *priv; gboolean was_authenticated; g_return_if_fail (SOUP_IS_AUTH (auth)); g_return_if_fail (username != NULL); g_return_if_fail (password != NULL); + priv = soup_auth_get_instance_private (auth); + if (priv->cancelled) + return; + was_authenticated = soup_auth_is_authenticated (auth); SOUP_AUTH_GET_CLASS (auth)->authenticate (auth, username, password); if (was_authenticated != soup_auth_is_authenticated (auth)) @@ -336,6 +375,30 @@ soup_auth_authenticate (SoupAuth *auth, const char *username, const char *passwo } /** + * soup_auth_cancel: + * @auth: a #SoupAuth + * + * Call this on an auth to cancel it. You need to cancel an auth to complete + * an asynchronous authenticate operation when no credentials are provided + * (soup_auth_authenticate() is not called). + * The #SoupAuth will be cancelled on dispose if it hans't been authenticated. + */ +void +soup_auth_cancel (SoupAuth *auth) +{ + SoupAuthPrivate *priv; + + g_return_if_fail (SOUP_IS_AUTH (auth)); + + priv = soup_auth_get_instance_private (auth); + if (priv->cancelled) + return; + + priv->cancelled = TRUE; + g_object_notify (G_OBJECT (auth), "is-cancelled"); +} + +/** * soup_auth_is_for_proxy: * @auth: a #SoupAuth * @@ -447,12 +510,37 @@ soup_auth_get_info (SoupAuth *auth) gboolean soup_auth_is_authenticated (SoupAuth *auth) { + SoupAuthPrivate *priv; + g_return_val_if_fail (SOUP_IS_AUTH (auth), TRUE); + priv = soup_auth_get_instance_private (auth); + if (priv->cancelled) + return FALSE; + return SOUP_AUTH_GET_CLASS (auth)->is_authenticated (auth); } /** + * soup_auth_is_cancelled: + * @auth: a #SoupAuth + * + * Tests if @auth has been cancelled + * + * Returns: %TRUE if @auth has been cancelled + */ +gboolean +soup_auth_is_cancelled (SoupAuth *auth) +{ + SoupAuthPrivate *priv; + + g_return_val_if_fail (SOUP_IS_AUTH (auth), TRUE); + + priv = soup_auth_get_instance_private (auth); + return priv->cancelled; +} + +/** * soup_auth_get_authorization: * @auth: a #SoupAuth * @msg: the #SoupMessage to be authorized @@ -490,9 +578,15 @@ gboolean soup_auth_is_ready (SoupAuth *auth, SoupMessage *msg) { + SoupAuthPrivate *priv; + g_return_val_if_fail (SOUP_IS_AUTH (auth), TRUE); g_return_val_if_fail (SOUP_IS_MESSAGE (msg), TRUE); + priv = soup_auth_get_instance_private (auth); + if (priv->cancelled) + return FALSE; + if (SOUP_AUTH_GET_CLASS (auth)->is_ready) return SOUP_AUTH_GET_CLASS (auth)->is_ready (auth, msg); else @@ -513,8 +607,14 @@ soup_auth_is_ready (SoupAuth *auth, gboolean soup_auth_can_authenticate (SoupAuth *auth) { + SoupAuthPrivate *priv; + g_return_val_if_fail (SOUP_IS_AUTH (auth), FALSE); + priv = soup_auth_get_instance_private (auth); + if (priv->cancelled) + return FALSE; + return SOUP_AUTH_GET_CLASS (auth)->can_authenticate (auth); } diff --git a/libsoup/auth/soup-auth.h b/libsoup/auth/soup-auth.h index ab3f2519..284aa3da 100644 --- a/libsoup/auth/soup-auth.h +++ b/libsoup/auth/soup-auth.h @@ -67,8 +67,16 @@ SOUP_AVAILABLE_IN_2_4 void soup_auth_authenticate (SoupAuth *auth, const char *username, const char *password); + +SOUP_AVAILABLE_IN_ALL +void soup_auth_cancel (SoupAuth *auth); + SOUP_AVAILABLE_IN_2_4 gboolean soup_auth_is_authenticated (SoupAuth *auth); + +SOUP_AVAILABLE_IN_ALL +gboolean soup_auth_is_cancelled (SoupAuth *auth); + SOUP_AVAILABLE_IN_2_42 gboolean soup_auth_is_ready (SoupAuth *auth, SoupMessage *msg); |
