Merge lp:~mardy/online-accounts-api/providers-1627001 into lp:online-accounts-api

Proposed by Alberto Mardegan
Status: Merged
Approved by: Alberto Mardegan
Approved revision: 52
Merged at revision: 38
Proposed branch: lp:~mardy/online-accounts-api/providers-1627001
Merge into: lp:online-accounts-api
Diff against target: 1839 lines (+826/-80)
34 files modified
debian/control (+1/-1)
src/lib/OnlineAccounts/CMakeLists.txt (+2/-0)
src/lib/OnlineAccounts/Service (+1/-0)
src/lib/OnlineAccounts/account.cpp (+11/-0)
src/lib/OnlineAccounts/account.h (+3/-0)
src/lib/OnlineAccounts/account_p.h (+2/-0)
src/lib/OnlineAccounts/dbus_interface.cpp (+2/-0)
src/lib/OnlineAccounts/manager.cpp (+14/-1)
src/lib/OnlineAccounts/manager.h (+6/-1)
src/lib/OnlineAccounts/manager_p.h (+6/-0)
src/lib/OnlineAccounts/service.cpp (+54/-0)
src/lib/OnlineAccounts/service.h (+83/-0)
src/lib/OnlineAccountsDaemon/CMakeLists.txt (+1/-0)
src/lib/OnlineAccountsDaemon/com.ubuntu.OnlineAccounts.Manager.xml (+14/-0)
src/lib/OnlineAccountsDaemon/dbus_constants.h (+3/-0)
src/lib/OnlineAccountsDaemon/i18n.cpp (+34/-0)
src/lib/OnlineAccountsDaemon/i18n.h (+32/-0)
src/lib/OnlineAccountsDaemon/manager.cpp (+86/-10)
src/lib/OnlineAccountsDaemon/manager.h (+2/-1)
src/lib/OnlineAccountsDaemon/manager_adaptor.cpp (+7/-3)
src/lib/OnlineAccountsDaemon/manager_adaptor.h (+4/-1)
src/lib/Ubuntu/OnlineAccounts.2/account.cpp (+34/-4)
src/lib/Ubuntu/OnlineAccounts.2/account.h (+10/-1)
src/lib/Ubuntu/OnlineAccounts.2/account_model.cpp (+28/-1)
src/lib/Ubuntu/OnlineAccounts.2/account_model.h (+9/-0)
src/lib/Ubuntu/OnlineAccounts.2/plugin.cpp (+5/-0)
tests/daemon/functional_tests/data/com.ubuntu.tests_application.application (+4/-1)
tests/daemon/functional_tests/data/com.ubuntu.tests_coolshare.service (+1/-1)
tests/daemon/functional_tests/data/coolmail.service (+0/-1)
tests/daemon/functional_tests/data/missing-provider.service (+14/-0)
tests/daemon/functional_tests/functional_tests.cpp (+133/-10)
tests/daemon/functional_tests/test_process.py (+5/-2)
tests/lib/OnlineAccounts/functional_tests/functional_tests.cpp (+108/-22)
tests/lib/qml_module/tst_qml_module.cpp (+107/-19)
To merge this branch: bzr merge lp:~mardy/online-accounts-api/providers-1627001
Reviewer Review Type Date Requested Status
Alexandre Abreu (community) Approve
Review via email: mp+310060@code.launchpad.net

Commit message

Add provider information to public API

Allow clients to retrieve the list of available service providers, consisting of translated display name and icon URL.
Also, add a service() method to the Account class, to get the data associated with each account.

Description of the change

Add provider information to public API

Allow clients to retrieve the list of available service providers, consisting of translated display name and icon URL.
Also, add a service() method to the Account class, to get the data associated with each account.

To post a comment you must log in.
Revision history for this message
Michi Henning (michihenning) wrote :

I may be missing something here, but (not being familiar with the code), it looks like the translated service name is not present? We need the translated name of the service too (such as "Google" or "Dropbox", or their equivalents in Arabic script, or whatever).

35. By Alberto Mardegan

Bump dependency on libaccounts-qt

36. By Alberto Mardegan

Add missing files

37. By Alberto Mardegan

DOn't use qjsEngine() it doesn't exist in QT 5.4

Revision history for this message
Alberto Mardegan (mardy) wrote :

> I may be missing something here, but (not being familiar with the code), it
> looks like the translated service name is not present? We need the translated
> name of the service too (such as "Google" or "Dropbox", or their equivalents
> in Arabic script, or whatever).

It's there, line 549 of the diff. I'll soon prepare a test app to verify that everything is place, in case unit tests are not catching everything.

38. By Alberto Mardegan

more of the same

39. By Alberto Mardegan

Cast QList<QString> to QStringList

40. By Alberto Mardegan

Don't use Q_GADGET functionality in Qt < 5.5

41. By Alberto Mardegan

Fix typo

42. By Alberto Mardegan

type conv for qt 5.4

43. By Alberto Mardegan

fix

44. By Alberto Mardegan

skip test

45. By Alberto Mardegan

fix

46. By Alberto Mardegan

Fallback to provider's icon and display name

47. By Alberto Mardegan

test debugging

48. By Alberto Mardegan

fix test

49. By Alberto Mardegan

remove debugging

50. By Alberto Mardegan

Don't crash if serviceList property is retrieved when the model is not ready

With this fix, we also need a signal to inform the QML engine of when the
property becomes available

51. By Alberto Mardegan

Skip missing providers

52. By Alberto Mardegan

Expose enums to QML

Revision history for this message
Alberto Mardegan (mardy) wrote :

This is implemented and available for testing here: https://bileto.ubuntu.com/#/ticket/2016

See the "Test plan" in that silo for a quick way to test it.

Revision history for this message
Alexandre Abreu (abreu-alexandre) wrote :

LGTM

one inlined question

review: Approve
53. By Alberto Mardegan

