Merge lp:~pete-woods/unity-notifications/clients-own-their-notifications into lp:unity-notifications

Proposed by Pete Woods on 2015-06-01
Status: Merged
Approved by: Pete Woods on 2015-06-16
Approved revision: no longer in the source branch.
Merged at revision: 227
Proposed branch: lp:~pete-woods/unity-notifications/clients-own-their-notifications
Merge into: lp:unity-notifications
Prerequisite: lp:~pete-woods/unity-notifications/handle-reopen-notification
Diff against target: 342 lines (+132/-19)
5 files modified
include/Notification.h (+2/-0)
include/NotificationServer.h (+1/-0)
src/Notification.cpp (+9/-0)
src/NotificationServer.cpp (+44/-3)
test/notificationservertest.cpp (+76/-16)
To merge this branch: bzr merge lp:~pete-woods/unity-notifications/clients-own-their-notifications
Reviewer Review Type Date Requested Status
Charles Kerr (community) 2015-06-01 Approve on 2015-06-15
Review via email: mp+260740@code.launchpad.net

Commit Message

Notifications are now owned by the client that opened them

Description of the Change

Notifications are now owned by the client that opened them

To post a comment you must log in.
Charles Kerr (charlesk) wrote :

Looks great!

review: Approve
232. By Pete Woods on 2015-06-23

Fix parallel build issues

234. By Pete Woods on 2015-06-23

Actually pass in notification server

235. By Pete Woods on 2015-06-23

Notifications are now owned by the client that opened them

236. By Pete Woods on 2015-06-23

