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