on xenial help sign in
Watch AccountsService for changes to the user's real name. This was preventing us from noticing when the user set their name in the welcome wizard.

Approved by: Albert Astals Cid

commit1fee4d1e39049feede6eeed6e6f5368f7829756e authorMichael Terry <michael.terry@canonical.com> dateThu 10 Mar 2016, 22:42 (11 years ago) parent8391b0adb71975
9 files changed+198−50
plugins/IntegratedLightDM/liblightdm/CMakeLists.txt+16−3 plugins/IntegratedLightDM/liblightdm/UsersModel.cpp+4−18 plugins/IntegratedLightDM/liblightdm/UsersModel.h+1−1 plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp+43−9 plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.h+15−3 tests/mocks/IntegratedLightDM/liblightdm/UsersModel.cpp−14 tests/plugins/AccountsService/PropertiesServer.cpp+3−2 tests/plugins/IntegratedLightDM/CMakeLists.txt+25 tests/plugins/IntegratedLightDM/integrated.cpp+91
plugins/IntegratedLightDM/liblightdm/CMakeLists.txt+16−3
@@ -5,13 +5,16 @@ set(LibLightDM_SOURCES
55 UsersModel.cpp
66 GreeterPrivate.cpp
77 UsersModelPrivate.cpp
8+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsServiceDBusAdaptor.cpp
89 ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
910 )
1011
1112add_library(integratedLightDM STATIC ${LibLightDM_SOURCES})
13+add_library(integratedLightDMSession STATIC ${LibLightDM_SOURCES})
1214add_library(MockLightDM-demo-shared SHARED ${LibLightDM_SOURCES})
1315
1416include_directories(
17+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService
1518 ${CMAKE_CURRENT_BINARY_DIR}
1619 ${GLIB_INCLUDE_DIRS}
1720 ${LIBUSERMETRICSOUTPUT_INCLUDE_DIRS}
@@ -22,17 +25,27 @@ target_link_libraries(integratedLightDM
2225 ${LIBUSERMETRICSOUTPUT_LDFLAGS}
2326 -lpam
2427)
28+target_link_libraries(integratedLightDMSession
29+ ${GLIB_LIBRARIES}
30+ ${LIBUSERMETRICSOUTPUT_LDFLAGS}
31+ -lpam
32+)
2533target_link_libraries(MockLightDM-demo-shared
2634 ${GLIB_LIBRARIES}
2735 ${LIBUSERMETRICSOUTPUT_LDFLAGS}
2836 -lpam
2937)
3038
31−qt5_use_modules(integratedLightDM Concurrent Gui)
32−qt5_use_modules(MockLightDM-demo-shared Concurrent Gui)
39+qt5_use_modules(integratedLightDM Concurrent DBus Gui)
40+qt5_use_modules(integratedLightDMSession Concurrent DBus Gui)
41+qt5_use_modules(MockLightDM-demo-shared Concurrent DBus Gui)
3342
34−set_target_properties(integratedLightDM PROPERTIES COMPILE_FLAGS -fPIC)
43+set_target_properties(integratedLightDM PROPERTIES
44+ COMPILE_FLAGS "-DSM_BUSNAME=systemBus -fPIC")
45+set_target_properties(integratedLightDMSession PROPERTIES
46+ COMPILE_FLAGS "-DSM_BUSNAME=sessionBus -fPIC")
3547set_target_properties(MockLightDM-demo-shared PROPERTIES
48+ COMPILE_FLAGS "-DSM_BUSNAME=systemBus"
3649 OUTPUT_NAME lightdm-qt5-2)
3750
3851install(TARGETS MockLightDM-demo-shared
plugins/IntegratedLightDM/liblightdm/UsersModel.cpp+4−18
@@ -54,24 +54,10 @@ UsersModel::UsersModel(QObject *parent) :
5454 roles[ImagePathRole] = "imagePath";
5555 setRoleNames(roles);
5656
57− // Now modify our mock user backgrounds
58− QDir bgdir = QDir(QStringLiteral("/usr/share/demo-assets/shell/backgrounds/"));
59− QStringList backgrounds = bgdir.entryList(QDir::Files | QDir::NoDotAndDotDot);
60−
61− for (int i = 0, j = 0; i < d->entries.size(); i++) {
62− Entry &entry = d->entries[i];
63− if (entry.background.isNull() && !backgrounds.isEmpty()) {
64− entry.background = bgdir.filePath(backgrounds[j++]);
65− if (j >= backgrounds.length()) {
66− j = 0;
67− }
68− }
69− }
70−}
71−
72−UsersModel::~UsersModel()
73−{
74− delete d_ptr;
57+ connect(d_ptr, &UsersModelPrivate::dataChanged, this, [this](int i) {
58+ QModelIndex index = createIndex(i, 0);
59+ Q_EMIT dataChanged(index, index);
60+ });
7561}
7662
7763int UsersModel::rowCount(const QModelIndex &parent) const
plugins/IntegratedLightDM/liblightdm/UsersModel.h+1−1
@@ -41,7 +41,7 @@ class Q_DECL_EXPORT UsersModel : public QAbstractListModel
4141
4242public:
4343 explicit UsersModel(QObject *parent = 0);
44− virtual ~UsersModel();
44+ virtual ~UsersModel() = default;
4545
4646 enum UserModelRoles {NameRole = Qt::UserRole,
4747 RealNameRole,
plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp+43−9
@@ -18,7 +18,11 @@
1818
1919#include "UsersModelPrivate.h"
2020
21+#include "AccountsServiceDBusAdaptor.h"
22+#include "UsersModel.h"
23+
2124#include <glib.h>
25+#include <QDebug>
2226#include <QDir>
2327#include <QSettings>
2428#include <QStringList>
@@ -27,7 +31,9 @@ namespace QLightDM
2731{
2832
2933UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
30− : q_ptr(parent)
34+ : QObject(parent),
35+ q_ptr(parent),
36+ m_service(new AccountsServiceDBusAdaptor(this))
3137{
3238 QFileInfo demoFile(QDir::homePath() + "/.unity8-greeter-demo");
3339 QString currentUser = g_get_user_name();
@@ -43,15 +49,43 @@ UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
4349 entries.append({user, name, 0, 0, false, false, 0, 0});
4450 }
4551 } else {
46− // If we were using the actual liblightdm, we could just ask it
47− // for the user's real name. But we aren't. We *should* ask
48− // AccountsService for the real name, like liblightdm does internally,
49− // but this is close enough since AS and passwd are always in sync.
50− QString realName = QString::fromUtf8(g_get_real_name()); // gets name from passwd entry
51− if (realName == QStringLiteral("Unknown")) { // glib doesn't translate this string
52− realName.clear();
52+ entries.append({currentUser, 0, 0, 0, false, false, 0, 0});
53+
54+ connect(m_service, &AccountsServiceDBusAdaptor::maybeChanged,
55+ this, [this](const QString &user) {
56+ if (user == entries[0].username) {
57+ updateName(true);
58+ }
59+ });
60+ updateName(false);
61+ }
62+}
63+
64+void UsersModelPrivate::updateName(bool async)
65+{
66+ auto pendingReply = m_service->getUserPropertyAsync(entries[0].username,
67+ QStringLiteral("org.freedesktop.Accounts.User"),
68+ QStringLiteral("RealName"));
69+ auto *watcher = new QDBusPendingCallWatcher(pendingReply, this);
70+
71+ connect(watcher, &QDBusPendingCallWatcher::finished,
72+ this, [this](QDBusPendingCallWatcher* watcher) {
73+
74+ QDBusPendingReply<QVariant> reply = *watcher;
75+ watcher->deleteLater();
76+ if (reply.isError()) {
77+ qWarning() << "Failed to get 'RealName' property - " << reply.error().message();
78+ return;
79+ }
80+
81+ const QString realName = reply.value().toString();
82+ if (entries[0].real_name != realName) {
83+ entries[0].real_name = realName;
84+ Q_EMIT dataChanged(0);
5385 }
54− entries.append({currentUser, realName, 0, 0, false, false, 0, 0});
86+ });
87+ if (!async) {
88+ watcher->waitForFinished();
5589 }
5690}
5791
plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.h+15−3
@@ -19,8 +19,11 @@
1919#ifndef UNITY_MOCK_USERSMODEL_PRIVATE_H
2020#define UNITY_MOCK_USERSMODEL_PRIVATE_H
2121
22−#include <QtCore/QList>
23−#include <QtCore/QString>
22+#include <QList>
23+#include <QObject>
24+#include <QString>
25+
26+class AccountsServiceDBusAdaptor;
2427
2528namespace QLightDM
2629{
@@ -39,19 +42,28 @@ public:
3942 QString infographic;
4043};
4144
42−class UsersModelPrivate
45+class UsersModelPrivate : public QObject
4346{
47+ Q_OBJECT
48+
4449public:
4550 explicit UsersModelPrivate(UsersModel *parent = 0);
4651 virtual ~UsersModelPrivate() = default;
4752
4853 QList<Entry> entries;
4954
55+Q_SIGNALS:
56+ void dataChanged(int);
57+
5058protected:
5159 UsersModel * const q_ptr;
5260
5361private:
5462 Q_DECLARE_PUBLIC(UsersModel)
63+
64+ void updateName(bool async);
65+
66+ AccountsServiceDBusAdaptor *m_service;
5567};
5668
5769}
tests/mocks/IntegratedLightDM/liblightdm/UsersModel.cpp−14
@@ -47,20 +47,6 @@ UsersModel::UsersModel(QObject *parent) :
4747 roles[HasMessagesRole] = "hasMessages";
4848 roles[ImagePathRole] = "imagePath";
4949 setRoleNames(roles);
50−
51− // Now modify our mock user backgrounds
52− QDir bgdir = QDir("/usr/share/demo-assets/shell/backgrounds/");
53− QStringList backgrounds = bgdir.entryList(QDir::Files | QDir::NoDotAndDotDot);
54−
55− for (int i = 0, j = 0; i < d->entries.size(); i++) {
56− Entry &entry = d->entries[i];
57− if (entry.background.isNull() && !backgrounds.isEmpty()) {
58− entry.background = bgdir.filePath(backgrounds[j++]);
59− if (j >= backgrounds.length()) {
60− j = 0;
61− }
62− }
63− }
6450}
6551
6652UsersModel::~UsersModel()
tests/plugins/AccountsService/PropertiesServer.cpp+3−2
@@ -67,8 +67,8 @@ void PropertiesServer::Set(const QString &interface, const QString &property, co
6767
6868 oldValue = newValue;
6969
70− // Special case for Background file.
71− if (interface == "org.freedesktop.Accounts.User" && property == "BackgroundFile") {
70+ // Special case for user properties.
71+ if (interface == "org.freedesktop.Accounts.User") {
7272 Q_EMIT Changed();
7373 } else {
7474 QVariantMap propertyChanges;
@@ -99,4 +99,5 @@ void PropertiesServer::Reset()
9999 m_properties["com.ubuntu.location.providers.here.AccountsService"]["LicenseAccepted"] = false;
100100 m_properties["com.ubuntu.location.providers.here.AccountsService"]["LicenseBasePath"] = "";
101101 m_properties["org.freedesktop.Accounts.User"]["BackgroundFile"] = "";
102+ m_properties["org.freedesktop.Accounts.User"]["RealName"] = "";
102103}
tests/plugins/IntegratedLightDM/CMakeLists.txt+25
@@ -65,3 +65,28 @@ add_unity8_uitest(GreeterUsers GreeterUsersModelTestExec
6565 DEPENDS MockLightDM
6666 LIGHTDM
6767 )
68+
69+add_executable(GreeterIntegratedTestExec
70+ integrated.cpp
71+ )
72+qt5_use_modules(GreeterIntegratedTestExec Core DBus Quick Test)
73+target_link_libraries(GreeterIntegratedTestExec
74+ ${GLIB_LIBRARIES}
75+ integratedLightDMSession
76+ )
77+target_include_directories(GreeterIntegratedTestExec PUBLIC
78+ ${GLIB_INCLUDE_DIRS}
79+ ${CMAKE_SOURCE_DIR}/plugins/IntegratedLightDM/liblightdm
80+ )
81+add_unity8_unittest(GreeterIntegrated dbus-test-runner
82+ ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/plugins/IntegratedLightDM/liblightdm/
83+ ARG_PREFIX "--parameter"
84+ ARGS
85+ --task $<TARGET_FILE:mock-server>
86+ --task-name server
87+ --ignore-return
88+ --task $<TARGET_FILE:GreeterIntegratedTestExec>
89+ --task-name client
90+ --wait-for org.freedesktop.Accounts
91+ DEPENDS integratedLightDMSession
92+ )
tests/plugins/IntegratedLightDM/integrated.cppnew file+91
@@ -0,0 +1,91 @@
1+/*
2+ * Copyright (C) 2016 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+
17+#include "UsersModel.h"
18+
19+#include <glib.h>
20+#include <QDBusInterface>
21+#include <QDBusReply>
22+#include <QtTest>
23+
24+class GreeterIntegratedTest : public QObject
25+{
26+ Q_OBJECT
27+
28+private Q_SLOTS:
29+
30+ void init()
31+ {
32+ m_accounts = new QDBusInterface(QStringLiteral("org.freedesktop.Accounts"),
33+ QStringLiteral("/org/freedesktop/Accounts"),
34+ QStringLiteral("org.freedesktop.Accounts"),
35+ QDBusConnection::sessionBus());
36+ QDBusReply<bool> addReply = m_accounts->call(QStringLiteral("AddUser"),
37+ g_get_user_name());
38+ QVERIFY(addReply.isValid());
39+ QCOMPARE(addReply.value(), true);
40+
41+ m_user = new QDBusInterface(QStringLiteral("org.freedesktop.Accounts"),
42+ QStringLiteral("/%1").arg(g_get_user_name()),
43+ QStringLiteral("org.freedesktop.DBus.Properties"),
44+ QDBusConnection::sessionBus());
45+
46+ m_model = new QLightDM::UsersModel();
47+ QVERIFY(m_model);
48+ }
49+
50+ void cleanup()
51+ {
52+ QDBusReply<bool> addReply = m_accounts->call(QStringLiteral("RemoveUser"),
53+ g_get_user_name());
54+ QVERIFY(addReply.isValid());
55+ QCOMPARE(addReply.value(), true);
56+
57+ delete m_model;
58+ delete m_accounts;
59+ delete m_user;
60+ }
61+
62+ void testWatchRealName()
63+ {
64+ auto index = m_model->index(0, 0);
65+
66+ QCOMPARE(m_model->data(index, QLightDM::UsersModel::RealNameRole).toString(),
67+ QStringLiteral(""));
68+
69+ // The real AccountsService doesn't let you set via dbus properties. You
70+ // have to call SetRealName instead (so that they can protect the call
71+ // via policykit). But our test server does let us.
72+ QVariant wrapped = QVariant::fromValue(QDBusVariant(QStringLiteral("Test User")));
73+ QDBusReply<void> reply = m_user->call(QStringLiteral("Set"),
74+ QStringLiteral("org.freedesktop.Accounts.User"),
75+ QStringLiteral("RealName"),
76+ wrapped);
77+ QVERIFY(reply.isValid());
78+
79+ QTRY_COMPARE(m_model->data(index, QLightDM::UsersModel::RealNameRole).toString(),
80+ QStringLiteral("Test User"));
81+ }
82+
83+private:
84+ QLightDM::UsersModel *m_model;
85+ QDBusInterface *m_accounts;
86+ QDBusInterface *m_user;
87+};
88+
89+QTEST_MAIN(GreeterIntegratedTest)
90+
91+#include "integrated.moc"