1 /*
2  * Copyright (c) 2022-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 "js_accessibility_manager.h"
17 
18 #include <algorithm>
19 
20 #include "accessibility_constants.h"
21 #include "accessibility_event_info.h"
22 #include "accessibility_system_ability_client.h"
23 
24 #include "adapter/ohos/entrance/ace_application_info.h"
25 #include "adapter/ohos/entrance/ace_container.h"
26 #include "base/log/ace_trace.h"
27 #include "base/log/dump_log.h"
28 #include "base/log/event_report.h"
29 #include "base/log/log.h"
30 #include "base/utils/linear_map.h"
31 #include "base/utils/string_utils.h"
32 #include "base/utils/utils.h"
33 #include "core/components_ng/base/inspector.h"
34 #include "core/components_ng/pattern/scrollable/scrollable_utils.h"
35 #include "core/components_v2/inspector/inspector_constants.h"
36 #include "core/pipeline/pipeline_context.h"
37 #include "core/pipeline_ng/pipeline_context.h"
38 #include "frameworks/bridge/common/dom/dom_type.h"
39 #include "frameworks/core/components_ng/pattern/ui_extension/ui_extension_config.h"
40 #include "frameworks/core/components_ng/pattern/web/web_pattern.h"
41 #include "js_third_provider_interaction_operation.h"
42 #include "nlohmann/json.hpp"
43 
44 using namespace OHOS::Accessibility;
45 using namespace OHOS::AccessibilityConfig;
46 using namespace std;
47 
48 namespace OHOS::Ace::Framework {
49 namespace {
50 const char DUMP_ORDER[] = "-accessibility";
51 const char DUMP_INSPECTOR[] = "-inspector";
52 const char ACCESSIBILITY_FOCUSED_EVENT[] = "accessibilityfocus";
53 const char ACCESSIBILITY_CLEAR_FOCUS_EVENT[] = "accessibilityclearfocus";
54 const char TEXT_CHANGE_EVENT[] = "textchange";
55 const char PAGE_CHANGE_EVENT[] = "pagechange";
56 const char SCROLL_END_EVENT[] = "scrollend";
57 const char SCROLL_START_EVENT[] = "scrollstart";
58 const char MOUSE_HOVER_ENTER[] = "mousehoverenter";
59 const char MOUSE_HOVER_EXIT[] = "mousehoverexit";
60 const char LIST_TAG[] = "List";
61 const char SIDEBARCONTAINER_TAG[] = "SideBarContainer";
62 const char STRING_DIR_FORWARD[] = "forward";
63 const char STRING_DIR_BACKWARD[] = "backward";
64 constexpr int32_t INVALID_PARENT_ID = -2100000;
65 constexpr int32_t DEFAULT_PARENT_ID = 2100000;
66 constexpr int32_t ROOT_STACK_BASE = 1100000;
67 constexpr int32_t ROOT_DECOR_BASE = 3100000;
68 constexpr int32_t CARD_NODE_ID_RATION = 10000;
69 constexpr int32_t CARD_ROOT_NODE_ID_RATION = 1000;
70 constexpr int32_t CARD_BASE = 100000;
71 constexpr int32_t DELAY_SEND_EVENT_MILLISECOND = 20;
72 constexpr uint32_t SUB_TREE_OFFSET_IN_PAGE_ID = 16;
73 constexpr int32_t MAX_PAGE_ID_WITH_SUB_TREE = (1 << SUB_TREE_OFFSET_IN_PAGE_ID);
74 
75 const std::string ACTION_ARGU_SCROLL_STUB = "scrolltype"; // wait for change
76 const std::string ACTION_DEFAULT_PARAM = "ACCESSIBILITY_ACTION_INVALID";
77 
78 const std::map<Accessibility::ActionType, std::function<bool(const AccessibilityActionParam& param)>> ACTIONS = {
79     { ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD,
__anon0e15bb040202() 80         [](const AccessibilityActionParam& param) {
81             return param.accessibilityProperty->ActActionScrollForward(param.scrollType);
82         } },
83     { ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD,
__anon0e15bb040302() 84         [](const AccessibilityActionParam& param) {
85             return param.accessibilityProperty->ActActionScrollBackward(param.scrollType);
86         } },
87     { ActionType::ACCESSIBILITY_ACTION_SET_TEXT,
__anon0e15bb040402() 88         [](const AccessibilityActionParam& param) {
89             return param.accessibilityProperty->ActActionSetText(param.setTextArgument);
90         } },
91     { ActionType::ACCESSIBILITY_ACTION_SET_SELECTION,
__anon0e15bb040502() 92         [](const AccessibilityActionParam& param) {
93             return param.accessibilityProperty->ActActionSetSelection(param.setSelectionStart,
94                                                                       param.setSelectionEnd, param.setSelectionDir);
95         } },
96     { ActionType::ACCESSIBILITY_ACTION_COPY,
__anon0e15bb040602() 97         [](const AccessibilityActionParam& param) { return param.accessibilityProperty->ActActionCopy(); } },
98     { ActionType::ACCESSIBILITY_ACTION_CUT,
__anon0e15bb040702() 99         [](const AccessibilityActionParam& param) { return param.accessibilityProperty->ActActionCut(); } },
100     { ActionType::ACCESSIBILITY_ACTION_PASTE,
__anon0e15bb040802() 101         [](const AccessibilityActionParam& param) { return param.accessibilityProperty->ActActionPaste(); } },
102     { ActionType::ACCESSIBILITY_ACTION_CLICK,
__anon0e15bb040902() 103         [](const AccessibilityActionParam& param) { return param.accessibilityProperty->ActActionClick(); } },
104     { ActionType::ACCESSIBILITY_ACTION_LONG_CLICK,
__anon0e15bb040a02() 105         [](const AccessibilityActionParam& param) { return param.accessibilityProperty->ActActionLongClick(); } },
106     { ActionType::ACCESSIBILITY_ACTION_SELECT,
__anon0e15bb040b02() 107         [](const AccessibilityActionParam& param) { return param.accessibilityProperty->ActActionSelect(); } },
108     { ActionType::ACCESSIBILITY_ACTION_CLEAR_SELECTION,
__anon0e15bb040c02() 109         [](const AccessibilityActionParam& param) { return param.accessibilityProperty->ActActionClearSelection(); } },
110     { ActionType::ACCESSIBILITY_ACTION_NEXT_TEXT,
__anon0e15bb040d02() 111         [](const AccessibilityActionParam& param) {
112             return param.accessibilityProperty->ActActionMoveText(static_cast<int32_t>(param.moveUnit), true);
113         } },
114     { ActionType::ACCESSIBILITY_ACTION_PREVIOUS_TEXT,
__anon0e15bb040e02() 115         [](const AccessibilityActionParam& param) {
116             return param.accessibilityProperty->ActActionMoveText(static_cast<int32_t>(param.moveUnit), false);
117         } },
118     { ActionType::ACCESSIBILITY_ACTION_SET_CURSOR_POSITION,
__anon0e15bb040f02() 119         [](const AccessibilityActionParam& param) {
120             return param.accessibilityProperty->ActActionSetIndex(static_cast<int32_t>(param.setCursorIndex));
121         } },
122     { ActionType::ACCESSIBILITY_ACTION_SPAN_CLICK,
__anon0e15bb041002() 123         [](const AccessibilityActionParam& param) {
124             return param.accessibilityProperty->ActActionExecSubComponent(static_cast<int32_t>(param.spanId));
125         } },
126 };
127 
IsExtensionComponent(const RefPtr<NG::UINode> & node)128 bool IsExtensionComponent(const RefPtr<NG::UINode>& node)
129 {
130     return node && (node->GetTag() == V2::UI_EXTENSION_COMPONENT_ETS_TAG
131         || node->GetTag() == V2::EMBEDDED_COMPONENT_ETS_TAG
132         || node->GetTag() == V2::ISOLATED_COMPONENT_ETS_TAG);
133 }
134 
IsIsolatedComponent(const RefPtr<NG::UINode> & node)135 bool IsIsolatedComponent(const RefPtr<NG::UINode>& node)
136 {
137     return node && (node->GetTag() == V2::ISOLATED_COMPONENT_ETS_TAG);
138 }
139 
IsUIExtensionShowPlaceholder(const RefPtr<NG::UINode> & node)140 bool IsUIExtensionShowPlaceholder(const RefPtr<NG::UINode>& node)
141 {
142     CHECK_NULL_RETURN(node, true);
143     if (node->GetTag() == V2::ISOLATED_COMPONENT_ETS_TAG) {
144         return false;
145     }
146 #ifdef WINDOW_SCENE_SUPPORTED
147     auto pipeline = node->GetContextRefPtr();
148     CHECK_NULL_RETURN(pipeline, true);
149     auto manager = pipeline->GetUIExtensionManager();
150     CHECK_NULL_RETURN(manager, true);
151     return manager->IsShowPlaceholder(node->GetId());
152 #endif
153     return true;
154 }
155 
ConvertStrToEventType(const std::string & type)156 Accessibility::EventType ConvertStrToEventType(const std::string& type)
157 {
158     // static linear map must be sorted by key.
159     static const LinearMapNode<Accessibility::EventType> eventTypeMap[] = {
160         { ACCESSIBILITY_CLEAR_FOCUS_EVENT, Accessibility::EventType::TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED_EVENT },
161         { ACCESSIBILITY_FOCUSED_EVENT, Accessibility::EventType::TYPE_VIEW_ACCESSIBILITY_FOCUSED_EVENT },
162         { DOM_CLICK, Accessibility::EventType::TYPE_VIEW_CLICKED_EVENT },
163         { DOM_FOCUS, Accessibility::EventType::TYPE_VIEW_FOCUSED_EVENT },
164         { DOM_LONG_PRESS, Accessibility::EventType::TYPE_VIEW_LONG_CLICKED_EVENT },
165         { MOUSE_HOVER_ENTER, Accessibility::EventType::TYPE_VIEW_HOVER_ENTER_EVENT },
166         { MOUSE_HOVER_EXIT, Accessibility::EventType::TYPE_VIEW_HOVER_EXIT_EVENT },
167         { PAGE_CHANGE_EVENT, Accessibility::EventType::TYPE_PAGE_STATE_UPDATE },
168         { SCROLL_END_EVENT, Accessibility::EventType::TYPE_VIEW_SCROLLED_EVENT },
169         { SCROLL_START_EVENT, Accessibility::EventType::TYPE_VIEW_SCROLLED_START },
170         { DOM_SELECTED, Accessibility::EventType::TYPE_VIEW_SELECTED_EVENT },
171         { TEXT_CHANGE_EVENT, Accessibility::EventType::TYPE_VIEW_TEXT_UPDATE_EVENT },
172         { DOM_TOUCH_END, Accessibility::EventType::TYPE_TOUCH_END },
173         { DOM_TOUCH_START, Accessibility::EventType::TYPE_TOUCH_BEGIN },
174     };
175     Accessibility::EventType eventType = Accessibility::EventType::TYPE_VIEW_INVALID;
176     int64_t idx = BinarySearchFindIndex(eventTypeMap, ArraySize(eventTypeMap), type.c_str());
177     if (idx >= 0) {
178         eventType = eventTypeMap[idx].value;
179     }
180     return eventType;
181 }
182 
ConvertAceEventType(AccessibilityEventType type)183 Accessibility::EventType ConvertAceEventType(AccessibilityEventType type)
184 {
185     static const LinearEnumMapNode<AccessibilityEventType, Accessibility::EventType> eventTypeMap[] = {
186         { AccessibilityEventType::CLICK, Accessibility::EventType::TYPE_VIEW_CLICKED_EVENT },
187         { AccessibilityEventType::LONG_PRESS, Accessibility::EventType::TYPE_VIEW_LONG_CLICKED_EVENT },
188         { AccessibilityEventType::SELECTED, Accessibility::EventType::TYPE_VIEW_SELECTED_EVENT },
189         { AccessibilityEventType::FOCUS, Accessibility::EventType::TYPE_VIEW_FOCUSED_EVENT },
190         { AccessibilityEventType::TEXT_CHANGE, Accessibility::EventType::TYPE_VIEW_TEXT_UPDATE_EVENT },
191         { AccessibilityEventType::HOVER_ENTER_EVENT, Accessibility::EventType::TYPE_VIEW_HOVER_ENTER_EVENT },
192         { AccessibilityEventType::PAGE_CHANGE, Accessibility::EventType::TYPE_PAGE_STATE_UPDATE },
193         { AccessibilityEventType::HOVER_EXIT_EVENT, Accessibility::EventType::TYPE_VIEW_HOVER_EXIT_EVENT },
194         { AccessibilityEventType::CHANGE, Accessibility::EventType::TYPE_PAGE_CONTENT_UPDATE },
195         { AccessibilityEventType::COMPONENT_CHANGE, Accessibility::EventType::TYPE_VIEW_TEXT_UPDATE_EVENT },
196         { AccessibilityEventType::SCROLL_END, Accessibility::EventType::TYPE_VIEW_SCROLLED_EVENT },
197         { AccessibilityEventType::TEXT_SELECTION_UPDATE,
198             Accessibility::EventType::TYPE_VIEW_TEXT_SELECTION_UPDATE_EVENT },
199         { AccessibilityEventType::ACCESSIBILITY_FOCUSED,
200             Accessibility::EventType::TYPE_VIEW_ACCESSIBILITY_FOCUSED_EVENT },
201         { AccessibilityEventType::ACCESSIBILITY_FOCUS_CLEARED,
202             Accessibility::EventType::TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED_EVENT },
203         { AccessibilityEventType::TEXT_MOVE_UNIT, Accessibility::EventType::TYPE_VIEW_TEXT_MOVE_UNIT_EVENT },
204         { AccessibilityEventType::REQUEST_FOCUS, Accessibility::EventType::TYPE_VIEW_REQUEST_FOCUS_FOR_ACCESSIBILITY },
205         { AccessibilityEventType::SCROLL_START, Accessibility::EventType::TYPE_VIEW_SCROLLED_START },
206         { AccessibilityEventType::PAGE_CLOSE, Accessibility::EventType::TYPE_PAGE_CLOSE },
207         { AccessibilityEventType::ANNOUNCE_FOR_ACCESSIBILITY,
208             Accessibility::EventType::TYPE_VIEW_ANNOUNCE_FOR_ACCESSIBILITY },
209         { AccessibilityEventType::PAGE_OPEN, Accessibility::EventType::TYPE_PAGE_OPEN },
210         { AccessibilityEventType::ELEMENT_INFO_CHANGE, Accessibility::EventType::TYPE_ELEMENT_INFO_CHANGE },
211     };
212     Accessibility::EventType eventType = Accessibility::EventType::TYPE_VIEW_INVALID;
213     int64_t idx = BinarySearchFindIndex(eventTypeMap, ArraySize(eventTypeMap), type);
214     if (idx >= 0) {
215         eventType = eventTypeMap[idx].value;
216     }
217     return eventType;
218 }
219 
ConvertAceAction(AceAction aceAction)220 ActionType ConvertAceAction(AceAction aceAction)
221 {
222     static const ActionTable actionTable[] = {
223         { AceAction::ACTION_CLICK, ActionType::ACCESSIBILITY_ACTION_CLICK },
224         { AceAction::ACTION_LONG_CLICK, ActionType::ACCESSIBILITY_ACTION_LONG_CLICK },
225         { AceAction::ACTION_SCROLL_FORWARD, ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD },
226         { AceAction::ACTION_SCROLL_BACKWARD, ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD },
227         { AceAction::ACTION_FOCUS, ActionType::ACCESSIBILITY_ACTION_FOCUS },
228         { AceAction::ACTION_CLEAR_FOCUS, ActionType::ACCESSIBILITY_ACTION_CLEAR_FOCUS },
229         { AceAction::ACTION_ACCESSIBILITY_FOCUS, ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS },
230         { AceAction::ACTION_CLEAR_ACCESSIBILITY_FOCUS, ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS },
231         { AceAction::ACTION_NEXT_AT_MOVEMENT_GRANULARITY, ActionType::ACCESSIBILITY_ACTION_NEXT_TEXT },
232         { AceAction::ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, ActionType::ACCESSIBILITY_ACTION_PREVIOUS_TEXT },
233         { AceAction::ACTION_SET_TEXT, ActionType::ACCESSIBILITY_ACTION_SET_TEXT },
234         { AceAction::ACTION_COPY, ActionType::ACCESSIBILITY_ACTION_COPY },
235         { AceAction::ACTION_PASTE, ActionType::ACCESSIBILITY_ACTION_PASTE },
236         { AceAction::ACTION_CUT, ActionType::ACCESSIBILITY_ACTION_CUT },
237         { AceAction::ACTION_SELECT, ActionType::ACCESSIBILITY_ACTION_SELECT },
238         { AceAction::ACTION_CLEAR_SELECTION, ActionType::ACCESSIBILITY_ACTION_CLEAR_SELECTION },
239         { AceAction::ACTION_SET_SELECTION, ActionType::ACCESSIBILITY_ACTION_SET_SELECTION },
240         { AceAction::ACTION_SET_CURSOR_POSITION, ActionType::ACCESSIBILITY_ACTION_SET_CURSOR_POSITION },
241         { AceAction::ACTION_EXEC_SUB_COMPONENT, ActionType::ACCESSIBILITY_ACTION_SPAN_CLICK },
242     };
243     for (const auto& item : actionTable) {
244         if (aceAction == item.aceAction) {
245             return item.action;
246         }
247     }
248     return ActionType::ACCESSIBILITY_ACTION_INVALID;
249 }
250 
ConvertAccessibilityValue(const AccessibilityValue & value)251 inline RangeInfo ConvertAccessibilityValue(const AccessibilityValue& value)
252 {
253     return RangeInfo(value.min, value.max, value.current);
254 }
255 
ConvertToCardAccessibilityId(int64_t nodeId,int64_t cardId,int64_t rootNodeId)256 int64_t ConvertToCardAccessibilityId(int64_t nodeId, int64_t cardId, int64_t rootNodeId)
257 {
258     // result is integer total ten digits, top five for agp virtualViewId, end five for ace nodeId,
259     // for example agp virtualViewId is 32, ace nodeId is 1000001, convert to result is 00032 10001.
260     int64_t result = 0;
261     if (nodeId == rootNodeId + ROOT_STACK_BASE) {
262         // for example agp virtualViewId is 32 root node is 2100000, convert to result is 00032 21000.
263         result = cardId * CARD_BASE + (static_cast<int64_t>(nodeId / CARD_BASE)) * CARD_ROOT_NODE_ID_RATION +
264                  nodeId % CARD_BASE;
265     } else {
266         result = cardId * CARD_BASE + (static_cast<int64_t>(nodeId / DOM_ROOT_NODE_ID_BASE)) * CARD_NODE_ID_RATION +
267                  nodeId % DOM_ROOT_NODE_ID_BASE;
268     }
269     return result;
270 }
271 
UpdateAccessibilityNodeInfo(const RefPtr<AccessibilityNode> & node,AccessibilityElementInfo & nodeInfo,const RefPtr<JsAccessibilityManager> & manager,int windowId)272 void UpdateAccessibilityNodeInfo(const RefPtr<AccessibilityNode>& node, AccessibilityElementInfo& nodeInfo,
273     const RefPtr<JsAccessibilityManager>& manager, int windowId)
274 {
275     int leftTopX = static_cast<int>(node->GetLeft()) + manager->GetWindowLeft(node->GetWindowId());
276     int leftTopY = static_cast<int>(node->GetTop()) + manager->GetWindowTop(node->GetWindowId());
277     int rightBottomX = leftTopX + static_cast<int>(node->GetWidth());
278     int rightBottomY = leftTopY + static_cast<int>(node->GetHeight());
279     if (manager->isOhosHostCard()) {
280         int64_t id = ConvertToCardAccessibilityId(node->GetNodeId(), manager->GetCardId(), manager->GetRootNodeId());
281         nodeInfo.SetAccessibilityId(id);
282         if (node->GetParentId() == -1) {
283             nodeInfo.SetParent(-1);
284         } else {
285             nodeInfo.SetParent(
286                 ConvertToCardAccessibilityId(node->GetParentId(), manager->GetCardId(), manager->GetRootNodeId()));
287         }
288         leftTopX = static_cast<int>(node->GetLeft() + manager->GetCardOffset().GetX());
289         leftTopY = static_cast<int>(node->GetTop() + manager->GetCardOffset().GetY());
290         rightBottomX = leftTopX + static_cast<int>(node->GetWidth());
291         rightBottomY = leftTopY + static_cast<int>(node->GetHeight());
292         Accessibility::Rect bounds(leftTopX, leftTopY, rightBottomX, rightBottomY);
293         nodeInfo.SetRectInScreen(bounds);
294     } else {
295         if (node->GetTag() == SIDEBARCONTAINER_TAG) {
296             Rect sideBarRect = node->GetRect();
297             for (const auto& childNode : node->GetChildList()) {
298                 sideBarRect = sideBarRect.CombineRect(childNode->GetRect());
299             }
300             leftTopX = static_cast<int>(sideBarRect.Left()) + manager->GetWindowLeft(node->GetWindowId());
301             leftTopY = static_cast<int>(sideBarRect.Top()) + manager->GetWindowTop(node->GetWindowId());
302             rightBottomX = static_cast<int>(sideBarRect.Right()) + manager->GetWindowLeft(node->GetWindowId());
303             rightBottomY = static_cast<int>(sideBarRect.Bottom()) + manager->GetWindowTop(node->GetWindowId());
304         }
305         Accessibility::Rect bounds(leftTopX, leftTopY, rightBottomX, rightBottomY);
306         nodeInfo.SetRectInScreen(bounds);
307         nodeInfo.SetComponentId(static_cast<int64_t>(node->GetNodeId()));
308         nodeInfo.SetParent(static_cast<int64_t>(node->GetParentId()));
309     }
310 
311     if (node->GetParentId() == -1) {
312         const auto& children = node->GetChildList();
313         if (!children.empty()) {
314             auto lastChildNode = manager->GetAccessibilityNodeById(children.back()->GetNodeId());
315             if (lastChildNode) {
316                 rightBottomX = leftTopX + static_cast<int>(lastChildNode->GetWidth());
317                 rightBottomY = leftTopY + static_cast<int>(lastChildNode->GetHeight());
318                 Accessibility::Rect bounds(leftTopX, leftTopY, rightBottomX, rightBottomY);
319                 nodeInfo.SetRectInScreen(bounds);
320             }
321         }
322         nodeInfo.SetParent(INVALID_PARENT_ID);
323     }
324     if (node->GetNodeId() == 0) {
325         nodeInfo.SetParent(INVALID_PARENT_ID);
326     }
327     nodeInfo.SetPagePath(manager->GetPagePath());
328     nodeInfo.SetWindowId(windowId);
329     nodeInfo.SetChecked(node->GetCheckedState());
330     nodeInfo.SetEnabled(node->GetEnabledState());
331     nodeInfo.SetFocused(node->GetFocusedState());
332     nodeInfo.SetSelected(node->GetSelectedState());
333     nodeInfo.SetCheckable(node->GetCheckableState());
334     nodeInfo.SetClickable(node->GetClickableState());
335     nodeInfo.SetFocusable(node->GetFocusableState());
336     nodeInfo.SetScrollable(node->GetScrollableState());
337     nodeInfo.SetLongClickable(node->GetLongClickableState());
338     nodeInfo.SetEditable(node->GetEditable());
339     nodeInfo.SetPluraLineSupported(node->GetIsMultiLine());
340     nodeInfo.SetPassword(node->GetIsPassword());
341     nodeInfo.SetTextLengthLimit(node->GetMaxTextLength());
342     nodeInfo.SetSelectedBegin(node->GetTextSelectionStart());
343     nodeInfo.SetSelectedEnd(node->GetTextSelectionEnd());
344     nodeInfo.SetVisible(node->GetShown() && node->GetVisible());
345     nodeInfo.SetHint(node->GetHintText());
346     std::string accessibilityLabel = node->GetAccessibilityLabel();
347     nodeInfo.SetLabeled(atol(accessibilityLabel.c_str()));
348     nodeInfo.SetError(node->GetErrorText());
349     nodeInfo.SetComponentResourceId(node->GetJsComponentId());
350     nodeInfo.SetInspectorKey(node->GetJsComponentId());
351     RangeInfo rangeInfo = ConvertAccessibilityValue(node->GetAccessibilityValue());
352     nodeInfo.SetRange(rangeInfo);
353     nodeInfo.SetInputType(static_cast<int>(node->GetTextInputType()));
354     nodeInfo.SetComponentType(node->GetTag());
355     GridInfo gridInfo(
356         node->GetCollectionInfo().rows, node->GetCollectionInfo().columns, (nodeInfo.IsPluraLineSupported() ? 0 : 1));
357     nodeInfo.SetGrid(gridInfo);
358     nodeInfo.SetAccessibilityFocus(node->GetAccessibilityFocusedState());
359     nodeInfo.SetPageId(node->GetPageId());
360 
361     int32_t row = node->GetCollectionItemInfo().row;
362     int32_t column = node->GetCollectionItemInfo().column;
363     GridItemInfo gridItemInfo(row, row, column, column, false, nodeInfo.IsSelected());
364     nodeInfo.SetGridItem(gridItemInfo);
365     nodeInfo.SetBundleName(AceApplicationInfo::GetInstance().GetPackageName());
366 
367     if (node->GetTag() == LIST_TAG) {
368         nodeInfo.SetItemCounts(node->GetListItemCounts());
369         nodeInfo.SetBeginIndex(node->GetListBeginIndex());
370         nodeInfo.SetEndIndex(node->GetListEndIndex());
371     }
372     if (node->GetIsPassword()) {
373         std::string strStar(node->GetText().size(), '*');
374         nodeInfo.SetContent(strStar);
375     } else {
376         nodeInfo.SetContent(node->GetText());
377     }
378 
379     auto supportAceActions = node->GetSupportAction();
380     std::vector<ActionType> actions(supportAceActions.size());
381 
382     for (auto it = supportAceActions.begin(); it != supportAceActions.end(); ++it) {
383         AccessibleAction action(ConvertAceAction(*it), "ace");
384         nodeInfo.AddAction(action);
385     }
386 
387     if (node->GetImportantForAccessibility() == NG::AccessibilityProperty::Level::YES_STR) {
388         actions.emplace_back(ActionType::ACCESSIBILITY_ACTION_FOCUS);
389         nodeInfo.SetCheckable(true);
390     } else if (node->GetImportantForAccessibility() == NG::AccessibilityProperty::Level::NO_STR ||
391                node->GetImportantForAccessibility() == NG::AccessibilityProperty::Level::NO_HIDE_DESCENDANTS) {
392         nodeInfo.SetVisible(false);
393     }
394 
395     manager->UpdateNodeChildIds(node);
396     for (const auto& child : node->GetChildIds()) {
397         nodeInfo.AddChild(child);
398     }
399 
400 #ifdef ACE_DEBUG
401     std::string actionForLog;
402     for (const auto& action : supportAceActions) {
403         if (!actionForLog.empty()) {
404             actionForLog.append(",");
405         }
406         actionForLog.append(std::to_string(static_cast<int32_t>(action)));
407     }
408 #endif
409 }
410 
UpdateCacheInfo(std::list<AccessibilityElementInfo> & infos,uint32_t mode,const RefPtr<AccessibilityNode> & node,const RefPtr<JsAccessibilityManager> & jsAccessibilityManager,int windowId)411 void UpdateCacheInfo(std::list<AccessibilityElementInfo>& infos, uint32_t mode, const RefPtr<AccessibilityNode>& node,
412     const RefPtr<JsAccessibilityManager>& jsAccessibilityManager, int windowId)
413 {
414     TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "elementId: %{public}d, mode: %{public}d", node->GetNodeId(), mode);
415     // parent
416     uint32_t umode = mode;
417     if (umode & static_cast<uint32_t>(PREFETCH_PREDECESSORS)) {
418         if (node->GetParentId() != -1 && node->GetParentId() != DEFAULT_PARENT_ID) {
419             AccessibilityElementInfo parentNodeInfo;
420             UpdateAccessibilityNodeInfo(node->GetParentNode(), parentNodeInfo, jsAccessibilityManager, windowId);
421             infos.emplace_back(parentNodeInfo);
422         }
423     }
424     // sister/brothers
425     if (umode & static_cast<uint32_t>(PREFETCH_SIBLINGS)) {
426         if (node->GetParentId() != -1 && node->GetParentId() != DEFAULT_PARENT_ID) {
427             for (const auto& item : node->GetParentNode()->GetChildList()) {
428                 if (node->GetNodeId() != item->GetNodeId()) {
429                     AccessibilityElementInfo siblingNodeInfo;
430                     UpdateAccessibilityNodeInfo(item, siblingNodeInfo, jsAccessibilityManager, windowId);
431                     infos.emplace_back(siblingNodeInfo);
432                 }
433             }
434         }
435     }
436     // children
437     if (umode & static_cast<uint32_t>(PREFETCH_CHILDREN)) {
438         for (const auto& item : node->GetChildList()) {
439             AccessibilityElementInfo childNodeInfo;
440             UpdateAccessibilityNodeInfo(item, childNodeInfo, jsAccessibilityManager, windowId);
441             infos.emplace_back(childNodeInfo);
442         }
443     }
444 
445     // get all children
446     if (umode & static_cast<uint32_t>(PREFETCH_RECURSIVE_CHILDREN)) {
447         std::list<RefPtr<AccessibilityNode>> children;
448         for (const auto& item : node->GetChildList()) {
449             children.emplace_back(item);
450         }
451 
452         while (!children.empty()) {
453             auto parent = children.front();
454             children.pop_front();
455             AccessibilityElementInfo childNodeInfo;
456             UpdateAccessibilityNodeInfo(parent, childNodeInfo, jsAccessibilityManager, windowId);
457             infos.push_back(childNodeInfo);
458             for (const auto& item : parent->GetChildList()) {
459                 children.emplace_back(item);
460             }
461         }
462     }
463 }
464 
SortAccessibilityInfosByBreadth(std::list<AccessibilityElementInfo> & infos,std::list<int64_t> & accessibilityIdQueue,std::list<AccessibilityElementInfo> & output)465 void SortAccessibilityInfosByBreadth(std::list<AccessibilityElementInfo>& infos,
466     std::list<int64_t>& accessibilityIdQueue, std::list<AccessibilityElementInfo>& output)
467 {
468     while (!accessibilityIdQueue.empty()) {
469         auto accessibilityId = accessibilityIdQueue.front();
470         accessibilityIdQueue.pop_front();
471         for (std::list<AccessibilityElementInfo>::iterator info = infos.begin(); info != infos.end(); ++info) {
472             if (accessibilityId != info->GetAccessibilityId()) {
473                 continue;
474             }
475             for (auto& child : info->GetChildIds()) {
476                 accessibilityIdQueue.emplace_back(child);
477             }
478             output.emplace_back(*info);
479             infos.erase(info);
480             break;
481         }
482         SortAccessibilityInfosByBreadth(infos, accessibilityIdQueue, output);
483     }
484 }
485 
SortExtensionAccessibilityInfo(std::list<AccessibilityElementInfo> & infos,int64_t rootAccessibilityId)486 void SortExtensionAccessibilityInfo(std::list<AccessibilityElementInfo>& infos, int64_t rootAccessibilityId)
487 {
488     auto input = infos;
489     infos.clear();
490     std::list<int64_t> accessibilityIdQueue;
491     accessibilityIdQueue.emplace_back(rootAccessibilityId);
492     SortAccessibilityInfosByBreadth(input, accessibilityIdQueue, infos);
493 }
494 
ConvertExtensionAccessibilityId(AccessibilityElementInfo & info,const RefPtr<NG::FrameNode> & extensionNode,int64_t uiExtensionOffset,AccessibilityElementInfo & parentInfo)495 void ConvertExtensionAccessibilityId(AccessibilityElementInfo& info, const RefPtr<NG::FrameNode>& extensionNode,
496     int64_t uiExtensionOffset, AccessibilityElementInfo& parentInfo)
497 {
498     auto extensionAbilityId =
499             extensionNode->WrapExtensionAbilityId(uiExtensionOffset, info.GetAccessibilityId());
500     info.SetAccessibilityId(extensionAbilityId);
501     auto parentNodeId =
502         extensionNode->WrapExtensionAbilityId(uiExtensionOffset, info.GetParentNodeId());
503     info.SetParent(parentNodeId);
504     auto childIds = info.GetChildIds();
505     for (auto& child : childIds) {
506         info.RemoveChild(child);
507         info.AddChild(extensionNode->WrapExtensionAbilityId(uiExtensionOffset, child));
508     }
509     if (V2::ROOT_ETS_TAG == info.GetComponentType()) {
510         for (auto& child : info.GetChildIds()) {
511             parentInfo.AddChild(child);
512         }
513     }
514 }
515 
ConvertExtensionAccessibilityNodeId(std::list<AccessibilityElementInfo> & infos,const RefPtr<NG::FrameNode> & extensionNode,int64_t uiExtensionOffset,AccessibilityElementInfo & parentInfo)516 void ConvertExtensionAccessibilityNodeId(std::list<AccessibilityElementInfo>& infos,
517     const RefPtr<NG::FrameNode>& extensionNode, int64_t uiExtensionOffset,
518     AccessibilityElementInfo& parentInfo)
519 {
520     CHECK_NULL_VOID(extensionNode);
521     for (auto& accessibilityElementInfo : infos) {
522         ConvertExtensionAccessibilityId(accessibilityElementInfo, extensionNode, uiExtensionOffset, parentInfo);
523     }
524     for (auto& accessibilityElementInfo : infos) {
525         if (std::find(parentInfo.GetChildIds().begin(), parentInfo.GetChildIds().end(),
526             accessibilityElementInfo.GetAccessibilityId()) != parentInfo.GetChildIds().end()) {
527             accessibilityElementInfo.SetParent(extensionNode->GetAccessibilityId());
528         }
529     }
530 }
531 
BoolToString(bool tag)532 inline std::string BoolToString(bool tag)
533 {
534     return tag ? "true" : "false";
535 }
536 
ConvertInputTypeToString(AceTextCategory type)537 std::string ConvertInputTypeToString(AceTextCategory type)
538 {
539     switch (type) {
540         case AceTextCategory::INPUT_TYPE_DEFAULT:
541             return "INPUT_TYPE_DEFAULT";
542         case AceTextCategory::INPUT_TYPE_TEXT:
543             return "INPUT_TYPE_TEXT";
544         case AceTextCategory::INPUT_TYPE_EMAIL:
545             return "INPUT_TYPE_EMAIL";
546         case AceTextCategory::INPUT_TYPE_DATE:
547             return "INPUT_TYPE_DATE";
548         case AceTextCategory::INPUT_TYPE_TIME:
549             return "INPUT_TYPE_TIME";
550         case AceTextCategory::INPUT_TYPE_NUMBER:
551             return "INPUT_TYPE_NUMBER";
552         case AceTextCategory::INPUT_TYPE_PASSWORD:
553             return "INPUT_TYPE_PASSWORD";
554         case AceTextCategory::INPUT_TYPE_PHONENUMBER:
555             return "INPUT_TYPE_PHONENUMBER";
556         case AceTextCategory::INPUT_TYPE_USER_NAME:
557             return "INPUT_TYPE_USER_NAME";
558         case AceTextCategory::INPUT_TYPE_NEW_PASSWORD:
559             return "INPUT_TYPE_NEW_PASSWORD";
560         default:
561             return "illegal input type";
562     }
563 }
564 
FindAccessibilityFocus(const RefPtr<AccessibilityNode> & node,RefPtr<AccessibilityNode> & resultNode)565 bool FindAccessibilityFocus(const RefPtr<AccessibilityNode>& node, RefPtr<AccessibilityNode>& resultNode)
566 {
567     CHECK_NULL_RETURN(node, false);
568     if (node->GetAccessibilityFocusedState()) {
569         resultNode = node;
570         return true;
571     }
572     if (!node->GetChildList().empty()) {
573         for (const auto& item : node->GetChildList()) {
574             if (resultNode != nullptr) {
575                 return true;
576             }
577             if (FindAccessibilityFocus(item, resultNode)) {
578                 return true;
579             }
580         }
581     }
582 
583     return false;
584 }
585 
FindFocusedExtensionElementInfoNG(const SearchParameter & searchParam,const RefPtr<NG::FrameNode> & node,Accessibility::AccessibilityElementInfo & info)586 void FindFocusedExtensionElementInfoNG(const SearchParameter& searchParam,
587     const RefPtr<NG::FrameNode>& node, Accessibility::AccessibilityElementInfo& info)
588 {
589     if (NG::UI_EXTENSION_OFFSET_MIN < (searchParam.uiExtensionOffset + 1)) {
590         node->FindFocusedExtensionElementInfoNG(searchParam.nodeId, searchParam.mode,
591             searchParam.uiExtensionOffset / NG::UI_EXTENSION_ID_FACTOR, info);
592     } else {
593         info.SetValidElement(false);
594     }
595 }
596 
SetUiExtensionAbilityParentIdForFocus(const RefPtr<NG::UINode> & uiExtensionNode,const int64_t uiExtensionOffset,Accessibility::AccessibilityElementInfo & info)597 void SetUiExtensionAbilityParentIdForFocus(const RefPtr<NG::UINode>& uiExtensionNode,
598     const int64_t uiExtensionOffset, Accessibility::AccessibilityElementInfo& info)
599 {
600     auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiExtensionNode);
601     if (frameNode) {
602         auto parentId = info.GetParentNodeId();
603         AccessibilityElementInfo parentInfo;
604         ConvertExtensionAccessibilityId(info, frameNode, uiExtensionOffset, parentInfo);
605         if (parentId == NG::UI_EXTENSION_ROOT_ID) {
606             info.SetParent(frameNode->GetAccessibilityId());
607         }
608     }
609 }
610 
611 RefPtr<NG::FrameNode> GetFramenodeByAccessibilityId(const RefPtr<NG::FrameNode>& root, int64_t id);
612 
FindAccessibilityFocus(const RefPtr<NG::UINode> & node,int32_t focusType,Accessibility::AccessibilityElementInfo & info,const int64_t uiExtensionOffset,const RefPtr<PipelineBase> & context,int64_t currentFocusNodeId)613 RefPtr<NG::FrameNode> FindAccessibilityFocus(const RefPtr<NG::UINode>& node,
614     int32_t focusType, Accessibility::AccessibilityElementInfo& info,
615     const int64_t uiExtensionOffset, const RefPtr<PipelineBase>& context, int64_t currentFocusNodeId)
616 {
617     CHECK_NULL_RETURN(node, nullptr);
618     auto frameNode = AceType::DynamicCast<NG::FrameNode>(node);
619     if (frameNode) {
620         if (frameNode->GetRenderContext()->GetAccessibilityFocus().value_or(false)) {
621             auto node = GetFramenodeByAccessibilityId(frameNode, currentFocusNodeId);
622             return node;
623         }
624     }
625     if (node->GetChildren(true).empty()) {
626         return nullptr;
627     }
628     for (const auto& child : node->GetChildren(true)) {
629         auto extensionNode = AceType::DynamicCast<NG::FrameNode>(child);
630         if (IsIsolatedComponent(child) && extensionNode &&
631             !IsUIExtensionShowPlaceholder(extensionNode) &&
632             (extensionNode->GetUiExtensionId() > NG::UI_EXTENSION_UNKNOW_ID) &&
633             (((extensionNode->GetUiExtensionId() <= NG::UI_EXTENSION_ID_FIRST_MAX) &&
634             (NG::UI_EXTENSION_OFFSET_MAX == uiExtensionOffset)) ||
635             (extensionNode->GetUiExtensionId() <= NG::UI_EXTENSION_ID_OTHER_MAX))) {
636             SearchParameter transferSearchParam {NG::UI_EXTENSION_ROOT_ID, "", focusType, uiExtensionOffset};
637             OHOS::Ace::Framework::FindFocusedExtensionElementInfoNG(
638                 transferSearchParam, extensionNode, info);
639             if (info.GetAccessibilityId() < 0) {
640                 continue;
641             }
642             SetUiExtensionAbilityParentIdForFocus(extensionNode, uiExtensionOffset, info);
643             return extensionNode;
644         }
645         auto result = FindAccessibilityFocus(child, focusType, info, uiExtensionOffset, context, currentFocusNodeId);
646         if (result) {
647             return result;
648         }
649     }
650     return nullptr;
651 }
652 
FindInputFocus(const RefPtr<AccessibilityNode> & node,RefPtr<AccessibilityNode> & resultNode)653 bool FindInputFocus(const RefPtr<AccessibilityNode>& node, RefPtr<AccessibilityNode>& resultNode)
654 {
655     CHECK_NULL_RETURN(node, false);
656     if (!node->GetFocusedState() && (node->GetParentId() != -1)) {
657         return false;
658     }
659     if (node->GetFocusedState()) {
660         resultNode = node;
661     }
662     if (!node->GetChildList().empty()) {
663         for (const auto& item : node->GetChildList()) {
664             if (FindInputFocus(item, resultNode)) {
665                 return true;
666             }
667         }
668     }
669     return node->GetFocusedState();
670 }
671 
FindInputFocus(const RefPtr<NG::UINode> & node,int32_t focusType,Accessibility::AccessibilityElementInfo & info,const int64_t uiExtensionOffset,const RefPtr<PipelineBase> & context)672 RefPtr<NG::FrameNode> FindInputFocus(const RefPtr<NG::UINode>& node, int32_t focusType,
673     Accessibility::AccessibilityElementInfo& info, const int64_t uiExtensionOffset,
674     const RefPtr<PipelineBase>& context)
675 {
676     auto frameNode = AceType::DynamicCast<NG::FrameNode>(node);
677     CHECK_NULL_RETURN(frameNode, nullptr);
678     if (!(frameNode->GetFocusHub() ? frameNode->GetFocusHub()->IsCurrentFocus() : false)) {
679         return nullptr;
680     }
681     if (frameNode->GetFocusHub()->IsChild()) {
682         if (frameNode->IsInternal()) {
683             return frameNode->GetFocusParent();
684         }
685         return frameNode;
686     }
687     auto focusHub = frameNode->GetFocusHub();
688     RefPtr<NG::FrameNode> target;
689     focusHub->AnyChildFocusHub([&target, &info, context, focusType, uiExtensionOffset](
690                                    const RefPtr<NG::FocusHub>& focusChild) {
691         auto extensionNode = focusChild->GetFrameNode();
692         if ((extensionNode && IsIsolatedComponent(extensionNode)) &&
693             !IsUIExtensionShowPlaceholder(extensionNode) &&
694             (extensionNode->GetUiExtensionId() > NG::UI_EXTENSION_UNKNOW_ID) &&
695             (((extensionNode->GetUiExtensionId() <= NG::UI_EXTENSION_ID_FIRST_MAX) &&
696             (NG::UI_EXTENSION_OFFSET_MAX == uiExtensionOffset)) ||
697             (extensionNode->GetUiExtensionId() <= NG::UI_EXTENSION_ID_OTHER_MAX))) {
698             SearchParameter transferSearchParam {NG::UI_EXTENSION_ROOT_ID, "", focusType, uiExtensionOffset};
699             OHOS::Ace::Framework::FindFocusedExtensionElementInfoNG(
700                 transferSearchParam, extensionNode, info);
701             if (info.GetAccessibilityId() < 0) {
702                 return false;
703             }
704             SetUiExtensionAbilityParentIdForFocus(extensionNode, uiExtensionOffset, info);
705             target = extensionNode;
706             return true;
707         }
708         target = FindInputFocus(focusChild->GetFrameNode(), focusType, info, uiExtensionOffset, context);
709         return target ? true : false;
710     });
711     return target;
712 }
713 
FindText(const RefPtr<AccessibilityNode> & node,const std::string & text,std::list<RefPtr<AccessibilityNode>> & nodeList)714 void FindText(
715     const RefPtr<AccessibilityNode>& node, const std::string& text, std::list<RefPtr<AccessibilityNode>>& nodeList)
716 {
717     CHECK_NULL_VOID(node);
718     if (node->GetText().find(text) != std::string::npos) {
719         nodeList.push_back(node);
720     }
721     if (!node->GetChildList().empty()) {
722         for (const auto& child : node->GetChildList()) {
723             FindText(child, text, nodeList);
724         }
725     }
726 }
727 
FindText(const RefPtr<NG::UINode> & node,const std::string & text,std::list<RefPtr<NG::FrameNode>> & nodeList)728 void FindText(const RefPtr<NG::UINode>& node, const std::string& text, std::list<RefPtr<NG::FrameNode>>& nodeList)
729 {
730     CHECK_NULL_VOID(node);
731 
732     auto frameNode = AceType::DynamicCast<NG::FrameNode>(node);
733     if (frameNode && !frameNode->IsInternal()) {
734         if (frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>()->GetGroupText().find(text) !=
735             std::string::npos) {
736             nodeList.push_back(frameNode);
737         }
738     }
739 
740     if (!node->GetChildren(true).empty()) {
741         for (const auto& child : node->GetChildren(true)) {
742             FindText(child, text, nodeList);
743         }
744     }
745 }
746 
FindFrameNodeByAccessibilityId(int64_t id,const std::list<RefPtr<NG::UINode>> & children,std::queue<NG::UINode * > & nodes,RefPtr<NG::FrameNode> & result)747 bool FindFrameNodeByAccessibilityId(int64_t id, const std::list<RefPtr<NG::UINode>>& children,
748     std::queue<NG::UINode*>& nodes, RefPtr<NG::FrameNode>& result)
749 {
750     NG::FrameNode* frameNode = nullptr;
751     for (const auto& child : children) {
752         frameNode = AceType::DynamicCast<NG::FrameNode>(Referenced::RawPtr(child));
753         if (frameNode != nullptr && !frameNode->CheckAccessibilityLevelNo()) {
754             if (frameNode->GetAccessibilityId() == id) {
755                 result = AceType::DynamicCast<NG::FrameNode>(child);
756                 return true;
757             }
758         }
759         nodes.push(Referenced::RawPtr(child));
760     }
761     return false;
762 }
763 
GetFramenodeByAccessibilityId(const RefPtr<NG::FrameNode> & root,int64_t id)764 RefPtr<NG::FrameNode> GetFramenodeByAccessibilityId(const RefPtr<NG::FrameNode>& root, int64_t id)
765 {
766     CHECK_NULL_RETURN(root, nullptr);
767     if (root->GetAccessibilityId() == id) {
768         return root;
769     }
770     std::queue<NG::UINode*> nodes;
771     nodes.push(Referenced::RawPtr(root));
772     RefPtr<NG::FrameNode> frameNodeResult = nullptr;
773 
774     while (!nodes.empty()) {
775         auto current = nodes.front();
776         nodes.pop();
777         if (current->HasVirtualNodeAccessibilityProperty()) {
778             auto fnode = AceType::DynamicCast<NG::FrameNode>(current);
779             auto property = fnode->GetAccessibilityProperty<NG::AccessibilityProperty>();
780             const auto& children = std::list<RefPtr<NG::UINode>> { property->GetAccessibilityVirtualNode() };
781             if (FindFrameNodeByAccessibilityId(id, children, nodes, frameNodeResult)) {
782                 return frameNodeResult;
783             }
784         } else {
785             const auto& children = current->GetChildren(true);
786             if (FindFrameNodeByAccessibilityId(id, children, nodes, frameNodeResult)) {
787                 return frameNodeResult;
788             }
789         }
790         auto frameNode = AceType::DynamicCast<NG::FrameNode>(current);
791         if (!frameNode) {
792             continue;
793         }
794         auto overlayNode = frameNode->GetOverlayNode();
795         if (overlayNode) {
796             const auto& children = std::list<RefPtr<NG::UINode>> { overlayNode };
797             if (FindFrameNodeByAccessibilityId(id, children, nodes, frameNodeResult)) {
798                 return frameNodeResult;
799             }
800         }
801     }
802     return nullptr;
803 }
804 
GetFrameNodeParent(const RefPtr<NG::UINode> & uiNode,RefPtr<NG::FrameNode> & parent)805 void GetFrameNodeParent(const RefPtr<NG::UINode>& uiNode, RefPtr<NG::FrameNode>& parent)
806 {
807     if (AceType::InstanceOf<NG::FrameNode>(uiNode)) {
808         auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
809         if (!frameNode->IsInternal()) {
810             parent = frameNode;
811             return;
812         }
813     }
814     CHECK_NULL_VOID(uiNode);
815     auto parentNode = uiNode->GetParent();
816     GetFrameNodeParent(parentNode, parent);
817 }
818 
CheckFrameNodeByAccessibilityLevel(const RefPtr<NG::FrameNode> & frameNode,bool isParent)819 bool CheckFrameNodeByAccessibilityLevel(const RefPtr<NG::FrameNode>& frameNode, bool isParent)
820 {
821     return true;
822 }
823 
GetFrameNodeChildren(const RefPtr<NG::UINode> & uiNode,std::vector<int64_t> & children,int32_t pageId)824 void GetFrameNodeChildren(const RefPtr<NG::UINode>& uiNode, std::vector<int64_t>& children, int32_t pageId)
825 {
826     auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
827     if (AceType::InstanceOf<NG::FrameNode>(uiNode)) {
828         if (!frameNode->IsFirstVirtualNode()) {
829             CHECK_NULL_VOID(frameNode->IsActive());
830         }
831         if (uiNode->GetTag() == "stage") {
832         } else if (uiNode->GetTag() == "page") {
833             if (uiNode->GetPageId() != pageId) {
834                 return;
835             }
836         } else if (!frameNode->IsInternal() || frameNode->IsFirstVirtualNode()) {
837             if (CheckFrameNodeByAccessibilityLevel(frameNode, false)) {
838                 children.emplace_back(uiNode->GetAccessibilityId());
839                 return;
840             }
841         }
842     }
843 
844     if (frameNode) {
845         auto overlayNode = frameNode->GetOverlayNode();
846         if (overlayNode) {
847             GetFrameNodeChildren(overlayNode, children, pageId);
848         }
849     }
850 
851     if (AceType::InstanceOf<NG::FrameNode>(uiNode)) {
852         auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
853         auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
854         auto uiVirtualNode = accessibilityProperty->GetAccessibilityVirtualNode();
855         if (uiVirtualNode != nullptr) {
856             auto virtualNode = AceType::DynamicCast<NG::FrameNode>(uiVirtualNode);
857             if (virtualNode != nullptr) {
858                 GetFrameNodeChildren(virtualNode, children, pageId);
859                 return;
860             }
861         }
862     }
863 
864     for (const auto& frameChild : uiNode->GetChildren(true)) {
865         GetFrameNodeChildren(frameChild, children, pageId);
866     }
867 }
868 
GetFrameNodeChildren(const RefPtr<NG::UINode> & uiNode,std::list<RefPtr<NG::FrameNode>> & children,int32_t pageId=-1)869 void GetFrameNodeChildren(
870     const RefPtr<NG::UINode>& uiNode, std::list<RefPtr<NG::FrameNode>>& children, int32_t pageId = -1)
871 {
872     if (AceType::InstanceOf<NG::FrameNode>(uiNode)) {
873         auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
874         CHECK_NULL_VOID(frameNode->IsActive());
875         if (uiNode->GetTag() == "page") {
876             if (pageId != -1 && uiNode->GetPageId() != pageId) {
877                 return;
878             }
879         } else if (!frameNode->IsInternal() && uiNode->GetTag() != "stage") {
880             if (CheckFrameNodeByAccessibilityLevel(frameNode, false)) {
881                 children.emplace_back(frameNode);
882                 return;
883             }
884         }
885     }
886 
887     auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
888     if (frameNode) {
889         auto overlayNode = frameNode->GetOverlayNode();
890         if (overlayNode) {
891             GetFrameNodeChildren(overlayNode, children, pageId);
892         }
893     }
894 
895     if (AceType::InstanceOf<NG::FrameNode>(uiNode)) {
896         auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
897         auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
898         auto uiVirtualNode = accessibilityProperty->GetAccessibilityVirtualNode();
899         if (uiVirtualNode != nullptr) {
900             auto virtualNode = AceType::DynamicCast<NG::FrameNode>(uiVirtualNode);
901             if (virtualNode != nullptr) {
902                 GetFrameNodeChildren(virtualNode, children, pageId);
903                 return;
904             }
905         }
906     }
907 
908     for (const auto& frameChild : uiNode->GetChildren(true)) {
909         GetFrameNodeChildren(frameChild, children, pageId);
910     }
911 }
912 
GetNodeAccessibilityVisible(const RefPtr<NG::FrameNode> & frameNode,bool isAllAncestorAccessibilityVisible,bool clipVisible)913 bool GetNodeAccessibilityVisible(const RefPtr<NG::FrameNode>& frameNode, bool isAllAncestorAccessibilityVisible,
914                                  bool clipVisible)
915 {
916     if (frameNode->IsFirstVirtualNode()) {
917         return frameNode->IsVisible() && isAllAncestorAccessibilityVisible && clipVisible;
918     } else {
919         return frameNode->IsActive() && frameNode->IsVisible() && isAllAncestorAccessibilityVisible && clipVisible;
920     }
921 }
922 
ProcessParentFrameNode(const RefPtr<NG::UINode> & parent,std::string & parentPath,bool & isAllAncestorAccessibilityVisible)923 bool ProcessParentFrameNode(
924     const RefPtr<NG::UINode>& parent, std::string& parentPath, bool& isAllAncestorAccessibilityVisible)
925 {
926     auto parentFrameNode = AceType::DynamicCast<NG::FrameNode>(parent);
927     if (parentFrameNode->CheckAccessibilityLevelNo()) {
928         return false;
929     }
930 
931     parentPath += "Parent ID: " + std::to_string(parent->GetAccessibilityId()) +
932                   " IsActive: " + std::to_string(parentFrameNode->IsActive()) +
933                   " IsVisible: " + std::to_string(parentFrameNode->IsVisible()) +
934                   " AccessibilityVisible: " + std::to_string(parentFrameNode->GetAccessibilityVisible()) +
935                   " Parent Tag: " + parent->GetTag() + " | ";
936 
937     if (parent->GetTag() == V2::PAGE_ETS_TAG) {
938         isAllAncestorAccessibilityVisible = parentFrameNode->GetAccessibilityVisible();
939     } else if (parentFrameNode->IsFirstVirtualNode()) {
940         isAllAncestorAccessibilityVisible = parentFrameNode->IsVisible();
941     } else {
942         isAllAncestorAccessibilityVisible = parentFrameNode->IsActive() && parentFrameNode->IsVisible();
943     }
944 
945     return !isAllAncestorAccessibilityVisible;
946 }
947 
GetInitialParent(const RefPtr<NG::UINode> & uiNode)948 RefPtr<NG::UINode> GetInitialParent(const RefPtr<NG::UINode>& uiNode)
949 {
950     if (AceType::InstanceOf<NG::FrameNode>(uiNode)) {
951         auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
952         if (frameNode->IsFirstVirtualNode()) {
953             auto weakNode = frameNode->GetVirtualNodeParent();
954             return weakNode.Upgrade();
955         } else {
956             return uiNode->GetParent();
957         }
958     }
959     return nullptr;
960 }
961 
SetRootAccessibilityVisible(const RefPtr<NG::UINode> & uiNode,AccessibilityElementInfo & nodeInfo)962 void SetRootAccessibilityVisible(const RefPtr<NG::UINode>& uiNode, AccessibilityElementInfo& nodeInfo)
963 {
964     RefPtr<NG::UINode> parent = GetInitialParent(uiNode);
965     bool isAllAncestorAccessibilityVisible = true;
966     bool clipVisible = true;
967     auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
968     CHECK_NULL_VOID(frameNode);
969     OHOS::Ace::NG::RectF frameRect;
970     OHOS::Ace::NG::RectF visibleInnerRect;
971     OHOS::Ace::NG::RectF visibleRect;
972     frameNode->GetVisibleRectWithClip(visibleRect, visibleInnerRect, frameRect, true);
973     bool isClipCheckSkip = NearEqual(visibleRect.Width(), 0.0) && NearEqual(visibleRect.Height(), 0.0) &&
974                            NearEqual(visibleInnerRect.Width(), 0.0) && NearEqual(visibleInnerRect.Height(), 0.0);
975     clipVisible = (GreatNotEqual(visibleInnerRect.Width(), 0.0) && GreatNotEqual(visibleInnerRect.Height(), 0.0)) ||
976                   isClipCheckSkip;
977     std::string parentPath;
978     while (parent) {
979         if (AceType::InstanceOf<NG::FrameNode>(parent)) {
980             if (ProcessParentFrameNode(parent, parentPath, isAllAncestorAccessibilityVisible)) {
981                 break;
982             }
983         }
984         parent = parent->GetParent();
985     }
986     TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "Complete parent path:current id %{public}" PRId64 " %{public}s",
987         nodeInfo.GetAccessibilityId(), parentPath.c_str());
988 
989     bool nodeAccessibilityVisible =
990         GetNodeAccessibilityVisible(frameNode, isAllAncestorAccessibilityVisible, clipVisible);
991     if (!nodeAccessibilityVisible) {
992         TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY,
993             "Element %{public}" PRId64 " is invisible. isActive %{public}d, isVisible %{public}d"
994             " isAllAncestorAccessibilityVisible:%{public}d clipVisible:%{public}d",
995             nodeInfo.GetAccessibilityId(), frameNode->IsActive(), frameNode->IsVisible(),
996             isAllAncestorAccessibilityVisible, clipVisible);
997     }
998 
999     if (frameNode->GetTag() != V2::PAGE_ETS_TAG) {
1000         frameNode->SetAccessibilityVisible(nodeAccessibilityVisible);
1001     }
1002     nodeInfo.SetAccessibilityVisible(frameNode->GetAccessibilityVisible());
1003 }
1004 
GetParentId(const RefPtr<NG::UINode> & uiNode)1005 int64_t GetParentId(const RefPtr<NG::UINode>& uiNode)
1006 {
1007     if (AceType::InstanceOf<NG::FrameNode>(uiNode)) {
1008         if (AceType::DynamicCast<NG::FrameNode>(uiNode)->IsFirstVirtualNode()) {
1009             auto weakNode = AceType::DynamicCast<NG::FrameNode>(uiNode)->GetVirtualNodeParent();
1010             auto refNode = weakNode.Upgrade();
1011             return refNode == nullptr ? INVALID_PARENT_ID : refNode->GetAccessibilityId();
1012         }
1013     }
1014     auto parent = uiNode->GetParent();
1015     while (parent) {
1016         if (AceType::InstanceOf<NG::FrameNode>(parent)) {
1017             if ((parent->GetTag() == V2::PAGE_ETS_TAG) || (parent->GetTag() == V2::STAGE_ETS_TAG) ||
1018                 AceType::DynamicCast<NG::FrameNode>(parent)->CheckAccessibilityLevelNo()) {
1019                 parent = parent->GetParent();
1020                 continue;
1021             }
1022             return parent->GetAccessibilityId();
1023         }
1024         parent = parent->GetParent();
1025     }
1026     return INVALID_PARENT_ID;
1027 }
1028 
FillElementInfo(int64_t elementId,AccessibilityElementInfo & elementInfo,const RefPtr<PipelineBase> & context,const RefPtr<JsAccessibilityManager> & jsAccessibilityManager,const FillEventInfoParam & param)1029 void FillElementInfo(int64_t elementId, AccessibilityElementInfo& elementInfo, const RefPtr<PipelineBase>& context,
1030     const RefPtr<JsAccessibilityManager>& jsAccessibilityManager, const FillEventInfoParam& param)
1031 {
1032     int64_t elementIdUnwrap = elementId;
1033     int64_t uiextensionId = 0;
1034     std::list<AccessibilityElementInfo> elementInfos;
1035     int32_t mode = 0;
1036     CHECK_NULL_VOID(jsAccessibilityManager);
1037 #ifdef WINDOW_SCENE_SUPPORTED
1038     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
1039     CHECK_NULL_VOID(ngPipeline);
1040     auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
1041     CHECK_NULL_VOID(uiExtensionManager);
1042     if (uiExtensionManager->IsWrapExtensionAbilityId(elementId)) {
1043         auto unWrapIdPair = uiExtensionManager->UnWrapExtensionAbilityId(
1044             NG::UI_EXTENSION_OFFSET_MAX, elementIdUnwrap);
1045         elementIdUnwrap = unWrapIdPair.second;
1046         uiextensionId = unWrapIdPair.first;
1047     }
1048 #endif
1049     TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY,
1050         "start to search elementId: %{public}" PRId64, elementIdUnwrap);
1051     jsAccessibilityManager->SearchElementInfoByAccessibilityIdNG(
1052         elementIdUnwrap, mode, elementInfos, context, NG::UI_EXTENSION_OFFSET_MAX);
1053     if (elementInfos.empty()) {
1054         LOGE("Element infos is empty. Find element infos failed.");
1055         return;
1056     }
1057     elementInfo = elementInfos.front();
1058     if (uiextensionId > 0) {
1059         elementIdUnwrap = (uiextensionId * NG::UI_EXTENSION_OFFSET_MAX) + elementInfo.GetAccessibilityId();
1060         TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "elementIdUnwrap: %{public}" PRId64, elementIdUnwrap);
1061     }
1062     elementInfo.SetAccessibilityId(elementIdUnwrap);
1063     elementInfo.SetWindowId(param.windowId);
1064 }
1065 
FillEventInfo(const RefPtr<NG::FrameNode> & node,AccessibilityEventInfo & eventInfo,const RefPtr<PipelineBase> & context,const RefPtr<JsAccessibilityManager> & jsAccessibilityManager,const FillEventInfoParam & param)1066 void FillEventInfo(const RefPtr<NG::FrameNode>& node,
1067                    AccessibilityEventInfo& eventInfo,
1068                    const RefPtr<PipelineBase>& context,
1069                    const RefPtr<JsAccessibilityManager>& jsAccessibilityManager,
1070                    const FillEventInfoParam& param)
1071 {
1072     CHECK_NULL_VOID(node);
1073     eventInfo.SetComponentType(node->GetTag());
1074     eventInfo.SetPageId(node->GetPageId());
1075     auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
1076     CHECK_NULL_VOID(accessibilityProperty);
1077     eventInfo.AddContent(accessibilityProperty->GetGroupText());
1078     eventInfo.SetItemCounts(accessibilityProperty->GetCollectionItemCounts());
1079     eventInfo.SetBeginIndex(accessibilityProperty->GetBeginIndex());
1080     eventInfo.SetEndIndex(accessibilityProperty->GetEndIndex());
1081     AccessibilityElementInfo elementInfo;
1082     FillElementInfo(param.elementId, elementInfo, context, jsAccessibilityManager, param);
1083     if (param.stackNodeId != -1) {
1084         int64_t stackNodeId = param.stackNodeId;
1085         AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(elementInfo.GetBelongTreeId(), stackNodeId);
1086         elementInfo.SetNavDestinationId(stackNodeId);
1087     }
1088     eventInfo.SetElementInfo(elementInfo);
1089 }
1090 #ifdef WEB_SUPPORTED
1091 
FillWebElementInfo(int64_t elementId,AccessibilityElementInfo & elementInfo,const RefPtr<PipelineBase> & context,const RefPtr<JsAccessibilityManager> & jsAccessibilityManager,const FillEventInfoParam & param,const RefPtr<NG::WebPattern> & webPattern)1092 void FillWebElementInfo(int64_t elementId, AccessibilityElementInfo& elementInfo,
1093                         const RefPtr<PipelineBase>& context,
1094                         const RefPtr<JsAccessibilityManager>& jsAccessibilityManager,
1095                         const FillEventInfoParam& param,
1096                         const RefPtr<NG::WebPattern>& webPattern)
1097 {
1098     std::list<AccessibilityElementInfo> elementInfos;
1099     int32_t mode = 0;
1100     CHECK_NULL_VOID(jsAccessibilityManager);
1101     jsAccessibilityManager->SearchWebElementInfoByAccessibilityIdNG(
1102         elementId, mode, elementInfos, context, webPattern);
1103     if (elementInfos.empty()) {
1104         LOGE("Element infos is empty. Find element infos failed.");
1105         return;
1106     }
1107     elementInfo = elementInfos.front();
1108     elementInfo.SetWindowId(param.windowId);
1109 }
1110 
FillWebEventInfo(AccessibilityEventInfo & eventInfo,const RefPtr<PipelineBase> & context,const RefPtr<JsAccessibilityManager> & jsAccessibilityManager,const FillEventInfoParam & param,const RefPtr<NG::WebPattern> & webPattern)1111 void FillWebEventInfo(AccessibilityEventInfo& eventInfo,
1112                       const RefPtr<PipelineBase>& context,
1113                       const RefPtr<JsAccessibilityManager>& jsAccessibilityManager,
1114                       const FillEventInfoParam& param,
1115                       const RefPtr<NG::WebPattern>& webPattern)
1116 {
1117     CHECK_NULL_VOID(webPattern);
1118     auto webNode = webPattern->GetHost();
1119     CHECK_NULL_VOID(webNode);
1120     eventInfo.SetPageId(webNode->GetPageId());
1121     AccessibilityElementInfo elementInfo;
1122     FillWebElementInfo(param.elementId, elementInfo, context, jsAccessibilityManager, param, webPattern);
1123     eventInfo.SetComponentType(elementInfo.GetComponentType());
1124     eventInfo.AddContent(elementInfo.GetContent());
1125     eventInfo.SetItemCounts(elementInfo.GetItemCounts());
1126     eventInfo.SetBeginIndex(elementInfo.GetBeginIndex());
1127     eventInfo.SetEndIndex(elementInfo.GetEndIndex());
1128     elementInfo.SetNavDestinationId(param.stackNodeId);
1129     eventInfo.SetElementInfo(elementInfo);
1130 }
1131 #endif
1132 
FillEventInfo(const RefPtr<AccessibilityNode> & node,AccessibilityEventInfo & eventInfo)1133 void FillEventInfo(const RefPtr<AccessibilityNode>& node, AccessibilityEventInfo& eventInfo)
1134 {
1135     eventInfo.SetComponentType(node->GetTag());
1136     if (node->GetTag() == LIST_TAG) {
1137         eventInfo.SetItemCounts(node->GetListItemCounts());
1138         eventInfo.SetBeginIndex(node->GetListBeginIndex());
1139         eventInfo.SetEndIndex(node->GetListEndIndex());
1140     }
1141     eventInfo.SetPageId(node->GetPageId());
1142     eventInfo.AddContent(node->GetText());
1143     eventInfo.SetLatestContent(node->GetText());
1144 }
1145 
IsPopupSupported(const RefPtr<NG::PipelineContext> & pipeline,int64_t nodeId)1146 inline bool IsPopupSupported(const RefPtr<NG::PipelineContext>& pipeline, int64_t nodeId)
1147 {
1148     CHECK_NULL_RETURN(pipeline, false);
1149     auto overlayManager = pipeline->GetOverlayManager();
1150     if (overlayManager) {
1151         return overlayManager->HasPopupInfo(nodeId);
1152     }
1153     return false;
1154 }
1155 
SetAccessibilityFocusAction(AccessibilityElementInfo & nodeInfo,const char * tag)1156 void SetAccessibilityFocusAction(AccessibilityElementInfo& nodeInfo, const char* tag)
1157 {
1158     if (nodeInfo.HasAccessibilityFocus()) {
1159         AccessibleAction action(ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS, tag);
1160         nodeInfo.AddAction(action);
1161     } else {
1162         AccessibleAction action(ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS, tag);
1163         nodeInfo.AddAction(action);
1164     }
1165 }
1166 
UpdateSupportAction(const RefPtr<NG::FrameNode> & node,AccessibilityElementInfo & nodeInfo)1167 void UpdateSupportAction(const RefPtr<NG::FrameNode>& node, AccessibilityElementInfo& nodeInfo)
1168 {
1169     CHECK_NULL_VOID(node);
1170     if (nodeInfo.IsFocusable()) {
1171         if (nodeInfo.IsFocused()) {
1172             AccessibleAction action(ACCESSIBILITY_ACTION_CLEAR_FOCUS, "ace");
1173             nodeInfo.AddAction(action);
1174         } else {
1175             AccessibleAction action(ACCESSIBILITY_ACTION_FOCUS, "ace");
1176             nodeInfo.AddAction(action);
1177         }
1178     }
1179 
1180     auto eventHub = node->GetEventHub<NG::EventHub>();
1181     CHECK_NULL_VOID(eventHub);
1182     auto gestureEventHub = eventHub->GetGestureEventHub();
1183     CHECK_NULL_VOID(gestureEventHub);
1184     nodeInfo.SetClickable(gestureEventHub->IsAccessibilityClickable());
1185     if (gestureEventHub->IsAccessibilityClickable()) {
1186         AccessibleAction action(ACCESSIBILITY_ACTION_CLICK, "ace");
1187         nodeInfo.AddAction(action);
1188     }
1189     nodeInfo.SetLongClickable(gestureEventHub->IsAccessibilityLongClickable());
1190     if (gestureEventHub->IsAccessibilityLongClickable()) {
1191         AccessibleAction action(ACCESSIBILITY_ACTION_LONG_CLICK, "ace");
1192         nodeInfo.AddAction(action);
1193     }
1194 }
1195 
UpdateUserAccessibilityElementInfo(const RefPtr<NG::AccessibilityProperty> & accessibilityProperty,AccessibilityElementInfo & nodeInfo)1196 void UpdateUserAccessibilityElementInfo(
1197     const RefPtr<NG::AccessibilityProperty>& accessibilityProperty, AccessibilityElementInfo& nodeInfo)
1198 {
1199     CHECK_NULL_VOID(accessibilityProperty);
1200     if (accessibilityProperty->HasUserDisabled()) {
1201         nodeInfo.SetEnabled(!accessibilityProperty->IsUserDisabled());
1202     }
1203     if (accessibilityProperty->HasUserCheckedType()) {
1204         nodeInfo.SetChecked(accessibilityProperty->GetUserCheckedType());
1205     } else {
1206         nodeInfo.SetChecked(accessibilityProperty->IsChecked());
1207     }
1208     if (accessibilityProperty->HasUserSelected()) {
1209         nodeInfo.SetSelected(accessibilityProperty->IsUserSelected());
1210     } else {
1211         nodeInfo.SetSelected(accessibilityProperty->IsSelected());
1212     }
1213 
1214     if (nodeInfo.IsEnabled()) {
1215         if (accessibilityProperty->HasUserCheckable()) {
1216             nodeInfo.SetCheckable(accessibilityProperty->IsUserCheckable());
1217         } else {
1218             nodeInfo.SetCheckable(accessibilityProperty->IsCheckable());
1219         }
1220     }
1221 }
1222 
IsUserCheckedOrSelected(const RefPtr<NG::FrameNode> frameNode)1223 bool IsUserCheckedOrSelected(const RefPtr<NG::FrameNode> frameNode)
1224 {
1225     auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
1226     CHECK_NULL_RETURN(accessibilityProperty, false);
1227     if (accessibilityProperty->HasUserCheckedType() || accessibilityProperty->HasUserSelected()) {
1228         return true;
1229     }
1230     return false;
1231 }
1232 
UpdateAccessibilityTextValueInfo(RefPtr<NG::AccessibilityProperty> & accessibilityProperty,AccessibilityElementInfo & nodeInfo)1233 void UpdateAccessibilityTextValueInfo(
1234     RefPtr<NG::AccessibilityProperty>& accessibilityProperty, AccessibilityElementInfo& nodeInfo)
1235 {
1236     if (accessibilityProperty->HasUserTextValue()) {
1237         nodeInfo.SetContent(accessibilityProperty->GetUserTextValue());
1238     } else {
1239         nodeInfo.SetContent(accessibilityProperty->GetGroupText());
1240     }
1241 
1242     if (!accessibilityProperty->HasUserTextValue() && accessibilityProperty->GetAccessibilityText().empty() &&
1243         accessibilityProperty->IsAccessibilityGroup() && accessibilityProperty->IsAccessibilityTextPreferred()) {
1244         nodeInfo.SetAccessibilityText(accessibilityProperty->GetGroupPreferAccessibilityText());
1245     } else {
1246         nodeInfo.SetAccessibilityText(accessibilityProperty->GetAccessibilityText());
1247     }
1248 }
1249 
UpdateElementInfoPageIdWithTreeId(Accessibility::AccessibilityElementInfo & info,int32_t treeId)1250 void UpdateElementInfoPageIdWithTreeId(Accessibility::AccessibilityElementInfo& info, int32_t treeId)
1251 {
1252     int32_t pageId = info.GetPageId();
1253     if ((pageId >= MAX_PAGE_ID_WITH_SUB_TREE) || (pageId < 0)) {
1254         TAG_LOGE(AceLogTag::ACE_ACCESSIBILITY, "pageId %{public}d cannot set tree id", pageId);
1255     } else {
1256         uint32_t unsignedPageId = static_cast<uint32_t>(pageId);
1257         uint32_t unsignedTreeId = static_cast<uint32_t>(treeId);
1258         info.SetPageId((unsignedTreeId << SUB_TREE_OFFSET_IN_PAGE_ID) | unsignedPageId);
1259     }
1260 }
1261 
ScrollByOffsetToParent(const RefPtr<NG::FrameNode> & curFrameNode,const RefPtr<NG::FrameNode> & parentFrameNode)1262 bool ScrollByOffsetToParent(const RefPtr<NG::FrameNode>& curFrameNode, const RefPtr<NG::FrameNode>& parentFrameNode)
1263 {
1264     CHECK_NULL_RETURN(curFrameNode, false);
1265     CHECK_NULL_RETURN(parentFrameNode, false);
1266     auto parentPattern = parentFrameNode->GetPattern<NG::ScrollablePattern>();
1267     CHECK_NULL_RETURN(parentPattern, false);
1268 
1269     auto scrollAbility = parentPattern->GetScrollOffsetAbility();
1270     auto scrollFunc = scrollAbility.scrollFunc;
1271     auto scrollAxis = scrollAbility.axis;
1272     if (!scrollFunc || scrollAxis == Axis::NONE) {
1273         return false;
1274     }
1275     auto moveOffset = NG::ScrollableUtils::GetMoveOffset(parentFrameNode, curFrameNode, scrollAxis == Axis::VERTICAL,
1276         scrollAbility.contentStartOffset, scrollAbility.contentEndOffset);
1277     if (!NearZero(moveOffset)) {
1278         TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "Scroll offset: %{public}f on %{public}s/%{public}d, axis: %{public}d",
1279             moveOffset, parentFrameNode->GetTag().c_str(), parentFrameNode->GetId(), scrollAxis);
1280         auto ret = scrollFunc(parentPattern->IsReverse() ? -moveOffset : moveOffset);
1281         auto pipeline = NG::PipelineContext::GetCurrentContextSafelyWithCheck();
1282         if (pipeline) {
1283             pipeline->FlushUITasks();
1284         }
1285         return ret;
1286     }
1287     return false;
1288 }
1289 
ScrollByOffset(const RefPtr<NG::FrameNode> & curFrameNode)1290 bool ScrollByOffset(const RefPtr<NG::FrameNode>& curFrameNode)
1291 {
1292     CHECK_NULL_RETURN(curFrameNode, false);
1293     bool ret = false;
1294     auto parentFrameNode = curFrameNode->GetParentFrameNode();
1295 
1296     while (parentFrameNode) {
1297         if (ScrollByOffsetToParent(curFrameNode, parentFrameNode)) {
1298             ret = true;
1299         }
1300         parentFrameNode = parentFrameNode->GetParentFrameNode();
1301     }
1302     return ret;
1303 }
1304 
ProcessFocusScroll(const RefPtr<NG::FrameNode> & curFrameNode,RefPtr<NG::PipelineContext> & context)1305 void ProcessFocusScroll(const RefPtr<NG::FrameNode>& curFrameNode, RefPtr<NG::PipelineContext>& context)
1306 {
1307     CHECK_NULL_VOID(context);
1308     context->GetTaskExecutor()->PostTask(
1309         [node = AceType::WeakClaim(AceType::RawPtr(curFrameNode))] {
1310             auto focusNode = node.Upgrade();
1311             CHECK_NULL_VOID(focusNode);
1312             auto accessibilityProperty = focusNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
1313             CHECK_NULL_VOID(accessibilityProperty);
1314             if (accessibilityProperty->GetAccessibilityFocusState()) {
1315                 ScrollByOffset(focusNode);
1316             }
1317         },
1318         TaskExecutor::TaskType::UI, "ArkUIAccessibilityProcessFocusScroll");
1319 }
1320 } // namespace
1321 
UpdateAccessibilityElementInfo(const RefPtr<NG::FrameNode> & node,AccessibilityElementInfo & nodeInfo)1322 void JsAccessibilityManager::UpdateAccessibilityElementInfo(
1323     const RefPtr<NG::FrameNode>& node, AccessibilityElementInfo& nodeInfo)
1324 {
1325     CHECK_NULL_VOID(node);
1326     auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
1327     CHECK_NULL_VOID(accessibilityProperty);
1328     if (accessibilityProperty->HasAccessibilityRole()) {
1329         nodeInfo.SetComponentType(accessibilityProperty->GetAccessibilityRole());
1330     }
1331 
1332     UpdateAccessibilityTextValueInfo(accessibilityProperty, nodeInfo);
1333     if (accessibilityProperty->HasRange()) {
1334         RangeInfo rangeInfo = ConvertAccessibilityValue(accessibilityProperty->GetAccessibilityValue());
1335         nodeInfo.SetRange(rangeInfo);
1336     }
1337     if (accessibilityProperty->HasSubComponent()) {
1338         std::vector<SubComponentInfo> subComponentInfos;
1339         accessibilityProperty->GetSubComponentInfo(subComponentInfos);
1340         for (const auto& subComponent : subComponentInfos) {
1341             nodeInfo.AddSpan(SpanInfo(subComponent.spanId, subComponent.spanText,
1342                 subComponent.accessibilityText, subComponent.accessibilityDescription,
1343                 subComponent.accessibilityLevel));
1344         }
1345     }
1346     nodeInfo.SetHint(accessibilityProperty->GetHintText());
1347     nodeInfo.SetAccessibilityGroup(accessibilityProperty->IsAccessibilityGroup());
1348     nodeInfo.SetAccessibilityLevel(accessibilityProperty->GetAccessibilityLevel());
1349     nodeInfo.SetTextType(accessibilityProperty->GetTextType());
1350     nodeInfo.SetTextLengthLimit(accessibilityProperty->GetTextLengthLimit());
1351     nodeInfo.SetOffset(accessibilityProperty->GetScrollOffSet());
1352     auto context = node->GetRenderContext();
1353     if (context != nullptr) {
1354         nodeInfo.SetZIndex(context->GetZIndex().value_or(0));
1355         nodeInfo.SetOpacity(context->GetOpacity().value_or(1));
1356         nodeInfo.SetBackgroundColor(context->GetBackgroundColor().value_or(Color::TRANSPARENT).ToString());
1357         nodeInfo.SetBackgroundImage(context->GetBackgroundImage().value_or(ImageSourceInfo("")).ToString());
1358         if (context->GetForeground() != nullptr) {
1359             nodeInfo.SetBlur(context->GetForeground()->propBlurRadius.value_or(Dimension(0)).ToString());
1360         }
1361     }
1362     auto eventHub = node->GetEventHub<NG::EventHub>();
1363     if (eventHub != nullptr) {
1364         auto gestureEventHub = eventHub->GetGestureEventHub();
1365         if (gestureEventHub != nullptr) {
1366             nodeInfo.SetHitTestBehavior(gestureEventHub->GetHitTestModeStr());
1367         }
1368     }
1369 
1370     UpdateUserAccessibilityElementInfo(accessibilityProperty, nodeInfo);
1371 
1372     nodeInfo.SetPassword(accessibilityProperty->IsPassword());
1373     nodeInfo.SetPluraLineSupported(accessibilityProperty->IsMultiLine());
1374     nodeInfo.SetHinting(accessibilityProperty->IsHint());
1375     nodeInfo.SetDescriptionInfo(accessibilityProperty->GetAccessibilityDescription());
1376     if (accessibilityProperty->HasUserCurrentValue()) {
1377         nodeInfo.SetCurrentIndex(accessibilityProperty->GetUserCurrentValue());
1378     } else {
1379         nodeInfo.SetCurrentIndex(accessibilityProperty->GetCurrentIndex());
1380     }
1381     if (accessibilityProperty->HasUserMinValue()) {
1382         nodeInfo.SetBeginIndex(accessibilityProperty->GetUserMinValue());
1383     } else {
1384         nodeInfo.SetBeginIndex(accessibilityProperty->GetBeginIndex());
1385     }
1386     if (accessibilityProperty->HasUserMaxValue()) {
1387         nodeInfo.SetEndIndex(accessibilityProperty->GetUserMaxValue());
1388     } else {
1389         nodeInfo.SetEndIndex(accessibilityProperty->GetEndIndex());
1390     }
1391     auto tag = node->GetTag();
1392     if (tag == V2::TOAST_ETS_TAG || tag == V2::POPUP_ETS_TAG || tag == V2::DIALOG_ETS_TAG ||
1393         tag == V2::ACTION_SHEET_DIALOG_ETS_TAG || tag == V2::ALERT_DIALOG_ETS_TAG || tag == V2::MENU_ETS_TAG ||
1394         tag == "SelectMenu") {
1395         nodeInfo.SetLiveRegion(1);
1396     }
1397     nodeInfo.SetContentInvalid(accessibilityProperty->GetContentInvalid());
1398     nodeInfo.SetError(accessibilityProperty->GetErrorText());
1399     nodeInfo.SetSelectedBegin(accessibilityProperty->GetTextSelectionStart());
1400     nodeInfo.SetSelectedEnd(accessibilityProperty->GetTextSelectionEnd());
1401     nodeInfo.SetInputType(static_cast<int>(accessibilityProperty->GetTextInputType()));
1402     nodeInfo.SetItemCounts(accessibilityProperty->GetCollectionItemCounts());
1403     nodeInfo.SetChildTreeIdAndWinId(
1404         accessibilityProperty->GetChildTreeId(), accessibilityProperty->GetChildWindowId());
1405     if (nodeInfo.GetComponentType() == "FormComponent") {
1406         TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "elementId: %{public}" PRId64 ", Set: %{public}d %{public}d",
1407             nodeInfo.GetAccessibilityId(), accessibilityProperty->GetChildTreeId(),
1408             accessibilityProperty->GetChildWindowId());
1409     }
1410     if (nodeInfo.GetWindowId() == static_cast<int32_t>(windowId_)) {
1411         nodeInfo.SetBelongTreeId(treeId_);
1412         nodeInfo.SetParentWindowId(parentWindowId_);
1413     } else {
1414         nodeInfo.SetBelongTreeId(0);
1415         nodeInfo.SetParentWindowId(0);
1416     }
1417 
1418     GridInfo gridInfo(accessibilityProperty->GetCollectionInfo().rows,
1419         accessibilityProperty->GetCollectionInfo().columns, accessibilityProperty->GetCollectionInfo().selectMode);
1420     nodeInfo.SetGrid(gridInfo);
1421     ExtraElementInfo extraElementInfo {};
1422     accessibilityProperty->GetAllExtraElementInfo(extraElementInfo);
1423     nodeInfo.SetExtraElement(extraElementInfo);
1424 
1425     int32_t row = accessibilityProperty->GetCollectionItemInfo().row;
1426     int32_t column = accessibilityProperty->GetCollectionItemInfo().column;
1427     int32_t rowSpan = accessibilityProperty->GetCollectionItemInfo().rowSpan;
1428     int32_t columnSpan = accessibilityProperty->GetCollectionItemInfo().columnSpan;
1429     bool heading = accessibilityProperty->GetCollectionItemInfo().heading;
1430     GridItemInfo gridItemInfo(row, rowSpan, column, columnSpan, heading, nodeInfo.IsSelected());
1431     nodeInfo.SetGridItem(gridItemInfo);
1432 
1433     SetAccessibilityFocusAction(nodeInfo, "ace");
1434     if (nodeInfo.IsEnabled()) {
1435         nodeInfo.SetScrollable(accessibilityProperty->IsScrollable());
1436         nodeInfo.SetEditable(accessibilityProperty->IsEditable());
1437         nodeInfo.SetDeletable(accessibilityProperty->IsDeletable());
1438         UpdateSupportAction(node, nodeInfo);
1439         accessibilityProperty->ResetSupportAction();
1440         auto supportAceActions = accessibilityProperty->GetSupportAction();
1441         for (auto it = supportAceActions.begin(); it != supportAceActions.end(); ++it) {
1442             AccessibleAction action(ConvertAceAction(*it), "ace");
1443             nodeInfo.AddAction(action);
1444         }
1445     }
1446 }
1447 #ifdef WEB_SUPPORTED
1448 
UpdateWebAccessibilityElementInfo(const std::shared_ptr<NWeb::NWebAccessibilityNodeInfo> & node,AccessibilityElementInfo & nodeInfo,int32_t treeId)1449 void JsAccessibilityManager::UpdateWebAccessibilityElementInfo(
1450     const std::shared_ptr<NWeb::NWebAccessibilityNodeInfo>& node, AccessibilityElementInfo& nodeInfo, int32_t treeId)
1451 {
1452     CHECK_NULL_VOID(node);
1453     nodeInfo.SetContent(node->GetContent());
1454     nodeInfo.SetAccessibilityText(node->GetContent());
1455     RangeInfo rangeInfo(node->GetRangeInfoMin(), node->GetRangeInfoMax(), node->GetRangeInfoCurrent());
1456     nodeInfo.SetRange(rangeInfo);
1457     nodeInfo.SetHint(node->GetHint());
1458     nodeInfo.SetHinting(node->GetIsHinting());
1459     nodeInfo.SetDescriptionInfo(node->GetDescriptionInfo());
1460     nodeInfo.SetChecked(node->GetIsChecked());
1461     nodeInfo.SetSelected(node->GetIsSelected());
1462     nodeInfo.SetPassword(node->GetIsPassword());
1463     nodeInfo.SetPluraLineSupported(node->GetIsPluralLineSupported());
1464     nodeInfo.SetLiveRegion(node->GetLiveRegion());
1465     nodeInfo.SetContentInvalid(node->GetIsContentInvalid());
1466     nodeInfo.SetError(node->GetError());
1467     nodeInfo.SetSelectedBegin(node->GetSelectionStart());
1468     nodeInfo.SetSelectedEnd(node->GetSelectionEnd());
1469     nodeInfo.SetInputType(node->GetInputType());
1470     nodeInfo.SetItemCounts(node->GetItemCounts());
1471 
1472     nodeInfo.SetBelongTreeId(treeId);
1473     nodeInfo.SetParentWindowId(parentWebWindowId_);
1474 
1475     GridInfo gridInfo(node->GetGridRows(), node->GetGridColumns(), node->GetGridSelectedMode());
1476     nodeInfo.SetGrid(gridInfo);
1477 
1478     int32_t row = node->GetGridItemRow();
1479     int32_t column = node->GetGridItemColumn();
1480     int32_t rowSpan = node->GetGridItemRowSpan();
1481     int32_t columnSpan = node->GetGridItemColumnSpan();
1482     bool heading = node->GetIsHeading();
1483     GridItemInfo gridItemInfo(row, rowSpan, column, columnSpan, heading, nodeInfo.IsSelected());
1484     nodeInfo.SetGridItem(gridItemInfo);
1485 
1486     SetAccessibilityFocusAction(nodeInfo, "web");
1487     if (nodeInfo.IsEnabled()) {
1488         nodeInfo.SetCheckable(node->GetIsCheckable());
1489         nodeInfo.SetScrollable(node->GetIsScrollable());
1490         nodeInfo.SetEditable(node->GetIsEditable());
1491         nodeInfo.SetDeletable(node->GetIsDeletable());
1492         nodeInfo.SetClickable(node->GetIsClickable());
1493         auto supportAceActions = node->GetActions();
1494         for (auto it = supportAceActions.begin(); it != supportAceActions.end(); ++it) {
1495             AccessibleAction action(ConvertAceAction(static_cast<AceAction>(*it)), "web");
1496             nodeInfo.AddAction(action);
1497         }
1498     }
1499     nodeInfo.SetAccessibilityGroup(node->GetIsAccessibilityGroup());
1500 }
1501 
1502 #endif
1503 namespace {
UpdateChildrenOfAccessibilityElementInfo(const RefPtr<NG::FrameNode> & node,const CommonProperty & commonProperty,AccessibilityElementInfo & nodeInfo)1504 void UpdateChildrenOfAccessibilityElementInfo(
1505     const RefPtr<NG::FrameNode>& node, const CommonProperty& commonProperty, AccessibilityElementInfo& nodeInfo)
1506 {
1507     if (!IsExtensionComponent(node) || IsUIExtensionShowPlaceholder(node)) {
1508         std::vector<int64_t> children;
1509         for (const auto& item : node->GetChildren(true)) {
1510             GetFrameNodeChildren(item, children, commonProperty.pageId);
1511         }
1512 
1513         auto overlayNode = node->GetOverlayNode();
1514         if (overlayNode != nullptr) {
1515             GetFrameNodeChildren(overlayNode, children, commonProperty.pageId);
1516         }
1517 
1518         auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
1519         auto uiVirtualNode = accessibilityProperty->GetAccessibilityVirtualNode();
1520         if (uiVirtualNode != nullptr) {
1521             auto virtualNode = AceType::DynamicCast<NG::FrameNode>(uiVirtualNode);
1522             if (virtualNode != nullptr) {
1523                 children.clear();
1524                 GetFrameNodeChildren(virtualNode, children, commonProperty.pageId);
1525             }
1526         }
1527         for (const auto& child : children) {
1528             nodeInfo.AddChild(child);
1529         }
1530     }
1531 }
1532 
1533 }
1534 
UpdateVirtualNodeChildAccessibilityElementInfo(const RefPtr<NG::FrameNode> & node,const CommonProperty & commonProperty,AccessibilityElementInfo & nodeParentInfo,AccessibilityElementInfo & nodeInfo,const RefPtr<NG::PipelineContext> & ngPipeline)1535 void JsAccessibilityManager::UpdateVirtualNodeChildAccessibilityElementInfo(
1536     const RefPtr<NG::FrameNode>& node, const CommonProperty& commonProperty,
1537     AccessibilityElementInfo& nodeParentInfo, AccessibilityElementInfo& nodeInfo,
1538     const RefPtr<NG::PipelineContext>& ngPipeline)
1539 {
1540     CHECK_NULL_VOID(node);
1541     nodeInfo.SetParent(GetParentId(node));
1542     UpdateChildrenOfAccessibilityElementInfo(node, commonProperty, nodeInfo);
1543 
1544     nodeInfo.SetAccessibilityId(node->GetAccessibilityId());
1545     nodeInfo.SetComponentType(node->GetTag());
1546 
1547     nodeInfo.SetEnabled(node->GetFocusHub() ? node->GetFocusHub()->IsEnabled() : true);
1548     nodeInfo.SetFocused(node->GetFocusHub() ? node->GetFocusHub()->IsCurrentFocus() : false);
1549     nodeInfo.SetAccessibilityFocus(node->GetRenderContext()->GetAccessibilityFocus().value_or(false));
1550     nodeInfo.SetInspectorKey(node->GetInspectorId().value_or(""));
1551     nodeInfo.SetVisible(node->IsVisible());
1552     if (node->IsVisible()) {
1553         auto rect = node->GetVirtualNodeTransformRectRelativeToWindow();
1554         auto left = rect.Left() + commonProperty.windowLeft;
1555         auto top = rect.Top() + commonProperty.windowTop;
1556         auto right = rect.Right() + commonProperty.windowLeft;
1557         auto bottom = rect.Bottom() + commonProperty.windowTop;
1558         Accessibility::Rect bounds { left, top, right, bottom };
1559         nodeInfo.SetRectInScreen(bounds);
1560     }
1561     nodeInfo.SetWindowId(commonProperty.windowId);
1562     nodeInfo.SetPageId(node->GetPageId());
1563     nodeInfo.SetPagePath(commonProperty.pagePath);
1564     nodeInfo.SetBundleName(AceApplicationInfo::GetInstance().GetPackageName());
1565 
1566     if (nodeInfo.IsEnabled()) {
1567         nodeInfo.SetFocusable(node->GetFocusHub() ? node->GetFocusHub()->IsFocusable() : false);
1568         nodeInfo.SetPopupSupported(IsPopupSupported(ngPipeline, node->GetId()));
1569     }
1570     nodeInfo.SetComponentResourceId(node->GetInspectorId().value_or(""));
1571     UpdateAccessibilityElementInfo(node, nodeInfo);
1572 }
1573 
UpdateVirtualNodeAccessibilityElementInfo(const RefPtr<NG::FrameNode> & parent,const RefPtr<NG::FrameNode> & node,const CommonProperty & commonProperty,AccessibilityElementInfo & nodeInfo,const RefPtr<NG::PipelineContext> & ngPipeline)1574 void JsAccessibilityManager::UpdateVirtualNodeAccessibilityElementInfo(
1575     const RefPtr<NG::FrameNode>& parent, const RefPtr<NG::FrameNode>& node,
1576     const CommonProperty& commonProperty, AccessibilityElementInfo& nodeInfo,
1577     const RefPtr<NG::PipelineContext>& ngPipeline)
1578 {
1579     CHECK_NULL_VOID(parent);
1580     CHECK_NULL_VOID(node);
1581     nodeInfo.SetParent(GetParentId(node));
1582     UpdateChildrenOfAccessibilityElementInfo(node, commonProperty, nodeInfo);
1583 
1584     nodeInfo.SetAccessibilityId(node->GetAccessibilityId());
1585     nodeInfo.SetComponentType(node->GetTag());
1586 
1587     nodeInfo.SetEnabled(node->GetFocusHub() ? node->GetFocusHub()->IsEnabled() : true);
1588     nodeInfo.SetFocused(node->GetFocusHub() ? node->GetFocusHub()->IsCurrentFocus() : false);
1589     nodeInfo.SetAccessibilityFocus(node->GetRenderContext()->GetAccessibilityFocus().value_or(false));
1590     nodeInfo.SetInspectorKey(node->GetInspectorId().value_or(""));
1591     nodeInfo.SetVisible(node->IsVisible());
1592     if (node->IsVisible()) {
1593         auto virtualNodeRect = node->GetTransformRectRelativeToWindow();
1594         auto parentRect = parent->GetTransformRectRelativeToWindow();
1595         auto left = parentRect.Left() + commonProperty.windowLeft;
1596         auto top = parentRect.Top() + commonProperty.windowTop;
1597         auto right = parentRect.Left() + virtualNodeRect.Width() + commonProperty.windowLeft;
1598         if (virtualNodeRect.Width() > (parentRect.Right() - parentRect.Left())) {
1599             right = parentRect.Right() + commonProperty.windowLeft;
1600         }
1601         auto bottom = parentRect.Top() + virtualNodeRect.Height() + commonProperty.windowTop;
1602         if (virtualNodeRect.Height() > (parentRect.Bottom() - parentRect.Top())) {
1603             bottom = parentRect.Bottom() + commonProperty.windowTop;
1604         }
1605         Accessibility::Rect bounds { left, top, right, bottom };
1606         nodeInfo.SetRectInScreen(bounds);
1607     }
1608     nodeInfo.SetWindowId(commonProperty.windowId);
1609     nodeInfo.SetPageId(node->GetPageId());
1610     nodeInfo.SetPagePath(commonProperty.pagePath);
1611     nodeInfo.SetBundleName(AceApplicationInfo::GetInstance().GetPackageName());
1612 
1613     if (nodeInfo.IsEnabled()) {
1614         nodeInfo.SetFocusable(node->GetFocusHub() ? node->GetFocusHub()->IsFocusable() : false);
1615         nodeInfo.SetPopupSupported(IsPopupSupported(ngPipeline, node->GetId()));
1616     }
1617     nodeInfo.SetComponentResourceId(node->GetInspectorId().value_or(""));
1618     UpdateAccessibilityElementInfo(node, nodeInfo);
1619 }
1620 
UpdateAccessibilityVisible(const RefPtr<NG::FrameNode> & node,AccessibilityElementInfo & nodeInfo)1621 void JsAccessibilityManager::UpdateAccessibilityVisible(
1622     const RefPtr<NG::FrameNode>& node, AccessibilityElementInfo& nodeInfo)
1623 {
1624     auto parentNode = node->GetParentFrameNode();
1625     UpdateElementInfoTreeId(nodeInfo);
1626 
1627     if (!parentNode) {
1628         if (node->GetTag() != V2::PAGE_ETS_TAG) {
1629             node->SetAccessibilityVisible(node->IsActive() && node->IsVisible());
1630         }
1631     } else {
1632         if (node->GetTag() == V2::PAGE_ETS_TAG) {
1633             nodeInfo.SetAccessibilityVisible(node->IsActive() && node->IsVisible() && node->GetAccessibilityVisible() &&
1634                                              parentNode->GetAccessibilityVisible());
1635             return;
1636         }
1637         auto nodeAccessibilityVisible = node->IsActive() && node->IsVisible() && parentNode->GetAccessibilityVisible();
1638         node->SetAccessibilityVisible(nodeAccessibilityVisible);
1639         if (!nodeAccessibilityVisible) {
1640             TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY,
1641                 "Element %{public}" PRId64 " is invisible. node isActive %{public}d, node isVisible %{public}d"
1642                 "parent accessibilityVisible:%{public}d.parent id %{public}" PRId64,
1643                 nodeInfo.GetAccessibilityId(), node->IsActive(), node->IsVisible(),
1644                 parentNode->GetAccessibilityVisible(), parentNode->GetAccessibilityId());
1645         }
1646     }
1647     nodeInfo.SetAccessibilityVisible(node->GetAccessibilityVisible());
1648 }
1649 
1650 namespace {
GetFinalRealRect(const RefPtr<NG::FrameNode> & node)1651     NG::RectF GetFinalRealRect(const RefPtr<NG::FrameNode>& node)
1652     {
1653         // get the node position after rotation compensation
1654         auto offset = node->GetPositionToWindowWithTransform(false);
1655         auto offsetBottom = node->GetPositionToWindowWithTransform(true);
1656         return {
1657             LessNotEqual(offset.GetX(), offsetBottom.GetX()) ? offset.GetX() : offsetBottom.GetX(),
1658             LessNotEqual(offset.GetY(), offsetBottom.GetY()) ? offset.GetY() : offsetBottom.GetY(),
1659             LessNotEqual(offset.GetX(), offsetBottom.GetX())
1660                 ? offsetBottom.GetX() - offset.GetX()
1661                 : offset.GetX() - offsetBottom.GetX(),
1662             LessNotEqual(offset.GetY(), offsetBottom.GetY())
1663                 ? offsetBottom.GetY() - offset.GetY()
1664                 : offset.GetY() - offsetBottom.GetY()
1665             };
1666     }
1667 }
1668 
UpdateAccessibilityElementInfo(const RefPtr<NG::FrameNode> & node,const CommonProperty & commonProperty,AccessibilityElementInfo & nodeInfo,const RefPtr<NG::PipelineContext> & ngPipeline)1669 void JsAccessibilityManager::UpdateAccessibilityElementInfo(
1670     const RefPtr<NG::FrameNode>& node, const CommonProperty& commonProperty,
1671     AccessibilityElementInfo& nodeInfo, const RefPtr<NG::PipelineContext>& ngPipeline)
1672 {
1673     CHECK_NULL_VOID(node);
1674     nodeInfo.SetParent(GetParentId(node));
1675     UpdateChildrenOfAccessibilityElementInfo(node, commonProperty, nodeInfo);
1676 
1677     nodeInfo.SetAccessibilityId(node->GetAccessibilityId());
1678     nodeInfo.SetComponentType(node->GetTag());
1679 
1680     nodeInfo.SetEnabled(node->GetFocusHub() ? node->GetFocusHub()->IsEnabled() : true);
1681     nodeInfo.SetFocused(node->GetFocusHub() ? node->GetFocusHub()->IsCurrentFocus() : false);
1682     nodeInfo.SetAccessibilityFocus(node->GetRenderContext()->GetAccessibilityFocus().value_or(false));
1683     nodeInfo.SetInspectorKey(node->GetInspectorId().value_or(""));
1684     nodeInfo.SetVisible(node->IsVisible());
1685     if (node->IsAccessibilityVirtualNode()) {
1686         auto rect = node->GetVirtualNodeTransformRectRelativeToWindow();
1687         auto left = rect.Left() + commonProperty.windowLeft;
1688         auto top = rect.Top() + commonProperty.windowTop;
1689         auto right = rect.Right() + commonProperty.windowLeft;
1690         auto bottom = rect.Bottom() + commonProperty.windowTop;
1691         Accessibility::Rect bounds { left, top, right, bottom };
1692         nodeInfo.SetRectInScreen(bounds);
1693     } else if (node->IsVisible()) {
1694         auto rect = GetFinalRealRect(node);
1695         auto left = rect.Left() + commonProperty.windowLeft;
1696         auto top = rect.Top() + commonProperty.windowTop;
1697         auto right = rect.Right() + commonProperty.windowLeft;
1698         auto bottom = rect.Bottom() + commonProperty.windowTop;
1699         Accessibility::Rect bounds { left, top, right, bottom };
1700         nodeInfo.SetRectInScreen(bounds);
1701     }
1702     nodeInfo.SetWindowId(commonProperty.windowId);
1703     // is abnormal that pageId equals to 0, use commonProperty.pageId to fix pageId
1704     if (node->GetPageId()) {
1705         nodeInfo.SetPageId(node->GetPageId());
1706     } else {
1707         nodeInfo.SetPageId(commonProperty.pageId);
1708     }
1709     nodeInfo.SetPagePath(commonProperty.pagePath);
1710     nodeInfo.SetBundleName(AceApplicationInfo::GetInstance().GetPackageName());
1711 
1712     if (nodeInfo.IsEnabled()) {
1713         nodeInfo.SetFocusable(node->GetFocusHub() ? node->GetFocusHub()->IsFocusable() : false);
1714         nodeInfo.SetPopupSupported(IsPopupSupported(ngPipeline, node->GetId()));
1715     }
1716     nodeInfo.SetComponentResourceId(node->GetInspectorId().value_or(""));
1717     UpdateAccessibilityElementInfo(node, nodeInfo);
1718     UpdateAccessibilityVisible(node, nodeInfo);
1719 }
1720 #ifdef WEB_SUPPORTED
1721 
UpdateWebAccessibilityElementInfo(const std::shared_ptr<NWeb::NWebAccessibilityNodeInfo> & node,const CommonProperty & commonProperty,AccessibilityElementInfo & nodeInfo,const RefPtr<NG::WebPattern> & webPattern)1722 void JsAccessibilityManager::UpdateWebAccessibilityElementInfo(
1723     const std::shared_ptr<NWeb::NWebAccessibilityNodeInfo>& node, const CommonProperty& commonProperty,
1724     AccessibilityElementInfo& nodeInfo, const RefPtr<NG::WebPattern>& webPattern)
1725 {
1726     if (node->GetParentId() == -1) {
1727         nodeInfo.SetParent(INVALID_PARENT_ID);
1728     } else {
1729         nodeInfo.SetParent(node->GetParentId());
1730     }
1731     for (const auto& child : node->GetChildIds()) {
1732         nodeInfo.AddChild(child);
1733     }
1734 
1735     nodeInfo.SetAccessibilityId(node->GetAccessibilityId());
1736     nodeInfo.SetComponentType(node->GetComponentType());
1737     nodeInfo.SetEnabled(node->GetIsEnabled());
1738     nodeInfo.SetFocused(node->GetIsFocused());
1739     nodeInfo.SetAccessibilityFocus(node->GetIsAccessibilityFocus());
1740 
1741     nodeInfo.SetVisible(node->GetIsVisible());
1742     if (node->GetIsVisible()) {
1743         CHECK_NULL_VOID(webPattern);
1744         auto webNode = webPattern->GetHost();
1745         CHECK_NULL_VOID(webNode);
1746         auto webRect = webNode->GetTransformRectRelativeToWindow();
1747         auto left = webRect.Left() + node->GetRectX() + commonProperty.windowLeft;
1748         auto top = webRect.Top() + node->GetRectY() + commonProperty.windowTop;
1749         auto right = webRect.Left() + node->GetRectX() + node->GetRectWidth() + commonProperty.windowLeft;
1750         auto bottom = webRect.Top() + node->GetRectY() + node->GetRectHeight() + commonProperty.windowTop;
1751         Accessibility::Rect bounds { left, top, right, bottom };
1752         nodeInfo.SetRectInScreen(bounds);
1753     }
1754 
1755     nodeInfo.SetWindowId(commonProperty.windowId);
1756     nodeInfo.SetPageId(node->GetPageId());
1757     nodeInfo.SetPagePath(commonProperty.pagePath);
1758     nodeInfo.SetBundleName(AceApplicationInfo::GetInstance().GetPackageName());
1759 
1760     if (nodeInfo.IsEnabled()) {
1761         nodeInfo.SetFocusable(node->GetIsFocusable());
1762         nodeInfo.SetPopupSupported(node->GetIsPopupSupported());
1763     }
1764     CHECK_NULL_VOID(webPattern);
1765     UpdateWebAccessibilityElementInfo(node, nodeInfo, webPattern->GetTreeId());
1766 }
1767 
1768 #endif
1769 namespace {
SearchExtensionElementInfoByAccessibilityIdNG(int64_t elementId,int32_t mode,const RefPtr<NG::FrameNode> & node,int64_t offset)1770 std::list<AccessibilityElementInfo> SearchExtensionElementInfoByAccessibilityIdNG(
1771     int64_t elementId, int32_t mode, const RefPtr<NG::FrameNode>& node,  int64_t offset)
1772 {
1773     std::list<AccessibilityElementInfo> extensionElementInfo;
1774     if (NG::UI_EXTENSION_OFFSET_MIN < (offset + 1)) {
1775         node->SearchExtensionElementInfoByAccessibilityIdNG(elementId, mode,
1776             offset / NG::UI_EXTENSION_ID_FACTOR, extensionElementInfo);
1777     }
1778     return extensionElementInfo;
1779 }
1780 
UpdateUiExtensionParentIdForFocus(const RefPtr<NG::FrameNode> & rootNode,const int64_t uiExtensionOffset,Accessibility::AccessibilityElementInfo & info)1781 void UpdateUiExtensionParentIdForFocus(const RefPtr<NG::FrameNode>& rootNode, const int64_t uiExtensionOffset,
1782     Accessibility::AccessibilityElementInfo& info)
1783 {
1784     if ((uiExtensionOffset != NG::UI_EXTENSION_OFFSET_MAX) && (info.GetComponentType() != V2::ROOT_ETS_TAG) &&
1785         (info.GetParentNodeId() == rootNode->GetAccessibilityId())) {
1786             info.SetParent(NG::UI_EXTENSION_ROOT_ID);
1787     }
1788 }
1789 
GetChildrenFromFrameNode(const RefPtr<NG::FrameNode> & node,std::list<RefPtr<NG::FrameNode>> & children,int32_t pageId)1790 void GetChildrenFromFrameNode(const RefPtr<NG::FrameNode>& node,
1791     std::list<RefPtr<NG::FrameNode>>& children, int32_t pageId)
1792 {
1793     std::list<RefPtr<NG::FrameNode>> frameNodeChildren;
1794     auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
1795     auto uiVirtualNode = accessibilityProperty->GetAccessibilityVirtualNode();
1796     if (uiVirtualNode != nullptr) {
1797         auto virtualNode = AceType::DynamicCast<NG::FrameNode>(uiVirtualNode);
1798         if (virtualNode != nullptr) {
1799             GetFrameNodeChildren(virtualNode, frameNodeChildren, pageId);
1800         }
1801     } else {
1802         for (const auto& item : node->GetChildren(true)) {
1803             GetFrameNodeChildren(item, frameNodeChildren, pageId);
1804         }
1805 
1806         auto overlayNode = node->GetOverlayNode();
1807         if (overlayNode != nullptr) {
1808             GetFrameNodeChildren(overlayNode, frameNodeChildren, pageId);
1809         }
1810     }
1811     while (!frameNodeChildren.empty()) {
1812         children.emplace_back(frameNodeChildren.front());
1813         frameNodeChildren.pop_front();
1814     }
1815 }
1816 }
1817 
UpdateVirtualNodeInfo(std::list<AccessibilityElementInfo> & infos,AccessibilityElementInfo & nodeInfo,const RefPtr<NG::UINode> & uiVirtualNode,const CommonProperty & commonProperty,const RefPtr<NG::PipelineContext> & ngPipeline)1818 void JsAccessibilityManager::UpdateVirtualNodeInfo(std::list<AccessibilityElementInfo>& infos,
1819     AccessibilityElementInfo& nodeInfo, const RefPtr<NG::UINode>& uiVirtualNode, const CommonProperty& commonProperty,
1820     const RefPtr<NG::PipelineContext>& ngPipeline)
1821 {
1822     for (const auto& item : uiVirtualNode->GetChildren(true)) {
1823         AccessibilityElementInfo virtualInfo;
1824         auto frameNodeChild = AceType::DynamicCast<NG::FrameNode>(item);
1825         if (frameNodeChild == nullptr) {
1826             continue;
1827         }
1828         UpdateVirtualNodeChildAccessibilityElementInfo(frameNodeChild, commonProperty,
1829             nodeInfo, virtualInfo, ngPipeline);
1830         virtualInfo.SetParent(uiVirtualNode->GetAccessibilityId());
1831         nodeInfo.AddChild(frameNodeChild->GetAccessibilityId());
1832         UpdateVirtualNodeInfo(infos, virtualInfo, item, commonProperty, ngPipeline);
1833         infos.push_back(virtualInfo);
1834     }
1835 }
1836 
1837 namespace {
SearchExtensionElementInfoNG(const SearchParameter & searchParam,const RefPtr<NG::FrameNode> & node,std::list<Accessibility::AccessibilityElementInfo> & infos,Accessibility::AccessibilityElementInfo & parentInfo)1838 void SearchExtensionElementInfoNG(const SearchParameter& searchParam,
1839     const RefPtr<NG::FrameNode>& node, std::list<Accessibility::AccessibilityElementInfo>& infos,
1840     Accessibility::AccessibilityElementInfo& parentInfo)
1841 {
1842     auto extensionElementInfos = SearchExtensionElementInfoByAccessibilityIdNG(
1843         searchParam.nodeId, searchParam.mode, node, searchParam.uiExtensionOffset);
1844     if (extensionElementInfos.size() > 0) {
1845         auto rootParentId = extensionElementInfos.front().GetParentNodeId();
1846         ConvertExtensionAccessibilityNodeId(extensionElementInfos, node, searchParam.uiExtensionOffset, parentInfo);
1847         if (rootParentId == NG::UI_EXTENSION_ROOT_ID) {
1848             extensionElementInfos.front().SetParent(node->GetAccessibilityId());
1849         }
1850         if (parentInfo.GetComponentType() == V2::ISOLATED_COMPONENT_ETS_TAG) {
1851             auto windowId = parentInfo.GetWindowId();
1852             for (auto& info : extensionElementInfos) {
1853                 info.SetWindowId(windowId);
1854             }
1855         }
1856         for (auto& info : extensionElementInfos) {
1857             infos.push_back(info);
1858         }
1859     }
1860 }
1861 
IsNodeInRoot(const RefPtr<NG::FrameNode> & node,const RefPtr<NG::PipelineContext> & ngPipeline)1862 bool IsNodeInRoot(const RefPtr<NG::FrameNode>& node, const RefPtr<NG::PipelineContext>& ngPipeline)
1863 {
1864     CHECK_NULL_RETURN(node, false);
1865     CHECK_NULL_RETURN(ngPipeline, false);
1866     auto rect = node->GetTransformRectRelativeToWindow();
1867     auto root = ngPipeline->GetRootElement();
1868     CHECK_NULL_RETURN(root, false);
1869     auto rootRect = root->GetTransformRectRelativeToWindow();
1870     return LessNotEqual(rect.GetX(), rootRect.GetX() + rootRect.Width());
1871 }
1872 }
1873 
UpdateCacheInfoNG(std::list<AccessibilityElementInfo> & infos,const RefPtr<NG::FrameNode> & node,const CommonProperty & commonProperty,const RefPtr<NG::PipelineContext> & ngPipeline,const SearchParameter & searchParam)1874 void JsAccessibilityManager::UpdateCacheInfoNG(std::list<AccessibilityElementInfo>& infos,
1875     const RefPtr<NG::FrameNode>& node, const CommonProperty& commonProperty,
1876     const RefPtr<NG::PipelineContext>& ngPipeline, const SearchParameter& searchParam)
1877 {
1878     uint32_t umode = searchParam.mode;
1879     std::list<RefPtr<NG::FrameNode>> children;
1880     // get all children
1881     if (!(umode & static_cast<uint32_t>(PREFETCH_RECURSIVE_CHILDREN))) {
1882         return;
1883     }
1884     GetChildrenFromFrameNode(node, children, commonProperty.pageId);
1885     while (!children.empty()) {
1886         RefPtr<NG::FrameNode> frameNodeParent = children.front();
1887         children.pop_front();
1888         AccessibilityElementInfo nodeInfo;
1889         auto accessibilityProperty = frameNodeParent->GetAccessibilityProperty<NG::AccessibilityProperty>();
1890         auto uiVirtualNode = accessibilityProperty->GetAccessibilityVirtualNode();
1891         UpdateAccessibilityElementInfo(frameNodeParent, commonProperty, nodeInfo, ngPipeline);
1892         if (uiVirtualNode != nullptr) {
1893             auto virtualNode = AceType::DynamicCast<NG::FrameNode>(uiVirtualNode);
1894             if (virtualNode == nullptr) {
1895                 continue;
1896             }
1897             AccessibilityElementInfo virtualInfo;
1898             UpdateVirtualNodeAccessibilityElementInfo(frameNodeParent, virtualNode,
1899                 commonProperty, virtualInfo, ngPipeline);
1900             virtualInfo.SetParent(frameNodeParent->GetAccessibilityId());
1901             auto childIds = nodeInfo.GetChildIds();
1902             for (auto& child : childIds) {
1903                 nodeInfo.RemoveChild(child);
1904             }
1905             nodeInfo.AddChild(virtualNode->GetAccessibilityId());
1906             auto uiParentNode = AceType::DynamicCast<NG::UINode>(frameNodeParent);
1907             if (!uiVirtualNode->GetChildren(true).empty()) {
1908                 UpdateVirtualNodeInfo(infos, virtualInfo, uiVirtualNode, commonProperty, ngPipeline);
1909             }
1910             infos.push_back(virtualInfo);
1911             infos.push_back(nodeInfo);
1912             continue;
1913         }
1914         if (!IsExtensionComponent(frameNodeParent) || IsUIExtensionShowPlaceholder(frameNodeParent)) {
1915             infos.push_back(nodeInfo);
1916             GetChildrenFromFrameNode(frameNodeParent, children, commonProperty.pageId);
1917             continue;
1918         }
1919         if (!((frameNodeParent->GetUiExtensionId() > NG::UI_EXTENSION_UNKNOW_ID) &&
1920             (((frameNodeParent->GetUiExtensionId() <= NG::UI_EXTENSION_ID_FIRST_MAX) &&
1921             (NG::UI_EXTENSION_OFFSET_MAX == searchParam.uiExtensionOffset)) ||
1922             (frameNodeParent->GetUiExtensionId() <= NG::UI_EXTENSION_ID_OTHER_MAX)))) {
1923             continue;
1924         }
1925         auto transferParam = searchParam;
1926         transferParam.nodeId = NG::UI_EXTENSION_ROOT_ID;
1927         SearchExtensionElementInfoNG(transferParam, frameNodeParent, infos, nodeInfo);
1928         infos.push_back(nodeInfo);
1929     }
1930 }
1931 
1932 namespace {
CanAccessibilityFocusedNG(const RefPtr<NG::FrameNode> & node)1933 bool CanAccessibilityFocusedNG(const RefPtr<NG::FrameNode>& node)
1934 {
1935     CHECK_NULL_RETURN(node, false);
1936     auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
1937     CHECK_NULL_RETURN(accessibilityProperty, false);
1938     auto level = accessibilityProperty->GetAccessibilityLevel();
1939     return !node->IsRootNode() &&
1940            node->GetLayoutProperty()->GetVisibilityValue(VisibleType::VISIBLE) == VisibleType::VISIBLE &&
1941            level != NG::AccessibilityProperty::Level::NO_STR &&
1942            level != NG::AccessibilityProperty::Level::NO_HIDE_DESCENDANTS;
1943 }
1944 // focus move search
AddFocusableNode(std::list<RefPtr<NG::FrameNode>> & nodeList,const RefPtr<NG::FrameNode> & node)1945 void AddFocusableNode(std::list<RefPtr<NG::FrameNode>>& nodeList, const RefPtr<NG::FrameNode>& node)
1946 {
1947     auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
1948     CHECK_NULL_VOID(accessibilityProperty);
1949     auto level = accessibilityProperty->GetAccessibilityLevel();
1950     if (CanAccessibilityFocusedNG(node)) {
1951         nodeList.emplace_back(node);
1952     }
1953 
1954     if (!accessibilityProperty->IsAccessibilityGroup() &&
1955         level != NG::AccessibilityProperty::Level::NO_HIDE_DESCENDANTS) {
1956         std::list<RefPtr<NG::FrameNode>> children;
1957         for (const auto& child : node->GetChildren(true)) {
1958             GetFrameNodeChildren(child, children);
1959         }
1960 
1961         for (const auto& child : children) {
1962             AddFocusableNode(nodeList, child);
1963         }
1964     }
1965 }
1966 
1967 // execute action
RequestFocus(RefPtr<NG::FrameNode> & frameNode)1968 bool RequestFocus(RefPtr<NG::FrameNode>& frameNode)
1969 {
1970     auto focusHub = frameNode->GetFocusHub();
1971     CHECK_NULL_RETURN(focusHub, false);
1972     return focusHub->RequestFocusImmediately();
1973 }
1974 
LostFocus(const RefPtr<NG::FrameNode> & frameNode)1975 bool LostFocus(const RefPtr<NG::FrameNode>& frameNode)
1976 {
1977     CHECK_NULL_RETURN(frameNode, false);
1978     auto focusHub = frameNode->GetFocusHub();
1979     CHECK_NULL_RETURN(focusHub, false);
1980     focusHub->LostFocus();
1981     return true;
1982 }
1983 
ActClick(RefPtr<NG::FrameNode> & frameNode)1984 bool ActClick(RefPtr<NG::FrameNode>& frameNode)
1985 {
1986     auto gesture = frameNode->GetEventHub<NG::EventHub>()->GetGestureEventHub();
1987     CHECK_NULL_RETURN(gesture, false);
1988     bool result = gesture->ActClick();
1989     auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
1990     CHECK_NULL_RETURN(accessibilityProperty, result);
1991     auto accessibilityAction = ACTIONS.find(ACCESSIBILITY_ACTION_CLICK);
1992     if (accessibilityAction == ACTIONS.end()) {
1993         return result;
1994     }
1995     AccessibilityActionParam param;
1996     param.accessibilityProperty = accessibilityProperty;
1997     result |= accessibilityAction->second(param);
1998     return result;
1999 }
2000 
ActLongClick(RefPtr<NG::FrameNode> & frameNode)2001 bool ActLongClick(RefPtr<NG::FrameNode>& frameNode)
2002 {
2003     auto gesture = frameNode->GetEventHub<NG::EventHub>()->GetGestureEventHub();
2004     CHECK_NULL_RETURN(gesture, false);
2005     return gesture->ActLongClick();
2006 }
2007 
ClearAccessibilityFocus(const RefPtr<NG::FrameNode> & root,int64_t focusNodeId)2008 void ClearAccessibilityFocus(const RefPtr<NG::FrameNode>& root, int64_t focusNodeId)
2009 {
2010     auto oldFocusNode = GetFramenodeByAccessibilityId(root, focusNodeId);
2011     CHECK_NULL_VOID(oldFocusNode);
2012     oldFocusNode->GetRenderContext()->UpdateAccessibilityFocus(false);
2013 }
2014 
ActAccessibilityFocus(int64_t elementId,RefPtr<NG::FrameNode> & frameNode,RefPtr<NG::PipelineContext> & context,int64_t & currentFocusNodeId,bool isNeedClear)2015 bool ActAccessibilityFocus(int64_t elementId, RefPtr<NG::FrameNode>& frameNode, RefPtr<NG::PipelineContext>& context,
2016     int64_t& currentFocusNodeId, bool isNeedClear)
2017 {
2018     CHECK_NULL_RETURN(frameNode, false);
2019     bool isAccessibilityVirtualNode = frameNode->IsAccessibilityVirtualNode();
2020     RefPtr<NG::RenderContext> renderContext = nullptr;
2021     if (isAccessibilityVirtualNode) {
2022         auto parentUinode = frameNode->GetVirtualNodeParent().Upgrade();
2023         CHECK_NULL_RETURN(parentUinode, false);
2024         auto parentFrame = AceType::DynamicCast<NG::FrameNode>(parentUinode);
2025         CHECK_NULL_RETURN(parentFrame, false);
2026         renderContext = parentFrame->GetRenderContext();
2027     } else {
2028         renderContext = frameNode->GetRenderContext();
2029     }
2030     CHECK_NULL_RETURN(renderContext, false);
2031     if (isNeedClear) {
2032         if (elementId != currentFocusNodeId) {
2033             return false;
2034         }
2035         renderContext->UpdateAccessibilityFocus(false);
2036         currentFocusNodeId = -1;
2037         auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
2038         CHECK_NULL_RETURN(accessibilityProperty, true);
2039         accessibilityProperty->OnAccessibilityFocusCallback(false);
2040         accessibilityProperty->SetAccessibilityFocusState(false);
2041         return true;
2042     }
2043     if (elementId == currentFocusNodeId) {
2044         return false;
2045     }
2046     Framework::ClearAccessibilityFocus(context->GetRootElement(), currentFocusNodeId);
2047     if (isAccessibilityVirtualNode) {
2048         auto rect = frameNode->GetTransformRectRelativeToWindow();
2049         NG::RectT<int32_t> rectInt { static_cast<int32_t>(rect.Left()), static_cast<int32_t>(rect.Top()),
2050             static_cast<int32_t>(rect.Width()), static_cast<int32_t>(rect.Height()) };
2051         renderContext->UpdateAccessibilityFocusRect(rectInt);
2052         renderContext->UpdateAccessibilityFocus(true, frameNode->GetAccessibilityId());
2053     } else {
2054         renderContext->ResetAccessibilityFocusRect();
2055         renderContext->UpdateAccessibilityFocus(true);
2056     }
2057     currentFocusNodeId = frameNode->GetAccessibilityId();
2058     auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
2059     CHECK_NULL_RETURN(accessibilityProperty, false);
2060     accessibilityProperty->OnAccessibilityFocusCallback(true);
2061     accessibilityProperty->SetAccessibilityFocusState(true);
2062     ProcessFocusScroll(frameNode, context);
2063     return true;
2064 }
2065 
GetSupportAction(const std::unordered_set<AceAction> & supportAceActions)2066 inline string GetSupportAction(const std::unordered_set<AceAction>& supportAceActions)
2067 {
2068     std::string actionForDump;
2069     for (const auto& action : supportAceActions) {
2070         if (!actionForDump.empty()) {
2071             actionForDump.append(",");
2072         }
2073         actionForDump.append(std::to_string(static_cast<int32_t>(action)));
2074     }
2075     return actionForDump;
2076 }
2077 
ConvertActionTypeToString(ActionType action)2078 static std::string ConvertActionTypeToString(ActionType action)
2079 {
2080     static const ActionStrTable actionStrTable[] = {
2081         { ActionType::ACCESSIBILITY_ACTION_FOCUS, "ACCESSIBILITY_ACTION_FOCUS" },
2082         { ActionType::ACCESSIBILITY_ACTION_CLEAR_FOCUS, "ACCESSIBILITY_ACTION_CLEAR_FOCUS" },
2083         { ActionType::ACCESSIBILITY_ACTION_SELECT, "ACCESSIBILITY_ACTION_SELECT" },
2084         { ActionType::ACCESSIBILITY_ACTION_CLEAR_SELECTION, "ACCESSIBILITY_ACTION_CLEAR_SELECTION" },
2085         { ActionType::ACCESSIBILITY_ACTION_CLICK, "ACCESSIBILITY_ACTION_CLICK" },
2086         { ActionType::ACCESSIBILITY_ACTION_LONG_CLICK, "ACCESSIBILITY_ACTION_LONG_CLICK" },
2087         { ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS, "ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS" },
2088         { ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS,
2089             "ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS" },
2090         { ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD, "ACCESSIBILITY_ACTION_SCROLL_FORWARD" },
2091         { ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD, "ACCESSIBILITY_ACTION_SCROLL_BACKWARD" },
2092         { ActionType::ACCESSIBILITY_ACTION_COPY, "ACCESSIBILITY_ACTION_COPY" },
2093         { ActionType::ACCESSIBILITY_ACTION_PASTE, "ACCESSIBILITY_ACTION_PASTE" },
2094         { ActionType::ACCESSIBILITY_ACTION_CUT, "ACCESSIBILITY_ACTION_CUT" },
2095         { ActionType::ACCESSIBILITY_ACTION_SET_SELECTION, "ACCESSIBILITY_ACTION_SET_SELECTION" },
2096         { ActionType::ACCESSIBILITY_ACTION_SET_TEXT, "ACCESSIBILITY_ACTION_SET_TEXT" },
2097         { ActionType::ACCESSIBILITY_ACTION_NEXT_TEXT, "ACCESSIBILITY_ACTION_NEXT_TEXT" },
2098         { ActionType::ACCESSIBILITY_ACTION_PREVIOUS_TEXT, "ACCESSIBILITY_ACTION_PREVIOUS_TEXT" },
2099         { ActionType::ACCESSIBILITY_ACTION_SET_CURSOR_POSITION, "ACCESSIBILITY_ACTION_SET_CURSOR_POSITION" },
2100         { ActionType::ACCESSIBILITY_ACTION_SPAN_CLICK, "ACCESSIBILITY_ACTION_SPAN_CLICK" },
2101     };
2102     for (const auto& item : actionStrTable) {
2103         if (action == item.action) {
2104             return item.actionStr;
2105         }
2106     }
2107     return ACTION_DEFAULT_PARAM;
2108 }
2109 
ConvertAccessibilityAction(ActionType accessibilityAction)2110 static AceAction ConvertAccessibilityAction(ActionType accessibilityAction)
2111 {
2112     static const ActionTable actionTable[] = {
2113         { AceAction::ACTION_CLICK, ActionType::ACCESSIBILITY_ACTION_CLICK },
2114         { AceAction::ACTION_LONG_CLICK, ActionType::ACCESSIBILITY_ACTION_LONG_CLICK },
2115         { AceAction::ACTION_SCROLL_FORWARD, ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD },
2116         { AceAction::ACTION_SCROLL_BACKWARD, ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD },
2117         { AceAction::ACTION_FOCUS, ActionType::ACCESSIBILITY_ACTION_FOCUS },
2118         { AceAction::ACTION_CLEAR_FOCUS, ActionType::ACCESSIBILITY_ACTION_CLEAR_FOCUS },
2119         { AceAction::ACTION_ACCESSIBILITY_FOCUS, ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS },
2120         { AceAction::ACTION_CLEAR_ACCESSIBILITY_FOCUS, ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS },
2121         { AceAction::ACTION_NEXT_AT_MOVEMENT_GRANULARITY, ActionType::ACCESSIBILITY_ACTION_NEXT_TEXT },
2122         { AceAction::ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, ActionType::ACCESSIBILITY_ACTION_PREVIOUS_TEXT },
2123         { AceAction::ACTION_SET_TEXT, ActionType::ACCESSIBILITY_ACTION_SET_TEXT },
2124         { AceAction::ACTION_COPY, ActionType::ACCESSIBILITY_ACTION_COPY },
2125         { AceAction::ACTION_PASTE, ActionType::ACCESSIBILITY_ACTION_PASTE },
2126         { AceAction::ACTION_CUT, ActionType::ACCESSIBILITY_ACTION_CUT },
2127         { AceAction::ACTION_SELECT, ActionType::ACCESSIBILITY_ACTION_SELECT },
2128         { AceAction::ACTION_CLEAR_SELECTION, ActionType::ACCESSIBILITY_ACTION_CLEAR_SELECTION },
2129         { AceAction::ACTION_SET_SELECTION, ActionType::ACCESSIBILITY_ACTION_SET_SELECTION },
2130         { AceAction::ACTION_SET_CURSOR_POSITION, ActionType::ACCESSIBILITY_ACTION_SET_CURSOR_POSITION },
2131         { AceAction::ACTION_EXEC_SUB_COMPONENT, ActionType::ACCESSIBILITY_ACTION_SPAN_CLICK },
2132     };
2133     for (const auto& item : actionTable) {
2134         if (accessibilityAction == item.action) {
2135             return item.aceAction;
2136         }
2137     }
2138     return AceAction::ACTION_NONE;
2139 }
2140 
DumpSupportActionNG(const AccessibilityElementInfo & nodeInfo)2141 static void DumpSupportActionNG(const AccessibilityElementInfo& nodeInfo)
2142 {
2143     DumpLog::GetInstance().AddDesc(
2144         "support action instructions: use command to make application components perform corresponding action");
2145     DumpLog::GetInstance().AddDesc(
2146         "use support action command: aa dump -i [AbilityRecord] -c -inspector [AccessibilityId] [AceAction]");
2147     std::string actionForDump;
2148     for (const auto& action : nodeInfo.GetActionList()) {
2149         if (!actionForDump.empty()) {
2150             actionForDump.append(",");
2151         }
2152         actionForDump.append(ConvertActionTypeToString(action.GetActionType()));
2153         actionForDump.append(": ");
2154         actionForDump.append(std::to_string(static_cast<int32_t>(ConvertAccessibilityAction(action.GetActionType()))));
2155     }
2156     DumpLog::GetInstance().AddDesc("support action: ", actionForDump);
2157 }
2158 
DumpContentListNG(const AccessibilityElementInfo & nodeInfo)2159 inline void DumpContentListNG(const AccessibilityElementInfo& nodeInfo)
2160 {
2161     std::vector<std::string> contentList;
2162     nodeInfo.GetContentList(contentList);
2163     std::string contents;
2164     for (auto content : contentList) {
2165         if (!contents.empty()) {
2166             contents.append(",");
2167         }
2168         contents.append(content);
2169     }
2170     DumpLog::GetInstance().AddDesc("content list: ", contents);
2171 }
2172 
DumpExtraElementInfoNG(const AccessibilityElementInfo & nodeInfo)2173 static void DumpExtraElementInfoNG(const AccessibilityElementInfo& nodeInfo)
2174 {
2175     ExtraElementInfo extraElementInfo = nodeInfo.GetExtraElement();
2176     if (!extraElementInfo.GetExtraElementInfoValueStr().empty()) {
2177         for (auto i = extraElementInfo.GetExtraElementInfoValueStr().begin();
2178              i != extraElementInfo.GetExtraElementInfoValueStr().end(); ++i) {
2179             DumpLog::GetInstance().AddDesc("extra element info: ", i->first, i->second);
2180         }
2181     }
2182     if (!extraElementInfo.GetExtraElementInfoValueInt().empty()) {
2183         for (auto i = extraElementInfo.GetExtraElementInfoValueInt().begin();
2184              i != extraElementInfo.GetExtraElementInfoValueInt().end(); ++i) {
2185             DumpLog::GetInstance().AddDesc("extra element info: ", i->first, i->second);
2186         }
2187     }
2188 }
2189 
UpdateSpanList(std::vector<SpanInfo> & spansInfosList,std::string & spans)2190 static void UpdateSpanList(std::vector<SpanInfo>& spansInfosList, std::string& spans)
2191 {
2192     for (const auto& span : spansInfosList) {
2193         if (!spans.empty()) {
2194             spans.append(",");
2195         }
2196         spans.append("\n\t span id: ");
2197         spans.append(std::to_string(span.GetSpanId()));
2198         spans.append(", span text: ");
2199         spans.append(span.GetSpanText());
2200         spans.append(", accessibility text: ");
2201         spans.append(span.GetAccessibilityText());
2202         spans.append(", accessibility description: ");
2203         spans.append(span.GetAccessibilityDescription());
2204         spans.append(", accessibility level: ");
2205         spans.append(span.GetAccessibilityLevel());
2206     }
2207 }
2208 
DumpSpanListNG(const AccessibilityElementInfo & nodeInfo)2209 inline void DumpSpanListNG(const AccessibilityElementInfo& nodeInfo)
2210 {
2211     std::string spans;
2212     std::vector<SpanInfo> spansInfosList = nodeInfo.GetSpanList();
2213     std::size_t spanCount = spansInfosList.size();
2214     UpdateSpanList(spansInfosList, spans);
2215     DumpLog::GetInstance().AddDesc("span list count: ", static_cast<int32_t>(spanCount));
2216     DumpLog::GetInstance().AddDesc("span list: ", spans);
2217 }
2218 
ChildrenToString(const std::vector<int64_t> & children,int32_t treeId)2219 inline std::string ChildrenToString(const std::vector<int64_t>& children, int32_t treeId)
2220 {
2221     std::string ids;
2222     for (auto child : children) {
2223         if (!ids.empty()) {
2224             ids.append(",");
2225         }
2226         int64_t childId = child;
2227         AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(treeId, childId);
2228         ids.append(std::to_string(childId));
2229     }
2230     return ids;
2231 }
2232 
DumpRectNG(const Accessibility::Rect & rect)2233 inline void DumpRectNG(const Accessibility::Rect& rect)
2234 {
2235     DumpLog::GetInstance().AddDesc(
2236         "width: ", std::to_string(rect.GetRightBottomXScreenPostion() - rect.GetLeftTopXScreenPostion()));
2237     DumpLog::GetInstance().AddDesc(
2238         "height: ", std::to_string(rect.GetRightBottomYScreenPostion() - rect.GetLeftTopYScreenPostion()));
2239     DumpLog::GetInstance().AddDesc("left: ", std::to_string(rect.GetLeftTopXScreenPostion()));
2240     DumpLog::GetInstance().AddDesc("top: ", std::to_string(rect.GetLeftTopYScreenPostion()));
2241     DumpLog::GetInstance().AddDesc("right: ", std::to_string(rect.GetRightBottomXScreenPostion()));
2242     DumpLog::GetInstance().AddDesc("bottom: ", std::to_string(rect.GetRightBottomYScreenPostion()));
2243 }
2244 
GenerateAccessibilityEventInfo(const AccessibilityEvent & accessibilityEvent,AccessibilityEventInfo & eventInfo)2245 void GenerateAccessibilityEventInfo(const AccessibilityEvent& accessibilityEvent, AccessibilityEventInfo& eventInfo)
2246 {
2247     Accessibility::EventType type = Accessibility::EventType::TYPE_VIEW_INVALID;
2248     if (accessibilityEvent.type != AccessibilityEventType::UNKNOWN) {
2249         type = ConvertAceEventType(accessibilityEvent.type);
2250     } else {
2251         type = ConvertStrToEventType(accessibilityEvent.eventType);
2252     }
2253 
2254     if (type == Accessibility::EventType::TYPE_VIEW_INVALID) {
2255         return;
2256     }
2257 
2258     eventInfo.SetTimeStamp(GetMicroTickCount());
2259     eventInfo.SetBeforeText(accessibilityEvent.beforeText);
2260     eventInfo.SetLatestContent(accessibilityEvent.latestContent);
2261     eventInfo.SetTextAnnouncedForAccessibility(accessibilityEvent.textAnnouncedForAccessibility);
2262     eventInfo.SetWindowChangeTypes(static_cast<Accessibility::WindowUpdateType>(accessibilityEvent.windowChangeTypes));
2263     eventInfo.SetWindowContentChangeTypes(
2264         static_cast<Accessibility::WindowsContentChangeTypes>(accessibilityEvent.windowContentChangeTypes));
2265     eventInfo.SetSource(accessibilityEvent.nodeId);
2266     eventInfo.SetEventType(type);
2267     eventInfo.SetCurrentIndex(static_cast<int>(accessibilityEvent.currentItemIndex));
2268     eventInfo.SetItemCounts(static_cast<int>(accessibilityEvent.itemCount));
2269     eventInfo.SetBundleName(AceApplicationInfo::GetInstance().GetPackageName());
2270 }
2271 } // namespace
2272 
DumpAccessibilityPropertyNG(const AccessibilityElementInfo & nodeInfo)2273 void JsAccessibilityManager::DumpAccessibilityPropertyNG(const AccessibilityElementInfo& nodeInfo)
2274 {
2275     DumpLog::GetInstance().AddDesc("checked: ", BoolToString(nodeInfo.IsChecked()));
2276     DumpLog::GetInstance().AddDesc("selected: ", BoolToString(nodeInfo.IsSelected()));
2277     DumpLog::GetInstance().AddDesc("checkable: ", BoolToString(nodeInfo.IsCheckable()));
2278     DumpLog::GetInstance().AddDesc("scrollable: ", BoolToString(nodeInfo.IsScrollable()));
2279     DumpLog::GetInstance().AddDesc("accessibility hint: ", BoolToString(nodeInfo.IsGivingHint()));
2280     DumpLog::GetInstance().AddDesc("hint text: ", nodeInfo.GetHint());
2281     DumpLog::GetInstance().AddDesc("error text: ", nodeInfo.GetError());
2282     DumpLog::GetInstance().AddDesc("max text length: ", nodeInfo.GetTextLengthLimit());
2283     DumpLog::GetInstance().AddDesc("scroll offset: ", nodeInfo.GetOffset());
2284     DumpLog::GetInstance().AddDesc("text selection start: ", nodeInfo.GetSelectedBegin());
2285     DumpLog::GetInstance().AddDesc("text selection end: ", nodeInfo.GetSelectedEnd());
2286     DumpLog::GetInstance().AddDesc("is multi line: ", BoolToString(nodeInfo.IsPluraLineSupported()));
2287     DumpLog::GetInstance().AddDesc("is password: ", BoolToString(nodeInfo.IsPassword()));
2288     DumpLog::GetInstance().AddDesc(
2289         "text input type: ", ConvertInputTypeToString(static_cast<AceTextCategory>(nodeInfo.GetInputType())));
2290 
2291     DumpLog::GetInstance().AddDesc("min value: ", nodeInfo.GetRange().GetMin());
2292     DumpLog::GetInstance().AddDesc("max value: ", nodeInfo.GetRange().GetMax());
2293     DumpLog::GetInstance().AddDesc("current value: ", nodeInfo.GetRange().GetCurrent());
2294     DumpLog::GetInstance().AddDesc("grid info rows: ", nodeInfo.GetGrid().GetRowCount());
2295     DumpLog::GetInstance().AddDesc("grid info columns: ", nodeInfo.GetGrid().GetColumnCount());
2296     DumpLog::GetInstance().AddDesc("grid info select mode: ", nodeInfo.GetGrid().GetSelectionMode());
2297     DumpLog::GetInstance().AddDesc("grid item info, row: ", nodeInfo.GetGridItem().GetRowIndex());
2298     DumpLog::GetInstance().AddDesc("grid item info, column: ", nodeInfo.GetGridItem().GetColumnIndex());
2299     DumpLog::GetInstance().AddDesc("grid item info, rowSpan: ", nodeInfo.GetGridItem().GetRowSpan());
2300     DumpLog::GetInstance().AddDesc("grid item info, columnSpan: ", nodeInfo.GetGridItem().GetColumnSpan());
2301     DumpLog::GetInstance().AddDesc("grid item info, is heading: ", nodeInfo.GetGridItem().IsHeading());
2302     DumpLog::GetInstance().AddDesc("grid item info, selected: ", nodeInfo.GetGridItem().IsSelected());
2303     DumpLog::GetInstance().AddDesc("current index: ", nodeInfo.GetCurrentIndex());
2304     DumpLog::GetInstance().AddDesc("begin index: ", nodeInfo.GetBeginIndex());
2305     DumpLog::GetInstance().AddDesc("end index: ", nodeInfo.GetEndIndex());
2306     DumpLog::GetInstance().AddDesc("collection item counts: ", nodeInfo.GetItemCounts());
2307     DumpLog::GetInstance().AddDesc("editable: ", BoolToString(nodeInfo.IsEditable()));
2308     DumpLog::GetInstance().AddDesc("is essential: ", BoolToString(nodeInfo.IsEssential()));
2309     DumpLog::GetInstance().AddDesc("deletable: ", nodeInfo.IsDeletable());
2310     DumpLog::GetInstance().AddDesc("live region: ", nodeInfo.GetLiveRegion());
2311     DumpLog::GetInstance().AddDesc("content description: ", nodeInfo.GetDescriptionInfo());
2312     DumpLog::GetInstance().AddDesc("content invalid: ", BoolToString(nodeInfo.GetContentInvalid()));
2313     DumpLog::GetInstance().AddDesc("accessibility label: ", nodeInfo.GetLabeledAccessibilityId());
2314     DumpLog::GetInstance().AddDesc("accessibilityVisible: ", nodeInfo.GetAccessibilityVisible());
2315     DumpExtraElementInfoNG(nodeInfo);
2316     DumpLog::GetInstance().AddDesc(
2317         "trigger action: ", static_cast<int32_t>(ConvertAccessibilityAction(nodeInfo.GetTriggerAction())));
2318     DumpLog::GetInstance().AddDesc("text move step: " + std::to_string(nodeInfo.GetTextMovementStep()));
2319     DumpSpanListNG(nodeInfo);
2320     DumpSupportActionNG(nodeInfo);
2321     DumpContentListNG(nodeInfo);
2322     DumpLog::GetInstance().AddDesc("latest content: ", nodeInfo.GetLatestContent());
2323 }
2324 
DumpCommonPropertyNG(const AccessibilityElementInfo & nodeInfo,int32_t treeId)2325 void JsAccessibilityManager::DumpCommonPropertyNG(const AccessibilityElementInfo& nodeInfo, int32_t treeId)
2326 {
2327     int64_t elementId = nodeInfo.GetAccessibilityId();
2328     AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(treeId, elementId);
2329     DumpLog::GetInstance().AddDesc("ID: ", elementId);
2330     int64_t parentId = nodeInfo.GetParentNodeId();
2331     AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(treeId, parentId);
2332     DumpLog::GetInstance().AddDesc("parent ID: ", parentId);
2333     DumpLog::GetInstance().AddDesc("child IDs: ", ChildrenToString(nodeInfo.GetChildIds(), treeId));
2334     DumpLog::GetInstance().AddDesc("component type: ", nodeInfo.GetComponentType());
2335     DumpLog::GetInstance().AddDesc("text: ", nodeInfo.GetContent());
2336     DumpLog::GetInstance().AddDesc("window id: " + std::to_string(nodeInfo.GetWindowId()));
2337     DumpRectNG(nodeInfo.GetRectInScreen());
2338 
2339     DumpLog::GetInstance().AddDesc("enabled: ", BoolToString(nodeInfo.IsEnabled()));
2340     DumpLog::GetInstance().AddDesc("focusable: ", BoolToString(nodeInfo.IsFocusable()));
2341     DumpLog::GetInstance().AddDesc("focused: ", BoolToString(nodeInfo.IsFocused()));
2342     DumpLog::GetInstance().AddDesc("visible: ", BoolToString(nodeInfo.IsVisible()));
2343     DumpLog::GetInstance().AddDesc("accessibility focused: ", BoolToString(nodeInfo.HasAccessibilityFocus()));
2344     DumpLog::GetInstance().AddDesc("accessibilityText: " + nodeInfo.GetAccessibilityText());
2345     DumpLog::GetInstance().AddDesc("accessibilityGroup: " + BoolToString(nodeInfo.GetAccessibilityGroup()));
2346     DumpLog::GetInstance().AddDesc("accessibilityLevel: " + nodeInfo.GetAccessibilityLevel());
2347     DumpLog::GetInstance().AddDesc("accessibilityDescription: " + nodeInfo.GetDescriptionInfo());
2348     DumpLog::GetInstance().AddDesc("hitTestBehavior: " + nodeInfo.GetHitTestBehavior());
2349 
2350     DumpLog::GetInstance().AddDesc("inspector key: ", nodeInfo.GetInspectorKey());
2351     DumpLog::GetInstance().AddDesc("bundle name: ", nodeInfo.GetBundleName());
2352     DumpLog::GetInstance().AddDesc("page id: " + std::to_string(nodeInfo.GetPageId()));
2353     DumpLog::GetInstance().AddDesc("page path: ", nodeInfo.GetPagePath());
2354     DumpLog::GetInstance().AddDesc("is valid element: ", BoolToString(nodeInfo.IsValidElement()));
2355     DumpLog::GetInstance().AddDesc("resource name: ", nodeInfo.GetComponentResourceId());
2356 
2357     DumpLog::GetInstance().AddDesc("clickable: ", BoolToString(nodeInfo.IsClickable()));
2358     DumpLog::GetInstance().AddDesc("long clickable: ", BoolToString(nodeInfo.IsLongClickable()));
2359     DumpLog::GetInstance().AddDesc("popup supported: ", BoolToString(nodeInfo.IsPopupSupported()));
2360     DumpLog::GetInstance().AddDesc("zindex: ", std::to_string(nodeInfo.GetZIndex()));
2361 }
2362 
UpdateVirtualNodeFocus()2363 void JsAccessibilityManager::UpdateVirtualNodeFocus()
2364 {
2365     auto frameNode = lastFrameNode_.Upgrade();
2366     CHECK_NULL_VOID(frameNode);
2367     if (!frameNode->IsAccessibilityVirtualNode()) {
2368         return;
2369     }
2370     RefPtr<NG::RenderContext> renderContext;
2371     auto geometryNode = frameNode->GetGeometryNode();
2372     CHECK_NULL_VOID(geometryNode);
2373     bool frameSizeChange = geometryNode->GetFrameSize() != oldGeometrySize_;
2374     if (frameNode->GetAccessibilityId() == currentFocusNodeId_ && frameSizeChange) {
2375         auto parentUinode = frameNode->GetVirtualNodeParent().Upgrade();
2376         CHECK_NULL_VOID(parentUinode);
2377         auto parentFrame = AceType::DynamicCast<NG::FrameNode>(parentUinode);
2378         CHECK_NULL_VOID(parentFrame);
2379         renderContext = parentFrame->GetRenderContext();
2380         CHECK_NULL_VOID(renderContext);
2381         renderContext->UpdateAccessibilityFocus(false);
2382         auto rect = frameNode->GetTransformRectRelativeToWindow();
2383         NG::RectT<int32_t> rectInt { static_cast<int32_t>(rect.Left()), static_cast<int32_t>(rect.Top()),
2384             static_cast<int32_t>(rect.Width()), static_cast<int32_t>(rect.Height()) };
2385         renderContext->UpdateAccessibilityFocusRect(rectInt);
2386         renderContext->UpdateAccessibilityFocus(true, frameNode->GetAccessibilityId());
2387         auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
2388         CHECK_NULL_VOID(accessibilityProperty);
2389         accessibilityProperty->SetAccessibilityFocusState(true);
2390     }
2391 }
2392 
~JsAccessibilityManager()2393 JsAccessibilityManager::~JsAccessibilityManager()
2394 {
2395     auto eventType = AccessibilityStateEventType::EVENT_ACCESSIBILITY_STATE_CHANGED;
2396 
2397     UnsubscribeStateObserver(eventType);
2398 
2399     DeregisterInteractionOperation();
2400 }
OnConfigChanged(const AccessibilityConfig::CONFIG_ID id,const AccessibilityConfig::ConfigValue & value)2401 void JsAccessibilityManager::ToastAccessibilityConfigObserver::OnConfigChanged(
2402     const AccessibilityConfig::CONFIG_ID id, const AccessibilityConfig::ConfigValue& value)
2403 {
2404     TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "accessibility content timeout changed:%{public}u", value.contentTimeout);
2405     AceApplicationInfo::GetInstance().SetBarrierfreeDuration((int32_t)value.contentTimeout);
2406 }
2407 
SubscribeToastObserver()2408 bool JsAccessibilityManager::SubscribeToastObserver()
2409 {
2410     if (!toastObserver_) {
2411         toastObserver_ = std::make_shared<ToastAccessibilityConfigObserver>();
2412     }
2413     CHECK_NULL_RETURN(toastObserver_, false);
2414     auto& config = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
2415     bool isSuccess = config.InitializeContext();
2416     if (!isSuccess) {
2417         return false;
2418     }
2419     config.SubscribeConfigObserver(CONFIG_CONTENT_TIMEOUT, toastObserver_);
2420     return true;
2421 }
2422 
UnsubscribeToastObserver()2423 bool JsAccessibilityManager::UnsubscribeToastObserver()
2424 {
2425     CHECK_NULL_RETURN(toastObserver_, false);
2426     auto& config = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
2427     bool isSuccess = config.InitializeContext();
2428     if (!isSuccess) {
2429         return false;
2430     }
2431     config.UnsubscribeConfigObserver(CONFIG_CONTENT_TIMEOUT, toastObserver_);
2432     return true;
2433 }
2434 
SubscribeStateObserver(int eventType)2435 bool JsAccessibilityManager::SubscribeStateObserver(int eventType)
2436 {
2437     if (!stateObserver_) {
2438         stateObserver_ = std::make_shared<JsAccessibilityStateObserver>();
2439     }
2440 
2441     stateObserver_->SetAccessibilityManager(WeakClaim(this));
2442     stateObserver_->SetPipeline(context_);
2443 
2444     auto instance = AccessibilitySystemAbilityClient::GetInstance();
2445     CHECK_NULL_RETURN(instance, false);
2446     Accessibility::RetError ret = instance->SubscribeStateObserver(stateObserver_, eventType);
2447     TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, " the result of SubscribeStateObserver:%{public}d", ret);
2448     return ret == RET_OK;
2449 }
2450 
UnsubscribeStateObserver(int eventType)2451 bool JsAccessibilityManager::UnsubscribeStateObserver(int eventType)
2452 {
2453     CHECK_NULL_RETURN(stateObserver_, false);
2454     std::shared_ptr<AccessibilitySystemAbilityClient> instance = AccessibilitySystemAbilityClient::GetInstance();
2455     CHECK_NULL_RETURN(instance, false);
2456     Accessibility::RetError ret = instance->UnsubscribeStateObserver(stateObserver_, eventType);
2457     return ret == RET_OK;
2458 }
2459 
InitializeCallback()2460 void JsAccessibilityManager::InitializeCallback()
2461 {
2462     if (IsRegister()) {
2463         return;
2464     }
2465 
2466     auto pipelineContext = GetPipelineContext().Upgrade();
2467     CHECK_NULL_VOID(pipelineContext);
2468     windowId_ = pipelineContext->GetWindowId();
2469 
2470     auto client = AccessibilitySystemAbilityClient::GetInstance();
2471     CHECK_NULL_VOID(client);
2472     bool isEnabled = false;
2473     client->IsEnabled(isEnabled);
2474     AceApplicationInfo::GetInstance().SetAccessibilityEnabled(isEnabled);
2475 
2476     if (pipelineContext->IsFormRender() || pipelineContext->IsJsCard() || pipelineContext->IsJsPlugin()) {
2477         return;
2478     }
2479 
2480     auto container = Platform::AceContainer::GetContainer(pipelineContext->GetInstanceId());
2481     if (container != nullptr && container->IsUIExtensionWindow()) {
2482         pipelineContext->AddUIExtensionCallbackEvent(OHOS::Ace::NG::UIExtCallbackEventId::ON_UEA_ACCESSIBILITY_READY);
2483         return;
2484     }
2485 
2486     SubscribeStateObserver(AccessibilityStateEventType::EVENT_ACCESSIBILITY_STATE_CHANGED);
2487     if (isEnabled) {
2488         RegisterInteractionOperation(windowId_);
2489     }
2490 }
2491 
SendAccessibilitySyncEvent(const AccessibilityEvent & accessibilityEvent,AccessibilityEventInfo eventInfo)2492 bool JsAccessibilityManager::SendAccessibilitySyncEvent(
2493     const AccessibilityEvent& accessibilityEvent, AccessibilityEventInfo eventInfo)
2494 {
2495     if (!IsRegister()) {
2496         return false;
2497     }
2498     auto client = AccessibilitySystemAbilityClient::GetInstance();
2499     CHECK_NULL_RETURN(client, false);
2500     bool isEnabled = false;
2501     client->IsEnabled(isEnabled);
2502     if (!isEnabled) {
2503         return false;
2504     }
2505     AccessibilityElementInfo info = eventInfo.GetElementInfo();
2506     int64_t elementId = eventInfo.GetAccessibilityId();
2507     if (info.GetBelongTreeId() > 0) {
2508         AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(info.GetBelongTreeId(), elementId);
2509     }
2510     eventInfo.SetSource(elementId);
2511     UpdateElementInfoTreeId(info);
2512     eventInfo.SetElementInfo(info);
2513     eventInfo.SetPageId(info.GetPageId());
2514     TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY,
2515         "send accessibility componentType:%{public}s event:%{public}d accessibilityId:%{public}" PRId64,
2516         eventInfo.GetComponentType().c_str(), eventInfo.GetEventType(), eventInfo.GetAccessibilityId());
2517     return client->SendEvent(eventInfo);
2518 }
2519 
TransferAccessibilityAsyncEvent(const AccessibilityEventInfo & eventInfo,int64_t uiExtensionOffset)2520 bool JsAccessibilityManager::TransferAccessibilityAsyncEvent(
2521     const AccessibilityEventInfo& eventInfo, int64_t uiExtensionOffset)
2522 {
2523 #ifdef WINDOW_SCENE_SUPPORTED
2524     auto client = AccessibilitySystemAbilityClient::GetInstance();
2525     CHECK_NULL_RETURN(client, false);
2526     bool isEnabled = false;
2527     client->IsEnabled(isEnabled);
2528     if (!isEnabled) {
2529         return false;
2530     }
2531 
2532     auto pipeline = context_.Upgrade();
2533     CHECK_NULL_RETURN(pipeline, false);
2534     RefPtr<NG::PipelineContext> ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipeline);
2535     CHECK_NULL_RETURN(ngPipeline, false);
2536     auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
2537     CHECK_NULL_RETURN(uiExtensionManager, false);
2538     auto container = Container::GetContainer(ngPipeline->GetInstanceId());
2539     bool isDynamicRender = container && container->IsDynamicRender();
2540     if (!IsRegister() && !isDynamicRender) {
2541         return false;
2542     }
2543     AccessibilityEventInfo eventInfoNew = eventInfo;
2544     if (isDynamicRender) {
2545         auto focusedContainer = Container::GetFoucsed();
2546         if (focusedContainer) {
2547             eventInfoNew.SetWindowId(focusedContainer->GetWindowId());
2548         }
2549     }
2550     eventInfoNew.SetSource(uiExtensionOffset * GetUiextensionId() + eventInfo.GetViewId());
2551     AccessibilityElementInfo elementInfo;
2552     FillElementInfo(eventInfoNew.GetAccessibilityId(), elementInfo, pipeline, Claim(this),
2553         FillEventInfoParam { eventInfoNew.GetAccessibilityId(), -1, eventInfoNew.GetWindowId() });
2554     eventInfoNew.SetElementInfo(elementInfo);
2555     TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "send accessibility event:%{public}d accessibilityId:%{public}" PRId64,
2556         eventInfoNew.GetEventType(), eventInfoNew.GetAccessibilityId());
2557     return client->SendEvent(eventInfoNew);
2558 #endif
2559     return false;
2560 }
2561 
SendExtensionAccessibilityEvent(const AccessibilityEventInfo & eventInfo,int64_t uiExtensionOffset)2562 void JsAccessibilityManager::SendExtensionAccessibilityEvent(
2563     const AccessibilityEventInfo& eventInfo, int64_t uiExtensionOffset)
2564 {
2565     TransferAccessibilityAsyncEvent(eventInfo, uiExtensionOffset);
2566 }
2567 
FillEventInfoWithNode(const RefPtr<NG::FrameNode> & node,AccessibilityEventInfo & eventInfo,const RefPtr<NG::PipelineContext> & context,int64_t elementId)2568 void JsAccessibilityManager::FillEventInfoWithNode(
2569     const RefPtr<NG::FrameNode>& node,
2570     AccessibilityEventInfo& eventInfo,
2571     const RefPtr<NG::PipelineContext>& context,
2572     int64_t elementId)
2573 {
2574     CHECK_NULL_VOID(node);
2575     eventInfo.SetComponentType(node->GetTag());
2576     eventInfo.SetPageId(node->GetPageId());
2577     auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
2578     CHECK_NULL_VOID(accessibilityProperty);
2579     eventInfo.AddContent(accessibilityProperty->GetGroupText());
2580     eventInfo.SetItemCounts(accessibilityProperty->GetCollectionItemCounts());
2581     eventInfo.SetBeginIndex(accessibilityProperty->GetBeginIndex());
2582     eventInfo.SetEndIndex(accessibilityProperty->GetEndIndex());
2583     AccessibilityElementInfo elementInfo;
2584 
2585     CommonProperty commonProperty;
2586     auto mainContext = context_.Upgrade();
2587     CHECK_NULL_VOID(mainContext);
2588     GenerateCommonProperty(context, commonProperty, mainContext);
2589     UpdateAccessibilityElementInfo(node, commonProperty, elementInfo, context);
2590     elementInfo.SetWindowId(eventInfo.GetWindowId());
2591     eventInfo.SetElementInfo(elementInfo);
2592 }
2593 
GetDelayTimeBeforeSendEvent(const AccessibilityEvent & accessibilityEvent,const RefPtr<AceType> & node)2594 int64_t JsAccessibilityManager::GetDelayTimeBeforeSendEvent(
2595     const AccessibilityEvent& accessibilityEvent,
2596     const RefPtr<AceType>& node)
2597 {
2598     if (accessibilityEvent.type != AccessibilityEventType::CLICK) {
2599         return 0;
2600     }
2601 
2602     auto frameNode = AceType::DynamicCast<NG::FrameNode>(node);
2603     if (frameNode) {
2604         if (IsUserCheckedOrSelected(frameNode)) {
2605             return DELAY_SEND_EVENT_MILLISECOND;
2606         }
2607     } else {
2608         auto context = GetPipelineContext().Upgrade();
2609         if (!AceType::InstanceOf<NG::PipelineContext>(context)) {
2610             return 0;
2611         }
2612         RefPtr<NG::FrameNode> findeNode;
2613         auto ngPipeline = FindPipelineByElementId(accessibilityEvent.nodeId, findeNode);
2614         if ((findeNode) && IsUserCheckedOrSelected(findeNode)) {
2615             return DELAY_SEND_EVENT_MILLISECOND;
2616         }
2617     }
2618 
2619     return 0;
2620 }
2621 
SendEventToAccessibilityWithNode(const AccessibilityEvent & accessibilityEvent,const RefPtr<AceType> & node,const RefPtr<PipelineBase> & context)2622 void JsAccessibilityManager::SendEventToAccessibilityWithNode(
2623     const AccessibilityEvent& accessibilityEvent, const RefPtr<AceType>& node, const RefPtr<PipelineBase>& context)
2624 {
2625     auto delayTime = GetDelayTimeBeforeSendEvent(accessibilityEvent, node);
2626     if ((delayTime > 0) && context) {
2627         context->GetTaskExecutor()->PostDelayedTask(
2628             [weak = WeakClaim(this), accessibilityEvent, node, context] {
2629                 auto jsAccessibilityManager = weak.Upgrade();
2630                 CHECK_NULL_VOID(jsAccessibilityManager);
2631                 jsAccessibilityManager->SendEventToAccessibilityWithNodeInner(accessibilityEvent, node, context);
2632             },
2633             TaskExecutor::TaskType::UI, delayTime, "ArkUIAccessibilitySendSyncEventWithDelay");
2634         return;
2635     }
2636     SendEventToAccessibilityWithNodeInner(accessibilityEvent, node, context);
2637 }
2638 
SendEventToAccessibilityWithNodeInner(const AccessibilityEvent & accessibilityEvent,const RefPtr<AceType> & node,const RefPtr<PipelineBase> & context)2639 void JsAccessibilityManager::SendEventToAccessibilityWithNodeInner(
2640     const AccessibilityEvent& accessibilityEvent, const RefPtr<AceType>& node, const RefPtr<PipelineBase>& context)
2641 {
2642     ACE_ACCESS_SCOPED_TRACE("SendAccessibilityAsyncEvent");
2643     CHECK_NULL_VOID(node);
2644     CHECK_NULL_VOID(context);
2645     int32_t windowId = static_cast<int32_t>(context->GetRealHostWindowId());
2646     if (windowId == 0) {
2647         return;
2648     }
2649     if (!AceType::InstanceOf<NG::FrameNode>(node)) {
2650         return;
2651     }
2652     auto frameNode = AceType::DynamicCast<NG::FrameNode>(node);
2653     CHECK_NULL_VOID(frameNode);
2654     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
2655     CHECK_NULL_VOID(ngPipeline);
2656 
2657     if ((!frameNode->IsActive()) || frameNode->CheckAccessibilityLevelNo()) {
2658         TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "node: %{public}" PRId64 ", is not active or level is no",
2659             frameNode->GetAccessibilityId());
2660         return;
2661     }
2662 
2663     AccessibilityEventInfo eventInfo;
2664 
2665     if (accessibilityEvent.type != AccessibilityEventType::PAGE_CHANGE || accessibilityEvent.windowId == 0) {
2666         eventInfo.SetWindowId(windowId);
2667     } else {
2668         eventInfo.SetWindowId(accessibilityEvent.windowId);
2669     }
2670     FillEventInfoWithNode(frameNode, eventInfo, ngPipeline, accessibilityEvent.nodeId);
2671     if ((ngPipeline != nullptr) && (ngPipeline->IsFormRender())) {
2672         eventInfo.SetWindowId(static_cast<int32_t>(GetWindowId()));
2673     }
2674     GenerateAccessibilityEventInfo(accessibilityEvent, eventInfo);
2675 
2676     auto container = Container::GetContainer(context->GetInstanceId());
2677     if (container && container->IsDynamicRender()) {
2678         SendExtensionAccessibilityEvent(eventInfo, NG::UI_EXTENSION_UNKNOW_ID);
2679     } else {
2680         context->GetTaskExecutor()->PostTask(
2681             [weak = WeakClaim(this), accessibilityEvent, eventInfo] {
2682                 auto jsAccessibilityManager = weak.Upgrade();
2683                 CHECK_NULL_VOID(jsAccessibilityManager);
2684                 jsAccessibilityManager->SendAccessibilitySyncEvent(accessibilityEvent, eventInfo);
2685             },
2686             TaskExecutor::TaskType::BACKGROUND, "ArkUIAccessibilitySendSyncEvent");
2687     }
2688 }
2689 
GetRealEventWindowId(const AccessibilityEvent & accessibilityEvent,const RefPtr<NG::PipelineContext> & ngPipeline,uint32_t & windowId)2690 void GetRealEventWindowId(
2691     const AccessibilityEvent& accessibilityEvent, const RefPtr<NG::PipelineContext>& ngPipeline, uint32_t& windowId)
2692 {
2693     if ((accessibilityEvent.type == AccessibilityEventType::PAGE_CHANGE && accessibilityEvent.windowId != 0) ||
2694         accessibilityEvent.windowChangeTypes == WINDOW_UPDATE_ADDED) {
2695         windowId = accessibilityEvent.windowId;
2696         return;
2697     }
2698     if ((ngPipeline != nullptr) && (ngPipeline->IsFormRender())) {
2699         return;
2700     }
2701     windowId = ngPipeline->GetRealHostWindowId();
2702 }
2703 
SendAccessibilityAsyncEvent(const AccessibilityEvent & accessibilityEvent)2704 void JsAccessibilityManager::SendAccessibilityAsyncEvent(const AccessibilityEvent& accessibilityEvent)
2705 {
2706     auto delayTime = GetDelayTimeBeforeSendEvent(accessibilityEvent, nullptr);
2707     if (delayTime > 0) {
2708         auto context = GetPipelineContext().Upgrade();
2709         if (context) {
2710             context->GetTaskExecutor()->PostDelayedTask(
2711                 [weak = WeakClaim(this), accessibilityEvent] {
2712                     auto jsAccessibilityManager = weak.Upgrade();
2713                     CHECK_NULL_VOID(jsAccessibilityManager);
2714                     jsAccessibilityManager->SendAccessibilityAsyncEventInner(accessibilityEvent);
2715                 },
2716                 TaskExecutor::TaskType::UI, delayTime, "ArkUIAccessibilitySendSyncEventWithDelay");
2717         }
2718         return;
2719     }
2720     SendAccessibilityAsyncEventInner(accessibilityEvent);
2721 }
2722 
SendAccessibilityAsyncEventInner(const AccessibilityEvent & accessibilityEvent)2723 void JsAccessibilityManager::SendAccessibilityAsyncEventInner(const AccessibilityEvent& accessibilityEvent)
2724 {
2725     ACE_ACCESS_SCOPED_TRACE("SendAccessibilityAsyncEvent");
2726     auto context = GetPipelineContext().Upgrade();
2727     CHECK_NULL_VOID(context);
2728     int32_t windowId = static_cast<int32_t>(context->GetRealHostWindowId());
2729     if (windowId == 0) {
2730         return;
2731     }
2732     RefPtr<NG::PipelineContext> ngPipeline;
2733     AccessibilityEventInfo eventInfo;
2734     uint32_t realWindowId = GetWindowId();
2735     if (AceType::InstanceOf<NG::PipelineContext>(context)) {
2736         RefPtr<NG::FrameNode> node;
2737         ngPipeline = FindPipelineByElementId(accessibilityEvent.nodeId, node);
2738         CHECK_NULL_VOID(ngPipeline);
2739         CHECK_NULL_VOID(node);
2740         GetRealEventWindowId(accessibilityEvent, ngPipeline, realWindowId);
2741         FillEventInfo(node, eventInfo, ngPipeline, Claim(this),
2742             FillEventInfoParam {
2743                 accessibilityEvent.nodeId, accessibilityEvent.stackNodeId, realWindowId });
2744         eventInfo.SetWindowId(realWindowId);
2745     } else {
2746         ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
2747         auto node = GetAccessibilityNodeFromPage(accessibilityEvent.nodeId);
2748         CHECK_NULL_VOID(node);
2749         FillEventInfo(node, eventInfo);
2750         eventInfo.SetWindowId(windowId);
2751     }
2752     if (accessibilityEvent.type == AccessibilityEventType::PAGE_CHANGE && accessibilityEvent.windowId != 0) {
2753         eventInfo.SetWindowId(accessibilityEvent.windowId);
2754     }
2755     if (ngPipeline != nullptr) {
2756         if (ngPipeline->IsFormRender()) {
2757             eventInfo.SetWindowId(static_cast<int32_t>(GetWindowId()));
2758         }
2759     }
2760     GenerateAccessibilityEventInfo(accessibilityEvent, eventInfo);
2761 
2762     auto container = Container::GetContainer(context->GetInstanceId());
2763     if (container && container->IsDynamicRender()) {
2764         SendExtensionAccessibilityEvent(eventInfo, NG::UI_EXTENSION_OFFSET_MAX);
2765     } else {
2766         context->GetTaskExecutor()->PostTask(
2767             [weak = WeakClaim(this), accessibilityEvent, eventInfo] {
2768                 auto jsAccessibilityManager = weak.Upgrade();
2769                 CHECK_NULL_VOID(jsAccessibilityManager);
2770                 jsAccessibilityManager->SendAccessibilitySyncEvent(accessibilityEvent, eventInfo);
2771             },
2772             TaskExecutor::TaskType::BACKGROUND, "ArkUIAccessibilitySendSyncEvent");
2773     }
2774 }
2775 
2776 #ifdef WEB_SUPPORTED
2777 
SendWebAccessibilityAsyncEvent(const AccessibilityEvent & accessibilityEvent,const RefPtr<NG::WebPattern> & webPattern)2778 void JsAccessibilityManager::SendWebAccessibilityAsyncEvent(
2779     const AccessibilityEvent& accessibilityEvent, const RefPtr<NG::WebPattern>& webPattern)
2780 {
2781     ACE_ACCESS_SCOPED_TRACE("SendWebAccessibilityAsyncEvent");
2782     auto context = GetPipelineContext().Upgrade();
2783     CHECK_NULL_VOID(context);
2784     int32_t windowId = static_cast<int32_t>(context->GetRealHostWindowId());
2785     if (windowId == 0) {
2786         return;
2787     }
2788 
2789     AccessibilityEventInfo eventInfo;
2790     RefPtr<NG::PipelineContext> ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context_.Upgrade());
2791     CHECK_NULL_VOID(ngPipeline);
2792     FillWebEventInfo(eventInfo, ngPipeline, Claim(this),
2793         FillEventInfoParam {
2794                 accessibilityEvent.nodeId, accessibilityEvent.stackNodeId, ngPipeline->GetRealHostWindowId() },
2795         webPattern);
2796     eventInfo.SetWindowId(ngPipeline->GetRealHostWindowId());
2797 
2798     if (accessibilityEvent.type == AccessibilityEventType::PAGE_CHANGE && accessibilityEvent.windowId != 0) {
2799         eventInfo.SetWindowId(accessibilityEvent.windowId);
2800     }
2801 
2802     GenerateAccessibilityEventInfo(accessibilityEvent, eventInfo);
2803 
2804     context->GetTaskExecutor()->PostTask(
2805         [weak = WeakClaim(this), accessibilityEvent, eventInfo] {
2806             auto jsAccessibilityManager = weak.Upgrade();
2807             CHECK_NULL_VOID(jsAccessibilityManager);
2808             jsAccessibilityManager->SendAccessibilitySyncEvent(accessibilityEvent, eventInfo);
2809         },
2810         TaskExecutor::TaskType::BACKGROUND, "ArkUIAccessibilitySendSyncEvent");
2811 }
2812 #endif
2813 
UpdateNodeChildIds(const RefPtr<AccessibilityNode> & node)2814 void JsAccessibilityManager::UpdateNodeChildIds(const RefPtr<AccessibilityNode>& node)
2815 {
2816     CHECK_NULL_VOID(node);
2817     node->ActionUpdateIds();
2818     const auto& children = node->GetChildList();
2819     std::vector<int32_t> childrenVec;
2820     auto cardId = GetCardId();
2821     auto rootNodeId = GetRootNodeId();
2822 
2823     // get last stack children to barrier free service.
2824     if ((node->GetNodeId() == GetRootNodeId() + ROOT_STACK_BASE) && !children.empty() && !IsDeclarative()) {
2825         auto lastChildNodeId = children.back()->GetNodeId();
2826         if (isOhosHostCard()) {
2827             childrenVec.emplace_back(ConvertToCardAccessibilityId(lastChildNodeId, cardId, rootNodeId));
2828         } else {
2829             childrenVec.emplace_back(lastChildNodeId);
2830             for (const auto& child : children) {
2831                 if (child->GetNodeId() == ROOT_DECOR_BASE - 1) {
2832                     childrenVec.emplace_back(child->GetNodeId());
2833                     break;
2834                 }
2835             }
2836         }
2837     } else {
2838         childrenVec.resize(children.size());
2839         if (isOhosHostCard()) {
2840             std::transform(children.begin(), children.end(), childrenVec.begin(),
2841                 [cardId, rootNodeId](const RefPtr<AccessibilityNode>& child) {
2842                     return ConvertToCardAccessibilityId(child->GetNodeId(), cardId, rootNodeId);
2843                 });
2844         } else {
2845             std::transform(children.begin(), children.end(), childrenVec.begin(),
2846                 [](const RefPtr<AccessibilityNode>& child) { return child->GetNodeId(); });
2847         }
2848     }
2849     node->SetChildIds(childrenVec);
2850 }
2851 
ProcessParameters(ActionType op,const std::vector<std::string> & params,std::map<std::string,std::string> & paramsMap)2852 void JsAccessibilityManager::ProcessParameters(
2853     ActionType op, const std::vector<std::string>& params, std::map<std::string, std::string>& paramsMap)
2854 {
2855     if (op == ActionType::ACCESSIBILITY_ACTION_SET_TEXT) {
2856         if (params.size() == EVENT_DUMP_PARAM_LENGTH_UPPER) {
2857             paramsMap = { { ACTION_ARGU_SET_TEXT, params[EVENT_DUMP_ACTION_PARAM_INDEX] } };
2858         }
2859     }
2860 
2861     if (op == ActionType::ACCESSIBILITY_ACTION_SET_SELECTION) {
2862         paramsMap[ACTION_ARGU_SELECT_TEXT_START] = "-1";
2863         paramsMap[ACTION_ARGU_SELECT_TEXT_END] = "-1";
2864         paramsMap[ACTION_ARGU_SELECT_TEXT_INFORWARD] = STRING_DIR_BACKWARD;
2865         if (params.size() > EVENT_DUMP_PARAM_LENGTH_LOWER) {
2866             paramsMap[ACTION_ARGU_SELECT_TEXT_START] = params[EVENT_DUMP_ACTION_PARAM_INDEX];
2867         }
2868         if (params.size() > EVENT_DUMP_PARAM_LENGTH_LOWER + 1) {
2869             paramsMap[ACTION_ARGU_SELECT_TEXT_END] = params[EVENT_DUMP_ACTION_PARAM_INDEX + 1];
2870         }
2871         // 2 means params number Offset
2872         if (params.size() > EVENT_DUMP_PARAM_LENGTH_LOWER + 2) {
2873             // 2 means params number Offset
2874             paramsMap[ACTION_ARGU_SELECT_TEXT_INFORWARD] = params[EVENT_DUMP_ACTION_PARAM_INDEX + 2];
2875         }
2876     }
2877 
2878     if (op == ActionType::ACCESSIBILITY_ACTION_NEXT_TEXT || op == ActionType::ACCESSIBILITY_ACTION_PREVIOUS_TEXT) {
2879         if (params.size() == EVENT_DUMP_PARAM_LENGTH_UPPER) {
2880             paramsMap[ACTION_ARGU_MOVE_UNIT] = std::to_string(TextMoveUnit::STEP_CHARACTER);
2881         }
2882         paramsMap[ACTION_ARGU_MOVE_UNIT] = std::to_string(TextMoveUnit::STEP_CHARACTER);
2883     }
2884 
2885     if (op == ActionType::ACCESSIBILITY_ACTION_SET_CURSOR_POSITION) {
2886         paramsMap[ACTION_ARGU_SET_OFFSET] = params[EVENT_DUMP_ACTION_PARAM_INDEX];
2887     }
2888 
2889     if ((op == ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD) ||
2890         (op == ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD)) {
2891         if (params.size() > EVENT_DUMP_PARAM_LENGTH_LOWER) {
2892             paramsMap = { { ACTION_ARGU_SCROLL_STUB, params[EVENT_DUMP_ACTION_PARAM_INDEX] } };
2893         }
2894     }
2895 
2896     if (op == ActionType::ACCESSIBILITY_ACTION_SPAN_CLICK) {
2897         if (params.size() > EVENT_DUMP_PARAM_LENGTH_LOWER) {
2898             paramsMap = { { ACTION_ARGU_SPAN_ID, params[EVENT_DUMP_ACTION_PARAM_INDEX] } };
2899         }
2900     }
2901 }
2902 
TransferExecuteAction(int64_t elementId,const RefPtr<NG::FrameNode> & node,const std::map<std::string,std::string> & actionArguments,ActionType action,int64_t uiExtensionOffset)2903 bool TransferExecuteAction(int64_t elementId, const RefPtr<NG::FrameNode>& node,
2904     const std::map<std::string, std::string>& actionArguments,
2905     ActionType action, int64_t uiExtensionOffset)
2906 {
2907     bool isExecuted = false;
2908     if ((uiExtensionOffset + 1) > NG::UI_EXTENSION_OFFSET_MIN) {
2909         isExecuted = node->TransferExecuteAction(
2910             elementId, actionArguments, static_cast<int>(action),
2911             uiExtensionOffset / NG::UI_EXTENSION_ID_FACTOR);
2912     }
2913     return isExecuted;
2914 }
2915 
GetPipelineByWindowId(uint32_t windowId)2916 RefPtr<NG::PipelineContext> JsAccessibilityManager::GetPipelineByWindowId(uint32_t windowId)
2917 {
2918     auto mainPipeline = AceType::DynamicCast<NG::PipelineContext>(context_.Upgrade());
2919     if (mainPipeline!= nullptr && mainPipeline->GetWindowId() == windowId) {
2920         return mainPipeline;
2921     }
2922     for (auto subPipelineWeak : GetSubPipelineContexts()) {
2923         auto subContextNG = AceType::DynamicCast<NG::PipelineContext>(subPipelineWeak.Upgrade());
2924         if (subContextNG!= nullptr && subContextNG->GetWindowId() == windowId) {
2925             return subContextNG;
2926         }
2927     }
2928     if (GetWindowId() == windowId) {
2929         return mainPipeline;
2930     }
2931     return nullptr;
2932 }
2933 
DumpTreeNG(bool useWindowId,uint32_t windowId,int64_t rootId,bool isDumpSimplify)2934 void JsAccessibilityManager::DumpTreeNG(bool useWindowId, uint32_t windowId, int64_t rootId, bool isDumpSimplify)
2935 {
2936     if (!useWindowId && rootId == -1) {
2937         // used to adapt old function
2938         DumpTree(0, 0);
2939         return;
2940     }
2941 
2942     auto pipeline = GetPipelineByWindowId(windowId);
2943     if (pipeline == nullptr) {
2944         DumpLog::GetInstance().Print("Error: pipeline is not found!");
2945         return;
2946     }
2947     auto rootNode = pipeline->GetRootElement();
2948     CHECK_NULL_VOID(rootNode);
2949     CommonProperty commonProperty;
2950     auto mainPipeline = context_.Upgrade();
2951     CHECK_NULL_VOID(mainPipeline);
2952     GenerateCommonProperty(pipeline, commonProperty, mainPipeline);
2953     auto nodeId = rootId == -1 ? rootNode->GetAccessibilityId() : rootId;
2954     DumpTreeNG(rootNode, 0, nodeId, commonProperty, isDumpSimplify);
2955 }
2956 
DumpHoverTestNG(uint32_t windowId,int64_t rootId,int32_t x,int32_t y,bool verbose)2957 void JsAccessibilityManager::DumpHoverTestNG(uint32_t windowId, int64_t rootId, int32_t x, int32_t y, bool verbose)
2958 {
2959     auto pipeline = GetPipelineByWindowId(windowId);
2960     CHECK_NULL_VOID(pipeline);
2961     auto accessibilityManagerNG = pipeline->GetAccessibilityManagerNG();
2962     CHECK_NULL_VOID(accessibilityManagerNG);
2963     auto pipelineRoot = pipeline->GetRootElement();
2964     RefPtr<NG::FrameNode> root = nullptr;
2965     if (rootId == -1) {
2966         root = pipelineRoot;
2967     } else {
2968         root = GetFramenodeByAccessibilityId(pipelineRoot, rootId);
2969     }
2970     CHECK_NULL_VOID(root);
2971 
2972     DumpLog::GetInstance().Print("Window ID: " + std::to_string(windowId));
2973     DumpLog::GetInstance().Print("Root ID: " + std::to_string(root->GetAccessibilityId()));
2974     NG::PointF hoverPoint(x, y);
2975     DumpLog::GetInstance().Print("Hover Point: " + hoverPoint.ToString());
2976 
2977     std::string summary;
2978     std::string detail;
2979     accessibilityManagerNG->HoverTestDebug(root, hoverPoint, summary, detail);
2980     DumpLog::GetInstance().Print(summary);
2981     if (verbose) {
2982         DumpLog::GetInstance().Print(detail);
2983     }
2984 }
2985 
CheckDumpInfoParams(const std::vector<std::string> & params)2986 bool JsAccessibilityManager::CheckDumpInfoParams(const std::vector<std::string> &params)
2987 {
2988     if (params.size() < 1) {
2989         return false;
2990     }
2991     const std::string firstParam = params[0];
2992     if (firstParam.compare("-inspector") != 0 && firstParam.compare("-accessibility") != 0 &&
2993         firstParam.compare("-simplify") != 0) {
2994         return false;
2995     }
2996     return true;
2997 }
2998 
OnDumpInfoNG(const std::vector<std::string> & params,uint32_t windowId)2999 void JsAccessibilityManager::OnDumpInfoNG(const std::vector<std::string>& params, uint32_t windowId)
3000 {
3001     if (!CheckDumpInfoParams(params)) {
3002         DumpLog::GetInstance().Print("Error: invalid arguments!");
3003         return;
3004     }
3005     enum class DumpMode {
3006         TREE,
3007         NODE,
3008         HANDLE_EVENT,
3009         HOVER_TEST
3010     };
3011     bool useWindowId = false;
3012     DumpMode mode = DumpMode::TREE;
3013     bool isDumpSimplify = params[0].compare("-simplify") == 0;
3014     bool verbose = false;
3015     int64_t rootId = -1;
3016     int32_t pointX = 0;
3017     int32_t pointY = 0;
3018     int64_t nodeId = -1;
3019     int32_t action = 0;
3020     for (auto arg = params.begin() + 1; arg != params.end(); ++arg) {
3021         if (*arg == "-w") {
3022             useWindowId = true;
3023         } else if (*arg == "--root") {
3024             ++arg;
3025             if (arg == params.end()) {
3026                 DumpLog::GetInstance().Print(std::string("Error: --root is used to set the root node, ") +
3027                     "e.g. '--root ${AccessibilityId}'!");
3028                 return;
3029             }
3030             rootId = StringUtils::StringToLongInt(*arg);
3031         } else if (*arg == "--hover-test") {
3032             mode = DumpMode::HOVER_TEST;
3033             static constexpr int32_t NUM_POINT_DIMENSION = 2;
3034             if (std::distance(arg, params.end()) <= NUM_POINT_DIMENSION) {
3035                 DumpLog::GetInstance().Print(std::string("Error: --hover-test is used to get nodes at a point ") +
3036                     "relative to the root node, e.g. '--hover-test ${x} ${y}'!");
3037                 return;
3038             }
3039             ++arg;
3040             pointX = StringUtils::StringToInt(*arg);
3041             ++arg;
3042             pointY = StringUtils::StringToInt(*arg);
3043         } else if (*arg == "-v") {
3044             verbose = true;
3045         } else {
3046             if (mode == DumpMode::NODE) {
3047                 mode = DumpMode::HANDLE_EVENT;
3048                 action = StringUtils::StringToInt(*arg);
3049                 break;
3050             } else {
3051                 mode = DumpMode::NODE;
3052                 nodeId = StringUtils::StringToLongInt(*arg);
3053             }
3054         }
3055     }
3056     std::vector<std::string> info;
3057     bool isChildElement = CheckIsChildElement(nodeId, params, info);
3058     if (isChildElement) {
3059         TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "dump child element: %{public}" PRId64, nodeId);
3060         return;
3061     }
3062     switch (mode) {
3063         case DumpMode::TREE:
3064             DumpTreeNG(useWindowId, windowId, rootId, isDumpSimplify);
3065             break;
3066         case DumpMode::NODE:
3067             DumpPropertyNG(nodeId);
3068             break;
3069         case DumpMode::HANDLE_EVENT:
3070             DumpHandleEvent(params);
3071             break;
3072         case DumpMode::HOVER_TEST:
3073             DumpHoverTestNG(windowId, rootId, pointX, pointY, verbose);
3074             break;
3075         default:
3076             DumpLog::GetInstance().Print("Error: invalid arguments!");
3077             break;
3078     }
3079 }
3080 
DumpHandleEvent(const std::vector<std::string> & params)3081 void JsAccessibilityManager::DumpHandleEvent(const std::vector<std::string>& params)
3082 {
3083     if (params.size() > EVENT_DUMP_PARAM_LENGTH_UPPER + 1) {
3084         return DumpLog::GetInstance().Print("Error: params length is illegal!");
3085     }
3086     if (params[EVENT_DUMP_ORDER_INDEX] != DUMP_ORDER && params[EVENT_DUMP_ORDER_INDEX] != DUMP_INSPECTOR) {
3087         return DumpLog::GetInstance().Print("Error: not accessibility dump order!");
3088     }
3089     auto pipeline = context_.Upgrade();
3090     CHECK_NULL_VOID(pipeline);
3091     int64_t nodeId = StringUtils::StringToLongInt(params[EVENT_DUMP_ID_INDEX]);
3092 
3093     int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
3094     int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
3095     AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(nodeId, splitElementId, splitTreeId);
3096     nodeId = splitElementId;
3097 
3098     auto action = static_cast<AceAction>(StringUtils::StringToInt(params[EVENT_DUMP_ACTION_INDEX]));
3099     auto op = ConvertAceAction(action);
3100     if ((op != ActionType::ACCESSIBILITY_ACTION_SET_SELECTION) && (params.size() > EVENT_DUMP_PARAM_LENGTH_UPPER + 1)) {
3101         return DumpLog::GetInstance().Print("Error: params is illegal!");
3102     }
3103     std::map<std::string, std::string> paramsMap;
3104     ProcessParameters(op, params, paramsMap);
3105     if (AceType::InstanceOf<NG::PipelineContext>(pipeline)) {
3106         RefPtr<NG::FrameNode> node;
3107 #ifdef WINDOW_SCENE_SUPPORTED
3108         auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipeline);
3109         auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
3110         CHECK_NULL_VOID(uiExtensionManager);
3111         if (uiExtensionManager->IsWrapExtensionAbilityId(nodeId)) {
3112             ExecuteActionNG(nodeId, paramsMap, op, ngPipeline, NG::UI_EXTENSION_OFFSET_MAX);
3113             return;
3114         }
3115 #endif
3116         pipeline = FindPipelineByElementId(nodeId, node);
3117         CHECK_NULL_VOID(pipeline);
3118         pipeline->GetTaskExecutor()->PostTask(
3119             [weak = WeakClaim(this), op, nodeId, paramsMap, pipeline]() {
3120                 auto jsAccessibilityManager = weak.Upgrade();
3121                 CHECK_NULL_VOID(jsAccessibilityManager);
3122                 jsAccessibilityManager->ExecuteActionNG(nodeId, paramsMap, op, pipeline, NG::UI_EXTENSION_OFFSET_MAX);
3123             },
3124             TaskExecutor::TaskType::UI, "ArkUIAccessibilityExecuteAction");
3125         return;
3126     }
3127     auto node = GetAccessibilityNodeFromPage(nodeId);
3128     CHECK_NULL_VOID(node);
3129     pipeline->GetTaskExecutor()->PostTask(
3130         [weak = WeakClaim(this), op, node, paramsMap, pipeline]() {
3131             auto jsAccessibilityManager = weak.Upgrade();
3132             CHECK_NULL_VOID(jsAccessibilityManager);
3133             jsAccessibilityManager->AccessibilityActionEvent(
3134                 op, paramsMap, node, AceType::DynamicCast<PipelineContext>(pipeline));
3135         },
3136         TaskExecutor::TaskType::UI, "ArkUIAccessibilityActionEvent");
3137 }
3138 
DumpProperty(const RefPtr<AccessibilityNode> & node)3139 void JsAccessibilityManager::DumpProperty(const RefPtr<AccessibilityNode>& node)
3140 {
3141     const auto& supportAceActions = node->GetSupportAction();
3142     const auto& charValue = node->GetChartValue();
3143 
3144     DumpLog::GetInstance().AddDesc("ID: ", node->GetNodeId());
3145     DumpLog::GetInstance().AddDesc("parent ID: ", node->GetParentId());
3146     DumpLog::GetInstance().AddDesc("child IDs: ", GetNodeChildIds(node));
3147     DumpLog::GetInstance().AddDesc("component type: ", node->GetTag());
3148     DumpLog::GetInstance().AddDesc("input type: ", node->GetInputType());
3149     DumpLog::GetInstance().AddDesc("text: ", node->GetText());
3150     DumpLog::GetInstance().AddDesc("width: ", node->GetWidth());
3151     DumpLog::GetInstance().AddDesc("height: ", node->GetHeight());
3152     DumpLog::GetInstance().AddDesc("left: ", node->GetLeft() + GetCardOffset().GetX());
3153     DumpLog::GetInstance().AddDesc("top: ", node->GetTop() + GetCardOffset().GetY());
3154     DumpLog::GetInstance().AddDesc("enabled: ", BoolToString(node->GetEnabledState()));
3155     DumpLog::GetInstance().AddDesc("checked: ", BoolToString(node->GetCheckedState()));
3156     DumpLog::GetInstance().AddDesc("selected: ", BoolToString(node->GetSelectedState()));
3157     DumpLog::GetInstance().AddDesc("focusable: ", BoolToString(node->GetFocusableState()));
3158     DumpLog::GetInstance().AddDesc("focused: ", BoolToString(node->GetFocusedState()));
3159     DumpLog::GetInstance().AddDesc("checkable: ", BoolToString(node->GetCheckableState()));
3160     DumpLog::GetInstance().AddDesc("clickable: ", BoolToString(node->GetClickableState()));
3161     DumpLog::GetInstance().AddDesc("long clickable: ", BoolToString(node->GetLongClickableState()));
3162     DumpLog::GetInstance().AddDesc("scrollable: ", BoolToString(node->GetScrollableState()));
3163     DumpLog::GetInstance().AddDesc("editable: ", BoolToString(node->GetEditable()));
3164     DumpLog::GetInstance().AddDesc("hint text: ", node->GetHintText());
3165     DumpLog::GetInstance().AddDesc("error text: ", node->GetErrorText());
3166     DumpLog::GetInstance().AddDesc("js component id: ", node->GetJsComponentId());
3167     DumpLog::GetInstance().AddDesc("accessibility label: ", node->GetAccessibilityLabel());
3168     DumpLog::GetInstance().AddDesc("accessibility hint: ", node->GetAccessibilityHint());
3169     DumpLog::GetInstance().AddDesc("max text length: ", node->GetMaxTextLength());
3170     DumpLog::GetInstance().AddDesc("text selection start: ", node->GetTextSelectionStart());
3171     DumpLog::GetInstance().AddDesc("text selection end: ", node->GetTextSelectionEnd());
3172     DumpLog::GetInstance().AddDesc("is multi line: ", BoolToString(node->GetIsMultiLine()));
3173     DumpLog::GetInstance().AddDesc("is password", BoolToString(node->GetIsPassword()));
3174     DumpLog::GetInstance().AddDesc("text input type: ", ConvertInputTypeToString(node->GetTextInputType()));
3175     DumpLog::GetInstance().AddDesc("min value: ", node->GetAccessibilityValue().min);
3176     DumpLog::GetInstance().AddDesc("max value: ", node->GetAccessibilityValue().max);
3177     DumpLog::GetInstance().AddDesc("current value: ", node->GetAccessibilityValue().current);
3178     DumpLog::GetInstance().AddDesc("collection info rows: ", node->GetCollectionInfo().rows);
3179     DumpLog::GetInstance().AddDesc("collection info columns: ", node->GetCollectionInfo().columns);
3180     DumpLog::GetInstance().AddDesc("collection item info, row: ", node->GetCollectionItemInfo().row);
3181     DumpLog::GetInstance().AddDesc("collection item info, column: ", node->GetCollectionItemInfo().column);
3182     DumpLog::GetInstance().AddDesc("chart has value: ", BoolToString(charValue && !charValue->empty()));
3183     DumpLog::GetInstance().AddDesc("accessibilityGroup: ", BoolToString(node->GetAccessible()));
3184     DumpLog::GetInstance().AddDesc("accessibilityImportance: ", node->GetImportantForAccessibility());
3185     DumpLog::GetInstance().AddDesc("support action: ", GetSupportAction(supportAceActions));
3186     DumpLog::GetInstance().Print(0, node->GetTag(), node->GetChildList().size());
3187 }
3188 
DumpPropertyNG(int64_t nodeID)3189 void JsAccessibilityManager::DumpPropertyNG(int64_t nodeID)
3190 {
3191     auto pipeline = context_.Upgrade();
3192     CHECK_NULL_VOID(pipeline);
3193     RefPtr<NG::PipelineContext> ngPipeline;
3194 
3195 #ifdef WINDOW_SCENE_SUPPORTED
3196     ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipeline);
3197     auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
3198     CHECK_NULL_VOID(uiExtensionManager);
3199     std::list<AccessibilityElementInfo> extensionElementInfos;
3200     if (uiExtensionManager->IsWrapExtensionAbilityId(nodeID)) {
3201         SearchElementInfoByAccessibilityIdNG(
3202             nodeID, PREFETCH_RECURSIVE_CHILDREN, extensionElementInfos, ngPipeline, NG::UI_EXTENSION_OFFSET_MAX);
3203         for (auto& extensionElementInfo : extensionElementInfos) {
3204             if (nodeID == extensionElementInfo.GetAccessibilityId()) {
3205                 DumpCommonPropertyNG(extensionElementInfo, treeId_);
3206                 DumpAccessibilityPropertyNG(extensionElementInfo);
3207                 DumpLog::GetInstance().Print(
3208                     0, extensionElementInfo.GetComponentType(), extensionElementInfo.GetChildCount());
3209                 return;
3210             }
3211         }
3212     }
3213 #endif
3214 
3215     RefPtr<NG::FrameNode> frameNode;
3216     ngPipeline = FindPipelineByElementId(nodeID, frameNode);
3217     CHECK_NULL_VOID(ngPipeline);
3218     CHECK_NULL_VOID(frameNode);
3219 
3220     CommonProperty commonProperty;
3221     GenerateCommonProperty(ngPipeline, commonProperty, pipeline);
3222     AccessibilityElementInfo nodeInfo;
3223     UpdateAccessibilityElementInfo(frameNode, commonProperty, nodeInfo, ngPipeline);
3224     if (IsExtensionComponent(frameNode) && !IsUIExtensionShowPlaceholder(frameNode)) {
3225         SearchParameter param {-1, "", PREFETCH_RECURSIVE_CHILDREN, NG::UI_EXTENSION_OFFSET_MAX};
3226         std::list<AccessibilityElementInfo> extensionElementInfos;
3227         SearchExtensionElementInfoNG(param, frameNode, extensionElementInfos, nodeInfo);
3228     }
3229     DumpCommonPropertyNG(nodeInfo, treeId_);
3230     DumpAccessibilityPropertyNG(nodeInfo);
3231     auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
3232     if (accessibilityProperty) {
3233         DumpLog::GetInstance().AddDesc("offset: ", accessibilityProperty->GetScrollOffSet());
3234         DumpLog::GetInstance().AddDesc("childTreeId: ", accessibilityProperty->GetChildTreeId());
3235         DumpLog::GetInstance().AddDesc("childWindowId: ", accessibilityProperty->GetChildWindowId());
3236     }
3237     DumpLog::GetInstance().Print(0, nodeInfo.GetComponentType(), nodeInfo.GetChildCount());
3238 }
3239 
DumpProperty(const std::vector<std::string> & params)3240 void JsAccessibilityManager::DumpProperty(const std::vector<std::string>& params)
3241 {
3242     CHECK_NULL_VOID(DumpLog::GetInstance().GetDumpFile());
3243     if (params.empty()) {
3244         DumpLog::GetInstance().Print("Error: params cannot be empty!");
3245         return;
3246     }
3247     if (params.size() != PROPERTY_DUMP_PARAM_LENGTH) {
3248         DumpLog::GetInstance().Print("Error: params length is illegal!");
3249         return;
3250     }
3251     if (params[0] != DUMP_ORDER && params[0] != DUMP_INSPECTOR) {
3252         DumpLog::GetInstance().Print("Error: not accessibility dump order!");
3253         return;
3254     }
3255 
3256     auto pipeline = context_.Upgrade();
3257     CHECK_NULL_VOID(pipeline);
3258 
3259     if (!AceType::InstanceOf<NG::PipelineContext>(pipeline)) {
3260         auto node = GetAccessibilityNodeFromPage(StringUtils::StringToLongInt(params[1]));
3261         if (!node) {
3262             DumpLog::GetInstance().Print("Error: can't find node with ID " + params[1]);
3263             return;
3264         }
3265         DumpProperty(node);
3266     } else {
3267         DumpPropertyNG(StringUtils::StringToLongInt(params[1]));
3268     }
3269 }
3270 
DumpAccessibilityElementInfosTreeNG(std::list<AccessibilityElementInfo> & infos,int32_t depth,int64_t accessibilityId,bool isRoot)3271 static void DumpAccessibilityElementInfosTreeNG(
3272     std::list<AccessibilityElementInfo>& infos, int32_t depth, int64_t accessibilityId, bool isRoot)
3273 {
3274     AccessibilityElementInfo accessibilityInfo;
3275     for (auto& info : infos) {
3276         if (accessibilityId == info.GetAccessibilityId()) {
3277             accessibilityInfo = info;
3278             break;
3279         }
3280     }
3281     if (!isRoot) {
3282         DumpLog::GetInstance().AddDesc("ID: " + std::to_string(accessibilityInfo.GetAccessibilityId()));
3283         DumpLog::GetInstance().AddDesc("compid: " + accessibilityInfo.GetInspectorKey());
3284         DumpLog::GetInstance().AddDesc("text: " + accessibilityInfo.GetContent());
3285         DumpLog::GetInstance().AddDesc("accessibilityText: " + accessibilityInfo.GetContent());
3286         DumpLog::GetInstance().AddDesc("accessibilityGroup: ");
3287         DumpLog::GetInstance().AddDesc("accessibilityLevel: ");
3288         DumpLog::GetInstance().AddDesc("top: " +
3289             std::to_string(accessibilityInfo.GetRectInScreen().GetLeftTopYScreenPostion()));
3290         DumpLog::GetInstance().AddDesc("left: " +
3291             std::to_string(accessibilityInfo.GetRectInScreen().GetLeftTopXScreenPostion()));
3292         DumpLog::GetInstance().AddDesc("width: " + std::to_string(
3293             accessibilityInfo.GetRectInScreen().GetRightBottomXScreenPostion() -
3294             accessibilityInfo.GetRectInScreen().GetLeftTopXScreenPostion()));
3295         DumpLog::GetInstance().AddDesc("height: " + std::to_string(
3296             accessibilityInfo.GetRectInScreen().GetRightBottomYScreenPostion() -
3297             accessibilityInfo.GetRectInScreen().GetLeftTopYScreenPostion()));
3298         DumpLog::GetInstance().AddDesc("visible: " + std::to_string(accessibilityInfo.IsVisible()));
3299         DumpLog::GetInstance().AddDesc(
3300             "clickable: " + std::to_string(accessibilityInfo.IsClickable()));
3301         DumpLog::GetInstance().AddDesc("longclickable: " +
3302             std::to_string(accessibilityInfo.IsLongClickable()));
3303         DumpLog::GetInstance().AddDesc("checkable: " + std::to_string(accessibilityInfo.IsCheckable()));
3304         DumpLog::GetInstance().AddDesc("scrollable: " + std::to_string(accessibilityInfo.IsScrollable()));
3305         DumpLog::GetInstance().AddDesc("checked: " + std::to_string(accessibilityInfo.IsChecked()));
3306         DumpLog::GetInstance().AddDesc("hint: " + accessibilityInfo.GetHint());
3307         DumpLog::GetInstance().Print(depth, accessibilityInfo.GetComponentType(), accessibilityInfo.GetChildCount());
3308         depth ++;
3309     }
3310     for (auto child : accessibilityInfo.GetChildIds()) {
3311         DumpAccessibilityElementInfosTreeNG(infos, depth, child, false);
3312     }
3313 }
3314 
DumpTreeNodeInfoNG(const RefPtr<NG::FrameNode> & node,int32_t depth,const CommonProperty & commonProperty,int32_t childSize)3315 static void DumpTreeNodeInfoNG(
3316     const RefPtr<NG::FrameNode>& node, int32_t depth, const CommonProperty& commonProperty, int32_t childSize)
3317 {
3318     NG::RectF rect = node->GetTransformRectRelativeToWindow();
3319     DumpLog::GetInstance().AddDesc("ID: " + std::to_string(node->GetAccessibilityId()));
3320     DumpLog::GetInstance().AddDesc("compid: " + node->GetInspectorId().value_or(""));
3321     DumpLog::GetInstance().AddDesc("text: " +
3322         node->GetAccessibilityProperty<NG::AccessibilityProperty>()->GetGroupText());
3323     DumpLog::GetInstance().AddDesc(
3324         "accessibilityText: " + node->GetAccessibilityProperty<NG::AccessibilityProperty>()->GetAccessibilityText());
3325     DumpLog::GetInstance().AddDesc("accessibilityGroup: " +
3326         std::to_string(node->GetAccessibilityProperty<NG::AccessibilityProperty>()->IsAccessibilityGroup()));
3327     DumpLog::GetInstance().AddDesc(
3328         "accessibilityLevel: " + node->GetAccessibilityProperty<NG::AccessibilityProperty>()->GetAccessibilityLevel());
3329     DumpLog::GetInstance().AddDesc("top: " + std::to_string(rect.Top() + commonProperty.windowTop));
3330     DumpLog::GetInstance().AddDesc("left: " + std::to_string(rect.Left() + commonProperty.windowLeft));
3331     DumpLog::GetInstance().AddDesc("width: " + std::to_string(rect.Width()));
3332     DumpLog::GetInstance().AddDesc("height: " + std::to_string(rect.Height()));
3333     DumpLog::GetInstance().AddDesc("visible: " + std::to_string(node->IsVisible()));
3334     auto eventHub = node->GetEventHub<NG::EventHub>();
3335     if (eventHub) {
3336         auto gestureEventHub = eventHub->GetGestureEventHub();
3337         DumpLog::GetInstance().AddDesc(
3338             "clickable: " + std::to_string(gestureEventHub ? gestureEventHub->IsAccessibilityClickable() : false));
3339         DumpLog::GetInstance().AddDesc("longclickable: " +
3340             std::to_string(gestureEventHub ? gestureEventHub->IsAccessibilityLongClickable() : false));
3341     }
3342     DumpLog::GetInstance().AddDesc(
3343         "checkable: " + std::to_string(node->GetAccessibilityProperty<NG::AccessibilityProperty>()->IsCheckable()));
3344     DumpLog::GetInstance().AddDesc(
3345         "scrollable: " + std::to_string(node->GetAccessibilityProperty<NG::AccessibilityProperty>()->IsScrollable()));
3346     DumpLog::GetInstance().AddDesc(
3347         "checked: " + std::to_string(node->GetAccessibilityProperty<NG::AccessibilityProperty>()->IsChecked()));
3348     DumpLog::GetInstance().AddDesc(
3349         "hint: " + node->GetAccessibilityProperty<NG::AccessibilityProperty>()->GetHintText());
3350     DumpLog::GetInstance().AddDesc(
3351         "childTree: " + std::to_string(node->GetAccessibilityProperty<NG::AccessibilityProperty>()->GetChildTreeId()));
3352     DumpLog::GetInstance().Print(depth, node->GetTag(), childSize);
3353 }
3354 
DumpTreeNodeSafeAreaInfoNg(const RefPtr<NG::FrameNode> & node)3355 void JsAccessibilityManager::DumpTreeNodeSafeAreaInfoNg(const RefPtr<NG::FrameNode>& node)
3356 {
3357     auto layoutProperty = node->GetLayoutProperty();
3358     if (layoutProperty) {
3359         auto&& opts = layoutProperty->GetSafeAreaExpandOpts();
3360         if (opts && opts->type != NG::SAFE_AREA_TYPE_NONE && opts->edges != NG::SAFE_AREA_EDGE_NONE) {
3361             DumpLog::GetInstance().AddDesc(opts->ToString());
3362         }
3363         if (layoutProperty->GetSafeAreaInsets()) {
3364             DumpLog::GetInstance().AddDesc(layoutProperty->GetSafeAreaInsets()->ToString());
3365         }
3366     }
3367     if (node->SelfOrParentExpansive()) {
3368         auto geometryNode = node->GetGeometryNode();
3369         if (geometryNode) {
3370             auto rect = geometryNode->GetSelfAdjust();
3371             auto parentRect = geometryNode->GetParentAdjust();
3372             bool isDefaultSize = NearZero(rect.GetX(), 0.0) && NearZero(rect.GetY(), 0.0) &&
3373                                  NearZero(rect.Width(), 0.0) && NearZero(rect.Height(), 0.0);
3374             bool isParentDefaultSize = NearZero(parentRect.GetX(), 0.0) && NearZero(parentRect.GetY(), 0.0) &&
3375                                        NearZero(parentRect.Width(), 0.0) && NearZero(parentRect.Height(), 0.0);
3376             if (!isDefaultSize && !isParentDefaultSize) {
3377                 DumpLog::GetInstance().AddDesc(std::string("selfAdjust: ")
3378                                                    .append(rect.ToString().c_str())
3379                                                    .append(",parentAdjust")
3380                                                    .append(parentRect.ToString().c_str()));
3381             }
3382         }
3383     }
3384     CHECK_NULL_VOID(node->GetTag() == V2::PAGE_ETS_TAG);
3385     auto pipeline = node->GetContext();
3386     CHECK_NULL_VOID(pipeline);
3387     auto manager = pipeline->GetSafeAreaManager();
3388     CHECK_NULL_VOID(manager);
3389     if (!manager->IsIgnoreAsfeArea() && !manager->IsNeedAvoidWindow() && !manager->IsFullScreen() &&
3390         !manager->KeyboardSafeAreaEnabled() && !pipeline->GetUseCutout()) {
3391         DumpLog::GetInstance().AddDesc(
3392             std::string("ignoreSafeArea: ")
3393                 .append(std::to_string(manager->IsIgnoreAsfeArea()))
3394                 .append(std::string(", isNeedAvoidWindow: ").c_str())
3395                 .append(std::to_string(manager->IsNeedAvoidWindow()))
3396                 .append(std::string(", IisFullScreen: ").c_str())
3397                 .append(std::to_string(manager->IsFullScreen()))
3398                 .append(std::string(", isKeyboardAvoidMode: ").c_str())
3399                 .append(std::to_string(static_cast<int32_t>(manager->GetKeyBoardAvoidMode())))
3400                 .append(std::string(", isUseCutout: ").c_str())
3401                 .append(std::to_string(pipeline->GetUseCutout())));
3402     }
3403 }
3404 
DumpPadding(const std::unique_ptr<NG::PaddingProperty> & padding,std::string label)3405 void JsAccessibilityManager::DumpPadding(const std::unique_ptr<NG::PaddingProperty>& padding, std::string label)
3406 {
3407     NG::CalcLength defaultValue = NG::CalcLength(Dimension(0));
3408     auto left = padding->left.value_or(defaultValue).GetDimension().Value();
3409     auto right = padding->right.value_or(defaultValue).GetDimension().Value();
3410     auto top = padding->top.value_or(defaultValue).GetDimension().Value();
3411     auto bottom = padding->bottom.value_or(defaultValue).GetDimension().Value();
3412     if (!NearZero(left, 0.0) && !NearZero(right, 0.0) && !NearZero(top, 0.0) && !NearZero(bottom, 0.0)) {
3413         DumpLog::GetInstance().AddDesc(label.append(padding->ToString().c_str()));
3414     }
3415 }
3416 
DumpBorder(const std::unique_ptr<NG::BorderWidthProperty> & border,std::string label)3417 void JsAccessibilityManager::DumpBorder(const std::unique_ptr<NG::BorderWidthProperty>& border, std::string label)
3418 {
3419     Dimension defaultValue(0);
3420     auto left = border->leftDimen.value_or(defaultValue).Value();
3421     auto right = border->rightDimen.value_or(defaultValue).Value();
3422     auto top = border->topDimen.value_or(defaultValue).Value();
3423     auto bottom = border->bottomDimen.value_or(defaultValue).Value();
3424     if (!NearZero(left, 0.0) && !NearZero(right, 0.0) && !NearZero(top, 0.0) && !NearZero(bottom, 0.0)) {
3425         DumpLog::GetInstance().AddDesc(label.append(border->ToString().c_str()));
3426     }
3427 }
3428 
DumpTreeNodeCommonInfoNg(const RefPtr<NG::FrameNode> & node,const CommonProperty & commonProperty)3429 void JsAccessibilityManager::DumpTreeNodeCommonInfoNg(
3430     const RefPtr<NG::FrameNode>& node, const CommonProperty& commonProperty)
3431 {
3432     DumpLog::GetInstance().AddDesc("ID: " + std::to_string(node->GetAccessibilityId()));
3433     auto renderContext = node->GetRenderContext();
3434     if (renderContext) {
3435         auto backgroundColor = renderContext->GetBackgroundColor();
3436         if (backgroundColor && backgroundColor->ColorToString().compare("#00000000") != 0) {
3437             DumpLog::GetInstance().AddDesc("BackgroundColor: " + backgroundColor->ColorToString());
3438         }
3439         DumpLog::GetInstance().AddDesc(std::string("PaintRectWithoutTransform: ")
3440                                            .append(renderContext->GetPaintRectWithoutTransform().ToString()));
3441     }
3442     NG::RectF rect = node->GetTransformRectRelativeToWindow();
3443     auto top = rect.Top() + commonProperty.windowTop;
3444     auto left = rect.Left() + commonProperty.windowLeft;
3445     if (!NearZero(top, 0.0) && !NearZero(left, 0.0)) {
3446         DumpLog::GetInstance().AddDesc("top: " + std::to_string(top));
3447         DumpLog::GetInstance().AddDesc("left: " + std::to_string(left));
3448     }
3449     DumpLog::GetInstance().AddDesc("width: " + std::to_string(rect.Width()));
3450     DumpLog::GetInstance().AddDesc("height: " + std::to_string(rect.Height()));
3451     auto layoutProperty = node->GetLayoutProperty();
3452     if (layoutProperty) {
3453         if (!node->IsVisible()) {
3454             DumpLog::GetInstance().AddDesc(
3455                 "visible: " + std::to_string(static_cast<int32_t>(layoutProperty->GetVisibility().value())));
3456         }
3457         auto& padding = layoutProperty->GetPaddingProperty();
3458         if (padding) {
3459             DumpPadding(padding, std::string("Padding: "));
3460         }
3461         auto& margin = layoutProperty->GetMarginProperty();
3462         if (margin) {
3463             DumpPadding(margin, std::string("Margin: "));
3464         }
3465         auto& border = layoutProperty->GetBorderWidthProperty();
3466         if (border) {
3467             DumpBorder(border, std::string("Border: "));
3468         }
3469         auto layoutRect = layoutProperty->GetLayoutRect();
3470         if (layoutRect) {
3471             DumpLog::GetInstance().AddDesc(std::string("LayoutRect: ").append(layoutRect.value().ToString().c_str()));
3472         }
3473     }
3474 }
3475 
DumpTreeNodeSimplifyInfoNG(const RefPtr<NG::FrameNode> & node,int32_t depth,const CommonProperty & commonProperty,int32_t childSize)3476 void JsAccessibilityManager::DumpTreeNodeSimplifyInfoNG(
3477     const RefPtr<NG::FrameNode>& node, int32_t depth, const CommonProperty& commonProperty, int32_t childSize)
3478 {
3479     DumpTreeNodeCommonInfoNg(node, commonProperty);
3480     DumpTreeNodeSafeAreaInfoNg(node);
3481     DumpLog::GetInstance().Print(depth, node->GetTag(), childSize);
3482 }
3483 
DumpTreeAccessibilityNodeNG(const RefPtr<NG::UINode> & uiNodeParent,int32_t depth,int64_t nodeID,const CommonProperty & commonProperty)3484 void JsAccessibilityManager::DumpTreeAccessibilityNodeNG(const RefPtr<NG::UINode>& uiNodeParent, int32_t depth,
3485     int64_t nodeID, const CommonProperty& commonProperty)
3486 {
3487     CHECK_NULL_VOID(uiNodeParent);
3488     auto virtualFrameNode = AceType::DynamicCast<NG::FrameNode>(uiNodeParent);
3489     auto uiNodeChildren = uiNodeParent->GetChildren(true);
3490     auto vNode = GetFramenodeByAccessibilityId(virtualFrameNode, nodeID);
3491     if (!vNode) {
3492         if (uiNodeChildren.size() == 0) {
3493             return;
3494         }
3495     }
3496     std::vector<int64_t> children;
3497     for (const auto& item : uiNodeChildren) {
3498         GetFrameNodeChildren(item, children, commonProperty.pageId);
3499     }
3500     if (vNode != nullptr) {
3501         DumpTreeNodeInfoNG(vNode, depth + 1, commonProperty, children.size());
3502     }
3503     for (const auto& item : uiNodeChildren) {
3504         DumpTreeAccessibilityNodeNG(item, depth + 1, item->GetAccessibilityId(), commonProperty);
3505     }
3506 }
3507 
DumpTreeNG(const RefPtr<NG::FrameNode> & parent,int32_t depth,int64_t nodeID,const CommonProperty & commonProperty,bool isDumpSimplify)3508 void JsAccessibilityManager::DumpTreeNG(const RefPtr<NG::FrameNode>& parent, int32_t depth,
3509     int64_t nodeID, const CommonProperty& commonProperty, bool isDumpSimplify)
3510 {
3511     auto node = GetFramenodeByAccessibilityId(parent, nodeID);
3512     if (!node) {
3513         DumpLog::GetInstance().Print("Error: failed to get accessibility node with ID " + std::to_string(nodeID));
3514         return;
3515     }
3516     if (!node->IsActive()) {
3517         return;
3518     }
3519     std::vector<int64_t> children;
3520     for (const auto& item : node->GetChildren(true)) {
3521         GetFrameNodeChildren(item, children, commonProperty.pageId);
3522     }
3523 
3524     auto overlayNode = node->GetOverlayNode();
3525     if (overlayNode) {
3526         GetFrameNodeChildren(overlayNode, children, commonProperty.pageId);
3527     }
3528 
3529     if (isDumpSimplify) {
3530         DumpTreeNodeSimplifyInfoNG(node, depth, commonProperty, children.size());
3531     } else {
3532         DumpTreeNodeInfoNG(node, depth, commonProperty, children.size());
3533     }
3534     auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
3535     auto uiVirtualNode = accessibilityProperty->GetAccessibilityVirtualNode();
3536     bool hasVirtualNode = false;
3537     if (uiVirtualNode != nullptr) {
3538         auto virtualNode = AceType::DynamicCast<NG::FrameNode>(uiVirtualNode);
3539         CHECK_NULL_VOID(virtualNode);
3540         hasVirtualNode = true;
3541         DumpTreeAccessibilityNodeNG(uiVirtualNode, depth+1, virtualNode->GetAccessibilityId(), commonProperty);
3542     }
3543     if (IsExtensionComponent(node) && !IsUIExtensionShowPlaceholder(node)) {
3544         std::list<AccessibilityElementInfo> extensionElementInfos;
3545         auto pipeline = context_.Upgrade();
3546         CHECK_NULL_VOID(pipeline);
3547         SearchElementInfoByAccessibilityIdNG(
3548             node->GetAccessibilityId(), PREFETCH_RECURSIVE_CHILDREN, extensionElementInfos,
3549             pipeline, NG::UI_EXTENSION_OFFSET_MAX);
3550         if (!extensionElementInfos.empty()) {
3551             DumpAccessibilityElementInfosTreeNG(extensionElementInfos, depth + 1, node->GetAccessibilityId(), true);
3552         }
3553     }
3554     if (!hasVirtualNode) {
3555         for (auto childId : children) {
3556             DumpTreeNG(node, depth + 1, childId, commonProperty, isDumpSimplify);
3557         }
3558     }
3559 }
3560 
DumpTree(int32_t depth,int64_t nodeID,bool isDumpSimplify)3561 void JsAccessibilityManager::DumpTree(int32_t depth, int64_t nodeID, bool isDumpSimplify)
3562 {
3563     auto pipeline = context_.Upgrade();
3564     CHECK_NULL_VOID(pipeline);
3565     if (!AceType::InstanceOf<NG::PipelineContext>(pipeline)) {
3566         AccessibilityNodeManager::DumpTree(depth, nodeID, isDumpSimplify);
3567     } else {
3568         auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipeline);
3569         auto rootNode = ngPipeline->GetRootElement();
3570         CHECK_NULL_VOID(rootNode);
3571         nodeID = rootNode->GetAccessibilityId();
3572         CommonProperty commonProperty;
3573         GenerateCommonProperty(ngPipeline, commonProperty, pipeline);
3574         DumpTreeNG(rootNode, depth, nodeID, commonProperty, isDumpSimplify);
3575         for (auto subContext : GetSubPipelineContexts()) {
3576             auto subPipeline = subContext.Upgrade();
3577             ngPipeline = AceType::DynamicCast<NG::PipelineContext>(subPipeline);
3578             CHECK_NULL_VOID(ngPipeline);
3579             rootNode = ngPipeline->GetRootElement();
3580             CHECK_NULL_VOID(rootNode);
3581             nodeID = rootNode->GetAccessibilityId();
3582             commonProperty.windowId = static_cast<int32_t>(ngPipeline->GetWindowId());
3583             commonProperty.windowLeft = GetWindowLeft(ngPipeline->GetWindowId());
3584             commonProperty.windowTop = GetWindowTop(ngPipeline->GetWindowId());
3585             commonProperty.pageId = 0;
3586             commonProperty.pagePath = "";
3587             DumpTreeNG(rootNode, depth, nodeID, commonProperty, isDumpSimplify);
3588         }
3589     }
3590 }
3591 
SetCardViewParams(const std::string & key,bool focus)3592 void JsAccessibilityManager::SetCardViewParams(const std::string& key, bool focus)
3593 {
3594     callbackKey_ = key;
3595     if (!callbackKey_.empty()) {
3596         InitializeCallback();
3597     }
3598 }
3599 
UpdateViewScale()3600 void JsAccessibilityManager::UpdateViewScale()
3601 {
3602     auto context = GetPipelineContext().Upgrade();
3603     CHECK_NULL_VOID(context);
3604     float scaleX = 1.0;
3605     float scaleY = 1.0;
3606     if (context->GetViewScale(scaleX, scaleY)) {
3607         scaleX_ = scaleX;
3608         scaleY_ = scaleY;
3609     }
3610 }
3611 
HandleComponentPostBinding()3612 void JsAccessibilityManager::HandleComponentPostBinding()
3613 {
3614     for (auto targetIter = nodeWithTargetMap_.begin(); targetIter != nodeWithTargetMap_.end();) {
3615         auto nodeWithTarget = targetIter->second.Upgrade();
3616         if (nodeWithTarget) {
3617             if (nodeWithTarget->GetTag() == ACCESSIBILITY_TAG_POPUP) {
3618                 auto idNodeIter = nodeWithIdMap_.find(targetIter->first);
3619                 if (idNodeIter != nodeWithIdMap_.end()) {
3620                     auto nodeWithId = idNodeIter->second.Upgrade();
3621                     if (nodeWithId) {
3622                         nodeWithId->SetAccessibilityHint(nodeWithTarget->GetText());
3623                     } else {
3624                         nodeWithIdMap_.erase(idNodeIter);
3625                     }
3626                 }
3627             }
3628             ++targetIter;
3629         } else {
3630             // clear the disabled node in the maps
3631             nodeWithTargetMap_.erase(targetIter++);
3632         }
3633     }
3634 
3635     // clear the disabled node in the maps
3636     for (auto idItem = nodeWithIdMap_.begin(); idItem != nodeWithIdMap_.end();) {
3637         if (!idItem->second.Upgrade()) {
3638             nodeWithIdMap_.erase(idItem++);
3639         } else {
3640             ++idItem;
3641         }
3642     }
3643 }
3644 
Create()3645 RefPtr<AccessibilityNodeManager> AccessibilityNodeManager::Create()
3646 {
3647     return AceType::MakeRefPtr<JsAccessibilityManager>();
3648 }
3649 
GetPipelineByWindowId(const int32_t windowId)3650 RefPtr<PipelineBase> JsAccessibilityManager::GetPipelineByWindowId(const int32_t windowId)
3651 {
3652     auto context = context_.Upgrade();
3653     if (AceType::InstanceOf<NG::PipelineContext>(context)) {
3654         CHECK_NULL_RETURN(context, nullptr);
3655         if (context->GetWindowId() == static_cast<uint32_t>(windowId)) {
3656             return context;
3657         }
3658         if (GetWindowId() == static_cast<uint32_t>(windowId)) {
3659             return context;
3660         }
3661         for (auto& subContext : GetSubPipelineContexts()) {
3662             context = subContext.Upgrade();
3663             CHECK_NULL_RETURN(context, nullptr);
3664             if (context->GetWindowId() == static_cast<uint32_t>(windowId)) {
3665                 return context;
3666             }
3667         }
3668         return nullptr;
3669     } else {
3670         return context;
3671     }
3672 }
3673 
SearchElementInfoByAccessibilityId(const int64_t elementId,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t mode)3674 void JsAccessibilityManager::JsInteractionOperation::SearchElementInfoByAccessibilityId(const int64_t elementId,
3675     const int32_t requestId, AccessibilityElementOperatorCallback& callback, const int32_t mode)
3676 {
3677     TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "search by id: %{public}" PRId64 ", mode: %{public}d",
3678         elementId, mode);
3679     int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
3680     int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
3681     AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
3682 
3683     auto jsAccessibilityManager = GetHandler().Upgrade();
3684     CHECK_NULL_VOID(jsAccessibilityManager);
3685     auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
3686     CHECK_NULL_VOID(context);
3687     auto windowId = windowId_;
3688     context->GetTaskExecutor()->PostTask(
3689         [weak = GetHandler(), splitElementId, requestId, &callback, mode, windowId]() {
3690             auto jsAccessibilityManager = weak.Upgrade();
3691             CHECK_NULL_VOID(jsAccessibilityManager);
3692             ACE_SCOPED_TRACE("SearchElementInfoByAccessibilityId");
3693             jsAccessibilityManager->SearchElementInfoByAccessibilityId(
3694                 splitElementId, requestId, callback, mode, windowId);
3695         },
3696         TaskExecutor::TaskType::UI, "ArkUIAccessibilitySearchElementInfoById");
3697 }
3698 #ifdef WEB_SUPPORTED
3699 
SearchElementInfoByAccessibilityId(const int64_t elementId,const int32_t requestId,Accessibility::AccessibilityElementOperatorCallback & callback,const int32_t mode)3700 void JsAccessibilityManager::WebInteractionOperation::SearchElementInfoByAccessibilityId(const int64_t elementId,
3701     const int32_t requestId, Accessibility::AccessibilityElementOperatorCallback& callback, const int32_t mode)
3702 {
3703     TAG_LOGD(AceLogTag::ACE_WEB, "search by id: %{public}" PRId64 ", mode: %{public}d",
3704         elementId, mode);
3705     int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
3706     int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
3707     AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
3708 
3709     auto jsAccessibilityManager = GetHandler().Upgrade();
3710     CHECK_NULL_VOID(jsAccessibilityManager);
3711     auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
3712     CHECK_NULL_VOID(context);
3713     auto windowId = windowId_;
3714     auto web = webPattern_;
3715     context->GetTaskExecutor()->PostTask(
3716         [weak = GetHandler(), splitElementId, requestId, &callback, mode, windowId, web]() {
3717             auto jsAccessibilityManager = weak.Upgrade();
3718             CHECK_NULL_VOID(jsAccessibilityManager);
3719             auto webPattern = web.Upgrade();
3720             CHECK_NULL_VOID(webPattern);
3721             ACE_SCOPED_TRACE("SearchWebElementInfoByAccessibilityId");
3722             jsAccessibilityManager->SearchWebElementInfoByAccessibilityId(
3723                 splitElementId, requestId, callback, mode, windowId, webPattern);
3724         },
3725         TaskExecutor::TaskType::UI, "ArkWebAccessibilitySearchElementInfoById");
3726 }
3727 
SearchElementInfosByText(const int64_t elementId,const std::string & text,const int32_t requestId,Accessibility::AccessibilityElementOperatorCallback & callback)3728 void JsAccessibilityManager::WebInteractionOperation::SearchElementInfosByText(const int64_t elementId,
3729     const std::string& text, const int32_t requestId, Accessibility::AccessibilityElementOperatorCallback& callback)
3730 {
3731 }
3732 
FindFocusedElementInfo(const int64_t elementId,const int32_t focusType,const int32_t requestId,Accessibility::AccessibilityElementOperatorCallback & callback)3733 void JsAccessibilityManager::WebInteractionOperation::FindFocusedElementInfo(const int64_t elementId,
3734     const int32_t focusType, const int32_t requestId, Accessibility::AccessibilityElementOperatorCallback& callback)
3735 {
3736     TAG_LOGD(AceLogTag::ACE_WEB, "find focus: %{public}" PRId64 ", focusType: %{public}d",
3737         elementId, focusType);
3738     int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
3739     int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
3740     AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
3741 
3742     auto jsAccessibilityManager = GetHandler().Upgrade();
3743     CHECK_NULL_VOID(jsAccessibilityManager);
3744     auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
3745     CHECK_NULL_VOID(context);
3746     auto windowId = windowId_;
3747     auto web = webPattern_;
3748     context->GetTaskExecutor()->PostTask(
3749         [weak = GetHandler(), splitElementId, focusType, requestId, &callback, windowId, web]() {
3750             auto jsAccessibilityManager = weak.Upgrade();
3751             CHECK_NULL_VOID(jsAccessibilityManager);
3752             auto webPattern = web.Upgrade();
3753             CHECK_NULL_VOID(webPattern);
3754             ACE_SCOPED_TRACE("FindWebFocusedElementInfo");
3755             jsAccessibilityManager->FindWebFocusedElementInfo(
3756                 splitElementId, focusType, requestId, callback, windowId, webPattern);
3757         },
3758         TaskExecutor::TaskType::UI, "ArkWebFindFocusedElementInfo");
3759 }
3760 
FocusMoveSearch(const int64_t elementId,const int32_t direction,const int32_t requestId,Accessibility::AccessibilityElementOperatorCallback & callback)3761 void JsAccessibilityManager::WebInteractionOperation::FocusMoveSearch(const int64_t elementId, const int32_t direction,
3762     const int32_t requestId, Accessibility::AccessibilityElementOperatorCallback& callback)
3763 {
3764     TAG_LOGD(AceLogTag::ACE_WEB, "move search: %{public}" PRId64 ", direction: %{public}d",
3765         elementId, direction);
3766     int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
3767     int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
3768     AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
3769 
3770     auto jsAccessibilityManager = GetHandler().Upgrade();
3771     CHECK_NULL_VOID(jsAccessibilityManager);
3772     auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
3773     CHECK_NULL_VOID(context);
3774     auto windowId = windowId_;
3775     auto web = webPattern_;
3776     context->GetTaskExecutor()->PostTask(
3777         [weak = GetHandler(), splitElementId, direction, requestId, &callback, windowId, web] {
3778             auto jsAccessibilityManager = weak.Upgrade();
3779             CHECK_NULL_VOID(jsAccessibilityManager);
3780             auto webPattern = web.Upgrade();
3781             CHECK_NULL_VOID(webPattern);
3782             ACE_SCOPED_TRACE("FocusMoveSearch");
3783             jsAccessibilityManager->WebFocusMoveSearch(splitElementId, direction, requestId, callback,
3784                 windowId, webPattern);
3785         },
3786         TaskExecutor::TaskType::UI, "ArkWebFocusMoveSearch");
3787 }
3788 
ExecuteAction(const int64_t elementId,const int32_t action,const std::map<std::string,std::string> & actionArguments,const int32_t requestId,Accessibility::AccessibilityElementOperatorCallback & callback)3789 void JsAccessibilityManager::WebInteractionOperation::ExecuteAction(const int64_t elementId, const int32_t action,
3790     const std::map<std::string, std::string>& actionArguments, const int32_t requestId,
3791     Accessibility::AccessibilityElementOperatorCallback& callback)
3792 {
3793     TAG_LOGD(AceLogTag::ACE_WEB, "elementId: %{public}" PRId64 ", action: %{public}d", elementId, action);
3794     int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
3795     int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
3796     AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
3797 
3798     auto jsAccessibilityManager = GetHandler().Upgrade();
3799     CHECK_NULL_VOID(jsAccessibilityManager);
3800     auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
3801     CHECK_NULL_VOID(context);
3802     auto actionInfo = static_cast<ActionType>(action);
3803     ActionParam param { actionInfo, actionArguments };
3804     auto windowId = windowId_;
3805     auto web = webPattern_;
3806     context->GetTaskExecutor()->PostTask(
3807         [weak = GetHandler(), splitElementId, param, requestId, &callback, windowId, web] {
3808             auto jsAccessibilityManager = weak.Upgrade();
3809             CHECK_NULL_VOID(jsAccessibilityManager);
3810             auto webPattern = web.Upgrade();
3811             CHECK_NULL_VOID(webPattern);
3812             ACE_SCOPED_TRACE("ExecuteAction");
3813             jsAccessibilityManager->ExecuteWebAction(splitElementId, param, requestId, callback, windowId, webPattern);
3814         },
3815         TaskExecutor::TaskType::UI, "ArkWebAccessibilityExecuteAction");
3816 }
3817 
ClearFocus()3818 void JsAccessibilityManager::WebInteractionOperation::ClearFocus() {}
3819 
SetChildTreeIdAndWinId(const int64_t nodeId,const int32_t treeId,const int32_t childWindowId)3820 void JsAccessibilityManager::WebInteractionOperation::SetChildTreeIdAndWinId(const int64_t nodeId, const int32_t treeId,
3821     const int32_t childWindowId) {}
3822 
SetBelongTreeId(const int32_t treeId)3823 void JsAccessibilityManager::WebInteractionOperation::SetBelongTreeId(const int32_t treeId) {}
3824 
GetCursorPosition(const int64_t elementId,const int32_t requestId,AccessibilityElementOperatorCallback & callback)3825 void JsAccessibilityManager::WebInteractionOperation::GetCursorPosition(
3826     const int64_t elementId, const int32_t requestId, AccessibilityElementOperatorCallback& callback)
3827 {
3828     TAG_LOGD(AceLogTag::ACE_WEB, "GetCursorPosition id: %{public}" PRId64, elementId);
3829     int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
3830     int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
3831     AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
3832 
3833     auto jsAccessibilityManager = GetHandler().Upgrade();
3834     CHECK_NULL_VOID(jsAccessibilityManager);
3835     auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
3836     CHECK_NULL_VOID(context);
3837     auto web = webPattern_;
3838     context->GetTaskExecutor()->PostTask(
3839         [weak = GetHandler(), splitElementId, requestId, &callback, web]() {
3840             auto jsAccessibilityManager = weak.Upgrade();
3841             CHECK_NULL_VOID(jsAccessibilityManager);
3842             auto webPattern = web.Upgrade();
3843             CHECK_NULL_VOID(webPattern);
3844             ACE_SCOPED_TRACE("GetWebCursorPosition");
3845             jsAccessibilityManager->GetWebCursorPosition(splitElementId, requestId, callback, webPattern);
3846         },
3847         TaskExecutor::TaskType::UI, "GetWebCursorPosition");
3848 }
3849 
OutsideTouch()3850 void JsAccessibilityManager::WebInteractionOperation::OutsideTouch() {}
3851 #endif
3852 
SearchElementInfoByAccessibilityId(const int64_t elementId,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t mode,const int32_t windowId)3853 void JsAccessibilityManager::SearchElementInfoByAccessibilityId(const int64_t elementId, const int32_t requestId,
3854     AccessibilityElementOperatorCallback& callback, const int32_t mode, const int32_t windowId)
3855 {
3856     std::list<AccessibilityElementInfo> infos;
3857 
3858     auto pipeline = GetPipelineByWindowId(windowId);
3859     if (pipeline) {
3860         auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipeline);
3861         if (ngPipeline) {
3862             SearchElementInfoByAccessibilityIdNG(elementId, mode, infos, pipeline, NG::UI_EXTENSION_OFFSET_MAX);
3863             SetSearchElementInfoByAccessibilityIdResult(callback, std::move(infos), requestId);
3864             return;
3865         }
3866     }
3867 
3868     int64_t nodeId = elementId;
3869     if (elementId == -1) {
3870         nodeId = 0;
3871     }
3872     auto weak = WeakClaim(this);
3873     auto jsAccessibilityManager = weak.Upgrade();
3874     CHECK_NULL_VOID(jsAccessibilityManager);
3875     auto node = jsAccessibilityManager->GetAccessibilityNodeFromPage(nodeId);
3876     if (!node) {
3877         SetSearchElementInfoByAccessibilityIdResult(callback, std::move(infos), requestId);
3878         return;
3879     }
3880 
3881     AccessibilityElementInfo nodeInfo;
3882     UpdateAccessibilityNodeInfo(node, nodeInfo, jsAccessibilityManager, jsAccessibilityManager->windowId_);
3883     infos.push_back(nodeInfo);
3884     // cache parent/siblings/children infos
3885     UpdateCacheInfo(infos, mode, node, jsAccessibilityManager, jsAccessibilityManager->windowId_);
3886 
3887     SetSearchElementInfoByAccessibilityIdResult(callback, std::move(infos), requestId);
3888 }
3889 
SearchElementInfoByAccessibilityIdNG(int64_t elementId,int32_t mode,std::list<AccessibilityElementInfo> & infos,const RefPtr<PipelineBase> & context,int64_t uiExtensionOffset)3890 void JsAccessibilityManager::SearchElementInfoByAccessibilityIdNG(int64_t elementId, int32_t mode,
3891     std::list<AccessibilityElementInfo>& infos, const RefPtr<PipelineBase>& context, int64_t uiExtensionOffset)
3892 {
3893     TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "elementId: %{public}" PRId64 ", treeId: %{public}d, mode: %{public}d",
3894         elementId, treeId_, mode);
3895     auto mainContext = context_.Upgrade();
3896     CHECK_NULL_VOID(mainContext);
3897 
3898     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
3899     CHECK_NULL_VOID(ngPipeline);
3900     auto rootNode = ngPipeline->GetRootElement();
3901     CHECK_NULL_VOID(rootNode);
3902 
3903     AccessibilityElementInfo nodeInfo;
3904     int64_t nodeId = elementId;
3905     if (elementId == -1) {
3906         nodeId = rootNode->GetAccessibilityId();
3907     }
3908 
3909 #ifdef WINDOW_SCENE_SUPPORTED
3910     auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
3911     CHECK_NULL_VOID(uiExtensionManager);
3912     if (uiExtensionManager->IsWrapExtensionAbilityId(nodeId)) {
3913         SearchParameter param {nodeId, "", mode, uiExtensionOffset};
3914         return SearchExtensionElementInfoByAccessibilityIdNG(param, rootNode, infos, context, ngPipeline);
3915     }
3916 #endif
3917 
3918     CommonProperty commonProperty;
3919     GenerateCommonProperty(ngPipeline, commonProperty, mainContext);
3920     TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "commonProperty.windowId: %{public}d", commonProperty.windowId);
3921     auto node = GetFramenodeByAccessibilityId(rootNode, nodeId);
3922     CHECK_NULL_VOID(node);
3923     UpdateAccessibilityElementInfo(node, commonProperty, nodeInfo, ngPipeline);
3924     SetRootAccessibilityVisible(node, nodeInfo);
3925     if (IsExtensionComponent(node) && !IsUIExtensionShowPlaceholder(node)) {
3926         SearchParameter param {-1, "", mode, uiExtensionOffset};
3927         SearchExtensionElementInfoNG(param, node, infos, nodeInfo);
3928     }
3929     infos.push_back(nodeInfo);
3930     SearchParameter param {nodeId, "", mode, uiExtensionOffset};
3931     UpdateCacheInfoNG(infos, node, commonProperty, ngPipeline, param);
3932     SortExtensionAccessibilityInfo(infos, nodeInfo.GetAccessibilityId());
3933     if ((infos.size() > 0) && (uiExtensionOffset != NG::UI_EXTENSION_OFFSET_MAX) &&
3934         (infos.front().GetComponentType() != V2::ROOT_ETS_TAG) &&
3935         (infos.front().GetParentNodeId() == rootNode->GetAccessibilityId())) {
3936             infos.front().SetParent(NG::UI_EXTENSION_ROOT_ID);
3937     }
3938 }
3939 
SearchExtensionElementInfoByAccessibilityIdNG(const SearchParameter & searchParam,const RefPtr<NG::FrameNode> & node,std::list<Accessibility::AccessibilityElementInfo> & infos,const RefPtr<PipelineBase> & context,const RefPtr<NG::PipelineContext> & ngPipeline)3940 void JsAccessibilityManager::SearchExtensionElementInfoByAccessibilityIdNG(const SearchParameter& searchParam,
3941     const RefPtr<NG::FrameNode>& node, std::list<Accessibility::AccessibilityElementInfo>& infos,
3942     const RefPtr<PipelineBase>& context, const RefPtr<NG::PipelineContext>& ngPipeline)
3943 {
3944 #ifdef WINDOW_SCENE_SUPPORTED
3945     auto mainContext = context_.Upgrade();
3946     CHECK_NULL_VOID(mainContext);
3947     auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
3948     CHECK_NULL_VOID(uiExtensionManager);
3949     auto unWrapIdPair = uiExtensionManager->UnWrapExtensionAbilityId(searchParam.uiExtensionOffset, searchParam.nodeId);
3950     int64_t childWrapId = unWrapIdPair.second;
3951     int64_t uiExtensionId = unWrapIdPair.first;
3952     auto uiExtensionNode = FindNodeFromRootByExtensionId(node, uiExtensionId);
3953     CHECK_NULL_VOID(uiExtensionNode);
3954     SearchParameter param {childWrapId, "", searchParam.mode, searchParam.uiExtensionOffset};
3955     AccessibilityElementInfo nodeInfo;
3956     CommonProperty commonProperty;
3957     GenerateCommonProperty(ngPipeline, commonProperty, mainContext);
3958     UpdateAccessibilityElementInfo(uiExtensionNode, commonProperty, nodeInfo, ngPipeline);
3959     SearchExtensionElementInfoNG(param, uiExtensionNode, infos, nodeInfo);
3960 #endif
3961 }
3962 
SearchElementInfosByTextNG(int64_t elementId,const std::string & text,const RefPtr<NG::FrameNode> & node,int64_t offset)3963 std::list<AccessibilityElementInfo> JsAccessibilityManager::SearchElementInfosByTextNG(
3964     int64_t elementId, const std::string& text, const RefPtr<NG::FrameNode>& node, int64_t offset)
3965 {
3966     std::list<AccessibilityElementInfo> extensionElementInfo;
3967     if (NG::UI_EXTENSION_OFFSET_MIN < (offset + 1)) {
3968         node->SearchElementInfosByTextNG(elementId, text, offset, extensionElementInfo);
3969     }
3970     return extensionElementInfo;
3971 }
3972 
SearchElementInfosByTextNG(const SearchParameter & searchParam,const RefPtr<NG::FrameNode> & node,std::list<Accessibility::AccessibilityElementInfo> & infos,const RefPtr<PipelineBase> & context,const RefPtr<NG::PipelineContext> & ngPipeline)3973 void JsAccessibilityManager::SearchElementInfosByTextNG(const SearchParameter& searchParam,
3974     const RefPtr<NG::FrameNode>& node, std::list<Accessibility::AccessibilityElementInfo>& infos,
3975     const RefPtr<PipelineBase>& context, const RefPtr<NG::PipelineContext>& ngPipeline)
3976 {
3977 #ifdef WINDOW_SCENE_SUPPORTED
3978     auto mainContext = context_.Upgrade();
3979     CHECK_NULL_VOID(mainContext);
3980     auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
3981     CHECK_NULL_VOID(uiExtensionManager);
3982     auto unWrapIdPair = uiExtensionManager->UnWrapExtensionAbilityId(searchParam.uiExtensionOffset, searchParam.nodeId);
3983     int64_t childWrapId = unWrapIdPair.second;
3984     int64_t uiExtensionId = unWrapIdPair.first;
3985     std::list<AccessibilityElementInfo> extensionElementInfos;
3986     AccessibilityElementInfo nodeInfo;
3987     auto uiExtensionNode = FindNodeFromRootByExtensionId(node, uiExtensionId);
3988     CHECK_NULL_VOID(uiExtensionNode);
3989 
3990     extensionElementInfos = SearchElementInfosByTextNG(
3991         childWrapId, searchParam.text, uiExtensionNode, searchParam.uiExtensionOffset / NG::UI_EXTENSION_ID_FACTOR);
3992     if (extensionElementInfos.empty()) {
3993         return;
3994     }
3995     CommonProperty commonProperty;
3996     GenerateCommonProperty(ngPipeline, commonProperty, mainContext);
3997     UpdateAccessibilityElementInfo(uiExtensionNode, commonProperty, nodeInfo, ngPipeline);
3998     ConvertExtensionAccessibilityNodeId(extensionElementInfos, uiExtensionNode,
3999         searchParam.uiExtensionOffset, nodeInfo);
4000     for (auto& info : extensionElementInfos) {
4001         infos.emplace_back(info);
4002     }
4003 #endif
4004 }
4005 
FindNodeFromRootByExtensionId(const RefPtr<NG::FrameNode> & root,const int64_t uiExtensionId)4006 RefPtr<NG::FrameNode> JsAccessibilityManager::FindNodeFromRootByExtensionId(
4007     const RefPtr<NG::FrameNode>& root, const int64_t uiExtensionId)
4008 {
4009     CHECK_NULL_RETURN(root, nullptr);
4010     std::queue<RefPtr<NG::UINode>> nodes;
4011     nodes.push(root);
4012     RefPtr<NG::FrameNode> frameNode;
4013     while (!nodes.empty()) {
4014         auto current = nodes.front();
4015         nodes.pop();
4016         frameNode = AceType::DynamicCast<NG::FrameNode>(current);
4017         if (IsExtensionComponent(frameNode) && !IsUIExtensionShowPlaceholder(frameNode) &&
4018             (uiExtensionId == frameNode->GetUiExtensionId())) {
4019             return frameNode;
4020         }
4021         const auto& children = current->GetChildren(true);
4022         for (const auto& child : children) {
4023             nodes.push(child);
4024         }
4025     }
4026     return nullptr;
4027 }
4028 
SearchElementInfosByTextNG(int64_t elementId,const std::string & text,std::list<Accessibility::AccessibilityElementInfo> & infos,const RefPtr<PipelineBase> & context,int64_t uiExtensionOffset)4029 void JsAccessibilityManager::SearchElementInfosByTextNG(int64_t elementId, const std::string& text,
4030     std::list<Accessibility::AccessibilityElementInfo>& infos, const RefPtr<PipelineBase>& context,
4031     int64_t uiExtensionOffset)
4032 {
4033     auto mainContext = context_.Upgrade();
4034     CHECK_NULL_VOID(mainContext);
4035     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
4036     CHECK_NULL_VOID(ngPipeline);
4037     auto rootNode = ngPipeline->GetRootElement();
4038     CHECK_NULL_VOID(rootNode);
4039 #ifdef WINDOW_SCENE_SUPPORTED
4040     auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
4041     CHECK_NULL_VOID(uiExtensionManager);
4042     if (uiExtensionManager->IsWrapExtensionAbilityId(elementId)) {
4043         SearchParameter param {elementId, text, 0, uiExtensionOffset};
4044         SearchElementInfosByTextNG(param, rootNode, infos, context, ngPipeline);
4045         return;
4046     }
4047 #endif
4048     if (elementId == NG::UI_EXTENSION_ROOT_ID) {
4049         elementId = rootNode->GetAccessibilityId();
4050     }
4051     auto node = GetFramenodeByAccessibilityId(rootNode, elementId);
4052     CHECK_NULL_VOID(node);
4053     CommonProperty commonProperty;
4054     GenerateCommonProperty(ngPipeline, commonProperty, mainContext);
4055     nlohmann::json textJson = nlohmann::json::parse(text, nullptr, false);
4056     if (textJson.is_null() || textJson.is_discarded() || !textJson.contains("type")) {
4057         return;
4058     }
4059     if (textJson["type"] == "textType") {
4060         SearchParameter param {0, text, 0, uiExtensionOffset};
4061         FindTextByTextHint(node, infos, ngPipeline, commonProperty, param);
4062         return;
4063     }
4064     if (!textJson.contains("value")) {
4065         return;
4066     }
4067     SearchParameter param {0, textJson["value"], 0, uiExtensionOffset};
4068     FindText(node, infos, ngPipeline, commonProperty, param);
4069 }
4070 
SearchElementInfosByText(const int64_t elementId,const std::string & text,const int32_t requestId,AccessibilityElementOperatorCallback & callback)4071 void JsAccessibilityManager::JsInteractionOperation::SearchElementInfosByText(const int64_t elementId,
4072     const std::string& text, const int32_t requestId, AccessibilityElementOperatorCallback& callback)
4073 {
4074     TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "search by text: %{public}" PRId64 ", text: %{public}s",
4075         elementId, text.c_str());
4076     int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
4077     int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
4078     AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
4079 
4080     if (text.empty()) {
4081         return;
4082     }
4083     auto jsAccessibilityManager = GetHandler().Upgrade();
4084     CHECK_NULL_VOID(jsAccessibilityManager);
4085     auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
4086     CHECK_NULL_VOID(context);
4087     auto windowId = windowId_;
4088     if (context) {
4089         context->GetTaskExecutor()->PostTask(
4090             [weak = GetHandler(), splitElementId, text, requestId, &callback, windowId]() {
4091                 auto jsAccessibilityManager = weak.Upgrade();
4092                 CHECK_NULL_VOID(jsAccessibilityManager);
4093                 ACE_SCOPED_TRACE("SearchElementInfosByText");
4094                 jsAccessibilityManager->SearchElementInfosByText(
4095                     splitElementId, text, requestId, callback, windowId);
4096             },
4097             TaskExecutor::TaskType::UI, "ArkUIAccessibilitySearchElementInfoByText");
4098     }
4099 }
4100 
SearchElementInfosByText(const int64_t elementId,const std::string & text,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t windowId)4101 void JsAccessibilityManager::SearchElementInfosByText(const int64_t elementId, const std::string& text,
4102     const int32_t requestId, AccessibilityElementOperatorCallback& callback, const int32_t windowId)
4103 {
4104     if (text.empty()) {
4105         return;
4106     }
4107 
4108     if (elementId == -1) {
4109         return;
4110     }
4111 
4112     std::list<AccessibilityElementInfo> infos;
4113 
4114     auto pipeline = GetPipelineByWindowId(windowId);
4115     if (pipeline) {
4116         if (AceType::InstanceOf<NG::PipelineContext>(pipeline)) {
4117             SearchElementInfosByTextNG(elementId, text, infos, pipeline, NG::UI_EXTENSION_OFFSET_MAX);
4118             SetSearchElementInfoByTextResult(callback, std::move(infos), requestId);
4119             return;
4120         }
4121     }
4122 
4123     auto weak = WeakClaim(this);
4124     auto jsAccessibilityManager = weak.Upgrade();
4125     CHECK_NULL_VOID(jsAccessibilityManager);
4126     int64_t nodeId = elementId;
4127     auto node = jsAccessibilityManager->GetAccessibilityNodeFromPage(nodeId);
4128     CHECK_NULL_VOID(node);
4129     std::list<RefPtr<AccessibilityNode>> nodeList;
4130     OHOS::Ace::Framework::FindText(node, text, nodeList);
4131     if (!nodeList.empty()) {
4132         for (const auto& node : nodeList) {
4133             AccessibilityElementInfo nodeInfo;
4134             UpdateAccessibilityNodeInfo(node, nodeInfo, jsAccessibilityManager, jsAccessibilityManager->windowId_);
4135             infos.emplace_back(nodeInfo);
4136         }
4137     }
4138 
4139     SetSearchElementInfoByTextResult(callback, std::move(infos), requestId);
4140 }
4141 
FindFocusedElementInfo(const int64_t elementId,const int32_t focusType,const int32_t requestId,AccessibilityElementOperatorCallback & callback)4142 void JsAccessibilityManager::JsInteractionOperation::FindFocusedElementInfo(const int64_t elementId,
4143     const int32_t focusType, const int32_t requestId, AccessibilityElementOperatorCallback& callback)
4144 {
4145     TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "find focus: %{public}" PRId64 ", focusType: %{public}d",
4146         elementId, focusType);
4147     int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
4148     int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
4149     AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
4150 
4151     auto jsAccessibilityManager = GetHandler().Upgrade();
4152     CHECK_NULL_VOID(jsAccessibilityManager);
4153     auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
4154     CHECK_NULL_VOID(context);
4155     auto windowId = windowId_;
4156     context->GetTaskExecutor()->PostTask(
4157         [weak = GetHandler(), splitElementId, focusType, requestId, &callback, windowId]() {
4158             auto jsAccessibilityManager = weak.Upgrade();
4159             CHECK_NULL_VOID(jsAccessibilityManager);
4160             ACE_SCOPED_TRACE("FindFocusedElementInfo");
4161             jsAccessibilityManager->FindFocusedElementInfo(splitElementId, focusType, requestId, callback, windowId);
4162         },
4163         TaskExecutor::TaskType::UI, "ArkUIAccessibilityFindFocusedElementInfo");
4164 }
4165 
FindFocusedElementInfo(const int64_t elementId,const int32_t focusType,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t windowId)4166 void JsAccessibilityManager::FindFocusedElementInfo(const int64_t elementId, const int32_t focusType,
4167     const int32_t requestId, AccessibilityElementOperatorCallback& callback, const int32_t windowId)
4168 {
4169     AccessibilityElementInfo nodeInfo;
4170     if (focusType != FOCUS_TYPE_INPUT && focusType != FOCUS_TYPE_ACCESSIBILITY) {
4171         nodeInfo.SetValidElement(false);
4172         SetFindFocusedElementInfoResult(callback, nodeInfo, requestId);
4173         return;
4174     }
4175 
4176     auto context = GetPipelineByWindowId(windowId);
4177     if (!context) {
4178         SetFindFocusedElementInfoResult(callback, nodeInfo, requestId);
4179         return;
4180     }
4181 
4182     if (AceType::InstanceOf<NG::PipelineContext>(context)) {
4183         FindFocusedElementInfoNG(elementId, focusType, nodeInfo, context, NG::UI_EXTENSION_OFFSET_MAX);
4184         SetFindFocusedElementInfoResult(callback, nodeInfo, requestId);
4185         return;
4186     }
4187 
4188     int64_t nodeId = static_cast<int64_t>(elementId);
4189     if (elementId == -1) {
4190         nodeId = 0;
4191     }
4192 
4193     auto node = GetAccessibilityNodeFromPage(nodeId);
4194     if (!node) {
4195         nodeInfo.SetValidElement(false);
4196         SetFindFocusedElementInfoResult(callback, nodeInfo, requestId);
4197         return;
4198     }
4199 
4200     RefPtr<AccessibilityNode> resultNode = nullptr;
4201     bool status = false;
4202     if (focusType == FOCUS_TYPE_ACCESSIBILITY) {
4203         status = FindAccessibilityFocus(node, resultNode);
4204     }
4205     if (focusType == FOCUS_TYPE_INPUT) {
4206         status = FindInputFocus(node, resultNode);
4207     }
4208 
4209     if ((status) && (resultNode != nullptr)) {
4210         UpdateAccessibilityNodeInfo(resultNode, nodeInfo, Claim(this), windowId_);
4211     }
4212 
4213     SetFindFocusedElementInfoResult(callback, nodeInfo, requestId);
4214 }
4215 
FindFocusedElementInfoNG(int64_t elementId,int32_t focusType,Accessibility::AccessibilityElementInfo & info,const RefPtr<PipelineBase> & context,const int64_t uiExtensionOffset)4216 void JsAccessibilityManager::FindFocusedElementInfoNG(int64_t elementId, int32_t focusType,
4217     Accessibility::AccessibilityElementInfo& info, const RefPtr<PipelineBase>& context,
4218     const int64_t uiExtensionOffset)
4219 {
4220     auto mainContext = context_.Upgrade();
4221     CHECK_NULL_VOID(mainContext);
4222     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
4223     CHECK_NULL_VOID(ngPipeline);
4224     auto rootNode = ngPipeline->GetRootElement();
4225     CHECK_NULL_VOID(rootNode);
4226 #ifdef WINDOW_SCENE_SUPPORTED
4227     auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
4228     CHECK_NULL_VOID(uiExtensionManager);
4229     if (uiExtensionManager->IsWrapExtensionAbilityId(elementId)) {
4230         SearchParameter param {elementId, "", focusType, uiExtensionOffset};
4231         return FindFocusedExtensionElementInfoNG(param, info, context, rootNode);
4232     }
4233 #endif
4234     int64_t nodeId = elementId;
4235     if (elementId == -1) {
4236         nodeId = rootNode->GetAccessibilityId();
4237     }
4238     auto node = GetFramenodeByAccessibilityId(rootNode, nodeId);
4239     if (!node) {
4240         return info.SetValidElement(false);
4241     }
4242     if (IsExtensionComponent(node) && !IsUIExtensionShowPlaceholder(node)) {
4243         SearchParameter transferSearchParam {NG::UI_EXTENSION_ROOT_ID, "", focusType, uiExtensionOffset};
4244         OHOS::Ace::Framework::FindFocusedExtensionElementInfoNG(transferSearchParam, node, info);
4245         return SetUiExtensionAbilityParentIdForFocus(node, uiExtensionOffset, info);
4246     }
4247     RefPtr<NG::FrameNode> resultNode;
4248     if (focusType == FOCUS_TYPE_ACCESSIBILITY) {
4249         resultNode = FindAccessibilityFocus(node, focusType, info, uiExtensionOffset, context, currentFocusNodeId_);
4250     }
4251     if (focusType == FOCUS_TYPE_INPUT) {
4252         resultNode = FindInputFocus(node, focusType, info, uiExtensionOffset, context);
4253     }
4254     if ((!resultNode) || (IsExtensionComponent(resultNode) && !IsUIExtensionShowPlaceholder(resultNode))) {
4255         return;
4256     }
4257     CommonProperty commonProperty;
4258     GenerateCommonProperty(ngPipeline, commonProperty, mainContext);
4259     UpdateAccessibilityElementInfo(resultNode, commonProperty, info, ngPipeline);
4260     UpdateUiExtensionParentIdForFocus(rootNode, uiExtensionOffset, info);
4261 }
4262 
FindFocusedExtensionElementInfoNG(const SearchParameter & searchParam,Accessibility::AccessibilityElementInfo & info,const RefPtr<PipelineBase> & context,const RefPtr<NG::FrameNode> & root)4263 void JsAccessibilityManager::FindFocusedExtensionElementInfoNG(const SearchParameter& searchParam,
4264     Accessibility::AccessibilityElementInfo& info,
4265     const RefPtr<PipelineBase>& context, const RefPtr<NG::FrameNode>& root)
4266 {
4267 #ifdef WINDOW_SCENE_SUPPORTED
4268     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
4269     CHECK_NULL_VOID(ngPipeline);
4270     auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
4271     CHECK_NULL_VOID(uiExtensionManager);
4272     auto elementIdPair = uiExtensionManager->UnWrapExtensionAbilityId(searchParam.uiExtensionOffset,
4273         searchParam.nodeId);
4274     auto uiExtensionNode = uiExtensionManager->GetFocusUiExtensionNode();
4275     CHECK_NULL_VOID(uiExtensionNode);
4276     SearchParameter transferSearchParam {elementIdPair.second, "",
4277         searchParam.mode, searchParam.uiExtensionOffset};
4278     OHOS::Ace::Framework::FindFocusedExtensionElementInfoNG(transferSearchParam, uiExtensionNode, info);
4279     SetUiExtensionAbilityParentIdForFocus(uiExtensionNode, searchParam.uiExtensionOffset, info);
4280 #endif
4281 }
4282 
FindNodeFromPipeline(const WeakPtr<PipelineBase> & context,const int64_t elementId)4283 RefPtr<NG::FrameNode> JsAccessibilityManager::FindNodeFromPipeline(
4284     const WeakPtr<PipelineBase>& context, const int64_t elementId)
4285 {
4286     auto pipeline = context.Upgrade();
4287     CHECK_NULL_RETURN(pipeline, nullptr);
4288 
4289     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipeline);
4290     auto rootNode = ngPipeline->GetRootElement();
4291     CHECK_NULL_RETURN(rootNode, nullptr);
4292 
4293     int64_t nodeId = elementId;
4294     // accessibility use -1 for first search to get root node
4295     if (elementId == -1) {
4296         nodeId = rootNode->GetAccessibilityId();
4297     }
4298 
4299     auto node = GetFramenodeByAccessibilityId(rootNode, nodeId);
4300     if (node) {
4301         return node;
4302     }
4303     return nullptr;
4304 }
4305 
FindPipelineByElementId(const int64_t elementId,RefPtr<NG::FrameNode> & node)4306 RefPtr<NG::PipelineContext> JsAccessibilityManager::FindPipelineByElementId(
4307     const int64_t elementId, RefPtr<NG::FrameNode>& node)
4308 {
4309     node = FindNodeFromPipeline(context_, elementId);
4310     if (node) {
4311         auto context = AceType::DynamicCast<NG::PipelineContext>(context_.Upgrade());
4312         return context;
4313     }
4314     for (auto subContext : GetSubPipelineContexts()) {
4315         node = FindNodeFromPipeline(subContext, elementId);
4316         if (node) {
4317             auto context = AceType::DynamicCast<NG::PipelineContext>(subContext.Upgrade());
4318             return context;
4319         }
4320     }
4321     return nullptr;
4322 }
4323 
ExecuteAction(const int64_t elementId,const int32_t action,const std::map<std::string,std::string> & actionArguments,const int32_t requestId,AccessibilityElementOperatorCallback & callback)4324 void JsAccessibilityManager::JsInteractionOperation::ExecuteAction(const int64_t elementId, const int32_t action,
4325     const std::map<std::string, std::string>& actionArguments, const int32_t requestId,
4326     AccessibilityElementOperatorCallback& callback)
4327 {
4328     TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "elementId: %{public}" PRId64 ", action: %{public}d", elementId, action);
4329     int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
4330     int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
4331     AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
4332 
4333     auto jsAccessibilityManager = GetHandler().Upgrade();
4334     CHECK_NULL_VOID(jsAccessibilityManager);
4335     auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
4336     CHECK_NULL_VOID(context);
4337     auto actionInfo = static_cast<ActionType>(action);
4338     ActionParam param { actionInfo, actionArguments };
4339     auto windowId = windowId_;
4340     context->GetTaskExecutor()->PostTask(
4341         [weak = GetHandler(), splitElementId, param, requestId, &callback, windowId] {
4342             auto jsAccessibilityManager = weak.Upgrade();
4343             CHECK_NULL_VOID(jsAccessibilityManager);
4344             ACE_SCOPED_TRACE("ExecuteAction");
4345             jsAccessibilityManager->ExecuteAction(splitElementId, param, requestId, callback, windowId);
4346         },
4347         TaskExecutor::TaskType::UI, "ArkUIAccessibilityExecuteAction");
4348 }
4349 
AccessibilityActionEvent(const ActionType & action,const std::map<std::string,std::string> & actionArguments,const RefPtr<AccessibilityNode> & node,const RefPtr<PipelineContext> & context)4350 bool JsAccessibilityManager::AccessibilityActionEvent(const ActionType& action,
4351     const std::map<std::string, std::string>& actionArguments, const RefPtr<AccessibilityNode>& node,
4352     const RefPtr<PipelineContext>& context)
4353 {
4354     if (!node || !context) {
4355         return false;
4356     }
4357     ContainerScope scope(context->GetInstanceId());
4358     switch (action) {
4359         case ActionType::ACCESSIBILITY_ACTION_CLICK: {
4360             node->SetClicked(true);
4361             if (!node->GetClickEventMarker().IsEmpty()) {
4362 #ifndef NG_BUILD
4363                 context->SendEventToFrontend(node->GetClickEventMarker());
4364 #endif
4365                 node->ActionClick();
4366                 return true;
4367             }
4368             return node->ActionClick();
4369         }
4370         case ActionType::ACCESSIBILITY_ACTION_LONG_CLICK: {
4371             if (!node->GetLongPressEventMarker().IsEmpty()) {
4372 #ifndef NG_BUILD
4373                 context->SendEventToFrontend(node->GetLongPressEventMarker());
4374 #endif
4375                 node->ActionLongClick();
4376                 return true;
4377             }
4378             return node->ActionLongClick();
4379         }
4380         case ActionType::ACCESSIBILITY_ACTION_SET_TEXT: {
4381             if (!node->GetSetTextEventMarker().IsEmpty()) {
4382 #ifndef NG_BUILD
4383                 context->SendEventToFrontend(node->GetSetTextEventMarker());
4384 #endif
4385                 node->ActionSetText(actionArguments.find(ACTION_ARGU_SET_TEXT)->second);
4386                 return true;
4387             }
4388             return node->ActionSetText(actionArguments.find(ACTION_ARGU_SET_TEXT)->second);
4389         }
4390         case ActionType::ACCESSIBILITY_ACTION_FOCUS: {
4391 #ifndef NG_BUILD
4392             context->AccessibilityRequestFocus(std::to_string(node->GetNodeId()));
4393 #endif
4394             if (!node->GetFocusEventMarker().IsEmpty()) {
4395 #ifndef NG_BUILD
4396                 context->SendEventToFrontend(node->GetFocusEventMarker());
4397 #endif
4398                 node->ActionFocus();
4399                 return true;
4400             }
4401             return node->ActionFocus();
4402         }
4403         case ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS: {
4404             return RequestAccessibilityFocus(node);
4405         }
4406         case ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
4407             return ClearAccessibilityFocus(node);
4408         }
4409         case ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD:
4410             return node->ActionScrollForward();
4411         case ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD:
4412             return node->ActionScrollBackward();
4413         default:
4414             return false;
4415     }
4416 }
4417 
SendActionEvent(const Accessibility::ActionType & action,int64_t nodeId)4418 void JsAccessibilityManager::SendActionEvent(const Accessibility::ActionType& action, int64_t nodeId)
4419 {
4420     static std::unordered_map<Accessibility::ActionType, std::string> actionToStr {
4421         { Accessibility::ActionType::ACCESSIBILITY_ACTION_CLICK, DOM_CLICK },
4422         { Accessibility::ActionType::ACCESSIBILITY_ACTION_LONG_CLICK, DOM_LONG_PRESS },
4423         { Accessibility::ActionType::ACCESSIBILITY_ACTION_FOCUS, DOM_FOCUS },
4424         { Accessibility::ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS, ACCESSIBILITY_FOCUSED_EVENT },
4425         { Accessibility::ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS, ACCESSIBILITY_CLEAR_FOCUS_EVENT },
4426         { Accessibility::ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD, SCROLL_END_EVENT },
4427         { Accessibility::ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD, SCROLL_END_EVENT },
4428     };
4429     if (actionToStr.find(action) == actionToStr.end()) {
4430         return;
4431     }
4432     AccessibilityEvent accessibilityEvent;
4433     accessibilityEvent.eventType = actionToStr[action];
4434     accessibilityEvent.nodeId = static_cast<int64_t>(nodeId);
4435     SendAccessibilityAsyncEvent(accessibilityEvent);
4436 }
4437 
4438 namespace {
stringToLower(std::string & str)4439 void stringToLower(std::string &str)
4440 {
4441     std::transform(str.begin(), str.end(), str.begin(), [](char &c) {
4442         return std::tolower(c);
4443     });
4444 }
4445 
conversionDirection(std::string dir)4446 bool conversionDirection(std::string dir)
4447 {
4448     stringToLower(dir);
4449     if (dir.compare(STRING_DIR_FORWARD) == 0) {
4450         return true;
4451     }
4452 
4453     return false;
4454 }
4455 
getArgumentByKey(const std::map<std::string,std::string> & actionArguments,const std::string & checkKey)4456 int32_t getArgumentByKey(const std::map<std::string, std::string>& actionArguments, const std::string& checkKey)
4457 {
4458     auto iter = actionArguments.find(checkKey);
4459     int32_t argument = -1; // -1:default value
4460     if (iter != actionArguments.end()) {
4461         std::stringstream strArguments;
4462         strArguments << iter->second;
4463         strArguments >> argument;
4464     }
4465     return argument;
4466 }
4467 
findAccessibilityScrollType(int32_t accessibilityScrollTypeValue)4468 AccessibilityScrollType findAccessibilityScrollType(int32_t accessibilityScrollTypeValue)
4469 {
4470     switch (accessibilityScrollTypeValue) {
4471         case 0:
4472             return AccessibilityScrollType::SCROLL_HALF;
4473         case 1:
4474             return AccessibilityScrollType::SCROLL_FULL;
4475         default:
4476             return AccessibilityScrollType::SCROLL_DEFAULT;
4477     }
4478 }
4479 
getAccessibilityScrollType(const std::map<std::string,std::string> & actionArguments,const std::string & checkKey)4480 AccessibilityScrollType getAccessibilityScrollType(const std::map<std::string, std::string>& actionArguments,
4481     const std::string& checkKey)
4482 {
4483     auto argument = getArgumentByKey(actionArguments, checkKey);
4484     return findAccessibilityScrollType(argument);
4485 }
4486 
4487 
ActAccessibilityAction(Accessibility::ActionType action,const std::map<std::string,std::string> & actionArguments,RefPtr<NG::AccessibilityProperty> accessibilityProperty)4488 bool ActAccessibilityAction(Accessibility::ActionType action, const std::map<std::string, std::string>& actionArguments,
4489     RefPtr<NG::AccessibilityProperty> accessibilityProperty)
4490 {
4491     AccessibilityActionParam param;
4492     if (action == ActionType::ACCESSIBILITY_ACTION_SET_SELECTION) {
4493         std::string dir = STRING_DIR_BACKWARD;
4494         auto iter = actionArguments.find(ACTION_ARGU_SELECT_TEXT_INFORWARD);
4495         if (iter != actionArguments.end()) {
4496             dir = iter->second;
4497         }
4498         param.setSelectionStart = getArgumentByKey(actionArguments, ACTION_ARGU_SELECT_TEXT_START);
4499         param.setSelectionEnd = getArgumentByKey(actionArguments, ACTION_ARGU_SELECT_TEXT_END);
4500         param.setSelectionDir = conversionDirection(dir);
4501     }
4502     if (action == ActionType::ACCESSIBILITY_ACTION_SET_TEXT) {
4503         auto iter = actionArguments.find(ACTION_ARGU_SET_TEXT);
4504         if (iter != actionArguments.end()) {
4505             param.setTextArgument = iter->second;
4506         }
4507     }
4508     if (action == ActionType::ACCESSIBILITY_ACTION_NEXT_TEXT ||
4509         action == ActionType::ACCESSIBILITY_ACTION_PREVIOUS_TEXT) {
4510         int moveUnit = TextMoveUnit::STEP_CHARACTER;
4511         auto iter = actionArguments.find(ACTION_ARGU_MOVE_UNIT);
4512         if (iter != actionArguments.end()) {
4513             std::stringstream str_moveUnit;
4514             str_moveUnit << iter->second;
4515             str_moveUnit >> moveUnit;
4516         }
4517         param.moveUnit = static_cast<TextMoveUnit>(moveUnit);
4518     }
4519     if (action == ActionType::ACCESSIBILITY_ACTION_SET_CURSOR_POSITION) {
4520         param.setCursorIndex = getArgumentByKey(actionArguments, ACTION_ARGU_SET_OFFSET);
4521     }
4522     if ((action == ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD) ||
4523         (action == ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD)) {
4524         param.scrollType = getAccessibilityScrollType(actionArguments, ACTION_ARGU_SCROLL_STUB);
4525     }
4526     if (action == ActionType::ACCESSIBILITY_ACTION_SPAN_CLICK) {
4527         param.spanId = getArgumentByKey(actionArguments, ACTION_ARGU_SPAN_ID);
4528     }
4529     auto accessibiltyAction = ACTIONS.find(action);
4530     if (accessibiltyAction != ACTIONS.end()) {
4531         param.accessibilityProperty = accessibilityProperty;
4532         return accessibiltyAction->second(param);
4533     }
4534     return false;
4535 }
4536 }
4537 
ExecuteExtensionActionNG(int64_t elementId,const std::map<std::string,std::string> & actionArguments,int32_t action,const RefPtr<PipelineBase> & context,int64_t uiExtensionOffset)4538 bool JsAccessibilityManager::ExecuteExtensionActionNG(int64_t elementId,
4539     const std::map<std::string, std::string>& actionArguments, int32_t action, const RefPtr<PipelineBase>& context,
4540     int64_t uiExtensionOffset)
4541 {
4542     return ExecuteActionNG(
4543         elementId, actionArguments, static_cast<ActionType>(action), context, uiExtensionOffset);
4544 }
4545 
ExecuteActionNG(int64_t elementId,const std::map<std::string,std::string> & actionArguments,ActionType action,const RefPtr<PipelineBase> & context,int64_t uiExtensionOffset)4546 bool JsAccessibilityManager::ExecuteActionNG(int64_t elementId,
4547     const std::map<std::string, std::string>& actionArguments, ActionType action, const RefPtr<PipelineBase>& context,
4548     int64_t uiExtensionOffset)
4549 {
4550     bool result = false;
4551     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
4552     CHECK_NULL_RETURN(ngPipeline, result);
4553 #ifdef WINDOW_SCENE_SUPPORTED
4554     auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
4555     CHECK_NULL_RETURN(uiExtensionManager, result);
4556     if (uiExtensionManager->IsWrapExtensionAbilityId(elementId)) {
4557         auto unWrapIdPair = uiExtensionManager->UnWrapExtensionAbilityId(uiExtensionOffset, elementId);
4558         int64_t childWrapId = unWrapIdPair.second;
4559         int64_t uiExtensionId = unWrapIdPair.first;
4560         auto rootNode = ngPipeline->GetRootElement();
4561         CHECK_NULL_RETURN(rootNode, result);
4562         auto uiExtensionNode = FindNodeFromRootByExtensionId(rootNode, uiExtensionId);
4563         CHECK_NULL_RETURN(uiExtensionNode, result);
4564         return OHOS::Ace::Framework::TransferExecuteAction(
4565             childWrapId, uiExtensionNode, actionArguments, action, uiExtensionOffset);
4566     }
4567 #endif
4568     ContainerScope instance(ngPipeline->GetInstanceId());
4569     auto frameNode = GetFramenodeByAccessibilityId(ngPipeline->GetRootElement(), elementId);
4570     if (!frameNode && elementId == lastElementId_) {
4571         frameNode = lastFrameNode_.Upgrade();
4572     }
4573     CHECK_NULL_RETURN(frameNode, result);
4574 
4575     auto enabled = frameNode->GetFocusHub() ? frameNode->GetFocusHub()->IsEnabled() : true;
4576     if (!enabled && action != ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS &&
4577         action != ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS) {
4578         return result;
4579     }
4580     result = ConvertActionTypeToBoolen(action, frameNode, elementId, ngPipeline);
4581     if (!result) {
4582         auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
4583         CHECK_NULL_RETURN(accessibilityProperty, false);
4584         result = ActAccessibilityAction(action, actionArguments, accessibilityProperty);
4585     }
4586     return result;
4587 }
4588 
ConvertActionTypeToBoolen(ActionType action,RefPtr<NG::FrameNode> & frameNode,int64_t elementId,RefPtr<NG::PipelineContext> & context)4589 bool JsAccessibilityManager::ConvertActionTypeToBoolen(ActionType action, RefPtr<NG::FrameNode>& frameNode,
4590     int64_t elementId, RefPtr<NG::PipelineContext>& context)
4591 {
4592     bool result = false;
4593     switch (action) {
4594         case ActionType::ACCESSIBILITY_ACTION_FOCUS: {
4595             result = RequestFocus(frameNode);
4596             break;
4597         }
4598         case ActionType::ACCESSIBILITY_ACTION_CLEAR_FOCUS: {
4599             result = LostFocus(frameNode);
4600             break;
4601         }
4602         case ActionType::ACCESSIBILITY_ACTION_CLICK: {
4603             result = ActClick(frameNode);
4604             break;
4605         }
4606         case ActionType::ACCESSIBILITY_ACTION_LONG_CLICK: {
4607             result = ActLongClick(frameNode);
4608             break;
4609         }
4610         case ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS: {
4611             SaveLast(elementId, frameNode);
4612             SaveCurrentFocusNodeSize(frameNode);
4613             result = ActAccessibilityFocus(elementId, frameNode, context, currentFocusNodeId_, false);
4614             break;
4615         }
4616         case ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
4617             SaveLast(elementId, frameNode);
4618             result = ActAccessibilityFocus(elementId, frameNode, context, currentFocusNodeId_, true);
4619             break;
4620         }
4621         default:
4622             break;
4623     }
4624     return result;
4625 }
4626 
ExecuteAction(const int64_t elementId,const ActionParam & param,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t windowId)4627 void JsAccessibilityManager::ExecuteAction(const int64_t elementId, const ActionParam& param, const int32_t requestId,
4628     AccessibilityElementOperatorCallback& callback, const int32_t windowId)
4629 {
4630     auto action = param.action;
4631     auto actionArguments = param.actionArguments;
4632 
4633     bool actionResult = false;
4634     auto context = GetPipelineByWindowId(windowId);
4635     if (!context) {
4636         SetExecuteActionResult(callback, actionResult, requestId);
4637         return;
4638     }
4639 
4640     if (AceType::InstanceOf<NG::PipelineContext>(context)) {
4641         actionResult = ExecuteActionNG(elementId, actionArguments, action, context, NG::UI_EXTENSION_OFFSET_MAX);
4642     } else {
4643         auto node = GetAccessibilityNodeFromPage(elementId);
4644         if (!node) {
4645             SetExecuteActionResult(callback, false, requestId);
4646             return;
4647         }
4648 
4649         actionResult =
4650             AccessibilityActionEvent(action, actionArguments, node, AceType::DynamicCast<PipelineContext>(context));
4651     }
4652     SetExecuteActionResult(callback, actionResult, requestId);
4653     if (actionResult && AceType::InstanceOf<PipelineContext>(context)) {
4654         SendActionEvent(action, elementId);
4655     }
4656 }
4657 
GetCursorPosition(const int64_t elementId,const int32_t requestId,AccessibilityElementOperatorCallback & callback)4658 void JsAccessibilityManager::JsInteractionOperation::GetCursorPosition(const int64_t elementId,
4659     const int32_t requestId, AccessibilityElementOperatorCallback &callback)
4660 {
4661     int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
4662     int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
4663     AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
4664 
4665     auto jsAccessibilityManager = GetHandler().Upgrade();
4666     CHECK_NULL_VOID(jsAccessibilityManager);
4667     auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
4668     CHECK_NULL_VOID(context);
4669     RefPtr<NG::FrameNode> node;
4670     auto ngPipeline = jsAccessibilityManager->FindPipelineByElementId(splitElementId, node);
4671     CHECK_NULL_VOID(ngPipeline);
4672 #ifdef WINDOW_SCENE_SUPPORTED
4673     auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
4674     CHECK_NULL_VOID(uiExtensionManager);
4675     if (uiExtensionManager->IsWrapExtensionAbilityId(splitElementId)) {
4676         auto unWrapIdPair = uiExtensionManager->UnWrapExtensionAbilityId(NG::UI_EXTENSION_OFFSET_MAX, elementId);
4677         int64_t uiExtensionId = unWrapIdPair.first;
4678         auto rootNode = ngPipeline->GetRootElement();
4679         CHECK_NULL_VOID(rootNode);
4680         auto uiExtensionNode = jsAccessibilityManager->FindNodeFromRootByExtensionId(rootNode, uiExtensionId);
4681         CHECK_NULL_VOID(uiExtensionNode);
4682         auto accessibilityProperty = uiExtensionNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
4683         CHECK_NULL_VOID(accessibilityProperty);
4684         auto callNumber = accessibilityProperty->ActActionGetIndex();
4685         callback.SetCursorPositionResult(callNumber, requestId);
4686         return;
4687     }
4688 #endif
4689     auto frameNode = GetFramenodeByAccessibilityId(ngPipeline->GetRootElement(), splitElementId);
4690     CHECK_NULL_VOID(frameNode);
4691     auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
4692     CHECK_NULL_VOID(accessibilityProperty);
4693     auto callNumber = accessibilityProperty->ActActionGetIndex();
4694     callback.SetCursorPositionResult(callNumber, requestId);
4695 }
4696 
ClearFocus()4697 void JsAccessibilityManager::JsInteractionOperation::ClearFocus()
4698 {
4699     auto jsAccessibilityManager = GetHandler().Upgrade();
4700     CHECK_NULL_VOID(jsAccessibilityManager);
4701     auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
4702     CHECK_NULL_VOID(context);
4703     context->GetTaskExecutor()->PostTask(
4704         [weak = GetHandler()] {
4705             auto jsAccessibilityManager = weak.Upgrade();
4706             CHECK_NULL_VOID(jsAccessibilityManager);
4707             ACE_SCOPED_TRACE("ClearCurrentFocus");
4708             jsAccessibilityManager->ClearCurrentFocus();
4709         },
4710         TaskExecutor::TaskType::UI, "ArkUIAccessibilityClearCurrentFocus");
4711 }
4712 
OutsideTouch()4713 void JsAccessibilityManager::JsInteractionOperation::OutsideTouch() {}
4714 #ifdef WEB_SUPPORTED
4715 
GetChildrenFromWebNode(int64_t nodeId,std::list<int64_t> & children,const RefPtr<NG::PipelineContext> & ngPipeline,const RefPtr<NG::WebPattern> & webPattern)4716 void GetChildrenFromWebNode(
4717     int64_t nodeId, std::list<int64_t>& children,
4718     const RefPtr<NG::PipelineContext>& ngPipeline, const RefPtr<NG::WebPattern>& webPattern)
4719 {
4720     std::list<int64_t> webNodeChildren;
4721     if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
4722         auto node = webPattern->GetAccessibilityNodeById(nodeId);
4723         CHECK_NULL_VOID(node);
4724     for (auto& childId : node->GetChildIds()) {
4725             webNodeChildren.emplace_back(childId);
4726         }
4727     }
4728     while (!webNodeChildren.empty()) {
4729         children.emplace_back(webNodeChildren.front());
4730         webNodeChildren.pop_front();
4731     }
4732 }
4733 
SearchWebElementInfoByAccessibilityId(const int64_t elementId,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t mode,const int32_t windowId,const RefPtr<NG::WebPattern> & webPattern)4734 void JsAccessibilityManager::SearchWebElementInfoByAccessibilityId(const int64_t elementId, const int32_t requestId,
4735     AccessibilityElementOperatorCallback& callback, const int32_t mode, const int32_t windowId,
4736     const RefPtr<NG::WebPattern>& webPattern)
4737 {
4738     std::list<AccessibilityElementInfo> infos;
4739 
4740     auto pipeline = GetPipelineByWindowId(windowId);
4741     CHECK_NULL_VOID(pipeline);
4742     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipeline);
4743     CHECK_NULL_VOID(ngPipeline);
4744 
4745     if (!ngPipeline->GetOnFoucs() && (SystemProperties::GetDeviceType() == DeviceType::TWO_IN_ONE)) {
4746         TAG_LOGD(AceLogTag::ACE_WEB,
4747             "SearchWebElementInfo GetOnFocus, elementId: %{public}" PRId64
4748             ", requestId: %{public}d, mode: %{public}d, windowId: %{public}d",
4749             elementId, requestId, mode, windowId);
4750         SetSearchElementInfoByAccessibilityIdResult(callback, std::move(infos), requestId);
4751         return;
4752     }
4753     CHECK_NULL_VOID(webPattern);
4754     auto webNode = webPattern->GetHost();
4755     bool webActive = webPattern->GetActiveStatus();
4756     if (!webActive) {
4757         TAG_LOGD(AceLogTag::ACE_WEB,
4758             "SearchWebElementinfo webActive false, elementId: %{public}" PRId64
4759             ", requestId: %{public}d, mode: %{public}d, windowId: %{public}d",
4760             elementId, requestId, mode, windowId);
4761         SetSearchElementInfoByAccessibilityIdResult(callback, std::move(infos), requestId);
4762         return;
4763     }
4764     if (!IsNodeInRoot(webNode, ngPipeline)) {
4765         TAG_LOGD(AceLogTag::ACE_WEB,
4766             "SearchWebElementInfo IsNodeInRoot, elementId: %{public}" PRId64
4767             ", requestId: %{public}d, mode: %{public}d, windowId: %{public}d",
4768             elementId, requestId, mode, windowId);
4769         SetSearchElementInfoByAccessibilityIdResult(callback, std::move(infos), requestId);
4770         return;
4771     }
4772 
4773     SearchWebElementInfoByAccessibilityIdNG(elementId, mode, infos, ngPipeline, webPattern);
4774     SetSearchElementInfoByAccessibilityIdResult(callback, std::move(infos), requestId);
4775 }
4776 
SearchWebElementInfoByAccessibilityIdNG(int64_t elementId,int32_t mode,std::list<AccessibilityElementInfo> & infos,const RefPtr<PipelineBase> & context,const RefPtr<NG::WebPattern> & webPattern)4777 void JsAccessibilityManager::SearchWebElementInfoByAccessibilityIdNG(int64_t elementId, int32_t mode,
4778     std::list<AccessibilityElementInfo>& infos, const RefPtr<PipelineBase>& context,
4779     const RefPtr<NG::WebPattern>& webPattern)
4780 {
4781     TAG_LOGD(AceLogTag::ACE_WEB, "elementId: %{public}" PRId64 ", treeId: %{public}d, mode: %{public}d",
4782         elementId, treeId_, mode);
4783     auto mainContext = context_.Upgrade();
4784     CHECK_NULL_VOID(mainContext);
4785 
4786     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
4787     CHECK_NULL_VOID(ngPipeline);
4788 
4789     AccessibilityElementInfo nodeInfo;
4790 
4791     CommonProperty commonProperty;
4792     GenerateCommonProperty(ngPipeline, commonProperty, mainContext);
4793 
4794     CHECK_NULL_VOID(webPattern);
4795     auto node = webPattern->GetAccessibilityNodeById(elementId);
4796     CHECK_NULL_VOID(node);
4797     UpdateWebAccessibilityElementInfo(node, commonProperty, nodeInfo, webPattern);
4798     nodeInfo.SetAccessibilityVisible(webPattern->GetAccessibilityVisible(elementId));
4799     infos.push_back(nodeInfo);
4800     SearchParameter param {elementId, "", mode, 0};
4801     UpdateWebCacheInfo(infos, elementId, commonProperty, ngPipeline, param, webPattern);
4802 }
4803 
FindWebFocusedElementInfo(const int64_t elementId,const int32_t focusType,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t windowId,const RefPtr<NG::WebPattern> & webPattern)4804 void JsAccessibilityManager::FindWebFocusedElementInfo(const int64_t elementId, const int32_t focusType,
4805     const int32_t requestId, AccessibilityElementOperatorCallback& callback, const int32_t windowId,
4806     const RefPtr<NG::WebPattern>& webPattern)
4807 {
4808     AccessibilityElementInfo nodeInfo;
4809     if (focusType != FOCUS_TYPE_INPUT && focusType != FOCUS_TYPE_ACCESSIBILITY) {
4810         nodeInfo.SetValidElement(false);
4811         SetFindFocusedElementInfoResult(callback, nodeInfo, requestId);
4812         return;
4813     }
4814 
4815     auto context = GetPipelineByWindowId(windowId);
4816     if (!context || AceType::InstanceOf<NG::PipelineContext>(context)) {
4817         nodeInfo.SetValidElement(false);
4818         SetFindFocusedElementInfoResult(callback, nodeInfo, requestId);
4819         return;
4820     }
4821 
4822     FindWebFocusedElementInfoNG(elementId, focusType, nodeInfo, context, webPattern);
4823     SetFindFocusedElementInfoResult(callback, nodeInfo, requestId);
4824 }
4825 
FindWebFocusedElementInfoNG(int64_t elementId,int32_t focusType,Accessibility::AccessibilityElementInfo & info,const RefPtr<PipelineBase> & context,const RefPtr<NG::WebPattern> & webPattern)4826 void JsAccessibilityManager::FindWebFocusedElementInfoNG(int64_t elementId, int32_t focusType,
4827     Accessibility::AccessibilityElementInfo& info, const RefPtr<PipelineBase>& context,
4828     const RefPtr<NG::WebPattern>& webPattern)
4829 {
4830     auto mainContext = context_.Upgrade();
4831     CHECK_NULL_VOID(mainContext);
4832     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
4833     CHECK_NULL_VOID(ngPipeline);
4834     auto node = webPattern->GetFocusedAccessibilityNode(elementId, focusType == FOCUS_TYPE_ACCESSIBILITY);
4835     if (!node) {
4836         info.SetValidElement(false);
4837         return;
4838     }
4839     CHECK_NULL_VOID(node);
4840     CommonProperty commonProperty;
4841     GenerateCommonProperty(ngPipeline, commonProperty, mainContext);
4842     UpdateWebAccessibilityElementInfo(node, commonProperty, info, webPattern);
4843 }
4844 
WebFocusMoveSearch(const int64_t elementId,const int32_t direction,const int32_t requestId,Accessibility::AccessibilityElementOperatorCallback & callback,const int32_t windowId,const RefPtr<NG::WebPattern> & webPattern)4845 void JsAccessibilityManager::WebFocusMoveSearch(const int64_t elementId, const int32_t direction,
4846     const int32_t requestId, Accessibility::AccessibilityElementOperatorCallback& callback, const int32_t windowId,
4847     const RefPtr<NG::WebPattern>& webPattern)
4848 {
4849     AccessibilityElementInfo nodeInfo;
4850     auto context = GetPipelineByWindowId(windowId);
4851     if (!context) {
4852         nodeInfo.SetValidElement(false);
4853         SetFocusMoveSearchResult(callback, nodeInfo, requestId);
4854         return;
4855     }
4856 
4857     WebFocusMoveSearchNG(elementId, direction, nodeInfo, context, webPattern);
4858     SetFocusMoveSearchResult(callback, nodeInfo, requestId);
4859 }
4860 
WebFocusMoveSearchNG(int64_t elementId,int32_t direction,AccessibilityElementInfo & info,const RefPtr<PipelineBase> & context,const RefPtr<NG::WebPattern> & webPattern)4861 void JsAccessibilityManager::WebFocusMoveSearchNG(int64_t elementId, int32_t direction,
4862     AccessibilityElementInfo& info, const RefPtr<PipelineBase>& context,
4863     const RefPtr<NG::WebPattern>& webPattern)
4864 {
4865     auto mainContext = context_.Upgrade();
4866     CHECK_NULL_VOID(mainContext);
4867     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
4868     CHECK_NULL_VOID(ngPipeline);
4869 
4870     auto node = webPattern->GetAccessibilityNodeByFocusMove(elementId, direction);
4871     if (!node) {
4872         info.SetValidElement(false);
4873         return;
4874     }
4875     CommonProperty commonProperty;
4876     GenerateCommonProperty(ngPipeline, commonProperty, mainContext);
4877     UpdateWebAccessibilityElementInfo(node, commonProperty, info, webPattern);
4878 }
4879 
ExecuteWebActionNG(int64_t elementId,ActionType action,const std::map<std::string,std::string> & actionArguments,const RefPtr<NG::WebPattern> & webPattern)4880 bool JsAccessibilityManager::ExecuteWebActionNG(int64_t elementId, ActionType action,
4881     const std::map<std::string, std::string>& actionArguments, const RefPtr<NG::WebPattern>& webPattern)
4882 {
4883     CHECK_NULL_RETURN(webPattern, false);
4884     return webPattern->ExecuteAction(elementId, ConvertAccessibilityAction(action), actionArguments);
4885 }
4886 
ExecuteWebAction(const int64_t elementId,const ActionParam & param,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t windowId,const RefPtr<NG::WebPattern> & webPattern)4887 void JsAccessibilityManager::ExecuteWebAction(const int64_t elementId, const ActionParam& param,
4888     const int32_t requestId, AccessibilityElementOperatorCallback& callback, const int32_t windowId,
4889     const RefPtr<NG::WebPattern>& webPattern)
4890 {
4891     auto action = param.action;
4892     auto actionArguments = param.actionArguments;
4893 
4894     bool actionResult = false;
4895     auto context = GetPipelineByWindowId(windowId);
4896     if (!context || !AceType::InstanceOf<NG::PipelineContext>(context)) {
4897         SetExecuteActionResult(callback, actionResult, requestId);
4898         return;
4899     }
4900 
4901     actionResult = ExecuteWebActionNG(elementId, action, actionArguments, webPattern);
4902     SetExecuteActionResult(callback, actionResult, requestId);
4903 }
4904 
RegisterWebInteractionOperationAsChildTree(int64_t accessibilityId,const WeakPtr<NG::WebPattern> & webPattern)4905 bool JsAccessibilityManager::RegisterWebInteractionOperationAsChildTree(int64_t accessibilityId,
4906     const WeakPtr<NG::WebPattern>& webPattern)
4907 {
4908     std::shared_ptr<AccessibilitySystemAbilityClient> instance = AccessibilitySystemAbilityClient::GetInstance();
4909     CHECK_NULL_RETURN(instance, false);
4910     auto pipelineContext = GetPipelineContext().Upgrade();
4911     CHECK_NULL_RETURN(pipelineContext, false);
4912     auto container = Platform::AceContainer::GetContainer(pipelineContext->GetInstanceId());
4913     if (container != nullptr && container->IsUIExtensionWindow()) {
4914         windowId_ = pipelineContext->GetRealHostWindowId();
4915     }
4916 
4917     AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(treeId_, accessibilityId);
4918 
4919     uint32_t windowId = GetWindowId();
4920     auto interactionOperation = std::make_shared<WebInteractionOperation>(windowId);
4921     interactionOperation->SetHandler(WeakClaim(this));
4922     interactionOperation->SetWebPattern(webPattern);
4923     auto pattern = webPattern.Upgrade();
4924     CHECK_NULL_RETURN(pattern, false);
4925     Accessibility::Registration registration {
4926         .windowId = windowId,
4927         .parentWindowId = windowId,
4928         .parentTreeId = treeId_,
4929         .elementId = accessibilityId,
4930     };
4931     parentWebWindowId_ = windowId;
4932     TAG_LOGI(AceLogTag::ACE_WEB, "windowId: %{public}u, parentWindowId: %{public}u, "
4933         "parentTreeId: %{public}d, elementId %{public}" PRId64,
4934         windowId, windowId, treeId_, accessibilityId);
4935     Accessibility::RetError retReg = instance->RegisterElementOperator(registration, interactionOperation);
4936     TAG_LOGI(AceLogTag::ACE_WEB, "RegisterWebInteractionOperationAsChildTree result: %{public}d", retReg);
4937     return retReg == RET_OK;
4938 }
4939 
DeregisterWebInteractionOperationAsChildTree(int32_t treeId)4940 bool JsAccessibilityManager::DeregisterWebInteractionOperationAsChildTree(int32_t treeId)
4941 {
4942     std::shared_ptr<AccessibilitySystemAbilityClient> instance = AccessibilitySystemAbilityClient::GetInstance();
4943     CHECK_NULL_RETURN(instance, false);
4944     uint32_t windowId = GetWindowId();
4945     Accessibility::RetError retReg = instance->DeregisterElementOperator(windowId, treeId);
4946     return retReg == RET_OK;
4947 }
4948 
UpdateWebCacheInfo(std::list<AccessibilityElementInfo> & infos,int64_t nodeId,const CommonProperty & commonProperty,const RefPtr<NG::PipelineContext> & ngPipeline,const SearchParameter & searchParam,const RefPtr<NG::WebPattern> & webPattern)4949 void JsAccessibilityManager::UpdateWebCacheInfo(std::list<AccessibilityElementInfo>& infos,
4950     int64_t nodeId, const CommonProperty& commonProperty, const RefPtr<NG::PipelineContext>& ngPipeline,
4951     const SearchParameter& searchParam, const RefPtr<NG::WebPattern>& webPattern)
4952 {
4953     uint32_t umode = searchParam.mode;
4954     std::list<int64_t> children;
4955     // get all children
4956     if (!(umode & static_cast<uint32_t>(PREFETCH_RECURSIVE_CHILDREN))) {
4957         return;
4958     }
4959     GetChildrenFromWebNode(nodeId, children, ngPipeline, webPattern);
4960     while (!children.empty()) {
4961         int64_t parent = children.front();
4962         children.pop_front();
4963         AccessibilityElementInfo nodeInfo;
4964 
4965         GetChildrenFromWebNode(parent, children, ngPipeline, webPattern);
4966         auto node = webPattern->GetAccessibilityNodeById(parent);
4967         if (node) {
4968             UpdateWebAccessibilityElementInfo(node, commonProperty, nodeInfo, webPattern);
4969             infos.push_back(nodeInfo);
4970         }
4971     }
4972 }
4973 #endif //WEB_SUPPORTED
4974 
RegisterInteractionOperationAsChildTree(const Registration & registration)4975 bool JsAccessibilityManager::RegisterInteractionOperationAsChildTree(
4976     const Registration& registration)
4977 {
4978     bool ret = false;
4979     switch (registration.operatorType) {
4980         case OperatorType::JS_THIRD_PROVIDER:
4981             ret = RegisterThirdProviderInteractionOperationAsChildTree(registration);
4982             break;
4983         default:
4984             TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY,
4985                 "RegisterInteractionOperationAsChildTree operatorType: %{public}d",
4986                 static_cast<int32_t>(registration.operatorType));
4987     }
4988     return ret;
4989 }
4990 
RegisterThirdProviderInteractionOperationAsChildTree(const Registration & registration)4991 bool JsAccessibilityManager::RegisterThirdProviderInteractionOperationAsChildTree(
4992     const Registration& registration)
4993 {
4994     std::shared_ptr<AccessibilitySystemAbilityClient> instance =
4995         AccessibilitySystemAbilityClient::GetInstance();
4996     CHECK_NULL_RETURN(instance, false);
4997     Accessibility::Registration innerRegistration {
4998         .windowId = registration.windowId,
4999         .parentWindowId = registration.parentWindowId,
5000         .parentTreeId = registration.parentTreeId,
5001         .elementId = registration.elementId,
5002     };
5003 
5004     auto provider = registration.accessibilityProvider.Upgrade();
5005     CHECK_NULL_RETURN(provider, false);
5006     auto interactionOperation = std::make_shared<JsThirdProviderInteractionOperation>(
5007         registration.accessibilityProvider, WeakClaim(this), registration.hostNode);
5008     provider->SendThirdAccessibilityProvider(interactionOperation);
5009     interactionOperation->Initialize();
5010     RegisterJsThirdProviderInteractionOperation(registration.elementId,
5011         interactionOperation);
5012     Accessibility::RetError retReg = instance->RegisterElementOperator(
5013         innerRegistration, interactionOperation);
5014     TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY,
5015         "RegisterWebInteractionOperationAsChildTree result: %{public}d", retReg);
5016     return retReg == RET_OK;
5017 }
5018 
DeregisterInteractionOperationAsChildTree(uint32_t windowId,int32_t treeId)5019 bool JsAccessibilityManager::DeregisterInteractionOperationAsChildTree(
5020     uint32_t windowId, int32_t treeId)
5021 {
5022     std::shared_ptr<AccessibilitySystemAbilityClient> instance =
5023         AccessibilitySystemAbilityClient::GetInstance();
5024     CHECK_NULL_RETURN(instance, false);
5025     Accessibility::RetError retReg = instance->DeregisterElementOperator(windowId, treeId);
5026     return retReg == RET_OK;
5027 }
5028 
RegisterInteractionOperation(int windowId)5029 int JsAccessibilityManager::RegisterInteractionOperation(int windowId)
5030 {
5031     if (IsRegister()) {
5032         return 0;
5033     }
5034 
5035     std::shared_ptr<AccessibilitySystemAbilityClient> instance = AccessibilitySystemAbilityClient::GetInstance();
5036     CHECK_NULL_RETURN(instance, -1);
5037     auto interactionOperation = std::make_shared<JsInteractionOperation>(windowId);
5038     interactionOperation->SetHandler(WeakClaim(this));
5039     Accessibility::RetError retReg = instance->RegisterElementOperator(windowId, interactionOperation);
5040     RefPtr<PipelineBase> context;
5041     for (auto subContext : GetSubPipelineContexts()) {
5042         context = subContext.Upgrade();
5043         CHECK_NULL_RETURN(context, -1);
5044         interactionOperation = std::make_shared<JsInteractionOperation>(context->GetWindowId());
5045         interactionOperation->SetHandler(WeakClaim(this));
5046         auto retResult = instance->RegisterElementOperator(context->GetWindowId(), interactionOperation);
5047         retReg = retResult == RET_OK ? retReg : retResult;
5048     }
5049     Register(retReg == RET_OK);
5050     if (retReg == RET_OK) {
5051         NotifyChildTreeOnRegister(treeId_);
5052     }
5053 
5054     return retReg;
5055 }
5056 
RegisterSubWindowInteractionOperation(int windowId)5057 void JsAccessibilityManager::RegisterSubWindowInteractionOperation(int windowId)
5058 {
5059     if (!AceApplicationInfo::GetInstance().IsAccessibilityEnabled() || !IsRegister()) {
5060         return;
5061     }
5062 
5063     std::shared_ptr<AccessibilitySystemAbilityClient> instance = AccessibilitySystemAbilityClient::GetInstance();
5064     CHECK_NULL_VOID(instance);
5065     auto interactionOperation = std::make_shared<JsInteractionOperation>(windowId);
5066     interactionOperation->SetHandler(WeakClaim(this));
5067     instance->RegisterElementOperator(windowId, interactionOperation);
5068 }
5069 
DeregisterInteractionOperation()5070 void JsAccessibilityManager::DeregisterInteractionOperation()
5071 {
5072     if (!IsRegister()) {
5073         return;
5074     }
5075     int windowId = static_cast<int>(GetWindowId());
5076 
5077     auto instance = AccessibilitySystemAbilityClient::GetInstance();
5078     CHECK_NULL_VOID(instance);
5079     Register(false);
5080     if (currentFocusNodeId_ != -1 && lastElementId_ != -1) {
5081         auto focusNode = lastFrameNode_.Upgrade();
5082         if (focusNode != nullptr) {
5083             focusNode->GetRenderContext()->UpdateAccessibilityFocus(false);
5084         }
5085     }
5086     lastFrameNode_.Reset();
5087     lastElementId_ = -1;
5088     currentFocusNodeId_ = -1;
5089     if (parentWindowId_ == 0) {
5090         instance->DeregisterElementOperator(windowId);
5091     } else {
5092         instance->DeregisterElementOperator(windowId, treeId_);
5093         parentElementId_ = INVALID_PARENT_ID;
5094         parentTreeId_ = 0;
5095         parentWindowId_ = 0;
5096     }
5097 
5098     RefPtr<PipelineBase> context;
5099     for (auto subContext : GetSubPipelineContexts()) {
5100         context = subContext.Upgrade();
5101         CHECK_NULL_VOID(context);
5102         instance->DeregisterElementOperator(context->GetWindowId());
5103     }
5104     NotifyChildTreeOnDeregister();
5105 }
5106 
RegisterAccessibilityChildTreeCallback(int64_t elementId,const std::shared_ptr<AccessibilityChildTreeCallback> & callback)5107 void JsAccessibilityManager::RegisterAccessibilityChildTreeCallback(
5108     int64_t elementId, const std::shared_ptr<AccessibilityChildTreeCallback> &callback)
5109 {
5110     std::lock_guard<std::mutex> lock(childTreeCallbackMapMutex_);
5111     childTreeCallbackMap_[elementId] = callback;
5112 }
5113 
DeregisterAccessibilityChildTreeCallback(int64_t elementId)5114 void JsAccessibilityManager::DeregisterAccessibilityChildTreeCallback(int64_t elementId)
5115 {
5116     std::lock_guard<std::mutex> lock(childTreeCallbackMapMutex_);
5117     childTreeCallbackMap_.erase(elementId);
5118 }
5119 
RegisterAccessibilitySAObserverCallback(int64_t elementId,const std::shared_ptr<AccessibilitySAObserverCallback> & callback)5120 void JsAccessibilityManager::RegisterAccessibilitySAObserverCallback(
5121     int64_t elementId, const std::shared_ptr<AccessibilitySAObserverCallback> &callback)
5122 {
5123     std::lock_guard<std::mutex> lock(componentSACallbackMutex_);
5124     componentSACallbackMap_[elementId] = callback;
5125 }
5126 
DeregisterAccessibilitySAObserverCallback(int64_t elementId)5127 void JsAccessibilityManager::DeregisterAccessibilitySAObserverCallback(int64_t elementId)
5128 {
5129     std::lock_guard<std::mutex> lock(componentSACallbackMutex_);
5130     componentSACallbackMap_.erase(elementId);
5131 }
5132 
NotifyAccessibilitySAStateChange(bool state)5133 void JsAccessibilityManager::NotifyAccessibilitySAStateChange(bool state)
5134 {
5135     std::lock_guard<std::mutex> lock(componentSACallbackMutex_);
5136     for (auto &item : componentSACallbackMap_) {
5137         if (item.second == nullptr) {
5138             continue;
5139         }
5140         item.second->OnState(state);
5141     }
5142 }
5143 
NotifyChildTreeOnRegister(int32_t treeId)5144 void JsAccessibilityManager::NotifyChildTreeOnRegister(int32_t treeId)
5145 {
5146     TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "NotifyChildTreeOnRegister size: %{public}zu", childTreeCallbackMap_.size());
5147     std::lock_guard<std::mutex> lock(childTreeCallbackMapMutex_);
5148     for (auto &item : childTreeCallbackMap_) {
5149         if (item.second == nullptr) {
5150             continue;
5151         }
5152         item.second->OnRegister(GetWindowId(), treeId);
5153     }
5154 }
5155 
NotifyChildTreeOnDeregister()5156 void JsAccessibilityManager::NotifyChildTreeOnDeregister()
5157 {
5158     TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "NotifyChildTreeOnDeregister size: %{public}zu",
5159         childTreeCallbackMap_.size());
5160     std::lock_guard<std::mutex> lock(childTreeCallbackMapMutex_);
5161     for (auto &item : childTreeCallbackMap_) {
5162         if (item.second == nullptr) {
5163             continue;
5164         }
5165         item.second->OnDeregister();
5166     }
5167 }
5168 
NotifySetChildTreeIdAndWinId(int64_t elementId,const int32_t treeId,const int32_t childWindowId)5169 void JsAccessibilityManager::NotifySetChildTreeIdAndWinId(
5170     int64_t elementId, const int32_t treeId, const int32_t childWindowId)
5171 {
5172     std::lock_guard<std::mutex> lock(childTreeCallbackMapMutex_);
5173     auto findResult = childTreeCallbackMap_.find(elementId);
5174     if (findResult == childTreeCallbackMap_.end()) {
5175         TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "node: %{public}" PRId64 " not found, treeId: %{public}d", elementId,
5176             treeId);
5177         return;
5178     }
5179     auto callback = findResult->second;
5180     CHECK_NULL_VOID(callback);
5181     callback->SetChildTreeId(treeId);
5182     callback->OnSetChildTree(childWindowId, treeId);
5183 }
5184 
CheckIsChildElement(int64_t & elementId,const std::vector<std::string> & params,std::vector<std::string> & info)5185 bool JsAccessibilityManager::CheckIsChildElement(
5186     int64_t &elementId, const std::vector<std::string> &params, std::vector<std::string> &info)
5187 {
5188     if (elementId <= 0) {
5189         return false;
5190     }
5191 
5192     int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
5193     int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
5194     AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
5195     if (splitTreeId <= 0 || splitTreeId == treeId_) {
5196         elementId = splitElementId;
5197         return false;
5198     }
5199     std::lock_guard<std::mutex> lock(childTreeCallbackMapMutex_);
5200     for (const auto &item : childTreeCallbackMap_) {
5201         if (item.second == nullptr) {
5202             continue;
5203         }
5204         if (item.second->GetChildTreeId() != splitTreeId) {
5205             continue;
5206         }
5207         item.second->OnDumpChildInfo(params, info);
5208         for (const auto &childInfo : info) {
5209             DumpLog::GetInstance().Print(childInfo.c_str());
5210         }
5211         return true;
5212     }
5213     return false;
5214 }
5215 
NeedRegisterChildTree(uint32_t parentWindowId,int32_t parentTreeId,int64_t parentElementId)5216 bool JsAccessibilityManager::NeedRegisterChildTree(
5217     uint32_t parentWindowId, int32_t parentTreeId, int64_t parentElementId)
5218 {
5219     if (!IsRegister()) {
5220         return true;
5221     }
5222 
5223     if (parentWindowId_ == parentWindowId && parentTreeId_ == parentTreeId && parentElementId_ == parentElementId) {
5224         return false;
5225     }
5226     DeregisterInteractionOperationAsChildTree();
5227     return true;
5228 }
5229 
RegisterInteractionOperationAsChildTree(uint32_t parentWindowId,int32_t parentTreeId,int64_t parentElementId)5230 void JsAccessibilityManager::RegisterInteractionOperationAsChildTree(
5231     uint32_t parentWindowId, int32_t parentTreeId, int64_t parentElementId)
5232 {
5233     AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(parentTreeId, parentElementId);
5234     if (!NeedRegisterChildTree(parentWindowId, parentTreeId, parentElementId)) {
5235         return;
5236     }
5237 
5238     std::shared_ptr<AccessibilitySystemAbilityClient> instance = AccessibilitySystemAbilityClient::GetInstance();
5239     CHECK_NULL_VOID(instance);
5240     auto pipelineContext = GetPipelineContext().Upgrade();
5241     CHECK_NULL_VOID(pipelineContext);
5242     auto container = Platform::AceContainer::GetContainer(pipelineContext->GetInstanceId());
5243     if (container != nullptr && container->IsUIExtensionWindow()) {
5244         windowId_ = pipelineContext->GetRealHostWindowId();
5245     } else if (pipelineContext->IsFormRender()) {
5246         windowId_ = parentWindowId;
5247     }
5248 
5249     uint32_t windowId = GetWindowId();
5250     auto interactionOperation = std::make_shared<JsInteractionOperation>(windowId);
5251     interactionOperation->SetHandler(WeakClaim(this));
5252     Accessibility::Registration registration {
5253         .windowId = windowId,
5254         .parentWindowId = parentWindowId,
5255         .parentTreeId = parentTreeId,
5256         .elementId = parentElementId,
5257     };
5258     TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "windowId: %{public}u, parentWindowId: %{public}u, "
5259                                            "parentTreeId: %{public}d, %{public}" PRId64,
5260                                            windowId, parentWindowId, parentTreeId, parentElementId);
5261     Accessibility::RetError retReg = instance->RegisterElementOperator(registration, interactionOperation);
5262     TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "RegisterElementOperator result: %{public}d", retReg);
5263     Register(retReg == RET_OK);
5264     AceApplicationInfo::GetInstance().SetAccessibilityEnabled(retReg == RET_OK);
5265     parentElementId_ = parentElementId;
5266     parentTreeId_ = parentTreeId;
5267     parentWindowId_ = parentWindowId;
5268 
5269     for (auto subContext : GetSubPipelineContexts()) {
5270         auto context = subContext.Upgrade();
5271         CHECK_NULL_VOID(context);
5272         interactionOperation = std::make_shared<JsInteractionOperation>(context->GetWindowId());
5273         interactionOperation->SetHandler(WeakClaim(this));
5274         instance->RegisterElementOperator(context->GetWindowId(), interactionOperation);
5275     }
5276 }
5277 
SetAccessibilityGetParentRectHandler(std::function<void (int32_t &,int32_t &)> && callback)5278 void JsAccessibilityManager::SetAccessibilityGetParentRectHandler(std::function<void(int32_t &, int32_t &)> &&callback)
5279 {
5280     getParentRectHandler_ = std::move(callback);
5281 }
5282 
DeregisterInteractionOperationAsChildTree()5283 void JsAccessibilityManager::DeregisterInteractionOperationAsChildTree()
5284 {
5285     if (!IsRegister()) {
5286         return;
5287     }
5288     TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "deregister accessibility childTree");
5289 
5290     std::shared_ptr<AccessibilitySystemAbilityClient> instance = AccessibilitySystemAbilityClient::GetInstance();
5291     CHECK_NULL_VOID(instance);
5292     uint32_t windowId = GetWindowId();
5293     Register(false);
5294     currentFocusNodeId_ = -1;
5295     instance->DeregisterElementOperator(windowId, treeId_);
5296     AceApplicationInfo::GetInstance().SetAccessibilityEnabled(false);
5297     parentElementId_ = INVALID_PARENT_ID;
5298     parentTreeId_ = 0;
5299     parentWindowId_ = 0;
5300     NotifyChildTreeOnDeregister();
5301 
5302     RefPtr<PipelineBase> context;
5303     for (auto subContext : GetSubPipelineContexts()) {
5304         context = subContext.Upgrade();
5305         CHECK_NULL_VOID(context);
5306         instance->DeregisterElementOperator(context->GetWindowId());
5307     }
5308 }
5309 
SendUecOnTreeEvent(int64_t splitElementId)5310 void JsAccessibilityManager::SendUecOnTreeEvent(int64_t splitElementId)
5311 {
5312     auto context = GetPipelineContext().Upgrade();
5313     CHECK_NULL_VOID(context);
5314     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
5315     CHECK_NULL_VOID(ngPipeline);
5316     auto rootNode = ngPipeline->GetRootElement();
5317     CHECK_NULL_VOID(rootNode);
5318     auto frameNode = GetFramenodeByAccessibilityId(rootNode, splitElementId);
5319     CHECK_NULL_VOID(frameNode);
5320 
5321     if ((!frameNode) || (IsExtensionComponent(frameNode) && !IsUIExtensionShowPlaceholder(frameNode))) {
5322         TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "Register element is uec: %{public}s ", frameNode->GetTag().c_str());
5323         rootNode->OnAccessibilityEvent(AccessibilityEventType::CHANGE);
5324     } else {
5325         TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "Register element is not uec: %{public}s", frameNode->GetTag().c_str());
5326     }
5327 }
SetChildTreeIdAndWinId(const int64_t nodeId,const int32_t treeId,const int32_t childWindowId)5328 void JsAccessibilityManager::JsInteractionOperation::SetChildTreeIdAndWinId(
5329     const int64_t nodeId, const int32_t treeId, const int32_t childWindowId)
5330 {
5331     int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
5332     int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
5333     AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(nodeId, splitElementId, splitTreeId);
5334     TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "SetChildTreeId node: %{public}" PRId64 " treeId: %{public}d",
5335         splitElementId, treeId);
5336     auto jsAccessibilityManager = GetHandler().Upgrade();
5337     CHECK_NULL_VOID(jsAccessibilityManager);
5338     jsAccessibilityManager->NotifySetChildTreeIdAndWinId(splitElementId, treeId, childWindowId);
5339 }
5340 
SetBelongTreeId(const int32_t treeId)5341 void JsAccessibilityManager::JsInteractionOperation::SetBelongTreeId(const int32_t treeId)
5342 {
5343     TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "SetBelongTreeId treeId: %{public}d", treeId);
5344     auto jsAccessibilityManager = GetHandler().Upgrade();
5345     CHECK_NULL_VOID(jsAccessibilityManager);
5346     jsAccessibilityManager->treeId_ = treeId;
5347     auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
5348     CHECK_NULL_VOID(context);
5349     context->GetTaskExecutor()->PostTask(
5350         [weak = GetHandler(), treeId] {
5351             auto jsAccessibilityManager = weak.Upgrade();
5352             CHECK_NULL_VOID(jsAccessibilityManager);
5353             ACE_SCOPED_TRACE("SetBelongTreeId");
5354             jsAccessibilityManager->NotifyChildTreeOnRegister(treeId);
5355         },
5356         TaskExecutor::TaskType::UI, "ArkUIAccessibilityClearCurrentFocus");
5357 }
5358 
UpdateElementInfoTreeId(Accessibility::AccessibilityElementInfo & info)5359 void JsAccessibilityManager::UpdateElementInfoTreeId(Accessibility::AccessibilityElementInfo& info)
5360 {
5361     int32_t treeId = info.GetBelongTreeId();
5362     if (treeId <= 0) {
5363         return;
5364     }
5365 
5366     int64_t elementId = info.GetAccessibilityId();
5367     AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(treeId, elementId);
5368     info.SetAccessibilityId(elementId);
5369 
5370     int64_t parentId = info.GetParentNodeId();
5371     if (parentId != INVALID_PARENT_ID) {
5372         AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(treeId, parentId);
5373         info.SetParent(parentId);
5374     }
5375 
5376     UpdateElementInfoPageIdWithTreeId(info, treeId);
5377 
5378     std::vector<int64_t> childIds = info.GetChildIds();
5379     for (int64_t child : childIds) {
5380         info.RemoveChild(child);
5381         AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(treeId, child);
5382         info.AddChild(child);
5383     }
5384 }
5385 
UpdateElementInfosTreeId(std::list<Accessibility::AccessibilityElementInfo> & infos)5386 void JsAccessibilityManager::UpdateElementInfosTreeId(std::list<Accessibility::AccessibilityElementInfo>& infos)
5387 {
5388     for (auto &item : infos) {
5389         int32_t treeId = item.GetBelongTreeId();
5390         if (treeId <= 0) {
5391             continue;
5392         }
5393 
5394         int64_t elementId = item.GetAccessibilityId();
5395         AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(treeId, elementId);
5396         item.SetAccessibilityId(elementId);
5397 
5398         int64_t parentId = item.GetParentNodeId();
5399         if (parentId != INVALID_PARENT_ID) {
5400             AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(treeId, parentId);
5401             item.SetParent(parentId);
5402         }
5403 
5404         UpdateElementInfoPageIdWithTreeId(item, treeId);
5405 
5406         std::vector<int64_t> childIds = item.GetChildIds();
5407         for (int64_t child : childIds) {
5408             item.RemoveChild(child);
5409             AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(treeId, child);
5410             item.AddChild(child);
5411         }
5412     }
5413 }
5414 
SetPipelineContext(const RefPtr<PipelineBase> & context)5415 void JsAccessibilityManager::SetPipelineContext(const RefPtr<PipelineBase>& context)
5416 {
5417     context_ = context;
5418     if (stateObserver_ != nullptr) {
5419         stateObserver_->SetPipeline(context_);
5420     }
5421 }
5422 
OnStateChanged(const bool state)5423 void JsAccessibilityManager::JsAccessibilityStateObserver::OnStateChanged(const bool state)
5424 {
5425     TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "accessibility state changed:%{public}d", state);
5426     // Do not upgrade jsAccessibilityManager on async thread, destructor will cause freeze
5427     auto pipelineRef = pipeline_.Upgrade();
5428     CHECK_NULL_VOID(pipelineRef);
5429     pipelineRef->GetTaskExecutor()->PostTask(
5430         [weak = accessibilityManager_, state]() {
5431             auto jsAccessibilityManager = weak.Upgrade();
5432             CHECK_NULL_VOID(jsAccessibilityManager);
5433             if (state) {
5434                 jsAccessibilityManager->RegisterInteractionOperation(jsAccessibilityManager->GetWindowId());
5435             } else {
5436                 jsAccessibilityManager->DeregisterInteractionOperation();
5437             }
5438             AceApplicationInfo::GetInstance().SetAccessibilityEnabled(state);
5439             jsAccessibilityManager->NotifyAccessibilitySAStateChange(state);
5440         },
5441         TaskExecutor::TaskType::UI, "ArkUIAccessibilityStateChanged");
5442 }
5443 
FocusMoveSearch(int64_t elementId,const int32_t direction,const int32_t requestId,AccessibilityElementOperatorCallback & callback)5444 void JsAccessibilityManager::JsInteractionOperation::FocusMoveSearch(
5445     int64_t elementId, const int32_t direction, const int32_t requestId, AccessibilityElementOperatorCallback& callback)
5446 {
5447     TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "move search: %{public}" PRId64 ", direction: %{public}d",
5448         elementId, direction);
5449     int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
5450     int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
5451     AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
5452 
5453     auto jsAccessibilityManager = GetHandler().Upgrade();
5454     CHECK_NULL_VOID(jsAccessibilityManager);
5455     auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
5456     CHECK_NULL_VOID(context);
5457     auto windowId = windowId_;
5458     context->GetTaskExecutor()->PostTask(
5459         [weak = GetHandler(), splitElementId, direction, requestId, &callback, windowId] {
5460             auto jsAccessibilityManager = weak.Upgrade();
5461             CHECK_NULL_VOID(jsAccessibilityManager);
5462             ACE_SCOPED_TRACE("FocusMoveSearch");
5463             jsAccessibilityManager->FocusMoveSearch(splitElementId, direction, requestId, callback, windowId);
5464         },
5465         TaskExecutor::TaskType::UI, "ArkUIAccessibilityFocusMoveSearch");
5466 }
5467 
FocusMoveSearch(const int64_t elementId,const int32_t direction,const int32_t requestId,Accessibility::AccessibilityElementOperatorCallback & callback,const int32_t windowId)5468 void JsAccessibilityManager::FocusMoveSearch(const int64_t elementId, const int32_t direction, const int32_t requestId,
5469     Accessibility::AccessibilityElementOperatorCallback& callback, const int32_t windowId)
5470 {
5471     AccessibilityElementInfo nodeInfo;
5472     auto context = GetPipelineByWindowId(windowId);
5473     if (!context) {
5474         nodeInfo.SetValidElement(false);
5475         SetFocusMoveSearchResult(callback, nodeInfo, requestId);
5476         return;
5477     }
5478 
5479     if (AceType::InstanceOf<NG::PipelineContext>(context)) {
5480         FocusMoveSearchNG(elementId, direction, nodeInfo, context, NG::UI_EXTENSION_OFFSET_MAX);
5481         SetFocusMoveSearchResult(callback, nodeInfo, requestId);
5482         return;
5483     }
5484 
5485     auto node = GetAccessibilityNodeFromPage(elementId);
5486     if (!node) {
5487         nodeInfo.SetValidElement(false);
5488         SetFocusMoveSearchResult(callback, nodeInfo, requestId);
5489         return;
5490     }
5491 
5492     // get root node.
5493     auto rootNode = node;
5494     while (rootNode->GetParentNode()) {
5495         rootNode = rootNode->GetParentNode();
5496         if (!rootNode->GetParentNode()) {
5497             break;
5498         }
5499     }
5500 
5501     std::list<RefPtr<AccessibilityNode>> nodeList;
5502     AddFocusableNode(nodeList, rootNode);
5503     RefPtr<AccessibilityNode> resultNode;
5504 
5505     switch (direction) {
5506         case FocusMoveDirection::FORWARD:
5507         case FocusMoveDirection::BACKWARD:
5508             // forward and backward
5509             resultNode = FindNodeInRelativeDirection(nodeList, node, direction);
5510             break;
5511         case FocusMoveDirection::UP:
5512         case FocusMoveDirection::DOWN:
5513         case FocusMoveDirection::LEFT:
5514         case FocusMoveDirection::RIGHT:
5515             // up, down, left and right
5516             resultNode = FindNodeInAbsoluteDirection(nodeList, node, direction);
5517             break;
5518         default:
5519             break;
5520     }
5521 
5522     if (resultNode) {
5523         auto jsAccessibilityManager = Claim(this);
5524         UpdateAccessibilityNodeInfo(resultNode, nodeInfo, jsAccessibilityManager, windowId_);
5525     }
5526 
5527     SetFocusMoveSearchResult(callback, nodeInfo, requestId);
5528 }
5529 
AddFocusableNode(std::list<RefPtr<AccessibilityNode>> & nodeList,const RefPtr<AccessibilityNode> & node)5530 void JsAccessibilityManager::AddFocusableNode(
5531     std::list<RefPtr<AccessibilityNode>>& nodeList, const RefPtr<AccessibilityNode>& node)
5532 {
5533     const std::string importance = node->GetImportantForAccessibility();
5534     if (CanAccessibilityFocused(node)) {
5535         nodeList.push_back(node);
5536     }
5537     if (!node->GetAccessible() && importance != "no-hide-descendants") {
5538         for (auto& child : node->GetChildList()) {
5539             AddFocusableNode(nodeList, child);
5540         }
5541     }
5542 }
5543 
CanAccessibilityFocused(const RefPtr<AccessibilityNode> & node)5544 bool JsAccessibilityManager::CanAccessibilityFocused(const RefPtr<AccessibilityNode>& node)
5545 {
5546     return node != nullptr && !node->IsRootNode() && node->GetVisible() &&
5547            node->GetImportantForAccessibility() != "no" &&
5548            node->GetImportantForAccessibility() != "no-hide-descendants";
5549 }
5550 
FindNodeInRelativeDirection(const std::list<RefPtr<AccessibilityNode>> & nodeList,RefPtr<AccessibilityNode> & node,const int direction)5551 RefPtr<AccessibilityNode> JsAccessibilityManager::FindNodeInRelativeDirection(
5552     const std::list<RefPtr<AccessibilityNode>>& nodeList, RefPtr<AccessibilityNode>& node, const int direction)
5553 {
5554     switch (direction) {
5555         case FocusMoveDirection::FORWARD:
5556             return GetNextFocusableNode(nodeList, node);
5557         case FocusMoveDirection::BACKWARD:
5558             return GetPreviousFocusableNode(nodeList, node);
5559         default:
5560             break;
5561     }
5562 
5563     return nullptr;
5564 }
5565 
FindNodeInAbsoluteDirection(const std::list<RefPtr<AccessibilityNode>> & nodeList,RefPtr<AccessibilityNode> & node,const int direction)5566 RefPtr<AccessibilityNode> JsAccessibilityManager::FindNodeInAbsoluteDirection(
5567     const std::list<RefPtr<AccessibilityNode>>& nodeList, RefPtr<AccessibilityNode>& node, const int direction)
5568 {
5569     auto tempBest = node->GetRect();
5570     auto nodeRect = node->GetRect();
5571 
5572     switch (direction) {
5573         case FocusMoveDirection::LEFT:
5574             tempBest.SetLeft(node->GetLeft() + node->GetWidth() + 1);
5575             break;
5576         case FocusMoveDirection::RIGHT:
5577             tempBest.SetLeft(node->GetLeft() - node->GetWidth() - 1);
5578             break;
5579         case FocusMoveDirection::UP:
5580             tempBest.SetTop(node->GetTop() + node->GetHeight() + 1);
5581             break;
5582         case FocusMoveDirection::DOWN:
5583             tempBest.SetTop(node->GetTop() - node->GetHeight() - 1);
5584             break;
5585         default:
5586             break;
5587     }
5588 
5589     RefPtr<AccessibilityNode> nearestNode = nullptr;
5590     for (auto nodeItem = nodeList.begin(); nodeItem != nodeList.end(); nodeItem++) {
5591         if ((*nodeItem)->GetNodeId() == node->GetNodeId() || (*nodeItem)->IsRootNode()) {
5592             continue;
5593         }
5594         auto itemRect = (*nodeItem)->GetRect();
5595         if (CheckBetterRect(nodeRect, direction, itemRect, tempBest)) {
5596             tempBest = itemRect;
5597             nearestNode = (*nodeItem);
5598         }
5599     }
5600 
5601     return nearestNode;
5602 }
5603 
GetNextFocusableNode(const std::list<RefPtr<AccessibilityNode>> & nodeList,RefPtr<AccessibilityNode> & node)5604 RefPtr<AccessibilityNode> JsAccessibilityManager::GetNextFocusableNode(
5605     const std::list<RefPtr<AccessibilityNode>>& nodeList, RefPtr<AccessibilityNode>& node)
5606 {
5607     auto nodeItem = nodeList.begin();
5608     for (; nodeItem != nodeList.end(); nodeItem++) {
5609         if ((*nodeItem)->GetNodeId() == node->GetNodeId()) {
5610             break;
5611         }
5612     }
5613 
5614     if (nodeItem != nodeList.end() && ++nodeItem != nodeList.end()) {
5615         return (*nodeItem);
5616     }
5617     if (!nodeList.empty()) {
5618         return (*nodeList.begin());
5619     }
5620 
5621     return nullptr;
5622 }
5623 
GetPreviousFocusableNode(const std::list<RefPtr<AccessibilityNode>> & nodeList,RefPtr<AccessibilityNode> & node)5624 RefPtr<AccessibilityNode> JsAccessibilityManager::GetPreviousFocusableNode(
5625     const std::list<RefPtr<AccessibilityNode>>& nodeList, RefPtr<AccessibilityNode>& node)
5626 {
5627     auto nodeItem = nodeList.rbegin();
5628     for (; nodeItem != nodeList.rend(); nodeItem++) {
5629         if ((*nodeItem)->GetNodeId() == node->GetNodeId()) {
5630             break;
5631         }
5632     }
5633 
5634     if (nodeItem != nodeList.rend() && ++nodeItem != nodeList.rend()) {
5635         return (*nodeItem);
5636     }
5637 
5638     if (!nodeList.empty()) {
5639         return (*nodeList.rbegin());
5640     }
5641     return nullptr;
5642 }
5643 
RequestAccessibilityFocus(const RefPtr<AccessibilityNode> & node)5644 bool JsAccessibilityManager::RequestAccessibilityFocus(const RefPtr<AccessibilityNode>& node)
5645 {
5646     auto requestNodeId = node->GetNodeId();
5647     if (currentFocusNodeId_ == requestNodeId) {
5648         return false;
5649     }
5650 
5651     ClearCurrentFocus();
5652     currentFocusNodeId_ = requestNodeId;
5653     node->SetAccessibilityFocusedState(true);
5654     return node->ActionAccessibilityFocus(true);
5655 }
5656 
ClearAccessibilityFocus(const RefPtr<AccessibilityNode> & node)5657 bool JsAccessibilityManager::ClearAccessibilityFocus(const RefPtr<AccessibilityNode>& node)
5658 {
5659     auto requestNodeId = node->GetNodeId();
5660     if (currentFocusNodeId_ != requestNodeId) {
5661         return false;
5662     }
5663 
5664     currentFocusNodeId_ = -1;
5665     node->SetAccessibilityFocusedState(false);
5666     return node->ActionAccessibilityFocus(false);
5667 }
5668 
ClearCurrentFocus()5669 bool JsAccessibilityManager::ClearCurrentFocus()
5670 {
5671     auto currentFocusNode = GetAccessibilityNodeFromPage(currentFocusNodeId_);
5672     CHECK_NULL_RETURN(currentFocusNode, false);
5673     currentFocusNodeId_ = -1;
5674     currentFocusNode->SetFocusedState(false);
5675     currentFocusNode->SetAccessibilityFocusedState(false);
5676     return currentFocusNode->ActionAccessibilityFocus(false);
5677 }
5678 
FocusExtensionElementMoveSearchNG(const SearchParameter & searchParam,const RefPtr<NG::FrameNode> & node,Accessibility::AccessibilityElementInfo & info)5679 void FocusExtensionElementMoveSearchNG(const SearchParameter& searchParam,
5680     const RefPtr<NG::FrameNode>& node, Accessibility::AccessibilityElementInfo& info)
5681 {
5682     if (NG::UI_EXTENSION_OFFSET_MIN < (searchParam.uiExtensionOffset + 1)) {
5683         node->FocusMoveSearchNG(searchParam.nodeId, searchParam.mode,
5684             searchParam.uiExtensionOffset / NG::UI_EXTENSION_ID_FACTOR, info);
5685     } else {
5686         info.SetValidElement(false);
5687     }
5688 }
5689 
GetExtensionNextFocusableNode(const AccessibilityElementInfo & focusElement,const std::list<AccessibilityElementInfo> & nodeList,AccessibilityElementInfo & node)5690 void GetExtensionNextFocusableNode(const AccessibilityElementInfo& focusElement,
5691     const std::list<AccessibilityElementInfo>& nodeList, AccessibilityElementInfo& node)
5692 {
5693     auto nodeItem = nodeList.begin();
5694     for (; nodeItem != nodeList.end(); nodeItem++) {
5695         if ((*nodeItem).GetAccessibilityId() == focusElement.GetAccessibilityId()) {
5696             break;
5697         }
5698     }
5699 
5700     if (nodeItem != nodeList.end() && ++nodeItem != nodeList.end()) {
5701         node = (*nodeItem);
5702     }
5703     if (!nodeList.empty()) {
5704         node = (*nodeList.begin());
5705     }
5706 }
5707 
GetExtensionPreviousFocusableNode(const AccessibilityElementInfo & focusElement,const std::list<AccessibilityElementInfo> & nodeList,AccessibilityElementInfo & node)5708 void GetExtensionPreviousFocusableNode(const AccessibilityElementInfo& focusElement,
5709     const std::list<AccessibilityElementInfo>& nodeList, AccessibilityElementInfo& node)
5710 {
5711     auto nodeItem = nodeList.rbegin();
5712     for (; nodeItem != nodeList.rend(); nodeItem++) {
5713         if ((*nodeItem).GetAccessibilityId() == focusElement.GetAccessibilityId()) {
5714             break;
5715         }
5716     }
5717 
5718     if (nodeItem != nodeList.rend() && ++nodeItem != nodeList.rend()) {
5719         node = (*nodeItem);
5720     }
5721 
5722     if (!nodeList.empty()) {
5723         node = (*nodeList.rbegin());
5724     }
5725 }
5726 
FindExtensionNodeInAbsoluteDirection(const AccessibilityElementInfo & focusElement,const std::list<AccessibilityElementInfo> & nodeList,AccessibilityElementInfo & node,int32_t direction)5727 void FindExtensionNodeInAbsoluteDirection(const AccessibilityElementInfo& focusElement,
5728     const std::list<AccessibilityElementInfo>& nodeList, AccessibilityElementInfo& node, int32_t direction)
5729 {
5730     auto left = focusElement.GetRectInScreen().GetLeftTopXScreenPostion();
5731     auto top = focusElement.GetRectInScreen().GetLeftTopYScreenPostion();
5732     auto width = focusElement.GetRectInScreen().GetRightBottomXScreenPostion() -
5733         focusElement.GetRectInScreen().GetLeftTopXScreenPostion();
5734     auto height = focusElement.GetRectInScreen().GetRightBottomYScreenPostion() -
5735         focusElement.GetRectInScreen().GetLeftTopYScreenPostion();
5736     Rect rect(left, top, width, height);
5737     Rect tempBest(left, top, width, height);
5738     auto nodeRect = tempBest;
5739     switch (direction) {
5740         case FocusMoveDirection::LEFT:
5741             tempBest.SetLeft(left + width + 1);
5742             break;
5743         case FocusMoveDirection::RIGHT:
5744             tempBest.SetLeft(left - width - 1);
5745             break;
5746         case FocusMoveDirection::UP:
5747             tempBest.SetTop(top + height + 1);
5748             break;
5749         case FocusMoveDirection::DOWN:
5750             tempBest.SetTop(top - height - 1);
5751             break;
5752         default:
5753             break;
5754     }
5755     for (const auto& nodeItem : nodeList) {
5756         if (nodeItem.GetAccessibilityId() == focusElement.GetAccessibilityId() ||
5757             V2::ROOT_ETS_TAG == nodeItem.GetComponentType()) {
5758             continue;
5759         }
5760         left = nodeItem.GetRectInScreen().GetLeftTopXScreenPostion();
5761         top = nodeItem.GetRectInScreen().GetLeftTopYScreenPostion();
5762         width = nodeItem.GetRectInScreen().GetRightBottomXScreenPostion() -
5763             nodeItem.GetRectInScreen().GetLeftTopXScreenPostion();
5764         height = nodeItem.GetRectInScreen().GetRightBottomYScreenPostion() -
5765             nodeItem.GetRectInScreen().GetLeftTopYScreenPostion();
5766         Rect itemRect(left, top, width, height);
5767         if (CheckBetterRect(nodeRect, direction, itemRect, tempBest)) {
5768             tempBest = itemRect;
5769             node = nodeItem;
5770         }
5771     }
5772 }
5773 
FindExtensionNodeInRelativeDirection(const AccessibilityElementInfo & focusElement,const std::list<AccessibilityElementInfo> & nodeList,AccessibilityElementInfo & node,int direction)5774 void FindExtensionNodeInRelativeDirection(const AccessibilityElementInfo& focusElement,
5775     const std::list<AccessibilityElementInfo>& nodeList, AccessibilityElementInfo& node, int direction)
5776 {
5777     switch (direction) {
5778         case FocusMoveDirection::FORWARD:
5779             GetExtensionNextFocusableNode(focusElement, nodeList, node);
5780             break;
5781         case FocusMoveDirection::BACKWARD:
5782             GetExtensionPreviousFocusableNode(focusElement, nodeList, node);
5783             break;
5784         default:
5785             break;
5786     }
5787 }
5788 
FilterAccessibilityElementByFocusable(std::list<AccessibilityElementInfo> & elementList,AccessibilityElementInfo & focusElement,int64_t elementId)5789 void FilterAccessibilityElementByFocusable(std::list<AccessibilityElementInfo>& elementList,
5790     AccessibilityElementInfo& focusElement, int64_t elementId)
5791 {
5792     auto input = elementList;
5793     elementList.clear();
5794     std::set<int64_t> filterIds;
5795     for (auto& element : input) {
5796         if (filterIds.find(element.GetParentNodeId()) != filterIds.end()) {
5797             filterIds.insert(element.GetAccessibilityId());
5798             continue;
5799         }
5800         auto width = element.GetRectInScreen().GetRightBottomXScreenPostion() -
5801             element.GetRectInScreen().GetLeftTopXScreenPostion();
5802         auto height = element.GetRectInScreen().GetRightBottomYScreenPostion() -
5803             element.GetRectInScreen().GetLeftTopYScreenPostion();
5804         if (width == 0 || height == 0) {
5805             filterIds.insert(element.GetAccessibilityId());
5806             continue;
5807         }
5808         elementList.emplace_back(element);
5809         if (element.GetAccessibilityId() == elementId) {
5810             focusElement = element;
5811         }
5812     }
5813 }
5814 
GetResultOfFocusMoveSearchNG(int64_t elementId,int32_t direction,AccessibilityElementInfo & info)5815 void JsAccessibilityManager::GetResultOfFocusMoveSearchNG(
5816     int64_t elementId, int32_t direction, AccessibilityElementInfo& info)
5817 {
5818     auto pipeline = context_.Upgrade();
5819     CHECK_NULL_VOID(pipeline);
5820     std::list<AccessibilityElementInfo> nodeList;
5821     SearchElementInfoByAccessibilityIdNG(NG::UI_EXTENSION_ROOT_ID,
5822         PREFETCH_RECURSIVE_CHILDREN, nodeList, pipeline, NG::UI_EXTENSION_OFFSET_MAX);
5823     AccessibilityElementInfo focusElement;
5824     FilterAccessibilityElementByFocusable(nodeList, focusElement, elementId);
5825     switch (direction) {
5826         case FocusMoveDirection::FORWARD:
5827         case FocusMoveDirection::BACKWARD:
5828             Framework::FindExtensionNodeInRelativeDirection(focusElement, nodeList, info, direction);
5829             break;
5830         case FocusMoveDirection::UP:
5831         case FocusMoveDirection::DOWN:
5832         case FocusMoveDirection::LEFT:
5833         case FocusMoveDirection::RIGHT:
5834             Framework::FindExtensionNodeInAbsoluteDirection(focusElement, nodeList, info, direction);
5835             break;
5836         default:
5837             break;
5838     }
5839 }
5840 
FocusMoveSearchNG(int64_t elementId,int32_t direction,Accessibility::AccessibilityElementInfo & info,const RefPtr<PipelineBase> & context,const int64_t uiExtensionOffset)5841 void JsAccessibilityManager::FocusMoveSearchNG(int64_t elementId, int32_t direction,
5842     Accessibility::AccessibilityElementInfo& info, const RefPtr<PipelineBase>& context,
5843     const int64_t uiExtensionOffset)
5844 {
5845     auto mainContext = context_.Upgrade();
5846     CHECK_NULL_VOID(mainContext);
5847     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
5848     CHECK_NULL_VOID(ngPipeline);
5849     auto rootNode = ngPipeline->GetRootElement();
5850     CHECK_NULL_VOID(rootNode);
5851     auto node = GetFramenodeByAccessibilityId(rootNode, elementId);
5852     info.SetValidElement(false);
5853     GetResultOfFocusMoveSearchNG(elementId, direction, info);
5854 }
5855 
FocusExtensionElementMoveSearchNG(const SearchParameter & searchParam,Accessibility::AccessibilityElementInfo & info,const RefPtr<PipelineBase> & context,const RefPtr<NG::FrameNode> & root,RefPtr<NG::FrameNode> & outputExtensionNode)5856 void JsAccessibilityManager::FocusExtensionElementMoveSearchNG(const SearchParameter& searchParam,
5857     Accessibility::AccessibilityElementInfo& info, const RefPtr<PipelineBase>& context,
5858     const RefPtr<NG::FrameNode>& root, RefPtr<NG::FrameNode>& outputExtensionNode)
5859 {
5860 #ifdef WINDOW_SCENE_SUPPORTED
5861     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
5862     CHECK_NULL_VOID(ngPipeline);
5863     auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
5864     CHECK_NULL_VOID(uiExtensionManager);
5865     auto elementIdPair =
5866         uiExtensionManager->UnWrapExtensionAbilityId(searchParam.uiExtensionOffset, searchParam.nodeId);
5867     outputExtensionNode = uiExtensionManager->GetFocusUiExtensionNode();
5868     CHECK_NULL_VOID(outputExtensionNode);
5869     SearchParameter transferSearchParam {elementIdPair.second, "",
5870         searchParam.mode, searchParam.uiExtensionOffset};
5871     OHOS::Ace::Framework::FocusExtensionElementMoveSearchNG(transferSearchParam, outputExtensionNode, info);
5872     AccessibilityElementInfo parentInfo;
5873     ConvertExtensionAccessibilityId(info, outputExtensionNode, searchParam.uiExtensionOffset, parentInfo);
5874 #endif
5875 }
5876 
5877 // AccessibilitySystemAbilityClient will release callback after DeregisterElementOperator
SetSearchElementInfoByAccessibilityIdResult(AccessibilityElementOperatorCallback & callback,std::list<AccessibilityElementInfo> && infos,const int32_t requestId)5878 void JsAccessibilityManager::SetSearchElementInfoByAccessibilityIdResult(AccessibilityElementOperatorCallback& callback,
5879     std::list<AccessibilityElementInfo>&& infos, const int32_t requestId)
5880 {
5881     if (!IsRegister()) {
5882         return;
5883     }
5884     auto context = GetPipelineContext().Upgrade();
5885     CHECK_NULL_VOID(context);
5886     context->GetTaskExecutor()->PostTask(
5887         [weak = WeakClaim(this), infos = std::move(infos), &callback, requestId] () mutable {
5888             auto jsAccessibilityManager = weak.Upgrade();
5889             CHECK_NULL_VOID(jsAccessibilityManager);
5890             TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "winId: %{public}d, treeId: %{public}d, reqId: %{public}d",
5891                 jsAccessibilityManager->windowId_, jsAccessibilityManager->treeId_, requestId);
5892             if (!jsAccessibilityManager->IsRegister()) {
5893                 return;
5894             }
5895             jsAccessibilityManager->UpdateElementInfosTreeId(infos);
5896             callback.SetSearchElementInfoByAccessibilityIdResult(infos, requestId);
5897         }, TaskExecutor::TaskType::BACKGROUND, "ArkUIAccessibilitySetSearchElementInfoById");
5898 }
5899 
SetSearchElementInfoByTextResult(AccessibilityElementOperatorCallback & callback,std::list<AccessibilityElementInfo> && infos,const int32_t requestId)5900 void JsAccessibilityManager::SetSearchElementInfoByTextResult(AccessibilityElementOperatorCallback& callback,
5901     std::list<AccessibilityElementInfo>&& infos, const int32_t requestId)
5902 {
5903     if (!IsRegister()) {
5904         return;
5905     }
5906     auto context = GetPipelineContext().Upgrade();
5907     CHECK_NULL_VOID(context);
5908     context->GetTaskExecutor()->PostTask(
5909         [weak = WeakClaim(this), infos = std::move(infos), &callback, requestId] () mutable {
5910             auto jsAccessibilityManager = weak.Upgrade();
5911             CHECK_NULL_VOID(jsAccessibilityManager);
5912             if (!jsAccessibilityManager->IsRegister()) {
5913                 return;
5914             }
5915             jsAccessibilityManager->UpdateElementInfosTreeId(infos);
5916             callback.SetSearchElementInfoByTextResult(infos, requestId);
5917         }, TaskExecutor::TaskType::BACKGROUND, "ArkUIAccessibilitySetSearchElementInfoByText");
5918 }
5919 
SetFindFocusedElementInfoResult(AccessibilityElementOperatorCallback & callback,AccessibilityElementInfo & info,const int32_t requestId)5920 void JsAccessibilityManager::SetFindFocusedElementInfoResult(
5921     AccessibilityElementOperatorCallback& callback, AccessibilityElementInfo& info, const int32_t requestId)
5922 {
5923     if (IsRegister()) {
5924         UpdateElementInfoTreeId(info);
5925         callback.SetFindFocusedElementInfoResult(info, requestId);
5926     }
5927 }
5928 
SetFocusMoveSearchResult(AccessibilityElementOperatorCallback & callback,AccessibilityElementInfo & info,const int32_t requestId)5929 void JsAccessibilityManager::SetFocusMoveSearchResult(
5930     AccessibilityElementOperatorCallback& callback, AccessibilityElementInfo& info, const int32_t requestId)
5931 {
5932     if (IsRegister()) {
5933         UpdateElementInfoTreeId(info);
5934         callback.SetFocusMoveSearchResult(info, requestId);
5935     }
5936 }
5937 
SetExecuteActionResult(AccessibilityElementOperatorCallback & callback,const bool succeeded,const int32_t requestId)5938 void JsAccessibilityManager::SetExecuteActionResult(
5939     AccessibilityElementOperatorCallback& callback, const bool succeeded, const int32_t requestId)
5940 {
5941     if (IsRegister()) {
5942         callback.SetExecuteActionResult(succeeded, requestId);
5943     }
5944 }
5945 
GetPagePath()5946 std::string JsAccessibilityManager::GetPagePath()
5947 {
5948     auto context = context_.Upgrade();
5949     CHECK_NULL_RETURN(context, "");
5950     auto frontend = context->GetFrontend();
5951     CHECK_NULL_RETURN(frontend, "");
5952     ContainerScope scope(context->GetInstanceId());
5953     return frontend->GetPagePath();
5954 }
5955 
GenerateCommonProperty(const RefPtr<PipelineBase> & context,CommonProperty & output,const RefPtr<PipelineBase> & mainContext)5956 void JsAccessibilityManager::GenerateCommonProperty(const RefPtr<PipelineBase>& context, CommonProperty& output,
5957     const RefPtr<PipelineBase>& mainContext)
5958 {
5959     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
5960     CHECK_NULL_VOID(ngPipeline);
5961     auto stageManager = ngPipeline->GetStageManager();
5962     CHECK_NULL_VOID(stageManager);
5963     if (!ngPipeline->IsFormRender()) {
5964         output.windowId = static_cast<int32_t>(ngPipeline->GetRealHostWindowId());
5965     } else {
5966         output.windowId = static_cast<int32_t>(GetWindowId());
5967     }
5968     if (getParentRectHandler_) {
5969         getParentRectHandler_(output.windowTop, output.windowLeft);
5970     } else {
5971         output.windowLeft = GetWindowLeft(ngPipeline->GetWindowId());
5972         output.windowTop = GetWindowTop(ngPipeline->GetWindowId());
5973     }
5974     auto page = stageManager->GetLastPageWithTransition();
5975     if (page != nullptr) {
5976         output.pageId = page->GetPageId();
5977         output.pagePath = GetPagePath();
5978     }
5979     if (context->GetWindowId() != mainContext->GetWindowId()) {
5980         output.pageId = 0;
5981         output.pagePath = "";
5982     }
5983 }
5984 
FindText(const RefPtr<NG::UINode> & node,std::list<Accessibility::AccessibilityElementInfo> & infos,const RefPtr<NG::PipelineContext> & context,const CommonProperty & commonProperty,const SearchParameter & searchParam)5985 void JsAccessibilityManager::FindText(const RefPtr<NG::UINode>& node,
5986     std::list<Accessibility::AccessibilityElementInfo>& infos, const RefPtr<NG::PipelineContext>& context,
5987     const CommonProperty& commonProperty, const SearchParameter& searchParam)
5988 {
5989     CHECK_NULL_VOID(node);
5990     auto frameNode = AceType::DynamicCast<NG::FrameNode>(node);
5991     if (frameNode && !frameNode->IsInternal()) {
5992         if (frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>()->GetGroupText().find(
5993             searchParam.text) != std::string::npos) {
5994             AccessibilityElementInfo nodeInfo;
5995             UpdateAccessibilityElementInfo(frameNode, commonProperty, nodeInfo, context);
5996             infos.emplace_back(nodeInfo);
5997         }
5998     }
5999     if (IsExtensionComponent(frameNode) && !IsUIExtensionShowPlaceholder(frameNode)) {
6000         auto infosByIPC = SearchElementInfosByTextNG(NG::UI_EXTENSION_ROOT_ID, searchParam.text,
6001             frameNode, searchParam.uiExtensionOffset / NG::UI_EXTENSION_ID_FACTOR);
6002         if (!infosByIPC.empty()) {
6003             AccessibilityElementInfo nodeInfo;
6004             UpdateAccessibilityElementInfo(frameNode, commonProperty, nodeInfo, context);
6005             ConvertExtensionAccessibilityNodeId(infosByIPC, frameNode, searchParam.uiExtensionOffset, nodeInfo);
6006             for (auto& info : infosByIPC) {
6007                 infos.emplace_back(info);
6008             }
6009         }
6010     }
6011     if (!node->GetChildren(true).empty()) {
6012         for (const auto& child : node->GetChildren(true)) {
6013             FindText(child, infos, context, commonProperty, searchParam);
6014         }
6015     }
6016 }
6017 
FindTextByTextHint(const RefPtr<NG::UINode> & node,std::list<Accessibility::AccessibilityElementInfo> & infos,const RefPtr<NG::PipelineContext> & context,const CommonProperty & commonProperty,const SearchParameter & searchParam)6018 void JsAccessibilityManager::FindTextByTextHint(const RefPtr<NG::UINode>& node,
6019     std::list<Accessibility::AccessibilityElementInfo>& infos, const RefPtr<NG::PipelineContext>& context,
6020     const CommonProperty& commonProperty, const SearchParameter& searchParam)
6021 {
6022     CHECK_NULL_VOID(node);
6023     auto frameNode = AceType::DynamicCast<NG::FrameNode>(node);
6024     if (frameNode && !frameNode->IsInternal()) {
6025         std::string text = searchParam.text;
6026         nlohmann::json textJson = nlohmann::json::parse(text, nullptr, false);
6027         std::string value = "";
6028         if (!textJson.is_null() && !textJson.is_discarded() && textJson.contains("value")) {
6029             value = textJson["value"];
6030         }
6031         std::string textType = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>()->GetTextType();
6032         nlohmann::json textTypeJson = nlohmann::json::parse(textType, nullptr, false);
6033         if (!textTypeJson.is_null() && !textTypeJson.is_discarded() &&
6034             textTypeJson.contains("type") && textTypeJson["type"] == value) {
6035             AccessibilityElementInfo nodeInfo;
6036             UpdateAccessibilityElementInfo(frameNode, commonProperty, nodeInfo, context);
6037             infos.emplace_back(nodeInfo);
6038         }
6039     }
6040     if (IsIsolatedComponent(frameNode)) {
6041         auto infosByIPC = SearchElementInfosByTextNG(NG::UI_EXTENSION_ROOT_ID, searchParam.text,
6042             frameNode, searchParam.uiExtensionOffset / NG::UI_EXTENSION_ID_FACTOR);
6043         if (!infosByIPC.empty()) {
6044             AccessibilityElementInfo nodeInfo;
6045             UpdateAccessibilityElementInfo(frameNode, commonProperty, nodeInfo, context);
6046             ConvertExtensionAccessibilityNodeId(infosByIPC, frameNode, searchParam.uiExtensionOffset, nodeInfo);
6047             for (auto& info : infosByIPC) {
6048                 infos.emplace_back(info);
6049             }
6050         }
6051     }
6052     if (!node->GetChildren(true).empty()) {
6053         for (const auto& child : node->GetChildren(true)) {
6054             FindTextByTextHint(child, infos, context, commonProperty, searchParam);
6055         }
6056     }
6057 }
6058 
TransferThirdProviderHoverEvent(const WeakPtr<NG::FrameNode> & hostNode,const NG::PointF & point,SourceType source,NG::AccessibilityHoverEventType eventType,TimeStamp time)6059 void JsAccessibilityManager::TransferThirdProviderHoverEvent(
6060     const WeakPtr<NG::FrameNode>& hostNode, const NG::PointF& point, SourceType source,
6061     NG::AccessibilityHoverEventType eventType, TimeStamp time)
6062 {
6063     auto pipelineContext = GetPipelineContext().Upgrade();
6064     CHECK_NULL_VOID(pipelineContext);
6065     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
6066     CHECK_NULL_VOID(ngPipeline);
6067     auto frameNode = hostNode.Upgrade();
6068     CHECK_NULL_VOID(frameNode);
6069     AccessibilityHoverForThirdConfig config;
6070     config.hostElementId = frameNode->GetAccessibilityId();
6071     config.point = point;
6072     config.sourceType = source;
6073     config.eventType = eventType;
6074     config.time = time;
6075     config.hostNode = frameNode;
6076     config.context = ngPipeline;
6077     HandleAccessibilityHoverForThird(config);
6078 }
6079 
OnDumpChildInfoForThird(int64_t hostElementId,const std::vector<std::string> & params,std::vector<std::string> & info)6080 bool JsAccessibilityManager::OnDumpChildInfoForThird(
6081     int64_t hostElementId,
6082     const std::vector<std::string>& params,
6083     std::vector<std::string>& info)
6084 {
6085     return OnDumpChildInfoForThirdRecursive(hostElementId, params, info, WeakClaim(this));
6086 }
6087 
6088 #ifdef WEB_SUPPORTED
GetWebCursorPosition(const int64_t elementId,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const RefPtr<NG::WebPattern> & webPattern)6089 void JsAccessibilityManager::GetWebCursorPosition(const int64_t elementId, const int32_t requestId,
6090     AccessibilityElementOperatorCallback& callback, const RefPtr<NG::WebPattern>& webPattern)
6091 {
6092     CHECK_NULL_VOID(webPattern);
6093     auto node = webPattern->GetAccessibilityNodeById(elementId);
6094     CHECK_NULL_VOID(node);
6095 
6096     callback.SetCursorPositionResult(node->GetSelectionStart(), requestId);
6097 }
6098 #endif // WEB_SUPPORTED
6099 
FireAccessibilityEventCallback(uint32_t eventId,int64_t parameter)6100 void JsAccessibilityManager::FireAccessibilityEventCallback(uint32_t eventId, int64_t parameter)
6101 {
6102     auto eventType = static_cast<AccessibilityCallbackEventId>(eventId);
6103     AccessibilityEvent event;
6104     switch (eventType) {
6105         case AccessibilityCallbackEventId::ON_LOAD_PAGE:
6106             event.nodeId = parameter;
6107             event.windowChangeTypes = WindowUpdateType::WINDOW_UPDATE_ACTIVE;
6108             event.type = AccessibilityEventType::CHANGE;
6109             SendAccessibilityAsyncEvent(event);
6110             break;
6111         case AccessibilityCallbackEventId::ON_SEND_ELEMENT_INFO_CHANGE:
6112             event.type = AccessibilityEventType::ELEMENT_INFO_CHANGE;
6113             event.nodeId = parameter;
6114             SendAccessibilityAsyncEvent(event);
6115             break;
6116         default:
6117             break;
6118     }
6119 }
6120 } // namespace OHOS::Ace::Framework
6121