Handle local notifications

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/Notification.h'
2--- include/Notification.h 2014-07-18 14:21:41 +0000
3+++ include/Notification.h 2015-06-23 15:48:50 +0000
4@@ -109,6 +109,8 @@
5 void setType(Type type);
6 ActionModel* getActions() const;
7 void setActions(const QStringList &actions);
8+ QString getClientId() const;
9+ void setClientId(const QString& clientId);
10 void detachFromServer();
11
12 QVariantMap getHints() const;
13
14=== modified file 'include/NotificationServer.h'
15--- include/NotificationServer.h 2015-06-23 15:48:50 +0000
16+++ include/NotificationServer.h 2015-06-23 15:48:50 +0000
17@@ -77,6 +77,7 @@
18
19 private:
20 void incrementCounter();
21+ QString messageSender();
22
23 QSharedPointer<Notification> buildNotification(NotificationID id, const QVariantMap &hints);
24 NotificationModel &model;
25
26=== modified file 'src/Notification.cpp'
27--- src/Notification.cpp 2014-09-22 12:43:29 +0000
28+++ src/Notification.cpp 2015-06-23 15:48:50 +0000
29@@ -39,6 +39,7 @@
30 ActionModel* actionsModel;
31 QVariantMap hints;
32 int displayTime;
33+ QString clientId;
34 };
35
36 /*
37@@ -205,6 +206,14 @@
38 }
39 }
40
41+QString Notification::getClientId() const {
42+ return p->clientId;
43+}
44+
45+void Notification::setClientId(const QString& clientId) {
46+ p->clientId = clientId;
47+}
48+
49 void Notification::detachFromServer() {
50 /*
51 * FIXME. This function should not exist. In fact
52
53=== modified file 'src/NotificationServer.cpp'
54--- src/NotificationServer.cpp 2015-06-23 15:48:50 +0000
55+++ src/NotificationServer.cpp 2015-06-23 15:48:50 +0000
56@@ -26,6 +26,13 @@
57 #include <QDBusConnectionInterface>
58 #include <QSharedPointer>
59
60+static const char* LOCAL_OWNER = "local";
61+
62+static bool isAuthorised(const QString& clientId, QSharedPointer<Notification> notification)
63+{
64+ return (clientId == LOCAL_OWNER) || (notification->getClientId() == clientId);
65+}
66+
67 NotificationServer::NotificationServer(const QDBusConnection& connection, NotificationModel &m, QObject *parent) :
68 QObject(parent), model(m), idCounter(0), m_connection(connection) {
69
70@@ -146,6 +153,14 @@
71 idCounter = 1;
72 }
73
74+QString NotificationServer::messageSender() {
75+ QString sender(LOCAL_OWNER);
76+ if (calledFromDBus()) {
77+ sender = message().service();
78+ }
79+ return sender;
80+}
81+
82 unsigned int NotificationServer::Notify(const QString &app_name, uint replaces_id,
83 const QString &app_icon, const QString &summary,
84 const QString &body, const QStringList &actions,
85@@ -157,12 +172,22 @@
86 int currentId = 0;
87
88 bool newNotification = true;
89+ QString clientId = messageSender();
90
91 QSharedPointer<Notification> notification;
92 if (replaces_id != 0) {
93 if (model.hasNotification(replaces_id)) {
94 newNotification = false;
95 notification = model.getNotification(replaces_id);
96+ if (!isAuthorised(clientId, notification)) {
97+ auto message =
98+ QString::fromUtf8(
99+ "Client '%1' tried to update notification %2, which it does not own.").arg(
100+ clientId).arg(replaces_id);
101+ qWarning() << message;
102+ sendErrorReply(QDBusError::InvalidArgs, message);
103+ return FAILURE;
104+ }
105 } else {
106 notification = buildNotification(replaces_id, hints);
107 }
108@@ -240,7 +265,9 @@
109 QVariant value = hints[VALUE_HINT];
110 notification->setValue(value.toInt());
111
112- if(newNotification) {
113+ notification->setClientId(clientId);
114+
115+ if (newNotification) {
116 model.insertNotification(notification);
117 } else {
118 model.notificationUpdated(currentId);
119@@ -249,8 +276,22 @@
120 }
121
122 void NotificationServer::CloseNotification (unsigned int id) {
123- Q_EMIT NotificationClosed(id, 1);
124- model.removeNotification(id);
125+ if (model.hasNotification(id)) {
126+ auto clientId = messageSender();
127+ auto notification = model.getNotification(id);
128+ if (!isAuthorised(clientId, notification))
129+ {
130+ auto message =
131+ QString::fromUtf8(
132+ "Client '%1' tried to close notification %2, which it does not own.").arg(
133+ clientId).arg(id);
134+ qWarning() << message;
135+ sendErrorReply(QDBusError::InvalidArgs, message);
136+ return;
137+ }
138+ Q_EMIT NotificationClosed(id, 1);
139+ model.removeNotification(id);
140+ }
141 }
142
143 QString NotificationServer::GetServerInformation (QString &vendor, QString &version, QString &specVersion) const {
144
145=== modified file 'test/notificationservertest.cpp'
146--- test/notificationservertest.cpp 2015-06-23 15:48:50 +0000
147+++ test/notificationservertest.cpp 2015-06-23 15:48:50 +0000
148@@ -16,6 +16,10 @@
149
150 QSharedPointer<OrgFreedesktopNotificationsInterface> notificationsInterface;
151
152+ QSharedPointer<QDBusConnection> secondConnection;
153+
154+ QSharedPointer<OrgFreedesktopNotificationsInterface> notificationsInterfaceSecond;
155+
156 private Q_SLOTS:
157
158 void init() {
159@@ -31,20 +35,40 @@
160 QStringList{"--no-gui"})));
161 dbus->startServices();
162
163+ // Create a connection to the server
164 notificationsInterface.reset(
165 new OrgFreedesktopNotificationsInterface(DBUS_SERVICE_NAME,
166 DBUS_PATH,
167 dbus->sessionConnection()));
168+
169+ secondConnection.reset(
170+ new QDBusConnection(
171+ QDBusConnection::connectToBus(
172+ dbus->sessionBus(),
173+ dbus->sessionBus() + "_second")));
174+
175+ // Create a second connection to the server over a different dbus connection
176+ notificationsInterfaceSecond.reset(
177+ new OrgFreedesktopNotificationsInterface(
178+ DBUS_SERVICE_NAME,
179+ DBUS_PATH,
180+ *secondConnection));
181 }
182
183 void cleanup() {
184+ notificationsInterfaceSecond.reset();
185+
186+ secondConnection.reset();
187+
188 notificationsInterface.reset();
189
190 dbus.reset();
191 }
192
193-int notify(const QString& name, int replacesId = 0) {
194- auto reply = notificationsInterface->Notify("my app", replacesId, "icon " + name,
195+int _notify(
196+ QSharedPointer<OrgFreedesktopNotificationsInterface> interface,
197+ const QString& name, int replacesId = 0) {
198+ auto reply = interface->Notify("my app", replacesId, "icon " + name,
199 "summary " + name,
200 "body " + name, QStringList(),
201 QVariantMap(), 0);
202@@ -55,6 +79,14 @@
203 return reply;
204 }
205
206+int notifyFirst(const QString& name, int replacesId = 0) {
207+ return _notify(notificationsInterface, name, replacesId);
208+}
209+
210+int notifySecond(const QString& name, int replacesId = 0, bool secondInterface = false) {
211+ return _notify(notificationsInterfaceSecond, name, replacesId);
212+}
213+
214 void expectNotification(const NotificationDataList& notifications, int index, int id, const QString& name) {
215 QCOMPARE(
216 notifications.at(index),
217@@ -68,11 +100,27 @@
218 );
219 }
220
221+void close(QSharedPointer<OrgFreedesktopNotificationsInterface> interface, int id) {
222+ auto reply = interface->CloseNotification(id);
223+ reply.waitForFinished();
224+ if (reply.isError()) {
225+ throw std::domain_error(reply.error().message().toStdString());
226+ }
227+}
228+
229+void closeFirst(int id) {
230+ close(notificationsInterface, id);
231+}
232+
233+void closeSecond(int id) {
234+ close(notificationsInterfaceSecond, id);
235+}
236+
237 void testNotify() {
238- uint id1 = notify("1");
239+ uint id1 = notifyFirst("1");
240 QCOMPARE(id1, uint(1));
241
242- uint id2 = notify("2");
243+ uint id2 = notifyFirst("2");
244 QCOMPARE(id2, uint(2));
245
246 NotificationDataList notifications = notificationsInterface->GetNotifications("my app");
247@@ -83,10 +131,10 @@
248 }
249
250 void testClose() {
251- uint id1 = notify("1");
252+ uint id1 = notifyFirst("1");
253 QCOMPARE(id1, uint(1));
254
255- uint id2 = notify("2");
256+ uint id2 = notifyFirst("2");
257 QCOMPARE(id2, uint(2));
258
259 {
260@@ -97,7 +145,7 @@
261 expectNotification(notifications, 1, id2, "2");
262 }
263
264- notificationsInterface->CloseNotification(id1).waitForFinished();
265+ closeFirst(id1);
266
267 {
268 NotificationDataList notifications = notificationsInterface->GetNotifications("my app");
269@@ -108,7 +156,7 @@
270 }
271
272 void testNotifyCloseNotify() {
273- uint id1 = notify("1");
274+ uint id1 = notifyFirst("1");
275 QCOMPARE(id1, uint(1));
276
277 {
278@@ -118,14 +166,14 @@
279 expectNotification(notifications, 0, id1, "1");
280 }
281
282- notificationsInterface->CloseNotification(id1).waitForFinished();
283+ closeFirst(id1);
284
285 {
286 NotificationDataList notifications = notificationsInterface->GetNotifications("my app");
287 QCOMPARE(notifications.size(), 0);
288 }
289
290- id1 = notify("1", id1);
291+ id1 = notifyFirst("1", id1);
292 QCOMPARE(id1, uint(1));
293
294 {
295@@ -137,22 +185,22 @@
296 }
297
298 void testNotifyCounterIncrement() {
299- uint id1 = notify("1", 1);
300+ uint id1 = notifyFirst("1", 1);
301 QCOMPARE(id1, uint(1));
302
303- uint id2 = notify("2", 2);
304+ uint id2 = notifyFirst("2", 2);
305 QCOMPARE(id2, uint(2));
306
307- uint id4 = notify("4", 4);
308+ uint id4 = notifyFirst("4", 4);
309 QCOMPARE(id4, uint(4));
310
311- uint id5 = notify("5", 5);
312+ uint id5 = notifyFirst("5", 5);
313 QCOMPARE(id5, uint(5));
314
315- uint id3 = notify("3");
316+ uint id3 = notifyFirst("3");
317 QCOMPARE(id3, uint(3));
318
319- uint id6 = notify("6");
320+ uint id6 = notifyFirst("6");
321 QCOMPARE(id6, uint(6));
322
323 {
324@@ -168,6 +216,18 @@
325 }
326 }
327
328+void testNotifyTwoClientsOneNaughty() {
329+ // Create notification from one client
330+ uint id1 = notifySecond("1");
331+ QCOMPARE(id1, uint(1));
332+
333+ // Try and update notification from another client
334+ QVERIFY_EXCEPTION_THROWN(notifyFirst("2", id1), std::domain_error);
335+
336+ // Try and close notification from another client
337+ QVERIFY_EXCEPTION_THROWN(closeFirst(id1), std::domain_error);
338+}
339+
340 void testGetCapabilities() {
341 QStringList capabilities = notificationsInterface->GetCapabilities();
342 QStringList expected {"actions",

Subscribers

People subscribed via source and target branches

to all changes: