Commit edfc62a9 authored by Zeeshan Ali's avatar Zeeshan Ali

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.
parent 386a6a57
Pipeline #13608 passed with stage
in 3 minutes and 30 seconds
......@@ -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;
}
......
......@@ -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,15 +37,30 @@
<!--
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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment