File indexing completed on 2024-04-28 05:33:52

0001 /*
0002     SPDX-FileCopyrightText: 2016 Jan Grulich <jgrulich@redhat.com>
0003     SPDX-FileCopyrightText: 2020 Kai Uwe Broulik <kde@broulik.de>
0004 
0005     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0006 */
0007 
0008 #include "connectivitymonitor.h"
0009 
0010 #include <QDBusReply>
0011 #include <QDesktopServices>
0012 
0013 #include <KIO/OpenUrlJob>
0014 #include <KLocalizedString>
0015 
0016 #include <NetworkManagerQt/ActiveConnection>
0017 
0018 #include <QCoroCore>
0019 #include <QCoroDBus>
0020 
0021 #include "plasma_nm_kded.h"
0022 #include <chrono>
0023 
0024 using namespace std::chrono_literals;
0025 
0026 ConnectivityMonitor::ConnectivityMonitor(QObject *parent)
0027     : QObject(parent)
0028 {
0029     m_limitedConnectivityTimer.setSingleShot(true);
0030     m_limitedConnectivityTimer.setInterval(10s);
0031     connect(&m_limitedConnectivityTimer, &QTimer::timeout, this, &ConnectivityMonitor::showLimitedConnectivityNotification);
0032 
0033     checkConnectivity();
0034 
0035     connect(NetworkManager::notifier(), &NetworkManager::Notifier::connectivityChanged, this, &ConnectivityMonitor::connectivityChanged);
0036 }
0037 
0038 ConnectivityMonitor::~ConnectivityMonitor()
0039 {
0040     if (m_notification) {
0041         m_notification->close();
0042     }
0043 }
0044 
0045 void ConnectivityMonitor::connectivityChanged(NetworkManager::Connectivity connectivity)
0046 {
0047     if (m_notification && m_notification->property("nm_connectivity") != connectivity) {
0048         m_notification->close();
0049         m_notification = nullptr;
0050     }
0051 
0052     if (connectivity == NetworkManager::Limited) {
0053         qCDebug(PLASMA_NM_KDED_LOG) << "Network connectivity limited, scheduling notification";
0054         if (!m_limitedConnectivityTimer.isActive()) {
0055             m_limitedConnectivityTimer.start();
0056         }
0057     } else {
0058         m_limitedConnectivityTimer.stop();
0059 
0060         if (connectivity == NetworkManager::Portal) {
0061             qCDebug(PLASMA_NM_KDED_LOG) << "Detected captive portal";
0062             const NetworkManager::ActiveConnection::Ptr primaryConnection = NetworkManager::primaryConnection();
0063             const QString title = primaryConnection ? primaryConnection->id() : i18n("Network authentication");
0064 
0065             if (m_notification) {
0066                 m_notification->setTitle(title);
0067                 m_notification->sendEvent();
0068             } else {
0069                 m_notification = new KNotification(QStringLiteral("CaptivePortal"), KNotification::Persistent);
0070                 m_notification->setComponentName(QStringLiteral("networkmanagement"));
0071                 m_notification->setTitle(title);
0072                 m_notification->setText(i18n("You need to log into this network"));
0073 
0074                 auto logInAction = m_notification->addAction(i18n("Log in"));
0075                 connect(logInAction, &KNotificationAction::activated, this, [this]() {
0076                     auto job = new KIO::OpenUrlJob(QUrl(QStringLiteral("http://networkcheck.kde.org")));
0077                     job->setStartupId(m_notification->xdgActivationToken().toUtf8());
0078                     job->start();
0079                 });
0080                 m_notification->sendEvent();
0081             }
0082         }
0083     }
0084 }
0085 
0086 void ConnectivityMonitor::showLimitedConnectivityNotification()
0087 {
0088     if (m_notification) {
0089         return;
0090     }
0091 
0092     m_notification = new KNotification(QStringLiteral("LimitedConnectivity"));
0093     m_notification->setComponentName(QStringLiteral("networkmanagement"));
0094     m_notification->setTitle(i18n("Limited Connectivity"));
0095     m_notification->setText(i18n("This device appears to be connected to a network but is unable to reach the internet."));
0096     m_notification->sendEvent();
0097 }
0098 
0099 QCoro::Task<void> ConnectivityMonitor::checkConnectivity()
0100 {
0101     QDBusReply<uint> reply = co_await NetworkManager::checkConnectivity();
0102 
0103     if (reply.isValid()) {
0104         connectivityChanged((NetworkManager::Connectivity)reply.value());
0105     }
0106 }
0107 
0108 #include "moc_connectivitymonitor.cpp"