on 75b8c19 help sign in
unity8/plugins/AccountsService/AccountsService.cpp
568 lines 21 kB history raw
1/*
2 * Copyright (C) 2013 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Author: Michael Terry <michael.terry@canonical.com>
17 */
19#include "AccountsService.h"
20#include "AccountsServiceDBusAdaptor.h"
22#include <QDBusInterface>
23#include <QFile>
24#include <QStringList>
25#include <QDebug>
27AccountsService::AccountsService(QObject* parent, const QString &user)
28 : QObject(parent),
29 m_service(new AccountsServiceDBusAdaptor(this)),
30 m_demoEdges(false),
31 m_demoEdgesCompleted(),
32 m_enableLauncherWhileLocked(false),
33 m_enableIndicatorsWhileLocked(false),
34 m_statsWelcomeScreen(false),
35 m_passwordDisplayHint(Keyboard),
36 m_failedLogins(0),
37 m_hereEnabled(false),
38 m_hereLicensePath() // null means not set yet
40 m_unityInput = new QDBusInterface(QStringLiteral("com.canonical.Unity.Input"),
41 QStringLiteral("/com/canonical/Unity/Input"),
42 QStringLiteral("com.canonical.Unity.Input"),
43 QDBusConnection::SM_BUSNAME(), this);
45 connect(m_service, &AccountsServiceDBusAdaptor::propertiesChanged, this, &AccountsService::onPropertiesChanged);
46 connect(m_service, &AccountsServiceDBusAdaptor::maybeChanged, this, &AccountsService::onMaybeChanged);
48 setUser(!user.isEmpty() ? user : QString::fromUtf8(qgetenv("USER")));
51QString AccountsService::user() const
53 return m_user;
56void AccountsService::setUser(const QString &user)
58 if (user.isEmpty() || m_user == user)
59 return;
61 m_user = user;
62 Q_EMIT userChanged();
64 updateDemoEdgesCompleted(false);
65 updateDemoEdges(false);
66 updateEnableLauncherWhileLocked(false);
67 updateEnableIndicatorsWhileLocked(false);
68 updateBackgroundFile(false);
69 updateMouseCursorSpeed();
70 updateTouchpadCursorSpeed();
71 updateStatsWelcomeScreen(false);
72 updatePasswordDisplayHint(false);
73 updateFailedLogins(false);
74 updateHereEnabled(false);
75 updateHereLicensePath(false);
78bool AccountsService::demoEdges() const
80 return m_demoEdges;
83void AccountsService::setDemoEdges(bool demoEdges)
85 if (m_demoEdges != demoEdges) {
86 m_demoEdges = demoEdges;
87 m_service->setUserPropertyAsync(m_user, QStringLiteral("com.canonical.unity.AccountsService"), QStringLiteral("demo-edges"), demoEdges);
89 Q_EMIT demoEdgesChanged();
90 }
93QStringList AccountsService::demoEdgesCompleted() const
95 return m_demoEdgesCompleted;
98void AccountsService::markDemoEdgeCompleted(const QString &edge)
100 if (!m_demoEdgesCompleted.contains(edge)) {
101 m_demoEdgesCompleted << edge;
102 m_service->setUserPropertyAsync(m_user, "com.canonical.unity.AccountsService", "DemoEdgesCompleted", m_demoEdgesCompleted);
104 Q_EMIT demoEdgesCompletedChanged();
105 }
108bool AccountsService::enableLauncherWhileLocked() const
110 return m_enableLauncherWhileLocked;
113bool AccountsService::enableIndicatorsWhileLocked() const
115 return m_enableIndicatorsWhileLocked;
118QString AccountsService::backgroundFile() const
120 return m_backgroundFile;
123bool AccountsService::statsWelcomeScreen() const
125 return m_statsWelcomeScreen;
128AccountsService::PasswordDisplayHint AccountsService::passwordDisplayHint() const
130 return m_passwordDisplayHint;
133bool AccountsService::hereEnabled() const
135 return m_hereEnabled;
138void AccountsService::setHereEnabled(bool enabled)
140 if (m_hereEnabled != enabled) {
141 m_hereEnabled = enabled;
142 m_service->setUserPropertyAsync(m_user, QStringLiteral("com.ubuntu.location.providers.here.AccountsService"), QStringLiteral("LicenseAccepted"), enabled);
144 Q_EMIT hereEnabledChanged();
145 }
148QString AccountsService::hereLicensePath() const
150 return m_hereLicensePath;
153bool AccountsService::hereLicensePathValid() const
155 return !m_hereLicensePath.isNull();
158void AccountsService::updateDemoEdges(bool async)
160 QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
161 QStringLiteral("com.canonical.unity.AccountsService"),
162 QStringLiteral("demo-edges"));
163 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
165 connect(watcher, &QDBusPendingCallWatcher::finished,
166 this, [this](QDBusPendingCallWatcher* watcher) {
168 QDBusPendingReply<QDBusVariant> reply = *watcher;
169 watcher->deleteLater();
170 if (reply.isError()) {
171 qWarning() << "Failed to get 'demo-edges' property - " << reply.error().message();
172 return;
173 }
175 auto demoEdges = reply.value().variant().toBool();
176 if (m_demoEdges != demoEdges) {
177 m_demoEdges = demoEdges;
178 Q_EMIT demoEdgesChanged();
179 }
180 });
181 if (!async) {
182 watcher->waitForFinished();
183 delete watcher;
184 }
187void AccountsService::updateDemoEdgesCompleted(bool async)
189 QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
190 "com.canonical.unity.AccountsService",
191 "DemoEdgesCompleted");
192 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
194 connect(watcher, &QDBusPendingCallWatcher::finished,
195 this, [this](QDBusPendingCallWatcher* watcher) {
197 QDBusPendingReply<QDBusVariant> reply = *watcher;
198 watcher->deleteLater();
199 if (reply.isError()) {
200 qWarning() << "Failed to get 'DemoEdgesCompleted' property - " << reply.error().message();
201 return;
202 }
204 auto demoEdgesCompleted = reply.value().variant().toStringList();
205 if (m_demoEdgesCompleted != demoEdgesCompleted) {
206 m_demoEdgesCompleted = demoEdgesCompleted;
207 Q_EMIT demoEdgesCompletedChanged();
208 }
209 });
210 if (!async) {
211 watcher->waitForFinished();
212 delete watcher;
213 }
216void AccountsService::updateEnableLauncherWhileLocked(bool async)
218 QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
219 QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy"),
220 QStringLiteral("EnableLauncherWhileLocked"));
221 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
223 connect(watcher, &QDBusPendingCallWatcher::finished,
224 this, [this](QDBusPendingCallWatcher* watcher) {
226 QDBusPendingReply<QVariant> reply = *watcher;
227 watcher->deleteLater();
228 if (reply.isError()) {
229 qWarning() << "Failed to get 'EnableLauncherWhileLocked' property - " << reply.error().message();
230 return;
231 }
233 const bool enableLauncherWhileLocked = reply.value().toBool();
234 if (m_enableLauncherWhileLocked != enableLauncherWhileLocked) {
235 m_enableLauncherWhileLocked = enableLauncherWhileLocked;
236 Q_EMIT enableLauncherWhileLockedChanged();
237 }
238 });
239 if (!async) {
240 watcher->waitForFinished();
241 delete watcher;
242 }
245void AccountsService::updateEnableIndicatorsWhileLocked(bool async)
247 QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
248 QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy"),
249 QStringLiteral("EnableIndicatorsWhileLocked"));
250 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
252 connect(watcher, &QDBusPendingCallWatcher::finished,
253 this, [this](QDBusPendingCallWatcher* watcher) {
255 QDBusPendingReply<QVariant> reply = *watcher;
256 watcher->deleteLater();
257 if (reply.isError()) {
258 qWarning() << "Failed to get 'EnableIndicatorsWhileLocked' property - " << reply.error().message();
259 return;
260 }
262 const bool enableIndicatorsWhileLocked = reply.value().toBool();
263 if (m_enableIndicatorsWhileLocked != enableIndicatorsWhileLocked) {
264 m_enableIndicatorsWhileLocked = enableIndicatorsWhileLocked;
265 Q_EMIT enableIndicatorsWhileLockedChanged();
266 }
267 });
268 if (!async) {
269 watcher->waitForFinished();
270 delete watcher;
271 }
274void AccountsService::updateBackgroundFile(bool async)
276 QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
277 QStringLiteral("org.freedesktop.Accounts.User"),
278 QStringLiteral("BackgroundFile"));
279 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
281 connect(watcher, &QDBusPendingCallWatcher::finished,
282 this, [this](QDBusPendingCallWatcher* watcher) {
284 QDBusPendingReply<QVariant> reply = *watcher;
285 watcher->deleteLater();
286 if (reply.isError()) {
287 qWarning() << "Failed to get 'BackgroundFile' property - " << reply.error().message();
288 return;
289 }
291 const QString backgroundFile = reply.value().toString();
292 if (m_backgroundFile != backgroundFile) {
293 m_backgroundFile = backgroundFile;
294 Q_EMIT backgroundFileChanged();
295 }
296 });
297 if (!async) {
298 watcher->waitForFinished();
299 delete watcher;
300 }
303void AccountsService::updateMouseCursorSpeed()
305 QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
306 QStringLiteral("com.ubuntu.AccountsService.Input"),
307 QStringLiteral("MouseCursorSpeed"));
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 'MouseCursorSpeed' property - " << reply.error().message();
317 return;
318 }
320 // Merely proxy this along to USC. We don't care about keeping a copy
321 // or exporting it internally.
322 m_unityInput->asyncCall(QStringLiteral("setMouseCursorSpeed"), reply.value());
323 });
326void AccountsService::updateTouchpadCursorSpeed()
328 QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
329 QStringLiteral("com.ubuntu.AccountsService.Input"),
330 QStringLiteral("TouchpadCursorSpeed"));
331 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
333 connect(watcher, &QDBusPendingCallWatcher::finished,
334 this, [this](QDBusPendingCallWatcher* watcher) {
336 QDBusPendingReply<QVariant> reply = *watcher;
337 watcher->deleteLater();
338 if (reply.isError()) {
339 qWarning() << "Failed to get 'TouchpadCursorSpeed' property - " << reply.error().message();
340 return;
341 }
343 // Merely proxy this along to USC. We don't care about keeping a copy
344 // or exporting it internally.
345 m_unityInput->asyncCall(QStringLiteral("setTouchpadCursorSpeed"), reply.value());
346 });
349void AccountsService::updateStatsWelcomeScreen(bool async)
351 QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
352 QStringLiteral("com.ubuntu.touch.AccountsService.SecurityPrivacy"),
353 QStringLiteral("StatsWelcomeScreen"));
354 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
356 connect(watcher, &QDBusPendingCallWatcher::finished,
357 this, [this](QDBusPendingCallWatcher* watcher) {
359 QDBusPendingReply<QVariant> reply = *watcher;
360 watcher->deleteLater();
361 if (reply.isError()) {
362 qWarning() << "Failed to get 'StatsWelcomeScreen' property - " << reply.error().message();
363 return;
364 }
366 const bool statsWelcomeScreen = reply.value().toBool();
367 if (m_statsWelcomeScreen != statsWelcomeScreen) {
368 m_statsWelcomeScreen = statsWelcomeScreen;
369 Q_EMIT statsWelcomeScreenChanged();
370 }
371 });
372 if (!async) {
373 watcher->waitForFinished();
374 delete watcher;
375 }
378void AccountsService::updatePasswordDisplayHint(bool async)
380 QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
381 QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy"),
382 QStringLiteral("PasswordDisplayHint"));
383 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
385 connect(watcher, &QDBusPendingCallWatcher::finished,
386 this, [this](QDBusPendingCallWatcher* watcher) {
388 QDBusPendingReply<QVariant> reply = *watcher;
389 watcher->deleteLater();
390 if (reply.isError()) {
391 qWarning() << "Failed to get 'PasswordDisplayHint' property - " << reply.error().message();
392 return;
393 }
395 const PasswordDisplayHint passwordDisplayHint = (PasswordDisplayHint)reply.value().toInt();
396 if (m_passwordDisplayHint != passwordDisplayHint) {
397 m_passwordDisplayHint = passwordDisplayHint;
398 Q_EMIT passwordDisplayHintChanged();
399 }
400 });
401 if (!async) {
402 watcher->waitForFinished();
403 delete watcher;
404 }
407void AccountsService::updateFailedLogins(bool async)
409 QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
410 QStringLiteral("com.canonical.unity.AccountsService.Private"),
411 QStringLiteral("FailedLogins"));
412 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
414 connect(watcher, &QDBusPendingCallWatcher::finished,
415 this, [this](QDBusPendingCallWatcher* watcher) {
417 QDBusPendingReply<QVariant> reply = *watcher;
418 watcher->deleteLater();
419 if (reply.isError()) {
420 qWarning() << "Failed to get 'FailedLogins' property - " << reply.error().message();
421 return;
422 }
424 const uint failedLogins = reply.value().toUInt();
425 if (m_failedLogins != failedLogins) {
426 m_failedLogins = failedLogins;
427 Q_EMIT failedLoginsChanged();
428 }
429 });
430 if (!async) {
431 watcher->waitForFinished();
432 delete watcher;
433 }
436void AccountsService::updateHereEnabled(bool async)
438 QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
439 QStringLiteral("com.ubuntu.location.providers.here.AccountsService"),
440 QStringLiteral("LicenseAccepted"));
441 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
443 connect(watcher, &QDBusPendingCallWatcher::finished,
444 this, [this](QDBusPendingCallWatcher* watcher) {
446 QDBusPendingReply<QVariant> reply = *watcher;
447 watcher->deleteLater();
448 if (reply.isError()) {
449 qWarning() << "Failed to get 'LicenseAccepted' property - " << reply.error().message();
450 return;
451 }
453 const bool hereEnabled = reply.value().toBool();
454 if (m_hereEnabled != hereEnabled) {
455 m_hereEnabled = hereEnabled;
456 Q_EMIT hereEnabledChanged();
457 }
458 });
459 if (!async) {
460 watcher->waitForFinished();
461 delete watcher;
462 }
465void AccountsService::updateHereLicensePath(bool async)
467 QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
468 QStringLiteral("com.ubuntu.location.providers.here.AccountsService"),
469 QStringLiteral("LicenseBasePath"));
470 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
472 connect(watcher, &QDBusPendingCallWatcher::finished,
473 this, [this](QDBusPendingCallWatcher* watcher) {
475 QDBusPendingReply<QVariant> reply = *watcher;
476 watcher->deleteLater();
477 if (reply.isError()) {
478 qWarning() << "Failed to get 'LicenseBasePath' property - " << reply.error().message();
479 return;
480 }
482 QString hereLicensePath = reply.value().toString();
483 if (hereLicensePath.isEmpty() || !QFile::exists(hereLicensePath))
484 hereLicensePath = QLatin1String("");
486 if (m_hereLicensePath.isNull() || m_hereLicensePath != hereLicensePath) {
487 m_hereLicensePath = hereLicensePath;
488 Q_EMIT hereLicensePathChanged();
489 }
490 });
491 if (!async) {
492 watcher->waitForFinished();
493 delete watcher;
494 }
497uint AccountsService::failedLogins() const
499 return m_failedLogins;
502void AccountsService::setFailedLogins(uint failedLogins)
504 if (m_failedLogins != failedLogins) {
505 m_failedLogins = failedLogins;
506 m_service->setUserPropertyAsync(m_user, QStringLiteral("com.canonical.unity.AccountsService.Private"), QStringLiteral("FailedLogins"), failedLogins);
508 Q_EMIT failedLoginsChanged();
509 }
512void AccountsService::onPropertiesChanged(const QString &user, const QString &interface, const QStringList &changed)
514 if (m_user != user) {
515 return;
516 }
518 if (interface == QLatin1String("com.canonical.unity.AccountsService")) {
519 if (changed.contains(QStringLiteral("demo-edges"))) {
520 updateDemoEdges();
521 }
522 if (changed.contains(QStringLiteral("DemoEdgesCompleted"))) {
523 updateDemoEdgesCompleted();
524 }
525 } else if (interface == QLatin1String("com.canonical.unity.AccountsService.Private")) {
526 if (changed.contains(QStringLiteral("FailedLogins"))) {
527 updateFailedLogins();
528 }
529 } else if (interface == QLatin1String("com.ubuntu.AccountsService.Input")) {
530 if (changed.contains(QStringLiteral("MouseCursorSpeed"))) {
531 updateMouseCursorSpeed();
532 }
533 if (changed.contains(QStringLiteral("TouchpadCursorSpeed"))) {
534 updateTouchpadCursorSpeed();
535 }
536 } else if (interface == QLatin1String("com.ubuntu.touch.AccountsService.SecurityPrivacy")) {
537 if (changed.contains(QStringLiteral("StatsWelcomeScreen"))) {
538 updateStatsWelcomeScreen();
539 }
540 } else if (interface == QLatin1String("com.ubuntu.AccountsService.SecurityPrivacy")) {
541 if (changed.contains(QStringLiteral("PasswordDisplayHint"))) {
542 updatePasswordDisplayHint();
543 }
544 if (changed.contains(QStringLiteral("EnableLauncherWhileLocked"))) {
545 updateEnableLauncherWhileLocked();
546 }
547 if (changed.contains(QStringLiteral("EnableIndicatorsWhileLocked"))) {
548 updateEnableIndicatorsWhileLocked();
549 }
550 } else if (interface == QLatin1String("com.ubuntu.location.providers.here.AccountsService")) {
551 if (changed.contains(QStringLiteral("LicenseAccepted"))) {
552 updateHereEnabled();
553 }
554 if (changed.contains(QStringLiteral("LicenseBasePath"))) {
555 updateHereLicensePath();
556 }
557 }
560void AccountsService::onMaybeChanged(const QString &user)
562 if (m_user != user) {
563 return;
564 }
566 // Standard properties might have changed
567 updateBackgroundFile();