| // Copyright 2018 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/win/ui_automation_util.h" |
| |
| #include <algorithm> |
| #include <iterator> |
| |
| #include "base/logging.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_util.h" |
| #include "base/win/scoped_safearray.h" |
| #include "base/win/scoped_variant.h" |
| |
| std::wstring GetCachedBstrValue(IUIAutomationElement* element, |
| PROPERTYID property_id) { |
| HRESULT result = S_OK; |
| base::win::ScopedVariant var; |
| |
| result = element->GetCachedPropertyValueEx(property_id, TRUE, var.Receive()); |
| if (FAILED(result)) |
| return std::wstring(); |
| |
| if (V_VT(var.ptr()) != VT_BSTR) { |
| LOG_IF(ERROR, V_VT(var.ptr()) != VT_UNKNOWN) |
| << __func__ << " property is not a BSTR: " << V_VT(var.ptr()); |
| return std::wstring(); |
| } |
| |
| return std::wstring(V_BSTR(var.ptr())); |
| } |
| |
| bool GetCachedBoolValue(IUIAutomationElement* element, PROPERTYID property_id) { |
| #if DCHECK_IS_ON() |
| base::win::ScopedVariant var; |
| |
| if (FAILED(element->GetCachedPropertyValueEx(property_id, TRUE, |
| var.Receive()))) { |
| return false; |
| } |
| |
| if (V_VT(var.ptr()) != VT_BOOL) { |
| LOG_IF(ERROR, V_VT(var.ptr()) != VT_UNKNOWN) |
| << __func__ << " property is not a BOOL: " << V_VT(var.ptr()); |
| return false; |
| } |
| |
| return V_BOOL(var.ptr()) != 0; |
| #else // DCHECK_IS_ON() |
| return false; |
| #endif // !DCHECK_IS_ON() |
| } |
| |
| int32_t GetCachedInt32Value(IUIAutomationElement* element, |
| PROPERTYID property_id) { |
| #if DCHECK_IS_ON() |
| base::win::ScopedVariant var; |
| |
| if (FAILED(element->GetCachedPropertyValueEx(property_id, TRUE, |
| var.Receive()))) { |
| return false; |
| } |
| |
| if (V_VT(var.ptr()) != VT_I4) { |
| LOG_IF(ERROR, V_VT(var.ptr()) != VT_UNKNOWN) |
| << __func__ << " property is not an I4: " << V_VT(var.ptr()); |
| return false; |
| } |
| |
| return V_I4(var.ptr()); |
| #else // DCHECK_IS_ON() |
| return 0; |
| #endif // !DCHECK_IS_ON() |
| } |
| |
| std::vector<int32_t> GetCachedInt32ArrayValue(IUIAutomationElement* element, |
| PROPERTYID property_id) { |
| std::vector<int32_t> values; |
| #if DCHECK_IS_ON() |
| base::win::ScopedVariant var; |
| |
| if (FAILED(element->GetCachedPropertyValueEx(property_id, TRUE, |
| var.Receive()))) { |
| return values; |
| } |
| |
| if (V_VT(var.ptr()) != (VT_I4 | VT_ARRAY)) { |
| LOG_IF(ERROR, V_VT(var.ptr()) != VT_UNKNOWN) |
| << __func__ << " property is not an I4 array: " << V_VT(var.ptr()); |
| return values; |
| } |
| |
| // Convert to ScopedSafearray for convenient access to the data. |
| base::win::ScopedSafearray scoped_array(var.Release().parray); |
| |
| auto lock_scope = scoped_array.CreateLockScope<VT_I4>(); |
| if (!lock_scope) { |
| return values; |
| } |
| |
| values.assign(lock_scope->begin(), lock_scope->end()); |
| #endif // DCHECK_IS_ON() |
| return values; |
| } |
| |
| std::string IntArrayToString(const std::vector<int32_t>& values) { |
| #if DCHECK_IS_ON() |
| std::vector<std::string> value_strings; |
| std::ranges::transform( |
| values, std::back_inserter(value_strings), |
| [](int32_t value) { return base::NumberToString(value); }); |
| return base::JoinString(value_strings, ", "); |
| #else // DCHECK_IS_ON() |
| return std::string(); |
| #endif // !DCHECK_IS_ON() |
| } |
| |
| const char* GetEventName(EVENTID event_id) { |
| #if DCHECK_IS_ON() |
| switch (event_id) { |
| case UIA_ToolTipOpenedEventId: |
| return "UIA_ToolTipOpenedEventId"; |
| case UIA_ToolTipClosedEventId: |
| return "UIA_ToolTipClosedEventId"; |
| case UIA_StructureChangedEventId: |
| return "UIA_StructureChangedEventId"; |
| case UIA_MenuOpenedEventId: |
| return "UIA_MenuOpenedEventId"; |
| case UIA_AutomationPropertyChangedEventId: |
| return "UIA_AutomationPropertyChangedEventId"; |
| case UIA_AutomationFocusChangedEventId: |
| return "UIA_AutomationFocusChangedEventId"; |
| case UIA_AsyncContentLoadedEventId: |
| return "UIA_AsyncContentLoadedEventId"; |
| case UIA_MenuClosedEventId: |
| return "UIA_MenuClosedEventId"; |
| case UIA_LayoutInvalidatedEventId: |
| return "UIA_LayoutInvalidatedEventId"; |
| case UIA_Invoke_InvokedEventId: |
| return "UIA_Invoke_InvokedEventId"; |
| case UIA_SelectionItem_ElementAddedToSelectionEventId: |
| return "UIA_SelectionItem_ElementAddedToSelectionEventId"; |
| case UIA_SelectionItem_ElementRemovedFromSelectionEventId: |
| return "UIA_SelectionItem_ElementRemovedFromSelectionEventId"; |
| case UIA_SelectionItem_ElementSelectedEventId: |
| return "UIA_SelectionItem_ElementSelectedEventId"; |
| case UIA_Selection_InvalidatedEventId: |
| return "UIA_Selection_InvalidatedEventId"; |
| case UIA_Text_TextSelectionChangedEventId: |
| return "UIA_Text_TextSelectionChangedEventId"; |
| case UIA_Text_TextChangedEventId: |
| return "UIA_Text_TextChangedEventId"; |
| case UIA_Window_WindowOpenedEventId: |
| return "UIA_Window_WindowOpenedEventId"; |
| case UIA_Window_WindowClosedEventId: |
| return "UIA_Window_WindowClosedEventId"; |
| case UIA_MenuModeStartEventId: |
| return "UIA_MenuModeStartEventId"; |
| case UIA_MenuModeEndEventId: |
| return "UIA_MenuModeEndEventId"; |
| case UIA_InputReachedTargetEventId: |
| return "UIA_InputReachedTargetEventId"; |
| case UIA_InputReachedOtherElementEventId: |
| return "UIA_InputReachedOtherElementEventId"; |
| case UIA_InputDiscardedEventId: |
| return "UIA_InputDiscardedEventId"; |
| case UIA_SystemAlertEventId: |
| return "UIA_SystemAlertEventId"; |
| case UIA_LiveRegionChangedEventId: |
| return "UIA_LiveRegionChangedEventId"; |
| case UIA_HostedFragmentRootsInvalidatedEventId: |
| return "UIA_HostedFragmentRootsInvalidatedEventId"; |
| case UIA_Drag_DragStartEventId: |
| return "UIA_Drag_DragStartEventId"; |
| case UIA_Drag_DragCancelEventId: |
| return "UIA_Drag_DragCancelEventId"; |
| case UIA_Drag_DragCompleteEventId: |
| return "UIA_Drag_DragCompleteEventId"; |
| case UIA_DropTarget_DragEnterEventId: |
| return "UIA_DropTarget_DragEnterEventId"; |
| case UIA_DropTarget_DragLeaveEventId: |
| return "UIA_DropTarget_DragLeaveEventId"; |
| case UIA_DropTarget_DroppedEventId: |
| return "UIA_DropTarget_DroppedEventId"; |
| case UIA_TextEdit_TextChangedEventId: |
| return "UIA_TextEdit_TextChangedEventId"; |
| case UIA_TextEdit_ConversionTargetChangedEventId: |
| return "UIA_TextEdit_ConversionTargetChangedEventId"; |
| case UIA_ActiveTextPositionChangedEventId: |
| return "UIA_ActiveTextPositionChangedEventId"; |
| } |
| #endif // DCHECK_IS_ON() |
| return ""; |
| } |
| |
| const char* GetControlType(long control_type) { |
| #if DCHECK_IS_ON() |
| switch (control_type) { |
| case UIA_ButtonControlTypeId: |
| return "UIA_ButtonControlTypeId"; |
| case UIA_CalendarControlTypeId: |
| return "UIA_CalendarControlTypeId"; |
| case UIA_CheckBoxControlTypeId: |
| return "UIA_CheckBoxControlTypeId"; |
| case UIA_ComboBoxControlTypeId: |
| return "UIA_ComboBoxControlTypeId"; |
| case UIA_EditControlTypeId: |
| return "UIA_EditControlTypeId"; |
| case UIA_HyperlinkControlTypeId: |
| return "UIA_HyperlinkControlTypeId"; |
| case UIA_ImageControlTypeId: |
| return "UIA_ImageControlTypeId"; |
| case UIA_ListItemControlTypeId: |
| return "UIA_ListItemControlTypeId"; |
| case UIA_ListControlTypeId: |
| return "UIA_ListControlTypeId"; |
| case UIA_MenuControlTypeId: |
| return "UIA_MenuControlTypeId"; |
| case UIA_MenuBarControlTypeId: |
| return "UIA_MenuBarControlTypeId"; |
| case UIA_MenuItemControlTypeId: |
| return "UIA_MenuItemControlTypeId"; |
| case UIA_ProgressBarControlTypeId: |
| return "UIA_ProgressBarControlTypeId"; |
| case UIA_RadioButtonControlTypeId: |
| return "UIA_RadioButtonControlTypeId"; |
| case UIA_ScrollBarControlTypeId: |
| return "UIA_ScrollBarControlTypeId"; |
| case UIA_SliderControlTypeId: |
| return "UIA_SliderControlTypeId"; |
| case UIA_SpinnerControlTypeId: |
| return "UIA_SpinnerControlTypeId"; |
| case UIA_StatusBarControlTypeId: |
| return "UIA_StatusBarControlTypeId"; |
| case UIA_TabControlTypeId: |
| return "UIA_TabControlTypeId"; |
| case UIA_TabItemControlTypeId: |
| return "UIA_TabItemControlTypeId"; |
| case UIA_TextControlTypeId: |
| return "UIA_TextControlTypeId"; |
| case UIA_ToolBarControlTypeId: |
| return "UIA_ToolBarControlTypeId"; |
| case UIA_ToolTipControlTypeId: |
| return "UIA_ToolTipControlTypeId"; |
| case UIA_TreeControlTypeId: |
| return "UIA_TreeControlTypeId"; |
| case UIA_TreeItemControlTypeId: |
| return "UIA_TreeItemControlTypeId"; |
| case UIA_CustomControlTypeId: |
| return "UIA_CustomControlTypeId"; |
| case UIA_GroupControlTypeId: |
| return "UIA_GroupControlTypeId"; |
| case UIA_ThumbControlTypeId: |
| return "UIA_ThumbControlTypeId"; |
| case UIA_DataGridControlTypeId: |
| return "UIA_DataGridControlTypeId"; |
| case UIA_DataItemControlTypeId: |
| return "UIA_DataItemControlTypeId"; |
| case UIA_DocumentControlTypeId: |
| return "UIA_DocumentControlTypeId"; |
| case UIA_SplitButtonControlTypeId: |
| return "UIA_SplitButtonControlTypeId"; |
| case UIA_WindowControlTypeId: |
| return "UIA_WindowControlTypeId"; |
| case UIA_PaneControlTypeId: |
| return "UIA_PaneControlTypeId"; |
| case UIA_HeaderControlTypeId: |
| return "UIA_HeaderControlTypeId"; |
| case UIA_HeaderItemControlTypeId: |
| return "UIA_HeaderItemControlTypeId"; |
| case UIA_TableControlTypeId: |
| return "UIA_TableControlTypeId"; |
| case UIA_TitleBarControlTypeId: |
| return "UIA_TitleBarControlTypeId"; |
| case UIA_SeparatorControlTypeId: |
| return "UIA_SeparatorControlTypeId"; |
| case UIA_SemanticZoomControlTypeId: |
| return "UIA_SemanticZoomControlTypeId"; |
| case UIA_AppBarControlTypeId: |
| return "UIA_AppBarControlTypeId"; |
| } |
| #endif // DCHECK_IS_ON() |
| return ""; |
| } |