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