1 /*
2     SPDX-FileCopyrightText: 2019 David Edmundson <davidedmundson@kde.org>
3 
4     SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "sessionmanagement.h"
8 
9 #include "sessionmanagementbackend.h"
10 
11 #include <KAuthorized>
12 #include <KConfigGroup>
13 #include <KSharedConfig>
14 
15 #include "kscreenlocker_interface.h"
16 #include "ksmserver_interface.h"
17 #include "logoutprompt_interface.h"
18 #include "screenlocker_interface.h"
19 #include "shutdown_interface.h"
20 
21 // add a constructor with the service names and paths pre-populated
22 class LogoutPromptIface : public OrgKdeLogoutPromptInterface
23 {
24     Q_OBJECT
25 public:
LogoutPromptIface()26     LogoutPromptIface()
27         : OrgKdeLogoutPromptInterface(QStringLiteral("org.kde.LogoutPrompt"), QStringLiteral("/LogoutPrompt"), QDBusConnection::sessionBus())
28     {
29     }
30 };
31 
32 class ShutdownIface : public OrgKdeShutdownInterface
33 {
34     Q_OBJECT
35 public:
ShutdownIface()36     ShutdownIface()
37         : OrgKdeShutdownInterface(QStringLiteral("org.kde.Shutdown"), QStringLiteral("/Shutdown"), QDBusConnection::sessionBus())
38     {
39     }
40 };
41 
SessionManagement(QObject * parent)42 SessionManagement::SessionManagement(QObject *parent)
43     : QObject(parent)
44 {
45     auto backend = SessionBackend::self();
46     connect(backend, &SessionBackend::stateChanged, this, &SessionManagement::stateChanged);
47     connect(backend, &SessionBackend::canShutdownChanged, this, &SessionManagement::canShutdownChanged);
48     connect(backend, &SessionBackend::canRebootChanged, this, &SessionManagement::canRebootChanged);
49     connect(backend, &SessionBackend::canSuspendChanged, this, &SessionManagement::canSuspendChanged);
50     connect(backend, &SessionBackend::canHybridSuspendChanged, this, &SessionManagement::canHybridSuspendChanged);
51     connect(backend, &SessionBackend::canHibernateChanged, this, &SessionManagement::canHibernateChanged);
52     connect(backend, &SessionBackend::aboutToSuspend, this, &SessionManagement::aboutToSuspend);
53     connect(backend, &SessionBackend::resumingFromSuspend, this, &SessionManagement::resumingFromSuspend);
54 }
55 
canShutdown() const56 bool SessionManagement::canShutdown() const
57 {
58     return canLogout() && SessionBackend::self()->canShutdown();
59 }
60 
canReboot() const61 bool SessionManagement::canReboot() const
62 {
63     return canLogout() && SessionBackend::self()->canReboot();
64 }
65 
canLogout() const66 bool SessionManagement::canLogout() const
67 {
68     // checking both is for compatibility with old kiosk configs
69     // authorizeAction is the "correct" one
70     return KAuthorized::authorizeAction(QStringLiteral("logout")) && KAuthorized::authorize(QStringLiteral("logout"));
71 }
72 
canSuspend() const73 bool SessionManagement::canSuspend() const
74 {
75     return SessionBackend::self()->canSuspend();
76 }
77 
canHybridSuspend() const78 bool SessionManagement::canHybridSuspend() const
79 {
80     return SessionBackend::self()->canHybridSuspend();
81 }
82 
canHibernate() const83 bool SessionManagement::canHibernate() const
84 {
85     return SessionBackend::self()->canHibernate();
86 }
87 
canSwitchUser() const88 bool SessionManagement::canSwitchUser() const
89 {
90     return KAuthorized::authorizeAction(QStringLiteral("start_new_session"));
91 }
92 
canLock() const93 bool SessionManagement::canLock() const
94 {
95     return KAuthorized::authorizeAction(QStringLiteral("lock_screen"));
96 }
97 
canSaveSession() const98 bool SessionManagement::canSaveSession() const
99 {
100     const KConfigGroup c(KSharedConfig::openConfig(QStringLiteral("ksmserverrc")), "General");
101     return canLogout() && c.readEntry("loginMode") == QLatin1String("restoreSavedSession");
102 }
103 
state() const104 SessionManagement::State SessionManagement::state() const
105 {
106     return SessionBackend::self()->state();
107 }
108 
requestShutdown(ConfirmationMode confirmationMode)109 void SessionManagement::requestShutdown(ConfirmationMode confirmationMode)
110 {
111     if (!canShutdown()) {
112         return;
113     }
114     bool confirm = confirmationMode == ConfirmationMode::ForcePrompt;
115     if (confirmationMode == ConfirmationMode::Default) {
116         confirm = SessionBackend::self()->confirmLogout();
117     }
118     if (confirm) {
119         LogoutPromptIface iface;
120         iface.promptShutDown().waitForFinished();
121     } else {
122         ShutdownIface iface;
123         iface.logoutAndShutdown().waitForFinished();
124     }
125 }
126 
requestReboot(ConfirmationMode confirmationMode)127 void SessionManagement::requestReboot(ConfirmationMode confirmationMode)
128 {
129     if (!canReboot()) {
130         return;
131     }
132     bool confirm = confirmationMode == ConfirmationMode::ForcePrompt;
133     if (confirmationMode == ConfirmationMode::Default) {
134         confirm = SessionBackend::self()->confirmLogout();
135     }
136     if (confirm) {
137         LogoutPromptIface iface;
138         iface.promptReboot().waitForFinished();
139     } else {
140         ShutdownIface iface;
141         iface.logoutAndReboot().waitForFinished();
142     }
143 }
144 
requestLogout(ConfirmationMode confirmationMode)145 void SessionManagement::requestLogout(ConfirmationMode confirmationMode)
146 {
147     if (!canLogout()) {
148         return;
149     }
150     bool confirm = confirmationMode == ConfirmationMode::ForcePrompt;
151     if (confirmationMode == ConfirmationMode::Default) {
152         confirm = SessionBackend::self()->confirmLogout();
153     }
154     if (confirm) {
155         LogoutPromptIface iface;
156         iface.promptLogout().waitForFinished();
157     } else {
158         ShutdownIface iface;
159         iface.logout().waitForFinished();
160     }
161 }
162 
suspend()163 void SessionManagement::suspend()
164 {
165     if (!canSuspend()) {
166         return;
167     }
168     SessionBackend::self()->suspend();
169 }
170 
hybridSuspend()171 void SessionManagement::hybridSuspend()
172 {
173     if (!canHybridSuspend()) {
174         return;
175     }
176     SessionManagement::hybridSuspend();
177 }
178 
hibernate()179 void SessionManagement::hibernate()
180 {
181     if (!canHibernate()) {
182         return;
183     }
184     SessionBackend::self()->hibernate();
185 }
186 
lock()187 void SessionManagement::lock()
188 {
189     if (!canLock()) {
190         return;
191     }
192     OrgFreedesktopScreenSaverInterface iface(QStringLiteral("org.freedesktop.ScreenSaver"), QStringLiteral("/ScreenSaver"), QDBusConnection::sessionBus());
193     iface.Lock();
194 }
195 
switchUser()196 void SessionManagement::switchUser()
197 {
198     if (!canSwitchUser()) {
199         return;
200     }
201     OrgKdeScreensaverInterface iface(QStringLiteral("org.freedesktop.ScreenSaver"), QStringLiteral("/ScreenSaver"), QDBusConnection::sessionBus());
202     iface.SwitchUser();
203 }
204 
saveSession()205 void SessionManagement::saveSession()
206 {
207     if (!canSaveSession()) {
208         return;
209     }
210     OrgKdeKSMServerInterfaceInterface ksmserver(QStringLiteral("org.kde.ksmserver"), QStringLiteral("/KSMServer"), QDBusConnection::sessionBus());
211     ksmserver.saveCurrentSession();
212 }
213 
214 #include "sessionmanagement.moc"
215