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, ¶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>::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