17 #include "AccountsService.h" 18 #include "AccountsServiceDBusAdaptor.h" 20 #include <QDBusInterface> 22 #include <QStringList> 27 #define IFACE_ACCOUNTS_USER QStringLiteral("org.freedesktop.Accounts.User") 28 #define IFACE_UBUNTU_INPUT QStringLiteral("com.ubuntu.AccountsService.Input") 29 #define IFACE_UBUNTU_SECURITY QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy") 30 #define IFACE_UBUNTU_SECURITY_OLD QStringLiteral("com.ubuntu.touch.AccountsService.SecurityPrivacy") 31 #define IFACE_UNITY QStringLiteral("com.canonical.unity.AccountsService") 32 #define IFACE_UNITY_PRIVATE QStringLiteral("com.canonical.unity.AccountsService.Private") 34 #define PROP_BACKGROUND_FILE QStringLiteral("BackgroundFile") 35 #define PROP_DEMO_EDGES QStringLiteral("DemoEdges2") 36 #define PROP_DEMO_EDGES_COMPLETED QStringLiteral("DemoEdgesCompleted") 37 #define PROP_EMAIL QStringLiteral("Email") 38 #define PROP_ENABLE_FINGERPRINT_IDENTIFICATION QStringLiteral("EnableFingerprintIdentification") 39 #define PROP_ENABLE_INDICATORS_WHILE_LOCKED QStringLiteral("EnableIndicatorsWhileLocked") 40 #define PROP_ENABLE_LAUNCHER_WHILE_LOCKED QStringLiteral("EnableLauncherWhileLocked") 41 #define PROP_FAILED_FINGERPRINT_LOGINS QStringLiteral("FailedFingerprintLogins") 42 #define PROP_FAILED_LOGINS QStringLiteral("FailedLogins") 43 #define PROP_INPUT_SOURCES QStringLiteral("InputSources") 44 #define PROP_LICENSE_ACCEPTED QStringLiteral("LicenseAccepted") 45 #define PROP_LICENSE_BASE_PATH QStringLiteral("LicenseBasePath") 46 #define PROP_MOUSE_CURSOR_SPEED QStringLiteral("MouseCursorSpeed") 47 #define PROP_MOUSE_DOUBLE_CLICK_SPEED QStringLiteral("MouseDoubleClickSpeed") 48 #define PROP_MOUSE_PRIMARY_BUTTON QStringLiteral("MousePrimaryButton") 49 #define PROP_MOUSE_SCROLL_SPEED QStringLiteral("MouseScrollSpeed") 50 #define PROP_PASSWORD_DISPLAY_HINT QStringLiteral("PasswordDisplayHint") 51 #define PROP_REAL_NAME QStringLiteral("RealName") 52 #define PROP_STATS_WELCOME_SCREEN QStringLiteral("StatsWelcomeScreen") 53 #define PROP_TOUCHPAD_CURSOR_SPEED QStringLiteral("TouchpadCursorSpeed") 54 #define PROP_TOUCHPAD_DISABLE_WHILE_TYPING QStringLiteral("TouchpadDisableWhileTyping") 55 #define PROP_TOUCHPAD_DISABLE_WITH_MOUSE QStringLiteral("TouchpadDisableWithMouse") 56 #define PROP_TOUCHPAD_DOUBLE_CLICK_SPEED QStringLiteral("TouchpadDoubleClickSpeed") 57 #define PROP_TOUCHPAD_PRIMARY_BUTTON QStringLiteral("TouchpadPrimaryButton") 58 #define PROP_TOUCHPAD_SCROLL_SPEED QStringLiteral("TouchpadScrollSpeed") 59 #define PROP_TOUCHPAD_TAP_TO_CLICK QStringLiteral("TouchpadTapToClick") 60 #define PROP_TOUCHPAD_TWO_FINGER_SCROLL QStringLiteral("TouchpadTwoFingerScroll") 62 using StringMap = QMap<QString,QString>;
63 using StringMapList = QList<StringMap>;
64 Q_DECLARE_METATYPE(StringMapList)
67 QVariant primaryButtonConverter(const QVariant &value)
69 QString stringValue = value.toString();
70 if (stringValue == QLatin1String(
"left")) {
71 return QVariant::fromValue(0);
72 }
else if (stringValue == QLatin1String(
"right")) {
73 return QVariant::fromValue(1);
75 return QVariant::fromValue(0);
79 AccountsService::AccountsService(QObject* parent,
const QString &user)
81 , m_service(new AccountsServiceDBusAdaptor(this))
83 m_unityInput =
new QDBusInterface(QStringLiteral(
"com.canonical.Unity.Input"),
84 QStringLiteral(
"/com/canonical/Unity/Input"),
85 QStringLiteral(
"com.canonical.Unity.Input"),
86 QDBusConnection::SM_BUSNAME(),
this);
88 connect(m_service, &AccountsServiceDBusAdaptor::propertiesChanged,
this, &AccountsService::onPropertiesChanged);
89 connect(m_service, &AccountsServiceDBusAdaptor::maybeChanged,
this, &AccountsService::onMaybeChanged);
91 registerProperty(IFACE_ACCOUNTS_USER, PROP_BACKGROUND_FILE, QStringLiteral(
"backgroundFileChanged"));
92 registerProperty(IFACE_ACCOUNTS_USER, PROP_EMAIL, QStringLiteral(
"emailChanged"));
93 registerProperty(IFACE_ACCOUNTS_USER, PROP_REAL_NAME, QStringLiteral(
"realNameChanged"));
94 registerProperty(IFACE_ACCOUNTS_USER, PROP_INPUT_SOURCES, QStringLiteral(
"keymapsChanged"));
95 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_FINGERPRINT_IDENTIFICATION, QStringLiteral(
"enableFingerprintIdentificationChanged"));
96 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED, QStringLiteral(
"enableLauncherWhileLockedChanged"));
97 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_INDICATORS_WHILE_LOCKED, QStringLiteral(
"enableIndicatorsWhileLockedChanged"));
98 registerProperty(IFACE_UBUNTU_SECURITY, PROP_PASSWORD_DISPLAY_HINT, QStringLiteral(
"passwordDisplayHintChanged"));
99 registerProperty(IFACE_UBUNTU_SECURITY_OLD, PROP_STATS_WELCOME_SCREEN, QStringLiteral(
"statsWelcomeScreenChanged"));
100 registerProperty(IFACE_UNITY, PROP_DEMO_EDGES, QStringLiteral(
"demoEdgesChanged"));
101 registerProperty(IFACE_UNITY, PROP_DEMO_EDGES_COMPLETED, QStringLiteral(
"demoEdgesCompletedChanged"));
102 registerProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_FINGERPRINT_LOGINS, QStringLiteral(
"failedFingerprintLoginsChanged"));
103 registerProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_LOGINS, QStringLiteral(
"failedLoginsChanged"));
105 registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_CURSOR_SPEED,
106 m_unityInput, QStringLiteral(
"setMouseCursorSpeed"));
107 registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_DOUBLE_CLICK_SPEED,
108 m_unityInput, QStringLiteral(
"setMouseDoubleClickSpeed"));
109 registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_PRIMARY_BUTTON,
110 m_unityInput, QStringLiteral(
"setMousePrimaryButton"),
111 primaryButtonConverter);
112 registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_SCROLL_SPEED,
113 m_unityInput, QStringLiteral(
"setMouseScrollSpeed"));
114 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_CURSOR_SPEED,
115 m_unityInput, QStringLiteral(
"setTouchpadCursorSpeed"));
116 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_SCROLL_SPEED,
117 m_unityInput, QStringLiteral(
"setTouchpadScrollSpeed"));
118 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_DISABLE_WHILE_TYPING,
119 m_unityInput, QStringLiteral(
"setTouchpadDisableWhileTyping"));
120 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_DISABLE_WITH_MOUSE,
121 m_unityInput, QStringLiteral(
"setTouchpadDisableWithMouse"));
122 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_DOUBLE_CLICK_SPEED,
123 m_unityInput, QStringLiteral(
"setTouchpadDoubleClickSpeed"));
124 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_PRIMARY_BUTTON,
125 m_unityInput, QStringLiteral(
"setTouchpadPrimaryButton"),
126 primaryButtonConverter);
127 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_TAP_TO_CLICK,
128 m_unityInput, QStringLiteral(
"setTouchpadTapToClick"));
129 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_TWO_FINGER_SCROLL,
130 m_unityInput, QStringLiteral(
"setTouchpadTwoFingerScroll"));
132 setUser(!user.isEmpty() ? user : QString::fromUtf8(g_get_user_name()));
135 QString AccountsService::user()
const 140 void AccountsService::setUser(
const QString &user)
142 if (user.isEmpty() || m_user == user)
145 bool wasEmpty = m_user.isEmpty();
148 Q_EMIT userChanged();
155 bool AccountsService::demoEdges()
const 157 auto value = getProperty(IFACE_UNITY, PROP_DEMO_EDGES);
158 return value.toBool();
161 void AccountsService::setDemoEdges(
bool demoEdges)
163 setProperty(IFACE_UNITY, PROP_DEMO_EDGES, demoEdges);
166 QStringList AccountsService::demoEdgesCompleted()
const 168 auto value = getProperty(IFACE_UNITY, PROP_DEMO_EDGES_COMPLETED);
169 return value.toStringList();
172 void AccountsService::markDemoEdgeCompleted(
const QString &edge)
174 auto currentList = demoEdgesCompleted();
175 if (!currentList.contains(edge)) {
176 setProperty(IFACE_UNITY, PROP_DEMO_EDGES_COMPLETED, currentList << edge);
180 bool AccountsService::enableFingerprintIdentification()
const 182 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_FINGERPRINT_IDENTIFICATION);
183 return value.toBool();
186 bool AccountsService::enableLauncherWhileLocked()
const 188 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED);
189 return value.toBool();
192 bool AccountsService::enableIndicatorsWhileLocked()
const 194 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_INDICATORS_WHILE_LOCKED);
195 return value.toBool();
198 QString AccountsService::backgroundFile()
const 200 auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_BACKGROUND_FILE);
201 return value.toString();
204 bool AccountsService::statsWelcomeScreen()
const 206 auto value = getProperty(IFACE_UBUNTU_SECURITY_OLD, PROP_STATS_WELCOME_SCREEN);
207 return value.toBool();
210 AccountsService::PasswordDisplayHint AccountsService::passwordDisplayHint()
const 212 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_PASSWORD_DISPLAY_HINT);
213 return (PasswordDisplayHint)value.toInt();
216 QString AccountsService::realName()
const 218 auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_REAL_NAME);
219 return value.toString();
222 void AccountsService::setRealName(
const QString &realName)
224 setProperty(IFACE_ACCOUNTS_USER, PROP_REAL_NAME, realName);
227 QString AccountsService::email()
const 229 auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_EMAIL);
230 return value.toString();
233 void AccountsService::setEmail(
const QString &email)
235 setProperty(IFACE_ACCOUNTS_USER, PROP_EMAIL, email);
238 QStringList AccountsService::keymaps()
const 240 auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_INPUT_SOURCES);
241 QDBusArgument arg = value.value<QDBusArgument>();
242 StringMapList maps = qdbus_cast<StringMapList>(arg);
243 QStringList simplifiedMaps;
245 Q_FOREACH(
const StringMap &map, maps) {
246 Q_FOREACH(
const QString &entry, map) {
247 simplifiedMaps.append(entry);
251 if (!simplifiedMaps.isEmpty()) {
252 return simplifiedMaps;
255 return {QStringLiteral(
"us")};
258 void AccountsService::setKeymaps(
const QStringList &keymaps)
260 if (keymaps.isEmpty()) {
261 qWarning() <<
"Setting empty keymaps is not supported";
265 StringMapList result;
266 Q_FOREACH(
const QString &keymap, keymaps) {
268 map.insert(QStringLiteral(
"xkb"), keymap);
272 setProperty(IFACE_ACCOUNTS_USER, PROP_INPUT_SOURCES, QVariant::fromValue(result));
273 Q_EMIT keymapsChanged();
276 uint AccountsService::failedFingerprintLogins()
const 278 return getProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_FINGERPRINT_LOGINS).toUInt();
281 void AccountsService::setFailedFingerprintLogins(uint failedFingerprintLogins)
283 setProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_FINGERPRINT_LOGINS, failedFingerprintLogins);
286 uint AccountsService::failedLogins()
const 288 return getProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_LOGINS).toUInt();
291 void AccountsService::setFailedLogins(uint failedLogins)
293 setProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_LOGINS, failedLogins);
300 void AccountsService::emitChangedForProperty(
const QString &interface,
const QString &property)
302 QString signalName = m_properties[interface][property].signal;
303 QMetaObject::invokeMethod(
this, signalName.toUtf8().data());
306 QVariant AccountsService::getProperty(
const QString &interface,
const QString &property)
const 308 return m_properties[interface][property].value;
311 void AccountsService::setProperty(
const QString &interface,
const QString &property,
const QVariant &value)
313 if (m_properties[interface][property].value != value) {
314 m_properties[interface][property].value = value;
315 m_service->setUserPropertyAsync(m_user, interface, property, value);
316 emitChangedForProperty(interface, property);
320 void AccountsService::updateCache(
const QString &interface,
const QString &property,
const QVariant &value)
322 PropertyInfo &info = m_properties[interface][property];
324 if (info.proxyInterface) {
326 if (info.proxyConverter) {
327 finalValue = info.proxyConverter(value);
331 info.proxyInterface->asyncCall(info.proxyMethod, finalValue);
335 if (info.value != value) {
337 emitChangedForProperty(interface, property);
341 void AccountsService::updateProperty(
const QString &interface,
const QString &property)
343 QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
346 QDBusPendingCallWatcher *watcher =
new QDBusPendingCallWatcher(pendingReply,
this);
348 connect(watcher, &QDBusPendingCallWatcher::finished,
349 this, [
this, interface, property](QDBusPendingCallWatcher* watcher) {
351 QDBusPendingReply<QVariant> reply = *watcher;
352 watcher->deleteLater();
353 if (reply.isError()) {
354 qWarning() <<
"Failed to get '" <<
property <<
"' property:" << reply.error().message();
358 updateCache(interface, property, reply.value());
362 void AccountsService::updateAllProperties(
const QString &interface,
bool async)
364 QDBusPendingCall pendingReply = m_service->getAllPropertiesAsync(m_user,
366 QDBusPendingCallWatcher *watcher =
new QDBusPendingCallWatcher(pendingReply,
this);
368 connect(watcher, &QDBusPendingCallWatcher::finished,
369 this, [
this, interface](QDBusPendingCallWatcher* watcher) {
371 QDBusPendingReply< QHash<QString, QVariant> > reply = *watcher;
372 watcher->deleteLater();
373 if (reply.isError()) {
374 qWarning() <<
"Failed to get all properties for" <<
interface << ":" << reply.error().message();
378 auto valueHash = reply.value();
379 auto i = valueHash.constBegin();
380 while (i != valueHash.constEnd()) {
381 updateCache(interface, i.key(), i.value());
386 watcher->waitForFinished();
390 void AccountsService::registerProxy(const QString &interface, const QString &property, QDBusInterface *iface, const QString &method, ProxyConverter converter)
392 registerProperty(interface, property,
nullptr);
394 m_properties[interface][property].proxyInterface = iface;
395 m_properties[interface][property].proxyMethod = method;
396 m_properties[interface][property].proxyConverter = converter;
399 void AccountsService::registerProperty(
const QString &interface,
const QString &property,
const QString &signal)
401 m_properties[interface][property] = PropertyInfo();
402 m_properties[interface][property].signal = signal;
405 void AccountsService::onPropertiesChanged(
const QString &user,
const QString &interface,
const QStringList &changed)
407 if (m_user != user) {
411 auto propHash = m_properties.value(interface);
412 auto i = propHash.constBegin();
413 while (i != propHash.constEnd()) {
414 if (changed.contains(i.key())) {
415 updateProperty(interface, i.key());
421 void AccountsService::onMaybeChanged(
const QString &user)
423 if (m_user != user) {
428 auto propHash = m_properties.value(IFACE_ACCOUNTS_USER);
429 auto i = propHash.constBegin();
430 while (i != propHash.constEnd()) {
431 updateProperty(IFACE_ACCOUNTS_USER, i.key());
436 void AccountsService::refresh(
bool async)
438 auto i = m_properties.constBegin();
439 while (i != m_properties.constEnd()) {
440 updateAllProperties(i.key(), async);