1 /*
2 * Copyright (c) 2024 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_security_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_abstract_model.h"
29 #include "core/components_ng/base/view_stack_processor.h"
30 #include "core/components_ng/pattern/ui_extension/preview_ui_extension_component/preview_ui_extension_adapter.h"
31 #include "core/components_ng/pattern/ui_extension/ui_extension_model.h"
32 #include "core/components_ng/pattern/ui_extension/ui_extension_model_ng.h"
33 #include "interfaces/include/ws_common.h"
34
35 namespace OHOS::Ace::Framework {
36 namespace {
37 constexpr uint8_t ARGC_TWO = 2;
38 const CalcDimension SECURITY_UEC_MIN_WIDTH(10.0f, DimensionUnit::VP);
39 const CalcDimension SECURITY_UEC_MIN_HEIGHT(10.0f, DimensionUnit::VP);
40 }
JSBind(BindingTarget globalObj)41 void JSSecurityUIExtensionProxy::JSBind(BindingTarget globalObj)
42 {
43 JSClass<JSSecurityUIExtensionProxy>::Declare("SecurityUIExtensionProxy");
44 JSClass<JSSecurityUIExtensionProxy>::CustomMethod("send", &JSSecurityUIExtensionProxy::Send);
45 JSClass<JSSecurityUIExtensionProxy>::CustomMethod("sendSync", &JSSecurityUIExtensionProxy::SendSync);
46 JSClass<JSSecurityUIExtensionProxy>::CustomMethod("on", &JSSecurityUIExtensionProxy::On);
47 JSClass<JSSecurityUIExtensionProxy>::CustomMethod("off", &JSSecurityUIExtensionProxy::Off);
48 JSClass<JSSecurityUIExtensionProxy>::Bind(
49 globalObj, &JSSecurityUIExtensionProxy::Constructor, &JSSecurityUIExtensionProxy::Destructor);
50 }
51
Constructor(const JSCallbackInfo & info)52 void JSSecurityUIExtensionProxy::Constructor(const JSCallbackInfo& info)
53 {
54 auto uiExtensionProxy = Referenced::MakeRefPtr<JSSecurityUIExtensionProxy>();
55 uiExtensionProxy->IncRefCount();
56 info.SetReturnValue(Referenced::RawPtr(uiExtensionProxy));
57 }
58
Destructor(JSSecurityUIExtensionProxy * uiExtensionProxy)59 void JSSecurityUIExtensionProxy::Destructor(JSSecurityUIExtensionProxy* uiExtensionProxy)
60 {
61 if (uiExtensionProxy != nullptr) {
62 uiExtensionProxy->DecRefCount();
63 }
64 }
65
Send(const JSCallbackInfo & info)66 void JSSecurityUIExtensionProxy::Send(const JSCallbackInfo& info)
67 {
68 if (!info[0]->IsObject()) {
69 return;
70 }
71 ContainerScope scope(instanceId_);
72 auto engine = EngineHelper::GetCurrentEngine();
73 CHECK_NULL_VOID(engine);
74 NativeEngine* nativeEngine = engine->GetNativeEngine();
75 panda::Local<JsiValue> value = info[0].Get().GetLocalHandle();
76 JSValueWrapper valueWrapper = value;
77 ScopeRAII scopeNapi(reinterpret_cast<napi_env>(nativeEngine));
78 napi_value nativeValue = nativeEngine->ValueToNapiValue(valueWrapper);
79 auto wantParams = WantParamsWrap::CreateWantWrap(
80 reinterpret_cast<napi_env>(nativeEngine), nativeValue);
81 if (proxy_) {
82 proxy_->SendData(wantParams);
83 }
84 }
85
SendSync(const JSCallbackInfo & info)86 void JSSecurityUIExtensionProxy::SendSync(const JSCallbackInfo& info)
87 {
88 if (info.Length() == 0 || !info[0]->IsObject()) {
89 return;
90 }
91 ContainerScope scope(instanceId_);
92 auto engine = EngineHelper::GetCurrentEngine();
93 CHECK_NULL_VOID(engine);
94 NativeEngine* nativeEngine = engine->GetNativeEngine();
95 CHECK_NULL_VOID(nativeEngine);
96 panda::Local<JsiValue> value = info[0].Get().GetLocalHandle();
97 JSValueWrapper valueWrapper = value;
98 ScopeRAII scopeNapi(reinterpret_cast<napi_env>(nativeEngine));
99 napi_value nativeValue = nativeEngine->ValueToNapiValue(valueWrapper);
100 auto wantParams = WantParamsWrap::CreateWantWrap(
101 reinterpret_cast<napi_env>(nativeEngine), nativeValue);
102 if (proxy_) {
103 AAFwk::WantParams reWantParams;
104 int32_t sendCode = proxy_->SendDataSync(wantParams, reWantParams);
105 if (sendCode != 0) {
106 std::string errMsg;
107 if (sendCode == ERROR_CODE_UIEXTENSION_NOT_REGISTER_SYNC_CALLBACK) {
108 errMsg = "No callback has been registered to process synchronous data transferring.";
109 } else if (sendCode == ERROR_CODE_UIEXTENSION_TRANSFER_DATA_FAILED) {
110 errMsg = "Transferring data failed.";
111 } else {
112 errMsg = "Unknown error.";
113 }
114 JSException::Throw(sendCode, errMsg.c_str());
115 return;
116 }
117 auto execCtx = info.GetExecutionContext();
118 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
119 auto reNativeWantParams = WantWrap::ConvertParamsToNativeValue(
120 reWantParams, reinterpret_cast<napi_env>(nativeEngine));
121 auto reWantParamsJSVal =
122 Framework::JsConverter::ConvertNapiValueToJsVal(reNativeWantParams);
123 info.SetReturnValue(reWantParamsJSVal);
124 }
125 }
126
FindCbList(napi_env env,napi_value cb,SecurityCallbackFuncPairList & callbackFuncPairList)127 SecurityCallbackFuncPairList::const_iterator JSSecurityUIExtensionProxy::FindCbList(
128 napi_env env, napi_value cb, SecurityCallbackFuncPairList& callbackFuncPairList)
129 {
130 return std::find_if(callbackFuncPairList.begin(), callbackFuncPairList.end(),
131 [env, cb](const auto& item) -> bool {
132 bool result = false;
133 napi_value refItem;
134 napi_get_reference_value(env, item.first, &refItem);
135 napi_strict_equals(env, refItem, cb, &result);
136 return result;
137 });
138 }
139
AddCallbackToList(napi_env env,napi_value cb,napi_handle_scope scope,RegisterType type,const std::function<void (const RefPtr<NG::SecurityUIExtensionProxy> &)> && onFunc)140 void JSSecurityUIExtensionProxy::AddCallbackToList(
141 napi_env env, napi_value cb, napi_handle_scope scope, RegisterType type,
142 const std::function<void(const RefPtr<NG::SecurityUIExtensionProxy>&)>&& onFunc)
143 {
144 if (type == RegisterType::SYNC) {
145 auto iter = FindCbList(env, cb, onSyncOnCallbackList_);
146 if (iter == onSyncOnCallbackList_.end()) {
147 napi_ref ref = nullptr;
148 napi_create_reference(env, cb, 1, &ref);
149 onSyncOnCallbackList_.emplace_back(ref, onFunc);
150 }
151 } else if (type == RegisterType::ASYNC) {
152 auto iter = FindCbList(env, cb, onAsyncOnCallbackList_);
153 if (iter == onAsyncOnCallbackList_.end()) {
154 napi_ref ref = nullptr;
155 napi_create_reference(env, cb, 1, &ref);
156 onAsyncOnCallbackList_.emplace_back(ref, onFunc);
157 }
158 }
159 napi_close_handle_scope(env, scope);
160 }
161
DeleteCallbackFromList(uint32_t argc,napi_env env,napi_value cb,RegisterType type)162 void JSSecurityUIExtensionProxy::DeleteCallbackFromList(
163 uint32_t 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 == ARGC_TWO) {
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::SecurityUIExtensionProxy>&)>> JSSecurityUIExtensionProxy::GetOnFuncList(
195 RegisterType type)
196 {
197 std::list<std::function<void(const RefPtr<NG::SecurityUIExtensionProxy>&)>> 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 JSSecurityUIExtensionProxy::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
NeedCheckComponentSize()223 bool NeedCheckComponentSize()
224 {
225 std::string type =
226 UIExtensionModel::GetInstance()->GetUiExtensionType(NG::SessionType::SECURITY_UI_EXTENSION_ABILITY);
227 if (type.empty()) {
228 return true;
229 }
230 const std::unordered_set<std::string> noNeedCheckExtensionType = { "sysPicker/photoPicker" };
231 return noNeedCheckExtensionType.find(type) == noNeedCheckExtensionType.end();
232 }
233
CreateInstanceAndSet(NG::UIExtensionConfig & config)234 void CreateInstanceAndSet(NG::UIExtensionConfig& config)
235 {
236 UIExtensionModel::GetInstance()->Create(config);
237 ViewAbstractModel::GetInstance()->SetMinWidth(SECURITY_UEC_MIN_WIDTH);
238 ViewAbstractModel::GetInstance()->SetMinHeight(SECURITY_UEC_MIN_HEIGHT);
239 if (!NeedCheckComponentSize()) {
240 LOGI("No need check size due to extension type is special");
241 return;
242 }
243 ViewAbstractModel::GetInstance()->SetWidth(SECURITY_UEC_MIN_WIDTH);
244 ViewAbstractModel::GetInstance()->SetHeight(SECURITY_UEC_MIN_HEIGHT);
245 }
246
CanTurnOn(const JSCallbackInfo & info)247 bool JSSecurityUIExtensionProxy::CanTurnOn(const JSCallbackInfo& info)
248 {
249 if (!info[0]->IsString() || !info[1]->IsFunction()) {
250 return false;
251 }
252 const RegisterType registerType = GetRegisterType(info[0]->ToString());
253 return registerType != RegisterType::UNKNOWN;
254 }
255
On(const JSCallbackInfo & info)256 void JSSecurityUIExtensionProxy::On(const JSCallbackInfo& info)
257 {
258 if (!CanTurnOn(info)) {
259 return;
260 }
261 const RegisterType registerType = GetRegisterType(info[0]->ToString());
262 WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(
263 NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
264 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[1]));
265 auto instanceId = ContainerScope::CurrentId();
266 auto onOnFunc = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
267 instanceId, node = frameNode] (const RefPtr<NG::SecurityUIExtensionProxy>& session) {
268 ContainerScope scope(instanceId);
269 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
270 auto pipelineContext = PipelineContext::GetCurrentContext();
271 CHECK_NULL_VOID(pipelineContext);
272 pipelineContext->UpdateCurrentActiveNode(node);
273 JSRef<JSObject> contextObj = JSClass<JSSecurityUIExtensionProxy>::NewInstance();
274 RefPtr<JSSecurityUIExtensionProxy> proxy =
275 Referenced::Claim(contextObj->Unwrap<JSSecurityUIExtensionProxy>());
276 CHECK_NULL_VOID(proxy);
277 proxy->SetInstanceId(instanceId);
278 proxy->SetProxy(session);
279 auto param = JSRef<JSVal>::Cast(contextObj);
280 func->ExecuteJS(1, ¶m);
281 };
282
283 ContainerScope scope(instanceId_);
284 auto engine = EngineHelper::GetCurrentEngine();
285 CHECK_NULL_VOID(engine);
286 NativeEngine* nativeEngine = engine->GetNativeEngine();
287 CHECK_NULL_VOID(nativeEngine);
288 auto env = reinterpret_cast<napi_env>(nativeEngine);
289 ScopeRAII scopeNapi(env);
290 panda::Local<JsiValue> value = info[1].Get().GetLocalHandle();
291 JSValueWrapper valueWrapper = value;
292 napi_value cb = nativeEngine->ValueToNapiValue(valueWrapper);
293 napi_handle_scope napiScope = nullptr;
294 napi_open_handle_scope(env, &napiScope);
295 CHECK_NULL_VOID(napiScope);
296 std::lock_guard<std::mutex> lock(callbackLisLock_);
297 AddCallbackToList(env, cb, napiScope, registerType, std::move(onOnFunc));
298 auto pattern = proxy_->GetPattern();
299 CHECK_NULL_VOID(pattern);
300 auto onFuncList = GetOnFuncList(registerType);
301 if (registerType == RegisterType::SYNC) {
302 pattern->SetSyncCallbacks(std::move(onFuncList));
303 } else if (registerType == RegisterType::ASYNC) {
304 pattern->SetAsyncCallbacks(std::move(onFuncList));
305 }
306 }
307
Off(const JSCallbackInfo & info)308 void JSSecurityUIExtensionProxy::Off(const JSCallbackInfo& info)
309 {
310 if (!info[0]->IsString()) {
311 return;
312 }
313 const RegisterType registerType = GetRegisterType(info[0]->ToString());
314 if (registerType == RegisterType::UNKNOWN) {
315 return;
316 }
317
318 ContainerScope scope(instanceId_);
319 auto engine = EngineHelper::GetCurrentEngine();
320 CHECK_NULL_VOID(engine);
321 NativeEngine* nativeEngine = engine->GetNativeEngine();
322 CHECK_NULL_VOID(nativeEngine);
323 auto env = reinterpret_cast<napi_env>(nativeEngine);
324 ScopeRAII scopeNapi(env);
325 napi_value cb = nullptr;
326 if (info[1]->IsFunction()) {
327 panda::Local<JsiValue> value = info[1].Get().GetLocalHandle();
328 JSValueWrapper valueWrapper = value;
329 cb = nativeEngine->ValueToNapiValue(valueWrapper);
330 }
331
332 std::lock_guard<std::mutex> lock(callbackLisLock_);
333 DeleteCallbackFromList(info.Length(), env, cb, registerType);
334 auto pattern = proxy_->GetPattern();
335 CHECK_NULL_VOID(pattern);
336 auto onFuncList = GetOnFuncList(registerType);
337 if (registerType == RegisterType::SYNC) {
338 pattern->SetSyncCallbacks(std::move(onFuncList));
339 } else if (registerType == RegisterType::ASYNC) {
340 pattern->SetAsyncCallbacks(std::move(onFuncList));
341 }
342 }
343
SetInstanceId(int32_t instanceId)344 void JSSecurityUIExtensionProxy::SetInstanceId(int32_t instanceId)
345 {
346 instanceId_ = instanceId;
347 }
348
SetProxy(const RefPtr<NG::SecurityUIExtensionProxy> & proxy)349 void JSSecurityUIExtensionProxy::SetProxy(
350 const RefPtr<NG::SecurityUIExtensionProxy>& proxy)
351 {
352 proxy_ = proxy;
353 }
354
JSBind(BindingTarget globalObj)355 void JSSecurityUIExtension::JSBind(BindingTarget globalObj)
356 {
357 JSClass<JSSecurityUIExtension>::Declare("SecurityUIExtensionComponent");
358 MethodOptions opt = MethodOptions::NONE;
359 JSClass<JSSecurityUIExtension>::StaticMethod("create", &JSSecurityUIExtension::Create, opt);
360 JSClass<JSSecurityUIExtension>::StaticMethod("onRemoteReady", &JSSecurityUIExtension::OnRemoteReady);
361 JSClass<JSSecurityUIExtension>::StaticMethod("onReceive", &JSSecurityUIExtension::OnReceive);
362 JSClass<JSSecurityUIExtension>::StaticMethod("onError", &JSSecurityUIExtension::OnError);
363 JSClass<JSSecurityUIExtension>::StaticMethod("onTerminated", &JSSecurityUIExtension::OnTerminated);
364 JSClass<JSSecurityUIExtension>::StaticMethod("width", &JSSecurityUIExtension::JsWidth);
365 JSClass<JSSecurityUIExtension>::StaticMethod("height", &JSSecurityUIExtension::JsHeight);
366 JSClass<JSSecurityUIExtension>::StaticMethod("backgroundColor", &JSViewAbstract::JsBackgroundColor);
367 JSClass<JSSecurityUIExtension>::Bind(globalObj);
368 }
369
GetSizeValue(const JSCallbackInfo & info)370 CalcDimension JSSecurityUIExtension::GetSizeValue(const JSCallbackInfo& info)
371 {
372 CalcDimension value;
373 if (!JSViewAbstract::ParseJsDimensionVp(info[0], value)) {
374 return -1.0;
375 }
376 return value;
377 }
378
JsWidth(const JSCallbackInfo & info)379 void JSSecurityUIExtension::JsWidth(const JSCallbackInfo& info)
380 {
381 CalcDimension value = GetSizeValue(info);
382 if (NeedCheckComponentSize() && LessNotEqual(value.Value(), 0.0)) {
383 return;
384 }
385 JSViewAbstract::JsWidth(info);
386 }
387
JsHeight(const JSCallbackInfo & info)388 void JSSecurityUIExtension::JsHeight(const JSCallbackInfo& info)
389 {
390 CalcDimension value = GetSizeValue(info);
391 if (NeedCheckComponentSize() && LessNotEqual(value.Value(), 0.0)) {
392 return;
393 }
394 JSViewAbstract::JsHeight(info);
395 }
396
Create(const JSCallbackInfo & info)397 void JSSecurityUIExtension::Create(const JSCallbackInfo& info)
398 {
399 if (!info[0]->IsObject()) {
400 return;
401 }
402
403 NG::UIExtensionConfig config;
404 config.sessionType = NG::SessionType::SECURITY_UI_EXTENSION_ABILITY;
405 auto wantObj = JSRef<JSObject>::Cast(info[0]);
406 RefPtr<OHOS::Ace::WantWrap> want = CreateWantWrapFromNapiValue(wantObj);
407 if (want == nullptr) {
408 TAG_LOGI(AceLogTag::ACE_SECURITYUIEXTENSION, "want is nullptr");
409 return;
410 }
411
412 config.wantWrap = want;
413 RefPtr<NG::FrameNode> placeholderNode = nullptr;
414 if (info.Length() > 1 && info[1]->IsObject()) {
415 auto obj = JSRef<JSObject>::Cast(info[1]);
416 JSRef<JSVal> transferringCallerValue = obj->GetProperty("isTransferringCaller");
417 if (transferringCallerValue->IsBoolean()) {
418 config.transferringCaller = transferringCallerValue->ToBoolean();
419 }
420 JSRef<JSVal> enableDensityDPI = obj->GetProperty("dpiFollowStrategy");
421 if (enableDensityDPI->IsNumber()) {
422 config.densityDpi = (enableDensityDPI->ToNumber<int32_t>())==0 ? true : false;
423 }
424 do {
425 JSRef<JSVal> componentContent = obj->GetProperty("placeholder");
426 if (!componentContent->IsObject()) {
427 break;
428 }
429 auto componentContentObj = JSRef<JSObject>::Cast(componentContent);
430 JSRef<JSVal> builderNode = componentContentObj->GetProperty("builderNode_");
431 if (!builderNode->IsObject()) {
432 break;
433 }
434 auto builderNodeObj = JSRef<JSObject>::Cast(builderNode);
435 JSRef<JSVal> nodePtr = builderNodeObj->GetProperty("nodePtr_");
436 if (nodePtr.IsEmpty()) {
437 break;
438 }
439 const auto* vm = nodePtr->GetEcmaVM();
440 auto* node = nodePtr->GetLocalHandle()->ToNativePointer(vm)->Value();
441 auto* frameNode = reinterpret_cast<NG::FrameNode*>(node);
442 if (!frameNode) {
443 break;
444 }
445 config.placeholderNode = AceType::Claim(frameNode);
446 } while (false);
447 }
448 CreateInstanceAndSet(config);
449 }
450
OnRemoteReady(const JSCallbackInfo & info)451 void JSSecurityUIExtension::OnRemoteReady(const JSCallbackInfo& info)
452 {
453 if (!info[0]->IsFunction()) {
454 return;
455 }
456 WeakPtr<NG::FrameNode> frameNode =
457 AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
458 auto jsFunc = AceType::MakeRefPtr<JsFunction>(
459 JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
460 auto instanceId = ContainerScope::CurrentId();
461 auto onRemoteReady = [execCtx = info.GetExecutionContext(),
462 func = std::move(jsFunc), instanceId, node = frameNode]
463 (const RefPtr<NG::SecurityUIExtensionProxy>& session) {
464 ContainerScope scope(instanceId);
465 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
466 auto pipelineContext = PipelineContext::GetCurrentContext();
467 CHECK_NULL_VOID(pipelineContext);
468 pipelineContext->UpdateCurrentActiveNode(node);
469 JSRef<JSObject> contextObj = JSClass<JSSecurityUIExtensionProxy>::NewInstance();
470 RefPtr<JSSecurityUIExtensionProxy> proxy =
471 Referenced::Claim(contextObj->Unwrap<JSSecurityUIExtensionProxy>());
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()->SetSecurityOnRemoteReady(std::move(onRemoteReady));
479 }
480
OnReceive(const JSCallbackInfo & info)481 void JSSecurityUIExtension::OnReceive(const JSCallbackInfo& info)
482 {
483 if (!info[0]->IsFunction()) {
484 return;
485 }
486 WeakPtr<NG::FrameNode> frameNode =
487 AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
488 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
489 auto instanceId = ContainerScope::CurrentId();
490 auto onReceive = [execCtx = info.GetExecutionContext(),
491 func = std::move(jsFunc), instanceId, node = frameNode]
492 (const AAFwk::WantParams& wantParams) {
493 ContainerScope scope(instanceId);
494 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
495 ACE_SCORING_EVENT("SecurityUIExtensionComponent.UIExtensionDataSession.onReceive");
496 auto pipelineContext = PipelineContext::GetCurrentContext();
497 CHECK_NULL_VOID(pipelineContext);
498 pipelineContext->UpdateCurrentActiveNode(node);
499 auto engine = EngineHelper::GetCurrentEngine();
500 CHECK_NULL_VOID(engine);
501 NativeEngine* nativeEngine = engine->GetNativeEngine();
502 CHECK_NULL_VOID(nativeEngine);
503 auto env = reinterpret_cast<napi_env>(nativeEngine);
504 auto nativeWantParams = WantWrap::ConvertParamsToNativeValue(wantParams, env);
505 auto wantParamsJSVal = JsConverter::ConvertNapiValueToJsVal(nativeWantParams);
506 func->ExecuteJS(1, &wantParamsJSVal);
507 };
508 UIExtensionModel::GetInstance()->SetOnReceive(
509 std::move(onReceive), NG::SessionType::SECURITY_UI_EXTENSION_ABILITY);
510 }
511
OnError(const JSCallbackInfo & info)512 void JSSecurityUIExtension::OnError(const JSCallbackInfo& info)
513 {
514 if (!info[0]->IsFunction()) {
515 return;
516 }
517 WeakPtr<NG::FrameNode> frameNode =
518 AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
519 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
520 auto instanceId = ContainerScope::CurrentId();
521 auto onError = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
522 instanceId, node = frameNode] (int32_t code, const std::string& name, const std::string& message) {
523 ContainerScope scope(instanceId);
524 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
525 ACE_SCORING_EVENT("SecurityUIExtensionComponent.onError");
526 auto pipelineContext = PipelineContext::GetCurrentContext();
527 CHECK_NULL_VOID(pipelineContext);
528 pipelineContext->UpdateCurrentActiveNode(node);
529 JSRef<JSObject> obj = JSRef<JSObject>::New();
530 obj->SetProperty<int32_t>("code", code);
531 obj->SetProperty<std::string>("name", name);
532 obj->SetProperty<std::string>("message", message);
533 auto returnValue = JSRef<JSVal>::Cast(obj);
534 func->ExecuteJS(1, &returnValue);
535 };
536 UIExtensionModel::GetInstance()->SetOnError(
537 std::move(onError), NG::SessionType::SECURITY_UI_EXTENSION_ABILITY);
538 }
539
OnTerminated(const JSCallbackInfo & info)540 void JSSecurityUIExtension::OnTerminated(const JSCallbackInfo& info)
541 {
542 if (!info[0]->IsFunction()) {
543 return;
544 }
545 WeakPtr<NG::FrameNode> frameNode =
546 AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
547 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
548 auto instanceId = ContainerScope::CurrentId();
549 auto onTerminated = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
550 instanceId, node = frameNode] (int32_t code, const RefPtr<WantWrap>& wantWrap) {
551 ContainerScope scope(instanceId);
552 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
553 ACE_SCORING_EVENT("SecurityUIExtensionComponent.onTerminated");
554 auto pipelineContext = PipelineContext::GetCurrentContext();
555 CHECK_NULL_VOID(pipelineContext);
556 pipelineContext->UpdateCurrentActiveNode(node);
557 auto engine = EngineHelper::GetCurrentEngine();
558 CHECK_NULL_VOID(engine);
559 NativeEngine* nativeEngine = engine->GetNativeEngine();
560 CHECK_NULL_VOID(nativeEngine);
561 JSRef<JSObject> obj = JSRef<JSObject>::New();
562 obj->SetProperty<int32_t>("code", code);
563 if (wantWrap) {
564 auto nativeWant = WantWrap::ConvertToNativeValue(
565 wantWrap->GetWant(), reinterpret_cast<napi_env>(nativeEngine));
566 auto wantJSVal = JsConverter::ConvertNapiValueToJsVal(nativeWant);
567 obj->SetPropertyObject("want", wantJSVal);
568 }
569 auto returnValue = JSRef<JSVal>::Cast(obj);
570 func->ExecuteJS(1, &returnValue);
571 };
572 UIExtensionModel::GetInstance()->SetOnTerminated(
573 std::move(onTerminated), NG::SessionType::SECURITY_UI_EXTENSION_ABILITY);
574 }
575
JSBind(BindingTarget globalObj)576 void JSPreviewUIExtension::JSBind(BindingTarget globalObj)
577 {
578 JSClass<JSPreviewUIExtension>::Declare("PreviewUIExtensionComponent");
579 MethodOptions opt = MethodOptions::NONE;
580 JSClass<JSPreviewUIExtension>::StaticMethod("create", &JSPreviewUIExtension::Create, opt);
581 JSClass<JSPreviewUIExtension>::StaticMethod("onError", &JSPreviewUIExtension::OnError);
582 JSClass<JSPreviewUIExtension>::StaticMethod("width", &JSPreviewUIExtension::JsWidth);
583 JSClass<JSPreviewUIExtension>::StaticMethod("height", &JSPreviewUIExtension::JsHeight);
584 JSClass<JSPreviewUIExtension>::Bind(globalObj);
585 }
586
GetSizeValue(const JSCallbackInfo & info)587 static CalcDimension GetSizeValue(const JSCallbackInfo& info)
588 {
589 CalcDimension value;
590 if (!JSViewAbstract::ParseJsDimensionVp(info[0], value)) {
591 return -1.0;
592 }
593 return value;
594 }
595
JsWidth(const JSCallbackInfo & info)596 void JSPreviewUIExtension::JsWidth(const JSCallbackInfo& info)
597 {
598 JSViewAbstract::JsWidth(info);
599 CalcDimension value = GetSizeValue(info);
600 if (LessNotEqual(value.Value(), 0.0)) {
601 return;
602 }
603 ViewAbstractModel::GetInstance()->SetWidth(value);
604 }
605
JsHeight(const JSCallbackInfo & info)606 void JSPreviewUIExtension::JsHeight(const JSCallbackInfo& info)
607 {
608 JSViewAbstract::JsHeight(info);
609 CalcDimension value = GetSizeValue(info);
610 if (LessNotEqual(value.Value(), 0.0)) {
611 return;
612 }
613 ViewAbstractModel::GetInstance()->SetHeight(value);
614 }
615
Create(const JSCallbackInfo & info)616 void JSPreviewUIExtension::Create(const JSCallbackInfo& info)
617 {
618 if (!info[0]->IsObject()) {
619 return;
620 }
621 NG::UIExtensionConfig config;
622 config.sessionType = NG::SessionType::UI_EXTENSION_ABILITY;
623 auto wantObj = JSRef<JSObject>::Cast(info[0]);
624 RefPtr<OHOS::Ace::WantWrap> want = CreateWantWrapFromNapiValue(wantObj);
625 if (want == nullptr) {
626 TAG_LOGI(AceLogTag::ACE_SECURITYUIEXTENSION, "want is nullptr");
627 return;
628 }
629 config.wantWrap = want;
630 RefPtr<NG::FrameNode> placeholderNode = nullptr;
631 if (info.Length() > 1 && info[1]->IsObject()) {
632 auto obj = JSRef<JSObject>::Cast(info[1]);
633 JSRef<JSVal> transferringCallerValue = obj->GetProperty("isTransferringCaller");
634 if (transferringCallerValue->IsBoolean()) {
635 config.transferringCaller = transferringCallerValue->ToBoolean();
636 }
637 JSRef<JSVal> enableDensityDPI = obj->GetProperty("dpiFollowStrategy");
638 if (enableDensityDPI->IsNumber()) {
639 config.densityDpi = (enableDensityDPI->ToNumber<int32_t>())==0 ? true : false;
640 }
641 do {
642 JSRef<JSVal> componentContent = obj->GetProperty("placeholder");
643 if (!componentContent->IsObject()) {
644 break;
645 }
646 auto componentContentObj = JSRef<JSObject>::Cast(componentContent);
647 JSRef<JSVal> builderNode = componentContentObj->GetProperty("builderNode_");
648 if (!builderNode->IsObject()) {
649 break;
650 }
651 auto builderNodeObj = JSRef<JSObject>::Cast(builderNode);
652 JSRef<JSVal> nodePtr = builderNodeObj->GetProperty("nodePtr_");
653 if (nodePtr.IsEmpty()) {
654 break;
655 }
656 const auto* vm = nodePtr->GetEcmaVM();
657 auto* node = nodePtr->GetLocalHandle()->ToNativePointer(vm)->Value();
658 auto* frameNode = reinterpret_cast<NG::FrameNode*>(node);
659 if (!frameNode) {
660 break;
661 }
662 config.placeholderNode = AceType::Claim(frameNode);
663 } while (false);
664 }
665 NG::PreviewUIExtensionAdapter::GetInstance()->Create(config);
666 }
667
OnError(const JSCallbackInfo & info)668 void JSPreviewUIExtension::OnError(const JSCallbackInfo& info)
669 {
670 if (!info[0]->IsFunction()) {
671 return;
672 }
673 auto frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
674 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
675 auto instanceId = ContainerScope::CurrentId();
676 auto onError = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
677 instanceId, node = AceType::WeakClaim(frameNode)]
678 (int32_t code, const std::string& name, const std::string& message) {
679 ContainerScope scope(instanceId);
680 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
681 ACE_SCORING_EVENT("PreviewUIExtensionComponent.onError");
682 auto pipelineContext = PipelineContext::GetCurrentContext();
683 CHECK_NULL_VOID(pipelineContext);
684 pipelineContext->UpdateCurrentActiveNode(node);
685 JSRef<JSObject> obj = JSRef<JSObject>::New();
686 obj->SetProperty<int32_t>("code", code);
687 obj->SetProperty<std::string>("name", name);
688 obj->SetProperty<std::string>("message", message);
689 auto returnValue = JSRef<JSVal>::Cast(obj);
690 func->ExecuteJS(1, &returnValue);
691 };
692 NG::PreviewUIExtensionAdapter::GetInstance()->SetOnError(AceType::Claim(frameNode), std::move(onError));
693 }
694 } // namespace OHOS::Ace::Framework
695