diff options
author | Benjamin Berg <bberg@redhat.com> | 2019-01-31 15:30:45 +0100 |
---|---|---|
committer | Benjamin Berg <bberg@redhat.com> | 2019-03-07 13:38:56 +0100 |
commit | 044418f5005758097f2babff1f35184947ce0c03 (patch) | |
tree | b1a9d4b8da6f2ed70d6a0b2deb99a4a9019e23fb | |
parent | b3fe46d43dcfa43fd33c20a9e4765b8e46b1a7f6 (diff) | |
download | geoclue-044418f5005758097f2babff1f35184947ce0c03.tar.gz |
Add new API to allow automatic server side deletion of client
If gclue_client_proxy_create_full is called with the corresponding flag
set, then the newly created GClueClientProxy will be set up so that
DeleteClient is automatically called on the server when the object is
destroyed.
See #102
-rw-r--r-- | docs/lib/libgeoclue-sections.txt | 6 | ||||
-rw-r--r-- | libgeoclue/gclue-helpers.c | 221 | ||||
-rw-r--r-- | libgeoclue/gclue-helpers.h | 14 | ||||
-rw-r--r-- | public-api/gclue-enums.h | 12 |
4 files changed, 237 insertions, 16 deletions
diff --git a/docs/lib/libgeoclue-sections.txt b/docs/lib/libgeoclue-sections.txt index 83add2c..8352198 100644 --- a/docs/lib/libgeoclue-sections.txt +++ b/docs/lib/libgeoclue-sections.txt @@ -58,6 +58,9 @@ gclue_client_complete_stop gclue_client_proxy_create gclue_client_proxy_create_finish gclue_client_proxy_create_sync +gclue_client_proxy_create_full +gclue_client_proxy_create_full_finish +gclue_client_proxy_create_full_sync gclue_client_proxy_new gclue_client_proxy_new_finish gclue_client_proxy_new_sync @@ -85,6 +88,9 @@ GClueClientProxyPrivate GClueAccuracyLevel GCLUE_TYPE_ACCURACY_LEVEL gclue_accuracy_level_get_type +GClueClientProxyCreateFlags +GCLUE_TYPE_CLIENT_PROXY_CREATE_FLAGS +gclue_client_proxy_create_flags_get_type <SUBSECTION Private> gclue_accuracy_level_build_string_from_mask gclue_accuracy_level_get_string diff --git a/libgeoclue/gclue-helpers.c b/libgeoclue/gclue-helpers.c index 15ccc5b..bbb3809 100644 --- a/libgeoclue/gclue-helpers.c +++ b/libgeoclue/gclue-helpers.c @@ -35,20 +35,29 @@ */ typedef struct { - char *desktop_id; - GClueAccuracyLevel accuracy_level; + char *desktop_id; + GClueAccuracyLevel accuracy_level; + GClueClientProxyCreateFlags flags; + GClueManager *manager; gulong notify_id; } ClientCreateData; +typedef struct { + GClueManager *manager; + char *client_path; +} ClientDestroyData; + static ClientCreateData * -client_create_data_new (const char *desktop_id, - GClueAccuracyLevel accuracy_level) +client_create_data_new (const char *desktop_id, + GClueAccuracyLevel accuracy_level, + GClueClientProxyCreateFlags flags) { ClientCreateData *data = g_slice_new0 (ClientCreateData); data->desktop_id = g_strdup (desktop_id); data->accuracy_level = accuracy_level; + data->flags = flags; return data; } @@ -56,10 +65,58 @@ client_create_data_new (const char *desktop_id, static void client_create_data_free (ClientCreateData *data) { + g_clear_object (&data->manager); g_free (data->desktop_id); g_slice_free (ClientCreateData, data); } +static ClientDestroyData * +client_destroy_data_new (GClueManager *manager, + const char *client_path) +{ + ClientDestroyData *data = g_slice_new0 (ClientDestroyData); + + if (manager) + data->manager = g_object_ref (manager); + data->client_path = g_strdup (client_path); + + return data; +} + +static void +on_delete_client_finished (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr(GError) error = NULL; + ClientDestroyData *data = user_data; + + if (!gclue_manager_call_delete_client_finish ( + GCLUE_MANAGER (source_object), + res, + &error)) { + g_warning ("GClue: Failed to automatically delete client: %s", + error->message); + } + + g_clear_object (&data->manager); + g_clear_pointer (&data->client_path, g_free); + g_slice_free (ClientDestroyData, data); +} + +static void +on_client_destroyed (gpointer data, + GObject *where_the_object_was) +{ + ClientDestroyData *destroy_data = data; + + gclue_manager_call_delete_client (destroy_data->manager, + destroy_data->client_path, + NULL, + on_delete_client_finished, + destroy_data); +} + static void on_client_proxy_ready (GObject *source_object, GAsyncResult *res, @@ -67,6 +124,7 @@ on_client_proxy_ready (GObject *source_object, { GTask *task = G_TASK (user_data); ClientCreateData *data; + ClientDestroyData *destroy; GClueClient *client; GError *error = NULL; @@ -82,6 +140,16 @@ on_client_proxy_ready (GObject *source_object, gclue_client_set_desktop_id (client, data->desktop_id); gclue_client_set_requested_accuracy_level (client, data->accuracy_level); + if (data->flags & GCLUE_CLIENT_PROXY_CREATE_AUTO_DELETE) { + destroy = client_destroy_data_new ( + data->manager, + g_dbus_proxy_get_object_path ( + G_DBUS_PROXY (client))); + g_object_weak_ref (G_OBJECT (client), + on_client_destroyed, + destroy); + } + g_task_return_pointer (task, client, g_object_unref); g_object_unref (task); } @@ -124,6 +192,7 @@ on_manager_proxy_ready (GObject *source_object, gpointer user_data) { GTask *task = G_TASK (user_data); + ClientCreateData *data; GClueManager *manager; GError *error = NULL; @@ -135,12 +204,30 @@ on_manager_proxy_ready (GObject *source_object, return; } + data = g_task_get_task_data (task); + data->manager = g_object_ref (manager); gclue_manager_call_get_client (manager, g_task_get_cancellable (task), on_get_client_ready, task); } +static void +on_client_proxy_full_finished (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr(GTask) task = user_data; + GClueClient *client; + GError *error = NULL; + + client = gclue_client_proxy_create_finish (res, &error); + if (!client) + g_task_return_error (task, error); + else + g_task_return_pointer (task, client, g_object_unref); +} + /** * gclue_client_proxy_create: * @desktop_id: The desktop file id (the basename of the desktop file). @@ -150,7 +237,11 @@ on_manager_proxy_ready (GObject *source_object, * @user_data: User data to pass to @callback. * * A utility function to create a #GClueClientProxy without having to deal with - * a #GClueManager. + * a #GClueManager. See also gclue_client_proxy_create_full() which improves + * resource management. + * + * This is identitcal to calling gclue_client_proxy_create_full() without any + * flags set. * * See #gclue_client_proxy_create_sync() for the synchronous, blocking version * of this function. @@ -163,11 +254,102 @@ gclue_client_proxy_create (const char *desktop_id, gpointer user_data) { GTask *task; + + task = g_task_new (NULL, cancellable, callback, user_data); + + gclue_client_proxy_create_full (desktop_id, + accuracy_level, + GCLUE_CLIENT_PROXY_CREATE_NONE, + cancellable, + on_client_proxy_full_finished, + task); +} + +/** + * gclue_client_proxy_create_finish: + * @result: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to + * gclue_client_proxy_create(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with gclue_client_proxy_create(). + * + * Returns: (transfer full) (type GClueClientProxy): The constructed proxy + * object or %NULL if @error is set. + */ +GClueClient * +gclue_client_proxy_create_finish (GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (g_task_is_valid (result, NULL), NULL); + + return g_task_propagate_pointer (G_TASK (result), error); +} + +/** + * gclue_client_proxy_create_sync: + * @desktop_id: The desktop file id (the basename of the desktop file). + * @accuracy_level: The requested accuracy level as #GClueAccuracyLevel. + * @cancellable: (allow-none): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * The synchronous and blocking version of #gclue_client_proxy_create(). + * See also gclue_client_proxy_create_full_sync() which improves resource + * management. + * + * This function is identical to calling gclue_client_proxy_create_full_sync() + * without any flags set. + * + * Returns: (transfer full) (type GClueClientProxy): The constructed proxy + * object or %NULL if @error is set. + */ +GClueClient * +gclue_client_proxy_create_sync (const char *desktop_id, + GClueAccuracyLevel accuracy_level, + GCancellable *cancellable, + GError **error) +{ + return gclue_client_proxy_create_full_sync ( + desktop_id, + accuracy_level, + GCLUE_CLIENT_PROXY_CREATE_NONE, + cancellable, + error); +} + +/** + * gclue_client_proxy_create_full: + * @desktop_id: The desktop file id (the basename of the desktop file). + * @accuracy_level: The requested accuracy level as #GClueAccuracyLevel. + * @flags: #GClueClientProxyCreateFlags to modify the creation. + * @cancellable: (allow-none): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the results are ready. + * @user_data: User data to pass to @callback. + * + * A utility function to create a #GClueClientProxy without having to deal with + * a #GClueManager. + * + * By setting the #GCLUE_CLIENT_PROXY_CREATE_AUTO_DELETE flag you can ensure + * that the client will be deleted again from the geoclue service when + * it is destroyed. This flag should be used unless you are doing explicit + * resource management. + * + * See #gclue_client_proxy_create_full_sync() for the synchronous, blocking + * version of this function. + */ +void +gclue_client_proxy_create_full (const char *desktop_id, + GClueAccuracyLevel accuracy_level, + GClueClientProxyCreateFlags flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; ClientCreateData *data; task = g_task_new (NULL, cancellable, callback, user_data); - data = client_create_data_new (desktop_id, accuracy_level); + data = client_create_data_new (desktop_id, accuracy_level, flags); g_task_set_task_data (task, data, (GDestroyNotify) client_create_data_free); @@ -182,19 +364,19 @@ gclue_client_proxy_create (const char *desktop_id, } /** - * gclue_client_proxy_create_finish: + * gclue_client_proxy_create_full_finish: * @result: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to * gclue_client_proxy_create(). * @error: Return location for error or %NULL. * - * Finishes an operation started with gclue_client_proxy_create(). + * Finishes an operation started with gclue_client_proxy_create_full(). * * Returns: (transfer full) (type GClueClientProxy): The constructed proxy * object or %NULL if @error is set. */ GClueClient * -gclue_client_proxy_create_finish (GAsyncResult *result, - GError **error) +gclue_client_proxy_create_full_finish (GAsyncResult *result, + GError **error) { g_return_val_if_fail (g_task_is_valid (result, NULL), NULL); @@ -221,22 +403,29 @@ on_client_proxy_created (GObject *source_object, } /** - * gclue_client_proxy_create_sync: + * gclue_client_proxy_create_full_sync: * @desktop_id: The desktop file id (the basename of the desktop file). * @accuracy_level: The requested accuracy level as #GClueAccuracyLevel. + * @flags: #GClueClientProxyCreateFlags to modify the creation. * @cancellable: (allow-none): A #GCancellable or %NULL. * @error: Return location for error or %NULL. * - * The synchronous and blocking version of #gclue_client_proxy_create(). + * The synchronous and blocking version of #gclue_client_proxy_create_full(). + * + * By setting the #GCLUE_CLIENT_PROXY_CREATE_AUTO_DELETE flag you can ensure + * that the client will be deleted again from the geoclue service when + * it is destroyed. This flag should be used unless you are doing explicit + * resource management. * * Returns: (transfer full) (type GClueClientProxy): The constructed proxy * object or %NULL if @error is set. */ GClueClient * -gclue_client_proxy_create_sync (const char *desktop_id, - GClueAccuracyLevel accuracy_level, - GCancellable *cancellable, - GError **error) +gclue_client_proxy_create_full_sync (const char *desktop_id, + GClueAccuracyLevel accuracy_level, + GClueClientProxyCreateFlags flags, + GCancellable *cancellable, + GError **error) { GClueClient *client; ClientCreateSyncData *data = g_slice_new0 (ClientCreateSyncData); diff --git a/libgeoclue/gclue-helpers.h b/libgeoclue/gclue-helpers.h index 37997b0..f43b447 100644 --- a/libgeoclue/gclue-helpers.h +++ b/libgeoclue/gclue-helpers.h @@ -42,6 +42,20 @@ GClueClient * gclue_client_proxy_create_sync (const char *desktop_id GCancellable *cancellable, GError **error); +void gclue_client_proxy_create_full (const char *desktop_id, + GClueAccuracyLevel accuracy_level, + GClueClientProxyCreateFlags flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GClueClient * gclue_client_proxy_create_full_finish (GAsyncResult *result, + GError **error); +GClueClient * gclue_client_proxy_create_full_sync (const char *desktop_id, + GClueAccuracyLevel accuracy_level, + GClueClientProxyCreateFlags flags, + GCancellable *cancellable, + GError **error); + G_END_DECLS #endif /* #ifndef __GCLUE_HELPERS_H__*/ diff --git a/public-api/gclue-enums.h b/public-api/gclue-enums.h index d1a9881..33e499b 100644 --- a/public-api/gclue-enums.h +++ b/public-api/gclue-enums.h @@ -49,6 +49,18 @@ typedef enum {/*< underscore_name=gclue_accuracy_level>*/ const char *gclue_accuracy_level_get_string (GClueAccuracyLevel val); +/** + * GClueClientProxyCreateFlags: + * @GCLUE_CLIENT_PROXY_CREATE_NONE: Empty set of create flags + * @GCLUE_CLIENT_PROXY_CREATE_AUTO_DELETE: + * Automatically delete the client from the server when the #GClueClient is + * destroyed. This flag should usually be set. + **/ +typedef enum {/*< underscore_name=gclue_client_proxy_create_flags>*/ + GCLUE_CLIENT_PROXY_CREATE_NONE = 0, + GCLUE_CLIENT_PROXY_CREATE_AUTO_DELETE = 1 << 0, +} GClueClientProxyCreateFlags; + G_END_DECLS #endif /* GCLUE_ENUMS_H */ |