[libsoup] soup-session: don't resolve default proxy-resolver/tlsdb if not needed



commit d1cb3455a7278a7a5d8ac770852ae489a54e6452
Author: Dan Winship <danw gnome org>
Date:   Sun Sep 29 16:23:53 2013 -0400

    soup-session: don't resolve default proxy-resolver/tlsdb if not needed
    
    If the user overrides the proxy or TLS configuration of a session at
    construct time, we should avoid ever trying to resolve the default
    extensions.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=708696

 libsoup/soup-session.c |   62 +++++++++++++++++++----
 tests/session-test.c   |  130 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 182 insertions(+), 10 deletions(-)
---
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index a9258ef..bd586cd 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -88,6 +88,7 @@ typedef struct {
        GTlsDatabase *tlsdb;
        char *ssl_ca_file;
        gboolean ssl_strict;
+       gboolean tlsdb_use_default;
 
        SoupMessageQueue *queue;
 
@@ -122,6 +123,7 @@ typedef struct {
 
        GResolver *resolver;
        GProxyResolver *proxy_resolver;
+       gboolean proxy_use_default;
        SoupURI *proxy_uri;
 
        char **http_aliases, **https_aliases;
@@ -268,9 +270,6 @@ soup_session_constructor (GType                  type,
                SoupSession *session = SOUP_SESSION (object);
                SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
 
-               g_clear_object (&priv->tlsdb);
-               priv->tlsdb = g_tls_backend_get_default_database (g_tls_backend_get_default ());
-
                g_clear_pointer (&priv->async_context, g_main_context_unref);
                priv->async_context = g_main_context_ref_thread_default ();
                priv->use_thread_context = TRUE;
@@ -279,7 +278,12 @@ soup_session_constructor (GType                  type,
 
                priv->http_aliases[0] = NULL;
 
-               priv->proxy_resolver = g_object_ref (g_proxy_resolver_get_default ());
+               /* If the user overrides the proxy or tlsdb during construction,
+                * we don't want to needlessly resolve the extension point. So
+                * we just set flags saying to do it later.
+                */
+               priv->proxy_use_default = TRUE;
+               priv->tlsdb_use_default = TRUE;
 
                soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER);
        }
@@ -435,6 +439,7 @@ set_tlsdb (SoupSession *session, GTlsDatabase *tlsdb)
        SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
        GTlsDatabase *system_default;
 
+       priv->tlsdb_use_default = FALSE;
        if (tlsdb == priv->tlsdb)
                return;
 
@@ -470,6 +475,8 @@ set_use_system_ca_file (SoupSession *session, gboolean use_system_ca_file)
        SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
        GTlsDatabase *system_default;
 
+       priv->tlsdb_use_default = FALSE;
+
        system_default = g_tls_backend_get_default_database (g_tls_backend_get_default ());
 
        if (use_system_ca_file)
@@ -487,6 +494,7 @@ set_ssl_ca_file (SoupSession *session, const char *ssl_ca_file)
        GTlsDatabase *tlsdb;
        GError *error = NULL;
 
+       priv->tlsdb_use_default = FALSE;
        if (!g_strcmp0 (priv->ssl_ca_file, ssl_ca_file))
                return;
 
@@ -562,6 +570,7 @@ set_proxy_resolver (SoupSession *session, SoupURI *uri,
        G_GNUC_END_IGNORE_DEPRECATIONS;
        g_clear_object (&priv->proxy_resolver);
        g_clear_pointer (&priv->proxy_uri, soup_uri_free);
+       priv->proxy_use_default = FALSE;
 
        if (uri) {
                char *uri_string;
@@ -711,6 +720,30 @@ soup_session_set_property (GObject *object, guint prop_id,
        }
 }
 
+static GProxyResolver *
+get_proxy_resolver (SoupSession *session)
+{
+       SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
+
+       if (priv->proxy_use_default) {
+               priv->proxy_resolver = g_object_ref (g_proxy_resolver_get_default ());
+               priv->proxy_use_default = FALSE;
+       }
+       return priv->proxy_resolver;
+}
+
+static GTlsDatabase *
+get_tls_database (SoupSession *session)
+{
+       SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
+
+       if (priv->tlsdb_use_default) {
+               priv->tlsdb = g_tls_backend_get_default_database (g_tls_backend_get_default ());
+               priv->tlsdb_use_default = FALSE;
+       }
+       return priv->tlsdb;
+}
+
 static void
 soup_session_get_property (GObject *object, guint prop_id,
                           GValue *value, GParamSpec *pspec)
@@ -728,7 +761,7 @@ soup_session_get_property (GObject *object, guint prop_id,
                g_value_set_boxed (value, priv->proxy_uri);
                break;
        case PROP_PROXY_RESOLVER:
-               g_value_set_object (value, priv->proxy_resolver);
+               g_value_set_object (value, get_proxy_resolver (session));
                break;
        case PROP_MAX_CONNS:
                g_value_set_int (value, priv->max_conns);
@@ -748,11 +781,11 @@ soup_session_get_property (GObject *object, guint prop_id,
                break;
        case PROP_SSL_USE_SYSTEM_CA_FILE:
                tlsdb = g_tls_backend_get_default_database (g_tls_backend_get_default ());
-               g_value_set_boolean (value, priv->tlsdb == tlsdb);
+               g_value_set_boolean (value, get_tls_database (session) == tlsdb);
                g_clear_object (&tlsdb);
                break;
        case PROP_TLS_DATABASE:
-               g_value_set_object (value, priv->tlsdb);
+               g_value_set_object (value, get_tls_database (session));
                break;
        case PROP_SSL_STRICT:
                g_value_set_boolean (value, priv->ssl_strict);
@@ -1609,6 +1642,8 @@ get_connection_for_host (SoupSession *session,
        SoupConnection *conn;
        GSList *conns;
        int num_pending = 0;
+       GProxyResolver *proxy_resolver;
+       GTlsDatabase *tlsdb;
 
        if (priv->disposed)
                return FALSE;
@@ -1645,13 +1680,16 @@ get_connection_for_host (SoupSession *session,
                return NULL;
        }
 
+       proxy_resolver = get_proxy_resolver (session);
+       tlsdb = get_tls_database (session);
+
        conn = g_object_new (
                SOUP_TYPE_CONNECTION,
                SOUP_CONNECTION_REMOTE_URI, host->uri,
-               SOUP_CONNECTION_PROXY_RESOLVER, priv->proxy_resolver,
+               SOUP_CONNECTION_PROXY_RESOLVER, proxy_resolver,
                SOUP_CONNECTION_SSL, soup_uri_is_https (soup_message_get_uri (item->msg), 
priv->https_aliases),
-               SOUP_CONNECTION_SSL_CREDENTIALS, priv->tlsdb,
-               SOUP_CONNECTION_SSL_STRICT, priv->ssl_strict && (priv->tlsdb != NULL || SOUP_IS_PLAIN_SESSION 
(session)),
+               SOUP_CONNECTION_SSL_CREDENTIALS, tlsdb,
+               SOUP_CONNECTION_SSL_STRICT, priv->ssl_strict && (tlsdb != NULL || SOUP_IS_PLAIN_SESSION 
(session)),
                SOUP_CONNECTION_ASYNC_CONTEXT, priv->async_context,
                SOUP_CONNECTION_USE_THREAD_CONTEXT, priv->use_thread_context,
                SOUP_CONNECTION_TIMEOUT, priv->io_timeout,
@@ -2593,6 +2631,10 @@ soup_session_remove_feature_by_type (SoupSession *session, GType feature_type)
                                goto restart;
                        }
                }
+               G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
+               if (g_type_is_a (feature_type, SOUP_TYPE_PROXY_URI_RESOLVER))
+                       priv->proxy_use_default = FALSE;
+               G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
        } else if (g_type_is_a (feature_type, SOUP_TYPE_REQUEST)) {
                SoupRequestClass *request_class;
                int i;
diff --git a/tests/session-test.c b/tests/session-test.c
index b8e224e..d40e776 100644
--- a/tests/session-test.c
+++ b/tests/session-test.c
@@ -263,6 +263,135 @@ do_priority_tests (char *uri)
        soup_test_session_abort_unref (session);
 }
 
+static void
+test_session_properties (const char *name,
+                        SoupSession *session,
+                        GProxyResolver *expected_proxy_resolver,
+                        GTlsDatabase *expected_tls_database)
+{
+       GProxyResolver *proxy_resolver = NULL;
+       GTlsDatabase *tlsdb = NULL;
+
+       g_object_get (G_OBJECT (session),
+                     SOUP_SESSION_PROXY_RESOLVER, &proxy_resolver,
+                     SOUP_SESSION_TLS_DATABASE, &tlsdb,
+                     NULL);
+       if (proxy_resolver != expected_proxy_resolver) {
+               debug_printf (1, "  %s has %s proxy resolver!\n",
+                             name, proxy_resolver ? (expected_proxy_resolver ? "wrong" : "a") : "no");
+               errors++;
+       }
+       if (tlsdb != expected_tls_database) {
+               debug_printf (1, "  %s has %s TLS database!\n",
+                             name, tlsdb ? (expected_tls_database ? "wrong" : "a") : "no");
+               errors++;
+       }
+       g_clear_object (&proxy_resolver);
+       g_clear_object (&tlsdb);
+}
+
+static void
+do_property_tests (void)
+{
+       SoupSession *session;
+       GProxyResolver *proxy_resolver, *default_proxy_resolver;
+       GTlsDatabase *tlsdb, *default_tlsdb;
+       SoupURI *uri;
+
+       debug_printf (1, "\nTesting session init properties\n");
+
+       default_proxy_resolver = g_proxy_resolver_get_default ();
+       default_tlsdb = g_tls_backend_get_default_database (g_tls_backend_get_default ());
+
+       /* NOTE: We intentionally do not use soup_test_session_new() here */
+
+       session = g_object_new (SOUP_TYPE_SESSION,
+                               NULL);
+       test_session_properties ("Base plain session", session,
+                                default_proxy_resolver, default_tlsdb);
+       g_object_unref (session);
+
+       session = g_object_new (SOUP_TYPE_SESSION,
+                               SOUP_SESSION_PROXY_RESOLVER, NULL,
+                               NULL);
+       test_session_properties ("Session with NULL :proxy-resolver", session,
+                                NULL, default_tlsdb);
+       g_object_unref (session);
+
+       proxy_resolver = g_simple_proxy_resolver_new (NULL, NULL);
+       session = g_object_new (SOUP_TYPE_SESSION,
+                               SOUP_SESSION_PROXY_RESOLVER, proxy_resolver,
+                               NULL);
+       test_session_properties ("Session with non-NULL :proxy-resolver", session,
+                                proxy_resolver, default_tlsdb);
+       g_object_unref (proxy_resolver);
+       g_object_unref (session);
+
+       session = g_object_new (SOUP_TYPE_SESSION,
+                               SOUP_SESSION_PROXY_URI, NULL,
+                               NULL);
+       test_session_properties ("Session with NULL :proxy-uri", session,
+                                NULL, default_tlsdb);
+       g_object_unref (session);
+
+       uri = soup_uri_new ("http://example.com/";);
+       session = g_object_new (SOUP_TYPE_SESSION,
+                               SOUP_SESSION_PROXY_URI, uri,
+                               NULL);
+       g_object_get (G_OBJECT (session),
+                     SOUP_SESSION_PROXY_RESOLVER, &proxy_resolver,
+                     NULL);
+       test_session_properties ("Session with non-NULL :proxy-uri", session,
+                                proxy_resolver, default_tlsdb);
+       if (!G_IS_SIMPLE_PROXY_RESOLVER (proxy_resolver)) {
+               debug_printf (1, "  proxy resolver had wrong type (%s)\n",
+                             G_OBJECT_TYPE_NAME (proxy_resolver));
+               errors++;
+       }
+       g_object_unref (proxy_resolver);
+       g_object_unref (session);
+       soup_uri_free (uri);
+
+       G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
+       session = g_object_new (SOUP_TYPE_SESSION,
+                               SOUP_SESSION_REMOVE_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_URI_RESOLVER,
+                               NULL);
+       test_session_properties ("Session with removed proxy resolver feature", session,
+                                NULL, default_tlsdb);
+       g_object_unref (session);
+       G_GNUC_END_IGNORE_DEPRECATIONS;
+
+       session = g_object_new (SOUP_TYPE_SESSION,
+                               SOUP_SESSION_TLS_DATABASE, NULL,
+                               NULL);
+       test_session_properties ("Session with NULL :tls-database", session,
+                                default_proxy_resolver, NULL);
+       g_object_unref (session);
+
+       tlsdb = g_tls_file_database_new (SRCDIR "/test-cert.pem", NULL);
+       session = g_object_new (SOUP_TYPE_SESSION,
+                               SOUP_SESSION_TLS_DATABASE, tlsdb,
+                               NULL);
+       test_session_properties ("Session with non-NULL :tls-database", session,
+                                default_proxy_resolver, tlsdb);
+       g_object_unref (tlsdb);
+       g_object_unref (session);
+
+       session = g_object_new (SOUP_TYPE_SESSION,
+                               SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, FALSE,
+                               NULL);
+       test_session_properties ("Session with :ssl-use-system-ca-file FALSE", session,
+                                default_proxy_resolver, NULL);
+       g_object_unref (session);
+
+       session = g_object_new (SOUP_TYPE_SESSION,
+                               SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, TRUE,
+                               NULL);
+       test_session_properties ("Session with :ssl-use-system-ca-file TRUE", session,
+                                default_proxy_resolver, default_tlsdb);
+       g_object_unref (session);
+}
+
 int
 main (int argc, char **argv)
 {
@@ -281,6 +410,7 @@ main (int argc, char **argv)
        do_async_tests (uri, timeout_uri);
        do_sync_tests (uri, timeout_uri);
        do_priority_tests (uri);
+       do_property_tests ();
 
        g_free (uri);
        g_free (timeout_uri);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]