Skip to content

Commit

Permalink
Stop synchronisation when behind a captive portal
Browse files Browse the repository at this point in the history
Fixes: #11533
  • Loading branch information
erikjv committed Apr 4, 2024
1 parent 32670a7 commit 7dd72f4
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 8 deletions.
17 changes: 17 additions & 0 deletions src/gui/accountstate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() { }
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/gui/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ struct CommandLineOptions
bool logFlush = false;
bool logDebug = false;

bool debugMode = false;
bool debugMode = true;

QString fileToOpen;
};
Expand Down
28 changes: 21 additions & 7 deletions src/gui/owncloudgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
45 changes: 45 additions & 0 deletions src/libsync/accessmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <QLoggingCategory>
#include <QNetworkCookie>
#include <QNetworkCookieJar>
#include <QNetworkInformation>
#include <QNetworkProxy>
#include <QNetworkReply>
#include <QNetworkRequest>
Expand All @@ -35,6 +36,7 @@ Q_LOGGING_CATEGORY(lcAccessManager, "sync.accessmanager", QtInfoMsg)

AccessManager::AccessManager(QObject *parent)
: QNetworkAccessManager(parent)
, _forcedCaptivePortal(false)
{
setCookieJar(new CookieJar);

Expand All @@ -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()
Expand Down Expand Up @@ -151,4 +161,39 @@ QList<QSslError> AccessManager::filterSslErrors(const QList<QSslError> &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
8 changes: 8 additions & 0 deletions src/libsync/accessmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,19 @@ class OWNCLOUDSYNC_EXPORT AccessManager : public QNetworkAccessManager
*/
QList<QSslError> filterSslErrors(const QList<QSslError> &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<QSslCertificate> _customTrustedCaCertificates;
bool _forcedCaptivePortal;
};

} // namespace OCC
Expand Down
4 changes: 4 additions & 0 deletions src/libsync/account.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand All @@ -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);
Expand Down

0 comments on commit 7dd72f4

Please sign in to comment.