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