summaryrefslogtreecommitdiff
path: root/src/gclue-client-info.c
diff options
context:
space:
mode:
authorZeeshan Ali (Khattak) <zeeshanak@gnome.org>2016-01-29 17:31:48 +0100
committerZeeshan Ali (Khattak) <zeeshanak@gnome.org>2016-01-29 17:46:43 +0100
commit664ce7ba6ed3cadc7914097cc69cec27ea6bffc5 (patch)
tree2c29764c303a734e66f0a21c26c61ef5d5a383c7 /src/gclue-client-info.c
parentdab11e2e13a96857e4b62a89f6e8f14324d6e88c (diff)
downloadgeoclue-664ce7ba6ed3cadc7914097cc69cec27ea6bffc5.tar.gz
client-info: Reliable desktop ID for xdg-app
xdg-app shows the desktop ID of the apps in name column of /proc/PID/cgroup file and it can't be faked so let's make use of that when we are dealing with xdg-app apps.
Diffstat (limited to 'src/gclue-client-info.c')
-rw-r--r--src/gclue-client-info.c101
1 files changed, 97 insertions, 4 deletions
diff --git a/src/gclue-client-info.c b/src/gclue-client-info.c
index 3e886f6..f128736 100644
--- a/src/gclue-client-info.c
+++ b/src/gclue-client-info.c
@@ -43,6 +43,7 @@ struct _GClueClientInfoPrivate
guint watch_id;
guint32 user_id;
+ char *xdg_id;
};
enum
@@ -73,6 +74,7 @@ gclue_client_info_finalize (GObject *object)
}
g_clear_pointer (&priv->bus_name, g_free);
+ g_clear_pointer (&priv->xdg_id, g_free);
g_clear_object (&priv->connection);
/* Chain up to the parent class */
@@ -179,14 +181,60 @@ on_name_vanished (GDBusConnection *connection,
0);
}
+/* Based on got_credentials_cb() from xdg-app source code */
+static char *
+get_xdg_id (guint32 pid)
+{
+ char *xdg_id = NULL;
+ g_autofree char *path = NULL;
+ g_autofree char *content = NULL;
+ gchar **lines;
+ int i;
+
+ path = g_strdup_printf ("/proc/%u/cgroup", pid);
+
+ if (!g_file_get_contents (path, &content, NULL, NULL))
+ return NULL;
+ lines = g_strsplit (content, "\n", -1);
+
+ for (i = 0; lines[i] != NULL; i++) {
+ const char *unit = lines[i] + strlen ("1:name=systemd:");
+ g_autofree char *scope = NULL;
+ const char *name;
+ char *dash;
+
+ if (!g_str_has_prefix (lines[i], "1:name=systemd:"))
+ continue;
+
+ scope = g_path_get_basename (unit);
+ if (!g_str_has_prefix (scope, "xdg-app-") ||
+ !g_str_has_suffix (scope, ".scope"))
+ break;
+
+ name = scope + strlen("xdg-app-");
+ dash = strchr (name, '-');
+
+ if (dash == NULL)
+ break;
+
+ *dash = 0;
+ xdg_id = g_strdup (name);
+ }
+
+ g_strfreev (lines);
+
+ return xdg_id;
+}
+
static void
-on_get_user_id_ready (GObject *source_object,
- GAsyncResult *res,
- gpointer user_data)
+on_get_pid_ready (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
{
GTask *task = G_TASK (user_data);
gpointer *info = g_task_get_source_object (task);
GClueClientInfoPrivate *priv = GCLUE_CLIENT_INFO (info)->priv;
+ guint32 pid;
GError *error = NULL;
GVariant *results = NULL;
@@ -201,9 +249,11 @@ on_get_user_id_ready (GObject *source_object,
}
g_assert (g_variant_n_children (results) > 0);
- g_variant_get_child (results, 0, "u", &priv->user_id);
+ g_variant_get_child (results, 0, "u", &pid);
g_variant_unref (results);
+ priv->xdg_id = get_xdg_id (pid);
+
priv->watch_id = g_bus_watch_name_on_connection (priv->connection,
priv->bus_name,
G_BUS_NAME_WATCHER_FLAGS_NONE,
@@ -218,6 +268,41 @@ on_get_user_id_ready (GObject *source_object,
}
static void
+on_get_user_id_ready (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GTask *task = G_TASK (user_data);
+ gpointer *info = g_task_get_source_object (task);
+ GClueClientInfoPrivate *priv = GCLUE_CLIENT_INFO (info)->priv;
+ GError *error = NULL;
+ GVariant *results = NULL;
+
+ results = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
+ res,
+ &error);
+ if (results == NULL) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+
+ return;
+ }
+
+ g_assert (g_variant_n_children (results) > 0);
+ g_variant_get_child (results, 0, "u", &priv->user_id);
+ g_variant_unref (results);
+
+ g_dbus_proxy_call (priv->dbus_proxy,
+ "GetConnectionUnixProcessID",
+ g_variant_new ("(s)", priv->bus_name),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ g_task_get_cancellable (task),
+ on_get_pid_ready,
+ task);
+}
+
+static void
on_dbus_proxy_ready (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
@@ -348,3 +433,11 @@ gclue_client_info_check_bus_name (GClueClientInfo *info,
return (strcmp (bus_name, info->priv->bus_name) == 0);
}
+
+const char *
+gclue_client_info_get_xdg_id (GClueClientInfo *info)
+{
+ g_return_val_if_fail (GCLUE_IS_CLIENT_INFO(info), FALSE);
+
+ return info->priv->xdg_id;
+}