Skip to content

Commit ed93abb

Browse files
committed
fix: prevent polkit popup when session is in background
1. Added SessionStateTracker using login1 User.Display to get current session path, then query Session.Active property 2. Guard conn->save() calls in DeviceManagerRealize and DeviceInterRealize with session active check to prevent unnecessary polkit authentication requests when user switches to another session 3. Use leaky singleton pattern for SessionStateTracker to avoid destructor race conditions with static local objects Influence: 1. Test switching between user sessions (e.g. switch to aaa desktop) and verify no polkit popup (settings.modify.system) appears on the background session 2. Verify WiFi connection saving still works correctly when session is in foreground 3. Check that network settings are properly saved when user is actively using the session 4. Test with multiple user sessions and verify no crashes on logout/login fix: 防止会话在后台时弹出polkit弹框 1. 添加SessionStateTracker,通过login1 User.Display获取当前用户主会话 路径,查询Session.Active属性判断会话状态 2. 在DeviceManagerRealize和DeviceInterRealize中用会话活跃状态守护 conn->save()调用,防止用户切换到其他会话时触发不必要的polkit认证请求 3. 使用leaky singleton模式避免静态局部对象析构竞态问题 Influence: 1. 测试在用户会话间切换(如切换到aaa桌面)时,后台会话不会弹出polkit弹框 2. 验证会话在前台时WiFi连接保存功能正常 3. 检查用户活跃使用会话时网络设置能正确保存 4. 测试多用户会话场景,验证注销/登录时无崩溃 PMS: BUG-363065
1 parent 69065b5 commit ed93abb

4 files changed

Lines changed: 171 additions & 19 deletions

File tree

src/impl/networkmanager/devicemanagerrealize.cpp

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "configsetting.h"
1111
#include "ipmanager.h"
1212
#include "nmnetworkmanager.h"
13+
#include "sessionstatetracker.h"
1314

