File indexing completed on 2024-05-05 17:42:32

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 <QDBusPendingCallWatcher>
0011 #include <QDBusPendingReply>
0012 #include <QDesktopServices>
0013 
0014 #include <KIO/OpenUrlJob>
0015 #include <KLocalizedString>
0016 
0017 #include <NetworkManagerQt/ActiveConnection>
0018 
0019 #include "plasma_nm_kded.h"
0020 #include <chrono>
0021 
0022 using namespace std::chrono_literals;
0023 
0024 ConnectivityMonitor::ConnectivityMonitor(QObject *parent)
0025     : QObject(parent)
0026 {
0027     m_limitedConnectivityTimer.setSingleShot(true);
0028     m_limitedConnectivityTimer.setInterval(10s);
0029     connect(&m_limitedConnectivityTimer, &QTimer::timeout, this, &ConnectivityMonitor::showLimitedConnectivityNotification);
0030 
0031     checkConnectivity();
0032 
0033     connect(NetworkManager::notifier(), &NetworkManager::Notifier::connectivityChanged, this, &ConnectivityMonitor::connectivityChanged);
0034 }
0035 
0036 ConnectivityMonitor::~ConnectivityMonitor()
0037 {
0038     if (m_notification) {
0039         m_notification->close();
0040     }
0041 }
0042 
0043 void ConnectivityMonitor::connectivityChanged(NetworkManager::Connectivity connectivity)
0044 {
0045     if (m_notification && m_notification->property("nm_connectivity") != connectivity) {
0046         m_notification->close();
0047         m_notification = nullptr;
0048     }
0049 
0050     if (connectivity == NetworkManager::Limited) {
0051         qCDebug(PLASMA_NM_KDED_LOG) << "Network connectivity limited, scheduling notification";
0052         if (!m_limitedConnectivityTimer.isActive()) {
0053             m_limitedConnectivityTimer.start();
0054         }
0055     } else {
0056         m_limitedConnectivityTimer.stop();
0057 
0058         if (connectivity == NetworkManager::Portal) {
0059             qCDebug(PLASMA_NM_KDED_LOG) << "Detected captive portal";
0060             const NetworkManager::ActiveConnection::Ptr primaryConnection = NetworkManager::primaryConnection();
0061             const QString title = primaryConnection ? primaryConnection->id() : i18n("Network authentication");
0062 
0063             if (m_notification) {
0064                 m_notification->setTitle(title);
0065                 m_notification->update();
0066             } else {
0067                 m_notification = new KNotification(QStringLiteral("CaptivePortal"), KNotification::Persistent);
0068                 m_notification->setActions(QStringList{i18n("Log in")});
0069                 m_notification->setComponentName(QStringLiteral("networkmanagement"));
0070                 m_notification->setTitle(title);
0071                 m_notification->setText(i18n("You need to log into this network"));
0072                 connect(m_notification, &KNotification::action1Activated, this, [this]() {
0073                     auto job = new KIO::OpenUrlJob(QUrl(QStringLiteral("http://networkcheck.kde.org")));
0074                     job->setStartupId(m_notification->xdgActivationToken().toUtf8());
0075                     job->start();
0076                 });
0077                 m_notification->sendEvent();
0078             }
0079         }
0080     }
0081 }
0082 
0083 void ConnectivityMonitor::showLimitedConnectivityNotification()
0084 {
0085     if (m_notification) {
0086         return;
0087     }
0088 
0089     m_notification = new KNotification(QStringLiteral("LimitedConnectivity"));
0090     m_notification->setComponentName(QStringLiteral("networkmanagement"));
0091     m_notification->setTitle(i18n("Limited Connectivity"));
0092     m_notification->setText(i18n("This device appears to be connected to a network but is unable to reach the internet."));
0093     m_notification->sendEvent();
0094 }
0095 
0096 void ConnectivityMonitor::checkConnectivity()
0097 {
0098     QDBusPendingReply<uint> pendingReply = NetworkManager::checkConnectivity();
0099     auto callWatcher = new QDBusPendingCallWatcher(pendingReply);
0100     connect(callWatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) {
0101         QDBusPendingReply<uint> reply = *watcher;
0102         if (reply.isValid()) {
0103             connectivityChanged((NetworkManager::Connectivity)reply.value());
0104         }
0105         watcher->deleteLater();
0106     });
0107 }