on xenial help sign in
Fix a race between Qml loading and DBus registration that caused problems when jenkins tried to unlock the phone.
89dbba8Michael Terry
plugins/LightDM/CMakeLists.txt+2
@@ -10,6 +10,7 @@ include_directories(
10 ${CMAKE_SOURCE_DIR}/plugins/Utils
10 ${CMAKE_SOURCE_DIR}/plugins/Utils
11 ${CMAKE_SOURCE_DIR}/tests/mocks/LightDM
11 ${CMAKE_SOURCE_DIR}/tests/mocks/LightDM
12 #${LIBLIGHTDM_INCLUDE_DIRS}
12 #${LIBLIGHTDM_INCLUDE_DIRS}
13+ ${libunity8-private_SOURCE_DIR}
13 ${LIBUSERMETRICSOUTPUT_INCLUDE_DIRS}
14 ${LIBUSERMETRICSOUTPUT_INCLUDE_DIRS}
14)
15)
15
16
@@ -28,6 +29,7 @@ add_library(LightDM-qml MODULE
28
29
29target_link_libraries(LightDM-qml
30target_link_libraries(LightDM-qml
30 MockLightDM-demo
31 MockLightDM-demo
32+ unity8-private
31# TODO: Once we split out a separate greeter process, uncomment these lines
33# TODO: Once we split out a separate greeter process, uncomment these lines
32# ${LIBLIGHTDM_LDFLAGS}
34# ${LIBLIGHTDM_LDFLAGS}
33 ${LIBUSERMETRICSOUTPUT_LDFLAGS}
35 ${LIBUSERMETRICSOUTPUT_LDFLAGS}
plugins/LightDM/DBusGreeter.cpp+3−24
@@ -20,11 +20,9 @@
20#include <QDBusMessage>
20#include <QDBusMessage>
21#include <QStringList>
21#include <QStringList>
22
22
23−DBusGreeter::DBusGreeter(Greeter *greeter, const QDBusConnection &connection, const QString &path)
23+DBusGreeter::DBusGreeter(Greeter *greeter, const QString &path)
24− : QObject(greeter),
24+ : UnityDBusObject(path, "com.canonical.UnityGreeter", true, greeter),
25− m_greeter(greeter),
25+ m_greeter(greeter)
26− m_connection(connection),
27− m_path(path)
28{
26{
29 connect(m_greeter, SIGNAL(isActiveChanged()), this, SLOT(isActiveChangedHandler()));
27 connect(m_greeter, SIGNAL(isActiveChanged()), this, SLOT(isActiveChangedHandler()));
30}
28}
@@ -49,22 +47,3 @@ void DBusGreeter::isActiveChangedHandler()
49 notifyPropertyChanged("IsActive", isActive());
47 notifyPropertyChanged("IsActive", isActive());
50 Q_EMIT isActiveChanged();
48 Q_EMIT isActiveChanged();
51}
49}
52−
53−// Manually emit a PropertiesChanged signal over DBus, because QtDBus
54−// doesn't do it for us on Q_PROPERTIES, oddly enough.
55−void DBusGreeter::notifyPropertyChanged(const QString& propertyName, const QVariant &value)
56−{
57− QDBusMessage message;
58− QVariantMap changedProps;
59−
60− changedProps.insert(propertyName, value);
61−
62− message = QDBusMessage::createSignal(m_path,
63− "org.freedesktop.DBus.Properties",
64− "PropertiesChanged");
65− message << "com.canonical.UnityGreeter";
66− message << changedProps;
67− message << QStringList();
68−
69− m_connection.send(message);
70−}
plugins/LightDM/DBusGreeter.h+3−6
@@ -17,15 +17,15 @@
17#ifndef UNITY_DBUSGREETER_H
17#ifndef UNITY_DBUSGREETER_H
18#define UNITY_DBUSGREETER_H
18#define UNITY_DBUSGREETER_H
19
19
20+#include "unitydbusobject.h"
20#include <QDBusConnection>
21#include <QDBusConnection>
21−#include <QObject>
22
22
23class Greeter;
23class Greeter;
24
24
25/** This is an internal class used to talk with the indicators.
25/** This is an internal class used to talk with the indicators.
26 */
26 */
27
27
28−class DBusGreeter : public QObject
28+class DBusGreeter : public UnityDBusObject
29{
29{
30 Q_OBJECT
30 Q_OBJECT
31 Q_CLASSINFO("D-Bus Interface", "com.canonical.UnityGreeter")
31 Q_CLASSINFO("D-Bus Interface", "com.canonical.UnityGreeter")
@@ -33,7 +33,7 @@ class DBusGreeter : public QObject
33 Q_PROPERTY(bool IsActive READ isActive NOTIFY isActiveChanged) // since 14.10
33 Q_PROPERTY(bool IsActive READ isActive NOTIFY isActiveChanged) // since 14.10
34
34
35public:
35public:
36− explicit DBusGreeter(Greeter *greeter, const QDBusConnection &connection, const QString &path);
36+ explicit DBusGreeter(Greeter *greeter, const QString &path);
37
37
38 bool isActive() const;
38 bool isActive() const;
39 Q_SCRIPTABLE void ShowGreeter(); // temporary, until we split the greeter again
39 Q_SCRIPTABLE void ShowGreeter(); // temporary, until we split the greeter again
@@ -44,12 +44,9 @@ Q_SIGNALS:
44
44
45private Q_SLOTS:
45private Q_SLOTS:
46 void isActiveChangedHandler();
46 void isActiveChangedHandler();
47− void notifyPropertyChanged(const QString &propertyName, const QVariant &value);
48
47
49private:
48private:
50 Greeter *m_greeter;
49 Greeter *m_greeter;
51− QDBusConnection m_connection;
52− QString m_path;
53};
50};
54
51
55#endif
52#endif
plugins/LightDM/DBusGreeterList.cpp+3−24
@@ -20,11 +20,9 @@
20#include <QDBusMessage>
20#include <QDBusMessage>
21#include <QStringList>
21#include <QStringList>
22
22
23−DBusGreeterList::DBusGreeterList(Greeter *greeter, const QDBusConnection &connection, const QString &path)
23+DBusGreeterList::DBusGreeterList(Greeter *greeter, const QString &path)
24− : QObject(greeter),
24+ : UnityDBusObject(path, "com.canonical.UnityGreeter", true, greeter),
25− m_greeter(greeter),
25+ m_greeter(greeter)
26− m_connection(connection),
27− m_path(path)
28{
26{
29 connect(m_greeter, SIGNAL(authenticationUserChanged(const QString &)), this, SLOT(authenticationUserChangedHandler(const QString &)));
27 connect(m_greeter, SIGNAL(authenticationUserChanged(const QString &)), this, SLOT(authenticationUserChangedHandler(const QString &)));
30 connect(m_greeter, SIGNAL(promptlessChanged()), this, SLOT(promptlessChangedHandler()));
28 connect(m_greeter, SIGNAL(promptlessChanged()), this, SLOT(promptlessChangedHandler()));
@@ -56,22 +54,3 @@ void DBusGreeterList::promptlessChangedHandler()
56 notifyPropertyChanged("EntryIsLocked", entryIsLocked());
54 notifyPropertyChanged("EntryIsLocked", entryIsLocked());
57 Q_EMIT entryIsLockedChanged();
55 Q_EMIT entryIsLockedChanged();
58}
56}
59−
60−// Manually emit a PropertiesChanged signal over DBus, because QtDBus
61−// doesn't do it for us on Q_PROPERTIES, oddly enough.
62−void DBusGreeterList::notifyPropertyChanged(const QString& propertyName, const QVariant &value)
63−{
64− QDBusMessage message;
65− QVariantMap changedProps;
66−
67− changedProps.insert(propertyName, value);
68−
69− message = QDBusMessage::createSignal(m_path,
70− "org.freedesktop.DBus.Properties",
71− "PropertiesChanged");
72− message << "com.canonical.UnityGreeter.List";
73− message << changedProps;
74− message << QStringList();
75−
76− m_connection.send(message);
77−}
plugins/LightDM/DBusGreeterList.h+3−6
@@ -17,15 +17,15 @@
17#ifndef UNITY_DBUSGREETERLIST_H
17#ifndef UNITY_DBUSGREETERLIST_H
18#define UNITY_DBUSGREETERLIST_H
18#define UNITY_DBUSGREETERLIST_H
19
19
20+#include "unitydbusobject.h"
20#include <QDBusConnection>
21#include <QDBusConnection>
21−#include <QObject>
22
22
23class Greeter;
23class Greeter;
24
24
25/** This is an internal class used to talk with the indicators.
25/** This is an internal class used to talk with the indicators.
26 */
26 */
27
27
28−class DBusGreeterList : public QObject
28+class DBusGreeterList : public UnityDBusObject
29{
29{
30 Q_OBJECT
30 Q_OBJECT
31 Q_CLASSINFO("D-Bus Interface", "com.canonical.UnityGreeter.List")
31 Q_CLASSINFO("D-Bus Interface", "com.canonical.UnityGreeter.List")
@@ -34,7 +34,7 @@ class DBusGreeterList : public QObject
34 Q_PROPERTY(bool EntryIsLocked READ entryIsLocked NOTIFY entryIsLockedChanged) // since 14.04
34 Q_PROPERTY(bool EntryIsLocked READ entryIsLocked NOTIFY entryIsLockedChanged) // since 14.04
35
35
36public:
36public:
37− explicit DBusGreeterList(Greeter *greeter, const QDBusConnection &connection, const QString &path);
37+ explicit DBusGreeterList(Greeter *greeter, const QString &path);
38
38
39 Q_SCRIPTABLE void SetActiveEntry(const QString &entry); // since 13.04
39 Q_SCRIPTABLE void SetActiveEntry(const QString &entry); // since 13.04
40 Q_SCRIPTABLE QString GetActiveEntry() const; // since 13.10
40 Q_SCRIPTABLE QString GetActiveEntry() const; // since 13.10
@@ -49,12 +49,9 @@ Q_SIGNALS:
49private Q_SLOTS:
49private Q_SLOTS:
50 void authenticationUserChangedHandler(const QString &user);
50 void authenticationUserChangedHandler(const QString &user);
51 void promptlessChangedHandler();
51 void promptlessChangedHandler();
52− void notifyPropertyChanged(const QString &propertyName, const QVariant &value);
53
52
54private:
53private:
55 Greeter *m_greeter;
54 Greeter *m_greeter;
56− QDBusConnection m_connection;
57− QString m_path;
58};
55};
59
56
60#endif
57#endif
plugins/LightDM/plugin.cpp+2−9
@@ -30,21 +30,14 @@
30#include <QDBusConnection>
30#include <QDBusConnection>
31#include <QtQml/qqml.h>
31#include <QtQml/qqml.h>
32
32
33−static const char* GREETER_LIST_DBUS_PATH = "/list";
34−static const char* GREETER_DBUS_SERVICE = "com.canonical.UnityGreeter";
35−
36static QObject *greeter_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
33static QObject *greeter_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
37{
34{
38 Q_UNUSED(engine)
35 Q_UNUSED(engine)
39 Q_UNUSED(scriptEngine)
36 Q_UNUSED(scriptEngine)
40
37
41 Greeter *greeter = new Greeter();
38 Greeter *greeter = new Greeter();
42− QDBusConnection connection = QDBusConnection::sessionBus();
43− DBusGreeter *root = new DBusGreeter(greeter, connection, "/");
39+ new DBusGreeter(greeter, "/");
44− connection.registerObject("/", root, QDBusConnection::ExportScriptableContents);
45− DBusGreeterList *list = new DBusGreeterList(greeter, connection, GREETER_LIST_DBUS_PATH);
40+ new DBusGreeterList(greeter, "/list");
46− connection.registerObject(GREETER_LIST_DBUS_PATH, list, QDBusConnection::ExportScriptableContents);
47− connection.registerService(GREETER_DBUS_SERVICE);
48
41
49 return greeter;
42 return greeter;
50}
43}
plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cpp+1−5
@@ -21,12 +21,8 @@
21#include <QDebug>
21#include <QDebug>
22
22
23DBusDashCommunicatorService::DBusDashCommunicatorService(QObject *parent):
23DBusDashCommunicatorService::DBusDashCommunicatorService(QObject *parent):
24− QObject(parent)
24+ UnityDBusObject("/com/canonical/UnityDash", "com.canonical.UnityDash", false, parent)
25{
25{
26− QDBusConnection connection = QDBusConnection::sessionBus();
27−
28− connection.registerService("com.canonical.UnityDash");
29− connection.registerObject("/com/canonical/UnityDash", this, QDBusConnection::ExportScriptableSlots);
30}
26}
31
27
32DBusDashCommunicatorService::~DBusDashCommunicatorService()
28DBusDashCommunicatorService::~DBusDashCommunicatorService()
plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.h+2−2
@@ -17,9 +17,9 @@
17#ifndef DBUSDASHCOMMUNICATORSERVICE_H
17#ifndef DBUSDASHCOMMUNICATORSERVICE_H
18#define DBUSDASHCOMMUNICATORSERVICE_H
18#define DBUSDASHCOMMUNICATORSERVICE_H
19
19
20−#include <QObject>
20+#include "unitydbusobject.h"
21
21
22−class DBusDashCommunicatorService: public QObject
22+class DBusDashCommunicatorService: public UnityDBusObject
23{
23{
24 Q_OBJECT
24 Q_OBJECT
25 Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.DashCommunicator")
25 Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.DashCommunicator")
plugins/Unity/Launcher/CMakeLists.txt+5−1
@@ -9,6 +9,7 @@ include_directories(
9 ${CMAKE_CURRENT_SOURCE_DIR}
9 ${CMAKE_CURRENT_SOURCE_DIR}
10 ${CMAKE_SOURCE_DIR}/plugins/AccountsService
10 ${CMAKE_SOURCE_DIR}/plugins/AccountsService
11 ${GSETTINGS_QT_INCLUDE_DIRS}
11 ${GSETTINGS_QT_INCLUDE_DIRS}
12+ ${libunity8-private_SOURCE_DIR}
12)
13)
13
14
14set(QMLLAUNCHERPLUGIN_SRC
15set(QMLLAUNCHERPLUGIN_SRC
@@ -30,7 +31,10 @@ add_library(UnityLauncher-qml MODULE
30 ${QMLLAUNCHERPLUGIN_SRC}
31 ${QMLLAUNCHERPLUGIN_SRC}
31 )
32 )
32
33
33−target_link_libraries(UnityLauncher-qml ${GSETTINGS_QT_LDFLAGS})
34+target_link_libraries(UnityLauncher-qml
35+ unity8-private
36+ ${GSETTINGS_QT_LDFLAGS}
37+ )
34
38
35qt5_use_modules(UnityLauncher-qml DBus Qml Gui)
39qt5_use_modules(UnityLauncher-qml DBus Qml Gui)
36
40
plugins/Unity/Launcher/dbusinterface.cpp+3−36
@@ -27,25 +27,13 @@
27#include <QDebug>
27#include <QDebug>
28
28
29DBusInterface::DBusInterface(LauncherModel *parent):
29DBusInterface::DBusInterface(LauncherModel *parent):
30− QDBusVirtualObject(parent),
30+ UnityDBusVirtualObject("/com/canonical/Unity/Launcher", "com.canonical.Unity.Launcher", true, parent),
31 m_launcherModel(parent)
31 m_launcherModel(parent)
32{
32{
33− /* Set up ourselves on DBus */
34− QDBusConnection con = QDBusConnection::sessionBus();
35− if (!con.registerService("com.canonical.Unity.Launcher")) {
36− qWarning() << "Unable to register launcher name";
37− }
38− if (!con.registerVirtualObject("/com/canonical/Unity/Launcher", this, QDBusConnection::VirtualObjectRegisterOption::SubPath)) {
39− qWarning() << "Unable to register launcher object";
40− }
41}
33}
42
34
43DBusInterface::~DBusInterface()
35DBusInterface::~DBusInterface()
44{
36{
45− /* Remove oursevles from DBus */
46− QDBusConnection con = QDBusConnection::sessionBus();
47− con.unregisterService("com.canonical.Unity.Launcher");
48− con.unregisterObject("/com/canonical/Unity/Launcher");
49}
37}
50
38
51QString DBusInterface::introspect(const QString &path) const
39QString DBusInterface::introspect(const QString &path) const
@@ -186,13 +174,13 @@ bool DBusInterface::handleMessage(const QDBusMessage& message, const QDBusConnec
186 int newCount = message.arguments()[2].toInt();
174 int newCount = message.arguments()[2].toInt();
187 if (!item || newCount != item->count()) {
175 if (!item || newCount != item->count()) {
188 Q_EMIT countChanged(appid, newCount);
176 Q_EMIT countChanged(appid, newCount);
189− emitPropChangedDbus(appid, "count", QVariant(newCount));
177+ notifyPropertyChanged("com.canonical.Unity.Launcher.Item", encodeAppId(appid), "count", QVariant(newCount));
190 }
178 }
191 } else if (message.arguments()[1].toString() == "countVisible") {
179 } else if (message.arguments()[1].toString() == "countVisible") {
192 bool newVisible = message.arguments()[2].toBool();
180 bool newVisible = message.arguments()[2].toBool();
193 if (!item || newVisible != item->countVisible()) {
181 if (!item || newVisible != item->countVisible()) {
194 Q_EMIT countVisibleChanged(appid, newVisible);
182 Q_EMIT countVisibleChanged(appid, newVisible);
195− emitPropChangedDbus(appid, "countVisible", newVisible);
183+ notifyPropertyChanged("com.canonical.Unity.Launcher.Item", encodeAppId(appid), "countVisible", newVisible);
196 }
184 }
197 }
185 }
198 } else if (message.member() == "GetAll") {
186 } else if (message.member() == "GetAll") {
@@ -209,24 +197,3 @@ bool DBusInterface::handleMessage(const QDBusMessage& message, const QDBusConnec
209 QDBusMessage reply = message.createReply(retval);
197 QDBusMessage reply = message.createReply(retval);
210 return connection.send(reply);
198 return connection.send(reply);
211}
199}
212−
213−void DBusInterface::emitPropChangedDbus(const QString& appId, const QString& property, const QVariant &value)
214−{
215− QString path("/com/canonical/Unity/Launcher/");
216− path.append(encodeAppId(appId));
217−
218− QDBusMessage message = QDBusMessage::createSignal(path, "org.freedesktop.DBus.Properties", "PropertiesChanged");
219−
220− QList<QVariant> arguments;
221− QVariantHash changedprops;
222− changedprops[property] = QVariant::fromValue(QDBusVariant(value));
223− QVariantList deletedprops;
224−
225− arguments.append(changedprops);
226− arguments.append(deletedprops);
227−
228− message.setArguments(arguments);
229−
230− QDBusConnection con = QDBusConnection::sessionBus();
231− con.send(message);
232−}
plugins/Unity/Launcher/dbusinterface.h+2−5
@@ -18,12 +18,11 @@
18 */
18 */
19
19
20#include "launcheritem.h"
20#include "launcheritem.h"
21−
21+#include "unitydbusvirtualobject.h"
22−#include <QDBusVirtualObject>
23
22
24class LauncherModel;
23class LauncherModel;
25
24
26−class DBusInterface: public QDBusVirtualObject
25+class DBusInterface: public UnityDBusVirtualObject
27{
26{
28 Q_OBJECT
27 Q_OBJECT
29public:
28public:
@@ -43,8 +42,6 @@ private:
43 static QString decodeAppId(const QString& path);
42 static QString decodeAppId(const QString& path);
44 static QString encodeAppId(const QString& appId);
43 static QString encodeAppId(const QString& appId);
45
44
46− void emitPropChangedDbus(const QString& appId, const QString& property, const QVariant &value);
47−
48 LauncherModel *m_launcherModel;
45 LauncherModel *m_launcherModel;
49
46
50};
47};
plugins/Unity/Session/CMakeLists.txt+5−1
@@ -5,6 +5,7 @@ pkg_search_module(GIO REQUIRED gio-2.0)
5include_directories(
5include_directories(
6 ${CMAKE_CURRENT_SOURCE_DIR}
6 ${CMAKE_CURRENT_SOURCE_DIR}
7 ${GIO_INCLUDE_DIRS}
7 ${GIO_INCLUDE_DIRS}
8+ ${libunity8-private_SOURCE_DIR}
8)
9)
9
10
10set(QMLSESSIONPLUGIN_SRC
11set(QMLSESSIONPLUGIN_SRC
@@ -18,7 +19,10 @@ add_library(UnitySession-qml MODULE
18 )
19 )
19
20
20qt5_use_modules(UnitySession-qml DBus Qml)
21qt5_use_modules(UnitySession-qml DBus Qml)
21−target_link_libraries(UnitySession-qml ${GIO_LDFLAGS})
22+target_link_libraries(UnitySession-qml
23+ unity8-private
24+ ${GIO_LDFLAGS}
25+ )
22
26
23# export the qmldir and qmltypes files
27# export the qmldir and qmltypes files
24add_unity8_plugin(Unity.Session 0.1 Unity/Session TARGETS UnitySession-qml)
28add_unity8_plugin(Unity.Session 0.1 Unity/Session TARGETS UnitySession-qml)
plugins/Unity/Session/dbusunitysessionservice.cpp+2−8
@@ -21,15 +21,9 @@
21#include <QDBusConnection>
21#include <QDBusConnection>
22#include <QDBusInterface>
22#include <QDBusInterface>
23
23
24−DBusUnitySessionService::DBusUnitySessionService() : QObject()
24+DBusUnitySessionService::DBusUnitySessionService()
25+ : UnityDBusObject("/com/canonical/Unity/Session", "com.canonical.Unity")
25{
26{
26− QDBusConnection connection = QDBusConnection::sessionBus();
27−
28− connection.registerService("com.canonical.Unity");
29− connection.registerObject("/com/canonical/Unity/Session", this,
30− QDBusConnection::ExportScriptableSignals
31− | QDBusConnection::ExportScriptableSlots
32− | QDBusConnection::ExportScriptableInvokables);
33}
27}
34
28
35DBusUnitySessionService::~DBusUnitySessionService()
29DBusUnitySessionService::~DBusUnitySessionService()
plugins/Unity/Session/dbusunitysessionservice.h+2−2
@@ -17,7 +17,7 @@
17#ifndef DBUSUNITYSESSIONSERVICE_H
17#ifndef DBUSUNITYSESSIONSERVICE_H
18#define DBUSUNITYSESSIONSERVICE_H
18#define DBUSUNITYSESSIONSERVICE_H
19
19
20−#include <QObject>
20+#include "unitydbusobject.h"
21
21
22/**
22/**
23 * DBusUnitySessionService provides com.canonical.Unity.Session dbus
23 * DBusUnitySessionService provides com.canonical.Unity.Session dbus
@@ -26,7 +26,7 @@
26 * com.canonical.Unity.Session interface provides public methods
26 * com.canonical.Unity.Session interface provides public methods
27 * and signals to handle Logout/Reboot/Shutdown.
27 * and signals to handle Logout/Reboot/Shutdown.
28 */
28 */
29−class DBusUnitySessionService : public QObject
29+class DBusUnitySessionService : public UnityDBusObject
30{
30{
31 Q_OBJECT
31 Q_OBJECT
32 Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.Session")
32 Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.Session")
qml/Shell.qml+13
@@ -371,6 +371,10 @@ Item {
371 onHideGreeter: greeter.login()
371 onHideGreeter: greeter.login()
372
372
373 onShowPrompt: {
373 onShowPrompt: {
374+ shell.enabled = true;
375+ if (!LightDM.Greeter.active) {
376+ return; // could happen if hideGreeter() comes in before we prompt
377+ }
374 if (greeter.narrowMode) {
378 if (greeter.narrowMode) {
375 if (isDefaultPrompt) {
379 if (isDefaultPrompt) {
376 if (lockscreen.alphaNumeric) {
380 if (lockscreen.alphaNumeric) {
@@ -391,6 +395,9 @@ Item {
391 }
395 }
392
396
393 onPromptlessChanged: {
397 onPromptlessChanged: {
398+ if (!LightDM.Greeter.active) {
399+ return; // could happen if hideGreeter() comes in before we prompt
400+ }
394 if (greeter.narrowMode) {
401 if (greeter.narrowMode) {
395 if (LightDM.Greeter.promptless && LightDM.Greeter.authenticated) {
402 if (LightDM.Greeter.promptless && LightDM.Greeter.authenticated) {
396 lockscreen.hide()
403 lockscreen.hide()
@@ -402,6 +409,7 @@ Item {
402 }
409 }
403
410
404 onAuthenticationComplete: {
411 onAuthenticationComplete: {
412+ shell.enabled = true;
405 if (LightDM.Greeter.authenticated) {
413 if (LightDM.Greeter.authenticated) {
406 AccountsService.failedLogins = 0
414 AccountsService.failedLogins = 0
407 }
415 }
@@ -538,6 +546,11 @@ Item {
538
546
539 onShownChanged: {
547 onShownChanged: {
540 if (shown) {
548 if (shown) {
549+ // Disable everything so that user can't swipe greeter or
550+ // launcher until we get first prompt/authenticate, which
551+ // will re-enable the shell.
552+ shell.enabled = false;
553+
541 if (greeter.narrowMode) {
554 if (greeter.narrowMode) {
542 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
555 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
543 } else {
556 } else {
src/libunity8-private/CMakeLists.txt+2
@@ -6,6 +6,8 @@ project(lib${LIB_NAME})
6
6
7set(lib${LIB_NAME}_SRCS
7set(lib${LIB_NAME}_SRCS
8 abstractdbusservicemonitor.cpp
8 abstractdbusservicemonitor.cpp
9+ unitydbusobject.cpp
10+ unitydbusvirtualobject.cpp
9 )
11 )
10
12
11add_library(${LIB_NAME} SHARED
13add_library(${LIB_NAME} SHARED
src/libunity8-private/unitydbusobject.cppnew file+86
@@ -0,0 +1,86 @@
1+/*
2+ * Copyright (C) 2014 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 "unitydbusobject.h"
18+
19+#include <QDebug>
20+#include <QDBusMessage>
21+#include <QMetaClassInfo>
22+#include <QTimer>
23+
24+UnityDBusObject::UnityDBusObject(const QString &path, const QString &service, bool async, QObject *parent)
25+ : QObject(parent)
26+ , m_connection(QDBusConnection::sessionBus())
27+ , m_path(path)
28+ , m_service(service)
29+{
30+ if (async) {
31+ // Use a zero-timer to let Qml finish loading before we announce on DBus
32+ QTimer::singleShot(0, this, SLOT(registerObject()));
33+ } else {
34+ registerObject();
35+ }
36+}
37+
38+UnityDBusObject::~UnityDBusObject()
39+{
40+ // Leave service in place because multiple objects may be registered with
41+ // the same service. But we know we own the object path and can unregister it.
42+ m_connection.unregisterObject(path());
43+}
44+
45+QDBusConnection UnityDBusObject::connection() const
46+{
47+ return m_connection;
48+}
49+
50+QString UnityDBusObject::path() const
51+{
52+ return m_path;
53+}
54+
55+// Manually emit a PropertiesChanged signal over DBus, because QtDBus
56+// doesn't do it for us on Q_PROPERTIES, oddly enough.
57+void UnityDBusObject::notifyPropertyChanged(const QString& propertyName, const QVariant &value)
58+{
59+ QDBusMessage message;
60+ QString interface;
61+ QVariantMap changedProps;
62+
63+ interface = metaObject()->classInfo(metaObject()->indexOfClassInfo("D-Bus Interface")).value();
64+ changedProps.insert(propertyName, value);
65+
66+ message = QDBusMessage::createSignal(path(),
67+ "org.freedesktop.DBus.Properties",
68+ "PropertiesChanged");
69+ message << interface;
70+ message << changedProps;
71+ message << QStringList();
72+
73+ connection().send(message);
74+}
75+
76+void UnityDBusObject::registerObject()
77+{
78+ if (!m_connection.registerObject(m_path, this, QDBusConnection::ExportScriptableContents)) {
79+ qWarning() << "Unable to register DBus object" << m_path;
80+ }
81+ if (!m_service.isEmpty()) {
82+ if (!m_connection.registerService(m_service)) {
83+ qWarning() << "Unable to register DBus service" << m_service;
84+ }
85+ }
86+}
src/libunity8-private/unitydbusobject.hnew file+46
@@ -0,0 +1,46 @@
1+/*
2+ * Copyright (C) 2014 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+#ifndef UNITYDBUSOBJECT_H
18+#define UNITYDBUSOBJECT_H
19+
20+#include <QDBusConnection>
21+#include <QObject>
22+
23+class Q_DECL_EXPORT UnityDBusObject : public QObject
24+{
25+ Q_OBJECT
26+
27+public:
28+ explicit UnityDBusObject(const QString &path, const QString &service = QString(), bool async = true, QObject *parent = 0);
29+ ~UnityDBusObject();
30+
31+ QDBusConnection connection() const;
32+ QString path() const;
33+
34+protected:
35+ void notifyPropertyChanged(const QString& propertyName, const QVariant &value);
36+
37+private Q_SLOTS:
38+ void registerObject();
39+
40+private:
41+ QDBusConnection m_connection;
42+ QString m_path;
43+ QString m_service;
44+};
45+
46+#endif // UNITYDBUSOBJECT_H
src/libunity8-private/unitydbusvirtualobject.cppnew file+83
@@ -0,0 +1,83 @@
1+/*
2+ * Copyright (C) 2014 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 "unitydbusvirtualobject.h"
18+
19+#include <QDebug>
20+#include <QDBusMessage>
21+#include <QTimer>
22+
23+UnityDBusVirtualObject::UnityDBusVirtualObject(const QString &path, const QString &service, bool async, QObject *parent)
24+ : QDBusVirtualObject(parent)
25+ , m_connection(QDBusConnection::sessionBus())
26+ , m_path(path)
27+ , m_service(service)
28+{
29+ if (async) {
30+ // Use a zero-timer to let Qml finish loading before we announce on DBus
31+ QTimer::singleShot(0, this, SLOT(registerObject()));
32+ } else {
33+ registerObject();
34+ }
35+}
36+
37+UnityDBusVirtualObject::~UnityDBusVirtualObject()
38+{
39+ // Leave service in place because multiple objects may be registered with
40+ // the same service. But we know we own the object path and can unregister it.
41+ m_connection.unregisterObject(path());
42+}
43+
44+QDBusConnection UnityDBusVirtualObject::connection() const
45+{
46+ return m_connection;
47+}
48+
49+QString UnityDBusVirtualObject::path() const
50+{
51+ return m_path;
52+}
53+
54+// Manually emit a PropertiesChanged signal over DBus, because QtDBus
55+// doesn't do it for us on Q_PROPERTIES, oddly enough.
56+void UnityDBusVirtualObject::notifyPropertyChanged(const QString& interface, const QString& node, const QString& propertyName, const QVariant &value)
57+{
58+ QDBusMessage message;
59+ QVariantMap changedProps;
60+
61+ changedProps.insert(propertyName, value);
62+
63+ message = QDBusMessage::createSignal(path() + "/" + node,
64+ "org.freedesktop.DBus.Properties",
65+ "PropertiesChanged");
66+ message << interface;
67+ message << changedProps;
68+ message << QStringList();
69+
70+ connection().send(message);
71+}
72+
73+void UnityDBusVirtualObject::registerObject()
74+{
75+ if (!m_connection.registerVirtualObject(m_path, this, QDBusConnection::VirtualObjectRegisterOption::SubPath)) {
76+ qWarning() << "Unable to register DBus object" << m_path;
77+ }
78+ if (!m_service.isEmpty()) {
79+ if (!m_connection.registerService(m_service)) {
80+ qWarning() << "Unable to register DBus service" << m_service;
81+ }
82+ }
83+}
src/libunity8-private/unitydbusvirtualobject.hnew file+47
@@ -0,0 +1,47 @@
1+/*
2+ * Copyright (C) 2014 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+#ifndef UNITYDBUSVIRTUALOBJECT_H
18+#define UNITYDBUSVIRTUALOBJECT_H
19+
20+#include <QDBusConnection>
21+#include <QDBusVirtualObject>
22+#include <QObject>
23+
24+class Q_DECL_EXPORT UnityDBusVirtualObject : public QDBusVirtualObject
25+{
26+ Q_OBJECT
27+
28+public:
29+ explicit UnityDBusVirtualObject(const QString &path, const QString &service = QString(), bool async = true, QObject *parent = 0);
30+ ~UnityDBusVirtualObject();
31+
32+ QDBusConnection connection() const;
33+ QString path() const;
34+
35+protected:
36+ void notifyPropertyChanged(const QString& interface, const QString& node, const QString& propertyName, const QVariant &value);
37+
38+private Q_SLOTS:
39+ void registerObject();
40+
41+private:
42+ QDBusConnection m_connection;
43+ QString m_path;
44+ QString m_service;
45+};
46+
47+#endif // UNITYDBUSVIRTUALOBJECT_H
tests/mocks/LightDM/CMakeLists.txt+2
@@ -15,6 +15,7 @@ include_directories(
15 ${CMAKE_CURRENT_BINARY_DIR}
15 ${CMAKE_CURRENT_BINARY_DIR}
16 ${CMAKE_SOURCE_DIR}/plugins/Utils
16 ${CMAKE_SOURCE_DIR}/plugins/Utils
17 ${CMAKE_SOURCE_DIR}/tests/mocks/libusermetrics
17 ${CMAKE_SOURCE_DIR}/tests/mocks/libusermetrics
18+ ${libunity8-private_SOURCE_DIR}
18)
19)
19
20
20set(QMLPLUGIN_SRC
21set(QMLPLUGIN_SRC
@@ -40,6 +41,7 @@ target_link_libraries(MockLightDM-qml
40 -llightdm-qt5-2
41 -llightdm-qt5-2
41 -L${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics
42 -L${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics
42 -lusermetricsoutput
43 -lusermetricsoutput
44+ unity8-private
43 )
45 )
44
46
45qt5_use_modules(MockLightDM-qml DBus Gui Qml)
47qt5_use_modules(MockLightDM-qml DBus Gui Qml)
tests/plugins/Unity/Launcher/CMakeLists.txt+5−1
@@ -7,6 +7,7 @@ include_directories(
7 ${CMAKE_SOURCE_DIR}/plugins/AccountsService
7 ${CMAKE_SOURCE_DIR}/plugins/AccountsService
8 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher
8 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher
9 ${GSETTINGS_QT_INCLUDE_DIRS}
9 ${GSETTINGS_QT_INCLUDE_DIRS}
10+ ${libunity8-private_SOURCE_DIR}
10 )
11 )
11
12
12add_definitions(-DSM_BUSNAME=sessionBus)
13add_definitions(-DSM_BUSNAME=sessionBus)
@@ -34,7 +35,10 @@ add_executable(launchermodeltestExec
34 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
35 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
35 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
36 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
36 )
37 )
37−target_link_libraries(launchermodeltestExec ${GSETTINGS_QT_LDFLAGS})
38+target_link_libraries(launchermodeltestExec
39+ unity8-private
40+ ${GSETTINGS_QT_LDFLAGS}
41+ )
38qt5_use_modules(launchermodeltestExec Test Core DBus Xml Gui)
42qt5_use_modules(launchermodeltestExec Test Core DBus Xml Gui)
39
43
40# copy .desktop files into build directory for shadow builds
44# copy .desktop files into build directory for shadow builds
tests/plugins/Unity/Launcher/launchermodeltest.cpp+1
@@ -133,6 +133,7 @@ private Q_SLOTS:
133
133
134 void initTestCase() {
134 void initTestCase() {
135 launcherModel = new LauncherModel(this);
135 launcherModel = new LauncherModel(this);
136+ QCoreApplication::processEvents(); // to let the model register on DBus
136 QCOMPARE(launcherModel->rowCount(QModelIndex()), 0);
137 QCOMPARE(launcherModel->rowCount(QModelIndex()), 0);
137
138
138 appManager = new MockAppManager(this);
139 appManager = new MockAppManager(this);
tests/plugins/Unity/Session/CMakeLists.txt+4
@@ -1,6 +1,7 @@
1include_directories(
1include_directories(
2 ${CMAKE_CURRENT_BINARY_DIR}
2 ${CMAKE_CURRENT_BINARY_DIR}
3 ${CMAKE_SOURCE_DIR}/plugins/Unity/Session
3 ${CMAKE_SOURCE_DIR}/plugins/Unity/Session
4+ ${libunity8-private_SOURCE_DIR}
4)
5)
5
6
6add_definitions(-DSM_BUSNAME=sessionBus)
7add_definitions(-DSM_BUSNAME=sessionBus)
@@ -17,4 +18,7 @@ add_executable(sessionbackendtestExec
17 sessionbackendtest.cpp
18 sessionbackendtest.cpp
18 ${CMAKE_SOURCE_DIR}/plugins/Unity/Session/dbusunitysessionservice.cpp
19 ${CMAKE_SOURCE_DIR}/plugins/Unity/Session/dbusunitysessionservice.cpp
19)
20)
21+target_link_libraries(sessionbackendtestExec
22+ unity8-private
23+ )
20qt5_use_modules(sessionbackendtestExec Test Core Qml DBus)
24qt5_use_modules(sessionbackendtestExec Test Core Qml DBus)
tests/plugins/Unity/Session/sessionbackendtest.cpp+1
@@ -45,6 +45,7 @@ private Q_SLOTS:
45 QFETCH(QString, method);
45 QFETCH(QString, method);
46
46
47 DBusUnitySessionService dbusUnitySessionService;
47 DBusUnitySessionService dbusUnitySessionService;
48+ QCoreApplication::processEvents(); // to let the service register on DBus
48
49
49 QDBusConnection con = QDBusConnection::sessionBus();
50 QDBusConnection con = QDBusConnection::sessionBus();
50 QDBusInterface interface ("com.canonical.Unity",
51 QDBusInterface interface ("com.canonical.Unity",
tests/qmltests/tst_Shell.qml+3
@@ -161,6 +161,8 @@ Item {
161 property Item shell: shellLoader.status === Loader.Ready ? shellLoader.item : null
161 property Item shell: shellLoader.status === Loader.Ready ? shellLoader.item : null
162
162
163 function init() {
163 function init() {
164+ tryCompare(shell, "enabled", true); // enabled by greeter when ready
165+
164 swipeAwayGreeter();
166 swipeAwayGreeter();
165
167
166 sessionSpy.target = findChild(shell, "greeter")
168 sessionSpy.target = findChild(shell, "greeter")
@@ -171,6 +173,7 @@ Item {
171 }
173 }
172
174
173 function cleanup() {
175 function cleanup() {
176+ tryCompare(shell, "enabled", true); // make sure greeter didn't leave us in disabled state
174 launcherShowDashHomeSpy.target = null;
177 launcherShowDashHomeSpy.target = null;
175
178
176 shellLoader.itemDestroyed = false;
179 shellLoader.itemDestroyed = false;
tests/qmltests/tst_ShellWithPin.qml+3
@@ -129,6 +129,7 @@ Item {
129 property Item shell: shellLoader.status === Loader.Ready ? shellLoader.item : null
129 property Item shell: shellLoader.status === Loader.Ready ? shellLoader.item : null
130
130
131 function init() {
131 function init() {
132+ tryCompare(shell, "enabled", true); // will be enabled when greeter is all ready
132 sessionSpy.target = findChild(shell, "greeter")
133 sessionSpy.target = findChild(shell, "greeter")
133 swipeAwayGreeter()
134 swipeAwayGreeter()
134 waitForLockscreen()
135 waitForLockscreen()
@@ -137,6 +138,8 @@ Item {
137 }
138 }
138
139
139 function cleanup() {
140 function cleanup() {
141+ tryCompare(shell, "enabled", true); // make sure greeter didn't leave us in disabled state
142+
140 shellLoader.itemDestroyed = false
143 shellLoader.itemDestroyed = false
141
144
142 shellLoader.active = false
145 shellLoader.active = false
tests/qmltests/tst_TabletShell.qml+3
@@ -121,12 +121,15 @@ Row {
121 property Item shell: shellLoader.status === Loader.Ready ? shellLoader.item : null
121 property Item shell: shellLoader.status === Loader.Ready ? shellLoader.item : null
122
122
123 function init() {
123 function init() {
124+ tryCompare(shell, "enabled", true); // will be enabled when greeter is all ready
124 sessionSpy.clear()
125 sessionSpy.clear()
125 sessionSpy.target = findChild(shell, "greeter")
126 sessionSpy.target = findChild(shell, "greeter")
126 dashCommunicatorSpy.target = findInvisibleChild(shell, "dashCommunicator")
127 dashCommunicatorSpy.target = findInvisibleChild(shell, "dashCommunicator")
127 }
128 }
128
129
129 function cleanup() {
130 function cleanup() {
131+ tryCompare(shell, "enabled", true); // make sure greeter didn't leave us in disabled state
132+
130 shellLoader.itemDestroyed = false
133 shellLoader.itemDestroyed = false
131
134
132 shellLoader.active = false
135 shellLoader.active = false