From f47d8ddf744bff7903d58a4b7e33f5c919e0f8a0 Mon Sep 17 00:00:00 2001 From: Teo Mrnjavac Date: Wed, 22 May 2013 16:15:25 +0200 Subject: [PATCH] Added CredentialsManager as a QtKeychain credentials cache. --- src/libtomahawk/CMakeLists.txt | 1 + src/libtomahawk/accounts/AccountManager.cpp | 24 +++- src/libtomahawk/accounts/AccountManager.h | 5 + .../accounts/CredentialsManager.cpp | 110 ++++++++++++++++++ src/libtomahawk/accounts/CredentialsManager.h | 74 ++++++++++++ 5 files changed, 211 insertions(+), 3 deletions(-) create mode 100644 src/libtomahawk/accounts/CredentialsManager.cpp create mode 100644 src/libtomahawk/accounts/CredentialsManager.h diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index df96b0182..c2d4e0ca2 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -204,6 +204,7 @@ list(APPEND libSources accounts/Account.cpp accounts/AccountModel.cpp accounts/AccountModelFilterProxy.cpp + accounts/CredentialsManager.cpp accounts/ResolverAccount.cpp accounts/AccountDelegate.cpp accounts/DelegateConfigWrapper.cpp diff --git a/src/libtomahawk/accounts/AccountManager.cpp b/src/libtomahawk/accounts/AccountManager.cpp index 8b20bd7c5..a267ec411 100644 --- a/src/libtomahawk/accounts/AccountManager.cpp +++ b/src/libtomahawk/accounts/AccountManager.cpp @@ -18,6 +18,8 @@ */ #include "AccountManager.h" + +#include "CredentialsManager.h" #include "config.h" #include "SourceList.h" #include "TomahawkSettings.h" @@ -33,6 +35,7 @@ #include #include + namespace Tomahawk { @@ -86,7 +89,7 @@ AccountManager::init() m_accountFactories[ f->factoryId() ] = f; registerAccountFactoryForFilesystem( f ); - emit ready(); + emit ready(); //Notifies TomahawkApp to load the remaining AccountFactories, then Accounts from config } @@ -276,7 +279,22 @@ void AccountManager::loadFromConfig() { QStringList accountIds = TomahawkSettings::instance()->accounts(); + + qDebug() << "LOADING ALL CREDENTIALS" << accountIds; + + m_creds = new CredentialsManager( this ); + connect( m_creds, SIGNAL( ready() ), + this, SLOT( finishLoadingFromConfig() ) ); + m_creds->loadCredentials( accountIds ); +} + + +void +AccountManager::finishLoadingFromConfig() +{ + QStringList accountIds = m_creds->keys(); qDebug() << "LOADING ALL ACCOUNTS" << accountIds; + foreach ( const QString& accountId, accountIds ) { QString pluginFactory = factoryFromId( accountId ); @@ -498,6 +516,6 @@ AccountManager::onStateChanged( Account::ConnectionState state ) } -}; +} -}; +} diff --git a/src/libtomahawk/accounts/AccountManager.h b/src/libtomahawk/accounts/AccountManager.h index 8f080676e..7b3076dfb 100644 --- a/src/libtomahawk/accounts/AccountManager.h +++ b/src/libtomahawk/accounts/AccountManager.h @@ -34,6 +34,8 @@ namespace Tomahawk namespace Accounts { +class CredentialsManager; + class DLLEXPORT AccountManager : public QObject { Q_OBJECT @@ -105,6 +107,7 @@ private slots: void init(); void onStateChanged( Tomahawk::Accounts::Account::ConnectionState state ); void onError( int code, const QString& msg ); + void finishLoadingFromConfig(); void onSettingsChanged(); @@ -117,6 +120,8 @@ private: Account* loadPlugin( const QString &accountId ); void hookupAccount( Account* ) const; + CredentialsManager* m_creds; + QList< Account* > m_accounts; QList< Account* > m_enabledAccounts; QList< Account* > m_connectedAccounts; diff --git a/src/libtomahawk/accounts/CredentialsManager.cpp b/src/libtomahawk/accounts/CredentialsManager.cpp new file mode 100644 index 000000000..7217f5fbc --- /dev/null +++ b/src/libtomahawk/accounts/CredentialsManager.cpp @@ -0,0 +1,110 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2013, Teo Mrnjavac + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#include "CredentialsManager.h" + +#include "utils/Logger.h" + +#include + +#include + +namespace Tomahawk +{ + +namespace Accounts +{ + + +CredentialsManager::CredentialsManager( QObject* parent ) + : QObject( parent ) +{ + +} + + +void +CredentialsManager::loadCredentials( QStringList keys ) +{ + foreach ( QString key, keys ) + { + QKeychain::ReadPasswordJob* j = new QKeychain::ReadPasswordJob( QLatin1String( "tomahawkaccounts" ), this ); + j->setKey( key ); + j->setAutoDelete( false ); +#if defined( Q_OS_UNIX ) && !defined( Q_OS_MAC ) + j->setInsecureFallback( true ); +#endif + connect( j, SIGNAL( finished( QKeychain::Job* ) ), + SLOT( keychainJobFinished( QKeychain::Job* ) ) ); + m_readJobs << j; + j->start(); + } + +} + + +QStringList +CredentialsManager::keys() const +{ + QStringList keys = m_credentials.keys(); + return keys; +} + + +void +CredentialsManager::keychainJobFinished( QKeychain::Job* j ) +{ + if ( j->error() == QKeychain::NoError ) + { + if ( QKeychain::ReadPasswordJob* readJob = qobject_cast< QKeychain::ReadPasswordJob* >( j ) ) + { + tDebug() << "QtKeychain readJob for" << readJob->key() << "finished without errors"; + + QVariantHash creds; + QDataStream dataStream( readJob->binaryData() ); + dataStream >> creds; + + m_credentials.insert( readJob->key(), creds ); + + m_readJobs.removeAll( readJob ); + + if ( m_readJobs.isEmpty() ) + { + emit ready(); + } + } + } + else if ( QKeychain::WritePasswordJob* writeJob = qobject_cast< QKeychain::WritePasswordJob* >( j ) ) + { + tLog() << Q_FUNC_INFO << "QtKeychain writeJob finished"; + } + else if ( QKeychain::DeletePasswordJob* deleteJob = qobject_cast< QKeychain::DeletePasswordJob* >( j ) ) + { + tLog() << Q_FUNC_INFO << "QtKeychain deleteJob finished"; + } + else + { + tDebug() << "QtKeychain job finished with error:" << j->error() << j->errorString(); + } + j->deleteLater(); +} + + +} //namespace Accounts + +} //namespace Tomahawk diff --git a/src/libtomahawk/accounts/CredentialsManager.h b/src/libtomahawk/accounts/CredentialsManager.h new file mode 100644 index 000000000..c0b19e533 --- /dev/null +++ b/src/libtomahawk/accounts/CredentialsManager.h @@ -0,0 +1,74 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2013, Teo Mrnjavac + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#ifndef CREDENTIALSMANAGER_H +#define CREDENTIALSMANAGER_H + +#include +#include + + +namespace QKeychain +{ +class Job; +class ReadPasswordJob; +class WritePasswordJob; +} + + +namespace Tomahawk +{ + +namespace Accounts +{ + +/** + * @brief The CredentialsManager class holds an in-memory cache of whatever credentials are stored + * in the system's QtKeychain-accessible credentials storage. + * After instantiating the class, loadCredentials should be called, and this is the only time a read + * operation from QtKeychain is performed. When CredentialsManager emits ready(), it can be used for + * all other operations. The only QtKeychain operations performed at any time after startup are + * write and delete. + * This ensures an illusion of synchronous operations for Tomahawk's Account classes, even though all + * QtKeychain jobs are async. + */ +class CredentialsManager : public QObject +{ + Q_OBJECT +public: + explicit CredentialsManager( QObject* parent = 0 ); + + void loadCredentials( QStringList keys ); + + QStringList keys() const; + +signals: + void ready(); + +private slots: + void keychainJobFinished( QKeychain::Job* ); + +private: + QHash< QString, QVariantHash > m_credentials; + QList< QKeychain::ReadPasswordJob* > m_readJobs; +}; + +} //namespace Accounts + +} //namespace Tomahawk +#endif // CREDENTIALSMANAGER_H