~ci-train-bot/online-accounts-api/online-accounts-api-ubuntu-xenial-landing-033

« back to all changes in this revision

Viewing changes to src/lib/OnlineAccounts/manager.cpp

  • Committer: Alberto Mardegan
  • Date: 2015-04-28 17:01:03 UTC
  • mfrom: (5.1.30 qt-api-impl)
  • Revision ID: alberto.mardegan@canonical.com-20150428170103-9hty50555f6e7uz6
Qt client API implementation

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of libOnlineAccounts
 
3
 *
 
4
 * Copyright (C) 2015 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 "manager_p.h"
 
22
 
 
23
#include <QDBusConnection>
 
24
#include <QDBusMessage>
 
25
#include <QDBusPendingCallWatcher>
 
26
#include <QDebug>
 
27
#include "account_p.h"
 
28
#include "authentication_data_p.h"
 
29
#include "dbus_constants.h"
 
30
#include "pending_call_p.h"
 
31
 
 
32
using namespace OnlineAccounts;
 
33
 
 
34
ManagerPrivate::ManagerPrivate(Manager *q, const QString &applicationId):
 
35
    QObject(),
 
36
    m_applicationId(applicationId),
 
37
    m_daemon(ONLINE_ACCOUNTS_MANAGER_SERVICE_NAME,
 
38
             ONLINE_ACCOUNTS_MANAGER_PATH,
 
39
             ONLINE_ACCOUNTS_MANAGER_INTERFACE,
 
40
             QDBusConnection::sessionBus()),
 
41
    m_getAccountsCall(0),
 
42
    q_ptr(q)
 
43
{
 
44
    qRegisterMetaType<Account*>();
 
45
 
 
46
    QObject::connect(&m_daemon,
 
47
                     SIGNAL(accountChanged(const QString&, const OnlineAccounts::AccountInfo&)),
 
48
                     this,
 
49
                     SLOT(onAccountChanged(const QString&, const OnlineAccounts::AccountInfo&)));
 
50
    retrieveAccounts();
 
51
}
 
52
 
 
53
ManagerPrivate::~ManagerPrivate()
 
54
{
 
55
    delete m_getAccountsCall;
 
56
    m_getAccountsCall = 0;
 
57
}
 
58
 
 
59
PendingCall ManagerPrivate::authenticate(const AccountInfo &info,
 
60
                                         const AuthenticationData &authData)
 
61
{
 
62
    Q_Q(Manager);
 
63
    QDBusPendingCall call = m_daemon.authenticate(info.id(),
 
64
                                                  info.service(),
 
65
                                                  authData.interactive(),
 
66
                                                  authData.mustInvalidateCachedReply(),
 
67
                                                  authData.d->m_parameters);
 
68
    return PendingCall(new PendingCallPrivate(q, call,
 
69
                                              PendingCallPrivate::Authenticate,
 
70
                                              authData.method()));
 
71
}
 
72
 
 
73
PendingCall ManagerPrivate::requestAccess(const QString &service,
 
74
                                          const QVariantMap &parameters)
 
75
{
 
76
    Q_Q(Manager);
 
77
    QDBusPendingCall call = m_daemon.requestAccess(service, parameters);
 
78
    return PendingCall(new PendingCallPrivate(q, call,
 
79
                                              PendingCallPrivate::RequestAccess,
 
80
                                              AuthenticationMethodUnknown));
 
81
}
 
82
 
 
83
Account *ManagerPrivate::ensureAccount(const AccountInfo &info)
 
84
{
 
85
    if (Q_UNLIKELY(info.id() == 0)) return 0;
 
86
 
 
87
    QHash<AccountId,AccountData>::iterator i = m_accounts.find(info.id());
 
88
    if (i == m_accounts.end()) {
 
89
        i = m_accounts.insert(info.id(), AccountData(info));
 
90
    }
 
91
 
 
92
    AccountData &accountData = i.value();
 
93
    accountData.info = info.stripMetadata();
 
94
    if (!accountData.account) {
 
95
        accountData.account =
 
96
            new Account(new AccountPrivate(q_ptr, accountData.info), this);
 
97
    } else {
 
98
        /* Update the account information */
 
99
        accountData.account->d_ptr->update(accountData.info);
 
100
    }
 
101
 
 
102
    return accountData.account;
 
103
}
 
104
 
 
105
void ManagerPrivate::retrieveAccounts()
 
106
{
 
107
    if (Q_UNLIKELY(m_getAccountsCall)) return;
 
108
 
 
109
    QVariantMap filters;
 
110
    filters["applicationId"] = m_applicationId;
 
111
    m_getAccountsCall =
 
112
        new QDBusPendingCallWatcher(m_daemon.getAccounts(filters));
 
113
    QObject::connect(m_getAccountsCall,
 
114
                     SIGNAL(finished(QDBusPendingCallWatcher*)),
 
115
                     this, SLOT(onGetAccountsFinished()));
 
116
}
 
