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
|
||||
)
|
||||
|
||||
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)
|
||||
if(NOT SAILFISHOS)
|
||||
add_subdirectory(kcm)
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
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)
|
||||
configure_file(dbushelper.h.in ${CMAKE_CURRENT_BINARY_DIR}/dbushelper.h)
|
||||
|
||||
|
|
|
@ -19,9 +19,39 @@
|
|||
*/
|
||||
|
||||
#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 {
|
||||
|
||||
#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)
|
||||
{
|
||||
static QRegExp regexp(QStringLiteral("[^A-Za-z0-9_]"), Qt::CaseSensitive, QRegExp::Wildcard);
|
||||
|
@ -30,11 +60,88 @@ void filterNonExportableCharacters(QString& s)
|
|||
|
||||
QDBusConnection sessionBus()
|
||||
{
|
||||
#ifdef Q_OS_MAC
|
||||
return QDBusConnection::connectToBus(QStringLiteral(KDECONNECT_PRIVATE_DBUS_ADDR), QStringLiteral(KDECONNECT_PRIVATE_DBUS_NAME));
|
||||
#ifdef USE_PRIVATE_DBUS
|
||||
return QDBusConnection::connectToBus(KdeConnectConfig::instance()->privateDBusAddress(),
|
||||
QStringLiteral(KDECONNECT_PRIVATE_DBUS_NAME));
|
||||
#else
|
||||
return QDBusConnection::sessionBus();
|
||||
#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 {
|
||||
void KDECONNECTCORE_EXPORT filterNonExportableCharacters(QString& s);
|
||||
|
||||
#ifdef USE_PRIVATE_DBUS
|
||||
void KDECONNECTCORE_EXPORT launchDBusDaemon();
|
||||
void KDECONNECTCORE_EXPORT closeDBusDaemon();
|
||||
#endif
|
||||
QDBusConnection KDECONNECTCORE_EXPORT sessionBus();
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <QSettings>
|
||||
#include <QSslCertificate>
|
||||
#include <QtCrypto>
|
||||
#include <QThread>
|
||||
|
||||
#include "core_debug.h"
|
||||
#include "dbushelper.h"
|
||||
|
@ -52,6 +53,9 @@ struct KdeConnectConfigPrivate {
|
|||
QSettings* m_config;
|
||||
QSettings* m_trustedDevices;
|
||||
|
||||
#ifdef USE_PRIVATE_DBUS
|
||||
QString m_privateDBusAddress; // Private DBus Address cache
|
||||
#endif
|
||||
};
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
#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 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:
|
||||
KdeConnectConfig();
|
||||
|
||||
|
|
|
@ -111,6 +111,10 @@ int main(int argc, char* argv[])
|
|||
KAboutData::setApplicationData(aboutData);
|
||||
app.setQuitOnLastWindowClosed(false);
|
||||
|
||||
#ifdef USE_PRIVATE_DBUS
|
||||
DbusHelper::launchDBusDaemon();
|
||||
#endif
|
||||
|
||||
QCommandLineParser parser;
|
||||
QCommandLineOption replaceOption({QStringLiteral("replace")}, i18n("Replace an existing instance"));
|
||||
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
|
||||
}
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
#ifndef USE_PRIVATE_DBUS
|
||||
KDBusService dbusService(KDBusService::Unique);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ int main(int argc, char** argv)
|
|||
kdeconnectdProcess.start(basePath + QStringLiteral("Contents/MacOS/kdeconnectd")); // Start kdeconnectd
|
||||
#endif
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
#ifndef USE_PRIVATE_DBUS
|
||||
KDBusService dbusService(KDBusService::Unique);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -41,3 +41,6 @@ ecm_add_test(testnotificationlistener.cpp
|
|||
if(SMSAPP_ENABLED)
|
||||
ecm_add_test(testsmshelper.cpp LINK_LIBRARIES ${kdeconnect_sms_libraries})
|
||||
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