17#include "AccountsService.h"
18#include "AccountsServiceDBusAdaptor.h"
20#include <QDBusInterface>
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_HIDE_NOTIFICATION_CONTENT_WHILE_LOCKED QStringLiteral("HideNotificationContentWhileLocked")
42#define PROP_ENABLE_LAUNCHER_WHILE_LOCKED QStringLiteral("EnableLauncherWhileLocked")
43#define PROP_FAILED_FINGERPRINT_LOGINS QStringLiteral("FailedFingerprintLogins")
44#define PROP_FAILED_LOGINS QStringLiteral("FailedLogins")
45#define PROP_INPUT_SOURCES QStringLiteral("InputSources")
46#define PROP_LICENSE_ACCEPTED QStringLiteral("LicenseAccepted")
47#define PROP_LICENSE_BASE_PATH QStringLiteral("LicenseBasePath")
48#define PROP_MOUSE_CURSOR_SPEED QStringLiteral("MouseCursorSpeed")
49#define PROP_MOUSE_DOUBLE_CLICK_SPEED QStringLiteral("MouseDoubleClickSpeed")
50#define PROP_MOUSE_PRIMARY_BUTTON QStringLiteral("MousePrimaryButton")
51#define PROP_MOUSE_SCROLL_SPEED QStringLiteral("MouseScrollSpeed")
52#define PROP_PASSWORD_DISPLAY_HINT QStringLiteral("PasswordDisplayHint")
53#define PROP_PINCODE_PROMPT_MANAGER QStringLiteral("PinCodePromptManager")
54#define PROP_PINCODE_LENGTH QStringLiteral("PinCodeLength")
55#define PROP_REAL_NAME QStringLiteral("RealName")
56#define PROP_STATS_WELCOME_SCREEN QStringLiteral("StatsWelcomeScreen")
57#define PROP_TOUCHPAD_CURSOR_SPEED QStringLiteral("TouchpadCursorSpeed")
58#define PROP_TOUCHPAD_DISABLE_WHILE_TYPING QStringLiteral("TouchpadDisableWhileTyping")
59#define PROP_TOUCHPAD_DISABLE_WITH_MOUSE QStringLiteral("TouchpadDisableWithMouse")
60#define PROP_TOUCHPAD_DOUBLE_CLICK_SPEED QStringLiteral("TouchpadDoubleClickSpeed")
61#define PROP_TOUCHPAD_PRIMARY_BUTTON QStringLiteral("TouchpadPrimaryButton")
62#define PROP_TOUCHPAD_SCROLL_SPEED QStringLiteral("TouchpadScrollSpeed")
63#define PROP_TOUCHPAD_TAP_TO_CLICK QStringLiteral("TouchpadTapToClick")
64#define PROP_TOUCHPAD_TWO_FINGER_SCROLL QStringLiteral("TouchpadTwoFingerScroll")
66using StringMap = QMap<QString,QString>;
67using StringMapList = QList<StringMap>;
68Q_DECLARE_METATYPE(StringMapList)
71QVariant primaryButtonConverter(
const QVariant &value)
73 QString stringValue = value.toString();
74 if (stringValue == QLatin1String(
"left")) {
75 return QVariant::fromValue(0);
76 }
else if (stringValue == QLatin1String(
"right")) {
77 return QVariant::fromValue(1);
79 return QVariant::fromValue(0);
83AccountsService::AccountsService(QObject* parent,
const QString &user)
85 , m_defaultPinPromptManager(
"PinPrompt.qml")
86 , m_service(new AccountsServiceDBusAdaptor(this))
88 m_syscompInput =
new QDBusInterface(QStringLiteral(
"com.lomiri.SystemCompositor.Input"),
89 QStringLiteral(
"/com/lomiri/SystemCompositor/Input"),
90 QStringLiteral(
"com.lomiri.SystemCompositor.Input"),
91 QDBusConnection::SM_BUSNAME(),
this);
93 connect(m_service, &AccountsServiceDBusAdaptor::propertiesChanged,
this, &AccountsService::onPropertiesChanged);
94 connect(m_service, &AccountsServiceDBusAdaptor::maybeChanged,
this, &AccountsService::onMaybeChanged);
96 #ifdef ENABLE_UBUNTU_ACCOUNTSSERVICE
97 registerProperty(IFACE_ACCOUNTS_USER, PROP_BACKGROUND_FILE, QStringLiteral(
"backgroundFileChanged"));
99 registerProperty(IFACE_LOMIRI, PROP_BACKGROUND_FILE, QStringLiteral(
"backgroundFileChanged"));
102 registerProperty(IFACE_ACCOUNTS_USER, PROP_EMAIL, QStringLiteral(
"emailChanged"));
103 registerProperty(IFACE_ACCOUNTS_USER, PROP_REAL_NAME, QStringLiteral(
"realNameChanged"));
104 registerProperty(IFACE_ACCOUNTS_USER, PROP_INPUT_SOURCES, QStringLiteral(
"keymapsChanged"));
105 registerProperty(IFACE_UBUNTU_SECURITY, PROP_PINCODE_PROMPT_MANAGER, QStringLiteral(
"pinCodePromptManagerChanged"));
106 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_FINGERPRINT_IDENTIFICATION, QStringLiteral(
"enableFingerprintIdentificationChanged"));
107 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED, QStringLiteral(
"enableLauncherWhileLockedChanged"));
108 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_INDICATORS_WHILE_LOCKED, QStringLiteral(
"enableIndicatorsWhileLockedChanged"));
109 registerProperty(IFACE_UBUNTU_SECURITY, PROP_HIDE_NOTIFICATION_CONTENT_WHILE_LOCKED, QStringLiteral(
"hideNotificationContentWhileLocked"));
110 registerProperty(IFACE_UBUNTU_SECURITY, PROP_PASSWORD_DISPLAY_HINT, QStringLiteral(
"passwordDisplayHintChanged"));
111 registerProperty(IFACE_UBUNTU_SECURITY, PROP_PINCODE_LENGTH, QStringLiteral(
"pincodeLengthChanged"));
112 registerProperty(IFACE_UBUNTU_SECURITY_OLD, PROP_STATS_WELCOME_SCREEN, QStringLiteral(
"statsWelcomeScreenChanged"));
113 registerProperty(IFACE_LOMIRI, PROP_DEMO_EDGES, QStringLiteral(
"demoEdgesChanged"));
114 registerProperty(IFACE_LOMIRI, PROP_DEMO_EDGES_COMPLETED, QStringLiteral(
"demoEdgesCompletedChanged"));
115 registerProperty(IFACE_LOMIRI_PRIVATE, PROP_FAILED_FINGERPRINT_LOGINS, QStringLiteral(
"failedFingerprintLoginsChanged"));
116 registerProperty(IFACE_LOMIRI_PRIVATE, PROP_FAILED_LOGINS, QStringLiteral(
"failedLoginsChanged"));
118 registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_CURSOR_SPEED,
119 m_syscompInput, QStringLiteral(
"setMouseCursorSpeed"));
120 registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_DOUBLE_CLICK_SPEED,
121 m_syscompInput, QStringLiteral(
"setMouseDoubleClickSpeed"));
122 registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_PRIMARY_BUTTON,
123 m_syscompInput, QStringLiteral(
"setMousePrimaryButton"),
124 primaryButtonConverter);
125 registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_SCROLL_SPEED,
126 m_syscompInput, QStringLiteral(
"setMouseScrollSpeed"));
127 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_CURSOR_SPEED,
128 m_syscompInput, QStringLiteral(
"setTouchpadCursorSpeed"));
129 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_SCROLL_SPEED,
130 m_syscompInput, QStringLiteral(
"setTouchpadScrollSpeed"));
131 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_DISABLE_WHILE_TYPING,
132 m_syscompInput, QStringLiteral(
"setTouchpadDisableWhileTyping"));
133 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_DISABLE_WITH_MOUSE,
134 m_syscompInput, QStringLiteral(
"setTouchpadDisableWithMouse"));
135 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_DOUBLE_CLICK_SPEED,
136 m_syscompInput, QStringLiteral(
"setTouchpadDoubleClickSpeed"));
137 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_PRIMARY_BUTTON,
138 m_syscompInput, QStringLiteral(
"setTouchpadPrimaryButton"),
139 primaryButtonConverter);
140 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_TAP_TO_CLICK,
141 m_syscompInput, QStringLiteral(
"setTouchpadTapToClick"));
142 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_TWO_FINGER_SCROLL,
143 m_syscompInput, QStringLiteral(
"setTouchpadTwoFingerScroll"));
145 setUser(!user.isEmpty() ? user : QString::fromUtf8(g_get_user_name()));
148QString AccountsService::user()
const
153void AccountsService::setUser(
const QString &user)
155 if (user.isEmpty() || m_user == user)
158 bool wasEmpty = m_user.isEmpty();
161 Q_EMIT userChanged();
168bool AccountsService::demoEdges()
const
170 auto value = getProperty(IFACE_LOMIRI, PROP_DEMO_EDGES);
171 return value.toBool();
174void AccountsService::setDemoEdges(
bool demoEdges)
176 setProperty(IFACE_LOMIRI, PROP_DEMO_EDGES, demoEdges);
179QStringList AccountsService::demoEdgesCompleted()
const
181 auto value = getProperty(IFACE_LOMIRI, PROP_DEMO_EDGES_COMPLETED);
182 return value.toStringList();
185void AccountsService::markDemoEdgeCompleted(
const QString &edge)
187 auto currentList = demoEdgesCompleted();
188 if (!currentList.contains(edge)) {
189 setProperty(IFACE_LOMIRI, PROP_DEMO_EDGES_COMPLETED, currentList << edge);
193bool AccountsService::enableFingerprintIdentification()
const
195 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_FINGERPRINT_IDENTIFICATION);
196 return value.toBool();
199bool AccountsService::enableLauncherWhileLocked()
const
201 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED);
202 return value.toBool();
205bool AccountsService::enableIndicatorsWhileLocked()
const
207 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_INDICATORS_WHILE_LOCKED);
208 return value.toBool();
211bool AccountsService::hideNotificationContentWhileLocked()
const
213 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_HIDE_NOTIFICATION_CONTENT_WHILE_LOCKED);
214 return value.toBool();
217QString AccountsService::backgroundFile()
const
219 #ifdef ENABLE_UBUNTU_ACCOUNTSSERVICE
220 auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_BACKGROUND_FILE);
222 auto value = getProperty(IFACE_LOMIRI, PROP_BACKGROUND_FILE);
225 return value.toString();
228bool AccountsService::statsWelcomeScreen()
const
230 auto value = getProperty(IFACE_UBUNTU_SECURITY_OLD, PROP_STATS_WELCOME_SCREEN);
231 return value.toBool();
234AccountsService::PasswordDisplayHint AccountsService::passwordDisplayHint()
const
236 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_PASSWORD_DISPLAY_HINT);
237 return (PasswordDisplayHint)value.toInt();
240QString AccountsService::pinCodePromptManager()
const
243 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_PINCODE_PROMPT_MANAGER);
244 if (!value.isValid()) {
245 return m_defaultPinPromptManager;
247 QString file = value.toString() +
".qml";
248 if (file == m_defaultPinPromptManager) {
249 return m_defaultPinPromptManager;
250 }
else if (!QFile::exists(qmlDirectory() +
"/Greeter/" + file)) {
251 qWarning() <<
"failed to load pinCodePromptManager " << file <<
", fallback to " << m_defaultPinPromptManager;
252 return m_defaultPinPromptManager;
259QString AccountsService::defaultPinCodePromptManager()
const
261 return m_defaultPinPromptManager;
264uint AccountsService::pincodeLength()
const
266 return getProperty(IFACE_UBUNTU_SECURITY, PROP_PINCODE_LENGTH).toUInt();
269QString AccountsService::realName()
const
271 auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_REAL_NAME);
272 return value.toString();
275void AccountsService::setRealName(
const QString &realName)
277 setProperty(IFACE_ACCOUNTS_USER, PROP_REAL_NAME, realName);
280QString AccountsService::email()
const
282 auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_EMAIL);
283 return value.toString();
286void AccountsService::setEmail(
const QString &email)
288 setProperty(IFACE_ACCOUNTS_USER, PROP_EMAIL, email);
291QStringList AccountsService::keymaps()
const
293 auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_INPUT_SOURCES);
294 QDBusArgument arg = value.value<QDBusArgument>();
295 StringMapList maps = qdbus_cast<StringMapList>(arg);
296 QStringList simplifiedMaps;
298 Q_FOREACH(
const StringMap &map, maps) {
299 Q_FOREACH(
const QString &entry, map) {
300 simplifiedMaps.append(entry);
304 if (!simplifiedMaps.isEmpty()) {
305 return simplifiedMaps;
308 return {QStringLiteral(
"us")};
311void AccountsService::setKeymaps(
const QStringList &keymaps)
313 if (keymaps.isEmpty()) {
314 qWarning() <<
"Setting empty keymaps is not supported";
318 StringMapList result;
319 Q_FOREACH(
const QString &keymap, keymaps) {
321 map.insert(QStringLiteral(
"xkb"), keymap);
325 setProperty(IFACE_ACCOUNTS_USER, PROP_INPUT_SOURCES, QVariant::fromValue(result));
326 Q_EMIT keymapsChanged();
329uint AccountsService::failedFingerprintLogins()
const
331 return getProperty(IFACE_LOMIRI_PRIVATE, PROP_FAILED_FINGERPRINT_LOGINS).toUInt();
334void AccountsService::setFailedFingerprintLogins(uint failedFingerprintLogins)
336 setProperty(IFACE_LOMIRI_PRIVATE, PROP_FAILED_FINGERPRINT_LOGINS, failedFingerprintLogins);
339uint AccountsService::failedLogins()
const
341 return getProperty(IFACE_LOMIRI_PRIVATE, PROP_FAILED_LOGINS).toUInt();
344void AccountsService::setFailedLogins(uint failedLogins)
346 setProperty(IFACE_LOMIRI_PRIVATE, PROP_FAILED_LOGINS, failedLogins);
353void AccountsService::emitChangedForProperty(
const QString &interface,
const QString &property)
355 QString signalName = m_properties[interface][property].signal;
356 QMetaObject::invokeMethod(
this, signalName.toUtf8().data());
359QVariant AccountsService::getProperty(
const QString &interface,
const QString &property)
const
361 return m_properties[interface][property].value;
364void AccountsService::setProperty(
const QString &interface,
const QString &property,
const QVariant &value)
366 if (m_properties[interface][property].value != value) {
367 m_properties[interface][property].value = value;
368 m_service->setUserPropertyAsync(m_user, interface, property, value);
369 emitChangedForProperty(interface, property);
373void AccountsService::updateCache(
const QString &interface,
const QString &property,
const QVariant &value)
375 PropertyInfo &info = m_properties[interface][property];
377 if (info.proxyInterface) {
379 if (info.proxyConverter) {
380 finalValue = info.proxyConverter(value);
384 info.proxyInterface->asyncCall(info.proxyMethod, finalValue);
388 if (info.value != value) {
390 emitChangedForProperty(interface, property);
394void AccountsService::updateProperty(
const QString &interface,
const QString &property)
396 QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
399 QDBusPendingCallWatcher *watcher =
new QDBusPendingCallWatcher(pendingReply,
this);
401 connect(watcher, &QDBusPendingCallWatcher::finished,
402 this, [
this, interface, property](QDBusPendingCallWatcher* watcher) {
404 QDBusPendingReply<QVariant> reply = *watcher;
405 watcher->deleteLater();
406 if (reply.isError()) {
407 qWarning() <<
"Failed to get '" << property <<
"' property:" << reply.error().message();
411 updateCache(interface, property, reply.value());
415void AccountsService::updateAllProperties(
const QString &interface,
bool async)
417 QDBusPendingCall pendingReply = m_service->getAllPropertiesAsync(m_user,
419 QDBusPendingCallWatcher *watcher =
new QDBusPendingCallWatcher(pendingReply,
this);
421 connect(watcher, &QDBusPendingCallWatcher::finished,
422 this, [
this, interface](QDBusPendingCallWatcher* watcher) {
424 QDBusPendingReply< QHash<QString, QVariant> > reply = *watcher;
425 watcher->deleteLater();
426 if (reply.isError()) {
427 qWarning() <<
"Failed to get all properties for" << interface <<
":" << reply.error().message();
431 auto valueHash = reply.value();
432 auto i = valueHash.constBegin();
433 while (i != valueHash.constEnd()) {
434 updateCache(interface, i.key(), i.value());
439 watcher->waitForFinished();
443void AccountsService::registerProxy(
const QString &interface,
const QString &property, QDBusInterface *iface,
const QString &method, ProxyConverter converter)
445 registerProperty(interface, property,
nullptr);
447 m_properties[interface][property].proxyInterface = iface;
448 m_properties[interface][property].proxyMethod = method;
449 m_properties[interface][property].proxyConverter = converter;
452void AccountsService::registerProperty(
const QString &interface,
const QString &property,
const QString &signal)
454 m_properties[interface][property] = PropertyInfo();
455 m_properties[interface][property].signal = signal;
458void AccountsService::onPropertiesChanged(
const QString &user,
const QString &interface,
const QStringList &changed)
460 if (m_user != user) {
464 auto propHash = m_properties.value(interface);
465 auto i = propHash.constBegin();
466 while (i != propHash.constEnd()) {
467 if (changed.contains(i.key())) {
468 updateProperty(interface, i.key());
474void AccountsService::onMaybeChanged(
const QString &user)
476 if (m_user != user) {
481 auto propHash = m_properties.value(IFACE_ACCOUNTS_USER);
482 auto i = propHash.constBegin();
483 while (i != propHash.constEnd()) {
484 updateProperty(IFACE_ACCOUNTS_USER, i.key());
489void AccountsService::refresh(
bool async)
491 auto i = m_properties.constBegin();
492 while (i != m_properties.constEnd()) {
493 updateAllProperties(i.key(), async);