2
* This file is part of libOnlineAccounts
4
* Copyright (C) 2015 Canonical Ltd.
6
* Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
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.
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.
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/>.
21
#include "manager_p.h"
23
#include <QDBusConnection>
24
#include <QDBusMessage>
25
#include <QDBusPendingCallWatcher>
27
#include "account_p.h"
28
#include "authentication_data_p.h"
29
#include "dbus_constants.h"
30
#include "pending_call_p.h"
32
using namespace OnlineAccounts;
34
ManagerPrivate::ManagerPrivate(Manager *q, const QString &applicationId):
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()),
44
qRegisterMetaType<Account*>();
46
QObject::connect(&m_daemon,
47
SIGNAL(accountChanged(const QString&, const OnlineAccounts::AccountInfo&)),
49
SLOT(onAccountChanged(const QString&, const OnlineAccounts::AccountInfo&)));
53
ManagerPrivate::~ManagerPrivate()
55
delete m_getAccountsCall;
56
m_getAccountsCall = 0;
59
PendingCall ManagerPrivate::authenticate(const AccountInfo &info,
60
const AuthenticationData &authData)
63
QDBusPendingCall call = m_daemon.authenticate(info.id(),
65
authData.interactive(),
66
authData.mustInvalidateCachedReply(),
67
authData.d->m_parameters);
68
return PendingCall(new PendingCallPrivate(q, call,
69
PendingCallPrivate::Authenticate,
73
PendingCall ManagerPrivate::requestAccess(const QString &service,
74
const QVariantMap ¶meters)
77
QDBusPendingCall call = m_daemon.requestAccess(service, parameters);
78
return PendingCall(new PendingCallPrivate(q, call,
79
PendingCallPrivate::RequestAccess,
80
AuthenticationMethodUnknown));
83
Account *ManagerPrivate::ensureAccount(const AccountInfo &info)
85
if (Q_UNLIKELY(info.id() == 0)) return 0;
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));
92
AccountData &accountData = i.value();
93
accountData.info = info.stripMetadata();
94
if (!accountData.account) {
96
new Account(new AccountPrivate(q_ptr, accountData.info), this);
98
/* Update the account information */
99
accountData.account->d_ptr->update(accountData.info);
102
return accountData.account;
105
void ManagerPrivate::retrieveAccounts()
107
if (Q_UNLIKELY(m_getAccountsCall)) return;
110
filters["applicationId"] = m_applicationId;
112
new QDBusPendingCallWatcher(m_daemon.getAccounts(filters));
113
QObject::connect(m_getAccountsCall,
114
SIGNAL(finished(QDBusPendingCallWatcher*)),
115
this, SLOT(onGetAccountsFinished()));
118
void ManagerPrivate::onGetAccountsFinished()
122
Q_ASSERT(m_getAccountsCall);
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
130
QList<AccountInfo> accountInfos = reply.argumentAt<0>();
131
Q_FOREACH(const AccountInfo &info, accountInfos) {
132
m_accounts.insert(info.id(), AccountData(info));
135
m_getAccountsCall->deleteLater();
136
m_getAccountsCall = 0;
141
void ManagerPrivate::onAccountChanged(const QString &service,
142
const AccountInfo &info)
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
156
m_accounts.remove(info.id());
159
/* No need to handle the Update change type: ensureAccount already updates
160
* the account and emits the necessary notification */
163
Manager::Manager(const QString &applicationId, QObject *parent):
165
d_ptr(new ManagerPrivate(this, applicationId))
175
bool Manager::isReady() const
178
return !d->m_getAccountsCall;
181
void Manager::waitForReady()
184
if (d->m_getAccountsCall) {
185
d->m_getAccountsCall->waitForFinished();
189
QList<Account*> Manager::availableAccounts(const QString &service)
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;
199
if (!accountData.account) {
200
accountData.account =
201
new Account(new AccountPrivate(this, accountData.info), this);
204
result.append(accountData.account);
210
Account *Manager::account(AccountId accountId)
214
QHash<AccountId,AccountData>::iterator i = d->m_accounts.find(accountId);
215
if (Q_UNLIKELY(i == d->m_accounts.end())) return 0;
217
AccountData &accountData = i.value();
218
if (!accountData.account) {
219
accountData.account =
220
new Account(new AccountPrivate(this, accountData.info), this);
223
return accountData.account;
226
PendingCall Manager::requestAccess(const QString &service,
227
const AuthenticationData &authData)
230
return d->requestAccess(service, authData.d->m_parameters);