summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZeeshan Ali <zeenix@collabora.co.uk>2018-12-31 16:47:55 +0100
committerZeeshan Ali <zeenix@collabora.co.uk>2018-12-31 16:54:38 +0100
commitedfc62a96cc86dbd0b9cb9414e13072921ebe9ac (patch)
tree1cce06920aa2fc1a305e745842ecd1ba6b83db6e
parent386a6a576f43b311b1de4498565846d8f057a2d4 (diff)
downloadgeoclue-edfc62a96cc86dbd0b9cb9414e13072921ebe9ac.tar.gz
service,manager: New API for mult-client apps
We modified `Manager.GetClient` method in 3e1d9bf4 (service: Allow multiple clients on the same connection) and while that made things possible for the Flatpak location portal, it meant us creating redundant clients for existing system apps (e.g gnome-settings-daemon) and we don't want that. This patch changes `GetClient` to the old behaviour of reusing existing clients and adds a new method `CreateClient` that always creates a new client object. Fixes #96. Also related: #79.
-rw-r--r--src/gclue-service-manager.c82
-rw-r--r--src/org.freedesktop.GeoClue2.Manager.xml24
2 files changed, 89 insertions, 17 deletions
diff --git a/src/gclue-service-manager.c b/src/gclue-service-manager.c
index 6dffdd5..c343685 100644
--- a/src/gclue-service-manager.c
+++ b/src/gclue-service-manager.c
@@ -100,6 +100,18 @@ sync_in_use_property (GClueServiceManager *manager)
gclue_dbus_manager_set_in_use (gdbus_manager, in_use);
}
+static int
+compare_client_bus_name (gconstpointer a,
+ gconstpointer b)
+{
+ GClueClientInfo *info;
+ const char *bus_name = (const char *) b;
+
+ info = gclue_service_client_get_client_info (GCLUE_SERVICE_CLIENT (a));
+
+ return g_strcmp0 (bus_name, gclue_client_info_get_bus_name (info));
+}
+
static void
on_peer_vanished (GClueClientInfo *info,
gpointer user_data)
@@ -114,13 +126,8 @@ on_peer_vanished (GClueClientInfo *info,
l = priv->clients;
while (l != NULL) {
GList *next = l->next;
- GClueClientInfo *i;
-
- i = gclue_service_client_get_client_info
- (GCLUE_SERVICE_CLIENT (l->data));
- if (g_strcmp0 (bus_name,
- gclue_client_info_get_bus_name (i)) == 0) {
+ if (compare_client_bus_name (l->data, bus_name) == 0) {
const char *id, *path;
id = gclue_dbus_client_get_desktop_id
@@ -149,6 +156,8 @@ typedef struct
GClueDBusManager *manager;
GDBusMethodInvocation *invocation;
GClueClientInfo *client_info;
+ gboolean reuse_client;
+
} OnClientInfoNewReadyData;
static gboolean
@@ -166,6 +175,25 @@ complete_get_client (OnClientInfoNewReadyData *data)
agent_proxy = g_hash_table_lookup (priv->agents,
GINT_TO_POINTER (user_id));
+ if (data->reuse_client) {
+ GList *node;
+ const char *peer;
+
+ peer = g_dbus_method_invocation_get_sender (data->invocation);
+ node = g_list_find_custom (priv->clients,
+ peer,
+ compare_client_bus_name);
+ if (node != NULL) {
+ GClueServiceClient *client;
+
+ client = GCLUE_SERVICE_CLIENT (node->data);
+ path = g_strdup
+ (gclue_service_client_get_path (client));
+
+ goto client_created;
+ }
+ }
+
path = g_strdup_printf ("/org/freedesktop/GeoClue2/Client/%u",
++priv->last_client_id);
@@ -189,9 +217,15 @@ complete_get_client (OnClientInfoNewReadyData *data)
G_CALLBACK (on_peer_vanished),
data->manager);
- gclue_dbus_manager_complete_get_client (data->manager,
- data->invocation,
- path);
+client_created:
+ if (data->reuse_client)
+ gclue_dbus_manager_complete_get_client (data->manager,
+ data->invocation,
+ path);
+ else
+ gclue_dbus_manager_complete_create_client (data->manager,
+ data->invocation,
+ path);
goto out;
error_out:
@@ -254,24 +288,44 @@ on_client_info_new_ready (GObject *source_object,
complete_get_client (data);
}
-static gboolean
-gclue_service_manager_handle_get_client (GClueDBusManager *manager,
- GDBusMethodInvocation *invocation)
+static void
+handle_get_client (GClueDBusManager *manager,
+ GDBusMethodInvocation *invocation,
+ gboolean reuse_client)
{
GClueServiceManager *self = GCLUE_SERVICE_MANAGER (manager);
GClueServiceManagerPrivate *priv = self->priv;
const char *peer;
OnClientInfoNewReadyData *data;
+ peer = g_dbus_method_invocation_get_sender (invocation);
+
data = g_slice_new (OnClientInfoNewReadyData);
data->manager = manager;
data->invocation = invocation;
- peer = g_dbus_method_invocation_get_sender (invocation);
+ data->reuse_client = reuse_client;
gclue_client_info_new_async (peer,
priv->connection,
NULL,
on_client_info_new_ready,
data);
+}
+
+static gboolean
+gclue_service_manager_handle_get_client (GClueDBusManager *manager,
+ GDBusMethodInvocation *invocation)
+{
+ handle_get_client (manager, invocation, TRUE);
+
+ return TRUE;
+}
+
+static gboolean
+gclue_service_manager_handle_create_client (GClueDBusManager *manager,
+ GDBusMethodInvocation *invocation)
+{
+ handle_get_client (manager, invocation, FALSE);
+
return TRUE;
}
@@ -571,6 +625,8 @@ static void
gclue_service_manager_manager_iface_init (GClueDBusManagerIface *iface)
{
iface->handle_get_client = gclue_service_manager_handle_get_client;
+ iface->handle_create_client =
+ gclue_service_manager_handle_create_client;
iface->handle_add_agent = gclue_service_manager_handle_add_agent;
}
diff --git a/src/org.freedesktop.GeoClue2.Manager.xml b/src/org.freedesktop.GeoClue2.Manager.xml
index cf9590f..e676bcf 100644
--- a/src/org.freedesktop.GeoClue2.Manager.xml
+++ b/src/org.freedesktop.GeoClue2.Manager.xml
@@ -15,8 +15,9 @@
This is the interface you use to talk to main GeoClue2 manager object at
path "/org/freedesktop/GeoClue2/Manager". The only thing you do with this
- interface is to call org.freedesktop.GeoClue2.Manager.GetClient() on it
- to get your application specific client object.
+ interface is to call org.freedesktop.GeoClue2.Manager.GetClient() or
+ org.freedesktop.GeoClue2.Manager.CreateClient() on it to get your
+ application specific client object(s).
-->
<interface name="org.freedesktop.GeoClue2.Manager">
<!--
@@ -36,16 +37,31 @@
<!--
GetClient:
- @client: The path for newly created client object
+ @client: The path for the client object
Retrieves a client object which can only be used by the calling
- application only.
+ application only. On the first call from a specific D-Bus peer, this
+ method will create the client object but subsequent calls will return
+ the path of the existing client.
-->
<method name="GetClient">
<arg name="client" type="o" direction="out"/>
</method>
<!--
+ CreateClient:
+ @client: The path for the newly created client object
+
+ Creates and retrieves a client object which can only be used by the
+ calling application only. Unlike
+ org.freedesktop.GeoClue2.Manager.GetClient(), thid method always
+ creates a new client.
+ -->
+ <method name="CreateClient">
+ <arg name="client" type="o" direction="out"/>
+ </method>
+
+ <!--
AddAgent:
@id: The Desktop ID (excluding .desktop) of the agent