Merge lp:~mardy/ubuntu-system-settings-online-accounts/rtm-fixes into lp:ubuntu-system-settings-online-accounts/rtm-14.09

Proposed by Alberto Mardegan on 2014-11-28
Status: Merged
Approved by: David Barth on 2015-01-08
Approved revision: 206
Merged at revision: 203
Proposed branch: lp:~mardy/ubuntu-system-settings-online-accounts/rtm-fixes
Merge into: lp:ubuntu-system-settings-online-accounts/rtm-14.09
Diff against target: 1412 lines (+753/-50)
27 files modified
debian/changelog (+11/-0)
debian/control (+1/-0)
online-accounts-service/mir-helper-stub.cpp (+2/-2)
online-accounts-service/mir-helper.cpp (+23/-12)
online-accounts-service/mir-helper.h (+4/-1)
online-accounts-service/request.cpp (+15/-1)
online-accounts-service/request.h (+3/-0)
online-accounts-service/ui-proxy.cpp (+24/-12)
online-accounts-ui/dialog-request.cpp (+286/-0)
online-accounts-ui/dialog-request.h (+54/-0)
online-accounts-ui/ipc.h (+1/-0)
online-accounts-ui/online-accounts-ui.pro (+3/-0)
online-accounts-ui/provider-request.cpp (+7/-11)
online-accounts-ui/qml/ProviderRequest.qml (+14/-0)
online-accounts-ui/qml/SignOnUiDialog.qml (+115/-0)
online-accounts-ui/request.cpp (+15/-1)
online-accounts-ui/request.h (+2/-0)
online-accounts-ui/signonui-request.cpp (+32/-2)
online-accounts-ui/ui-server.cpp (+1/-0)
online-accounts-ui/ui.qrc (+1/-0)
plugins/OnlineAccountsPlugin/application-manager.cpp (+11/-1)
plugins/module/ServiceItem.qml (+1/-2)
tests/online-accounts-service/mock/request-mock.cpp (+13/-0)
tests/online-accounts-service/mock/request-mock.h (+1/-0)
tests/online-accounts-service/tst_ui_proxy.cpp (+71/-1)
tests/online-accounts-ui/tst_signonui_request.pro (+1/-0)
tests/plugin/tst_application_manager.cpp (+41/-4)
To merge this branch: bzr merge lp:~mardy/ubuntu-system-settings-online-accounts/rtm-fixes
Reviewer Review Type Date Requested Status
David Barth (community) 2014-11-28 Approve on 2014-11-28
Review via email: mp+243134@code.launchpad.net

Commit message

Backport of two bugfixes:

- Handle early authentication requests in the same trust session
- Handle requests from unconfined applications

Description of the change

Backport of two bugfixes:

- Handle early authentication requests in the same trust session
- Handle requests from unconfined applications

To post a comment you must log in.
David Barth (dbarth) :
review: Approve
204. By Alberto Mardegan on 2014-12-08

Implement QML dialog for password queries

Authentication plugins can request SignOnUi to show a login form to the user. Support for this action is implemented by unity7's signon-ui, but was never implemented in this project.

205. By Alberto Mardegan on 2015-01-05

