Skip to content

Commit

Permalink
VPN-4987 [Part 1] - Check for internet connectivity upon activation + V…
Browse files Browse the repository at this point in the history
…PN-5994 - Inspector command (#8834)

* rebase

* Reachability

* remove m_currentReachability

* Check internet connection during activation

* Rename to isDeviceConnected

* rename signal to isDeviceConnectedChanged

* emit signal when isDeviceConnected is true

* load default backend to access reachability()

* Put this behind a feature flag for now until UI is done

* Only loadDefaultBackend if Qt>=6.4
  • Loading branch information
Gela authored Jan 19, 2024
1 parent 5a4d87a commit 95a0acb
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 2 deletions.
20 changes: 20 additions & 0 deletions src/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#include "controller.h"

#include <QNetworkInformation>

#include "app.h"
#include "apppermission.h"
#include "captiveportal/captiveportal.h"
Expand All @@ -21,6 +23,7 @@
#include "models/servercountrymodel.h"
#include "mozillavpn.h"
#include "networkrequest.h"
#include "networkwatcher.h"
#include "rfc/rfc1112.h"
#include "rfc/rfc1918.h"
#include "rfc/rfc4193.h"
Expand Down Expand Up @@ -931,6 +934,23 @@ bool Controller::activate(const ServerData& serverData,
return true;
}

if (Feature::get(Feature::Feature_checkConnectivityOnActivation)
->isSupported()) {
// Ensure that the device is connected to the Internet.
if (MozillaVPN::instance()->networkWatcher()->getReachability() ==
QNetworkInformation::Reachability::Disconnected) {
logger.debug() << "Internet probe failed during controller activation. "
"Device has no network connectivity.";
m_isDeviceConnected = false;
emit isDeviceConnectedChanged();
return false;
}
if (!m_isDeviceConnected) {
m_isDeviceConnected = true;
emit isDeviceConnectedChanged();
}
}

// Before attempting to enable VPN connection we should check that the
// subscription is active.
setState(StateCheckSubscription);
Expand Down
5 changes: 5 additions & 0 deletions src/controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class Controller : public QObject, public LogSerializer {
void updateRequired();
void deleteOSTunnelConfig();
void startHandshakeTimer();
bool isDeviceConnected() const { return m_isDeviceConnected; }

const ServerData& currentServer() const { return m_serverData; }

Expand Down Expand Up @@ -109,6 +110,8 @@ class Controller : public QObject, public LogSerializer {
NOTIFY enableDisconnectInConfirmingChanged);
Q_PROPERTY(bool silentServerSwitchingSupported READ
silentServerSwitchingSupported CONSTANT);
Q_PROPERTY(bool isDeviceConnected READ isDeviceConnected NOTIFY
isDeviceConnectedChanged);

#ifdef MZ_DUMMY
// This is just for testing purposes. Not exposed in prod.
Expand Down Expand Up @@ -141,6 +144,7 @@ class Controller : public QObject, public LogSerializer {
void readyToBackendFailure();
void readyToServerUnavailable(bool pingReceived);
void activationBlockedForCaptivePortal();
void isDeviceConnectedChanged();

#ifdef MZ_DUMMY
void currentServerChanged();
Expand Down Expand Up @@ -204,6 +208,7 @@ class Controller : public QObject, public LogSerializer {

QScopedPointer<ControllerImpl> m_impl;
bool m_portalDetected = false;
bool m_isDeviceConnected = true;

// Server data can change while the controller is busy completing an
// activation or a server switch because they are managed by the
Expand Down
7 changes: 7 additions & 0 deletions src/feature/featurelist.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ FEATURE(captivePortal, // Feature ID
QStringList(), // feature dependencies
FeatureCallback_captivePortal)

FEATURE(checkConnectivityOnActivation, // Feature ID
"Check Connectivity On Activation", // Feature name
FeatureCallback_true, // Can be flipped on
FeatureCallback_true, // Can be flipped off
QStringList(), // feature dependencies
FeatureCallback_false)

FEATURE(customDNS, // Feature ID
"Custom DNS", // Feature name
FeatureCallback_true, // Can be flipped on
Expand Down
14 changes: 14 additions & 0 deletions src/mozillavpn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2162,6 +2162,20 @@ void MozillaVPN::registerInspectorCommands() {
return QJsonObject();
});

InspectorHandler::registerCommand(
"force_no_network",
"Mock the internet connection being down by passing true, pass false to "
"restore",
1, [](InspectorHandler*, const QList<QByteArray>& arguments) {
QJsonObject obj;
QByteArray byteArray = arguments[1].toLower();
// Check if the byte array contains the string "true"
bool forceDisconnection = byteArray.contains("true");
MozillaVPN::instance()->networkWatcher()->simulateDisconnection(
forceDisconnection);
return QJsonObject();
});

InspectorHandler::registerCommand(
"force_connection_health",
"Force VPN connection health stability. Possible values are: stable, "
Expand Down
16 changes: 15 additions & 1 deletion src/networkwatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <QMetaEnum>
#include <QNetworkInformation>
#include <QtGlobal>

#include "controller.h"
#include "leakdetector.h"
Expand Down Expand Up @@ -87,6 +88,13 @@ void NetworkWatcher::initialize() {
m_impl->start();
}

#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
// This call creates an instance of QNetworkInformation which can be used
// later on to check other network related attributes such as network type, or
// whether or not the network is behind captive portal.
QNetworkInformation::loadDefaultBackend();
#endif

connect(settingsHolder, &SettingsHolder::unsecuredNetworkAlertChanged, this,
&NetworkWatcher::settingsChanged);
connect(settingsHolder, &SettingsHolder::captivePortalAlertChanged, this,
Expand Down Expand Up @@ -170,8 +178,14 @@ void NetworkWatcher::notificationClicked(NotificationHandler::Message message) {
}

QNetworkInformation::Reachability NetworkWatcher::getReachability() {
if (QNetworkInformation::instance()) {
if (m_simulatedDisconnection) {
return QNetworkInformation::Reachability::Disconnected;
} else if (QNetworkInformation::instance()) {
return QNetworkInformation::instance()->reachability();
}
return QNetworkInformation::Reachability::Unknown;
}

void NetworkWatcher::simulateDisconnection(bool simulatedDisconnection) {
m_simulatedDisconnection = simulatedDisconnection;
}
8 changes: 7 additions & 1 deletion src/networkwatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@ class NetworkWatcher final : public QObject {

void initialize();

// public for the inspector.
// Public for the Inspector.
void unsecuredNetwork(const QString& networkName, const QString& networkId);
// Used for the Inspector. simulateOffline = true to mock being disconnected,
// false to restore.
void simulateDisconnection(bool simulatedDisconnection);

QNetworkInformation::Reachability getReachability();

Expand All @@ -48,6 +51,9 @@ class NetworkWatcher final : public QObject {

// This is used to connect NotificationHandler lazily.
bool m_firstNotification = true;

// Used to simulate network disconnection in the Inspector
bool m_simulatedDisconnection = false;
};

#endif // NETWORKWATCHER_H

0 comments on commit 95a0acb

Please sign in to comment.