Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VPN-4987 [Part 1] - Check for internet connectivity upon activation + VPN-5994 - Inspector command #8834

Merged
merged 10 commits into from
Jan 19, 2024
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 @@ -2146,6 +2146,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
Loading