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 "js_vpn_extension.h"
17
18 #include "ability_handler.h"
19 #include "ability_info.h"
20 #include "configuration_utils.h"
21 #include "hitrace_meter.h"
22 #include "hilog_wrapper.h"
23 #include "js_extension_common.h"
24 #include "js_extension_context.h"
25 #include "runtime.h"
26 #include "js_runtime.h"
27 #include "js_runtime_utils.h"
28 #include "display_manager.h"
29 #include "js_vpn_extension_context.h"
30 #include "napi/native_api.h"
31 #include "napi/native_node_api.h"
32 #include "napi_common_configuration.h"
33 #include "napi_common_want.h"
34 #include "napi_remote_object.h"
35 #ifdef SUPPORT_GRAPHICS
36 #include "iservice_registry.h"
37 #include "system_ability_definition.h"
38 #include "window_scene.h"
39 #include "netmgr_ext_log_wrapper.h"
40 #endif
41
42 using namespace OHOS::AbilityRuntime;
43 namespace OHOS {
44 namespace NetManagerStandard {
45 namespace {
46 constexpr size_t ARGC_ONE = 1;
47 constexpr size_t ARGC_TWO = 2;
48 }
49
50 namespace {
PromiseCallback(napi_env env,napi_callback_info info)51 napi_value PromiseCallback(napi_env env, napi_callback_info info)
52 {
53 void *data = nullptr;
54 NAPI_CALL_NO_THROW(napi_get_cb_info(env, info, nullptr, nullptr, nullptr, &data), nullptr);
55 auto *callbackInfo = static_cast<AppExecFwk::AbilityTransactionCallbackInfo<> *>(data);
56 if (callbackInfo == nullptr) {
57 HILOG_WARN("callbackInfo nullptr.");
58 return nullptr;
59 }
60 callbackInfo->Call();
61 AppExecFwk::AbilityTransactionCallbackInfo<>::Destroy(callbackInfo);
62 data = nullptr;
63 return nullptr;
64 }
65
OnConnectPromiseCallback(napi_env env,napi_callback_info info)66 napi_value OnConnectPromiseCallback(napi_env env, napi_callback_info info)
67 {
68 NETMGR_EXT_LOG_D("enter");
69 void *data = nullptr;
70 size_t argc = ARGC_MAX_COUNT;
71 napi_value argv[ARGC_MAX_COUNT] = {nullptr};
72 NAPI_CALL_NO_THROW(napi_get_cb_info(env, info, &argc, argv, nullptr, &data), nullptr);
73 auto *callbackInfo = static_cast<AppExecFwk::AbilityTransactionCallbackInfo<sptr<IRemoteObject>> *>(data);
74 sptr<IRemoteObject> vpn = nullptr;
75 if (argc > 0) {
76 vpn = NAPI_ohos_rpc_getNativeRemoteObject(env, argv[0]);
77 }
78 if (callbackInfo == nullptr) {
79 HILOG_WARN("callbackInfo nullptr.");
80 return nullptr;
81 }
82 callbackInfo->Call(vpn);
83 AppExecFwk::AbilityTransactionCallbackInfo<sptr<IRemoteObject>>::Destroy(callbackInfo);
84 data = nullptr;
85 NETMGR_EXT_LOG_D("end");
86 return nullptr;
87 }
88 }
89
90 using namespace OHOS::AppExecFwk;
91
AttachVpnExtensionContext(napi_env env,void * value,void *)92 napi_value AttachVpnExtensionContext(napi_env env, void *value, void *)
93 {
94 NETMGR_EXT_LOG_I("call");
95 if (value == nullptr) {
96 HILOG_WARN("invalid parameter.");
97 return nullptr;
98 }
99 auto ptr = reinterpret_cast<std::weak_ptr<VpnExtensionContext> *>(value)->lock();
100 if (ptr == nullptr) {
101 HILOG_WARN("invalid context.");
102 return nullptr;
103 }
104 napi_value object = CreateJsVpnExtensionContext(env, ptr);
105 auto result = JsRuntime::LoadSystemModuleByEngine(env, "application.VpnExtensionContext", &object, 1);
106 if (result == nullptr) {
107 return nullptr;
108 }
109 auto contextObj = result->GetNapiValue();
110 napi_coerce_to_native_binding_object(
111 env, contextObj, DetachCallbackFunc, AttachVpnExtensionContext, value, nullptr);
112 auto workContext = new (std::nothrow) std::weak_ptr<VpnExtensionContext>(ptr);
113 if (workContext == nullptr) {
114 NETMGR_EXT_LOG_E("failed to new workContext");
115 return nullptr;
116 }
117 napi_wrap(env, contextObj, workContext,
118 [](napi_env, void *data, void *) {
119 NETMGR_EXT_LOG_I("Finalizer for weak_ptr vpn extension context is called");
120 delete static_cast<std::weak_ptr<VpnExtensionContext> *>(data);
121 },
122 nullptr, nullptr);
123 return contextObj;
124 }
125
Create(const std::unique_ptr<Runtime> & runtime)126 JsVpnExtension* JsVpnExtension::Create(const std::unique_ptr<Runtime>& runtime)
127 {
128 return new JsVpnExtension(static_cast<JsRuntime&>(*runtime));
129 }
130
JsVpnExtension(JsRuntime & jsRuntime)131 JsVpnExtension::JsVpnExtension(JsRuntime& jsRuntime) : jsRuntime_(jsRuntime) {}
~JsVpnExtension()132 JsVpnExtension::~JsVpnExtension()
133 {
134 NETMGR_EXT_LOG_D("Js vpn extension destructor.");
135 auto context = GetContext();
136 if (context) {
137 context->Unbind();
138 }
139
140 jsRuntime_.FreeNativeReference(std::move(jsObj_));
141 jsRuntime_.FreeNativeReference(std::move(shellContextRef_));
142 }
143
Init(const std::shared_ptr<AbilityLocalRecord> & record,const std::shared_ptr<OHOSApplication> & application,std::shared_ptr<AbilityHandler> & handler,const sptr<IRemoteObject> & token)144 void JsVpnExtension::Init(const std::shared_ptr<AbilityLocalRecord> &record,
145 const std::shared_ptr<OHOSApplication> &application, std::shared_ptr<AbilityHandler> &handler,
146 const sptr<IRemoteObject> &token)
147 {
148 VpnExtension::Init(record, application, handler, token);
149 std::string srcPath = "";
150 GetSrcPath(srcPath);
151 if (srcPath.empty()) {
152 NETMGR_EXT_LOG_E("Failed to get srcPath");
153 return;
154 }
155
156 std::string moduleName(Extension::abilityInfo_->moduleName);
157 moduleName.append("::").append(abilityInfo_->name);
158 NETMGR_EXT_LOG_D("JsVpnExtension::Init moduleName:%{public}s,srcPath:%{public}s.",
159 moduleName.c_str(), srcPath.c_str());
160 HandleScope handleScope(jsRuntime_);
161 auto env = jsRuntime_.GetNapiEnv();
162
163 jsObj_ = jsRuntime_.LoadModule(
164 moduleName, srcPath, abilityInfo_->hapPath, abilityInfo_->compileMode == CompileMode::ES_MODULE,
165 false, abilityInfo_->srcEntrance);
166 if (jsObj_ == nullptr) {
167 NETMGR_EXT_LOG_E("Failed to get jsObj_");
168 return;
169 }
170
171 NETMGR_EXT_LOG_I("JsVpnExtension::Init ConvertNativeValueTo.");
172 napi_value obj = jsObj_->GetNapiValue();
173 if (!CheckTypeForNapiValue(env, obj, napi_object)) {
174 NETMGR_EXT_LOG_E("Failed to get JsVpnExtension object");
175 return;
176 }
177
178 BindContext(env, obj);
179
180 SetExtensionCommon(JsExtensionCommon::Create(jsRuntime_, static_cast<NativeReference&>(*jsObj_), shellContextRef_));
181
182 handler_ = handler;
183 auto context = GetContext();
184 auto appContext = Context::GetApplicationContext();
185 if (context != nullptr && appContext != nullptr) {
186 auto appConfig = appContext->GetConfiguration();
187 if (appConfig != nullptr) {
188 NETMGR_EXT_LOG_D("Original config dump: %{public}s", appConfig->GetName().c_str());
189 context->SetConfiguration(std::make_shared<Configuration>(*appConfig));
190 }
191 }
192 ListenWMS();
193 }
194
ListenWMS()195 void JsVpnExtension::ListenWMS()
196 {
197 #ifdef SUPPORT_GRAPHICS
198 NETMGR_EXT_LOG_I("RegisterDisplayListener");
199 auto abilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
200 if (abilityManager == nullptr) {
201 NETMGR_EXT_LOG_E("Failed to get SaMgr.");
202 return;
203 }
204
205 auto jsVpnExtension = std::static_pointer_cast<JsVpnExtension>(shared_from_this());
206 displayListener_ = sptr<JsVpnExtensionDisplayListener>::MakeSptr(jsVpnExtension);
207 if (displayListener_ == nullptr) {
208 NETMGR_EXT_LOG_E("Failed to create display listener.");
209 return;
210 }
211
212 auto listener = sptr<SystemAbilityStatusChangeListener>::MakeSptr(displayListener_);
213 if (listener == nullptr) {
214 NETMGR_EXT_LOG_E("Failed to create status change listener.");
215 return;
216 }
217
218 auto ret = abilityManager->SubscribeSystemAbility(WINDOW_MANAGER_SERVICE_ID, listener);
219 if (ret != 0) {
220 NETMGR_EXT_LOG_E("subscribe system ability failed, ret = %{public}d.", ret);
221 }
222 #endif
223 }
224
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)225 void JsVpnExtension::SystemAbilityStatusChangeListener::OnAddSystemAbility(int32_t systemAbilityId,
226 const std::string& deviceId)
227 {
228 NETMGR_EXT_LOG_I("systemAbilityId: %{public}d add", systemAbilityId);
229 if (systemAbilityId == WINDOW_MANAGER_SERVICE_ID) {
230 Rosen::DisplayManager::GetInstance().RegisterDisplayListener(tmpDisplayListener_);
231 }
232 }
233
BindContext(napi_env env,napi_value obj)234 void JsVpnExtension::BindContext(napi_env env, napi_value obj)
235 {
236 auto context = GetContext();
237 if (context == nullptr) {
238 NETMGR_EXT_LOG_E("Failed to get context");
239 return;
240 }
241 NETMGR_EXT_LOG_I("call");
242 napi_value contextObj = CreateJsVpnExtensionContext(env, context);
243 shellContextRef_ = JsRuntime::LoadSystemModuleByEngine(env, "application.VpnExtensionContext",
244 &contextObj, ARGC_ONE);
245 if (shellContextRef_ == nullptr) {
246 NETMGR_EXT_LOG_E("Failed to get context");
247 return;
248 }
249 contextObj = shellContextRef_->GetNapiValue();
250 if (!CheckTypeForNapiValue(env, contextObj, napi_object)) {
251 NETMGR_EXT_LOG_E("Failed to get context native object");
252 return;
253 }
254 auto workContext = new (std::nothrow) std::weak_ptr<VpnExtensionContext>(context);
255 if (workContext == nullptr) {
256 NETMGR_EXT_LOG_E("Failed to get workContext");
257 return;
258 }
259 napi_coerce_to_native_binding_object(
260 env, contextObj, DetachCallbackFunc, AttachVpnExtensionContext, workContext, nullptr);
261 NETMGR_EXT_LOG_I("JsVpnExtension::Init Bind.");
262 context->Bind(jsRuntime_, shellContextRef_.get());
263 NETMGR_EXT_LOG_I("JsVpnExtension::SetProperty.");
264 napi_set_named_property(env, obj, "context", contextObj);
265 NETMGR_EXT_LOG_I("Set vpn extension context");
266
267 napi_wrap(env, contextObj, workContext,
268 [](napi_env, void* data, void*) {
269 NETMGR_EXT_LOG_I("Finalizer for weak_ptr vpn extension context is called");
270 delete static_cast<std::weak_ptr<VpnExtensionContext>*>(data);
271 },
272 nullptr, nullptr);
273
274 NETMGR_EXT_LOG_I("JsVpnExtension::Init end.");
275 }
276
OnStart(const AAFwk::Want & want)277 void JsVpnExtension::OnStart(const AAFwk::Want &want)
278 {
279 Extension::OnStart(want);
280 NETMGR_EXT_LOG_I("call");
281
282 auto context = GetContext();
283 if (context == nullptr) {
284 NETMGR_EXT_LOG_E("context is null");
285 return;
286 }
287
288 int displayId = want.GetIntParam(Want::PARAM_RESV_DISPLAY_ID, Rosen::WindowScene::DEFAULT_DISPLAY_ID);
289 auto configUtils = std::make_shared<ConfigurationUtils>();
290 configUtils->InitDisplayConfig(displayId, context->GetConfiguration(), context->GetResourceManager());
291
292 HandleScope handleScope(jsRuntime_);
293 napi_env env = jsRuntime_.GetNapiEnv();
294
295 // display config has changed, need update context.config
296 JsExtensionContext::ConfigurationUpdated(env, shellContextRef_, context->GetConfiguration());
297
298 napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want);
299 napi_value argv[] = {napiWant};
300 CallObjectMethod("onCreate", argv, ARGC_ONE);
301 NETMGR_EXT_LOG_I("ok");
302 }
303
OnStop()304 void JsVpnExtension::OnStop()
305 {
306 VpnExtension::OnStop();
307 NETMGR_EXT_LOG_I("call");
308 CallObjectMethod("onDestroy");
309 bool ret = ConnectionManager::GetInstance().DisconnectCaller(GetContext()->GetToken());
310 if (ret) {
311 ConnectionManager::GetInstance().ReportConnectionLeakEvent(getpid(), gettid());
312 NETMGR_EXT_LOG_I("The vpn extension connection is not disconnected.");
313 }
314 Rosen::DisplayManager::GetInstance().UnregisterDisplayListener(displayListener_);
315 NETMGR_EXT_LOG_I("ok");
316 }
317
OnConnect(const AAFwk::Want & want)318 sptr<IRemoteObject> JsVpnExtension::OnConnect(const AAFwk::Want &want)
319 {
320 HandleScope handleScope(jsRuntime_);
321 napi_value result = CallOnConnect(want);
322 napi_env env = jsRuntime_.GetNapiEnv();
323 auto remoteObj = NAPI_ohos_rpc_getNativeRemoteObject(env, result);
324 if (remoteObj == nullptr) {
325 NETMGR_EXT_LOG_E("remoteObj null.");
326 }
327 return remoteObj;
328 }
329
OnConnect(const AAFwk::Want & want,AppExecFwk::AbilityTransactionCallbackInfo<sptr<IRemoteObject>> * callbackInfo,bool & isAsyncCallback)330 sptr<IRemoteObject> JsVpnExtension::OnConnect(const AAFwk::Want &want,
331 AppExecFwk::AbilityTransactionCallbackInfo<sptr<IRemoteObject>> *callbackInfo, bool &isAsyncCallback)
332 {
333 HandleScope handleScope(jsRuntime_);
334 napi_env env = jsRuntime_.GetNapiEnv();
335 napi_value result = CallOnConnect(want);
336 bool isPromise = CheckPromise(result);
337 if (!isPromise) {
338 isAsyncCallback = false;
339 sptr<IRemoteObject> remoteObj = NAPI_ohos_rpc_getNativeRemoteObject(env, result);
340 if (remoteObj == nullptr) {
341 NETMGR_EXT_LOG_E("remoteObj null.");
342 }
343 return remoteObj;
344 }
345
346 bool callResult = false;
347 do {
348 if (!CheckTypeForNapiValue(env, result, napi_object)) {
349 NETMGR_EXT_LOG_E("CallPromise, error to convert native value to NativeObject.");
350 break;
351 }
352 napi_value then = nullptr;
353 napi_get_named_property(env, result, "then", &then);
354 if (then == nullptr) {
355 NETMGR_EXT_LOG_E("CallPromise, error to get property: then.");
356 break;
357 }
358 bool isCallable = false;
359 napi_is_callable(env, then, &isCallable);
360 if (!isCallable) {
361 NETMGR_EXT_LOG_E("CallPromise, property then is not callable");
362 break;
363 }
364 napi_value promiseCallback = nullptr;
365 napi_create_function(env, "promiseCallback", strlen("promiseCallback"),
366 OnConnectPromiseCallback, callbackInfo, &promiseCallback);
367 napi_value argv[1] = { promiseCallback };
368 napi_call_function(env, result, then, 1, argv, nullptr);
369 callResult = true;
370 } while (false);
371
372 if (!callResult) {
373 NETMGR_EXT_LOG_E("error to call promise.");
374 isAsyncCallback = false;
375 } else {
376 isAsyncCallback = true;
377 }
378 return nullptr;
379 }
380
OnDisconnect(const AAFwk::Want & want)381 void JsVpnExtension::OnDisconnect(const AAFwk::Want &want)
382 {
383 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
384 Extension::OnDisconnect(want);
385 NETMGR_EXT_LOG_D("%{public}s begin.", __func__);
386 CallOnDisconnect(want, false);
387 NETMGR_EXT_LOG_D("%{public}s end.", __func__);
388 }
389
OnDisconnect(const AAFwk::Want & want,AppExecFwk::AbilityTransactionCallbackInfo<> * callbackInfo,bool & isAsyncCallback)390 void JsVpnExtension::OnDisconnect(const AAFwk::Want &want,
391 AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo, bool &isAsyncCallback)
392 {
393 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
394 Extension::OnDisconnect(want);
395 NETMGR_EXT_LOG_D("%{public}s start.", __func__);
396 napi_value result = CallOnDisconnect(want, true);
397 bool isPromise = CheckPromise(result);
398 if (!isPromise) {
399 isAsyncCallback = false;
400 return;
401 }
402 bool callResult = CallPromise(result, callbackInfo);
403 if (!callResult) {
404 NETMGR_EXT_LOG_E("error to call promise.");
405 isAsyncCallback = false;
406 } else {
407 isAsyncCallback = true;
408 }
409
410 NETMGR_EXT_LOG_D("%{public}s end.", __func__);
411 }
412
OnCommand(const AAFwk::Want & want,bool restart,int startId)413 void JsVpnExtension::OnCommand(const AAFwk::Want &want, bool restart, int startId)
414 {
415 Extension::OnCommand(want, restart, startId);
416 NETMGR_EXT_LOG_I("restart=%{public}s,startId=%{public}d.",
417 restart ? "true" : "false",
418 startId);
419 // wrap want
420 HandleScope handleScope(jsRuntime_);
421 napi_env env = jsRuntime_.GetNapiEnv();
422 napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want);
423 // wrap startId
424 napi_value napiStartId = nullptr;
425 napi_create_int32(env, startId, &napiStartId);
426 napi_value argv[] = {napiWant, napiStartId};
427 CallObjectMethod("onRequest", argv, ARGC_TWO);
428 NETMGR_EXT_LOG_I("ok");
429 }
430
CallObjectMethod(const char * name,napi_value const * argv,size_t argc)431 napi_value JsVpnExtension::CallObjectMethod(const char* name, napi_value const* argv, size_t argc)
432 {
433 NETMGR_EXT_LOG_I("CallObjectMethod(%{public}s)", name);
434
435 if (!jsObj_) {
436 HILOG_WARN("Not found VpnExtension.js");
437 return nullptr;
438 }
439
440 HandleScope handleScope(jsRuntime_);
441 napi_env env = jsRuntime_.GetNapiEnv();
442
443 napi_value obj = jsObj_->GetNapiValue();
444 if (!CheckTypeForNapiValue(env, obj, napi_object)) {
445 NETMGR_EXT_LOG_E("Failed to get VpnExtension object");
446 return nullptr;
447 }
448
449 napi_value method = nullptr;
450 napi_get_named_property(env, obj, name, &method);
451 if (!CheckTypeForNapiValue(env, method, napi_function)) {
452 NETMGR_EXT_LOG_E("Failed to get '%{public}s' from VpnExtension object", name);
453 return nullptr;
454 }
455 NETMGR_EXT_LOG_I("CallFunction(%{public}s) ok", name);
456 napi_value result = nullptr;
457 napi_call_function(env, obj, method, argc, argv, &result);
458 return result;
459 }
460
GetSrcPath(std::string & srcPath)461 void JsVpnExtension::GetSrcPath(std::string &srcPath)
462 {
463 NETMGR_EXT_LOG_D("GetSrcPath start.");
464 if (!Extension::abilityInfo_->isModuleJson) {
465 /* temporary compatibility api8 + config.json */
466 srcPath.append(Extension::abilityInfo_->package);
467 srcPath.append("/assets/js/");
468 if (!Extension::abilityInfo_->srcPath.empty()) {
469 srcPath.append(Extension::abilityInfo_->srcPath);
470 }
471 srcPath.append("/").append(Extension::abilityInfo_->name).append(".abc");
472 return;
473 }
474
475 if (!Extension::abilityInfo_->srcEntrance.empty()) {
476 srcPath.append(Extension::abilityInfo_->moduleName + "/");
477 srcPath.append(Extension::abilityInfo_->srcEntrance);
478 srcPath.erase(srcPath.rfind('.'));
479 srcPath.append(".abc");
480 }
481 }
482
CallOnConnect(const AAFwk::Want & want)483 napi_value JsVpnExtension::CallOnConnect(const AAFwk::Want &want)
484 {
485 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
486 Extension::OnConnect(want);
487 NETMGR_EXT_LOG_D("call");
488 napi_env env = jsRuntime_.GetNapiEnv();
489 napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want);
490 napi_value argv[] = {napiWant};
491 if (!jsObj_) {
492 HILOG_WARN("Not found VpnExtension.js");
493 return nullptr;
494 }
495
496 napi_value obj = jsObj_->GetNapiValue();
497 if (!CheckTypeForNapiValue(env, obj, napi_object)) {
498 NETMGR_EXT_LOG_E("Failed to get VpnExtension object");
499 return nullptr;
500 }
501
502 napi_value method = nullptr;
503 napi_get_named_property(env, obj, "onConnect", &method);
504 if (method == nullptr) {
505 NETMGR_EXT_LOG_E("Failed to get onConnect from VpnExtension object");
506 return nullptr;
507 }
508 napi_value remoteNative = nullptr;
509 napi_call_function(env, obj, method, ARGC_ONE, argv, &remoteNative);
510 if (remoteNative == nullptr) {
511 NETMGR_EXT_LOG_E("remoteNative nullptr.");
512 }
513 NETMGR_EXT_LOG_I("ok");
514 return remoteNative;
515 }
516
CallOnDisconnect(const AAFwk::Want & want,bool withResult)517 napi_value JsVpnExtension::CallOnDisconnect(const AAFwk::Want &want, bool withResult)
518 {
519 HandleEscape handleEscape(jsRuntime_);
520 napi_env env = jsRuntime_.GetNapiEnv();
521 napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want);
522 napi_value argv[] = { napiWant };
523 if (!jsObj_) {
524 HILOG_WARN("Not found VpnExtension.js");
525 return nullptr;
526 }
527
528 napi_value obj = jsObj_->GetNapiValue();
529 if (!CheckTypeForNapiValue(env, obj, napi_object)) {
530 NETMGR_EXT_LOG_E("Failed to get VpnExtension object");
531 return nullptr;
532 }
533
534 napi_value method = nullptr;
535 napi_get_named_property(env, obj, "onDisconnect", &method);
536 if (method == nullptr) {
537 NETMGR_EXT_LOG_E("Failed to get onDisconnect from VpnExtension object");
538 return nullptr;
539 }
540
541 if (withResult) {
542 napi_value result = nullptr;
543 napi_call_function(env, obj, method, ARGC_ONE, argv, &result);
544 return handleEscape.Escape(result);
545 } else {
546 napi_call_function(env, obj, method, ARGC_ONE, argv, nullptr);
547 return nullptr;
548 }
549 }
550
CheckPromise(napi_value result)551 bool JsVpnExtension::CheckPromise(napi_value result)
552 {
553 if (result == nullptr) {
554 NETMGR_EXT_LOG_D("CheckPromise, result is nullptr, no need to call promise.");
555 return false;
556 }
557 napi_env env = jsRuntime_.GetNapiEnv();
558 bool isPromise = false;
559 napi_is_promise(env, result, &isPromise);
560 if (!isPromise) {
561 NETMGR_EXT_LOG_D("CheckPromise, result is not promise, no need to call promise.");
562 return false;
563 }
564 return true;
565 }
566
CallPromise(napi_value result,AppExecFwk::AbilityTransactionCallbackInfo<> * callbackInfo)567 bool JsVpnExtension::CallPromise(napi_value result, AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo)
568 {
569 napi_env env = jsRuntime_.GetNapiEnv();
570 if (!CheckTypeForNapiValue(env, result, napi_object)) {
571 NETMGR_EXT_LOG_E("CallPromise, Error to convert native value to NativeObject.");
572 return false;
573 }
574 napi_value then = nullptr;
575 napi_get_named_property(env, result, "then", &then);
576 if (then == nullptr) {
577 NETMGR_EXT_LOG_E("CallPromise, Error to get property: then.");
578 return false;
579 }
580 bool isCallable = false;
581 napi_is_callable(env, then, &isCallable);
582 if (!isCallable) {
583 NETMGR_EXT_LOG_E("CallPromise, Property then is not callable.");
584 return false;
585 }
586 HandleScope handleScope(jsRuntime_);
587 napi_value promiseCallback = nullptr;
588 napi_create_function(env, "promiseCallback", strlen("promiseCallback"), PromiseCallback,
589 callbackInfo, &promiseCallback);
590 napi_value argv[1] = { promiseCallback };
591 napi_call_function(env, result, then, 1, argv, nullptr);
592 NETMGR_EXT_LOG_D("end");
593 return true;
594 }
595
OnConfigurationUpdated(const AppExecFwk::Configuration & configuration)596 void JsVpnExtension::OnConfigurationUpdated(const AppExecFwk::Configuration& configuration)
597 {
598 VpnExtension::OnConfigurationUpdated(configuration);
599 NETMGR_EXT_LOG_I("call");
600 auto context = GetContext();
601 if (context == nullptr) {
602 NETMGR_EXT_LOG_E("Context is invalid.");
603 return;
604 }
605
606 auto contextConfig = context->GetConfiguration();
607 if (contextConfig != nullptr) {
608 NETMGR_EXT_LOG_D("Config dump: %{public}s", contextConfig->GetName().c_str());
609 std::vector<std::string> changeKeyV;
610 contextConfig->CompareDifferent(changeKeyV, configuration);
611 if (!changeKeyV.empty()) {
612 contextConfig->Merge(changeKeyV, configuration);
613 }
614 NETMGR_EXT_LOG_D("Config dump after merge: %{public}s", contextConfig->GetName().c_str());
615 }
616 ConfigurationUpdated();
617 }
618
ConfigurationUpdated()619 void JsVpnExtension::ConfigurationUpdated()
620 {
621 NETMGR_EXT_LOG_D("called.");
622 HandleScope handleScope(jsRuntime_);
623 napi_env env = jsRuntime_.GetNapiEnv();
624
625 // Notify extension context
626 auto fullConfig = GetContext()->GetConfiguration();
627 if (!fullConfig) {
628 NETMGR_EXT_LOG_E("configuration is nullptr.");
629 return;
630 }
631
632 napi_value napiConfiguration = OHOS::AppExecFwk::WrapConfiguration(env, *fullConfig);
633 CallObjectMethod("onConfigurationUpdated", &napiConfiguration, ARGC_ONE);
634 CallObjectMethod("onConfigurationUpdate", &napiConfiguration, ARGC_ONE);
635 JsExtensionContext::ConfigurationUpdated(env, shellContextRef_, fullConfig);
636 }
637
Dump(const std::vector<std::string> & params,std::vector<std::string> & info)638 void JsVpnExtension::Dump(const std::vector<std::string> ¶ms, std::vector<std::string> &info)
639 {
640 Extension::Dump(params, info);
641 NETMGR_EXT_LOG_I("call");
642 HandleScope handleScope(jsRuntime_);
643 napi_env env = jsRuntime_.GetNapiEnv();
644 // create js array object of params
645 napi_value argv[] = { CreateNativeArray(env, params) };
646
647 if (!jsObj_) {
648 HILOG_WARN("Not found VpnExtension.js");
649 return;
650 }
651
652 napi_value obj = jsObj_->GetNapiValue();
653 if (!CheckTypeForNapiValue(env, obj, napi_object)) {
654 NETMGR_EXT_LOG_E("Failed to get VpnExtension object");
655 return;
656 }
657
658 napi_value method = nullptr;
659 napi_get_named_property(env, obj, "onDump", &method);
660 if (!CheckTypeForNapiValue(env, method, napi_function)) {
661 method = nullptr;
662 napi_get_named_property(env, obj, "dump", &method);
663 if (!CheckTypeForNapiValue(env, method, napi_function)) {
664 NETMGR_EXT_LOG_E("Failed to get onConnect from VpnExtension object");
665 return;
666 }
667 }
668 NETMGR_EXT_LOG_I("JsVpnExtension::CallFunction onConnect, success");
669 napi_value dumpInfo = nullptr;
670 napi_call_function(env, obj, method, ARGC_ONE, argv, &dumpInfo);
671 if (dumpInfo == nullptr) {
672 NETMGR_EXT_LOG_E("dumpInfo nullptr.");
673 return;
674 }
675 uint32_t len = 0;
676 napi_get_array_length(env, dumpInfo, &len);
677 for (uint32_t i = 0; i < len; i++) {
678 std::string dumpInfoStr;
679 napi_value element = nullptr;
680 napi_get_element(env, dumpInfo, i, &element);
681 if (!ConvertFromJsValue(env, element, dumpInfoStr)) {
682 NETMGR_EXT_LOG_E("Parse dumpInfoStr failed.");
683 return;
684 }
685 info.push_back(dumpInfoStr);
686 }
687 NETMGR_EXT_LOG_D("Dump info size: %{public}zu", info.size());
688 }
689
690 #ifdef SUPPORT_GRAPHICS
OnCreate(Rosen::DisplayId displayId)691 void JsVpnExtension::OnCreate(Rosen::DisplayId displayId)
692 {
693 NETMGR_EXT_LOG_D("enter.");
694 }
695
OnDestroy(Rosen::DisplayId displayId)696 void JsVpnExtension::OnDestroy(Rosen::DisplayId displayId)
697 {
698 NETMGR_EXT_LOG_D("exit.");
699 }
700
OnChange(Rosen::DisplayId displayId)701 void JsVpnExtension::OnChange(Rosen::DisplayId displayId)
702 {
703 NETMGR_EXT_LOG_D("displayId: %{public}" PRIu64"", displayId);
704 auto context = GetContext();
705 if (context == nullptr) {
706 NETMGR_EXT_LOG_E("Context is invalid.");
707 return;
708 }
709
710 auto contextConfig = context->GetConfiguration();
711 if (contextConfig == nullptr) {
712 NETMGR_EXT_LOG_E("Configuration is invalid.");
713 return;
714 }
715
716 NETMGR_EXT_LOG_D("Config dump: %{public}s", contextConfig->GetName().c_str());
717 bool configChanged = false;
718 auto configUtils = std::make_shared<ConfigurationUtils>();
719 configUtils->UpdateDisplayConfig(displayId, contextConfig, context->GetResourceManager(), configChanged);
720 NETMGR_EXT_LOG_D("Config dump after update: %{public}s", contextConfig->GetName().c_str());
721
722 if (configChanged) {
723 auto jsVpnExtension = std::static_pointer_cast<JsVpnExtension>(shared_from_this());
724 auto task = [jsVpnExtension]() {
725 if (jsVpnExtension) {
726 jsVpnExtension->ConfigurationUpdated();
727 }
728 };
729 if (handler_ != nullptr) {
730 handler_->PostTask(task, "JsVpnExtension:OnChange");
731 }
732 }
733
734 NETMGR_EXT_LOG_D("finished.");
735 }
736 #endif
737 } // NetManagerStandard
738 } // OHOS
739