Show a notification instead of a login window on startup #3350

The original problem is that showing a popup not originated
from the main settings window while it's focused won't be
shown in front to the user.

This try not to highjack the user's attention of the user
by showing a notification when checking the connection for
valid credentials, and require the user to sign in through
the UI. There are still issues with showing that popup from
the tray icon, but the user will most likely be looking for
the popup in that case. The new sign in button directly in
the settings account works properly.
This commit is contained in:
Jocelyn Turcotte 2015-09-01 15:37:58 +02:00
parent 628957de21
commit dcb687929f
14 changed files with 48 additions and 23 deletions

View file

@ -79,7 +79,7 @@ void AccountState::setState(State state)
_connectionStatus = ConnectionValidator::Undefined;
_connectionErrors.clear();
} else if (oldState == SignedOut && _state == Disconnected) {
checkConnectivity();
checkConnectivity(AbstractCredentials::Interactive);
}
}
@ -131,7 +131,7 @@ bool AccountState::isConnectedOrTemporarilyUnavailable() const
return isConnected() || _state == ServiceUnavailable;
}
void AccountState::checkConnectivity()
void AccountState::checkConnectivity(AbstractCredentials::FetchMode credentialsFetchMode)
{
if (isSignedOut() || _waitingForNewCredentials) {
return;
@ -141,7 +141,7 @@ void AccountState::checkConnectivity()
qDebug() << "ConnectionValidator already running, ignoring";
return;
}
ConnectionValidator * conValidator = new ConnectionValidator(account());
ConnectionValidator * conValidator = new ConnectionValidator(account(), credentialsFetchMode);
_connectionValidator = conValidator;
connect(conValidator, SIGNAL(connectionResult(ConnectionValidator::Status,QStringList)),
SLOT(slotConnectionValidatorResult(ConnectionValidator::Status,QStringList)));
@ -243,7 +243,10 @@ void AccountState::slotCredentialsFetched(AbstractCredentials* credentials)
delete _connectionValidator;
}
checkConnectivity();
// If we made it this far, it means that we either fetched credentials
// interactively, or that we already aborted for missing/invalid credentials.
Q_ASSERT(credentials->ready());
checkConnectivity(AbstractCredentials::Interactive);
}
std::unique_ptr<QSettings> AccountState::settings()

View file

@ -84,7 +84,7 @@ public:
/// Triggers a ping to the server to update state and
/// connection status and errors.
void checkConnectivity();
void checkConnectivity(AbstractCredentials::FetchMode credentialsFetchMode);
/** Returns a new settings object for this account, already in the right groups. */
std::unique_ptr<QSettings> settings();

View file

@ -223,7 +223,7 @@ void Application::slotCheckConnection()
// when the error is permanent.
if (state != AccountState::SignedOut
&& state != AccountState::ConfigurationError) {
accountState->checkConnectivity();
accountState->checkConnectivity(AbstractCredentials::NonInteractive);
}
}

View file

@ -28,6 +28,7 @@
#include "accessmanager.h"
#include "account.h"
#include "logger.h"
#include "theme.h"
#include "cookiejar.h"
#include "syncengine.h"
@ -94,6 +95,7 @@ ShibbolethCredentials::ShibbolethCredentials(const QNetworkCookie& cookie)
: _ready(true),
_stillValid(true),
_fetchJobInProgress(false),
_interactiveFetch(true),
_browser(0),
_shibCookie(cookie)
{
@ -191,11 +193,12 @@ bool ShibbolethCredentials::ready() const
return _ready;
}
void ShibbolethCredentials::fetch()
void ShibbolethCredentials::fetch(FetchMode mode)
{
if(_fetchJobInProgress) {
return;
}
_interactiveFetch = mode == Interactive;
if (_user.isEmpty()) {
_user = _account->credentialSetting(QLatin1String(userC)).toString();
@ -357,8 +360,13 @@ void ShibbolethCredentials::slotReadJobDone(QKeychain::Job *job)
_stillValid = true;
_fetchJobInProgress = false;
Q_EMIT fetched();
} else {
} else if (_interactiveFetch) {
showLoginWindow();
} else {
Logger::instance()->postOptionalGuiLog(tr("Reauthentication required"), tr("You need to re-login to continue using the account %1.").arg(_account->displayName()));
_ready = false;
_fetchJobInProgress = false;
Q_EMIT fetched();
}
}

View file

@ -55,7 +55,7 @@ public:
QString user() const Q_DECL_OVERRIDE;
QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE;
bool ready() const Q_DECL_OVERRIDE;
void fetch() Q_DECL_OVERRIDE;
void fetch(FetchMode mode = Interactive) Q_DECL_OVERRIDE;
bool stillValid(QNetworkReply *reply) Q_DECL_OVERRIDE;
void persist() Q_DECL_OVERRIDE;
void invalidateToken() Q_DECL_OVERRIDE;
@ -94,6 +94,7 @@ private:
bool _ready;
bool _stillValid;
bool _fetchJobInProgress;
bool _interactiveFetch;
QPointer<ShibbolethWebView> _browser;
QNetworkCookie _shibCookie;
QString _user;

View file

