accounts-qt
1.15
|
00001 /* vi: set et sw=4 ts=4 cino=t0,(0: */ 00002 /* 00003 * This file is part of libaccounts-qt 00004 * 00005 * Copyright (C) 2009-2011 Nokia Corporation. 00006 * Copyright (C) 2012-2016 Canonical Ltd. 00007 * 00008 * Contact: Alberto Mardegan <alberto.mardegan@canonical.com> 00009 * 00010 * This library is free software; you can redistribute it and/or 00011 * modify it under the terms of the GNU Lesser General Public License 00012 * version 2.1 as published by the Free Software Foundation. 00013 * 00014 * This library is distributed in the hope that it will be useful, but 00015 * WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Lesser General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Lesser General Public 00020 * License along with this library; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 00022 * 02110-1301 USA 00023 */ 00024 00025 #include "account.h" 00026 #include "manager.h" 00027 #include "manager_p.h" 00028 #include "utils.h" 00029 00030 #include <QPointer> 00031 #include <libaccounts-glib/ag-account.h> 00032 00033 namespace Accounts { 00034 00075 class Account::Private 00076 { 00077 public: 00078 Private(Manager *manager, const QString &providerName, Account *account); 00079 Private(Manager *manager, AgAccount *agAccount); 00080 00081 ~Private() 00082 { 00083 g_cancellable_cancel(m_cancellable); 00084 g_object_unref(m_cancellable); 00085 m_cancellable = NULL; 00086 } 00087 00088 void init(Account *account); 00089 00090 QPointer<Manager> m_manager; 00091 AgAccount *m_account; //real account 00092 GCancellable *m_cancellable; 00093 QString prefix; 00094 00095 static void on_display_name_changed(Account *self); 00096 static void on_enabled(Account *self, const gchar *service_name, 00097 gboolean enabled); 00098 static void account_store_cb(AgAccount *account, 00099 GAsyncResult *res, 00100 Account *self); 00101 static void on_deleted(Account *self); 00102 }; 00103 00104 class Watch::Private 00105 { 00106 public: 00107 static void account_notify_cb(AgAccount *account, const gchar *key, 00108 Watch *self); 00109 }; 00110 } //namespace Accounts 00111 00112 00113 using namespace Accounts; 00114 00115 static QChar slash = QChar::fromLatin1('/'); 00116 00126 Watch::Watch(QObject *parent): 00127 QObject(parent) 00128 { 00129 } 00130 00131 Watch::~Watch() 00132 { 00133 Account *account = qobject_cast<Account *>(QObject::parent()); 00134 /* The destructor of Account deletes the child Watches before detaching 00135 * them, so here account should always be not NULL */ 00136 Q_ASSERT(account != NULL); 00137 ag_account_remove_watch(account->d->m_account, watch); 00138 } 00139 00140 Account::Private::Private(Manager *manager, const QString &providerName, 00141 Account *account): 00142 m_manager(manager), 00143 m_cancellable(g_cancellable_new()) 00144 { 00145 m_account = ag_manager_create_account(manager->d->m_manager, 00146 providerName.toUtf8().constData()); 00147 init(account); 00148 } 00149 00150 Account::Private::Private(Manager *manager, AgAccount *agAccount): 00151 m_manager(manager), 00152 m_account(agAccount), 00153 m_cancellable(g_cancellable_new()) 00154 { 00155 } 00156 00157 void Account::Private::init(Account *account) 00158 { 00159 if (m_account == 0) return; 00160 g_signal_connect_swapped(m_account, "display-name-changed", 00161 G_CALLBACK(&Private::on_display_name_changed), 00162 account); 00163 g_signal_connect_swapped(m_account, "enabled", 00164 G_CALLBACK(&Private::on_enabled), account); 00165 g_signal_connect_swapped(m_account, "deleted", 00166 G_CALLBACK(&Private::on_deleted), account); 00167 } 00168 00169 void Account::Private::on_display_name_changed(Account *self) 00170 { 00171 const gchar *name = ag_account_get_display_name(self->d->m_account); 00172 00173 Q_EMIT self->displayNameChanged(UTF8(name)); 00174 } 00175 00176 void Account::Private::on_enabled(Account *self, const gchar *service_name, 00177 gboolean enabled) 00178 { 00179 Q_EMIT self->enabledChanged(UTF8(service_name), enabled); 00180 } 00181 00182 void Account::Private::on_deleted(Account *self) 00183 { 00184 Q_EMIT self->removed(); 00185 } 00186 00202 Account::Account(Manager *manager, const QString &providerName, 00203 QObject *parent): 00204 QObject(parent), 00205 d(new Private(manager, providerName, this)) 00206 { 00207 } 00208 00209 Account::Account(Private *d, QObject *parent): 00210 QObject(parent), 00211 d(d) 00212 { 00213 d->init(this); 00214 } 00215 00225 Account *Account::fromId(Manager *manager, AccountId id, QObject *parent) 00226 { 00227 GError *error = 0; 00228 AgAccount *account = ag_manager_load_account(manager->d->m_manager, id, 00229 &error); 00230 if (account == 0) { 00231 Q_ASSERT(error != 0); 00232 manager->d->lastError = Error(error); 00233 g_error_free(error); 00234 return 0; 00235 } 00236 Q_ASSERT(error == 0); 00237 return new Account(new Private(manager, account), parent); 00238 } 00239 00243 Account::~Account() 00244 { 00245 QObjectList list = children(); 00246 for (int i = 0; i < list.count(); i++) 00247 { 00248 QObject *o = list.at(i); 00249 if (qobject_cast<Watch *>(o)) 00250 delete o; 00251 } 00252 00253 g_signal_handlers_disconnect_by_func 00254 (d->m_account, (void *)&Private::on_display_name_changed, this); 00255 g_signal_handlers_disconnect_by_func 00256 (d->m_account, (void *)&Private::on_enabled, this); 00257 g_signal_handlers_disconnect_by_func 00258 (d->m_account, (void *)&Private::on_deleted, this); 00259 g_object_unref(d->m_account); 00260 delete d; 00261 d = 0; 00262 } 00263 00268 AccountId Account::id() const 00269 { 00270 return d->m_account ? d->m_account->id : 0; 00271 } 00272 00276 Manager *Account::manager() const 00277 { 00278 return d->m_manager; 00279 } 00280 00284 bool Account::supportsService(const QString &serviceType) const 00285 { 00286 return ag_account_supports_service(d->m_account, 00287 serviceType.toUtf8().constData()); 00288 } 00289 00298 ServiceList Account::services(const QString &serviceType) const 00299 { 00300 GList *list; 00301 if (serviceType.isEmpty()) { 00302 list = ag_account_list_services(d->m_account); 00303 } else { 00304 list = ag_account_list_services_by_type(d->m_account, 00305 serviceType.toUtf8().constData()); 00306 } 00307 00308 /* convert glist -> ServiceList */ 00309 ServiceList servList; 00310 GList *iter; 00311 for (iter = list; iter; iter = iter->next) 00312 { 00313 AgService *service = (AgService*)iter->data; 00314 servList.append(Service(service, StealReference)); 00315 } 00316 00317 g_list_free(list); 00318 00319 return servList; 00320 } 00321 00327 ServiceList Account::enabledServices() const 00328 { 00329 GList *list; 00330 list = ag_account_list_enabled_services(d->m_account); 00331 00332 /* convert glist -> ServiceList */ 00333 ServiceList servList; 00334 GList *iter; 00335 for (iter = list; iter; iter = g_list_next(iter)) 00336 { 00337 AgService *service = (AgService*)iter->data; 00338 servList.append(Service(service, StealReference)); 00339 } 00340 00341 g_list_free(list); 00342 00343 return servList; 00344 } 00345 00356 bool Account::enabled() const 00357 { 00358 return isEnabled(); 00359 } 00360 00367 bool Account::isEnabled() const 00368 { 00369 return ag_account_get_enabled(d->m_account); 00370 } 00371 00379 void Account::setEnabled(bool enabled) 00380 { 00381 ag_account_set_enabled(d->m_account, enabled); 00382 } 00383 00389 QString Account::displayName() const 00390 { 00391 return UTF8(ag_account_get_display_name(d->m_account)); 00392 } 00393 00398 void Account::setDisplayName(const QString &displayName) 00399 { 00400 ag_account_set_display_name(d->m_account, 00401 displayName.toUtf8().constData()); 00402 } 00403 00407 QString Account::providerName() const 00408 { 00409 return UTF8(ag_account_get_provider_name(d->m_account)); 00410 } 00411 00415 Provider Account::provider() const 00416 { 00417 return manager()->provider(providerName()); 00418 } 00419 00425 void Account::selectService(const Service &service) 00426 { 00427 AgService *agService = NULL; 00428 00429 if (service.isValid()) 00430 agService = service.service(); 00431 00432 ag_account_select_service(d->m_account, agService); 00433 d->prefix = QString(); 00434 } 00435 00439 Service Account::selectedService() const 00440 { 00441 AgService *agService = ag_account_get_selected_service(d->m_account); 00442 return Service(agService); 00443 } 00444 00450 QStringList Account::allKeys() const 00451 { 00452 QStringList allKeys; 00453 AgAccountSettingIter iter; 00454 const gchar *key; 00455 GVariant *val; 00456 00457 /* iterate the settings */ 00458 QByteArray tmp = d->prefix.toLatin1(); 00459 ag_account_settings_iter_init(d->m_account, &iter, tmp.constData()); 00460 while (ag_account_settings_iter_get_next(&iter, &key, &val)) 00461 { 00462 allKeys.append(QString(ASCII(key))); 00463 } 00464 return allKeys; 00465 } 00466 00473 void Account::beginGroup(const QString &prefix) 00474 { 00475 d->prefix += prefix + slash; 00476 } 00477 00483 QStringList Account::childGroups() const 00484 { 00485 QStringList groups, all_keys; 00486 00487 all_keys = allKeys(); 00488 Q_FOREACH (const QString &key, all_keys) 00489 { 00490 if (key.contains(slash)) { 00491 QString group = key.section(slash, 0, 0); 00492 if (!groups.contains(group)) 00493 groups.append(group); 00494 } 00495 } 00496 return groups; 00497 } 00498 00504 QStringList Account::childKeys() const 00505 { 00506 QStringList keys, all_keys; 00507 00508 all_keys = allKeys(); 00509 Q_FOREACH (const QString &key, all_keys) 00510 { 00511 if (!key.contains(slash)) 00512 keys.append(key); 00513 } 00514 return keys; 00515 } 00516 00521 void Account::clear() 00522 { 00523 /* clear() must ignore the group: so, temporarily reset it and call 00524 * remove("") */ 00525 QString saved_prefix = d->prefix; 00526 d->prefix = QString(); 00527 remove(QString()); 00528 d->prefix = saved_prefix; 00529 } 00530 00537 bool Account::contains(const QString &key) const 00538 { 00539 return childKeys().contains(key); 00540 } 00541 00547 void Account::endGroup() 00548 { 00549 d->prefix = d->prefix.section(slash, 0, -3, 00550 QString::SectionIncludeTrailingSep); 00551 if (d->prefix[0] == slash) d->prefix.remove(0, 1); 00552 } 00553 00559 QString Account::group() const 00560 { 00561 if (d->prefix.endsWith(slash)) 00562 return d->prefix.left(d->prefix.size() - 1); 00563 return d->prefix; 00564 } 00565 00569 bool Account::isWritable() const 00570 { 00571 return true; 00572 } 00573 00581 void Account::remove(const QString &key) 00582 { 00583 if (key.isEmpty()) 00584 { 00585 /* delete all keys in the group */ 00586 QStringList keys = allKeys(); 00587 Q_FOREACH (const QString &key, keys) 00588 { 00589 if (!key.isEmpty()) 00590 remove(key); 00591 } 00592 } 00593 else 00594 { 00595 QString full_key = d->prefix + key; 00596 QByteArray tmpkey = full_key.toLatin1(); 00597 ag_account_set_variant(d->m_account, tmpkey.constData(), NULL); 00598 } 00599 } 00600 00608 void Account::setValue(const QString &key, const QVariant &value) 00609 { 00610 GVariant *variant = qVariantToGVariant(value); 00611 if (variant == 0) { 00612 return; 00613 } 00614 00615 QString full_key = d->prefix + key; 00616 QByteArray tmpkey = full_key.toLatin1(); 00617 ag_account_set_variant(d->m_account, tmpkey.constData(), variant); 00618 } 00619 00620 void Account::Private::account_store_cb(AgAccount *account, 00621 GAsyncResult *res, 00622 Account *self) 00623 { 00624 GError *error = NULL; 00625 ag_account_store_finish(account, res, &error); 00626 if (error) { 00627 if (error->domain == G_IO_ERROR && 00628 error->code == G_IO_ERROR_CANCELLED) { 00629 } else { 00630 Q_EMIT self->error(Error(error)); 00631 } 00632 g_error_free(error); 00633 } else { 00634 Q_EMIT self->synced(); 00635 } 00636 } 00637 00652 QVariant Account::value(const QString &key, const QVariant &defaultValue, 00653 SettingSource *source) const 00654 { 00655 QString full_key = d->prefix + key; 00656 QByteArray ba = full_key.toLatin1(); 00657 AgSettingSource settingSource; 00658 GVariant *variant = 00659 ag_account_get_variant(d->m_account, ba.constData(), &settingSource); 00660 if (source != 0) { 00661 switch (settingSource) { 00662 case AG_SETTING_SOURCE_ACCOUNT: *source = ACCOUNT; break; 00663 case AG_SETTING_SOURCE_PROFILE: *source = TEMPLATE; break; 00664 default: *source = NONE; break; 00665 } 00666 } 00667 00668 return (variant != 0) ? gVariantToQVariant(variant) : defaultValue; 00669 } 00670 00686 SettingSource Account::value(const QString &key, QVariant &value) const 00687 { 00688 SettingSource source; 00689 QVariant variant = this->value(key, QVariant(), &source); 00690 if (variant.isValid()) { 00691 if (value.type() != variant.type()) { 00692 if (!variant.convert(value.type())) source = NONE; 00693 } 00694 value = variant; 00695 } 00696 00697 return source; 00698 } 00699 00709 QString Account::valueAsString(const QString &key, 00710 QString default_value, 00711 SettingSource *source) const 00712 { 00713 QVariant var = default_value; 00714 SettingSource src = value(key, var); 00715 if (source) 00716 *source = src; 00717 return var.toString(); 00718 } 00719 00729 int Account::valueAsInt(const QString &key, 00730 int default_value, 00731 SettingSource *source) const 00732 { 00733 QVariant var = default_value; 00734 SettingSource src = value(key, var); 00735 if (source) 00736 *source = src; 00737 return var.toInt(); 00738 } 00739 00749 quint64 Account::valueAsUInt64(const QString &key, 00750 quint64 default_value, 00751 SettingSource *source) const 00752 { 00753 QVariant var = default_value; 00754 SettingSource src = value(key, var); 00755 if (source) 00756 *source = src; 00757 return var.toULongLong(); 00758 } 00759 00769 bool Account::valueAsBool(const QString &key, 00770 bool default_value, 00771 SettingSource *source) const 00772 { 00773 QVariant var = default_value; 00774 SettingSource src = value(key, var); 00775 if (source) 00776 *source = src; 00777 return var.toBool(); 00778 } 00779 00780 void Watch::Private::account_notify_cb(AgAccount *account, const gchar *key, 00781 Watch *watch) 00782 { 00783 Q_EMIT watch->notify(key); 00784 00785 Q_UNUSED(account); 00786 } 00787 00798 Watch *Account::watchKey(const QString &key) 00799 { 00800 AgAccountWatch ag_watch; 00801 Watch *watch = new Watch(this); 00802 00803 if (!key.isEmpty()) 00804 { 00805 QString full_key = d->prefix + key; 00806 ag_watch = ag_account_watch_key 00807 (d->m_account, full_key.toLatin1().constData(), 00808 (AgAccountNotifyCb)&Watch::Private::account_notify_cb, watch); 00809 } 00810 else 00811 { 00812 ag_watch = ag_account_watch_dir 00813 (d->m_account, d->prefix.toLatin1().constData(), 00814 (AgAccountNotifyCb)&Watch::Private::account_notify_cb, watch); 00815 } 00816 00817 if (!ag_watch) 00818 { 00819 delete watch; 00820 return NULL; 00821 } 00822 00823 watch->setWatch(ag_watch); 00824 return watch; 00825 } 00826 00839 void Account::sync() 00840 { 00841 ag_account_store_async(d->m_account, 00842 d->m_cancellable, 00843 (GAsyncReadyCallback)&Private::account_store_cb, 00844 this); 00845 } 00846 00854 bool Account::syncAndBlock() 00855 { 00856 GError *error = NULL; 00857 bool ret; 00858 00859 ret = ag_account_store_blocking(d->m_account, &error); 00860 if (error) 00861 { 00862 qWarning() << "Store operation failed: " << error->message; 00863 g_error_free(error); 00864 } 00865 00866 return ret; 00867 } 00868 00873 void Account::remove() 00874 { 00875 ag_account_delete(d->m_account); 00876 } 00877 00887 void Account::sign(const QString &key, const char *token) 00888 { 00889 ag_account_sign (d->m_account, key.toUtf8().constData(), token); 00890 } 00891 00903 bool Account::verify(const QString &key, const char **token) 00904 { 00905 return ag_account_verify(d->m_account, key.toUtf8().constData(), token); 00906 } 00907 00920 bool Account::verifyWithTokens(const QString &key, QList<const char*> tokens) 00921 { 00922 int tokensCount = tokens.count(); 00923 00924 const char *tmp[tokensCount + 1]; 00925 00926 for (int i = 0; i < tokensCount; ++i) 00927 { 00928 tmp[i] = tokens.at(i); 00929 } 00930 tmp[tokensCount] = NULL; 00931 00932 return ag_account_verify_with_tokens(d->m_account, key.toUtf8().constData(), tmp); 00933 } 00934 00935 uint Account::credentialsId() 00936 { 00937 QString key = ACCOUNTS_KEY_CREDENTIALS_ID; 00938 QVariant val(QVariant::Int); 00939 00940 if (value(key, val) != NONE) 00941 return val.toUInt(); 00942 00943 uint id = 0; 00944 Service service = selectedService(); 00945 if (service.isValid()) { 00946 selectService(); 00947 if (value(key, val) != NONE) 00948 id = val.toUInt(); 00949 selectService(service); 00950 } 00951 return id; 00952 } 00953 00954 AgAccount *Account::account() 00955 { 00956 return d->m_account; 00957 }