117
 
 
118
void ManagerPrivate::onGetAccountsFinished()
 
119
{
 
120
    Q_Q(Manager);
 
121
 
 
122
    Q_ASSERT(m_getAccountsCall);
 
123
 
 
124
    QDBusPendingReply<QList<AccountInfo> > reply = *m_getAccountsCall;
 
125
    if (Q_UNLIKELY(reply.isError())) {
 
126
        qWarning() << "GetAccounts call failed:" << reply.error();
 
127
        /* No special handling of the error: the Manager will simply not have
 
128
         * any account */
 
129
    } else {
 
130
        QList<AccountInfo> accountInfos = reply.argumentAt<0>();
 
131
        Q_FOREACH(const AccountInfo &info, accountInfos) {
 
132
            m_accounts.insert(info.id(), AccountData(info));
 
133
        }
 
134
    }
 
135
    m_getAccountsCall->deleteLater();
 
136
    m_getAccountsCall = 0;
 
137
 
 
138
    Q_EMIT q->ready();
 
139
}
 
140
 
 
141
void ManagerPrivate::onAccountChanged(const QString &service,
 
142
                                      const AccountInfo &info)
 
143
{
 
144
    Q_Q(Manager);
 
145
    Q_UNUSED(service);
 
146
 
 
147
    Account *account = ensureAccount(info);
 
148
    if (info.changeType() == AccountInfo::Enabled) {
 
149
        Q_EMIT q->accountAvailable(account);
 
150
    } else if (info.changeType() == AccountInfo::Disabled) {
 
151
        account->d_ptr->setInvalid();
 
152
        /* We don't delete the account, since the client might be using it, but
 
153
         * we remove it from our list so that we won't return it to the client
 
154
         * anymore.
 
155
         */
 
156
        m_accounts.remove(info.id());
 
157
    }
 
158
 
 
159
    /* No need to handle the Update change type: ensureAccount already updates
 
160
     * the account and emits the necessary notification */
 
161
}
 
162
 
 
163
Manager::Manager(const QString &applicationId, QObject *parent):
 
164
    QObject(parent),
 
165
    d_ptr(new ManagerPrivate(this, applicationId))
 
166
{
 
167
}
 
168
 
 
169
Manager::~Manager()
 
170
{
 
171
    delete d_ptr;
 
172
    d_ptr = 0;
 
173
}
 
174
 
 
175
bool Manager::isReady() const
 
176
{
 
177
    Q_D(const Manager);
 
178
    return !d->m_getAccountsCall;
 
179
}
 
180
 
 
181
void Manager::waitForReady()
 
182
{
 
183
    Q_D(Manager);
 
184
    if (d->m_getAccountsCall) {
 
185
        d->m_getAccountsCall->waitForFinished();
 
186
    }
 
187
}
 
188
 
 
189
QList<Account*> Manager::availableAccounts(const QString &service)
 
190
{
 
191
    Q_D(Manager);
 
192
 
 
193
    QList<Account*> result;
 
194
    for (QHash<AccountId,AccountData>::iterator i = d->m_accounts.begin();
 
195
         i != d->m_accounts.end(); i++) {
 
196
        AccountData &accountData = i.value();
 
197
        if (!service.isEmpty() && accountData.info.service() != service) continue;
 
198
 
 
199
        if (!accountData.account) {
 
200
            accountData.account =
 
201
                new Account(new AccountPrivate(this, accountData.info), this);
 
202
        }
 
203
 
 
204
        result.append(accountData.account);
 
205
    }
 
206
 
 
207
    return result;
 
208
}
 
209
 
 
210
Account *Manager::account(AccountId accountId)
 
211
{
 
212
    Q_D(Manager);
 
213
 
 
214
    QHash<AccountId,AccountData>::iterator i = d->m_accounts.find(accountId);
 
215
    if (Q_UNLIKELY(i == d->m_accounts.end())) return 0;
 
216
 
 
217
    AccountData &accountData = i.value();
 
218
    if (!accountData.account) {
 
219
        accountData.account =
 
220
            new Account(new AccountPrivate(this, accountData.info), this);
 
221
    }
 
222
 
 
223
    return accountData.account;
 
224
}
 
225
 
 
226
PendingCall Manager::requestAccess(const QString &service,
 
227
                                   const AuthenticationData &authData)
 
228
{
 
229
    Q_D(Manager);
 
230
    return d->requestAccess(service, authData.d->m_parameters);
 
231
}