diff options
author | Jan Grulich <jgrulich@redhat.com> | 2017-10-26 13:33:12 +0200 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2017-11-14 15:55:01 +0000 |
commit | c35c017a6c4a9b9b20f18d121300dd96609ee253 (patch) | |
tree | 8cce735f2a43064016d6bd4ec5acf5c1a23abb37 /src | |
parent | 772863355a0cf57a49e93608790dfd17c8fd82da (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>
Diffstat (limited to 'src')
-rw-r--r-- | src/platformsupport/services/genericunix/qgenericunixservices.cpp | 107 | ||||
-rw-r--r-- | src/platformsupport/services/services.pro | 2 |
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 |