• 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 "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> &params, 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