• 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 {
GetInstance()34 UIExtensionModel* UIExtensionModel::GetInstance()
35 {
36     if (!Container::IsCurrentUseNewPipeline()) {
37         LOGE("Get UIExtensionModel in non NewPipeline.");
38     }
39     static NG::UIExtensionModelNG instance;
40     return &instance;
41 }
42 } // namespace OHOS::Ace
43 
44 namespace OHOS::Ace::Framework {
JSBind(BindingTarget globalObj)45 void JSUIExtensionProxy::JSBind(BindingTarget globalObj)
46 {
47     JSClass<JSUIExtensionProxy>::Declare("UIExtensionProxy ");
48     JSClass<JSUIExtensionProxy>::CustomMethod("send", &JSUIExtensionProxy::Send);
49     JSClass<JSUIExtensionProxy>::CustomMethod("sendSync", &JSUIExtensionProxy::SendSync);
50     JSClass<JSUIExtensionProxy>::CustomMethod("on", &JSUIExtensionProxy::On);
51     JSClass<JSUIExtensionProxy>::CustomMethod("off", &JSUIExtensionProxy::Off);
52     JSClass<JSUIExtensionProxy>::Bind(globalObj, &JSUIExtensionProxy::Constructor, &JSUIExtensionProxy::Destructor);
53 }
54 
Constructor(const JSCallbackInfo & info)55 void JSUIExtensionProxy::Constructor(const JSCallbackInfo& info)
56 {
57     auto uiExtensionProxy = Referenced::MakeRefPtr<JSUIExtensionProxy>();
58     uiExtensionProxy->IncRefCount();
59     info.SetReturnValue(Referenced::RawPtr(uiExtensionProxy));
60 }
61 
Destructor(JSUIExtensionProxy * uiExtensionProxy)62 void JSUIExtensionProxy::Destructor(JSUIExtensionProxy* uiExtensionProxy)
63 {
64     if (uiExtensionProxy != nullptr) {
65         uiExtensionProxy->DecRefCount();
66     }
67 }
68 
Send(const JSCallbackInfo & info)69 void JSUIExtensionProxy::Send(const JSCallbackInfo& info)
70 {
71     if (!info[0]->IsObject()) {
72         return;
73     }
74     ContainerScope scope(instanceId_);
75     auto engine = EngineHelper::GetCurrentEngine();
76     CHECK_NULL_VOID(engine);
77     NativeEngine* nativeEngine = engine->GetNativeEngine();
78     panda::Local<JsiValue> value = info[0].Get().GetLocalHandle();
79     JSValueWrapper valueWrapper = value;
80     ScopeRAII scopeNapi(reinterpret_cast<napi_env>(nativeEngine));
81     napi_value nativeValue = nativeEngine->ValueToNapiValue(valueWrapper);
82 
83     auto wantParams = WantParamsWrap::CreateWantWrap(reinterpret_cast<napi_env>(nativeEngine), nativeValue);
84     if (proxy_) {
85         proxy_->SendData(wantParams);
86     }
87 }
88 
SendSync(const JSCallbackInfo & info)89 void JSUIExtensionProxy::SendSync(const JSCallbackInfo& info)
90 {
91     if (info.Length() == 0 || !info[0]->IsObject()) {
92         return;
93     }
94     ContainerScope scope(instanceId_);
95     auto engine = EngineHelper::GetCurrentEngine();
96     CHECK_NULL_VOID(engine);
97     NativeEngine* nativeEngine = engine->GetNativeEngine();
98     CHECK_NULL_VOID(nativeEngine);
99     panda::Local<JsiValue> value = info[0].Get().GetLocalHandle();
100     JSValueWrapper valueWrapper = value;
101     ScopeRAII scopeNapi(reinterpret_cast<napi_env>(nativeEngine));
102     napi_value nativeValue = nativeEngine->ValueToNapiValue(valueWrapper);
103     auto wantParams = WantParamsWrap::CreateWantWrap(reinterpret_cast<napi_env>(nativeEngine), nativeValue);
104     if (proxy_) {
105         AAFwk::WantParams reWantParams;
106         int32_t sendCode = proxy_->SendDataSync(wantParams, reWantParams);
107         if (sendCode != 0) {
108             std::string errMsg;
109             if (sendCode == ERROR_CODE_UIEXTENSION_NOT_REGISTER_SYNC_CALLBACK) {
110                 errMsg = "No callback has been registered to process synchronous data transferring.";
111             } else if (sendCode == ERROR_CODE_UIEXTENSION_TRANSFER_DATA_FAILED) {
112                 errMsg = "Transferring data failed.";
113             } else {
114                 errMsg = "Unknown error.";
115             }
116             JSException::Throw(sendCode, errMsg.c_str());
117             return;
118         }
119         auto execCtx = info.GetExecutionContext();
120         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
121         auto reNativeWantParams =
122             WantWrap::ConvertParamsToNativeValue(reWantParams, reinterpret_cast<napi_env>(nativeEngine));
123         auto reWantParamsJSVal = Framework::JsConverter::ConvertNapiValueToJsVal(reNativeWantParams);
124         info.SetReturnValue(reWantParamsJSVal);
125     }
126 }
127 
FindCbList(napi_env env,napi_value cb,CallbackFuncPairList & callbackFuncPairList)128 CallbackFuncPairList::const_iterator JSUIExtensionProxy::FindCbList(napi_env env, napi_value cb,
129     CallbackFuncPairList& callbackFuncPairList)
130 {
131     return std::find_if(callbackFuncPairList.begin(), callbackFuncPairList.end(),
132         [env, cb](const auto& item) -> bool {
133         bool result = false;
134         napi_value refItem;
135         napi_get_reference_value(env, item.first, &refItem);
136         napi_strict_equals(env, refItem, cb, &result);
137         return result;
138     });
139 }
140 
AddCallbackToList(napi_env env,napi_value cb,napi_handle_scope scope,RegisterType type,const std::function<void (const RefPtr<NG::UIExtensionProxy> &)> && onFunc)141 void JSUIExtensionProxy::AddCallbackToList(napi_env env, napi_value cb,
142     napi_handle_scope scope, RegisterType type,
143     const std::function<void(const RefPtr<NG::UIExtensionProxy>&)>&& onFunc)
144 {
145     if (type == RegisterType::SYNC) {
146         auto iter = FindCbList(env, cb, onSyncOnCallbackList_);
147         if (iter == onSyncOnCallbackList_.end()) {
148             napi_ref ref = nullptr;
149             napi_create_reference(env, cb, 1, &ref);
150             onSyncOnCallbackList_.emplace_back(ref, onFunc);
151         }
152     } else if (type == RegisterType::ASYNC) {
153         auto iter = FindCbList(env, cb, onAsyncOnCallbackList_);
154         if (iter == onAsyncOnCallbackList_.end()) {
155             napi_ref ref = nullptr;
156             napi_create_reference(env, cb, 1, &ref);
157             onAsyncOnCallbackList_.emplace_back(ref, onFunc);
158         }
159     }
160     napi_close_handle_scope(env, scope);
161 }
162 
DeleteCallbackFromList(int argc,napi_env env,napi_value cb,RegisterType type)163 void JSUIExtensionProxy::DeleteCallbackFromList(int argc, napi_env env, napi_value cb, RegisterType type)
164 {
165     if (argc == 1) {
166         if (type == RegisterType::SYNC) {
167             for (const auto& item : onSyncOnCallbackList_) {
168                 napi_delete_reference(env, item.first);
169             }
170             onSyncOnCallbackList_.clear();
171         } else if (type == RegisterType::ASYNC) {
172             for (const auto& item : onAsyncOnCallbackList_) {
173                 napi_delete_reference(env, item.first);
174             }
175             onAsyncOnCallbackList_.clear();
176         }
177     } else if (argc == 2) {
178         if (type == RegisterType::SYNC) {
179             auto iter = FindCbList(env, cb, onSyncOnCallbackList_);
180             if (iter != onSyncOnCallbackList_.end()) {
181                 napi_delete_reference(env, iter->first);
182                 onSyncOnCallbackList_.erase(iter);
183             }
184         } else if (type == RegisterType::ASYNC) {
185             auto iter = FindCbList(env, cb, onAsyncOnCallbackList_);
186             if (iter != onAsyncOnCallbackList_.end()) {
187                 napi_delete_reference(env, iter->first);
188                 onAsyncOnCallbackList_.erase(iter);
189             }
190         }
191     }
192 }
193 
GetOnFuncList(RegisterType type)194 std::list<std::function<void(const RefPtr<NG::UIExtensionProxy>&)>> JSUIExtensionProxy::GetOnFuncList(
195     RegisterType type)
196 {
197     std::list<std::function<void(const RefPtr<NG::UIExtensionProxy>&)>> reList;
198     if (type == RegisterType::SYNC) {
199         for (const auto& item : onSyncOnCallbackList_) {
200             reList.emplace_back(item.second);
201         }
202     } else if (type == RegisterType::ASYNC) {
203         for (const auto& item : onAsyncOnCallbackList_) {
204             reList.emplace_back(item.second);
205         }
206     }
207     return reList;
208 }
209 
GetRegisterType(const std::string & strType)210 RegisterType JSUIExtensionProxy::GetRegisterType(const std::string& strType)
211 {
212     RegisterType type = RegisterType::UNKNOWN;
213     static constexpr char syncType[] = "syncReceiverRegister";
214     static constexpr char asyncType[] = "asyncReceiverRegister";
215     if (strType.compare(syncType) == 0) {
216         type = RegisterType::SYNC;
217     } else if (strType.compare(asyncType) == 0) {
218         type = RegisterType::ASYNC;
219     }
220     return type;
221 }
222 
On(const JSCallbackInfo & info)223 void JSUIExtensionProxy::On(const JSCallbackInfo& info)
224 {
225     if (!info[0]->IsString() || !info[1]->IsFunction()) {
226         return;
227     }
228     const RegisterType registerType = GetRegisterType(info[0]->ToString());
229     if (registerType == RegisterType::UNKNOWN) {
230         return;
231     }
232 
233     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(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), instanceId, node = frameNode]
237         (const RefPtr<NG::UIExtensionProxy>& 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<JSUIExtensionProxy>::NewInstance();
244         RefPtr<JSUIExtensionProxy> proxy = Referenced::Claim(contextObj->Unwrap<JSUIExtensionProxy>());
245         CHECK_NULL_VOID(proxy);
246         proxy->SetInstanceId(instanceId);
247         proxy->SetProxy(session);
248         auto param = JSRef<JSVal>::Cast(contextObj);
249         func->ExecuteJS(1, &param);
250     };
251 
252     ContainerScope scope(instanceId_);
253     auto engine = EngineHelper::GetCurrentEngine();
254     CHECK_NULL_VOID(engine);
255     NativeEngine* nativeEngine = engine->GetNativeEngine();
256     CHECK_NULL_VOID(nativeEngine);
257     auto env = reinterpret_cast<napi_env>(nativeEngine);
258     ScopeRAII scopeNapi(env);
259     panda::Local<JsiValue> value = info[1].Get().GetLocalHandle();
260     JSValueWrapper valueWrapper = value;
261     napi_value cb = nativeEngine->ValueToNapiValue(valueWrapper);
262     napi_handle_scope napiScope = nullptr;
263     napi_open_handle_scope(env, &napiScope);
264     CHECK_NULL_VOID(napiScope);
265 
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 JSUIExtensionProxy::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 JSUIExtensionProxy::SetInstanceId(int32_t instanceId)
315 {
316     instanceId_ = instanceId;
317 }
318 
SetProxy(const RefPtr<NG::UIExtensionProxy> & proxy)319 void JSUIExtensionProxy::SetProxy(const RefPtr<NG::UIExtensionProxy>& proxy)
320 {
321     proxy_ = proxy;
322 }
323 
JSBind(BindingTarget globalObj)324 void JSUIExtension::JSBind(BindingTarget globalObj)
325 {
326     JSClass<JSUIExtension>::Declare("UIExtensionComponent");
327     MethodOptions opt = MethodOptions::NONE;
328     JSClass<JSUIExtension>::StaticMethod("create", &JSUIExtension::Create, opt);
329     JSClass<JSUIExtension>::StaticMethod("onRemoteReady", &JSUIExtension::OnRemoteReady);
330     JSClass<JSUIExtension>::StaticMethod("onReceive", &JSUIExtension::OnReceive);
331     JSClass<JSUIExtension>::StaticMethod("onRelease", &JSUIExtension::OnRelease);
332     JSClass<JSUIExtension>::StaticMethod("onResult", &JSUIExtension::OnResult);
333     JSClass<JSUIExtension>::StaticMethod("onError", &JSUIExtension::OnError);
334     JSClass<JSUIExtension>::StaticMethod("onTerminated", &JSUIExtension::OnTerminated);
335     JSClass<JSUIExtension>::InheritAndBind<JSViewAbstract>(globalObj);
336 }
337 
Create(const JSCallbackInfo & info)338 void JSUIExtension::Create(const JSCallbackInfo& info)
339 {
340     if (!info[0]->IsObject()) {
341         return;
342     }
343     auto wantObj = JSRef<JSObject>::Cast(info[0]);
344     RefPtr<OHOS::Ace::WantWrap> want = CreateWantWrapFromNapiValue(wantObj);
345 
346     bool transferringCaller = false;
347     bool densityDpi = false;
348     RefPtr<NG::FrameNode> placeholderNode = nullptr;
349     if (info.Length() > 1 && info[1]->IsObject()) {
350         auto obj = JSRef<JSObject>::Cast(info[1]);
351         JSRef<JSVal> transferringCallerValue = obj->GetProperty("isTransferringCaller");
352         if (transferringCallerValue->IsBoolean()) {
353             transferringCaller = transferringCallerValue->ToBoolean();
354         }
355         JSRef<JSVal> enableDensityDPI = obj->GetProperty("dpiFollowStrategy");
356         if (enableDensityDPI->IsNumber()) {
357             densityDpi = (enableDensityDPI->ToNumber<int32_t>())==0 ? true : false;
358         }
359         do {
360             JSRef<JSVal> componentContent = obj->GetProperty("placeholder");
361             if (!componentContent->IsObject()) {
362                 break;
363             }
364             auto componentContentObj = JSRef<JSObject>::Cast(componentContent);
365             JSRef<JSVal> builderNode = componentContentObj->GetProperty("builderNode_");
366             if (!builderNode->IsObject()) {
367                 break;
368             }
369             auto builderNodeObj = JSRef<JSObject>::Cast(builderNode);
370             JSRef<JSVal> nodePtr = builderNodeObj->GetProperty("nodePtr_");
371             if (nodePtr.IsEmpty()) {
372                 break;
373             }
374             const auto* vm = nodePtr->GetEcmaVM();
375             auto* node = nodePtr->GetLocalHandle()->ToNativePointer(vm)->Value();
376             auto* frameNode = reinterpret_cast<NG::FrameNode*>(node);
377             if (!frameNode) {
378                 break;
379             }
380             placeholderNode = AceType::Claim(frameNode);
381         } while (false);
382     }
383     UIExtensionModel::GetInstance()->Create(want, placeholderNode, transferringCaller, densityDpi);
384 }
385 
OnRemoteReady(const JSCallbackInfo & info)386 void JSUIExtension::OnRemoteReady(const JSCallbackInfo& info)
387 {
388     if (!info[0]->IsFunction()) {
389         return;
390     }
391     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
392     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
393     auto instanceId = ContainerScope::CurrentId();
394     auto onRemoteReady = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId, node = frameNode]
395         (const RefPtr<NG::UIExtensionProxy>& session) {
396         ContainerScope scope(instanceId);
397         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
398         auto pipelineContext = PipelineContext::GetCurrentContext();
399         CHECK_NULL_VOID(pipelineContext);
400         pipelineContext->UpdateCurrentActiveNode(node);
401         JSRef<JSObject> contextObj = JSClass<JSUIExtensionProxy>::NewInstance();
402         RefPtr<JSUIExtensionProxy> proxy = Referenced::Claim(contextObj->Unwrap<JSUIExtensionProxy>());
403         CHECK_NULL_VOID(proxy);
404         proxy->SetInstanceId(instanceId);
405         proxy->SetProxy(session);
406         auto returnValue = JSRef<JSVal>::Cast(contextObj);
407         func->ExecuteJS(1, &returnValue);
408     };
409     UIExtensionModel::GetInstance()->SetOnRemoteReady(std::move(onRemoteReady));
410 }
411 
OnReceive(const JSCallbackInfo & info)412 void JSUIExtension::OnReceive(const JSCallbackInfo& info)
413 {
414     if (!info[0]->IsFunction()) {
415         return;
416     }
417     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
418     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
419     auto instanceId = ContainerScope::CurrentId();
420     auto onReceive = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId, node = frameNode]
421         (const AAFwk::WantParams& wantParams) {
422         ContainerScope scope(instanceId);
423         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
424         ACE_SCORING_EVENT("UIExtensionComponent.UIExtensionDataSession.onReceive");
425         auto pipelineContext = PipelineContext::GetCurrentContext();
426         CHECK_NULL_VOID(pipelineContext);
427         pipelineContext->UpdateCurrentActiveNode(node);
428         auto engine = EngineHelper::GetCurrentEngine();
429         CHECK_NULL_VOID(engine);
430         NativeEngine* nativeEngine = engine->GetNativeEngine();
431         CHECK_NULL_VOID(nativeEngine);
432         auto env = reinterpret_cast<napi_env>(nativeEngine);
433         auto nativeWantParams = WantWrap::ConvertParamsToNativeValue(wantParams, env);
434         auto wantParamsJSVal = JsConverter::ConvertNapiValueToJsVal(nativeWantParams);
435         func->ExecuteJS(1, &wantParamsJSVal);
436     };
437     UIExtensionModel::GetInstance()->SetOnReceive(std::move(onReceive));
438 }
439 
OnRelease(const JSCallbackInfo & info)440 void JSUIExtension::OnRelease(const JSCallbackInfo& info)
441 {
442     if (!info[0]->IsFunction()) {
443         return;
444     }
445     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
446     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
447     auto instanceId = ContainerScope::CurrentId();
448     auto onRelease = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId, node = frameNode]
449         (int32_t releaseCode) {
450         ContainerScope scope(instanceId);
451         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
452         ACE_SCORING_EVENT("UIExtensionComponent.onRelease");
453         auto pipelineContext = PipelineContext::GetCurrentContext();
454         CHECK_NULL_VOID(pipelineContext);
455         pipelineContext->UpdateCurrentActiveNode(node);
456         auto newJSVal = JSRef<JSVal>::Make(ToJSValue(releaseCode));
457         func->ExecuteJS(1, &newJSVal);
458     };
459     UIExtensionModel::GetInstance()->SetOnRelease(std::move(onRelease));
460 }
461 
OnResult(const JSCallbackInfo & info)462 void JSUIExtension::OnResult(const JSCallbackInfo& info)
463 {
464     if (!info[0]->IsFunction()) {
465         return;
466     }
467     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
468     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
469     auto instanceId = ContainerScope::CurrentId();
470     auto onResult = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId, node = frameNode]
471         (int32_t code, const AAFwk::Want& want) {
472             ContainerScope scope(instanceId);
473             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
474             ACE_SCORING_EVENT("UIExtensionComponent.onResult");
475             auto pipelineContext = PipelineContext::GetCurrentContext();
476             CHECK_NULL_VOID(pipelineContext);
477             pipelineContext->UpdateCurrentActiveNode(node);
478             auto engine = EngineHelper::GetCurrentEngine();
479             CHECK_NULL_VOID(engine);
480             NativeEngine* nativeEngine = engine->GetNativeEngine();
481             CHECK_NULL_VOID(nativeEngine);
482             auto nativeWant = WantWrap::ConvertToNativeValue(want, reinterpret_cast<napi_env>(nativeEngine));
483             auto wantJSVal = JsConverter::ConvertNapiValueToJsVal(nativeWant);
484             JSRef<JSObject> obj = JSRef<JSObject>::New();
485             obj->SetProperty<int32_t>("code", code);
486             obj->SetPropertyObject("want", wantJSVal);
487             auto returnValue = JSRef<JSVal>::Cast(obj);
488             func->ExecuteJS(1, &returnValue);
489         };
490     UIExtensionModel::GetInstance()->SetOnResult(std::move(onResult));
491 }
492 
OnError(const JSCallbackInfo & info)493 void JSUIExtension::OnError(const JSCallbackInfo& info)
494 {
495     if (!info[0]->IsFunction()) {
496         return;
497     }
498     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
499     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
500     auto instanceId = ContainerScope::CurrentId();
501     auto onError = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId, node = frameNode]
502         (int32_t code, const std::string& name, const std::string& message) {
503             ContainerScope scope(instanceId);
504             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
505             ACE_SCORING_EVENT("UIExtensionComponent.onError");
506             auto pipelineContext = PipelineContext::GetCurrentContext();
507             CHECK_NULL_VOID(pipelineContext);
508             pipelineContext->UpdateCurrentActiveNode(node);
509             JSRef<JSObject> obj = JSRef<JSObject>::New();
510             obj->SetProperty<int32_t>("code", code);
511             obj->SetProperty<std::string>("name", name);
512             obj->SetProperty<std::string>("message", message);
513             auto returnValue = JSRef<JSVal>::Cast(obj);
514             func->ExecuteJS(1, &returnValue);
515         };
516     UIExtensionModel::GetInstance()->SetOnError(std::move(onError));
517 }
518 
OnTerminated(const JSCallbackInfo & info)519 void JSUIExtension::OnTerminated(const JSCallbackInfo& info)
520 {
521     if (!info[0]->IsFunction()) {
522         return;
523     }
524     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
525     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
526     auto instanceId = ContainerScope::CurrentId();
527     auto onTerminated = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId, node = frameNode](
528                             int32_t code, const RefPtr<WantWrap>& wantWrap) {
529         ContainerScope scope(instanceId);
530         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
531         ACE_SCORING_EVENT("EmbeddedComponent.onTerminated");
532         auto pipelineContext = PipelineContext::GetCurrentContext();
533         CHECK_NULL_VOID(pipelineContext);
534         pipelineContext->UpdateCurrentActiveNode(node);
535         auto engine = EngineHelper::GetCurrentEngine();
536         CHECK_NULL_VOID(engine);
537         NativeEngine* nativeEngine = engine->GetNativeEngine();
538         CHECK_NULL_VOID(nativeEngine);
539         JSRef<JSObject> obj = JSRef<JSObject>::New();
540         obj->SetProperty<int32_t>("code", code);
541         if (wantWrap) {
542             auto nativeWant =
543                 WantWrap::ConvertToNativeValue(wantWrap->GetWant(), reinterpret_cast<napi_env>(nativeEngine));
544             auto wantJSVal = JsConverter::ConvertNapiValueToJsVal(nativeWant);
545             obj->SetPropertyObject("want", wantJSVal);
546         }
547         auto returnValue = JSRef<JSVal>::Cast(obj);
548         func->ExecuteJS(1, &returnValue);
549     };
550     UIExtensionModel::GetInstance()->SetOnTerminated(std::move(onTerminated));
551 }
552 } // namespace OHOS::Ace::Framework
553