From 63d1350ed10d91a5915ef47fb0a92c43b70c7686 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Sun, 17 Feb 2013 19:30:29 -0500 Subject: [PATCH] EBackend: Add a "connectable" property (GSocketConnectable). This is the socket endpoint for the network service to which the EBackend is a client. This can be NULL if the EBackend does not use network sockets. The initial value of the "connectable" property is derived from the ESourceAuthentication extension of the EBackend's "source" property, if the extension is present. --- .../reference/libebackend/libebackend-sections.txt | 2 + libebackend/e-backend.c | 148 +++++++++++++++++++++ libebackend/e-backend.h | 4 + 3 files changed, 154 insertions(+) diff --git a/docs/reference/libebackend/libebackend-sections.txt b/docs/reference/libebackend/libebackend-sections.txt index 9854be2..81e59b2 100644 --- a/docs/reference/libebackend/libebackend-sections.txt +++ b/docs/reference/libebackend/libebackend-sections.txt @@ -77,6 +77,8 @@ EBackend e_backend_get_online e_backend_set_online e_backend_get_source +e_backend_ref_connectable +e_backend_set_connectable e_backend_authenticate_sync e_backend_authenticate e_backend_authenticate_finish diff --git a/libebackend/e-backend.c b/libebackend/e-backend.c index eb71e3e..8c36b0f 100644 --- a/libebackend/e-backend.c +++ b/libebackend/e-backend.c @@ -48,8 +48,10 @@ typedef struct _AsyncContext AsyncContext; struct _EBackendPrivate { + GMutex property_lock; ESource *source; EUserPrompter *prompter; + GSocketConnectable *connectable; gboolean online; }; @@ -59,6 +61,7 @@ struct _AsyncContext { enum { PROP_0, + PROP_CONNECTABLE, PROP_ONLINE, PROP_SOURCE, PROP_USER_PROMPTER @@ -92,6 +95,12 @@ backend_set_property (GObject *object, GParamSpec *pspec) { switch (property_id) { + case PROP_CONNECTABLE: + e_backend_set_connectable ( + E_BACKEND (object), + g_value_get_object (value)); + return; + case PROP_ONLINE: e_backend_set_online ( E_BACKEND (object), @@ -115,6 +124,12 @@ backend_get_property (GObject *object, GParamSpec *pspec) { switch (property_id) { + case PROP_CONNECTABLE: + g_value_take_object ( + value, e_backend_ref_connectable ( + E_BACKEND (object))); + return; + case PROP_ONLINE: g_value_set_boolean ( value, e_backend_get_online ( @@ -146,19 +161,66 @@ backend_dispose (GObject *object) g_clear_object (&priv->source); g_clear_object (&priv->prompter); + g_clear_object (&priv->connectable); /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (e_backend_parent_class)->dispose (object); } static void +backend_finalize (GObject *object) +{ + EBackendPrivate *priv; + + priv = E_BACKEND_GET_PRIVATE (object); + + g_mutex_clear (&priv->property_lock); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (e_backend_parent_class)->finalize (object); +} + +static void backend_constructed (GObject *object) { + EBackend *backend; + ESource *source; GNetworkMonitor *monitor; + const gchar *extension_name; + + backend = E_BACKEND (object); /* Chain up to parent's constructed() method. */ G_OBJECT_CLASS (e_backend_parent_class)->constructed (object); + /* Create an initial GSocketConnectable from the data + * source's [Authentication] extension, if present. */ + source = e_backend_get_source (backend); + extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; + if (e_source_has_extension (source, extension_name)) { + ESourceAuthentication *extension; + gchar *host; + guint16 port; + + extension = e_source_get_extension (source, extension_name); + host = e_source_authentication_dup_host (extension); + port = e_source_authentication_get_port (extension); + + /* XXX We should realy check both host and port, but + * too many backends neglect to set a port number. + * Need to fix that first before we can insist on + * a valid port number. */ + if (host != NULL) { + GSocketConnectable *connectable; + + connectable = g_network_address_new (host, port); + e_backend_set_connectable (backend, connectable); + g_object_unref (connectable); + } + + g_free (host); + } + /* Synchronize network monitoring. */ monitor = g_network_monitor_get_default (); @@ -270,6 +332,7 @@ e_backend_class_init (EBackendClass *class) object_class->set_property = backend_set_property; object_class->get_property = backend_get_property; object_class->dispose = backend_dispose; + object_class->finalize = backend_finalize; object_class->constructed = backend_constructed; class->authenticate_sync = backend_authenticate_sync; @@ -279,6 +342,17 @@ e_backend_class_init (EBackendClass *class) g_object_class_install_property ( object_class, + PROP_CONNECTABLE, + g_param_spec_object ( + "connectable", + "Connectable", + "Socket endpoint of a network service", + G_TYPE_SOCKET_CONNECTABLE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, PROP_ONLINE, g_param_spec_boolean ( "online", @@ -318,6 +392,8 @@ e_backend_init (EBackend *backend) { backend->priv = E_BACKEND_GET_PRIVATE (backend); backend->priv->prompter = e_user_prompter_new (); + + g_mutex_init (&backend->priv->property_lock); } /** @@ -385,6 +461,78 @@ e_backend_get_source (EBackend *backend) } /** + * e_backend_ref_connectable: + * @backend: an #EBackend + * + * Returns the socket endpoint for the network service to which @backend + * is a client, or %NULL if @backend does not use network sockets. + * + * The initial value of the #EBackend:connectable property is derived from + * the #ESourceAuthentication extension of the @backend's #EBackend:source + * property, if the extension is present. + * + * The returned #GSocketConnectable is referenced for thread-safety and + * must be unreferenced with g_object_unref() when finished with it. + * + * Returns: a #GSocketConnectable, or %NULL + * + * Since: 3.8 + **/ +GSocketConnectable * +e_backend_ref_connectable (EBackend *backend) +{ + GSocketConnectable *connectable = NULL; + + g_return_val_if_fail (E_IS_BACKEND (backend), NULL); + + g_mutex_lock (&backend->priv->property_lock); + + if (backend->priv->connectable != NULL) + connectable = g_object_ref (backend->priv->connectable); + + g_mutex_unlock (&backend->priv->property_lock); + + return connectable; +} + +/** + * e_backend_set_connectable: + * @backend: an #EBackend + * @connectable: a #GSocketConnectable, or %NULL + * + * Sets the socket endpoint for the network service to which @backend is + * a client. This can be %NULL if @backend does not use network sockets. + * + * The initial value of the #EBackend:connectable property is derived from + * the #ESourceAuthentication extension of the @backend's #EBackend:source + * property, if the extension is present. + * + * Since: 3.8 + **/ +void +e_backend_set_connectable (EBackend *backend, + GSocketConnectable *connectable) +{ + g_return_if_fail (E_IS_BACKEND (backend)); + + if (connectable != NULL) { + g_return_if_fail (G_IS_SOCKET_CONNECTABLE (connectable)); + g_object_ref (connectable); + } + + g_mutex_lock (&backend->priv->property_lock); + + if (backend->priv->connectable != NULL) + g_object_unref (backend->priv->connectable); + + backend->priv->connectable = connectable; + + g_mutex_unlock (&backend->priv->property_lock); + + g_object_notify (G_OBJECT (backend), "connectable"); +} + +/** * e_backend_authenticate_sync: * @backend: an #EBackend * @auth: an #ESourceAuthenticator diff --git a/libebackend/e-backend.h b/libebackend/e-backend.h index c0af453..b99527a 100644 --- a/libebackend/e-backend.h +++ b/libebackend/e-backend.h @@ -96,6 +96,10 @@ gboolean e_backend_get_online (EBackend *backend); void e_backend_set_online (EBackend *backend, gboolean online); ESource * e_backend_get_source (EBackend *backend); +GSocketConnectable * + e_backend_ref_connectable (EBackend *backend); +void e_backend_set_connectable (EBackend *backend, + GSocketConnectable *connectable); gboolean e_backend_authenticate_sync (EBackend *backend, ESourceAuthenticator *auth, GCancellable *cancellable, -- 2.7.4