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