• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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