Allow to use private DBus
This commit is contained in:
parent
8406e0de99
commit
4f4b6c309f
10 changed files with 294 additions and 5 deletions
|
@ -69,6 +69,10 @@ set_package_properties(KF5Kirigami2 PROPERTIES
|
||||||
TYPE RUNTIME
|
TYPE RUNTIME
|
||||||
)
|
)
|
||||||
|
|
||||||
|
option(PRIVATE_DBUS_ENABLED "Use private dbus session for kdeconnect" OFF)
|
||||||
|
if(PRIVATE_DBUS_ENABLED OR APPLE)
|
||||||
|
add_compile_definitions(USE_PRIVATE_DBUS)
|
||||||
|
endif()
|
||||||
add_subdirectory(core)
|
add_subdirectory(core)
|
||||||
if(NOT SAILFISHOS)
|
if(NOT SAILFISHOS)
|
||||||
add_subdirectory(kcm)
|
add_subdirectory(kcm)
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
add_definitions(-DTRANSLATION_DOMAIN=\"kdeconnect-core\")
|
add_definitions(-DTRANSLATION_DOMAIN=\"kdeconnect-core\")
|
||||||
|
|
||||||
set(KDECONNECT_PRIVATE_DBUS_ADDR unix:path=/tmp/kdeconnect-dbus)
|
set(KDECONNECT_PRIVATE_DBUS_ADDR unix:tmpdir=/tmp)
|
||||||
|
if(WIN32)
|
||||||
|
set(KDECONNECT_PRIVATE_DBUS_ADDR tcp:host=localhost,port=0)
|
||||||
|
endif()
|
||||||
set(KDECONNECT_PRIVATE_DBUS_NAME DBusKDEConnectOnly)
|
set(KDECONNECT_PRIVATE_DBUS_NAME DBusKDEConnectOnly)
|
||||||
configure_file(dbushelper.h.in ${CMAKE_CURRENT_BINARY_DIR}/dbushelper.h)
|
configure_file(dbushelper.h.in ${CMAKE_CURRENT_BINARY_DIR}/dbushelper.h)
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,39 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dbushelper.h"
|
#include "dbushelper.h"
|
||||||
|
#include "core_debug.h"
|
||||||
|
|
||||||
|
#include <QRegExp>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
#include "kdeconnectconfig.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
#include <CoreFoundation/CFBundle.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace DbusHelper {
|
namespace DbusHelper {
|
||||||
|
|
||||||
|
#ifdef USE_PRIVATE_DBUS
|
||||||
|
class DBusInstancePrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DBusInstancePrivate();
|
||||||
|
~DBusInstancePrivate();
|
||||||
|
|
||||||
|
void launchDBusDaemon();
|
||||||
|
void closeDBusDaemon();
|
||||||
|
private:
|
||||||
|
QProcess *m_dbusProcess;
|
||||||
|
};
|
||||||
|
|
||||||
|
static DBusInstancePrivate dbusInstance;
|
||||||
|
#endif
|
||||||
|
|
||||||
void filterNonExportableCharacters(QString& s)
|
void filterNonExportableCharacters(QString& s)
|
||||||
{
|
{
|
||||||
static QRegExp regexp(QStringLiteral("[^A-Za-z0-9_]"), Qt::CaseSensitive, QRegExp::Wildcard);
|
static QRegExp regexp(QStringLiteral("[^A-Za-z0-9_]"), Qt::CaseSensitive, QRegExp::Wildcard);
|
||||||
|
@ -30,11 +60,88 @@ void filterNonExportableCharacters(QString& s)
|
||||||
|
|
||||||
QDBusConnection sessionBus()
|
QDBusConnection sessionBus()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_MAC
|
#ifdef USE_PRIVATE_DBUS
|
||||||
return QDBusConnection::connectToBus(QStringLiteral(KDECONNECT_PRIVATE_DBUS_ADDR), QStringLiteral(KDECONNECT_PRIVATE_DBUS_NAME));
|
return QDBusConnection::connectToBus(KdeConnectConfig::instance()->privateDBusAddress(),
|
||||||
|
QStringLiteral(KDECONNECT_PRIVATE_DBUS_NAME));
|
||||||
#else
|
#else
|
||||||
return QDBusConnection::sessionBus();
|
return QDBusConnection::sessionBus();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_PRIVATE_DBUS
|
||||||
|
void launchDBusDaemon()
|
||||||
|
{
|
||||||
|
dbusInstance.launchDBusDaemon();
|
||||||
|
}
|
||||||
|
|
||||||
|
void closeDBusDaemon()
|
||||||
|
{
|
||||||
|
dbusInstance.closeDBusDaemon();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DBusInstancePrivate::launchDBusDaemon()
|
||||||
|
{
|
||||||
|
// Kill old dbus daemon
|
||||||
|
if (m_dbusProcess != nullptr) closeDBusDaemon();
|
||||||
|
|
||||||
|
// Start dbus daemon
|
||||||
|
m_dbusProcess = new QProcess();
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
// On macOS, assuming the executable is in Contents/MacOS
|
||||||
|
CFURLRef url = (CFURLRef)CFAutorelease((CFURLRef)CFBundleCopyBundleURL(CFBundleGetMainBundle()));
|
||||||
|
QString basePath = QUrl::fromCFURL(url).path();
|
||||||
|
QString kdeconnectDBusExecutable = basePath + QStringLiteral("Contents/MacOS/dbus-daemon"),
|
||||||
|
kdeconnectDBusConfiguration = basePath + QStringLiteral("Contents/Resources/dbus-1/session.conf");
|
||||||
|
qCDebug(KDECONNECT_CORE) << "App package path: " << basePath;
|
||||||
|
|
||||||
|
m_dbusProcess->setProgram(kdeconnectDBusExecutable);
|
||||||
|
m_dbusProcess->setArguments({QStringLiteral("--print-address"),
|
||||||
|
QStringLiteral("--nofork"),
|
||||||
|
QStringLiteral("--config-file=") + kdeconnectDBusConfiguration,
|
||||||
|
QStringLiteral("--address=") + QStringLiteral(KDECONNECT_PRIVATE_DBUS_ADDR)});
|
||||||
|
m_dbusProcess->setWorkingDirectory(basePath);
|
||||||
|
#elif defined(Q_OS_WIN)
|
||||||
|
// On Windows
|
||||||
|
m_dbusProcess->setProgram(QStringLiteral("dbus-daemon.exe"));
|
||||||
|
m_dbusProcess->setArguments({QStringLiteral("--session"),
|
||||||
|
QStringLiteral("--print-address"),
|
||||||
|
QStringLiteral("--nofork"),
|
||||||
|
QStringLiteral("--address=") + QStringLiteral(KDECONNECT_PRIVATE_DBUS_ADDR)});
|
||||||
|
#else
|
||||||
|
// On Linux or other unix-like system
|
||||||
|
m_dbusProcess->setProgram(QStringLiteral("dbus-daemon"));
|
||||||
|
m_dbusProcess->setArguments({QStringLiteral("--session"),
|
||||||
|
QStringLiteral("--print-address"),
|
||||||
|
QStringLiteral("--nofork"),
|
||||||
|
QStringLiteral("--address=") + QStringLiteral(KDECONNECT_PRIVATE_DBUS_ADDR)});
|
||||||
|
#endif
|
||||||
|
m_dbusProcess->setStandardOutputFile(KdeConnectConfig::instance()->privateDBusAddressPath());
|
||||||
|
m_dbusProcess->setStandardErrorFile(QProcess::nullDevice());
|
||||||
|
m_dbusProcess->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DBusInstancePrivate::closeDBusDaemon()
|
||||||
|
{
|
||||||
|
if (m_dbusProcess != nullptr)
|
||||||
|
{
|
||||||
|
m_dbusProcess->terminate();
|
||||||
|
m_dbusProcess->waitForFinished();
|
||||||
|
delete m_dbusProcess;
|
||||||
|
m_dbusProcess = nullptr;
|
||||||
|
|
||||||
|
QFile privateDBusAddressFile(KdeConnectConfig::instance()->privateDBusAddressPath());
|
||||||
|
|
||||||
|
if (privateDBusAddressFile.exists()) privateDBusAddressFile.resize(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DBusInstancePrivate::DBusInstancePrivate()
|
||||||
|
:m_dbusProcess(nullptr){}
|
||||||
|
|
||||||
|
DBusInstancePrivate::~DBusInstancePrivate()
|
||||||
|
{
|
||||||
|
closeDBusDaemon();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,10 @@
|
||||||
namespace DbusHelper {
|
namespace DbusHelper {
|
||||||
void KDECONNECTCORE_EXPORT filterNonExportableCharacters(QString& s);
|
void KDECONNECTCORE_EXPORT filterNonExportableCharacters(QString& s);
|
||||||
|
|
||||||
|
#ifdef USE_PRIVATE_DBUS
|
||||||
|
void KDECONNECTCORE_EXPORT launchDBusDaemon();
|
||||||
|
void KDECONNECTCORE_EXPORT closeDBusDaemon();
|
||||||
|
#endif
|
||||||
QDBusConnection KDECONNECTCORE_EXPORT sessionBus();
|
QDBusConnection KDECONNECTCORE_EXPORT sessionBus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QSslCertificate>
|
#include <QSslCertificate>
|
||||||
#include <QtCrypto>
|
#include <QtCrypto>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
#include "core_debug.h"
|
#include "core_debug.h"
|
||||||
#include "dbushelper.h"
|
#include "dbushelper.h"
|
||||||
|
@ -52,6 +53,9 @@ struct KdeConnectConfigPrivate {
|
||||||
QSettings* m_config;
|
QSettings* m_config;
|
||||||
QSettings* m_trustedDevices;
|
QSettings* m_trustedDevices;
|
||||||
|
|
||||||
|
#ifdef USE_PRIVATE_DBUS
|
||||||
|
QString m_privateDBusAddress; // Private DBus Address cache
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
KdeConnectConfig* KdeConnectConfig::instance()
|
KdeConnectConfig* KdeConnectConfig::instance()
|
||||||
|
@ -327,3 +331,47 @@ void KdeConnectConfig::generateCertificate(const QString& certPath)
|
||||||
Daemon::instance()->reportError(QStringLiteral("KDE Connect"), i18n("Could not store certificate file: %1", certPath));
|
Daemon::instance()->reportError(QStringLiteral("KDE Connect"), i18n("Could not store certificate file: %1", certPath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_PRIVATE_DBUS
|
||||||
|
QString KdeConnectConfig::privateDBusAddressPath()
|
||||||
|
{
|
||||||
|
return baseConfigDir().absoluteFilePath(QStringLiteral("private_dbus_address"));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString KdeConnectConfig::privateDBusAddress()
|
||||||
|
{
|
||||||
|
if (d->m_privateDBusAddress.length() != 0) return d->m_privateDBusAddress;
|
||||||
|
|
||||||
|
QString dbusAddressPath = privateDBusAddressPath();
|
||||||
|
QFile dbusAddressFile(dbusAddressPath);
|
||||||
|
|
||||||
|
if (!dbusAddressFile.open(QFile::ReadOnly | QFile::Text)) {
|
||||||
|
qCCritical(KDECONNECT_CORE) << "Private DBus enabled but error read private dbus address conf";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
QTextStream in(&dbusAddressFile);
|
||||||
|
|
||||||
|
qCDebug(KDECONNECT_CORE) << "Waiting for private dbus";
|
||||||
|
|
||||||
|
int retry = 0;
|
||||||
|
QString addr = in.readLine();
|
||||||
|
while(addr.length() == 0 && retry < 5) {
|
||||||
|
qCDebug(KDECONNECT_CORE) << "Retry reading private DBus address after 3s";
|
||||||
|
QThread::sleep(3);
|
||||||
|
retry ++;
|
||||||
|
addr = in.readLine(); // Read until first not empty line
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr.length() == 0) {
|
||||||
|
qCCritical(KDECONNECT_CORE) << "Private DBus enabled but read private dbus address failed";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(KDECONNECT_CORE) << "Private dbus address: " << addr;
|
||||||
|
|
||||||
|
d->m_privateDBusAddress = addr;
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -70,6 +70,13 @@ public:
|
||||||
QDir deviceConfigDir(const QString& deviceId);
|
QDir deviceConfigDir(const QString& deviceId);
|
||||||
QDir pluginConfigDir(const QString& deviceId, const QString& pluginName); //Used by KdeConnectPluginConfig
|
QDir pluginConfigDir(const QString& deviceId, const QString& pluginName); //Used by KdeConnectPluginConfig
|
||||||
|
|
||||||
|
#ifdef USE_PRIVATE_DBUS
|
||||||
|
/*
|
||||||
|
* Get private DBus Address when use private DBus
|
||||||
|
*/
|
||||||
|
QString privateDBusAddressPath();
|
||||||
|
QString privateDBusAddress();
|
||||||
|
#endif
|
||||||
private:
|
private:
|
||||||
KdeConnectConfig();
|
KdeConnectConfig();
|
||||||
|
|
||||||
|
|
|
@ -111,6 +111,10 @@ int main(int argc, char* argv[])
|
||||||
KAboutData::setApplicationData(aboutData);
|
KAboutData::setApplicationData(aboutData);
|
||||||
app.setQuitOnLastWindowClosed(false);
|
app.setQuitOnLastWindowClosed(false);
|
||||||
|
|
||||||
|
#ifdef USE_PRIVATE_DBUS
|
||||||
|
DbusHelper::launchDBusDaemon();
|
||||||
|
#endif
|
||||||
|
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
QCommandLineOption replaceOption({QStringLiteral("replace")}, i18n("Replace an existing instance"));
|
QCommandLineOption replaceOption({QStringLiteral("replace")}, i18n("Replace an existing instance"));
|
||||||
parser.addOption(replaceOption);
|
parser.addOption(replaceOption);
|
||||||
|
@ -126,7 +130,7 @@ int main(int argc, char* argv[])
|
||||||
DbusHelper::sessionBus().call(message); //deliberately block until it's done, so we register the name after the app quits
|
DbusHelper::sessionBus().call(message); //deliberately block until it's done, so we register the name after the app quits
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef Q_OS_MAC
|
#ifndef USE_PRIVATE_DBUS
|
||||||
KDBusService dbusService(KDBusService::Unique);
|
KDBusService dbusService(KDBusService::Unique);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ int main(int argc, char** argv)
|
||||||
kdeconnectdProcess.start(basePath + QStringLiteral("Contents/MacOS/kdeconnectd")); // Start kdeconnectd
|
kdeconnectdProcess.start(basePath + QStringLiteral("Contents/MacOS/kdeconnectd")); // Start kdeconnectd
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef Q_OS_MAC
|
#ifndef USE_PRIVATE_DBUS
|
||||||
KDBusService dbusService(KDBusService::Unique);
|
KDBusService dbusService(KDBusService::Unique);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -41,3 +41,6 @@ ecm_add_test(testnotificationlistener.cpp
|
||||||
if(SMSAPP_ENABLED)
|
if(SMSAPP_ENABLED)
|
||||||
ecm_add_test(testsmshelper.cpp LINK_LIBRARIES ${kdeconnect_sms_libraries})
|
ecm_add_test(testsmshelper.cpp LINK_LIBRARIES ${kdeconnect_sms_libraries})
|
||||||
endif()
|
endif()
|
||||||
|
if(PRIVATE_DBUS_ENABLED)
|
||||||
|
ecm_add_test(testprivatedbus.cpp LINK_LIBRARIES ${kdeconnect_libraries})
|
||||||
|
endif()
|
||||||
|
|
109
tests/testprivatedbus.cpp
Normal file
109
tests/testprivatedbus.cpp
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2019 Weixuan XIAO <veyx.shaw@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of
|
||||||
|
* the License or (at your option) version 3 or any later version
|
||||||
|
* accepted by the membership of KDE e.V. (or its successor approved
|
||||||
|
* by the membership of KDE e.V.), which shall act as a proxy
|
||||||
|
* defined in Section 14 of version 3 of the license.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dbushelper.h"
|
||||||
|
|
||||||
|
#include <QtTest>
|
||||||
|
#include <QDBusMessage>
|
||||||
|
#include <QDBusConnectionInterface>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class tests the working of private dbus in kdeconnect
|
||||||
|
*/
|
||||||
|
class PrivateDBusTest : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
PrivateDBusTest()
|
||||||
|
{
|
||||||
|
DbusHelper::launchDBusDaemon();
|
||||||
|
}
|
||||||
|
|
||||||
|
~PrivateDBusTest()
|
||||||
|
{
|
||||||
|
DbusHelper::closeDBusDaemon();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void testConnectionWithPrivateDBus();
|
||||||
|
void testServiceRegistrationWithPrivateDBus();
|
||||||
|
void testMethodCallWithPrivateDBus();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open private DBus normally and get connection info
|
||||||
|
*/
|
||||||
|
void PrivateDBusTest::testConnectionWithPrivateDBus()
|
||||||
|
{
|
||||||
|
QDBusConnection conn = DbusHelper::sessionBus();
|
||||||
|
|
||||||
|
QVERIFY2(conn.isConnected(), "Connection not established");
|
||||||
|
QVERIFY2(conn.name() == QStringLiteral(KDECONNECT_PRIVATE_DBUS_NAME),
|
||||||
|
"DBus Connection is not the right one");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open private DBus connection normally and register a service
|
||||||
|
*/
|
||||||
|
void PrivateDBusTest::testServiceRegistrationWithPrivateDBus()
|
||||||
|
{
|
||||||
|
QDBusConnection conn = DbusHelper::sessionBus();
|
||||||
|
QVERIFY2(conn.isConnected(), "DBus not connected");
|
||||||
|
|
||||||
|
QDBusConnectionInterface *bus = conn.interface();
|
||||||
|
QVERIFY2(bus != nullptr, "Failed to get DBus interface");
|
||||||
|
|
||||||
|
QVERIFY2(bus->registerService(QStringLiteral("privatedbus.test")) == QDBusConnectionInterface::ServiceRegistered,
|
||||||
|
"Failed to register DBus Serice");
|
||||||
|
|
||||||
|
bus->unregisterService(QStringLiteral("privatedbus.test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open private DBus connection normally, call a method and get its reply
|
||||||
|
*/
|
||||||
|
void PrivateDBusTest::testMethodCallWithPrivateDBus()
|
||||||
|
{
|
||||||
|
QDBusConnection conn = DbusHelper::sessionBus();
|
||||||
|
QVERIFY2(conn.isConnected(), "DBus not connected");
|
||||||
|
|
||||||
|
/*
|
||||||
|
dbus-send --session \
|
||||||
|
--dest=org.freedesktop.DBus \
|
||||||
|
--type=method_call \
|
||||||
|
--print-reply \
|
||||||
|
/org/freedesktop/DBus \
|
||||||
|
org.freedesktop.DBus.ListNames
|
||||||
|
*/
|
||||||
|
QDBusMessage msg = conn.call(
|
||||||
|
QDBusMessage::createMethodCall(
|
||||||
|
QStringLiteral("org.freedesktop.DBus"), // Service
|
||||||
|
QStringLiteral("/org/freedesktop/DBus"), // Path
|
||||||
|
QStringLiteral("org.freedesktop.DBus"), // Interface
|
||||||
|
QStringLiteral("ListNames") // Method
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
QVERIFY2(msg.type() == QDBusMessage::ReplyMessage, "Failed calling method on private DBus");
|
||||||
|
}
|
||||||
|
|
||||||
|
QTEST_MAIN(PrivateDBusTest);
|
||||||
|
#include "testprivatedbus.moc"
|
Loading…
Reference in a new issue