diff options
author | Zeeshan Ali <zeenix@collabora.co.uk> | 2018-12-31 16:47:55 +0100 |
---|---|---|
committer | Zeeshan Ali <zeenix@collabora.co.uk> | 2018-12-31 16:54:38 +0100 |
commit | edfc62a96cc86dbd0b9cb9414e13072921ebe9ac (patch) | |
tree | 1cce06920aa2fc1a305e745842ecd1ba6b83db6e | |
parent | 386a6a576f43b311b1de4498565846d8f057a2d4 (diff) | |
download | geoclue-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.c | 82 | ||||
-rw-r--r-- | src/org.freedesktop.GeoClue2.Manager.xml | 24 |
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 |