Make sure apps don't appear on top of each other

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2014-10-29 17:10:11 +0000
3+++ debian/changelog 2015-01-08 13:59:01 +0000
4@@ -1,3 +1,14 @@
5+ubuntu-system-settings-online-accounts (0.5+14.10.20141029~rtm-0ubuntu2) UNRELEASED; urgency=medium
6+
7+ * Backport a few bugfixes:
8+ - Handle requests from unconfined applications (LP: #1376445)
9+ - Implement password prompt UI (LP: #1379863)
10+ - Handle early authentication requests in the same trust session (LP:
11+ #1380914)
12+ - Make sure apps don't appear on top of each other (LP: #1384314)
13+
14+ -- Alberto Mardegan <alberto.mardegan@canonical.com> Thu, 08 Jan 2015 14:55:37 +0100
15+
16 ubuntu-system-settings-online-accounts (0.5+14.10.20141029~rtm-0ubuntu1) 14.09; urgency=low
17
18 [ Ubuntu daily release ]
19
20=== modified file 'debian/control'
21--- debian/control 2014-10-28 17:51:37 +0000
22+++ debian/control 2015-01-08 13:59:01 +0000
23@@ -6,6 +6,7 @@
24 pkg-config,
25 python3:any,
26 libaccounts-qt5-dev (>= 1.13),
27+ libapparmor-dev,
28 libclick-0.4-dev,
29 libmirclient-dev [!powerpc !ppc64 !ppc64el],
30 libnotify-dev,
31
32=== modified file 'online-accounts-service/mir-helper-stub.cpp'
33--- online-accounts-service/mir-helper-stub.cpp 2014-08-18 13:24:54 +0000
34+++ online-accounts-service/mir-helper-stub.cpp 2015-01-08 13:59:01 +0000
35@@ -62,8 +62,8 @@
36 return m_instance;
37 }
38
39-PromptSession *MirHelper::createPromptSession(pid_t initiatorPid)
40+PromptSessionP MirHelper::createPromptSession(pid_t initiatorPid)
41 {
42 Q_UNUSED(initiatorPid);
43- return 0;
44+ return PromptSessionP();
45 }
46
47=== modified file 'online-accounts-service/mir-helper.cpp'
48--- online-accounts-service/mir-helper.cpp 2014-09-04 14:33:01 +0000
49+++ online-accounts-service/mir-helper.cpp 2015-01-08 13:59:01 +0000
50@@ -24,8 +24,9 @@
51 #include <mir_toolkit/mir_client_library.h>
52 #include <mir_toolkit/mir_prompt_session.h>
53
54-#include <QList>
55+#include <QHash>
56 #include <QStandardPaths>
57+#include <QWeakPointer>
58
59 using namespace OnlineAccountsUi;
60
61@@ -36,12 +37,13 @@
62 class PromptSessionPrivate
63 {
64 public:
65- inline PromptSessionPrivate(MirPromptSession *session);
66+ inline PromptSessionPrivate(MirPromptSession *session, pid_t initiatorPid);
67 inline ~PromptSessionPrivate();
68
69 void emitFinished() { Q_EMIT q_ptr->finished(); }
70
71 MirPromptSession *m_mirSession;
72+ pid_t m_initiatorPid;
73 QList<int> m_fds;
74 mutable PromptSession *q_ptr;
75 };
76@@ -61,14 +63,16 @@
77 private:
78 friend class PromptSession;
79 MirConnection *m_connection;
80- QList<PromptSession*> m_sessions;
81+ QHash<pid_t,QWeakPointer<PromptSession> > m_sessions;
82 mutable MirHelper *q_ptr;
83 };
84
85 } // namespace
86
87-PromptSessionPrivate::PromptSessionPrivate(MirPromptSession *session):
88- m_mirSession(session)
89+PromptSessionPrivate::PromptSessionPrivate(MirPromptSession *session,
90+ pid_t initiatorPid):
91+ m_mirSession(session),
92+ m_initiatorPid(initiatorPid)
93 {
94 }
95
96@@ -82,14 +86,13 @@
97 d_ptr(priv)
98 {
99 priv->q_ptr = this;
100- MirHelperPrivate *helperPrivate = MirHelper::instance()->d_ptr;
101- helperPrivate->m_sessions.append(this);
102 }
103
104 PromptSession::~PromptSession()
105 {
106+ Q_D(PromptSession);
107 MirHelperPrivate *helperPrivate = MirHelper::instance()->d_ptr;
108- helperPrivate->m_sessions.removeOne(this);
109+ helperPrivate->m_sessions.remove(d->m_initiatorPid);
110 delete d_ptr;
111 }
112
113@@ -153,7 +156,7 @@
114
115 void MirHelperPrivate::onSessionStopped(MirPromptSession *mirSession)
116 {
117- Q_FOREACH(PromptSession *session, m_sessions) {
118+ Q_FOREACH(PromptSessionP session, m_sessions) {
119 if (mirSession == session->d_ptr->m_mirSession) {
120 session->d_ptr->emitFinished();
121 }
122@@ -177,7 +180,7 @@
123 return 0;
124 }
125
126- return new PromptSession(new PromptSessionPrivate(mirSession));
127+ return new PromptSession(new PromptSessionPrivate(mirSession, initiatorPid));
128 }
129
130 MirHelper::MirHelper(QObject *parent):
131@@ -199,10 +202,18 @@
132 return m_instance;
133 }
134
135-PromptSession *MirHelper::createPromptSession(pid_t initiatorPid)
136+PromptSessionP MirHelper::createPromptSession(pid_t initiatorPid)
137 {
138 Q_D(MirHelper);
139- return d->createPromptSession(initiatorPid);
140+ PromptSessionP session = d->m_sessions.value(initiatorPid);
141+ if (session.isNull()) {
142+ PromptSession *s = d->createPromptSession(initiatorPid);
143+ if (s) {
144+ session = PromptSessionP(s);
145+ d->m_sessions.insert(initiatorPid, session);
146+ }
147+ }
148+ return session;
149 }
150
151 #include "mir-helper.moc"
152
153=== modified file 'online-accounts-service/mir-helper.h'
154--- online-accounts-service/mir-helper.h 2014-09-04 08:27:19 +0000
155+++ online-accounts-service/mir-helper.h 2015-01-08 13:59:01 +0000
156@@ -22,6 +22,7 @@
157 #define OAU_MIR_HELPER_H
158
159 #include <QObject>
160+#include <QSharedPointer>
161
162 namespace OnlineAccountsUi {
163
164@@ -49,6 +50,8 @@
165 Q_DECLARE_PRIVATE(PromptSession)
166 };
167
168+typedef QSharedPointer<PromptSession> PromptSessionP;
169+
170 class MirHelper: public QObject
171 {
172 Q_OBJECT
173@@ -56,7 +59,7 @@
174 public:
175 static MirHelper *instance();
176
177- PromptSession *createPromptSession(pid_t initiatorPid);
178+ PromptSessionP createPromptSession(pid_t initiatorPid);
179
180 private:
181 explicit MirHelper(QObject *parent = 0);
182
183=== modified file 'online-accounts-service/request.cpp'
184--- online-accounts-service/request.cpp 2014-08-06 13:49:45 +0000
185+++ online-accounts-service/request.cpp 2015-01-08 13:59:01 +0000
186@@ -65,6 +65,7 @@
187 QVariantMap m_parameters;
188 QString m_clientApparmorProfile;
189 bool m_inProgress;
190+ int m_delay;
191 };
192
193 } // namespace
194@@ -78,7 +79,8 @@
195 m_connection(connection),
196 m_message(message),
197 m_parameters(parameters),
198- m_inProgress(false)
199+ m_inProgress(false),
200+ m_delay(0)
201 {
202 m_clientApparmorProfile = findClientApparmorProfile();
203 }
204@@ -176,6 +178,18 @@
205 return d->m_message.interface();
206 }
207
208+void Request::setDelay(int delay)
209+{
210+ Q_D(Request);
211+ d->m_delay = delay;
212+}
213+
214+int Request::delay() const
215+{
216+ Q_D(const Request);
217+ return d->m_delay;
218+}
219+
220 void Request::cancel()
221 {
222 setCanceled();
223
224=== modified file 'online-accounts-service/request.h'
225--- online-accounts-service/request.h 2014-08-06 13:49:45 +0000
226+++ online-accounts-service/request.h 2015-01-08 13:59:01 +0000
227@@ -49,6 +49,9 @@
228 QString clientApparmorProfile() const;
229 QString interface() const;
230
231+ void setDelay(int delay);
232+ int delay() const;
233+
234 public Q_SLOTS:
235 void cancel();
236
237
238=== modified file 'online-accounts-service/ui-proxy.cpp'
239--- online-accounts-service/ui-proxy.cpp 2014-09-04 09:44:53 +0000
240+++ online-accounts-service/ui-proxy.cpp 2015-01-08 13:59:01 +0000
241@@ -31,6 +31,7 @@
242 #include <QProcess>
243 #include <QProcessEnvironment>
244 #include <QStandardPaths>
245+#include <QTimer>
246 #include <SignOn/uisessiondata_priv.h>
247
248 using namespace OnlineAccountsUi;
249@@ -58,17 +59,19 @@
250 void onNewConnection();
251 void onDataReady(QByteArray &data);
252 void onRequestCompleted();
253+ void onFinishedTimer();
254
255 private:
256 QProcess m_process;
257 QLocalServer m_server;
258 QLocalSocket *m_socket;
259 OnlineAccountsUi::Ipc m_ipc;
260+ QTimer m_finishedTimer;
261 int m_nextRequestId;
262 QMap<int,Request*> m_requests;
263 QStringList m_handlers;
264 pid_t m_clientPid;
265- PromptSession *m_promptSession;
266+ PromptSessionP m_promptSession;
267 mutable UiProxy *q_ptr;
268 };
269
270@@ -79,7 +82,6 @@
271 m_socket(0),
272 m_nextRequestId(0),
273 m_clientPid(clientPid),
274- m_promptSession(0),
275 q_ptr(uiProxy)
276 {
277 QObject::connect(&m_server, SIGNAL(newConnection()),
278@@ -87,6 +89,10 @@
279 QObject::connect(&m_ipc, SIGNAL(dataReady(QByteArray &)),
280 this, SLOT(onDataReady(QByteArray &)));
281 m_process.setProcessChannelMode(QProcess::ForwardedChannels);
282+
283+ m_finishedTimer.setSingleShot(true);
284+ QObject::connect(&m_finishedTimer, SIGNAL(timeout()),
285+ this, SLOT(onFinishedTimer()));
286 }
287
288 UiProxyPrivate::~UiProxyPrivate()
289@@ -96,8 +102,6 @@
290 request->cancel();
291 }
292
293- delete m_promptSession;
294-
295 if (m_socket) {
296 m_socket->abort();
297 delete m_socket;
298@@ -154,6 +158,7 @@
299 QString code = map.value(OAU_OPERATION_CODE).toString();
300 if (code == OAU_OPERATION_CODE_REQUEST_FINISHED) {
301 Q_ASSERT(request);
302+ request->setDelay(map.value(OAU_OPERATION_DELAY).toInt());
303 request->setResult(map.value(OAU_OPERATION_DATA).toMap());
304 } else if (code == OAU_OPERATION_CODE_REQUEST_FAILED) {
305 Q_ASSERT(request);
306@@ -192,18 +197,17 @@
307 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
308 if (!env.value("QT_QPA_PLATFORM").startsWith("ubuntu")) return;
309
310- PromptSession *session =
311+ PromptSessionP session =
312 MirHelper::instance()->createPromptSession(m_clientPid);
313 if (!session) return;
314
315 QString mirSocket = session->requestSocket();
316 if (mirSocket.isEmpty()) {
317- delete session;
318 return;
319 }
320
321 m_promptSession = session;
322- QObject::connect(m_promptSession, SIGNAL(finished()),
323+ QObject::connect(m_promptSession.data(), SIGNAL(finished()),
324 q, SIGNAL(finished()));
325
326 env.insert("MIR_SOCKET", mirSocket);
327@@ -251,17 +255,25 @@
328 sendOperation(operation);
329 }
330
331+void UiProxyPrivate::onFinishedTimer()
332+{
333+ Q_Q(UiProxy);
334+
335+ if (m_requests.isEmpty()) {
336+ Q_EMIT q->finished();
337+ }
338+}
339+
340 void UiProxyPrivate::onRequestCompleted()
341 {
342- Q_Q(UiProxy);
343-
344 Request *request = qobject_cast<Request*>(sender());
345+ Q_ASSERT(request);
346+ m_finishedTimer.setInterval(request->delay());
347+ m_finishedTimer.start();
348+
349 int id = m_requests.key(request, -1);
350 if (id != -1) {
351 m_requests.remove(id);
352- if (m_requests.isEmpty()) {
353- Q_EMIT q->finished();
354- }
355 }
356 }
357
358
359=== added file 'online-accounts-ui/dialog-request.cpp'
360--- online-accounts-ui/dialog-request.cpp 1970-01-01 00:00:00 +0000
361+++ online-accounts-ui/dialog-request.cpp 2015-01-08 13:59:01 +0000
362@@ -0,0 +1,286 @@
363+/*
364+ * This file is part of online-accounts-ui
365+ *
366+ * Copyright (C) 2014 Canonical Ltd.
367+ *
368+ * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
369+ *
370+ * This program is free software: you can redistribute it and/or modify it
371+ * under the terms of the GNU General Public License version 3, as published
372+ * by the Free Software Foundation.
373+ *
374+ * This program is distributed in the hope that it will be useful, but
375+ * WITHOUT ANY WARRANTY; without even the implied warranties of
376+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
377+ * PURPOSE. See the GNU General Public License for more details.
378+ *
379+ * You should have received a copy of the GNU General Public License along
380+ * with this program. If not, see <http://www.gnu.org/licenses/>.
381+ */
382+
383+#include "dialog-request.h"
384+
385+#include "debug.h"
386+#include "dialog.h"
387+#include "globals.h"
388+#include "i18n.h"
389+
390+#include <OnlineAccountsPlugin/request-handler.h>
391+#include <QDir>
392+#include <QQmlContext>
393+#include <QQmlEngine>
394+#include <SignOn/uisessiondata_priv.h>
395+
396+using namespace SignOnUi;
397+
398+/* These fields are temporarily defined here; they'll be eventually moved to
399+ * signond's include files. */
400+#define SSOUI_KEY_USERNAME_TEXT QLatin1String("UserNameText")
401+#define SSOUI_KEY_PASSWORD_TEXT QLatin1String("PasswordText")
402+#define SSOUI_KEY_REGISTER_URL QLatin1String("RegisterUrl")
403+#define SSOUI_KEY_REGISTER_TEXT QLatin1String("RegisterText")
404+#define SSOUI_KEY_LOGIN_TEXT QLatin1String("LoginText")
405+
406+namespace SignOnUi {
407+
408+class DialogRequestPrivate: public QObject
409+{
410+ Q_OBJECT
411+ Q_DECLARE_PUBLIC(DialogRequest)
412+ Q_PROPERTY(QString title READ title CONSTANT)
413+ Q_PROPERTY(QString userName READ userName WRITE setUserName \
414+ NOTIFY userNameChanged)
415+ Q_PROPERTY(QString password READ password WRITE setPassword \
416+ NOTIFY passwordChanged)
417+ Q_PROPERTY(QString userNameText READ userNameText CONSTANT)
418+ Q_PROPERTY(QString passwordText READ passwordText CONSTANT)
419+ Q_PROPERTY(QString message READ message CONSTANT)
420+ Q_PROPERTY(bool queryUserName READ queryUserName CONSTANT)
421+ Q_PROPERTY(bool queryPassword READ queryPassword CONSTANT)
422+ Q_PROPERTY(QUrl forgotPasswordUrl READ forgotPasswordUrl CONSTANT)
423+ Q_PROPERTY(QString forgotPasswordText READ forgotPasswordText CONSTANT)
424+ Q_PROPERTY(QUrl registerUrl READ registerUrl CONSTANT)
425+ Q_PROPERTY(QString registerText READ registerText CONSTANT)
426+ Q_PROPERTY(QString loginText READ loginText CONSTANT)
427+
428+public:
429+ DialogRequestPrivate(DialogRequest *request);
430+ ~DialogRequestPrivate();
431+
432+ void start();
433+
434+ QString title() const { return m_title; }
435+ void setUserName(const QString &userName);
436+ QString userName() const { return m_userName; }
437+ void setPassword(const QString &password);
438+ QString password() const { return m_password; }
439+ QString userNameText() const { return m_userNameText; }
440+ QString passwordText() const { return m_passwordText; }
441+ QString message() const { return m_message; }
442+ bool queryUserName() const { return m_queryUsername; }
443+ bool queryPassword() const { return m_queryPassword; }
444+ QUrl forgotPasswordUrl() const { return m_forgotPasswordUrl; }
445+ QString forgotPasswordText() const { return m_forgotPasswordText; }
446+ QUrl registerUrl() const { return m_registerUrl; }
447+ QString registerText() const { return m_registerText; }
448+ QString loginText() const { return m_loginText; }
449+
450+public Q_SLOTS:
451+ void cancel();
452+ void accept();
453+
454+Q_SIGNALS:
455+ void userNameChanged();
456+ void passwordChanged();
457+
458+private Q_SLOTS:
459+ void onFinished();
460+
461+private:
462+ void closeView();
463+
464+private:
465+ Dialog *m_dialog;
466+ QString m_title;
467+ QString m_userName;
468+ QString m_password;
469+ QString m_userNameText;
470+ QString m_passwordText;
471+ QString m_message;
472+ bool m_queryUsername;
473+ bool m_queryPassword;
474+ QUrl m_forgotPasswordUrl;
475+ QString m_forgotPasswordText;
476+ QUrl m_registerUrl;
477+ QString m_registerText;
478+ QString m_loginText;
479+ mutable DialogRequest *q_ptr;
480+};
481+
482+} // namespace
483+
484+DialogRequestPrivate::DialogRequestPrivate(DialogRequest *request):
485+ QObject(request),
486+ m_dialog(0),
487+ m_queryUsername(false),
488+ m_queryPassword(false),
489+ q_ptr(request)
490+{
491+ const QVariantMap &params = q_ptr->parameters();
492+
493+ if (params.contains(SSOUI_KEY_TITLE)) {
494+ m_title = params[SSOUI_KEY_TITLE].toString();
495+ } else if (params.contains(SSOUI_KEY_CAPTION)) {
496+ m_title = OnlineAccountsUi::_("Web authentication for %1",
497+ SIGNONUI_I18N_DOMAIN).
498+ arg(params[SSOUI_KEY_CAPTION].toString());
499+ } else {
500+ m_title = OnlineAccountsUi::_("Web authentication",
501+ SIGNONUI_I18N_DOMAIN);
502+ }
503+
504+ m_queryUsername = params.value(SSOUI_KEY_QUERYUSERNAME, false).toBool();
505+ m_userName = params.value(SSOUI_KEY_USERNAME).toString();
506+ m_userNameText = params.value(SSOUI_KEY_USERNAME_TEXT).toString();
507+ if (m_userNameText.isEmpty()) {
508+ m_userNameText = OnlineAccountsUi::_("Username:",
509+ SIGNONUI_I18N_DOMAIN);
510+ }
511+
512+ m_queryPassword = params.value(SSOUI_KEY_QUERYPASSWORD, false).toBool();
513+ m_password = params.value(SSOUI_KEY_PASSWORD).toString();
514+ m_passwordText = params.value(SSOUI_KEY_PASSWORD_TEXT).toString();
515+ if (m_passwordText.isEmpty()) {
516+ m_passwordText = OnlineAccountsUi::_("Password:",
517+ SIGNONUI_I18N_DOMAIN);
518+ }
519+
520+
521+ m_message = params.value(SSOUI_KEY_MESSAGE).toString();
522+
523+ m_forgotPasswordUrl =
524+ QUrl(params.value(SSOUI_KEY_FORGOTPASSWORDURL).toString());
525+ m_forgotPasswordText = params.value(SSOUI_KEY_FORGOTPASSWORD).toString();
526+
527+ m_registerUrl =
528+ QUrl(params.value(SSOUI_KEY_REGISTER_URL).toString());
529+ m_registerText = params.value(SSOUI_KEY_REGISTER_TEXT).toString();
530+
531+ m_loginText = params.value(SSOUI_KEY_LOGIN_TEXT).toString();
532+ if (m_loginText.isEmpty()) {
533+ m_loginText = OnlineAccountsUi::_("Sign in");
534+ }
535+}
536+
537+DialogRequestPrivate::~DialogRequestPrivate()
538+{
539+ closeView();
540+ delete m_dialog;
541+}
542+
543+void DialogRequestPrivate::start()
544+{
545+ Q_Q(DialogRequest);
546+
547+ const QVariantMap &params = q->parameters();
548+ DEBUG() << params;
549+
550+ if (!q->hasHandler()) {
551+ m_dialog = new Dialog;
552+ m_dialog->setTitle(m_title);
553+
554+ QObject::connect(m_dialog, SIGNAL(finished(int)),
555+ this, SLOT(onFinished()));
556+
557+ m_dialog->engine()->addImportPath(PLUGIN_PRIVATE_MODULE_DIR);
558+ m_dialog->rootContext()->setContextProperty("request", this);
559+ m_dialog->setSource(QUrl("qrc:/qml/SignOnUiDialog.qml"));
560+ q->setWindow(m_dialog);
561+ } else {
562+ DEBUG() << "Setting request on handler";
563+ q->handler()->setRequest(this);
564+ }
565+}
566+
567+void DialogRequestPrivate::accept()
568+{
569+ DEBUG() << "User accepted";
570+ onFinished();
571+}
572+
573+void DialogRequestPrivate::cancel()
574+{
575+ Q_Q(DialogRequest);
576+
577+ DEBUG() << "User requested to cancel";
578+ q->setCanceled();
579+ closeView();
580+}
581+
582+void DialogRequestPrivate::setUserName(const QString &userName)
583+{
584+ if (userName == m_userName) return;
585+ m_userName = userName;
586+ Q_EMIT userNameChanged();
587+}
588+
589+void DialogRequestPrivate::setPassword(const QString &password)
590+{
591+ if (password == m_password) return;
592+ m_password = password;
593+ Q_EMIT passwordChanged();
594+}
595+
596+void DialogRequestPrivate::onFinished()
597+{
598+ Q_Q(DialogRequest);
599+
600+ DEBUG() << "Dialog closed";
601+
602+ QVariantMap reply;
603+
604+ if (m_queryUsername) {
605+ reply[SSOUI_KEY_USERNAME] = m_userName;
606+ }
607+ if (m_queryPassword) {
608+ reply[SSOUI_KEY_PASSWORD] = m_password;
609+ }
610+
611+ closeView();
612+
613+ q->setResult(reply);
614+}
615+
616+void DialogRequestPrivate::closeView()
617+{
618+ Q_Q(DialogRequest);
619+
620+ if (q->hasHandler()) {
621+ q->handler()->setRequest(0);
622+ } else if (m_dialog) {
623+ m_dialog->close();
624+ }
625+}
626+
627+DialogRequest::DialogRequest(int id,
628+ const QString &clientProfile,
629+ const QVariantMap &parameters,
630+ QObject *parent):
631+ Request(id, clientProfile, parameters, parent),
632+ d_ptr(new DialogRequestPrivate(this))
633+{
634+}
635+
636+DialogRequest::~DialogRequest()
637+{
638+}
639+
640+void DialogRequest::start()
641+{
642+ Q_D(DialogRequest);
643+
644+ Request::start();
645+ d->start();
646+}
647+
648+#include "dialog-request.moc"
649
650=== added file 'online-accounts-ui/dialog-request.h'
651--- online-accounts-ui/dialog-request.h 1970-01-01 00:00:00 +0000
652+++ online-accounts-ui/dialog-request.h 2015-01-08 13:59:01 +0000
653@@ -0,0 +1,54 @@
654+/*
655+ * This file is part of online-accounts-ui
656+ *
657+ * Copyright (C) 2014 Canonical Ltd.
658+ *
659+ * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
660+ *
661+ * This program is free software: you can redistribute it and/or modify it
662+ * under the terms of the GNU General Public License version 3, as published
663+ * by the Free Software Foundation.
664+ *
665+ * This program is distributed in the hope that it will be useful, but
666+ * WITHOUT ANY WARRANTY; without even the implied warranties of
667+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
668+ * PURPOSE. See the GNU General Public License for more details.
669+ *
670+ * You should have received a copy of the GNU General Public License along
671+ * with this program. If not, see <http://www.gnu.org/licenses/>.
672+ */
673+
674+#ifndef SIGNON_UI_DIALOG_REQUEST_H
675+#define SIGNON_UI_DIALOG_REQUEST_H
676+
677+#include "signonui-request.h"
678+
679+#include <QObject>
680+
681+namespace SignOnUi {
682+
683+class DialogRequestPrivate;
684+
685+class DialogRequest: public Request
686+{
687+ Q_OBJECT
688+
689+public:
690+ explicit DialogRequest(int id,
691+ const QString &clientProfile,
692+ const QVariantMap &parameters,
693+ QObject *parent = 0);
694+ ~DialogRequest();
695+
696+ // reimplemented virtual methods
697+ void start();
698+
699+private:
700+ DialogRequestPrivate *d_ptr;
701+ Q_DECLARE_PRIVATE(DialogRequest)
702+};
703+
704+} // namespace
705+
706+#endif // SIGNON_UI_DIALOG_REQUEST_H
707+
708
709=== modified file 'online-accounts-ui/ipc.h'
710--- online-accounts-ui/ipc.h 2014-08-06 13:49:45 +0000
711+++ online-accounts-ui/ipc.h 2015-01-08 13:59:01 +0000
712@@ -33,6 +33,7 @@
713 #define OAU_OPERATION_CODE_REQUEST_FAILED "failed"
714 #define OAU_OPERATION_ID "id"
715 #define OAU_OPERATION_DATA "data"
716+#define OAU_OPERATION_DELAY "delay"
717 #define OAU_OPERATION_INTERFACE "interface"
718 #define OAU_OPERATION_CLIENT_PROFILE "profile"
719 #define OAU_OPERATION_ERROR_NAME "errname"
720
721=== modified file 'online-accounts-ui/online-accounts-ui.pro'
722--- online-accounts-ui/online-accounts-ui.pro 2014-10-28 18:18:54 +0000
723+++ online-accounts-ui/online-accounts-ui.pro 2015-01-08 13:59:01 +0000
724@@ -20,6 +20,7 @@
725
726 PKGCONFIG += \
727 accounts-qt5 \
728+ libapparmor \
729 libnotify \
730 libsignon-qt5 \
731 signon-plugins-common
732@@ -47,6 +48,7 @@
733 browser-request.cpp \
734 debug.cpp \
735 dialog.cpp \
736+ dialog-request.cpp \
737 i18n.cpp \
738 ipc.cpp \
739 main.cpp \
740@@ -62,6 +64,7 @@
741 browser-request.h \
742 debug.h \
743 dialog.h \
744+ dialog-request.h \
745 i18n.h \
746 ipc.h \
747 notification.h \
748
749=== modified file 'online-accounts-ui/provider-request.cpp'
750--- online-accounts-ui/provider-request.cpp 2014-10-03 14:56:11 +0000
751+++ online-accounts-ui/provider-request.cpp 2015-01-08 13:59:01 +0000
752@@ -24,8 +24,6 @@
753 #include "provider-request.h"
754
755 #include <OnlineAccountsPlugin/application-manager.h>
756-#include <QDesktopServices>
757-#include <QGuiApplication>
758 #include <QQmlContext>
759 #include <QQmlEngine>
760 #include <QQuickItem>
761@@ -149,14 +147,6 @@
762
763 if (!visible) {
764 q->setResult(QVariantMap());
765- /* FIXME HACK: remove when window reparenting is implemented */
766- QString profile =
767- m_applicationInfo.value(QStringLiteral("profile")).toString();
768- if (QGuiApplication::platformName().startsWith("ubuntu") &&
769- !profile.isEmpty()) {
770- QDesktopServices::openUrl(
771- QUrl(QString("application:///%1.desktop").arg(profile)));
772- }
773 }
774 }
775
776@@ -172,10 +162,16 @@
777 {
778 Q_Q(ProviderRequest);
779 DEBUG() << "Access allowed for account:" << accountId;
780+ /* If the request came from an app, add a small delay so that we could
781+ * serve an authentication request coming right after this one. */
782+ if (m_applicationInfo.value("id").toString() !=
783+ QStringLiteral("system-settings")) {
784+ q->setDelay(3000);
785+ }
786 QVariantMap result;
787 result.insert(OAU_KEY_ACCOUNT_ID, quint32(accountId));
788 q->setResult(result);
789- m_view->close();
790+ /* We keep the view opened */
791 }
792
793 ProviderRequest::ProviderRequest(const QString &interface,
794
795=== modified file 'online-accounts-ui/qml/ProviderRequest.qml'
796--- online-accounts-ui/qml/ProviderRequest.qml 2014-10-08 09:43:28 +0000
797+++ online-accounts-ui/qml/ProviderRequest.qml 2015-01-08 13:59:01 +0000
798@@ -51,6 +51,8 @@
799 on__CreatedAccountIdChanged: grantAccessIfReady()
800 onDenied: wasDenied = true
801
802+ onAllowed: loader.sourceComponent = spinnerComponent
803+
804 PageStack {
805 id: pageStack
806
807@@ -140,6 +142,18 @@
808 }
809
810 Component {
811+ id: spinnerComponent
812+ Item {
813+ ActivityIndicator {
814+ anchors.centerIn: parent
815+ width: units.gu(5)
816+ height: width
817+ running: true
818+ }
819+ }
820+ }
821+
822+ Component {
823 id: accountServiceComponent
824 AccountService {
825 autoSync: false
826
827=== added file 'online-accounts-ui/qml/SignOnUiDialog.qml'
828--- online-accounts-ui/qml/SignOnUiDialog.qml 1970-01-01 00:00:00 +0000
829+++ online-accounts-ui/qml/SignOnUiDialog.qml 2015-01-08 13:59:01 +0000
830@@ -0,0 +1,115 @@
831+import QtQuick 2.0
832+import Ubuntu.Components 0.1
833+import Ubuntu.Components.ListItems 0.1 as ListItem
834+import Ubuntu.OnlineAccounts.Plugin 1.0
835+
836+MainView {
837+ id: root
838+
839+ property var signonRequest: request
840+
841+ width: units.gu(60)
842+ height: units.gu(90)
843+
844+ Page {
845+ title: signonRequest.title
846+
847+ Column {
848+ id: loginForm
849+ anchors.left: parent.left
850+ anchors.right: parent.right
851+
852+ ListItem.Caption {
853+ visible: signonRequest.message !== ""
854+ text: signonRequest.message
855+ }
856+
857+ Label {
858+ id: userNameLabel
859+ visible: signonRequest.queryUserName
860+ text: signonRequest.userNameText
861+ }
862+
863+ TextField {
864+ id: userNameField
865+ visible: signonRequest.queryUserName
866+ text: signonRequest.userName
867+ onTextChanged: signonRequest.userName = text
868+ }
869+
870+ Column {
871+ anchors.left: parent.left
872+ anchors.right: parent.right
873+ visible: signonRequest.queryPassword
874+
875+ Label {
876+ id: passwordLabel
877+ text: signonRequest.passwordText
878+ }
879+
880+ TextField {
881+ id: passwordField
882+ text: signonRequest.password
883+ echoMode: TextInput.Password
884+ onTextChanged: signonRequest.password = text
885+ Keys.onReturnPressed: signonRequest.accept()
886+ }
887+ Label {
888+ visible: signonRequest.forgotPasswordUrl.toString() !== ""
889+ text: "<a href=\"" + signonRequest.forgotPasswordUrl + "\">" +
890+ signonRequest.forgotPasswordText + "</a>"
891+ }
892+ }
893+ }
894+
895+ Item {
896+ anchors.left: parent.left
897+ anchors.right: parent.right
898+ anchors.top: loginForm.bottom
899+ anchors.bottom: pageFooter.top
900+
901+ Row {
902+ height: childrenRect.height
903+ anchors.left: parent.left
904+ anchors.right: parent.right
905+ anchors.bottom: parent.bottom
906+ spacing: units.gu(1)
907+
908+ Button {
909+ text: i18n.dtr("ubuntu-system-settings-online-accounts", "Cancel")
910+ width: (parent.width / 2) - 0.5 * parent.spacing
911+ onClicked: signonRequest.cancel()
912+ }
913+
914+ Button {
915+ text: signonRequest.loginText
916+ width: (parent.width / 2) - 0.5 * parent.spacing
917+ onClicked: signonRequest.accept()
918+ }
919+ }
920+ }
921+
922+ Item {
923+ id: pageFooter
924+ anchors.left: parent.left
925+ anchors.right: parent.right
926+ anchors.bottom: osk.top
927+ visible: signonRequest.registerUrl.toString() !== ""
928+
929+ ListItem.ThinDivider {
930+ anchors.bottom: registerUrlLabel.top
931+ }
932+
933+ Label {
934+ anchors.bottom: parent.bottom
935+ id: registerUrlLabel
936+ text: "<a href=\"" + signonRequest.registerUrl + "\">" +
937+ signonRequest.registerText + "</a>"
938+ }
939+ }
940+
941+ KeyboardRectangle {
942+ id: osk
943+ }
944+ }
945+}
946
947=== modified file 'online-accounts-ui/request.cpp'
948--- online-accounts-ui/request.cpp 2014-08-07 13:41:03 +0000
949+++ online-accounts-ui/request.cpp 2015-01-08 13:59:01 +0000
950@@ -76,6 +76,7 @@
951 QString m_errorName;
952 QString m_errorMessage;
953 QVariantMap m_result;
954+ int m_delay;
955 };
956
957 } // namespace
958@@ -92,7 +93,8 @@
959 m_parameters(parameters),
960 m_clientApparmorProfile(clientProfile),
961 m_inProgress(false),
962- m_window(0)
963+ m_window(0),
964+ m_delay(0)
965 {
966 }
967
968@@ -241,6 +243,18 @@
969 return d->m_errorMessage;
970 }
971
972+void Request::setDelay(int delay)
973+{
974+ Q_D(Request);
975+ d->m_delay = delay;
976+}
977+
978+int Request::delay() const
979+{
980+ Q_D(const Request);
981+ return d->m_delay;
982+}
983+
984 void Request::start()
985 {
986 Q_D(Request);
987
988=== modified file 'online-accounts-ui/request.h'
989--- online-accounts-ui/request.h 2014-08-07 13:41:03 +0000
990+++ online-accounts-ui/request.h 2015-01-08 13:59:01 +0000
991@@ -53,6 +53,7 @@
992 QVariantMap result() const;
993 QString errorName() const;
994 QString errorMessage() const;
995+ int delay() const;
996
997 public Q_SLOTS:
998 virtual void start();
999@@ -68,6 +69,7 @@
1000 const QVariantMap &parameters,
1001 QObject *parent = 0);
1002 virtual void setWindow(QWindow *window);
1003+ void setDelay(int delay);
1004
1005 protected Q_SLOTS:
1006 void fail(const QString &name, const QString &message);
1007
1008=== modified file 'online-accounts-ui/signonui-request.cpp'
1009--- online-accounts-ui/signonui-request.cpp 2014-10-09 12:24:45 +0000
1010+++ online-accounts-ui/signonui-request.cpp 2015-01-08 13:59:01 +0000
1011@@ -22,6 +22,7 @@
1012
1013 #include "browser-request.h"
1014 #include "debug.h"
1015+#include "dialog-request.h"
1016 #include "globals.h"
1017 #include "notification.h"
1018
1019@@ -35,6 +36,7 @@
1020 #include <QPointer>
1021 #include <SignOn/uisessiondata.h>
1022 #include <SignOn/uisessiondata_priv.h>
1023+#include <sys/apparmor.h>
1024
1025 using namespace SignOnUi;
1026
1027@@ -203,16 +205,44 @@
1028 return new SignOnUi::BrowserRequest(id, clientProfile,
1029 parameters, parent);
1030 } else {
1031- return 0; // TODO new DialogRequest(connection, message, parameters, parent);
1032+ return new SignOnUi::DialogRequest(id, clientProfile,
1033+ parameters, parent);
1034 }
1035 }
1036 #endif
1037
1038+static QString findClientProfile(const QString &clientProfile,
1039+ const QVariantMap &parameters)
1040+{
1041+ QString profile = clientProfile;
1042+ /* If the request is coming on the SignOnUi interface from an
1043+ * unconfined process and it carries the SSOUI_KEY_PID key, it means that
1044+ * it's coming from signond. In that case, we want to know what was the
1045+ * client which originated the call.
1046+ */
1047+ if (profile == "unconfined" &&
1048+ parameters.contains(SSOUI_KEY_PID)) {
1049+ pid_t pid = parameters.value(SSOUI_KEY_PID).toUInt();
1050+ char *con = NULL, *mode = NULL;
1051+ int ret = aa_gettaskcon(pid, &con, &mode);
1052+ if (Q_LIKELY(ret >= 0)) {
1053+ profile = QString::fromUtf8(con);
1054+ /* libapparmor allocates "con" and "mode" in a single allocation,
1055+ * so freeing "con" is actually freeing both. */
1056+ free(con);
1057+ } else {
1058+ qWarning() << "Couldn't get apparmor profile of PID" << pid;
1059+ }
1060+ }
1061+ return profile;
1062+}
1063+
1064 Request::Request(int id,
1065 const QString &clientProfile,
1066 const QVariantMap &parameters,
1067 QObject *parent):
1068- OnlineAccountsUi::Request(SIGNONUI_INTERFACE, id, clientProfile,
1069+ OnlineAccountsUi::Request(SIGNONUI_INTERFACE, id,
1070+ findClientProfile(clientProfile, parameters),
1071 parameters, parent),
1072 d_ptr(new RequestPrivate(this))
1073 {
1074
1075=== modified file 'online-accounts-ui/ui-server.cpp'
1076--- online-accounts-ui/ui-server.cpp 2014-10-09 12:24:45 +0000
1077+++ online-accounts-ui/ui-server.cpp 2015-01-08 13:59:01 +0000
1078@@ -142,6 +142,7 @@
1079 OAU_OPERATION_CODE_REQUEST_FINISHED);
1080 operation.insert(OAU_OPERATION_ID, request->id());
1081 operation.insert(OAU_OPERATION_DATA, request->result());
1082+ operation.insert(OAU_OPERATION_DELAY, request->delay());
1083 operation.insert(OAU_OPERATION_INTERFACE, request->interface());
1084 sendOperation(operation);
1085 } else {
1086
1087=== modified file 'online-accounts-ui/ui.qrc'
1088--- online-accounts-ui/ui.qrc 2014-08-13 14:39:53 +0000
1089+++ online-accounts-ui/ui.qrc 2015-01-08 13:59:01 +0000
1090@@ -3,6 +3,7 @@
1091 <file>qml/AccountCreationPage.qml</file>
1092 <file>qml/AuthorizationPage.qml</file>
1093 <file>qml/ProviderRequest.qml</file>
1094+ <file>qml/SignOnUiDialog.qml</file>
1095 <file>qml/SignOnUiPage.qml</file>
1096 </qresource>
1097 </RCC>
1098
1099=== modified file 'plugins/OnlineAccountsPlugin/application-manager.cpp'
1100--- plugins/OnlineAccountsPlugin/application-manager.cpp 2014-10-06 09:33:22 +0000
1101+++ plugins/OnlineAccountsPlugin/application-manager.cpp 2015-01-08 13:59:01 +0000
1102@@ -158,7 +158,17 @@
1103 app.insert(QStringLiteral("id"), applicationId);
1104 app.insert(QStringLiteral("displayName"), application.displayName());
1105 app.insert(QStringLiteral("icon"), application.iconName());
1106- app.insert(QStringLiteral("profile"), profile);
1107+ /* The applicationMatchesProfile() test above ensures that either the peer
1108+ * is unconfined, or the profile in the .application file matches the one
1109+ * we see from our peer.
1110+ * In the first case, what we really want is the profile from the
1111+ * .application file (if that's set), to cover the case where an unconfined
1112+ * process is asking authorization on behalf of a confined app. */
1113+ QString targetProfile = d->applicationProfile(application.name());
1114+ if (targetProfile.isEmpty()) {
1115+ targetProfile = profile;
1116+ }
1117+ app.insert(QStringLiteral("profile"), targetProfile);
1118
1119 /* List all the services supported by this application */
1120 QVariantList serviceIds;
1121
1122=== modified file 'plugins/module/ServiceItem.qml'
1123--- plugins/module/ServiceItem.qml 2014-09-30 13:30:39 +0000
1124+++ plugins/module/ServiceItem.qml 2015-01-08 13:59:01 +0000
1125@@ -21,7 +21,7 @@
1126 import Ubuntu.Components.ListItems 0.1 as ListItem
1127 import Ubuntu.OnlineAccounts 0.1
1128
1129-Item {
1130+Column {
1131 property variant accountServiceHandle
1132
1133 signal applicationAdded(string applicationId)
1134@@ -29,7 +29,6 @@
1135
1136 anchors.left: parent.left
1137 anchors.right: parent.right
1138- height: childrenRect.height
1139
1140 Repeater {
1141 resources: AccountService {
1142
1143=== modified file 'tests/online-accounts-service/mock/request-mock.cpp'
1144--- tests/online-accounts-service/mock/request-mock.cpp 2014-08-25 14:54:38 +0000
1145+++ tests/online-accounts-service/mock/request-mock.cpp 2015-01-08 13:59:01 +0000
1146@@ -34,6 +34,7 @@
1147 m_message(message),
1148 m_parameters(parameters),
1149 m_inProgress(false),
1150+ m_delay(0),
1151 q_ptr(request)
1152 {
1153 }
1154@@ -95,6 +96,18 @@
1155 return d->m_message.interface();
1156 }
1157
1158+void Request::setDelay(int delay)
1159+{
1160+ Q_D(Request);
1161+ d->m_delay = delay;
1162+}
1163+
1164+int Request::delay() const
1165+{
1166+ Q_D(const Request);
1167+ return d->m_delay;
1168+}
1169+
1170 void Request::cancel()
1171 {
1172 setCanceled();
1173
1174=== modified file 'tests/online-accounts-service/mock/request-mock.h'
1175--- tests/online-accounts-service/mock/request-mock.h 2014-08-25 14:54:38 +0000
1176+++ tests/online-accounts-service/mock/request-mock.h 2015-01-08 13:59:01 +0000
1177@@ -55,6 +55,7 @@
1178 QVariantMap m_parameters;
1179 QString m_clientApparmorProfile;
1180 bool m_inProgress;
1181+ int m_delay;
1182 mutable Request *q_ptr;
1183 };
1184
1185
1186=== modified file 'tests/online-accounts-service/tst_ui_proxy.cpp'
1187--- tests/online-accounts-service/tst_ui_proxy.cpp 2014-08-26 08:39:20 +0000
1188+++ tests/online-accounts-service/tst_ui_proxy.cpp 2015-01-08 13:59:01 +0000
1189@@ -45,6 +45,7 @@
1190 ~RemoteProcess();
1191
1192 bool run();
1193+ void setDelay(int delay) { m_delay = delay; }
1194 void setResult(const QVariantMap &result);
1195 void fail(const QString &errorName, const QString &errorMessage);
1196 void registerHandler(const QString &matchId);
1197@@ -66,6 +67,7 @@
1198 QProcess *m_process;
1199 QVariantMap m_lastData;
1200 int m_requestId;
1201+ int m_delay;
1202 QString m_requestInterface;
1203 QLocalSocket m_socket;
1204 Ipc m_ipc;
1205@@ -78,7 +80,8 @@
1206 QObject(process),
1207 m_program(program),
1208 m_arguments(arguments),
1209- m_process(process)
1210+ m_process(process),
1211+ m_delay(0)
1212 {
1213 QObject::connect(&m_ipc, SIGNAL(dataReady(QByteArray &)),
1214 this, SLOT(onDataReady(QByteArray &)));
1215@@ -111,6 +114,7 @@
1216 operation.insert(OAU_OPERATION_ID, m_requestId);
1217 operation.insert(OAU_OPERATION_INTERFACE, m_requestInterface);
1218 operation.insert(OAU_OPERATION_DATA, result);
1219+ operation.insert(OAU_OPERATION_DELAY, m_delay);
1220 sendOperation(operation);
1221 deleteLater();
1222 }
1223@@ -196,6 +200,8 @@
1224 void testInit();
1225 void testRequest_data();
1226 void testRequest();
1227+ void testRequestDelay_data();
1228+ void testRequestDelay();
1229 void testHandler();
1230 void testWrapper();
1231
1232@@ -335,6 +341,70 @@
1233 delete proxy;
1234 }
1235
1236+void UiProxyTest::testRequestDelay_data()
1237+{
1238+ QTest::addColumn<int>("delay");
1239+
1240+ QTest::newRow("no delay") << 0;
1241+
1242+ QTest::newRow("300 ms") << 300;
1243+
1244+ QTest::newRow("half second") << 500;
1245+}
1246+
1247+void UiProxyTest::testRequestDelay()
1248+{
1249+ QFETCH(int, delay);
1250+
1251+ QVariantMap parameters;
1252+ parameters.insert("greeting", "Hello!");
1253+ Request *request = createRequest(OAU_INTERFACE, "hello",
1254+ "unconfined", parameters);
1255+ RequestPrivate *r = RequestPrivate::mocked(request);
1256+ QSignalSpy requestFailCalled(r, SIGNAL(failCalled(QString,QString)));
1257+ QSignalSpy requestSetResultCalled(r, SIGNAL(setResultCalled(QVariantMap)));
1258+
1259+ UiProxy *proxy = new UiProxy(0, this);
1260+ QVERIFY(proxy->init());
1261+
1262+ QSignalSpy finished(proxy, SIGNAL(finished()));
1263+ proxy->handleRequest(request);
1264+
1265+ QTRY_VERIFY(!remoteProcesses.isEmpty());
1266+ QCOMPARE(remoteProcesses.count(), 1);
1267+
1268+ RemoteProcess *process = remoteProcesses.values().first();
1269+ QVERIFY(process);
1270+ QSignalSpy dataReceived(process, SIGNAL(dataReceived(QVariantMap)));
1271+
1272+ /* Check the received data */
1273+ if (process->lastReceived().isEmpty()) {
1274+ QVERIFY(dataReceived.wait());
1275+ }
1276+
1277+ QVariantMap result;
1278+ result.insert("response", "OK");
1279+ process->setDelay(delay);
1280+ process->setResult(result);
1281+ QVERIFY(requestSetResultCalled.wait());
1282+ QCOMPARE(requestSetResultCalled.count(), 1);
1283+ QCOMPARE(requestSetResultCalled.at(0).at(0).toMap(), result);
1284+
1285+ QCOMPARE(request->delay(), delay);
1286+
1287+ int wontFinishBefore = qMax(delay - 200, 0);
1288+ if (wontFinishBefore > 0) {
1289+ QTest::qWait(wontFinishBefore);
1290+ QCOMPARE(finished.count(), 0);
1291+ QTest::qWait(250);
1292+ } else {
1293+ QTest::qWait(10);
1294+ }
1295+ QCOMPARE(finished.count(), 1);
1296+
1297+ delete proxy;
1298+}
1299+
1300 void UiProxyTest::testHandler()
1301 {
1302 UiProxy *proxy = new UiProxy(0, this);
1303
1304=== modified file 'tests/online-accounts-ui/tst_signonui_request.pro'
1305--- tests/online-accounts-ui/tst_signonui_request.pro 2014-10-09 12:24:45 +0000
1306+++ tests/online-accounts-ui/tst_signonui_request.pro 2015-01-08 13:59:01 +0000
1307@@ -10,6 +10,7 @@
1308
1309 PKGCONFIG += \
1310 accounts-qt5 \
1311+ libapparmor \
1312 libsignon-qt5 \
1313 signon-plugins-common
1314
1315
1316=== modified file 'tests/plugin/tst_application_manager.cpp'
1317--- tests/plugin/tst_application_manager.cpp 2014-10-06 09:33:22 +0000
1318+++ tests/plugin/tst_application_manager.cpp 2015-01-08 13:59:01 +0000
1319@@ -190,7 +190,8 @@
1320 {
1321 QTest::addColumn<QString>("applicationId");
1322 QTest::addColumn<QString>("contents");
1323- QTest::addColumn<QString>("profile");
1324+ QTest::addColumn<QString>("inputProfile");
1325+ QTest::addColumn<QString>("expectedProfile");
1326 QTest::addColumn<QStringList>("services");
1327
1328 QTest::newRow("no-services") <<
1329@@ -201,6 +202,7 @@
1330 " <profile>com.ubuntu.test_MyApp_0.2</profile>\n"
1331 "</application>" <<
1332 "com.ubuntu.test_MyApp_0.2" <<
1333+ "com.ubuntu.test_MyApp_0.2" <<
1334 QStringList();
1335
1336 QTest::newRow("no-valid-services") <<
1337@@ -214,6 +216,7 @@
1338 " <profile>com.ubuntu.test_MyApp2_0.2</profile>\n"
1339 "</application>" <<
1340 "com.ubuntu.test_MyApp2_0.2" <<
1341+ "com.ubuntu.test_MyApp2_0.2" <<
1342 QStringList();
1343
1344 QTest::newRow("email-services") <<
1345@@ -229,6 +232,7 @@
1346 " <profile>com.ubuntu.test_MyApp3_0.2</profile>\n"
1347 "</application>" <<
1348 "com.ubuntu.test_MyApp3_0.2" <<
1349+ "com.ubuntu.test_MyApp3_0.2" <<
1350 (QStringList() << "cool-mail" << "bad-mail");
1351
1352 QTest::newRow("cool-services") <<
1353@@ -247,7 +251,39 @@
1354 " <profile>com.ubuntu.test_MyApp4_0.2</profile>\n"
1355 "</application>" <<
1356 "com.ubuntu.test_MyApp4_0.2" <<
1357+ "com.ubuntu.test_MyApp4_0.2" <<
1358 (QStringList() << "cool-mail" << "cool-sharing");
1359+
1360+ QTest::newRow("unconfined app") <<
1361+ "com.ubuntu.test_UnconfinedApp" <<
1362+ "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
1363+ "<application id=\"com.ubuntu.test_UnconfinedApp\">\n"
1364+ " <description>My application 5</description>\n"
1365+ " <services>\n"
1366+ " <service id=\"cool-mail\">\n"
1367+ " <description>Send email</description>\n"
1368+ " </service>\n"
1369+ " </services>\n"
1370+ " <profile>com.ubuntu.test_UnconfinedApp_0.2</profile>\n"
1371+ "</application>" <<
1372+ "unconfined" <<
1373+ "com.ubuntu.test_UnconfinedApp_0.2" <<
1374+ (QStringList() << "cool-mail");
1375+
1376+ QTest::newRow("unconfined app, no profile") <<
1377+ "com.ubuntu.test_UnconfinedApp2" <<
1378+ "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
1379+ "<application id=\"com.ubuntu.test_UnconfinedApp2\">\n"
1380+ " <description>My application 6</description>\n"
1381+ " <services>\n"
1382+ " <service id=\"cool-mail\">\n"
1383+ " <description>Send email</description>\n"
1384+ " </service>\n"
1385+ " </services>\n"
1386+ "</application>" <<
1387+ "unconfined" <<
1388+ "unconfined" <<
1389+ (QStringList() << "cool-mail");
1390 }
1391
1392 void ApplicationManagerTest::testApplicationInfo()
1393@@ -256,16 +292,17 @@
1394
1395 QFETCH(QString, applicationId);
1396 QFETCH(QString, contents);
1397- QFETCH(QString, profile);
1398+ QFETCH(QString, inputProfile);
1399+ QFETCH(QString, expectedProfile);
1400 QFETCH(QStringList, services);
1401
1402 writeAccountsFile(applicationId + ".application", contents);
1403
1404 ApplicationManager manager;
1405
1406- QVariantMap info = manager.applicationInfo(applicationId, profile);
1407+ QVariantMap info = manager.applicationInfo(applicationId, inputProfile);
1408 QCOMPARE(info.value("id").toString(), applicationId);
1409- QCOMPARE(info.value("profile").toString(), profile);
1410+ QCOMPARE(info.value("profile").toString(), expectedProfile);
1411 QCOMPARE(info.value("services").toStringList().toSet(), services.toSet());
1412 }
1413

Subscribers

People subscribed via source and target branches