[glib] Use OpenFile for local files



commit 4c8ab22b95de887af7e233095816c3ae9dd8c10e
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat May 20 16:21:14 2017 -0400

    Use OpenFile for local files
    
    The OpenURI portal has a separate method to handle local
    files now. Use it.
    
    At the same time, split out the openuri helpers into separate
    files, and generate code for the OpenURI portal.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=783193

 gio/Makefile.am                        |    4 +
 gio/gappinfo.c                         |  264 ++--------------------------
 gio/gopenuriportal.c                   |  302 ++++++++++++++++++++++++++++++++
 gio/gopenuriportal.h                   |   41 +++++
 gio/org.freedesktop.portal.OpenURI.xml |  105 +++++++++++
 5 files changed, 471 insertions(+), 245 deletions(-)
---
diff --git a/gio/Makefile.am b/gio/Makefile.am
index b0aad64..f07c94a 100644
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@ -281,6 +281,8 @@ unix_sources = \
        gportalnotificationbackend.c \
        gdocumentportal.c       \
        gdocumentportal.h       \
+       gopenuriportal.c        \
+       gopenuriportal.h        \
        gportalsupport.c        \
        gportalsupport.h        \
        $(portal_sources)       \
@@ -368,6 +370,7 @@ CLEANFILES += $(xdp_dbus_built_sources)
 
 portal_interfaces = \
        org.freedesktop.portal.Documents.xml \
+       org.freedesktop.portal.OpenURI.xml \
        org.freedesktop.portal.NetworkMonitor.xml \
        org.freedesktop.portal.ProxyResolver.xml \
        $(NULL)
@@ -384,6 +387,7 @@ $(xdp_dbus_built_sources) : $(portal_interfaces)
                --annotate "org.freedesktop.portal.Documents.Add()" "org.gtk.GDBus.C.UnixFD" "true" \
                --annotate "org.freedesktop.portal.Documents.AddNamed()" "org.gtk.GDBus.C.UnixFD" "true" \
                --annotate "org.freedesktop.portal.Documents.AddFull()" "org.gtk.GDBus.C.UnixFD" "true" \
+               --annotate "org.freedesktop.portal.OpenURI.OpenFile()" "org.gtk.GDBus.C.UnixFD" "true" \
                $^
 
 portal_sources = \
diff --git a/gio/gappinfo.c b/gio/gappinfo.c
index 471f975..36a000e 100644
--- a/gio/gappinfo.c
+++ b/gio/gappinfo.c
@@ -32,15 +32,12 @@
 #ifdef G_OS_UNIX
 #include "gdbusconnection.h"
 #include "gdbusmessage.h"
-#include "gdocumentportal.h"
 #include "gportalsupport.h"
