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