Merge lp:~mardy/signon-ui/lp1135038 into lp:signon-ui

Proposed by Alberto Mardegan
Status: Merged
Approved by: Alberto Mardegan
Approved revision: 79
Merged at revision: 78
Proposed branch: lp:~mardy/signon-ui/lp1135038
Merge into: lp:signon-ui
Diff against target: 672 lines (+367/-51)
12 files modified
.bzrignore (+2/-0)
src/inactivity-timer.cpp (+68/-0)
src/inactivity-timer.h (+58/-0)
src/indicator-service.cpp (+18/-0)
src/indicator-service.h (+5/-0)
src/main.cpp (+12/-7)
src/service.cpp (+15/-42)
src/service.h (+3/-2)
src/src.pro (+2/-0)
tests/unit/tst_inactivity_timer.cpp (+143/-0)
tests/unit/tst_inactivity_timer.pro (+37/-0)
tests/unit/unit.pro (+4/-0)
To merge this branch: bzr merge lp:~mardy/signon-ui/lp1135038
Reviewer Review Type Date Requested Status
David King (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+153356@code.launchpad.net

Commit message

Do not quit if some accounts are failing

The inactivity timer should not trigger if there are some account failures (we
even had a comment warning about that!), because signon-ui is also the host for
the com.canonical.indicators.webcredentials service.

Create a new InactivityTimer to monitor both the Service and IndicatorService
objects.

Description of the change

Do not quit if some accounts are failing

The inactivity timer should not trigger if there are some account failures (we
even had a comment warning about that!), because signon-ui is also the host for
the com.canonical.indicators.webcredentials service.

Create a new InactivityTimer to monitor both the Service and IndicatorService
objects.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:~mardy/signon-ui/lp1135038 updated
79. By Alberto Mardegan

Use xvfb-run

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
David King (amigadave) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2012-11-15 08:10:18 +0000
3+++ .bzrignore 2013-03-14 13:21:22 +0000
4@@ -13,6 +13,7 @@
5 core
6 debian/
7 Makefile
8+Makefile.*
9 moc_*
10 qrc_*.cpp
11 signon-ui-test
12@@ -20,6 +21,7 @@
13 src/signon_ui_adaptor.*
14 src/webcredentials_adaptor.*
15 tests/unit/signon-ui-unittest
16+tests/unit/tst_inactivity_timer
17 tests/.config/Trolltech.conf
18 tests/functional/.cache/
19 tests/functional/.config/
20
21=== added file 'src/inactivity-timer.cpp'
22--- src/inactivity-timer.cpp 1970-01-01 00:00:00 +0000
23+++ src/inactivity-timer.cpp 2013-03-14 13:21:22 +0000
24@@ -0,0 +1,68 @@
25+/*
26+ * This file is part of signon-ui
27+ *
28+ * Copyright (C) 2013 Canonical Ltd.
29+ *
30+ * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
31+ *
32+ * This program is free software: you can redistribute it and/or modify it
33+ * under the terms of the GNU General Public License version 3, as published
34+ * by the Free Software Foundation.
35+ *
36+ * This program is distributed in the hope that it will be useful, but
37+ * WITHOUT ANY WARRANTY; without even the implied warranties of
38+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
39+ * PURPOSE. See the GNU General Public License for more details.
40+ *
41+ * You should have received a copy of the GNU General Public License along
42+ * with this program. If not, see <http://www.gnu.org/licenses/>.
43+ */
44+
45+#include "inactivity-timer.h"
46+
47+#include "debug.h"
48+
49+using namespace SignOnUi;
50+
51+InactivityTimer::InactivityTimer(int interval, QObject *parent):
52+ QObject(parent),
53+ m_interval(interval)
54+{
55+ m_timer.setSingleShot(true);
56+ QObject::connect(&m_timer, SIGNAL(timeout()),
57+ this, SLOT(onTimeout()));
58+}
59+
60+void InactivityTimer::watchObject(QObject *object)
61+{
62+ connect(object, SIGNAL(isIdleChanged()), SLOT(onIdleChanged()));
63+ m_watchedObjects.append(object);
64+
65+ /* Force an initial check */
66+ onIdleChanged();
67+}
68+
69+void InactivityTimer::onIdleChanged()
70+{
71+ if (allObjectsAreIdle()) {
72+ m_timer.start(m_interval);
73+ }
74+}
75+
76+void InactivityTimer::onTimeout()
77+{
78+ TRACE();
79+ if (allObjectsAreIdle()) {
80+ Q_EMIT timeout();
81+ }
82+}
83+
84+bool InactivityTimer::allObjectsAreIdle() const
85+{
86+ foreach (const QObject *object, m_watchedObjects) {
87+ if (!object->property("isIdle").toBool()) {
88+ return false;
89+ }
90+ }
91+ return true;
92+}
93
94=== added file 'src/inactivity-timer.h'
95--- src/inactivity-timer.h 1970-01-01 00:00:00 +0000
96+++ src/inactivity-timer.h 2013-03-14 13:21:22 +0000
97@@ -0,0 +1,58 @@
98+/*
99+ * This file is part of signon-ui
100+ *
101+ * Copyright (C) 2013 Canonical Ltd.
102+ *
103+ * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
104+ *
105+ * This program is free software: you can redistribute it and/or modify it
106+ * under the terms of the GNU General Public License version 3, as published
107+ * by the Free Software Foundation.
108+ *
109+ * This program is distributed in the hope that it will be useful, but
110+ * WITHOUT ANY WARRANTY; without even the implied warranties of
111+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
112+ * PURPOSE. See the GNU General Public License for more details.
113+ *
114+ * You should have received a copy of the GNU General Public License along
115+ * with this program. If not, see <http://www.gnu.org/licenses/>.
116+ */
117+
118+#ifndef SIGNON_UI_INACTIVITY_TIMER_H
119+#define SIGNON_UI_INACTIVITY_TIMER_H
120+
121+#include <QList>
122+#include <QObject>
123+#include <QTimer>
124+
125+namespace SignOnUi {
126+
127+class InactivityTimer: public QObject
128+{
129+ Q_OBJECT
130+
131+public:
132+ InactivityTimer(int interval, QObject *parent = 0);
133+ ~InactivityTimer() {}
134+
135+ void watchObject(QObject *object);
136+
137+Q_SIGNALS:
138+ void timeout();
139+
140+private Q_SLOTS:
141+ void onIdleChanged();
142+ void onTimeout();
143+
144+private:
145+ bool allObjectsAreIdle() const;
146+
147+private:
148+ QList<QObject*> m_watchedObjects;
149+ QTimer m_timer;
150+ int m_interval;
151+};
152+
153+} // namespace
154+
155+#endif // SIGNON_UI_INACTIVITY_TIMER_H
156
157=== modified file 'src/indicator-service.cpp'
158--- src/indicator-service.cpp 2013-01-23 07:48:35 +0000
159+++ src/indicator-service.cpp 2013-03-14 13:21:22 +0000
160@@ -121,14 +121,23 @@
161
162 void IndicatorServicePrivate::RemoveFailures(const QSet<uint> &accountIds)
163 {
164+ Q_Q(IndicatorService);
165 m_failures.subtract(accountIds);
166 notifyPropertyChanged("Failures");
167+ if (q->isIdle()) {
168+ Q_EMIT q->isIdleChanged();
169+ }
170 }
171
172 void IndicatorServicePrivate::ReportFailure(uint accountId,
173 const QVariantMap &notification)
174 {
175+ Q_Q(IndicatorService);
176+ bool wasIdle = q->isIdle();
177 m_failures.insert(accountId);
178+ if (wasIdle) {
179+ Q_EMIT q->isIdleChanged();
180+ }
181
182 /* If the original client data is provided, we remember it: it can
183 * be used to replay the authentication later.
184@@ -249,6 +258,8 @@
185
186 void IndicatorServicePrivate::onReauthenticatorFinished(bool success)
187 {
188+ Q_Q(IndicatorService);
189+
190 Reauthenticator *reauthenticator =
191 qobject_cast<Reauthenticator*>(sender());
192
193@@ -277,6 +288,7 @@
194
195 if (m_failures.isEmpty()) {
196 ClearErrorStatus();
197+ Q_EMIT q->isIdleChanged();
198 }
199 }
200
201@@ -342,4 +354,10 @@
202 return d->m_errorStatus;
203 }
204
205+bool IndicatorService::isIdle() const
206+{
207+ Q_D(const IndicatorService);
208+ return d->m_failures.isEmpty();
209+}
210+
211 #include "indicator-service.moc"
212
213=== modified file 'src/indicator-service.h'
214--- src/indicator-service.h 2012-03-06 13:54:30 +0000
215+++ src/indicator-service.h 2013-03-14 13:21:22 +0000
216@@ -36,6 +36,7 @@
217 class IndicatorService: public QObject
218 {
219 Q_OBJECT
220+ Q_PROPERTY(bool isIdle READ isIdle NOTIFY isIdleChanged)
221
222 public:
223
224@@ -52,6 +53,10 @@
225
226 QSet<uint> failures() const;
227 bool errorStatus() const;
228+ bool isIdle() const;
229+
230+Q_SIGNALS:
231+ void isIdleChanged();
232
233 private:
234 IndicatorServicePrivate *d_ptr;
235
236=== modified file 'src/main.cpp'
237--- src/main.cpp 2013-02-01 17:11:24 +0000
238+++ src/main.cpp 2013-03-14 13:21:22 +0000
239@@ -20,6 +20,7 @@
240
241 #include "debug.h"
242 #include "i18n.h"
243+#include "inactivity-timer.h"
244 #include "indicator-service.h"
245 #include "my-network-proxy-factory.h"
246 #include "service.h"
247@@ -75,24 +76,26 @@
248 QNetworkProxyFactory::setApplicationProxyFactory(proxyFactory);
249
250 Service *service = new Service();
251- if (daemonTimeout > 0)
252- service->setTimeout(daemonTimeout);
253 QDBusConnection connection = QDBusConnection::sessionBus();
254 connection.registerService(QLatin1String(serviceName));
255 connection.registerObject(QLatin1String(objectPath),
256 service,
257 QDBusConnection::ExportAllContents);
258- /* FIXME: before quitting we should check if the IndicatorService is idle
259- * too. However, since this feature is used for unit tests only, for the
260- * time being this is fine.
261- */
262- QObject::connect(service, SIGNAL(idleTimeout()), &app, SLOT(quit()));
263
264 IndicatorService *indicatorService = new IndicatorService();
265 connection.registerService(QLatin1String(WEBCREDENTIALS_BUS_NAME));
266 connection.registerObject(QLatin1String(WEBCREDENTIALS_OBJECT_PATH),
267 indicatorService->serviceObject());
268
269+ InactivityTimer *inactivityTimer = 0;
270+ if (daemonTimeout > 0) {
271+ inactivityTimer = new InactivityTimer(daemonTimeout * 1000);
272+ inactivityTimer->watchObject(service);
273+ inactivityTimer->watchObject(indicatorService);
274+ QObject::connect(inactivityTimer, SIGNAL(timeout()),
275+ &app, SLOT(quit()));
276+ }
277+
278 int ret = app.exec();
279
280 connection.unregisterService(QLatin1String(WEBCREDENTIALS_BUS_NAME));
281@@ -103,6 +106,8 @@
282 connection.unregisterObject(QLatin1String(objectPath));
283 delete service;
284
285+ delete inactivityTimer;
286+
287 return ret;
288 }
289
290
291=== modified file 'src/service.cpp'
292--- src/service.cpp 2012-04-03 11:46:12 +0000
293+++ src/service.cpp 2013-03-14 13:21:22 +0000
294@@ -23,7 +23,6 @@
295 #include "debug.h"
296 #include "request.h"
297
298-#include <QTimer>
299 #include <QQueue>
300
301 using namespace SignOnUi;
302@@ -41,24 +40,16 @@
303 ServicePrivate(Service *service);
304 ~ServicePrivate();
305
306- void setTimeout(int timeout);
307-
308 RequestQueue &queueForWindowId(WId windowId);
309 void enqueue(Request *request);
310 void runQueue(RequestQueue &queue);
311 void cancelUiRequest(const QString &requestId);
312
313-private:
314- void resetTimer();
315-
316 private Q_SLOTS:
317 void onRequestCompleted();
318- void onTimeout();
319
320 private:
321 mutable Service *q_ptr;
322- QTimer m_timer;
323- int m_timeout;
324 /* each window Id has a different queue */
325 QMap<WId,RequestQueue> m_requests;
326 };
327@@ -67,41 +58,14 @@
328
329 ServicePrivate::ServicePrivate(Service *service):
330 QObject(service),
331- q_ptr(service),
332- m_timeout(0)
333+ q_ptr(service)
334 {
335- m_timer.setSingleShot(true);
336- QObject::connect(&m_timer, SIGNAL(timeout()),
337- this, SLOT(onTimeout()));
338 }
339
340 ServicePrivate::~ServicePrivate()
341 {
342 }
343
344-void ServicePrivate::setTimeout(int timeout)
345-{
346- m_timeout = timeout * 1000;
347- resetTimer();
348-}
349-
350-void ServicePrivate::resetTimer()
351-{
352- m_timer.stop();
353- if (m_timeout > 0) {
354- m_timer.start(m_timeout);
355- }
356-}
357-
358-void ServicePrivate::onTimeout()
359-{
360- Q_Q(Service);
361-
362- if (m_requests.isEmpty()) {
363- Q_EMIT q->idleTimeout();
364- }
365-}
366-
367 RequestQueue &ServicePrivate::queueForWindowId(WId windowId)
368 {
369 if (!m_requests.contains(windowId)) {
370@@ -113,13 +77,18 @@
371
372 void ServicePrivate::enqueue(Request *request)
373 {
374- resetTimer();
375+ Q_Q(Service);
376+ bool wasIdle = q->isIdle();
377
378 WId windowId = request->windowId();
379
380 RequestQueue &queue = queueForWindowId(windowId);
381 queue.enqueue(request);
382
383+ if (wasIdle) {
384+ Q_EMIT q->isIdleChanged();
385+ }
386+
387 runQueue(queue);
388 }
389
390@@ -140,7 +109,7 @@
391
392 void ServicePrivate::onRequestCompleted()
393 {
394- resetTimer();
395+ Q_Q(Service);
396
397 Request *request = qobject_cast<Request*>(sender());
398 WId windowId = request->windowId();
399@@ -160,6 +129,10 @@
400 /* start the next request */
401 runQueue(queue);
402 }
403+
404+ if (q->isIdle()) {
405+ Q_EMIT q->isIdleChanged();
406+ }
407 }
408
409 void ServicePrivate::cancelUiRequest(const QString &requestId)
410@@ -193,10 +166,10 @@
411 {
412 }
413
414-void Service::setTimeout(int timeout)
415+bool Service::isIdle() const
416 {
417- Q_D(Service);
418- d->setTimeout(timeout);
419+ Q_D(const Service);
420+ return d->m_requests.isEmpty();
421 }
422
423 QVariantMap Service::queryDialog(const QVariantMap &parameters)
424
425=== modified file 'src/service.h'
426--- src/service.h 2012-04-03 11:46:12 +0000
427+++ src/service.h 2013-03-14 13:21:22 +0000
428@@ -32,13 +32,14 @@
429 class Service: public QObject, protected QDBusContext
430 {
431 Q_OBJECT
432+ Q_PROPERTY(bool isIdle READ isIdle NOTIFY isIdleChanged)
433 Q_CLASSINFO("D-Bus Interface", "com.nokia.singlesignonui")
434
435 public:
436 explicit Service(QObject *parent = 0);
437 ~Service();
438
439- void setTimeout(int timeout);
440+ bool isIdle() const;
441
442 public Q_SLOTS:
443 QVariantMap queryDialog(const QVariantMap &parameters);
444@@ -46,7 +47,7 @@
445 Q_NOREPLY void cancelUiRequest(const QString &requestId);
446
447 Q_SIGNALS:
448- void idleTimeout();
449+ void isIdleChanged();
450
451 private:
452 ServicePrivate *d_ptr;
453
454=== modified file 'src/src.pro'
455--- src/src.pro 2013-01-23 07:48:35 +0000
456+++ src/src.pro 2013-03-14 13:21:22 +0000
457@@ -34,6 +34,7 @@
458 dialog.h \
459 errors.h \
460 i18n.h \
461+ inactivity-timer.h \
462 indicator-service.h \
463 network-access-manager.h \
464 reauthenticator.h \
465@@ -49,6 +50,7 @@
466 dialog-request.cpp \
467 dialog.cpp \
468 i18n.cpp \
469+ inactivity-timer.cpp \
470 indicator-service.cpp \
471 main.cpp \
472 my-network-proxy-factory.cpp \
473
474=== added file 'tests/unit/tst_inactivity_timer.cpp'
475--- tests/unit/tst_inactivity_timer.cpp 1970-01-01 00:00:00 +0000
476+++ tests/unit/tst_inactivity_timer.cpp 2013-03-14 13:21:22 +0000
477@@ -0,0 +1,143 @@
478+/*
479+ * This file is part of signon-ui
480+ *
481+ * Copyright (C) 2013 Canonical Ltd.
482+ *
483+ * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
484+ *
485+ * This program is free software: you can redistribute it and/or modify it
486+ * under the terms of the GNU General Public License version 3, as published
487+ * by the Free Software Foundation.
488+ *
489+ * This program is distributed in the hope that it will be useful, but
490+ * WITHOUT ANY WARRANTY; without even the implied warranties of
491+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
492+ * PURPOSE. See the GNU General Public License for more details.
493+ *
494+ * You should have received a copy of the GNU General Public License along
495+ * with this program. If not, see <http://www.gnu.org/licenses/>.
496+ */
497+
498+#include "debug.h"
499+#include "inactivity-timer.h"
500+
501+#include <QDebug>
502+#include <QObject>
503+#include <QSignalSpy>
504+#include <QTest>
505+
506+using namespace SignOnUi;
507+
508+class InactivityTest: public QObject
509+{
510+ Q_OBJECT
511+
512+public:
513+ InactivityTest() {};
514+
515+private Q_SLOTS:
516+ void testAlwaysIdle();
517+ void testIdleThenBusy();
518+ void testStartBusy();
519+};
520+
521+class TestObject: public QObject
522+{
523+ Q_OBJECT
524+ Q_PROPERTY(bool isIdle READ isIdle NOTIFY isIdleChanged)
525+
526+public:
527+ TestObject(): QObject(0), m_isIdle(false) {}
528+ ~TestObject() {}
529+
530+ bool isIdle() const { return m_isIdle; }
531+ void setIdle(bool idle) {
532+ if (idle == m_isIdle) return;
533+ m_isIdle = idle;
534+ Q_EMIT isIdleChanged();
535+ }
536+
537+Q_SIGNALS:
538+ void isIdleChanged();
539+
540+private:
541+ bool m_isIdle;
542+};
543+
544+void InactivityTest::testAlwaysIdle()
545+{
546+ InactivityTimer inactivityTimer(100);
547+ QSignalSpy timeout(&inactivityTimer, SIGNAL(timeout()));
548+
549+ TestObject object1;
550+ object1.setIdle(true);
551+ inactivityTimer.watchObject(&object1);
552+
553+ TestObject object2;
554+ object2.setIdle(true);
555+ inactivityTimer.watchObject(&object2);
556+
557+ QCOMPARE(timeout.count(), 0);
558+ QTest::qWait(150);
559+ QCOMPARE(timeout.count(), 1);
560+}
561+
562+void InactivityTest::testIdleThenBusy()
563+{
564+ InactivityTimer inactivityTimer(100);
565+ QSignalSpy timeout(&inactivityTimer, SIGNAL(timeout()));
566+
567+ TestObject object1;
568+ object1.setIdle(true);
569+ inactivityTimer.watchObject(&object1);
570+
571+ TestObject object2;
572+ object2.setIdle(true);
573+ inactivityTimer.watchObject(&object2);
574+
575+ QCOMPARE(timeout.count(), 0);
576+
577+ QTest::qWait(30);
578+ QCOMPARE(timeout.count(), 0);
579+ object2.setIdle(false);
580+
581+ QTest::qWait(100);
582+ QCOMPARE(timeout.count(), 0);
583+ object2.setIdle(true);
584+ QTest::qWait(30);
585+ QCOMPARE(timeout.count(), 0);
586+
587+ QTest::qWait(100);
588+ QCOMPARE(timeout.count(), 1);
589+}
590+
591+void InactivityTest::testStartBusy()
592+{
593+ InactivityTimer inactivityTimer(100);
594+ QSignalSpy timeout(&inactivityTimer, SIGNAL(timeout()));
595+
596+ TestObject object1;
597+ inactivityTimer.watchObject(&object1);
598+
599+ TestObject object2;
600+ inactivityTimer.watchObject(&object2);
601+
602+ QCOMPARE(timeout.count(), 0);
603+
604+ QTest::qWait(130);
605+ QCOMPARE(timeout.count(), 0);
606+ object2.setIdle(true);
607+
608+ QTest::qWait(130);
609+ QCOMPARE(timeout.count(), 0);
610+ object1.setIdle(true);
611+
612+ QTest::qWait(30);
613+ QCOMPARE(timeout.count(), 0);
614+
615+ QTest::qWait(100);
616+ QCOMPARE(timeout.count(), 1);
617+}
618+
619+QTEST_MAIN(InactivityTest);
620+#include "tst_inactivity_timer.moc"
621
622=== added file 'tests/unit/tst_inactivity_timer.pro'
623--- tests/unit/tst_inactivity_timer.pro 1970-01-01 00:00:00 +0000
624+++ tests/unit/tst_inactivity_timer.pro 2013-03-14 13:21:22 +0000
625@@ -0,0 +1,37 @@
626+include(../../common-project-config.pri)
627+include($${TOP_SRC_DIR}/common-vars.pri)
628+include($${TOP_SRC_DIR}/common-installs-config.pri)
629+
630+TARGET = tst_inactivity_timer
631+
632+CONFIG += \
633+ build_all \
634+ debug \
635+ qtestlib
636+
637+QT += \
638+ core
639+
640+SOURCES += \
641+ tst_inactivity_timer.cpp \
642+ $$TOP_SRC_DIR/src/debug.cpp \
643+ $$TOP_SRC_DIR/src/inactivity-timer.cpp
644+HEADERS += \
645+ $$TOP_SRC_DIR/src/debug.h \
646+ $$TOP_SRC_DIR/src/inactivity-timer.h
647+
648+INCLUDEPATH += \
649+ . \
650+ $$TOP_SRC_DIR/src
651+
652+QMAKE_CXXFLAGS += \
653+ -fno-exceptions \
654+ -fno-rtti
655+
656+DEFINES += \
657+ DEBUG_ENABLED \
658+ UNIT_TESTS
659+
660+check.commands = "xvfb-run -a ./$$TARGET"
661+check.depends = $$TARGET
662+QMAKE_EXTRA_TARGETS += check
663
664=== renamed file 'tests/unit/unit.pro' => 'tests/unit/tst_signon_ui.pro'
665=== added file 'tests/unit/unit.pro'
666--- tests/unit/unit.pro 1970-01-01 00:00:00 +0000
667+++ tests/unit/unit.pro 2013-03-14 13:21:22 +0000
668@@ -0,0 +1,4 @@
669+TEMPLATE = subdirs
670+SUBDIRS = \
671+ tst_inactivity_timer.pro \
672+ tst_signon_ui.pro

Subscribers

People subscribed via source and target branches

to all changes: