diff --git a/.github/workflows/wasm.yaml b/.github/workflows/wasm.yaml index e5c75e67ac..de1f8db7c5 100644 --- a/.github/workflows/wasm.yaml +++ b/.github/workflows/wasm.yaml @@ -45,6 +45,9 @@ jobs: - name: Setup emsdk uses: mymindstorm/setup-emsdk@v7 + - name: Set up gecko driver + uses: browser-actions/setup-geckodriver@latest + - name: Compiling shell: bash run: | @@ -122,10 +125,8 @@ jobs: with: name: WebAssembly Build Qt6 # Destination path - path: wasm - - - uses: browser-actions/setup-geckodriver@latest - + path: wasm + - name: Build addons shell: bash run: ./scripts/addon/generate_all_tests.py -q /opt/$QTVERSION/gcc_64/bin diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c3fceecd6..72860c32b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,7 +79,7 @@ if(NOT DEFINED BUILD_ID) endif() ## Toolchain Setup -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) if(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.17) cmake_policy(SET CMP0099 OLD) diff --git a/README.md b/README.md index 80e1ed61f0..829f75744e 100644 --- a/README.md +++ b/README.md @@ -46,11 +46,19 @@ cd mozilla-vpn-client git submodule update --init ``` -## How to build from the source code +## Minimum build requirements -In order to build this application, you need to install a few dependencies. +This list is not comprehensive. Different platforms may require other tools to be installed. +Check out the platform section for more information on your specific platform. -#### Install Qt6 +- [C++20](https://en.cppreference.com/w/cpp/20) +- [Qt6](https://www.qt.io/product/qt6) +- [Python 3](https://www.python.org/downloads/) +- [Cmake > 3.16](https://cmake.org/install/) +- [Rust](https://www.rust-lang.org/tools/install) +- [Go](https://go.dev/) + +### Installing Qt6 Qt6 can be installed in a number of ways: @@ -80,7 +88,7 @@ Qt6 can be installed in a number of ways: ./scripts/utils/qt6_compile.sh ``` -#### Install Python 3 +### Installing Python 3 [Python](https://www.python.org/) >= 3.6 is required. You also need to install a few python modules using [pip](https://pypi.org/): @@ -91,7 +99,7 @@ pip install -r requirements.txt --user (`pip3` may need to be substituted for `pip` in the above line.) -#### Install CMake +### Installing CMake There are many ways to install [CMake](https://cmake.org). @@ -101,17 +109,17 @@ On macOS, it is easy to do with [Homebrew](https://brew.sh/). After brew install cmake ``` -#### Install rust +### Installing Rust [Rust](https://www.rust-lang.org/) is required for desktop builds (macOS, Linux and Windows). See the official rust documentation to know how to install it. -#### What's next? +### What's next? We support the following platforms: Linux, Windows, macOS, iOS, Android and WASM. Each one is unique and it has a different section in this document. -### How to build from source code for Desktop +## How to build from source code for Desktop On deskop platforms, such as Windows, Linux and macOS, we build the Mozilla VPN using CMake, and as long as the required dependencies can be located in your @@ -306,6 +314,9 @@ This step needs to be executed each time Xcode updates. There are two ways to build the project on iOS, using the legacy Qt build system `qmake` and we have also added experimental support for `cmake`. +> **Note**: Due to lack of low level networking support, it is not possible to turn on +> the VPN from the iOS simulator in XCode. + #### Building with QMake 1. On iOS, we compile the app using @@ -546,11 +557,11 @@ https://mozilla-mobile.github.io/mozilla-vpn-client/inspector/) to interact with the app. Connect the inspector to the app using the web-socket interface. On desktop, use `ws://localhost:8765`. -The inspector offers a number of tools to help debug and navigate through the VPN client: +The inspector offers a number of tools to help debug and navigate through the VPN client: * **Shell:** By default the inspector link will take you to the Shell. From there type `help` to see the list of available commands. * **Logs:** Will constantly output all the app activities happening in real time. This information includes the timesamp, component and message. From the left column you can select which component(s) you'd like to monitor. * **Network Inspector:** Includes a list of all incoming and outgoing network requests. This is especially helpful when debugging network related issues or monitoring how the app communicates with external components such as the Guardian. -* **QML Inspector:** Allows you to identify and inspect all QML components in the app by mirroring the local VPN client running on your machine and highlighting components by clicking on the QML instance on the right. +* **QML Inspector:** Allows you to identify and inspect all QML components in the app by mirroring the local VPN client running on your machine and highlighting components by clicking on the QML instance on the right. ![inspector_snapshot](https://user-images.githubusercontent.com/3746552/204422879-0799cbd8-91cd-4601-8df8-0d0e9f7cd887.png) diff --git a/linux/debian/control b/linux/debian/control index 28ef9ca18e..5a10d081be 100644 --- a/linux/debian/control +++ b/linux/debian/control @@ -5,8 +5,9 @@ Maintainer: mozilla Build-Depends: debhelper (>= 9.20160709), cdbs, cmake (>= 3.16~) | cmake-mozilla (>= 3.16~), - quilt, flex, + gcc (>=4:8.0.0~) | gcc-8, + g++ (>=4:8.0.0~) | g++-8, golang (>=2:1.13~) | golang-1.13, cargo, python3-yaml, @@ -63,5 +64,3 @@ Depends: libpolkit-gobject-1-0 (>=0.105), qt6-qpa-plugins (>=6.2.0~) Description: A fast, secure and easy to use VPN. Built by the makers of Firefox. Read more on https://vpn.mozilla.org - - diff --git a/linux/debian/rules b/linux/debian/rules index 61b583e55f..8386d06c99 100755 --- a/linux/debian/rules +++ b/linux/debian/rules @@ -11,6 +11,12 @@ ifneq (ok,$(dpkg --compare-versions $(GOLANG_NATIVE_VERSION) ge 2:1.13 && echo o export PATH := $(GODIR)/bin:$(PATH) endif +GCC_NATIVE_VERSION = $(shell gcc -dumpversion 2>/dev/null || echo 0) +ifneq (ok,$(shell dpkg --compare-versions $(GCC_NATIVE_VERSION) ge 8 && echo ok)) + export CC := gcc-8 + export CXX := g++-8 +endif + %: dh $@ --with=systemd --warn-missing diff --git a/nebula/ui/components/VPNBoldInterLabel.qml b/nebula/ui/components/VPNBoldInterLabel.qml index e3f5b2a140..a45832addd 100644 --- a/nebula/ui/components/VPNBoldInterLabel.qml +++ b/nebula/ui/components/VPNBoldInterLabel.qml @@ -13,6 +13,7 @@ Text { lineHeight: VPNTheme.theme.controllerInterLineHeight color: VPNTheme.theme.fontColorDark wrapMode: Text.Wrap + horizontalAlignment: Qt.AlignLeft Accessible.role: Accessible.StaticText Accessible.name: text diff --git a/nebula/ui/components/VPNSubtitle.qml b/nebula/ui/components/VPNSubtitle.qml index fc7bd8969f..6e98fbb991 100644 --- a/nebula/ui/components/VPNSubtitle.qml +++ b/nebula/ui/components/VPNSubtitle.qml @@ -17,4 +17,6 @@ Text { color: VPNTheme.theme.fontColor lineHeightMode: Text.FixedHeight lineHeight: VPNTheme.theme.labelLineHeight + Accessible.role: Accessible.StaticText + Accessible.name: text } diff --git a/nebula/ui/components/forms/VPNPasswordInput.qml b/nebula/ui/components/forms/VPNPasswordInput.qml index efa495e763..fdec277b0d 100644 --- a/nebula/ui/components/forms/VPNPasswordInput.qml +++ b/nebula/ui/components/forms/VPNPasswordInput.qml @@ -11,8 +11,7 @@ import components.forms 0.1 VPNTextField { property bool charactersMasked: true property bool isValid: true - property alias button: toggleButton - property alias placeholder: passwordInput._placeholderText + property alias button: showHidePasswordButton id: passwordInput @@ -25,12 +24,10 @@ VPNTextField { echoMode: charactersMasked ? TextInput.Password : TextInput.Normal hasError: !isValid - height: VPNTheme.theme.rowHeight - rightPadding: VPNTheme.theme.windowMargin * 0.5 + toggleButton.width - width: parent.width + rightPadding: VPNTheme.theme.windowMargin * 0.5 + showHidePasswordButton.width VPNIconButton { - id: toggleButton + id: showHidePasswordButton accessibleName: passwordInput.charactersMasked ? VPNl18n.InAppAuthShowPassword @@ -42,9 +39,10 @@ VPNTextField { } height: parent.height - VPNTheme.theme.listSpacing width: parent.height - VPNTheme.theme.listSpacing + onClicked: passwordInput.charactersMasked = !passwordInput.charactersMasked Image { - anchors.centerIn: toggleButton + anchors.centerIn: showHidePasswordButton fillMode: Image.PreserveAspectFit source: passwordInput.charactersMasked ? "qrc:/nebula/resources/eye-hidden.svg" @@ -53,18 +51,13 @@ VPNTextField { sourceSize.width: VPNTheme.theme.iconSize * 1.5 } - function toggleVisibility() { - passwordInput.charactersMasked = !passwordInput.charactersMasked; - } - - // Temporary workaround for QTBUG-78813: TextInput prevents touch events + // workaround for QTBUG-78813: TextInput prevents touch events // from reaching other MouseAreas. // https://bugreports.qt.io/browse/QTBUG-78813 MouseArea { + onPressed: showHidePasswordButton.clicked() anchors.fill: parent - onPressed: { - toggleButton.toggleVisibility(); - } + enabled: ["android", "ios"].includes(Qt.platform.os) } } } diff --git a/nebula/ui/components/forms/VPNSearchBar.qml b/nebula/ui/components/forms/VPNSearchBar.qml index 203bda02c5..0c28c5a592 100644 --- a/nebula/ui/components/forms/VPNSearchBar.qml +++ b/nebula/ui/components/forms/VPNSearchBar.qml @@ -29,7 +29,6 @@ ColumnLayout { Accessible.searchEdit: true Layout.fillWidth: true - _accessibleName: _placeholderText background: VPNInputBackground {} leftInset: VPNTheme.theme.windowMargin * 3 leftPadding: VPNTheme.theme.windowMargin * 3 diff --git a/nebula/ui/components/forms/VPNTextField.qml b/nebula/ui/components/forms/VPNTextField.qml index 0573d6356a..2d156a2997 100644 --- a/nebula/ui/components/forms/VPNTextField.qml +++ b/nebula/ui/components/forms/VPNTextField.qml @@ -14,13 +14,11 @@ TextField { property bool showInteractionStates: true property bool forceBlurOnOutsidePress: true property alias _placeholderText: centeredPlaceholderText.text - property string _accessibleName: _placeholderText - property string _accessibleDescription: "" id: textField - Accessible.name: _accessibleName - Accessible.description: _accessibleDescription + Accessible.name: centeredPlaceholderText.text + Accessible.description: centeredPlaceholderText.text Accessible.focused: textField.focus Layout.alignment: Qt.AlignVCenter Layout.preferredHeight: VPNTheme.theme.rowHeight diff --git a/nebula/ui/components/inAppAuth/VPNInAppAuthenticationInputs.qml b/nebula/ui/components/inAppAuth/VPNInAppAuthenticationInputs.qml index f20fe9273d..c8d6efafce 100644 --- a/nebula/ui/components/inAppAuth/VPNInAppAuthenticationInputs.qml +++ b/nebula/ui/components/inAppAuth/VPNInAppAuthenticationInputs.qml @@ -67,7 +67,7 @@ ColumnLayout { ToolTip { property bool _isSignUp: VPNAuthInApp.state === VPNAuthInApp.StateSignUp id: toolTip - visible: _isSignUp && passwordInput.activeFocus + visible: _isSignUp && passwordInput.text.length > 0 && passwordInput.activeFocus padding: VPNTheme.theme.windowMargin x: VPNTheme.theme.vSpacing y: passwordInput.y - height - 4 diff --git a/src/apps/vpn/appconstants.h b/src/apps/vpn/appconstants.h index a5f78cfbcc..1d6cd8e140 100644 --- a/src/apps/vpn/appconstants.h +++ b/src/apps/vpn/appconstants.h @@ -109,6 +109,9 @@ constexpr const char* ADDON_SETTINGS_GROUP = "addons"; #define PRODBETAEXPR(type, functionName, prod, beta) \ inline type functionName() { return Constants::inProduction() ? prod : beta; } +constexpr const char* MOZILLA_VPN_SUMO_URL = + "https://support.mozilla.org/en-US/products/firefox-private-network-vpn"; + PRODBETAEXPR( const char*, benchmarkUploadUrl, "https://benchmark.vpn.mozilla.org/upload", "https://dev.vpn-network-benchmark.nonprod.webservices.mozgcp.net/upload"); diff --git a/src/apps/vpn/controller.cpp b/src/apps/vpn/controller.cpp index 069d9b779f..0cff268dbe 100644 --- a/src/apps/vpn/controller.cpp +++ b/src/apps/vpn/controller.cpp @@ -53,16 +53,16 @@ constexpr const int MULLVAD_PROXY_RANGE_LENGTH = 20; namespace { Logger logger("Controller"); -ControllerImpl::Reason stateToReason(Controller::State state) { +Controller::Reason stateToReason(Controller::State state) { if (state == Controller::StateSwitching) { - return ControllerImpl::ReasonSwitching; + return Controller::ReasonSwitching; } if (state == Controller::StateConfirming) { - return ControllerImpl::ReasonConfirming; + return Controller::ReasonConfirming; } - return ControllerImpl::ReasonNone; + return Controller::ReasonNone; } } // namespace @@ -191,11 +191,11 @@ bool Controller::activate() { clearRetryCounter(); - activateInternal(); + activateInternal(stateToReason(m_state)); return true; } -void Controller::activateInternal(bool forcePort53) { +void Controller::activateInternal(Reason reason, bool forcePort53) { logger.debug() << "Activation internal"; Q_ASSERT(m_impl); @@ -239,7 +239,7 @@ void Controller::activateInternal(bool forcePort53) { exitHop.m_excludedAddresses.append(exitHop.m_server.ipv6AddrIn()); // If requested, force the use of port 53/DNS. - if (settingsHolder->tunnelPort53() || forcePort53) { + if (forcePort53) { exitHop.m_server.forcePort(53); } // For single-hop, they are the same @@ -257,7 +257,7 @@ void Controller::activateInternal(bool forcePort53) { return; } // If requested, force the use of port 53/DNS. - if (settingsHolder->tunnelPort53() || forcePort53) { + if (forcePort53) { hop.m_server.forcePort(53); } @@ -292,10 +292,10 @@ void Controller::activateInternal(bool forcePort53) { m_ping_canary.start(m_activationQueue.first().m_server.ipv4AddrIn(), "0.0.0.0/0"); logger.info() << "Canary Ping Started"; - activateNext(); + activateNext(reason); } -void Controller::activateNext() { +void Controller::activateNext(Reason reason) { MozillaVPN* vpn = MozillaVPN::instance(); const Device* device = vpn->deviceModel()->currentDevice(vpn->keys()); if (device == nullptr) { @@ -307,7 +307,7 @@ void Controller::activateNext() { logger.debug() << "Activating peer" << logger.keys(hop.m_server.publicKey()); m_handshakeTimer.start(HANDSHAKE_TIMEOUT_SEC * 1000); - m_impl->activate(hop, device, vpn->keys(), stateToReason(m_state)); + m_impl->activate(hop, device, vpn->keys(), reason); // Move to the confirming state if we are awaiting any connection handshakes. setState(StateConfirming); @@ -336,7 +336,7 @@ bool Controller::silentSwitchServers() { vpn->currentServer()->exitServerPublicKey()); // Activate the first connection to kick off the server switch. - activateInternal(); + activateInternal(ReasonSwitching); return true; } @@ -382,7 +382,7 @@ void Controller::connected(const QString& pubkey) { // Start the next connection if there is more work to do. m_activationQueue.removeFirst(); if (!m_activationQueue.isEmpty()) { - activateNext(); + activateNext(stateToReason(m_state)); return; } } @@ -424,14 +424,14 @@ void Controller::handshakeTimeout() { // Try again, again if there are sufficient retries left. ++m_connectionRetry; emit connectionRetryChanged(); - if (m_connectionRetry == 1 && !SettingsHolder::instance()->tunnelPort53()) { + if (m_connectionRetry == 1) { logger.info() << "Connection Attempt: Using Port 53 Option this time."; // On the first retry, opportunisticly try again using the port 53 // option enabled, if that feature is disabled. - activateInternal(true); + activateInternal(stateToReason(m_state), true); return; } else if (m_connectionRetry < CONNECTION_MAX_RETRY) { - activateInternal(); + activateInternal(stateToReason(m_state)); return; } diff --git a/src/apps/vpn/controller.h b/src/apps/vpn/controller.h index c07e1406b5..c6100cd82d 100644 --- a/src/apps/vpn/controller.h +++ b/src/apps/vpn/controller.h @@ -48,6 +48,12 @@ class Controller final : public QObject { }; Q_ENUM(State) + enum Reason { + ReasonNone = 0, + ReasonSwitching, + ReasonConfirming, + }; + private: Q_PROPERTY(State state READ state NOTIFY stateChanged) Q_PROPERTY(qint64 time READ time NOTIFY timeChanged) @@ -134,8 +140,8 @@ class Controller final : public QObject { QList getAllowedIPAddressRanges(const Server& server); QStringList getExcludedAddresses(const Server& server); - void activateInternal(bool forceDNSPort = false); - void activateNext(); + void activateInternal(Reason reason, bool forceDNSPort = false); + void activateNext(Reason reason); void clearRetryCounter(); void clearConnectedTime(); diff --git a/src/apps/vpn/controllerimpl.h b/src/apps/vpn/controllerimpl.h index b6c4fc6e5c..76d37831af 100644 --- a/src/apps/vpn/controllerimpl.h +++ b/src/apps/vpn/controllerimpl.h @@ -30,12 +30,6 @@ class ControllerImpl : public QObject { virtual ~ControllerImpl() = default; - enum Reason { - ReasonNone = 0, - ReasonSwitching, - ReasonConfirming, - }; - // This method is called to initialize the controller. The initialization // is completed when the signal "initialized" is emitted. virtual void initialize(const Device* device, const Keys* keys) = 0; @@ -46,11 +40,11 @@ class ControllerImpl : public QObject { // state terminates when the "connected" (or the "disconnected") signal is // received. virtual void activate(const HopConnection& hop, const Device* device, - const Keys* keys, Reason Reason) = 0; + const Keys* keys, Controller::Reason Reason) = 0; // This method terminates the VPN tunnel. The VPN client is in // "disconnecting" state until the "disconnected" signal is received. - virtual void deactivate(Reason reason) = 0; + virtual void deactivate(Controller::Reason reason) = 0; // This method is used to retrieve the VPN tunnel status (mainly the number // of bytes sent and received). It's called always when the VPN tunnel is diff --git a/src/apps/vpn/externalophandler.cpp b/src/apps/vpn/externalophandler.cpp index 9a7c5f1681..6c99311ed7 100644 --- a/src/apps/vpn/externalophandler.cpp +++ b/src/apps/vpn/externalophandler.cpp @@ -46,7 +46,7 @@ void ExternalOpHandler::unregisterBlocker(Blocker* blocker) { m_blockers.removeOne(blocker); } -void ExternalOpHandler::request(Op op) { +bool ExternalOpHandler::request(Op op) { logger.debug() << "Op request received"; MozillaVPN* vpn = MozillaVPN::instance(); @@ -54,7 +54,7 @@ void ExternalOpHandler::request(Op op) { for (Blocker* blocker : m_blockers) { if (blocker->maybeBlockRequest(op)) { logger.debug() << "Operation rejected by a blocker"; - return; + return false; } } @@ -78,4 +78,6 @@ void ExternalOpHandler::request(Op op) { case OpCloseEvent: break; } + + return true; } diff --git a/src/apps/vpn/externalophandler.h b/src/apps/vpn/externalophandler.h index bef79e34f3..61559d0027 100644 --- a/src/apps/vpn/externalophandler.h +++ b/src/apps/vpn/externalophandler.h @@ -29,7 +29,7 @@ class ExternalOpHandler final : public QObject { static ExternalOpHandler* instance(); - void request(Op op); + [[nodiscard]] bool request(Op op); void registerBlocker(Blocker* blocker); void unregisterBlocker(Blocker* blocker); diff --git a/src/apps/vpn/frontend/navigator.cpp b/src/apps/vpn/frontend/navigator.cpp index 7ad1838ffc..7298d77b74 100644 --- a/src/apps/vpn/frontend/navigator.cpp +++ b/src/apps/vpn/frontend/navigator.cpp @@ -623,7 +623,11 @@ void Navigator::removeItem(QObject* item) { bool Navigator::eventHandled() { logger.debug() << "Close event handled"; - ExternalOpHandler::instance()->request(ExternalOpHandler::OpCloseEvent); + if (!ExternalOpHandler::instance()->request( + ExternalOpHandler::OpCloseEvent)) { + // Something is blocking the close event handler" + return true; + } #if defined(MVPN_ANDROID) || defined(MVPN_WASM) if (m_screenHistory.isEmpty()) { diff --git a/src/apps/vpn/localsocketcontroller.cpp b/src/apps/vpn/localsocketcontroller.cpp index f38a37afdd..4d194518af 100644 --- a/src/apps/vpn/localsocketcontroller.cpp +++ b/src/apps/vpn/localsocketcontroller.cpp @@ -116,7 +116,7 @@ void LocalSocketController::daemonConnected() { void LocalSocketController::activate(const HopConnection& hop, const Device* device, const Keys* keys, - Reason reason) { + Controller::Reason reason) { Q_UNUSED(reason); QJsonObject json; @@ -161,7 +161,7 @@ void LocalSocketController::activate(const HopConnection& hop, write(json); } -void LocalSocketController::deactivate(Reason reason) { +void LocalSocketController::deactivate(Controller::Reason reason) { logger.debug() << "Deactivating"; if (m_daemonState != eReady) { @@ -170,7 +170,7 @@ void LocalSocketController::deactivate(Reason reason) { return; } - if (reason == ReasonSwitching) { + if (reason == Controller::ReasonSwitching) { logger.debug() << "No disconnect for quick server switching"; emit disconnected(); return; diff --git a/src/apps/vpn/localsocketcontroller.h b/src/apps/vpn/localsocketcontroller.h index 24c3489ce5..e00bb2d63b 100644 --- a/src/apps/vpn/localsocketcontroller.h +++ b/src/apps/vpn/localsocketcontroller.h @@ -24,9 +24,9 @@ class LocalSocketController final : public ControllerImpl { void initialize(const Device* device, const Keys* keys) override; void activate(const HopConnection& hop, const Device* device, - const Keys* keys, Reason Reason) override; + const Keys* keys, Controller::Reason Reason) override; - void deactivate(Reason reason) override; + void deactivate(Controller::Reason reason) override; void checkStatus() override; diff --git a/src/apps/vpn/notificationhandler.cpp b/src/apps/vpn/notificationhandler.cpp index 0c0727ceb2..252d384969 100644 --- a/src/apps/vpn/notificationhandler.cpp +++ b/src/apps/vpn/notificationhandler.cpp @@ -301,8 +301,10 @@ void NotificationHandler::messageClickHandle() { return; } - ExternalOpHandler::instance()->request( - ExternalOpHandler::OpNotificationClicked); + if (!ExternalOpHandler::instance()->request( + ExternalOpHandler::OpNotificationClicked)) { + return; + } emit notificationClicked(m_lastMessage); m_lastMessage = None; diff --git a/src/apps/vpn/platforms/android/androidcontroller.cpp b/src/apps/vpn/platforms/android/androidcontroller.cpp index 95c197b912..3e2bbcf0d7 100644 --- a/src/apps/vpn/platforms/android/androidcontroller.cpp +++ b/src/apps/vpn/platforms/android/androidcontroller.cpp @@ -108,7 +108,7 @@ void AndroidController::initialize(const Device* device, const Keys* keys) { } void AndroidController::activate(const HopConnection& hop, const Device* device, - const Keys* keys, Reason reason) { + const Keys* keys, Controller::Reason reason) { Q_ASSERT(hop.m_hopindex == 0); logger.debug() << "Activation"; @@ -194,10 +194,10 @@ void AndroidController::activate(const HopConnection& hop, const Device* device, doc.toJson()); } -void AndroidController::deactivate(Reason reason) { +void AndroidController::deactivate(Controller::Reason reason) { logger.debug() << "deactivation"; - if (reason != ReasonNone) { + if (reason != Controller::ReasonNone) { // Just show that we're disconnected // we're doing the actual disconnect once // the vpn-service has the new server ready in Action->Activate diff --git a/src/apps/vpn/platforms/android/androidcontroller.h b/src/apps/vpn/platforms/android/androidcontroller.h index 66b19fdaa2..97990dca7c 100644 --- a/src/apps/vpn/platforms/android/androidcontroller.h +++ b/src/apps/vpn/platforms/android/androidcontroller.h @@ -20,9 +20,9 @@ class AndroidController final : public ControllerImpl { void initialize(const Device* device, const Keys* keys) override; void activate(const HopConnection& hop, const Device* device, - const Keys* keys, Reason Reason) override; + const Keys* keys, Controller::Reason Reason) override; - void deactivate(Reason reason) override; + void deactivate(Controller::Reason reason) override; void checkStatus() override; diff --git a/src/apps/vpn/platforms/dummy/dummycontroller.cpp b/src/apps/vpn/platforms/dummy/dummycontroller.cpp index 6d165a5a98..ed8f2db36c 100644 --- a/src/apps/vpn/platforms/dummy/dummycontroller.cpp +++ b/src/apps/vpn/platforms/dummy/dummycontroller.cpp @@ -33,7 +33,7 @@ DummyController::DummyController() : m_delayTimer(this) { DummyController::~DummyController() { MVPN_COUNT_DTOR(DummyController); } void DummyController::activate(const HopConnection& hop, const Device* device, - const Keys* keys, Reason reason) { + const Keys* keys, Controller::Reason reason) { Q_UNUSED(device); Q_UNUSED(keys); Q_UNUSED(reason); @@ -46,7 +46,7 @@ void DummyController::activate(const HopConnection& hop, const Device* device, m_delayTimer.start(DUMMY_CONNECTION_DELAY_MSEC); } -void DummyController::deactivate(Reason reason) { +void DummyController::deactivate(Controller::Reason reason) { Q_UNUSED(reason); logger.debug() << "DummyController deactivated"; diff --git a/src/apps/vpn/platforms/dummy/dummycontroller.h b/src/apps/vpn/platforms/dummy/dummycontroller.h index 12ebbdd0a4..d3db6a3292 100644 --- a/src/apps/vpn/platforms/dummy/dummycontroller.h +++ b/src/apps/vpn/platforms/dummy/dummycontroller.h @@ -25,9 +25,9 @@ class DummyController final : public ControllerImpl { } void activate(const HopConnection& hop, const Device* device, - const Keys* keys, Reason reason) override; + const Keys* keys, Controller::Reason reason) override; - void deactivate(Reason reason) override; + void deactivate(Controller::Reason reason) override; void checkStatus() override; diff --git a/src/apps/vpn/platforms/ios/ioscontroller.h b/src/apps/vpn/platforms/ios/ioscontroller.h index 3ac4f530d6..4b5c5a9f73 100644 --- a/src/apps/vpn/platforms/ios/ioscontroller.h +++ b/src/apps/vpn/platforms/ios/ioscontroller.h @@ -19,9 +19,9 @@ class IOSController final : public ControllerImpl { void initialize(const Device* device, const Keys* keys) override; void activate(const HopConnection& hop, const Device* device, - const Keys* keys, Reason reason) override; + const Keys* keys, Controller::Reason reason) override; - void deactivate(Reason reason) override; + void deactivate(Controller::Reason reason) override; void checkStatus() override; diff --git a/src/apps/vpn/platforms/ios/ioscontroller.mm b/src/apps/vpn/platforms/ios/ioscontroller.mm index f7433fe553..ed3e8be6ea 100644 --- a/src/apps/vpn/platforms/ios/ioscontroller.mm +++ b/src/apps/vpn/platforms/ios/ioscontroller.mm @@ -105,7 +105,7 @@ } void IOSController::activate(const HopConnection& hop, const Device* device, const Keys* keys, - Reason reason) { + Controller::Reason reason) { Q_UNUSED(device); Q_UNUSED(keys); @@ -146,10 +146,10 @@ }]; } -void IOSController::deactivate(Reason reason) { +void IOSController::deactivate(Controller::Reason reason) { logger.debug() << "IOSController deactivated"; - if (reason != ReasonNone) { + if (reason != Controller::ReasonNone) { logger.debug() << "We do not need to disable the VPN for switching or connection check."; emit disconnected(); return; diff --git a/src/apps/vpn/platforms/linux/linuxcontroller.cpp b/src/apps/vpn/platforms/linux/linuxcontroller.cpp index 9b8945c611..72e28dcd96 100644 --- a/src/apps/vpn/platforms/linux/linuxcontroller.cpp +++ b/src/apps/vpn/platforms/linux/linuxcontroller.cpp @@ -68,7 +68,7 @@ void LinuxController::initializeCompleted(QDBusPendingCallWatcher* call) { } void LinuxController::activate(const HopConnection& hop, const Device* device, - const Keys* keys, Reason reason) { + const Keys* keys, Controller::Reason reason) { Q_UNUSED(reason); connect( @@ -81,10 +81,10 @@ void LinuxController::activate(const HopConnection& hop, const Device* device, logger.debug() << "LinuxController activated"; } -void LinuxController::deactivate(Reason reason) { +void LinuxController::deactivate(Controller::Reason reason) { logger.debug() << "LinuxController deactivated"; - if (reason == ReasonSwitching) { + if (reason == Controller::ReasonSwitching) { logger.debug() << "No disconnect for quick server switching"; emit disconnected(); return; diff --git a/src/apps/vpn/platforms/linux/linuxcontroller.h b/src/apps/vpn/platforms/linux/linuxcontroller.h index e056c2d27c..0a633b2320 100644 --- a/src/apps/vpn/platforms/linux/linuxcontroller.h +++ b/src/apps/vpn/platforms/linux/linuxcontroller.h @@ -23,9 +23,9 @@ class LinuxController final : public ControllerImpl { void initialize(const Device* device, const Keys* keys) override; void activate(const HopConnection& hop, const Device* device, - const Keys* keys, Reason reason) override; + const Keys* keys, Controller::Reason reason) override; - void deactivate(Reason reason) override; + void deactivate(Controller::Reason reason) override; void checkStatus() override; diff --git a/src/apps/vpn/platforms/macos/macosmenubar.cpp b/src/apps/vpn/platforms/macos/macosmenubar.cpp index c4bf078a9f..23004a077d 100644 --- a/src/apps/vpn/platforms/macos/macosmenubar.cpp +++ b/src/apps/vpn/platforms/macos/macosmenubar.cpp @@ -61,7 +61,7 @@ void MacOSMenuBar::initialize() { // Do not use qtTrId here! m_aboutAction = fileMenu->addAction("about.vpn", []() { - ExternalOpHandler::instance()->request(ExternalOpHandler::OpAbout); + (void)ExternalOpHandler::instance()->request(ExternalOpHandler::OpAbout); }); m_aboutAction->setMenuRole(QAction::AboutRole); m_aboutAction->setVisible(vpn->state() == MozillaVPN::StateMain); diff --git a/src/apps/vpn/platforms/windows/windowsnetworkwatcher.cpp b/src/apps/vpn/platforms/windows/windowsnetworkwatcher.cpp index 5b3d39d8ea..63a42abf2f 100644 --- a/src/apps/vpn/platforms/windows/windowsnetworkwatcher.cpp +++ b/src/apps/vpn/platforms/windows/windowsnetworkwatcher.cpp @@ -14,15 +14,6 @@ #pragma comment(lib, "Wlanapi.lib") #pragma comment(lib, "windowsapp.lib") -#include -// See -// https://github.com/microsoft/Windows.UI.Composition-Win32-Samples/issues/47 -namespace winrt::impl { -template -auto wait_for(Async const& async, Windows::Foundation::TimeSpan const& timeout); -} -#include - namespace { Logger logger("WindowsNetworkWatcher"); } @@ -148,26 +139,6 @@ void WindowsNetworkWatcher::processWlan(PWLAN_NOTIFICATION_DATA data) { } NetworkWatcherImpl::TransportType WindowsNetworkWatcher::getTransportType() { - using namespace winrt::Windows::Networking::Connectivity; - ConnectionProfile profile = - NetworkInformation::GetInternetConnectionProfile(); - - if (profile.IsWlanConnectionProfile()) { - return TransportType_WiFi; - } - if (profile.IsWwanConnectionProfile()) { - return TransportType_Cellular; - } - NetworkAdapter device = profile.NetworkAdapter(); - if (device == nullptr) { - return TransportType_Unknown; - } - - switch (device.IanaInterfaceType()) { - case 6: - return TransportType_Ethernet; - case 71: - return TransportType_WiFi; - } + // TODO: Implement this once we update to Qt6.3 (VPN-3511) return TransportType_Other; } diff --git a/src/apps/vpn/settingslist.h b/src/apps/vpn/settingslist.h index 1bd100c36c..4a8ebc89fe 100644 --- a/src/apps/vpn/settingslist.h +++ b/src/apps/vpn/settingslist.h @@ -488,16 +488,6 @@ SETTING_STRING(token, // getter true // remove when reset ) -SETTING_BOOL(tunnelPort53, // getter - setTunnelPort53, // setter - removeTunnelPort53, // remover - hasTunnelPort53, // has - "tunnelPort53", // key - false, // default value - true, // user setting - false // remove when reset -) - SETTING_BOOL(unsecuredNetworkAlert, // getter setUnsecuredNetworkAlert, // setter removeUnsecuredNetworkAlert, // remover diff --git a/src/apps/vpn/systemtraynotificationhandler.cpp b/src/apps/vpn/systemtraynotificationhandler.cpp index 11a136b179..4431d975c9 100644 --- a/src/apps/vpn/systemtraynotificationhandler.cpp +++ b/src/apps/vpn/systemtraynotificationhandler.cpp @@ -78,12 +78,13 @@ void SystemTrayNotificationHandler::createStatusMenu() { m_statusLabel->setEnabled(false); m_lastLocationLabel = m_menu->addAction("", []() { - ExternalOpHandler::instance()->request(ExternalOpHandler::OpActivate); + (void)ExternalOpHandler::instance()->request(ExternalOpHandler::OpActivate); }); m_lastLocationLabel->setEnabled(false); m_disconnectAction = m_menu->addAction("", []() { - ExternalOpHandler::instance()->request(ExternalOpHandler::OpDeactivate); + (void)ExternalOpHandler::instance()->request( + ExternalOpHandler::OpDeactivate); }); m_separator = m_menu->addSeparator(); @@ -94,7 +95,7 @@ void SystemTrayNotificationHandler::createStatusMenu() { m_menu->addSeparator(); m_quitAction = m_menu->addAction("", []() { - ExternalOpHandler::instance()->request(ExternalOpHandler::OpQuit); + (void)ExternalOpHandler::instance()->request(ExternalOpHandler::OpQuit); }); } diff --git a/src/apps/vpn/tutorial/tutorial.cpp b/src/apps/vpn/tutorial/tutorial.cpp index 8a089dff68..d8a8d0e92f 100644 --- a/src/apps/vpn/tutorial/tutorial.cpp +++ b/src/apps/vpn/tutorial/tutorial.cpp @@ -142,5 +142,5 @@ bool Tutorial::maybeBlockRequest(ExternalOpHandler::Op op) { void Tutorial::interruptAccepted(ExternalOpHandler::Op op) { logger.debug() << "Interrupt by the user"; stop(); - ExternalOpHandler::instance()->request(op); + (void)ExternalOpHandler::instance()->request(op); } diff --git a/src/apps/vpn/ui/screens/getHelp/ViewGetHelp.qml b/src/apps/vpn/ui/screens/getHelp/ViewGetHelp.qml index 5df7d2281e..5a687ed88d 100644 --- a/src/apps/vpn/ui/screens/getHelp/ViewGetHelp.qml +++ b/src/apps/vpn/ui/screens/getHelp/ViewGetHelp.qml @@ -26,7 +26,7 @@ VPNViewBase { accessibleName: VPNl18n.GetHelpHelpCenter title: VPNl18n.GetHelpHelpCenter - onClicked: VPNUrlOpener.openLink(VPNUrlOpener.LinkHelpSupport) + onClicked: VPNUrlOpener.openLink(VPNUrlOpener.LinkSumo) iconSource: "qrc:/nebula/resources/externalLink.svg" backgroundColor: VPNTheme.theme.clickableRowBlue width: parent.width - VPNTheme.theme.windowMargin diff --git a/src/apps/vpn/ui/screens/getHelp/contactUs/ViewContactUsForm.qml b/src/apps/vpn/ui/screens/getHelp/contactUs/ViewContactUsForm.qml index 90879e2e9c..2979f0fc4f 100644 --- a/src/apps/vpn/ui/screens/getHelp/contactUs/ViewContactUsForm.qml +++ b/src/apps/vpn/ui/screens/getHelp/contactUs/ViewContactUsForm.qml @@ -42,7 +42,7 @@ VPNViewBase { secondaryButtonText: VPNl18n.InAppSupportWorkflowSupportErrorBrowserButton, secondaryButtonObjectName: "errorFxALinkButton", secondaryButtonOnClick: () => { - VPNUrlOpener.openLink(VPNUrlOpener.LinkHelpSupport); + VPNUrlOpener.openLink(VPNUrlOpener.LinkSumo); getHelpStackView.pop(); }, } diff --git a/src/apps/vpn/urlopener.cpp b/src/apps/vpn/urlopener.cpp index 498d448833..91f23c0203 100644 --- a/src/apps/vpn/urlopener.cpp +++ b/src/apps/vpn/urlopener.cpp @@ -70,9 +70,8 @@ void UrlOpener::openLink(LinkType linkType) { url.append("/reset_password"); break; - case LinkHelpSupport: - url = NetworkRequest::apiBaseUrl(); - url.append("/r/vpn/support"); + case LinkSumo: + url = AppConstants::MOZILLA_VPN_SUMO_URL; break; case LinkLeaveReview: diff --git a/src/apps/vpn/urlopener.h b/src/apps/vpn/urlopener.h index 1510cb4819..24741cf2c7 100644 --- a/src/apps/vpn/urlopener.h +++ b/src/apps/vpn/urlopener.h @@ -22,7 +22,6 @@ class UrlOpener final : public QObject { LinkContact, LinkForgotPassword, LinkLeaveReview, - LinkHelpSupport, LinkTermsOfService, LinkPrivacyNotice, LinkUpdate, @@ -34,6 +33,7 @@ class UrlOpener final : public QObject { LinkSubscriptionIapApple, LinkSubscriptionFxa, LinkSubscriptionIapGoogle, + LinkSumo, LinkUpgradeToBundle, }; Q_ENUM(LinkType) diff --git a/tests/functional/testOnboarding.js b/tests/functional/testOnboarding.js index 51dd79a418..69866a9488 100644 --- a/tests/functional/testOnboarding.js +++ b/tests/functional/testOnboarding.js @@ -50,7 +50,7 @@ describe('Initial view and onboarding', function() { await vpn.clickOnElement('helpCenter'); await vpn.waitForCondition(async () => { const url = await vpn.getLastUrl(); - return url.endsWith('/r/vpn/support'); + return url.endsWith('/firefox-private-network-vpn'); }); await vpn.clickOnElement(getHelpScreen.SUPPORT); diff --git a/tests/functional/testSettings.js b/tests/functional/testSettings.js index 17a48f3389..b859284b31 100644 --- a/tests/functional/testSettings.js +++ b/tests/functional/testSettings.js @@ -374,7 +374,7 @@ describe('Settings', function () { await vpn.clickOnElement(getHelpScreen.HELP_CENTER); await vpn.waitForCondition(async () => { const url = await vpn.getLastUrl(); - return url.endsWith('/r/vpn/support'); + return url.endsWith('/firefox-private-network-vpn'); }); await vpn.wait(); diff --git a/tests/qml/moccontroller.cpp b/tests/qml/moccontroller.cpp index f1cdae6920..e090d99c77 100644 --- a/tests/qml/moccontroller.cpp +++ b/tests/qml/moccontroller.cpp @@ -17,7 +17,10 @@ void Controller::implInitialized(bool, bool, const QDateTime&) {} bool Controller::activate() { return false; } -void Controller::activateInternal(bool forcePort53) { Q_UNUSED(forcePort53) } +void Controller::activateInternal(Reason reason, bool forcePort53) { + Q_UNUSED(reason); + Q_UNUSED(forcePort53) +} bool Controller::deactivate() { return false; } diff --git a/tests/unit/moccontroller.cpp b/tests/unit/moccontroller.cpp index 843fc496c5..b9afc758c2 100644 --- a/tests/unit/moccontroller.cpp +++ b/tests/unit/moccontroller.cpp @@ -18,7 +18,10 @@ void Controller::implInitialized(bool, bool, const QDateTime&) {} bool Controller::activate() { return false; } -void Controller::activateInternal(bool forcePort53) { Q_UNUSED(forcePort53) } +void Controller::activateInternal(Reason reason, bool forcePort53) { + Q_UNUSED(reason); + Q_UNUSED(forcePort53) +} bool Controller::deactivate() { return false; } diff --git a/translations/strings.yaml b/translations/strings.yaml index 71162887e8..5bd884789e 100644 --- a/translations/strings.yaml +++ b/translations/strings.yaml @@ -301,10 +301,6 @@ settings: value: Connect VPN on startup comment: Startup refers to a device's startup, not the VPN client's. startAtBootSubtitle: Mozilla VPN will launch and connect when you start up your device - tunnelPort53: - value: Tunnel VPN through port 53/DNS - comment: Tunnel is used as a verb, as in to direct traffic through - tunnelPort53Description: Use port 53/DNS for Wireguard traffic, which may help evade firewalls crashOptInDescription: value: Allow Mozilla VPN to automatically send crash reports to help fix unexpected crashes comment: This is the description of a checkbox option to allow the app to send crash reports without a user prompt