From df2ca7f25f5cac57b1c6d00932b0fe0fc4d449df Mon Sep 17 00:00:00 2001 From: Weixuan Xiao Date: Tue, 9 Jul 2019 19:42:08 +0000 Subject: [PATCH] Private DBus set launchctl env to fake a session bus --- core/dbushelper.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++++ core/dbushelper.h.in | 5 +++++ indicator/main.cpp | 41 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/core/dbushelper.cpp b/core/dbushelper.cpp index 6fe6c958e..b9a16a8d8 100644 --- a/core/dbushelper.cpp +++ b/core/dbushelper.cpp @@ -32,6 +32,8 @@ #ifdef Q_OS_MAC #include +#include +#include #endif namespace DbusHelper { @@ -72,6 +74,7 @@ QDBusConnection sessionBus() void launchDBusDaemon() { dbusInstance.launchDBusDaemon(); + qAddPostRoutine(closeDBusDaemon); } void closeDBusDaemon() @@ -79,6 +82,21 @@ void closeDBusDaemon() dbusInstance.closeDBusDaemon(); } +#ifdef Q_OS_MAC +void macosUnsetLaunchctlEnv() +{ + // Unset Launchd env + QProcess unsetLaunchdDBusEnv; + unsetLaunchdDBusEnv.setProgram(QStringLiteral("launchctl")); + unsetLaunchdDBusEnv.setArguments({ + QStringLiteral("unsetenv"), + QStringLiteral(KDECONNECT_SESSION_DBUS_LAUNCHD_ENV) + }); + unsetLaunchdDBusEnv.start(); + unsetLaunchdDBusEnv.waitForFinished(); +} +#endif + void DBusInstancePrivate::launchDBusDaemon() { // Kill old dbus daemon @@ -118,6 +136,28 @@ void DBusInstancePrivate::launchDBusDaemon() m_dbusProcess->setStandardOutputFile(KdeConnectConfig::instance()->privateDBusAddressPath()); m_dbusProcess->setStandardErrorFile(QProcess::nullDevice()); m_dbusProcess->start(); + +#ifdef Q_OS_MAC + // Set launchctl env + QString privateDBusAddress = KdeConnectConfig::instance()->privateDBusAddress(); + QRegularExpressionMatch path; + if (privateDBusAddress.contains(QRegularExpression( + QStringLiteral("path=(?/tmp/dbus-[A-Za-z0-9]+)") + ), &path)) { + qCDebug(KDECONNECT_CORE) << "DBus address: " << path.captured(QStringLiteral("path")); + QProcess setLaunchdDBusEnv; + setLaunchdDBusEnv.setProgram(QStringLiteral("launchctl")); + setLaunchdDBusEnv.setArguments({ + QStringLiteral("setenv"), + QStringLiteral(KDECONNECT_SESSION_DBUS_LAUNCHD_ENV), + path.captured(QStringLiteral("path")) + }); + setLaunchdDBusEnv.start(); + setLaunchdDBusEnv.waitForFinished(); + } else { + qCDebug(KDECONNECT_CORE) << "Cannot get dbus address"; + } +#endif } void DBusInstancePrivate::closeDBusDaemon() @@ -132,6 +172,10 @@ void DBusInstancePrivate::closeDBusDaemon() QFile privateDBusAddressFile(KdeConnectConfig::instance()->privateDBusAddressPath()); if (privateDBusAddressFile.exists()) privateDBusAddressFile.resize(0); + +#ifdef Q_OS_MAC + macosUnsetLaunchctlEnv(); +#endif } } diff --git a/core/dbushelper.h.in b/core/dbushelper.h.in index ae0701768..afcf392b2 100644 --- a/core/dbushelper.h.in +++ b/core/dbushelper.h.in @@ -28,6 +28,8 @@ #define KDECONNECT_PRIVATE_DBUS_ADDR "${KDECONNECT_PRIVATE_DBUS_ADDR}" #define KDECONNECT_PRIVATE_DBUS_NAME "${KDECONNECT_PRIVATE_DBUS_NAME}" +#define KDECONNECT_SESSION_DBUS_LAUNCHD_ENV "DBUS_LAUNCHD_SESSION_BUS_SOCKET" + namespace DbusHelper { void KDECONNECTCORE_EXPORT filterNonExportableCharacters(QString& s); @@ -36,6 +38,9 @@ namespace DbusHelper { void KDECONNECTCORE_EXPORT closeDBusDaemon(); #endif QDBusConnection KDECONNECTCORE_EXPORT sessionBus(); +#ifdef Q_OS_MAC + void KDECONNECTCORE_EXPORT macosUnsetLaunchctlEnv(); +#endif } #endif diff --git a/indicator/main.cpp b/indicator/main.cpp index 3ef31c829..c9bb94ced 100644 --- a/indicator/main.cpp +++ b/indicator/main.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #ifdef QSYSTRAY #include @@ -61,13 +62,49 @@ int main(int argc, char** argv) #endif #ifdef Q_OS_MAC + // Unset launchctl env, avoid block + DbusHelper::macosUnsetLaunchctlEnv(); + // Get bundle path CFURLRef url = (CFURLRef)CFAutorelease((CFURLRef)CFBundleCopyBundleURL(CFBundleGetMainBundle())); QString basePath = QUrl::fromCFURL(url).path(); + // Start kdeconnectd QProcess kdeconnectdProcess; - kdeconnectdProcess.start(basePath + QStringLiteral("Contents/MacOS/kdeconnectd")); // Start kdeconnectd - QThread::sleep(5); // Wait for kdeconnectd and its dbus-daemon + kdeconnectdProcess.start(basePath + QStringLiteral("Contents/MacOS/kdeconnectd")); + + // Wait for dbus daemon env + QProcess getLaunchdDBusEnv; + int retry = 0; + do { + getLaunchdDBusEnv.setProgram(QStringLiteral("launchctl")); + getLaunchdDBusEnv.setArguments({ + QStringLiteral("getenv"), + QStringLiteral(KDECONNECT_SESSION_DBUS_LAUNCHD_ENV) + }); + getLaunchdDBusEnv.start(); + getLaunchdDBusEnv.waitForFinished(); + + QString launchdDBusEnv = QString::fromLocal8Bit(getLaunchdDBusEnv.readAllStandardOutput()); + + if (launchdDBusEnv.length() > 0) { + break; + } else if (retry >= 10) { + // Show a warning and exit + qCritical() << "Fail to get launchctl" << KDECONNECT_SESSION_DBUS_LAUNCHD_ENV << "env"; + + QMessageBox::critical(nullptr, i18n("KDE Connect"), + i18n("Cannot connect to DBus\n" + "KDE Connect will quit"), + QMessageBox::Abort, + QMessageBox::Abort); + + return -1; + } else { + QThread::sleep(1); // Retry after 1s + retry++; + } + } while(true); #endif #ifndef USE_PRIVATE_DBUS