service/UnifiedPushReceiver.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "UnifiedPushReceiver.h" | ||
| 2 | #include "WebPushPayloadCodec.h" | ||
| 3 | |||
| 4 | #include <QDBusReply> | ||
| 5 | |||
| 6 | #include <QDBusConnection> | ||
| 7 | #include <QDBusConnectionInterface> | ||
| 8 | #include <QDBusMessage> | ||
| 9 | #include <QDBusPendingCallWatcher> | ||
| 10 | #include <QDBusPendingReply> | ||
| 11 | #include <QDBusServiceWatcher> | ||
| 12 | #include <QDateTime> | ||
| 13 | #include <QLoggingCategory> | ||
| 14 | #include <algorithm> | ||
| 15 | |||
| 16 |
4/7✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 8 taken 27 times.
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 8 not taken.
✓ Branch 5 → 6 taken 1 time.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
|
28 | Q_LOGGING_CATEGORY(lcUnifiedPush, "mailjd.davpush.unifiedpush") |
| 17 | |||
| 18 | namespace { | ||
| 19 | const QString kDistributorPath = QStringLiteral("/org/unifiedpush/Distributor"); | ||
| 20 | const QString kDistributor2 = QStringLiteral("org.unifiedpush.Distributor2"); | ||
| 21 | const QString kDistributor1 = QStringLiteral("org.unifiedpush.Distributor1"); | ||
| 22 | const QString kConnectorPath = QStringLiteral("/org/unifiedpush/Connector"); | ||
| 23 | const QString kKdeDistributor = QStringLiteral("org.unifiedpush.Distributor.kde"); | ||
| 24 | const QString kSucceeded = QStringLiteral("REGISTRATION_SUCCEEDED"); | ||
| 25 | // The distributor answers Register after its own provider registration | ||
| 26 | // (network); one bounded wait instead of D-Bus's default 25 s. | ||
| 27 | constexpr int kRegisterTimeoutMs = 120000; | ||
| 28 | constexpr int kMaxRecentIds = 64; | ||
| 29 | |||
| 30 | 28 | qint64 nowMs() { return QDateTime::currentMSecsSinceEpoch(); } | |
| 31 | |||
| 32 | 1 | QString describeReason(const QString &reason) { | |
| 33 |
1/2✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 10 not taken.
|
2 | if (reason == QLatin1String("ACTION_REQUIRED")) return QStringLiteral("the system push service needs to be set up"); |
| 34 | ✗ | if (reason == QLatin1String("NETWORK")) return QStringLiteral("the system push service cannot reach its server"); | |
| 35 | ✗ | if (reason == QLatin1String("UNAUTHORIZED")) return QStringLiteral("the system push service refused MailJD"); | |
| 36 | ✗ | if (reason == QLatin1String("VAPID_REQUIRED")) return QStringLiteral("the system push service requires a VAPID key"); | |
| 37 | ✗ | return QStringLiteral("the system push service reported an internal error"); | |
| 38 | } | ||
| 39 | } // namespace | ||
| 40 | |||
| 41 | // --- discovery ---------------------------------------------------------------- | ||
| 42 | |||
| 43 | 826 | QString UnifiedPushReceiver::findDistributor() { | |
| 44 |
2/2✓ Branch 2 → 3 taken 826 times.
✓ Branch 3 → 4 taken 826 times.
|
826 | QDBusConnectionInterface *bus = QDBusConnection::sessionBus().interface(); |
| 45 |
1/2✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 826 times.
|
826 | if (!bus) return {}; |
| 46 |
1/1✓ Branch 7 → 8 taken 826 times.
|
826 | QStringList names = bus->registeredServiceNames().value(); |
| 47 |
1/1✓ Branch 10 → 11 taken 826 times.
|
826 | const QStringList activatable = bus->activatableServiceNames().value(); |
| 48 |
2/2✓ Branch 21 → 15 taken 7434 times.
✓ Branch 21 → 22 taken 826 times.
|
8260 | for (const QString &name : activatable) |
| 49 |
3/3✓ Branch 17 → 18 taken 5072 times.
✓ Branch 17 → 19 taken 2362 times.
✓ Branch 18 → 19 taken 5072 times.
|
7434 | if (!names.contains(name)) names.append(name); |
| 50 | 826 | QStringList distributors; | |
| 51 |
2/2✓ Branch 37 → 25 taken 11265 times.
✓ Branch 37 → 38 taken 826 times.
|
12091 | for (const QString &name : std::as_const(names)) |
| 52 |
7/8✓ Branch 26 → 27 taken 11265 times.
✓ Branch 27 → 28 taken 6 times.
✓ Branch 27 → 32 taken 11259 times.
✓ Branch 30 → 31 taken 6 times.
✗ Branch 30 → 32 not taken.
✓ Branch 33 → 34 taken 6 times.
✓ Branch 33 → 35 taken 11259 times.
✓ Branch 34 → 35 taken 6 times.
|
11265 | if (name.startsWith(kDistributorPrefix) && name.size() > kDistributorPrefix.size()) distributors.append(name); |
| 53 |
2/2✓ Branch 39 → 40 taken 823 times.
✓ Branch 39 → 41 taken 3 times.
|
826 | if (distributors.isEmpty()) return {}; |
| 54 |
1/1✓ Branch 41 → 42 taken 3 times.
|
3 | const QString preferred = qEnvironmentVariable("UNIFIEDPUSH_DISTRIBUTOR"); |
| 55 |
2/2✓ Branch 43 → 44 taken 1 time.
✓ Branch 43 → 45 taken 2 times.
|
3 | if (distributors.contains(preferred)) return preferred; |
| 56 |
1/2✗ Branch 46 → 47 not taken.
✓ Branch 46 → 48 taken 2 times.
|
2 | if (distributors.contains(kKdeDistributor)) return kKdeDistributor; |
| 57 |
3/3✓ Branch 48 → 49 taken 2 times.
✓ Branch 49 → 50 taken 2 times.
✓ Branch 50 → 51 taken 2 times.
|
2 | std::sort(distributors.begin(), distributors.end()); |
| 58 |
1/1✓ Branch 51 → 52 taken 2 times.
|
2 | return distributors.first(); |
| 59 | 826 | } | |
| 60 | |||
| 61 | 18 | QString UnifiedPushReceiver::connectorService() { | |
| 62 | // Reverse DNS of the project domain; tests may run beside a real MailJD. | ||
| 63 |
1/1✓ Branch 2 → 3 taken 18 times.
|
18 | const QString override = qEnvironmentVariable("MAILJD_UNIFIEDPUSH_SERVICE"); |
| 64 |
2/4✗ Branch 4 → 5 not taken.
✓ Branch 4 → 8 taken 18 times.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 18 times.
|
36 | return override.isEmpty() ? QStringLiteral("de.jdsoft.MailJD") : override; |
| 65 | 18 | } | |
| 66 | |||
| 67 | 1 | void UnifiedPushReceiver::unregisterToken(const QString &distributor, const QString &token) { | |
| 68 |
3/6✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 6 not taken.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 1 time.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 1 time.
|
1 | if (distributor.isEmpty() || token.isEmpty()) return; |
| 69 |
1/1✓ Branch 13 → 14 taken 1 time.
|
1 | QDBusMessage call = QDBusMessage::createMethodCall(distributor, kDistributorPath, kDistributor2, QStringLiteral("Unregister")); |
| 70 |
3/5✓ Branch 22 → 23 taken 1 time.
✓ Branch 26 → 27 taken 1 time.
✓ Branch 26 → 28 taken 1 time.
✗ Branch 58 → 59 not taken.
✗ Branch 58 → 60 not taken.
|
3 | call << QVariantMap{{QStringLiteral("token"), token}}; |
| 71 |
2/2✓ Branch 30 → 31 taken 1 time.
✓ Branch 31 → 32 taken 1 time.
|
1 | const QDBusPendingCall pending = QDBusConnection::sessionBus().asyncCall(call, 30000); |
| 72 |
3/6✓ Branch 33 → 34 taken 1 time.
✓ Branch 34 → 35 taken 1 time.
✗ Branch 35 → 36 not taken.
✓ Branch 35 → 37 taken 1 time.
✗ Branch 78 → 79 not taken.
✗ Branch 78 → 80 not taken.
|
1 | auto *watcher = new QDBusPendingCallWatcher(pending); |
| 73 |
1/3✓ Branch 39 → 40 taken 1 time.
✗ Branch 83 → 84 not taken.
✗ Branch 83 → 85 not taken.
|
1 | QObject::connect(watcher, &QDBusPendingCallWatcher::finished, watcher, [distributor, token](QDBusPendingCallWatcher *w) { |
| 74 |
1/1✓ Branch 2 → 3 taken 1 time.
|
1 | w->deleteLater(); |
| 75 |
2/3✓ Branch 3 → 4 taken 1 time.
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 17 not taken.
|
1 | if (!w->isError()) { |
| 76 |
6/6✓ Branch 5 → 6 taken 1 time.
✓ Branch 9 → 10 taken 1 time.
✓ Branch 10 → 11 taken 1 time.
✓ Branch 11 → 12 taken 1 time.
✓ Branch 15 → 7 taken 1 time.
✓ Branch 15 → 16 taken 1 time.
|
2 | qCInfo(lcUnifiedPush) << "Unregistered a replaced receiver at" << distributor; |
| 77 | 1 | return; | |
| 78 | } | ||
| 79 | // Older distributors: Distributor1.Unregister(s token). | ||
| 80 | ✗ | QDBusMessage v1 = QDBusMessage::createMethodCall(distributor, kDistributorPath, kDistributor1, QStringLiteral("Unregister")); | |
| 81 | ✗ | v1 << token; | |
| 82 | ✗ | QDBusConnection::sessionBus().asyncCall(v1, 30000); | |
| 83 | ✗ | }); | |
| 84 | 3 | } | |
| 85 | |||
| 86 | 820 | QObject *UnifiedPushReceiver::watchDistributors(QObject *parent, std::function<void()> changed) { | |
| 87 |
1/1✓ Branch 4 → 5 taken 820 times.
|
2460 | auto *watcher = new QDBusServiceWatcher(QStringLiteral("org.unifiedpush.Distributor*"), QDBusConnection::sessionBus(), |
| 88 |
2/5✓ Branch 8 → 9 taken 820 times.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 820 times.
✗ Branch 30 → 31 not taken.
✗ Branch 30 → 32 not taken.
|
2460 | QDBusServiceWatcher::WatchForOwnerChange, parent); |
| 89 |
1/1✓ Branch 15 → 16 taken 820 times.
|
820 | QObject::connect(watcher, &QDBusServiceWatcher::serviceOwnerChanged, parent, |
| 90 |
1/1✓ Branch 14 → 15 taken 820 times.
|
1640 | [changed](const QString &, const QString &, const QString &) { changed(); }); |
| 91 | 820 | return watcher; | |
| 92 | } | ||
| 93 | |||
| 94 | // --- receiver ------------------------------------------------------------------- | ||
| 95 | |||
| 96 |
1/1✓ Branch 5 → 6 taken 11 times.
|
11 | UnifiedPushReceiver::UnifiedPushReceiver(QObject *parent) : PushReceiver(parent) { |
| 97 |
1/1✓ Branch 7 → 8 taken 11 times.
|
11 | m_retry.setSingleShot(true); |
| 98 |
1/1✓ Branch 8 → 9 taken 11 times.
|
11 | connect(&m_retry, &QTimer::timeout, this, &UnifiedPushReceiver::registerWithDistributor); |
| 99 | 11 | } | |
| 100 | |||
| 101 | 12 | UnifiedPushReceiver::~UnifiedPushReceiver() { | |
| 102 | 11 | stop(); | |
| 103 | 12 | } | |
| 104 | |||
| 105 | 9 | void UnifiedPushReceiver::start(const Config &config) { | |
| 106 | 9 | stop(); | |
| 107 | 9 | m_config = config; | |
| 108 | 9 | m_running = true; | |
| 109 | 9 | m_attempts = 0; | |
| 110 | 9 | m_connectedOnce = false; | |
| 111 | 9 | m_lostDistributor = false; | |
| 112 | 9 | auto *connector = UnifiedPushConnector::instance(); | |
| 113 |
1/2✗ Branch 6 → 7 not taken.
✓ Branch 6 → 14 taken 9 times.
|
9 | if (!connector->available()) { |
| 114 | ✗ | setState(DavPushReceiverState::Failed, Failure::Protocol, | |
| 115 | ✗ | QStringLiteral("another MailJD instance owns the push connector")); | |
| 116 | ✗ | return; | |
| 117 | } | ||
| 118 | 9 | connector->attach(m_config.channel, this); | |
| 119 |
1/3✓ Branch 17 → 18 taken 9 times.
✗ Branch 40 → 41 not taken.
✗ Branch 40 → 43 not taken.
|
18 | m_watcher = new QDBusServiceWatcher(m_config.server, QDBusConnection::sessionBus(), |
| 120 |
2/3✓ Branch 18 → 19 taken 9 times.
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 23 taken 9 times.
|
27 | QDBusServiceWatcher::WatchForOwnerChange, this); |
| 121 | 9 | connect(m_watcher, &QDBusServiceWatcher::serviceOwnerChanged, this, | |
| 122 |
1/1✓ Branch 23 → 24 taken 9 times.
|
11 | [this](const QString &, const QString &, const QString &newOwner) { onDistributorOwner(newOwner); }); |
| 123 |
1/1✓ Branch 26 → 27 taken 9 times.
|
9 | setState(DavPushReceiverState::Connecting); |
| 124 | 9 | registerWithDistributor(); | |
| 125 | } | ||
| 126 | |||
| 127 | 23 | void UnifiedPushReceiver::stop() { | |
| 128 |
2/2✓ Branch 2 → 3 taken 14 times.
✓ Branch 2 → 4 taken 9 times.
|
23 | if (!m_running) return; |
| 129 | 9 | m_running = false; | |
| 130 | 9 | m_registered = false; | |
| 131 | 9 | m_retry.stop(); | |
| 132 |
1/2✓ Branch 5 → 6 taken 9 times.
✗ Branch 5 → 7 not taken.
|
9 | delete m_watcher; |
| 133 | 9 | m_watcher = nullptr; | |
| 134 | 9 | UnifiedPushConnector::instance()->detach(m_config.channel, this); | |
| 135 | 9 | m_connectedSince = 0; | |
| 136 |
1/1✓ Branch 10 → 11 taken 9 times.
|
9 | setState(DavPushReceiverState::Stopped); |
| 137 | } | ||
| 138 | |||
| 139 | 10 | void UnifiedPushReceiver::registerWithDistributor() { | |
| 140 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 10 times.
|
10 | if (!m_running) return; |
| 141 | 10 | ++m_attempts; | |
| 142 |
1/1✓ Branch 7 → 8 taken 10 times.
|
20 | QVariantMap args{{QStringLiteral("service"), connectorService()}, |
| 143 | 20 | {QStringLiteral("token"), m_config.channel}, | |
| 144 |
2/4✓ Branch 22 → 23 taken 30 times.
✓ Branch 22 → 24 taken 10 times.
✗ Branch 69 → 70 not taken.
✗ Branch 69 → 71 not taken.
|
60 | {QStringLiteral("description"), QStringLiteral("MailJD: calendar, task and contact changes")}}; |
| 145 |
2/3✓ Branch 34 → 35 taken 10 times.
✗ Branch 34 → 44 not taken.
✓ Branch 39 → 40 taken 10 times.
|
20 | if (!m_config.vapidKey.isEmpty()) args.insert(QStringLiteral("vapid"), m_config.vapidKey); |
| 146 |
1/1✓ Branch 47 → 48 taken 10 times.
|
10 | QDBusMessage call = QDBusMessage::createMethodCall(m_config.server, kDistributorPath, kDistributor2, QStringLiteral("Register")); |
| 147 |
1/1✓ Branch 51 → 52 taken 10 times.
|
10 | call << args; |
| 148 |
5/8✓ Branch 53 → 54 taken 10 times.
✓ Branch 54 → 55 taken 10 times.
✓ Branch 55 → 56 taken 10 times.
✓ Branch 56 → 57 taken 10 times.
✗ Branch 59 → 60 not taken.
✓ Branch 59 → 61 taken 10 times.
✗ Branch 129 → 130 not taken.
✗ Branch 129 → 131 not taken.
|
10 | auto *watcher = new QDBusPendingCallWatcher(QDBusConnection::sessionBus().asyncCall(call, kRegisterTimeoutMs), this); |
| 149 |
1/1✓ Branch 61 → 62 taken 10 times.
|
10 | connect(watcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *w) { |
| 150 |
1/1✓ Branch 2 → 3 taken 10 times.
|
10 | w->deleteLater(); |
| 151 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 10 times.
|
11 | if (!m_running) return; |
| 152 |
1/1✓ Branch 5 → 6 taken 10 times.
|
10 | QDBusPendingReply<QVariantMap> reply = *w; |
| 153 |
3/3✓ Branch 6 → 7 taken 10 times.
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 44 taken 9 times.
|
10 | if (reply.isError()) { |
| 154 |
2/2✓ Branch 8 → 9 taken 1 time.
✓ Branch 9 → 10 taken 1 time.
|
1 | const QString name = reply.error().name(); |
| 155 |
2/4✓ Branch 13 → 14 taken 1 time.
✗ Branch 13 → 17 not taken.
✓ Branch 16 → 17 taken 1 time.
✗ Branch 16 → 18 not taken.
|
2 | if (name == QLatin1String("org.freedesktop.DBus.Error.UnknownMethod") || |
| 156 |
1/2✓ Branch 19 → 20 taken 1 time.
✗ Branch 19 → 22 not taken.
|
2 | name == QLatin1String("org.freedesktop.DBus.Error.UnknownInterface")) { |
| 157 |
1/1✓ Branch 20 → 21 taken 1 time.
|
1 | registerVersion1(); |
| 158 | 1 | return; | |
| 159 | } | ||
| 160 | ✗ | qCInfo(lcUnifiedPush) << "Register at" << m_config.server << "failed:" << name; | |
| 161 | ✗ | retryLater(Failure::Network, QStringLiteral("the system push service does not answer")); | |
| 162 | ✗ | return; | |
| 163 | 1 | } | |
| 164 |
1/1✓ Branch 44 → 45 taken 9 times.
|
9 | const QVariantMap result = reply.value(); |
| 165 |
3/3✓ Branch 55 → 56 taken 9 times.
✓ Branch 56 → 57 taken 9 times.
✓ Branch 58 → 59 taken 9 times.
|
18 | onRegistered(result.value(QStringLiteral("success")).toString() == kSucceeded, |
| 166 |
2/2✓ Branch 49 → 50 taken 9 times.
✓ Branch 50 → 51 taken 9 times.
|
27 | result.value(QStringLiteral("reason")).toString()); |
| 167 |
2/2✓ Branch 72 → 73 taken 9 times.
✓ Branch 72 → 75 taken 1 time.
|
10 | }); |
| 168 | 50 | } | |
| 169 | |||
| 170 | 1 | void UnifiedPushReceiver::registerVersion1() { | |
| 171 |
1/1✓ Branch 5 → 6 taken 1 time.
|
1 | QDBusMessage call = QDBusMessage::createMethodCall(m_config.server, kDistributorPath, kDistributor1, QStringLiteral("Register")); |
| 172 |
4/4✓ Branch 8 → 9 taken 1 time.
✓ Branch 10 → 11 taken 1 time.
✓ Branch 12 → 13 taken 1 time.
✓ Branch 17 → 18 taken 1 time.
|
2 | call << connectorService() << m_config.channel << QStringLiteral("MailJD: calendar, task and contact changes"); |
| 173 |
5/8✓ Branch 24 → 25 taken 1 time.
✓ Branch 25 → 26 taken 1 time.
✓ Branch 26 → 27 taken 1 time.
✓ Branch 27 → 28 taken 1 time.
✗ Branch 30 → 31 not taken.
✓ Branch 30 → 32 taken 1 time.
✗ Branch 66 → 67 not taken.
✗ Branch 66 → 68 not taken.
|
1 | auto *watcher = new QDBusPendingCallWatcher(QDBusConnection::sessionBus().asyncCall(call, kRegisterTimeoutMs), this); |
| 174 |
1/1✓ Branch 32 → 33 taken 1 time.
|
1 | connect(watcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *w) { |
| 175 |
1/1✓ Branch 2 → 3 taken 1 time.
|
1 | w->deleteLater(); |
| 176 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1 time.
|
1 | if (!m_running) return; |
| 177 |
1/1✓ Branch 5 → 6 taken 1 time.
|
1 | QDBusPendingReply<QString, QString> reply = *w; |
| 178 |
2/3✓ Branch 6 → 7 taken 1 time.
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 15 taken 1 time.
|
1 | if (reply.isError()) { |
| 179 | ✗ | retryLater(Failure::Network, QStringLiteral("the system push service does not answer")); | |
| 180 | ✗ | return; | |
| 181 | } | ||
| 182 |
3/3✓ Branch 15 → 16 taken 1 time.
✓ Branch 16 → 17 taken 1 time.
✓ Branch 18 → 19 taken 1 time.
|
1 | onRegistered(reply.argumentAt<0>() == kSucceeded, reply.argumentAt<1>()); |
| 183 |
1/2✓ Branch 23 → 24 taken 1 time.
✗ Branch 23 → 26 not taken.
|
1 | }); |
| 184 | 1 | } | |
| 185 | |||
| 186 | 10 | void UnifiedPushReceiver::onRegistered(bool success, const QString &reason) { | |
| 187 |
2/2✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 35 taken 9 times.
|
10 | if (!success) { |
| 188 |
7/7✓ Branch 3 → 4 taken 1 time.
✓ Branch 7 → 8 taken 1 time.
✓ Branch 8 → 9 taken 1 time.
✓ Branch 9 → 10 taken 1 time.
✓ Branch 10 → 11 taken 1 time.
✓ Branch 14 → 5 taken 1 time.
✓ Branch 14 → 15 taken 1 time.
|
2 | qCInfo(lcUnifiedPush) << "Registration refused by" << m_config.server << reason; |
| 189 |
4/8✓ Branch 17 → 18 taken 1 time.
✗ Branch 17 → 23 not taken.
✓ Branch 20 → 21 taken 1 time.
✗ Branch 20 → 23 not taken.
✗ Branch 22 → 23 not taken.
✓ Branch 22 → 24 taken 1 time.
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 30 taken 1 time.
|
1 | if (reason == QLatin1String("NETWORK") || reason == QLatin1String("INTERNAL_ERROR") || reason.isEmpty()) { |
| 190 | ✗ | retryLater(Failure::Network, describeReason(reason)); | |
| 191 | } else { | ||
| 192 | // Needs the user (setup, authorisation, key): no automatic retry. | ||
| 193 |
2/2✓ Branch 30 → 31 taken 1 time.
✓ Branch 31 → 32 taken 1 time.
|
1 | setState(DavPushReceiverState::Failed, Failure::Authentication, describeReason(reason)); |
| 194 | } | ||
| 195 | 1 | return; | |
| 196 | } | ||
| 197 | 9 | m_registered = true; | |
| 198 | 9 | m_attempts = 0; | |
| 199 |
6/6✓ Branch 35 → 36 taken 9 times.
✓ Branch 39 → 40 taken 9 times.
✓ Branch 40 → 41 taken 9 times.
✓ Branch 41 → 42 taken 9 times.
✓ Branch 45 → 37 taken 9 times.
✓ Branch 45 → 46 taken 9 times.
|
18 | qCInfo(lcUnifiedPush) << "Registered at" << m_config.server; |
| 200 | // Connected once the endpoint is known (it may arrive before the reply). | ||
| 201 |
2/2✓ Branch 47 → 48 taken 1 time.
✓ Branch 47 → 49 taken 8 times.
|
9 | if (!m_endpoint.isEmpty()) deliverEndpoint(m_endpoint); |
| 202 | } | ||
| 203 | |||
| 204 | ✗ | void UnifiedPushReceiver::retryLater(Failure failure, const QString &detail) { | |
| 205 | // 30 s doubling to 15 min, like the ntfy receiver's backoff. | ||
| 206 | ✗ | const int seconds = qMin(900, 30 << qMin(m_attempts - 1, 5)); | |
| 207 | ✗ | m_nextAttemptAt = nowMs() + qint64(seconds) * 1000; | |
| 208 | ✗ | m_retry.start(seconds * 1000); | |
| 209 | ✗ | setState(DavPushReceiverState::Backoff, failure, detail); | |
| 210 | ✗ | } | |
| 211 | |||
| 212 | 2 | void UnifiedPushReceiver::onDistributorOwner(const QString &newOwner) { | |
| 213 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 2 times.
|
2 | if (!m_running) return; |
| 214 |
2/2✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 26 taken 1 time.
|
2 | if (newOwner.isEmpty()) { |
| 215 |
7/7✓ Branch 6 → 7 taken 1 time.
✓ Branch 10 → 11 taken 1 time.
✓ Branch 11 → 12 taken 1 time.
✓ Branch 12 → 13 taken 1 time.
✓ Branch 13 → 14 taken 1 time.
✓ Branch 17 → 8 taken 1 time.
✓ Branch 17 → 18 taken 1 time.
|
2 | qCInfo(lcUnifiedPush) << "System push service" << m_config.server << "stopped"; |
| 216 | 1 | m_registered = false; | |
| 217 | 1 | m_lostDistributor = true; | |
| 218 | 1 | m_connectedSince = 0; | |
| 219 | 1 | m_retry.stop(); | |
| 220 |
1/1✓ Branch 22 → 23 taken 1 time.
|
2 | setState(DavPushReceiverState::Backoff, Failure::Network, QStringLiteral("the system push service stopped")); |
| 221 | 1 | return; | |
| 222 | } | ||
| 223 |
7/7✓ Branch 26 → 27 taken 1 time.
✓ Branch 30 → 31 taken 1 time.
✓ Branch 31 → 32 taken 1 time.
✓ Branch 32 → 33 taken 1 time.
✓ Branch 33 → 34 taken 1 time.
✓ Branch 37 → 28 taken 1 time.
✓ Branch 37 → 38 taken 1 time.
|
2 | qCInfo(lcUnifiedPush) << "System push service" << m_config.server << "is back"; |
| 224 | 1 | m_attempts = 0; | |
| 225 |
1/1✓ Branch 39 → 40 taken 1 time.
|
1 | setState(DavPushReceiverState::Connecting); |
| 226 | 1 | registerWithDistributor(); | |
| 227 | } | ||
| 228 | |||
| 229 | 11 | void UnifiedPushReceiver::deliverEndpoint(const QString &endpoint) { | |
| 230 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 11 times.
|
11 | if (!m_running) return; |
| 231 | 11 | const bool changed = endpoint != m_endpoint; | |
| 232 | 11 | m_endpoint = endpoint; | |
| 233 |
10/10✓ Branch 6 → 7 taken 9 times.
✓ Branch 6 → 22 taken 2 times.
✓ Branch 7 → 8 taken 9 times.
✓ Branch 11 → 12 taken 9 times.
✓ Branch 12 → 13 taken 9 times.
✓ Branch 13 → 14 taken 1 time.
✓ Branch 13 → 15 taken 8 times.
✓ Branch 16 → 17 taken 9 times.
✓ Branch 20 → 9 taken 9 times.
✓ Branch 20 → 21 taken 9 times.
|
20 | if (changed) qCInfo(lcUnifiedPush) << "Push endpoint" << (m_connectedOnce ? "changed" : "received"); |
| 234 |
1/4✗ Branch 22 → 23 not taken.
✓ Branch 22 → 25 taken 11 times.
✗ Branch 23 → 24 not taken.
✗ Branch 23 → 25 not taken.
|
11 | if (!m_registered && !changed) return; |
| 235 | 11 | m_lastActivity = nowMs(); | |
| 236 |
6/6✓ Branch 27 → 28 taken 2 times.
✓ Branch 27 → 29 taken 9 times.
✓ Branch 28 → 29 taken 1 time.
✓ Branch 28 → 30 taken 1 time.
✓ Branch 31 → 32 taken 10 times.
✓ Branch 31 → 40 taken 1 time.
|
11 | if (state() != DavPushReceiverState::Connected || changed) { |
| 237 | 10 | m_connectedSince = nowMs(); | |
| 238 | 10 | m_nextAttemptAt = 0; | |
| 239 | 10 | const bool afterGap = m_lostDistributor; | |
| 240 | 10 | m_lostDistributor = false; | |
| 241 |
1/1✓ Branch 34 → 35 taken 10 times.
|
10 | setState(DavPushReceiverState::Connected); |
| 242 |
2/2✓ Branch 36 → 37 taken 9 times.
✓ Branch 36 → 38 taken 1 time.
|
10 | if (changed) emit stateChanged(); // owners compare endpoint() on every state signal |
| 243 | 10 | emit streamResumed(afterGap); | |
| 244 | 10 | m_connectedOnce = true; | |
| 245 | } | ||
| 246 | } | ||
| 247 | |||
| 248 | 7 | void UnifiedPushReceiver::deliverMessage(const QByteArray &message, const QString &id) { | |
| 249 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 7 times.
|
7 | if (!m_running) return; |
| 250 | 7 | m_lastActivity = nowMs(); | |
| 251 |
1/2✓ Branch 6 → 7 taken 7 times.
✗ Branch 6 → 15 not taken.
|
7 | if (!id.isEmpty()) { |
| 252 |
2/2✓ Branch 8 → 9 taken 1 time.
✓ Branch 8 → 10 taken 6 times.
|
7 | if (m_recentIds.contains(id)) return; |
| 253 | 6 | m_recentIds.append(id); | |
| 254 |
1/2✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 6 times.
|
6 | if (m_recentIds.size() > kMaxRecentIds) m_recentIds.removeFirst(); |
| 255 | 6 | m_lastMessageId = id; | |
| 256 | } | ||
| 257 | 6 | emit bytesReceived(message.size()); | |
| 258 | 6 | emit messageReceived(message, id); | |
| 259 | } | ||
| 260 | |||
| 261 | 1 | void UnifiedPushReceiver::deliverUnregistered() { | |
| 262 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 1 time.
|
1 | if (!m_running) return; |
| 263 |
5/5✓ Branch 4 → 5 taken 1 time.
✓ Branch 8 → 9 taken 1 time.
✓ Branch 9 → 10 taken 1 time.
✓ Branch 13 → 6 taken 1 time.
✓ Branch 13 → 14 taken 1 time.
|
2 | qCInfo(lcUnifiedPush) << "The system push service removed MailJD's registration"; |
| 264 | 1 | m_registered = false; | |
| 265 | 1 | m_endpoint.clear(); | |
| 266 | 1 | m_connectedSince = 0; | |
| 267 | // Removed by the user in the system settings: no automatic re-register. | ||
| 268 |
1/1✓ Branch 18 → 19 taken 1 time.
|
2 | setState(DavPushReceiverState::Failed, Failure::Authentication, |
| 269 | 2 | QStringLiteral("the registration was removed in the system push service")); | |
| 270 | } | ||
| 271 | |||
| 272 | // --- connector ---------------------------------------------------------------- | ||
| 273 | |||
| 274 | 20 | UnifiedPushConnector *UnifiedPushConnector::instance() { | |
| 275 |
6/12✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 10 taken 19 times.
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 10 not taken.
✓ Branch 5 → 6 taken 1 time.
✓ Branch 6 → 7 taken 1 time.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 1 time.
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 14 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 15 → 17 not taken.
|
20 | static UnifiedPushConnector *connector = new UnifiedPushConnector(); |
| 276 | 20 | return connector; | |
| 277 | } | ||
| 278 | |||
| 279 |
1/1✓ Branch 3 → 4 taken 1 time.
|
1 | UnifiedPushConnector::UnifiedPushConnector() { |
| 280 |
1/1✓ Branch 7 → 8 taken 1 time.
|
1 | QDBusConnection bus = QDBusConnection::sessionBus(); |
| 281 |
2/3✓ Branch 8 → 9 taken 1 time.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 21 taken 1 time.
|
1 | if (!bus.isConnected()) { |
| 282 | ✗ | qCInfo(lcUnifiedPush) << "No session bus: system push service unavailable"; | |
| 283 | ✗ | return; | |
| 284 | } | ||
| 285 |
3/6✓ Branch 21 → 22 taken 1 time.
✓ Branch 22 → 23 taken 1 time.
✗ Branch 23 → 24 not taken.
✓ Branch 23 → 25 taken 1 time.
✗ Branch 77 → 78 not taken.
✗ Branch 77 → 79 not taken.
|
1 | new UnifiedPushConnector2Adaptor(this); |
| 286 |
3/6✓ Branch 25 → 26 taken 1 time.
✓ Branch 26 → 27 taken 1 time.
✗ Branch 27 → 28 not taken.
✓ Branch 27 → 29 taken 1 time.
✗ Branch 80 → 81 not taken.
✗ Branch 80 → 82 not taken.
|
1 | new UnifiedPushConnector1Adaptor(this); |
| 287 |
2/3✓ Branch 30 → 31 taken 1 time.
✗ Branch 31 → 32 not taken.
✓ Branch 31 → 43 taken 1 time.
|
1 | if (!bus.registerObject(kConnectorPath, this, QDBusConnection::ExportAdaptors)) { |
| 288 | ✗ | qCWarning(lcUnifiedPush) << "Cannot export the push connector object"; | |
| 289 | ✗ | return; | |
| 290 | } | ||
| 291 |
2/2✓ Branch 43 → 44 taken 1 time.
✓ Branch 44 → 45 taken 1 time.
|
1 | m_available = bus.registerService(UnifiedPushReceiver::connectorService()); |
| 292 |
1/1✓ Branch 47 → 48 taken 1 time.
|
1 | connect(bus.interface(), &QDBusConnectionInterface::serviceOwnerChanged, this, |
| 293 |
1/1✓ Branch 46 → 47 taken 1 time.
|
1 | &UnifiedPushConnector::onNameOwnerChanged); |
| 294 |
1/2✗ Branch 49 → 50 not taken.
✓ Branch 49 → 65 taken 1 time.
|
1 | if (!m_available) |
| 295 | ✗ | qCWarning(lcUnifiedPush) << "Push connector name" << UnifiedPushReceiver::connectorService() << "is taken"; | |
| 296 | 1 | } | |
| 297 | |||
| 298 | 11 | void UnifiedPushConnector::attach(const QString &token, UnifiedPushReceiver *receiver) { | |
| 299 |
2/2✓ Branch 2 → 3 taken 11 times.
✓ Branch 3 → 4 taken 11 times.
|
11 | m_receivers.insert(token, receiver); |
| 300 | 11 | } | |
| 301 | |||
| 302 | 10 | void UnifiedPushConnector::detach(const QString &token, UnifiedPushReceiver *receiver) { | |
| 303 |
1/2✓ Branch 5 → 6 taken 10 times.
✗ Branch 5 → 7 not taken.
|
10 | if (m_receivers.value(token) == receiver) m_receivers.remove(token); |
| 304 | 10 | } | |
| 305 | |||
| 306 | 24 | UnifiedPushReceiver *UnifiedPushConnector::receiverFrom(const QString &token, const QString &caller) const { | |
| 307 | // S106-065: a guarded pointer across the owner lookup. The lookup is a | ||
| 308 | // blocking bus round trip whose nested event loop can run the deleteLater() | ||
| 309 | // of a receiver being replaced; a raw copy was returned dangling. | ||
| 310 | 24 | const QPointer<UnifiedPushReceiver> receiver = m_receivers.value(token); | |
| 311 |
3/6✓ Branch 4 → 5 taken 24 times.
✗ Branch 4 → 7 not taken.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 24 times.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 24 taken 24 times.
|
24 | if (!receiver || caller.isEmpty()) { |
| 312 | ✗ | if (receiver) qCWarning(lcUnifiedPush) << "Ignored a push call from outside a bus call"; | |
| 313 | ✗ | return nullptr; | |
| 314 | } | ||
| 315 | 24 | const QString service = receiver->distributorService(); | |
| 316 |
1/1✓ Branch 26 → 27 taken 24 times.
|
24 | const QString owner = ownerOf(service); |
| 317 |
7/8✓ Branch 28 → 29 taken 23 times.
✓ Branch 28 → 32 taken 1 time.
✗ Branch 31 → 32 not taken.
✓ Branch 31 → 33 taken 23 times.
✓ Branch 34 → 35 taken 23 times.
✓ Branch 34 → 36 taken 1 time.
✓ Branch 36 → 37 taken 1 time.
✓ Branch 36 → 48 taken 23 times.
|
24 | if (!receiver || m_receivers.value(token) != receiver) { |
| 318 |
5/5✓ Branch 37 → 38 taken 1 time.
✓ Branch 41 → 42 taken 1 time.
✓ Branch 42 → 43 taken 1 time.
✓ Branch 46 → 39 taken 1 time.
✓ Branch 46 → 47 taken 1 time.
|
2 | qCInfo(lcUnifiedPush) << "Push call dropped: its receiver was replaced during the caller check"; |
| 319 | 1 | return nullptr; | |
| 320 | } | ||
| 321 |
5/6✓ Branch 49 → 50 taken 23 times.
✗ Branch 49 → 52 not taken.
✓ Branch 51 → 52 taken 4 times.
✓ Branch 51 → 53 taken 19 times.
✓ Branch 54 → 55 taken 4 times.
✓ Branch 54 → 66 taken 19 times.
|
23 | if (owner.isEmpty() || owner != caller) { |
| 322 |
5/5✓ Branch 55 → 56 taken 4 times.
✓ Branch 59 → 60 taken 4 times.
✓ Branch 60 → 61 taken 4 times.
✓ Branch 64 → 57 taken 4 times.
✓ Branch 64 → 65 taken 4 times.
|
8 | qCWarning(lcUnifiedPush) << "Ignored a push call from a bus client that is not the registered distributor"; |
| 323 | 4 | return nullptr; | |
| 324 | } | ||
| 325 | 19 | return receiver.data(); | |
| 326 | 24 | } | |
| 327 | |||
| 328 | // S106-066: the owner of a distributor name is looked up once and then | ||
| 329 | // followed through NameOwnerChanged — every connector call used to pay a | ||
| 330 | // blocking bus round trip, which a flood of calls multiplied. | ||
| 331 | 26 | QString UnifiedPushConnector::ownerOf(const QString &service) const { | |
| 332 |
2/2✓ Branch 5 → 6 taken 19 times.
✓ Branch 5 → 8 taken 7 times.
|
26 | if (const auto cached = m_owners.constFind(service); cached != m_owners.constEnd()) |
| 333 | 19 | return *cached; | |
| 334 | 7 | QString owner; | |
| 335 |
2/2✓ Branch 9 → 11 taken 3 times.
✓ Branch 9 → 15 taken 4 times.
|
7 | if (m_ownerLookup) { |
| 336 |
1/1✓ Branch 11 → 12 taken 3 times.
|
3 | owner = m_ownerLookup(service); |
| 337 | } else { | ||
| 338 |
3/3✓ Branch 15 → 16 taken 4 times.
✓ Branch 16 → 17 taken 4 times.
✓ Branch 17 → 18 taken 4 times.
|
4 | const QDBusReply<QString> reply = QDBusConnection::sessionBus().interface()->serviceOwner(service); |
| 339 |
2/3✓ Branch 19 → 20 taken 4 times.
✓ Branch 20 → 21 taken 4 times.
✗ Branch 20 → 22 not taken.
|
4 | owner = reply.isValid() ? reply.value() : QString(); |
| 340 | 4 | } | |
| 341 |
2/3✓ Branch 28 → 29 taken 7 times.
✗ Branch 28 → 30 not taken.
✓ Branch 29 → 30 taken 7 times.
|
7 | if (!owner.isEmpty()) m_owners.insert(service, owner); |
| 342 | 7 | return owner; | |
| 343 | 7 | } | |
| 344 | |||
| 345 | 4 | void UnifiedPushConnector::onNameOwnerChanged(const QString &name, const QString &, const QString &newOwner) { | |
| 346 |
2/2✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 5 taken 2 times.
|
4 | if (newOwner.isEmpty()) m_owners.remove(name); |
| 347 |
1/2✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 2 times.
|
2 | else if (m_owners.contains(name)) m_owners.insert(name, newOwner); |
| 348 | 4 | } | |
| 349 | |||
| 350 | 1 | UnifiedPushConnector2Adaptor::UnifiedPushConnector2Adaptor(UnifiedPushConnector *connector) | |
| 351 | 1 | : QDBusAbstractAdaptor(connector), m_connector(connector) {} | |
| 352 | |||
| 353 | 8 | QVariantMap UnifiedPushConnector2Adaptor::Message(const QVariantMap &args) { | |
| 354 |
2/2✓ Branch 6 → 7 taken 8 times.
✓ Branch 7 → 8 taken 8 times.
|
16 | const QString id = args.value(QStringLiteral("id")).toString(); |
| 355 | // S106-066: an oversized message is dropped before any lookup (the | ||
| 356 | // decrypt path accepts at most kMaxEncryptedBytes anyway). | ||
| 357 |
4/4✓ Branch 16 → 17 taken 8 times.
✓ Branch 17 → 18 taken 8 times.
✓ Branch 24 → 25 taken 1 time.
✓ Branch 24 → 42 taken 7 times.
|
16 | if (args.value(QStringLiteral("message")).toByteArray().size() > WebPushPayloadCodec::kMaxEncryptedBytes) |
| 358 |
6/18✗ Branch 26 → 27 not taken.
✓ Branch 26 → 28 taken 1 time.
✓ Branch 33 → 34 taken 1 time.
✗ Branch 33 → 37 not taken.
✓ Branch 35 → 36 taken 1 time.
✓ Branch 35 → 37 taken 1 time.
✓ Branch 37 → 38 taken 1 time.
✗ Branch 37 → 39 not taken.
✓ Branch 39 → 40 taken 1 time.
✗ Branch 39 → 41 not taken.
✗ Branch 111 → 112 not taken.
✗ Branch 111 → 115 not taken.
✗ Branch 113 → 114 not taken.
✗ Branch 113 → 115 not taken.
✗ Branch 117 → 118 not taken.
✗ Branch 117 → 119 not taken.
✗ Branch 121 → 122 not taken.
✗ Branch 121 → 123 not taken.
|
4 | return id.isEmpty() ? QVariantMap{} : QVariantMap{{QStringLiteral("id"), id}}; |
| 359 |
6/6✓ Branch 42 → 43 taken 7 times.
✓ Branch 47 → 48 taken 7 times.
✓ Branch 48 → 49 taken 7 times.
✓ Branch 49 → 50 taken 7 times.
✓ Branch 56 → 57 taken 6 times.
✓ Branch 56 → 70 taken 1 time.
|
14 | if (auto *receiver = m_connector->receiverFrom(args.value(QStringLiteral("token")).toString(), m_connector->callingService())) |
| 360 |
3/3✓ Branch 61 → 62 taken 6 times.
✓ Branch 62 → 63 taken 6 times.
✓ Branch 63 → 64 taken 6 times.
|
12 | receiver->deliverMessage(args.value(QStringLiteral("message")).toByteArray(), id); |
| 361 | 7 | QVariantMap result; | |
| 362 |
2/3✓ Branch 71 → 72 taken 7 times.
✗ Branch 71 → 81 not taken.
✓ Branch 76 → 77 taken 7 times.
|
14 | if (!id.isEmpty()) result.insert(QStringLiteral("id"), id); // acknowledges the message |
| 363 | 7 | return result; | |
| 364 | 10 | } | |
| 365 | |||
| 366 | 10 | QVariantMap UnifiedPushConnector2Adaptor::NewEndpoint(const QVariantMap &args) { | |
| 367 |
6/6✓ Branch 2 → 3 taken 10 times.
✓ Branch 7 → 8 taken 10 times.
✓ Branch 8 → 9 taken 10 times.
✓ Branch 9 → 10 taken 10 times.
✓ Branch 16 → 17 taken 9 times.
✓ Branch 16 → 30 taken 1 time.
|
20 | if (auto *receiver = m_connector->receiverFrom(args.value(QStringLiteral("token")).toString(), m_connector->callingService())) |
| 368 |
3/3✓ Branch 21 → 22 taken 9 times.
✓ Branch 22 → 23 taken 9 times.
✓ Branch 23 → 24 taken 9 times.
|
18 | receiver->deliverEndpoint(args.value(QStringLiteral("endpoint")).toString()); |
| 369 | 10 | return {}; | |
| 370 | } | ||
| 371 | |||
| 372 | 2 | QVariantMap UnifiedPushConnector2Adaptor::Unregistered(const QVariantMap &args) { | |
| 373 |
6/6✓ Branch 2 → 3 taken 2 times.
✓ Branch 7 → 8 taken 2 times.
✓ Branch 8 → 9 taken 2 times.
✓ Branch 9 → 10 taken 2 times.
✓ Branch 16 → 17 taken 1 time.
✓ Branch 16 → 18 taken 1 time.
|
4 | if (auto *receiver = m_connector->receiverFrom(args.value(QStringLiteral("token")).toString(), m_connector->callingService())) |
| 374 | 1 | receiver->deliverUnregistered(); | |
| 375 | 2 | return {}; | |
| 376 | } | ||
| 377 | |||
| 378 | 1 | UnifiedPushConnector1Adaptor::UnifiedPushConnector1Adaptor(UnifiedPushConnector *connector) | |
| 379 | 1 | : QDBusAbstractAdaptor(connector), m_connector(connector) {} | |
| 380 | |||
| 381 | 1 | void UnifiedPushConnector1Adaptor::Message(const QString &token, const QByteArray &message, const QString &id) { | |
| 382 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1 time.
|
1 | if (message.size() > WebPushPayloadCodec::kMaxEncryptedBytes) return; // S106-066 |
| 383 |
3/4✓ Branch 5 → 6 taken 1 time.
✓ Branch 6 → 7 taken 1 time.
✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 10 not taken.
|
1 | if (auto *receiver = m_connector->receiverFrom(token, m_connector->callingService())) |
| 384 | 1 | receiver->deliverMessage(message, id); | |
| 385 | } | ||
| 386 | |||
| 387 | 1 | void UnifiedPushConnector1Adaptor::NewEndpoint(const QString &token, const QString &endpoint) { | |
| 388 |
3/4✓ Branch 2 → 3 taken 1 time.
✓ Branch 3 → 4 taken 1 time.
✓ Branch 5 → 6 taken 1 time.
✗ Branch 5 → 7 not taken.
|
1 | if (auto *receiver = m_connector->receiverFrom(token, m_connector->callingService())) receiver->deliverEndpoint(endpoint); |
| 389 | 1 | } | |
| 390 | |||
| 391 | ✗ | void UnifiedPushConnector1Adaptor::Unregistered(const QString &token) { | |
| 392 | ✗ | if (auto *receiver = m_connector->receiverFrom(token, m_connector->callingService())) receiver->deliverUnregistered(); | |
| 393 | ✗ | } | |
| 394 |