Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qohosnetconnection.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include <QtCore/private/qcore_ohos_p.h>
6#include <QtCore/private/qnapi_p.h>
7#include <QtCore/private/qohoscommon_p.h>
8#include <QtCore/private/qohoslogger_p.h>
9#include <optional>
10#include <qohosnetconnection_p.h>
11#include <vector>
12
13QT_BEGIN_NAMESPACE
14
16
17namespace {
18
19NetState parseNetCapabilities(QOhosJsState &jsState, const QNapi::Object &netCapabilities)
20{
21 NetState state = {};
23
24 const auto bearerTypes = QNapi::getFilteredArrayElements<std::vector<NetBearType>, QNapi::Number>(
25 netCapabilities.get<QNapi::Array>("bearerTypes"),
26 [&](QNapi::Number bearerType) {
27 return jsState.tryMapOhosEnumFromJs<NetBearType>(bearerType);
28 });
29 if (!bearerTypes.empty())
30 state.transport = bearerTypes.front();
31
32 auto networkCapArray = QNapi::getOptionalPropOrEmpty<QNapi::Array>(netCapabilities, "networkCap");
33 if (!networkCapArray.IsEmpty()) {
34 const auto networkCap = QNapi::getFilteredArrayElements<std::vector<NetCap>, QNapi::Number>(
35 networkCapArray,
36 [&](QNapi::Number capability) {
37 return jsState.tryMapOhosEnumFromJs<NetCap>(capability);
38 });
39 bool internetCapable = false;
40 bool validated = false;
41 bool checkingConnectivity = false;
42 state.metered = true;
43 for (const auto capability : networkCap) {
44 if (capability == NetCap::NET_CAPABILITY_INTERNET)
45 internetCapable = true;
46 else if (capability == NetCap::NET_CAPABILITY_VALIDATED)
47 validated = true;
48 else if (capability == NetCap::NET_CAPABILITY_CHECKING_CONNECTIVITY)
49 checkingConnectivity = true;
50 else if (capability == NetCap::NET_CAPABILITY_PORTAL)
51 state.behindCaptivePortal = true;
52 else if (capability == NetCap::NET_CAPABILITY_NOT_METERED)
53 state.metered = false;
54 }
55 if (checkingConnectivity)
57 else if (validated)
59 else if (internetCapable)
61 }
62
63 return state;
64}
65
66NetState readDefaultNetState(QOhosJsState &jsState)
67{
68 try {
69 auto netHandle = jsState.eval<QNapi::Object>("@ohos.net.connection.getDefaultNetSync()");
70 constexpr qint32 invalidNetId = 0;
71 if (netHandle.get<QNapi::Number>("netId").Int32Value() == invalidNetId)
72 return NetState{};
73 auto netCapabilities = jsState.eval<QNapi::Object>(
74 "@ohos.net.connection.getNetCapabilitiesSync(*)", {netHandle});
75 return parseNetCapabilities(jsState, netCapabilities);
76 } catch (const Napi::Error &error) {
77 qOhosPrintfError(
78 "%s: failed to read default network state: %s", Q_FUNC_INFO, error.what());
79 return NetState{};
80 }
81}
82
83std::shared_ptr<void> registerNetConnectionEventHandlers(
84 QNapi::Object netConnection,
85 std::vector<std::pair<std::string, QNapi::CallbackFuncWrapper>> eventHandlers)
86{
87 for (auto &[eventTypeName, eventHandler] : eventHandlers)
88 netConnection.eval("on(*)", {eventTypeName, std::move(eventHandler)});
89
90 netConnection.eval(
91 "register(*)",
92 {
93 [](const QOhosCallbackInfo &cbInfo) {
94 if (cbInfo.Length() != 0 && cbInfo.getFirstArg<QNapi::Value>(Q_FUNC_INFO).IsObject())
95 QtOhos::logJsCallbackError(cbInfo, "@ohos.net.connection.NetConnection.register()");
96 }
97 });
98
99 auto netConnectionRef = QtOhos::moveToSharedPtr(
100 QNapi::Reference<>::makePersistentFrom(netConnection));
101
102 return QtOhos::makeDestroyNotifier(
103 [netConnectionRef]() {
104 try {
105 netConnectionRef->eval(
106 "unregister(*)",
107 {
108 [](const QOhosCallbackInfo &cbInfo) {
109 if (cbInfo.Length() != 0 && cbInfo.getFirstArg<QNapi::Value>(Q_FUNC_INFO).IsObject())
110 QtOhos::logJsCallbackError(cbInfo, "@ohos.net.connection.NetConnection.unregister()");
111 }
112 });
113 } catch (const Napi::Error &error) {
114 qOhosPrintfError(
115 "%s: net connection unregister failed (ignoring): %s",
116 Q_FUNC_INFO, error.what());
117 }
118 });
119}
120
121std::shared_ptr<void> registerNetConnectionListener(
122 QOhosJsState &jsState, QOhosConsumer<NetState> updateListener)
123{
124 auto sharedUpdateListener = QtOhos::moveToSharedPtr(std::move(updateListener));
125
126 return registerNetConnectionEventHandlers(
127 jsState.eval<QNapi::Object>("@ohos.net.connection.createNetConnection()"),
128 {
129 {
130 "netAvailable",
131 [sharedUpdateListener](const QOhosCallbackInfo &cbInfo) {
132 (*sharedUpdateListener)(readDefaultNetState(cbInfo.jsState()));
133 }
134 },
135 {
136 "netCapabilitiesChange",
137 [sharedUpdateListener](const QOhosCallbackInfo &cbInfo) {
138 auto netCapabilityInfo = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
139 (*sharedUpdateListener)(
140 parseNetCapabilities(cbInfo.jsState(), netCapabilityInfo.get<QNapi::Object>("netCap")));
141 }
142 },
143 {
144 "netLost",
145 [sharedUpdateListener]() {
146 (*sharedUpdateListener)(NetState{});
147 }
148 },
149 {
150 "netUnavailable",
151 [sharedUpdateListener]() {
152 (*sharedUpdateListener)(NetState{});
153 }
154 },
155 });
156}
157
158}
159
160QOhosSupplier<NetState> makeOhosNetStateDataSource(QOhosConsumer<NetState> stateChangeConsumer)
161{
162 struct Context {
163 QOhosConsumer<NetState> stateChangedHandler;
164 NetState currentState;
165 std::shared_ptr<void> listenerHandle;
166 };
167
168 auto context = QOhosJsThreadGateway::eval(
169 [&](QOhosJsState &jsState) {
170 auto context = std::make_shared<Context>();
171 context->stateChangedHandler = std::move(stateChangeConsumer);
172 context->currentState = readDefaultNetState(jsState);
173
174 auto onStateChanged = [weakContext = QtOhos::makeWeakPtr(context)](NetState state) {
175 QtOhos::invokeInQtThread(
176 [weakContext, state]() {
177 auto context = weakContext.lock();
178 if (context) {
179 context->currentState = state;
180 context->stateChangedHandler(context->currentState);
181 }
182 });
183 };
184
185 try {
186 context->listenerHandle = QtOhos::makeProxyWithJsThreadDeleter(
187 registerNetConnectionListener(jsState, std::move(onStateChanged)));
188 } catch (const Napi::Error &error) {
189 qOhosPrintfError(
190 "%s: failed to register @ohos.net.connection listener: %s", Q_FUNC_INFO, error.what());
191 }
192
193 return context;
194 });
195
196 return [context]() {
197 return context->currentState;
198 };
199}
200
201}
202
203QT_END_NAMESPACE
QOhosSupplier< NetState > makeOhosNetStateDataSource(QOhosConsumer< NetState > stateChangeConsumer)