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