Merge lp:~online-accounts/ubuntu-system-settings-online-accounts/master into lp:ubuntu-system-settings-online-accounts
- master
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | David Barth |
Approved revision: | no longer in the source branch. |
Merged at revision: | 220 |
Proposed branch: | lp:~online-accounts/ubuntu-system-settings-online-accounts/master |
Merge into: | lp:ubuntu-system-settings-online-accounts |
Diff against target: |
2361 lines (+1245/-359) 37 files modified
.bzrignore (+1/-0) common-vars.pri (+1/-1) debian/changelog (+9/-0) online-accounts-service/libaccounts-service.cpp (+257/-0) online-accounts-service/libaccounts-service.h (+69/-0) online-accounts-service/main.cpp (+9/-0) online-accounts-service/online-accounts-service.pro (+7/-2) online-accounts-service/request-manager.cpp (+5/-3) online-accounts-service/request.cpp (+12/-32) online-accounts-service/request.h (+1/-0) online-accounts-service/signonui-service.cpp (+19/-2) online-accounts-service/ui-proxy.cpp (+116/-26) online-accounts-service/ui-proxy.h (+4/-0) online-accounts-service/utils.cpp (+57/-0) online-accounts-service/utils.h (+34/-0) online-accounts-ui/browser-request.cpp (+5/-4) online-accounts-ui/globals.h (+2/-0) online-accounts-ui/main.cpp (+17/-3) online-accounts-ui/online-accounts-ui.pro (+0/-2) online-accounts-ui/signonui-request.cpp (+17/-107) online-accounts-ui/signonui-request.h (+1/-0) plugins/module/OAuth.qml (+1/-0) plugins/module/ServiceItem.qml (+1/-2) plugins/plugins.pro (+2/-1) tests/online-accounts-service/mock/request-mock.cpp (+10/-0) tests/online-accounts-service/mock/request-mock.h (+2/-0) tests/online-accounts-service/online-accounts-service.pro (+1/-0) tests/online-accounts-service/tst_libaccounts_service.cpp (+522/-0) tests/online-accounts-service/tst_libaccounts_service.pro (+38/-0) tests/online-accounts-service/tst_service.pro (+2/-0) tests/online-accounts-service/tst_signonui_service.pro (+2/-0) tests/online-accounts-service/tst_ui_proxy.pro (+1/-0) tests/online-accounts-ui/mock/signonui-request-mock.cpp (+6/-0) tests/online-accounts-ui/mock/signonui-request-mock.h (+3/-0) tests/online-accounts-ui/tst_browser_request.cpp (+11/-3) tests/online-accounts-ui/tst_signonui_request.cpp (+0/-168) tests/online-accounts-ui/tst_signonui_request.pro (+0/-3) |
To merge this branch: | bzr merge lp:~online-accounts/ubuntu-system-settings-online-accounts/master |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Online Accounts | Pending | ||
Review via email: mp+246305@code.launchpad.net |
Description of the change
New upstream release
- Make sure app items are not overlaid on top of each other (LP: #1384314)
- Remove snap decision fallback
- Make account plugins confinable
Testing instructions for plugin confinement:
1) Install http://
2) copy http://
3) run
cd /var/lib/
sudo apparmor_parser -r \
click_
4) Then try creating an Evernote account; it shoudl succeed.
Some apparmor denials (probably from oxide/chromium) appear in the syslog, they'll need to be investigated.
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:224
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:225
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 220. By Alberto Mardegan
-
New upstream release
- Make sure app items are not overlaid on top of each other (LP: #1384314)
- Remove snap decision fallback
- Make account plugins confinable (LP: #1219644) Fixes: #1219644, #1376445, #1380914, #1384314
Approved by: PS Jenkins bot
Preview Diff
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2014-10-08 07:12:09 +0000 |
3 | +++ .bzrignore 2015-01-16 17:10:14 +0000 |
4 | @@ -47,6 +47,7 @@ |
5 | /tests/client/tst_client |
6 | /tests/client/tst_qml_client |
7 | /tests/online-accounts-service/tst_inactivity_timer |
8 | +/tests/online-accounts-service/tst_libaccounts_service |
9 | /tests/online-accounts-service/tst_service |
10 | /tests/online-accounts-service/tst_signonui_service |
11 | /tests/online-accounts-service/tst_ui_proxy |
12 | |
13 | === modified file 'common-vars.pri' |
14 | --- common-vars.pri 2014-03-19 12:14:14 +0000 |
15 | +++ common-vars.pri 2015-01-16 17:10:14 +0000 |
16 | @@ -13,6 +13,6 @@ |
17 | # Project version |
18 | # remember to update debian/* files if you changes this |
19 | #----------------------------------------------------------------------------- |
20 | -PROJECT_VERSION = 0.3 |
21 | +PROJECT_VERSION = 0.6 |
22 | |
23 | # End of File |
24 | |
25 | === modified file 'debian/changelog' |
26 | --- debian/changelog 2014-12-09 13:45:40 +0000 |
27 | +++ debian/changelog 2015-01-16 17:10:14 +0000 |
28 | @@ -1,3 +1,12 @@ |
29 | +ubuntu-system-settings-online-accounts (0.6) UNRELEASED; urgency=medium |
30 | + |
31 | + * New upstream release |
32 | + - Make sure app items are not overlaid on top of each other (LP: #1384314) |
33 | + - Remove snap decision fallback |
34 | + - Make account plugins confinable (LP: #1219644) |
35 | + |
36 | + -- Alberto Mardegan <alberto.mardegan@canonical.com> Tue, 13 Jan 2015 14:56:51 +0100 |
37 | + |
38 | ubuntu-system-settings-online-accounts (0.5+15.04.20141209-0ubuntu1) vivid; urgency=low |
39 | |
40 | [ Ubuntu daily release ] |
41 | |
42 | === added file 'online-accounts-service/libaccounts-service.cpp' |
43 | --- online-accounts-service/libaccounts-service.cpp 1970-01-01 00:00:00 +0000 |
44 | +++ online-accounts-service/libaccounts-service.cpp 2015-01-16 17:10:14 +0000 |
45 | @@ -0,0 +1,257 @@ |
46 | +/* |
47 | + * Copyright (C) 2014 Canonical Ltd. |
48 | + * |
49 | + * Contact: Alberto Mardegan <alberto.mardegan@canonical.com> |
50 | + * |
51 | + * This file is part of online-accounts-ui |
52 | + * |
53 | + * This program is free software: you can redistribute it and/or modify it |
54 | + * under the terms of the GNU General Public License version 3, as published |
55 | + * by the Free Software Foundation. |
56 | + * |
57 | + * This program is distributed in the hope that it will be useful, but |
58 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
59 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
60 | + * PURPOSE. See the GNU General Public License for more details. |
61 | + * |
62 | + * You should have received a copy of the GNU General Public License along |
63 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
64 | + */ |
65 | + |
66 | +#include "debug.h" |
67 | +#include "libaccounts-service.h" |
68 | +#include "utils.h" |
69 | + |
70 | +#include <Accounts/Account> |
71 | +#include <Accounts/Manager> |
72 | +#include <Accounts/Service> |
73 | +#include <QDBusArgument> |
74 | +#include <QDBusConnection> |
75 | +#include <QVariantMap> |
76 | + |
77 | +using namespace OnlineAccountsUi; |
78 | + |
79 | +static QString stripVersion(const QString &appId) |
80 | +{ |
81 | + QStringList components = appId.split('_'); |
82 | + if (components.count() != 3) return appId; |
83 | + |
84 | + /* Click packages have a profile of the form |
85 | + * $name_$application_$version |
86 | + * (see https://wiki.ubuntu.com/SecurityTeam/Specifications/ApplicationConfinement/Manifest#Click) |
87 | + * |
88 | + * We assume that this is a click package, and strip out the last part. |
89 | + */ |
90 | + components.removeLast(); |
91 | + return components.join('_'); |
92 | +} |
93 | + |
94 | +namespace OnlineAccountsUi { |
95 | + |
96 | +struct ServiceChanges { |
97 | + QString service; |
98 | + QString serviceType; |
99 | + quint32 serviceId; |
100 | + QVariantMap settings; |
101 | + QStringList removedKeys; |
102 | +}; |
103 | + |
104 | +struct AccountChanges { |
105 | + quint32 accountId; |
106 | + bool created; |
107 | + bool deleted; |
108 | + QString provider; |
109 | + QList<ServiceChanges> serviceChanges; |
110 | +}; |
111 | + |
112 | +struct PendingWrite { |
113 | + PendingWrite(const QDBusConnection &c, const QDBusMessage &m): |
114 | + message(m), connection(c) {} |
115 | + QDBusMessage message; |
116 | + QDBusConnection connection; |
117 | +}; |
118 | + |
119 | +class LibaccountsServicePrivate: public QObject |
120 | +{ |
121 | + Q_OBJECT |
122 | + Q_DECLARE_PUBLIC(LibaccountsService) |
123 | + |
124 | +public: |
125 | + LibaccountsServicePrivate(LibaccountsService *q); |
126 | + ~LibaccountsServicePrivate() {}; |
127 | + |
128 | + void writeChanges(const AccountChanges &changes); |
129 | + |
130 | +private Q_SLOTS: |
131 | + void onAccountSynced(); |
132 | + void onAccountError(Accounts::Error error); |
133 | + |
134 | +private: |
135 | + Accounts::Manager m_manager; |
136 | + QHash<Accounts::Account *,PendingWrite> m_pendingWrites; |
137 | + mutable LibaccountsService *q_ptr; |
138 | +}; |
139 | + |
140 | +} // namespace |
141 | + |
142 | +LibaccountsServicePrivate::LibaccountsServicePrivate(LibaccountsService *q): |
143 | + QObject(q), |
144 | + m_manager(new Accounts::Manager(this)), |
145 | + q_ptr(q) |
146 | +{ |
147 | +} |
148 | + |
149 | +void LibaccountsServicePrivate::writeChanges(const AccountChanges &changes) |
150 | +{ |
151 | + Q_Q(LibaccountsService); |
152 | + |
153 | + Accounts::Account *account; |
154 | + |
155 | + if (changes.created) { |
156 | + account = m_manager.createAccount(changes.provider); |
157 | + } else { |
158 | + account = m_manager.account(changes.accountId); |
159 | + if (Q_UNLIKELY(!account)) { |
160 | + qWarning() << "Couldn't load account" << changes.accountId; |
161 | + return; |
162 | + } |
163 | + } |
164 | + |
165 | + Q_ASSERT(account); |
166 | + |
167 | + if (changes.deleted) { |
168 | + account->remove(); |
169 | + } else { |
170 | + Q_FOREACH(const ServiceChanges &sc, changes.serviceChanges) { |
171 | + if (sc.service == "global") { |
172 | + account->selectService(); |
173 | + } else { |
174 | + Accounts::Service service = m_manager.service(sc.service); |
175 | + if (Q_UNLIKELY(!service.isValid())) { |
176 | + qWarning() << "Invalid service" << sc.service; |
177 | + continue; |
178 | + } |
179 | + |
180 | + account->selectService(service); |
181 | + } |
182 | + |
183 | + QMapIterator<QString, QVariant> it(sc.settings); |
184 | + while (it.hasNext()) { |
185 | + it.next(); |
186 | + account->setValue(it.key(), it.value()); |
187 | + } |
188 | + |
189 | + Q_FOREACH(const QString &key, sc.removedKeys) { |
190 | + account->remove(key); |
191 | + } |
192 | + } |
193 | + } |
194 | + |
195 | + m_pendingWrites.insert(account, |
196 | + PendingWrite(q->connection(), q->message())); |
197 | + QObject::connect(account, SIGNAL(synced()), |
198 | + this, SLOT(onAccountSynced())); |
199 | + QObject::connect(account, SIGNAL(error(Accounts::Error)), |
200 | + this, SLOT(onAccountError(Accounts::Error))); |
201 | + account->sync(); |
202 | +} |
203 | + |
204 | +void LibaccountsServicePrivate::onAccountSynced() |
205 | +{ |
206 | + Q_Q(LibaccountsService); |
207 | + |
208 | + Accounts::Account *account = qobject_cast<Accounts::Account*>(sender()); |
209 | + uint accountId = account->id(); |
210 | + account->deleteLater(); |
211 | + |
212 | + QHash<Accounts::Account*,PendingWrite>::iterator i = |
213 | + m_pendingWrites.find(account); |
214 | + if (Q_LIKELY(i != m_pendingWrites.end())) { |
215 | + PendingWrite &w = i.value(); |
216 | + w.connection.send(w.message.createReply(accountId)); |
217 | + m_pendingWrites.erase(i); |
218 | + } |
219 | +} |
220 | + |
221 | +void LibaccountsServicePrivate::onAccountError(Accounts::Error error) |
222 | +{ |
223 | + Q_Q(LibaccountsService); |
224 | + |
225 | + Accounts::Account *account = qobject_cast<Accounts::Account*>(sender()); |
226 | + account->deleteLater(); |
227 | + |
228 | + QHash<Accounts::Account*,PendingWrite>::iterator i = |
229 | + m_pendingWrites.find(account); |
230 | + if (Q_LIKELY(i != m_pendingWrites.end())) { |
231 | + PendingWrite &w = i.value(); |
232 | + QDBusMessage reply = |
233 | + w.message.createErrorReply(QDBusError::InternalError, |
234 | + error.message()); |
235 | + w.connection.send(reply); |
236 | + m_pendingWrites.erase(i); |
237 | + } |
238 | +} |
239 | + |
240 | +LibaccountsService::LibaccountsService(QObject *parent): |
241 | + QObject(parent), |
242 | + d_ptr(new LibaccountsServicePrivate(this)) |
243 | +{ |
244 | +} |
245 | + |
246 | +LibaccountsService::~LibaccountsService() |
247 | +{ |
248 | + delete d_ptr; |
249 | +} |
250 | + |
251 | +void LibaccountsService::store(const QDBusMessage &msg) |
252 | +{ |
253 | + Q_D(LibaccountsService); |
254 | + |
255 | + DEBUG() << "Got request:" << msg; |
256 | + |
257 | + /* The following line tells QtDBus not to generate a reply now */ |
258 | + setDelayedReply(true); |
259 | + |
260 | + AccountChanges changes; |
261 | + |
262 | + // signature: "ubbsa(ssua{sv}as)" |
263 | + QList<QVariant> args = msg.arguments(); |
264 | + int n = 0; |
265 | + changes.accountId = args.value(n++).toUInt(); |
266 | + changes.created = args.value(n++).toBool(); |
267 | + changes.deleted = args.value(n++).toBool(); |
268 | + changes.provider = args.value(n++).toString(); |
269 | + |
270 | + /* before continuing demarshalling the arguments, check if the provider ID |
271 | + * matches the apparmor label of the peer; if it doesn't, we shouldn't |
272 | + * honour this request. */ |
273 | + QString profile = apparmorProfileOfPeer(msg); |
274 | + if (stripVersion(profile) != changes.provider) { |
275 | + DEBUG() << "Declining AccountManager store request to" << profile << |
276 | + "for provider" << changes.provider; |
277 | + QDBusMessage reply = msg.createErrorReply(QDBusError::AccessDenied, |
278 | + "Profile/provider mismatch"); |
279 | + connection().send(reply); |
280 | + return; |
281 | + } |
282 | + |
283 | + const QDBusArgument dbusChanges = args.value(n++).value<QDBusArgument>(); |
284 | + dbusChanges.beginArray(); |
285 | + while (!dbusChanges.atEnd()) { |
286 | + ServiceChanges sc; |
287 | + dbusChanges.beginStructure(); |
288 | + dbusChanges >> sc.service; |
289 | + dbusChanges >> sc.serviceType; |
290 | + dbusChanges >> sc.serviceId; |
291 | + dbusChanges >> sc.settings; |
292 | + dbusChanges >> sc.removedKeys; |
293 | + dbusChanges.endStructure(); |
294 | + |
295 | + changes.serviceChanges.append(sc); |
296 | + } |
297 | + dbusChanges.endArray(); |
298 | + |
299 | + d->writeChanges(changes); |
300 | +} |
301 | + |
302 | +#include "libaccounts-service.moc" |
303 | |
304 | === added file 'online-accounts-service/libaccounts-service.h' |
305 | --- online-accounts-service/libaccounts-service.h 1970-01-01 00:00:00 +0000 |
306 | +++ online-accounts-service/libaccounts-service.h 2015-01-16 17:10:14 +0000 |
307 | @@ -0,0 +1,69 @@ |
308 | +/* |
309 | + * Copyright (C) 2014 Canonical Ltd. |
310 | + * |
311 | + * Contact: Alberto Mardegan <alberto.mardegan@canonical.com> |
312 | + * |
313 | + * This file is part of online-accounts-ui |
314 | + * |
315 | + * This program is free software: you can redistribute it and/or modify it |
316 | + * under the terms of the GNU General Public License version 3, as published |
317 | + * by the Free Software Foundation. |
318 | + * |
319 | + * This program is distributed in the hope that it will be useful, but |
320 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
321 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
322 | + * PURPOSE. See the GNU General Public License for more details. |
323 | + * |
324 | + * You should have received a copy of the GNU General Public License along |
325 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
326 | + */ |
327 | + |
328 | +#ifndef OAU_LIBACCOUNTS_SERVICE_H |
329 | +#define OAU_LIBACCOUNTS_SERVICE_H |
330 | + |
331 | +#include <QDBusContext> |
332 | +#include <QDBusMessage> |
333 | +#include <QObject> |
334 | + |
335 | +namespace OnlineAccountsUi { |
336 | + |
337 | +#define LIBACCOUNTS_OBJECT_PATH \ |
338 | + QStringLiteral("/com/google/code/AccountsSSO/Accounts/Manager") |
339 | +#define LIBACCOUNTS_BUS_NAME \ |
340 | + QStringLiteral("com.google.code.AccountsSSO.Accounts.Manager") |
341 | + |
342 | +class LibaccountsServicePrivate; |
343 | + |
344 | +class LibaccountsService: public QObject, protected QDBusContext |
345 | +{ |
346 | + Q_OBJECT |
347 | + Q_CLASSINFO("D-Bus Interface", |
348 | + "com.google.code.AccountsSSO.Accounts.Manager") |
349 | + Q_CLASSINFO("D-Bus Introspection", "" |
350 | +" <interface name=\"com.google.code.AccountsSSO.Accounts.Manager\">\n" |
351 | +" <method name=\"store\">\n" |
352 | +" <arg direction=\"in\" type=\"u\" name=\"account_id\"/>\n" |
353 | +" <arg direction=\"in\" type=\"b\"/>\n" |
354 | +" <arg direction=\"in\" type=\"b\"/>\n" |
355 | +" <arg direction=\"in\" type=\"s\"/>\n" |
356 | +" <arg direction=\"in\" type=\"a(ssua{sv}as)\"/>\n" |
357 | +" <arg direction=\"out\" type=\"u\" name=\"account_id\"/>\n" |
358 | +" </method>\n" |
359 | +" </interface>\n" |
360 | + "") |
361 | + |
362 | +public: |
363 | + explicit LibaccountsService(QObject *parent = 0); |
364 | + ~LibaccountsService(); |
365 | + |
366 | +public Q_SLOTS: |
367 | + void store(const QDBusMessage &msg); |
368 | + |
369 | +private: |
370 | + LibaccountsServicePrivate *d_ptr; |
371 | + Q_DECLARE_PRIVATE(LibaccountsService) |
372 | +}; |
373 | + |
374 | +} // namespace |
375 | + |
376 | +#endif // OAU_LIBACCOUNTS_SERVICE_H |
377 | |
378 | === modified file 'online-accounts-service/main.cpp' |
379 | --- online-accounts-service/main.cpp 2014-08-19 12:11:24 +0000 |
380 | +++ online-accounts-service/main.cpp 2015-01-16 17:10:14 +0000 |
381 | @@ -22,6 +22,7 @@ |
382 | #include "globals.h" |
383 | #include "inactivity-timer.h" |
384 | #include "indicator-service.h" |
385 | +#include "libaccounts-service.h" |
386 | #include "request-manager.h" |
387 | #include "service.h" |
388 | #include "signonui-service.h" |
389 | @@ -79,6 +80,10 @@ |
390 | connection.registerObject(WEBCREDENTIALS_OBJECT_PATH, |
391 | indicatorService->serviceObject()); |
392 | |
393 | + LibaccountsService *libaccountsService = new LibaccountsService(); |
394 | + connection.registerService(LIBACCOUNTS_BUS_NAME); |
395 | + connection.registerObject(LIBACCOUNTS_OBJECT_PATH, libaccountsService, |
396 | + QDBusConnection::ExportAllContents); |
397 | |
398 | InactivityTimer *inactivityTimer = 0; |
399 | if (daemonTimeout > 0) { |
400 | @@ -91,6 +96,10 @@ |
401 | |
402 | int ret = app.exec(); |
403 | |
404 | + connection.unregisterService(LIBACCOUNTS_BUS_NAME); |
405 | + connection.unregisterObject(LIBACCOUNTS_OBJECT_PATH); |
406 | + delete libaccountsService; |
407 | + |
408 | connection.unregisterService(WEBCREDENTIALS_BUS_NAME); |
409 | connection.unregisterObject(WEBCREDENTIALS_OBJECT_PATH); |
410 | delete indicatorService; |
411 | |
412 | === modified file 'online-accounts-service/online-accounts-service.pro' |
413 | --- online-accounts-service/online-accounts-service.pro 2014-08-26 08:39:20 +0000 |
414 | +++ online-accounts-service/online-accounts-service.pro 2015-01-16 17:10:14 +0000 |
415 | @@ -14,6 +14,7 @@ |
416 | network |
417 | |
418 | PKGCONFIG += \ |
419 | + accounts-qt5 \ |
420 | libnotify \ |
421 | libsignon-qt5 \ |
422 | signon-plugins-common |
423 | @@ -46,13 +47,15 @@ |
424 | $${COMMON_SRC}/notification.cpp \ |
425 | inactivity-timer.cpp \ |
426 | indicator-service.cpp \ |
427 | + libaccounts-service.cpp \ |
428 | main.cpp \ |
429 | reauthenticator.cpp \ |
430 | request.cpp \ |
431 | request-manager.cpp \ |
432 | service.cpp \ |
433 | signonui-service.cpp \ |
434 | - ui-proxy.cpp |
435 | + ui-proxy.cpp \ |
436 | + utils.cpp |
437 | |
438 | HEADERS += \ |
439 | $${COMMON_SRC}/debug.h \ |
440 | @@ -61,13 +64,15 @@ |
441 | $${COMMON_SRC}/notification.h \ |
442 | inactivity-timer.h \ |
443 | indicator-service.h \ |
444 | + libaccounts-service.h \ |
445 | mir-helper.h \ |
446 | reauthenticator.h \ |
447 | request.h \ |
448 | request-manager.h \ |
449 | service.h \ |
450 | signonui-service.h \ |
451 | - ui-proxy.h |
452 | + ui-proxy.h \ |
453 | + utils.h |
454 | |
455 | QMAKE_SUBSTITUTES += \ |
456 | com.ubuntu.OnlineAccountsUi.service.in |
457 | |
458 | === modified file 'online-accounts-service/request-manager.cpp' |
459 | --- online-accounts-service/request-manager.cpp 2014-10-13 10:48:54 +0000 |
460 | +++ online-accounts-service/request-manager.cpp 2015-01-16 17:10:14 +0000 |
461 | @@ -117,14 +117,16 @@ |
462 | return; // Nothing to do |
463 | } |
464 | |
465 | + QObject::connect(request, SIGNAL(completed()), |
466 | + this, SLOT(onRequestCompleted())); |
467 | + |
468 | UiProxy *proxy = new UiProxy(request->clientPid(), this); |
469 | if (Q_UNLIKELY(!proxy->init())) { |
470 | qWarning() << "UiProxy initialization failed!"; |
471 | - runQueue(queue); |
472 | + request->fail(OAU_ERROR_PROMPT_SESSION, |
473 | + "Could not create a prompt session"); |
474 | return; |
475 | } |
476 | - QObject::connect(request, SIGNAL(completed()), |
477 | - this, SLOT(onRequestCompleted())); |
478 | QObject::connect(proxy, SIGNAL(finished()), |
479 | this, SLOT(onProxyFinished())); |
480 | m_proxies.append(proxy); |
481 | |
482 | === modified file 'online-accounts-service/request.cpp' |
483 | --- online-accounts-service/request.cpp 2014-11-21 13:50:15 +0000 |
484 | +++ online-accounts-service/request.cpp 2015-01-16 17:10:14 +0000 |
485 | @@ -21,6 +21,7 @@ |
486 | #include "debug.h" |
487 | #include "globals.h" |
488 | #include "request.h" |
489 | +#include "utils.h" |
490 | |
491 | #include <SignOn/uisessiondata_priv.h> |
492 | |
493 | @@ -58,9 +59,6 @@ |
494 | } |
495 | |
496 | private: |
497 | - QString findClientApparmorProfile(); |
498 | - |
499 | -private: |
500 | mutable Request *q_ptr; |
501 | QDBusConnection m_connection; |
502 | QDBusMessage m_message; |
503 | @@ -84,41 +82,13 @@ |
504 | m_inProgress(false), |
505 | m_delay(0) |
506 | { |
507 | - m_clientApparmorProfile = findClientApparmorProfile(); |
508 | + m_clientApparmorProfile = apparmorProfileOfPeer(message); |
509 | } |
510 | |
511 | RequestPrivate::~RequestPrivate() |
512 | { |
513 | } |
514 | |
515 | -QString RequestPrivate::findClientApparmorProfile() |
516 | -{ |
517 | - QString uniqueConnectionId = m_message.service(); |
518 | - /* This is mainly for unit tests: real messages on the session bus always |
519 | - * have a service name. */ |
520 | - if (uniqueConnectionId.isEmpty()) return QString(); |
521 | - |
522 | - QString appId; |
523 | - |
524 | - QDBusMessage msg = |
525 | - QDBusMessage::createMethodCall("org.freedesktop.DBus", |
526 | - "/org/freedesktop/DBus", |
527 | - "org.freedesktop.DBus", |
528 | - "GetConnectionAppArmorSecurityContext"); |
529 | - QVariantList args; |
530 | - args << uniqueConnectionId; |
531 | - msg.setArguments(args); |
532 | - QDBusMessage reply = QDBusConnection::sessionBus().call(msg, QDBus::Block); |
533 | - if (reply.type() == QDBusMessage::ReplyMessage) { |
534 | - appId = reply.arguments().value(0, QString()).toString(); |
535 | - DEBUG() << "App ID:" << appId; |
536 | - } else { |
537 | - qWarning() << "Error getting app ID:" << reply.errorName() << |
538 | - reply.errorMessage(); |
539 | - } |
540 | - return appId; |
541 | -} |
542 | - |
543 | Request::Request(const QDBusConnection &connection, |
544 | const QDBusMessage &message, |
545 | const QVariantMap ¶meters, |
546 | @@ -192,6 +162,16 @@ |
547 | return d->m_message.interface(); |
548 | } |
549 | |
550 | +QString Request::providerId() const |
551 | +{ |
552 | + Q_D(const Request); |
553 | + if (interface() == OAU_INTERFACE) { |
554 | + return d->m_parameters.value(OAU_KEY_PROVIDER, 0).toString(); |
555 | + } else { |
556 | + return QString(); |
557 | + } |
558 | +} |
559 | + |
560 | void Request::setDelay(int delay) |
561 | { |
562 | Q_D(Request); |
563 | |
564 | === modified file 'online-accounts-service/request.h' |
565 | --- online-accounts-service/request.h 2014-11-21 13:50:15 +0000 |
566 | +++ online-accounts-service/request.h 2015-01-16 17:10:14 +0000 |
567 | @@ -49,6 +49,7 @@ |
568 | const QVariantMap ¶meters() const; |
569 | QString clientApparmorProfile() const; |
570 | QString interface() const; |
571 | + QString providerId() const; |
572 | |
573 | void setDelay(int delay); |
574 | int delay() const; |
575 | |
576 | === modified file 'online-accounts-service/signonui-service.cpp' |
577 | --- online-accounts-service/signonui-service.cpp 2014-08-22 11:31:24 +0000 |
578 | +++ online-accounts-service/signonui-service.cpp 2015-01-16 17:10:14 +0000 |
579 | @@ -156,15 +156,32 @@ |
580 | |
581 | QString ServicePrivate::rootDirForIdentity(quint32 id) |
582 | { |
583 | + /* the BrowserRequest class instructs the webview to store its cookies and |
584 | + * local data into |
585 | + * ~/.cache/online-accounts-ui/id-<signon-id>-<provider-id>/; while we |
586 | + * don't normally expect to find more than one entry for a given signon-id, |
587 | + * it's a possibility we cannot completely discard, since in older versions |
588 | + * we were not appending the "-<provider-id>" suffix. Besides, unless we |
589 | + * look up into the accounts DB, we don't know the value for the provider |
590 | + * ID. |
591 | + * Because of both of these reasons, we list all the directories whose name |
592 | + * starts with "id-<signon-id>" and pick the most recent one. |
593 | + */ |
594 | QString cachePath = |
595 | QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation); |
596 | - return cachePath + QString("/online-accounts-ui/id-%1").arg(id); |
597 | + QDir cacheDir(cachePath + QStringLiteral("/online-accounts-ui")); |
598 | + QString nameFilter = QString("id-%1*").arg(id); |
599 | + QStringList rootDirs = cacheDir.entryList(QStringList() << nameFilter, |
600 | + QDir::Dirs, QDir::Time); |
601 | + return rootDirs.count() > 0 ? cacheDir.filePath(rootDirs.at(0)) : QString(); |
602 | } |
603 | |
604 | void ServicePrivate::removeIdentityData(quint32 id) |
605 | { |
606 | /* Remove any data associated with the given identity. */ |
607 | - QDir rootDir(ServicePrivate::rootDirForIdentity(id)); |
608 | + QString rootDirName = rootDirForIdentity(id); |
609 | + if (rootDirName.isEmpty()) return; |
610 | + QDir rootDir(rootDirName); |
611 | rootDir.removeRecursively(); |
612 | } |
613 | |
614 | |
615 | === modified file 'online-accounts-service/ui-proxy.cpp' |
616 | --- online-accounts-service/ui-proxy.cpp 2014-11-21 13:50:15 +0000 |
617 | +++ online-accounts-service/ui-proxy.cpp 2015-01-16 17:10:14 +0000 |
618 | @@ -24,7 +24,11 @@ |
619 | #include "request.h" |
620 | #include "ui-proxy.h" |
621 | |
622 | +#include <Accounts/Manager> |
623 | +#include <Accounts/Provider> |
624 | #include <QDir> |
625 | +#include <QDomDocument> |
626 | +#include <QDomElement> |
627 | #include <QFileInfo> |
628 | #include <QLocalServer> |
629 | #include <QLocalSocket> |
630 | @@ -49,11 +53,14 @@ |
631 | inline UiProxyPrivate(pid_t clientPid, UiProxy *pluginProxy); |
632 | inline ~UiProxyPrivate(); |
633 | |
634 | + void setStatus(UiProxy::Status status); |
635 | bool setupSocket(); |
636 | bool init(); |
637 | void sendOperation(const QVariantMap &data); |
638 | void sendRequest(int requestId, Request *request); |
639 | - void setupPromptSession(); |
640 | + bool setupPromptSession(); |
641 | + QString findAppArmorProfile(); |
642 | + void startProcess(); |
643 | |
644 | private Q_SLOTS: |
645 | void onNewConnection(); |
646 | @@ -63,6 +70,7 @@ |
647 | |
648 | private: |
649 | QProcess m_process; |
650 | + UiProxy::Status m_status; |
651 | QLocalServer m_server; |
652 | QLocalSocket *m_socket; |
653 | OnlineAccountsUi::Ipc m_ipc; |
654 | @@ -71,7 +79,9 @@ |
655 | QMap<int,Request*> m_requests; |
656 | QStringList m_handlers; |
657 | pid_t m_clientPid; |
658 | + QString m_providerId; |
659 | PromptSessionP m_promptSession; |
660 | + QStringList m_arguments; |
661 | mutable UiProxy *q_ptr; |
662 | }; |
663 | |
664 | @@ -79,6 +89,7 @@ |
665 | |
666 | UiProxyPrivate::UiProxyPrivate(pid_t clientPid, UiProxy *uiProxy): |
667 | QObject(uiProxy), |
668 | + m_status(UiProxy::Null), |
669 | m_socket(0), |
670 | m_nextRequestId(0), |
671 | m_clientPid(clientPid), |
672 | @@ -109,6 +120,14 @@ |
673 | m_server.close(); |
674 | } |
675 | |
676 | +void UiProxyPrivate::setStatus(UiProxy::Status status) |
677 | +{ |
678 | + Q_Q(UiProxy); |
679 | + if (m_status == status) return; |
680 | + m_status = status; |
681 | + Q_EMIT q->statusChanged(); |
682 | +} |
683 | + |
684 | void UiProxyPrivate::sendOperation(const QVariantMap &data) |
685 | { |
686 | QByteArray ba; |
687 | @@ -136,6 +155,8 @@ |
688 | m_ipc.setChannels(socket, socket); |
689 | m_server.close(); // stop listening |
690 | |
691 | + setStatus(UiProxy::Ready); |
692 | + |
693 | /* Execute any pending requests */ |
694 | QMapIterator<int, Request*> it(m_requests); |
695 | while (it.hasNext()) { |
696 | @@ -178,7 +199,7 @@ |
697 | QDir socketDir(runtimeDir + "/online-accounts-ui"); |
698 | if (!socketDir.exists()) socketDir.mkpath("."); |
699 | |
700 | - QString uniqueName = QString("ui-%1").arg(socketCounter++); |
701 | + QString uniqueName = QString("ui-%1-%2").arg(socketCounter++).arg(m_providerId); |
702 | |
703 | /* If the file exists, it's a stale file: online-accounts-ui is a single |
704 | * instance process, and the only one creating files in this directory. */ |
705 | @@ -190,57 +211,114 @@ |
706 | return m_server.listen(socketDir.filePath(uniqueName)); |
707 | } |
708 | |
709 | -void UiProxyPrivate::setupPromptSession() |
710 | +bool UiProxyPrivate::setupPromptSession() |
711 | { |
712 | Q_Q(UiProxy); |
713 | |
714 | - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); |
715 | - if (!env.value("QT_QPA_PLATFORM").startsWith("ubuntu")) return; |
716 | - |
717 | PromptSessionP session = |
718 | MirHelper::instance()->createPromptSession(m_clientPid); |
719 | - if (!session) return; |
720 | + if (!session) return false; |
721 | |
722 | QString mirSocket = session->requestSocket(); |
723 | if (mirSocket.isEmpty()) { |
724 | - return; |
725 | + return false; |
726 | } |
727 | |
728 | m_promptSession = session; |
729 | QObject::connect(m_promptSession.data(), SIGNAL(finished()), |
730 | q, SIGNAL(finished())); |
731 | |
732 | + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); |
733 | env.insert("MIR_SOCKET", mirSocket); |
734 | m_process.setProcessEnvironment(env); |
735 | + return true; |
736 | } |
737 | |
738 | bool UiProxyPrivate::init() |
739 | { |
740 | - if (Q_UNLIKELY(!setupSocket())) return false; |
741 | + m_arguments.clear(); |
742 | + if (!m_promptSession) { |
743 | + /* the first argument is required to be the desktop file */ |
744 | + m_arguments.append("--desktop_file_hint=/usr/share/applications/online-accounts-ui.desktop"); |
745 | + } |
746 | + |
747 | + if (m_clientPid) { |
748 | + setupPromptSession(); |
749 | + } |
750 | + |
751 | + return true; |
752 | +} |
753 | + |
754 | +QString UiProxyPrivate::findAppArmorProfile() |
755 | +{ |
756 | + if (Q_UNLIKELY(m_providerId.isEmpty())) return QString(); |
757 | + |
758 | + /* Load the provider XML file */ |
759 | + Accounts::Manager manager; |
760 | + Accounts::Provider provider = manager.provider(m_providerId); |
761 | + if (Q_UNLIKELY(!provider.isValid())) { |
762 | + qWarning() << "Provider not found:" << m_providerId; |
763 | + return QString(); |
764 | + } |
765 | + |
766 | + const QDomDocument doc = provider.domDocument(); |
767 | + QDomElement root = doc.documentElement(); |
768 | + return root.firstChildElement("profile").text(); |
769 | +} |
770 | + |
771 | +void UiProxyPrivate::startProcess() |
772 | +{ |
773 | + if (Q_UNLIKELY(!setupSocket())) { |
774 | + qWarning() << "Couldn't setup IPC socket"; |
775 | + setStatus(UiProxy::Error); |
776 | + return; |
777 | + } |
778 | + m_arguments.append("--socket"); |
779 | + m_arguments.append(m_server.fullServerName()); |
780 | + |
781 | + QString profile = findAppArmorProfile(); |
782 | + if (profile.isEmpty()) { |
783 | + profile = "unconfined"; |
784 | + } else { |
785 | + /* Set TMPDIR to a location which the confined process can actually |
786 | + * use */ |
787 | + QString tmpdir = |
788 | + QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation) + |
789 | + "/" + profile.split('_')[0]; |
790 | + QProcessEnvironment env = m_process.processEnvironment(); |
791 | + env.insert("TMPDIR", tmpdir); |
792 | + m_process.setProcessEnvironment(env); |
793 | + } |
794 | + |
795 | + m_arguments.append("--profile"); |
796 | + m_arguments.append(profile); |
797 | |
798 | QString processName; |
799 | - QStringList arguments; |
800 | QString wrapper = QString::fromUtf8(qgetenv("OAU_WRAPPER")); |
801 | QString accountsUi = QStringLiteral(INSTALL_BIN_DIR "/online-accounts-ui"); |
802 | if (wrapper.isEmpty()) { |
803 | processName = accountsUi; |
804 | } else { |
805 | processName = wrapper; |
806 | - arguments.append(accountsUi); |
807 | - } |
808 | - if (!m_promptSession) { |
809 | - /* the first argument is required to be the desktop file */ |
810 | - arguments.append("--desktop_file_hint=/usr/share/applications/online-accounts-ui.desktop"); |
811 | - } |
812 | - arguments.append("--socket"); |
813 | - arguments.append(m_server.fullServerName()); |
814 | - |
815 | - if (m_clientPid) { |
816 | - setupPromptSession(); |
817 | - } |
818 | - |
819 | - m_process.start(processName, arguments); |
820 | - return m_process.waitForStarted(); |
821 | + m_arguments.prepend(accountsUi); |
822 | + } |
823 | + |
824 | + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); |
825 | + if (env.value("QT_QPA_PLATFORM").startsWith("ubuntu")) { |
826 | + if (!setupPromptSession()) { |
827 | + qWarning() << "Couldn't setup prompt session"; |
828 | + setStatus(UiProxy::Error); |
829 | + return; |
830 | + } |
831 | + } |
832 | + |
833 | + setStatus(UiProxy::Loading); |
834 | + m_process.start(processName, m_arguments); |
835 | + if (Q_UNLIKELY(!m_process.waitForStarted())) { |
836 | + qWarning() << "Couldn't start account plugin process"; |
837 | + setStatus(UiProxy::Error); |
838 | + return; |
839 | + } |
840 | } |
841 | |
842 | void UiProxyPrivate::sendRequest(int requestId, Request *request) |
843 | @@ -285,6 +363,13 @@ |
844 | |
845 | UiProxy::~UiProxy() |
846 | { |
847 | + DEBUG(); |
848 | +} |
849 | + |
850 | +UiProxy::Status UiProxy::status() const |
851 | +{ |
852 | + Q_D(const UiProxy); |
853 | + return d->m_status; |
854 | } |
855 | |
856 | bool UiProxy::init() |
857 | @@ -297,14 +382,19 @@ |
858 | { |
859 | Q_D(UiProxy); |
860 | |
861 | + if (d->m_providerId.isEmpty()) { |
862 | + d->m_providerId = request->providerId(); |
863 | + } |
864 | int requestId = d->m_nextRequestId++; |
865 | d->m_requests.insert(requestId, request); |
866 | QObject::connect(request, SIGNAL(completed()), |
867 | d, SLOT(onRequestCompleted())); |
868 | request->setInProgress(true); |
869 | |
870 | - if (d->m_socket && d->m_socket->isValid()) { |
871 | + if (d->m_status == UiProxy::Ready) { |
872 | d->sendRequest(requestId, request); |
873 | + } else if (d->m_status == UiProxy::Null) { |
874 | + d->startProcess(); |
875 | } |
876 | } |
877 | |
878 | |
879 | === modified file 'online-accounts-service/ui-proxy.h' |
880 | --- online-accounts-service/ui-proxy.h 2014-08-12 12:33:10 +0000 |
881 | +++ online-accounts-service/ui-proxy.h 2015-01-16 17:10:14 +0000 |
882 | @@ -37,11 +37,15 @@ |
883 | explicit UiProxy(pid_t clientPid, QObject *parent = 0); |
884 | ~UiProxy(); |
885 | |
886 | + enum Status { Null, Ready, Loading, Error }; |
887 | + Status status() const; |
888 | + |
889 | bool init(); |
890 | void handleRequest(Request *request); |
891 | bool hasHandlerFor(const QVariantMap ¶meters); |
892 | |
893 | Q_SIGNALS: |
894 | + void statusChanged(); |
895 | void finished(); |
896 | |
897 | private: |
898 | |
899 | === added file 'online-accounts-service/utils.cpp' |
900 | --- online-accounts-service/utils.cpp 1970-01-01 00:00:00 +0000 |
901 | +++ online-accounts-service/utils.cpp 2015-01-16 17:10:14 +0000 |
902 | @@ -0,0 +1,57 @@ |
903 | +/* |
904 | + * Copyright (C) 2014 Canonical Ltd. |
905 | + * |
906 | + * Contact: Alberto Mardegan <alberto.mardegan@canonical.com> |
907 | + * |
908 | + * This file is part of online-accounts-ui |
909 | + * |
910 | + * This program is free software: you can redistribute it and/or modify it |
911 | + * under the terms of the GNU General Public License version 3, as published |
912 | + * by the Free Software Foundation. |
913 | + * |
914 | + * This program is distributed in the hope that it will be useful, but |
915 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
916 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
917 | + * PURPOSE. See the GNU General Public License for more details. |
918 | + * |
919 | + * You should have received a copy of the GNU General Public License along |
920 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
921 | + */ |
922 | + |
923 | +#include "debug.h" |
924 | +#include "utils.h" |
925 | + |
926 | +#include <QDBusConnection> |
927 | +#include <QDBusMessage> |
928 | + |
929 | +namespace OnlineAccountsUi { |
930 | + |
931 | +QString apparmorProfileOfPeer(const QDBusMessage &message) |
932 | +{ |
933 | + QString uniqueConnectionId = message.service(); |
934 | + /* This is mainly for unit tests: real messages on the session bus always |
935 | + * have a service name. */ |
936 | + if (uniqueConnectionId.isEmpty()) return QString(); |
937 | + |
938 | + QString appId; |
939 | + |
940 | + QDBusMessage msg = |
941 | + QDBusMessage::createMethodCall("org.freedesktop.DBus", |
942 | + "/org/freedesktop/DBus", |
943 | + "org.freedesktop.DBus", |
944 | + "GetConnectionAppArmorSecurityContext"); |
945 | + QVariantList args; |
946 | + args << uniqueConnectionId; |
947 | + msg.setArguments(args); |
948 | + QDBusMessage reply = QDBusConnection::sessionBus().call(msg, QDBus::Block); |
949 | + if (reply.type() == QDBusMessage::ReplyMessage) { |
950 | + appId = reply.arguments().value(0, QString()).toString(); |
951 | + DEBUG() << "App ID:" << appId; |
952 | + } else { |
953 | + qWarning() << "Error getting app ID:" << reply.errorName() << |
954 | + reply.errorMessage(); |
955 | + } |
956 | + return appId; |
957 | +} |
958 | + |
959 | +} // namespace |
960 | |
961 | === added file 'online-accounts-service/utils.h' |
962 | --- online-accounts-service/utils.h 1970-01-01 00:00:00 +0000 |
963 | +++ online-accounts-service/utils.h 2015-01-16 17:10:14 +0000 |
964 | @@ -0,0 +1,34 @@ |
965 | +/* |
966 | + * Copyright (C) 2014 Canonical Ltd. |
967 | + * |
968 | + * Contact: Alberto Mardegan <alberto.mardegan@canonical.com> |
969 | + * |
970 | + * This file is part of online-accounts-ui |
971 | + * |
972 | + * This program is free software: you can redistribute it and/or modify it |
973 | + * under the terms of the GNU General Public License version 3, as published |
974 | + * by the Free Software Foundation. |
975 | + * |
976 | + * This program is distributed in the hope that it will be useful, but |
977 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
978 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
979 | + * PURPOSE. See the GNU General Public License for more details. |
980 | + * |
981 | + * You should have received a copy of the GNU General Public License along |
982 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
983 | + */ |
984 | + |
985 | +#ifndef OAU_UTILS_H |
986 | +#define OAU_UTILS_H |
987 | + |
988 | +#include <QString> |
989 | + |
990 | +class QDBusMessage; |
991 | + |
992 | +namespace OnlineAccountsUi { |
993 | + |
994 | +QString apparmorProfileOfPeer(const QDBusMessage &message); |
995 | + |
996 | +} // namespace |
997 | + |
998 | +#endif // OAU_UTILS_H |
999 | |
1000 | === modified file 'online-accounts-ui/browser-request.cpp' |
1001 | --- online-accounts-ui/browser-request.cpp 2014-10-09 12:24:45 +0000 |
1002 | +++ online-accounts-ui/browser-request.cpp 2015-01-16 17:10:14 +0000 |
1003 | @@ -70,7 +70,7 @@ |
1004 | QUrl responseUrl() const { return m_responseUrl; } |
1005 | QUrl rootDir() const { return QUrl::fromLocalFile(m_rootDir); } |
1006 | |
1007 | - static QString rootDirForIdentity(quint32 id); |
1008 | + QString rootDirForIdentity() const; |
1009 | |
1010 | public Q_SLOTS: |
1011 | void setCookies(const QVariant &cookies); |
1012 | @@ -120,11 +120,12 @@ |
1013 | delete m_dialog; |
1014 | } |
1015 | |
1016 | -QString BrowserRequestPrivate::rootDirForIdentity(quint32 id) |
1017 | +QString BrowserRequestPrivate::rootDirForIdentity() const |
1018 | { |
1019 | + Q_Q(const BrowserRequest); |
1020 | QString cachePath = |
1021 | QStandardPaths::writableLocation(QStandardPaths::CacheLocation); |
1022 | - return cachePath + QString("/id-%1").arg(id); |
1023 | + return cachePath + QString("/id-%1-%2").arg(q->identity()).arg(q->providerId()); |
1024 | } |
1025 | |
1026 | void BrowserRequestPrivate::start() |
1027 | @@ -134,7 +135,7 @@ |
1028 | const QVariantMap ¶ms = q->parameters(); |
1029 | DEBUG() << params; |
1030 | |
1031 | - QDir rootDir(rootDirForIdentity(q->identity())); |
1032 | + QDir rootDir(rootDirForIdentity()); |
1033 | if (!rootDir.exists()) { |
1034 | rootDir.mkpath("."); |
1035 | } |
1036 | |
1037 | === modified file 'online-accounts-ui/globals.h' |
1038 | --- online-accounts-ui/globals.h 2014-09-15 12:16:50 +0000 |
1039 | +++ online-accounts-ui/globals.h 2015-01-16 17:10:14 +0000 |
1040 | @@ -40,6 +40,8 @@ |
1041 | QStringLiteral(OAU_ERROR_PREFIX "InvalidParameters") |
1042 | #define OAU_ERROR_INVALID_APPLICATION \ |
1043 | QStringLiteral(OAU_ERROR_PREFIX "InvalidApplication") |
1044 | +#define OAU_ERROR_PROMPT_SESSION \ |
1045 | + QStringLiteral(OAU_ERROR_PREFIX "NoPromptSession") |
1046 | |
1047 | /* SignOnUi service */ |
1048 | #define SIGNONUI_SERVICE_NAME QStringLiteral("com.nokia.singlesignonui") |
1049 | |
1050 | === modified file 'online-accounts-ui/main.cpp' |
1051 | --- online-accounts-ui/main.cpp 2014-12-09 10:10:25 +0000 |
1052 | +++ online-accounts-ui/main.cpp 2015-01-16 17:10:14 +0000 |
1053 | @@ -32,6 +32,7 @@ |
1054 | #else |
1055 | #include <QtGui/private/qopenglcontext_p.h> |
1056 | #endif |
1057 | +#include <sys/apparmor.h> |
1058 | |
1059 | using namespace OnlineAccountsUi; |
1060 | |
1061 | @@ -81,14 +82,27 @@ |
1062 | QOpenGLContextPrivate::setGlobalShareContext(glcontext); |
1063 | #endif |
1064 | |
1065 | + QString socket; |
1066 | + QString profile; |
1067 | QStringList arguments = app.arguments(); |
1068 | - int i = arguments.indexOf("--socket"); |
1069 | - if (i < 0 || i + 1 >= arguments.count()) { |
1070 | + for (int i = 0; i < arguments.count(); i++) { |
1071 | + const QString &arg = arguments[i]; |
1072 | + if (arg == "--socket") { |
1073 | + socket = arguments.value(++i); |
1074 | + } else if (arg == "--profile") { |
1075 | + profile = arguments.value(++i); |
1076 | + } |
1077 | + } |
1078 | + if (Q_UNLIKELY(socket.isEmpty())) { |
1079 | qWarning() << "Missing --socket argument"; |
1080 | return EXIT_FAILURE; |
1081 | } |
1082 | |
1083 | - UiServer server(arguments[i + 1]); |
1084 | + if (!profile.isEmpty()) { |
1085 | + aa_change_profile(profile.toUtf8().constData()); |
1086 | + } |
1087 | + |
1088 | + UiServer server(socket); |
1089 | QObject::connect(&server, SIGNAL(finished()), |
1090 | &app, SLOT(quit())); |
1091 | if (Q_UNLIKELY(!server.init())) { |
1092 | |
1093 | === modified file 'online-accounts-ui/online-accounts-ui.pro' |
1094 | --- online-accounts-ui/online-accounts-ui.pro 2014-10-31 12:05:37 +0000 |
1095 | +++ online-accounts-ui/online-accounts-ui.pro 2015-01-16 17:10:14 +0000 |
1096 | @@ -52,7 +52,6 @@ |
1097 | i18n.cpp \ |
1098 | ipc.cpp \ |
1099 | main.cpp \ |
1100 | - notification.cpp \ |
1101 | panel-request.cpp \ |
1102 | provider-request.cpp \ |
1103 | request.cpp \ |
1104 | @@ -67,7 +66,6 @@ |
1105 | dialog-request.h \ |
1106 | i18n.h \ |
1107 | ipc.h \ |
1108 | - notification.h \ |
1109 | panel-request.h \ |
1110 | provider-request.h \ |
1111 | request.h \ |
1112 | |
1113 | === modified file 'online-accounts-ui/signonui-request.cpp' |
1114 | --- online-accounts-ui/signonui-request.cpp 2014-10-14 09:05:52 +0000 |
1115 | +++ online-accounts-ui/signonui-request.cpp 2015-01-16 17:10:14 +0000 |
1116 | @@ -24,13 +24,9 @@ |
1117 | #include "debug.h" |
1118 | #include "dialog-request.h" |
1119 | #include "globals.h" |
1120 | -#include "notification.h" |
1121 | |
1122 | #include <Accounts/Account> |
1123 | -#include <Accounts/Application> |
1124 | -#include <Accounts/Provider> |
1125 | #include <OnlineAccountsPlugin/account-manager.h> |
1126 | -#include <OnlineAccountsPlugin/application-manager.h> |
1127 | #include <OnlineAccountsPlugin/request-handler.h> |
1128 | #include <QDBusArgument> |
1129 | #include <QPointer> |
1130 | @@ -52,19 +48,13 @@ |
1131 | ~RequestPrivate(); |
1132 | |
1133 | private: |
1134 | - void setWindow(QWindow *window); |
1135 | Accounts::Account *findAccount(); |
1136 | |
1137 | -private Q_SLOTS: |
1138 | - void onActionInvoked(const QString &action); |
1139 | - void onNotificationClosed(); |
1140 | - |
1141 | private: |
1142 | mutable Request *q_ptr; |
1143 | QVariantMap m_clientData; |
1144 | QPointer<RequestHandler> m_handler; |
1145 | - OnlineAccountsUi::Notification *m_notification; |
1146 | - QWindow *m_window; |
1147 | + Accounts::Account *m_account; |
1148 | }; |
1149 | |
1150 | } // namespace |
1151 | @@ -72,9 +62,7 @@ |
1152 | RequestPrivate::RequestPrivate(Request *request): |
1153 | QObject(request), |
1154 | q_ptr(request), |
1155 | - m_handler(0), |
1156 | - m_notification(0), |
1157 | - m_window(0) |
1158 | + m_handler(0) |
1159 | { |
1160 | const QVariantMap ¶meters = request->parameters(); |
1161 | if (parameters.contains(SSOUI_KEY_CLIENT_DATA)) { |
1162 | @@ -83,55 +71,12 @@ |
1163 | variant.toMap() : |
1164 | qdbus_cast<QVariantMap>(variant.value<QDBusArgument>()); |
1165 | } |
1166 | + |
1167 | + m_account = findAccount(); |
1168 | } |
1169 | |
1170 | RequestPrivate::~RequestPrivate() |
1171 | { |
1172 | - delete m_notification; |
1173 | - m_notification = 0; |
1174 | -} |
1175 | - |
1176 | -void RequestPrivate::setWindow(QWindow *window) |
1177 | -{ |
1178 | - Q_Q(Request); |
1179 | - |
1180 | - /* Don't show the window yet: the user must be presented with a |
1181 | - * snap-decision, and we'll show the window only if he decides to |
1182 | - * authenticate. */ |
1183 | - Accounts::Account *account = findAccount(); |
1184 | - if (Q_UNLIKELY(!account)) { |
1185 | - QVariantMap result; |
1186 | - result[SSOUI_KEY_ERROR] = SignOn::QUERY_ERROR_FORBIDDEN; |
1187 | - q->setResult(result); |
1188 | - return; |
1189 | - } |
1190 | - |
1191 | - OnlineAccountsUi::ApplicationManager *appManager = |
1192 | - OnlineAccountsUi::ApplicationManager::instance(); |
1193 | - Accounts::Application application = |
1194 | - appManager->applicationFromProfile(q->clientApparmorProfile()); |
1195 | - |
1196 | - OnlineAccountsUi::AccountManager *accountManager = |
1197 | - OnlineAccountsUi::AccountManager::instance(); |
1198 | - Accounts::Provider provider = |
1199 | - accountManager->provider(account->providerName()); |
1200 | - |
1201 | - QString summary = |
1202 | - QString("Please authorize %1 to access your %2 account %3"). |
1203 | - arg(application.isValid() ? application.displayName() : "Ubuntu"). |
1204 | - arg(provider.displayName()). |
1205 | - arg(account->displayName()); |
1206 | - m_notification = |
1207 | - new OnlineAccountsUi::Notification("Authentication request", summary); |
1208 | - m_notification->addAction("cancel", "Cancel"); |
1209 | - m_notification->addAction("continue", "Authorize..."); |
1210 | - m_notification->setSnapDecision(true); |
1211 | - QObject::connect(m_notification, SIGNAL(actionInvoked(const QString &)), |
1212 | - this, SLOT(onActionInvoked(const QString &))); |
1213 | - QObject::connect(m_notification, SIGNAL(closed()), |
1214 | - this, SLOT(onNotificationClosed())); |
1215 | - m_notification->show(); |
1216 | - m_window = window; |
1217 | } |
1218 | |
1219 | Accounts::Account *RequestPrivate::findAccount() |
1220 | @@ -162,39 +107,6 @@ |
1221 | return 0; |
1222 | } |
1223 | |
1224 | -void RequestPrivate::onActionInvoked(const QString &action) |
1225 | -{ |
1226 | - Q_Q(Request); |
1227 | - |
1228 | - DEBUG() << action; |
1229 | - |
1230 | - QObject::disconnect(m_notification, 0, this, 0); |
1231 | - m_notification->deleteLater(); |
1232 | - m_notification = 0; |
1233 | - |
1234 | - if (action == QStringLiteral("continue")) { |
1235 | - q->setWindow(m_window); |
1236 | - } else { |
1237 | - q->cancel(); |
1238 | - } |
1239 | -} |
1240 | - |
1241 | -void RequestPrivate::onNotificationClosed() |
1242 | -{ |
1243 | - Q_Q(Request); |
1244 | - |
1245 | - DEBUG(); |
1246 | - |
1247 | - /* setResult() should have been called by onActionInvoked(), but calling it |
1248 | - * twice won't harm because only the first invocation counts. */ |
1249 | - QVariantMap result; |
1250 | - result[SSOUI_KEY_ERROR] = SignOn::QUERY_ERROR_FORBIDDEN; |
1251 | - q->setResult(result); |
1252 | - |
1253 | - m_notification->deleteLater(); |
1254 | - m_notification = 0; |
1255 | -} |
1256 | - |
1257 | #ifndef NO_REQUEST_FACTORY |
1258 | Request *Request::newRequest(int id, |
1259 | const QString &clientProfile, |
1260 | @@ -266,22 +178,13 @@ |
1261 | { |
1262 | Q_D(Request); |
1263 | |
1264 | - /* While a notification is shown, ignore any further calls to |
1265 | - * setWindow(). */ |
1266 | - if (d->m_notification) return; |
1267 | - |
1268 | - /* The first time that this method is called, we handle it by presenting a |
1269 | - * snap decision to the user. |
1270 | - * Then, if this is called again with the same QWindow, it means that the |
1271 | - * snap decision was accepted, and we show the window. |
1272 | - */ |
1273 | - if (window == d->m_window || |
1274 | - /* If we are part of a prompt session, just show the window */ |
1275 | - !qgetenv("MIR_SOCKET").isEmpty()) { |
1276 | + /* Show the window only if we are in a prompt session */ |
1277 | + if (qgetenv("MIR_SOCKET").isEmpty()) { |
1278 | + QVariantMap result; |
1279 | + result[SSOUI_KEY_ERROR] = SignOn::QUERY_ERROR_FORBIDDEN; |
1280 | + setResult(result); |
1281 | + } else { |
1282 | OnlineAccountsUi::Request::setWindow(window); |
1283 | - d->m_window = 0; |
1284 | - } else { |
1285 | - d->setWindow(window); |
1286 | } |
1287 | } |
1288 | |
1289 | @@ -300,6 +203,13 @@ |
1290 | return parameters().value(SSOUI_KEY_MECHANISM).toString(); |
1291 | } |
1292 | |
1293 | +QString Request::providerId() const |
1294 | +{ |
1295 | + Q_D(const Request); |
1296 | + return d->m_account ? d->m_account->providerName() : |
1297 | + d->m_clientData.value("providerId").toString(); |
1298 | +} |
1299 | + |
1300 | const QVariantMap &Request::clientData() const |
1301 | { |
1302 | Q_D(const Request); |
1303 | |
1304 | === modified file 'online-accounts-ui/signonui-request.h' |
1305 | --- online-accounts-ui/signonui-request.h 2014-08-08 11:37:56 +0000 |
1306 | +++ online-accounts-ui/signonui-request.h 2015-01-16 17:10:14 +0000 |
1307 | @@ -45,6 +45,7 @@ |
1308 | uint identity() const; |
1309 | QString method() const; |
1310 | QString mechanism() const; |
1311 | + QString providerId() const; |
1312 | |
1313 | const QVariantMap &clientData() const; |
1314 | |
1315 | |
1316 | === modified file 'plugins/module/OAuth.qml' |
1317 | --- plugins/module/OAuth.qml 2014-06-10 14:48:22 +0000 |
1318 | +++ plugins/module/OAuth.qml 2015-01-16 17:10:14 +0000 |
1319 | @@ -169,6 +169,7 @@ |
1320 | if (creds.credentialsId == 0) return |
1321 | var parameters = {} |
1322 | parameters[requestHandler.matchKey] = requestHandler.matchId |
1323 | + parameters["providerId"] = account.provider.id |
1324 | for (var p in authenticationParameters) { |
1325 | parameters[p] = authenticationParameters[p] |
1326 | } |
1327 | |
1328 | === modified file 'plugins/module/ServiceItem.qml' |
1329 | --- plugins/module/ServiceItem.qml 2014-09-30 13:30:39 +0000 |
1330 | +++ plugins/module/ServiceItem.qml 2015-01-16 17:10:14 +0000 |
1331 | @@ -21,7 +21,7 @@ |
1332 | import Ubuntu.Components.ListItems 0.1 as ListItem |
1333 | import Ubuntu.OnlineAccounts 0.1 |
1334 | |
1335 | -Item { |
1336 | +Column { |
1337 | property variant accountServiceHandle |
1338 | |
1339 | signal applicationAdded(string applicationId) |
1340 | @@ -29,7 +29,6 @@ |
1341 | |
1342 | anchors.left: parent.left |
1343 | anchors.right: parent.right |
1344 | - height: childrenRect.height |
1345 | |
1346 | Repeater { |
1347 | resources: AccountService { |
1348 | |
1349 | === modified file 'plugins/plugins.pro' |
1350 | --- plugins/plugins.pro 2014-10-03 14:56:11 +0000 |
1351 | +++ plugins/plugins.pro 2015-01-16 17:10:14 +0000 |
1352 | @@ -1,6 +1,7 @@ |
1353 | TEMPLATE = subdirs |
1354 | -CONFIG += ordered |
1355 | SUBDIRS = \ |
1356 | OnlineAccountsPlugin \ |
1357 | module \ |
1358 | example |
1359 | + |
1360 | +module.depends = OnlineAccountsPlugin |
1361 | |
1362 | === modified file 'tests/online-accounts-service/mock/request-mock.cpp' |
1363 | --- tests/online-accounts-service/mock/request-mock.cpp 2014-11-25 13:34:16 +0000 |
1364 | +++ tests/online-accounts-service/mock/request-mock.cpp 2015-01-16 17:10:14 +0000 |
1365 | @@ -48,6 +48,11 @@ |
1366 | m_clientApparmorProfile = profile; |
1367 | } |
1368 | |
1369 | +void RequestPrivate::setProviderId(const QString &provider) |
1370 | +{ |
1371 | + m_providerId = provider; |
1372 | +} |
1373 | + |
1374 | Request::Request(const QDBusConnection &connection, |
1375 | const QDBusMessage &message, |
1376 | const QVariantMap ¶meters, |
1377 | @@ -96,6 +101,11 @@ |
1378 | return d->m_message.interface(); |
1379 | } |
1380 | |
1381 | +QString Request::providerId() const { |
1382 | + Q_D(const Request); |
1383 | + return d->m_providerId; |
1384 | +} |
1385 | + |
1386 | void Request::setDelay(int delay) |
1387 | { |
1388 | Q_D(Request); |
1389 | |
1390 | === modified file 'tests/online-accounts-service/mock/request-mock.h' |
1391 | --- tests/online-accounts-service/mock/request-mock.h 2014-11-25 13:34:16 +0000 |
1392 | +++ tests/online-accounts-service/mock/request-mock.h 2015-01-16 17:10:14 +0000 |
1393 | @@ -43,6 +43,7 @@ |
1394 | static RequestPrivate *mocked(Request *r) { return r->d_ptr; } |
1395 | |
1396 | void setClientApparmorProfile(const QString &profile); |
1397 | + void setProviderId(const QString &provider); |
1398 | |
1399 | Q_SIGNALS: |
1400 | void cancelCalled(); |
1401 | @@ -54,6 +55,7 @@ |
1402 | QDBusMessage m_message; |
1403 | QVariantMap m_parameters; |
1404 | QString m_clientApparmorProfile; |
1405 | + QString m_providerId; |
1406 | bool m_inProgress; |
1407 | int m_delay; |
1408 | mutable Request *q_ptr; |
1409 | |
1410 | === modified file 'tests/online-accounts-service/online-accounts-service.pro' |
1411 | --- tests/online-accounts-service/online-accounts-service.pro 2014-08-25 14:54:38 +0000 |
1412 | +++ tests/online-accounts-service/online-accounts-service.pro 2015-01-16 17:10:14 +0000 |
1413 | @@ -1,6 +1,7 @@ |
1414 | TEMPLATE = subdirs |
1415 | SUBDIRS = \ |
1416 | tst_inactivity_timer.pro \ |
1417 | + tst_libaccounts_service.pro \ |
1418 | tst_service.pro \ |
1419 | tst_signonui_service.pro \ |
1420 | tst_ui_proxy.pro |
1421 | |
1422 | === added file 'tests/online-accounts-service/tst_libaccounts_service.cpp' |
1423 | --- tests/online-accounts-service/tst_libaccounts_service.cpp 1970-01-01 00:00:00 +0000 |
1424 | +++ tests/online-accounts-service/tst_libaccounts_service.cpp 2015-01-16 17:10:14 +0000 |
1425 | @@ -0,0 +1,522 @@ |
1426 | +/* |
1427 | + * Copyright (C) 2013 Canonical Ltd. |
1428 | + * |
1429 | + * Contact: Alberto Mardegan <alberto.mardegan@canonical.com> |
1430 | + * |
1431 | + * This file is part of online-accounts-ui |
1432 | + * |
1433 | + * This program is free software: you can redistribute it and/or modify it |
1434 | + * under the terms of the GNU General Public License version 3, as published |
1435 | + * by the Free Software Foundation. |
1436 | + * |
1437 | + * This program is distributed in the hope that it will be useful, but |
1438 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1439 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1440 | + * PURPOSE. See the GNU General Public License for more details. |
1441 | + * |
1442 | + * You should have received a copy of the GNU General Public License along |
1443 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1444 | + */ |
1445 | + |
1446 | +#include "debug.h" |
1447 | +#include "libaccounts-service.h" |
1448 | + |
1449 | +#include <Accounts/Account> |
1450 | +#include <Accounts/Manager> |
1451 | +#include <Accounts/Service> |
1452 | +#include <QDBusConnection> |
1453 | +#include <QDebug> |
1454 | +#include <QProcess> |
1455 | +#include <QSignalSpy> |
1456 | +#include <QString> |
1457 | +#include <QTest> |
1458 | + |
1459 | +using namespace OnlineAccountsUi; |
1460 | + |
1461 | +#define TEST_SERVICE_NAME \ |
1462 | + "com.ubuntu.OnlineAccountsUi.LibaccountsService.Test" |
1463 | +#define TEST_OBJECT_PATH "/" |
1464 | + |
1465 | +class LibaccountsServiceTest: public QObject |
1466 | +{ |
1467 | + Q_OBJECT |
1468 | + |
1469 | +public: |
1470 | + LibaccountsServiceTest(); |
1471 | + |
1472 | +private: |
1473 | + QProcess *requestStore(const QString &args, bool showError = false) { |
1474 | + QString command = QStringLiteral("gdbus call --session " |
1475 | + "--dest " TEST_SERVICE_NAME " " |
1476 | + "--object-path " TEST_OBJECT_PATH " " |
1477 | + "--method com.google.code.AccountsSSO.Accounts.Manager.store "); |
1478 | + QProcess *process = new QProcess(this); |
1479 | + if (showError) { |
1480 | + process->setProcessChannelMode(QProcess::ForwardedErrorChannel); |
1481 | + } |
1482 | + process->start(command + args); |
1483 | + process->waitForStarted(); |
1484 | + return process; |
1485 | + } |
1486 | + |
1487 | +private Q_SLOTS: |
1488 | + void init(); |
1489 | + void testProfile_data(); |
1490 | + void testProfile(); |
1491 | + void testFailure(); |
1492 | + void testAccount_data(); |
1493 | + void testAccount(); |
1494 | + void testSettings_data(); |
1495 | + void testSettings(); |
1496 | + |
1497 | +private: |
1498 | + LibaccountsService m_service; |
1499 | +}; |
1500 | + |
1501 | +/* Mocking libaccounts-qt { */ |
1502 | +class ManagerController { |
1503 | +public: |
1504 | + ManagerController(): lastLoadedAccount(0) { m_instance = this; } |
1505 | + ~ManagerController() { m_instance = 0; } |
1506 | + static ManagerController *instance() { return m_instance; } |
1507 | + |
1508 | + void setServices(const QStringList &services) { m_services = services; } |
1509 | + |
1510 | +public: |
1511 | + Accounts::Account *lastLoadedAccount; |
1512 | + |
1513 | +private: |
1514 | + friend class Accounts::Manager; |
1515 | + QStringList m_services; |
1516 | + static ManagerController *m_instance; |
1517 | +}; |
1518 | + |
1519 | +ManagerController *ManagerController::m_instance = 0; |
1520 | + |
1521 | +typedef QHash<QString,QVariantMap> ServiceSettings; |
1522 | +typedef QHash<QString,QSet<QString> > RemovedKeys; |
1523 | + |
1524 | +class AccountController: public QObject { |
1525 | + Q_OBJECT |
1526 | +public: |
1527 | + AccountController(Accounts::Account *account): |
1528 | + QObject(account), |
1529 | + m_id(0), |
1530 | + m_wasDeleted(false), |
1531 | + m_syncWasCalled(false), |
1532 | + m_account(account) { |
1533 | + m_controllers[account] = this; |
1534 | + } |
1535 | + |
1536 | + static AccountController *mock(Accounts::Account *account) { |
1537 | + return m_controllers[account]; |
1538 | + } |
1539 | + |
1540 | + bool syncWasCalled() const { return m_syncWasCalled; } |
1541 | + void doSync(Accounts::Error error = Accounts::Error()) { |
1542 | + if (error.type() == Accounts::Error::NoError) { |
1543 | + QMetaObject::invokeMethod(m_account, "synced", Qt::QueuedConnection); |
1544 | + } else { |
1545 | + QMetaObject::invokeMethod(m_account, "error", Qt::QueuedConnection, |
1546 | + Q_ARG(Accounts::Error, error)); |
1547 | + } |
1548 | + } |
1549 | + |
1550 | +protected: |
1551 | + void syncCalled() { m_syncWasCalled = true; } |
1552 | + |
1553 | +public: |
1554 | + quint32 m_id; |
1555 | + QString m_provider; |
1556 | + ServiceSettings m_serviceSettings; |
1557 | + RemovedKeys m_removedKeys; |
1558 | + bool m_wasDeleted; |
1559 | + bool m_syncWasCalled; |
1560 | +private: |
1561 | + friend class Accounts::Account; |
1562 | + static QHash<Accounts::Account *,AccountController*> m_controllers; |
1563 | + Accounts::Account *m_account; |
1564 | +}; |
1565 | + |
1566 | +QHash<Accounts::Account *,AccountController*> AccountController::m_controllers; |
1567 | + |
1568 | +struct _AgService { |
1569 | + _AgService(const QString &name): name(name) {} |
1570 | + QString name; |
1571 | +}; |
1572 | + |
1573 | +namespace Accounts { |
1574 | + |
1575 | +Service::Service(): |
1576 | + m_service(0), |
1577 | + m_tags(0) |
1578 | +{ |
1579 | +} |
1580 | + |
1581 | +Service::Service(AgService *service, ReferenceMode): |
1582 | + m_service(service), |
1583 | + m_tags(0) |
1584 | +{ |
1585 | +} |
1586 | + |
1587 | +Service::Service(const Service &other): |
1588 | + m_service(other.m_service ? new _AgService(other.m_service->name) : 0), |
1589 | + m_tags(0) |
1590 | +{ |
1591 | +} |
1592 | + |
1593 | +Service &Service::operator=(const Service &other) |
1594 | +{ |
1595 | + delete m_service; |
1596 | + m_service = other.m_service ? new _AgService(other.m_service->name) : 0; |
1597 | + return *this; |
1598 | +} |
1599 | + |
1600 | +Service::~Service() |
1601 | +{ |
1602 | + delete m_service; |
1603 | +} |
1604 | + |
1605 | +bool Service::isValid() const |
1606 | +{ |
1607 | + return m_service != 0; |
1608 | +} |
1609 | + |
1610 | +class Account::Private { |
1611 | +public: |
1612 | + Private() {} |
1613 | + |
1614 | + QString m_selectedService; |
1615 | + AccountController *m_controller; |
1616 | +}; |
1617 | + |
1618 | +Account::Account(Private *d, QObject *parent): |
1619 | + QObject(parent), |
1620 | + d(d) |
1621 | +{ |
1622 | + d->m_controller = new AccountController(this); |
1623 | +} |
1624 | + |
1625 | +Account::~Account() |
1626 | +{ |
1627 | + delete d; |
1628 | +} |
1629 | + |
1630 | +AccountId Account::id() const |
1631 | +{ |
1632 | + return d->m_controller->m_id; |
1633 | +} |
1634 | + |
1635 | +void Account::selectService(const Service &service) |
1636 | +{ |
1637 | + d->m_selectedService = service.m_service ? |
1638 | + service.m_service->name : QString(); |
1639 | +} |
1640 | + |
1641 | +void Account::setValue(const QString &key, const QVariant &value) |
1642 | +{ |
1643 | + QVariantMap &settings = |
1644 | + d->m_controller->m_serviceSettings[d->m_selectedService]; |
1645 | + settings.insert(key, value); |
1646 | +} |
1647 | + |
1648 | +void Account::remove(const QString &key) |
1649 | +{ |
1650 | + QSet<QString> &removedKeys = |
1651 | + d->m_controller->m_removedKeys[d->m_selectedService]; |
1652 | + removedKeys.insert(key); |
1653 | +} |
1654 | + |
1655 | +void Account::sync() |
1656 | +{ |
1657 | + d->m_controller->syncCalled(); |
1658 | +} |
1659 | + |
1660 | +void Account::remove() |
1661 | +{ |
1662 | + d->m_controller->m_wasDeleted = true; |
1663 | +} |
1664 | + |
1665 | +Watch::~Watch() |
1666 | +{ |
1667 | +} |
1668 | + |
1669 | +class Manager::Private { |
1670 | +public: |
1671 | + Private() {} |
1672 | + |
1673 | + ManagerController m_controller; |
1674 | +}; |
1675 | + |
1676 | +Manager::Manager(QObject *parent): |
1677 | + QObject(parent), |
1678 | + d(new Private()) |
1679 | +{ |
1680 | +} |
1681 | + |
1682 | +Manager::~Manager() |
1683 | +{ |
1684 | + delete d; |
1685 | +} |
1686 | + |
1687 | +Account *Manager::account(const AccountId &id) const |
1688 | +{ |
1689 | + Account::Private *accountD = new Account::Private(); |
1690 | + d->m_controller.lastLoadedAccount = |
1691 | + new Account(accountD, const_cast<Manager*>(this)); |
1692 | + accountD->m_controller->m_id = id; |
1693 | + return d->m_controller.lastLoadedAccount; |
1694 | +} |
1695 | + |
1696 | +Account *Manager::createAccount(const QString &providerName) |
1697 | +{ |
1698 | + Account::Private *accountD = new Account::Private(); |
1699 | + d->m_controller.lastLoadedAccount = new Account(accountD, this); |
1700 | + accountD->m_controller->m_provider = providerName; |
1701 | + return d->m_controller.lastLoadedAccount; |
1702 | +} |
1703 | + |
1704 | +Service Manager::service(const QString &serviceName) const |
1705 | +{ |
1706 | + if (d->m_controller.m_services.contains(serviceName)) { |
1707 | + return Service(new _AgService(serviceName)); |
1708 | + } else { |
1709 | + return Service(); |
1710 | + } |
1711 | +} |
1712 | + |
1713 | +} // namespace |
1714 | + |
1715 | +/* } mocking libaccounts-qt */ |
1716 | + |
1717 | +/* mocking utils.cpp { */ |
1718 | +namespace OnlineAccountsUi { |
1719 | + |
1720 | +static QString staticApparmorProfile; |
1721 | + |
1722 | +QString apparmorProfileOfPeer(const QDBusMessage &) |
1723 | +{ |
1724 | + return staticApparmorProfile; |
1725 | +} |
1726 | + |
1727 | +void setApparmorProfile(const QString &profile) |
1728 | +{ |
1729 | + staticApparmorProfile = profile; |
1730 | +} |
1731 | + |
1732 | +} // namespace |
1733 | +/* } mocking utils.cpp */ |
1734 | + |
1735 | +Q_DECLARE_METATYPE(QProcess::ExitStatus) |
1736 | + |
1737 | +LibaccountsServiceTest::LibaccountsServiceTest(): |
1738 | + QObject(0) |
1739 | +{ |
1740 | + QDBusConnection conn = QDBusConnection::sessionBus(); |
1741 | + conn.registerService(TEST_SERVICE_NAME); |
1742 | + conn.registerObject(TEST_OBJECT_PATH, &m_service, |
1743 | + QDBusConnection::ExportAllContents); |
1744 | + |
1745 | + qRegisterMetaType<QProcess::ExitStatus>(); |
1746 | + setLoggingLevel(2); |
1747 | +} |
1748 | + |
1749 | +void LibaccountsServiceTest::init() |
1750 | +{ |
1751 | + ManagerController *mc = ManagerController::instance(); |
1752 | + mc->lastLoadedAccount = 0; |
1753 | +} |
1754 | + |
1755 | +void LibaccountsServiceTest::testProfile_data() |
1756 | +{ |
1757 | + QTest::addColumn<QString>("profile"); |
1758 | + QTest::addColumn<QString>("provider"); |
1759 | + QTest::addColumn<bool>("mustPass"); |
1760 | + |
1761 | + QTest::newRow("non click, mismatch") << |
1762 | + "appProfile" << "OneProvider" << false; |
1763 | + |
1764 | + QTest::newRow("non click, match") << |
1765 | + "theProfile" << "theProfile" << true; |
1766 | + |
1767 | + QTest::newRow("click, mismatch") << |
1768 | + "com.ubuntu.package_app_0.1" << "com.ubuntu.package_other" << false; |
1769 | + |
1770 | + QTest::newRow("click, match") << |
1771 | + "com.ubuntu.package_app_0.2" << "com.ubuntu.package_app" << true; |
1772 | +} |
1773 | + |
1774 | +void LibaccountsServiceTest::testProfile() |
1775 | +{ |
1776 | + QFETCH(QString, profile); |
1777 | + QFETCH(QString, provider); |
1778 | + QFETCH(bool, mustPass); |
1779 | + |
1780 | + setApparmorProfile(profile); |
1781 | + QString params = QString::fromUtf8("0 true false %1 []").arg(provider); |
1782 | + QProcess *client = requestStore(params); |
1783 | + QSignalSpy finished(client, SIGNAL(finished(int,QProcess::ExitStatus))); |
1784 | + |
1785 | + if (mustPass) { |
1786 | + ManagerController *mc = ManagerController::instance(); |
1787 | + QTRY_VERIFY(mc->lastLoadedAccount != 0); |
1788 | + AccountController *ac = AccountController::mock(mc->lastLoadedAccount); |
1789 | + QTRY_COMPARE(ac->syncWasCalled(), true); |
1790 | + ac->doSync(); |
1791 | + } |
1792 | + |
1793 | + finished.wait(); |
1794 | + |
1795 | + QByteArray stdErr = client->readAllStandardError(); |
1796 | + QCOMPARE(stdErr.contains("Profile/provider mismatch"), !mustPass); |
1797 | +} |
1798 | + |
1799 | +void LibaccountsServiceTest::testFailure() |
1800 | +{ |
1801 | + setApparmorProfile("MyProvider"); |
1802 | + QProcess *client = requestStore("0 true false MyProvider []"); |
1803 | + QSignalSpy finished(client, SIGNAL(finished(int,QProcess::ExitStatus))); |
1804 | + |
1805 | + ManagerController *mc = ManagerController::instance(); |
1806 | + QTRY_VERIFY(mc->lastLoadedAccount != 0); |
1807 | + AccountController *ac = AccountController::mock(mc->lastLoadedAccount); |
1808 | + QTRY_COMPARE(ac->syncWasCalled(), true); |
1809 | + |
1810 | + // return an error |
1811 | + Accounts::Error error(Accounts::Error::Database, "hi there"); |
1812 | + ac->doSync(error); |
1813 | + finished.wait(); |
1814 | + |
1815 | + QVERIFY(client->readAllStandardError().contains("hi there")); |
1816 | +} |
1817 | + |
1818 | +void LibaccountsServiceTest::testAccount_data() |
1819 | +{ |
1820 | + QTest::addColumn<QString>("clientSettings"); |
1821 | + QTest::addColumn<QString>("provider"); |
1822 | + QTest::addColumn<quint32>("accountId"); |
1823 | + QTest::addColumn<bool>("deleted"); |
1824 | + |
1825 | + QTest::newRow("new account") << |
1826 | + "0 true false Cool" << |
1827 | + "Cool" << quint32(0) << false; |
1828 | + |
1829 | + QTest::newRow("existing account") << |
1830 | + "5 false false Bad" << |
1831 | + "Bad" << quint32(5) << false; |
1832 | + |
1833 | + QTest::newRow("deleting account") << |
1834 | + "7 false true Die" << |
1835 | + "Die" << quint32(7) << true; |
1836 | +} |
1837 | + |
1838 | +void LibaccountsServiceTest::testAccount() |
1839 | +{ |
1840 | + QFETCH(QString, clientSettings); |
1841 | + QFETCH(QString, provider); |
1842 | + QFETCH(quint32, accountId); |
1843 | + QFETCH(bool, deleted); |
1844 | + |
1845 | + setApparmorProfile(provider); |
1846 | + |
1847 | + ManagerController *mc = ManagerController::instance(); |
1848 | + |
1849 | + QString params = QString::fromUtf8("%1 []").arg(clientSettings); |
1850 | + QProcess *client = requestStore(params, true); |
1851 | + QSignalSpy finished(client, SIGNAL(finished(int,QProcess::ExitStatus))); |
1852 | + |
1853 | + QTRY_VERIFY(mc->lastLoadedAccount != 0); |
1854 | + AccountController *ac = AccountController::mock(mc->lastLoadedAccount); |
1855 | + QTRY_COMPARE(ac->syncWasCalled(), true); |
1856 | + |
1857 | + QCOMPARE(ac->m_id, accountId); |
1858 | + if (accountId == 0) { |
1859 | + QCOMPARE(ac->m_provider, provider); |
1860 | + } |
1861 | + QCOMPARE(ac->m_wasDeleted, deleted); |
1862 | + |
1863 | + ac->doSync(); |
1864 | + |
1865 | + finished.wait(); |
1866 | +} |
1867 | + |
1868 | +void LibaccountsServiceTest::testSettings_data() |
1869 | +{ |
1870 | + QTest::addColumn<QString>("clientSettings"); |
1871 | + QTest::addColumn<ServiceSettings>("settings"); |
1872 | + QTest::addColumn<RemovedKeys>("removedKeys"); |
1873 | + |
1874 | + QHash<QString,QVariantMap> settings; |
1875 | + QHash<QString,QSet<QString> > removedKeys; |
1876 | + |
1877 | + QTest::newRow("no services") << |
1878 | + "\"[]\"" << |
1879 | + settings << removedKeys; |
1880 | + QTest::newRow("no settings") << |
1881 | + "\"[('cool', 'type', 3, {}, [])]\"" << |
1882 | + settings << removedKeys; |
1883 | + |
1884 | + settings["cool"].insert("enabled", false); |
1885 | + settings["cool"].insert("name", QString("Bob")); |
1886 | + QTest::newRow("some keys changed") << |
1887 | + "\"[('cool', 'type', 3, {'enabled': <false>, 'name': <'Bob'>}, [])]\"" << |
1888 | + settings << removedKeys; |
1889 | + settings.clear(); |
1890 | + |
1891 | + removedKeys["cool"].insert("enabled"); |
1892 | + removedKeys["cool"].insert("id"); |
1893 | + QTest::newRow("some keys removed") << |
1894 | + "\"[('cool', 'type', 3, {}, ['enabled','id'])]\"" << |
1895 | + settings << removedKeys; |
1896 | + removedKeys.clear(); |
1897 | + |
1898 | + settings["cool"].insert("enabled", true); |
1899 | + settings["cool"].insert("name", QString("Tom")); |
1900 | + removedKeys["cool"].insert("id"); |
1901 | + settings["bad"].insert("port", quint32(4000)); |
1902 | + removedKeys["bad"].insert("name"); |
1903 | + QTest::newRow("two services, lots of changes") << |
1904 | + "\"[" |
1905 | + "('cool', 'type', 3, {'enabled': <true>, 'name': <'Tom'>}, ['id'])," |
1906 | + "('bad', 'btype', 2, {'port': <uint32 4000>}, ['name'])" |
1907 | + "]\"" << |
1908 | + settings << removedKeys; |
1909 | + settings.clear(); |
1910 | + removedKeys.clear(); |
1911 | + |
1912 | + QTest::newRow("invalid service") << |
1913 | + "\"[('findme', 'type', 3, {}, ['enabled','id'])]\"" << |
1914 | + settings << removedKeys; |
1915 | +} |
1916 | + |
1917 | +void LibaccountsServiceTest::testSettings() |
1918 | +{ |
1919 | + QFETCH(QString, clientSettings); |
1920 | + QFETCH(ServiceSettings, settings); |
1921 | + QFETCH(RemovedKeys, removedKeys); |
1922 | + |
1923 | + setApparmorProfile("MyProvider"); |
1924 | + |
1925 | + ManagerController *mc = ManagerController::instance(); |
1926 | + mc->setServices(QStringList() << "cool" << "bad"); |
1927 | + |
1928 | + QString params = |
1929 | + QString::fromUtf8("0 true false MyProvider %1").arg(clientSettings); |
1930 | + QProcess *client = requestStore(params, true); |
1931 | + QSignalSpy finished(client, SIGNAL(finished(int,QProcess::ExitStatus))); |
1932 | + |
1933 | + QTRY_VERIFY(mc->lastLoadedAccount != 0); |
1934 | + AccountController *ac = AccountController::mock(mc->lastLoadedAccount); |
1935 | + QTRY_COMPARE(ac->syncWasCalled(), true); |
1936 | + |
1937 | + QCOMPARE(ac->m_serviceSettings, settings); |
1938 | + QCOMPARE(ac->m_removedKeys, removedKeys); |
1939 | + |
1940 | + ac->doSync(); |
1941 | + |
1942 | + finished.wait(); |
1943 | +} |
1944 | + |
1945 | +QTEST_MAIN(LibaccountsServiceTest); |
1946 | + |
1947 | +#include "tst_libaccounts_service.moc" |
1948 | |
1949 | === added file 'tests/online-accounts-service/tst_libaccounts_service.pro' |
1950 | --- tests/online-accounts-service/tst_libaccounts_service.pro 1970-01-01 00:00:00 +0000 |
1951 | +++ tests/online-accounts-service/tst_libaccounts_service.pro 2015-01-16 17:10:14 +0000 |
1952 | @@ -0,0 +1,38 @@ |
1953 | +include(../../common-project-config.pri) |
1954 | + |
1955 | +TARGET = tst_libaccounts_service |
1956 | + |
1957 | +CONFIG += \ |
1958 | + debug \ |
1959 | + link_pkgconfig |
1960 | + |
1961 | +QT += \ |
1962 | + core \ |
1963 | + dbus \ |
1964 | + testlib \ |
1965 | + xml |
1966 | + |
1967 | +ONLINE_ACCOUNTS_SERVICE_DIR = $${TOP_SRC_DIR}/online-accounts-service |
1968 | +COMMON_SRC_DIR = $${TOP_SRC_DIR}/online-accounts-ui |
1969 | +LIBACCOUNTS_QT_DIR = $$system(pkg-config --variable=includedir accounts-qt5)/Accounts |
1970 | + |
1971 | +SOURCES += \ |
1972 | + $${COMMON_SRC_DIR}/debug.cpp \ |
1973 | + $${ONLINE_ACCOUNTS_SERVICE_DIR}/libaccounts-service.cpp \ |
1974 | + tst_libaccounts_service.cpp |
1975 | + |
1976 | +HEADERS += \ |
1977 | + $${ONLINE_ACCOUNTS_SERVICE_DIR}/libaccounts-service.h \ |
1978 | + $${ONLINE_ACCOUNTS_SERVICE_DIR}/utils.h \ |
1979 | + $${LIBACCOUNTS_QT_DIR}/account.h \ |
1980 | + $${LIBACCOUNTS_QT_DIR}/manager.h |
1981 | + |
1982 | +INCLUDEPATH += \ |
1983 | + $${ONLINE_ACCOUNTS_SERVICE_DIR} \ |
1984 | + $${COMMON_SRC_DIR} \ |
1985 | + $$system(pkg-config --variable=includedir accounts-qt5) |
1986 | + |
1987 | +check.commands = "xvfb-run -s '-screen 0 640x480x24' -a dbus-test-runner -t ./$${TARGET}" |
1988 | +check.depends = $${TARGET} |
1989 | +QMAKE_EXTRA_TARGETS += check |
1990 | + |
1991 | |
1992 | === modified file 'tests/online-accounts-service/tst_service.pro' |
1993 | --- tests/online-accounts-service/tst_service.pro 2014-10-13 11:25:27 +0000 |
1994 | +++ tests/online-accounts-service/tst_service.pro 2015-01-16 17:10:14 +0000 |
1995 | @@ -25,6 +25,7 @@ |
1996 | $${ONLINE_ACCOUNTS_SERVICE_DIR}/request.cpp \ |
1997 | $${ONLINE_ACCOUNTS_SERVICE_DIR}/request-manager.cpp \ |
1998 | $${ONLINE_ACCOUNTS_SERVICE_DIR}/service.cpp \ |
1999 | + $${ONLINE_ACCOUNTS_SERVICE_DIR}/utils.cpp \ |
2000 | tst_service.cpp |
2001 | |
2002 | HEADERS += \ |
2003 | @@ -33,6 +34,7 @@ |
2004 | $${ONLINE_ACCOUNTS_SERVICE_DIR}/request-manager.h \ |
2005 | $${ONLINE_ACCOUNTS_SERVICE_DIR}/service.h \ |
2006 | $${ONLINE_ACCOUNTS_SERVICE_DIR}/ui-proxy.h \ |
2007 | + $${ONLINE_ACCOUNTS_SERVICE_DIR}/utils.h \ |
2008 | |
2009 | INCLUDEPATH += \ |
2010 | $${ONLINE_ACCOUNTS_SERVICE_DIR} \ |
2011 | |
2012 | === modified file 'tests/online-accounts-service/tst_signonui_service.pro' |
2013 | --- tests/online-accounts-service/tst_signonui_service.pro 2014-08-19 11:14:34 +0000 |
2014 | +++ tests/online-accounts-service/tst_signonui_service.pro 2015-01-16 17:10:14 +0000 |
2015 | @@ -24,6 +24,7 @@ |
2016 | SOURCES += \ |
2017 | $${ONLINE_ACCOUNTS_SERVICE_DIR}/request.cpp \ |
2018 | $${ONLINE_ACCOUNTS_SERVICE_DIR}/signonui-service.cpp \ |
2019 | + $${ONLINE_ACCOUNTS_SERVICE_DIR}/utils.cpp \ |
2020 | mock/request-manager-mock.cpp \ |
2021 | tst_signonui_service.cpp |
2022 | |
2023 | @@ -31,6 +32,7 @@ |
2024 | $${ONLINE_ACCOUNTS_SERVICE_DIR}/request.h \ |
2025 | $${ONLINE_ACCOUNTS_SERVICE_DIR}/request-manager.h \ |
2026 | $${ONLINE_ACCOUNTS_SERVICE_DIR}/signonui-service.h \ |
2027 | + $${ONLINE_ACCOUNTS_SERVICE_DIR}/utils.h \ |
2028 | mock/request-manager-mock.h |
2029 | |
2030 | INCLUDEPATH += \ |
2031 | |
2032 | === modified file 'tests/online-accounts-service/tst_ui_proxy.pro' |
2033 | --- tests/online-accounts-service/tst_ui_proxy.pro 2014-08-26 08:39:20 +0000 |
2034 | +++ tests/online-accounts-service/tst_ui_proxy.pro 2015-01-16 17:10:14 +0000 |
2035 | @@ -16,6 +16,7 @@ |
2036 | INSTALL_BIN_DIR=\\\"$${INSTALL_PREFIX}/bin\\\" |
2037 | |
2038 | PKGCONFIG += \ |
2039 | + accounts-qt5 \ |
2040 | signon-plugins-common |
2041 | |
2042 | ONLINE_ACCOUNTS_SERVICE_DIR = $${TOP_SRC_DIR}/online-accounts-service |
2043 | |
2044 | === modified file 'tests/online-accounts-ui/mock/signonui-request-mock.cpp' |
2045 | --- tests/online-accounts-ui/mock/signonui-request-mock.cpp 2014-09-17 14:39:07 +0000 |
2046 | +++ tests/online-accounts-ui/mock/signonui-request-mock.cpp 2015-01-16 17:10:14 +0000 |
2047 | @@ -86,6 +86,12 @@ |
2048 | return parameters().value(SSOUI_KEY_MECHANISM).toString(); |
2049 | } |
2050 | |
2051 | +QString Request::providerId() const |
2052 | +{ |
2053 | + Q_D(const Request); |
2054 | + return d->m_providerId; |
2055 | +} |
2056 | + |
2057 | const QVariantMap &Request::clientData() const |
2058 | { |
2059 | Q_D(const Request); |
2060 | |
2061 | === modified file 'tests/online-accounts-ui/mock/signonui-request-mock.h' |
2062 | --- tests/online-accounts-ui/mock/signonui-request-mock.h 2014-10-09 12:24:45 +0000 |
2063 | +++ tests/online-accounts-ui/mock/signonui-request-mock.h 2015-01-16 17:10:14 +0000 |
2064 | @@ -39,10 +39,13 @@ |
2065 | ~RequestPrivate(); |
2066 | static RequestPrivate *mocked(Request *r) { return r->d_ptr; } |
2067 | |
2068 | + void setProviderId(const QString &id) { m_providerId = id; } |
2069 | + |
2070 | private: |
2071 | mutable Request *q_ptr; |
2072 | QVariantMap m_clientData; |
2073 | QPointer<RequestHandler> m_handler; |
2074 | + QString m_providerId; |
2075 | }; |
2076 | |
2077 | } // namespace |
2078 | |
2079 | === modified file 'tests/online-accounts-ui/tst_browser_request.cpp' |
2080 | --- tests/online-accounts-ui/tst_browser_request.cpp 2014-10-09 12:24:45 +0000 |
2081 | +++ tests/online-accounts-ui/tst_browser_request.cpp 2015-01-16 17:10:14 +0000 |
2082 | @@ -85,6 +85,7 @@ |
2083 | void BrowserRequestTest::testParametersWithHandler_data() |
2084 | { |
2085 | QTest::addColumn<QVariantMap>("parameters"); |
2086 | + QTest::addColumn<QString>("providerId"); |
2087 | QTest::addColumn<QString>("pageComponentUrl"); |
2088 | QTest::addColumn<QString>("startUrl"); |
2089 | QTest::addColumn<QString>("finalUrl"); |
2090 | @@ -95,10 +96,11 @@ |
2091 | |
2092 | QTest::newRow("empty") << |
2093 | QVariantMap() << |
2094 | + QString() << |
2095 | "DefaultPage.qml" << |
2096 | QString() << |
2097 | QString() << |
2098 | - baseCacheDir + "/id-0"; |
2099 | + baseCacheDir + "/id-0-"; |
2100 | |
2101 | QVariantMap parameters; |
2102 | QVariantMap clientData; |
2103 | @@ -107,10 +109,11 @@ |
2104 | parameters.insert(SSOUI_KEY_IDENTITY, uint(4)); |
2105 | QTest::newRow("with URLs and ID") << |
2106 | parameters << |
2107 | + "google" << |
2108 | "DefaultPage.qml" << |
2109 | "http://localhost/start.html" << |
2110 | "http://localhost/end.html" << |
2111 | - baseCacheDir + "/id-4"; |
2112 | + baseCacheDir + "/id-4-google"; |
2113 | parameters.clear(); |
2114 | |
2115 | clientData.insert("X-PageComponent", |
2116 | @@ -121,16 +124,18 @@ |
2117 | parameters.insert(SSOUI_KEY_IDENTITY, uint(4)); |
2118 | QTest::newRow("with page component") << |
2119 | parameters << |
2120 | + "com.ubuntu.app_plugin" << |
2121 | "file:///usr/share/signon-ui/MyPage.qml" << |
2122 | "http://localhost/start.html" << |
2123 | "http://localhost/end.html" << |
2124 | - baseCacheDir + "/id-4"; |
2125 | + baseCacheDir + "/id-4-com.ubuntu.app_plugin"; |
2126 | parameters.clear(); |
2127 | } |
2128 | |
2129 | void BrowserRequestTest::testParametersWithHandler() |
2130 | { |
2131 | QFETCH(QVariantMap, parameters); |
2132 | + QFETCH(QString, providerId); |
2133 | QFETCH(QString, pageComponentUrl); |
2134 | QFETCH(QString, startUrl); |
2135 | QFETCH(QString, finalUrl); |
2136 | @@ -140,6 +145,9 @@ |
2137 | QSignalSpy requestChanged(&handler, SIGNAL(requestChanged())); |
2138 | |
2139 | TestRequest request(parameters); |
2140 | + SignOnUi::RequestPrivate *mockedRequest = |
2141 | + SignOnUi::RequestPrivate::mocked(&request); |
2142 | + mockedRequest->setProviderId(providerId); |
2143 | request.setHandler(&handler); |
2144 | |
2145 | request.start(); |
2146 | |
2147 | === modified file 'tests/online-accounts-ui/tst_signonui_request.cpp' |
2148 | --- tests/online-accounts-ui/tst_signonui_request.cpp 2014-10-09 12:24:45 +0000 |
2149 | +++ tests/online-accounts-ui/tst_signonui_request.cpp 2015-01-16 17:10:14 +0000 |
2150 | @@ -20,7 +20,6 @@ |
2151 | |
2152 | #include "globals.h" |
2153 | #include "signonui-request.h" |
2154 | -#include "mock/notification-mock.h" |
2155 | #include "mock/request-mock.h" |
2156 | #include "mock/ui-server-mock.h" |
2157 | |
2158 | @@ -68,8 +67,6 @@ |
2159 | void testParameters_data(); |
2160 | void testParameters(); |
2161 | void testHandler(); |
2162 | - void testSnapDecision_data(); |
2163 | - void testSnapDecision(); |
2164 | |
2165 | private: |
2166 | bool mustCreateAccount(uint credentialsId) { return credentialsId > 10; } |
2167 | @@ -167,171 +164,6 @@ |
2168 | delete handler; |
2169 | } |
2170 | |
2171 | -void SignonuiRequestTest::testSnapDecision_data() |
2172 | -{ |
2173 | - QTest::addColumn<uint>("credentialsId"); |
2174 | - QTest::addColumn<QString>("accountName"); |
2175 | - QTest::addColumn<QString>("clientProfile"); |
2176 | - QTest::addColumn<QString>("applicationName"); |
2177 | - QTest::addColumn<bool>("mustAccept"); |
2178 | - QTest::addColumn<QVariantMap>("result"); |
2179 | - |
2180 | - QVariantMap acceptedResult; |
2181 | - acceptedResult.insert("some key", QString("some value")); |
2182 | - |
2183 | - QVariantMap declinedResult; |
2184 | - declinedResult.insert(SSOUI_KEY_ERROR, SignOn::QUERY_ERROR_CANCELED); |
2185 | - |
2186 | - QVariantMap errorResult; |
2187 | - errorResult.insert(SSOUI_KEY_ERROR, SignOn::QUERY_ERROR_FORBIDDEN); |
2188 | - |
2189 | - QTest::newRow("no account") << |
2190 | - uint(0) << |
2191 | - "tom@example.com" << |
2192 | - "com.ubuntu.tests_application_0.3" << |
2193 | - QString() << |
2194 | - false << |
2195 | - errorResult; |
2196 | - |
2197 | - QTest::newRow("invalid account") << |
2198 | - uint(1) << |
2199 | - "tom@example.com" << |
2200 | - "com.ubuntu.tests_application_0.3" << |
2201 | - QString() << |
2202 | - false << |
2203 | - errorResult; |
2204 | - |
2205 | - QTest::newRow("valid application, accepted") << |
2206 | - uint(14231) << |
2207 | - "tom@example.com" << |
2208 | - "com.ubuntu.tests_application_0.3" << |
2209 | - "Easy Mailer" << |
2210 | - true << |
2211 | - acceptedResult; |
2212 | - |
2213 | - QTest::newRow("valid application, declined") << |
2214 | - uint(14231) << |
2215 | - "tom@example.com" << |
2216 | - "com.ubuntu.tests_application_0.3" << |
2217 | - "Easy Mailer" << |
2218 | - false << |
2219 | - declinedResult; |
2220 | - |
2221 | - QTest::newRow("unconfined application, accepted") << |
2222 | - uint(14235) << |
2223 | - "tom@example.com" << |
2224 | - "unconfined" << |
2225 | - "Ubuntu" << |
2226 | - true << |
2227 | - acceptedResult; |
2228 | - |
2229 | - QTest::newRow("unconfined application, declined") << |
2230 | - uint(14235) << |
2231 | - "tom@example.com" << |
2232 | - "unconfined" << |
2233 | - "Ubuntu" << |
2234 | - false << |
2235 | - declinedResult; |
2236 | -} |
2237 | - |
2238 | -void SignonuiRequestTest::testSnapDecision() |
2239 | -{ |
2240 | - QString providerId("cool"); |
2241 | - QFETCH(uint, credentialsId); |
2242 | - QFETCH(QString, accountName); |
2243 | - QFETCH(QString, clientProfile); |
2244 | - QFETCH(QString, applicationName); |
2245 | - QFETCH(bool, mustAccept); |
2246 | - QFETCH(QVariantMap, result); |
2247 | - |
2248 | - // First, create an account |
2249 | - Accounts::Manager *manager = new Accounts::Manager(this); |
2250 | - Accounts::Provider provider = manager->provider(providerId); |
2251 | - QVERIFY(provider.isValid()); |
2252 | - if (mustCreateAccount(credentialsId)) { |
2253 | - Accounts::Account *account = manager->createAccount(providerId); |
2254 | - QVERIFY(account != 0); |
2255 | - account->setEnabled(true); |
2256 | - account->setDisplayName(accountName); |
2257 | - account->setCredentialsId(credentialsId); |
2258 | - account->syncAndBlock(); |
2259 | - } |
2260 | - |
2261 | - /* Then, create a request referring to the same credentials ID of the |
2262 | - * created account. */ |
2263 | - QVariantMap parameters; |
2264 | - parameters.insert(SSOUI_KEY_IDENTITY, credentialsId); |
2265 | - parameters.insert(SSOUI_KEY_METHOD, "funnyMethod"); |
2266 | - parameters.insert(SSOUI_KEY_MECHANISM, "funnyMechanism"); |
2267 | - TestRequest request(clientProfile, parameters); |
2268 | - OnlineAccountsUi::RequestPrivate *mockRequest = |
2269 | - OnlineAccountsUi::RequestPrivate::mocked(&request); |
2270 | - QSignalSpy failCalled(mockRequest, |
2271 | - SIGNAL(failCalled(const QString&, const QString&))); |
2272 | - QSignalSpy setResultCalled(mockRequest, |
2273 | - SIGNAL(setResultCalled(const QVariantMap &))); |
2274 | - request.start(); |
2275 | - |
2276 | - /* Request to show a window; a snap decision should appear instead */ |
2277 | - QWindow *window = new QWindow; |
2278 | - QSignalSpy setWindowCalled(mockRequest, |
2279 | - SIGNAL(setWindowCalled(QWindow*))); |
2280 | - request.setWindow(window); |
2281 | - QCOMPARE(setWindowCalled.count(), 0); |
2282 | - if (mustCreateAccount(credentialsId)) { |
2283 | - QCOMPARE(NotificationPrivate::allNotifications.count(), 1); |
2284 | - } else { |
2285 | - /* If the account is not found, no notification should appear, and an |
2286 | - * error returned to the app */ |
2287 | - QCOMPARE(NotificationPrivate::allNotifications.count(), 0); |
2288 | - QCOMPARE(setResultCalled.count(), 1); |
2289 | - QCOMPARE(setResultCalled.at(0).at(0).toMap(), result); |
2290 | - return; |
2291 | - } |
2292 | - |
2293 | - /* Inspect the snap decision contents */ |
2294 | - Notification *notification = |
2295 | - NotificationPrivate::allNotifications.first(); |
2296 | - NotificationPrivate *mockNotification = |
2297 | - NotificationPrivate::mocked(notification); |
2298 | - QCOMPARE(mockNotification->m_summary, QString("Authentication request")); |
2299 | - QCOMPARE(mockNotification->m_body, |
2300 | - QString("Please authorize %1 to access your %2 account %3"). |
2301 | - arg(applicationName).arg(provider.displayName()).arg(accountName)); |
2302 | - QVERIFY(mockNotification->m_isSnapDecision); |
2303 | - |
2304 | - /* Invoke the action on the snap decision */ |
2305 | - QString action = mustAccept ? "continue" : "cancel"; |
2306 | - QSignalSpy actionInvoked(notification, |
2307 | - SIGNAL(actionInvoked(const QString &))); |
2308 | - mockNotification->invokeAction(action); |
2309 | - QCOMPARE(actionInvoked.count(), 1); |
2310 | - QCOMPARE(actionInvoked.at(0).at(0).toString(), action); |
2311 | - |
2312 | - /* Here we iterate the main loop because the notification object is |
2313 | - * destroyed with deleteLater() */ |
2314 | - QTest::qWait(5); |
2315 | - |
2316 | - if (mustAccept) { |
2317 | - QCOMPARE(setWindowCalled.count(), 1); |
2318 | - QCOMPARE(setWindowCalled.at(0).at(0), QVariant::fromValue(window)); |
2319 | - QCOMPARE(failCalled.count(), 0); |
2320 | - QCOMPARE(setResultCalled.count(), 0); |
2321 | - |
2322 | - /* deliver the result */ |
2323 | - request.sendResult(result); |
2324 | - QCOMPARE(setResultCalled.count(), 1); |
2325 | - QCOMPARE(setResultCalled.at(0).at(0).toMap(), result); |
2326 | - } else { |
2327 | - QCOMPARE(setWindowCalled.count(), 0); |
2328 | - QCOMPARE(failCalled.count(), 0); |
2329 | - QCOMPARE(setResultCalled.count(), 1); |
2330 | - QCOMPARE(setResultCalled.at(0).at(0).toMap(), result); |
2331 | - } |
2332 | - delete window; |
2333 | - delete manager; |
2334 | -} |
2335 | - |
2336 | QTEST_MAIN(SignonuiRequestTest); |
2337 | |
2338 | #include "tst_signonui_request.moc" |
2339 | |
2340 | === modified file 'tests/online-accounts-ui/tst_signonui_request.pro' |
2341 | --- tests/online-accounts-ui/tst_signonui_request.pro 2014-10-14 11:19:19 +0000 |
2342 | +++ tests/online-accounts-ui/tst_signonui_request.pro 2015-01-16 17:10:14 +0000 |
2343 | @@ -27,18 +27,15 @@ |
2344 | SOURCES += \ |
2345 | $${ONLINE_ACCOUNTS_UI_DIR}/debug.cpp \ |
2346 | $${ONLINE_ACCOUNTS_UI_DIR}/signonui-request.cpp \ |
2347 | - mock/notification-mock.cpp \ |
2348 | mock/request-mock.cpp \ |
2349 | mock/qwindow.cpp \ |
2350 | mock/ui-server-mock.cpp \ |
2351 | tst_signonui_request.cpp |
2352 | |
2353 | HEADERS += \ |
2354 | - $${ONLINE_ACCOUNTS_UI_DIR}/notification.h \ |
2355 | $${ONLINE_ACCOUNTS_UI_DIR}/request.h \ |
2356 | $${ONLINE_ACCOUNTS_UI_DIR}/signonui-request.h \ |
2357 | $${ONLINE_ACCOUNTS_UI_DIR}/ui-server.h \ |
2358 | - mock/notification-mock.h \ |
2359 | mock/request-mock.h \ |
2360 | mock/ui-server-mock.h \ |
2361 | window-watcher.h |
PASSED: Continuous integration, rev:222 jenkins. qa.ubuntu. com/job/ ubuntu- system- settings- online- accounts- ci/191/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- vivid-touch/ 784 jenkins. qa.ubuntu. com/job/ ubuntu- system- settings- online- accounts- vivid-amd64- ci/13 jenkins. qa.ubuntu. com/job/ ubuntu- system- settings- online- accounts- vivid-i386- ci/11 jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- runner- vivid-mako/ 682 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 782 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 782/artifact/ work/output/ *zip*/output. zip s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 17031
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/ubuntu- system- settings- online- accounts- ci/191/ rebuild
http://