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 "base/log/ace_scoring_log.h"
18 #include "core/components_ng/base/inspector_filter.h"
19 #include "core/components_ng/pattern/button/button_layout_property.h"
20 #include "core/components_ng/pattern/button/button_pattern.h"
21 #include "core/components_ng/pattern/image/image_pattern.h"
22 #ifdef SECURITY_COMPONENT_ENABLE
23 #include "core/components_ng/pattern/security_component/security_component_handler.h"
24 #endif
25 #include "core/components_ng/pattern/security_component/security_component_log.h"
26 #include "core/components_ng/pattern/security_component/security_component_theme.h"
27 #include "core/components_ng/pattern/text/text_layout_property.h"
28 #include "core/components/common/layout/constants.h"
29 #include "core/components_v2/inspector/inspector_constants.h"
30 #ifdef SECURITY_COMPONENT_ENABLE
31 #include "pointer_event.h"
32 #endif
33 
34 namespace OHOS::Ace::NG {
35 namespace {
36 #ifdef SECURITY_COMPONENT_ENABLE
37 const int32_t DELAY_RELEASE_MILLSEC = 10;
38 #endif
39 }
SecurityComponentPattern()40 SecurityComponentPattern::SecurityComponentPattern()
41 {
42 #ifdef SECURITY_COMPONENT_ENABLE
43     uiEventHandler_ = OHOS::AppExecFwk::EventHandler::Current();
44 #endif
45 }
46 
~SecurityComponentPattern()47 SecurityComponentPattern::~SecurityComponentPattern()
48 {
49 #ifdef SECURITY_COMPONENT_ENABLE
50     UnregisterSecurityComponent();
51 #endif
52 }
53 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)54 bool SecurityComponentPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty,
55     const DirtySwapConfig& config)
56 {
57     CHECK_NULL_RETURN(dirty, false);
58     return !(config.skipMeasure || dirty->SkipMeasureContent());
59 }
60 
SetNodeHitTestMode(RefPtr<FrameNode> & node,HitTestMode mode)61 void SecurityComponentPattern::SetNodeHitTestMode(RefPtr<FrameNode>& node, HitTestMode mode)
62 {
63     if (node == nullptr) {
64         return;
65     }
66     auto gestureHub = node->GetOrCreateGestureEventHub();
67     CHECK_NULL_VOID(gestureHub);
68     gestureHub->SetHitTestMode(mode);
69 }
70 
OnKeyEvent(const KeyEvent & event)71 bool SecurityComponentPattern::OnKeyEvent(const KeyEvent& event)
72 {
73     if (event.action != KeyAction::DOWN) {
74         return false;
75     }
76     if ((event.code == KeyCode::KEY_SPACE) || (event.code == KeyCode::KEY_ENTER) ||
77         (event.code == KeyCode::KEY_NUMPAD_ENTER)) {
78         auto frameNode = GetHost();
79         CHECK_NULL_RETURN(frameNode, false);
80         int32_t res = 1;
81 #ifdef SECURITY_COMPONENT_ENABLE
82         res = ReportSecurityComponentClickEvent(event);
83         if (res == Security::SecurityComponent::SC_SERVICE_ERROR_WAIT_FOR_DIALOG_CLOSE) {
84             res = static_cast<int32_t>(SecurityComponentHandleResult::DROP_CLICK);
85         } else if (res != 0) {
86             SC_LOG_ERROR("ReportSecurityComponentClickEvent failed, errno %{public}d", res);
87             res = 1;
88         }
89 #endif
90         auto jsonNode = JsonUtil::Create(true);
91         CHECK_NULL_RETURN(jsonNode, false);
92         jsonNode->Put("handleRes", res);
93         std::shared_ptr<JsonValue> jsonShrd(jsonNode.release());
94         auto gestureEventHub = frameNode->GetOrCreateGestureEventHub();
95         gestureEventHub->ActClick(jsonShrd);
96         return true;
97     }
98     return false;
99 }
100 
InitOnKeyEvent(RefPtr<FrameNode> & secCompNode)101 void SecurityComponentPattern::InitOnKeyEvent(RefPtr<FrameNode>& secCompNode)
102 {
103     if (isSetOnKeyEvent) {
104         return;
105     }
106     auto focusHub = secCompNode->GetOrCreateFocusHub();
107     auto onKeyEvent = [wp = WeakClaim(this)](const KeyEvent& event) -> bool {
108         auto pattern = wp.Upgrade();
109         if (!pattern) {
110             return false;
111         }
112         return pattern->OnKeyEvent(event);
113     };
114     focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
115     isSetOnKeyEvent = true;
116 }
117 
IsParentMenu(RefPtr<FrameNode> & secCompNode)118 bool SecurityComponentPattern::IsParentMenu(RefPtr<FrameNode>& secCompNode)
119 {
120     auto parent = secCompNode->GetParent();
121     while (parent != nullptr) {
122         if (parent->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
123             return true;
124         }
125         parent = parent->GetParent();
126     }
127     return false;
128 }
129 
HandleClickEventFromTouch(const TouchEventInfo & info)130 void SecurityComponentPattern::HandleClickEventFromTouch(const TouchEventInfo& info)
131 {
132 #ifdef SECURITY_COMPONENT_ENABLE
133     auto host = GetHost();
134     CHECK_NULL_VOID(host);
135 
136     if (!IsParentMenu(host)) {
137         return;
138     }
139 
140     auto pointerEvent = info.GetPointerEvent();
141     CHECK_NULL_VOID(pointerEvent);
142 
143     int32_t pointerId = pointerEvent->GetPointerId();
144     MMI::PointerEvent::PointerItem item;
145     if (!pointerEvent->GetPointerItem(pointerId, item)) {
146         SC_LOG_WARN("Get pointer item failed");
147         return;
148     }
149 
150     GestureEvent gestureInfo;
151     gestureInfo.SetDisplayX(item.GetDisplayX());
152     gestureInfo.SetDisplayY(item.GetDisplayY());
153     gestureInfo.SetPointerEvent(info.GetPointerEvent());
154     int res = ReportSecurityComponentClickEvent(gestureInfo);
155     if (res == Security::SecurityComponent::SC_SERVICE_ERROR_WAIT_FOR_DIALOG_CLOSE) {
156         return;
157     }
158     if (res != 0) {
159         SC_LOG_WARN("ReportSecurityComponentClickEvent failed, errno %{public}d", res);
160         res = 1;
161     }
162     auto jsonNode = JsonUtil::Create(true);
163     CHECK_NULL_VOID(jsonNode);
164     jsonNode->Put("handleRes", res);
165     std::shared_ptr<JsonValue> jsonShrd(jsonNode.release());
166     auto gestureEventHub = host->GetOrCreateGestureEventHub();
167     gestureEventHub->ActClick(jsonShrd);
168 #endif
169 }
170 
171 // When security component is a child node of menu wrapper, the menu is immediately hidden
172 // after being touched, and then the security component will trigger a click event.
173 // However, it will be considered to have been triggered in a hidden state,
174 // Therefore, we should report click event on UP touch event.
OnTouch(const TouchEventInfo & info)175 void SecurityComponentPattern::OnTouch(const TouchEventInfo& info)
176 {
177     auto touchType = info.GetTouches().front().GetTouchType();
178     if (touchType == TouchType::DOWN) {
179         lastTouchOffset_ = std::make_unique<Offset>(info.GetTouches().front().GetLocalLocation());
180     } else if (touchType == TouchType::UP) {
181         auto touchUpOffset = info.GetTouches().front().GetLocalLocation();
182         if (lastTouchOffset_ &&
183             (touchUpOffset - *lastTouchOffset_).GetDistance() <= DEFAULT_SECURITY_COMPONENT_CLICK_DISTANCE) {
184             HandleClickEventFromTouch(info);
185         }
186         lastTouchOffset_.reset();
187     }
188 }
189 
InitOnTouch(RefPtr<FrameNode> & secCompNode)190 void SecurityComponentPattern::InitOnTouch(RefPtr<FrameNode>& secCompNode)
191 {
192     if (onTouchListener_ != nullptr) {
193         return;
194     }
195     auto gestureHub = secCompNode->GetOrCreateGestureEventHub();
196     CHECK_NULL_VOID(gestureHub);
197 
198     auto touchCallback = [weak = WeakClaim(this)](const TouchEventInfo& info) {
199         auto pattern = weak.Upgrade();
200         CHECK_NULL_VOID(pattern);
201         pattern->OnTouch(info);
202     };
203     onTouchListener_ = MakeRefPtr<TouchEventImpl>(std::move(touchCallback));
204     gestureHub->AddTouchEvent(onTouchListener_);
205 }
206 
InitOnClick(RefPtr<FrameNode> & secCompNode,RefPtr<FrameNode> & icon,RefPtr<FrameNode> & text,RefPtr<FrameNode> & button)207 void SecurityComponentPattern::InitOnClick(RefPtr<FrameNode>& secCompNode, RefPtr<FrameNode>& icon,
208     RefPtr<FrameNode>& text, RefPtr<FrameNode>& button)
209 {
210     if (clickListener_ != nullptr) {
211         return;
212     }
213     auto secCompGesture = secCompNode->GetOrCreateGestureEventHub();
214     CHECK_NULL_VOID(secCompGesture);
215     auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
216 #ifdef SECURITY_COMPONENT_ENABLE
217         auto buttonPattern = weak.Upgrade();
218         CHECK_NULL_VOID(buttonPattern);
219         auto frameNode = buttonPattern->GetHost();
220         CHECK_NULL_VOID(frameNode);
221         if (info.GetSecCompHandleEvent()) {
222             return;
223         }
224         auto jsonNode = JsonUtil::Create(true);
225         CHECK_NULL_VOID(jsonNode);
226         std::shared_ptr<JsonValue> jsonShrd(jsonNode.release());
227         int32_t res;
228         // if info.GetPointerEvent() is null, device may in screen read mode
229         // otherwise, this event should be dropped in menu
230         if (buttonPattern->IsParentMenu(frameNode) && info.GetPointerEvent() != nullptr) {
231             res = static_cast<int32_t>(SecurityComponentHandleResult::DROP_CLICK);
232         } else {
233             res = buttonPattern->ReportSecurityComponentClickEvent(info);
234             if (res == Security::SecurityComponent::SC_SERVICE_ERROR_WAIT_FOR_DIALOG_CLOSE) {
235                 res = static_cast<int32_t>(SecurityComponentHandleResult::DROP_CLICK);
236             } else if (res != 0) {
237                 SC_LOG_WARN("ReportSecurityComponentClickEvent failed, errno %{public}d", res);
238                 res = static_cast<int32_t>(SecurityComponentHandleResult::CLICK_GRANT_FAILED);
239             }
240         }
241         jsonShrd->Put("handleRes", res);
242         info.SetSecCompHandleEvent(jsonShrd);
243 #endif
244     };
245 
246     clickListener_ = MakeRefPtr<ClickEvent>(std::move(clickCallback));
247     secCompGesture->AddClickEvent(clickListener_);
248     SetNodeHitTestMode(icon, HitTestMode::HTMTRANSPARENT);
249     SetNodeHitTestMode(text, HitTestMode::HTMTRANSPARENT);
250 }
251 
ToJsonValueIconNode(std::unique_ptr<JsonValue> & json,const RefPtr<FrameNode> & iconNode,const InspectorFilter & filter) const252 void SecurityComponentPattern::ToJsonValueIconNode(std::unique_ptr<JsonValue>& json, const RefPtr<FrameNode>& iconNode,
253     const InspectorFilter& filter) const
254 {
255     auto iconProp = iconNode->GetLayoutProperty<ImageLayoutProperty>();
256     CHECK_NULL_VOID(iconProp);
257     json->PutExtAttr("iconSize",
258         iconProp->GetCalcLayoutConstraint()->selfIdealSize->Width()->GetDimension().ToString().c_str(), filter);
259     json->PutExtAttr("iconColor", iconProp->GetImageSourceInfo().value().GetFillColor().
260         value_or(Color::WHITE).ColorToString().c_str(), filter);
261 }
262 
ToJsonValueTextNode(std::unique_ptr<JsonValue> & json,const RefPtr<FrameNode> & textNode,const InspectorFilter & filter) const263 void SecurityComponentPattern::ToJsonValueTextNode(std::unique_ptr<JsonValue>& json, const RefPtr<FrameNode>& textNode,
264     const InspectorFilter& filter) const
265 {
266     auto textProp = textNode->GetLayoutProperty<TextLayoutProperty>();
267     CHECK_NULL_VOID(textProp);
268     json->PutExtAttr("fontSize", textProp->GetFontSize().value_or(Dimension(0.0)).ToString().c_str(), filter);
269     json->PutExtAttr("fontWeight", V2::ConvertWrapFontWeightToStirng(
270         textProp->GetFontWeight().value_or(FontWeight::NORMAL)).c_str(), filter);
271     json->PutExtAttr("fontFamily", "HarmonyOS Sans", filter);
272     json->PutExtAttr("fontStyle",
273         static_cast<int64_t>(textProp->GetItalicFontStyle().value_or(Ace::FontStyle::NORMAL)), filter);
274     json->PutExtAttr("fontColor", textProp->GetTextColor().value_or(Color::WHITE).ColorToString().c_str(), filter);
275 }
276 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const277 void SecurityComponentPattern::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
278 {
279     /* no fixed attr below, just return */
280     if (filter.IsFastFilter()) {
281         ToJsonValueRect(json, filter);
282         return;
283     }
284     auto node = GetHost();
285     CHECK_NULL_VOID(node);
286 
287     auto layoutProperty = AceType::DynamicCast<SecurityComponentLayoutProperty>(node->GetLayoutProperty());
288     CHECK_NULL_VOID(layoutProperty);
289     json->PutExtAttr("text", layoutProperty->GetSecurityComponentDescription().value_or(0), filter);
290     json->PutExtAttr("icon", layoutProperty->GetIconStyle().value_or(0), filter);
291     json->PutExtAttr("buttonType", layoutProperty->GetBackgroundType().value_or(0), filter);
292     json->PutExtAttr("layoutDirection", static_cast<int64_t>(
293         layoutProperty->GetTextIconLayoutDirection().value_or(SecurityComponentLayoutDirection::VERTICAL)), filter);
294     json->PutExtAttr("type", node->GetTag().c_str(), filter);
295 
296     RefPtr<FrameNode> iconNode = GetSecCompChildNode(node, V2::IMAGE_ETS_TAG);
297     if (iconNode != nullptr) {
298         ToJsonValueIconNode(json, iconNode, filter);
299     }
300     RefPtr<FrameNode> textNode = GetSecCompChildNode(node, V2::TEXT_ETS_TAG);
301     if (textNode != nullptr) {
302         ToJsonValueTextNode(json, textNode, filter);
303     }
304     auto paddingJson = JsonUtil::Create(true);
305     CHECK_NULL_VOID(paddingJson);
306     paddingJson->Put("top", layoutProperty->GetBackgroundTopPadding().value_or(Dimension(0.0)).ToString().c_str());
307     paddingJson->Put("bottom",
308         layoutProperty->GetBackgroundBottomPadding().value_or(Dimension(0.0)).ToString().c_str());
309     paddingJson->Put("left", layoutProperty->GetBackgroundLeftPadding().value_or(Dimension(0.0)).ToString().c_str());
310     paddingJson->Put("right", layoutProperty->GetBackgroundRightPadding().value_or(Dimension(0.0)).ToString().c_str());
311     json->PutExtAttr("padding", paddingJson, filter);
312     json->PutExtAttr("textIconSpace",
313         layoutProperty->GetTextIconSpace().value_or(Dimension(0.0)).ToString().c_str(), filter);
314     ToJsonValueRect(json, filter);
315 }
316 
ToJsonValueRect(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const317 void SecurityComponentPattern::ToJsonValueRect(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
318 {
319     /* no fixed attr below, just return */
320     if (filter.IsFastFilter()) {
321         return;
322     }
323     auto node = GetHost();
324     CHECK_NULL_VOID(node);
325 
326     RefPtr<FrameNode> buttonNode = GetSecCompChildNode(node, V2::BUTTON_ETS_TAG);
327     if (buttonNode != nullptr) {
328         const auto& renderContext = buttonNode->GetRenderContext();
329         CHECK_NULL_VOID(renderContext);
330         json->PutExtAttr("backgroundColor",
331             renderContext->GetBackgroundColor().value().ColorToString().c_str(), filter);
332         json->PutExtAttr("borderColor",
333             renderContext->GetBorderColor()->leftColor.value_or(Color::BLACK).ColorToString().c_str(), filter);
334         json->PutExtAttr("borderStyle",
335             static_cast<int>(renderContext->GetBorderStyle()->styleLeft.value_or(BorderStyle::NONE)), filter);
336         auto bgProp = buttonNode->GetLayoutProperty<ButtonLayoutProperty>();
337         CHECK_NULL_VOID(bgProp);
338         const auto& borderWidth = bgProp->GetBorderWidthProperty();
339         if (borderWidth != nullptr) {
340             json->PutExtAttr("borderWidth",
341                 borderWidth->leftDimen.value_or(Dimension(0.0)).ToString().c_str(), filter);
342         }
343         auto borderRadius = bgProp->GetBorderRadius();
344         if (borderRadius.has_value()) {
345             json->PutExtAttr("borderRadius", borderRadius->radiusTopLeft.value_or(Dimension(0.0, DimensionUnit::VP)).
346                 ToString().c_str(), filter);
347         } else {
348             json->PutExtAttr("borderRadius", "0.00vp", filter);
349         }
350     }
351 }
352 
GetFocusPattern() const353 FocusPattern SecurityComponentPattern::GetFocusPattern() const
354 {
355     auto frameNode = GetHost();
356     RefPtr<FrameNode> buttonNode = GetSecCompChildNode(frameNode, V2::BUTTON_ETS_TAG);
357     if (buttonNode != nullptr) {
358         auto buttonPattern = buttonNode->GetPattern<ButtonPattern>();
359         return buttonPattern->GetFocusPattern();
360     }
361 
362     return { FocusType::NODE, true, FocusStyleType::OUTER_BORDER };
363 }
364 
UpdateIconProperty(RefPtr<FrameNode> & scNode,RefPtr<FrameNode> & iconNode)365 void SecurityComponentPattern::UpdateIconProperty(RefPtr<FrameNode>& scNode, RefPtr<FrameNode>& iconNode)
366 {
367     auto iconLayoutProp = iconNode->GetLayoutProperty<ImageLayoutProperty>();
368     auto scLayoutProp = scNode->GetLayoutProperty<SecurityComponentLayoutProperty>();
369     CHECK_NULL_VOID(scLayoutProp);
370     if (scLayoutProp->GetIconSize().has_value()) {
371         auto iconSize = scLayoutProp->GetIconSize().value();
372         iconLayoutProp->UpdateUserDefinedIdealSize(CalcSize(NG::CalcLength(iconSize), NG::CalcLength(iconSize)));
373     }
374 
375     auto scPaintProp = scNode->GetPaintProperty<SecurityComponentPaintProperty>();
376     CHECK_NULL_VOID(scPaintProp);
377     if (scPaintProp->GetIconColor().has_value() && iconLayoutProp->GetImageSourceInfo().has_value()) {
378         auto iconSrcInfo = iconLayoutProp->GetImageSourceInfo().value();
379         iconSrcInfo.SetFillColor(scPaintProp->GetIconColor().value());
380         iconLayoutProp->UpdateImageSourceInfo(iconSrcInfo);
381     }
382 }
383 
UpdateTextProperty(RefPtr<FrameNode> & scNode,RefPtr<FrameNode> & textNode)384 void SecurityComponentPattern::UpdateTextProperty(RefPtr<FrameNode>& scNode, RefPtr<FrameNode>& textNode)
385 {
386     auto scLayoutProp = scNode->GetLayoutProperty<SecurityComponentLayoutProperty>();
387     auto textLayoutProp = textNode->GetLayoutProperty<TextLayoutProperty>();
388     if (scLayoutProp->GetFontSize().has_value()) {
389         textLayoutProp->UpdateFontSize(scLayoutProp->GetFontSize().value());
390     }
391     if (scLayoutProp->GetFontStyle().has_value()) {
392         textLayoutProp->UpdateItalicFontStyle(scLayoutProp->GetFontStyle().value());
393     }
394     if (scLayoutProp->GetFontWeight().has_value()) {
395         textLayoutProp->UpdateFontWeight(scLayoutProp->GetFontWeight().value());
396     }
397     if (scLayoutProp->GetFontFamily().has_value()) {
398         textLayoutProp->UpdateFontFamily(scLayoutProp->GetFontFamily().value());
399     }
400     auto scPaintProp = scNode->GetPaintProperty<SecurityComponentPaintProperty>();
401     if (scPaintProp->GetFontColor().has_value()) {
402         textLayoutProp->UpdateTextColor(scPaintProp->GetFontColor().value());
403     }
404 }
405 
UpdateButtonProperty(RefPtr<FrameNode> & scNode,RefPtr<FrameNode> & buttonNode)406 void SecurityComponentPattern::UpdateButtonProperty(RefPtr<FrameNode>& scNode, RefPtr<FrameNode>& buttonNode)
407 {
408     auto scLayoutProp = scNode->GetLayoutProperty<SecurityComponentLayoutProperty>();
409     auto scPaintProp = scNode->GetPaintProperty<SecurityComponentPaintProperty>();
410     auto buttonLayoutProp = buttonNode->GetLayoutProperty<ButtonLayoutProperty>();
411     const auto& buttonRender = buttonNode->GetRenderContext();
412     CHECK_NULL_VOID(buttonRender);
413 
414     if (scLayoutProp->GetBackgroundBorderWidth().has_value()) {
415         BorderWidthProperty widthProp;
416         widthProp.SetBorderWidth(scLayoutProp->GetBackgroundBorderWidth().value());
417         buttonLayoutProp->UpdateBorderWidth(widthProp);
418     }
419 
420     if (scPaintProp->GetBackgroundBorderStyle().has_value()) {
421         BorderStyleProperty style;
422         style.SetBorderStyle(scPaintProp->GetBackgroundBorderStyle().value());
423         buttonRender->UpdateBorderStyle(style);
424     }
425     if (scLayoutProp->GetBackgroundBorderRadius().has_value()) {
426         buttonLayoutProp->UpdateBorderRadius(
427             BorderRadiusProperty(scLayoutProp->GetBackgroundBorderRadius().value()));
428     }
429     if (scPaintProp->GetBackgroundColor().has_value()) {
430         buttonRender->UpdateBackgroundColor(scPaintProp->GetBackgroundColor().value());
431     }
432     if (scPaintProp->GetBackgroundBorderColor().has_value()) {
433         BorderColorProperty borderColor;
434         borderColor.SetColor(scPaintProp->GetBackgroundBorderColor().value());
435         buttonRender->UpdateBorderColor(borderColor);
436     }
437 }
438 
OnModifyDone()439 void SecurityComponentPattern::OnModifyDone()
440 {
441     auto frameNode = GetHost();
442     CHECK_NULL_VOID(frameNode);
443 
444     RefPtr<FrameNode> iconNode = GetSecCompChildNode(frameNode, V2::IMAGE_ETS_TAG);
445     if (iconNode != nullptr) {
446         UpdateIconProperty(frameNode, iconNode);
447         iconNode->MarkModifyDone();
448     }
449 
450     RefPtr<FrameNode> textNode = GetSecCompChildNode(frameNode, V2::TEXT_ETS_TAG);
451     if (textNode != nullptr) {
452         UpdateTextProperty(frameNode, textNode);
453         textNode->MarkModifyDone();
454     }
455 
456     RefPtr<FrameNode> buttonNode = GetSecCompChildNode(frameNode, V2::BUTTON_ETS_TAG);
457     if (buttonNode != nullptr) {
458         UpdateButtonProperty(frameNode, buttonNode);
459         buttonNode->MarkModifyDone();
460     }
461 
462     InitOnClick(frameNode, iconNode, textNode, buttonNode);
463     InitOnKeyEvent(frameNode);
464     InitAppearCallback(frameNode);
465     InitOnTouch(frameNode);
466 }
467 
IsFontColorSet()468 bool SecurityComponentPattern::IsFontColorSet()
469 {
470     auto frameNode = GetHost();
471     CHECK_NULL_RETURN(frameNode, false);
472     auto prop = frameNode->GetLayoutProperty<SecurityComponentLayoutProperty>();
473     if (prop && prop->GetIsFontColorSet().has_value()) {
474         return prop->GetIsFontColorSet().value();
475     }
476     return false;
477 }
478 
OnColorConfigurationUpdate()479 void SecurityComponentPattern::OnColorConfigurationUpdate()
480 {
481     auto node = GetHost();
482     CHECK_NULL_VOID(node);
483     node->SetNeedCallChildrenUpdate(IsFontColorSet());
484 }
485 
InitAppearCallback(RefPtr<FrameNode> & frameNode)486 void SecurityComponentPattern::InitAppearCallback(RefPtr<FrameNode>& frameNode)
487 {
488     if (isAppearCallback_) {
489         return;
490     }
491     auto eventHub = frameNode->GetEventHub<EventHub>();
492     CHECK_NULL_VOID(eventHub);
493 
494     auto context = frameNode->GetContextRefPtr();
495     CHECK_NULL_VOID(context);
496     auto instanceId = context->GetInstanceId();
497     auto onAppear = [weak = WeakClaim(this), instanceId]() {
498         ContainerScope scope(instanceId);
499 #ifdef SECURITY_COMPONENT_ENABLE
500         auto securityComponentPattern = weak.Upgrade();
501         CHECK_NULL_VOID(securityComponentPattern);
502         securityComponentPattern->isAppear_ = true;
503         securityComponentPattern->RegisterSecurityComponent();
504 #endif
505     };
506 
507     auto onDisAppear = [weak = WeakClaim(this)]() {
508 #ifdef SECURITY_COMPONENT_ENABLE
509         auto securityComponentPattern = weak.Upgrade();
510         CHECK_NULL_VOID(securityComponentPattern);
511         securityComponentPattern->isAppear_ = false;
512         securityComponentPattern->UnregisterSecurityComponent();
513 #endif
514     };
515     eventHub->SetOnAppear(std::move(onAppear));
516     eventHub->SetOnDisappear(std::move(onDisAppear));
517     isAppearCallback_ = true;
518 }
519 
OnWindowHide()520 void SecurityComponentPattern::OnWindowHide()
521 {
522 #ifdef SECURITY_COMPONENT_ENABLE
523     UnregisterSecurityComponent();
524 #endif
525 }
526 
OnWindowShow()527 void SecurityComponentPattern::OnWindowShow()
528 {
529 #ifdef SECURITY_COMPONENT_ENABLE
530     if (!isAppear_) {
531         return;
532     }
533     RegisterSecurityComponent();
534 #endif
535 }
536 
537 #ifdef SECURITY_COMPONENT_ENABLE
RegisterSecurityComponentRetry()538 void SecurityComponentPattern::RegisterSecurityComponentRetry()
539 {
540     auto frameNode = GetHost();
541     CHECK_NULL_VOID(frameNode);
542     // service is shutdowning, try to load it.
543     int32_t retryCount = MAX_RETRY_TIMES;
544     while (retryCount > 0) {
545         int32_t res = SecurityComponentHandler::RegisterSecurityComponent(frameNode, scId_);
546         if (res == Security::SecurityComponent::SCErrCode::SC_OK) {
547             regStatus_ = SecurityComponentRegisterStatus::REGISTERED;
548             return;
549         } else if (res != Security::SecurityComponent::SCErrCode::SC_SERVICE_ERROR_SERVICE_NOT_EXIST) {
550             SC_LOG_WARN("Register security component failed, err %{public}d.", res);
551             regStatus_ = SecurityComponentRegisterStatus::UNREGISTERED;
552             return;
553         }
554 
555         retryCount--;
556         std::this_thread::sleep_for(std::chrono::milliseconds(REGISTER_RETRY_INTERVAL));
557     }
558     regStatus_ = SecurityComponentRegisterStatus::UNREGISTERED;
559     SC_LOG_WARN("Register security component failed, retry %{public}d", MAX_RETRY_TIMES);
560 }
561 
RegisterSecurityComponent()562 void SecurityComponentPattern::RegisterSecurityComponent()
563 {
564     if (regStatus_ == SecurityComponentRegisterStatus::REGISTERED ||
565         regStatus_ == SecurityComponentRegisterStatus::REGISTERING) {
566         return;
567     }
568 
569     if (SecurityComponentHandler::IsSecurityComponentServiceExist()) {
570         RegisterSecurityComponentRetry();
571         return;
572     }
573     regStatus_ = SecurityComponentRegisterStatus::REGISTERING;
574     auto taskExecutor = Container::CurrentTaskExecutor();
575     CHECK_NULL_VOID(taskExecutor);
576     auto frameNode = GetHost();
577     CHECK_NULL_VOID(frameNode);
578     auto pipeline = frameNode->GetContextRefPtr();
579     CHECK_NULL_VOID(pipeline);
580     taskExecutor->PostTask(
581         [weak = WeakClaim(this), weakContext = WeakPtr(pipeline)] {
582             if (!SecurityComponentHandler::LoadSecurityComponentService()) {
583                 SC_LOG_WARN("load security component service failed.");
584                 return;
585             }
586             auto context = weakContext.Upgrade();
587             CHECK_NULL_VOID(context);
588             auto taskExecutor = context->GetTaskExecutor();
589             CHECK_NULL_VOID(taskExecutor);
590             taskExecutor->PostTask(
591                 [weak, instanceID = context->GetInstanceId()] {
592                     ContainerScope scope(instanceID);
593                     auto pattern = weak.Upgrade();
594                     CHECK_NULL_VOID(pattern);
595                     if (pattern->regStatus_ != SecurityComponentRegisterStatus::REGISTERING) {
596                         return;
597                     }
598 
599                     pattern->RegisterSecurityComponentRetry();
600                 },
601                 TaskExecutor::TaskType::UI, "ArkUISecurityComponentRegisterRetry");
602         },
603         TaskExecutor::TaskType::BACKGROUND, "ArkUISecurityComponentRegister");
604 }
605 
UnregisterSecurityComponent()606 void SecurityComponentPattern::UnregisterSecurityComponent()
607 {
608     if (regStatus_ == SecurityComponentRegisterStatus::REGISTERED) {
609         SecurityComponentHandler::UnregisterSecurityComponent(scId_);
610     } else {
611         SC_LOG_INFO("security component has not registered, regStatus %{public}d.", regStatus_);
612     }
613     regStatus_ = SecurityComponentRegisterStatus::UNREGISTERED;
614     scId_ = -1;
615 }
616 
DoTriggerOnclick(int32_t result)617 void SecurityComponentPattern::DoTriggerOnclick(int32_t result)
618 {
619     auto host = GetHost();
620     CHECK_NULL_VOID(host);
621     auto jsonNode = JsonUtil::Create(true);
622     CHECK_NULL_VOID(jsonNode);
623     if (result != 0) {
624         jsonNode->Put("handleRes", static_cast<int32_t>(SecurityComponentHandleResult::CLICK_GRANT_FAILED));
625     } else {
626         jsonNode->Put("handleRes", static_cast<int32_t>(SecurityComponentHandleResult::CLICK_SUCCESS));
627     }
628 
629     std::shared_ptr<JsonValue> jsonShrd(jsonNode.release());
630     auto gestureEventHub = host->GetOrCreateGestureEventHub();
631     CHECK_NULL_VOID(gestureEventHub);
632     gestureEventHub->ActClick(jsonShrd);
633 }
634 
DelayReleaseNode(RefPtr<FrameNode> & node)635 void SecurityComponentPattern::DelayReleaseNode(RefPtr<FrameNode>& node)
636 {
637     if (uiEventHandler_ == nullptr) {
638         SC_LOG_WARN("UIEventHandler invalid");
639         return;
640     }
641     uiEventHandler_->PostTask(
642         [nodeInner = std::move(node)]() { return; },
643         DELAY_RELEASE_MILLSEC);
644 }
645 
CreateFirstUseDialogCloseFunc(RefPtr<FrameNode> & frameNode,RefPtr<PipelineContext> & pipeline,const std::string & taskName)646 std::function<int32_t(int32_t)> SecurityComponentPattern::CreateFirstUseDialogCloseFunc(
647     RefPtr<FrameNode>& frameNode, RefPtr<PipelineContext>& pipeline, const std::string& taskName)
648 {
649     return [weak = WeakClaim(this), weakContext = WeakPtr(pipeline),
650         node = frameNode, taskName = taskName](int32_t result) mutable {
651         auto pattern = weak.Upgrade();
652         if (pattern == nullptr) {
653             return -1;
654         }
655         auto context = weakContext.Upgrade();
656         if (context == nullptr) {
657             pattern->DelayReleaseNode(node);
658             return -1;
659         }
660         auto taskExecutor = context->GetTaskExecutor();
661         if (taskExecutor == nullptr) {
662             pattern->DelayReleaseNode(node);
663             return -1;
664         }
665         taskExecutor->PostTask(
666             [weak, instanceId = context->GetInstanceId(), result, nodeInner = std::move(node)] {
667                 if (result == static_cast<int32_t>(SecurityComponentHandleResult::GRANT_CANCEL)) {
668                     return;
669                 }
670                 ContainerScope scope(instanceId);
671                 auto pattern = weak.Upgrade();
672                 if (pattern == nullptr) {
673                     return;
674                 }
675                 pattern->DoTriggerOnclick(result);
676             },
677             TaskExecutor::TaskType::UI, taskName);
678         return 0;
679     };
680 }
681 
ReportSecurityComponentClickEvent(GestureEvent & event)682 int32_t SecurityComponentPattern::ReportSecurityComponentClickEvent(GestureEvent& event)
683 {
684     if (regStatus_ == SecurityComponentRegisterStatus::UNREGISTERED) {
685         SC_LOG_WARN("ClickEventHandler: security component has not registered.");
686         return -1;
687     }
688     auto frameNode = GetHost();
689     CHECK_NULL_RETURN(frameNode, -1);
690     if (regStatus_ == SecurityComponentRegisterStatus::REGISTERING) {
691         RegisterSecurityComponentRetry();
692     }
693     if (regStatus_ != SecurityComponentRegisterStatus::REGISTERED) {
694         SC_LOG_WARN("ClickEventHandler: security component try to register failed.");
695         return -1;
696     }
697 
698     auto pipeline = frameNode->GetContextRefPtr();
699     CHECK_NULL_RETURN(pipeline, -1);
700     std::function<void (int32_t)> OnClickAfterFirstUseDialog;
701     if (frameNode->GetTag() == V2::PASTE_BUTTON_ETS_TAG) {
702         OnClickAfterFirstUseDialog = [] (int32_t) {};
703         return SecurityComponentHandler::ReportSecurityComponentClickEvent(scId_,
704             frameNode, event, std::move(OnClickAfterFirstUseDialog));
705     }
706 
707     OnClickAfterFirstUseDialog = CreateFirstUseDialogCloseFunc(
708         frameNode, pipeline, "ArkUISecurityComponentGestureTriggerOnClick");
709 
710     return SecurityComponentHandler::ReportSecurityComponentClickEvent(scId_,
711         frameNode, event, std::move(OnClickAfterFirstUseDialog));
712 }
713 
ReportSecurityComponentClickEvent(const KeyEvent & event)714 int32_t SecurityComponentPattern::ReportSecurityComponentClickEvent(const KeyEvent& event)
715 {
716     if (regStatus_ == SecurityComponentRegisterStatus::UNREGISTERED) {
717         SC_LOG_WARN("KeyEventHandler: security component has not registered.");
718         return -1;
719     }
720     auto frameNode = GetHost();
721     CHECK_NULL_RETURN(frameNode, -1);
722     if (regStatus_ == SecurityComponentRegisterStatus::REGISTERING) {
723         RegisterSecurityComponentRetry();
724     }
725     if (regStatus_ != SecurityComponentRegisterStatus::REGISTERED) {
726         SC_LOG_WARN("KeyEventHandler: security component try to register failed.");
727         return -1;
728     }
729 
730     auto pipeline = frameNode->GetContextRefPtr();
731     CHECK_NULL_RETURN(pipeline, -1);
732     std::function<void (int32_t)> OnClickAfterFirstUseDialog;
733     if (frameNode->GetTag() == V2::PASTE_BUTTON_ETS_TAG) {
734         OnClickAfterFirstUseDialog = [] (int32_t) {};
735         return SecurityComponentHandler::ReportSecurityComponentClickEvent(scId_,
736             frameNode, event, std::move(OnClickAfterFirstUseDialog));
737     }
738 
739     OnClickAfterFirstUseDialog = CreateFirstUseDialogCloseFunc(
740         frameNode, pipeline, "ArkUISecurityComponentKeyTriggerOnClick");
741 
742     return SecurityComponentHandler::ReportSecurityComponentClickEvent(scId_,
743         frameNode, event, std::move(OnClickAfterFirstUseDialog));
744 }
745 #endif
746 } // namespace OHOS::Ace::NG
747