1 /*
2 * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "js_accessibility_manager.h"
17
18 #include "accessibility_system_ability_client.h"
19
20 #include "adapter/ohos/entrance/ace_container.h"
21 #include "base/log/event_report.h"
22 #include "core/components_ng/pattern/scrollable/scrollable_utils.h"
23 #include "core/components_ng/base/frame_node.h"
24 #include "frameworks/core/components_ng/pattern/ui_extension/platform_container_handler.h"
25 #include "frameworks/core/components_ng/pattern/overlay/accessibility_focus_paint_node_pattern.h"
26 #include "frameworks/core/components_ng/pattern/web/web_pattern.h"
27 #include "js_third_provider_interaction_operation.h"
28 #include "frameworks/core/components_ng/pattern/web/transitional_node_info.h"
29 #include "base/log/event_report.h"
30
31 using namespace OHOS::Accessibility;
32 using namespace OHOS::AccessibilityConfig;
33
34 namespace OHOS::Ace::Framework {
35 namespace {
36 const char DUMP_ORDER[] = "-accessibility";
37 const char DUMP_INSPECTOR[] = "-inspector";
38 const char ACCESSIBILITY_FOCUSED_EVENT[] = "accessibilityfocus";
39 const char ACCESSIBILITY_CLEAR_FOCUS_EVENT[] = "accessibilityclearfocus";
40 const char TEXT_CHANGE_EVENT[] = "textchange";
41 const char PAGE_CHANGE_EVENT[] = "pagechange";
42 const char SCROLL_END_EVENT[] = "scrollend";
43 const char SCROLL_START_EVENT[] = "scrollstart";
44 const char MOUSE_HOVER_ENTER[] = "mousehoverenter";
45 const char MOUSE_HOVER_EXIT[] = "mousehoverexit";
46 const char LIST_TAG[] = "List";
47 const char SIDEBARCONTAINER_TAG[] = "SideBarContainer";
48 const char STRING_DIR_FORWARD[] = "forward";
49 const char STRING_DIR_BACKWARD[] = "backward";
50 constexpr int32_t INVALID_PARENT_ID = -2100000;
51 constexpr int32_t DEFAULT_PARENT_ID = 2100000;
52 constexpr int32_t ROOT_STACK_BASE = 1100000;
53 constexpr int32_t ROOT_DECOR_BASE = 3100000;
54 constexpr int32_t CARD_NODE_ID_RATION = 10000;
55 constexpr int32_t CARD_ROOT_NODE_ID_RATION = 1000;
56 constexpr int32_t CARD_BASE = 100000;
57 constexpr int32_t DELAY_SEND_EVENT_MILLISECOND = 20;
58 constexpr uint32_t SUB_TREE_OFFSET_IN_PAGE_ID = 16;
59 constexpr int32_t MAX_PAGE_ID_WITH_SUB_TREE = (1 << SUB_TREE_OFFSET_IN_PAGE_ID);
60
61 const std::string ACTION_ARGU_SCROLL_STUB = "scrolltype"; // wait for change
62 const std::string ACTION_DEFAULT_PARAM = "ACCESSIBILITY_ACTION_INVALID";
63
64 const std::map<Accessibility::ActionType, std::function<bool(const AccessibilityActionParam& param)>> ACTIONS = {
65 { ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD,
__anona14df10c0202() 66 [](const AccessibilityActionParam& param) {
67 return param.accessibilityProperty->ActActionScrollForward(param.scrollType);
68 } },
69 { ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD,
__anona14df10c0302() 70 [](const AccessibilityActionParam& param) {
71 return param.accessibilityProperty->ActActionScrollBackward(param.scrollType);
72 } },
73 { ActionType::ACCESSIBILITY_ACTION_SET_TEXT,
__anona14df10c0402() 74 [](const AccessibilityActionParam& param) {
75 return param.accessibilityProperty->ActActionSetText(param.setTextArgument);
76 } },
77 { ActionType::ACCESSIBILITY_ACTION_SET_SELECTION,
__anona14df10c0502() 78 [](const AccessibilityActionParam& param) {
79 return param.accessibilityProperty->ActActionSetSelection(param.setSelectionStart,
80 param.setSelectionEnd, param.setSelectionDir);
81 } },
82 { ActionType::ACCESSIBILITY_ACTION_COPY,
__anona14df10c0602() 83 [](const AccessibilityActionParam& param) { return param.accessibilityProperty->ActActionCopy(); } },
84 { ActionType::ACCESSIBILITY_ACTION_CUT,
__anona14df10c0702() 85 [](const AccessibilityActionParam& param) { return param.accessibilityProperty->ActActionCut(); } },
86 { ActionType::ACCESSIBILITY_ACTION_PASTE,
__anona14df10c0802() 87 [](const AccessibilityActionParam& param) { return param.accessibilityProperty->ActActionPaste(); } },
88 { ActionType::ACCESSIBILITY_ACTION_CLICK,
__anona14df10c0902() 89 [](const AccessibilityActionParam& param) { return param.accessibilityProperty->ActActionClick(); } },
90 { ActionType::ACCESSIBILITY_ACTION_LONG_CLICK,
__anona14df10c0a02() 91 [](const AccessibilityActionParam& param) { return param.accessibilityProperty->ActActionLongClick(); } },
92 { ActionType::ACCESSIBILITY_ACTION_SELECT,
__anona14df10c0b02() 93 [](const AccessibilityActionParam& param) { return param.accessibilityProperty->ActActionSelect(); } },
94 { ActionType::ACCESSIBILITY_ACTION_CLEAR_SELECTION,
__anona14df10c0c02() 95 [](const AccessibilityActionParam& param) { return param.accessibilityProperty->ActActionClearSelection(); } },
96 { ActionType::ACCESSIBILITY_ACTION_NEXT_TEXT,
__anona14df10c0d02() 97 [](const AccessibilityActionParam& param) {
98 return param.accessibilityProperty->ActActionMoveText(static_cast<int32_t>(param.moveUnit), true);
99 } },
100 { ActionType::ACCESSIBILITY_ACTION_PREVIOUS_TEXT,
__anona14df10c0e02() 101 [](const AccessibilityActionParam& param) {
102 return param.accessibilityProperty->ActActionMoveText(static_cast<int32_t>(param.moveUnit), false);
103 } },
104 { ActionType::ACCESSIBILITY_ACTION_SET_CURSOR_POSITION,
__anona14df10c0f02() 105 [](const AccessibilityActionParam& param) {
106 return param.accessibilityProperty->ActActionSetIndex(static_cast<int32_t>(param.setCursorIndex));
107 } },
108 { ActionType::ACCESSIBILITY_ACTION_SPAN_CLICK,
__anona14df10c1002() 109 [](const AccessibilityActionParam& param) {
110 return param.accessibilityProperty->ActActionExecSubComponent(static_cast<int32_t>(param.spanId));
111 } },
112 };
113
IsDynamicComponent(const RefPtr<NG::UINode> & node)114 bool IsDynamicComponent(const RefPtr<NG::UINode>& node)
115 {
116 return node && (node->GetTag() == V2::DYNAMIC_COMPONENT_ETS_TAG);
117 }
118
IsExtensionComponent(const RefPtr<NG::UINode> & node)119 bool IsExtensionComponent(const RefPtr<NG::UINode>& node)
120 {
121 return node && (node->GetTag() == V2::UI_EXTENSION_COMPONENT_ETS_TAG
122 || node->GetTag() == V2::EMBEDDED_COMPONENT_ETS_TAG
123 || node->GetTag() == V2::ISOLATED_COMPONENT_ETS_TAG);
124 }
125
IsIsolatedComponent(const RefPtr<NG::UINode> & node)126 bool IsIsolatedComponent(const RefPtr<NG::UINode>& node)
127 {
128 return node && (node->GetTag() == V2::ISOLATED_COMPONENT_ETS_TAG);
129 }
130
IsUIExtensionShowPlaceholder(const RefPtr<NG::UINode> & node)131 bool IsUIExtensionShowPlaceholder(const RefPtr<NG::UINode>& node)
132 {
133 CHECK_NULL_RETURN(node, true);
134 if (node->GetTag() == V2::ISOLATED_COMPONENT_ETS_TAG) {
135 return false;
136 }
137 #ifdef WINDOW_SCENE_SUPPORTED
138 auto pipeline = node->GetContextRefPtr();
139 CHECK_NULL_RETURN(pipeline, true);
140 auto manager = pipeline->GetUIExtensionManager();
141 CHECK_NULL_RETURN(manager, true);
142 return manager->IsShowPlaceholder(node->GetId());
143 #endif
144 return true;
145 }
146
NeedUpdateChildrenOfAccessibilityElementInfo(const RefPtr<NG::UINode> & node)147 bool NeedUpdateChildrenOfAccessibilityElementInfo(const RefPtr<NG::UINode>& node)
148 {
149 return !IsDynamicComponent(node);
150 }
151
CheckChildIsAccessibilityFocus(const RefPtr<NG::UINode> & uiNode,RefPtr<NG::FrameNode> & focusFrameNode)152 bool CheckChildIsAccessibilityFocus(const RefPtr<NG::UINode> &uiNode, RefPtr<NG::FrameNode> &focusFrameNode)
153 {
154 CHECK_NULL_RETURN(uiNode, false);
155 auto nowFrameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
156 if (nowFrameNode) {
157 auto accessibilityProperty = nowFrameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
158 if (accessibilityProperty) {
159 auto isFocus = accessibilityProperty->GetAccessibilityFocusState();
160 if (isFocus) {
161 focusFrameNode = nowFrameNode;
162 return true;
163 }
164 }
165 }
166 auto children = uiNode->GetChildren(true);
167 for (const auto& child : children) {
168 if (CheckChildIsAccessibilityFocus(child, focusFrameNode)) {
169 return true;
170 }
171 }
172 return false;
173 }
174
UpdatePaintNodeRender(const RefPtr<NG::FrameNode> & focusNode)175 void UpdatePaintNodeRender(const RefPtr<NG::FrameNode>& focusNode)
176 {
177 CHECK_NULL_VOID(focusNode);
178 ACE_SCOPED_TRACE("Node[%s] UpdatePaintNodeRender", focusNode->GetTag().c_str());
179 auto paintNode = focusNode->GetPaintNode();
180 CHECK_NULL_VOID(paintNode);
181 auto pattern = paintNode->GetPattern<NG::AccessibilityFocusPaintNodePattern>();
182 CHECK_NULL_VOID(pattern);
183 pattern->UpdateRenderWithFocusNode();
184 auto renderContext = paintNode->GetRenderContext();
185 CHECK_NULL_VOID(renderContext);
186 auto accessibilityProperty = focusNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
187 CHECK_NULL_VOID(accessibilityProperty);
188
189 if (accessibilityProperty->IsMatchAccessibilityResponseRegion(false)) {
190 auto rectInt = accessibilityProperty->GetAccessibilityResponseRegionRect(false);
191 renderContext->UpdateAccessibilityFocusRect(rectInt);
192 } else {
193 renderContext->UpdateAccessibilityRoundRect();
194 }
195 }
196
ConvertStrToEventType(const std::string & type)197 Accessibility::EventType ConvertStrToEventType(const std::string& type)
198 {
199 // static linear map must be sorted by key.
200 static const LinearMapNode<Accessibility::EventType> eventTypeMap[] = {
201 { ACCESSIBILITY_CLEAR_FOCUS_EVENT, Accessibility::EventType::TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED_EVENT },
202 { ACCESSIBILITY_FOCUSED_EVENT, Accessibility::EventType::TYPE_VIEW_ACCESSIBILITY_FOCUSED_EVENT },
203 { DOM_CLICK, Accessibility::EventType::TYPE_VIEW_CLICKED_EVENT },
204 { DOM_FOCUS, Accessibility::EventType::TYPE_VIEW_FOCUSED_EVENT },
205 { DOM_LONG_PRESS, Accessibility::EventType::TYPE_VIEW_LONG_CLICKED_EVENT },
206 { MOUSE_HOVER_ENTER, Accessibility::EventType::TYPE_VIEW_HOVER_ENTER_EVENT },
207 { MOUSE_HOVER_EXIT, Accessibility::EventType::TYPE_VIEW_HOVER_EXIT_EVENT },
208 { PAGE_CHANGE_EVENT, Accessibility::EventType::TYPE_PAGE_STATE_UPDATE },
209 { SCROLL_END_EVENT, Accessibility::EventType::TYPE_VIEW_SCROLLED_EVENT },
210 { SCROLL_START_EVENT, Accessibility::EventType::TYPE_VIEW_SCROLLED_START },
211 { DOM_SELECTED, Accessibility::EventType::TYPE_VIEW_SELECTED_EVENT },
212 { TEXT_CHANGE_EVENT, Accessibility::EventType::TYPE_VIEW_TEXT_UPDATE_EVENT },
213 { DOM_TOUCH_END, Accessibility::EventType::TYPE_TOUCH_END },
214 { DOM_TOUCH_START, Accessibility::EventType::TYPE_TOUCH_BEGIN },
215 };
216 Accessibility::EventType eventType = Accessibility::EventType::TYPE_VIEW_INVALID;
217 int64_t idx = BinarySearchFindIndex(eventTypeMap, ArraySize(eventTypeMap), type.c_str());
218 if (idx >= 0) {
219 eventType = eventTypeMap[idx].value;
220 }
221 return eventType;
222 }
223
ConvertAceEventType(AccessibilityEventType type)224 Accessibility::EventType ConvertAceEventType(AccessibilityEventType type)
225 {
226 static const LinearEnumMapNode<AccessibilityEventType, Accessibility::EventType> eventTypeMap[] = {
227 { AccessibilityEventType::CLICK, Accessibility::EventType::TYPE_VIEW_CLICKED_EVENT },
228 { AccessibilityEventType::LONG_PRESS, Accessibility::EventType::TYPE_VIEW_LONG_CLICKED_EVENT },
229 { AccessibilityEventType::SELECTED, Accessibility::EventType::TYPE_VIEW_SELECTED_EVENT },
230 { AccessibilityEventType::FOCUS, Accessibility::EventType::TYPE_VIEW_FOCUSED_EVENT },
231 { AccessibilityEventType::TEXT_CHANGE, Accessibility::EventType::TYPE_VIEW_TEXT_UPDATE_EVENT },
232 { AccessibilityEventType::HOVER_ENTER_EVENT, Accessibility::EventType::TYPE_VIEW_HOVER_ENTER_EVENT },
233 { AccessibilityEventType::PAGE_CHANGE, Accessibility::EventType::TYPE_PAGE_STATE_UPDATE },
234 { AccessibilityEventType::HOVER_EXIT_EVENT, Accessibility::EventType::TYPE_VIEW_HOVER_EXIT_EVENT },
235 { AccessibilityEventType::CHANGE, Accessibility::EventType::TYPE_PAGE_CONTENT_UPDATE },
236 { AccessibilityEventType::COMPONENT_CHANGE, Accessibility::EventType::TYPE_VIEW_TEXT_UPDATE_EVENT },
237 { AccessibilityEventType::SCROLL_END, Accessibility::EventType::TYPE_VIEW_SCROLLED_EVENT },
238 { AccessibilityEventType::TEXT_SELECTION_UPDATE,
239 Accessibility::EventType::TYPE_VIEW_TEXT_SELECTION_UPDATE_EVENT },
240 { AccessibilityEventType::ACCESSIBILITY_FOCUSED,
241 Accessibility::EventType::TYPE_VIEW_ACCESSIBILITY_FOCUSED_EVENT },
242 { AccessibilityEventType::ACCESSIBILITY_FOCUS_CLEARED,
243 Accessibility::EventType::TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED_EVENT },
244 { AccessibilityEventType::TEXT_MOVE_UNIT, Accessibility::EventType::TYPE_VIEW_TEXT_MOVE_UNIT_EVENT },
245 { AccessibilityEventType::REQUEST_FOCUS, Accessibility::EventType::TYPE_VIEW_REQUEST_FOCUS_FOR_ACCESSIBILITY },
246 { AccessibilityEventType::SCROLL_START, Accessibility::EventType::TYPE_VIEW_SCROLLED_START },
247 { AccessibilityEventType::PAGE_CLOSE, Accessibility::EventType::TYPE_PAGE_CLOSE },
248 { AccessibilityEventType::ANNOUNCE_FOR_ACCESSIBILITY,
249 Accessibility::EventType::TYPE_VIEW_ANNOUNCE_FOR_ACCESSIBILITY },
250 { AccessibilityEventType::PAGE_OPEN, Accessibility::EventType::TYPE_PAGE_OPEN },
251 { AccessibilityEventType::ELEMENT_INFO_CHANGE, Accessibility::EventType::TYPE_ELEMENT_INFO_CHANGE },
252 { AccessibilityEventType::SCROLLING_EVENT, Accessibility::EventType::TYPE_VIEW_SCROLLING_EVENT },
253 };
254 Accessibility::EventType eventType = Accessibility::EventType::TYPE_VIEW_INVALID;
255 int64_t idx = BinarySearchFindIndex(eventTypeMap, ArraySize(eventTypeMap), type);
256 if (idx >= 0) {
257 eventType = eventTypeMap[idx].value;
258 }
259 return eventType;
260 }
261
ConvertAceAction(AceAction aceAction)262 ActionType ConvertAceAction(AceAction aceAction)
263 {
264 static const ActionTable actionTable[] = {
265 { AceAction::ACTION_CLICK, ActionType::ACCESSIBILITY_ACTION_CLICK },
266 { AceAction::ACTION_LONG_CLICK, ActionType::ACCESSIBILITY_ACTION_LONG_CLICK },
267 { AceAction::ACTION_SCROLL_FORWARD, ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD },
268 { AceAction::ACTION_SCROLL_BACKWARD, ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD },
269 { AceAction::ACTION_FOCUS, ActionType::ACCESSIBILITY_ACTION_FOCUS },
270 { AceAction::ACTION_CLEAR_FOCUS, ActionType::ACCESSIBILITY_ACTION_CLEAR_FOCUS },
271 { AceAction::ACTION_ACCESSIBILITY_FOCUS, ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS },
272 { AceAction::ACTION_CLEAR_ACCESSIBILITY_FOCUS, ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS },
273 { AceAction::ACTION_NEXT_AT_MOVEMENT_GRANULARITY, ActionType::ACCESSIBILITY_ACTION_NEXT_TEXT },
274 { AceAction::ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, ActionType::ACCESSIBILITY_ACTION_PREVIOUS_TEXT },
275 { AceAction::ACTION_SET_TEXT, ActionType::ACCESSIBILITY_ACTION_SET_TEXT },
276 { AceAction::ACTION_COPY, ActionType::ACCESSIBILITY_ACTION_COPY },
277 { AceAction::ACTION_PASTE, ActionType::ACCESSIBILITY_ACTION_PASTE },
278 { AceAction::ACTION_CUT, ActionType::ACCESSIBILITY_ACTION_CUT },
279 { AceAction::ACTION_SELECT, ActionType::ACCESSIBILITY_ACTION_SELECT },
280 { AceAction::ACTION_CLEAR_SELECTION, ActionType::ACCESSIBILITY_ACTION_CLEAR_SELECTION },
281 { AceAction::ACTION_SET_SELECTION, ActionType::ACCESSIBILITY_ACTION_SET_SELECTION },
282 { AceAction::ACTION_SET_CURSOR_POSITION, ActionType::ACCESSIBILITY_ACTION_SET_CURSOR_POSITION },
283 { AceAction::ACTION_EXEC_SUB_COMPONENT, ActionType::ACCESSIBILITY_ACTION_SPAN_CLICK },
284 { AceAction::ACTION_NEXT_HTML_ITEM, ActionType::ACCESSIBILITY_ACTION_NEXT_HTML_ITEM },
285 { AceAction::ACTION_PREVIOUS_HTML_ITEM, ActionType::ACCESSIBILITY_ACTION_PREVIOUS_HTML_ITEM },
286 };
287 for (const auto& item : actionTable) {
288 if (aceAction == item.aceAction) {
289 return item.action;
290 }
291 }
292 return ActionType::ACCESSIBILITY_ACTION_INVALID;
293 }
294
ConvertAccessibilityValue(const AccessibilityValue & value)295 inline RangeInfo ConvertAccessibilityValue(const AccessibilityValue& value)
296 {
297 return RangeInfo(value.min, value.max, value.current);
298 }
299
ConvertToCardAccessibilityId(int64_t nodeId,int64_t cardId,int64_t rootNodeId)300 int64_t ConvertToCardAccessibilityId(int64_t nodeId, int64_t cardId, int64_t rootNodeId)
301 {
302 // result is integer total ten digits, top five for agp virtualViewId, end five for ace nodeId,
303 // for example agp virtualViewId is 32, ace nodeId is 1000001, convert to result is 00032 10001.
304 int64_t result = 0;
305 if (nodeId == rootNodeId + ROOT_STACK_BASE) {
306 // for example agp virtualViewId is 32 root node is 2100000, convert to result is 00032 21000.
307 result = cardId * CARD_BASE + (static_cast<int64_t>(nodeId / CARD_BASE)) * CARD_ROOT_NODE_ID_RATION +
308 nodeId % CARD_BASE;
309 } else {
310 result = cardId * CARD_BASE + (static_cast<int64_t>(nodeId / DOM_ROOT_NODE_ID_BASE)) * CARD_NODE_ID_RATION +
311 nodeId % DOM_ROOT_NODE_ID_BASE;
312 }
313 return result;
314 }
CheckInvalidNodeParentID(const RefPtr<AccessibilityNode> & node,AccessibilityElementInfo & nodeInfo,const RefPtr<JsAccessibilityManager> & manager,int & leftTopX,int & leftTopY,int & rightBottomX,int & rightBottomY)315 void CheckInvalidNodeParentID(const RefPtr<AccessibilityNode>& node, AccessibilityElementInfo& nodeInfo,
316 const RefPtr<JsAccessibilityManager>& manager, int& leftTopX, int& leftTopY, int& rightBottomX, int& rightBottomY)
317 {
318 if (node->GetParentId() == -1) {
319 const auto& children = node->GetChildList();
320 if (!children.empty()) {
321 auto lastChildNode = manager->GetAccessibilityNodeById(children.back()->GetNodeId());
322 if (lastChildNode) {
323 rightBottomX = leftTopX + static_cast<int>(lastChildNode->GetWidth());
324 rightBottomY = leftTopY + static_cast<int>(lastChildNode->GetHeight());
325 Accessibility::Rect bounds(leftTopX, leftTopY, rightBottomX, rightBottomY);
326 nodeInfo.SetRectInScreen(bounds);
327 }
328 }
329 nodeInfo.SetParent(INVALID_PARENT_ID);
330 }
331 if (node->GetNodeId() == 0) {
332 nodeInfo.SetParent(INVALID_PARENT_ID);
333 }
334 }
UpdateAccessibilityNodeInfo(const RefPtr<AccessibilityNode> & node,AccessibilityElementInfo & nodeInfo,const RefPtr<JsAccessibilityManager> & manager,int windowId)335 void UpdateAccessibilityNodeInfo(const RefPtr<AccessibilityNode>& node, AccessibilityElementInfo& nodeInfo,
336 const RefPtr<JsAccessibilityManager>& manager, int windowId)
337 {
338 int leftTopX = static_cast<int>(node->GetLeft()) + manager->GetWindowLeft(node->GetWindowId());
339 int leftTopY = static_cast<int>(node->GetTop()) + manager->GetWindowTop(node->GetWindowId());
340 int rightBottomX = leftTopX + static_cast<int>(node->GetWidth());
341 int rightBottomY = leftTopY + static_cast<int>(node->GetHeight());
342 if (manager->isOhosHostCard()) {
343 int64_t id = ConvertToCardAccessibilityId(node->GetNodeId(), manager->GetCardId(), manager->GetRootNodeId());
344 nodeInfo.SetAccessibilityId(id);
345 if (node->GetParentId() == -1) {
346 nodeInfo.SetParent(-1);
347 } else {
348 nodeInfo.SetParent(
349 ConvertToCardAccessibilityId(node->GetParentId(), manager->GetCardId(), manager->GetRootNodeId()));
350 }
351 leftTopX = static_cast<int>(node->GetLeft() + manager->GetCardOffset().GetX());
352 leftTopY = static_cast<int>(node->GetTop() + manager->GetCardOffset().GetY());
353 rightBottomX = leftTopX + static_cast<int>(node->GetWidth());
354 rightBottomY = leftTopY + static_cast<int>(node->GetHeight());
355 Accessibility::Rect bounds(leftTopX, leftTopY, rightBottomX, rightBottomY);
356 nodeInfo.SetRectInScreen(bounds);
357 } else {
358 if (node->GetTag() == SIDEBARCONTAINER_TAG) {
359 Rect sideBarRect = node->GetRect();
360 for (const auto& childNode : node->GetChildList()) {
361 sideBarRect = sideBarRect.CombineRect(childNode->GetRect());
362 }
363 leftTopX = static_cast<int>(sideBarRect.Left()) + manager->GetWindowLeft(node->GetWindowId());
364 leftTopY = static_cast<int>(sideBarRect.Top()) + manager->GetWindowTop(node->GetWindowId());
365 rightBottomX = static_cast<int>(sideBarRect.Right()) + manager->GetWindowLeft(node->GetWindowId());
366 rightBottomY = static_cast<int>(sideBarRect.Bottom()) + manager->GetWindowTop(node->GetWindowId());
367 }
368 Accessibility::Rect bounds(leftTopX, leftTopY, rightBottomX, rightBottomY);
369 nodeInfo.SetRectInScreen(bounds);
370 nodeInfo.SetComponentId(static_cast<int64_t>(node->GetNodeId()));
371 nodeInfo.SetParent(static_cast<int64_t>(node->GetParentId()));
372 }
373 CheckInvalidNodeParentID(node, nodeInfo, manager, leftTopX, leftTopY, rightBottomX, rightBottomY);
374 nodeInfo.SetPagePath(manager->GetPagePath());
375 nodeInfo.SetWindowId(windowId);
376 nodeInfo.SetChecked(node->GetCheckedState());
377 nodeInfo.SetEnabled(node->GetEnabledState());
378 nodeInfo.SetFocused(node->GetFocusedState());
379 nodeInfo.SetSelected(node->GetSelectedState());
380 nodeInfo.SetCheckable(node->GetCheckableState());
381 nodeInfo.SetClickable(node->GetClickableState());
382 nodeInfo.SetFocusable(node->GetFocusableState());
383 nodeInfo.SetScrollable(node->GetScrollableState());
384 nodeInfo.SetLongClickable(node->GetLongClickableState());
385 nodeInfo.SetEditable(node->GetEditable());
386 nodeInfo.SetPluraLineSupported(node->GetIsMultiLine());
387 nodeInfo.SetPassword(node->GetIsPassword());
388 nodeInfo.SetTextLengthLimit(node->GetMaxTextLength());
389 nodeInfo.SetSelectedBegin(node->GetTextSelectionStart());
390 nodeInfo.SetSelectedEnd(node->GetTextSelectionEnd());
391 nodeInfo.SetVisible(node->GetShown() && node->GetVisible());
392 nodeInfo.SetHint(node->GetHintText());
393 std::string accessibilityLabel = node->GetAccessibilityLabel();
394 nodeInfo.SetLabeled(atol(accessibilityLabel.c_str()));
395 nodeInfo.SetError(node->GetErrorText());
396 nodeInfo.SetComponentResourceId(node->GetJsComponentId());
397 nodeInfo.SetInspectorKey(node->GetJsComponentId());
398 RangeInfo rangeInfo = ConvertAccessibilityValue(node->GetAccessibilityValue());
399 nodeInfo.SetRange(rangeInfo);
400 nodeInfo.SetInputType(static_cast<int>(node->GetTextInputType()));
401 nodeInfo.SetComponentType(node->GetTag());
402 GridInfo gridInfo(
403 node->GetCollectionInfo().rows, node->GetCollectionInfo().columns, (nodeInfo.IsPluraLineSupported() ? 0 : 1));
404 nodeInfo.SetGrid(gridInfo);
405 nodeInfo.SetAccessibilityFocus(node->GetAccessibilityFocusedState());
406 nodeInfo.SetPageId(node->GetPageId());
407
408 int32_t row = node->GetCollectionItemInfo().row;
409 int32_t column = node->GetCollectionItemInfo().column;
410 GridItemInfo gridItemInfo(row, row, column, column, false, nodeInfo.IsSelected());
411 nodeInfo.SetGridItem(gridItemInfo);
412 nodeInfo.SetBundleName(AceApplicationInfo::GetInstance().GetPackageName());
413
414 if (node->GetTag() == LIST_TAG) {
415 nodeInfo.SetItemCounts(node->GetListItemCounts());
416 nodeInfo.SetBeginIndex(node->GetListBeginIndex());
417 nodeInfo.SetEndIndex(node->GetListEndIndex());
418 }
419 if (node->GetIsPassword()) {
420 std::string strStar(node->GetText().size(), '*');
421 nodeInfo.SetContent(strStar);
422 } else {
423 nodeInfo.SetContent(node->GetText());
424 }
425
426 auto supportAceActions = node->GetSupportAction();
427 std::vector<ActionType> actions(supportAceActions.size());
428
429 for (auto it = supportAceActions.begin(); it != supportAceActions.end(); ++it) {
430 AccessibleAction action(ConvertAceAction(*it), "ace");
431 nodeInfo.AddAction(action);
432 }
433
434 if (node->GetImportantForAccessibility() == NG::AccessibilityProperty::Level::YES_STR) {
435 actions.emplace_back(ActionType::ACCESSIBILITY_ACTION_FOCUS);
436 nodeInfo.SetCheckable(true);
437 } else if (node->GetImportantForAccessibility() == NG::AccessibilityProperty::Level::NO_STR ||
438 node->GetImportantForAccessibility() == NG::AccessibilityProperty::Level::NO_HIDE_DESCENDANTS) {
439 nodeInfo.SetVisible(false);
440 }
441 manager->UpdateNodeChildIds(node);
442 for (const auto& child : node->GetChildIds()) {
443 nodeInfo.AddChild(child);
444 }
445
446 #ifdef ACE_DEBUG
447 std::string actionForLog;
448 for (const auto& action : supportAceActions) {
449 if (!actionForLog.empty()) {
450 actionForLog.append(",");
451 }
452 actionForLog.append(std::to_string(static_cast<int32_t>(action)));
453 }
454 #endif
455 }
456
UpdateCacheInfo(std::list<AccessibilityElementInfo> & infos,uint32_t mode,const RefPtr<AccessibilityNode> & node,const RefPtr<JsAccessibilityManager> & jsAccessibilityManager,int windowId)457 void UpdateCacheInfo(std::list<AccessibilityElementInfo>& infos, uint32_t mode, const RefPtr<AccessibilityNode>& node,
458 const RefPtr<JsAccessibilityManager>& jsAccessibilityManager, int windowId)
459 {
460 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "elementId: %{public}d, mode: %{public}d", node->GetNodeId(), mode);
461 // parent
462 uint32_t umode = mode;
463 if (umode & static_cast<uint32_t>(PREFETCH_PREDECESSORS)) {
464 if (node->GetParentId() != -1 && node->GetParentId() != DEFAULT_PARENT_ID) {
465 AccessibilityElementInfo parentNodeInfo;
466 UpdateAccessibilityNodeInfo(node->GetParentNode(), parentNodeInfo, jsAccessibilityManager, windowId);
467 infos.emplace_back(parentNodeInfo);
468 }
469 }
470 // sister/brothers
471 if (umode & static_cast<uint32_t>(PREFETCH_SIBLINGS)) {
472 if (node->GetParentId() != -1 && node->GetParentId() != DEFAULT_PARENT_ID) {
473 for (const auto& item : node->GetParentNode()->GetChildList()) {
474 if (node->GetNodeId() != item->GetNodeId()) {
475 AccessibilityElementInfo siblingNodeInfo;
476 UpdateAccessibilityNodeInfo(item, siblingNodeInfo, jsAccessibilityManager, windowId);
477 infos.emplace_back(siblingNodeInfo);
478 }
479 }
480 }
481 }
482 // children
483 if (umode & static_cast<uint32_t>(PREFETCH_CHILDREN)) {
484 for (const auto& item : node->GetChildList()) {
485 AccessibilityElementInfo childNodeInfo;
486 UpdateAccessibilityNodeInfo(item, childNodeInfo, jsAccessibilityManager, windowId);
487 infos.emplace_back(childNodeInfo);
488 }
489 }
490
491 // get all children
492 if (umode & static_cast<uint32_t>(PREFETCH_RECURSIVE_CHILDREN)) {
493 std::list<RefPtr<AccessibilityNode>> children;
494 for (const auto& item : node->GetChildList()) {
495 children.emplace_back(item);
496 }
497
498 while (!children.empty()) {
499 auto parent = children.front();
500 children.pop_front();
501 AccessibilityElementInfo childNodeInfo;
502 UpdateAccessibilityNodeInfo(parent, childNodeInfo, jsAccessibilityManager, windowId);
503 infos.push_back(childNodeInfo);
504 for (const auto& item : parent->GetChildList()) {
505 children.emplace_back(item);
506 }
507 }
508 }
509 }
510
SortAccessibilityInfosByBreadth(std::list<AccessibilityElementInfo> & infos,std::list<int64_t> & accessibilityIdQueue,std::list<AccessibilityElementInfo> & output)511 void SortAccessibilityInfosByBreadth(std::list<AccessibilityElementInfo>& infos,
512 std::list<int64_t>& accessibilityIdQueue, std::list<AccessibilityElementInfo>& output)
513 {
514 while (!accessibilityIdQueue.empty()) {
515 auto accessibilityId = accessibilityIdQueue.front();
516 accessibilityIdQueue.pop_front();
517 for (std::list<AccessibilityElementInfo>::iterator info = infos.begin(); info != infos.end(); ++info) {
518 if (accessibilityId != info->GetAccessibilityId()) {
519 continue;
520 }
521 for (auto& child : info->GetChildIds()) {
522 accessibilityIdQueue.emplace_back(child);
523 }
524 output.emplace_back(*info);
525 infos.erase(info);
526 break;
527 }
528 SortAccessibilityInfosByBreadth(infos, accessibilityIdQueue, output);
529 }
530 }
531
SortExtensionAccessibilityInfo(std::list<AccessibilityElementInfo> & infos,int64_t rootAccessibilityId)532 void SortExtensionAccessibilityInfo(std::list<AccessibilityElementInfo>& infos, int64_t rootAccessibilityId)
533 {
534 auto input = infos;
535 infos.clear();
536 std::list<int64_t> accessibilityIdQueue;
537 accessibilityIdQueue.emplace_back(rootAccessibilityId);
538 SortAccessibilityInfosByBreadth(input, accessibilityIdQueue, infos);
539 }
540
ConvertExtensionAccessibilityId(AccessibilityElementInfo & info,const RefPtr<NG::FrameNode> & extensionNode,int64_t uiExtensionOffset,AccessibilityElementInfo & parentInfo)541 void ConvertExtensionAccessibilityId(AccessibilityElementInfo& info, const RefPtr<NG::FrameNode>& extensionNode,
542 int64_t uiExtensionOffset, AccessibilityElementInfo& parentInfo)
543 {
544 auto extensionAbilityId =
545 extensionNode->WrapExtensionAbilityId(uiExtensionOffset, info.GetAccessibilityId());
546 info.SetAccessibilityId(extensionAbilityId);
547 auto parentNodeId =
548 extensionNode->WrapExtensionAbilityId(uiExtensionOffset, info.GetParentNodeId());
549 info.SetParent(parentNodeId);
550 auto childIds = info.GetChildIds();
551 for (auto& child : childIds) {
552 info.RemoveChild(child);
553 info.AddChild(extensionNode->WrapExtensionAbilityId(uiExtensionOffset, child));
554 }
555 if (V2::ROOT_ETS_TAG == info.GetComponentType()) {
556 for (auto& child : info.GetChildIds()) {
557 parentInfo.AddChild(child);
558 }
559 }
560 }
561
ConvertExtensionAccessibilityNodeId(std::list<AccessibilityElementInfo> & infos,const RefPtr<NG::FrameNode> & extensionNode,int64_t uiExtensionOffset,AccessibilityElementInfo & parentInfo)562 void ConvertExtensionAccessibilityNodeId(std::list<AccessibilityElementInfo>& infos,
563 const RefPtr<NG::FrameNode>& extensionNode, int64_t uiExtensionOffset,
564 AccessibilityElementInfo& parentInfo)
565 {
566 CHECK_NULL_VOID(extensionNode);
567 for (auto& accessibilityElementInfo : infos) {
568 ConvertExtensionAccessibilityId(accessibilityElementInfo, extensionNode, uiExtensionOffset, parentInfo);
569 }
570 for (auto& accessibilityElementInfo : infos) {
571 if (std::find(parentInfo.GetChildIds().begin(), parentInfo.GetChildIds().end(),
572 accessibilityElementInfo.GetAccessibilityId()) != parentInfo.GetChildIds().end()) {
573 accessibilityElementInfo.SetParent(extensionNode->GetAccessibilityId());
574 }
575 }
576 }
577
BoolToString(bool tag)578 inline std::string BoolToString(bool tag)
579 {
580 return tag ? "true" : "false";
581 }
582
ConvertInputTypeToString(AceTextCategory type)583 std::string ConvertInputTypeToString(AceTextCategory type)
584 {
585 switch (type) {
586 case AceTextCategory::INPUT_TYPE_DEFAULT:
587 return "INPUT_TYPE_DEFAULT";
588 case AceTextCategory::INPUT_TYPE_TEXT:
589 return "INPUT_TYPE_TEXT";
590 case AceTextCategory::INPUT_TYPE_EMAIL:
591 return "INPUT_TYPE_EMAIL";
592 case AceTextCategory::INPUT_TYPE_DATE:
593 return "INPUT_TYPE_DATE";
594 case AceTextCategory::INPUT_TYPE_TIME:
595 return "INPUT_TYPE_TIME";
596 case AceTextCategory::INPUT_TYPE_NUMBER:
597 return "INPUT_TYPE_NUMBER";
598 case AceTextCategory::INPUT_TYPE_PASSWORD:
599 return "INPUT_TYPE_PASSWORD";
600 case AceTextCategory::INPUT_TYPE_PHONENUMBER:
601 return "INPUT_TYPE_PHONENUMBER";
602 case AceTextCategory::INPUT_TYPE_USER_NAME:
603 return "INPUT_TYPE_USER_NAME";
604 case AceTextCategory::INPUT_TYPE_NEW_PASSWORD:
605 return "INPUT_TYPE_NEW_PASSWORD";
606 default:
607 return "illegal input type";
608 }
609 }
610
FindAccessibilityFocus(const RefPtr<AccessibilityNode> & node,RefPtr<AccessibilityNode> & resultNode)611 bool FindAccessibilityFocus(const RefPtr<AccessibilityNode>& node, RefPtr<AccessibilityNode>& resultNode)
612 {
613 CHECK_NULL_RETURN(node, false);
614 if (node->GetAccessibilityFocusedState()) {
615 resultNode = node;
616 return true;
617 }
618 if (!node->GetChildList().empty()) {
619 for (const auto& item : node->GetChildList()) {
620 if (resultNode != nullptr) {
621 return true;
622 }
623 if (FindAccessibilityFocus(item, resultNode)) {
624 return true;
625 }
626 }
627 }
628
629 return false;
630 }
631
FindFocusedExtensionElementInfoNG(const SearchParameter & searchParam,const RefPtr<NG::FrameNode> & node,Accessibility::AccessibilityElementInfo & info)632 void FindFocusedExtensionElementInfoNG(const SearchParameter& searchParam,
633 const RefPtr<NG::FrameNode>& node, Accessibility::AccessibilityElementInfo& info)
634 {
635 if (NG::UI_EXTENSION_OFFSET_MIN < (searchParam.uiExtensionOffset + 1)) {
636 node->FindFocusedExtensionElementInfoNG(searchParam.nodeId, searchParam.mode,
637 searchParam.uiExtensionOffset / NG::UI_EXTENSION_ID_FACTOR, info);
638 } else {
639 info.SetValidElement(false);
640 }
641 }
642
SetUiExtensionAbilityParentIdForFocus(const RefPtr<NG::UINode> & uiExtensionNode,const int64_t uiExtensionOffset,Accessibility::AccessibilityElementInfo & info)643 void SetUiExtensionAbilityParentIdForFocus(const RefPtr<NG::UINode>& uiExtensionNode,
644 const int64_t uiExtensionOffset, Accessibility::AccessibilityElementInfo& info)
645 {
646 auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiExtensionNode);
647 if (frameNode) {
648 auto parentId = info.GetParentNodeId();
649 AccessibilityElementInfo parentInfo;
650 ConvertExtensionAccessibilityId(info, frameNode, uiExtensionOffset, parentInfo);
651 if (parentId == NG::UI_EXTENSION_ROOT_ID) {
652 info.SetParent(frameNode->GetAccessibilityId());
653 }
654 }
655 }
656
657 RefPtr<NG::FrameNode> GetFramenodeByAccessibilityId(const RefPtr<NG::FrameNode>& root, int64_t id);
658
FindAccessibilityFocus(const RefPtr<NG::UINode> & node,int32_t focusType,Accessibility::AccessibilityElementInfo & info,const int64_t uiExtensionOffset,const RefPtr<PipelineBase> & context,int64_t currentFocusNodeId)659 RefPtr<NG::FrameNode> FindAccessibilityFocus(const RefPtr<NG::UINode>& node,
660 int32_t focusType, Accessibility::AccessibilityElementInfo& info,
661 const int64_t uiExtensionOffset, const RefPtr<PipelineBase>& context, int64_t currentFocusNodeId)
662 {
663 CHECK_NULL_RETURN(node, nullptr);
664 auto frameNode = AceType::DynamicCast<NG::FrameNode>(node);
665 if (frameNode) {
666 if (frameNode->GetRenderContext()->GetAccessibilityFocus().value_or(false)) {
667 auto node = GetFramenodeByAccessibilityId(frameNode, currentFocusNodeId);
668 std::string finalNodeId = node ? std::to_string(node->GetAccessibilityId()) : "nullptr";
669 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY,
670 "currentFocusNodeId: %{public}" PRId64 ", result accessiblityId: %s",
671 currentFocusNodeId, finalNodeId.c_str());
672 return node;
673 }
674 }
675 if (node->GetChildren(true).empty()) {
676 return nullptr;
677 }
678 for (const auto& child : node->GetChildren(true)) {
679 auto extensionNode = AceType::DynamicCast<NG::FrameNode>(child);
680 if (IsIsolatedComponent(child) && extensionNode &&
681 !IsUIExtensionShowPlaceholder(extensionNode) &&
682 (extensionNode->GetUiExtensionId() > NG::UI_EXTENSION_UNKNOW_ID) &&
683 (((extensionNode->GetUiExtensionId() <= NG::UI_EXTENSION_ID_FIRST_MAX) &&
684 (NG::UI_EXTENSION_OFFSET_MAX == uiExtensionOffset)) ||
685 (extensionNode->GetUiExtensionId() <= NG::UI_EXTENSION_ID_OTHER_MAX))) {
686 SearchParameter transferSearchParam {NG::UI_EXTENSION_ROOT_ID, "", focusType, uiExtensionOffset};
687 OHOS::Ace::Framework::FindFocusedExtensionElementInfoNG(
688 transferSearchParam, extensionNode, info);
689 if (info.GetAccessibilityId() < 0) {
690 continue;
691 }
692 SetUiExtensionAbilityParentIdForFocus(extensionNode, uiExtensionOffset, info);
693 return extensionNode;
694 }
695 auto result = FindAccessibilityFocus(child, focusType, info, uiExtensionOffset, context, currentFocusNodeId);
696 if (result) {
697 return result;
698 }
699 }
700 return nullptr;
701 }
702
FindInputFocus(const RefPtr<AccessibilityNode> & node,RefPtr<AccessibilityNode> & resultNode)703 bool FindInputFocus(const RefPtr<AccessibilityNode>& node, RefPtr<AccessibilityNode>& resultNode)
704 {
705 CHECK_NULL_RETURN(node, false);
706 if (!node->GetFocusedState() && (node->GetParentId() != -1)) {
707 return false;
708 }
709 if (node->GetFocusedState()) {
710 resultNode = node;
711 }
712 if (!node->GetChildList().empty()) {
713 for (const auto& item : node->GetChildList()) {
714 if (FindInputFocus(item, resultNode)) {
715 return true;
716 }
717 }
718 }
719 return node->GetFocusedState();
720 }
721
FindInputFocus(const RefPtr<NG::UINode> & node,int32_t focusType,Accessibility::AccessibilityElementInfo & info,const int64_t uiExtensionOffset,const RefPtr<PipelineBase> & context)722 RefPtr<NG::FrameNode> FindInputFocus(const RefPtr<NG::UINode>& node, int32_t focusType,
723 Accessibility::AccessibilityElementInfo& info, const int64_t uiExtensionOffset,
724 const RefPtr<PipelineBase>& context)
725 {
726 auto frameNode = AceType::DynamicCast<NG::FrameNode>(node);
727 CHECK_NULL_RETURN(frameNode, nullptr);
728 if (!(frameNode->GetFocusHub() ? frameNode->GetFocusHub()->IsCurrentFocus() : false)) {
729 return nullptr;
730 }
731 if (frameNode->GetFocusHub()->IsChild()) {
732 if (frameNode->IsInternal()) {
733 return frameNode->GetFocusParent();
734 }
735 return frameNode;
736 }
737 auto focusHub = frameNode->GetFocusHub();
738 RefPtr<NG::FrameNode> target;
739 focusHub->AnyChildFocusHub([&target, &info, context, focusType, uiExtensionOffset](
740 const RefPtr<NG::FocusHub>& focusChild) {
741 auto extensionNode = focusChild->GetFrameNode();
742 if ((extensionNode && IsIsolatedComponent(extensionNode)) &&
743 !IsUIExtensionShowPlaceholder(extensionNode) &&
744 (extensionNode->GetUiExtensionId() > NG::UI_EXTENSION_UNKNOW_ID) &&
745 (((extensionNode->GetUiExtensionId() <= NG::UI_EXTENSION_ID_FIRST_MAX) &&
746 (NG::UI_EXTENSION_OFFSET_MAX == uiExtensionOffset)) ||
747 (extensionNode->GetUiExtensionId() <= NG::UI_EXTENSION_ID_OTHER_MAX))) {
748 SearchParameter transferSearchParam {NG::UI_EXTENSION_ROOT_ID, "", focusType, uiExtensionOffset};
749 OHOS::Ace::Framework::FindFocusedExtensionElementInfoNG(
750 transferSearchParam, extensionNode, info);
751 if (info.GetAccessibilityId() < 0) {
752 return false;
753 }
754 SetUiExtensionAbilityParentIdForFocus(extensionNode, uiExtensionOffset, info);
755 target = extensionNode;
756 return true;
757 }
758 target = FindInputFocus(focusChild->GetFrameNode(), focusType, info, uiExtensionOffset, context);
759 return target ? true : false;
760 });
761 return target;
762 }
763
FindText(const RefPtr<AccessibilityNode> & node,const std::string & text,std::list<RefPtr<AccessibilityNode>> & nodeList)764 void FindText(
765 const RefPtr<AccessibilityNode>& node, const std::string& text, std::list<RefPtr<AccessibilityNode>>& nodeList)
766 {
767 CHECK_NULL_VOID(node);
768 if (node->GetText().find(text) != std::string::npos) {
769 nodeList.push_back(node);
770 }
771 if (!node->GetChildList().empty()) {
772 for (const auto& child : node->GetChildList()) {
773 FindText(child, text, nodeList);
774 }
775 }
776 }
777
FindText(const RefPtr<NG::UINode> & node,const std::string & text,std::list<RefPtr<NG::FrameNode>> & nodeList)778 void FindText(const RefPtr<NG::UINode>& node, const std::string& text, std::list<RefPtr<NG::FrameNode>>& nodeList)
779 {
780 CHECK_NULL_VOID(node);
781
782 auto frameNode = AceType::DynamicCast<NG::FrameNode>(node);
783 if (frameNode && !frameNode->IsInternal()) {
784 if (frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>()->GetGroupText().find(text) !=
785 std::string::npos) {
786 nodeList.push_back(frameNode);
787 }
788 }
789
790 if (!node->GetChildren(true).empty()) {
791 for (const auto& child : node->GetChildren(true)) {
792 FindText(child, text, nodeList);
793 }
794 }
795 }
796
FindFrameNodeByAccessibilityId(int64_t id,const std::list<RefPtr<NG::UINode>> & children,std::queue<NG::UINode * > & nodes,RefPtr<NG::FrameNode> & result)797 bool FindFrameNodeByAccessibilityId(int64_t id, const std::list<RefPtr<NG::UINode>>& children,
798 std::queue<NG::UINode*>& nodes, RefPtr<NG::FrameNode>& result)
799 {
800 NG::FrameNode* frameNode = nullptr;
801 for (const auto& child : children) {
802 frameNode = AceType::DynamicCast<NG::FrameNode>(Referenced::RawPtr(child));
803 if (frameNode != nullptr && !frameNode->CheckAccessibilityLevelNo()) {
804 if (frameNode->GetAccessibilityId() == id) {
805 result = AceType::DynamicCast<NG::FrameNode>(child);
806 return true;
807 }
808 }
809 nodes.push(Referenced::RawPtr(child));
810 }
811 return false;
812 }
813
GetFramenodeByAccessibilityId(const RefPtr<NG::FrameNode> & root,int64_t id)814 RefPtr<NG::FrameNode> GetFramenodeByAccessibilityId(const RefPtr<NG::FrameNode>& root, int64_t id)
815 {
816 CHECK_NULL_RETURN(root, nullptr);
817 if (root->GetAccessibilityId() == id) {
818 return root;
819 }
820 std::queue<NG::UINode*> nodes;
821 nodes.push(Referenced::RawPtr(root));
822 RefPtr<NG::FrameNode> frameNodeResult = nullptr;
823
824 while (!nodes.empty()) {
825 auto current = nodes.front();
826 nodes.pop();
827 if (current->HasVirtualNodeAccessibilityProperty()) {
828 auto fnode = AceType::DynamicCast<NG::FrameNode>(current);
829 auto property = fnode->GetAccessibilityProperty<NG::AccessibilityProperty>();
830 const auto& children = std::list<RefPtr<NG::UINode>> { property->GetAccessibilityVirtualNode() };
831 if (FindFrameNodeByAccessibilityId(id, children, nodes, frameNodeResult)) {
832 return frameNodeResult;
833 }
834 } else {
835 const auto& children = current->GetChildren(true);
836 if (FindFrameNodeByAccessibilityId(id, children, nodes, frameNodeResult)) {
837 return frameNodeResult;
838 }
839 }
840 auto frameNode = AceType::DynamicCast<NG::FrameNode>(current);
841 if (!frameNode) {
842 continue;
843 }
844 auto overlayNode = frameNode->GetOverlayNode();
845 if (overlayNode) {
846 const auto& children = std::list<RefPtr<NG::UINode>> { overlayNode };
847 if (FindFrameNodeByAccessibilityId(id, children, nodes, frameNodeResult)) {
848 return frameNodeResult;
849 }
850 }
851 }
852 return nullptr;
853 }
854
855 using FindCondition = std::function<bool(const RefPtr<NG::FrameNode>&)>;
856
FindFrameNodeByCondition(const std::list<RefPtr<NG::UINode>> & children,std::queue<RefPtr<NG::UINode>> & nodes,RefPtr<NG::FrameNode> & result,FindCondition condition)857 bool FindFrameNodeByCondition(const std::list<RefPtr<NG::UINode>>& children,
858 std::queue<RefPtr<NG::UINode>>& nodes, RefPtr<NG::FrameNode>& result, FindCondition condition)
859 {
860 for (const auto& child : children) {
861 auto frameNode = AceType::DynamicCast<NG::FrameNode>(child);
862 if (frameNode != nullptr && !frameNode->CheckAccessibilityLevelNo()) {
863 if (condition(frameNode)) {
864 result = frameNode;
865 return true;
866 }
867 }
868 nodes.push(child);
869 }
870 return false;
871 }
872
GetFramenodeByCondition(const RefPtr<NG::FrameNode> & root,FindCondition condition)873 RefPtr<NG::FrameNode> GetFramenodeByCondition(const RefPtr<NG::FrameNode>& root, FindCondition condition)
874 {
875 CHECK_NULL_RETURN(root, nullptr);
876
877 std::queue<RefPtr<NG::UINode>> nodes;
878 nodes.push(root);
879 RefPtr<NG::FrameNode> frameNodeResult = nullptr;
880
881 while (!nodes.empty()) {
882 auto current = nodes.front();
883 nodes.pop();
884 if (current->HasVirtualNodeAccessibilityProperty()) {
885 auto fnode = AceType::DynamicCast<NG::FrameNode>(current);
886 auto property = fnode->GetAccessibilityProperty<NG::AccessibilityProperty>();
887 const auto& children = std::list<RefPtr<NG::UINode>> { property->GetAccessibilityVirtualNode() };
888 if (FindFrameNodeByCondition(children, nodes, frameNodeResult, condition)) {
889 return frameNodeResult;
890 }
891 } else {
892 const auto& children = current->GetChildren(true);
893 if (FindFrameNodeByCondition(children, nodes, frameNodeResult, condition)) {
894 return frameNodeResult;
895 }
896 }
897 auto frameNode = AceType::DynamicCast<NG::FrameNode>(current);
898 if (!frameNode) {
899 continue;
900 }
901 auto overlayNode = frameNode->GetOverlayNode();
902 if (overlayNode) {
903 const auto& children = std::list<RefPtr<NG::UINode>> { overlayNode };
904 if (FindFrameNodeByCondition(children, nodes, frameNodeResult, condition)) {
905 return frameNodeResult;
906 }
907 }
908 }
909 return nullptr;
910 }
911
GetFrameNodeParent(const RefPtr<NG::UINode> & uiNode,RefPtr<NG::FrameNode> & parent)912 void GetFrameNodeParent(const RefPtr<NG::UINode>& uiNode, RefPtr<NG::FrameNode>& parent)
913 {
914 if (AceType::InstanceOf<NG::FrameNode>(uiNode)) {
915 auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
916 if (!frameNode->IsInternal()) {
917 parent = frameNode;
918 return;
919 }
920 }
921 CHECK_NULL_VOID(uiNode);
922 auto parentNode = uiNode->GetParent();
923 GetFrameNodeParent(parentNode, parent);
924 }
925
CheckFrameNodeByAccessibilityLevel(const RefPtr<NG::FrameNode> & frameNode,bool isParent)926 bool CheckFrameNodeByAccessibilityLevel(const RefPtr<NG::FrameNode>& frameNode, bool isParent)
927 {
928 return true;
929 }
930
IsInPageNodes(int32_t pageId,const std::vector<RefPtr<NG::FrameNode>> & pageNodes)931 bool IsInPageNodes(int32_t pageId, const std::vector<RefPtr<NG::FrameNode>>& pageNodes)
932 {
933 for (const auto& page : pageNodes) {
934 CHECK_NULL_CONTINUE(page);
935 if (pageId == page->GetPageId()) {
936 return true;
937 }
938 }
939 return false;
940 }
941
CheckAndSetAccessibilityVisible(const RefPtr<NG::FrameNode> & node,bool isReduceMode=false)942 bool CheckAndSetAccessibilityVisible(const RefPtr<NG::FrameNode>& node, bool isReduceMode = false)
943 {
944 if (!isReduceMode) {
945 return true;
946 }
947 auto parentNode = node->GetParentFrameNode();
948 if (!parentNode) {
949 if (node->GetTag() != V2::PAGE_ETS_TAG) {
950 node->SetAccessibilityVisible(node->IsActive() && node->IsVisible());
951 }
952 } else {
953 if (node->GetTag() == V2::PAGE_ETS_TAG) {
954 return node->GetAccessibilityVisible();
955 }
956 auto nodeAccessibilityVisible = node->IsActive() && node->IsVisible() && parentNode->GetAccessibilityVisible();
957 node->SetAccessibilityVisible(nodeAccessibilityVisible);
958 }
959 return node->GetAccessibilityVisible();
960 }
961
GetFrameNodeChildren(const RefPtr<NG::UINode> & uiNode,std::vector<std::pair<int64_t,int32_t>> & childrenIdInfo,const CommonProperty & commonProperty)962 void GetFrameNodeChildren(
963 const RefPtr<NG::UINode>& uiNode,
964 std::vector<std::pair<int64_t, int32_t>>& childrenIdInfo,
965 const CommonProperty& commonProperty)
966 {
967 auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
968 if (AceType::InstanceOf<NG::FrameNode>(uiNode)) {
969 if (!frameNode->IsFirstVirtualNode()) {
970 CHECK_NULL_VOID(frameNode->IsActive());
971 }
972 if (uiNode->GetTag() == "stage") {
973 } else if (uiNode->GetTag() == "page") {
974 if (!IsInPageNodes(uiNode->GetPageId(), commonProperty.pageNodes)) {
975 return;
976 }
977 } else if (!frameNode->IsInternal() || frameNode->IsFirstVirtualNode()) {
978 if (CheckFrameNodeByAccessibilityLevel(frameNode, false) &&
979 CheckAndSetAccessibilityVisible(frameNode, commonProperty.isReduceMode)) {
980 auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
981 childrenIdInfo.emplace_back(
982 std::make_pair(frameNode->GetAccessibilityId(),
983 accessibilityProperty ? accessibilityProperty->GetAccessibilityZIndex() : -1));
984 return;
985 }
986 }
987 }
988
989 if (frameNode) {
990 auto overlayNode = frameNode->GetOverlayNode();
991 if (overlayNode) {
992 GetFrameNodeChildren(overlayNode, childrenIdInfo, commonProperty);
993 }
994 }
995
996 if (AceType::InstanceOf<NG::FrameNode>(uiNode)) {
997 auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
998 auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
999 auto uiVirtualNode = accessibilityProperty->GetAccessibilityVirtualNode();
1000 if (uiVirtualNode != nullptr) {
1001 auto virtualNode = AceType::DynamicCast<NG::FrameNode>(uiVirtualNode);
1002 if (virtualNode != nullptr) {
1003 GetFrameNodeChildren(virtualNode, childrenIdInfo, commonProperty);
1004 return;
1005 }
1006 }
1007 }
1008
1009 for (const auto& frameChild : uiNode->GetChildren(true)) {
1010 GetFrameNodeChildren(frameChild, childrenIdInfo, commonProperty);
1011 }
1012 }
1013
GetFrameNodeChildren(const RefPtr<NG::UINode> & uiNode,std::list<RefPtr<NG::FrameNode>> & children,const CommonProperty & commonProperty)1014 void GetFrameNodeChildren(
1015 const RefPtr<NG::UINode>& uiNode,
1016 std::list<RefPtr<NG::FrameNode>>& children,
1017 const CommonProperty& commonProperty)
1018 {
1019 auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
1020 if (frameNode) {
1021 CHECK_NULL_VOID(frameNode->IsActive());
1022 if (uiNode->GetTag() == "page") {
1023 if (!commonProperty.pageNodes.empty() && !IsInPageNodes(uiNode->GetPageId(), commonProperty.pageNodes)) {
1024 return;
1025 }
1026 } else if (!frameNode->IsInternal() && uiNode->GetTag() != "stage") {
1027 if (CheckFrameNodeByAccessibilityLevel(frameNode, false)&&
1028 CheckAndSetAccessibilityVisible(frameNode, commonProperty.isReduceMode)) {
1029 children.emplace_back(frameNode);
1030 return;
1031 }
1032 }
1033
1034 auto overlayNode = frameNode->GetOverlayNode();
1035 if (overlayNode) {
1036 GetFrameNodeChildren(overlayNode, children, commonProperty);
1037 }
1038
1039 auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
1040 auto uiVirtualNode = accessibilityProperty->GetAccessibilityVirtualNode();
1041 if (uiVirtualNode != nullptr) {
1042 auto virtualNode = AceType::DynamicCast<NG::FrameNode>(uiVirtualNode);
1043 if (virtualNode != nullptr) {
1044 GetFrameNodeChildren(virtualNode, children, commonProperty);
1045 return;
1046 }
1047 }
1048 }
1049
1050 for (const auto& frameChild : uiNode->GetChildren(true)) {
1051 GetFrameNodeChildren(frameChild, children, commonProperty);
1052 }
1053 }
1054
GetNodeAccessibilityVisible(const RefPtr<NG::FrameNode> & frameNode,bool isAllAncestorAccessibilityVisible,bool clipVisible)1055 bool GetNodeAccessibilityVisible(const RefPtr<NG::FrameNode>& frameNode, bool isAllAncestorAccessibilityVisible,
1056 bool clipVisible)
1057 {
1058 if (frameNode->IsFirstVirtualNode()) {
1059 return frameNode->IsVisible() && isAllAncestorAccessibilityVisible && clipVisible;
1060 } else {
1061 return frameNode->IsActive() && frameNode->IsVisible() && isAllAncestorAccessibilityVisible && clipVisible;
1062 }
1063 }
1064
ProcessParentFrameNode(const RefPtr<NG::UINode> & parent,std::string & parentPath,bool & isAllAncestorAccessibilityVisible)1065 bool ProcessParentFrameNode(
1066 const RefPtr<NG::UINode>& parent, std::string& parentPath, bool& isAllAncestorAccessibilityVisible)
1067 {
1068 auto parentFrameNode = AceType::DynamicCast<NG::FrameNode>(parent);
1069 if (parentFrameNode->CheckAccessibilityLevelNo()) {
1070 return false;
1071 }
1072
1073 parentPath += "Parent ID: " + std::to_string(parent->GetAccessibilityId()) +
1074 " IsActive: " + std::to_string(parentFrameNode->IsActive()) +
1075 " IsVisible: " + std::to_string(parentFrameNode->IsVisible()) +
1076 " AccessibilityVisible: " + std::to_string(parentFrameNode->GetAccessibilityVisible()) +
1077 " Parent Tag: " + parent->GetTag() + " | ";
1078
1079 if (parent->GetTag() == V2::PAGE_ETS_TAG) {
1080 isAllAncestorAccessibilityVisible = parentFrameNode->GetAccessibilityVisible();
1081 } else if (parentFrameNode->IsFirstVirtualNode()) {
1082 isAllAncestorAccessibilityVisible = parentFrameNode->IsVisible();
1083 } else {
1084 isAllAncestorAccessibilityVisible = parentFrameNode->IsActive() && parentFrameNode->IsVisible();
1085 }
1086
1087 return !isAllAncestorAccessibilityVisible;
1088 }
1089
GetInitialParent(const RefPtr<NG::UINode> & uiNode)1090 RefPtr<NG::UINode> GetInitialParent(const RefPtr<NG::UINode>& uiNode)
1091 {
1092 if (AceType::InstanceOf<NG::FrameNode>(uiNode)) {
1093 auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
1094 if (frameNode->IsFirstVirtualNode()) {
1095 auto weakNode = frameNode->GetVirtualNodeParent();
1096 return weakNode.Upgrade();
1097 } else {
1098 return uiNode->GetParent();
1099 }
1100 }
1101 return nullptr;
1102 }
1103
SetRootAccessibilityVisible(const RefPtr<NG::UINode> & uiNode,AccessibilityElementInfo & nodeInfo)1104 void SetRootAccessibilityVisible(const RefPtr<NG::UINode>& uiNode, AccessibilityElementInfo& nodeInfo)
1105 {
1106 RefPtr<NG::UINode> parent = GetInitialParent(uiNode);
1107 bool isAllAncestorAccessibilityVisible = true;
1108 bool clipVisible = true;
1109 auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
1110 OHOS::Ace::NG::RectF frameRect;
1111 OHOS::Ace::NG::RectF visibleInnerRect;
1112 OHOS::Ace::NG::RectF visibleRect;
1113 frameNode->SetIsCalculateInnerVisibleRectClip(true);
1114 frameNode->GetVisibleRectWithClip(visibleRect, visibleInnerRect, frameRect);
1115 bool isClipCheckSkip = NearEqual(visibleRect.Width(), 0.0) && NearEqual(visibleRect.Height(), 0.0) &&
1116 NearEqual(visibleInnerRect.Width(), 0.0) && NearEqual(visibleInnerRect.Height(), 0.0);
1117 clipVisible = (GreatNotEqual(visibleInnerRect.Width(), 0.0) && GreatNotEqual(visibleInnerRect.Height(), 0.0)) ||
1118 isClipCheckSkip;
1119 auto renderContext = frameNode->GetRenderContext();
1120 CHECK_NULL_VOID(renderContext);
1121 auto rect = renderContext->GetPaintRectWithoutTransform();
1122 if (NearEqual(rect.Width(), 0.0) && NearEqual(rect.Height(), 0.0)) {
1123 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "Component %{public}s is not visible: width and height are both zero.",
1124 std::to_string(frameNode->GetAccessibilityId()).c_str());
1125 clipVisible = false;
1126 }
1127 std::string parentPath;
1128 while (parent) {
1129 if (AceType::InstanceOf<NG::FrameNode>(parent)) {
1130 if (ProcessParentFrameNode(parent, parentPath, isAllAncestorAccessibilityVisible)) {
1131 break;
1132 }
1133 }
1134 parent = parent->GetParent();
1135 }
1136 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "Complete parent path:current id %{public}" PRId64 " %{public}s",
1137 nodeInfo.GetAccessibilityId(), parentPath.c_str());
1138
1139 bool nodeAccessibilityVisible =
1140 GetNodeAccessibilityVisible(frameNode, isAllAncestorAccessibilityVisible, clipVisible);
1141 if (!nodeAccessibilityVisible) {
1142 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY,
1143 "Element %{public}" PRId64 " is invisible. isActive %{public}d, isVisible %{public}d"
1144 " isAllAncestorAccessibilityVisible:%{public}d clipVisible:%{public}d",
1145 nodeInfo.GetAccessibilityId(), frameNode->IsActive(), frameNode->IsVisible(),
1146 isAllAncestorAccessibilityVisible, clipVisible);
1147 }
1148
1149 if (frameNode->GetTag() != V2::PAGE_ETS_TAG) {
1150 frameNode->SetAccessibilityVisible(nodeAccessibilityVisible);
1151 }
1152 nodeInfo.SetAccessibilityVisible(frameNode->GetAccessibilityVisible());
1153 }
1154
SetRootAccessibilityNextFocusId(const RefPtr<NG::UINode> & currentNode,const RefPtr<NG::FrameNode> & rootNode,AccessibilityElementInfo & nodeInfo)1155 void SetRootAccessibilityNextFocusId(const RefPtr<NG::UINode>& currentNode, const RefPtr<NG::FrameNode>& rootNode,
1156 AccessibilityElementInfo& nodeInfo)
1157 {
1158 auto currentFrameNode = AceType::DynamicCast<NG::FrameNode>(currentNode);
1159 CHECK_NULL_VOID(currentFrameNode);
1160 auto accessibilityProperty = currentFrameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
1161 CHECK_NULL_VOID(accessibilityProperty);
1162 if (accessibilityProperty->GetAccessibilityNextFocusInspectorKey() == "") {
1163 return;
1164 }
1165
1166 FindCondition condition = [accessibilityProperty](const RefPtr<NG::FrameNode>& node) {
1167 return node->GetInspectorId() == accessibilityProperty->GetAccessibilityNextFocusInspectorKey();
1168 };
1169 auto nextNode = GetFramenodeByCondition(rootNode, condition);
1170 CHECK_NULL_VOID(nextNode);
1171 nodeInfo.SetAccessibilityNextFocusId(nextNode->GetAccessibilityId());
1172 }
1173
SetRootAccessibilityPreFocusId(const RefPtr<NG::UINode> & currentNode,const RefPtr<NG::FrameNode> & rootNode,AccessibilityElementInfo & nodeInfo)1174 void SetRootAccessibilityPreFocusId(const RefPtr<NG::UINode>& currentNode, const RefPtr<NG::FrameNode>& rootNode,
1175 AccessibilityElementInfo& nodeInfo)
1176 {
1177 auto currentFrameNode = AceType::DynamicCast<NG::FrameNode>(currentNode);
1178 CHECK_NULL_VOID(currentFrameNode);
1179
1180 auto currentInspectorId = currentFrameNode->GetInspectorId();
1181 if (currentInspectorId != "") {
1182 FindCondition preCondition = [currentInspectorId](const RefPtr<NG::FrameNode>& node) {
1183 auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
1184 return currentInspectorId == accessibilityProperty->GetAccessibilityNextFocusInspectorKey();
1185 };
1186 auto preNode = GetFramenodeByCondition(rootNode, preCondition);
1187 CHECK_NULL_VOID(preNode);
1188 nodeInfo.SetAccessibilityPreviousFocusId(preNode->GetAccessibilityId());
1189 }
1190 }
1191
GetParentId(const RefPtr<NG::UINode> & uiNode)1192 int64_t GetParentId(const RefPtr<NG::UINode>& uiNode)
1193 {
1194 if (AceType::InstanceOf<NG::FrameNode>(uiNode)) {
1195 if (AceType::DynamicCast<NG::FrameNode>(uiNode)->IsFirstVirtualNode()) {
1196 auto weakNode = AceType::DynamicCast<NG::FrameNode>(uiNode)->GetVirtualNodeParent();
1197 auto refNode = weakNode.Upgrade();
1198 return refNode == nullptr ? INVALID_PARENT_ID : refNode->GetAccessibilityId();
1199 }
1200 }
1201 auto parent = uiNode->GetParent();
1202 while (parent) {
1203 if (AceType::InstanceOf<NG::FrameNode>(parent)) {
1204 if ((parent->GetTag() == V2::PAGE_ETS_TAG) || (parent->GetTag() == V2::STAGE_ETS_TAG) ||
1205 AceType::DynamicCast<NG::FrameNode>(parent)->CheckAccessibilityLevelNo()) {
1206 parent = parent->GetParent();
1207 continue;
1208 }
1209 return parent->GetAccessibilityId();
1210 }
1211 parent = parent->GetParent();
1212 }
1213 return INVALID_PARENT_ID;
1214 }
1215
FillElementInfo(int64_t elementId,AccessibilityElementInfo & elementInfo,const RefPtr<PipelineBase> & context,const RefPtr<JsAccessibilityManager> & jsAccessibilityManager,const FillEventInfoParam & param)1216 void FillElementInfo(int64_t elementId, AccessibilityElementInfo& elementInfo, const RefPtr<PipelineBase>& context,
1217 const RefPtr<JsAccessibilityManager>& jsAccessibilityManager, const FillEventInfoParam& param)
1218 {
1219 int64_t elementIdUnwrap = elementId;
1220 int64_t uiextensionId = 0;
1221 std::list<AccessibilityElementInfo> elementInfos;
1222 int32_t mode = 0;
1223 CHECK_NULL_VOID(jsAccessibilityManager);
1224 #ifdef WINDOW_SCENE_SUPPORTED
1225 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
1226 auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
1227 CHECK_NULL_VOID(uiExtensionManager);
1228 if (uiExtensionManager->IsWrapExtensionAbilityId(elementId)) {
1229 auto unWrapIdPair = uiExtensionManager->UnWrapExtensionAbilityId(
1230 NG::UI_EXTENSION_OFFSET_MAX, elementIdUnwrap);
1231 elementIdUnwrap = unWrapIdPair.second;
1232 uiextensionId = unWrapIdPair.first;
1233 }
1234 #endif
1235 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY,
1236 "start to search elementId: %{public}" PRId64, elementIdUnwrap);
1237 jsAccessibilityManager->SearchElementInfoByAccessibilityIdNG(
1238 elementIdUnwrap, mode, elementInfos, context, NG::UI_EXTENSION_OFFSET_MAX);
1239 if (elementInfos.empty()) {
1240 LOGE("Element infos is empty. Find element infos failed.");
1241 return;
1242 }
1243 elementInfo = elementInfos.front();
1244 if (uiextensionId > 0) {
1245 elementIdUnwrap = (uiextensionId * NG::UI_EXTENSION_OFFSET_MAX) + elementInfo.GetAccessibilityId();
1246 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "elementIdUnwrap: %{public}" PRId64, elementIdUnwrap);
1247 }
1248 elementInfo.SetAccessibilityId(elementIdUnwrap);
1249 elementInfo.SetWindowId(param.windowId);
1250 jsAccessibilityManager->UpdateElementInfoInnerWindowId(elementInfo, elementId);
1251 }
1252
FillEventInfo(const RefPtr<NG::FrameNode> & node,AccessibilityEventInfo & eventInfo,const RefPtr<PipelineBase> & context,const RefPtr<JsAccessibilityManager> & jsAccessibilityManager,const FillEventInfoParam & param)1253 void FillEventInfo(const RefPtr<NG::FrameNode>& node,
1254 AccessibilityEventInfo& eventInfo,
1255 const RefPtr<PipelineBase>& context,
1256 const RefPtr<JsAccessibilityManager>& jsAccessibilityManager,
1257 const FillEventInfoParam& param)
1258 {
1259 CHECK_NULL_VOID(node);
1260 eventInfo.SetComponentType(node->GetTag());
1261 eventInfo.SetPageId(node->GetPageId());
1262 auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
1263 CHECK_NULL_VOID(accessibilityProperty);
1264 eventInfo.SetItemCounts(accessibilityProperty->GetCollectionItemCounts());
1265 eventInfo.SetBeginIndex(accessibilityProperty->GetBeginIndex());
1266 eventInfo.SetEndIndex(accessibilityProperty->GetEndIndex());
1267 AccessibilityElementInfo elementInfo;
1268 FillElementInfo(param.elementId, elementInfo, context, jsAccessibilityManager, param);
1269 if (param.stackNodeId != -1) {
1270 int64_t stackNodeId = param.stackNodeId;
1271 AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(elementInfo.GetBelongTreeId(), stackNodeId);
1272 elementInfo.SetNavDestinationId(stackNodeId);
1273 }
1274 eventInfo.AddContent(elementInfo.GetContent());
1275 eventInfo.SetElementInfo(elementInfo);
1276 }
1277 #ifdef WEB_SUPPORTED
1278
FillWebElementInfo(int64_t elementId,AccessibilityElementInfo & elementInfo,const RefPtr<PipelineBase> & context,const RefPtr<JsAccessibilityManager> & jsAccessibilityManager,const FillEventInfoParam & param,const RefPtr<NG::WebPattern> & webPattern)1279 void FillWebElementInfo(int64_t elementId, AccessibilityElementInfo& elementInfo,
1280 const RefPtr<PipelineBase>& context,
1281 const RefPtr<JsAccessibilityManager>& jsAccessibilityManager,
1282 const FillEventInfoParam& param,
1283 const RefPtr<NG::WebPattern>& webPattern)
1284 {
1285 std::list<AccessibilityElementInfo> elementInfos;
1286 int32_t mode = 0;
1287 CHECK_NULL_VOID(jsAccessibilityManager);
1288 jsAccessibilityManager->SearchWebElementInfoByAccessibilityIdNG(
1289 elementId, mode, elementInfos, context, webPattern);
1290 if (elementInfos.empty()) {
1291 LOGE("Element infos is empty. Find element infos failed.");
1292 return;
1293 }
1294 elementInfo = elementInfos.front();
1295 elementInfo.SetWindowId(param.windowId);
1296 }
1297
FillWebEventInfo(AccessibilityEventInfo & eventInfo,const RefPtr<PipelineBase> & context,const RefPtr<JsAccessibilityManager> & jsAccessibilityManager,const FillEventInfoParam & param,const RefPtr<NG::WebPattern> & webPattern)1298 void FillWebEventInfo(AccessibilityEventInfo& eventInfo,
1299 const RefPtr<PipelineBase>& context,
1300 const RefPtr<JsAccessibilityManager>& jsAccessibilityManager,
1301 const FillEventInfoParam& param,
1302 const RefPtr<NG::WebPattern>& webPattern)
1303 {
1304 CHECK_NULL_VOID(webPattern);
1305 auto webNode = webPattern->GetHost();
1306 CHECK_NULL_VOID(webNode);
1307 eventInfo.SetPageId(webNode->GetPageId());
1308 AccessibilityElementInfo elementInfo;
1309 FillWebElementInfo(param.elementId, elementInfo, context, jsAccessibilityManager, param, webPattern);
1310 eventInfo.SetComponentType(elementInfo.GetComponentType());
1311 eventInfo.AddContent(elementInfo.GetContent());
1312 eventInfo.SetItemCounts(elementInfo.GetItemCounts());
1313 eventInfo.SetBeginIndex(elementInfo.GetBeginIndex());
1314 eventInfo.SetEndIndex(elementInfo.GetEndIndex());
1315 elementInfo.SetNavDestinationId(param.stackNodeId);
1316 eventInfo.SetElementInfo(elementInfo);
1317 }
1318 #endif
1319
FillEventInfo(const RefPtr<AccessibilityNode> & node,AccessibilityEventInfo & eventInfo)1320 void FillEventInfo(const RefPtr<AccessibilityNode>& node, AccessibilityEventInfo& eventInfo)
1321 {
1322 eventInfo.SetComponentType(node->GetTag());
1323 if (node->GetTag() == LIST_TAG) {
1324 eventInfo.SetItemCounts(node->GetListItemCounts());
1325 eventInfo.SetBeginIndex(node->GetListBeginIndex());
1326 eventInfo.SetEndIndex(node->GetListEndIndex());
1327 }
1328 eventInfo.SetPageId(node->GetPageId());
1329 eventInfo.AddContent(node->GetText());
1330 eventInfo.SetLatestContent(node->GetText());
1331 }
1332
IsPopupSupported(const RefPtr<NG::PipelineContext> & pipeline,int64_t nodeId)1333 inline bool IsPopupSupported(const RefPtr<NG::PipelineContext>& pipeline, int64_t nodeId)
1334 {
1335 CHECK_NULL_RETURN(pipeline, false);
1336 auto overlayManager = pipeline->GetOverlayManager();
1337 if (overlayManager) {
1338 return overlayManager->HasPopupInfo(nodeId);
1339 }
1340 return false;
1341 }
1342
SetAccessibilityFocusAction(AccessibilityElementInfo & nodeInfo,const char * tag)1343 void SetAccessibilityFocusAction(AccessibilityElementInfo& nodeInfo, const char* tag)
1344 {
1345 if (nodeInfo.HasAccessibilityFocus()) {
1346 AccessibleAction action(ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS, tag);
1347 nodeInfo.AddAction(action);
1348 } else {
1349 AccessibleAction action(ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS, tag);
1350 nodeInfo.AddAction(action);
1351 }
1352 }
1353
UpdateSupportAction(const RefPtr<NG::FrameNode> & node,AccessibilityElementInfo & nodeInfo)1354 void UpdateSupportAction(const RefPtr<NG::FrameNode>& node, AccessibilityElementInfo& nodeInfo)
1355 {
1356 CHECK_NULL_VOID(node);
1357 if (nodeInfo.IsFocusable()) {
1358 if (nodeInfo.IsFocused()) {
1359 AccessibleAction action(ACCESSIBILITY_ACTION_CLEAR_FOCUS, "ace");
1360 nodeInfo.AddAction(action);
1361 } else {
1362 AccessibleAction action(ACCESSIBILITY_ACTION_FOCUS, "ace");
1363 nodeInfo.AddAction(action);
1364 }
1365 }
1366
1367 auto eventHub = node->GetEventHub<NG::EventHub>();
1368 CHECK_NULL_VOID(eventHub);
1369 auto gestureEventHub = eventHub->GetGestureEventHub();
1370 CHECK_NULL_VOID(gestureEventHub);
1371 nodeInfo.SetClickable(gestureEventHub->IsAccessibilityClickable());
1372 if (gestureEventHub->IsAccessibilityClickable()) {
1373 AccessibleAction action(ACCESSIBILITY_ACTION_CLICK, "ace");
1374 nodeInfo.AddAction(action);
1375 }
1376 nodeInfo.SetLongClickable(gestureEventHub->IsAccessibilityLongClickable());
1377 if (gestureEventHub->IsAccessibilityLongClickable()) {
1378 AccessibleAction action(ACCESSIBILITY_ACTION_LONG_CLICK, "ace");
1379 nodeInfo.AddAction(action);
1380 }
1381 }
1382
UpdateUserAccessibilityElementInfo(const RefPtr<NG::AccessibilityProperty> & accessibilityProperty,AccessibilityElementInfo & nodeInfo)1383 void UpdateUserAccessibilityElementInfo(
1384 const RefPtr<NG::AccessibilityProperty>& accessibilityProperty, AccessibilityElementInfo& nodeInfo)
1385 {
1386 CHECK_NULL_VOID(accessibilityProperty);
1387 if (accessibilityProperty->HasUserDisabled()) {
1388 nodeInfo.SetEnabled(!accessibilityProperty->IsUserDisabled());
1389 }
1390 if (accessibilityProperty->HasUserCheckedType()) {
1391 nodeInfo.SetChecked(accessibilityProperty->GetUserCheckedType());
1392 } else {
1393 nodeInfo.SetChecked(accessibilityProperty->IsChecked());
1394 }
1395 if (accessibilityProperty->HasUserSelected()) {
1396 nodeInfo.SetSelected(accessibilityProperty->IsUserSelected());
1397 } else {
1398 nodeInfo.SetSelected(accessibilityProperty->IsSelected());
1399 }
1400
1401 if (nodeInfo.IsEnabled()) {
1402 if (accessibilityProperty->HasUserCheckable()) {
1403 nodeInfo.SetCheckable(accessibilityProperty->IsUserCheckable());
1404 } else {
1405 nodeInfo.SetCheckable(accessibilityProperty->IsCheckable());
1406 }
1407 }
1408 }
1409
IsUserCheckedOrSelected(const RefPtr<NG::FrameNode> frameNode)1410 bool IsUserCheckedOrSelected(const RefPtr<NG::FrameNode> frameNode)
1411 {
1412 auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
1413 CHECK_NULL_RETURN(accessibilityProperty, false);
1414 if (accessibilityProperty->HasUserCheckedType() || accessibilityProperty->HasUserSelected()) {
1415 return true;
1416 }
1417 return false;
1418 }
1419
UpdateAccessibilityTextValueInfo(RefPtr<NG::AccessibilityProperty> & accessibilityProperty,AccessibilityElementInfo & nodeInfo)1420 void UpdateAccessibilityTextValueInfo(
1421 RefPtr<NG::AccessibilityProperty>& accessibilityProperty, AccessibilityElementInfo& nodeInfo)
1422 {
1423 if (accessibilityProperty->HasUserTextValue()) {
1424 nodeInfo.SetContent(accessibilityProperty->GetUserTextValue());
1425 } else {
1426 nodeInfo.SetContent(accessibilityProperty->GetGroupText());
1427 }
1428
1429 if (!accessibilityProperty->HasUserTextValue() && accessibilityProperty->GetAccessibilityText().empty() &&
1430 accessibilityProperty->IsAccessibilityGroup() && accessibilityProperty->IsAccessibilityTextPreferred()) {
1431 nodeInfo.SetAccessibilityText(accessibilityProperty->GetGroupPreferAccessibilityText());
1432 } else {
1433 nodeInfo.SetAccessibilityText(accessibilityProperty->GetAccessibilityText());
1434 }
1435 }
1436
UpdateElementInfoPageIdWithTreeId(Accessibility::AccessibilityElementInfo & info,int32_t treeId)1437 void UpdateElementInfoPageIdWithTreeId(Accessibility::AccessibilityElementInfo& info, int32_t treeId)
1438 {
1439 int32_t pageId = info.GetPageId();
1440 if ((pageId >= MAX_PAGE_ID_WITH_SUB_TREE) || (pageId < 0)) {
1441 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "pageId %{public}d cannot set tree id", pageId);
1442 } else {
1443 uint32_t unsignedPageId = static_cast<uint32_t>(pageId);
1444 uint32_t unsignedTreeId = static_cast<uint32_t>(treeId);
1445 info.SetPageId((unsignedTreeId << SUB_TREE_OFFSET_IN_PAGE_ID) | unsignedPageId);
1446 }
1447 }
1448
ScrollByOffsetToParent(const RefPtr<NG::FrameNode> & curFrameNode,const RefPtr<NG::FrameNode> & parentFrameNode)1449 bool ScrollByOffsetToParent(const RefPtr<NG::FrameNode>& curFrameNode, const RefPtr<NG::FrameNode>& parentFrameNode)
1450 {
1451 CHECK_NULL_RETURN(curFrameNode, false);
1452 CHECK_NULL_RETURN(parentFrameNode, false);
1453 auto parentPattern = parentFrameNode->GetPattern<NG::ScrollablePattern>();
1454 CHECK_NULL_RETURN(parentPattern, false);
1455
1456 auto scrollAbility = parentPattern->GetScrollOffsetAbility();
1457 auto scrollFunc = scrollAbility.scrollFunc;
1458 auto scrollAxis = scrollAbility.axis;
1459 if (!scrollFunc || scrollAxis == Axis::NONE) {
1460 return false;
1461 }
1462 if (parentFrameNode->GetTag() == V2::SCROLL_ETS_TAG) {
1463 return false;
1464 }
1465 auto moveOffset = NG::ScrollableUtils::GetMoveOffset(parentFrameNode, curFrameNode, scrollAxis == Axis::VERTICAL,
1466 scrollAbility.contentStartOffset, scrollAbility.contentEndOffset);
1467 if (!NearZero(moveOffset)) {
1468 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "Scroll offset: %{public}f on %{public}s/%{public}d, axis: %{public}d",
1469 moveOffset, parentFrameNode->GetTag().c_str(), parentFrameNode->GetId(), scrollAxis);
1470 auto ret = scrollFunc(parentPattern->IsReverse() ? -moveOffset : moveOffset);
1471 auto pipeline = NG::PipelineContext::GetCurrentContextSafelyWithCheck();
1472 if (pipeline) {
1473 pipeline->FlushUITasks();
1474 }
1475 return ret;
1476 }
1477 return false;
1478 }
1479
ScrollByOffset(const RefPtr<NG::FrameNode> & curFrameNode)1480 bool ScrollByOffset(const RefPtr<NG::FrameNode>& curFrameNode)
1481 {
1482 CHECK_NULL_RETURN(curFrameNode, false);
1483 bool ret = false;
1484 auto parentFrameNode = curFrameNode->GetParentFrameNode();
1485
1486 while (parentFrameNode) {
1487 if (ScrollByOffsetToParent(curFrameNode, parentFrameNode)) {
1488 ret = true;
1489 }
1490 parentFrameNode = parentFrameNode->GetParentFrameNode();
1491 }
1492 return ret;
1493 }
1494
ProcessFocusScroll(const RefPtr<NG::FrameNode> & curFrameNode,RefPtr<NG::PipelineContext> & context)1495 void ProcessFocusScroll(const RefPtr<NG::FrameNode>& curFrameNode, RefPtr<NG::PipelineContext>& context)
1496 {
1497 CHECK_NULL_VOID(context);
1498 context->GetTaskExecutor()->PostTask(
1499 [node = AceType::WeakClaim(AceType::RawPtr(curFrameNode))] {
1500 auto focusNode = node.Upgrade();
1501 CHECK_NULL_VOID(focusNode);
1502 auto accessibilityProperty = focusNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
1503 CHECK_NULL_VOID(accessibilityProperty);
1504 if (accessibilityProperty->GetAccessibilityFocusState()) {
1505 ScrollByOffset(focusNode);
1506 }
1507 },
1508 TaskExecutor::TaskType::UI, "ArkUIAccessibilityProcessFocusScroll");
1509 }
1510
GetLastPageId(const RefPtr<NG::PipelineContext> & ngPipeline)1511 int32_t GetLastPageId(const RefPtr<NG::PipelineContext>& ngPipeline)
1512 {
1513 CHECK_NULL_RETURN(ngPipeline, -1);
1514 auto stageManager = ngPipeline->GetStageManager();
1515 CHECK_NULL_RETURN(stageManager, -1);
1516 auto page = stageManager->GetLastPageWithTransition();
1517 CHECK_NULL_RETURN(page, -1);
1518 return page->GetPageId();
1519 }
1520
AddHasRegisteredHover(const RefPtr<NG::FrameNode> & node,ExtraElementInfo & extraElementInfo)1521 void AddHasRegisteredHover(const RefPtr<NG::FrameNode>& node, ExtraElementInfo& extraElementInfo)
1522 {
1523 CHECK_NULL_VOID(node);
1524 auto eventHub = node->GetEventHub<NG::EventHub>();
1525 CHECK_NULL_VOID(eventHub);
1526 auto inputEventHub = eventHub->GetInputEventHub();
1527 CHECK_NULL_VOID(inputEventHub);
1528 if (inputEventHub->HasAccessibilityHoverEvent()) {
1529 extraElementInfo.SetExtraElementInfo("hasRegisteredHover", true);
1530 }
1531 }
1532 } // namespace
1533
UpdateAccessibilityElementInfo(const RefPtr<NG::FrameNode> & node,AccessibilityElementInfo & nodeInfo)1534 void JsAccessibilityManager::UpdateAccessibilityElementInfo(
1535 const RefPtr<NG::FrameNode>& node, AccessibilityElementInfo& nodeInfo)
1536 {
1537 CHECK_NULL_VOID(node);
1538 auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
1539 CHECK_NULL_VOID(accessibilityProperty);
1540 if (accessibilityProperty->HasAccessibilityRole()) {
1541 nodeInfo.SetComponentType(accessibilityProperty->GetAccessibilityRole());
1542 }
1543 if (accessibilityProperty->HasAccessibilityCustomRole()) {
1544 nodeInfo.SetCustomComponentType(accessibilityProperty->GetAccessibilityCustomRole());
1545 }
1546
1547 UpdateAccessibilityTextValueInfo(accessibilityProperty, nodeInfo);
1548
1549 RangeInfo rangeInfo = ConvertAccessibilityValue(accessibilityProperty->GetAccessibilityValue());
1550 if (accessibilityProperty->HasUserRangeCurrentValue()) {
1551 rangeInfo.SetCurrent(accessibilityProperty->GetUserRangeCurrentValue());
1552 }
1553 if (accessibilityProperty->HasUserRangeMinValue()) {
1554 rangeInfo.SetMin(accessibilityProperty->GetUserRangeMinValue());
1555 }
1556 if (accessibilityProperty->HasUserRangeMaxValue()) {
1557 rangeInfo.SetMax(accessibilityProperty->GetUserRangeMaxValue());
1558 }
1559 nodeInfo.SetRange(rangeInfo);
1560 if (accessibilityProperty->HasSubComponent()) {
1561 std::vector<SubComponentInfo> subComponentInfos;
1562 accessibilityProperty->GetSubComponentInfo(subComponentInfos);
1563 for (const auto& subComponent : subComponentInfos) {
1564 nodeInfo.AddSpan(SpanInfo(subComponent.spanId, subComponent.spanText,
1565 subComponent.accessibilityText, subComponent.accessibilityDescription,
1566 subComponent.accessibilityLevel));
1567 }
1568 }
1569 nodeInfo.SetAccessibilityNextFocusInspectorKey(accessibilityProperty->GetAccessibilityNextFocusInspectorKey());
1570 nodeInfo.SetAccessibilityScrollable(accessibilityProperty->IsUserScrollTriggerable());
1571 nodeInfo.SetHint(accessibilityProperty->GetHintText());
1572 nodeInfo.SetAccessibilityGroup(accessibilityProperty->IsAccessibilityGroup());
1573 nodeInfo.SetAccessibilityLevel(accessibilityProperty->GetAccessibilityLevel());
1574 nodeInfo.SetTextType(accessibilityProperty->GetTextType());
1575 nodeInfo.SetTextLengthLimit(accessibilityProperty->GetTextLengthLimit());
1576 nodeInfo.SetOffset(accessibilityProperty->GetScrollOffSet());
1577 auto context = node->GetRenderContext();
1578 if (context != nullptr) {
1579 nodeInfo.SetZIndex(context->GetZIndex().value_or(0));
1580 nodeInfo.SetOpacity(context->GetOpacity().value_or(1));
1581 nodeInfo.SetBackgroundColor(context->GetBackgroundColor().value_or(Color::TRANSPARENT).ToString());
1582 nodeInfo.SetBackgroundImage(context->GetBackgroundImage().value_or(ImageSourceInfo("")).ToString());
1583 if (context->GetForeground() != nullptr) {
1584 nodeInfo.SetBlur(context->GetForeground()->propBlurRadius.value_or(Dimension(0)).ToString());
1585 }
1586 }
1587 auto eventHub = node->GetEventHub<NG::EventHub>();
1588 if (eventHub != nullptr) {
1589 nodeInfo.SetHitTestBehavior(NG::GestureEventHub::GetHitTestModeStr(eventHub->GetGestureEventHub()));
1590 }
1591
1592 UpdateUserAccessibilityElementInfo(accessibilityProperty, nodeInfo);
1593
1594 nodeInfo.SetPassword(accessibilityProperty->IsPassword());
1595 nodeInfo.SetPluraLineSupported(accessibilityProperty->IsMultiLine());
1596 nodeInfo.SetHinting(accessibilityProperty->IsHint());
1597 nodeInfo.SetDescriptionInfo(accessibilityProperty->GetAccessibilityDescription());
1598 if (accessibilityProperty->HasUserCurrentValue()) {
1599 nodeInfo.SetCurrentIndex(accessibilityProperty->GetUserCurrentValue());
1600 } else {
1601 nodeInfo.SetCurrentIndex(accessibilityProperty->GetCurrentIndex());
1602 }
1603 if (accessibilityProperty->HasUserMinValue()) {
1604 nodeInfo.SetBeginIndex(accessibilityProperty->GetUserMinValue());
1605 } else {
1606 nodeInfo.SetBeginIndex(accessibilityProperty->GetBeginIndex());
1607 }
1608 if (accessibilityProperty->HasUserMaxValue()) {
1609 nodeInfo.SetEndIndex(accessibilityProperty->GetUserMaxValue());
1610 } else {
1611 nodeInfo.SetEndIndex(accessibilityProperty->GetEndIndex());
1612 }
1613 auto tag = node->GetTag();
1614 if (tag == V2::TOAST_ETS_TAG || tag == V2::POPUP_ETS_TAG || tag == V2::DIALOG_ETS_TAG ||
1615 tag == V2::ACTION_SHEET_DIALOG_ETS_TAG || tag == V2::ALERT_DIALOG_ETS_TAG || tag == V2::MENU_ETS_TAG ||
1616 tag == "SelectMenu") {
1617 nodeInfo.SetLiveRegion(1);
1618 }
1619 nodeInfo.SetContentInvalid(accessibilityProperty->GetContentInvalid());
1620 nodeInfo.SetError(accessibilityProperty->GetErrorText());
1621 nodeInfo.SetSelectedBegin(accessibilityProperty->GetTextSelectionStart());
1622 nodeInfo.SetSelectedEnd(accessibilityProperty->GetTextSelectionEnd());
1623 nodeInfo.SetInputType(static_cast<int>(accessibilityProperty->GetTextInputType()));
1624 nodeInfo.SetItemCounts(accessibilityProperty->GetCollectionItemCounts());
1625 nodeInfo.SetChildTreeIdAndWinId(
1626 accessibilityProperty->GetChildTreeId(), accessibilityProperty->GetChildWindowId());
1627 if (nodeInfo.GetComponentType() == "FormComponent") {
1628 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "elementId: %{public}" PRId64 ", Set: %{public}d %{public}d",
1629 nodeInfo.GetAccessibilityId(), accessibilityProperty->GetChildTreeId(),
1630 accessibilityProperty->GetChildWindowId());
1631 }
1632 if (nodeInfo.GetWindowId() == static_cast<int32_t>(windowId_)) {
1633 nodeInfo.SetBelongTreeId(treeId_);
1634 nodeInfo.SetParentWindowId(parentWindowId_);
1635 } else {
1636 nodeInfo.SetBelongTreeId(0);
1637 nodeInfo.SetParentWindowId(0);
1638 }
1639
1640 GridInfo gridInfo(accessibilityProperty->GetCollectionInfo().rows,
1641 accessibilityProperty->GetCollectionInfo().columns, accessibilityProperty->GetCollectionInfo().selectMode);
1642 nodeInfo.SetGrid(gridInfo);
1643 ExtraElementInfo extraElementInfo {};
1644 accessibilityProperty->GetAllExtraElementInfo(extraElementInfo);
1645 AddHasRegisteredHover(node, extraElementInfo);
1646 if (node->IsAccessibilityVirtualNode()) {
1647 auto parentUinode = node->GetVirtualNodeParent().Upgrade();
1648 if (parentUinode) {
1649 auto parentFrame = AceType::DynamicCast<NG::FrameNode>(parentUinode);
1650 AddHasRegisteredHover(parentFrame, extraElementInfo);
1651 }
1652 }
1653 nodeInfo.SetExtraElement(extraElementInfo);
1654
1655 int32_t row = accessibilityProperty->GetCollectionItemInfo().row;
1656 int32_t column = accessibilityProperty->GetCollectionItemInfo().column;
1657 int32_t rowSpan = accessibilityProperty->GetCollectionItemInfo().rowSpan;
1658 int32_t columnSpan = accessibilityProperty->GetCollectionItemInfo().columnSpan;
1659 bool heading = accessibilityProperty->GetCollectionItemInfo().heading;
1660 GridItemInfo gridItemInfo(row, rowSpan, column, columnSpan, heading, nodeInfo.IsSelected());
1661 nodeInfo.SetGridItem(gridItemInfo);
1662
1663 SetAccessibilityFocusAction(nodeInfo, "ace");
1664 if (nodeInfo.IsEnabled()) {
1665 nodeInfo.SetScrollable(accessibilityProperty->IsScrollable());
1666 nodeInfo.SetEditable(accessibilityProperty->IsEditable());
1667 nodeInfo.SetDeletable(accessibilityProperty->IsDeletable());
1668 UpdateSupportAction(node, nodeInfo);
1669 accessibilityProperty->ResetSupportAction();
1670 auto supportAceActions = accessibilityProperty->GetSupportAction();
1671 for (auto it = supportAceActions.begin(); it != supportAceActions.end(); ++it) {
1672 AccessibleAction action(ConvertAceAction(*it), "ace");
1673 nodeInfo.AddAction(action);
1674 }
1675 }
1676 }
1677 #ifdef WEB_SUPPORTED
1678
UpdateWebAccessibilityElementInfo(const std::shared_ptr<NG::TransitionalNodeInfo> & node,AccessibilityElementInfo & nodeInfo,int32_t treeId)1679 void JsAccessibilityManager::UpdateWebAccessibilityElementInfo(
1680 const std::shared_ptr<NG::TransitionalNodeInfo>& node, AccessibilityElementInfo& nodeInfo, int32_t treeId)
1681 {
1682 CHECK_NULL_VOID(node);
1683 nodeInfo.SetContent(node->GetContent());
1684 nodeInfo.SetAccessibilityText(node->GetContent());
1685 RangeInfo rangeInfo(node->GetRangeInfoMin(), node->GetRangeInfoMax(), node->GetRangeInfoCurrent());
1686 nodeInfo.SetRange(rangeInfo);
1687 nodeInfo.SetHint(node->GetHint());
1688 nodeInfo.SetHinting(node->GetIsHinting());
1689 nodeInfo.SetDescriptionInfo(node->GetDescriptionInfo());
1690 nodeInfo.SetChecked(node->GetIsChecked());
1691 nodeInfo.SetSelected(node->GetIsSelected());
1692 nodeInfo.SetPassword(node->GetIsPassword());
1693 nodeInfo.SetPluraLineSupported(node->GetIsPluralLineSupported());
1694 nodeInfo.SetLiveRegion(node->GetLiveRegion());
1695 nodeInfo.SetContentInvalid(node->GetIsContentInvalid());
1696 nodeInfo.SetError(node->GetError());
1697 nodeInfo.SetSelectedBegin(node->GetSelectionStart());
1698 nodeInfo.SetSelectedEnd(node->GetSelectionEnd());
1699 nodeInfo.SetInputType(node->GetInputType());
1700 nodeInfo.SetItemCounts(node->GetItemCounts());
1701
1702 nodeInfo.SetBelongTreeId(treeId);
1703 nodeInfo.SetParentWindowId(parentWebWindowId_);
1704
1705 GridInfo gridInfo(node->GetGridRows(), node->GetGridColumns(), node->GetGridSelectedMode());
1706 nodeInfo.SetGrid(gridInfo);
1707
1708 int32_t row = node->GetGridItemRow();
1709 int32_t column = node->GetGridItemColumn();
1710 int32_t rowSpan = node->GetGridItemRowSpan();
1711 int32_t columnSpan = node->GetGridItemColumnSpan();
1712 bool heading = node->GetIsHeading();
1713 GridItemInfo gridItemInfo(row, rowSpan, column, columnSpan, heading, nodeInfo.IsSelected());
1714 nodeInfo.SetGridItem(gridItemInfo);
1715
1716 SetAccessibilityFocusAction(nodeInfo, "web");
1717 nodeInfo.SetCheckable(node->GetIsCheckable());
1718 nodeInfo.SetScrollable(node->GetIsScrollable());
1719 nodeInfo.SetEditable(node->GetIsEditable());
1720 nodeInfo.SetDeletable(node->GetIsDeletable());
1721 nodeInfo.SetClickable(node->GetIsClickable());
1722 auto supportAceActions = node->GetActions();
1723 for (auto it = supportAceActions.begin(); it != supportAceActions.end(); ++it) {
1724 AccessibleAction action(ConvertAceAction(static_cast<AceAction>(*it)), "web");
1725 nodeInfo.AddAction(action);
1726 }
1727 nodeInfo.SetAccessibilityGroup(node->GetIsAccessibilityGroup());
1728 }
1729
1730 #endif
1731 namespace {
UpdateChildrenOfAccessibilityElementInfo(const RefPtr<NG::FrameNode> & node,const CommonProperty & commonProperty,AccessibilityElementInfo & nodeInfo)1732 void UpdateChildrenOfAccessibilityElementInfo(
1733 const RefPtr<NG::FrameNode>& node, const CommonProperty& commonProperty, AccessibilityElementInfo& nodeInfo)
1734 {
1735 if (!NeedUpdateChildrenOfAccessibilityElementInfo(node)) {
1736 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "Node %{public}s not need update children"
1737 " of accessibilityElementInfo", node->GetTag().c_str());
1738 return;
1739 }
1740 if (!IsExtensionComponent(node) || IsUIExtensionShowPlaceholder(node)) {
1741 std::vector<std::pair<int64_t, int32_t>> childrenIdInfo;
1742 for (const auto& item : node->GetChildren(true)) {
1743 GetFrameNodeChildren(item, childrenIdInfo, commonProperty);
1744 }
1745
1746 auto overlayNode = node->GetOverlayNode();
1747 if (overlayNode != nullptr) {
1748 GetFrameNodeChildren(overlayNode, childrenIdInfo, commonProperty);
1749 }
1750
1751 auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
1752 auto uiVirtualNode = accessibilityProperty->GetAccessibilityVirtualNode();
1753 if (uiVirtualNode != nullptr) {
1754 auto virtualNode = AceType::DynamicCast<NG::FrameNode>(uiVirtualNode);
1755 if (virtualNode != nullptr) {
1756 childrenIdInfo.clear();
1757 GetFrameNodeChildren(virtualNode, childrenIdInfo, commonProperty);
1758 }
1759 }
1760 std::sort(childrenIdInfo.begin(), childrenIdInfo.end(),
1761 [](const auto&zIndexA, const auto&zIndexB) { return zIndexA.second < zIndexB.second; });
1762 for (const auto& childrenIdPair : childrenIdInfo) {
1763 nodeInfo.AddChild(childrenIdPair.first);
1764 }
1765 }
1766 }
1767
1768 }
1769
UpdateVirtualNodeChildAccessibilityElementInfo(const RefPtr<NG::FrameNode> & node,const CommonProperty & commonProperty,AccessibilityElementInfo & nodeParentInfo,AccessibilityElementInfo & nodeInfo,const RefPtr<NG::PipelineContext> & ngPipeline)1770 void JsAccessibilityManager::UpdateVirtualNodeChildAccessibilityElementInfo(
1771 const RefPtr<NG::FrameNode>& node, const CommonProperty& commonProperty,
1772 AccessibilityElementInfo& nodeParentInfo, AccessibilityElementInfo& nodeInfo,
1773 const RefPtr<NG::PipelineContext>& ngPipeline)
1774 {
1775 CHECK_NULL_VOID(node);
1776 nodeInfo.SetParent(GetParentId(node));
1777 UpdateChildrenOfAccessibilityElementInfo(node, commonProperty, nodeInfo);
1778
1779 nodeInfo.SetAccessibilityId(node->GetAccessibilityId());
1780 nodeInfo.SetComponentType(node->GetTag());
1781
1782 nodeInfo.SetEnabled(node->GetFocusHub() ? node->GetFocusHub()->IsEnabled() : true);
1783 nodeInfo.SetFocused(node->GetFocusHub() ? node->GetFocusHub()->IsCurrentFocus() : false);
1784 nodeInfo.SetAccessibilityFocus(node->GetRenderContext()->GetAccessibilityFocus().value_or(false));
1785 nodeInfo.SetInspectorKey(node->GetInspectorId().value_or(""));
1786 nodeInfo.SetVisible(node->IsVisible());
1787 if (node->IsVisible()) {
1788 auto rect = node->GetVirtualNodeTransformRectRelativeToWindow();
1789 auto left = rect.Left() + commonProperty.windowLeft;
1790 auto top = rect.Top() + commonProperty.windowTop;
1791 auto right = rect.Right() + commonProperty.windowLeft;
1792 auto bottom = rect.Bottom() + commonProperty.windowTop;
1793 Accessibility::Rect bounds { left, top, right, bottom };
1794 nodeInfo.SetRectInScreen(bounds);
1795 }
1796 nodeInfo.SetWindowId(commonProperty.windowId);
1797 nodeInfo.SetInnerWindowId(commonProperty.innerWindowId);
1798 nodeInfo.SetPageId(node->GetPageId());
1799 nodeInfo.SetPagePath(
1800 GetPagePathInPageNodes(nodeInfo.GetPageId(), commonProperty.pageNodes, commonProperty.pagePaths));
1801 nodeInfo.SetBundleName(AceApplicationInfo::GetInstance().GetPackageName());
1802
1803 if (nodeInfo.IsEnabled()) {
1804 nodeInfo.SetFocusable(node->GetFocusHub() ? node->GetFocusHub()->IsFocusable() : false);
1805 nodeInfo.SetPopupSupported(IsPopupSupported(ngPipeline, node->GetId()));
1806 }
1807 nodeInfo.SetComponentResourceId(node->GetInspectorId().value_or(""));
1808 UpdateAccessibilityElementInfo(node, nodeInfo);
1809 }
1810
UpdateVirtualNodeAccessibilityElementInfo(const RefPtr<NG::FrameNode> & parent,const RefPtr<NG::FrameNode> & node,const CommonProperty & commonProperty,AccessibilityElementInfo & nodeInfo,const RefPtr<NG::PipelineContext> & ngPipeline)1811 void JsAccessibilityManager::UpdateVirtualNodeAccessibilityElementInfo(
1812 const RefPtr<NG::FrameNode>& parent, const RefPtr<NG::FrameNode>& node,
1813 const CommonProperty& commonProperty, AccessibilityElementInfo& nodeInfo,
1814 const RefPtr<NG::PipelineContext>& ngPipeline)
1815 {
1816 CHECK_NULL_VOID(parent);
1817 CHECK_NULL_VOID(node);
1818 nodeInfo.SetParent(GetParentId(node));
1819 UpdateChildrenOfAccessibilityElementInfo(node, commonProperty, nodeInfo);
1820
1821 nodeInfo.SetAccessibilityId(node->GetAccessibilityId());
1822 nodeInfo.SetComponentType(node->GetTag());
1823
1824 nodeInfo.SetEnabled(node->GetFocusHub() ? node->GetFocusHub()->IsEnabled() : true);
1825 nodeInfo.SetFocused(node->GetFocusHub() ? node->GetFocusHub()->IsCurrentFocus() : false);
1826 nodeInfo.SetAccessibilityFocus(node->GetRenderContext()->GetAccessibilityFocus().value_or(false));
1827 nodeInfo.SetInspectorKey(node->GetInspectorId().value_or(""));
1828 nodeInfo.SetVisible(node->IsVisible());
1829 if (node->IsVisible()) {
1830 auto virtualNodeRect = node->GetTransformRectRelativeToWindow();
1831 auto parentRect = parent->GetTransformRectRelativeToWindow();
1832 auto left = parentRect.Left() + commonProperty.windowLeft;
1833 auto top = parentRect.Top() + commonProperty.windowTop;
1834 auto right = parentRect.Left() + virtualNodeRect.Width() + commonProperty.windowLeft;
1835 if (virtualNodeRect.Width() > (parentRect.Right() - parentRect.Left())) {
1836 right = parentRect.Right() + commonProperty.windowLeft;
1837 }
1838 auto bottom = parentRect.Top() + virtualNodeRect.Height() + commonProperty.windowTop;
1839 if (virtualNodeRect.Height() > (parentRect.Bottom() - parentRect.Top())) {
1840 bottom = parentRect.Bottom() + commonProperty.windowTop;
1841 }
1842 Accessibility::Rect bounds { left, top, right, bottom };
1843 nodeInfo.SetRectInScreen(bounds);
1844 }
1845 nodeInfo.SetWindowId(commonProperty.windowId);
1846 nodeInfo.SetInnerWindowId(commonProperty.innerWindowId);
1847 nodeInfo.SetPageId(node->GetPageId());
1848 nodeInfo.SetPagePath(
1849 GetPagePathInPageNodes(nodeInfo.GetPageId(), commonProperty.pageNodes, commonProperty.pagePaths));
1850 nodeInfo.SetBundleName(AceApplicationInfo::GetInstance().GetPackageName());
1851
1852 if (nodeInfo.IsEnabled()) {
1853 nodeInfo.SetFocusable(node->GetFocusHub() ? node->GetFocusHub()->IsFocusable() : false);
1854 nodeInfo.SetPopupSupported(IsPopupSupported(ngPipeline, node->GetId()));
1855 }
1856 nodeInfo.SetComponentResourceId(node->GetInspectorId().value_or(""));
1857 UpdateAccessibilityElementInfo(node, nodeInfo);
1858 }
1859
1860 namespace {
GetPositionToWindowWithTransform(NG::OffsetF & offset,NG::OffsetF & offsetBottom,const RefPtr<NG::FrameNode> & node)1861 void GetPositionToWindowWithTransform(NG::OffsetF& offset, NG::OffsetF& offsetBottom, const RefPtr<NG::FrameNode>& node)
1862 {
1863 CHECK_NULL_VOID(node);
1864 auto context = node->GetRenderContext();
1865 CHECK_NULL_VOID(context);
1866 auto rect = context->GetPaintRectWithoutTransform();
1867
1868 offset = rect.GetOffset();
1869 offsetBottom = NG::OffsetF(rect.GetX() + rect.Width(), rect.GetY() + rect.Height());
1870
1871 NG::PointF leftTopPointNode(offset.GetX(), offset.GetY());
1872 NG::PointF rightBottomPointNode(rect.GetX() + rect.Width(), rect.GetY() + rect.Height());
1873 context->GetPointTransformRotate(leftTopPointNode);
1874 context->GetPointTransformRotate(rightBottomPointNode);
1875 auto parent = node->GetAncestorNodeOfFrame(true);
1876 while (parent) {
1877 // if get the window boundary (window scene), not calculate transform
1878 if (!parent->IsWindowBoundary()) {
1879 auto parentRenderContext = parent->GetRenderContext();
1880 if (!parentRenderContext) {
1881 parent = parent->GetAncestorNodeOfFrame(true);
1882 continue;
1883 }
1884 auto parentOffset = parentRenderContext->GetPaintRectWithoutTransform().GetOffset();
1885 NG::PointF leftTopPointAfterAddOffset(parentOffset.GetX() + leftTopPointNode.GetX(),
1886 parentOffset.GetY() + leftTopPointNode.GetY());
1887 NG::PointF rightBottomPointAfterAddOffset(parentOffset.GetX() + rightBottomPointNode.GetX(),
1888 parentOffset.GetY() + rightBottomPointNode.GetY());
1889
1890 auto parentTransformMat = parentRenderContext->GetMatrixWithTransformRotate();
1891 Point leftTop(leftTopPointAfterAddOffset.GetX(), leftTopPointAfterAddOffset.GetY());
1892 Point rightBottom(rightBottomPointAfterAddOffset.GetX(), rightBottomPointAfterAddOffset.GetY());
1893 auto leftTopPoint = parentTransformMat * leftTop;
1894 auto rightBottomPoint = parentTransformMat * rightBottom;
1895 leftTopPointNode.SetX(leftTopPoint.GetX());
1896 leftTopPointNode.SetY(leftTopPoint.GetY());
1897 rightBottomPointNode.SetX(rightBottomPoint.GetX());
1898 rightBottomPointNode.SetY(rightBottomPoint.GetY());
1899 }
1900 parent = parent->GetAncestorNodeOfFrame(true);
1901 }
1902 offset.SetX(leftTopPointNode.GetX());
1903 offset.SetY(leftTopPointNode.GetY());
1904 offsetBottom.SetX(rightBottomPointNode.GetX());
1905 offsetBottom.SetY(rightBottomPointNode.GetY());
1906 }
1907
GetFinalRealRect(const RefPtr<NG::FrameNode> & node)1908 NG::RectF GetFinalRealRect(const RefPtr<NG::FrameNode>& node)
1909 {
1910 if ((node->GetTag() == V2::WINDOW_SCENE_ETS_TAG) && node->IsWindowBoundary()) {
1911 auto renderContext = node->GetRenderContext();
1912 CHECK_NULL_RETURN(renderContext, NG::RectF());
1913 auto rect = renderContext->GetPaintRectWithoutTransform();
1914 // commonproperty will contain the offset and scale of the window scene
1915 return {0, 0, rect.Width(), rect.Height()};
1916 }
1917
1918 NG::OffsetF offset;
1919 NG::OffsetF offsetBottom;
1920 GetPositionToWindowWithTransform(offset, offsetBottom, node);
1921 return {
1922 LessNotEqual(offset.GetX(), offsetBottom.GetX()) ? offset.GetX() : offsetBottom.GetX(),
1923 LessNotEqual(offset.GetY(), offsetBottom.GetY()) ? offset.GetY() : offsetBottom.GetY(),
1924 LessNotEqual(offset.GetX(), offsetBottom.GetX())
1925 ? offsetBottom.GetX() - offset.GetX()
1926 : offset.GetX() - offsetBottom.GetX(),
1927 LessNotEqual(offset.GetY(), offsetBottom.GetY())
1928 ? offsetBottom.GetY() - offset.GetY()
1929 : offset.GetY() - offsetBottom.GetY()
1930 };
1931 }
1932
SetRectInScreen(const RefPtr<NG::FrameNode> & node,AccessibilityElementInfo & nodeInfo,const CommonProperty & commonProperty)1933 void SetRectInScreen(const RefPtr<NG::FrameNode>& node, AccessibilityElementInfo& nodeInfo,
1934 const CommonProperty& commonProperty)
1935 {
1936 if (node->IsAccessibilityVirtualNode()) {
1937 auto rect = node->GetVirtualNodeTransformRectRelativeToWindow();
1938 auto left = rect.Left() + commonProperty.windowLeft;
1939 auto top = rect.Top() + commonProperty.windowTop;
1940 auto right = rect.Right() + commonProperty.windowLeft;
1941 auto bottom = rect.Bottom() + commonProperty.windowTop;
1942 Accessibility::Rect bounds { left, top, right, bottom };
1943 nodeInfo.SetRectInScreen(bounds);
1944 } else if (node->IsVisible()) {
1945 auto rect = GetFinalRealRect(node);
1946 auto rotateTransformData = commonProperty.rotateTransform;
1947 auto currentDegree = rotateTransformData.rotateDegree;
1948 if (!NearZero(currentDegree, 0)) {
1949 AccessibilityRect rotateRect(rect.GetX(), rect.GetY(), rect.Width(), rect.Height());
1950 rotateRect.Rotate(rotateTransformData.innerCenterX, rotateTransformData.innerCenterY, currentDegree);
1951 rotateRect.ApplyTransformation(rotateTransformData, commonProperty.scaleX, commonProperty.scaleY);
1952 Accessibility::Rect bounds { rotateRect.GetX(), rotateRect.GetY(),
1953 rotateRect.GetX() + rotateRect.GetWidth(), rotateRect.GetY() + rotateRect.GetHeight()};
1954 nodeInfo.SetRectInScreen(bounds);
1955 return;
1956 }
1957 if (!NearZero(commonProperty.scaleX, 0) && !NearZero(commonProperty.scaleY, 0)) {
1958 rect.SetRect(rect.GetX() * commonProperty.scaleX, rect.GetY() * commonProperty.scaleY,
1959 rect.Width() * commonProperty.scaleX, rect.Height() * commonProperty.scaleY);
1960 }
1961 auto left = rect.Left() + commonProperty.windowLeft;
1962 auto top = rect.Top() + commonProperty.windowTop;
1963 auto right = rect.Right() + commonProperty.windowLeft;
1964 auto bottom = rect.Bottom() + commonProperty.windowTop;
1965 Accessibility::Rect bounds { left, top, right, bottom };
1966 nodeInfo.SetRectInScreen(bounds);
1967 }
1968 }
1969 }
1970
UpdateAccessibilityVisible(const RefPtr<NG::FrameNode> & node,AccessibilityElementInfo & nodeInfo)1971 void JsAccessibilityManager::UpdateAccessibilityVisible(
1972 const RefPtr<NG::FrameNode>& node, AccessibilityElementInfo& nodeInfo)
1973 {
1974 auto parentNode = node->GetParentFrameNode();
1975 UpdateElementInfoTreeId(nodeInfo);
1976
1977 if (!parentNode) {
1978 if (node->GetTag() != V2::PAGE_ETS_TAG) {
1979 node->SetAccessibilityVisible(node->IsActive() && node->IsVisible());
1980 }
1981 } else {
1982 if (node->GetTag() == V2::PAGE_ETS_TAG) {
1983 nodeInfo.SetAccessibilityVisible(node->IsActive() && node->IsVisible() && node->GetAccessibilityVisible() &&
1984 parentNode->GetAccessibilityVisible());
1985 return;
1986 }
1987 auto nodeAccessibilityVisible = node->IsActive() && node->IsVisible() && parentNode->GetAccessibilityVisible();
1988 node->SetAccessibilityVisible(nodeAccessibilityVisible);
1989 if (!nodeAccessibilityVisible) {
1990 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY,
1991 "Element %{public}" PRId64 " is invisible. node isActive %{public}d, node isVisible %{public}d"
1992 "parent accessibilityVisible:%{public}d.parent id %{public}" PRId64,
1993 nodeInfo.GetAccessibilityId(), node->IsActive(), node->IsVisible(),
1994 parentNode->GetAccessibilityVisible(), parentNode->GetAccessibilityId());
1995 }
1996 }
1997 nodeInfo.SetAccessibilityVisible(node->GetAccessibilityVisible());
1998 }
1999
UpdateAccessibilityElementInfo(const RefPtr<NG::FrameNode> & node,const CommonProperty & commonProperty,AccessibilityElementInfo & nodeInfo,const RefPtr<NG::PipelineContext> & ngPipeline)2000 void JsAccessibilityManager::UpdateAccessibilityElementInfo(
2001 const RefPtr<NG::FrameNode>& node, const CommonProperty& commonProperty,
2002 AccessibilityElementInfo& nodeInfo, const RefPtr<NG::PipelineContext>& ngPipeline)
2003 {
2004 CHECK_NULL_VOID(node);
2005 nodeInfo.SetParent(GetParentId(node));
2006 UpdateChildrenOfAccessibilityElementInfo(node, commonProperty, nodeInfo);
2007 nodeInfo.SetAccessibilityId(node->GetAccessibilityId());
2008 nodeInfo.SetComponentType(node->GetTag());
2009 nodeInfo.SetEnabled(node->GetFocusHub() ? node->GetFocusHub()->IsEnabled() : true);
2010 nodeInfo.SetFocused(node->GetFocusHub() ? node->GetFocusHub()->IsCurrentFocus() : false);
2011 nodeInfo.SetAccessibilityFocus(node->GetRenderContext()->GetAccessibilityFocus().value_or(false));
2012 nodeInfo.SetClip(node->GetRenderContext()->GetClipEdge().value_or(false));
2013 nodeInfo.SetInspectorKey(node->GetInspectorId().value_or(""));
2014 nodeInfo.SetVisible(node->IsVisible());
2015 nodeInfo.SetIsActive(node->IsActive());
2016 SetRectInScreen(node, nodeInfo, commonProperty);
2017 nodeInfo.SetWindowId(commonProperty.windowId);
2018 nodeInfo.SetInnerWindowId(commonProperty.innerWindowId);
2019 // is abnormal that pageId equals to 0, use last pageId to fix pageId
2020 if (node->GetPageId()) {
2021 nodeInfo.SetPageId(node->GetPageId());
2022 } else {
2023 nodeInfo.SetPageId(GetLastPageId(ngPipeline));
2024 }
2025 nodeInfo.SetPagePath(
2026 GetPagePathInPageNodes(nodeInfo.GetPageId(), commonProperty.pageNodes, commonProperty.pagePaths));
2027 nodeInfo.SetBundleName(AceApplicationInfo::GetInstance().GetPackageName());
2028
2029 if (nodeInfo.IsEnabled()) {
2030 nodeInfo.SetFocusable(node->GetFocusHub() ? node->GetFocusHub()->IsFocusable() : false);
2031 nodeInfo.SetPopupSupported(IsPopupSupported(ngPipeline, node->GetId()));
2032 }
2033 nodeInfo.SetComponentResourceId(node->GetInspectorId().value_or(""));
2034 UpdateAccessibilityElementInfo(node, nodeInfo);
2035 UpdateAccessibilityVisible(node, nodeInfo);
2036 }
2037 #ifdef WEB_SUPPORTED
2038
UpdateWebAccessibilityElementInfo(const std::shared_ptr<NG::TransitionalNodeInfo> & node,const CommonProperty & commonProperty,AccessibilityElementInfo & nodeInfo,const RefPtr<NG::WebPattern> & webPattern)2039 void JsAccessibilityManager::UpdateWebAccessibilityElementInfo(
2040 const std::shared_ptr<NG::TransitionalNodeInfo>& node, const CommonProperty& commonProperty,
2041 AccessibilityElementInfo& nodeInfo, const RefPtr<NG::WebPattern>& webPattern)
2042 {
2043 if (node->GetParentId() == -1) {
2044 nodeInfo.SetParent(INVALID_PARENT_ID);
2045 } else {
2046 nodeInfo.SetParent(node->GetParentId());
2047 }
2048 for (const auto& child : node->GetChildIds()) {
2049 nodeInfo.AddChild(child);
2050 }
2051
2052 nodeInfo.SetAccessibilityId(node->GetAccessibilityId());
2053 nodeInfo.SetComponentType(node->GetComponentType());
2054 nodeInfo.SetEnabled(node->GetIsEnabled());
2055 nodeInfo.SetFocused(node->GetIsFocused());
2056 nodeInfo.SetAccessibilityFocus(node->GetIsAccessibilityFocus());
2057 nodeInfo.SetVisible(node->GetIsVisible());
2058
2059 if (node->GetIsVisible()) {
2060 CHECK_NULL_VOID(webPattern);
2061 auto webNode = webPattern->GetHost();
2062 CHECK_NULL_VOID(webNode);
2063 auto webRect = webNode->GetTransformRectRelativeToWindow();
2064 auto left = (webRect.Left() + node->GetRectX()) * scaleX_ + commonProperty.windowLeft;
2065 auto top = (webRect.Top() + node->GetRectY()) * scaleY_ + commonProperty.windowTop;
2066 auto right = left + node->GetRectWidth() * scaleX_;
2067 auto bottom = top + node->GetRectHeight() * scaleY_;
2068 Accessibility::Rect bounds { left, top, right, bottom };
2069 nodeInfo.SetRectInScreen(bounds);
2070 }
2071
2072 nodeInfo.SetWindowId(commonProperty.windowId);
2073 nodeInfo.SetPageId(node->GetPageId());
2074 nodeInfo.SetPagePath(
2075 GetPagePathInPageNodes(nodeInfo.GetPageId(), commonProperty.pageNodes, commonProperty.pagePaths));
2076 nodeInfo.SetBundleName(AceApplicationInfo::GetInstance().GetPackageName());
2077
2078 if (nodeInfo.IsEnabled()) {
2079 nodeInfo.SetFocusable(node->GetIsFocusable());
2080 nodeInfo.SetPopupSupported(node->GetIsPopupSupported());
2081 }
2082 CHECK_NULL_VOID(webPattern);
2083 UpdateWebAccessibilityElementInfo(node, nodeInfo, webPattern->GetTreeId());
2084 }
2085
2086 #endif
2087 namespace {
SearchExtensionElementInfoByAccessibilityIdNG(int64_t elementId,int32_t mode,const RefPtr<NG::FrameNode> & node,int64_t offset)2088 std::list<AccessibilityElementInfo> SearchExtensionElementInfoByAccessibilityIdNG(
2089 int64_t elementId, int32_t mode, const RefPtr<NG::FrameNode>& node, int64_t offset)
2090 {
2091 std::list<AccessibilityElementInfo> extensionElementInfo;
2092 if (NG::UI_EXTENSION_OFFSET_MIN < (offset + 1)) {
2093 node->SearchExtensionElementInfoByAccessibilityIdNG(elementId, mode,
2094 offset / NG::UI_EXTENSION_ID_FACTOR, extensionElementInfo);
2095 }
2096 return extensionElementInfo;
2097 }
2098
UpdateUiExtensionParentIdForFocus(const RefPtr<NG::FrameNode> & rootNode,const int64_t uiExtensionOffset,Accessibility::AccessibilityElementInfo & info)2099 void UpdateUiExtensionParentIdForFocus(const RefPtr<NG::FrameNode>& rootNode, const int64_t uiExtensionOffset,
2100 Accessibility::AccessibilityElementInfo& info)
2101 {
2102 if ((uiExtensionOffset != NG::UI_EXTENSION_OFFSET_MAX) && (info.GetComponentType() != V2::ROOT_ETS_TAG) &&
2103 (info.GetParentNodeId() == rootNode->GetAccessibilityId())) {
2104 info.SetParent(NG::UI_EXTENSION_ROOT_ID);
2105 }
2106 }
2107
GetChildrenFromFrameNode(const RefPtr<NG::FrameNode> & node,std::list<RefPtr<NG::FrameNode>> & children,const CommonProperty & commonProperty)2108 void GetChildrenFromFrameNode(
2109 const RefPtr<NG::FrameNode>& node,
2110 std::list<RefPtr<NG::FrameNode>>& children,
2111 const CommonProperty& commonProperty)
2112 {
2113 std::list<RefPtr<NG::FrameNode>> frameNodeChildren;
2114 auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
2115 auto uiVirtualNode = accessibilityProperty->GetAccessibilityVirtualNode();
2116 if (uiVirtualNode != nullptr) {
2117 auto virtualNode = AceType::DynamicCast<NG::FrameNode>(uiVirtualNode);
2118 if (virtualNode != nullptr) {
2119 GetFrameNodeChildren(virtualNode, frameNodeChildren, commonProperty);
2120 }
2121 } else {
2122 for (const auto& item : node->GetChildren(true)) {
2123 GetFrameNodeChildren(item, frameNodeChildren, commonProperty);
2124 }
2125
2126 auto overlayNode = node->GetOverlayNode();
2127 if (overlayNode != nullptr) {
2128 GetFrameNodeChildren(overlayNode, frameNodeChildren, commonProperty);
2129 }
2130 }
2131 while (!frameNodeChildren.empty()) {
2132 children.emplace_back(frameNodeChildren.front());
2133 frameNodeChildren.pop_front();
2134 }
2135 }
2136 }
2137
UpdateVirtualNodeInfo(std::list<AccessibilityElementInfo> & infos,AccessibilityElementInfo & nodeInfo,const RefPtr<NG::UINode> & uiVirtualNode,const CommonProperty & commonProperty,const RefPtr<NG::PipelineContext> & ngPipeline)2138 void JsAccessibilityManager::UpdateVirtualNodeInfo(std::list<AccessibilityElementInfo>& infos,
2139 AccessibilityElementInfo& nodeInfo, const RefPtr<NG::UINode>& uiVirtualNode, const CommonProperty& commonProperty,
2140 const RefPtr<NG::PipelineContext>& ngPipeline)
2141 {
2142 for (const auto& item : uiVirtualNode->GetChildren(true)) {
2143 AccessibilityElementInfo virtualInfo;
2144 auto frameNodeChild = AceType::DynamicCast<NG::FrameNode>(item);
2145 if (frameNodeChild == nullptr) {
2146 continue;
2147 }
2148 UpdateVirtualNodeChildAccessibilityElementInfo(frameNodeChild, commonProperty,
2149 nodeInfo, virtualInfo, ngPipeline);
2150 virtualInfo.SetParent(uiVirtualNode->GetAccessibilityId());
2151 nodeInfo.AddChild(frameNodeChild->GetAccessibilityId());
2152 UpdateVirtualNodeInfo(infos, virtualInfo, item, commonProperty, ngPipeline);
2153 infos.push_back(virtualInfo);
2154 }
2155 }
2156
2157 namespace {
SearchExtensionElementInfoNG(const SearchParameter & searchParam,const RefPtr<NG::FrameNode> & node,std::list<Accessibility::AccessibilityElementInfo> & infos,Accessibility::AccessibilityElementInfo & parentInfo)2158 void SearchExtensionElementInfoNG(const SearchParameter& searchParam,
2159 const RefPtr<NG::FrameNode>& node, std::list<Accessibility::AccessibilityElementInfo>& infos,
2160 Accessibility::AccessibilityElementInfo& parentInfo)
2161 {
2162 auto extensionElementInfos = SearchExtensionElementInfoByAccessibilityIdNG(
2163 searchParam.nodeId, searchParam.mode, node, searchParam.uiExtensionOffset);
2164 if (!extensionElementInfos.empty()) {
2165 auto rootParentId = extensionElementInfos.front().GetParentNodeId();
2166 ConvertExtensionAccessibilityNodeId(extensionElementInfos, node, searchParam.uiExtensionOffset, parentInfo);
2167 if (rootParentId == NG::UI_EXTENSION_ROOT_ID) {
2168 extensionElementInfos.front().SetParent(node->GetAccessibilityId());
2169 }
2170 if (parentInfo.GetComponentType() == V2::ISOLATED_COMPONENT_ETS_TAG) {
2171 auto windowId = parentInfo.GetWindowId();
2172 for (auto& info : extensionElementInfos) {
2173 info.SetWindowId(windowId);
2174 }
2175 }
2176 for (auto& info : extensionElementInfos) {
2177 infos.push_back(info);
2178 }
2179 }
2180 }
2181 }
2182
UpdateChildrenNodeInCache(std::list<AccessibilityElementInfo> & infos,const CommonProperty & commonProperty,const RefPtr<NG::PipelineContext> & ngPipeline,const SearchParameter & searchParam,std::list<RefPtr<NG::FrameNode>> & children)2183 void JsAccessibilityManager::UpdateChildrenNodeInCache(std::list<AccessibilityElementInfo>& infos,
2184 const CommonProperty& commonProperty, const RefPtr<NG::PipelineContext>& ngPipeline,
2185 const SearchParameter& searchParam, std::list<RefPtr<NG::FrameNode>>& children)
2186 {
2187 while (!children.empty()) {
2188 RefPtr<NG::FrameNode> frameNodeParent = children.front();
2189 children.pop_front();
2190 AccessibilityElementInfo nodeInfo;
2191 auto accessibilityProperty = frameNodeParent->GetAccessibilityProperty<NG::AccessibilityProperty>();
2192 auto uiVirtualNode = accessibilityProperty->GetAccessibilityVirtualNode();
2193 if (CheckAndSetAccessibilityVisible(frameNodeParent, commonProperty.isReduceMode)) {
2194 UpdateAccessibilityElementInfo(frameNodeParent, commonProperty, nodeInfo, ngPipeline);
2195 }
2196 if (uiVirtualNode != nullptr) {
2197 auto virtualNode = AceType::DynamicCast<NG::FrameNode>(uiVirtualNode);
2198 if (virtualNode == nullptr) {
2199 continue;
2200 }
2201 AccessibilityElementInfo virtualInfo;
2202 UpdateVirtualNodeAccessibilityElementInfo(
2203 frameNodeParent, virtualNode, commonProperty, virtualInfo, ngPipeline);
2204 virtualInfo.SetParent(frameNodeParent->GetAccessibilityId());
2205 auto childIds = nodeInfo.GetChildIds();
2206 for (auto& child : childIds) {
2207 nodeInfo.RemoveChild(child);
2208 }
2209 nodeInfo.AddChild(virtualNode->GetAccessibilityId());
2210 auto uiParentNode = AceType::DynamicCast<NG::UINode>(frameNodeParent);
2211 if (!uiVirtualNode->GetChildren(true).empty()) {
2212 UpdateVirtualNodeInfo(infos, virtualInfo, uiVirtualNode, commonProperty, ngPipeline);
2213 }
2214 infos.push_back(virtualInfo);
2215 infos.push_back(nodeInfo);
2216 continue;
2217 }
2218 if (!IsExtensionComponent(frameNodeParent) || IsUIExtensionShowPlaceholder(frameNodeParent)) {
2219 infos.push_back(nodeInfo);
2220 GetChildrenFromFrameNode(frameNodeParent, children, commonProperty);
2221 continue;
2222 }
2223 if (!((frameNodeParent->GetUiExtensionId() > NG::UI_EXTENSION_UNKNOW_ID) &&
2224 (((frameNodeParent->GetUiExtensionId() <= NG::UI_EXTENSION_ID_FIRST_MAX) &&
2225 (NG::UI_EXTENSION_OFFSET_MAX == searchParam.uiExtensionOffset)) ||
2226 (frameNodeParent->GetUiExtensionId() <= NG::UI_EXTENSION_ID_OTHER_MAX)))) {
2227 continue;
2228 }
2229 auto transferParam = searchParam;
2230 transferParam.nodeId = NG::UI_EXTENSION_ROOT_ID;
2231 SearchExtensionElementInfoNG(transferParam, frameNodeParent, infos, nodeInfo);
2232 infos.push_back(nodeInfo);
2233 }
2234 }
2235
UpdateCacheInfoNG(std::list<AccessibilityElementInfo> & infos,const RefPtr<NG::FrameNode> & node,CommonProperty & commonProperty,const RefPtr<NG::PipelineContext> & ngPipeline,const SearchParameter & searchParam)2236 void JsAccessibilityManager::UpdateCacheInfoNG(std::list<AccessibilityElementInfo>& infos,
2237 const RefPtr<NG::FrameNode>& node, CommonProperty& commonProperty,
2238 const RefPtr<NG::PipelineContext>& ngPipeline, const SearchParameter& searchParam)
2239 {
2240 uint32_t umode = searchParam.mode;
2241 std::list<RefPtr<NG::FrameNode>> children;
2242 // get all children
2243 if ((umode & (static_cast<uint32_t>(PREFETCH_RECURSIVE_CHILDREN) |
2244 static_cast<uint32_t>(PREFETCH_RECURSIVE_CHILDREN_REDUCED))) == 0) {
2245 return;
2246 }
2247 commonProperty.isReduceMode = umode & static_cast<uint32_t>(PREFETCH_RECURSIVE_CHILDREN_REDUCED);
2248 GetChildrenFromFrameNode(node, children, commonProperty);
2249 UpdateChildrenNodeInCache(infos, commonProperty, ngPipeline, searchParam, children);
2250 }
2251
2252 namespace {
CanAccessibilityFocusedNG(const RefPtr<NG::FrameNode> & node)2253 bool CanAccessibilityFocusedNG(const RefPtr<NG::FrameNode>& node)
2254 {
2255 CHECK_NULL_RETURN(node, false);
2256 auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
2257 CHECK_NULL_RETURN(accessibilityProperty, false);
2258 auto level = accessibilityProperty->GetAccessibilityLevel();
2259 return !node->IsRootNode() &&
2260 node->GetLayoutProperty()->GetVisibilityValue(VisibleType::VISIBLE) == VisibleType::VISIBLE &&
2261 level != NG::AccessibilityProperty::Level::NO_STR &&
2262 level != NG::AccessibilityProperty::Level::NO_HIDE_DESCENDANTS;
2263 }
2264 // focus move search
AddFocusableNode(std::list<RefPtr<NG::FrameNode>> & nodeList,const RefPtr<NG::FrameNode> & node)2265 void AddFocusableNode(std::list<RefPtr<NG::FrameNode>>& nodeList, const RefPtr<NG::FrameNode>& node)
2266 {
2267 auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
2268 CHECK_NULL_VOID(accessibilityProperty);
2269 auto level = accessibilityProperty->GetAccessibilityLevel();
2270 if (CanAccessibilityFocusedNG(node)) {
2271 nodeList.emplace_back(node);
2272 }
2273
2274 if (!accessibilityProperty->IsAccessibilityGroup() &&
2275 level != NG::AccessibilityProperty::Level::NO_HIDE_DESCENDANTS) {
2276 std::list<RefPtr<NG::FrameNode>> children;
2277 CommonProperty commonProperty;
2278 commonProperty.pageNodes.clear(); // empty means search all page
2279 commonProperty.pagePaths.clear();
2280 for (const auto& child : node->GetChildren(true)) {
2281 GetFrameNodeChildren(child, children, commonProperty);
2282 }
2283
2284 for (const auto& child : children) {
2285 AddFocusableNode(nodeList, child);
2286 }
2287 }
2288 }
2289
2290 // execute action
RequestFocus(RefPtr<NG::FrameNode> & frameNode)2291 bool RequestFocus(RefPtr<NG::FrameNode>& frameNode)
2292 {
2293 auto focusHub = frameNode->GetFocusHub();
2294 CHECK_NULL_RETURN(focusHub, false);
2295 return focusHub->RequestFocusImmediately();
2296 }
2297
LostFocus(const RefPtr<NG::FrameNode> & frameNode)2298 bool LostFocus(const RefPtr<NG::FrameNode>& frameNode)
2299 {
2300 CHECK_NULL_RETURN(frameNode, false);
2301 auto focusHub = frameNode->GetFocusHub();
2302 CHECK_NULL_RETURN(focusHub, false);
2303 focusHub->LostFocus();
2304 return true;
2305 }
2306
ActClick(RefPtr<NG::FrameNode> & frameNode)2307 bool ActClick(RefPtr<NG::FrameNode>& frameNode)
2308 {
2309 auto eventHub = frameNode->GetEventHub<NG::EventHub>();
2310 CHECK_NULL_RETURN(eventHub, false);
2311 auto gesture = eventHub->GetGestureEventHub();
2312 CHECK_NULL_RETURN(gesture, false);
2313 bool result = gesture->ActClick();
2314 auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
2315 CHECK_NULL_RETURN(accessibilityProperty, result);
2316 auto accessibilityAction = ACTIONS.find(ACCESSIBILITY_ACTION_CLICK);
2317 if (accessibilityAction == ACTIONS.end()) {
2318 return result;
2319 }
2320 AccessibilityActionParam param;
2321 param.accessibilityProperty = accessibilityProperty;
2322 result |= accessibilityAction->second(param);
2323 return result;
2324 }
2325
ActLongClick(RefPtr<NG::FrameNode> & frameNode)2326 bool ActLongClick(RefPtr<NG::FrameNode>& frameNode)
2327 {
2328 auto gesture = frameNode->GetEventHub<NG::EventHub>()->GetGestureEventHub();
2329 CHECK_NULL_RETURN(gesture, false);
2330 return gesture->ActLongClick();
2331 }
2332
CreateOrUpdateAccessibilityFocusPaint(const RefPtr<NG::FrameNode> & focusFrameNode)2333 void CreateOrUpdateAccessibilityFocusPaint(const RefPtr<NG::FrameNode>& focusFrameNode)
2334 {
2335 CHECK_NULL_VOID(focusFrameNode);
2336 ACE_SCOPED_TRACE("CreateOrUpdateAccessibilityFocusPaint: targetNode[%s].", focusFrameNode->GetTag().c_str());
2337 auto paintNode = NG::FrameNode::CreateFrameNode(V2::ACCESSIBILITY_FOCUS_PAINT_NODE_TAG,
2338 ElementRegister::GetInstance()->MakeUniqueId(),
2339 AceType::MakeRefPtr<NG::AccessibilityFocusPaintNodePattern>(focusFrameNode));
2340 CHECK_NULL_VOID(paintNode);
2341 auto pattern = paintNode->GetPattern<NG::AccessibilityFocusPaintNodePattern>();
2342 CHECK_NULL_VOID(pattern);
2343 pattern->UpdateFocusNode(focusFrameNode);
2344 auto renderContext = paintNode->GetRenderContext();
2345 CHECK_NULL_VOID(renderContext);
2346 renderContext->OnZIndexUpdate(INT32_MAX);
2347 renderContext->ResetAccessibilityFocusRect();
2348 renderContext->UpdateAccessibilityFocus(true);
2349
2350 auto pipeline = focusFrameNode->GetContextRefPtr();
2351 CHECK_NULL_VOID(pipeline);
2352 auto overlayManager = pipeline->GetOverlayManager();
2353 CHECK_NULL_VOID(overlayManager);
2354
2355 auto rootNode = AceType::DynamicCast<NG::FrameNode>(overlayManager->FindWindowScene(focusFrameNode));
2356 CHECK_NULL_VOID(rootNode);
2357 pattern->UpdateRootNode(rootNode);
2358 rootNode->SetFocusPaintNode(paintNode);
2359 rootNode->MarkNeedSyncRenderTree();
2360 rootNode->RebuildRenderContextTree();
2361 }
2362
RemoveAccessibilityFocusPaint(const RefPtr<NG::FrameNode> & focusFrameNode)2363 void RemoveAccessibilityFocusPaint(const RefPtr<NG::FrameNode>& focusFrameNode)
2364 {
2365 CHECK_NULL_VOID(focusFrameNode);
2366 ACE_SCOPED_TRACE("Node[%s] RemoveAccessibilityFocusPaint", focusFrameNode->GetTag().c_str());
2367 auto paintNode = focusFrameNode->GetPaintNode();
2368 CHECK_NULL_VOID(paintNode);
2369 focusFrameNode->SetPaintNode(nullptr);
2370 auto renderContext = paintNode->GetRenderContext();
2371 CHECK_NULL_VOID(renderContext);
2372 renderContext->UpdateAccessibilityFocus(false);
2373 auto pattern = paintNode->GetPattern<NG::AccessibilityFocusPaintNodePattern>();
2374 CHECK_NULL_VOID(pattern);
2375 auto rootNode = AceType::DynamicCast<NG::FrameNode>(pattern->GetRootNode().Upgrade());
2376 CHECK_NULL_VOID(rootNode);
2377 rootNode->SetFocusPaintNode(nullptr);
2378 rootNode->MarkNeedSyncRenderTree();
2379 rootNode->RebuildRenderContextTree();
2380 }
2381
PaintAccessibilityFocusNode(const RefPtr<NG::FrameNode> & focusNode,bool focus)2382 void PaintAccessibilityFocusNode(const RefPtr<NG::FrameNode>& focusNode, bool focus)
2383 {
2384 CHECK_NULL_VOID(focusNode);
2385 if (focusNode->IsDrawFocusOnTop()) {
2386 if (focus) {
2387 CreateOrUpdateAccessibilityFocusPaint(focusNode);
2388 UpdatePaintNodeRender(focusNode);
2389 } else {
2390 RemoveAccessibilityFocusPaint(focusNode);
2391 }
2392 } else {
2393 auto context = focusNode->GetRenderContext();
2394 CHECK_NULL_VOID(context);
2395 context->UpdateAccessibilityFocus(focus);
2396 }
2397 }
2398
ClearAccessibilityFocus(const RefPtr<NG::FrameNode> & root,int64_t focusNodeId)2399 void ClearAccessibilityFocus(const RefPtr<NG::FrameNode>& root, int64_t focusNodeId)
2400 {
2401 auto oldFocusNode = GetFramenodeByAccessibilityId(root, focusNodeId);
2402 CHECK_NULL_VOID(oldFocusNode);
2403 if (oldFocusNode->IsDrawFocusOnTop()) {
2404 PaintAccessibilityFocusNode(oldFocusNode, false);
2405 } else {
2406 oldFocusNode->GetRenderContext()->UpdateAccessibilityFocus(false);
2407 }
2408 }
2409
UpdateAccessibilityFocusRect(const RefPtr<NG::FrameNode> & frameNode,RefPtr<NG::RenderContext> & renderContext,bool isAccessibilityVirtualNode)2410 void UpdateAccessibilityFocusRect(const RefPtr<NG::FrameNode>& frameNode,
2411 RefPtr<NG::RenderContext>& renderContext,
2412 bool isAccessibilityVirtualNode)
2413 {
2414 CHECK_NULL_VOID(frameNode);
2415 CHECK_NULL_VOID(renderContext);
2416 auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
2417 CHECK_NULL_VOID(accessibilityProperty);
2418 if (accessibilityProperty->IsMatchAccessibilityResponseRegion(isAccessibilityVirtualNode)) {
2419 auto rectInt = accessibilityProperty->GetAccessibilityResponseRegionRect(isAccessibilityVirtualNode);
2420 renderContext->UpdateAccessibilityFocusRect(rectInt);
2421 if (isAccessibilityVirtualNode) {
2422 renderContext->UpdateAccessibilityFocus(true, frameNode->GetAccessibilityId());
2423 } else {
2424 PaintAccessibilityFocusNode(frameNode, true);
2425 }
2426 } else {
2427 if (isAccessibilityVirtualNode) {
2428 auto rect = frameNode->GetTransformRectRelativeToWindow();
2429 NG::RectT<int32_t> rectInt { static_cast<int32_t>(rect.Left()), static_cast<int32_t>(rect.Top()),
2430 static_cast<int32_t>(rect.Width()), static_cast<int32_t>(rect.Height()) };
2431 renderContext->UpdateAccessibilityFocusRect(rectInt);
2432 renderContext->UpdateAccessibilityFocus(true, frameNode->GetAccessibilityId());
2433 } else {
2434 renderContext->ResetAccessibilityFocusRect();
2435 PaintAccessibilityFocusNode(frameNode, true);
2436 }
2437 }
2438 }
2439
ActAccessibilityFocus(int64_t elementId,const RefPtr<NG::FrameNode> & frameNode,RefPtr<NG::PipelineContext> & context,int64_t & currentFocusNodeId,bool isNeedClear)2440 bool ActAccessibilityFocus(int64_t elementId, const RefPtr<NG::FrameNode>& frameNode,
2441 RefPtr<NG::PipelineContext>& context, int64_t& currentFocusNodeId, bool isNeedClear)
2442 {
2443 CHECK_NULL_RETURN(frameNode, false);
2444 bool isAccessibilityVirtualNode = frameNode->IsAccessibilityVirtualNode();
2445 RefPtr<NG::RenderContext> renderContext = nullptr;
2446 if (isAccessibilityVirtualNode) {
2447 auto parentUinode = frameNode->GetVirtualNodeParent().Upgrade();
2448 CHECK_NULL_RETURN(parentUinode, false);
2449 auto parentFrame = AceType::DynamicCast<NG::FrameNode>(parentUinode);
2450 CHECK_NULL_RETURN(parentFrame, false);
2451 renderContext = parentFrame->GetRenderContext();
2452 } else {
2453 renderContext = frameNode->GetRenderContext();
2454 }
2455 CHECK_NULL_RETURN(renderContext, false);
2456 if (isNeedClear) {
2457 if (elementId != currentFocusNodeId) {
2458 return false;
2459 }
2460 if (isAccessibilityVirtualNode) {
2461 renderContext->UpdateAccessibilityFocus(false);
2462 } else {
2463 PaintAccessibilityFocusNode(frameNode, false);
2464 }
2465 currentFocusNodeId = -1;
2466 auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
2467 CHECK_NULL_RETURN(accessibilityProperty, true);
2468 accessibilityProperty->OnAccessibilityFocusCallback(false);
2469 accessibilityProperty->SetAccessibilityFocusState(false);
2470 return true;
2471 }
2472 if (elementId == currentFocusNodeId) {
2473 return false;
2474 }
2475 Framework::ClearAccessibilityFocus(context->GetRootElement(), currentFocusNodeId);
2476 UpdateAccessibilityFocusRect(frameNode, renderContext, isAccessibilityVirtualNode);
2477 currentFocusNodeId = frameNode->GetAccessibilityId();
2478 auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
2479 CHECK_NULL_RETURN(accessibilityProperty, false);
2480 accessibilityProperty->OnAccessibilityFocusCallback(true);
2481 accessibilityProperty->SetAccessibilityFocusState(true);
2482 ProcessFocusScroll(frameNode, context);
2483 return true;
2484 }
2485
GetSupportAction(const std::unordered_set<AceAction> & supportAceActions)2486 inline std::string GetSupportAction(const std::unordered_set<AceAction>& supportAceActions)
2487 {
2488 std::string actionForDump;
2489 for (const auto& action : supportAceActions) {
2490 if (!actionForDump.empty()) {
2491 actionForDump.append(",");
2492 }
2493 actionForDump.append(std::to_string(static_cast<int32_t>(action)));
2494 }
2495 return actionForDump;
2496 }
2497
ConvertActionTypeToString(ActionType action)2498 static std::string ConvertActionTypeToString(ActionType action)
2499 {
2500 static const ActionStrTable actionStrTable[] = {
2501 { ActionType::ACCESSIBILITY_ACTION_FOCUS, "ACCESSIBILITY_ACTION_FOCUS" },
2502 { ActionType::ACCESSIBILITY_ACTION_CLEAR_FOCUS, "ACCESSIBILITY_ACTION_CLEAR_FOCUS" },
2503 { ActionType::ACCESSIBILITY_ACTION_SELECT, "ACCESSIBILITY_ACTION_SELECT" },
2504 { ActionType::ACCESSIBILITY_ACTION_CLEAR_SELECTION, "ACCESSIBILITY_ACTION_CLEAR_SELECTION" },
2505 { ActionType::ACCESSIBILITY_ACTION_CLICK, "ACCESSIBILITY_ACTION_CLICK" },
2506 { ActionType::ACCESSIBILITY_ACTION_LONG_CLICK, "ACCESSIBILITY_ACTION_LONG_CLICK" },
2507 { ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS, "ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS" },
2508 { ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS,
2509 "ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS" },
2510 { ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD, "ACCESSIBILITY_ACTION_SCROLL_FORWARD" },
2511 { ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD, "ACCESSIBILITY_ACTION_SCROLL_BACKWARD" },
2512 { ActionType::ACCESSIBILITY_ACTION_COPY, "ACCESSIBILITY_ACTION_COPY" },
2513 { ActionType::ACCESSIBILITY_ACTION_PASTE, "ACCESSIBILITY_ACTION_PASTE" },
2514 { ActionType::ACCESSIBILITY_ACTION_CUT, "ACCESSIBILITY_ACTION_CUT" },
2515 { ActionType::ACCESSIBILITY_ACTION_SET_SELECTION, "ACCESSIBILITY_ACTION_SET_SELECTION" },
2516 { ActionType::ACCESSIBILITY_ACTION_SET_TEXT, "ACCESSIBILITY_ACTION_SET_TEXT" },
2517 { ActionType::ACCESSIBILITY_ACTION_NEXT_TEXT, "ACCESSIBILITY_ACTION_NEXT_TEXT" },
2518 { ActionType::ACCESSIBILITY_ACTION_PREVIOUS_TEXT, "ACCESSIBILITY_ACTION_PREVIOUS_TEXT" },
2519 { ActionType::ACCESSIBILITY_ACTION_SET_CURSOR_POSITION, "ACCESSIBILITY_ACTION_SET_CURSOR_POSITION" },
2520 { ActionType::ACCESSIBILITY_ACTION_SPAN_CLICK, "ACCESSIBILITY_ACTION_SPAN_CLICK" },
2521 { ActionType::ACCESSIBILITY_ACTION_NEXT_HTML_ITEM, "ACCESSIBILITY_ACTION_NEXT_HTML_ITEM" },
2522 { ActionType::ACCESSIBILITY_ACTION_PREVIOUS_HTML_ITEM, "ACCESSIBILITY_ACTION_PREVIOUS_HTML_ITEM" },
2523 };
2524 for (const auto& item : actionStrTable) {
2525 if (action == item.action) {
2526 return item.actionStr;
2527 }
2528 }
2529 return ACTION_DEFAULT_PARAM;
2530 }
2531
ConvertAccessibilityAction(ActionType accessibilityAction)2532 static AceAction ConvertAccessibilityAction(ActionType accessibilityAction)
2533 {
2534 static const ActionTable actionTable[] = {
2535 { AceAction::ACTION_CLICK, ActionType::ACCESSIBILITY_ACTION_CLICK },
2536 { AceAction::ACTION_LONG_CLICK, ActionType::ACCESSIBILITY_ACTION_LONG_CLICK },
2537 { AceAction::ACTION_SCROLL_FORWARD, ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD },
2538 { AceAction::ACTION_SCROLL_BACKWARD, ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD },
2539 { AceAction::ACTION_FOCUS, ActionType::ACCESSIBILITY_ACTION_FOCUS },
2540 { AceAction::ACTION_CLEAR_FOCUS, ActionType::ACCESSIBILITY_ACTION_CLEAR_FOCUS },
2541 { AceAction::ACTION_ACCESSIBILITY_FOCUS, ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS },
2542 { AceAction::ACTION_CLEAR_ACCESSIBILITY_FOCUS, ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS },
2543 { AceAction::ACTION_NEXT_AT_MOVEMENT_GRANULARITY, ActionType::ACCESSIBILITY_ACTION_NEXT_TEXT },
2544 { AceAction::ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, ActionType::ACCESSIBILITY_ACTION_PREVIOUS_TEXT },
2545 { AceAction::ACTION_SET_TEXT, ActionType::ACCESSIBILITY_ACTION_SET_TEXT },
2546 { AceAction::ACTION_COPY, ActionType::ACCESSIBILITY_ACTION_COPY },
2547 { AceAction::ACTION_PASTE, ActionType::ACCESSIBILITY_ACTION_PASTE },
2548 { AceAction::ACTION_CUT, ActionType::ACCESSIBILITY_ACTION_CUT },
2549 { AceAction::ACTION_SELECT, ActionType::ACCESSIBILITY_ACTION_SELECT },
2550 { AceAction::ACTION_CLEAR_SELECTION, ActionType::ACCESSIBILITY_ACTION_CLEAR_SELECTION },
2551 { AceAction::ACTION_SET_SELECTION, ActionType::ACCESSIBILITY_ACTION_SET_SELECTION },
2552 { AceAction::ACTION_SET_CURSOR_POSITION, ActionType::ACCESSIBILITY_ACTION_SET_CURSOR_POSITION },
2553 { AceAction::ACTION_EXEC_SUB_COMPONENT, ActionType::ACCESSIBILITY_ACTION_SPAN_CLICK },
2554 { AceAction::ACTION_NEXT_HTML_ITEM, ActionType::ACCESSIBILITY_ACTION_NEXT_HTML_ITEM },
2555 { AceAction::ACTION_PREVIOUS_HTML_ITEM, ActionType::ACCESSIBILITY_ACTION_PREVIOUS_HTML_ITEM },
2556 };
2557 for (const auto& item : actionTable) {
2558 if (accessibilityAction == item.action) {
2559 return item.aceAction;
2560 }
2561 }
2562 return AceAction::ACTION_NONE;
2563 }
2564
DumpSupportActionNG(const AccessibilityElementInfo & nodeInfo)2565 static void DumpSupportActionNG(const AccessibilityElementInfo& nodeInfo)
2566 {
2567 DumpLog::GetInstance().AddDesc(
2568 "support action instructions: use command to make application components perform corresponding action");
2569 DumpLog::GetInstance().AddDesc(
2570 "use support action command: aa dump -i [AbilityRecord] -c -inspector [AccessibilityId] [AceAction]");
2571 std::string actionForDump;
2572 for (const auto& action : nodeInfo.GetActionList()) {
2573 if (!actionForDump.empty()) {
2574 actionForDump.append(",");
2575 }
2576 actionForDump.append(ConvertActionTypeToString(action.GetActionType()));
2577 actionForDump.append(": ");
2578 actionForDump.append(std::to_string(static_cast<int32_t>(ConvertAccessibilityAction(action.GetActionType()))));
2579 }
2580 DumpLog::GetInstance().AddDesc("support action: ", actionForDump);
2581 }
2582
DumpGridInfoNG(const AccessibilityElementInfo & nodeInfo)2583 static void DumpGridInfoNG(const AccessibilityElementInfo& nodeInfo)
2584 {
2585 DumpLog::GetInstance().AddDesc("grid info rows: ", nodeInfo.GetGrid().GetRowCount());
2586 DumpLog::GetInstance().AddDesc("grid info columns: ", nodeInfo.GetGrid().GetColumnCount());
2587 DumpLog::GetInstance().AddDesc("grid info select mode: ", nodeInfo.GetGrid().GetSelectionMode());
2588 DumpLog::GetInstance().AddDesc("grid item info, row: ", nodeInfo.GetGridItem().GetRowIndex());
2589 DumpLog::GetInstance().AddDesc("grid item info, column: ", nodeInfo.GetGridItem().GetColumnIndex());
2590 DumpLog::GetInstance().AddDesc("grid item info, rowSpan: ", nodeInfo.GetGridItem().GetRowSpan());
2591 DumpLog::GetInstance().AddDesc("grid item info, columnSpan: ", nodeInfo.GetGridItem().GetColumnSpan());
2592 DumpLog::GetInstance().AddDesc("grid item info, is heading: ", nodeInfo.GetGridItem().IsHeading());
2593 DumpLog::GetInstance().AddDesc("grid item info, selected: ", nodeInfo.GetGridItem().IsSelected());
2594 }
2595
DumpContentListNG(const AccessibilityElementInfo & nodeInfo)2596 inline void DumpContentListNG(const AccessibilityElementInfo& nodeInfo)
2597 {
2598 std::vector<std::string> contentList;
2599 nodeInfo.GetContentList(contentList);
2600 std::string contents;
2601 for (const auto& content : contentList) {
2602 if (!contents.empty()) {
2603 contents.append(",");
2604 }
2605 contents.append(content);
2606 }
2607 DumpLog::GetInstance().AddDesc("content list: ", contents);
2608 }
2609
DumpExtraElementInfoNG(const AccessibilityElementInfo & nodeInfo)2610 static void DumpExtraElementInfoNG(const AccessibilityElementInfo& nodeInfo)
2611 {
2612 ExtraElementInfo extraElementInfo = nodeInfo.GetExtraElement();
2613 if (!extraElementInfo.GetExtraElementInfoValueStr().empty()) {
2614 for (auto i = extraElementInfo.GetExtraElementInfoValueStr().begin();
2615 i != extraElementInfo.GetExtraElementInfoValueStr().end(); ++i) {
2616 DumpLog::GetInstance().AddDesc("extra element info: ", i->first, i->second);
2617 }
2618 }
2619 if (!extraElementInfo.GetExtraElementInfoValueInt().empty()) {
2620 for (auto i = extraElementInfo.GetExtraElementInfoValueInt().begin();
2621 i != extraElementInfo.GetExtraElementInfoValueInt().end(); ++i) {
2622 DumpLog::GetInstance().AddDesc("extra element info: ", i->first, i->second);
2623 }
2624 }
2625 }
2626
UpdateSpanList(std::vector<SpanInfo> & spansInfosList,std::string & spans)2627 static void UpdateSpanList(std::vector<SpanInfo>& spansInfosList, std::string& spans)
2628 {
2629 for (const auto& span : spansInfosList) {
2630 if (!spans.empty()) {
2631 spans.append(",");
2632 }
2633 spans.append("\n\t span id: ");
2634 spans.append(std::to_string(span.GetSpanId()));
2635 spans.append(", span text: ");
2636 spans.append(span.GetSpanText());
2637 spans.append(", accessibility text: ");
2638 spans.append(span.GetAccessibilityText());
2639 spans.append(", accessibility description: ");
2640 spans.append(span.GetAccessibilityDescription());
2641 spans.append(", accessibility level: ");
2642 spans.append(span.GetAccessibilityLevel());
2643 }
2644 }
2645
DumpSpanListNG(const AccessibilityElementInfo & nodeInfo)2646 inline void DumpSpanListNG(const AccessibilityElementInfo& nodeInfo)
2647 {
2648 std::string spans;
2649 std::vector<SpanInfo> spansInfosList = nodeInfo.GetSpanList();
2650 std::size_t spanCount = spansInfosList.size();
2651 UpdateSpanList(spansInfosList, spans);
2652 DumpLog::GetInstance().AddDesc("span list count: ", static_cast<int32_t>(spanCount));
2653 DumpLog::GetInstance().AddDesc("span list: ", spans);
2654 }
2655
ChildrenToString(const std::vector<int64_t> & children,int32_t treeId)2656 inline std::string ChildrenToString(const std::vector<int64_t>& children, int32_t treeId)
2657 {
2658 std::string ids;
2659 for (auto child : children) {
2660 if (!ids.empty()) {
2661 ids.append(",");
2662 }
2663 int64_t childId = child;
2664 AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(treeId, childId);
2665 ids.append(std::to_string(childId));
2666 }
2667 return ids;
2668 }
2669
DumpRectNG(const Accessibility::Rect & rect)2670 inline void DumpRectNG(const Accessibility::Rect& rect)
2671 {
2672 DumpLog::GetInstance().AddDesc(
2673 "width: ", std::to_string(rect.GetRightBottomXScreenPostion() - rect.GetLeftTopXScreenPostion()));
2674 DumpLog::GetInstance().AddDesc(
2675 "height: ", std::to_string(rect.GetRightBottomYScreenPostion() - rect.GetLeftTopYScreenPostion()));
2676 DumpLog::GetInstance().AddDesc("left: ", std::to_string(rect.GetLeftTopXScreenPostion()));
2677 DumpLog::GetInstance().AddDesc("top: ", std::to_string(rect.GetLeftTopYScreenPostion()));
2678 DumpLog::GetInstance().AddDesc("right: ", std::to_string(rect.GetRightBottomXScreenPostion()));
2679 DumpLog::GetInstance().AddDesc("bottom: ", std::to_string(rect.GetRightBottomYScreenPostion()));
2680 }
2681
GenerateAccessibilityEventInfo(const AccessibilityEvent & accessibilityEvent,AccessibilityEventInfo & eventInfo)2682 void GenerateAccessibilityEventInfo(const AccessibilityEvent& accessibilityEvent, AccessibilityEventInfo& eventInfo)
2683 {
2684 Accessibility::EventType type = Accessibility::EventType::TYPE_VIEW_INVALID;
2685 if (accessibilityEvent.type != AccessibilityEventType::UNKNOWN) {
2686 type = ConvertAceEventType(accessibilityEvent.type);
2687 } else {
2688 type = ConvertStrToEventType(accessibilityEvent.eventType);
2689 }
2690
2691 if (type == Accessibility::EventType::TYPE_VIEW_INVALID) {
2692 return;
2693 }
2694
2695 eventInfo.SetTimeStamp(GetMicroTickCount());
2696 eventInfo.SetBeforeText(accessibilityEvent.beforeText);
2697 eventInfo.SetLatestContent(accessibilityEvent.latestContent);
2698 eventInfo.SetTextAnnouncedForAccessibility(accessibilityEvent.textAnnouncedForAccessibility);
2699 eventInfo.SetWindowChangeTypes(static_cast<Accessibility::WindowUpdateType>(accessibilityEvent.windowChangeTypes));
2700 eventInfo.SetWindowContentChangeTypes(
2701 static_cast<Accessibility::WindowsContentChangeTypes>(accessibilityEvent.windowContentChangeTypes));
2702 eventInfo.SetSource(accessibilityEvent.nodeId);
2703 eventInfo.SetEventType(type);
2704 eventInfo.SetCurrentIndex(static_cast<int>(accessibilityEvent.currentItemIndex));
2705 eventInfo.SetItemCounts(static_cast<int>(accessibilityEvent.itemCount));
2706 eventInfo.SetBundleName(AceApplicationInfo::GetInstance().GetPackageName());
2707 eventInfo.SetBeginIndex(accessibilityEvent.startIndex);
2708 eventInfo.SetEndIndex(accessibilityEvent.endIndex);
2709 }
2710 } // namespace
2711
DumpAccessibilityPropertyNG(const AccessibilityElementInfo & nodeInfo)2712 void JsAccessibilityManager::DumpAccessibilityPropertyNG(const AccessibilityElementInfo& nodeInfo)
2713 {
2714 DumpLog::GetInstance().AddDesc("checked: ", BoolToString(nodeInfo.IsChecked()));
2715 DumpLog::GetInstance().AddDesc("selected: ", BoolToString(nodeInfo.IsSelected()));
2716 DumpLog::GetInstance().AddDesc("checkable: ", BoolToString(nodeInfo.IsCheckable()));
2717 DumpLog::GetInstance().AddDesc("scrollable: ", BoolToString(nodeInfo.IsScrollable()));
2718 DumpLog::GetInstance().AddDesc("accessibility hint: ", BoolToString(nodeInfo.IsGivingHint()));
2719 DumpLog::GetInstance().AddDesc("hint text: ", nodeInfo.GetHint());
2720 DumpLog::GetInstance().AddDesc("error text: ", nodeInfo.GetError());
2721 DumpLog::GetInstance().AddDesc("max text length: ", nodeInfo.GetTextLengthLimit());
2722 DumpLog::GetInstance().AddDesc("scroll offset: ", nodeInfo.GetOffset());
2723 DumpLog::GetInstance().AddDesc("text selection start: ", nodeInfo.GetSelectedBegin());
2724 DumpLog::GetInstance().AddDesc("text selection end: ", nodeInfo.GetSelectedEnd());
2725 DumpLog::GetInstance().AddDesc("is multi line: ", BoolToString(nodeInfo.IsPluraLineSupported()));
2726 DumpLog::GetInstance().AddDesc("is password: ", BoolToString(nodeInfo.IsPassword()));
2727 DumpLog::GetInstance().AddDesc(
2728 "text input type: ", ConvertInputTypeToString(static_cast<AceTextCategory>(nodeInfo.GetInputType())));
2729 DumpGridInfoNG(nodeInfo);
2730 DumpLog::GetInstance().AddDesc("min value: ", nodeInfo.GetRange().GetMin());
2731 DumpLog::GetInstance().AddDesc("max value: ", nodeInfo.GetRange().GetMax());
2732 DumpLog::GetInstance().AddDesc("current value: ", nodeInfo.GetRange().GetCurrent());
2733 DumpLog::GetInstance().AddDesc("current index: ", nodeInfo.GetCurrentIndex());
2734 DumpLog::GetInstance().AddDesc("begin index: ", nodeInfo.GetBeginIndex());
2735 DumpLog::GetInstance().AddDesc("end index: ", nodeInfo.GetEndIndex());
2736 DumpLog::GetInstance().AddDesc("collection item counts: ", nodeInfo.GetItemCounts());
2737 DumpLog::GetInstance().AddDesc("editable: ", BoolToString(nodeInfo.IsEditable()));
2738 DumpLog::GetInstance().AddDesc("is essential: ", BoolToString(nodeInfo.IsEssential()));
2739 DumpLog::GetInstance().AddDesc("deletable: ", nodeInfo.IsDeletable());
2740 DumpLog::GetInstance().AddDesc("live region: ", nodeInfo.GetLiveRegion());
2741 DumpLog::GetInstance().AddDesc("content description: ", nodeInfo.GetDescriptionInfo());
2742 DumpLog::GetInstance().AddDesc("content invalid: ", BoolToString(nodeInfo.GetContentInvalid()));
2743 DumpLog::GetInstance().AddDesc("accessibility label: ", nodeInfo.GetLabeledAccessibilityId());
2744 DumpLog::GetInstance().AddDesc("isActive: ", nodeInfo.GetIsActive());
2745 DumpLog::GetInstance().AddDesc("accessibilityVisible: ", nodeInfo.GetAccessibilityVisible());
2746 DumpLog::GetInstance().AddDesc("accessibilityNextFocusInspectorKey: ",
2747 nodeInfo.GetAccessibilityNextFocusInspectorKey());
2748 DumpLog::GetInstance().AddDesc("accessibilityScrollTriggerable: ",
2749 nodeInfo.GetAccessibilityScrollable());
2750 DumpLog::GetInstance().AddDesc("accessibilityNextFocusId: ", nodeInfo.GetAccessibilityNextFocusId());
2751 DumpLog::GetInstance().AddDesc("accessibilityPreviousFocusId: ", nodeInfo.GetAccessibilityPreviousFocusId());
2752 DumpLog::GetInstance().AddDesc("clip: ", nodeInfo.GetClip());
2753 DumpExtraElementInfoNG(nodeInfo);
2754 DumpLog::GetInstance().AddDesc(
2755 "trigger action: ", static_cast<int32_t>(ConvertAccessibilityAction(nodeInfo.GetTriggerAction())));
2756 DumpLog::GetInstance().AddDesc("text move step: " + std::to_string(nodeInfo.GetTextMovementStep()));
2757 DumpSpanListNG(nodeInfo);
2758 DumpSupportActionNG(nodeInfo);
2759 DumpContentListNG(nodeInfo);
2760 DumpLog::GetInstance().AddDesc("latest content: ", nodeInfo.GetLatestContent());
2761 }
2762
DumpCommonPropertyNG(const AccessibilityElementInfo & nodeInfo,int32_t treeId)2763 void JsAccessibilityManager::DumpCommonPropertyNG(const AccessibilityElementInfo& nodeInfo, int32_t treeId)
2764 {
2765 int64_t elementId = nodeInfo.GetAccessibilityId();
2766 AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(treeId, elementId);
2767 DumpLog::GetInstance().AddDesc("ID: ", elementId);
2768 int64_t parentId = nodeInfo.GetParentNodeId();
2769 AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(treeId, parentId);
2770 DumpLog::GetInstance().AddDesc("parent ID: ", parentId);
2771 DumpLog::GetInstance().AddDesc("child IDs: ", ChildrenToString(nodeInfo.GetChildIds(), treeId));
2772 DumpLog::GetInstance().AddDesc("component type: ", nodeInfo.GetComponentType());
2773 DumpLog::GetInstance().AddDesc("accessibilityCustomRole: " + nodeInfo.GetCustomComponentType());
2774 DumpLog::GetInstance().AddDesc("text: ", nodeInfo.GetContent());
2775 DumpLog::GetInstance().AddDesc("window id: " + std::to_string(nodeInfo.GetWindowId()));
2776 DumpRectNG(nodeInfo.GetRectInScreen());
2777
2778 DumpLog::GetInstance().AddDesc("enabled: ", BoolToString(nodeInfo.IsEnabled()));
2779 DumpLog::GetInstance().AddDesc("focusable: ", BoolToString(nodeInfo.IsFocusable()));
2780 DumpLog::GetInstance().AddDesc("focused: ", BoolToString(nodeInfo.IsFocused()));
2781 DumpLog::GetInstance().AddDesc("visible: ", BoolToString(nodeInfo.IsVisible()));
2782 DumpLog::GetInstance().AddDesc("accessibility focused: ", BoolToString(nodeInfo.HasAccessibilityFocus()));
2783 DumpLog::GetInstance().AddDesc("accessibilityText: " + nodeInfo.GetAccessibilityText());
2784 DumpLog::GetInstance().AddDesc("accessibilityGroup: " + BoolToString(nodeInfo.GetAccessibilityGroup()));
2785 DumpLog::GetInstance().AddDesc("accessibilityLevel: " + nodeInfo.GetAccessibilityLevel());
2786 DumpLog::GetInstance().AddDesc("accessibilityDescription: " + nodeInfo.GetDescriptionInfo());
2787 DumpLog::GetInstance().AddDesc("hitTestBehavior: " + nodeInfo.GetHitTestBehavior());
2788
2789 DumpLog::GetInstance().AddDesc("inspector key: ", nodeInfo.GetInspectorKey());
2790 DumpLog::GetInstance().AddDesc("bundle name: ", nodeInfo.GetBundleName());
2791 DumpLog::GetInstance().AddDesc("page id: " + std::to_string(nodeInfo.GetPageId()));
2792 DumpLog::GetInstance().AddDesc("page path: ", nodeInfo.GetPagePath());
2793 DumpLog::GetInstance().AddDesc("is valid element: ", BoolToString(nodeInfo.IsValidElement()));
2794 DumpLog::GetInstance().AddDesc("resource name: ", nodeInfo.GetComponentResourceId());
2795
2796 DumpLog::GetInstance().AddDesc("clickable: ", BoolToString(nodeInfo.IsClickable()));
2797 DumpLog::GetInstance().AddDesc("long clickable: ", BoolToString(nodeInfo.IsLongClickable()));
2798 DumpLog::GetInstance().AddDesc("popup supported: ", BoolToString(nodeInfo.IsPopupSupported()));
2799 DumpLog::GetInstance().AddDesc("zindex: ", std::to_string(nodeInfo.GetZIndex()));
2800 }
2801
UpdateVirtualNodeFocus()2802 void JsAccessibilityManager::UpdateVirtualNodeFocus()
2803 {
2804 auto frameNode = lastFrameNode_.Upgrade();
2805 CHECK_NULL_VOID(frameNode);
2806 if (!frameNode->IsAccessibilityVirtualNode()) {
2807 return;
2808 }
2809 RefPtr<NG::RenderContext> renderContext;
2810 auto geometryNode = frameNode->GetGeometryNode();
2811 CHECK_NULL_VOID(geometryNode);
2812 bool frameSizeChange = geometryNode->GetFrameSize() != oldGeometrySize_;
2813 if (frameNode->GetAccessibilityId() == currentFocusNodeId_ && frameSizeChange) {
2814 auto parentUinode = frameNode->GetVirtualNodeParent().Upgrade();
2815 CHECK_NULL_VOID(parentUinode);
2816 auto parentFrame = AceType::DynamicCast<NG::FrameNode>(parentUinode);
2817 CHECK_NULL_VOID(parentFrame);
2818 renderContext = parentFrame->GetRenderContext();
2819 CHECK_NULL_VOID(renderContext);
2820 renderContext->UpdateAccessibilityFocus(false);
2821 auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
2822 CHECK_NULL_VOID(accessibilityProperty);
2823 if (accessibilityProperty->IsMatchAccessibilityResponseRegion(true)) {
2824 auto rectInt = accessibilityProperty->GetAccessibilityResponseRegionRect(true);
2825 renderContext->UpdateAccessibilityFocusRect(rectInt);
2826 } else {
2827 auto rect = frameNode->GetTransformRectRelativeToWindow();
2828 NG::RectT<int32_t> rectInt { static_cast<int32_t>(rect.Left()), static_cast<int32_t>(rect.Top()),
2829 static_cast<int32_t>(rect.Width()), static_cast<int32_t>(rect.Height()) };
2830 renderContext->UpdateAccessibilityFocusRect(rectInt);
2831 }
2832 renderContext->UpdateAccessibilityFocus(true, frameNode->GetAccessibilityId());
2833 accessibilityProperty->SetAccessibilityFocusState(true);
2834 }
2835 }
2836
~JsAccessibilityManager()2837 JsAccessibilityManager::~JsAccessibilityManager()
2838 {
2839 UnsubscribeStateObserver(AccessibilityStateEventType::EVENT_ACCESSIBILITY_STATE_CHANGED);
2840 UnsubscribeStateObserver(AccessibilityStateEventType::EVENT_SCREEN_READER_STATE_CHANGED);
2841
2842 DeregisterInteractionOperation();
2843 }
OnConfigChanged(const AccessibilityConfig::CONFIG_ID id,const AccessibilityConfig::ConfigValue & value)2844 void JsAccessibilityManager::ToastAccessibilityConfigObserver::OnConfigChanged(
2845 const AccessibilityConfig::CONFIG_ID id, const AccessibilityConfig::ConfigValue& value)
2846 {
2847 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "accessibility content timeout changed:%{public}u", value.contentTimeout);
2848 AceApplicationInfo::GetInstance().SetBarrierfreeDuration((int32_t)value.contentTimeout);
2849 }
2850
SubscribeToastObserver()2851 bool JsAccessibilityManager::SubscribeToastObserver()
2852 {
2853 if (!toastObserver_) {
2854 toastObserver_ = std::make_shared<ToastAccessibilityConfigObserver>();
2855 }
2856 CHECK_NULL_RETURN(toastObserver_, false);
2857 auto& config = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
2858 bool isSuccess = config.InitializeContext();
2859 if (!isSuccess) {
2860 return false;
2861 }
2862 config.SubscribeConfigObserver(CONFIG_CONTENT_TIMEOUT, toastObserver_);
2863 return true;
2864 }
2865
UnsubscribeToastObserver()2866 bool JsAccessibilityManager::UnsubscribeToastObserver()
2867 {
2868 CHECK_NULL_RETURN(toastObserver_, false);
2869 auto& config = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
2870 bool isSuccess = config.InitializeContext();
2871 if (!isSuccess) {
2872 return false;
2873 }
2874 config.UnsubscribeConfigObserver(CONFIG_CONTENT_TIMEOUT, toastObserver_);
2875 return true;
2876 }
2877
SubscribeStateObserver(uint32_t eventType)2878 bool JsAccessibilityManager::SubscribeStateObserver(uint32_t eventType)
2879 {
2880 if (!stateObserver_[eventType]) {
2881 stateObserver_[eventType] = std::make_shared<JsAccessibilityStateObserver>();
2882 }
2883
2884 stateObserver_[eventType]->SetAccessibilityManager(WeakClaim(this));
2885 stateObserver_[eventType]->SetPipeline(context_);
2886 stateObserver_[eventType]->SetEventType(eventType);
2887
2888 auto instance = AccessibilitySystemAbilityClient::GetInstance();
2889 CHECK_NULL_RETURN(instance, false);
2890 Accessibility::RetError ret = instance->SubscribeStateObserver(stateObserver_[eventType], eventType);
2891 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, " the result of SubscribeStateObserver:%{public}d, eventType:%{public}u",
2892 ret, eventType);
2893 return ret == RET_OK;
2894 }
2895
UnsubscribeStateObserver(uint32_t eventType)2896 bool JsAccessibilityManager::UnsubscribeStateObserver(uint32_t eventType)
2897 {
2898 CHECK_NULL_RETURN(stateObserver_[eventType], false);
2899 std::shared_ptr<AccessibilitySystemAbilityClient> instance = AccessibilitySystemAbilityClient::GetInstance();
2900 CHECK_NULL_RETURN(instance, false);
2901 Accessibility::RetError ret = instance->UnsubscribeStateObserver(stateObserver_[eventType], eventType);
2902 return ret == RET_OK;
2903 }
2904
GenerateAccessibilityWorkMode()2905 AccessibilityWorkMode JsAccessibilityManager::GenerateAccessibilityWorkMode()
2906 {
2907 AccessibilityWorkMode accessibilityWorkMode;
2908 auto client = AccessibilitySystemAbilityClient::GetInstance();
2909 CHECK_NULL_RETURN(client, accessibilityWorkMode);
2910 auto ret = client->IsTouchExplorationEnabled(accessibilityWorkMode.isTouchExplorationEnabled);
2911 if (ret != RET_OK) {
2912 accessibilityWorkMode.isTouchExplorationEnabled = true;
2913 }
2914 return accessibilityWorkMode;
2915 }
2916
InitializeCallback()2917 void JsAccessibilityManager::InitializeCallback()
2918 {
2919 if (IsRegister()) {
2920 return;
2921 }
2922
2923 auto pipelineContext = GetPipelineContext().Upgrade();
2924 CHECK_NULL_VOID(pipelineContext);
2925 windowId_ = pipelineContext->GetWindowId();
2926
2927 auto client = AccessibilitySystemAbilityClient::GetInstance();
2928 CHECK_NULL_VOID(client);
2929 bool isEnabled = false;
2930 client->IsEnabled(isEnabled);
2931 client->IsScreenReaderEnabled(isScreenReaderEnabled_);
2932 AceApplicationInfo::GetInstance().SetAccessibilityEnabled(isEnabled);
2933
2934 auto container = Platform::AceContainer::GetContainer(pipelineContext->GetInstanceId());
2935 if (container != nullptr && container->IsDynamicRender()) {
2936 RegisterDynamicRenderGetParentRectHandler();
2937 return;
2938 }
2939
2940 if (pipelineContext->IsFormRender() || pipelineContext->IsJsCard() || pipelineContext->IsJsPlugin()) {
2941 return;
2942 }
2943
2944 if (container != nullptr && container->IsUIExtensionWindow()) {
2945 pipelineContext->AddUIExtensionCallbackEvent(OHOS::Ace::NG::UIExtCallbackEventId::ON_UEA_ACCESSIBILITY_READY);
2946 RegisterUIExtBusinessConsumeCallback();
2947 RegisterGetParentRectHandler();
2948 return;
2949 }
2950
2951 SubscribeStateObserver(AccessibilityStateEventType::EVENT_ACCESSIBILITY_STATE_CHANGED);
2952 SubscribeStateObserver(AccessibilityStateEventType::EVENT_SCREEN_READER_STATE_CHANGED);
2953 if (isEnabled) {
2954 RegisterInteractionOperation(windowId_);
2955 }
2956 }
2957
RegisterGetParentRectHandler()2958 void JsAccessibilityManager::RegisterGetParentRectHandler()
2959 {
2960 auto accessibilityGetParentRect = [weak = WeakClaim(this)](AccessibilityParentRectInfo& parentRectInfo) {
2961 auto jsAccessibilityManager = weak.Upgrade();
2962 CHECK_NULL_VOID(jsAccessibilityManager);
2963 auto uecRectInfo = jsAccessibilityManager->GetUECAccessibilityParentRectInfo();
2964 if (uecRectInfo.isChanged) {
2965 parentRectInfo.left = uecRectInfo.left;
2966 parentRectInfo.top = uecRectInfo.top;
2967 parentRectInfo.scaleX = uecRectInfo.scaleX;
2968 parentRectInfo.scaleY = uecRectInfo.scaleY;
2969 parentRectInfo.rotateTransform = uecRectInfo.rotateTransform;
2970 } else {
2971 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(jsAccessibilityManager->context_.Upgrade());
2972 CHECK_NULL_VOID(ngPipeline);
2973 parentRectInfo.left = jsAccessibilityManager->GetWindowLeft(ngPipeline->GetWindowId());
2974 parentRectInfo.top = jsAccessibilityManager->GetWindowTop(ngPipeline->GetWindowId());
2975 auto container = Container::CurrentSafely();
2976 if (container) {
2977 auto windowScale = container->GetWindowScale();
2978 parentRectInfo.scaleX = windowScale;
2979 parentRectInfo.scaleY = windowScale;
2980 }
2981 }
2982 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY,
2983 "Get host rect [scaleX:%{public}f, scaleY:%{public}f].", parentRectInfo.scaleX, parentRectInfo.scaleY);
2984 };
2985 SetAccessibilityGetParentRectHandler(accessibilityGetParentRect);
2986 }
2987
RegisterUIExtBusinessConsumeCallback()2988 void JsAccessibilityManager::RegisterUIExtBusinessConsumeCallback()
2989 {
2990 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context_.Upgrade());
2991 CHECK_NULL_VOID(ngPipeline);
2992 auto uiExtManager = ngPipeline->GetUIExtensionManager();
2993 CHECK_NULL_VOID(uiExtManager);
2994 auto updateAccessibilityParentRectCallback = [weak = WeakClaim(this)](const AAFwk::Want& data) -> int32_t {
2995 auto jsAccessibilityManager = weak.Upgrade();
2996 CHECK_NULL_RETURN(jsAccessibilityManager, -1);
2997 AccessibilityParentRectInfo info;
2998 info.left = data.GetIntParam("left", 0);
2999 info.top = data.GetIntParam("top", 0);
3000 info.scaleX = data.GetFloatParam("scaleX", 1.0f);
3001 info.scaleY = data.GetFloatParam("scaleY", 1.0f);
3002 RotateTransform rotateTransform(data.GetIntParam("rotateDegree", 0), data.GetIntParam("centerX", 0),
3003 data.GetIntParam("centerY", 0), data.GetIntParam("innerCenterX", 0),
3004 data.GetIntParam("innerCenterY", 0));
3005 info.rotateTransform = rotateTransform;
3006 info.isChanged = true;
3007 jsAccessibilityManager->UpdateUECAccessibilityParentRectInfo(info);
3008 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY,
3009 "Update UIExt Accessiblity [scaleX:%{public}f, scaleY:%{public}f].", info.scaleX, info.scaleY);
3010 // go on transfer info to next uiextension
3011 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(jsAccessibilityManager->context_.Upgrade());
3012 CHECK_NULL_RETURN(ngPipeline, -1);
3013 auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
3014 CHECK_NULL_RETURN(uiExtensionManager, -1);
3015 uiExtensionManager->TransferAccessibilityRectInfo();
3016 return 0;
3017 };
3018 uiExtManager->RegisterBusinessDataConsumeCallback(
3019 Ace::NG::UIContentBusinessCode::TRANSFORM_PARAM, updateAccessibilityParentRectCallback);
3020 }
3021
GetUECAccessibilityParentRectInfo() const3022 AccessibilityParentRectInfo JsAccessibilityManager::GetUECAccessibilityParentRectInfo() const
3023 {
3024 return uecRectInfo_;
3025 }
3026
UpdateUECAccessibilityParentRectInfo(const AccessibilityParentRectInfo & info)3027 void JsAccessibilityManager::UpdateUECAccessibilityParentRectInfo(const AccessibilityParentRectInfo& info)
3028 {
3029 uecRectInfo_ = info;
3030 }
3031
RegisterDynamicRenderGetParentRectHandler()3032 void JsAccessibilityManager::RegisterDynamicRenderGetParentRectHandler()
3033 {
3034 auto accessibilityGetParentRect = [weak = WeakClaim(this)](AccessibilityParentRectInfo& parentRectInfo) {
3035 auto jsAccessibilityManager = weak.Upgrade();
3036 CHECK_NULL_VOID(jsAccessibilityManager);
3037 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(jsAccessibilityManager->context_.Upgrade());
3038 CHECK_NULL_VOID(ngPipeline);
3039 auto container = Platform::AceContainer::GetContainer(ngPipeline->GetInstanceId());
3040 CHECK_NULL_VOID(container);
3041 auto containerHandler = container->GetContainerHandler().Upgrade();
3042 CHECK_NULL_VOID(containerHandler);
3043
3044 HandlerData data = {
3045 .actionCode = static_cast<int32_t>(NG::DynamicContainerHandleAction::ACCESSIBILITY_GET_RECT) };
3046 HandlerReply reply;
3047
3048 containerHandler->SendDataToHost(data, reply);
3049
3050 parentRectInfo.left = reply.GetParam<int32_t>("left", 0);
3051 parentRectInfo.top = reply.GetParam<int32_t>("top", 0);
3052 parentRectInfo.scaleX = reply.GetParam<float>("scaleX", 1.0f);
3053 parentRectInfo.scaleY = reply.GetParam<float>("scaleY", 1.0f);
3054 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY,
3055 "Get DC host rect [left:%{public}d, top:%{public}d, scaleX:%{public}f, scaleY:%{public}f].",
3056 parentRectInfo.left, parentRectInfo.top, parentRectInfo.scaleX, parentRectInfo.scaleY);
3057 };
3058 SetAccessibilityGetParentRectHandler(accessibilityGetParentRect);
3059 }
3060
3061
3062 namespace {
3063 const char FULL_SILENT[] = "FULL_SILENT";
3064
IsPageEvent(const Accessibility::EventType & eventType)3065 bool IsPageEvent(const Accessibility::EventType& eventType)
3066 {
3067 return eventType && (eventType == Accessibility::EventType::TYPE_PAGE_STATE_UPDATE
3068 || eventType == Accessibility::EventType::TYPE_PAGE_CONTENT_UPDATE
3069 || eventType == Accessibility::EventType::TYPE_PAGE_OPEN
3070 || eventType == Accessibility::EventType::TYPE_PAGE_CLOSE);
3071 }
3072
IsRootOrPageComponent(const std::string & componentType)3073 bool IsRootOrPageComponent(const std::string& componentType)
3074 {
3075 return !componentType.empty() && (componentType == V2::ROOT_ETS_TAG || componentType == V2::PAGE_ETS_TAG);
3076 }
3077
CheckSendAccessibilityEventByPageMode(const std::string & pageMode,const std::string & componentType,const int32_t pageId)3078 bool CheckSendAccessibilityEventByPageMode(
3079 const std::string& pageMode, const std::string& componentType, const int32_t pageId)
3080 {
3081 if (pageMode == FULL_SILENT) {
3082 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY,
3083 "current pageMode:%{public}s, drop page event", pageMode.c_str());
3084 return false;
3085 }
3086 if (IsRootOrPageComponent(componentType) && pageId <= 1) {
3087 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY,
3088 "current pageMode:%{public}s componentType:%{public}s pageId:%{public}d, drop page event",
3089 pageMode.c_str(), componentType.c_str(), pageId);
3090 return false;
3091 }
3092 return true;
3093 }
3094
CheckExtensionComponentReadyByPageId(const int32_t pageId,const std::vector<std::pair<WeakPtr<NG::FrameNode>,bool>> & nodeVec)3095 bool CheckExtensionComponentReadyByPageId(
3096 const int32_t pageId, const std::vector<std::pair<WeakPtr<NG::FrameNode>, bool>>& nodeVec)
3097 {
3098 for (const auto& [node, status] : nodeVec) {
3099 auto frameNode = node.Upgrade();
3100 if (frameNode && ((frameNode->GetPageId() == pageId || pageId == -1) && !status)) {
3101 return false;
3102 }
3103 }
3104 return true;
3105 }
3106
IsDelNode(const WeakPtr<NG::FrameNode> & node)3107 bool IsDelNode(const WeakPtr<NG::FrameNode>& node)
3108 {
3109 auto frameNode = node.Upgrade();
3110 CHECK_NULL_RETURN(frameNode, true);
3111 auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
3112 CHECK_NULL_RETURN(accessibilityProperty, true);
3113 return !accessibilityProperty->HasAccessibilitySamePage();
3114 }
3115
UpdateExtensionComponentStatusVec(std::vector<std::pair<WeakPtr<NG::FrameNode>,bool>> & nodeVec)3116 void UpdateExtensionComponentStatusVec(std::vector<std::pair<WeakPtr<NG::FrameNode>, bool>>& nodeVec)
3117 {
3118 for (auto it = nodeVec.begin(); it != nodeVec.end();) {
3119 if (IsDelNode(it->first)) {
3120 it = nodeVec.erase(it);
3121 } else {
3122 ++it;
3123 }
3124 }
3125 }
3126
UpdatePageId(const RefPtr<PipelineBase> & context,int32_t & pageId)3127 void UpdatePageId(const RefPtr<PipelineBase>& context, int32_t& pageId)
3128 {
3129 if (pageId != -1) {
3130 return;
3131 }
3132 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
3133 CHECK_NULL_VOID(ngPipeline);
3134 auto stageManager = ngPipeline->GetStageManager();
3135 CHECK_NULL_VOID(stageManager);
3136 auto node = stageManager->GetLastPage();
3137 CHECK_NULL_VOID(node);
3138 pageId = node->GetPageId();
3139 }
3140
ClearDefaultFocusList(std::list<WeakPtr<NG::FrameNode>> & nodeList)3141 void ClearDefaultFocusList(std::list<WeakPtr<NG::FrameNode>>& nodeList)
3142 {
3143 for (auto it = nodeList.begin(); it != nodeList.end();) {
3144 auto node = it->Upgrade();
3145 if (!node) {
3146 it = nodeList.erase(it);
3147 } else {
3148 ++it;
3149 }
3150 }
3151 }
3152
GetEventTypeByAccessibilityEvent(const AccessibilityEvent & accessibilityEvent)3153 Accessibility::EventType GetEventTypeByAccessibilityEvent(const AccessibilityEvent& accessibilityEvent)
3154 {
3155 Accessibility::EventType type = Accessibility::EventType::TYPE_VIEW_INVALID;
3156 if (accessibilityEvent.type != AccessibilityEventType::UNKNOWN) {
3157 type = ConvertAceEventType(accessibilityEvent.type);
3158 } else {
3159 type = ConvertStrToEventType(accessibilityEvent.eventType);
3160 }
3161 return type;
3162 }
3163 }
3164
IsSendAccessibilityEvent(const AccessibilityEvent & accessibilityEvent)3165 bool JsAccessibilityManager::IsSendAccessibilityEvent(const AccessibilityEvent& accessibilityEvent)
3166 {
3167 if (!IsPageEvent(GetEventTypeByAccessibilityEvent(accessibilityEvent))) {
3168 return true;
3169 }
3170 std::string componentType;
3171 int32_t pageId = -1;
3172 auto pipelineContext = GetPipelineContext().Upgrade();
3173 if (pipelineContext) {
3174 GetComponentTypeAndPageIdByNodeId(accessibilityEvent.nodeId, pipelineContext, componentType, pageId);
3175 auto container = Platform::AceContainer::GetContainer(pipelineContext->GetInstanceId());
3176 if (container != nullptr && container->IsUIExtensionWindow()) {
3177 return IsSendAccessibilityEventForUEA(accessibilityEvent, componentType, pageId);
3178 }
3179 UpdatePageId(pipelineContext, pageId);
3180 }
3181 return IsSendAccessibilityEventForHost(accessibilityEvent, componentType, pageId);
3182 }
3183
IsSendAccessibilityEventForUEA(const AccessibilityEvent & accessibilityEvent,const std::string & componentType,const int32_t pageId)3184 bool JsAccessibilityManager::IsSendAccessibilityEventForUEA(
3185 const AccessibilityEvent& accessibilityEvent, const std::string& componentType, const int32_t pageId)
3186 {
3187 if (pageMode_.empty()) {
3188 if (treeId_ == -1) {
3189 cacheEventVec_.push_back(accessibilityEvent);
3190 return false;
3191 }
3192 return true;
3193 }
3194 if (!CheckSendAccessibilityEventByPageMode(pageMode_, componentType, pageId)) {
3195 return false;
3196 }
3197 if (treeId_ == -1) {
3198 cacheEventVec_.push_back(accessibilityEvent);
3199 return false;
3200 }
3201 return true;
3202 }
3203
IsSendAccessibilityEventForHost(const AccessibilityEvent & accessibilityEvent,const std::string & componentType,const int32_t pageId)3204 bool JsAccessibilityManager::IsSendAccessibilityEventForHost(
3205 const AccessibilityEvent& accessibilityEvent, const std::string& componentType, const int32_t pageId)
3206 {
3207 UpdateExtensionComponentStatusVec(extensionComponentStatusVec_);
3208 ClearDefaultFocusList(defaultFocusList_);
3209
3210 if (extensionComponentStatusVec_.empty() || defaultFocusList_.empty()) {
3211 return true;
3212 }
3213
3214 for (const auto& [node, status] : extensionComponentStatusVec_) {
3215 auto frameNode = node.Upgrade();
3216 CHECK_NULL_CONTINUE(frameNode);
3217 auto nodePageId = frameNode->GetPageId();
3218 if (!pageIdEventMap_.count(nodePageId)) {
3219 pageIdEventMap_[nodePageId] = std::nullopt;
3220 }
3221 }
3222 if (!CheckExtensionComponentReadyByPageId(pageId, extensionComponentStatusVec_)) {
3223 if (pageIdEventMap_.count(pageId) && pageIdEventMap_[pageId].has_value()) {
3224 auto event = pageIdEventMap_[pageId].value();
3225 auto eventType = GetEventTypeByAccessibilityEvent(event);
3226 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY,
3227 "override the event, componentType:%{public}s event:%{public}d nodeId:%{public}" PRId64,
3228 event.componentType.c_str(), eventType, event.nodeId);
3229 }
3230 AccessibilityEvent event = accessibilityEvent;
3231 event.componentType = componentType;
3232 pageIdEventMap_[pageId] = event;
3233 return false;
3234 }
3235 return true;
3236 }
3237
GetComponentTypeAndPageIdByNodeId(const int64_t nodeId,const RefPtr<PipelineBase> & context,std::string & componentType,int32_t & pageId)3238 void JsAccessibilityManager::GetComponentTypeAndPageIdByNodeId(const int64_t nodeId,
3239 const RefPtr<PipelineBase>& context, std::string& componentType, int32_t& pageId)
3240 {
3241 CHECK_NULL_VOID(context);
3242 if (AceType::InstanceOf<NG::PipelineContext>(context)) {
3243 RefPtr<NG::FrameNode> node;
3244 FindPipelineByElementId(nodeId, node);
3245 CHECK_NULL_VOID(node);
3246 componentType = node->GetTag();
3247 pageId = node->GetPageId();
3248 } else {
3249 auto node = GetAccessibilityNodeFromPage(nodeId);
3250 CHECK_NULL_VOID(node);
3251 componentType = node->GetTag();
3252 pageId = node->GetPageId();
3253 }
3254 }
3255
SendCacheAccessibilityEvent(int32_t instanceId)3256 void JsAccessibilityManager::SendCacheAccessibilityEvent(int32_t instanceId)
3257 {
3258 auto container = Platform::AceContainer::GetContainer(instanceId);
3259 if (container == nullptr || !container->IsUIExtensionWindow()) {
3260 return;
3261 }
3262
3263 if (!cacheEventVec_.empty()) {
3264 for (const auto& event : cacheEventVec_) {
3265 SendAccessibilityAsyncEventInner(event);
3266 }
3267 cacheEventVec_.clear();
3268 }
3269 }
3270
SendCacheAccessibilityEventForHost(const int32_t pageId)3271 void JsAccessibilityManager::SendCacheAccessibilityEventForHost(const int32_t pageId)
3272 {
3273 if (!CheckExtensionComponentReadyByPageId(pageId, extensionComponentStatusVec_)) {
3274 return;
3275 }
3276
3277 if (pageIdEventMap_.count(pageId) && pageIdEventMap_[pageId].has_value()) {
3278 auto event = pageIdEventMap_[pageId].value();
3279 SendAccessibilityAsyncEventInner(event);
3280 pageIdEventMap_[pageId] = std::nullopt;
3281 }
3282 }
3283
AddFrameNodeToUecStatusVec(const RefPtr<NG::FrameNode> & node)3284 void JsAccessibilityManager::AddFrameNodeToUecStatusVec(const RefPtr<NG::FrameNode>& node)
3285 {
3286 extensionComponentStatusVec_.emplace_back(WeakPtr(node), false);
3287 }
3288
AddFrameNodeToDefaultFocusList(const RefPtr<NG::FrameNode> & node,bool isFocus)3289 void JsAccessibilityManager::AddFrameNodeToDefaultFocusList(const RefPtr<NG::FrameNode>& node, bool isFocus)
3290 {
3291 if (isFocus) {
3292 AddDefaultFocusNode(node);
3293 return;
3294 }
3295 EraseDefaultFocusNode(node);
3296 }
3297
AddDefaultFocusNode(const RefPtr<NG::FrameNode> & defaultFocusNode)3298 void JsAccessibilityManager::AddDefaultFocusNode(const RefPtr<NG::FrameNode>& defaultFocusNode)
3299 {
3300 CHECK_NULL_VOID(defaultFocusNode);
3301 auto nodeId = defaultFocusNode->GetId();
3302 for (const auto& node : defaultFocusList_) {
3303 auto frameNode = node.Upgrade();
3304 if (frameNode && (frameNode->GetId() == nodeId)) {
3305 return;
3306 }
3307 }
3308 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY,
3309 "add frameNode to defaultFocusList, nodeId: %{public}d.", nodeId);
3310 defaultFocusList_.push_back(WeakPtr(defaultFocusNode));
3311 }
3312
EraseDefaultFocusNode(const RefPtr<NG::FrameNode> & defaultFocusNode)3313 void JsAccessibilityManager::EraseDefaultFocusNode(const RefPtr<NG::FrameNode>& defaultFocusNode)
3314 {
3315 CHECK_NULL_VOID(defaultFocusNode);
3316 auto nodeId = defaultFocusNode->GetId();
3317 for (auto it = defaultFocusList_.begin(); it != defaultFocusList_.end();) {
3318 auto node = it->Upgrade();
3319 if (node && (node->GetId() == nodeId)) {
3320 it = defaultFocusList_.erase(it);
3321 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY,
3322 "erase frameNode from defaultFocusList, nodeId: %{public}d.", nodeId);
3323 return;
3324 } else {
3325 ++it;
3326 }
3327 }
3328 }
3329
RegisterUIExtGetPageModeCallback(RefPtr<NG::UIExtensionManager> & uiExtManager)3330 void JsAccessibilityManager::RegisterUIExtGetPageModeCallback(RefPtr<NG::UIExtensionManager>& uiExtManager)
3331 {
3332 CHECK_NULL_VOID(uiExtManager);
3333 auto callback = [weak = WeakClaim(this)](const AAFwk::Want& data) -> int32_t {
3334 if (!data.HasParameter("pageMode")) {
3335 return -1;
3336 }
3337 auto accessibilityManager = weak.Upgrade();
3338 CHECK_NULL_RETURN(accessibilityManager, -1);
3339
3340 auto pageMode = data.GetStringParam("pageMode");
3341 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY,
3342 "host send pageMode to uea, pageMode: %{public}s.", pageMode.c_str());
3343 accessibilityManager->UpdatePageMode(pageMode);
3344 return 0;
3345 };
3346 uiExtManager->RegisterBusinessDataConsumeCallback(NG::UIContentBusinessCode::SEND_PAGE_MODE_TO_UEA, callback);
3347 }
3348
UpdateFrameNodeState(int32_t nodeId)3349 void JsAccessibilityManager::UpdateFrameNodeState(int32_t nodeId)
3350 {
3351 for (auto& [node, status] : extensionComponentStatusVec_) {
3352 auto frameNode = node.Upgrade();
3353 if (frameNode && (frameNode->GetId() == nodeId)) {
3354 status = true;
3355 SendCacheAccessibilityEventForHost(frameNode->GetPageId());
3356 return;
3357 }
3358 }
3359 }
3360
SendAccessibilitySyncEvent(const AccessibilityEvent & accessibilityEvent,AccessibilityEventInfo eventInfo)3361 bool JsAccessibilityManager::SendAccessibilitySyncEvent(
3362 const AccessibilityEvent& accessibilityEvent, AccessibilityEventInfo eventInfo)
3363 {
3364 if (!IsRegister()) {
3365 return false;
3366 }
3367 auto client = AccessibilitySystemAbilityClient::GetInstance();
3368 CHECK_NULL_RETURN(client, false);
3369 bool isEnabled = false;
3370 client->IsEnabled(isEnabled);
3371 if (!isEnabled) {
3372 return false;
3373 }
3374 AccessibilityElementInfo info = eventInfo.GetElementInfo();
3375 int64_t elementId = eventInfo.GetAccessibilityId();
3376 if (info.GetBelongTreeId() > 0) {
3377 AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(info.GetBelongTreeId(), elementId);
3378 }
3379 eventInfo.SetSource(elementId);
3380 UpdateElementInfoTreeId(info);
3381 eventInfo.SetElementInfo(info);
3382 eventInfo.SetPageId(info.GetPageId());
3383 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY,
3384 "send accessibility componentType:%{public}s event:%{public}d accessibilityId:%{public}" PRId64,
3385 eventInfo.GetComponentType().c_str(), eventInfo.GetEventType(), eventInfo.GetAccessibilityId());
3386 return client->SendEvent(eventInfo);
3387 }
3388
TransferAccessibilityAsyncEvent(const AccessibilityEventInfo & eventInfo,int64_t uiExtensionOffset)3389 bool JsAccessibilityManager::TransferAccessibilityAsyncEvent(
3390 const AccessibilityEventInfo& eventInfo, int64_t uiExtensionOffset)
3391 {
3392 #ifdef WINDOW_SCENE_SUPPORTED
3393 auto client = AccessibilitySystemAbilityClient::GetInstance();
3394 CHECK_NULL_RETURN(client, false);
3395 bool isEnabled = false;
3396 client->IsEnabled(isEnabled);
3397 if (!isEnabled) {
3398 return false;
3399 }
3400
3401 auto pipeline = context_.Upgrade();
3402 CHECK_NULL_RETURN(pipeline, false);
3403 RefPtr<NG::PipelineContext> ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipeline);
3404 CHECK_NULL_RETURN(ngPipeline, false);
3405 auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
3406 CHECK_NULL_RETURN(uiExtensionManager, false);
3407 auto container = Container::GetContainer(ngPipeline->GetInstanceId());
3408 bool isDynamicRender = container && container->IsDynamicRender() &&
3409 container->GetUIContentType() == UIContentType::ISOLATED_COMPONENT;
3410 if (!IsRegister() && !isDynamicRender) {
3411 return false;
3412 }
3413 AccessibilityEventInfo eventInfoNew = eventInfo;
3414 if (isDynamicRender) {
3415 auto focusedContainer = Container::GetFoucsed();
3416 if (focusedContainer) {
3417 eventInfoNew.SetWindowId(focusedContainer->GetWindowId());
3418 }
3419 }
3420 eventInfoNew.SetSource(uiExtensionOffset * GetUiextensionId() + eventInfo.GetViewId());
3421 AccessibilityElementInfo elementInfo;
3422 FillElementInfo(eventInfoNew.GetAccessibilityId(), elementInfo, pipeline, Claim(this),
3423 FillEventInfoParam { eventInfoNew.GetAccessibilityId(), -1, eventInfoNew.GetWindowId() });
3424 eventInfoNew.SetElementInfo(elementInfo);
3425 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "send accessibility event:%{public}d accessibilityId:%{public}" PRId64,
3426 eventInfoNew.GetEventType(), eventInfoNew.GetAccessibilityId());
3427 return client->SendEvent(eventInfoNew);
3428 #endif
3429 return false;
3430 }
3431
SendExtensionAccessibilityEvent(const AccessibilityEventInfo & eventInfo,int64_t uiExtensionOffset)3432 void JsAccessibilityManager::SendExtensionAccessibilityEvent(
3433 const AccessibilityEventInfo& eventInfo, int64_t uiExtensionOffset)
3434 {
3435 TransferAccessibilityAsyncEvent(eventInfo, uiExtensionOffset);
3436 }
3437
FillEventInfoWithNode(const RefPtr<NG::FrameNode> & node,AccessibilityEventInfo & eventInfo,const RefPtr<NG::PipelineContext> & context,int64_t elementId)3438 void JsAccessibilityManager::FillEventInfoWithNode(
3439 const RefPtr<NG::FrameNode>& node,
3440 AccessibilityEventInfo& eventInfo,
3441 const RefPtr<NG::PipelineContext>& context,
3442 int64_t elementId)
3443 {
3444 CHECK_NULL_VOID(node);
3445 eventInfo.SetComponentType(node->GetTag());
3446 eventInfo.SetPageId(node->GetPageId());
3447 auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
3448 CHECK_NULL_VOID(accessibilityProperty);
3449 eventInfo.SetItemCounts(accessibilityProperty->GetCollectionItemCounts());
3450 eventInfo.SetBeginIndex(accessibilityProperty->GetBeginIndex());
3451 eventInfo.SetEndIndex(accessibilityProperty->GetEndIndex());
3452 AccessibilityElementInfo elementInfo;
3453
3454 CommonProperty commonProperty;
3455 auto mainContext = context_.Upgrade();
3456 CHECK_NULL_VOID(mainContext);
3457 GenerateCommonProperty(context, commonProperty, mainContext, node);
3458 UpdateAccessibilityElementInfo(node, commonProperty, elementInfo, context);
3459 elementInfo.SetWindowId(eventInfo.GetWindowId());
3460 eventInfo.AddContent(elementInfo.GetContent());
3461 eventInfo.SetElementInfo(elementInfo);
3462 }
3463
GetDelayTimeBeforeSendEvent(const AccessibilityEvent & accessibilityEvent,const RefPtr<AceType> & node)3464 int64_t JsAccessibilityManager::GetDelayTimeBeforeSendEvent(
3465 const AccessibilityEvent& accessibilityEvent,
3466 const RefPtr<AceType>& node)
3467 {
3468 if (accessibilityEvent.type != AccessibilityEventType::CLICK) {
3469 return 0;
3470 }
3471
3472 auto frameNode = AceType::DynamicCast<NG::FrameNode>(node);
3473 if (frameNode) {
3474 if (IsUserCheckedOrSelected(frameNode)) {
3475 return DELAY_SEND_EVENT_MILLISECOND;
3476 }
3477 } else {
3478 auto context = GetPipelineContext().Upgrade();
3479 if (!AceType::InstanceOf<NG::PipelineContext>(context)) {
3480 return 0;
3481 }
3482 RefPtr<NG::FrameNode> findeNode;
3483 auto ngPipeline = FindPipelineByElementId(accessibilityEvent.nodeId, findeNode);
3484 if ((findeNode) && IsUserCheckedOrSelected(findeNode)) {
3485 return DELAY_SEND_EVENT_MILLISECOND;
3486 }
3487 }
3488
3489 return 0;
3490 }
3491
IsEventIgnoredByWorkMode(const AccessibilityEvent & accessibilityEvent)3492 bool JsAccessibilityManager::IsEventIgnoredByWorkMode(const AccessibilityEvent& accessibilityEvent)
3493 {
3494 auto accessibilityWorkMode = GenerateAccessibilityWorkMode();
3495 if (!accessibilityWorkMode.isTouchExplorationEnabled) {
3496 switch (accessibilityEvent.type) {
3497 case AccessibilityEventType::ELEMENT_INFO_CHANGE:
3498 case AccessibilityEventType::TEXT_CHANGE:
3499 case AccessibilityEventType::FOCUS:
3500 return true;
3501 default:
3502 return false;
3503 }
3504 }
3505 return false;
3506 }
3507
SendEventToAccessibilityWithNode(const AccessibilityEvent & accessibilityEvent,const RefPtr<AceType> & node,const RefPtr<PipelineBase> & context)3508 void JsAccessibilityManager::SendEventToAccessibilityWithNode(
3509 const AccessibilityEvent& accessibilityEvent, const RefPtr<AceType>& node, const RefPtr<PipelineBase>& context)
3510 {
3511 if (IsEventIgnoredByWorkMode(accessibilityEvent) || !IsSendAccessibilityEvent(accessibilityEvent)) {
3512 return;
3513 }
3514 auto delayTime = GetDelayTimeBeforeSendEvent(accessibilityEvent, node);
3515 if ((delayTime > 0) && context) {
3516 context->GetTaskExecutor()->PostDelayedTask(
3517 [weak = WeakClaim(this), accessibilityEvent, node, context] {
3518 auto jsAccessibilityManager = weak.Upgrade();
3519 CHECK_NULL_VOID(jsAccessibilityManager);
3520 jsAccessibilityManager->SendEventToAccessibilityWithNodeInner(accessibilityEvent, node, context);
3521 },
3522 TaskExecutor::TaskType::UI, delayTime, "ArkUIAccessibilitySendSyncEventWithDelay");
3523 return;
3524 }
3525 SendEventToAccessibilityWithNodeInner(accessibilityEvent, node, context);
3526 }
3527
SendEventToAccessibilityWithNodeInner(const AccessibilityEvent & accessibilityEvent,const RefPtr<AceType> & node,const RefPtr<PipelineBase> & context)3528 void JsAccessibilityManager::SendEventToAccessibilityWithNodeInner(
3529 const AccessibilityEvent& accessibilityEvent, const RefPtr<AceType>& node, const RefPtr<PipelineBase>& context)
3530 {
3531 ACE_SCOPED_TRACE("SendAccessibilityAsyncEvent");
3532 CHECK_NULL_VOID(node);
3533 CHECK_NULL_VOID(context);
3534 int32_t windowId = static_cast<int32_t>(context->GetRealHostWindowId());
3535 if (windowId == 0) {
3536 return;
3537 }
3538 if (!AceType::InstanceOf<NG::FrameNode>(node)) {
3539 return;
3540 }
3541 auto frameNode = AceType::DynamicCast<NG::FrameNode>(node);
3542 CHECK_NULL_VOID(frameNode);
3543 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
3544 CHECK_NULL_VOID(ngPipeline);
3545
3546 if ((!frameNode->IsActive()) || frameNode->CheckAccessibilityLevelNo()) {
3547 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "node: %{public}" PRId64 ", is not active or level is no",
3548 frameNode->GetAccessibilityId());
3549 return;
3550 }
3551
3552 AccessibilityEventInfo eventInfo;
3553
3554 if (accessibilityEvent.type != AccessibilityEventType::PAGE_CHANGE || accessibilityEvent.windowId == 0) {
3555 eventInfo.SetWindowId(windowId);
3556 } else {
3557 eventInfo.SetWindowId(accessibilityEvent.windowId);
3558 }
3559 FillEventInfoWithNode(frameNode, eventInfo, ngPipeline, accessibilityEvent.nodeId);
3560 if ((ngPipeline != nullptr) && (ngPipeline->IsFormRender())) {
3561 eventInfo.SetWindowId(static_cast<int32_t>(GetWindowId()));
3562 }
3563 GenerateAccessibilityEventInfo(accessibilityEvent, eventInfo);
3564
3565 auto container = Container::GetContainer(context->GetInstanceId());
3566 if (container && container->IsDynamicRender() &&
3567 container->GetUIContentType() == UIContentType::ISOLATED_COMPONENT) {
3568 SendExtensionAccessibilityEvent(eventInfo, NG::UI_EXTENSION_UNKNOW_ID);
3569 } else {
3570 context->GetTaskExecutor()->PostTask(
3571 [weak = WeakClaim(this), accessibilityEvent, eventInfo] {
3572 auto jsAccessibilityManager = weak.Upgrade();
3573 CHECK_NULL_VOID(jsAccessibilityManager);
3574 jsAccessibilityManager->SendAccessibilitySyncEvent(accessibilityEvent, eventInfo);
3575 },
3576 TaskExecutor::TaskType::BACKGROUND, "ArkUIAccessibilitySendSyncEvent");
3577 }
3578 }
3579
GetRealEventWindowId(const AccessibilityEvent & accessibilityEvent,const RefPtr<NG::PipelineContext> & ngPipeline,uint32_t & windowId)3580 void GetRealEventWindowId(
3581 const AccessibilityEvent& accessibilityEvent, const RefPtr<NG::PipelineContext>& ngPipeline, uint32_t& windowId)
3582 {
3583 if ((accessibilityEvent.type == AccessibilityEventType::PAGE_CHANGE && accessibilityEvent.windowId != 0) ||
3584 accessibilityEvent.windowChangeTypes == WINDOW_UPDATE_ADDED) {
3585 windowId = accessibilityEvent.windowId;
3586 return;
3587 }
3588 if ((ngPipeline != nullptr) && (ngPipeline->IsFormRender())) {
3589 return;
3590 }
3591 windowId = ngPipeline->GetRealHostWindowId();
3592 }
3593
SendAccessibilityAsyncEvent(const AccessibilityEvent & accessibilityEvent)3594 void JsAccessibilityManager::SendAccessibilityAsyncEvent(const AccessibilityEvent& accessibilityEvent)
3595 {
3596 if (IsEventIgnoredByWorkMode(accessibilityEvent) || !IsSendAccessibilityEvent(accessibilityEvent)) {
3597 return;
3598 }
3599 auto delayTime = GetDelayTimeBeforeSendEvent(accessibilityEvent, nullptr);
3600 if (delayTime > 0) {
3601 auto context = GetPipelineContext().Upgrade();
3602 if (context) {
3603 context->GetTaskExecutor()->PostDelayedTask(
3604 [weak = WeakClaim(this), accessibilityEvent] {
3605 auto jsAccessibilityManager = weak.Upgrade();
3606 CHECK_NULL_VOID(jsAccessibilityManager);
3607 jsAccessibilityManager->SendAccessibilityAsyncEventInner(accessibilityEvent);
3608 },
3609 TaskExecutor::TaskType::UI, delayTime, "ArkUIAccessibilitySendSyncEventWithDelay");
3610 }
3611 return;
3612 }
3613 SendAccessibilityAsyncEventInner(accessibilityEvent);
3614 }
3615
SendAccessibilityAsyncEventInner(const AccessibilityEvent & accessibilityEvent)3616 void JsAccessibilityManager::SendAccessibilityAsyncEventInner(const AccessibilityEvent& accessibilityEvent)
3617 {
3618 ACE_ACCESS_SCOPED_TRACE("SendAccessibilityAsyncEvent");
3619 auto context = GetPipelineContext().Upgrade();
3620 CHECK_NULL_VOID(context);
3621 int32_t windowId = static_cast<int32_t>(context->GetRealHostWindowId());
3622 if (windowId == 0) {
3623 return;
3624 }
3625 RefPtr<NG::PipelineContext> ngPipeline;
3626 AccessibilityEventInfo eventInfo;
3627 uint32_t realWindowId = GetWindowId();
3628 if (AceType::InstanceOf<NG::PipelineContext>(context)) {
3629 RefPtr<NG::FrameNode> node;
3630 ngPipeline = FindPipelineByElementId(accessibilityEvent.nodeId, node);
3631 CHECK_NULL_VOID(ngPipeline);
3632 CHECK_NULL_VOID(node);
3633 GetRealEventWindowId(accessibilityEvent, ngPipeline, realWindowId);
3634 FillEventInfo(node, eventInfo, ngPipeline, Claim(this),
3635 FillEventInfoParam {
3636 accessibilityEvent.nodeId, accessibilityEvent.stackNodeId, realWindowId });
3637 eventInfo.SetWindowId(realWindowId);
3638 } else {
3639 ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
3640 auto node = GetAccessibilityNodeFromPage(accessibilityEvent.nodeId);
3641 CHECK_NULL_VOID(node);
3642 FillEventInfo(node, eventInfo);
3643 eventInfo.SetWindowId(windowId);
3644 }
3645 if (accessibilityEvent.type == AccessibilityEventType::PAGE_CHANGE && accessibilityEvent.windowId != 0) {
3646 eventInfo.SetWindowId(accessibilityEvent.windowId);
3647 }
3648 if ((ngPipeline != nullptr) && (ngPipeline->IsFormRender())) {
3649 eventInfo.SetWindowId(static_cast<int32_t>(GetWindowId()));
3650 }
3651
3652 GenerateAccessibilityEventInfo(accessibilityEvent, eventInfo);
3653
3654 auto container = Container::GetContainer(context->GetInstanceId());
3655 if (container && container->IsDynamicRender() &&
3656 container->GetUIContentType() == UIContentType::ISOLATED_COMPONENT) {
3657 SendExtensionAccessibilityEvent(eventInfo, NG::UI_EXTENSION_OFFSET_MAX);
3658 } else {
3659 context->GetTaskExecutor()->PostTask(
3660 [weak = WeakClaim(this), accessibilityEvent, eventInfo] {
3661 auto jsAccessibilityManager = weak.Upgrade();
3662 CHECK_NULL_VOID(jsAccessibilityManager);
3663 jsAccessibilityManager->SendAccessibilitySyncEvent(accessibilityEvent, eventInfo);
3664 },
3665 TaskExecutor::TaskType::BACKGROUND, "ArkUIAccessibilitySendSyncEvent");
3666 }
3667 }
3668
3669 #ifdef WEB_SUPPORTED
3670
SendWebAccessibilityAsyncEvent(const AccessibilityEvent & accessibilityEvent,const RefPtr<NG::WebPattern> & webPattern)3671 void JsAccessibilityManager::SendWebAccessibilityAsyncEvent(
3672 const AccessibilityEvent& accessibilityEvent, const RefPtr<NG::WebPattern>& webPattern)
3673 {
3674 ACE_ACCESS_SCOPED_TRACE("SendWebAccessibilityAsyncEvent");
3675 auto context = GetPipelineContext().Upgrade();
3676 CHECK_NULL_VOID(context);
3677 int32_t windowId = static_cast<int32_t>(context->GetRealHostWindowId());
3678 if (windowId == 0) {
3679 return;
3680 }
3681
3682 AccessibilityEventInfo eventInfo;
3683 RefPtr<NG::PipelineContext> ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context_.Upgrade());
3684 CHECK_NULL_VOID(ngPipeline);
3685 FillWebEventInfo(eventInfo, ngPipeline, Claim(this),
3686 FillEventInfoParam {
3687 accessibilityEvent.nodeId, accessibilityEvent.stackNodeId, ngPipeline->GetRealHostWindowId() },
3688 webPattern);
3689 eventInfo.SetWindowId(ngPipeline->GetRealHostWindowId());
3690
3691 if (accessibilityEvent.type == AccessibilityEventType::PAGE_CHANGE && accessibilityEvent.windowId != 0) {
3692 eventInfo.SetWindowId(accessibilityEvent.windowId);
3693 }
3694
3695 GenerateAccessibilityEventInfo(accessibilityEvent, eventInfo);
3696
3697 context->GetTaskExecutor()->PostTask(
3698 [weak = WeakClaim(this), accessibilityEvent, eventInfo] {
3699 auto jsAccessibilityManager = weak.Upgrade();
3700 CHECK_NULL_VOID(jsAccessibilityManager);
3701 jsAccessibilityManager->SendAccessibilitySyncEvent(accessibilityEvent, eventInfo);
3702 },
3703 TaskExecutor::TaskType::BACKGROUND, "ArkUIAccessibilitySendSyncEvent");
3704 }
3705 #endif
3706
UpdateNodeChildIds(const RefPtr<AccessibilityNode> & node)3707 void JsAccessibilityManager::UpdateNodeChildIds(const RefPtr<AccessibilityNode>& node)
3708 {
3709 CHECK_NULL_VOID(node);
3710 node->ActionUpdateIds();
3711 const auto& children = node->GetChildList();
3712 std::vector<int32_t> childrenVec;
3713 auto cardId = GetCardId();
3714 auto rootNodeId = GetRootNodeId();
3715
3716 // get last stack children to barrier free service.
3717 if ((node->GetNodeId() == GetRootNodeId() + ROOT_STACK_BASE) && !children.empty() && !IsDeclarative()) {
3718 auto lastChildNodeId = children.back()->GetNodeId();
3719 if (isOhosHostCard()) {
3720 childrenVec.emplace_back(ConvertToCardAccessibilityId(lastChildNodeId, cardId, rootNodeId));
3721 } else {
3722 childrenVec.emplace_back(lastChildNodeId);
3723 for (const auto& child : children) {
3724 if (child->GetNodeId() == ROOT_DECOR_BASE - 1) {
3725 childrenVec.emplace_back(child->GetNodeId());
3726 break;
3727 }
3728 }
3729 }
3730 } else {
3731 childrenVec.resize(children.size());
3732 if (isOhosHostCard()) {
3733 std::transform(children.begin(), children.end(), childrenVec.begin(),
3734 [cardId, rootNodeId](const RefPtr<AccessibilityNode>& child) {
3735 return ConvertToCardAccessibilityId(child->GetNodeId(), cardId, rootNodeId);
3736 });
3737 } else {
3738 std::transform(children.begin(), children.end(), childrenVec.begin(),
3739 [](const RefPtr<AccessibilityNode>& child) { return child->GetNodeId(); });
3740 }
3741 }
3742 node->SetChildIds(childrenVec);
3743 }
3744
ProcessParameters(ActionType op,const std::vector<std::string> & params,std::map<std::string,std::string> & paramsMap)3745 void JsAccessibilityManager::ProcessParameters(
3746 ActionType op, const std::vector<std::string>& params, std::map<std::string, std::string>& paramsMap)
3747 {
3748 if (op == ActionType::ACCESSIBILITY_ACTION_SET_TEXT) {
3749 if (params.size() == (EVENT_DUMP_ACTION_PARAM_INDEX + 1)) {
3750 paramsMap = { { ACTION_ARGU_SET_TEXT, params[EVENT_DUMP_ACTION_PARAM_INDEX] } };
3751 }
3752 }
3753
3754 if (op == ActionType::ACCESSIBILITY_ACTION_SET_SELECTION) {
3755 paramsMap[ACTION_ARGU_SELECT_TEXT_START] = "-1";
3756 paramsMap[ACTION_ARGU_SELECT_TEXT_END] = "-1";
3757 paramsMap[ACTION_ARGU_SELECT_TEXT_INFORWARD] = STRING_DIR_BACKWARD;
3758 if (params.size() > EVENT_DUMP_PARAM_LENGTH_LOWER) {
3759 paramsMap[ACTION_ARGU_SELECT_TEXT_START] = params[EVENT_DUMP_ACTION_PARAM_INDEX];
3760 }
3761 if (params.size() > EVENT_DUMP_PARAM_LENGTH_LOWER + 1) {
3762 paramsMap[ACTION_ARGU_SELECT_TEXT_END] = params[EVENT_DUMP_ACTION_PARAM_INDEX + 1];
3763 }
3764 // 2 means params number Offset
3765 if (params.size() > EVENT_DUMP_PARAM_LENGTH_LOWER + 2) {
3766 // 2 means params number Offset
3767 paramsMap[ACTION_ARGU_SELECT_TEXT_INFORWARD] = params[EVENT_DUMP_ACTION_PARAM_INDEX + 2];
3768 }
3769 }
3770
3771 if (op == ActionType::ACCESSIBILITY_ACTION_NEXT_TEXT || op == ActionType::ACCESSIBILITY_ACTION_PREVIOUS_TEXT) {
3772 if (params.size() == EVENT_DUMP_PARAM_LENGTH_UPPER) {
3773 paramsMap[ACTION_ARGU_MOVE_UNIT] = std::to_string(TextMoveUnit::STEP_CHARACTER);
3774 }
3775 paramsMap[ACTION_ARGU_MOVE_UNIT] = std::to_string(TextMoveUnit::STEP_CHARACTER);
3776 }
3777
3778 if (op == ActionType::ACCESSIBILITY_ACTION_SET_CURSOR_POSITION) {
3779 paramsMap[ACTION_ARGU_SET_OFFSET] = params[EVENT_DUMP_ACTION_PARAM_INDEX];
3780 }
3781
3782 if ((op == ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD) ||
3783 (op == ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD)) {
3784 if (params.size() > EVENT_DUMP_PARAM_LENGTH_LOWER) {
3785 paramsMap = { { ACTION_ARGU_SCROLL_STUB, params[EVENT_DUMP_ACTION_PARAM_INDEX] } };
3786 }
3787 }
3788
3789 if (op == ActionType::ACCESSIBILITY_ACTION_SPAN_CLICK) {
3790 if (params.size() > EVENT_DUMP_PARAM_LENGTH_LOWER) {
3791 paramsMap = { { ACTION_ARGU_SPAN_ID, params[EVENT_DUMP_ACTION_PARAM_INDEX] } };
3792 }
3793 }
3794 }
3795
TransferExecuteAction(int64_t elementId,const RefPtr<NG::FrameNode> & node,const std::map<std::string,std::string> & actionArguments,ActionType action,int64_t uiExtensionOffset)3796 bool TransferExecuteAction(int64_t elementId, const RefPtr<NG::FrameNode>& node,
3797 const std::map<std::string, std::string>& actionArguments,
3798 ActionType action, int64_t uiExtensionOffset)
3799 {
3800 bool isExecuted = false;
3801 if ((uiExtensionOffset + 1) > NG::UI_EXTENSION_OFFSET_MIN) {
3802 isExecuted = node->TransferExecuteAction(
3803 elementId, actionArguments, static_cast<int>(action),
3804 uiExtensionOffset / NG::UI_EXTENSION_ID_FACTOR);
3805 }
3806 return isExecuted;
3807 }
3808
GetPipelineByWindowId(uint32_t windowId)3809 RefPtr<NG::PipelineContext> JsAccessibilityManager::GetPipelineByWindowId(uint32_t windowId)
3810 {
3811 auto mainPipeline = AceType::DynamicCast<NG::PipelineContext>(context_.Upgrade());
3812 if (mainPipeline!= nullptr && mainPipeline->GetWindowId() == windowId) {
3813 return mainPipeline;
3814 }
3815 for (auto subPipelineWeak : GetSubPipelineContexts()) {
3816 auto subContextNG = AceType::DynamicCast<NG::PipelineContext>(subPipelineWeak.Upgrade());
3817 if (subContextNG!= nullptr && subContextNG->GetWindowId() == windowId) {
3818 return subContextNG;
3819 }
3820 }
3821 if (GetWindowId() == windowId) {
3822 return mainPipeline;
3823 }
3824 return nullptr;
3825 }
3826
3827 // DFX related
3828 namespace {
CheckAndGetEventTestArgument(std::vector<std::string>::const_iterator start,const std::vector<std::string> & params,DumpInfoArgument & argument)3829 bool CheckAndGetEventTestArgument(std::vector<std::string>::const_iterator start,
3830 const std::vector<std::string>& params, DumpInfoArgument& argument)
3831 {
3832 auto arg = start;
3833 argument.mode = DumpMode::EVENT_TEST;
3834 constexpr int32_t NUM_EVENT_DIMENSION = 2;
3835 if (std::distance(arg, params.end()) <= NUM_EVENT_DIMENSION) {
3836 DumpLog::GetInstance().Print(std::string("Error: --event-test is used to send event with node ") +
3837 "need elementId and eventId, e.g. '--event-test ${elementId} ${eventId}'!");
3838 return false;
3839 }
3840 ++arg;
3841 argument.nodeId = StringUtils::StringToLongInt(*arg);
3842 ++arg;
3843 argument.eventId = StringUtils::StringToInt(*arg);
3844 return true;
3845 }
3846 } // DFX related
3847
DumpTreeNG(bool useWindowId,uint32_t windowId,int64_t rootId,bool isDumpSimplify)3848 void JsAccessibilityManager::DumpTreeNG(bool useWindowId, uint32_t windowId, int64_t rootId, bool isDumpSimplify)
3849 {
3850 if (!useWindowId && rootId == -1) {
3851 // used to adapt old function
3852 DumpTree(0, 0);
3853 return;
3854 }
3855
3856 auto pipeline = GetPipelineByWindowId(windowId);
3857 if (pipeline == nullptr) {
3858 DumpLog::GetInstance().Print("Error: pipeline is not found!");
3859 return;
3860 }
3861 auto rootNode = pipeline->GetRootElement();
3862 CHECK_NULL_VOID(rootNode);
3863 CommonProperty commonProperty;
3864 auto mainPipeline = context_.Upgrade();
3865 CHECK_NULL_VOID(mainPipeline);
3866 GenerateCommonProperty(pipeline, commonProperty, mainPipeline, rootNode);
3867 auto nodeId = rootId == -1 ? rootNode->GetAccessibilityId() : rootId;
3868 DumpTreeNG(rootNode, 0, nodeId, commonProperty, isDumpSimplify);
3869 }
3870
DumpHoverTestNG(uint32_t windowId,int64_t rootId,int32_t x,int32_t y,bool verbose)3871 void JsAccessibilityManager::DumpHoverTestNG(uint32_t windowId, int64_t rootId, int32_t x, int32_t y, bool verbose)
3872 {
3873 auto pipeline = GetPipelineByWindowId(windowId);
3874 CHECK_NULL_VOID(pipeline);
3875 auto accessibilityManagerNG = pipeline->GetAccessibilityManagerNG();
3876 CHECK_NULL_VOID(accessibilityManagerNG);
3877 auto pipelineRoot = pipeline->GetRootElement();
3878 RefPtr<NG::FrameNode> root = nullptr;
3879 if (rootId == -1) {
3880 root = pipelineRoot;
3881 } else {
3882 root = GetFramenodeByAccessibilityId(pipelineRoot, rootId);
3883 }
3884 CHECK_NULL_VOID(root);
3885
3886 DumpLog::GetInstance().Print("Window ID: " + std::to_string(windowId));
3887 DumpLog::GetInstance().Print("Root ID: " + std::to_string(root->GetAccessibilityId()));
3888 NG::PointF hoverPoint(x, y);
3889 DumpLog::GetInstance().Print("Hover Point: " + hoverPoint.ToString());
3890
3891 std::string summary;
3892 std::string detail;
3893 accessibilityManagerNG->HoverTestDebug(root, hoverPoint, summary, detail);
3894 DumpLog::GetInstance().Print(summary);
3895 if (verbose) {
3896 DumpLog::GetInstance().Print(detail);
3897 }
3898 }
3899
DumpProcessEventParameters(AccessibilityEvent & event,const std::vector<std::string> & params)3900 bool JsAccessibilityManager::DumpProcessEventParameters(
3901 AccessibilityEvent& event, const std::vector<std::string>& params)
3902 {
3903 constexpr int32_t NUM_PARAMETERS_DIMENSION = 1;
3904 if (params.size() < 1) {
3905 return false;
3906 }
3907 for (auto arg = params.begin() + 1; arg != params.end(); ++arg) {
3908 if (*arg == "--stackNodeId") {
3909 if (std::distance(arg, params.end()) <= NUM_PARAMETERS_DIMENSION) {
3910 DumpLog::GetInstance().Print(std::string("Error: parameters need with data"));
3911 return false;
3912 }
3913 ++arg;
3914 event.stackNodeId = StringUtils::StringToLongInt(*arg);
3915 } else if (*arg == "--beforeText") {
3916 if (std::distance(arg, params.end()) <= NUM_PARAMETERS_DIMENSION) {
3917 DumpLog::GetInstance().Print(std::string("Error: parameters need with data"));
3918 return false;
3919 }
3920 ++arg;
3921 event.beforeText = *arg;
3922 } else if (*arg == "--latestContent") {
3923 if (std::distance(arg, params.end()) <= NUM_PARAMETERS_DIMENSION) {
3924 DumpLog::GetInstance().Print(std::string("Error: parameters need with data"));
3925 return false;
3926 }
3927 ++arg;
3928 event.latestContent = *arg;
3929 } else if (*arg == "--textAnnounced") {
3930 if (std::distance(arg, params.end()) <= NUM_PARAMETERS_DIMENSION) {
3931 DumpLog::GetInstance().Print(std::string("Error: parameters need with data"));
3932 return false;
3933 }
3934 ++arg;
3935 event.textAnnouncedForAccessibility = *arg;
3936 }
3937 }
3938 return true;
3939 }
3940
DumpSendEventTest(int64_t nodeId,int32_t eventId,const std::vector<std::string> & params)3941 void JsAccessibilityManager::DumpSendEventTest(int64_t nodeId, int32_t eventId, const std::vector<std::string>& params)
3942 {
3943 auto pipeline = context_.Upgrade();
3944 CHECK_NULL_VOID(pipeline);
3945 RefPtr<NG::PipelineContext> ngPipeline;
3946
3947 RefPtr<NG::FrameNode> frameNode;
3948 ngPipeline = FindPipelineByElementId(nodeId, frameNode);
3949 CHECK_NULL_VOID(ngPipeline);
3950 CHECK_NULL_VOID(frameNode);
3951
3952 AccessibilityEvent accessibilityEvent;
3953 accessibilityEvent.nodeId = nodeId;
3954 accessibilityEvent.windowChangeTypes = WindowUpdateType::WINDOW_UPDATE_ACTIVE;
3955 accessibilityEvent.type = static_cast<AccessibilityEventType>(eventId);
3956 if (DumpProcessEventParameters(accessibilityEvent, params)) {
3957 SendEventToAccessibilityWithNode(accessibilityEvent, frameNode, ngPipeline);
3958 }
3959 }
3960
CheckDumpInfoParams(const std::vector<std::string> & params)3961 bool JsAccessibilityManager::CheckDumpInfoParams(const std::vector<std::string> ¶ms)
3962 {
3963 if (params.size() < 1) {
3964 return false;
3965 }
3966 const std::string firstParam = params[0];
3967 if (firstParam.compare("-inspector") != 0 && firstParam.compare("-accessibility") != 0 &&
3968 firstParam.compare("-simplify") != 0) {
3969 return false;
3970 }
3971 return true;
3972 }
3973
GetDumpInfoArgument(const std::vector<std::string> & params,DumpInfoArgument & argument)3974 bool JsAccessibilityManager::GetDumpInfoArgument(const std::vector<std::string>& params, DumpInfoArgument& argument)
3975 {
3976 if (params.size() < 1) {
3977 return false;
3978 }
3979 argument.isDumpSimplify = params[0].compare("-simplify") == 0;
3980 for (auto arg = params.begin() + 1; arg != params.end(); ++arg) {
3981 if (*arg == "-w") {
3982 argument.useWindowId = true;
3983 } else if (*arg == "--root") {
3984 ++arg;
3985 if (arg == params.end()) {
3986 DumpLog::GetInstance().Print(std::string("Error: --root is used to set the root node, ") +
3987 "e.g. '--root ${AccessibilityId}'!");
3988 return false;
3989 }
3990 argument.rootId = StringUtils::StringToLongInt(*arg);
3991 } else if (*arg == "--hover-test") {
3992 argument.mode = DumpMode::HOVER_TEST;
3993 static constexpr int32_t NUM_POINT_DIMENSION = 2;
3994 if (std::distance(arg, params.end()) <= NUM_POINT_DIMENSION) {
3995 DumpLog::GetInstance().Print(std::string("Error: --hover-test is used to get nodes at a point ") +
3996 "relative to the root node, e.g. '--hover-test ${x} ${y}'!");
3997 return false;
3998 }
3999 ++arg;
4000 argument.pointX = StringUtils::StringToInt(*arg);
4001 ++arg;
4002 argument.pointY = StringUtils::StringToInt(*arg);
4003 } else if (*arg == "--event-test") {
4004 return CheckAndGetEventTestArgument(arg, params, argument);
4005 } else if (*arg == "-v") {
4006 argument.verbose = true;
4007 } else if (*arg == "-json") {
4008 argument.mode = DumpMode::TREE;
4009 } else {
4010 if (argument.mode == DumpMode::NODE) {
4011 argument.mode = DumpMode::HANDLE_EVENT;
4012 break;
4013 } else {
4014 argument.mode = DumpMode::NODE;
4015 argument.nodeId = StringUtils::StringToLongInt(*arg);
4016 }
4017 }
4018 }
4019 return true;
4020 }
4021
OnDumpInfoNG(const std::vector<std::string> & params,uint32_t windowId,bool hasJson)4022 void JsAccessibilityManager::OnDumpInfoNG(const std::vector<std::string>& params, uint32_t windowId, bool hasJson)
4023 {
4024 if (!CheckDumpInfoParams(params)) {
4025 DumpLog::GetInstance().Print("Error: invalid arguments!");
4026 return;
4027 }
4028 DumpInfoArgument argument;
4029 if (!GetDumpInfoArgument(params, argument)) {
4030 return;
4031 }
4032 std::vector<std::string> info;
4033 bool isChildElement = CheckIsChildElement(argument.nodeId, params, info, argument.mode, argument.rootId);
4034 if (isChildElement) {
4035 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "dump child element: %{public}" PRId64, argument.nodeId);
4036 return;
4037 }
4038 switch (argument.mode) {
4039 case DumpMode::TREE:
4040 isUseJson_ = hasJson;
4041 DumpTreeNG(argument.useWindowId, windowId, argument.rootId, argument.isDumpSimplify);
4042 break;
4043 case DumpMode::NODE:
4044 DumpPropertyNG(argument.nodeId);
4045 break;
4046 case DumpMode::HANDLE_EVENT:
4047 DumpHandleEvent(params);
4048 break;
4049 case DumpMode::HOVER_TEST:
4050 DumpHoverTestNG(windowId, argument.rootId, argument.pointX, argument.pointY, argument.verbose);
4051 break;
4052 case DumpMode::EVENT_TEST:
4053 DumpSendEventTest(argument.nodeId, argument.eventId, params);
4054 break;
4055 default:
4056 DumpLog::GetInstance().Print("Error: invalid arguments!");
4057 break;
4058 }
4059 }
4060
CheckDumpHandleEventParams(const std::vector<std::string> & params)4061 bool JsAccessibilityManager::CheckDumpHandleEventParams(const std::vector<std::string>& params)
4062 {
4063 if (params.size() > EVENT_DUMP_PARAM_LENGTH_UPPER + 1) {
4064 DumpLog::GetInstance().Print("Error: params length is illegal!");
4065 return false;
4066 }
4067 if (params[EVENT_DUMP_ORDER_INDEX] != DUMP_ORDER && params[EVENT_DUMP_ORDER_INDEX] != DUMP_INSPECTOR) {
4068 DumpLog::GetInstance().Print("Error: Unrecognized dump command for accessibility!");
4069 return false;
4070 }
4071 return true;
4072 }
4073
CheckGetActionIdAndOp(const std::vector<std::string> & params,int64_t & actionAccessibilityId,ActionType & actionOp)4074 bool JsAccessibilityManager::CheckGetActionIdAndOp(
4075 const std::vector<std::string>& params,
4076 int64_t& actionAccessibilityId,
4077 ActionType& actionOp)
4078 {
4079 if (EVENT_DUMP_ID_INDEX > params.size()) {
4080 return false;
4081 }
4082 if (EVENT_DUMP_ACTION_INDEX != std::clamp(EVENT_DUMP_ACTION_INDEX, EVENT_DUMP_ID_INDEX, params.size())) {
4083 return false;
4084 }
4085 actionAccessibilityId = StringUtils::StringToLongInt(params[EVENT_DUMP_ID_INDEX]);
4086 auto action = static_cast<AceAction>(StringUtils::StringToInt(params[EVENT_DUMP_ACTION_INDEX]));
4087 actionOp = ConvertAceAction(action);
4088 if ((actionOp != ActionType::ACCESSIBILITY_ACTION_SET_SELECTION) &&
4089 (params.size() > EVENT_DUMP_PARAM_LENGTH_UPPER + 1)) {
4090 return false;
4091 }
4092 if (actionOp == ActionType::ACCESSIBILITY_ACTION_INVALID) {
4093 return false;
4094 }
4095 return true;
4096 }
4097
DumpHandleEvent(const std::vector<std::string> & params)4098 void JsAccessibilityManager::DumpHandleEvent(const std::vector<std::string>& params)
4099 {
4100 if (!CheckDumpHandleEventParams(params)) {
4101 return;
4102 }
4103 auto pipeline = context_.Upgrade();
4104 CHECK_NULL_VOID(pipeline);
4105 int64_t nodeId = StringUtils::StringToLongInt(params[EVENT_DUMP_ID_INDEX]);
4106
4107 int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
4108 int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
4109 AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(nodeId, splitElementId, splitTreeId);
4110 nodeId = splitElementId;
4111
4112 auto action = static_cast<AceAction>(StringUtils::StringToInt(params[EVENT_DUMP_ACTION_INDEX]));
4113 auto op = ConvertAceAction(action);
4114 if ((op != ActionType::ACCESSIBILITY_ACTION_SET_SELECTION) && (params.size() > EVENT_DUMP_PARAM_LENGTH_UPPER + 1)) {
4115 return DumpLog::GetInstance().Print("Error: params is illegal!");
4116 }
4117 std::map<std::string, std::string> paramsMap;
4118 ProcessParameters(op, params, paramsMap);
4119 if (AceType::InstanceOf<NG::PipelineContext>(pipeline)) {
4120 RefPtr<NG::FrameNode> node;
4121 #ifdef WINDOW_SCENE_SUPPORTED
4122 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipeline);
4123 auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
4124 CHECK_NULL_VOID(uiExtensionManager);
4125 if (uiExtensionManager->IsWrapExtensionAbilityId(nodeId)) {
4126 ExecuteActionNG(nodeId, paramsMap, op, ngPipeline, NG::UI_EXTENSION_OFFSET_MAX);
4127 return;
4128 }
4129 #endif
4130 pipeline = FindPipelineByElementId(nodeId, node);
4131 CHECK_NULL_VOID(pipeline);
4132 pipeline->GetTaskExecutor()->PostTask(
4133 [weak = WeakClaim(this), op, nodeId, paramsMap]() {
4134 auto jsAccessibilityManager = weak.Upgrade();
4135 CHECK_NULL_VOID(jsAccessibilityManager);
4136 RefPtr<NG::FrameNode> node;
4137 auto pipeline = jsAccessibilityManager->FindPipelineByElementId(nodeId, node);
4138 CHECK_NULL_VOID(pipeline);
4139 jsAccessibilityManager->ExecuteActionNG(nodeId, paramsMap, op, pipeline, NG::UI_EXTENSION_OFFSET_MAX);
4140 },
4141 TaskExecutor::TaskType::UI, "ArkUIAccessibilityExecuteAction");
4142 return;
4143 }
4144 auto node = GetAccessibilityNodeFromPage(nodeId);
4145 CHECK_NULL_VOID(node);
4146 pipeline->GetTaskExecutor()->PostTask(
4147 [weak = WeakClaim(this), op, node, paramsMap]() {
4148 auto jsAccessibilityManager = weak.Upgrade();
4149 CHECK_NULL_VOID(jsAccessibilityManager);
4150 auto pipeline = jsAccessibilityManager->context_.Upgrade();
4151 CHECK_NULL_VOID(pipeline);
4152 jsAccessibilityManager->AccessibilityActionEvent(
4153 op, paramsMap, node, AceType::DynamicCast<PipelineContext>(pipeline));
4154 },
4155 TaskExecutor::TaskType::UI, "ArkUIAccessibilityActionEvent");
4156 }
4157
DumpProperty(const RefPtr<AccessibilityNode> & node)4158 void JsAccessibilityManager::DumpProperty(const RefPtr<AccessibilityNode>& node)
4159 {
4160 const auto& supportAceActions = node->GetSupportAction();
4161 const auto& charValue = node->GetChartValue();
4162
4163 DumpLog::GetInstance().AddDesc("ID: ", node->GetNodeId());
4164 DumpLog::GetInstance().AddDesc("parent ID: ", node->GetParentId());
4165 DumpLog::GetInstance().AddDesc("child IDs: ", GetNodeChildIds(node));
4166 DumpLog::GetInstance().AddDesc("component type: ", node->GetTag());
4167 DumpLog::GetInstance().AddDesc("input type: ", node->GetInputType());
4168 DumpLog::GetInstance().AddDesc("text: ", node->GetText());
4169 DumpLog::GetInstance().AddDesc("width: ", node->GetWidth());
4170 DumpLog::GetInstance().AddDesc("height: ", node->GetHeight());
4171 DumpLog::GetInstance().AddDesc("left: ", node->GetLeft() + GetCardOffset().GetX());
4172 DumpLog::GetInstance().AddDesc("top: ", node->GetTop() + GetCardOffset().GetY());
4173 DumpLog::GetInstance().AddDesc("enabled: ", BoolToString(node->GetEnabledState()));
4174 DumpLog::GetInstance().AddDesc("checked: ", BoolToString(node->GetCheckedState()));
4175 DumpLog::GetInstance().AddDesc("selected: ", BoolToString(node->GetSelectedState()));
4176 DumpLog::GetInstance().AddDesc("focusable: ", BoolToString(node->GetFocusableState()));
4177 DumpLog::GetInstance().AddDesc("focused: ", BoolToString(node->GetFocusedState()));
4178 DumpLog::GetInstance().AddDesc("checkable: ", BoolToString(node->GetCheckableState()));
4179 DumpLog::GetInstance().AddDesc("clickable: ", BoolToString(node->GetClickableState()));
4180 DumpLog::GetInstance().AddDesc("long clickable: ", BoolToString(node->GetLongClickableState()));
4181 DumpLog::GetInstance().AddDesc("scrollable: ", BoolToString(node->GetScrollableState()));
4182 DumpLog::GetInstance().AddDesc("editable: ", BoolToString(node->GetEditable()));
4183 DumpLog::GetInstance().AddDesc("hint text: ", node->GetHintText());
4184 DumpLog::GetInstance().AddDesc("error text: ", node->GetErrorText());
4185 DumpLog::GetInstance().AddDesc("js component id: ", node->GetJsComponentId());
4186 DumpLog::GetInstance().AddDesc("accessibility label: ", node->GetAccessibilityLabel());
4187 DumpLog::GetInstance().AddDesc("accessibility hint: ", node->GetAccessibilityHint());
4188 DumpLog::GetInstance().AddDesc("max text length: ", node->GetMaxTextLength());
4189 DumpLog::GetInstance().AddDesc("text selection start: ", node->GetTextSelectionStart());
4190 DumpLog::GetInstance().AddDesc("text selection end: ", node->GetTextSelectionEnd());
4191 DumpLog::GetInstance().AddDesc("is multi line: ", BoolToString(node->GetIsMultiLine()));
4192 DumpLog::GetInstance().AddDesc("is password", BoolToString(node->GetIsPassword()));
4193 DumpLog::GetInstance().AddDesc("text input type: ", ConvertInputTypeToString(node->GetTextInputType()));
4194 DumpLog::GetInstance().AddDesc("min value: ", node->GetAccessibilityValue().min);
4195 DumpLog::GetInstance().AddDesc("max value: ", node->GetAccessibilityValue().max);
4196 DumpLog::GetInstance().AddDesc("current value: ", node->GetAccessibilityValue().current);
4197 DumpLog::GetInstance().AddDesc("collection info rows: ", node->GetCollectionInfo().rows);
4198 DumpLog::GetInstance().AddDesc("collection info columns: ", node->GetCollectionInfo().columns);
4199 DumpLog::GetInstance().AddDesc("collection item info, row: ", node->GetCollectionItemInfo().row);
4200 DumpLog::GetInstance().AddDesc("collection item info, column: ", node->GetCollectionItemInfo().column);
4201 DumpLog::GetInstance().AddDesc("chart has value: ", BoolToString(charValue && !charValue->empty()));
4202 DumpLog::GetInstance().AddDesc("accessibilityGroup: ", BoolToString(node->GetAccessible()));
4203 DumpLog::GetInstance().AddDesc("accessibilityImportance: ", node->GetImportantForAccessibility());
4204 DumpLog::GetInstance().AddDesc("support action: ", GetSupportAction(supportAceActions));
4205 DumpLog::GetInstance().Print(0, node->GetTag(), node->GetChildList().size());
4206 }
4207
DumpPropertyNG(int64_t nodeID)4208 void JsAccessibilityManager::DumpPropertyNG(int64_t nodeID)
4209 {
4210 auto pipeline = context_.Upgrade();
4211 CHECK_NULL_VOID(pipeline);
4212 RefPtr<NG::PipelineContext> ngPipeline;
4213
4214 #ifdef WINDOW_SCENE_SUPPORTED
4215 ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipeline);
4216 auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
4217 CHECK_NULL_VOID(uiExtensionManager);
4218 std::list<AccessibilityElementInfo> extensionElementInfos;
4219 if (uiExtensionManager->IsWrapExtensionAbilityId(nodeID)) {
4220 SearchElementInfoByAccessibilityIdNG(
4221 nodeID, PREFETCH_RECURSIVE_CHILDREN, extensionElementInfos, ngPipeline, NG::UI_EXTENSION_OFFSET_MAX);
4222 for (auto& extensionElementInfo : extensionElementInfos) {
4223 if (nodeID == extensionElementInfo.GetAccessibilityId()) {
4224 DumpCommonPropertyNG(extensionElementInfo, treeId_);
4225 DumpAccessibilityPropertyNG(extensionElementInfo);
4226 DumpLog::GetInstance().Print(
4227 0, extensionElementInfo.GetComponentType(), extensionElementInfo.GetChildCount());
4228 return;
4229 }
4230 }
4231 }
4232 #endif
4233
4234 RefPtr<NG::FrameNode> frameNode;
4235 ngPipeline = FindPipelineByElementId(nodeID, frameNode);
4236 CHECK_NULL_VOID(ngPipeline);
4237 CHECK_NULL_VOID(frameNode);
4238
4239 CommonProperty commonProperty;
4240 GenerateCommonProperty(ngPipeline, commonProperty, pipeline, frameNode);
4241 AccessibilityElementInfo nodeInfo;
4242 UpdateAccessibilityElementInfo(frameNode, commonProperty, nodeInfo, ngPipeline);
4243 SetRootAccessibilityVisible(frameNode, nodeInfo);
4244 SetRootAccessibilityNextFocusId(frameNode, ngPipeline->GetRootElement(), nodeInfo);
4245 SetRootAccessibilityPreFocusId(frameNode, ngPipeline->GetRootElement(), nodeInfo);
4246 if (IsExtensionComponent(frameNode) && !IsUIExtensionShowPlaceholder(frameNode)) {
4247 SearchParameter param {-1, "", PREFETCH_RECURSIVE_CHILDREN, NG::UI_EXTENSION_OFFSET_MAX};
4248 std::list<AccessibilityElementInfo> extensionElementInfos;
4249 SearchExtensionElementInfoNG(param, frameNode, extensionElementInfos, nodeInfo);
4250 }
4251 DumpCommonPropertyNG(nodeInfo, treeId_);
4252 DumpAccessibilityPropertyNG(nodeInfo);
4253 auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
4254 if (accessibilityProperty) {
4255 DumpLog::GetInstance().AddDesc("offset: ", accessibilityProperty->GetScrollOffSet());
4256 DumpLog::GetInstance().AddDesc("childTreeId: ", accessibilityProperty->GetChildTreeId());
4257 DumpLog::GetInstance().AddDesc("childWindowId: ", accessibilityProperty->GetChildWindowId());
4258 }
4259 DumpLog::GetInstance().Print(0, nodeInfo.GetComponentType(), nodeInfo.GetChildCount());
4260 }
4261
DumpProperty(const std::vector<std::string> & params)4262 void JsAccessibilityManager::DumpProperty(const std::vector<std::string>& params)
4263 {
4264 CHECK_NULL_VOID(DumpLog::GetInstance().GetDumpFile());
4265 if (params.empty()) {
4266 DumpLog::GetInstance().Print("Error: params cannot be empty!");
4267 return;
4268 }
4269 if (params.size() != PROPERTY_DUMP_PARAM_LENGTH) {
4270 DumpLog::GetInstance().Print("Error: params length is illegal!");
4271 return;
4272 }
4273 if (params[0] != DUMP_ORDER && params[0] != DUMP_INSPECTOR) {
4274 DumpLog::GetInstance().Print("Error: not accessibility dump order!");
4275 return;
4276 }
4277
4278 auto pipeline = context_.Upgrade();
4279 CHECK_NULL_VOID(pipeline);
4280
4281 if (!AceType::InstanceOf<NG::PipelineContext>(pipeline)) {
4282 auto node = GetAccessibilityNodeFromPage(StringUtils::StringToLongInt(params[1]));
4283 if (!node) {
4284 DumpLog::GetInstance().Print("Error: can't find node with ID " + params[1]);
4285 return;
4286 }
4287 DumpProperty(node);
4288 } else {
4289 DumpPropertyNG(StringUtils::StringToLongInt(params[1]));
4290 }
4291 }
4292
DumpAccessibilityElementInfosTreeNG(std::list<AccessibilityElementInfo> & infos,int32_t depth,int64_t accessibilityId,bool isRoot)4293 static void DumpAccessibilityElementInfosTreeNG(
4294 std::list<AccessibilityElementInfo>& infos, int32_t depth, int64_t accessibilityId, bool isRoot)
4295 {
4296 AccessibilityElementInfo accessibilityInfo;
4297 for (auto& info : infos) {
4298 if (accessibilityId == info.GetAccessibilityId()) {
4299 accessibilityInfo = info;
4300 break;
4301 }
4302 }
4303 if (!isRoot) {
4304 DumpLog::GetInstance().AddDesc("ID: " + std::to_string(accessibilityInfo.GetAccessibilityId()));
4305 DumpLog::GetInstance().AddDesc("compid: " + accessibilityInfo.GetInspectorKey());
4306 DumpLog::GetInstance().AddDesc("text: " + accessibilityInfo.GetContent());
4307 DumpLog::GetInstance().AddDesc("accessibilityText: " + accessibilityInfo.GetContent());
4308 DumpLog::GetInstance().AddDesc("accessibilityGroup: ");
4309 DumpLog::GetInstance().AddDesc("accessibilityLevel: ");
4310 DumpLog::GetInstance().AddDesc("accessibilityCustomRole: " + accessibilityInfo.GetCustomComponentType());
4311 DumpLog::GetInstance().AddDesc("top: " +
4312 std::to_string(accessibilityInfo.GetRectInScreen().GetLeftTopYScreenPostion()));
4313 DumpLog::GetInstance().AddDesc("left: " +
4314 std::to_string(accessibilityInfo.GetRectInScreen().GetLeftTopXScreenPostion()));
4315 DumpLog::GetInstance().AddDesc("width: " + std::to_string(
4316 accessibilityInfo.GetRectInScreen().GetRightBottomXScreenPostion() -
4317 accessibilityInfo.GetRectInScreen().GetLeftTopXScreenPostion()));
4318 DumpLog::GetInstance().AddDesc("height: " + std::to_string(
4319 accessibilityInfo.GetRectInScreen().GetRightBottomYScreenPostion() -
4320 accessibilityInfo.GetRectInScreen().GetLeftTopYScreenPostion()));
4321 DumpLog::GetInstance().AddDesc("visible: " + std::to_string(accessibilityInfo.IsVisible()));
4322 DumpLog::GetInstance().AddDesc(
4323 "clickable: " + std::to_string(accessibilityInfo.IsClickable()));
4324 DumpLog::GetInstance().AddDesc("longclickable: " +
4325 std::to_string(accessibilityInfo.IsLongClickable()));
4326 DumpLog::GetInstance().AddDesc("checkable: " + std::to_string(accessibilityInfo.IsCheckable()));
4327 DumpLog::GetInstance().AddDesc("scrollable: " + std::to_string(accessibilityInfo.IsScrollable()));
4328 DumpLog::GetInstance().AddDesc("checked: " + std::to_string(accessibilityInfo.IsChecked()));
4329 DumpLog::GetInstance().AddDesc("hint: " + accessibilityInfo.GetHint());
4330 DumpLog::GetInstance().Print(depth, accessibilityInfo.GetComponentType(), accessibilityInfo.GetChildCount());
4331 depth ++;
4332 }
4333 for (auto child : accessibilityInfo.GetChildIds()) {
4334 DumpAccessibilityElementInfosTreeNG(infos, depth, child, false);
4335 }
4336 }
4337
DumpTreeNodeInfoNG(const RefPtr<NG::FrameNode> & node,int32_t depth,const CommonProperty & commonProperty,int32_t childSize)4338 static void DumpTreeNodeInfoNG(
4339 const RefPtr<NG::FrameNode>& node, int32_t depth, const CommonProperty& commonProperty, int32_t childSize)
4340 {
4341 NG::RectF rect = node->GetTransformRectRelativeToWindow(true);
4342 auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
4343 DumpLog::GetInstance().AddDesc("ID: " + std::to_string(node->GetAccessibilityId()));
4344 DumpLog::GetInstance().AddDesc("compid: " + node->GetInspectorId().value_or(""));
4345 if (accessibilityProperty) {
4346 DumpLog::GetInstance().AddDesc("text: " + accessibilityProperty->GetGroupText());
4347 DumpLog::GetInstance().AddDesc("accessibilityText: " + accessibilityProperty->GetAccessibilityText());
4348 DumpLog::GetInstance().AddDesc(
4349 "accessibilityGroup: " + std::to_string(accessibilityProperty->IsAccessibilityGroup()));
4350 DumpLog::GetInstance().AddDesc("accessibilityLevel: " + accessibilityProperty->GetAccessibilityLevel());
4351 DumpLog::GetInstance().AddDesc(
4352 "accessibilityCustomRole: " + accessibilityProperty->GetAccessibilityCustomRole());
4353 }
4354 DumpLog::GetInstance().AddDesc("top: " + std::to_string(rect.Top() + commonProperty.windowTop));
4355 DumpLog::GetInstance().AddDesc("left: " + std::to_string(rect.Left() + commonProperty.windowLeft));
4356 DumpLog::GetInstance().AddDesc("width: " + std::to_string(rect.Width()));
4357 DumpLog::GetInstance().AddDesc("height: " + std::to_string(rect.Height()));
4358 DumpLog::GetInstance().AddDesc("visible: " + std::to_string(node->IsVisible()));
4359 auto eventHub = node->GetEventHub<NG::EventHub>();
4360 if (eventHub) {
4361 auto gestureEventHub = eventHub->GetGestureEventHub();
4362 DumpLog::GetInstance().AddDesc(
4363 "clickable: " + std::to_string(gestureEventHub ? gestureEventHub->IsAccessibilityClickable() : false));
4364 DumpLog::GetInstance().AddDesc("longclickable: " +
4365 std::to_string(gestureEventHub ? gestureEventHub->IsAccessibilityLongClickable() : false));
4366 }
4367 if (accessibilityProperty) {
4368 DumpLog::GetInstance().AddDesc("checkable: " + std::to_string(accessibilityProperty->IsCheckable()));
4369 DumpLog::GetInstance().AddDesc("scrollable: " + std::to_string(accessibilityProperty->IsScrollable()));
4370 DumpLog::GetInstance().AddDesc("checked: " + std::to_string(accessibilityProperty->IsChecked()));
4371 DumpLog::GetInstance().AddDesc("hint: " + accessibilityProperty->GetHintText());
4372 DumpLog::GetInstance().AddDesc("childTree: " + std::to_string(accessibilityProperty->GetChildTreeId()));
4373 }
4374 DumpLog::GetInstance().Print(depth, node->GetTag(), childSize);
4375 }
4376
DumpTreeNodeSafeAreaInfoNg(const RefPtr<NG::FrameNode> & node)4377 void JsAccessibilityManager::DumpTreeNodeSafeAreaInfoNg(const RefPtr<NG::FrameNode>& node)
4378 {
4379 auto layoutProperty = node->GetLayoutProperty();
4380 if (layoutProperty) {
4381 auto&& opts = layoutProperty->GetSafeAreaExpandOpts();
4382 if (opts && opts->type != NG::SAFE_AREA_TYPE_NONE && opts->edges != NG::SAFE_AREA_EDGE_NONE) {
4383 DumpLog::GetInstance().AddDesc(opts->ToString());
4384 }
4385 if (layoutProperty->GetSafeAreaInsets()) {
4386 DumpLog::GetInstance().AddDesc(layoutProperty->GetSafeAreaInsets()->ToString());
4387 }
4388 }
4389 if (node->SelfOrParentExpansive()) {
4390 auto geometryNode = node->GetGeometryNode();
4391 if (geometryNode) {
4392 auto rect = geometryNode->GetSelfAdjust();
4393 auto parentRect = geometryNode->GetParentAdjust();
4394 bool isDefaultSize = NearZero(rect.GetX(), 0.0) && NearZero(rect.GetY(), 0.0) &&
4395 NearZero(rect.Width(), 0.0) && NearZero(rect.Height(), 0.0);
4396 bool isParentDefaultSize = NearZero(parentRect.GetX(), 0.0) && NearZero(parentRect.GetY(), 0.0) &&
4397 NearZero(parentRect.Width(), 0.0) && NearZero(parentRect.Height(), 0.0);
4398 if (!isDefaultSize && !isParentDefaultSize) {
4399 DumpLog::GetInstance().AddDesc(std::string("selfAdjust: ")
4400 .append(rect.ToString().c_str())
4401 .append(",parentAdjust")
4402 .append(parentRect.ToString().c_str()));
4403 }
4404 }
4405 }
4406 CHECK_NULL_VOID(node->GetTag() == V2::PAGE_ETS_TAG);
4407 auto pipeline = node->GetContext();
4408 CHECK_NULL_VOID(pipeline);
4409 auto manager = pipeline->GetSafeAreaManager();
4410 CHECK_NULL_VOID(manager);
4411 if (!manager->IsIgnoreSafeArea() && !manager->IsNeedAvoidWindow() && !manager->IsFullScreen() &&
4412 !manager->KeyboardSafeAreaEnabled() && !manager->GetUseCutout()) {
4413 DumpLog::GetInstance().AddDesc(
4414 std::string("ignoreSafeArea: ")
4415 .append(std::to_string(manager->IsIgnoreSafeArea()))
4416 .append(std::string(", isNeedAvoidWindow: ").c_str())
4417 .append(std::to_string(manager->IsNeedAvoidWindow()))
4418 .append(std::string(", IisFullScreen: ").c_str())
4419 .append(std::to_string(manager->IsFullScreen()))
4420 .append(std::string(", isKeyboardAvoidMode: ").c_str())
4421 .append(std::to_string(static_cast<int32_t>(manager->GetKeyBoardAvoidMode())))
4422 .append(std::string(", isUseCutout: ").c_str())
4423 .append(std::to_string(manager->GetUseCutout())));
4424 }
4425 }
4426
DumpPadding(const std::unique_ptr<NG::PaddingProperty> & padding,std::string label)4427 void JsAccessibilityManager::DumpPadding(const std::unique_ptr<NG::PaddingProperty>& padding, std::string label)
4428 {
4429 NG::CalcLength defaultValue = NG::CalcLength(Dimension(0));
4430 auto left = padding->left.value_or(defaultValue).GetDimension().Value();
4431 auto right = padding->right.value_or(defaultValue).GetDimension().Value();
4432 auto top = padding->top.value_or(defaultValue).GetDimension().Value();
4433 auto bottom = padding->bottom.value_or(defaultValue).GetDimension().Value();
4434 if (!NearZero(left, 0.0) && !NearZero(right, 0.0) && !NearZero(top, 0.0) && !NearZero(bottom, 0.0)) {
4435 DumpLog::GetInstance().AddDesc(label.append(padding->ToString().c_str()));
4436 }
4437 }
4438
DumpBorder(const std::unique_ptr<NG::BorderWidthProperty> & border,std::string label)4439 void JsAccessibilityManager::DumpBorder(const std::unique_ptr<NG::BorderWidthProperty>& border, std::string label)
4440 {
4441 Dimension defaultValue(0);
4442 auto left = border->leftDimen.value_or(defaultValue).Value();
4443 auto right = border->rightDimen.value_or(defaultValue).Value();
4444 auto top = border->topDimen.value_or(defaultValue).Value();
4445 auto bottom = border->bottomDimen.value_or(defaultValue).Value();
4446 if (!NearZero(left, 0.0) && !NearZero(right, 0.0) && !NearZero(top, 0.0) && !NearZero(bottom, 0.0)) {
4447 DumpLog::GetInstance().AddDesc(label.append(border->ToString().c_str()));
4448 }
4449 }
4450
DumpTreeNodeCommonInfoNg(const RefPtr<NG::FrameNode> & node,const CommonProperty & commonProperty)4451 void JsAccessibilityManager::DumpTreeNodeCommonInfoNg(
4452 const RefPtr<NG::FrameNode>& node, const CommonProperty& commonProperty)
4453 {
4454 DumpLog::GetInstance().AddDesc("ID: " + std::to_string(node->GetAccessibilityId()));
4455 auto renderContext = node->GetRenderContext();
4456 if (renderContext) {
4457 auto backgroundColor = renderContext->GetBackgroundColor();
4458 if (backgroundColor && backgroundColor->ColorToString().compare("#00000000") != 0) {
4459 DumpLog::GetInstance().AddDesc("BackgroundColor: " + backgroundColor->ColorToString());
4460 }
4461 DumpLog::GetInstance().AddDesc(std::string("PaintRectWithoutTransform: ")
4462 .append(renderContext->GetPaintRectWithoutTransform().ToString()));
4463 }
4464 NG::RectF rect = node->GetTransformRectRelativeToWindow(true);
4465 auto top = rect.Top() + commonProperty.windowTop;
4466 auto left = rect.Left() + commonProperty.windowLeft;
4467 if (!NearZero(top, 0.0) && !NearZero(left, 0.0)) {
4468 DumpLog::GetInstance().AddDesc("top: " + std::to_string(top));
4469 DumpLog::GetInstance().AddDesc("left: " + std::to_string(left));
4470 }
4471 DumpLog::GetInstance().AddDesc("width: " + std::to_string(rect.Width()));
4472 DumpLog::GetInstance().AddDesc("height: " + std::to_string(rect.Height()));
4473 auto layoutProperty = node->GetLayoutProperty();
4474 if (layoutProperty) {
4475 if (!node->IsVisible() && layoutProperty->GetVisibility().has_value()) {
4476 DumpLog::GetInstance().AddDesc(
4477 "visible: " + std::to_string(static_cast<int32_t>(layoutProperty->GetVisibility().value())));
4478 }
4479 auto& padding = layoutProperty->GetPaddingProperty();
4480 if (padding) {
4481 DumpPadding(padding, std::string("Padding: "));
4482 }
4483 auto& safeAreaPadding = layoutProperty->GetSafeAreaPaddingProperty();
4484 if (safeAreaPadding) {
4485 DumpPadding(safeAreaPadding, std::string("SafeAreaPadding: "));
4486 }
4487 auto& margin = layoutProperty->GetMarginProperty();
4488 if (margin) {
4489 DumpPadding(margin, std::string("Margin: "));
4490 }
4491 auto& border = layoutProperty->GetBorderWidthProperty();
4492 if (border) {
4493 DumpBorder(border, std::string("Border: "));
4494 }
4495 auto layoutRect = layoutProperty->GetLayoutRect();
4496 if (layoutRect) {
4497 DumpLog::GetInstance().AddDesc(std::string("LayoutRect: ").append(layoutRect.value().ToString().c_str()));
4498 }
4499 }
4500 }
4501
DumpTreeNodeSimplifyInfoNG(const RefPtr<NG::FrameNode> & node,int32_t depth,const CommonProperty & commonProperty,int32_t childSize)4502 void JsAccessibilityManager::DumpTreeNodeSimplifyInfoNG(
4503 const RefPtr<NG::FrameNode>& node, int32_t depth, const CommonProperty& commonProperty, int32_t childSize)
4504 {
4505 DumpTreeNodeCommonInfoNg(node, commonProperty);
4506 DumpTreeNodeSafeAreaInfoNg(node);
4507 DumpLog::GetInstance().Print(depth, node->GetTag(), childSize);
4508 }
4509
DumpTreeAccessibilityNodeNG(const RefPtr<NG::UINode> & uiNodeParent,int32_t depth,int64_t nodeID,const CommonProperty & commonProperty)4510 void JsAccessibilityManager::DumpTreeAccessibilityNodeNG(const RefPtr<NG::UINode>& uiNodeParent, int32_t depth,
4511 int64_t nodeID, const CommonProperty& commonProperty)
4512 {
4513 CHECK_NULL_VOID(uiNodeParent);
4514 auto virtualFrameNode = AceType::DynamicCast<NG::FrameNode>(uiNodeParent);
4515 auto uiNodeChildren = uiNodeParent->GetChildren(true);
4516 auto vNode = GetFramenodeByAccessibilityId(virtualFrameNode, nodeID);
4517 if (!vNode) {
4518 if (uiNodeChildren.size() == 0) {
4519 return;
4520 }
4521 }
4522 std::vector<std::pair<int64_t, int32_t>> childrenIdInfo;
4523 for (const auto& item : uiNodeChildren) {
4524 GetFrameNodeChildren(item, childrenIdInfo, commonProperty);
4525 }
4526 if (vNode != nullptr) {
4527 DumpTreeNodeInfoNG(vNode, depth + 1, commonProperty, childrenIdInfo.size());
4528 }
4529 for (const auto& item : uiNodeChildren) {
4530 DumpTreeAccessibilityNodeNG(item, depth + 1, item->GetAccessibilityId(), commonProperty);
4531 }
4532 }
4533
DumpTreeNG(const RefPtr<NG::FrameNode> & parent,int32_t depth,int64_t nodeID,const CommonProperty & commonProperty,bool isDumpSimplify)4534 void JsAccessibilityManager::DumpTreeNG(const RefPtr<NG::FrameNode>& parent, int32_t depth,
4535 int64_t nodeID, const CommonProperty& commonProperty, bool isDumpSimplify)
4536 {
4537 auto node = GetFramenodeByAccessibilityId(parent, nodeID);
4538 if (!node) {
4539 DumpLog::GetInstance().Print("Error: failed to get accessibility node with ID " + std::to_string(nodeID));
4540 return;
4541 }
4542 if (!node->IsActive()) {
4543 return;
4544 }
4545 std::vector<std::pair<int64_t, int32_t>> childrenIdInfo;
4546 for (const auto& item : node->GetChildren(true)) {
4547 GetFrameNodeChildren(item, childrenIdInfo, commonProperty);
4548 }
4549
4550 auto overlayNode = node->GetOverlayNode();
4551 if (overlayNode) {
4552 GetFrameNodeChildren(overlayNode, childrenIdInfo, commonProperty);
4553 }
4554
4555 if (isDumpSimplify) {
4556 DumpTreeNodeSimplifyInfoNG(node, depth, commonProperty, childrenIdInfo.size());
4557 } else if (!isUseJson_) {
4558 DumpTreeNodeInfoNG(node, depth, commonProperty, childrenIdInfo.size());
4559 } else {
4560 DumpTreeNodeInfoInJson(node, depth, commonProperty, childrenIdInfo.size());
4561 }
4562 auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
4563 auto uiVirtualNode = accessibilityProperty->GetAccessibilityVirtualNode();
4564 bool hasVirtualNode = false;
4565 if (uiVirtualNode != nullptr) {
4566 auto virtualNode = AceType::DynamicCast<NG::FrameNode>(uiVirtualNode);
4567 CHECK_NULL_VOID(virtualNode);
4568 hasVirtualNode = true;
4569 DumpTreeAccessibilityNodeNG(uiVirtualNode, depth+1, virtualNode->GetAccessibilityId(), commonProperty);
4570 }
4571 if (IsExtensionComponent(node) && !IsUIExtensionShowPlaceholder(node)) {
4572 std::list<AccessibilityElementInfo> extensionElementInfos;
4573 auto pipeline = context_.Upgrade();
4574 CHECK_NULL_VOID(pipeline);
4575 SearchElementInfoByAccessibilityIdNG(
4576 node->GetAccessibilityId(), PREFETCH_RECURSIVE_CHILDREN, extensionElementInfos,
4577 pipeline, NG::UI_EXTENSION_OFFSET_MAX);
4578 if (!extensionElementInfos.empty()) {
4579 DumpAccessibilityElementInfosTreeNG(extensionElementInfos, depth + 1, node->GetAccessibilityId(), true);
4580 }
4581 }
4582 if (!hasVirtualNode) {
4583 for (const auto& childIdPair : childrenIdInfo) {
4584 DumpTreeNG(node, depth + 1, childIdPair.first, commonProperty, isDumpSimplify);
4585 }
4586 }
4587 }
4588
DumpTree(int32_t depth,int64_t nodeID,bool isDumpSimplify)4589 void JsAccessibilityManager::DumpTree(int32_t depth, int64_t nodeID, bool isDumpSimplify)
4590 {
4591 auto pipeline = context_.Upgrade();
4592 CHECK_NULL_VOID(pipeline);
4593 if (!AceType::InstanceOf<NG::PipelineContext>(pipeline)) {
4594 AccessibilityNodeManager::DumpTree(depth, nodeID, isDumpSimplify);
4595 } else {
4596 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipeline);
4597 auto rootNode = ngPipeline->GetRootElement();
4598 CHECK_NULL_VOID(rootNode);
4599 nodeID = rootNode->GetAccessibilityId();
4600 CommonProperty commonProperty;
4601 GenerateCommonProperty(ngPipeline, commonProperty, pipeline, rootNode);
4602 DumpTreeNG(rootNode, depth, nodeID, commonProperty, isDumpSimplify);
4603 for (const auto& subContext : GetSubPipelineContexts()) {
4604 auto subPipeline = subContext.Upgrade();
4605 ngPipeline = AceType::DynamicCast<NG::PipelineContext>(subPipeline);
4606 CHECK_NULL_VOID(ngPipeline);
4607 rootNode = ngPipeline->GetRootElement();
4608 CHECK_NULL_VOID(rootNode);
4609 nodeID = rootNode->GetAccessibilityId();
4610 commonProperty.windowId = static_cast<int32_t>(ngPipeline->GetWindowId());
4611 commonProperty.windowLeft = GetWindowLeft(ngPipeline->GetWindowId());
4612 commonProperty.windowTop = GetWindowTop(ngPipeline->GetWindowId());
4613 commonProperty.pageNodes.clear(); // empty means search all page
4614 commonProperty.pagePaths.clear();
4615 DumpTreeNG(rootNode, depth, nodeID, commonProperty, isDumpSimplify);
4616 }
4617 }
4618 }
4619
SetCardViewParams(const std::string & key,bool focus)4620 void JsAccessibilityManager::SetCardViewParams(const std::string& key, bool focus)
4621 {
4622 callbackKey_ = key;
4623 if (!callbackKey_.empty()) {
4624 InitializeCallback();
4625 }
4626 }
4627
UpdateViewScale()4628 void JsAccessibilityManager::UpdateViewScale()
4629 {
4630 auto context = GetPipelineContext().Upgrade();
4631 CHECK_NULL_VOID(context);
4632 float scaleX = 1.0;
4633 float scaleY = 1.0;
4634 if (context->GetViewScale(scaleX, scaleY)) {
4635 scaleX_ = scaleX;
4636 scaleY_ = scaleY;
4637 }
4638 }
4639
HandleComponentPostBinding()4640 void JsAccessibilityManager::HandleComponentPostBinding()
4641 {
4642 for (auto targetIter = nodeWithTargetMap_.begin(); targetIter != nodeWithTargetMap_.end();) {
4643 auto nodeWithTarget = targetIter->second.Upgrade();
4644 if (nodeWithTarget) {
4645 if (nodeWithTarget->GetTag() == ACCESSIBILITY_TAG_POPUP) {
4646 auto idNodeIter = nodeWithIdMap_.find(targetIter->first);
4647 if (idNodeIter != nodeWithIdMap_.end()) {
4648 auto nodeWithId = idNodeIter->second.Upgrade();
4649 if (nodeWithId) {
4650 nodeWithId->SetAccessibilityHint(nodeWithTarget->GetText());
4651 } else {
4652 nodeWithIdMap_.erase(idNodeIter);
4653 }
4654 }
4655 }
4656 ++targetIter;
4657 } else {
4658 // clear the disabled node in the maps
4659 targetIter = nodeWithTargetMap_.erase(targetIter);
4660 }
4661 }
4662
4663 // clear the disabled node in the maps
4664 for (auto idItem = nodeWithIdMap_.begin(); idItem != nodeWithIdMap_.end();) {
4665 if (!idItem->second.Upgrade()) {
4666 idItem = nodeWithIdMap_.erase(idItem);
4667 } else {
4668 ++idItem;
4669 }
4670 }
4671 }
4672
Create()4673 RefPtr<AccessibilityNodeManager> AccessibilityNodeManager::Create()
4674 {
4675 return AceType::MakeRefPtr<JsAccessibilityManager>();
4676 }
4677
GetPipelineByWindowId(const int32_t windowId)4678 RefPtr<PipelineBase> JsAccessibilityManager::GetPipelineByWindowId(const int32_t windowId)
4679 {
4680 auto context = context_.Upgrade();
4681 if (AceType::InstanceOf<NG::PipelineContext>(context)) {
4682 CHECK_NULL_RETURN(context, nullptr);
4683 if (context->GetWindowId() == static_cast<uint32_t>(windowId)) {
4684 return context;
4685 }
4686 if (GetWindowId() == static_cast<uint32_t>(windowId)) {
4687 return context;
4688 }
4689 for (auto& subContext : GetSubPipelineContexts()) {
4690 context = subContext.Upgrade();
4691 CHECK_NULL_RETURN(context, nullptr);
4692 if (context->GetWindowId() == static_cast<uint32_t>(windowId)) {
4693 return context;
4694 }
4695 }
4696 return nullptr;
4697 } else {
4698 return context;
4699 }
4700 }
4701
SearchElementInfoByAccessibilityId(const int64_t elementId,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t mode)4702 void JsAccessibilityManager::JsInteractionOperation::SearchElementInfoByAccessibilityId(const int64_t elementId,
4703 const int32_t requestId, AccessibilityElementOperatorCallback& callback, const int32_t mode)
4704 {
4705 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "ArkUI search by id: %{public}" PRId64 ", mode: %{public}d",
4706 elementId, mode);
4707 int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
4708 int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
4709 AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
4710
4711 auto jsAccessibilityManager = GetHandler().Upgrade();
4712 if (!jsAccessibilityManager) {
4713 std::list<AccessibilityElementInfo> infos;
4714 callback.SetSearchElementInfoByAccessibilityIdResult(infos, requestId);
4715 TAG_LOGE(AceLogTag::ACE_ACCESSIBILITY, "SetSearchElementInfoByAccessibilityIdResult, requestId: %{public}d",
4716 requestId);
4717 return;
4718 }
4719 auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
4720 if (!context) {
4721 std::list<AccessibilityElementInfo> infos;
4722 callback.SetSearchElementInfoByAccessibilityIdResult(infos, requestId);
4723 TAG_LOGE(AceLogTag::ACE_ACCESSIBILITY, "SetSearchElementInfoByAccessibilityIdResult, requestId: %{public}d",
4724 requestId);
4725 return;
4726 }
4727 auto windowId = windowId_;
4728 context->GetTaskExecutor()->PostTask(
4729 [weak = GetHandler(), splitElementId, requestId, &callback, mode, windowId]() {
4730 auto jsAccessibilityManager = weak.Upgrade();
4731 if (!jsAccessibilityManager) {
4732 std::list<AccessibilityElementInfo> infos;
4733 callback.SetSearchElementInfoByAccessibilityIdResult(infos, requestId);
4734 TAG_LOGE(AceLogTag::ACE_ACCESSIBILITY,
4735 "SetSearchElementInfoByAccessibilityIdResult, requestId: %{public}d", requestId);
4736 return;
4737 }
4738 ACE_SCOPED_TRACE("SearchElementInfoByAccessibilityId");
4739 jsAccessibilityManager->SearchElementInfoByAccessibilityId(
4740 splitElementId, requestId, callback, mode, windowId);
4741 },
4742 TaskExecutor::TaskType::UI, "ArkUIAccessibilitySearchElementInfoById");
4743 }
4744 #ifdef WEB_SUPPORTED
4745
SearchElementInfoByAccessibilityId(const int64_t elementId,const int32_t requestId,Accessibility::AccessibilityElementOperatorCallback & callback,const int32_t mode)4746 void JsAccessibilityManager::WebInteractionOperation::SearchElementInfoByAccessibilityId(const int64_t elementId,
4747 const int32_t requestId, Accessibility::AccessibilityElementOperatorCallback& callback, const int32_t mode)
4748 {
4749 uint32_t realMode = mode;
4750 if (realMode & static_cast<uint32_t>(PREFETCH_RECURSIVE_CHILDREN_REDUCED)) {
4751 realMode &= ~static_cast<uint32_t>(PREFETCH_RECURSIVE_CHILDREN_REDUCED);
4752 realMode |= static_cast<uint32_t>(PREFETCH_RECURSIVE_CHILDREN);
4753 }
4754 TAG_LOGD(AceLogTag::ACE_WEB, "search by id: %{public}" PRId64 ", mode: %{public}d",
4755 elementId, mode);
4756 int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
4757 int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
4758 AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
4759
4760 auto jsAccessibilityManager = GetHandler().Upgrade();
4761 CHECK_NULL_VOID(jsAccessibilityManager);
4762 auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
4763 CHECK_NULL_VOID(context);
4764 auto windowId = windowId_;
4765 auto web = webPattern_;
4766 context->GetTaskExecutor()->PostTask(
4767 [weak = GetHandler(), splitElementId, requestId, &callback, realMode, windowId, web]() {
4768 auto jsAccessibilityManager = weak.Upgrade();
4769 CHECK_NULL_VOID(jsAccessibilityManager);
4770 auto webPattern = web.Upgrade();
4771 CHECK_NULL_VOID(webPattern);
4772 ACE_SCOPED_TRACE("SearchWebElementInfoByAccessibilityId");
4773 jsAccessibilityManager->SearchWebElementInfoByAccessibilityId(
4774 splitElementId, requestId, callback, realMode, windowId, webPattern);
4775 },
4776 TaskExecutor::TaskType::UI, "ArkWebAccessibilitySearchElementInfoById");
4777 }
4778
SearchElementInfosByText(const int64_t elementId,const std::string & text,const int32_t requestId,Accessibility::AccessibilityElementOperatorCallback & callback)4779 void JsAccessibilityManager::WebInteractionOperation::SearchElementInfosByText(const int64_t elementId,
4780 const std::string& text, const int32_t requestId, Accessibility::AccessibilityElementOperatorCallback& callback)
4781 {
4782 }
4783
SearchDefaultFocusByWindowId(const int32_t windowId,const int32_t requestId,Accessibility::AccessibilityElementOperatorCallback & callback,const int32_t pageId)4784 void JsAccessibilityManager::WebInteractionOperation::SearchDefaultFocusByWindowId(const int32_t windowId,
4785 const int32_t requestId, Accessibility::AccessibilityElementOperatorCallback &callback, const int32_t pageId)
4786 {
4787 }
4788
FindFocusedElementInfo(const int64_t elementId,const int32_t focusType,const int32_t requestId,Accessibility::AccessibilityElementOperatorCallback & callback)4789 void JsAccessibilityManager::WebInteractionOperation::FindFocusedElementInfo(const int64_t elementId,
4790 const int32_t focusType, const int32_t requestId, Accessibility::AccessibilityElementOperatorCallback& callback)
4791 {
4792 TAG_LOGD(AceLogTag::ACE_WEB, "find focus: %{public}" PRId64 ", focusType: %{public}d",
4793 elementId, focusType);
4794 int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
4795 int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
4796 AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
4797
4798 auto jsAccessibilityManager = GetHandler().Upgrade();
4799 CHECK_NULL_VOID(jsAccessibilityManager);
4800 auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
4801 CHECK_NULL_VOID(context);
4802 auto windowId = windowId_;
4803 auto web = webPattern_;
4804 context->GetTaskExecutor()->PostTask(
4805 [weak = GetHandler(), splitElementId, focusType, requestId, &callback, windowId, web]() {
4806 auto jsAccessibilityManager = weak.Upgrade();
4807 CHECK_NULL_VOID(jsAccessibilityManager);
4808 auto webPattern = web.Upgrade();
4809 CHECK_NULL_VOID(webPattern);
4810 ACE_SCOPED_TRACE("FindWebFocusedElementInfo");
4811 jsAccessibilityManager->FindWebFocusedElementInfo(
4812 splitElementId, focusType, requestId, callback, windowId, webPattern);
4813 },
4814 TaskExecutor::TaskType::UI, "ArkWebFindFocusedElementInfo");
4815 }
4816
FocusMoveSearch(const int64_t elementId,const int32_t direction,const int32_t requestId,Accessibility::AccessibilityElementOperatorCallback & callback)4817 void JsAccessibilityManager::WebInteractionOperation::FocusMoveSearch(const int64_t elementId, const int32_t direction,
4818 const int32_t requestId, Accessibility::AccessibilityElementOperatorCallback& callback)
4819 {
4820 TAG_LOGD(AceLogTag::ACE_WEB, "move search: %{public}" PRId64 ", direction: %{public}d",
4821 elementId, direction);
4822 int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
4823 int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
4824 AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
4825
4826 auto jsAccessibilityManager = GetHandler().Upgrade();
4827 CHECK_NULL_VOID(jsAccessibilityManager);
4828 auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
4829 CHECK_NULL_VOID(context);
4830 auto windowId = windowId_;
4831 auto web = webPattern_;
4832 context->GetTaskExecutor()->PostTask(
4833 [weak = GetHandler(), splitElementId, direction, requestId, &callback, windowId, web] {
4834 auto jsAccessibilityManager = weak.Upgrade();
4835 CHECK_NULL_VOID(jsAccessibilityManager);
4836 auto webPattern = web.Upgrade();
4837 CHECK_NULL_VOID(webPattern);
4838 ACE_SCOPED_TRACE("FocusMoveSearch");
4839 jsAccessibilityManager->WebFocusMoveSearch(splitElementId, direction, requestId, callback,
4840 windowId, webPattern);
4841 },
4842 TaskExecutor::TaskType::UI, "ArkWebFocusMoveSearch");
4843 }
4844
ExecuteAction(const int64_t elementId,const int32_t action,const std::map<std::string,std::string> & actionArguments,const int32_t requestId,Accessibility::AccessibilityElementOperatorCallback & callback)4845 void JsAccessibilityManager::WebInteractionOperation::ExecuteAction(const int64_t elementId, const int32_t action,
4846 const std::map<std::string, std::string>& actionArguments, const int32_t requestId,
4847 Accessibility::AccessibilityElementOperatorCallback& callback)
4848 {
4849 TAG_LOGD(AceLogTag::ACE_WEB, "elementId: %{public}" PRId64 ", action: %{public}d", elementId, action);
4850 int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
4851 int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
4852 AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
4853
4854 auto jsAccessibilityManager = GetHandler().Upgrade();
4855 CHECK_NULL_VOID(jsAccessibilityManager);
4856 auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
4857 CHECK_NULL_VOID(context);
4858 auto actionInfo = static_cast<ActionType>(action);
4859 ActionParam param { actionInfo, actionArguments };
4860 auto windowId = windowId_;
4861 auto web = webPattern_;
4862 context->GetTaskExecutor()->PostTask(
4863 [weak = GetHandler(), splitElementId, param, requestId, &callback, windowId, web] {
4864 auto jsAccessibilityManager = weak.Upgrade();
4865 CHECK_NULL_VOID(jsAccessibilityManager);
4866 auto webPattern = web.Upgrade();
4867 CHECK_NULL_VOID(webPattern);
4868 ACE_SCOPED_TRACE("ExecuteAction");
4869 jsAccessibilityManager->ExecuteWebAction(splitElementId, param, requestId, callback, windowId, webPattern);
4870 },
4871 TaskExecutor::TaskType::UI, "ArkWebAccessibilityExecuteAction");
4872 }
4873
ClearFocus()4874 void JsAccessibilityManager::WebInteractionOperation::ClearFocus() {}
4875
SetChildTreeIdAndWinId(const int64_t nodeId,const int32_t treeId,const int32_t childWindowId)4876 void JsAccessibilityManager::WebInteractionOperation::SetChildTreeIdAndWinId(const int64_t nodeId, const int32_t treeId,
4877 const int32_t childWindowId) {}
4878
SetBelongTreeId(const int32_t treeId)4879 void JsAccessibilityManager::WebInteractionOperation::SetBelongTreeId(const int32_t treeId) {}
4880
GetCursorPosition(const int64_t elementId,const int32_t requestId,AccessibilityElementOperatorCallback & callback)4881 void JsAccessibilityManager::WebInteractionOperation::GetCursorPosition(
4882 const int64_t elementId, const int32_t requestId, AccessibilityElementOperatorCallback& callback)
4883 {
4884 TAG_LOGD(AceLogTag::ACE_WEB, "GetCursorPosition id: %{public}" PRId64, elementId);
4885 int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
4886 int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
4887 AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
4888
4889 auto jsAccessibilityManager = GetHandler().Upgrade();
4890 CHECK_NULL_VOID(jsAccessibilityManager);
4891 auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
4892 CHECK_NULL_VOID(context);
4893 auto web = webPattern_;
4894 context->GetTaskExecutor()->PostTask(
4895 [weak = GetHandler(), splitElementId, requestId, &callback, web]() {
4896 auto jsAccessibilityManager = weak.Upgrade();
4897 CHECK_NULL_VOID(jsAccessibilityManager);
4898 auto webPattern = web.Upgrade();
4899 CHECK_NULL_VOID(webPattern);
4900 ACE_SCOPED_TRACE("GetWebCursorPosition");
4901 jsAccessibilityManager->GetWebCursorPosition(splitElementId, requestId, callback, webPattern);
4902 },
4903
4904 TaskExecutor::TaskType::UI, "GetWebCursorPosition");
4905 }
4906
OutsideTouch()4907 void JsAccessibilityManager::WebInteractionOperation::OutsideTouch() {}
4908 #endif
4909
SearchElementInfoByAccessibilityId(const int64_t elementId,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t mode,const int32_t windowId)4910 void JsAccessibilityManager::SearchElementInfoByAccessibilityId(const int64_t elementId, const int32_t requestId,
4911 AccessibilityElementOperatorCallback& callback, const int32_t mode, const int32_t windowId)
4912 {
4913 std::list<AccessibilityElementInfo> infos;
4914
4915 auto pipeline = GetPipelineByWindowId(windowId);
4916 if (pipeline) {
4917 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipeline);
4918 if (ngPipeline) {
4919 SearchElementInfoByAccessibilityIdNG(elementId, mode, infos, pipeline, NG::UI_EXTENSION_OFFSET_MAX);
4920 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY,
4921 "SearchElementInfoByAccessibilityIdNG info size: %{public}zu, elementId: %{public}" PRId64,
4922 infos.size(), elementId);
4923 SetSearchElementInfoByAccessibilityIdResult(callback, std::move(infos), requestId);
4924 return;
4925 }
4926 }
4927
4928 int64_t nodeId = elementId;
4929 if (elementId == -1) {
4930 nodeId = 0;
4931 }
4932 auto weak = WeakClaim(this);
4933 auto jsAccessibilityManager = weak.Upgrade();
4934 CHECK_NULL_VOID(jsAccessibilityManager);
4935 auto node = jsAccessibilityManager->GetAccessibilityNodeFromPage(nodeId);
4936 if (!node) {
4937 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY,
4938 "SearchElementInfoByAccessibilityIdNG info size: %{public}zu, elementId: %{public}" PRId64,
4939 infos.size(), elementId);
4940 SetSearchElementInfoByAccessibilityIdResult(callback, std::move(infos), requestId);
4941 return;
4942 }
4943
4944 AccessibilityElementInfo nodeInfo;
4945 UpdateAccessibilityNodeInfo(node, nodeInfo, jsAccessibilityManager, jsAccessibilityManager->windowId_);
4946 infos.push_back(nodeInfo);
4947 // cache parent/siblings/children infos
4948 UpdateCacheInfo(infos, mode, node, jsAccessibilityManager, jsAccessibilityManager->windowId_);
4949 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY,
4950 "SearchElementInfoByAccessibilityIdNG info size: %{public}zu, elementId: %{public}" PRId64,
4951 infos.size(), elementId);
4952 SetSearchElementInfoByAccessibilityIdResult(callback, std::move(infos), requestId);
4953 }
4954
SearchElementInfoByAccessibilityIdNG(int64_t elementId,int32_t mode,std::list<AccessibilityElementInfo> & infos,const RefPtr<PipelineBase> & context,int64_t uiExtensionOffset)4955 void JsAccessibilityManager::SearchElementInfoByAccessibilityIdNG(int64_t elementId, int32_t mode,
4956 std::list<AccessibilityElementInfo>& infos, const RefPtr<PipelineBase>& context, int64_t uiExtensionOffset)
4957 {
4958 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "elementId: %{public}" PRId64 ", treeId: %{public}d, mode: %{public}d",
4959 elementId, treeId_, mode);
4960 auto mainContext = context_.Upgrade();
4961 CHECK_NULL_VOID(mainContext);
4962
4963 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
4964 CHECK_NULL_VOID(ngPipeline);
4965 auto rootNode = ngPipeline->GetRootElement();
4966 CHECK_NULL_VOID(rootNode);
4967
4968 AccessibilityElementInfo nodeInfo;
4969 int64_t nodeId = elementId;
4970 if (elementId == -1) {
4971 nodeId = rootNode->GetAccessibilityId();
4972 }
4973
4974 #ifdef WINDOW_SCENE_SUPPORTED
4975 auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
4976 CHECK_NULL_VOID(uiExtensionManager);
4977 if (uiExtensionManager->IsWrapExtensionAbilityId(nodeId)) {
4978 SearchParameter param {nodeId, "", mode, uiExtensionOffset};
4979 return SearchExtensionElementInfoByAccessibilityIdNG(param, rootNode, infos, context, ngPipeline);
4980 }
4981 #endif
4982
4983 auto node = GetFramenodeByAccessibilityId(rootNode, nodeId);
4984 CHECK_NULL_VOID(node);
4985 CommonProperty commonProperty;
4986 GenerateCommonProperty(ngPipeline, commonProperty, mainContext, node);
4987 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY,
4988 "windowId: %{public}d, windowLeft: %{public}d, "
4989 "windowTop: %{public}d",
4990 commonProperty.windowId, commonProperty.windowLeft, commonProperty.windowTop);
4991 UpdateAccessibilityElementInfo(node, commonProperty, nodeInfo, ngPipeline);
4992 SetRootAccessibilityVisible(node, nodeInfo);
4993 SetRootAccessibilityNextFocusId(node, rootNode, nodeInfo);
4994 SetRootAccessibilityPreFocusId(node, rootNode, nodeInfo);
4995 if (IsExtensionComponent(node) && !IsUIExtensionShowPlaceholder(node)) {
4996 SearchParameter param {-1, "", mode, uiExtensionOffset};
4997 SearchExtensionElementInfoNG(param, node, infos, nodeInfo);
4998 }
4999 infos.push_back(nodeInfo);
5000 SearchParameter param {nodeId, "", mode, uiExtensionOffset};
5001 UpdateCacheInfoNG(infos, node, commonProperty, ngPipeline, param);
5002 SortExtensionAccessibilityInfo(infos, nodeInfo.GetAccessibilityId());
5003 if ((infos.size() > 0) && (uiExtensionOffset != NG::UI_EXTENSION_OFFSET_MAX) &&
5004 (infos.front().GetComponentType() != V2::ROOT_ETS_TAG) &&
5005 (infos.front().GetParentNodeId() == rootNode->GetAccessibilityId())) {
5006 infos.front().SetParent(NG::UI_EXTENSION_ROOT_ID);
5007 }
5008 }
5009
SearchExtensionElementInfoByAccessibilityIdNG(const SearchParameter & searchParam,const RefPtr<NG::FrameNode> & node,std::list<Accessibility::AccessibilityElementInfo> & infos,const RefPtr<PipelineBase> & context,const RefPtr<NG::PipelineContext> & ngPipeline)5010 void JsAccessibilityManager::SearchExtensionElementInfoByAccessibilityIdNG(const SearchParameter& searchParam,
5011 const RefPtr<NG::FrameNode>& node, std::list<Accessibility::AccessibilityElementInfo>& infos,
5012 const RefPtr<PipelineBase>& context, const RefPtr<NG::PipelineContext>& ngPipeline)
5013 {
5014 #ifdef WINDOW_SCENE_SUPPORTED
5015 auto mainContext = context_.Upgrade();
5016 CHECK_NULL_VOID(mainContext);
5017 auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
5018 CHECK_NULL_VOID(uiExtensionManager);
5019 auto unWrapIdPair = uiExtensionManager->UnWrapExtensionAbilityId(searchParam.uiExtensionOffset, searchParam.nodeId);
5020 int64_t childWrapId = unWrapIdPair.second;
5021 int64_t uiExtensionId = unWrapIdPair.first;
5022 auto uiExtensionNode = FindNodeFromRootByExtensionId(node, uiExtensionId);
5023 CHECK_NULL_VOID(uiExtensionNode);
5024 SearchParameter param {childWrapId, "", searchParam.mode, searchParam.uiExtensionOffset};
5025 AccessibilityElementInfo nodeInfo;
5026 CommonProperty commonProperty;
5027 GenerateCommonProperty(ngPipeline, commonProperty, mainContext, uiExtensionNode);
5028 UpdateAccessibilityElementInfo(uiExtensionNode, commonProperty, nodeInfo, ngPipeline);
5029 SearchExtensionElementInfoNG(param, uiExtensionNode, infos, nodeInfo);
5030 #endif
5031 }
5032
SearchElementInfosByTextNG(int64_t elementId,const std::string & text,const RefPtr<NG::FrameNode> & node,int64_t offset)5033 std::list<AccessibilityElementInfo> JsAccessibilityManager::SearchElementInfosByTextNG(
5034 int64_t elementId, const std::string& text, const RefPtr<NG::FrameNode>& node, int64_t offset)
5035 {
5036 std::list<AccessibilityElementInfo> extensionElementInfo;
5037 if (NG::UI_EXTENSION_OFFSET_MIN < (offset + 1)) {
5038 node->SearchElementInfosByTextNG(elementId, text, offset, extensionElementInfo);
5039 }
5040 return extensionElementInfo;
5041 }
5042
SearchElementInfosByTextNG(const SearchParameter & searchParam,const RefPtr<NG::FrameNode> & node,std::list<Accessibility::AccessibilityElementInfo> & infos,const RefPtr<PipelineBase> & context,const RefPtr<NG::PipelineContext> & ngPipeline)5043 void JsAccessibilityManager::SearchElementInfosByTextNG(const SearchParameter& searchParam,
5044 const RefPtr<NG::FrameNode>& node, std::list<Accessibility::AccessibilityElementInfo>& infos,
5045 const RefPtr<PipelineBase>& context, const RefPtr<NG::PipelineContext>& ngPipeline)
5046 {
5047 #ifdef WINDOW_SCENE_SUPPORTED
5048 auto mainContext = context_.Upgrade();
5049 CHECK_NULL_VOID(mainContext);
5050 auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
5051 CHECK_NULL_VOID(uiExtensionManager);
5052 auto unWrapIdPair = uiExtensionManager->UnWrapExtensionAbilityId(searchParam.uiExtensionOffset, searchParam.nodeId);
5053 int64_t childWrapId = unWrapIdPair.second;
5054 int64_t uiExtensionId = unWrapIdPair.first;
5055 std::list<AccessibilityElementInfo> extensionElementInfos;
5056 AccessibilityElementInfo nodeInfo;
5057 auto uiExtensionNode = FindNodeFromRootByExtensionId(node, uiExtensionId);
5058 CHECK_NULL_VOID(uiExtensionNode);
5059
5060 extensionElementInfos = SearchElementInfosByTextNG(
5061 childWrapId, searchParam.text, uiExtensionNode, searchParam.uiExtensionOffset / NG::UI_EXTENSION_ID_FACTOR);
5062 if (extensionElementInfos.empty()) {
5063 return;
5064 }
5065 CommonProperty commonProperty;
5066 GenerateCommonProperty(ngPipeline, commonProperty, mainContext, uiExtensionNode);
5067 UpdateAccessibilityElementInfo(uiExtensionNode, commonProperty, nodeInfo, ngPipeline);
5068 SetRootAccessibilityVisible(node, nodeInfo);
5069
5070 auto rootNode = ngPipeline->GetRootElement();
5071 CHECK_NULL_VOID(rootNode);
5072 SetRootAccessibilityNextFocusId(node, rootNode, nodeInfo);
5073 SetRootAccessibilityPreFocusId(node, rootNode, nodeInfo);
5074 ConvertExtensionAccessibilityNodeId(extensionElementInfos, uiExtensionNode,
5075 searchParam.uiExtensionOffset, nodeInfo);
5076 for (auto& info : extensionElementInfos) {
5077 infos.emplace_back(info);
5078 }
5079 #endif
5080 }
5081
FindNodeFromRootByExtensionId(const RefPtr<NG::FrameNode> & root,const int64_t uiExtensionId)5082 RefPtr<NG::FrameNode> JsAccessibilityManager::FindNodeFromRootByExtensionId(
5083 const RefPtr<NG::FrameNode>& root, const int64_t uiExtensionId)
5084 {
5085 CHECK_NULL_RETURN(root, nullptr);
5086 std::queue<RefPtr<NG::UINode>> nodes;
5087 nodes.push(root);
5088 RefPtr<NG::FrameNode> frameNode;
5089 while (!nodes.empty()) {
5090 auto current = nodes.front();
5091 nodes.pop();
5092 frameNode = AceType::DynamicCast<NG::FrameNode>(current);
5093 if (IsExtensionComponent(frameNode) && !IsUIExtensionShowPlaceholder(frameNode) &&
5094 (uiExtensionId == frameNode->GetUiExtensionId())) {
5095 return frameNode;
5096 }
5097 const auto& children = current->GetChildren(true);
5098 for (const auto& child : children) {
5099 nodes.push(child);
5100 }
5101 }
5102 return nullptr;
5103 }
5104
SearchElementInfosByTextNG(int64_t elementId,const std::string & text,std::list<Accessibility::AccessibilityElementInfo> & infos,const RefPtr<PipelineBase> & context,int64_t uiExtensionOffset)5105 void JsAccessibilityManager::SearchElementInfosByTextNG(int64_t elementId, const std::string& text,
5106 std::list<Accessibility::AccessibilityElementInfo>& infos, const RefPtr<PipelineBase>& context,
5107 int64_t uiExtensionOffset)
5108 {
5109 auto mainContext = context_.Upgrade();
5110 CHECK_NULL_VOID(mainContext);
5111 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
5112 CHECK_NULL_VOID(ngPipeline);
5113 auto rootNode = ngPipeline->GetRootElement();
5114 CHECK_NULL_VOID(rootNode);
5115 #ifdef WINDOW_SCENE_SUPPORTED
5116 auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
5117 CHECK_NULL_VOID(uiExtensionManager);
5118 if (uiExtensionManager->IsWrapExtensionAbilityId(elementId)) {
5119 SearchParameter param {elementId, text, 0, uiExtensionOffset};
5120 SearchElementInfosByTextNG(param, rootNode, infos, context, ngPipeline);
5121 return;
5122 }
5123 #endif
5124 if (elementId == NG::UI_EXTENSION_ROOT_ID) {
5125 elementId = rootNode->GetAccessibilityId();
5126 }
5127 auto node = GetFramenodeByAccessibilityId(rootNode, elementId);
5128 CHECK_NULL_VOID(node);
5129 CommonProperty commonProperty;
5130 GenerateCommonProperty(ngPipeline, commonProperty, mainContext, node);
5131 nlohmann::json textJson = nlohmann::json::parse(text, nullptr, false);
5132 if (textJson.is_null() || textJson.is_discarded() || !textJson.contains("type")) {
5133 return;
5134 }
5135 if (textJson["type"] == "textType") {
5136 SearchParameter param {0, text, 0, uiExtensionOffset};
5137 FindTextByTextHint(node, infos, ngPipeline, commonProperty, param);
5138 return;
5139 }
5140 if (!textJson.contains("value")) {
5141 return;
5142 }
5143 SearchParameter param {0, textJson["value"], 0, uiExtensionOffset};
5144 FindText(node, infos, ngPipeline, commonProperty, param);
5145 }
5146
SearchElementInfosByText(const int64_t elementId,const std::string & text,const int32_t requestId,AccessibilityElementOperatorCallback & callback)5147 void JsAccessibilityManager::JsInteractionOperation::SearchElementInfosByText(const int64_t elementId,
5148 const std::string& text, const int32_t requestId, AccessibilityElementOperatorCallback& callback)
5149 {
5150 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "search by text: %{public}" PRId64 ", text: %{public}s",
5151 elementId, text.c_str());
5152 int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
5153 int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
5154 AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
5155
5156 if (text.empty()) {
5157 return;
5158 }
5159 auto jsAccessibilityManager = GetHandler().Upgrade();
5160 CHECK_NULL_VOID(jsAccessibilityManager);
5161 auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
5162 CHECK_NULL_VOID(context);
5163 auto windowId = windowId_;
5164 if (context) {
5165 context->GetTaskExecutor()->PostTask(
5166 [weak = GetHandler(), splitElementId, text, requestId, &callback, windowId]() {
5167 auto jsAccessibilityManager = weak.Upgrade();
5168 CHECK_NULL_VOID(jsAccessibilityManager);
5169 ACE_SCOPED_TRACE("SearchElementInfosByText");
5170 jsAccessibilityManager->SearchElementInfosByText(
5171 splitElementId, text, requestId, callback, windowId);
5172 },
5173 TaskExecutor::TaskType::UI, "ArkUIAccessibilitySearchElementInfoByText");
5174 }
5175 }
5176
SearchElementInfosByText(const int64_t elementId,const std::string & text,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t windowId)5177 void JsAccessibilityManager::SearchElementInfosByText(const int64_t elementId, const std::string& text,
5178 const int32_t requestId, AccessibilityElementOperatorCallback& callback, const int32_t windowId)
5179 {
5180 if (text.empty()) {
5181 return;
5182 }
5183
5184 if (elementId == -1) {
5185 return;
5186 }
5187
5188 std::list<AccessibilityElementInfo> infos;
5189
5190 auto pipeline = GetPipelineByWindowId(windowId);
5191 if (pipeline) {
5192 if (AceType::InstanceOf<NG::PipelineContext>(pipeline)) {
5193 SearchElementInfosByTextNG(elementId, text, infos, pipeline, NG::UI_EXTENSION_OFFSET_MAX);
5194 SetSearchElementInfoByTextResult(callback, std::move(infos), requestId);
5195 return;
5196 }
5197 }
5198
5199 auto weak = WeakClaim(this);
5200 auto jsAccessibilityManager = weak.Upgrade();
5201 CHECK_NULL_VOID(jsAccessibilityManager);
5202 int64_t nodeId = elementId;
5203 auto node = jsAccessibilityManager->GetAccessibilityNodeFromPage(nodeId);
5204 CHECK_NULL_VOID(node);
5205 std::list<RefPtr<AccessibilityNode>> nodeList;
5206 OHOS::Ace::Framework::FindText(node, text, nodeList);
5207 if (!nodeList.empty()) {
5208 for (const auto& node : nodeList) {
5209 AccessibilityElementInfo nodeInfo;
5210 UpdateAccessibilityNodeInfo(node, nodeInfo, jsAccessibilityManager, jsAccessibilityManager->windowId_);
5211 infos.emplace_back(nodeInfo);
5212 }
5213 }
5214
5215 SetSearchElementInfoByTextResult(callback, std::move(infos), requestId);
5216 }
5217
SearchDefaultFocusByWindowId(const int32_t windowId,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t pageId)5218 void JsAccessibilityManager::JsInteractionOperation::SearchDefaultFocusByWindowId(const int32_t windowId,
5219 const int32_t requestId, AccessibilityElementOperatorCallback& callback, const int32_t pageId)
5220 {
5221 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "search by windowId: %{public}d, pageId: %{public}d.", windowId, pageId);
5222
5223 auto jsAccessibilityManager = GetHandler().Upgrade();
5224 CHECK_NULL_VOID(jsAccessibilityManager);
5225 auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
5226 CHECK_NULL_VOID(context);
5227 context->GetTaskExecutor()->PostTask(
5228 [weak = GetHandler(), windowId, pageId, requestId, &callback]() {
5229 auto jsAccessibilityManager = weak.Upgrade();
5230 CHECK_NULL_VOID(jsAccessibilityManager);
5231 ACE_SCOPED_TRACE("SearchDefaultFocusByWindowId");
5232 jsAccessibilityManager->SearchDefaultFocusByWindowId(
5233 windowId, pageId, requestId, callback);
5234 },
5235 TaskExecutor::TaskType::UI, "ArkUIAccessibilitySearchDefaultFocusByWindowId");
5236 }
5237
SearchDefaultFocusByWindowId(const int32_t windowId,int32_t pageId,const int32_t requestId,AccessibilityElementOperatorCallback & callback)5238 void JsAccessibilityManager::SearchDefaultFocusByWindowId(const int32_t windowId, int32_t pageId,
5239 const int32_t requestId, AccessibilityElementOperatorCallback& callback)
5240 {
5241 std::list<AccessibilityElementInfo> infos;
5242
5243 auto pipeline = GetPipelineByWindowId(windowId);
5244 if (pipeline) {
5245 UpdatePageId(pipeline, pageId);
5246 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipeline);
5247 if (ngPipeline) {
5248 SearchDefaultFocusByWindowIdNG(pageId, infos, pipeline);
5249 SetSearchDefaultFocusByWindowIdResult(callback, std::move(infos), requestId);
5250 return;
5251 }
5252 }
5253
5254 auto defaultFocusNodeList = GetDefaultFocusList();
5255 for (const auto& defaultFocusNode : defaultFocusNodeList) {
5256 auto frameNode = defaultFocusNode.Upgrade();
5257 if (frameNode && (frameNode->GetPageId() == pageId || pageId == -1)) {
5258 auto node = GetAccessibilityNodeFromPage(frameNode->GetAccessibilityId());
5259 CHECK_NULL_CONTINUE(node);
5260 AccessibilityElementInfo nodeInfo;
5261 UpdateAccessibilityNodeInfo(node, nodeInfo, Claim(this), windowId_);
5262 infos.emplace_back(nodeInfo);
5263 }
5264 }
5265 SetSearchDefaultFocusByWindowIdResult(callback, std::move(infos), requestId);
5266 }
5267
SearchDefaultFocusByWindowIdNG(const int32_t pageId,std::list<Accessibility::AccessibilityElementInfo> & infos,const RefPtr<PipelineBase> & context)5268 void JsAccessibilityManager::SearchDefaultFocusByWindowIdNG(const int32_t pageId,
5269 std::list<Accessibility::AccessibilityElementInfo>& infos, const RefPtr<PipelineBase>& context)
5270 {
5271 auto mainContext = context_.Upgrade();
5272 CHECK_NULL_VOID(mainContext);
5273 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
5274 CHECK_NULL_VOID(ngPipeline);
5275
5276 for (const auto& defaultFocusNode : defaultFocusList_) {
5277 auto node = defaultFocusNode.Upgrade();
5278 if (node && (node->GetPageId() == pageId || pageId == -1)) {
5279 AccessibilityElementInfo nodeInfo;
5280
5281 CommonProperty commonProperty;
5282 GenerateCommonProperty(ngPipeline, commonProperty, mainContext, node);
5283 UpdateAccessibilityElementInfo(node, commonProperty, nodeInfo, ngPipeline);
5284 infos.emplace_back(nodeInfo);
5285 }
5286 }
5287 }
5288
FindFocusedElementInfo(const int64_t elementId,const int32_t focusType,const int32_t requestId,AccessibilityElementOperatorCallback & callback)5289 void JsAccessibilityManager::JsInteractionOperation::FindFocusedElementInfo(const int64_t elementId,
5290 const int32_t focusType, const int32_t requestId, AccessibilityElementOperatorCallback& callback)
5291 {
5292 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "find focus: %{public}" PRId64 ", focusType: %{public}d",
5293 elementId, focusType);
5294 int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
5295 int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
5296 AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
5297
5298 auto jsAccessibilityManager = GetHandler().Upgrade();
5299 CHECK_NULL_VOID(jsAccessibilityManager);
5300 auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
5301 CHECK_NULL_VOID(context);
5302 auto windowId = windowId_;
5303 context->GetTaskExecutor()->PostTask(
5304 [weak = GetHandler(), splitElementId, focusType, requestId, &callback, windowId]() {
5305 auto jsAccessibilityManager = weak.Upgrade();
5306 CHECK_NULL_VOID(jsAccessibilityManager);
5307 ACE_SCOPED_TRACE("FindFocusedElementInfo");
5308 jsAccessibilityManager->FindFocusedElementInfo(splitElementId, focusType, requestId, callback, windowId);
5309 },
5310 TaskExecutor::TaskType::UI, "ArkUIAccessibilityFindFocusedElementInfo");
5311 }
5312
FindFocusedElementInfo(const int64_t elementId,const int32_t focusType,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t windowId)5313 void JsAccessibilityManager::FindFocusedElementInfo(const int64_t elementId, const int32_t focusType,
5314 const int32_t requestId, AccessibilityElementOperatorCallback& callback, const int32_t windowId)
5315 {
5316 AccessibilityElementInfo nodeInfo;
5317 if (focusType != FOCUS_TYPE_INPUT && focusType != FOCUS_TYPE_ACCESSIBILITY) {
5318 nodeInfo.SetValidElement(false);
5319 SetFindFocusedElementInfoResult(callback, nodeInfo, requestId);
5320 return;
5321 }
5322
5323 auto context = GetPipelineByWindowId(windowId);
5324 if (!context) {
5325 SetFindFocusedElementInfoResult(callback, nodeInfo, requestId);
5326 return;
5327 }
5328
5329 if (AceType::InstanceOf<NG::PipelineContext>(context)) {
5330 FindFocusedElementInfoNG(elementId, focusType, nodeInfo, context, NG::UI_EXTENSION_OFFSET_MAX);
5331 SetFindFocusedElementInfoResult(callback, nodeInfo, requestId);
5332 return;
5333 }
5334
5335 int64_t nodeId = static_cast<int64_t>(elementId);
5336 if (elementId == -1) {
5337 nodeId = 0;
5338 }
5339
5340 auto node = GetAccessibilityNodeFromPage(nodeId);
5341 if (!node) {
5342 nodeInfo.SetValidElement(false);
5343 SetFindFocusedElementInfoResult(callback, nodeInfo, requestId);
5344 return;
5345 }
5346
5347 RefPtr<AccessibilityNode> resultNode = nullptr;
5348 bool status = false;
5349 if (focusType == FOCUS_TYPE_ACCESSIBILITY) {
5350 status = FindAccessibilityFocus(node, resultNode);
5351 }
5352 if (focusType == FOCUS_TYPE_INPUT) {
5353 status = FindInputFocus(node, resultNode);
5354 }
5355
5356 if ((status) && (resultNode != nullptr)) {
5357 UpdateAccessibilityNodeInfo(resultNode, nodeInfo, Claim(this), windowId_);
5358 }
5359
5360 SetFindFocusedElementInfoResult(callback, nodeInfo, requestId);
5361 }
5362
FindFocusedElementInfoNG(int64_t elementId,int32_t focusType,Accessibility::AccessibilityElementInfo & info,const RefPtr<PipelineBase> & context,const int64_t uiExtensionOffset)5363 void JsAccessibilityManager::FindFocusedElementInfoNG(int64_t elementId, int32_t focusType,
5364 Accessibility::AccessibilityElementInfo& info, const RefPtr<PipelineBase>& context,
5365 const int64_t uiExtensionOffset)
5366 {
5367 auto mainContext = context_.Upgrade();
5368 CHECK_NULL_VOID(mainContext);
5369 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
5370 CHECK_NULL_VOID(ngPipeline);
5371 auto rootNode = ngPipeline->GetRootElement();
5372 CHECK_NULL_VOID(rootNode);
5373 #ifdef WINDOW_SCENE_SUPPORTED
5374 auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
5375 CHECK_NULL_VOID(uiExtensionManager);
5376 if (uiExtensionManager->IsWrapExtensionAbilityId(elementId)) {
5377 SearchParameter param {elementId, "", focusType, uiExtensionOffset};
5378 return FindFocusedExtensionElementInfoNG(param, info, context, rootNode);
5379 }
5380 #endif
5381 int64_t nodeId = elementId;
5382 if (elementId == -1) {
5383 nodeId = rootNode->GetAccessibilityId();
5384 }
5385 auto node = GetFramenodeByAccessibilityId(rootNode, nodeId);
5386 if (!node) {
5387 return info.SetValidElement(false);
5388 }
5389 if (IsExtensionComponent(node) && !IsUIExtensionShowPlaceholder(node)) {
5390 SearchParameter transferSearchParam {NG::UI_EXTENSION_ROOT_ID, "", focusType, uiExtensionOffset};
5391 OHOS::Ace::Framework::FindFocusedExtensionElementInfoNG(transferSearchParam, node, info);
5392 return SetUiExtensionAbilityParentIdForFocus(node, uiExtensionOffset, info);
5393 }
5394 RefPtr<NG::FrameNode> resultNode;
5395 if (focusType == FOCUS_TYPE_ACCESSIBILITY) {
5396 resultNode = FindAccessibilityFocus(node, focusType, info, uiExtensionOffset, context, currentFocusNodeId_);
5397 }
5398 if (focusType == FOCUS_TYPE_INPUT) {
5399 resultNode = FindInputFocus(node, focusType, info, uiExtensionOffset, context);
5400 }
5401 if ((!resultNode) || (IsExtensionComponent(resultNode) && !IsUIExtensionShowPlaceholder(resultNode))) {
5402 return;
5403 }
5404 CommonProperty commonProperty;
5405 GenerateCommonProperty(ngPipeline, commonProperty, mainContext, resultNode);
5406 UpdateAccessibilityElementInfo(resultNode, commonProperty, info, ngPipeline);
5407 UpdateUiExtensionParentIdForFocus(rootNode, uiExtensionOffset, info);
5408 }
5409
FindFocusedExtensionElementInfoNG(const SearchParameter & searchParam,Accessibility::AccessibilityElementInfo & info,const RefPtr<PipelineBase> & context,const RefPtr<NG::FrameNode> & root)5410 void JsAccessibilityManager::FindFocusedExtensionElementInfoNG(const SearchParameter& searchParam,
5411 Accessibility::AccessibilityElementInfo& info,
5412 const RefPtr<PipelineBase>& context, const RefPtr<NG::FrameNode>& root)
5413 {
5414 #ifdef WINDOW_SCENE_SUPPORTED
5415 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
5416 CHECK_NULL_VOID(ngPipeline);
5417 auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
5418 CHECK_NULL_VOID(uiExtensionManager);
5419 auto elementIdPair = uiExtensionManager->UnWrapExtensionAbilityId(searchParam.uiExtensionOffset,
5420 searchParam.nodeId);
5421 auto uiExtensionNode = uiExtensionManager->GetFocusUiExtensionNode();
5422 CHECK_NULL_VOID(uiExtensionNode);
5423 SearchParameter transferSearchParam {elementIdPair.second, "",
5424 searchParam.mode, searchParam.uiExtensionOffset};
5425 OHOS::Ace::Framework::FindFocusedExtensionElementInfoNG(transferSearchParam, uiExtensionNode, info);
5426 SetUiExtensionAbilityParentIdForFocus(uiExtensionNode, searchParam.uiExtensionOffset, info);
5427 #endif
5428 }
5429
FindNodeFromPipeline(const WeakPtr<PipelineBase> & context,const int64_t elementId)5430 RefPtr<NG::FrameNode> JsAccessibilityManager::FindNodeFromPipeline(
5431 const WeakPtr<PipelineBase>& context, const int64_t elementId)
5432 {
5433 auto pipeline = context.Upgrade();
5434 CHECK_NULL_RETURN(pipeline, nullptr);
5435
5436 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipeline);
5437 auto rootNode = ngPipeline->GetRootElement();
5438 CHECK_NULL_RETURN(rootNode, nullptr);
5439
5440 int64_t nodeId = elementId;
5441 // accessibility use -1 for first search to get root node
5442 if (elementId == -1) {
5443 nodeId = rootNode->GetAccessibilityId();
5444 }
5445
5446 auto node = GetFramenodeByAccessibilityId(rootNode, nodeId);
5447 if (node) {
5448 return node;
5449 }
5450 return nullptr;
5451 }
5452
FindPipelineByElementId(const int64_t elementId,RefPtr<NG::FrameNode> & node)5453 RefPtr<NG::PipelineContext> JsAccessibilityManager::FindPipelineByElementId(
5454 const int64_t elementId, RefPtr<NG::FrameNode>& node)
5455 {
5456 node = FindNodeFromPipeline(context_, elementId);
5457 if (node) {
5458 auto context = AceType::DynamicCast<NG::PipelineContext>(context_.Upgrade());
5459 return context;
5460 }
5461 for (auto subContext : GetSubPipelineContexts()) {
5462 node = FindNodeFromPipeline(subContext, elementId);
5463 if (node) {
5464 auto context = AceType::DynamicCast<NG::PipelineContext>(subContext.Upgrade());
5465 return context;
5466 }
5467 }
5468 return nullptr;
5469 }
5470
ExecuteAction(const int64_t elementId,const int32_t action,const std::map<std::string,std::string> & actionArguments,const int32_t requestId,AccessibilityElementOperatorCallback & callback)5471 void JsAccessibilityManager::JsInteractionOperation::ExecuteAction(const int64_t elementId, const int32_t action,
5472 const std::map<std::string, std::string>& actionArguments, const int32_t requestId,
5473 AccessibilityElementOperatorCallback& callback)
5474 {
5475 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "ExecuteAction elementId: %{public}" PRId64 ", action: %{public}d",
5476 elementId, action);
5477 int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
5478 int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
5479 AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
5480
5481 auto jsAccessibilityManager = GetHandler().Upgrade();
5482 if (!jsAccessibilityManager) {
5483 TAG_LOGE(AceLogTag::ACE_ACCESSIBILITY, "ExecuteAction failed, requestId: %{public}d", requestId);
5484 callback.SetExecuteActionResult(false, requestId);
5485 return;
5486 }
5487 auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
5488 if (!context) {
5489 TAG_LOGE(AceLogTag::ACE_ACCESSIBILITY, "ExecuteAction failed, requestId: %{public}d", requestId);
5490 callback.SetExecuteActionResult(false, requestId);
5491 return;
5492 }
5493 auto actionInfo = static_cast<ActionType>(action);
5494 ActionParam param { actionInfo, actionArguments };
5495 auto windowId = windowId_;
5496 context->GetTaskExecutor()->PostTask(
5497 [weak = GetHandler(), splitElementId, param, requestId, &callback, windowId] {
5498 auto jsAccessibilityManager = weak.Upgrade();
5499 if (!jsAccessibilityManager) {
5500 TAG_LOGE(AceLogTag::ACE_ACCESSIBILITY, "ExecuteAction failed, requestId: %{public}d", requestId);
5501 callback.SetExecuteActionResult(false, requestId);
5502 return;
5503 }
5504 ACE_SCOPED_TRACE("ExecuteAction");
5505 jsAccessibilityManager->ExecuteAction(splitElementId, param, requestId, callback, windowId);
5506 },
5507 TaskExecutor::TaskType::UI, "ArkUIAccessibilityExecuteAction");
5508 }
5509
AccessibilityActionEvent(const ActionType & action,const std::map<std::string,std::string> & actionArguments,const RefPtr<AccessibilityNode> & node,const RefPtr<PipelineContext> & context)5510 bool JsAccessibilityManager::AccessibilityActionEvent(const ActionType& action,
5511 const std::map<std::string, std::string>& actionArguments, const RefPtr<AccessibilityNode>& node,
5512 const RefPtr<PipelineContext>& context)
5513 {
5514 if (!node || !context) {
5515 return false;
5516 }
5517 ContainerScope scope(context->GetInstanceId());
5518 switch (action) {
5519 case ActionType::ACCESSIBILITY_ACTION_CLICK: {
5520 node->SetClicked(true);
5521 if (!node->GetClickEventMarker().IsEmpty()) {
5522 #ifndef NG_BUILD
5523 context->SendEventToFrontend(node->GetClickEventMarker());
5524 #endif
5525 node->ActionClick();
5526 return true;
5527 }
5528 return node->ActionClick();
5529 }
5530 case ActionType::ACCESSIBILITY_ACTION_LONG_CLICK: {
5531 if (!node->GetLongPressEventMarker().IsEmpty()) {
5532 #ifndef NG_BUILD
5533 context->SendEventToFrontend(node->GetLongPressEventMarker());
5534 #endif
5535 node->ActionLongClick();
5536 return true;
5537 }
5538 return node->ActionLongClick();
5539 }
5540 case ActionType::ACCESSIBILITY_ACTION_SET_TEXT: {
5541 if (!node->GetSetTextEventMarker().IsEmpty()) {
5542 #ifndef NG_BUILD
5543 context->SendEventToFrontend(node->GetSetTextEventMarker());
5544 #endif
5545 node->ActionSetText(actionArguments.find(ACTION_ARGU_SET_TEXT)->second);
5546 return true;
5547 }
5548 return node->ActionSetText(actionArguments.find(ACTION_ARGU_SET_TEXT)->second);
5549 }
5550 case ActionType::ACCESSIBILITY_ACTION_FOCUS: {
5551 #ifndef NG_BUILD
5552 context->AccessibilityRequestFocus(std::to_string(node->GetNodeId()));
5553 #endif
5554 if (!node->GetFocusEventMarker().IsEmpty()) {
5555 #ifndef NG_BUILD
5556 context->SendEventToFrontend(node->GetFocusEventMarker());
5557 #endif
5558 node->ActionFocus();
5559 return true;
5560 }
5561 return node->ActionFocus();
5562 }
5563 case ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS: {
5564 return RequestAccessibilityFocus(node);
5565 }
5566 case ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
5567 return ClearAccessibilityFocus(node);
5568 }
5569 case ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD:
5570 return node->ActionScrollForward();
5571 case ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD:
5572 return node->ActionScrollBackward();
5573 default:
5574 return false;
5575 }
5576 }
5577
SendActionEvent(const Accessibility::ActionType & action,int64_t nodeId)5578 void JsAccessibilityManager::SendActionEvent(const Accessibility::ActionType& action, int64_t nodeId)
5579 {
5580 static std::unordered_map<Accessibility::ActionType, std::string> actionToStr {
5581 { Accessibility::ActionType::ACCESSIBILITY_ACTION_CLICK, DOM_CLICK },
5582 { Accessibility::ActionType::ACCESSIBILITY_ACTION_LONG_CLICK, DOM_LONG_PRESS },
5583 { Accessibility::ActionType::ACCESSIBILITY_ACTION_FOCUS, DOM_FOCUS },
5584 { Accessibility::ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS, ACCESSIBILITY_FOCUSED_EVENT },
5585 { Accessibility::ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS, ACCESSIBILITY_CLEAR_FOCUS_EVENT },
5586 { Accessibility::ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD, SCROLL_END_EVENT },
5587 { Accessibility::ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD, SCROLL_END_EVENT },
5588 };
5589 if (actionToStr.find(action) == actionToStr.end()) {
5590 return;
5591 }
5592 AccessibilityEvent accessibilityEvent;
5593 accessibilityEvent.eventType = actionToStr[action];
5594 accessibilityEvent.nodeId = static_cast<int64_t>(nodeId);
5595 SendAccessibilityAsyncEvent(accessibilityEvent);
5596 }
5597
5598 namespace {
stringToLower(std::string & str)5599 void stringToLower(std::string &str)
5600 {
5601 std::transform(str.begin(), str.end(), str.begin(), [](char &c) {
5602 return std::tolower(c);
5603 });
5604 }
5605
conversionDirection(std::string dir)5606 bool conversionDirection(std::string dir)
5607 {
5608 stringToLower(dir);
5609 if (dir.compare(STRING_DIR_FORWARD) == 0) {
5610 return true;
5611 }
5612
5613 return false;
5614 }
5615
getArgumentByKey(const std::map<std::string,std::string> & actionArguments,const std::string & checkKey)5616 int32_t getArgumentByKey(const std::map<std::string, std::string>& actionArguments, const std::string& checkKey)
5617 {
5618 auto iter = actionArguments.find(checkKey);
5619 int32_t argument = -1; // -1:default value
5620 if (iter != actionArguments.end()) {
5621 std::stringstream strArguments;
5622 strArguments << iter->second;
5623 strArguments >> argument;
5624 }
5625 return argument;
5626 }
5627
findAccessibilityScrollType(int32_t accessibilityScrollTypeValue)5628 AccessibilityScrollType findAccessibilityScrollType(int32_t accessibilityScrollTypeValue)
5629 {
5630 switch (accessibilityScrollTypeValue) {
5631 case 0:
5632 return AccessibilityScrollType::SCROLL_HALF;
5633 case 1:
5634 return AccessibilityScrollType::SCROLL_FULL;
5635 default:
5636 return AccessibilityScrollType::SCROLL_DEFAULT;
5637 }
5638 }
5639
getAccessibilityScrollType(const std::map<std::string,std::string> & actionArguments,const std::string & checkKey)5640 AccessibilityScrollType getAccessibilityScrollType(const std::map<std::string, std::string>& actionArguments,
5641 const std::string& checkKey)
5642 {
5643 auto argument = getArgumentByKey(actionArguments, checkKey);
5644 return findAccessibilityScrollType(argument);
5645 }
5646
5647
ActAccessibilityAction(Accessibility::ActionType action,const std::map<std::string,std::string> & actionArguments,RefPtr<NG::AccessibilityProperty> accessibilityProperty)5648 bool ActAccessibilityAction(Accessibility::ActionType action, const std::map<std::string, std::string>& actionArguments,
5649 RefPtr<NG::AccessibilityProperty> accessibilityProperty)
5650 {
5651 AccessibilityActionParam param;
5652 if (action == ActionType::ACCESSIBILITY_ACTION_SET_SELECTION) {
5653 std::string dir = STRING_DIR_BACKWARD;
5654 auto iter = actionArguments.find(ACTION_ARGU_SELECT_TEXT_INFORWARD);
5655 if (iter != actionArguments.end()) {
5656 dir = iter->second;
5657 }
5658 param.setSelectionStart = getArgumentByKey(actionArguments, ACTION_ARGU_SELECT_TEXT_START);
5659 param.setSelectionEnd = getArgumentByKey(actionArguments, ACTION_ARGU_SELECT_TEXT_END);
5660 param.setSelectionDir = conversionDirection(dir);
5661 }
5662 if (action == ActionType::ACCESSIBILITY_ACTION_SET_TEXT) {
5663 auto iter = actionArguments.find(ACTION_ARGU_SET_TEXT);
5664 if (iter != actionArguments.end()) {
5665 param.setTextArgument = iter->second;
5666 }
5667 }
5668 if (action == ActionType::ACCESSIBILITY_ACTION_NEXT_TEXT ||
5669 action == ActionType::ACCESSIBILITY_ACTION_PREVIOUS_TEXT) {
5670 int moveUnit = TextMoveUnit::STEP_CHARACTER;
5671 auto iter = actionArguments.find(ACTION_ARGU_MOVE_UNIT);
5672 if (iter != actionArguments.end()) {
5673 std::stringstream str_moveUnit;
5674 str_moveUnit << iter->second;
5675 str_moveUnit >> moveUnit;
5676 }
5677 param.moveUnit = static_cast<TextMoveUnit>(moveUnit);
5678 }
5679 if (action == ActionType::ACCESSIBILITY_ACTION_SET_CURSOR_POSITION) {
5680 param.setCursorIndex = getArgumentByKey(actionArguments, ACTION_ARGU_SET_OFFSET);
5681 }
5682 if ((action == ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD) ||
5683 (action == ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD)) {
5684 param.scrollType = getAccessibilityScrollType(actionArguments, ACTION_ARGU_SCROLL_STUB);
5685 }
5686 if (action == ActionType::ACCESSIBILITY_ACTION_SPAN_CLICK) {
5687 param.spanId = getArgumentByKey(actionArguments, ACTION_ARGU_SPAN_ID);
5688 }
5689 auto accessibiltyAction = ACTIONS.find(action);
5690 if (accessibiltyAction != ACTIONS.end()) {
5691 param.accessibilityProperty = accessibilityProperty;
5692 return accessibiltyAction->second(param);
5693 }
5694 return false;
5695 }
5696 }
5697
ExecuteExtensionActionNG(int64_t elementId,const std::map<std::string,std::string> & actionArguments,int32_t action,const RefPtr<PipelineBase> & context,int64_t uiExtensionOffset)5698 bool JsAccessibilityManager::ExecuteExtensionActionNG(int64_t elementId,
5699 const std::map<std::string, std::string>& actionArguments, int32_t action, const RefPtr<PipelineBase>& context,
5700 int64_t uiExtensionOffset)
5701 {
5702 return ExecuteActionNG(
5703 elementId, actionArguments, static_cast<ActionType>(action), context, uiExtensionOffset);
5704 }
5705
ExecuteActionNG(int64_t elementId,const std::map<std::string,std::string> & actionArguments,ActionType action,const RefPtr<PipelineBase> & context,int64_t uiExtensionOffset)5706 bool JsAccessibilityManager::ExecuteActionNG(int64_t elementId,
5707 const std::map<std::string, std::string>& actionArguments, ActionType action, const RefPtr<PipelineBase>& context,
5708 int64_t uiExtensionOffset)
5709 {
5710 bool result = false;
5711 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
5712 CHECK_NULL_RETURN(ngPipeline, result);
5713 #ifdef WINDOW_SCENE_SUPPORTED
5714 auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
5715 CHECK_NULL_RETURN(uiExtensionManager, result);
5716 if (uiExtensionManager->IsWrapExtensionAbilityId(elementId)) {
5717 auto unWrapIdPair = uiExtensionManager->UnWrapExtensionAbilityId(uiExtensionOffset, elementId);
5718 int64_t childWrapId = unWrapIdPair.second;
5719 int64_t uiExtensionId = unWrapIdPair.first;
5720 auto rootNode = ngPipeline->GetRootElement();
5721 CHECK_NULL_RETURN(rootNode, result);
5722 auto uiExtensionNode = FindNodeFromRootByExtensionId(rootNode, uiExtensionId);
5723 CHECK_NULL_RETURN(uiExtensionNode, result);
5724 return OHOS::Ace::Framework::TransferExecuteAction(
5725 childWrapId, uiExtensionNode, actionArguments, action, uiExtensionOffset);
5726 }
5727 #endif
5728 ContainerScope instance(ngPipeline->GetInstanceId());
5729 auto frameNode = GetFramenodeByAccessibilityId(ngPipeline->GetRootElement(), elementId);
5730
5731 if (!frameNode && elementId == lastElementId_) {
5732 frameNode = lastFrameNode_.Upgrade();
5733 }
5734
5735
5736 CHECK_NULL_RETURN(frameNode, result);
5737
5738 auto enabled = frameNode->GetFocusHub() ? frameNode->GetFocusHub()->IsEnabled() : true;
5739 if (!enabled && action != ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS &&
5740 action != ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS) {
5741 return result;
5742 }
5743 result = ConvertActionTypeToBoolen(action, frameNode, elementId, ngPipeline);
5744 if (!result) {
5745 auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
5746 CHECK_NULL_RETURN(accessibilityProperty, false);
5747 result = ActAccessibilityAction(action, actionArguments, accessibilityProperty);
5748 if (!result) {
5749 EventReport::ReportAccessibilityFailEvent(ConvertActionTypeToString(action));
5750 }
5751 }
5752 return result;
5753 }
5754
ConvertActionTypeToBoolen(ActionType action,RefPtr<NG::FrameNode> & frameNode,int64_t elementId,RefPtr<NG::PipelineContext> & context)5755 bool JsAccessibilityManager::ConvertActionTypeToBoolen(ActionType action, RefPtr<NG::FrameNode>& frameNode,
5756 int64_t elementId, RefPtr<NG::PipelineContext>& context)
5757 {
5758 bool result = false;
5759 switch (action) {
5760 case ActionType::ACCESSIBILITY_ACTION_FOCUS: {
5761 result = RequestFocus(frameNode);
5762 break;
5763 }
5764 case ActionType::ACCESSIBILITY_ACTION_CLEAR_FOCUS: {
5765 result = LostFocus(frameNode);
5766 break;
5767 }
5768 case ActionType::ACCESSIBILITY_ACTION_CLICK: {
5769 result = ActClick(frameNode);
5770 break;
5771 }
5772 case ActionType::ACCESSIBILITY_ACTION_LONG_CLICK: {
5773 result = ActLongClick(frameNode);
5774 break;
5775 }
5776 case ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS: {
5777 SaveLast(elementId, frameNode);
5778 SaveCurrentFocusNodeSize(frameNode);
5779 result = ActAccessibilityFocus(elementId, frameNode, context, currentFocusNodeId_, false);
5780 break;
5781 }
5782 case ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
5783 SaveLast(elementId, frameNode);
5784 result = ActAccessibilityFocus(elementId, frameNode, context, currentFocusNodeId_, true);
5785 break;
5786 }
5787 default:
5788 break;
5789 }
5790 return result;
5791 }
5792
ExecuteAction(const int64_t elementId,const ActionParam & param,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t windowId)5793 void JsAccessibilityManager::ExecuteAction(const int64_t elementId, const ActionParam& param, const int32_t requestId,
5794 AccessibilityElementOperatorCallback& callback, const int32_t windowId)
5795 {
5796 auto action = param.action;
5797 auto actionArguments = param.actionArguments;
5798
5799 bool actionResult = false;
5800 auto context = GetPipelineByWindowId(windowId);
5801 if (!context) {
5802 SetExecuteActionResult(callback, actionResult, requestId);
5803 return;
5804 }
5805
5806 if (AceType::InstanceOf<NG::PipelineContext>(context)) {
5807 actionResult = ExecuteActionNG(elementId, actionArguments, action, context, NG::UI_EXTENSION_OFFSET_MAX);
5808 } else {
5809 auto node = GetAccessibilityNodeFromPage(elementId);
5810 if (!node) {
5811 SetExecuteActionResult(callback, false, requestId);
5812 return;
5813 }
5814
5815 actionResult =
5816 AccessibilityActionEvent(action, actionArguments, node, AceType::DynamicCast<PipelineContext>(context));
5817 }
5818 SetExecuteActionResult(callback, actionResult, requestId);
5819 if (actionResult && AceType::InstanceOf<PipelineContext>(context)) {
5820 SendActionEvent(action, elementId);
5821 }
5822 }
5823
GetCursorPosition(const int64_t elementId,const int32_t requestId,AccessibilityElementOperatorCallback & callback)5824 void JsAccessibilityManager::JsInteractionOperation::GetCursorPosition(const int64_t elementId,
5825 const int32_t requestId, AccessibilityElementOperatorCallback &callback)
5826 {
5827 int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
5828 int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
5829 AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
5830
5831 auto jsAccessibilityManager = GetHandler().Upgrade();
5832 CHECK_NULL_VOID(jsAccessibilityManager);
5833 auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
5834 CHECK_NULL_VOID(context);
5835 RefPtr<NG::FrameNode> node;
5836 auto ngPipeline = jsAccessibilityManager->FindPipelineByElementId(splitElementId, node);
5837 CHECK_NULL_VOID(ngPipeline);
5838 #ifdef WINDOW_SCENE_SUPPORTED
5839 auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
5840 CHECK_NULL_VOID(uiExtensionManager);
5841 if (uiExtensionManager->IsWrapExtensionAbilityId(splitElementId)) {
5842 auto unWrapIdPair = uiExtensionManager->UnWrapExtensionAbilityId(NG::UI_EXTENSION_OFFSET_MAX, elementId);
5843 int64_t uiExtensionId = unWrapIdPair.first;
5844 auto rootNode = ngPipeline->GetRootElement();
5845 CHECK_NULL_VOID(rootNode);
5846 auto uiExtensionNode = jsAccessibilityManager->FindNodeFromRootByExtensionId(rootNode, uiExtensionId);
5847 CHECK_NULL_VOID(uiExtensionNode);
5848 auto accessibilityProperty = uiExtensionNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
5849 CHECK_NULL_VOID(accessibilityProperty);
5850 auto callNumber = accessibilityProperty->ActActionGetIndex();
5851 callback.SetCursorPositionResult(callNumber, requestId);
5852 return;
5853 }
5854 #endif
5855 auto frameNode = GetFramenodeByAccessibilityId(ngPipeline->GetRootElement(), splitElementId);
5856 CHECK_NULL_VOID(frameNode);
5857 auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
5858 CHECK_NULL_VOID(accessibilityProperty);
5859 auto callNumber = accessibilityProperty->ActActionGetIndex();
5860 callback.SetCursorPositionResult(callNumber, requestId);
5861 }
5862
ClearFocus()5863 void JsAccessibilityManager::JsInteractionOperation::ClearFocus()
5864 {
5865 auto jsAccessibilityManager = GetHandler().Upgrade();
5866 CHECK_NULL_VOID(jsAccessibilityManager);
5867 auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
5868 CHECK_NULL_VOID(context);
5869 context->GetTaskExecutor()->PostTask(
5870 [weak = GetHandler()] {
5871 auto jsAccessibilityManager = weak.Upgrade();
5872 CHECK_NULL_VOID(jsAccessibilityManager);
5873 ACE_SCOPED_TRACE("ClearCurrentFocus");
5874 jsAccessibilityManager->ClearCurrentFocus();
5875 },
5876 TaskExecutor::TaskType::UI, "ArkUIAccessibilityClearCurrentFocus");
5877 }
5878
OutsideTouch()5879 void JsAccessibilityManager::JsInteractionOperation::OutsideTouch() {}
5880 #ifdef WEB_SUPPORTED
5881
GetChildrenFromWebNode(int64_t nodeId,std::list<int64_t> & children,const RefPtr<NG::PipelineContext> & ngPipeline,const RefPtr<NG::WebPattern> & webPattern)5882 void GetChildrenFromWebNode(
5883 int64_t nodeId, std::list<int64_t>& children,
5884 const RefPtr<NG::PipelineContext>& ngPipeline, const RefPtr<NG::WebPattern>& webPattern)
5885 {
5886 std::list<int64_t> webNodeChildren;
5887 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
5888 auto node = webPattern->GetTransitionalNodeById(nodeId);
5889 CHECK_NULL_VOID(node);
5890 for (auto& childId : node->GetChildIds()) {
5891 webNodeChildren.emplace_back(childId);
5892 }
5893 }
5894 while (!webNodeChildren.empty()) {
5895 children.emplace_back(webNodeChildren.front());
5896 webNodeChildren.pop_front();
5897 }
5898 }
5899
SearchWebElementInfoByAccessibilityId(const int64_t elementId,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t mode,const int32_t windowId,const RefPtr<NG::WebPattern> & webPattern)5900 void JsAccessibilityManager::SearchWebElementInfoByAccessibilityId(const int64_t elementId, const int32_t requestId,
5901 AccessibilityElementOperatorCallback& callback, const int32_t mode, const int32_t windowId,
5902 const RefPtr<NG::WebPattern>& webPattern)
5903 {
5904 std::list<AccessibilityElementInfo> infos;
5905
5906 auto pipeline = GetPipelineByWindowId(windowId);
5907 CHECK_NULL_VOID(pipeline);
5908 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipeline);
5909 CHECK_NULL_VOID(ngPipeline);
5910
5911 if (!ngPipeline->GetOnFoucs() && (SystemProperties::GetDeviceType() == DeviceType::TWO_IN_ONE)) {
5912 TAG_LOGD(AceLogTag::ACE_WEB,
5913 "SearchWebElementInfo GetOnFocus, elementId: %{public}" PRId64
5914 ", requestId: %{public}d, mode: %{public}d, windowId: %{public}d",
5915 elementId, requestId, mode, windowId);
5916 SetSearchElementInfoByAccessibilityIdResult(callback, std::move(infos), requestId);
5917 return;
5918 }
5919 CHECK_NULL_VOID(webPattern);
5920
5921 if (elementId == -1) {
5922 auto webNode = webPattern->GetHost();
5923 AccessibilityElementInfo webInfo;
5924 SetRootAccessibilityVisible(webNode, webInfo);
5925 if (!webInfo.GetAccessibilityVisible()) {
5926 TAG_LOGD(AceLogTag::ACE_WEB,
5927 "SearchWebElementinfo accessibility visible false, elementId: %{public}" PRId64
5928 ", requestId: %{public}d, mode: %{public}d, windowId: %{public}d",
5929 elementId, requestId, mode, windowId);
5930 SetSearchElementInfoByAccessibilityIdResult(callback, std::move(infos), requestId);
5931 return;
5932 }
5933 }
5934
5935 SearchWebElementInfoByAccessibilityIdNG(elementId, mode, infos, ngPipeline, webPattern);
5936 SetSearchElementInfoByAccessibilityIdResult(callback, std::move(infos), requestId);
5937 }
5938
SearchWebElementInfoByAccessibilityIdNG(int64_t elementId,int32_t mode,std::list<AccessibilityElementInfo> & infos,const RefPtr<PipelineBase> & context,const RefPtr<NG::WebPattern> & webPattern)5939 void JsAccessibilityManager::SearchWebElementInfoByAccessibilityIdNG(int64_t elementId, int32_t mode,
5940 std::list<AccessibilityElementInfo>& infos, const RefPtr<PipelineBase>& context,
5941 const RefPtr<NG::WebPattern>& webPattern)
5942 {
5943 TAG_LOGD(AceLogTag::ACE_WEB, "elementId: %{public}" PRId64 ", treeId: %{public}d, mode: %{public}d",
5944 elementId, treeId_, mode);
5945 auto mainContext = context_.Upgrade();
5946 CHECK_NULL_VOID(mainContext);
5947
5948 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
5949 CHECK_NULL_VOID(ngPipeline);
5950
5951 AccessibilityElementInfo nodeInfo;
5952
5953 CommonProperty commonProperty;
5954 GenerateCommonProperty(ngPipeline, commonProperty, mainContext);
5955
5956 CHECK_NULL_VOID(webPattern);
5957 auto node = webPattern->GetTransitionalNodeById(elementId);
5958 CHECK_NULL_VOID(node);
5959 UpdateWebAccessibilityElementInfo(node, commonProperty, nodeInfo, webPattern);
5960 nodeInfo.SetAccessibilityVisible(webPattern->GetAccessibilityVisible(elementId));
5961 infos.push_back(nodeInfo);
5962 SearchParameter param {elementId, "", mode, 0};
5963 UpdateWebCacheInfo(infos, elementId, commonProperty, ngPipeline, param, webPattern);
5964 }
5965
FindWebFocusedElementInfo(const int64_t elementId,const int32_t focusType,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t windowId,const RefPtr<NG::WebPattern> & webPattern)5966 void JsAccessibilityManager::FindWebFocusedElementInfo(const int64_t elementId, const int32_t focusType,
5967 const int32_t requestId, AccessibilityElementOperatorCallback& callback, const int32_t windowId,
5968 const RefPtr<NG::WebPattern>& webPattern)
5969 {
5970 AccessibilityElementInfo nodeInfo;
5971 if (focusType != FOCUS_TYPE_INPUT && focusType != FOCUS_TYPE_ACCESSIBILITY) {
5972 nodeInfo.SetValidElement(false);
5973 SetFindFocusedElementInfoResult(callback, nodeInfo, requestId);
5974 return;
5975 }
5976
5977 auto context = GetPipelineByWindowId(windowId);
5978 if (!context || AceType::InstanceOf<NG::PipelineContext>(context)) {
5979 nodeInfo.SetValidElement(false);
5980 SetFindFocusedElementInfoResult(callback, nodeInfo, requestId);
5981 return;
5982 }
5983
5984 FindWebFocusedElementInfoNG(elementId, focusType, nodeInfo, context, webPattern);
5985 SetFindFocusedElementInfoResult(callback, nodeInfo, requestId);
5986 }
5987
FindWebFocusedElementInfoNG(int64_t elementId,int32_t focusType,Accessibility::AccessibilityElementInfo & info,const RefPtr<PipelineBase> & context,const RefPtr<NG::WebPattern> & webPattern)5988 void JsAccessibilityManager::FindWebFocusedElementInfoNG(int64_t elementId, int32_t focusType,
5989 Accessibility::AccessibilityElementInfo& info, const RefPtr<PipelineBase>& context,
5990 const RefPtr<NG::WebPattern>& webPattern)
5991 {
5992 auto mainContext = context_.Upgrade();
5993 CHECK_NULL_VOID(mainContext);
5994 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
5995 CHECK_NULL_VOID(ngPipeline);
5996 auto node = webPattern->GetFocusedAccessibilityNode(elementId, focusType == FOCUS_TYPE_ACCESSIBILITY);
5997 if (!node) {
5998 info.SetValidElement(false);
5999 return;
6000 }
6001 CHECK_NULL_VOID(node);
6002 CommonProperty commonProperty;
6003 GenerateCommonProperty(ngPipeline, commonProperty, mainContext);
6004 UpdateWebAccessibilityElementInfo(node, commonProperty, info, webPattern);
6005 }
6006
WebFocusMoveSearch(const int64_t elementId,const int32_t direction,const int32_t requestId,Accessibility::AccessibilityElementOperatorCallback & callback,const int32_t windowId,const RefPtr<NG::WebPattern> & webPattern)6007 void JsAccessibilityManager::WebFocusMoveSearch(const int64_t elementId, const int32_t direction,
6008 const int32_t requestId, Accessibility::AccessibilityElementOperatorCallback& callback, const int32_t windowId,
6009 const RefPtr<NG::WebPattern>& webPattern)
6010 {
6011 AccessibilityElementInfo nodeInfo;
6012 auto context = GetPipelineByWindowId(windowId);
6013 if (!context) {
6014 nodeInfo.SetValidElement(false);
6015 SetFocusMoveSearchResult(callback, nodeInfo, requestId);
6016 return;
6017 }
6018
6019 WebFocusMoveSearchNG(elementId, direction, nodeInfo, context, webPattern);
6020 SetFocusMoveSearchResult(callback, nodeInfo, requestId);
6021 }
6022
WebFocusMoveSearchNG(int64_t elementId,int32_t direction,AccessibilityElementInfo & info,const RefPtr<PipelineBase> & context,const RefPtr<NG::WebPattern> & webPattern)6023 void JsAccessibilityManager::WebFocusMoveSearchNG(int64_t elementId, int32_t direction,
6024 AccessibilityElementInfo& info, const RefPtr<PipelineBase>& context,
6025 const RefPtr<NG::WebPattern>& webPattern)
6026 {
6027 auto mainContext = context_.Upgrade();
6028 CHECK_NULL_VOID(mainContext);
6029 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
6030 CHECK_NULL_VOID(ngPipeline);
6031
6032 CommonProperty commonProperty;
6033 GenerateCommonProperty(ngPipeline, commonProperty, mainContext);
6034 CHECK_NULL_VOID(webPattern);
6035 auto node = webPattern->GetAccessibilityNodeByFocusMove(elementId, direction);
6036 if (node) {
6037 UpdateWebAccessibilityElementInfo(node, commonProperty, info, webPattern);
6038 } else {
6039 auto webNode = webPattern->GetHost();
6040 CHECK_NULL_VOID(webNode);
6041 UpdateAccessibilityElementInfo(webNode, commonProperty, info, ngPipeline);
6042 }
6043 }
6044
ExecuteWebActionNG(int64_t elementId,ActionType action,const std::map<std::string,std::string> & actionArguments,const RefPtr<NG::WebPattern> & webPattern)6045 bool JsAccessibilityManager::ExecuteWebActionNG(int64_t elementId, ActionType action,
6046 const std::map<std::string, std::string>& actionArguments, const RefPtr<NG::WebPattern>& webPattern)
6047 {
6048 CHECK_NULL_RETURN(webPattern, false);
6049 return webPattern->ExecuteAction(elementId, ConvertAccessibilityAction(action), actionArguments);
6050 }
6051
ExecuteWebAction(const int64_t elementId,const ActionParam & param,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const int32_t windowId,const RefPtr<NG::WebPattern> & webPattern)6052 void JsAccessibilityManager::ExecuteWebAction(const int64_t elementId, const ActionParam& param,
6053 const int32_t requestId, AccessibilityElementOperatorCallback& callback, const int32_t windowId,
6054 const RefPtr<NG::WebPattern>& webPattern)
6055 {
6056 auto action = param.action;
6057 auto actionArguments = param.actionArguments;
6058
6059 bool actionResult = false;
6060 auto context = GetPipelineByWindowId(windowId);
6061 if (!context || !AceType::InstanceOf<NG::PipelineContext>(context)) {
6062 SetExecuteActionResult(callback, actionResult, requestId);
6063 return;
6064 }
6065
6066 actionResult = ExecuteWebActionNG(elementId, action, actionArguments, webPattern);
6067 SetExecuteActionResult(callback, actionResult, requestId);
6068 }
6069
RegisterWebInteractionOperationAsChildTree(int64_t accessibilityId,const WeakPtr<NG::WebPattern> & webPattern)6070 bool JsAccessibilityManager::RegisterWebInteractionOperationAsChildTree(int64_t accessibilityId,
6071 const WeakPtr<NG::WebPattern>& webPattern)
6072 {
6073 std::shared_ptr<AccessibilitySystemAbilityClient> instance = AccessibilitySystemAbilityClient::GetInstance();
6074 CHECK_NULL_RETURN(instance, false);
6075 auto pipelineContext = GetPipelineContext().Upgrade();
6076 CHECK_NULL_RETURN(pipelineContext, false);
6077 auto container = Platform::AceContainer::GetContainer(pipelineContext->GetInstanceId());
6078 if (container != nullptr && container->IsUIExtensionWindow()) {
6079 windowId_ = pipelineContext->GetRealHostWindowId();
6080 }
6081
6082 AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(treeId_, accessibilityId);
6083
6084 uint32_t windowId = GetWindowId();
6085 auto interactionOperation = std::make_shared<WebInteractionOperation>(windowId);
6086 interactionOperation->SetHandler(WeakClaim(this));
6087 interactionOperation->SetWebPattern(webPattern);
6088 auto pattern = webPattern.Upgrade();
6089 CHECK_NULL_RETURN(pattern, false);
6090 Accessibility::Registration registration {
6091 .windowId = windowId,
6092 .parentWindowId = windowId,
6093 .parentTreeId = treeId_,
6094 .elementId = accessibilityId,
6095 };
6096 parentWebWindowId_ = windowId;
6097 TAG_LOGI(AceLogTag::ACE_WEB, "windowId: %{public}u, parentWindowId: %{public}u, "
6098 "parentTreeId: %{public}d, elementId %{public}" PRId64,
6099 windowId, windowId, treeId_, accessibilityId);
6100 Accessibility::RetError retReg = instance->RegisterElementOperator(registration, interactionOperation);
6101 TAG_LOGI(AceLogTag::ACE_WEB, "RegisterWebInteractionOperationAsChildTree result: %{public}d", retReg);
6102 return retReg == RET_OK;
6103 }
6104
DeregisterWebInteractionOperationAsChildTree(int32_t treeId)6105 bool JsAccessibilityManager::DeregisterWebInteractionOperationAsChildTree(int32_t treeId)
6106 {
6107 std::shared_ptr<AccessibilitySystemAbilityClient> instance = AccessibilitySystemAbilityClient::GetInstance();
6108 CHECK_NULL_RETURN(instance, false);
6109 uint32_t windowId = GetWindowId();
6110 Accessibility::RetError retReg = instance->DeregisterElementOperator(windowId, treeId);
6111 return retReg == RET_OK;
6112 }
6113
UpdateWebCacheInfo(std::list<AccessibilityElementInfo> & infos,int64_t nodeId,const CommonProperty & commonProperty,const RefPtr<NG::PipelineContext> & ngPipeline,const SearchParameter & searchParam,const RefPtr<NG::WebPattern> & webPattern)6114 void JsAccessibilityManager::UpdateWebCacheInfo(std::list<AccessibilityElementInfo>& infos,
6115 int64_t nodeId, const CommonProperty& commonProperty, const RefPtr<NG::PipelineContext>& ngPipeline,
6116 const SearchParameter& searchParam, const RefPtr<NG::WebPattern>& webPattern)
6117 {
6118 uint32_t umode = searchParam.mode;
6119 std::list<int64_t> children;
6120 // get all children
6121 if (!(umode & static_cast<uint32_t>(PREFETCH_RECURSIVE_CHILDREN))) {
6122 return;
6123 }
6124 GetChildrenFromWebNode(nodeId, children, ngPipeline, webPattern);
6125 while (!children.empty()) {
6126 int64_t parent = children.front();
6127 children.pop_front();
6128 AccessibilityElementInfo nodeInfo;
6129
6130 GetChildrenFromWebNode(parent, children, ngPipeline, webPattern);
6131 auto node = webPattern->GetTransitionalNodeById(parent);
6132 if (node) {
6133 UpdateWebAccessibilityElementInfo(node, commonProperty, nodeInfo, webPattern);
6134 infos.push_back(nodeInfo);
6135 }
6136 }
6137 }
6138 #endif //WEB_SUPPORTED
6139
RegisterInteractionOperationAsChildTree(const Registration & registration)6140 bool JsAccessibilityManager::RegisterInteractionOperationAsChildTree(
6141 const Registration& registration)
6142 {
6143 bool ret = false;
6144 switch (registration.operatorType) {
6145 case OperatorType::JS_THIRD_PROVIDER:
6146 ret = RegisterThirdProviderInteractionOperationAsChildTree(registration);
6147 break;
6148 default:
6149 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY,
6150 "RegisterInteractionOperationAsChildTree operatorType: %{public}d",
6151 static_cast<int32_t>(registration.operatorType));
6152 }
6153 return ret;
6154 }
6155
RegisterThirdProviderInteractionOperationAsChildTree(const Registration & registration)6156 bool JsAccessibilityManager::RegisterThirdProviderInteractionOperationAsChildTree(
6157 const Registration& registration)
6158 {
6159 std::shared_ptr<AccessibilitySystemAbilityClient> instance =
6160 AccessibilitySystemAbilityClient::GetInstance();
6161 CHECK_NULL_RETURN(instance, false);
6162 Accessibility::Registration innerRegistration {
6163 .windowId = registration.windowId,
6164 .parentWindowId = registration.parentWindowId,
6165 .parentTreeId = registration.parentTreeId,
6166 .elementId = registration.elementId,
6167 };
6168
6169 auto provider = registration.accessibilityProvider.Upgrade();
6170 CHECK_NULL_RETURN(provider, false);
6171 auto interactionOperation = std::make_shared<JsThirdProviderInteractionOperation>(
6172 registration.accessibilityProvider, WeakClaim(this), registration.hostNode);
6173 provider->SendThirdAccessibilityProvider(interactionOperation);
6174 interactionOperation->Initialize();
6175 RegisterJsThirdProviderInteractionOperation(registration.elementId,
6176 interactionOperation);
6177 Accessibility::RetError retReg = instance->RegisterElementOperator(
6178 innerRegistration, interactionOperation);
6179 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY,
6180 "RegisterWebInteractionOperationAsChildTree result: %{public}d", retReg);
6181 return retReg == RET_OK;
6182 }
6183
DeregisterInteractionOperationAsChildTree(uint32_t windowId,int32_t treeId)6184 bool JsAccessibilityManager::DeregisterInteractionOperationAsChildTree(
6185 uint32_t windowId, int32_t treeId)
6186 {
6187 std::shared_ptr<AccessibilitySystemAbilityClient> instance =
6188 AccessibilitySystemAbilityClient::GetInstance();
6189 CHECK_NULL_RETURN(instance, false);
6190 Accessibility::RetError retReg = instance->DeregisterElementOperator(windowId, treeId);
6191 return retReg == RET_OK;
6192 }
6193
RegisterInteractionOperation(int windowId)6194 int JsAccessibilityManager::RegisterInteractionOperation(int windowId)
6195 {
6196 if (IsRegister()) {
6197 return 0;
6198 }
6199
6200 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "RegisterInteractionOperation windowId: %{public}u", windowId);
6201 std::shared_ptr<AccessibilitySystemAbilityClient> instance = AccessibilitySystemAbilityClient::GetInstance();
6202 CHECK_NULL_RETURN(instance, -1);
6203 auto interactionOperation = std::make_shared<JsInteractionOperation>(windowId);
6204 interactionOperation->SetHandler(WeakClaim(this));
6205 Accessibility::RetError retReg = instance->RegisterElementOperator(windowId, interactionOperation);
6206 RefPtr<PipelineBase> context;
6207 for (const auto& subContext : GetSubPipelineContexts()) {
6208 context = subContext.Upgrade();
6209 CHECK_NULL_RETURN(context, -1);
6210 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "RegisterSubPipeline windowId: %{public}u", context->GetWindowId());
6211 interactionOperation = std::make_shared<JsInteractionOperation>(context->GetWindowId());
6212 interactionOperation->SetHandler(WeakClaim(this));
6213 auto retResult = instance->RegisterElementOperator(context->GetWindowId(), interactionOperation);
6214 retReg = retResult == RET_OK ? retReg : retResult;
6215 }
6216 Register(retReg == RET_OK);
6217 if (retReg == RET_OK) {
6218 NotifyChildTreeOnRegister(treeId_);
6219 }
6220
6221 return retReg;
6222 }
6223
RegisterSubWindowInteractionOperation(int windowId)6224 void JsAccessibilityManager::RegisterSubWindowInteractionOperation(int windowId)
6225 {
6226 if (!AceApplicationInfo::GetInstance().IsAccessibilityEnabled() || !IsRegister()) {
6227 return;
6228 }
6229
6230 std::shared_ptr<AccessibilitySystemAbilityClient> instance = AccessibilitySystemAbilityClient::GetInstance();
6231 CHECK_NULL_VOID(instance);
6232 auto interactionOperation = std::make_shared<JsInteractionOperation>(windowId);
6233 interactionOperation->SetHandler(WeakClaim(this));
6234 instance->RegisterElementOperator(windowId, interactionOperation);
6235 }
6236
DeregisterInteractionOperation()6237 void JsAccessibilityManager::DeregisterInteractionOperation()
6238 {
6239 if (!IsRegister()) {
6240 return;
6241 }
6242 int windowId = static_cast<int>(GetWindowId());
6243
6244 auto instance = AccessibilitySystemAbilityClient::GetInstance();
6245 CHECK_NULL_VOID(instance);
6246 Register(false);
6247 if (currentFocusNodeId_ != -1 && lastElementId_ != -1) {
6248 auto focusNode = lastFrameNode_.Upgrade();
6249 PaintAccessibilityFocusNode(focusNode, false);
6250 }
6251 lastFrameNode_.Reset();
6252 lastElementId_ = -1;
6253 currentFocusNodeId_ = -1;
6254 if (parentWindowId_ == 0) {
6255 instance->DeregisterElementOperator(windowId);
6256 } else {
6257 instance->DeregisterElementOperator(windowId, treeId_);
6258 parentElementId_ = INVALID_PARENT_ID;
6259 parentTreeId_ = 0;
6260 parentWindowId_ = 0;
6261 }
6262
6263 RefPtr<PipelineBase> context;
6264 for (const auto& subContext : GetSubPipelineContexts()) {
6265 context = subContext.Upgrade();
6266 CHECK_NULL_VOID(context);
6267 instance->DeregisterElementOperator(context->GetWindowId());
6268 }
6269 NotifyChildTreeOnDeregister();
6270 }
6271
RegisterAccessibilityChildTreeCallback(int64_t elementId,const std::shared_ptr<AccessibilityChildTreeCallback> & callback)6272 void JsAccessibilityManager::RegisterAccessibilityChildTreeCallback(
6273 int64_t elementId, const std::shared_ptr<AccessibilityChildTreeCallback> &callback)
6274 {
6275 std::lock_guard<std::mutex> lock(childTreeCallbackMapMutex_);
6276 childTreeCallbackMap_[elementId] = callback;
6277 }
6278
DeregisterAccessibilityChildTreeCallback(int64_t elementId)6279 void JsAccessibilityManager::DeregisterAccessibilityChildTreeCallback(int64_t elementId)
6280 {
6281 std::lock_guard<std::mutex> lock(childTreeCallbackMapMutex_);
6282 childTreeCallbackMap_.erase(elementId);
6283 }
6284
RegisterAccessibilitySAObserverCallback(int64_t elementId,const std::shared_ptr<AccessibilitySAObserverCallback> & callback)6285 void JsAccessibilityManager::RegisterAccessibilitySAObserverCallback(
6286 int64_t elementId, const std::shared_ptr<AccessibilitySAObserverCallback> &callback)
6287 {
6288 std::lock_guard<std::mutex> lock(componentSACallbackMutex_);
6289 componentSACallbackMap_[elementId] = callback;
6290 }
6291
DeregisterAccessibilitySAObserverCallback(int64_t elementId)6292 void JsAccessibilityManager::DeregisterAccessibilitySAObserverCallback(int64_t elementId)
6293 {
6294 std::lock_guard<std::mutex> lock(componentSACallbackMutex_);
6295 componentSACallbackMap_.erase(elementId);
6296 }
6297
NotifyAccessibilitySAStateChange(bool state)6298 void JsAccessibilityManager::NotifyAccessibilitySAStateChange(bool state)
6299 {
6300 std::lock_guard<std::mutex> lock(componentSACallbackMutex_);
6301 for (auto &item : componentSACallbackMap_) {
6302 if (item.second == nullptr) {
6303 continue;
6304 }
6305 item.second->OnState(state);
6306 }
6307 }
6308
NotifyChildTreeOnRegister(int32_t treeId)6309 void JsAccessibilityManager::NotifyChildTreeOnRegister(int32_t treeId)
6310 {
6311 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "NotifyChildTreeOnRegister size: %{public}zu", childTreeCallbackMap_.size());
6312 std::lock_guard<std::mutex> lock(childTreeCallbackMapMutex_);
6313 for (auto &item : childTreeCallbackMap_) {
6314 if (item.second == nullptr) {
6315 continue;
6316 }
6317 item.second->OnRegister(GetWindowId(), treeId);
6318 }
6319 }
6320
NotifyChildTreeOnDeregister()6321 void JsAccessibilityManager::NotifyChildTreeOnDeregister()
6322 {
6323 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "NotifyChildTreeOnDeregister size: %{public}zu",
6324 childTreeCallbackMap_.size());
6325 std::lock_guard<std::mutex> lock(childTreeCallbackMapMutex_);
6326 for (auto &item : childTreeCallbackMap_) {
6327 if (item.second == nullptr) {
6328 continue;
6329 }
6330 item.second->OnDeregister();
6331 }
6332 }
6333
NotifySetChildTreeIdAndWinId(int64_t elementId,const int32_t treeId,const int32_t childWindowId)6334 void JsAccessibilityManager::NotifySetChildTreeIdAndWinId(
6335 int64_t elementId, const int32_t treeId, const int32_t childWindowId)
6336 {
6337 std::lock_guard<std::mutex> lock(childTreeCallbackMapMutex_);
6338 auto findResult = childTreeCallbackMap_.find(elementId);
6339 if (findResult == childTreeCallbackMap_.end()) {
6340 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "node: %{public}" PRId64 " not found, treeId: %{public}d", elementId,
6341 treeId);
6342 return;
6343 }
6344 auto callback = findResult->second;
6345 CHECK_NULL_VOID(callback);
6346 callback->SetChildTreeId(treeId);
6347 callback->OnSetChildTree(childWindowId, treeId);
6348 }
6349
CheckIsChildElement(int64_t & elementId,const std::vector<std::string> & params,std::vector<std::string> & info,DumpMode mode,int64_t & rootId)6350 bool JsAccessibilityManager::CheckIsChildElement(
6351 int64_t &elementId,
6352 const std::vector<std::string> ¶ms,
6353 std::vector<std::string> &info,
6354 DumpMode mode,
6355 int64_t &rootId)
6356 {
6357 int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
6358 int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
6359
6360 if (mode == DumpMode::TREE) {
6361 AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(rootId, splitElementId, splitTreeId);
6362 if (splitTreeId <= 0 || splitTreeId == treeId_) {
6363 rootId = splitElementId;
6364 return false;
6365 }
6366 } else {
6367 if (elementId <= 0) {
6368 return false;
6369 }
6370
6371 AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
6372 if (splitTreeId <= 0 || splitTreeId == treeId_) {
6373 elementId = splitElementId;
6374 return false;
6375 }
6376 }
6377
6378 std::lock_guard<std::mutex> lock(childTreeCallbackMapMutex_);
6379 for (const auto &item : childTreeCallbackMap_) {
6380 if (item.second == nullptr) {
6381 continue;
6382 }
6383 if (item.second->GetChildTreeId() != splitTreeId) {
6384 continue;
6385 }
6386 item.second->OnDumpChildInfo(params, info);
6387 for (const auto &childInfo : info) {
6388 DumpLog::GetInstance().Print(childInfo.c_str());
6389 }
6390 return true;
6391 }
6392 return false;
6393 }
6394
NeedRegisterChildTree(uint32_t parentWindowId,int32_t parentTreeId,int64_t parentElementId)6395 bool JsAccessibilityManager::NeedRegisterChildTree(
6396 uint32_t parentWindowId, int32_t parentTreeId, int64_t parentElementId)
6397 {
6398 if (!IsRegister()) {
6399 return true;
6400 }
6401
6402 if (parentWindowId_ == parentWindowId && parentTreeId_ == parentTreeId && parentElementId_ == parentElementId) {
6403 return false;
6404 }
6405 DeregisterInteractionOperationAsChildTree();
6406 return true;
6407 }
6408
RegisterInteractionOperationAsChildTree(uint32_t parentWindowId,int32_t parentTreeId,int64_t parentElementId)6409 void JsAccessibilityManager::RegisterInteractionOperationAsChildTree(
6410 uint32_t parentWindowId, int32_t parentTreeId, int64_t parentElementId)
6411 {
6412 AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(parentTreeId, parentElementId);
6413 if (!NeedRegisterChildTree(parentWindowId, parentTreeId, parentElementId)) {
6414 return;
6415 }
6416
6417 std::shared_ptr<AccessibilitySystemAbilityClient> instance = AccessibilitySystemAbilityClient::GetInstance();
6418 CHECK_NULL_VOID(instance);
6419 auto pipelineContext = GetPipelineContext().Upgrade();
6420 CHECK_NULL_VOID(pipelineContext);
6421 auto container = Platform::AceContainer::GetContainer(pipelineContext->GetInstanceId());
6422 if (container != nullptr && container->IsUIExtensionWindow()) {
6423 windowId_ = pipelineContext->GetRealHostWindowId();
6424 } else if (pipelineContext->IsFormRender()) {
6425 windowId_ = parentWindowId;
6426 }
6427
6428 uint32_t windowId = GetWindowId();
6429 auto interactionOperation = std::make_shared<JsInteractionOperation>(windowId);
6430 interactionOperation->SetHandler(WeakClaim(this));
6431 Accessibility::Registration registration {
6432 .windowId = windowId,
6433 .parentWindowId = parentWindowId,
6434 .parentTreeId = parentTreeId,
6435 .elementId = parentElementId,
6436 };
6437 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "windowId: %{public}u, parentWindowId: %{public}u, "
6438 "parentTreeId: %{public}d, %{public}" PRId64,
6439 windowId, parentWindowId, parentTreeId, parentElementId);
6440 Accessibility::RetError retReg = instance->RegisterElementOperator(registration, interactionOperation);
6441 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "RegisterElementOperator result: %{public}d", retReg);
6442 Register(retReg == RET_OK);
6443 AceApplicationInfo::GetInstance().SetAccessibilityEnabled(retReg == RET_OK);
6444 parentElementId_ = parentElementId;
6445 parentTreeId_ = parentTreeId;
6446 parentWindowId_ = parentWindowId;
6447
6448 for (const auto& subContext : GetSubPipelineContexts()) {
6449 auto context = subContext.Upgrade();
6450 CHECK_NULL_VOID(context);
6451 interactionOperation = std::make_shared<JsInteractionOperation>(context->GetWindowId());
6452 interactionOperation->SetHandler(WeakClaim(this));
6453 instance->RegisterElementOperator(context->GetWindowId(), interactionOperation);
6454 }
6455 }
6456
SetAccessibilityGetParentRectHandler(std::function<void (int32_t &,int32_t &)> && callback)6457 void JsAccessibilityManager::SetAccessibilityGetParentRectHandler(std::function<void(int32_t &, int32_t &)> &&callback)
6458 {
6459 getParentRectHandler_ = std::move(callback);
6460 }
6461
SetAccessibilityGetParentRectHandler(std::function<void (AccessibilityParentRectInfo &)> && callback)6462 void JsAccessibilityManager::SetAccessibilityGetParentRectHandler(
6463 std::function<void(AccessibilityParentRectInfo &)> &&callback)
6464 {
6465 getParentRectHandlerNew_ = std::move(callback);
6466 }
6467
DeregisterInteractionOperationAsChildTree()6468 void JsAccessibilityManager::DeregisterInteractionOperationAsChildTree()
6469 {
6470 if (!IsRegister()) {
6471 return;
6472 }
6473 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "deregister accessibility childTree");
6474
6475 std::shared_ptr<AccessibilitySystemAbilityClient> instance = AccessibilitySystemAbilityClient::GetInstance();
6476 CHECK_NULL_VOID(instance);
6477 uint32_t windowId = GetWindowId();
6478 Register(false);
6479 currentFocusNodeId_ = -1;
6480 instance->DeregisterElementOperator(windowId, treeId_);
6481 AceApplicationInfo::GetInstance().SetAccessibilityEnabled(false);
6482 parentElementId_ = INVALID_PARENT_ID;
6483 parentTreeId_ = 0;
6484 parentWindowId_ = 0;
6485 NotifyChildTreeOnDeregister();
6486
6487 RefPtr<PipelineBase> context;
6488 for (const auto& subContext : GetSubPipelineContexts()) {
6489 context = subContext.Upgrade();
6490 CHECK_NULL_VOID(context);
6491 instance->DeregisterElementOperator(context->GetWindowId());
6492 }
6493 }
6494
SendUecOnTreeEvent(int64_t splitElementId)6495 void JsAccessibilityManager::SendUecOnTreeEvent(int64_t splitElementId)
6496 {
6497 auto context = GetPipelineContext().Upgrade();
6498 CHECK_NULL_VOID(context);
6499 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
6500 CHECK_NULL_VOID(ngPipeline);
6501 auto rootNode = ngPipeline->GetRootElement();
6502 CHECK_NULL_VOID(rootNode);
6503 auto frameNode = GetFramenodeByAccessibilityId(rootNode, splitElementId);
6504 CHECK_NULL_VOID(frameNode);
6505
6506 if ((!frameNode) || (IsExtensionComponent(frameNode) && !IsUIExtensionShowPlaceholder(frameNode))) {
6507 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "Register element is uec: %{public}s ", frameNode->GetTag().c_str());
6508 rootNode->OnAccessibilityEvent(AccessibilityEventType::CHANGE);
6509 } else {
6510 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "Register element is not uec: %{public}s", frameNode->GetTag().c_str());
6511 }
6512 }
SetChildTreeIdAndWinId(const int64_t nodeId,const int32_t treeId,const int32_t childWindowId)6513 void JsAccessibilityManager::JsInteractionOperation::SetChildTreeIdAndWinId(
6514 const int64_t nodeId, const int32_t treeId, const int32_t childWindowId)
6515 {
6516 int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
6517 int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
6518 AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(nodeId, splitElementId, splitTreeId);
6519 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "SetChildTreeId node: %{public}" PRId64 " treeId: %{public}d",
6520 splitElementId, treeId);
6521 auto jsAccessibilityManager = GetHandler().Upgrade();
6522 CHECK_NULL_VOID(jsAccessibilityManager);
6523 auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
6524 CHECK_NULL_VOID(context);
6525 context->GetTaskExecutor()->PostTask(
6526 [weak = GetHandler(), splitElementId, treeId, childWindowId] {
6527 auto jsAccessibilityManager = weak.Upgrade();
6528 CHECK_NULL_VOID(jsAccessibilityManager);
6529 ACE_SCOPED_TRACE("SetChildTreeIdAndWinId");
6530 jsAccessibilityManager->NotifySetChildTreeIdAndWinId(splitElementId, treeId, childWindowId);
6531 },
6532 TaskExecutor::TaskType::UI, "ArkUISetChildTreeIdAndWinId");
6533 }
6534
SetBelongTreeId(const int32_t treeId)6535 void JsAccessibilityManager::JsInteractionOperation::SetBelongTreeId(const int32_t treeId)
6536 {
6537 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "SetBelongTreeId treeId: %{public}d", treeId);
6538 auto jsAccessibilityManager = GetHandler().Upgrade();
6539 CHECK_NULL_VOID(jsAccessibilityManager);
6540 jsAccessibilityManager->treeId_ = treeId;
6541 auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
6542 CHECK_NULL_VOID(context);
6543 jsAccessibilityManager->SendCacheAccessibilityEvent(context->GetInstanceId());
6544 context->GetTaskExecutor()->PostTask(
6545 [weak = GetHandler(), treeId] {
6546 auto jsAccessibilityManager = weak.Upgrade();
6547 CHECK_NULL_VOID(jsAccessibilityManager);
6548 ACE_SCOPED_TRACE("SetBelongTreeId");
6549 jsAccessibilityManager->NotifyChildTreeOnRegister(treeId);
6550 },
6551 TaskExecutor::TaskType::UI, "ArkUIAccessibilityClearCurrentFocus");
6552 }
6553
UpdateElementInfoTreeId(Accessibility::AccessibilityElementInfo & info)6554 void JsAccessibilityManager::UpdateElementInfoTreeId(Accessibility::AccessibilityElementInfo& info)
6555 {
6556 int32_t treeId = info.GetBelongTreeId();
6557 if (treeId <= 0) {
6558 return;
6559 }
6560
6561 int64_t elementId = info.GetAccessibilityId();
6562 AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(treeId, elementId);
6563 info.SetAccessibilityId(elementId);
6564
6565 int64_t parentId = info.GetParentNodeId();
6566 if (parentId != INVALID_PARENT_ID) {
6567 AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(treeId, parentId);
6568 info.SetParent(parentId);
6569 }
6570
6571 UpdateElementInfoPageIdWithTreeId(info, treeId);
6572
6573 std::vector<int64_t> childIds = info.GetChildIds();
6574 for (int64_t child : childIds) {
6575 info.RemoveChild(child);
6576 AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(treeId, child);
6577 info.AddChild(child);
6578 }
6579 }
6580
UpdateElementInfosTreeId(std::list<Accessibility::AccessibilityElementInfo> & infos)6581 void JsAccessibilityManager::UpdateElementInfosTreeId(std::list<Accessibility::AccessibilityElementInfo>& infos)
6582 {
6583 for (auto &item : infos) {
6584 int32_t treeId = item.GetBelongTreeId();
6585 if (treeId <= 0) {
6586 continue;
6587 }
6588
6589 int64_t elementId = item.GetAccessibilityId();
6590 AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(treeId, elementId);
6591 item.SetAccessibilityId(elementId);
6592
6593 int64_t parentId = item.GetParentNodeId();
6594 if (parentId != INVALID_PARENT_ID) {
6595 AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(treeId, parentId);
6596 item.SetParent(parentId);
6597 }
6598
6599 UpdateElementInfoPageIdWithTreeId(item, treeId);
6600
6601 std::vector<int64_t> childIds = item.GetChildIds();
6602 for (int64_t child : childIds) {
6603 item.RemoveChild(child);
6604 AccessibilitySystemAbilityClient::SetSplicElementIdTreeId(treeId, child);
6605 item.AddChild(child);
6606 }
6607 }
6608 }
6609
SetPipelineContext(const RefPtr<PipelineBase> & context)6610 void JsAccessibilityManager::SetPipelineContext(const RefPtr<PipelineBase>& context)
6611 {
6612 context_ = context;
6613 if (stateObserver_[AccessibilityStateEventType::EVENT_ACCESSIBILITY_STATE_CHANGED] != nullptr) {
6614 stateObserver_[AccessibilityStateEventType::EVENT_ACCESSIBILITY_STATE_CHANGED]->SetPipeline(context_);
6615 }
6616 }
6617
OnStateChanged(const bool state)6618 void JsAccessibilityManager::JsAccessibilityStateObserver::OnStateChanged(const bool state)
6619 {
6620 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "accessibility state changed:%{public}d, event type:%{public}u", state,
6621 eventType_);
6622
6623 // Do not upgrade jsAccessibilityManager on async thread, destructor will cause freeze
6624 auto pipelineRef = pipeline_.Upgrade();
6625 CHECK_NULL_VOID(pipelineRef);
6626 pipelineRef->GetTaskExecutor()->PostTask(
6627 [weak = accessibilityManager_, state, eventType = eventType_]() {
6628 auto jsAccessibilityManager = weak.Upgrade();
6629 CHECK_NULL_VOID(jsAccessibilityManager);
6630 if (eventType == AccessibilityStateEventType::EVENT_ACCESSIBILITY_STATE_CHANGED) {
6631 if (state) {
6632 jsAccessibilityManager->RegisterInteractionOperation(jsAccessibilityManager->GetWindowId());
6633 } else {
6634 jsAccessibilityManager->DeregisterInteractionOperation();
6635 }
6636 AceApplicationInfo::GetInstance().SetAccessibilityEnabled(state);
6637 jsAccessibilityManager->NotifyAccessibilitySAStateChange(state);
6638 } else if (eventType == AccessibilityStateEventType::EVENT_SCREEN_READER_STATE_CHANGED) {
6639 jsAccessibilityManager->isScreenReaderEnabled_ = state;
6640 }
6641 },
6642 TaskExecutor::TaskType::UI, "ArkUIAccessibilityStateChanged");
6643 }
6644
FocusMoveSearch(int64_t elementId,const int32_t direction,const int32_t requestId,AccessibilityElementOperatorCallback & callback)6645 void JsAccessibilityManager::JsInteractionOperation::FocusMoveSearch(
6646 int64_t elementId, const int32_t direction, const int32_t requestId, AccessibilityElementOperatorCallback& callback)
6647 {
6648 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "move search: %{public}" PRId64 ", direction: %{public}d",
6649 elementId, direction);
6650 int64_t splitElementId = AccessibilityElementInfo::UNDEFINED_ACCESSIBILITY_ID;
6651 int32_t splitTreeId = AccessibilityElementInfo::UNDEFINED_TREE_ID;
6652 AccessibilitySystemAbilityClient::GetTreeIdAndElementIdBySplitElementId(elementId, splitElementId, splitTreeId);
6653
6654 auto jsAccessibilityManager = GetHandler().Upgrade();
6655 CHECK_NULL_VOID(jsAccessibilityManager);
6656 auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
6657 CHECK_NULL_VOID(context);
6658 auto windowId = windowId_;
6659 context->GetTaskExecutor()->PostTask(
6660 [weak = GetHandler(), splitElementId, direction, requestId, &callback, windowId] {
6661 auto jsAccessibilityManager = weak.Upgrade();
6662 CHECK_NULL_VOID(jsAccessibilityManager);
6663 ACE_SCOPED_TRACE("FocusMoveSearch");
6664 jsAccessibilityManager->FocusMoveSearch(splitElementId, direction, requestId, callback, windowId);
6665 },
6666 TaskExecutor::TaskType::UI, "ArkUIAccessibilityFocusMoveSearch");
6667 }
6668
FocusMoveSearch(const int64_t elementId,const int32_t direction,const int32_t requestId,Accessibility::AccessibilityElementOperatorCallback & callback,const int32_t windowId)6669 void JsAccessibilityManager::FocusMoveSearch(const int64_t elementId, const int32_t direction, const int32_t requestId,
6670 Accessibility::AccessibilityElementOperatorCallback& callback, const int32_t windowId)
6671 {
6672 AccessibilityElementInfo nodeInfo;
6673 auto context = GetPipelineByWindowId(windowId);
6674 if (!context) {
6675 nodeInfo.SetValidElement(false);
6676 SetFocusMoveSearchResult(callback, nodeInfo, requestId);
6677 return;
6678 }
6679
6680 if (AceType::InstanceOf<NG::PipelineContext>(context)) {
6681 FocusMoveSearchNG(elementId, direction, nodeInfo, context, NG::UI_EXTENSION_OFFSET_MAX);
6682 SetFocusMoveSearchResult(callback, nodeInfo, requestId);
6683 return;
6684 }
6685
6686 auto node = GetAccessibilityNodeFromPage(elementId);
6687 if (!node) {
6688 nodeInfo.SetValidElement(false);
6689 SetFocusMoveSearchResult(callback, nodeInfo, requestId);
6690 return;
6691 }
6692
6693 // get root node.
6694 auto rootNode = node;
6695 while (rootNode->GetParentNode()) {
6696 rootNode = rootNode->GetParentNode();
6697 if (!rootNode->GetParentNode()) {
6698 break;
6699 }
6700 }
6701
6702 std::list<RefPtr<AccessibilityNode>> nodeList;
6703 AddFocusableNode(nodeList, rootNode);
6704 RefPtr<AccessibilityNode> resultNode;
6705
6706 switch (direction) {
6707 case FocusMoveDirection::FORWARD:
6708 case FocusMoveDirection::BACKWARD:
6709 // forward and backward
6710 resultNode = FindNodeInRelativeDirection(nodeList, node, direction);
6711 break;
6712 case FocusMoveDirection::UP:
6713 case FocusMoveDirection::DOWN:
6714 case FocusMoveDirection::LEFT:
6715 case FocusMoveDirection::RIGHT:
6716 // up, down, left and right
6717 resultNode = FindNodeInAbsoluteDirection(nodeList, node, direction);
6718 break;
6719 default:
6720 break;
6721 }
6722
6723 if (resultNode) {
6724 auto jsAccessibilityManager = Claim(this);
6725 UpdateAccessibilityNodeInfo(resultNode, nodeInfo, jsAccessibilityManager, windowId_);
6726 }
6727
6728 SetFocusMoveSearchResult(callback, nodeInfo, requestId);
6729 }
6730
AddFocusableNode(std::list<RefPtr<AccessibilityNode>> & nodeList,const RefPtr<AccessibilityNode> & node)6731 void JsAccessibilityManager::AddFocusableNode(
6732 std::list<RefPtr<AccessibilityNode>>& nodeList, const RefPtr<AccessibilityNode>& node)
6733 {
6734 const std::string importance = node->GetImportantForAccessibility();
6735 if (CanAccessibilityFocused(node)) {
6736 nodeList.push_back(node);
6737 }
6738 if (!node->GetAccessible() && importance != "no-hide-descendants") {
6739 for (auto& child : node->GetChildList()) {
6740 AddFocusableNode(nodeList, child);
6741 }
6742 }
6743 }
6744
CanAccessibilityFocused(const RefPtr<AccessibilityNode> & node)6745 bool JsAccessibilityManager::CanAccessibilityFocused(const RefPtr<AccessibilityNode>& node)
6746 {
6747 return node != nullptr && !node->IsRootNode() && node->GetVisible() &&
6748 node->GetImportantForAccessibility() != "no" &&
6749 node->GetImportantForAccessibility() != "no-hide-descendants";
6750 }
6751
FindNodeInRelativeDirection(const std::list<RefPtr<AccessibilityNode>> & nodeList,RefPtr<AccessibilityNode> & node,const int direction)6752 RefPtr<AccessibilityNode> JsAccessibilityManager::FindNodeInRelativeDirection(
6753 const std::list<RefPtr<AccessibilityNode>>& nodeList, RefPtr<AccessibilityNode>& node, const int direction)
6754 {
6755 switch (direction) {
6756 case FocusMoveDirection::FORWARD:
6757 return GetNextFocusableNode(nodeList, node);
6758 case FocusMoveDirection::BACKWARD:
6759 return GetPreviousFocusableNode(nodeList, node);
6760 default:
6761 break;
6762 }
6763
6764 return nullptr;
6765 }
6766
FindNodeInAbsoluteDirection(const std::list<RefPtr<AccessibilityNode>> & nodeList,RefPtr<AccessibilityNode> & node,const int direction)6767 RefPtr<AccessibilityNode> JsAccessibilityManager::FindNodeInAbsoluteDirection(
6768 const std::list<RefPtr<AccessibilityNode>>& nodeList, RefPtr<AccessibilityNode>& node, const int direction)
6769 {
6770 auto tempBest = node->GetRect();
6771 auto nodeRect = node->GetRect();
6772
6773 switch (direction) {
6774 case FocusMoveDirection::LEFT:
6775 tempBest.SetLeft(node->GetLeft() + node->GetWidth() + 1);
6776 break;
6777 case FocusMoveDirection::RIGHT:
6778 tempBest.SetLeft(node->GetLeft() - node->GetWidth() - 1);
6779 break;
6780 case FocusMoveDirection::UP:
6781 tempBest.SetTop(node->GetTop() + node->GetHeight() + 1);
6782 break;
6783 case FocusMoveDirection::DOWN:
6784 tempBest.SetTop(node->GetTop() - node->GetHeight() - 1);
6785 break;
6786 default:
6787 break;
6788 }
6789
6790 RefPtr<AccessibilityNode> nearestNode = nullptr;
6791 for (auto nodeItem = nodeList.begin(); nodeItem != nodeList.end(); nodeItem++) {
6792 if ((*nodeItem)->GetNodeId() == node->GetNodeId() || (*nodeItem)->IsRootNode()) {
6793 continue;
6794 }
6795 auto itemRect = (*nodeItem)->GetRect();
6796 if (CheckBetterRect(nodeRect, direction, itemRect, tempBest)) {
6797 tempBest = itemRect;
6798 nearestNode = (*nodeItem);
6799 }
6800 }
6801
6802 return nearestNode;
6803 }
6804
GetNextFocusableNode(const std::list<RefPtr<AccessibilityNode>> & nodeList,RefPtr<AccessibilityNode> & node)6805 RefPtr<AccessibilityNode> JsAccessibilityManager::GetNextFocusableNode(
6806 const std::list<RefPtr<AccessibilityNode>>& nodeList, RefPtr<AccessibilityNode>& node)
6807 {
6808 auto nodeItem = nodeList.begin();
6809 for (; nodeItem != nodeList.end(); nodeItem++) {
6810 if ((*nodeItem)->GetNodeId() == node->GetNodeId()) {
6811 break;
6812 }
6813 }
6814
6815 if (nodeItem != nodeList.end() && ++nodeItem != nodeList.end()) {
6816 return (*nodeItem);
6817 }
6818 if (!nodeList.empty()) {
6819 return (*nodeList.begin());
6820 }
6821
6822 return nullptr;
6823 }
6824
GetPreviousFocusableNode(const std::list<RefPtr<AccessibilityNode>> & nodeList,RefPtr<AccessibilityNode> & node)6825 RefPtr<AccessibilityNode> JsAccessibilityManager::GetPreviousFocusableNode(
6826 const std::list<RefPtr<AccessibilityNode>>& nodeList, RefPtr<AccessibilityNode>& node)
6827 {
6828 auto nodeItem = nodeList.rbegin();
6829 for (; nodeItem != nodeList.rend(); nodeItem++) {
6830 if ((*nodeItem)->GetNodeId() == node->GetNodeId()) {
6831 break;
6832 }
6833 }
6834
6835 if (nodeItem != nodeList.rend() && ++nodeItem != nodeList.rend()) {
6836 return (*nodeItem);
6837 }
6838
6839 if (!nodeList.empty()) {
6840 return (*nodeList.rbegin());
6841 }
6842 return nullptr;
6843 }
6844
RequestAccessibilityFocus(const RefPtr<AccessibilityNode> & node)6845 bool JsAccessibilityManager::RequestAccessibilityFocus(const RefPtr<AccessibilityNode>& node)
6846 {
6847 auto requestNodeId = node->GetNodeId();
6848 if (currentFocusNodeId_ == requestNodeId) {
6849 return false;
6850 }
6851
6852 ClearCurrentFocus();
6853 currentFocusNodeId_ = requestNodeId;
6854 node->SetAccessibilityFocusedState(true);
6855 return node->ActionAccessibilityFocus(true);
6856 }
6857
ClearAccessibilityFocus(const RefPtr<AccessibilityNode> & node)6858 bool JsAccessibilityManager::ClearAccessibilityFocus(const RefPtr<AccessibilityNode>& node)
6859 {
6860 auto requestNodeId = node->GetNodeId();
6861 if (currentFocusNodeId_ != requestNodeId) {
6862 return false;
6863 }
6864
6865 currentFocusNodeId_ = -1;
6866 node->SetAccessibilityFocusedState(false);
6867 return node->ActionAccessibilityFocus(false);
6868 }
6869
ClearCurrentFocus()6870 bool JsAccessibilityManager::ClearCurrentFocus()
6871 {
6872 auto currentFocusNode = GetAccessibilityNodeFromPage(currentFocusNodeId_);
6873 CHECK_NULL_RETURN(currentFocusNode, false);
6874 currentFocusNodeId_ = -1;
6875 currentFocusNode->SetFocusedState(false);
6876 currentFocusNode->SetAccessibilityFocusedState(false);
6877 return currentFocusNode->ActionAccessibilityFocus(false);
6878 }
6879
FocusExtensionElementMoveSearchNG(const SearchParameter & searchParam,const RefPtr<NG::FrameNode> & node,Accessibility::AccessibilityElementInfo & info)6880 void FocusExtensionElementMoveSearchNG(const SearchParameter& searchParam,
6881 const RefPtr<NG::FrameNode>& node, Accessibility::AccessibilityElementInfo& info)
6882 {
6883 if (NG::UI_EXTENSION_OFFSET_MIN < (searchParam.uiExtensionOffset + 1)) {
6884 node->FocusMoveSearchNG(searchParam.nodeId, searchParam.mode,
6885 searchParam.uiExtensionOffset / NG::UI_EXTENSION_ID_FACTOR, info);
6886 } else {
6887 info.SetValidElement(false);
6888 }
6889 }
6890
GetExtensionNextFocusableNode(const AccessibilityElementInfo & focusElement,const std::list<AccessibilityElementInfo> & nodeList,AccessibilityElementInfo & node)6891 void GetExtensionNextFocusableNode(const AccessibilityElementInfo& focusElement,
6892 const std::list<AccessibilityElementInfo>& nodeList, AccessibilityElementInfo& node)
6893 {
6894 auto nodeItem = nodeList.begin();
6895 for (; nodeItem != nodeList.end(); nodeItem++) {
6896 if ((*nodeItem).GetAccessibilityId() == focusElement.GetAccessibilityId()) {
6897 break;
6898 }
6899 }
6900
6901 if (nodeItem != nodeList.end() && ++nodeItem != nodeList.end()) {
6902 node = (*nodeItem);
6903 }
6904 if (!nodeList.empty()) {
6905 node = (*nodeList.begin());
6906 }
6907 }
6908
GetExtensionPreviousFocusableNode(const AccessibilityElementInfo & focusElement,const std::list<AccessibilityElementInfo> & nodeList,AccessibilityElementInfo & node)6909 void GetExtensionPreviousFocusableNode(const AccessibilityElementInfo& focusElement,
6910 const std::list<AccessibilityElementInfo>& nodeList, AccessibilityElementInfo& node)
6911 {
6912 auto nodeItem = nodeList.rbegin();
6913 for (; nodeItem != nodeList.rend(); nodeItem++) {
6914 if ((*nodeItem).GetAccessibilityId() == focusElement.GetAccessibilityId()) {
6915 break;
6916 }
6917 }
6918
6919 if (nodeItem != nodeList.rend() && ++nodeItem != nodeList.rend()) {
6920 node = (*nodeItem);
6921 }
6922
6923 if (!nodeList.empty()) {
6924 node = (*nodeList.rbegin());
6925 }
6926 }
6927
FindExtensionNodeInAbsoluteDirection(const AccessibilityElementInfo & focusElement,const std::list<AccessibilityElementInfo> & nodeList,AccessibilityElementInfo & node,int32_t direction)6928 void FindExtensionNodeInAbsoluteDirection(const AccessibilityElementInfo& focusElement,
6929 const std::list<AccessibilityElementInfo>& nodeList, AccessibilityElementInfo& node, int32_t direction)
6930 {
6931 auto left = focusElement.GetRectInScreen().GetLeftTopXScreenPostion();
6932 auto top = focusElement.GetRectInScreen().GetLeftTopYScreenPostion();
6933 auto width = focusElement.GetRectInScreen().GetRightBottomXScreenPostion() -
6934 focusElement.GetRectInScreen().GetLeftTopXScreenPostion();
6935 auto height = focusElement.GetRectInScreen().GetRightBottomYScreenPostion() -
6936 focusElement.GetRectInScreen().GetLeftTopYScreenPostion();
6937 Rect rect(left, top, width, height);
6938 Rect tempBest(left, top, width, height);
6939 auto nodeRect = tempBest;
6940 switch (direction) {
6941 case FocusMoveDirection::LEFT:
6942 tempBest.SetLeft(left + width + 1);
6943 break;
6944 case FocusMoveDirection::RIGHT:
6945 tempBest.SetLeft(left - width - 1);
6946 break;
6947 case FocusMoveDirection::UP:
6948 tempBest.SetTop(top + height + 1);
6949 break;
6950 case FocusMoveDirection::DOWN:
6951 tempBest.SetTop(top - height - 1);
6952 break;
6953 default:
6954 break;
6955 }
6956 for (const auto& nodeItem : nodeList) {
6957 if (nodeItem.GetAccessibilityId() == focusElement.GetAccessibilityId() ||
6958 V2::ROOT_ETS_TAG == nodeItem.GetComponentType()) {
6959 continue;
6960 }
6961 left = nodeItem.GetRectInScreen().GetLeftTopXScreenPostion();
6962 top = nodeItem.GetRectInScreen().GetLeftTopYScreenPostion();
6963 width = nodeItem.GetRectInScreen().GetRightBottomXScreenPostion() -
6964 nodeItem.GetRectInScreen().GetLeftTopXScreenPostion();
6965 height = nodeItem.GetRectInScreen().GetRightBottomYScreenPostion() -
6966 nodeItem.GetRectInScreen().GetLeftTopYScreenPostion();
6967 Rect itemRect(left, top, width, height);
6968 if (CheckBetterRect(nodeRect, direction, itemRect, tempBest)) {
6969 tempBest = itemRect;
6970 node = nodeItem;
6971 }
6972 }
6973 }
6974
FindExtensionNodeInRelativeDirection(const AccessibilityElementInfo & focusElement,const std::list<AccessibilityElementInfo> & nodeList,AccessibilityElementInfo & node,int direction)6975 void FindExtensionNodeInRelativeDirection(const AccessibilityElementInfo& focusElement,
6976 const std::list<AccessibilityElementInfo>& nodeList, AccessibilityElementInfo& node, int direction)
6977 {
6978 switch (direction) {
6979 case FocusMoveDirection::FORWARD:
6980 GetExtensionNextFocusableNode(focusElement, nodeList, node);
6981 break;
6982 case FocusMoveDirection::BACKWARD:
6983 GetExtensionPreviousFocusableNode(focusElement, nodeList, node);
6984 break;
6985 default:
6986 break;
6987 }
6988 }
6989
FilterAccessibilityElementByFocusable(std::list<AccessibilityElementInfo> & elementList,AccessibilityElementInfo & focusElement,int64_t elementId)6990 void FilterAccessibilityElementByFocusable(std::list<AccessibilityElementInfo>& elementList,
6991 AccessibilityElementInfo& focusElement, int64_t elementId)
6992 {
6993 auto input = elementList;
6994 elementList.clear();
6995 std::set<int64_t> filterIds;
6996 for (auto& element : input) {
6997 if (filterIds.find(element.GetParentNodeId()) != filterIds.end()) {
6998 filterIds.insert(element.GetAccessibilityId());
6999 continue;
7000 }
7001 auto width = element.GetRectInScreen().GetRightBottomXScreenPostion() -
7002 element.GetRectInScreen().GetLeftTopXScreenPostion();
7003 auto height = element.GetRectInScreen().GetRightBottomYScreenPostion() -
7004 element.GetRectInScreen().GetLeftTopYScreenPostion();
7005 if (width == 0 || height == 0) {
7006 filterIds.insert(element.GetAccessibilityId());
7007 continue;
7008 }
7009 elementList.emplace_back(element);
7010 if (element.GetAccessibilityId() == elementId) {
7011 focusElement = element;
7012 }
7013 }
7014 }
7015
GetResultOfFocusMoveSearchNG(int64_t elementId,int32_t direction,AccessibilityElementInfo & info)7016 void JsAccessibilityManager::GetResultOfFocusMoveSearchNG(
7017 int64_t elementId, int32_t direction, AccessibilityElementInfo& info)
7018 {
7019 auto pipeline = context_.Upgrade();
7020 CHECK_NULL_VOID(pipeline);
7021 std::list<AccessibilityElementInfo> nodeList;
7022 SearchElementInfoByAccessibilityIdNG(NG::UI_EXTENSION_ROOT_ID,
7023 PREFETCH_RECURSIVE_CHILDREN, nodeList, pipeline, NG::UI_EXTENSION_OFFSET_MAX);
7024 AccessibilityElementInfo focusElement;
7025 FilterAccessibilityElementByFocusable(nodeList, focusElement, elementId);
7026 switch (direction) {
7027 case FocusMoveDirection::FORWARD:
7028 case FocusMoveDirection::BACKWARD:
7029 Framework::FindExtensionNodeInRelativeDirection(focusElement, nodeList, info, direction);
7030 break;
7031 case FocusMoveDirection::UP:
7032 case FocusMoveDirection::DOWN:
7033 case FocusMoveDirection::LEFT:
7034 case FocusMoveDirection::RIGHT:
7035 Framework::FindExtensionNodeInAbsoluteDirection(focusElement, nodeList, info, direction);
7036 break;
7037 default:
7038 break;
7039 }
7040 }
7041
FocusMoveSearchNG(int64_t elementId,int32_t direction,Accessibility::AccessibilityElementInfo & info,const RefPtr<PipelineBase> & context,const int64_t uiExtensionOffset)7042 void JsAccessibilityManager::FocusMoveSearchNG(int64_t elementId, int32_t direction,
7043 Accessibility::AccessibilityElementInfo& info, const RefPtr<PipelineBase>& context,
7044 const int64_t uiExtensionOffset)
7045 {
7046 auto mainContext = context_.Upgrade();
7047 CHECK_NULL_VOID(mainContext);
7048 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
7049 CHECK_NULL_VOID(ngPipeline);
7050 auto rootNode = ngPipeline->GetRootElement();
7051 CHECK_NULL_VOID(rootNode);
7052 auto node = GetFramenodeByAccessibilityId(rootNode, elementId);
7053 info.SetValidElement(false);
7054 GetResultOfFocusMoveSearchNG(elementId, direction, info);
7055 }
7056
FocusExtensionElementMoveSearchNG(const SearchParameter & searchParam,Accessibility::AccessibilityElementInfo & info,const RefPtr<PipelineBase> & context,const RefPtr<NG::FrameNode> & root,RefPtr<NG::FrameNode> & outputExtensionNode)7057 void JsAccessibilityManager::FocusExtensionElementMoveSearchNG(const SearchParameter& searchParam,
7058 Accessibility::AccessibilityElementInfo& info, const RefPtr<PipelineBase>& context,
7059 const RefPtr<NG::FrameNode>& root, RefPtr<NG::FrameNode>& outputExtensionNode)
7060 {
7061 #ifdef WINDOW_SCENE_SUPPORTED
7062 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
7063 CHECK_NULL_VOID(ngPipeline);
7064 auto uiExtensionManager = ngPipeline->GetUIExtensionManager();
7065 CHECK_NULL_VOID(uiExtensionManager);
7066 auto elementIdPair =
7067 uiExtensionManager->UnWrapExtensionAbilityId(searchParam.uiExtensionOffset, searchParam.nodeId);
7068 outputExtensionNode = uiExtensionManager->GetFocusUiExtensionNode();
7069 CHECK_NULL_VOID(outputExtensionNode);
7070 SearchParameter transferSearchParam {elementIdPair.second, "",
7071 searchParam.mode, searchParam.uiExtensionOffset};
7072 OHOS::Ace::Framework::FocusExtensionElementMoveSearchNG(transferSearchParam, outputExtensionNode, info);
7073 AccessibilityElementInfo parentInfo;
7074 ConvertExtensionAccessibilityId(info, outputExtensionNode, searchParam.uiExtensionOffset, parentInfo);
7075 #endif
7076 }
7077
7078 // AccessibilitySystemAbilityClient will release callback after DeregisterElementOperator
SetSearchElementInfoByAccessibilityIdResult(AccessibilityElementOperatorCallback & callback,std::list<AccessibilityElementInfo> && infos,const int32_t requestId)7079 void JsAccessibilityManager::SetSearchElementInfoByAccessibilityIdResult(AccessibilityElementOperatorCallback& callback,
7080 std::list<AccessibilityElementInfo>&& infos, const int32_t requestId)
7081 {
7082 if (!IsRegister()) {
7083 return;
7084 }
7085 auto context = GetPipelineContext().Upgrade();
7086 CHECK_NULL_VOID(context);
7087 context->GetTaskExecutor()->PostTask(
7088 [weak = WeakClaim(this), infos = std::move(infos), &callback, requestId] () mutable {
7089 auto jsAccessibilityManager = weak.Upgrade();
7090 CHECK_NULL_VOID(jsAccessibilityManager);
7091 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "winId: %{public}d, treeId: %{public}d, reqId: %{public}d",
7092 jsAccessibilityManager->windowId_, jsAccessibilityManager->treeId_, requestId);
7093 if (!jsAccessibilityManager->IsRegister()) {
7094 return;
7095 }
7096 jsAccessibilityManager->UpdateElementInfosTreeId(infos);
7097 callback.SetSearchElementInfoByAccessibilityIdResult(infos, requestId);
7098 }, TaskExecutor::TaskType::BACKGROUND, "ArkUIAccessibilitySetSearchElementInfoById");
7099 }
7100
SetSearchElementInfoByTextResult(AccessibilityElementOperatorCallback & callback,std::list<AccessibilityElementInfo> && infos,const int32_t requestId)7101 void JsAccessibilityManager::SetSearchElementInfoByTextResult(AccessibilityElementOperatorCallback& callback,
7102 std::list<AccessibilityElementInfo>&& infos, const int32_t requestId)
7103 {
7104 if (!IsRegister()) {
7105 return;
7106 }
7107 auto context = GetPipelineContext().Upgrade();
7108 CHECK_NULL_VOID(context);
7109 context->GetTaskExecutor()->PostTask(
7110 [weak = WeakClaim(this), infos = std::move(infos), &callback, requestId] () mutable {
7111 auto jsAccessibilityManager = weak.Upgrade();
7112 CHECK_NULL_VOID(jsAccessibilityManager);
7113 if (!jsAccessibilityManager->IsRegister()) {
7114 return;
7115 }
7116 jsAccessibilityManager->UpdateElementInfosTreeId(infos);
7117 callback.SetSearchElementInfoByTextResult(infos, requestId);
7118 }, TaskExecutor::TaskType::BACKGROUND, "ArkUIAccessibilitySetSearchElementInfoByText");
7119 }
7120
SetSearchDefaultFocusByWindowIdResult(AccessibilityElementOperatorCallback & callback,std::list<AccessibilityElementInfo> && infos,const int32_t requestId)7121 void JsAccessibilityManager::SetSearchDefaultFocusByWindowIdResult(AccessibilityElementOperatorCallback& callback,
7122 std::list<AccessibilityElementInfo>&& infos, const int32_t requestId)
7123 {
7124 if (!IsRegister()) {
7125 return;
7126 }
7127 auto context = GetPipelineContext().Upgrade();
7128 CHECK_NULL_VOID(context);
7129 context->GetTaskExecutor()->PostTask(
7130 [weak = WeakClaim(this), infos = std::move(infos), &callback, requestId] () mutable {
7131 auto jsAccessibilityManager = weak.Upgrade();
7132 CHECK_NULL_VOID(jsAccessibilityManager);
7133 if (!jsAccessibilityManager->IsRegister()) {
7134 return;
7135 }
7136 jsAccessibilityManager->UpdateElementInfosTreeId(infos);
7137 callback.SetSearchDefaultFocusByWindowIdResult(infos, requestId);
7138 }, TaskExecutor::TaskType::BACKGROUND, "ArkUIAccessibilitySetSearchDefaultFocusByWindowId");
7139 }
7140
SetFindFocusedElementInfoResult(AccessibilityElementOperatorCallback & callback,AccessibilityElementInfo & info,const int32_t requestId)7141 void JsAccessibilityManager::SetFindFocusedElementInfoResult(
7142 AccessibilityElementOperatorCallback& callback, AccessibilityElementInfo& info, const int32_t requestId)
7143 {
7144 if (IsRegister()) {
7145 UpdateElementInfoTreeId(info);
7146 callback.SetFindFocusedElementInfoResult(info, requestId);
7147 }
7148 }
7149
SetFocusMoveSearchResult(AccessibilityElementOperatorCallback & callback,AccessibilityElementInfo & info,const int32_t requestId)7150 void JsAccessibilityManager::SetFocusMoveSearchResult(
7151 AccessibilityElementOperatorCallback& callback, AccessibilityElementInfo& info, const int32_t requestId)
7152 {
7153 if (IsRegister()) {
7154 UpdateElementInfoTreeId(info);
7155 callback.SetFocusMoveSearchResult(info, requestId);
7156 }
7157 }
7158
SetFocusMoveResultWithNode(const WeakPtr<NG::FrameNode> & hostNode,AccessibilityElementOperatorCallback & callback,const int32_t requestId)7159 void JsAccessibilityManager::SetFocusMoveResultWithNode(
7160 const WeakPtr<NG::FrameNode>& hostNode, AccessibilityElementOperatorCallback& callback, const int32_t requestId)
7161 {
7162 if (!IsRegister()) {
7163 return;
7164 }
7165 AccessibilityElementInfo nodeInfo;
7166 auto host = hostNode.Upgrade();
7167 if (host) {
7168 auto context = host->GetContextRefPtr();
7169 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
7170 CommonProperty commonProperty;
7171 GenerateCommonProperty(ngPipeline, commonProperty, ngPipeline, host);
7172 UpdateAccessibilityElementInfo(host, commonProperty, nodeInfo, ngPipeline);
7173 } else {
7174 nodeInfo.SetValidElement(false);
7175 }
7176 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY,
7177 "SetFocusMoveResultWithNode : %{public}" PRId64, nodeInfo.GetAccessibilityId());
7178 SetFocusMoveSearchResult(callback, nodeInfo, requestId);
7179 }
7180
SetExecuteActionResult(AccessibilityElementOperatorCallback & callback,const bool succeeded,const int32_t requestId)7181 void JsAccessibilityManager::SetExecuteActionResult(
7182 AccessibilityElementOperatorCallback& callback, const bool succeeded, const int32_t requestId)
7183 {
7184 if (IsRegister()) {
7185 callback.SetExecuteActionResult(succeeded, requestId);
7186 }
7187 }
7188
GetPagePath()7189 std::string JsAccessibilityManager::GetPagePath()
7190 {
7191 auto context = context_.Upgrade();
7192 CHECK_NULL_RETURN(context, "");
7193 auto frontend = context->GetFrontend();
7194 CHECK_NULL_RETURN(frontend, "");
7195 ContainerScope scope(context->GetInstanceId());
7196 return frontend->GetPagePath();
7197 }
7198
IsUpdateWindowSceneInfo(const RefPtr<NG::FrameNode> & node,NG::WindowSceneInfo & windowSceneInfo)7199 bool JsAccessibilityManager::IsUpdateWindowSceneInfo(const RefPtr<NG::FrameNode>& node,
7200 NG::WindowSceneInfo& windowSceneInfo)
7201 {
7202 CHECK_NULL_RETURN(node, false);
7203 // update windowScene node commonProperty left, top position and get scale data
7204 auto parent = node->GetAncestorNodeOfFrame(false);
7205 if (node->GetTag() == V2::WINDOW_SCENE_ETS_TAG) {
7206 parent = node;
7207 }
7208
7209 while (parent) {
7210 // window scene with windowboundary property, is the same as window
7211 if ((parent->GetTag() != V2::WINDOW_SCENE_ETS_TAG) || (!parent->IsWindowBoundary())) {
7212 parent = parent->GetAncestorNodeOfFrame(false);
7213 continue;
7214 }
7215 auto accessibilityProperty = parent->GetAccessibilityProperty<NG::AccessibilityProperty>();
7216 if (accessibilityProperty) {
7217 accessibilityProperty->GetWindowScenePosition(windowSceneInfo);
7218 }
7219 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY,
7220 "windowScene nodeId: %{public}" PRId64
7221 ", left: %{public}d, top: %{public}d, windowSceneScale: [%{public}f, %{public}f], "
7222 "innerWindowId:%{public}d, type: %{public}d",
7223 parent->GetAccessibilityId(), windowSceneInfo.left, windowSceneInfo.top,
7224 windowSceneInfo.scaleX, windowSceneInfo.scaleY, windowSceneInfo.innerWindowId,
7225 parent->GetWindowPatternType());
7226 return true;
7227 }
7228 return false;
7229 }
7230
UpdateElementInfoInnerWindowId(Accessibility::AccessibilityElementInfo & info,const int64_t & elementId)7231 void JsAccessibilityManager::UpdateElementInfoInnerWindowId(
7232 Accessibility::AccessibilityElementInfo& info, const int64_t& elementId)
7233 {
7234 auto node = FindNodeFromPipeline(context_, elementId);
7235 if (node) {
7236 NG::WindowSceneInfo windowSceneInfo;
7237 IsUpdateWindowSceneInfo(node, windowSceneInfo);
7238 info.SetInnerWindowId(windowSceneInfo.innerWindowId);
7239 }
7240 }
7241
GetPagePathInPageNodes(int32_t pageId,const std::vector<RefPtr<NG::FrameNode>> & pageNodes,const std::vector<std::string> pagePaths)7242 const std::string JsAccessibilityManager::GetPagePathInPageNodes(
7243 int32_t pageId,
7244 const std::vector<RefPtr<NG::FrameNode>>& pageNodes,
7245 const std::vector<std::string> pagePaths)
7246 {
7247 if (pagePaths.empty()) {
7248 return GetPagePath();
7249 }
7250 if (pagePaths.size() != pageNodes.size()) {
7251 return GetPagePath();
7252 }
7253 for (std::size_t i = 0; i < pageNodes.size(); ++i) {
7254 CHECK_NULL_CONTINUE(pageNodes[i]);
7255 if (pageId != pageNodes[i]->GetPageId()) {
7256 continue;
7257 }
7258 return pagePaths[i];
7259 }
7260 return GetPagePath();
7261 }
7262
GetCurrentWindowPages(const RefPtr<NG::PipelineContext> & ngPipeline,std::vector<RefPtr<NG::FrameNode>> & pageNodes,std::vector<std::string> & pagePaths)7263 void JsAccessibilityManager::GetCurrentWindowPages(
7264 const RefPtr<NG::PipelineContext>& ngPipeline,
7265 std::vector<RefPtr<NG::FrameNode>>& pageNodes,
7266 std::vector<std::string>& pagePaths)
7267 {
7268 CHECK_NULL_VOID(ngPipeline);
7269 auto stageManager = ngPipeline->GetStageManager();
7270 CHECK_NULL_VOID(stageManager);
7271 if (stageManager->IsSplitMode()) {
7272 pageNodes = stageManager->GetTopPagesWithTransition();
7273 pagePaths = stageManager->GetTopPagePaths();
7274 if (pageNodes.empty()) {
7275 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "Split mode enable, cannot get page");
7276 }
7277 return;
7278 }
7279 auto page = stageManager->GetLastPageWithTransition();
7280 CHECK_NULL_VOID(page);
7281 pageNodes.push_back(page);
7282 pagePaths.push_back(GetPagePath());
7283 }
7284
UpdateWindowInfo(AccessibilityWindowInfo & windowInfo,const RefPtr<PipelineBase> & context)7285 void JsAccessibilityManager::UpdateWindowInfo(AccessibilityWindowInfo& windowInfo, const RefPtr<PipelineBase>& context)
7286 {
7287 CHECK_NULL_VOID(context);
7288 auto container = Platform::AceContainer::GetContainer(context->GetInstanceId());
7289 CHECK_NULL_VOID(container);
7290 auto singleHandTransform = container->GetSingleHandTransform();
7291 windowInfo.top = windowInfo.top * singleHandTransform.scaleY_ + singleHandTransform.y_;
7292 windowInfo.left = windowInfo.left * singleHandTransform.scaleX_ + singleHandTransform.x_;
7293 windowInfo.scaleX *= singleHandTransform.scaleX_;
7294 windowInfo.scaleY *= singleHandTransform.scaleY_;
7295 }
7296
GenerateWindowInfo(const RefPtr<NG::FrameNode> & node,const RefPtr<PipelineBase> & context)7297 AccessibilityWindowInfo JsAccessibilityManager::GenerateWindowInfo(const RefPtr<NG::FrameNode>& node,
7298 const RefPtr<PipelineBase>& context)
7299 {
7300 AccessibilityWindowInfo windowInfo;
7301 NG::WindowSceneInfo windowSceneInfo;
7302 if (IsUpdateWindowSceneInfo(node, windowSceneInfo)) {
7303 windowInfo.left = windowSceneInfo.left;
7304 windowInfo.top = windowSceneInfo.top;
7305 windowInfo.scaleX = windowSceneInfo.scaleX;
7306 windowInfo.scaleY = windowSceneInfo.scaleY;
7307 windowInfo.innerWindowId = windowSceneInfo.innerWindowId;
7308 return windowInfo;
7309 }
7310 RefPtr<NG::PipelineContext> ngPipeline;
7311 if (context) {
7312 ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
7313 } else {
7314 ngPipeline = AceType::DynamicCast<NG::PipelineContext>(GetPipelineContext().Upgrade());
7315 }
7316 CHECK_NULL_RETURN(ngPipeline, windowInfo);
7317 auto container = Platform::AceContainer::GetContainer(ngPipeline->GetInstanceId());
7318 if (container && !container->IsSubWindow()) {
7319 // subwindow by subpipeline, donot use getParentRectHandler when it is registered in mainpipeline
7320 if (getParentRectHandler_) {
7321 getParentRectHandler_(windowInfo.top, windowInfo.left);
7322 return windowInfo;
7323 } else if (getParentRectHandlerNew_) {
7324 if (IsReentrantLimit()) {
7325 return windowInfo;
7326 }
7327 SetReentrantLimit(true);
7328 AccessibilityParentRectInfo rectInfo;
7329 getParentRectHandlerNew_(rectInfo);
7330 windowInfo.top = rectInfo.top;
7331 windowInfo.left = rectInfo.left;
7332 windowInfo.scaleX = rectInfo.scaleX;
7333 windowInfo.scaleY = rectInfo.scaleY;
7334 windowInfo.rotateTransform = rectInfo.rotateTransform;
7335 SetReentrantLimit(false);
7336 return windowInfo;
7337 }
7338 }
7339 windowInfo.left = GetWindowLeft(ngPipeline->GetWindowId());
7340 windowInfo.top = GetWindowTop(ngPipeline->GetWindowId());
7341 if (container) {
7342 auto windowScale = container->GetWindowScale();
7343 windowInfo.scaleX = windowScale;
7344 windowInfo.scaleY = windowScale;
7345 }
7346 UpdateWindowInfo(windowInfo, ngPipeline);
7347
7348 return windowInfo;
7349 }
7350
GenerateCommonProperty(const RefPtr<PipelineBase> & context,CommonProperty & output,const RefPtr<PipelineBase> & mainContext,const RefPtr<NG::FrameNode> & node)7351 void JsAccessibilityManager::GenerateCommonProperty(const RefPtr<PipelineBase>& context, CommonProperty& output,
7352 const RefPtr<PipelineBase>& mainContext, const RefPtr<NG::FrameNode>& node)
7353 {
7354 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(context);
7355 CHECK_NULL_VOID(ngPipeline);
7356 if (!ngPipeline->IsFormRender()) {
7357 output.windowId = static_cast<int32_t>(ngPipeline->GetRealHostWindowId());
7358 } else {
7359 output.windowId = static_cast<int32_t>(GetWindowId());
7360 }
7361
7362 auto windowInfo = GenerateWindowInfo(node, context);
7363 output.windowLeft = windowInfo.left;
7364 output.windowTop = windowInfo.top;
7365 scaleX_ = windowInfo.scaleX;
7366 scaleY_ = windowInfo.scaleY;
7367 output.scaleX = windowInfo.scaleX;
7368 output.scaleY = windowInfo.scaleY;
7369 output.innerWindowId = windowInfo.innerWindowId;
7370 output.rotateTransform = windowInfo.rotateTransform;
7371 // handle this time page info
7372 GetCurrentWindowPages(ngPipeline, output.pageNodes, output.pagePaths);
7373 if (context->GetWindowId() != mainContext->GetWindowId()) {
7374 output.pageNodes.clear();
7375 output.pagePaths.clear();
7376 }
7377 }
7378
FindText(const RefPtr<NG::UINode> & node,std::list<Accessibility::AccessibilityElementInfo> & infos,const RefPtr<NG::PipelineContext> & context,const CommonProperty & commonProperty,const SearchParameter & searchParam)7379 void JsAccessibilityManager::FindText(const RefPtr<NG::UINode>& node,
7380 std::list<Accessibility::AccessibilityElementInfo>& infos, const RefPtr<NG::PipelineContext>& context,
7381 const CommonProperty& commonProperty, const SearchParameter& searchParam)
7382 {
7383 CHECK_NULL_VOID(node);
7384 auto frameNode = AceType::DynamicCast<NG::FrameNode>(node);
7385 if (frameNode && !frameNode->IsInternal()) {
7386 if (frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>()->GetGroupText().find(
7387 searchParam.text) != std::string::npos) {
7388 AccessibilityElementInfo nodeInfo;
7389 UpdateAccessibilityElementInfo(frameNode, commonProperty, nodeInfo, context);
7390 infos.emplace_back(nodeInfo);
7391 }
7392 }
7393 if (IsExtensionComponent(frameNode) && !IsUIExtensionShowPlaceholder(frameNode)) {
7394 auto infosByIPC = SearchElementInfosByTextNG(NG::UI_EXTENSION_ROOT_ID, searchParam.text,
7395 frameNode, searchParam.uiExtensionOffset / NG::UI_EXTENSION_ID_FACTOR);
7396 if (!infosByIPC.empty()) {
7397 AccessibilityElementInfo nodeInfo;
7398 UpdateAccessibilityElementInfo(frameNode, commonProperty, nodeInfo, context);
7399 ConvertExtensionAccessibilityNodeId(infosByIPC, frameNode, searchParam.uiExtensionOffset, nodeInfo);
7400 for (auto& info : infosByIPC) {
7401 infos.emplace_back(info);
7402 }
7403 }
7404 }
7405 if (!node->GetChildren(true).empty()) {
7406 for (const auto& child : node->GetChildren(true)) {
7407 FindText(child, infos, context, commonProperty, searchParam);
7408 }
7409 }
7410 }
7411
FindTextByTextHint(const RefPtr<NG::UINode> & node,std::list<Accessibility::AccessibilityElementInfo> & infos,const RefPtr<NG::PipelineContext> & context,const CommonProperty & commonProperty,const SearchParameter & searchParam)7412 void JsAccessibilityManager::FindTextByTextHint(const RefPtr<NG::UINode>& node,
7413 std::list<Accessibility::AccessibilityElementInfo>& infos, const RefPtr<NG::PipelineContext>& context,
7414 const CommonProperty& commonProperty, const SearchParameter& searchParam)
7415 {
7416 CHECK_NULL_VOID(node);
7417 auto frameNode = AceType::DynamicCast<NG::FrameNode>(node);
7418 if (frameNode && !frameNode->IsInternal()) {
7419 std::string text = searchParam.text;
7420 nlohmann::json textJson = nlohmann::json::parse(text, nullptr, false);
7421 std::string value = "";
7422 if (!textJson.is_null() && !textJson.is_discarded() && textJson.contains("value")) {
7423 value = textJson["value"];
7424 }
7425 std::string textType = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>()->GetTextType();
7426 nlohmann::json textTypeJson = nlohmann::json::parse(textType, nullptr, false);
7427 if (!textTypeJson.is_null() && !textTypeJson.is_discarded() &&
7428 textTypeJson.contains("type") && textTypeJson["type"] == value) {
7429 AccessibilityElementInfo nodeInfo;
7430 UpdateAccessibilityElementInfo(frameNode, commonProperty, nodeInfo, context);
7431 infos.emplace_back(nodeInfo);
7432 }
7433 }
7434 if (IsIsolatedComponent(frameNode)) {
7435 auto infosByIPC = SearchElementInfosByTextNG(NG::UI_EXTENSION_ROOT_ID, searchParam.text,
7436 frameNode, searchParam.uiExtensionOffset / NG::UI_EXTENSION_ID_FACTOR);
7437 if (!infosByIPC.empty()) {
7438 AccessibilityElementInfo nodeInfo;
7439 UpdateAccessibilityElementInfo(frameNode, commonProperty, nodeInfo, context);
7440 ConvertExtensionAccessibilityNodeId(infosByIPC, frameNode, searchParam.uiExtensionOffset, nodeInfo);
7441 for (auto& info : infosByIPC) {
7442 infos.emplace_back(info);
7443 }
7444 }
7445 }
7446 if (!node->GetChildren(true).empty()) {
7447 for (const auto& child : node->GetChildren(true)) {
7448 FindTextByTextHint(child, infos, context, commonProperty, searchParam);
7449 }
7450 }
7451 }
7452
CreateNodeInfoJson(const RefPtr<NG::FrameNode> & node,const CommonProperty & commonProperty,std::unique_ptr<JsonValue> & json,int32_t childSize)7453 void JsAccessibilityManager::CreateNodeInfoJson(const RefPtr<NG::FrameNode>& node, const CommonProperty& commonProperty,
7454 std::unique_ptr<JsonValue>& json, int32_t childSize)
7455 {
7456 CHECK_NULL_VOID(node);
7457 auto child = JsonUtil::Create(true);
7458 child->Put("childSize", childSize);
7459 child->Put("ID", node->GetAccessibilityId());
7460 child->Put("compid", node->GetInspectorId().value_or("").c_str());
7461 auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
7462 if (accessibilityProperty) {
7463 child->Put("text", accessibilityProperty->GetGroupText().c_str());
7464 child->Put("accessibilityText", accessibilityProperty->GetAccessibilityText().c_str());
7465 child->Put("accessibilityGroup", accessibilityProperty->IsAccessibilityGroup());
7466 child->Put("accessibilityLevel", accessibilityProperty->GetAccessibilityLevel().c_str());
7467 }
7468 NG::RectF rect = node->GetTransformRectRelativeToWindow(true);
7469 child->Put("top", rect.Top() + commonProperty.windowTop);
7470 child->Put("left", rect.Left() + commonProperty.windowLeft);
7471 child->Put("width", rect.Width());
7472 child->Put("height", rect.Height());
7473 child->Put("visible", node->IsVisible());
7474 auto eventHub = node->GetEventHub<NG::EventHub>();
7475 if (eventHub) {
7476 auto gestureEventHub = eventHub->GetGestureEventHub();
7477 child->Put("clickable", gestureEventHub ? gestureEventHub->IsAccessibilityClickable() : false);
7478 child->Put("longclickable", gestureEventHub ? gestureEventHub->IsAccessibilityLongClickable() : false);
7479 }
7480 if (accessibilityProperty) {
7481 child->Put("checkable", accessibilityProperty->IsCheckable());
7482 child->Put("scrollable", accessibilityProperty->IsScrollable());
7483 child->Put("checked", accessibilityProperty->IsChecked());
7484 child->Put("hint", accessibilityProperty->GetHintText().c_str());
7485 child->Put("childTree", accessibilityProperty->GetChildTreeId());
7486 }
7487 std::string tag =
7488 node->GetTag() == "root" ? "root" : node->GetTag() + "_" + std::to_string(node->GetAccessibilityId());
7489 json->Put(tag.c_str(), child);
7490 }
7491
DumpTreeNodeInfoInJson(const RefPtr<NG::FrameNode> & node,int32_t depth,const CommonProperty & commonProperty,int32_t childSize)7492 void JsAccessibilityManager::DumpTreeNodeInfoInJson(
7493 const RefPtr<NG::FrameNode>& node, int32_t depth, const CommonProperty& commonProperty, int32_t childSize)
7494 {
7495 auto json = JsonUtil::Create(true);
7496 CreateNodeInfoJson(node, commonProperty, json, childSize);
7497 std::string content = DumpLog::GetInstance().FormatDumpInfo(json->ToString(), depth);
7498 std::string prefix = DumpLog::GetInstance().GetPrefix(depth);
7499 std::string fulljson = prefix.append(content);
7500 DumpLog::GetInstance().PrintJson(fulljson);
7501 }
7502
7503
TransferThirdProviderHoverEvent(const WeakPtr<NG::FrameNode> & hostNode,const NG::PointF & point,SourceType source,NG::AccessibilityHoverEventType eventType,TimeStamp time)7504 void JsAccessibilityManager::TransferThirdProviderHoverEvent(
7505 const WeakPtr<NG::FrameNode>& hostNode, const NG::PointF& point, SourceType source,
7506 NG::AccessibilityHoverEventType eventType, TimeStamp time)
7507 {
7508 auto pipelineContext = GetPipelineContext().Upgrade();
7509 CHECK_NULL_VOID(pipelineContext);
7510 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
7511 CHECK_NULL_VOID(ngPipeline);
7512 auto frameNode = hostNode.Upgrade();
7513 CHECK_NULL_VOID(frameNode);
7514 AccessibilityHoverForThirdConfig config;
7515 config.hostElementId = frameNode->GetAccessibilityId();
7516 config.point = point;
7517 config.sourceType = source;
7518 config.eventType = eventType;
7519 config.time = time;
7520 config.context = ngPipeline;
7521 HandleAccessibilityHoverForThird(config);
7522 }
7523
OnDumpChildInfoForThird(int64_t hostElementId,const std::vector<std::string> & params,std::vector<std::string> & info)7524 bool JsAccessibilityManager::OnDumpChildInfoForThird(
7525 int64_t hostElementId,
7526 const std::vector<std::string>& params,
7527 std::vector<std::string>& info)
7528 {
7529 return OnDumpChildInfoForThirdRecursive(hostElementId, params, info, WeakClaim(this));
7530 }
7531
7532 #ifdef WEB_SUPPORTED
GetWebCursorPosition(const int64_t elementId,const int32_t requestId,AccessibilityElementOperatorCallback & callback,const RefPtr<NG::WebPattern> & webPattern)7533 void JsAccessibilityManager::GetWebCursorPosition(const int64_t elementId, const int32_t requestId,
7534 AccessibilityElementOperatorCallback& callback, const RefPtr<NG::WebPattern>& webPattern)
7535 {
7536 CHECK_NULL_VOID(webPattern);
7537 auto node = webPattern->GetTransitionalNodeById(elementId);
7538 CHECK_NULL_VOID(node);
7539
7540 callback.SetCursorPositionResult(node->GetSelectionStart(), requestId);
7541 }
7542 #endif // WEB_SUPPORTED
7543
FireAccessibilityEventCallback(uint32_t eventId,int64_t parameter)7544 void JsAccessibilityManager::FireAccessibilityEventCallback(uint32_t eventId, int64_t parameter)
7545 {
7546 auto eventType = static_cast<AccessibilityCallbackEventId>(eventId);
7547 AccessibilityEvent event;
7548 switch (eventType) {
7549 case AccessibilityCallbackEventId::ON_LOAD_PAGE:
7550 event.nodeId = parameter;
7551 event.windowChangeTypes = WindowUpdateType::WINDOW_UPDATE_ACTIVE;
7552 event.type = AccessibilityEventType::CHANGE;
7553 SendAccessibilityAsyncEvent(event);
7554 break;
7555 default:
7556 break;
7557 }
7558 }
7559
GetTransformDegreeRelativeToWindow(const RefPtr<NG::FrameNode> & node,bool excludeSelf)7560 int32_t JsAccessibilityManager::GetTransformDegreeRelativeToWindow(const RefPtr<NG::FrameNode>& node, bool excludeSelf)
7561 {
7562 int32_t rotateDegree = 0;
7563 auto context = node->GetRenderContext();
7564 if (context && !excludeSelf) {
7565 rotateDegree = context->GetRotateDegree();
7566 }
7567 auto parent = node->GetAncestorNodeOfFrame(true);
7568 while (parent) {
7569 if (parent->IsWindowBoundary()) {
7570 break;
7571 }
7572 auto contextParent = parent->GetRenderContext();
7573 if (contextParent) {
7574 rotateDegree += contextParent->GetRotateDegree();
7575 }
7576 parent = parent->GetAncestorNodeOfFrame(true);
7577 }
7578 return rotateDegree %= FULL_ANGLE;
7579 }
7580
GetTransformRectInfoRelativeToWindow(const RefPtr<NG::FrameNode> & node,const RefPtr<PipelineBase> & context)7581 AccessibilityParentRectInfo JsAccessibilityManager::GetTransformRectInfoRelativeToWindow(
7582 const RefPtr<NG::FrameNode>& node, const RefPtr<PipelineBase>& context)
7583 {
7584 AccessibilityParentRectInfo rectInfo;
7585 CHECK_NULL_RETURN(node, rectInfo);
7586 CHECK_NULL_RETURN(context, rectInfo);
7587 auto windowInfo = GenerateWindowInfo(node, context);
7588 auto rectFinal = GetFinalRealRect(node);
7589 RotateTransform rotateData;
7590 RotateTransform windowRotateData = windowInfo.rotateTransform;
7591 rotateData.rotateDegree = GetTransformDegreeRelativeToWindow(node);
7592 AccessibilityRect rotateRect(rectFinal.GetX(), rectFinal.GetY(),
7593 rectFinal.Width(), rectFinal.Height());
7594 if (windowRotateData.rotateDegree) {
7595 rotateRect.Rotate(windowRotateData.innerCenterX, windowRotateData.innerCenterY,
7596 windowRotateData.rotateDegree);
7597 rotateRect.ApplyTransformation(windowRotateData, windowInfo.scaleX, windowInfo.scaleY);
7598 rotateData.rotateDegree += windowRotateData.rotateDegree;
7599 } else {
7600 RotateTransform roateDataTemp(0, windowInfo.left, windowInfo.top, 0, 0);
7601 rotateRect.ApplyTransformation(roateDataTemp, windowInfo.scaleX, windowInfo.scaleY);
7602 }
7603 rectInfo.left = rotateRect.GetX();
7604 rectInfo.top = rotateRect.GetY();
7605 rectInfo.scaleX *= windowInfo.scaleX;
7606 rectInfo.scaleY *= windowInfo.scaleY;
7607 if (rotateData.rotateDegree) {
7608 rotateData.centerX = static_cast<int32_t>(rotateRect.GetWidth()) * 0.5f + rotateRect.GetX();
7609 rotateData.centerY = static_cast<int32_t>(rotateRect.GetHeight()) * 0.5f + rotateRect.GetY();
7610 auto renderContext = node->GetRenderContext();
7611 CHECK_NULL_RETURN(renderContext, rectInfo);
7612 auto rectOrigin = renderContext->GetPaintRectWithoutTransform();
7613 rotateData.innerCenterX = rectOrigin.Width() * 0.5f;
7614 rotateData.innerCenterY = rectOrigin.Height() * 0.5f;
7615 }
7616 rectInfo.rotateTransform = rotateData;
7617 return rectInfo;
7618 }
7619
UpdateAccessibilityNodeRect(const RefPtr<NG::FrameNode> & frameNode)7620 void JsAccessibilityManager::UpdateAccessibilityNodeRect(const RefPtr<NG::FrameNode>& frameNode)
7621 {
7622 CHECK_NULL_VOID(frameNode);
7623 auto renderContext = frameNode->GetRenderContext();
7624 CHECK_NULL_VOID(renderContext);
7625 auto accessibilityProperty = frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
7626 CHECK_NULL_VOID(accessibilityProperty);
7627 auto isFocus = accessibilityProperty->GetAccessibilityFocusState();
7628 if (isFocus && !frameNode->IsAccessibilityVirtualNode() && !frameNode->IsDrawFocusOnTop()) {
7629 if (accessibilityProperty->IsMatchAccessibilityResponseRegion(false)) {
7630 auto rectInt = accessibilityProperty->GetAccessibilityResponseRegionRect(false);
7631 renderContext->UpdateAccessibilityFocusRect(rectInt);
7632 } else {
7633 renderContext->UpdateAccessibilityRoundRect();
7634 }
7635 } else {
7636 RefPtr<NG::FrameNode> focusFrameNode = nullptr;
7637 auto checkflag = CheckChildIsAccessibilityFocus(frameNode, focusFrameNode);
7638 if (checkflag && focusFrameNode && focusFrameNode->IsDrawFocusOnTop()) {
7639 UpdatePaintNodeRender(focusFrameNode);
7640 }
7641 }
7642 }
7643
OnAccessbibilityDetachFromMainTree(const RefPtr<NG::FrameNode> & focusNode)7644 void JsAccessibilityManager::OnAccessbibilityDetachFromMainTree(const RefPtr<NG::FrameNode>& focusNode)
7645 {
7646 auto paintNode = focusNode->GetPaintNode();
7647 CHECK_NULL_VOID(paintNode);
7648 auto paintNodePattern = AceType::DynamicCast<NG::AccessibilityFocusPaintNodePattern>(paintNode->GetPattern());
7649 CHECK_NULL_VOID(paintNodePattern);
7650 auto currentFocusNode = paintNodePattern->GetFocusNode().Upgrade();
7651 CHECK_NULL_VOID(currentFocusNode);
7652 if (currentFocusNode->GetId() == focusNode->GetId()) {
7653 paintNodePattern->OnDetachFromFocusNode();
7654 RemoveAccessibilityFocusPaint(focusNode);
7655 }
7656 }
7657 } // namespace OHOS::Ace::Framework
7658