1415
#include <networkmanagerqt/wirelessdevice.h>
1516
#include <networkmanagerqt/wireddevice.h>
@@ -846,12 +847,14 @@ void WirelessDeviceManagerRealize::connectNetwork(const AccessPoints *accessPoin
846847
wsSetting->setInitialized(keyMgmt != NetworkManager::WirelessSecuritySetting::KeyMgmt::WpaNone && keyMgmt != NetworkManager::WirelessSecuritySetting::KeyMgmt::Unknown);
847848
NMVariantMapMap settingMap = currentConnection->settings()->toMap();
848849
qCDebug(DNC) << "securit changed..." << settingMap;
849-
if (currentConnection->isUnsaved()) {
850-
currentConnection->updateUnsaved(settingMap);
851-
} else {
852-
currentConnection->update(settingMap);
853-
QDBusPendingReply<> reply = currentConnection->save();
854-
reply.waitForFinished();
850+
if (SessionStateTracker::instance()->isSessionActive()) {
851+
if (currentConnection->isUnsaved()) {
852+
currentConnection->updateUnsaved(settingMap);
853+
} else {
854+
currentConnection->update(settingMap);
855+
QDBusPendingReply<> reply = currentConnection->save();
856+
reply.waitForFinished();
857+
}
855858
}
856859
}
857860
QVariantMap options;
@@ -1009,14 +1012,16 @@ void WirelessDeviceManagerRealize::onActiveConnectionChanged()
10091012
if (activeAp && conn) {
10101013
conn->settings()->setTimestamp(QDateTime::currentDateTime());
10111014
if (state == NetworkManager::ActiveConnection::Activated && conn->isUnsaved()) {
1012-
const NetworkManager::Setting::SettingType settingType[] = { NetworkManager::Setting::Security8021x, NetworkManager::Setting::WirelessSecurity };
1013-
for (auto type : settingType) {
1014-
NetworkManager::Setting::Ptr setting = conn->settings()->setting(type);
1015-
if (setting) {
1016-
conn->secrets(setting->name());
1015+
if (SessionStateTracker::instance()->isSessionActive()) {
1016+
const NetworkManager::Setting::SettingType settingType[] = { NetworkManager::Setting::Security8021x, NetworkManager::Setting::WirelessSecurity };
1017+
for (auto type : settingType) {
1018+
NetworkManager::Setting::Ptr setting = conn->settings()->setting(type);
1019+
if (setting) {
1020+
conn->secrets(setting->name());
1021+
}
10171022
}
1023+
conn->save();
10181024
}
1019-
conn->save();
10201025
connect(conn.data(), &NetworkManager::Connection::unsavedChanged, this, [this] {
10211026
Q_EMIT activeConnectionChanged();
10221027
});

src/impl/networkmanager/networkmanagerprocesser.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "hotspotcontrollernm.h"
88
#include "networkdevicebase.h"
99
#include "networkmanagerprocesser.h"
10+
#include "sessionstatetracker.h"
1011
#include "proxycontrollernm.h"
1112
#include "vpncontrollernm.h"
1213
#include "networkdetails.h"
@@ -80,6 +81,13 @@ void NetworkManagerProcesser::initConnections()
8081
connect(NetworkManager::notifier(), &NetworkManager::Notifier::activeConnectionsChanged, this, &NetworkManagerProcesser::onUpdateNetworkDetail);
8182
// 当网络状态发生变化时,也刷新Detail
8283
connect(NetworkManager::notifier(), &NetworkManager::Notifier::statusChanged, this, &NetworkManagerProcesser::onUpdateNetworkDetail);
84+
// 会话从后台切回前台时,本地用户主动刷新网络状态
85+
connect(SessionStateTracker::instance(), &SessionStateTracker::sessionResumed, this, [this] {
86+
if (SessionStateTracker::instance()->isLocalUser()) {
87+
qCDebug(DNC) << "session resumed, refreshing network state";
88+
onUpdateNetworkDetail();
89+
}
90+
});
8391
}
8492

8593
void NetworkManagerProcesser::onDevicesChanged(const QList<QDBusObjectPath> &devices)
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
2+
//
3+
// SPDX-License-Identifier: GPL-3.0-or-later
4+
#ifndef SESSIONSTATETRACKER_H
5+
#define SESSIONSTATETRACKER_H
6+
7+
#include <QDBusConnection>
8+
#include <QDBusInterface>
9+
#include <QDBusMessage>
10+
#include <QDBusPendingCallWatcher>
11+
#include <QDBusPendingReply>
12+
#include <QDBusObjectPath>
13+
#include <QDBusReply>
14+
#include <QDBusVariant>
15+
#include <QDebug>
16+
#include <QObject>
17+
#include <QVariantMap>
18+
19+
class SessionStateTracker : public QObject {
20+
Q_OBJECT
21+
public:
22+
static SessionStateTracker *instance() {
23+
static SessionStateTracker *s_instance = new SessionStateTracker();
24+
return s_instance;
25+
}
26+
27+
bool isSessionActive() const {
28+
return m_userActive;
29+
}
30+
31+
bool isLocalUser() const {
32+
return m_isLocal;
33+
}
34+
35+
private:
36+
SessionStateTracker()
37+
: QObject(nullptr)
38+
, m_userActive(true)
39+
, m_isLocal(false)
40+
{
41+
// Step 1: 异步获取 User.Display(session 路径)
42+
QDBusMessage msg = QDBusMessage::createMethodCall(
43+
"org.freedesktop.login1",
44+
"/org/freedesktop/login1/user/self",
45+
"org.freedesktop.DBus.Properties",
46+
"Get"
47+
);
48+
msg << "org.freedesktop.login1.User" << "Display";
49+
QDBusConnection::systemBus().callWithCallback(msg, this, SLOT(onDisplayReady(QDBusVariant)));
50+
}
51+
52+
~SessionStateTracker() = default;
53+
SessionStateTracker(const SessionStateTracker &) = delete;
54+
SessionStateTracker &operator=(const SessionStateTracker &) = delete;
55+
56+
private slots:
57+
void onDisplayReady(const QDBusVariant &display) {
58+
const QDBusArgument arg = display.variant().value<QDBusArgument>();
59+
QString id;
60+
QDBusObjectPath path;
61+
arg.beginStructure();
62+
arg >> id >> path;
63+
arg.endStructure();
64+
65+
if (path.path().isEmpty()) {
66+
qWarning() << "[SessionStateTracker] Display empty, keep default active";
67+
return;
68+
}
69+
70+
// Step 2: 检查 Remote 属性
71+
QDBusMessage remoteMsg = QDBusMessage::createMethodCall(
72+
"org.freedesktop.login1",
73+
path.path(),
74+
"org.freedesktop.DBus.Properties",
75+
"Get"
76+
);
77+
remoteMsg << "org.freedesktop.login1.Session" << "Remote";
78+
QDBusPendingReply<QDBusVariant> remoteReply = QDBusConnection::systemBus().asyncCall(remoteMsg);
79+
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(remoteReply, this);
80+
connect(watcher, &QDBusPendingCallWatcher::finished, this, [path, this](QDBusPendingCallWatcher *self) {
81+
QDBusPendingReply<QDBusVariant> reply = *self;
82+
bool remote = !reply.isError() && reply.value().variant().toBool();
83+
if (!remote) {
84+
m_isLocal = true;
85+
// Step 3: 监听 Active 变化
86+
QDBusConnection::systemBus().connect(
87+
"org.freedesktop.login1",
88+
path.path(),
89+
"org.freedesktop.DBus.Properties",
90+
"PropertiesChanged",
91+
this,
92+
SLOT(onSessionPropertiesChanged(QString, QVariantMap, QStringList))
93+
);
94+
// 同时读一次初始 Active 状态
95+
QDBusMessage activeMsg = QDBusMessage::createMethodCall(
96+
"org.freedesktop.login1",
97+
path.path(),
98+
"org.freedesktop.DBus.Properties",
99+
"Get"
100+
);
101+
activeMsg << "org.freedesktop.login1.Session" << "Active";
102+
QDBusPendingReply<QDBusVariant> activeReply = QDBusConnection::systemBus().asyncCall(activeMsg);
103+
QDBusPendingCallWatcher *activeWatcher = new QDBusPendingCallWatcher(activeReply, this);
104+
connect(activeWatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *sw) {
105+
QDBusPendingReply<QDBusVariant> sr = *sw;
106+
if (!sr.isError()) {
107+
m_userActive = sr.value().variant().toBool();
108+
}
109+
sw->deleteLater();
110+
});
111+
}
112+
self->deleteLater();
113+
});
114+
}
115+
116+
void onSessionPropertiesChanged(const QString &interface, const QVariantMap &properties, const QStringList &) {
117+
if (interface == "org.freedesktop.login1.Session" && properties.contains("Active")) {
118+
m_userActive = properties.value("Active").toBool();
119+
if (m_userActive) {
120+
qWarning() << "[SessionStateTracker] session resumed";
121+
Q_EMIT sessionResumed();
122+
} else {
123+
qWarning() << "[SessionStateTracker] session left";
124+
}
125+
}
126+
}
127+
128+
signals:
129+
void sessionResumed();
130+
131+
private:
132+
bool m_userActive;
133+
bool m_isLocal;
134+
};
135+
136+
#endif // SESSIONSTATETRACKER_H

src/impl/serviceinter/deviceinterrealize.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2018-2026 UnionTech Software Technology Co., Ltd.
22
//
33
// SPDX-License-Identifier: GPL-3.0-or-later
44

@@ -7,6 +7,7 @@
77
#include "wireddevice.h"
88
#include "wirelessdevice.h"
99
#include "accesspointsproxyinter.h"
10+
#include "../networkmanager/sessionstatetracker.h"
1011

1112
#include <QHostAddress>
1213

@@ -366,14 +367,16 @@ void DeviceInterRealize::onActiveConnectionChanged()
366367
connect(activeConnection.data(), &NetworkManager::ActiveConnection::stateChanged, this, [ activeConnection, this ](NetworkManager::ActiveConnection::State state) {
367368
if (state == NetworkManager::ActiveConnection::State::Activated) {
368369
NetworkManager::Connection::Ptr conn = activeConnection->connection();
369-
const NetworkManager::Setting::SettingType settingType[] = { NetworkManager::Setting::Security8021x, NetworkManager::Setting::WirelessSecurity };
370-
for (auto type : settingType) {
371-
NetworkManager::Setting::Ptr setting = conn->settings()->setting(type);
372-
if (setting) {
373-
conn->secrets(setting->name());
370+
if (SessionStateTracker::instance()->isSessionActive()) {
371+
const NetworkManager::Setting::SettingType settingType[] = { NetworkManager::Setting::Security8021x, NetworkManager::Setting::WirelessSecurity };
372+
for (auto type : settingType) {
373+
NetworkManager::Setting::Ptr setting = conn->settings()->setting(type);
374+
if (setting) {
375+
conn->secrets(setting->name());
376+
}
374377
}
378+
conn->save();
375379
}
376-
conn->save();
377380
connect(conn.data(), &NetworkManager::Connection::unsavedChanged, this, [this] {
378381
Q_EMIT activeConnectionChanged();
379382
});

0 commit comments

Comments
 (0)