@@ -24,17 +24,29 @@
24#include <QStringList>
24#include <QStringList>
25#include <QDebug>
25#include <QDebug>
27+#define IFACE_ACCOUNTS_USER QStringLiteral("org.freedesktop.Accounts.User")
28+#define IFACE_LOCATION_HERE QStringLiteral("com.ubuntu.location.providers.here.AccountsService")
29+#define IFACE_UBUNTU_INPUT QStringLiteral("com.ubuntu.AccountsService.Input")
30+#define IFACE_UBUNTU_SECURITY QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy")
31+#define IFACE_UBUNTU_SECURITY_OLD QStringLiteral("com.ubuntu.touch.AccountsService.SecurityPrivacy")
32+#define IFACE_UNITY QStringLiteral("com.canonical.unity.AccountsService")
33+#define IFACE_UNITY_PRIVATE QStringLiteral("com.canonical.unity.AccountsService.Private")
35+#define PROP_BACKGROUND_FILE QStringLiteral("BackgroundFile")
36+#define PROP_DEMO_EDGES QStringLiteral("demo-edges")
37+#define PROP_ENABLE_INDICATORS_WHILE_LOCKED QStringLiteral("EnableIndicatorsWhileLocked")
38+#define PROP_ENABLE_LAUNCHER_WHILE_LOCKED QStringLiteral("EnableLauncherWhileLocked")
39+#define PROP_FAILED_LOGINS QStringLiteral("FailedLogins")
40+#define PROP_LICENSE_ACCEPTED QStringLiteral("LicenseAccepted")
41+#define PROP_LICENSE_BASE_PATH QStringLiteral("LicenseBasePath")
42+#define PROP_MOUSE_CURSOR_SPEED QStringLiteral("MouseCursorSpeed")
43+#define PROP_PASSWORD_DISPLAY_HINT QStringLiteral("PasswordDisplayHint")
44+#define PROP_STATS_WELCOME_SCREEN QStringLiteral("StatsWelcomeScreen")
45+#define PROP_TOUCHPAD_CURSOR_SPEED QStringLiteral("TouchpadCursorSpeed")
27AccountsService::AccountsService(QObject* parent, const QString &user)
47AccountsService::AccountsService(QObject* parent, const QString &user)
28− : QObject(parent),
48+ : QObject(parent)
29− m_service(new AccountsServiceDBusAdaptor(this)),
49+ , m_service(new AccountsServiceDBusAdaptor(this))
31− m_enableLauncherWhileLocked(false),
32− m_enableIndicatorsWhileLocked(false),
33− m_statsWelcomeScreen(false),
34− m_passwordDisplayHint(Keyboard),
36− m_hereEnabled(false),
37− m_hereLicensePath() // null means not set yet
39 m_unityInput = new QDBusInterface(QStringLiteral("com.canonical.Unity.Input"),
51 m_unityInput = new QDBusInterface(QStringLiteral("com.canonical.Unity.Input"),
40 QStringLiteral("/com/canonical/Unity/Input"),
52 QStringLiteral("/com/canonical/Unity/Input"),
@@ -44,6 +56,21 @@ AccountsService::AccountsService(QObject* parent, const QString &user)
44 connect(m_service, &AccountsServiceDBusAdaptor::propertiesChanged, this, &AccountsService::onPropertiesChanged);
56 connect(m_service, &AccountsServiceDBusAdaptor::propertiesChanged, this, &AccountsService::onPropertiesChanged);
45 connect(m_service, &AccountsServiceDBusAdaptor::maybeChanged, this, &AccountsService::onMaybeChanged);
57 connect(m_service, &AccountsServiceDBusAdaptor::maybeChanged, this, &AccountsService::onMaybeChanged);
59+ registerProperty(IFACE_ACCOUNTS_USER, PROP_BACKGROUND_FILE, QStringLiteral("backgroundFileChanged"));
60+ registerProperty(IFACE_LOCATION_HERE, PROP_LICENSE_ACCEPTED, QStringLiteral("hereEnabledChanged"));
61+ registerProperty(IFACE_LOCATION_HERE, PROP_LICENSE_BASE_PATH, QStringLiteral("hereLicensePathChanged"));
62+ registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED, QStringLiteral("enableLauncherWhileLockedChanged"));
63+ registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_INDICATORS_WHILE_LOCKED, QStringLiteral("enableIndicatorsWhileLockedChanged"));
64+ registerProperty(IFACE_UBUNTU_SECURITY, PROP_PASSWORD_DISPLAY_HINT, QStringLiteral("passwordDisplayHintChanged"));
65+ registerProperty(IFACE_UBUNTU_SECURITY_OLD, PROP_STATS_WELCOME_SCREEN, QStringLiteral("statsWelcomeScreenChanged"));
66+ registerProperty(IFACE_UNITY, PROP_DEMO_EDGES, QStringLiteral("demoEdgesChanged"));
67+ registerProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_LOGINS, QStringLiteral("failedLoginsChanged"));
69+ registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_CURSOR_SPEED,
70+ m_unityInput, QStringLiteral("setMouseCursorSpeed"));
71+ registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_CURSOR_SPEED,
72+ m_unityInput, QStringLiteral("setTouchpadCursorSpeed"));
47 setUser(!user.isEmpty() ? user : QString::fromUtf8(qgetenv("USER")));
74 setUser(!user.isEmpty() ? user : QString::fromUtf8(qgetenv("USER")));
@@ -57,410 +84,193 @@ void AccountsService::setUser(const QString &user)
57 if (user.isEmpty() || m_user == user)
84 if (user.isEmpty() || m_user == user)
87+ bool wasEmpty = m_user.isEmpty();
60 m_user = user;
89 m_user = user;
61 Q_EMIT userChanged();
90 Q_EMIT userChanged();
63− updateDemoEdges(false);
92+ // Do the first update synchronously, as a cheap way to block rendering
64− updateEnableLauncherWhileLocked(false);
93+ // until we have the right values on bootup.
65− updateEnableIndicatorsWhileLocked(false);
94+ refresh(!wasEmpty);
66− updateBackgroundFile(false);
67− updateMouseCursorSpeed();
68− updateTouchpadCursorSpeed();
69− updateStatsWelcomeScreen(false);
70− updatePasswordDisplayHint(false);
71− updateFailedLogins(false);
72− updateHereEnabled(false);
73− updateHereLicensePath(false);
76bool AccountsService::demoEdges() const
97bool AccountsService::demoEdges() const
78− return m_demoEdges;
99+ auto value = getProperty(IFACE_UNITY, PROP_DEMO_EDGES);
100+ return value.toBool();
81void AccountsService::setDemoEdges(bool demoEdges)
103void AccountsService::setDemoEdges(bool demoEdges)
83− if (m_demoEdges != demoEdges) {
105+ setProperty(IFACE_UNITY, PROP_DEMO_EDGES, demoEdges);
84− m_demoEdges = demoEdges;
85− m_service->setUserPropertyAsync(m_user, QStringLiteral("com.canonical.unity.AccountsService"), QStringLiteral("demo-edges"), demoEdges);
87− Q_EMIT demoEdgesChanged();
91bool AccountsService::enableLauncherWhileLocked() const
108bool AccountsService::enableLauncherWhileLocked() const
93− return m_enableLauncherWhileLocked;
110+ auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED);
111+ return value.toBool();
96bool AccountsService::enableIndicatorsWhileLocked() const
114bool AccountsService::enableIndicatorsWhileLocked() const
98− return m_enableIndicatorsWhileLocked;
116+ auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_INDICATORS_WHILE_LOCKED);
117+ return value.toBool();
101QString AccountsService::backgroundFile() const
120QString AccountsService::backgroundFile() const
103− return m_backgroundFile;
122+ auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_BACKGROUND_FILE);
123+ return value.toString();
106bool AccountsService::statsWelcomeScreen() const
126bool AccountsService::statsWelcomeScreen() const
108− return m_statsWelcomeScreen;
128+ auto value = getProperty(IFACE_UBUNTU_SECURITY_OLD, PROP_STATS_WELCOME_SCREEN);
129+ return value.toBool();
111AccountsService::PasswordDisplayHint AccountsService::passwordDisplayHint() const
132AccountsService::PasswordDisplayHint AccountsService::passwordDisplayHint() const
113− return m_passwordDisplayHint;
134+ auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_PASSWORD_DISPLAY_HINT);
135+ return (PasswordDisplayHint)value.toInt();
116bool AccountsService::hereEnabled() const
138bool AccountsService::hereEnabled() const
118− return m_hereEnabled;
140+ auto value = getProperty(IFACE_LOCATION_HERE, PROP_LICENSE_ACCEPTED);
141+ return value.toBool();
121void AccountsService::setHereEnabled(bool enabled)
144void AccountsService::setHereEnabled(bool enabled)
123− if (m_hereEnabled != enabled) {
146+ setProperty(IFACE_LOCATION_HERE, PROP_LICENSE_ACCEPTED, enabled);
124− m_hereEnabled = enabled;
125− m_service->setUserPropertyAsync(m_user, QStringLiteral("com.ubuntu.location.providers.here.AccountsService"), QStringLiteral("LicenseAccepted"), enabled);
127− Q_EMIT hereEnabledChanged();
131QString AccountsService::hereLicensePath() const
149QString AccountsService::hereLicensePath() const
133− return m_hereLicensePath;
151+ auto value = getProperty(IFACE_LOCATION_HERE, PROP_LICENSE_BASE_PATH);
152+ QString hereLicensePath = value.toString();
153+ if (hereLicensePath.isEmpty() || !QFile::exists(hereLicensePath))
154+ hereLicensePath.clear();
155+ return hereLicensePath;
136bool AccountsService::hereLicensePathValid() const
158bool AccountsService::hereLicensePathValid() const
160+ auto value = getProperty(IFACE_LOCATION_HERE, PROP_LICENSE_BASE_PATH);
138− return !m_hereLicensePath.isNull();
161+ return !value.toString().isNull();
141−void AccountsService::updateDemoEdges(bool async)
164+uint AccountsService::failedLogins() const
143− QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
166+ return getProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_LOGINS).toUInt();
144− QStringLiteral("com.canonical.unity.AccountsService"),
145− QStringLiteral("demo-edges"));
146− QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
148− connect(watcher, &QDBusPendingCallWatcher::finished,
149− this, [this](QDBusPendingCallWatcher* watcher) {
151− QDBusPendingReply<QDBusVariant> reply = *watcher;
152− watcher->deleteLater();
153− if (reply.isError()) {
154− qWarning() << "Failed to get 'demo-edges' property - " << reply.error().message();
158− auto demoEdges = reply.value().variant().toBool();
159− if (m_demoEdges != demoEdges) {
160− m_demoEdges = demoEdges;
161− Q_EMIT demoEdgesChanged();
165− watcher->waitForFinished();
170−void AccountsService::updateEnableLauncherWhileLocked(bool async)
169+void AccountsService::setFailedLogins(uint failedLogins)
172− QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
171+ setProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_LOGINS, failedLogins);
173− QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy"),
174− QStringLiteral("EnableLauncherWhileLocked"));
175− QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
177− connect(watcher, &QDBusPendingCallWatcher::finished,
178− this, [this](QDBusPendingCallWatcher* watcher) {
180− QDBusPendingReply<QVariant> reply = *watcher;
181− watcher->deleteLater();
182− if (reply.isError()) {
183− qWarning() << "Failed to get 'EnableLauncherWhileLocked' property - " << reply.error().message();
187− const bool enableLauncherWhileLocked = reply.value().toBool();
188− if (m_enableLauncherWhileLocked != enableLauncherWhileLocked) {
189− m_enableLauncherWhileLocked = enableLauncherWhileLocked;
190− Q_EMIT enableLauncherWhileLockedChanged();
194− watcher->waitForFinished();
199−void AccountsService::updateEnableIndicatorsWhileLocked(bool async)
174+// ====================================================
200−{
175+// Everything below this line is generic helper methods
201− QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
176+// ====================================================
202− QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy"),
203− QStringLiteral("EnableIndicatorsWhileLocked"));
204− QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
206− connect(watcher, &QDBusPendingCallWatcher::finished,
178+void AccountsService::emitChangedForProperty(const QString &interface, const QString &property)
207− this, [this](QDBusPendingCallWatcher* watcher) {
209− QDBusPendingReply<QVariant> reply = *watcher;
210− watcher->deleteLater();
211− if (reply.isError()) {
212− qWarning() << "Failed to get 'EnableIndicatorsWhileLocked' property - " << reply.error().message();
216− const bool enableIndicatorsWhileLocked = reply.value().toBool();
217− if (m_enableIndicatorsWhileLocked != enableIndicatorsWhileLocked) {
218− m_enableIndicatorsWhileLocked = enableIndicatorsWhileLocked;
219− Q_EMIT enableIndicatorsWhileLockedChanged();
223− watcher->waitForFinished();
228−void AccountsService::updateBackgroundFile(bool async)
230− QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
180+ QString signalName = m_properties[interface][property].signal;
231− QStringLiteral("org.freedesktop.Accounts.User"),
181+ QMetaObject::invokeMethod(this, signalName.toUtf8().data());
232− QStringLiteral("BackgroundFile"));
233− QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
235− connect(watcher, &QDBusPendingCallWatcher::finished,
236− this, [this](QDBusPendingCallWatcher* watcher) {
238− QDBusPendingReply<QVariant> reply = *watcher;
239− watcher->deleteLater();
240− if (reply.isError()) {
241− qWarning() << "Failed to get 'BackgroundFile' property - " << reply.error().message();
245− const QString backgroundFile = reply.value().toString();
246− if (m_backgroundFile != backgroundFile) {
247− m_backgroundFile = backgroundFile;
248− Q_EMIT backgroundFileChanged();
252− watcher->waitForFinished();
257−void AccountsService::updateMouseCursorSpeed()
184+QVariant AccountsService::getProperty(const QString &interface, const QString &property) const
259− QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
186+ return m_properties[interface][property].value;
260− QStringLiteral("com.ubuntu.AccountsService.Input"),
261− QStringLiteral("MouseCursorSpeed"));
262− QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
264− connect(watcher, &QDBusPendingCallWatcher::finished,
265− this, [this](QDBusPendingCallWatcher* watcher) {
267− QDBusPendingReply<QVariant> reply = *watcher;
268− watcher->deleteLater();
269− if (reply.isError()) {
270− qWarning() << "Failed to get 'MouseCursorSpeed' property - " << reply.error().message();
274− // Merely proxy this along to USC. We don't care about keeping a copy
275− // or exporting it internally.
276− m_unityInput->asyncCall(QStringLiteral("setMouseCursorSpeed"), reply.value());
280−void AccountsService::updateTouchpadCursorSpeed()
189+void AccountsService::setProperty(const QString &interface, const QString &property, const QVariant &value)
282− QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
191+ if (m_properties[interface][property].value != value) {
283− QStringLiteral("com.ubuntu.AccountsService.Input"),
192+ m_properties[interface][property].value = value;
284− QStringLiteral("TouchpadCursorSpeed"));
193+ m_service->setUserPropertyAsync(m_user, interface, property, value);
285− QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
194+ emitChangedForProperty(interface, property);
287− connect(watcher, &QDBusPendingCallWatcher::finished,
288− this, [this](QDBusPendingCallWatcher* watcher) {
290− QDBusPendingReply<QVariant> reply = *watcher;
291− watcher->deleteLater();
292− if (reply.isError()) {
293− qWarning() << "Failed to get 'TouchpadCursorSpeed' property - " << reply.error().message();
297− // Merely proxy this along to USC. We don't care about keeping a copy
298− // or exporting it internally.
299− m_unityInput->asyncCall(QStringLiteral("setTouchpadCursorSpeed"), reply.value());
303−void AccountsService::updateStatsWelcomeScreen(bool async)
305− QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
306− QStringLiteral("com.ubuntu.touch.AccountsService.SecurityPrivacy"),
307− QStringLiteral("StatsWelcomeScreen"));
308− QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
310− connect(watcher, &QDBusPendingCallWatcher::finished,
311− this, [this](QDBusPendingCallWatcher* watcher) {
313− QDBusPendingReply<QVariant> reply = *watcher;
314− watcher->deleteLater();
315− if (reply.isError()) {
316− qWarning() << "Failed to get 'StatsWelcomeScreen' property - " << reply.error().message();
320− const bool statsWelcomeScreen = reply.value().toBool();
321− if (m_statsWelcomeScreen != statsWelcomeScreen) {
322− m_statsWelcomeScreen = statsWelcomeScreen;
323− Q_EMIT statsWelcomeScreenChanged();
327− watcher->waitForFinished();
332−void AccountsService::updatePasswordDisplayHint(bool async)
198+void AccountsService::updateCache(const QString &interface, const QString &property, const QVariant &value)
334− QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
200+ PropertyInfo &info = m_properties[interface][property];
335− QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy"),
336− QStringLiteral("PasswordDisplayHint"));
337− QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
339− connect(watcher, &QDBusPendingCallWatcher::finished,
340− this, [this](QDBusPendingCallWatcher* watcher) {
342− QDBusPendingReply<QVariant> reply = *watcher;
202+ if (info.proxyInterface) {
343− watcher->deleteLater();
203+ info.proxyInterface->asyncCall(info.proxyMethod, value);
344− if (reply.isError()) {
204+ return; // don't bother saving a copy
345− qWarning() << "Failed to get 'PasswordDisplayHint' property - " << reply.error().message();
349− const PasswordDisplayHint passwordDisplayHint = (PasswordDisplayHint)reply.value().toInt();
350− if (m_passwordDisplayHint != passwordDisplayHint) {
351− m_passwordDisplayHint = passwordDisplayHint;
352− Q_EMIT passwordDisplayHintChanged();
356− watcher->waitForFinished();
361−void AccountsService::updateFailedLogins(bool async)
363− QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
364− QStringLiteral("com.canonical.unity.AccountsService.Private"),
365− QStringLiteral("FailedLogins"));
366− QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
368− connect(watcher, &QDBusPendingCallWatcher::finished,
369− this, [this](QDBusPendingCallWatcher* watcher) {
371− QDBusPendingReply<QVariant> reply = *watcher;
372− watcher->deleteLater();
373− if (reply.isError()) {
374− qWarning() << "Failed to get 'FailedLogins' property - " << reply.error().message();
378− const uint failedLogins = reply.value().toUInt();
207+ if (info.value != value) {
379− if (m_failedLogins != failedLogins) {
208+ info.value = value;
380− m_failedLogins = failedLogins;
209+ emitChangedForProperty(interface, property);
381− Q_EMIT failedLoginsChanged();
385− watcher->waitForFinished();
390−void AccountsService::updateHereEnabled(bool async)
213+void AccountsService::updateProperty(const QString &interface, const QString &property)
392 QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
215 QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
393− QStringLiteral("com.ubuntu.location.providers.here.AccountsService"),
216+ interface,
394− QStringLiteral("LicenseAccepted"));
217+ property);
395 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
218 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
397 connect(watcher, &QDBusPendingCallWatcher::finished,
220 connect(watcher, &QDBusPendingCallWatcher::finished,
398− this, [this](QDBusPendingCallWatcher* watcher) {
221+ this, [this, interface, property](QDBusPendingCallWatcher* watcher) {
400 QDBusPendingReply<QVariant> reply = *watcher;
223 QDBusPendingReply<QVariant> reply = *watcher;
401 watcher->deleteLater();
224 watcher->deleteLater();
402 if (reply.isError()) {
225 if (reply.isError()) {
403− qWarning() << "Failed to get 'LicenseAccepted' property - " << reply.error().message();
226+ qWarning() << "Failed to get '" << property << "' property:" << reply.error().message();
407− const bool hereEnabled = reply.value().toBool();
230+ updateCache(interface, property, reply.value());
408− if (m_hereEnabled != hereEnabled) {
409− m_hereEnabled = hereEnabled;
410− Q_EMIT hereEnabledChanged();
414− watcher->waitForFinished();
419−void AccountsService::updateHereLicensePath(bool async)
234+void AccountsService::updateAllProperties(const QString &interface, bool async)
421− QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
236+ QDBusPendingCall pendingReply = m_service->getAllPropertiesAsync(m_user,
422− QStringLiteral("com.ubuntu.location.providers.here.AccountsService"),
237+ interface);
423− QStringLiteral("LicenseBasePath"));
424 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
238 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
426 connect(watcher, &QDBusPendingCallWatcher::finished,
240 connect(watcher, &QDBusPendingCallWatcher::finished,
427− this, [this](QDBusPendingCallWatcher* watcher) {
241+ this, [this, interface](QDBusPendingCallWatcher* watcher) {
429− QDBusPendingReply<QVariant> reply = *watcher;
243+ QDBusPendingReply< QHash<QString, QVariant> > reply = *watcher;
430 watcher->deleteLater();
244 watcher->deleteLater();
431 if (reply.isError()) {
245 if (reply.isError()) {
432− qWarning() << "Failed to get 'LicenseBasePath' property - " << reply.error().message();
246+ qWarning() << "Failed to get all properties for" << interface << ":" << reply.error().message();
436− QString hereLicensePath = reply.value().toString();
250+ auto valueHash = reply.value();
437− if (hereLicensePath.isEmpty() || !QFile::exists(hereLicensePath))
251+ auto i = valueHash.constBegin();
438− hereLicensePath = QLatin1String("");
252+ while (i != valueHash.constEnd()) {
439−
253+ updateCache(interface, i.key(), i.value());
440− if (m_hereLicensePath.isNull() || m_hereLicensePath != hereLicensePath) {
254+ ++i;
441− m_hereLicensePath = hereLicensePath;
442− Q_EMIT hereLicensePathChanged();
445 if (!async) {
257 if (!async) {
446 watcher->waitForFinished();
258 watcher->waitForFinished();
451−uint AccountsService::failedLogins() const
262+void AccountsService::registerProxy(const QString &interface, const QString &property, QDBusInterface *iface, const QString &method)
453− return m_failedLogins;
264+ registerProperty(interface, property, nullptr);
266+ m_properties[interface][property].proxyInterface = iface;
267+ m_properties[interface][property].proxyMethod = method;
456−void AccountsService::setFailedLogins(uint failedLogins)
270+void AccountsService::registerProperty(const QString &interface, const QString &property, const QString &signal)
458− if (m_failedLogins != failedLogins) {
272+ m_properties[interface][property] = PropertyInfo();
459− m_failedLogins = failedLogins;
273+ m_properties[interface][property].signal = signal;
460− m_service->setUserPropertyAsync(m_user, QStringLiteral("com.canonical.unity.AccountsService.Private"), QStringLiteral("FailedLogins"), failedLogins);
462− Q_EMIT failedLoginsChanged();
466void AccountsService::onPropertiesChanged(const QString &user, const QString &interface, const QStringList &changed)
276void AccountsService::onPropertiesChanged(const QString &user, const QString &interface, const QStringList &changed)
@@ -469,42 +279,13 @@ void AccountsService::onPropertiesChanged(const QString &user, const QString &in
472− if (interface == QLatin1String("com.canonical.unity.AccountsService")) {
282+ auto propHash = m_properties.value(interface);
473− if (changed.contains(QStringLiteral("demo-edges"))) {
283+ auto i = propHash.constBegin();
474− updateDemoEdges();
284+ while (i != propHash.constEnd()) {
476− } else if (interface == QLatin1String("com.canonical.unity.AccountsService.Private")) {
477− if (changed.contains(QStringLiteral("FailedLogins"))) {
478− updateFailedLogins();
480− } else if (interface == QLatin1String("com.ubuntu.AccountsService.Input")) {
481− if (changed.contains(QStringLiteral("MouseCursorSpeed"))) {
482− updateMouseCursorSpeed();
484− if (changed.contains(QStringLiteral("TouchpadCursorSpeed"))) {
485− updateTouchpadCursorSpeed();
487− } else if (interface == QLatin1String("com.ubuntu.touch.AccountsService.SecurityPrivacy")) {
488− if (changed.contains(QStringLiteral("StatsWelcomeScreen"))) {
489− updateStatsWelcomeScreen();
491− } else if (interface == QLatin1String("com.ubuntu.AccountsService.SecurityPrivacy")) {
492− if (changed.contains(QStringLiteral("PasswordDisplayHint"))) {
493− updatePasswordDisplayHint();
495− if (changed.contains(QStringLiteral("EnableLauncherWhileLocked"))) {
285+ if (changed.contains(i.key())) {
496− updateEnableLauncherWhileLocked();
286+ updateProperty(interface, i.key());
498− if (changed.contains(QStringLiteral("EnableIndicatorsWhileLocked"))) {
499− updateEnableIndicatorsWhileLocked();
501− } else if (interface == QLatin1String("com.ubuntu.location.providers.here.AccountsService")) {
502− if (changed.contains(QStringLiteral("LicenseAccepted"))) {
503− updateHereEnabled();
505− if (changed.contains(QStringLiteral("LicenseBasePath"))) {
506− updateHereLicensePath();
@@ -514,6 +295,20 @@ void AccountsService::onMaybeChanged(const QString &user)
517− // Standard properties might have changed
298+ // Any of the standard properties might have changed!
518− updateBackgroundFile();
299+ auto propHash = m_properties.value(IFACE_ACCOUNTS_USER);
300+ auto i = propHash.constBegin();
301+ while (i != propHash.constEnd()) {
302+ updateProperty(IFACE_ACCOUNTS_USER, i.key());
307+void AccountsService::refresh(bool async)
309+ auto i = m_properties.constBegin();
310+ while (i != m_properties.constEnd()) {
311+ updateAllProperties(i.key(), async);