-#endif
-
-#ifdef G_OS_UNIX
-#define FLATPAK_OPENURI_PORTAL_BUS_NAME "org.freedesktop.portal.Desktop"
-#define FLATPAK_OPENURI_PORTAL_PATH "/org/freedesktop/portal/desktop"
-#define FLATPAK_OPENURI_PORTAL_IFACE "org.freedesktop.portal.OpenURI"
-#define FLATPAK_OPENURI_PORTAL_METHOD "OpenURI"
+#include "gunixfdlist.h"
+#include "gopenuriportal.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #endif
 
 /**
@@ -687,240 +684,6 @@ g_app_info_should_show (GAppInfo *appinfo)
   return (* iface->should_show) (appinfo);
 }
 
-#ifdef G_OS_UNIX
-static void
-response_received (GDBusConnection *connection,
-                   const char      *sender_name,
-                   const char      *object_path,
-                   const char      *interface_name,
-                   const char      *signal_name,
-                   GVariant        *parameters,
-                   gpointer         user_data)
-{
-  GTask *task = user_data;
-  guint32 response;
-  guint signal_id;
-
-  signal_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (task), "signal-id"));
-  g_dbus_connection_signal_unsubscribe (connection, signal_id);
-
-  g_variant_get (parameters, "(u@a{sv})", &response, NULL);
-
-  if (response == 0)
-    g_task_return_boolean (task, TRUE);
-  else if (response == 1)
-    g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Launch cancelled");
-  else
-    g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Launch failed");
-
-  g_object_unref (task);
-}
-
-static void
-open_uri_done (GObject      *source,
-               GAsyncResult *result,
-               gpointer      user_data)
-{
-  GDBusConnection *connection = G_DBUS_CONNECTION (source);
-  GTask *task = user_data;
-  GVariant *res;
-  GError *error = NULL;
-  const char *path;
-  guint signal_id;
-
-  res = g_dbus_connection_call_finish (connection, result, &error);
-
-  if (res == NULL)
-    {
-      g_task_return_error (task, error);
-      g_object_unref (task);
-      return;
-    }
-
-  g_variant_get (res, "(&o)", &path);
-
-  signal_id =
-      g_dbus_connection_signal_subscribe (connection,
-                                          "org.freedesktop.portal.Desktop",
-                                          "org.freedesktop.portal.Request",
-                                          "Response",
-                                          path,
-                                          NULL,
-                                          G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
-                                          response_received,
-                                          task, NULL);
-
-  g_object_set_data (G_OBJECT (task), "signal-id", GINT_TO_POINTER (signal_id));
-
-  g_variant_unref (res);
-}
-
-static char *
-real_uri_for_portal (const char          *uri,
-                     GAppLaunchContext   *context,
-                     GCancellable        *cancellable,
-                     GAsyncReadyCallback  callback,
-                     gpointer             user_data,
-                     GError             **error)
-{
-  GFile *file = NULL;
-  char *real_uri = NULL;
-
-  file = g_file_new_for_uri (uri);
-  if (g_file_is_native (file))
-    {
-      real_uri = g_document_portal_add_document (file, error);
-      g_object_unref (file);
-
-      if (real_uri == NULL)
-        {
-          g_task_report_error (context, callback, user_data, NULL, *error);
-          return NULL;
-        }
-    }
-  else
-    {
-      g_object_unref (file);
-      real_uri = g_strdup (uri);
-    }
-
-  return real_uri;
-}
-
-static void
-launch_default_with_portal_async (const char          *uri,
-                                  GAppLaunchContext   *context,
-                                  GCancellable        *cancellable,
-                                  GAsyncReadyCallback  callback,
-                                  gpointer             user_data)
-{
-  GDBusConnection *session_bus;
-  GVariantBuilder opt_builder;
-  const char *parent_window = NULL;
-  char *real_uri;
-  GTask *task;
-  GAsyncReadyCallback dbus_callback;
-  GError *error = NULL;
-
-  session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
-  if (session_bus == NULL)
-    {
-      g_task_report_error (context, callback, user_data, NULL, error);
-      return;
-    }
-
-  if (context && context->priv->envp)
-    parent_window = g_environ_getenv (context->priv->envp, "PARENT_WINDOW_ID");
-
-  real_uri = real_uri_for_portal (uri, context, cancellable, callback, user_data, &error);
-  if (real_uri == NULL)
-    {
-      g_object_unref (session_bus);
-      return;
-    }
-
-  g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
-
-  if (callback)
-    {
-      task = g_task_new (context, cancellable, callback, user_data);
-      dbus_callback = open_uri_done;
-    }
-  else
-    {
-      task = NULL;
-      dbus_callback = NULL;
-    }
-
-  g_dbus_connection_call (session_bus,
-                          FLATPAK_OPENURI_PORTAL_BUS_NAME,
-                          FLATPAK_OPENURI_PORTAL_PATH,
-                          FLATPAK_OPENURI_PORTAL_IFACE,
-                          FLATPAK_OPENURI_PORTAL_METHOD,
-                          g_variant_new ("(ss@a{sv})",
-                                         parent_window ? parent_window : "",
-                                         real_uri,
-                                         g_variant_builder_end (&opt_builder)),
-                          NULL,
-                          G_DBUS_CALL_FLAGS_NONE,
-                          G_MAXINT,
-                          cancellable,
-                          dbus_callback,
-                          task);
-
-  g_dbus_connection_flush (session_bus, cancellable, NULL, NULL);
-  g_object_unref (session_bus);
-  g_free (real_uri);
-}
-
-static void
-launch_default_with_portal_sync (const char          *uri,
-                                 GAppLaunchContext   *context)
-{
-  GDBusConnection *session_bus;
-  GVariantBuilder opt_builder;
-  GVariant *res = NULL;
-  const char *parent_window = NULL;
-  char *real_uri;
-  GError *error = NULL;
-
-  session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
-  if (session_bus == NULL)
-    {
-      g_task_report_error (context, NULL, NULL, NULL, error);
-      return;
-    }
-
-  if (context && context->priv->envp)
-    parent_window = g_environ_getenv (context->priv->envp, "PARENT_WINDOW_ID");
-
-  real_uri = real_uri_for_portal (uri, context, NULL, NULL, NULL, &error);
-  if (real_uri == NULL)
-    {
-      g_object_unref (session_bus);
-      return;
-    }
-
-  g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
-
-  /* Calling the D-Bus method for the OpenURI portal "protects" the logic from
-   * not ever having the remote method running in case the xdg-desktop-portal
-   * process is not yet running and the caller quits quickly after the call.
-   */
-  res = g_dbus_connection_call_sync (session_bus,
-                                     FLATPAK_OPENURI_PORTAL_BUS_NAME,
-                                     FLATPAK_OPENURI_PORTAL_PATH,
-                                     FLATPAK_OPENURI_PORTAL_IFACE,
-                                     FLATPAK_OPENURI_PORTAL_METHOD,
-                                     g_variant_new ("(ss@a{sv})",
-                                                    parent_window ? parent_window : "",
-                                                    real_uri,
-                                                    g_variant_builder_end (&opt_builder)),
-                                     NULL,
-                                     G_DBUS_CALL_FLAGS_NONE,
-                                     G_MAXINT,
-                                     NULL,
-                                     &error);
-  if (res == NULL)
-    g_task_report_error (context, NULL, NULL, NULL, error);
-  else
-    g_variant_unref (res);
-
-  g_dbus_connection_flush (session_bus, NULL, NULL, NULL);
-  g_object_unref (session_bus);
-  g_free (real_uri);
-}
-
-static gboolean
-launch_default_with_portal (const char         *uri,
-                            GAppLaunchContext  *context,
-                            GError            **error)
-{
-  launch_default_with_portal_sync (uri, context);
-  return TRUE;
-}
-#endif
-
 static gboolean
 launch_default_for_uri (const char         *uri,
                         GAppLaunchContext  *context,
@@ -985,10 +748,16 @@ g_app_info_launch_default_for_uri (const char         *uri,
 #ifdef G_OS_UNIX
   if (glib_should_use_portal ())
     {
+      const char *parent_window = NULL;
+
       /* Reset any error previously set by launch_default_for_uri */
       g_clear_error (error);
 
-      return launch_default_with_portal (uri, launch_context, error);
+      if (launch_context && launch_context->priv->envp)
+        parent_window = g_environ_getenv (launch_context->priv->envp, "PARENT_WINDOW_ID");
+
+      return g_openuri_portal_open_uri (uri, parent_window, error);
+
     }
 #endif
 
@@ -1028,7 +797,12 @@ g_app_info_launch_default_for_uri_async (const char          *uri,
 #ifdef G_OS_UNIX
   if (!res && glib_should_use_portal ())
     {
-      launch_default_with_portal_async (uri, context, cancellable, callback, user_data);
+      const  char *parent_window = NULL;
+
+      if (context && context->priv->envp)
+        parent_window = g_environ_getenv (context->priv->envp, "PARENT_WINDOW_ID");
+
+      g_openuri_portal_open_uri_async (uri, parent_window, cancellable, callback, user_data);
       return;
     }
 #endif
@@ -1057,7 +831,7 @@ gboolean
 g_app_info_launch_default_for_uri_finish (GAsyncResult  *result,
                                           GError       **error)
 {
-  return g_task_propagate_boolean (G_TASK (result), error);
+  return g_openuri_portal_open_uri_finish (result, error);
 }
 
 /**
diff --git a/gio/gopenuriportal.c b/gio/gopenuriportal.c
new file mode 100644
index 0000000..973190b
--- /dev/null
+++ b/gio/gopenuriportal.c
@@ -0,0 +1,302 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2017 Red Hat, Inc.
+ *
+ * This library 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/>.
+ */
+
+#include "config.h"
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "gopenuriportal.h"
+#include "xdp-dbus.h"
+#include "gstdio.h"
+
+#ifdef G_OS_UNIX
+#include "gunixfdlist.h"
+#endif
+
+#ifndef O_PATH
+#define O_PATH 0
+#endif
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#else
+#define HAVE_O_CLOEXEC 1
+#endif
+
+
+static GXdpOpenURI *openuri;
+
+static gboolean
+init_openuri_portal (void)
+{
+  static gsize openuri_inited = 0;
+
+  if (g_once_init_enter (&openuri_inited))
+    {
+      GError *error = NULL;
+      GDBusConnection *connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+
+      if (connection != NULL)
+        {
+          openuri = gxdp_open_uri_proxy_new_sync (connection, 0,
+                                                  "org.freedesktop.portal.Desktop",
+                                                  "/org/freedesktop/portal/desktop",
+                                                  NULL, &error);
+          if (openuri == NULL)
+            {
+              g_warning ("Cannot create document portal proxy: %s", error->message);
+              g_error_free (error);
+            }
+
+          g_object_unref (connection);
+        }
+      else
+        {
+          g_warning ("Cannot connect to session bus when initializing document portal: %s",
+                     error->message);
+          g_error_free (error);
+        }
+
+      g_once_init_leave (&openuri_inited, 1);
+    }
+
+  return openuri != NULL;
+}
+
+gboolean
+g_openuri_portal_open_uri (const char  *uri,
+                           const char  *parent_window,
+                           GError     **error)
+{
+  GFile *file = NULL;
+  GVariantBuilder opt_builder;
+  gboolean res;
+
+  if (!init_openuri_portal ())
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED,
+                   "OpenURI portal is not available");
+      return FALSE;
+    }
+
+  g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
+
+  file = g_file_new_for_uri (uri);
+  if (g_file_is_native (file))
+    {
+      char *path = NULL;
+      GUnixFDList *fd_list = NULL;
+      int fd, fd_id;
+
+      path = g_file_get_path (file);
+
+      fd = g_open (path, O_PATH | O_CLOEXEC);
+#ifndef HAVE_O_CLOEXEC
+      fcntl (fd, F_SETFD, FD_CLOEXEC);
+#endif
+      fd_list = g_unix_fd_list_new_from_array (&fd, 1);
+      fd = -1;
+      fd_id = 0;
+
+      res = gxdp_open_uri_call_open_file_sync (openuri,
+                                               parent_window ? parent_window : "",
+                                               g_variant_new ("h", fd_id),
+                                               g_variant_builder_end (&opt_builder),
+                                               fd_list,
+                                               NULL,
+                                               NULL,
+                                               NULL,
+                                               error);
+      g_free (path);
+      g_object_unref (fd_list);
+    }
+  else
+    {
+      res = gxdp_open_uri_call_open_uri_sync (openuri,
+                                              parent_window ? parent_window : "",
+                                              uri,
+                                              g_variant_builder_end (&opt_builder),
+                                              NULL,
+                                              NULL,
+                                              error);
+    }
+
+  g_object_unref (file);
+
+  return res;
+}
+
+enum {
+  XDG_DESKTOP_PORTAL_SUCCESS   = 0,
+  XDG_DESKTOP_PORTAL_CANCELLED = 1,
+  XDG_DESKTOP_PORTAL_FAILED    = 2
+};
+
+static void
+response_received (GDBusConnection *connection,
+                   const char      *sender_name,
+                   const char      *object_path,
+                   const char      *interface_name,
+                   const char      *signal_name,
+                   GVariant        *parameters,
+                   gpointer         user_data)
+{
+  GTask *task = user_data;
+  guint32 response;
+  guint signal_id;
+
+  signal_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (task), "signal-id"));
+  g_dbus_connection_signal_unsubscribe (connection, signal_id);
+
+  g_variant_get (parameters, "(u@a{sv})", &response, NULL);
+
+  switch (response)
+    {
+    case XDG_DESKTOP_PORTAL_SUCCESS:
+      g_task_return_boolean (task, TRUE);
+      break;
+    case XDG_DESKTOP_PORTAL_CANCELLED:
+      g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Launch cancelled");
+      break;
+    case XDG_DESKTOP_PORTAL_FAILED:
+    default:
+      g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Launch failed");
+      break;
+    }
+
+  g_object_unref (task);
+}
+
+static void
+open_call_done (GObject      *source,
+                GAsyncResult *result,
+                gpointer      user_data)
+{
+  GDBusConnection *connection = G_DBUS_CONNECTION (source);
+  GTask *task = user_data;
+  GError *error = NULL;
+  gboolean open_file;
+  gboolean res;
+  char *path;
+  guint signal_id;
+
+  open_file = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (task), "open-file"));
+
+  if (open_file)
+    res = gxdp_open_uri_call_open_file_finish (openuri, &path, NULL, result, &error);
+  else
+    res = gxdp_open_uri_call_open_uri_finish (openuri, &path, result, &error);
+
+  if (!res)
+    {
+      g_task_return_error (task, error);
+      g_object_unref (task);
+      g_free (path);
+      return;
+    }
+
+  signal_id = g_dbus_connection_signal_subscribe (connection,
+                                                  "org.freedesktop.portal.Desktop",
+                                                  "org.freedesktop.portal.Request",
+                                                  "Response",
+                                                  path,
+                                                  NULL,
+                                                  G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
+                                                  response_received,
+                                                  task,
+                                                  NULL);
+  g_object_set_data (G_OBJECT (task), "signal-id", GINT_TO_POINTER (signal_id));
+}
+
+void
+g_openuri_portal_open_uri_async (const char          *uri,
+                                 const char          *parent_window,
+                                 GCancellable        *cancellable,
+                                 GAsyncReadyCallback  callback,
+                                 gpointer             user_data)
+{
+  GTask *task;
+  GFile *file;
+  GVariantBuilder opt_builder;
+
+  if (!init_openuri_portal ())
+    {
+      g_task_report_new_error (NULL, callback, user_data, NULL,
+                               G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED,
+                               "OpenURI portal is not available");
+      return;
+    }
+
+  if (callback)
+    task = g_task_new (NULL, cancellable, callback, user_data);
+  else
+    task = NULL;
+
+  g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
+
+  file = g_file_new_for_uri (uri);
+  if (g_file_is_native (file))
+    {
+      char *path = NULL;
+      GUnixFDList *fd_list = NULL;
+      int fd, fd_id;
+
+      if (task)
+        g_object_set_data (G_OBJECT (task), "open-file", GINT_TO_POINTER (TRUE));
+
+      path = g_file_get_path (file);
+      fd = g_open (path, O_PATH | O_CLOEXEC);
+#ifndef HAVE_O_CLOEXEC
+      fcntl (fd, F_SETFD, FD_CLOEXEC);
+#endif
+      fd_list = g_unix_fd_list_new_from_array (&fd, 1);
+      fd = -1;
+      fd_id = 0;
+
+      gxdp_open_uri_call_open_file (openuri,
+                                    parent_window ? parent_window : "",
+                                    g_variant_new ("h", fd_id),
+                                    g_variant_builder_end (&opt_builder),
+                                    fd_list,
+                                    cancellable,
+                                    task ? open_call_done : NULL,
+                                    task);
+      g_object_unref (fd_list);
+      g_free (path);
+    }
+  else
+    {
+      gxdp_open_uri_call_open_uri (openuri,
+                                   parent_window ? parent_window : "",
+                                   uri,
+                                   g_variant_builder_end (&opt_builder),
+                                   cancellable,
+                                   task ? open_call_done : NULL,
+                                   task);
+    }
+
+  g_object_unref (file);
+}
+
+gboolean
+g_openuri_portal_open_uri_finish (GAsyncResult  *result,
+                                  GError       **error)
+{
+  return g_task_propagate_boolean (G_TASK (result), error);
+}
diff --git a/gio/gopenuriportal.h b/gio/gopenuriportal.h
new file mode 100644
index 0000000..49403b4
--- /dev/null
+++ b/gio/gopenuriportal.h
@@ -0,0 +1,41 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2017 Red Hat, Inc.
+ *
+ * This library 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/>.
+ */
+
+#ifndef __G_OPEN_URI_PORTAL_H__
+
+#include <glib.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+gboolean g_openuri_portal_open_uri        (const char  *uri,
+                                           const char  *parent_window,
+                                           GError     **error);
+
+void     g_openuri_portal_open_uri_async  (const char          *uri,
+                                           const char          *parent_window,
+                                           GCancellable        *cancellable,
+                                           GAsyncReadyCallback  callback,
+                                           gpointer             user_data);
+
+gboolean g_openuri_portal_open_uri_finish (GAsyncResult        *result,
+                                           GError             **error);
+
+G_END_DECLS
+
+#endif
diff --git a/gio/org.freedesktop.portal.OpenURI.xml b/gio/org.freedesktop.portal.OpenURI.xml
new file mode 100644
index 0000000..198d3c2
--- /dev/null
+++ b/gio/org.freedesktop.portal.OpenURI.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0"?>
+<!--
+ Copyright (C) 2016 Red Hat, Inc.
+
+ This library 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/>.
+
+ Author: Matthias Clasen <mclasen redhat com>
+-->
+
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd";>
+  <!--
+       org.freedesktop.portal.OpenURI:
+       @short_description: Portal for opening URIs
+
+       The OpenURI portal allows sandboxed applications to open
+       URIs (e.g. a http: link to the applications homepage)
+       under the control of the user.
+  -->
+  <interface name="org.freedesktop.portal.OpenURI">
+    <!--
+        OpenURI:
+        @parent_window: Identifier for the application window
+        @uri: The uri to open
+        @options: Vardict with optional further onformation
+        @handle: Object path for the #org.freedesktop.portal.Request object representing this call
+
+        Asks to open a uri.
+
+        The @parent_window identifier must be of the form "x11:$XID" for an X11
+        window. Support for other window systems may be added in the future.
+
+        Note that file:// uris are explicitly not supported by this method.
+        To request opening local files, use org.freedesktop.portal.OpenFile().
+
+        Supported keys in the @options vardict include:
+        <variablelist>
+          <varlistentry>
+            <term>writable b</term>
+            <listitem><para>
+              Whether to allow the chosen application to write to the file.
+            </para><para>
+              This key only takes effect the uri points to a local file that
+              is exported in the document portal, and the chosen application
+              is sandboxed itself.
+            </para></listitem>
+          </varlistentry>
+        </variablelist>
+
+    -->
+    <method name="OpenURI">
+      <arg type="s" name="parent_window" direction="in"/>
+      <arg type="s" name="uri" direction="in"/>
+      <arg type="a{sv}" name="options" direction="in"/>
+      <arg type="o" name="handle" direction="out"/>
+    </method>
+
+    <!--
+        OpenFile:
+        @parent_window: Identifier for the application window
+        @fd: File descriptor for the file to open
+        @options: Vardict with optional further onformation
+        @handle: Object path for the #org.freedesktop.portal.Request object representing this call
+
+        Asks to open a local file.
+
+        The @parent_window identifier must be of the form "x11:$XID" for an X11
+        window. Support for other window systems may be added in the future.
+
+        Supported keys in the @options vardict include:
+        <variablelist>
+          <varlistentry>
+            <term>writable b</term>
+            <listitem><para>
+              Whether to allow the chosen application to write to the file.
+            </para><para>
+              This key only takes effect the uri points to a local file that
+              is exported in the document portal, and the chosen application
+              is sandboxed itself.
+            </para></listitem>
+          </varlistentry>
+        </variablelist>
+
+        The OpenFile method was introduced in version 2 of the OpenURI portal API.
+    -->
+    <method name="OpenFile">
+      <arg type="s" name="parent_window" direction="in"/>
+      <arg type="h" name="fd" direction="in"/>
+      <arg type="a{sv}" name="options" direction="in"/>
+      <arg type="o" name="handle" direction="out"/>
+    </method>
+
+    <property name="version" type="u" access="read"/>
+  </interface>
+</node>


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