From 792c1c94f7f0569af0682b3e73248c5c0c52d3e9 Mon Sep 17 00:00:00 2001 From: Aetf Date: Sun, 1 Dec 2019 21:13:07 -0500 Subject: [PATCH] FdoSecrets: check and show PID and executable for existing secret service process --- src/fdosecrets/FdoSecretsPlugin.cpp | 30 ++++++++++- src/fdosecrets/FdoSecretsPlugin.h | 6 +++ src/fdosecrets/objects/Service.cpp | 5 +- .../widgets/SettingsWidgetFdoSecrets.cpp | 54 +++++++++++++++++++ .../widgets/SettingsWidgetFdoSecrets.h | 12 +++++ .../widgets/SettingsWidgetFdoSecrets.ui | 10 +++- 6 files changed, 112 insertions(+), 5 deletions(-) diff --git a/src/fdosecrets/FdoSecretsPlugin.cpp b/src/fdosecrets/FdoSecretsPlugin.cpp index 646f85301..6c77e5dc6 100644 --- a/src/fdosecrets/FdoSecretsPlugin.cpp +++ b/src/fdosecrets/FdoSecretsPlugin.cpp @@ -24,6 +24,8 @@ #include "gui/DatabaseTabWidget.h" +#include + #include using FdoSecrets::Service; @@ -56,7 +58,7 @@ void FdoSecretsPlugin::updateServiceState() if (!m_secretService && m_dbTabs) { m_secretService.reset(new Service(this, m_dbTabs)); connect(m_secretService.data(), &Service::error, this, [this](const QString& msg) { - emit error(tr("Fdo Secret Service: %1").arg(msg)); + emit error(tr("Fdo Secret Service: %1").arg(msg)); }); if (!m_secretService->initialize()) { m_secretService.reset(); @@ -95,3 +97,29 @@ void FdoSecretsPlugin::emitRequestShowNotification(const QString& msg, const QSt } emit requestShowNotification(msg, title, 10000); } + +QString FdoSecretsPlugin::reportExistingService() const +{ + auto pidStr = tr("Unknown", "Unknown PID"); + auto exeStr = tr("Unknown", "Unknown executable path"); + + // try get pid + auto pid = QDBusConnection::sessionBus().interface()->servicePid(DBUS_SERVICE_SECRET); + if (pid.isValid()) { + pidStr = QString::number(pid.value()); + + // try get the first part of the cmdline, which usually is the executable name/path + QFile proc(QStringLiteral("/proc/%1/cmdline").arg(pid.value())); + if (proc.open(QFile::ReadOnly)) { + auto parts = proc.readAll().split('\0'); + if (parts.length() >= 1) { + exeStr = QString::fromLocal8Bit(parts[0]).trimmed(); + } + } + } + auto otherService = tr("PID: %1, Executable: %2", "PID: 1234, Executable: /path/to/exe") + .arg(pidStr, exeStr.toHtmlEscaped()); + return tr("Another secret service is running (%1).
" + "Please stop/remove it before re-enabling the Secret Service Integration.") + .arg(otherService); +} diff --git a/src/fdosecrets/FdoSecretsPlugin.h b/src/fdosecrets/FdoSecretsPlugin.h index 828c0bd76..4f284f469 100644 --- a/src/fdosecrets/FdoSecretsPlugin.h +++ b/src/fdosecrets/FdoSecretsPlugin.h @@ -64,6 +64,12 @@ public: */ DatabaseTabWidget* dbTabs() const; + /** + * Check the running secret service and returns info about it + * @return html string suitable to be shown in the UI + */ + QString reportExistingService() const; + public slots: void emitRequestSwitchToDatabases(); void emitRequestShowNotification(const QString& msg, const QString& title = {}); diff --git a/src/fdosecrets/objects/Service.cpp b/src/fdosecrets/objects/Service.cpp index 5408f4cb2..59f086107 100644 --- a/src/fdosecrets/objects/Service.cpp +++ b/src/fdosecrets/objects/Service.cpp @@ -59,9 +59,8 @@ namespace FdoSecrets bool Service::initialize() { if (!QDBusConnection::sessionBus().registerService(QStringLiteral(DBUS_SERVICE_SECRET))) { - qDebug() << "Another secret service is running"; - emit error(tr("Failed to register DBus service at %1: another secret service is running.") - .arg(QLatin1Literal(DBUS_SERVICE_SECRET))); + emit error(tr("Failed to register DBus service at %1.
").arg(QLatin1String(DBUS_SERVICE_SECRET)) + + m_plugin->reportExistingService()); return false; } diff --git a/src/fdosecrets/widgets/SettingsWidgetFdoSecrets.cpp b/src/fdosecrets/widgets/SettingsWidgetFdoSecrets.cpp index 5ae267a12..29b01c67b 100644 --- a/src/fdosecrets/widgets/SettingsWidgetFdoSecrets.cpp +++ b/src/fdosecrets/widgets/SettingsWidgetFdoSecrets.cpp @@ -27,6 +27,8 @@ #include "gui/DatabaseWidget.h" #include +#include +#include #include #include #include @@ -236,6 +238,8 @@ SettingsWidgetFdoSecrets::SettingsWidgetFdoSecrets(FdoSecretsPlugin* plugin, QWi , m_plugin(plugin) { m_ui->setupUi(this); + m_ui->warningMsg->setHidden(true); + m_ui->warningMsg->setCloseButtonVisible(false); auto sessModel = new SettingsSessionModel(plugin, this); m_ui->tableSessions->setModel(sessModel); @@ -262,6 +266,12 @@ SettingsWidgetFdoSecrets::SettingsWidgetFdoSecrets(FdoSecretsPlugin* plugin, QWi m_ui->tabWidget->setEnabled(m_ui->enableFdoSecretService->isChecked()); connect(m_ui->enableFdoSecretService, &QCheckBox::toggled, m_ui->tabWidget, &QTabWidget::setEnabled); + + // background checking + m_checkTimer.setInterval(2000); + connect(&m_checkTimer, &QTimer::timeout, this, &SettingsWidgetFdoSecrets::checkDBusName); + connect(m_plugin, &FdoSecretsPlugin::secretServiceStarted, &m_checkTimer, &QTimer::stop); + connect(m_plugin, SIGNAL(secretServiceStopped()), &m_checkTimer, SLOT(start())); } void SettingsWidgetFdoSecrets::setupView(QAbstractItemView* view, @@ -300,4 +310,48 @@ void SettingsWidgetFdoSecrets::saveSettings() FdoSecrets::settings()->setNoConfirmDeleteItem(m_ui->noConfirmDeleteItem->isChecked()); } +void SettingsWidgetFdoSecrets::showMessage(const QString& text, MessageWidget::MessageType type) +{ + // Show error messages for a longer time to make sure the user can read them + if (type == MessageWidget::Error) { + m_ui->warningMsg->setCloseButtonVisible(true); + m_ui->warningMsg->showMessage(text, type, -1); + } else { + m_ui->warningMsg->setCloseButtonVisible(false); + m_ui->warningMsg->showMessage(text, type, 2000); + } +} + +void SettingsWidgetFdoSecrets::showEvent(QShowEvent* event) +{ + QWidget::showEvent(event); + QTimer::singleShot(0, this, &SettingsWidgetFdoSecrets::checkDBusName); + m_checkTimer.start(); +} + +void SettingsWidgetFdoSecrets::hideEvent(QHideEvent* event) +{ + QWidget::hideEvent(event); + m_checkTimer.stop(); +} + +void SettingsWidgetFdoSecrets::checkDBusName() +{ + if (m_plugin->serviceInstance()) { + // only need checking if the service is not started or failed to start. + return; + } + + auto reply = QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral(DBUS_SERVICE_SECRET)); + if (!reply.isValid()) { + showMessage(tr("Error: Failed to connect to DBus. Please check your DBus setup."), MessageWidget::Error); + return; + } + if (reply.value()) { + showMessage(tr("Warning: ") + m_plugin->reportExistingService(), MessageWidget::Warning); + return; + } + m_ui->warningMsg->hideMessage(); +} + #include "SettingsWidgetFdoSecrets.moc" diff --git a/src/fdosecrets/widgets/SettingsWidgetFdoSecrets.h b/src/fdosecrets/widgets/SettingsWidgetFdoSecrets.h index 2bf58f826..f6147cc24 100644 --- a/src/fdosecrets/widgets/SettingsWidgetFdoSecrets.h +++ b/src/fdosecrets/widgets/SettingsWidgetFdoSecrets.h @@ -18,7 +18,10 @@ #ifndef KEEPASSXC_SETTINGSWIDGETFDOSECRETS_H #define KEEPASSXC_SETTINGSWIDGETFDOSECRETS_H +#include "gui/MessageWidget.h" + #include +#include #include class QAbstractItemView; @@ -50,6 +53,14 @@ public slots: void loadSettings(); void saveSettings(); +private slots: + void checkDBusName(); + void showMessage(const QString& text, MessageWidget::MessageType type); + +protected: + void showEvent(QShowEvent* event) override; + void hideEvent(QHideEvent* event) override; + private: void setupView(QAbstractItemView* view, int manageColumn, int editorTypeId, QItemEditorCreatorBase* creator); @@ -57,6 +68,7 @@ private: QScopedPointer m_ui; QScopedPointer m_factory; FdoSecretsPlugin* m_plugin; + QTimer m_checkTimer; }; #endif // KEEPASSXC_SETTINGSWIDGETFDOSECRETS_H diff --git a/src/fdosecrets/widgets/SettingsWidgetFdoSecrets.ui b/src/fdosecrets/widgets/SettingsWidgetFdoSecrets.ui index cfbeaa210..ee7d49431 100644 --- a/src/fdosecrets/widgets/SettingsWidgetFdoSecrets.ui +++ b/src/fdosecrets/widgets/SettingsWidgetFdoSecrets.ui @@ -15,7 +15,7 @@ - + @@ -132,6 +132,14 @@ + + + MessageWidget + QWidget +
gui/MessageWidget.h
+ 1 +
+