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 "core/components_ng/pattern/security_component/security_component_pattern.h"
17 #include "core/components_ng/pattern/button/button_pattern.h"
18 #ifdef SECURITY_COMPONENT_ENABLE
19 #include "core/components_ng/pattern/security_component/security_component_handler.h"
20 #endif
21 #include "core/components_ng/pattern/security_component/security_component_log.h"
22 #include "core/components/common/layout/constants.h"
23 #ifdef SECURITY_COMPONENT_ENABLE
24 #include "pointer_event.h"
25 #endif
26
27 namespace OHOS::Ace::NG {
28 namespace {
29 #ifdef SECURITY_COMPONENT_ENABLE
30 const int32_t DELAY_RELEASE_MILLSEC = 10;
31 static std::unordered_map<uint64_t, RefPtr<FrameNode>> g_scNodeMap;
32 static std::vector<uint64_t> g_omittedNodeIndex;
33 static uint64_t g_scIndex = 0;
34 static std::mutex g_scMutex;
35 const std::string SYSTEM_INTERNAL_ERROR_MESSAGE = "system internal error";
36 #endif
37 }
SecurityComponentPattern()38 SecurityComponentPattern::SecurityComponentPattern()
39 {
40 #ifdef SECURITY_COMPONENT_ENABLE
41 uiEventHandler_ = OHOS::AppExecFwk::EventHandler::Current();
42 #endif
43 }
44
~SecurityComponentPattern()45 SecurityComponentPattern::~SecurityComponentPattern()
46 {
47 #ifdef SECURITY_COMPONENT_ENABLE
48 UnregisterSecurityComponent();
49 #endif
50 }
51
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)52 bool SecurityComponentPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty,
53 const DirtySwapConfig& config)
54 {
55 CHECK_NULL_RETURN(dirty, false);
56 return !(config.skipMeasure || dirty->SkipMeasureContent());
57 }
58
SetNodeHitTestMode(RefPtr<FrameNode> & node,HitTestMode mode)59 void SecurityComponentPattern::SetNodeHitTestMode(RefPtr<FrameNode>& node, HitTestMode mode)
60 {
61 if (node == nullptr) {
62 return;
63 }
64 auto gestureHub = node->GetOrCreateGestureEventHub();
65 CHECK_NULL_VOID(gestureHub);
66 gestureHub->SetHitTestMode(mode);
67 }
68
OnLanguageConfigurationUpdate()69 void SecurityComponentPattern::OnLanguageConfigurationUpdate()
70 {
71 auto node = GetHost();
72 CHECK_NULL_VOID(node);
73 auto textNode = GetSecCompChildNode(node, V2::TEXT_ETS_TAG);
74 CHECK_NULL_VOID(textNode);
75 auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
76 CHECK_NULL_VOID(textLayoutProperty);
77 auto layoutProperty = AceType::DynamicCast<SecurityComponentLayoutProperty>(node->GetLayoutProperty());
78 if (layoutProperty && layoutProperty->GetTextStyle().has_value()) {
79 auto textStyle = layoutProperty->GetTextStyle().value();
80 if (textStyle != static_cast<int32_t>(SecurityComponentDescription::TEXT_NULL)) {
81 auto pipeline = textNode->GetContextRefPtr();
82 CHECK_NULL_VOID(pipeline);
83 auto theme = pipeline->GetTheme<SecurityComponentTheme>();
84 CHECK_NULL_VOID(theme);
85
86 std::string text;
87 if (node->GetTag() == V2::PASTE_BUTTON_ETS_TAG) {
88 text = theme->GetPasteDescriptions(textStyle);
89 } else if (node->GetTag() == V2::LOCATION_BUTTON_ETS_TAG) {
90 text = theme->GetLocationDescriptions(textStyle);
91 } else if (node->GetTag() == V2::SAVE_BUTTON_ETS_TAG) {
92 text = theme->GetSaveDescriptions(textStyle);
93 }
94
95 textLayoutProperty->UpdateContent(text);
96 }
97 }
98 }
99
OnKeyEvent(const KeyEvent & event)100 bool SecurityComponentPattern::OnKeyEvent(const KeyEvent& event)
101 {
102 if (event.action != KeyAction::DOWN) {
103 return false;
104 }
105 if ((event.code == KeyCode::KEY_SPACE) || (event.code == KeyCode::KEY_ENTER) ||
106 (event.code == KeyCode::KEY_NUMPAD_ENTER)) {
107 auto frameNode = GetHost();
108 CHECK_NULL_RETURN(frameNode, false);
109 int32_t res = 1;
110 #ifdef SECURITY_COMPONENT_ENABLE
111 res = ReportSecurityComponentClickEvent(event);
112 if (res == Security::SecurityComponent::SC_SERVICE_ERROR_WAIT_FOR_DIALOG_CLOSE) {
113 res = static_cast<int32_t>(SecurityComponentHandleResult::DROP_CLICK);
114 } else if (res != 0) {
115 SC_LOG_ERROR("ReportSecurityComponentClickEvent failed, errno %{public}d", res);
116 res = 1;
117 }
118 #endif
119 auto jsonNode = JsonUtil::Create(true);
120 CHECK_NULL_RETURN(jsonNode, false);
121 jsonNode->Put("handleRes", res);
122 std::shared_ptr<JsonValue> jsonShrd(jsonNode.release());
123 auto gestureEventHub = frameNode->GetOrCreateGestureEventHub();
124 gestureEventHub->ActClick(jsonShrd);
125 return true;
126 }
127 return false;
128 }
129
InitOnKeyEvent(RefPtr<FrameNode> & secCompNode)130 void SecurityComponentPattern::InitOnKeyEvent(RefPtr<FrameNode>& secCompNode)
131 {
132 if (isSetOnKeyEvent) {
133 return;
134 }
135 auto focusHub = secCompNode->GetOrCreateFocusHub();
136 auto onKeyEvent = [wp = WeakClaim(this)](const KeyEvent& event) -> bool {
137 auto pattern = wp.Upgrade();
138 if (!pattern) {
139 return false;
140 }
141 return pattern->OnKeyEvent(event);
142 };
143 focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
144 isSetOnKeyEvent = true;
145 }
146
IsParentMenu(RefPtr<FrameNode> & secCompNode)147 bool SecurityComponentPattern::IsParentMenu(RefPtr<FrameNode>& secCompNode)
148 {
149 auto parent = secCompNode->GetParent();
150 while (parent != nullptr) {
151 if (parent->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
152 return true;
153 }
154 parent = parent->GetParent();
155 }
156 return false;
157 }
158
HandleClickEventFromTouch(const TouchEventInfo & info)159 void SecurityComponentPattern::HandleClickEventFromTouch(const TouchEventInfo& info)
160 {
161 #ifdef SECURITY_COMPONENT_ENABLE
162 auto host = GetHost();
163 CHECK_NULL_VOID(host);
164
165 if (!IsParentMenu(host)) {
166 return;
167 }
168
169 auto pointerEvent = info.GetPointerEvent();
170 CHECK_NULL_VOID(pointerEvent);
171
172 int32_t pointerId = pointerEvent->GetPointerId();
173 MMI::PointerEvent::PointerItem item;
174 if (!pointerEvent->GetPointerItem(pointerId, item)) {
175 SC_LOG_WARN("Get pointer item failed");
176 return;
177 }
178
179 GestureEvent gestureInfo;
180 gestureInfo.SetDisplayX(item.GetDisplayX());
181 gestureInfo.SetDisplayY(item.GetDisplayY());
182 gestureInfo.SetPointerEvent(info.GetPointerEvent());
183 std::string message;
184 int res = ReportSecurityComponentClickEvent(gestureInfo, message);
185 if (res == Security::SecurityComponent::SC_SERVICE_ERROR_WAIT_FOR_DIALOG_CLOSE) {
186 return;
187 }
188 if (res != 0) {
189 SC_LOG_WARN("ReportSecurityComponentClickEvent failed, errno %{public}d", res);
190 res = 1;
191 }
192 auto jsonNode = JsonUtil::Create(true);
193 CHECK_NULL_VOID(jsonNode);
194 jsonNode->Put("handleRes", res);
195 std::shared_ptr<JsonValue> jsonShrd(jsonNode.release());
196 auto gestureEventHub = host->GetOrCreateGestureEventHub();
197 gestureEventHub->ActClick(jsonShrd);
198 #endif
199 }
200
201 // When security component is a child node of menu wrapper, the menu is immediately hidden
202 // after being touched, and then the security component will trigger a click event.
203 // However, it will be considered to have been triggered in a hidden state,
204 // Therefore, we should report click event on UP touch event.
OnTouch(const TouchEventInfo & info)205 void SecurityComponentPattern::OnTouch(const TouchEventInfo& info)
206 {
207 auto touchType = info.GetTouches().front().GetTouchType();
208 if (touchType == TouchType::DOWN) {
209 lastTouchOffset_ = std::make_unique<Offset>(info.GetTouches().front().GetLocalLocation());
210 } else if (touchType == TouchType::UP) {
211 auto touchUpOffset = info.GetTouches().front().GetLocalLocation();
212 if (lastTouchOffset_ &&
213 (touchUpOffset - *lastTouchOffset_).GetDistance() <= DEFAULT_SECURITY_COMPONENT_CLICK_DISTANCE) {
214 HandleClickEventFromTouch(info);
215 }
216 lastTouchOffset_.reset();
217 }
218 }
219
InitOnTouch(RefPtr<FrameNode> & secCompNode)220 void SecurityComponentPattern::InitOnTouch(RefPtr<FrameNode>& secCompNode)
221 {
222 if (onTouchListener_ != nullptr) {
223 return;
224 }
225 auto gestureHub = secCompNode->GetOrCreateGestureEventHub();
226 CHECK_NULL_VOID(gestureHub);
227
228 auto touchCallback = [weak = WeakClaim(this)](const TouchEventInfo& info) {
229 auto pattern = weak.Upgrade();
230 CHECK_NULL_VOID(pattern);
231 pattern->OnTouch(info);
232 };
233 onTouchListener_ = MakeRefPtr<TouchEventImpl>(std::move(touchCallback));
234 gestureHub->AddTouchEvent(onTouchListener_);
235 }
236
InitOnClick(RefPtr<FrameNode> & secCompNode,RefPtr<FrameNode> & icon,RefPtr<FrameNode> & text,RefPtr<FrameNode> & button)237 void SecurityComponentPattern::InitOnClick(RefPtr<FrameNode>& secCompNode, RefPtr<FrameNode>& icon,
238 RefPtr<FrameNode>& text, RefPtr<FrameNode>& button)
239 {
240 if (clickListener_ != nullptr) {
241 return;
242 }
243 auto secCompGesture = secCompNode->GetOrCreateGestureEventHub();
244 CHECK_NULL_VOID(secCompGesture);
245 auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
246 #ifdef SECURITY_COMPONENT_ENABLE
247 auto buttonPattern = weak.Upgrade();
248 CHECK_NULL_VOID(buttonPattern);
249 auto frameNode = buttonPattern->GetHost();
250 CHECK_NULL_VOID(frameNode);
251 if (info.GetSecCompHandleEvent()) {
252 return;
253 }
254 auto jsonNode = JsonUtil::Create(true);
255 CHECK_NULL_VOID(jsonNode);
256 std::shared_ptr<JsonValue> jsonShrd(jsonNode.release());
257 int32_t res;
258 int32_t code = SecurityComponentErrorCode::SUCCESS;
259 std::string message;
260 // if info.GetPointerEvent() is null, device may in screen read mode
261 // otherwise, this event should be dropped in menu
262 if (buttonPattern->IsParentMenu(frameNode) && info.GetPointerEvent() != nullptr) {
263 res = static_cast<int32_t>(SecurityComponentHandleResult::DROP_CLICK);
264 } else {
265 res = buttonPattern->ReportSecurityComponentClickEvent(info, message);
266 code = res;
267 if (res == Security::SecurityComponent::SC_SERVICE_ERROR_WAIT_FOR_DIALOG_CLOSE) {
268 res = static_cast<int32_t>(SecurityComponentHandleResult::DROP_CLICK);
269 } else if (res != 0) {
270 SC_LOG_WARN("ReportSecurityComponentClickEvent failed, errno %{public}d", res);
271 res = static_cast<int32_t>(SecurityComponentHandleResult::CLICK_GRANT_FAILED);
272 }
273 }
274 buttonPattern->HandleReportSecCompClickEventResult(code, message);
275 jsonShrd->Put("handleRes", res);
276 jsonShrd->Put("code", code);
277 jsonShrd->Put("message", message.c_str());
278 info.SetSecCompHandleEvent(jsonShrd);
279 #endif
280 };
281
282 clickListener_ = MakeRefPtr<ClickEvent>(std::move(clickCallback));
283 secCompGesture->AddClickEvent(clickListener_);
284 SetNodeHitTestMode(icon, HitTestMode::HTMTRANSPARENT);
285 SetNodeHitTestMode(text, HitTestMode::HTMTRANSPARENT);
286 }
287
ToJsonValueIconNode(std::unique_ptr<JsonValue> & json,const RefPtr<FrameNode> & iconNode,const InspectorFilter & filter) const288 void SecurityComponentPattern::ToJsonValueIconNode(std::unique_ptr<JsonValue>& json, const RefPtr<FrameNode>& iconNode,
289 const InspectorFilter& filter) const
290 {
291 auto node = GetHost();
292 CHECK_NULL_VOID(node);
293 auto* pipeline = node->GetContextWithCheck();
294 CHECK_NULL_VOID(pipeline);
295 auto theme = pipeline->GetTheme<SecurityComponentTheme>();
296 CHECK_NULL_VOID(theme);
297 auto iconProp = iconNode->GetLayoutProperty<ImageLayoutProperty>();
298 CHECK_NULL_VOID(iconProp);
299 CHECK_NULL_VOID(iconProp->GetCalcLayoutConstraint());
300 // GetDimension would ret a empty dimension when width is empty
301 auto width = iconProp->GetCalcLayoutConstraint()->selfIdealSize->Width();
302 if (width.has_value()) {
303 json->PutExtAttr("iconSize", width->GetDimension().ToString().c_str(), filter);
304 } else {
305 json->PutExtAttr("iconSize", theme->GetIconSize().ToString().c_str(), filter);
306 }
307 json->PutExtAttr("iconColor", iconProp->GetImageSourceInfo()->GetFillColor().
308 value_or(theme->GetIconColor()).ColorToString().c_str(), filter);
309 }
310
ToJsonValueSymbolIconNode(std::unique_ptr<JsonValue> & json,const RefPtr<FrameNode> & symbolIconNode,const InspectorFilter & filter) const311 void SecurityComponentPattern::ToJsonValueSymbolIconNode(std::unique_ptr<JsonValue>& json,
312 const RefPtr<FrameNode>& symbolIconNode, const InspectorFilter& filter) const
313 {
314 CHECK_NULL_VOID(symbolIconNode);
315 auto iconProp = symbolIconNode->GetLayoutProperty<TextLayoutProperty>();
316 CHECK_NULL_VOID(iconProp);
317 json->PutExtAttr("iconSize",
318 iconProp->GetFontSize().value_or(Dimension(0, DimensionUnit::VP)).ToString().c_str(), filter);
319 json->PutExtAttr("iconColor",
320 V2::ConvertSymbolColorToString(iconProp->GetSymbolColorListValue({})).c_str(), filter);
321 }
322
ToJsonValueTextNode(std::unique_ptr<JsonValue> & json,const RefPtr<FrameNode> & textNode,const InspectorFilter & filter) const323 void SecurityComponentPattern::ToJsonValueTextNode(std::unique_ptr<JsonValue>& json, const RefPtr<FrameNode>& textNode,
324 const InspectorFilter& filter) const
325 {
326 auto node = GetHost();
327 CHECK_NULL_VOID(node);
328 auto* pipeline = node->GetContextWithCheck();
329 CHECK_NULL_VOID(pipeline);
330 auto theme = pipeline->GetTheme<SecurityComponentTheme>();
331 CHECK_NULL_VOID(theme);
332 auto textProp = textNode->GetLayoutProperty<TextLayoutProperty>();
333 CHECK_NULL_VOID(textProp);
334 json->PutExtAttr("fontSize", textProp->GetFontSize().value_or(theme->GetFontSize()).ToString().c_str(), filter);
335 json->PutExtAttr("fontWeight", V2::ConvertWrapFontWeightToStirng(
336 textProp->GetFontWeight().value_or(FontWeight::NORMAL)).c_str(), filter);
337 json->PutExtAttr("fontFamily", "HarmonyOS Sans", filter);
338 json->PutExtAttr("fontStyle",
339 static_cast<int64_t>(textProp->GetItalicFontStyle().value_or(Ace::FontStyle::NORMAL)), filter);
340 json->PutExtAttr("fontColor",
341 textProp->GetTextColor().value_or(theme->GetFontColor()).ColorToString().c_str(), filter);
342 }
343
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const344 void SecurityComponentPattern::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
345 {
346 /* no fixed attr below, just return */
347 if (filter.IsFastFilter()) {
348 ToJsonValueRect(json, filter);
349 return;
350 }
351 auto node = GetHost();
352 CHECK_NULL_VOID(node);
353 auto* pipeline = node->GetContextWithCheck();
354 CHECK_NULL_VOID(pipeline);
355 auto theme = pipeline->GetTheme<SecurityComponentTheme>();
356 CHECK_NULL_VOID(theme);
357
358 auto layoutProperty = AceType::DynamicCast<SecurityComponentLayoutProperty>(node->GetLayoutProperty());
359 CHECK_NULL_VOID(layoutProperty);
360 json->PutExtAttr("text", layoutProperty->GetSecurityComponentDescription().value_or(0), filter);
361 json->PutExtAttr("icon", layoutProperty->GetIconStyle().value_or(0), filter);
362 json->PutExtAttr("buttonType", layoutProperty->GetBackgroundType().value_or(0), filter);
363 json->PutExtAttr("layoutDirection", static_cast<int64_t>(
364 layoutProperty->GetTextIconLayoutDirection().value_or(SecurityComponentLayoutDirection::VERTICAL)), filter);
365 json->PutExtAttr("type", node->GetTag().c_str(), filter);
366
367 RefPtr<FrameNode> iconNode = GetSecCompChildNode(node, V2::IMAGE_ETS_TAG);
368 if (iconNode != nullptr) {
369 ToJsonValueIconNode(json, iconNode, filter);
370 }
371 RefPtr<FrameNode> symbolIconNode = GetSecCompChildNode(node, V2::SYMBOL_ETS_TAG);
372 if (symbolIconNode != nullptr) {
373 ToJsonValueSymbolIconNode(json, symbolIconNode, filter);
374 }
375 RefPtr<FrameNode> textNode = GetSecCompChildNode(node, V2::TEXT_ETS_TAG);
376 if (textNode != nullptr) {
377 ToJsonValueTextNode(json, textNode, filter);
378 }
379 auto paddingJson = JsonUtil::Create(true);
380 CHECK_NULL_VOID(paddingJson);
381 paddingJson->Put("top",
382 layoutProperty->GetBackgroundTopPadding().value_or(theme->GetBackgroundTopPadding()).ToString().c_str());
383 paddingJson->Put("bottom",
384 layoutProperty->GetBackgroundBottomPadding().value_or(theme->GetBackgroundBottomPadding()).ToString().c_str());
385 paddingJson->Put("left",
386 layoutProperty->GetBackgroundLeftPadding().value_or(theme->GetBackgroundLeftPadding()).ToString().c_str());
387 paddingJson->Put("right",
388 layoutProperty->GetBackgroundRightPadding().value_or(theme->GetBackgroundRightPadding()).ToString().c_str());
389 json->PutExtAttr("padding", paddingJson, filter);
390 json->PutExtAttr("textIconSpace",
391 layoutProperty->GetTextIconSpace().value_or(theme->GetTextIconSpace()).ToString().c_str(), filter);
392 ToJsonValueRect(json, filter);
393 }
394
ToJsonValueRect(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const395 void SecurityComponentPattern::ToJsonValueRect(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
396 {
397 /* no fixed attr below, just return */
398 if (filter.IsFastFilter()) {
399 return;
400 }
401 auto node = GetHost();
402 CHECK_NULL_VOID(node);
403 auto* pipeline = node->GetContextWithCheck();
404 CHECK_NULL_VOID(pipeline);
405 auto theme = pipeline->GetTheme<SecurityComponentTheme>();
406 CHECK_NULL_VOID(theme);
407
408 RefPtr<FrameNode> buttonNode = GetSecCompChildNode(node, V2::BUTTON_ETS_TAG);
409 if (buttonNode != nullptr) {
410 const auto& renderContext = buttonNode->GetRenderContext();
411 CHECK_NULL_VOID(renderContext);
412 if (renderContext->HasBackgroundColor()) {
413 json->PutExtAttr("backgroundColor",
414 renderContext->GetBackgroundColor().value().ColorToString().c_str(), filter);
415 } else {
416 json->PutExtAttr("backgroundColor", theme->GetBackgroundColor().ColorToString().c_str(), filter);
417 }
418 if (renderContext->HasBorderColor()) {
419 json->PutExtAttr("borderColor",
420 renderContext->GetBorderColor()->leftColor.value_or(Color::BLACK).ColorToString().c_str(), filter);
421 } else {
422 json->PutExtAttr("borderColor", theme->GetBorderColor().ColorToString().c_str(), filter);
423 }
424 if (renderContext->HasBorderStyle()) {
425 json->PutExtAttr("borderStyle",
426 static_cast<int>(renderContext->GetBorderStyle()->styleLeft.value_or(BorderStyle::NONE)), filter);
427 } else {
428 json->PutExtAttr("borderStyle", static_cast<int>(BorderStyle::NONE), filter);
429 }
430 auto bgProp = buttonNode->GetLayoutProperty<ButtonLayoutProperty>();
431 CHECK_NULL_VOID(bgProp);
432 const auto& borderWidth = bgProp->GetBorderWidthProperty();
433 if (borderWidth != nullptr) {
434 json->PutExtAttr("borderWidth",
435 borderWidth->leftDimen.value_or(theme->GetBorderWidth()).ToString().c_str(), filter);
436 }
437 auto borderRadius = bgProp->GetBorderRadius();
438 if (borderRadius.has_value()) {
439 json->PutExtAttr("borderRadius", borderRadius->radiusTopLeft.value_or(theme->GetBorderRadius()).
440 ToString().c_str(), filter);
441 } else {
442 json->PutExtAttr("borderRadius", theme->GetBorderRadius().ToString().c_str(), filter);
443 }
444 }
445 }
446
GetFocusPattern() const447 FocusPattern SecurityComponentPattern::GetFocusPattern() const
448 {
449 auto frameNode = GetHost();
450 RefPtr<FrameNode> buttonNode = GetSecCompChildNode(frameNode, V2::BUTTON_ETS_TAG);
451 if (buttonNode != nullptr) {
452 auto buttonPattern = buttonNode->GetPattern<ButtonPattern>();
453 return buttonPattern->GetFocusPattern();
454 }
455
456 return { FocusType::NODE, true, FocusStyleType::OUTER_BORDER };
457 }
458
UpdateIconProperty(RefPtr<FrameNode> & scNode,RefPtr<FrameNode> & iconNode)459 void SecurityComponentPattern::UpdateIconProperty(RefPtr<FrameNode>& scNode, RefPtr<FrameNode>& iconNode)
460 {
461 auto iconLayoutProp = iconNode->GetLayoutProperty<ImageLayoutProperty>();
462 auto scLayoutProp = scNode->GetLayoutProperty<SecurityComponentLayoutProperty>();
463 CHECK_NULL_VOID(scLayoutProp);
464 if (scLayoutProp->GetIconSize().has_value()) {
465 auto iconSize = scLayoutProp->GetIconSize().value();
466 iconLayoutProp->UpdateUserDefinedIdealSize(CalcSize(NG::CalcLength(iconSize), NG::CalcLength(iconSize)));
467 }
468
469 auto scPaintProp = scNode->GetPaintProperty<SecurityComponentPaintProperty>();
470 CHECK_NULL_VOID(scPaintProp);
471 if (scPaintProp->GetIconColor().has_value() && iconLayoutProp->GetImageSourceInfo().has_value()) {
472 auto iconSrcInfo = iconLayoutProp->GetImageSourceInfo().value();
473 iconSrcInfo.SetFillColor(scPaintProp->GetIconColor().value());
474 iconLayoutProp->UpdateImageSourceInfo(iconSrcInfo);
475 }
476 }
477
UpdateTextProperty(RefPtr<FrameNode> & scNode,RefPtr<FrameNode> & textNode)478 void SecurityComponentPattern::UpdateTextProperty(RefPtr<FrameNode>& scNode, RefPtr<FrameNode>& textNode)
479 {
480 auto scLayoutProp = scNode->GetLayoutProperty<SecurityComponentLayoutProperty>();
481 auto textLayoutProp = textNode->GetLayoutProperty<TextLayoutProperty>();
482 if (scLayoutProp->GetFontSize().has_value()) {
483 textLayoutProp->UpdateFontSize(scLayoutProp->GetFontSize().value());
484 }
485 if (scLayoutProp->GetFontStyle().has_value()) {
486 textLayoutProp->UpdateItalicFontStyle(scLayoutProp->GetFontStyle().value());
487 }
488 if (scLayoutProp->GetFontWeight().has_value()) {
489 textLayoutProp->UpdateFontWeight(scLayoutProp->GetFontWeight().value());
490 }
491 if (scLayoutProp->GetFontFamily().has_value()) {
492 textLayoutProp->UpdateFontFamily(scLayoutProp->GetFontFamily().value());
493 }
494 auto scPaintProp = scNode->GetPaintProperty<SecurityComponentPaintProperty>();
495 if (scPaintProp->GetFontColor().has_value()) {
496 textLayoutProp->UpdateTextColor(scPaintProp->GetFontColor().value());
497 }
498 if (scLayoutProp->GetMaxFontScale().has_value()) {
499 textLayoutProp->UpdateMaxFontScale(scLayoutProp->GetMaxFontScale().value());
500 }
501 if (scLayoutProp->GetMinFontScale().has_value()) {
502 textLayoutProp->UpdateMinFontScale(scLayoutProp->GetMinFontScale().value());
503 }
504 if (scLayoutProp->GetMaxLines().has_value()) {
505 textLayoutProp->UpdateMaxLines(scLayoutProp->GetMaxLines().value());
506 }
507 if (scLayoutProp->GetAdaptMaxFontSize().has_value()) {
508 textLayoutProp->UpdateAdaptMaxFontSize(scLayoutProp->GetAdaptMaxFontSize().value());
509 }
510 if (scLayoutProp->GetAdaptMinFontSize().has_value()) {
511 textLayoutProp->UpdateAdaptMinFontSize(scLayoutProp->GetAdaptMinFontSize().value());
512 }
513 if (scLayoutProp->GetHeightAdaptivePolicy().has_value()) {
514 textLayoutProp->UpdateHeightAdaptivePolicy(scLayoutProp->GetHeightAdaptivePolicy().value());
515 }
516 }
517
HandleEnabled()518 void SecurityComponentPattern::HandleEnabled()
519 {
520 auto host = GetHost();
521 CHECK_NULL_VOID(host);
522 auto eventHub = host->GetEventHub<EventHub>();
523 CHECK_NULL_VOID(eventHub);
524 auto enabled = eventHub->IsEnabled();
525 auto renderContext = host->GetRenderContext();
526 CHECK_NULL_VOID(renderContext);
527 auto* pipeline = host->GetContextWithCheck();
528 CHECK_NULL_VOID(pipeline);
529 auto theme = pipeline->GetTheme<SecurityComponentTheme>();
530 CHECK_NULL_VOID(theme);
531 auto alpha = theme->GetBgDisabledAlpha();
532 auto originalOpacity = renderContext->GetOpacityValue(1.0);
533 renderContext->OnOpacityUpdate(enabled ? originalOpacity : alpha * originalOpacity);
534 }
535
UpdateButtonProperty(RefPtr<FrameNode> & scNode,RefPtr<FrameNode> & buttonNode)536 void SecurityComponentPattern::UpdateButtonProperty(RefPtr<FrameNode>& scNode, RefPtr<FrameNode>& buttonNode)
537 {
538 auto scLayoutProp = scNode->GetLayoutProperty<SecurityComponentLayoutProperty>();
539 auto scPaintProp = scNode->GetPaintProperty<SecurityComponentPaintProperty>();
540 auto buttonLayoutProp = buttonNode->GetLayoutProperty<ButtonLayoutProperty>();
541 const auto& buttonRender = buttonNode->GetRenderContext();
542 CHECK_NULL_VOID(buttonRender);
543 auto buttonEventHub = buttonNode->GetEventHub<ButtonEventHub>();
544 CHECK_NULL_VOID(buttonEventHub);
545
546 if (scLayoutProp->GetBackgroundBorderWidth().has_value()) {
547 BorderWidthProperty widthProp;
548 widthProp.SetBorderWidth(scLayoutProp->GetBackgroundBorderWidth().value());
549 buttonLayoutProp->UpdateBorderWidth(widthProp);
550 }
551
552 if (scPaintProp->GetBackgroundBorderStyle().has_value()) {
553 BorderStyleProperty style;
554 style.SetBorderStyle(scPaintProp->GetBackgroundBorderStyle().value());
555 buttonRender->UpdateBorderStyle(style);
556 }
557 if (scLayoutProp->GetBackgroundBorderRadius().has_value()) {
558 buttonLayoutProp->UpdateBorderRadius(
559 BorderRadiusProperty(scLayoutProp->GetBackgroundBorderRadius().value()));
560 }
561 if (scPaintProp->GetBackgroundColor().has_value()) {
562 buttonRender->UpdateBackgroundColor(scPaintProp->GetBackgroundColor().value());
563 }
564 if (scPaintProp->GetBackgroundBorderColor().has_value()) {
565 BorderColorProperty borderColor;
566 borderColor.SetColor(scPaintProp->GetBackgroundBorderColor().value());
567 buttonRender->UpdateBorderColor(borderColor);
568 }
569 if (scLayoutProp->GetStateEffect().has_value()) {
570 buttonEventHub->SetStateEffect(scLayoutProp->GetStateEffect().value());
571 }
572 if (scLayoutProp->GetHoverEffect().has_value()) {
573 auto inputHub = buttonEventHub->GetOrCreateInputEventHub();
574 CHECK_NULL_VOID(inputHub);
575 inputHub->SetHoverEffect(scLayoutProp->GetHoverEffect().value());
576 }
577 HandleEnabled();
578 }
579
OnModifyDone()580 void SecurityComponentPattern::OnModifyDone()
581 {
582 auto frameNode = GetHost();
583 CHECK_NULL_VOID(frameNode);
584
585 RefPtr<FrameNode> iconNode = GetSecCompChildNode(frameNode, V2::IMAGE_ETS_TAG);
586 if (iconNode != nullptr) {
587 UpdateIconProperty(frameNode, iconNode);
588 iconNode->MarkModifyDone();
589 }
590
591 RefPtr<FrameNode> textNode = GetSecCompChildNode(frameNode, V2::TEXT_ETS_TAG);
592 if (textNode != nullptr) {
593 UpdateTextProperty(frameNode, textNode);
594 textNode->MarkModifyDone();
595 }
596
597 RefPtr<FrameNode> buttonNode = GetSecCompChildNode(frameNode, V2::BUTTON_ETS_TAG);
598 if (buttonNode != nullptr) {
599 UpdateButtonProperty(frameNode, buttonNode);
600 buttonNode->MarkModifyDone();
601 }
602
603 InitOnClick(frameNode, iconNode, textNode, buttonNode);
604 InitOnKeyEvent(frameNode);
605 InitAppearCallback(frameNode);
606 InitOnTouch(frameNode);
607 }
608
IsFontColorSet()609 bool SecurityComponentPattern::IsFontColorSet()
610 {
611 auto frameNode = GetHost();
612 CHECK_NULL_RETURN(frameNode, false);
613 auto prop = frameNode->GetLayoutProperty<SecurityComponentLayoutProperty>();
614 if (prop && prop->GetIsFontColorSet().has_value()) {
615 return prop->GetIsFontColorSet().value();
616 }
617 return false;
618 }
619
OnColorConfigurationUpdate()620 void SecurityComponentPattern::OnColorConfigurationUpdate()
621 {
622 auto node = GetHost();
623 CHECK_NULL_VOID(node);
624 node->SetNeedCallChildrenUpdate(IsFontColorSet());
625 }
626
InitAppearCallback(RefPtr<FrameNode> & frameNode)627 void SecurityComponentPattern::InitAppearCallback(RefPtr<FrameNode>& frameNode)
628 {
629 if (isAppearCallback_) {
630 return;
631 }
632 auto eventHub = frameNode->GetEventHub<EventHub>();
633 CHECK_NULL_VOID(eventHub);
634
635 auto context = frameNode->GetContextRefPtr();
636 CHECK_NULL_VOID(context);
637 auto instanceId = context->GetInstanceId();
638 auto onAppear = [weak = WeakClaim(this), instanceId]() {
639 ContainerScope scope(instanceId);
640 #ifdef SECURITY_COMPONENT_ENABLE
641 auto securityComponentPattern = weak.Upgrade();
642 CHECK_NULL_VOID(securityComponentPattern);
643 securityComponentPattern->isAppear_ = true;
644 securityComponentPattern->RegisterSecurityComponent();
645 #endif
646 };
647
648 auto onDisAppear = [weak = WeakClaim(this)]() {
649 #ifdef SECURITY_COMPONENT_ENABLE
650 auto securityComponentPattern = weak.Upgrade();
651 CHECK_NULL_VOID(securityComponentPattern);
652 securityComponentPattern->isAppear_ = false;
653 securityComponentPattern->UnregisterSecurityComponent();
654 #endif
655 };
656 eventHub->SetOnAppear(std::move(onAppear));
657 eventHub->SetOnDisappear(std::move(onDisAppear));
658 isAppearCallback_ = true;
659 }
660
OnWindowHide()661 void SecurityComponentPattern::OnWindowHide()
662 {
663 #ifdef SECURITY_COMPONENT_ENABLE
664 UnregisterSecurityComponent();
665 #endif
666 }
667
OnWindowShow()668 void SecurityComponentPattern::OnWindowShow()
669 {
670 #ifdef SECURITY_COMPONENT_ENABLE
671 if (!isAppear_) {
672 return;
673 }
674 RegisterSecurityComponent();
675 #endif
676 }
677
678 #ifdef SECURITY_COMPONENT_ENABLE
RegisterSecurityComponentRetry()679 void SecurityComponentPattern::RegisterSecurityComponentRetry()
680 {
681 auto frameNode = GetHost();
682 CHECK_NULL_VOID(frameNode);
683 // service is shutdowning, try to load it.
684 int32_t retryCount = MAX_RETRY_TIMES;
685 while (retryCount > 0) {
686 int32_t res = SecurityComponentHandler::RegisterSecurityComponent(frameNode, scId_);
687 if (res == Security::SecurityComponent::SCErrCode::SC_OK) {
688 regStatus_ = SecurityComponentRegisterStatus::REGISTERED;
689 return;
690 } else if (res != Security::SecurityComponent::SCErrCode::SC_SERVICE_ERROR_SERVICE_NOT_EXIST) {
691 SC_LOG_WARN("Register security component failed, err %{public}d.", res);
692 regStatus_ = SecurityComponentRegisterStatus::UNREGISTERED;
693 return;
694 }
695
696 retryCount--;
697 std::this_thread::sleep_for(std::chrono::milliseconds(REGISTER_RETRY_INTERVAL));
698 }
699 regStatus_ = SecurityComponentRegisterStatus::UNREGISTERED;
700 SC_LOG_WARN("Register security component failed, retry %{public}d", MAX_RETRY_TIMES);
701 }
702
RegisterSecurityComponent()703 void SecurityComponentPattern::RegisterSecurityComponent()
704 {
705 if (regStatus_ == SecurityComponentRegisterStatus::REGISTERED ||
706 regStatus_ == SecurityComponentRegisterStatus::REGISTERING) {
707 return;
708 }
709
710 if (SecurityComponentHandler::IsSecurityComponentServiceExist()) {
711 RegisterSecurityComponentRetry();
712 return;
713 }
714 regStatus_ = SecurityComponentRegisterStatus::REGISTERING;
715 auto taskExecutor = Container::CurrentTaskExecutor();
716 CHECK_NULL_VOID(taskExecutor);
717 auto frameNode = GetHost();
718 CHECK_NULL_VOID(frameNode);
719 auto pipeline = frameNode->GetContextRefPtr();
720 CHECK_NULL_VOID(pipeline);
721 taskExecutor->PostTask(
722 [weak = WeakClaim(this), weakContext = WeakPtr(pipeline)] {
723 if (!SecurityComponentHandler::LoadSecurityComponentService()) {
724 SC_LOG_WARN("load security component service failed.");
725 return;
726 }
727 auto context = weakContext.Upgrade();
728 CHECK_NULL_VOID(context);
729 auto taskExecutor = context->GetTaskExecutor();
730 CHECK_NULL_VOID(taskExecutor);
731 taskExecutor->PostTask(
732 [weak, instanceID = context->GetInstanceId()] {
733 ContainerScope scope(instanceID);
734 auto pattern = weak.Upgrade();
735 CHECK_NULL_VOID(pattern);
736 if (pattern->regStatus_ != SecurityComponentRegisterStatus::REGISTERING) {
737 return;
738 }
739
740 pattern->RegisterSecurityComponentRetry();
741 },
742 TaskExecutor::TaskType::UI, "ArkUISecurityComponentRegisterRetry");
743 },
744 TaskExecutor::TaskType::BACKGROUND, "ArkUISecurityComponentRegister");
745 }
746
UnregisterSecurityComponent()747 void SecurityComponentPattern::UnregisterSecurityComponent()
748 {
749 if (regStatus_ == SecurityComponentRegisterStatus::REGISTERED) {
750 SecurityComponentHandler::UnregisterSecurityComponent(scId_);
751 } else {
752 SC_LOG_INFO("security component has not registered, regStatus %{public}d.", regStatus_);
753 }
754 regStatus_ = SecurityComponentRegisterStatus::UNREGISTERED;
755 scId_ = -1;
756 }
757
DoTriggerOnclick(int32_t result)758 void SecurityComponentPattern::DoTriggerOnclick(int32_t result)
759 {
760 auto host = GetHost();
761 CHECK_NULL_VOID(host);
762 auto jsonNode = JsonUtil::Create(true);
763 CHECK_NULL_VOID(jsonNode);
764 if (result != 0) {
765 jsonNode->Put("handleRes", static_cast<int32_t>(SecurityComponentHandleResult::CLICK_GRANT_FAILED));
766 } else {
767 jsonNode->Put("handleRes", static_cast<int32_t>(SecurityComponentHandleResult::CLICK_SUCCESS));
768 }
769
770 std::shared_ptr<JsonValue> jsonShrd(jsonNode.release());
771 auto gestureEventHub = host->GetOrCreateGestureEventHub();
772 CHECK_NULL_VOID(gestureEventHub);
773 gestureEventHub->ActClick(jsonShrd);
774 }
775
DelayReleaseNode(uint64_t index)776 void SecurityComponentPattern::DelayReleaseNode(uint64_t index)
777 {
778 if (uiEventHandler_ == nullptr) {
779 SC_LOG_WARN("UIEventHandler invalid");
780 return;
781 }
782 bool res = uiEventHandler_->PostTask([index] {
783 std::lock_guard<std::mutex> lock(g_scMutex);
784 g_scNodeMap.erase(index);
785 if (g_omittedNodeIndex.size() != 0) {
786 for (auto item : g_omittedNodeIndex) {
787 g_scNodeMap.erase(item);
788 }
789 g_omittedNodeIndex.clear();
790 }
791 SC_LOG_INFO("Security component frameNode cached size: %{public}zu, index: %{public}" PRId64,
792 g_scNodeMap.size(), index);
793 return;
794 },
795 DELAY_RELEASE_MILLSEC);
796 if (!res) {
797 SC_LOG_ERROR("Security component post task failed.");
798 g_omittedNodeIndex.push_back(index);
799 }
800 }
801
CreateFirstUseDialogCloseFunc(RefPtr<FrameNode> & frameNode,RefPtr<PipelineContext> & pipeline,const std::string & taskName)802 std::function<int32_t(int32_t)> SecurityComponentPattern::CreateFirstUseDialogCloseFunc(
803 RefPtr<FrameNode>& frameNode, RefPtr<PipelineContext>& pipeline, const std::string& taskName)
804 {
805 return [weak = WeakClaim(this), weakContext = WeakPtr(pipeline),
806 node = frameNode, taskName = taskName](int32_t result) mutable {
807 std::lock_guard<std::mutex> lock(g_scMutex);
808 g_scNodeMap[++g_scIndex] = std::move(node);
809 auto pattern = weak.Upgrade();
810 if (pattern == nullptr) {
811 return -1;
812 }
813 auto context = weakContext.Upgrade();
814 if (context == nullptr) {
815 pattern->DelayReleaseNode(g_scIndex);
816 return -1;
817 }
818 auto taskExecutor = context->GetTaskExecutor();
819 if (taskExecutor == nullptr) {
820 pattern->DelayReleaseNode(g_scIndex);
821 return -1;
822 }
823 bool res = taskExecutor->PostTask(
824 [weak, instanceId = context->GetInstanceId(), result, index = g_scIndex] {
825 ContainerScope scope(instanceId);
826 std::lock_guard<std::mutex> lock(g_scMutex);
827 SC_LOG_INFO("Security component frameNode cached size: %{public}zu, index: %{public}" PRId64,
828 g_scNodeMap.size(), index);
829 if (g_omittedNodeIndex.size() != 0) {
830 for (auto item : g_omittedNodeIndex) {
831 g_scNodeMap.erase(item);
832 }
833 g_omittedNodeIndex.clear();
834 }
835 if (result == static_cast<int32_t>(SecurityComponentHandleResult::GRANT_CANCEL)) {
836 g_scNodeMap.erase(index);
837 return;
838 }
839 auto pattern = weak.Upgrade();
840 if (pattern == nullptr) {
841 g_scNodeMap.erase(index);
842 return;
843 }
844 pattern->DoTriggerOnclick(result);
845 g_scNodeMap.erase(index);
846 },
847 TaskExecutor::TaskType::UI, taskName);
848 if (!res) {
849 SC_LOG_ERROR("Security component post task failed.");
850 g_omittedNodeIndex.push_back(g_scIndex);
851 }
852 return 0;
853 };
854 }
855
ReportSecurityComponentClickEvent(GestureEvent & event,std::string & message)856 int32_t SecurityComponentPattern::ReportSecurityComponentClickEvent(GestureEvent& event, std::string& message)
857 {
858 if (regStatus_ == SecurityComponentRegisterStatus::UNREGISTERED) {
859 SC_LOG_WARN("ClickEventHandler: security component has not registered.");
860 return -1;
861 }
862 auto frameNode = GetHost();
863 CHECK_NULL_RETURN(frameNode, -1);
864 if (regStatus_ == SecurityComponentRegisterStatus::REGISTERING) {
865 RegisterSecurityComponentRetry();
866 }
867 if (regStatus_ != SecurityComponentRegisterStatus::REGISTERED) {
868 SC_LOG_WARN("ClickEventHandler: security component try to register failed.");
869 return -1;
870 }
871
872 auto pipeline = frameNode->GetContextRefPtr();
873 CHECK_NULL_RETURN(pipeline, -1);
874 std::function<void (int32_t)> OnClickAfterFirstUseDialog;
875 if (frameNode->GetTag() == V2::PASTE_BUTTON_ETS_TAG) {
876 OnClickAfterFirstUseDialog = [] (int32_t) {};
877 return SecurityComponentHandler::ReportSecurityComponentClickEvent(scId_,
878 frameNode, event, std::move(OnClickAfterFirstUseDialog), message);
879 }
880
881 OnClickAfterFirstUseDialog = CreateFirstUseDialogCloseFunc(
882 frameNode, pipeline, "ArkUISecurityComponentGestureTriggerOnClick");
883
884 return SecurityComponentHandler::ReportSecurityComponentClickEvent(scId_,
885 frameNode, event, std::move(OnClickAfterFirstUseDialog), message);
886 }
887
ReportSecurityComponentClickEvent(const KeyEvent & event)888 int32_t SecurityComponentPattern::ReportSecurityComponentClickEvent(const KeyEvent& event)
889 {
890 if (regStatus_ == SecurityComponentRegisterStatus::UNREGISTERED) {
891 SC_LOG_WARN("KeyEventHandler: security component has not registered.");
892 return -1;
893 }
894 auto frameNode = GetHost();
895 CHECK_NULL_RETURN(frameNode, -1);
896 if (regStatus_ == SecurityComponentRegisterStatus::REGISTERING) {
897 RegisterSecurityComponentRetry();
898 }
899 if (regStatus_ != SecurityComponentRegisterStatus::REGISTERED) {
900 SC_LOG_WARN("KeyEventHandler: security component try to register failed.");
901 return -1;
902 }
903
904 auto pipeline = frameNode->GetContextRefPtr();
905 CHECK_NULL_RETURN(pipeline, -1);
906 std::function<void (int32_t)> OnClickAfterFirstUseDialog;
907 if (frameNode->GetTag() == V2::PASTE_BUTTON_ETS_TAG) {
908 OnClickAfterFirstUseDialog = [] (int32_t) {};
909 return SecurityComponentHandler::ReportSecurityComponentClickEvent(scId_,
910 frameNode, event, std::move(OnClickAfterFirstUseDialog));
911 }
912
913 OnClickAfterFirstUseDialog = CreateFirstUseDialogCloseFunc(
914 frameNode, pipeline, "ArkUISecurityComponentKeyTriggerOnClick");
915
916 return SecurityComponentHandler::ReportSecurityComponentClickEvent(scId_,
917 frameNode, event, std::move(OnClickAfterFirstUseDialog));
918 }
919
HandleReportSecCompClickEventResult(int32_t & code,std::string & message)920 void SecurityComponentPattern::HandleReportSecCompClickEventResult(int32_t& code, std::string& message)
921 {
922 if (!message.empty()) {
923 code = SecurityComponentErrorCode::PROPERTY_SETING_ERROR;
924 }
925
926 if (code != SecurityComponentErrorCode::SUCCESS && message.empty()) {
927 message = SYSTEM_INTERNAL_ERROR_MESSAGE;
928 code = SecurityComponentErrorCode::SYSTEM_INTERNAL_ERROR;
929 }
930 }
931 #endif
932 } // namespace OHOS::Ace::NG
933