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