Unity 8
AccountsService.cpp
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  */
18 
19 #include "AccountsService.h"
20 #include "AccountsServiceDBusAdaptor.h"
21 
22 #include <QFile>
23 #include <QStringList>
24 #include <QDebug>
25 
26 AccountsService::AccountsService(QObject* parent, const QString &user)
27  : QObject(parent),
28  m_service(new AccountsServiceDBusAdaptor(this)),
29  m_demoEdges(false),
30  m_enableLauncherWhileLocked(false),
31  m_enableIndicatorsWhileLocked(false),
32  m_statsWelcomeScreen(false),
33  m_passwordDisplayHint(Keyboard),
34  m_failedLogins(0),
35  m_hereEnabled(false),
36  m_hereLicensePath() // null means not set yet
37 {
38  connect(m_service, &AccountsServiceDBusAdaptor::propertiesChanged, this, &AccountsService::onPropertiesChanged);
39  connect(m_service, &AccountsServiceDBusAdaptor::maybeChanged, this, &AccountsService::onMaybeChanged);
40 
41  setUser(!user.isEmpty() ? user : QString::fromUtf8(qgetenv("USER")));
42 }
43 
44 QString AccountsService::user() const
45 {
46  return m_user;
47 }
48 
49 void AccountsService::setUser(const QString &user)
50 {
51  if (user.isEmpty() || m_user == user)
52  return;
53 
54  m_user = user;
55  Q_EMIT userChanged();
56 
57  updateDemoEdges(false);
58  updateEnableLauncherWhileLocked(false);
59  updateEnableIndicatorsWhileLocked(false);
60  updateBackgroundFile(false);
61  updateStatsWelcomeScreen(false);
62  updatePasswordDisplayHint(false);
63  updateFailedLogins(false);
64  updateHereEnabled(false);
65  updateHereLicensePath(false);
66 }
67 
68 bool AccountsService::demoEdges() const
69 {
70  return m_demoEdges;
71 }
72 
73 void AccountsService::setDemoEdges(bool demoEdges)
74 {
75  if (m_demoEdges != demoEdges) {
76  m_demoEdges = demoEdges;
77  m_service->setUserProperty(m_user, QStringLiteral("com.canonical.unity.AccountsService"), QStringLiteral("demo-edges"), demoEdges);
78 
79  Q_EMIT demoEdgesChanged();
80  }
81 }
82 
83 bool AccountsService::enableLauncherWhileLocked() const
84 {
85  return m_enableLauncherWhileLocked;
86 }
87 
88 bool AccountsService::enableIndicatorsWhileLocked() const
89 {
90  return m_enableIndicatorsWhileLocked;
91 }
92 
93 QString AccountsService::backgroundFile() const
94 {
95  return m_backgroundFile;
96 }
97 
98 bool AccountsService::statsWelcomeScreen() const
99 {
100  return m_statsWelcomeScreen;
101 }
102 
103 AccountsService::PasswordDisplayHint AccountsService::passwordDisplayHint() const
104 {
105  return m_passwordDisplayHint;
106 }
107 
108 bool AccountsService::hereEnabled() const
109 {
110  return m_hereEnabled;
111 }
112 
113 void AccountsService::setHereEnabled(bool enabled)
114 {
115  if (m_hereEnabled != enabled) {
116  m_hereEnabled = enabled;
117  m_service->setUserProperty(m_user, QStringLiteral("com.ubuntu.location.providers.here.AccountsService"), QStringLiteral("LicenseAccepted"), enabled);
118 
119  Q_EMIT hereEnabledChanged();
120  }
121 }
122 
123 QString AccountsService::hereLicensePath() const
124 {
125  return m_hereLicensePath;
126 }
127 
128 bool AccountsService::hereLicensePathValid() const
129 {
130  return !m_hereLicensePath.isNull();
131 }
132 
133 void AccountsService::updateDemoEdges(bool async)
134 {
135  QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
136  QStringLiteral("com.canonical.unity.AccountsService"),
137  QStringLiteral("demo-edges"));
138  QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
139 
140  connect(watcher, &QDBusPendingCallWatcher::finished,
141  this, [this](QDBusPendingCallWatcher* watcher) {
142 
143  QDBusPendingReply<QDBusVariant> reply = *watcher;
144  watcher->deleteLater();
145  if (reply.isError()) {
146  qWarning() << "Failed to get 'demo-edges' property - " << reply.error().message();
147  return;
148  }
149 
150  auto demoEdges = reply.value().variant().toBool();
151  if (m_demoEdges != demoEdges) {
152  m_demoEdges = demoEdges;
153  Q_EMIT demoEdgesChanged();
154  }
155  });
156  if (!async) {
157  watcher->waitForFinished();
158  delete watcher;
159  }
160 }
161 
162 void AccountsService::updateEnableLauncherWhileLocked(bool async)
163 {
164  QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
165  QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy"),
166  QStringLiteral("EnableLauncherWhileLocked"));
167  QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
168 
169  connect(watcher, &QDBusPendingCallWatcher::finished,
170  this, [this](QDBusPendingCallWatcher* watcher) {
171 
172  QDBusPendingReply<QVariant> reply = *watcher;
173  watcher->deleteLater();
174  if (reply.isError()) {
175  qWarning() << "Failed to get 'EnableLauncherWhileLocked' property - " << reply.error().message();
176  return;
177  }
178 
179  const bool enableLauncherWhileLocked = reply.value().toBool();
180  if (m_enableLauncherWhileLocked != enableLauncherWhileLocked) {
181  m_enableLauncherWhileLocked = enableLauncherWhileLocked;
182  Q_EMIT enableLauncherWhileLockedChanged();
183  }
184  });
185  if (!async) {
186  watcher->waitForFinished();
187  delete watcher;
188  }
189 }
190 
191 void AccountsService::updateEnableIndicatorsWhileLocked(bool async)
192 {
193  QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
194  QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy"),
195  QStringLiteral("EnableIndicatorsWhileLocked"));
196  QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
197 
198  connect(watcher, &QDBusPendingCallWatcher::finished,
199  this, [this](QDBusPendingCallWatcher* watcher) {
200 
201  QDBusPendingReply<QVariant> reply = *watcher;
202  watcher->deleteLater();
203  if (reply.isError()) {
204  qWarning() << "Failed to get 'EnableIndicatorsWhileLocked' property - " << reply.error().message();
205  return;
206  }
207 
208  const bool enableIndicatorsWhileLocked = reply.value().toBool();
209  if (m_enableIndicatorsWhileLocked != enableIndicatorsWhileLocked) {
210  m_enableIndicatorsWhileLocked = enableIndicatorsWhileLocked;
211  Q_EMIT enableIndicatorsWhileLockedChanged();
212  }
213  });
214  if (!async) {
215  watcher->waitForFinished();
216  delete watcher;
217  }
218 }
219 
220 void AccountsService::updateBackgroundFile(bool async)
221 {
222  QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
223  QStringLiteral("org.freedesktop.Accounts.User"),
224  QStringLiteral("BackgroundFile"));
225  QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
226 
227  connect(watcher, &QDBusPendingCallWatcher::finished,
228  this, [this](QDBusPendingCallWatcher* watcher) {
229 
230  QDBusPendingReply<QVariant> reply = *watcher;
231  watcher->deleteLater();
232  if (reply.isError()) {
233  qWarning() << "Failed to get 'BackgroundFile' property - " << reply.error().message();
234  return;
235  }
236 
237  const QString backgroundFile = reply.value().toString();
238  if (m_backgroundFile != backgroundFile) {
239  m_backgroundFile = backgroundFile;
240  Q_EMIT backgroundFileChanged();
241  }
242  });
243  if (!async) {
244  watcher->waitForFinished();
245  delete watcher;
246  }
247 }
248 
249 void AccountsService::updateStatsWelcomeScreen(bool async)
250 {
251  QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
252  QStringLiteral("com.ubuntu.touch.AccountsService.SecurityPrivacy"),
253  QStringLiteral("StatsWelcomeScreen"));
254  QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
255 
256  connect(watcher, &QDBusPendingCallWatcher::finished,
257  this, [this](QDBusPendingCallWatcher* watcher) {
258 
259  QDBusPendingReply<QVariant> reply = *watcher;
260  watcher->deleteLater();
261  if (reply.isError()) {
262  qWarning() << "Failed to get 'StatsWelcomeScreen' property - " << reply.error().message();
263  return;
264  }
265 
266  const bool statsWelcomeScreen = reply.value().toBool();
267  if (m_statsWelcomeScreen != statsWelcomeScreen) {
268  m_statsWelcomeScreen = statsWelcomeScreen;
269  Q_EMIT statsWelcomeScreenChanged();
270  }
271  });
272  if (!async) {
273  watcher->waitForFinished();
274  delete watcher;
275  }
276 }
277 
278 void AccountsService::updatePasswordDisplayHint(bool async)
279 {
280  QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
281  QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy"),
282  QStringLiteral("PasswordDisplayHint"));
283  QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
284 
285  connect(watcher, &QDBusPendingCallWatcher::finished,
286  this, [this](QDBusPendingCallWatcher* watcher) {
287 
288  QDBusPendingReply<QVariant> reply = *watcher;
289  watcher->deleteLater();
290  if (reply.isError()) {
291  qWarning() << "Failed to get 'PasswordDisplayHint' property - " << reply.error().message();
292  return;
293  }
294 
295  const PasswordDisplayHint passwordDisplayHint = (PasswordDisplayHint)reply.value().toInt();
296  if (m_passwordDisplayHint != passwordDisplayHint) {
297  m_passwordDisplayHint = passwordDisplayHint;
298  Q_EMIT passwordDisplayHintChanged();
299  }
300  });
301  if (!async) {
302  watcher->waitForFinished();
303  delete watcher;
304  }
305 }
306 
307 void AccountsService::updateFailedLogins(bool async)
308 {
309  QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
310  QStringLiteral("com.canonical.unity.AccountsService.Private"),
311  QStringLiteral("FailedLogins"));
312  QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
313 
314  connect(watcher, &QDBusPendingCallWatcher::finished,
315  this, [this](QDBusPendingCallWatcher* watcher) {
316 
317  QDBusPendingReply<QVariant> reply = *watcher;
318  watcher->deleteLater();
319  if (reply.isError()) {
320  qWarning() << "Failed to get 'FailedLogins' property - " << reply.error().message();
321  return;
322  }
323 
324  const uint failedLogins = reply.value().toUInt();
325  if (m_failedLogins != failedLogins) {
326  m_failedLogins = failedLogins;
327  Q_EMIT failedLoginsChanged();
328  }
329  });
330  if (!async) {
331  watcher->waitForFinished();
332  delete watcher;
333  }
334 }
335 
336 void AccountsService::updateHereEnabled(bool async)
337 {
338  QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
339  QStringLiteral("com.ubuntu.location.providers.here.AccountsService"),
340  QStringLiteral("LicenseAccepted"));
341  QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
342 
343  connect(watcher, &QDBusPendingCallWatcher::finished,
344  this, [this](QDBusPendingCallWatcher* watcher) {
345 
346  QDBusPendingReply<QVariant> reply = *watcher;
347  watcher->deleteLater();
348  if (reply.isError()) {
349  qWarning() << "Failed to get 'LicenseAccepted' property - " << reply.error().message();
350  return;
351  }
352 
353  const bool hereEnabled = reply.value().toBool();
354  if (m_hereEnabled != hereEnabled) {
355  m_hereEnabled = hereEnabled;
356  Q_EMIT hereEnabledChanged();
357  }
358  });
359  if (!async) {
360  watcher->waitForFinished();
361  delete watcher;
362  }
363 }
364 
365 void AccountsService::updateHereLicensePath(bool async)
366 {
367  QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
368  QStringLiteral("com.ubuntu.location.providers.here.AccountsService"),
369  QStringLiteral("LicenseBasePath"));
370  QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
371 
372  connect(watcher, &QDBusPendingCallWatcher::finished,
373  this, [this](QDBusPendingCallWatcher* watcher) {
374 
375  QDBusPendingReply<QVariant> reply = *watcher;
376  watcher->deleteLater();
377  if (reply.isError()) {
378  qWarning() << "Failed to get 'LicenseBasePath' property - " << reply.error().message();
379  return;
380  }
381 
382  QString hereLicensePath = reply.value().toString();
383  if (hereLicensePath.isEmpty() || !QFile::exists(hereLicensePath))
384  hereLicensePath = QLatin1String("");
385 
386  if (m_hereLicensePath.isNull() || m_hereLicensePath != hereLicensePath) {
387  m_hereLicensePath = hereLicensePath;
388  Q_EMIT hereLicensePathChanged();
389  }
390  });
391  if (!async) {
392  watcher->waitForFinished();
393  delete watcher;
394  }
395 }
396 
397 uint AccountsService::failedLogins() const
398 {
399  return m_failedLogins;
400 }
401 
402 void AccountsService::setFailedLogins(uint failedLogins)
403 {
404  if (m_failedLogins != failedLogins) {
405  m_failedLogins = failedLogins;
406  m_service->setUserProperty(m_user, QStringLiteral("com.canonical.unity.AccountsService.Private"), QStringLiteral("FailedLogins"), failedLogins);
407 
408  Q_EMIT failedLoginsChanged();
409  }
410 }
411 
412 void AccountsService::onPropertiesChanged(const QString &user, const QString &interface, const QStringList &changed)
413 {
414  if (m_user != user) {
415  return;
416  }
417 
418  if (interface == QLatin1String("com.canonical.unity.AccountsService")) {
419  if (changed.contains(QStringLiteral("demo-edges"))) {
420  updateDemoEdges();
421  }
422  } else if (interface == QLatin1String("com.canonical.unity.AccountsService.Private")) {
423  if (changed.contains(QStringLiteral("FailedLogins"))) {
424  updateFailedLogins();
425  }
426  } else if (interface == QLatin1String("com.ubuntu.touch.AccountsService.SecurityPrivacy")) {
427  if (changed.contains(QStringLiteral("StatsWelcomeScreen"))) {
428  updateStatsWelcomeScreen();
429  }
430  } else if (interface == QLatin1String("com.ubuntu.AccountsService.SecurityPrivacy")) {
431  if (changed.contains(QStringLiteral("PasswordDisplayHint"))) {
432  updatePasswordDisplayHint();
433  }
434  if (changed.contains(QStringLiteral("EnableLauncherWhileLocked"))) {
435  updateEnableLauncherWhileLocked();
436  }
437  if (changed.contains(QStringLiteral("EnableIndicatorsWhileLocked"))) {
438  updateEnableIndicatorsWhileLocked();
439  }
440  } else if (interface == QLatin1String("com.ubuntu.location.providers.here.AccountsService")) {
441  if (changed.contains(QStringLiteral("LicenseAccepted"))) {
442  updateHereEnabled();
443  }
444  if (changed.contains(QStringLiteral("LicenseBasePath"))) {
445  updateHereLicensePath();
446  }
447  }
448 }
449 
450 void AccountsService::onMaybeChanged(const QString &user)
451 {
452  if (m_user != user) {
453  return;
454  }
455 
456  // Standard properties might have changed
457  updateBackgroundFile();
458 }