1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <cstdint>
17 #include <memory>
18 #include <mutex>
19
20 #include "ability_manager_client.h"
21 #include "errorcode_convertor.h"
22 #include "extension_ability_info.h"
23 #include "module_template.h"
24 #include "napi/native_node_api.h"
25 #include "napi_common_want.h"
26 #include "napi_utils.h"
27 #include "net_datashare_utils_iface.h"
28 #include "net_manager_constants.h"
29 #include "netmanager_ext_log.h"
30 #include "networkvpn_client.h"
31 #include "vpn_connection_ext.h"
32 #include "vpn_extension_context.h"
33 #include "vpn_monitor_ext.h"
34 #include "want.h"
35
36 namespace OHOS {
37 namespace NetManagerStandard {
38 constexpr int32_t ARG_NUM_0 = 0;
39 constexpr int32_t PARAM_ONE = 1;
40
CreateResolvedPromise(napi_env env)41 static napi_value CreateResolvedPromise(napi_env env)
42 {
43 napi_deferred deferred = nullptr;
44 napi_value promise = nullptr;
45 if (napi_create_promise(env, &deferred, &promise) != napi_ok) {
46 return NapiUtils::GetUndefined(env);
47 }
48 napi_resolve_deferred(env, deferred, NapiUtils::GetUndefined(env));
49 return promise;
50 }
51
CreateRejectedPromise(napi_env env)52 static napi_value CreateRejectedPromise(napi_env env)
53 {
54 napi_deferred deferred = nullptr;
55 napi_value promise = nullptr;
56 if (napi_create_promise(env, &deferred, &promise) != napi_ok) {
57 return NapiUtils::GetUndefined(env);
58 }
59 napi_reject_deferred(env, deferred, NapiUtils::GetUndefined(env));
60 return promise;
61 }
62
ResolvePromiseInIpcThread(napi_env env,napi_deferred deferred)63 static void ResolvePromiseInIpcThread(napi_env env, napi_deferred deferred)
64 {
65 napi_send_event(
66 env, [env, deferred]() { napi_resolve_deferred(env, deferred, NapiUtils::GetUndefined(env)); },
67 napi_eprio_high);
68 }
69
RejectPromiseInIpcThread(napi_env env,napi_deferred deferred)70 static void RejectPromiseInIpcThread(napi_env env, napi_deferred deferred)
71 {
72 napi_send_event(
73 env, [env, deferred]() { napi_reject_deferred(env, deferred, NapiUtils::GetUndefined(env)); }, napi_eprio_high);
74 }
75
CreateObserveDataSharePromise(napi_env env,const std::string & bundleName)76 static napi_value CreateObserveDataSharePromise(napi_env env, const std::string &bundleName)
77 {
78 napi_deferred deferred = nullptr;
79 napi_value promise = nullptr;
80 if (napi_create_promise(env, &deferred, &promise) != napi_ok) {
81 return NapiUtils::GetUndefined(env);
82 }
83
84 auto once = std::make_shared<std::once_flag>();
85 auto callbackId = std::make_shared<int32_t>();
86 auto deferWrapper = std::make_shared<napi_deferred>();
87 *deferWrapper = deferred;
88 auto onChange = [env, deferWrapper, bundleName, once, callbackId]() {
89 if (!once) {
90 return;
91 }
92 std::call_once(*once, [env, deferWrapper, bundleName, callbackId]() {
93 bool vpnDialogSelect = false;
94 std::string vpnExtMode = std::to_string(vpnDialogSelect);
95 int32_t ret = NetDataShareHelperUtilsIface::Query(VPNEXT_MODE_URI, bundleName, vpnExtMode);
96 NETMANAGER_EXT_LOGI("query vpn state after dialog: %{public}d %{public}s", ret, vpnExtMode.c_str());
97 if (callbackId) {
98 NetDataShareHelperUtilsIface::UnregisterObserver(VPNEXT_MODE_URI, *callbackId);
99 }
100 if (deferWrapper && *deferWrapper) {
101 auto deferred = *deferWrapper;
102 *deferWrapper = nullptr;
103 if (vpnExtMode == "1") {
104 ResolvePromiseInIpcThread(env, deferred);
105 } else {
106 RejectPromiseInIpcThread(env, deferred);
107 }
108 }
109 });
110 };
111
112 *callbackId = NetDataShareHelperUtilsIface::RegisterObserver(VPNEXT_MODE_URI, onChange);
113 return promise;
114 }
115
MakeDataExt(napi_env env,size_t argc,napi_value * argv,EventManager * manager)116 static void *MakeDataExt(napi_env env, size_t argc, napi_value *argv, EventManager *manager)
117 {
118 if ((argc != PARAM_ONE) || (NapiUtils::GetValueType(env, argv[ARG_NUM_0]) != napi_object)) {
119 NETMANAGER_EXT_LOGE("funciton prameter error");
120 napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PARAMETER_ERROR).c_str(), "Parameter error");
121 return nullptr;
122 }
123
124 VpnExtensionContext *vpnExtensionContext = nullptr;
125 napi_status status = napi_unwrap(env, argv[ARG_NUM_0], reinterpret_cast<void **>(&vpnExtensionContext));
126 if (status != napi_ok || vpnExtensionContext == nullptr) {
127 NETMANAGER_EXT_LOGE("Failed to get vpnExtensionContext napi instance");
128 napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PARAMETER_ERROR).c_str(), "Parameter error");
129 return nullptr;
130 }
131
132 int32_t ret = NetworkVpnClient::GetInstance().CreateVpnConnection(true);
133 if (ret != NETMANAGER_EXT_SUCCESS) {
134 NETMANAGER_EXT_LOGE("execute CreateVpnConnection failed: %{public}d", ret);
135 std::string errorMsg = NetBaseErrorCodeConvertor().ConvertErrorCode(ret);
136 napi_throw_error(env, std::to_string(ret).c_str(), errorMsg.c_str());
137 return nullptr;
138 }
139 return reinterpret_cast<void *>(&NetworkVpnClient::GetInstance());
140 }
141
142 static bool g_started = false;
143
Replace(std::string s)144 static std::string Replace(std::string s)
145 {
146 std::string tmp = VPN_DIALOG_POSTFIX;
147 auto pos = s.find(tmp);
148 if (pos == std::string::npos) {
149 return s;
150 }
151 s.replace(pos, tmp.length(), "");
152 return s;
153 }
154
StartVpnExtensionAbility(napi_env env,napi_callback_info info)155 napi_value StartVpnExtensionAbility(napi_env env, napi_callback_info info)
156 {
157 napi_value thisVal = nullptr;
158 std::size_t argc = MAX_PARAM_NUM;
159
160 napi_value argv[MAX_PARAM_NUM] = {nullptr};
161 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVal, nullptr));
162 if ((argc != PARAM_ONE) || (NapiUtils::GetValueType(env, argv[ARG_NUM_0]) != napi_object)) {
163 NETMANAGER_EXT_LOGE("funciton prameter error");
164 napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PARAMETER_ERROR).c_str(), "Parameter error");
165 return CreateRejectedPromise(env);
166 }
167 AAFwk::Want want;
168 int32_t accountId = -1;
169 if (!AppExecFwk::UnwrapWant(env, argv[0], want)) {
170 NETMANAGER_EXT_LOGE("Failed to parse want");
171 napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PARAMETER_ERROR).c_str(), "Parse want error");
172 return CreateRejectedPromise(env);
173 }
174
175 std::string bundleName = want.GetElement().GetBundleName();
176 int32_t rst = NetworkVpnClient::GetInstance().RegisterBundleName(bundleName);
177 NETMANAGER_EXT_LOGI("VPN RegisterBundleName result = %{public}d", rst);
178 std::string abilityName = want.GetElement().GetAbilityName();
179 if (abilityName.find(VPN_DIALOG_POSTFIX) == std::string::npos) {
180 bool vpnDialogSelect = false;
181 std::string vpnExtMode = std::to_string(vpnDialogSelect);
182 int32_t ret = NetDataShareHelperUtilsIface::Query(VPNEXT_MODE_URI, bundleName, vpnExtMode);
183 if (!g_started || ret != 0 || vpnExtMode != "1") {
184 g_started = true;
185 std::string selfAppName;
186 auto getAppNameRes = NetworkVpnClient::GetInstance().GetSelfAppName(selfAppName);
187 NETMANAGER_EXT_LOGI("StartVpnExtensionAbility SelfAppName = %{public}s %{public}d", selfAppName.c_str(),
188 getAppNameRes);
189 VpnMonitor::GetInstance().ShowVpnDialog(bundleName, abilityName, selfAppName);
190 NETMANAGER_EXT_LOGE("dataShareHelperUtils Query error, err = %{public}d", ret);
191 return CreateObserveDataSharePromise(env, bundleName);
192 }
193 }
194 auto elem = want.GetElement();
195 elem.SetAbilityName(Replace(abilityName));
196 want.SetElement(elem);
197 ErrCode err = AAFwk::AbilityManagerClient::GetInstance()->StartExtensionAbility(
198 want, nullptr, accountId, AppExecFwk::ExtensionAbilityType::VPN);
199 NETMANAGER_EXT_LOGI("execute StartVpnExtensionAbility result: %{public}d", err);
200 return CreateResolvedPromise(env);
201 }
202
StopVpnExtensionAbility(napi_env env,napi_callback_info info)203 napi_value StopVpnExtensionAbility(napi_env env, napi_callback_info info)
204 {
205 napi_value thisVal = nullptr;
206 std::size_t argc = MAX_PARAM_NUM;
207
208 napi_value argv[MAX_PARAM_NUM] = {nullptr};
209 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVal, nullptr));
210 if ((argc != PARAM_ONE) || (NapiUtils::GetValueType(env, argv[ARG_NUM_0]) != napi_object)) {
211 NETMANAGER_EXT_LOGE("funciton prameter error");
212 napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PARAMETER_ERROR).c_str(), "Parameter error");
213 return CreateRejectedPromise(env);
214 }
215 AAFwk::Want want;
216 int32_t accountId = -1;
217 if (!AppExecFwk::UnwrapWant(env, argv[0], want)) {
218 NETMANAGER_EXT_LOGE("Failed to parse want");
219 napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PARAMETER_ERROR).c_str(), "Parse want error");
220 return CreateRejectedPromise(env);
221 }
222
223 ErrCode err = AAFwk::AbilityManagerClient::GetInstance()->StopExtensionAbility(
224 want, nullptr, accountId, AppExecFwk::ExtensionAbilityType::VPN);
225 NETMANAGER_EXT_LOGI("execute StopExtensionAbility result: %{public}d", err);
226 return CreateResolvedPromise(env);
227 }
228
CreateVpnConnection(napi_env env,napi_callback_info info)229 static napi_value CreateVpnConnection(napi_env env, napi_callback_info info)
230 {
231 return ModuleTemplate::NewInstance(env, info, VPN_CONNECTION_EXT, MakeDataExt, [](napi_env, void *data, void *) {
232 NETMANAGER_EXT_LOGI("finalize VpnConnection");
233 });
234 }
235
UpdateVpnAuthorize(napi_env env,napi_callback_info info)236 static napi_value UpdateVpnAuthorize(napi_env env, napi_callback_info info)
237 {
238 napi_value thisVal = nullptr;
239 std::size_t argc = MAX_PARAM_NUM;
240 napi_value argv[MAX_PARAM_NUM] = {nullptr};
241 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVal, nullptr));
242
243 if ((argc != PARAM_ONE) || (NapiUtils::GetValueType(env, argv[ARG_NUM_0]) != napi_string)) {
244 NETMANAGER_EXT_LOGE("funciton prameter error");
245 napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PARAMETER_ERROR).c_str(), "Parameter error");
246 return nullptr;
247 }
248 std::string bundleName = NapiUtils::GetStringFromValueUtf8(env, argv[ARG_NUM_0]);
249
250 bool vpnDialogSelect = true;
251 if (bundleName.find(VPN_DIALOG_POSTFIX) != std::string::npos) {
252 vpnDialogSelect = false;
253 bundleName = Replace(bundleName);
254 }
255 std::string vpnExtMode = std::to_string(vpnDialogSelect);
256 int32_t ret = NetDataShareHelperUtilsIface::Update(VPNEXT_MODE_URI, bundleName, vpnExtMode);
257 NETMANAGER_EXT_LOGI("UpdateVpnAuthorize result. ret = %{public}d", ret);
258
259 napi_value jsValue = nullptr;
260 napi_get_boolean(env, true, &jsValue);
261 return jsValue;
262 }
263
RegisterVpnExtModule(napi_env env,napi_value exports)264 napi_value RegisterVpnExtModule(napi_env env, napi_value exports)
265 {
266 NapiUtils::DefineProperties(env, exports,
267 {
268 DECLARE_NAPI_FUNCTION(CREATE_VPN_CONNECTION, CreateVpnConnection),
269 DECLARE_NAPI_FUNCTION(START_VPN_EXTENSION, StartVpnExtensionAbility),
270 DECLARE_NAPI_FUNCTION(STOP_VPN_EXTENSION, StopVpnExtensionAbility),
271 DECLARE_NAPI_FUNCTION(UPDATE_VPN_AUTHORIZE, UpdateVpnAuthorize),
272 });
273 ModuleTemplate::DefineClass(env, exports,
274 {
275 DECLARE_NAPI_FUNCTION(SET_UP_EXT, VpnConnectionExt::SetUp),
276 DECLARE_NAPI_FUNCTION(PROTECT_EXT, VpnConnectionExt::Protect),
277 DECLARE_NAPI_FUNCTION(DESTROY_EXT, VpnConnectionExt::Destroy),
278 },
279 VPN_CONNECTION_EXT);
280 return exports;
281 }
282
283 static napi_module g_vpnModule = {
284 .nm_version = 1,
285 .nm_flags = 0,
286 .nm_filename = nullptr,
287 .nm_register_func = RegisterVpnExtModule,
288 .nm_modname = VPN_EXT_MODULE_NAME,
289 .nm_priv = nullptr,
290 .reserved = {nullptr},
291 };
292
VpnNapiRegister()293 extern "C" __attribute__((constructor)) void VpnNapiRegister()
294 {
295 napi_module_register(&g_vpnModule);
296 }
297 } // namespace NetManagerStandard
298 } // namespace OHOS
299