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