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