Remove commented line

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/control'
--- debian/control 2016-10-03 07:46:50 +0000
+++ debian/control 2016-11-10 09:12:06 +0000
@@ -6,7 +6,7 @@
6 debhelper (>= 9),6 debhelper (>= 9),
7 pkg-config,7 pkg-config,
8 python3:any,8 python3:any,
9 libaccounts-qt5-dev,9 libaccounts-qt5-dev (>= 1.15),
10 libapparmor-dev,10 libapparmor-dev,
11 libonline-accounts-client-dev (>= 0.7),11 libonline-accounts-client-dev (>= 0.7),
12 libqtdbusmock1-dev,12 libqtdbusmock1-dev,
1313
=== modified file 'src/lib/OnlineAccounts/CMakeLists.txt'
--- src/lib/OnlineAccounts/CMakeLists.txt 2016-11-01 09:48:22 +0000
+++ src/lib/OnlineAccounts/CMakeLists.txt 2016-11-10 09:12:06 +0000
@@ -22,6 +22,7 @@
22 manager.cpp22 manager.cpp
23 pending_call.cpp23 pending_call.cpp
24 request_access_reply.cpp24 request_access_reply.cpp
25 service.cpp
25)26)
26set_target_properties(${CLIENT_LIB} PROPERTIES27set_target_properties(${CLIENT_LIB} PROPERTIES
27 VERSION 1.0.028 VERSION 1.0.0
@@ -52,5 +53,6 @@
52 PasswordData53 PasswordData
53 PendingCall pending_call.h54 PendingCall pending_call.h
54 PendingCallWatcher55 PendingCallWatcher
56 Service service.h
55 DESTINATION include/${CLIENT_LIB}/OnlineAccounts57 DESTINATION include/${CLIENT_LIB}/OnlineAccounts
56)58)
5759
=== added file 'src/lib/OnlineAccounts/Service'
--- src/lib/OnlineAccounts/Service 1970-01-01 00:00:00 +0000
+++ src/lib/OnlineAccounts/Service 2016-11-10 09:12:06 +0000
@@ -0,0 +1,1 @@
1#include "service.h"
02
=== modified file 'src/lib/OnlineAccounts/account.cpp'
--- src/lib/OnlineAccounts/account.cpp 2015-08-26 13:32:38 +0000
+++ src/lib/OnlineAccounts/account.cpp 2016-11-10 09:12:06 +0000
@@ -53,6 +53,11 @@
53 }53 }
54}54}
5555
56Service AccountPrivate::service() const
57{
58 return m_manager->d_ptr->service(m_info.service());
59}
60
56Account::Account(AccountPrivate *priv, QObject *parent):61Account::Account(AccountPrivate *priv, QObject *parent):
57 QObject(parent),62 QObject(parent),
58 d_ptr(priv)63 d_ptr(priv)
@@ -72,6 +77,12 @@
72 return d->m_isValid;77 return d->m_isValid;
73}78}
7479
80Service Account::service() const
81{
82 Q_D(const Account);
83 return d->service();
84}
85
75AccountId Account::id() const86AccountId Account::id() const
76{87{
77 Q_D(const Account);88 Q_D(const Account);
7889
=== modified file 'src/lib/OnlineAccounts/account.h'
--- src/lib/OnlineAccounts/account.h 2015-08-26 13:32:38 +0000
+++ src/lib/OnlineAccounts/account.h 2016-11-10 09:12:06 +0000
@@ -26,6 +26,7 @@
2626
27#include "global.h"27#include "global.h"
28#include "pending_call.h"28#include "pending_call.h"
29#include "service.h"
2930
30namespace OnlineAccounts {31namespace OnlineAccounts {
3132
@@ -43,6 +44,8 @@
43 /* Returns false if account deleted or disabled */44 /* Returns false if account deleted or disabled */
44 bool isValid() const;45 bool isValid() const;
4546
47 Service service() const;
48
46 AccountId id() const;49 AccountId id() const;
47 QString displayName() const;50 QString displayName() const;
48 QString serviceId() const;51 QString serviceId() const;
4952
=== modified file 'src/lib/OnlineAccounts/account_p.h'
--- src/lib/OnlineAccounts/account_p.h 2015-03-04 10:01:32 +0000
+++ src/lib/OnlineAccounts/account_p.h 2016-11-10 09:12:06 +0000
@@ -37,6 +37,8 @@
37 void setInvalid();37 void setInvalid();
38 void update(const AccountInfo &info);38 void update(const AccountInfo &info);
3939
40 Service service() const;
41
40private:42private:
41 Manager *m_manager;43 Manager *m_manager;
42 AccountInfo m_info;44 AccountInfo m_info;
4345
=== modified file 'src/lib/OnlineAccounts/dbus_interface.cpp'
--- src/lib/OnlineAccounts/dbus_interface.cpp 2015-03-03 07:09:50 +0000
+++ src/lib/OnlineAccounts/dbus_interface.cpp 2016-11-10 09:12:06 +0000
@@ -22,6 +22,7 @@
2222
23#include <QDBusMetaType>23#include <QDBusMetaType>
24#include <QDebug>24#include <QDebug>
25#include <QVariantMap>
25#include <climits>26#include <climits>
2627
27using namespace OnlineAccounts;28using namespace OnlineAccounts;
@@ -37,6 +38,7 @@
3738
38 qDBusRegisterMetaType<AccountInfo>();39 qDBusRegisterMetaType<AccountInfo>();
39 qDBusRegisterMetaType<QList<AccountInfo>>();40 qDBusRegisterMetaType<QList<AccountInfo>>();
41 qDBusRegisterMetaType<QList<QVariantMap>>();
4042
41 bool ok = connect("AccountChanged", "s(ua{sv})",43 bool ok = connect("AccountChanged", "s(ua{sv})",
42 this, SLOT(onAccountChanged(const QString&,const OnlineAccounts::AccountInfo&)));44 this, SLOT(onAccountChanged(const QString&,const OnlineAccounts::AccountInfo&)));
4345
=== modified file 'src/lib/OnlineAccounts/manager.cpp'
--- src/lib/OnlineAccounts/manager.cpp 2016-11-01 09:48:22 +0000
+++ src/lib/OnlineAccounts/manager.cpp 2016-11-10 09:12:06 +0000
@@ -45,6 +45,7 @@
45 q_ptr(q)45 q_ptr(q)
46{46{
47 qRegisterMetaType<Account*>();47 qRegisterMetaType<Account*>();
48 qRegisterMetaType<Service>("OnlineAccounts::Service");
4849
49 QObject::connect(&m_daemon,50 QObject::connect(&m_daemon,
50 SIGNAL(accountChanged(const QString&, const OnlineAccounts::AccountInfo&)),51 SIGNAL(accountChanged(const QString&, const OnlineAccounts::AccountInfo&)),
@@ -125,7 +126,7 @@
125126
126 Q_ASSERT(m_getAccountsCall);127 Q_ASSERT(m_getAccountsCall);
127128
128 QDBusPendingReply<QList<AccountInfo> > reply = *m_getAccountsCall;129 QDBusPendingReply<QList<AccountInfo>,QList<QVariantMap>> reply = *m_getAccountsCall;
129 if (Q_UNLIKELY(reply.isError())) {130 if (Q_UNLIKELY(reply.isError())) {
130 qCWarning(DBG_ONLINE_ACCOUNTS) << "GetAccounts call failed:" <<131 qCWarning(DBG_ONLINE_ACCOUNTS) << "GetAccounts call failed:" <<
131 reply.error();132 reply.error();
@@ -136,6 +137,12 @@
136 Q_FOREACH(const AccountInfo &info, accountInfos) {137 Q_FOREACH(const AccountInfo &info, accountInfos) {
137 m_accounts.insert({info.id(), info.service()}, AccountData(info));138 m_accounts.insert({info.id(), info.service()}, AccountData(info));
138 }139 }
140
141 QList<QVariantMap> services = reply.argumentAt<1>();
142 for (const QVariantMap &data: services) {
143 Service service(new Service::ServiceData(data));
144 m_services.insert(service.id(), service);
145 }
139 }146 }
140 m_getAccountsCall->deleteLater();147 m_getAccountsCall->deleteLater();
141 m_getAccountsCall = 0;148 m_getAccountsCall = 0;
@@ -197,6 +204,12 @@
197 }204 }
198}205}
199206
207QList<Service> Manager::availableServices() const
208{
209 Q_D(const Manager);
210 return d->m_services.values();
211}
212
200QList<Account*> Manager::availableAccounts(const QString &service)213QList<Account*> Manager::availableAccounts(const QString &service)
201{214{
202 Q_D(Manager);215 Q_D(Manager);
203216
=== modified file 'src/lib/OnlineAccounts/manager.h'
--- src/lib/OnlineAccounts/manager.h 2016-07-22 05:08:06 +0000
+++ src/lib/OnlineAccounts/manager.h 2016-11-10 09:12:06 +0000
@@ -27,12 +27,14 @@
27#include "error.h"27#include "error.h"
28#include "global.h"28#include "global.h"
29#include "pending_call.h"29#include "pending_call.h"
30#include "service.h"
3031
31class QDBusConnection;32class QDBusConnection;
3233
33namespace OnlineAccounts {34namespace OnlineAccounts {
3435
35class Account;36class Account;
37class AccountPrivate;
36class AuthenticationData;38class AuthenticationData;
37class RequestAccessReplyPrivate;39class RequestAccessReplyPrivate;
3840
@@ -44,12 +46,14 @@
44public:46public:
45 explicit Manager(const QString &applicationId, QObject *parent = 0);47 explicit Manager(const QString &applicationId, QObject *parent = 0);
46 Manager(const QString &applicationId, const QDBusConnection &bus,48 Manager(const QString &applicationId, const QDBusConnection &bus,
47 QObject *parent = 0); 49 QObject *parent = 0);
48 ~Manager();50 ~Manager();
4951
50 bool isReady() const;52 bool isReady() const;
51 void waitForReady();53 void waitForReady();
5254
55 QList<Service> availableServices() const;
56
53 QList<Account*> availableAccounts(const QString &service = QString());57 QList<Account*> availableAccounts(const QString &service = QString());
54 Account *account(AccountId accountId);58 Account *account(AccountId accountId);
55 Account *account(AccountId accountId, const QString &service);59 Account *account(AccountId accountId, const QString &service);
@@ -63,6 +67,7 @@
6367
64private:68private:
65 friend class Account;69 friend class Account;
70 friend class AccountPrivate;
66 friend class RequestAccessReplyPrivate;71 friend class RequestAccessReplyPrivate;
67 Q_DECLARE_PRIVATE(Manager)72 Q_DECLARE_PRIVATE(Manager)
68 Q_DISABLE_COPY(Manager)73 Q_DISABLE_COPY(Manager)
6974
=== modified file 'src/lib/OnlineAccounts/manager_p.h'
--- src/lib/OnlineAccounts/manager_p.h 2016-07-22 05:08:06 +0000
+++ src/lib/OnlineAccounts/manager_p.h 2016-11-10 09:12:06 +0000
@@ -58,6 +58,11 @@
5858
59 Account *ensureAccount(const AccountInfo &info);59 Account *ensureAccount(const AccountInfo &info);
6060
61 static Service serviceFromMap(const QVariantMap &map);
62 Service service(const QString &serviceId) {
63 return m_services.value(serviceId);
64 }
65
61private:66private:
62 void retrieveAccounts();67 void retrieveAccounts();
6368
@@ -71,6 +76,7 @@
71 DBusInterface m_daemon;76 DBusInterface m_daemon;
72 QDBusPendingCallWatcher *m_getAccountsCall;77 QDBusPendingCallWatcher *m_getAccountsCall;
73 QMap<QPair<AccountId,QString>,AccountData> m_accounts;78 QMap<QPair<AccountId,QString>,AccountData> m_accounts;
79 QMap<QString,Service> m_services;
74 mutable Manager *q_ptr;80 mutable Manager *q_ptr;
75};81};
7682
7783
=== added file 'src/lib/OnlineAccounts/service.cpp'
--- src/lib/OnlineAccounts/service.cpp 1970-01-01 00:00:00 +0000
+++ src/lib/OnlineAccounts/service.cpp 2016-11-10 09:12:06 +0000
@@ -0,0 +1,54 @@
1/*
2 * This file is part of libOnlineAccounts
3 *
4 * Copyright (C) 2016 Canonical Ltd.
5 *
6 * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License version 3, as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranties of
14 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include "service.h"
22
23#include <QVariantMap>
24#include "OnlineAccountsDaemon/dbus_constants.h"
25
26using namespace OnlineAccounts;
27
28Service::ServiceData::ServiceData(const QVariantMap &map):
29 m_id(map.value(ONLINE_ACCOUNTS_INFO_KEY_SERVICE_ID).toString()),
30 m_displayName(map.value(ONLINE_ACCOUNTS_INFO_KEY_DISPLAY_NAME).toString()),
31 m_iconSource(map.value(ONLINE_ACCOUNTS_INFO_KEY_ICON_SOURCE).toString())
32{
33}
34
35Service::Service():
36 d(new ServiceData(QVariantMap()))
37{
38}
39
40Service::Service(const QVariantMap &map):
41 d(new ServiceData(map))
42{
43}
44
45#if QT_VERSION < QT_VERSION_CHECK(5, 5, 0)
46QVariantMap Service::toMap() const
47{
48 return QVariantMap {
49 { "serviceId", id() },
50 { "displayName", displayName() },
51 { "iconSource", iconSource() },
52 };
53}
54#endif
055
=== added file 'src/lib/OnlineAccounts/service.h'
--- src/lib/OnlineAccounts/service.h 1970-01-01 00:00:00 +0000
+++ src/lib/OnlineAccounts/service.h 2016-11-10 09:12:06 +0000
@@ -0,0 +1,83 @@
1/*
2 * This file is part of libOnlineAccounts
3 *
4 * Copyright (C) 2016 Canonical Ltd.
5 *
6 * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License version 3, as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranties of
14 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#ifndef ONLINE_ACCOUNTS_SERVICE_H
22#define ONLINE_ACCOUNTS_SERVICE_H
23
24#include <QObject>
25#include <QSharedData>
26#include <QSharedDataPointer>
27#include <QUrl>
28#include <QVariantMap>
29
30#include "global.h"
31
32namespace OnlineAccounts {
33
34class Manager;
35class ManagerPrivate;
36
37class ONLINE_ACCOUNTS_EXPORT Service
38{
39 Q_GADGET
40 Q_PROPERTY(QString serviceId READ id CONSTANT)
41 Q_PROPERTY(QString displayName READ displayName CONSTANT)
42 Q_PROPERTY(QUrl iconSource READ iconSource CONSTANT)
43
44private:
45 class ServiceData: public QSharedData {
46 ServiceData(const QVariantMap &map);
47 friend class ManagerPrivate;
48 friend class Service;
49 QString m_id;
50 QString m_displayName;
51 QUrl m_iconSource;
52 };
53
54public:
55 Service();
56 ~Service() {}
57
58 Service(const Service &other): d(other.d) {}
59
60 bool isValid() const { return !d->m_id.isEmpty(); }
61 QString id() const { return d->m_id; }
62 QString displayName() const { return d->m_displayName; }
63 QUrl iconSource() const { return d->m_iconSource; }
64
65#if QT_VERSION < QT_VERSION_CHECK(5, 5, 0)
66 QVariantMap toMap() const;
67#endif
68
69protected:
70 Service(const QVariantMap &map);
71
72private:
73 friend class Manager;
74 friend class ManagerPrivate;
75 Service(ServiceData *d): d(d) {};
76 QSharedDataPointer<ServiceData> d;
77};
78
79} // namespace
80
81Q_DECLARE_METATYPE(OnlineAccounts::Service)
82
83#endif // ONLINE_ACCOUNTS_SERVICE_H
084
=== modified file 'src/lib/OnlineAccountsDaemon/CMakeLists.txt'
--- src/lib/OnlineAccountsDaemon/CMakeLists.txt 2015-09-04 08:32:00 +0000
+++ src/lib/OnlineAccountsDaemon/CMakeLists.txt 2016-11-10 09:12:06 +0000
@@ -23,6 +23,7 @@
23 authentication_request.cpp23 authentication_request.cpp
24 authenticator.cpp24 authenticator.cpp
25 client_registry.cpp25 client_registry.cpp
26 i18n.cpp
26 manager.cpp27 manager.cpp
27 manager_adaptor.cpp28 manager_adaptor.cpp
28 state_saver.cpp29 state_saver.cpp
2930
=== modified file 'src/lib/OnlineAccountsDaemon/com.ubuntu.OnlineAccounts.Manager.xml'
--- src/lib/OnlineAccountsDaemon/com.ubuntu.OnlineAccounts.Manager.xml 2015-08-28 14:25:23 +0000
+++ src/lib/OnlineAccountsDaemon/com.ubuntu.OnlineAccounts.Manager.xml 2016-11-10 09:12:06 +0000
@@ -49,6 +49,7 @@
49 -->49 -->
50 <method name="GetAccounts">50 <method name="GetAccounts">
51 <arg name="filters" type="a{sv}" direction="in" />51 <arg name="filters" type="a{sv}" direction="in" />
52
52 <!--53 <!--
53 The return value is a list of account IDs paired with a dictionary of account data.54 The return value is a list of account IDs paired with a dictionary of account data.
54 This will always include:55 This will always include:
@@ -61,9 +62,22 @@
61 the framework level.62 the framework level.
62 -->63 -->
63 <arg name="accounts" type="a(ua{sv})" direction="out" />64 <arg name="accounts" type="a(ua{sv})" direction="out" />
65
66 <!--
67 The returned "services" is a list of dictionaries of the services' data.
68 This will always include:
69 - "serviceId" (s)
70 - "displayName" (s): the translated display name
71 - "iconSource" (s): URL to the service icon; if the URL starts with
72 "image://theme/", then what follows is the symbolic icon name
73 -->
74 <arg name="services" type="aa{sv}" direction="out" />
75
64 <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>76 <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
65 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0"77 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0"
66 value="QList&lt;AccountInfo&gt;"/>78 value="QList&lt;AccountInfo&gt;"/>
79 <annotation name="org.qtproject.QtDBus.QtTypeName.Out1"
80 value="QList&lt;QVariantMap&gt;"/>
67 </method>81 </method>
6882
69 <!--83 <!--
7084
=== modified file 'src/lib/OnlineAccountsDaemon/dbus_constants.h'
--- src/lib/OnlineAccountsDaemon/dbus_constants.h 2016-02-11 09:00:13 +0000
+++ src/lib/OnlineAccountsDaemon/dbus_constants.h 2016-11-10 09:12:06 +0000
@@ -42,6 +42,9 @@
42# define ONLINE_ACCOUNTS_INFO_CHANGE_DISABLED 142# define ONLINE_ACCOUNTS_INFO_CHANGE_DISABLED 1
43# define ONLINE_ACCOUNTS_INFO_CHANGE_UPDATED 243# define ONLINE_ACCOUNTS_INFO_CHANGE_UPDATED 2
4444
45/* Keys for the service info dictionary */
46#define ONLINE_ACCOUNTS_INFO_KEY_ICON_SOURCE "iconSource"
47
45/* Error codes */48/* Error codes */
46#define ONLINE_ACCOUNTS_ERROR_PREFIX "com.ubuntu.OnlineAccounts.Error."49#define ONLINE_ACCOUNTS_ERROR_PREFIX "com.ubuntu.OnlineAccounts.Error."
47#define ONLINE_ACCOUNTS_ERROR_NO_ACCOUNT \50#define ONLINE_ACCOUNTS_ERROR_NO_ACCOUNT \
4851
=== added file 'src/lib/OnlineAccountsDaemon/i18n.cpp'
--- src/lib/OnlineAccountsDaemon/i18n.cpp 1970-01-01 00:00:00 +0000
+++ src/lib/OnlineAccountsDaemon/i18n.cpp 2016-11-10 09:12:06 +0000
@@ -0,0 +1,34 @@
1/*
2 * This file is part of OnlineAccountsDaemon
3 *
4 * Copyright (C) 2016 Canonical Ltd.
5 *
6 * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License version 3, as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranties of
14 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#define NO_TR_OVERRIDE
22#include "i18n.h"
23
24#include <libintl.h>
25
26namespace OnlineAccountsDaemon {
27
28QString translate(const QString &text, const QString &domain)
29{
30 return QString::fromUtf8(dgettext(domain.toUtf8().constData(),
31 text.toUtf8().constData()));
32}
33
34}; // namespace
035
=== added file 'src/lib/OnlineAccountsDaemon/i18n.h'
--- src/lib/OnlineAccountsDaemon/i18n.h 1970-01-01 00:00:00 +0000
+++ src/lib/OnlineAccountsDaemon/i18n.h 2016-11-10 09:12:06 +0000
@@ -0,0 +1,32 @@
1/*
2 * This file is part of OnlineAccountsDaemon
3 *
4 * Copyright (C) 2016 Canonical Ltd.
5 *
6 * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License version 3, as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranties of
14 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#ifndef ONLINE_ACCOUNTS_DAEMON_I18N_H
22#define ONLINE_ACCOUNTS_DAEMON_I18N_H
23
24#include <QString>
25
26namespace OnlineAccountsDaemon {
27
28QString translate(const QString &text, const QString &domain);
29
30} // namespace
31
32#endif // ONLINE_ACCOUNTS_DAEMON_I18N_H
033
=== modified file 'src/lib/OnlineAccountsDaemon/manager.cpp'
--- src/lib/OnlineAccountsDaemon/manager.cpp 2016-09-28 13:09:06 +0000
+++ src/lib/OnlineAccountsDaemon/manager.cpp 2016-11-10 09:12:06 +0000
@@ -36,6 +36,7 @@
36#include "authenticator.h"36#include "authenticator.h"
37#include "client_registry.h"37#include "client_registry.h"
38#include "dbus_constants.h"38#include "dbus_constants.h"
39#include "i18n.h"
39#include "manager_adaptor.h"40#include "manager_adaptor.h"
40#include "state_saver.h"41#include "state_saver.h"
4142
@@ -78,8 +79,10 @@
78 const QStringList &clients);79 const QStringList &clients);
7980
80 AccountInfo readAccountInfo(const Accounts::AccountService *as);81 AccountInfo readAccountInfo(const Accounts::AccountService *as);
82 QList<QVariantMap> buildServiceList(const Accounts::Application &app) const;
81 QList<AccountInfo> getAccounts(const QVariantMap &filters,83 QList<AccountInfo> getAccounts(const QVariantMap &filters,
82 const CallContext &context);84 const CallContext &context,
85 QList<QVariantMap> &services);
83 void authenticate(uint accountId, const QString &serviceId,86 void authenticate(uint accountId, const QString &serviceId,
84 bool interactive, bool invalidate,87 bool interactive, bool invalidate,
85 const QVariantMap &parameters,88 const QVariantMap &parameters,
@@ -89,6 +92,8 @@
89 const CallContext &context);92 const CallContext &context);
90 bool canAccess(const QString &context, const QString &serviceId);93 bool canAccess(const QString &context, const QString &serviceId);
9194
95 static QString applicationIdFromLabel(const QString &label);
96
92 void notifyAccountChange(const ActiveAccount &account, uint change);97 void notifyAccountChange(const ActiveAccount &account, uint change);
9398
94private Q_SLOTS:99private Q_SLOTS:
@@ -344,22 +349,82 @@
344 return AccountInfo(as->account()->id(), info);349 return AccountInfo(as->account()->id(), info);
345}350}
346351
352QList<QVariantMap>
353ManagerPrivate::buildServiceList(const Accounts::Application &app) const
354{
355 QList<QVariantMap> services;
356
357 const auto serviceList = m_manager.serviceList(app);
358 for (const Accounts::Service &service: serviceList) {
359 QString displayName = translate(service.displayName(),
360 service.trCatalog());
361 QString icon = service.iconName();
362
363 /* Applications might declare support for a service while the provider
364 * (and account plugin) for that account is not installed. We probably
365 * don't want to include these services in the list, as it would lead
366 * to empty/invalid UI elements. */
367 Accounts::Provider provider = m_manager.provider(service.provider());
368 if (!provider.isValid()) continue;
369
370 /* Now check the service data; if either display name or icon are
371 * empty, fetch this information from the provider file, as a fallback
372 */
373 if (displayName.isEmpty() ||
374 // sometimes we use a '.' as display name placeholder
375 displayName == ".") {
376 displayName = translate(provider.displayName(),
377 provider.trCatalog());
378 }
379 if (icon.isEmpty()) {
380 icon = provider.iconName();
381 }
382
383 QString iconSource;
384 if (icon.startsWith('/')) {
385 iconSource = QStringLiteral("file:/") + icon;
386 } else {
387 iconSource = QStringLiteral("image://theme/") + icon;
388 }
389
390 services.append({
391 { ONLINE_ACCOUNTS_INFO_KEY_SERVICE_ID, service.name() },
392 { ONLINE_ACCOUNTS_INFO_KEY_DISPLAY_NAME, displayName },
393 { ONLINE_ACCOUNTS_INFO_KEY_ICON_SOURCE, iconSource },
394 });
395 }
396
397 return services;
398}
399
347QList<AccountInfo> ManagerPrivate::getAccounts(const QVariantMap &filters,400QList<AccountInfo> ManagerPrivate::getAccounts(const QVariantMap &filters,
348 const CallContext &context)401 const CallContext &context,
402 QList<QVariantMap> &services)
349{403{
350 QString desiredApplicationId = filters.value("applicationId").toString();404 QString desiredApplicationId = filters.value("applicationId").toString();
351 QString desiredServiceId = filters.value("serviceId").toString();405 QString desiredServiceId = filters.value("serviceId").toString();
352 Accounts::AccountId desiredAccountId = filters.value("accountId").toUInt();406 Accounts::AccountId desiredAccountId = filters.value("accountId").toUInt();
353407
354 Accounts::Application application = desiredApplicationId.isEmpty() ?408 QString applicationId = desiredApplicationId.isEmpty() ?
355 Accounts::Application() : m_manager.application(desiredApplicationId);409 applicationIdFromLabel(context.securityContext()) : desiredApplicationId;
356410
357 if (application.isValid() &&411 Accounts::Application application = m_manager.application(applicationId);
358 canAccess(context.securityContext(), desiredApplicationId)) {412
413 QList<AccountInfo> accounts;
414
415 if (!application.isValid() ||
416 !canAccess(context.securityContext(), applicationId)) {
417 if (!desiredApplicationId.isEmpty()) {
418 context.sendError(ONLINE_ACCOUNTS_ERROR_PERMISSION_DENIED,
419 QString("App '%1' cannot act as '%2'").
420 arg(applicationId).arg(desiredApplicationId));
421 return accounts;
422 }
423 } else {
359 m_clients.insert(context.clientName(), application);424 m_clients.insert(context.clientName(), application);
360 }425 }
361426
362 QList<AccountInfo> accounts;427 services = buildServiceList(application);
363428
364 Q_FOREACH(Accounts::AccountId accountId, m_manager.accountListEnabled()) {429 Q_FOREACH(Accounts::AccountId accountId, m_manager.accountListEnabled()) {
365 if (desiredAccountId != 0 && accountId != desiredAccountId) {430 if (desiredAccountId != 0 && accountId != desiredAccountId) {
@@ -473,6 +538,16 @@
473 return serviceId.left(pos) == pkgname;538 return serviceId.left(pos) == pkgname;
474}539}
475540
541QString ManagerPrivate::applicationIdFromLabel(const QString &label)
542{
543 QStringList parts = label.split('_');
544 if (parts.count() == 3) {
545 return QStringList(parts.mid(0, 2)).join('_');
546 } else {
547 return QString();
548 }
549}
550
476void ManagerPrivate::onAccountServiceEnabled(bool enabled)551void ManagerPrivate::onAccountServiceEnabled(bool enabled)
477{552{
478 auto as = qobject_cast<Accounts::AccountService*>(sender());553 auto as = qobject_cast<Accounts::AccountService*>(sender());
@@ -553,10 +628,11 @@
553}628}
554629
555QList<AccountInfo> Manager::getAccounts(const QVariantMap &filters,630QList<AccountInfo> Manager::getAccounts(const QVariantMap &filters,
556 const CallContext &context)631 const CallContext &context,
632 QList<QVariantMap> &services)
557{633{
558 Q_D(Manager);634 Q_D(Manager);
559 return d->getAccounts(filters, context);635 return d->getAccounts(filters, context, services);
560}636}
561637
562void Manager::authenticate(uint accountId, const QString &serviceId,638void Manager::authenticate(uint accountId, const QString &serviceId,
563639
=== modified file 'src/lib/OnlineAccountsDaemon/manager.h'
--- src/lib/OnlineAccountsDaemon/manager.h 2015-09-03 13:28:30 +0000
+++ src/lib/OnlineAccountsDaemon/manager.h 2016-11-10 09:12:06 +0000
@@ -52,7 +52,8 @@
52 bool isIdle() const;52 bool isIdle() const;
5353
54 QList<AccountInfo> getAccounts(const QVariantMap &filters,54 QList<AccountInfo> getAccounts(const QVariantMap &filters,
55 const CallContext &context);55 const CallContext &context,
56 QList<QVariantMap> &services);
56 void authenticate(uint accountId, const QString &serviceId,57 void authenticate(uint accountId, const QString &serviceId,
57 bool interactive, bool invalidate,58 bool interactive, bool invalidate,
58 const QVariantMap &parameters,59 const QVariantMap &parameters,
5960
=== modified file 'src/lib/OnlineAccountsDaemon/manager_adaptor.cpp'
--- src/lib/OnlineAccountsDaemon/manager_adaptor.cpp 2015-08-28 14:25:23 +0000
+++ src/lib/OnlineAccountsDaemon/manager_adaptor.cpp 2016-11-10 09:12:06 +0000
@@ -147,6 +147,7 @@
147 qRegisterMetaType<QList<AccountInfo> >("QList<AccountInfo>");147 qRegisterMetaType<QList<AccountInfo> >("QList<AccountInfo>");
148 qDBusRegisterMetaType<AccountInfo>();148 qDBusRegisterMetaType<AccountInfo>();
149 qDBusRegisterMetaType<QList<AccountInfo>>();149 qDBusRegisterMetaType<QList<AccountInfo>>();
150 qDBusRegisterMetaType<QList<QVariantMap>>();
150151
151 setAutoRelaySignals(false);152 setAutoRelaySignals(false);
152}153}
@@ -175,10 +176,13 @@
175 return QVariantMap();176 return QVariantMap();
176}177}
177178
178QList<AccountInfo> ManagerAdaptor::GetAccounts(const QVariantMap &filters)179void ManagerAdaptor::GetAccounts(const QVariantMap &filters,
180 QList<AccountInfo> &accounts,
181 QList<QVariantMap> &services)
179{182{
180 return parent()->getAccounts(filters,183 accounts = parent()->getAccounts(filters,
181 CallContext(dbusContext()));184 CallContext(dbusContext()),
185 services);
182}186}
183187
184AccountInfo ManagerAdaptor::RequestAccess(const QString &serviceId,188AccountInfo ManagerAdaptor::RequestAccess(const QString &serviceId,
185189
=== modified file 'src/lib/OnlineAccountsDaemon/manager_adaptor.h'
--- src/lib/OnlineAccountsDaemon/manager_adaptor.h 2015-09-02 11:42:04 +0000
+++ src/lib/OnlineAccountsDaemon/manager_adaptor.h 2016-11-10 09:12:06 +0000
@@ -85,6 +85,7 @@
85" <method name=\"GetAccounts\">\n"85" <method name=\"GetAccounts\">\n"
86" <arg direction=\"in\" type=\"a{sv}\" name=\"filters\"/>\n"86" <arg direction=\"in\" type=\"a{sv}\" name=\"filters\"/>\n"
87" <arg direction=\"out\" type=\"a(ua{sv})\" name=\"accounts\"/>\n"87" <arg direction=\"out\" type=\"a(ua{sv})\" name=\"accounts\"/>\n"
88" <arg direction=\"out\" type=\"aa{sv}\" name=\"services\"/>\n"
88" </method>\n"89" </method>\n"
89" <method name=\"Authenticate\">\n"90" <method name=\"Authenticate\">\n"
90" <arg direction=\"in\" type=\"u\" name=\"accountId\"/>\n"91" <arg direction=\"in\" type=\"u\" name=\"accountId\"/>\n"
@@ -123,7 +124,9 @@
123 QVariantMap Authenticate(uint accountId, const QString &serviceId,124 QVariantMap Authenticate(uint accountId, const QString &serviceId,
124 bool interactive, bool invalidate,125 bool interactive, bool invalidate,
125 const QVariantMap &parameters);126 const QVariantMap &parameters);
126 QList<AccountInfo> GetAccounts(const QVariantMap &filters);127 void GetAccounts(const QVariantMap &filters,
128 QList<AccountInfo> &accounts,
129 QList<QVariantMap> &services);
127 AccountInfo RequestAccess(const QString &serviceId,130 AccountInfo RequestAccess(const QString &serviceId,
128 const QVariantMap &parameters,131 const QVariantMap &parameters,
129 QVariantMap &credentials);132 QVariantMap &credentials);
130133
=== modified file 'src/lib/Ubuntu/OnlineAccounts.2/account.cpp'
--- src/lib/Ubuntu/OnlineAccounts.2/account.cpp 2016-01-13 14:23:12 +0000
+++ src/lib/Ubuntu/OnlineAccounts.2/account.cpp 2016-11-10 09:12:06 +0000
@@ -26,6 +26,9 @@
26#include "OnlineAccounts/AuthenticationReply"26#include "OnlineAccounts/AuthenticationReply"
27#include "OnlineAccounts/PendingCall"27#include "OnlineAccounts/PendingCall"
2828
29#include <QDebug>
30#include <QJSEngine>
31
29using namespace OnlineAccountsModule;32using namespace OnlineAccountsModule;
3033
31namespace OnlineAccountsModule {34namespace OnlineAccountsModule {
@@ -36,20 +39,25 @@
36 Q_DECLARE_PUBLIC(Account)39 Q_DECLARE_PUBLIC(Account)
3740
38public:41public:
39 AccountPrivate(OnlineAccounts::Account *account, Account *q);42 AccountPrivate(OnlineAccounts::Account *account, QJSEngine *engine,
43 Account *q);
4044
41private Q_SLOTS:45private Q_SLOTS:
42 void onAuthenticationFinished();46 void onAuthenticationFinished();
4347
44private:48private:
45 OnlineAccounts::Account *m_account;49 OnlineAccounts::Account *m_account;
50 QJSEngine *m_engine;
46 mutable Account *q_ptr;51 mutable Account *q_ptr;
47};52};
4853
49} // namespace54} // namespace
5055
51AccountPrivate::AccountPrivate(OnlineAccounts::Account *account, Account *q):56AccountPrivate::AccountPrivate(OnlineAccounts::Account *account,
57 QJSEngine *engine,
58 Account *q):
52 m_account(account),59 m_account(account),
60 m_engine(engine),
53 q_ptr(q)61 q_ptr(q)
54{62{
55 QObject::connect(account, SIGNAL(changed()),63 QObject::connect(account, SIGNAL(changed()),
@@ -122,9 +130,10 @@
122 * \endlist130 * \endlist
123 */131 */
124132
125Account::Account(OnlineAccounts::Account *account, QObject *parent):133Account::Account(OnlineAccounts::Account *account, QJSEngine *engine,
134 QObject *parent):
126 QObject(parent),135 QObject(parent),
127 d_ptr(new AccountPrivate(account, this))136 d_ptr(new AccountPrivate(account, engine, this))
128{137{
129}138}
130139
@@ -187,6 +196,27 @@
187}196}
188197
189/*!198/*!
199 * \qmlproperty int Account::service
200 *
201 * Service data associated with this account. This is an object containing the
202 * following properties:
203 * \list
204 * \li \c serviceId - same service ID returned by Account::serviceId
205 * \li \c displayName - the localized display name for the service
206 * \li \c iconSource - URL for the icon; can be a "file://" URL to a local
207 * file, or an icon from the theme if the URL starts with "image://theme/"
208 */
209QJSValue Account::service() const
210{
211 Q_D(const Account);
212#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
213 return d->m_engine->toScriptValue(d->m_account->service());
214#else
215 return d->m_engine->toScriptValue(d->m_account->service().toMap());
216#endif
217}
218
219/*!
190 * \qmlproperty enumeration Account::authenticationMethod220 * \qmlproperty enumeration Account::authenticationMethod
191 *221 *
192 * The authentication method used when authenticating with the account.222 * The authentication method used when authenticating with the account.
193223
=== modified file 'src/lib/Ubuntu/OnlineAccounts.2/account.h'
--- src/lib/Ubuntu/OnlineAccounts.2/account.h 2016-01-13 14:23:12 +0000
+++ src/lib/Ubuntu/OnlineAccounts.2/account.h 2016-11-10 09:12:06 +0000
@@ -21,10 +21,13 @@
21#ifndef ONLINE_ACCOUNTS_MODULE_ACCOUNT_H21#ifndef ONLINE_ACCOUNTS_MODULE_ACCOUNT_H
22#define ONLINE_ACCOUNTS_MODULE_ACCOUNT_H22#define ONLINE_ACCOUNTS_MODULE_ACCOUNT_H
2323
24#include <QJSValue>
24#include <QObject>25#include <QObject>
25#include <QString>26#include <QString>
26#include <QVariantMap>27#include <QVariantMap>
2728
29class QJSEngine;
30
28namespace OnlineAccounts {31namespace OnlineAccounts {
29class Account;32class Account;
30}33}
@@ -40,6 +43,7 @@
40 Q_PROPERTY(QString displayName READ displayName NOTIFY accountChanged)43 Q_PROPERTY(QString displayName READ displayName NOTIFY accountChanged)
41 Q_PROPERTY(int accountId READ accountId CONSTANT)44 Q_PROPERTY(int accountId READ accountId CONSTANT)
42 Q_PROPERTY(QString serviceId READ serviceId CONSTANT)45 Q_PROPERTY(QString serviceId READ serviceId CONSTANT)
46 Q_PROPERTY(QJSValue service READ service CONSTANT)
43 Q_PROPERTY(AuthenticationMethod authenticationMethod \47 Q_PROPERTY(AuthenticationMethod authenticationMethod \
44 READ authenticationMethod CONSTANT)48 READ authenticationMethod CONSTANT)
45 Q_PROPERTY(QVariantMap settings READ settings NOTIFY accountChanged)49 Q_PROPERTY(QVariantMap settings READ settings NOTIFY accountChanged)
@@ -64,13 +68,15 @@
64 ErrorCodeInteractionRequired,68 ErrorCodeInteractionRequired,
65 };69 };
6670
67 explicit Account(OnlineAccounts::Account *account, QObject *parent = 0);71 explicit Account(OnlineAccounts::Account *account, QJSEngine *engine,
72 QObject *parent = 0);
68 ~Account();73 ~Account();
6974
70 bool isValid() const;75 bool isValid() const;
71 QString displayName() const;76 QString displayName() const;
72 int accountId() const;77 int accountId() const;
73 QString serviceId() const;78 QString serviceId() const;
79 QJSValue service() const;
74 AuthenticationMethod authenticationMethod() const;80 AuthenticationMethod authenticationMethod() const;
75 QVariantMap settings() const;81 QVariantMap settings() const;
7682
@@ -90,4 +96,7 @@
9096
91} // namespace97} // namespace
9298
99Q_DECLARE_METATYPE(OnlineAccountsModule::Account::AuthenticationMethod)
100Q_DECLARE_METATYPE(OnlineAccountsModule::Account::ErrorCode)
101
93#endif // ONLINE_ACCOUNTS_MODULE_ACCOUNT_H102#endif // ONLINE_ACCOUNTS_MODULE_ACCOUNT_H
94103
=== modified file 'src/lib/Ubuntu/OnlineAccounts.2/account_model.cpp'
--- src/lib/Ubuntu/OnlineAccounts.2/account_model.cpp 2016-01-18 12:23:07 +0000
+++ src/lib/Ubuntu/OnlineAccounts.2/account_model.cpp 2016-11-10 09:12:06 +0000
@@ -30,6 +30,7 @@
30#include <QDebug>30#include <QDebug>
31#include <QQmlEngine>31#include <QQmlEngine>
32#include <QVariantMap>32#include <QVariantMap>
33#include <QtQml>
3334
34using namespace OnlineAccountsModule;35using namespace OnlineAccountsModule;
3536
@@ -85,6 +86,7 @@
85 roleNames[AccountModel::AuthenticationMethodRole] = "authenticationMethod";86 roleNames[AccountModel::AuthenticationMethodRole] = "authenticationMethod";
86 roleNames[AccountModel::SettingsRole] = "settings";87 roleNames[AccountModel::SettingsRole] = "settings";
87 roleNames[AccountModel::AccountRole] = "account";88 roleNames[AccountModel::AccountRole] = "account";
89 roleNames[AccountModel::ServiceRole] = "service";
88}90}
8991
90void AccountModelPrivate::queueUpdate()92void AccountModelPrivate::queueUpdate()
@@ -122,13 +124,17 @@
122124
123Account *AccountModelPrivate::handleAccount(OnlineAccounts::Account *account)125Account *AccountModelPrivate::handleAccount(OnlineAccounts::Account *account)
124{126{
127 Q_Q(AccountModel);
128
125 /* First, check if the account is already handled */129 /* First, check if the account is already handled */
126 Q_FOREACH(Account *a, m_accounts) {130 Q_FOREACH(Account *a, m_accounts) {
127 if (account == a->internalObject()) {131 if (account == a->internalObject()) {
128 return a;132 return a;
129 }133 }
130 }134 }
131 Account *a = new Account(account, this);135
136 QQmlEngine *engine = qmlEngine(q);
137 Account *a = new Account(account, engine, this);
132 QQmlEngine::setObjectOwnership(a, QQmlEngine::CppOwnership);138 QQmlEngine::setObjectOwnership(a, QQmlEngine::CppOwnership);
133 QObject::connect(a, SIGNAL(validChanged()),139 QObject::connect(a, SIGNAL(validChanged()),
134 this, SLOT(onAccountValidChanged()));140 this, SLOT(onAccountValidChanged()));
@@ -386,6 +392,24 @@
386 return objects;392 return objects;
387}393}
388394
395QJSValue AccountModel::serviceList() const
396{
397 Q_D(const AccountModel);
398 QJSEngine *engine = qmlEngine(this);
399 QJSValue ret = engine->newArray();
400 if (!d->m_manager) return ret;
401 int i = 0;
402 Q_FOREACH(const auto &service, d->m_manager->availableServices()) {
403#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
404 QJSValue v = engine->toScriptValue(service);
405#else
406 QJSValue v = engine->toScriptValue(service.toMap());
407#endif
408 ret.setProperty(i++, v);
409 }
410 return ret;
411}
412
389/*!413/*!
390 * \qmlsignal AccountModel::accessReply(jsobject reply, jsobject authenticationData)414 * \qmlsignal AccountModel::accessReply(jsobject reply, jsobject authenticationData)
391 *415 *
@@ -495,6 +519,9 @@
495 case AccountRole:519 case AccountRole:
496 ret = QVariant::fromValue<QObject*>(account);520 ret = QVariant::fromValue<QObject*>(account);
497 break;521 break;
522 case ServiceRole:
523 ret = QVariant::fromValue(account->service());
524 break;
498 }525 }
499526
500 return ret;527 return ret;
501528
=== modified file 'src/lib/Ubuntu/OnlineAccounts.2/account_model.h'
--- src/lib/Ubuntu/OnlineAccounts.2/account_model.h 2016-01-18 12:23:07 +0000
+++ src/lib/Ubuntu/OnlineAccounts.2/account_model.h 2016-11-10 09:12:06 +0000
@@ -21,8 +21,12 @@
21#ifndef ONLINE_ACCOUNTS_MODULE_ACCOUNT_MODEL_H21#ifndef ONLINE_ACCOUNTS_MODULE_ACCOUNT_MODEL_H
22#define ONLINE_ACCOUNTS_MODULE_ACCOUNT_MODEL_H22#define ONLINE_ACCOUNTS_MODULE_ACCOUNT_MODEL_H
2323
24#include "OnlineAccounts/Service"
25
24#include <QAbstractListModel>26#include <QAbstractListModel>
25#include <QQmlParserStatus>27#include <QQmlParserStatus>
28#include <QQmlListProperty>
29#include <QJSValue>
26#include <QString>30#include <QString>
27#include <QVariant>31#include <QVariant>
2832
@@ -43,6 +47,8 @@
43 WRITE setServiceId NOTIFY serviceIdChanged)47 WRITE setServiceId NOTIFY serviceIdChanged)
44 Q_PROPERTY(QList<QObject*> accountList READ accountList \48 Q_PROPERTY(QList<QObject*> accountList READ accountList \
45 NOTIFY accountListChanged)49 NOTIFY accountListChanged)
50 Q_PROPERTY(QJSValue serviceList READ serviceList \
51 NOTIFY isReadyChanged)
4652
47public:53public:
48 enum Roles {54 enum Roles {
@@ -53,6 +59,7 @@
53 AuthenticationMethodRole,59 AuthenticationMethodRole,
54 SettingsRole,60 SettingsRole,
55 AccountRole,61 AccountRole,
62 ServiceRole,
56 };63 };
5764
58 explicit AccountModel(QObject *parent = 0);65 explicit AccountModel(QObject *parent = 0);
@@ -68,6 +75,8 @@
6875
69 QList<QObject*> accountList() const;76 QList<QObject*> accountList() const;
7077
78 QJSValue serviceList() const;
79
71 Q_INVOKABLE void requestAccess(const QString &service,80 Q_INVOKABLE void requestAccess(const QString &service,
72 const QVariantMap &params);81 const QVariantMap &params);
7382
7483
=== modified file 'src/lib/Ubuntu/OnlineAccounts.2/plugin.cpp'
--- src/lib/Ubuntu/OnlineAccounts.2/plugin.cpp 2015-07-31 12:44:30 +0000
+++ src/lib/Ubuntu/OnlineAccounts.2/plugin.cpp 2016-11-10 09:12:06 +0000
@@ -20,6 +20,7 @@
2020
21#include "plugin.h"21#include "plugin.h"
2222
23#include "account.h"
23#include "account_model.h"24#include "account_model.h"
2425
25#include <QDebug>26#include <QDebug>
@@ -32,4 +33,8 @@
32 qDebug() << Q_FUNC_INFO << uri;33 qDebug() << Q_FUNC_INFO << uri;
3334
34 qmlRegisterType<AccountModel>(uri, 2, 0, "AccountModel");35 qmlRegisterType<AccountModel>(uri, 2, 0, "AccountModel");
36 qmlRegisterUncreatableType<Account>(uri, 2, 0, "Account",
37 "Cannot be created from QML");
38 qmlRegisterUncreatableType<OnlineAccounts::Service>(uri, 2, 0, "Service",
39 "Cannot be created from QML");
35}40}
3641
=== modified file 'tests/daemon/functional_tests/data/com.ubuntu.tests_application.application'
--- tests/daemon/functional_tests/data/com.ubuntu.tests_application.application 2015-07-07 12:58:49 +0000
+++ tests/daemon/functional_tests/data/com.ubuntu.tests_application.application 2016-11-10 09:12:06 +0000
@@ -5,9 +5,12 @@
5 <desktop-entry>mailer.desktop</desktop-entry>5 <desktop-entry>mailer.desktop</desktop-entry>
66
7 <services>7 <services>
8 <service id="coolshare">8 <service id="com.ubuntu.tests_coolshare">
9 <description>Mailer can even share stuff on CoolShare</description>9 <description>Mailer can even share stuff on CoolShare</description>
10 </service>10 </service>
11 <service id="missing-provider">
12 <description>service exists, provider does not</description>
13 </service>
11 </services>14 </services>
12 <profile>com.ubuntu.tests_application_0.3</profile>15 <profile>com.ubuntu.tests_application_0.3</profile>
13</application>16</application>
1417
=== modified file 'tests/daemon/functional_tests/data/com.ubuntu.tests_coolshare.service'
--- tests/daemon/functional_tests/data/com.ubuntu.tests_coolshare.service 2016-09-28 13:09:06 +0000
+++ tests/daemon/functional_tests/data/com.ubuntu.tests_coolshare.service 2016-11-10 09:12:06 +0000
@@ -1,5 +1,5 @@
1<?xml version="1.0" encoding="UTF-8" ?>1<?xml version="1.0" encoding="UTF-8" ?>
2<service id="coolshare">2<service id="com.ubuntu.tests_coolshare">
3 <type>sharing</type>3 <type>sharing</type>
4 <name>Cool Share</name>4 <name>Cool Share</name>
5 <icon>general_otherservice</icon>5 <icon>general_otherservice</icon>
66
=== modified file 'tests/daemon/functional_tests/data/coolmail.service'
--- tests/daemon/functional_tests/data/coolmail.service 2015-07-02 08:29:48 +0000
+++ tests/daemon/functional_tests/data/coolmail.service 2016-11-10 09:12:06 +0000
@@ -2,7 +2,6 @@
2<service id="coolmail">2<service id="coolmail">
3 <type>e-mail</type>3 <type>e-mail</type>
4 <name>Cool Mail</name>4 <name>Cool Mail</name>
5 <icon>general_myservice</icon>
6 <provider>cool</provider>5 <provider>cool</provider>
76
8 <template>7 <template>
98
=== added file 'tests/daemon/functional_tests/data/missing-provider.service'
--- tests/daemon/functional_tests/data/missing-provider.service 1970-01-01 00:00:00 +0000
+++ tests/daemon/functional_tests/data/missing-provider.service 2016-11-10 09:12:06 +0000
@@ -0,0 +1,14 @@
1<?xml version="1.0" encoding="UTF-8" ?>
2<service id="missing-provider">
3 <type>sharing</type>
4 <name>Orphan</name>
5 <icon>icon_missing_provider</icon>
6 <provider>missing</provider>
7
8 <template>
9 <group name="auth">
10 <setting name="method">password</setting>
11 <setting name="mechanism">password</setting>
12 </group>
13 </template>
14</service>
015
=== modified file 'tests/daemon/functional_tests/functional_tests.cpp'
--- tests/daemon/functional_tests/functional_tests.cpp 2016-10-13 13:42:12 +0000
+++ tests/daemon/functional_tests/functional_tests.cpp 2016-11-10 09:12:06 +0000
@@ -60,8 +60,28 @@
60 return qstrdup(doc.toJson(QJsonDocument::Compact).data());60 return qstrdup(doc.toJson(QJsonDocument::Compact).data());
61}61}
6262
63template<>
64char *toString(const QSet<QVariantMap> &set)
65{
66 QByteArray ba = "QSet<QVariantMap>(";
67 QStringList list;
68 Q_FOREACH(const QVariantMap &map, set) {
69 list.append(QJsonDocument::fromVariant(map).toJson(QJsonDocument::Compact));
70 }
71 ba += list.join(", ");
72 ba += ")";
73 return qstrdup(ba.data());
74}
75
63} // QTest namespace76} // QTest namespace
6477
78static inline uint qHash(const QVariantMap &m, uint seed = 0)
79{
80 QString signature = QStringList(m.keys()).join(' ') +
81 m.value(ONLINE_ACCOUNTS_INFO_KEY_SERVICE_ID).toString();
82 return ::qHash(signature, seed);
83}
84
65class TestProcess: public QProcess85class TestProcess: public QProcess
66{86{
67 Q_OBJECT87 Q_OBJECT
@@ -90,6 +110,12 @@
90 void quit() { write("\n"); waitForFinished(); }110 void quit() { write("\n"); waitForFinished(); }
91111
92 QList<AccountInfo> getAccounts(const QVariantMap &filters) {112 QList<AccountInfo> getAccounts(const QVariantMap &filters) {
113 QList<QVariantMap> services;
114 return getAccounts(filters, services);
115 }
116
117 QList<AccountInfo> getAccounts(const QVariantMap &filters,
118 QList<QVariantMap> &services) {
93 QJsonDocument doc(QJsonObject::fromVariantMap(filters));119 QJsonDocument doc(QJsonObject::fromVariantMap(filters));
94 m_replyExpected = true;120 m_replyExpected = true;
95 write("GetAccounts -f ");121 write("GetAccounts -f ");
@@ -97,16 +123,31 @@
97123
98 waitForReadyRead();124 waitForReadyRead();
99 doc = QJsonDocument::fromJson(readLine());125 doc = QJsonDocument::fromJson(readLine());
126 qDebug() << "Got Json:" << doc;
100 m_replyExpected = false;127 m_replyExpected = false;
101 QList<AccountInfo> accountInfos;128 QList<AccountInfo> accountInfos;
102 Q_FOREACH(const QJsonValue &v, doc.array()) {129 if (checkError(doc)) return accountInfos;
130 const QJsonArray accountsJson = doc.array().at(0).toArray();
131 const QJsonArray servicesJson = doc.array().at(1).toArray();
132 Q_FOREACH(const QJsonValue &v, accountsJson) {
103 QJsonArray a = v.toArray();133 QJsonArray a = v.toArray();
104 accountInfos.append(AccountInfo(a.at(0).toInt(),134 accountInfos.append(AccountInfo(a.at(0).toInt(),
105 a.at(1).toObject().toVariantMap()));135 a.at(1).toObject().toVariantMap()));
106 }136 }
137 Q_FOREACH(const QJsonValue &v, servicesJson) {
138 services.append(v.toObject().toVariantMap());
139 }
107 return accountInfos;140 return accountInfos;
108 }141 }
109142
143 QString errorName() const { return m_errorName; }
144
145protected:
146 bool checkError(const QJsonDocument &doc) {
147 m_errorName = doc.object().value("error").toString();
148 return !m_errorName.isEmpty();
149 }
150
110private Q_SLOTS:151private Q_SLOTS:
111 void onReadyRead() {152 void onReadyRead() {
112 if (m_replyExpected) return;153 if (m_replyExpected) return;
@@ -128,6 +169,7 @@
128169
129private:170private:
130 QString m_uniqueName;171 QString m_uniqueName;
172 QString m_errorName;
131 bool m_replyExpected;173 bool m_replyExpected;
132};174};
133175
@@ -275,35 +317,113 @@
275 delete m_dbus;317 delete m_dbus;
276}318}
277319
320
278void FunctionalTests::testGetAccountsFiltering_data()321void FunctionalTests::testGetAccountsFiltering_data()
279{322{
280 QTest::addColumn<QVariantMap>("filters");323 QTest::addColumn<QVariantMap>("filters");
281 QTest::addColumn<QString>("securityContext");324 QTest::addColumn<QString>("securityContext");
325 QTest::addColumn<QString>("expectedError");
282 QTest::addColumn<QList<int> >("expectedAccountIds");326 QTest::addColumn<QList<int> >("expectedAccountIds");
327 QTest::addColumn<QList<QVariantMap> >("expectedServices");
283328
284 QVariantMap filters;329 QVariantMap filters;
285 QTest::newRow("empty filters") <<330 QTest::newRow("empty filters") <<
286 filters <<331 filters <<
287 "unconfined" <<332 "unconfined" <<
288 (QList<int>() << 1 << 2 << 3);333 QString() <<
334 (QList<int>() << 1 << 2 << 3) <<
335 QList<QVariantMap> {};
289336
290 QTest::newRow("empty filters, confined") <<337 QTest::newRow("empty filters, confined") <<
291 filters <<338 filters <<
292 "com.ubuntu.tests_application_0.2" <<339 "com.ubuntu.tests_application_0.2" <<
293 (QList<int>() << 2);340 QString() <<
294341 (QList<int>() << 2) <<
295 filters[ONLINE_ACCOUNTS_INFO_KEY_SERVICE_ID] = "coolmail";342 QList<QVariantMap> {
296 QTest::newRow("by service ID") <<343 {
297 filters <<344 { ONLINE_ACCOUNTS_INFO_KEY_DISPLAY_NAME, "Cool Share" },
298 "unconfined" <<345 { ONLINE_ACCOUNTS_INFO_KEY_SERVICE_ID, "com.ubuntu.tests_coolshare" },
299 (QList<int>() << 1 << 3);346 { ONLINE_ACCOUNTS_INFO_KEY_ICON_SOURCE, "image://theme/general_otherservice" },
347 },
348 };
349
350 filters[ONLINE_ACCOUNTS_INFO_KEY_SERVICE_ID] = "coolmail";
351 QTest::newRow("unconfined, by service ID") <<
352 filters <<
353 "unconfined" <<
354 QString() <<
355 (QList<int>() << 1 << 3) <<
356 QList<QVariantMap> {};
357 filters.clear();
358
359 filters[ONLINE_ACCOUNTS_INFO_KEY_SERVICE_ID] = "coolmail";
360 QTest::newRow("confined, by service ID") <<
361 filters <<
362 "com.ubuntu.tests_application_0.2" <<
363 QString() <<
364 (QList<int>()) <<
365 QList<QVariantMap> {
366 {
367 { ONLINE_ACCOUNTS_INFO_KEY_DISPLAY_NAME, "Cool Share" },
368 { ONLINE_ACCOUNTS_INFO_KEY_SERVICE_ID, "com.ubuntu.tests_coolshare" },
369 { ONLINE_ACCOUNTS_INFO_KEY_ICON_SOURCE, "image://theme/general_otherservice" },
370 },
371 };
372 filters.clear();
373
374 filters["applicationId"] = "com.ubuntu.tests_application";
375 QTest::newRow("by app ID") <<
376 filters <<
377 "unconfined" <<
378 QString() <<
379 (QList<int>() << 2) <<
380 QList<QVariantMap> {
381 {
382 { ONLINE_ACCOUNTS_INFO_KEY_DISPLAY_NAME, "Cool Share" },
383 { ONLINE_ACCOUNTS_INFO_KEY_SERVICE_ID, "com.ubuntu.tests_coolshare" },
384 { ONLINE_ACCOUNTS_INFO_KEY_ICON_SOURCE, "image://theme/general_otherservice" },
385 },
386 };
387 filters.clear();
388
389 filters["applicationId"] = "mailer";
390 QTest::newRow("confined app requesting other app ID") <<
391 filters <<
392 "com.ubuntu.tests_application_0.2" <<
393 ONLINE_ACCOUNTS_ERROR_PERMISSION_DENIED <<
394 (QList<int>()) <<
395 QList<QVariantMap> {};
396 filters.clear();
397
398 filters["applicationId"] = "mailer";
399 QTest::newRow("by app ID, with service fallback") <<
400 filters <<
401 "unconfined" <<
402 QString() <<
403 QList<int>{ 3, 1 } <<
404 QList<QVariantMap> {
405 {
406 { ONLINE_ACCOUNTS_INFO_KEY_DISPLAY_NAME, "OAuth 1 test" },
407 { ONLINE_ACCOUNTS_INFO_KEY_SERVICE_ID, "oauth1auth" },
408 { ONLINE_ACCOUNTS_INFO_KEY_ICON_SOURCE, "image://theme/general_myservice" },
409 },
410 {
411 { ONLINE_ACCOUNTS_INFO_KEY_DISPLAY_NAME, "Cool Mail" },
412 { ONLINE_ACCOUNTS_INFO_KEY_SERVICE_ID, "coolmail" },
413 { ONLINE_ACCOUNTS_INFO_KEY_ICON_SOURCE, "image://theme/general_myprovider" },
414 },
415 };
416 filters.clear();
417
300}418}
301419
302void FunctionalTests::testGetAccountsFiltering()420void FunctionalTests::testGetAccountsFiltering()
303{421{
304 QFETCH(QVariantMap, filters);422 QFETCH(QVariantMap, filters);
305 QFETCH(QString, securityContext);423 QFETCH(QString, securityContext);
424 QFETCH(QString, expectedError);
306 QFETCH(QList<int>, expectedAccountIds);425 QFETCH(QList<int>, expectedAccountIds);
426 QFETCH(QList<QVariantMap>, expectedServices);
307427
308 DaemonInterface *daemon = new DaemonInterface(m_dbus->sessionConnection());428 DaemonInterface *daemon = new DaemonInterface(m_dbus->sessionConnection());
309429
@@ -313,7 +433,10 @@
313 };433 };
314 m_dbus->dbusApparmor().setCredentials(testProcess.uniqueName(), credentials);434 m_dbus->dbusApparmor().setCredentials(testProcess.uniqueName(), credentials);
315435
316 QList<AccountInfo> accountInfos = testProcess.getAccounts(filters);436 QList<QVariantMap> services;
437 QList<AccountInfo> accountInfos = testProcess.getAccounts(filters, services);
438 QCOMPARE(testProcess.errorName(), expectedError);
439 QCOMPARE(services.toSet(), expectedServices.toSet());
317 QList<int> accountIds;440 QList<int> accountIds;
318 Q_FOREACH(const AccountInfo &info, accountInfos) {441 Q_FOREACH(const AccountInfo &info, accountInfos) {
319 accountIds.append(info.id() + m_firstAccountId);442 accountIds.append(info.id() + m_firstAccountId);
320443
=== modified file 'tests/daemon/functional_tests/test_process.py'
--- tests/daemon/functional_tests/test_process.py 2016-07-19 11:55:45 +0000
+++ tests/daemon/functional_tests/test_process.py 2016-11-10 09:12:06 +0000
@@ -30,8 +30,11 @@
30 filters = dbus.Dictionary(signature='sv')30 filters = dbus.Dictionary(signature='sv')
31 if args.filters:31 if args.filters:
32 filters.update(json.loads(args.filters))32 filters.update(json.loads(args.filters))
33 print('%s' % json.dumps(self.manager.GetAccounts(filters), sort_keys=True),33 try:
34 flush=True)34 print('%s' % json.dumps(self.manager.GetAccounts(filters), sort_keys=True),
35 flush=True)
36 except dbus.exceptions.DBusException as err:
37 print('{ "error": "%s" }' % err.get_dbus_name(), flush=True)
3538
36 def on_account_changed(self, serviceId, accountInfo):39 def on_account_changed(self, serviceId, accountInfo):
37 info = json.dumps(accountInfo, sort_keys=True)40 info = json.dumps(accountInfo, sort_keys=True)
3841
=== modified file 'tests/lib/OnlineAccounts/functional_tests/functional_tests.cpp'
--- tests/lib/OnlineAccounts/functional_tests/functional_tests.cpp 2016-07-22 05:08:06 +0000
+++ tests/lib/OnlineAccounts/functional_tests/functional_tests.cpp 2016-11-10 09:12:06 +0000
@@ -26,18 +26,22 @@
26#include "OnlineAccounts/account_info.h"26#include "OnlineAccounts/account_info.h"
27#include "OnlineAccountsDaemon/dbus_constants.h"27#include "OnlineAccountsDaemon/dbus_constants.h"
28#include <QDBusConnection>28#include <QDBusConnection>
29#include <QJsonDocument>
30#include <QJsonObject>
29#include <QObject>31#include <QObject>
30#include <QSignalSpy>32#include <QSignalSpy>
31#include <QTest>33#include <QTest>
32#include <libqtdbusmock/DBusMock.h>34#include <libqtdbusmock/DBusMock.h>
3335
34namespace QTest {36namespace QTest {
37
35template<>38template<>
36char *toString(const QVariantMap &map)39char *toString(const QVariantMap &map)
37{40{
38 QJsonDocument doc(QJsonObject::fromVariantMap(map));41 QJsonDocument doc(QJsonObject::fromVariantMap(map));
39 return qstrdup(doc.toJson(QJsonDocument::Compact).data());42 return qstrdup(doc.toJson(QJsonDocument::Compact).data());
40}43}
44
41} // QTest namespace45} // QTest namespace
4246
43class FunctionalTests: public QObject47class FunctionalTests: public QObject
@@ -82,6 +86,8 @@
82 void testManagerReady();86 void testManagerReady();
83 void testManagerAvailableAccounts_data();87 void testManagerAvailableAccounts_data();
84 void testManagerAvailableAccounts();88 void testManagerAvailableAccounts();
89 void testManagerAvailableServices_data();
90 void testManagerAvailableServices();
85 void testManagerAccount();91 void testManagerAccount();
86 void testManagerRequestAccess_data();92 void testManagerRequestAccess_data();
87 void testManagerRequestAccess();93 void testManagerRequestAccess();
@@ -132,7 +138,7 @@
132 QFETCH(bool, haveGetAccountsMethod);138 QFETCH(bool, haveGetAccountsMethod);
133139
134 if (haveGetAccountsMethod) {140 if (haveGetAccountsMethod) {
135 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})", "ret = []");141 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})aa{sv}", "ret = ([], [])");
136 }142 }
137 OnlineAccounts::Manager manager("my-app");143 OnlineAccounts::Manager manager("my-app");
138144
@@ -150,12 +156,12 @@
150 QTest::addColumn<QStringList>("expectedDisplayNames");156 QTest::addColumn<QStringList>("expectedDisplayNames");
151157
152 QTest::newRow("no accounts") <<158 QTest::newRow("no accounts") <<
153 "ret = []" <<159 "ret = ([], [])" <<
154 QList<int>() <<160 QList<int>() <<
155 QStringList();161 QStringList();
156162
157 QTest::newRow("one account, no data") <<163 QTest::newRow("one account, no data") <<
158 "ret = [(1, {'displayName': 'Tom'})]" <<164 "ret = ([(1, {'displayName': 'Tom'})], [])" <<
159 (QList<int>() << 1) <<165 (QList<int>() << 1) <<
160 (QStringList() << "Tom");166 (QStringList() << "Tom");
161}167}
@@ -166,7 +172,7 @@
166 QFETCH(QList<int>, expectedIds);172 QFETCH(QList<int>, expectedIds);
167 QFETCH(QStringList, expectedDisplayNames);173 QFETCH(QStringList, expectedDisplayNames);
168174
169 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})", reply);175 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})aa{sv}", reply);
170 OnlineAccounts::Manager manager("my-app");176 OnlineAccounts::Manager manager("my-app");
171177
172 manager.waitForReady();178 manager.waitForReady();
@@ -181,10 +187,77 @@
181 QCOMPARE(displayNames, expectedDisplayNames);187 QCOMPARE(displayNames, expectedDisplayNames);
182}188}
183189
190void FunctionalTests::testManagerAvailableServices_data()
191{
192 QTest::addColumn<QString>("reply");
193 QTest::addColumn<QList<QVariantMap>>("expectedServices");
194
195 QTest::newRow("no services") <<
196 "ret = ([], [])" <<
197 QList<QVariantMap> {};
198
199 QTest::newRow("one service") <<
200 "ret = ([], [{"
201 "'" ONLINE_ACCOUNTS_INFO_KEY_SERVICE_ID "': 'app_coolshare',"
202 "'" ONLINE_ACCOUNTS_INFO_KEY_DISPLAY_NAME "': 'Cool Share',"
203 "'" ONLINE_ACCOUNTS_INFO_KEY_ICON_SOURCE "': 'image://theme/coolshare',"
204 "}])" <<
205 QList<QVariantMap> {
206 {
207 { "serviceId", "app_coolshare" },
208 { "displayName", "Cool Share" },
209 { "iconSource", "image://theme/coolshare"},
210 },
211 };
212}
213
214void FunctionalTests::testManagerAvailableServices()
215{
216 QFETCH(QString, reply);
217 QFETCH(QList<QVariantMap>, expectedServices);
218
219 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})aa{sv}", reply);
220 OnlineAccounts::Manager manager("my-app");
221
222 manager.waitForReady();
223 const auto availableServices = manager.availableServices();
224#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
225 QList<QVariantMap> services;
226 for (const OnlineAccounts::Service &service: availableServices) {
227 QVariantMap data;
228
229 const QMetaObject &mo = service.staticMetaObject;
230 for (int i = mo.propertyOffset(); i < mo.propertyCount(); i++) {
231 const QMetaProperty prop = mo.property(i);
232 data.insert(prop.name(), prop.readOnGadget(&service));
233 }
234
235 services.append(data);
236 }
237
238 QCOMPARE(services, expectedServices);
239#else
240 QCOMPARE(availableServices.count(), expectedServices.count());
241#endif
242}
243
184void FunctionalTests::testManagerAccount()244void FunctionalTests::testManagerAccount()
185{245{
186 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})",246 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})aa{sv}",
187 "ret = [(1, {'displayName': 'John'})]");247 "ret = (["
248 " (1, {"
249 " 'displayName': 'John',"
250 " 'serviceId': 'app_coolshare',"
251 " }),"
252 " (2, {"
253 " 'displayName': 'Bob',"
254 " 'serviceId': 'a missing one',"
255 " }),"
256 "], [{"
257 " 'serviceId': 'app_coolshare',"
258 " 'displayName': 'Cool Share',"
259 " 'iconSource': 'image://theme/coolshare',"
260 "}])");
188 OnlineAccounts::Manager manager("my-app");261 OnlineAccounts::Manager manager("my-app");
189262
190 manager.waitForReady();263 manager.waitForReady();
@@ -193,10 +266,22 @@
193 OnlineAccounts::Account *account = manager.account(4);266 OnlineAccounts::Account *account = manager.account(4);
194 QVERIFY(!account);267 QVERIFY(!account);
195268
269 // valid account linking to invalid service
270 account = manager.account(2);
271 QVERIFY(account);
272 QCOMPARE(account->displayName(), QString("Bob"));
273 QCOMPARE(account->serviceId(), QString("a missing one"));
274 QVERIFY(!account->service().isValid());
275
196 // valid account276 // valid account
197 account = manager.account(1);277 account = manager.account(1);
198 QVERIFY(account);278 QVERIFY(account);
199 QCOMPARE(account->displayName(), QString("John"));279 QCOMPARE(account->displayName(), QString("John"));
280 QCOMPARE(account->serviceId(), QString("app_coolshare"));
281 QVERIFY(account->service().isValid());
282 QCOMPARE(account->service().displayName(), QString("Cool Share"));
283 QCOMPARE(account->service().iconSource(),
284 QUrl("image://theme/coolshare"));
200}285}
201286
202void FunctionalTests::testManagerRequestAccess_data()287void FunctionalTests::testManagerRequestAccess_data()
@@ -236,7 +321,7 @@
236 QFETCH(QString, displayName);321 QFETCH(QString, displayName);
237 QFETCH(QString, accessToken);322 QFETCH(QString, accessToken);
238323
239 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})", "ret = []");324 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})aa{sv}", "ret = ([], [])");
240 addMockedMethod("RequestAccess", "sa{sv}", "(ua{sv})a{sv}", reply);325 addMockedMethod("RequestAccess", "sa{sv}", "(ua{sv})a{sv}", reply);
241 OnlineAccounts::Manager manager("my-app");326 OnlineAccounts::Manager manager("my-app");
242327
@@ -277,12 +362,12 @@
277 QTest::addColumn<QVariantMap>("settings");362 QTest::addColumn<QVariantMap>("settings");
278363
279 QTest::newRow("empty account") <<364 QTest::newRow("empty account") <<
280 "ret = [(1, {})]" <<365 "[(1, {})]" <<
281 1 <<366 1 <<
282 "" << "" << 0 << QVariantMap();367 "" << "" << 0 << QVariantMap();
283368
284 QTest::newRow("no settings") <<369 QTest::newRow("no settings") <<
285 "ret = [(3, {"370 "[(3, {"
286 " 'displayName': 'Bob',"371 " 'displayName': 'Bob',"
287 " 'serviceId': 'MyService',"372 " 'serviceId': 'MyService',"
288 " 'authMethod': 1,"373 " 'authMethod': 1,"
@@ -297,7 +382,7 @@
297 settings.insert("Host", "example.com");382 settings.insert("Host", "example.com");
298 settings.insert("Port", int(7000));383 settings.insert("Port", int(7000));
299 QTest::newRow("with settings") <<384 QTest::newRow("with settings") <<
300 "ret = [(4, {"385 "[(4, {"
301 " 'displayName': 'Tom',"386 " 'displayName': 'Tom',"
302 " 'serviceId': 'MyService',"387 " 'serviceId': 'MyService',"
303 " 'authMethod': 2,"388 " 'authMethod': 2,"
@@ -320,7 +405,8 @@
320 QFETCH(int, authenticationMethod);405 QFETCH(int, authenticationMethod);
321 QFETCH(QVariantMap, settings);406 QFETCH(QVariantMap, settings);
322407
323 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})", reply);408 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})aa{sv}",
409 QString("ret = (%1, [])").arg(reply));
324 OnlineAccounts::Manager manager("my-app");410 OnlineAccounts::Manager manager("my-app");
325411
326 manager.waitForReady();412 manager.waitForReady();
@@ -347,7 +433,7 @@
347433
348void FunctionalTests::testPendingCallWatcher()434void FunctionalTests::testPendingCallWatcher()
349{435{
350 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})", "ret = []");436 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})aa{sv}", "ret = ([], [])");
351 addMockedMethod("RequestAccess", "sa{sv}", "(ua{sv})a{sv}",437 addMockedMethod("RequestAccess", "sa{sv}", "(ua{sv})a{sv}",
352 "ret = ((1, {'displayName': 'Bob'}),{})");438 "ret = ((1, {'displayName': 'Bob'}),{})");
353 OnlineAccounts::Manager manager("my-app");439 OnlineAccounts::Manager manager("my-app");
@@ -378,7 +464,7 @@
378464
379void FunctionalTests::testAccountChanges()465void FunctionalTests::testAccountChanges()
380{466{
381 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})", "ret = []");467 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})aa{sv}", "ret = ([], [])");
382 OnlineAccounts::Manager manager("my-app");468 OnlineAccounts::Manager manager("my-app");
383 QSignalSpy accountAvailable(&manager,469 QSignalSpy accountAvailable(&manager,
384 SIGNAL(accountAvailable(OnlineAccounts::Account*)));470 SIGNAL(accountAvailable(OnlineAccounts::Account*)));
@@ -442,8 +528,8 @@
442528
443void FunctionalTests::testMultipleServices()529void FunctionalTests::testMultipleServices()
444{530{
445 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})",531 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})aa{sv}",
446 "ret = ["532 "ret = (["
447 "(1, {"533 "(1, {"
448 " 'displayName': 'One',"534 " 'displayName': 'One',"
449 " 'serviceId': 'service2',"535 " 'serviceId': 'service2',"
@@ -464,7 +550,7 @@
464 " 'serviceId': 'service1',"550 " 'serviceId': 'service1',"
465 " 'authMethod': 1,"551 " 'authMethod': 1,"
466 "}),"552 "}),"
467 "]");553 "], [])");
468 OnlineAccounts::Manager manager("my-app");554 OnlineAccounts::Manager manager("my-app");
469 manager.waitForReady();555 manager.waitForReady();
470556
@@ -494,8 +580,8 @@
494580
495void FunctionalTests::testAuthentication()581void FunctionalTests::testAuthentication()
496{582{
497 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})",583 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})aa{sv}",
498 "ret = ["584 "ret = (["
499 "(1, {"585 "(1, {"
500 " 'displayName': 'Bob',"586 " 'displayName': 'Bob',"
501 " 'serviceId': 'MyService0',"587 " 'serviceId': 'MyService0',"
@@ -516,7 +602,7 @@
516 " 'serviceId': 'MyService3',"602 " 'serviceId': 'MyService3',"
517 " 'authMethod': 4,"603 " 'authMethod': 4,"
518 "}),"604 "}),"
519 "]");605 "], [])");
520 addMockedMethod("Authenticate", "usbba{sv}", "a{sv}",606 addMockedMethod("Authenticate", "usbba{sv}", "a{sv}",
521 "if args[0] == 1:\n"607 "if args[0] == 1:\n"
522 " ret = {"608 " ret = {"
@@ -671,12 +757,12 @@
671 QFETCH(int, errorCode);757 QFETCH(int, errorCode);
672 QFETCH(QString, errorMessage);758 QFETCH(QString, errorMessage);
673759
674 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})",760 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})aa{sv}",
675 "ret = [(1, {"761 "ret = ([(1, {"
676 " 'displayName': 'Bob',"762 " 'displayName': 'Bob',"
677 " 'serviceId': 'MyService0',"763 " 'serviceId': 'MyService0',"
678 " 'authMethod': 2,"764 " 'authMethod': 2,"
679 "})]");765 "})], [])");
680 addMockedMethod("Authenticate", "usbba{sv}", "a{sv}", reply);766 addMockedMethod("Authenticate", "usbba{sv}", "a{sv}", reply);
681 OnlineAccounts::Manager manager("my-app");767 OnlineAccounts::Manager manager("my-app");
682 manager.waitForReady();768 manager.waitForReady();
683769
=== modified file 'tests/lib/qml_module/tst_qml_module.cpp'
--- tests/lib/qml_module/tst_qml_module.cpp 2016-10-06 08:20:10 +0000
+++ tests/lib/qml_module/tst_qml_module.cpp 2016-11-10 09:12:06 +0000
@@ -55,14 +55,18 @@
55 }55 }
5656
57 void addMockedMethod(const QString &name,57 void addMockedMethod(const QString &name,
58 const QString &in_sig,58 const QString &in_sig,
59 const QString &out_sig,59 const QString &out_sig,
60 const QString &code)60 const QString &code)
61 {61 {
62 return mocked().AddMethod(ONLINE_ACCOUNTS_MANAGER_INTERFACE,62 return mocked().AddMethod(ONLINE_ACCOUNTS_MANAGER_INTERFACE,
63 name, in_sig, out_sig, code).waitForFinished();63 name, in_sig, out_sig, code).waitForFinished();
64 }64 }
6565
66 void addGetAccountsMethod(const QString &code) {
67 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})aa{sv}", code);
68 }
69
66 void emitAccountChanged(const QString &service,70 void emitAccountChanged(const QString &service,
67 uint accountId,71 uint accountId,
68 const QVariantMap &changes)72 const QVariantMap &changes)
@@ -90,6 +94,8 @@
90 void initTestCase();94 void initTestCase();
91 void testModuleImport();95 void testModuleImport();
92 void testModelProperties();96 void testModelProperties();
97 void testServices_data();
98 void testServices();
93 void testModelRoles_data();99 void testModelRoles_data();
94 void testModelRoles();100 void testModelRoles();
95 void testModelFilters_data();101 void testModelFilters_data();
@@ -156,9 +162,85 @@
156 delete object;162 delete object;
157}163}
158164
165void ModuleTest::testServices_data()
166{
167 QTest::addColumn<QString>("reply");
168 QTest::addColumn<QList<QVariantMap>>("expectedServices");
169
170 QTest::newRow("no services") <<
171 "[]" <<
172 QList<QVariantMap> {};
173
174 QTest::newRow("one service") <<
175 "[{"
176 "'" ONLINE_ACCOUNTS_INFO_KEY_SERVICE_ID "': 'app_coolshare',"
177 "'" ONLINE_ACCOUNTS_INFO_KEY_DISPLAY_NAME "': 'Cool Share',"
178 "'" ONLINE_ACCOUNTS_INFO_KEY_ICON_SOURCE "': 'image://theme/coolshare',"
179 "}]" <<
180 QList<QVariantMap> {
181 {
182 { "serviceId", "app_coolshare" },
183 { "displayName", "Cool Share" },
184 { "iconSource", "image://theme/coolshare"},
185 },
186 };
187}
188
189void ModuleTest::testServices()
190{
191 QFETCH(QString, reply);
192 QFETCH(QList<QVariantMap>, expectedServices);
193
194 addGetAccountsMethod(QString("ret = ([], %1)").arg(reply));
195
196 QQmlEngine engine;
197 QQmlComponent component(&engine);
198 /* We could return the serviceList property directly, but that would be
199 * passing a OnlineAccounts::Service as QJSValue, which might not be a
200 * proof that every property is properly accessible from QML. Therefore, we
201 * explicitly run through the list and copy it as a new object. */
202 component.setData("import Ubuntu.OnlineAccounts 2.0\n"
203 "AccountModel {\n"
204 " applicationId: \"foo\"\n"
205 " function getServices() {\n"
206 " var ret = [];\n"
207 " for (var i = 0; i < serviceList.length; i++) {\n"
208 " var s = serviceList[i];\n"
209 " var service = {};\n"
210 " for (var key in s) { service[key] = s[key]; }\n"
211 " ret.push(service);\n"
212 " }\n"
213 " return ret;\n"
214 " }\n"
215 "}",
216 QUrl());
217 QObject *object = component.create();
218 QVERIFY(object != 0);
219 QAbstractListModel *model = qobject_cast<QAbstractListModel*>(object);
220 QVERIFY(model != 0);
221
222 QSignalSpy ready(object, SIGNAL(isReadyChanged()));
223 ready.wait();
224
225 QVariant serviceList;
226 bool ok = QMetaObject::invokeMethod(object, "getServices",
227 Q_RETURN_ARG(QVariant, serviceList));
228 QVERIFY(ok);
229
230 QVariantList serviceVariantList = serviceList.toList();
231 QList<QVariantMap> services;
232 for (const QVariant &v: serviceVariantList) {
233 services.append(v.toMap());
234 }
235
236 QCOMPARE(services, expectedServices);
237 delete object;
238}
239
159void ModuleTest::testModelRoles_data()240void ModuleTest::testModelRoles_data()
160{241{
161 QTest::addColumn<QString>("accountData");242 QTest::addColumn<QString>("accountData");
243 QTest::addColumn<QString>("serviceData");
162 QTest::addColumn<QString>("displayName");244 QTest::addColumn<QString>("displayName");
163 QTest::addColumn<QString>("serviceId");245 QTest::addColumn<QString>("serviceId");
164 QTest::addColumn<int>("authenticationMethod");246 QTest::addColumn<int>("authenticationMethod");
@@ -167,6 +249,7 @@
167 QVariantMap settings;249 QVariantMap settings;
168 QTest::newRow("empty") <<250 QTest::newRow("empty") <<
169 "{}" <<251 "{}" <<
252 "" <<
170 "" << "" << 0 << settings;253 "" << "" << 0 << settings;
171254
172 settings.insert("Server", "www.example.com");255 settings.insert("Server", "www.example.com");
@@ -179,19 +262,23 @@
179 " '" ONLINE_ACCOUNTS_INFO_KEY_SETTINGS "Server': 'www.example.com',"262 " '" ONLINE_ACCOUNTS_INFO_KEY_SETTINGS "Server': 'www.example.com',"
180 " '" ONLINE_ACCOUNTS_INFO_KEY_SETTINGS "Port': 9900,"263 " '" ONLINE_ACCOUNTS_INFO_KEY_SETTINGS "Port': 9900,"
181 "}" <<264 "}" <<
265 "{"
266 " '" ONLINE_ACCOUNTS_INFO_KEY_SERVICE_ID "': 'cool',"
267 "}" <<
182 "Tom" << "cool" << 2 << settings;268 "Tom" << "cool" << 2 << settings;
183}269}
184270
185void ModuleTest::testModelRoles()271void ModuleTest::testModelRoles()
186{272{
187 QFETCH(QString, accountData);273 QFETCH(QString, accountData);
274 QFETCH(QString, serviceData);
188 QFETCH(QString, displayName);275 QFETCH(QString, displayName);
189 QFETCH(QString, serviceId);276 QFETCH(QString, serviceId);
190 QFETCH(int, authenticationMethod);277 QFETCH(int, authenticationMethod);
191 QFETCH(QVariantMap, settings);278 QFETCH(QVariantMap, settings);
192279
193 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})",280 addGetAccountsMethod(QString("ret = ([(1, %1)], [%2])").
194 QString("ret = [(1, %1)]").arg(accountData));281 arg(accountData).arg(serviceData));
195282
196 QQmlEngine engine;283 QQmlEngine engine;
197 QQmlComponent component(&engine);284 QQmlComponent component(&engine);
@@ -218,7 +305,6 @@
218 QCOMPARE(get(model, 0, "serviceId").toString(), serviceId);305 QCOMPARE(get(model, 0, "serviceId").toString(), serviceId);
219 QCOMPARE(get(model, 0, "authenticationMethod").toInt(),306 QCOMPARE(get(model, 0, "authenticationMethod").toInt(),
220 authenticationMethod);307 authenticationMethod);
221 // until https://bugs.launchpad.net/bugs/1479768 is fixed
222 QCOMPARE(get(model, 0, "settings").toMap(), settings);308 QCOMPARE(get(model, 0, "settings").toMap(), settings);
223 QObject *account = get(model, 0, "account").value<QObject*>();309 QObject *account = get(model, 0, "account").value<QObject*>();
224 QVERIFY(account != 0);310 QVERIFY(account != 0);
@@ -226,6 +312,10 @@
226 QCOMPARE(account,312 QCOMPARE(account,
227 model->property("accountList").value<QList<QObject*> >().first());313 model->property("accountList").value<QList<QObject*> >().first());
228314
315 QJSValue service = get(model, 0, "service").value<QJSValue>();
316 QVERIFY(service.isObject());
317 QCOMPARE(service.property("serviceId").toString(), serviceId);
318
229 delete object;319 delete object;
230}320}
231321
@@ -237,17 +327,17 @@
237 QTest::addColumn<QStringList>("expectedDisplayNames");327 QTest::addColumn<QStringList>("expectedDisplayNames");
238328
239 QTest::newRow("no accounts") <<329 QTest::newRow("no accounts") <<
240 "ret = []" <<330 "[]" <<
241 "" <<331 "" <<
242 QList<int>();332 QList<int>();
243333
244 QTest::newRow("one account, no service filter") <<334 QTest::newRow("one account, no service filter") <<
245 "ret = [(1, {'displayName': 'Tom', 'serviceId': 'Foo' })]" <<335 "[(1, {'displayName': 'Tom', 'serviceId': 'Foo' })]" <<
246 "" <<336 "" <<
247 (QList<int>() << 1);337 (QList<int>() << 1);
248338
249 QTest::newRow("one account, with service filter") <<339 QTest::newRow("one account, with service filter") <<
250 "ret = [(1, {'displayName': 'Tom', 'serviceId': 'Foo' })]" <<340 "[(1, {'displayName': 'Tom', 'serviceId': 'Foo' })]" <<
251 "serviceId: \"bar\"" <<341 "serviceId: \"bar\"" <<
252 QList<int>();342 QList<int>();
253}343}
@@ -258,7 +348,7 @@
258 QFETCH(QString, filters);348 QFETCH(QString, filters);
259 QFETCH(QList<int>, expectedIds);349 QFETCH(QList<int>, expectedIds);
260350
261 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})", reply);351 addGetAccountsMethod(QString("ret = (%1, [])").arg(reply));
262352
263 QQmlEngine engine;353 QQmlEngine engine;
264 QQmlComponent component(&engine);354 QQmlComponent component(&engine);
@@ -287,7 +377,7 @@
287377
288void ModuleTest::testModelChanges()378void ModuleTest::testModelChanges()
289{379{
290 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})", "ret = []");380 addGetAccountsMethod("ret = ([], [])");
291 QQmlEngine engine;381 QQmlEngine engine;
292 QQmlComponent component(&engine);382 QQmlComponent component(&engine);
293 component.setData("import Ubuntu.OnlineAccounts 2.0\n"383 component.setData("import Ubuntu.OnlineAccounts 2.0\n"
@@ -397,8 +487,7 @@
397 QFETCH(QVariantMap, expectedAccessReply);487 QFETCH(QVariantMap, expectedAccessReply);
398 QFETCH(QVariantMap, expectedAuthenticationData);488 QFETCH(QVariantMap, expectedAuthenticationData);
399489
400 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})",490 addGetAccountsMethod("ret = ([(1, {'displayName': 'Tom', 'serviceId': 'Foo' })], [])");
401 "ret = [(1, {'displayName': 'Tom', 'serviceId': 'Foo' })]");
402 addMockedMethod("RequestAccess", "sa{sv}", "(ua{sv})a{sv}", reply);491 addMockedMethod("RequestAccess", "sa{sv}", "(ua{sv})a{sv}", reply);
403492
404 QQmlEngine engine;493 QQmlEngine engine;
@@ -536,12 +625,11 @@
536 QFETCH(QVariantMap, params);625 QFETCH(QVariantMap, params);
537 QFETCH(QVariantMap, expectedAuthenticationData);626 QFETCH(QVariantMap, expectedAuthenticationData);
538627
539 addMockedMethod("GetAccounts", "a{sv}", "a(ua{sv})",628 addGetAccountsMethod(QString("ret = ([(1, {"
540 QString("ret = [(1, {"629 " 'displayName': 'Bob',"
541 " 'displayName': 'Bob',"630 " 'serviceId': 'MyService0',"
542 " 'serviceId': 'MyService0',"631 " 'authMethod': %1,"
543 " 'authMethod': %1,"632 "})], [])").arg(authMethod));
544 "})]").arg(authMethod));
545 addMockedMethod("Authenticate", "usbba{sv}", "a{sv}", reply);633 addMockedMethod("Authenticate", "usbba{sv}", "a{sv}", reply);
546634
547 QQmlEngine engine;635 QQmlEngine engine;

Subscribers

People subscribed via source and target branches