on xenial help sign in
Add support for launching apps from split launcher
commitb288715736a011b855f4532889368981d8ace8c8 authorMichael Terry <michael.terry@canonical.com> dateFri 30 Aug 2013, 17:08 (13 years ago) parent8688555a7fd827
16 files changed+430−2
GreeterShell.qml+3−2 debian/control+1 plugins/CMakeLists.txt+1 plugins/SessionBroadcast/CMakeLists.txt+13 plugins/SessionBroadcast/SessionBroadcast.cpp+70 plugins/SessionBroadcast/SessionBroadcast.h+49 plugins/SessionBroadcast/plugin.cpp+35 plugins/SessionBroadcast/plugin.h+33 plugins/SessionBroadcast/qmldir+3 tests/plugins/CMakeLists.txt+1 tests/plugins/SessionBroadcast/BroadcastServer.cpp+30 tests/plugins/SessionBroadcast/BroadcastServer.h+41 tests/plugins/SessionBroadcast/CMakeLists.txt+37 tests/plugins/SessionBroadcast/client.cpp+62 tests/plugins/SessionBroadcast/interfaces.xml+12 tests/plugins/SessionBroadcast/server.cpp+39
GreeterShell.qml+3−2
@@ -17,6 +17,7 @@
1717import QtQuick 2.0
1818import Ubuntu.Application 0.1
1919import LightDM 0.1 as LightDM
20+import SessionBroadcast 0.1
2021import "Greeter"
2122import "Launcher"
2223import "Panel"
@@ -27,8 +28,8 @@ BasicShell {
2728 id: shell
2829
2930 function activateApplication(desktopFile, argument) {
30− greeter.login()
31− // TODO: support opening the app once inside user's session
31+ SessionBroadcast.requestApplicationStart(LightDM.Greeter.authenticationUser, desktopFile)
32+ greeter.hide()
3233 }
3334
3435 Lockscreen {
debian/control+1
@@ -71,6 +71,7 @@ Depends: gsettings-desktop-schemas,
7171 qtdeclarative5-ubuntu-ui-toolkit-plugin,
7272 qtdeclarative5-unity-notifications-plugin | unity-notifications-impl,
7373 qtdeclarative5-xmllistmodel-plugin,
74+ unity-greeter-session-broadcast,
7475 unity-launcher-impl-2,
7576 unity-notifications-impl-1,
7677 unity8-fake-env | qtubuntu-shell,
plugins/CMakeLists.txt+1
@@ -3,6 +3,7 @@ add_subdirectory(HudClient)
33add_subdirectory(LightDM)
44add_subdirectory(ListViewWithPageHeader)
55add_subdirectory(Powerd)
6+add_subdirectory(SessionBroadcast)
67add_subdirectory(SessionManager)
78add_subdirectory(Ubuntu)
89add_subdirectory(Unity)
plugins/SessionBroadcast/CMakeLists.txtnew file+13
@@ -0,0 +1,13 @@
1+include(Plugins)
2+
3+add_definitions(-DSM_BUSNAME=systemBus)
4+
5+add_library(SessionBroadcast-qml MODULE
6+ SessionBroadcast.cpp
7+ plugin.cpp
8+ )
9+
10+qt5_use_modules(SessionBroadcast-qml DBus Qml)
11+
12+export_qmlfiles(SessionBroadcast SessionBroadcast)
13+export_qmlplugin(SessionBroadcast 0.1 SessionBroadcast TARGETS SessionBroadcast-qml)
plugins/SessionBroadcast/SessionBroadcast.cppnew file+70
@@ -0,0 +1,70 @@
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 "SessionBroadcast.h"
20+#include <QDBusConnection>
21+#include <QDBusConnectionInterface>
22+#include <QDBusInterface>
23+#include <QFileInfo>
24+
25+SessionBroadcast::SessionBroadcast(QObject* parent)
26+ : QObject(parent),
27+ broadcaster(NULL)
28+{
29+ auto connection = QDBusConnection::SM_BUSNAME();
30+ auto interface = connection.interface();
31+ interface->startService("com.canonical.Unity.Greeter.Broadcast");
32+ broadcaster = new QDBusInterface("com.canonical.Unity.Greeter.Broadcast",
33+ "/com/canonical/Unity/Greeter/Broadcast",
34+ "com.canonical.Unity.Greeter.Broadcast",
35+ connection, this);
36+
37+ connection.connect("com.canonical.Unity.Greeter.Broadcast",
38+ "/com/canonical/Unity/Greeter/Broadcast",
39+ "com.canonical.Unity.Greeter.Broadcast",
40+ "StartApplication",
41+ this,
42+ SLOT(onStartApplication(const QString &, const QString &)));
43+}
44+
45+void SessionBroadcast::requestApplicationStart(const QString &username, const QString &appId)
46+{
47+ // unity-greeter-session-broadcast deals in short appIds. That is,
48+ // desktop file names without the ".desktop". It doesn't really allow
49+ // for arbitrary-path desktop files, for security reasons (hard to
50+ // contain with apparmor and such). So we need to mangle the names a bit.
51+ // If incoming appId is random path like /hello/foobar.desktop, then just
52+ // do our best and ask for foobar.
53+ QString desktopSuffix = ".desktop";
54+ QString mangled = appId;
55+ if (mangled.endsWith(desktopSuffix))
56+ mangled.chop(desktopSuffix.size());
57+ mangled = QFileInfo(mangled).fileName(); // chop off path
58+
59+ broadcaster->asyncCall("RequestApplicationStart", username, mangled);
60+}
61+
62+void SessionBroadcast::onStartApplication(const QString &username, const QString &appId)
63+{
64+ // Since this signal is just used for testing, we don't *really* care if
65+ // username matches, but just in case we do eventually use the signal, we
66+ // should only listen to our own requests.
67+ if (username == qgetenv("USER")) {
68+ Q_EMIT startApplication(appId);
69+ }
70+}
plugins/SessionBroadcast/SessionBroadcast.hnew file+49
@@ -0,0 +1,49 @@
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+ * Authors: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+#ifndef UNITY_SESSIONBROADCAST_H
20+#define UNITY_SESSIONBROADCAST_H
21+
22+#include <QObject>
23+#include <QString>
24+
25+class QDBusInterface;
26+
27+class SessionBroadcast: public QObject
28+{
29+ Q_OBJECT
30+
31+public:
32+ explicit SessionBroadcast(QObject *parent = 0);
33+
34+ Q_INVOKABLE void requestApplicationStart(const QString &username, const QString &appId);
35+
36+Q_SIGNALS:
37+ // This signal isn't actually used by the shell
38+ // (unity-greeter-session-broadcast handles launching an app for us), but
39+ // it's useful for testing the plugin.
40+ void startApplication(const QString &appId);
41+
42+private Q_SLOTS:
43+ void onStartApplication(const QString &username, const QString &appId);
44+
45+private:
46+ QDBusInterface *broadcaster;
47+};
48+
49+#endif
plugins/SessionBroadcast/plugin.cppnew file+35
@@ -0,0 +1,35 @@
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+ * Authors: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+#include "plugin.h"
20+#include "SessionBroadcast.h"
21+
22+#include <QtQml>
23+
24+static QObject *broadcast_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
25+{
26+ Q_UNUSED(engine)
27+ Q_UNUSED(scriptEngine)
28+ return new SessionBroadcast();
29+}
30+
31+void SessionBroadcastPlugin::registerTypes(const char *uri)
32+{
33+ Q_ASSERT(uri == QLatin1String("SessionBroadcast"));
34+ qmlRegisterSingletonType<SessionBroadcast>(uri, 0, 1, "SessionBroadcast", broadcast_provider);
35+}
plugins/SessionBroadcast/plugin.hnew file+33
@@ -0,0 +1,33 @@
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+ * Authors: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+#ifndef UNITY_SESSIONBROADCAST_PLUGIN_H
20+#define UNITY_SESSIONBROADCAST_PLUGIN_H
21+
22+#include <QQmlExtensionPlugin>
23+
24+class SessionBroadcastPlugin : public QQmlExtensionPlugin
25+{
26+ Q_OBJECT
27+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
28+
29+public:
30+ void registerTypes(const char *uri);
31+};
32+
33+#endif
plugins/SessionBroadcast/qmldirnew file+3
@@ -0,0 +1,3 @@
1+module SessionBroadcast
2+plugin SessionBroadcast-qml
3+typeinfo plugin.qmltypes
tests/plugins/CMakeLists.txt+1
@@ -1,5 +1,6 @@
11add_subdirectory(AccountsService)
22add_subdirectory(ListViewWithPageHeader)
3+add_subdirectory(SessionBroadcast)
34add_subdirectory(SessionManager)
45add_subdirectory(Ubuntu)
56add_subdirectory(Unity)
tests/plugins/SessionBroadcast/BroadcastServer.cppnew file+30
@@ -0,0 +1,30 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * version 3 along with this program. If not, see
15+ * <http://www.gnu.org/licenses/>
16+ *
17+ * Authored by: Michael Terry <michael.terry@canonical.com>
18+ */
19+
20+#include "BroadcastServer.h"
21+
22+BroadcastServer::BroadcastServer(QObject *parent)
23+ : QObject(parent)
24+{
25+}
26+
27+void BroadcastServer::RequestApplicationStart(const QString &username, const QString &appId)
28+{
29+ StartApplication(username, appId);
30+}
tests/plugins/SessionBroadcast/BroadcastServer.hnew file+41
@@ -0,0 +1,41 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * version 3 along with this program. If not, see
15+ * <http://www.gnu.org/licenses/>
16+ *
17+ * Authored by: Michael Terry <michael.terry@canonical.com>
18+ */
19+
20+#ifndef UNITY_MOCK_BROADCASTSERVER_H
21+#define UNITY_MOCK_BROADCASTSERVER_H
22+
23+#include <QDBusContext>
24+#include <QObject>
25+#include <QString>
26+
27+class BroadcastServer: public QObject, protected QDBusContext
28+{
29+ Q_OBJECT
30+
31+public:
32+ explicit BroadcastServer(QObject *parent = 0);
33+
34+public Q_SLOTS:
35+ void RequestApplicationStart(const QString &username, const QString &appId);
36+
37+Q_SIGNALS:
38+ void StartApplication(const QString &username, const QString &appId);
39+};
40+
41+#endif
tests/plugins/SessionBroadcast/CMakeLists.txtnew file+37
@@ -0,0 +1,37 @@
1+macro(make_dbus_class NAME INTERFACE)
2+ if(${CMAKE_CURRENT_SOURCE_DIR}/interfaces.xml IS_NEWER_THAN ${CMAKE_CURRENT_BINARY_DIR}/${NAME}Adaptor.h)
3+ execute_process(COMMAND qdbusxml2cpp -c ${NAME}Adaptor -a ${CMAKE_CURRENT_BINARY_DIR}/${NAME}Adaptor ${CMAKE_CURRENT_SOURCE_DIR}/interfaces.xml ${INTERFACE})
4+ endif()
5+endmacro(make_dbus_class)
6+
7+make_dbus_class(Broadcast com.canonical.Unity.Greeter.Broadcast)
8+
9+include_directories(
10+ ${CMAKE_CURRENT_BINARY_DIR}
11+ ${CMAKE_SOURCE_DIR}/plugins/SessionBroadcast
12+ )
13+
14+add_definitions(-DSM_BUSNAME=sessionBus)
15+
16+add_executable(mock-server
17+ ${CMAKE_CURRENT_BINARY_DIR}/BroadcastAdaptor.cpp
18+ server.cpp
19+ BroadcastServer.cpp
20+ )
21+qt5_use_modules(mock-server Core DBus)
22+
23+add_executable(sessionbroadcasttest
24+ ${CMAKE_SOURCE_DIR}/plugins/SessionBroadcast/SessionBroadcast.cpp
25+ client.cpp
26+ )
27+qt5_use_modules(sessionbroadcasttest Core DBus Test)
28+
29+add_test(NAME sessionbroadcasttest
30+ COMMAND dbus-test-runner
31+ --task ${CMAKE_CURRENT_BINARY_DIR}/mock-server
32+ --task-name server
33+ --ignore-return
34+ --task ${CMAKE_CURRENT_BINARY_DIR}/sessionbroadcasttest
35+ --task-name client
36+ --wait-for com.canonical.Unity.Greeter.Broadcast
37+ )
tests/plugins/SessionBroadcast/client.cppnew file+62
@@ -0,0 +1,62 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * version 3 along with this program. If not, see
15+ * <http://www.gnu.org/licenses/>
16+ *
17+ * Authored by: Michael Terry <michael.terry@canonical.com>
18+ */
19+
20+#include "SessionBroadcast.h"
21+#include <QSignalSpy>
22+#include <QTest>
23+
24+class BroadcastServiceTest : public QObject
25+{
26+ Q_OBJECT
27+
28+private Q_SLOTS:
29+
30+ void testRequest(const QString &requestedAppId, const QString &expectedAppId)
31+ {
32+ SessionBroadcast broadcaster;
33+ QSignalSpy spy(&broadcaster, SIGNAL(startApplication(const QString &)));
34+
35+ broadcaster.requestApplicationStart(qgetenv("USER"), requestedAppId);
36+
37+ // Wait one second for the signal
38+ int i = 0;
39+ while (spy.count() == 0 && i++ < 10)
40+ QTest::qWait(100);
41+ QCOMPARE(spy.count(), 1);
42+
43+ // Test the argument
44+ auto arguments = spy.takeFirst();
45+ QCOMPARE(arguments.at(0).toString(), QString(expectedAppId));
46+ }
47+
48+ void testAppId()
49+ {
50+ // Since our mock u-g-s-b just passes on the incoming appId, we test
51+ // here that our plugin mangles the names appropriately.
52+ testRequest("appid", "appid");
53+ testRequest("appid.desktop", "appid");
54+ testRequest("appid.info", "appid.info");
55+ testRequest("/usr/share/applications/appid.desktop", "appid");
56+ testRequest("/full/appid.desktop", "appid");
57+ }
58+};
59+
60+QTEST_MAIN(BroadcastServiceTest)
61+
62+#include "client.moc"
tests/plugins/SessionBroadcast/interfaces.xmlnew file+12
@@ -0,0 +1,12 @@
1+<node>
2+ <interface name="com.canonical.Unity.Greeter.Broadcast">
3+ <method name="RequestApplicationStart">
4+ <arg name="username" type="s" direction="in" />
5+ <arg name="appId" type="s" direction="in" />
6+ </method>
7+ <signal name="StartApplication">
8+ <arg name="username" type="s" direction="out" />
9+ <arg name="appId" type="s" direction="out" />
10+ </signal>
11+ </interface>
12+</node>
tests/plugins/SessionBroadcast/server.cppnew file+39
@@ -0,0 +1,39 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * version 3 along with this program. If not, see
15+ * <http://www.gnu.org/licenses/>
16+ *
17+ * Authored by: Michael Terry <michael.terry@canonical.com>
18+ */
19+
20+#include "BroadcastAdaptor.h"
21+#include "BroadcastServer.h"
22+#include <QCoreApplication>
23+
24+int main(int argc, char *argv[])
25+{
26+ QCoreApplication a(argc, argv);
27+
28+ auto broadcaster = new BroadcastServer();
29+ new BroadcastAdaptor(broadcaster);
30+
31+ // We use the session bus for testing. The real plugin uses the system bus
32+ auto connection = QDBusConnection::sessionBus();
33+ if (!connection.registerObject("/com/canonical/Unity/Greeter/Broadcast", broadcaster))
34+ return 1;
35+ if (!connection.registerService("com.canonical.Unity.Greeter.Broadcast"))
36+ return 1;
37+
38+ return a.exec();
39+}