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