summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Grulich <jgrulich@redhat.com>2017-10-26 13:33:12 +0200
committerThiago Macieira <thiago.macieira@intel.com>2017-11-14 15:55:01 +0000
commitc35c017a6c4a9b9b20f18d121300dd96609ee253 (patch)
tree8cce735f2a43064016d6bd4ec5acf5c1a23abb37
parent772863355a0cf57a49e93608790dfd17c8fd82da (diff)
Add support for flatpak portals
Adds support for OpenURI and Email Flatpak portals. To support them we just do specific DBus calls, which are then caught and forwarded by xdg-desktop-portal daemon/service. This is needed for Qt applications running in sandbox, otherwise they cannot open links or email clients inside sandbox. Other portal support, like for opening files can be added into a platform theme, but adding support for OpenURI and Email portal requires writing custom platform services plugin and this is only possible when you write complete platform plugin, thus we want to have this support directly in Qt. Support for other portals will most likely follow soon, but at this moment we have to get rid of creating our custom platform plugin to just have our own platform services for flatpak support. [ChangeLog][Platform Specific Changes][Linux] Added support for flatpak portals. Flatpak is a software utility for software deployment and package management. It provides a sandbox environment in which users can run applications in isolation from the rest of the system. To communicate with the system flatpak uses portals, which are designed to be a bridge between sandboxed applications and desktop/system running on user's computer. Flatpak runs automatically this as service, called xdg-desktop-portal, which exports portals on DBus and which are by default visible to all applications running under Flatpak. Change-Id: Ice57ad120d30a3154b133172c79d8e9d6e61bd4c Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/platformsupport/services/genericunix/qgenericunixservices.cpp107
-rw-r--r--src/platformsupport/services/services.pro2
2 files changed, 108 insertions, 1 deletions
diff --git a/src/platformsupport/services/genericunix/qgenericunixservices.cpp b/src/platformsupport/services/genericunix/qgenericunixservices.cpp
index cdb5d33859..cb1e367b9f 100644
--- a/src/platformsupport/services/genericunix/qgenericunixservices.cpp
+++ b/src/platformsupport/services/genericunix/qgenericunixservices.cpp
@@ -49,6 +49,24 @@
#include <QtCore/QStandardPaths>
#include <QtCore/QUrl>
+#if QT_CONFIG(dbus)
+// These QtCore includes are needed for flatpak support
+#include <QtCore/private/qcore_unix_p.h>
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QUrlQuery>
+
+#include <QtDBus/QDBusConnection>
+#include <QtDBus/QDBusMessage>
+#include <QtDBus/QDBusPendingCall>
+#include <QtDBus/QDBusPendingCallWatcher>
+#include <QtDBus/QDBusPendingReply>
+#include <QtDBus/QDBusUnixFileDescriptor>
+
+#include <fcntl.h>
+
+#endif // QT_CONFIG(dbus)
+
#include <stdlib.h>
QT_BEGIN_NAMESPACE
@@ -153,6 +171,83 @@ static inline bool launch(const QString &launcher, const QUrl &url)
return ok;
}
+#if QT_CONFIG(dbus)
+static inline bool checkRunningUnderFlatpak()
+{
+ return !QStandardPaths::locate(QStandardPaths::RuntimeLocation, QLatin1String("flatpak-info")).isEmpty();
+}
+
+static inline bool flatpakOpenUrl(const QUrl &url)
+{
+ // DBus signature:
+ // OpenURI (IN s parent_window,
+ // IN s uri,
+ // IN a{sv} options,
+ // OUT o handle)
+ // Options:
+ // writable (b) - Whether to allow the chosen application to write to the file.
+ // 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.
+
+ QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.portal.Desktop"),
+ QLatin1String("/org/freedesktop/portal/desktop"),
+ QLatin1String("org.freedesktop.portal.OpenURI"),
+ QLatin1String("OpenURI"));
+ // FIXME parent_window_id and handle writable option
+ message << QString() << url.toString() << QVariantMap();
+
+ QDBusPendingReply<QDBusObjectPath> reply = QDBusConnection::sessionBus().call(message);
+ return !reply.isError();
+}
+
+static inline bool flatpakSendEmail(const QUrl &url)
+{
+ // DBus signature:
+ // ComposeEmail (IN s parent_window,
+ // IN a{sv} options,
+ // OUT o handle)
+ // Options:
+ // address (s) - The email address to send to.
+ // subject (s) - The subject for the email.
+ // body (s) - The body for the email.
+ // attachment_fds (ah) - File descriptors for files to attach.
+
+ QUrlQuery urlQuery(url);
+ QVariantMap options;
+ options.insert(QLatin1String("address"), url.path());
+ options.insert(QLatin1String("subject"), urlQuery.queryItemValue(QLatin1String("subject")));
+ options.insert(QLatin1String("body"), urlQuery.queryItemValue(QLatin1String("body")));
+
+ // O_PATH seems to be present since Linux 2.6.39, which is not case of RHEL 6
+#ifdef O_PATH
+ QList<QDBusUnixFileDescriptor> attachments;
+ const QStringList attachmentUris = urlQuery.allQueryItemValues(QLatin1String("attachment"));
+
+ for (const QString &attachmentUri : attachmentUris) {
+ const int fd = qt_safe_open(QFile::encodeName(attachmentUri), O_PATH);
+ if (fd != -1) {
+ QDBusUnixFileDescriptor descriptor(fd);
+ attachments << descriptor;
+ qt_safe_close(fd);
+ }
+ }
+
+ options.insert(QLatin1String("attachment_fds"), QVariant::fromValue(attachments));
+#endif
+
+ QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.portal.Desktop"),
+ QLatin1String("/org/freedesktop/portal/desktop"),
+ QLatin1String("org.freedesktop.portal.Email"),
+ QLatin1String("ComposeEmail"));
+
+ // FIXME parent_window_id
+ message << QString() << options;
+
+ QDBusPendingReply<QDBusObjectPath> reply = QDBusConnection::sessionBus().call(message);
+ return !reply.isError();
+}
+#endif // QT_CONFIG(dbus)
+
QByteArray QGenericUnixServices::desktopEnvironment() const
{
static const QByteArray result = detectDesktopEnvironment();
@@ -161,8 +256,18 @@ QByteArray QGenericUnixServices::desktopEnvironment() const
bool QGenericUnixServices::openUrl(const QUrl &url)
{
- if (url.scheme() == QLatin1String("mailto"))
+ if (url.scheme() == QLatin1String("mailto")) {
+#if QT_CONFIG(dbus)
+ if (checkRunningUnderFlatpak())
+ return flatpakSendEmail(url);
+#endif
return openDocument(url);
+ }
+
+#if QT_CONFIG(dbus)
+ if (checkRunningUnderFlatpak())
+ return flatpakOpenUrl(url);
+#endif
if (m_webBrowser.isEmpty() && !detectWebBrowser(desktopEnvironment(), true, &m_webBrowser)) {
qWarning("Unable to detect a web browser to launch '%s'", qPrintable(url.toString()));
diff --git a/src/platformsupport/services/services.pro b/src/platformsupport/services/services.pro
index 91957a0a78..2027c7b5be 100644
--- a/src/platformsupport/services/services.pro
+++ b/src/platformsupport/services/services.pro
@@ -2,6 +2,8 @@ TARGET = QtServiceSupport
MODULE = service_support
QT = core-private gui-private
+qtConfig(dbus): QT += dbus
+
CONFIG += static internal_module
DEFINES += QT_NO_CAST_FROM_ASCII