summaryrefslogtreecommitdiff
path: root/buteo-plugins/buteo-common/socialnetworksyncadaptor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'buteo-plugins/buteo-common/socialnetworksyncadaptor.cpp')
-rw-r--r--buteo-plugins/buteo-common/socialnetworksyncadaptor.cpp470
1 files changed, 0 insertions, 470 deletions
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 <chris.adams@jollamobile.com>
- **
- ** 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 <QtCore/QJsonDocument>
-#include <QtCore/QTimer>
-#include <QtSql/QSqlDatabase>
-#include <QtSql/QSqlQuery>
-#include <QtSql/QSqlError>
-#include <QtSql/QSqlRecord>
-
-#include <QtNetwork/QNetworkAccessManager>
-#include <QtNetwork/QNetworkReply>
-
-#include "buteosyncfw_p.h"
-
-// libaccounts-qt5
-#include <Accounts/Manager>
-#include <Accounts/Account>
-#include <Accounts/Service>
-
-// libsocialcache
-#include <socialcache/socialimagesdatabase.h>
-#include <socialcache/socialnetworksyncdatabase.h>
-
-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 &timestamp)
-{
- // 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<int> 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<int> 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<QTimer*>(sender());
- QNetworkReply *reply = timer->property("networkReply").value<QNetworkReply*>();
- 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<bool>(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<QNetworkReply*>(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<SocialImage::ConstPtr> 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<SocialImage::ConstPtr> 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();
-}