8486a2fd2b
Users have complained that they don't see the notification when it is
shown and are not aware that their files aren't syncing.
Remove the non-interactive credentials fetch logic and add make sure
that the shibboleth popup will flash in the taskbar instead.
This will still not allow the popup to show in front in all cases,
but this is a compromise that we have to chose.
This reverts commit dcb687929f.
Issue https://github.com/owncloud/enterprise/issues/990
320 linhas
9.0 KiB
C++
320 linhas
9.0 KiB
C++
/*
|
|
* 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"
|
|
#include "accountmanager.h"
|
|
#include "account.h"
|
|
#include "creds/abstractcredentials.h"
|
|
#include "logger.h"
|
|
#include "configfile.h"
|
|
|
|
#include <QDebug>
|
|
#include <QSettings>
|
|
#include <qfontmetrics.h>
|
|
|
|
namespace OCC {
|
|
|
|
AccountState::AccountState(AccountPtr account)
|
|
: QObject()
|
|
, _account(account)
|
|
, _state(AccountState::Disconnected)
|
|
, _connectionStatus(ConnectionValidator::Undefined)
|
|
, _waitingForNewCredentials(false)
|
|
{
|
|
qRegisterMetaType<AccountState*>("AccountState*");
|
|
|
|
connect(account.data(), SIGNAL(invalidCredentials()),
|
|
SLOT(slotInvalidCredentials()));
|
|
connect(account.data(), SIGNAL(credentialsFetched(AbstractCredentials*)),
|
|
SLOT(slotCredentialsFetched(AbstractCredentials*)));
|
|
connect(account.data(), SIGNAL(credentialsAsked(AbstractCredentials*)),
|
|
SLOT(slotCredentialsAsked(AbstractCredentials*)));
|
|
_timeSinceLastETagCheck.invalidate();
|
|
}
|
|
|
|
AccountState::~AccountState()
|
|
{
|
|
}
|
|
|
|
AccountPtr AccountState::account() const
|
|
{
|
|
return _account;
|
|
}
|
|
|
|
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) {
|
|
checkConnectivity();
|
|
}
|
|
}
|
|
|
|
// might not have changed but the underlying _connectionErrors might have
|
|
emit stateChanged(_state);
|
|
}
|
|
|
|
QString AccountState::stateString(State state)
|
|
{
|
|
switch (state)
|
|
{
|
|
case SignedOut:
|
|
return tr("Signed out");
|
|
case Disconnected:
|
|
return tr("Disconnected");
|
|
case Connected:
|
|
return tr("Connected");
|
|
case ServiceUnavailable:
|
|
return tr("Service unavailable");
|
|
case NetworkError:
|
|
return tr("Network error");
|
|
case ConfigurationError:
|
|
return tr("Configuration error");
|
|
}
|
|
return tr("Unknown account state");
|
|
}
|
|
|
|
bool AccountState::isSignedOut() const
|
|
{
|
|
return _state == SignedOut;
|
|
}
|
|
|
|
void AccountState::signOutByUi()
|
|
{
|
|
account()->credentials()->forgetSensitiveData();
|
|
setState(SignedOut);
|
|
}
|
|
|
|
void AccountState::signIn()
|
|
{
|
|
if (_state == SignedOut) {
|
|
setState(Disconnected);
|
|
}
|
|
}
|
|
|
|
bool AccountState::isConnected() const
|
|
{
|
|
return _state == Connected;
|
|
}
|
|
|
|
bool AccountState::isConnectedOrTemporarilyUnavailable() const
|
|
{
|
|
return isConnected() || _state == ServiceUnavailable;
|
|
}
|
|
|
|
void AccountState::tagLastSuccessfullETagRequest()
|
|
{
|
|
_timeSinceLastETagCheck.restart();
|
|
}
|
|
|
|
void AccountState::checkConnectivity()
|
|
{
|
|
if (isSignedOut() || _waitingForNewCredentials) {
|
|
return;
|
|
}
|
|
|
|
if (_connectionValidator) {
|
|
qDebug() << "ConnectionValidator already running, ignoring" << account()->displayName();
|
|
return;
|
|
}
|
|
|
|
// IF the account is connected the connection check can be skipped
|
|
// if the last successful etag check job is not so long ago.
|
|
ConfigFile cfg;
|
|
int polltime = cfg.remotePollInterval();
|
|
|
|
if (isConnected() && _timeSinceLastETagCheck.isValid()
|
|
&& _timeSinceLastETagCheck.elapsed() < polltime) {
|
|
//qDebug() << account()->displayName() << "The last ETag check succeeded within the last " << polltime/1000 << " secs. No connection check needed!";
|
|
return;
|
|
}
|
|
|
|
ConnectionValidator * conValidator = new ConnectionValidator(account());
|
|
_connectionValidator = conValidator;
|
|
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.
|
|
|
|
#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();
|
|
|
|
// 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());
|
|
#endif
|
|
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:
|
|
if (_state != Connected) {
|
|
setState(Connected);
|
|
}
|
|
break;
|
|
case ConnectionValidator::Undefined:
|
|
case ConnectionValidator::NotConfigured:
|
|
setState(Disconnected);
|
|
break;
|
|
case ConnectionValidator::ServerVersionMismatch:
|
|
setState(ConfigurationError);
|
|
break;
|
|
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;
|
|
case ConnectionValidator::CredentialsMissingOrWrong:
|
|
slotInvalidCredentials();
|
|
break;
|
|
case ConnectionValidator::UserCanceledCredentials:
|
|
setState(SignedOut);
|
|
break;
|
|
case ConnectionValidator::ServiceUnavailable:
|
|
setState(ServiceUnavailable);
|
|
break;
|
|
case ConnectionValidator::Timeout:
|
|
setState(NetworkError);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void AccountState::slotInvalidCredentials()
|
|
{
|
|
if (isSignedOut() || _waitingForNewCredentials)
|
|
return;
|
|
|
|
if (account()->credentials()->ready())
|
|
account()->credentials()->invalidateToken();
|
|
account()->credentials()->fetchFromKeychain();
|
|
|
|
setState(ConfigurationError);
|
|
_waitingForNewCredentials = true;
|
|
}
|
|
|
|
void AccountState::slotCredentialsFetched(AbstractCredentials* credentials)
|
|
{
|
|
if (!credentials->ready()) {
|
|
// No exiting credentials found in the keychain
|
|
credentials->askFromUser();
|
|
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();
|
|
}
|
|
|
|
void AccountState::slotCredentialsAsked(AbstractCredentials* credentials)
|
|
{
|
|
_waitingForNewCredentials = false;
|
|
|
|
if (!credentials->ready()) {
|
|
// User canceled the connection or did not give a password
|
|
setState(SignedOut);
|
|
return;
|
|
}
|
|
|
|
// When new credentials become available we always want to restart the
|
|
// connection validation, even if it's currently running.
|
|
delete _connectionValidator;
|
|
|
|
checkConnectivity();
|
|
}
|
|
|
|
std::unique_ptr<QSettings> AccountState::settings()
|
|
{
|
|
auto s = _account->settingsWithGroup(QLatin1String("Accounts"));
|
|
s->beginGroup(_account->id());
|
|
return s;
|
|
}
|
|
|
|
QString AccountState::shortDisplayNameForSettings(int width) const
|
|
{
|
|
QString user = account()->credentials()->user();
|
|
QString host = account()->url().host();
|
|
int port = account()->url().port();
|
|
if (port > 0 && port != 80 && port != 443) {
|
|
host.append(QLatin1Char(':'));
|
|
host.append(QString::number(port));
|
|
}
|
|
if (width > 0) {
|
|
QFont f;
|
|
QFontMetrics fm(f);
|
|
host = fm.elidedText(host, Qt::ElideMiddle, width);
|
|
user = fm.elidedText(user, Qt::ElideRight, width);
|
|
}
|
|
return user + QLatin1String("\n") + host;
|
|
}
|
|
|
|
|
|
|
|
} // namespace OCC
|