• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "js_accessibility_manager.h"
17 
18 #include "accessibility_constants.h"
19 #include "accessibility_event_info.h"
20 #include "accessibility_system_ability_client.h"
21 
22 #include "adapter/ohos/entrance/ace_application_info.h"
23 #include "base/log/dump_log.h"
24 #include "base/log/event_report.h"
25 #include "base/log/log.h"
26 #include "base/utils/linear_map.h"
27 #include "base/utils/string_utils.h"
28 #include "base/utils/utils.h"
29 #include "core/components_ng/base/inspector.h"
30 #include "core/components_v2/inspector/inspector_constants.h"
31 #include "core/pipeline/pipeline_context.h"
32 #include "core/pipeline_ng/pipeline_context.h"
33 #include "frameworks/bridge/common/dom/dom_type.h"
34 
35 using namespace OHOS::Accessibility;
36 using namespace OHOS::AccessibilityConfig;
37 using namespace std;
38 
39 namespace OHOS::Ace::Framework {
40 namespace {
41 const char DUMP_ORDER[] = "-accessibility";
42 const char DUMP_INSPECTOR[] = "-inspector";
43 const char ACCESSIBILITY_FOCUSED_EVENT[] = "accessibilityfocus";
44 const char ACCESSIBILITY_CLEAR_FOCUS_EVENT[] = "accessibilityclearfocus";
45 const char TEXT_CHANGE_EVENT[] = "textchange";
46 const char PAGE_CHANGE_EVENT[] = "pagechange";
47 const char SCROLL_END_EVENT[] = "scrollend";
48 const char SCROLL_START_EVENT[] = "scrollstart";
49 const char MOUSE_HOVER_ENTER[] = "mousehoverenter";
50 const char MOUSE_HOVER_EXIT[] = "mousehoverexit";
51 const char IMPORTANT_YES[] = "yes";
52 const char IMPORTANT_NO[] = "no";
53 const char IMPORTANT_NO_HIDE_DES[] = "no-hide-descendants";
54 const char LIST_TAG[] = "List";
55 const char SIDEBARCONTAINER_TAG[] = "SideBarContainer";
56 constexpr int32_t INVALID_PARENT_ID = -2100000;
57 constexpr int32_t DEFAULT_PARENT_ID = 2100000;
58 constexpr int32_t ROOT_STACK_BASE = 1100000;
59 constexpr int32_t ROOT_DECOR_BASE = 3100000;
60 constexpr int32_t CARD_NODE_ID_RATION = 10000;
61 constexpr int32_t CARD_ROOT_NODE_ID_RATION = 1000;
62 constexpr int32_t CARD_BASE = 100000;
63 
64 struct ActionTable {
65     AceAction aceAction;
66     ActionType action;
67 };
68 
69 struct CommonProperty {
70     int32_t windowId = 0;
71     int32_t windowLeft = 0;
72     int32_t windowTop = 0;
73     int32_t pageId = 0;
74     std::string pagePath;
75 };
76 
77 struct AccessibilityActionParam {
78     RefPtr<NG::AccessibilityProperty> accessibilityProperty;
79     std::string setTextArgument = "";
80     int32_t setSelectionStart = -1;
81     int32_t setSelectionEnd = -1;
82     TextMoveUnit moveUnit = TextMoveUnit::STEP_CHARACTER;
83 };
84 
85 const std::map<Accessibility::ActionType, std::function<bool(const AccessibilityActionParam& param)>> ACTIONS = {
86     { ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD,
__anon8056d5eb0202() 87         [](const AccessibilityActionParam& param) { return param.accessibilityProperty->ActActionScrollForward(); } },
88     { ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD,
__anon8056d5eb0302() 89         [](const AccessibilityActionParam& param) { return param.accessibilityProperty->ActActionScrollBackward(); } },
90     { ActionType::ACCESSIBILITY_ACTION_SET_TEXT,
__anon8056d5eb0402() 91         [](const AccessibilityActionParam& param) {
92             return param.accessibilityProperty->ActActionSetText(param.setTextArgument);
93         } },
94     { ActionType::ACCESSIBILITY_ACTION_SET_SELECTION,
__anon8056d5eb0502() 95         [](const AccessibilityActionParam& param) {
96             return param.accessibilityProperty->ActActionSetSelection(param.setSelectionStart, param.setSelectionEnd);
97         } },
98     { ActionType::ACCESSIBILITY_ACTION_COPY,
__anon8056d5eb0602() 99         [](const AccessibilityActionParam& param) { return param.accessibilityProperty->ActActionCopy(); } },
100     { ActionType::ACCESSIBILITY_ACTION_CUT,
__anon8056d5eb0702() 101         [](const AccessibilityActionParam& param) { return param.accessibilityProperty->ActActionCut(); } },
102     { ActionType::ACCESSIBILITY_ACTION_PASTE,
__anon8056d5eb0802() 103         [](const AccessibilityActionParam& param) { return param.accessibilityProperty->ActActionPaste(); } },
104     { ActionType::ACCESSIBILITY_ACTION_SELECT,
__anon8056d5eb0902() 105         [](const AccessibilityActionParam& param) { return param.accessibilityProperty->ActActionSelect(); } },
106     { ActionType::ACCESSIBILITY_ACTION_CLEAR_SELECTION,
__anon8056d5eb0a02() 107         [](const AccessibilityActionParam& param) { return param.accessibilityProperty->ActActionClearSelection(); } },
108     { ActionType::ACCESSIBILITY_ACTION_NEXT_TEXT,
__anon8056d5eb0b02() 109         [](const AccessibilityActionParam& param) {
110             return param.accessibilityProperty->ActActionMoveText(static_cast<int32_t>(param.moveUnit), true);
111         } },
112     { ActionType::ACCESSIBILITY_ACTION_PREVIOUS_TEXT,
__anon8056d5eb0c02() 113         [](const AccessibilityActionParam& param) {
114             return param.accessibilityProperty->ActActionMoveText(static_cast<int32_t>(param.moveUnit), false);
115         } },
116 };
117 
ConvertStrToEventType(const std::string & type)118 Accessibility::EventType ConvertStrToEventType(const std::string& type)
119 {
120     // static linear map must be sorted by key.
121     static const LinearMapNode<Accessibility::EventType> eventTypeMap[] = {
122         { ACCESSIBILITY_CLEAR_FOCUS_EVENT, Accessibility::EventType::TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED_EVENT },
123         { ACCESSIBILITY_FOCUSED_EVENT, Accessibility::EventType::TYPE_VIEW_ACCESSIBILITY_FOCUSED_EVENT },
124         { DOM_CLICK, Accessibility::EventType::TYPE_VIEW_CLICKED_EVENT },
125         { DOM_FOCUS, Accessibility::EventType::TYPE_VIEW_FOCUSED_EVENT },
126         { DOM_LONG_PRESS, Accessibility::EventType::TYPE_VIEW_LONG_CLICKED_EVENT },
127         { MOUSE_HOVER_ENTER, Accessibility::EventType::TYPE_VIEW_HOVER_ENTER_EVENT },
128         { MOUSE_HOVER_EXIT, Accessibility::EventType::TYPE_VIEW_HOVER_EXIT_EVENT },
129         { PAGE_CHANGE_EVENT, Accessibility::EventType::TYPE_PAGE_STATE_UPDATE },
130         { SCROLL_END_EVENT, Accessibility::EventType::TYPE_VIEW_SCROLLED_EVENT },
131         { SCROLL_START_EVENT, Accessibility::EventType::TYPE_VIEW_SCROLLED_EVENT },
132         { DOM_SELECTED, Accessibility::EventType::TYPE_VIEW_SELECTED_EVENT },
133         { TEXT_CHANGE_EVENT, Accessibility::EventType::TYPE_VIEW_TEXT_UPDATE_EVENT },
134         { DOM_TOUCH_END, Accessibility::EventType::TYPE_TOUCH_END },
135         { DOM_TOUCH_START, Accessibility::EventType::TYPE_TOUCH_BEGIN },
136     };
137     Accessibility::EventType eventType = Accessibility::EventType::TYPE_VIEW_INVALID;
138     int64_t idx = BinarySearchFindIndex(eventTypeMap, ArraySize(eventTypeMap), type.c_str());
139     if (idx >= 0) {
140         eventType = eventTypeMap[idx].value;
141     }
142     return eventType;
143 }
144 
ConvertAceEventType(AccessibilityEventType type)145 Accessibility::EventType ConvertAceEventType(AccessibilityEventType type)
146 {
147     static const LinearEnumMapNode<AccessibilityEventType, Accessibility::EventType> eventTypeMap[] = {
148         { AccessibilityEventType::CLICK, Accessibility::EventType::TYPE_VIEW_CLICKED_EVENT },
149         { AccessibilityEventType::LONG_PRESS, Accessibility::EventType::TYPE_VIEW_LONG_CLICKED_EVENT },
150         { AccessibilityEventType::SELECTED, Accessibility::EventType::TYPE_VIEW_SELECTED_EVENT },
151         { AccessibilityEventType::FOCUS, Accessibility::EventType::TYPE_VIEW_FOCUSED_EVENT },
152         { AccessibilityEventType::TEXT_CHANGE, Accessibility::EventType::TYPE_VIEW_TEXT_UPDATE_EVENT },
153         { AccessibilityEventType::PAGE_CHANGE, Accessibility::EventType::TYPE_PAGE_STATE_UPDATE },
154         { AccessibilityEventType::CHANGE, Accessibility::EventType::TYPE_PAGE_CONTENT_UPDATE },
155         { AccessibilityEventType::SCROLL_END, Accessibility::EventType::TYPE_VIEW_SCROLLED_EVENT },
156         { AccessibilityEventType::TEXT_SELECTION_UPDATE,
157             Accessibility::EventType::TYPE_VIEW_TEXT_SELECTION_UPDATE_EVENT },
158         { AccessibilityEventType::ACCESSIBILITY_FOCUSED,
159             Accessibility::EventType::TYPE_VIEW_ACCESSIBILITY_FOCUSED_EVENT },
160         { AccessibilityEventType::ACCESSIBILITY_FOCUS_CLEARED,
161             Accessibility::EventType::TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED_EVENT },
162         { AccessibilityEventType::TEXT_MOVE_UNIT, Accessibility::EventType::TYPE_VIEW_TEXT_MOVE_UNIT_EVENT },
163     };
164     Accessibility::EventType eventType = Accessibility::EventType::TYPE_VIEW_INVALID;
165     int64_t idx = BinarySearchFindIndex(eventTypeMap, ArraySize(eventTypeMap), type);
166     if (idx >= 0) {
167         eventType = eventTypeMap[idx].value;
168     }
169     return eventType;
170 }
171 
ConvertAceAction(AceAction aceAction)172 ActionType ConvertAceAction(AceAction aceAction)
173 {
174     static const ActionTable actionTable[] = {
175         { AceAction::ACTION_CLICK, ActionType::ACCESSIBILITY_ACTION_CLICK },
176         { AceAction::ACTION_LONG_CLICK, ActionType::ACCESSIBILITY_ACTION_LONG_CLICK },
177         { AceAction::ACTION_SCROLL_FORWARD, ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD },
178         { AceAction::ACTION_SCROLL_BACKWARD, ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD },
179         { AceAction::ACTION_FOCUS, ActionType::ACCESSIBILITY_ACTION_FOCUS },
180         { AceAction::ACTION_CLEAR_FOCUS, ActionType::ACCESSIBILITY_ACTION_CLEAR_FOCUS },
181         { AceAction::ACTION_ACCESSIBILITY_FOCUS, ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS },
182         { AceAction::ACTION_CLEAR_ACCESSIBILITY_FOCUS, ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS },
183         { AceAction::ACTION_NEXT_AT_MOVEMENT_GRANULARITY, ActionType::ACCESSIBILITY_ACTION_NEXT_TEXT },
184         { AceAction::ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, ActionType::ACCESSIBILITY_ACTION_PREVIOUS_TEXT },
185         { AceAction::ACTION_SET_TEXT, ActionType::ACCESSIBILITY_ACTION_SET_TEXT },
186         { AceAction::ACTION_COPY, ActionType::ACCESSIBILITY_ACTION_COPY },
187         { AceAction::ACTION_PASTE, ActionType::ACCESSIBILITY_ACTION_PASTE },
188         { AceAction::ACTION_CUT, ActionType::ACCESSIBILITY_ACTION_CUT },
189         { AceAction::ACTION_SELECT, ActionType::ACCESSIBILITY_ACTION_SELECT },
190         { AceAction::ACTION_CLEAR_SELECTION, ActionType::ACCESSIBILITY_ACTION_CLEAR_SELECTION },
191         { AceAction::ACTION_SET_SELECTION, ActionType::ACCESSIBILITY_ACTION_SET_SELECTION },
192     };
193     for (const auto& item : actionTable) {
194         if (aceAction == item.aceAction) {
195             return item.action;
196         }
197     }
198     return ActionType::ACCESSIBILITY_ACTION_INVALID;
199 }
200 
ConvertAccessibilityValue(const AccessibilityValue & value)201 inline RangeInfo ConvertAccessibilityValue(const AccessibilityValue& value)
202 {
203     return RangeInfo(static_cast<int>(value.min), static_cast<int>(value.max), static_cast<int>(value.current));
204 }
205 
ConvertToCardAccessibilityId(int32_t nodeId,int32_t cardId,int32_t rootNodeId)206 int32_t ConvertToCardAccessibilityId(int32_t nodeId, int32_t cardId, int32_t rootNodeId)
207 {
208     // result is integer total ten digits, top five for agp virtualViewId, end five for ace nodeId,
209     // for example agp virtualViewId is 32, ace nodeId is 1000001, convert to result is 00032 10001.
210     int32_t result = 0;
211     if (nodeId == rootNodeId + ROOT_STACK_BASE) {
212         // for example agp virtualViewId is 32 root node is 2100000, convert to result is 00032 21000.
213         result = cardId * CARD_BASE + (static_cast<int32_t>(nodeId / CARD_BASE)) * CARD_ROOT_NODE_ID_RATION +
214                  nodeId % CARD_BASE;
215     } else {
216         result = cardId * CARD_BASE + (static_cast<int32_t>(nodeId / DOM_ROOT_NODE_ID_BASE)) * CARD_NODE_ID_RATION +
217                  nodeId % DOM_ROOT_NODE_ID_BASE;
218     }
219     return result;
220 }
221 
UpdateAccessibilityNodeInfo(const RefPtr<AccessibilityNode> & node,AccessibilityElementInfo & nodeInfo,const RefPtr<JsAccessibilityManager> & manager,int windowId)222 void UpdateAccessibilityNodeInfo(const RefPtr<AccessibilityNode>& node, AccessibilityElementInfo& nodeInfo,
223     const RefPtr<JsAccessibilityManager>& manager, int windowId)
224 {
225     LOGD("nodeId:%{public}d", node->GetNodeId());
226     int leftTopX = static_cast<int>(node->GetLeft()) + manager->GetWindowLeft(node->GetWindowId());
227     int leftTopY = static_cast<int>(node->GetTop()) + manager->GetWindowTop(node->GetWindowId());
228     int rightBottomX = leftTopX + static_cast<int>(node->GetWidth());
229     int rightBottomY = leftTopY + static_cast<int>(node->GetHeight());
230     if (manager->isOhosHostCard()) {
231         int32_t id = ConvertToCardAccessibilityId(node->GetNodeId(), manager->GetCardId(), manager->GetRootNodeId());
232         nodeInfo.SetAccessibilityId(id);
233         if (node->GetParentId() == -1) {
234             nodeInfo.SetParent(-1);
235         } else {
236             nodeInfo.SetParent(
237                 ConvertToCardAccessibilityId(node->GetParentId(), manager->GetCardId(), manager->GetRootNodeId()));
238         }
239         leftTopX = static_cast<int>(node->GetLeft() + manager->GetCardOffset().GetX());
240         leftTopY = static_cast<int>(node->GetTop() + manager->GetCardOffset().GetY());
241         rightBottomX = leftTopX + static_cast<int>(node->GetWidth());
242         rightBottomY = leftTopY + static_cast<int>(node->GetHeight());
243         Accessibility::Rect bounds(leftTopX, leftTopY, rightBottomX, rightBottomY);
244         nodeInfo.SetRectInScreen(bounds);
245     } else {
246         if (node->GetTag() == SIDEBARCONTAINER_TAG) {
247             Rect sideBarRect = node->GetRect();
248             for (const auto& childNode : node->GetChildList()) {
249                 sideBarRect = sideBarRect.CombineRect(childNode->GetRect());
250             }
251             leftTopX = static_cast<int>(sideBarRect.Left()) + manager->GetWindowLeft(node->GetWindowId());
252             leftTopY = static_cast<int>(sideBarRect.Top()) + manager->GetWindowTop(node->GetWindowId());
253             rightBottomX = static_cast<int>(sideBarRect.Right()) + manager->GetWindowLeft(node->GetWindowId());
254             rightBottomY = static_cast<int>(sideBarRect.Bottom()) + manager->GetWindowTop(node->GetWindowId());
255         }
256         Accessibility::Rect bounds(leftTopX, leftTopY, rightBottomX, rightBottomY);
257         nodeInfo.SetRectInScreen(bounds);
258         nodeInfo.SetComponentId(static_cast<int>(node->GetNodeId()));
259         nodeInfo.SetParent(static_cast<int>(node->GetParentId()));
260     }
261 
262     if (node->GetParentId() == -1) {
263         const auto& children = node->GetChildList();
264         if (!children.empty()) {
265             auto lastChildNode = manager->GetAccessibilityNodeById(children.back()->GetNodeId());
266             if (lastChildNode) {
267                 rightBottomX = leftTopX + static_cast<int>(lastChildNode->GetWidth());
268                 rightBottomY = leftTopY + static_cast<int>(lastChildNode->GetHeight());
269                 Accessibility::Rect bounds(leftTopX, leftTopY, rightBottomX, rightBottomY);
270                 nodeInfo.SetRectInScreen(bounds);
271             }
272         }
273         nodeInfo.SetParent(INVALID_PARENT_ID);
274     }
275     if (node->GetNodeId() == 0) {
276         nodeInfo.SetParent(INVALID_PARENT_ID);
277     }
278     nodeInfo.SetPagePath(manager->GetPagePath());
279     nodeInfo.SetWindowId(windowId);
280     nodeInfo.SetChecked(node->GetCheckedState());
281     nodeInfo.SetEnabled(node->GetEnabledState());
282     nodeInfo.SetFocused(node->GetFocusedState());
283     nodeInfo.SetSelected(node->GetSelectedState());
284     nodeInfo.SetCheckable(node->GetCheckableState());
285     nodeInfo.SetClickable(node->GetClickableState());
286     nodeInfo.SetFocusable(node->GetFocusableState());
287     nodeInfo.SetScrollable(node->GetScrollableState());
288     nodeInfo.SetLongClickable(node->GetLongClickableState());
289     nodeInfo.SetEditable(node->GetEditable());
290     nodeInfo.SetPluraLineSupported(node->GetIsMultiLine());
291     nodeInfo.SetPassword(node->GetIsPassword());
292     nodeInfo.SetTextLengthLimit(node->GetMaxTextLength());
293     nodeInfo.SetSelectedBegin(node->GetTextSelectionStart());
294     nodeInfo.SetSelectedEnd(node->GetTextSelectionEnd());
295     nodeInfo.SetVisible(node->GetShown() && node->GetVisible());
296     nodeInfo.SetHint(node->GetHintText());
297     std::string accessibilityLabel = node->GetAccessibilityLabel();
298     nodeInfo.SetLabeled(atoi(accessibilityLabel.c_str()));
299     nodeInfo.SetError(node->GetErrorText());
300     nodeInfo.SetComponentResourceId(node->GetJsComponentId());
301     nodeInfo.SetInspectorKey(node->GetJsComponentId());
302     RangeInfo rangeInfo = ConvertAccessibilityValue(node->GetAccessibilityValue());
303     nodeInfo.SetRange(rangeInfo);
304     nodeInfo.SetInputType(static_cast<int>(node->GetTextInputType()));
305     nodeInfo.SetComponentType(node->GetTag());
306     GridInfo gridInfo(
307         node->GetCollectionInfo().rows, node->GetCollectionInfo().columns, (nodeInfo.IsPluraLineSupported() ? 0 : 1));
308     nodeInfo.SetGrid(gridInfo);
309     nodeInfo.SetAccessibilityFocus(node->GetAccessibilityFocusedState());
310     nodeInfo.SetPageId(node->GetPageId());
311 
312     int32_t row = node->GetCollectionItemInfo().row;
313     int32_t column = node->GetCollectionItemInfo().column;
314     GridItemInfo gridItemInfo(row, row, column, column, false, nodeInfo.IsSelected());
315     nodeInfo.SetGridItem(gridItemInfo);
316     nodeInfo.SetBundleName(AceApplicationInfo::GetInstance().GetPackageName());
317 
318     if (node->GetTag() == LIST_TAG) {
319         nodeInfo.SetItemCounts(node->GetListItemCounts());
320         nodeInfo.SetBeginIndex(node->GetListBeginIndex());
321         nodeInfo.SetEndIndex(node->GetListEndIndex());
322     }
323     if (node->GetIsPassword()) {
324         std::string strStar(node->GetText().size(), '*');
325         nodeInfo.SetContent(strStar);
326     } else {
327         nodeInfo.SetContent(node->GetText());
328     }
329 
330     if (!node->GetAccessibilityHint().empty()) {
331         if (node->GetAccessibilityLabel().empty()) {
332             LOGI("UpdateAccessibilityNodeInfo Label is null");
333         } else {
334             LOGI("UpdateAccessibilityNodeInfo Label is not null");
335         }
336     }
337 
338     auto supportAceActions = node->GetSupportAction();
339     std::vector<ActionType> actions(supportAceActions.size());
340 
341     for (auto it = supportAceActions.begin(); it != supportAceActions.end(); ++it) {
342         AccessibleAction action(ConvertAceAction(*it), "ace");
343         nodeInfo.AddAction(action);
344     }
345 
346     if (node->GetImportantForAccessibility() == IMPORTANT_YES) {
347         actions.emplace_back(ActionType::ACCESSIBILITY_ACTION_FOCUS);
348         nodeInfo.SetCheckable(true);
349     } else if (node->GetImportantForAccessibility() == IMPORTANT_NO ||
350                node->GetImportantForAccessibility() == IMPORTANT_NO_HIDE_DES) {
351         nodeInfo.SetVisible(false);
352     }
353 
354     manager->UpdateNodeChildIds(node);
355     for (const auto& child : node->GetChildIds()) {
356         nodeInfo.AddChild(child);
357     }
358 
359 #ifdef ACE_DEBUG
360     std::string actionForLog;
361     for (const auto& action : supportAceActions) {
362         if (!actionForLog.empty()) {
363             actionForLog.append(",");
364         }
365         actionForLog.append(std::to_string(static_cast<int32_t>(action)));
366     }
367     LOGD("Support action is %{public}s", actionForLog.c_str());
368 #endif
369 }
370 
UpdateCacheInfo(std::list<AccessibilityElementInfo> & infos,uint32_t mode,const RefPtr<AccessibilityNode> & node,const RefPtr<JsAccessibilityManager> & jsAccessibilityManager,int windowId)371 void UpdateCacheInfo(std::list<AccessibilityElementInfo>& infos, uint32_t mode, const RefPtr<AccessibilityNode>& node,
372     const RefPtr<JsAccessibilityManager>& jsAccessibilityManager, int windowId)
373 {
374     // parent
375     uint32_t umode = mode;
376     if (umode & static_cast<uint32_t>(PREFETCH_PREDECESSORS)) {
377         if (node->GetParentId() != -1 && node->GetParentId() != DEFAULT_PARENT_ID) {
378             AccessibilityElementInfo parentNodeInfo;
379             UpdateAccessibilityNodeInfo(node->GetParentNode(), parentNodeInfo, jsAccessibilityManager, windowId);
380             infos.emplace_back(parentNodeInfo);
381         }
382     }
383     // sister/brothers
384     if (umode & static_cast<uint32_t>(PREFETCH_SIBLINGS)) {
385         if (node->GetParentId() != -1 && node->GetParentId() != DEFAULT_PARENT_ID) {
386             for (const auto& item : node->GetParentNode()->GetChildList()) {
387                 if (node->GetNodeId() != item->GetNodeId()) {
388                     AccessibilityElementInfo siblingNodeInfo;
389                     UpdateAccessibilityNodeInfo(item, siblingNodeInfo, jsAccessibilityManager, windowId);
390                     infos.emplace_back(siblingNodeInfo);
391                 }
392             }
393         }
394     }
395     // children
396     if (umode & static_cast<uint32_t>(PREFETCH_CHILDREN)) {
397         for (const auto& item : node->GetChildList()) {
398             AccessibilityElementInfo childNodeInfo;
399             UpdateAccessibilityNodeInfo(item, childNodeInfo, jsAccessibilityManager, windowId);
400             infos.emplace_back(childNodeInfo);
401         }
402     }
403 }
404 
BoolToString(bool tag)405 inline std::string BoolToString(bool tag)
406 {
407     return tag ? "true" : "false";
408 }
409 
ConvertInputTypeToString(AceTextCategory type)410 std::string ConvertInputTypeToString(AceTextCategory type)
411 {
412     switch (type) {
413         case AceTextCategory::INPUT_TYPE_DEFAULT:
414             return "INPUT_TYPE_DEFAULT";
415         case AceTextCategory::INPUT_TYPE_TEXT:
416             return "INPUT_TYPE_TEXT";
417         case AceTextCategory::INPUT_TYPE_EMAIL:
418             return "INPUT_TYPE_EMAIL";
419         case AceTextCategory::INPUT_TYPE_DATE:
420             return "INPUT_TYPE_DATE";
421         case AceTextCategory::INPUT_TYPE_TIME:
422             return "INPUT_TYPE_TIME";
423         case AceTextCategory::INPUT_TYPE_NUMBER:
424             return "INPUT_TYPE_NUMBER";
425         case AceTextCategory::INPUT_TYPE_PASSWORD:
426             return "INPUT_TYPE_PASSWORD";
427         case AceTextCategory::INPUT_TYPE_PHONENUMBER:
428             return "INPUT_TYPE_PHONENUMBER";
429         default:
430             return "illegal input type";
431     }
432 }
433 
FindAccessibilityFocus(const RefPtr<AccessibilityNode> & node,RefPtr<AccessibilityNode> & resultNode)434 bool FindAccessibilityFocus(const RefPtr<AccessibilityNode>& node, RefPtr<AccessibilityNode>& resultNode)
435 {
436     CHECK_NULL_RETURN_NOLOG(node, false);
437     if (node->GetAccessibilityFocusedState()) {
438         resultNode = node;
439         LOGI("FindFocus nodeId(%{public}d)", resultNode->GetNodeId());
440         return true;
441     }
442     if (!node->GetChildList().empty()) {
443         for (const auto& item : node->GetChildList()) {
444             if (resultNode != nullptr) {
445                 return true;
446             }
447             if (FindAccessibilityFocus(item, resultNode)) {
448                 LOGI("FindFocus nodeId:%{public}d", item->GetNodeId());
449                 return true;
450             }
451         }
452     }
453 
454     return false;
455 }
456 
FindAccessibilityFocus(const RefPtr<NG::UINode> & node)457 RefPtr<NG::FrameNode> FindAccessibilityFocus(const RefPtr<NG::UINode>& node)
458 {
459     CHECK_NULL_RETURN_NOLOG(node, nullptr);
460     auto frameNode = AceType::DynamicCast<NG::FrameNode>(node);
461     if (frameNode) {
462         if (frameNode->GetRenderContext()->GetAccessibilityFocus().value_or(false)) {
463             LOGI("FindFocus nodeId(%{public}d)", node->GetAccessibilityId());
464             return frameNode;
465         }
466     }
467 
468     if (!node->GetChildren().empty()) {
469         for (const auto& child : node->GetChildren()) {
470             auto result = FindAccessibilityFocus(child);
471             if (result) {
472                 return result;
473             }
474         }
475     }
476     return nullptr;
477 }
478 
FindInputFocus(const RefPtr<AccessibilityNode> & node,RefPtr<AccessibilityNode> & resultNode)479 bool FindInputFocus(const RefPtr<AccessibilityNode>& node, RefPtr<AccessibilityNode>& resultNode)
480 {
481     CHECK_NULL_RETURN_NOLOG(node, false);
482     if (!node->GetFocusedState() && (node->GetParentId() != -1)) {
483         return false;
484     }
485     if (node->GetFocusedState()) {
486         resultNode = node;
487         LOGI("FindFocus nodeId:%{public}d", resultNode->GetNodeId());
488     }
489     if (!node->GetChildList().empty()) {
490         for (const auto& item : node->GetChildList()) {
491             if (FindInputFocus(item, resultNode)) {
492                 return true;
493             }
494         }
495     }
496     return node->GetFocusedState();
497 }
498 
FindInputFocus(const RefPtr<NG::UINode> & node)499 RefPtr<NG::FrameNode> FindInputFocus(const RefPtr<NG::UINode>& node)
500 {
501     auto frameNode = AceType::DynamicCast<NG::FrameNode>(node);
502     CHECK_NULL_RETURN_NOLOG(frameNode, nullptr);
503     if (!(frameNode->GetFocusHub() ? frameNode->GetFocusHub()->IsCurrentFocus() : false)) {
504         return nullptr;
505     }
506 
507     if (frameNode->GetFocusHub()->IsChild()) {
508         LOGI("FoundFocus nodeId(%{public}d)", node->GetAccessibilityId());
509         if (frameNode->IsInternal()) {
510             return frameNode->GetFocusParent();
511         }
512         return frameNode;
513     }
514 
515     auto focusHub = frameNode->GetFocusHub();
516     auto focusChildren = focusHub->GetChildren();
517     for (const auto& focusChild : focusChildren) {
518         auto childNode = FindInputFocus(focusChild->GetFrameNode());
519         if (childNode) {
520             return childNode;
521         }
522     }
523     return nullptr;
524 }
525 
FindText(const RefPtr<AccessibilityNode> & node,const std::string & text,std::list<RefPtr<AccessibilityNode>> & nodeList)526 void FindText(
527     const RefPtr<AccessibilityNode>& node, const std::string& text, std::list<RefPtr<AccessibilityNode>>& nodeList)
528 {
529     CHECK_NULL_VOID_NOLOG(node);
530     if (node->GetText().find(text) != std::string::npos) {
531         LOGI("FindText find nodeId(%{public}d)", node->GetNodeId());
532         nodeList.push_back(node);
533     }
534     if (!node->GetChildList().empty()) {
535         for (const auto& child : node->GetChildList()) {
536             FindText(child, text, nodeList);
537         }
538     }
539 }
540 
FindText(const RefPtr<NG::UINode> & node,const std::string & text,std::list<RefPtr<NG::FrameNode>> & nodeList)541 void FindText(const RefPtr<NG::UINode>& node, const std::string& text, std::list<RefPtr<NG::FrameNode>>& nodeList)
542 {
543     CHECK_NULL_VOID(node);
544 
545     auto frameNode = AceType::DynamicCast<NG::FrameNode>(node);
546     if (frameNode && !frameNode->IsInternal()) {
547         if (frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>()->GetAccessibilityText().find(text) !=
548             std::string::npos) {
549             LOGI("FindText find nodeId(%{public}d)", frameNode->GetAccessibilityId());
550             nodeList.push_back(frameNode);
551         }
552     }
553 
554     if (!node->GetChildren().empty()) {
555         for (const auto& child : node->GetChildren()) {
556             FindText(child, text, nodeList);
557         }
558     }
559 }
560 
GetInspectorById(const RefPtr<NG::FrameNode> & root,int32_t id)561 RefPtr<NG::FrameNode> GetInspectorById(const RefPtr<NG::FrameNode>& root, int32_t id)
562 {
563     CHECK_NULL_RETURN(root, nullptr);
564     std::queue<RefPtr<NG::UINode>> nodes;
565     nodes.push(root);
566     RefPtr<NG::FrameNode> frameNode;
567     while (!nodes.empty()) {
568         auto current = nodes.front();
569         nodes.pop();
570         frameNode = AceType::DynamicCast<NG::FrameNode>(current);
571         if (frameNode != nullptr) {
572             if (id == frameNode->GetAccessibilityId()) {
573                 return frameNode;
574             }
575         }
576         const auto& children = current->GetChildren();
577         for (const auto& child : children) {
578             nodes.push(child);
579         }
580     }
581     return nullptr;
582 }
583 
GetFrameNodeParent(const RefPtr<NG::UINode> & uiNode,RefPtr<NG::FrameNode> & parent)584 void GetFrameNodeParent(const RefPtr<NG::UINode>& uiNode, RefPtr<NG::FrameNode>& parent)
585 {
586     if (AceType::InstanceOf<NG::FrameNode>(uiNode)) {
587         auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
588         if (!frameNode->IsInternal()) {
589             parent = frameNode;
590             return;
591         }
592     }
593     CHECK_NULL_VOID(uiNode);
594     auto parentNode = uiNode->GetParent();
595     GetFrameNodeParent(parentNode, parent);
596 }
597 
CheckFrameNodeByAccessibilityLevel(const RefPtr<NG::FrameNode> & frameNode,bool isParent)598 bool CheckFrameNodeByAccessibilityLevel(const RefPtr<NG::FrameNode>& frameNode, bool isParent)
599 {
600     bool ret = false;
601     CHECK_NULL_RETURN(frameNode, false);
602     auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
603     CHECK_NULL_RETURN(accessibilityProperty, false);
604     auto uiNode = frameNode->GetParent();
605     RefPtr<NG::FrameNode> parentNode;
606     if (uiNode != nullptr) {
607         GetFrameNodeParent(uiNode, parentNode);
608     }
609 
610     if (isParent) {
611         if (accessibilityProperty->GetAccessibilityLevel() == IMPORTANT_NO_HIDE_DES) {
612             ret = false;
613             return ret;
614         }
615         if (!parentNode) {
616             if (accessibilityProperty->IsAccessibilityGroup()) {
617                 ret = false;
618             } else {
619                 ret = true;
620             }
621         } else {
622             if (accessibilityProperty->IsAccessibilityGroup()) {
623                 ret = false;
624             } else {
625                 ret = CheckFrameNodeByAccessibilityLevel(parentNode, true);
626             }
627         }
628     } else {
629         if (accessibilityProperty->GetAccessibilityLevel() == IMPORTANT_YES) {
630             ret = true;
631             if (!parentNode) {
632                 return ret;
633             }
634             auto parentAccessibilityProperty = parentNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
635             if (parentAccessibilityProperty->IsAccessibilityGroup()) {
636                 ret = false;
637             } else {
638                 ret = CheckFrameNodeByAccessibilityLevel(parentNode, true);
639             }
640         } else {
641             ret = false;
642         }
643     }
644     return ret;
645 }
646 
GetFrameNodeChildren(const RefPtr<NG::UINode> & uiNode,std::vector<int32_t> & children,int32_t pageId)647 void GetFrameNodeChildren(const RefPtr<NG::UINode>& uiNode, std::vector<int32_t>& children, int32_t pageId)
648 {
649     auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
650     if (AceType::InstanceOf<NG::FrameNode>(uiNode)) {
651         CHECK_NULL_VOID_NOLOG(frameNode->IsActive());
652         if (uiNode->GetTag() == "stage") {
653         } else if (uiNode->GetTag() == "page") {
654             if (uiNode->GetPageId() != pageId) {
655                 return;
656             }
657         } else if (!frameNode->IsInternal()) {
658             if (CheckFrameNodeByAccessibilityLevel(frameNode, false)) {
659                 children.emplace_back(uiNode->GetAccessibilityId());
660                 return;
661             }
662         }
663     }
664 
665     for (const auto& frameChild : uiNode->GetChildren()) {
666         GetFrameNodeChildren(frameChild, children, pageId);
667     }
668 }
669 
GetFrameNodeChildren(const RefPtr<NG::UINode> & uiNode,std::list<RefPtr<NG::FrameNode>> & children)670 void GetFrameNodeChildren(const RefPtr<NG::UINode>& uiNode, std::list<RefPtr<NG::FrameNode>>& children)
671 {
672     if (AceType::InstanceOf<NG::FrameNode>(uiNode)) {
673         auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
674         if (!frameNode->IsInternal()) {
675             if (CheckFrameNodeByAccessibilityLevel(frameNode, false)) {
676                 children.emplace_back(frameNode);
677                 return;
678             }
679         }
680     } else {
681         for (const auto& frameChild : uiNode->GetChildren()) {
682             GetFrameNodeChildren(frameChild, children);
683         }
684     }
685 }
686 
GetParentId(const RefPtr<NG::UINode> & uiNode)687 int32_t GetParentId(const RefPtr<NG::UINode>& uiNode)
688 {
689     auto parent = uiNode->GetParent();
690     while (parent) {
691         if (AceType::InstanceOf<NG::FrameNode>(parent)) {
692             return parent->GetAccessibilityId();
693         }
694         parent = parent->GetParent();
695     }
696     return INVALID_PARENT_ID;
697 }
698 
FillEventInfo(const RefPtr<NG::FrameNode> & node,AccessibilityEventInfo & eventInfo)699 void FillEventInfo(const RefPtr<NG::FrameNode>& node, AccessibilityEventInfo& eventInfo)
700 {
701     CHECK_NULL_VOID_NOLOG(node);
702     eventInfo.SetComponentType(node->GetTag());
703     eventInfo.SetPageId(node->GetPageId());
704     auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
705     CHECK_NULL_VOID(accessibilityProperty);
706     eventInfo.AddContent(accessibilityProperty->GetAccessibilityText());
707     eventInfo.SetItemCounts(accessibilityProperty->GetCollectionItemCounts());
708     eventInfo.SetBeginIndex(accessibilityProperty->GetBeginIndex());
709     eventInfo.SetEndIndex(accessibilityProperty->GetEndIndex());
710 }
711 
FillEventInfo(const RefPtr<AccessibilityNode> & node,AccessibilityEventInfo & eventInfo)712 void FillEventInfo(const RefPtr<AccessibilityNode>& node, AccessibilityEventInfo& eventInfo)
713 {
714     eventInfo.SetComponentType(node->GetTag());
715     if (node->GetTag() == LIST_TAG) {
716         eventInfo.SetItemCounts(node->GetListItemCounts());
717         eventInfo.SetBeginIndex(node->GetListBeginIndex());
718         eventInfo.SetEndIndex(node->GetListEndIndex());
719     }
720     eventInfo.SetPageId(node->GetPageId());
721     eventInfo.AddContent(node->GetText());
722     eventInfo.SetLatestContent(node->GetText());
723 }
724 
IsPopupSupported(const RefPtr<NG::PipelineContext> & pipeline,int32_t nodeId)725 inline bool IsPopupSupported(const RefPtr<NG::PipelineContext>& pipeline, int32_t nodeId)
726 {
727     CHECK_NULL_RETURN_NOLOG(pipeline, false);
728     auto overlayManager = pipeline->GetOverlayManager();
729     if (overlayManager) {
730         return overlayManager->HasPopupInfo(nodeId);
731     }
732     return false;
733 }
734 
UpdateSupportAction(const RefPtr<NG::FrameNode> & node,AccessibilityElementInfo & nodeInfo)735 void UpdateSupportAction(const RefPtr<NG::FrameNode>& node, AccessibilityElementInfo& nodeInfo)
736 {
737     CHECK_NULL_VOID_NOLOG(node);
738     auto gestureEventHub = node->GetEventHub<NG::EventHub>()->GetGestureEventHub();
739     if (gestureEventHub) {
740         nodeInfo.SetClickable(gestureEventHub->IsAccessibilityClickable());
741         if (gestureEventHub->IsAccessibilityClickable()) {
742             AccessibleAction action(ACCESSIBILITY_ACTION_CLICK, "ace");
743             nodeInfo.AddAction(action);
744         }
745         nodeInfo.SetLongClickable(gestureEventHub->IsAccessibilityLongClickable());
746         if (gestureEventHub->IsAccessibilityLongClickable()) {
747             AccessibleAction action(ACCESSIBILITY_ACTION_LONG_CLICK, "ace");
748             nodeInfo.AddAction(action);
749         }
750     }
751     if (nodeInfo.IsFocusable()) {
752         if (nodeInfo.IsFocused()) {
753             AccessibleAction action(ACCESSIBILITY_ACTION_CLEAR_FOCUS, "ace");
754             nodeInfo.AddAction(action);
755         } else {
756             AccessibleAction action(ACCESSIBILITY_ACTION_FOCUS, "ace");
757             nodeInfo.AddAction(action);
758         }
759     }
760 
761     if (nodeInfo.HasAccessibilityFocus()) {
762         AccessibleAction action(ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS, "ace");
763         nodeInfo.AddAction(action);
764     } else {
765         AccessibleAction action(ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS, "ace");
766         nodeInfo.AddAction(action);
767     }
768 }
769 
UpdateAccessibilityElementInfo(const RefPtr<NG::FrameNode> & node,AccessibilityElementInfo & nodeInfo)770 static void UpdateAccessibilityElementInfo(const RefPtr<NG::FrameNode>& node, AccessibilityElementInfo& nodeInfo)
771 {
772     CHECK_NULL_VOID_NOLOG(node);
773     auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
774     CHECK_NULL_VOID_NOLOG(accessibilityProperty);
775 
776     nodeInfo.SetContent(accessibilityProperty->GetAccessibilityText());
777     if (accessibilityProperty->HasRange()) {
778         RangeInfo rangeInfo = ConvertAccessibilityValue(accessibilityProperty->GetAccessibilityValue());
779         nodeInfo.SetRange(rangeInfo);
780     }
781     nodeInfo.SetHint(accessibilityProperty->GetHintText());
782     nodeInfo.SetTextLengthLimit(accessibilityProperty->GetTextLengthLimit());
783     nodeInfo.SetChecked(accessibilityProperty->IsChecked());
784     nodeInfo.SetSelected(accessibilityProperty->IsSelected());
785     nodeInfo.SetPassword(accessibilityProperty->IsPassword());
786     nodeInfo.SetPluraLineSupported(accessibilityProperty->IsMultiLine());
787     nodeInfo.SetHinting(accessibilityProperty->IsHint());
788     nodeInfo.SetCurrentIndex(accessibilityProperty->GetCurrentIndex());
789     nodeInfo.SetBeginIndex(accessibilityProperty->GetBeginIndex());
790     nodeInfo.SetEndIndex(accessibilityProperty->GetEndIndex());
791     auto tag = node->GetTag();
792     if (tag == V2::TOAST_ETS_TAG || tag == V2::POPUP_ETS_TAG || tag == V2::DIALOG_ETS_TAG ||
793         tag == V2::ACTION_SHEET_DIALOG_ETS_TAG || tag == V2::ALERT_DIALOG_ETS_TAG || tag == V2::MENU_ETS_TAG ||
794         tag == "SelectMenu") {
795         nodeInfo.SetLiveRegion(1);
796     }
797     nodeInfo.SetContentInvalid(accessibilityProperty->GetContentInvalid());
798     nodeInfo.SetError(accessibilityProperty->GetErrorText());
799     nodeInfo.SetSelectedBegin(accessibilityProperty->GetTextSelectionStart());
800     nodeInfo.SetSelectedEnd(accessibilityProperty->GetTextSelectionEnd());
801     nodeInfo.SetInputType(static_cast<int>(accessibilityProperty->GetTextInputType()));
802     nodeInfo.SetItemCounts(accessibilityProperty->GetCollectionItemCounts());
803 
804     GridInfo gridInfo(accessibilityProperty->GetCollectionInfo().rows,
805         accessibilityProperty->GetCollectionInfo().columns, accessibilityProperty->GetCollectionInfo().selectMode);
806     nodeInfo.SetGrid(gridInfo);
807 
808     int32_t row = accessibilityProperty->GetCollectionItemInfo().row;
809     int32_t column = accessibilityProperty->GetCollectionItemInfo().column;
810     int32_t rowSpan = accessibilityProperty->GetCollectionItemInfo().rowSpan;
811     int32_t columnSpan = accessibilityProperty->GetCollectionItemInfo().columnSpan;
812     bool heading = accessibilityProperty->GetCollectionItemInfo().heading;
813     GridItemInfo gridItemInfo(row, rowSpan, column, columnSpan, heading, nodeInfo.IsSelected());
814     nodeInfo.SetGridItem(gridItemInfo);
815 
816     if (nodeInfo.IsEnabled()) {
817         nodeInfo.SetCheckable(accessibilityProperty->IsCheckable());
818         nodeInfo.SetScrollable(accessibilityProperty->IsScrollable());
819         nodeInfo.SetEditable(accessibilityProperty->IsEditable());
820         nodeInfo.SetDeletable(accessibilityProperty->IsDeletable());
821         UpdateSupportAction(node, nodeInfo);
822         accessibilityProperty->ResetSupportAction();
823         auto supportAceActions = accessibilityProperty->GetSupportAction();
824         for (auto it = supportAceActions.begin(); it != supportAceActions.end(); ++it) {
825             AccessibleAction action(ConvertAceAction(*it), "ace");
826             nodeInfo.AddAction(action);
827         }
828     }
829 }
830 
UpdateAccessibilityElementInfo(const RefPtr<NG::FrameNode> & node,const CommonProperty & commonProperty,AccessibilityElementInfo & nodeInfo,const RefPtr<NG::PipelineContext> & ngPipeline)831 void UpdateAccessibilityElementInfo(const RefPtr<NG::FrameNode>& node, const CommonProperty& commonProperty,
832     AccessibilityElementInfo& nodeInfo, const RefPtr<NG::PipelineContext>& ngPipeline)
833 {
834     CHECK_NULL_VOID_NOLOG(node);
835     nodeInfo.SetParent(GetParentId(node));
836     std::vector<int32_t> children;
837     for (const auto& item : node->GetChildren()) {
838         GetFrameNodeChildren(item, children, commonProperty.pageId);
839     }
840     for (const auto& child : children) {
841         nodeInfo.AddChild(child);
842     }
843 
844     nodeInfo.SetAccessibilityId(node->GetAccessibilityId());
845     nodeInfo.SetComponentType(node->GetTag());
846 
847     nodeInfo.SetEnabled(node->GetFocusHub() ? node->GetFocusHub()->IsEnabled() : true);
848     nodeInfo.SetFocused(node->GetFocusHub() ? node->GetFocusHub()->IsCurrentFocus() : false);
849     nodeInfo.SetAccessibilityFocus(node->GetRenderContext()->GetAccessibilityFocus().value_or(false));
850     nodeInfo.SetInspectorKey(node->GetInspectorId().value_or(""));
851     nodeInfo.SetVisible(node->IsVisible());
852     if (node->IsVisible()) {
853         auto rect = node->GetTransformRectRelativeToWindow();
854         auto left = rect.Left() + commonProperty.windowLeft;
855         auto top = rect.Top() + commonProperty.windowTop;
856         auto right = rect.Right() + commonProperty.windowLeft;
857         auto bottom = rect.Bottom() + commonProperty.windowTop;
858         Accessibility::Rect bounds { left, top, right, bottom };
859         nodeInfo.SetRectInScreen(bounds);
860         LOGD("UpdateAccessibilityElementInfo nodeId:%{public}d, tag:%{public}s rect:left:%{public}f, top:%{public}f, "
861              "right:%{public}f, bottom:%{public}f",
862             node->GetAccessibilityId(), node->GetTag().c_str(), left, top, right, bottom);
863     }
864 
865     nodeInfo.SetWindowId(commonProperty.windowId);
866     nodeInfo.SetPageId(node->GetPageId());
867     nodeInfo.SetPagePath(commonProperty.pagePath);
868     nodeInfo.SetBundleName(AceApplicationInfo::GetInstance().GetPackageName());
869 
870     if (nodeInfo.IsEnabled()) {
871         nodeInfo.SetFocusable(node->GetFocusHub() ? node->GetFocusHub()->IsFocusable() : false);
872         nodeInfo.SetPopupSupported(IsPopupSupported(ngPipeline, node->GetId()));
873     }
874     nodeInfo.SetComponentResourceId(node->GetInspectorId().value_or(""));
875     UpdateAccessibilityElementInfo(node, nodeInfo);
876 }
877 
CanAccessibilityFocusedNG(const RefPtr<NG::FrameNode> & node)878 bool CanAccessibilityFocusedNG(const RefPtr<NG::FrameNode>& node)
879 {
880     CHECK_NULL_RETURN(node, false);
881     auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
882     CHECK_NULL_RETURN(accessibilityProperty, false);
883     return !node->IsRootNode() &&
884            node->GetLayoutProperty()->GetVisibilityValue(VisibleType::VISIBLE) == VisibleType::VISIBLE &&
885            accessibilityProperty->GetAccessibilityLevel() != IMPORTANT_NO &&
886            accessibilityProperty->GetAccessibilityLevel() != IMPORTANT_NO_HIDE_DES;
887 }
888 // focus move search
AddFocusableNode(std::list<RefPtr<NG::FrameNode>> & nodeList,const RefPtr<NG::FrameNode> & node)889 void AddFocusableNode(std::list<RefPtr<NG::FrameNode>>& nodeList, const RefPtr<NG::FrameNode>& node)
890 {
891     auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
892     CHECK_NULL_VOID(accessibilityProperty);
893     const std::string level = accessibilityProperty->GetAccessibilityLevel();
894     if (CanAccessibilityFocusedNG(node)) {
895         nodeList.emplace_back(node);
896     }
897 
898     if (!accessibilityProperty->IsAccessibilityGroup() && level != IMPORTANT_NO_HIDE_DES) {
899         std::list<RefPtr<NG::FrameNode>> children;
900         for (const auto& child : node->GetChildren()) {
901             GetFrameNodeChildren(child, children);
902         }
903 
904         for (const auto& child : children) {
905             AddFocusableNode(nodeList, child);
906         }
907     }
908 }
909 
GetNextFocusableNode(const std::list<RefPtr<NG::FrameNode>> & nodeList,RefPtr<NG::FrameNode> & node)910 RefPtr<NG::FrameNode> GetNextFocusableNode(
911     const std::list<RefPtr<NG::FrameNode>>& nodeList, RefPtr<NG::FrameNode>& node)
912 {
913     auto nodeItem = nodeList.begin();
914     for (; nodeItem != nodeList.end(); nodeItem++) {
915         if ((*nodeItem)->GetAccessibilityId() == node->GetAccessibilityId()) {
916             break;
917         }
918     }
919 
920     if (nodeItem != nodeList.end()) {
921         if (++nodeItem != nodeList.end()) {
922             return (*nodeItem);
923         }
924     }
925     if (!nodeList.empty()) {
926         return (*nodeList.begin());
927     }
928 
929     return nullptr;
930 }
931 
GetPreviousFocusableNode(const std::list<RefPtr<NG::FrameNode>> & nodeList,RefPtr<NG::FrameNode> & node)932 RefPtr<NG::FrameNode> GetPreviousFocusableNode(
933     const std::list<RefPtr<NG::FrameNode>>& nodeList, RefPtr<NG::FrameNode>& node)
934 {
935     auto nodeItem = nodeList.rbegin();
936     for (; nodeItem != nodeList.rend(); nodeItem++) {
937         if ((*nodeItem)->GetAccessibilityId() == node->GetAccessibilityId()) {
938             break;
939         }
940     }
941 
942     if (nodeItem != nodeList.rend()) {
943         if (++nodeItem != nodeList.rend()) {
944             return (*nodeItem);
945         }
946     }
947     if (!nodeList.empty()) {
948         return (*nodeList.rbegin());
949     }
950 
951     return nullptr;
952 }
953 
FindNodeInRelativeDirection(const std::list<RefPtr<NG::FrameNode>> & nodeList,RefPtr<NG::FrameNode> & node,int direction)954 RefPtr<NG::FrameNode> FindNodeInRelativeDirection(
955     const std::list<RefPtr<NG::FrameNode>>& nodeList, RefPtr<NG::FrameNode>& node, int direction)
956 {
957     switch (direction) {
958         case FocusMoveDirection::FORWARD:
959             return GetNextFocusableNode(nodeList, node);
960         case FocusMoveDirection::BACKWARD:
961             return GetPreviousFocusableNode(nodeList, node);
962         default:
963             break;
964     }
965 
966     return nullptr;
967 }
968 
FindNodeInAbsoluteDirection(const std::list<RefPtr<NG::FrameNode>> & nodeList,RefPtr<NG::FrameNode> & node,const int direction)969 RefPtr<NG::FrameNode> FindNodeInAbsoluteDirection(
970     const std::list<RefPtr<NG::FrameNode>>& nodeList, RefPtr<NG::FrameNode>& node, const int direction)
971 {
972     NG::RectF rect = node->GetTransformRectRelativeToWindow();
973     auto left = rect.Left();
974     auto top = rect.Top();
975     auto width = rect.Width();
976     auto height = rect.Height();
977     Rect tempBest(left, top, width, height);
978     auto nodeRect = tempBest;
979     switch (direction) {
980         case FocusMoveDirection::LEFT:
981             tempBest.SetLeft(left + width + 1);
982             break;
983         case FocusMoveDirection::RIGHT:
984             tempBest.SetLeft(left - width - 1);
985             break;
986         case FocusMoveDirection::UP:
987             tempBest.SetTop(top + height + 1);
988             break;
989         case FocusMoveDirection::DOWN:
990             tempBest.SetTop(top - height - 1);
991             break;
992         default:
993             break;
994     }
995 
996     RefPtr<NG::FrameNode> nearestNode = nullptr;
997     for (const auto& nodeItem : nodeList) {
998         if (nodeItem->GetAccessibilityId() == node->GetAccessibilityId() || nodeItem->IsRootNode()) {
999             continue;
1000         }
1001         rect = nodeItem->GetTransformRectRelativeToWindow();
1002         rect.SetOffset(nodeItem->GetTransformRelativeOffset());
1003         Rect itemRect(rect.Left(), rect.Top(), rect.Width(), rect.Height());
1004         if (CheckBetterRect(nodeRect, direction, itemRect, tempBest)) {
1005             tempBest = itemRect;
1006             nearestNode = nodeItem;
1007         }
1008     }
1009     LOGI("found %{public}d", nearestNode ? nearestNode->GetAccessibilityId() : -1);
1010     return nearestNode;
1011 }
1012 
1013 // execute action
RequestFocus(RefPtr<NG::FrameNode> & frameNode)1014 bool RequestFocus(RefPtr<NG::FrameNode>& frameNode)
1015 {
1016     auto focusHub = frameNode->GetFocusHub();
1017     CHECK_NULL_RETURN_NOLOG(focusHub, false);
1018     return focusHub->RequestFocusImmediately();
1019 }
1020 
LostFocus(const RefPtr<NG::FrameNode> & frameNode)1021 bool LostFocus(const RefPtr<NG::FrameNode>& frameNode)
1022 {
1023     CHECK_NULL_RETURN_NOLOG(frameNode, false);
1024     auto focusHub = frameNode->GetFocusHub();
1025     CHECK_NULL_RETURN_NOLOG(focusHub, false);
1026     focusHub->LostFocus();
1027     return true;
1028 }
1029 
ActClick(RefPtr<NG::FrameNode> & frameNode)1030 bool ActClick(RefPtr<NG::FrameNode>& frameNode)
1031 {
1032     auto gesture = frameNode->GetEventHub<NG::EventHub>()->GetGestureEventHub();
1033     CHECK_NULL_RETURN_NOLOG(gesture, false);
1034     return gesture->ActClick();
1035 }
1036 
ActLongClick(RefPtr<NG::FrameNode> & frameNode)1037 bool ActLongClick(RefPtr<NG::FrameNode>& frameNode)
1038 {
1039     auto gesture = frameNode->GetEventHub<NG::EventHub>()->GetGestureEventHub();
1040     CHECK_NULL_RETURN_NOLOG(gesture, false);
1041     return gesture->ActLongClick();
1042 }
1043 
ClearAccessibilityFocus(const RefPtr<NG::FrameNode> & root,int32_t focusNodeId)1044 void ClearAccessibilityFocus(const RefPtr<NG::FrameNode>& root, int32_t focusNodeId)
1045 {
1046     auto oldFocusNode = GetInspectorById(root, focusNodeId);
1047     CHECK_NULL_VOID_NOLOG(oldFocusNode);
1048     oldFocusNode->GetRenderContext()->UpdateAccessibilityFocus(false);
1049 }
1050 
ActAccessibilityFocus(int32_t elementId,RefPtr<NG::FrameNode> & frameNode,RefPtr<NG::PipelineContext> & context,NodeId & currentFocusNodeId,bool isNeedClear)1051 bool ActAccessibilityFocus(int32_t elementId, RefPtr<NG::FrameNode>& frameNode, RefPtr<NG::PipelineContext>& context,
1052     NodeId& currentFocusNodeId, bool isNeedClear)
1053 {
1054     CHECK_NULL_RETURN(frameNode, false);
1055     auto renderContext = frameNode->GetRenderContext();
1056     CHECK_NULL_RETURN(renderContext, false);
1057     if (isNeedClear) {
1058         if (elementId != currentFocusNodeId) {
1059             return false;
1060         }
1061         renderContext->UpdateAccessibilityFocus(false);
1062         currentFocusNodeId = -1;
1063         return true;
1064     }
1065     if (elementId == currentFocusNodeId) {
1066         LOGW("This node is focused.");
1067         return false;
1068     }
1069     Framework::ClearAccessibilityFocus(context->GetRootElement(), currentFocusNodeId);
1070     renderContext->UpdateAccessibilityFocus(true);
1071     currentFocusNodeId = frameNode->GetAccessibilityId();
1072     return true;
1073 }
1074 
GetSupportAction(const std::unordered_set<AceAction> & supportAceActions)1075 inline string GetSupportAction(const std::unordered_set<AceAction>& supportAceActions)
1076 {
1077     std::string actionForDump;
1078     for (const auto& action : supportAceActions) {
1079         if (!actionForDump.empty()) {
1080             actionForDump.append(",");
1081         }
1082         actionForDump.append(std::to_string(static_cast<int32_t>(action)));
1083     }
1084     return actionForDump;
1085 }
1086 
ConvertActionTypeToString(ActionType action)1087 static std::string ConvertActionTypeToString(ActionType action)
1088 {
1089     switch (action) {
1090         case ActionType::ACCESSIBILITY_ACTION_FOCUS:
1091             return "ACCESSIBILITY_ACTION_FOCUS";
1092         case ActionType::ACCESSIBILITY_ACTION_CLEAR_FOCUS:
1093             return "ACCESSIBILITY_ACTION_CLEAR_FOCUS";
1094         case ActionType::ACCESSIBILITY_ACTION_SELECT:
1095             return "ACCESSIBILITY_ACTION_SELECT";
1096         case ActionType::ACCESSIBILITY_ACTION_CLEAR_SELECTION:
1097             return "ACCESSIBILITY_ACTION_CLEAR_SELECTION";
1098         case ActionType::ACCESSIBILITY_ACTION_CLICK:
1099             return "ACCESSIBILITY_ACTION_CLICK";
1100         case ActionType::ACCESSIBILITY_ACTION_LONG_CLICK:
1101             return "ACCESSIBILITY_ACTION_LONG_CLICK";
1102         case ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS:
1103             return "ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS";
1104         case ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS:
1105             return "ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS";
1106         case ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD:
1107             return "ACCESSIBILITY_ACTION_SCROLL_FORWARD";
1108         case ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD:
1109             return "ACCESSIBILITY_ACTION_SCROLL_BACKWARD";
1110         case ActionType::ACCESSIBILITY_ACTION_COPY:
1111             return "ACCESSIBILITY_ACTION_COPY";
1112         case ActionType::ACCESSIBILITY_ACTION_PASTE:
1113             return "ACCESSIBILITY_ACTION_PASTE";
1114         case ActionType::ACCESSIBILITY_ACTION_CUT:
1115             return "ACCESSIBILITY_ACTION_CUT";
1116         case ActionType::ACCESSIBILITY_ACTION_SET_SELECTION:
1117             return "ACCESSIBILITY_ACTION_SET_SELECTION";
1118         case ActionType::ACCESSIBILITY_ACTION_SET_TEXT:
1119             return "ACCESSIBILITY_ACTION_SET_TEXT";
1120         case ActionType::ACCESSIBILITY_ACTION_NEXT_TEXT:
1121             return "ACCESSIBILITY_ACTION_NEXT_TEXT";
1122         case ActionType::ACCESSIBILITY_ACTION_PREVIOUS_TEXT:
1123             return "ACCESSIBILITY_ACTION_PREVIOUS_TEXT";
1124         default:
1125             return "ACCESSIBILITY_ACTION_INVALID";
1126     }
1127 }
1128 
ConvertAccessibilityAction(ActionType accessibilityAction)1129 static AceAction ConvertAccessibilityAction(ActionType accessibilityAction)
1130 {
1131     static const ActionTable actionTable[] = {
1132         { AceAction::ACTION_CLICK, ActionType::ACCESSIBILITY_ACTION_CLICK },
1133         { AceAction::ACTION_LONG_CLICK, ActionType::ACCESSIBILITY_ACTION_LONG_CLICK },
1134         { AceAction::ACTION_SCROLL_FORWARD, ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD },
1135         { AceAction::ACTION_SCROLL_BACKWARD, ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD },
1136         { AceAction::ACTION_FOCUS, ActionType::ACCESSIBILITY_ACTION_FOCUS },
1137         { AceAction::ACTION_CLEAR_FOCUS, ActionType::ACCESSIBILITY_ACTION_CLEAR_FOCUS },
1138         { AceAction::ACTION_ACCESSIBILITY_FOCUS, ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS },
1139         { AceAction::ACTION_CLEAR_ACCESSIBILITY_FOCUS, ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS },
1140         { AceAction::ACTION_NEXT_AT_MOVEMENT_GRANULARITY, ActionType::ACCESSIBILITY_ACTION_NEXT_TEXT },
1141         { AceAction::ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, ActionType::ACCESSIBILITY_ACTION_PREVIOUS_TEXT },
1142         { AceAction::ACTION_SET_TEXT, ActionType::ACCESSIBILITY_ACTION_SET_TEXT },
1143         { AceAction::ACTION_COPY, ActionType::ACCESSIBILITY_ACTION_COPY },
1144         { AceAction::ACTION_PASTE, ActionType::ACCESSIBILITY_ACTION_PASTE },
1145         { AceAction::ACTION_CUT, ActionType::ACCESSIBILITY_ACTION_CUT },
1146         { AceAction::ACTION_SELECT, ActionType::ACCESSIBILITY_ACTION_SELECT },
1147         { AceAction::ACTION_CLEAR_SELECTION, ActionType::ACCESSIBILITY_ACTION_CLEAR_SELECTION },
1148         { AceAction::ACTION_SET_SELECTION, ActionType::ACCESSIBILITY_ACTION_SET_SELECTION },
1149     };
1150     for (const auto& item : actionTable) {
1151         if (accessibilityAction == item.action) {
1152             return item.aceAction;
1153         }
1154     }
1155     return AceAction::ACTION_NONE;
1156 }
1157 
DumpSupportActionNG(const AccessibilityElementInfo & nodeInfo)1158 static void DumpSupportActionNG(const AccessibilityElementInfo& nodeInfo)
1159 {
1160     DumpLog::GetInstance().AddDesc(
1161         "support action instructions: use command to make application components perform corresponding action");
1162     DumpLog::GetInstance().AddDesc(
1163         "use support action command: aa dump -i [AbilityRecord] -c -inspector [AccessibilityId] [AceAction]");
1164     std::string actionForDump;
1165     for (const auto& action : nodeInfo.GetActionList()) {
1166         if (!actionForDump.empty()) {
1167             actionForDump.append(",");
1168         }
1169         actionForDump.append(ConvertActionTypeToString(action.GetActionType()));
1170         actionForDump.append(": ");
1171         actionForDump.append(std::to_string(static_cast<int32_t>(ConvertAccessibilityAction(action.GetActionType()))));
1172     }
1173     DumpLog::GetInstance().AddDesc("support action: ", actionForDump);
1174 }
1175 
DumpContentListNG(const AccessibilityElementInfo & nodeInfo)1176 inline void DumpContentListNG(const AccessibilityElementInfo& nodeInfo)
1177 {
1178     std::vector<std::string> contentList;
1179     nodeInfo.GetContentList(contentList);
1180     std::string contents;
1181     for (auto content : contentList) {
1182         if (!contents.empty()) {
1183             contents.append(",");
1184         }
1185         contents.append(content);
1186     }
1187     DumpLog::GetInstance().AddDesc("content list: ", contents);
1188 }
1189 
DumpAccessibilityPropertyNG(const AccessibilityElementInfo & nodeInfo)1190 static void DumpAccessibilityPropertyNG(const AccessibilityElementInfo& nodeInfo)
1191 {
1192     DumpLog::GetInstance().AddDesc("checked: ", BoolToString(nodeInfo.IsChecked()));
1193     DumpLog::GetInstance().AddDesc("selected: ", BoolToString(nodeInfo.IsSelected()));
1194     DumpLog::GetInstance().AddDesc("checkable: ", BoolToString(nodeInfo.IsCheckable()));
1195     DumpLog::GetInstance().AddDesc("scrollable: ", BoolToString(nodeInfo.IsScrollable()));
1196     DumpLog::GetInstance().AddDesc("accessibility hint: ", BoolToString(nodeInfo.IsGivingHint()));
1197     DumpLog::GetInstance().AddDesc("hint text: ", nodeInfo.GetHint());
1198     DumpLog::GetInstance().AddDesc("error text: ", nodeInfo.GetError());
1199     DumpLog::GetInstance().AddDesc("max text length: ", nodeInfo.GetTextLengthLimit());
1200     DumpLog::GetInstance().AddDesc("text selection start: ", nodeInfo.GetSelectedBegin());
1201     DumpLog::GetInstance().AddDesc("text selection end: ", nodeInfo.GetSelectedEnd());
1202     DumpLog::GetInstance().AddDesc("is multi line: ", BoolToString(nodeInfo.IsPluraLineSupported()));
1203     DumpLog::GetInstance().AddDesc("is password: ", BoolToString(nodeInfo.IsPassword()));
1204     DumpLog::GetInstance().AddDesc(
1205         "text input type: ", ConvertInputTypeToString(static_cast<AceTextCategory>(nodeInfo.GetInputType())));
1206 
1207     DumpLog::GetInstance().AddDesc("min value: ", nodeInfo.GetRange().GetMin());
1208     DumpLog::GetInstance().AddDesc("max value: ", nodeInfo.GetRange().GetMax());
1209     DumpLog::GetInstance().AddDesc("current value: ", nodeInfo.GetRange().GetCurrent());
1210     DumpLog::GetInstance().AddDesc("gird info rows: ", nodeInfo.GetGrid().GetRowCount());
1211     DumpLog::GetInstance().AddDesc("gird info columns: ", nodeInfo.GetGrid().GetColumnCount());
1212     DumpLog::GetInstance().AddDesc("gird info select mode: ", nodeInfo.GetGrid().GetSelectionMode());
1213     DumpLog::GetInstance().AddDesc("gird item info, row: ", nodeInfo.GetGridItem().GetRowIndex());
1214     DumpLog::GetInstance().AddDesc("gird item info, column: ", nodeInfo.GetGridItem().GetColumnIndex());
1215     DumpLog::GetInstance().AddDesc("gird item info, rowSpan: ", nodeInfo.GetGridItem().GetRowSpan());
1216     DumpLog::GetInstance().AddDesc("gird item info, columnSpan: ", nodeInfo.GetGridItem().GetColumnSpan());
1217     DumpLog::GetInstance().AddDesc("gird item info, is heading: ", nodeInfo.GetGridItem().IsHeading());
1218     DumpLog::GetInstance().AddDesc("gird item info, selected: ", nodeInfo.GetGridItem().IsSelected());
1219     DumpLog::GetInstance().AddDesc("current index: ", nodeInfo.GetCurrentIndex());
1220     DumpLog::GetInstance().AddDesc("begin index: ", nodeInfo.GetBeginIndex());
1221     DumpLog::GetInstance().AddDesc("end index: ", nodeInfo.GetEndIndex());
1222     DumpLog::GetInstance().AddDesc("collection item counts: ", nodeInfo.GetItemCounts());
1223     DumpLog::GetInstance().AddDesc("editable: ", BoolToString(nodeInfo.IsEditable()));
1224     DumpLog::GetInstance().AddDesc("is essential: ", BoolToString(nodeInfo.IsEssential()));
1225     DumpLog::GetInstance().AddDesc("deletable: ", nodeInfo.IsDeletable());
1226     DumpLog::GetInstance().AddDesc("live region: ", nodeInfo.GetLiveRegion());
1227     DumpLog::GetInstance().AddDesc("content description: ", nodeInfo.GetDescriptionInfo());
1228     DumpLog::GetInstance().AddDesc("content invalid: ", BoolToString(nodeInfo.GetContentInvalid()));
1229     DumpLog::GetInstance().AddDesc("accessibility label: ", nodeInfo.GetLabeledAccessibilityId());
1230     DumpLog::GetInstance().AddDesc(
1231         "trigger action: ", static_cast<int32_t>(ConvertAccessibilityAction(nodeInfo.GetTriggerAction())));
1232     DumpLog::GetInstance().AddDesc("text move step: " + std::to_string(nodeInfo.GetTextMovementStep()));
1233     DumpSupportActionNG(nodeInfo);
1234     DumpContentListNG(nodeInfo);
1235     DumpLog::GetInstance().AddDesc("latest content: ", nodeInfo.GetLatestContent());
1236 }
1237 
ChildernToString(const vector<int32_t> & children)1238 inline string ChildernToString(const vector<int32_t>& children)
1239 {
1240     std::string ids;
1241     for (auto child : children) {
1242         if (!ids.empty()) {
1243             ids.append(",");
1244         }
1245         ids.append(std::to_string(child));
1246     }
1247     return ids;
1248 }
1249 
DumpRectNG(const Accessibility::Rect & rect)1250 inline void DumpRectNG(const Accessibility::Rect& rect)
1251 {
1252     DumpLog::GetInstance().AddDesc(
1253         "width: ", std::to_string(rect.GetRightBottomXScreenPostion() - rect.GetLeftTopXScreenPostion()));
1254     DumpLog::GetInstance().AddDesc(
1255         "height: ", std::to_string(rect.GetRightBottomYScreenPostion() - rect.GetLeftTopYScreenPostion()));
1256     DumpLog::GetInstance().AddDesc("left: ", std::to_string(rect.GetLeftTopXScreenPostion()));
1257     DumpLog::GetInstance().AddDesc("top: ", std::to_string(rect.GetLeftTopYScreenPostion()));
1258     DumpLog::GetInstance().AddDesc("right: ", std::to_string(rect.GetRightBottomXScreenPostion()));
1259     DumpLog::GetInstance().AddDesc("bottom: ", std::to_string(rect.GetRightBottomYScreenPostion()));
1260 }
1261 
DumpCommonPropertyNG(const AccessibilityElementInfo & nodeInfo)1262 static void DumpCommonPropertyNG(const AccessibilityElementInfo& nodeInfo)
1263 {
1264     DumpLog::GetInstance().AddDesc("ID: ", nodeInfo.GetAccessibilityId());
1265     DumpLog::GetInstance().AddDesc("parent ID: ", nodeInfo.GetParentNodeId());
1266     DumpLog::GetInstance().AddDesc("child IDs: ", ChildernToString(nodeInfo.GetChildIds()));
1267     DumpLog::GetInstance().AddDesc("component type: ", nodeInfo.GetComponentType());
1268     DumpLog::GetInstance().AddDesc("text: ", nodeInfo.GetContent());
1269     DumpLog::GetInstance().AddDesc("window id: " + std::to_string(nodeInfo.GetWindowId()));
1270     DumpRectNG(nodeInfo.GetRectInScreen());
1271 
1272     DumpLog::GetInstance().AddDesc("enabled: ", BoolToString(nodeInfo.IsEnabled()));
1273     DumpLog::GetInstance().AddDesc("focusable: ", BoolToString(nodeInfo.IsFocusable()));
1274     DumpLog::GetInstance().AddDesc("focused: ", BoolToString(nodeInfo.IsFocused()));
1275     DumpLog::GetInstance().AddDesc("visible: ", BoolToString(nodeInfo.IsVisible()));
1276     DumpLog::GetInstance().AddDesc("accessibility focused: ", BoolToString(nodeInfo.HasAccessibilityFocus()));
1277     DumpLog::GetInstance().AddDesc("inspector key: ", nodeInfo.GetInspectorKey());
1278     DumpLog::GetInstance().AddDesc("bundle name: ", nodeInfo.GetBundleName());
1279     DumpLog::GetInstance().AddDesc("page id: " + std::to_string(nodeInfo.GetPageId()));
1280     DumpLog::GetInstance().AddDesc("page path: ", nodeInfo.GetPagePath());
1281     DumpLog::GetInstance().AddDesc("is valid element: ", BoolToString(nodeInfo.IsValidElement()));
1282     DumpLog::GetInstance().AddDesc("resource name: ", nodeInfo.GetComponentResourceId());
1283 
1284     DumpLog::GetInstance().AddDesc("clickable: ", BoolToString(nodeInfo.IsClickable()));
1285     DumpLog::GetInstance().AddDesc("long clickable: ", BoolToString(nodeInfo.IsLongClickable()));
1286     DumpLog::GetInstance().AddDesc("popup supported: ", BoolToString(nodeInfo.IsPopupSupported()));
1287 }
1288 } // namespace
1289 
~JsAccessibilityManager()1290 JsAccessibilityManager::~JsAccessibilityManager()
1291 {
1292     auto eventType = AccessibilityStateEventType::EVENT_ACCESSIBILITY_STATE_CHANGED;
1293 
1294     UnsubscribeStateObserver(eventType);
1295     UnsubscribeToastObserver();
1296 
1297     DeregisterInteractionOperation();
1298 }
OnConfigChanged(const AccessibilityConfig::CONFIG_ID id,const AccessibilityConfig::ConfigValue & value)1299 void JsAccessibilityManager::ToastAccessibilityConfigObserver::OnConfigChanged(
1300     const AccessibilityConfig::CONFIG_ID id, const AccessibilityConfig::ConfigValue& value)
1301 {
1302     LOGD("accessibility content timeout changed:%{public}u", value.contentTimeout);
1303     AceApplicationInfo::GetInstance().SetBarrierfreeDuration((int32_t)value.contentTimeout);
1304 }
1305 
SubscribeToastObserver()1306 bool JsAccessibilityManager::SubscribeToastObserver()
1307 {
1308     LOGD("SubscribeToastObserver");
1309     if (!toastObserver_) {
1310         toastObserver_ = std::make_shared<ToastAccessibilityConfigObserver>();
1311     }
1312     CHECK_NULL_RETURN_NOLOG(toastObserver_, false);
1313     auto& config = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1314     bool isSuccess = config.InitializeContext();
1315     if (!isSuccess) {
1316         LOGE("AccessibilityConfig InitializeContext failed");
1317         return false;
1318     }
1319     config.SubscribeConfigObserver(CONFIG_CONTENT_TIMEOUT, toastObserver_);
1320     return true;
1321 }
1322 
UnsubscribeToastObserver()1323 bool JsAccessibilityManager::UnsubscribeToastObserver()
1324 {
1325     LOGI("UnsubscribeToastObserver");
1326     CHECK_NULL_RETURN_NOLOG(toastObserver_, false);
1327     auto& config = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1328     bool isSuccess = config.InitializeContext();
1329     if (!isSuccess) {
1330         LOGE("AccessibilityConfig InitializeContext failed");
1331         return false;
1332     }
1333     config.UnsubscribeConfigObserver(CONFIG_CONTENT_TIMEOUT, toastObserver_);
1334     return true;
1335 }
1336 
SubscribeStateObserver(int eventType)1337 bool JsAccessibilityManager::SubscribeStateObserver(int eventType)
1338 {
1339     LOGD("SubscribeStateObserver");
1340     if (!stateObserver_) {
1341         stateObserver_ = std::make_shared<JsAccessibilityStateObserver>();
1342     }
1343 
1344     stateObserver_->SetHandler(WeakClaim(this));
1345 
1346     auto instance = AccessibilitySystemAbilityClient::GetInstance();
1347     CHECK_NULL_RETURN_NOLOG(instance, false);
1348     Accessibility::RetError ret = instance->SubscribeStateObserver(stateObserver_, eventType);
1349     LOGD("SubscribeStateObserver:%{public}d", ret);
1350     return ret == RET_OK;
1351 }
1352 
UnsubscribeStateObserver(int eventType)1353 bool JsAccessibilityManager::UnsubscribeStateObserver(int eventType)
1354 {
1355     LOGI("UnsubscribeStateObserver");
1356     CHECK_NULL_RETURN_NOLOG(stateObserver_, false);
1357     std::shared_ptr<AccessibilitySystemAbilityClient> instance = AccessibilitySystemAbilityClient::GetInstance();
1358     CHECK_NULL_RETURN_NOLOG(instance, false);
1359     Accessibility::RetError ret = instance->UnsubscribeStateObserver(stateObserver_, eventType);
1360     LOGI("UnsubscribeStateObserver:%{public}d", ret);
1361     return ret == RET_OK;
1362 }
1363 
InitializeCallback()1364 void JsAccessibilityManager::InitializeCallback()
1365 {
1366     LOGD("InitializeCallback");
1367     if (IsRegister()) {
1368         return;
1369     }
1370 
1371     auto pipelineContext = GetPipelineContext().Upgrade();
1372     CHECK_NULL_VOID_NOLOG(pipelineContext);
1373     windowId_ = pipelineContext->GetWindowId();
1374 
1375     auto client = AccessibilitySystemAbilityClient::GetInstance();
1376     CHECK_NULL_VOID_NOLOG(client);
1377     bool isEnabled = false;
1378     client->IsEnabled(isEnabled);
1379     AceApplicationInfo::GetInstance().SetAccessibilityEnabled(isEnabled);
1380 
1381     SubscribeToastObserver();
1382 
1383     if (!pipelineContext->IsFormRender()) {
1384         SubscribeStateObserver(AccessibilityStateEventType::EVENT_ACCESSIBILITY_STATE_CHANGED);
1385         if (isEnabled) {
1386             RegisterInteractionOperation(windowId_);
1387         }
1388     }
1389 }
1390 
SendAccessibilitySyncEvent(const AccessibilityEvent & accessibilityEvent,AccessibilityEventInfo eventInfo)1391 bool JsAccessibilityManager::SendAccessibilitySyncEvent(
1392     const AccessibilityEvent& accessibilityEvent, AccessibilityEventInfo eventInfo)
1393 {
1394     if (!IsRegister()) {
1395         return false;
1396     }
1397 
1398     auto client = AccessibilitySystemAbilityClient::GetInstance();
1399     CHECK_NULL_RETURN(client, false);
1400     bool isEnabled = false;
1401     client->IsEnabled(isEnabled);
1402     if (!isEnabled) {
1403         return false;
1404     }
1405 
1406     LOGD("type:%{public}s nodeId:%{public}d", accessibilityEvent.eventType.c_str(), accessibilityEvent.nodeId);
1407 
1408     Accessibility::EventType type = Accessibility::EventType::TYPE_VIEW_INVALID;
1409     if (accessibilityEvent.type != AccessibilityEventType::UNKNOWN) {
1410         type = ConvertAceEventType(accessibilityEvent.type);
1411     } else {
1412         type = ConvertStrToEventType(accessibilityEvent.eventType);
1413     }
1414 
1415     if (type == Accessibility::EventType::TYPE_VIEW_INVALID) {
1416         return false;
1417     }
1418 
1419     eventInfo.SetTimeStamp(GetMicroTickCount());
1420     eventInfo.SetBeforeText(accessibilityEvent.beforeText);
1421     eventInfo.SetLatestContent(accessibilityEvent.latestContent);
1422     eventInfo.SetWindowChangeTypes(static_cast<Accessibility::WindowUpdateType>(accessibilityEvent.windowChangeTypes));
1423     eventInfo.SetWindowContentChangeTypes(
1424         static_cast<Accessibility::WindowsContentChangeTypes>(accessibilityEvent.windowContentChangeTypes));
1425     eventInfo.SetSource(accessibilityEvent.nodeId);
1426     eventInfo.SetEventType(type);
1427     eventInfo.SetCurrentIndex(static_cast<int>(accessibilityEvent.currentItemIndex));
1428     eventInfo.SetItemCounts(static_cast<int>(accessibilityEvent.itemCount));
1429     eventInfo.SetBundleName(AceApplicationInfo::GetInstance().GetPackageName());
1430 
1431     return client->SendEvent(eventInfo);
1432 }
1433 
SendAccessibilityAsyncEvent(const AccessibilityEvent & accessibilityEvent)1434 void JsAccessibilityManager::SendAccessibilityAsyncEvent(const AccessibilityEvent& accessibilityEvent)
1435 {
1436     auto context = GetPipelineContext().Upgrade();
1437     CHECK_NULL_VOID_NOLOG(context);
1438     int32_t windowId = context->GetWindowId();
1439     if (windowId == 0) {
1440         return;
1441     }
1442 
1443     AccessibilityEventInfo eventInfo;
1444     if (AceType::InstanceOf<NG::PipelineContext>(context)) {
1445         RefPtr<NG::FrameNode> node;
1446         auto ngPipeline = FindPipelineByElementId(accessibilityEvent.nodeId, node);
1447         CHECK_NULL_VOID_NOLOG(ngPipeline);
1448         CHECK_NULL_VOID_NOLOG(node);
1449         FillEventInfo(node, eventInfo);
1450     } else {
1451         auto node = GetAccessibilityNodeFromPage(accessibilityEvent.nodeId);
1452         CHECK_NULL_VOID_NOLOG(node);
1453         FillEventInfo(node, eventInfo);
1454     }
1455     if (accessibilityEvent.type != AccessibilityEventType::PAGE_CHANGE) {
1456         eventInfo.SetWindowId(windowId);
1457     } else {
1458         eventInfo.SetWindowId(accessibilityEvent.windowId);
1459     }
1460     context->GetTaskExecutor()->PostTask(
1461         [weak = WeakClaim(this), accessibilityEvent, eventInfo] {
1462             auto jsAccessibilityManager = weak.Upgrade();
1463             CHECK_NULL_VOID(jsAccessibilityManager);
1464             jsAccessibilityManager->SendAccessibilitySyncEvent(accessibilityEvent, eventInfo);
1465         },
1466         TaskExecutor::TaskType::BACKGROUND);
1467 }
1468 
UpdateNodeChildIds(const RefPtr<AccessibilityNode> & node)1469 void JsAccessibilityManager::UpdateNodeChildIds(const RefPtr<AccessibilityNode>& node)
1470 {
1471     CHECK_NULL_VOID_NOLOG(node);
1472     node->ActionUpdateIds();
1473     const auto& children = node->GetChildList();
1474     std::vector<int32_t> childrenVec;
1475     auto cardId = GetCardId();
1476     auto rootNodeId = GetRootNodeId();
1477 
1478     // get last stack children to barrier free service.
1479     if ((node->GetNodeId() == GetRootNodeId() + ROOT_STACK_BASE) && !children.empty() && !IsDeclarative()) {
1480         auto lastChildNodeId = children.back()->GetNodeId();
1481         if (isOhosHostCard()) {
1482             childrenVec.emplace_back(ConvertToCardAccessibilityId(lastChildNodeId, cardId, rootNodeId));
1483         } else {
1484             childrenVec.emplace_back(lastChildNodeId);
1485             for (const auto& child : children) {
1486                 if (child->GetNodeId() == ROOT_DECOR_BASE - 1) {
1487                     childrenVec.emplace_back(child->GetNodeId());
1488                     break;
1489                 }
1490             }
1491         }
1492     } else {
1493         childrenVec.resize(children.size());
1494         if (isOhosHostCard()) {
1495             std::transform(children.begin(), children.end(), childrenVec.begin(),
1496                 [cardId, rootNodeId](const RefPtr<AccessibilityNode>& child) {
1497                     return ConvertToCardAccessibilityId(child->GetNodeId(), cardId, rootNodeId);
1498                 });
1499         } else {
1500             std::transform(children.begin(), children.end(), childrenVec.begin(),
1501                 [](const RefPtr<AccessibilityNode>& child) { return child->GetNodeId(); });
1502         }
1503     }
1504     node->SetChildIds(childrenVec);
1505 }
1506 
ProcessParameters(ActionType op,const std::vector<std::string> & params,std::map<std::string,std::string> & paramsMap)1507 void JsAccessibilityManager::ProcessParameters(
1508     ActionType op, const std::vector<std::string>& params, std::map<std::string, std::string>& paramsMap)
1509 {
1510     if (op == ActionType::ACCESSIBILITY_ACTION_SET_TEXT) {
1511         if (params.size() == EVENT_DUMP_PARAM_LENGTH_UPPER) {
1512             paramsMap = { { ACTION_ARGU_SET_TEXT, params[EVENT_DUMP_ACTION_PARAM_INDEX] } };
1513         }
1514     }
1515 
1516     if (op == ActionType::ACCESSIBILITY_ACTION_SET_SELECTION) {
1517         if (params.size() == EVENT_DUMP_PARAM_LENGTH_LOWER) {
1518             paramsMap[ACTION_ARGU_SELECT_TEXT_START] = "-1";
1519             paramsMap[ACTION_ARGU_SELECT_TEXT_END] = "-1";
1520         } else if (params.size() == EVENT_DUMP_PARAM_LENGTH_UPPER) {
1521             paramsMap[ACTION_ARGU_SELECT_TEXT_START] = params[EVENT_DUMP_ACTION_PARAM_INDEX];
1522             paramsMap[ACTION_ARGU_SELECT_TEXT_END] = "-1";
1523         } else {
1524             paramsMap[ACTION_ARGU_SELECT_TEXT_START] = params[EVENT_DUMP_ACTION_PARAM_INDEX];
1525             paramsMap[ACTION_ARGU_SELECT_TEXT_END] = params[EVENT_DUMP_PARAM_LENGTH_UPPER];
1526         }
1527     }
1528 
1529     if (op == ActionType::ACCESSIBILITY_ACTION_NEXT_TEXT || op == ActionType::ACCESSIBILITY_ACTION_PREVIOUS_TEXT) {
1530         if (params.size() == EVENT_DUMP_PARAM_LENGTH_UPPER) {
1531             paramsMap[ACTION_ARGU_MOVE_UNIT] = std::to_string(TextMoveUnit::STEP_CHARACTER);
1532         }
1533         paramsMap[ACTION_ARGU_MOVE_UNIT] = std::to_string(TextMoveUnit::STEP_CHARACTER);
1534     }
1535 }
1536 
DumpHandleEvent(const std::vector<std::string> & params)1537 void JsAccessibilityManager::DumpHandleEvent(const std::vector<std::string>& params)
1538 {
1539     if (params.size() > EVENT_DUMP_PARAM_LENGTH_UPPER + 1) {
1540         DumpLog::GetInstance().Print("Error: params length is illegal!");
1541         return;
1542     }
1543     if (params[EVENT_DUMP_ORDER_INDEX] != DUMP_ORDER && params[EVENT_DUMP_ORDER_INDEX] != DUMP_INSPECTOR) {
1544         DumpLog::GetInstance().Print("Error: not accessibility dump order!");
1545         return;
1546     }
1547 
1548     auto pipeline = context_.Upgrade();
1549     CHECK_NULL_VOID(pipeline);
1550     int32_t nodeId = StringUtils::StringToInt(params[EVENT_DUMP_ID_INDEX]);
1551     auto action = static_cast<AceAction>(StringUtils::StringToInt(params[EVENT_DUMP_ACTION_INDEX]));
1552     auto op = ConvertAceAction(action);
1553 
1554     if ((op != ActionType::ACCESSIBILITY_ACTION_SET_SELECTION) && (params.size() > EVENT_DUMP_PARAM_LENGTH_UPPER + 1)) {
1555         DumpLog::GetInstance().Print("Error: params is illegal!");
1556         return;
1557     }
1558 
1559     std::map<std::string, std::string> paramsMap;
1560     ProcessParameters(op, params, paramsMap);
1561     if (AceType::InstanceOf<NG::PipelineContext>(pipeline)) {
1562         RefPtr<NG::FrameNode> node;
1563         pipeline = FindPipelineByElementId(nodeId, node);
1564         CHECK_NULL_VOID_NOLOG(pipeline);
1565         CHECK_NULL_VOID_NOLOG(node);
1566         pipeline->GetTaskExecutor()->PostTask(
1567             [weak = WeakClaim(this), op, nodeId, paramsMap, pipeline]() {
1568                 auto jsAccessibilityManager = weak.Upgrade();
1569                 CHECK_NULL_VOID(jsAccessibilityManager);
1570                 jsAccessibilityManager->ExecuteActionNG(nodeId, paramsMap, op, pipeline);
1571             },
1572             TaskExecutor::TaskType::UI);
1573         return;
1574     }
1575 
1576     auto node = GetAccessibilityNodeFromPage(nodeId);
1577     CHECK_NULL_VOID(node);
1578 
1579     pipeline->GetTaskExecutor()->PostTask(
1580         [weak = WeakClaim(this), op, node, paramsMap, pipeline]() {
1581             auto jsAccessibilityManager = weak.Upgrade();
1582             CHECK_NULL_VOID(jsAccessibilityManager);
1583             jsAccessibilityManager->AccessibilityActionEvent(
1584                 op, paramsMap, node, AceType::DynamicCast<PipelineContext>(pipeline));
1585         },
1586         TaskExecutor::TaskType::UI);
1587 }
1588 
DumpProperty(const RefPtr<AccessibilityNode> & node)1589 void JsAccessibilityManager::DumpProperty(const RefPtr<AccessibilityNode>& node)
1590 {
1591     const auto& supportAceActions = node->GetSupportAction();
1592     const auto& charValue = node->GetChartValue();
1593 
1594     DumpLog::GetInstance().AddDesc("ID: ", node->GetNodeId());
1595     DumpLog::GetInstance().AddDesc("parent ID: ", node->GetParentId());
1596     DumpLog::GetInstance().AddDesc("child IDs: ", GetNodeChildIds(node));
1597     DumpLog::GetInstance().AddDesc("component type: ", node->GetTag());
1598     DumpLog::GetInstance().AddDesc("input type: ", node->GetInputType());
1599     DumpLog::GetInstance().AddDesc("text: ", node->GetText());
1600     DumpLog::GetInstance().AddDesc("width: ", node->GetWidth());
1601     DumpLog::GetInstance().AddDesc("height: ", node->GetHeight());
1602     DumpLog::GetInstance().AddDesc("left: ", node->GetLeft() + GetCardOffset().GetX());
1603     DumpLog::GetInstance().AddDesc("top: ", node->GetTop() + GetCardOffset().GetY());
1604     DumpLog::GetInstance().AddDesc("enabled: ", BoolToString(node->GetEnabledState()));
1605     DumpLog::GetInstance().AddDesc("checked: ", BoolToString(node->GetCheckedState()));
1606     DumpLog::GetInstance().AddDesc("selected: ", BoolToString(node->GetSelectedState()));
1607     DumpLog::GetInstance().AddDesc("focusable: ", BoolToString(node->GetFocusableState()));
1608     DumpLog::GetInstance().AddDesc("focused: ", BoolToString(node->GetFocusedState()));
1609     DumpLog::GetInstance().AddDesc("checkable: ", BoolToString(node->GetCheckableState()));
1610     DumpLog::GetInstance().AddDesc("clickable: ", BoolToString(node->GetClickableState()));
1611     DumpLog::GetInstance().AddDesc("long clickable: ", BoolToString(node->GetLongClickableState()));
1612     DumpLog::GetInstance().AddDesc("scrollable: ", BoolToString(node->GetScrollableState()));
1613     DumpLog::GetInstance().AddDesc("editable: ", BoolToString(node->GetEditable()));
1614     DumpLog::GetInstance().AddDesc("hint text: ", node->GetHintText());
1615     DumpLog::GetInstance().AddDesc("error text: ", node->GetErrorText());
1616     DumpLog::GetInstance().AddDesc("js component id: ", node->GetJsComponentId());
1617     DumpLog::GetInstance().AddDesc("accessibility label: ", node->GetAccessibilityLabel());
1618     DumpLog::GetInstance().AddDesc("accessibility hint: ", node->GetAccessibilityHint());
1619     DumpLog::GetInstance().AddDesc("max text length: ", node->GetMaxTextLength());
1620     DumpLog::GetInstance().AddDesc("text selection start: ", node->GetTextSelectionStart());
1621     DumpLog::GetInstance().AddDesc("text selection end: ", node->GetTextSelectionEnd());
1622     DumpLog::GetInstance().AddDesc("is multi line: ", BoolToString(node->GetIsMultiLine()));
1623     DumpLog::GetInstance().AddDesc("is password", BoolToString(node->GetIsPassword()));
1624     DumpLog::GetInstance().AddDesc("text input type: ", ConvertInputTypeToString(node->GetTextInputType()));
1625     DumpLog::GetInstance().AddDesc("min value: ", node->GetAccessibilityValue().min);
1626     DumpLog::GetInstance().AddDesc("max value: ", node->GetAccessibilityValue().max);
1627     DumpLog::GetInstance().AddDesc("current value: ", node->GetAccessibilityValue().current);
1628     DumpLog::GetInstance().AddDesc("collection info rows: ", node->GetCollectionInfo().rows);
1629     DumpLog::GetInstance().AddDesc("collection info columns: ", node->GetCollectionInfo().columns);
1630     DumpLog::GetInstance().AddDesc("collection item info, row: ", node->GetCollectionItemInfo().row);
1631     DumpLog::GetInstance().AddDesc("collection item info, column: ", node->GetCollectionItemInfo().column);
1632     DumpLog::GetInstance().AddDesc("chart has value: ", BoolToString(charValue && !charValue->empty()));
1633     DumpLog::GetInstance().AddDesc("accessibilityGroup: ", BoolToString(node->GetAccessible()));
1634     DumpLog::GetInstance().AddDesc("accessibilityImportance: ", node->GetImportantForAccessibility());
1635     DumpLog::GetInstance().AddDesc("support action: ", GetSupportAction(supportAceActions));
1636     DumpLog::GetInstance().Print(0, node->GetTag(), node->GetChildList().size());
1637 }
1638 
DumpPropertyNG(const std::vector<std::string> & params)1639 void JsAccessibilityManager::DumpPropertyNG(const std::vector<std::string>& params)
1640 {
1641     auto pipeline = context_.Upgrade();
1642     CHECK_NULL_VOID(pipeline);
1643 
1644     RefPtr<NG::FrameNode> frameNode;
1645     auto nodeID = StringUtils::StringToInt(params[1]);
1646     auto ngPipeline = FindPipelineByElementId(nodeID, frameNode);
1647     CHECK_NULL_VOID(ngPipeline);
1648     CHECK_NULL_VOID(frameNode);
1649 
1650     auto windowLeft = GetWindowLeft(ngPipeline->GetWindowId());
1651     auto windowTop = GetWindowTop(ngPipeline->GetWindowId());
1652     int32_t pageId = 0;
1653     string pagePath;
1654     if (ngPipeline->GetWindowId() == pipeline->GetWindowId()) {
1655         auto stageManager = ngPipeline->GetStageManager();
1656         CHECK_NULL_VOID(stageManager);
1657         auto page = stageManager->GetLastPage();
1658         CHECK_NULL_VOID(page);
1659         pageId = page->GetPageId();
1660         pagePath = GetPagePath();
1661     }
1662 
1663     AccessibilityElementInfo nodeInfo;
1664     CommonProperty commonProperty { ngPipeline->GetWindowId(), windowLeft, windowTop, pageId, pagePath };
1665     UpdateAccessibilityElementInfo(frameNode, commonProperty, nodeInfo, ngPipeline);
1666     DumpCommonPropertyNG(nodeInfo);
1667 
1668     DumpAccessibilityPropertyNG(nodeInfo);
1669     DumpLog::GetInstance().Print(0, nodeInfo.GetComponentType(), nodeInfo.GetChildCount());
1670 }
1671 
DumpProperty(const std::vector<std::string> & params)1672 void JsAccessibilityManager::DumpProperty(const std::vector<std::string>& params)
1673 {
1674     CHECK_NULL_VOID_NOLOG(DumpLog::GetInstance().GetDumpFile());
1675     if (params.empty()) {
1676         DumpLog::GetInstance().Print("Error: params cannot be empty!");
1677         return;
1678     }
1679     if (params.size() != PROPERTY_DUMP_PARAM_LENGTH) {
1680         DumpLog::GetInstance().Print("Error: params length is illegal!");
1681         return;
1682     }
1683     if (params[0] != DUMP_ORDER && params[0] != DUMP_INSPECTOR) {
1684         DumpLog::GetInstance().Print("Error: not accessibility dump order!");
1685         return;
1686     }
1687 
1688     auto pipeline = context_.Upgrade();
1689     CHECK_NULL_VOID(pipeline);
1690 
1691     if (!AceType::InstanceOf<NG::PipelineContext>(pipeline)) {
1692         auto node = GetAccessibilityNodeFromPage(StringUtils::StringToInt(params[1]));
1693         if (!node) {
1694             DumpLog::GetInstance().Print("Error: can't find node with ID " + params[1]);
1695             return;
1696         }
1697         DumpProperty(node);
1698     } else {
1699         DumpPropertyNG(params);
1700     }
1701 }
1702 
DumpTreeNG(const RefPtr<NG::FrameNode> & parent,int32_t depth,NodeId nodeID,const CommonProperty & commonProperty)1703 static void DumpTreeNG(
1704     const RefPtr<NG::FrameNode>& parent, int32_t depth, NodeId nodeID, const CommonProperty& commonProperty)
1705 {
1706     auto node = GetInspectorById(parent, nodeID);
1707     if (!node) {
1708         DumpLog::GetInstance().Print("Error: failed to get accessibility node with ID " + std::to_string(nodeID));
1709         return;
1710     }
1711 
1712     if (!node->IsActive()) {
1713         return;
1714     }
1715 
1716     NG::RectF rect = node->GetTransformRectRelativeToWindow();
1717     DumpLog::GetInstance().AddDesc("ID: " + std::to_string(node->GetAccessibilityId()));
1718     DumpLog::GetInstance().AddDesc("compid: " + node->GetInspectorId().value_or(""));
1719     DumpLog::GetInstance().AddDesc("text: " + node->GetAccessibilityProperty<NG::AccessibilityProperty>()->GetText());
1720     DumpLog::GetInstance().AddDesc(
1721         "accessibilityText: " + node->GetAccessibilityProperty<NG::AccessibilityProperty>()->GetAccessibilityText());
1722     DumpLog::GetInstance().AddDesc(
1723         "accessibilityGroup: " +
1724         std::to_string(node->GetAccessibilityProperty<NG::AccessibilityProperty>()->IsAccessibilityGroup()));
1725     DumpLog::GetInstance().AddDesc(
1726         "accessibilityLevel: " + node->GetAccessibilityProperty<NG::AccessibilityProperty>()->GetAccessibilityLevel());
1727     DumpLog::GetInstance().AddDesc("top: " + std::to_string(rect.Top() + commonProperty.windowTop));
1728     DumpLog::GetInstance().AddDesc("left: " + std::to_string(rect.Left() + commonProperty.windowLeft));
1729     DumpLog::GetInstance().AddDesc("width: " + std::to_string(rect.Width()));
1730     DumpLog::GetInstance().AddDesc("height: " + std::to_string(rect.Height()));
1731     DumpLog::GetInstance().AddDesc("visible: " + std::to_string(node->IsVisible()));
1732     auto gestureEventHub = node->GetEventHub<NG::EventHub>()->GetGestureEventHub();
1733     DumpLog::GetInstance().AddDesc(
1734         "clickable: " + std::to_string(gestureEventHub ? gestureEventHub->IsAccessibilityClickable() : false));
1735     DumpLog::GetInstance().AddDesc(
1736         "checkable: " + std::to_string(node->GetAccessibilityProperty<NG::AccessibilityProperty>()->IsCheckable()));
1737 
1738     std::vector<int32_t> children;
1739     for (const auto& item : node->GetChildren()) {
1740         GetFrameNodeChildren(item, children, commonProperty.pageId);
1741     }
1742     DumpLog::GetInstance().Print(depth, node->GetTag(), children.size());
1743 
1744     for (auto nodeId : children) {
1745         DumpTreeNG(node, depth + 1, nodeId, commonProperty);
1746     }
1747 }
1748 
DumpTree(int32_t depth,NodeId nodeID)1749 void JsAccessibilityManager::DumpTree(int32_t depth, NodeId nodeID)
1750 {
1751     auto pipeline = context_.Upgrade();
1752     CHECK_NULL_VOID(pipeline);
1753     if (!AceType::InstanceOf<NG::PipelineContext>(pipeline)) {
1754         AccessibilityNodeManager::DumpTree(depth, nodeID);
1755     } else {
1756         auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipeline);
1757         auto rootNode = ngPipeline->GetRootElement();
1758         CHECK_NULL_VOID(rootNode);
1759         nodeID = rootNode->GetAccessibilityId();
1760         auto windowLeft = GetWindowLeft(ngPipeline->GetWindowId());
1761         auto windowTop = GetWindowTop(ngPipeline->GetWindowId());
1762         auto stageManager = ngPipeline->GetStageManager();
1763         CHECK_NULL_VOID(stageManager);
1764         auto page = stageManager->GetLastPage();
1765         CHECK_NULL_VOID(page);
1766         auto pageId = page->GetPageId();
1767         auto pagePath = GetPagePath();
1768         CommonProperty commonProperty { ngPipeline->GetWindowId(), windowLeft, windowTop, pageId, pagePath };
1769         DumpTreeNG(rootNode, depth, nodeID, commonProperty);
1770         for (auto subContext : GetSubPipelineContexts()) {
1771             ngPipeline = AceType::DynamicCast<NG::PipelineContext>(subContext.Upgrade());
1772             CHECK_NULL_VOID(ngPipeline);
1773             rootNode = ngPipeline->GetRootElement();
1774             CHECK_NULL_VOID(rootNode);
1775             nodeID = rootNode->GetAccessibilityId();
1776             commonProperty.windowId = ngPipeline->GetWindowId();
1777             commonProperty.windowLeft = GetWindowLeft(ngPipeline->GetWindowId());
1778             commonProperty.windowTop = GetWindowTop(ngPipeline->GetWindowId());
1779             commonProperty.pageId = 0;
1780             commonProperty.pagePath = "";
1781             DumpTreeNG(rootNode, depth + 1, nodeID, commonProperty);
1782         }
1783     }
1784 }
1785 
SetCardViewParams(const std::string & key,bool focus)1786 void JsAccessibilityManager::SetCardViewParams(const std::string& key, bool focus)
1787 {
1788     LOGD("SetCardViewParams key=%{public}s  focus=%{public}d", key.c_str(), focus);
1789     callbackKey_ = key;
1790     if (!callbackKey_.empty()) {
1791         InitializeCallback();
1792     }
1793 }
1794 
UpdateViewScale()1795 void JsAccessibilityManager::UpdateViewScale()
1796 {
1797     auto context = GetPipelineContext().Upgrade();
1798     CHECK_NULL_VOID_NOLOG(context);
1799     float scaleX = 1.0;
1800     float scaleY = 1.0;
1801     if (context->GetViewScale(scaleX, scaleY)) {
1802         scaleX_ = scaleX;
1803         scaleY_ = scaleY;
1804     }
1805 }
1806 
HandleComponentPostBinding()1807 void JsAccessibilityManager::HandleComponentPostBinding()
1808 {
1809     for (auto targetIter = nodeWithTargetMap_.begin(); targetIter != nodeWithTargetMap_.end();) {
1810         auto nodeWithTarget = targetIter->second.Upgrade();
1811         if (nodeWithTarget) {
1812             if (nodeWithTarget->GetTag() == ACCESSIBILITY_TAG_POPUP) {
1813                 auto idNodeIter = nodeWithIdMap_.find(targetIter->first);
1814                 if (idNodeIter != nodeWithIdMap_.end()) {
1815                     auto nodeWithId = idNodeIter->second.Upgrade();
1816                     if (nodeWithId) {
1817                         nodeWithId->SetAccessibilityHint(nodeWithTarget->GetText());
1818                     } else {
1819                         nodeWithIdMap_.erase(idNodeIter);
1820                     }
1821                 }
1822             }
1823             ++targetIter;
1824         } else {
1825             // clear the disabled node in the maps
1826             nodeWithTargetMap_.erase(targetIter++);
1827         }
1828     }
1829 
1830     // clear the disabled node in the maps
1831     for (auto idItem = nodeWithIdMap_.begin(); idItem != nodeWithIdMap_.end();) {
1832         if (!idItem->second.Upgrade()) {
1833             nodeWithIdMap_.erase(idItem++);
1834         } else {
1835             ++idItem;
1836         }
1837     }
1838 }
1839 
Create()1840 RefPtr<AccessibilityNodeManager> AccessibilityNodeManager::Create()
1841 {
1842     return AceType::MakeRefPtr<JsAccessibilityManager>();
1843 }
1844 
GetPipelineByWindowId(const int32_t windowId)1845 RefPtr<PipelineBase> JsAccessibilityManager::GetPipelineByWindowId(const int32_t windowId)
1846 {
1847     auto context = context_.Upgrade();
1848     if (AceType::InstanceOf<NG::PipelineContext>(context)) {
1849         CHECK_NULL_RETURN_NOLOG(context, nullptr);
1850         if (context->GetWindowId() == static_cast<uint32_t>(windowId)) {
1851             return context;
1852         }
1853         for (auto& subContext : GetSubPipelineContexts()) {
1854             context = subContext.Upgrade();
1855             CHECK_NULL_RETURN_NOLOG(context, nullptr);
1856             if (context->GetWindowId() == static_cast<uint32_t>(windowId)) {
1857                 return context;
1858             }
1859         }
1860         return nullptr;
1861     } else {
1862         return context;
1863     }
1864 }
1865 
SearchElementInfoByAccessibilityId(const int32_t elementId,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t mode)1866 void JsAccessibilityManager::JsInteractionOperation::SearchElementInfoByAccessibilityId(const int32_t elementId,
1867     const int32_t requestId, AccessibilityElementOperatorCallback& callback, const int32_t mode)
1868 {
1869     LOGD("elementId(%{public}d) requestId(%{public}d) mode(%{public}d)", elementId, requestId, mode);
1870     auto jsAccessibilityManager = GetHandler().Upgrade();
1871     CHECK_NULL_VOID(jsAccessibilityManager);
1872     auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
1873     CHECK_NULL_VOID_NOLOG(context);
1874     auto windowId = windowId_;
1875     context->GetTaskExecutor()->PostTask(
1876         [jsAccessibilityManager, elementId, requestId, &callback, mode, windowId]() {
1877             CHECK_NULL_VOID(jsAccessibilityManager);
1878             jsAccessibilityManager->SearchElementInfoByAccessibilityId(elementId, requestId, callback, mode, windowId);
1879         },
1880         TaskExecutor::TaskType::UI);
1881 }
1882 
SearchElementInfoByAccessibilityId(const int32_t elementId,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t mode,const int32_t windowId)1883 void JsAccessibilityManager::SearchElementInfoByAccessibilityId(const int32_t elementId, const int32_t requestId,
1884     AccessibilityElementOperatorCallback& callback, const int32_t mode, const int32_t windowId)
1885 {
1886     std::list<AccessibilityElementInfo> infos;
1887 
1888     auto pipeline = GetPipelineByWindowId(windowId);
1889     if (pipeline) {
1890         auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipeline);
1891         if (ngPipeline) {
1892             SearchElementInfoByAccessibilityIdNG(elementId, mode, infos, pipeline);
1893             SetSearchElementInfoByAccessibilityIdResult(callback, infos, requestId);
1894             return;
1895         }
1896     }
1897 
1898     NodeId nodeId = elementId;
1899     // get root node
1900     if (elementId == -1) {
1901         nodeId = 0;
1902     }
1903     auto weak = WeakClaim(this);
1904     auto jsAccessibilityManager = weak.Upgrade();
1905     CHECK_NULL_VOID_NOLOG(jsAccessibilityManager);
1906     auto node = jsAccessibilityManager->GetAccessibilityNodeFromPage(nodeId);
1907     if (!node) {
1908         LOGW("AccessibilityNodeInfo can't attach component by Id = %{public}d, window:%{public}d", nodeId, windowId_);
1909         SetSearchElementInfoByAccessibilityIdResult(callback, infos, requestId);
1910         return;
1911     }
1912 
1913     AccessibilityElementInfo nodeInfo;
1914     UpdateAccessibilityNodeInfo(node, nodeInfo, jsAccessibilityManager, jsAccessibilityManager->windowId_);
1915     infos.push_back(nodeInfo);
1916     // cache parent/siblings/children infos
1917     UpdateCacheInfo(infos, mode, node, jsAccessibilityManager, jsAccessibilityManager->windowId_);
1918 
1919     SetSearchElementInfoByAccessibilityIdResult(callback, infos, requestId);
1920     LOGD("requestId(%{public}d)", requestId);
1921 }
1922 
SearchElementInfoByAccessibilityIdNG(int32_t elementId,int32_t mode,std::list<AccessibilityElementInfo> & infos,const RefPtr<PipelineBase> & context)1923 void JsAccessibilityManager::SearchElementInfoByAccessibilityIdNG(
1924     int32_t elementId, int32_t mode, std::list<AccessibilityElementInfo>& infos, const RefPtr<PipelineBase>& context)
1925 {
1926     auto mainContext = context_.Upgrade();
1927     CHECK_NULL_VOID(mainContext);
1928 
1929     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
1930     CHECK_NULL_VOID(ngPipeline);
1931     auto rootNode = ngPipeline->GetRootElement();
1932     CHECK_NULL_VOID(rootNode);
1933 
1934     AccessibilityElementInfo nodeInfo;
1935     NodeId nodeId = elementId;
1936     // accessibility use -1 for first search to get root node
1937     if (elementId == -1) {
1938         nodeId = rootNode->GetAccessibilityId();
1939     }
1940 
1941     auto node = GetInspectorById(rootNode, nodeId);
1942     CHECK_NULL_VOID(node);
1943     int32_t pageId = 0;
1944     std::string pagePath;
1945     if (context->GetWindowId() == mainContext->GetWindowId()) {
1946         auto stageManager = ngPipeline->GetStageManager();
1947         CHECK_NULL_VOID(stageManager);
1948         auto page = stageManager->GetLastPage();
1949         CHECK_NULL_VOID(page);
1950         pageId = page->GetPageId();
1951         pagePath = GetPagePath();
1952     }
1953     CommonProperty commonProperty { ngPipeline->GetWindowId(), GetWindowLeft(ngPipeline->GetWindowId()),
1954         GetWindowTop(ngPipeline->GetWindowId()), pageId, pagePath };
1955     UpdateAccessibilityElementInfo(node, commonProperty, nodeInfo, ngPipeline);
1956 
1957     infos.push_back(nodeInfo);
1958 }
1959 
SearchElementInfosByTextNG(int32_t elementId,const std::string & text,std::list<Accessibility::AccessibilityElementInfo> & infos,const RefPtr<PipelineBase> & context)1960 void JsAccessibilityManager::SearchElementInfosByTextNG(int32_t elementId, const std::string& text,
1961     std::list<Accessibility::AccessibilityElementInfo>& infos, const RefPtr<PipelineBase>& context)
1962 {
1963     auto mainContext = context_.Upgrade();
1964     CHECK_NULL_VOID(mainContext);
1965 
1966     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
1967     CHECK_NULL_VOID(ngPipeline);
1968     auto rootNode = ngPipeline->GetRootElement();
1969     CHECK_NULL_VOID(rootNode);
1970 
1971     auto node = GetInspectorById(rootNode, elementId);
1972     CHECK_NULL_VOID(node);
1973     std::list<RefPtr<NG::FrameNode>> results;
1974     FindText(node, text, results);
1975     if (results.empty()) {
1976         return;
1977     }
1978     int32_t pageId = 0;
1979     std::string pagePath;
1980     if (context->GetWindowId() == mainContext->GetWindowId()) {
1981         auto stageManager = ngPipeline->GetStageManager();
1982         CHECK_NULL_VOID(stageManager);
1983         auto page = stageManager->GetLastPage();
1984         CHECK_NULL_VOID(page);
1985         pageId = page->GetPageId();
1986         pagePath = GetPagePath();
1987     }
1988     CommonProperty commonProperty { ngPipeline->GetWindowId(), GetWindowLeft(ngPipeline->GetWindowId()),
1989         GetWindowTop(ngPipeline->GetWindowId()), pageId, pagePath };
1990     for (const auto& node : results) {
1991         AccessibilityElementInfo nodeInfo;
1992         UpdateAccessibilityElementInfo(node, commonProperty, nodeInfo, ngPipeline);
1993         infos.emplace_back(nodeInfo);
1994     }
1995 }
1996 
SearchElementInfosByText(const int32_t elementId,const std::string & text,const int32_t requestId,AccessibilityElementOperatorCallback & callback)1997 void JsAccessibilityManager::JsInteractionOperation::SearchElementInfosByText(const int32_t elementId,
1998     const std::string& text, const int32_t requestId, AccessibilityElementOperatorCallback& callback)
1999 {
2000     LOGI("elementId(%{public}d) text(%{public}s)", elementId, text.c_str());
2001     if (text.empty()) {
2002         LOGW("Text is null");
2003         return;
2004     }
2005     auto jsAccessibilityManager = GetHandler().Upgrade();
2006     CHECK_NULL_VOID_NOLOG(jsAccessibilityManager);
2007     auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
2008     CHECK_NULL_VOID_NOLOG(context);
2009     auto windowId = windowId_;
2010     if (context) {
2011         context->GetTaskExecutor()->PostTask(
2012             [jsAccessibilityManager, elementId, text, requestId, &callback, windowId]() {
2013                 CHECK_NULL_VOID_NOLOG(jsAccessibilityManager);
2014                 jsAccessibilityManager->SearchElementInfosByText(elementId, text, requestId, callback, windowId);
2015             },
2016             TaskExecutor::TaskType::UI);
2017     }
2018 }
2019 
SearchElementInfosByText(const int32_t elementId,const std::string & text,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t windowId)2020 void JsAccessibilityManager::SearchElementInfosByText(const int32_t elementId, const std::string& text,
2021     const int32_t requestId, AccessibilityElementOperatorCallback& callback, const int32_t windowId)
2022 {
2023     if (text.empty()) {
2024         LOGW("Text is null");
2025         return;
2026     }
2027 
2028     if (elementId == -1) {
2029         return;
2030     }
2031 
2032     std::list<AccessibilityElementInfo> infos;
2033 
2034     auto pipeline = GetPipelineByWindowId(windowId);
2035     if (pipeline) {
2036         if (AceType::InstanceOf<NG::PipelineContext>(pipeline)) {
2037             SearchElementInfosByTextNG(elementId, text, infos, pipeline);
2038             SetSearchElementInfoByTextResult(callback, infos, requestId);
2039             return;
2040         }
2041     }
2042 
2043     auto weak = WeakClaim(this);
2044     auto jsAccessibilityManager = weak.Upgrade();
2045     CHECK_NULL_VOID_NOLOG(jsAccessibilityManager);
2046     NodeId nodeId = elementId;
2047     auto node = jsAccessibilityManager->GetAccessibilityNodeFromPage(nodeId);
2048     CHECK_NULL_VOID_NOLOG(node);
2049     std::list<RefPtr<AccessibilityNode>> nodeList;
2050     FindText(node, text, nodeList);
2051     if (!nodeList.empty()) {
2052         for (const auto& node : nodeList) {
2053             LOGI(" FindText end nodeId:%{public}d", node->GetNodeId());
2054             AccessibilityElementInfo nodeInfo;
2055             UpdateAccessibilityNodeInfo(node, nodeInfo, jsAccessibilityManager, jsAccessibilityManager->windowId_);
2056             infos.emplace_back(nodeInfo);
2057         }
2058     }
2059 
2060     LOGI("SetSearchElementInfoByTextResult infos.size(%{public}zu)", infos.size());
2061     SetSearchElementInfoByTextResult(callback, infos, requestId);
2062 }
2063 
FindFocusedElementInfo(const int32_t elementId,const int32_t focusType,const int32_t requestId,AccessibilityElementOperatorCallback & callback)2064 void JsAccessibilityManager::JsInteractionOperation::FindFocusedElementInfo(const int32_t elementId,
2065     const int32_t focusType, const int32_t requestId, AccessibilityElementOperatorCallback& callback)
2066 {
2067     LOGI("elementId(%{public}d) focusType(%{public}d)", elementId, focusType);
2068     auto jsAccessibilityManager = GetHandler().Upgrade();
2069     CHECK_NULL_VOID_NOLOG(jsAccessibilityManager);
2070     auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
2071     CHECK_NULL_VOID_NOLOG(context);
2072     auto windowId = windowId_;
2073     context->GetTaskExecutor()->PostTask(
2074         [jsAccessibilityManager, elementId, focusType, requestId, &callback, windowId]() {
2075             CHECK_NULL_VOID_NOLOG(jsAccessibilityManager);
2076             jsAccessibilityManager->FindFocusedElementInfo(elementId, focusType, requestId, callback, windowId);
2077         },
2078         TaskExecutor::TaskType::UI);
2079 }
2080 
FindFocusedElementInfo(const int32_t elementId,const int32_t focusType,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t windowId)2081 void JsAccessibilityManager::FindFocusedElementInfo(const int32_t elementId, const int32_t focusType,
2082     const int32_t requestId, AccessibilityElementOperatorCallback& callback, const int32_t windowId)
2083 {
2084     AccessibilityElementInfo nodeInfo;
2085     if (focusType != FOCUS_TYPE_INPUT && focusType != FOCUS_TYPE_ACCESSIBILITY) {
2086         nodeInfo.SetValidElement(false);
2087         SetFindFocusedElementInfoResult(callback, nodeInfo, requestId);
2088         return;
2089     }
2090 
2091     auto context = GetPipelineByWindowId(windowId);
2092     if (!context) {
2093         SetFindFocusedElementInfoResult(callback, nodeInfo, requestId);
2094         return;
2095     }
2096 
2097     if (AceType::InstanceOf<NG::PipelineContext>(context)) {
2098         FindFocusedElementInfoNG(elementId, focusType, nodeInfo, context);
2099         SetFindFocusedElementInfoResult(callback, nodeInfo, requestId);
2100         return;
2101     }
2102 
2103     NodeId nodeId = static_cast<NodeId>(elementId);
2104     if (elementId == -1) {
2105         nodeId = 0;
2106     }
2107 
2108     auto node = GetAccessibilityNodeFromPage(nodeId);
2109     if (!node) {
2110         nodeInfo.SetValidElement(false);
2111         SetFindFocusedElementInfoResult(callback, nodeInfo, requestId);
2112         return;
2113     }
2114 
2115     RefPtr<AccessibilityNode> resultNode = nullptr;
2116     bool status = false;
2117     if (focusType == FOCUS_TYPE_ACCESSIBILITY) {
2118         status = FindAccessibilityFocus(node, resultNode);
2119     }
2120     if (focusType == FOCUS_TYPE_INPUT) {
2121         status = FindInputFocus(node, resultNode);
2122     }
2123 
2124     LOGI("FindFocus status(%{public}d)", status);
2125     if ((status) && (resultNode != nullptr)) {
2126         LOGI("FindFocus nodeId:%{public}d", resultNode->GetNodeId());
2127         UpdateAccessibilityNodeInfo(resultNode, nodeInfo, Claim(this), windowId_);
2128     }
2129 
2130     SetFindFocusedElementInfoResult(callback, nodeInfo, requestId);
2131 }
2132 
FindFocusedElementInfoNG(int32_t elementId,int32_t focusType,Accessibility::AccessibilityElementInfo & info,const RefPtr<PipelineBase> & context)2133 void JsAccessibilityManager::FindFocusedElementInfoNG(int32_t elementId, int32_t focusType,
2134     Accessibility::AccessibilityElementInfo& info, const RefPtr<PipelineBase>& context)
2135 {
2136     auto mainContext = context_.Upgrade();
2137     CHECK_NULL_VOID(mainContext);
2138 
2139     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
2140     CHECK_NULL_VOID(ngPipeline);
2141     auto rootNode = ngPipeline->GetRootElement();
2142     CHECK_NULL_VOID(rootNode);
2143 
2144     NodeId nodeId = elementId;
2145     // accessibility use -1 for first search to get root node
2146     if (elementId == -1) {
2147         nodeId = rootNode->GetAccessibilityId();
2148     }
2149 
2150     auto node = GetInspectorById(rootNode, nodeId);
2151     if (!node) {
2152         info.SetValidElement(false);
2153         return;
2154     }
2155     RefPtr<NG::FrameNode> resultNode;
2156     if (focusType == FOCUS_TYPE_ACCESSIBILITY) {
2157         resultNode = FindAccessibilityFocus(node);
2158     }
2159     if (focusType == FOCUS_TYPE_INPUT) {
2160         resultNode = FindInputFocus(node);
2161     }
2162     CHECK_NULL_VOID_NOLOG(resultNode);
2163     int32_t pageId = 0;
2164     std::string pagePath;
2165     if (context->GetWindowId() == mainContext->GetWindowId()) {
2166         auto stageManager = ngPipeline->GetStageManager();
2167         CHECK_NULL_VOID(stageManager);
2168         auto page = stageManager->GetLastPage();
2169         CHECK_NULL_VOID(page);
2170         pageId = page->GetPageId();
2171         pagePath = GetPagePath();
2172     }
2173     CommonProperty commonProperty { ngPipeline->GetWindowId(), GetWindowLeft(ngPipeline->GetWindowId()),
2174         GetWindowTop(ngPipeline->GetWindowId()), pageId, pagePath };
2175     UpdateAccessibilityElementInfo(resultNode, commonProperty, info, ngPipeline);
2176 }
2177 
FindNodeFromPipeline(const WeakPtr<PipelineBase> & context,const int32_t elementId)2178 RefPtr<NG::FrameNode> JsAccessibilityManager::FindNodeFromPipeline(
2179     const WeakPtr<PipelineBase>& context, const int32_t elementId)
2180 {
2181     auto pipeline = context.Upgrade();
2182     CHECK_NULL_RETURN(pipeline, nullptr);
2183 
2184     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipeline);
2185     auto rootNode = ngPipeline->GetRootElement();
2186     CHECK_NULL_RETURN(rootNode, nullptr);
2187 
2188     NodeId nodeId = elementId;
2189     // accessibility use -1 for first search to get root node
2190     if (elementId == -1) {
2191         nodeId = rootNode->GetAccessibilityId();
2192     }
2193 
2194     RefPtr<NG::FrameNode> node = GetInspectorById(rootNode, nodeId);
2195     if (node) {
2196         return node;
2197     }
2198     return nullptr;
2199 }
2200 
FindPipelineByElementId(const int32_t elementId,RefPtr<NG::FrameNode> & node)2201 RefPtr<NG::PipelineContext> JsAccessibilityManager::FindPipelineByElementId(
2202     const int32_t elementId, RefPtr<NG::FrameNode>& node)
2203 {
2204     node = FindNodeFromPipeline(context_, elementId);
2205     if (node) {
2206         auto context = AceType::DynamicCast<NG::PipelineContext>(context_.Upgrade());
2207         return context;
2208     }
2209     for (auto subContext : GetSubPipelineContexts()) {
2210         node = FindNodeFromPipeline(subContext, elementId);
2211         if (node) {
2212             auto context = AceType::DynamicCast<NG::PipelineContext>(subContext.Upgrade());
2213             return context;
2214         }
2215     }
2216     return nullptr;
2217 }
2218 
ExecuteAction(const int32_t elementId,const int32_t action,const std::map<std::string,std::string> & actionArguments,const int32_t requestId,AccessibilityElementOperatorCallback & callback)2219 void JsAccessibilityManager::JsInteractionOperation::ExecuteAction(const int32_t elementId, const int32_t action,
2220     const std::map<std::string, std::string>& actionArguments, const int32_t requestId,
2221     AccessibilityElementOperatorCallback& callback)
2222 {
2223     LOGI("id:%{public}d, action:%{public}d, request:%{public}d.", elementId, action, requestId);
2224     auto jsAccessibilityManager = GetHandler().Upgrade();
2225     CHECK_NULL_VOID_NOLOG(jsAccessibilityManager);
2226     auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
2227     CHECK_NULL_VOID_NOLOG(context);
2228     auto actionInfo = static_cast<ActionType>(action);
2229     ActionParam param { actionInfo, actionArguments };
2230     auto windowId = windowId_;
2231     context->GetTaskExecutor()->PostTask(
2232         [jsAccessibilityManager, elementId, param, requestId, &callback, windowId] {
2233             CHECK_NULL_VOID_NOLOG(jsAccessibilityManager);
2234             jsAccessibilityManager->ExecuteAction(elementId, param, requestId, callback, windowId);
2235         },
2236         TaskExecutor::TaskType::UI);
2237 }
2238 
AccessibilityActionEvent(const ActionType & action,const std::map<std::string,std::string> actionArguments,const RefPtr<AccessibilityNode> & node,const RefPtr<PipelineContext> & context)2239 bool JsAccessibilityManager::AccessibilityActionEvent(const ActionType& action,
2240     const std::map<std::string, std::string> actionArguments, const RefPtr<AccessibilityNode>& node,
2241     const RefPtr<PipelineContext>& context)
2242 {
2243     if (!node || !context) {
2244         return false;
2245     }
2246     ContainerScope scope(context->GetInstanceId());
2247     switch (action) {
2248         case ActionType::ACCESSIBILITY_ACTION_CLICK: {
2249             node->SetClicked(true);
2250             if (!node->GetClickEventMarker().IsEmpty()) {
2251                 context->SendEventToFrontend(node->GetClickEventMarker());
2252                 node->ActionClick();
2253                 return true;
2254             }
2255             return node->ActionClick();
2256         }
2257         case ActionType::ACCESSIBILITY_ACTION_LONG_CLICK: {
2258             if (!node->GetLongPressEventMarker().IsEmpty()) {
2259                 context->SendEventToFrontend(node->GetLongPressEventMarker());
2260                 node->ActionLongClick();
2261                 return true;
2262             }
2263             return node->ActionLongClick();
2264         }
2265         case ActionType::ACCESSIBILITY_ACTION_SET_TEXT: {
2266             if (!node->GetSetTextEventMarker().IsEmpty()) {
2267                 context->SendEventToFrontend(node->GetSetTextEventMarker());
2268                 node->ActionSetText(actionArguments.find(ACTION_ARGU_SET_TEXT)->second);
2269                 return true;
2270             }
2271             return node->ActionSetText(actionArguments.find(ACTION_ARGU_SET_TEXT)->second);
2272         }
2273         case ActionType::ACCESSIBILITY_ACTION_FOCUS: {
2274             context->AccessibilityRequestFocus(std::to_string(node->GetNodeId()));
2275             if (!node->GetFocusEventMarker().IsEmpty()) {
2276                 context->SendEventToFrontend(node->GetFocusEventMarker());
2277                 node->ActionFocus();
2278                 return true;
2279             }
2280             return node->ActionFocus();
2281         }
2282         case ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS: {
2283             return RequestAccessibilityFocus(node);
2284         }
2285         case ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
2286             return ClearAccessibilityFocus(node);
2287         }
2288         case ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD:
2289             return node->ActionScrollForward();
2290         case ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD:
2291             return node->ActionScrollBackward();
2292         default:
2293             return false;
2294     }
2295 }
2296 
SendActionEvent(const Accessibility::ActionType & action,NodeId nodeId)2297 void JsAccessibilityManager::SendActionEvent(const Accessibility::ActionType& action, NodeId nodeId)
2298 {
2299     static std::unordered_map<Accessibility::ActionType, std::string> actionToStr {
2300         { Accessibility::ActionType::ACCESSIBILITY_ACTION_CLICK, DOM_CLICK },
2301         { Accessibility::ActionType::ACCESSIBILITY_ACTION_LONG_CLICK, DOM_LONG_PRESS },
2302         { Accessibility::ActionType::ACCESSIBILITY_ACTION_FOCUS, DOM_FOCUS },
2303         { Accessibility::ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS, ACCESSIBILITY_FOCUSED_EVENT },
2304         { Accessibility::ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS, ACCESSIBILITY_CLEAR_FOCUS_EVENT },
2305         { Accessibility::ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD, SCROLL_END_EVENT },
2306         { Accessibility::ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD, SCROLL_END_EVENT },
2307     };
2308     if (actionToStr.find(action) == actionToStr.end()) {
2309         return;
2310     }
2311     AccessibilityEvent accessibilityEvent;
2312     accessibilityEvent.eventType = actionToStr[action];
2313     accessibilityEvent.nodeId = static_cast<int>(nodeId);
2314     SendAccessibilityAsyncEvent(accessibilityEvent);
2315 }
2316 
ActAccessibilityAction(Accessibility::ActionType action,const std::map<std::string,std::string> actionArguments,RefPtr<NG::AccessibilityProperty> accessibilityProperty)2317 bool ActAccessibilityAction(Accessibility::ActionType action, const std::map<std::string, std::string> actionArguments,
2318     RefPtr<NG::AccessibilityProperty> accessibilityProperty)
2319 {
2320     AccessibilityActionParam param;
2321     if (action == ActionType::ACCESSIBILITY_ACTION_SET_SELECTION) {
2322         int start = -1;
2323         int end = -1;
2324         auto iter = actionArguments.find(ACTION_ARGU_SELECT_TEXT_START);
2325         if (iter != actionArguments.end()) {
2326             std::stringstream str_start;
2327             str_start << iter->second;
2328             str_start >> start;
2329         }
2330         iter = actionArguments.find(ACTION_ARGU_SELECT_TEXT_END);
2331         if (iter != actionArguments.end()) {
2332             std::stringstream str_end;
2333             str_end << iter->second;
2334             str_end >> end;
2335         }
2336         param.setSelectionStart = start;
2337         param.setSelectionEnd = end;
2338     }
2339     if (action == ActionType::ACCESSIBILITY_ACTION_SET_TEXT) {
2340         auto iter = actionArguments.find(ACTION_ARGU_SET_TEXT);
2341         if (iter != actionArguments.end()) {
2342             param.setTextArgument = iter->second;
2343         }
2344     }
2345     if (action == ActionType::ACCESSIBILITY_ACTION_NEXT_TEXT ||
2346         action == ActionType::ACCESSIBILITY_ACTION_PREVIOUS_TEXT) {
2347         int moveUnit = TextMoveUnit::STEP_CHARACTER;
2348         auto iter = actionArguments.find(ACTION_ARGU_MOVE_UNIT);
2349         if (iter != actionArguments.end()) {
2350             std::stringstream str_moveUnit;
2351             str_moveUnit << iter->second;
2352             str_moveUnit >> moveUnit;
2353         }
2354         param.moveUnit = static_cast<TextMoveUnit>(moveUnit);
2355     }
2356     auto accessibiltyAction = ACTIONS.find(action);
2357     if (accessibiltyAction != ACTIONS.end()) {
2358         param.accessibilityProperty = accessibilityProperty;
2359         return accessibiltyAction->second(param);
2360     }
2361     return false;
2362 }
2363 
ExecuteActionNG(int32_t elementId,const std::map<std::string,std::string> & actionArguments,ActionType action,const RefPtr<PipelineBase> & context)2364 bool JsAccessibilityManager::ExecuteActionNG(int32_t elementId,
2365     const std::map<std::string, std::string>& actionArguments, ActionType action, const RefPtr<PipelineBase>& context)
2366 {
2367     bool result = false;
2368     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
2369     CHECK_NULL_RETURN(ngPipeline, result);
2370     ContainerScope instance(ngPipeline->GetInstanceId());
2371     auto frameNode = GetInspectorById(ngPipeline->GetRootElement(), elementId);
2372     CHECK_NULL_RETURN(frameNode, result);
2373     auto enabled = frameNode->GetFocusHub() ? frameNode->GetFocusHub()->IsEnabled() : true;
2374     if (!enabled) {
2375         return result;
2376     }
2377 
2378     switch (action) {
2379         case ActionType::ACCESSIBILITY_ACTION_FOCUS: {
2380             result = RequestFocus(frameNode);
2381             break;
2382         }
2383         case ActionType::ACCESSIBILITY_ACTION_CLEAR_FOCUS: {
2384             result = LostFocus(frameNode);
2385             break;
2386         }
2387         case ActionType::ACCESSIBILITY_ACTION_CLICK: {
2388             result = ActClick(frameNode);
2389             break;
2390         }
2391         case ActionType::ACCESSIBILITY_ACTION_LONG_CLICK: {
2392             result = ActLongClick(frameNode);
2393             break;
2394         }
2395         case ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS: {
2396             result = ActAccessibilityFocus(elementId, frameNode, ngPipeline, currentFocusNodeId_, false);
2397             break;
2398         }
2399         case ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
2400             result = ActAccessibilityFocus(elementId, frameNode, ngPipeline, currentFocusNodeId_, true);
2401             break;
2402         }
2403         default:
2404             break;
2405     }
2406     if (!result) {
2407         auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
2408         CHECK_NULL_RETURN(accessibilityProperty, false);
2409         result = ActAccessibilityAction(action, actionArguments, accessibilityProperty);
2410     }
2411     return result;
2412 }
2413 
ExecuteAction(const int32_t elementId,const ActionParam & param,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t windowId)2414 void JsAccessibilityManager::ExecuteAction(const int32_t elementId, const ActionParam& param, const int32_t requestId,
2415     AccessibilityElementOperatorCallback& callback, const int32_t windowId)
2416 {
2417     auto action = param.action;
2418     auto actionArguments = param.actionArguments;
2419     LOGI("ExecuteAction elementId:%{public}d action:%{public}d", elementId, action);
2420 
2421     bool actionResult = false;
2422     auto context = GetPipelineByWindowId(windowId);
2423     if (!context) {
2424         SetExecuteActionResult(callback, actionResult, requestId);
2425         return;
2426     }
2427 
2428     if (AceType::InstanceOf<NG::PipelineContext>(context)) {
2429         actionResult = ExecuteActionNG(elementId, actionArguments, action, context);
2430     } else {
2431         auto node = GetAccessibilityNodeFromPage(elementId);
2432         if (!node) {
2433             LOGW("AccessibilityNodeInfo can't attach component by Id = %{public}d", elementId);
2434             SetExecuteActionResult(callback, false, requestId);
2435             return;
2436         }
2437 
2438         actionResult =
2439             AccessibilityActionEvent(action, actionArguments, node, AceType::DynamicCast<PipelineContext>(context));
2440     }
2441     LOGI("SetExecuteActionResult actionResult= %{public}d", actionResult);
2442     SetExecuteActionResult(callback, actionResult, requestId);
2443     if (actionResult && AceType::InstanceOf<PipelineContext>(context)) {
2444         SendActionEvent(action, elementId);
2445     }
2446 }
2447 
ClearFocus()2448 void JsAccessibilityManager::JsInteractionOperation::ClearFocus()
2449 {
2450     LOGI("ClearFocus");
2451     auto jsAccessibilityManager = GetHandler().Upgrade();
2452     CHECK_NULL_VOID_NOLOG(jsAccessibilityManager);
2453     auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
2454     CHECK_NULL_VOID_NOLOG(context);
2455     context->GetTaskExecutor()->PostTask(
2456         [jsAccessibilityManager] {
2457             if (!jsAccessibilityManager) {
2458                 return;
2459             }
2460             jsAccessibilityManager->ClearCurrentFocus();
2461         },
2462         TaskExecutor::TaskType::UI);
2463 }
2464 
OutsideTouch()2465 void JsAccessibilityManager::JsInteractionOperation::OutsideTouch() {}
2466 
IsRegister()2467 bool JsAccessibilityManager::IsRegister()
2468 {
2469     return isReg_;
2470 }
2471 
Register(bool state)2472 void JsAccessibilityManager::Register(bool state)
2473 {
2474     isReg_ = state;
2475 }
2476 
RegisterInteractionOperation(int windowId)2477 int JsAccessibilityManager::RegisterInteractionOperation(int windowId)
2478 {
2479     LOGI("RegisterInteractionOperation windowId:%{public}d", windowId);
2480     if (IsRegister()) {
2481         return 0;
2482     }
2483 
2484     std::shared_ptr<AccessibilitySystemAbilityClient> instance = AccessibilitySystemAbilityClient::GetInstance();
2485     CHECK_NULL_RETURN_NOLOG(instance, -1);
2486     auto interactionOperation = std::make_shared<JsInteractionOperation>(windowId);
2487     interactionOperation->SetHandler(WeakClaim(this));
2488     Accessibility::RetError retReg = instance->RegisterElementOperator(windowId, interactionOperation);
2489     RefPtr<PipelineBase> context;
2490     for (auto subContext : GetSubPipelineContexts()) {
2491         context = subContext.Upgrade();
2492         CHECK_NULL_RETURN_NOLOG(context, -1);
2493         interactionOperation = std::make_shared<JsInteractionOperation>(context->GetWindowId());
2494         interactionOperation->SetHandler(WeakClaim(this));
2495         retReg = instance->RegisterElementOperator(context->GetWindowId(), interactionOperation);
2496     }
2497     LOGI("RegisterInteractionOperation end windowId:%{public}d, ret:%{public}d", windowId, retReg);
2498     Register(retReg == RET_OK);
2499 
2500     return retReg;
2501 }
2502 
RegisterSubWindowInteractionOperation(int windowId)2503 void JsAccessibilityManager::RegisterSubWindowInteractionOperation(int windowId)
2504 {
2505     if (!AceApplicationInfo::GetInstance().IsAccessibilityEnabled() || !IsRegister()) {
2506         return;
2507     }
2508 
2509     std::shared_ptr<AccessibilitySystemAbilityClient> instance = AccessibilitySystemAbilityClient::GetInstance();
2510     CHECK_NULL_VOID_NOLOG(instance);
2511     auto interactionOperation = std::make_shared<JsInteractionOperation>(windowId);
2512     interactionOperation->SetHandler(WeakClaim(this));
2513     Accessibility::RetError retReg = instance->RegisterElementOperator(windowId, interactionOperation);
2514     if (!retReg) {
2515         LOGE("RegisterInteractionOperation failed, windowId:%{public}d, ret:%{public}d", windowId, retReg);
2516     }
2517 }
2518 
DeregisterInteractionOperation()2519 void JsAccessibilityManager::DeregisterInteractionOperation()
2520 {
2521     if (!IsRegister()) {
2522         return;
2523     }
2524     int windowId = GetWindowId();
2525 
2526     auto instance = AccessibilitySystemAbilityClient::GetInstance();
2527     CHECK_NULL_VOID_NOLOG(instance);
2528     Register(false);
2529     currentFocusNodeId_ = -1;
2530     LOGI("DeregisterInteractionOperation windowId:%{public}d", windowId);
2531     instance->DeregisterElementOperator(windowId);
2532     RefPtr<PipelineBase> context;
2533     for (auto subContext : GetSubPipelineContexts()) {
2534         context = subContext.Upgrade();
2535         CHECK_NULL_VOID_NOLOG(context);
2536         instance->DeregisterElementOperator(context->GetWindowId());
2537     }
2538 }
2539 
OnStateChanged(const bool state)2540 void JsAccessibilityManager::JsAccessibilityStateObserver::OnStateChanged(const bool state)
2541 {
2542     LOGI("accessibility state changed:%{public}d", state);
2543     auto jsAccessibilityManager = GetHandler().Upgrade();
2544     CHECK_NULL_VOID_NOLOG(jsAccessibilityManager);
2545     auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
2546     CHECK_NULL_VOID_NOLOG(context);
2547     context->GetTaskExecutor()->PostTask(
2548         [jsAccessibilityManager, state]() {
2549             if (state) {
2550                 jsAccessibilityManager->RegisterInteractionOperation(jsAccessibilityManager->GetWindowId());
2551             } else {
2552                 jsAccessibilityManager->DeregisterInteractionOperation();
2553             }
2554             AceApplicationInfo::GetInstance().SetAccessibilityEnabled(state);
2555         },
2556         TaskExecutor::TaskType::UI);
2557 }
2558 
FocusMoveSearch(int32_t elementId,const int32_t direction,const int32_t requestId,AccessibilityElementOperatorCallback & callback)2559 void JsAccessibilityManager::JsInteractionOperation::FocusMoveSearch(
2560     int32_t elementId, const int32_t direction, const int32_t requestId, AccessibilityElementOperatorCallback& callback)
2561 {
2562     LOGI("elementId:%{public}d,direction:%{public}d,requestId:%{public}d", elementId, direction, requestId);
2563     auto jsAccessibilityManager = GetHandler().Upgrade();
2564     CHECK_NULL_VOID_NOLOG(jsAccessibilityManager);
2565     auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
2566     CHECK_NULL_VOID_NOLOG(context);
2567     auto windowId = windowId_;
2568     context->GetTaskExecutor()->PostTask(
2569         [jsAccessibilityManager, elementId, direction, requestId, &callback, windowId] {
2570             CHECK_NULL_VOID_NOLOG(jsAccessibilityManager);
2571             jsAccessibilityManager->FocusMoveSearch(elementId, direction, requestId, callback, windowId);
2572         },
2573         TaskExecutor::TaskType::UI);
2574 }
2575 
FocusMoveSearch(const int32_t elementId,const int32_t direction,const int32_t requestId,Accessibility::AccessibilityElementOperatorCallback & callback,const int32_t windowId)2576 void JsAccessibilityManager::FocusMoveSearch(const int32_t elementId, const int32_t direction, const int32_t requestId,
2577     Accessibility::AccessibilityElementOperatorCallback& callback, const int32_t windowId)
2578 {
2579     AccessibilityElementInfo nodeInfo;
2580     auto context = GetPipelineByWindowId(windowId);
2581     if (!context) {
2582         LOGI("FocusMoveSearch context is null");
2583         nodeInfo.SetValidElement(false);
2584         SetFocusMoveSearchResult(callback, nodeInfo, requestId);
2585         return;
2586     }
2587 
2588     if (AceType::InstanceOf<NG::PipelineContext>(context)) {
2589         FocusMoveSearchNG(elementId, direction, nodeInfo, context);
2590         SetFocusMoveSearchResult(callback, nodeInfo, requestId);
2591         return;
2592     }
2593 
2594     auto node = GetAccessibilityNodeFromPage(elementId);
2595     if (!node) {
2596         LOGW("AccessibilityNodeInfo can't attach component by Id = %{public}d", (NodeId)elementId);
2597         nodeInfo.SetValidElement(false);
2598         SetFocusMoveSearchResult(callback, nodeInfo, requestId);
2599         return;
2600     }
2601 
2602     // get root node.
2603     auto rootNode = node;
2604     while (rootNode->GetParentNode()) {
2605         rootNode = rootNode->GetParentNode();
2606         if (!rootNode->GetParentNode()) {
2607             break;
2608         }
2609     }
2610 
2611     std::list<RefPtr<AccessibilityNode>> nodeList;
2612     AddFocusableNode(nodeList, rootNode);
2613     RefPtr<AccessibilityNode> resultNode;
2614 
2615     switch (direction) {
2616         case FocusMoveDirection::FORWARD:
2617         case FocusMoveDirection::BACKWARD:
2618             // forward and backward
2619             resultNode = FindNodeInRelativeDirection(nodeList, node, direction);
2620             break;
2621         case FocusMoveDirection::UP:
2622         case FocusMoveDirection::DOWN:
2623         case FocusMoveDirection::LEFT:
2624         case FocusMoveDirection::RIGHT:
2625             // up, down, left and right
2626             resultNode = FindNodeInAbsoluteDirection(nodeList, node, direction);
2627             break;
2628         default:
2629             break;
2630     }
2631 
2632     if (resultNode) {
2633         LOGI("FocusMoveSearch end nodeId:%{public}d", resultNode->GetNodeId());
2634         auto jsAccessibilityManager = Claim(this);
2635         UpdateAccessibilityNodeInfo(resultNode, nodeInfo, jsAccessibilityManager, windowId_);
2636     }
2637 
2638     SetFocusMoveSearchResult(callback, nodeInfo, requestId);
2639 }
2640 
AddFocusableNode(std::list<RefPtr<AccessibilityNode>> & nodeList,const RefPtr<AccessibilityNode> & node)2641 void JsAccessibilityManager::AddFocusableNode(
2642     std::list<RefPtr<AccessibilityNode>>& nodeList, const RefPtr<AccessibilityNode>& node)
2643 {
2644     const std::string importance = node->GetImportantForAccessibility();
2645     if (CanAccessibilityFocused(node)) {
2646         nodeList.push_back(node);
2647     }
2648     if (!node->GetAccessible() && importance != "no-hide-descendants") {
2649         for (auto& child : node->GetChildList()) {
2650             AddFocusableNode(nodeList, child);
2651         }
2652     }
2653 }
2654 
CanAccessibilityFocused(const RefPtr<AccessibilityNode> & node)2655 bool JsAccessibilityManager::CanAccessibilityFocused(const RefPtr<AccessibilityNode>& node)
2656 {
2657     return node != nullptr && !node->IsRootNode() && node->GetVisible() &&
2658            node->GetImportantForAccessibility() != "no" &&
2659            node->GetImportantForAccessibility() != "no-hide-descendants";
2660 }
2661 
FindNodeInRelativeDirection(const std::list<RefPtr<AccessibilityNode>> & nodeList,RefPtr<AccessibilityNode> & node,const int direction)2662 RefPtr<AccessibilityNode> JsAccessibilityManager::FindNodeInRelativeDirection(
2663     const std::list<RefPtr<AccessibilityNode>>& nodeList, RefPtr<AccessibilityNode>& node, const int direction)
2664 {
2665     switch (direction) {
2666         case FocusMoveDirection::FORWARD:
2667             return GetNextFocusableNode(nodeList, node);
2668         case FocusMoveDirection::BACKWARD:
2669             return GetPreviousFocusableNode(nodeList, node);
2670         default:
2671             break;
2672     }
2673 
2674     return nullptr;
2675 }
2676 
FindNodeInAbsoluteDirection(const std::list<RefPtr<AccessibilityNode>> & nodeList,RefPtr<AccessibilityNode> & node,const int direction)2677 RefPtr<AccessibilityNode> JsAccessibilityManager::FindNodeInAbsoluteDirection(
2678     const std::list<RefPtr<AccessibilityNode>>& nodeList, RefPtr<AccessibilityNode>& node, const int direction)
2679 {
2680     LOGI("FindNodeInAbsoluteDirection");
2681     auto tempBest = node->GetRect();
2682     auto nodeRect = node->GetRect();
2683 
2684     switch (direction) {
2685         case FocusMoveDirection::LEFT:
2686             tempBest.SetLeft(node->GetLeft() + node->GetWidth() + 1);
2687             break;
2688         case FocusMoveDirection::RIGHT:
2689             tempBest.SetLeft(node->GetLeft() - node->GetWidth() - 1);
2690             break;
2691         case FocusMoveDirection::UP:
2692             tempBest.SetTop(node->GetTop() + node->GetHeight() + 1);
2693             break;
2694         case FocusMoveDirection::DOWN:
2695             tempBest.SetTop(node->GetTop() - node->GetHeight() - 1);
2696             break;
2697         default:
2698             break;
2699     }
2700 
2701     RefPtr<AccessibilityNode> nearestNode = nullptr;
2702     for (auto nodeItem = nodeList.begin(); nodeItem != nodeList.end(); nodeItem++) {
2703         if ((*nodeItem)->GetNodeId() == node->GetNodeId() || (*nodeItem)->IsRootNode()) {
2704             continue;
2705         }
2706         auto itemRect = (*nodeItem)->GetRect();
2707         if (CheckBetterRect(nodeRect, direction, itemRect, tempBest)) {
2708             tempBest = itemRect;
2709             nearestNode = (*nodeItem);
2710         }
2711     }
2712 
2713     return nearestNode;
2714 }
2715 
GetNextFocusableNode(const std::list<RefPtr<AccessibilityNode>> & nodeList,RefPtr<AccessibilityNode> & node)2716 RefPtr<AccessibilityNode> JsAccessibilityManager::GetNextFocusableNode(
2717     const std::list<RefPtr<AccessibilityNode>>& nodeList, RefPtr<AccessibilityNode>& node)
2718 {
2719     LOGI("GetNextFocusableNode");
2720     auto nodeItem = nodeList.begin();
2721     for (; nodeItem != nodeList.end(); nodeItem++) {
2722         if ((*nodeItem)->GetNodeId() == node->GetNodeId()) {
2723             break;
2724         }
2725     }
2726 
2727     if (nodeItem != nodeList.end() && ++nodeItem != nodeList.end()) {
2728         return (*nodeItem);
2729     }
2730     if (!nodeList.empty()) {
2731         return (*nodeList.begin());
2732     }
2733 
2734     return nullptr;
2735 }
2736 
GetPreviousFocusableNode(const std::list<RefPtr<AccessibilityNode>> & nodeList,RefPtr<AccessibilityNode> & node)2737 RefPtr<AccessibilityNode> JsAccessibilityManager::GetPreviousFocusableNode(
2738     const std::list<RefPtr<AccessibilityNode>>& nodeList, RefPtr<AccessibilityNode>& node)
2739 {
2740     LOGI("GetPreviousFocusableNode");
2741     auto nodeItem = nodeList.rbegin();
2742     for (; nodeItem != nodeList.rend(); nodeItem++) {
2743         if ((*nodeItem)->GetNodeId() == node->GetNodeId()) {
2744             break;
2745         }
2746     }
2747 
2748     if (nodeItem != nodeList.rend() && ++nodeItem != nodeList.rend()) {
2749         return (*nodeItem);
2750     }
2751 
2752     if (!nodeList.empty()) {
2753         return (*nodeList.rbegin());
2754     }
2755     return nullptr;
2756 }
2757 
RequestAccessibilityFocus(const RefPtr<AccessibilityNode> & node)2758 bool JsAccessibilityManager::RequestAccessibilityFocus(const RefPtr<AccessibilityNode>& node)
2759 {
2760     LOGI("RequestAccessibilityFocus");
2761     auto requestNodeId = node->GetNodeId();
2762     if (currentFocusNodeId_ == requestNodeId) {
2763         LOGW("This node is focused.");
2764         return false;
2765     }
2766 
2767     ClearCurrentFocus();
2768     currentFocusNodeId_ = requestNodeId;
2769     node->SetAccessibilityFocusedState(true);
2770     LOGI("RequestAccessibilityFocus SetFocusedState true nodeId:%{public}d", node->GetNodeId());
2771     return node->ActionAccessibilityFocus(true);
2772 }
2773 
ClearAccessibilityFocus(const RefPtr<AccessibilityNode> & node)2774 bool JsAccessibilityManager::ClearAccessibilityFocus(const RefPtr<AccessibilityNode>& node)
2775 {
2776     LOGI("ClearAccessibilityFocus");
2777     auto requestNodeId = node->GetNodeId();
2778     if (currentFocusNodeId_ != requestNodeId) {
2779         LOGW("This node is not focused.");
2780         return false;
2781     }
2782 
2783     currentFocusNodeId_ = -1;
2784     node->SetAccessibilityFocusedState(false);
2785     return node->ActionAccessibilityFocus(false);
2786 }
2787 
ClearCurrentFocus()2788 bool JsAccessibilityManager::ClearCurrentFocus()
2789 {
2790     LOGI("ClearCurrentFocus");
2791     auto currentFocusNode = GetAccessibilityNodeFromPage(currentFocusNodeId_);
2792     CHECK_NULL_RETURN_NOLOG(currentFocusNode, false);
2793     currentFocusNodeId_ = -1;
2794     currentFocusNode->SetFocusedState(false);
2795     currentFocusNode->SetAccessibilityFocusedState(false);
2796     LOGI("ClearCurrentFocus SetFocusedState false nodeId:%{public}d", currentFocusNode->GetNodeId());
2797     return currentFocusNode->ActionAccessibilityFocus(false);
2798 }
2799 
FocusMoveSearchNG(int32_t elementId,int32_t direction,Accessibility::AccessibilityElementInfo & info,const RefPtr<PipelineBase> & context)2800 void JsAccessibilityManager::FocusMoveSearchNG(int32_t elementId, int32_t direction,
2801     Accessibility::AccessibilityElementInfo& info, const RefPtr<PipelineBase>& context)
2802 {
2803     auto mainContext = context_.Upgrade();
2804     CHECK_NULL_VOID(mainContext);
2805 
2806     auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
2807     CHECK_NULL_VOID(ngPipeline);
2808     auto rootNode = ngPipeline->GetRootElement();
2809     CHECK_NULL_VOID(rootNode);
2810 
2811     auto node = GetInspectorById(rootNode, elementId);
2812     if (!node) {
2813         info.SetValidElement(false);
2814         return;
2815     }
2816     std::list<RefPtr<NG::FrameNode>> nodeList;
2817     Framework::AddFocusableNode(nodeList, rootNode);
2818 
2819     RefPtr<NG::FrameNode> resultNode;
2820     switch (direction) {
2821         case FocusMoveDirection::FORWARD:
2822         case FocusMoveDirection::BACKWARD:
2823             resultNode = Framework::FindNodeInRelativeDirection(nodeList, node, direction);
2824             break;
2825         case FocusMoveDirection::UP:
2826         case FocusMoveDirection::DOWN:
2827         case FocusMoveDirection::LEFT:
2828         case FocusMoveDirection::RIGHT:
2829             resultNode = Framework::FindNodeInAbsoluteDirection(nodeList, node, direction);
2830             break;
2831         default:
2832             break;
2833     }
2834 
2835     CHECK_NULL_VOID_NOLOG(resultNode);
2836     int32_t pageId = 0;
2837     std::string pagePath;
2838     if (context->GetWindowId() == mainContext->GetWindowId()) {
2839         auto stageManager = ngPipeline->GetStageManager();
2840         CHECK_NULL_VOID(stageManager);
2841         auto page = stageManager->GetLastPage();
2842         CHECK_NULL_VOID(page);
2843         pageId = page->GetPageId();
2844         pagePath = GetPagePath();
2845     }
2846     CommonProperty commonProperty { ngPipeline->GetWindowId(), GetWindowLeft(ngPipeline->GetWindowId()),
2847         GetWindowTop(ngPipeline->GetWindowId()), pageId, pagePath };
2848     UpdateAccessibilityElementInfo(resultNode, commonProperty, info, ngPipeline);
2849 }
2850 
2851 // AccessibilitySystemAbilityClient will release callback after DeregisterElementOperator
SetSearchElementInfoByAccessibilityIdResult(AccessibilityElementOperatorCallback & callback,const std::list<AccessibilityElementInfo> & infos,const int32_t requestId)2852 void JsAccessibilityManager::SetSearchElementInfoByAccessibilityIdResult(AccessibilityElementOperatorCallback& callback,
2853     const std::list<AccessibilityElementInfo>& infos, const int32_t requestId)
2854 {
2855     if (IsRegister()) {
2856         callback.SetSearchElementInfoByAccessibilityIdResult(infos, requestId);
2857     }
2858 }
2859 
SetSearchElementInfoByTextResult(AccessibilityElementOperatorCallback & callback,const std::list<AccessibilityElementInfo> & infos,const int32_t requestId)2860 void JsAccessibilityManager::SetSearchElementInfoByTextResult(AccessibilityElementOperatorCallback& callback,
2861     const std::list<AccessibilityElementInfo>& infos, const int32_t requestId)
2862 {
2863     if (IsRegister()) {
2864         callback.SetSearchElementInfoByTextResult(infos, requestId);
2865     }
2866 }
2867 
SetFindFocusedElementInfoResult(AccessibilityElementOperatorCallback & callback,const AccessibilityElementInfo & info,const int32_t requestId)2868 void JsAccessibilityManager::SetFindFocusedElementInfoResult(
2869     AccessibilityElementOperatorCallback& callback, const AccessibilityElementInfo& info, const int32_t requestId)
2870 {
2871     if (IsRegister()) {
2872         callback.SetFindFocusedElementInfoResult(info, requestId);
2873     }
2874 }
2875 
SetFocusMoveSearchResult(AccessibilityElementOperatorCallback & callback,const AccessibilityElementInfo & info,const int32_t requestId)2876 void JsAccessibilityManager::SetFocusMoveSearchResult(
2877     AccessibilityElementOperatorCallback& callback, const AccessibilityElementInfo& info, const int32_t requestId)
2878 {
2879     if (IsRegister()) {
2880         callback.SetFocusMoveSearchResult(info, requestId);
2881     }
2882 }
2883 
SetExecuteActionResult(AccessibilityElementOperatorCallback & callback,const bool succeeded,const int32_t requestId)2884 void JsAccessibilityManager::SetExecuteActionResult(
2885     AccessibilityElementOperatorCallback& callback, const bool succeeded, const int32_t requestId)
2886 {
2887     if (IsRegister()) {
2888         callback.SetExecuteActionResult(succeeded, requestId);
2889     }
2890 }
2891 
GetPagePath()2892 std::string JsAccessibilityManager::GetPagePath()
2893 {
2894     auto context = context_.Upgrade();
2895     CHECK_NULL_RETURN(context, "");
2896     auto frontend = context->GetFrontend();
2897     CHECK_NULL_RETURN(frontend, "");
2898     ContainerScope scope(context->GetInstanceId());
2899     return frontend->GetPagePath();
2900 }
2901 
2902 } // namespace OHOS::Ace::Framework
2903