17 #include "AccountsService.h"
18 #include "AccountsServiceDBusAdaptor.h"
20 #include <QDBusInterface>
22 #include <QStringList>
28 #define IFACE_ACCOUNTS_USER QStringLiteral("org.freedesktop.Accounts.User")
29 #define IFACE_UBUNTU_INPUT QStringLiteral("com.lomiri.AccountsService.Input")
30 #define IFACE_UBUNTU_SECURITY QStringLiteral("com.lomiri.AccountsService.SecurityPrivacy")
31 #define IFACE_UBUNTU_SECURITY_OLD QStringLiteral("com.lomiri.touch.AccountsService.SecurityPrivacy")
32 #define IFACE_LOMIRI QStringLiteral("com.lomiri.shell.AccountsService")
33 #define IFACE_LOMIRI_PRIVATE QStringLiteral("com.lomiri.shell.AccountsService.Private")
35 #define PROP_BACKGROUND_FILE QStringLiteral("BackgroundFile")
36 #define PROP_DEMO_EDGES QStringLiteral("DemoEdges2")
37 #define PROP_DEMO_EDGES_COMPLETED QStringLiteral("DemoEdgesCompleted")
38 #define PROP_EMAIL QStringLiteral("Email")
39 #define PROP_ENABLE_FINGERPRINT_IDENTIFICATION QStringLiteral("EnableFingerprintIdentification")
40 #define PROP_ENABLE_INDICATORS_WHILE_LOCKED QStringLiteral("EnableIndicatorsWhileLocked")
41 #define PROP_ENABLE_LAUNCHER_WHILE_LOCKED QStringLiteral("EnableLauncherWhileLocked")
42 #define PROP_FAILED_FINGERPRINT_LOGINS QStringLiteral("FailedFingerprintLogins")
43 #define PROP_FAILED_LOGINS QStringLiteral("FailedLogins")
44 #define PROP_INPUT_SOURCES QStringLiteral("InputSources")
45 #define PROP_LICENSE_ACCEPTED QStringLiteral("LicenseAccepted")
46 #define PROP_LICENSE_BASE_PATH QStringLiteral("LicenseBasePath")
47 #define PROP_MOUSE_CURSOR_SPEED QStringLiteral("MouseCursorSpeed")
48 #define PROP_MOUSE_DOUBLE_CLICK_SPEED QStringLiteral("MouseDoubleClickSpeed")
49 #define PROP_MOUSE_PRIMARY_BUTTON QStringLiteral("MousePrimaryButton")
50 #define PROP_MOUSE_SCROLL_SPEED QStringLiteral("MouseScrollSpeed")
51 #define PROP_PASSWORD_DISPLAY_HINT QStringLiteral("PasswordDisplayHint")
52 #define PROP_PINCODE_PROMPT_MANAGER QStringLiteral("PinCodePromptManager")
53 #define PROP_PINCODE_LENGTH QStringLiteral("PinCodeLength")
54 #define PROP_REAL_NAME QStringLiteral("RealName")
55 #define PROP_STATS_WELCOME_SCREEN QStringLiteral("StatsWelcomeScreen")
56 #define PROP_TOUCHPAD_CURSOR_SPEED QStringLiteral("TouchpadCursorSpeed")
57 #define PROP_TOUCHPAD_DISABLE_WHILE_TYPING QStringLiteral("TouchpadDisableWhileTyping")
58 #define PROP_TOUCHPAD_DISABLE_WITH_MOUSE QStringLiteral("TouchpadDisableWithMouse")
59 #define PROP_TOUCHPAD_DOUBLE_CLICK_SPEED QStringLiteral("TouchpadDoubleClickSpeed")
60 #define PROP_TOUCHPAD_PRIMARY_BUTTON QStringLiteral("TouchpadPrimaryButton")
61 #define PROP_TOUCHPAD_SCROLL_SPEED QStringLiteral("TouchpadScrollSpeed")
62 #define PROP_TOUCHPAD_TAP_TO_CLICK QStringLiteral("TouchpadTapToClick")
63 #define PROP_TOUCHPAD_TWO_FINGER_SCROLL QStringLiteral("TouchpadTwoFingerScroll")
65 using StringMap = QMap<QString,QString>;
66 using StringMapList = QList<StringMap>;
67 Q_DECLARE_METATYPE(StringMapList)
70 QVariant primaryButtonConverter(
const QVariant &value)
72 QString stringValue = value.toString();
73 if (stringValue == QLatin1String(
"left")) {
74 return QVariant::fromValue(0);
75 }
else if (stringValue == QLatin1String(
"right")) {
76 return QVariant::fromValue(1);
78 return QVariant::fromValue(0);
82 AccountsService::AccountsService(QObject* parent,
const QString &user)
84 , m_defaultPinPromptManager(
"PinPrompt.qml")
85 , m_service(new AccountsServiceDBusAdaptor(this))
87 m_syscompInput =
new QDBusInterface(QStringLiteral(
"com.lomiri.SystemCompositor.Input"),
88 QStringLiteral(
"/com/lomiri/SystemCompositor/Input"),
89 QStringLiteral(
"com.lomiri.SystemCompositor.Input"),
90 QDBusConnection::SM_BUSNAME(),
this);
92 connect(m_service, &AccountsServiceDBusAdaptor::propertiesChanged,
this, &AccountsService::onPropertiesChanged);
93 connect(m_service, &AccountsServiceDBusAdaptor::maybeChanged,
this, &AccountsService::onMaybeChanged);
95 registerProperty(IFACE_ACCOUNTS_USER, PROP_BACKGROUND_FILE, QStringLiteral(
"backgroundFileChanged"));
96 registerProperty(IFACE_ACCOUNTS_USER, PROP_EMAIL, QStringLiteral(
"emailChanged"));
97 registerProperty(IFACE_ACCOUNTS_USER, PROP_REAL_NAME, QStringLiteral(
"realNameChanged"));
98 registerProperty(IFACE_ACCOUNTS_USER, PROP_INPUT_SOURCES, QStringLiteral(
"keymapsChanged"));
99 registerProperty(IFACE_UBUNTU_SECURITY, PROP_PINCODE_PROMPT_MANAGER, QStringLiteral(
"pinCodePromptManagerChanged"));
100 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_FINGERPRINT_IDENTIFICATION, QStringLiteral(
"enableFingerprintIdentificationChanged"));
101 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED, QStringLiteral(
"enableLauncherWhileLockedChanged"));
102 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_INDICATORS_WHILE_LOCKED, QStringLiteral(
"enableIndicatorsWhileLockedChanged"));
103 registerProperty(IFACE_UBUNTU_SECURITY, PROP_PASSWORD_DISPLAY_HINT, QStringLiteral(
"passwordDisplayHintChanged"));
104 registerProperty(IFACE_UBUNTU_SECURITY, PROP_PINCODE_LENGTH, QStringLiteral(
"pincodeLengthChanged"));
105 registerProperty(IFACE_UBUNTU_SECURITY_OLD, PROP_STATS_WELCOME_SCREEN, QStringLiteral(
"statsWelcomeScreenChanged"));
106 registerProperty(IFACE_LOMIRI, PROP_DEMO_EDGES, QStringLiteral(
"demoEdgesChanged"));
107 registerProperty(IFACE_LOMIRI, PROP_DEMO_EDGES_COMPLETED, QStringLiteral(
"demoEdgesCompletedChanged"));
108 registerProperty(IFACE_LOMIRI_PRIVATE, PROP_FAILED_FINGERPRINT_LOGINS, QStringLiteral(
"failedFingerprintLoginsChanged"));
109 registerProperty(IFACE_LOMIRI_PRIVATE, PROP_FAILED_LOGINS, QStringLiteral(
"failedLoginsChanged"));
111 registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_CURSOR_SPEED,
112 m_syscompInput, QStringLiteral(
"setMouseCursorSpeed"));
113 registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_DOUBLE_CLICK_SPEED,
114 m_syscompInput, QStringLiteral(
"setMouseDoubleClickSpeed"));
115 registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_PRIMARY_BUTTON,
116 m_syscompInput, QStringLiteral(
"setMousePrimaryButton"),
117 primaryButtonConverter);
118 registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_SCROLL_SPEED,
119 m_syscompInput, QStringLiteral(
"setMouseScrollSpeed"));
120 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_CURSOR_SPEED,
121 m_syscompInput, QStringLiteral(
"setTouchpadCursorSpeed"));
122 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_SCROLL_SPEED,
123 m_syscompInput, QStringLiteral(
"setTouchpadScrollSpeed"));
124 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_DISABLE_WHILE_TYPING,
125 m_syscompInput, QStringLiteral(
"setTouchpadDisableWhileTyping"));
126 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_DISABLE_WITH_MOUSE,
127 m_syscompInput, QStringLiteral(
"setTouchpadDisableWithMouse"));
128 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_DOUBLE_CLICK_SPEED,
129 m_syscompInput, QStringLiteral(
"setTouchpadDoubleClickSpeed"));
130 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_PRIMARY_BUTTON,
131 m_syscompInput, QStringLiteral(
"setTouchpadPrimaryButton"),
132 primaryButtonConverter);
133 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_TAP_TO_CLICK,
134 m_syscompInput, QStringLiteral(
"setTouchpadTapToClick"));
135 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_TWO_FINGER_SCROLL,
136 m_syscompInput, QStringLiteral(
"setTouchpadTwoFingerScroll"));
138 setUser(!user.isEmpty() ? user : QString::fromUtf8(g_get_user_name()));
141 QString AccountsService::user()
const
146 void AccountsService::setUser(
const QString &user)
148 if (user.isEmpty() || m_user == user)
151 bool wasEmpty = m_user.isEmpty();
154 Q_EMIT userChanged();
161 bool AccountsService::demoEdges()
const
163 auto value = getProperty(IFACE_LOMIRI, PROP_DEMO_EDGES);
164 return value.toBool();
167 void AccountsService::setDemoEdges(
bool demoEdges)
169 setProperty(IFACE_LOMIRI, PROP_DEMO_EDGES, demoEdges);
172 QStringList AccountsService::demoEdgesCompleted()
const
174 auto value = getProperty(IFACE_LOMIRI, PROP_DEMO_EDGES_COMPLETED);
175 return value.toStringList();
178 void AccountsService::markDemoEdgeCompleted(
const QString &edge)
180 auto currentList = demoEdgesCompleted();
181 if (!currentList.contains(edge)) {
182 setProperty(IFACE_LOMIRI, PROP_DEMO_EDGES_COMPLETED, currentList << edge);
186 bool AccountsService::enableFingerprintIdentification()
const
188 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_FINGERPRINT_IDENTIFICATION);
189 return value.toBool();
192 bool AccountsService::enableLauncherWhileLocked()
const
194 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED);
195 return value.toBool();
198 bool AccountsService::enableIndicatorsWhileLocked()
const
200 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_INDICATORS_WHILE_LOCKED);
201 return value.toBool();
204 QString AccountsService::backgroundFile()
const
206 auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_BACKGROUND_FILE);
207 return value.toString();
210 bool AccountsService::statsWelcomeScreen()
const
212 auto value = getProperty(IFACE_UBUNTU_SECURITY_OLD, PROP_STATS_WELCOME_SCREEN);
213 return value.toBool();
216 AccountsService::PasswordDisplayHint AccountsService::passwordDisplayHint()
const
218 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_PASSWORD_DISPLAY_HINT);
219 return (PasswordDisplayHint)value.toInt();
222 QString AccountsService::pinCodePromptManager()
const
225 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_PINCODE_PROMPT_MANAGER);
226 if (!value.isValid()) {
227 return m_defaultPinPromptManager;
229 QString file = value.toString() +
".qml";
230 if (file == m_defaultPinPromptManager) {
231 return m_defaultPinPromptManager;
232 }
else if (!QFile::exists(qmlDirectory() +
"/Greeter/" + file)) {
233 qWarning() <<
"failed to load pinCodePromptManager " << file <<
", fallback to " << m_defaultPinPromptManager;
234 return m_defaultPinPromptManager;
241 QString AccountsService::defaultPinCodePromptManager()
const
243 return m_defaultPinPromptManager;
246 uint AccountsService::pincodeLength()
const
248 return getProperty(IFACE_UBUNTU_SECURITY, PROP_PINCODE_LENGTH).toUInt();
251 QString AccountsService::realName()
const
253 auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_REAL_NAME);
254 return value.toString();
257 void AccountsService::setRealName(
const QString &realName)
259 setProperty(IFACE_ACCOUNTS_USER, PROP_REAL_NAME, realName);
262 QString AccountsService::email()
const
264 auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_EMAIL);
265 return value.toString();
268 void AccountsService::setEmail(
const QString &email)
270 setProperty(IFACE_ACCOUNTS_USER, PROP_EMAIL, email);
273 QStringList AccountsService::keymaps()
const
275 auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_INPUT_SOURCES);
276 QDBusArgument arg = value.value<QDBusArgument>();
277 StringMapList maps = qdbus_cast<StringMapList>(arg);
278 QStringList simplifiedMaps;
280 Q_FOREACH(
const StringMap &map, maps) {
281 Q_FOREACH(
const QString &entry, map) {
282 simplifiedMaps.append(entry);
286 if (!simplifiedMaps.isEmpty()) {
287 return simplifiedMaps;
290 return {QStringLiteral(
"us")};
293 void AccountsService::setKeymaps(
const QStringList &keymaps)
295 if (keymaps.isEmpty()) {
296 qWarning() <<
"Setting empty keymaps is not supported";
300 StringMapList result;
301 Q_FOREACH(
const QString &keymap, keymaps) {
303 map.insert(QStringLiteral(
"xkb"), keymap);
307 setProperty(IFACE_ACCOUNTS_USER, PROP_INPUT_SOURCES, QVariant::fromValue(result));
308 Q_EMIT keymapsChanged();
311 uint AccountsService::failedFingerprintLogins()
const
313 return getProperty(IFACE_LOMIRI_PRIVATE, PROP_FAILED_FINGERPRINT_LOGINS).toUInt();
316 void AccountsService::setFailedFingerprintLogins(uint failedFingerprintLogins)
318 setProperty(IFACE_LOMIRI_PRIVATE, PROP_FAILED_FINGERPRINT_LOGINS, failedFingerprintLogins);
321 uint AccountsService::failedLogins()
const
323 return getProperty(IFACE_LOMIRI_PRIVATE, PROP_FAILED_LOGINS).toUInt();
326 void AccountsService::setFailedLogins(uint failedLogins)
328 setProperty(IFACE_LOMIRI_PRIVATE, PROP_FAILED_LOGINS, failedLogins);
335 void AccountsService::emitChangedForProperty(
const QString &interface,
const QString &property)
337 QString signalName = m_properties[interface][property].signal;
338 QMetaObject::invokeMethod(
this, signalName.toUtf8().data());
341 QVariant AccountsService::getProperty(
const QString &interface,
const QString &property)
const
343 return m_properties[interface][property].value;
346 void AccountsService::setProperty(
const QString &interface,
const QString &property,
const QVariant &value)
348 if (m_properties[interface][property].value != value) {
349 m_properties[interface][property].value = value;
350 m_service->setUserPropertyAsync(m_user, interface, property, value);
351 emitChangedForProperty(interface, property);
355 void AccountsService::updateCache(
const QString &interface,
const QString &property,
const QVariant &value)
357 PropertyInfo &info = m_properties[interface][property];
359 if (info.proxyInterface) {
361 if (info.proxyConverter) {
362 finalValue = info.proxyConverter(value);
366 info.proxyInterface->asyncCall(info.proxyMethod, finalValue);
370 if (info.value != value) {
372 emitChangedForProperty(interface, property);
376 void AccountsService::updateProperty(
const QString &interface,
const QString &property)
378 QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
381 QDBusPendingCallWatcher *watcher =
new QDBusPendingCallWatcher(pendingReply,
this);
383 connect(watcher, &QDBusPendingCallWatcher::finished,
384 this, [
this, interface, property](QDBusPendingCallWatcher* watcher) {
386 QDBusPendingReply<QVariant> reply = *watcher;
387 watcher->deleteLater();
388 if (reply.isError()) {
389 qWarning() <<
"Failed to get '" << property <<
"' property:" << reply.error().message();
393 updateCache(interface, property, reply.value());
397 void AccountsService::updateAllProperties(
const QString &interface,
bool async)
399 QDBusPendingCall pendingReply = m_service->getAllPropertiesAsync(m_user,
401 QDBusPendingCallWatcher *watcher =
new QDBusPendingCallWatcher(pendingReply,
this);
403 connect(watcher, &QDBusPendingCallWatcher::finished,
404 this, [
this, interface](QDBusPendingCallWatcher* watcher) {
406 QDBusPendingReply< QHash<QString, QVariant> > reply = *watcher;
407 watcher->deleteLater();
408 if (reply.isError()) {
409 qWarning() <<
"Failed to get all properties for" << interface <<
":" << reply.error().message();
413 auto valueHash = reply.value();
414 auto i = valueHash.constBegin();
415 while (i != valueHash.constEnd()) {
416 updateCache(interface, i.key(), i.value());
421 watcher->waitForFinished();
425 void AccountsService::registerProxy(
const QString &interface,
const QString &property, QDBusInterface *iface,
const QString &method, ProxyConverter converter)
427 registerProperty(interface, property,
nullptr);
429 m_properties[interface][property].proxyInterface = iface;
430 m_properties[interface][property].proxyMethod = method;
431 m_properties[interface][property].proxyConverter = converter;
434 void AccountsService::registerProperty(
const QString &interface,
const QString &property,
const QString &signal)
436 m_properties[interface][property] = PropertyInfo();
437 m_properties[interface][property].signal = signal;
440 void AccountsService::onPropertiesChanged(
const QString &user,
const QString &interface,
const QStringList &changed)
442 if (m_user != user) {
446 auto propHash = m_properties.value(interface);
447 auto i = propHash.constBegin();
448 while (i != propHash.constEnd()) {
449 if (changed.contains(i.key())) {
450 updateProperty(interface, i.key());
456 void AccountsService::onMaybeChanged(
const QString &user)
458 if (m_user != user) {
463 auto propHash = m_properties.value(IFACE_ACCOUNTS_USER);
464 auto i = propHash.constBegin();
465 while (i != propHash.constEnd()) {
466 updateProperty(IFACE_ACCOUNTS_USER, i.key());
471 void AccountsService::refresh(
bool async)
473 auto i = m_properties.constBegin();
474 while (i != m_properties.constEnd()) {
475 updateAllProperties(i.key(), async);