[tracker/wip/carlosg/portal: 46/61] portal: Add XDG portal implementation



commit b2d6d5d90c473601e1ff853faa205ff98747bf67
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Jan 22 18:39:26 2020 +0100

    portal: Add XDG portal implementation

 src/meson.build                   |   3 +
 src/portal/meson.build            |  14 ++
 src/portal/tracker-main.c         | 153 +++++++++++++++++++
 src/portal/tracker-portal-utils.c | 176 ++++++++++++++++++++++
 src/portal/tracker-portal-utils.h |  31 ++++
 src/portal/tracker-portal.c       | 298 ++++++++++++++++++++++++++++++++++++++
 src/portal/tracker-portal.h       |  33 +++++
 7 files changed, 708 insertions(+)
---
diff --git a/src/meson.build b/src/meson.build
index 2f9817ece..78f21b9b9 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -16,3 +16,6 @@ subdir('libtracker-sparql')
 
 # Public commandline control tool
 subdir('tracker')
+
+# XDG Portal
+subdir('portal')
diff --git a/src/portal/meson.build b/src/portal/meson.build
new file mode 100644
index 000000000..5c9849844
--- /dev/null
+++ b/src/portal/meson.build
@@ -0,0 +1,14 @@
+sources = [
+    'tracker-main.c',
+    'tracker-portal.c',
+    'tracker-portal-utils.c',
+]
+
+executable('xdg-tracker-portal', sources,
+    c_args: tracker_c_args,
+    install: true,
+    install_rpath: tracker_install_rpath,
+    install_dir: get_option('libexecdir'),
+    dependencies: [tracker_sparql_dep],
+    include_directories: [commoninc, configinc, srcinc],
+)
diff --git a/src/portal/tracker-main.c b/src/portal/tracker-main.c
new file mode 100644
index 000000000..e8977fc4b
--- /dev/null
+++ b/src/portal/tracker-main.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2020, Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <locale.h>
+
+#include <glib.h>
+#include <glib-unix.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#include <libtracker-common/tracker-common.h>
+
+#include "tracker-portal.h"
+
+static gboolean version = FALSE;
+
+const char usage_string[] =
+       "xdg-tracker-portal [--version | -v]";
+
+const char about[] =
+       "Tracker XDG portal " PACKAGE_VERSION "\n"
+       "\n"
+       "This program is free software and comes without any warranty.\n"
+       "It is licensed under version 2 or later of the General Public "
+       "License which can be viewed at:\n"
+       "\n"
+       "  http://www.gnu.org/licenses/gpl.txt";
+       "\n";
+
+static GOptionEntry entries[] = {
+       { "version", 'v', 0, G_OPTION_ARG_NONE, &version,
+         N_("Version"),
+         NULL
+       },
+};
+
+static int
+print_version (void)
+{
+       puts (about);
+       return 0;
+}
+
+static gboolean
+sigterm_cb (gpointer user_data)
+{
+       g_main_loop_quit (user_data);
+
+       return G_SOURCE_REMOVE;
+}
+
+static void
+name_acquired_callback (GDBusConnection *connection,
+                        const gchar     *name,
+                        gpointer         user_data)
+{
+       g_debug ("Name '%s' acquired", name);
+       g_main_loop_quit (user_data);
+}
+
+static void
+name_lost_callback (GDBusConnection *connection,
+                    const gchar     *name,
+                    gpointer         user_data)
+{
+       g_critical ("Name '%s' lost", name);
+       exit (EXIT_FAILURE);
+}
+
+int
+main (int argc, char *argv[])
+{
+       GMainLoop *main_loop;
+       g_autoptr(GError) error = NULL;
+       GDBusConnection *connection;
+       g_autoptr(GOptionContext) context = NULL;
+       TrackerPortal *portal;
+
+       setlocale (LC_ALL, "");
+
+       bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+       bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+       textdomain (GETTEXT_PACKAGE);
+
+       context = g_option_context_new (NULL);
+       g_option_context_add_main_entries (context, entries, NULL);
+
+       if (!g_option_context_parse (context, &argc, (char***) &argv, &error)) {
+               g_printerr ("%s, %s\n", _("Unrecognized options"), error->message);
+               g_error_free (error);
+               return EXIT_FAILURE;
+       }
+
+       if (version) {
+               print_version ();
+               return EXIT_SUCCESS;
+       }
+
+       connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+       if (!connection) {
+               g_printerr ("%s", error->message);
+               return EXIT_FAILURE;
+       }
+
+       main_loop = g_main_loop_new (NULL, FALSE);
+
+       g_bus_own_name_on_connection (connection,
+                                     "org.freedesktop.portal.Tracker",
+                                     G_BUS_NAME_OWNER_FLAGS_NONE,
+                                     name_acquired_callback,
+                                     name_lost_callback,
+                                     g_main_loop_ref (main_loop),
+                                     (GDestroyNotify) g_main_loop_unref);
+
+       g_main_loop_run (main_loop);
+
+       portal = tracker_portal_new (connection, NULL, &error);
+       if (!portal) {
+               g_printerr ("%s", error->message);
+               return EXIT_FAILURE;
+       }
+
+       g_unix_signal_add (SIGINT, sigterm_cb, main_loop);
+       g_unix_signal_add (SIGTERM, sigterm_cb, main_loop);
+       g_main_loop_run (main_loop);
+
+       g_main_loop_unref (main_loop);
+
+       g_clear_object (&portal);
+
+       return EXIT_FAILURE;
+}
diff --git a/src/portal/tracker-portal-utils.c b/src/portal/tracker-portal-utils.c
new file mode 100644
index 000000000..2582a720e
--- /dev/null
+++ b/src/portal/tracker-portal-utils.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright © 2014 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *       Alexander Larsson <alexl redhat com>
+ *
+ * Code borrowed from xdg-desktop-portal/src/xdp-utils.[ch]
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "tracker-portal-utils.h"
+
+#define DBUS_NAME_DBUS "org.freedesktop.DBus"
+#define DBUS_INTERFACE_DBUS DBUS_NAME_DBUS
+#define DBUS_PATH_DBUS "/org/freedesktop/DBus"
+
+static GKeyFile *
+parse_app_info_from_flatpak_info (int pid, GError **error)
+{
+       g_autofree char *root_path = NULL;
+       int root_fd = -1;
+       int info_fd = -1;
+       struct stat stat_buf;
+       g_autoptr(GError) local_error = NULL;
+       g_autoptr(GMappedFile) mapped = NULL;
+       g_autoptr(GKeyFile) metadata = NULL;
+       g_autofree char *id = NULL;
+
+       root_path = g_strdup_printf ("/proc/%u/root", pid);
+       root_fd = openat (AT_FDCWD, root_path, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY);
+       if (root_fd == -1) {
+               /* Not able to open the root dir shouldn't happen. Probably the app died and
+                * we're failing due to /proc/$pid not existing. In that case fail instead
+                * of treating this as privileged. */
+               g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                            "Unable to open %s", root_path);
+               return NULL;
+       }
+
+       metadata = g_key_file_new ();
+
+       info_fd = openat (root_fd, ".flatpak-info", O_RDONLY | O_CLOEXEC | O_NOCTTY);
+       close (root_fd);
+       if (info_fd == -1) {
+               if (errno == ENOENT) {
+                       /* No file => on the host, return NULL with no error */
+                       return NULL;
+               }
+
+               /* Some weird error => failure */
+               g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                            "Unable to open application info file");
+               return NULL;
+       }
+
+       if (fstat (info_fd, &stat_buf) != 0 || !S_ISREG (stat_buf.st_mode)) {
+               /* Some weird fd => failure */
+               close (info_fd);
+               g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                            "Unable to open application info file");
+               return NULL;
+       }
+
+       mapped = g_mapped_file_new_from_fd  (info_fd, FALSE, &local_error);
+       if (mapped == NULL) {
+               close (info_fd);
+               g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                            "Can't map .flatpak-info file: %s", local_error->message);
+               return NULL;
+       }
+
+       if (!g_key_file_load_from_data (metadata,
+                                       g_mapped_file_get_contents (mapped),
+                                       g_mapped_file_get_length (mapped),
+                                       G_KEY_FILE_NONE, &local_error)) {
+               close (info_fd);
+               g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                            "Can't load .flatpak-info file: %s", local_error->message);
+               return NULL;
+       }
+
+       close (info_fd);
+
+       return g_steal_pointer (&metadata);
+}
+
+static GKeyFile *
+tracker_connection_lookup_app_info_sync (GDBusConnection       *connection,
+                                         const char            *sender,
+                                         GCancellable          *cancellable,
+                                         GError               **error)
+{
+       g_autoptr(GDBusMessage) msg = NULL;
+       g_autoptr(GDBusMessage) reply = NULL;
+       GVariant *body;
+       g_autoptr(GVariantIter) iter = NULL;
+       g_autoptr(GKeyFile) app_info = NULL;
+       const char *key;
+       GVariant *value;
+       g_autoptr(GError) local_error = NULL;
+       guint32 pid = 0;
+
+       msg = g_dbus_message_new_method_call (DBUS_NAME_DBUS,
+                                             DBUS_PATH_DBUS,
+                                             DBUS_INTERFACE_DBUS,
+                                             "GetConnectionCredentials");
+       g_dbus_message_set_body (msg, g_variant_new ("(s)", sender));
+
+       reply = g_dbus_connection_send_message_with_reply_sync (connection, msg,
+                                                               G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+                                                               30000,
+                                                               NULL,
+                                                               cancellable,
+                                                               error);
+       if (reply == NULL)
+               return NULL;
+
+       if (g_dbus_message_get_message_type (reply) == G_DBUS_MESSAGE_TYPE_ERROR) {
+               g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Can't find peer app id");
+               return NULL;
+       }
+
+       body = g_dbus_message_get_body (reply);
+
+       g_variant_get (body, "(a{sv})", &iter);
+       while (g_variant_iter_loop (iter, "{&sv}", &key, &value)) {
+               if (strcmp (key, "ProcessID") == 0)
+                       pid = g_variant_get_uint32 (value);
+       }
+
+       if (pid == 0) {
+               g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Can't find app PID");
+               return NULL;
+       }
+
+       app_info = parse_app_info_from_flatpak_info (pid, &local_error);
+
+       if (app_info == NULL && local_error) {
+               g_propagate_error (error, g_steal_pointer (&local_error));
+               return NULL;
+       }
+
+       return g_steal_pointer (&app_info);
+}
+
+GKeyFile *
+tracker_invocation_lookup_app_info_sync (GDBusMethodInvocation *invocation,
+                                        GCancellable          *cancellable,
+                                        GError               **error)
+{
+       GDBusConnection *connection = g_dbus_method_invocation_get_connection (invocation);
+       const gchar *sender = g_dbus_method_invocation_get_sender (invocation);
+
+       return tracker_connection_lookup_app_info_sync (connection, sender, cancellable, error);
+}
diff --git a/src/portal/tracker-portal-utils.h b/src/portal/tracker-portal-utils.h
new file mode 100644
index 000000000..dcae4a0e3
--- /dev/null
+++ b/src/portal/tracker-portal-utils.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright © 2014 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *       Alexander Larsson <alexl redhat com>
+ *
+ * Code borrowed from xdg-desktop-portal/src/xdp-utils.[ch]
+ */
+#ifndef __TRACKER_PORTAL_UTILS_H__
+#define __TRACKER_PORTAL_UTILS_H__
+
+#include <gio/gio.h>
+
+GKeyFile * tracker_invocation_lookup_app_info_sync (GDBusMethodInvocation *invocation,
+                                                    GCancellable          *cancellable,
+                                                    GError               **error);
+
+#endif /* __TRACKER_PORTAL_UTILS_H__ */
diff --git a/src/portal/tracker-portal.c b/src/portal/tracker-portal.c
new file mode 100644
index 000000000..87c2832e3
--- /dev/null
+++ b/src/portal/tracker-portal.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2020, Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#include "config.h"
+
+#include <libtracker-sparql/tracker-sparql.h>
+#include <libtracker-common/tracker-common.h>
+
+#include "tracker-portal.h"
+
+typedef struct _TrackerPortal TrackerPortal;
+typedef struct _TrackerSession TrackerSession;
+
+struct _TrackerSession
+{
+       TrackerSparqlConnection *connection;
+       GDBusConnection *dbus_connection;
+       TrackerEndpoint *endpoint;
+       gchar *object_path;
+};
+
+struct _TrackerPortal
+{
+       GObject parent_instance;
+       GDBusConnection *dbus_connection;
+       guint register_id;
+       GDBusNodeInfo *node_info;
+       GCancellable *cancellable;
+       GArray *sessions;
+       guint64 session_ids;
+};
+
+enum
+{
+       PROP_DBUS_CONNECTION = 1,
+       N_PROPS
+};
+
+static GParamSpec *props[N_PROPS] = { 0 };
+
+static void tracker_portal_initable_iface_init (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (TrackerPortal, tracker_portal, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, tracker_portal_initable_iface_init))
+
+static const gchar portal_xml[] =
+       "<node>"
+       "  <interface name='org.freedesktop.portal.Tracker'>"
+       "    <method name='CreateSession'>"
+       "      <arg type='s' name='service' direction='in' />"
+       "      <arg type='o' name='result' direction='out' />"
+       "    </method>"
+       "  </interface>"
+       "</node>";
+
+static void
+tracker_portal_set_property (GObject       *object,
+                             guint          prop_id,
+                             const GValue  *value,
+                             GParamSpec    *pspec)
+{
+       TrackerPortal *portal = TRACKER_PORTAL (object);
+
+       switch (prop_id) {
+       case PROP_DBUS_CONNECTION:
+               portal->dbus_connection = g_value_dup_object (value);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+tracker_portal_get_property (GObject    *object,
+                             guint       prop_id,
+                             GValue     *value,
+                             GParamSpec *pspec)
+{
+       TrackerPortal *portal = TRACKER_PORTAL (object);
+
+       switch (prop_id) {
+       case PROP_DBUS_CONNECTION:
+               g_value_set_object (value, portal->dbus_connection);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+tracker_portal_finalize (GObject *object)
+{
+       TrackerPortal *portal = TRACKER_PORTAL (object);
+
+       g_debug ("Finalizing Tracker portal");
+
+       g_clear_pointer (&portal->sessions, g_array_unref);
+
+       if (portal->register_id != 0) {
+               g_dbus_connection_unregister_object (portal->dbus_connection,
+                                                    portal->register_id);
+               portal->register_id = 0;
+       }
+
+       g_clear_object (&portal->dbus_connection);
+       g_clear_pointer (&portal->node_info,
+                        g_dbus_node_info_unref);
+
+       G_OBJECT_CLASS (tracker_portal_parent_class)->finalize (object);
+       g_debug ("Tracker portal finalized");
+}
+
+static void
+tracker_portal_class_init (TrackerPortalClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->set_property = tracker_portal_set_property;
+       object_class->get_property = tracker_portal_get_property;
+       object_class->finalize = tracker_portal_finalize;
+
+       props[PROP_DBUS_CONNECTION] =
+               g_param_spec_object ("dbus-connection",
+                                    "DBus connection",
+                                    "DBus connection",
+                                    G_TYPE_DBUS_CONNECTION,
+                                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+       g_object_class_install_properties (object_class, N_PROPS, props);
+}
+
+static void
+clear_session (gpointer user_data)
+{
+       TrackerSession *session = user_data;
+
+       g_debug ("Closing session '%s'", session->object_path);
+       g_clear_object (&session->endpoint);
+       g_clear_object (&session->connection);
+       g_clear_object (&session->dbus_connection);
+       g_clear_pointer (&session->object_path, g_free);
+}
+
+static void
+tracker_portal_init (TrackerPortal *portal)
+{
+       portal->sessions = g_array_new (FALSE, TRUE, sizeof (TrackerSession));
+       g_array_set_clear_func (portal->sessions, clear_session);
+}
+
+static void
+portal_iface_method_call (GDBusConnection       *connection,
+                          const gchar           *sender,
+                          const gchar           *object_path,
+                          const gchar           *interface_name,
+                          const gchar           *method_name,
+                          GVariant              *parameters,
+                          GDBusMethodInvocation *invocation,
+                          gpointer               user_data)
+{
+       TrackerPortal *portal = user_data;
+
+       if (g_strcmp0 (method_name, "CreateSession") == 0) {
+               g_autofree gchar *uri = NULL;
+               g_autofree gchar *service = NULL;
+               g_autofree gchar *object_path = NULL;
+               g_autofree gchar *session_object_path = NULL;
+               g_autoptr(GDBusConnection) dbus_connection = NULL;
+               g_autoptr(TrackerSparqlConnection) connection = NULL;
+               g_autoptr(TrackerEndpoint) endpoint = NULL;
+               g_autoptr(GError) error = NULL;
+               GBusType bus_type;
+               TrackerSession session;
+
+               g_variant_get (parameters, "(s)", &uri);
+               g_debug ("Creating session for service URI '%s'", uri);
+
+               if (!tracker_util_parse_dbus_uri (uri,
+                                                 &bus_type,
+                                                 &service,
+                                                 &object_path)) {
+                       g_debug ("Could not parse URI '%s'", uri);
+                       g_dbus_method_invocation_return_error (invocation,
+                                                              G_DBUS_ERROR,
+                                                              G_DBUS_ERROR_INVALID_ARGS,
+                                                              "Service cannot be parsed");
+                       return;
+               }
+
+               dbus_connection = g_bus_get_sync (bus_type, NULL, &error);
+
+               if (!dbus_connection) {
+                       g_debug ("Could not get bus connection");
+                       g_dbus_method_invocation_return_gerror (invocation, error);
+                       return;
+               }
+
+               connection = tracker_sparql_connection_bus_new (service, object_path, dbus_connection, 
&error);
+               if (!connection) {
+                       g_debug ("Could not stablish connection to service");
+                       g_dbus_method_invocation_return_gerror (invocation, error);
+                       return;
+               }
+
+               session_object_path = g_strdup_printf ("/org/freedesktop/portal/Tracker/Session_%" 
G_GUINT64_FORMAT,
+                                                      portal->session_ids++);
+
+               endpoint = TRACKER_ENDPOINT (tracker_endpoint_dbus_new (connection,
+                                                                       dbus_connection,
+                                                                       session_object_path,
+                                                                       NULL,
+                                                                       &error));
+               if (!endpoint) {
+                       g_debug ("Could not create endpoint");
+                       g_dbus_method_invocation_return_gerror (invocation, error);
+                       return;
+               }
+
+               session = (TrackerSession) {
+                       .dbus_connection = g_steal_pointer (&dbus_connection),
+                       .connection = g_steal_pointer (&connection),
+                       .endpoint = g_steal_pointer (&endpoint),
+                       .object_path = g_steal_pointer (&session_object_path),
+               };
+               g_array_append_val (portal->sessions, session);
+
+               g_debug ("Created session object '%s'", session.object_path);
+               g_dbus_method_invocation_return_value (invocation,
+                                                      g_variant_new ("(o)", session.object_path));
+       } else {
+               g_dbus_method_invocation_return_error (invocation,
+                                                      G_DBUS_ERROR,
+                                                      G_DBUS_ERROR_UNKNOWN_METHOD,
+                                                      "Unknown method '%s'", method_name);
+       }
+}
+
+static gboolean
+tracker_portal_initable_init (GInitable     *initable,
+                              GCancellable  *cancellable,
+                              GError       **error)
+{
+       TrackerPortal *portal = TRACKER_PORTAL (initable);
+
+       portal->node_info = g_dbus_node_info_new_for_xml (portal_xml, error);
+       if (!portal->node_info)
+               return FALSE;
+
+       portal->register_id =
+               g_dbus_connection_register_object (portal->dbus_connection,
+                                                  "/org/freedesktop/portal/Tracker",
+                                                  portal->node_info->interfaces[0],
+                                                  &(GDBusInterfaceVTable) {
+                                                          portal_iface_method_call,
+                                                          NULL,
+                                                          NULL
+                                                  },
+                                                  portal,
+                                                  NULL,
+                                                  error);
+       return TRUE;
+}
+
+static void
+tracker_portal_initable_iface_init (GInitableIface *iface)
+{
+       iface->init = tracker_portal_initable_init;
+}
+
+TrackerPortal *
+tracker_portal_new (GDBusConnection  *connection,
+                    GCancellable     *cancellable,
+                    GError          **error)
+{
+       return g_initable_new (TRACKER_TYPE_PORTAL, cancellable, error,
+                              "dbus-connection", connection,
+                              NULL);
+}
diff --git a/src/portal/tracker-portal.h b/src/portal/tracker-portal.h
new file mode 100644
index 000000000..dcf0b4e71
--- /dev/null
+++ b/src/portal/tracker-portal.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020, Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+#ifndef __TRACKER_PORTAL_H__
+#define __TRACKER_PORTAL_H__
+
+#include <gio/gio.h>
+
+#define TRACKER_TYPE_PORTAL tracker_portal_get_type ()
+G_DECLARE_FINAL_TYPE (TrackerPortal, tracker_portal, TRACKER, PORTAL, GObject)
+
+TrackerPortal * tracker_portal_new (GDBusConnection  *connection,
+                                    GCancellable     *cancellable,
+                                    GError          **error);
+
+#endif /* __TRACKER_PORTAL_H__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]