Merge lp:~mardy/ubuntu-system-settings-online-accounts/rtm-fixes into lp:ubuntu-system-settings-online-accounts/rtm-14.09
- rtm-fixes
- Merge into rtm-14.09
Proposed by
Alberto Mardegan
Status: | Merged | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Approved by: | David Barth | ||||||||||||||||
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 | ||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
David Barth (community) | Approve | ||
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.
Revision history for this message
David Barth (dbarth) : | # |
review:
Approve
- 204. By Alberto Mardegan
-
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
-
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 ¶ms = 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 ¶ms = 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 ¶meters, |
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 ¶meters, |
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 ¶meters, |
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 ¶meters) |
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 ¶meters, |
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 |