2 * Copyright (C) 2013-2016 Canonical, Ltd.
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.
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.
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/>.
17#include "AccountsService.h"
18#include "AccountsServiceDBusAdaptor.h"
20#include <QDBusInterface>
27#include <gio/gio.h> // for gsettings
29#define IFACE_ACCOUNTS_USER QStringLiteral("org.freedesktop.Accounts.User")
30#define IFACE_LOCATION_HERE QStringLiteral("com.ubuntu.location.providers.here.AccountsService")
31#define IFACE_UBUNTU_INPUT QStringLiteral("com.ubuntu.AccountsService.Input")
32#define IFACE_UBUNTU_SECURITY QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy")
33#define IFACE_UBUNTU_SECURITY_OLD QStringLiteral("com.ubuntu.touch.AccountsService.SecurityPrivacy")
34#define IFACE_UNITY QStringLiteral("com.canonical.unity.AccountsService")
35#define IFACE_UNITY_PRIVATE QStringLiteral("com.canonical.unity.AccountsService.Private")
37#define PROP_BACKGROUND_FILE QStringLiteral("BackgroundFile")
38#define PROP_DEMO_EDGES QStringLiteral("demo-edges")
39#define PROP_DEMO_EDGES_COMPLETED QStringLiteral("DemoEdgesCompleted")
40#define PROP_EMAIL QStringLiteral("Email")
41#define PROP_ENABLE_FINGERPRINT_IDENTIFICATION QStringLiteral("EnableFingerprintIdentification")
42#define PROP_ENABLE_INDICATORS_WHILE_LOCKED QStringLiteral("EnableIndicatorsWhileLocked")
43#define PROP_ENABLE_LAUNCHER_WHILE_LOCKED QStringLiteral("EnableLauncherWhileLocked")
44#define PROP_FAILED_FINGERPRINT_LOGINS QStringLiteral("FailedFingerprintLogins")
45#define PROP_FAILED_LOGINS QStringLiteral("FailedLogins")
46#define PROP_INPUT_SOURCES QStringLiteral("InputSources")
47#define PROP_LICENSE_ACCEPTED QStringLiteral("LicenseAccepted")
48#define PROP_LICENSE_BASE_PATH QStringLiteral("LicenseBasePath")
49#define PROP_MOUSE_CURSOR_SPEED QStringLiteral("MouseCursorSpeed")
50#define PROP_MOUSE_DOUBLE_CLICK_SPEED QStringLiteral("MouseDoubleClickSpeed")
51#define PROP_MOUSE_PRIMARY_BUTTON QStringLiteral("MousePrimaryButton")
52#define PROP_MOUSE_SCROLL_SPEED QStringLiteral("MouseScrollSpeed")
53#define PROP_PASSWORD_DISPLAY_HINT QStringLiteral("PasswordDisplayHint")
54#define PROP_REAL_NAME QStringLiteral("RealName")
55#define PROP_STATS_WELCOME_SCREEN QStringLiteral("StatsWelcomeScreen")
56#define PROP_TOUCHPAD_CURSOR_SPEED QStringLiteral("TouchpadCursorSpeed")
57#define PROP_TOUCHPAD_DISABLE_WHILE_TYPING QStringLiteral("TouchpadDisableWhileTyping")
58#define PROP_TOUCHPAD_DISABLE_WITH_MOUSE QStringLiteral("TouchpadDisableWithMouse")
59#define PROP_TOUCHPAD_DOUBLE_CLICK_SPEED QStringLiteral("TouchpadDoubleClickSpeed")
60#define PROP_TOUCHPAD_PRIMARY_BUTTON QStringLiteral("TouchpadPrimaryButton")
61#define PROP_TOUCHPAD_SCROLL_SPEED QStringLiteral("TouchpadScrollSpeed")
62#define PROP_TOUCHPAD_TAP_TO_CLICK QStringLiteral("TouchpadTapToClick")
63#define PROP_TOUCHPAD_TWO_FINGER_SCROLL QStringLiteral("TouchpadTwoFingerScroll")
65using StringMap = QMap<QString,QString>;
66using StringMapList = QList<StringMap>;
67Q_DECLARE_METATYPE(StringMapList)
70QVariant primaryButtonConverter(const QVariant &value)
72 QString stringValue = value.toString();
73 if (stringValue == "left") {
74 return QVariant::fromValue(0);
75 } else if (stringValue == "right") {
76 return QVariant::fromValue(1); // Mir is less clear on this -- any non-zero value is the same
78 return QVariant::fromValue(0); // default to left
82AccountsService::AccountsService(QObject* parent, const QString &user)
84 , m_service(new AccountsServiceDBusAdaptor(this))
86 m_unityInput = new QDBusInterface(QStringLiteral("com.canonical.Unity.Input"),
87 QStringLiteral("/com/canonical/Unity/Input"),
88 QStringLiteral("com.canonical.Unity.Input"),
89 QDBusConnection::SM_BUSNAME(), this);
91 connect(m_service, &AccountsServiceDBusAdaptor::propertiesChanged, this, &AccountsService::onPropertiesChanged);
92 connect(m_service, &AccountsServiceDBusAdaptor::maybeChanged, this, &AccountsService::onMaybeChanged);
94 registerProperty(IFACE_ACCOUNTS_USER, PROP_BACKGROUND_FILE, QStringLiteral("backgroundFileChanged"));
95 registerProperty(IFACE_ACCOUNTS_USER, PROP_EMAIL, QStringLiteral("emailChanged"));
96 registerProperty(IFACE_ACCOUNTS_USER, PROP_REAL_NAME, QStringLiteral("realNameChanged"));
97 registerProperty(IFACE_ACCOUNTS_USER, PROP_INPUT_SOURCES, QStringLiteral("keymapsChanged"));
98 registerProperty(IFACE_LOCATION_HERE, PROP_LICENSE_ACCEPTED, QStringLiteral("hereEnabledChanged"));
99 registerProperty(IFACE_LOCATION_HERE, PROP_LICENSE_BASE_PATH, QStringLiteral("hereLicensePathChanged"));
100 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_FINGERPRINT_IDENTIFICATION, QStringLiteral("enableFingerprintIdentificationChanged"));
101 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED, QStringLiteral("enableLauncherWhileLockedChanged"));
102 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_INDICATORS_WHILE_LOCKED, QStringLiteral("enableIndicatorsWhileLockedChanged"));
103 registerProperty(IFACE_UBUNTU_SECURITY, PROP_PASSWORD_DISPLAY_HINT, QStringLiteral("passwordDisplayHintChanged"));
104 registerProperty(IFACE_UBUNTU_SECURITY_OLD, PROP_STATS_WELCOME_SCREEN, QStringLiteral("statsWelcomeScreenChanged"));
105 registerProperty(IFACE_UNITY, PROP_DEMO_EDGES, QStringLiteral("demoEdgesChanged"));
106 registerProperty(IFACE_UNITY, PROP_DEMO_EDGES_COMPLETED, QStringLiteral("demoEdgesCompletedChanged"));
107 registerProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_FINGERPRINT_LOGINS, QStringLiteral("failedFingerprintLoginsChanged"));
108 registerProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_LOGINS, QStringLiteral("failedLoginsChanged"));
110 registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_CURSOR_SPEED,
111 m_unityInput, QStringLiteral("setMouseCursorSpeed"));
112 registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_DOUBLE_CLICK_SPEED,
113 m_unityInput, QStringLiteral("setMouseDoubleClickSpeed"));
114 registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_PRIMARY_BUTTON,
115 m_unityInput, QStringLiteral("setMousePrimaryButton"),
116 primaryButtonConverter);
117 registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_SCROLL_SPEED,
118 m_unityInput, QStringLiteral("setMouseScrollSpeed"));
119 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_CURSOR_SPEED,
120 m_unityInput, QStringLiteral("setTouchpadCursorSpeed"));
121 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_SCROLL_SPEED,
122 m_unityInput, QStringLiteral("setTouchpadScrollSpeed"));
123 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_DISABLE_WHILE_TYPING,
124 m_unityInput, QStringLiteral("setTouchpadDisableWhileTyping"));
125 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_DISABLE_WITH_MOUSE,
126 m_unityInput, QStringLiteral("setTouchpadDisableWithMouse"));
127 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_DOUBLE_CLICK_SPEED,
128 m_unityInput, QStringLiteral("setTouchpadDoubleClickSpeed"));
129 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_PRIMARY_BUTTON,
130 m_unityInput, QStringLiteral("setTouchpadPrimaryButton"),
131 primaryButtonConverter);
132 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_TAP_TO_CLICK,
133 m_unityInput, QStringLiteral("setTouchpadTapToClick"));
134 registerProxy(IFACE_UBUNTU_INPUT, PROP_TOUCHPAD_TWO_FINGER_SCROLL,
135 m_unityInput, QStringLiteral("setTouchpadTwoFingerScroll"));
137 setUser(!user.isEmpty() ? user : QString::fromUtf8(g_get_user_name()));
140QString AccountsService::user() const
145void AccountsService::setUser(const QString &user)
147 if (user.isEmpty() || m_user == user)
150 bool wasEmpty = m_user.isEmpty();
153 Q_EMIT userChanged();
155 // Do the first update synchronously, as a cheap way to block rendering
156 // until we have the right values on bootup.
160bool AccountsService::demoEdges() const
162 auto value = getProperty(IFACE_UNITY, PROP_DEMO_EDGES);
163 return value.toBool();
166void AccountsService::setDemoEdges(bool demoEdges)
168 setProperty(IFACE_UNITY, PROP_DEMO_EDGES, demoEdges);
171QStringList AccountsService::demoEdgesCompleted() const
173 auto value = getProperty(IFACE_UNITY, PROP_DEMO_EDGES_COMPLETED);
174 return value.toStringList();
177void AccountsService::markDemoEdgeCompleted(const QString &edge)
179 auto currentList = demoEdgesCompleted();
180 if (!currentList.contains(edge)) {
181 setProperty(IFACE_UNITY, PROP_DEMO_EDGES_COMPLETED, currentList << edge);
185bool AccountsService::enableFingerprintIdentification() const
187 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_FINGERPRINT_IDENTIFICATION);
188 return value.toBool();
191bool AccountsService::enableLauncherWhileLocked() const
193 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED);
194 return value.toBool();
197bool AccountsService::enableIndicatorsWhileLocked() const
199 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_INDICATORS_WHILE_LOCKED);
200 return value.toBool();
203QString AccountsService::backgroundFile() const
205 auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_BACKGROUND_FILE);
206 return value.toString();
209bool AccountsService::statsWelcomeScreen() const
211 auto value = getProperty(IFACE_UBUNTU_SECURITY_OLD, PROP_STATS_WELCOME_SCREEN);
212 return value.toBool();
215AccountsService::PasswordDisplayHint AccountsService::passwordDisplayHint() const
217 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_PASSWORD_DISPLAY_HINT);
218 return (PasswordDisplayHint)value.toInt();
221bool AccountsService::hereEnabled() const
223 auto value = getProperty(IFACE_LOCATION_HERE, PROP_LICENSE_ACCEPTED);
224 return value.toBool();
227void AccountsService::setHereEnabled(bool enabled)
229 setProperty(IFACE_LOCATION_HERE, PROP_LICENSE_ACCEPTED, enabled);
232QString AccountsService::hereLicensePath() const
234 auto value = getProperty(IFACE_LOCATION_HERE, PROP_LICENSE_BASE_PATH);
235 QString hereLicensePath = value.toString();
236 if (hereLicensePath.isEmpty() || !QFile::exists(hereLicensePath))
237 hereLicensePath = QStringLiteral("");
238 return hereLicensePath;
241bool AccountsService::hereLicensePathValid() const
243 auto value = getProperty(IFACE_LOCATION_HERE, PROP_LICENSE_BASE_PATH);
244 return !value.toString().isNull();
247QString AccountsService::realName() const
249 auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_REAL_NAME);
250 return value.toString();
253void AccountsService::setRealName(const QString &realName)
255 setProperty(IFACE_ACCOUNTS_USER, PROP_REAL_NAME, realName);
258QString AccountsService::email() const
260 auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_EMAIL);
261 return value.toString();
264void AccountsService::setEmail(const QString &email)
266 setProperty(IFACE_ACCOUNTS_USER, PROP_EMAIL, email);
269QStringList AccountsService::keymaps() const
271 auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_INPUT_SOURCES);
272 QDBusArgument arg = value.value<QDBusArgument>();
273 StringMapList maps = qdbus_cast<StringMapList>(arg);
274 QStringList simplifiedMaps;
276 Q_FOREACH(const StringMap &map, maps) {
277 Q_FOREACH(const QString &entry, map) {
278 simplifiedMaps.append(entry);
282 if (!simplifiedMaps.isEmpty()) {
283 return simplifiedMaps;
286 return {QStringLiteral("us")};
289void AccountsService::migrateKeymapSettings()
292 if (!settings.value(QStringLiteral("KeymapsMigrated")).toBool()) {
293 auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_INPUT_SOURCES);
294 QDBusArgument arg = value.value<QDBusArgument>();
295 StringMapList maps = qdbus_cast<StringMapList>(arg);
297 // Save the config settings (for the keyboard indicator)
298 GSettings * sourcesSettings = g_settings_new("org.gnome.desktop.input-sources");
299 GVariantBuilder builder;
300 g_variant_builder_init(&builder, G_VARIANT_TYPE("a(ss)"));
301 Q_FOREACH(const auto & keymapPair, maps) {
302 g_variant_builder_add(&builder, "(ss)", keymapPair.firstKey().toUtf8().constData(),
303 keymapPair.first().toUtf8().constData());
305 g_settings_set_value(sourcesSettings, "sources", g_variant_builder_end(&builder));
306 g_object_unref(sourcesSettings);
308 settings.setValue(QStringLiteral("KeymapsMigrated"), true);
312uint AccountsService::failedFingerprintLogins() const
314 return getProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_FINGERPRINT_LOGINS).toUInt();
317void AccountsService::setFailedFingerprintLogins(uint failedFingerprintLogins)
319 setProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_FINGERPRINT_LOGINS, failedFingerprintLogins);
322uint AccountsService::failedLogins() const
324 return getProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_LOGINS).toUInt();
327void AccountsService::setFailedLogins(uint failedLogins)
329 setProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_LOGINS, failedLogins);
332// ====================================================
333// Everything below this line is generic helper methods
334// ====================================================
336void AccountsService::emitChangedForProperty(const QString &interface, const QString &property)
338 QString signalName = m_properties[interface][property].signal;
339 QMetaObject::invokeMethod(this, signalName.toUtf8().data());
342QVariant AccountsService::getProperty(const QString &interface, const QString &property) const
344 return m_properties[interface][property].value;
347void AccountsService::setProperty(const QString &interface, const QString &property, const QVariant &value)
349 if (m_properties[interface][property].value != value) {
350 m_properties[interface][property].value = value;
351 m_service->setUserPropertyAsync(m_user, interface, property, value);
352 emitChangedForProperty(interface, property);
356void AccountsService::updateCache(const QString &interface, const QString &property, const QVariant &value)
358 PropertyInfo &info = m_properties[interface][property];
360 if (info.proxyInterface) {
362 if (info.proxyConverter) {
363 finalValue = info.proxyConverter(value);
367 info.proxyInterface->asyncCall(info.proxyMethod, finalValue);
368 return; // don't bother saving a copy
371 if (info.value != value) {
373 emitChangedForProperty(interface, property);
377void AccountsService::updateProperty(const QString &interface, const QString &property)
379 QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
382 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
384 connect(watcher, &QDBusPendingCallWatcher::finished,
385 this, [this, interface, property](QDBusPendingCallWatcher* watcher) {
387 QDBusPendingReply<QVariant> reply = *watcher;
388 watcher->deleteLater();
389 if (reply.isError()) {
390 qWarning() << "Failed to get '" << property << "' property:" << reply.error().message();
394 updateCache(interface, property, reply.value());
398void AccountsService::updateAllProperties(const QString &interface, bool async)
400 QDBusPendingCall pendingReply = m_service->getAllPropertiesAsync(m_user,
402 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
404 connect(watcher, &QDBusPendingCallWatcher::finished,
405 this, [this, interface](QDBusPendingCallWatcher* watcher) {
407 QDBusPendingReply< QHash<QString, QVariant> > reply = *watcher;
408 watcher->deleteLater();
409 if (reply.isError()) {
410 qWarning() << "Failed to get all properties for" << interface << ":" << reply.error().message();
414 auto valueHash = reply.value();
415 auto i = valueHash.constBegin();
416 while (i != valueHash.constEnd()) {
417 updateCache(interface, i.key(), i.value());
422 watcher->waitForFinished();
426void AccountsService::registerProxy(const QString &interface, const QString &property, QDBusInterface *iface, const QString &method, ProxyConverter converter)
428 registerProperty(interface, property, nullptr);
430 m_properties[interface][property].proxyInterface = iface;
431 m_properties[interface][property].proxyMethod = method;
432 m_properties[interface][property].proxyConverter = converter;
435void AccountsService::registerProperty(const QString &interface, const QString &property, const QString &signal)
437 m_properties[interface][property] = PropertyInfo();
438 m_properties[interface][property].signal = signal;
441void AccountsService::onPropertiesChanged(const QString &user, const QString &interface, const QStringList &changed)
443 if (m_user != user) {
447 auto propHash = m_properties.value(interface);
448 auto i = propHash.constBegin();
449 while (i != propHash.constEnd()) {
450 if (changed.contains(i.key())) {
451 updateProperty(interface, i.key());
457void AccountsService::onMaybeChanged(const QString &user)
459 if (m_user != user) {
463 // Any of the standard properties might have changed!
464 auto propHash = m_properties.value(IFACE_ACCOUNTS_USER);
465 auto i = propHash.constBegin();
466 while (i != propHash.constEnd()) {
467 updateProperty(IFACE_ACCOUNTS_USER, i.key());
472void AccountsService::refresh(bool async)
474 auto i = m_properties.constBegin();
475 while (i != m_properties.constEnd()) {
476 updateAllProperties(i.key(), async);
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list