1 /*
2  * Copyright (c) 2024 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 "bridge/declarative_frontend/jsview/js_security_ui_extension.h"
17 
18 #include <functional>
19 #include <string>
20 #include "want_params.h"
21 
22 #include "base/log/ace_scoring_log.h"
23 #include "base/want/want_wrap.h"
24 #include "bridge/common/utils/engine_helper.h"
25 #include "bridge/declarative_frontend/engine/js_converter.h"
26 #include "bridge/declarative_frontend/jsview/js_utils.h"
27 #include "core/common/container_scope.h"
28 #include "core/components_ng/base/view_abstract_model.h"
29 #include "core/components_ng/base/view_stack_processor.h"
30 #include "core/components_ng/pattern/ui_extension/ui_extension_model.h"
31 #include "core/components_ng/pattern/ui_extension/ui_extension_model_ng.h"
32 #include "interfaces/include/ws_common.h"
33 
34 namespace OHOS::Ace::Framework {
35 namespace {
36     constexpr int ARGC_TWO = 2;
37     const CalcDimension SECURITY_UEC_MIN_WIDTH(10.0f, DimensionUnit::VP);
38     const CalcDimension SECURITY_UEC_MIN_HEIGHT(10.0f, DimensionUnit::VP);
39 }
JSBind(BindingTarget globalObj)40 void JSSecurityUIExtensionProxy::JSBind(BindingTarget globalObj)
41 {
42     JSClass<JSSecurityUIExtensionProxy>::Declare("SecurityUIExtensionProxy");
43     JSClass<JSSecurityUIExtensionProxy>::CustomMethod("send", &JSSecurityUIExtensionProxy::Send);
44     JSClass<JSSecurityUIExtensionProxy>::CustomMethod("sendSync", &JSSecurityUIExtensionProxy::SendSync);
45     JSClass<JSSecurityUIExtensionProxy>::CustomMethod("on", &JSSecurityUIExtensionProxy::On);
46     JSClass<JSSecurityUIExtensionProxy>::CustomMethod("off", &JSSecurityUIExtensionProxy::Off);
47     JSClass<JSSecurityUIExtensionProxy>::Bind(
48         globalObj, &JSSecurityUIExtensionProxy::Constructor, &JSSecurityUIExtensionProxy::Destructor);
49 }
50 
Constructor(const JSCallbackInfo & info)51 void JSSecurityUIExtensionProxy::Constructor(const JSCallbackInfo& info)
52 {
53     auto uiExtensionProxy = Referenced::MakeRefPtr<JSSecurityUIExtensionProxy>();
54     uiExtensionProxy->IncRefCount();
55     info.SetReturnValue(Referenced::RawPtr(uiExtensionProxy));
56 }
57 
Destructor(JSSecurityUIExtensionProxy * uiExtensionProxy)58 void JSSecurityUIExtensionProxy::Destructor(JSSecurityUIExtensionProxy* uiExtensionProxy)
59 {
60     if (uiExtensionProxy != nullptr) {
61         uiExtensionProxy->DecRefCount();
62     }
63 }
64 
Send(const JSCallbackInfo & info)65 void JSSecurityUIExtensionProxy::Send(const JSCallbackInfo& info)
66 {
67     if (!info[0]->IsObject()) {
68         return;
69     }
70     ContainerScope scope(instanceId_);
71     auto engine = EngineHelper::GetCurrentEngine();
72     CHECK_NULL_VOID(engine);
73     NativeEngine* nativeEngine = engine->GetNativeEngine();
74     panda::Local<JsiValue> value = info[0].Get().GetLocalHandle();
75     JSValueWrapper valueWrapper = value;
76     ScopeRAII scopeNapi(reinterpret_cast<napi_env>(nativeEngine));
77     napi_value nativeValue = nativeEngine->ValueToNapiValue(valueWrapper);
78     auto wantParams = WantParamsWrap::CreateWantWrap(
79         reinterpret_cast<napi_env>(nativeEngine), nativeValue);
80     if (proxy_) {
81         proxy_->SendData(wantParams);
82     }
83 }
84 
SendSync(const JSCallbackInfo & info)85 void JSSecurityUIExtensionProxy::SendSync(const JSCallbackInfo& info)
86 {
87     if (info.Length() == 0 || !info[0]->IsObject()) {
88         return;
89     }
90     ContainerScope scope(instanceId_);
91     auto engine = EngineHelper::GetCurrentEngine();
92     CHECK_NULL_VOID(engine);
93     NativeEngine* nativeEngine = engine->GetNativeEngine();
94     CHECK_NULL_VOID(nativeEngine);
95     panda::Local<JsiValue> value = info[0].Get().GetLocalHandle();
96     JSValueWrapper valueWrapper = value;
97     ScopeRAII scopeNapi(reinterpret_cast<napi_env>(nativeEngine));
98     napi_value nativeValue = nativeEngine->ValueToNapiValue(valueWrapper);
99     auto wantParams = WantParamsWrap::CreateWantWrap(
100         reinterpret_cast<napi_env>(nativeEngine), nativeValue);
101     if (proxy_) {
102         AAFwk::WantParams reWantParams;
103         int32_t sendCode = proxy_->SendDataSync(wantParams, reWantParams);
104         if (sendCode != 0) {
105             std::string errMsg;
106             if (sendCode == ERROR_CODE_UIEXTENSION_NOT_REGISTER_SYNC_CALLBACK) {
107                 errMsg = "No callback has been registered to process synchronous data transferring.";
108             } else if (sendCode == ERROR_CODE_UIEXTENSION_TRANSFER_DATA_FAILED) {
109                 errMsg = "Transferring data failed.";
110             } else {
111                 errMsg = "Unknown error.";
112             }
113             JSException::Throw(sendCode, errMsg.c_str());
114             return;
115         }
116         auto execCtx = info.GetExecutionContext();
117         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
118         auto reNativeWantParams = WantWrap::ConvertParamsToNativeValue(
119             reWantParams, reinterpret_cast<napi_env>(nativeEngine));
120         auto reWantParamsJSVal =
121             Framework::JsConverter::ConvertNapiValueToJsVal(reNativeWantParams);
122         info.SetReturnValue(reWantParamsJSVal);
123     }
124 }
125 
FindCbList(napi_env env,napi_value cb,SecurityCallbackFuncPairList & callbackFuncPairList)126 SecurityCallbackFuncPairList::const_iterator JSSecurityUIExtensionProxy::FindCbList(
127     napi_env env, napi_value cb, SecurityCallbackFuncPairList& callbackFuncPairList)
128 {
129     return std::find_if(callbackFuncPairList.begin(), callbackFuncPairList.end(),
130         [env, cb](const auto& item) -> bool {
131         bool result = false;
132         napi_value refItem;
133         napi_get_reference_value(env, item.first, &refItem);
134         napi_strict_equals(env, refItem, cb, &result);
135         return result;
136     });
137 }
138 
AddCallbackToList(napi_env env,napi_value cb,napi_handle_scope scope,RegisterType type,const std::function<void (const RefPtr<NG::SecurityUIExtensionProxy> &)> && onFunc)139 void JSSecurityUIExtensionProxy::AddCallbackToList(
140     napi_env env, napi_value cb, napi_handle_scope scope, RegisterType type,
141     const std::function<void(const RefPtr<NG::SecurityUIExtensionProxy>&)>&& onFunc)
142 {
143     if (type == RegisterType::SYNC) {
144         auto iter = FindCbList(env, cb, onSyncOnCallbackList_);
145         if (iter == onSyncOnCallbackList_.end()) {
146             napi_ref ref = nullptr;
147             napi_create_reference(env, cb, 1, &ref);
148             onSyncOnCallbackList_.emplace_back(ref, onFunc);
149         }
150     } else if (type == RegisterType::ASYNC) {
151         auto iter = FindCbList(env, cb, onAsyncOnCallbackList_);
152         if (iter == onAsyncOnCallbackList_.end()) {
153             napi_ref ref = nullptr;
154             napi_create_reference(env, cb, 1, &ref);
155             onAsyncOnCallbackList_.emplace_back(ref, onFunc);
156         }
157     }
158     napi_close_handle_scope(env, scope);
159 }
160 
DeleteCallbackFromList(int argc,napi_env env,napi_value cb,RegisterType type)161 void JSSecurityUIExtensionProxy::DeleteCallbackFromList(
162     int argc, napi_env env, napi_value cb, RegisterType type)
163 {
164     if (argc == 1) {
165         if (type == RegisterType::SYNC) {
166             for (const auto& item : onSyncOnCallbackList_) {
167                 napi_delete_reference(env, item.first);
168             }
169             onSyncOnCallbackList_.clear();
170         } else if (type == RegisterType::ASYNC) {
171             for (const auto& item : onAsyncOnCallbackList_) {
172                 napi_delete_reference(env, item.first);
173             }
174             onAsyncOnCallbackList_.clear();
175         }
176     } else if (argc == ARGC_TWO) {
177         if (type == RegisterType::SYNC) {
178             auto iter = FindCbList(env, cb, onSyncOnCallbackList_);
179             if (iter != onSyncOnCallbackList_.end()) {
180                 napi_delete_reference(env, iter->first);
181                 onSyncOnCallbackList_.erase(iter);
182             }
183         } else if (type == RegisterType::ASYNC) {
184             auto iter = FindCbList(env, cb, onAsyncOnCallbackList_);
185             if (iter != onAsyncOnCallbackList_.end()) {
186                 napi_delete_reference(env, iter->first);
187                 onAsyncOnCallbackList_.erase(iter);
188             }
189         }
190     }
191 }
192 
GetOnFuncList(RegisterType type)193 std::list<std::function<void(const RefPtr<NG::SecurityUIExtensionProxy>&)>> JSSecurityUIExtensionProxy::GetOnFuncList(
194     RegisterType type)
195 {
196     std::list<std::function<void(const RefPtr<NG::SecurityUIExtensionProxy>&)>> reList;
197     if (type == RegisterType::SYNC) {
198         for (const auto& item : onSyncOnCallbackList_) {
199             reList.emplace_back(item.second);
200         }
201     } else if (type == RegisterType::ASYNC) {
202         for (const auto& item : onAsyncOnCallbackList_) {
203             reList.emplace_back(item.second);
204         }
205     }
206     return reList;
207 }
208 
GetRegisterType(const std::string & strType)209 RegisterType JSSecurityUIExtensionProxy::GetRegisterType(const std::string& strType)
210 {
211     RegisterType type = RegisterType::UNKNOWN;
212     static constexpr char syncType[] = "syncReceiverRegister";
213     static constexpr char asyncType[] = "asyncReceiverRegister";
214     if (strType.compare(syncType) == 0) {
215         type = RegisterType::SYNC;
216     } else if (strType.compare(asyncType) == 0) {
217         type = RegisterType::ASYNC;
218     }
219     return type;
220 }
221 
On(const JSCallbackInfo & info)222 void JSSecurityUIExtensionProxy::On(const JSCallbackInfo& info)
223 {
224     if (!info[0]->IsString() || !info[1]->IsFunction()) {
225         return;
226     }
227     const RegisterType registerType = GetRegisterType(info[0]->ToString());
228     if (registerType == RegisterType::UNKNOWN) {
229         return;
230     }
231 
232     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(
233         NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
234     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[1]));
235     auto instanceId = ContainerScope::CurrentId();
236     auto onOnFunc = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
237         instanceId, node = frameNode] (const RefPtr<NG::SecurityUIExtensionProxy>& session) {
238             ContainerScope scope(instanceId);
239             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
240             auto pipelineContext = PipelineContext::GetCurrentContext();
241             CHECK_NULL_VOID(pipelineContext);
242             pipelineContext->UpdateCurrentActiveNode(node);
243             JSRef<JSObject> contextObj = JSClass<JSSecurityUIExtensionProxy>::NewInstance();
244             RefPtr<JSSecurityUIExtensionProxy> proxy =
245                 Referenced::Claim(contextObj->Unwrap<JSSecurityUIExtensionProxy>());
246             CHECK_NULL_VOID(proxy);
247             proxy->SetInstanceId(instanceId);
248             proxy->SetProxy(session);
249             auto param = JSRef<JSVal>::Cast(contextObj);
250             func->ExecuteJS(1, &param);
251         };
252 
253     ContainerScope scope(instanceId_);
254     auto engine = EngineHelper::GetCurrentEngine();
255     CHECK_NULL_VOID(engine);
256     NativeEngine* nativeEngine = engine->GetNativeEngine();
257     CHECK_NULL_VOID(nativeEngine);
258     auto env = reinterpret_cast<napi_env>(nativeEngine);
259     ScopeRAII scopeNapi(env);
260     panda::Local<JsiValue> value = info[1].Get().GetLocalHandle();
261     JSValueWrapper valueWrapper = value;
262     napi_value cb = nativeEngine->ValueToNapiValue(valueWrapper);
263     napi_handle_scope napiScope = nullptr;
264     napi_open_handle_scope(env, &napiScope);
265     CHECK_NULL_VOID(napiScope);
266     std::lock_guard<std::mutex> lock(callbackLisLock_);
267     AddCallbackToList(env, cb, napiScope, registerType, std::move(onOnFunc));
268     auto pattern = proxy_->GetPattern();
269     CHECK_NULL_VOID(pattern);
270     auto onFuncList = GetOnFuncList(registerType);
271     if (registerType == RegisterType::SYNC) {
272         pattern->SetSyncCallbacks(std::move(onFuncList));
273     } else if (registerType == RegisterType::ASYNC) {
274         pattern->SetAsyncCallbacks(std::move(onFuncList));
275     }
276 }
277 
Off(const JSCallbackInfo & info)278 void JSSecurityUIExtensionProxy::Off(const JSCallbackInfo& info)
279 {
280     if (!info[0]->IsString()) {
281         return;
282     }
283     const RegisterType registerType = GetRegisterType(info[0]->ToString());
284     if (registerType == RegisterType::UNKNOWN) {
285         return;
286     }
287 
288     ContainerScope scope(instanceId_);
289     auto engine = EngineHelper::GetCurrentEngine();
290     CHECK_NULL_VOID(engine);
291     NativeEngine* nativeEngine = engine->GetNativeEngine();
292     CHECK_NULL_VOID(nativeEngine);
293     auto env = reinterpret_cast<napi_env>(nativeEngine);
294     ScopeRAII scopeNapi(env);
295     napi_value cb = nullptr;
296     if (info[1]->IsFunction()) {
297         panda::Local<JsiValue> value = info[1].Get().GetLocalHandle();
298         JSValueWrapper valueWrapper = value;
299         cb = nativeEngine->ValueToNapiValue(valueWrapper);
300     }
301 
302     std::lock_guard<std::mutex> lock(callbackLisLock_);
303     DeleteCallbackFromList(info.Length(), env, cb, registerType);
304     auto pattern = proxy_->GetPattern();
305     CHECK_NULL_VOID(pattern);
306     auto onFuncList = GetOnFuncList(registerType);
307     if (registerType == RegisterType::SYNC) {
308         pattern->SetSyncCallbacks(std::move(onFuncList));
309     } else if (registerType == RegisterType::ASYNC) {
310         pattern->SetAsyncCallbacks(std::move(onFuncList));
311     }
312 }
313 
SetInstanceId(int32_t instanceId)314 void JSSecurityUIExtensionProxy::SetInstanceId(int32_t instanceId)
315 {
316     instanceId_ = instanceId;
317 }
318 
SetProxy(const RefPtr<NG::SecurityUIExtensionProxy> & proxy)319 void JSSecurityUIExtensionProxy::SetProxy(
320     const RefPtr<NG::SecurityUIExtensionProxy>& proxy)
321 {
322     proxy_ = proxy;
323 }
324 
JSBind(BindingTarget globalObj)325 void JSSecurityUIExtension::JSBind(BindingTarget globalObj)
326 {
327     JSClass<JSSecurityUIExtension>::Declare("SecurityUIExtensionComponent");
328     MethodOptions opt = MethodOptions::NONE;
329     JSClass<JSSecurityUIExtension>::StaticMethod("create", &JSSecurityUIExtension::Create, opt);
330     JSClass<JSSecurityUIExtension>::StaticMethod("onRemoteReady", &JSSecurityUIExtension::OnRemoteReady);
331     JSClass<JSSecurityUIExtension>::StaticMethod("onReceive", &JSSecurityUIExtension::OnReceive);
332     JSClass<JSSecurityUIExtension>::StaticMethod("onError", &JSSecurityUIExtension::OnError);
333     JSClass<JSSecurityUIExtension>::StaticMethod("onTerminated", &JSSecurityUIExtension::OnTerminated);
334     JSClass<JSSecurityUIExtension>::StaticMethod("width", &JSViewAbstract::JsWidth);
335     JSClass<JSSecurityUIExtension>::StaticMethod("height", &JSViewAbstract::JsHeight);
336     JSClass<JSSecurityUIExtension>::StaticMethod("backgroundColor", &JSViewAbstract::JsBackgroundColor);
337     JSClass<JSSecurityUIExtension>::Bind(globalObj);
338 }
339 
Create(const JSCallbackInfo & info)340 void JSSecurityUIExtension::Create(const JSCallbackInfo& info)
341 {
342     if (!info[0]->IsObject()) {
343         return;
344     }
345 
346     NG::UIExtensionConfig config;
347     config.sessionType = NG::SessionType::SECURITY_UI_EXTENSION_ABILITY;
348     auto wantObj = JSRef<JSObject>::Cast(info[0]);
349     RefPtr<OHOS::Ace::WantWrap> want = CreateWantWrapFromNapiValue(wantObj);
350     if (want == nullptr) {
351         TAG_LOGI(AceLogTag::ACE_SECURITYUIEXTENSION, "want is nullptr");
352         return;
353     }
354 
355     config.wantWrap = want;
356     RefPtr<NG::FrameNode> placeholderNode = nullptr;
357     if (info.Length() > 1 && info[1]->IsObject()) {
358         auto obj = JSRef<JSObject>::Cast(info[1]);
359         JSRef<JSVal> transferringCallerValue = obj->GetProperty("isTransferringCaller");
360         if (transferringCallerValue->IsBoolean()) {
361             config.transferringCaller = transferringCallerValue->ToBoolean();
362         }
363         JSRef<JSVal> enableDensityDPI = obj->GetProperty("dpiFollowStrategy");
364         if (enableDensityDPI->IsNumber()) {
365             config.densityDpi = (enableDensityDPI->ToNumber<int32_t>())==0 ? true : false;
366         }
367         do {
368             JSRef<JSVal> componentContent = obj->GetProperty("placeholder");
369             if (!componentContent->IsObject()) {
370                 break;
371             }
372             auto componentContentObj = JSRef<JSObject>::Cast(componentContent);
373             JSRef<JSVal> builderNode = componentContentObj->GetProperty("builderNode_");
374             if (!builderNode->IsObject()) {
375                 break;
376             }
377             auto builderNodeObj = JSRef<JSObject>::Cast(builderNode);
378             JSRef<JSVal> nodePtr = builderNodeObj->GetProperty("nodePtr_");
379             if (nodePtr.IsEmpty()) {
380                 break;
381             }
382             const auto* vm = nodePtr->GetEcmaVM();
383             auto* node = nodePtr->GetLocalHandle()->ToNativePointer(vm)->Value();
384             auto* frameNode = reinterpret_cast<NG::FrameNode*>(node);
385             if (!frameNode) {
386                 break;
387             }
388             config.placeholderNode = AceType::Claim(frameNode);
389         } while (false);
390     }
391     UIExtensionModel::GetInstance()->Create(config);
392     ViewAbstractModel::GetInstance()->SetMinWidth(SECURITY_UEC_MIN_WIDTH);
393     ViewAbstractModel::GetInstance()->SetMinHeight(SECURITY_UEC_MIN_HEIGHT);
394 }
395 
OnRemoteReady(const JSCallbackInfo & info)396 void JSSecurityUIExtension::OnRemoteReady(const JSCallbackInfo& info)
397 {
398     if (!info[0]->IsFunction()) {
399         return;
400     }
401     WeakPtr<NG::FrameNode> frameNode =
402         AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
403     auto jsFunc = AceType::MakeRefPtr<JsFunction>(
404         JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
405     auto instanceId = ContainerScope::CurrentId();
406     auto onRemoteReady = [execCtx = info.GetExecutionContext(),
407         func = std::move(jsFunc), instanceId, node = frameNode]
408             (const RefPtr<NG::SecurityUIExtensionProxy>& session) {
409             ContainerScope scope(instanceId);
410             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
411             auto pipelineContext = PipelineContext::GetCurrentContext();
412             CHECK_NULL_VOID(pipelineContext);
413             pipelineContext->UpdateCurrentActiveNode(node);
414             JSRef<JSObject> contextObj = JSClass<JSSecurityUIExtensionProxy>::NewInstance();
415             RefPtr<JSSecurityUIExtensionProxy> proxy =
416                 Referenced::Claim(contextObj->Unwrap<JSSecurityUIExtensionProxy>());
417             CHECK_NULL_VOID(proxy);
418             proxy->SetInstanceId(instanceId);
419             proxy->SetProxy(session);
420             auto returnValue = JSRef<JSVal>::Cast(contextObj);
421             func->ExecuteJS(1, &returnValue);
422         };
423     UIExtensionModel::GetInstance()->SetSecurityOnRemoteReady(std::move(onRemoteReady));
424 }
425 
OnReceive(const JSCallbackInfo & info)426 void JSSecurityUIExtension::OnReceive(const JSCallbackInfo& info)
427 {
428     if (!info[0]->IsFunction()) {
429         return;
430     }
431     WeakPtr<NG::FrameNode> frameNode =
432         AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
433     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
434     auto instanceId = ContainerScope::CurrentId();
435     auto onReceive = [execCtx = info.GetExecutionContext(),
436         func = std::move(jsFunc), instanceId, node = frameNode]
437             (const AAFwk::WantParams& wantParams) {
438             ContainerScope scope(instanceId);
439             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
440             ACE_SCORING_EVENT("SecurityUIExtensionComponent.UIExtensionDataSession.onReceive");
441             auto pipelineContext = PipelineContext::GetCurrentContext();
442             CHECK_NULL_VOID(pipelineContext);
443             pipelineContext->UpdateCurrentActiveNode(node);
444             auto engine = EngineHelper::GetCurrentEngine();
445             CHECK_NULL_VOID(engine);
446             NativeEngine* nativeEngine = engine->GetNativeEngine();
447             CHECK_NULL_VOID(nativeEngine);
448             auto env = reinterpret_cast<napi_env>(nativeEngine);
449             auto nativeWantParams = WantWrap::ConvertParamsToNativeValue(wantParams, env);
450             auto wantParamsJSVal = JsConverter::ConvertNapiValueToJsVal(nativeWantParams);
451             func->ExecuteJS(1, &wantParamsJSVal);
452         };
453     UIExtensionModel::GetInstance()->SetOnReceive(
454         std::move(onReceive), NG::SessionType::SECURITY_UI_EXTENSION_ABILITY);
455 }
456 
OnError(const JSCallbackInfo & info)457 void JSSecurityUIExtension::OnError(const JSCallbackInfo& info)
458 {
459     if (!info[0]->IsFunction()) {
460         return;
461     }
462     WeakPtr<NG::FrameNode> frameNode =
463         AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
464     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
465     auto instanceId = ContainerScope::CurrentId();
466     auto onError = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
467         instanceId, node = frameNode] (int32_t code, const std::string& name, const std::string& message) {
468             ContainerScope scope(instanceId);
469             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
470             ACE_SCORING_EVENT("SecurityUIExtensionComponent.onError");
471             auto pipelineContext = PipelineContext::GetCurrentContext();
472             CHECK_NULL_VOID(pipelineContext);
473             pipelineContext->UpdateCurrentActiveNode(node);
474             JSRef<JSObject> obj = JSRef<JSObject>::New();
475             obj->SetProperty<int32_t>("code", code);
476             obj->SetProperty<std::string>("name", name);
477             obj->SetProperty<std::string>("message", message);
478             auto returnValue = JSRef<JSVal>::Cast(obj);
479             func->ExecuteJS(1, &returnValue);
480         };
481     UIExtensionModel::GetInstance()->SetOnError(
482         std::move(onError), NG::SessionType::SECURITY_UI_EXTENSION_ABILITY);
483 }
484 
OnTerminated(const JSCallbackInfo & info)485 void JSSecurityUIExtension::OnTerminated(const JSCallbackInfo& info)
486 {
487     if (!info[0]->IsFunction()) {
488         return;
489     }
490     WeakPtr<NG::FrameNode> frameNode =
491         AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
492     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
493     auto instanceId = ContainerScope::CurrentId();
494     auto onTerminated = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
495         instanceId, node = frameNode] (int32_t code, const RefPtr<WantWrap>& wantWrap) {
496             ContainerScope scope(instanceId);
497             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
498             ACE_SCORING_EVENT("SecurityUIExtensionComponent.onTerminated");
499             auto pipelineContext = PipelineContext::GetCurrentContext();
500             CHECK_NULL_VOID(pipelineContext);
501             pipelineContext->UpdateCurrentActiveNode(node);
502             auto engine = EngineHelper::GetCurrentEngine();
503             CHECK_NULL_VOID(engine);
504             NativeEngine* nativeEngine = engine->GetNativeEngine();
505             CHECK_NULL_VOID(nativeEngine);
506             JSRef<JSObject> obj = JSRef<JSObject>::New();
507             obj->SetProperty<int32_t>("code", code);
508             if (wantWrap) {
509                 auto nativeWant = WantWrap::ConvertToNativeValue(
510                     wantWrap->GetWant(), reinterpret_cast<napi_env>(nativeEngine));
511                 auto wantJSVal = JsConverter::ConvertNapiValueToJsVal(nativeWant);
512                 obj->SetPropertyObject("want", wantJSVal);
513             }
514             auto returnValue = JSRef<JSVal>::Cast(obj);
515             func->ExecuteJS(1, &returnValue);
516         };
517     UIExtensionModel::GetInstance()->SetOnTerminated(
518         std::move(onTerminated), NG::SessionType::SECURITY_UI_EXTENSION_ABILITY);
519 }
520 } // namespace OHOS::Ace::Framework
521