summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Berg <bberg@redhat.com>2019-01-31 15:30:45 +0100
committerBenjamin Berg <bberg@redhat.com>2019-03-07 13:38:56 +0100
commit044418f5005758097f2babff1f35184947ce0c03 (patch)
treeb1a9d4b8da6f2ed70d6a0b2deb99a4a9019e23fb
parentb3fe46d43dcfa43fd33c20a9e4765b8e46b1a7f6 (diff)
downloadgeoclue-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.txt6
-rw-r--r--libgeoclue/gclue-helpers.c221
-rw-r--r--libgeoclue/gclue-helpers.h14
-rw-r--r--public-api/gclue-enums.h12
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 */