appinfo: support opening files through document portal

In addition to URIs, we now also support opening files internal to the
sandboxed application through the document portal.
This commit is contained in:
Cosimo Cecchi 2016-07-11 15:14:34 -07:00
parent f4e2047f20
commit 62bd8f54bb
5 changed files with 260 additions and 1 deletions

View File

@ -344,6 +344,7 @@ BUILT_SOURCES += $(xdp_dbus_built_sources)
CLEANFILES += $(xdp_dbus_built_sources)
portal_interfaces = \
org.freedesktop.portal.Documents.xml \
org.freedesktop.portal.NetworkMonitor.xml \
org.freedesktop.portal.ProxyResolver.xml \
$(NULL)
@ -357,6 +358,8 @@ $(xdp_dbus_built_sources) : $(portal_interfaces)
--interface-prefix org.freedesktop.portal. \
--c-namespace GXdp \
--generate-c-code $(builddir)/xdp-dbus \
--annotate "org.freedesktop.portal.Documents.Add()" "org.gtk.GDBus.C.UnixFD" "true" \
--annotate "org.freedesktop.portal.Documents.AddNamed()" "org.gtk.GDBus.C.UnixFD" "true" \
$^
portal_sources = \
@ -389,6 +392,8 @@ libgio_2_0_la_SOURCES = \
gdatagrambased.c \
gdatainputstream.c \
gdataoutputstream.c \
gdocumentportal.c \
gdocumentportal.h \
gdrive.c \
gdummyfile.h \
gdummyfile.c \

View File

@ -29,6 +29,7 @@
#include "glibintl.h"
#include <gioerror.h>
#include <gfile.h>
#include "gdocumentportal.h"
#include "gportalsupport.h"
@ -680,6 +681,8 @@ launch_default_with_portal (const char *uri,
GDBusConnection *session_bus;
GVariantBuilder opt_builder;
const char *parent_window = NULL;
GFile *file;
char *real_uri;
session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
if (session_bus == NULL)
@ -690,6 +693,28 @@ launch_default_with_portal (const char *uri,
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
file = g_file_new_for_uri (uri);
if (g_file_is_native (file))
{
GError *local_error = NULL;
real_uri = g_document_portal_add_document (file, &local_error);
g_object_unref (file);
if (real_uri == NULL)
{
g_warning ("Can't register with document portal: %s", local_error->message);
g_propagate_error (error, local_error);
return FALSE;
}
}
else
{
g_object_unref (file);
real_uri = g_strdup (uri);
}
g_dbus_connection_call (session_bus,
"org.freedesktop.portal.Desktop",
"/org/freedesktop/portal/desktop",
@ -697,7 +722,7 @@ launch_default_with_portal (const char *uri,
"OpenURI",
g_variant_new ("(ss@a{sv})",
parent_window ? parent_window : "",
uri,
real_uri,
g_variant_builder_end (&opt_builder)),
NULL,
G_DBUS_CALL_FLAGS_NONE,
@ -708,6 +733,7 @@ launch_default_with_portal (const char *uri,
g_dbus_connection_flush (session_bus, NULL, NULL, NULL);
g_object_unref (session_bus);
g_free (real_uri);
return TRUE;
}

126
gio/gdocumentportal.c Normal file
View File

@ -0,0 +1,126 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright 2016 Endless Mobile, 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 "gdocumentportal.h"
#include "xdp-dbus.h"
#include "gstdio.h"
#ifdef G_OS_UNIX
#include "gunixfdlist.h"
#endif
static GXdpDocuments *documents;
static char *documents_mountpoint;
static void
init_document_portal (void)
{
static gsize documents_inited = 0;
if (g_once_init_enter (&documents_inited))
{
GError *error = NULL;
GDBusConnection *connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
if (connection != NULL)
{
documents = gxdp_documents_proxy_new_sync (connection, 0,
"org.freedesktop.portal.Documents",
"/org/freedesktop/portal/documents",
NULL, NULL);
gxdp_documents_call_get_mount_point_sync (documents,
&documents_mountpoint,
NULL, NULL);
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 (&documents_inited, 1);
}
}
char *
g_document_portal_add_document (GFile *file,
GError **error)
{
char *doc_path, *path, *basename;
char *doc_id = NULL;
char *doc_uri = NULL;
GUnixFDList *fd_list = NULL;
int fd, fd_in;
gboolean ret;
init_document_portal ();
path = g_file_get_path (file);
fd = g_open (path, O_PATH | O_CLOEXEC);
if (fd == -1)
{
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
"Failed to open %s", path);
goto out;
}
fd_list = g_unix_fd_list_new ();
fd_in = g_unix_fd_list_append (fd_list, fd, error);
g_close (fd, NULL);
if (fd_in == -1)
goto out;
ret = gxdp_documents_call_add_sync (documents,
g_variant_new_handle (fd_in),
TRUE,
TRUE,
fd_list,
&doc_id,
NULL,
NULL,
error);
if (!ret)
goto out;
basename = g_path_get_basename (path);
doc_path = g_build_filename (documents_mountpoint, doc_id, basename, NULL);
g_free (basename);
doc_uri = g_filename_to_uri (doc_path, NULL, NULL);
g_free (doc_path);
out:
if (fd_list)
g_object_unref (fd_list);
g_free (path);
g_free (doc_id);
return doc_uri;
}

31
gio/gdocumentportal.h Normal file
View File

@ -0,0 +1,31 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright 2016 Endless Mobile, 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_DOCUMENT_PORTAL_H__
#include <glib.h>
#include <gio/gio.h>
G_BEGIN_DECLS
char * g_document_portal_add_document (GFile *file,
GError **error);
G_END_DECLS
#endif

View File

@ -0,0 +1,71 @@
<!DOCTYPE node PUBLIC
"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<!--
Copyright (C) 2015 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, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
Author: Alexander Larsson <alexl@redhat.com>
-->
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
<interface name='org.freedesktop.portal.Documents'>
<method name="GetMountPoint">
<arg type='ay' name='path' direction='out'/>
</method>
<method name="Add">
<arg type='h' name='o_path_fd' direction='in'/>
<arg type='b' name='reuse_existing' direction='in'/>
<arg type='b' name='persistent' direction='in'/>
<arg type='s' name='doc_id' direction='out'/>
</method>
<method name="AddNamed">
<arg type='h' name='o_path_parent_fd' direction='in'/>
<arg type='ay' name='filename' direction='in'/>
<arg type='b' name='reuse_existing' direction='in'/>
<arg type='b' name='persistent' direction='in'/>
<arg type='s' name='doc_id' direction='out'/>
</method>
<method name="GrantPermissions">
<arg type='s' name='doc_id' direction='in'/>
<arg type='s' name='app_id' direction='in'/>
<arg type='as' name='permissions' direction='in'/>
</method>
<method name="RevokePermissions">
<arg type='s' name='doc_id' direction='in'/>
<arg type='s' name='app_id' direction='in'/>
<arg type='as' name='permissions' direction='in'/>
</method>
<method name="Delete">
<arg type='s' name='doc_id' direction='in'/>
</method>
<method name="Lookup">
<arg type='ay' name='filename' direction='in'/>
<arg type='s' name='doc_id' direction='out'/>
</method>
<method name="Info">
<arg type='s' name='doc_id' direction='in'/>
<arg type='ay' name='path' direction='out'/>
<arg type='a{sas}' name='apps' direction='out'/>
</method>
<method name="List">
<arg type='s' name='app_id' direction='in'/>
<arg type='a{say}' name='docs' direction='out'/>
</method>
</interface>
</node>