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, ¶m);
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