2014-12-17 16:09:57 +03:00
/*
* Copyright ( C ) by Daniel Molkentin < danimo @ owncloud . com >
*
* This program 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 ; version 2 of the License .
*
* This program 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 .
*/
# include "accountstate.h"
2015-04-09 17:19:17 +03:00
# include "accountmanager.h"
2014-12-17 16:09:57 +03:00
# include "account.h"
# include "creds/abstractcredentials.h"
2015-09-05 16:39:22 +03:00
# include "logger.h"
2014-12-17 16:09:57 +03:00
# include <QDebug>
2015-06-15 16:04:39 +03:00
# include <QSettings>
2015-08-30 16:20:35 +03:00
# include <qfontmetrics.h>
2014-12-17 16:09:57 +03:00
namespace OCC {
2014-12-18 14:09:48 +03:00
AccountState : : AccountState ( AccountPtr account )
2015-04-23 16:59:32 +03:00
: QObject ( )
2014-12-17 16:09:57 +03:00
, _account ( account )
, _state ( AccountState : : Disconnected )
, _connectionStatus ( ConnectionValidator : : Undefined )
, _waitingForNewCredentials ( false )
2015-09-05 16:39:22 +03:00
, _credentialsFetchMode ( Interactive )
2014-12-17 16:09:57 +03:00
{
qRegisterMetaType < AccountState * > ( " AccountState* " ) ;
2014-12-18 14:09:48 +03:00
connect ( account . data ( ) , SIGNAL ( invalidCredentials ( ) ) ,
2014-12-17 16:09:57 +03:00
SLOT ( slotInvalidCredentials ( ) ) ) ;
2014-12-18 14:09:48 +03:00
connect ( account . data ( ) , SIGNAL ( credentialsFetched ( AbstractCredentials * ) ) ,
2014-12-17 16:09:57 +03:00
SLOT ( slotCredentialsFetched ( AbstractCredentials * ) ) ) ;
2015-09-05 16:39:22 +03:00
connect ( account . data ( ) , SIGNAL ( credentialsAsked ( AbstractCredentials * ) ) ,
SLOT ( slotCredentialsAsked ( AbstractCredentials * ) ) ) ;
2014-12-17 16:09:57 +03:00
}
AccountState : : ~ AccountState ( )
{
2015-04-23 16:59:32 +03:00
qDebug ( ) < < " Account state for account " < < account ( ) - > displayName ( ) < < " deleted " ;
2014-12-17 16:09:57 +03:00
}
2014-12-18 14:09:48 +03:00
AccountPtr AccountState : : account ( ) const
2014-12-17 16:09:57 +03:00
{
2015-04-17 18:56:17 +03:00
return _account ;
2014-12-17 16:09:57 +03:00
}
AccountState : : ConnectionStatus AccountState : : connectionStatus ( ) const
{
return _connectionStatus ;
}
QStringList AccountState : : connectionErrors ( ) const
{
return _connectionErrors ;
}
QString AccountState : : connectionStatusString ( ConnectionStatus status )
{
return ConnectionValidator : : statusString ( status ) ;
}
AccountState : : State AccountState : : state ( ) const
{
return _state ;
}
void AccountState : : setState ( State state )
{
if ( _state ! = state ) {
qDebug ( ) < < " AccountState state change: "
< < stateString ( _state ) < < " -> " < < stateString ( state ) ;
State oldState = _state ;
_state = state ;
if ( _state = = SignedOut ) {
_connectionStatus = ConnectionValidator : : Undefined ;
_connectionErrors . clear ( ) ;
} else if ( oldState = = SignedOut & & _state = = Disconnected ) {
2015-09-05 16:39:22 +03:00
checkConnectivity ( Interactive ) ;
2014-12-17 16:09:57 +03:00
}
}
2015-05-15 13:26:23 +03:00
// might not have changed but the underlying _connectionErrors might have
emit stateChanged ( _state ) ;
2014-12-17 16:09:57 +03:00
}
QString AccountState : : stateString ( State state )
{
switch ( state )
{
case SignedOut :
2015-07-01 13:30:18 +03:00
return tr ( " Signed out " ) ;
2014-12-17 16:09:57 +03:00
case Disconnected :
2015-07-01 13:30:18 +03:00
return tr ( " Disconnected " ) ;
2014-12-17 16:09:57 +03:00
case Connected :
2015-07-01 13:30:18 +03:00
return tr ( " Connected " ) ;
2015-04-24 12:32:47 +03:00
case ServiceUnavailable :
2015-07-01 13:30:18 +03:00
return tr ( " Service unavailable " ) ;
2014-12-17 16:09:57 +03:00
case NetworkError :
2015-07-01 13:30:18 +03:00
return tr ( " Network error " ) ;
2014-12-17 16:09:57 +03:00
case ConfigurationError :
2015-07-01 13:30:18 +03:00
return tr ( " Configuration error " ) ;
2014-12-17 16:09:57 +03:00
}
2015-07-01 13:30:18 +03:00
return tr ( " Unknown account state " ) ;
2014-12-17 16:09:57 +03:00
}
bool AccountState : : isSignedOut ( ) const
{
return _state = = SignedOut ;
}
void AccountState : : setSignedOut ( bool signedOut )
{
if ( signedOut ) {
setState ( SignedOut ) ;
2015-07-07 15:44:16 +03:00
} else if ( _state = = SignedOut ) {
2014-12-17 16:09:57 +03:00
setState ( Disconnected ) ;
}
}
bool AccountState : : isConnected ( ) const
{
return _state = = Connected ;
}
2015-04-24 12:32:47 +03:00
bool AccountState : : isConnectedOrTemporarilyUnavailable ( ) const
2015-02-25 11:49:39 +03:00
{
2015-04-24 12:32:47 +03:00
return isConnected ( ) | | _state = = ServiceUnavailable ;
2015-02-25 11:49:39 +03:00
}
2015-09-05 16:39:22 +03:00
void AccountState : : checkConnectivity ( CredentialFetchMode credentialsFetchMode )
2014-12-17 16:09:57 +03:00
{
if ( isSignedOut ( ) | | _waitingForNewCredentials ) {
return ;
}
2015-05-15 13:26:23 +03:00
if ( _connectionValidator ) {
qDebug ( ) < < " ConnectionValidator already running, ignoring " ;
return ;
}
2015-09-05 16:39:22 +03:00
_credentialsFetchMode = credentialsFetchMode ;
ConnectionValidator * conValidator = new ConnectionValidator ( account ( ) ) ;
2015-05-15 13:26:23 +03:00
_connectionValidator = conValidator ;
2014-12-17 16:09:57 +03:00
connect ( conValidator , SIGNAL ( connectionResult ( ConnectionValidator : : Status , QStringList ) ) ,
SLOT ( slotConnectionValidatorResult ( ConnectionValidator : : Status , QStringList ) ) ) ;
if ( isConnected ( ) ) {
// Use a small authed propfind as a minimal ping when we're
// already connected.
conValidator - > checkAuthentication ( ) ;
} else {
// Check the server and then the auth.
2015-03-19 13:40:47 +03:00
# ifdef Q_OS_WIN
// There seems to be a bug in Qt on Windows where QNAM sometimes stops
// working correctly after the computer woke up from sleep. See #2895 #2899
// and #2973.
// As an attempted workaround, reset the QNAM regularly if the account is
// disconnected.
account ( ) - > resetNetworkAccessManager ( ) ;
2015-07-02 12:28:40 +03:00
// If we don't reset the ssl config a second CheckServerJob can produce a
// ssl config that does not have a sensible certificate chain.
account ( ) - > setSslConfiguration ( QSslConfiguration ( ) ) ;
2015-03-19 13:40:47 +03:00
# endif
2014-12-17 16:09:57 +03:00
conValidator - > checkServerAndAuth ( ) ;
}
}
void AccountState : : slotConnectionValidatorResult ( ConnectionValidator : : Status status , const QStringList & errors )
{
if ( isSignedOut ( ) ) {
return ;
}
if ( _connectionStatus ! = status ) {
qDebug ( ) < < " AccountState connection status change: "
< < connectionStatusString ( _connectionStatus ) < < " -> "
< < connectionStatusString ( status ) ;
_connectionStatus = status ;
}
_connectionErrors = errors ;
switch ( status )
{
case ConnectionValidator : : Connected :
2015-07-07 15:44:16 +03:00
if ( _state ! = Connected ) {
2015-06-08 13:14:37 +03:00
setState ( Connected ) ;
}
2014-12-17 16:09:57 +03:00
break ;
case ConnectionValidator : : Undefined :
case ConnectionValidator : : NotConfigured :
setState ( Disconnected ) ;
break ;
case ConnectionValidator : : ServerVersionMismatch :
setState ( ConfigurationError ) ;
break ;
2015-02-11 11:23:04 +03:00
case ConnectionValidator : : StatusNotFound :
// This can happen either because the server does not exist
// or because we are having network issues. The latter one is
// much more likely, so keep trying to connect.
setState ( NetworkError ) ;
break ;
2015-09-05 16:37:20 +03:00
case ConnectionValidator : : CredentialsMissingOrWrong :
slotInvalidCredentials ( ) ;
2014-12-17 16:09:57 +03:00
break ;
2015-01-21 17:30:25 +03:00
case ConnectionValidator : : UserCanceledCredentials :
setState ( SignedOut ) ;
break ;
2015-04-24 12:32:47 +03:00
case ConnectionValidator : : ServiceUnavailable :
setState ( ServiceUnavailable ) ;
2015-02-25 11:49:39 +03:00
break ;
2014-12-17 16:09:57 +03:00
case ConnectionValidator : : Timeout :
setState ( NetworkError ) ;
break ;
}
}
void AccountState : : slotInvalidCredentials ( )
{
2015-09-05 16:37:20 +03:00
if ( isSignedOut ( ) | | _waitingForNewCredentials )
2014-12-17 16:09:57 +03:00
return ;
2015-09-05 16:37:20 +03:00
if ( account ( ) - > credentials ( ) - > ready ( ) )
account ( ) - > credentials ( ) - > invalidateToken ( ) ;
account ( ) - > credentials ( ) - > fetchFromKeychain ( ) ;
2014-12-17 16:09:57 +03:00
setState ( ConfigurationError ) ;
_waitingForNewCredentials = true ;
}
void AccountState : : slotCredentialsFetched ( AbstractCredentials * credentials )
2015-09-05 16:39:22 +03:00
{
if ( ! credentials - > ready ( ) ) {
// No exiting credentials found in the keychain
if ( _credentialsFetchMode = = Interactive )
credentials - > askFromUser ( ) ;
else {
Logger : : instance ( ) - > postOptionalGuiLog ( tr ( " Reauthentication required " ) , tr ( " You need to re-login to continue using the account %1. " ) . arg ( _account - > displayName ( ) ) ) ;
setState ( SignedOut ) ;
_waitingForNewCredentials = false ;
}
return ;
}
_waitingForNewCredentials = false ;
// When new credentials become available we always want to restart the
// connection validation, even if it's currently running.
delete _connectionValidator ;
checkConnectivity ( _credentialsFetchMode ) ;
}
void AccountState : : slotCredentialsAsked ( AbstractCredentials * credentials )
2014-12-17 16:09:57 +03:00
{
_waitingForNewCredentials = false ;
if ( ! credentials - > ready ( ) ) {
// User canceled the connection or did not give a password
setState ( SignedOut ) ;
return ;
}
2015-05-22 10:38:44 +03:00
// When new credentials become available we always want to restart the
// connection validation, even if it's currently running.
2015-09-05 16:39:22 +03:00
delete _connectionValidator ;
2015-05-22 10:38:44 +03:00
2015-09-05 16:39:22 +03:00
checkConnectivity ( _credentialsFetchMode ) ;
2014-12-17 16:09:57 +03:00
}
2015-07-02 14:31:42 +03:00
std : : unique_ptr < QSettings > AccountState : : settings ( )
2015-06-15 16:04:39 +03:00
{
auto s = _account - > settingsWithGroup ( QLatin1String ( " Accounts " ) ) ;
s - > beginGroup ( _account - > id ( ) ) ;
return s ;
}
2015-08-30 16:20:35 +03:00
QString AccountState : : shortDisplayNameForSettings ( int width ) const
2015-08-05 15:49:16 +03:00
{
2015-08-30 16:20:35 +03:00
QString user = account ( ) - > credentials ( ) - > user ( ) ;
QString host = account ( ) - > url ( ) . host ( ) ;
2015-09-10 11:17:16 +03:00
int port = account ( ) - > url ( ) . port ( ) ;
if ( port > 0 & & port ! = 80 & & port ! = 443 ) {
host . append ( QLatin1Char ( ' : ' ) ) ;
host . append ( QString : : number ( port ) ) ;
}
2015-08-30 16:20:35 +03:00
if ( width > 0 ) {
QFont f ;
QFontMetrics fm ( f ) ;
2015-09-10 11:17:16 +03:00
host = fm . elidedText ( host , Qt : : ElideMiddle , width ) ;
2015-08-30 16:20:35 +03:00
user = fm . elidedText ( user , Qt : : ElideRight , width ) ;
2015-08-05 15:49:16 +03:00
}
2015-08-30 16:20:35 +03:00
return user + QLatin1String ( " \n " ) + host ;
2015-08-05 15:49:16 +03:00
}
2015-04-17 18:56:17 +03:00
2014-12-17 16:09:57 +03:00
} // namespace OCC