@ -23,9 +23,10 @@
namespace OCC {
ConnectionValidator::ConnectionValidator(AccountPtr account, QObject *parent)
ConnectionValidator::ConnectionValidator(AccountPtr account, AbstractCredentials::FetchMode credentialsFetchMode, QObject *parent)
: QObject(parent),
_account(account),
_credentialsFetchMode(credentialsFetchMode),
_isCheckingServerAndAuth(false)
{
}
@ -128,7 +129,7 @@ void ConnectionValidator::slotStatusFound(const QUrl&url, const QVariantMap &inf
// We can't proceed with the auth check because we don't have credentials.
// Fetch them now! Once fetched, a new connectivity check will be
// initiated anyway.
creds->fetch();
creds->fetch(_credentialsFetchMode);
// no result is reported
deleteLater();

View file

@ -20,6 +20,7 @@
#include <QVariantMap>
#include <QNetworkReply>
#include "accountfwd.h"
#include "creds/abstractcredentials.h"
namespace OCC {
@ -68,7 +69,7 @@ class OWNCLOUDSYNC_EXPORT ConnectionValidator : public QObject
{
Q_OBJECT
public:
explicit ConnectionValidator(AccountPtr account, QObject *parent = 0);
explicit ConnectionValidator(AccountPtr account, AbstractCredentials::FetchMode credentialsFetchMode, QObject *parent = 0);
enum Status {
Undefined,
@ -114,6 +115,7 @@ private:
QStringList _errors;
AccountPtr _account;
AbstractCredentials::FetchMode _credentialsFetchMode;
bool _isCheckingServerAndAuth;
};

View file

@ -30,6 +30,7 @@ class OWNCLOUDSYNC_EXPORT AbstractCredentials : public QObject
Q_OBJECT
public:
enum FetchMode { Interactive, NonInteractive };
AbstractCredentials();
// No need for virtual destructor - QObject already has one.
@ -48,7 +49,7 @@ public:
virtual QString user() const = 0;
virtual QNetworkAccessManager* getQNAM() const = 0;
virtual bool ready() const = 0;
virtual void fetch() = 0;
virtual void fetch(FetchMode mode = Interactive) = 0;
virtual bool stillValid(QNetworkReply *reply) = 0;
virtual void persist() = 0;
/** Invalidates auth token, or password for basic auth */

View file

@ -56,7 +56,7 @@ bool DummyCredentials::stillValid(QNetworkReply *reply)
return true;
}
void DummyCredentials::fetch()
void DummyCredentials::fetch(FetchMode)
{
Q_EMIT(fetched());
}

View file

@ -35,7 +35,7 @@ public:
QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE;
bool ready() const Q_DECL_OVERRIDE;
bool stillValid(QNetworkReply *reply) Q_DECL_OVERRIDE;
void fetch() Q_DECL_OVERRIDE;
void fetch(FetchMode mode = Interactive) Q_DECL_OVERRIDE;
void persist() Q_DECL_OVERRIDE;
void invalidateToken() Q_DECL_OVERRIDE {}
};

View file

@ -24,6 +24,7 @@
#include "account.h"
#include "accessmanager.h"
#include "logger.h"
#include "utility.h"
#include "theme.h"
#include "syncengine.h"
@ -87,7 +88,8 @@ HttpCredentials::HttpCredentials()
_certificatePath(),
_certificatePasswd(),
_ready(false),
_fetchJobInProgress(false)
_fetchJobInProgress(false),
_interactiveFetch(true)
{
}
@ -97,7 +99,8 @@ HttpCredentials::HttpCredentials(const QString& user, const QString& password, c
_certificatePath(certificatePath),
_certificatePasswd(certificatePasswd),
_ready(true),
_fetchJobInProgress(false)
_fetchJobInProgress(false),
_interactiveFetch(true)
{
}
@ -199,11 +202,12 @@ QString HttpCredentials::fetchUser()
return _user;
}
void HttpCredentials::fetch()
void HttpCredentials::fetch(FetchMode mode)
{
if (_fetchJobInProgress) {
return;
}
_interactiveFetch = mode == Interactive;
// User must be fetched from config file
fetchUser();
@ -274,8 +278,12 @@ void HttpCredentials::slotReadJobDone(QKeychain::Job *job)
job->errorString());
}
bool ok;
QString pwd = queryPassword(&ok, hint);
bool ok = false;
QString pwd;
if (_interactiveFetch)
pwd = queryPassword(&ok, hint);
else
Logger::instance()->postOptionalGuiLog(tr("Reauthentication required"), tr("You need to re-login to continue using the account %1.").arg(_account->displayName()));
_fetchJobInProgress = false;
if (ok) {
_password = pwd;

View file

@ -44,7 +44,7 @@ public:
QString authType() const Q_DECL_OVERRIDE;
QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE;
bool ready() const Q_DECL_OVERRIDE;
void fetch() Q_DECL_OVERRIDE;
void fetch(FetchMode mode = Interactive) Q_DECL_OVERRIDE;
bool stillValid(QNetworkReply *reply) Q_DECL_OVERRIDE;
void persist() Q_DECL_OVERRIDE;
QString user() const Q_DECL_OVERRIDE;
@ -74,6 +74,7 @@ private:
QString _certificatePasswd;
bool _ready;
bool _fetchJobInProgress; //True if the keychain job is in progress or the input dialog visible
bool _interactiveFetch;
};
} // namespace OCC

View file

@ -166,7 +166,7 @@ bool TokenCredentials::ready() const
return _ready;
}
void TokenCredentials::fetch()
void TokenCredentials::fetch(FetchMode)
{
Q_EMIT fetched();
}

View file

@ -46,7 +46,7 @@ public:
QString authType() const Q_DECL_OVERRIDE;
QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE;
bool ready() const Q_DECL_OVERRIDE;
void fetch() Q_DECL_OVERRIDE;
void fetch(FetchMode mode = Interactive) Q_DECL_OVERRIDE;
bool stillValid(QNetworkReply *reply) Q_DECL_OVERRIDE;
void persist() Q_DECL_OVERRIDE;
QString user() const Q_DECL_OVERRIDE;