• 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 {
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(uint32_t argc,napi_env env,napi_value cb,RegisterType type)168 void JSUIExtensionProxy::DeleteCallbackFromList(uint32_t 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>::StaticMethod("onDrawReady", &JSUIExtension::OnDrawReady);
341     JSClass<JSUIExtension>::InheritAndBind<JSViewAbstract>(globalObj);
342 }
343 
ResolveAreaPlaceholderParams(const JSRef<JSObject> & obj,std::map<NG::PlaceholderType,RefPtr<NG::FrameNode>> & placeholderMap)344 void JSUIExtension::ResolveAreaPlaceholderParams(const JSRef<JSObject>& obj,
345     std::map<NG::PlaceholderType, RefPtr<NG::FrameNode>>& placeholderMap)
346 {
347     static const std::map<std::string, NG::PlaceholderType> placeholderTypeTable = {
348         { UI_EXTENSION_PLACEHOLDER_TYPE_UNDEFINED, NG::PlaceholderType::UNDEFINED },
349         { UI_EXTENSION_PLACEHOLDER_TYPE_ROTATION, NG::PlaceholderType::ROTATION },
350         { UI_EXTENSION_PLACEHOLDER_TYPE_FOLD_TO_EXPAND, NG::PlaceholderType::FOLD_TO_EXPAND }
351     };
352     do {
353         JSRef<JSVal> componentContentMap = obj->GetProperty("areaChangePlaceholder");
354         if (!componentContentMap->IsObject()) {
355             break;
356         }
357         auto contentMapObj = JSRef<JSObject>::Cast(componentContentMap);
358         for (auto [strName, type] : placeholderTypeTable) {
359             JSRef<JSVal> typeContent = contentMapObj->GetProperty(strName.c_str());
360             if (!typeContent->IsObject()) {
361                 continue;
362             }
363             auto componentContentObj = JSRef<JSObject>::Cast(typeContent);
364             JSRef<JSVal> builderNode = componentContentObj->GetProperty("builderNode_");
365             if (!builderNode->IsObject()) {
366                 continue;
367             }
368             auto builderNodeObj = JSRef<JSObject>::Cast(builderNode);
369             JSRef<JSVal> nodePtr = builderNodeObj->GetProperty("nodePtr_");
370             if (nodePtr.IsEmpty()) {
371                 continue;
372             }
373             const auto* vm = nodePtr->GetEcmaVM();
374             if (!(nodePtr->GetLocalHandle()->IsNativePointer(vm))) {
375                 continue;
376             }
377             auto* node = nodePtr->GetLocalHandle()->ToNativePointer(vm)->Value();
378             auto* frameNode = reinterpret_cast<NG::FrameNode*>(node);
379             if (!frameNode) {
380                 continue;
381             }
382             RefPtr<NG::FrameNode> placeholderNode = AceType::Claim(frameNode);
383             placeholderMap.insert({type, placeholderNode});
384         }
385     } while (false);
386 }
387 
388 namespace {
InsertPlaceholderObj(JsiRef<JsiObject> & obj,std::map<NG::PlaceholderType,RefPtr<NG::FrameNode>> & placeholderMap)389 void InsertPlaceholderObj(JsiRef<JsiObject>& obj,
390     std::map<NG::PlaceholderType, RefPtr<NG::FrameNode>>& placeholderMap)
391 {
392     do {
393         RefPtr<NG::FrameNode> placeholderNode = nullptr;
394         JSRef<JSVal> componentContent = obj->GetProperty("placeholder");
395         if (!componentContent->IsObject()) {
396             break;
397         }
398         auto componentContentObj = JSRef<JSObject>::Cast(componentContent);
399         JSRef<JSVal> builderNode = componentContentObj->GetProperty("builderNode_");
400         if (!builderNode->IsObject()) {
401             break;
402         }
403         auto builderNodeObj = JSRef<JSObject>::Cast(builderNode);
404         JSRef<JSVal> nodePtr = builderNodeObj->GetProperty("nodePtr_");
405         if (nodePtr.IsEmpty()) {
406             break;
407         }
408         const auto* vm = nodePtr->GetEcmaVM();
409         if (!(nodePtr->GetLocalHandle()->IsNativePointer(vm))) {
410             break;
411         }
412         auto* node = nodePtr->GetLocalHandle()->ToNativePointer(vm)->Value();
413         auto* frameNode = reinterpret_cast<NG::FrameNode*>(node);
414         if (!frameNode) {
415             break;
416         }
417         placeholderNode = AceType::Claim(frameNode);
418         placeholderMap.insert({NG::PlaceholderType::INITIAL, placeholderNode});
419     } while (false);
420 }
421 } // namespace
422 
Create(const JSCallbackInfo & info)423 void JSUIExtension::Create(const JSCallbackInfo& info)
424 {
425     if (!info[0]->IsObject()) {
426         return;
427     }
428     auto wantObj = JSRef<JSObject>::Cast(info[0]);
429     RefPtr<OHOS::Ace::WantWrap> want = CreateWantWrapFromNapiValue(wantObj);
430 
431     bool transferringCaller = false;
432     bool densityDpi = false;
433     bool windowModeStrategy = false;
434     std::map<NG::PlaceholderType, RefPtr<NG::FrameNode>> placeholderMap;
435     if (info.Length() > 1 && info[1]->IsObject()) {
436         auto obj = JSRef<JSObject>::Cast(info[1]);
437         JSRef<JSVal> transferringCallerValue = obj->GetProperty("isTransferringCaller");
438         if (transferringCallerValue->IsBoolean()) {
439             transferringCaller = transferringCallerValue->ToBoolean();
440         }
441         JSRef<JSVal> enableDensityDPI = obj->GetProperty("dpiFollowStrategy");
442         if (enableDensityDPI->IsNumber()) {
443             densityDpi = (enableDensityDPI->ToNumber<int32_t>())==0 ? true : false;
444         }
445         JSRef<JSVal> windowModeStrategyValue = obj->GetProperty("windowModeFollowStrategy");
446         if (windowModeStrategyValue->IsNumber()) {
447             windowModeStrategy = (windowModeStrategyValue->ToNumber<int32_t>()) == 0 ? true : false;
448         }
449         InsertPlaceholderObj(obj, placeholderMap);
450         ResolveAreaPlaceholderParams(obj, placeholderMap);
451     }
452     UIExtensionModel::GetInstance()->Create(want, placeholderMap, transferringCaller, densityDpi, windowModeStrategy);
453 }
454 
OnRemoteReady(const JSCallbackInfo & info)455 void JSUIExtension::OnRemoteReady(const JSCallbackInfo& info)
456 {
457     if (!info[0]->IsFunction()) {
458         return;
459     }
460     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
461     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
462     auto instanceId = ContainerScope::CurrentId();
463     auto onRemoteReady = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId, node = frameNode]
464         (const RefPtr<NG::UIExtensionProxy>& session) {
465         ContainerScope scope(instanceId);
466         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
467         auto pipelineContext = PipelineContext::GetCurrentContext();
468         CHECK_NULL_VOID(pipelineContext);
469         pipelineContext->UpdateCurrentActiveNode(node);
470         JSRef<JSObject> contextObj = JSClass<JSUIExtensionProxy>::NewInstance();
471         RefPtr<JSUIExtensionProxy> proxy = Referenced::Claim(contextObj->Unwrap<JSUIExtensionProxy>());
472         CHECK_NULL_VOID(proxy);
473         proxy->SetInstanceId(instanceId);
474         proxy->SetProxy(session);
475         auto returnValue = JSRef<JSVal>::Cast(contextObj);
476         func->ExecuteJS(1, &returnValue);
477     };
478     UIExtensionModel::GetInstance()->SetOnRemoteReady(std::move(onRemoteReady));
479 }
480 
OnReceive(const JSCallbackInfo & info)481 void JSUIExtension::OnReceive(const JSCallbackInfo& info)
482 {
483     if (!info[0]->IsFunction()) {
484         return;
485     }
486     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
487     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
488     auto instanceId = ContainerScope::CurrentId();
489     auto onReceive = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId, node = frameNode]
490         (const AAFwk::WantParams& wantParams) {
491         ContainerScope scope(instanceId);
492         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
493         ACE_SCORING_EVENT("UIExtensionComponent.UIExtensionDataSession.onReceive");
494         auto pipelineContext = PipelineContext::GetCurrentContext();
495         CHECK_NULL_VOID(pipelineContext);
496         pipelineContext->UpdateCurrentActiveNode(node);
497         auto engine = EngineHelper::GetCurrentEngine();
498         CHECK_NULL_VOID(engine);
499         NativeEngine* nativeEngine = engine->GetNativeEngine();
500         CHECK_NULL_VOID(nativeEngine);
501         auto env = reinterpret_cast<napi_env>(nativeEngine);
502         auto nativeWantParams = WantWrap::ConvertParamsToNativeValue(wantParams, env);
503         auto wantParamsJSVal = JsConverter::ConvertNapiValueToJsVal(nativeWantParams);
504         func->ExecuteJS(1, &wantParamsJSVal);
505     };
506     UIExtensionModel::GetInstance()->SetOnReceive(std::move(onReceive));
507 }
508 
OnRelease(const JSCallbackInfo & info)509 void JSUIExtension::OnRelease(const JSCallbackInfo& info)
510 {
511     if (!info[0]->IsFunction()) {
512         return;
513     }
514     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
515     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
516     auto instanceId = ContainerScope::CurrentId();
517     auto onRelease = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId, node = frameNode]
518         (int32_t releaseCode) {
519         ContainerScope scope(instanceId);
520         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
521         ACE_SCORING_EVENT("UIExtensionComponent.onRelease");
522         auto pipelineContext = PipelineContext::GetCurrentContext();
523         CHECK_NULL_VOID(pipelineContext);
524         pipelineContext->UpdateCurrentActiveNode(node);
525         auto newJSVal = JSRef<JSVal>::Make(ToJSValue(releaseCode));
526         func->ExecuteJS(1, &newJSVal);
527     };
528     UIExtensionModel::GetInstance()->SetOnRelease(std::move(onRelease));
529 }
530 
OnResult(const JSCallbackInfo & info)531 void JSUIExtension::OnResult(const JSCallbackInfo& info)
532 {
533     if (!info[0]->IsFunction()) {
534         return;
535     }
536     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
537     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
538     auto instanceId = ContainerScope::CurrentId();
539     auto onResult = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId, node = frameNode]
540         (int32_t code, const AAFwk::Want& want) {
541             ContainerScope scope(instanceId);
542             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
543             ACE_SCORING_EVENT("UIExtensionComponent.onResult");
544             auto pipelineContext = PipelineContext::GetCurrentContext();
545             CHECK_NULL_VOID(pipelineContext);
546             pipelineContext->UpdateCurrentActiveNode(node);
547             auto engine = EngineHelper::GetCurrentEngine();
548             CHECK_NULL_VOID(engine);
549             NativeEngine* nativeEngine = engine->GetNativeEngine();
550             CHECK_NULL_VOID(nativeEngine);
551             auto nativeWant = WantWrap::ConvertToNativeValue(want, reinterpret_cast<napi_env>(nativeEngine));
552             auto wantJSVal = JsConverter::ConvertNapiValueToJsVal(nativeWant);
553             JSRef<JSObject> obj = JSRef<JSObject>::New();
554             obj->SetProperty<int32_t>("code", code);
555             obj->SetPropertyObject("want", wantJSVal);
556             auto returnValue = JSRef<JSVal>::Cast(obj);
557             func->ExecuteJS(1, &returnValue);
558         };
559     UIExtensionModel::GetInstance()->SetOnResult(std::move(onResult));
560 }
561 
OnError(const JSCallbackInfo & info)562 void JSUIExtension::OnError(const JSCallbackInfo& info)
563 {
564     if (!info[0]->IsFunction()) {
565         return;
566     }
567     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
568     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
569     auto instanceId = ContainerScope::CurrentId();
570     auto onError = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId, node = frameNode]
571         (int32_t code, const std::string& name, const std::string& message) {
572             ContainerScope scope(instanceId);
573             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
574             ACE_SCORING_EVENT("UIExtensionComponent.onError");
575             auto pipelineContext = PipelineContext::GetCurrentContext();
576             CHECK_NULL_VOID(pipelineContext);
577             pipelineContext->UpdateCurrentActiveNode(node);
578             JSRef<JSObject> obj = JSRef<JSObject>::New();
579             obj->SetProperty<int32_t>("code", code);
580             obj->SetProperty<std::string>("name", name);
581             obj->SetProperty<std::string>("message", message);
582             auto returnValue = JSRef<JSVal>::Cast(obj);
583             func->ExecuteJS(1, &returnValue);
584         };
585     UIExtensionModel::GetInstance()->SetOnError(std::move(onError));
586 }
587 
OnTerminated(const JSCallbackInfo & info)588 void JSUIExtension::OnTerminated(const JSCallbackInfo& info)
589 {
590     if (!info[0]->IsFunction()) {
591         return;
592     }
593     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
594     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
595     auto instanceId = ContainerScope::CurrentId();
596     auto onTerminated = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId, node = frameNode](
597                             int32_t code, const RefPtr<WantWrap>& wantWrap) {
598         ContainerScope scope(instanceId);
599         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
600         ACE_SCORING_EVENT("EmbeddedComponent.onTerminated");
601         auto pipelineContext = PipelineContext::GetCurrentContext();
602         CHECK_NULL_VOID(pipelineContext);
603         pipelineContext->UpdateCurrentActiveNode(node);
604         auto engine = EngineHelper::GetCurrentEngine();
605         CHECK_NULL_VOID(engine);
606         NativeEngine* nativeEngine = engine->GetNativeEngine();
607         CHECK_NULL_VOID(nativeEngine);
608         JSRef<JSObject> obj = JSRef<JSObject>::New();
609         obj->SetProperty<int32_t>("code", code);
610         if (wantWrap) {
611             auto nativeWant =
612                 WantWrap::ConvertToNativeValue(wantWrap->GetWant(), reinterpret_cast<napi_env>(nativeEngine));
613             auto wantJSVal = JsConverter::ConvertNapiValueToJsVal(nativeWant);
614             obj->SetPropertyObject("want", wantJSVal);
615         }
616         auto returnValue = JSRef<JSVal>::Cast(obj);
617         func->ExecuteJS(1, &returnValue);
618     };
619     UIExtensionModel::GetInstance()->SetOnTerminated(std::move(onTerminated));
620 }
621 
OnDrawReady(const JSCallbackInfo & info)622 void JSUIExtension::OnDrawReady(const JSCallbackInfo& info)
623 {
624     if (!info[0]->IsFunction()) {
625         return;
626     }
627     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
628     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
629     auto instanceId = ContainerScope::CurrentId();
630     auto onDrawReady = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), instanceId, node = frameNode]
631         () {
632             ContainerScope scope(instanceId);
633             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
634             ACE_SCORING_EVENT("UIExtensionComponent.onDrawReady");
635             auto pipelineContext = PipelineContext::GetCurrentContext();
636             CHECK_NULL_VOID(pipelineContext);
637             pipelineContext->UpdateCurrentActiveNode(node);
638             auto newJSVal = JSRef<JSVal>::Make();
639             func->ExecuteJS(1, &newJSVal);
640     };
641     UIExtensionModel::GetInstance()->SetOnDrawReady(std::move(onDrawReady));
642 }
643 } // namespace OHOS::Ace::Framework
644