From f9a01cdd69d04a972c5d8611ba58237c9fefc336 Mon Sep 17 00:00:00 2001 From: Andrew Branson Date: Thu, 19 Feb 2026 13:21:57 +0100 Subject: Use shared buteo-common, and separate notifications --- .../buteo-common/socialnetworksyncadaptor.cpp | 470 --------------------- 1 file changed, 470 deletions(-) delete mode 100644 buteo-plugins/buteo-common/socialnetworksyncadaptor.cpp (limited to 'buteo-plugins/buteo-common/socialnetworksyncadaptor.cpp') diff --git a/buteo-plugins/buteo-common/socialnetworksyncadaptor.cpp b/buteo-plugins/buteo-common/socialnetworksyncadaptor.cpp deleted file mode 100644 index 42e6d95..0000000 --- a/buteo-plugins/buteo-common/socialnetworksyncadaptor.cpp +++ /dev/null @@ -1,470 +0,0 @@ -/**************************************************************************** - ** - ** Copyright (C) 2013-2026 Jolla Ltd. - ** Contact: Chris Adams - ** - ** This program/library is free software; you can redistribute it and/or - ** modify it under the terms of the GNU Lesser General Public License - ** version 2.1 as published by the Free Software Foundation. - ** - ** This program/library is distributed in the hope that it will be useful, - ** but WITHOUT ANY WARRANTY; without even the implied warranty of - ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - ** Lesser General Public License for more details. - ** - ** You should have received a copy of the GNU Lesser General Public - ** License along with this program/library; if not, write to the Free - ** Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - ** 02110-1301 USA - ** - ****************************************************************************/ - -#include "socialnetworksyncadaptor.h" -#include "socialdnetworkaccessmanager_p.h" -#include "trace.h" - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "buteosyncfw_p.h" - -// libaccounts-qt5 -#include -#include -#include - -// libsocialcache -#include -#include - -namespace { - QStringList validDataTypesInitialiser() - { - return QStringList() - << QStringLiteral("Contacts") - << QStringLiteral("Calendars") - << QStringLiteral("Notifications") - << QStringLiteral("Images") - << QStringLiteral("Videos") - << QStringLiteral("Posts") - << QStringLiteral("Messages") - << QStringLiteral("Emails") - << QStringLiteral("Signon") - << QStringLiteral("Backup") - << QStringLiteral("BackupQuery") - << QStringLiteral("BackupRestore"); - } -} - -SocialNetworkSyncAdaptor::SocialNetworkSyncAdaptor(const QString &serviceName, - SocialNetworkSyncAdaptor::DataType dataType, - QNetworkAccessManager *qnam, - QObject *parent) - : QObject(parent) - , m_dataType(dataType) - , m_accountManager(new Accounts::Manager(this)) - , m_networkAccessManager(qnam != 0 ? qnam : new SocialdNetworkAccessManager) - , m_accountSyncProfile(NULL) - , m_syncDb(new SocialNetworkSyncDatabase()) - , m_status(SocialNetworkSyncAdaptor::Invalid) - , m_enabled(false) - , m_syncAborted(false) - , m_serviceName(serviceName) -{ -} - -SocialNetworkSyncAdaptor::~SocialNetworkSyncAdaptor() -{ - delete m_networkAccessManager; - delete m_accountSyncProfile; - delete m_syncDb; -} - -// The SocialNetworkSyncAdaptor takes ownership of the sync profiles. -void SocialNetworkSyncAdaptor::setAccountSyncProfile(Buteo::SyncProfile* perAccountSyncProfile) -{ - delete m_accountSyncProfile; - m_accountSyncProfile = perAccountSyncProfile; -} - -SocialNetworkSyncAdaptor::Status SocialNetworkSyncAdaptor::status() const -{ - return m_status; -} - -bool SocialNetworkSyncAdaptor::enabled() const -{ - return m_enabled; -} - -QString SocialNetworkSyncAdaptor::serviceName() const -{ - return m_serviceName; -} - -bool SocialNetworkSyncAdaptor::syncAborted() const -{ - return m_syncAborted; -} - -void SocialNetworkSyncAdaptor::sync(const QString &dataType, int accountId) -{ - Q_UNUSED(dataType) - Q_UNUSED(accountId) - qCWarning(lcSocialPlugin) << "sync() must be overridden by derived types"; -} - -void SocialNetworkSyncAdaptor::abortSync(Sync::SyncStatus status) -{ - qCInfo(lcSocialPlugin) << "forcing timeout of outstanding replies due to abort:" << status; - m_syncAborted = true; - triggerReplyTimeouts(); -} - -/*! - * \brief SocialNetworkSyncAdaptor::checkAccount - * \param account - * \return true if synchronization of this adaptor's datatype is enabled for the account - * - * The default implementation checks that the account is enabled - * with the accounts&sso service associated with this sync adaptor. - */ -bool SocialNetworkSyncAdaptor::checkAccount(Accounts::Account *account) -{ - bool globallyEnabled = account->enabled(); - Accounts::Service srv(m_accountManager->service(syncServiceName())); - if (!srv.isValid()) { - qCInfo(lcSocialPlugin) << "invalid service" << syncServiceName() << "specified, account" << account->id() - << "will be disabled for" << m_serviceName << dataTypeName(m_dataType) << "sync"; - return false; - } - account->selectService(srv); - bool serviceEnabled = account->enabled(); - account->selectService(Accounts::Service()); - return globallyEnabled && serviceEnabled; -} - -/*! - \internal - Called when the semaphores for all accounts have been decreased - to zero. This is the final function which is called prior to - telling buteo that the sync plugin can be destroyed. - The implementation MUST be synchronous. -*/ -void SocialNetworkSyncAdaptor::finalCleanup() -{ -} - -/*! - \internal - Called when the semaphores decreased to 0, this method is used - to finalize something, like saving all data to a database. - - You can call incrementSemaphore to perform asynchronous tasks - in this method. finalize will then be called again when the - asynchronous task is finished (and when decrementSemaphore is - called), be sure to have a condition check in order not to run - into an infinite loop. - - It is unsafe to call decrementSemaphore in this method, as - the semaphore handling method will find that the semaphore - went to 0 twice and will perform cleanup operations twice. - Please call decrementSemaphore at the end of the asynchronous - task (preferably in a slot), and only call incrementSemaphore - for asynchronous tasks. - */ -void SocialNetworkSyncAdaptor::finalize(int accountId) -{ - Q_UNUSED(accountId) -} - -/*! - \internal - Returns the last sync timestamp for the given service, account and data type. - If data from prior to this timestamp is received in subsequent requests, it does not need to be synced. - This function will return an invalid QDateTime if no synchronisation has occurred. -*/ -QDateTime SocialNetworkSyncAdaptor::lastSyncTimestamp(const QString &serviceName, - const QString &dataType, - int accountId) const -{ - return m_syncDb->lastSyncTimestamp(serviceName, dataType, accountId); -} - -/*! - \internal - Updates the last sync timestamp for the given service, account and data type to the given \a timestamp. -*/ -bool SocialNetworkSyncAdaptor::updateLastSyncTimestamp(const QString &serviceName, - const QString &dataType, - int accountId, - const QDateTime ×tamp) -{ - // Workaround - // TODO: do better, with a queue - m_syncDb->addSyncTimestamp(serviceName, dataType, accountId, timestamp); - m_syncDb->commit(); - m_syncDb->wait(); - return m_syncDb->writeStatus() == AbstractSocialCacheDatabase::Finished; -} - -/*! - \internal - Returns the list of identifiers of accounts which have been synced for - the given \a dataType. -*/ -QList SocialNetworkSyncAdaptor::syncedAccounts(const QString &dataType) -{ - return m_syncDb->syncedAccounts(m_serviceName, dataType); -} - -/*! - * \internal - * Changes status if there is real change and emits statusChanged() signal. - */ -void SocialNetworkSyncAdaptor::setStatus(Status status) -{ - if (m_status != status) { - m_status = status; - emit statusChanged(); - } -} - -/*! - * \internal - * Should be used in constructors to set the initial state - * of enabled and status, without emitting signals - * - */ -void SocialNetworkSyncAdaptor::setInitialActive(bool enabled) -{ - m_enabled = enabled; - if (enabled) { - m_status = Inactive; - } else { - m_status = Invalid; - } -} - -/*! - * \internal - * Should be called by any specific sync adapter when - * they've finished syncing data. The transition from - * busy status to inactive status is what causes the - * Buteo plugin to emit the sync results (and allows - * subsequent syncs to occur). - */ -void SocialNetworkSyncAdaptor::setFinishedInactive() -{ - finalCleanup(); - qCInfo(lcSocialPlugin) << "Finished" << m_serviceName << SocialNetworkSyncAdaptor::dataTypeName(m_dataType) - << "sync at:" << QDateTime::currentDateTime().toString(Qt::ISODate); - setStatus(SocialNetworkSyncAdaptor::Inactive); -} - -void SocialNetworkSyncAdaptor::incrementSemaphore(int accountId) -{ - int semaphoreValue = m_accountSyncSemaphores.value(accountId); - semaphoreValue += 1; - m_accountSyncSemaphores.insert(accountId, semaphoreValue); - qCDebug(lcSocialPlugin) << "incremented busy semaphore for account" << accountId << "to:" << semaphoreValue; -} - -void SocialNetworkSyncAdaptor::decrementSemaphore(int accountId) -{ - if (!m_accountSyncSemaphores.contains(accountId)) { - qCWarning(lcSocialPlugin) << "no such semaphore for account" << accountId; - return; - } - - int semaphoreValue = m_accountSyncSemaphores.value(accountId); - semaphoreValue -= 1; - qCDebug(lcSocialPlugin) << "decremented busy semaphore for account" << accountId << "to:" << semaphoreValue; - if (semaphoreValue < 0) { - qCWarning(lcSocialPlugin) << "busy semaphore is negative for account" << accountId; - return; - } - m_accountSyncSemaphores.insert(accountId, semaphoreValue); - - if (semaphoreValue == 0) { - finalize(accountId); - - // With the newer implementation, in finalize we can raise semaphores, - // so if after calling finalize, the semaphore count is not the same anymore, - // we shouldn't update the sync timestamp - if (m_accountSyncSemaphores.value(accountId) > 0) { - return; - } - - // finished all outstanding sync requests for this account. - // update the sync time in the global sociald database. - updateLastSyncTimestamp(m_serviceName, - SocialNetworkSyncAdaptor::dataTypeName(m_dataType), accountId, - QDateTime::currentDateTime().toTimeSpec(Qt::UTC)); - - // if all outstanding requests for all accounts have finished, - // then update our status to Inactive / ready to handle more sync requests. - bool allAreZero = true; - QList semaphores = m_accountSyncSemaphores.values(); - foreach (int sv, semaphores) { - if (sv != 0) { - allAreZero = false; - break; - } - } - - if (allAreZero) { - setFinishedInactive(); // Finished! - } - } -} - -void SocialNetworkSyncAdaptor::timeoutReply() -{ - QTimer *timer = qobject_cast(sender()); - QNetworkReply *reply = timer->property("networkReply").value(); - int accountId = timer->property("accountId").toInt(); - - qCWarning(lcSocialPlugin) << "network request timed out while performing sync with account" << accountId; - - m_networkReplyTimeouts[accountId].remove(reply); - reply->setProperty("isError", QVariant::fromValue(true)); - reply->finished(); // invoke finished, so that the error handling there decrements the semaphore etc. - reply->disconnect(); -} - -void SocialNetworkSyncAdaptor::setupReplyTimeout(int accountId, QNetworkReply *reply, int msecs) -{ - // this function should be called whenever a new network request is performed. - QTimer *timer = new QTimer(this); - timer->setSingleShot(true); - timer->setInterval(msecs); - timer->setProperty("accountId", accountId); - timer->setProperty("networkReply", QVariant::fromValue(reply)); - connect(timer, &QTimer::timeout, this, &SocialNetworkSyncAdaptor::timeoutReply); - timer->start(); - m_networkReplyTimeouts[accountId].insert(reply, timer); -} - -void SocialNetworkSyncAdaptor::removeReplyTimeout(int accountId, QNetworkReply *reply) -{ - // this function should be called by the finished() handler for the reply. - QTimer *timer = m_networkReplyTimeouts[accountId].value(reply); - if (!reply) { - return; - } - - delete timer; - m_networkReplyTimeouts[accountId].remove(reply); -} - -void SocialNetworkSyncAdaptor::triggerReplyTimeouts() -{ - // if we've lost network connectivity, we should immediately timeout all replies. - Q_FOREACH (int accountId, m_networkReplyTimeouts.keys()) { - Q_FOREACH (QTimer *timer, m_networkReplyTimeouts[accountId]) { - timer->stop(); - timer->setInterval(1); - timer->start(); - } - } -} - -QJsonObject SocialNetworkSyncAdaptor::parseJsonObjectReplyData(const QByteArray &replyData, bool *ok) -{ - QJsonDocument jsonDocument = QJsonDocument::fromJson(replyData); - *ok = !jsonDocument.isEmpty(); - if (*ok && jsonDocument.isObject()) { - return jsonDocument.object(); - } - *ok = false; - return QJsonObject(); -} - -QJsonArray SocialNetworkSyncAdaptor::parseJsonArrayReplyData(const QByteArray &replyData, bool *ok) -{ - QJsonDocument jsonDocument = QJsonDocument::fromJson(replyData); - *ok = !jsonDocument.isEmpty(); - if (*ok && jsonDocument.isArray()) { - return jsonDocument.array(); - } - *ok = false; - return QJsonArray(); -} - -/* - Valid data types are data types which are known to the API. - Note that just because a data type is valid does not mean - that it will necessarily be supported by a given social network - sync adaptor. -*/ -QStringList SocialNetworkSyncAdaptor::validDataTypes() -{ - static QStringList retn(validDataTypesInitialiser()); - return retn; -} - -/* - String for Enum since the DBus API uses strings -*/ -QString SocialNetworkSyncAdaptor::dataTypeName(SocialNetworkSyncAdaptor::DataType t) -{ - switch (t) { - case SocialNetworkSyncAdaptor::Contacts: return QStringLiteral("Contacts"); - case SocialNetworkSyncAdaptor::Calendars: return QStringLiteral("Calendars"); - case SocialNetworkSyncAdaptor::Notifications: return QStringLiteral("Notifications"); - case SocialNetworkSyncAdaptor::Images: return QStringLiteral("Images"); - case SocialNetworkSyncAdaptor::Videos: return QStringLiteral("Videos"); - case SocialNetworkSyncAdaptor::Posts: return QStringLiteral("Posts"); - case SocialNetworkSyncAdaptor::Messages: return QStringLiteral("Messages"); - case SocialNetworkSyncAdaptor::Emails: return QStringLiteral("Emails"); - case SocialNetworkSyncAdaptor::Signon: return QStringLiteral("Signon"); - case SocialNetworkSyncAdaptor::Backup: return QStringLiteral("Backup"); - case SocialNetworkSyncAdaptor::BackupQuery: return QStringLiteral("BackupQuery"); - case SocialNetworkSyncAdaptor::BackupRestore: return QStringLiteral("BackupRestore"); - default: break; - } - - return QString(); -} - -void SocialNetworkSyncAdaptor::purgeCachedImages(SocialImagesDatabase *database, - int accountId) -{ - database->queryImages(accountId); - database->wait(); - - QList images = database->images(); - foreach (SocialImage::ConstPtr image, images) { - qCDebug(lcSocialPlugin) << "Purge cached image " << image->imageFile() << " for account " << image->accountId(); - QFile::remove(image->imageFile()); - } - - database->removeImages(images); - database->commit(); - database->wait(); -} - -void SocialNetworkSyncAdaptor::purgeExpiredImages(SocialImagesDatabase *database, - int accountId) -{ - database->queryExpired(accountId); - database->wait(); - - QList images = database->images(); - foreach (SocialImage::ConstPtr image, images) { - qCDebug(lcSocialPlugin) << "Purge expired image " << image->imageFile() << " for account " << image->accountId(); - QFile::remove(image->imageFile()); - } - - database->removeImages(images); - database->commit(); - database->wait(); -} -- cgit v1.2.3