diff --git a/src/gui/accountstate.cpp b/src/gui/accountstate.cpp index 17cb3b16f30..eefd8c342bf 100644 --- a/src/gui/accountstate.cpp +++ b/src/gui/accountstate.cpp @@ -171,6 +171,22 @@ AccountState::AccountState(AccountPtr account) ownCloudGui::raise(); msgBox->open(); }); + + + connect(_account->accessManager(), &AccessManager::isBehindCaptivePortalChanged, this, [this](bool onoff) { + if (onoff) { + _queueGuard.block(); + } else { + // TODO: empty queue? + _queueGuard.unblock(); + } + }); + if (_account->accessManager()->isBehindCaptivePortal()) { + _queueGuard.block(); + } else { + // TODO: empty queue? + _queueGuard.unblock(); + } } AccountState::~AccountState() { } @@ -247,6 +263,7 @@ void AccountState::setState(State state) } else if (_state == Connected && Utility::internetConnectionIsMetered() && ConfigFile().pauseSyncWhenMetered()) { _state = PausedDueToMetered; } + // Do we need an extra state PausedDueToCaptivePortal? } // might not have changed but the underlying _connectionErrors might have diff --git a/src/gui/main.cpp b/src/gui/main.cpp index d7fc389bf04..8ec844dd2ad 100644 --- a/src/gui/main.cpp +++ b/src/gui/main.cpp @@ -85,7 +85,7 @@ struct CommandLineOptions bool logFlush = false; bool logDebug = false; - bool debugMode = false; + bool debugMode = true; QString fileToOpen; }; diff --git a/src/gui/owncloudgui.cpp b/src/gui/owncloudgui.cpp index 53520da5381..4d70023e4e1 100644 --- a/src/gui/owncloudgui.cpp +++ b/src/gui/owncloudgui.cpp @@ -641,17 +641,31 @@ void ownCloudGui::updateContextMenu() _contextMenu->addSeparator(); if (_app->debugMode()) { - auto *crashMenu = _contextMenu->addMenu(QStringLiteral("Debug actions")); - crashMenu->addAction(QStringLiteral("Crash if asserts enabled - OC_ENSURE"), _app, [] { + auto *debugMenu = _contextMenu->addMenu(QStringLiteral("Debug actions")); + debugMenu->addAction(QStringLiteral("Crash if asserts enabled - OC_ENSURE"), _app, [] { if (OC_ENSURE(false)) { Q_UNREACHABLE(); } }); - crashMenu->addAction(QStringLiteral("Crash if asserts enabled - Q_ASSERT"), _app, [] { Q_ASSERT(false); }); - crashMenu->addAction(QStringLiteral("Crash now - Utility::crash()"), _app, [] { Utility::crash(); }); - crashMenu->addAction(QStringLiteral("Crash now - OC_ENFORCE()"), _app, [] { OC_ENFORCE(false); }); - crashMenu->addAction(QStringLiteral("Crash now - qFatal"), _app, [] { qFatal("la Qt fatale"); }); - crashMenu->addAction(QStringLiteral("Restart now"), _app, [] { RestartManager::requestRestart(); }); + debugMenu->addAction(QStringLiteral("Crash if asserts enabled - Q_ASSERT"), _app, [] { Q_ASSERT(false); }); + debugMenu->addAction(QStringLiteral("Crash now - Utility::crash()"), _app, [] { Utility::crash(); }); + debugMenu->addAction(QStringLiteral("Crash now - OC_ENFORCE()"), _app, [] { OC_ENFORCE(false); }); + debugMenu->addAction(QStringLiteral("Crash now - qFatal"), _app, [] { qFatal("la Qt fatale"); }); + debugMenu->addAction(QStringLiteral("Restart now"), _app, [] { RestartManager::requestRestart(); }); + debugMenu->addSeparator(); + auto captivePortalCheckbox = debugMenu->addAction(QStringLiteral("Behind Captive Portal")); + captivePortalCheckbox->setCheckable(true); + + for (const auto &a : accountList) { + if (a->account()->accessManager()->forcedCaptivePortal()) { + captivePortalCheckbox->setChecked(true); + } + } + connect(captivePortalCheckbox, &QAction::triggered, [](bool checked) { + for (const auto &a : AccountManager::instance()->accounts()) { + a->account()->accessManager()->setForcedCaptivePortal(checked); + } + }); } _contextMenu->addSeparator(); diff --git a/src/libsync/accessmanager.cpp b/src/libsync/accessmanager.cpp index 35fe0659298..1f144be9930 100644 --- a/src/libsync/accessmanager.cpp +++ b/src/libsync/accessmanager.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,7 @@ Q_LOGGING_CATEGORY(lcAccessManager, "sync.accessmanager", QtInfoMsg) AccessManager::AccessManager(QObject *parent) : QNetworkAccessManager(parent) + , _forcedCaptivePortal(false) { setCookieJar(new CookieJar); @@ -47,6 +49,14 @@ AccessManager::AccessManager(QObject *parent) filtered.end()); reply->ignoreSslErrors(filtered); }); + + if (auto *qNetInfo = QNetworkInformation::instance()) { + connect(qNetInfo, &QNetworkInformation::isBehindCaptivePortalChanged, this, [this](bool onoff) { + if (!_forcedCaptivePortal) { + emit isBehindCaptivePortalChanged(onoff); + } + }); + } } QByteArray AccessManager::generateRequestId() @@ -151,4 +161,39 @@ QList AccessManager::filterSslErrors(const QList &errors) return filtered; } +bool AccessManager::isBehindCaptivePortal() +{ + if (_forcedCaptivePortal) { + return true; + } + + if (auto *qNetInfo = QNetworkInformation::instance()) { + return qNetInfo->isBehindCaptivePortal(); + } + + return false; +} + +bool AccessManager::forcedCaptivePortal() +{ + return _forcedCaptivePortal; +} + +void AccessManager::setForcedCaptivePortal(bool onoff) +{ + if (_forcedCaptivePortal != onoff) { + _forcedCaptivePortal = onoff; + qCDebug(lcUtility) << "Switching forced captive portal to" << onoff; + + if (auto *qNetInfo = QNetworkInformation::instance()) { + // Emit a signal only if we are/were simulating being behind a captive portal. + // In the case we were simulating (but stop doing so now), but in reality are still + // behind a portal, do not emit anything. + if (!qNetInfo->isBehindCaptivePortal()) { + emit isBehindCaptivePortalChanged(onoff); + } + } + } +} + } // namespace OCC diff --git a/src/libsync/accessmanager.h b/src/libsync/accessmanager.h index 75c1005132a..8375697dfb8 100644 --- a/src/libsync/accessmanager.h +++ b/src/libsync/accessmanager.h @@ -55,11 +55,19 @@ class OWNCLOUDSYNC_EXPORT AccessManager : public QNetworkAccessManager */ QList filterSslErrors(const QList &errors) const; + bool isBehindCaptivePortal(); + bool forcedCaptivePortal(); + void setForcedCaptivePortal(bool onoff); + +signals: + void isBehindCaptivePortalChanged(bool state); + protected: QNetworkReply *createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData = nullptr) override; private: QSet _customTrustedCaCertificates; + bool _forcedCaptivePortal; }; } // namespace OCC diff --git a/src/libsync/account.cpp b/src/libsync/account.cpp index a53921ab4b2..f14fc1ac44c 100644 --- a/src/libsync/account.cpp +++ b/src/libsync/account.cpp @@ -172,11 +172,14 @@ AbstractCredentials *Account::credentials() const void Account::setCredentials(AbstractCredentials *cred) { + bool forcedCaptivePortal = false; + // set active credential manager QNetworkCookieJar *jar = nullptr; if (_am) { jar = _am->cookieJar(); jar->setParent(nullptr); + forcedCaptivePortal = _am->isBehindCaptivePortal(); _am->deleteLater(); } @@ -186,6 +189,7 @@ void Account::setCredentials(AbstractCredentials *cred) cred->setAccount(this); _am = _credentials->createAM(); + _am->setForcedCaptivePortal(forcedCaptivePortal); // the network access manager takes ownership when setCache is called, so we have to reinitialize it every time we reset the manager _networkCache = new QNetworkDiskCache(this);