1
mirror of https://invent.kde.org/network/falkon.git synced 2024-11-11 01:22:10 +01:00

QtSingleApplication: Add DBus backend for Linux

It should be more reliable than lockfile.

BUG: 404494
FIXED-IN: 3.1.0
This commit is contained in:
David Rosca 2019-02-19 11:10:57 +01:00
parent 1553ab3c1b
commit 102bd219b7
No known key found for this signature in database
GPG Key ID: EBC3FC294452C6D8
3 changed files with 70 additions and 4 deletions

View File

@ -44,6 +44,11 @@
#include <QDataStream> #include <QDataStream>
#include <QTime> #include <QTime>
#include "../config.h"
#if defined(Q_OS_LINUX) && !defined(DISABLE_DBUS)
#define USE_DBUS
#endif
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
#include <QLibrary> #include <QLibrary>
#include <qt_windows.h> #include <qt_windows.h>
@ -65,6 +70,33 @@ namespace QtLP_Private {
#endif #endif
} }
#ifdef USE_DBUS
#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QDBusAbstractAdaptor>
class QtSingleAppDBusInterface : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.kde.QtSingleApplication")
public:
explicit QtSingleAppDBusInterface(QObject *parent)
: QDBusAbstractAdaptor(parent)
{
}
public Q_SLOTS:
void SendMessage(const QString &message)
{
Q_EMIT messageReceived(message);
}
Q_SIGNALS:
void messageReceived(const QString &message);
};
#endif
const char* QtLocalPeer::ack = "ack"; const char* QtLocalPeer::ack = "ack";
QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId) QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId)
@ -100,18 +132,36 @@ QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId)
socketName += QLatin1Char('-') + QString::number(::getuid(), 16); socketName += QLatin1Char('-') + QString::number(::getuid(), 16);
#endif #endif
#ifdef USE_DBUS
if (!QDBusConnection::sessionBus().isConnected()) {
qCritical("Failed to connect to session bus!");
}
m_dbusRegistered = QDBusConnection::sessionBus().registerService(id);
if (m_dbusRegistered) {
QtSingleAppDBusInterface *iface = new QtSingleAppDBusInterface(this);
connect(iface, &QtSingleAppDBusInterface::messageReceived, this, &QtLocalPeer::messageReceived);
QDBusConnection::sessionBus().registerObject(QStringLiteral("/"), this);
}
#else
server = new QLocalServer(this); server = new QLocalServer(this);
QString lockName = QDir(QDir::tempPath()).absolutePath() QString lockName = QDir(QDir::tempPath()).absolutePath()
+ QLatin1Char('/') + socketName + QLatin1Char('/') + socketName
+ QLatin1String("-lockfile"); + QLatin1String("-lockfile");
lockFile.setFileName(lockName); lockFile.setFileName(lockName);
lockFile.open(QIODevice::ReadWrite); lockFile.open(QIODevice::ReadWrite);
#endif
} }
bool QtLocalPeer::isClient() bool QtLocalPeer::isClient()
{ {
#ifdef USE_DBUS
if (m_dbusRegistered) {
return false;
}
return QDBusConnection::sessionBus().interface()->isServiceRegistered(id).value();
#else
if (lockFile.isLocked()) if (lockFile.isLocked())
return false; return false;
@ -130,6 +180,7 @@ bool QtLocalPeer::isClient()
qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString())); qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString()));
QObject::connect(server, &QLocalServer::newConnection, this, &QtLocalPeer::receiveConnection); QObject::connect(server, &QLocalServer::newConnection, this, &QtLocalPeer::receiveConnection);
return false; return false;
#endif
} }
@ -138,6 +189,13 @@ bool QtLocalPeer::sendMessage(const QString &message, int timeout)
if (!isClient()) if (!isClient())
return false; return false;
#ifdef USE_DBUS
QDBusMessage msg = QDBusMessage::createMethodCall(id, QStringLiteral("/"),
QStringLiteral("org.kde.QtSingleApplication"),
QStringLiteral("SendMessage"));
msg << message;
return QDBusConnection::sessionBus().call(msg, QDBus::Block, timeout).type() == QDBusMessage::ReplyMessage;
#else
QLocalSocket socket; QLocalSocket socket;
bool connOk = false; bool connOk = false;
for(int i = 0; i < 2; i++) { for(int i = 0; i < 2; i++) {
@ -167,15 +225,19 @@ bool QtLocalPeer::sendMessage(const QString &message, int timeout)
res &= (socket.read(qstrlen(ack)) == ack); res &= (socket.read(qstrlen(ack)) == ack);
} }
return res; return res;
#endif
} }
void QtLocalPeer::removeLockedFile() void QtLocalPeer::removeLockedFile()
{ {
#ifndef USE_DBUS
lockFile.remove(); lockFile.remove();
#endif
} }
void QtLocalPeer::receiveConnection() void QtLocalPeer::receiveConnection()
{ {
#ifndef USE_DBUS
QLocalSocket* socket = server->nextPendingConnection(); QLocalSocket* socket = server->nextPendingConnection();
if (!socket) if (!socket)
return; return;
@ -214,4 +276,7 @@ void QtLocalPeer::receiveConnection()
socket->waitForDisconnected(1000); // make sure client reads ack socket->waitForDisconnected(1000); // make sure client reads ack
delete socket; delete socket;
emit messageReceived(message); //### (might take a long time to return) emit messageReceived(message); //### (might take a long time to return)
#endif
} }
#include "qtlocalpeer.moc"

View File

@ -73,6 +73,7 @@ protected:
private: private:
static const char* ack; static const char* ack;
bool m_dbusRegistered = false;
}; };
#endif // QTLOCALPEER_H #endif // QTLOCALPEER_H

View File

@ -223,14 +223,14 @@ MainApplication::MainApplication(int &argc, char** argv)
// Don't start single application in private browsing // Don't start single application in private browsing
if (!isPrivate()) { if (!isPrivate()) {
QString appId = QStringLiteral("FalkonWebBrowser"); QString appId = QStringLiteral("org.kde.Falkon");
if (isPortable()) { if (isPortable()) {
appId.append(QLatin1String("Portable")); appId.append(QLatin1String(".Portable"));
} }
if (isTestModeEnabled()) { if (isTestModeEnabled()) {
appId.append(QSL("TestMode")); appId.append(QSL(".TestMode"));
} }
if (newInstance) { if (newInstance) {
@ -241,7 +241,7 @@ MainApplication::MainApplication(int &argc, char** argv)
// Generate unique appId so it is possible to start more separate instances // Generate unique appId so it is possible to start more separate instances
// of the same profile. It is dangerous to run more instances of the same profile, // of the same profile. It is dangerous to run more instances of the same profile,
// but if the user wants it, we should allow it. // but if the user wants it, we should allow it.
appId.append(startProfile + QString::number(QDateTime::currentMSecsSinceEpoch())); appId.append(QLatin1Char('.') + startProfile + QString::number(QDateTime::currentMSecsSinceEpoch()));
} }
} }