accounts-qt  1.15
account.cpp
1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /*
3  * This file is part of libaccounts-qt
4  *
5  * Copyright (C) 2009-2011 Nokia Corporation.
6  * Copyright (C) 2012-2016 Canonical Ltd.
7  *
8  * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public License
12  * version 2.1 as published by the Free Software Foundation.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22  * 02110-1301 USA
23  */
24 
25 #include "account.h"
26 #include "manager.h"
27 #include "manager_p.h"
28 #include "utils.h"
29 
30 #include <QPointer>
31 #include <libaccounts-glib/ag-account.h>
32 
33 namespace Accounts {
34 
75 class Account::Private
76 {
77 public:
78  Private(Manager *manager, const QString &providerName, Account *account);
79  Private(Manager *manager, AgAccount *agAccount);
80 
81  ~Private()
82  {
83  g_cancellable_cancel(m_cancellable);
84  g_object_unref(m_cancellable);
85  m_cancellable = NULL;
86  }
87 
88  void init(Account *account);
89 
90  QPointer<Manager> m_manager;
91  AgAccount *m_account; //real account
92  GCancellable *m_cancellable;
93  QString prefix;
94 
95  static void on_display_name_changed(Account *self);
96  static void on_enabled(Account *self, const gchar *service_name,
97  gboolean enabled);
98  static void account_store_cb(AgAccount *account,
99  GAsyncResult *res,
100  Account *self);
101  static void on_deleted(Account *self);
102 };
103 
104 class Watch::Private
105 {
106 public:
107  static void account_notify_cb(AgAccount *account, const gchar *key,
108  Watch *self);
109 };
110 } //namespace Accounts
111 
112 
113 using namespace Accounts;
114 
115 static QChar slash = QChar::fromLatin1('/');
116 
126 Watch::Watch(QObject *parent):
127  QObject(parent)
128 {
129 }
130 
131 Watch::~Watch()
132 {
133  Account *account = qobject_cast<Account *>(QObject::parent());
134  /* The destructor of Account deletes the child Watches before detaching
135  * them, so here account should always be not NULL */
136  Q_ASSERT(account != NULL);
137  ag_account_remove_watch(account->d->m_account, watch);
138 }
139 
140 Account::Private::Private(Manager *manager, const QString &providerName,
141  Account *account):
142  m_manager(manager),
143  m_cancellable(g_cancellable_new())
144 {
145  m_account = ag_manager_create_account(manager->d->m_manager,
146  providerName.toUtf8().constData());
147  init(account);
148 }
149 
150 Account::Private::Private(Manager *manager, AgAccount *agAccount):
151  m_manager(manager),
152  m_account(agAccount),
153  m_cancellable(g_cancellable_new())
154 {
155 }
156 
157 void Account::Private::init(Account *account)
158 {
159  if (m_account == 0) return;
160  g_signal_connect_swapped(m_account, "display-name-changed",
161  G_CALLBACK(&Private::on_display_name_changed),
162  account);
163  g_signal_connect_swapped(m_account, "enabled",
164  G_CALLBACK(&Private::on_enabled), account);
165  g_signal_connect_swapped(m_account, "deleted",
166  G_CALLBACK(&Private::on_deleted), account);
167 }
168 
169 void Account::Private::on_display_name_changed(Account *self)
170 {
171  const gchar *name = ag_account_get_display_name(self->d->m_account);
172 
173  Q_EMIT self->displayNameChanged(UTF8(name));
174 }
175 
176 void Account::Private::on_enabled(Account *self, const gchar *service_name,
177  gboolean enabled)
178 {
179  Q_EMIT self->enabledChanged(UTF8(service_name), enabled);
180 }
181 
182 void Account::Private::on_deleted(Account *self)
183 {
184  Q_EMIT self->removed();
185 }
186 
202 Account::Account(Manager *manager, const QString &providerName,
203  QObject *parent):
204  QObject(parent),
205  d(new Private(manager, providerName, this))
206 {
207 }
208 
209 Account::Account(Private *d, QObject *parent):
210  QObject(parent),
211  d(d)
212 {
213  d->init(this);
214 }
215 
225 Account *Account::fromId(Manager *manager, AccountId id, QObject *parent)
226 {
227  GError *error = 0;
228  AgAccount *account = ag_manager_load_account(manager->d->m_manager, id,
229  &error);
230  if (account == 0) {
231  Q_ASSERT(error != 0);
232  manager->d->lastError = Error(error);
233  g_error_free(error);
234  return 0;
235  }
236  Q_ASSERT(error == 0);
237  return new Account(new Private(manager, account), parent);
238 }
239 
243 Account::~Account()
244 {
245  QObjectList list = children();
246  for (int i = 0; i < list.count(); i++)
247  {
248  QObject *o = list.at(i);
249  if (qobject_cast<Watch *>(o))
250  delete o;
251  }
252 
253  g_signal_handlers_disconnect_by_func
254  (d->m_account, (void *)&Private::on_display_name_changed, this);
255  g_signal_handlers_disconnect_by_func
256  (d->m_account, (void *)&Private::on_enabled, this);
257  g_signal_handlers_disconnect_by_func
258  (d->m_account, (void *)&Private::on_deleted, this);
259  g_object_unref(d->m_account);
260  delete d;
261  d = 0;
262 }
263 
268 AccountId Account::id() const
269 {
270  return d->m_account ? d->m_account->id : 0;
271 }
272 
276 Manager *Account::manager() const
277 {
278  return d->m_manager;
279 }
280 
284 bool Account::supportsService(const QString &serviceType) const
285 {
286  return ag_account_supports_service(d->m_account,
287  serviceType.toUtf8().constData());
288 }
289 
298 ServiceList Account::services(const QString &serviceType) const
299 {
300  GList *list;
301  if (serviceType.isEmpty()) {
302  list = ag_account_list_services(d->m_account);
303  } else {
304  list = ag_account_list_services_by_type(d->m_account,
305  serviceType.toUtf8().constData());
306  }
307 
308  /* convert glist -> ServiceList */
309  ServiceList servList;
310  GList *iter;
311  for (iter = list; iter; iter = iter->next)
312  {
313  AgService *service = (AgService*)iter->data;
314  servList.append(Service(service, StealReference));
315  }
316 
317  g_list_free(list);
318 
319  return servList;
320 }
321 
327 ServiceList Account::enabledServices() const
328 {
329  GList *list;
330  list = ag_account_list_enabled_services(d->m_account);
331 
332  /* convert glist -> ServiceList */
333  ServiceList servList;
334  GList *iter;
335  for (iter = list; iter; iter = g_list_next(iter))
336  {
337  AgService *service = (AgService*)iter->data;
338  servList.append(Service(service, StealReference));
339  }
340 
341  g_list_free(list);
342 
343  return servList;
344 }
345 
356 bool Account::enabled() const
357 {
358  return isEnabled();
359 }
360 
367 bool Account::isEnabled() const
368 {
369  return ag_account_get_enabled(d->m_account);
370 }
371 
379 void Account::setEnabled(bool enabled)
380 {
381  ag_account_set_enabled(d->m_account, enabled);
382 }
383 
389 QString Account::displayName() const
390 {
391  return UTF8(ag_account_get_display_name(d->m_account));
392 }
393 
398 void Account::setDisplayName(const QString &displayName)
399 {
400  ag_account_set_display_name(d->m_account,
401  displayName.toUtf8().constData());
402 }
403 
407 QString Account::providerName() const
408 {
409  return UTF8(ag_account_get_provider_name(d->m_account));
410 }
411 
415 Provider Account::provider() const
416 {
417  return manager()->provider(providerName());
418 }
419 
425 void Account::selectService(const Service &service)
426 {
427  AgService *agService = NULL;
428 
429  if (service.isValid())
430  agService = service.service();
431 
432  ag_account_select_service(d->m_account, agService);
433  d->prefix = QString();
434 }
435 
439 Service Account::selectedService() const
440 {
441  AgService *agService = ag_account_get_selected_service(d->m_account);
442  return Service(agService);
443 }
444 
450 QStringList Account::allKeys() const
451 {
452  QStringList allKeys;
453  AgAccountSettingIter iter;
454  const gchar *key;
455  GVariant *val;
456 
457  /* iterate the settings */
458  QByteArray tmp = d->prefix.toLatin1();
459  ag_account_settings_iter_init(d->m_account, &iter, tmp.constData());
460  while (ag_account_settings_iter_get_next(&iter, &key, &val))
461  {
462  allKeys.append(QString(ASCII(key)));
463  }
464  return allKeys;
465 }
466 
473 void Account::beginGroup(const QString &prefix)
474 {
475  d->prefix += prefix + slash;
476 }
477 
483 QStringList Account::childGroups() const
484 {
485  QStringList groups, all_keys;
486 
487  all_keys = allKeys();
488  Q_FOREACH (const QString &key, all_keys)
489  {
490  if (key.contains(slash)) {
491  QString group = key.section(slash, 0, 0);
492  if (!groups.contains(group))
493  groups.append(group);
494  }
495  }
496  return groups;
497 }
498 
504 QStringList Account::childKeys() const
505 {
506  QStringList keys, all_keys;
507 
508  all_keys = allKeys();
509  Q_FOREACH (const QString &key, all_keys)
510  {
511  if (!key.contains(slash))
512  keys.append(key);
513  }
514  return keys;
515 }
516 
521 void Account::clear()
522 {
523  /* clear() must ignore the group: so, temporarily reset it and call
524  * remove("") */
525  QString saved_prefix = d->prefix;
526  d->prefix = QString();
527  remove(QString());
528  d->prefix = saved_prefix;
529 }
530 
537 bool Account::contains(const QString &key) const
538 {
539  return childKeys().contains(key);
540 }
541 
547 void Account::endGroup()
548 {
549  d->prefix = d->prefix.section(slash, 0, -3,
550  QString::SectionIncludeTrailingSep);
551  if (d->prefix[0] == slash) d->prefix.remove(0, 1);
552 }
553 
559 QString Account::group() const
560 {
561  if (d->prefix.endsWith(slash))
562  return d->prefix.left(d->prefix.size() - 1);
563  return d->prefix;
564 }
565 
569 bool Account::isWritable() const
570 {
571  return true;
572 }
573 
581 void Account::remove(const QString &key)
582 {
583  if (key.isEmpty())
584  {
585  /* delete all keys in the group */
586  QStringList keys = allKeys();
587  Q_FOREACH (const QString &key, keys)
588  {
589  if (!key.isEmpty())
590  remove(key);
591  }
592  }
593  else
594  {
595  QString full_key = d->prefix + key;
596  QByteArray tmpkey = full_key.toLatin1();
597  ag_account_set_variant(d->m_account, tmpkey.constData(), NULL);
598  }
599 }
600 
608 void Account::setValue(const QString &key, const QVariant &value)
609 {
610  GVariant *variant = qVariantToGVariant(value);
611  if (variant == 0) {
612  return;
613  }
614 
615  QString full_key = d->prefix + key;
616  QByteArray tmpkey = full_key.toLatin1();
617  ag_account_set_variant(d->m_account, tmpkey.constData(), variant);
618 }
619 
620 void Account::Private::account_store_cb(AgAccount *account,
621  GAsyncResult *res,
622  Account *self)
623 {
624  GError *error = NULL;
625  ag_account_store_finish(account, res, &error);
626  if (error) {
627  if (error->domain == G_IO_ERROR &&
628  error->code == G_IO_ERROR_CANCELLED) {
629  } else {
630  Q_EMIT self->error(Error(error));
631  }
632  g_error_free(error);
633  } else {
634  Q_EMIT self->synced();
635  }
636 }
637 
652 QVariant Account::value(const QString &key, const QVariant &defaultValue,
653  SettingSource *source) const
654 {
655  QString full_key = d->prefix + key;
656  QByteArray ba = full_key.toLatin1();
657  AgSettingSource settingSource;
658  GVariant *variant =
659  ag_account_get_variant(d->m_account, ba.constData(), &settingSource);
660  if (source != 0) {
661  switch (settingSource) {
662  case AG_SETTING_SOURCE_ACCOUNT: *source = ACCOUNT; break;
663  case AG_SETTING_SOURCE_PROFILE: *source = TEMPLATE; break;
664  default: *source = NONE; break;
665  }
666  }
667 
668  return (variant != 0) ? gVariantToQVariant(variant) : defaultValue;
669 }
670 
686 SettingSource Account::value(const QString &key, QVariant &value) const
687 {
688  SettingSource source;
689  QVariant variant = this->value(key, QVariant(), &source);
690  if (variant.isValid()) {
691  if (value.type() != variant.type()) {
692  if (!variant.convert(value.type())) source = NONE;
693  }
694  value = variant;
695  }
696 
697  return source;
698 }
699 
709 QString Account::valueAsString(const QString &key,
710  QString default_value,
711  SettingSource *source) const
712 {
713  QVariant var = default_value;
714  SettingSource src = value(key, var);
715  if (source)
716  *source = src;
717  return var.toString();
718 }
719 
729 int Account::valueAsInt(const QString &key,
730  int default_value,
731  SettingSource *source) const
732 {
733  QVariant var = default_value;
734  SettingSource src = value(key, var);
735  if (source)
736  *source = src;
737  return var.toInt();
738 }
739 
749 quint64 Account::valueAsUInt64(const QString &key,
750  quint64 default_value,
751  SettingSource *source) const
752 {
753  QVariant var = default_value;
754  SettingSource src = value(key, var);
755  if (source)
756  *source = src;
757  return var.toULongLong();
758 }
759 
769 bool Account::valueAsBool(const QString &key,
770  bool default_value,
771  SettingSource *source) const
772 {
773  QVariant var = default_value;
774  SettingSource src = value(key, var);
775  if (source)
776  *source = src;
777  return var.toBool();
778 }
779 
780 void Watch::Private::account_notify_cb(AgAccount *account, const gchar *key,
781  Watch *watch)
782 {
783  Q_EMIT watch->notify(key);
784 
785  Q_UNUSED(account);
786 }
787 
798 Watch *Account::watchKey(const QString &key)
799 {
800  AgAccountWatch ag_watch;
801  Watch *watch = new Watch(this);
802 
803  if (!key.isEmpty())
804  {
805  QString full_key = d->prefix + key;
806  ag_watch = ag_account_watch_key
807  (d->m_account, full_key.toLatin1().constData(),
808  (AgAccountNotifyCb)&Watch::Private::account_notify_cb, watch);
809  }
810  else
811  {
812  ag_watch = ag_account_watch_dir
813  (d->m_account, d->prefix.toLatin1().constData(),
814  (AgAccountNotifyCb)&Watch::Private::account_notify_cb, watch);
815  }
816 
817  if (!ag_watch)
818  {
819  delete watch;
820  return NULL;
821  }
822 
823  watch->setWatch(ag_watch);
824  return watch;
825 }
826 
839 void Account::sync()
840 {
841  ag_account_store_async(d->m_account,
842  d->m_cancellable,
843  (GAsyncReadyCallback)&Private::account_store_cb,
844  this);
845 }
846 
854 bool Account::syncAndBlock()
855 {
856  GError *error = NULL;
857  bool ret;
858 
859  ret = ag_account_store_blocking(d->m_account, &error);
860  if (error)
861  {
862  qWarning() << "Store operation failed: " << error->message;
863  g_error_free(error);
864  }
865 
866  return ret;
867 }
868 
873 void Account::remove()
874 {
875  ag_account_delete(d->m_account);
876 }
877 
887 void Account::sign(const QString &key, const char *token)
888 {
889  ag_account_sign (d->m_account, key.toUtf8().constData(), token);
890 }
891 
903 bool Account::verify(const QString &key, const char **token)
904 {
905  return ag_account_verify(d->m_account, key.toUtf8().constData(), token);
906 }
907 
920 bool Account::verifyWithTokens(const QString &key, QList<const char*> tokens)
921 {
922  int tokensCount = tokens.count();
923 
924  const char *tmp[tokensCount + 1];
925 
926  for (int i = 0; i < tokensCount; ++i)
927  {
928  tmp[i] = tokens.at(i);
929  }
930  tmp[tokensCount] = NULL;
931 
932  return ag_account_verify_with_tokens(d->m_account, key.toUtf8().constData(), tmp);
933 }
934 
935 uint Account::credentialsId()
936 {
937  QString key = ACCOUNTS_KEY_CREDENTIALS_ID;
938  QVariant val(QVariant::Int);
939 
940  if (value(key, val) != NONE)
941  return val.toUInt();
942 
943  uint id = 0;
944  Service service = selectedService();
945  if (service.isValid()) {
946  selectService();
947  if (value(key, val) != NONE)
948  id = val.toUInt();
949  selectService(service);
950  }
951  return id;
952 }
953 
954 AgAccount *Account::account()
955 {
956  return d->m_account;
957 }
QStringList allKeys() const
Return all the keys in the current group.
Manager of accounts, services and providers.
Definition: manager.h:51
Provider provider(const QString &providerName) const
Gets an object representing a provider.
Definition: manager.cpp:421
Monitors an account key or group of keys.
Definition: account.h:70
bool isEnabled() const
Check whether the account service is enabled.
Service service() const
Return the Service.
QStringList childKeys() const
Return all the keys which are direct children of the current group.
Representation of an account provider.
Definition: provider.h:48
QString group() const
Return the name of the current group.
bool enabled() const
Check whether the account service is enabled.
Representation of an account service.
Definition: service.h:48
Error lastError() const
Gets the last error.
Definition: manager.cpp:583
QVariant value(const QString &key, const QVariant &defaultValue, SettingSource *source=0) const
Retrieves the value of an account setting, as a QVariant.
bool isValid() const
Check whether this object represents a Service.
Definition: service.cpp:104
Base object definition for accounts error handling.
Definition: error.h:43
Account * account() const
Return the Account.